jssm 5.112.3 → 5.113.0

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 (78) hide show
  1. package/README.md +3 -3
  2. package/dist/deno/README.md +347 -0
  3. package/dist/deno/jssm.js +1 -0
  4. package/dist/{es6 → deno}/jssm_constants.d.ts +5 -0
  5. package/dist/{es6 → deno}/jssm_types.d.ts +298 -5
  6. package/dist/jssm.es5.cjs +1 -1
  7. package/dist/jssm.es5.iife.js +1 -1
  8. package/dist/jssm.es6.mjs +1 -1
  9. package/dist/jssm_viz.cjs +1 -1
  10. package/dist/jssm_viz.iife.cjs +1 -1
  11. package/dist/jssm_viz.mjs +1 -1
  12. package/jssm.es5.d.cts +241 -2
  13. package/jssm.es6.d.ts +241 -2
  14. package/jssm_viz.es5.d.cts +216 -2
  15. package/jssm_viz.es6.d.ts +216 -2
  16. package/package.json +18 -2
  17. package/.clocignore +0 -1
  18. package/.codeclimate.yml +0 -22
  19. package/.editorconfig +0 -12
  20. package/.eslintrc +0 -20
  21. package/.gitattributes +0 -17
  22. package/.log-progress.json +0 -9
  23. package/.nycrc +0 -6
  24. package/.travis.yml +0 -9
  25. package/CHANGELOG.md +0 -263
  26. package/CLAUDE.md +0 -11
  27. package/dist/es6/fsl_parser.js +0 -1
  28. package/dist/es6/jssm.js +0 -3320
  29. package/dist/es6/jssm_arrow.js +0 -211
  30. package/dist/es6/jssm_compiler.js +0 -380
  31. package/dist/es6/jssm_constants.js +0 -121
  32. package/dist/es6/jssm_error.js +0 -47
  33. package/dist/es6/jssm_theme.js +0 -24
  34. package/dist/es6/jssm_types.js +0 -3
  35. package/dist/es6/jssm_util.js +0 -337
  36. package/dist/es6/jssm_viz.js +0 -560
  37. package/dist/es6/jssm_viz_colors.js +0 -63
  38. package/dist/es6/themes/jssm_base_stylesheet.d.ts +0 -11
  39. package/dist/es6/themes/jssm_base_stylesheet.js +0 -58
  40. package/dist/es6/themes/jssm_theme_bold.d.ts +0 -11
  41. package/dist/es6/themes/jssm_theme_bold.js +0 -58
  42. package/dist/es6/themes/jssm_theme_default.d.ts +0 -11
  43. package/dist/es6/themes/jssm_theme_default.js +0 -58
  44. package/dist/es6/themes/jssm_theme_modern.d.ts +0 -11
  45. package/dist/es6/themes/jssm_theme_modern.js +0 -58
  46. package/dist/es6/themes/jssm_theme_ocean.d.ts +0 -11
  47. package/dist/es6/themes/jssm_theme_ocean.js +0 -56
  48. package/dist/es6/themes/jssm_theme_plain.d.ts +0 -11
  49. package/dist/es6/themes/jssm_theme_plain.js +0 -70
  50. package/dist/es6/version.js +0 -2
  51. package/dist/jssm.es5.nonmin.cjs +0 -24506
  52. package/dist/jssm.es6.nonmin.cjs +0 -24473
  53. package/dist/jssm_viz.es5.iife.nonmin.cjs +0 -24679
  54. package/dist/jssm_viz.es5.nonmin.cjs +0 -24674
  55. package/dist/jssm_viz.es6.nonmin.cjs +0 -24661
  56. package/jest-dragon.config.cjs +0 -36
  57. package/jest-spec.config.cjs +0 -36
  58. package/jest-stoch.config.cjs +0 -36
  59. package/jest-unicode.config.cjs +0 -36
  60. package/log-progress.data.json +0 -28
  61. package/rollup.config.deno.js +0 -44
  62. package/rollup.config.es5.js +0 -52
  63. package/rollup.config.es6.js +0 -55
  64. package/rollup.config.viz.es5.js +0 -46
  65. package/rollup.config.viz.es6.js +0 -46
  66. package/rollup.config.viz.iife.js +0 -36
  67. package/tutorial_learn_testing.md +0 -168
  68. package/typedoc-options.cjs +0 -69
  69. /package/dist/{es6 → deno}/fsl_parser.d.ts +0 -0
  70. /package/dist/{es6 → deno}/jssm.d.ts +0 -0
  71. /package/dist/{es6 → deno}/jssm_arrow.d.ts +0 -0
  72. /package/dist/{es6 → deno}/jssm_compiler.d.ts +0 -0
  73. /package/dist/{es6 → deno}/jssm_error.d.ts +0 -0
  74. /package/dist/{es6 → deno}/jssm_theme.d.ts +0 -0
  75. /package/dist/{es6 → deno}/jssm_util.d.ts +0 -0
  76. /package/dist/{es6 → deno}/jssm_viz.d.ts +0 -0
  77. /package/dist/{es6 → deno}/jssm_viz_colors.d.ts +0 -0
  78. /package/dist/{es6 → deno}/version.d.ts +0 -0
@@ -1,121 +0,0 @@
1
- /*******
2
- *
3
- * Convenience aliases for common mathematical and numeric constants from
4
- * `Number` and `Math`. Re-exported so that FSL data expressions and tests
5
- * can reference them without importing `Math` directly.
6
- *
7
- * Includes: `NegInfinity`, `PosInfinity`, `Epsilon`, `Pi`, `E`, `Root2`,
8
- * `RootHalf`, `Ln2`, `Ln10`, `Log2E`, `Log10E`, `MaxSafeInt`, `MinSafeInt`,
9
- * `MaxPosNum`, `MinPosNum`, `Phi` (golden ratio), `EulerC` (Euler–Mascheroni).
10
- *
11
- */
12
- export const NegInfinity = Number.NEGATIVE_INFINITY, PosInfinity = Number.POSITIVE_INFINITY, Epsilon = Number.EPSILON, Pi = Math.PI, E = Math.E, Root2 = Math.SQRT2, RootHalf = Math.SQRT1_2, Ln2 = Math.LN2, Ln10 = Math.LN10, Log2E = Math.LOG2E, Log10E = Math.LOG10E, MaxSafeInt = Number.MAX_SAFE_INTEGER, MinSafeInt = Number.MIN_SAFE_INTEGER, MaxPosNum = Number.MAX_VALUE, MinPosNum = Number.MIN_VALUE, Phi = 1.61803398874989484820, EulerC = 0.57721566490153286060;
13
- /*******
14
- *
15
- * Complete list of node shapes supported by Graphviz. Used by jssm-viz to
16
- * validate and render state shapes in FSL `state ... : { shape: ... }` blocks.
17
- *
18
- * `shapes` is an alias for `gviz_shapes`.
19
- *
20
- */
21
- const gviz_shapes = [
22
- "box3d",
23
- "polygon",
24
- "ellipse",
25
- "oval",
26
- "circle",
27
- "point",
28
- "egg",
29
- "triangle",
30
- "plaintext",
31
- "plain",
32
- "diamond",
33
- "trapezium",
34
- "parallelogram",
35
- "house",
36
- "pentagon",
37
- "hexagon",
38
- "septagon",
39
- "octagon",
40
- "doublecircle",
41
- "doubleoctagon",
42
- "tripleoctagon",
43
- "invtriangle",
44
- "invtrapezium",
45
- "invhouse",
46
- "Mdiamond",
47
- "Msquare",
48
- "Mcircle",
49
- "rectangle",
50
- "rect",
51
- "square",
52
- "star",
53
- "none",
54
- "underline",
55
- "cylinder",
56
- "note",
57
- "tab",
58
- "folder",
59
- "box",
60
- "component",
61
- "promoter",
62
- "cds",
63
- "terminator",
64
- "utr",
65
- "primersite",
66
- "restrictionsite",
67
- "fivepoverhang",
68
- "threepoverhang",
69
- "noverhang",
70
- "assembly",
71
- "signature",
72
- "insulator",
73
- "ribosite",
74
- "rnastab",
75
- "proteasesite",
76
- "proteinstab",
77
- "rpromoter",
78
- "rarrow",
79
- "larrow",
80
- "lpromoter",
81
- "record"
82
- ];
83
- const shapes = gviz_shapes;
84
- /*******
85
- *
86
- * List of CSS/SVG named colors accepted by jssm-viz for state styling
87
- * properties like `background-color` and `text-color`. Case-insensitive
88
- * matching is done at parse time; the canonical casing here follows the
89
- * CSS specification.
90
- *
91
- */
92
- const named_colors = [
93
- "AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige",
94
- "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown",
95
- "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral",
96
- "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan",
97
- "DarkGoldenRod", "DarkGray", "DarkGrey", "DarkGreen", "DarkKhaki",
98
- "DarkMagenta", "DarkOliveGreen", "Darkorange", "DarkOrchid", "DarkRed",
99
- "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray",
100
- "DarkSlateGrey", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue",
101
- "DimGray", "DimGrey", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen",
102
- "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "GoldenRod", "Gray", "Grey",
103
- "Green", "GreenYellow", "HoneyDew", "HotPink", "IndianRed", "Indigo", "Ivory",
104
- "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon",
105
- "LightBlue", "LightCoral", "LightCyan", "LightGoldenRodYellow", "LightGray",
106
- "LightGrey", "LightGreen", "LightPink", "LightSalmon", "LightSeaGreen",
107
- "LightSkyBlue", "LightSlateGray", "LightSlateGrey", "LightSteelBlue",
108
- "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon",
109
- "MediumAquaMarine", "MediumBlue", "MediumOrchid", "MediumPurple",
110
- "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise",
111
- "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin",
112
- "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed",
113
- "Orchid", "PaleGoldenRod", "PaleGreen", "PaleTurquoise", "PaleVioletRed",
114
- "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple",
115
- "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown",
116
- "SeaGreen", "SeaShell", "Sienna", "Silver", "SkyBlue", "SlateBlue",
117
- "SlateGray", "SlateGrey", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal",
118
- "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke",
119
- "Yellow", "YellowGreen"
120
- ];
121
- export { gviz_shapes, shapes, named_colors, };
@@ -1,47 +0,0 @@
1
- /*******
2
- *
3
- * Custom error class for jssm. Enriches the standard `Error` with
4
- * machine context (current state, instance name) and an optional
5
- * `requested_state` so that error messages are self-describing.
6
- *
7
- * ```typescript
8
- * throw new JssmError(machine, 'no such state', { requested_state: 'Blue' });
9
- * // JssmError: [[my-light]]: no such state (at "Red", requested "Blue")
10
- * ```
11
- *
12
- * @param machine - The `Machine` instance that raised the error, or
13
- * `undefined` if no machine is available. Used to
14
- * read `state()` and `instance_name()` for context.
15
- * @param message - A human-readable description of the error.
16
- * @param JEEI - Optional {@link JssmErrorExtendedInfo} with extra
17
- * context such as `requested_state`.
18
- *
19
- */
20
- class JssmError extends Error {
21
- constructor(machine, message, JEEI) {
22
- const { requested_state } = (JEEI === undefined)
23
- ? { requested_state: undefined }
24
- : JEEI;
25
- const follow_ups = [];
26
- if (machine) {
27
- if (machine.state() !== undefined) {
28
- follow_ups.push(`at "${machine.state()}"`);
29
- }
30
- }
31
- if (requested_state !== undefined) {
32
- follow_ups.push(`requested "${requested_state}"`);
33
- }
34
- const complex_msg = `${((machine === null || machine === void 0 ? void 0 : machine.instance_name()) !== undefined)
35
- ? `[[${machine.instance_name()}]]: `
36
- : ''}${message}${follow_ups.length
37
- ? ` (${follow_ups.join(', ')})`
38
- : ''}`;
39
- super(complex_msg);
40
- this.name = 'JssmError';
41
- this.message = complex_msg;
42
- this.base_message = message;
43
- this.requested_state = requested_state;
44
- }
45
- }
46
- ;
47
- export { JssmError };
@@ -1,24 +0,0 @@
1
- import { base_theme } from './themes/jssm_base_stylesheet';
2
- import { default_theme } from './themes/jssm_theme_default';
3
- import { modern_theme } from './themes/jssm_theme_modern';
4
- import { ocean_theme } from './themes/jssm_theme_ocean';
5
- import { plain_theme } from './themes/jssm_theme_plain';
6
- import { bold_theme } from './themes/jssm_theme_bold';
7
- /*******
8
- *
9
- * Registry mapping theme names to their stylesheet definitions. Each entry
10
- * maps an {@link FslTheme} string (e.g. `'default'`, `'ocean'`) to a
11
- * {@link JssmBaseTheme} object containing colors, shapes, and other visual
12
- * defaults used by jssm-viz when rendering state machine diagrams.
13
- *
14
- * Add new themes by importing their definition and calling
15
- * `theme_mapping.set(name, theme)`.
16
- *
17
- */
18
- const theme_mapping = new Map();
19
- theme_mapping.set('default', default_theme);
20
- theme_mapping.set('modern', modern_theme);
21
- theme_mapping.set('ocean', ocean_theme);
22
- theme_mapping.set('plain', plain_theme);
23
- theme_mapping.set('bold', bold_theme);
24
- export { theme_mapping, base_theme };
@@ -1,3 +0,0 @@
1
- const FslDirections = ['up', 'right', 'down', 'left'];
2
- const FslThemes = ['default', 'ocean', 'modern', 'plain', 'bold'];
3
- export { FslDirections, FslThemes };
@@ -1,337 +0,0 @@
1
- import { JssmError } from './jssm_error';
2
- /*******
3
- *
4
- * Predicate for validating an array for uniqueness. Returns `true` when
5
- * `el` is the first occurrence in `source`, `false` otherwise. Intended
6
- * for use as an `Array.filter` callback. Not generally meant for external
7
- * use.
8
- *
9
- * ```typescript
10
- * [1, 2, 2, 3].filter(arr_uniq_p); // [1, 2, 3]
11
- * ```
12
- *
13
- * @param el - The current element being tested.
14
- * @param i - The index of the current element.
15
- * @param source - The full array being filtered.
16
- *
17
- * @returns `true` if `el` is the first occurrence in `source`.
18
- *
19
- */
20
- function arr_uniq_p(el, i, source) {
21
- return source.indexOf(el) === i;
22
- }
23
- /*******
24
- *
25
- * Wraps a string in an array, or passes through if already non-string.
26
- * Used to normalize arguments that accept either a single state name or
27
- * an array of state names.
28
- *
29
- * ```typescript
30
- * array_box_if_string('hello'); // ['hello']
31
- * array_box_if_string(['a','b']); // ['a','b']
32
- * ```
33
- *
34
- * @param n - A string to box, or a value to pass through unchanged.
35
- *
36
- * @returns The input wrapped in an array if it was a string, otherwise the
37
- * input unchanged.
38
- *
39
- */
40
- const array_box_if_string = n => typeof n === 'string' ? [n] : n;
41
- /*******
42
- *
43
- * Selects a single item from a weighted array of objects using cumulative
44
- * probability. Each object in the array should have a numeric property
45
- * indicating its relative weight (defaults to `'probability'`). Objects
46
- * missing the property are treated as weight 1.
47
- *
48
- * ```typescript
49
- * const opts = [
50
- * { value: 'common', probability: 0.8 },
51
- * { value: 'rare', probability: 0.2 }
52
- * ];
53
- *
54
- * weighted_rand_select(opts); // most often { value: 'common', ... }
55
- * ```
56
- *
57
- * @param options - Non-empty array of objects to choose from.
58
- * @param probability_property - Name of the numeric weight property on each
59
- * object. Defaults to `'probability'`.
60
- * @param rng - Optional random number generator `() => number`
61
- * in `[0, 1)`. Defaults to `Math.random`.
62
- *
63
- * @returns One element from `options`, chosen by weighted random selection.
64
- *
65
- * @throws {TypeError} If `options` is not a non-empty array of objects.
66
- *
67
- */
68
- // this is explicitly about other peoples' data, so it has to be weakly typed
69
- /* eslint-disable flowtype/no-weak-types */
70
- const weighted_rand_select = (options, probability_property = 'probability', rng) => {
71
- if (!Array.isArray(options)) {
72
- throw new TypeError('options must be a non-empty array of objects');
73
- }
74
- if (options.length === 0) {
75
- throw new TypeError('options must be a non-empty array of objects');
76
- }
77
- if (!(typeof options[0] === 'object')) {
78
- throw new TypeError('options must be a non-empty array of objects');
79
- }
80
- const frand = rng
81
- ? (cap) => rng() * cap
82
- : (cap) => Math.random() * cap, or_one = (item) => item === undefined ? 1 : item, prob_sum = options.reduce((acc, val) => acc + or_one(val[probability_property]), 0), rnd = frand(prob_sum);
83
- let cursor = 0, cursor_sum = 0;
84
- while (cursor < options.length && (cursor_sum += or_one(options[cursor++][probability_property])) <= rnd) { } // eslint-disable-line no-empty,fp/no-loops
85
- return options[cursor - 1];
86
- };
87
- /* eslint-enable flowtype/no-weak-types */
88
- /*******
89
- *
90
- * Returns, for a non-negative integer argument `n`, the series `[0 .. n]`.
91
- *
92
- * ```typescript
93
- * import { seq } from './jssm';
94
- *
95
- * seq(5); // [0, 1, 2, 3, 4]
96
- * seq(0); // []
97
- * ```
98
- *
99
- */
100
- function seq(n) {
101
- if (!(Number.isInteger(n))) {
102
- throw new TypeError('seq/1 takes a non-negative integer n as an argument');
103
- }
104
- if (n < 0) {
105
- throw new TypeError('seq/1 takes a non-negative integer n as an argument');
106
- }
107
- return (new Array(n))
108
- .fill(true)
109
- .map((_, i) => i);
110
- }
111
- /*******
112
- *
113
- * Returns the histograph of an array as a `Map`. Makes no attempt to cope
114
- * with deep equality; will fail for complex contents, as such.
115
- *
116
- * ```typescript
117
- * import { histograph } from './jssm';
118
- *
119
- * histograph( [0, 0, 1, 1, 2, 2, 1] ); // Map()
120
- * ```
121
- *
122
- */
123
- const histograph = (ar) => // eslint-disable-line flowtype/no-weak-types
124
- [...ar].sort()
125
- .reduce((m, v) => // TODO FIXME eslint-disable-line flowtype/no-weak-types,no-sequences
126
- (m.set(v, (m.has(v) ? m.get(v) + 1 : 1)), m), new Map());
127
- /*******
128
- *
129
- * Draws `n` weighted random samples from an array of objects. Each draw is
130
- * independent (with replacement), delegating to {@link weighted_rand_select}.
131
- *
132
- * ```typescript
133
- * const opts = [
134
- * { value: 'a', probability: 0.9 },
135
- * { value: 'b', probability: 0.1 }
136
- * ];
137
- *
138
- * weighted_sample_select(3, opts, 'probability');
139
- * // e.g. [ { value: 'a', ... }, { value: 'a', ... }, { value: 'b', ... } ]
140
- * ```
141
- *
142
- * @param n - Number of samples to draw.
143
- * @param options - Non-empty array of weighted objects.
144
- * @param probability_property - Name of the numeric weight property.
145
- * @param rng - Optional random number generator.
146
- *
147
- * @returns An array of `n` independently selected items.
148
- *
149
- */
150
- const weighted_sample_select = (n, options, probability_property, rng) => // TODO FIXME no any // eslint-disable-line flowtype/no-weak-types
151
- seq(n)
152
- .map((_i) => // TODO FIXME eslint-disable-line flowtype/no-weak-types
153
- weighted_rand_select(options, probability_property, rng));
154
- /*******
155
- *
156
- * Draws `n` weighted random samples, extracts a named key from each, and
157
- * returns a histograph (`Map`) of how often each key value appeared. Useful
158
- * for validating that a probabilistic transition distribution is roughly
159
- * correct over many trials.
160
- *
161
- * ```typescript
162
- * const opts = [
163
- * { to: 'a', probability: 0.7 },
164
- * { to: 'b', probability: 0.3 }
165
- * ];
166
- *
167
- * weighted_histo_key(1000, opts, 'probability', 'to');
168
- * // Map { 'a' => ~700, 'b' => ~300 }
169
- * ```
170
- *
171
- * @param n - Number of samples to draw.
172
- * @param opts - Non-empty array of weighted objects.
173
- * @param prob_prop - Name of the numeric weight property.
174
- * @param extract - Name of the property to extract from each sample for
175
- * histogramming.
176
- * @param rng - Optional random number generator.
177
- *
178
- * @returns A `Map` from extracted key values to their occurrence counts.
179
- *
180
- */
181
- const weighted_histo_key = (n, opts, prob_prop, extract, rng) => // TODO FIXME no any // eslint-disable-line flowtype/no-weak-types
182
- histograph(weighted_sample_select(n, opts, prob_prop, rng)
183
- .map((s) => s[extract] // TODO FIXME eslint-disable-line flowtype/no-weak-types
184
- ));
185
- /*******
186
- *
187
- * Internal method generating composite keys for the hook lookup map by
188
- * JSON-serializing a `[property, state]` pair. Not meant for external use.
189
- *
190
- * ```typescript
191
- * name_bind_prop_and_state('color', 'Red'); // '["color","Red"]'
192
- * ```
193
- *
194
- * @param prop - The property name (e.g. a data key or hook category).
195
- * @param state - The state name to bind to.
196
- *
197
- * @returns A deterministic JSON string key for the `[prop, state]` pair.
198
- *
199
- * @throws {JssmError} If either argument is not a string.
200
- *
201
- */
202
- function name_bind_prop_and_state(prop, state) {
203
- if (typeof prop !== 'string') {
204
- throw new JssmError(undefined, `Name of property must be a string; got ${prop}`);
205
- }
206
- if (typeof state !== 'string') {
207
- throw new JssmError(undefined, `Name of state must be a string; got ${state}`);
208
- }
209
- return JSON.stringify([prop, state]);
210
- }
211
- /*******
212
- *
213
- * Internal method generating composite keys for transition hooks by
214
- * JSON-serializing a `[from, to]` state pair. Used to look up hooks
215
- * registered on a specific edge. Not meant for external use.
216
- *
217
- * ```typescript
218
- * hook_name('Red', 'Green'); // '["Red","Green"]'
219
- * ```
220
- *
221
- * @param from - The source state name.
222
- * @param to - The target state name.
223
- *
224
- * @returns A deterministic JSON string key for the `[from, to]` pair.
225
- *
226
- */
227
- const hook_name = (from, to) => JSON.stringify([from, to]);
228
- /*******
229
- *
230
- * Internal method generating composite keys for named-action hooks by
231
- * JSON-serializing a `[from, to, action]` triple. Used to look up hooks
232
- * registered on a specific action-labeled edge. Not meant for external use.
233
- *
234
- * ```typescript
235
- * named_hook_name('Red', 'Green', 'next'); // '["Red","Green","next"]'
236
- * ```
237
- *
238
- * @param from - The source state name.
239
- * @param to - The target state name.
240
- * @param action - The action label on the edge.
241
- *
242
- * @returns A deterministic JSON string key for the `[from, to, action]` triple.
243
- *
244
- */
245
- const named_hook_name = (from, to, action) => JSON.stringify([from, to, action]);
246
- /*******
247
- *
248
- * Creates a SplitMix32 random generator. Used by the randomness test suite.
249
- *
250
- * Sourced from `bryc`: https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32
251
- *
252
- * Replaces the Mulberry generator, which was found to have problems
253
- *
254
- */
255
- function gen_splitmix32(a) {
256
- if (a === undefined) {
257
- a = new Date().getTime();
258
- }
259
- return function () {
260
- a |= 0;
261
- a = a + 0x9e3779b9 | 0;
262
- let t = a ^ a >>> 16;
263
- t = Math.imul(t, 0x21f0aaad);
264
- t = t ^ t >>> 15;
265
- t = Math.imul(t, 0x735a2d97);
266
- return ((t = t ^ t >>> 15) >>> 0) / 4294967296;
267
- };
268
- }
269
- /*******
270
- *
271
- * Reduces an array to its unique contents. Compares with `===` and makes no
272
- * effort to deep-compare contents; two matching arrays or objects contained
273
- * will be treated as distinct, according to javascript rules. This also means
274
- * that `NaNs` will be ***dropped***, because they do not self-compare.
275
- *
276
- * ```typescript
277
- * unique( [] ); // []
278
- * unique( [0,0] ); // [0]
279
- * unique( [0,1,2, 0,1,2, 0,1,2] ); // [0,1,2]
280
- * unique( [ [1], [1] ] ); // [ [1], [1] ] because arrays don't match
281
- * unique( [0,NaN,2] ); // [0,2]
282
- * ```
283
- *
284
- */
285
- const unique = (arr) => arr.filter((v, i, a) => a.indexOf(v) === i);
286
- /*******
287
- *
288
- * Lists all repeated items in an array along with their counts. Subject to
289
- * matching rules of Map. `NaN` is manually removed because of conflict rules
290
- * around {@link unique}. Because these are compared with `===` and because
291
- * arrays and objects never match that way unless they're the same object,
292
- * arrays and objects are never considered repeats.
293
- *
294
- * ```typescript
295
- * find_repeated<string>([ ]); // []
296
- * find_repeated<string>([ "one" ]); // []
297
- * find_repeated<string>([ "one", "two" ]); // []
298
- * find_repeated<string>([ "one", "one" ]); // [ ["one", 2] ]
299
- * find_repeated<string>([ "one", "two", "one" ]); // [ ["one", 2] ]
300
- * find_repeated<number>([ 0, NaN, 0, NaN ]); // [ [0, 2] ]
301
- * ```
302
- *
303
- */
304
- function find_repeated(arr) {
305
- const uniqued = unique(arr);
306
- if (uniqued.length !== arr.length) {
307
- const residue_keys = new Map();
308
- arr.forEach(k => residue_keys.set(k, residue_keys.has(k)
309
- ? (residue_keys.get(k) + 1)
310
- : 1));
311
- uniqued.forEach(k => residue_keys.set(k, residue_keys.get(k) - 1));
312
- return [...residue_keys.entries()]
313
- .filter((e) => ((e[1] > 0) && (!(Number.isNaN(e[0])))))
314
- .map((e) => [e[0], e[1] + 1]);
315
- }
316
- else {
317
- return [];
318
- }
319
- }
320
- /*******
321
- *
322
- * Returns a `Promise` that resolves after `ms` milliseconds. Useful for
323
- * inserting delays in async test flows or demos.
324
- *
325
- * ```typescript
326
- * await sleep(100); // pauses execution for 100ms
327
- * ```
328
- *
329
- * @param ms - Number of milliseconds to wait before resolving.
330
- *
331
- * @returns A `Promise<void>` that resolves after the timeout.
332
- *
333
- */
334
- function sleep(ms) {
335
- return new Promise(resolve => setTimeout(resolve, ms));
336
- }
337
- 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 };