toosoon-prng-controllers
Version:
This project provides PRNG functions with a set of controllers for generating pseudo-random values using a seed-based approach
604 lines (603 loc) • 16 kB
JavaScript
import prng from './prng';
/**
* Utility abstract class for generating a pseudo-random values
*
* @class PRNGController
* @abstract
* @template {unknown} [T=unknown]
*/
export class PRNGController {
/**
* Seed string used for pseudo-random generations
*/
seed;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
*/
constructor(seed) {
this.seed = `${seed}`;
prng.addController(this);
}
/**
* Dispose this controller
*/
dispose() {
prng.removeController(this);
}
}
/**
* Utility abstract class for managing multiple instances of controllers
*
* @class PRNGGroupController
* @abstract
* @template {unknown} [T=unknown]
* @template {PRNGController<T>} [C=PRNGController<T>]
*/
export class PRNGGroupController {
/**
* Seed string used for pseudo-random generations
*/
seed;
/**
* Controllers managed by this group
*/
controllers = [];
/**
* @param {Seed} seed Seed string used for pseudo-random generations
*/
constructor(seed) {
this.seed = `${seed}`;
}
/**
* Generate a pseudo-random value
*
* @param {number} index Index of the controller to use
* @returns {T} Generated pseudo-random value
*/
getValueAt(index) {
let controller = this.controllers[index];
if (!controller) {
controller = this.createController(index);
this.controllers[index] = controller;
}
return controller.value;
}
/**
* Dispose this group controllers
*/
dispose() {
this.controllers.forEach((controller) => controller.dispose());
this.controllers = [];
}
}
// *********************
// Controllers
// *********************
/**
* Utility class for generating pseudo-random boolean values
*
* @exports
* @class BooleanController
* @extends PRNGController
*/
export class BooleanController extends PRNGController {
/**
* Pseudo-random boolean value generated by this controller
*/
value;
/**
* Probability to get `true`
*/
probability;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [probability=0.5] Probability to get `true`
*/
constructor(seed, probability = 0.5) {
super(seed);
this.probability = probability;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomBoolean(this.seed, this.probability);
return this.value;
}
}
/**
* Utility class for generating pseudo-random sign values (-1 or 1)
*
* @exports
* @class SignController
* @extends PRNGController
*/
export class SignController extends PRNGController {
/**
* Pseudo-random sign value generated by this controller
*/
value;
/**
* Probability to get `1`
*/
probability;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [probability=0.5] Probability to get `1`
*/
constructor(seed, probability = 0.5) {
super(seed);
this.probability = probability;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomSign(this.seed, this.probability);
return this.value;
}
}
/**
* Utility class for generating pseudo-random floating-point numbers within a specified range
*
* @exports
* @class FloatController
* @extends PRNGController
*/
export class FloatController extends PRNGController {
/**
* Pseudo-random floating-point number value generated by this controller
*/
value;
/**
* Minimum boundary
*/
min;
/**
* Maximum boundary
*/
max;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [min=0] Minimum boundary
* @param {number} [max=1] Maximum boundary
*/
constructor(seed, min = 0, max = 1) {
super(seed);
this.min = min;
this.max = max;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomFloat(this.seed, this.min, this.max);
return this.value;
}
}
/**
* Utility class for generating pseudo-random integer numbers within a specified range
*
* @exports
* @class IntController
* @extends PRNGController
*/
export class IntController extends PRNGController {
/**
* Pseudo-random integer number value generated by this controller
*/
value;
/**
* Minimum boundary
*/
min;
/**
* Maximum boundary
*/
max;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} min Minimum boundary
* @param {number} max Maximum boundary
*/
constructor(seed, min, max) {
super(seed);
this.min = min;
this.max = max;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomInt(this.seed, this.min, this.max);
return this.value;
}
}
/**
* Utility class for generating pseudo-random hexadecimal colors
*
* @exports
* @class HexColorController
* @extends PRNGController
*/
export class HexColorController extends PRNGController {
/**
* Pseudo-random hexadecimal color value generated by this controller
*/
value;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
*/
constructor(seed) {
super(seed);
this.value = this.getValue();
}
getValue() {
this.value = prng.randomHexColor(this.seed);
return this.value;
}
}
/**
* Utility class for pseudo-randomly picking an item from an array
*
* @exports
* @class ItemController
* @extends PRNGController<T>
* @template {unknown} [T=unknown]
*/
export class ItemController extends PRNGController {
/**
* Item pseudo-randomly picked from the items array
*/
value;
/**
* Array of items to pseudo-randomly pick from
*/
items;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {T[]} items Array of items to pseudo-randomly pick from
*/
constructor(seed, items) {
super(seed);
this.items = items;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomItem(this.seed, this.items);
return this.value;
}
}
/**
* Utility class for pseudo-randomly picking a property value from an object
*
* @exports
* @class ObjectPropertyController
* @extends PRNGController<T|undefined>
* @template {unknown} [T=unknown]
*/
export class ObjectPropertyController extends PRNGController {
/**
* Property value pseudo-randomly picked from the object
*/
value;
/**
* Object to pseudo-randomly pick the property value from
*/
object;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {object} object Object to pseudo-randomly pick the property value from
*/
constructor(seed, object) {
super(seed);
this.object = object;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomObjectProperty(this.seed, this.object);
return this.value;
}
}
/**
* Utility class for pseudo-randomly picking an item from an array of weighted items
*
* @exports
* @class WeightsController
* @extends PRNGController
*/
export class WeightsController extends PRNGController {
/**
* Item pseudo-randomly picked from the weighted items array
*/
value;
/**
* Array of weighted items to pseudo-randomly pick from
*/
items;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {WeightedItems<T>} items Array of weighted items to pseudo-randomly pick from
*/
constructor(seed, items) {
super(seed);
this.items = items;
this.value = this.getValue();
}
getValue() {
const index = prng.randomIndex(this.seed, this.weights);
this.value = this.items[index].value;
return this.value;
}
/**
* Array of weights
*/
get weights() {
return this.items.map((item) => item.weight);
}
}
/**
* Utility class for generating pseudo-random numbers fitting a Gaussian (normal) distribution
*
* @exports
* @class GaussianController
* @extends PRNGController
*/
export class GaussianController extends PRNGController {
/**
* Pseudo-random number value generated by this controller
*/
value;
/**
* Mean (central) value of the distribution
*/
mean;
/**
* Spread (standard deviation) of the distribution
*/
spread;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [mean=0] Mean (central) value of the distribution
* @param {number} [spread=1] Spread (standard deviation) of the distribution
*/
constructor(seed, mean = 0, spread = 1) {
super(seed);
this.mean = mean;
this.spread = spread;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomGaussian(this.seed, this.mean, this.spread);
return this.value;
}
}
// *********************
// Group Controllers
// *********************
/**
* Utility class for managing multiple {@link BooleanController}
*
* @exports
* @class BooleanGroupController
* @extends PRNGGroupController<boolean, BooleanController>
*/
export class BooleanGroupController extends PRNGGroupController {
/**
* Probability to get `true`
*/
probability;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [probability=0.5] Probability to get `true`
*/
constructor(seed, probability = 0.5) {
super(seed);
this.probability = probability;
}
createController(index) {
return new BooleanController(`${this.seed}${index}`, this.probability);
}
}
/**
* Utility class for managing multiple {@link SignController}
*
* @exports
* @class SignGroupController
* @extends PRNGGroupController<number, SignController>
*/
export class SignGroupController extends PRNGGroupController {
/**
* Probability to get `1`
*/
probability;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [probability=0.5] Probability to get `1`
*/
constructor(seed, probability = 0.5) {
super(seed);
this.probability = probability;
}
createController(index) {
return new SignController(`${this.seed}${index}`, this.probability);
}
}
/**
* Utility class for managing multiple {@link FloatController}
*
* @exports
* @class FloatGroupController
* @extends PRNGGroupController<number, FloatController>
*/
export class FloatGroupController extends PRNGGroupController {
/**
* Minimum boundary
*/
min;
/**
* Maximum boundary
*/
max;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [min=0] Minimum boundary
* @param {number} [max=1] Maximum boundary
*/
constructor(seed, min = 0, max = 1) {
super(seed);
this.min = min;
this.max = max;
}
createController(index) {
return new FloatController(`${this.seed}${index}`, this.min, this.max);
}
}
/**
* Utility class for managing multiple {@link IntController}
*
* @exports
* @class IntGroupController
* @extends PRNGGroupController<number, IntController>
*/
export class IntGroupController extends PRNGGroupController {
/**
* Minimum boundary
*/
min;
/**
* Maximum boundary
*/
max;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} min Minimum boundary
* @param {number} max Maximum boundary
*/
constructor(seed, min, max) {
super(seed);
this.min = min;
this.max = max;
}
createController(index) {
return new IntController(`${this.seed}${index}`, this.min, this.max);
}
}
/**
* Utility class for managing multiple {@link HexColorController}
*
* @exports
* @class HexColorGroupController
* @extends PRNGGroupController<string, HexColorController>
*/
export class HexColorGroupController extends PRNGGroupController {
// constructor(seed: Seed) {
// super(seed);
// }
createController(index) {
return new HexColorController(`${this.seed}${index}`);
}
}
/**
* Utility class for managing multiple {@link ItemController}
*
* @exports
* @class ItemGroupController
* @extends PRNGGroupController<T, ItemController<T>>
* @template {unknown} [T=unknown]
*/
export class ItemGroupController extends PRNGGroupController {
/**
* Array of items to pseudo-randomly pick from
*/
items;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {T[]} items Array of items to pseudo-randomly pick from
*/
constructor(seed, items) {
super(seed);
this.items = items;
}
createController(index) {
return new ItemController(`${this.seed}${index}`, this.items);
}
}
/**
* Utility class for managing multiple {@link ObjectPropertyController}
*
* @exports
* @class ObjectPropertyGroupController
* @extends PRNGGroupController<T|undefined, ObjectPropertyController<T>>
* @template {unknown} [T=unknown]
*/
export class ObjectPropertyGroupController extends PRNGGroupController {
/**
* Object to pseudo-randomly pick the property value from
*/
object;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {object} object Object to pseudo-randomly pick the property value from
*/
constructor(seed, object) {
super(seed);
this.object = object;
}
createController(index) {
return new ObjectPropertyController(`${this.seed}${index}`, this.object);
}
}
/**
* Utility class for managing multiple {@link WeightsController}
*
* @exports
* @class WeightsGroupController
* @extends PRNGGroupController<T, WeightsController<T>>
* @template {unknown} [T=unknown]
*/
export class WeightsGroupController extends PRNGGroupController {
/**
* Array of weighted items to pseudo-randomly pick from
*/
items;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {WeightedItems<T>} items Array of weighted items to pseudo-randomly pick from
*/
constructor(seed, items) {
super(seed);
this.items = items;
}
createController(index) {
return new WeightsController(`${this.seed}${index}`, this.items);
}
/**
* Array of weights
*/
get weights() {
return this.items.map((item) => item.weight);
}
}
/**
* Utility class for managing multiple {@link GaussianController}
*
* @exports
* @class GaussianGroupController
* @extends PRNGGroupController<number, GaussianController>
*/
export class GaussianGroupController extends PRNGGroupController {
/**
* Mean (central) value of the distribution
*/
mean;
/**
* Spread (standard deviation) of the distribution
*/
spread;
/**
* @param {Seed} seed Seed string used for pseudo-random generations
* @param {number} [mean=0] Mean (central) value of the distribution
* @param {number} [spread=1] Spread (standard deviation) of the distribution
*/
constructor(seed, mean = 0, spread = 1) {
super(seed);
this.mean = mean;
this.spread = spread;
}
createController(index) {
return new GaussianController(`${this.seed}${index}`, this.mean, this.spread);
}
}