toosoon-prng-controllers
Version:
This project provides PRNG functions with a set of Controllers for generating pseudo-random values using a seed-based approach and various algorithms
452 lines (451 loc) • 11.7 kB
JavaScript
import prng from './prng';
/**
* Utility abstract class for generating pseudo-random values
*
* @class PRNGController
* @abstract
*/
export class PRNGController {
seed;
gui;
constructor(seed) {
this.seed = `${seed}`;
prng.addController(this);
}
addGUI(gui, params = {}) {
this.gui = gui.addBinding(this, 'value', { label: this.seed, ...params });
return this.gui;
}
dispose() {
prng.removeController(this);
this.gui?.dispose();
}
}
/**
* Utility abstract class for managing multiple instances of individual controllers
*
* @class PRNGGroupController
* @abstract
*/
export class PRNGGroupController {
seed;
controllers = [];
gui;
guiParams;
constructor(seed) {
this.seed = `${seed}`;
}
addGUI(gui, params = {}) {
this.gui = gui.addFolder({ title: this.seed, expanded: false, ...params });
this.guiParams = params;
return this.gui;
}
getValueAt(index) {
let controller = this.controllers[index];
if (!controller) {
controller = this.createController(index);
if (this.gui) {
controller.addGUI(this.gui, { label: `${this.gui.title}-${index}`, ...this.guiParams });
}
this.controllers[index] = controller;
}
return controller.value;
}
dispose() {
this.controllers.forEach((controller) => controller.dispose());
this.controllers = [];
this.gui?.dispose();
}
}
// *********************
// Controllers
// *********************
/**
* Utility class for generating pseudo-random boolean value
*
* @exports
* @class BooleanController
* @extends PRNGController
*/
export class BooleanController extends PRNGController {
value;
probability;
constructor(seed, probability = 0.5) {
super(seed);
this.probability = probability;
this.value = this.getValue();
}
getValue() {
this.value = prng.randomBoolean(this.seed, this.probability);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for generating pseudo-random sign value (-1 or 1)
*
* @exports
* @class SignController
* @extends PRNGController
*/
export class SignController extends PRNGController {
value;
probability;
constructor(seed, probability = 0.5) {
super(seed);
this.probability = probability;
this.value = this.getValue();
}
addGUI(gui, params = {}) {
return super.addGUI(gui, { options: [-1, 1], ...params });
}
getValue() {
this.value = prng.randomSign(this.seed, this.probability);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for generating pseudo-random floating-point number within a specified range
*
* @exports
* @class FloatController
* @extends PRNGController
*/
export class FloatController extends PRNGController {
value;
min;
max;
constructor(seed, min = 0, max = 1) {
super(seed);
this.min = min;
this.max = max;
this.value = this.getValue();
}
addGUI(gui, { min, max, step = 0.01, ...params } = {}) {
return super.addGUI(gui, { min, max, step, ...params });
}
getValue() {
this.value = prng.randomFloat(this.seed, this.min, this.max);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for generating pseudo-random integer number within a specified range
*
* @exports
* @class IntController
* @extends PRNGController
*/
export class IntController extends PRNGController {
value;
min;
max;
constructor(seed, min, max) {
super(seed);
this.min = min;
this.max = max;
this.value = prng.randomInt(this.seed, min, max);
}
addGUI(gui, { min, max, step = 1, ...params } = {}) {
return super.addGUI(gui, { min, max, step, ...params });
}
getValue() {
this.value = prng.randomInt(this.seed, this.min, this.max);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for generating pseudo-random hexadecimal color
*
* @exports
* @class HexColorController
* @extends PRNGController
*/
export class HexColorController extends PRNGController {
value;
constructor(seed) {
super(seed);
this.value = this.getValue();
}
addGUI(gui, { view = 'color', ...params } = {}) {
return super.addGUI(gui, { view, ...params });
}
getValue() {
this.value = prng.randomHexColor(this.seed);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for picking a pseudo-random item from a given array
*
* @exports
* @class ItemController
* @extends PRNGController
*/
export class ItemController extends PRNGController {
value;
items;
constructor(seed, items) {
super(seed);
this.items = items;
this.value = this.getValue();
}
addGUI(gui, params = {}) {
return super.addGUI(gui, { options: this.items, ...params });
}
getValue() {
this.value = prng.randomItem(this.seed, this.items);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for picking a pseudo-random property value from a given object
*
* @exports
* @class ObjectPropertyController
* @extends PRNGController
*/
export class ObjectPropertyController extends PRNGController {
value;
object;
constructor(seed, object) {
super(seed);
this.object = object;
this.value = this.getValue();
}
addGUI(gui, params = {}) {
return super.addGUI(gui, { options: this.object, ...params });
}
getValue() {
this.value = prng.randomObjectProperty(this.seed, this.object);
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for selecting a pseudo-random index from an array of weighted items
*
* @exports
* @class WeightsController
* @extends PRNGController
*/
export class WeightsController extends PRNGController {
value;
items;
weights;
constructor(seed, items) {
super(seed);
this.items = items;
this.weights = this.items.map((item) => item.weight);
this.value = this.getValue();
}
addGUI(gui, params = {}) {
return super.addGUI(gui, { options: this.items.map((item) => item.value), ...params });
}
getValue() {
const index = prng.randomIndex(this.seed, this.weights);
this.value = this.items[index].value;
this.gui?.refresh();
return this.value;
}
}
/**
* Utility class for generating a pseudo-random number fitting a Gaussian (normal) distribution
*
* @exports
* @class GaussianController
* @extends PRNGController
*/
export class GaussianController extends PRNGController {
value;
mean;
spread;
constructor(seed, mean = 0, spread = 1) {
super(seed);
this.mean = mean;
this.spread = spread;
this.value = this.getValue();
}
addGUI(gui, { min = this.mean - this.spread, max = this.mean + this.spread, step, ...params } = {}) {
return super.addGUI(gui, { min, max, step, ...params });
}
getValue() {
this.value = prng.randomGaussian(this.seed, this.mean, this.spread);
this.gui?.refresh();
return this.value;
}
}
// *********************
// Group Controllers
// *********************
/**
* Utility class for managing multiple `BooleanController`
*
* @exports
* @class BooleanGroupController
* @extends PRNGGroupController
*/
export class BooleanGroupController extends PRNGGroupController {
probability;
controllers = [];
constructor(seed, probability) {
super(seed);
this.probability = probability;
}
createController(index) {
return new BooleanController(`${this.seed}-${index}`, this.probability);
}
}
/**
* Utility class for managing multiple `SignController`
*
* @exports
* @class SignGroupController
* @extends PRNGGroupController
*/
export class SignGroupController extends PRNGGroupController {
probability;
controllers = [];
constructor(seed, probability) {
super(seed);
this.probability = probability;
}
createController(index) {
return new SignController(`${this.seed}-${index}`, this.probability);
}
}
/**
* Utility class for managing multiple `FloatController`
*
* @exports
* @class FloatGroupController
* @extends PRNGGroupController
*/
export class FloatGroupController extends PRNGGroupController {
min;
max;
controllers = [];
constructor(seed, min, max) {
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 `IntController`
*
* @exports
* @class IntGroupController
* @extends PRNGGroupController
*/
export class IntGroupController extends PRNGGroupController {
min;
max;
controllers = [];
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 `HexColorController`
*
* @exports
* @class HexColorGroupController
* @extends PRNGGroupController
*/
export class HexColorGroupController extends PRNGGroupController {
controllers = [];
// constructor(seed: string | number) {
// super(seed);
// }
createController(index) {
return new HexColorController(`${this.seed}-${index}`);
}
}
/**
* Utility class for managing multiple `ItemController`
*
* @exports
* @class ItemGroupController
* @extends PRNGGroupController
*/
export class ItemGroupController extends PRNGGroupController {
items;
controllers = [];
constructor(seed, items) {
super(seed);
this.items = items;
}
createController(index) {
return new ItemController(`${this.seed}-${index}`, this.items);
}
}
/**
* Utility class for managing multiple `ObjectPropertyController`
*
* @exports
* @class ObjectPropertyGroupController
* @extends PRNGGroupController
*/
export class ObjectPropertyGroupController extends PRNGGroupController {
object;
controllers = [];
constructor(seed, object) {
super(seed);
this.object = object;
}
createController(index) {
return new ObjectPropertyController(`${this.seed}-${index}`, this.object);
}
}
/**
* Utility class for managing multiple `WeightsController`
*
* @exports
* @class WeightsGroupController
* @extends PRNGGroupController
*/
export class WeightsGroupController extends PRNGGroupController {
items;
controllers = [];
constructor(seed, items) {
super(seed);
this.items = items;
}
createController(index) {
return new WeightsController(`${this.seed}-${index}`, this.items);
}
}
/**
* Utility class for managing multiple `GaussianController`
*
* @exports
* @class GaussianGroupController
* @extends PRNGGroupController
*/
export class GaussianGroupController extends PRNGGroupController {
controllers = [];
mean;
spread;
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);
}
}