@xtia/alea-rc 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -13
- package/entry/browser.js +2 -2
- package/entry/common.d.ts +1 -1
- package/entry/common.js +1 -1
- package/entry/node.js +2 -2
- package/internal/alea.d.ts +3 -23
- package/internal/alea.js +13 -43
- package/internal/factories.d.ts +3 -3
- package/internal/factories.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ Alea is a utility wrapper for turning random numbers into useful values. Give it
|
|
|
7
7
|
* Fully typed
|
|
8
8
|
* Crypto-safe and seeded algorithms out-of-the-box
|
|
9
9
|
* No dependencies
|
|
10
|
-
* ~2.
|
|
11
|
-
* Ranged int, array shuffling, dice roll, weighted sampling, phrase generation, UUID, bytes and many more
|
|
10
|
+
* ~2.4kb minified core
|
|
11
|
+
* Ranged int, array shuffling, dice roll, weighted sampling, recursive template phrase generation, UUID, bytes and many more
|
|
12
12
|
|
|
13
13
|
## Brief:
|
|
14
14
|
|
|
@@ -21,31 +21,38 @@ import { alea, cryptoAlea } from "@xtia/alea";
|
|
|
21
21
|
const damage = alea.roll(2, 6); // 2d6
|
|
22
22
|
const duration = alea.between(1000, 1500);
|
|
23
23
|
const loot = alea.chance(0.125) ? "epic" : "common";
|
|
24
|
-
const id = alea.string(5);
|
|
24
|
+
const id = alea.string(5, "abcdef0123456789");
|
|
25
25
|
const npcName = alea.sample(["Alice", "Bob", "Charlie"]);
|
|
26
26
|
|
|
27
27
|
// secure source (driven by environment's crypto)
|
|
28
28
|
const key = cryptoAlea.string(16);
|
|
29
29
|
```
|
|
30
|
-
|
|
31
|
-
## Custom sources
|
|
30
|
+
# Custom sources
|
|
32
31
|
|
|
33
32
|
Use any provider as RNG source:
|
|
34
33
|
|
|
35
34
|
```ts
|
|
36
35
|
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
aleaFromFunc,
|
|
37
|
+
aleaFromSeed,
|
|
38
|
+
aleaFromByteSource,
|
|
40
39
|
} from "@xtia/alea";
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
41
|
+
// deterministic, with seed (uses Mulberry32 PRNG):
|
|
42
|
+
const seededRng = aleaFromSeed("abc123");
|
|
43
|
+
|
|
44
|
+
// custom source of randomness:
|
|
45
|
+
const xkcdRng = aleaFromFunc(() => 4/6); // https://xkcd.com/221/
|
|
46
|
+
|
|
47
|
+
// from random byte providers:
|
|
48
|
+
const secureRng = aleaFromByteSource(
|
|
45
49
|
buf => hardwareRNG.fillRandomBytes(buf)
|
|
46
50
|
);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or use a provided PRNG algorithm:
|
|
47
54
|
|
|
48
|
-
|
|
55
|
+
```ts
|
|
49
56
|
import {
|
|
50
57
|
mulberry32,
|
|
51
58
|
sfc32,
|
|
@@ -57,5 +64,5 @@ const fast = mulberry32("my-seed");
|
|
|
57
64
|
const varied = sfc32(1, 2, 3, 4);
|
|
58
65
|
const strong = xoshiro128pp(5, 6, 7, 8);
|
|
59
66
|
|
|
60
|
-
const
|
|
67
|
+
const reproducibleRoll = varied.roll(3, 6);
|
|
61
68
|
```
|
package/entry/browser.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { aleaFromByteSource } from "../internal/factories.js";
|
|
2
2
|
export * from "./common.js";
|
|
3
|
-
export const cryptoAlea =
|
|
3
|
+
export const cryptoAlea = aleaFromByteSource((arr) => globalThis.crypto.getRandomValues(arr));
|
package/entry/common.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Alea } from "../internal/alea.js";
|
|
2
2
|
export type { Alea };
|
|
3
|
-
export {
|
|
3
|
+
export { aleaFromByteSource, aleaFromSeed, aleaFromFunc, } from "../internal/factories.js";
|
|
4
4
|
export { charsets } from "../internal/charsets.js";
|
|
5
5
|
export { alea } from "../internal/mathalea.js";
|
package/entry/common.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { aleaFromByteSource, aleaFromSeed, aleaFromFunc, } from "../internal/factories.js";
|
|
2
2
|
export { charsets } from "../internal/charsets.js";
|
|
3
3
|
export { alea } from "../internal/mathalea.js";
|
package/entry/node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { aleaFromByteSource } from "../internal/factories.js";
|
|
2
2
|
import { randomBytes } from 'node:crypto';
|
|
3
3
|
export * from "./common.js";
|
|
4
|
-
export const cryptoAlea =
|
|
4
|
+
export const cryptoAlea = aleaFromByteSource(arr => {
|
|
5
5
|
randomBytes(arr.length).copy(arr);
|
|
6
6
|
});
|
package/internal/alea.d.ts
CHANGED
|
@@ -9,12 +9,6 @@ export declare class Alea {
|
|
|
9
9
|
* @param next Source RNG - a function that returns a value >= 0 and < 1
|
|
10
10
|
*/
|
|
11
11
|
constructor(next: RandomFunction);
|
|
12
|
-
/**
|
|
13
|
-
* Generate a series of normalised random values
|
|
14
|
-
* @param count
|
|
15
|
-
* @returns Random values
|
|
16
|
-
*/
|
|
17
|
-
batch(count: number): number[];
|
|
18
12
|
/**
|
|
19
13
|
* Pick a random item from an array
|
|
20
14
|
* @param items
|
|
@@ -103,26 +97,12 @@ export declare class Alea {
|
|
|
103
97
|
*/
|
|
104
98
|
round(n: number): number;
|
|
105
99
|
/**
|
|
106
|
-
* Get a random
|
|
100
|
+
* Get a random normal pair using Box-Muller transform
|
|
107
101
|
* @param mean
|
|
108
102
|
* @param deviation
|
|
109
|
-
* @returns
|
|
110
|
-
*/
|
|
111
|
-
normal(mean: number, deviation: number): number;
|
|
112
|
-
/**
|
|
113
|
-
* Get a random integer value between `min` and `max`, inclusive.
|
|
114
|
-
* @param min Minimum value, **inclusive**
|
|
115
|
-
* @param max Maximum value, **inclusive**
|
|
116
|
-
* @returns Random int value
|
|
117
|
-
*/
|
|
118
|
-
int(min: number, max: number): number;
|
|
119
|
-
/**
|
|
120
|
-
* Roll dice
|
|
121
|
-
* @param count Number of dice to roll (default 1)
|
|
122
|
-
* @param sides Number of sides per die (default 6)
|
|
123
|
-
* @returns Dice result
|
|
103
|
+
* @returns Gaussian normal pair
|
|
124
104
|
*/
|
|
125
|
-
|
|
105
|
+
normal(mean?: number, deviation?: number): [number, number];
|
|
126
106
|
/**
|
|
127
107
|
* Generate a random UUID (version 4)
|
|
128
108
|
*
|
package/internal/alea.js
CHANGED
|
@@ -5,17 +5,6 @@ export class Alea {
|
|
|
5
5
|
constructor(next) {
|
|
6
6
|
this.next = next;
|
|
7
7
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Generate a series of normalised random values
|
|
10
|
-
* @param count
|
|
11
|
-
* @returns Random values
|
|
12
|
-
*/
|
|
13
|
-
batch(count) {
|
|
14
|
-
if (!Number.isInteger(count) || count < 0) {
|
|
15
|
-
throw new RangeError("count must be a non-negative integer");
|
|
16
|
-
}
|
|
17
|
-
return Array.from({ length: count }, () => this.next());
|
|
18
|
-
}
|
|
19
8
|
sample(items, count) {
|
|
20
9
|
if (count === undefined) {
|
|
21
10
|
if (items.length === 0)
|
|
@@ -80,8 +69,7 @@ export class Alea {
|
|
|
80
69
|
const pool = [...charset];
|
|
81
70
|
if (pool.length === 0)
|
|
82
71
|
throw new RangeError("charset must not be empty");
|
|
83
|
-
|
|
84
|
-
return chars.join("");
|
|
72
|
+
return Array.from({ length }, () => this.sample(pool)).join("");
|
|
85
73
|
}
|
|
86
74
|
/**
|
|
87
75
|
* Generate a phrase from a table and a root string
|
|
@@ -158,10 +146,10 @@ export class Alea {
|
|
|
158
146
|
const words = Math.floor(len / 4);
|
|
159
147
|
const view = new DataView(byteArray.buffer, byteArray.byteOffset, byteArray.byteLength);
|
|
160
148
|
for (let i = 0; i < words; i++) {
|
|
161
|
-
view.setUint32(i * 4, this.
|
|
149
|
+
view.setUint32(i * 4, this.between(0, 0x100000000) >>> 0);
|
|
162
150
|
}
|
|
163
151
|
for (let i = words * 4; i < len; i++) {
|
|
164
|
-
byteArray[i] = this.
|
|
152
|
+
byteArray[i] = this.between(0, 256) | 0;
|
|
165
153
|
}
|
|
166
154
|
return result;
|
|
167
155
|
}
|
|
@@ -181,42 +169,24 @@ export class Alea {
|
|
|
181
169
|
return this.chance(n - floor) ? floor + 1 : floor;
|
|
182
170
|
}
|
|
183
171
|
/**
|
|
184
|
-
* Get a random
|
|
172
|
+
* Get a random normal pair using Box-Muller transform
|
|
185
173
|
* @param mean
|
|
186
174
|
* @param deviation
|
|
187
|
-
* @returns
|
|
175
|
+
* @returns Gaussian normal pair
|
|
188
176
|
*/
|
|
189
|
-
normal(mean, deviation) {
|
|
177
|
+
normal(mean = 0, deviation = 1) {
|
|
190
178
|
let u1 = this.next();
|
|
191
|
-
while (u1 <= Number.EPSILON)
|
|
179
|
+
while (u1 <= Number.EPSILON)
|
|
192
180
|
u1 = this.next();
|
|
193
|
-
}
|
|
194
181
|
const u2 = this.next();
|
|
195
182
|
const mag = Math.sqrt(-2 * Math.log(u1));
|
|
196
183
|
const angle = 2 * Math.PI * u2;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
* @returns Random int value
|
|
204
|
-
*/
|
|
205
|
-
int(min, max) {
|
|
206
|
-
return Math.floor(this.between(min, max + 1));
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Roll dice
|
|
210
|
-
* @param count Number of dice to roll (default 1)
|
|
211
|
-
* @param sides Number of sides per die (default 6)
|
|
212
|
-
* @returns Dice result
|
|
213
|
-
*/
|
|
214
|
-
roll(count = 1, sides = 6) {
|
|
215
|
-
let total = 0;
|
|
216
|
-
for (let i = 0; i < count; i++) {
|
|
217
|
-
total += this.int(1, sides);
|
|
218
|
-
}
|
|
219
|
-
return total;
|
|
184
|
+
const z0 = mag * Math.cos(angle);
|
|
185
|
+
const z1 = mag * Math.sin(angle);
|
|
186
|
+
return [
|
|
187
|
+
mean + z0 * deviation,
|
|
188
|
+
mean + z1 * deviation
|
|
189
|
+
];
|
|
220
190
|
}
|
|
221
191
|
/**
|
|
222
192
|
* Generate a random UUID (version 4)
|
package/internal/factories.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { Alea } from "./alea.js";
|
|
|
10
10
|
* @param applyBytes A callback that fills a Uint8Array with random bytes
|
|
11
11
|
* @returns A byte generator-sourced Alea instance
|
|
12
12
|
*/
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function aleaFromByteSource(applyBytes: (buffer: Uint8Array) => void): Alea;
|
|
14
14
|
/**
|
|
15
15
|
* Create an Alea instance using a Mulberry32 source
|
|
16
16
|
*
|
|
@@ -20,7 +20,7 @@ export declare function createAleaFromByteSource(applyBytes: (buffer: Uint8Array
|
|
|
20
20
|
* @param seed
|
|
21
21
|
* @returns Alea instance using Mulberry32
|
|
22
22
|
*/
|
|
23
|
-
export declare function
|
|
23
|
+
export declare function aleaFromSeed(seed: number | string): Alea;
|
|
24
24
|
/**
|
|
25
25
|
* Create an Alea instance using a custom function as an RNG source
|
|
26
26
|
* @example
|
|
@@ -31,4 +31,4 @@ export declare function createAleaFromSeed(seed: number | string): Alea;
|
|
|
31
31
|
* @param fn Source RNG; a function that returns a value >= 0 and < 1
|
|
32
32
|
* @returns Custom function-sourced Alea instance
|
|
33
33
|
*/
|
|
34
|
-
export declare function
|
|
34
|
+
export declare function aleaFromFunc(fn: () => number): Alea;
|
package/internal/factories.js
CHANGED
|
@@ -11,7 +11,7 @@ import { Alea } from "./alea.js";
|
|
|
11
11
|
* @param applyBytes A callback that fills a Uint8Array with random bytes
|
|
12
12
|
* @returns A byte generator-sourced Alea instance
|
|
13
13
|
*/
|
|
14
|
-
export function
|
|
14
|
+
export function aleaFromByteSource(applyBytes) {
|
|
15
15
|
const buffer = new ArrayBuffer(4);
|
|
16
16
|
const view = new Uint8Array(buffer);
|
|
17
17
|
const uint32View = new Uint32Array(buffer);
|
|
@@ -29,7 +29,7 @@ export function createAleaFromByteSource(applyBytes) {
|
|
|
29
29
|
* @param seed
|
|
30
30
|
* @returns Alea instance using Mulberry32
|
|
31
31
|
*/
|
|
32
|
-
export function
|
|
32
|
+
export function aleaFromSeed(seed) {
|
|
33
33
|
return mulberry32(seed);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
@@ -42,7 +42,7 @@ export function createAleaFromSeed(seed) {
|
|
|
42
42
|
* @param fn Source RNG; a function that returns a value >= 0 and < 1
|
|
43
43
|
* @returns Custom function-sourced Alea instance
|
|
44
44
|
*/
|
|
45
|
-
export function
|
|
45
|
+
export function aleaFromFunc(fn) {
|
|
46
46
|
return new Alea(fn);
|
|
47
47
|
}
|
|
48
48
|
// const xkcdAlea = createAleaFromFunc(() => 4/6); // decided by die roll
|