anthelpers 0.0.2 → 0.1.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.
@@ -5,9 +5,19 @@
5
5
  </component>
6
6
  <component name="ChangeListManager">
7
7
  <list default="true" id="cbb82d94-0dbd-445b-8adb-15f10cc25fd5" name="Changes" comment="git add ,">
8
+ <change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
9
+ <change afterPath="$PROJECT_DIR$/Random.js" afterDir="false" />
10
+ <change afterPath="$PROJECT_DIR$/Random.ts" afterDir="false" />
11
+ <change afterPath="$PROJECT_DIR$/deepEquals.js" afterDir="false" />
12
+ <change afterPath="$PROJECT_DIR$/deepEquals.ts" afterDir="false" />
13
+ <change afterPath="$PROJECT_DIR$/parseBigInt.js" afterDir="false" />
14
+ <change afterPath="$PROJECT_DIR$/parseBigInt.ts" afterDir="false" />
15
+ <change afterPath="$PROJECT_DIR$/promise.d.ts" afterDir="false" />
16
+ <change afterPath="$PROJECT_DIR$/tests.js" afterDir="false" />
8
17
  <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
18
+ <change beforePath="$PROJECT_DIR$/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/index.js" afterDir="false" />
9
19
  <change beforePath="$PROJECT_DIR$/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/index.ts" afterDir="false" />
10
- <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
20
+ <change beforePath="$PROJECT_DIR$/tsconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/tsconfig.json" afterDir="false" />
11
21
  </list>
12
22
  <option name="SHOW_DIALOG" value="false" />
13
23
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -21,6 +31,7 @@
21
31
  <option name="RECENT_TEMPLATES">
22
32
  <list>
23
33
  <option value="JavaScript File" />
34
+ <option value="TypeScript File" />
24
35
  </list>
25
36
  </option>
26
37
  </component>
@@ -64,6 +75,11 @@
64
75
  &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
65
76
  }
66
77
  }</component>
78
+ <component name="RecentsManager">
79
+ <key name="MoveFile.RECENT_KEYS">
80
+ <recent name="D:\var\www\BOTs\antHelpers" />
81
+ </key>
82
+ </component>
67
83
  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
68
84
  <component name="TaskManager">
69
85
  <task active="true" id="Default" summary="Default task">
@@ -75,7 +91,18 @@
75
91
  <workItem from="1750690125892" duration="677000" />
76
92
  <workItem from="1750701696645" duration="1183000" />
77
93
  <workItem from="1751299376418" duration="401000" />
78
- <workItem from="1751299850777" duration="55000" />
94
+ <workItem from="1751299850777" duration="165000" />
95
+ <workItem from="1751300373838" duration="17000" />
96
+ <workItem from="1757840101515" duration="6954000" />
97
+ <workItem from="1757922653752" duration="3977000" />
98
+ <workItem from="1758026845729" duration="60000" />
99
+ <workItem from="1758153479792" duration="47000" />
100
+ <workItem from="1758195396963" duration="724000" />
101
+ <workItem from="1758196639774" duration="11000" />
102
+ <workItem from="1759948417753" duration="22000" />
103
+ <workItem from="1760055007271" duration="99000" />
104
+ <workItem from="1760360991867" duration="6060000" />
105
+ <workItem from="1760367500301" duration="5155000" />
79
106
  </task>
80
107
  <task id="LOCAL-00001" summary="git add ,">
81
108
  <option name="closed" value="true" />
@@ -93,6 +120,15 @@
93
120
  <option name="exactExcludedFiles">
94
121
  <list>
95
122
  <option value="$PROJECT_DIR$/index.js" />
123
+ <option value="$PROJECT_DIR$/WebWorkers/PromisedWorker.js" />
124
+ <option value="$PROJECT_DIR$/WebWorkers/PromisedWorkerInside.js" />
125
+ <option value="$PROJECT_DIR$/WebWorkers/FetchedWorker.js" />
126
+ <option value="$PROJECT_DIR$/WebWorkers/CustomError.js" />
127
+ <option value="$PROJECT_DIR$/WebWorkers/FetchedWorkerWithin.js" />
128
+ <option value="$PROJECT_DIR$/parseBigInt.js" />
129
+ <option value="$PROJECT_DIR$/deepEquals.js" />
130
+ <option value="$PROJECT_DIR$/WebWorkers/FWClass.js" />
131
+ <option value="$PROJECT_DIR$/Random.js" />
96
132
  </list>
97
133
  </option>
98
134
  </component>
package/Random.js ADDED
@@ -0,0 +1,76 @@
1
+ // javascript.js
2
+ import { EXMAScript } from "./index.js";
3
+ export class Random {
4
+ #seed;
5
+ constructor(seed = 0n) {
6
+ this.#seed = BigInt(seed);
7
+ }
8
+ next(min = 0n, max = 1000n) {
9
+ // Linear congruential generator
10
+ this.#seed = (this.#seed * 6364136223846793005n + 1n) & ((1n << 64n) - 1n);
11
+ min = BigInt(min);
12
+ max = BigInt(max);
13
+ return min + (this.#seed % (max - min));
14
+ }
15
+ [Symbol.toStringTag] = "PRandom";
16
+ static [Symbol.toStringTag] = "PRandom constructor";
17
+ fillArray(array, min = 0n, max = 100000n) {
18
+ const length = EXMAScript.toIntegerOrInfinity(array?.length);
19
+ if (length === 0)
20
+ return array;
21
+ for (let i = 0; i < length; i++) {
22
+ const skip = (array[i] = this.next(min, max)) % 17n;
23
+ for (let ii = 0; ii < skip; ii++)
24
+ this.next(min, max);
25
+ }
26
+ return array;
27
+ }
28
+ }
29
+ export class WeightedRandomRarity extends Random {
30
+ #rarities;
31
+ constructor(rarities, seed = undefined) {
32
+ super(BigInt(seed ?? Date.now()));
33
+ const entries = Object.entries(Object.assign({}, rarities));
34
+ (this.#rarities = entries.map(([key, value]) => [key,
35
+ Math.trunc(value)])).forEach(([key, value]) => {
36
+ if (value < 0)
37
+ throw new RangeError(`${key}: is negative`);
38
+ });
39
+ }
40
+ // @ts-expect-error
41
+ next() {
42
+ const entries = this.#rarities;
43
+ const total = this.cumulative();
44
+ const rand = super.next(0n, BigInt(total));
45
+ let cumulative = 0;
46
+ for (const [key, w] of entries) {
47
+ cumulative += w;
48
+ if (rand < cumulative)
49
+ return key;
50
+ }
51
+ return entries[0][0];
52
+ }
53
+ cumulative() {
54
+ const entries = this.#rarities;
55
+ return entries.reduce((sum, [, value]) => sum + value, 0);
56
+ }
57
+ getOdds() {
58
+ const total = this.cumulative();
59
+ const entries = this.#rarities, result = {
60
+ [Symbol.toStringTag]: "Rarities", total,
61
+ asPercents: { [Symbol.toStringTag]: "Rarities asPercents" },
62
+ asFloats: { [Symbol.toStringTag]: "Rarities asFloats" },
63
+ internal: { [Symbol.toStringTag]: "Rarities asFloats" },
64
+ };
65
+ for (const entry of entries) {
66
+ result.internal[entry[0]] = entry[1];
67
+ result.asFloats[entry[0]] = entry[1] / total;
68
+ const asPercent = ((entry[1] / total) * 100).toFixed(2) + '%';
69
+ result.asPercents[entry[0]] = asPercent.replace(/\.00%$/, '%');
70
+ }
71
+ Object.freeze(result.internal);
72
+ Object.freeze(result.asFloats);
73
+ Object.freeze(result.asPercents);
74
+ return Object.freeze(result);
75
+ }
76
+ }
package/Random.ts ADDED
@@ -0,0 +1,86 @@
1
+ // Random.ts
2
+ import {EXMAScript} from "./index.js";
3
+
4
+ export class Random {
5
+ #seed;
6
+
7
+ constructor(seed = 0n) {
8
+ this.#seed = BigInt(seed);
9
+ }
10
+
11
+ next(min: bigint = 0n, max: bigint = 1000n): bigint {
12
+ // Linear congruential generator
13
+ this.#seed = (this.#seed * 6364136223846793005n + 1n) & ((1n << 64n) - 1n);
14
+ min = BigInt(min);
15
+ max = BigInt(max);
16
+ return min + (this.#seed % (max - min));
17
+ }
18
+
19
+ [Symbol.toStringTag] = "PRandom";
20
+ static [Symbol.toStringTag] = "PRandom constructor";
21
+
22
+ fillArray(array: unknown[], min: bigint = 0n, max: bigint = 100000n) {
23
+ const length = EXMAScript.toIntegerOrInfinity(array?.length);
24
+ if (length === 0) return array;
25
+ for (let i = 0; i < length; i++) {
26
+ const skip = (array[i] = this.next(min, max)) % 17n;
27
+ for (let ii = 0; ii < skip; ii++) this.next(min, max);
28
+ }
29
+ return array;
30
+ }
31
+ }
32
+
33
+ export class WeightedRandomRarity extends Random {
34
+ readonly #rarities: [string, number][];
35
+
36
+ constructor(rarities: { [rarity: string]: number }, seed = undefined) {
37
+ super(BigInt(seed ?? Date.now()));
38
+ const entries = Object.entries(Object.assign({}, rarities));
39
+ (this.#rarities = entries.map(([key, value]) => [key,
40
+ Math.trunc(value)])).forEach(([key, value]) => {
41
+ if (value < 0) throw new RangeError(`${key}: is negative`);
42
+ });
43
+ }
44
+
45
+ // @ts-expect-error
46
+ next(): string {
47
+ const entries = this.#rarities;
48
+ const total = this.cumulative();
49
+ const rand = super.next(0n, BigInt(total));
50
+ let cumulative = 0;
51
+ for (const [key, w] of entries) {
52
+ cumulative += w;
53
+ if (rand < cumulative) return key;
54
+ }
55
+ return entries[0][0];
56
+ }
57
+
58
+ cumulative(): number {
59
+ const entries = this.#rarities;
60
+ return entries.reduce((sum, [, value]) => sum + value, 0);
61
+ }
62
+
63
+ getOdds(): {
64
+ asPercents: { [rarity: string]: number },
65
+ asFloats: { [rarity: string]: number },
66
+ internal: { [rarity: string]: number }
67
+ } {
68
+ const total = this.cumulative();
69
+ const entries = this.#rarities, result: any = {
70
+ [Symbol.toStringTag]: "Rarities", total,
71
+ asPercents: {[Symbol.toStringTag]: "Rarities asPercents"},
72
+ asFloats: {[Symbol.toStringTag]: "Rarities asFloats"},
73
+ internal: {[Symbol.toStringTag]: "Rarities asFloats"},
74
+ };
75
+ for (const entry of entries) {
76
+ result.internal[entry[0]] = entry[1];
77
+ result.asFloats[entry[0]] = entry[1] / total;
78
+ const asPercent = ((entry[1] / total) * 100).toFixed(2) + '%';
79
+ result.asPercents[entry[0]] = asPercent.replace(/\.00%$/, '%');
80
+ }
81
+ Object.freeze(result.internal);
82
+ Object.freeze(result.asFloats);
83
+ Object.freeze(result.asPercents);
84
+ return Object.freeze(result);
85
+ }
86
+ }
package/deepEquals.js ADDED
@@ -0,0 +1,34 @@
1
+ // deeplyEquals
2
+ export function deeplyEquals(le, ri, checkProto = false) {
3
+ if (le === ri)
4
+ return true;
5
+ if (le === null || ri === null)
6
+ return false;
7
+ if (typeof le !== typeof ri)
8
+ return false;
9
+ if (typeof le == "object" && typeof ri == "object") {
10
+ const leProps = sortAsStrings(Reflect.ownKeys(le));
11
+ const riProps = sortAsStrings(Reflect.ownKeys(ri));
12
+ if (leProps.length !== riProps.length)
13
+ return false;
14
+ for (let i = 0; i < leProps.length; i++) {
15
+ const key = leProps[i];
16
+ if (key !== riProps[i])
17
+ return false; // ensure same key names
18
+ if (!deeplyEquals(le[key], ri[key], checkProto))
19
+ return false;
20
+ }
21
+ if (checkProto)
22
+ return deeplyEquals(Object.getPrototypeOf(le), Object.getPrototypeOf(ri));
23
+ return true;
24
+ }
25
+ else
26
+ return false;
27
+ }
28
+ export function sortAsStrings(array) {
29
+ return Array.from(array, value => ({
30
+ value, toString() {
31
+ return String(this.value);
32
+ }
33
+ })).sort().map(({ value }) => value);
34
+ }
package/deepEquals.ts ADDED
@@ -0,0 +1,26 @@
1
+ // deeplyEquals
2
+ export function deeplyEquals(le: any, ri: any, checkProto: boolean = false): boolean {
3
+ if (le === ri) return true;
4
+ if (le === null || ri === null) return false;
5
+ if (typeof le !== typeof ri) return false;
6
+ if (typeof le == "object" && typeof ri == "object") {
7
+ const leProps = sortAsStrings(Reflect.ownKeys(le));
8
+ const riProps = sortAsStrings(Reflect.ownKeys(ri));
9
+ if (leProps.length !== riProps.length) return false;
10
+ for (let i = 0; i < leProps.length; i++) {
11
+ const key = leProps[i];
12
+ if (key !== riProps[i]) return false; // ensure same key names
13
+ if (!deeplyEquals(le[key], ri[key], checkProto)) return false;
14
+ }
15
+ if (checkProto) return deeplyEquals(Object.getPrototypeOf(le), Object.getPrototypeOf(ri));
16
+ return true;
17
+ } else return false;
18
+ }
19
+
20
+ export function sortAsStrings<T>(array: T[]): T[] {
21
+ return Array.from(array, value => ({
22
+ value, toString() {
23
+ return String(this.value)
24
+ }
25
+ })).sort().map(({value}) => value);
26
+ }
package/index.js CHANGED
@@ -20,7 +20,7 @@ export function indent_codeblock(string) {
20
20
  * @param {string} string - The input string to format as a Markdown quote.
21
21
  * @returns {string} A string formatted as a Markdown blockquote.
22
22
  */
23
- function quoteMarkdown(string) {
23
+ export function quoteMarkdown(string) {
24
24
  return '> ' + normalize_newlines(string).replace(/\n/g, '\n> ');
25
25
  }
26
26
  /**
@@ -28,9 +28,9 @@ function quoteMarkdown(string) {
28
28
  * Characters escaped include: ~ ` > - \ [ ] ( ) # ^ & * _ ! <
29
29
  *
30
30
  * @param {string} string - The input string to escape for Markdown.
31
- * @returns {string} The escaped string, safe for Markdown rendering.
31
+ * @reexport returns {string} The escaped string, safe for Markdown rendering.
32
32
  */
33
- function markdown_escape(string) {
33
+ export function markdown_escape(string) {
34
34
  return normalize_newlines(string).replace(/[~`>\-\\\[\]()#^&*_!<]/g, '\\$&');
35
35
  }
36
36
  /**
@@ -54,3 +54,284 @@ export function jsonEncode(jsonicItem, indent = false, replacer) {
54
54
  export function jsonEncodeIndent(jsonicItem, indent = true, replacer) {
55
55
  return indent_codeblock(jsonEncode(jsonicItem, indent, replacer));
56
56
  }
57
+ // CustomError
58
+ export class CustomError extends Error {
59
+ detail;
60
+ constructor(message, detail) {
61
+ super(message);
62
+ this.detail = detail;
63
+ this.name = new.target?.name ?? 'CustomError';
64
+ }
65
+ get [Symbol.toStringTag]() {
66
+ return this.name;
67
+ }
68
+ static [Symbol.toStringTag] = "CustomError";
69
+ }
70
+ export const EXMAScript = Object.freeze({
71
+ __proto__: {
72
+ [Symbol.toStringTag]: 'EXMAScriptInternals',
73
+ }, toIntegerOrInfinity(n) {
74
+ n = +n;
75
+ if (Object.is(n, NaN) || n === 0) {
76
+ return 0;
77
+ }
78
+ else
79
+ return Math.trunc(n);
80
+ }, OrdinaryToPrimitive(mixed, hint = "number") {
81
+ if (!["string", "number"].includes(hint))
82
+ throw new TypeError('incorrect hint');
83
+ if (!isObject(mixed))
84
+ return mixed;
85
+ const methodNames = hint === "string" ? ["toString", "valueOf"] : ["valueOf", "toString"];
86
+ for (let methodName of methodNames) {
87
+ if (methodName in mixed) {
88
+ if (typeof mixed[methodName] === "function") {
89
+ const primitive = mixed[methodName]();
90
+ if (!isObject(primitive))
91
+ return primitive;
92
+ }
93
+ }
94
+ }
95
+ throw new TypeError('could not convert to Primitive');
96
+ }, toPrimitive(value, hint) {
97
+ if (!["string", "number"].includes(hint))
98
+ throw new TypeError('incorrect hint');
99
+ let primitive;
100
+ if (value === null)
101
+ return "null";
102
+ if (typeof value === "object" || typeof value === "function") {
103
+ if (Symbol.toPrimitive in value && typeof value[Symbol.toPrimitive] === "function") {
104
+ primitive = value[Symbol.toPrimitive]('string');
105
+ if (isObject(primitive))
106
+ throw new TypeError;
107
+ }
108
+ else {
109
+ primitive = EXMAScript.OrdinaryToPrimitive(value, "string");
110
+ }
111
+ }
112
+ else
113
+ primitive = value;
114
+ return primitive;
115
+ }, toPropertyKey(value) {
116
+ const primitive = EXMAScript.toPrimitive(value, "string");
117
+ if (typeof primitive === "symbol")
118
+ return primitive;
119
+ return String(primitive);
120
+ }, toNumeric(value) {
121
+ // Handle object conversion
122
+ value = EXMAScript.toPrimitive(value, "number");
123
+ if (typeof value === 'bigint')
124
+ return value;
125
+ else
126
+ return +value;
127
+ }, isNaN(nan) {
128
+ return isNaN(nan);
129
+ }, webBuiltins: Object.freeze({
130
+ [Symbol.toStringTag]: 'WebInternals',
131
+ TokenList: class TokenList {
132
+ #tokens;
133
+ constructor(array) {
134
+ this.#tokens = new Set(Array.from(array, s => `${s}`));
135
+ }
136
+ [Symbol.toStringTag] = 'TokenList';
137
+ toString() {
138
+ return Array.prototype.join.call(Array.from(this.#tokens.keys()), ' ');
139
+ }
140
+ add(...tokens) {
141
+ Array.from(tokens).forEach(s => this.#tokens.add(this._validateToken(s)));
142
+ }
143
+ contains(token) {
144
+ return this.#tokens.has(token);
145
+ }
146
+ remove(...tokens) {
147
+ Array.from(tokens).forEach(s => this.#tokens.delete(this._validateToken(s)));
148
+ }
149
+ toggle(token, force = undefined) {
150
+ token = this._validateToken(token);
151
+ if (this.contains(token)) {
152
+ if (force === false || force === undefined) {
153
+ this.remove(token);
154
+ return false;
155
+ }
156
+ if (force) {
157
+ this.add(token);
158
+ return true;
159
+ }
160
+ }
161
+ }
162
+ _validateToken(token) {
163
+ token = `${token}`;
164
+ if (token === '') {
165
+ throw new EXMAScript.webBuiltins.SyntaxError('token is empty');
166
+ }
167
+ else if (/\s+/.test(token)) {
168
+ throw new EXMAScript.webBuiltins.InvalidCharacterError('token is contains whitespace');
169
+ }
170
+ return token;
171
+ }
172
+ replace(oldToken, newToken) {
173
+ oldToken = this._validateToken(oldToken);
174
+ newToken = this._validateToken(newToken);
175
+ if (this.contains(oldToken)) {
176
+ this.remove(oldToken);
177
+ this.remove(newToken);
178
+ return true;
179
+ }
180
+ return false;
181
+ }
182
+ get value() {
183
+ return this.toString();
184
+ }
185
+ get length() {
186
+ return this.#tokens.size;
187
+ }
188
+ },
189
+ SyntaxError: class extends CustomError {
190
+ constructor(m) {
191
+ super(m, '"SyntaxError" DOMException');
192
+ }
193
+ },
194
+ InvalidCharacterError: class extends CustomError {
195
+ constructor(m) {
196
+ super(m, '"InvalidCharacterError" DOMException');
197
+ }
198
+ },
199
+ }),
200
+ });
201
+ export function ResolveSecondsAfterNow(s = 0) {
202
+ return new Date((new Date).setMilliseconds(0) + (+s) * 1000);
203
+ }
204
+ /*
205
+ function ResolveSecondsAfterNow(s=0){return new Date((new Date).setMilliseconds(0)+(+s)*1000)}
206
+ */
207
+ export const mkJsonifable = ((Base) => class extends Base {
208
+ toJSON() {
209
+ const json = super.toJSON?.(...arguments);
210
+ if (json !== undefined)
211
+ return json;
212
+ return `${this}`;
213
+ }
214
+ });
215
+ // assignProperties.ts
216
+ export function assignProperties(to, source, propertyNames) {
217
+ if (!isObject(to))
218
+ throw new TypeError('to isnt an object');
219
+ for (let properryObj of propertyNames) {
220
+ const property = EXMAScript.toPropertyKey(properryObj);
221
+ Reflect.set(to, property, Reflect.get(source, property));
222
+ }
223
+ return to;
224
+ }
225
+ export function isObject(value) {
226
+ if (value === null)
227
+ return false;
228
+ return (typeof value === "object" || typeof value === "function");
229
+ }
230
+ export function sortArray(array, key, converter) {
231
+ return Array.from(array, converter ?? (m => m)).map(value => ({
232
+ value, key: +Function.prototype.apply.call(key, value),
233
+ })).sort((a, b) => a.key - b.key).map(({ value }) => value);
234
+ }
235
+ export function getProperty(on, properties) {
236
+ const array = Array.from(properties, EXMAScript.toPropertyKey);
237
+ if (!isObject(on))
238
+ throw new TypeError;
239
+ let self = on;
240
+ for (let property of array) {
241
+ self = on;
242
+ on = Reflect.get(on, property);
243
+ if (on === null || on === undefined) {
244
+ const element = { result: undefined, self };
245
+ throw new CustomError(`couldnt read properties on (${on}) reading (${String(property)})`, element);
246
+ }
247
+ }
248
+ const result = on;
249
+ return { result, self };
250
+ } // the result is the property, the self is the (this) value.
251
+ export function allKeys(object) {
252
+ object = Object(object);
253
+ const result = Reflect.ownKeys(object);
254
+ while (object = Object.getPrototypeOf(object)) {
255
+ result.push(...Reflect.ownKeys(object));
256
+ }
257
+ return [...(new Set(result))];
258
+ }
259
+ export function isSafeIntegerRange(n) {
260
+ n = -(-n);
261
+ if (typeof n === "bigint") {
262
+ return n > Number.MIN_SAFE_INTEGER && n < Number.MAX_SAFE_INTEGER;
263
+ }
264
+ else
265
+ return Number.isSafeInteger(n);
266
+ }
267
+ export function NumericAbs(n) {
268
+ n = -n;
269
+ if (n < 0)
270
+ return -n;
271
+ return n;
272
+ }
273
+ export function getObjectType(o) {
274
+ const s = Object.prototype.toString.call(o);
275
+ return s.slice("[object ".length, -1);
276
+ }
277
+ export function countBooleansAndNullishItems(array) {
278
+ array = Array.from(array ?? [], b => (b === null || b === undefined) ? null : Boolean(b));
279
+ const result = { true: 0, false: 0, nullish: 0 };
280
+ for (let e of array) {
281
+ if (e === null)
282
+ result.nullish += 1;
283
+ else if (e)
284
+ result.true += 1;
285
+ else
286
+ result.false += 1;
287
+ }
288
+ return result;
289
+ }
290
+ export function removeDuplications(array) {
291
+ const dupe = Symbol("dupelication"), dupes = new Set;
292
+ return Array.from(array, function (m) {
293
+ if (dupes.has(m))
294
+ return dupe;
295
+ dupes.add(m);
296
+ return m;
297
+ }).filter(m => m !== dupe);
298
+ }
299
+ export function startOfDay(date) {
300
+ return (new Date(date ?? Date.now())).setHours(0, 0, 0, 0);
301
+ }
302
+ export function startOfDayUTC(date) {
303
+ return (new Date(date ?? Date.now())).setUTCHours(0, 0, 0, 0);
304
+ }
305
+ export class CounterItems {
306
+ #items = new Map;
307
+ [Symbol.toStringTag] = 'CounterItems';
308
+ add(object) {
309
+ if (!this.#items.has(object)) {
310
+ !this.#items.set(object, 0);
311
+ }
312
+ this.#items.set(object, this.#items.get(object) + 1);
313
+ return this;
314
+ }
315
+ set0(object) {
316
+ if (!this.#items.has(object)) {
317
+ !this.#items.set(object, 0);
318
+ }
319
+ return this;
320
+ }
321
+ get(object) {
322
+ return Number(this.#items.get(object));
323
+ }
324
+ toJSON() {
325
+ const obj = { __proto__: null };
326
+ for (const [key, value] of this.#items) {
327
+ if (typeof key === 'string') {
328
+ obj[key] = value;
329
+ }
330
+ }
331
+ return obj;
332
+ }
333
+ clear() {
334
+ this.#items.clear();
335
+ return this;
336
+ }
337
+ }