extra-rand 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +72 -4
  2. package/lib/index.d.ts +11 -7
  3. package/lib/index.js +11 -23
  4. package/lib/index.js.map +1 -1
  5. package/lib/map-to-index-by-weight.d.ts +2 -1
  6. package/lib/map-to-index-by-weight.js +4 -8
  7. package/lib/map-to-index-by-weight.js.map +1 -1
  8. package/lib/map-to-range.js +1 -5
  9. package/lib/map-to-range.js.map +1 -1
  10. package/lib/native-random-number-generator.d.ts +2 -0
  11. package/lib/native-random-number-generator.js +4 -0
  12. package/lib/native-random-number-generator.js.map +1 -0
  13. package/lib/random-bool.d.ts +2 -0
  14. package/lib/random-bool.js +13 -7
  15. package/lib/random-bool.js.map +1 -1
  16. package/lib/random-by-model.d.ts +17 -0
  17. package/lib/random-by-model.js +42 -0
  18. package/lib/random-by-model.js.map +1 -0
  19. package/lib/random-by-weight-model.d.ts +8 -0
  20. package/lib/random-by-weight-model.js +16 -0
  21. package/lib/random-by-weight-model.js.map +1 -0
  22. package/lib/random-index-by-weight.d.ts +4 -0
  23. package/lib/random-index-by-weight.js +15 -0
  24. package/lib/random-index-by-weight.js.map +1 -0
  25. package/lib/random-int-inclusive.d.ts +2 -0
  26. package/lib/random-int-inclusive.js +14 -7
  27. package/lib/random-int-inclusive.js.map +1 -1
  28. package/lib/random-int.d.ts +2 -0
  29. package/lib/random-int.js +14 -7
  30. package/lib/random-int.js.map +1 -1
  31. package/lib/random-weighted.d.ts +7 -0
  32. package/lib/random-weighted.js +17 -0
  33. package/lib/random-weighted.js.map +1 -0
  34. package/lib/random.d.ts +2 -0
  35. package/lib/random.js +14 -7
  36. package/lib/random.js.map +1 -1
  37. package/lib/types.d.ts +3 -0
  38. package/lib/types.js +2 -0
  39. package/lib/types.js.map +1 -0
  40. package/package.json +29 -23
  41. package/src/index.ts +12 -7
  42. package/src/map-to-index-by-weight.ts +3 -2
  43. package/src/native-random-number-generator.ts +5 -0
  44. package/src/random-bool.ts +23 -3
  45. package/src/random-by-model.ts +63 -0
  46. package/src/random-by-weight-model.ts +32 -0
  47. package/src/random-index-by-weight.ts +30 -0
  48. package/src/random-int-inclusive.ts +28 -3
  49. package/src/random-int.ts +25 -3
  50. package/src/random-weighted.ts +32 -0
  51. package/src/random.ts +25 -3
  52. package/src/types.ts +3 -0
  53. package/lib/random-by-weight.d.ts +0 -1
  54. package/lib/random-by-weight.js +0 -9
  55. package/lib/random-by-weight.js.map +0 -1
  56. package/src/random-by-weight.ts +0 -9
package/README.md CHANGED
@@ -9,9 +9,16 @@ yarn add extra-rand
9
9
  ```
10
10
 
11
11
  ## API
12
+ ```ts
13
+ interface IRandomNumberGenerator {
14
+ next(): number // [0, 1)
15
+ }
16
+ ```
17
+
12
18
  ### random
13
19
  ```ts
14
20
  function random(min: number, max: number): number
21
+ function random(generator: IRandomNumberGenerator, min: number, max: number): number
15
22
  ```
16
23
 
17
24
  The function returns a number in the range `[min, max)`.
@@ -19,6 +26,7 @@ The function returns a number in the range `[min, max)`.
19
26
  ### randomInt
20
27
  ```ts
21
28
  function randomInt(min: number, max: number): number
29
+ function randomInt(generator: IRandomNumberGenerator, min: number, max: number): number
22
30
  ```
23
31
 
24
32
  The function returns an integer in the range `[Math.ceil(min), Math.floor(max))`.
@@ -26,6 +34,11 @@ The function returns an integer in the range `[Math.ceil(min), Math.floor(max))`
26
34
  ### randomIntInclusive
27
35
  ```ts
28
36
  function randomIntInclusive(min: number, max: number): number
37
+ function randomIntInclusive(
38
+ generator: IRandomNumberGenerator
39
+ , min: number
40
+ , max: number
41
+ ): number
29
42
  ```
30
43
 
31
44
  The function returns an integer in the range `[Math.ceil(min), Math.floor(max)]`.
@@ -33,15 +46,70 @@ The function returns an integer in the range `[Math.ceil(min), Math.floor(max)]`
33
46
  ### randomBool
34
47
  ```ts
35
48
  function randomBool(probabilityOfTrue: number): boolean
49
+ function randomBool(generator: IRandomNumberGenerator, probabilityOfTrue: number): boolean
36
50
  ```
37
51
 
38
- ### randomByWeight
52
+ ### randomIndexByWeight
39
53
  ```ts
40
- function randomByWeight(weights: number[]): number
54
+ function randomIndexByWeight(weights: NonEmptyArray<number>): number
55
+ function randomIndexByWeight(
56
+ generator: IRandomNumberGenerator
57
+ , weights: NonEmptyArray<number>
58
+ ): number
41
59
  ```
42
60
 
43
61
  The function returns an index of one of weights.
44
62
 
63
+ ### randomWeighted
64
+ ```ts
65
+ interface IWeighted {
66
+ weight: number
67
+ }
68
+
69
+ function randomWeighted<T extends IWeighted>(values: NonEmptyArray<T>): T
70
+ function randomWeighted<T extends IWeighted>(
71
+ generator: IRandomNumberGenerator
72
+ , values: NonEmptyArray<T>
73
+ ): T
74
+ ```
75
+
76
+ ### randomByWeightModel
77
+ ```ts
78
+ type IWeightModel<T> = NonEmptyArray<{
79
+ weight: number
80
+ value: T
81
+ }>
82
+
83
+ function randomByWeightModel<T>(model: IWeightModel<T>): T
84
+ function randomByWeightModel<T>(generator: IRandomNumberGenerator, model: IWeightModel<T>): T
85
+ ```
86
+
87
+ ### randomByModel
88
+ ```ts
89
+ enum Type {
90
+ Float
91
+ , Integer
92
+ , IntegerInclusive
93
+ }
94
+
95
+ type IRandomModel =
96
+ | number
97
+ | Getter<number>
98
+ | {
99
+ type: Type
100
+ min: number
101
+ max: number
102
+ }
103
+ | NonEmptyArray<{
104
+ weight: number
105
+ value: IRandomModel
106
+ }>
107
+
108
+
109
+ function randomByModel(model: IRandomModel): number
110
+ function randomByModel(generator: IRandomNumberGenerator, model: IRandomModel): number
111
+ ```
112
+
45
113
  ### mapToRange
46
114
  ```ts
47
115
  function mapToRange(
@@ -55,10 +123,10 @@ A low-level function helps you to use random number generators other than `Math.
55
123
 
56
124
  ### mapToIndexByWeight
57
125
  ```ts
58
- function mapByWeight(
126
+ function mapToIndexByWeight(
59
127
  value: number
60
128
  , oldMin: number, oldMax: number
61
- , weights: number[]
129
+ , weights: NonEmptyArray<number>
62
130
  ): number
63
131
  ```
64
132
 
package/lib/index.d.ts CHANGED
@@ -1,7 +1,11 @@
1
- export * from './random';
2
- export * from './random-int';
3
- export * from './random-int-inclusive';
4
- export * from './random-bool';
5
- export * from './random-by-weight';
6
- export * from './map-to-range';
7
- export * from './map-to-index-by-weight';
1
+ export * from './types.js';
2
+ export * from './random.js';
3
+ export * from './random-int.js';
4
+ export * from './random-int-inclusive.js';
5
+ export * from './random-bool.js';
6
+ export * from './random-index-by-weight.js';
7
+ export * from './random-weighted.js';
8
+ export * from './random-by-weight-model.js';
9
+ export * from './random-by-model.js';
10
+ export * from './map-to-range.js';
11
+ export * from './map-to-index-by-weight.js';
package/lib/index.js CHANGED
@@ -1,24 +1,12 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./random"), exports);
18
- __exportStar(require("./random-int"), exports);
19
- __exportStar(require("./random-int-inclusive"), exports);
20
- __exportStar(require("./random-bool"), exports);
21
- __exportStar(require("./random-by-weight"), exports);
22
- __exportStar(require("./map-to-range"), exports);
23
- __exportStar(require("./map-to-index-by-weight"), exports);
1
+ export * from './types.js';
2
+ export * from './random.js';
3
+ export * from './random-int.js';
4
+ export * from './random-int-inclusive.js';
5
+ export * from './random-bool.js';
6
+ export * from './random-index-by-weight.js';
7
+ export * from './random-weighted.js';
8
+ export * from './random-by-weight-model.js';
9
+ export * from './random-by-model.js';
10
+ export * from './map-to-range.js';
11
+ export * from './map-to-index-by-weight.js';
24
12
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,+CAA4B;AAC5B,yDAAsC;AACtC,gDAA6B;AAC7B,qDAAkC;AAElC,iDAA8B;AAC9B,2DAAwC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AAEpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA"}
@@ -1 +1,2 @@
1
- export declare function mapToIndexByWeight(value: number, oldMin: number, oldMax: number, weights: number[]): number;
1
+ import { NonEmptyArray } from 'justypes';
2
+ export declare function mapToIndexByWeight(value: number, oldMin: number, oldMax: number, weights: NonEmptyArray<number>): number;
@@ -1,18 +1,15 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapToIndexByWeight = void 0;
4
- const map_to_range_1 = require("./map-to-range");
5
- function mapToIndexByWeight(value, oldMin, oldMax, weights) {
1
+ import { mapToRange } from './map-to-range.js';
2
+ export function mapToIndexByWeight(value, oldMin, oldMax, weights) {
6
3
  const newMin = 0;
7
4
  const newMax = weights.reduce((acc, cur) => acc + Math.max(cur, 0));
8
5
  if (newMax === 0) {
9
- const index = Math.floor((0, map_to_range_1.mapToRange)(value, oldMin, oldMax, newMin, weights.length));
6
+ const index = Math.floor(mapToRange(value, oldMin, oldMax, newMin, weights.length));
10
7
  return index === weights.length
11
8
  ? weights.length - 1
12
9
  : index;
13
10
  }
14
11
  else {
15
- const newValue = (0, map_to_range_1.mapToRange)(value, oldMin, oldMax, newMin, newMax);
12
+ const newValue = mapToRange(value, oldMin, oldMax, newMin, newMax);
16
13
  let remains = newMax;
17
14
  for (let i = weights.length; i--;) {
18
15
  const weight = weights[i];
@@ -29,5 +26,4 @@ function mapToIndexByWeight(value, oldMin, oldMax, weights) {
29
26
  throw new Error('Impossible route');
30
27
  }
31
28
  }
32
- exports.mapToIndexByWeight = mapToIndexByWeight;
33
29
  //# sourceMappingURL=map-to-index-by-weight.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-to-index-by-weight.js","sourceRoot":"","sources":["../src/map-to-index-by-weight.ts"],"names":[],"mappings":";;;AAAA,iDAA2C;AAE3C,SAAgB,kBAAkB,CAChC,KAAa,EACb,MAAc,EAAE,MAAc,EAC9B,OAAiB;IAEjB,MAAM,MAAM,GAAG,CAAC,CAAA;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IACnE,IAAI,MAAM,KAAK,CAAC,EAAE;QAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,yBAAU,EAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;QAEnF,OAAO,KAAK,KAAK,OAAO,CAAC,MAAM;YAC1B,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,KAAK,CAAA;KACb;SAAM;QACL,MAAM,QAAQ,GAAG,IAAA,yBAAU,EAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAElE,IAAI,OAAO,GAAG,MAAM,CAAA;QACpB,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG;YACjC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YACzB,IAAI,MAAM,IAAI,CAAC,EAAE;gBACf,SAAQ;aACT;iBAAM;gBACL,OAAO,IAAI,MAAM,CAAA;gBACjB,IAAI,QAAQ,IAAI,OAAO,EAAE;oBACvB,OAAO,CAAC,CAAA;iBACT;aACF;SACF;QAED,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;KACpC;AACH,CAAC;AAhCD,gDAgCC"}
1
+ {"version":3,"file":"map-to-index-by-weight.js","sourceRoot":"","sources":["../src/map-to-index-by-weight.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,MAAc,EAAE,MAAc,EAC9B,OAA8B;IAE9B,MAAM,MAAM,GAAG,CAAC,CAAA;IAChB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IACnE,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;QAEnF,OAAO,KAAK,KAAK,OAAO,CAAC,MAAM;YAC1B,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACpB,CAAC,CAAC,KAAK,CAAA;IACd,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;QAElE,IAAI,OAAO,GAAG,MAAM,CAAA;QACpB,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC;YAClC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YACzB,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;gBAChB,SAAQ;YACV,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,MAAM,CAAA;gBACjB,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACxB,OAAO,CAAC,CAAA;gBACV,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;AACH,CAAC"}
@@ -1,10 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapToRange = void 0;
4
- function mapToRange(value, oldMin, oldMax, newMin, newMax) {
1
+ export function mapToRange(value, oldMin, oldMax, newMin, newMax) {
5
2
  return (value - oldMin) / (oldMax - oldMin)
6
3
  * (newMax - newMin)
7
4
  + newMin;
8
5
  }
9
- exports.mapToRange = mapToRange;
10
6
  //# sourceMappingURL=map-to-range.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-to-range.js","sourceRoot":"","sources":["../src/map-to-range.ts"],"names":[],"mappings":";;;AAAA,SAAgB,UAAU,CACxB,KAAa,EACb,MAAc,EAAE,MAAc,EAC9B,MAAc,EAAE,MAAc;IAE9B,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;UACpC,CAAC,MAAM,GAAG,MAAM,CAAC;UACjB,MAAM,CAAA;AACf,CAAC;AARD,gCAQC"}
1
+ {"version":3,"file":"map-to-range.js","sourceRoot":"","sources":["../src/map-to-range.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CACxB,KAAa,EACb,MAAc,EAAE,MAAc,EAC9B,MAAc,EAAE,MAAc;IAE9B,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;UACpC,CAAC,MAAM,GAAG,MAAM,CAAC;UACjB,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { IRandomNumberGenerator } from './types.js';
2
+ export declare const NativeRandomNumberGenerator: IRandomNumberGenerator;
@@ -0,0 +1,4 @@
1
+ export const NativeRandomNumberGenerator = {
2
+ next: Math.random
3
+ };
4
+ //# sourceMappingURL=native-random-number-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-random-number-generator.js","sourceRoot":"","sources":["../src/native-random-number-generator.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,2BAA2B,GAA2B;IACjE,IAAI,EAAE,IAAI,CAAC,MAAM;CAClB,CAAA"}
@@ -1 +1,3 @@
1
+ import { IRandomNumberGenerator } from './types.js';
1
2
  export declare function randomBool(probabilityOfTrue: number): boolean;
3
+ export declare function randomBool(generator: IRandomNumberGenerator, probabilityOfTrue: number): boolean;
@@ -1,9 +1,15 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.randomBool = void 0;
4
- const random_1 = require("./random");
5
- function randomBool(probabilityOfTrue) {
6
- return (0, random_1.random)(0, 1) < probabilityOfTrue;
1
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
2
+ import { random } from './random.js';
3
+ export function randomBool(...args) {
4
+ let generator;
5
+ let probabilityOfTrue;
6
+ if (args.length === 1) {
7
+ generator = NativeRandomNumberGenerator;
8
+ [probabilityOfTrue] = args;
9
+ }
10
+ else {
11
+ [generator, probabilityOfTrue] = args;
12
+ }
13
+ return random(generator, 0, 1) < probabilityOfTrue;
7
14
  }
8
- exports.randomBool = randomBool;
9
15
  //# sourceMappingURL=random-bool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"random-bool.js","sourceRoot":"","sources":["../src/random-bool.ts"],"names":[],"mappings":";;;AAAA,qCAAiC;AAEjC,SAAgB,UAAU,CAAC,iBAAyB;IAClD,OAAO,IAAA,eAAM,EAAC,CAAC,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAA;AACzC,CAAC;AAFD,gCAEC"}
1
+ {"version":3,"file":"random-bool.js","sourceRoot":"","sources":["../src/random-bool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOpC,MAAM,UAAU,UAAU,CAAC,GAAG,IAEkC;IAE9D,IAAI,SAAiC,CAAA;IACrC,IAAI,iBAAyB,CAAA;IAE7B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IAC7B,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,CAAC;IAED,OAAO,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAA;AACpD,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { Getter, NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
3
+ export declare enum Type {
4
+ Float = 0,
5
+ Integer = 1,
6
+ IntegerInclusive = 2
7
+ }
8
+ export type IRandomModel = number | Getter<number> | {
9
+ type: Type;
10
+ min: number;
11
+ max: number;
12
+ } | NonEmptyArray<{
13
+ weight: number;
14
+ value: IRandomModel;
15
+ }>;
16
+ export declare function randomByModel(model: IRandomModel): number;
17
+ export declare function randomByModel(generator: IRandomNumberGenerator, model: IRandomModel): number;
@@ -0,0 +1,42 @@
1
+ import { isArray, isFunction, isNumber } from 'extra-utils';
2
+ import { randomByWeightModel } from './random-by-weight-model.js';
3
+ import { random } from './random.js';
4
+ import { randomInt } from './random-int.js';
5
+ import { randomIntInclusive } from './random-int-inclusive.js';
6
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
7
+ export var Type;
8
+ (function (Type) {
9
+ Type[Type["Float"] = 0] = "Float";
10
+ Type[Type["Integer"] = 1] = "Integer";
11
+ Type[Type["IntegerInclusive"] = 2] = "IntegerInclusive";
12
+ })(Type || (Type = {}));
13
+ export function randomByModel(...args) {
14
+ let generator;
15
+ let model;
16
+ if (args.length === 1) {
17
+ generator = NativeRandomNumberGenerator;
18
+ [model] = args;
19
+ }
20
+ else {
21
+ [generator, model] = args;
22
+ }
23
+ if (isNumber(model)) {
24
+ return model;
25
+ }
26
+ else if (isFunction(model)) {
27
+ return model();
28
+ }
29
+ else if (isArray(model)) {
30
+ const subModel = randomByWeightModel(generator, model);
31
+ return randomByModel(generator, subModel);
32
+ }
33
+ else {
34
+ const { type, min, max } = model;
35
+ switch (type) {
36
+ case Type.Float: return random(generator, min, max);
37
+ case Type.Integer: return randomInt(generator, min, max);
38
+ case Type.IntegerInclusive: return randomIntInclusive(generator, min, max);
39
+ }
40
+ }
41
+ }
42
+ //# sourceMappingURL=random-by-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random-by-model.js","sourceRoot":"","sources":["../src/random-by-model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAE9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAEjF,MAAM,CAAN,IAAY,IAIX;AAJD,WAAY,IAAI;IACd,iCAAK,CAAA;IACL,qCAAO,CAAA;IACP,uDAAgB,CAAA;AAClB,CAAC,EAJW,IAAI,KAAJ,IAAI,QAIf;AAoBD,MAAM,UAAU,aAAa,CAAC,GAAG,IAEyB;IAExD,IAAI,SAAiC,CAAA;IACrC,IAAI,KAAmB,CAAA;IAEvB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IACjB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3B,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAA;IACd,CAAC;SAAM,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,EAAE,CAAA;IAChB,CAAC;SAAM,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACtD,OAAO,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC3C,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;QAChC,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YACnD,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YACxD,KAAK,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,kBAAkB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;QAC5E,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
3
+ export type IWeightModel<T> = NonEmptyArray<{
4
+ weight: number;
5
+ value: T;
6
+ }>;
7
+ export declare function randomByWeightModel<T>(model: IWeightModel<T>): T;
8
+ export declare function randomByWeightModel<T>(generator: IRandomNumberGenerator, model: IWeightModel<T>): T;
@@ -0,0 +1,16 @@
1
+ import { randomWeighted } from './random-weighted.js';
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
3
+ export function randomByWeightModel(...args) {
4
+ let generator;
5
+ let model;
6
+ if (args.length === 1) {
7
+ generator = NativeRandomNumberGenerator;
8
+ [model] = args;
9
+ }
10
+ else {
11
+ [generator, model] = args;
12
+ }
13
+ const { value } = randomWeighted(generator, model);
14
+ return value;
15
+ }
16
+ //# sourceMappingURL=random-by-weight-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random-by-weight-model.js","sourceRoot":"","sources":["../src/random-by-weight-model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAYjF,MAAM,UAAU,mBAAmB,CAAI,GAAG,IAEmB;IAE3D,IAAI,SAAiC,CAAA;IACrC,IAAI,KAAsB,CAAA;IAE1B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IACjB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3B,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;IAClD,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
3
+ export declare function randomIndexByWeight(weights: NonEmptyArray<number>): number;
4
+ export declare function randomIndexByWeight(generator: IRandomNumberGenerator, weights: NonEmptyArray<number>): number;
@@ -0,0 +1,15 @@
1
+ import { mapToIndexByWeight } from './map-to-index-by-weight.js';
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
3
+ export function randomIndexByWeight(...args) {
4
+ let generator;
5
+ let weights;
6
+ if (args.length === 1) {
7
+ generator = NativeRandomNumberGenerator;
8
+ [weights] = args;
9
+ }
10
+ else {
11
+ [generator, weights] = args;
12
+ }
13
+ return mapToIndexByWeight(generator.next(), 0, 1, weights);
14
+ }
15
+ //# sourceMappingURL=random-index-by-weight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random-index-by-weight.js","sourceRoot":"","sources":["../src/random-index-by-weight.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAEhE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAOjF,MAAM,UAAU,mBAAmB,CAAC,GAAG,IAE8B;IAEnE,IAAI,SAAiC,CAAA;IACrC,IAAI,OAA8B,CAAA;IAElC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IACnB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC7B,CAAC;IAED,OAAO,kBAAkB,CACvB,SAAS,CAAC,IAAI,EAAE,EAChB,CAAC,EAAE,CAAC,EACJ,OAAO,CACR,CAAA;AACH,CAAC"}
@@ -1 +1,3 @@
1
+ import { IRandomNumberGenerator } from './types.js';
1
2
  export declare function randomIntInclusive(min: number, max: number): number;
3
+ export declare function randomIntInclusive(generator: IRandomNumberGenerator, min: number, max: number): number;
@@ -1,9 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.randomIntInclusive = void 0;
4
- const map_to_range_1 = require("./map-to-range");
5
- function randomIntInclusive(min, max) {
6
- return Math.floor((0, map_to_range_1.mapToRange)(Math.random(), 0, 1, Math.ceil(min), Math.floor(max) + 1));
1
+ import { mapToRange } from './map-to-range.js';
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
3
+ export function randomIntInclusive(...args) {
4
+ let generator;
5
+ let min;
6
+ let max;
7
+ if (args.length === 2) {
8
+ generator = NativeRandomNumberGenerator;
9
+ [min, max] = args;
10
+ }
11
+ else {
12
+ [generator, min, max] = args;
13
+ }
14
+ return Math.floor(mapToRange(generator.next(), 0, 1, Math.ceil(min), Math.floor(max) + 1));
7
15
  }
8
- exports.randomIntInclusive = randomIntInclusive;
9
16
  //# sourceMappingURL=random-int-inclusive.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"random-int-inclusive.js","sourceRoot":"","sources":["../src/random-int-inclusive.ts"],"names":[],"mappings":";;;AAAA,iDAA2C;AAE3C,SAAgB,kBAAkB,CAAC,GAAW,EAAE,GAAW;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,yBAAU,EAC1B,IAAI,CAAC,MAAM,EAAE,EACb,CAAC,EAAE,CAAC,EACJ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CACpC,CAAC,CAAA;AACJ,CAAC;AAND,gDAMC"}
1
+ {"version":3,"file":"random-int-inclusive.js","sourceRoot":"","sources":["../src/random-int-inclusive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAWjF,MAAM,UAAU,kBAAkB,CAAC,GAAG,IAEyB;IAE7D,IAAI,SAAiC,CAAA;IACrC,IAAI,GAAW,CAAA;IACf,IAAI,GAAW,CAAA;IAEf,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IAC9B,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAC1B,SAAS,CAAC,IAAI,EAAE,EAChB,CAAC,EAAE,CAAC,EACJ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CACpC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1,3 @@
1
+ import { IRandomNumberGenerator } from './types.js';
1
2
  export declare function randomInt(min: number, max: number): number;
3
+ export declare function randomInt(generator: IRandomNumberGenerator, min: number, max: number): number;
package/lib/random-int.js CHANGED
@@ -1,9 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.randomInt = void 0;
4
- const map_to_range_1 = require("./map-to-range");
5
- function randomInt(min, max) {
6
- return Math.floor((0, map_to_range_1.mapToRange)(Math.random(), 0, 1, Math.ceil(min), Math.floor(max)));
1
+ import { mapToRange } from './map-to-range.js';
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
3
+ export function randomInt(...args) {
4
+ let generator;
5
+ let min;
6
+ let max;
7
+ if (args.length === 2) {
8
+ generator = NativeRandomNumberGenerator;
9
+ [min, max] = args;
10
+ }
11
+ else {
12
+ [generator, min, max] = args;
13
+ }
14
+ return Math.floor(mapToRange(generator.next(), 0, 1, Math.ceil(min), Math.floor(max)));
7
15
  }
8
- exports.randomInt = randomInt;
9
16
  //# sourceMappingURL=random-int.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"random-int.js","sourceRoot":"","sources":["../src/random-int.ts"],"names":[],"mappings":";;;AAAA,iDAA2C;AAE3C,SAAgB,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,yBAAU,EAC1B,IAAI,CAAC,MAAM,EAAE,EACb,CAAC,EAAE,CAAC,EACJ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAChC,CAAC,CAAA;AACJ,CAAC;AAND,8BAMC"}
1
+ {"version":3,"file":"random-int.js","sourceRoot":"","sources":["../src/random-int.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAQjF,MAAM,UAAU,SAAS,CAAC,GAAG,IAEkC;IAE7D,IAAI,SAAiC,CAAA;IACrC,IAAI,GAAW,CAAA;IACf,IAAI,GAAW,CAAA;IAEf,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IAC9B,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAC1B,SAAS,CAAC,IAAI,EAAE,EAChB,CAAC,EAAE,CAAC,EACJ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAChC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
3
+ export interface IWeighted {
4
+ weight: number;
5
+ }
6
+ export declare function randomWeighted<T extends IWeighted>(values: NonEmptyArray<T>): T;
7
+ export declare function randomWeighted<T extends IWeighted>(generator: IRandomNumberGenerator, values: NonEmptyArray<T>): T;
@@ -0,0 +1,17 @@
1
+ import { randomIndexByWeight } from './random-index-by-weight.js';
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
3
+ export function randomWeighted(...args) {
4
+ let generator;
5
+ let values;
6
+ if (args.length === 1) {
7
+ generator = NativeRandomNumberGenerator;
8
+ [values] = args;
9
+ }
10
+ else {
11
+ [generator, values] = args;
12
+ }
13
+ const weights = values.map(option => option.weight);
14
+ const index = randomIndexByWeight(generator, weights);
15
+ return values[index];
16
+ }
17
+ //# sourceMappingURL=random-weighted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random-weighted.js","sourceRoot":"","sources":["../src/random-weighted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAGjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAWjF,MAAM,UAAU,cAAc,CAAsB,GAAG,IAEQ;IAE7D,IAAI,SAAiC,CAAA;IACrC,IAAI,MAAwB,CAAA;IAE5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAClB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5B,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAA0B,CAAA;IAC5E,MAAM,KAAK,GAAG,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACrD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC"}
package/lib/random.d.ts CHANGED
@@ -1 +1,3 @@
1
+ import { IRandomNumberGenerator } from './types.js';
1
2
  export declare function random(min: number, max: number): number;
3
+ export declare function random(generator: IRandomNumberGenerator, min: number, max: number): number;
package/lib/random.js CHANGED
@@ -1,9 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.random = void 0;
4
- const map_to_range_1 = require("./map-to-range");
5
- function random(min, max) {
6
- return (0, map_to_range_1.mapToRange)(Math.random(), 0, 1, min, max);
1
+ import { mapToRange } from './map-to-range.js';
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
3
+ export function random(...args) {
4
+ let generator;
5
+ let min;
6
+ let max;
7
+ if (args.length === 2) {
8
+ generator = NativeRandomNumberGenerator;
9
+ [min, max] = args;
10
+ }
11
+ else {
12
+ [generator, min, max] = args;
13
+ }
14
+ return mapToRange(generator.next(), 0, 1, min, max);
7
15
  }
8
- exports.random = random;
9
16
  //# sourceMappingURL=random.js.map
package/lib/random.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"random.js","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":";;;AAAA,iDAA2C;AAE3C,SAAgB,MAAM,CAAC,GAAW,EAAE,GAAW;IAC7C,OAAO,IAAA,yBAAU,EACf,IAAI,CAAC,MAAM,EAAE,EACb,CAAC,EAAE,CAAC,EACJ,GAAG,EAAE,GAAG,CACT,CAAA;AACH,CAAC;AAND,wBAMC"}
1
+ {"version":3,"file":"random.js","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AAQjF,MAAM,UAAU,MAAM,CAAC,GAAG,IAEqC;IAE7D,IAAI,SAAiC,CAAA;IACrC,IAAI,GAAW,CAAA;IACf,IAAI,GAAW,CAAA;IAEf,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IACpB,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IAC9B,CAAC;IAED,OAAO,UAAU,CACf,SAAS,CAAC,IAAI,EAAE,EAChB,CAAC,EAAE,CAAC,EACJ,GAAG,EAAE,GAAG,CACT,CAAA;AACH,CAAC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export interface IRandomNumberGenerator {
2
+ next(): number;
3
+ }
package/lib/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "extra-rand",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Yet another random library",
5
5
  "keywords": [
6
6
  "random"
@@ -12,43 +12,49 @@
12
12
  "main": "lib/index.js",
13
13
  "types": "lib/index.d.ts",
14
14
  "sideEffects": false,
15
+ "type": "module",
16
+ "engines": {
17
+ "node": ">=18.17.0"
18
+ },
15
19
  "repository": "git@github.com:BlackGlory/extra-rand.git",
16
20
  "author": "BlackGlory <woshenmedoubuzhidao@blackglory.me>",
17
21
  "license": "MIT",
18
22
  "scripts": {
19
- "lint": "eslint --ext .js,.jsx,.ts,.tsx --quiet src __tests__",
20
- "test": "jest --config jest.config.js",
21
- "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
22
- "test:coverage": "jest --coverage --config jest.config.js",
23
- "prepublishOnly": "run-s clean build",
23
+ "prepare": "ts-patch install -s",
24
+ "lint": "eslint --quiet src __tests__",
25
+ "test": "vitest --run",
26
+ "prepublishOnly": "run-s prepare clean build",
24
27
  "clean": "rimraf lib",
25
- "build": "run-s build:*",
26
- "build:compile": "tsc --project tsconfig.build.json --module commonjs --target es2018 --outDir lib",
27
- "build:patch": "tscpaths -p tsconfig.build.json -s ./src -o ./lib",
28
+ "build": "tsc --project tsconfig.build.json --outDir lib",
28
29
  "release": "standard-version"
29
30
  },
30
31
  "husky": {
31
32
  "hooks": {
32
- "pre-commit": "run-s lint build test",
33
+ "pre-commit": "run-s prepare lint build test",
33
34
  "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
34
35
  }
35
36
  },
36
37
  "devDependencies": {
37
- "@commitlint/cli": "^17.5.1",
38
- "@commitlint/config-conventional": "^17.4.4",
39
- "@types/jest": "^29.5.0",
40
- "@typescript-eslint/eslint-plugin": "^5.57.0",
41
- "@typescript-eslint/parser": "^5.57.0",
42
- "eslint": "^8.37.0",
38
+ "@commitlint/cli": "^19.2.2",
39
+ "@commitlint/config-conventional": "^19.2.2",
40
+ "@eslint/js": "^9.0.0",
41
+ "eslint": "^9.0.0",
43
42
  "husky": "^4.3.8",
44
- "jest": "^29.5.0",
45
43
  "npm-run-all": "^4.1.5",
46
- "rimraf": "^3.0.2",
44
+ "rimraf": "^5.0.5",
47
45
  "standard-version": "^9.5.0",
48
- "ts-jest": "^29.0.5",
49
- "tscpaths": "^0.0.9",
50
- "tslib": "^2.5.0",
51
- "typescript": "^4.7.4"
46
+ "ts-patch": "^3.1.2",
47
+ "tslib": "^2.6.2",
48
+ "typescript": "^5.4.5",
49
+ "typescript-eslint": "^7.7.0",
50
+ "typescript-transform-paths": "^3.4.7",
51
+ "vite": "^5.2.9",
52
+ "vite-tsconfig-paths": "^4.3.2",
53
+ "vitest": "^1.5.0"
52
54
  },
53
- "dependencies": {}
55
+ "dependencies": {
56
+ "@blackglory/errors": "^3.0.3",
57
+ "extra-utils": "^5.7.0",
58
+ "justypes": "^4.2.1"
59
+ }
54
60
  }
package/src/index.ts CHANGED
@@ -1,8 +1,13 @@
1
- export * from './random'
2
- export * from './random-int'
3
- export * from './random-int-inclusive'
4
- export * from './random-bool'
5
- export * from './random-by-weight'
1
+ export * from './types.js'
6
2
 
7
- export * from './map-to-range'
8
- export * from './map-to-index-by-weight'
3
+ export * from './random.js'
4
+ export * from './random-int.js'
5
+ export * from './random-int-inclusive.js'
6
+ export * from './random-bool.js'
7
+ export * from './random-index-by-weight.js'
8
+ export * from './random-weighted.js'
9
+ export * from './random-by-weight-model.js'
10
+ export * from './random-by-model.js'
11
+
12
+ export * from './map-to-range.js'
13
+ export * from './map-to-index-by-weight.js'
@@ -1,9 +1,10 @@
1
- import { mapToRange } from './map-to-range'
1
+ import { NonEmptyArray } from 'justypes'
2
+ import { mapToRange } from './map-to-range.js'
2
3
 
3
4
  export function mapToIndexByWeight(
4
5
  value: number
5
6
  , oldMin: number, oldMax: number
6
- , weights: number[]
7
+ , weights: NonEmptyArray<number>
7
8
  ): number {
8
9
  const newMin = 0
9
10
  const newMax = weights.reduce((acc, cur) => acc + Math.max(cur, 0))
@@ -0,0 +1,5 @@
1
+ import { IRandomNumberGenerator } from './types.js'
2
+
3
+ export const NativeRandomNumberGenerator: IRandomNumberGenerator = {
4
+ next: Math.random
5
+ }
@@ -1,5 +1,25 @@
1
- import { random } from './random'
1
+ import { IRandomNumberGenerator } from './types.js'
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
3
+ import { random } from './random.js'
2
4
 
3
- export function randomBool(probabilityOfTrue: number): boolean {
4
- return random(0, 1) < probabilityOfTrue
5
+ export function randomBool(probabilityOfTrue: number): boolean
6
+ export function randomBool(
7
+ generator: IRandomNumberGenerator
8
+ , probabilityOfTrue: number
9
+ ): boolean
10
+ export function randomBool(...args:
11
+ | [probabilityOfTrue: number]
12
+ | [generator: IRandomNumberGenerator, probabilityOfTrue: number]
13
+ ): boolean {
14
+ let generator: IRandomNumberGenerator
15
+ let probabilityOfTrue: number
16
+
17
+ if (args.length === 1) {
18
+ generator = NativeRandomNumberGenerator
19
+ ;[probabilityOfTrue] = args
20
+ } else {
21
+ [generator, probabilityOfTrue] = args
22
+ }
23
+
24
+ return random(generator, 0, 1) < probabilityOfTrue
5
25
  }
@@ -0,0 +1,63 @@
1
+ import { Getter, NonEmptyArray } from 'justypes'
2
+ import { isArray, isFunction, isNumber } from 'extra-utils'
3
+ import { randomByWeightModel } from './random-by-weight-model.js'
4
+ import { random } from './random.js'
5
+ import { randomInt } from './random-int.js'
6
+ import { randomIntInclusive } from './random-int-inclusive.js'
7
+ import { IRandomNumberGenerator } from './types.js'
8
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
9
+
10
+ export enum Type {
11
+ Float
12
+ , Integer
13
+ , IntegerInclusive
14
+ }
15
+
16
+ export type IRandomModel =
17
+ | number
18
+ | Getter<number>
19
+ | {
20
+ type: Type
21
+ min: number
22
+ max: number
23
+ }
24
+ | NonEmptyArray<{
25
+ weight: number
26
+ value: IRandomModel
27
+ }>
28
+
29
+ export function randomByModel(model: IRandomModel): number
30
+ export function randomByModel(
31
+ generator: IRandomNumberGenerator
32
+ , model: IRandomModel
33
+ ): number
34
+ export function randomByModel(...args:
35
+ | [model: IRandomModel]
36
+ | [generator: IRandomNumberGenerator, model: IRandomModel]
37
+ ): number {
38
+ let generator: IRandomNumberGenerator
39
+ let model: IRandomModel
40
+
41
+ if (args.length === 1) {
42
+ generator = NativeRandomNumberGenerator
43
+ ;[model] = args
44
+ } else {
45
+ [generator, model] = args
46
+ }
47
+
48
+ if (isNumber(model)) {
49
+ return model
50
+ } else if (isFunction(model)) {
51
+ return model()
52
+ } else if (isArray(model)) {
53
+ const subModel = randomByWeightModel(generator, model)
54
+ return randomByModel(generator, subModel)
55
+ } else {
56
+ const { type, min, max } = model
57
+ switch (type) {
58
+ case Type.Float: return random(generator, min, max)
59
+ case Type.Integer: return randomInt(generator, min, max)
60
+ case Type.IntegerInclusive: return randomIntInclusive(generator, min, max)
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,32 @@
1
+ import { NonEmptyArray } from 'justypes'
2
+ import { randomWeighted } from './random-weighted.js'
3
+ import { IRandomNumberGenerator } from './types.js'
4
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
5
+
6
+ export type IWeightModel<T> = NonEmptyArray<{
7
+ weight: number
8
+ value: T
9
+ }>
10
+
11
+ export function randomByWeightModel<T>(model: IWeightModel<T>): T
12
+ export function randomByWeightModel<T>(
13
+ generator: IRandomNumberGenerator
14
+ , model: IWeightModel<T>
15
+ ): T
16
+ export function randomByWeightModel<T>(...args:
17
+ | [model: IWeightModel<T>]
18
+ | [generator: IRandomNumberGenerator, model: IWeightModel<T>]
19
+ ): T {
20
+ let generator: IRandomNumberGenerator
21
+ let model: IWeightModel<T>
22
+
23
+ if (args.length === 1) {
24
+ generator = NativeRandomNumberGenerator
25
+ ;[model] = args
26
+ } else {
27
+ [generator, model] = args
28
+ }
29
+
30
+ const { value } = randomWeighted(generator, model)
31
+ return value
32
+ }
@@ -0,0 +1,30 @@
1
+ import { NonEmptyArray } from 'justypes'
2
+ import { mapToIndexByWeight } from './map-to-index-by-weight.js'
3
+ import { IRandomNumberGenerator } from './types.js'
4
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
5
+
6
+ export function randomIndexByWeight(weights: NonEmptyArray<number>): number
7
+ export function randomIndexByWeight(
8
+ generator: IRandomNumberGenerator
9
+ , weights: NonEmptyArray<number>
10
+ ): number
11
+ export function randomIndexByWeight(...args:
12
+ | [weights: NonEmptyArray<number>]
13
+ | [generator: IRandomNumberGenerator, weights: NonEmptyArray<number>]
14
+ ): number {
15
+ let generator: IRandomNumberGenerator
16
+ let weights: NonEmptyArray<number>
17
+
18
+ if (args.length === 1) {
19
+ generator = NativeRandomNumberGenerator
20
+ ;[weights] = args
21
+ } else {
22
+ [generator, weights] = args
23
+ }
24
+
25
+ return mapToIndexByWeight(
26
+ generator.next()
27
+ , 0, 1
28
+ , weights
29
+ )
30
+ }
@@ -1,8 +1,33 @@
1
- import { mapToRange } from './map-to-range'
1
+ import { mapToRange } from './map-to-range.js'
2
+ import { IRandomNumberGenerator } from './types.js'
3
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
4
+
5
+ export function randomIntInclusive(
6
+ min: number
7
+ , max: number
8
+ ): number
9
+ export function randomIntInclusive(
10
+ generator: IRandomNumberGenerator
11
+ , min: number
12
+ , max: number
13
+ ): number
14
+ export function randomIntInclusive(...args:
15
+ | [min: number, max: number]
16
+ | [generator: IRandomNumberGenerator, min: number, max: number]
17
+ ): number {
18
+ let generator: IRandomNumberGenerator
19
+ let min: number
20
+ let max: number
21
+
22
+ if (args.length === 2) {
23
+ generator = NativeRandomNumberGenerator
24
+ ;[min, max] = args
25
+ } else {
26
+ [generator, min, max] = args
27
+ }
2
28
 
3
- export function randomIntInclusive(min: number, max: number): number {
4
29
  return Math.floor(mapToRange(
5
- Math.random()
30
+ generator.next()
6
31
  , 0, 1
7
32
  , Math.ceil(min), Math.floor(max) + 1
8
33
  ))
package/src/random-int.ts CHANGED
@@ -1,8 +1,30 @@
1
- import { mapToRange } from './map-to-range'
1
+ import { mapToRange } from './map-to-range.js'
2
+ import { IRandomNumberGenerator } from './types.js'
3
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
4
+
5
+ export function randomInt(min: number, max: number): number
6
+ export function randomInt(
7
+ generator: IRandomNumberGenerator
8
+ , min: number
9
+ , max: number
10
+ ): number
11
+ export function randomInt(...args:
12
+ | [min: number, max: number]
13
+ | [generator: IRandomNumberGenerator, min: number, max: number]
14
+ ): number {
15
+ let generator: IRandomNumberGenerator
16
+ let min: number
17
+ let max: number
18
+
19
+ if (args.length === 2) {
20
+ generator = NativeRandomNumberGenerator
21
+ ;[min, max] = args
22
+ } else {
23
+ [generator, min, max] = args
24
+ }
2
25
 
3
- export function randomInt(min: number, max: number): number {
4
26
  return Math.floor(mapToRange(
5
- Math.random()
27
+ generator.next()
6
28
  , 0, 1
7
29
  , Math.ceil(min), Math.floor(max)
8
30
  ))
@@ -0,0 +1,32 @@
1
+ import { randomIndexByWeight } from './random-index-by-weight.js'
2
+ import { NonEmptyArray } from 'justypes'
3
+ import { IRandomNumberGenerator } from './types.js'
4
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
5
+
6
+ export interface IWeighted {
7
+ weight: number
8
+ }
9
+
10
+ export function randomWeighted<T extends IWeighted>(values: NonEmptyArray<T>): T
11
+ export function randomWeighted<T extends IWeighted>(
12
+ generator: IRandomNumberGenerator
13
+ , values: NonEmptyArray<T>
14
+ ): T
15
+ export function randomWeighted<T extends IWeighted>(...args:
16
+ | [values: NonEmptyArray<T>]
17
+ | [generator: IRandomNumberGenerator, values: NonEmptyArray<T>]
18
+ ): T {
19
+ let generator: IRandomNumberGenerator
20
+ let values: NonEmptyArray<T>
21
+
22
+ if (args.length === 1) {
23
+ generator = NativeRandomNumberGenerator
24
+ ;[values] = args
25
+ } else {
26
+ [generator, values] = args
27
+ }
28
+
29
+ const weights = values.map(option => option.weight) as NonEmptyArray<number>
30
+ const index = randomIndexByWeight(generator, weights)
31
+ return values[index]
32
+ }
package/src/random.ts CHANGED
@@ -1,8 +1,30 @@
1
- import { mapToRange } from './map-to-range'
1
+ import { mapToRange } from './map-to-range.js'
2
+ import { IRandomNumberGenerator } from './types.js'
3
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
4
+
5
+ export function random(min: number, max: number): number
6
+ export function random(
7
+ generator: IRandomNumberGenerator
8
+ , min: number
9
+ , max: number
10
+ ): number
11
+ export function random(...args:
12
+ | [min: number, max: number]
13
+ | [generator: IRandomNumberGenerator, min: number, max: number]
14
+ ): number {
15
+ let generator: IRandomNumberGenerator
16
+ let min: number
17
+ let max: number
18
+
19
+ if (args.length === 2) {
20
+ generator = NativeRandomNumberGenerator
21
+ ;[min, max] = args
22
+ } else {
23
+ [generator, min, max] = args
24
+ }
2
25
 
3
- export function random(min: number, max: number): number {
4
26
  return mapToRange(
5
- Math.random()
27
+ generator.next()
6
28
  , 0, 1
7
29
  , min, max
8
30
  )
package/src/types.ts ADDED
@@ -0,0 +1,3 @@
1
+ export interface IRandomNumberGenerator {
2
+ next(): number
3
+ }
@@ -1 +0,0 @@
1
- export declare function randomByWeight(weights: number[]): number;
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.randomByWeight = void 0;
4
- const map_to_index_by_weight_1 = require("./map-to-index-by-weight");
5
- function randomByWeight(weights) {
6
- return (0, map_to_index_by_weight_1.mapToIndexByWeight)(Math.random(), 0, 1, weights);
7
- }
8
- exports.randomByWeight = randomByWeight;
9
- //# sourceMappingURL=random-by-weight.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"random-by-weight.js","sourceRoot":"","sources":["../src/random-by-weight.ts"],"names":[],"mappings":";;;AAAA,qEAA6D;AAE7D,SAAgB,cAAc,CAAC,OAAiB;IAC9C,OAAO,IAAA,2CAAkB,EACvB,IAAI,CAAC,MAAM,EAAE,EACb,CAAC,EAAE,CAAC,EACJ,OAAO,CACR,CAAA;AACH,CAAC;AAND,wCAMC"}
@@ -1,9 +0,0 @@
1
- import { mapToIndexByWeight } from './map-to-index-by-weight'
2
-
3
- export function randomByWeight(weights: number[]): number {
4
- return mapToIndexByWeight(
5
- Math.random()
6
- , 0, 1
7
- , weights
8
- )
9
- }