@zoodogood/utils 5.1.2-change.4266 → 7.0.0-change.4513
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/lib/discordjs/message_lifecycle.d.ts.map +1 -1
- package/lib/discordjs/message_lifecycle.js +1 -2
- package/lib/objectives/BusyNumeric.d.ts.map +1 -1
- package/lib/objectives/BusyNumeric.js +2 -1
- package/lib/objectives/GlitchText.js +2 -2
- package/lib/objectives/getRandomElementFromArray.d.ts +13 -8
- package/lib/objectives/getRandomElementFromArray.d.ts.map +1 -1
- package/lib/objectives/getRandomElementFromArray.js +119 -16
- package/lib/objectives/mod.d.ts +2 -2
- package/lib/objectives/mod.d.ts.map +1 -1
- package/lib/objectives/mod.js +2 -2
- package/lib/objectives/randomElementFromArray.d.ts +37 -0
- package/lib/objectives/randomElementFromArray.d.ts.map +1 -0
- package/lib/objectives/randomElementFromArray.js +219 -0
- package/lib/objectives/randomNumberInRange.d.ts +8 -0
- package/lib/objectives/randomNumberInRange.d.ts.map +1 -0
- package/lib/objectives/randomNumberInRange.js +8 -0
- package/lib/primitives/mod.d.ts +1 -4
- package/lib/primitives/mod.d.ts.map +1 -1
- package/lib/primitives/mod.js +1 -11
- package/lib/primitives/pluralization/index.d.ts +13 -0
- package/lib/primitives/pluralization/index.d.ts.map +1 -0
- package/lib/primitives/pluralization/index.js +107 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message_lifecycle.d.ts","sourceRoot":"","sources":["../../src/discordjs/message_lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACpB,YAAY,EACZ,OAAO,EACP,KAAK,oBAAoB,EAEzB,KAAK,gBAAgB,EACrB,IAAI,EAEJ,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAEN,KAAK,qBAAqB,EAG1B,MAAM,UAAU,CAAC;AAElB,iBAAS,UAAU,CAClB,CAAC,SACE,IAAI,GACJ,gBAAgB,GAChB,OAAO,GACP,CAAC,EAAE,GAAG;IAAE,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC,GACpC,CAAC,EAAE,GAAG;IAAE,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,EAEvE,MAAM,EAAE,CAAC,GACP;IACF,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D,CAWA;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,wBAAgB,YAAY,CAC3B,KAAK,EAAE;KAAG,GAAG,IAAI,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,OAAO;CAAE,WAmBvD;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,eAAe,wBA8DzD;AAED;;;GAGG;AAEH,wBAAsB,eAAe,CAAC,OAAO,SAAS,OAAO,EAC5D,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EACxC,OAAO,EAAE,eAAe,+BAIxB;AAED,wBAAsB,WAAW,CAAC,OAAO,SAAS,OAAO,EACxD,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EACxC,YAAY,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,EAC9C,WAAW,EAAE,eAAe,GAC1B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"message_lifecycle.d.ts","sourceRoot":"","sources":["../../src/discordjs/message_lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACpB,YAAY,EACZ,OAAO,EACP,KAAK,oBAAoB,EAEzB,KAAK,gBAAgB,EACrB,IAAI,EAEJ,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAEN,KAAK,qBAAqB,EAG1B,MAAM,UAAU,CAAC;AAElB,iBAAS,UAAU,CAClB,CAAC,SACE,IAAI,GACJ,gBAAgB,GAChB,OAAO,GACP,CAAC,EAAE,GAAG;IAAE,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC,GACpC,CAAC,EAAE,GAAG;IAAE,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,EAEvE,MAAM,EAAE,CAAC,GACP;IACF,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1D,CAWA;AAED,MAAM,WAAW,eAAe;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,wBAAgB,YAAY,CAC3B,KAAK,EAAE;KAAG,GAAG,IAAI,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,OAAO;CAAE,WAmBvD;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,eAAe,wBA8DzD;AAED;;;GAGG;AAEH,wBAAsB,eAAe,CAAC,OAAO,SAAS,OAAO,EAC5D,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EACxC,OAAO,EAAE,eAAe,+BAIxB;AAED,wBAAsB,WAAW,CAAC,OAAO,SAAS,OAAO,EACxD,MAAM,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EACxC,YAAY,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,EAC9C,WAAW,EAAE,eAAe,GAC1B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAoG3B"}
|
|
@@ -125,7 +125,6 @@ export async function sendMessage(target, message_data, mut_payload) {
|
|
|
125
125
|
if (!chain) {
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
|
-
const channel = sendableOf(target);
|
|
129
128
|
const index = chain.indexOf(message.id);
|
|
130
129
|
if (index === 0) {
|
|
131
130
|
return;
|
|
@@ -134,7 +133,7 @@ export async function sendMessage(target, message_data, mut_payload) {
|
|
|
134
133
|
if (!child_message_id) {
|
|
135
134
|
return;
|
|
136
135
|
}
|
|
137
|
-
return await
|
|
136
|
+
return await sendableOf(target).messages.fetch(child_message_id);
|
|
138
137
|
})()) ||
|
|
139
138
|
(await (async () => {
|
|
140
139
|
const child_message = await justSendMessage(sendableOf(target), mut_payload._chain_child);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BusyNumeric.d.ts","sourceRoot":"","sources":["../../src/objectives/BusyNumeric.ts"],"names":[],"mappings":"AAuBA;;;;;;;GAOG;AAQH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,UAE3D;AACD,qBAAa,WAAW;;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAM;IACxD,SAAS,EAAE,MAAM,CAAC;IAElB,IAAI,eAAe,YASlB;IAED,IAAI,aAAa,YAShB;gBACW,KAAK,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"BusyNumeric.d.ts","sourceRoot":"","sources":["../../src/objectives/BusyNumeric.ts"],"names":[],"mappings":"AAuBA;;;;;;;GAOG;AAQH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,UAE3D;AACD,qBAAa,WAAW;;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAM;IACxD,SAAS,EAAE,MAAM,CAAC;IAElB,IAAI,eAAe,YASlB;IAED,IAAI,aAAa,YAShB;gBACW,KAAK,EAAE,MAAM;IAOzB,SAAS,CAAC,KAAK,EAAE,MAAM;IAIvB,cAAc;IAMd,OAAO,CAAC,EAAE,EAAE,MAAM;;;;;IAqClB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAkEtC,OAAO;;;;MAUL;CACH"}
|
|
@@ -59,6 +59,7 @@ export class BusyNumeric {
|
|
|
59
59
|
}
|
|
60
60
|
constructor(range) {
|
|
61
61
|
assert(range > 0, "Range must be positive");
|
|
62
|
+
assert(range <= Number.MAX_SAFE_INTEGER, "range <= Number.MAX_SAFE_INTEGER");
|
|
62
63
|
this.range = range;
|
|
63
64
|
this.free_area = this.range + /* includes position 0 */ 1;
|
|
64
65
|
}
|
|
@@ -131,7 +132,7 @@ export class BusyNumeric {
|
|
|
131
132
|
const [index, points] = is_left_included
|
|
132
133
|
? [place_index - 1, [target[0], end]]
|
|
133
134
|
: [place_index, [start, target[1]]];
|
|
134
|
-
assert(!(target[0] <= start && target[1] >= end), "Assertion error: [start, end] in
|
|
135
|
+
assert(!(target[0] <= start && target[1] >= end), "Assertion error: range [start, end] already in busy area");
|
|
135
136
|
this.free_area -= size_of_area(points) - size_of_area(target);
|
|
136
137
|
this.busy_areas.splice(index, 1, points);
|
|
137
138
|
return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomNumberInRange } from "./randomNumberInRange.js";
|
|
2
2
|
class GlitchText {
|
|
3
3
|
constructor(from = "", to = "hello, world", { step = 15, random = false, maximum = 100 } = {}) {
|
|
4
4
|
this.from = from;
|
|
@@ -18,7 +18,7 @@ class GlitchText {
|
|
|
18
18
|
word.pop();
|
|
19
19
|
if (word.length < target.length)
|
|
20
20
|
word.push(String.fromCharCode(~~(Math.random() * 50)));
|
|
21
|
-
word.forEach((_, index, array) => array[index] = String.fromCharCode(
|
|
21
|
+
word.forEach((_, index, array) => array[index] = String.fromCharCode(randomNumberInRange({ min: MIN, max: MAX })));
|
|
22
22
|
yield word.join("");
|
|
23
23
|
}
|
|
24
24
|
if (this.maximum)
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import { create_default_preventable } from "../primitives/createDefaultPreventable.js";
|
|
2
1
|
import { BusyNumeric } from "./BusyNumeric.js";
|
|
2
|
+
export declare const _WEIGHT_AUTO = 1000001;
|
|
3
3
|
interface IParams<T> {
|
|
4
|
-
associatedWeights?: number[];
|
|
4
|
+
associatedWeights?: number[] | typeof _WEIGHT_AUTO;
|
|
5
5
|
filter?: (item: T) => boolean;
|
|
6
6
|
}
|
|
7
7
|
interface IPickContext<T> {
|
|
8
|
-
busy_preventable: ReturnType<typeof create_default_preventable> & {
|
|
9
|
-
require_insert(): void;
|
|
10
|
-
};
|
|
11
8
|
item: T;
|
|
12
9
|
pick: (context: IPickContext<T>) => boolean;
|
|
13
10
|
threshold: number;
|
|
14
11
|
point: number;
|
|
12
|
+
index_of_item: number;
|
|
13
|
+
}
|
|
14
|
+
interface ILotteryContext {
|
|
15
|
+
index_of_item: number;
|
|
16
|
+
point: number;
|
|
17
|
+
remove_current_from_pull(): void;
|
|
15
18
|
}
|
|
16
19
|
export declare class RandomizerContext<T> {
|
|
17
20
|
hotel: BusyNumeric;
|
|
@@ -20,13 +23,15 @@ export declare class RandomizerContext<T> {
|
|
|
20
23
|
constructor(array: T[], thresholds?: number[]);
|
|
21
24
|
static from<T>({ array, associatedWeights, }: {
|
|
22
25
|
array: T[];
|
|
23
|
-
associatedWeights?:
|
|
26
|
+
associatedWeights?: number[];
|
|
24
27
|
}): RandomizerContext<T>;
|
|
25
28
|
pickRandom(pick?: IPickContext<T>["pick"]): T | undefined;
|
|
29
|
+
playLottery(): ILotteryContext | undefined;
|
|
26
30
|
}
|
|
27
31
|
export declare function pickInThresholds(thresholds: number[], value: number): number;
|
|
28
|
-
export declare function thresholdsOf(weights: NonNullable<
|
|
29
|
-
export declare function getRandomElementIndexInWeights(weights: NonNullable<
|
|
32
|
+
export declare function thresholdsOf(weights: NonNullable<number[]>): number[];
|
|
33
|
+
export declare function getRandomElementIndexInWeights(weights: NonNullable<number[]>): number | never;
|
|
30
34
|
export declare function getRandomElementFromArray<T>(array: T[], { associatedWeights, filter }?: IParams<T>): T | undefined;
|
|
35
|
+
export declare function getRandomElementsFromArray<T>(array: T[], amount?: number, { associatedWeights, filter }?: IParams<T>): T[];
|
|
31
36
|
export {};
|
|
32
37
|
//# sourceMappingURL=getRandomElementFromArray.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRandomElementFromArray.d.ts","sourceRoot":"","sources":["../../src/objectives/getRandomElementFromArray.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"getRandomElementFromArray.d.ts","sourceRoot":"","sources":["../../src/objectives/getRandomElementFromArray.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAgB,MAAM,kBAAkB,CAAC;AAG7D,eAAO,MAAM,YAAY,UAAY,CAAC;AACtC,UAAU,OAAO,CAAC,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,YAAY,CAAC;IACnD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;CAC9B;AAED,UAAU,YAAY,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,eAAe;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB,IAAI,IAAI,CAAC;CACjC;AAED,qBAAa,iBAAiB,CAAC,CAAC;IAC/B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;gBACV,KAAK,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE;IAc7C,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EACd,KAAK,EACL,iBAAiB,GACjB,EAAE;QACF,KAAK,EAAE,CAAC,EAAE,CAAC;QACX,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B;IAID,UAAU,CAAC,IAAI,GAAE,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAc,GAAG,CAAC,GAAG,SAAS;IAsDrE,WAAW,IAAI,eAAe,GAAG,SAAS;CAiD1C;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAY5E;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,GAGG,MAAM,EAAE,CACrE;AAED,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,GAC5B,MAAM,GAAG,KAAK,CAKhB;AAkBD,wBAAgB,yBAAyB,CAAC,CAAC,EAC1C,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,iBAAiB,EAAE,MAAmB,EAAE,GAAE,OAAO,CAAC,CAAC,CAAM,iBA8B3D;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAC3C,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,SAAI,EACV,EAAE,iBAAiB,EAAE,MAAmB,EAAE,GAAE,OAAO,CAAC,CAAC,CAAM,OAiD3D"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert";
|
|
2
2
|
import { binary_search } from "../primitives/binary_search.js";
|
|
3
|
-
import { create_default_preventable } from "../primitives/createDefaultPreventable.js";
|
|
4
3
|
import { BusyNumeric, size_of_area } from "./BusyNumeric.js";
|
|
5
4
|
import { getRandomNumberInRange } from "./getRandomNumberInRange.js";
|
|
5
|
+
export const _WEIGHT_AUTO = 1_000_001;
|
|
6
6
|
export class RandomizerContext {
|
|
7
7
|
hotel;
|
|
8
8
|
array;
|
|
@@ -13,6 +13,13 @@ export class RandomizerContext {
|
|
|
13
13
|
const range = thresholds?.at(-1) ?? array.length - 1;
|
|
14
14
|
this.hotel = new BusyNumeric(range);
|
|
15
15
|
}
|
|
16
|
+
/* Add to your code
|
|
17
|
+
if (associatedWeights === AUTO) {
|
|
18
|
+
// @ts-expect-error User known about AUTO keyword
|
|
19
|
+
associatedWeights = array.map(($) => $._weight);
|
|
20
|
+
}
|
|
21
|
+
associatedWeights?.length && assert(associatedWeights.at(-1)! < Number.MAX_SAFE_INTEGER)
|
|
22
|
+
*/
|
|
16
23
|
static from({ array, associatedWeights, }) {
|
|
17
24
|
const thresholds = associatedWeights && thresholdsOf(associatedWeights);
|
|
18
25
|
return new RandomizerContext(array, thresholds);
|
|
@@ -24,13 +31,17 @@ export class RandomizerContext {
|
|
|
24
31
|
if (!segments_count) {
|
|
25
32
|
break;
|
|
26
33
|
}
|
|
27
|
-
const target_of_free = getRandomNumberInRange({
|
|
34
|
+
const target_of_free = getRandomNumberInRange({
|
|
35
|
+
max: hotel.free_area - 1,
|
|
36
|
+
});
|
|
28
37
|
const position = (() => {
|
|
29
38
|
let segment = 0;
|
|
30
39
|
let distance = target_of_free;
|
|
31
40
|
let position = 0;
|
|
32
41
|
while (true) {
|
|
33
|
-
const free_area = (hotel.busy_areas[segment]?.[0] ?? hotel.range + 1) -
|
|
42
|
+
const free_area = (hotel.busy_areas[segment]?.[0] ?? hotel.range + 1) -
|
|
43
|
+
(hotel.busy_areas[segment - 1]?.[1] ?? -1) -
|
|
44
|
+
1;
|
|
34
45
|
distance -= free_area;
|
|
35
46
|
position += free_area;
|
|
36
47
|
if (distance < 0) {
|
|
@@ -40,33 +51,69 @@ export class RandomizerContext {
|
|
|
40
51
|
segment++;
|
|
41
52
|
}
|
|
42
53
|
})();
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
const index = thresholds
|
|
55
|
+
? pickInThresholds(thresholds, position)
|
|
56
|
+
: position;
|
|
45
57
|
const element = array[index];
|
|
46
58
|
const pickContext = {
|
|
47
|
-
busy_preventable: {
|
|
48
|
-
...create_default_preventable(),
|
|
49
|
-
require_insert() {
|
|
50
|
-
_require_insert = true;
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
59
|
item: element,
|
|
60
|
+
index_of_item: index,
|
|
54
61
|
pick,
|
|
55
62
|
threshold: index,
|
|
56
63
|
point: position,
|
|
57
64
|
};
|
|
58
65
|
const picked = pick(pickContext);
|
|
59
|
-
if (_require_insert || !picked && !pickContext.busy_preventable.default_prevented()) {
|
|
60
|
-
thresholds
|
|
61
|
-
? hotel.insert_area(thresholds[index - 1] + 1 || 0, thresholds[index])
|
|
62
|
-
: hotel.bifurcate(index);
|
|
63
|
-
}
|
|
64
66
|
if (picked) {
|
|
65
67
|
return element;
|
|
66
68
|
}
|
|
69
|
+
thresholds
|
|
70
|
+
? hotel.insert_area(thresholds[index - 1] + 1 || 0, thresholds[index])
|
|
71
|
+
: hotel.bifurcate(index);
|
|
67
72
|
}
|
|
68
73
|
return undefined;
|
|
69
74
|
}
|
|
75
|
+
playLottery() {
|
|
76
|
+
const { hotel, thresholds } = this;
|
|
77
|
+
while (true) {
|
|
78
|
+
const segments_count = hotel.segments_count();
|
|
79
|
+
if (!segments_count) {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
const target_of_free = getRandomNumberInRange({
|
|
83
|
+
max: hotel.free_area - 1,
|
|
84
|
+
});
|
|
85
|
+
const position = (() => {
|
|
86
|
+
let segment = 0;
|
|
87
|
+
let distance = target_of_free;
|
|
88
|
+
let position = 0;
|
|
89
|
+
while (true) {
|
|
90
|
+
const free_area = (hotel.busy_areas[segment]?.[0] ?? hotel.range + 1) -
|
|
91
|
+
(hotel.busy_areas[segment - 1]?.[1] ?? -1) -
|
|
92
|
+
1;
|
|
93
|
+
distance -= free_area;
|
|
94
|
+
position += free_area;
|
|
95
|
+
if (distance < 0) {
|
|
96
|
+
return position + distance;
|
|
97
|
+
}
|
|
98
|
+
position += size_of_area(hotel.busy_areas[segment] || [0, hotel.range + 1]);
|
|
99
|
+
segment++;
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
const index = thresholds
|
|
103
|
+
? pickInThresholds(thresholds, position)
|
|
104
|
+
: position;
|
|
105
|
+
const lotteryContext = {
|
|
106
|
+
index_of_item: index,
|
|
107
|
+
point: position,
|
|
108
|
+
remove_current_from_pull() {
|
|
109
|
+
thresholds
|
|
110
|
+
? hotel.insert_area(thresholds[index - 1] + 1 || 0, thresholds[index])
|
|
111
|
+
: hotel.bifurcate(index);
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
return lotteryContext;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
70
117
|
}
|
|
71
118
|
export function pickInThresholds(thresholds, value) {
|
|
72
119
|
assert(thresholds.length > 0);
|
|
@@ -108,9 +155,65 @@ export function getRandomElementIndexInWeights(weights) {
|
|
|
108
155
|
Повторяем
|
|
109
156
|
*/
|
|
110
157
|
export function getRandomElementFromArray(array, { associatedWeights, filter = () => true } = {}) {
|
|
158
|
+
assert(array.length, "Invalid array length");
|
|
159
|
+
if (associatedWeights === _WEIGHT_AUTO) {
|
|
160
|
+
// @ts-expect-error User know about AUTO keysymbol
|
|
161
|
+
associatedWeights = array.map(($) => $._weight);
|
|
162
|
+
}
|
|
163
|
+
associatedWeights?.length &&
|
|
164
|
+
assert(associatedWeights.at(-1) < Number.MAX_SAFE_INTEGER);
|
|
111
165
|
assert(!associatedWeights || associatedWeights.length === array.length, "Incorrectly passed argument associatedWeights: The length of the associatedWeights must exactly match the length of the weights array");
|
|
166
|
+
if (array.length === 1) {
|
|
167
|
+
return array[0];
|
|
168
|
+
}
|
|
169
|
+
// light strategy
|
|
170
|
+
if (!filter) {
|
|
171
|
+
if (associatedWeights) {
|
|
172
|
+
return array[getRandomElementIndexInWeights(associatedWeights)];
|
|
173
|
+
}
|
|
174
|
+
return array[Math.floor(Math.random() * array.length)];
|
|
175
|
+
}
|
|
112
176
|
return RandomizerContext.from({
|
|
113
177
|
array,
|
|
114
178
|
associatedWeights,
|
|
115
179
|
}).pickRandom(({ item }) => filter(item));
|
|
116
180
|
}
|
|
181
|
+
export function getRandomElementsFromArray(array, amount = 1, { associatedWeights, filter = () => true } = {}) {
|
|
182
|
+
assert(array.length);
|
|
183
|
+
assert(amount <= array.length);
|
|
184
|
+
assert(amount > 1, `Current amount: ${amount}, use getRandomElementFromArray instead of getRandomElement**s**FromArray if amount is 1`);
|
|
185
|
+
if (associatedWeights === _WEIGHT_AUTO) {
|
|
186
|
+
// @ts-expect-error User know about AUTO keysymbol
|
|
187
|
+
associatedWeights = array.map(($) => $._weight);
|
|
188
|
+
}
|
|
189
|
+
associatedWeights?.length &&
|
|
190
|
+
assert(associatedWeights.at(-1) < Number.MAX_SAFE_INTEGER);
|
|
191
|
+
assert(!associatedWeights || associatedWeights.length === array.length, "Incorrectly passed argument associatedWeights: The length of the associatedWeights must exactly match the length of the weights array");
|
|
192
|
+
if (amount === array.length) {
|
|
193
|
+
return Array.from(array);
|
|
194
|
+
}
|
|
195
|
+
// light strategy
|
|
196
|
+
if (!filter && !associatedWeights) {
|
|
197
|
+
const _array = Array.from(array);
|
|
198
|
+
return Array.from({ length: amount }, () => _array.splice(Math.floor(Math.random() * _array.length), 1)[0]);
|
|
199
|
+
}
|
|
200
|
+
const random_ctx = RandomizerContext.from({
|
|
201
|
+
array,
|
|
202
|
+
associatedWeights,
|
|
203
|
+
});
|
|
204
|
+
return Array.from({ length: amount }, (_, i) => {
|
|
205
|
+
while (true) {
|
|
206
|
+
const lottery_ctx = random_ctx.playLottery();
|
|
207
|
+
if (!lottery_ctx) {
|
|
208
|
+
// BEFORE PULL TO-DO вероятно неграммотное сообщение об ошибке
|
|
209
|
+
throw new Error("Not enought items was pass filter");
|
|
210
|
+
}
|
|
211
|
+
lottery_ctx.remove_current_from_pull();
|
|
212
|
+
const item = array[lottery_ctx.index_of_item];
|
|
213
|
+
if (!filter(item)) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
return item;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
package/lib/objectives/mod.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ export * from "./BusyNumeric.js";
|
|
|
2
2
|
export * from "./CustomCollector.js";
|
|
3
3
|
export * from "./DotNotatedInterface.js";
|
|
4
4
|
export * from "./ExtendedEnum/mod.js";
|
|
5
|
-
export * from "./getRandomElementFromArray.js";
|
|
6
|
-
export * from "./getRandomNumberInRange.js";
|
|
7
5
|
export * from "./GlitchText.js";
|
|
8
6
|
export * from "./LazySort/LazySort.build.js";
|
|
7
|
+
export * from "./randomElementFromArray.js";
|
|
8
|
+
export * from "./randomNumberInRange.js";
|
|
9
9
|
export * from "./rangeToArray.js";
|
|
10
10
|
declare function omit(object: object, filter: CallableFunction): {
|
|
11
11
|
[k: string]: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/objectives/mod.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/objectives/mod.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAElC,iBAAS,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB;;EAMrD;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
|
package/lib/objectives/mod.js
CHANGED
|
@@ -2,10 +2,10 @@ export * from "./BusyNumeric.js";
|
|
|
2
2
|
export * from "./CustomCollector.js";
|
|
3
3
|
export * from "./DotNotatedInterface.js";
|
|
4
4
|
export * from "./ExtendedEnum/mod.js";
|
|
5
|
-
export * from "./getRandomElementFromArray.js";
|
|
6
|
-
export * from "./getRandomNumberInRange.js";
|
|
7
5
|
export * from "./GlitchText.js";
|
|
8
6
|
export * from "./LazySort/LazySort.build.js";
|
|
7
|
+
export * from "./randomElementFromArray.js";
|
|
8
|
+
export * from "./randomNumberInRange.js";
|
|
9
9
|
export * from "./rangeToArray.js";
|
|
10
10
|
function omit(object, filter) {
|
|
11
11
|
const entries = Object.entries(object).filter(([key, value], i) => filter(key, value, i));
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BusyNumeric } from "./BusyNumeric.js";
|
|
2
|
+
export declare const _WEIGHT_AUTO = 1000001;
|
|
3
|
+
interface IParams<T> {
|
|
4
|
+
associatedWeights?: number[] | typeof _WEIGHT_AUTO;
|
|
5
|
+
filter?: (item: T) => boolean;
|
|
6
|
+
}
|
|
7
|
+
interface IPickContext<T> {
|
|
8
|
+
item: T;
|
|
9
|
+
pick: (context: IPickContext<T>) => boolean;
|
|
10
|
+
threshold: number;
|
|
11
|
+
point: number;
|
|
12
|
+
index_of_item: number;
|
|
13
|
+
}
|
|
14
|
+
interface ILotteryContext {
|
|
15
|
+
index_of_item: number;
|
|
16
|
+
point: number;
|
|
17
|
+
remove_current_from_pull(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class RandomizerContext<T> {
|
|
20
|
+
hotel: BusyNumeric;
|
|
21
|
+
array: T[];
|
|
22
|
+
thresholds?: number[];
|
|
23
|
+
constructor(array: T[], thresholds?: number[]);
|
|
24
|
+
static from<T>({ array, associatedWeights, }: {
|
|
25
|
+
array: T[];
|
|
26
|
+
associatedWeights?: number[];
|
|
27
|
+
}): RandomizerContext<T>;
|
|
28
|
+
pickRandom(pick?: IPickContext<T>["pick"]): T | undefined;
|
|
29
|
+
playLottery(): ILotteryContext | undefined;
|
|
30
|
+
}
|
|
31
|
+
export declare function pickInThresholds(thresholds: number[], value: number): number;
|
|
32
|
+
export declare function thresholdsOf(weights: NonNullable<number[]>): number[];
|
|
33
|
+
export declare function randomElementIndexInWeights(weights: NonNullable<number[]>): number | never;
|
|
34
|
+
export declare function randomElementFromArray<T>(array: T[], { associatedWeights, filter }?: IParams<T>): T | undefined;
|
|
35
|
+
export declare function randomElementsFromArray<T>(array: T[], amount?: number, { associatedWeights, filter }?: IParams<T>): T[];
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=randomElementFromArray.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"randomElementFromArray.d.ts","sourceRoot":"","sources":["../../src/objectives/randomElementFromArray.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAgB,MAAM,kBAAkB,CAAC;AAG7D,eAAO,MAAM,YAAY,UAAY,CAAC;AACtC,UAAU,OAAO,CAAC,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,YAAY,CAAC;IACnD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;CAC9B;AAED,UAAU,YAAY,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,eAAe;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB,IAAI,IAAI,CAAC;CACjC;AAED,qBAAa,iBAAiB,CAAC,CAAC;IAC/B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;gBACV,KAAK,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE;IAc7C,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EACd,KAAK,EACL,iBAAiB,GACjB,EAAE;QACF,KAAK,EAAE,CAAC,EAAE,CAAC;QACX,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B;IAID,UAAU,CAAC,IAAI,GAAE,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAc,GAAG,CAAC,GAAG,SAAS;IAsDrE,WAAW,IAAI,eAAe,GAAG,SAAS;CAiD1C;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAY5E;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,GAGG,MAAM,EAAE,CACrE;AAED,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,GAC5B,MAAM,GAAG,KAAK,CAKhB;AAkBD,wBAAgB,sBAAsB,CAAC,CAAC,EACvC,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,iBAAiB,EAAE,MAAmB,EAAE,GAAE,OAAO,CAAC,CAAC,CAAM,iBA8B3D;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EACxC,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,SAAI,EACV,EAAE,iBAAiB,EAAE,MAAmB,EAAE,GAAE,OAAO,CAAC,CAAC,CAAM,OAiD3D"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { binary_search } from "../primitives/binary_search.js";
|
|
3
|
+
import { BusyNumeric, size_of_area } from "./BusyNumeric.js";
|
|
4
|
+
import { randomNumberInRange } from "./randomNumberInRange.js";
|
|
5
|
+
export const _WEIGHT_AUTO = 1_000_001;
|
|
6
|
+
export class RandomizerContext {
|
|
7
|
+
hotel;
|
|
8
|
+
array;
|
|
9
|
+
thresholds;
|
|
10
|
+
constructor(array, thresholds) {
|
|
11
|
+
this.array = array;
|
|
12
|
+
this.thresholds = thresholds;
|
|
13
|
+
const range = thresholds?.at(-1) ?? array.length - 1;
|
|
14
|
+
this.hotel = new BusyNumeric(range);
|
|
15
|
+
}
|
|
16
|
+
/* Add to your code
|
|
17
|
+
if (associatedWeights === AUTO) {
|
|
18
|
+
// @ts-expect-error User known about AUTO keyword
|
|
19
|
+
associatedWeights = array.map(($) => $._weight);
|
|
20
|
+
}
|
|
21
|
+
associatedWeights?.length && assert(associatedWeights.at(-1)! < Number.MAX_SAFE_INTEGER)
|
|
22
|
+
*/
|
|
23
|
+
static from({ array, associatedWeights, }) {
|
|
24
|
+
const thresholds = associatedWeights && thresholdsOf(associatedWeights);
|
|
25
|
+
return new RandomizerContext(array, thresholds);
|
|
26
|
+
}
|
|
27
|
+
pickRandom(pick = () => true) {
|
|
28
|
+
const { hotel, thresholds, array } = this;
|
|
29
|
+
while (true) {
|
|
30
|
+
const segments_count = hotel.segments_count();
|
|
31
|
+
if (!segments_count) {
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
const target_of_free = randomNumberInRange({
|
|
35
|
+
max: hotel.free_area - 1,
|
|
36
|
+
});
|
|
37
|
+
const position = (() => {
|
|
38
|
+
let segment = 0;
|
|
39
|
+
let distance = target_of_free;
|
|
40
|
+
let position = 0;
|
|
41
|
+
while (true) {
|
|
42
|
+
const free_area = (hotel.busy_areas[segment]?.[0] ?? hotel.range + 1) -
|
|
43
|
+
(hotel.busy_areas[segment - 1]?.[1] ?? -1) -
|
|
44
|
+
1;
|
|
45
|
+
distance -= free_area;
|
|
46
|
+
position += free_area;
|
|
47
|
+
if (distance < 0) {
|
|
48
|
+
return position + distance;
|
|
49
|
+
}
|
|
50
|
+
position += size_of_area(hotel.busy_areas[segment] || [0, hotel.range + 1]);
|
|
51
|
+
segment++;
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
const index = thresholds
|
|
55
|
+
? pickInThresholds(thresholds, position)
|
|
56
|
+
: position;
|
|
57
|
+
const element = array[index];
|
|
58
|
+
const pickContext = {
|
|
59
|
+
item: element,
|
|
60
|
+
index_of_item: index,
|
|
61
|
+
pick,
|
|
62
|
+
threshold: index,
|
|
63
|
+
point: position,
|
|
64
|
+
};
|
|
65
|
+
const picked = pick(pickContext);
|
|
66
|
+
if (picked) {
|
|
67
|
+
return element;
|
|
68
|
+
}
|
|
69
|
+
thresholds
|
|
70
|
+
? hotel.insert_area(thresholds[index - 1] + 1 || 0, thresholds[index])
|
|
71
|
+
: hotel.bifurcate(index);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
playLottery() {
|
|
76
|
+
const { hotel, thresholds } = this;
|
|
77
|
+
while (true) {
|
|
78
|
+
const segments_count = hotel.segments_count();
|
|
79
|
+
if (!segments_count) {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
const target_of_free = randomNumberInRange({
|
|
83
|
+
max: hotel.free_area - 1,
|
|
84
|
+
});
|
|
85
|
+
const position = (() => {
|
|
86
|
+
let segment = 0;
|
|
87
|
+
let distance = target_of_free;
|
|
88
|
+
let position = 0;
|
|
89
|
+
while (true) {
|
|
90
|
+
const free_area = (hotel.busy_areas[segment]?.[0] ?? hotel.range + 1) -
|
|
91
|
+
(hotel.busy_areas[segment - 1]?.[1] ?? -1) -
|
|
92
|
+
1;
|
|
93
|
+
distance -= free_area;
|
|
94
|
+
position += free_area;
|
|
95
|
+
if (distance < 0) {
|
|
96
|
+
return position + distance;
|
|
97
|
+
}
|
|
98
|
+
position += size_of_area(hotel.busy_areas[segment] || [0, hotel.range + 1]);
|
|
99
|
+
segment++;
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
const index = thresholds
|
|
103
|
+
? pickInThresholds(thresholds, position)
|
|
104
|
+
: position;
|
|
105
|
+
const lotteryContext = {
|
|
106
|
+
index_of_item: index,
|
|
107
|
+
point: position,
|
|
108
|
+
remove_current_from_pull() {
|
|
109
|
+
thresholds
|
|
110
|
+
? hotel.insert_area(thresholds[index - 1] + 1 || 0, thresholds[index])
|
|
111
|
+
: hotel.bifurcate(index);
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
return lotteryContext;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export function pickInThresholds(thresholds, value) {
|
|
119
|
+
assert(thresholds.length > 0);
|
|
120
|
+
return binary_search(thresholds.length - 1, (index) => {
|
|
121
|
+
const hold = thresholds[index];
|
|
122
|
+
if (hold >= value && (thresholds[index - 1] ?? -1) < value) {
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
if (hold < value) {
|
|
126
|
+
return -1;
|
|
127
|
+
}
|
|
128
|
+
return 1;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
export function thresholdsOf(weights) {
|
|
132
|
+
assert(weights.length > 0, "Invalid array length");
|
|
133
|
+
let previousLimit = 0;
|
|
134
|
+
return weights.map((weight) => (previousLimit += weight));
|
|
135
|
+
}
|
|
136
|
+
export function randomElementIndexInWeights(weights) {
|
|
137
|
+
const thresholds = thresholdsOf(weights);
|
|
138
|
+
const lotteryPick = Math.random() * thresholds.at(-1);
|
|
139
|
+
return pickInThresholds(thresholds, lotteryPick);
|
|
140
|
+
}
|
|
141
|
+
// task: честный алгоритм , для которого каждый из элеметов списка имеет равный шанс на реализацию своей вероятности.
|
|
142
|
+
// Обычно весь список фильтруется и после выбирается элемент. В нашем случае фильтр будет срабатывать только для тех элементов,
|
|
143
|
+
// которые на этапе фильтрации «выбраны» — то есть имеют свою стопроцентную вероятность быть окончательными после успешного прохождения фильтра
|
|
144
|
+
// требования: честная вероятность; итоговая производительность должна быть выше обычной при проходе списка фильтром
|
|
145
|
+
// Алгоритм:
|
|
146
|
+
/*
|
|
147
|
+
Оптимальный алгоритм поиска случайного элемента списка, удовлетворяющего условию. Поддерживается возможность задавать элементам коэффициент вероятности
|
|
148
|
+
|
|
149
|
+
Перед выбором элемента выбираем случайный сегмент, далее случайный элемент в этом сегменте
|
|
150
|
+
|
|
151
|
+
Если соответствует условию, возвращаем элемент. Завершаем поиск
|
|
152
|
+
|
|
153
|
+
Иначе исключаем элемент путем раздвоения текущего сегмента так, чтобы элемент не оказался ни в одном сегменте списка
|
|
154
|
+
|
|
155
|
+
Повторяем
|
|
156
|
+
*/
|
|
157
|
+
export function randomElementFromArray(array, { associatedWeights, filter = () => true } = {}) {
|
|
158
|
+
assert(array.length, "Invalid array length");
|
|
159
|
+
if (associatedWeights === _WEIGHT_AUTO) {
|
|
160
|
+
// @ts-expect-error User know about AUTO keysymbol
|
|
161
|
+
associatedWeights = array.map(($) => $._weight);
|
|
162
|
+
}
|
|
163
|
+
associatedWeights?.length &&
|
|
164
|
+
assert(associatedWeights.at(-1) < Number.MAX_SAFE_INTEGER);
|
|
165
|
+
assert(!associatedWeights || associatedWeights.length === array.length, "Incorrectly passed argument associatedWeights: The length of the associatedWeights must exactly match the length of the weights array");
|
|
166
|
+
if (array.length === 1) {
|
|
167
|
+
return array[0];
|
|
168
|
+
}
|
|
169
|
+
// light strategy
|
|
170
|
+
if (!filter) {
|
|
171
|
+
if (associatedWeights) {
|
|
172
|
+
return array[randomElementIndexInWeights(associatedWeights)];
|
|
173
|
+
}
|
|
174
|
+
return array[Math.floor(Math.random() * array.length)];
|
|
175
|
+
}
|
|
176
|
+
return RandomizerContext.from({
|
|
177
|
+
array,
|
|
178
|
+
associatedWeights,
|
|
179
|
+
}).pickRandom(({ item }) => filter(item));
|
|
180
|
+
}
|
|
181
|
+
export function randomElementsFromArray(array, amount = 1, { associatedWeights, filter = () => true } = {}) {
|
|
182
|
+
assert(array.length);
|
|
183
|
+
assert(amount <= array.length);
|
|
184
|
+
assert(amount > 1, `Current amount: ${amount}, use randomElementFromArray instead of randomElement**s**FromArray if amount is 1`);
|
|
185
|
+
if (associatedWeights === _WEIGHT_AUTO) {
|
|
186
|
+
// @ts-expect-error User know about AUTO keysymbol
|
|
187
|
+
associatedWeights = array.map(($) => $._weight);
|
|
188
|
+
}
|
|
189
|
+
associatedWeights?.length &&
|
|
190
|
+
assert(associatedWeights.at(-1) < Number.MAX_SAFE_INTEGER);
|
|
191
|
+
assert(!associatedWeights || associatedWeights.length === array.length, "Incorrectly passed argument associatedWeights: The length of the associatedWeights must exactly match the length of the weights array");
|
|
192
|
+
if (amount === array.length) {
|
|
193
|
+
return Array.from(array);
|
|
194
|
+
}
|
|
195
|
+
// light strategy
|
|
196
|
+
if (!filter && !associatedWeights) {
|
|
197
|
+
const _array = Array.from(array);
|
|
198
|
+
return Array.from({ length: amount }, () => _array.splice(Math.floor(Math.random() * _array.length), 1)[0]);
|
|
199
|
+
}
|
|
200
|
+
const random_ctx = RandomizerContext.from({
|
|
201
|
+
array,
|
|
202
|
+
associatedWeights,
|
|
203
|
+
});
|
|
204
|
+
return Array.from({ length: amount }, (_, i) => {
|
|
205
|
+
while (true) {
|
|
206
|
+
const lottery_ctx = random_ctx.playLottery();
|
|
207
|
+
if (!lottery_ctx) {
|
|
208
|
+
// BEFORE PULL TO-DO вероятно неграммотное сообщение об ошибке
|
|
209
|
+
throw new Error("Not enought items was pass filter");
|
|
210
|
+
}
|
|
211
|
+
lottery_ctx.remove_current_from_pull();
|
|
212
|
+
const item = array[lottery_ctx.index_of_item];
|
|
213
|
+
if (!filter(item)) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
return item;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface IGetRandomValueOptions {
|
|
2
|
+
min?: number;
|
|
3
|
+
max: number;
|
|
4
|
+
needRound?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare function randomNumberInRange({ min, max, needRound, }: IGetRandomValueOptions): number;
|
|
7
|
+
export { randomNumberInRange };
|
|
8
|
+
//# sourceMappingURL=randomNumberInRange.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"randomNumberInRange.d.ts","sourceRoot":"","sources":["../../src/objectives/randomNumberInRange.ts"],"names":[],"mappings":"AAAA,UAAU,sBAAsB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,iBAAS,mBAAmB,CAAC,EAC5B,GAAO,EACP,GAAG,EACH,SAAgB,GAChB,EAAE,sBAAsB,UAOxB;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
package/lib/primitives/mod.d.ts
CHANGED
|
@@ -3,12 +3,9 @@ export * from "./BracketsParser.js";
|
|
|
3
3
|
export { CliParser } from "./CliParser.js";
|
|
4
4
|
export * from "./createDefaultPreventable.js";
|
|
5
5
|
export * from "./normalize.js";
|
|
6
|
+
export * from './pluralization/index.js';
|
|
6
7
|
export * from "./symbols.js";
|
|
7
8
|
export * from "./TextTableBuilder.js";
|
|
8
|
-
interface IEndingOptions {
|
|
9
|
-
unite?: (quantity: number, word: string) => string;
|
|
10
|
-
}
|
|
11
|
-
export declare function ending(quantity: number, base: string, multiple: string, alone: string, double: string, options?: IEndingOptions): string | number;
|
|
12
9
|
export declare function sortMutByResolve<T>(array: T[], resolve: ($: T) => number, { reverse }?: {
|
|
13
10
|
reverse?: boolean;
|
|
14
11
|
}): T[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/primitives/mod.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/primitives/mod.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AAGtC,wBAAgB,gBAAgB,CAAC,CAAC,EACjC,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,EACzB,EAAE,OAAO,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,OAKvC;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,OAG5C;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE,CAAC,WAO9D"}
|
package/lib/primitives/mod.js
CHANGED
|
@@ -3,19 +3,9 @@ export * from "./BracketsParser.js";
|
|
|
3
3
|
export { CliParser } from "./CliParser.js";
|
|
4
4
|
export * from "./createDefaultPreventable.js";
|
|
5
5
|
export * from "./normalize.js";
|
|
6
|
+
export * from './pluralization/index.js';
|
|
6
7
|
export * from "./symbols.js";
|
|
7
8
|
export * from "./TextTableBuilder.js";
|
|
8
|
-
export function ending(quantity, base, multiple, alone, double, options = {}) {
|
|
9
|
-
if (Number.isNaN(+quantity)) {
|
|
10
|
-
return Number.NaN;
|
|
11
|
-
}
|
|
12
|
-
const target = quantity % 100 < 20 ? quantity % 20 : quantity % 10;
|
|
13
|
-
const end = target >= 5 || target === 0 ? multiple : target > 1 ? double : alone;
|
|
14
|
-
const word = base + end;
|
|
15
|
-
options.unite ||= (quantity, word) => `${quantity} ${word}`;
|
|
16
|
-
const input = options.unite(quantity, word);
|
|
17
|
-
return input;
|
|
18
|
-
}
|
|
19
9
|
export function sortMutByResolve(array, resolve, { reverse } = {}) {
|
|
20
10
|
return reverse
|
|
21
11
|
? array.sort((a, b) => resolve(a) - resolve(b))
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface IEndingOptions {
|
|
2
|
+
unite?: (quantity: number, word: string) => string;
|
|
3
|
+
}
|
|
4
|
+
export declare function ending(quantity: number, base: string, multiple: string, alone: string, double: string, options?: IEndingOptions): string | number;
|
|
5
|
+
export declare enum GrammaticGender {
|
|
6
|
+
He = 0,
|
|
7
|
+
She = 1,
|
|
8
|
+
It = 2
|
|
9
|
+
}
|
|
10
|
+
export declare function pluralization_of_numeric(quantity: number, grammatic_gender: GrammaticGender, pattern: string[]): string | number;
|
|
11
|
+
export declare function pluralize_numeric_form(quantity: number, grammatic_gender: GrammaticGender): string;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/primitives/pluralization/index.ts"],"names":[],"mappings":"AACA,UAAU,cAAc;IACvB,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AACD,wBAAgB,MAAM,CACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,mBAqB5B;AAGD,oBAAY,eAAe;IAC1B,EAAE,IAAI;IACN,GAAG,IAAI;IACP,EAAE,IAAI;CACN;AACD,wBAAgB,wBAAwB,CACvC,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,eAAe,EACjC,OAAO,EAAE,MAAM,EAAE,mBASjB;AAED,wBAAgB,sBAAsB,CACrC,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,eAAe,GAC/B,MAAM,CA0FR"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export function ending(quantity, base, multiple, alone, double, options = {}) {
|
|
2
|
+
if (Number.isNaN(+quantity)) {
|
|
3
|
+
return Number.NaN;
|
|
4
|
+
}
|
|
5
|
+
// Закономерность чисел 10-20, 110-120...
|
|
6
|
+
const _clean_quantity = quantity % 100 < 20 ? quantity % 20 : quantity % 10;
|
|
7
|
+
const end = _clean_quantity >= 5 || _clean_quantity === 0
|
|
8
|
+
? multiple
|
|
9
|
+
: _clean_quantity > 1
|
|
10
|
+
? double
|
|
11
|
+
: alone;
|
|
12
|
+
const word = base + end;
|
|
13
|
+
options.unite ||= (quantity, word) => `${quantity} ${word}`;
|
|
14
|
+
const input = options.unite(quantity, word);
|
|
15
|
+
return input;
|
|
16
|
+
}
|
|
17
|
+
// MARK: Plularization
|
|
18
|
+
export var GrammaticGender;
|
|
19
|
+
(function (GrammaticGender) {
|
|
20
|
+
GrammaticGender[GrammaticGender["He"] = 0] = "He";
|
|
21
|
+
GrammaticGender[GrammaticGender["She"] = 1] = "She";
|
|
22
|
+
GrammaticGender[GrammaticGender["It"] = 2] = "It";
|
|
23
|
+
})(GrammaticGender || (GrammaticGender = {}));
|
|
24
|
+
export function pluralization_of_numeric(quantity, grammatic_gender, pattern) {
|
|
25
|
+
return ending(Math.abs(quantity), "", pattern[0], pattern[1], pattern[2], {
|
|
26
|
+
unite: (_, word) => word.replace("{}", pluralize_numeric_form(quantity, grammatic_gender)),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function pluralize_numeric_form(quantity, grammatic_gender) {
|
|
30
|
+
if (quantity === 0) {
|
|
31
|
+
return "ноль";
|
|
32
|
+
}
|
|
33
|
+
let _result = "";
|
|
34
|
+
if (quantity < 0) {
|
|
35
|
+
quantity = -quantity;
|
|
36
|
+
_result += "минус ";
|
|
37
|
+
}
|
|
38
|
+
if (quantity >= 1_000_000)
|
|
39
|
+
return String(quantity);
|
|
40
|
+
if (quantity >= 1_000) {
|
|
41
|
+
const x = Math.floor(quantity / 1_000);
|
|
42
|
+
_result += ending(x, "тысяч", "", "а", "и", {
|
|
43
|
+
unite: (_, word) => `${count_of_bit(x, GrammaticGender.She)} ${word} `,
|
|
44
|
+
});
|
|
45
|
+
quantity -= x * 1_000;
|
|
46
|
+
}
|
|
47
|
+
if (quantity >= 1) {
|
|
48
|
+
_result += `${count_of_bit(quantity, grammatic_gender)} `;
|
|
49
|
+
}
|
|
50
|
+
return _result.trimEnd();
|
|
51
|
+
function count_of_bit(value, grammatic_gender) {
|
|
52
|
+
let _result = "";
|
|
53
|
+
if (value >= 100) {
|
|
54
|
+
const x = Math.floor(value / 100);
|
|
55
|
+
_result += `${[
|
|
56
|
+
"сто",
|
|
57
|
+
"двести",
|
|
58
|
+
"триста",
|
|
59
|
+
"четыреста",
|
|
60
|
+
"пятьсот",
|
|
61
|
+
"шестьсот",
|
|
62
|
+
"семьсот",
|
|
63
|
+
"восемьсот",
|
|
64
|
+
"девятьсот",
|
|
65
|
+
][x - 1]} `;
|
|
66
|
+
value -= x * 100;
|
|
67
|
+
}
|
|
68
|
+
if (value >= 20) {
|
|
69
|
+
const x = Math.floor(value / 10);
|
|
70
|
+
_result += `${[
|
|
71
|
+
"двадцать",
|
|
72
|
+
"тридцать",
|
|
73
|
+
"сорок",
|
|
74
|
+
"пятьдесят",
|
|
75
|
+
"шестдесят",
|
|
76
|
+
"семдесят",
|
|
77
|
+
"восемьдесят",
|
|
78
|
+
"девяносто",
|
|
79
|
+
][x - 2]} `;
|
|
80
|
+
value -= x * 10;
|
|
81
|
+
}
|
|
82
|
+
if (value >= 1) {
|
|
83
|
+
_result += [
|
|
84
|
+
["один", "одна", "одно"][grammatic_gender],
|
|
85
|
+
["два", "две", "два"][grammatic_gender],
|
|
86
|
+
"три",
|
|
87
|
+
"четыре",
|
|
88
|
+
"пять",
|
|
89
|
+
"шесть",
|
|
90
|
+
"семь",
|
|
91
|
+
"восемь",
|
|
92
|
+
"девять",
|
|
93
|
+
"десять",
|
|
94
|
+
"одинадцать",
|
|
95
|
+
"двенадцать",
|
|
96
|
+
"тринадцать",
|
|
97
|
+
"четырнадцать",
|
|
98
|
+
"пятьнадцать",
|
|
99
|
+
"шестнадцать",
|
|
100
|
+
"семнадцать",
|
|
101
|
+
"восемнадцать",
|
|
102
|
+
"девятнадцать",
|
|
103
|
+
][value - 1];
|
|
104
|
+
}
|
|
105
|
+
return _result.trimEnd();
|
|
106
|
+
}
|
|
107
|
+
}
|