1 | /**
|
2 | * @license
|
3 | * Copyright 2018 Google LLC
|
4 | *
|
5 | * Use of this source code is governed by an MIT-style
|
6 | * license that can be found in the LICENSE file or at
|
7 | * https://opensource.org/licenses/MIT.
|
8 | * =============================================================================
|
9 | */
|
10 | /**
|
11 | * TensorFlow.js Layers: Recurrent Neural Network Layers.
|
12 | */
|
13 | import * as tfc from '@tensorflow/tfjs-core';
|
14 | import { serialization, tidy, util } from '@tensorflow/tfjs-core';
|
15 | import { getActivation, serializeActivation } from '../activations';
|
16 | import * as K from '../backend/tfjs_backend';
|
17 | import { nameScope } from '../common';
|
18 | import { getConstraint, serializeConstraint } from '../constraints';
|
19 | import { InputSpec, SymbolicTensor } from '../engine/topology';
|
20 | import { Layer } from '../engine/topology';
|
21 | import { AttributeError, NotImplementedError, ValueError } from '../errors';
|
22 | import { getInitializer, Initializer, Ones, serializeInitializer } from '../initializers';
|
23 | import { getRegularizer, serializeRegularizer } from '../regularizers';
|
24 | import { assertPositiveInteger } from '../utils/generic_utils';
|
25 | import * as math_utils from '../utils/math_utils';
|
26 | import { getExactlyOneShape, getExactlyOneTensor, isArrayOfShapes } from '../utils/types_utils';
|
27 | import { batchGetValue, batchSetValue } from '../variables';
|
28 | import { deserialize } from './serialization';
|
29 | /**
|
30 | * Standardize `apply()` args to a single list of tensor inputs.
|
31 | *
|
32 | * When running a model loaded from file, the input tensors `initialState` and
|
33 | * `constants` are passed to `RNN.apply()` as part of `inputs` instead of the
|
34 | * dedicated kwargs fields. `inputs` consists of
|
35 | * `[inputs, initialState0, initialState1, ..., constant0, constant1]` in this
|
36 | * case.
|
37 | * This method makes sure that arguments are
|
38 | * separated and that `initialState` and `constants` are `Array`s of tensors
|
39 | * (or None).
|
40 | *
|
41 | * @param inputs Tensor or `Array` of tensors.
|
42 | * @param initialState Tensor or `Array` of tensors or `null`/`undefined`.
|
43 | * @param constants Tensor or `Array` of tensors or `null`/`undefined`.
|
44 | * @returns An object consisting of
|
45 | * inputs: A tensor.
|
46 | * initialState: `Array` of tensors or `null`.
|
47 | * constants: `Array` of tensors or `null`.
|
48 | * @throws ValueError, if `inputs` is an `Array` but either `initialState` or
|
49 | * `constants` is provided.
|
50 | */
|
51 | export function standardizeArgs(inputs, initialState, constants, numConstants) {
|
52 | if (Array.isArray(inputs)) {
|
53 | if (initialState != null || constants != null) {
|
54 | throw new ValueError('When inputs is an array, neither initialState or constants ' +
|
55 | 'should be provided');
|
56 | }
|
57 | if (numConstants != null) {
|
58 | constants = inputs.slice(inputs.length - numConstants, inputs.length);
|
59 | inputs = inputs.slice(0, inputs.length - numConstants);
|
60 | }
|
61 | if (inputs.length > 1) {
|
62 | initialState = inputs.slice(1, inputs.length);
|
63 | }
|
64 | inputs = inputs[0];
|
65 | }
|
66 | function toListOrNull(x) {
|
67 | if (x == null || Array.isArray(x)) {
|
68 | return x;
|
69 | }
|
70 | else {
|
71 | return [x];
|
72 | }
|
73 | }
|
74 | initialState = toListOrNull(initialState);
|
75 | constants = toListOrNull(constants);
|
76 | return { inputs, initialState, constants };
|
77 | }
|
78 | /**
|
79 | * Iterates over the time dimension of a tensor.
|
80 | *
|
81 | * @param stepFunction RNN step function.
|
82 | * Parameters:
|
83 | * inputs: tensor with shape `[samples, ...]` (no time dimension),
|
84 | * representing input for the batch of samples at a certain time step.
|
85 | * states: an Array of tensors.
|
86 | * Returns:
|
87 | * outputs: tensor with shape `[samples, outputDim]` (no time dimension).
|
88 | * newStates: list of tensors, same length and shapes as `states`. The first
|
89 | * state in the list must be the output tensor at the previous timestep.
|
90 | * @param inputs Tensor of temporal data of shape `[samples, time, ...]` (at
|
91 | * least 3D).
|
92 | * @param initialStates Tensor with shape `[samples, outputDim]` (no time
|
93 | * dimension), containing the initial values of the states used in the step
|
94 | * function.
|
95 | * @param goBackwards If `true`, do the iteration over the time dimension in
|
96 | * reverse order and return the reversed sequence.
|
97 | * @param mask Binary tensor with shape `[sample, time, 1]`, with a zero for
|
98 | * every element that is masked.
|
99 | * @param constants An Array of constant values passed at each step.
|
100 | * @param unroll Whether to unroll the RNN or to use a symbolic loop. *Not*
|
101 | * applicable to this imperative deeplearn.js backend. Its value is ignored.
|
102 | * @param needPerStepOutputs Whether the per-step outputs are to be
|
103 | * concatenated into a single tensor and returned (as the second return
|
104 | * value). Default: `false`. This arg is included so that the relatively
|
105 | * expensive concatenation of the stepwise outputs can be omitted unless
|
106 | * the stepwise outputs need to be kept (e.g., for an LSTM layer of which
|
107 | * `returnSequence` is `true`.)
|
108 | * @returns An Array: `[lastOutput, outputs, newStates]`.
|
109 | * lastOutput: the lastest output of the RNN, of shape `[samples, ...]`.
|
110 | * outputs: tensor with shape `[samples, time, ...]` where each entry
|
111 | * `output[s, t]` is the output of the step function at time `t` for sample
|
112 | * `s`. This return value is provided if and only if the
|
113 | * `needPerStepOutputs` is set as `true`. If it is set as `false`, this
|
114 | * return value will be `undefined`.
|
115 | * newStates: Array of tensors, latest states returned by the step function,
|
116 | * of shape `(samples, ...)`.
|
117 | * @throws ValueError If input dimension is less than 3.
|
118 | *
|
119 | * TODO(nielsene): This needs to be tidy-ed.
|
120 | */
|
121 | export function rnn(stepFunction, inputs, initialStates, goBackwards = false, mask, constants, unroll = false, needPerStepOutputs = false) {
|
122 | return tfc.tidy(() => {
|
123 | const ndim = inputs.shape.length;
|
124 | if (ndim < 3) {
|
125 | throw new ValueError(`Input should be at least 3D, but is ${ndim}D.`);
|
126 | }
|
127 | // Transpose to time-major, i.e., from [batch, time, ...] to [time, batch,
|
128 | // ...].
|
129 | const axes = [1, 0].concat(math_utils.range(2, ndim));
|
130 | inputs = tfc.transpose(inputs, axes);
|
131 | if (constants != null) {
|
132 | throw new NotImplementedError('The rnn() functoin of the deeplearn.js backend does not support ' +
|
133 | 'constants yet.');
|
134 | }
|
135 | // Porting Note: the unroll option is ignored by the imperative backend.
|
136 | if (unroll) {
|
137 | console.warn('Backend rnn(): the unroll = true option is not applicable to the ' +
|
138 | 'imperative deeplearn.js backend.');
|
139 | }
|
140 | if (mask != null) {
|
141 | mask = tfc.cast(tfc.cast(mask, 'bool'), 'float32');
|
142 | if (mask.rank === ndim - 1) {
|
143 | mask = tfc.expandDims(mask, -1);
|
144 | }
|
145 | mask = tfc.transpose(mask, axes);
|
146 | }
|
147 | if (goBackwards) {
|
148 | inputs = tfc.reverse(inputs, 0);
|
149 | if (mask != null) {
|
150 | mask = tfc.reverse(mask, 0);
|
151 | }
|
152 | }
|
153 | // Porting Note: PyKeras with TensorFlow backend uses a symbolic loop
|
154 | // (tf.while_loop). But for the imperative deeplearn.js backend, we just
|
155 | // use the usual TypeScript control flow to iterate over the time steps in
|
156 | // the inputs.
|
157 | // Porting Note: PyKeras patches a "_use_learning_phase" attribute to
|
158 | // outputs.
|
159 | // This is not idiomatic in TypeScript. The info regarding whether we are
|
160 | // in a learning (i.e., training) phase for RNN is passed in a different
|
161 | // way.
|
162 | const perStepOutputs = [];
|
163 | let lastOutput;
|
164 | let states = initialStates;
|
165 | const timeSteps = inputs.shape[0];
|
166 | const perStepInputs = tfc.unstack(inputs);
|
167 | let perStepMasks;
|
168 | if (mask != null) {
|
169 | perStepMasks = tfc.unstack(mask);
|
170 | }
|
171 | for (let t = 0; t < timeSteps; ++t) {
|
172 | const currentInput = perStepInputs[t];
|
173 | const stepOutputs = tfc.tidy(() => stepFunction(currentInput, states));
|
174 | if (mask == null) {
|
175 | lastOutput = stepOutputs[0];
|
176 | states = stepOutputs[1];
|
177 | }
|
178 | else {
|
179 | const maskedOutputs = tfc.tidy(() => {
|
180 | const stepMask = perStepMasks[t];
|
181 | const negStepMask = tfc.sub(tfc.onesLike(stepMask), stepMask);
|
182 | // TODO(cais): Would tfc.where() be better for performance?
|
183 | const output = tfc.add(tfc.mul(stepOutputs[0], stepMask), tfc.mul(states[0], negStepMask));
|
184 | const newStates = states.map((state, i) => {
|
185 | return tfc.add(tfc.mul(stepOutputs[1][i], stepMask), tfc.mul(state, negStepMask));
|
186 | });
|
187 | return { output, newStates };
|
188 | });
|
189 | lastOutput = maskedOutputs.output;
|
190 | states = maskedOutputs.newStates;
|
191 | }
|
192 | if (needPerStepOutputs) {
|
193 | perStepOutputs.push(lastOutput);
|
194 | }
|
195 | }
|
196 | let outputs;
|
197 | if (needPerStepOutputs) {
|
198 | const axis = 1;
|
199 | outputs = tfc.stack(perStepOutputs, axis);
|
200 | }
|
201 | return [lastOutput, outputs, states];
|
202 | });
|
203 | }
|
204 | export class RNN extends Layer {
|
205 | constructor(args) {
|
206 | super(args);
|
207 | let cell;
|
208 | if (args.cell == null) {
|
209 | throw new ValueError('cell property is missing for the constructor of RNN.');
|
210 | }
|
211 | else if (Array.isArray(args.cell)) {
|
212 | cell = new StackedRNNCells({ cells: args.cell });
|
213 | }
|
214 | else {
|
215 | cell = args.cell;
|
216 | }
|
217 | if (cell.stateSize == null) {
|
218 | throw new ValueError('The RNN cell should have an attribute `stateSize` (tuple of ' +
|
219 | 'integers, one integer per RNN state).');
|
220 | }
|
221 | this.cell = cell;
|
222 | this.returnSequences =
|
223 | args.returnSequences == null ? false : args.returnSequences;
|
224 | this.returnState = args.returnState == null ? false : args.returnState;
|
225 | this.goBackwards = args.goBackwards == null ? false : args.goBackwards;
|
226 | this._stateful = args.stateful == null ? false : args.stateful;
|
227 | this.unroll = args.unroll == null ? false : args.unroll;
|
228 | this.supportsMasking = true;
|
229 | this.inputSpec = [new InputSpec({ ndim: 3 })];
|
230 | this.stateSpec = null;
|
231 | this.states_ = null;
|
232 | // TODO(cais): Add constantsSpec and numConstants.
|
233 | this.numConstants = null;
|
234 | // TODO(cais): Look into the use of initial_state in the kwargs of the
|
235 | // constructor.
|
236 | this.keptStates = [];
|
237 | }
|
238 | // Porting Note: This is the equivalent of `RNN.states` property getter in
|
239 | // PyKeras.
|
240 | getStates() {
|
241 | if (this.states_ == null) {
|
242 | const numStates = Array.isArray(this.cell.stateSize) ? this.cell.stateSize.length : 1;
|
243 | return math_utils.range(0, numStates).map(x => null);
|
244 | }
|
245 | else {
|
246 | return this.states_;
|
247 | }
|
248 | }
|
249 | // Porting Note: This is the equivalent of the `RNN.states` property setter in
|
250 | // PyKeras.
|
251 | setStates(states) {
|
252 | this.states_ = states;
|
253 | }
|
254 | computeOutputShape(inputShape) {
|
255 | if (isArrayOfShapes(inputShape)) {
|
256 | inputShape = inputShape[0];
|
257 | }
|
258 | inputShape = inputShape;
|
259 | // TODO(cais): Remove the casting once stacked RNN cells become supported.
|
260 | let stateSize = this.cell.stateSize;
|
261 | if (!Array.isArray(stateSize)) {
|
262 | stateSize = [stateSize];
|
263 | }
|
264 | const outputDim = stateSize[0];
|
265 | let outputShape;
|
266 | if (this.returnSequences) {
|
267 | outputShape = [inputShape[0], inputShape[1], outputDim];
|
268 | }
|
269 | else {
|
270 | outputShape = [inputShape[0], outputDim];
|
271 | }
|
272 | if (this.returnState) {
|
273 | const stateShape = [];
|
274 | for (const dim of stateSize) {
|
275 | stateShape.push([inputShape[0], dim]);
|
276 | }
|
277 | return [outputShape].concat(stateShape);
|
278 | }
|
279 | else {
|
280 | return outputShape;
|
281 | }
|
282 | }
|
283 | computeMask(inputs, mask) {
|
284 | return tfc.tidy(() => {
|
285 | if (Array.isArray(mask)) {
|
286 | mask = mask[0];
|
287 | }
|
288 | const outputMask = this.returnSequences ? mask : null;
|
289 | if (this.returnState) {
|
290 | const stateMask = this.states.map(s => null);
|
291 | return [outputMask].concat(stateMask);
|
292 | }
|
293 | else {
|
294 | return outputMask;
|
295 | }
|
296 | });
|
297 | }
|
298 | /**
|
299 | * Get the current state tensors of the RNN.
|
300 | *
|
301 | * If the state hasn't been set, return an array of `null`s of the correct
|
302 | * length.
|
303 | */
|
304 | get states() {
|
305 | if (this.states_ == null) {
|
306 | const numStates = Array.isArray(this.cell.stateSize) ? this.cell.stateSize.length : 1;
|
307 | const output = [];
|
308 | for (let i = 0; i < numStates; ++i) {
|
309 | output.push(null);
|
310 | }
|
311 | return output;
|
312 | }
|
313 | else {
|
314 | return this.states_;
|
315 | }
|
316 | }
|
317 | set states(s) {
|
318 | this.states_ = s;
|
319 | }
|
320 | build(inputShape) {
|
321 | // Note inputShape will be an Array of Shapes of initial states and
|
322 | // constants if these are passed in apply().
|
323 | const constantShape = null;
|
324 | if (this.numConstants != null) {
|
325 | throw new NotImplementedError('Constants support is not implemented in RNN yet.');
|
326 | }
|
327 | if (isArrayOfShapes(inputShape)) {
|
328 | inputShape = inputShape[0];
|
329 | }
|
330 | inputShape = inputShape;
|
331 | const batchSize = this.stateful ? inputShape[0] : null;
|
332 | const inputDim = inputShape.slice(2);
|
333 | this.inputSpec[0] = new InputSpec({ shape: [batchSize, null, ...inputDim] });
|
334 | // Allow cell (if RNNCell Layer) to build before we set or validate
|
335 | // stateSpec.
|
336 | const stepInputShape = [inputShape[0]].concat(inputShape.slice(2));
|
337 | if (constantShape != null) {
|
338 | throw new NotImplementedError('Constants support is not implemented in RNN yet.');
|
339 | }
|
340 | else {
|
341 | this.cell.build(stepInputShape);
|
342 | }
|
343 | // Set or validate stateSpec.
|
344 | let stateSize;
|
345 | if (Array.isArray(this.cell.stateSize)) {
|
346 | stateSize = this.cell.stateSize;
|
347 | }
|
348 | else {
|
349 | stateSize = [this.cell.stateSize];
|
350 | }
|
351 | if (this.stateSpec != null) {
|
352 | if (!util.arraysEqual(this.stateSpec.map(spec => spec.shape[spec.shape.length - 1]), stateSize)) {
|
353 | throw new ValueError(`An initialState was passed that is not compatible with ` +
|
354 | `cell.stateSize. Received stateSpec=${this.stateSpec}; ` +
|
355 | `However cell.stateSize is ${this.cell.stateSize}`);
|
356 | }
|
357 | }
|
358 | else {
|
359 | this.stateSpec =
|
360 | stateSize.map(dim => new InputSpec({ shape: [null, dim] }));
|
361 | }
|
362 | if (this.stateful) {
|
363 | this.resetStates();
|
364 | }
|
365 | }
|
366 | /**
|
367 | * Reset the state tensors of the RNN.
|
368 | *
|
369 | * If the `states` argument is `undefined` or `null`, will set the
|
370 | * state tensor(s) of the RNN to all-zero tensors of the appropriate
|
371 | * shape(s).
|
372 | *
|
373 | * If `states` is provided, will set the state tensors of the RNN to its
|
374 | * value.
|
375 | *
|
376 | * @param states Optional externally-provided initial states.
|
377 | * @param training Whether this call is done during training. For stateful
|
378 | * RNNs, this affects whether the old states are kept or discarded. In
|
379 | * particular, if `training` is `true`, the old states will be kept so
|
380 | * that subsequent backpropgataion through time (BPTT) may work properly.
|
381 | * Else, the old states will be discarded.
|
382 | */
|
383 | resetStates(states, training = false) {
|
384 | tidy(() => {
|
385 | if (!this.stateful) {
|
386 | throw new AttributeError('Cannot call resetStates() on an RNN Layer that is not stateful.');
|
387 | }
|
388 | const batchSize = this.inputSpec[0].shape[0];
|
389 | if (batchSize == null) {
|
390 | throw new ValueError('If an RNN is stateful, it needs to know its batch size. Specify ' +
|
391 | 'the batch size of your input tensors: \n' +
|
392 | '- If using a Sequential model, specify the batch size by ' +
|
393 | 'passing a `batchInputShape` option to your first layer.\n' +
|
394 | '- If using the functional API, specify the batch size by ' +
|
395 | 'passing a `batchShape` option to your Input layer.');
|
396 | }
|
397 | // Initialize state if null.
|
398 | if (this.states_ == null) {
|
399 | if (Array.isArray(this.cell.stateSize)) {
|
400 | this.states_ =
|
401 | this.cell.stateSize.map(dim => tfc.zeros([batchSize, dim]));
|
402 | }
|
403 | else {
|
404 | this.states_ = [tfc.zeros([batchSize, this.cell.stateSize])];
|
405 | }
|
406 | }
|
407 | else if (states == null) {
|
408 | // Dispose old state tensors.
|
409 | tfc.dispose(this.states_);
|
410 | // For stateful RNNs, fully dispose kept old states.
|
411 | if (this.keptStates != null) {
|
412 | tfc.dispose(this.keptStates);
|
413 | this.keptStates = [];
|
414 | }
|
415 | if (Array.isArray(this.cell.stateSize)) {
|
416 | this.states_ =
|
417 | this.cell.stateSize.map(dim => tfc.zeros([batchSize, dim]));
|
418 | }
|
419 | else {
|
420 | this.states_[0] = tfc.zeros([batchSize, this.cell.stateSize]);
|
421 | }
|
422 | }
|
423 | else {
|
424 | if (!Array.isArray(states)) {
|
425 | states = [states];
|
426 | }
|
427 | if (states.length !== this.states_.length) {
|
428 | throw new ValueError(`Layer ${this.name} expects ${this.states_.length} state(s), ` +
|
429 | `but it received ${states.length} state value(s). Input ` +
|
430 | `received: ${states}`);
|
431 | }
|
432 | if (training === true) {
|
433 | // Store old state tensors for complete disposal later, i.e., during
|
434 | // the next no-arg call to this method. We do not dispose the old
|
435 | // states immediately because that BPTT (among other things) require
|
436 | // them.
|
437 | this.keptStates.push(this.states_.slice());
|
438 | }
|
439 | else {
|
440 | tfc.dispose(this.states_);
|
441 | }
|
442 | for (let index = 0; index < this.states_.length; ++index) {
|
443 | const value = states[index];
|
444 | const dim = Array.isArray(this.cell.stateSize) ?
|
445 | this.cell.stateSize[index] :
|
446 | this.cell.stateSize;
|
447 | const expectedShape = [batchSize, dim];
|
448 | if (!util.arraysEqual(value.shape, expectedShape)) {
|
449 | throw new ValueError(`State ${index} is incompatible with layer ${this.name}: ` +
|
450 | `expected shape=${expectedShape}, received shape=${value.shape}`);
|
451 | }
|
452 | this.states_[index] = value;
|
453 | }
|
454 | }
|
455 | this.states_ = this.states_.map(state => tfc.keep(state.clone()));
|
456 | });
|
457 | }
|
458 | apply(inputs, kwargs) {
|
459 | // TODO(cais): Figure out whether initialState is in kwargs or inputs.
|
460 | let initialState = kwargs == null ? null : kwargs['initialState'];
|
461 | let constants = kwargs == null ? null : kwargs['constants'];
|
462 | if (kwargs == null) {
|
463 | kwargs = {};
|
464 | }
|
465 | const standardized = standardizeArgs(inputs, initialState, constants, this.numConstants);
|
466 | inputs = standardized.inputs;
|
467 | initialState = standardized.initialState;
|
468 | constants = standardized.constants;
|
469 | // If any of `initial_state` or `constants` are specified and are
|
470 | // `tf.SymbolicTensor`s, then add them to the inputs and temporarily modify
|
471 | // the input_spec to include them.
|
472 | let additionalInputs = [];
|
473 | let additionalSpecs = [];
|
474 | if (initialState != null) {
|
475 | kwargs['initialState'] = initialState;
|
476 | additionalInputs = additionalInputs.concat(initialState);
|
477 | this.stateSpec = [];
|
478 | for (const state of initialState) {
|
479 | this.stateSpec.push(new InputSpec({ shape: state.shape }));
|
480 | }
|
481 | // TODO(cais): Use the following instead.
|
482 | // this.stateSpec = initialState.map(state => new InputSpec({shape:
|
483 | // state.shape}));
|
484 | additionalSpecs = additionalSpecs.concat(this.stateSpec);
|
485 | }
|
486 | if (constants != null) {
|
487 | kwargs['constants'] = constants;
|
488 | additionalInputs = additionalInputs.concat(constants);
|
489 | // TODO(cais): Add this.constantsSpec.
|
490 | this.numConstants = constants.length;
|
491 | }
|
492 | const isTensor = additionalInputs[0] instanceof SymbolicTensor;
|
493 | if (isTensor) {
|
494 | // Compute full input spec, including state and constants.
|
495 | const fullInput = [inputs].concat(additionalInputs);
|
496 | const fullInputSpec = this.inputSpec.concat(additionalSpecs);
|
497 | // Perform the call with temporarily replaced inputSpec.
|
498 | const originalInputSpec = this.inputSpec;
|
499 | this.inputSpec = fullInputSpec;
|
500 | const output = super.apply(fullInput, kwargs);
|
501 | this.inputSpec = originalInputSpec;
|
502 | return output;
|
503 | }
|
504 | else {
|
505 | return super.apply(inputs, kwargs);
|
506 | }
|
507 | }
|
508 | // tslint:disable-next-line:no-any
|
509 | call(inputs, kwargs) {
|
510 | // Input shape: `[samples, time (padded with zeros), input_dim]`.
|
511 | // Note that the .build() method of subclasses **must** define
|
512 | // this.inputSpec and this.stateSpec owith complete input shapes.
|
513 | return tidy(() => {
|
514 | const mask = kwargs == null ? null : kwargs['mask'];
|
515 | const training = kwargs == null ? null : kwargs['training'];
|
516 | let initialState = kwargs == null ? null : kwargs['initialState'];
|
517 | inputs = getExactlyOneTensor(inputs);
|
518 | if (initialState == null) {
|
519 | if (this.stateful) {
|
520 | initialState = this.states_;
|
521 | }
|
522 | else {
|
523 | initialState = this.getInitialState(inputs);
|
524 | }
|
525 | }
|
526 | const numStates = Array.isArray(this.cell.stateSize) ? this.cell.stateSize.length : 1;
|
527 | if (initialState.length !== numStates) {
|
528 | throw new ValueError(`RNN Layer has ${numStates} state(s) but was passed ` +
|
529 | `${initialState.length} initial state(s).`);
|
530 | }
|
531 | if (this.unroll) {
|
532 | console.warn('Ignoring unroll = true for RNN layer, due to imperative backend.');
|
533 | }
|
534 | const cellCallKwargs = { training };
|
535 | // TODO(cais): Add support for constants.
|
536 | const step = (inputs, states) => {
|
537 | // `inputs` and `states` are concatenated to form a single `Array` of
|
538 | // `tf.Tensor`s as the input to `cell.call()`.
|
539 | const outputs = this.cell.call([inputs].concat(states), cellCallKwargs);
|
540 | // Marshall the return value into output and new states.
|
541 | return [outputs[0], outputs.slice(1)];
|
542 | };
|
543 | // TODO(cais): Add support for constants.
|
544 | const rnnOutputs = rnn(step, inputs, initialState, this.goBackwards, mask, null, this.unroll, this.returnSequences);
|
545 | const lastOutput = rnnOutputs[0];
|
546 | const outputs = rnnOutputs[1];
|
547 | const states = rnnOutputs[2];
|
548 | if (this.stateful) {
|
549 | this.resetStates(states, training);
|
550 | }
|
551 | const output = this.returnSequences ? outputs : lastOutput;
|
552 | // TODO(cais): Porperty set learning phase flag.
|
553 | if (this.returnState) {
|
554 | return [output].concat(states);
|
555 | }
|
556 | else {
|
557 | return output;
|
558 | }
|
559 | });
|
560 | }
|
561 | getInitialState(inputs) {
|
562 | return tidy(() => {
|
563 | // Build an all-zero tensor of shape [samples, outputDim].
|
564 | // [Samples, timeSteps, inputDim].
|
565 | let initialState = tfc.zeros(inputs.shape);
|
566 | // [Samples].
|
567 | initialState = tfc.sum(initialState, [1, 2]);
|
568 | initialState = K.expandDims(initialState); // [Samples, 1].
|
569 | if (Array.isArray(this.cell.stateSize)) {
|
570 | return this.cell.stateSize.map(dim => dim > 1 ? K.tile(initialState, [1, dim]) : initialState);
|
571 | }
|
572 | else {
|
573 | return this.cell.stateSize > 1 ?
|
574 | [K.tile(initialState, [1, this.cell.stateSize])] :
|
575 | [initialState];
|
576 | }
|
577 | });
|
578 | }
|
579 | get trainableWeights() {
|
580 | if (!this.trainable) {
|
581 | return [];
|
582 | }
|
583 | // Porting Note: In TypeScript, `this` is always an instance of `Layer`.
|
584 | return this.cell.trainableWeights;
|
585 | }
|
586 | get nonTrainableWeights() {
|
587 | // Porting Note: In TypeScript, `this` is always an instance of `Layer`.
|
588 | if (!this.trainable) {
|
589 | return this.cell.weights;
|
590 | }
|
591 | return this.cell.nonTrainableWeights;
|
592 | }
|
593 | setFastWeightInitDuringBuild(value) {
|
594 | super.setFastWeightInitDuringBuild(value);
|
595 | if (this.cell != null) {
|
596 | this.cell.setFastWeightInitDuringBuild(value);
|
597 | }
|
598 | }
|
599 | getConfig() {
|
600 | const baseConfig = super.getConfig();
|
601 | const config = {
|
602 | returnSequences: this.returnSequences,
|
603 | returnState: this.returnState,
|
604 | goBackwards: this.goBackwards,
|
605 | stateful: this.stateful,
|
606 | unroll: this.unroll,
|
607 | };
|
608 | if (this.numConstants != null) {
|
609 | config['numConstants'] = this.numConstants;
|
610 | }
|
611 | const cellConfig = this.cell.getConfig();
|
612 | if (this.getClassName() === RNN.className) {
|
613 | config['cell'] = {
|
614 | 'className': this.cell.getClassName(),
|
615 | 'config': cellConfig,
|
616 | };
|
617 | }
|
618 | // this order is necessary, to prevent cell name from replacing layer name
|
619 | return Object.assign(Object.assign(Object.assign({}, cellConfig), baseConfig), config);
|
620 | }
|
621 | /** @nocollapse */
|
622 | static fromConfig(cls, config, customObjects = {}) {
|
623 | const cellConfig = config['cell'];
|
624 | const cell = deserialize(cellConfig, customObjects);
|
625 | return new cls(Object.assign(config, { cell }));
|
626 | }
|
627 | }
|
628 | /** @nocollapse */
|
629 | RNN.className = 'RNN';
|
630 | serialization.registerClass(RNN);
|
631 | // Porting Note: This is a common parent class for RNN cells. There is no
|
632 | // equivalent of this in PyKeras. Having a common parent class forgoes the
|
633 | // need for `has_attr(cell, ...)` checks or its TypeScript equivalent.
|
634 | /**
|
635 | * An RNNCell layer.
|
636 | *
|
637 | * @doc {heading: 'Layers', subheading: 'Classes'}
|
638 | */
|
639 | export class RNNCell extends Layer {
|
640 | }
|
641 | export class SimpleRNNCell extends RNNCell {
|
642 | constructor(args) {
|
643 | super(args);
|
644 | this.DEFAULT_ACTIVATION = 'tanh';
|
645 | this.DEFAULT_KERNEL_INITIALIZER = 'glorotNormal';
|
646 | this.DEFAULT_RECURRENT_INITIALIZER = 'orthogonal';
|
647 | this.DEFAULT_BIAS_INITIALIZER = 'zeros';
|
648 | this.units = args.units;
|
649 | assertPositiveInteger(this.units, `units`);
|
650 | this.activation = getActivation(args.activation == null ? this.DEFAULT_ACTIVATION : args.activation);
|
651 | this.useBias = args.useBias == null ? true : args.useBias;
|
652 | this.kernelInitializer = getInitializer(args.kernelInitializer || this.DEFAULT_KERNEL_INITIALIZER);
|
653 | this.recurrentInitializer = getInitializer(args.recurrentInitializer || this.DEFAULT_RECURRENT_INITIALIZER);
|
654 | this.biasInitializer =
|
655 | getInitializer(args.biasInitializer || this.DEFAULT_BIAS_INITIALIZER);
|
656 | this.kernelRegularizer = getRegularizer(args.kernelRegularizer);
|
657 | this.recurrentRegularizer = getRegularizer(args.recurrentRegularizer);
|
658 | this.biasRegularizer = getRegularizer(args.biasRegularizer);
|
659 | this.kernelConstraint = getConstraint(args.kernelConstraint);
|
660 | this.recurrentConstraint = getConstraint(args.recurrentConstraint);
|
661 | this.biasConstraint = getConstraint(args.biasConstraint);
|
662 | this.dropout = math_utils.min([1, math_utils.max([0, args.dropout == null ? 0 : args.dropout])]);
|
663 | this.recurrentDropout = math_utils.min([
|
664 | 1,
|
665 | math_utils.max([0, args.recurrentDropout == null ? 0 : args.recurrentDropout])
|
666 | ]);
|
667 | this.dropoutFunc = args.dropoutFunc;
|
668 | this.stateSize = this.units;
|
669 | this.dropoutMask = null;
|
670 | this.recurrentDropoutMask = null;
|
671 | }
|
672 | build(inputShape) {
|
673 | inputShape = getExactlyOneShape(inputShape);
|
674 | // TODO(cais): Use regularizer.
|
675 | this.kernel = this.addWeight('kernel', [inputShape[inputShape.length - 1], this.units], null, this.kernelInitializer, this.kernelRegularizer, true, this.kernelConstraint);
|
676 | this.recurrentKernel = this.addWeight('recurrent_kernel', [this.units, this.units], null, this.recurrentInitializer, this.recurrentRegularizer, true, this.recurrentConstraint);
|
677 | if (this.useBias) {
|
678 | this.bias = this.addWeight('bias', [this.units], null, this.biasInitializer, this.biasRegularizer, true, this.biasConstraint);
|
679 | }
|
680 | else {
|
681 | this.bias = null;
|
682 | }
|
683 | this.built = true;
|
684 | }
|
685 | // Porting Note: PyKeras' equivalent of this method takes two tensor inputs:
|
686 | // `inputs` and `states`. Here, the two tensors are combined into an
|
687 | // `Tensor[]` Array as the first input argument.
|
688 | // Similarly, PyKeras' equivalent of this method returns two values:
|
689 | // `output` and `[output]`. Here the two are combined into one length-2
|
690 | // `Tensor[]`, consisting of `output` repeated.
|
691 | call(inputs, kwargs) {
|
692 | return tidy(() => {
|
693 | inputs = inputs;
|
694 | if (inputs.length !== 2) {
|
695 | throw new ValueError(`SimpleRNNCell expects 2 input Tensors, got ${inputs.length}.`);
|
696 | }
|
697 | let prevOutput = inputs[1];
|
698 | inputs = inputs[0];
|
699 | const training = kwargs['training'] == null ? false : kwargs['training'];
|
700 | if (0 < this.dropout && this.dropout < 1 && this.dropoutMask == null) {
|
701 | this.dropoutMask = generateDropoutMask({
|
702 | ones: () => tfc.onesLike(inputs),
|
703 | rate: this.dropout,
|
704 | training,
|
705 | dropoutFunc: this.dropoutFunc,
|
706 | });
|
707 | }
|
708 | if (0 < this.recurrentDropout && this.recurrentDropout < 1 &&
|
709 | this.recurrentDropoutMask == null) {
|
710 | this.recurrentDropoutMask = generateDropoutMask({
|
711 | ones: () => tfc.onesLike(prevOutput),
|
712 | rate: this.recurrentDropout,
|
713 | training,
|
714 | dropoutFunc: this.dropoutFunc,
|
715 | });
|
716 | }
|
717 | let h;
|
718 | const dpMask = this.dropoutMask;
|
719 | const recDpMask = this.recurrentDropoutMask;
|
720 | if (dpMask != null) {
|
721 | h = K.dot(tfc.mul(inputs, dpMask), this.kernel.read());
|
722 | }
|
723 | else {
|
724 | h = K.dot(inputs, this.kernel.read());
|
725 | }
|
726 | if (this.bias != null) {
|
727 | h = K.biasAdd(h, this.bias.read());
|
728 | }
|
729 | if (recDpMask != null) {
|
730 | prevOutput = tfc.mul(prevOutput, recDpMask);
|
731 | }
|
732 | let output = tfc.add(h, K.dot(prevOutput, this.recurrentKernel.read()));
|
733 | if (this.activation != null) {
|
734 | output = this.activation.apply(output);
|
735 | }
|
736 | // TODO(cais): Properly set learning phase on output tensor?
|
737 | return [output, output];
|
738 | });
|
739 | }
|
740 | getConfig() {
|
741 | const baseConfig = super.getConfig();
|
742 | const config = {
|
743 | units: this.units,
|
744 | activation: serializeActivation(this.activation),
|
745 | useBias: this.useBias,
|
746 | kernelInitializer: serializeInitializer(this.kernelInitializer),
|
747 | recurrentInitializer: serializeInitializer(this.recurrentInitializer),
|
748 | biasInitializer: serializeInitializer(this.biasInitializer),
|
749 | kernelRegularizer: serializeRegularizer(this.kernelRegularizer),
|
750 | recurrentRegularizer: serializeRegularizer(this.recurrentRegularizer),
|
751 | biasRegularizer: serializeRegularizer(this.biasRegularizer),
|
752 | activityRegularizer: serializeRegularizer(this.activityRegularizer),
|
753 | kernelConstraint: serializeConstraint(this.kernelConstraint),
|
754 | recurrentConstraint: serializeConstraint(this.recurrentConstraint),
|
755 | biasConstraint: serializeConstraint(this.biasConstraint),
|
756 | dropout: this.dropout,
|
757 | recurrentDropout: this.recurrentDropout,
|
758 | };
|
759 | return Object.assign(Object.assign({}, baseConfig), config);
|
760 | }
|
761 | }
|
762 | /** @nocollapse */
|
763 | SimpleRNNCell.className = 'SimpleRNNCell';
|
764 | serialization.registerClass(SimpleRNNCell);
|
765 | export class SimpleRNN extends RNN {
|
766 | constructor(args) {
|
767 | args.cell = new SimpleRNNCell(args);
|
768 | super(args);
|
769 | // TODO(cais): Add activityRegularizer.
|
770 | }
|
771 | call(inputs, kwargs) {
|
772 | return tidy(() => {
|
773 | if (this.cell.dropoutMask != null) {
|
774 | tfc.dispose(this.cell.dropoutMask);
|
775 | this.cell.dropoutMask = null;
|
776 | }
|
777 | if (this.cell.recurrentDropoutMask != null) {
|
778 | tfc.dispose(this.cell.recurrentDropoutMask);
|
779 | this.cell.recurrentDropoutMask = null;
|
780 | }
|
781 | const mask = kwargs == null ? null : kwargs['mask'];
|
782 | const training = kwargs == null ? null : kwargs['training'];
|
783 | const initialState = kwargs == null ? null : kwargs['initialState'];
|
784 | return super.call(inputs, { mask, training, initialState });
|
785 | });
|
786 | }
|
787 | /** @nocollapse */
|
788 | static fromConfig(cls, config) {
|
789 | return new cls(config);
|
790 | }
|
791 | }
|
792 | /** @nocollapse */
|
793 | SimpleRNN.className = 'SimpleRNN';
|
794 | serialization.registerClass(SimpleRNN);
|
795 | export class GRUCell extends RNNCell {
|
796 | constructor(args) {
|
797 | super(args);
|
798 | this.DEFAULT_ACTIVATION = 'tanh';
|
799 | this.DEFAULT_RECURRENT_ACTIVATION = 'hardSigmoid';
|
800 | this.DEFAULT_KERNEL_INITIALIZER = 'glorotNormal';
|
801 | this.DEFAULT_RECURRENT_INITIALIZER = 'orthogonal';
|
802 | this.DEFAULT_BIAS_INITIALIZER = 'zeros';
|
803 | if (args.resetAfter) {
|
804 | throw new ValueError(`GRUCell does not support reset_after parameter set to true.`);
|
805 | }
|
806 | this.units = args.units;
|
807 | assertPositiveInteger(this.units, 'units');
|
808 | this.activation = getActivation(args.activation === undefined ? this.DEFAULT_ACTIVATION :
|
809 | args.activation);
|
810 | this.recurrentActivation = getActivation(args.recurrentActivation === undefined ?
|
811 | this.DEFAULT_RECURRENT_ACTIVATION :
|
812 | args.recurrentActivation);
|
813 | this.useBias = args.useBias == null ? true : args.useBias;
|
814 | this.kernelInitializer = getInitializer(args.kernelInitializer || this.DEFAULT_KERNEL_INITIALIZER);
|
815 | this.recurrentInitializer = getInitializer(args.recurrentInitializer || this.DEFAULT_RECURRENT_INITIALIZER);
|
816 | this.biasInitializer =
|
817 | getInitializer(args.biasInitializer || this.DEFAULT_BIAS_INITIALIZER);
|
818 | this.kernelRegularizer = getRegularizer(args.kernelRegularizer);
|
819 | this.recurrentRegularizer = getRegularizer(args.recurrentRegularizer);
|
820 | this.biasRegularizer = getRegularizer(args.biasRegularizer);
|
821 | this.kernelConstraint = getConstraint(args.kernelConstraint);
|
822 | this.recurrentConstraint = getConstraint(args.recurrentConstraint);
|
823 | this.biasConstraint = getConstraint(args.biasConstraint);
|
824 | this.dropout = math_utils.min([1, math_utils.max([0, args.dropout == null ? 0 : args.dropout])]);
|
825 | this.recurrentDropout = math_utils.min([
|
826 | 1,
|
827 | math_utils.max([0, args.recurrentDropout == null ? 0 : args.recurrentDropout])
|
828 | ]);
|
829 | this.dropoutFunc = args.dropoutFunc;
|
830 | this.implementation = args.implementation;
|
831 | this.stateSize = this.units;
|
832 | this.dropoutMask = null;
|
833 | this.recurrentDropoutMask = null;
|
834 | }
|
835 | build(inputShape) {
|
836 | inputShape = getExactlyOneShape(inputShape);
|
837 | const inputDim = inputShape[inputShape.length - 1];
|
838 | this.kernel = this.addWeight('kernel', [inputDim, this.units * 3], null, this.kernelInitializer, this.kernelRegularizer, true, this.kernelConstraint);
|
839 | this.recurrentKernel = this.addWeight('recurrent_kernel', [this.units, this.units * 3], null, this.recurrentInitializer, this.recurrentRegularizer, true, this.recurrentConstraint);
|
840 | if (this.useBias) {
|
841 | this.bias = this.addWeight('bias', [this.units * 3], null, this.biasInitializer, this.biasRegularizer, true, this.biasConstraint);
|
842 | }
|
843 | else {
|
844 | this.bias = null;
|
845 | }
|
846 | // Porting Notes: Unlike the PyKeras implementation, we perform slicing
|
847 | // of the weights and bias in the call() method, at execution time.
|
848 | this.built = true;
|
849 | }
|
850 | call(inputs, kwargs) {
|
851 | return tidy(() => {
|
852 | inputs = inputs;
|
853 | if (inputs.length !== 2) {
|
854 | throw new ValueError(`GRUCell expects 2 input Tensors (inputs, h, c), got ` +
|
855 | `${inputs.length}.`);
|
856 | }
|
857 | const training = kwargs['training'] == null ? false : kwargs['training'];
|
858 | let hTMinus1 = inputs[1]; // Previous memory state.
|
859 | inputs = inputs[0];
|
860 | // Note: For superior performance, TensorFlow.js always uses
|
861 | // implementation 2, regardless of the actual value of
|
862 | // config.implementation.
|
863 | if (0 < this.dropout && this.dropout < 1 && this.dropoutMask == null) {
|
864 | this.dropoutMask = generateDropoutMask({
|
865 | ones: () => tfc.onesLike(inputs),
|
866 | rate: this.dropout,
|
867 | training,
|
868 | count: 3,
|
869 | dropoutFunc: this.dropoutFunc,
|
870 | });
|
871 | }
|
872 | if (0 < this.recurrentDropout && this.recurrentDropout < 1 &&
|
873 | this.recurrentDropoutMask == null) {
|
874 | this.recurrentDropoutMask = generateDropoutMask({
|
875 | ones: () => tfc.onesLike(hTMinus1),
|
876 | rate: this.recurrentDropout,
|
877 | training,
|
878 | count: 3,
|
879 | dropoutFunc: this.dropoutFunc,
|
880 | });
|
881 | }
|
882 | const dpMask = this.dropoutMask;
|
883 | const recDpMask = this.recurrentDropoutMask;
|
884 | let z;
|
885 | let r;
|
886 | let hh;
|
887 | if (0 < this.dropout && this.dropout < 1) {
|
888 | inputs = tfc.mul(inputs, dpMask[0]);
|
889 | }
|
890 | let matrixX = K.dot(inputs, this.kernel.read());
|
891 | if (this.useBias) {
|
892 | matrixX = K.biasAdd(matrixX, this.bias.read());
|
893 | }
|
894 | if (0 < this.recurrentDropout && this.recurrentDropout < 1) {
|
895 | hTMinus1 = tfc.mul(hTMinus1, recDpMask[0]);
|
896 | }
|
897 | const recurrentKernelValue = this.recurrentKernel.read();
|
898 | const [rk1, rk2] = tfc.split(recurrentKernelValue, [2 * this.units, this.units], recurrentKernelValue.rank - 1);
|
899 | const matrixInner = K.dot(hTMinus1, rk1);
|
900 | const [xZ, xR, xH] = tfc.split(matrixX, 3, matrixX.rank - 1);
|
901 | const [recurrentZ, recurrentR] = tfc.split(matrixInner, 2, matrixInner.rank - 1);
|
902 | z = this.recurrentActivation.apply(tfc.add(xZ, recurrentZ));
|
903 | r = this.recurrentActivation.apply(tfc.add(xR, recurrentR));
|
904 | const recurrentH = K.dot(tfc.mul(r, hTMinus1), rk2);
|
905 | hh = this.activation.apply(tfc.add(xH, recurrentH));
|
906 | const h = tfc.add(tfc.mul(z, hTMinus1), tfc.mul(tfc.add(1, tfc.neg(z)), hh));
|
907 | // TODO(cais): Add use_learning_phase flag properly.
|
908 | return [h, h];
|
909 | });
|
910 | }
|
911 | getConfig() {
|
912 | const baseConfig = super.getConfig();
|
913 | const config = {
|
914 | units: this.units,
|
915 | activation: serializeActivation(this.activation),
|
916 | recurrentActivation: serializeActivation(this.recurrentActivation),
|
917 | useBias: this.useBias,
|
918 | kernelInitializer: serializeInitializer(this.kernelInitializer),
|
919 | recurrentInitializer: serializeInitializer(this.recurrentInitializer),
|
920 | biasInitializer: serializeInitializer(this.biasInitializer),
|
921 | kernelRegularizer: serializeRegularizer(this.kernelRegularizer),
|
922 | recurrentRegularizer: serializeRegularizer(this.recurrentRegularizer),
|
923 | biasRegularizer: serializeRegularizer(this.biasRegularizer),
|
924 | activityRegularizer: serializeRegularizer(this.activityRegularizer),
|
925 | kernelConstraint: serializeConstraint(this.kernelConstraint),
|
926 | recurrentConstraint: serializeConstraint(this.recurrentConstraint),
|
927 | biasConstraint: serializeConstraint(this.biasConstraint),
|
928 | dropout: this.dropout,
|
929 | recurrentDropout: this.recurrentDropout,
|
930 | implementation: this.implementation,
|
931 | resetAfter: false
|
932 | };
|
933 | return Object.assign(Object.assign({}, baseConfig), config);
|
934 | }
|
935 | }
|
936 | /** @nocollapse */
|
937 | GRUCell.className = 'GRUCell';
|
938 | serialization.registerClass(GRUCell);
|
939 | export class GRU extends RNN {
|
940 | constructor(args) {
|
941 | if (args.implementation === 0) {
|
942 | console.warn('`implementation=0` has been deprecated, and now defaults to ' +
|
943 | '`implementation=1`. Please update your layer call.');
|
944 | }
|
945 | args.cell = new GRUCell(args);
|
946 | super(args);
|
947 | // TODO(cais): Add activityRegularizer.
|
948 | }
|
949 | call(inputs, kwargs) {
|
950 | return tidy(() => {
|
951 | if (this.cell.dropoutMask != null) {
|
952 | tfc.dispose(this.cell.dropoutMask);
|
953 | this.cell.dropoutMask = null;
|
954 | }
|
955 | if (this.cell.recurrentDropoutMask != null) {
|
956 | tfc.dispose(this.cell.recurrentDropoutMask);
|
957 | this.cell.recurrentDropoutMask = null;
|
958 | }
|
959 | const mask = kwargs == null ? null : kwargs['mask'];
|
960 | const training = kwargs == null ? null : kwargs['training'];
|
961 | const initialState = kwargs == null ? null : kwargs['initialState'];
|
962 | return super.call(inputs, { mask, training, initialState });
|
963 | });
|
964 | }
|
965 | /** @nocollapse */
|
966 | static fromConfig(cls, config) {
|
967 | if (config['implmentation'] === 0) {
|
968 | config['implementation'] = 1;
|
969 | }
|
970 | return new cls(config);
|
971 | }
|
972 | }
|
973 | /** @nocollapse */
|
974 | GRU.className = 'GRU';
|
975 | serialization.registerClass(GRU);
|
976 | export class LSTMCell extends RNNCell {
|
977 | constructor(args) {
|
978 | super(args);
|
979 | this.DEFAULT_ACTIVATION = 'tanh';
|
980 | this.DEFAULT_RECURRENT_ACTIVATION = 'hardSigmoid';
|
981 | this.DEFAULT_KERNEL_INITIALIZER = 'glorotNormal';
|
982 | this.DEFAULT_RECURRENT_INITIALIZER = 'orthogonal';
|
983 | this.DEFAULT_BIAS_INITIALIZER = 'zeros';
|
984 | this.units = args.units;
|
985 | assertPositiveInteger(this.units, 'units');
|
986 | this.activation = getActivation(args.activation === undefined ? this.DEFAULT_ACTIVATION :
|
987 | args.activation);
|
988 | this.recurrentActivation = getActivation(args.recurrentActivation === undefined ?
|
989 | this.DEFAULT_RECURRENT_ACTIVATION :
|
990 | args.recurrentActivation);
|
991 | this.useBias = args.useBias == null ? true : args.useBias;
|
992 | this.kernelInitializer = getInitializer(args.kernelInitializer || this.DEFAULT_KERNEL_INITIALIZER);
|
993 | this.recurrentInitializer = getInitializer(args.recurrentInitializer || this.DEFAULT_RECURRENT_INITIALIZER);
|
994 | this.biasInitializer =
|
995 | getInitializer(args.biasInitializer || this.DEFAULT_BIAS_INITIALIZER);
|
996 | this.unitForgetBias = args.unitForgetBias;
|
997 | this.kernelRegularizer = getRegularizer(args.kernelRegularizer);
|
998 | this.recurrentRegularizer = getRegularizer(args.recurrentRegularizer);
|
999 | this.biasRegularizer = getRegularizer(args.biasRegularizer);
|
1000 | this.kernelConstraint = getConstraint(args.kernelConstraint);
|
1001 | this.recurrentConstraint = getConstraint(args.recurrentConstraint);
|
1002 | this.biasConstraint = getConstraint(args.biasConstraint);
|
1003 | this.dropout = math_utils.min([1, math_utils.max([0, args.dropout == null ? 0 : args.dropout])]);
|
1004 | this.recurrentDropout = math_utils.min([
|
1005 | 1,
|
1006 | math_utils.max([0, args.recurrentDropout == null ? 0 : args.recurrentDropout])
|
1007 | ]);
|
1008 | this.dropoutFunc = args.dropoutFunc;
|
1009 | this.implementation = args.implementation;
|
1010 | this.stateSize = [this.units, this.units];
|
1011 | this.dropoutMask = null;
|
1012 | this.recurrentDropoutMask = null;
|
1013 | }
|
1014 | build(inputShape) {
|
1015 | var _a;
|
1016 | inputShape = getExactlyOneShape(inputShape);
|
1017 | const inputDim = inputShape[inputShape.length - 1];
|
1018 | this.kernel = this.addWeight('kernel', [inputDim, this.units * 4], null, this.kernelInitializer, this.kernelRegularizer, true, this.kernelConstraint);
|
1019 | this.recurrentKernel = this.addWeight('recurrent_kernel', [this.units, this.units * 4], null, this.recurrentInitializer, this.recurrentRegularizer, true, this.recurrentConstraint);
|
1020 | let biasInitializer;
|
1021 | if (this.useBias) {
|
1022 | if (this.unitForgetBias) {
|
1023 | const capturedBiasInit = this.biasInitializer;
|
1024 | const capturedUnits = this.units;
|
1025 | biasInitializer = new (_a = class CustomInit extends Initializer {
|
1026 | apply(shape, dtype) {
|
1027 | // TODO(cais): More informative variable names?
|
1028 | const bI = capturedBiasInit.apply([capturedUnits]);
|
1029 | const bF = (new Ones()).apply([capturedUnits]);
|
1030 | const bCAndH = capturedBiasInit.apply([capturedUnits * 2]);
|
1031 | return K.concatAlongFirstAxis(K.concatAlongFirstAxis(bI, bF), bCAndH);
|
1032 | }
|
1033 | },
|
1034 | /** @nocollapse */
|
1035 | _a.className = 'CustomInit',
|
1036 | _a)();
|
1037 | }
|
1038 | else {
|
1039 | biasInitializer = this.biasInitializer;
|
1040 | }
|
1041 | this.bias = this.addWeight('bias', [this.units * 4], null, biasInitializer, this.biasRegularizer, true, this.biasConstraint);
|
1042 | }
|
1043 | else {
|
1044 | this.bias = null;
|
1045 | }
|
1046 | // Porting Notes: Unlike the PyKeras implementation, we perform slicing
|
1047 | // of the weights and bias in the call() method, at execution time.
|
1048 | this.built = true;
|
1049 | }
|
1050 | call(inputs, kwargs) {
|
1051 | return tidy(() => {
|
1052 | const training = kwargs['training'] == null ? false : kwargs['training'];
|
1053 | inputs = inputs;
|
1054 | if (inputs.length !== 3) {
|
1055 | throw new ValueError(`LSTMCell expects 3 input Tensors (inputs, h, c), got ` +
|
1056 | `${inputs.length}.`);
|
1057 | }
|
1058 | let hTMinus1 = inputs[1]; // Previous memory state.
|
1059 | const cTMinus1 = inputs[2]; // Previous carry state.
|
1060 | inputs = inputs[0];
|
1061 | if (0 < this.dropout && this.dropout < 1 && this.dropoutMask == null) {
|
1062 | this.dropoutMask = generateDropoutMask({
|
1063 | ones: () => tfc.onesLike(inputs),
|
1064 | rate: this.dropout,
|
1065 | training,
|
1066 | count: 4,
|
1067 | dropoutFunc: this.dropoutFunc
|
1068 | });
|
1069 | }
|
1070 | if (0 < this.recurrentDropout && this.recurrentDropout < 1 &&
|
1071 | this.recurrentDropoutMask == null) {
|
1072 | this.recurrentDropoutMask = generateDropoutMask({
|
1073 | ones: () => tfc.onesLike(hTMinus1),
|
1074 | rate: this.recurrentDropout,
|
1075 | training,
|
1076 | count: 4,
|
1077 | dropoutFunc: this.dropoutFunc
|
1078 | });
|
1079 | }
|
1080 | const dpMask = this.dropoutMask;
|
1081 | const recDpMask = this.recurrentDropoutMask;
|
1082 | // Note: For superior performance, TensorFlow.js always uses
|
1083 | // implementation 2 regardless of the actual value of
|
1084 | // config.implementation.
|
1085 | let i;
|
1086 | let f;
|
1087 | let c;
|
1088 | let o;
|
1089 | if (0 < this.dropout && this.dropout < 1) {
|
1090 | inputs = tfc.mul(inputs, dpMask[0]);
|
1091 | }
|
1092 | let z = K.dot(inputs, this.kernel.read());
|
1093 | if (0 < this.recurrentDropout && this.recurrentDropout < 1) {
|
1094 | hTMinus1 = tfc.mul(hTMinus1, recDpMask[0]);
|
1095 | }
|
1096 | z = tfc.add(z, K.dot(hTMinus1, this.recurrentKernel.read()));
|
1097 | if (this.useBias) {
|
1098 | z = K.biasAdd(z, this.bias.read());
|
1099 | }
|
1100 | const [z0, z1, z2, z3] = tfc.split(z, 4, z.rank - 1);
|
1101 | i = this.recurrentActivation.apply(z0);
|
1102 | f = this.recurrentActivation.apply(z1);
|
1103 | c = tfc.add(tfc.mul(f, cTMinus1), tfc.mul(i, this.activation.apply(z2)));
|
1104 | o = this.recurrentActivation.apply(z3);
|
1105 | const h = tfc.mul(o, this.activation.apply(c));
|
1106 | // TODO(cais): Add use_learning_phase flag properly.
|
1107 | return [h, h, c];
|
1108 | });
|
1109 | }
|
1110 | getConfig() {
|
1111 | const baseConfig = super.getConfig();
|
1112 | const config = {
|
1113 | units: this.units,
|
1114 | activation: serializeActivation(this.activation),
|
1115 | recurrentActivation: serializeActivation(this.recurrentActivation),
|
1116 | useBias: this.useBias,
|
1117 | kernelInitializer: serializeInitializer(this.kernelInitializer),
|
1118 | recurrentInitializer: serializeInitializer(this.recurrentInitializer),
|
1119 | biasInitializer: serializeInitializer(this.biasInitializer),
|
1120 | unitForgetBias: this.unitForgetBias,
|
1121 | kernelRegularizer: serializeRegularizer(this.kernelRegularizer),
|
1122 | recurrentRegularizer: serializeRegularizer(this.recurrentRegularizer),
|
1123 | biasRegularizer: serializeRegularizer(this.biasRegularizer),
|
1124 | activityRegularizer: serializeRegularizer(this.activityRegularizer),
|
1125 | kernelConstraint: serializeConstraint(this.kernelConstraint),
|
1126 | recurrentConstraint: serializeConstraint(this.recurrentConstraint),
|
1127 | biasConstraint: serializeConstraint(this.biasConstraint),
|
1128 | dropout: this.dropout,
|
1129 | recurrentDropout: this.recurrentDropout,
|
1130 | implementation: this.implementation,
|
1131 | };
|
1132 | return Object.assign(Object.assign({}, baseConfig), config);
|
1133 | }
|
1134 | }
|
1135 | /** @nocollapse */
|
1136 | LSTMCell.className = 'LSTMCell';
|
1137 | serialization.registerClass(LSTMCell);
|
1138 | export class LSTM extends RNN {
|
1139 | constructor(args) {
|
1140 | if (args.implementation === 0) {
|
1141 | console.warn('`implementation=0` has been deprecated, and now defaults to ' +
|
1142 | '`implementation=1`. Please update your layer call.');
|
1143 | }
|
1144 | args.cell = new LSTMCell(args);
|
1145 | super(args);
|
1146 | // TODO(cais): Add activityRegularizer.
|
1147 | }
|
1148 | call(inputs, kwargs) {
|
1149 | return tidy(() => {
|
1150 | if (this.cell.dropoutMask != null) {
|
1151 | tfc.dispose(this.cell.dropoutMask);
|
1152 | this.cell.dropoutMask = null;
|
1153 | }
|
1154 | if (this.cell.recurrentDropoutMask != null) {
|
1155 | tfc.dispose(this.cell.recurrentDropoutMask);
|
1156 | this.cell.recurrentDropoutMask = null;
|
1157 | }
|
1158 | const mask = kwargs == null ? null : kwargs['mask'];
|
1159 | const training = kwargs == null ? null : kwargs['training'];
|
1160 | const initialState = kwargs == null ? null : kwargs['initialState'];
|
1161 | return super.call(inputs, { mask, training, initialState });
|
1162 | });
|
1163 | }
|
1164 | /** @nocollapse */
|
1165 | static fromConfig(cls, config) {
|
1166 | if (config['implmentation'] === 0) {
|
1167 | config['implementation'] = 1;
|
1168 | }
|
1169 | return new cls(config);
|
1170 | }
|
1171 | }
|
1172 | /** @nocollapse */
|
1173 | LSTM.className = 'LSTM';
|
1174 | serialization.registerClass(LSTM);
|
1175 | export class StackedRNNCells extends RNNCell {
|
1176 | constructor(args) {
|
1177 | super(args);
|
1178 | this.cells = args.cells;
|
1179 | }
|
1180 | get stateSize() {
|
1181 | // States are a flat list in reverse order of the cell stack.
|
1182 | // This allows perserving the requirement `stack.statesize[0] ===
|
1183 | // outputDim`. E.g., states of a 2-layer LSTM would be `[h2, c2, h1, c1]`,
|
1184 | // assuming one LSTM has states `[h, c]`.
|
1185 | const stateSize = [];
|
1186 | for (const cell of this.cells.slice().reverse()) {
|
1187 | if (Array.isArray(cell.stateSize)) {
|
1188 | stateSize.push(...cell.stateSize);
|
1189 | }
|
1190 | else {
|
1191 | stateSize.push(cell.stateSize);
|
1192 | }
|
1193 | }
|
1194 | return stateSize;
|
1195 | }
|
1196 | call(inputs, kwargs) {
|
1197 | return tidy(() => {
|
1198 | inputs = inputs;
|
1199 | let states = inputs.slice(1);
|
1200 | // Recover per-cell states.
|
1201 | const nestedStates = [];
|
1202 | for (const cell of this.cells.slice().reverse()) {
|
1203 | if (Array.isArray(cell.stateSize)) {
|
1204 | nestedStates.push(states.splice(0, cell.stateSize.length));
|
1205 | }
|
1206 | else {
|
1207 | nestedStates.push(states.splice(0, 1));
|
1208 | }
|
1209 | }
|
1210 | nestedStates.reverse();
|
1211 | // Call the cells in order and store the returned states.
|
1212 | const newNestedStates = [];
|
1213 | let callInputs;
|
1214 | for (let i = 0; i < this.cells.length; ++i) {
|
1215 | const cell = this.cells[i];
|
1216 | states = nestedStates[i];
|
1217 | // TODO(cais): Take care of constants.
|
1218 | if (i === 0) {
|
1219 | callInputs = [inputs[0]].concat(states);
|
1220 | }
|
1221 | else {
|
1222 | callInputs = [callInputs[0]].concat(states);
|
1223 | }
|
1224 | callInputs = cell.call(callInputs, kwargs);
|
1225 | newNestedStates.push(callInputs.slice(1));
|
1226 | }
|
1227 | // Format the new states as a flat list in reverse cell order.
|
1228 | states = [];
|
1229 | for (const cellStates of newNestedStates.slice().reverse()) {
|
1230 | states.push(...cellStates);
|
1231 | }
|
1232 | return [callInputs[0]].concat(states);
|
1233 | });
|
1234 | }
|
1235 | build(inputShape) {
|
1236 | if (isArrayOfShapes(inputShape)) {
|
1237 | // TODO(cais): Take care of input constants.
|
1238 | // const constantShape = inputShape.slice(1);
|
1239 | inputShape = inputShape[0];
|
1240 | }
|
1241 | inputShape = inputShape;
|
1242 | let outputDim;
|
1243 | this.cells.forEach((cell, i) => {
|
1244 | nameScope(`RNNCell_${i}`, () => {
|
1245 | // TODO(cais): Take care of input constants.
|
1246 | cell.build(inputShape);
|
1247 | if (Array.isArray(cell.stateSize)) {
|
1248 | outputDim = cell.stateSize[0];
|
1249 | }
|
1250 | else {
|
1251 | outputDim = cell.stateSize;
|
1252 | }
|
1253 | inputShape = [inputShape[0], outputDim];
|
1254 | });
|
1255 | });
|
1256 | this.built = true;
|
1257 | }
|
1258 | getConfig() {
|
1259 | const baseConfig = super.getConfig();
|
1260 | const getCellConfig = (cell) => {
|
1261 | return {
|
1262 | 'className': cell.getClassName(),
|
1263 | 'config': cell.getConfig(),
|
1264 | };
|
1265 | };
|
1266 | const cellConfigs = this.cells.map(getCellConfig);
|
1267 | const config = { 'cells': cellConfigs };
|
1268 | return Object.assign(Object.assign({}, baseConfig), config);
|
1269 | }
|
1270 | /** @nocollapse */
|
1271 | static fromConfig(cls, config, customObjects = {}) {
|
1272 | const cells = [];
|
1273 | for (const cellConfig of config['cells']) {
|
1274 | cells.push(deserialize(cellConfig, customObjects));
|
1275 | }
|
1276 | return new cls({ cells });
|
1277 | }
|
1278 | get trainableWeights() {
|
1279 | if (!this.trainable) {
|
1280 | return [];
|
1281 | }
|
1282 | const weights = [];
|
1283 | for (const cell of this.cells) {
|
1284 | weights.push(...cell.trainableWeights);
|
1285 | }
|
1286 | return weights;
|
1287 | }
|
1288 | get nonTrainableWeights() {
|
1289 | const weights = [];
|
1290 | for (const cell of this.cells) {
|
1291 | weights.push(...cell.nonTrainableWeights);
|
1292 | }
|
1293 | if (!this.trainable) {
|
1294 | const trainableWeights = [];
|
1295 | for (const cell of this.cells) {
|
1296 | trainableWeights.push(...cell.trainableWeights);
|
1297 | }
|
1298 | return trainableWeights.concat(weights);
|
1299 | }
|
1300 | return weights;
|
1301 | }
|
1302 | /**
|
1303 | * Retrieve the weights of a the model.
|
1304 | *
|
1305 | * @returns A flat `Array` of `tf.Tensor`s.
|
1306 | */
|
1307 | getWeights() {
|
1308 | const weights = [];
|
1309 | for (const cell of this.cells) {
|
1310 | weights.push(...cell.weights);
|
1311 | }
|
1312 | return batchGetValue(weights);
|
1313 | }
|
1314 | /**
|
1315 | * Set the weights of the model.
|
1316 | *
|
1317 | * @param weights An `Array` of `tf.Tensor`s with shapes and types matching
|
1318 | * the output of `getWeights()`.
|
1319 | */
|
1320 | setWeights(weights) {
|
1321 | const tuples = [];
|
1322 | for (const cell of this.cells) {
|
1323 | const numParams = cell.weights.length;
|
1324 | const inputWeights = weights.splice(numParams);
|
1325 | for (let i = 0; i < cell.weights.length; ++i) {
|
1326 | tuples.push([cell.weights[i], inputWeights[i]]);
|
1327 | }
|
1328 | }
|
1329 | batchSetValue(tuples);
|
1330 | }
|
1331 | }
|
1332 | /** @nocollapse */
|
1333 | StackedRNNCells.className = 'StackedRNNCells';
|
1334 | serialization.registerClass(StackedRNNCells);
|
1335 | export function generateDropoutMask(args) {
|
1336 | const { ones, rate, training = false, count = 1, dropoutFunc } = args;
|
1337 | const droppedInputs = () => dropoutFunc != null ? dropoutFunc(ones(), rate) : K.dropout(ones(), rate);
|
1338 | const createMask = () => K.inTrainPhase(droppedInputs, ones, training);
|
1339 | // just in case count is provided with null or undefined
|
1340 | if (!count || count <= 1) {
|
1341 | return tfc.keep(createMask().clone());
|
1342 | }
|
1343 | const masks = Array(count).fill(undefined).map(createMask);
|
1344 | return masks.map(m => tfc.keep(m.clone()));
|
1345 | }
|
1346 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjdXJyZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1sYXllcnMvc3JjL2xheWVycy9yZWN1cnJlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFFSDs7R0FFRztBQUVILE9BQU8sS0FBSyxHQUFHLE1BQU0sdUJBQXVCLENBQUM7QUFDN0MsT0FBTyxFQUFXLGFBQWEsRUFBVSxJQUFJLEVBQUUsSUFBSSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFFbEYsT0FBTyxFQUFhLGFBQWEsRUFBRSxtQkFBbUIsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzlFLE9BQU8sS0FBSyxDQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDN0MsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQW1DLGFBQWEsRUFBRSxtQkFBbUIsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3BHLE9BQU8sRUFBQyxTQUFTLEVBQUUsY0FBYyxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDN0QsT0FBTyxFQUFDLEtBQUssRUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BELE9BQU8sRUFBQyxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsVUFBVSxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQzFFLE9BQU8sRUFBQyxjQUFjLEVBQUUsV0FBVyxFQUF5QixJQUFJLEVBQUUsb0JBQW9CLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUcvRyxPQUFPLEVBQUMsY0FBYyxFQUFzQyxvQkFBb0IsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRXpHLE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzdELE9BQU8sS0FBSyxVQUFVLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxFQUFDLGtCQUFrQixFQUFFLG1CQUFtQixFQUFFLGVBQWUsRUFBQyxNQUFNLHNCQUFzQixDQUFD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UUFBUSxDQUFDLENBQUM7SUFFdkUsd0RBQXdEO0lBQ3hELElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxJQUFJLENBQUMsRUFBRTtRQUN4QixPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztLQUN2QztJQUVELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRTNELE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTggR29vZ2xlIExMQ1xuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZVxuICogbGljZW5zZSB0aGF0IGNhbiBiZSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIG9yIGF0XG4gKiBodHRwczovL29wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL01JVC5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuLyoqXG4gKiBUZW5zb3JGbG93LmpzIExheWVyczogUmVjdXJyZW50IE5ldXJhbCBOZXR3b3JrIExheWVycy5cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZmMgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy1jb3JlJztcbmltcG9ydCB7RGF0YVR5cGUsIHNlcmlhbGl6YXRpb24sIFRlbnNvciwgdGlkeSwgdXRpbH0gZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy1jb3JlJztcblxuaW1wb3J0IHtBY3RpdmF0aW9uLCBnZXRBY3RpdmF0aW9uLCBzZXJpYWxpemVBY3RpdmF0aW9ufSBmcm9tICcuLi9hY3RpdmF0aW9ucyc7XG5pbXBvcnQgKiBhcyBLIGZyb20gJy4uL2JhY2tlbmQvdGZqc19iYWNrZW5kJztcbmltcG9ydCB7bmFtZVNjb3BlfSBmcm9tICcuLi9jb21tb24nO1xuaW1wb3J0IHtDb25zdHJhaW50LCBDb25zdHJhaW50SWRlbnRpZmllciwgZ2V0Q29uc3RyYWludCwgc2VyaWFsaXplQ29uc3RyYWludH0gZnJvbSAnLi4vY29uc3RyYWludHMnO1xuaW1wb3J0IHtJbnB1dFNwZWMsIFN5bWJvbGljVGVuc29yfSBmcm9tICcuLi9lbmdpbmUvdG9wb2xvZ3knO1xuaW1wb3J0IHtMYXllciwgTGF5ZXJBcmdzfSBmcm9tICcuLi9lbmdpbmUvdG9wb2xvZ3knO1xuaW1wb3J0IHtBdHRyaWJ1dGVFcnJvciwgTm90SW1wbGVtZW50ZWRFcnJvciwgVmFsdWVFcnJvcn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7Z2V0SW5pdGlhbGl6ZXIsIEluaXRpYWxpemVyLCBJbml0aWFsaXplcklkZW50aWZpZXIsIE9uZXMsIHNlcmlhbGl6ZUluaXRpYWxpemVyfSBmcm9tICcuLi9pbml0aWFsaXplcnMnO1xuaW1wb3J0IHtBY3RpdmF0aW9uSWRlbnRpZmllcn0gZnJvbSAnLi4va2VyYXNfZm9ybWF0L2FjdGl2YXRpb25fY29uZmlnJztcbmltcG9ydCB7U2hhcGV9IGZyb20gJy4uL2tlcmFzX2Zvcm1hdC9jb21tb24nO1xuaW1wb3J0IHtnZXRSZWd1bGFyaXplciwgUmVndWxhcml6ZXIsIFJlZ3VsYXJpemVySWRlbnRpZmllciwgc2VyaWFsaXplUmVndWxhcml6ZXJ9IGZyb20gJy4uL3JlZ3VsYXJpemVycyc7XG5pbXBvcnQge0t3YXJncywgUm5uU3RlcEZ1bmN0aW9ufSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2Fzc2VydFBvc2l0aXZlSW50ZWdlcn0gZnJvbSAnLi4vdXRpbHMvZ2VuZXJpY191dGlscyc7XG5pbXBvcnQgKiBhcyBtYXRoX3V0aWxzIGZyb20gJy4uL3V0aWxzL21hdGhfdXRpbHMnO1xuaW1wb3J0IHtnZXRFeGFjdGx5T25lU2hhcGUsIGdldEV4YWN0bHlPbmVUZW5zb3IsIGlzQXJyYXlPZlNoYXBlc30gZnJvbSAnLi4vdXRpbHMvdHlwZXNfdXRpbHMnO1xuaW1wb3J0IHtiYXRjaEdldFZhbHVlLCBiYXRjaFNldFZhbHVlLCBMYXllclZhcmlhYmxlfSBmcm9tICcuLi92YXJpYWJsZXMnO1xuXG5pbXBvcnQge2Rlc2VyaWFsaXplfSBmcm9tICcuL3NlcmlhbGl6YXRpb24nO1xuXG4vKipcbiAqIFN0YW5kYXJkaXplIGBhcHBseSgpYCBhcmdzIHRvIGEgc2luZ2xlIGxpc3Qgb2YgdGVuc29yIGlucHV0cy5cbiAqXG4gKiBXaGVuIHJ1bm5pbmcgYSBtb2RlbCBsb2FkZWQgZnJvbSBmaWxlLCB0aGUgaW5wdXQgdGVuc29ycyBgaW5pdGlhbFN0YXRlYCBhbmRcbiAqIGBjb25zdGFudHNgIGFyZSBwYXNzZWQgdG8gYFJOTi5hcHBseSgpYCBhcyBwYXJ0IG9mIGBpbnB1dHNgIGluc3RlYWQgb2YgdGhlXG4gKiBkZWRpY2F0ZWQga3dhcmdzIGZpZWxkcy4gYGlucHV0c2AgY29uc2lzdHMgb2ZcbiAqIGBbaW5wdXRzLCBpbml0aWFsU3RhdGUwLCBpbml0aWFsU3RhdGUxLCAuLi4sIGNvbnN0YW50MCwgY29uc3RhbnQxXWAgaW4gdGhpc1xuICogY2FzZS5cbiAqIFRoaXMgbWV0aG9kIG1ha2VzIHN1cmUgdGhhdCBhcmd1bWVudHMgYXJlXG4gKiBzZXBhcmF0ZWQgYW5kIHRoYXQgYGluaXRpYWxTdGF0ZWAgYW5kIGBjb25zdGFudHNgIGFyZSBgQXJyYXlgcyBvZiB0ZW5zb3JzXG4gKiAob3IgTm9uZSkuXG4gKlxuICogQHBhcmFtIGlucHV0cyBUZW5zb3Igb3IgYEFycmF5YCBvZiAgdGVuc29ycy5cbiAqIEBwYXJhbSBpbml0aWFsU3RhdGUgVGVuc29yIG9yIGBBcnJheWAgb2YgdGVuc29ycyBvciBgbnVsbGAvYHVuZGVmaW5lZGAuXG4gKiBAcGFyYW0gY29uc3RhbnRzIFRlbnNvciBvciBgQXJyYXlgIG9mIHRlbnNvcnMgb3IgYG51bGxgL2B1bmRlZmluZWRgLlxuICogQHJldHVybnMgQW4gb2JqZWN0IGNvbnNpc3Rpbmcgb2ZcbiAqICAgaW5wdXRzOiBBIHRlbnNvci5cbiAqICAgaW5pdGlhbFN0YXRlOiBgQXJyYXlgIG9mIHRlbnNvcnMgb3IgYG51bGxgLlxuICogICBjb25zdGFudHM6IGBBcnJheWAgb2YgdGVuc29ycyBvciBgbnVsbGAuXG4gKiBAdGhyb3dzIFZhbHVlRXJyb3IsIGlmIGBpbnB1dHNgIGlzIGFuIGBBcnJheWAgYnV0IGVpdGhlciBgaW5pdGlhbFN0YXRlYCBvclxuICogICBgY29uc3RhbnRzYCBpcyBwcm92aWRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0YW5kYXJkaXplQXJncyhcbiAgICBpbnB1dHM6IFRlbnNvcnxUZW5zb3JbXXxTeW1ib2xpY1RlbnNvcnxTeW1ib2xpY1RlbnNvcltdLFxuICAgIGluaXRpYWxTdGF0ZTogVGVuc29yfFRlbnNvcltdfFN5bWJvbGljVGVuc29yfFN5bWJvbGljVGVuc29yW10sXG4gICAgY29uc3RhbnRzOiBUZW5zb3J8VGVuc29yW118U3ltYm9saWNUZW5zb3J8U3ltYm9saWNUZW5zb3JbXSxcbiAgICBudW1Db25zdGFudHM/OiBudW1iZXIpOiB7XG4gIGlucHV0czogVGVuc29yfFN5bWJvbGljVGVuc29yLFxuICBpbml0aWFsU3RhdGU6IFRlbnNvcltdfFN5bWJvbGljVGVuc29yW10sXG4gIGNvbnN0YW50czogVGVuc29yW118U3ltYm9saWNUZW5zb3JbXVxufSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGlucHV0cykpIHtcbiAgICBpZiAoaW5pdGlhbFN0YXRlICE9IG51bGwgfHwgY29uc3RhbnRzICE9IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgICdXaGVuIGlucHV0cyBpcyBhbiBhcnJheSwgbmVpdGhlciBpbml0aWFsU3RhdGUgb3IgY29uc3RhbnRzICcgK1xuICAgICAgICAgICdzaG91bGQgYmUgcHJvdmlkZWQnKTtcbiAgICB9XG4gICAgaWYgKG51bUNvbnN0YW50cyAhPSBudWxsKSB7XG4gICAgICBjb25zdGFudHMgPSBpbnB1dHMuc2xpY2UoaW5wdXRzLmxlbmd0aCAtIG51bUNvbnN0YW50cywgaW5wdXRzLmxlbmd0aCk7XG4gICAgICBpbnB1dHMgPSBpbnB1dHMuc2xpY2UoMCwgaW5wdXRzLmxlbmd0aCAtIG51bUNvbnN0YW50cyk7XG4gICAgfVxuICAgIGlmIChpbnB1dHMubGVuZ3RoID4gMSkge1xuICAgICAgaW5pdGlhbFN0YXRlID0gaW5wdXRzLnNsaWNlKDEsIGlucHV0cy5sZW5ndGgpO1xuICAgIH1cbiAgICBpbnB1dHMgPSBpbnB1dHNbMF07XG4gIH1cblxuICBmdW5jdGlvbiB0b0xpc3RPck51bGwoeDogVGVuc29yfFRlbnNvcltdfFN5bWJvbGljVGVuc29yfFxuICAgICAgICAgICAgICAgICAgICAgICAgU3ltYm9saWNUZW5zb3JbXSk6IFRlbnNvcltdfFN5bWJvbGljVGVuc29yW10ge1xuICAgIGlmICh4ID09IG51bGwgfHwgQXJyYXkuaXNBcnJheSh4KSkge1xuICAgICAgcmV0dXJuIHggYXMgVGVuc29yW10gfCBTeW1ib2xpY1RlbnNvcltdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW3hdIGFzIFRlbnNvcltdIHwgU3ltYm9saWNUZW5zb3JbXTtcbiAgICB9XG4gIH1cblxuICBpbml0aWFsU3RhdGUgPSB0b0xpc3RPck51bGwoaW5pdGlhbFN0YXRlKTtcbiAgY29uc3RhbnRzID0gdG9MaXN0T3JOdWxsKGNvbnN0YW50cyk7XG5cbiAgcmV0dXJuIHtpbnB1dHMsIGluaXRpYWxTdGF0ZSwgY29uc3RhbnRzfTtcbn1cblxuLyoqXG4gKiBJdGVyYXRlcyBvdmVyIHRoZSB0aW1lIGRpbWVuc2lvbiBvZiBhIHRlbnNvci5cbiAqXG4gKiBAcGFyYW0gc3RlcEZ1bmN0aW9uIFJOTiBzdGVwIGZ1bmN0aW9uLlxuICogICBQYXJhbWV0ZXJzOlxuICogICAgIGlucHV0czogdGVuc29yIHdpdGggc2hhcGUgYFtzYW1wbGVzLCAuLi5dYCAobm8gdGltZSBkaW1lbnNpb24pLFxuICogICAgICAgcmVwcmVzZW50aW5nIGlucHV0IGZvciB0aGUgYmF0Y2ggb2Ygc2FtcGxlcyBhdCBhIGNlcnRhaW4gdGltZSBzdGVwLlxuICogICAgIHN0YXRlczogYW4gQXJyYXkgb2YgdGVuc29ycy5cbiAqICAgUmV0dXJuczpcbiAqICAgICBvdXRwdXRzOiB0ZW5zb3Igd2l0aCBzaGFwZSBgW3NhbXBsZXMsIG91dHB1dERpbV1gIChubyB0aW1lIGRpbWVuc2lvbikuXG4gKiAgICAgbmV3U3RhdGVzOiBsaXN0IG9mIHRlbnNvcnMsIHNhbWUgbGVuZ3RoIGFuZCBzaGFwZXMgYXMgYHN0YXRlc2AuIFRoZSBmaXJzdFxuICogICAgICAgc3RhdGUgaW4gdGhlIGxpc3QgbXVzdCBiZSB0aGUgb3V0cHV0IHRlbnNvciBhdCB0aGUgcHJldmlvdXMgdGltZXN0ZXAuXG4gKiBAcGFyYW0gaW5wdXRzIFRlbnNvciBvZiB0ZW1wb3JhbCBkYXRhIG9mIHNoYXBlIGBbc2FtcGxlcywgdGltZSwgLi4uXWAgKGF0XG4gKiAgIGxlYXN0IDNEKS5cbiAqIEBwYXJhbSBpbml0aWFsU3RhdGVzIFRlbnNvciB3aXRoIHNoYXBlIGBbc2FtcGxlcywgb3V0cHV0RGltXWAgKG5vIHRpbWVcbiAqICAgZGltZW5zaW9uKSwgY29udGFpbmluZyB0aGUgaW5pdGlhbCB2YWx1ZXMgb2YgdGhlIHN0YXRlcyB1c2VkIGluIHRoZSBzdGVwXG4gKiAgIGZ1bmN0aW9uLlxuICogQHBhcmFtIGdvQmFja3dhcmRzIElmIGB0cnVlYCwgZG8gdGhlIGl0ZXJhdGlvbiBvdmVyIHRoZSB0aW1lIGRpbWVuc2lvbiBpblxuICogICByZXZlcnNlIG9yZGVyIGFuZCByZXR1cm4gdGhlIHJldmVyc2VkIHNlcXVlbmNlLlxuICogQHBhcmFtIG1hc2sgQmluYXJ5IHRlbnNvciB3aXRoIHNoYXBlIGBbc2FtcGxlLCB0aW1lLCAxXWAsIHdpdGggYSB6ZXJvIGZvclxuICogICBldmVyeSBlbGVtZW50IHRoYXQgaXMgbWFza2VkLlxuICogQHBhcmFtIGNvbnN0YW50cyBBbiBBcnJheSBvZiBjb25zdGFudCB2YWx1ZXMgcGFzc2VkIGF0IGVhY2ggc3RlcC5cbiAqIEBwYXJhbSB1bnJvbGwgV2hldGhlciB0byB1bnJvbGwgdGhlIFJOTiBvciB0byB1c2UgYSBzeW1ib2xpYyBsb29wLiAqTm90KlxuICogICBhcHBsaWNhYmxlIHRvIHRoaXMgaW1wZXJhdGl2ZSBkZWVwbGVhcm4uanMgYmFja2VuZC4gSXRzIHZhbHVlIGlzIGlnbm9yZWQuXG4gKiBAcGFyYW0gbmVlZFBlclN0ZXBPdXRwdXRzIFdoZXRoZXIgdGhlIHBlci1zdGVwIG91dHB1dHMgYXJlIHRvIGJlXG4gKiAgIGNvbmNhdGVuYXRlZCBpbnRvIGEgc2luZ2xlIHRlbnNvciBhbmQgcmV0dXJuZWQgKGFzIHRoZSBzZWNvbmQgcmV0dXJuXG4gKiAgIHZhbHVlKS4gRGVmYXVsdDogYGZhbHNlYC4gVGhpcyBhcmcgaXMgaW5jbHVkZWQgc28gdGhhdCB0aGUgcmVsYXRpdmVseVxuICogICBleHBlbnNpdmUgY29uY2F0ZW5hdGlvbiBvZiB0aGUgc3RlcHdpc2Ugb3V0cHV0cyBjYW4gYmUgb21pdHRlZCB1bmxlc3NcbiAqICAgdGhlIHN0ZXB3aXNlIG91dHB1dHMgbmVlZCB0byBiZSBrZXB0IChlLmcuLCBmb3IgYW4gTFNUTSBsYXllciBvZiB3aGljaFxuICogICBgcmV0dXJuU2VxdWVuY2VgIGlzIGB0cnVlYC4pXG4gKiBAcmV0dXJucyBBbiBBcnJheTogYFtsYXN0T3V0cHV0LCBvdXRwdXRzLCBuZXdTdGF0ZXNdYC5cbiAqICAgbGFzdE91dHB1dDogdGhlIGxhc3Rlc3Qgb3V0cHV0IG9mIHRoZSBSTk4sIG9mIHNoYXBlIGBbc2FtcGxlcywgLi4uXWAuXG4gKiAgIG91dHB1dHM6IHRlbnNvciB3aXRoIHNoYXBlIGBbc2FtcGxlcywgdGltZSwgLi4uXWAgd2hlcmUgZWFjaCBlbnRyeVxuICogICAgIGBvdXRwdXRbcywgdF1gIGlzIHRoZSBvdXRwdXQgb2YgdGhlIHN0ZXAgZnVuY3Rpb24gYXQgdGltZSBgdGAgZm9yIHNhbXBsZVxuICogICAgIGBzYC4gVGhpcyByZXR1cm4gdmFsdWUgaXMgcHJvdmlkZWQgaWYgYW5kIG9ubHkgaWYgdGhlXG4gKiAgICAgYG5lZWRQZXJTdGVwT3V0cHV0c2AgaXMgc2V0IGFzIGB0cnVlYC4gSWYgaXQgaXMgc2V0IGFzIGBmYWxzZWAsIHRoaXNcbiAqICAgICByZXR1cm4gdmFsdWUgd2lsbCBiZSBgdW5kZWZpbmVkYC5cbiAqICAgbmV3U3RhdGVzOiBBcnJheSBvZiB0ZW5zb3JzLCBsYXRlc3Qgc3RhdGVzIHJldHVybmVkIGJ5IHRoZSBzdGVwIGZ1bmN0aW9uLFxuICogICAgICBvZiBzaGFwZSBgKHNhbXBsZXMsIC4uLilgLlxuICogQHRocm93cyBWYWx1ZUVycm9yIElmIGlucHV0IGRpbWVuc2lvbiBpcyBsZXNzIHRoYW4gMy5cbiAqXG4gKiBUT0RPKG5pZWxzZW5lKTogVGhpcyBuZWVkcyB0byBiZSB0aWR5LWVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcm5uKFxuICAgIHN0ZXBGdW5jdGlvbjogUm5uU3RlcEZ1bmN0aW9uLCBpbnB1dHM6IFRlbnNvciwgaW5pdGlhbFN0YXRlczogVGVuc29yW10sXG4gICAgZ29CYWNrd2FyZHMgPSBmYWxzZSwgbWFzaz86IFRlbnNvciwgY29uc3RhbnRzPzogVGVuc29yW10sIHVucm9sbCA9IGZhbHNlLFxuICAgIG5lZWRQZXJTdGVwT3V0cHV0cyA9IGZhbHNlKTogW1RlbnNvciwgVGVuc29yLCBUZW5zb3JbXV0ge1xuICByZXR1cm4gdGZjLnRpZHkoKCkgPT4ge1xuICAgIGNvbnN0IG5kaW0gPSBpbnB1dHMuc2hhcGUubGVuZ3RoO1xuICAgIGlmIChuZGltIDwgMykge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoYElucHV0IHNob3VsZCBiZSBhdCBsZWFzdCAzRCwgYnV0IGlzICR7bmRpbX1ELmApO1xuICAgIH1cblxuICAgIC8vIFRyYW5zcG9zZSB0byB0aW1lLW1ham9yLCBpLmUuLCBmcm9tIFtiYXRjaCwgdGltZSwgLi4uXSB0byBbdGltZSwgYmF0Y2gsXG4gICAgLy8gLi4uXS5cbiAgICBjb25zdCBheGVzID0gWzEsIDBdLmNvbmNhdChtYXRoX3V0aWxzLnJhbmdlKDIsIG5kaW0pKTtcbiAgICBpbnB1dHMgPSB0ZmMudHJhbnNwb3NlKGlucHV0cywgYXhlcyk7XG5cbiAgICBpZiAoY29uc3RhbnRzICE9IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKFxuICAgICAgICAgICdUaGUgcm5uKCkgZnVuY3RvaW4gb2YgdGhlIGRlZXBsZWFybi5qcyBiYWNrZW5kIGRvZXMgbm90IHN1cHBvcnQgJyArXG4gICAgICAgICAgJ2NvbnN0YW50cyB5ZXQuJyk7XG4gICAgfVxuXG4gICAgLy8gUG9ydGluZyBOb3RlOiB0aGUgdW5yb2xsIG9wdGlvbiBpcyBpZ25vcmVkIGJ5IHRoZSBpbXBlcmF0aXZlIGJhY2tlbmQuXG4gICAgaWYgKHVucm9sbCkge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICdCYWNrZW5kIHJubigpOiB0aGUgdW5yb2xsID0gdHJ1ZSBvcHRpb24gaXMgbm90IGFwcGxpY2FibGUgdG8gdGhlICcgK1xuICAgICAgICAgICdpbXBlcmF0aXZlIGRlZXBsZWFybi5qcyBiYWNrZW5kLicpO1xuICAgIH1cblxuICAgIGlmIChtYXNrICE9IG51bGwpIHtcbiAgICAgIG1hc2sgPSB0ZmMuY2FzdCh0ZmMuY2FzdChtYXNrLCAnYm9vbCcpLCAnZmxvYXQzMicpO1xuICAgICAgaWYgKG1hc2sucmFuayA9PT0gbmRpbSAtIDEpIHtcbiAgICAgICAgbWFzayA9IHRmYy5leHBhbmREaW1zKG1hc2ssIC0xKTtcbiAgICAgIH1cbiAgICAgIG1hc2sgPSB0ZmMudHJhbnNwb3NlKG1hc2ssIGF4ZXMpO1xuICAgIH1cblxuICAgIGlmIChnb0JhY2t3YXJkcykge1xuICAgICAgaW5wdXRzID0gdGZjLnJldmVyc2UoaW5wdXRzLCAwKTtcbiAgICAgIGlmIChtYXNrICE9IG51bGwpIHtcbiAgICAgICAgbWFzayA9IHRmYy5yZXZlcnNlKG1hc2ssIDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFBvcnRpbmcgTm90ZTogUHlLZXJhcyB3aXRoIFRlbnNvckZsb3cgYmFja2VuZCB1c2VzIGEgc3ltYm9saWMgbG9vcFxuICAgIC8vICAgKHRmLndoaWxlX2xvb3ApLiBCdXQgZm9yIHRoZSBpbXBlcmF0aXZlIGRlZXBsZWFybi5qcyBiYWNrZW5kLCB3ZSBqdXN0XG4gICAgLy8gICB1c2UgdGhlIHVzdWFsIFR5cGVTY3JpcHQgY29udHJvbCBmbG93IHRvIGl0ZXJhdGUgb3ZlciB0aGUgdGltZSBzdGVwcyBpblxuICAgIC8vICAgdGhlIGlucHV0cy5cbiAgICAvLyBQb3J0aW5nIE5vdGU6IFB5S2VyYXMgcGF0Y2hlcyBhIFwiX3VzZV9sZWFybmluZ19waGFzZVwiIGF0dHJpYnV0ZSB0b1xuICAgIC8vIG91dHB1dHMuXG4gICAgLy8gICBUaGlzIGlzIG5vdCBpZGlvbWF0aWMgaW4gVHlwZVNjcmlwdC4gVGhlIGluZm8gcmVnYXJkaW5nIHdoZXRoZXIgd2UgYXJlXG4gICAgLy8gICBpbiBhIGxlYXJuaW5nIChpLmUuLCB0cmFpbmluZykgcGhhc2UgZm9yIFJOTiBpcyBwYXNzZWQgaW4gYSBkaWZmZXJlbnRcbiAgICAvLyAgIHdheS5cblxuICAgIGNvbnN0IHBlclN0ZXBPdXRwdXRzOiBUZW5zb3JbXSA9IFtdO1xuICAgIGxldCBsYXN0T3V0cHV0OiBUZW5zb3I7XG4gICAgbGV0IHN0YXRlcyA9IGluaXRpYWxTdGF0ZXM7XG4gICAgY29uc3QgdGltZVN0ZXBzID0gaW5wdXRzLnNoYXBlWzBdO1xuICAgIGNvbnN0IHBlclN0ZXBJbnB1dHMgPSB0ZmMudW5zdGFjayhpbnB1dHMpO1xuICAgIGxldCBwZXJTdGVwTWFza3M6IFRlbnNvcltdO1xuICAgIGlmIChtYXNrICE9IG51bGwpIHtcbiAgICAgIHBlclN0ZXBNYXNrcyA9IHRmYy51bnN0YWNrKG1hc2spO1xuICAgIH1cblxuICAgIGZvciAobGV0IHQgPSAwOyB0IDwgdGltZVN0ZXBzOyArK3QpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRJbnB1dCA9IHBlclN0ZXBJbnB1dHNbdF07XG4gICAgICBjb25zdCBzdGVwT3V0cHV0cyA9IHRmYy50aWR5KCgpID0+IHN0ZXBGdW5jdGlvbihjdXJyZW50SW5wdXQsIHN0YXRlcykpO1xuXG4gICAgICBpZiAobWFzayA9PSBudWxsKSB7XG4gICAgICAgIGxhc3RPdXRwdXQgPSBzdGVwT3V0cHV0c1swXTtcbiAgICAgICAgc3RhdGVzID0gc3RlcE91dHB1dHNbMV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBtYXNrZWRPdXRwdXRzID0gdGZjLnRpZHkoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHN0ZXBNYXNrID0gcGVyU3RlcE1hc2tzW3RdO1xuICAgICAgICAgIGNvbnN0IG5lZ1N0ZXBNYXNrID0gdGZjLnN1Yih0ZmMub25lc0xpa2Uoc3RlcE1hc2spLCBzdGVwTWFzayk7XG4gICAgICAgICAgLy8gVE9ETyhjYWlzKTogV291bGQgdGZjLndoZXJlKCkgYmUgYmV0dGVyIGZvciBwZXJmb3JtYW5jZT9cbiAgICAgICAgICBjb25zdCBvdXRwdXQgPSB0ZmMuYWRkKFxuICAgICAgICAgICAgICB0ZmMubXVsKHN0ZXBPdXRwdXRzWzBdLCBzdGVwTWFzayksXG4gICAgICAgICAgICAgIHRmYy5tdWwoc3RhdGVzWzBdLCBuZWdTdGVwTWFzaykpO1xuICAgICAgICAgIGNvbnN0IG5ld1N0YXRlcyA9IHN0YXRlcy5tYXAoKHN0YXRlLCBpKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGZjLmFkZChcbiAgICAgICAgICAgICAgICB0ZmMubXVsKHN0ZXBPdXRwdXRzWzFdW2ldLCBzdGVwTWFzayksXG4gICAgICAgICAgICAgICAgdGZjLm11bChzdGF0ZSwgbmVnU3RlcE1hc2spKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4ge291dHB1dCwgbmV3U3RhdGVzfTtcbiAgICAgICAgfSk7XG4gICAgICAgIGxhc3RPdXRwdXQgPSBtYXNrZWRPdXRwdXRzLm91dHB1dDtcbiAgICAgICAgc3RhdGVzID0gbWFza2VkT3V0cHV0cy5uZXdTdGF0ZXM7XG4gICAgICB9XG5cbiAgICAgIGlmIChuZWVkUGVyU3RlcE91dHB1dHMpIHtcbiAgICAgICAgcGVyU3RlcE91dHB1dHMucHVzaChsYXN0T3V0cHV0KTtcbiAgICAgIH1cbiAgICB9XG4gICAgbGV0IG91dHB1dHM6IFRlbnNvcjtcbiAgICBpZiAobmVlZFBlclN0ZXBPdXRwdXRzKSB7XG4gICAgICBjb25zdCBheGlzID0gMTtcbiAgICAgIG91dHB1dHMgPSB0ZmMuc3RhY2socGVyU3RlcE91dHB1dHMsIGF4aXMpO1xuICAgIH1cbiAgICByZXR1cm4gW2xhc3RPdXRwdXQsIG91dHB1dHMsIHN0YXRlc10gYXMgW1RlbnNvciwgVGVuc29yLCBUZW5zb3JbXV07XG4gIH0pO1xufVxuXG5leHBvcnQgZGVjbGFyZSBpbnRlcmZhY2UgQmFzZVJOTkxheWVyQXJncyBleHRlbmRzIExheWVyQXJncyB7XG4gIC8qKlxuICAgKiBBIFJOTiBjZWxsIGluc3RhbmNlLiBBIFJOTiBjZWxsIGlzIGEgY2xhc3MgdGhhdCBoYXM6XG4gICAqICAgLSBhIGBjYWxsKClgIG1ldGhvZCwgd2hpY2ggdGFrZXMgYFtUZW5zb3IsIFRlbnNvcl1gIGFzIHRoZVxuICAgKiAgICAgZmlyc3QgaW5wdXQgYXJndW1lbnQuIFRoZSBmaXJzdCBpdGVtIGlzIHRoZSBpbnB1dCBhdCB0aW1lIHQsIGFuZFxuICAgKiAgICAgc2Vjb25kIGl0ZW0gaXMgdGhlIGNlbGwgc3RhdGUgYXQgdGltZSB0LlxuICAgKiAgICAgVGhlIGBjYWxsKClgIG1ldGhvZCByZXR1cm5zIGBbb3V0cHV0QXRULCBzdGF0ZXNBdFRQbHVzMV1gLlxuICAgKiAgICAgVGhlIGBjYWxsKClgIG1ldGhvZCBvZiB0aGUgY2VsbCBjYW4gYWxzbyB0YWtlIHRoZSBhcmd1bWVudCBgY29uc3RhbnRzYCxcbiAgICogICAgIHNlZSBzZWN0aW9uIFwiTm90ZSBvbiBwYXNzaW5nIGV4dGVybmFsIGNvbnN0YW50c1wiIGJlbG93LlxuICAgKiAgICAgUG9ydGluZyBOb2RlOiBQeUtlcmFzIG92ZXJyaWRlcyB0aGUgYGNhbGwoKWAgc2lnbmF0dXJlIG9mIFJOTiBjZWxscyxcbiAgICogICAgICAgd2hpY2ggYXJlIExheWVyIHN1YnR5cGVzLCB0byBhY2NlcHQgdHdvIGFyZ3VtZW50cy4gdGZqcy1sYXllcnMgZG9lc1xuICAgKiAgICAgICBub3QgZG8gc3VjaCBvdmVycmlkaW5nLiBJbnN0ZWFkIHdlIHByZXNldmUgdGhlIGBjYWxsKClgIHNpZ25hdHVyZSxcbiAgICogICAgICAgd2hpY2ggZHVlIHRvIGl0cyBgVGVuc29yfFRlbnNvcltdYCBhcmd1bWVudCBhbmQgcmV0dXJuIHZhbHVlIGlzXG4gICAqICAgICAgIGZsZXhpYmxlIGVub3VnaCB0byBoYW5kbGUgdGhlIGlucHV0cyBhbmQgc3RhdGVzLlxuICAgKiAgIC0gYSBgc3RhdGVTaXplYCBhdHRyaWJ1dGUuIFRoaXMgY2FuIGJlIGEgc2luZ2xlIGludGVnZXIgKHNpbmdsZSBzdGF0ZSlcbiAgICogICAgIGluIHdoaWNoIGNhc2UgaXQgaXMgdGhlIHNpemUgb2YgdGhlIHJlY3VycmVudCBzdGF0ZSAod2hpY2ggc2hvdWxkIGJlXG4gICAqICAgICB0aGUgc2FtZSBhcyB0aGUgc2l6ZSBvZiB0aGUgY2VsbCBvdXRwdXQpLiBUaGlzIGNhbiBhbHNvIGJlIGFuIEFycmF5IG9mXG4gICAqICAgICBpbnRlZ2VycyAob25lIHNpemUgcGVyIHN0YXRlKS4gSW4gdGhpcyBjYXNlLCB0aGUgZmlyc3QgZW50cnlcbiAgICogICAgIChgc3RhdGVTaXplWzBdYCkgc2hvdWxkIGJlIHRoZSBzYW1lIGFzIHRoZSBzaXplIG9mIHRoZSBjZWxsIG91dHB1dC5cbiAgICogSXQgaXMgYWxzbyBwb3NzaWJsZSBmb3IgYGNlbGxgIHRvIGJlIGEgbGlzdCBvZiBSTk4gY2VsbCBpbnN0YW5jZXMsIGluIHdoaWNoXG4gICAqIGNhc2UgdGhlIGNlbGxzIGdldCBzdGFja2VkIG9uIGFmdGVyIHRoZSBvdGhlciBpbiB0aGUgUk5OLCBpbXBsZW1lbnRpbmcgYW5cbiAgICogZWZmaWNpZW50IHN0YWNrZWQgUk5OLlxuICAgKi9cbiAgY2VsbD86IFJOTkNlbGx8Uk5OQ2VsbFtdO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHJldHVybiB0aGUgbGFzdCBvdXRwdXQgaW4gdGhlIG91dHB1dCBzZXF1ZW5jZSwgb3IgdGhlIGZ1bGxcbiAgICogc2VxdWVuY2UuXG4gICAqL1xuICByZXR1cm5TZXF1ZW5jZXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHJldHVybiB0aGUgbGFzdCBzdGF0ZSBpbiBhZGRpdGlvbiB0byB0aGUgb3V0cHV0LlxuICAgKi9cbiAgcmV0dXJuU3RhdGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJZiBgdHJ1ZWAsIHByb2Nlc3MgdGhlIGlucHV0IHNlcXVlbmNlIGJhY2t3YXJkcyBhbmQgcmV0dXJuIHRoZSByZXZlcnNlZFxuICAgKiBzZXF1ZW5jZSAoZGVmYXVsdDogYGZhbHNlYCkuXG4gICAqL1xuICBnb0JhY2t3YXJkcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIElmIGB0cnVlYCwgdGhlIGxhc3Qgc3RhdGUgZm9yIGVhY2ggc2FtcGxlIGF0IGluZGV4IGkgaW4gYSBiYXRjaCB3aWxsIGJlXG4gICAqIHVzZWQgYXMgaW5pdGlhbCBzdGF0ZSBvZiB0aGUgc2FtcGxlIG9mIGluZGV4IGkgaW4gdGhlIGZvbGxvd2luZyBiYXRjaFxuICAgKiAoZGVmYXVsdDogYGZhbHNlYCkuXG4gICAqXG4gICAqIFlvdSBjYW4gc2V0IFJOTiBsYXllcnMgdG8gYmUgXCJzdGF0ZWZ1bFwiLCB3aGljaCBtZWFucyB0aGF0IHRoZSBzdGF0ZXNcbiAgICogY29tcHV0ZWQgZm9yIHRoZSBzYW1wbGVzIGluIG9uZSBiYXRjaCB3aWxsIGJlIHJldXNlZCBhcyBpbml0aWFsIHN0YXRlc1xuICAgKiBmb3IgdGhlIHNhbXBsZXMgaW4gdGhlIG5leHQgYmF0Y2guIFRoaXMgYXNzdW1lcyBhIG9uZS10by1vbmUgbWFwcGluZ1xuICAgKiBiZXR3ZWVuIHNhbXBsZXMgaW4gZGlmZmVyZW50IHN1Y2Nlc3NpdmUgYmF0Y2hlcy5cbiAgICpcbiAgICogVG8gZW5hYmxlIFwic3RhdGVmdWxuZXNzXCI6XG4gICAqICAgLSBzcGVjaWZ5IGBzdGF0ZWZ1bDogdHJ1ZWAgaW4gdGhlIGxheWVyIGNvbnN0cnVjdG9yLlxuICAgKiAgIC0gc3BlY2lmeSBhIGZpeGVkIGJhdGNoIHNpemUgZm9yIHlvdXIgbW9kZWwsIGJ5IHBhc3NpbmdcbiAgICogICAgIC0gaWYgc2VxdWVudGlhbCBtb2RlbDpcbiAgICogICAgICAgYGJhdGNoSW5wdXRTaGFwZTogWy4uLl1gIHRvIHRoZSBmaXJzdCBsYXllciBpbiB5b3VyIG1vZGVsLlxuICAgKiAgICAgLSBlbHNlIGZvciBmdW5jdGlvbmFsIG1vZGVsIHdpdGggMSBvciBtb3JlIElucHV0IGxheWVyczpcbiAgICogICAgICAgYGJhdGNoU2hhcGU6IFsuLi5dYCB0byBhbGwgdGhlIGZpcnN0IGxheWVycyBpbiB5b3VyIG1vZGVsLlxuICAgKiAgICAgVGhpcyBpcyB0aGUgZXhwZWN0ZWQgc2hhcGUgb2YgeW91ciBpbnB1dHNcbiAgICogICAgICppbmNsdWRpbmcgdGhlIGJhdGNoIHNpemUqLlxuICAgKiAgICAgSXQgc2hvdWxkIGJlIGEgdHVwbGUgb2YgaW50ZWdlcnMsIGUuZy4sIGBbMzIsIDEwLCAxMDBdYC5cbiAgICogICAtIHNwZWNpZnkgYHNodWZmbGU6IGZhbHNlYCB3aGVuIGNhbGxpbmcgYExheWVyc01vZGVsLmZpdCgpYC5cbiAgICpcbiAgICogVG8gcmVzZXQgdGhlIHN0YXRlIG9mIHlvdXIgbW9kZWwsIGNhbGwgYHJlc2V0U3RhdGVzKClgIG9uIGVpdGhlciB0aGVcbiAgICogc3BlY2lmaWMgbGF5ZXIgb3Igb24gdGhlIGVudGlyZSBtb2RlbC5cbiAgICovXG4gIHN0YXRlZnVsPzogYm9vbGVhbjtcbiAgLy8gVE9ETyhjYWlzKTogRXhwbG9yZSB3aGV0aGVyIHdlIGNhbiB3YXJuIHVzZXJzIHdoZW4gdGhleSBmYWlsIHRvIHNldFxuICAvLyAgIGBzaHVmZmxlOiBmYWxzZWAgd2hlbiB0cmFpbmluZyBhIG1vZGVsIGNvbnNpc3Rpbmcgb2Ygc3RhdGVmdWwgUk5Oc1xuICAvLyAgIGFuZCBhbnkgc3RhdGVmdWwgTGF5ZXJzIGluIGdlbmVyYWwuXG5cbiAgLyoqXG4gICAqIElmIGB0cnVlYCwgdGhlIG5ldHdvcmsgd2lsbCBiZSB1bnJvbGxlZCwgZWxzZSBhIHN5bWJvbGljIGxvb3Agd2lsbCBiZVxuICAgKiB1c2VkLiBVbnJvbGxpbmcgY2FuIHNwZWVkIHVwIGEgUk5OLCBhbHRob3VnaCBpdCB0ZW5kcyB0byBiZSBtb3JlXG4gICAqIG1lbW9yeS1pbnRlbnNpdmUuIFVucm9sbGluZyBpcyBvbmx5IHN1aXRhYmxlIGZvciBzaG9ydCBzZXF1ZW5jZXMgKGRlZmF1bHQ6XG4gICAqIGBmYWxzZWApLlxuICAgKiBQb3J0aW5nIE5vdGU6IHRmanMtbGF5ZXJzIGhhcyBhbiBpbXBlcmF0aXZlIGJhY2tlbmQuIFJOTnMgYXJlIGV4ZWN1dGVkIHdpdGhcbiAgICogICBub3JtYWwgVHlwZVNjcmlwdCBjb250cm9sIGZsb3cuIEhlbmNlIHRoaXMgcHJvcGVydHkgaXMgaW5hcHBsaWNhYmxlIGFuZFxuICAgKiAgIGlnbm9yZWQgaW4gdGZqcy1sYXllcnMuXG4gICAqL1xuICB1bnJvbGw/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBEaW1lbnNpb25hbGl0eSBvZiB0aGUgaW5wdXQgKGludGVnZXIpLlxuICAgKiAgIFRoaXMgb3B0aW9uIChvciBhbHRlcm5hdGl2ZWx5LCB0aGUgb3B0aW9uIGBpbnB1dFNoYXBlYCkgaXMgcmVxdWlyZWQgd2hlblxuICAgKiAgIHRoaXMgbGF5ZXIgaXMgdXNlZCBhcyB0aGUgZmlyc3QgbGF5ZXIgaW4gYSBtb2RlbC5cbiAgICovXG4gIGlucHV0RGltPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBMZW5ndGggb2YgdGhlIGlucHV0IHNlcXVlbmNlcywgdG8gYmUgc3BlY2lmaWVkIHdoZW4gaXQgaXMgY29uc3RhbnQuXG4gICAqIFRoaXMgYXJndW1lbnQgaXMgcmVxdWlyZWQgaWYgeW91IGFyZSBnb2luZyB0byBjb25uZWN0IGBGbGF0dGVuYCB0aGVuXG4gICAqIGBEZW5zZWAgbGF5ZXJzIHVwc3RyZWFtICh3aXRob3V0IGl0LCB0aGUgc2hhcGUgb2YgdGhlIGRlbnNlIG91dHB1dHMgY2Fubm90XG4gICAqIGJlIGNvbXB1dGVkKS4gTm90ZSB0aGF0IGlmIHRoZSByZWN1cnJlbnQgbGF5ZXIgaXMgbm90IHRoZSBmaXJzdCBsYXllciBpblxuICAgKiB5b3VyIG1vZGVsLCB5b3Ugd291bGQgbmVlZCB0byBzcGVjaWZ5IHRoZSBpbnB1dCBsZW5ndGggYXQgdGhlIGxldmVsIG9mIHRoZVxuICAgKiBmaXJzdCBsYXllciAoZS5nLiwgdmlhIHRoZSBgaW5wdXRTaGFwZWAgb3B0aW9uKS5cbiAgICovXG4gIGlucHV0TGVuZ3RoPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgUk5OIGV4dGVuZHMgTGF5ZXIge1xuICAvKiogQG5vY29sbGFwc2UgKi9cbiAgc3RhdGljIGNsYXNzTmFtZSA9ICdSTk4nO1xuICBwdWJsaWMgcmVhZG9ubHkgY2VsbDogUk5OQ2VsbDtcbiAgcHVibGljIHJlYWRvbmx5IHJldHVyblNlcXVlbmNlczogYm9vbGVhbjtcbiAgcHVibGljIHJlYWRvbmx5IHJldHVyblN0YXRlOiBib29sZWFuO1xuICBwdWJsaWMgcmVhZG9ubHkgZ29CYWNrd2FyZHM6IGJvb2xlYW47XG4gIHB1YmxpYyByZWFkb25seSB1bnJvbGw6IGJvb2xlYW47XG5cbiAgcHVibGljIHN0YXRlU3BlYzogSW5wdXRTcGVjW107XG4gIHByb3RlY3RlZCBzdGF0ZXNfOiBUZW5zb3JbXTtcblxuICAvLyBOT1RFKGNhaXMpOiBGb3Igc3RhdGVmdWwgUk5OcywgdGhlIG9sZCBzdGF0ZXMgY2Fubm90IGJlIGRpc3Bvc2VkIHJpZ2h0XG4gIC8vIGF3YXkgd2hlbiBuZXcgc3RhdGVzIGFyZSBzZXQsIGJlY2F1c2UgdGhlIG9sZCBzdGF0ZXMgbWF5IG5lZWQgdG8gYmUgdXNlZFxuICAvLyBsYXRlciBmb3IgYmFja3Byb3BhZ2F0aW9uIHRocm91Z2ggdGltZSAoQlBUVCkgYW5kIG90aGVyIHB1cnBvc2VzLiBTbyB3ZVxuICAvLyBrZWVwIHRoZW0gaGVyZSBmb3IgZmluYWwgZGlzcG9zYWwgd2hlbiB0aGUgc3RhdGUgaXMgcmVzZXQgY29tcGxldGVseVxuICAvLyAoaS5lLiwgdGhyb3VnaCBuby1hcmcgY2FsbCB0byBgcmVzZXRTdGF0ZXMoKWApLlxuICBwcm90ZWN0ZWQga2VwdFN0YXRlczogVGVuc29yW11bXTtcblxuICBwcml2YXRlIG51bUNvbnN0YW50czogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGFyZ3M6IFJOTkxheWVyQXJncykge1xuICAgIHN1cGVyKGFyZ3MpO1xuICAgIGxldCBjZWxsOiBSTk5DZWxsO1xuICAgIGlmIChhcmdzLmNlbGwgPT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgJ2NlbGwgcHJvcGVydHkgaXMgbWlzc2luZyBmb3IgdGhlIGNvbnN0cnVjdG9yIG9mIFJOTi4nKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJncy5jZWxsKSkge1xuICAgICAgY2VsbCA9IG5ldyBTdGFja2VkUk5OQ2VsbHMoe2NlbGxzOiBhcmdzLmNlbGx9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2VsbCA9IGFyZ3MuY2VsbDtcbiAgICB9XG4gICAgaWYgKGNlbGwuc3RhdGVTaXplID09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgICdUaGUgUk5OIGNlbGwgc2hvdWxkIGhhdmUgYW4gYXR0cmlidXRlIGBzdGF0ZVNpemVgICh0dXBsZSBvZiAnICtcbiAgICAgICAgICAnaW50ZWdlcnMsIG9uZSBpbnRlZ2VyIHBlciBSTk4gc3RhdGUpLicpO1xuICAgIH1cbiAgICB0aGlzLmNlbGwgPSBjZWxsO1xuICAgIHRoaXMucmV0dXJuU2VxdWVuY2VzID1cbiAgICAgICAgYXJncy5yZXR1cm5TZXF1ZW5jZXMgPT0gbnVsbCA/IGZhbHNlIDogYXJncy5yZXR1cm5TZXF1ZW5jZXM7XG4gICAgdGhpcy5yZXR1cm5TdGF0ZSA9IGFyZ3MucmV0dXJuU3RhdGUgPT0gbnVsbCA/IGZhbHNlIDogYXJncy5yZXR1cm5TdGF0ZTtcbiAgICB0aGlzLmdvQmFja3dhcmRzID0gYXJncy5nb0JhY2t3YXJkcyA9PSBudWxsID8gZmFsc2UgOiBhcmdzLmdvQmFja3dhcmRzO1xuICAgIHRoaXMuX3N0YXRlZnVsID0gYXJncy5zdGF0ZWZ1bCA9PSBudWxsID8gZmFsc2UgOiBhcmdzLnN0YXRlZnVsO1xuICAgIHRoaXMudW5yb2xsID0gYXJncy51bnJvbGwgPT0gbnVsbCA/IGZhbHNlIDogYXJncy51bnJvbGw7XG5cbiAgICB0aGlzLnN1cHBvcnRzTWFza2luZyA9IHRydWU7XG4gICAgdGhpcy5pbnB1dFNwZWMgPSBbbmV3IElucHV0U3BlYyh7bmRpbTogM30pXTtcbiAgICB0aGlzLnN0YXRlU3BlYyA9IG51bGw7XG4gICAgdGhpcy5zdGF0ZXNfID0gbnVsbDtcbiAgICAvLyBUT0RPKGNhaXMpOiBBZGQgY29uc3RhbnRzU3BlYyBhbmQgbnVtQ29uc3RhbnRzLlxuICAgIHRoaXMubnVtQ29uc3RhbnRzID0gbnVsbDtcbiAgICAvLyBUT0RPKGNhaXMpOiBMb29rIGludG8gdGhlIHVzZSBvZiBpbml0aWFsX3N0YXRlIGluIHRoZSBrd2FyZ3Mgb2YgdGhlXG4gICAgLy8gICBjb25zdHJ1Y3Rvci5cblxuICAgIHRoaXMua2VwdFN0YXRlcyA9IFtdO1xuICB9XG5cbiAgLy8gUG9ydGluZyBOb3RlOiBUaGlzIGlzIHRoZSBlcXVpdmFsZW50IG9mIGBSTk4uc3RhdGVzYCBwcm9wZXJ0eSBnZXR0ZXIgaW5cbiAgLy8gICBQeUtlcmFzLlxuICBnZXRTdGF0ZXMoKTogVGVuc29yW10ge1xuICAgIGlmICh0aGlzLnN0YXRlc18gPT0gbnVsbCkge1xuICAgICAgY29uc3QgbnVtU3RhdGVzID1cbiAgICAgICAgICBBcnJheS5pc0FycmF5KHRoaXMuY2VsbC5zdGF0ZVNpemUpID8gdGhpcy5jZWxsLnN0YXRlU2l6ZS5sZW5ndGggOiAxO1xuICAgICAgcmV0dXJuIG1hdGhfdXRpbHMucmFuZ2UoMCwgbnVtU3RhdGVzKS5tYXAoeCA9PiBudWxsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuc3RhdGVzXztcbiAgICB9XG4gIH1cblxuICAvLyBQb3J0aW5nIE5vdGU6IFRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgb2YgdGhlIGBSTk4uc3RhdGVzYCBwcm9wZXJ0eSBzZXR0ZXIgaW5cbiAgLy8gICBQeUtlcmFzLlxuICBzZXRTdGF0ZXMoc3RhdGVzOiBUZW5zb3JbXSk6IHZvaWQge1xuICAgIHRoaXMuc3RhdGVzXyA9IHN0YXRlcztcbiAgfVxuXG4gIG92ZXJyaWRlIGNvbXB1dGVPdXRwdXRTaGFwZShpbnB1dFNoYXBlOiBTaGFwZXxTaGFwZVtdKTogU2hhcGV8U2hhcGVbXSB7XG4gICAgaWYgKGlzQXJyYXlPZlNoYXBlcyhpbnB1dFNoYXBlKSkge1xuICAgICAgaW5wdXRTaGFwZSA9IChpbnB1dFNoYXBlIGFzIFNoYXBlW10pWzBdO1xuICAgIH1cbiAgICBpbnB1dFNoYXBlID0gaW5wdXRTaGFwZSBhcyBTaGFwZTtcblxuICAgIC8vIFRPRE8oY2Fpcyk6IFJlbW92ZSB0aGUgY2FzdGluZyBvbmNlIHN0YWNrZWQgUk5OIGNlbGxzIGJlY29tZSBzdXBwb3J0ZWQuXG4gICAgbGV0IHN0YXRlU2l6ZSA9IHRoaXMuY2VsbC5zdGF0ZVNpemU7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHN0YXRlU2l6ZSkpIHtcbiAgICAgIHN0YXRlU2l6ZSA9IFtzdGF0ZVNpemVdO1xuICAgIH1cbiAgICBjb25zdCBvdXRwdXREaW0gPSBzdGF0ZVNpemVbMF07XG4gICAgbGV0IG91dHB1dFNoYXBlOiBTaGFwZXxTaGFwZVtdO1xuICAgIGlmICh0aGlzLnJldHVyblNlcXVlbmNlcykge1xuICAgICAgb3V0cHV0U2hhcGUgPSBbaW5wdXRTaGFwZVswXSwgaW5wdXRTaGFwZVsxXSwgb3V0cHV0RGltXTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0U2hhcGUgPSBbaW5wdXRTaGFwZVswXSwgb3V0cHV0RGltXTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5yZXR1cm5TdGF0ZSkge1xuICAgICAgY29uc3Qgc3RhdGVTaGFwZTogU2hhcGVbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBkaW0gb2Ygc3RhdGVTaXplKSB7XG4gICAgICAgIHN0YXRlU2hhcGUucHVzaChbaW5wdXRTaGFwZVswXSwgZGltXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gW291dHB1dFNoYXBlXS5jb25jYXQoc3RhdGVTaGFwZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBvdXRwdXRTaGFwZTtcbiAgICB9XG4gIH1cblxuICBvdmVycmlkZSBjb21wdXRlTWFzayhpbnB1dHM6IFRlbnNvcnxUZW5zb3JbXSwgbWFzaz86IFRlbnNvcnxUZW5zb3JbXSk6IFRlbnNvclxuICAgICAgfFRlbnNvcltdIHtcbiAgICByZXR1cm4gdGZjLnRpZHkoKCkgPT4ge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkobWFzaykpIHtcbiAgICAgICAgbWFzayA9IG1hc2tbMF07XG4gICAgICB9XG4gICAgICBjb25zdCBvdXRwdXRNYXNrID0gdGhpcy5yZXR1cm5TZXF1ZW5jZXMgPyBtYXNrIDogbnVsbDtcblxuICAgICAgaWYgKHRoaXMucmV0dXJuU3RhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhdGVNYXNrID0gdGhpcy5zdGF0ZXMubWFwKHMgPT4gbnVsbCk7XG4gICAgICAgIHJldHVybiBbb3V0cHV0TWFza10uY29uY2F0KHN0YXRlTWFzayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gb3V0cHV0TWFzaztcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnQgc3RhdGUgdGVuc29ycyBvZiB0aGUgUk5OLlxuICAgKlxuICAgKiBJZiB0aGUgc3RhdGUgaGFzbid0IGJlZW4gc2V0LCByZXR1cm4gYW4gYXJyYXkgb2YgYG51bGxgcyBvZiB0aGUgY29ycmVjdFxuICAgKiBsZW5ndGguXG4gICAqL1xuICBnZXQgc3RhdGVzKCk6IFRlbnNvcltdIHtcbiAgICBpZiAodGhpcy5zdGF0ZXNfID09IG51bGwpIHtcbiAgICAgIGNvbnN0IG51bVN0YXRlcyA9XG4gICAgICAgICAgQXJyYXkuaXNBcnJheSh0aGlzLmNlbGwuc3RhdGVTaXplKSA/IHRoaXMuY2VsbC5zdGF0ZVNpemUubGVuZ3RoIDogMTtcbiAgICAgIGNvbnN0IG91dHB1dDogVGVuc29yW10gPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtU3RhdGVzOyArK2kpIHtcbiAgICAgICAgb3V0cHV0LnB1c2gobnVsbCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5zdGF0ZXNfO1xuICAgIH1cbiAgfVxuXG4gIHNldCBzdGF0ZXMoczogVGVuc29yW10pIHtcbiAgICB0aGlzLnN0YXRlc18gPSBzO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIGJ1aWxkKGlucHV0U2hhcGU6IFNoYXBlfFNoYXBlW10pOiB2b2lkIHtcbiAgICAvLyBOb3RlIGlucHV0U2hhcGUgd2lsbCBiZSBhbiBBcnJheSBvZiBTaGFwZXMgb2YgaW5pdGlhbCBzdGF0ZXMgYW5kXG4gICAgLy8gY29uc3RhbnRzIGlmIHRoZXNlIGFyZSBwYXNzZWQgaW4gYXBwbHkoKS5cbiAgICBjb25zdCBjb25zdGFudFNoYXBlOiBTaGFwZVtdID0gbnVsbDtcbiAgICBpZiAodGhpcy5udW1Db25zdGFudHMgIT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoXG4gICAgICAgICAgJ0NvbnN0YW50cyBzdXBwb3J0IGlzIG5vdCBpbXBsZW1lbnRlZCBpbiBSTk4geWV0LicpO1xuICAgIH1cblxuICAgIGlmIChpc0FycmF5T2ZTaGFwZXMoaW5wdXRTaGFwZSkpIHtcbiAgICAgIGlucHV0U2hhcGUgPSAoaW5wdXRTaGFwZSBhcyBTaGFwZVtdKVswXTtcbiAgICB9XG4gICAgaW5wdXRTaGFwZSA9IGlucHV0U2hhcGUgYXMgU2hhcGU7XG5cbiAgICBjb25zdCBiYXRjaFNpemU6IG51bWJlciA9IHRoaXMuc3RhdGVmdWwgPyBpbnB1dFNoYXBlWzBdIDogbnVsbDtcbiAgICBjb25zdCBpbnB1dERpbSA9IGlucHV0U2hhcGUuc2xpY2UoMik7XG4gICAgdGhpcy5pbnB1dFNwZWNbMF0gPSBuZXcgSW5wdXRTcGVjKHtzaGFwZTogW2JhdGNoU2l6ZSwgbnVsbCwgLi4uaW5wdXREaW1dfSk7XG5cbiAgICAvLyBBbGxvdyBjZWxsIChpZiBSTk5DZWxsIExheWVyKSB0byBidWlsZCBiZWZvcmUgd2Ugc2V0IG9yIHZhbGlkYXRlXG4gICAgLy8gc3RhdGVTcGVjLlxuICAgIGNvbnN0IHN0ZXBJbnB1dFNoYXBlID0gW2lucHV0U2hhcGVbMF1dLmNvbmNhdChpbnB1dFNoYXBlLnNsaWNlKDIpKTtcbiAgICBpZiAoY29uc3RhbnRTaGFwZSAhPSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcihcbiAgICAgICAgICAnQ29uc3RhbnRzIHN1cHBvcnQgaXMgbm90IGltcGxlbWVudGVkIGluIFJOTiB5ZXQuJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY2VsbC5idWlsZChzdGVwSW5wdXRTaGFwZSk7XG4gICAgfVxuXG4gICAgLy8gU2V0IG9yIHZhbGlkYXRlIHN0YXRlU3BlYy5cbiAgICBsZXQgc3RhdGVTaXplOiBudW1iZXJbXTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLmNlbGwuc3RhdGVTaXplKSkge1xuICAgICAgc3RhdGVTaXplID0gdGhpcy5jZWxsLnN0YXRlU2l6ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RhdGVTaXplID0gW3RoaXMuY2VsbC5zdGF0ZVNpemVdO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXRlU3BlYyAhPSBudWxsKSB7XG4gICAgICBpZiAoIXV0aWwuYXJyYXlzRXF1YWwoXG4gICAgICAgICAgICAgIHRoaXMuc3RhdGVTcGVjLm1hcChzcGVjID0+IHNwZWMuc2hhcGVbc3BlYy5zaGFwZS5sZW5ndGggLSAxXSksXG4gICAgICAgICAgICAgIHN0YXRlU2l6ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgICBgQW4gaW5pdGlhbFN0YXRlIHdhcyBwYXNzZWQgdGhhdCBpcyBub3QgY29tcGF0aWJsZSB3aXRoIGAgK1xuICAgICAgICAgICAgYGNlbGwuc3RhdGVTaXplLiBSZWNlaXZlZCBzdGF0ZVNwZWM9JHt0aGlzLnN0YXRlU3BlY307IGAgK1xuICAgICAgICAgICAgYEhvd2V2ZXIgY2VsbC5zdGF0ZVNpemUgaXMgJHt0aGlzLmNlbGwuc3RhdGVTaXplfWApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0YXRlU3BlYyA9XG4gICAgICAgICAgc3RhdGVTaXplLm1hcChkaW0gPT4gbmV3IElucHV0U3BlYyh7c2hhcGU6IFtudWxsLCBkaW1dfSkpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdGF0ZWZ1bCkge1xuICAgICAgdGhpcy5yZXNldFN0YXRlcygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgc3RhdGUgdGVuc29ycyBvZiB0aGUgUk5OLlxuICAgKlxuICAgKiBJZiB0aGUgYHN0YXRlc2AgYXJndW1lbnQgaXMgYHVuZGVmaW5lZGAgb3IgYG51bGxgLCB3aWxsIHNldCB0aGVcbiAgICogc3RhdGUgdGVuc29yKHMpIG9mIHRoZSBSTk4gdG8gYWxsLXplcm8gdGVuc29ycyBvZiB0aGUgYXBwcm9wcmlhdGVcbiAgICogc2hhcGUocykuXG4gICAqXG4gICAqIElmIGBzdGF0ZXNgIGlzIHByb3ZpZGVkLCB3aWxsIHNldCB0aGUgc3RhdGUgdGVuc29ycyBvZiB0aGUgUk5OIHRvIGl0c1xuICAgKiB2YWx1ZS5cbiAgICpcbiAgICogQHBhcmFtIHN0YXRlcyBPcHRpb25hbCBleHRlcm5hbGx5LXByb3ZpZGVkIGluaXRpYWwgc3RhdGVzLlxuICAgKiBAcGFyYW0gdHJhaW5pbmcgV2hldGhlciB0aGlzIGNhbGwgaXMgZG9uZSBkdXJpbmcgdHJhaW5pbmcuIEZvciBzdGF0ZWZ1bFxuICAgKiAgIFJOTnMsIHRoaXMgYWZmZWN0cyB3aGV0aGVyIHRoZSBvbGQgc3RhdGVzIGFyZSBrZXB0IG9yIGRpc2NhcmRlZC4gSW5cbiAgICogICBwYXJ0aWN1bGFyLCBpZiBgdHJhaW5pbmdgIGlzIGB0cnVlYCwgdGhlIG9sZCBzdGF0ZXMgd2lsbCBiZSBrZXB0IHNvXG4gICAqICAgdGhhdCBzdWJzZXF1ZW50IGJhY2twcm9wZ2F0YWlvbiB0aHJvdWdoIHRpbWUgKEJQVFQpIG1heSB3b3JrIHByb3Blcmx5LlxuICAgKiAgIEVsc2UsIHRoZSBvbGQgc3RhdGVzIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgKi9cbiAgb3ZlcnJpZGUgcmVzZXRTdGF0ZXMoc3RhdGVzPzogVGVuc29yfFRlbnNvcltdLCB0cmFpbmluZyA9IGZhbHNlKTogdm9pZCB7XG4gICAgdGlkeSgoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuc3RhdGVmdWwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEF0dHJpYnV0ZUVycm9yKFxuICAgICAgICAgICAgJ0Nhbm5vdCBjYWxsIHJlc2V0U3RhdGVzKCkgb24gYW4gUk5OIExheWVyIHRoYXQgaXMgbm90IHN0YXRlZnVsLicpO1xuICAgICAgfVxuICAgICAgY29uc3QgYmF0Y2hTaXplID0gdGhpcy5pbnB1dFNwZWNbMF0uc2hhcGVbMF07XG4gICAgICBpZiAoYmF0Y2hTaXplID09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgICAnSWYgYW4gUk5OIGlzIHN0YXRlZnVsLCBpdCBuZWVkcyB0byBrbm93IGl0cyBiYXRjaCBzaXplLiBTcGVjaWZ5ICcgK1xuICAgICAgICAgICAgJ3RoZSBiYXRjaCBzaXplIG9mIHlvdXIgaW5wdXQgdGVuc29yczogXFxuJyArXG4gICAgICAgICAgICAnLSBJZiB1c2luZyBhIFNlcXVlbnRpYWwgbW9kZWwsIHNwZWNpZnkgdGhlIGJhdGNoIHNpemUgYnkgJyArXG4gICAgICAgICAgICAncGFzc2luZyBhIGBiYXRjaElucHV0U2hhcGVgIG9wdGlvbiB0byB5b3VyIGZpcnN0IGxheWVyLlxcbicgK1xuICAgICAgICAgICAgJy0gSWYgdXNpbmcgdGhlIGZ1bmN0aW9uYWwgQVBJLCBzcGVjaWZ5IHRoZSBiYXRjaCBzaXplIGJ5ICcgK1xuICAgICAgICAgICAgJ3Bhc3NpbmcgYSBgYmF0Y2hTaGFwZWAgb3B0aW9uIHRvIHlvdXIgSW5wdXQgbGF5ZXIuJyk7XG4gICAgICB9XG4gICAgICAvLyBJbml0aWFsaXplIHN0YXRlIGlmIG51bGwuXG4gICAgICBpZiAodGhpcy5zdGF0ZXNfID09IG51bGwpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5jZWxsLnN0YXRlU2l6ZSkpIHtcbiAgICAgICAgICB0aGlzLnN0YXRlc18gPVxuICAgICAgICAgICAgICB0aGlzLmNlbGwuc3RhdGVTaXplLm1hcChkaW0gPT4gdGZjLnplcm9zKFtiYXRjaFNpemUsIGRpbV0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnN0YXRlc18gPSBbdGZjLnplcm9zKFtiYXRjaFNpemUsIHRoaXMuY2VsbC5zdGF0ZVNpemVdKV07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc3RhdGVzID09IG51bGwpIHtcbiAgICAgICAgLy8gRGlzcG9zZSBvbGQgc3RhdGUgdGVuc29ycy5cbiAgICAgICAgdGZjLmRpc3Bvc2UodGhpcy5zdGF0ZXNfKTtcbiAgICAgICAgLy8gRm9yIHN0YXRlZnVsIFJOTnMsIGZ1bGx5IGRpc3Bvc2Uga2VwdCBvbGQgc3RhdGVzLlxuICAgICAgICBpZiAodGhpcy5rZXB0U3RhdGVzICE9IG51bGwpIHtcbiAgICAgICAgICB0ZmMuZGlzcG9zZSh0aGlzLmtlcHRTdGF0ZXMpO1xuICAgICAgICAgIHRoaXMua2VwdFN0YXRlcyA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5jZWxsLnN0YXRlU2l6ZSkpIHtcbiAgICAgICAgICB0aGlzLnN0YXRlc18gPVxuICAgICAgICAgICAgICB0aGlzLmNlbGwuc3RhdGVTaXplLm1hcChkaW0gPT4gdGZjLnplcm9zKFtiYXRjaFNpemUsIGRpbV0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnN0YXRlc19bMF0gPSB0ZmMuemVyb3MoW2JhdGNoU2l6ZSwgdGhpcy5jZWxsLnN0YXRlU2l6ZV0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoc3RhdGVzKSkge1xuICAgICAgICAgIHN0YXRlcyA9IFtzdGF0ZXNdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0ZXMubGVuZ3RoICE9PSB0aGlzLnN0YXRlc18ubGVuZ3RoKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgICAgIGBMYXllciAke3RoaXMubmFtZX0gZXhwZWN0cyAke3RoaXMuc3RhdGVzXy5sZW5ndGh9IHN0YXRlKHMpLCBgICtcbiAgICAgICAgICAgICAgYGJ1dCBpdCByZWNlaXZlZCAke3N0YXRlcy5sZW5ndGh9IHN0YXRlIHZhbHVlKHMpLiBJbnB1dCBgICtcbiAgICAgICAgICAgICAgYHJlY2VpdmVkOiAke3N0YXRlc31gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0cmFpbmluZyA9PT0gdHJ1ZSkge1xuICAgICAgICAgIC8vIFN0b3JlIG9sZCBzdGF0ZSB0ZW5zb3JzIGZvciBjb21wbGV0ZSBkaXNwb3NhbCBsYXRlciwgaS5lLiwgZHVyaW5nXG4gICAgICAgICAgLy8gdGhlIG5leHQgbm8tYXJnIGNhbGwgdG8gdGhpcyBtZXRob2QuIFdlIGRvIG5vdCBkaXNwb3NlIHRoZSBvbGRcbiAgICAgICAgICAvLyBzdGF0ZXMgaW1tZWRpYXRlbHkgYmVjYXVzZSB0aGF0IEJQVFQgKGFtb25nIG90aGVyIHRoaW5ncykgcmVxdWlyZVxuICAgICAgICAgIC8vIHRoZW0uXG4gICAgICAgICAgdGhpcy5rZXB0U3RhdGVzLnB1c2godGhpcy5zdGF0ZXNfLnNsaWNlKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRmYy5kaXNwb3NlKHRoaXMuc3RhdGVzXyk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5zdGF0ZXNfLmxlbmd0aDsgKytpbmRleCkge1xuICAgICAgICAgIGNvbnN0IHZhbHVlID0gc3RhdGVzW2luZGV4XTtcbiAgICAgICAgICBjb25zdCBkaW0gPSBBcnJheS5pc0FycmF5KHRoaXMuY2VsbC5zdGF0ZVNpemUpID9cbiAgICAgICAgICAgICAgdGhpcy5jZWxsLnN0YXRlU2l6ZVtpbmRleF0gOlxuICAgICAgICAgICAgICB0aGlzLmNlbGwuc3RhdGVTaXplO1xuICAgICAgICAgIGNvbnN0IGV4cGVjdGVkU2hhcGUgPSBbYmF0Y2hTaXplLCBkaW1dO1xuICAgICAgICAgIGlmICghdXRpbC5hcnJheXNFcXVhbCh2YWx1ZS5zaGFwZSwgZXhwZWN0ZWRTaGFwZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgICAgICAgIGBTdGF0ZSAke2luZGV4fSBpcyBpbmNvbXBhdGlibGUgd2l0aCBsYXllciAke3RoaXMubmFtZX06IGAgK1xuICAgICAgICAgICAgICAgIGBleHBlY3RlZCBzaGFwZT0ke2V4cGVjdGVkU2hhcGV9LCByZWNlaXZlZCBzaGFwZT0ke1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5zaGFwZX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5zdGF0ZXNfW2luZGV4XSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLnN0YXRlc18gPSB0aGlzLnN0YXRlc18ubWFwKHN0YXRlID0+IHRmYy5rZWVwKHN0YXRlLmNsb25lKCkpKTtcbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFwcGx5KFxuICAgICAgaW5wdXRzOiBUZW5zb3J8VGVuc29yW118U3ltYm9saWNUZW5zb3J8U3ltYm9saWNUZW5zb3JbXSxcbiAgICAgIGt3YXJncz86IEt3YXJncyk6IFRlbnNvcnxUZW5zb3JbXXxTeW1ib2xpY1RlbnNvcnxTeW1ib2xpY1RlbnNvcltdIHtcbiAgICAvLyBUT0RPKGNhaXMpOiBGaWd1cmUgb3V0IHdoZXRoZXIgaW5pdGlhbFN0YXRlIGlzIGluIGt3YXJncyBvciBpbnB1dHMuXG4gICAgbGV0IGluaXRpYWxTdGF0ZTogVGVuc29yW118U3ltYm9saWNUZW5zb3JbXSA9XG4gICAgICAgIGt3YXJncyA9PSBudWxsID8gbnVsbCA6IGt3YXJnc1snaW5pdGlhbFN0YXRlJ107XG4gICAgbGV0IGNvbnN0YW50czogVGVuc29yW118U3ltYm9saWNUZW5zb3JbXSA9XG4gICAgICAgIGt3YXJncyA9PSBudWxsID8gbnVsbCA6IGt3YXJnc1snY29uc3RhbnRzJ107XG4gICAgaWYgKGt3YXJncyA9PSBudWxsKSB7XG4gICAgICBrd2FyZ3MgPSB7fTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFuZGFyZGl6ZWQgPVxuICAgICAgICBzdGFuZGFyZGl6ZUFyZ3MoaW5wdXRzLCBpbml0aWFsU3RhdGUsIGNvbnN0YW50cywgdGhpcy5udW1Db25zdGFudHMpO1xuICAgIGlucHV0cyA9IHN0YW5kYXJkaXplZC5pbnB1dHM7XG4gICAgaW5pdGlhbFN0YXRlID0gc3RhbmRhcmRpemVkLmluaXRpYWxTdGF0ZTtcbiAgICBjb25zdGFudHMgPSBzdGFuZGFyZGl6ZWQuY29uc3RhbnRzO1xuXG4gICAgLy8gSWYgYW55IG9mIGBpbml0aWFsX3N0YXRlYCBvciBgY29uc3RhbnRzYCBhcmUgc3BlY2lmaWVkIGFuZCBhcmVcbiAgICAvLyBgdGYuU3ltYm9saWNUZW5zb3JgcywgdGhlbiBhZGQgdGhlbSB0byB0aGUgaW5wdXRzIGFuZCB0ZW1wb3JhcmlseSBtb2RpZnlcbiAgICAvLyB0aGUgaW5wdXRfc3BlYyB0byBpbmNsdWRlIHRoZW0uXG5cbiAgICBsZXQgYWRkaXRpb25hbElucHV0czogQXJyYXk8VGVuc29yfFN5bWJvbGljVGVuc29yPiA9IFtdO1xuICAgIGxldCBhZGRpdGlvbmFsU3BlY3M6IElucHV0U3BlY1tdID0gW107XG4gICAgaWYgKGluaXRpYWxTdGF0ZSAhPSBudWxsKSB7XG4gICAgICBrd2FyZ3NbJ2luaXRpYWxTdGF0ZSddID0gaW5pdGlhbFN0YXRlO1xuICAgICAgYWRkaXRpb25hbElucHV0cyA9IGFkZGl0aW9uYWxJbnB1dHMuY29uY2F0KGluaXRpYWxTdGF0ZSk7XG4gICAgICB0aGlzLnN0YXRlU3BlYyA9IFtdO1xuICAgICAgZm9yIChjb25zdCBzdGF0ZSBvZiBpbml0aWFsU3RhdGUpIHtcbiAgICAgICAgdGhpcy5zdGF0ZVNwZWMucHVzaChuZXcgSW5wdXRTcGVjKHtzaGFwZTogc3RhdGUuc2hhcGV9KSk7XG4gICAgICB9XG4gICAgICAvLyBUT0RPKGNhaXMpOiBVc2UgdGhlIGZvbGxvd2luZyBpbnN0ZWFkLlxuICAgICAgLy8gdGhpcy5zdGF0ZVNwZWMgPSBpbml0aWFsU3RhdGUubWFwKHN0YXRlID0+IG5ldyBJbnB1dFNwZWMoe3NoYXBlOlxuICAgICAgLy8gc3RhdGUuc2hhcGV9KSk7XG4gICAgICBhZGRpdGlvbmFsU3BlY3MgPSBhZGRpdGlvbmFsU3BlY3MuY29uY2F0KHRoaXMuc3RhdGVTcGVjKTtcbiAgICB9XG4gICAgaWYgKGNvbnN0YW50cyAhPSBudWxsKSB7XG4gICAgICBrd2FyZ3NbJ2NvbnN0YW50cyddID0gY29uc3RhbnRzO1xuICAgICAgYWRkaXRpb25hbElucHV0cyA9IGFkZGl0aW9uYWxJbnB1dHMuY29uY2F0KGNvbnN0YW50cyk7XG4gICAgICAvLyBUT0RPKGNhaXMpOiBBZGQgdGhpcy5jb25zdGFudHNTcGVjLlxuICAgICAgdGhpcy5udW1Db25zdGFudHMgPSBjb25zdGFudHMubGVuZ3RoO1xuICAgIH1cblxuICAgIGNvbnN0IGlzVGVuc29yID0gYWRkaXRpb25hbElucHV0c1swXSBpbnN0YW5jZW9mIFN5bWJvbGljVGVuc29yO1xuICAgIGlmIChpc1RlbnNvcikge1xuICAgICAgLy8gQ29tcHV0ZSBmdWxsIGlucHV0IHNwZWMsIGluY2x1ZGluZyBzdGF0ZSBhbmQgY29uc3RhbnRzLlxuICAgICAgY29uc3QgZnVsbElucHV0ID1cbiAgICAgICAgICBbaW5wdXRzXS5jb25jYXQoYWRkaXRpb25hbElucHV0cykgYXMgVGVuc29yW10gfCBTeW1ib2xpY1RlbnNvcltdO1xuICAgICAgY29uc3QgZnVsbElucHV0U3BlYyA9IHRoaXMuaW5wdXRTcGVjLmNvbmNhdChhZGRpdGlvbmFsU3BlY3MpO1xuICAgICAgLy8gUGVyZm9ybSB0aGUgY2FsbCB3aXRoIHRlbXBvcmFyaWx5IHJlcGxhY2VkIGlucHV0U3BlYy5cbiAgICAgIGNvbnN0IG9yaWdpbmFsSW5wdXRTcGVjID0gdGhpcy5pbnB1dFNwZWM7XG4gICAgICB0aGlzLmlucHV0U3BlYyA9IGZ1bGxJbnB1dFNwZWM7XG4gICAgICBjb25zdCBvdXRwdXQgPSBzdXBlci5hcHBseShmdWxsSW5wdXQsIGt3YXJncyk7XG4gICAgICB0aGlzLmlucHV0U3BlYyA9IG9yaWdpbmFsSW5wdXRTcGVjO1xuICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHN1cGVyLmFwcGx5KGlucHV0cywga3dhcmdzKTtcbiAgICB9XG4gIH1cblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gIG92ZXJyaWRlIGNhbGwoaW5wdXRzOiBUZW5zb3J8VGVuc29yW10sIGt3YXJnczogS3dhcmdzKTogVGVuc29yfFRlbnNvcltdIHtcbiAgICAvLyBJbnB1dCBzaGFwZTogYFtzYW1wbGVzLCB0aW1lIChwYWRkZWQgd2l0aCB6ZXJvcyksIGlucHV0X2RpbV1gLlxuICAgIC8vIE5vdGUgdGhhdCB0aGUgLmJ1aWxkKCkgbWV0aG9kIG9mIHN1YmNsYXNzZXMgKiptdXN0KiogZGVmaW5lXG4gICAgLy8gdGhpcy5pbnB1dFNwZWMgYW5kIHRoaXMuc3RhdGVTcGVjIG93aXRoIGNvbXBsZXRlIGlucHV0IHNoYXBlcy5cbiAgICByZXR1cm4gdGlkeSgoKSA9PiB7XG4gICAgICBjb25zdCBtYXNrID0ga3dhcmdzID09IG51bGwgPyBudWxsIDoga3dhcmdzWydtYXNrJ10gYXMgVGVuc29yO1xuICAgICAgY29uc3QgdHJhaW5pbmcgPSBrd2FyZ3MgPT0gbnVsbCA/IG51bGwgOiBrd2FyZ3NbJ3RyYWluaW5nJ107XG4gICAgICBsZXQgaW5pdGlhbFN0YXRlOiBUZW5zb3JbXSA9XG4gICAgICAgICAga3dhcmdzID09IG51bGwgPyBudWxsIDoga3dhcmdzWydpbml0aWFsU3RhdGUnXTtcblxuICAgICAgaW5wdXRzID0gZ2V0RXhhY3RseU9uZVRlbnNvcihpbnB1dHMpO1xuICAgICAgaWYgKGluaXRpYWxTdGF0ZSA9PSBudWxsKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlZnVsKSB7XG4gICAgICAgICAgaW5pdGlhbFN0YXRlID0gdGhpcy5zdGF0ZXNfO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGluaXRpYWxTdGF0ZSA9IHRoaXMuZ2V0SW5pdGlhbFN0YXRlKGlucHV0cyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgbnVtU3RhdGVzID1cbiAgICAgICAgICBBcnJheS5pc0FycmF5KHRoaXMuY2VsbC5zdGF0ZVNpemUpID8gdGhpcy5jZWxsLnN0YXRlU2l6ZS5sZW5ndGggOiAxO1xuICAgICAgaWYgKGluaXRpYWxTdGF0ZS5sZW5ndGggIT09IG51bVN0YXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihcbiAgICAgICAgICAgIGBSTk4gTGF5ZXIgaGFzICR7bnVtU3RhdGVzfSBzdGF0ZShzKSBidXQgd2FzIHBhc3NlZCBgICtcbiAgICAgICAgICAgIGAke2luaXRpYWxTdGF0ZS5sZW5ndGh9IGluaXRpYWwgc3RhdGUocykuYCk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy51bnJvbGwpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgJ0lnbm9yaW5nIHVucm9sbCA9IHRydWUgZm9yIFJOTiBsYXllciwgZHVlIHRvIGltcGVyYXRpdmUgYmFja2VuZC4nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2VsbENhbGxLd2FyZ3M6IEt3YXJncyA9IHt0cmFpbmluZ307XG5cbiAgICAgIC8vIFRPRE8oY2Fpcyk6IEFkZCBzdXBwb3J0IGZvciBjb25zdGFudHMuXG4gICAgICBjb25zdCBzdGVwID0gKGlucHV0czogVGVuc29yLCBzdGF0ZXM6IFRlbnNvcltdKSA9PiB7XG4gICAgICAgIC8vIGBpbnB1dHNgIGFuZCBgc3RhdGVzYCBhcmUgY29uY2F0ZW5hdGVkIHRvIGZvcm0gYSBzaW5nbGUgYEFycmF5YCBvZlxuICAgICAgICAvLyBgdGYuVGVuc29yYHMgYXMgdGhlIGlucHV0IHRvIGBjZWxsLmNhbGwoKWAuXG4gICAgICAgIGNvbnN0IG91dHB1dHMgPVxuICAgICAgICAgICAgdGhpcy5jZWxsLmNhbGwoW2lucHV0c10uY29uY2F0KHN0YXRlcyksIGNlbGxDYWxsS3dhcmdzKSBhcyBUZW5zb3JbXTtcbiAgICAgICAgLy8gTWFyc2hhbGwgdGhlIHJldHVybiB2YWx1ZSBpbnRvIG91dHB1dCBhbmQgbmV3IHN0YXRlcy5cbiAgICAgICAgcmV0dXJuIFtvdXRwdXRzWzBdLCBvdXRwdXRzLnNsaWNlKDEpXSBhcyBbVGVuc29yLCBUZW5zb3JbXV07XG4gICAgICB9O1xuXG4gICAgICAvLyBUT0RPKGNhaXMpOiBBZGQgc3VwcG9ydCBmb3IgY29uc3RhbnRzLlxuXG4gICAgICBjb25zdCBybm5PdXRwdXRzID1cbiAgICAgICAgICBybm4oc3RlcCwgaW5wdXRzLCBpbml0aWFsU3RhdGUsIHRoaXMuZ29CYWNrd2FyZHMsIG1hc2ssIG51bGwsXG4gICAgICAgICAgICAgIHRoaXMudW5yb2xsLCB0aGlzLnJldHVyblNlcXVlbmNlcyk7XG4gICAgICBjb25zdCBsYXN0T3V0cHV0ID0gcm5uT3V0cHV0c1swXTtcbiAgICAgIGNvbnN0IG91dHB1dHMgPSBybm5PdXRwdXRzWzFdO1xuICAgICAgY29uc3Qgc3RhdGVzID0gcm5uT3V0cHV0c1syXTtcblxuICAgICAgaWYgKHRoaXMuc3RhdGVmdWwpIHtcbiAgICAgICAgdGhpcy5yZXNldFN0YXRlcyhzdGF0ZXMsIHRyYWluaW5nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5yZXR1cm5TZXF1ZW5jZXMgPyBvdXRwdXRzIDogbGFzdE91dHB1dDtcblxuICAgICAgLy8gVE9ETyhjYWlzKTogUG9ycGVydHkgc2V0IGxlYXJuaW5nIHBoYXNlIGZsYWcuXG5cbiAgICAgIGlmICh0aGlzLnJldHVyblN0YXRlKSB7XG4gICAgICAgIHJldHVybiBbb3V0cHV0XS5jb25jYXQoc3RhdGVzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBnZXRJbml0aWFsU3RhdGUoaW5wdXRzOiBUZW5zb3IpOiBUZW5zb3JbXSB7XG4gICAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgICAgLy8gQnVpbGQgYW4gYWxsLXplcm8gdGVuc29yIG9mIHNoYXBlIFtzYW1wbGVzLCBvdXRwdXREaW1dLlxuICAgICAgLy8gW1NhbXBsZXMsIHRpbWVTdGVwcywgaW5wdXREaW1dLlxuICAgICAgbGV0IGluaXRpYWxTdGF0ZSA9IHRmYy56ZXJvcyhpbnB1dHMuc2hhcGUpO1xuICAgICAgLy8gW1NhbXBsZXNdLlxuICAgICAgaW5pdGlhbFN0YXRlID0gdGZjLnN1bShpbml0aWFsU3RhdGUsIFsxLCAyXSk7XG4gICAgICBpbml0aWFsU3RhdGUgPSBLLmV4cGFuZERpbXMoaW5pdGlhbFN0YXRlKTsgIC8vIFtTYW1wbGVzLCAxXS5cblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5jZWxsLnN0YXRlU2l6ZSkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbC5zdGF0ZVNpemUubWFwKFxuICAgICAgICAgICAgZGltID0+IGRpbSA+IDEgPyBLLnRpbGUoaW5pdGlhbFN0YXRlLCBbMSwgZGltXSkgOiBpbml0aWFsU3RhdGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbC5zdGF0ZVNpemUgPiAxID9cbiAgICAgICAgICAgIFtLLnRpbGUoaW5pdGlhbFN0YXRlLCBbMSwgdGhpcy5jZWxsLnN0YXRlU2l6ZV0pXSA6XG4gICAgICAgICAgICBbaW5pdGlhbFN0YXRlXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGdldCB0cmFpbmFibGVXZWlnaHRzKCk6IExheWVyVmFyaWFibGVbXSB7XG4gICAgaWYgKCF0aGlzLnRyYWluYWJsZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICAvLyBQb3J0aW5nIE5vdGU6IEluIFR5cGVTY3JpcHQsIGB0aGlzYCBpcyBhbHdheXMgYW4gaW5zdGFuY2Ugb2YgYExheWVyYC5cbiAgICByZXR1cm4gdGhpcy5jZWxsLnRyYWluYWJsZVdlaWdodHM7XG4gIH1cblxuICBvdmVycmlkZSBnZXQgbm9uVHJhaW5hYmxlV2VpZ2h0cygpOiBMYXllclZhcmlhYmxlW10ge1xuICAgIC8vIFBvcnRpbmcgTm90ZTogSW4gVHlwZVNjcmlwdCwgYHRoaXNgIGlzIGFsd2F5cyBhbiBpbnN0YW5jZSBvZiBgTGF5ZXJgLlxuICAgIGlmICghdGhpcy50cmFpbmFibGUpIHtcbiAgICAgIHJldHVybiB0aGlzLmNlbGwud2VpZ2h0cztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2VsbC5ub25UcmFpbmFibGVXZWlnaHRzO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2V0RmFzdFdlaWdodEluaXREdXJpbmdCdWlsZCh2YWx1ZTogYm9vbGVhbikge1xuICAgIHN1cGVyLnNldEZhc3RXZWlnaHRJbml0RHVyaW5nQnVpbGQodmFsdWUpO1xuICAgIGlmICh0aGlzLmNlbGwgIT0gbnVsbCkge1xuICAgICAgdGhpcy5jZWxsLnNldEZhc3RXZWlnaHRJbml0RHVyaW5nQnVpbGQodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGdldENvbmZpZygpOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3Qge1xuICAgIGNvbnN0IGJhc2VDb25maWcgPSBzdXBlci5nZXRDb25maWcoKTtcblxuICAgIGNvbnN0IGNvbmZpZzogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0ID0ge1xuICAgICAgcmV0dXJuU2VxdWVuY2VzOiB0aGlzLnJldHVyblNlcXVlbmNlcyxcbiAgICAgIHJldHVyblN0YXRlOiB0aGlzLnJldHVyblN0YXRlLFxuICAgICAgZ29CYWNrd2FyZHM6IHRoaXMuZ29CYWNrd2FyZHMsXG4gICAgICBzdGF0ZWZ1bDogdGhpcy5zdGF0ZWZ1bCxcbiAgICAgIHVucm9sbDogdGhpcy51bnJvbGwsXG4gICAgfTtcblxuICAgIGlmICh0aGlzLm51bUNvbnN0YW50cyAhPSBudWxsKSB7XG4gICAgICBjb25maWdbJ251bUNvbnN0YW50cyddID0gdGhpcy5udW1Db25zdGFudHM7XG4gICAgfVxuXG4gICAgY29uc3QgY2VsbENvbmZpZyA9IHRoaXMuY2VsbC5nZXRDb25maWcoKTtcblxuICAgIGlmICh0aGlzLmdldENsYXNzTmFtZSgpID09PSBSTk4uY2xhc3NOYW1lKSB7XG4gICAgICBjb25maWdbJ2NlbGwnXSA9IHtcbiAgICAgICAgJ2NsYXNzTmFtZSc6IHRoaXMuY2VsbC5nZXRDbGFzc05hbWUoKSxcbiAgICAgICAgJ2NvbmZpZyc6IGNlbGxDb25maWcsXG4gICAgICB9IGFzIHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdFZhbHVlO1xuICAgIH1cblxuICAgIC8vIHRoaXMgb3JkZXIgaXMgbmVjZXNzYXJ5LCB0byBwcmV2ZW50IGNlbGwgbmFtZSBmcm9tIHJlcGxhY2luZyBsYXllciBuYW1lXG4gICAgcmV0dXJuIHsuLi5jZWxsQ29uZmlnLCAuLi5iYXNlQ29uZmlnLCAuLi5jb25maWd9O1xuICB9XG5cbiAgLyoqIEBub2NvbGxhcHNlICovXG4gIHN0YXRpYyBvdmVycmlkZSBmcm9tQ29uZmlnPFQgZXh0ZW5kcyBzZXJpYWxpemF0aW9uLlNlcmlhbGl6YWJsZT4oXG4gICAgICBjbHM6IHNlcmlhbGl6YXRpb24uU2VyaWFsaXphYmxlQ29uc3RydWN0b3I8VD4sXG4gICAgICBjb25maWc6IHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdCxcbiAgICAgIGN1c3RvbU9iamVjdHMgPSB7fSBhcyBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3QpOiBUIHtcbiAgICBjb25zdCBjZWxsQ29uZmlnID0gY29uZmlnWydjZWxsJ10gYXMgc2VyaWFsaXphdGlvbi5Db25maWdEaWN0O1xuICAgIGNvbnN0IGNlbGwgPSBkZXNlcmlhbGl6ZShjZWxsQ29uZmlnLCBjdXN0b21PYmplY3RzKSBhcyBSTk5DZWxsO1xuICAgIHJldHVybiBuZXcgY2xzKE9iamVjdC5hc3NpZ24oY29uZmlnLCB7Y2VsbH0pKTtcbiAgfVxufVxuc2VyaWFsaXphdGlvbi5yZWdpc3RlckNsYXNzKFJOTik7XG5cbi8vIFBvcnRpbmcgTm90ZTogVGhpcyBpcyBhIGNvbW1vbiBwYXJlbnQgY2xhc3MgZm9yIFJOTiBjZWxscy4gVGhlcmUgaXMgbm9cbi8vIGVxdWl2YWxlbnQgb2YgdGhpcyBpbiBQeUtlcmFzLiBIYXZpbmcgYSBjb21tb24gcGFyZW50IGNsYXNzIGZvcmdvZXMgdGhlXG4vLyAgbmVlZCBmb3IgYGhhc19hdHRyKGNlbGwsIC4uLilgIGNoZWNrcyBvciBpdHMgVHlwZVNjcmlwdCBlcXVpdmFsZW50LlxuLyoqXG4gKiBBbiBSTk5DZWxsIGxheWVyLlxuICpcbiAqIEBkb2Mge2hlYWRpbmc6ICdMYXllcnMnLCBzdWJoZWFkaW5nOiAnQ2xhc3Nlcyd9XG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSTk5DZWxsIGV4dGVuZHMgTGF5ZXIge1xuICAvKipcbiAgICogU2l6ZShzKSBvZiB0aGUgc3RhdGVzLlxuICAgKiBGb3IgUk5OIGNlbGxzIHdpdGggb25seSBhIHNpbmdsZSBzdGF0ZSwgdGhpcyBpcyBhIHNpbmdsZSBpbnRlZ2VyLlxuICAgKi9cbiAgLy8gU2VlXG4gIC8vIGh0dHBzOi8vd3d3LnR5cGVzY3JpcHRsYW5nLm9yZy9kb2NzL2hhbmRib29rL3JlbGVhc2Utbm90ZXMvdHlwZXNjcmlwdC00LTAuaHRtbCNwcm9wZXJ0aWVzLW92ZXJyaWRpbmctYWNjZXNzb3JzLWFuZC12aWNlLXZlcnNhLWlzLWFuLWVycm9yXG4gIHB1YmxpYyBhYnN0cmFjdCBzdGF0ZVNpemU6IG51bWJlcnxudW1iZXJbXTtcbiAgcHVibGljIGRyb3BvdXRNYXNrOiBUZW5zb3J8VGVuc29yW107XG4gIHB1YmxpYyByZWN1cnJlbnREcm9wb3V0TWFzazogVGVuc29yfFRlbnNvcltdO1xufVxuXG5leHBvcnQgZGVjbGFyZSBpbnRlcmZhY2UgU2ltcGxlUk5OQ2VsbExheWVyQXJncyBleHRlbmRzIExheWVyQXJncyB7XG4gIC8qKlxuICAgKiB1bml0czogUG9zaXRpdmUgaW50ZWdlciwgZGltZW5zaW9uYWxpdHkgb2YgdGhlIG91dHB1dCBzcGFjZS5cbiAgICovXG4gIHVuaXRzOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEFjdGl2YXRpb24gZnVuY3Rpb24gdG8gdXNlLlxuICAgKiBEZWZhdWx0OiBoeXBlcmJvbGljIHRhbmdlbnQgKCd0YW5oJykuXG4gICAqIElmIHlvdSBwYXNzIGBudWxsYCwgICdsaW5lYXInIGFjdGl2YXRpb24gd2lsbCBiZSBhcHBsaWVkLlxuICAgKi9cbiAgYWN0aXZhdGlvbj86IEFjdGl2YXRpb25JZGVudGlmaWVyO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBsYXllciB1c2VzIGEgYmlhcyB2ZWN0b3IuXG4gICAqL1xuICB1c2VCaWFzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXIgZm9yIHRoZSBga2VybmVsYCB3ZWlnaHRzIG1hdHJpeCwgdXNlZCBmb3IgdGhlIGxpbmVhclxuICAgKiB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgaW5wdXRzLlxuICAgKi9cbiAga2VybmVsSW5pdGlhbGl6ZXI/OiBJbml0aWFsaXplcklkZW50aWZpZXJ8SW5pdGlhbGl6ZXI7XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVyIGZvciB0aGUgYHJlY3VycmVudEtlcm5lbGAgd2VpZ2h0cyBtYXRyaXgsIHVzZWQgZm9yXG4gICAqIGxpbmVhciB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgcmVjdXJyZW50IHN0YXRlLlxuICAgKi9cbiAgcmVjdXJyZW50SW5pdGlhbGl6ZXI/OiBJbml0aWFsaXplcklkZW50aWZpZXJ8SW5pdGlhbGl6ZXI7XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVyIGZvciB0aGUgYmlhcyB2ZWN0b3IuXG4gICAqL1xuICBiaWFzSW5pdGlhbGl6ZXI/OiBJbml0aWFsaXplcklkZW50aWZpZXJ8SW5pdGlhbGl6ZXI7XG5cbiAgLyoqXG4gICAqIFJlZ3VsYXJpemVyIGZ1bmN0aW9uIGFwcGxpZWQgdG8gdGhlIGBrZXJuZWxgIHdlaWdodHMgbWF0cml4LlxuICAgKi9cbiAga2VybmVsUmVndWxhcml6ZXI/OiBSZWd1bGFyaXplcklkZW50aWZpZXJ8UmVndWxhcml6ZXI7XG5cbiAgLyoqXG4gICAqIFJlZ3VsYXJpemVyIGZ1bmN0aW9uIGFwcGxpZWQgdG8gdGhlIGByZWN1cnJlbnRfa2VybmVsYCB3ZWlnaHRzIG1hdHJpeC5cbiAgICovXG4gIHJlY3VycmVudFJlZ3VsYXJpemVyPzogUmVndWxhcml6ZXJJZGVudGlmaWVyfFJlZ3VsYXJpemVyO1xuXG4gIC8qKlxuICAgKiBSZWd1bGFyaXplciBmdW5jdGlvbiBhcHBsaWVkIHRvIHRoZSBiaWFzIHZlY3Rvci5cbiAgICovXG4gIGJpYXNSZWd1bGFyaXplcj86IFJlZ3VsYXJpemVySWRlbnRpZmllcnxSZWd1bGFyaXplcjtcblxuICAvKipcbiAgICogQ29uc3RyYWludCBmdW5jdGlvbiBhcHBsaWVkIHRvIHRoZSBga2VybmVsYCB3ZWlnaHRzIG1hdHJpeC5cbiAgICovXG4gIGtlcm5lbENvbnN0cmFpbnQ/OiBDb25zdHJhaW50SWRlbnRpZmllcnxDb25zdHJhaW50O1xuXG4gIC8qKlxuICAgKiBDb25zdHJhaW50IGZ1bmN0aW9uIGFwcGxpZWQgdG8gdGhlIGByZWN1cnJlbnRLZXJuZWxgIHdlaWdodHMgbWF0cml4LlxuICAgKi9cbiAgcmVjdXJyZW50Q29uc3RyYWludD86IENvbnN0cmFpbnRJZGVudGlmaWVyfENvbnN0cmFpbnQ7XG5cbiAgLyoqXG4gICAqIENvbnN0cmFpbnQgZnVuY3Rpb24gYXBwbGllZCB0byB0aGUgYmlhcyB2ZWN0b3IuXG4gICAqL1xuICBiaWFzQ29uc3RyYWludD86IENvbnN0cmFpbnRJZGVudGlmaWVyfENvbnN0cmFpbnQ7XG5cbiAgLyoqXG4gICAqIEZsb2F0IG51bWJlciBiZXR3ZWVuIDAgYW5kIDEuIEZyYWN0aW9uIG9mIHRoZSB1bml0cyB0byBkcm9wIGZvciB0aGUgbGluZWFyXG4gICAqIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBpbnB1dHMuXG4gICAqL1xuICBkcm9wb3V0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBGbG9hdCBudW1iZXIgYmV0d2VlbiAwIGFuZCAxLiBGcmFjdGlvbiBvZiB0aGUgdW5pdHMgdG8gZHJvcCBmb3IgdGhlIGxpbmVhclxuICAgKiB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgcmVjdXJyZW50IHN0YXRlLlxuICAgKi9cbiAgcmVjdXJyZW50RHJvcG91dD86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhpcyBpcyBhZGRlZCBmb3IgdGVzdCBESSBwdXJwb3NlLlxuICAgKi9cbiAgZHJvcG91dEZ1bmM/OiBGdW5jdGlvbjtcbn1cblxuZXhwb3J0IGNsYXNzIFNpbXBsZVJOTkNlbGwgZXh0ZW5kcyBSTk5DZWxsIHtcbiAgLyoqIEBub2NvbGxhcHNlICovXG4gIHN0YXRpYyBjbGFzc05hbWUgPSAnU2ltcGxlUk5OQ2VsbCc7XG4gIHJlYWRvbmx5IHVuaXRzOiBudW1iZXI7XG4gIHJlYWRvbmx5IGFjdGl2YXRpb246IEFjdGl2YXRpb247XG4gIHJlYWRvbmx5IHVzZUJpYXM6IGJvb2xlYW47XG5cbiAgcmVhZG9ubHkga2VybmVsSW5pdGlhbGl6ZXI6IEluaXRpYWxpemVyO1xuICByZWFkb25seSByZWN1cnJlbnRJbml0aWFsaXplcjogSW5pdGlhbGl6ZXI7XG4gIHJlYWRvbmx5IGJpYXNJbml0aWFsaXplcjogSW5pdGlhbGl6ZXI7XG5cbiAgcmVhZG9ubHkga2VybmVsQ29uc3RyYWludDogQ29uc3RyYWludDtcbiAgcmVhZG9ubHkgcmVjdXJyZW50Q29uc3RyYWludDogQ29uc3RyYWludDtcbiAgcmVhZG9ubHkgYmlhc0NvbnN0cmFpbnQ6IENvbnN0cmFpbnQ7XG5cbiAgcmVhZG9ubHkga2VybmVsUmVndWxhcml6ZXI6IFJlZ3VsYXJpemVyO1xuICByZWFkb25seSByZWN1cnJlbnRSZWd1bGFyaXplcjogUmVndWxhcml6ZXI7XG4gIHJlYWRvbmx5IGJpYXNSZWd1bGFyaXplcjogUmVndWxhcml6ZXI7XG5cbiAgcmVhZG9ubHkgZHJvcG91dDogbnVtYmVyO1xuICByZWFkb25seSByZWN1cnJlbnREcm9wb3V0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGRyb3BvdXRGdW5jOiBGdW5jdGlvbjtcblxuICByZWFkb25seSBzdGF0ZVNpemU6IG51bWJlcjtcblxuICBrZXJuZWw6IExheWVyVmFyaWFibGU7XG4gIHJlY3VycmVudEtlcm5lbDogTGF5ZXJWYXJpYWJsZTtcbiAgYmlhczogTGF5ZXJWYXJpYWJsZTtcblxuICByZWFkb25seSBERUZBVUxUX0FDVElWQVRJT04gPSAndGFuaCc7XG4gIHJlYWRvbmx5IERFRkFVTFRfS0VSTkVMX0lOSVRJQUxJWkVSID0gJ2dsb3JvdE5vcm1hbCc7XG4gIHJlYWRvbmx5IERFRkFVTFRfUkVDVVJSRU5UX0lOSVRJQUxJWkVSID0gJ29ydGhvZ29uYWwnO1xuICByZWFkb25seSBERUZBVUxUX0JJQVNfSU5JVElBTElaRVI6IEluaXRpYWxpemVySWRlbnRpZmllciA9ICd6ZXJvcyc7XG5cbiAgY29uc3RydWN0b3IoYXJnczogU2ltcGxlUk5OQ2VsbExheWVyQXJncykge1xuICAgIHN1cGVyKGFyZ3MpO1xuICAgIHRoaXMudW5pdHMgPSBhcmdzLnVuaXRzO1xuICAgIGFzc2VydFBvc2l0aXZlSW50ZWdlcih0aGlzLnVuaXRzLCBgdW5pdHNgKTtcbiAgICB0aGlzLmFjdGl2YXRpb24gPSBnZXRBY3RpdmF0aW9uKFxuICAgICAgICBhcmdzLmFjdGl2YXRpb24gPT0gbnVsbCA/IHRoaXMuREVGQVVMVF9BQ1RJVkFUSU9OIDogYXJncy5hY3RpdmF0aW9uKTtcbiAgICB0aGlzLnVzZUJpYXMgPSBhcmdzLnVzZUJpYXMgPT0gbnVsbCA/IHRydWUgOiBhcmdzLnVzZUJpYXM7XG5cbiAgICB0aGlzLmtlcm5lbEluaXRpYWxpemVyID0gZ2V0SW5pdGlhbGl6ZXIoXG4gICAgICAgIGFyZ3Mua2VybmVsSW5pdGlhbGl6ZXIgfHwgdGhpcy5ERUZBVUxUX0tFUk5FTF9JTklUSUFMSVpFUik7XG4gICAgdGhpcy5yZWN1cnJlbnRJbml0aWFsaXplciA9IGdldEluaXRpYWxpemVyKFxuICAgICAgICBhcmdzLnJlY3VycmVudEluaXRpYWxpemVyIHx8IHRoaXMuREVGQVVMVF9SRUNVUlJFTlRfSU5JVElBTElaRVIpO1xuXG4gICAgdGhpcy5iaWFzSW5pdGlhbGl6ZXIgPVxuICAgICAgICBnZXRJbml0aWFsaXplcihhcmdzLmJpYXNJbml0aWFsaXplciB8fCB0aGlzLkRFRkFVTFRfQklBU19JTklUSUFMSVpFUik7XG5cbiAgICB0aGlzLmtlcm5lbFJlZ3VsYXJpemVyID0gZ2V0UmVndWxhcml6ZXIoYXJncy5rZXJuZWxSZWd1bGFyaXplcik7XG4gICAgdGhpcy5yZWN1cnJlbnRSZWd1bGFyaXplciA9IGdldFJlZ3VsYXJpemVyKGFyZ3MucmVjdXJyZW50UmVndWxhcml6ZXIpO1xuICAgIHRoaXMuYmlhc1JlZ3VsYXJpemVyID0gZ2V0UmVndWxhcml6ZXIoYXJncy5iaWFzUmVndWxhcml6ZXIpO1xuXG4gICAgdGhpcy5rZXJuZWxDb25zdHJhaW50ID0gZ2V0Q29uc3RyYWludChhcmdzLmtlcm5lbENvbnN0cmFpbnQpO1xuICAgIHRoaXMucmVjdXJyZW50Q29uc3RyYWludCA9IGdldENvbnN0cmFpbnQoYXJncy5yZWN1cnJlbnRDb25zdHJhaW50KTtcbiAgICB0aGlzLmJpYXNDb25zdHJhaW50ID0gZ2V0Q29uc3RyYWludChhcmdzLmJpYXNDb25zdHJhaW50KTtcblxuICAgIHRoaXMuZHJvcG91dCA9IG1hdGhfdXRpbHMubWluKFxuICAgICAgICBbMSwgbWF0aF91dGlscy5tYXgoWzAsIGFyZ3MuZHJvcG91dCA9PSBudWxsID8gMCA6IGFyZ3MuZHJvcG91dF0pXSk7XG4gICAgdGhpcy5yZWN1cnJlbnREcm9wb3V0ID0gbWF0aF91dGlscy5taW4oW1xuICAgICAgMSxcbiAgICAgIG1hdGhfdXRpbHMubWF4KFxuICAgICAgICAgIFswLCBhcmdzLnJlY3VycmVudERyb3BvdXQgPT0gbnVsbCA/IDAgOiBhcmdzLnJlY3VycmVudERyb3BvdXRdKVxuICAgIF0pO1xuICAgIHRoaXMuZHJvcG91dEZ1bmMgPSBhcmdzLmRyb3BvdXRGdW5jO1xuICAgIHRoaXMuc3RhdGVTaXplID0gdGhpcy51bml0cztcbiAgICB0aGlzLmRyb3BvdXRNYXNrID0gbnVsbDtcbiAgICB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrID0gbnVsbDtcbiAgfVxuXG4gIG92ZXJyaWRlIGJ1aWxkKGlucHV0U2hhcGU6IFNoYXBlfFNoYXBlW10pOiB2b2lkIHtcbiAgICBpbnB1dFNoYXBlID0gZ2V0RXhhY3RseU9uZVNoYXBlKGlucHV0U2hhcGUpO1xuICAgIC8vIFRPRE8oY2Fpcyk6IFVzZSByZWd1bGFyaXplci5cbiAgICB0aGlzLmtlcm5lbCA9IHRoaXMuYWRkV2VpZ2h0KFxuICAgICAgICAna2VybmVsJywgW2lucHV0U2hhcGVbaW5wdXRTaGFwZS5sZW5ndGggLSAxXSwgdGhpcy51bml0c10sIG51bGwsXG4gICAgICAgIHRoaXMua2VybmVsSW5pdGlhbGl6ZXIsIHRoaXMua2VybmVsUmVndWxhcml6ZXIsIHRydWUsXG4gICAgICAgIHRoaXMua2VybmVsQ29uc3RyYWludCk7XG4gICAgdGhpcy5yZWN1cnJlbnRLZXJuZWwgPSB0aGlzLmFkZFdlaWdodChcbiAgICAgICAgJ3JlY3VycmVudF9rZXJuZWwnLCBbdGhpcy51bml0cywgdGhpcy51bml0c10sIG51bGwsXG4gICAgICAgIHRoaXMucmVjdXJyZW50SW5pdGlhbGl6ZXIsIHRoaXMucmVjdXJyZW50UmVndWxhcml6ZXIsIHRydWUsXG4gICAgICAgIHRoaXMucmVjdXJyZW50Q29uc3RyYWludCk7XG4gICAgaWYgKHRoaXMudXNlQmlhcykge1xuICAgICAgdGhpcy5iaWFzID0gdGhpcy5hZGRXZWlnaHQoXG4gICAgICAgICAgJ2JpYXMnLCBbdGhpcy51bml0c10sIG51bGwsIHRoaXMuYmlhc0luaXRpYWxpemVyLFxuICAgICAgICAgIHRoaXMuYmlhc1JlZ3VsYXJpemVyLCB0cnVlLCB0aGlzLmJpYXNDb25zdHJhaW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5iaWFzID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5idWlsdCA9IHRydWU7XG4gIH1cblxuICAvLyBQb3J0aW5nIE5vdGU6IFB5S2VyYXMnIGVxdWl2YWxlbnQgb2YgdGhpcyBtZXRob2QgdGFrZXMgdHdvIHRlbnNvciBpbnB1dHM6XG4gIC8vICAgYGlucHV0c2AgYW5kIGBzdGF0ZXNgLiBIZXJlLCB0aGUgdHdvIHRlbnNvcnMgYXJlIGNvbWJpbmVkIGludG8gYW5cbiAgLy8gICBgVGVuc29yW11gIEFycmF5IGFzIHRoZSBmaXJzdCBpbnB1dCBhcmd1bWVudC5cbiAgLy8gICBTaW1pbGFybHksIFB5S2VyYXMnIGVxdWl2YWxlbnQgb2YgdGhpcyBtZXRob2QgcmV0dXJucyB0d28gdmFsdWVzOlxuICAvLyAgICBgb3V0cHV0YCBhbmQgYFtvdXRwdXRdYC4gSGVyZSB0aGUgdHdvIGFyZSBjb21iaW5lZCBpbnRvIG9uZSBsZW5ndGgtMlxuICAvLyAgICBgVGVuc29yW11gLCBjb25zaXN0aW5nIG9mIGBvdXRwdXRgIHJlcGVhdGVkLlxuICBvdmVycmlkZSBjYWxsKGlucHV0czogVGVuc29yfFRlbnNvcltdLCBrd2FyZ3M6IEt3YXJncyk6IFRlbnNvcnxUZW5zb3JbXSB7XG4gICAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgICAgaW5wdXRzID0gaW5wdXRzIGFzIFRlbnNvcltdO1xuICAgICAgaWYgKGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbHVlRXJyb3IoXG4gICAgICAgICAgICBgU2ltcGxlUk5OQ2VsbCBleHBlY3RzIDIgaW5wdXQgVGVuc29ycywgZ290ICR7aW5wdXRzLmxlbmd0aH0uYCk7XG4gICAgICB9XG4gICAgICBsZXQgcHJldk91dHB1dCA9IGlucHV0c1sxXTtcbiAgICAgIGlucHV0cyA9IGlucHV0c1swXTtcbiAgICAgIGNvbnN0IHRyYWluaW5nID0ga3dhcmdzWyd0cmFpbmluZyddID09IG51bGwgPyBmYWxzZSA6IGt3YXJnc1sndHJhaW5pbmcnXTtcblxuICAgICAgaWYgKDAgPCB0aGlzLmRyb3BvdXQgJiYgdGhpcy5kcm9wb3V0IDwgMSAmJiB0aGlzLmRyb3BvdXRNYXNrID09IG51bGwpIHtcbiAgICAgICAgdGhpcy5kcm9wb3V0TWFzayA9IGdlbmVyYXRlRHJvcG91dE1hc2soe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVzOiAoKSA9PiB0ZmMub25lc0xpa2UoaW5wdXRzIGFzIFRlbnNvciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhdGU6IHRoaXMuZHJvcG91dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BvdXRGdW5jOiB0aGlzLmRyb3BvdXRGdW5jLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkgYXMgVGVuc29yO1xuICAgICAgfVxuICAgICAgaWYgKDAgPCB0aGlzLnJlY3VycmVudERyb3BvdXQgJiYgdGhpcy5yZWN1cnJlbnREcm9wb3V0IDwgMSAmJlxuICAgICAgICAgIHRoaXMucmVjdXJyZW50RHJvcG91dE1hc2sgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrID0gZ2VuZXJhdGVEcm9wb3V0TWFzayh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZXM6ICgpID0+IHRmYy5vbmVzTGlrZShwcmV2T3V0cHV0KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF0ZTogdGhpcy5yZWN1cnJlbnREcm9wb3V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpbmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcG91dEZ1bmM6IHRoaXMuZHJvcG91dEZ1bmMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSBhcyBUZW5zb3I7XG4gICAgICB9XG4gICAgICBsZXQgaDogVGVuc29yO1xuICAgICAgY29uc3QgZHBNYXNrOiBUZW5zb3IgPSB0aGlzLmRyb3BvdXRNYXNrIGFzIFRlbnNvcjtcbiAgICAgIGNvbnN0IHJlY0RwTWFzazogVGVuc29yID0gdGhpcy5yZWN1cnJlbnREcm9wb3V0TWFzayBhcyBUZW5zb3I7XG4gICAgICBpZiAoZHBNYXNrICE9IG51bGwpIHtcbiAgICAgICAgaCA9IEsuZG90KHRmYy5tdWwoaW5wdXRzLCBkcE1hc2spLCB0aGlzLmtlcm5lbC5yZWFkKCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaCA9IEsuZG90KGlucHV0cywgdGhpcy5rZXJuZWwucmVhZCgpKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmJpYXMgIT0gbnVsbCkge1xuICAgICAgICBoID0gSy5iaWFzQWRkKGgsIHRoaXMuYmlhcy5yZWFkKCkpO1xuICAgICAgfVxuICAgICAgaWYgKHJlY0RwTWFzayAhPSBudWxsKSB7XG4gICAgICAgIHByZXZPdXRwdXQgPSB0ZmMubXVsKHByZXZPdXRwdXQsIHJlY0RwTWFzayk7XG4gICAgICB9XG4gICAgICBsZXQgb3V0cHV0ID0gdGZjLmFkZChoLCBLLmRvdChwcmV2T3V0cHV0LCB0aGlzLnJlY3VycmVudEtlcm5lbC5yZWFkKCkpKTtcbiAgICAgIGlmICh0aGlzLmFjdGl2YXRpb24gIT0gbnVsbCkge1xuICAgICAgICBvdXRwdXQgPSB0aGlzLmFjdGl2YXRpb24uYXBwbHkob3V0cHV0KTtcbiAgICAgIH1cblxuICAgICAgLy8gVE9ETyhjYWlzKTogUHJvcGVybHkgc2V0IGxlYXJuaW5nIHBoYXNlIG9uIG91dHB1dCB0ZW5zb3I/XG4gICAgICByZXR1cm4gW291dHB1dCwgb3V0cHV0XTtcbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGdldENvbmZpZygpOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3Qge1xuICAgIGNvbnN0IGJhc2VDb25maWcgPSBzdXBlci5nZXRDb25maWcoKTtcblxuICAgIGNvbnN0IGNvbmZpZzogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0ID0ge1xuICAgICAgdW5pdHM6IHRoaXMudW5pdHMsXG4gICAgICBhY3RpdmF0aW9uOiBzZXJpYWxpemVBY3RpdmF0aW9uKHRoaXMuYWN0aXZhdGlvbiksXG4gICAgICB1c2VCaWFzOiB0aGlzLnVzZUJpYXMsXG4gICAgICBrZXJuZWxJbml0aWFsaXplcjogc2VyaWFsaXplSW5pdGlhbGl6ZXIodGhpcy5rZXJuZWxJbml0aWFsaXplciksXG4gICAgICByZWN1cnJlbnRJbml0aWFsaXplcjogc2VyaWFsaXplSW5pdGlhbGl6ZXIodGhpcy5yZWN1cnJlbnRJbml0aWFsaXplciksXG4gICAgICBiaWFzSW5pdGlhbGl6ZXI6IHNlcmlhbGl6ZUluaXRpYWxpemVyKHRoaXMuYmlhc0luaXRpYWxpemVyKSxcbiAgICAgIGtlcm5lbFJlZ3VsYXJpemVyOiBzZXJpYWxpemVSZWd1bGFyaXplcih0aGlzLmtlcm5lbFJlZ3VsYXJpemVyKSxcbiAgICAgIHJlY3VycmVudFJlZ3VsYXJpemVyOiBzZXJpYWxpemVSZWd1bGFyaXplcih0aGlzLnJlY3VycmVudFJlZ3VsYXJpemVyKSxcbiAgICAgIGJpYXNSZWd1bGFyaXplcjogc2VyaWFsaXplUmVndWxhcml6ZXIodGhpcy5iaWFzUmVndWxhcml6ZXIpLFxuICAgICAgYWN0aXZpdHlSZWd1bGFyaXplcjogc2VyaWFsaXplUmVndWxhcml6ZXIodGhpcy5hY3Rpdml0eVJlZ3VsYXJpemVyKSxcbiAgICAgIGtlcm5lbENvbnN0cmFpbnQ6IHNlcmlhbGl6ZUNvbnN0cmFpbnQodGhpcy5rZXJuZWxDb25zdHJhaW50KSxcbiAgICAgIHJlY3VycmVudENvbnN0cmFpbnQ6IHNlcmlhbGl6ZUNvbnN0cmFpbnQodGhpcy5yZWN1cnJlbnRDb25zdHJhaW50KSxcbiAgICAgIGJpYXNDb25zdHJhaW50OiBzZXJpYWxpemVDb25zdHJhaW50KHRoaXMuYmlhc0NvbnN0cmFpbnQpLFxuICAgICAgZHJvcG91dDogdGhpcy5kcm9wb3V0LFxuICAgICAgcmVjdXJyZW50RHJvcG91dDogdGhpcy5yZWN1cnJlbnREcm9wb3V0LFxuICAgIH07XG5cbiAgICByZXR1cm4gey4uLmJhc2VDb25maWcsIC4uLmNvbmZpZ307XG4gIH1cbn1cbnNlcmlhbGl6YXRpb24ucmVnaXN0ZXJDbGFzcyhTaW1wbGVSTk5DZWxsKTtcblxuZXhwb3J0IGRlY2xhcmUgaW50ZXJmYWNlIFNpbXBsZVJOTkxheWVyQXJncyBleHRlbmRzIEJhc2VSTk5MYXllckFyZ3Mge1xuICAvKipcbiAgICogUG9zaXRpdmUgaW50ZWdlciwgZGltZW5zaW9uYWxpdHkgb2YgdGhlIG91dHB1dCBzcGFjZS5cbiAgICovXG4gIHVuaXRzOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEFjdGl2YXRpb24gZnVuY3Rpb24gdG8gdXNlLlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byAgaHlwZXJib2xpYyB0YW5nZW50IChgdGFuaGApXG4gICAqXG4gICAqIElmIHlvdSBwYXNzIGBudWxsYCwgbm8gYWN0aXZhdGlvbiB3aWxsIGJlIGFwcGxpZWQuXG4gICAqL1xuICBhY3RpdmF0aW9uPzogQWN0aXZhdGlvbklkZW50aWZpZXI7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGxheWVyIHVzZXMgYSBiaWFzIHZlY3Rvci5cbiAgICovXG4gIHVzZUJpYXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplciBmb3IgdGhlIGBrZXJuZWxgIHdlaWdodHMgbWF0cml4LCB1c2VkIGZvciB0aGUgbGluZWFyXG4gICAqIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBpbnB1dHMuXG4gICAqL1xuICBrZXJuZWxJbml0aWFsaXplcj86IEluaXRpYWxpemVySWRlbnRpZmllcnxJbml0aWFsaXplcjtcblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXIgZm9yIHRoZSBgcmVjdXJyZW50S2VybmVsYCB3ZWlnaHRzIG1hdHJpeCwgdXNlZCBmb3JcbiAgICogbGluZWFyIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSByZWN1cnJlbnQgc3RhdGUuXG4gICAqL1xuICByZWN1cnJlbnRJbml0aWFsaXplcj86IEluaXRpYWxpemVySWRlbnRpZmllcnxJbml0aWFsaXplcjtcblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXIgZm9yIHRoZSBiaWFzIHZlY3Rvci5cbiAgICovXG4gIGJpYXNJbml0aWFsaXplcj86IEluaXRpYWxpemVySWRlbnRpZmllcnxJbml0aWFsaXplcjtcblxuICAvKipcbiAgICogUmVndWxhcml6ZXIgZnVuY3Rpb24gYXBwbGllZCB0byB0aGUga2VybmVsIHdlaWdodHMgbWF0cml4LlxuICAgKi9cbiAga2VybmVsUmVndWxhcml6ZXI/OiBSZWd1bGFyaXplcklkZW50aWZpZXJ8UmVndWxhcml6ZXI7XG5cbiAgLyoqXG4gICAqIFJlZ3VsYXJpemVyIGZ1bmN0aW9uIGFwcGxpZWQgdG8gdGhlIHJlY3VycmVudEtlcm5lbCB3ZWlnaHRzIG1hdHJpeC5cbiAgICovXG4gIHJlY3VycmVudFJlZ3VsYXJpemVyPzogUmVndWxhcml6ZXJJZGVudGlmaWVyfFJlZ3VsYXJpemVyO1xuXG4gIC8qKlxuICAgKiBSZWd1bGFyaXplciBmdW5jdGlvbiBhcHBsaWVkIHRvIHRoZSBiaWFzIHZlY3Rvci5cbiAgICovXG4gIGJpYXNSZWd1bGFyaXplcj86IFJlZ3VsYXJpemVySWRlbnRpZmllcnxSZWd1bGFyaXplcjtcblxuICAvKipcbiAgICogQ29uc3RyYWludCBmdW5jdGlvbiBhcHBsaWVkIHRvIHRoZSBrZXJuZWwgd2VpZ2h0cyBtYXRyaXguXG4gICAqL1xuICBrZXJuZWxDb25zdHJhaW50PzogQ29uc3RyYWludElkZW50aWZpZXJ8Q29uc3RyYWludDtcblxuICAvKipcbiAgICogQ29uc3RyYWludCBmdW5jdGlvbiBhcHBsaWVkIHRvIHRoZSByZWN1cnJlbnRLZXJuZWwgd2VpZ2h0cyBtYXRyaXguXG4gICAqL1xuICByZWN1cnJlbnRDb25zdHJhaW50PzogQ29uc3RyYWludElkZW50aWZpZXJ8Q29uc3RyYWludDtcblxuICAvKipcbiAgICogQ29uc3RyYWludCBmdW5jdGlvbiBhcHBsaWVkIHRvIHRoZSBiaWFzIHZlY3Rvci5cbiAgICovXG4gIGJpYXNDb25zdHJhaW50PzogQ29uc3RyYWludElkZW50aWZpZXJ8Q29uc3RyYWludDtcblxuICAvKipcbiAgICogTnVtYmVyIGJldHdlZW4gMCBhbmQgMS4gRnJhY3Rpb24gb2YgdGhlIHVuaXRzIHRvIGRyb3AgZm9yIHRoZSBsaW5lYXJcbiAgICogdHJhbnNmb3JtYXRpb24gb2YgdGhlIGlucHV0cy5cbiAgICovXG4gIGRyb3BvdXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE51bWJlciBiZXR3ZWVuIDAgYW5kIDEuIEZyYWN0aW9uIG9mIHRoZSB1bml0cyB0byBkcm9wIGZvciB0aGUgbGluZWFyXG4gICAqIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSByZWN1cnJlbnQgc3RhdGUuXG4gICAqL1xuICByZWN1cnJlbnREcm9wb3V0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGlzIGlzIGFkZGVkIGZvciB0ZXN0IERJIHB1cnBvc2UuXG4gICAqL1xuICBkcm9wb3V0RnVuYz86IEZ1bmN0aW9uO1xufVxuXG4vKipcbiAqIFJOTkxheWVyQ29uZmlnIGlzIGlkZW50aWNhbCB0byBCYXNlUk5OTGF5ZXJDb25maWcsIGV4Y2VwdCBpdCBtYWtlcyB0aGVcbiAqIGBjZWxsYCBwcm9wZXJ0eSByZXF1aXJlZC4gVGhpcyBpbnRlcmZhY2UgaXMgdG8gYmUgdXNlZCB3aXRoIGNvbnN0cnVjdG9yc1xuICogb2YgY29uY3JldGUgUk5OIGxheWVyIHN1YnR5cGVzLlxuICovXG5leHBvcnQgZGVjbGFyZSBpbnRlcmZhY2UgUk5OTGF5ZXJBcmdzIGV4dGVuZHMgQmFzZVJOTkxheWVyQXJncyB7XG4gIGNlbGw6IFJOTkNlbGx8Uk5OQ2VsbFtdO1xufVxuXG5leHBvcnQgY2xhc3MgU2ltcGxlUk5OIGV4dGVuZHMgUk5OIHtcbiAgLyoqIEBub2NvbGxhcHNlICovXG4gIHN0YXRpYyBvdmVycmlkZSBjbGFzc05hbWUgPSAnU2ltcGxlUk5OJztcbiAgY29uc3RydWN0b3IoYXJnczogU2ltcGxlUk5OTGF5ZXJBcmdzKSB7XG4gICAgYXJncy5jZWxsID0gbmV3IFNpbXBsZVJOTkNlbGwoYXJncyk7XG4gICAgc3VwZXIoYXJncyBhcyBSTk5MYXllckFyZ3MpO1xuICAgIC8vIFRPRE8oY2Fpcyk6IEFkZCBhY3Rpdml0eVJlZ3VsYXJpemVyLlxuICB9XG5cbiAgb3ZlcnJpZGUgY2FsbChpbnB1dHM6IFRlbnNvcnxUZW5zb3JbXSwga3dhcmdzOiBLd2FyZ3MpOiBUZW5zb3J8VGVuc29yW10ge1xuICAgIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmNlbGwuZHJvcG91dE1hc2sgIT0gbnVsbCkge1xuICAgICAgICB0ZmMuZGlzcG9zZSh0aGlzLmNlbGwuZHJvcG91dE1hc2spO1xuICAgICAgICB0aGlzLmNlbGwuZHJvcG91dE1hc2sgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuY2VsbC5yZWN1cnJlbnREcm9wb3V0TWFzayAhPSBudWxsKSB7XG4gICAgICAgIHRmYy5kaXNwb3NlKHRoaXMuY2VsbC5yZWN1cnJlbnREcm9wb3V0TWFzayk7XG4gICAgICAgIHRoaXMuY2VsbC5yZWN1cnJlbnREcm9wb3V0TWFzayA9IG51bGw7XG4gICAgICB9XG4gICAgICBjb25zdCBtYXNrID0ga3dhcmdzID09IG51bGwgPyBudWxsIDoga3dhcmdzWydtYXNrJ107XG4gICAgICBjb25zdCB0cmFpbmluZyA9IGt3YXJncyA9PSBudWxsID8gbnVsbCA6IGt3YXJnc1sndHJhaW5pbmcnXTtcbiAgICAgIGNvbnN0IGluaXRpYWxTdGF0ZTogVGVuc29yW10gPVxuICAgICAgICAgIGt3YXJncyA9PSBudWxsID8gbnVsbCA6IGt3YXJnc1snaW5pdGlhbFN0YXRlJ107XG4gICAgICByZXR1cm4gc3VwZXIuY2FsbChpbnB1dHMsIHttYXNrLCB0cmFpbmluZywgaW5pdGlhbFN0YXRlfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQG5vY29sbGFwc2UgKi9cbiAgc3RhdGljIG92ZXJyaWRlIGZyb21Db25maWc8VCBleHRlbmRzIHNlcmlhbGl6YXRpb24uU2VyaWFsaXphYmxlPihcbiAgICAgIGNsczogc2VyaWFsaXphdGlvbi5TZXJpYWxpemFibGVDb25zdHJ1Y3RvcjxUPixcbiAgICAgIGNvbmZpZzogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0KTogVCB7XG4gICAgcmV0dXJuIG5ldyBjbHMoY29uZmlnKTtcbiAgfVxufVxuc2VyaWFsaXphdGlvbi5yZWdpc3RlckNsYXNzKFNpbXBsZVJOTik7XG5cbi8vIFBvcnRpbmcgTm90ZTogU2luY2UgdGhpcyBpcyBhIHN1cGVyc2V0IG9mIFNpbXBsZVJOTkxheWVyQ29uZmlnLCB3ZSBleHRlbmRcbi8vICAgdGhhdCBpbnRlcmZhY2UgaW5zdGVhZCBvZiByZXBlYXRpbmcgdGhlIGZpZWxkcy5cbmV4cG9ydCBkZWNsYXJlIGludGVyZmFjZSBHUlVDZWxsTGF5ZXJBcmdzIGV4dGVuZHMgU2ltcGxlUk5OQ2VsbExheWVyQXJncyB7XG4gIC8qKlxuICAgKiBBY3RpdmF0aW9uIGZ1bmN0aW9uIHRvIHVzZSBmb3IgdGhlIHJlY3VycmVudCBzdGVwLlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byBoYXJkIHNpZ21vaWQgKGBoYXJkU2lnbW9pZGApLlxuICAgKlxuICAgKiBJZiBgbnVsbGAsIG5vIGFjdGl2YXRpb24gaXMgYXBwbGllZC5cbiAgICovXG4gIHJlY3VycmVudEFjdGl2YXRpb24/OiBBY3RpdmF0aW9uSWRlbnRpZmllcjtcblxuICAvKipcbiAgICogSW1wbGVtZW50YXRpb24gbW9kZSwgZWl0aGVyIDEgb3IgMi5cbiAgICpcbiAgICogTW9kZSAxIHdpbGwgc3RydWN0dXJlIGl0cyBvcGVyYXRpb25zIGFzIGEgbGFyZ2VyIG51bWJlciBvZlxuICAgKiAgIHNtYWxsZXIgZG90IHByb2R1Y3RzIGFuZCBhZGRpdGlvbnMuXG4gICAqXG4gICAqIE1vZGUgMiB3aWxsIGJhdGNoIHRoZW0gaW50byBmZXdlciwgbGFyZ2VyIG9wZXJhdGlvbnMuIFRoZXNlIG1vZGVzIHdpbGxcbiAgICogaGF2ZSBkaWZmZXJlbnQgcGVyZm9ybWFuY2UgcHJvZmlsZXMgb24gZGlmZmVyZW50IGhhcmR3YXJlIGFuZFxuICAgKiBmb3IgZGlmZmVyZW50IGFwcGxpY2F0aW9ucy5cbiAgICpcbiAgICogTm90ZTogRm9yIHN1cGVyaW9yIHBlcmZvcm1hbmNlLCBUZW5zb3JGbG93LmpzIGFsd2F5cyB1c2VzIGltcGxlbWVudGF0aW9uXG4gICAqIDIsIHJlZ2FyZGxlc3Mgb2YgdGhlIGFjdHVhbCB2YWx1ZSBvZiB0aGlzIGNvbmZpZ3VyYXRpb24gZmllbGQuXG4gICAqL1xuICBpbXBsZW1lbnRhdGlvbj86IG51bWJlcjtcblxuICAvKipcbiAgICogR1JVIGNvbnZlbnRpb24gKHdoZXRoZXIgdG8gYXBwbHkgcmVzZXQgZ2F0ZSBhZnRlciBvciBiZWZvcmUgbWF0cml4XG4gICAqIG11bHRpcGxpY2F0aW9uKS4gZmFsc2UgPSBcImJlZm9yZVwiLCB0cnVlID0gXCJhZnRlclwiIChvbmx5IGZhbHNlIGlzXG4gICAqIHN1cHBvcnRlZCkuXG4gICAqL1xuICByZXNldEFmdGVyPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIEdSVUNlbGwgZXh0ZW5kcyBSTk5DZWxsIHtcbiAgLyoqIEBub2NvbGxhcHNlICovXG4gIHN0YXRpYyBjbGFzc05hbWUgPSAnR1JVQ2VsbCc7XG4gIHJlYWRvbmx5IHVuaXRzOiBudW1iZXI7XG4gIHJlYWRvbmx5IGFjdGl2YXRpb246IEFjdGl2YXRpb247XG4gIHJlYWRvbmx5IHJlY3VycmVudEFjdGl2YXRpb246IEFjdGl2YXRpb247XG4gIHJlYWRvbmx5IHVzZUJpYXM6IGJvb2xlYW47XG5cbiAgcmVhZG9ubHkga2VybmVsSW5pdGlhbGl6ZXI6IEluaXRpYWxpemVyO1xuICByZWFkb25seSByZWN1cnJlbnRJbml0aWFsaXplcjogSW5pdGlhbGl6ZXI7XG4gIHJlYWRvbmx5IGJpYXNJbml0aWFsaXplcjogSW5pdGlhbGl6ZXI7XG5cbiAgcmVhZG9ubHkga2VybmVsUmVndWxhcml6ZXI6IFJlZ3VsYXJpemVyO1xuICByZWFkb25seSByZWN1cnJlbnRSZWd1bGFyaXplcjogUmVndWxhcml6ZXI7XG4gIHJlYWRvbmx5IGJpYXNSZWd1bGFyaXplcjogUmVndWxhcml6ZXI7XG5cbiAgcmVhZG9ubHkga2VybmVsQ29uc3RyYWludDogQ29uc3RyYWludDtcbiAgcmVhZG9ubHkgcmVjdXJyZW50Q29uc3RyYWludDogQ29uc3RyYWludDtcbiAgcmVhZG9ubHkgYmlhc0NvbnN0cmFpbnQ6IENvbnN0cmFpbnQ7XG5cbiAgcmVhZG9ubHkgZHJvcG91dDogbnVtYmVyO1xuICByZWFkb25seSByZWN1cnJlbnREcm9wb3V0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGRyb3BvdXRGdW5jOiBGdW5jdGlvbjtcblxuICByZWFkb25seSBzdGF0ZVNpemU6IG51bWJlcjtcbiAgcmVhZG9ubHkgaW1wbGVtZW50YXRpb246IG51bWJlcjtcblxuICByZWFkb25seSBERUZBVUxUX0FDVElWQVRJT04gPSAndGFuaCc7XG4gIHJlYWRvbmx5IERFRkFVTFRfUkVDVVJSRU5UX0FDVElWQVRJT046IEFjdGl2YXRpb25JZGVudGlmaWVyID0gJ2hhcmRTaWdtb2lkJztcblxuICByZWFkb25seSBERUZBVUxUX0tFUk5FTF9JTklUSUFMSVpFUiA9ICdnbG9yb3ROb3JtYWwnO1xuICByZWFkb25seSBERUZBVUxUX1JFQ1VSUkVOVF9JTklUSUFMSVpFUiA9ICdvcnRob2dvbmFsJztcbiAgcmVhZG9ubHkgREVGQVVMVF9CSUFTX0lOSVRJQUxJWkVSOiBJbml0aWFsaXplcklkZW50aWZpZXIgPSAnemVyb3MnO1xuXG4gIGtlcm5lbDogTGF5ZXJWYXJpYWJsZTtcbiAgcmVjdXJyZW50S2VybmVsOiBMYXllclZhcmlhYmxlO1xuICBiaWFzOiBMYXllclZhcmlhYmxlO1xuXG4gIGNvbnN0cnVjdG9yKGFyZ3M6IEdSVUNlbGxMYXllckFyZ3MpIHtcbiAgICBzdXBlcihhcmdzKTtcbiAgICBpZiAoYXJncy5yZXNldEFmdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihcbiAgICAgICAgICBgR1JVQ2VsbCBkb2VzIG5vdCBzdXBwb3J0IHJlc2V0X2FmdGVyIHBhcmFtZXRlciBzZXQgdG8gdHJ1ZS5gKTtcbiAgICB9XG4gICAgdGhpcy51bml0cyA9IGFyZ3MudW5pdHM7XG4gICAgYXNzZXJ0UG9zaXRpdmVJbnRlZ2VyKHRoaXMudW5pdHMsICd1bml0cycpO1xuICAgIHRoaXMuYWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb24oXG4gICAgICAgIGFyZ3MuYWN0aXZhdGlvbiA9PT0gdW5kZWZpbmVkID8gdGhpcy5ERUZBVUxUX0FDVElWQVRJT04gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MuYWN0aXZhdGlvbik7XG4gICAgdGhpcy5yZWN1cnJlbnRBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvbihcbiAgICAgICAgYXJncy5yZWN1cnJlbnRBY3RpdmF0aW9uID09PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgdGhpcy5ERUZBVUxUX1JFQ1VSUkVOVF9BQ1RJVkFUSU9OIDpcbiAgICAgICAgICAgIGFyZ3MucmVjdXJyZW50QWN0aXZhdGlvbik7XG4gICAgdGhpcy51c2VCaWFzID0gYXJncy51c2VCaWFzID09IG51bGwgPyB0cnVlIDogYXJncy51c2VCaWFzO1xuXG4gICAgdGhpcy5rZXJuZWxJbml0aWFsaXplciA9IGdldEluaXRpYWxpemVyKFxuICAgICAgICBhcmdzLmtlcm5lbEluaXRpYWxpemVyIHx8IHRoaXMuREVGQVVMVF9LRVJORUxfSU5JVElBTElaRVIpO1xuICAgIHRoaXMucmVjdXJyZW50SW5pdGlhbGl6ZXIgPSBnZXRJbml0aWFsaXplcihcbiAgICAgICAgYXJncy5yZWN1cnJlbnRJbml0aWFsaXplciB8fCB0aGlzLkRFRkFVTFRfUkVDVVJSRU5UX0lOSVRJQUxJWkVSKTtcblxuICAgIHRoaXMuYmlhc0luaXRpYWxpemVyID1cbiAgICAgICAgZ2V0SW5pdGlhbGl6ZXIoYXJncy5iaWFzSW5pdGlhbGl6ZXIgfHwgdGhpcy5ERUZBVUxUX0JJQVNfSU5JVElBTElaRVIpO1xuXG4gICAgdGhpcy5rZXJuZWxSZWd1bGFyaXplciA9IGdldFJlZ3VsYXJpemVyKGFyZ3Mua2VybmVsUmVndWxhcml6ZXIpO1xuICAgIHRoaXMucmVjdXJyZW50UmVndWxhcml6ZXIgPSBnZXRSZWd1bGFyaXplcihhcmdzLnJlY3VycmVudFJlZ3VsYXJpemVyKTtcbiAgICB0aGlzLmJpYXNSZWd1bGFyaXplciA9IGdldFJlZ3VsYXJpemVyKGFyZ3MuYmlhc1JlZ3VsYXJpemVyKTtcblxuICAgIHRoaXMua2VybmVsQ29uc3RyYWludCA9IGdldENvbnN0cmFpbnQoYXJncy5rZXJuZWxDb25zdHJhaW50KTtcbiAgICB0aGlzLnJlY3VycmVudENvbnN0cmFpbnQgPSBnZXRDb25zdHJhaW50KGFyZ3MucmVjdXJyZW50Q29uc3RyYWludCk7XG4gICAgdGhpcy5iaWFzQ29uc3RyYWludCA9IGdldENvbnN0cmFpbnQoYXJncy5iaWFzQ29uc3RyYWludCk7XG5cbiAgICB0aGlzLmRyb3BvdXQgPSBtYXRoX3V0aWxzLm1pbihcbiAgICAgICAgWzEsIG1hdGhfdXRpbHMubWF4KFswLCBhcmdzLmRyb3BvdXQgPT0gbnVsbCA/IDAgOiBhcmdzLmRyb3BvdXRdKV0pO1xuICAgIHRoaXMucmVjdXJyZW50RHJvcG91dCA9IG1hdGhfdXRpbHMubWluKFtcbiAgICAgIDEsXG4gICAgICBtYXRoX3V0aWxzLm1heChcbiAgICAgICAgICBbMCwgYXJncy5yZWN1cnJlbnREcm9wb3V0ID09IG51bGwgPyAwIDogYXJncy5yZWN1cnJlbnREcm9wb3V0XSlcbiAgICBdKTtcbiAgICB0aGlzLmRyb3BvdXRGdW5jID0gYXJncy5kcm9wb3V0RnVuYztcbiAgICB0aGlzLmltcGxlbWVudGF0aW9uID0gYXJncy5pbXBsZW1lbnRhdGlvbjtcbiAgICB0aGlzLnN0YXRlU2l6ZSA9IHRoaXMudW5pdHM7XG4gICAgdGhpcy5kcm9wb3V0TWFzayA9IG51bGw7XG4gICAgdGhpcy5yZWN1cnJlbnREcm9wb3V0TWFzayA9IG51bGw7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgYnVpbGQoaW5wdXRTaGFwZTogU2hhcGV8U2hhcGVbXSk6IHZvaWQge1xuICAgIGlucHV0U2hhcGUgPSBnZXRFeGFjdGx5T25lU2hhcGUoaW5wdXRTaGFwZSk7XG4gICAgY29uc3QgaW5wdXREaW0gPSBpbnB1dFNoYXBlW2lucHV0U2hhcGUubGVuZ3RoIC0gMV07XG4gICAgdGhpcy5rZXJuZWwgPSB0aGlzLmFkZFdlaWdodChcbiAgICAgICAgJ2tlcm5lbCcsIFtpbnB1dERpbSwgdGhpcy51bml0cyAqIDNdLCBudWxsLCB0aGlzLmtlcm5lbEluaXRpYWxpemVyLFxuICAgICAgICB0aGlzLmtlcm5lbFJlZ3VsYXJpemVyLCB0cnVlLCB0aGlzLmtlcm5lbENvbnN0cmFpbnQpO1xuICAgIHRoaXMucmVjdXJyZW50S2VybmVsID0gdGhpcy5hZGRXZWlnaHQoXG4gICAgICAgICdyZWN1cnJlbnRfa2VybmVsJywgW3RoaXMudW5pdHMsIHRoaXMudW5pdHMgKiAzXSwgbnVsbCxcbiAgICAgICAgdGhpcy5yZWN1cnJlbnRJbml0aWFsaXplciwgdGhpcy5yZWN1cnJlbnRSZWd1bGFyaXplciwgdHJ1ZSxcbiAgICAgICAgdGhpcy5yZWN1cnJlbnRDb25zdHJhaW50KTtcbiAgICBpZiAodGhpcy51c2VCaWFzKSB7XG4gICAgICB0aGlzLmJpYXMgPSB0aGlzLmFkZFdlaWdodChcbiAgICAgICAgICAnYmlhcycsIFt0aGlzLnVuaXRzICogM10sIG51bGwsIHRoaXMuYmlhc0luaXRpYWxpemVyLFxuICAgICAgICAgIHRoaXMuYmlhc1JlZ3VsYXJpemVyLCB0cnVlLCB0aGlzLmJpYXNDb25zdHJhaW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5iaWFzID0gbnVsbDtcbiAgICB9XG4gICAgLy8gUG9ydGluZyBOb3RlczogVW5saWtlIHRoZSBQeUtlcmFzIGltcGxlbWVudGF0aW9uLCB3ZSBwZXJmb3JtIHNsaWNpbmdcbiAgICAvLyAgIG9mIHRoZSB3ZWlnaHRzIGFuZCBiaWFzIGluIHRoZSBjYWxsKCkgbWV0aG9kLCBhdCBleGVjdXRpb24gdGltZS5cbiAgICB0aGlzLmJ1aWx0ID0gdHJ1ZTtcbiAgfVxuXG4gIG92ZXJyaWRlIGNhbGwoaW5wdXRzOiBUZW5zb3J8VGVuc29yW10sIGt3YXJnczogS3dhcmdzKTogVGVuc29yfFRlbnNvcltdIHtcbiAgICByZXR1cm4gdGlkeSgoKSA9PiB7XG4gICAgICBpbnB1dHMgPSBpbnB1dHMgYXMgVGVuc29yW107XG4gICAgICBpZiAoaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgICAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihcbiAgICAgICAgICAgIGBHUlVDZWxsIGV4cGVjdHMgMiBpbnB1dCBUZW5zb3JzIChpbnB1dHMsIGgsIGMpLCBnb3QgYCArXG4gICAgICAgICAgICBgJHtpbnB1dHMubGVuZ3RofS5gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdHJhaW5pbmcgPSBrd2FyZ3NbJ3RyYWluaW5nJ10gPT0gbnVsbCA/IGZhbHNlIDoga3dhcmdzWyd0cmFpbmluZyddO1xuICAgICAgbGV0IGhUTWludXMxID0gaW5wdXRzWzFdOyAgLy8gUHJldmlvdXMgbWVtb3J5IHN0YXRlLlxuICAgICAgaW5wdXRzID0gaW5wdXRzWzBdO1xuXG4gICAgICAvLyBOb3RlOiBGb3Igc3VwZXJpb3IgcGVyZm9ybWFuY2UsIFRlbnNvckZsb3cuanMgYWx3YXlzIHVzZXNcbiAgICAgIC8vIGltcGxlbWVudGF0aW9uIDIsIHJlZ2FyZGxlc3Mgb2YgdGhlIGFjdHVhbCB2YWx1ZSBvZlxuICAgICAgLy8gY29uZmlnLmltcGxlbWVudGF0aW9uLlxuICAgICAgaWYgKDAgPCB0aGlzLmRyb3BvdXQgJiYgdGhpcy5kcm9wb3V0IDwgMSAmJiB0aGlzLmRyb3BvdXRNYXNrID09IG51bGwpIHtcbiAgICAgICAgdGhpcy5kcm9wb3V0TWFzayA9IGdlbmVyYXRlRHJvcG91dE1hc2soe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVzOiAoKSA9PiB0ZmMub25lc0xpa2UoaW5wdXRzIGFzIFRlbnNvciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhdGU6IHRoaXMuZHJvcG91dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiAzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wb3V0RnVuYzogdGhpcy5kcm9wb3V0RnVuYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pIGFzIFRlbnNvcltdO1xuICAgICAgfVxuICAgICAgaWYgKDAgPCB0aGlzLnJlY3VycmVudERyb3BvdXQgJiYgdGhpcy5yZWN1cnJlbnREcm9wb3V0IDwgMSAmJlxuICAgICAgICAgIHRoaXMucmVjdXJyZW50RHJvcG91dE1hc2sgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrID0gZ2VuZXJhdGVEcm9wb3V0TWFzayh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZXM6ICgpID0+IHRmYy5vbmVzTGlrZShoVE1pbnVzMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhdGU6IHRoaXMucmVjdXJyZW50RHJvcG91dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiAzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wb3V0RnVuYzogdGhpcy5kcm9wb3V0RnVuYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pIGFzIFRlbnNvcltdO1xuICAgICAgfVxuICAgICAgY29uc3QgZHBNYXNrID0gdGhpcy5kcm9wb3V0TWFzayBhcyBbVGVuc29yLCBUZW5zb3IsIFRlbnNvcl07XG4gICAgICBjb25zdCByZWNEcE1hc2sgPSB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrIGFzIFtUZW5zb3IsIFRlbnNvciwgVGVuc29yXTtcbiAgICAgIGxldCB6OiBUZW5zb3I7XG4gICAgICBsZXQgcjogVGVuc29yO1xuICAgICAgbGV0IGhoOiBUZW5zb3I7XG5cbiAgICAgIGlmICgwIDwgdGhpcy5kcm9wb3V0ICYmIHRoaXMuZHJvcG91dCA8IDEpIHtcbiAgICAgICAgaW5wdXRzID0gdGZjLm11bChpbnB1dHMsIGRwTWFza1swXSk7XG4gICAgICB9XG4gICAgICBsZXQgbWF0cml4WCA9IEsuZG90KGlucHV0cywgdGhpcy5rZXJuZWwucmVhZCgpKTtcbiAgICAgIGlmICh0aGlzLnVzZUJpYXMpIHtcbiAgICAgICAgbWF0cml4WCA9IEsuYmlhc0FkZChtYXRyaXhYLCB0aGlzLmJpYXMucmVhZCgpKTtcbiAgICAgIH1cbiAgICAgIGlmICgwIDwgdGhpcy5yZWN1cnJlbnREcm9wb3V0ICYmIHRoaXMucmVjdXJyZW50RHJvcG91dCA8IDEpIHtcbiAgICAgICAgaFRNaW51czEgPSB0ZmMubXVsKGhUTWludXMxLCByZWNEcE1hc2tbMF0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZWN1cnJlbnRLZXJuZWxWYWx1ZSA9IHRoaXMucmVjdXJyZW50S2VybmVsLnJlYWQoKTtcbiAgICAgIGNvbnN0IFtyazEsIHJrMl0gPSB0ZmMuc3BsaXQoXG4gICAgICAgICAgcmVjdXJyZW50S2VybmVsVmFsdWUsIFsyICogdGhpcy51bml0cywgdGhpcy51bml0c10sXG4gICAgICAgICAgcmVjdXJyZW50S2VybmVsVmFsdWUucmFuayAtIDEpO1xuICAgICAgY29uc3QgbWF0cml4SW5uZXIgPSBLLmRvdChoVE1pbnVzMSwgcmsxKTtcblxuICAgICAgY29uc3QgW3haLCB4UiwgeEhdID0gdGZjLnNwbGl0KG1hdHJpeFgsIDMsIG1hdHJpeFgucmFuayAtIDEpO1xuICAgICAgY29uc3QgW3JlY3VycmVudFosIHJlY3VycmVudFJdID1cbiAgICAgICAgICB0ZmMuc3BsaXQobWF0cml4SW5uZXIsIDIsIG1hdHJpeElubmVyLnJhbmsgLSAxKTtcbiAgICAgIHogPSB0aGlzLnJlY3VycmVudEFjdGl2YXRpb24uYXBwbHkodGZjLmFkZCh4WiwgcmVjdXJyZW50WikpO1xuICAgICAgciA9IHRoaXMucmVjdXJyZW50QWN0aXZhdGlvbi5hcHBseSh0ZmMuYWRkKHhSLCByZWN1cnJlbnRSKSk7XG5cbiAgICAgIGNvbnN0IHJlY3VycmVudEggPSBLLmRvdCh0ZmMubXVsKHIsIGhUTWludXMxKSwgcmsyKTtcbiAgICAgIGhoID0gdGhpcy5hY3RpdmF0aW9uLmFwcGx5KHRmYy5hZGQoeEgsIHJlY3VycmVudEgpKTtcblxuICAgICAgY29uc3QgaCA9XG4gICAgICAgICAgdGZjLmFkZCh0ZmMubXVsKHosIGhUTWludXMxKSwgdGZjLm11bCh0ZmMuYWRkKDEsIHRmYy5uZWcoeikpLCBoaCkpO1xuICAgICAgLy8gVE9ETyhjYWlzKTogQWRkIHVzZV9sZWFybmluZ19waGFzZSBmbGFnIHByb3Blcmx5LlxuICAgICAgcmV0dXJuIFtoLCBoXTtcbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGdldENvbmZpZygpOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3Qge1xuICAgIGNvbnN0IGJhc2VDb25maWcgPSBzdXBlci5nZXRDb25maWcoKTtcblxuICAgIGNvbnN0IGNvbmZpZzogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0ID0ge1xuICAgICAgdW5pdHM6IHRoaXMudW5pdHMsXG4gICAgICBhY3RpdmF0aW9uOiBzZXJpYWxpemVBY3RpdmF0aW9uKHRoaXMuYWN0aXZhdGlvbiksXG4gICAgICByZWN1cnJlbnRBY3RpdmF0aW9uOiBzZXJpYWxpemVBY3RpdmF0aW9uKHRoaXMucmVjdXJyZW50QWN0aXZhdGlvbiksXG4gICAgICB1c2VCaWFzOiB0aGlzLnVzZUJpYXMsXG4gICAgICBrZXJuZWxJbml0aWFsaXplcjogc2VyaWFsaXplSW5pdGlhbGl6ZXIodGhpcy5rZXJuZWxJbml0aWFsaXplciksXG4gICAgICByZWN1cnJlbnRJbml0aWFsaXplcjogc2VyaWFsaXplSW5pdGlhbGl6ZXIodGhpcy5yZWN1cnJlbnRJbml0aWFsaXplciksXG4gICAgICBiaWFzSW5pdGlhbGl6ZXI6IHNlcmlhbGl6ZUluaXRpYWxpemVyKHRoaXMuYmlhc0luaXRpYWxpemVyKSxcbiAgICAgIGtlcm5lbFJlZ3VsYXJpemVyOiBzZXJpYWxpemVSZWd1bGFyaXplcih0aGlzLmtlcm5lbFJlZ3VsYXJpemVyKSxcbiAgICAgIHJlY3VycmVudFJlZ3VsYXJpemVyOiBzZXJpYWxpemVSZWd1bGFyaXplcih0aGlzLnJlY3VycmVudFJlZ3VsYXJpemVyKSxcbiAgICAgIGJpYXNSZWd1bGFyaXplcjogc2VyaWFsaXplUmVndWxhcml6ZXIodGhpcy5iaWFzUmVndWxhcml6ZXIpLFxuICAgICAgYWN0aXZpdHlSZWd1bGFyaXplcjogc2VyaWFsaXplUmVndWxhcml6ZXIodGhpcy5hY3Rpdml0eVJlZ3VsYXJpemVyKSxcbiAgICAgIGtlcm5lbENvbnN0cmFpbnQ6IHNlcmlhbGl6ZUNvbnN0cmFpbnQodGhpcy5rZXJuZWxDb25zdHJhaW50KSxcbiAgICAgIHJlY3VycmVudENvbnN0cmFpbnQ6IHNlcmlhbGl6ZUNvbnN0cmFpbnQodGhpcy5yZWN1cnJlbnRDb25zdHJhaW50KSxcbiAgICAgIGJpYXNDb25zdHJhaW50OiBzZXJpYWxpemVDb25zdHJhaW50KHRoaXMuYmlhc0NvbnN0cmFpbnQpLFxuICAgICAgZHJvcG91dDogdGhpcy5kcm9wb3V0LFxuICAgICAgcmVjdXJyZW50RHJvcG91dDogdGhpcy5yZWN1cnJlbnREcm9wb3V0LFxuICAgICAgaW1wbGVtZW50YXRpb246IHRoaXMuaW1wbGVtZW50YXRpb24sXG4gICAgICByZXNldEFmdGVyOiBmYWxzZVxuICAgIH07XG5cbiAgICByZXR1cm4gey4uLmJhc2VDb25maWcsIC4uLmNvbmZpZ307XG4gIH1cbn1cbnNlcmlhbGl6YXRpb24ucmVnaXN0ZXJDbGFzcyhHUlVDZWxsKTtcblxuLy8gUG9ydGluZyBOb3RlOiBTaW5jZSB0aGlzIGlzIGEgc3VwZXJzZXQgb2YgU2ltcGxlUk5OTGF5ZXJDb25maWcsIHdlIGluaGVyaXRcbi8vICAgZnJvbSB0aGF0IGludGVyZmFjZSBpbnN0ZWFkIG9mIHJlcGVhdGluZyB0aGUgZmllbGRzIGhlcmUuXG5leHBvcnQgZGVjbGFyZSBpbnRlcmZhY2UgR1JVTGF5ZXJBcmdzIGV4dGVuZHMgU2ltcGxlUk5OTGF5ZXJBcmdzIHtcbiAgLyoqXG4gICAqIEFjdGl2YXRpb24gZnVuY3Rpb24gdG8gdXNlIGZvciB0aGUgcmVjdXJyZW50IHN0ZXAuXG4gICAqXG4gICAqIERlZmF1bHRzIHRvIGhhcmQgc2lnbW9pZCAoYGhhcmRTaWdtb2lkYCkuXG4gICAqXG4gICAqIElmIGBudWxsYCwgbm8gYWN0aXZhdGlvbiBpcyBhcHBsaWVkLlxuICAgKi9cbiAgcmVjdXJyZW50QWN0aXZhdGlvbj86IEFjdGl2YXRpb25JZGVudGlmaWVyO1xuXG4gIC8qKlxuICAgKiBJbXBsZW1lbnRhdGlvbiBtb2RlLCBlaXRoZXIgMSBvciAyLlxuICAgKlxuICAgKiBNb2RlIDEgd2lsbCBzdHJ1Y3R1cmUgaXRzIG9wZXJhdGlvbnMgYXMgYSBsYXJnZXIgbnVtYmVyIG9mXG4gICAqIHNtYWxsZXIgZG90IHByb2R1Y3RzIGFuZCBhZGRpdGlvbnMuXG4gICAqXG4gICAqIE1vZGUgMiB3aWxsIGJhdGNoIHRoZW0gaW50byBmZXdlciwgbGFyZ2VyIG9wZXJhdGlvbnMuIFRoZXNlIG1vZGVzIHdpbGxcbiAgICogaGF2ZSBkaWZmZXJlbnQgcGVyZm9ybWFuY2UgcHJvZmlsZXMgb24gZGlmZmVyZW50IGhhcmR3YXJlIGFuZFxuICAgKiBmb3IgZGlmZmVyZW50IGFwcGxpY2F0aW9ucy5cbiAgICpcbiAgICogTm90ZTogRm9yIHN1cGVyaW9yIHBlcmZvcm1hbmNlLCBUZW5zb3JGbG93LmpzIGFsd2F5cyB1c2VzIGltcGxlbWVudGF0aW9uXG4gICAqIDIsIHJlZ2FyZGxlc3Mgb2YgdGhlIGFjdHVhbCB2YWx1ZSBvZiB0aGlzIGNvbmZpZ3VyYXRpb24gZmllbGQuXG4gICAqL1xuICBpbXBsZW1lbnRhdGlvbj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIEdSVSBleHRlbmRzIFJOTiB7XG4gIC8qKiBAbm9jb2xsYXBzZSAqL1xuICBzdGF0aWMgb3ZlcnJpZGUgY2xhc3NOYW1lID0gJ0dSVSc7XG4gIGNvbnN0cnVjdG9yKGFyZ3M6IEdSVUxheWVyQXJncykge1xuICAgIGlmIChhcmdzLmltcGxlbWVudGF0aW9uID09PSAwKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ2BpbXBsZW1lbnRhdGlvbj0wYCBoYXMgYmVlbiBkZXByZWNhdGVkLCBhbmQgbm93IGRlZmF1bHRzIHRvICcgK1xuICAgICAgICAgICdgaW1wbGVtZW50YXRpb249MWAuIFBsZWFzZSB1cGRhdGUgeW91ciBsYXllciBjYWxsLicpO1xuICAgIH1cbiAgICBhcmdzLmNlbGwgPSBuZXcgR1JVQ2VsbChhcmdzKTtcbiAgICBzdXBlcihhcmdzIGFzIFJOTkxheWVyQXJncyk7XG4gICAgLy8gVE9ETyhjYWlzKTogQWRkIGFjdGl2aXR5UmVndWxhcml6ZXIuXG4gIH1cblxuICBvdmVycmlkZSBjYWxsKGlucHV0czogVGVuc29yfFRlbnNvcltdLCBrd2FyZ3M6IEt3YXJncyk6IFRlbnNvcnxUZW5zb3JbXSB7XG4gICAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuY2VsbC5kcm9wb3V0TWFzayAhPSBudWxsKSB7XG4gICAgICAgIHRmYy5kaXNwb3NlKHRoaXMuY2VsbC5kcm9wb3V0TWFzayk7XG4gICAgICAgIHRoaXMuY2VsbC5kcm9wb3V0TWFzayA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5jZWxsLnJlY3VycmVudERyb3BvdXRNYXNrICE9IG51bGwpIHtcbiAgICAgICAgdGZjLmRpc3Bvc2UodGhpcy5jZWxsLnJlY3VycmVudERyb3BvdXRNYXNrKTtcbiAgICAgICAgdGhpcy5jZWxsLnJlY3VycmVudERyb3BvdXRNYXNrID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1hc2sgPSBrd2FyZ3MgPT0gbnVsbCA/IG51bGwgOiBrd2FyZ3NbJ21hc2snXTtcbiAgICAgIGNvbnN0IHRyYWluaW5nID0ga3dhcmdzID09IG51bGwgPyBudWxsIDoga3dhcmdzWyd0cmFpbmluZyddO1xuICAgICAgY29uc3QgaW5pdGlhbFN0YXRlOiBUZW5zb3JbXSA9XG4gICAgICAgICAga3dhcmdzID09IG51bGwgPyBudWxsIDoga3dhcmdzWydpbml0aWFsU3RhdGUnXTtcbiAgICAgIHJldHVybiBzdXBlci5jYWxsKGlucHV0cywge21hc2ssIHRyYWluaW5nLCBpbml0aWFsU3RhdGV9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBAbm9jb2xsYXBzZSAqL1xuICBzdGF0aWMgb3ZlcnJpZGUgZnJvbUNvbmZpZzxUIGV4dGVuZHMgc2VyaWFsaXphdGlvbi5TZXJpYWxpemFibGU+KFxuICAgICAgY2xzOiBzZXJpYWxpemF0aW9uLlNlcmlhbGl6YWJsZUNvbnN0cnVjdG9yPFQ+LFxuICAgICAgY29uZmlnOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3QpOiBUIHtcbiAgICBpZiAoY29uZmlnWydpbXBsbWVudGF0aW9uJ10gPT09IDApIHtcbiAgICAgIGNvbmZpZ1snaW1wbGVtZW50YXRpb24nXSA9IDE7XG4gICAgfVxuICAgIHJldHVybiBuZXcgY2xzKGNvbmZpZyk7XG4gIH1cbn1cbnNlcmlhbGl6YXRpb24ucmVnaXN0ZXJDbGFzcyhHUlUpO1xuXG4vLyBQb3J0aW5nIE5vdGU6IFNpbmNlIHRoaXMgaXMgYSBzdXBlcnNldCBvZiBTaW1wbGVSTk5MYXllckNvbmZpZywgd2UgZXh0ZW5kXG4vLyAgIHRoYXQgaW50ZXJmYWNlIGluc3RlYWQgb2YgcmVwZWF0aW5nIHRoZSBmaWVsZHMuXG5leHBvcnQgZGVjbGFyZSBpbnRlcmZhY2UgTFNUTUNlbGxMYXllckFyZ3MgZXh0ZW5kcyBTaW1wbGVSTk5DZWxsTGF5ZXJBcmdzIHtcbiAgLyoqXG4gICAqIEFjdGl2YXRpb24gZnVuY3Rpb24gdG8gdXNlIGZvciB0aGUgcmVjdXJyZW50IHN0ZXAuXG4gICAqXG4gICAqIERlZmF1bHRzIHRvIGhhcmQgc2lnbW9pZCAoYGhhcmRTaWdtb2lkYCkuXG4gICAqXG4gICAqIElmIGBudWxsYCwgbm8gYWN0aXZhdGlvbiBpcyBhcHBsaWVkLlxuICAgKi9cbiAgcmVjdXJyZW50QWN0aXZhdGlvbj86IEFjdGl2YXRpb25JZGVudGlmaWVyO1xuXG4gIC8qKlxuICAgKiBJZiBgdHJ1ZWAsIGFkZCAxIHRvIHRoZSBiaWFzIG9mIHRoZSBmb3JnZXQgZ2F0ZSBhdCBpbml0aWFsaXphdGlvbi5cbiAgICogU2V0dGluZyBpdCB0byBgdHJ1ZWAgd2lsbCBhbHNvIGZvcmNlIGBiaWFzSW5pdGlhbGl6ZXIgPSAnemVyb3MnYC5cbiAgICogVGhpcyBpcyByZWNvbW1lbmRlZCBpblxuICAgKiBbSm96ZWZvd2ljeiBldFxuICAgKiBhbC5dKGh0dHA6Ly93d3cuam1sci5vcmcvcHJvY2VlZGluZ3MvcGFwZXJzL3YzNy9qb3plZm93aWN6MTUucGRmKVxuICAgKi9cbiAgdW5pdEZvcmdldEJpYXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbXBsZW1lbnRhdGlvbiBtb2RlLCBlaXRoZXIgMSBvciAyLlxuICAgKlxuICAgKiBNb2RlIDEgd2lsbCBzdHJ1Y3R1cmUgaXRzIG9wZXJhdGlvbnMgYXMgYSBsYXJnZXIgbnVtYmVyIG9mXG4gICAqICAgc21hbGxlciBkb3QgcHJvZHVjdHMgYW5kIGFkZGl0aW9ucy5cbiAgICpcbiAgICogTW9kZSAyIHdpbGwgYmF0Y2ggdGhlbSBpbnRvIGZld2VyLCBsYXJnZXIgb3BlcmF0aW9ucy4gVGhlc2UgbW9kZXMgd2lsbFxuICAgKiBoYXZlIGRpZmZlcmVudCBwZXJmb3JtYW5jZSBwcm9maWxlcyBvbiBkaWZmZXJlbnQgaGFyZHdhcmUgYW5kXG4gICAqIGZvciBkaWZmZXJlbnQgYXBwbGljYXRpb25zLlxuICAgKlxuICAgKiBOb3RlOiBGb3Igc3VwZXJpb3IgcGVyZm9ybWFuY2UsIFRlbnNvckZsb3cuanMgYWx3YXlzIHVzZXMgaW1wbGVtZW50YXRpb25cbiAgICogMiwgcmVnYXJkbGVzcyBvZiB0aGUgYWN0dWFsIHZhbHVlIG9mIHRoaXMgY29uZmlndXJhdGlvbiBmaWVsZC5cbiAgICovXG4gIGltcGxlbWVudGF0aW9uPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgTFNUTUNlbGwgZXh0ZW5kcyBSTk5DZWxsIHtcbiAgLyoqIEBub2NvbGxhcHNlICovXG4gIHN0YXRpYyBjbGFzc05hbWUgPSAnTFNUTUNlbGwnO1xuICByZWFkb25seSB1bml0czogbnVtYmVyO1xuICByZWFkb25seSBhY3RpdmF0aW9uOiBBY3RpdmF0aW9uO1xuICByZWFkb25seSByZWN1cnJlbnRBY3RpdmF0aW9uOiBBY3RpdmF0aW9uO1xuICByZWFkb25seSB1c2VCaWFzOiBib29sZWFuO1xuXG4gIHJlYWRvbmx5IGtlcm5lbEluaXRpYWxpemVyOiBJbml0aWFsaXplcjtcbiAgcmVhZG9ubHkgcmVjdXJyZW50SW5pdGlhbGl6ZXI6IEluaXRpYWxpemVyO1xuICByZWFkb25seSBiaWFzSW5pdGlhbGl6ZXI6IEluaXRpYWxpemVyO1xuICByZWFkb25seSB1bml0Rm9yZ2V0QmlhczogYm9vbGVhbjtcblxuICByZWFkb25seSBrZXJuZWxDb25zdHJhaW50OiBDb25zdHJhaW50O1xuICByZWFkb25seSByZWN1cnJlbnRDb25zdHJhaW50OiBDb25zdHJhaW50O1xuICByZWFkb25seSBiaWFzQ29uc3RyYWludDogQ29uc3RyYWludDtcblxuICByZWFkb25seSBrZXJuZWxSZWd1bGFyaXplcjogUmVndWxhcml6ZXI7XG4gIHJlYWRvbmx5IHJlY3VycmVudFJlZ3VsYXJpemVyOiBSZWd1bGFyaXplcjtcbiAgcmVhZG9ubHkgYmlhc1JlZ3VsYXJpemVyOiBSZWd1bGFyaXplcjtcblxuICByZWFkb25seSBkcm9wb3V0OiBudW1iZXI7XG4gIHJlYWRvbmx5IHJlY3VycmVudERyb3BvdXQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgZHJvcG91dEZ1bmM6IEZ1bmN0aW9uO1xuXG4gIHJlYWRvbmx5IHN0YXRlU2l6ZTogbnVtYmVyW107XG4gIHJlYWRvbmx5IGltcGxlbWVudGF0aW9uOiBudW1iZXI7XG5cbiAgcmVhZG9ubHkgREVGQVVMVF9BQ1RJVkFUSU9OID0gJ3RhbmgnO1xuICByZWFkb25seSBERUZBVUxUX1JFQ1VSUkVOVF9BQ1RJVkFUSU9OID0gJ2hhcmRTaWdtb2lkJztcbiAgcmVhZG9ubHkgREVGQVVMVF9LRVJORUxfSU5JVElBTElaRVIgPSAnZ2xvcm90Tm9ybWFsJztcbiAgcmVhZG9ubHkgREVGQVVMVF9SRUNVUlJFTlRfSU5JVElBTElaRVIgPSAnb3J0aG9nb25hbCc7XG5cbiAgcmVhZG9ubHkgREVGQVVMVF9CSUFTX0lOSVRJQUxJWkVSID0gJ3plcm9zJztcblxuICBrZXJuZWw6IExheWVyVmFyaWFibGU7XG4gIHJlY3VycmVudEtlcm5lbDogTGF5ZXJWYXJpYWJsZTtcbiAgYmlhczogTGF5ZXJWYXJpYWJsZTtcblxuICBjb25zdHJ1Y3RvcihhcmdzOiBMU1RNQ2VsbExheWVyQXJncykge1xuICAgIHN1cGVyKGFyZ3MpO1xuXG4gICAgdGhpcy51bml0cyA9IGFyZ3MudW5pdHM7XG4gICAgYXNzZXJ0UG9zaXRpdmVJbnRlZ2VyKHRoaXMudW5pdHMsICd1bml0cycpO1xuICAgIHRoaXMuYWN0aXZhdGlvbiA9IGdldEFjdGl2YXRpb24oXG4gICAgICAgIGFyZ3MuYWN0aXZhdGlvbiA9PT0gdW5kZWZpbmVkID8gdGhpcy5ERUZBVUxUX0FDVElWQVRJT04gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MuYWN0aXZhdGlvbik7XG4gICAgdGhpcy5yZWN1cnJlbnRBY3RpdmF0aW9uID0gZ2V0QWN0aXZhdGlvbihcbiAgICAgICAgYXJncy5yZWN1cnJlbnRBY3RpdmF0aW9uID09PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgdGhpcy5ERUZBVUxUX1JFQ1VSUkVOVF9BQ1RJVkFUSU9OIDpcbiAgICAgICAgICAgIGFyZ3MucmVjdXJyZW50QWN0aXZhdGlvbik7XG4gICAgdGhpcy51c2VCaWFzID0gYXJncy51c2VCaWFzID09IG51bGwgPyB0cnVlIDogYXJncy51c2VCaWFzO1xuXG4gICAgdGhpcy5rZXJuZWxJbml0aWFsaXplciA9IGdldEluaXRpYWxpemVyKFxuICAgICAgICBhcmdzLmtlcm5lbEluaXRpYWxpemVyIHx8IHRoaXMuREVGQVVMVF9LRVJORUxfSU5JVElBTElaRVIpO1xuICAgIHRoaXMucmVjdXJyZW50SW5pdGlhbGl6ZXIgPSBnZXRJbml0aWFsaXplcihcbiAgICAgICAgYXJncy5yZWN1cnJlbnRJbml0aWFsaXplciB8fCB0aGlzLkRFRkFVTFRfUkVDVVJSRU5UX0lOSVRJQUxJWkVSKTtcblxuICAgIHRoaXMuYmlhc0luaXRpYWxpemVyID1cbiAgICAgICAgZ2V0SW5pdGlhbGl6ZXIoYXJncy5iaWFzSW5pdGlhbGl6ZXIgfHwgdGhpcy5ERUZBVUxUX0JJQVNfSU5JVElBTElaRVIpO1xuICAgIHRoaXMudW5pdEZvcmdldEJpYXMgPSBhcmdzLnVuaXRGb3JnZXRCaWFzO1xuXG4gICAgdGhpcy5rZXJuZWxSZWd1bGFyaXplciA9IGdldFJlZ3VsYXJpemVyKGFyZ3Mua2VybmVsUmVndWxhcml6ZXIpO1xuICAgIHRoaXMucmVjdXJyZW50UmVndWxhcml6ZXIgPSBnZXRSZWd1bGFyaXplcihhcmdzLnJlY3VycmVudFJlZ3VsYXJpemVyKTtcbiAgICB0aGlzLmJpYXNSZWd1bGFyaXplciA9IGdldFJlZ3VsYXJpemVyKGFyZ3MuYmlhc1JlZ3VsYXJpemVyKTtcblxuICAgIHRoaXMua2VybmVsQ29uc3RyYWludCA9IGdldENvbnN0cmFpbnQoYXJncy5rZXJuZWxDb25zdHJhaW50KTtcbiAgICB0aGlzLnJlY3VycmVudENvbnN0cmFpbnQgPSBnZXRDb25zdHJhaW50KGFyZ3MucmVjdXJyZW50Q29uc3RyYWludCk7XG4gICAgdGhpcy5iaWFzQ29uc3RyYWludCA9IGdldENvbnN0cmFpbnQoYXJncy5iaWFzQ29uc3RyYWludCk7XG5cbiAgICB0aGlzLmRyb3BvdXQgPSBtYXRoX3V0aWxzLm1pbihcbiAgICAgICAgWzEsIG1hdGhfdXRpbHMubWF4KFswLCBhcmdzLmRyb3BvdXQgPT0gbnVsbCA/IDAgOiBhcmdzLmRyb3BvdXRdKV0pO1xuICAgIHRoaXMucmVjdXJyZW50RHJvcG91dCA9IG1hdGhfdXRpbHMubWluKFtcbiAgICAgIDEsXG4gICAgICBtYXRoX3V0aWxzLm1heChcbiAgICAgICAgICBbMCwgYXJncy5yZWN1cnJlbnREcm9wb3V0ID09IG51bGwgPyAwIDogYXJncy5yZWN1cnJlbnREcm9wb3V0XSlcbiAgICBdKTtcbiAgICB0aGlzLmRyb3BvdXRGdW5jID0gYXJncy5kcm9wb3V0RnVuYztcbiAgICB0aGlzLmltcGxlbWVudGF0aW9uID0gYXJncy5pbXBsZW1lbnRhdGlvbjtcbiAgICB0aGlzLnN0YXRlU2l6ZSA9IFt0aGlzLnVuaXRzLCB0aGlzLnVuaXRzXTtcbiAgICB0aGlzLmRyb3BvdXRNYXNrID0gbnVsbDtcbiAgICB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrID0gbnVsbDtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBidWlsZChpbnB1dFNoYXBlOiBTaGFwZXxTaGFwZVtdKTogdm9pZCB7XG4gICAgaW5wdXRTaGFwZSA9IGdldEV4YWN0bHlPbmVTaGFwZShpbnB1dFNoYXBlKTtcbiAgICBjb25zdCBpbnB1dERpbSA9IGlucHV0U2hhcGVbaW5wdXRTaGFwZS5sZW5ndGggLSAxXTtcbiAgICB0aGlzLmtlcm5lbCA9IHRoaXMuYWRkV2VpZ2h0KFxuICAgICAgICAna2VybmVsJywgW2lucHV0RGltLCB0aGlzLnVuaXRzICogNF0sIG51bGwsIHRoaXMua2VybmVsSW5pdGlhbGl6ZXIsXG4gICAgICAgIHRoaXMua2VybmVsUmVndWxhcml6ZXIsIHRydWUsIHRoaXMua2VybmVsQ29uc3RyYWludCk7XG4gICAgdGhpcy5yZWN1cnJlbnRLZXJuZWwgPSB0aGlzLmFkZFdlaWdodChcbiAgICAgICAgJ3JlY3VycmVudF9rZXJuZWwnLCBbdGhpcy51bml0cywgdGhpcy51bml0cyAqIDRdLCBudWxsLFxuICAgICAgICB0aGlzLnJlY3VycmVudEluaXRpYWxpemVyLCB0aGlzLnJlY3VycmVudFJlZ3VsYXJpemVyLCB0cnVlLFxuICAgICAgICB0aGlzLnJlY3VycmVudENvbnN0cmFpbnQpO1xuICAgIGxldCBiaWFzSW5pdGlhbGl6ZXI6IEluaXRpYWxpemVyO1xuICAgIGlmICh0aGlzLnVzZUJpYXMpIHtcbiAgICAgIGlmICh0aGlzLnVuaXRGb3JnZXRCaWFzKSB7XG4gICAgICAgIGNvbnN0IGNhcHR1cmVkQmlhc0luaXQgPSB0aGlzLmJpYXNJbml0aWFsaXplcjtcbiAgICAgICAgY29uc3QgY2FwdHVyZWRVbml0cyA9IHRoaXMudW5pdHM7XG4gICAgICAgIGJpYXNJbml0aWFsaXplciA9IG5ldyAoY2xhc3MgQ3VzdG9tSW5pdCBleHRlbmRzIEluaXRpYWxpemVyIHtcbiAgICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgICBzdGF0aWMgY2xhc3NOYW1lID0gJ0N1c3RvbUluaXQnO1xuXG4gICAgICAgICAgYXBwbHkoc2hhcGU6IFNoYXBlLCBkdHlwZT86IERhdGFUeXBlKTogVGVuc29yIHtcbiAgICAgICAgICAgIC8vIFRPRE8oY2Fpcyk6IE1vcmUgaW5mb3JtYXRpdmUgdmFyaWFibGUgbmFtZXM/XG4gICAgICAgICAgICBjb25zdCBiSSA9IGNhcHR1cmVkQmlhc0luaXQuYXBwbHkoW2NhcHR1cmVkVW5pdHNdKTtcbiAgICAgICAgICAgIGNvbnN0IGJGID0gKG5ldyBPbmVzKCkpLmFwcGx5KFtjYXB0dXJlZFVuaXRzXSk7XG4gICAgICAgICAgICBjb25zdCBiQ0FuZEggPSBjYXB0dXJlZEJpYXNJbml0LmFwcGx5KFtjYXB0dXJlZFVuaXRzICogMl0pO1xuICAgICAgICAgICAgcmV0dXJuIEsuY29uY2F0QWxvbmdGaXJzdEF4aXMoXG4gICAgICAgICAgICAgICAgSy5jb25jYXRBbG9uZ0ZpcnN0QXhpcyhiSSwgYkYpLCBiQ0FuZEgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJpYXNJbml0aWFsaXplciA9IHRoaXMuYmlhc0luaXRpYWxpemVyO1xuICAgICAgfVxuICAgICAgdGhpcy5iaWFzID0gdGhpcy5hZGRXZWlnaHQoXG4gICAgICAgICAgJ2JpYXMnLCBbdGhpcy51bml0cyAqIDRdLCBudWxsLCBiaWFzSW5pdGlhbGl6ZXIsIHRoaXMuYmlhc1JlZ3VsYXJpemVyLFxuICAgICAgICAgIHRydWUsIHRoaXMuYmlhc0NvbnN0cmFpbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmJpYXMgPSBudWxsO1xuICAgIH1cbiAgICAvLyBQb3J0aW5nIE5vdGVzOiBVbmxpa2UgdGhlIFB5S2VyYXMgaW1wbGVtZW50YXRpb24sIHdlIHBlcmZvcm0gc2xpY2luZ1xuICAgIC8vICAgb2YgdGhlIHdlaWdodHMgYW5kIGJpYXMgaW4gdGhlIGNhbGwoKSBtZXRob2QsIGF0IGV4ZWN1dGlvbiB0aW1lLlxuICAgIHRoaXMuYnVpbHQgPSB0cnVlO1xuICB9XG5cbiAgb3ZlcnJpZGUgY2FsbChpbnB1dHM6IFRlbnNvcnxUZW5zb3JbXSwga3dhcmdzOiBLd2FyZ3MpOiBUZW5zb3J8VGVuc29yW10ge1xuICAgIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICAgIGNvbnN0IHRyYWluaW5nID0ga3dhcmdzWyd0cmFpbmluZyddID09IG51bGwgPyBmYWxzZSA6IGt3YXJnc1sndHJhaW5pbmcnXTtcbiAgICAgIGlucHV0cyA9IGlucHV0cyBhcyBUZW5zb3JbXTtcbiAgICAgIGlmIChpbnB1dHMubGVuZ3RoICE9PSAzKSB7XG4gICAgICAgIHRocm93IG5ldyBWYWx1ZUVycm9yKFxuICAgICAgICAgICAgYExTVE1DZWxsIGV4cGVjdHMgMyBpbnB1dCBUZW5zb3JzIChpbnB1dHMsIGgsIGMpLCBnb3QgYCArXG4gICAgICAgICAgICBgJHtpbnB1dHMubGVuZ3RofS5gKTtcbiAgICAgIH1cbiAgICAgIGxldCBoVE1pbnVzMSA9IGlucHV0c1sxXTsgICAgLy8gUHJldmlvdXMgbWVtb3J5IHN0YXRlLlxuICAgICAgY29uc3QgY1RNaW51czEgPSBpbnB1dHNbMl07ICAvLyBQcmV2aW91cyBjYXJyeSBzdGF0ZS5cbiAgICAgIGlucHV0cyA9IGlucHV0c1swXTtcbiAgICAgIGlmICgwIDwgdGhpcy5kcm9wb3V0ICYmIHRoaXMuZHJvcG91dCA8IDEgJiYgdGhpcy5kcm9wb3V0TWFzayA9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuZHJvcG91dE1hc2sgPSBnZW5lcmF0ZURyb3BvdXRNYXNrKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25lczogKCkgPT4gdGZjLm9uZXNMaWtlKGlucHV0cyBhcyBUZW5zb3IpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXRlOiB0aGlzLmRyb3BvdXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWluaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogNCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJvcG91dEZ1bmM6IHRoaXMuZHJvcG91dEZ1bmNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pIGFzIFRlbnNvcltdO1xuICAgICAgfVxuICAgICAgaWYgKDAgPCB0aGlzLnJlY3VycmVudERyb3BvdXQgJiYgdGhpcy5yZWN1cnJlbnREcm9wb3V0IDwgMSAmJlxuICAgICAgICAgIHRoaXMucmVjdXJyZW50RHJvcG91dE1hc2sgPT0gbnVsbCkge1xuICAgICAgICB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrID0gZ2VuZXJhdGVEcm9wb3V0TWFzayh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZXM6ICgpID0+IHRmYy5vbmVzTGlrZShoVE1pbnVzMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhdGU6IHRoaXMucmVjdXJyZW50RHJvcG91dCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiA0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcm9wb3V0RnVuYzogdGhpcy5kcm9wb3V0RnVuY1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkgYXMgVGVuc29yW107XG4gICAgICB9XG4gICAgICBjb25zdCBkcE1hc2sgPSB0aGlzLmRyb3BvdXRNYXNrIGFzIFtUZW5zb3IsIFRlbnNvciwgVGVuc29yLCBUZW5zb3JdO1xuICAgICAgY29uc3QgcmVjRHBNYXNrID1cbiAgICAgICAgICB0aGlzLnJlY3VycmVudERyb3BvdXRNYXNrIGFzIFtUZW5zb3IsIFRlbnNvciwgVGVuc29yLCBUZW5zb3JdO1xuXG4gICAgICAvLyBOb3RlOiBGb3Igc3VwZXJpb3IgcGVyZm9ybWFuY2UsIFRlbnNvckZsb3cuanMgYWx3YXlzIHVzZXNcbiAgICAgIC8vIGltcGxlbWVudGF0aW9uIDIgcmVnYXJkbGVzcyBvZiB0aGUgYWN0dWFsIHZhbHVlIG9mXG4gICAgICAvLyBjb25maWcuaW1wbGVtZW50YXRpb24uXG4gICAgICBsZXQgaTogVGVuc29yO1xuICAgICAgbGV0IGY6IFRlbnNvcjtcbiAgICAgIGxldCBjOiBUZW5zb3I7XG4gICAgICBsZXQgbzogVGVuc29yO1xuICAgICAgaWYgKDAgPCB0aGlzLmRyb3BvdXQgJiYgdGhpcy5kcm9wb3V0IDwgMSkge1xuICAgICAgICBpbnB1dHMgPSB0ZmMubXVsKGlucHV0cywgZHBNYXNrWzBdKTtcbiAgICAgIH1cbiAgICAgIGxldCB6ID0gSy5kb3QoaW5wdXRzLCB0aGlzLmtlcm5lbC5yZWFkKCkpO1xuICAgICAgaWYgKDAgPCB0aGlzLnJlY3VycmVudERyb3BvdXQgJiYgdGhpcy5yZWN1cnJlbnREcm9wb3V0IDwgMSkge1xuICAgICAgICBoVE1pbnVzMSA9IHRmYy5tdWwoaFRNaW51czEsIHJlY0RwTWFza1swXSk7XG4gICAgICB9XG4gICAgICB6ID0gdGZjLmFkZCh6LCBLLmRvdChoVE1pbnVzMSwgdGhpcy5yZWN1cnJlbnRLZXJuZWwucmVhZCgpKSk7XG4gICAgICBpZiAodGhpcy51c2VCaWFzKSB7XG4gICAgICAgIHogPSBLLmJpYXNBZGQoeiwgdGhpcy5iaWFzLnJlYWQoKSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IFt6MCwgejEsIHoyLCB6M10gPSB0ZmMuc3BsaXQoeiwgNCwgei5yYW5rIC0gMSk7XG5cbiAgICAgIGkgPSB0aGlzLnJlY3VycmVudEFjdGl2YXRpb24uYXBwbHkoejApO1xuICAgICAgZiA9IHRoaXMucmVjdXJyZW50QWN0aXZhdGlvbi5hcHBseSh6MSk7XG4gICAgICBjID0gdGZjLmFkZCh0ZmMubXVsKGYsIGNUTWludXMxKSwgdGZjLm11bChpLCB0aGlzLmFjdGl2YXRpb24uYXBwbHkoejIpKSk7XG4gICAgICBvID0gdGhpcy5yZWN1cnJlbnRBY3RpdmF0aW9uLmFwcGx5KHozKTtcblxuICAgICAgY29uc3QgaCA9IHRmYy5tdWwobywgdGhpcy5hY3RpdmF0aW9uLmFwcGx5KGMpKTtcbiAgICAgIC8vIFRPRE8oY2Fpcyk6IEFkZCB1c2VfbGVhcm5pbmdfcGhhc2UgZmxhZyBwcm9wZXJseS5cbiAgICAgIHJldHVybiBbaCwgaCwgY107XG4gICAgfSk7XG4gIH1cblxuICBvdmVycmlkZSBnZXRDb25maWcoKTogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0IHtcbiAgICBjb25zdCBiYXNlQ29uZmlnID0gc3VwZXIuZ2V0Q29uZmlnKCk7XG5cbiAgICBjb25zdCBjb25maWc6IHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdCA9IHtcbiAgICAgIHVuaXRzOiB0aGlzLnVuaXRzLFxuICAgICAgYWN0aXZhdGlvbjogc2VyaWFsaXplQWN0aXZhdGlvbih0aGlzLmFjdGl2YXRpb24pLFxuICAgICAgcmVjdXJyZW50QWN0aXZhdGlvbjogc2VyaWFsaXplQWN0aXZhdGlvbih0aGlzLnJlY3VycmVudEFjdGl2YXRpb24pLFxuICAgICAgdXNlQmlhczogdGhpcy51c2VCaWFzLFxuICAgICAga2VybmVsSW5pdGlhbGl6ZXI6IHNlcmlhbGl6ZUluaXRpYWxpemVyKHRoaXMua2VybmVsSW5pdGlhbGl6ZXIpLFxuICAgICAgcmVjdXJyZW50SW5pdGlhbGl6ZXI6IHNlcmlhbGl6ZUluaXRpYWxpemVyKHRoaXMucmVjdXJyZW50SW5pdGlhbGl6ZXIpLFxuICAgICAgYmlhc0luaXRpYWxpemVyOiBzZXJpYWxpemVJbml0aWFsaXplcih0aGlzLmJpYXNJbml0aWFsaXplciksXG4gICAgICB1bml0Rm9yZ2V0QmlhczogdGhpcy51bml0Rm9yZ2V0QmlhcyxcbiAgICAgIGtlcm5lbFJlZ3VsYXJpemVyOiBzZXJpYWxpemVSZWd1bGFyaXplcih0aGlzLmtlcm5lbFJlZ3VsYXJpemVyKSxcbiAgICAgIHJlY3VycmVudFJlZ3VsYXJpemVyOiBzZXJpYWxpemVSZWd1bGFyaXplcih0aGlzLnJlY3VycmVudFJlZ3VsYXJpemVyKSxcbiAgICAgIGJpYXNSZWd1bGFyaXplcjogc2VyaWFsaXplUmVndWxhcml6ZXIodGhpcy5iaWFzUmVndWxhcml6ZXIpLFxuICAgICAgYWN0aXZpdHlSZWd1bGFyaXplcjogc2VyaWFsaXplUmVndWxhcml6ZXIodGhpcy5hY3Rpdml0eVJlZ3VsYXJpemVyKSxcbiAgICAgIGtlcm5lbENvbnN0cmFpbnQ6IHNlcmlhbGl6ZUNvbnN0cmFpbnQodGhpcy5rZXJuZWxDb25zdHJhaW50KSxcbiAgICAgIHJlY3VycmVudENvbnN0cmFpbnQ6IHNlcmlhbGl6ZUNvbnN0cmFpbnQodGhpcy5yZWN1cnJlbnRDb25zdHJhaW50KSxcbiAgICAgIGJpYXNDb25zdHJhaW50OiBzZXJpYWxpemVDb25zdHJhaW50KHRoaXMuYmlhc0NvbnN0cmFpbnQpLFxuICAgICAgZHJvcG91dDogdGhpcy5kcm9wb3V0LFxuICAgICAgcmVjdXJyZW50RHJvcG91dDogdGhpcy5yZWN1cnJlbnREcm9wb3V0LFxuICAgICAgaW1wbGVtZW50YXRpb246IHRoaXMuaW1wbGVtZW50YXRpb24sXG4gICAgfTtcblxuICAgIHJldHVybiB7Li4uYmFzZUNvbmZpZywgLi4uY29uZmlnfTtcbiAgfVxufVxuc2VyaWFsaXphdGlvbi5yZWdpc3RlckNsYXNzKExTVE1DZWxsKTtcblxuLy8gUG9ydGluZyBOb3RlOiBTaW5jZSB0aGlzIGlzIGEgc3VwZXJzZXQgb2YgU2ltcGxlUk5OTGF5ZXJDb25maWcsIHdlIGluaGVyaXRcbi8vICAgZnJvbSB0aGF0IGludGVyZmFjZSBpbnN0ZWFkIG9mIHJlcGVhdGluZyB0aGUgZmllbGRzIGhlcmUuXG5leHBvcnQgZGVjbGFyZSBpbnRlcmZhY2UgTFNUTUxheWVyQXJncyBleHRlbmRzIFNpbXBsZVJOTkxheWVyQXJncyB7XG4gIC8qKlxuICAgKiBBY3RpdmF0aW9uIGZ1bmN0aW9uIHRvIHVzZSBmb3IgdGhlIHJlY3VycmVudCBzdGVwLlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byBoYXJkIHNpZ21vaWQgKGBoYXJkU2lnbW9pZGApLlxuICAgKlxuICAgKiBJZiBgbnVsbGAsIG5vIGFjdGl2YXRpb24gaXMgYXBwbGllZC5cbiAgICovXG4gIHJlY3VycmVudEFjdGl2YXRpb24/OiBBY3RpdmF0aW9uSWRlbnRpZmllcjtcblxuICAvKipcbiAgICogSWYgYHRydWVgLCBhZGQgMSB0byB0aGUgYmlhcyBvZiB0aGUgZm9yZ2V0IGdhdGUgYXQgaW5pdGlhbGl6YXRpb24uXG4gICAqIFNldHRpbmcgaXQgdG8gYHRydWVgIHdpbGwgYWxzbyBmb3JjZSBgYmlhc0luaXRpYWxpemVyID0gJ3plcm9zJ2AuXG4gICAqIFRoaXMgaXMgcmVjb21tZW5kZWQgaW5cbiAgICogW0pvemVmb3dpY3ogZXRcbiAgICogYWwuXShodHRwOi8vd3d3LmptbHIub3JnL3Byb2NlZWRpbmdzL3BhcGVycy92Mzcvam96ZWZvd2ljejE1LnBkZilcbiAgICovXG4gIHVuaXRGb3JnZXRCaWFzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW1wbGVtZW50YXRpb24gbW9kZSwgZWl0aGVyIDEgb3IgMi5cbiAgICogICBNb2RlIDEgd2lsbCBzdHJ1Y3R1cmUgaXRzIG9wZXJhdGlvbnMgYXMgYSBsYXJnZXIgbnVtYmVyIG9mXG4gICAqICAgc21hbGxlciBkb3QgcHJvZHVjdHMgYW5kIGFkZGl0aW9ucywgd2hlcmVhcyBtb2RlIDIgd2lsbFxuICAgKiAgIGJhdGNoIHRoZW0gaW50byBmZXdlciwgbGFyZ2VyIG9wZXJhdGlvbnMuIFRoZXNlIG1vZGVzIHdpbGxcbiAgICogICBoYXZlIGRpZmZlcmVudCBwZXJmb3JtYW5jZSBwcm9maWxlcyBvbiBkaWZmZXJlbnQgaGFyZHdhcmUgYW5kXG4gICAqICAgZm9yIGRpZmZlcmVudCBhcHBsaWNhdGlvbnMuXG4gICAqXG4gICAqIE5vdGU6IEZvciBzdXBlcmlvciBwZXJmb3JtYW5jZSwgVGVuc29yRmxvdy5qcyBhbHdheXMgdXNlcyBpbXBsZW1lbnRhdGlvblxuICAgKiAyLCByZWdhcmRsZXNzIG9mIHRoZSBhY3R1YWwgdmFsdWUgb2YgdGhpcyBjb25maWcgZmllbGQuXG4gICAqL1xuICBpbXBsZW1lbnRhdGlvbj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIExTVE0gZXh0ZW5kcyBSTk4ge1xuICAvKiogQG5vY29sbGFwc2UgKi9cbiAgc3RhdGljIG92ZXJyaWRlIGNsYXNzTmFtZSA9ICdMU1RNJztcbiAgY29uc3RydWN0b3IoYXJnczogTFNUTUxheWVyQXJncykge1xuICAgIGlmIChhcmdzLmltcGxlbWVudGF0aW9uID09PSAwKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ2BpbXBsZW1lbnRhdGlvbj0wYCBoYXMgYmVlbiBkZXByZWNhdGVkLCBhbmQgbm93IGRlZmF1bHRzIHRvICcgK1xuICAgICAgICAgICdgaW1wbGVtZW50YXRpb249MWAuIFBsZWFzZSB1cGRhdGUgeW91ciBsYXllciBjYWxsLicpO1xuICAgIH1cbiAgICBhcmdzLmNlbGwgPSBuZXcgTFNUTUNlbGwoYXJncyk7XG4gICAgc3VwZXIoYXJncyBhcyBSTk5MYXllckFyZ3MpO1xuICAgIC8vIFRPRE8oY2Fpcyk6IEFkZCBhY3Rpdml0eVJlZ3VsYXJpemVyLlxuICB9XG5cbiAgb3ZlcnJpZGUgY2FsbChpbnB1dHM6IFRlbnNvcnxUZW5zb3JbXSwga3dhcmdzOiBLd2FyZ3MpOiBUZW5zb3J8VGVuc29yW10ge1xuICAgIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmNlbGwuZHJvcG91dE1hc2sgIT0gbnVsbCkge1xuICAgICAgICB0ZmMuZGlzcG9zZSh0aGlzLmNlbGwuZHJvcG91dE1hc2spO1xuICAgICAgICB0aGlzLmNlbGwuZHJvcG91dE1hc2sgPSBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuY2VsbC5yZWN1cnJlbnREcm9wb3V0TWFzayAhPSBudWxsKSB7XG4gICAgICAgIHRmYy5kaXNwb3NlKHRoaXMuY2VsbC5yZWN1cnJlbnREcm9wb3V0TWFzayk7XG4gICAgICAgIHRoaXMuY2VsbC5yZWN1cnJlbnREcm9wb3V0TWFzayA9IG51bGw7XG4gICAgICB9XG4gICAgICBjb25zdCBtYXNrID0ga3dhcmdzID09IG51bGwgPyBudWxsIDoga3dhcmdzWydtYXNrJ107XG4gICAgICBjb25zdCB0cmFpbmluZyA9IGt3YXJncyA9PSBudWxsID8gbnVsbCA6IGt3YXJnc1sndHJhaW5pbmcnXTtcbiAgICAgIGNvbnN0IGluaXRpYWxTdGF0ZTogVGVuc29yW10gPVxuICAgICAgICAgIGt3YXJncyA9PSBudWxsID8gbnVsbCA6IGt3YXJnc1snaW5pdGlhbFN0YXRlJ107XG4gICAgICByZXR1cm4gc3VwZXIuY2FsbChpbnB1dHMsIHttYXNrLCB0cmFpbmluZywgaW5pdGlhbFN0YXRlfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQG5vY29sbGFwc2UgKi9cbiAgc3RhdGljIG92ZXJyaWRlIGZyb21Db25maWc8VCBleHRlbmRzIHNlcmlhbGl6YXRpb24uU2VyaWFsaXphYmxlPihcbiAgICAgIGNsczogc2VyaWFsaXphdGlvbi5TZXJpYWxpemFibGVDb25zdHJ1Y3RvcjxUPixcbiAgICAgIGNvbmZpZzogc2VyaWFsaXphdGlvbi5Db25maWdEaWN0KTogVCB7XG4gICAgaWYgKGNvbmZpZ1snaW1wbG1lbnRhdGlvbiddID09PSAwKSB7XG4gICAgICBjb25maWdbJ2ltcGxlbWVudGF0aW9uJ10gPSAxO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IGNscyhjb25maWcpO1xuICB9XG59XG5zZXJpYWxpemF0aW9uLnJlZ2lzdGVyQ2xhc3MoTFNUTSk7XG5cbmV4cG9ydCBkZWNsYXJlIGludGVyZmFjZSBTdGFja2VkUk5OQ2VsbHNBcmdzIGV4dGVuZHMgTGF5ZXJBcmdzIHtcbiAgLyoqXG4gICAqIEFuIGBBcnJheWAgb2YgYFJOTkNlbGxgIGluc3RhbmNlcy5cbiAgICovXG4gIGNlbGxzOiBSTk5DZWxsW107XG59XG5cbmV4cG9ydCBjbGFzcyBTdGFja2VkUk5OQ2VsbHMgZXh0ZW5kcyBSTk5DZWxsIHtcbiAgLyoqIEBub2NvbGxhcHNlICovXG4gIHN0YXRpYyBjbGFzc05hbWUgPSAnU3RhY2tlZFJOTkNlbGxzJztcbiAgcHJvdGVjdGVkIGNlbGxzOiBSTk5DZWxsW107XG5cbiAgY29uc3RydWN0b3IoYXJnczogU3RhY2tlZFJOTkNlbGxzQXJncykge1xuICAgIHN1cGVyKGFyZ3MpO1xuICAgIHRoaXMuY2VsbHMgPSBhcmdzLmNlbGxzO1xuICB9XG5cbiAgZ2V0IHN0YXRlU2l6ZSgpOiBudW1iZXJbXSB7XG4gICAgLy8gU3RhdGVzIGFyZSBhIGZsYXQgbGlzdCBpbiByZXZlcnNlIG9yZGVyIG9mIHRoZSBjZWxsIHN0YWNrLlxuICAgIC8vIFRoaXMgYWxsb3dzIHBlcnNlcnZpbmcgdGhlIHJlcXVpcmVtZW50IGBzdGFjay5zdGF0ZXNpemVbMF0gPT09XG4gICAgLy8gb3V0cHV0RGltYC4gRS5nLiwgc3RhdGVzIG9mIGEgMi1sYXllciBMU1RNIHdvdWxkIGJlIGBbaDIsIGMyLCBoMSwgYzFdYCxcbiAgICAvLyBhc3N1bWluZyBvbmUgTFNUTSBoYXMgc3RhdGVzIGBbaCwgY11gLlxuICAgIGNvbnN0IHN0YXRlU2l6ZTogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGNlbGwgb2YgdGhpcy5jZWxscy5zbGljZSgpLnJldmVyc2UoKSkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY2VsbC5zdGF0ZVNpemUpKSB7XG4gICAgICAgIHN0YXRlU2l6ZS5wdXNoKC4uLmNlbGwuc3RhdGVTaXplKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXRlU2l6ZS5wdXNoKGNlbGwuc3RhdGVTaXplKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0YXRlU2l6ZTtcbiAgfVxuXG4gIG92ZXJyaWRlIGNhbGwoaW5wdXRzOiBUZW5zb3J8VGVuc29yW10sIGt3YXJnczogS3dhcmdzKTogVGVuc29yfFRlbnNvcltdIHtcbiAgICByZXR1cm4gdGlkeSgoKSA9PiB7XG4gICAgICBpbnB1dHMgPSBpbnB1dHMgYXMgVGVuc29yW107XG4gICAgICBsZXQgc3RhdGVzID0gaW5wdXRzLnNsaWNlKDEpO1xuXG4gICAgICAvLyBSZWNvdmVyIHBlci1jZWxsIHN0YXRlcy5cbiAgICAgIGNvbnN0IG5lc3RlZFN0YXRlczogVGVuc29yW11bXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBjZWxsIG9mIHRoaXMuY2VsbHMuc2xpY2UoKS5yZXZlcnNlKCkpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY2VsbC5zdGF0ZVNpemUpKSB7XG4gICAgICAgICAgbmVzdGVkU3RhdGVzLnB1c2goc3RhdGVzLnNwbGljZSgwLCBjZWxsLnN0YXRlU2l6ZS5sZW5ndGgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXN0ZWRTdGF0ZXMucHVzaChzdGF0ZXMuc3BsaWNlKDAsIDEpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbmVzdGVkU3RhdGVzLnJldmVyc2UoKTtcblxuICAgICAgLy8gQ2FsbCB0aGUgY2VsbHMgaW4gb3JkZXIgYW5kIHN0b3JlIHRoZSByZXR1cm5lZCBzdGF0ZXMuXG4gICAgICBjb25zdCBuZXdOZXN0ZWRTdGF0ZXM6IFRlbnNvcltdW10gPSBbXTtcbiAgICAgIGxldCBjYWxsSW5wdXRzOiBUZW5zb3JbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jZWxscy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb25zdCBjZWxsID0gdGhpcy5jZWxsc1tpXTtcbiAgICAgICAgc3RhdGVzID0gbmVzdGVkU3RhdGVzW2ldO1xuICAgICAgICAvLyBUT0RPKGNhaXMpOiBUYWtlIGNhcmUgb2YgY29uc3RhbnRzLlxuICAgICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICAgIGNhbGxJbnB1dHMgPSBbaW5wdXRzWzBdXS5jb25jYXQoc3RhdGVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYWxsSW5wdXRzID0gW2NhbGxJbnB1dHNbMF1dLmNvbmNhdChzdGF0ZXMpO1xuICAgICAgICB9XG4gICAgICAgIGNhbGxJbnB1dHMgPSBjZWxsLmNhbGwoY2FsbElucHV0cywga3dhcmdzKSBhcyBUZW5zb3JbXTtcbiAgICAgICAgbmV3TmVzdGVkU3RhdGVzLnB1c2goY2FsbElucHV0cy5zbGljZSgxKSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvcm1hdCB0aGUgbmV3IHN0YXRlcyBhcyBhIGZsYXQgbGlzdCBpbiByZXZlcnNlIGNlbGwgb3JkZXIuXG4gICAgICBzdGF0ZXMgPSBbXTtcbiAgICAgIGZvciAoY29uc3QgY2VsbFN0YXRlcyBvZiBuZXdOZXN0ZWRTdGF0ZXMuc2xpY2UoKS5yZXZlcnNlKCkpIHtcbiAgICAgICAgc3RhdGVzLnB1c2goLi4uY2VsbFN0YXRlcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gW2NhbGxJbnB1dHNbMF1dLmNvbmNhdChzdGF0ZXMpO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIGJ1aWxkKGlucHV0U2hhcGU6IFNoYXBlfFNoYXBlW10pOiB2b2lkIHtcbiAgICBpZiAoaXNBcnJheU9mU2hhcGVzKGlucHV0U2hhcGUpKSB7XG4gICAgICAvLyBUT0RPKGNhaXMpOiBUYWtlIGNhcmUgb2YgaW5wdXQgY29uc3RhbnRzLlxuICAgICAgLy8gY29uc3QgY29uc3RhbnRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoMSk7XG4gICAgICBpbnB1dFNoYXBlID0gKGlucHV0U2hhcGUgYXMgU2hhcGVbXSlbMF07XG4gICAgfVxuICAgIGlucHV0U2hhcGUgPSBpbnB1dFNoYXBlIGFzIFNoYXBlO1xuICAgIGxldCBvdXRwdXREaW06IG51bWJlcjtcbiAgICB0aGlzLmNlbGxzLmZvckVhY2goKGNlbGwsIGkpID0+IHtcbiAgICAgIG5hbWVTY29wZShgUk5OQ2VsbF8ke2l9YCwgKCkgPT4ge1xuICAgICAgICAvLyBUT0RPKGNhaXMpOiBUYWtlIGNhcmUgb2YgaW5wdXQgY29uc3RhbnRzLlxuXG4gICAgICAgIGNlbGwuYnVpbGQoaW5wdXRTaGFwZSk7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNlbGwuc3RhdGVTaXplKSkge1xuICAgICAgICAgIG91dHB1dERpbSA9IGNlbGwuc3RhdGVTaXplWzBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dHB1dERpbSA9IGNlbGwuc3RhdGVTaXplO1xuICAgICAgICB9XG4gICAgICAgIGlucHV0U2hhcGUgPSBbaW5wdXRTaGFwZVswXSwgb3V0cHV0RGltXSBhcyBTaGFwZTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHRoaXMuYnVpbHQgPSB0cnVlO1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0Q29uZmlnKCk6IHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdCB7XG4gICAgY29uc3QgYmFzZUNvbmZpZyA9IHN1cGVyLmdldENvbmZpZygpO1xuXG4gICAgY29uc3QgZ2V0Q2VsbENvbmZpZyA9IChjZWxsOiBSTk5DZWxsKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAnY2xhc3NOYW1lJzogY2VsbC5nZXRDbGFzc05hbWUoKSxcbiAgICAgICAgJ2NvbmZpZyc6IGNlbGwuZ2V0Q29uZmlnKCksXG4gICAgICB9O1xuICAgIH07XG5cbiAgICBjb25zdCBjZWxsQ29uZmlncyA9IHRoaXMuY2VsbHMubWFwKGdldENlbGxDb25maWcpO1xuXG4gICAgY29uc3QgY29uZmlnID0geydjZWxscyc6IGNlbGxDb25maWdzfTtcblxuICAgIHJldHVybiB7Li4uYmFzZUNvbmZpZywgLi4uY29uZmlnfTtcbiAgfVxuXG4gIC8qKiBAbm9jb2xsYXBzZSAqL1xuICBzdGF0aWMgb3ZlcnJpZGUgZnJvbUNvbmZpZzxUIGV4dGVuZHMgc2VyaWFsaXphdGlvbi5TZXJpYWxpemFibGU+KFxuICAgICAgY2xzOiBzZXJpYWxpemF0aW9uLlNlcmlhbGl6YWJsZUNvbnN0cnVjdG9yPFQ+LFxuICAgICAgY29uZmlnOiBzZXJpYWxpemF0aW9uLkNvbmZpZ0RpY3QsXG4gICAgICBjdXN0b21PYmplY3RzID0ge30gYXMgc2VyaWFsaXphdGlvbi5Db25maWdEaWN0KTogVCB7XG4gICAgY29uc3QgY2VsbHM6IFJOTkNlbGxbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY2VsbENvbmZpZyBvZiAoY29uZmlnWydjZWxscyddIGFzIHNlcmlhbGl6YXRpb24uQ29uZmlnRGljdFtdKSkge1xuICAgICAgY2VsbHMucHVzaChkZXNlcmlhbGl6ZShjZWxsQ29uZmlnLCBjdXN0b21PYmplY3RzKSBhcyBSTk5DZWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBjbHMoe2NlbGxzfSk7XG4gIH1cblxuICBvdmVycmlkZSBnZXQgdHJhaW5hYmxlV2VpZ2h0cygpOiBMYXllclZhcmlhYmxlW10ge1xuICAgIGlmICghdGhpcy50cmFpbmFibGUpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgY29uc3Qgd2VpZ2h0czogTGF5ZXJWYXJpYWJsZVtdID0gW107XG4gICAgZm9yIChjb25zdCBjZWxsIG9mIHRoaXMuY2VsbHMpIHtcbiAgICAgIHdlaWdodHMucHVzaCguLi5jZWxsLnRyYWluYWJsZVdlaWdodHMpO1xuICAgIH1cbiAgICByZXR1cm4gd2VpZ2h0cztcbiAgfVxuXG4gIG92ZXJyaWRlIGdldCBub25UcmFpbmFibGVXZWlnaHRzKCk6IExheWVyVmFyaWFibGVbXSB7XG4gICAgY29uc3Qgd2VpZ2h0czogTGF5ZXJWYXJpYWJsZVtdID0gW107XG4gICAgZm9yIChjb25zdCBjZWxsIG9mIHRoaXMuY2VsbHMpIHtcbiAgICAgIHdlaWdodHMucHVzaCguLi5jZWxsLm5vblRyYWluYWJsZVdlaWdodHMpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMudHJhaW5hYmxlKSB7XG4gICAgICBjb25zdCB0cmFpbmFibGVXZWlnaHRzOiBMYXllclZhcmlhYmxlW10gPSBbXTtcbiAgICAgIGZvciAoY29uc3QgY2VsbCBvZiB0aGlzLmNlbGxzKSB7XG4gICAgICAgIHRyYWluYWJsZVdlaWdodHMucHVzaCguLi5jZWxsLnRyYWluYWJsZVdlaWdodHMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRyYWluYWJsZVdlaWdodHMuY29uY2F0KHdlaWdodHMpO1xuICAgIH1cbiAgICByZXR1cm4gd2VpZ2h0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZSB0aGUgd2VpZ2h0cyBvZiBhIHRoZSBtb2RlbC5cbiAgICpcbiAgICogQHJldHVybnMgQSBmbGF0IGBBcnJheWAgb2YgYHRmLlRlbnNvcmBzLlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0V2VpZ2h0cygpOiBUZW5zb3JbXSB7XG4gICAgY29uc3Qgd2VpZ2h0czogTGF5ZXJWYXJpYWJsZVtdID0gW107XG4gICAgZm9yIChjb25zdCBjZWxsIG9mIHRoaXMuY2VsbHMpIHtcbiAgICAgIHdlaWdodHMucHVzaCguLi5jZWxsLndlaWdodHMpO1xuICAgIH1cbiAgICByZXR1cm4gYmF0Y2hHZXRWYWx1ZSh3ZWlnaHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIHdlaWdodHMgb2YgdGhlIG1vZGVsLlxuICAgKlxuICAgKiBAcGFyYW0gd2VpZ2h0cyBBbiBgQXJyYXlgIG9mIGB0Zi5UZW5zb3JgcyB3aXRoIHNoYXBlcyBhbmQgdHlwZXMgbWF0Y2hpbmdcbiAgICogICAgIHRoZSBvdXRwdXQgb2YgYGdldFdlaWdodHMoKWAuXG4gICAqL1xuICBvdmVycmlkZSBzZXRXZWlnaHRzKHdlaWdodHM6IFRlbnNvcltdKTogdm9pZCB7XG4gICAgY29uc3QgdHVwbGVzOiBBcnJheTxbTGF5ZXJWYXJpYWJsZSwgVGVuc29yXT4gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGNlbGwgb2YgdGhpcy5jZWxscykge1xuICAgICAgY29uc3QgbnVtUGFyYW1zID0gY2VsbC53ZWlnaHRzLmxlbmd0aDtcbiAgICAgIGNvbnN0IGlucHV0V2VpZ2h0cyA9IHdlaWdodHMuc3BsaWNlKG51bVBhcmFtcyk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNlbGwud2VpZ2h0cy5sZW5ndGg7ICsraSkge1xuICAgICAgICB0dXBsZXMucHVzaChbY2VsbC53ZWlnaHRzW2ldLCBpbnB1dFdlaWdodHNbaV1dKTtcbiAgICAgIH1cbiAgICB9XG4gICAgYmF0Y2hTZXRWYWx1ZSh0dXBsZXMpO1xuICB9XG5cbiAgLy8gVE9ETyhjYWlzKTogTWF5YmUgaW1wbGVtbnQgYGxvc3Nlc2AgYW5kIGBnZXRMb3NzZXNGb3JgLlxufVxuc2VyaWFsaXphdGlvbi5yZWdpc3RlckNsYXNzKFN0YWNrZWRSTk5DZWxscyk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZURyb3BvdXRNYXNrKGFyZ3M6IHtcbiAgb25lczogKCkgPT4gdGZjLlRlbnNvcixcbiAgcmF0ZTogbnVtYmVyLFxuICB0cmFpbmluZz86IGJvb2xlYW4sXG4gIGNvdW50PzogbnVtYmVyLFxuICBkcm9wb3V0RnVuYz86IEZ1bmN0aW9uLFxufSk6IHRmYy5UZW5zb3J8dGZjLlRlbnNvcltdIHtcbiAgY29uc3Qge29uZXMsIHJhdGUsIHRyYWluaW5nID0gZmFsc2UsIGNvdW50ID0gMSwgZHJvcG91dEZ1bmN9ID0gYXJncztcblxuICBjb25zdCBkcm9wcGVkSW5wdXRzID0gKCkgPT5cbiAgICAgIGRyb3BvdXRGdW5jICE9IG51bGwgPyBkcm9wb3V0RnVuYyhvbmVzKCksIHJhdGUpIDogSy5kcm9wb3V0KG9uZXMoKSwgcmF0ZSk7XG5cbiAgY29uc3QgY3JlYXRlTWFzayA9ICgpID0+IEsuaW5UcmFpblBoYXNlKGRyb3BwZWRJbnB1dHMsIG9uZXMsIHRyYWluaW5nKTtcblxuICAvLyBqdXN0IGluIGNhc2UgY291bnQgaXMgcHJvdmlkZWQgd2l0aCBudWxsIG9yIHVuZGVmaW5lZFxuICBpZiAoIWNvdW50IHx8IGNvdW50IDw9IDEpIHtcbiAgICByZXR1cm4gdGZjLmtlZXAoY3JlYXRlTWFzaygpLmNsb25lKCkpO1xuICB9XG5cbiAgY29uc3QgbWFza3MgPSBBcnJheShjb3VudCkuZmlsbCh1bmRlZmluZWQpLm1hcChjcmVhdGVNYXNrKTtcblxuICByZXR1cm4gbWFza3MubWFwKG0gPT4gdGZjLmtlZXAobS5jbG9uZSgpKSk7XG59XG4iXX0= |
\ | No newline at end of file |