extra-rand 0.3.0 → 0.3.2

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 (50) hide show
  1. package/README.md +32 -1
  2. package/lib/index.d.ts +2 -0
  3. package/lib/index.js +2 -0
  4. package/lib/index.js.map +1 -1
  5. package/lib/native-random-number-generator.d.ts +2 -0
  6. package/lib/native-random-number-generator.js +4 -0
  7. package/lib/native-random-number-generator.js.map +1 -0
  8. package/lib/random-bool.d.ts +2 -0
  9. package/lib/random-bool.js +12 -2
  10. package/lib/random-bool.js.map +1 -1
  11. package/lib/random-by-model.d.ts +2 -0
  12. package/lib/random-by-model.js +16 -6
  13. package/lib/random-by-model.js.map +1 -1
  14. package/lib/random-by-weight-model.d.ts +2 -0
  15. package/lib/random-by-weight-model.js +12 -2
  16. package/lib/random-by-weight-model.js.map +1 -1
  17. package/lib/random-index-by-weight.d.ts +2 -0
  18. package/lib/random-index-by-weight.js +12 -2
  19. package/lib/random-index-by-weight.js.map +1 -1
  20. package/lib/random-int-inclusive.d.ts +2 -0
  21. package/lib/random-int-inclusive.js +13 -2
  22. package/lib/random-int-inclusive.js.map +1 -1
  23. package/lib/random-int.d.ts +2 -0
  24. package/lib/random-int.js +13 -2
  25. package/lib/random-int.js.map +1 -1
  26. package/lib/random-weighted.d.ts +2 -0
  27. package/lib/random-weighted.js +12 -2
  28. package/lib/random-weighted.js.map +1 -1
  29. package/lib/random.d.ts +2 -0
  30. package/lib/random.js +13 -2
  31. package/lib/random.js.map +1 -1
  32. package/lib/shuffle.d.ts +3 -0
  33. package/lib/shuffle.js +20 -0
  34. package/lib/shuffle.js.map +1 -0
  35. package/lib/types.d.ts +3 -0
  36. package/lib/types.js +2 -0
  37. package/lib/types.js.map +1 -0
  38. package/package.json +1 -1
  39. package/src/index.ts +3 -0
  40. package/src/native-random-number-generator.ts +5 -0
  41. package/src/random-bool.ts +22 -2
  42. package/src/random-by-model.ts +26 -6
  43. package/src/random-by-weight-model.ts +22 -2
  44. package/src/random-index-by-weight.ts +22 -2
  45. package/src/random-int-inclusive.ts +27 -2
  46. package/src/random-int.ts +24 -2
  47. package/src/random-weighted.ts +22 -2
  48. package/src/random.ts +24 -2
  49. package/src/shuffle.ts +27 -0
  50. package/src/types.ts +3 -0
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,11 +46,16 @@ 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
52
  ### randomIndexByWeight
39
53
  ```ts
40
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.
@@ -49,6 +67,10 @@ interface IWeighted {
49
67
  }
50
68
 
51
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
52
74
  ```
53
75
 
54
76
  ### randomByWeightModel
@@ -58,7 +80,8 @@ type IWeightModel<T> = NonEmptyArray<{
58
80
  value: T
59
81
  }>
60
82
 
61
- function randomByWeightModel<T>(model: IWeightModel<T>): number
83
+ function randomByWeightModel<T>(model: IWeightModel<T>): T
84
+ function randomByWeightModel<T>(generator: IRandomNumberGenerator, model: IWeightModel<T>): T
62
85
  ```
63
86
 
64
87
  ### randomByModel
@@ -82,7 +105,15 @@ type IRandomModel =
82
105
  value: IRandomModel
83
106
  }>
84
107
 
108
+
85
109
  function randomByModel(model: IRandomModel): number
110
+ function randomByModel(generator: IRandomNumberGenerator, model: IRandomModel): number
111
+ ```
112
+
113
+ ### shuffle
114
+ ```ts
115
+ function shuffle(arr: unknown[]): void
116
+ function shuffle(generator: IRandomNumberGenerator, arr: unknown[]): void
86
117
  ```
87
118
 
88
119
  ### mapToRange
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './types.js';
1
2
  export * from './random.js';
2
3
  export * from './random-int.js';
3
4
  export * from './random-int-inclusive.js';
@@ -6,5 +7,6 @@ export * from './random-index-by-weight.js';
6
7
  export * from './random-weighted.js';
7
8
  export * from './random-by-weight-model.js';
8
9
  export * from './random-by-model.js';
10
+ export * from './shuffle.js';
9
11
  export * from './map-to-range.js';
10
12
  export * from './map-to-index-by-weight.js';
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './types.js';
1
2
  export * from './random.js';
2
3
  export * from './random-int.js';
3
4
  export * from './random-int-inclusive.js';
@@ -6,6 +7,7 @@ export * from './random-index-by-weight.js';
6
7
  export * from './random-weighted.js';
7
8
  export * from './random-by-weight-model.js';
8
9
  export * from './random-by-model.js';
10
+ export * from './shuffle.js';
9
11
  export * from './map-to-range.js';
10
12
  export * from './map-to-index-by-weight.js';
11
13
  //# 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,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
+ {"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;AACpC,cAAc,cAAc,CAAA;AAE5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA"}
@@ -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,5 +1,15 @@
1
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
1
2
  import { random } from './random.js';
2
- export function randomBool(probabilityOfTrue) {
3
- return random(0, 1) < probabilityOfTrue;
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;
4
14
  }
5
15
  //# sourceMappingURL=random-bool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"random-bool.js","sourceRoot":"","sources":["../src/random-bool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,UAAU,UAAU,CAAC,iBAAyB;IAClD,OAAO,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAA;AACzC,CAAC"}
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"}
@@ -1,4 +1,5 @@
1
1
  import { Getter, NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
2
3
  export declare enum Type {
3
4
  Float = 0,
4
5
  Integer = 1,
@@ -13,3 +14,4 @@ export type IRandomModel = number | Getter<number> | {
13
14
  value: IRandomModel;
14
15
  }>;
15
16
  export declare function randomByModel(model: IRandomModel): number;
17
+ export declare function randomByModel(generator: IRandomNumberGenerator, model: IRandomModel): number;
@@ -3,13 +3,23 @@ import { randomByWeightModel } from './random-by-weight-model.js';
3
3
  import { random } from './random.js';
4
4
  import { randomInt } from './random-int.js';
5
5
  import { randomIntInclusive } from './random-int-inclusive.js';
6
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
6
7
  export var Type;
7
8
  (function (Type) {
8
9
  Type[Type["Float"] = 0] = "Float";
9
10
  Type[Type["Integer"] = 1] = "Integer";
10
11
  Type[Type["IntegerInclusive"] = 2] = "IntegerInclusive";
11
12
  })(Type || (Type = {}));
12
- export function randomByModel(model) {
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
+ }
13
23
  if (isNumber(model)) {
14
24
  return model;
15
25
  }
@@ -17,15 +27,15 @@ export function randomByModel(model) {
17
27
  return model();
18
28
  }
19
29
  else if (isArray(model)) {
20
- const subModel = randomByWeightModel(model);
21
- return randomByModel(subModel);
30
+ const subModel = randomByWeightModel(generator, model);
31
+ return randomByModel(generator, subModel);
22
32
  }
23
33
  else {
24
34
  const { type, min, max } = model;
25
35
  switch (type) {
26
- case Type.Float: return random(min, max);
27
- case Type.Integer: return randomInt(min, max);
28
- case Type.IntegerInclusive: return randomIntInclusive(min, max);
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);
29
39
  }
30
40
  }
31
41
  }
@@ -1 +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,MAAM,CAAN,IAAY,IAIX;AAJD,WAAY,IAAI;IACd,iCAAK,CAAA;IACL,qCAAO,CAAA;IACP,uDAAgB,CAAA;AAClB,CAAC,EAJW,IAAI,KAAJ,IAAI,QAIf;AAeD,MAAM,UAAU,aAAa,CAAC,KAAmB;IAC/C,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,KAAK,CAAC,CAAA;QAC3C,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAA;IAChC,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,GAAG,EAAE,GAAG,CAAC,CAAA;YACxC,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;YAC7C,KAAK,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;AACH,CAAC"}
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"}
@@ -1,6 +1,8 @@
1
1
  import { NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
2
3
  export type IWeightModel<T> = NonEmptyArray<{
3
4
  weight: number;
4
5
  value: T;
5
6
  }>;
6
7
  export declare function randomByWeightModel<T>(model: IWeightModel<T>): T;
8
+ export declare function randomByWeightModel<T>(generator: IRandomNumberGenerator, model: IWeightModel<T>): T;
@@ -1,6 +1,16 @@
1
1
  import { randomWeighted } from './random-weighted.js';
2
- export function randomByWeightModel(model) {
3
- const { value } = randomWeighted(model);
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);
4
14
  return value;
5
15
  }
6
16
  //# sourceMappingURL=random-by-weight-model.js.map
@@ -1 +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;AAOrD,MAAM,UAAU,mBAAmB,CAAI,KAAsB;IAC3D,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;IACvC,OAAO,KAAK,CAAA;AACd,CAAC"}
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"}
@@ -1,2 +1,4 @@
1
1
  import { NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
2
3
  export declare function randomIndexByWeight(weights: NonEmptyArray<number>): number;
4
+ export declare function randomIndexByWeight(generator: IRandomNumberGenerator, weights: NonEmptyArray<number>): number;
@@ -1,5 +1,15 @@
1
1
  import { mapToIndexByWeight } from './map-to-index-by-weight.js';
2
- export function randomIndexByWeight(weights) {
3
- return mapToIndexByWeight(Math.random(), 0, 1, weights);
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);
4
14
  }
5
15
  //# sourceMappingURL=random-index-by-weight.js.map
@@ -1 +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,MAAM,UAAU,mBAAmB,CAAC,OAA8B;IAChE,OAAO,kBAAkB,CACvB,IAAI,CAAC,MAAM,EAAE,EACb,CAAC,EAAE,CAAC,EACJ,OAAO,CACR,CAAA;AACH,CAAC"}
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,5 +1,16 @@
1
1
  import { mapToRange } from './map-to-range.js';
2
- export function randomIntInclusive(min, max) {
3
- return Math.floor(mapToRange(Math.random(), 0, 1, Math.ceil(min), Math.floor(max) + 1));
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));
4
15
  }
5
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,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,GAAW;IACzD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAC1B,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"}
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,5 +1,16 @@
1
1
  import { mapToRange } from './map-to-range.js';
2
- export function randomInt(min, max) {
3
- return Math.floor(mapToRange(Math.random(), 0, 1, Math.ceil(min), Math.floor(max)));
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)));
4
15
  }
5
16
  //# sourceMappingURL=random-int.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"random-int.js","sourceRoot":"","sources":["../src/random-int.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAC1B,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"}
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"}
@@ -1,5 +1,7 @@
1
1
  import { NonEmptyArray } from 'justypes';
2
+ import { IRandomNumberGenerator } from './types.js';
2
3
  export interface IWeighted {
3
4
  weight: number;
4
5
  }
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;
@@ -1,7 +1,17 @@
1
1
  import { randomIndexByWeight } from './random-index-by-weight.js';
2
- export function randomWeighted(values) {
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
+ }
3
13
  const weights = values.map(option => option.weight);
4
- const index = randomIndexByWeight(weights);
14
+ const index = randomIndexByWeight(generator, weights);
5
15
  return values[index];
6
16
  }
7
17
  //# sourceMappingURL=random-weighted.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"random-weighted.js","sourceRoot":"","sources":["../src/random-weighted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAOjE,MAAM,UAAU,cAAc,CAAsB,MAAwB;IAC1E,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAA0B,CAAA;IAC5E,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC1C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;AACtB,CAAC"}
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,5 +1,16 @@
1
1
  import { mapToRange } from './map-to-range.js';
2
- export function random(min, max) {
3
- return mapToRange(Math.random(), 0, 1, min, max);
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);
4
15
  }
5
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,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,UAAU,MAAM,CAAC,GAAW,EAAE,GAAW;IAC7C,OAAO,UAAU,CACf,IAAI,CAAC,MAAM,EAAE,EACb,CAAC,EAAE,CAAC,EACJ,GAAG,EAAE,GAAG,CACT,CAAA;AACH,CAAC"}
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"}
@@ -0,0 +1,3 @@
1
+ import { IRandomNumberGenerator } from './types.js';
2
+ export declare function shuffle(arr: unknown[]): void;
3
+ export declare function shuffle(generator: IRandomNumberGenerator, arr: unknown[]): void;
package/lib/shuffle.js ADDED
@@ -0,0 +1,20 @@
1
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js';
2
+ import { randomInt } from './random-int.js';
3
+ export function shuffle(...args) {
4
+ let generator;
5
+ let arr;
6
+ if (args.length === 1) {
7
+ generator = NativeRandomNumberGenerator;
8
+ [arr] = args;
9
+ }
10
+ else {
11
+ [generator, arr] = args;
12
+ }
13
+ for (let targetIndex = arr.length - 1; targetIndex > 1; targetIndex--) {
14
+ const index = randomInt(generator, 0, targetIndex);
15
+ const temp = arr[targetIndex];
16
+ arr[targetIndex] = arr[index];
17
+ arr[index] = temp;
18
+ }
19
+ }
20
+ //# sourceMappingURL=shuffle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shuffle.js","sourceRoot":"","sources":["../src/shuffle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAA;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAI3C,MAAM,UAAU,OAAO,CAAC,GAAG,IAE0B;IAEnD,IAAI,SAAiC,CAAA;IACrC,IAAI,GAAc,CAAA;IAElB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,SAAS,GAAG,2BAA2B,CACtC;QAAA,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IACf,CAAC;SAAM,CAAC;QACN,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,IAAI,CAAA;IACzB,CAAC;IAED,KAAK,IAAI,WAAW,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,WAAW,CAAC,CAAA;QAClD,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,CAAA;QAC7B,GAAG,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAA;QAC7B,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IACnB,CAAC;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.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Yet another random library",
5
5
  "keywords": [
6
6
  "random"
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export * from './types.js'
2
+
1
3
  export * from './random.js'
2
4
  export * from './random-int.js'
3
5
  export * from './random-int-inclusive.js'
@@ -6,6 +8,7 @@ export * from './random-index-by-weight.js'
6
8
  export * from './random-weighted.js'
7
9
  export * from './random-by-weight-model.js'
8
10
  export * from './random-by-model.js'
11
+ export * from './shuffle.js'
9
12
 
10
13
  export * from './map-to-range.js'
11
14
  export * from './map-to-index-by-weight.js'
@@ -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 { IRandomNumberGenerator } from './types.js'
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
1
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
  }
@@ -4,6 +4,8 @@ import { randomByWeightModel } from './random-by-weight-model.js'
4
4
  import { random } from './random.js'
5
5
  import { randomInt } from './random-int.js'
6
6
  import { randomIntInclusive } from './random-int-inclusive.js'
7
+ import { IRandomNumberGenerator } from './types.js'
8
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
7
9
 
8
10
  export enum Type {
9
11
  Float
@@ -24,20 +26,38 @@ export type IRandomModel =
24
26
  value: IRandomModel
25
27
  }>
26
28
 
27
- export function randomByModel(model: IRandomModel): number {
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
+
28
48
  if (isNumber(model)) {
29
49
  return model
30
50
  } else if (isFunction(model)) {
31
51
  return model()
32
52
  } else if (isArray(model)) {
33
- const subModel = randomByWeightModel(model)
34
- return randomByModel(subModel)
53
+ const subModel = randomByWeightModel(generator, model)
54
+ return randomByModel(generator, subModel)
35
55
  } else {
36
56
  const { type, min, max } = model
37
57
  switch (type) {
38
- case Type.Float: return random(min, max)
39
- case Type.Integer: return randomInt(min, max)
40
- case Type.IntegerInclusive: return randomIntInclusive(min, max)
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)
41
61
  }
42
62
  }
43
63
  }
@@ -1,12 +1,32 @@
1
1
  import { NonEmptyArray } from 'justypes'
2
2
  import { randomWeighted } from './random-weighted.js'
3
+ import { IRandomNumberGenerator } from './types.js'
4
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
3
5
 
4
6
  export type IWeightModel<T> = NonEmptyArray<{
5
7
  weight: number
6
8
  value: T
7
9
  }>
8
10
 
9
- export function randomByWeightModel<T>(model: IWeightModel<T>): T {
10
- const { value } = randomWeighted(model)
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)
11
31
  return value
12
32
  }
@@ -1,9 +1,29 @@
1
1
  import { NonEmptyArray } from 'justypes'
2
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
+ }
3
24
 
4
- export function randomIndexByWeight(weights: NonEmptyArray<number>): number {
5
25
  return mapToIndexByWeight(
6
- Math.random()
26
+ generator.next()
7
27
  , 0, 1
8
28
  , weights
9
29
  )
@@ -1,8 +1,33 @@
1
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
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
  ))
@@ -1,12 +1,32 @@
1
1
  import { randomIndexByWeight } from './random-index-by-weight.js'
2
2
  import { NonEmptyArray } from 'justypes'
3
+ import { IRandomNumberGenerator } from './types.js'
4
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
3
5
 
4
6
  export interface IWeighted {
5
7
  weight: number
6
8
  }
7
9
 
8
- export function randomWeighted<T extends IWeighted>(values: NonEmptyArray<T>): T {
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
+
9
29
  const weights = values.map(option => option.weight) as NonEmptyArray<number>
10
- const index = randomIndexByWeight(weights)
30
+ const index = randomIndexByWeight(generator, weights)
11
31
  return values[index]
12
32
  }
package/src/random.ts CHANGED
@@ -1,8 +1,30 @@
1
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/shuffle.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { IRandomNumberGenerator } from './types.js'
2
+ import { NativeRandomNumberGenerator } from './native-random-number-generator.js'
3
+ import { randomInt } from './random-int.js'
4
+
5
+ export function shuffle(arr: unknown[]): void
6
+ export function shuffle(generator: IRandomNumberGenerator, arr: unknown[]): void
7
+ export function shuffle(...args:
8
+ | [arr: unknown[]]
9
+ | [generator: IRandomNumberGenerator, arr: unknown[]]
10
+ ) {
11
+ let generator: IRandomNumberGenerator
12
+ let arr: unknown[]
13
+
14
+ if (args.length === 1) {
15
+ generator = NativeRandomNumberGenerator
16
+ ;[arr] = args
17
+ } else {
18
+ [generator, arr] = args
19
+ }
20
+
21
+ for (let targetIndex = arr.length - 1; targetIndex > 1; targetIndex--) {
22
+ const index = randomInt(generator, 0, targetIndex)
23
+ const temp = arr[targetIndex]
24
+ arr[targetIndex] = arr[index]
25
+ arr[index] = temp
26
+ }
27
+ }
package/src/types.ts ADDED
@@ -0,0 +1,3 @@
1
+ export interface IRandomNumberGenerator {
2
+ next(): number
3
+ }