@ncfour-us/stats 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2026 Tim Hahn
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # replace this
@@ -0,0 +1,36 @@
1
+ import { ILogger } from '@ncfour-us/logging';
2
+ import { SampleSet } from './sample-set.js';
3
+ /**
4
+ * The options for instantiating a Normal distribution SampleSet.
5
+ */
6
+ export interface NormalSampleSetOptions {
7
+ /**
8
+ * number of smaples to generate, default 1000
9
+ */
10
+ numSamples?: number;
11
+ /**
12
+ * optional mean value, default 0
13
+ */
14
+ mean?: number;
15
+ /**
16
+ * optional standard deviation value, default 1
17
+ */
18
+ stddev?: number;
19
+ /**
20
+ * optional logger to use.
21
+ */
22
+ logger?: ILogger;
23
+ }
24
+ /**
25
+ * Class to create a Normal distribution SampleSet
26
+ * with values in the range (-infinity,infinity),
27
+ * with default mean 0 and default standard deviation 1.
28
+ */
29
+ export declare class NormalSampleSet extends SampleSet {
30
+ /**
31
+ * Create a new NormalSampleSet instance.
32
+ *
33
+ * @param options See {@link NormalSampleSetOptions}
34
+ */
35
+ constructor(options: NormalSampleSetOptions);
36
+ }
@@ -0,0 +1,43 @@
1
+ // Copyright (c) 2026 Tim Hahn
2
+ import { SampleSet } from './sample-set.js';
3
+ import { UniformSampleSet } from './uniform-sample-set.js';
4
+ ;
5
+ /**
6
+ * Class to create a Normal distribution SampleSet
7
+ * with values in the range (-infinity,infinity),
8
+ * with default mean 0 and default standard deviation 1.
9
+ */
10
+ export class NormalSampleSet extends SampleSet {
11
+ /**
12
+ * Create a new NormalSampleSet instance.
13
+ *
14
+ * @param options See {@link NormalSampleSetOptions}
15
+ */
16
+ constructor(options) {
17
+ super({
18
+ logger: options.logger,
19
+ });
20
+ // Create a Normal distribution using the Box-Muller transform method.
21
+ //
22
+ // For information on this method, refer to: https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
23
+ const U1 = new UniformSampleSet({
24
+ numSamples: options.numSamples ?? 1000,
25
+ });
26
+ const U2 = new UniformSampleSet({
27
+ numSamples: options.numSamples ?? 1000,
28
+ });
29
+ const u1 = U1.getValues();
30
+ const u2 = U2.getValues();
31
+ const z0 = u1.map((u1Value, index) => {
32
+ return Math.sqrt(-2.0 * Math.log(u1Value)) * Math.cos(2.0 * Math.PI * u2[index]);
33
+ });
34
+ // const z1 = u1.map( (u1Value, index) => {
35
+ // return Math.sqrt(-2.0*Math.log(u1Value))*Math.sin(2.0*Math.PI*u2[index])
36
+ // });
37
+ const mean = options.mean ?? 0;
38
+ const stddev = options.stddev ?? 1;
39
+ this.addValues(z0.map((value) => mean + (value) * (stddev)));
40
+ this.logger?.trace(`NormalSampleSet.constructor: numSamples: ${this.getNumSamples()}`);
41
+ }
42
+ }
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9ybWFsLXNhbXBsZS1zZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcG9uZW50cy9ub3JtYWwtc2FtcGxlLXNldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw4QkFBOEI7QUFHOUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBMkIxRCxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxlQUFnQixTQUFRLFNBQVM7SUFFNUM7Ozs7T0FJRztJQUNILFlBQVksT0FBK0I7UUFFekMsS0FBSyxDQUFDO1lBQ0osTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1NBQ3ZCLENBQUMsQ0FBQztRQUVILHNFQUFzRTtRQUN0RSxFQUFFO1FBQ0YsdUdBQXVHO1FBRXZHLE1BQU0sRUFBRSxHQUFHLElBQUksZ0JBQWdCLENBQUM7WUFDOUIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksSUFBSTtTQUN2QyxDQUFDLENBQUM7UUFDSCxNQUFNLEVBQUUsR0FBRyxJQUFJLGdCQUFnQixDQUFDO1lBQzlCLFVBQVUsRUFBRSxPQUFPLENBQUMsVUFBVSxJQUFJLElBQUk7U0FDdkMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBYyxDQUFDO1FBQ3RDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxTQUFTLEVBQWMsQ0FBQztRQUV0QyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFFLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3BDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsR0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUMsSUFBSSxDQUFDLEVBQUUsR0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUMzRSxDQUFDLENBQUMsQ0FBQztRQUVILDJDQUEyQztRQUMzQyw2RUFBNkU7UUFDN0UsTUFBTTtRQUNOLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQy9CLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO1FBRW5DLElBQUksQ0FBQyxTQUFTLENBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFFLENBQUM7UUFFN0QsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsNENBQTRDLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFekYsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDI2IFRpbSBIYWhuXG5cbmltcG9ydCB7IElMb2dnZXIgfSBmcm9tICdAbmNmb3VyLXVzL2xvZ2dpbmcnO1xuaW1wb3J0IHsgU2FtcGxlU2V0IH0gZnJvbSAnLi9zYW1wbGUtc2V0LmpzJztcbmltcG9ydCB7IFVuaWZvcm1TYW1wbGVTZXQgfSBmcm9tICcuL3VuaWZvcm0tc2FtcGxlLXNldC5qcyc7XG5cbi8qKlxuICogVGhlIG9wdGlvbnMgZm9yIGluc3RhbnRpYXRpbmcgYSBOb3JtYWwgZGlzdHJpYnV0aW9uIFNhbXBsZVNldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOb3JtYWxTYW1wbGVTZXRPcHRpb25zIHtcblxuICAvKipcbiAgICogbnVtYmVyIG9mIHNtYXBsZXMgdG8gZ2VuZXJhdGUsIGRlZmF1bHQgMTAwMFxuICAgKi9cbiAgbnVtU2FtcGxlcz86IG51bWJlcjtcblxuICAvKipcbiAgICogb3B0aW9uYWwgbWVhbiB2YWx1ZSwgZGVmYXVsdCAwXG4gICAqL1xuICBtZWFuPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBvcHRpb25hbCBzdGFuZGFyZCBkZXZpYXRpb24gdmFsdWUsIGRlZmF1bHQgMVxuICAgKi9cbiAgc3RkZGV2PzogbnVtYmVyO1xuXG4gIC8vIGRlcGVuZGVuY2llc1xuICAvKipcbiAgICogb3B0aW9uYWwgbG9nZ2VyIHRvIHVzZS5cbiAgICovXG4gIGxvZ2dlcj86IElMb2dnZXI7XG59O1xuXG4vKipcbiAqIENsYXNzIHRvIGNyZWF0ZSBhIE5vcm1hbCBkaXN0cmlidXRpb24gU2FtcGxlU2V0XG4gKiB3aXRoIHZhbHVlcyBpbiB0aGUgcmFuZ2UgKC1pbmZpbml0eSxpbmZpbml0eSksXG4gKiB3aXRoIGRlZmF1bHQgbWVhbiAwIGFuZCBkZWZhdWx0IHN0YW5kYXJkIGRldmlhdGlvbiAxLlxuICovXG5leHBvcnQgY2xhc3MgTm9ybWFsU2FtcGxlU2V0IGV4dGVuZHMgU2FtcGxlU2V0IHtcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IE5vcm1hbFNhbXBsZVNldCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgU2VlIHtAbGluayBOb3JtYWxTYW1wbGVTZXRPcHRpb25zfVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9uczogTm9ybWFsU2FtcGxlU2V0T3B0aW9ucykge1xuXG4gICAgc3VwZXIoe1xuICAgICAgbG9nZ2VyOiBvcHRpb25zLmxvZ2dlcixcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBhIE5vcm1hbCBkaXN0cmlidXRpb24gdXNpbmcgdGhlIEJveC1NdWxsZXIgdHJhbnNmb3JtIG1ldGhvZC5cbiAgICAvL1xuICAgIC8vIEZvciBpbmZvcm1hdGlvbiBvbiB0aGlzIG1ldGhvZCwgcmVmZXIgdG86IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0JveCVFMiU4MCU5M011bGxlcl90cmFuc2Zvcm1cblxuICAgIGNvbnN0IFUxID0gbmV3IFVuaWZvcm1TYW1wbGVTZXQoe1xuICAgICAgbnVtU2FtcGxlczogb3B0aW9ucy5udW1TYW1wbGVzID8/IDEwMDAsXG4gICAgfSk7XG4gICAgY29uc3QgVTIgPSBuZXcgVW5pZm9ybVNhbXBsZVNldCh7XG4gICAgICBudW1TYW1wbGVzOiBvcHRpb25zLm51bVNhbXBsZXMgPz8gMTAwMCxcbiAgICB9KTtcblxuICAgIGNvbnN0IHUxID0gVTEuZ2V0VmFsdWVzKCkgYXMgbnVtYmVyW107XG4gICAgY29uc3QgdTIgPSBVMi5nZXRWYWx1ZXMoKSBhcyBudW1iZXJbXTtcblxuICAgIGNvbnN0IHowID0gdTEubWFwKCAodTFWYWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgIHJldHVybiBNYXRoLnNxcnQoLTIuMCpNYXRoLmxvZyh1MVZhbHVlKSkqTWF0aC5jb3MoMi4wKk1hdGguUEkqdTJbaW5kZXhdKTtcbiAgICB9KTtcblxuICAgIC8vIGNvbnN0IHoxID0gdTEubWFwKCAodTFWYWx1ZSwgaW5kZXgpID0+IHtcbiAgICAvLyAgIHJldHVybiBNYXRoLnNxcnQoLTIuMCpNYXRoLmxvZyh1MVZhbHVlKSkqTWF0aC5zaW4oMi4wKk1hdGguUEkqdTJbaW5kZXhdKVxuICAgIC8vIH0pO1xuICAgIGNvbnN0IG1lYW4gPSBvcHRpb25zLm1lYW4gPz8gMDtcbiAgICBjb25zdCBzdGRkZXYgPSBvcHRpb25zLnN0ZGRldiA/PyAxO1xuXG4gICAgdGhpcy5hZGRWYWx1ZXMoIHowLm1hcCgodmFsdWUpID0+IG1lYW4gKyAodmFsdWUpKihzdGRkZXYpKSApO1xuXG4gICAgdGhpcy5sb2dnZXI/LnRyYWNlKGBOb3JtYWxTYW1wbGVTZXQuY29uc3RydWN0b3I6IG51bVNhbXBsZXM6ICR7dGhpcy5nZXROdW1TYW1wbGVzKCl9YCk7XG5cbiAgfVxufVxuIl19
@@ -0,0 +1,11 @@
1
+ import { ILogger } from '@ncfour-us/logging';
2
+ import { SampleSet } from './sample-set.js';
3
+ export interface NormalSetOptions {
4
+ numSamples?: number;
5
+ min?: number;
6
+ max?: number;
7
+ logger?: ILogger;
8
+ }
9
+ export declare class NormalSet extends SampleSet {
10
+ constructor(options: NormalSetOptions);
11
+ }
@@ -0,0 +1,18 @@
1
+ // Copyright (c) 2026 Tim Hahn
2
+ import { SampleSet } from './sample-set.js';
3
+ ;
4
+ export class NormalSet extends SampleSet {
5
+ constructor(options) {
6
+ super({
7
+ logger: options.logger,
8
+ });
9
+ this.addValues(Array.from({ length: options.numSamples ?? 1000 }, (_element, _index) => {
10
+ const min = options.min ?? 0;
11
+ const max = options.max ?? 1;
12
+ const newVal = min + (max - min) * Math.random();
13
+ return newVal;
14
+ }));
15
+ this.logger?.trace(`NormalSet.constructor: numSamples: ${this.getNumSamples()}`);
16
+ }
17
+ }
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9ybWFsLXNldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL25vcm1hbC1zZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsOEJBQThCO0FBRzlCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQVMzQyxDQUFDO0FBRUYsTUFBTSxPQUFPLFNBQVUsU0FBUSxTQUFTO0lBRXRDLFlBQVksT0FBeUI7UUFFbkMsS0FBSyxDQUFDO1lBQ0osTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1NBQ3ZCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsVUFBVSxJQUFJLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JGLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQzdCLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1lBRTdCLE1BQU0sTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBQyxHQUFHLENBQUMsR0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFN0MsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVKLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLHNDQUFzQyxJQUFJLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRW5GLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAyNiBUaW0gSGFoblxuXG5pbXBvcnQgeyBJTG9nZ2VyIH0gZnJvbSAnQG5jZm91ci11cy9sb2dnaW5nJztcbmltcG9ydCB7IFNhbXBsZVNldCB9IGZyb20gJy4vc2FtcGxlLXNldC5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm9ybWFsU2V0T3B0aW9ucyB7XG4gIG51bVNhbXBsZXM/OiBudW1iZXI7XG4gIG1pbj86IG51bWJlcjtcbiAgbWF4PzogbnVtYmVyO1xuXG4gIC8vIGRlcGVuZGVuY2llc1xuICBsb2dnZXI/OiBJTG9nZ2VyO1xufTtcblxuZXhwb3J0IGNsYXNzIE5vcm1hbFNldCBleHRlbmRzIFNhbXBsZVNldCB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogTm9ybWFsU2V0T3B0aW9ucykge1xuXG4gICAgc3VwZXIoe1xuICAgICAgbG9nZ2VyOiBvcHRpb25zLmxvZ2dlcixcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkVmFsdWVzKEFycmF5LmZyb20oeyBsZW5ndGg6IG9wdGlvbnMubnVtU2FtcGxlcyA/PyAxMDAwIH0sIChfZWxlbWVudCwgX2luZGV4KSA9PiB7XG4gICAgICBjb25zdCBtaW4gPSBvcHRpb25zLm1pbiA/PyAwO1xuICAgICAgY29uc3QgbWF4ID0gb3B0aW9ucy5tYXggPz8gMTtcblxuICAgICAgY29uc3QgbmV3VmFsID0gbWluICsgKG1heC1taW4pKk1hdGgucmFuZG9tKCk7XG5cbiAgICAgIHJldHVybiBuZXdWYWw7XG4gICAgfSkpO1xuXG4gICAgdGhpcy5sb2dnZXI/LnRyYWNlKGBOb3JtYWxTZXQuY29uc3RydWN0b3I6IG51bVNhbXBsZXM6ICR7dGhpcy5nZXROdW1TYW1wbGVzKCl9YCk7XG5cbiAgfVxufVxuIl19
@@ -0,0 +1,172 @@
1
+ import { ILogger } from '@ncfour-us/logging';
2
+ /**
3
+ * SampleBucket is used to represent the calculated
4
+ * distribution for the SampleSet.
5
+ */
6
+ export declare class SampleBucket {
7
+ min: number;
8
+ max: number;
9
+ midPoint: number;
10
+ count: number;
11
+ constructor(min: number, max: number, count: number);
12
+ }
13
+ /**
14
+ * The type of values stored in the SampleSet
15
+ */
16
+ export type SampleSetValue = number | string;
17
+ /**
18
+ * SampleSetPercentiles represents the calculated percentiles
19
+ * for the values in the SampleSet.
20
+ */
21
+ export interface SampleSetPercentiles {
22
+ 0: SampleSetValue;
23
+ 25: SampleSetValue;
24
+ 50: SampleSetValue;
25
+ 75: SampleSetValue;
26
+ 100: SampleSetValue;
27
+ }
28
+ /**
29
+ * The options for instantiating the SampleSet.
30
+ */
31
+ export interface SampleSetOptions {
32
+ /**
33
+ * optional initial set of values to put into the SampleSet
34
+ */
35
+ initialValues?: SampleSetValue[];
36
+ /**
37
+ * optional logger to use.
38
+ */
39
+ logger?: ILogger;
40
+ }
41
+ /**
42
+ * Base class to represent samples of a random variable
43
+ * in the stats package.
44
+ *
45
+ * Other calculated distributions are based on this base
46
+ * class. However, instances of the base class can be
47
+ * created as well, if a set of random values exists to
48
+ * initialize the SampleSet.
49
+ */
50
+ export declare class SampleSet {
51
+ protected logger?: ILogger;
52
+ private valuesNumeric;
53
+ private values;
54
+ private dictionary;
55
+ private recalculate;
56
+ private mean;
57
+ private median;
58
+ private mode;
59
+ private variance;
60
+ private stddev;
61
+ private max;
62
+ private min;
63
+ private percentile25;
64
+ private percentile75;
65
+ private distribution;
66
+ /**
67
+ * Create a new SampleSet instance.
68
+ *
69
+ * @param options See {@link SampleSetOptions}
70
+ */
71
+ constructor(options: SampleSetOptions);
72
+ /**
73
+ * get the array of values held in the SampleSet.
74
+ *
75
+ * @returns SampleSetValue[] - array of SampleSetValue
76
+ */
77
+ getValues(): SampleSetValue[];
78
+ /**
79
+ * get a specific value, by index, held in the SampleSet.
80
+ *
81
+ * @returns SampleSetValue
82
+ */
83
+ getValue(index: number): SampleSetValue | undefined;
84
+ /**
85
+ * Replace the set of values held in the SampleSet
86
+ */
87
+ setValues(values: SampleSetValue[]): void;
88
+ /**
89
+ * Add values to the SampleSet
90
+ *
91
+ * @param values values to add to the SampleSet
92
+ */
93
+ addValues(values: SampleSetValue[]): void;
94
+ /**
95
+ * Add a single value to the SampleSet
96
+ *
97
+ * @param value value to add to the SampleSet
98
+ */
99
+ addValue(value: SampleSetValue): void;
100
+ /**
101
+ * Get the mean value of the SampleSet. For string
102
+ * values, this is ordered by string sorting rules.
103
+ *
104
+ * @returns SampleSetValue - mean value of the SampleSet
105
+ */
106
+ getMean(): SampleSetValue;
107
+ /**
108
+ * Get the median value of the SampleSet. For string
109
+ * values, this is ordered by string sorting rules.
110
+ *
111
+ * @returns SampleSetValue - median value of the SampleSet
112
+ */
113
+ getMedian(): SampleSetValue;
114
+ /**
115
+ * Get the mode value of the SampleSet. For string
116
+ * values, this is ordered by string sorting rules.
117
+ *
118
+ * @returns SampleSetValue - mode value of the SampleSet
119
+ */
120
+ getMode(): SampleSetValue;
121
+ /**
122
+ * Get the minimum value of the SampleSet. For string
123
+ * values, this is ordered by string sorting rules.
124
+ *
125
+ * @returns SampleSetValue - minimum value of the SampleSet
126
+ */
127
+ getMin(): SampleSetValue;
128
+ /**
129
+ * Get the maximum value of the SampleSet. For string
130
+ * values, this is ordered by string sorting rules.
131
+ *
132
+ * @returns SampleSetValue - maximum value of the SampleSet
133
+ */
134
+ getMax(): SampleSetValue;
135
+ /**
136
+ * Get the variance value of the SampleSet. For string
137
+ * values, this is the variance across the size of the SampleSet [0,sampleSet.getNumSamples()-1].
138
+ *
139
+ * @returns number - Calculated variance of the SampleSet
140
+ */
141
+ getVariance(): number;
142
+ /**
143
+ * Get the percentiles values for the SampleSet.
144
+ *
145
+ * @returns sampleSetPercentiles - the 0, 25, 50, 75, and 100th percential values for the SampleSet.
146
+ */
147
+ getPercentiles(): SampleSetPercentiles;
148
+ /**
149
+ * Get the standard deviation value of the SampleSet. For string
150
+ * values, this is the standard deviation across the size of the
151
+ * SampleSet [0,sampleSet.getNumSamples()-1].
152
+ *
153
+ * @returns number - Calculated standard deviation of the SampleSet
154
+ */
155
+ getStddev(): number;
156
+ /**
157
+ * Get the type of values in the SampleSet
158
+ *
159
+ * @returns true if numeric values, false if string values
160
+ */
161
+ isNumeric(): boolean;
162
+ /**
163
+ * Get the number of values in the SampleSet
164
+ *
165
+ * @returns number of samples in the SampleSet
166
+ */
167
+ getNumSamples(): number;
168
+ private recalculateStats;
169
+ private calcMean;
170
+ private calcVariance;
171
+ private calcFromSortedValues;
172
+ }
@@ -0,0 +1,429 @@
1
+ // Copyright (c) 2026 Tim Hahn
2
+ /**
3
+ * SampleBucket is used to represent the calculated
4
+ * distribution for the SampleSet.
5
+ */
6
+ export class SampleBucket {
7
+ min;
8
+ max;
9
+ midPoint;
10
+ count;
11
+ constructor(min, max, count) {
12
+ this.min = min;
13
+ this.max = max;
14
+ this.midPoint = this.min + (this.max - this.min) / 2;
15
+ this.count = count;
16
+ }
17
+ }
18
+ ;
19
+ /**
20
+ * Base class to represent samples of a random variable
21
+ * in the stats package.
22
+ *
23
+ * Other calculated distributions are based on this base
24
+ * class. However, instances of the base class can be
25
+ * created as well, if a set of random values exists to
26
+ * initialize the SampleSet.
27
+ */
28
+ export class SampleSet {
29
+ // dependencies
30
+ logger;
31
+ // sample data
32
+ valuesNumeric;
33
+ values;
34
+ dictionary;
35
+ // calculated items
36
+ recalculate; // sets whether or not re-calculation is needed
37
+ mean;
38
+ median;
39
+ mode;
40
+ variance;
41
+ stddev;
42
+ max;
43
+ min;
44
+ percentile25;
45
+ percentile75;
46
+ distribution;
47
+ /**
48
+ * Create a new SampleSet instance.
49
+ *
50
+ * @param options See {@link SampleSetOptions}
51
+ */
52
+ constructor(options) {
53
+ // dependencies
54
+ this.logger = options.logger;
55
+ // intialize information
56
+ this.recalculate = true;
57
+ this.mean = 0;
58
+ this.median = 0;
59
+ this.mode = 0;
60
+ this.variance = 0;
61
+ this.stddev = 0;
62
+ this.min = 0;
63
+ this.max = 0;
64
+ this.percentile25 = 0;
65
+ this.percentile75 = 0;
66
+ this.distribution = [];
67
+ // initialize values
68
+ this.valuesNumeric = true;
69
+ this.values = [];
70
+ this.dictionary = [];
71
+ if (options.initialValues) {
72
+ this.setValues(options.initialValues);
73
+ }
74
+ this.logger?.trace(`SampleSet.constructor: numSamples: ${this.values.length}`);
75
+ }
76
+ /**
77
+ * get the array of values held in the SampleSet.
78
+ *
79
+ * @returns SampleSetValue[] - array of SampleSetValue
80
+ */
81
+ getValues() {
82
+ let retVals;
83
+ if (this.valuesNumeric) {
84
+ retVals = this.values.map((value) => value);
85
+ }
86
+ else {
87
+ retVals = this.values.map((value) => this.dictionary[value]);
88
+ }
89
+ return retVals;
90
+ }
91
+ /**
92
+ * get a specific value, by index, held in the SampleSet.
93
+ *
94
+ * @returns SampleSetValue
95
+ */
96
+ getValue(index) {
97
+ let retVal;
98
+ if (index < 0 || index >= this.values.length) {
99
+ return undefined;
100
+ }
101
+ if (this.valuesNumeric) {
102
+ retVal = this.values[index];
103
+ }
104
+ else {
105
+ retVal = this.dictionary[this.values[index]];
106
+ }
107
+ return retVal;
108
+ }
109
+ /**
110
+ * Replace the set of values held in the SampleSet
111
+ */
112
+ setValues(values) {
113
+ this.values = [];
114
+ this.dictionary = [];
115
+ this.logger?.trace(`SampleSet.setValues: typeof value: ${typeof values[0]}`);
116
+ if (values.length > 0 && typeof values[0] === 'string') {
117
+ this.valuesNumeric = false;
118
+ }
119
+ else {
120
+ this.valuesNumeric = true;
121
+ }
122
+ this.addValues(values);
123
+ this.recalculate = true;
124
+ }
125
+ /**
126
+ * Add values to the SampleSet
127
+ *
128
+ * @param values values to add to the SampleSet
129
+ */
130
+ addValues(values) {
131
+ if (this.values.length > 0 &&
132
+ (typeof values[0] === 'string' && this.valuesNumeric) ||
133
+ (typeof values[0] === 'number' && !this.valuesNumeric)) {
134
+ // type mismatch on values being added - quietly IGNORE
135
+ this.logger?.error(`SampleSet.addValues: type mismatch on values added, valuesNumeric: ${this.valuesNumeric}, values type: ${typeof values[0]}`);
136
+ return;
137
+ }
138
+ if (values.length > 0 && typeof values[0] === 'string') {
139
+ this.valuesNumeric = false;
140
+ values.forEach((value) => {
141
+ const existingItemIndex = this.dictionary.findIndex((dictItem) => dictItem === value);
142
+ if (existingItemIndex >= 0) {
143
+ // item found in dictionary
144
+ this.values.push(existingItemIndex);
145
+ }
146
+ else {
147
+ // add to dictionary
148
+ this.dictionary.push(value);
149
+ this.values.push(this.dictionary.length - 1);
150
+ }
151
+ });
152
+ this.logger?.trace(`SampleSet.addValues: resulting dictionary: ${this.dictionary}`);
153
+ }
154
+ else {
155
+ // number values
156
+ this.valuesNumeric = true;
157
+ this.values = values.map((value) => value);
158
+ }
159
+ this.logger?.trace(`SampleSet.addValues: new numSamples: ${this.values.length}`);
160
+ this.recalculate = true;
161
+ }
162
+ /**
163
+ * Add a single value to the SampleSet
164
+ *
165
+ * @param value value to add to the SampleSet
166
+ */
167
+ addValue(value) {
168
+ if (this.values.length > 0 &&
169
+ (typeof value === 'string' && this.valuesNumeric) ||
170
+ (typeof value === 'number' && !this.valuesNumeric)) {
171
+ // type mismatch on values being added - quietly IGNORE
172
+ this.logger?.error(`SampleSet.addValue: type mismatch on value added, valuesNumeric: ${this.valuesNumeric}, values type: ${typeof value}`);
173
+ return;
174
+ }
175
+ if (typeof value === 'string') {
176
+ const existingItemIndex = this.dictionary.findIndex((dictItem) => dictItem === value);
177
+ if (existingItemIndex > 0) {
178
+ // item found in dictionary
179
+ this.values.push(existingItemIndex);
180
+ }
181
+ else {
182
+ // add to dictionary
183
+ this.dictionary.push(value);
184
+ this.values.push(this.dictionary.length - 1);
185
+ }
186
+ }
187
+ else {
188
+ this.values.push(value);
189
+ }
190
+ this.recalculate = true;
191
+ }
192
+ /**
193
+ * Get the mean value of the SampleSet. For string
194
+ * values, this is ordered by string sorting rules.
195
+ *
196
+ * @returns SampleSetValue - mean value of the SampleSet
197
+ */
198
+ getMean() {
199
+ if (this.recalculate) {
200
+ this.recalculateStats();
201
+ }
202
+ return this.valuesNumeric ? this.mean : this.dictionary[this.mean];
203
+ }
204
+ /**
205
+ * Get the median value of the SampleSet. For string
206
+ * values, this is ordered by string sorting rules.
207
+ *
208
+ * @returns SampleSetValue - median value of the SampleSet
209
+ */
210
+ getMedian() {
211
+ if (this.recalculate) {
212
+ this.recalculateStats();
213
+ }
214
+ return this.valuesNumeric ? this.median : this.dictionary[this.median];
215
+ }
216
+ /**
217
+ * Get the mode value of the SampleSet. For string
218
+ * values, this is ordered by string sorting rules.
219
+ *
220
+ * @returns SampleSetValue - mode value of the SampleSet
221
+ */
222
+ getMode() {
223
+ if (this.recalculate) {
224
+ this.recalculateStats();
225
+ }
226
+ return this.valuesNumeric ? this.mode : this.dictionary[this.mode];
227
+ }
228
+ /**
229
+ * Get the minimum value of the SampleSet. For string
230
+ * values, this is ordered by string sorting rules.
231
+ *
232
+ * @returns SampleSetValue - minimum value of the SampleSet
233
+ */
234
+ getMin() {
235
+ if (this.recalculate) {
236
+ this.recalculateStats();
237
+ }
238
+ return this.valuesNumeric ? this.min : this.dictionary[this.min];
239
+ }
240
+ /**
241
+ * Get the maximum value of the SampleSet. For string
242
+ * values, this is ordered by string sorting rules.
243
+ *
244
+ * @returns SampleSetValue - maximum value of the SampleSet
245
+ */
246
+ getMax() {
247
+ if (this.recalculate) {
248
+ this.recalculateStats();
249
+ }
250
+ return this.valuesNumeric ? this.max : this.dictionary[this.max];
251
+ }
252
+ /**
253
+ * Get the variance value of the SampleSet. For string
254
+ * values, this is the variance across the size of the SampleSet [0,sampleSet.getNumSamples()-1].
255
+ *
256
+ * @returns number - Calculated variance of the SampleSet
257
+ */
258
+ getVariance() {
259
+ if (this.recalculate) {
260
+ this.recalculateStats();
261
+ }
262
+ return this.variance;
263
+ }
264
+ /**
265
+ * Get the percentiles values for the SampleSet.
266
+ *
267
+ * @returns sampleSetPercentiles - the 0, 25, 50, 75, and 100th percential values for the SampleSet.
268
+ */
269
+ getPercentiles() {
270
+ if (this.recalculate) {
271
+ this.recalculateStats();
272
+ }
273
+ return {
274
+ 0: this.valuesNumeric ? this.min : this.dictionary[this.min],
275
+ 25: this.valuesNumeric ? this.percentile25 : this.dictionary[this.percentile25],
276
+ 50: this.valuesNumeric ? this.median : this.dictionary[this.median],
277
+ 75: this.valuesNumeric ? this.percentile75 : this.dictionary[this.percentile75],
278
+ 100: this.valuesNumeric ? this.max : this.dictionary[this.max],
279
+ };
280
+ }
281
+ /**
282
+ * Get the standard deviation value of the SampleSet. For string
283
+ * values, this is the standard deviation across the size of the
284
+ * SampleSet [0,sampleSet.getNumSamples()-1].
285
+ *
286
+ * @returns number - Calculated standard deviation of the SampleSet
287
+ */
288
+ getStddev() {
289
+ if (this.recalculate) {
290
+ this.recalculateStats();
291
+ }
292
+ return this.stddev;
293
+ }
294
+ /**
295
+ * Get the type of values in the SampleSet
296
+ *
297
+ * @returns true if numeric values, false if string values
298
+ */
299
+ isNumeric() {
300
+ return this.valuesNumeric;
301
+ }
302
+ /**
303
+ * Get the number of values in the SampleSet
304
+ *
305
+ * @returns number of samples in the SampleSet
306
+ */
307
+ getNumSamples() {
308
+ return this.values.length;
309
+ }
310
+ recalculateStats() {
311
+ this.calcMean();
312
+ this.calcVariance();
313
+ this.calcFromSortedValues();
314
+ this.recalculate = false;
315
+ }
316
+ calcMean() {
317
+ this.mean = this.values.reduce((sum, value) => sum + value, 0) / this.values.length;
318
+ this.mean = this.valuesNumeric ? this.mean : Math.round(this.mean);
319
+ }
320
+ // Calculates the variance and standard deviation
321
+ // NOTE - this function ASSUMES that the mean has already been recalculated
322
+ calcVariance() {
323
+ this.variance = this.values.reduce((sum, value) => sum + ((value - this.mean) * (value - this.mean)), 0) / this.values.length;
324
+ this.stddev = Math.sqrt(this.variance);
325
+ }
326
+ // Calculates median, mode, and distribution
327
+ calcFromSortedValues() {
328
+ // sort the values
329
+ let sortedValues;
330
+ if (this.valuesNumeric) {
331
+ // the default sort function is appropriate
332
+ sortedValues = this.values.toSorted((a, b) => a < b ?
333
+ -1 :
334
+ a > b ?
335
+ 1 :
336
+ 0);
337
+ this.logger?.trace(`SampleSet.calcFromSortedValues: sortedValues: ${sortedValues}`);
338
+ }
339
+ else {
340
+ // need to sort based on dictionary lookup
341
+ sortedValues = this.values.toSorted((a, b) => this.dictionary[a] < this.dictionary[b] ?
342
+ -1 :
343
+ (this.dictionary[a] > this.dictionary[b] ?
344
+ 1 :
345
+ 0));
346
+ this.logger?.trace(`SampleSet.calcFromSortedValues: sortedValues: ${sortedValues.map((value) => this.dictionary[value])}`);
347
+ }
348
+ // get the median
349
+ const midPointIndex = Math.trunc((this.values.length - 1) / 2);
350
+ this.median = sortedValues[midPointIndex];
351
+ this.logger?.trace(`SampleSet.calcFromSortedValues: midPointIndex: ${midPointIndex}`);
352
+ // get the min and max values
353
+ this.min = sortedValues[0];
354
+ this.max = sortedValues[sortedValues.length - 1];
355
+ // get the percentile25 and percentile50 values
356
+ let percentileIndex = Math.trunc((this.values.length - 1) / 4);
357
+ this.percentile25 = sortedValues[percentileIndex];
358
+ percentileIndex = Math.trunc((this.values.length - 1) * (3 / 4));
359
+ this.percentile75 = sortedValues[percentileIndex];
360
+ // create the distribution histogram/table
361
+ this.distribution = [];
362
+ if (this.valuesNumeric) {
363
+ // in this case, create buckets of equal size which span the range [min, max)
364
+ // and count the number of values in each range
365
+ // Use the sqrt(numSamples) rule of thumb for calculating the number of buckets
366
+ const numBuckets = Math.trunc(Math.sqrt(this.values.length) + 1);
367
+ const bucketSize = (this.max - this.min) / numBuckets;
368
+ let currentMin = sortedValues[0];
369
+ let currentMax = currentMin + bucketSize;
370
+ if (currentMax === this.max) {
371
+ // VERY unlikely - but just in case, add a very small amount so as not to have a
372
+ // bucket of one with only the max value at the end.
373
+ currentMax += 1e-10;
374
+ }
375
+ let count = 0;
376
+ for (let i = 0; i < sortedValues.length; i++) {
377
+ if (sortedValues[i] >= currentMin && sortedValues[i] < currentMax) {
378
+ count++;
379
+ }
380
+ else {
381
+ this.distribution.push(new SampleBucket(currentMin, currentMax, count));
382
+ currentMin += bucketSize;
383
+ currentMax = currentMin + bucketSize;
384
+ if (currentMax === this.max) {
385
+ // VERY unlikely - but just in case, add a very small amount so as not to have a
386
+ // bucket of one with only the max value at the end.
387
+ currentMax += 1e-10;
388
+ }
389
+ count = 1;
390
+ }
391
+ }
392
+ this.distribution.push(new SampleBucket(currentMin, currentMax, count));
393
+ // numBuckets and distribution.length should match
394
+ this.logger?.trace(`SampleSet.calcFromSortedValues: numeric data, numBuckets: ${numBuckets}, distribution.length: ${this.distribution.length}`);
395
+ }
396
+ else {
397
+ // in this case, the number of buckets matches the number of strings in the SampleSet
398
+ // which is the size of the dictionary
399
+ let currentValue = sortedValues[0];
400
+ let count = 0;
401
+ for (let i = 0; i < sortedValues.length; i++) {
402
+ if (sortedValues[i] === currentValue) {
403
+ count++;
404
+ }
405
+ else {
406
+ this.distribution.push(new SampleBucket(currentValue, currentValue, count));
407
+ currentValue = sortedValues[i];
408
+ count = 1;
409
+ }
410
+ }
411
+ this.distribution.push(new SampleBucket(currentValue, currentValue, count));
412
+ // dictionary.length and distribution.length should match
413
+ this.logger?.trace(`SampleSet.calcFromSortedValues: string data, dictionary.length: ${this.dictionary.length}, distribution.length: ${this.distribution.length}`);
414
+ this.logger?.trace(`SampleSet.calcFromSortedValues: dictionary: ${this.dictionary}`);
415
+ }
416
+ this.logger?.trace(`SampleSet.calcFromSortedValues: numeric: ${this.valuesNumeric}, distribution details: ${JSON.stringify(this.distribution, null, 2)}`);
417
+ // calculate the mode
418
+ const maxDistributionBucketIndex = this.distribution.reduce((curMaxIndex, bucket, index) => bucket.count > this.distribution[curMaxIndex].count ? index : curMaxIndex, 0);
419
+ if (this.valuesNumeric) {
420
+ this.mode = this.distribution[maxDistributionBucketIndex].min +
421
+ (this.distribution[maxDistributionBucketIndex].max - this.distribution[maxDistributionBucketIndex].min) / 2;
422
+ }
423
+ else {
424
+ this.mode = this.distribution[maxDistributionBucketIndex].min;
425
+ }
426
+ this.logger?.trace(`SampleSet.calcFromSortedValues: mode: ${this.mode}`);
427
+ }
428
+ }
429
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2FtcGxlLXNldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL3NhbXBsZS1zZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsOEJBQThCO0FBSTlCOzs7R0FHRztBQUNILE1BQU0sT0FBTyxZQUFZO0lBQ2hCLEdBQUcsQ0FBUztJQUNaLEdBQUcsQ0FBUztJQUNaLFFBQVEsQ0FBUztJQUNqQixLQUFLLENBQVM7SUFFckIsWUFBWSxHQUFXLEVBQUUsR0FBVyxFQUFFLEtBQWE7UUFDakQsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFDLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNyQixDQUFDO0NBQ0Y7QUFrQ0EsQ0FBQztBQUVGOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLFNBQVM7SUFDcEIsZUFBZTtJQUNMLE1BQU0sQ0FBVztJQUUzQixjQUFjO0lBQ04sYUFBYSxDQUFVO0lBQ3ZCLE1BQU0sQ0FBVztJQUNqQixVQUFVLENBQVc7SUFFN0IsbUJBQW1CO0lBQ1gsV0FBVyxDQUFVLENBQUMsK0NBQStDO0lBQ3JFLElBQUksQ0FBUztJQUNiLE1BQU0sQ0FBUztJQUNmLElBQUksQ0FBUztJQUNiLFFBQVEsQ0FBUztJQUNqQixNQUFNLENBQVM7SUFDZixHQUFHLENBQVM7SUFDWixHQUFHLENBQVM7SUFDWixZQUFZLENBQVM7SUFDckIsWUFBWSxDQUFTO0lBQ3JCLFlBQVksQ0FBaUI7SUFFckM7Ozs7T0FJRztJQUNILFlBQVksT0FBeUI7UUFDbkMsZUFBZTtRQUNmLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1B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KSAyMDI2IFRpbSBIYWhuXG5cbmltcG9ydCB7IElMb2dnZXIgfSBmcm9tICdAbmNmb3VyLXVzL2xvZ2dpbmcnO1xuXG4vKipcbiAqIFNhbXBsZUJ1Y2tldCBpcyB1c2VkIHRvIHJlcHJlc2VudCB0aGUgY2FsY3VsYXRlZFxuICogZGlzdHJpYnV0aW9uIGZvciB0aGUgU2FtcGxlU2V0LlxuICovXG5leHBvcnQgY2xhc3MgU2FtcGxlQnVja2V0IHtcbiAgcHVibGljIG1pbjogbnVtYmVyO1xuICBwdWJsaWMgbWF4OiBudW1iZXI7XG4gIHB1YmxpYyBtaWRQb2ludDogbnVtYmVyO1xuICBwdWJsaWMgY291bnQ6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihtaW46IG51bWJlciwgbWF4OiBudW1iZXIsIGNvdW50OiBudW1iZXIpIHtcbiAgICB0aGlzLm1pbiA9IG1pbjtcbiAgICB0aGlzLm1heCA9IG1heDtcbiAgICB0aGlzLm1pZFBvaW50ID0gdGhpcy5taW4gKyAodGhpcy5tYXgtdGhpcy5taW4pLzI7XG4gICAgdGhpcy5jb3VudCA9IGNvdW50O1xuICB9XG59XG5cbi8qKlxuICogVGhlIHR5cGUgb2YgdmFsdWVzIHN0b3JlZCBpbiB0aGUgU2FtcGxlU2V0XG4gKi9cbmV4cG9ydCB0eXBlIFNhbXBsZVNldFZhbHVlID0gbnVtYmVyIHwgc3RyaW5nO1xuXG4vKipcbiAqIFNhbXBsZVNldFBlcmNlbnRpbGVzIHJlcHJlc2VudHMgdGhlIGNhbGN1bGF0ZWQgcGVyY2VudGlsZXNcbiAqIGZvciB0aGUgdmFsdWVzIGluIHRoZSBTYW1wbGVTZXQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2FtcGxlU2V0UGVyY2VudGlsZXMge1xuICAwOiBTYW1wbGVTZXRWYWx1ZTtcbiAgMjU6IFNhbXBsZVNldFZhbHVlO1xuICA1MDogU2FtcGxlU2V0VmFsdWU7XG4gIDc1OiBTYW1wbGVTZXRWYWx1ZTtcbiAgMTAwOiBTYW1wbGVTZXRWYWx1ZTtcbn1cblxuLyoqXG4gKiBUaGUgb3B0aW9ucyBmb3IgaW5zdGFudGlhdGluZyB0aGUgU2FtcGxlU2V0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNhbXBsZVNldE9wdGlvbnMge1xuXG4gIC8qKlxuICAgKiBvcHRpb25hbCBpbml0aWFsIHNldCBvZiB2YWx1ZXMgdG8gcHV0IGludG8gdGhlIFNhbXBsZVNldFxuICAgKi9cbiAgaW5pdGlhbFZhbHVlcz86IFNhbXBsZVNldFZhbHVlW107XG5cbiAgLy8gZGVwZW5kZW5jaWVzXG4gIC8qKlxuICAgKiBvcHRpb25hbCBsb2dnZXIgdG8gdXNlLlxuICAgKi9cbiAgbG9nZ2VyPzogSUxvZ2dlcjtcbn07XG5cbi8qKlxuICogQmFzZSBjbGFzcyB0byByZXByZXNlbnQgc2FtcGxlcyBvZiBhIHJhbmRvbSB2YXJpYWJsZVxuICogaW4gdGhlIHN0YXRzIHBhY2thZ2UuXG4gKlxuICogT3RoZXIgY2FsY3VsYXRlZCBkaXN0cmlidXRpb25zIGFyZSBiYXNlZCBvbiB0aGlzIGJhc2VcbiAqIGNsYXNzLiAgSG93ZXZlciwgaW5zdGFuY2VzIG9mIHRoZSBiYXNlIGNsYXNzIGNhbiBiZVxuICogY3JlYXRlZCBhcyB3ZWxsLCBpZiBhIHNldCBvZiByYW5kb20gdmFsdWVzIGV4aXN0cyB0b1xuICogaW5pdGlhbGl6ZSB0aGUgU2FtcGxlU2V0LlxuICovXG5leHBvcnQgY2xhc3MgU2FtcGxlU2V0IHtcbiAgLy8gZGVwZW5kZW5jaWVzXG4gIHByb3RlY3RlZCBsb2dnZXI/OiBJTG9nZ2VyO1xuXG4gIC8vIHNhbXBsZSBkYXRhXG4gIHByaXZhdGUgdmFsdWVzTnVtZXJpYzogYm9vbGVhbjtcbiAgcHJpdmF0ZSB2YWx1ZXM6IG51bWJlcltdO1xuICBwcml2YXRlIGRpY3Rpb25hcnk6IHN0cmluZ1tdO1xuXG4gIC8vIGNhbGN1bGF0ZWQgaXRlbXNcbiAgcHJpdmF0ZSByZWNhbGN1bGF0ZTogYm9vbGVhbjsgLy8gc2V0cyB3aGV0aGVyIG9yIG5vdCByZS1jYWxjdWxhdGlvbiBpcyBuZWVkZWRcbiAgcHJpdmF0ZSBtZWFuOiBudW1iZXI7XG4gIHByaXZhdGUgbWVkaWFuOiBudW1iZXI7XG4gIHByaXZhdGUgbW9kZTogbnVtYmVyO1xuICBwcml2YXRlIHZhcmlhbmNlOiBudW1iZXI7XG4gIHByaXZhdGUgc3RkZGV2OiBudW1iZXI7XG4gIHByaXZhdGUgbWF4OiBudW1iZXI7XG4gIHByaXZhdGUgbWluOiBudW1iZXI7XG4gIHByaXZhdGUgcGVyY2VudGlsZTI1OiBudW1iZXI7XG4gIHByaXZhdGUgcGVyY2VudGlsZTc1OiBudW1iZXI7XG4gIHByaXZhdGUgZGlzdHJpYnV0aW9uOiBTYW1wbGVCdWNrZXRbXTtcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IFNhbXBsZVNldCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgU2VlIHtAbGluayBTYW1wbGVTZXRPcHRpb25zfVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9uczogU2FtcGxlU2V0T3B0aW9ucykge1xuICAgIC8vIGRlcGVuZGVuY2llc1xuICAgIHRoaXMubG9nZ2VyID0gb3B0aW9ucy5sb2dnZXI7XG5cbiAgICAvLyBpbnRpYWxpemUgaW5mb3JtYXRpb25cbiAgICB0aGlzLnJlY2FsY3VsYXRlID0gdHJ1ZTtcbiAgICB0aGlzLm1lYW4gPSAwO1xuICAgIHRoaXMubWVkaWFuID0gMDtcbiAgICB0aGlzLm1vZGUgPSAwO1xuICAgIHRoaXMudmFyaWFuY2UgPSAwO1xuICAgIHRoaXMuc3RkZGV2ID0gMDtcbiAgICB0aGlzLm1pbiA9IDA7XG4gICAgdGhpcy5tYXggPSAwO1xuICAgIHRoaXMucGVyY2VudGlsZTI1ID0gMDtcbiAgICB0aGlzLnBlcmNlbnRpbGU3NSA9IDA7XG4gICAgdGhpcy5kaXN0cmlidXRpb24gPSBbXTtcblxuICAgIC8vIGluaXRpYWxpemUgdmFsdWVzXG4gICAgdGhpcy52YWx1ZXNOdW1lcmljID0gdHJ1ZTtcbiAgICB0aGlzLnZhbHVlcyA9IChbXSBhcyBudW1iZXJbXSk7XG4gICAgdGhpcy5kaWN0aW9uYXJ5ID0gKFtdIGFzIHN0cmluZ1tdKTtcbiAgICBpZiAob3B0aW9ucy5pbml0aWFsVmFsdWVzKSB7XG4gICAgICB0aGlzLnNldFZhbHVlcyhvcHRpb25zLmluaXRpYWxWYWx1ZXMpO1xuICAgIH1cblxuICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmNvbnN0cnVjdG9yOiBudW1TYW1wbGVzOiAke3RoaXMudmFsdWVzLmxlbmd0aH1gKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIGdldCB0aGUgYXJyYXkgb2YgdmFsdWVzIGhlbGQgaW4gdGhlIFNhbXBsZVNldC5cbiAgICpcbiAgICogQHJldHVybnMgU2FtcGxlU2V0VmFsdWVbXSAtIGFycmF5IG9mIFNhbXBsZVNldFZhbHVlXG4gICAqL1xuICBwdWJsaWMgZ2V0VmFsdWVzKCk6IFNhbXBsZVNldFZhbHVlW10ge1xuICAgIGxldCByZXRWYWxzOiBTYW1wbGVTZXRWYWx1ZVtdO1xuICAgIGlmICh0aGlzLnZhbHVlc051bWVyaWMpIHtcbiAgICAgIHJldFZhbHMgPSB0aGlzLnZhbHVlcy5tYXAoKHZhbHVlKSA9PiB2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldFZhbHMgPSB0aGlzLnZhbHVlcy5tYXAoKHZhbHVlKSA9PiB0aGlzLmRpY3Rpb25hcnlbdmFsdWVdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0VmFscztcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgYSBzcGVjaWZpYyB2YWx1ZSwgYnkgaW5kZXgsIGhlbGQgaW4gdGhlIFNhbXBsZVNldC5cbiAgICpcbiAgICogQHJldHVybnMgU2FtcGxlU2V0VmFsdWVcbiAgICovXG4gIHB1YmxpYyBnZXRWYWx1ZShpbmRleDogbnVtYmVyKTogU2FtcGxlU2V0VmFsdWUgfCB1bmRlZmluZWQge1xuICAgIGxldCByZXRWYWw6IFNhbXBsZVNldFZhbHVlO1xuXG4gICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+PSB0aGlzLnZhbHVlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudmFsdWVzTnVtZXJpYykge1xuICAgICAgcmV0VmFsID0gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXRWYWwgPSB0aGlzLmRpY3Rpb25hcnlbdGhpcy52YWx1ZXNbaW5kZXhdXTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmV0VmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2UgdGhlIHNldCBvZiB2YWx1ZXMgaGVsZCBpbiB0aGUgU2FtcGxlU2V0XG4gICAqL1xuICBwdWJsaWMgc2V0VmFsdWVzKHZhbHVlczogU2FtcGxlU2V0VmFsdWVbXSk6IHZvaWQge1xuICAgIHRoaXMudmFsdWVzID0gW10gYXMgbnVtYmVyW107XG4gICAgdGhpcy5kaWN0aW9uYXJ5ID0gW10gYXMgc3RyaW5nW107XG5cbiAgICB0aGlzLmxvZ2dlcj8udHJhY2UoYFNhbXBsZVNldC5zZXRWYWx1ZXM6IHR5cGVvZiB2YWx1ZTogJHt0eXBlb2YgdmFsdWVzWzBdfWApO1xuXG4gICAgaWYgKHZhbHVlcy5sZW5ndGggPiAwICYmIHR5cGVvZiB2YWx1ZXNbMF0gPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLnZhbHVlc051bWVyaWMgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52YWx1ZXNOdW1lcmljID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZFZhbHVlcyh2YWx1ZXMpO1xuXG4gICAgdGhpcy5yZWNhbGN1bGF0ZSA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHZhbHVlcyB0byB0aGUgU2FtcGxlU2V0XG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZXMgdmFsdWVzIHRvIGFkZCB0byB0aGUgU2FtcGxlU2V0XG4gICAqL1xuICBwdWJsaWMgYWRkVmFsdWVzKHZhbHVlczogU2FtcGxlU2V0VmFsdWVbXSApOiB2b2lkIHtcbiAgICBpZiAoIHRoaXMudmFsdWVzLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgKCB0eXBlb2YgdmFsdWVzWzBdID09PSAnc3RyaW5nJyAmJiB0aGlzLnZhbHVlc051bWVyaWMgKSB8fFxuICAgICAgICAoIHR5cGVvZiB2YWx1ZXNbMF0gPT09ICdudW1iZXInICYmICF0aGlzLnZhbHVlc051bWVyaWMgKSApIHtcbiAgICAgIC8vIHR5cGUgbWlzbWF0Y2ggb24gdmFsdWVzIGJlaW5nIGFkZGVkIC0gcXVpZXRseSBJR05PUkVcbiAgICAgIHRoaXMubG9nZ2VyPy5lcnJvcihgU2FtcGxlU2V0LmFkZFZhbHVlczogdHlwZSBtaXNtYXRjaCBvbiB2YWx1ZXMgYWRkZWQsIHZhbHVlc051bWVyaWM6ICR7dGhpcy52YWx1ZXNOdW1lcmljfSwgdmFsdWVzIHR5cGU6ICR7dHlwZW9mIHZhbHVlc1swXX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDAgJiYgdHlwZW9mIHZhbHVlc1swXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMudmFsdWVzTnVtZXJpYyA9IGZhbHNlO1xuXG4gICAgICAodmFsdWVzIGFzIHN0cmluZ1tdKS5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xuICAgICAgICBjb25zdCBleGlzdGluZ0l0ZW1JbmRleCA9IHRoaXMuZGljdGlvbmFyeS5maW5kSW5kZXgoKGRpY3RJdGVtKSA9PiBkaWN0SXRlbSA9PT0gdmFsdWUpO1xuICAgICAgICBpZiAoZXhpc3RpbmdJdGVtSW5kZXggPj0gMCkge1xuICAgICAgICAgIC8vIGl0ZW0gZm91bmQgaW4gZGljdGlvbmFyeVxuICAgICAgICAgIHRoaXMudmFsdWVzLnB1c2goZXhpc3RpbmdJdGVtSW5kZXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGFkZCB0byBkaWN0aW9uYXJ5XG4gICAgICAgICAgdGhpcy5kaWN0aW9uYXJ5LnB1c2godmFsdWUpO1xuICAgICAgICAgIHRoaXMudmFsdWVzLnB1c2godGhpcy5kaWN0aW9uYXJ5Lmxlbmd0aC0xKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmFkZFZhbHVlczogcmVzdWx0aW5nIGRpY3Rpb25hcnk6ICR7dGhpcy5kaWN0aW9uYXJ5fWApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBudW1iZXIgdmFsdWVzXG4gICAgICB0aGlzLnZhbHVlc051bWVyaWMgPSB0cnVlO1xuICAgICAgdGhpcy52YWx1ZXMgPSAodmFsdWVzIGFzIG51bWJlcltdKS5tYXAoKHZhbHVlKSA9PiB2YWx1ZSkgYXMgbnVtYmVyW107XG4gICAgfVxuXG4gICAgdGhpcy5sb2dnZXI/LnRyYWNlKGBTYW1wbGVTZXQuYWRkVmFsdWVzOiBuZXcgbnVtU2FtcGxlczogJHt0aGlzLnZhbHVlcy5sZW5ndGh9YCk7XG5cbiAgICB0aGlzLnJlY2FsY3VsYXRlID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBzaW5nbGUgdmFsdWUgdG8gdGhlIFNhbXBsZVNldFxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgdG8gYWRkIHRvIHRoZSBTYW1wbGVTZXRcbiAgICovXG4gIHB1YmxpYyBhZGRWYWx1ZSh2YWx1ZTogU2FtcGxlU2V0VmFsdWUpIHtcbiAgICBpZiAoIHRoaXMudmFsdWVzLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgKCB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHRoaXMudmFsdWVzTnVtZXJpYyApIHx8XG4gICAgICAgICggdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiAhdGhpcy52YWx1ZXNOdW1lcmljICkgKSB7XG4gICAgICAvLyB0eXBlIG1pc21hdGNoIG9uIHZhbHVlcyBiZWluZyBhZGRlZCAtIHF1aWV0bHkgSUdOT1JFXG4gICAgICB0aGlzLmxvZ2dlcj8uZXJyb3IoYFNhbXBsZVNldC5hZGRWYWx1ZTogdHlwZSBtaXNtYXRjaCBvbiB2YWx1ZSBhZGRlZCwgdmFsdWVzTnVtZXJpYzogJHt0aGlzLnZhbHVlc051bWVyaWN9LCB2YWx1ZXMgdHlwZTogJHt0eXBlb2YgdmFsdWV9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nSXRlbUluZGV4ID0gdGhpcy5kaWN0aW9uYXJ5LmZpbmRJbmRleCgoZGljdEl0ZW0pID0+IGRpY3RJdGVtID09PSB2YWx1ZSk7XG4gICAgICBpZiAoZXhpc3RpbmdJdGVtSW5kZXggPiAwKSB7XG4gICAgICAgIC8vIGl0ZW0gZm91bmQgaW4gZGljdGlvbmFyeVxuICAgICAgICB0aGlzLnZhbHVlcy5wdXNoKGV4aXN0aW5nSXRlbUluZGV4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGFkZCB0byBkaWN0aW9uYXJ5XG4gICAgICAgIHRoaXMuZGljdGlvbmFyeS5wdXNoKHZhbHVlKTtcbiAgICAgICAgdGhpcy52YWx1ZXMucHVzaCh0aGlzLmRpY3Rpb25hcnkubGVuZ3RoLTEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlY2FsY3VsYXRlID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG1lYW4gdmFsdWUgb2YgdGhlIFNhbXBsZVNldC4gIEZvciBzdHJpbmdcbiAgICogdmFsdWVzLCB0aGlzIGlzIG9yZGVyZWQgYnkgc3RyaW5nIHNvcnRpbmcgcnVsZXMuXG4gICAqXG4gICAqIEByZXR1cm5zIFNhbXBsZVNldFZhbHVlIC0gbWVhbiB2YWx1ZSBvZiB0aGUgU2FtcGxlU2V0XG4gICAqL1xuICBwdWJsaWMgZ2V0TWVhbigpOiBTYW1wbGVTZXRWYWx1ZSB7XG4gICAgaWYgKHRoaXMucmVjYWxjdWxhdGUpIHtcbiAgICAgIHRoaXMucmVjYWxjdWxhdGVTdGF0cygpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZXNOdW1lcmljID8gdGhpcy5tZWFuIDogdGhpcy5kaWN0aW9uYXJ5W3RoaXMubWVhbl07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBtZWRpYW4gdmFsdWUgb2YgdGhlIFNhbXBsZVNldC4gIEZvciBzdHJpbmdcbiAgICogdmFsdWVzLCB0aGlzIGlzIG9yZGVyZWQgYnkgc3RyaW5nIHNvcnRpbmcgcnVsZXMuXG4gICAqXG4gICAqIEByZXR1cm5zIFNhbXBsZVNldFZhbHVlIC0gbWVkaWFuIHZhbHVlIG9mIHRoZSBTYW1wbGVTZXRcbiAgICovXG4gIHB1YmxpYyBnZXRNZWRpYW4oKTogU2FtcGxlU2V0VmFsdWUge1xuICAgIGlmICh0aGlzLnJlY2FsY3VsYXRlKSB7XG4gICAgICB0aGlzLnJlY2FsY3VsYXRlU3RhdHMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzTnVtZXJpYyA/IHRoaXMubWVkaWFuIDogdGhpcy5kaWN0aW9uYXJ5W3RoaXMubWVkaWFuXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG1vZGUgdmFsdWUgb2YgdGhlIFNhbXBsZVNldC4gIEZvciBzdHJpbmdcbiAgICogdmFsdWVzLCB0aGlzIGlzIG9yZGVyZWQgYnkgc3RyaW5nIHNvcnRpbmcgcnVsZXMuXG4gICAqXG4gICAqIEByZXR1cm5zIFNhbXBsZVNldFZhbHVlIC0gbW9kZSB2YWx1ZSBvZiB0aGUgU2FtcGxlU2V0XG4gICAqL1xuICBwdWJsaWMgZ2V0TW9kZSgpOiBTYW1wbGVTZXRWYWx1ZSB7XG4gICAgaWYgKHRoaXMucmVjYWxjdWxhdGUpIHtcbiAgICAgIHRoaXMucmVjYWxjdWxhdGVTdGF0cygpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZXNOdW1lcmljID8gdGhpcy5tb2RlIDogdGhpcy5kaWN0aW9uYXJ5W3RoaXMubW9kZV07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBtaW5pbXVtIHZhbHVlIG9mIHRoZSBTYW1wbGVTZXQuICBGb3Igc3RyaW5nXG4gICAqIHZhbHVlcywgdGhpcyBpcyBvcmRlcmVkIGJ5IHN0cmluZyBzb3J0aW5nIHJ1bGVzLlxuICAgKlxuICAgKiBAcmV0dXJucyBTYW1wbGVTZXRWYWx1ZSAtIG1pbmltdW0gdmFsdWUgb2YgdGhlIFNhbXBsZVNldFxuICAgKi9cbiAgcHVibGljIGdldE1pbigpOiBTYW1wbGVTZXRWYWx1ZSB7XG4gICAgaWYgKHRoaXMucmVjYWxjdWxhdGUpIHtcbiAgICAgIHRoaXMucmVjYWxjdWxhdGVTdGF0cygpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZXNOdW1lcmljID8gdGhpcy5taW4gOiB0aGlzLmRpY3Rpb25hcnlbdGhpcy5taW5dO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbWF4aW11bSB2YWx1ZSBvZiB0aGUgU2FtcGxlU2V0LiAgRm9yIHN0cmluZ1xuICAgKiB2YWx1ZXMsIHRoaXMgaXMgb3JkZXJlZCBieSBzdHJpbmcgc29ydGluZyBydWxlcy5cbiAgICpcbiAgICogQHJldHVybnMgU2FtcGxlU2V0VmFsdWUgLSBtYXhpbXVtIHZhbHVlIG9mIHRoZSBTYW1wbGVTZXRcbiAgICovXG4gIHB1YmxpYyBnZXRNYXgoKTogU2FtcGxlU2V0VmFsdWUge1xuICAgIGlmICh0aGlzLnJlY2FsY3VsYXRlKSB7XG4gICAgICB0aGlzLnJlY2FsY3VsYXRlU3RhdHMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzTnVtZXJpYyA/IHRoaXMubWF4IDogdGhpcy5kaWN0aW9uYXJ5W3RoaXMubWF4XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHZhcmlhbmNlIHZhbHVlIG9mIHRoZSBTYW1wbGVTZXQuICBGb3Igc3RyaW5nXG4gICAqIHZhbHVlcywgdGhpcyBpcyB0aGUgdmFyaWFuY2UgYWNyb3NzIHRoZSBzaXplIG9mIHRoZSBTYW1wbGVTZXQgWzAsc2FtcGxlU2V0LmdldE51bVNhbXBsZXMoKS0xXS5cbiAgICpcbiAgICogQHJldHVybnMgbnVtYmVyIC0gQ2FsY3VsYXRlZCB2YXJpYW5jZSBvZiB0aGUgU2FtcGxlU2V0XG4gICAqL1xuICBwdWJsaWMgZ2V0VmFyaWFuY2UoKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5yZWNhbGN1bGF0ZSkge1xuICAgICAgdGhpcy5yZWNhbGN1bGF0ZVN0YXRzKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnZhcmlhbmNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgcGVyY2VudGlsZXMgdmFsdWVzIGZvciB0aGUgU2FtcGxlU2V0LlxuICAgKlxuICAgKiBAcmV0dXJucyBzYW1wbGVTZXRQZXJjZW50aWxlcyAtIHRoZSAwLCAyNSwgNTAsIDc1LCBhbmQgMTAwdGggcGVyY2VudGlhbCB2YWx1ZXMgZm9yIHRoZSBTYW1wbGVTZXQuXG4gICAqL1xuICBwdWJsaWMgZ2V0UGVyY2VudGlsZXMoKTogU2FtcGxlU2V0UGVyY2VudGlsZXMge1xuICAgIGlmICh0aGlzLnJlY2FsY3VsYXRlKSB7XG4gICAgICB0aGlzLnJlY2FsY3VsYXRlU3RhdHMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIDA6IHRoaXMudmFsdWVzTnVtZXJpYyA/IHRoaXMubWluIDogdGhpcy5kaWN0aW9uYXJ5W3RoaXMubWluXSxcbiAgICAgIDI1OiB0aGlzLnZhbHVlc051bWVyaWMgPyB0aGlzLnBlcmNlbnRpbGUyNSA6IHRoaXMuZGljdGlvbmFyeVt0aGlzLnBlcmNlbnRpbGUyNV0sXG4gICAgICA1MDogdGhpcy52YWx1ZXNOdW1lcmljID8gdGhpcy5tZWRpYW4gOiB0aGlzLmRpY3Rpb25hcnlbdGhpcy5tZWRpYW5dLFxuICAgICAgNzU6IHRoaXMudmFsdWVzTnVtZXJpYyA/IHRoaXMucGVyY2VudGlsZTc1IDogdGhpcy5kaWN0aW9uYXJ5W3RoaXMucGVyY2VudGlsZTc1XSxcbiAgICAgIDEwMDogdGhpcy52YWx1ZXNOdW1lcmljID8gdGhpcy5tYXggOiB0aGlzLmRpY3Rpb25hcnlbdGhpcy5tYXhdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gdmFsdWUgb2YgdGhlIFNhbXBsZVNldC4gIEZvciBzdHJpbmdcbiAgICogdmFsdWVzLCB0aGlzIGlzIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gYWNyb3NzIHRoZSBzaXplIG9mIHRoZVxuICAgKiBTYW1wbGVTZXQgWzAsc2FtcGxlU2V0LmdldE51bVNhbXBsZXMoKS0xXS5cbiAgICpcbiAgICogQHJldHVybnMgbnVtYmVyIC0gQ2FsY3VsYXRlZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIFNhbXBsZVNldFxuICAgKi9cbiAgcHVibGljIGdldFN0ZGRldigpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLnJlY2FsY3VsYXRlKSB7XG4gICAgICB0aGlzLnJlY2FsY3VsYXRlU3RhdHMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3RkZGV2O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgdHlwZSBvZiB2YWx1ZXMgaW4gdGhlIFNhbXBsZVNldFxuICAgKlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIG51bWVyaWMgdmFsdWVzLCBmYWxzZSBpZiBzdHJpbmcgdmFsdWVzXG4gICAqL1xuICBwdWJsaWMgaXNOdW1lcmljKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc051bWVyaWM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBudW1iZXIgb2YgdmFsdWVzIGluIHRoZSBTYW1wbGVTZXRcbiAgICpcbiAgICogQHJldHVybnMgbnVtYmVyIG9mIHNhbXBsZXMgaW4gdGhlIFNhbXBsZVNldFxuICAgKi9cbiAgcHVibGljIGdldE51bVNhbXBsZXMoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSByZWNhbGN1bGF0ZVN0YXRzKCkge1xuXG4gICAgdGhpcy5jYWxjTWVhbigpO1xuICAgIHRoaXMuY2FsY1ZhcmlhbmNlKCk7XG4gICAgdGhpcy5jYWxjRnJvbVNvcnRlZFZhbHVlcygpO1xuXG4gICAgdGhpcy5yZWNhbGN1bGF0ZSA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBjYWxjTWVhbigpIHtcbiAgICB0aGlzLm1lYW4gPSB0aGlzLnZhbHVlcy5yZWR1Y2UoKHN1bSwgdmFsdWUpID0+IHN1bSt2YWx1ZSwgMCkgLyB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gICAgdGhpcy5tZWFuID0gdGhpcy52YWx1ZXNOdW1lcmljID8gdGhpcy5tZWFuIDogTWF0aC5yb3VuZCh0aGlzLm1lYW4pO1xuICB9XG5cbiAgLy8gQ2FsY3VsYXRlcyB0aGUgdmFyaWFuY2UgYW5kIHN0YW5kYXJkIGRldmlhdGlvblxuICAvLyBOT1RFIC0gdGhpcyBmdW5jdGlvbiBBU1NVTUVTIHRoYXQgdGhlIG1lYW4gaGFzIGFscmVhZHkgYmVlbiByZWNhbGN1bGF0ZWRcbiAgcHJpdmF0ZSBjYWxjVmFyaWFuY2UoKSB7XG4gICAgdGhpcy52YXJpYW5jZSA9IHRoaXMudmFsdWVzLnJlZHVjZSgoc3VtLCB2YWx1ZSkgPT4gc3VtKygodmFsdWUtdGhpcy5tZWFuKSoodmFsdWUtdGhpcy5tZWFuKSksIDApIC8gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICAgIHRoaXMuc3RkZGV2ID0gTWF0aC5zcXJ0KHRoaXMudmFyaWFuY2UpO1xuICB9XG5cbiAgLy8gQ2FsY3VsYXRlcyBtZWRpYW4sIG1vZGUsIGFuZCBkaXN0cmlidXRpb25cbiAgcHJpdmF0ZSBjYWxjRnJvbVNvcnRlZFZhbHVlcygpIHtcbiAgICAvLyBzb3J0IHRoZSB2YWx1ZXNcbiAgICBsZXQgc29ydGVkVmFsdWVzOiBudW1iZXJbXTtcblxuICAgIGlmICggdGhpcy52YWx1ZXNOdW1lcmljICkge1xuICAgICAgLy8gdGhlIGRlZmF1bHQgc29ydCBmdW5jdGlvbiBpcyBhcHByb3ByaWF0ZVxuICAgICAgc29ydGVkVmFsdWVzID0gdGhpcy52YWx1ZXMudG9Tb3J0ZWQoIChhLCBiKSA9PlxuICAgICAgICBhIDwgYiA/XG4gICAgICAgICAgLTEgOlxuICAgICAgICAgIGEgPiBiID9cbiAgICAgICAgICAgIDEgOlxuICAgICAgICAgICAgMCxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmNhbGNGcm9tU29ydGVkVmFsdWVzOiBzb3J0ZWRWYWx1ZXM6ICR7c29ydGVkVmFsdWVzfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBuZWVkIHRvIHNvcnQgYmFzZWQgb24gZGljdGlvbmFyeSBsb29rdXBcbiAgICAgIHNvcnRlZFZhbHVlcyA9IHRoaXMudmFsdWVzLnRvU29ydGVkKCAoYSwgYikgPT5cbiAgICAgICAgdGhpcy5kaWN0aW9uYXJ5W2FdIDwgdGhpcy5kaWN0aW9uYXJ5W2JdID9cbiAgICAgICAgICAtMSA6XG4gICAgICAgICAgKHRoaXMuZGljdGlvbmFyeVthXSA+IHRoaXMuZGljdGlvbmFyeVtiXSA/XG4gICAgICAgICAgICAxIDpcbiAgICAgICAgICAgIDAgKSxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmNhbGNGcm9tU29ydGVkVmFsdWVzOiBzb3J0ZWRWYWx1ZXM6ICR7c29ydGVkVmFsdWVzLm1hcCgodmFsdWUpID0+IHRoaXMuZGljdGlvbmFyeVt2YWx1ZV0pfWApO1xuICAgIH1cblxuXG4gICAgLy8gZ2V0IHRoZSBtZWRpYW5cbiAgICBjb25zdCBtaWRQb2ludEluZGV4ID0gTWF0aC50cnVuYygodGhpcy52YWx1ZXMubGVuZ3RoLTEpLzIpO1xuICAgIHRoaXMubWVkaWFuID0gc29ydGVkVmFsdWVzW21pZFBvaW50SW5kZXhdO1xuICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmNhbGNGcm9tU29ydGVkVmFsdWVzOiBtaWRQb2ludEluZGV4OiAke21pZFBvaW50SW5kZXh9YCk7XG5cbiAgICAvLyBnZXQgdGhlIG1pbiBhbmQgbWF4IHZhbHVlc1xuICAgIHRoaXMubWluID0gc29ydGVkVmFsdWVzWzBdO1xuICAgIHRoaXMubWF4ID0gc29ydGVkVmFsdWVzW3NvcnRlZFZhbHVlcy5sZW5ndGgtMV07XG5cbiAgICAvLyBnZXQgdGhlIHBlcmNlbnRpbGUyNSBhbmQgcGVyY2VudGlsZTUwIHZhbHVlc1xuICAgIGxldCBwZXJjZW50aWxlSW5kZXggPSBNYXRoLnRydW5jKCh0aGlzLnZhbHVlcy5sZW5ndGgtMSkvNCk7XG4gICAgdGhpcy5wZXJjZW50aWxlMjUgPSBzb3J0ZWRWYWx1ZXNbcGVyY2VudGlsZUluZGV4XTtcbiAgICBwZXJjZW50aWxlSW5kZXggPSBNYXRoLnRydW5jKCh0aGlzLnZhbHVlcy5sZW5ndGgtMSkqKDMvNCkpO1xuICAgIHRoaXMucGVyY2VudGlsZTc1ID0gc29ydGVkVmFsdWVzW3BlcmNlbnRpbGVJbmRleF07XG5cbiAgICAvLyBjcmVhdGUgdGhlIGRpc3RyaWJ1dGlvbiBoaXN0b2dyYW0vdGFibGVcbiAgICB0aGlzLmRpc3RyaWJ1dGlvbiA9IFtdO1xuICAgIGlmICggdGhpcy52YWx1ZXNOdW1lcmljICkge1xuICAgICAgLy8gaW4gdGhpcyBjYXNlLCBjcmVhdGUgYnVja2V0cyBvZiBlcXVhbCBzaXplIHdoaWNoIHNwYW4gdGhlIHJhbmdlIFttaW4sIG1heClcbiAgICAgIC8vIGFuZCBjb3VudCB0aGUgbnVtYmVyIG9mIHZhbHVlcyBpbiBlYWNoIHJhbmdlXG5cbiAgICAgIC8vIFVzZSB0aGUgc3FydChudW1TYW1wbGVzKSBydWxlIG9mIHRodW1iIGZvciBjYWxjdWxhdGluZyB0aGUgbnVtYmVyIG9mIGJ1Y2tldHNcbiAgICAgIGNvbnN0IG51bUJ1Y2tldHM6IG51bWJlciA9IE1hdGgudHJ1bmMoTWF0aC5zcXJ0KHRoaXMudmFsdWVzLmxlbmd0aCkrMSk7XG4gICAgICBjb25zdCBidWNrZXRTaXplOiBudW1iZXIgPSAodGhpcy5tYXgtdGhpcy5taW4pL251bUJ1Y2tldHM7XG5cbiAgICAgIGxldCBjdXJyZW50TWluOiBudW1iZXIgPSBzb3J0ZWRWYWx1ZXNbMF07XG4gICAgICBsZXQgY3VycmVudE1heDogbnVtYmVyID0gY3VycmVudE1pbiArIGJ1Y2tldFNpemU7XG4gICAgICBpZiAoY3VycmVudE1heCA9PT0gdGhpcy5tYXgpIHtcbiAgICAgICAgLy8gVkVSWSB1bmxpa2VseSAtIGJ1dCBqdXN0IGluIGNhc2UsIGFkZCBhIHZlcnkgc21hbGwgYW1vdW50IHNvIGFzIG5vdCB0byBoYXZlIGFcbiAgICAgICAgLy8gYnVja2V0IG9mIG9uZSB3aXRoIG9ubHkgdGhlIG1heCB2YWx1ZSBhdCB0aGUgZW5kLlxuICAgICAgICBjdXJyZW50TWF4ICs9IDFlLTEwO1xuICAgICAgfVxuICAgICAgbGV0IGNvdW50OiBudW1iZXIgPSAwO1xuXG4gICAgICBmb3IgKGxldCBpPTA7IGk8c29ydGVkVmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChzb3J0ZWRWYWx1ZXNbaV0gPj0gY3VycmVudE1pbiAmJiBzb3J0ZWRWYWx1ZXNbaV0gPCBjdXJyZW50TWF4KSB7XG4gICAgICAgICAgY291bnQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmRpc3RyaWJ1dGlvbi5wdXNoKG5ldyBTYW1wbGVCdWNrZXQoY3VycmVudE1pbiwgY3VycmVudE1heCwgY291bnQpKTtcbiAgICAgICAgICBjdXJyZW50TWluICs9IGJ1Y2tldFNpemU7XG4gICAgICAgICAgY3VycmVudE1heCA9IGN1cnJlbnRNaW4rYnVja2V0U2l6ZTtcbiAgICAgICAgICBpZiAoY3VycmVudE1heCA9PT0gdGhpcy5tYXgpIHtcbiAgICAgICAgICAgIC8vIFZFUlkgdW5saWtlbHkgLSBidXQganVzdCBpbiBjYXNlLCBhZGQgYSB2ZXJ5IHNtYWxsIGFtb3VudCBzbyBhcyBub3QgdG8gaGF2ZSBhXG4gICAgICAgICAgICAvLyBidWNrZXQgb2Ygb25lIHdpdGggb25seSB0aGUgbWF4IHZhbHVlIGF0IHRoZSBlbmQuXG4gICAgICAgICAgICBjdXJyZW50TWF4ICs9IDFlLTEwO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb3VudCA9IDE7XG4gICAgICAgIH1cblxuICAgICAgfVxuICAgICAgdGhpcy5kaXN0cmlidXRpb24ucHVzaChuZXcgU2FtcGxlQnVja2V0KGN1cnJlbnRNaW4sIGN1cnJlbnRNYXgsIGNvdW50KSk7XG5cbiAgICAgIC8vIG51bUJ1Y2tldHMgYW5kIGRpc3RyaWJ1dGlvbi5sZW5ndGggc2hvdWxkIG1hdGNoXG4gICAgICB0aGlzLmxvZ2dlcj8udHJhY2UoYFNhbXBsZVNldC5jYWxjRnJvbVNvcnRlZFZhbHVlczogbnVtZXJpYyBkYXRhLCBudW1CdWNrZXRzOiAke251bUJ1Y2tldHN9LCBkaXN0cmlidXRpb24ubGVuZ3RoOiAke3RoaXMuZGlzdHJpYnV0aW9uLmxlbmd0aH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaW4gdGhpcyBjYXNlLCB0aGUgbnVtYmVyIG9mIGJ1Y2tldHMgbWF0Y2hlcyB0aGUgbnVtYmVyIG9mIHN0cmluZ3MgaW4gdGhlIFNhbXBsZVNldFxuICAgICAgLy8gd2hpY2ggaXMgdGhlIHNpemUgb2YgdGhlIGRpY3Rpb25hcnlcblxuICAgICAgbGV0IGN1cnJlbnRWYWx1ZTogbnVtYmVyID0gc29ydGVkVmFsdWVzWzBdO1xuICAgICAgbGV0IGNvdW50OiBudW1iZXIgPSAwO1xuXG4gICAgICBmb3IgKGxldCBpPTA7IGk8c29ydGVkVmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChzb3J0ZWRWYWx1ZXNbaV0gPT09IGN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgIGNvdW50Kys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5kaXN0cmlidXRpb24ucHVzaChuZXcgU2FtcGxlQnVja2V0KGN1cnJlbnRWYWx1ZSwgY3VycmVudFZhbHVlLCBjb3VudCkpO1xuICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IHNvcnRlZFZhbHVlc1tpXTtcbiAgICAgICAgICBjb3VudCA9IDE7XG4gICAgICAgIH1cblxuICAgICAgfVxuICAgICAgdGhpcy5kaXN0cmlidXRpb24ucHVzaChuZXcgU2FtcGxlQnVja2V0KGN1cnJlbnRWYWx1ZSwgY3VycmVudFZhbHVlLCBjb3VudCkpO1xuXG4gICAgICAvLyBkaWN0aW9uYXJ5Lmxlbmd0aCBhbmQgZGlzdHJpYnV0aW9uLmxlbmd0aCBzaG91bGQgbWF0Y2hcbiAgICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmNhbGNGcm9tU29ydGVkVmFsdWVzOiBzdHJpbmcgZGF0YSwgZGljdGlvbmFyeS5sZW5ndGg6ICR7dGhpcy5kaWN0aW9uYXJ5Lmxlbmd0aH0sIGRpc3RyaWJ1dGlvbi5sZW5ndGg6ICR7dGhpcy5kaXN0cmlidXRpb24ubGVuZ3RofWApO1xuICAgICAgdGhpcy5sb2dnZXI/LnRyYWNlKGBTYW1wbGVTZXQuY2FsY0Zyb21Tb3J0ZWRWYWx1ZXM6IGRpY3Rpb25hcnk6ICR7dGhpcy5kaWN0aW9uYXJ5fWApO1xuICAgIH1cblxuICAgIHRoaXMubG9nZ2VyPy50cmFjZShgU2FtcGxlU2V0LmNhbGNGcm9tU29ydGVkVmFsdWVzOiBudW1lcmljOiAke3RoaXMudmFsdWVzTnVtZXJpY30sIGRpc3RyaWJ1dGlvbiBkZXRhaWxzOiAke0pTT04uc3RyaW5naWZ5KHRoaXMuZGlzdHJpYnV0aW9uLCBudWxsLCAyKX1gKTtcblxuICAgIC8vIGNhbGN1bGF0ZSB0aGUgbW9kZVxuICAgIGNvbnN0IG1heERpc3RyaWJ1dGlvbkJ1Y2tldEluZGV4ID0gdGhpcy5kaXN0cmlidXRpb24ucmVkdWNlKFxuICAgICAgKGN1ck1heEluZGV4LCBidWNrZXQsIGluZGV4KSA9PiBidWNrZXQuY291bnQgPiB0aGlzLmRpc3RyaWJ1dGlvbltjdXJNYXhJbmRleF0uY291bnQgPyBpbmRleCA6IGN1ck1heEluZGV4LFxuICAgICAgMCxcbiAgICApO1xuICAgIGlmICggdGhpcy52YWx1ZXNOdW1lcmljICkge1xuICAgICAgdGhpcy5tb2RlID0gdGhpcy5kaXN0cmlidXRpb25bbWF4RGlzdHJpYnV0aW9uQnVja2V0SW5kZXhdLm1pbiArXG4gICAgICAgICh0aGlzLmRpc3RyaWJ1dGlvblttYXhEaXN0cmlidXRpb25CdWNrZXRJbmRleF0ubWF4IC0gdGhpcy5kaXN0cmlidXRpb25bbWF4RGlzdHJpYnV0aW9uQnVja2V0SW5kZXhdLm1pbikvMjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tb2RlID0gdGhpcy5kaXN0cmlidXRpb25bbWF4RGlzdHJpYnV0aW9uQnVja2V0SW5kZXhdLm1pbjtcbiAgICB9XG5cbiAgICB0aGlzLmxvZ2dlcj8udHJhY2UoYFNhbXBsZVNldC5jYWxjRnJvbVNvcnRlZFZhbHVlczogbW9kZTogJHt0aGlzLm1vZGV9YCk7XG5cbiAgfVxuXG59XG4iXX0=
@@ -0,0 +1,35 @@
1
+ import { ILogger } from '@ncfour-us/logging';
2
+ import { SampleSet } from './sample-set.js';
3
+ /**
4
+ * The options for instantiating a Uniform distribution SampleSet.
5
+ */
6
+ export interface UniformSampleSetOptions {
7
+ /**
8
+ * number of smaples to generate, default 1000
9
+ */
10
+ numSamples?: number;
11
+ /**
12
+ * optional minimum value, default 0
13
+ */
14
+ min?: number;
15
+ /**
16
+ * optional maximum value, default 1
17
+ */
18
+ max?: number;
19
+ /**
20
+ * optional logger to use.
21
+ */
22
+ logger?: ILogger;
23
+ }
24
+ /**
25
+ * Class to create a Uniform distribution SampleSet
26
+ * with values in the range [0,1).
27
+ */
28
+ export declare class UniformSampleSet extends SampleSet {
29
+ /**
30
+ * Create a new UniformSampleSet instance.
31
+ *
32
+ * @param options See {@link UniformSampleSetOptions}
33
+ */
34
+ constructor(options: UniformSampleSetOptions);
35
+ }
@@ -0,0 +1,27 @@
1
+ // Copyright (c) 2026 Tim Hahn
2
+ import { SampleSet } from './sample-set.js';
3
+ ;
4
+ /**
5
+ * Class to create a Uniform distribution SampleSet
6
+ * with values in the range [0,1).
7
+ */
8
+ export class UniformSampleSet extends SampleSet {
9
+ /**
10
+ * Create a new UniformSampleSet instance.
11
+ *
12
+ * @param options See {@link UniformSampleSetOptions}
13
+ */
14
+ constructor(options) {
15
+ super({
16
+ logger: options.logger,
17
+ });
18
+ this.addValues(Array.from({ length: options.numSamples ?? 1000 }, (_element, _index) => {
19
+ const min = options.min ?? 0;
20
+ const max = options.max ?? 1;
21
+ const newVal = min + (max - min) * Math.random();
22
+ return newVal;
23
+ }));
24
+ this.logger?.trace(`UniformSampleSet.constructor: numSamples: ${this.getNumSamples()}`);
25
+ }
26
+ }
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5pZm9ybS1zYW1wbGUtc2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbXBvbmVudHMvdW5pZm9ybS1zYW1wbGUtc2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDhCQUE4QjtBQUc5QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUEyQjNDLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsU0FBUztJQUU3Qzs7OztPQUlHO0lBQ0gsWUFBWSxPQUFnQztRQUUxQyxLQUFLLENBQUM7WUFDSixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07U0FDdkIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksSUFBSSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckYsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFDN0IsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFFN0IsTUFBTSxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFDLEdBQUcsQ0FBQyxHQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUU3QyxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRUosSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsNkNBQTZDLElBQUksQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFMUYsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDI2IFRpbSBIYWhuXG5cbmltcG9ydCB7IElMb2dnZXIgfSBmcm9tICdAbmNmb3VyLXVzL2xvZ2dpbmcnO1xuaW1wb3J0IHsgU2FtcGxlU2V0IH0gZnJvbSAnLi9zYW1wbGUtc2V0LmpzJztcblxuLyoqXG4gKiBUaGUgb3B0aW9ucyBmb3IgaW5zdGFudGlhdGluZyBhIFVuaWZvcm0gZGlzdHJpYnV0aW9uIFNhbXBsZVNldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBVbmlmb3JtU2FtcGxlU2V0T3B0aW9ucyB7XG5cbiAgLyoqXG4gICAqIG51bWJlciBvZiBzbWFwbGVzIHRvIGdlbmVyYXRlLCBkZWZhdWx0IDEwMDBcbiAgICovXG4gIG51bVNhbXBsZXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIG9wdGlvbmFsIG1pbmltdW0gdmFsdWUsIGRlZmF1bHQgMFxuICAgKi9cbiAgbWluPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBvcHRpb25hbCBtYXhpbXVtIHZhbHVlLCBkZWZhdWx0IDFcbiAgICovXG4gIG1heD86IG51bWJlcjtcblxuICAvLyBkZXBlbmRlbmNpZXNcbiAgLyoqXG4gICAqIG9wdGlvbmFsIGxvZ2dlciB0byB1c2UuXG4gICAqL1xuICBsb2dnZXI/OiBJTG9nZ2VyO1xufTtcblxuLyoqXG4gKiBDbGFzcyB0byBjcmVhdGUgYSBVbmlmb3JtIGRpc3RyaWJ1dGlvbiBTYW1wbGVTZXRcbiAqIHdpdGggdmFsdWVzIGluIHRoZSByYW5nZSBbMCwxKS5cbiAqL1xuZXhwb3J0IGNsYXNzIFVuaWZvcm1TYW1wbGVTZXQgZXh0ZW5kcyBTYW1wbGVTZXQge1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgVW5pZm9ybVNhbXBsZVNldCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgU2VlIHtAbGluayBVbmlmb3JtU2FtcGxlU2V0T3B0aW9uc31cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFVuaWZvcm1TYW1wbGVTZXRPcHRpb25zKSB7XG5cbiAgICBzdXBlcih7XG4gICAgICBsb2dnZXI6IG9wdGlvbnMubG9nZ2VyLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRWYWx1ZXMoQXJyYXkuZnJvbSh7IGxlbmd0aDogb3B0aW9ucy5udW1TYW1wbGVzID8/IDEwMDAgfSwgKF9lbGVtZW50LCBfaW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IG1pbiA9IG9wdGlvbnMubWluID8/IDA7XG4gICAgICBjb25zdCBtYXggPSBvcHRpb25zLm1heCA/PyAxO1xuXG4gICAgICBjb25zdCBuZXdWYWwgPSBtaW4gKyAobWF4LW1pbikqTWF0aC5yYW5kb20oKTtcblxuICAgICAgcmV0dXJuIG5ld1ZhbDtcbiAgICB9KSk7XG5cbiAgICB0aGlzLmxvZ2dlcj8udHJhY2UoYFVuaWZvcm1TYW1wbGVTZXQuY29uc3RydWN0b3I6IG51bVNhbXBsZXM6ICR7dGhpcy5nZXROdW1TYW1wbGVzKCl9YCk7XG5cbiAgfVxufVxuIl19
package/lib/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { NormalSampleSet, NormalSampleSetOptions } from './components/normal-sample-set.js';
2
+ import { SampleBucket, SampleSet, SampleSetValue, SampleSetPercentiles, SampleSetOptions } from './components/sample-set.js';
3
+ import { UniformSampleSet, UniformSampleSetOptions } from './components/uniform-sample-set.js';
4
+ export type { SampleSetValue, SampleSetOptions, SampleSetPercentiles, UniformSampleSetOptions, NormalSampleSetOptions };
5
+ export { SampleBucket, SampleSet, UniformSampleSet, NormalSampleSet };
package/lib/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // Copyright (c) 2026 Tim Hahn
2
+ import { NormalSampleSet } from './components/normal-sample-set.js';
3
+ import { SampleBucket, SampleSet } from './components/sample-set.js';
4
+ import { UniformSampleSet } from './components/uniform-sample-set.js';
5
+ export { SampleBucket, SampleSet, UniformSampleSet, NormalSampleSet };
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsOEJBQThCO0FBRTlCLE9BQU8sRUFBRSxlQUFlLEVBQTBCLE1BQU0sbUNBQW1DLENBQUM7QUFDNUYsT0FBTyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQTBELE1BQU0sNEJBQTRCLENBQUM7QUFDN0gsT0FBTyxFQUFFLGdCQUFnQixFQUEyQixNQUFNLG9DQUFvQyxDQUFDO0FBSS9GLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDI2IFRpbSBIYWhuXG5cbmltcG9ydCB7IE5vcm1hbFNhbXBsZVNldCwgTm9ybWFsU2FtcGxlU2V0T3B0aW9ucyB9IGZyb20gJy4vY29tcG9uZW50cy9ub3JtYWwtc2FtcGxlLXNldC5qcyc7XG5pbXBvcnQgeyBTYW1wbGVCdWNrZXQsIFNhbXBsZVNldCwgU2FtcGxlU2V0VmFsdWUsIFNhbXBsZVNldFBlcmNlbnRpbGVzLCBTYW1wbGVTZXRPcHRpb25zIH0gZnJvbSAnLi9jb21wb25lbnRzL3NhbXBsZS1zZXQuanMnO1xuaW1wb3J0IHsgVW5pZm9ybVNhbXBsZVNldCwgVW5pZm9ybVNhbXBsZVNldE9wdGlvbnMgfSBmcm9tICcuL2NvbXBvbmVudHMvdW5pZm9ybS1zYW1wbGUtc2V0LmpzJztcblxuZXhwb3J0IHR5cGUgeyBTYW1wbGVTZXRWYWx1ZSwgU2FtcGxlU2V0T3B0aW9ucywgU2FtcGxlU2V0UGVyY2VudGlsZXMsIFVuaWZvcm1TYW1wbGVTZXRPcHRpb25zLCBOb3JtYWxTYW1wbGVTZXRPcHRpb25zIH07XG5cbmV4cG9ydCB7IFNhbXBsZUJ1Y2tldCwgU2FtcGxlU2V0LCBVbmlmb3JtU2FtcGxlU2V0LCBOb3JtYWxTYW1wbGVTZXQgfTtcbiJdfQ==
package/package.json ADDED
@@ -0,0 +1,139 @@
1
+ {
2
+ "name": "@ncfour-us/stats",
3
+ "description": "A set of basic statistics classes and utility functions",
4
+ "author": {
5
+ "name": "Tim Hahn",
6
+ "email": "hahntj@gmail.com",
7
+ "organization": false
8
+ },
9
+ "devDependencies": {
10
+ "@eslint/compat": "^2.1.1",
11
+ "@eslint/eslintrc": "^3.3.7",
12
+ "@eslint/js": "^9.39.5",
13
+ "@jest/globals": "^30.5.1",
14
+ "@ncfour-us/projen-utils": "^0.3.5",
15
+ "@stylistic/eslint-plugin": "^2",
16
+ "@types/jest": "^30.0.0",
17
+ "@types/node": "^24",
18
+ "@typescript-eslint/eslint-plugin": "^8",
19
+ "@typescript-eslint/parser": "^8",
20
+ "commit-and-tag-version": "^12",
21
+ "constructs": "^10.0.0",
22
+ "eslint": "^9",
23
+ "eslint-import-resolver-typescript": "^4.4.5",
24
+ "eslint-plugin-import": "^2.32.0",
25
+ "globals": "^14.0.0",
26
+ "jest": "^30.5.1",
27
+ "jest-junit": "^17",
28
+ "jiti": "^2.7.0",
29
+ "prettier": "^3.9.6",
30
+ "projen": "^0.103.23",
31
+ "ts-jest": "^29.4.12",
32
+ "ts-node": "^10.9.2",
33
+ "tsx": "^4.23.13",
34
+ "typedoc": "^0.28.20",
35
+ "typedoc-plugin-markdown": "^4.13.0",
36
+ "typescript": "^6.0.3"
37
+ },
38
+ "dependencies": {
39
+ "@ncfour-us/logging": "^0.1.0"
40
+ },
41
+ "engines": {
42
+ "node": ">= 24.0.0"
43
+ },
44
+ "devEngines": {
45
+ "packageManager": {
46
+ "name": "pnpm",
47
+ "version": ">=10",
48
+ "onFail": "ignore"
49
+ }
50
+ },
51
+ "main": "lib/index.js",
52
+ "license": "MIT",
53
+ "version": "0.0.0",
54
+ "jest": {
55
+ "coverageProvider": "v8",
56
+ "testMatch": [
57
+ "<rootDir>/@(src|test)/**/*(*.)@(spec|test).ts?(x)",
58
+ "<rootDir>/@(src|test)/**/__tests__/**/*.ts?(x)",
59
+ "<rootDir>/@(projenrc)/**/*(*.)@(spec|test).ts?(x)",
60
+ "<rootDir>/@(projenrc)/**/__tests__/**/*.ts?(x)"
61
+ ],
62
+ "clearMocks": true,
63
+ "collectCoverage": true,
64
+ "coverageReporters": [
65
+ "json",
66
+ "lcov",
67
+ "clover",
68
+ "cobertura",
69
+ "text"
70
+ ],
71
+ "coverageDirectory": "coverage",
72
+ "coveragePathIgnorePatterns": [
73
+ "/node_modules/"
74
+ ],
75
+ "testPathIgnorePatterns": [
76
+ "/node_modules/"
77
+ ],
78
+ "watchPathIgnorePatterns": [
79
+ "/node_modules/"
80
+ ],
81
+ "reporters": [
82
+ "default",
83
+ [
84
+ "jest-junit",
85
+ {
86
+ "outputDirectory": "test-reports"
87
+ }
88
+ ]
89
+ ],
90
+ "transform": {
91
+ "^.+\\.(mt|t|cj|j)s$": [
92
+ "ts-jest",
93
+ {
94
+ "useESM": true,
95
+ "tsconfig": "test/tsconfig.json"
96
+ }
97
+ ]
98
+ },
99
+ "extensionsToTreatAsEsm": [
100
+ ".ts"
101
+ ],
102
+ "moduleNameMapper": {
103
+ "^(\\.{1,2}/.*)\\.js$": "$1"
104
+ }
105
+ },
106
+ "types": "lib/index.d.ts",
107
+ "type": "module",
108
+ "exports": {
109
+ ".": "./lib/index.js"
110
+ },
111
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"pnpm exec projen\".",
112
+ "scripts": {
113
+ "build": "projen build",
114
+ "build:tag": "projen build:tag",
115
+ "build:tag:env": "projen build:tag:env",
116
+ "bump": "projen bump",
117
+ "bump:releasable-commits": "projen bump:releasable-commits",
118
+ "clobber": "projen clobber",
119
+ "compile": "projen compile",
120
+ "compile:examples": "projen compile:examples",
121
+ "default": "projen default",
122
+ "eject": "projen eject",
123
+ "eslint": "projen eslint",
124
+ "package": "projen package",
125
+ "post-compile": "projen post-compile",
126
+ "post-upgrade": "projen post-upgrade",
127
+ "pre-compile": "projen pre-compile",
128
+ "publish:git": "projen publish:git",
129
+ "publish:local": "projen publish:local",
130
+ "release": "projen release",
131
+ "test": "projen test",
132
+ "test:watch": "projen test:watch",
133
+ "unbump": "projen unbump",
134
+ "upgrade": "projen upgrade",
135
+ "watch": "projen watch",
136
+ "projen": "projen",
137
+ "build:docs": "pnpm typedoc"
138
+ }
139
+ }