jssm
Version:
A Javascript finite state machine (FSM) with a terse DSL and a simple API. Most FSMs are one-liners. Fast, easy, powerful, well tested, typed with TypeScript, and visualizations. MIT License.
259 lines (258 loc) • 8.98 kB
TypeScript
/*******
*
* Predicate for validating an array for uniqueness. Returns `true` when
* `el` is the first occurrence in `source`, `false` otherwise. Intended
* for use as an `Array.filter` callback. Not generally meant for external
* use.
*
* ```typescript
* [1, 2, 2, 3].filter(arr_uniq_p); // [1, 2, 3]
* ```
*
* @param el - The current element being tested.
* @param i - The index of the current element.
* @param source - The full array being filtered.
*
* @returns `true` if `el` is the first occurrence in `source`.
*
*/
declare function arr_uniq_p<T>(el: T, i: number, source: T[]): boolean;
/*******
*
* Wraps a string in an array, or passes through if already non-string.
* Used to normalize arguments that accept either a single state name or
* an array of state names.
*
* ```typescript
* array_box_if_string('hello'); // ['hello']
* array_box_if_string(['a','b']); // ['a','b']
* ```
*
* @param n - A string to box, or a value to pass through unchanged.
*
* @returns The input wrapped in an array if it was a string, otherwise the
* input unchanged.
*
*/
declare const array_box_if_string: (n: any) => any;
/*******
*
* Selects a single item from a weighted array of objects using cumulative
* probability. Each object in the array should have a numeric property
* indicating its relative weight (defaults to `'probability'`). Objects
* missing the property are treated as weight 1.
*
* ```typescript
* const opts = [
* { value: 'common', probability: 0.8 },
* { value: 'rare', probability: 0.2 }
* ];
*
* weighted_rand_select(opts); // most often { value: 'common', ... }
* ```
*
* @param options - Non-empty array of objects to choose from.
* @param probability_property - Name of the numeric weight property on each
* object. Defaults to `'probability'`.
* @param rng - Optional random number generator `() => number`
* in `[0, 1)`. Defaults to `Math.random`.
*
* @returns One element from `options`, chosen by weighted random selection.
*
* @throws {TypeError} If `options` is not a non-empty array of objects.
*
*/
declare const weighted_rand_select: Function;
/*******
*
* Returns, for a non-negative integer argument `n`, the series `[0 .. n]`.
*
* ```typescript
* import { seq } from './jssm';
*
* seq(5); // [0, 1, 2, 3, 4]
* seq(0); // []
* ```
*
*/
declare function seq(n: number): number[];
/*******
*
* Returns the histograph of an array as a `Map`. Makes no attempt to cope
* with deep equality; will fail for complex contents, as such.
*
* ```typescript
* import { histograph } from './jssm';
*
* histograph( [0, 0, 1, 1, 2, 2, 1] ); // Map()
* ```
*
*/
declare const histograph: Function;
/*******
*
* Draws `n` weighted random samples from an array of objects. Each draw is
* independent (with replacement), delegating to {@link weighted_rand_select}.
*
* ```typescript
* const opts = [
* { value: 'a', probability: 0.9 },
* { value: 'b', probability: 0.1 }
* ];
*
* weighted_sample_select(3, opts, 'probability');
* // e.g. [ { value: 'a', ... }, { value: 'a', ... }, { value: 'b', ... } ]
* ```
*
* @param n - Number of samples to draw.
* @param options - Non-empty array of weighted objects.
* @param probability_property - Name of the numeric weight property.
* @param rng - Optional random number generator.
*
* @returns An array of `n` independently selected items.
*
*/
declare const weighted_sample_select: Function;
/*******
*
* Draws `n` weighted random samples, extracts a named key from each, and
* returns a histograph (`Map`) of how often each key value appeared. Useful
* for validating that a probabilistic transition distribution is roughly
* correct over many trials.
*
* ```typescript
* const opts = [
* { to: 'a', probability: 0.7 },
* { to: 'b', probability: 0.3 }
* ];
*
* weighted_histo_key(1000, opts, 'probability', 'to');
* // Map { 'a' => ~700, 'b' => ~300 }
* ```
*
* @param n - Number of samples to draw.
* @param opts - Non-empty array of weighted objects.
* @param prob_prop - Name of the numeric weight property.
* @param extract - Name of the property to extract from each sample for
* histogramming.
* @param rng - Optional random number generator.
*
* @returns A `Map` from extracted key values to their occurrence counts.
*
*/
declare const weighted_histo_key: Function;
/*******
*
* Internal method generating composite keys for the hook lookup map by
* JSON-serializing a `[property, state]` pair. Not meant for external use.
*
* ```typescript
* name_bind_prop_and_state('color', 'Red'); // '["color","Red"]'
* ```
*
* @param prop - The property name (e.g. a data key or hook category).
* @param state - The state name to bind to.
*
* @returns A deterministic JSON string key for the `[prop, state]` pair.
*
* @throws {JssmError} If either argument is not a string.
*
*/
declare function name_bind_prop_and_state(prop: string, state: string): string;
/*******
*
* Internal method generating composite keys for transition hooks by
* JSON-serializing a `[from, to]` state pair. Used to look up hooks
* registered on a specific edge. Not meant for external use.
*
* ```typescript
* hook_name('Red', 'Green'); // '["Red","Green"]'
* ```
*
* @param from - The source state name.
* @param to - The target state name.
*
* @returns A deterministic JSON string key for the `[from, to]` pair.
*
*/
declare const hook_name: (from: string, to: string) => string;
/*******
*
* Internal method generating composite keys for named-action hooks by
* JSON-serializing a `[from, to, action]` triple. Used to look up hooks
* registered on a specific action-labeled edge. Not meant for external use.
*
* ```typescript
* named_hook_name('Red', 'Green', 'next'); // '["Red","Green","next"]'
* ```
*
* @param from - The source state name.
* @param to - The target state name.
* @param action - The action label on the edge.
*
* @returns A deterministic JSON string key for the `[from, to, action]` triple.
*
*/
declare const named_hook_name: (from: string, to: string, action: string) => string;
/*******
*
* Creates a SplitMix32 random generator. Used by the randomness test suite.
*
* Sourced from `bryc`: https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32
*
* Replaces the Mulberry generator, which was found to have problems
*
*/
declare function gen_splitmix32(a?: number | undefined): () => number;
/*******
*
* Reduces an array to its unique contents. Compares with `===` and makes no
* effort to deep-compare contents; two matching arrays or objects contained
* will be treated as distinct, according to javascript rules. This also means
* that `NaNs` will be ***dropped***, because they do not self-compare.
*
* ```typescript
* unique( [] ); // []
* unique( [0,0] ); // [0]
* unique( [0,1,2, 0,1,2, 0,1,2] ); // [0,1,2]
* unique( [ [1], [1] ] ); // [ [1], [1] ] because arrays don't match
* unique( [0,NaN,2] ); // [0,2]
* ```
*
*/
declare const unique: <T>(arr: T[]) => T[];
/*******
*
* Lists all repeated items in an array along with their counts. Subject to
* matching rules of Map. `NaN` is manually removed because of conflict rules
* around {@link unique}. Because these are compared with `===` and because
* arrays and objects never match that way unless they're the same object,
* arrays and objects are never considered repeats.
*
* ```typescript
* find_repeated<string>([ ]); // []
* find_repeated<string>([ "one" ]); // []
* find_repeated<string>([ "one", "two" ]); // []
* find_repeated<string>([ "one", "one" ]); // [ ["one", 2] ]
* find_repeated<string>([ "one", "two", "one" ]); // [ ["one", 2] ]
* find_repeated<number>([ 0, NaN, 0, NaN ]); // [ [0, 2] ]
* ```
*
*/
declare function find_repeated<T>(arr: T[]): [T, number][];
/*******
*
* Returns a `Promise` that resolves after `ms` milliseconds. Useful for
* inserting delays in async test flows or demos.
*
* ```typescript
* await sleep(100); // pauses execution for 100ms
* ```
*
* @param ms - Number of milliseconds to wait before resolving.
*
* @returns A `Promise<void>` that resolves after the timeout.
*
*/
declare function sleep(ms: number): Promise<unknown>;
export { seq, unique, find_repeated, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, name_bind_prop_and_state, hook_name, named_hook_name, gen_splitmix32, sleep };