@datagrok-libraries/statistics 1.0.1 → 1.1.1

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/lbfgs/lbfgs.js CHANGED
@@ -42,14 +42,14 @@ export function limitedMemoryBFGS(optimizable, parameters) {
42
42
  var oldValue = value;
43
43
 
44
44
  if (scale == 0.0) {
45
- console.log("Line search can't step in initial direction.");
45
+ //console.log("Line search can't step in initial direction.");
46
46
  }
47
47
 
48
48
  for (var iteration = 0; iteration < maxIterations; iteration++) {
49
49
  var start = +new Date();
50
50
  var end;
51
51
 
52
- //console.log("Beginning L-BFGS iteration, v=" + value + " ||g||=" + numeric.norm2(gradient));
52
+ ////console.log("Beginning L-BFGS iteration, v=" + value + " ||g||=" + numeric.norm2(gradient));
53
53
 
54
54
  // Update the buffers with diffs
55
55
  if (parameterChangeBuffer.length < memorySize) {
@@ -82,7 +82,9 @@ export function limitedMemoryBFGS(optimizable, parameters) {
82
82
  var scalingFactor = sy / yy;
83
83
  scaleBuffer.unshift(1.0 / sy);
84
84
 
85
- if (scalingFactor > 0.0) { console.log("Scaling factor greater than zero: " + scalingFactor); }
85
+ if (scalingFactor > 0.0) {
86
+ //console.log("Scaling factor greater than zero: " + scalingFactor);
87
+ }
86
88
 
87
89
  // Renaming the "gradient" array to "direction" -- but it's the same memory.
88
90
  copyInto(direction, gradient);
@@ -128,7 +130,7 @@ export function limitedMemoryBFGS(optimizable, parameters) {
128
130
 
129
131
  scale = backtrackingLineSearch(optimizable, direction, gradient, parameters);
130
132
  if (scale == 0.0) {
131
- console.log("Cannot step in current direction");
133
+ //console.log("Cannot step in current direction");
132
134
  }
133
135
 
134
136
  value = optimizable.getValue(parameters);
@@ -136,23 +138,23 @@ export function limitedMemoryBFGS(optimizable, parameters) {
136
138
 
137
139
  // Test for convergence
138
140
  if (2.0 * (value - oldValue) <= tolerance * (Math.abs(value) + Math.abs(oldValue) + epsilon)) {
139
- console.log("Value difference below threshold: " + value + " - " + oldValue);
141
+ //console.log("Value difference below threshold: " + value + " - " + oldValue);
140
142
  end = +new Date();
141
- console.log("Finished iterations " + (end - lbfgsStart));
143
+ //console.log("Finished iterations " + (end - lbfgsStart));
142
144
  return true;
143
145
  }
144
146
 
145
147
  var gradientNorm = numeric.norm2(gradient);
146
148
  if (gradientNorm < gradientTolerance) {
147
- console.log("Gradient norm below threshold: " + gradientNorm);
149
+ //console.log("Gradient norm below threshold: " + gradientNorm);
148
150
  end = +new Date();
149
- console.log("Finished iterations " + (end - lbfgsStart));
151
+ //console.log("Finished iterations " + (end - lbfgsStart));
150
152
  return true;
151
153
  }
152
154
  else if (gradientNorm == 0.0) {
153
- console.log("Gradient norm is zero");
155
+ //console.log("Gradient norm is zero");
154
156
  end = +new Date();
155
- console.log("Finished iterations " + (end - lbfgsStart));
157
+ //console.log("Finished iterations " + (end - lbfgsStart));
156
158
  return true;
157
159
  }
158
160
 
@@ -182,7 +184,7 @@ function backtrackingLineSearch(optimizable, direction, gradient, parameters) {
182
184
  // Make sure the initial step size isn't too big
183
185
  var twoNorm = numeric.norm2(direction);
184
186
  if (twoNorm > MAXIMUM_STEP) {
185
- console.log("Initial step " + twoNorm + " is too big, reducing")
187
+ //console.log("Initial step " + twoNorm + " is too big, reducing")
186
188
  numeric.muleq(direction, MAXIMUM_STEP / twoNorm);
187
189
  }
188
190
 
@@ -206,14 +208,14 @@ function backtrackingLineSearch(optimizable, direction, gradient, parameters) {
206
208
  }
207
209
 
208
210
  if (scale < minimumScale) {
209
- console.log("Step too small, exiting.");
211
+ //console.log("Step too small, exiting.");
210
212
  return 0.0;
211
213
  }
212
214
 
213
215
  var value = optimizable.getValue(parameters);
214
216
 
215
217
  if (value >= originalValue + DECREASE_FRACTION * scale * slope) {
216
- //console.log("Exiting line search at value " + value);
218
+ ////console.log("Exiting line search at value " + value);
217
219
  return scale;
218
220
  }
219
221
  else if (! isFinite(value)) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "friendlyName": "statistics",
7
- "version": "1.0.1",
7
+ "version": "1.1.1",
8
8
  "description": "",
9
9
  "dependencies": {
10
10
  "datagrok-api": "1.12.1",
@@ -0,0 +1,13 @@
1
+ export declare type Confidence = {
2
+ central: number;
3
+ top: number;
4
+ bottom: number;
5
+ };
6
+ /**
7
+ * @param {number[]} x observations vector.
8
+ * @param {number} confidenceLevel 0.05 means that 95% of observations enter the interval.
9
+ * @param {boolean} parametric symmetric parametric interval if true, sample quintiles if false.
10
+ * @return {Confidence} Object containing central tendency estimate and top and bottom of ht interval.
11
+ */
12
+ export declare function getConfidence(x: number[], confidenceLevel?: number, parametric?: boolean): Confidence;
13
+ //# sourceMappingURL=confidence-intervals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confidence-intervals.d.ts","sourceRoot":"","sources":["confidence-intervals.ts"],"names":[],"mappings":"AAGA,oBAAY,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,eAAe,GAAE,MAAa,EAAE,UAAU,GAAE,OAAc,GACnG,UAAU,CA8BX"}
@@ -0,0 +1,36 @@
1
+ //@ts-ignore: no types
2
+ import * as jStat from 'jstat';
3
+ /**
4
+ * @param {number[]} x observations vector.
5
+ * @param {number} confidenceLevel 0.05 means that 95% of observations enter the interval.
6
+ * @param {boolean} parametric symmetric parametric interval if true, sample quintiles if false.
7
+ * @return {Confidence} Object containing central tendency estimate and top and bottom of ht interval.
8
+ */
9
+ export function getConfidence(x, confidenceLevel = 0.05, parametric = true) {
10
+ if (x.length <= 1)
11
+ throw "vector is too short";
12
+ if (confidenceLevel >= 1 || confidenceLevel <= 0)
13
+ throw "incorrect confidence level";
14
+ if (parametric) {
15
+ const average = jStat.mean(x);
16
+ //true flag is obligatory for sample variance
17
+ const sigma = jStat.stdev(x, true);
18
+ //degrees of freedom as n-1 for student distribution
19
+ const interval = jStat.studentt.inv(1 - confidenceLevel / 2, x.length - 1) * sigma / Math.sqrt(x.length);
20
+ const res = {
21
+ central: average,
22
+ top: average + interval,
23
+ bottom: average - interval
24
+ };
25
+ return res;
26
+ }
27
+ else {
28
+ const res = {
29
+ central: jStat.median(x),
30
+ top: jStat.percentile(x, 1 - confidenceLevel / 2),
31
+ bottom: jStat.percentile(x, confidenceLevel / 2)
32
+ };
33
+ return res;
34
+ }
35
+ }
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlkZW5jZS1pbnRlcnZhbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb25maWRlbmNlLWludGVydmFscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxzQkFBc0I7QUFDdEIsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFRL0I7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLENBQVcsRUFBRSxrQkFBMEIsSUFBSSxFQUFFLGFBQXNCLElBQUk7SUFFbkcsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUM7UUFDZixNQUFNLHFCQUFxQixDQUFDO0lBRTlCLElBQUksZUFBZSxJQUFHLENBQUMsSUFBSSxlQUFlLElBQUcsQ0FBQztRQUM1QyxNQUFNLDRCQUE0QixDQUFDO0lBRXJDLElBQUksVUFBVSxFQUFFO1FBQ2QsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5Qiw2Q0FBNkM7UUFDN0MsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbkMsb0RBQW9EO1FBQ3BELE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxlQUFlLEdBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUMsS0FBSyxHQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRW5HLE1BQU0sR0FBRyxHQUFjO1lBQ3JCLE9BQU8sRUFBRSxPQUFPO1lBQ2hCLEdBQUcsRUFBRSxPQUFPLEdBQUcsUUFBUTtZQUN2QixNQUFNLEVBQUUsT0FBTyxHQUFHLFFBQVE7U0FDM0IsQ0FBQztRQUVGLE9BQU8sR0FBRyxDQUFDO0tBQ1o7U0FBTTtRQUNMLE1BQU0sR0FBRyxHQUFjO1lBQ3JCLE9BQU8sRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUN4QixHQUFHLEVBQUUsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGVBQWUsR0FBQyxDQUFDLENBQUM7WUFDL0MsTUFBTSxFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLGVBQWUsR0FBQyxDQUFDLENBQUM7U0FDL0MsQ0FBQztRQUVGLE9BQU8sR0FBRyxDQUFDO0tBQ1o7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy9AdHMtaWdub3JlOiBubyB0eXBlc1xuaW1wb3J0ICogYXMgalN0YXQgZnJvbSAnanN0YXQnO1xuXG5leHBvcnQgdHlwZSBDb25maWRlbmNlID0ge1xuICBjZW50cmFsOiBudW1iZXIsXG4gIHRvcDogbnVtYmVyLFxuICBib3R0b206IG51bWJlclxufVxuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyW119IHggb2JzZXJ2YXRpb25zIHZlY3Rvci5cbiAqIEBwYXJhbSB7bnVtYmVyfSBjb25maWRlbmNlTGV2ZWwgMC4wNSBtZWFucyB0aGF0IDk1JSBvZiBvYnNlcnZhdGlvbnMgZW50ZXIgdGhlIGludGVydmFsLlxuICogQHBhcmFtIHtib29sZWFufSBwYXJhbWV0cmljIHN5bW1ldHJpYyBwYXJhbWV0cmljIGludGVydmFsIGlmIHRydWUsIHNhbXBsZSBxdWludGlsZXMgaWYgZmFsc2UuXG4gKiBAcmV0dXJuIHtDb25maWRlbmNlfSBPYmplY3QgY29udGFpbmluZyBjZW50cmFsIHRlbmRlbmN5IGVzdGltYXRlIGFuZCB0b3AgYW5kIGJvdHRvbSBvZiBodCBpbnRlcnZhbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbmZpZGVuY2UoeDogbnVtYmVyW10sIGNvbmZpZGVuY2VMZXZlbDogbnVtYmVyID0gMC4wNSwgcGFyYW1ldHJpYzogYm9vbGVhbiA9IHRydWUpOlxuICBDb25maWRlbmNlIHtcbiAgaWYgKHgubGVuZ3RoIDw9IDEpIFxuICAgIHRocm93IFwidmVjdG9yIGlzIHRvbyBzaG9ydFwiO1xuXG4gIGlmIChjb25maWRlbmNlTGV2ZWwgPj0xIHx8IGNvbmZpZGVuY2VMZXZlbCA8PTApXG4gICAgdGhyb3cgXCJpbmNvcnJlY3QgY29uZmlkZW5jZSBsZXZlbFwiO1xuXG4gIGlmIChwYXJhbWV0cmljKSB7XG4gICAgY29uc3QgYXZlcmFnZSA9IGpTdGF0Lm1lYW4oeCk7XG4gICAgLy90cnVlIGZsYWcgaXMgb2JsaWdhdG9yeSBmb3Igc2FtcGxlIHZhcmlhbmNlXG4gICAgY29uc3Qgc2lnbWEgPSBqU3RhdC5zdGRldih4LCB0cnVlKTtcbiAgICAvL2RlZ3JlZXMgb2YgZnJlZWRvbSBhcyBuLTEgZm9yIHN0dWRlbnQgZGlzdHJpYnV0aW9uXG4gICAgY29uc3QgaW50ZXJ2YWwgPSBqU3RhdC5zdHVkZW50dC5pbnYoMSAtIGNvbmZpZGVuY2VMZXZlbC8yLCB4Lmxlbmd0aCAtIDEpKnNpZ21hL01hdGguc3FydCh4Lmxlbmd0aCk7XG5cbiAgICBjb25zdCByZXM6Q29uZmlkZW5jZSA9IHtcbiAgICAgIGNlbnRyYWw6IGF2ZXJhZ2UsXG4gICAgICB0b3A6IGF2ZXJhZ2UgKyBpbnRlcnZhbCxcbiAgICAgIGJvdHRvbTogYXZlcmFnZSAtIGludGVydmFsXG4gICAgfTsgIFxuXG4gICAgcmV0dXJuIHJlcztcbiAgfSBlbHNlIHtcbiAgICBjb25zdCByZXM6Q29uZmlkZW5jZSA9IHtcbiAgICAgIGNlbnRyYWw6IGpTdGF0Lm1lZGlhbih4KSxcbiAgICAgIHRvcDogalN0YXQucGVyY2VudGlsZSh4LCAxIC0gY29uZmlkZW5jZUxldmVsLzIpLFxuICAgICAgYm90dG9tOiBqU3RhdC5wZXJjZW50aWxlKHgsIGNvbmZpZGVuY2VMZXZlbC8yKVxuICAgIH07ICBcblxuICAgIHJldHVybiByZXM7XG4gIH1cbn1cbiJdfQ==
@@ -1,13 +1,24 @@
1
- declare type FitResult = {
1
+ export declare type FitResult = {
2
2
  parameters: number[];
3
3
  fittedCurve: (x: number) => number;
4
4
  confidenceTop: (x: number) => number;
5
5
  confidenceBottom: (x: number) => number;
6
+ rSquared: number;
7
+ auc: number;
8
+ };
9
+ export declare enum FitErrorModel {
10
+ Constant = 0,
11
+ Proportional = 1
12
+ }
13
+ export declare const FIT_FUNCTION_SIGMOID = "Sigmoid";
14
+ export declare const FIT_FUNCTION_LINEAR = "Linear";
15
+ export declare type FitFunctionType = 'Sigmoid' | 'Linear';
16
+ export declare const fitFunctions: {
17
+ [index: string]: any;
6
18
  };
7
19
  export declare function fit(data: {
8
20
  x: number[];
9
21
  y: number[];
10
- }, params: number[], curveFunction: (params: number[], x: number) => number, errorModel: string): FitResult;
22
+ }, params: number[], curveFunction: (params: number[], x: number) => number, errorModel: FitErrorModel, confidenceLevel?: number): FitResult;
11
23
  export declare function sigmoid(params: number[], x: number): number;
12
- export {};
13
24
  //# sourceMappingURL=fit-curve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fit-curve.d.ts","sourceRoot":"","sources":["fit-curve.ts"],"names":[],"mappings":"AAQA,aAAK,SAAS,GAAG;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC,CAAC,EAAC,MAAM,KAAI,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,EAAC,MAAM,KAAI,MAAM,CAAC;IACnC,gBAAgB,EAAE,CAAC,CAAC,EAAC,MAAM,KAAI,MAAM,CAAA;CACtC,CAAC;AAEF,wBAAgB,GAAG,CAAE,IAAI,EAAC;IAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,CAAC,EAAE,MAAM,EAAE,CAAA;CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAClD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CA2FzG;AA0JD,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3D"}
1
+ {"version":3,"file":"fit-curve.d.ts","sourceRoot":"","sources":["fit-curve.ts"],"names":[],"mappings":"AAUA,oBAAY,SAAS,GAAG;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC,CAAC,EAAC,MAAM,KAAI,MAAM,CAAC;IACjC,aAAa,EAAE,CAAC,CAAC,EAAC,MAAM,KAAI,MAAM,CAAC;IACnC,gBAAgB,EAAE,CAAC,CAAC,EAAC,MAAM,KAAI,MAAM,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAMF,oBAAY,aAAa;IACvB,QAAQ,IAAA;IACR,YAAY,IAAA;CACb;AAED,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAC9C,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAE5C,oBAAY,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AA4CnD,eAAO,MAAM,YAAY,EAAE;IAAC,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;CAG/C,CAAC;AAEF,wBAAgB,GAAG,CAAC,IAAI,EAAC;IAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,CAAC,EAAE,MAAM,EAAE,CAAA;CAAC,EAC/B,MAAM,EAAE,MAAM,EAAE,EAChB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,EACtD,UAAU,EAAE,aAAa,EACzB,eAAe,GAAE,MAAa,GAAG,SAAS,CAuE7D;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAO3D"}
@@ -1,36 +1,56 @@
1
1
  import { limitedMemoryBFGS } from "../../lbfgs/lbfgs";
2
- export function fit(data, params, curveFunction, errorModel) {
2
+ //@ts-ignore: no types
3
+ import * as jStat from 'jstat';
4
+ export var FitErrorModel;
5
+ (function (FitErrorModel) {
6
+ FitErrorModel[FitErrorModel["Constant"] = 0] = "Constant";
7
+ FitErrorModel[FitErrorModel["Proportional"] = 1] = "Proportional";
8
+ })(FitErrorModel || (FitErrorModel = {}));
9
+ export const FIT_FUNCTION_SIGMOID = 'Sigmoid';
10
+ export const FIT_FUNCTION_LINEAR = 'Linear';
11
+ class FitFunction {
12
+ }
13
+ class LinearFunction extends FitFunction {
14
+ get name() { return FIT_FUNCTION_LINEAR; }
15
+ get parameterNames() {
16
+ return ['Slope', 'Intercept'];
17
+ }
18
+ y(params, x) {
19
+ throw 'Not implemented';
20
+ }
21
+ getInitialParameters(x, y) {
22
+ throw 'Not implemented';
23
+ }
24
+ }
25
+ class SigmoidFunction extends FitFunction {
26
+ get name() { return FIT_FUNCTION_SIGMOID; }
27
+ get parameterNames() {
28
+ return ['Top', 'Bottom', 'Slope', 'IC50'];
29
+ }
30
+ y(params, x) {
31
+ throw 'Not implemented';
32
+ }
33
+ getInitialParameters(x, y) {
34
+ throw 'Not implemented';
35
+ }
36
+ }
37
+ export const fitFunctions = {
38
+ FIT_FUNCTION_LINEAR: new LinearFunction(),
39
+ FIT_FUNCTION_SIGMOID: new SigmoidFunction(),
40
+ };
41
+ export function fit(data, params, curveFunction, errorModel, confidenceLevel = 0.05) {
3
42
  let of;
4
43
  switch (errorModel) {
5
- case 'constant':
44
+ case FitErrorModel.Constant:
6
45
  of = objectiveNormalConstant;
7
46
  break;
8
- case 'proportional':
47
+ case FitErrorModel.Proportional:
9
48
  of = objectiveNormalProportional;
10
49
  break;
11
50
  default:
12
51
  of = objectiveNormalConstant;
13
52
  break;
14
53
  }
15
- function getDerivative(params, selectedParam) {
16
- let step = params[selectedParam] * 0.0001;
17
- step = step == 0 ? 0.001 : step;
18
- let paramsTop = [];
19
- let paramsBottom = [];
20
- for (let i = 0; i < params.length; i++) {
21
- if (i == selectedParam) {
22
- paramsTop.push(params[i] + step);
23
- paramsBottom.push(params[i] - step);
24
- }
25
- else {
26
- paramsTop.push(params[i]);
27
- paramsBottom.push(params[i]);
28
- }
29
- }
30
- const drvTop = of(curveFunction, data, paramsTop).value;
31
- const drvBottom = of(curveFunction, data, paramsBottom).value;
32
- return (drvTop - drvBottom) / (2 * step);
33
- }
34
54
  let iterations = 0;
35
55
  let optimizable = {
36
56
  getValue: (parameters) => {
@@ -39,9 +59,8 @@ export function fit(data, params, curveFunction, errorModel) {
39
59
  getGradient: (parameters, gradient) => {
40
60
  const length = Object.keys(parameters).length;
41
61
  iterations++;
42
- console.log(parameters.slice());
43
62
  for (let i = 0; i < parameters.length; i++)
44
- gradient[i] = getDerivative(parameters, i);
63
+ gradient[i] = getObjectiveDerivative(of, curveFunction, data, parameters, i);
45
64
  return gradient;
46
65
  }
47
66
  };
@@ -50,155 +69,34 @@ export function fit(data, params, curveFunction, errorModel) {
50
69
  let fittedCurve = (x) => {
51
70
  return curveFunction(params, x);
52
71
  };
72
+ let error = errorModel == FitErrorModel.Proportional ?
73
+ of(curveFunction, data, params).mult :
74
+ of(curveFunction, data, params).const;
75
+ let studentQ = jStat.studentt.inv(1 - confidenceLevel / 2, data.x.length - params.length);
53
76
  let top = (x) => {
54
77
  let value = curveFunction(params, x);
55
- if (errorModel == "constant")
56
- return value + 1.4 * error;
78
+ if (errorModel == FitErrorModel.Constant)
79
+ return value + studentQ * error / Math.sqrt(data.x.length);
57
80
  else
58
- return value + 1.4 * (Math.abs(value) * error);
81
+ return value + studentQ * (Math.abs(value) * error / Math.sqrt(data.x.length));
59
82
  };
60
- let error = errorModel == "constant" ?
61
- of(curveFunction, data, params).const :
62
- of(curveFunction, data, params).mult;
63
83
  let bottom = (x) => {
64
84
  let value = curveFunction(params, x);
65
- if (errorModel == "constant")
66
- return value - 1.4 * error;
85
+ if (errorModel == FitErrorModel.Constant)
86
+ return value - studentQ * error / Math.sqrt(data.x.length);
67
87
  else
68
- return value - 1.4 * (Math.abs(value) * error);
88
+ return value - studentQ * (Math.abs(value) * error / Math.sqrt(data.x.length));
69
89
  };
70
90
  let fitRes = {
71
91
  parameters: params,
72
92
  fittedCurve: fittedCurve,
73
93
  confidenceTop: top,
74
- confidenceBottom: bottom
94
+ confidenceBottom: bottom,
95
+ rSquared: getDetCoeff(fittedCurve, data),
96
+ auc: getAuc(fittedCurve, data)
75
97
  };
76
98
  return fitRes;
77
99
  }
78
- // performFit(): FitResult {
79
- // limitedMemoryBFGS(this.optimizable, this.params);
80
- // limitedMemoryBFGS(this.optimizable, this.params);
81
- // let fit: FitResult = {
82
- // parameters = this.parameters;
83
- // };
84
- // return {parameters: , curveFunction: this.curveFunction, confidence: this.confidence};
85
- // }
86
- // interface ICurveFitter<TArg> {
87
- // data: {observed: number[], args: TArg[]};
88
- // params: number[];
89
- // //curve function
90
- // cf (params: number[], args: TArg): number
91
- // //objective function
92
- // of (targetFunc: (params: number[], args: TArg) => number,
93
- // data: {observed: number[], args: TArg[]},
94
- // params: number[]): Likelihood
95
- // }
96
- // export class CurveFitter<TArg = number> implements ICurveFitter<TArg> {
97
- // errorModel: string;
98
- // data: {observed: number[], args: TArg[]};
99
- // params: number[];
100
- // cf;
101
- // of;
102
- // optimizable;
103
- // fitHistory: {iterations: number, parameters: {[iteration: number]: number[]},
104
- // likelihood: {[iteration: number]: number}} = {
105
- // iterations: 0,
106
- // parameters: {},
107
- // likelihood: {}
108
- // };
109
- // constructor(curveFunction: (params: number[], args: TArg) => number,
110
- // data: {observed: number[], args: TArg[]},
111
- // params: number[],
112
- // errorModel: 'constant' | 'proportional' = 'constant'//implement as enum
113
- // ) {
114
- // if(data.observed.length == 0 || data.observed.length != data.args.length)
115
- // throw new Error('invalid data');
116
- // this.data = data;
117
- // this.params = params;
118
- // this.errorModel = errorModel;
119
- // this.cf = curveFunction;
120
- // switch(errorModel) {
121
- // case 'constant':
122
- // this.of = objectiveNormalConstant;
123
- // break;
124
- // case 'proportional':
125
- // this.of = objectiveNormalProportional;
126
- // break;
127
- // default:
128
- // this.of = objectiveNormalConstant;
129
- // break;
130
- // }
131
- // this.optimizable = {
132
- // getValue: (parameters: number[]) => {
133
- // return this.of(this.cf, this.data, parameters).value;
134
- // },
135
- // getGradient: (parameters: number[], gradient: number[]) => {
136
- // const length = Object.keys(this.fitHistory.parameters).length;
137
- // this.fitHistory.iterations++;
138
- // this.fitHistory.parameters[length] = parameters.slice();
139
- // this.fitHistory.likelihood[length] = this.of(this.cf, this.data, parameters).value;
140
- // console.log(parameters.slice());
141
- // for (let i = 0; i < parameters.length; i++)
142
- // gradient[i] = this.getDerivative(parameters, i);
143
- // return gradient;
144
- // }
145
- // };
146
- // }
147
- // performFit(): void {
148
- // limitedMemoryBFGS(this.optimizable, this.params);
149
- // limitedMemoryBFGS(this.optimizable, this.params);
150
- // }
151
- // get parameters(): number[] {
152
- // return this.params;
153
- // }
154
- // get curveFunction(): Function {
155
- // let res = (arg: TArg) =>{
156
- // let params = this.fitHistory.parameters[this.fitHistory.iterations - 1];
157
- // return this.cf(params, arg);
158
- // }
159
- // return res;
160
- // }
161
- // get confidence(): {top:Function, bottom: Function} {
162
- // let params = this.fitHistory.parameters[this.fitHistory.iterations - 1];
163
- // let error = this.errorModel == "constant" ?
164
- // this.of(this.cf, this.data, params).const :
165
- // this.of(this.cf, this.data, params).mult;
166
- // let top = (arg: TArg) =>{
167
- // let value = this.cf(params, arg);
168
- // if (this.errorModel == "constant")
169
- // return value + 1.4*error;
170
- // else
171
- // return value + 1.4*(Math.abs(value)*error);
172
- // }
173
- // let bottom = (arg: TArg) =>{
174
- // let value = this.cf(params, arg);
175
- // if (this.errorModel == "constant")
176
- // return value - 1.4*error;
177
- // else
178
- // return value - 1.4*(Math.abs(value)*error);
179
- // }
180
- // return {top: top, bottom: bottom};
181
- // }
182
- // //central difference
183
- // private getDerivative(params: number[], selectedParam: number): number {
184
- // let step = params[selectedParam]*0.0001;
185
- // step = step == 0 ? 0.001 : step;
186
- // let paramsTop: number[] = [];
187
- // let paramsBottom: number[] = [];
188
- // for (let i = 0; i < params.length; i++) {
189
- // if(i == selectedParam) {
190
- // paramsTop.push(params[i] + step);
191
- // paramsBottom.push(params[i] - step);
192
- // } else {
193
- // paramsTop.push(params[i]);
194
- // paramsBottom.push(params[i]);
195
- // }
196
- // }
197
- // const drvTop = this.of(this.cf, this.data, paramsTop).value;
198
- // const drvBottom = this.of(this.cf, this.data, paramsBottom).value;
199
- // return (drvTop - drvBottom)/(2*step);
200
- // }
201
- // }
202
100
  export function sigmoid(params, x) {
203
101
  const A = params[0];
204
102
  const B = params[1];
@@ -207,6 +105,44 @@ export function sigmoid(params, x) {
207
105
  const res = D + (A - D) / (1 + Math.pow(10, (x - C) * B));
208
106
  return res;
209
107
  }
108
+ function getObjectiveDerivative(of, curveFunction, data, params, selectedParam) {
109
+ let step = params[selectedParam] * 0.0001;
110
+ step = step == 0 ? 0.001 : step;
111
+ let paramsTop = [];
112
+ let paramsBottom = [];
113
+ for (let i = 0; i < params.length; i++) {
114
+ if (i == selectedParam) {
115
+ paramsTop.push(params[i] + step);
116
+ paramsBottom.push(params[i] - step);
117
+ }
118
+ else {
119
+ paramsTop.push(params[i]);
120
+ paramsBottom.push(params[i]);
121
+ }
122
+ }
123
+ const drvTop = of(curveFunction, data, paramsTop).value;
124
+ const drvBottom = of(curveFunction, data, paramsBottom).value;
125
+ return (drvTop - drvBottom) / (2 * step);
126
+ }
127
+ function getAuc(fittedCurve, data) {
128
+ let auc = 0;
129
+ const integrationStep = 0.00001;
130
+ let min = Math.min(...data.x);
131
+ let max = Math.max(...data.x);
132
+ for (let x = min; x < max; x += integrationStep)
133
+ auc += integrationStep * fittedCurve(x);
134
+ return auc;
135
+ }
136
+ function getDetCoeff(fittedCurve, data) {
137
+ let ssRes = 0;
138
+ let ssTot = 0;
139
+ const yMean = jStat.mean(data.y);
140
+ for (let i = 0; i < data.x.length; i++) {
141
+ ssRes += Math.pow(data.y[i] - fittedCurve(data.x[i]), 2);
142
+ ssTot += Math.pow(data.y[i] - yMean, 2);
143
+ }
144
+ return 1 - ssRes / ssTot;
145
+ }
210
146
  function objectiveNormalConstant(targetFunc, data, params) {
211
147
  //assure observed and args same length
212
148
  const pi = Math.PI;
@@ -247,52 +183,4 @@ function objectiveNormalProportional(targetFunc, data, params) {
247
183
  likelihood += residuesSquares[i] / sigmaSq + Math.log(2 * pi * sigmaSq);
248
184
  return { value: -likelihood, const: sigma, mult: 0 };
249
185
  }
250
- // function objectiveNormalConstant<TArg> (
251
- // targetFunc: (params: number[], args: TArg) => number,
252
- // data: {observed: number[], args: TArg[]},
253
- // params: number[]
254
- // ): Likelihood {
255
- // //assure observed and args same length
256
- // const pi = Math.PI;
257
- // let sigma = 0;
258
- // let sigmaSq = 0;
259
- // let likelihood = 0;
260
- // let residuesSquares = new Float32Array(data.args.length);
261
- // for(let i = 0; i < data.args.length; i++) {
262
- // const obs = data.observed[i];
263
- // const pred = targetFunc(params, data.args[i]);
264
- // residuesSquares[i] = Math.pow(obs - pred, 2);
265
- // }
266
- // for(let i = 0; i < residuesSquares.length; i++)
267
- // sigmaSq += residuesSquares[i];
268
- // sigmaSq /= residuesSquares.length;
269
- // sigma = Math.sqrt(sigmaSq);
270
- // for(let i = 0; i < residuesSquares.length; i++)
271
- // likelihood += residuesSquares[i]/sigmaSq + Math.log(2 * pi * sigmaSq);
272
- // return {value: -likelihood, const: sigma, mult: 0};
273
- // }
274
- // function objectiveNormalProportional<TArg> (
275
- // targetFunc: (params: number[], args: TArg) => number,
276
- // data: {observed: number[], args: TArg[]},
277
- // params: number[]
278
- // ): Likelihood {
279
- // //assure observed and args same length
280
- // const pi = Math.PI;
281
- // let sigma = 0;
282
- // let sigmaSq = 0;
283
- // let likelihood = 0;
284
- // let residuesSquares = new Float32Array(data.args.length);
285
- // for(let i = 0; i < data.args.length; i++) {
286
- // const obs = data.observed[i];
287
- // const pred = targetFunc(params, data.args[i])
288
- // residuesSquares[i] = Math.pow(obs - pred, 2);
289
- // }
290
- // for(let i = 0; i < residuesSquares.length; i++)
291
- // sigmaSq += residuesSquares[i];
292
- // sigmaSq /= residuesSquares.length;
293
- // sigma = Math.sqrt(sigmaSq);
294
- // for(let i = 0; i < residuesSquares.length; i++)
295
- // likelihood += residuesSquares[i]/sigmaSq + Math.log(2*pi*sigmaSq);
296
- // return {value: -likelihood, const: sigma, mult: 0};
297
- // }
298
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml0LWN1cnZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZml0LWN1cnZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLG1CQUFtQixDQUFBO0FBZW5ELE1BQU0sVUFBVSxHQUFHLENBQUUsSUFBK0IsRUFBRSxNQUFnQixFQUNsRCxhQUFzRCxFQUFFLFVBQWtCO0lBRTVGLElBQUksRUFFMkIsQ0FBQztJQUNoQyxRQUFPLFVBQVUsRUFBRTtRQUNqQixLQUFLLFVBQVU7WUFDYixFQUFFLEdBQUcsdUJBQXVCLENBQUM7WUFDN0IsTUFBTTtRQUNSLEtBQUssY0FBYztZQUNqQixFQUFFLEdBQUcsMkJBQTJCLENBQUM7WUFDakMsTUFBTTtRQUNSO1lBQ0UsRUFBRSxHQUFHLHVCQUF1QixDQUFDO1lBQzdCLE1BQU07S0FDVDtJQUVELFNBQVMsYUFBYSxDQUFDLE1BQWdCLEVBQUUsYUFBcUI7UUFDNUQsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxHQUFDLE1BQU0sQ0FBQztRQUN4QyxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDaEMsSUFBSSxTQUFTLEdBQWEsRUFBRSxDQUFDO1FBQzdCLElBQUksWUFBWSxHQUFhLEVBQUUsQ0FBQztRQUNoQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN0QyxJQUFHLENBQUMsSUFBSSxhQUFhLEVBQUU7Z0JBQ3JCLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO2dCQUNqQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQzthQUNyQztpQkFBTTtn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O0FBQ3BELDZFQUE2RTtBQUU3RSxzR0FBc0c7QUFDdEcsSUFBSTtBQUVKLCtDQUErQztBQUMvQywyREFBMkQ7QUFDM0QsOENBQThDO0FBQzlDLHFCQUFxQjtBQUNyQixrQkFBa0I7QUFDbEIseUNBQXlDO0FBQ3pDLHNCQUFzQjtBQUN0QixpQkFBaUI7QUFDakIsbUJBQW1CO0FBQ25CLHNCQUFzQjtBQUV0Qiw0REFBNEQ7QUFDNUQsOENBQThDO0FBQzlDLGdDQUFnQztBQUNoQyxnREFBZ0Q7QUFDaEQsZ0RBQWdEO0FBQ2hELElBQUk7QUFFSixrREFBa0Q7QUFDbEQsaUNBQWlDO0FBQ2pDLHFDQUFxQztBQUNyQyw4QkFBOEI7QUFFOUIsa0RBQWtEO0FBQ2xELHFFQUFxRTtBQUVyRSxvR0FBb0c7QUFDcEcsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7bGltaXRlZE1lbW9yeUJGR1N9IGZyb20gXCIuLi8uLi9sYmZncy9sYmZnc1wiXG5cbnR5cGUgTGlrZWxpaG9vZCA9IHtcbiAgdmFsdWU6IG51bWJlciwgXG4gIGNvbnN0OiBudW1iZXIsIFxuICBtdWx0OiBudW1iZXJcbn07XG5cbnR5cGUgRml0UmVzdWx0ID0ge1xuICBwYXJhbWV0ZXJzOiBudW1iZXJbXSxcbiAgZml0dGVkQ3VydmU6ICh4Om51bWJlcik9PiBudW1iZXIsXG4gIGNvbmZpZGVuY2VUb3A6ICh4Om51bWJlcik9PiBudW1iZXIsXG4gIGNvbmZpZGVuY2VCb3R0b206ICh4Om51bWJlcik9PiBudW1iZXJcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBmaXQgKGRhdGE6e3g6IG51bWJlcltdLCB5OiBudW1iZXJbXX0sIHBhcmFtczogbnVtYmVyW10sXG4gICAgICAgICAgICAgICAgICAgIGN1cnZlRnVuY3Rpb246IChwYXJhbXM6IG51bWJlcltdLCB4OiBudW1iZXIpID0+IG51bWJlciwgZXJyb3JNb2RlbDogc3RyaW5nKTogRml0UmVzdWx0IHtcblxuICBsZXQgb2Y6ICh0YXJnZXRGdW5jOiAocGFyYW1zOiBudW1iZXJbXSwgeDogbnVtYmVyKSA9PiBudW1iZXIsIFxuICBkYXRhOiB7eTogbnVtYmVyW10sIHg6IG51bWJlcltdfSxcbiAgcGFyYW1zOiBudW1iZXJbXSkgPT4gTGlrZWxpaG9vZDtcbiAgc3dpdGNoKGVycm9yTW9kZWwpIHtcbiAgICBjYXNlICdjb25zdGFudCc6XG4gICAgICBvZiA9IG9iamVjdGl2ZU5vcm1hbENvbnN0YW50O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncHJvcG9ydGlvbmFsJzpcbiAgICAgIG9mID0gb2JqZWN0aXZlTm9ybWFsUHJvcG9ydGlvbmFsO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIG9mID0gb2JqZWN0aXZlTm9ybWFsQ29uc3RhbnQ7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERlcml2YXRpdmUocGFyYW1zOiBudW1iZXJbXSwgc2VsZWN0ZWRQYXJhbTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgc3RlcCA9IHBhcmFtc1tzZWxlY3RlZFBhcmFtXSowLjAwMDE7XG4gICAgc3RlcCA9IHN0ZXAgPT0gMCA/IDAuMDAxIDogc3RlcDsgXG4gICAgbGV0IHBhcmFtc1RvcDogbnVtYmVyW10gPSBbXTtcbiAgICBsZXQgcGFyYW1zQm90dG9tOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZihpID09IHNlbGVjdGVkUGFyYW0pIHtcbiAgICAgICAgcGFyYW1zVG9wLnB1c2gocGFyYW1zW2ldICsgc3RlcCk7XG4gICAgICAgIHBhcmFtc0JvdHRvbS5wdXNoKHBhcmFtc1tpXSAtIHN0ZXApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zVG9wLnB1c2gocGFyYW1zW2ldKTtcbiAgICAgICAgcGFyYW1zQm90dG9tLnB1c2gocGFyYW1zW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgZHJ2VG9wID0gb2YoY3VydmVGdW5jdGlvbiwgZGF0YSwgcGFyYW1zVG9wKS52YWx1ZTtcbiAgICBjb25zdCBkcnZCb3R0b20gPSBvZihjdXJ2ZUZ1bmN0aW9uLCBkYXRhLCBwYXJhbXNCb3R0b20pLnZhbHVlO1xuXG4gICAgcmV0dXJuIChkcnZUb3AgLSBkcnZCb3R0b20pLygyKnN0ZXApO1xuICB9XG5cblxuICBsZXQgaXRlcmF0aW9ucyA9IDA7XG5cbiAgbGV0IG9wdGltaXphYmxlID0ge1xuICAgIGdldFZhbHVlOiAocGFyYW1ldGVyczogbnVtYmVyW10pID0+IHtcbiAgICAgIHJldHVybiBvZihjdXJ2ZUZ1bmN0aW9uLCBkYXRhLCBwYXJhbWV0ZXJzKS52YWx1ZTtcbiAgICB9LFxuICAgIGdldEdyYWRpZW50OiAocGFyYW1ldGVyczogbnVtYmVyW10sIGdyYWRpZW50OiBudW1iZXJbXSkgPT4ge1xuICAgICAgY29uc3QgbGVuZ3RoID0gT2JqZWN0LmtleXMocGFyYW1ldGVycykubGVuZ3RoO1xuICAgICAgaXRlcmF0aW9ucysrO1xuICAgICAgY29uc29sZS5sb2cocGFyYW1ldGVycy5zbGljZSgpKTtcbiAgICAgIFxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJhbWV0ZXJzLmxlbmd0aDsgaSsrKVxuICAgICAgICBncmFkaWVudFtpXSA9IGdldERlcml2YXRpdmUocGFyYW1ldGVycywgaSk7XG5cbiAgICAgIHJldHVybiBncmFkaWVudDtcbiAgICB9XG4gIH07XG5cbiAgbGltaXRlZE1lbW9yeUJGR1Mob3B0aW1pemFibGUsIHBhcmFtcyk7XG4gIGxpbWl0ZWRNZW1vcnlCRkdTKG9wdGltaXphYmxlLCBwYXJhbXMpO1xuXG4gIGxldCBmaXR0ZWRDdXJ2ZSA9ICh4OiBudW1iZXIpID0+e1xuICAgIHJldHVybiBjdXJ2ZUZ1bmN0aW9uKHBhcmFtcywgeCk7XG4gIH1cblxuICBsZXQgdG9wID0gKHg6IG51bWJlcikgPT57XG4gICAgbGV0IHZhbHVlID0gY3VydmVGdW5jdGlvbihwYXJhbXMsIHgpO1xuICAgIGlmIChlcnJvck1vZGVsID09IFwiY29uc3RhbnRcIilcbiAgICAgIHJldHVybiAgdmFsdWUgKyAxLjQqZXJyb3I7XG4gICAgZWxzZVxuICAgICAgcmV0dXJuICB2YWx1ZSArIDEuNCooTWF0aC5hYnModmFsdWUpKmVycm9yKTtcbiAgfVxuXG4gIGxldCBlcnJvciA9IGVycm9yTW9kZWwgPT0gXCJjb25zdGFudFwiID9cbiAgb2YoY3VydmVGdW5jdGlvbiwgZGF0YSwgcGFyYW1zKS5jb25zdCA6XG4gIG9mKGN1cnZlRnVuY3Rpb24sIGRhdGEsIHBhcmFtcykubXVsdDtcblxuICBsZXQgYm90dG9tID0gKHg6IG51bWJlcikgPT57XG4gICAgbGV0IHZhbHVlID0gY3VydmVGdW5jdGlvbihwYXJhbXMsIHgpO1xuICAgIGlmIChlcnJvck1vZGVsID09IFwiY29uc3RhbnRcIilcbiAgICAgIHJldHVybiAgdmFsdWUgLSAxLjQqZXJyb3I7XG4gICAgZWxzZVxuICAgICAgcmV0dXJuICB2YWx1ZSAtIDEuNCooTWF0aC5hYnModmFsdWUpKmVycm9yKTtcbiAgfVxuXG4gIGxldCBmaXRSZXM6IEZpdFJlc3VsdCA9IHtcbiAgICBwYXJhbWV0ZXJzOiBwYXJhbXMsXG4gICAgZml0dGVkQ3VydmU6IGZpdHRlZEN1cnZlLFxuICAgIGNvbmZpZGVuY2VUb3A6IHRvcCxcbiAgICBjb25maWRlbmNlQm90dG9tOiBib3R0b21cbiAgfTtcblxuICByZXR1cm4gZml0UmVzO1xufVxuXG5cblxuLy8gcGVyZm9ybUZpdCgpOiBGaXRSZXN1bHQge1xuLy8gICBsaW1pdGVkTWVtb3J5QkZHUyh0aGlzLm9wdGltaXphYmxlLCB0aGlzLnBhcmFtcyk7XG4vLyAgIGxpbWl0ZWRNZW1vcnlCRkdTKHRoaXMub3B0aW1pemFibGUsIHRoaXMucGFyYW1zKTtcblxuLy8gICBsZXQgZml0OiBGaXRSZXN1bHQgPSB7XG4vLyAgICAgcGFyYW1ldGVycyA9IHRoaXMucGFyYW1ldGVycztcbi8vICAgfTtcblxuLy8gICByZXR1cm4ge3BhcmFtZXRlcnM6ICwgY3VydmVGdW5jdGlvbjogdGhpcy5jdXJ2ZUZ1bmN0aW9uLCBjb25maWRlbmNlOiB0aGlzLmNvbmZpZGVuY2V9O1xuLy8gfVxuXG5cbi8vIGludGVyZmFjZSBJQ3VydmVGaXR0ZXI8VEFyZz4ge1xuLy8gICBkYXRhOiB7b2JzZXJ2ZWQ6IG51bWJlcltdLCBhcmdzOiBUQXJnW119O1xuLy8gICBwYXJhbXM6IG51bWJlcltdO1xuXG4vLyAgIC8vY3VydmUgZnVuY3Rpb25cbi8vICAgY2YgKHBhcmFtczogbnVtYmVyW10sIGFyZ3M6IFRBcmcpOiBudW1iZXJcbi8vICAgLy9vYmplY3RpdmUgZnVuY3Rpb25cbi8vICAgb2YgKHRhcmdldEZ1bmM6IChwYXJhbXM6IG51bWJlcltdLCBhcmdzOiBUQXJnKSA9PiBudW1iZXIsIFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHtvYnNlcnZlZDogbnVtYmVyW10sIGFyZ3M6IFRBcmdbXX0sXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zOiBudW1iZXJbXSk6IExpa2VsaWhvb2Rcbi8vIH1cblxuLy8gZXhwb3J0IGNsYXNzIEN1cnZlRml0dGVyPFRBcmcgPSBudW1iZXI+IGltcGxlbWVudHMgSUN1cnZlRml0dGVyPFRBcmc+IHtcbi8vICAgZXJyb3JNb2RlbDogc3RyaW5nO1xuLy8gICBkYXRhOiB7b2JzZXJ2ZWQ6IG51bWJlcltdLCBhcmdzOiBUQXJnW119O1xuLy8gICBwYXJhbXM6IG51bWJlcltdO1xuLy8gICBjZjtcbi8vICAgb2Y7XG4vLyAgIG9wdGltaXphYmxlO1xuLy8gICBmaXRIaXN0b3J5OiB7aXRlcmF0aW9uczogbnVtYmVyLCBwYXJhbWV0ZXJzOiB7W2l0ZXJhdGlvbjogbnVtYmVyXTogbnVtYmVyW119LCBcbi8vICAgICAgICAgICAgICAgICBsaWtlbGlob29kOiB7W2l0ZXJhdGlvbjogbnVtYmVyXTogbnVtYmVyfX0gPSB7XG4vLyAgICAgaXRlcmF0aW9uczogMCxcbi8vICAgICBwYXJhbWV0ZXJzOiB7fSxcbi8vICAgICBsaWtlbGlob29kOiB7fVxuLy8gICB9O1xuXG4vLyAgIGNvbnN0cnVjdG9yKGN1cnZlRnVuY3Rpb246IChwYXJhbXM6IG51bWJlcltdLCBhcmdzOiBUQXJnKSA9PiBudW1iZXIsIFxuLy8gICAgICAgICAgICAgICBkYXRhOiB7b2JzZXJ2ZWQ6IG51bWJlcltdLCBhcmdzOiBUQXJnW119LFxuLy8gICAgICAgICAgICAgICBwYXJhbXM6IG51bWJlcltdLFxuLy8gICAgICAgICAgICAgICBlcnJvck1vZGVsOiAnY29uc3RhbnQnIHwgJ3Byb3BvcnRpb25hbCcgPSAnY29uc3RhbnQnLy9pbXBsZW1lbnQgYXMgZW51bVxuLy8gICAgICAgICAgICAgICApIHtcblxuLy8gICAgIGlmKGRhdGEub2JzZXJ2ZWQubGVuZ3RoID09IDAgfHwgZGF0YS5vYnNlcnZlZC5sZW5ndGggIT0gZGF0YS5hcmdzLmxlbmd0aClcbi8vICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBkYXRhJyk7XG4gICAgICBcbi8vICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuLy8gICAgIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuLy8gICAgIHRoaXMuZXJyb3JNb2RlbCA9IGVycm9yTW9kZWw7XG4vLyAgICAgdGhpcy5jZiA9IGN1cnZlRnVuY3Rpb247XG5cbi8vICAgICBzd2l0Y2goZXJyb3JNb2RlbCkge1xuLy8gICAgICAgY2FzZSAnY29uc3RhbnQnOlxuLy8gICAgICAgICB0aGlzLm9mID0gb2JqZWN0aXZlTm9ybWFsQ29uc3RhbnQ7XG4vLyAgICAgICAgIGJyZWFrO1xuLy8gICAgICAgY2FzZSAncHJvcG9ydGlvbmFsJzpcbi8vICAgICAgICAgdGhpcy5vZiA9IG9iamVjdGl2ZU5vcm1hbFByb3BvcnRpb25hbDtcbi8vICAgICAgICAgYnJlYWs7XG4vLyAgICAgICBkZWZhdWx0OlxuLy8gICAgICAgICB0aGlzLm9mID0gb2JqZWN0aXZlTm9ybWFsQ29uc3RhbnQ7XG4vLyAgICAgICAgIGJyZWFrO1xuLy8gICAgIH1cblxuLy8gICAgIHRoaXMub3B0aW1pemFibGUgPSB7XG4vLyAgICAgICBnZXRWYWx1ZTogKHBhcmFtZXRlcnM6IG51bWJlcltdKSA9PiB7XG4vLyAgICAgICAgIHJldHVybiB0aGlzLm9mKHRoaXMuY2YsIHRoaXMuZGF0YSwgcGFyYW1ldGVycykudmFsdWU7XG4vLyAgICAgICB9LFxuLy8gICAgICAgZ2V0R3JhZGllbnQ6IChwYXJhbWV0ZXJzOiBudW1iZXJbXSwgZ3JhZGllbnQ6IG51bWJlcltdKSA9PiB7XG4vLyAgICAgICAgIGNvbnN0IGxlbmd0aCA9IE9iamVjdC5rZXlzKHRoaXMuZml0SGlzdG9yeS5wYXJhbWV0ZXJzKS5sZW5ndGg7XG4vLyAgICAgICAgIHRoaXMuZml0SGlzdG9yeS5pdGVyYXRpb25zKys7XG4vLyAgICAgICAgIHRoaXMuZml0SGlzdG9yeS5wYXJhbWV0ZXJzW2xlbmd0aF0gPSBwYXJhbWV0ZXJzLnNsaWNlKCk7XG4vLyAgICAgICAgIHRoaXMuZml0SGlzdG9yeS5saWtlbGlob29kW2xlbmd0aF0gPSB0aGlzLm9mKHRoaXMuY2YsIHRoaXMuZGF0YSwgcGFyYW1ldGVycykudmFsdWU7XG4vLyAgICAgICAgIGNvbnNvbGUubG9nKHBhcmFtZXRlcnMuc2xpY2UoKSk7XG4gICAgICAgIFxuLy8gICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmFtZXRlcnMubGVuZ3RoOyBpKyspXG4vLyAgICAgICAgICAgZ3JhZGllbnRbaV0gPSB0aGlzLmdldERlcml2YXRpdmUocGFyYW1ldGVycywgaSk7XG5cbi8vICAgICAgICAgcmV0dXJuIGdyYWRpZW50O1xuLy8gICAgICAgfVxuLy8gICAgIH07XG4vLyAgIH1cblxuLy8gICBwZXJmb3JtRml0KCk6IHZvaWQge1xuLy8gICAgIGxpbWl0ZWRNZW1vcnlCRkdTKHRoaXMub3B0aW1pemFibGUsIHRoaXMucGFyYW1zKTtcbi8vICAgICBsaW1pdGVkTWVtb3J5QkZHUyh0aGlzLm9wdGltaXphYmxlLCB0aGlzLnBhcmFtcyk7XG4vLyAgIH1cblxuLy8gICBnZXQgcGFyYW1ldGVycygpOiBudW1iZXJbXSB7XG4vLyAgICAgcmV0dXJuIHRoaXMucGFyYW1zO1xuLy8gICB9XG5cbi8vICAgZ2V0IGN1cnZlRnVuY3Rpb24oKTogRnVuY3Rpb24ge1xuLy8gICAgIGxldCByZXMgPSAoYXJnOiBUQXJnKSA9Pntcbi8vICAgICAgIGxldCBwYXJhbXMgPSB0aGlzLmZpdEhpc3RvcnkucGFyYW1ldGVyc1t0aGlzLmZpdEhpc3RvcnkuaXRlcmF0aW9ucyAtIDFdO1xuXG4vLyAgICAgICByZXR1cm4gdGhpcy5jZihwYXJhbXMsIGFyZyk7XG4vLyAgICAgfVxuXG4vLyAgICAgcmV0dXJuIHJlcztcbi8vICAgfVxuXG4vLyAgIGdldCBjb25maWRlbmNlKCk6IHt0b3A6RnVuY3Rpb24sIGJvdHRvbTogRnVuY3Rpb259IHtcbi8vICAgICBsZXQgcGFyYW1zID0gdGhpcy5maXRIaXN0b3J5LnBhcmFtZXRlcnNbdGhpcy5maXRIaXN0b3J5Lml0ZXJhdGlvbnMgLSAxXTtcblxuLy8gICAgIGxldCBlcnJvciA9IHRoaXMuZXJyb3JNb2RlbCA9PSBcImNvbnN0YW50XCIgP1xuLy8gICAgICAgICAgICAgICAgIHRoaXMub2YodGhpcy5jZiwgdGhpcy5kYXRhLCBwYXJhbXMpLmNvbnN0IDpcbi8vICAgICAgICAgICAgICAgICB0aGlzLm9mKHRoaXMuY2YsIHRoaXMuZGF0YSwgcGFyYW1zKS5tdWx0O1xuXG4vLyAgICAgbGV0IHRvcCA9IChhcmc6IFRBcmcpID0+e1xuLy8gICAgICAgbGV0IHZhbHVlID0gdGhpcy5jZihwYXJhbXMsIGFyZyk7XG4vLyAgICAgICBpZiAodGhpcy5lcnJvck1vZGVsID09IFwiY29uc3RhbnRcIilcbi8vICAgICAgICAgcmV0dXJuICB2YWx1ZSArIDEuNCplcnJvcjtcbi8vICAgICAgIGVsc2Vcbi8vICAgICAgICAgcmV0dXJuICB2YWx1ZSArIDEuNCooTWF0aC5hYnModmFsdWUpKmVycm9yKTtcbi8vICAgICB9XG5cbi8vICAgICBsZXQgYm90dG9tID0gKGFyZzogVEFyZykgPT57XG4vLyAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmNmKHBhcmFtcywgYXJnKTtcbi8vICAgICAgIGlmICh0aGlzLmVycm9yTW9kZWwgPT0gXCJjb25zdGFudFwiKVxuLy8gICAgICAgICByZXR1cm4gIHZhbHVlIC0gMS40KmVycm9yO1xuLy8gICAgICAgZWxzZVxuLy8gICAgICAgICByZXR1cm4gIHZhbHVlIC0gMS40KihNYXRoLmFicyh2YWx1ZSkqZXJyb3IpO1xuLy8gICAgIH1cblxuLy8gICAgIHJldHVybiB7dG9wOiB0b3AsIGJvdHRvbTogYm90dG9tfTtcbi8vICAgfVxuXG4vLyAgIC8vY2VudHJhbCBkaWZmZXJlbmNlXG4vLyAgIHByaXZhdGUgZ2V0RGVyaXZhdGl2ZShwYXJhbXM6IG51bWJlcltdLCBzZWxlY3RlZFBhcmFtOiBudW1iZXIpOiBudW1iZXIge1xuLy8gICAgIGxldCBzdGVwID0gcGFyYW1zW3NlbGVjdGVkUGFyYW1dKjAuMDAwMTtcbi8vICAgICBzdGVwID0gc3RlcCA9PSAwID8gMC4wMDEgOiBzdGVwOyBcbi8vICAgICBsZXQgcGFyYW1zVG9wOiBudW1iZXJbXSA9IFtdO1xuLy8gICAgIGxldCBwYXJhbXNCb3R0b206IG51bWJlcltdID0gW107XG4vLyAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJhbXMubGVuZ3RoOyBpKyspIHtcbi8vICAgICAgIGlmKGkgPT0gc2VsZWN0ZWRQYXJhbSkge1xuLy8gICAgICAgICBwYXJhbXNUb3AucHVzaChwYXJhbXNbaV0gKyBzdGVwKTtcbi8vICAgICAgICAgcGFyYW1zQm90dG9tLnB1c2gocGFyYW1zW2ldIC0gc3RlcCk7XG4vLyAgICAgICB9IGVsc2Uge1xuLy8gICAgICAgICBwYXJhbXNUb3AucHVzaChwYXJhbXNbaV0pO1xuLy8gICAgICAgICBwYXJhbXNCb3R0b20ucHVzaChwYXJhbXNbaV0pO1xuLy8gICAgICAgfVxuLy8gICAgIH1cbi8vICAgICBjb25zdCBkcnZUb3AgPSB0aGlzLm9mKHRoaXMuY2YsIHRoaXMuZGF0YSwgcGFyYW1zVG9wKS52YWx1ZTtcbi8vICAgICBjb25zdCBkcnZCb3R0b20gPSB0aGlzLm9mKHRoaXMuY2YsIHRoaXMuZGF0YSwgcGFyYW1zQm90dG9tKS52YWx1ZTtcblxuLy8gICAgIHJldHVybiAoZHJ2VG9wIC0gZHJ2Qm90dG9tKS8oMipzdGVwKTtcbi8vICAgfVxuLy8gfVxuXG5leHBvcnQgZnVuY3Rpb24gc2lnbW9pZChwYXJhbXM6IG51bWJlcltdLCB4OiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBBID0gcGFyYW1zWzBdO1xuICBjb25zdCBCID0gcGFyYW1zWzFdO1xuICBjb25zdCBDID0gcGFyYW1zWzJdO1xuICBjb25zdCBEID0gcGFyYW1zWzNdO1xuICBjb25zdCByZXMgPSBEICsgKEEgLSBEKS8oMSArIE1hdGgucG93KDEwLCAoeCAtIEMpKkIpKTtcbiAgcmV0dXJuIHJlcztcbn1cblxuXG5cbmZ1bmN0aW9uIG9iamVjdGl2ZU5vcm1hbENvbnN0YW50IChcbiAgdGFyZ2V0RnVuYzogKHBhcmFtczogbnVtYmVyW10sIHg6IG51bWJlcikgPT4gbnVtYmVyLCBcbiAgZGF0YToge3k6IG51bWJlcltdLCB4OiBudW1iZXJbXX0sXG4gIHBhcmFtczogbnVtYmVyW11cbik6IExpa2VsaWhvb2Qge1xuLy9hc3N1cmUgb2JzZXJ2ZWQgYW5kIGFyZ3Mgc2FtZSBsZW5ndGhcbmNvbnN0IHBpID0gTWF0aC5QSTtcbmxldCBzaWdtYSA9IDA7XG5sZXQgc2lnbWFTcSA9IDA7XG5sZXQgbGlrZWxpaG9vZCA9IDA7XG5cbmxldCByZXNpZHVlc1NxdWFyZXMgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEueC5sZW5ndGgpO1xuZm9yKGxldCBpID0gMDsgaSA8IGRhdGEueC5sZW5ndGg7IGkrKykge1xuY29uc3Qgb2JzID0gZGF0YS55W2ldO1xuY29uc3QgcHJlZCA9IHRhcmdldEZ1bmMocGFyYW1zLCBkYXRhLnhbaV0pO1xucmVzaWR1ZXNTcXVhcmVzW2ldID0gTWF0aC5wb3cob2JzIC0gcHJlZCwgMik7XG59XG5cbmZvcihsZXQgaSA9IDA7IGkgPCByZXNpZHVlc1NxdWFyZXMubGVuZ3RoOyBpKyspXG5zaWdtYVNxICs9IHJlc2lkdWVzU3F1YXJlc1tpXTtcbnNpZ21hU3EgLz0gcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDtcbnNpZ21hID0gTWF0aC5zcXJ0KHNpZ21hU3EpO1xuXG5mb3IobGV0IGkgPSAwOyBpIDwgcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDsgaSsrKVxubGlrZWxpaG9vZCArPSByZXNpZHVlc1NxdWFyZXNbaV0vc2lnbWFTcSArIE1hdGgubG9nKDIgKiBwaSAqIHNpZ21hU3EpO1xuXG5yZXR1cm4ge3ZhbHVlOiAtbGlrZWxpaG9vZCwgY29uc3Q6IHNpZ21hLCBtdWx0OiAwfTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG59XG5cbmZ1bmN0aW9uIG9iamVjdGl2ZU5vcm1hbFByb3BvcnRpb25hbCAoXG50YXJnZXRGdW5jOiAocGFyYW1zOiBudW1iZXJbXSwgeDogbnVtYmVyKSA9PiBudW1iZXIsIFxuZGF0YToge3k6IG51bWJlcltdLCB4OiBudW1iZXJbXX0sXG5wYXJhbXM6IG51bWJlcltdXG4pOiBMaWtlbGlob29kIHtcbi8vYXNzdXJlIG9ic2VydmVkIGFuZCBhcmdzIHNhbWUgbGVuZ3RoXG5jb25zdCBwaSA9IE1hdGguUEk7XG5sZXQgc2lnbWEgPSAwO1xubGV0IHNpZ21hU3EgPSAwO1xubGV0IGxpa2VsaWhvb2QgPSAwO1xuXG5sZXQgcmVzaWR1ZXNTcXVhcmVzID0gbmV3IEZsb2F0MzJBcnJheShkYXRhLngubGVuZ3RoKTtcbmZvcihsZXQgaSA9IDA7IGkgPCBkYXRhLngubGVuZ3RoOyBpKyspIHtcbmNvbnN0IG9icyA9IGRhdGEueVtpXTtcbmNvbnN0IHByZWQgPSB0YXJnZXRGdW5jKHBhcmFtcywgZGF0YS54W2ldKVxucmVzaWR1ZXNTcXVhcmVzW2ldID0gTWF0aC5wb3cob2JzIC0gcHJlZCwgMik7XG59XG5cbmZvcihsZXQgaSA9IDA7IGkgPCByZXNpZHVlc1NxdWFyZXMubGVuZ3RoOyBpKyspXG5zaWdtYVNxICs9IHJlc2lkdWVzU3F1YXJlc1tpXTtcbnNpZ21hU3EgLz0gcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDtcbnNpZ21hID0gTWF0aC5zcXJ0KHNpZ21hU3EpO1xuXG5mb3IobGV0IGkgPSAwOyBpIDwgcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDsgaSsrKVxubGlrZWxpaG9vZCArPSByZXNpZHVlc1NxdWFyZXNbaV0vc2lnbWFTcSArIE1hdGgubG9nKDIqcGkqc2lnbWFTcSk7XG5cbnJldHVybiB7dmFsdWU6IC1saWtlbGlob29kLCBjb25zdDogc2lnbWEsIG11bHQ6IDB9OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbn1cblxuXG5cbi8vIGZ1bmN0aW9uIG9iamVjdGl2ZU5vcm1hbENvbnN0YW50PFRBcmc+IChcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRGdW5jOiAocGFyYW1zOiBudW1iZXJbXSwgYXJnczogVEFyZykgPT4gbnVtYmVyLCBcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiB7b2JzZXJ2ZWQ6IG51bWJlcltdLCBhcmdzOiBUQXJnW119LFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtczogbnVtYmVyW11cbi8vICk6IExpa2VsaWhvb2Qge1xuLy8gICAvL2Fzc3VyZSBvYnNlcnZlZCBhbmQgYXJncyBzYW1lIGxlbmd0aFxuLy8gICBjb25zdCBwaSA9IE1hdGguUEk7XG4vLyAgIGxldCBzaWdtYSA9IDA7XG4vLyAgIGxldCBzaWdtYVNxID0gMDtcbi8vICAgbGV0IGxpa2VsaWhvb2QgPSAwO1xuXG4vLyAgIGxldCByZXNpZHVlc1NxdWFyZXMgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEuYXJncy5sZW5ndGgpO1xuLy8gICBmb3IobGV0IGkgPSAwOyBpIDwgZGF0YS5hcmdzLmxlbmd0aDsgaSsrKSB7XG4vLyAgICAgY29uc3Qgb2JzID0gZGF0YS5vYnNlcnZlZFtpXTtcbi8vICAgICBjb25zdCBwcmVkID0gdGFyZ2V0RnVuYyhwYXJhbXMsIGRhdGEuYXJnc1tpXSk7XG4vLyAgICAgcmVzaWR1ZXNTcXVhcmVzW2ldID0gTWF0aC5wb3cob2JzIC0gcHJlZCwgMik7XG4vLyAgIH1cbiAgXG4vLyAgIGZvcihsZXQgaSA9IDA7IGkgPCByZXNpZHVlc1NxdWFyZXMubGVuZ3RoOyBpKyspXG4vLyAgICAgc2lnbWFTcSArPSByZXNpZHVlc1NxdWFyZXNbaV07XG4vLyAgIHNpZ21hU3EgLz0gcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDtcbi8vICAgc2lnbWEgPSBNYXRoLnNxcnQoc2lnbWFTcSk7XG5cbi8vICAgZm9yKGxldCBpID0gMDsgaSA8IHJlc2lkdWVzU3F1YXJlcy5sZW5ndGg7IGkrKylcbi8vICAgICBsaWtlbGlob29kICs9IHJlc2lkdWVzU3F1YXJlc1tpXS9zaWdtYVNxICsgTWF0aC5sb2coMiAqIHBpICogc2lnbWFTcSk7XG5cbi8vICAgcmV0dXJuIHt2YWx1ZTogLWxpa2VsaWhvb2QsIGNvbnN0OiBzaWdtYSwgbXVsdDogMH07ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuLy8gfVxuXG4vLyBmdW5jdGlvbiBvYmplY3RpdmVOb3JtYWxQcm9wb3J0aW9uYWw8VEFyZz4gKFxuLy8gICB0YXJnZXRGdW5jOiAocGFyYW1zOiBudW1iZXJbXSwgYXJnczogVEFyZykgPT4gbnVtYmVyLCBcbi8vICAgZGF0YToge29ic2VydmVkOiBudW1iZXJbXSwgYXJnczogVEFyZ1tdfSxcbi8vICAgcGFyYW1zOiBudW1iZXJbXVxuLy8gKTogTGlrZWxpaG9vZCB7XG4vLyAvL2Fzc3VyZSBvYnNlcnZlZCBhbmQgYXJncyBzYW1lIGxlbmd0aFxuLy8gY29uc3QgcGkgPSBNYXRoLlBJO1xuLy8gbGV0IHNpZ21hID0gMDtcbi8vIGxldCBzaWdtYVNxID0gMDtcbi8vIGxldCBsaWtlbGlob29kID0gMDtcblxuLy8gbGV0IHJlc2lkdWVzU3F1YXJlcyA9IG5ldyBGbG9hdDMyQXJyYXkoZGF0YS5hcmdzLmxlbmd0aCk7XG4vLyBmb3IobGV0IGkgPSAwOyBpIDwgZGF0YS5hcmdzLmxlbmd0aDsgaSsrKSB7XG4vLyBjb25zdCBvYnMgPSBkYXRhLm9ic2VydmVkW2ldO1xuLy8gY29uc3QgcHJlZCA9IHRhcmdldEZ1bmMocGFyYW1zLCBkYXRhLmFyZ3NbaV0pXG4vLyByZXNpZHVlc1NxdWFyZXNbaV0gPSBNYXRoLnBvdyhvYnMgLSBwcmVkLCAyKTtcbi8vIH1cblxuLy8gZm9yKGxldCBpID0gMDsgaSA8IHJlc2lkdWVzU3F1YXJlcy5sZW5ndGg7IGkrKylcbi8vIHNpZ21hU3EgKz0gcmVzaWR1ZXNTcXVhcmVzW2ldO1xuLy8gc2lnbWFTcSAvPSByZXNpZHVlc1NxdWFyZXMubGVuZ3RoO1xuLy8gc2lnbWEgPSBNYXRoLnNxcnQoc2lnbWFTcSk7XG5cbi8vIGZvcihsZXQgaSA9IDA7IGkgPCByZXNpZHVlc1NxdWFyZXMubGVuZ3RoOyBpKyspXG4vLyBsaWtlbGlob29kICs9IHJlc2lkdWVzU3F1YXJlc1tpXS9zaWdtYVNxICsgTWF0aC5sb2coMipwaSpzaWdtYVNxKTtcblxuLy8gcmV0dXJuIHt2YWx1ZTogLWxpa2VsaWhvb2QsIGNvbnN0OiBzaWdtYSwgbXVsdDogMH07ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuLy8gfVxuIl19
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml0LWN1cnZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZml0LWN1cnZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLG1CQUFtQixDQUFBO0FBQ25ELHNCQUFzQjtBQUN0QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQztBQXFCL0IsTUFBTSxDQUFOLElBQVksYUFHWDtBQUhELFdBQVksYUFBYTtJQUN2Qix5REFBUSxDQUFBO0lBQ1IsaUVBQVksQ0FBQTtBQUNkLENBQUMsRUFIVyxhQUFhLEtBQWIsYUFBYSxRQUd4QjtBQUVELE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLFNBQVMsQ0FBQztBQUM5QyxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxRQUFRLENBQUM7QUFJNUMsTUFBZSxXQUFXO0NBS3pCO0FBR0QsTUFBTSxjQUFlLFNBQVEsV0FBVztJQUN0QyxJQUFJLElBQUksS0FBYSxPQUFPLG1CQUFtQixDQUFDLENBQUMsQ0FBQztJQUVsRCxJQUFJLGNBQWM7UUFDaEIsT0FBTyxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQsQ0FBQyxDQUFDLE1BQWdCLEVBQUUsQ0FBUztRQUMzQixNQUFNLGlCQUFpQixDQUFDO0lBQzFCLENBQUM7SUFFRCxvQkFBb0IsQ0FBQyxDQUFXLEVBQUUsQ0FBVztRQUMzQyxNQUFNLGlCQUFpQixDQUFDO0lBQzFCLENBQUM7Q0FDRjtBQUdELE1BQU0sZUFBZ0IsU0FBUSxXQUFXO0lBQ3ZDLElBQUksSUFBSSxLQUFhLE9BQU8sb0JBQW9CLENBQUMsQ0FBQyxDQUFDO0lBRW5ELElBQUksY0FBYztRQUNoQixPQUFPLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVELENBQUMsQ0FBQyxNQUFnQixFQUFFLENBQVM7UUFDM0IsTUFBTSxpQkFBaUIs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Q0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDMUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztLQUM5QztJQUVELEtBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtRQUM1QyxPQUFPLElBQUksZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLE9BQU8sSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDO0lBQ2xDLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRTNCLEtBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtRQUM1QyxVQUFVLElBQUksZUFBZSxDQUFDLENBQUMsQ0FBQyxHQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBQyxFQUFFLEdBQUMsT0FBTyxDQUFDLENBQUM7SUFFcEUsT0FBTyxFQUFDLEtBQUssRUFBRSxDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUMsQ0FBQztBQUNyRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtsaW1pdGVkTWVtb3J5QkZHU30gZnJvbSBcIi4uLy4uL2xiZmdzL2xiZmdzXCJcbi8vQHRzLWlnbm9yZTogbm8gdHlwZXNcbmltcG9ydCAqIGFzIGpTdGF0IGZyb20gJ2pzdGF0JztcblxudHlwZSBMaWtlbGlob29kID0ge1xuICB2YWx1ZTogbnVtYmVyLCBcbiAgY29uc3Q6IG51bWJlciwgXG4gIG11bHQ6IG51bWJlclxufTtcblxuZXhwb3J0IHR5cGUgRml0UmVzdWx0ID0ge1xuICBwYXJhbWV0ZXJzOiBudW1iZXJbXSxcbiAgZml0dGVkQ3VydmU6ICh4Om51bWJlcik9PiBudW1iZXIsXG4gIGNvbmZpZGVuY2VUb3A6ICh4Om51bWJlcik9PiBudW1iZXIsXG4gIGNvbmZpZGVuY2VCb3R0b206ICh4Om51bWJlcik9PiBudW1iZXIsXG4gIHJTcXVhcmVkOiBudW1iZXIsXG4gIGF1YzogbnVtYmVyO1xufTtcblxudHlwZSBPYmplY3RpdmVGdW5jdGlvbiA9ICh0YXJnZXRGdW5jOiAocGFyYW1zOiBudW1iZXJbXSwgeDogbnVtYmVyKSA9PiBudW1iZXIsIFxuZGF0YToge3g6IG51bWJlcltdLCB5OiBudW1iZXJbXX0sXG5wYXJhbXM6IG51bWJlcltdKSA9PiBMaWtlbGlob29kO1xuXG5leHBvcnQgZW51bSBGaXRFcnJvck1vZGVsIHtcbiAgQ29uc3RhbnQsXG4gIFByb3BvcnRpb25hbFxufVxuXG5leHBvcnQgY29uc3QgRklUX0ZVTkNUSU9OX1NJR01PSUQgPSAnU2lnbW9pZCc7XG5leHBvcnQgY29uc3QgRklUX0ZVTkNUSU9OX0xJTkVBUiA9ICdMaW5lYXInO1xuXG5leHBvcnQgdHlwZSBGaXRGdW5jdGlvblR5cGUgPSAnU2lnbW9pZCcgfCAnTGluZWFyJztcblxuYWJzdHJhY3QgY2xhc3MgRml0RnVuY3Rpb24ge1xuICBhYnN0cmFjdCBnZXQgbmFtZSgpOiBzdHJpbmc7XG4gIGFic3RyYWN0IGdldCBwYXJhbWV0ZXJOYW1lcygpOiBzdHJpbmdbXTtcbiAgYWJzdHJhY3QgeShwYXJhbXM6IG51bWJlcltdLCB4OiBudW1iZXIpOiBudW1iZXI7XG4gIGFic3RyYWN0IGdldEluaXRpYWxQYXJhbWV0ZXJzKHg6IG51bWJlcltdLCB5OiBudW1iZXJbXSk6IG51bWJlcltdO1xufVxuXG5cbmNsYXNzIExpbmVhckZ1bmN0aW9uIGV4dGVuZHMgRml0RnVuY3Rpb24ge1xuICBnZXQgbmFtZSgpOiBzdHJpbmcgeyByZXR1cm4gRklUX0ZVTkNUSU9OX0xJTkVBUjsgfVxuXG4gIGdldCBwYXJhbWV0ZXJOYW1lcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFsnU2xvcGUnLCAnSW50ZXJjZXB0J107XG4gIH1cblxuICB5KHBhcmFtczogbnVtYmVyW10sIHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgdGhyb3cgJ05vdCBpbXBsZW1lbnRlZCc7XG4gIH1cblxuICBnZXRJbml0aWFsUGFyYW1ldGVycyh4OiBudW1iZXJbXSwgeTogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgdGhyb3cgJ05vdCBpbXBsZW1lbnRlZCc7XG4gIH1cbn1cblxuXG5jbGFzcyBTaWdtb2lkRnVuY3Rpb24gZXh0ZW5kcyBGaXRGdW5jdGlvbiB7XG4gIGdldCBuYW1lKCk6IHN0cmluZyB7IHJldHVybiBGSVRfRlVOQ1RJT05fU0lHTU9JRDsgfVxuXG4gIGdldCBwYXJhbWV0ZXJOYW1lcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFsnVG9wJywgJ0JvdHRvbScsICdTbG9wZScsICdJQzUwJ107XG4gIH1cblxuICB5KHBhcmFtczogbnVtYmVyW10sIHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgdGhyb3cgJ05vdCBpbXBsZW1lbnRlZCc7XG4gIH1cblxuICBnZXRJbml0aWFsUGFyYW1ldGVycyh4OiBudW1iZXJbXSwgeTogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgdGhyb3cgJ05vdCBpbXBsZW1lbnRlZCc7XG4gIH1cbn1cblxuXG5leHBvcnQgY29uc3QgZml0RnVuY3Rpb25zOiB7W2luZGV4OiBzdHJpbmddOiBhbnl9ID0ge1xuICBGSVRfRlVOQ1RJT05fTElORUFSOiBuZXcgTGluZWFyRnVuY3Rpb24oKSxcbiAgRklUX0ZVTkNUSU9OX1NJR01PSUQ6IG5ldyBTaWdtb2lkRnVuY3Rpb24oKSxcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBmaXQoZGF0YTp7eDogbnVtYmVyW10sIHk6IG51bWJlcltdfSwgXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtczogbnVtYmVyW10sXG4gICAgICAgICAgICAgICAgICAgIGN1cnZlRnVuY3Rpb246IChwYXJhbXM6IG51bWJlcltdLCB4OiBudW1iZXIpID0+IG51bWJlciwgXG4gICAgICAgICAgICAgICAgICAgIGVycm9yTW9kZWw6IEZpdEVycm9yTW9kZWwsXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZGVuY2VMZXZlbDogbnVtYmVyID0gMC4wNSk6IEZpdFJlc3VsdCB7XG5cbiAgbGV0IG9mOiBPYmplY3RpdmVGdW5jdGlvbjtcbiAgc3dpdGNoKGVycm9yTW9kZWwpIHtcbiAgICBjYXNlIEZpdEVycm9yTW9kZWwuQ29uc3RhbnQ6XG4gICAgICBvZiA9IG9iamVjdGl2ZU5vcm1hbENvbnN0YW50O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBGaXRFcnJvck1vZGVsLlByb3BvcnRpb25hbDpcbiAgICAgIG9mID0gb2JqZWN0aXZlTm9ybWFsUHJvcG9ydGlvbmFsO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIG9mID0gb2JqZWN0aXZlTm9ybWFsQ29uc3RhbnQ7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGxldCBpdGVyYXRpb25zID0gMDtcblxuICBsZXQgb3B0aW1pemFibGUgPSB7XG4gICAgZ2V0VmFsdWU6IChwYXJhbWV0ZXJzOiBudW1iZXJbXSkgPT4ge1xuICAgICAgcmV0dXJuIG9mKGN1cnZlRnVuY3Rpb24sIGRhdGEsIHBhcmFtZXRlcnMpLnZhbHVlO1xuICAgIH0sXG4gICAgZ2V0R3JhZGllbnQ6IChwYXJhbWV0ZXJzOiBudW1iZXJbXSwgZ3JhZGllbnQ6IG51bWJlcltdKSA9PiB7XG4gICAgICBjb25zdCBsZW5ndGggPSBPYmplY3Qua2V5cyhwYXJhbWV0ZXJzKS5sZW5ndGg7XG4gICAgICBpdGVyYXRpb25zKys7XG4gICAgICBcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1ldGVycy5sZW5ndGg7IGkrKylcbiAgICAgICAgZ3JhZGllbnRbaV0gPSBnZXRPYmplY3RpdmVEZXJpdmF0aXZlKG9mLCBjdXJ2ZUZ1bmN0aW9uLCBkYXRhLCBwYXJhbWV0ZXJzLCBpKTtcblxuICAgICAgcmV0dXJuIGdyYWRpZW50O1xuICAgIH1cbiAgfTtcblxuICBsaW1pdGVkTWVtb3J5QkZHUyhvcHRpbWl6YWJsZSwgcGFyYW1zKTtcbiAgbGltaXRlZE1lbW9yeUJGR1Mob3B0aW1pemFibGUsIHBhcmFtcyk7XG5cbiAgbGV0IGZpdHRlZEN1cnZlID0gKHg6IG51bWJlcikgPT4ge1xuICAgIHJldHVybiBjdXJ2ZUZ1bmN0aW9uKHBhcmFtcywgeCk7XG4gIH1cblxuICBsZXQgZXJyb3IgPSBlcnJvck1vZGVsID09IEZpdEVycm9yTW9kZWwuUHJvcG9ydGlvbmFsID9cbiAgb2YoY3VydmVGdW5jdGlvbiwgZGF0YSwgcGFyYW1zKS5tdWx0IDpcbiAgb2YoY3VydmVGdW5jdGlvbiwgZGF0YSwgcGFyYW1zKS5jb25zdDtcblxuICBsZXQgc3R1ZGVudFEgPSBqU3RhdC5zdHVkZW50dC5pbnYoMSAtIGNvbmZpZGVuY2VMZXZlbC8yLCBkYXRhLngubGVuZ3RoIC0gcGFyYW1zLmxlbmd0aCk7XG5cbiAgbGV0IHRvcCA9ICh4OiBudW1iZXIpID0+e1xuICAgIGxldCB2YWx1ZSA9IGN1cnZlRnVuY3Rpb24ocGFyYW1zLCB4KTtcbiAgICBpZiAoZXJyb3JNb2RlbCA9PSBGaXRFcnJvck1vZGVsLkNvbnN0YW50KVxuICAgICAgcmV0dXJuICB2YWx1ZSArIHN0dWRlbnRRKmVycm9yL01hdGguc3FydChkYXRhLngubGVuZ3RoKTtcbiAgICBlbHNlXG4gICAgICByZXR1cm4gIHZhbHVlICsgc3R1ZGVudFEqKE1hdGguYWJzKHZhbHVlKSplcnJvci9NYXRoLnNxcnQoZGF0YS54Lmxlbmd0aCkpO1xuICB9XG5cbiAgbGV0IGJvdHRvbSA9ICh4OiBudW1iZXIpID0+IHtcbiAgICBsZXQgdmFsdWUgPSBjdXJ2ZUZ1bmN0aW9uKHBhcmFtcywgeCk7XG4gICAgaWYgKGVycm9yTW9kZWwgPT0gRml0RXJyb3JNb2RlbC5Db25zdGFudClcbiAgICAgIHJldHVybiAgdmFsdWUgLSBzdHVkZW50USplcnJvci9NYXRoLnNxcnQoZGF0YS54Lmxlbmd0aCk7XG4gICAgZWxzZVxuICAgICAgcmV0dXJuICB2YWx1ZSAtIHN0dWRlbnRRKihNYXRoLmFicyh2YWx1ZSkqZXJyb3IvTWF0aC5zcXJ0KGRhdGEueC5sZW5ndGgpKTtcbiAgfVxuXG4gIGxldCBmaXRSZXM6IEZpdFJlc3VsdCA9IHtcbiAgICBwYXJhbWV0ZXJzOiBwYXJhbXMsXG4gICAgZml0dGVkQ3VydmU6IGZpdHRlZEN1cnZlLFxuICAgIGNvbmZpZGVuY2VUb3A6IHRvcCxcbiAgICBjb25maWRlbmNlQm90dG9tOiBib3R0b20sXG4gICAgclNxdWFyZWQ6IGdldERldENvZWZmKGZpdHRlZEN1cnZlLCBkYXRhKSxcbiAgICBhdWM6IGdldEF1YyhmaXR0ZWRDdXJ2ZSwgZGF0YSlcbiAgfTtcblxuICByZXR1cm4gZml0UmVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2lnbW9pZChwYXJhbXM6IG51bWJlcltdLCB4OiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBBID0gcGFyYW1zWzBdO1xuICBjb25zdCBCID0gcGFyYW1zWzFdO1xuICBjb25zdCBDID0gcGFyYW1zWzJdO1xuICBjb25zdCBEID0gcGFyYW1zWzNdO1xuICBjb25zdCByZXMgPSBEICsgKEEgLSBEKS8oMSArIE1hdGgucG93KDEwLCAoeCAtIEMpKkIpKTtcbiAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gZ2V0T2JqZWN0aXZlRGVyaXZhdGl2ZShvZjogT2JqZWN0aXZlRnVuY3Rpb24sIGN1cnZlRnVuY3Rpb246IChwYXJhbXM6IG51bWJlcltdLCB4OiBudW1iZXIpID0+IG51bWJlciwgXG4gICAgZGF0YToge3g6IG51bWJlcltdLCB5OiBudW1iZXJbXX0sIHBhcmFtczogbnVtYmVyW10sIHNlbGVjdGVkUGFyYW06IG51bWJlcik6IG51bWJlciB7XG4gIGxldCBzdGVwID0gcGFyYW1zW3NlbGVjdGVkUGFyYW1dKjAuMDAwMTtcbiAgc3RlcCA9IHN0ZXAgPT0gMCA/IDAuMDAxIDogc3RlcDsgXG4gIGxldCBwYXJhbXNUb3A6IG51bWJlcltdID0gW107XG4gIGxldCBwYXJhbXNCb3R0b206IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYoaSA9PSBzZWxlY3RlZFBhcmFtKSB7XG4gICAgICBwYXJhbXNUb3AucHVzaChwYXJhbXNbaV0gKyBzdGVwKTtcbiAgICAgIHBhcmFtc0JvdHRvbS5wdXNoKHBhcmFtc1tpXSAtIHN0ZXApO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYXJhbXNUb3AucHVzaChwYXJhbXNbaV0pO1xuICAgICAgcGFyYW1zQm90dG9tLnB1c2gocGFyYW1zW2ldKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgZHJ2VG9wID0gb2YoY3VydmVGdW5jdGlvbiwgZGF0YSwgcGFyYW1zVG9wKS52YWx1ZTtcbiAgY29uc3QgZHJ2Qm90dG9tID0gb2YoY3VydmVGdW5jdGlvbiwgZGF0YSwgcGFyYW1zQm90dG9tKS52YWx1ZTtcblxuICByZXR1cm4gKGRydlRvcCAtIGRydkJvdHRvbSkvKDIqc3RlcCk7XG59XG5cbmZ1bmN0aW9uIGdldEF1YyhmaXR0ZWRDdXJ2ZTogKHg6IG51bWJlcikgPT4gbnVtYmVyLCBcbiAgICAgICAgICAgICAgICBkYXRhOiB7eDogbnVtYmVyW10sIHk6IG51bWJlcltdfSk6IG51bWJlciB7XG4gIGxldCBhdWMgPSAwO1xuICBjb25zdCBpbnRlZ3JhdGlvblN0ZXAgPSAwLjAwMDAxO1xuICBsZXQgbWluID0gTWF0aC5taW4oLi4uZGF0YS54KTtcbiAgbGV0IG1heCA9IE1hdGgubWF4KC4uLmRhdGEueCk7XG5cblxuICBmb3IobGV0IHggPSBtaW47IHggPCBtYXg7IHgrPSBpbnRlZ3JhdGlvblN0ZXApXG4gICAgYXVjICs9IGludGVncmF0aW9uU3RlcCpmaXR0ZWRDdXJ2ZSh4KTtcblxuICByZXR1cm4gYXVjO1xufVxuXG5mdW5jdGlvbiBnZXREZXRDb2VmZihmaXR0ZWRDdXJ2ZTogKHg6IG51bWJlcikgPT4gbnVtYmVyLCBcbiAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHt4OiBudW1iZXJbXSwgeTogbnVtYmVyW119KTogbnVtYmVyIHtcbiAgbGV0IHNzUmVzID0gMDtcbiAgbGV0IHNzVG90ID0gMDtcbiAgXG4gIGNvbnN0IHlNZWFuID0galN0YXQubWVhbihkYXRhLnkpO1xuXG4gIGZvcihsZXQgaSA9IDA7IGkgPCBkYXRhLngubGVuZ3RoOyBpKyspIHtcbiAgICBzc1JlcyArPSBNYXRoLnBvdyhkYXRhLnlbaV0gLSBmaXR0ZWRDdXJ2ZShkYXRhLnhbaV0pLCAyKTtcbiAgICBzc1RvdCArPSBNYXRoLnBvdyhkYXRhLnlbaV0gLSB5TWVhbiwgMik7XG4gIH1cblxuICByZXR1cm4gMSAtIHNzUmVzL3NzVG90O1xufVxuXG5cbmZ1bmN0aW9uIG9iamVjdGl2ZU5vcm1hbENvbnN0YW50IChcbiAgdGFyZ2V0RnVuYzogKHBhcmFtczogbnVtYmVyW10sIHg6IG51bWJlcikgPT4gbnVtYmVyLCBcbiAgZGF0YToge3k6IG51bWJlcltdLCB4OiBudW1iZXJbXX0sXG4gIHBhcmFtczogbnVtYmVyW11cbik6IExpa2VsaWhvb2Qge1xuICAvL2Fzc3VyZSBvYnNlcnZlZCBhbmQgYXJncyBzYW1lIGxlbmd0aFxuICBjb25zdCBwaSA9IE1hdGguUEk7XG4gIGxldCBzaWdtYSA9IDA7XG4gIGxldCBzaWdtYVNxID0gMDtcbiAgbGV0IGxpa2VsaWhvb2QgPSAwO1xuXG4gIGxldCByZXNpZHVlc1NxdWFyZXMgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEueC5sZW5ndGgpO1xuICBmb3IobGV0IGkgPSAwOyBpIDwgZGF0YS54Lmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3Qgb2JzID0gZGF0YS55W2ldO1xuICAgIGNvbnN0IHByZWQgPSB0YXJnZXRGdW5jKHBhcmFtcywgZGF0YS54W2ldKTtcbiAgICByZXNpZHVlc1NxdWFyZXNbaV0gPSBNYXRoLnBvdyhvYnMgLSBwcmVkLCAyKTtcbiAgfVxuXG4gIGZvcihsZXQgaSA9IDA7IGkgPCByZXNpZHVlc1NxdWFyZXMubGVuZ3RoOyBpKyspXG4gICAgc2lnbWFTcSArPSByZXNpZHVlc1NxdWFyZXNbaV07XG4gIHNpZ21hU3EgLz0gcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDtcbiAgc2lnbWEgPSBNYXRoLnNxcnQoc2lnbWFTcSk7XG5cbiAgZm9yKGxldCBpID0gMDsgaSA8IHJlc2lkdWVzU3F1YXJlcy5sZW5ndGg7IGkrKylcbiAgICBsaWtlbGlob29kICs9IHJlc2lkdWVzU3F1YXJlc1tpXS9zaWdtYVNxICsgTWF0aC5sb2coMiAqIHBpICogc2lnbWFTcSk7XG5cbiAgcmV0dXJuIHt2YWx1ZTogLWxpa2VsaWhvb2QsIGNvbnN0OiBzaWdtYSwgbXVsdDogMH07ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxufVxuXG5mdW5jdGlvbiBvYmplY3RpdmVOb3JtYWxQcm9wb3J0aW9uYWwgKFxudGFyZ2V0RnVuYzogKHBhcmFtczogbnVtYmVyW10sIHg6IG51bWJlcikgPT4gbnVtYmVyLCBcbmRhdGE6IHt5OiBudW1iZXJbXSwgeDogbnVtYmVyW119LFxucGFyYW1zOiBudW1iZXJbXVxuKTogTGlrZWxpaG9vZCB7XG4gIC8vYXNzdXJlIG9ic2VydmVkIGFuZCBhcmdzIHNhbWUgbGVuZ3RoXG4gIGNvbnN0IHBpID0gTWF0aC5QSTtcbiAgbGV0IHNpZ21hID0gMDtcbiAgbGV0IHNpZ21hU3EgPSAwO1xuICBsZXQgbGlrZWxpaG9vZCA9IDA7XG5cbiAgbGV0IHJlc2lkdWVzU3F1YXJlcyA9IG5ldyBGbG9hdDMyQXJyYXkoZGF0YS54Lmxlbmd0aCk7XG4gIGZvcihsZXQgaSA9IDA7IGkgPCBkYXRhLngubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBvYnMgPSBkYXRhLnlbaV07XG4gICAgY29uc3QgcHJlZCA9IHRhcmdldEZ1bmMocGFyYW1zLCBkYXRhLnhbaV0pXG4gICAgcmVzaWR1ZXNTcXVhcmVzW2ldID0gTWF0aC5wb3cob2JzIC0gcHJlZCwgMik7XG4gIH1cblxuICBmb3IobGV0IGkgPSAwOyBpIDwgcmVzaWR1ZXNTcXVhcmVzLmxlbmd0aDsgaSsrKVxuICAgIHNpZ21hU3EgKz0gcmVzaWR1ZXNTcXVhcmVzW2ldO1xuICBzaWdtYVNxIC89IHJlc2lkdWVzU3F1YXJlcy5sZW5ndGg7XG4gIHNpZ21hID0gTWF0aC5zcXJ0KHNpZ21hU3EpO1xuXG4gIGZvcihsZXQgaSA9IDA7IGkgPCByZXNpZHVlc1NxdWFyZXMubGVuZ3RoOyBpKyspXG4gICAgbGlrZWxpaG9vZCArPSByZXNpZHVlc1NxdWFyZXNbaV0vc2lnbWFTcSArIE1hdGgubG9nKDIqcGkqc2lnbWFTcSk7XG5cbiAgcmV0dXJuIHt2YWx1ZTogLWxpa2VsaWhvb2QsIGNvbnN0OiBzaWdtYSwgbXVsdDogMH07ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxufVxuIl19