Skip to content

Instantly share code, notes, and snippets.

@miwillhite
Last active October 31, 2016 17:34
Show Gist options
  • Save miwillhite/128decbc7a1607ac12fd1923ef4ac4e1 to your computer and use it in GitHub Desktop.
Save miwillhite/128decbc7a1607ac12fd1923ef4ac4e1 to your computer and use it in GitHub Desktop.
requirebin sketch
const daggy = require('daggy');
const R = require('ramda');
const Future = require('fluture');
const S = require('sanctuary');
const { Left, Right, Either } = S;
const Answer = daggy.taggedSum({
Pure: ['value'],
Addressable: ['street', 'city', 'postal_code', 'state'], // Address
Contactable: ['contact_uid'], // Participant and Relationship
Indexable: ['value', 'idx'], // Checkbox, Radio
Plottable: ['value', 'x', 'y'], // Likert
Phoneable: ['number', 'extension'], // Phone Number
Numeric: ['numerator', 'denominator'], // Any of the number types
});
Answer.prototype.map = function (f) {
return this.cata({
Pure: function (v) { return Answer.Pure(f(v)) },
});
};
Answer.prototype.join = function () {
return this.cata({
Pure: function (v) { return Answer.of(v.value); },
});
};
Answer.prototype.chain = function (f) {
return this.cata({
Pure: function (v) { return this.map(f).join() },
});
};
Answer.prototype.toString = function () {
return 'Answer(' + R.toString(this.value) + ')';
};
Answer.of = Answer.Pure;
//console.log(
// R.compose(R.map(R.add(3)), Answer.of)(1),
// Answer.of(Answer.of(10)).join()
//);
console.log(
R.compose(
Future.fork(console.error, console.log),
// v-either v-answer
R.lift(R.map(R.lift(S.add(1)))),
Future.fold(Left, Right),
Future.of
)(Answer.of(4))
);
This file has been truncated, but you can view the full file.
setTimeout(function(){
;require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"daggy":[function(require,module,exports){
/**
# Daggy
Library for creating tagged constructors.
**/
(function(global, factory) {
'use strict';
if(typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if(typeof exports !== 'undefined') {
factory(exports);
} else {
global.daggy = {};
factory(global.daggy);
}
})(this, function(exports) {
function create(proto) {
function Ctor() {}
Ctor.prototype = proto;
return new Ctor();
}
exports.create = create;
/**
## `daggy.getInstance(self, constructor)`
Returns `self` if it's an `instanceof constructor`, otherwise
creates a new object with `constructor`'s prototype.
Allows creating constructors that can be used with or without
the new keyword but always have the correct prototype.
```javascript
function WrappedArray() {
var self = daggy.getInstance(this, WrappedArray);
self._array = [].slice.apply(arguments);
return self;
}
new WrappedArray(1, 2, 3) instanceof WrappedArray; // true
WrappedArray(1, 2, 3) instanceof WrappedArray; // true
```
**/
function getInstance(self, constructor) {
return self instanceof constructor ? self : create(constructor.prototype);
}
exports.getInstance = getInstance;
/**
## `daggy.tagged(arguments)`
Creates a new constructor with the given field names as
arguments and properties. Allows `instanceof` checks with
returned constructor.
```javascript
var Tuple3 = daggy.tagged('x', 'y', 'z');
var _123 = Tuple3(1, 2, 3); // optional new keyword
_123.x == 1 && _123.y == 2 && _123.z == 3; // true
_123 instanceof Tuple3; // true
```
**/
function tagged() {
var fields = [].slice.apply(arguments);
function wrapped() {
var self = getInstance(this, wrapped),
i;
if(arguments.length != fields.length)
throw new TypeError('Expected ' + fields.length + ' arguments, got ' + arguments.length);
for(i = 0; i < fields.length; i++)
self[fields[i]] = arguments[i];
return self;
}
wrapped._length = fields.length;
return wrapped;
}
exports.tagged = tagged;
/**
## `daggy.taggedSum(constructors)`
Creates a constructor for each key in `constructors`. Returns a
function with each constructor as a property. Allows
`instanceof` checks for each constructor and the returned
function.
```javascript
var Option = daggy.taggedSum({
Some: ['x'],
None: []
});
Option.Some(1) instanceof Option.Some; // true
Option.Some(1) instanceof Option; // true
Option.None instanceof Option; // true
function incOrZero(o) {
return o.cata({
Some: function(x) {
return x + 1;
},
None: function() {
return 0;
}
});
}
incOrZero(Option.Some(1)); // 2
incOrZero(Option.None); // 0
```
**/
function taggedSum(constructors) {
var key;
function definitions() {
throw new TypeError('Tagged sum was called instead of one of its properties.');
}
function makeCata(key) {
return function(dispatches) {
var fields = constructors[key],
args = [],
i;
if(!dispatches[key])
throw new TypeError("Constructors given to cata didn't include: " + key);
for(i = 0; i < fields.length; i++)
args.push(this[fields[i]]);
return dispatches[key].apply(this, args);
};
}
function makeProto(key) {
var proto = create(definitions.prototype);
proto.cata = makeCata(key);
return proto;
}
for(key in constructors) {
if(!constructors[key].length) {
definitions[key] = makeProto(key);
continue;
}
definitions[key] = tagged.apply(null, constructors[key]);
definitions[key].prototype = makeProto(key);
}
return definitions;
}
exports.taggedSum = taggedSum;
});
},{}]},{},[])
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImRhZ2d5LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLyoqXG4gICMgRGFnZ3lcblxuICBMaWJyYXJ5IGZvciBjcmVhdGluZyB0YWdnZWQgY29uc3RydWN0b3JzLlxuKiovXG4oZnVuY3Rpb24oZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgaWYodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSk7XG4gICAgfSBlbHNlIGlmKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBmYWN0b3J5KGV4cG9ydHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdsb2JhbC5kYWdneSA9IHt9O1xuICAgICAgICBmYWN0b3J5KGdsb2JhbC5kYWdneSk7XG4gICAgfVxufSkodGhpcywgZnVuY3Rpb24oZXhwb3J0cykge1xuICAgIGZ1bmN0aW9uIGNyZWF0ZShwcm90bykge1xuICAgICAgICBmdW5jdGlvbiBDdG9yKCkge31cbiAgICAgICAgQ3Rvci5wcm90b3R5cGUgPSBwcm90bztcbiAgICAgICAgcmV0dXJuIG5ldyBDdG9yKCk7XG4gICAgfVxuICAgIGV4cG9ydHMuY3JlYXRlID0gY3JlYXRlO1xuXG4gICAgLyoqXG4gICAgICAjIyBgZGFnZ3kuZ2V0SW5zdGFuY2Uoc2VsZiwgY29uc3RydWN0b3IpYFxuXG4gICAgICBSZXR1cm5zIGBzZWxmYCBpZiBpdCdzIGFuIGBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yYCwgb3RoZXJ3aXNlXG4gICAgICBjcmVhdGVzIGEgbmV3IG9iamVjdCB3aXRoIGBjb25zdHJ1Y3RvcmAncyBwcm90b3R5cGUuXG5cbiAgICAgIEFsbG93cyBjcmVhdGluZyBjb25zdHJ1Y3RvcnMgdGhhdCBjYW4gYmUgdXNlZCB3aXRoIG9yIHdpdGhvdXRcbiAgICAgIHRoZSBuZXcga2V5d29yZCBidXQgYWx3YXlzIGhhdmUgdGhlIGNvcnJlY3QgcHJvdG90eXBlLlxuXG4gICAgICBgYGBqYXZhc2NyaXB0XG4gICAgICBmdW5jdGlvbiBXcmFwcGVkQXJyYXkoKSB7XG4gICAgICAgICAgdmFyIHNlbGYgPSBkYWdneS5nZXRJbnN0YW5jZSh0aGlzLCBXcmFwcGVkQXJyYXkpO1xuICAgICAgICAgIHNlbGYuX2FycmF5ID0gW10uc2xpY2UuYXBwbHkoYXJndW1lbnRzKTtcbiAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgIH1cbiAgICAgIG5ldyBXcmFwcGVkQXJyYXkoMSwgMiwgMykgaW5zdGFuY2VvZiBXcmFwcGVkQXJyYXk7IC8vIHRydWVcbiAgICAgIFdyYXBwZWRBcnJheSgxLCAyLCAzKSBpbnN0YW5jZW9mIFdyYXBwZWRBcnJheTsgLy8gdHJ1ZVxuICAgICAgYGBgXG4gICAgKiovXG4gICAgZnVuY3Rpb24gZ2V0SW5zdGFuY2Uoc2VsZiwgY29uc3RydWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYgaW5zdGFuY2VvZiBjb25zdHJ1Y3RvciA/IHNlbGYgOiBjcmVhdGUoY29uc3RydWN0b3IucHJvdG90eXBlKTtcbiAgICB9XG4gICAgZXhwb3J0cy5nZXRJbnN0YW5jZSA9IGdldEluc3RhbmNlO1xuXG4gICAgLyoqXG4gICAgICAjIyBgZGFnZ3kudGFnZ2VkKGFyZ3VtZW50cylgXG5cbiAgICAgIENyZWF0ZXMgYSBuZXcgY29uc3RydWN0b3Igd2l0aCB0aGUgZ2l2ZW4gZmllbGQgbmFtZXMgYXNcbiAgICAgIGFyZ3VtZW50cyBhbmQgcHJvcGVydGllcy4gQWxsb3dzIGBpbnN0YW5jZW9mYCBjaGVja3Mgd2l0aFxuICAgICAgcmV0dXJuZWQgY29uc3RydWN0b3IuXG5cbiAgICAgIGBgYGphdmFzY3JpcHRcbiAgICAgIHZhciBUdXBsZTMgPSBkYWdneS50YWdnZWQoJ3gnLCAneScsICd6Jyk7XG5cbiAgICAgIHZhciBfMTIzID0gVHVwbGUzKDEsIDIsIDMpOyAvLyBvcHRpb25hbCBuZXcga2V5d29yZFxuICAgICAgXzEyMy54ID09IDEgJiYgXzEyMy55ID09IDIgJiYgXzEyMy56ID09IDM7IC8vIHRydWVcbiAgICAgIF8xMjMgaW5zdGFuY2VvZiBUdXBsZTM7IC8vIHRydWVcbiAgICAgIGBgYFxuICAgICoqL1xuICAgIGZ1bmN0aW9uIHRhZ2dlZCgpIHtcbiAgICAgICAgdmFyIGZpZWxkcyA9IFtdLnNsaWNlLmFwcGx5KGFyZ3VtZW50cyk7XG4gICAgICAgIGZ1bmN0aW9uIHdyYXBwZWQoKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IGdldEluc3RhbmNlKHRoaXMsIHdyYXBwZWQpLFxuICAgICAgICAgICAgICAgIGk7XG5cbiAgICAgICAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggIT0gZmllbGRzLmxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCAnICsgZmllbGRzLmxlbmd0aCArICcgYXJndW1lbnRzLCBnb3QgJyArIGFyZ3VtZW50cy5sZW5ndGgpO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmaWVsZHMubGVuZ3RoOyBpKyspXG4gICAgICAgICAgICAgICAgc2VsZltmaWVsZHNbaV1dID0gYXJndW1lbnRzW2ldO1xuXG4gICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgfVxuICAgICAgICB3cmFwcGVkLl9sZW5ndGggPSBmaWVsZHMubGVuZ3RoO1xuICAgICAgICByZXR1cm4gd3JhcHBlZDtcbiAgICB9XG4gICAgZXhwb3J0cy50YWdnZWQgPSB0YWdnZWQ7XG5cbiAgICAvKipcbiAgICAgICMjIGBkYWdneS50YWdnZWRTdW0oY29uc3RydWN0b3JzKWBcblxuICAgICAgQ3JlYXRlcyBhIGNvbnN0cnVjdG9yIGZvciBlYWNoIGtleSBpbiBgY29uc3RydWN0b3JzYC4gUmV0dXJucyBhXG4gICAgICBmdW5jdGlvbiB3aXRoIGVhY2ggY29uc3RydWN0b3IgYXMgYSBwcm9wZXJ0eS4gQWxsb3dzXG4gICAgICBgaW5zdGFuY2VvZmAgY2hlY2tzIGZvciBlYWNoIGNvbnN0cnVjdG9yIGFuZCB0aGUgcmV0dXJuZWRcbiAgICAgIGZ1bmN0aW9uLlxuXG4gICAgICBgYGBqYXZhc2NyaXB0XG4gICAgICB2YXIgT3B0aW9uID0gZGFnZ3kudGFnZ2VkU3VtKHtcbiAgICAgICAgICBTb21lOiBbJ3gnXSxcbiAgICAgICAgICBOb25lOiBbXVxuICAgICAgfSk7XG5cbiAgICAgIE9wdGlvbi5Tb21lKDEpIGluc3RhbmNlb2YgT3B0aW9uLlNvbWU7IC8vIHRydWVcbiAgICAgIE9wdGlvbi5Tb21lKDEpIGluc3RhbmNlb2YgT3B0aW9uOyAvLyB0cnVlXG4gICAgICBPcHRpb24uTm9uZSBpbnN0YW5jZW9mIE9wdGlvbjsgLy8gdHJ1ZVxuXG4gICAgICBmdW5jdGlvbiBpbmNPclplcm8obykge1xuICAgICAgICAgIHJldHVybiBvLmNhdGEoe1xuICAgICAgICAgICAgICBTb21lOiBmdW5jdGlvbih4KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4geCArIDE7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIE5vbmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGluY09yWmVybyhPcHRpb24uU29tZSgxKSk7IC8vIDJcbiAgICAgIGluY09yWmVybyhPcHRpb24uTm9uZSk7IC8vIDBcbiAgICAgIGBgYFxuICAgICoqL1xuICAgIGZ1bmN0aW9uIHRhZ2dlZFN1bShjb25zdHJ1Y3RvcnMpIHtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmdW5jdGlvbiBkZWZpbml0aW9ucygpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RhZ2dlZCBzdW0gd2FzIGNhbGxlZCBpbnN0ZWFkIG9mIG9uZSBvZiBpdHMgcHJvcGVydGllcy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG1ha2VDYXRhKGtleSkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGRpc3BhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmllbGRzID0gY29uc3RydWN0b3JzW2tleV0sXG4gICAgICAgICAgICAgICAgICAgIGFyZ3MgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgaTtcblxuICAgICAgICAgICAgICAgIGlmKCFkaXNwYXRjaGVzW2tleV0pXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDb25zdHJ1Y3RvcnMgZ2l2ZW4gdG8gY2F0YSBkaWRuJ3QgaW5jbHVkZTogXCIgKyBrZXkpO1xuXG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZmllbGRzLmxlbmd0aDsgaSsrKVxuICAgICAgICAgICAgICAgICAgICBhcmdzLnB1c2godGhpc1tmaWVsZHNbaV1dKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBkaXNwYXRjaGVzW2tleV0uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbWFrZVByb3RvKGtleSkge1xuICAgICAgICAgICAgdmFyIHByb3RvID0gY3JlYXRlKGRlZmluaXRpb25zLnByb3RvdHlwZSk7XG4gICAgICAgICAgICBwcm90by5jYXRhID0gbWFrZUNhdGEoa2V5KTtcbiAgICAgICAgICAgIHJldHVybiBwcm90bztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihrZXkgaW4gY29uc3RydWN0b3JzKSB7XG4gICAgICAgICAgICBpZighY29uc3RydWN0b3JzW2tleV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGVmaW5pdGlvbnNba2V5XSA9IG1ha2VQcm90byhrZXkpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmaW5pdGlvbnNba2V5XSA9IHRhZ2dlZC5hcHBseShudWxsLCBjb25zdHJ1Y3RvcnNba2V5XSk7XG4gICAgICAgICAgICBkZWZpbml0aW9uc1trZXldLnByb3RvdHlwZSA9IG1ha2VQcm90byhrZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRlZmluaXRpb25zO1xuICAgIH1cbiAgICBleHBvcnRzLnRhZ2dlZFN1bSA9IHRhZ2dlZFN1bTtcbn0pO1xuIl19
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"ramda":[function(require,module,exports){
// Ramda v0.22.1
// https://github.com/ramda/ramda
// (c) 2013-2016 Scott Sauyet, Michael Hurley, and David Chambers
// Ramda may be freely distributed under the MIT license.
;(function() {
'use strict';
/**
* A special placeholder value used to specify "gaps" within curried functions,
* allowing partial application of any combination of arguments, regardless of
* their positions.
*
* If `g` is a curried ternary function and `_` is `R.__`, the following are
* equivalent:
*
* - `g(1, 2, 3)`
* - `g(_, 2, 3)(1)`
* - `g(_, _, 3)(1)(2)`
* - `g(_, _, 3)(1, 2)`
* - `g(_, 2, _)(1, 3)`
* - `g(_, 2)(1)(3)`
* - `g(_, 2)(1, 3)`
* - `g(_, 2)(_, 3)(1)`
*
* @constant
* @memberOf R
* @since v0.6.0
* @category Function
* @example
*
* var greet = R.replace('{name}', R.__, 'Hello, {name}!');
* greet('Alice'); //=> 'Hello, Alice!'
*/
var __ = { '@@functional/placeholder': true };
/* eslint-disable no-unused-vars */
var _arity = function _arity(n, fn) {
/* eslint-disable no-unused-vars */
switch (n) {
case 0:
return function () {
return fn.apply(this, arguments);
};
case 1:
return function (a0) {
return fn.apply(this, arguments);
};
case 2:
return function (a0, a1) {
return fn.apply(this, arguments);
};
case 3:
return function (a0, a1, a2) {
return fn.apply(this, arguments);
};
case 4:
return function (a0, a1, a2, a3) {
return fn.apply(this, arguments);
};
case 5:
return function (a0, a1, a2, a3, a4) {
return fn.apply(this, arguments);
};
case 6:
return function (a0, a1, a2, a3, a4, a5) {
return fn.apply(this, arguments);
};
case 7:
return function (a0, a1, a2, a3, a4, a5, a6) {
return fn.apply(this, arguments);
};
case 8:
return function (a0, a1, a2, a3, a4, a5, a6, a7) {
return fn.apply(this, arguments);
};
case 9:
return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) {
return fn.apply(this, arguments);
};
case 10:
return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
return fn.apply(this, arguments);
};
default:
throw new Error('First argument to _arity must be a non-negative integer no greater than ten');
}
};
var _arrayFromIterator = function _arrayFromIterator(iter) {
var list = [];
var next;
while (!(next = iter.next()).done) {
list.push(next.value);
}
return list;
};
var _arrayOf = function _arrayOf() {
return Array.prototype.slice.call(arguments);
};
var _cloneRegExp = function _cloneRegExp(pattern) {
return new RegExp(pattern.source, (pattern.global ? 'g' : '') + (pattern.ignoreCase ? 'i' : '') + (pattern.multiline ? 'm' : '') + (pattern.sticky ? 'y' : '') + (pattern.unicode ? 'u' : ''));
};
var _complement = function _complement(f) {
return function () {
return !f.apply(this, arguments);
};
};
/**
* Private `concat` function to merge two array-like objects.
*
* @private
* @param {Array|Arguments} [set1=[]] An array-like object.
* @param {Array|Arguments} [set2=[]] An array-like object.
* @return {Array} A new, merged array.
* @example
*
* _concat([4, 5, 6], [1, 2, 3]); //=> [4, 5, 6, 1, 2, 3]
*/
var _concat = function _concat(set1, set2) {
set1 = set1 || [];
set2 = set2 || [];
var idx;
var len1 = set1.length;
var len2 = set2.length;
var result = [];
idx = 0;
while (idx < len1) {
result[result.length] = set1[idx];
idx += 1;
}
idx = 0;
while (idx < len2) {
result[result.length] = set2[idx];
idx += 1;
}
return result;
};
var _containsWith = function _containsWith(pred, x, list) {
var idx = 0;
var len = list.length;
while (idx < len) {
if (pred(x, list[idx])) {
return true;
}
idx += 1;
}
return false;
};
var _filter = function _filter(fn, list) {
var idx = 0;
var len = list.length;
var result = [];
while (idx < len) {
if (fn(list[idx])) {
result[result.length] = list[idx];
}
idx += 1;
}
return result;
};
var _forceReduced = function _forceReduced(x) {
return {
'@@transducer/value': x,
'@@transducer/reduced': true
};
};
// String(x => x) evaluates to "x => x", so the pattern may not match.
var _functionName = function _functionName(f) {
// String(x => x) evaluates to "x => x", so the pattern may not match.
var match = String(f).match(/^function (\w*)/);
return match == null ? '' : match[1];
};
var _has = function _has(prop, obj) {
return Object.prototype.hasOwnProperty.call(obj, prop);
};
var _identity = function _identity(x) {
return x;
};
var _isArguments = function () {
var toString = Object.prototype.toString;
return toString.call(arguments) === '[object Arguments]' ? function _isArguments(x) {
return toString.call(x) === '[object Arguments]';
} : function _isArguments(x) {
return _has('callee', x);
};
}();
/**
* Tests whether or not an object is an array.
*
* @private
* @param {*} val The object to test.
* @return {Boolean} `true` if `val` is an array, `false` otherwise.
* @example
*
* _isArray([]); //=> true
* _isArray(null); //=> false
* _isArray({}); //=> false
*/
var _isArray = Array.isArray || function _isArray(val) {
return val != null && val.length >= 0 && Object.prototype.toString.call(val) === '[object Array]';
};
var _isFunction = function _isFunction(x) {
return Object.prototype.toString.call(x) === '[object Function]';
};
/**
* Determine if the passed argument is an integer.
*
* @private
* @param {*} n
* @category Type
* @return {Boolean}
*/
var _isInteger = Number.isInteger || function _isInteger(n) {
return n << 0 === n;
};
var _isNumber = function _isNumber(x) {
return Object.prototype.toString.call(x) === '[object Number]';
};
var _isObject = function _isObject(x) {
return Object.prototype.toString.call(x) === '[object Object]';
};
var _isPlaceholder = function _isPlaceholder(a) {
return a != null && typeof a === 'object' && a['@@functional/placeholder'] === true;
};
var _isRegExp = function _isRegExp(x) {
return Object.prototype.toString.call(x) === '[object RegExp]';
};
var _isString = function _isString(x) {
return Object.prototype.toString.call(x) === '[object String]';
};
var _isTransformer = function _isTransformer(obj) {
return typeof obj['@@transducer/step'] === 'function';
};
var _map = function _map(fn, functor) {
var idx = 0;
var len = functor.length;
var result = Array(len);
while (idx < len) {
result[idx] = fn(functor[idx]);
idx += 1;
}
return result;
};
// Based on https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
var _objectAssign = function _objectAssign(target) {
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
var idx = 1;
var length = arguments.length;
while (idx < length) {
var source = arguments[idx];
if (source != null) {
for (var nextKey in source) {
if (_has(nextKey, source)) {
output[nextKey] = source[nextKey];
}
}
}
idx += 1;
}
return output;
};
var _of = function _of(x) {
return [x];
};
var _pipe = function _pipe(f, g) {
return function () {
return g.call(this, f.apply(this, arguments));
};
};
var _pipeP = function _pipeP(f, g) {
return function () {
var ctx = this;
return f.apply(ctx, arguments).then(function (x) {
return g.call(ctx, x);
});
};
};
// \b matches word boundary; [\b] matches backspace
var _quote = function _quote(s) {
var escaped = s.replace(/\\/g, '\\\\').replace(/[\b]/g, '\\b') // \b matches word boundary; [\b] matches backspace
.replace(/\f/g, '\\f').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\t/g, '\\t').replace(/\v/g, '\\v').replace(/\0/g, '\\0');
return '"' + escaped.replace(/"/g, '\\"') + '"';
};
var _reduced = function _reduced(x) {
return x && x['@@transducer/reduced'] ? x : {
'@@transducer/value': x,
'@@transducer/reduced': true
};
};
/**
* An optimized, private array `slice` implementation.
*
* @private
* @param {Arguments|Array} args The array or arguments object to consider.
* @param {Number} [from=0] The array index to slice from, inclusive.
* @param {Number} [to=args.length] The array index to slice to, exclusive.
* @return {Array} A new, sliced array.
* @example
*
* _slice([1, 2, 3, 4, 5], 1, 3); //=> [2, 3]
*
* var firstThreeArgs = function(a, b, c, d) {
* return _slice(arguments, 0, 3);
* };
* firstThreeArgs(1, 2, 3, 4); //=> [1, 2, 3]
*/
var _slice = function _slice(args, from, to) {
switch (arguments.length) {
case 1:
return _slice(args, 0, args.length);
case 2:
return _slice(args, from, args.length);
default:
var list = [];
var idx = 0;
var len = Math.max(0, Math.min(args.length, to) - from);
while (idx < len) {
list[idx] = args[from + idx];
idx += 1;
}
return list;
}
};
/**
* Polyfill from <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString>.
*/
var _toISOString = function () {
var pad = function pad(n) {
return (n < 10 ? '0' : '') + n;
};
return typeof Date.prototype.toISOString === 'function' ? function _toISOString(d) {
return d.toISOString();
} : function _toISOString(d) {
return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + '.' + (d.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) + 'Z';
};
}();
var _xfBase = {
init: function () {
return this.xf['@@transducer/init']();
},
result: function (result) {
return this.xf['@@transducer/result'](result);
}
};
var _xwrap = function () {
function XWrap(fn) {
this.f = fn;
}
XWrap.prototype['@@transducer/init'] = function () {
throw new Error('init not implemented on XWrap');
};
XWrap.prototype['@@transducer/result'] = function (acc) {
return acc;
};
XWrap.prototype['@@transducer/step'] = function (acc, x) {
return this.f(acc, x);
};
return function _xwrap(fn) {
return new XWrap(fn);
};
}();
var _aperture = function _aperture(n, list) {
var idx = 0;
var limit = list.length - (n - 1);
var acc = new Array(limit >= 0 ? limit : 0);
while (idx < limit) {
acc[idx] = _slice(list, idx, idx + n);
idx += 1;
}
return acc;
};
var _assign = typeof Object.assign === 'function' ? Object.assign : _objectAssign;
/**
* Similar to hasMethod, this checks whether a function has a [methodname]
* function. If it isn't an array it will execute that function otherwise it
* will default to the ramda implementation.
*
* @private
* @param {Function} fn ramda implemtation
* @param {String} methodname property to check for a custom implementation
* @return {Object} Whatever the return value of the method is.
*/
var _checkForMethod = function _checkForMethod(methodname, fn) {
return function () {
var length = arguments.length;
if (length === 0) {
return fn();
}
var obj = arguments[length - 1];
return _isArray(obj) || typeof obj[methodname] !== 'function' ? fn.apply(this, arguments) : obj[methodname].apply(obj, _slice(arguments, 0, length - 1));
};
};
/**
* Optimized internal one-arity curry function.
*
* @private
* @category Function
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
var _curry1 = function _curry1(fn) {
return function f1(a) {
if (arguments.length === 0 || _isPlaceholder(a)) {
return f1;
} else {
return fn.apply(this, arguments);
}
};
};
/**
* Optimized internal two-arity curry function.
*
* @private
* @category Function
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
var _curry2 = function _curry2(fn) {
return function f2(a, b) {
switch (arguments.length) {
case 0:
return f2;
case 1:
return _isPlaceholder(a) ? f2 : _curry1(function (_b) {
return fn(a, _b);
});
default:
return _isPlaceholder(a) && _isPlaceholder(b) ? f2 : _isPlaceholder(a) ? _curry1(function (_a) {
return fn(_a, b);
}) : _isPlaceholder(b) ? _curry1(function (_b) {
return fn(a, _b);
}) : fn(a, b);
}
};
};
/**
* Optimized internal three-arity curry function.
*
* @private
* @category Function
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
var _curry3 = function _curry3(fn) {
return function f3(a, b, c) {
switch (arguments.length) {
case 0:
return f3;
case 1:
return _isPlaceholder(a) ? f3 : _curry2(function (_b, _c) {
return fn(a, _b, _c);
});
case 2:
return _isPlaceholder(a) && _isPlaceholder(b) ? f3 : _isPlaceholder(a) ? _curry2(function (_a, _c) {
return fn(_a, b, _c);
}) : _isPlaceholder(b) ? _curry2(function (_b, _c) {
return fn(a, _b, _c);
}) : _curry1(function (_c) {
return fn(a, b, _c);
});
default:
return _isPlaceholder(a) && _isPlaceholder(b) && _isPlaceholder(c) ? f3 : _isPlaceholder(a) && _isPlaceholder(b) ? _curry2(function (_a, _b) {
return fn(_a, _b, c);
}) : _isPlaceholder(a) && _isPlaceholder(c) ? _curry2(function (_a, _c) {
return fn(_a, b, _c);
}) : _isPlaceholder(b) && _isPlaceholder(c) ? _curry2(function (_b, _c) {
return fn(a, _b, _c);
}) : _isPlaceholder(a) ? _curry1(function (_a) {
return fn(_a, b, c);
}) : _isPlaceholder(b) ? _curry1(function (_b) {
return fn(a, _b, c);
}) : _isPlaceholder(c) ? _curry1(function (_c) {
return fn(a, b, _c);
}) : fn(a, b, c);
}
};
};
/**
* Internal curryN function.
*
* @private
* @category Function
* @param {Number} length The arity of the curried function.
* @param {Array} received An array of arguments received thus far.
* @param {Function} fn The function to curry.
* @return {Function} The curried function.
*/
var _curryN = function _curryN(length, received, fn) {
return function () {
var combined = [];
var argsIdx = 0;
var left = length;
var combinedIdx = 0;
while (combinedIdx < received.length || argsIdx < arguments.length) {
var result;
if (combinedIdx < received.length && (!_isPlaceholder(received[combinedIdx]) || argsIdx >= arguments.length)) {
result = received[combinedIdx];
} else {
result = arguments[argsIdx];
argsIdx += 1;
}
combined[combinedIdx] = result;
if (!_isPlaceholder(result)) {
left -= 1;
}
combinedIdx += 1;
}
return left <= 0 ? fn.apply(this, combined) : _arity(left, _curryN(length, combined, fn));
};
};
/**
* Returns a function that dispatches with different strategies based on the
* object in list position (last argument). If it is an array, executes [fn].
* Otherwise, if it has a function with [methodname], it will execute that
* function (functor case). Otherwise, if it is a transformer, uses transducer
* [xf] to return a new transformer (transducer case). Otherwise, it will
* default to executing [fn].
*
* @private
* @param {String} methodname property to check for a custom implementation
* @param {Function} xf transducer to initialize if object is transformer
* @param {Function} fn default ramda implementation
* @return {Function} A function that dispatches on object in list position
*/
var _dispatchable = function _dispatchable(methodname, xf, fn) {
return function () {
var length = arguments.length;
if (length === 0) {
return fn();
}
var obj = arguments[length - 1];
if (!_isArray(obj)) {
var args = _slice(arguments, 0, length - 1);
if (typeof obj[methodname] === 'function') {
return obj[methodname].apply(obj, args);
}
if (_isTransformer(obj)) {
var transducer = xf.apply(null, args);
return transducer(obj);
}
}
return fn.apply(this, arguments);
};
};
var _dropLastWhile = function dropLastWhile(pred, list) {
var idx = list.length - 1;
while (idx >= 0 && pred(list[idx])) {
idx -= 1;
}
return _slice(list, 0, idx + 1);
};
var _xall = function () {
function XAll(f, xf) {
this.xf = xf;
this.f = f;
this.all = true;
}
XAll.prototype['@@transducer/init'] = _xfBase.init;
XAll.prototype['@@transducer/result'] = function (result) {
if (this.all) {
result = this.xf['@@transducer/step'](result, true);
}
return this.xf['@@transducer/result'](result);
};
XAll.prototype['@@transducer/step'] = function (result, input) {
if (!this.f(input)) {
this.all = false;
result = _reduced(this.xf['@@transducer/step'](result, false));
}
return result;
};
return _curry2(function _xall(f, xf) {
return new XAll(f, xf);
});
}();
var _xany = function () {
function XAny(f, xf) {
this.xf = xf;
this.f = f;
this.any = false;
}
XAny.prototype['@@transducer/init'] = _xfBase.init;
XAny.prototype['@@transducer/result'] = function (result) {
if (!this.any) {
result = this.xf['@@transducer/step'](result, false);
}
return this.xf['@@transducer/result'](result);
};
XAny.prototype['@@transducer/step'] = function (result, input) {
if (this.f(input)) {
this.any = true;
result = _reduced(this.xf['@@transducer/step'](result, true));
}
return result;
};
return _curry2(function _xany(f, xf) {
return new XAny(f, xf);
});
}();
var _xaperture = function () {
function XAperture(n, xf) {
this.xf = xf;
this.pos = 0;
this.full = false;
this.acc = new Array(n);
}
XAperture.prototype['@@transducer/init'] = _xfBase.init;
XAperture.prototype['@@transducer/result'] = function (result) {
this.acc = null;
return this.xf['@@transducer/result'](result);
};
XAperture.prototype['@@transducer/step'] = function (result, input) {
this.store(input);
return this.full ? this.xf['@@transducer/step'](result, this.getCopy()) : result;
};
XAperture.prototype.store = function (input) {
this.acc[this.pos] = input;
this.pos += 1;
if (this.pos === this.acc.length) {
this.pos = 0;
this.full = true;
}
};
XAperture.prototype.getCopy = function () {
return _concat(_slice(this.acc, this.pos), _slice(this.acc, 0, this.pos));
};
return _curry2(function _xaperture(n, xf) {
return new XAperture(n, xf);
});
}();
var _xdrop = function () {
function XDrop(n, xf) {
this.xf = xf;
this.n = n;
}
XDrop.prototype['@@transducer/init'] = _xfBase.init;
XDrop.prototype['@@transducer/result'] = _xfBase.result;
XDrop.prototype['@@transducer/step'] = function (result, input) {
if (this.n > 0) {
this.n -= 1;
return result;
}
return this.xf['@@transducer/step'](result, input);
};
return _curry2(function _xdrop(n, xf) {
return new XDrop(n, xf);
});
}();
var _xdropLast = function () {
function XDropLast(n, xf) {
this.xf = xf;
this.pos = 0;
this.full = false;
this.acc = new Array(n);
}
XDropLast.prototype['@@transducer/init'] = _xfBase.init;
XDropLast.prototype['@@transducer/result'] = function (result) {
this.acc = null;
return this.xf['@@transducer/result'](result);
};
XDropLast.prototype['@@transducer/step'] = function (result, input) {
if (this.full) {
result = this.xf['@@transducer/step'](result, this.acc[this.pos]);
}
this.store(input);
return result;
};
XDropLast.prototype.store = function (input) {
this.acc[this.pos] = input;
this.pos += 1;
if (this.pos === this.acc.length) {
this.pos = 0;
this.full = true;
}
};
return _curry2(function _xdropLast(n, xf) {
return new XDropLast(n, xf);
});
}();
var _xdropRepeatsWith = function () {
function XDropRepeatsWith(pred, xf) {
this.xf = xf;
this.pred = pred;
this.lastValue = undefined;
this.seenFirstValue = false;
}
XDropRepeatsWith.prototype['@@transducer/init'] = function () {
return this.xf['@@transducer/init']();
};
XDropRepeatsWith.prototype['@@transducer/result'] = function (result) {
return this.xf['@@transducer/result'](result);
};
XDropRepeatsWith.prototype['@@transducer/step'] = function (result, input) {
var sameAsLast = false;
if (!this.seenFirstValue) {
this.seenFirstValue = true;
} else if (this.pred(this.lastValue, input)) {
sameAsLast = true;
}
this.lastValue = input;
return sameAsLast ? result : this.xf['@@transducer/step'](result, input);
};
return _curry2(function _xdropRepeatsWith(pred, xf) {
return new XDropRepeatsWith(pred, xf);
});
}();
var _xdropWhile = function () {
function XDropWhile(f, xf) {
this.xf = xf;
this.f = f;
}
XDropWhile.prototype['@@transducer/init'] = _xfBase.init;
XDropWhile.prototype['@@transducer/result'] = _xfBase.result;
XDropWhile.prototype['@@transducer/step'] = function (result, input) {
if (this.f) {
if (this.f(input)) {
return result;
}
this.f = null;
}
return this.xf['@@transducer/step'](result, input);
};
return _curry2(function _xdropWhile(f, xf) {
return new XDropWhile(f, xf);
});
}();
var _xfilter = function () {
function XFilter(f, xf) {
this.xf = xf;
this.f = f;
}
XFilter.prototype['@@transducer/init'] = _xfBase.init;
XFilter.prototype['@@transducer/result'] = _xfBase.result;
XFilter.prototype['@@transducer/step'] = function (result, input) {
return this.f(input) ? this.xf['@@transducer/step'](result, input) : result;
};
return _curry2(function _xfilter(f, xf) {
return new XFilter(f, xf);
});
}();
var _xfind = function () {
function XFind(f, xf) {
this.xf = xf;
this.f = f;
this.found = false;
}
XFind.prototype['@@transducer/init'] = _xfBase.init;
XFind.prototype['@@transducer/result'] = function (result) {
if (!this.found) {
result = this.xf['@@transducer/step'](result, void 0);
}
return this.xf['@@transducer/result'](result);
};
XFind.prototype['@@transducer/step'] = function (result, input) {
if (this.f(input)) {
this.found = true;
result = _reduced(this.xf['@@transducer/step'](result, input));
}
return result;
};
return _curry2(function _xfind(f, xf) {
return new XFind(f, xf);
});
}();
var _xfindIndex = function () {
function XFindIndex(f, xf) {
this.xf = xf;
this.f = f;
this.idx = -1;
this.found = false;
}
XFindIndex.prototype['@@transducer/init'] = _xfBase.init;
XFindIndex.prototype['@@transducer/result'] = function (result) {
if (!this.found) {
result = this.xf['@@transducer/step'](result, -1);
}
return this.xf['@@transducer/result'](result);
};
XFindIndex.prototype['@@transducer/step'] = function (result, input) {
this.idx += 1;
if (this.f(input)) {
this.found = true;
result = _reduced(this.xf['@@transducer/step'](result, this.idx));
}
return result;
};
return _curry2(function _xfindIndex(f, xf) {
return new XFindIndex(f, xf);
});
}();
var _xfindLast = function () {
function XFindLast(f, xf) {
this.xf = xf;
this.f = f;
}
XFindLast.prototype['@@transducer/init'] = _xfBase.init;
XFindLast.prototype['@@transducer/result'] = function (result) {
return this.xf['@@transducer/result'](this.xf['@@transducer/step'](result, this.last));
};
XFindLast.prototype['@@transducer/step'] = function (result, input) {
if (this.f(input)) {
this.last = input;
}
return result;
};
return _curry2(function _xfindLast(f, xf) {
return new XFindLast(f, xf);
});
}();
var _xfindLastIndex = function () {
function XFindLastIndex(f, xf) {
this.xf = xf;
this.f = f;
this.idx = -1;
this.lastIdx = -1;
}
XFindLastIndex.prototype['@@transducer/init'] = _xfBase.init;
XFindLastIndex.prototype['@@transducer/result'] = function (result) {
return this.xf['@@transducer/result'](this.xf['@@transducer/step'](result, this.lastIdx));
};
XFindLastIndex.prototype['@@transducer/step'] = function (result, input) {
this.idx += 1;
if (this.f(input)) {
this.lastIdx = this.idx;
}
return result;
};
return _curry2(function _xfindLastIndex(f, xf) {
return new XFindLastIndex(f, xf);
});
}();
var _xmap = function () {
function XMap(f, xf) {
this.xf = xf;
this.f = f;
}
XMap.prototype['@@transducer/init'] = _xfBase.init;
XMap.prototype['@@transducer/result'] = _xfBase.result;
XMap.prototype['@@transducer/step'] = function (result, input) {
return this.xf['@@transducer/step'](result, this.f(input));
};
return _curry2(function _xmap(f, xf) {
return new XMap(f, xf);
});
}();
var _xreduceBy = function () {
function XReduceBy(valueFn, valueAcc, keyFn, xf) {
this.valueFn = valueFn;
this.valueAcc = valueAcc;
this.keyFn = keyFn;
this.xf = xf;
this.inputs = {};
}
XReduceBy.prototype['@@transducer/init'] = _xfBase.init;
XReduceBy.prototype['@@transducer/result'] = function (result) {
var key;
for (key in this.inputs) {
if (_has(key, this.inputs)) {
result = this.xf['@@transducer/step'](result, this.inputs[key]);
if (result['@@transducer/reduced']) {
result = result['@@transducer/value'];
break;
}
}
}
this.inputs = null;
return this.xf['@@transducer/result'](result);
};
XReduceBy.prototype['@@transducer/step'] = function (result, input) {
var key = this.keyFn(input);
this.inputs[key] = this.inputs[key] || [
key,
this.valueAcc
];
this.inputs[key][1] = this.valueFn(this.inputs[key][1], input);
return result;
};
return _curryN(4, [], function _xreduceBy(valueFn, valueAcc, keyFn, xf) {
return new XReduceBy(valueFn, valueAcc, keyFn, xf);
});
}();
var _xtake = function () {
function XTake(n, xf) {
this.xf = xf;
this.n = n;
this.i = 0;
}
XTake.prototype['@@transducer/init'] = _xfBase.init;
XTake.prototype['@@transducer/result'] = _xfBase.result;
XTake.prototype['@@transducer/step'] = function (result, input) {
this.i += 1;
var ret = this.n === 0 ? result : this.xf['@@transducer/step'](result, input);
return this.i >= this.n ? _reduced(ret) : ret;
};
return _curry2(function _xtake(n, xf) {
return new XTake(n, xf);
});
}();
var _xtakeWhile = function () {
function XTakeWhile(f, xf) {
this.xf = xf;
this.f = f;
}
XTakeWhile.prototype['@@transducer/init'] = _xfBase.init;
XTakeWhile.prototype['@@transducer/result'] = _xfBase.result;
XTakeWhile.prototype['@@transducer/step'] = function (result, input) {
return this.f(input) ? this.xf['@@transducer/step'](result, input) : _reduced(result);
};
return _curry2(function _xtakeWhile(f, xf) {
return new XTakeWhile(f, xf);
});
}();
/**
* Adds two values.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a
* @param {Number} b
* @return {Number}
* @see R.subtract
* @example
*
* R.add(2, 3); //=> 5
* R.add(7)(10); //=> 17
*/
var add = _curry2(function add(a, b) {
return Number(a) + Number(b);
});
/**
* Applies a function to the value at the given index of an array, returning a
* new copy of the array with the element at the given index replaced with the
* result of the function application.
*
* @func
* @memberOf R
* @since v0.14.0
* @category List
* @sig (a -> a) -> Number -> [a] -> [a]
* @param {Function} fn The function to apply.
* @param {Number} idx The index.
* @param {Array|Arguments} list An array-like object whose value
* at the supplied index will be replaced.
* @return {Array} A copy of the supplied array-like object with
* the element at index `idx` replaced with the value
* returned by applying `fn` to the existing element.
* @see R.update
* @example
*
* R.adjust(R.add(10), 1, [0, 1, 2]); //=> [0, 11, 2]
* R.adjust(R.add(10))(1)([0, 1, 2]); //=> [0, 11, 2]
*/
var adjust = _curry3(function adjust(fn, idx, list) {
if (idx >= list.length || idx < -list.length) {
return list;
}
var start = idx < 0 ? list.length : 0;
var _idx = start + idx;
var _list = _concat(list);
_list[_idx] = fn(list[_idx]);
return _list;
});
/**
* Returns `true` if all elements of the list match the predicate, `false` if
* there are any that don't.
*
* Dispatches to the `all` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a -> Boolean) -> [a] -> Boolean
* @param {Function} fn The predicate function.
* @param {Array} list The array to consider.
* @return {Boolean} `true` if the predicate is satisfied by every element, `false`
* otherwise.
* @see R.any, R.none, R.transduce
* @example
*
* var lessThan2 = R.flip(R.lt)(2);
* var lessThan3 = R.flip(R.lt)(3);
* R.all(lessThan2)([1, 2]); //=> false
* R.all(lessThan3)([1, 2]); //=> true
*/
var all = _curry2(_dispatchable('all', _xall, function all(fn, list) {
var idx = 0;
while (idx < list.length) {
if (!fn(list[idx])) {
return false;
}
idx += 1;
}
return true;
}));
/**
* Returns a function that always returns the given value. Note that for
* non-primitives the value returned is a reference to the original value.
*
* This function is known as `const`, `constant`, or `K` (for K combinator) in
* other languages and libraries.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig a -> (* -> a)
* @param {*} val The value to wrap in a function
* @return {Function} A Function :: * -> val.
* @example
*
* var t = R.always('Tee');
* t(); //=> 'Tee'
*/
var always = _curry1(function always(val) {
return function () {
return val;
};
});
/**
* Returns `true` if both arguments are `true`; `false` otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Logic
* @sig * -> * -> *
* @param {Boolean} a A boolean value
* @param {Boolean} b A boolean value
* @return {Boolean} `true` if both arguments are `true`, `false` otherwise
* @see R.both
* @example
*
* R.and(true, true); //=> true
* R.and(true, false); //=> false
* R.and(false, true); //=> false
* R.and(false, false); //=> false
*/
var and = _curry2(function and(a, b) {
return a && b;
});
/**
* Returns `true` if at least one of elements of the list match the predicate,
* `false` otherwise.
*
* Dispatches to the `any` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a -> Boolean) -> [a] -> Boolean
* @param {Function} fn The predicate function.
* @param {Array} list The array to consider.
* @return {Boolean} `true` if the predicate is satisfied by at least one element, `false`
* otherwise.
* @see R.all, R.none, R.transduce
* @example
*
* var lessThan0 = R.flip(R.lt)(0);
* var lessThan2 = R.flip(R.lt)(2);
* R.any(lessThan0)([1, 2]); //=> false
* R.any(lessThan2)([1, 2]); //=> true
*/
var any = _curry2(_dispatchable('any', _xany, function any(fn, list) {
var idx = 0;
while (idx < list.length) {
if (fn(list[idx])) {
return true;
}
idx += 1;
}
return false;
}));
/**
* Returns a new list, composed of n-tuples of consecutive elements If `n` is
* greater than the length of the list, an empty list is returned.
*
* Dispatches to the `aperture` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.12.0
* @category List
* @sig Number -> [a] -> [[a]]
* @param {Number} n The size of the tuples to create
* @param {Array} list The list to split into `n`-tuples
* @return {Array} The new list.
* @see R.transduce
* @example
*
* R.aperture(2, [1, 2, 3, 4, 5]); //=> [[1, 2], [2, 3], [3, 4], [4, 5]]
* R.aperture(3, [1, 2, 3, 4, 5]); //=> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
* R.aperture(7, [1, 2, 3, 4, 5]); //=> []
*/
var aperture = _curry2(_dispatchable('aperture', _xaperture, _aperture));
/**
* Returns a new list containing the contents of the given list, followed by
* the given element.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig a -> [a] -> [a]
* @param {*} el The element to add to the end of the new list.
* @param {Array} list The list whose contents will be added to the beginning of the output
* list.
* @return {Array} A new list containing the contents of the old list followed by `el`.
* @see R.prepend
* @example
*
* R.append('tests', ['write', 'more']); //=> ['write', 'more', 'tests']
* R.append('tests', []); //=> ['tests']
* R.append(['tests'], ['write', 'more']); //=> ['write', 'more', ['tests']]
*/
var append = _curry2(function append(el, list) {
return _concat(list, [el]);
});
/**
* Applies function `fn` to the argument list `args`. This is useful for
* creating a fixed-arity function from a variadic function. `fn` should be a
* bound function if context is significant.
*
* @func
* @memberOf R
* @since v0.7.0
* @category Function
* @sig (*... -> a) -> [*] -> a
* @param {Function} fn
* @param {Array} args
* @return {*}
* @see R.call, R.unapply
* @example
*
* var nums = [1, 2, 3, -99, 42, 6, 7];
* R.apply(Math.max, nums); //=> 42
*/
var apply = _curry2(function apply(fn, args) {
return fn.apply(this, args);
});
/**
* Makes a shallow clone of an object, setting or overriding the specified
* property with the given value. Note that this copies and flattens prototype
* properties onto the new object as well. All non-primitive properties are
* copied by reference.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Object
* @sig String -> a -> {k: v} -> {k: v}
* @param {String} prop the property name to set
* @param {*} val the new value
* @param {Object} obj the object to clone
* @return {Object} a new object similar to the original except for the specified property.
* @see R.dissoc
* @example
*
* R.assoc('c', 3, {a: 1, b: 2}); //=> {a: 1, b: 2, c: 3}
*/
var assoc = _curry3(function assoc(prop, val, obj) {
var result = {};
for (var p in obj) {
result[p] = obj[p];
}
result[prop] = val;
return result;
});
/**
* Makes a shallow clone of an object, setting or overriding the nodes required
* to create the given path, and placing the specific value at the tail end of
* that path. Note that this copies and flattens prototype properties onto the
* new object as well. All non-primitive properties are copied by reference.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Object
* @sig [String] -> a -> {k: v} -> {k: v}
* @param {Array} path the path to set
* @param {*} val the new value
* @param {Object} obj the object to clone
* @return {Object} a new object similar to the original except along the specified path.
* @see R.dissocPath
* @example
*
* R.assocPath(['a', 'b', 'c'], 42, {a: {b: {c: 0}}}); //=> {a: {b: {c: 42}}}
*/
var assocPath = _curry3(function assocPath(path, val, obj) {
switch (path.length) {
case 0:
return val;
case 1:
return assoc(path[0], val, obj);
default:
return assoc(path[0], assocPath(_slice(path, 1), val, Object(obj[path[0]])), obj);
}
});
/**
* Creates a function that is bound to a context.
* Note: `R.bind` does not provide the additional argument-binding capabilities of
* [Function.prototype.bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
*
* @func
* @memberOf R
* @since v0.6.0
* @category Function
* @category Object
* @sig (* -> *) -> {*} -> (* -> *)
* @param {Function} fn The function to bind to context
* @param {Object} thisObj The context to bind `fn` to
* @return {Function} A function that will execute in the context of `thisObj`.
* @see R.partial
* @example
*
* var log = R.bind(console.log, console);
* R.pipe(R.assoc('a', 2), R.tap(log), R.assoc('a', 3))({a: 1}); //=> {a: 3}
* // logs {a: 2}
*/
var bind = _curry2(function bind(fn, thisObj) {
return _arity(fn.length, function () {
return fn.apply(thisObj, arguments);
});
});
/**
* Restricts a number to be within a range.
*
* Also works for other ordered types such as Strings and Dates.
*
* @func
* @memberOf R
* @since v0.20.0
* @category Relation
* @sig Ord a => a -> a -> a -> a
* @param {Number} minimum number
* @param {Number} maximum number
* @param {Number} value to be clamped
* @return {Number} Returns the clamped value
* @example
*
* R.clamp(1, 10, -1) // => 1
* R.clamp(1, 10, 11) // => 10
* R.clamp(1, 10, 4) // => 4
*/
var clamp = _curry3(function clamp(min, max, value) {
if (min > max) {
throw new Error('min must not be greater than max in clamp(min, max, value)');
}
return value < min ? min : value > max ? max : value;
});
/**
* Makes a comparator function out of a function that reports whether the first
* element is less than the second.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (a, b -> Boolean) -> (a, b -> Number)
* @param {Function} pred A predicate function of arity two.
* @return {Function} A Function :: a -> b -> Int that returns `-1` if a < b, `1` if b < a, otherwise `0`.
* @example
*
* var cmp = R.comparator((a, b) => a.age < b.age);
* var people = [
* // ...
* ];
* R.sort(cmp, people);
*/
var comparator = _curry1(function comparator(pred) {
return function (a, b) {
return pred(a, b) ? -1 : pred(b, a) ? 1 : 0;
};
});
/**
* Returns a curried equivalent of the provided function, with the specified
* arity. The curried function has two unusual capabilities. First, its
* arguments needn't be provided one at a time. If `g` is `R.curryN(3, f)`, the
* following are equivalent:
*
* - `g(1)(2)(3)`
* - `g(1)(2, 3)`
* - `g(1, 2)(3)`
* - `g(1, 2, 3)`
*
* Secondly, the special placeholder value `R.__` may be used to specify
* "gaps", allowing partial application of any combination of arguments,
* regardless of their positions. If `g` is as above and `_` is `R.__`, the
* following are equivalent:
*
* - `g(1, 2, 3)`
* - `g(_, 2, 3)(1)`
* - `g(_, _, 3)(1)(2)`
* - `g(_, _, 3)(1, 2)`
* - `g(_, 2)(1)(3)`
* - `g(_, 2)(1, 3)`
* - `g(_, 2)(_, 3)(1)`
*
* @func
* @memberOf R
* @since v0.5.0
* @category Function
* @sig Number -> (* -> a) -> (* -> a)
* @param {Number} length The arity for the returned function.
* @param {Function} fn The function to curry.
* @return {Function} A new, curried function.
* @see R.curry
* @example
*
* var sumArgs = (...args) => R.sum(args);
*
* var curriedAddFourNumbers = R.curryN(4, sumArgs);
* var f = curriedAddFourNumbers(1, 2);
* var g = f(3);
* g(4); //=> 10
*/
var curryN = _curry2(function curryN(length, fn) {
if (length === 1) {
return _curry1(fn);
}
return _arity(length, _curryN(length, [], fn));
});
/**
* Decrements its argument.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Math
* @sig Number -> Number
* @param {Number} n
* @return {Number}
* @see R.inc
* @example
*
* R.dec(42); //=> 41
*/
var dec = add(-1);
/**
* Returns the second argument if it is not `null`, `undefined` or `NaN`
* otherwise the first argument is returned.
*
* @func
* @memberOf R
* @since v0.10.0
* @category Logic
* @sig a -> b -> a | b
* @param {a} val The default value.
* @param {b} val The value to return if it is not null or undefined
* @return {*} The the second value or the default value
* @example
*
* var defaultTo42 = R.defaultTo(42);
*
* defaultTo42(null); //=> 42
* defaultTo42(undefined); //=> 42
* defaultTo42('Ramda'); //=> 'Ramda'
* defaultTo42(parseInt('string')); //=> 42
*/
var defaultTo = _curry2(function defaultTo(d, v) {
return v == null || v !== v ? d : v;
});
/**
* Finds the set (i.e. no duplicates) of all elements in the first list not
* contained in the second list. Duplication is determined according to the
* value returned by applying the supplied predicate to two list elements.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig (a -> a -> Boolean) -> [*] -> [*] -> [*]
* @param {Function} pred A predicate used to test whether two items are equal.
* @param {Array} list1 The first list.
* @param {Array} list2 The second list.
* @return {Array} The elements in `list1` that are not in `list2`.
* @see R.difference, R.symmetricDifference, R.symmetricDifferenceWith
* @example
*
* var cmp = (x, y) => x.a === y.a;
* var l1 = [{a: 1}, {a: 2}, {a: 3}];
* var l2 = [{a: 3}, {a: 4}];
* R.differenceWith(cmp, l1, l2); //=> [{a: 1}, {a: 2}]
*/
var differenceWith = _curry3(function differenceWith(pred, first, second) {
var out = [];
var idx = 0;
var firstLen = first.length;
while (idx < firstLen) {
if (!_containsWith(pred, first[idx], second) && !_containsWith(pred, first[idx], out)) {
out.push(first[idx]);
}
idx += 1;
}
return out;
});
/**
* Returns a new object that does not contain a `prop` property.
*
* @func
* @memberOf R
* @since v0.10.0
* @category Object
* @sig String -> {k: v} -> {k: v}
* @param {String} prop the name of the property to dissociate
* @param {Object} obj the object to clone
* @return {Object} a new object similar to the original but without the specified property
* @see R.assoc
* @example
*
* R.dissoc('b', {a: 1, b: 2, c: 3}); //=> {a: 1, c: 3}
*/
var dissoc = _curry2(function dissoc(prop, obj) {
var result = {};
for (var p in obj) {
if (p !== prop) {
result[p] = obj[p];
}
}
return result;
});
/**
* Makes a shallow clone of an object, omitting the property at the given path.
* Note that this copies and flattens prototype properties onto the new object
* as well. All non-primitive properties are copied by reference.
*
* @func
* @memberOf R
* @since v0.11.0
* @category Object
* @sig [String] -> {k: v} -> {k: v}
* @param {Array} path the path to set
* @param {Object} obj the object to clone
* @return {Object} a new object without the property at path
* @see R.assocPath
* @example
*
* R.dissocPath(['a', 'b', 'c'], {a: {b: {c: 42}}}); //=> {a: {b: {}}}
*/
var dissocPath = _curry2(function dissocPath(path, obj) {
switch (path.length) {
case 0:
return obj;
case 1:
return dissoc(path[0], obj);
default:
var head = path[0];
var tail = _slice(path, 1);
return obj[head] == null ? obj : assoc(head, dissocPath(tail, obj[head]), obj);
}
});
/**
* Divides two numbers. Equivalent to `a / b`.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a The first value.
* @param {Number} b The second value.
* @return {Number} The result of `a / b`.
* @see R.multiply
* @example
*
* R.divide(71, 100); //=> 0.71
*
* var half = R.divide(R.__, 2);
* half(42); //=> 21
*
* var reciprocal = R.divide(1);
* reciprocal(4); //=> 0.25
*/
var divide = _curry2(function divide(a, b) {
return a / b;
});
/**
* Returns a new list excluding the leading elements of a given list which
* satisfy the supplied predicate function. It passes each value to the supplied
* predicate function, skipping elements while the predicate function returns
* `true`. The predicate function is applied to one argument: *(value)*.
*
* Dispatches to the `dropWhile` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.9.0
* @category List
* @sig (a -> Boolean) -> [a] -> [a]
* @param {Function} fn The function called per iteration.
* @param {Array} list The collection to iterate over.
* @return {Array} A new array.
* @see R.takeWhile, R.transduce, R.addIndex
* @example
*
* var lteTwo = x => x <= 2;
*
* R.dropWhile(lteTwo, [1, 2, 3, 4, 3, 2, 1]); //=> [3, 4, 3, 2, 1]
*/
var dropWhile = _curry2(_dispatchable('dropWhile', _xdropWhile, function dropWhile(pred, list) {
var idx = 0;
var len = list.length;
while (idx < len && pred(list[idx])) {
idx += 1;
}
return _slice(list, idx);
}));
/**
* Returns the empty value of its argument's type. Ramda defines the empty
* value of Array (`[]`), Object (`{}`), String (`''`), and Arguments. Other
* types are supported if they define `<Type>.empty` and/or
* `<Type>.prototype.empty`.
*
* Dispatches to the `empty` method of the first argument, if present.
*
* @func
* @memberOf R
* @since v0.3.0
* @category Function
* @sig a -> a
* @param {*} x
* @return {*}
* @example
*
* R.empty(Just(42)); //=> Nothing()
* R.empty([1, 2, 3]); //=> []
* R.empty('unicorns'); //=> ''
* R.empty({x: 1, y: 2}); //=> {}
*/
// else
var empty = _curry1(function empty(x) {
return x != null && typeof x.empty === 'function' ? x.empty() : x != null && x.constructor != null && typeof x.constructor.empty === 'function' ? x.constructor.empty() : _isArray(x) ? [] : _isString(x) ? '' : _isObject(x) ? {} : _isArguments(x) ? function () {
return arguments;
}() : // else
void 0;
});
/**
* Creates a new object by recursively evolving a shallow copy of `object`,
* according to the `transformation` functions. All non-primitive properties
* are copied by reference.
*
* A `transformation` function will not be invoked if its corresponding key
* does not exist in the evolved object.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Object
* @sig {k: (v -> v)} -> {k: v} -> {k: v}
* @param {Object} transformations The object specifying transformation functions to apply
* to the object.
* @param {Object} object The object to be transformed.
* @return {Object} The transformed object.
* @example
*
* var tomato = {firstName: ' Tomato ', data: {elapsed: 100, remaining: 1400}, id:123};
* var transformations = {
* firstName: R.trim,
* lastName: R.trim, // Will not get invoked.
* data: {elapsed: R.add(1), remaining: R.add(-1)}
* };
* R.evolve(transformations, tomato); //=> {firstName: 'Tomato', data: {elapsed: 101, remaining: 1399}, id:123}
*/
var evolve = _curry2(function evolve(transformations, object) {
var result = {};
var transformation, key, type;
for (key in object) {
transformation = transformations[key];
type = typeof transformation;
result[key] = type === 'function' ? transformation(object[key]) : type === 'object' ? evolve(transformations[key], object[key]) : object[key];
}
return result;
});
/**
* Returns the first element of the list which matches the predicate, or
* `undefined` if no element matches.
*
* Dispatches to the `find` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a -> Boolean) -> [a] -> a | undefined
* @param {Function} fn The predicate function used to determine if the element is the
* desired one.
* @param {Array} list The array to consider.
* @return {Object} The element found, or `undefined`.
* @see R.transduce
* @example
*
* var xs = [{a: 1}, {a: 2}, {a: 3}];
* R.find(R.propEq('a', 2))(xs); //=> {a: 2}
* R.find(R.propEq('a', 4))(xs); //=> undefined
*/
var find = _curry2(_dispatchable('find', _xfind, function find(fn, list) {
var idx = 0;
var len = list.length;
while (idx < len) {
if (fn(list[idx])) {
return list[idx];
}
idx += 1;
}
}));
/**
* Returns the index of the first element of the list which matches the
* predicate, or `-1` if no element matches.
*
* Dispatches to the `findIndex` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.1
* @category List
* @sig (a -> Boolean) -> [a] -> Number
* @param {Function} fn The predicate function used to determine if the element is the
* desired one.
* @param {Array} list The array to consider.
* @return {Number} The index of the element found, or `-1`.
* @see R.transduce
* @example
*
* var xs = [{a: 1}, {a: 2}, {a: 3}];
* R.findIndex(R.propEq('a', 2))(xs); //=> 1
* R.findIndex(R.propEq('a', 4))(xs); //=> -1
*/
var findIndex = _curry2(_dispatchable('findIndex', _xfindIndex, function findIndex(fn, list) {
var idx = 0;
var len = list.length;
while (idx < len) {
if (fn(list[idx])) {
return idx;
}
idx += 1;
}
return -1;
}));
/**
* Returns the last element of the list which matches the predicate, or
* `undefined` if no element matches.
*
* Dispatches to the `findLast` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.1
* @category List
* @sig (a -> Boolean) -> [a] -> a | undefined
* @param {Function} fn The predicate function used to determine if the element is the
* desired one.
* @param {Array} list The array to consider.
* @return {Object} The element found, or `undefined`.
* @see R.transduce
* @example
*
* var xs = [{a: 1, b: 0}, {a:1, b: 1}];
* R.findLast(R.propEq('a', 1))(xs); //=> {a: 1, b: 1}
* R.findLast(R.propEq('a', 4))(xs); //=> undefined
*/
var findLast = _curry2(_dispatchable('findLast', _xfindLast, function findLast(fn, list) {
var idx = list.length - 1;
while (idx >= 0) {
if (fn(list[idx])) {
return list[idx];
}
idx -= 1;
}
}));
/**
* Returns the index of the last element of the list which matches the
* predicate, or `-1` if no element matches.
*
* Dispatches to the `findLastIndex` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.1
* @category List
* @sig (a -> Boolean) -> [a] -> Number
* @param {Function} fn The predicate function used to determine if the element is the
* desired one.
* @param {Array} list The array to consider.
* @return {Number} The index of the element found, or `-1`.
* @see R.transduce
* @example
*
* var xs = [{a: 1, b: 0}, {a:1, b: 1}];
* R.findLastIndex(R.propEq('a', 1))(xs); //=> 1
* R.findLastIndex(R.propEq('a', 4))(xs); //=> -1
*/
var findLastIndex = _curry2(_dispatchable('findLastIndex', _xfindLastIndex, function findLastIndex(fn, list) {
var idx = list.length - 1;
while (idx >= 0) {
if (fn(list[idx])) {
return idx;
}
idx -= 1;
}
return -1;
}));
/**
* Iterate over an input `list`, calling a provided function `fn` for each
* element in the list.
*
* `fn` receives one argument: *(value)*.
*
* Note: `R.forEach` does not skip deleted or unassigned indices (sparse
* arrays), unlike the native `Array.prototype.forEach` method. For more
* details on this behavior, see:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Description
*
* Also note that, unlike `Array.prototype.forEach`, Ramda's `forEach` returns
* the original array. In some libraries this function is named `each`.
*
* Dispatches to the `forEach` method of the second argument, if present.
*
* @func
* @memberOf R
* @since v0.1.1
* @category List
* @sig (a -> *) -> [a] -> [a]
* @param {Function} fn The function to invoke. Receives one argument, `value`.
* @param {Array} list The list to iterate over.
* @return {Array} The original list.
* @see R.addIndex
* @example
*
* var printXPlusFive = x => console.log(x + 5);
* R.forEach(printXPlusFive, [1, 2, 3]); //=> [1, 2, 3]
* // logs 6
* // logs 7
* // logs 8
*/
var forEach = _curry2(_checkForMethod('forEach', function forEach(fn, list) {
var len = list.length;
var idx = 0;
while (idx < len) {
fn(list[idx]);
idx += 1;
}
return list;
}));
/**
* Creates a new object from a list key-value pairs. If a key appears in
* multiple pairs, the rightmost pair is included in the object.
*
* @func
* @memberOf R
* @since v0.3.0
* @category List
* @sig [[k,v]] -> {k: v}
* @param {Array} pairs An array of two-element arrays that will be the keys and values of the output object.
* @return {Object} The object made by pairing up `keys` and `values`.
* @see R.toPairs, R.pair
* @example
*
* R.fromPairs([['a', 1], ['b', 2], ['c', 3]]); //=> {a: 1, b: 2, c: 3}
*/
var fromPairs = _curry1(function fromPairs(pairs) {
var result = {};
var idx = 0;
while (idx < pairs.length) {
result[pairs[idx][0]] = pairs[idx][1];
idx += 1;
}
return result;
});
/**
* Takes a list and returns a list of lists where each sublist's elements are
* all "equal" according to the provided equality function.
*
* @func
* @memberOf R
* @since v0.21.0
* @category List
* @sig ((a, a) → Boolean) → [a] → [[a]]
* @param {Function} fn Function for determining whether two given (adjacent)
* elements should be in the same group
* @param {Array} list The array to group. Also accepts a string, which will be
* treated as a list of characters.
* @return {List} A list that contains sublists of equal elements,
* whose concatenations are equal to the original list.
* @example
*
* R.groupWith(R.equals, [0, 1, 1, 2, 3, 5, 8, 13, 21])
* //=> [[0], [1, 1], [2], [3], [5], [8], [13], [21]]
*
* R.groupWith((a, b) => a % 2 === b % 2, [0, 1, 1, 2, 3, 5, 8, 13, 21])
* //=> [[0], [1, 1], [2], [3, 5], [8], [13, 21]]
*
* R.groupWith(R.eqBy(isVowel), 'aestiou')
* //=> ['ae', 'st', 'iou']
*/
var groupWith = _curry2(function (fn, list) {
var res = [];
var idx = 0;
var len = list.length;
while (idx < len) {
var nextidx = idx + 1;
while (nextidx < len && fn(list[idx], list[nextidx])) {
nextidx += 1;
}
res.push(list.slice(idx, nextidx));
idx = nextidx;
}
return res;
});
/**
* Returns `true` if the first argument is greater than the second; `false`
* otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord a => a -> a -> Boolean
* @param {*} a
* @param {*} b
* @return {Boolean}
* @see R.lt
* @example
*
* R.gt(2, 1); //=> true
* R.gt(2, 2); //=> false
* R.gt(2, 3); //=> false
* R.gt('a', 'z'); //=> false
* R.gt('z', 'a'); //=> true
*/
var gt = _curry2(function gt(a, b) {
return a > b;
});
/**
* Returns `true` if the first argument is greater than or equal to the second;
* `false` otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord a => a -> a -> Boolean
* @param {Number} a
* @param {Number} b
* @return {Boolean}
* @see R.lte
* @example
*
* R.gte(2, 1); //=> true
* R.gte(2, 2); //=> true
* R.gte(2, 3); //=> false
* R.gte('a', 'z'); //=> false
* R.gte('z', 'a'); //=> true
*/
var gte = _curry2(function gte(a, b) {
return a >= b;
});
/**
* Returns whether or not an object has an own property with the specified name
*
* @func
* @memberOf R
* @since v0.7.0
* @category Object
* @sig s -> {s: x} -> Boolean
* @param {String} prop The name of the property to check for.
* @param {Object} obj The object to query.
* @return {Boolean} Whether the property exists.
* @example
*
* var hasName = R.has('name');
* hasName({name: 'alice'}); //=> true
* hasName({name: 'bob'}); //=> true
* hasName({}); //=> false
*
* var point = {x: 0, y: 0};
* var pointHas = R.has(R.__, point);
* pointHas('x'); //=> true
* pointHas('y'); //=> true
* pointHas('z'); //=> false
*/
var has = _curry2(_has);
/**
* Returns whether or not an object or its prototype chain has a property with
* the specified name
*
* @func
* @memberOf R
* @since v0.7.0
* @category Object
* @sig s -> {s: x} -> Boolean
* @param {String} prop The name of the property to check for.
* @param {Object} obj The object to query.
* @return {Boolean} Whether the property exists.
* @example
*
* function Rectangle(width, height) {
* this.width = width;
* this.height = height;
* }
* Rectangle.prototype.area = function() {
* return this.width * this.height;
* };
*
* var square = new Rectangle(2, 2);
* R.hasIn('width', square); //=> true
* R.hasIn('area', square); //=> true
*/
var hasIn = _curry2(function hasIn(prop, obj) {
return prop in obj;
});
/**
* Returns true if its arguments are identical, false otherwise. Values are
* identical if they reference the same memory. `NaN` is identical to `NaN`;
* `0` and `-0` are not identical.
*
* @func
* @memberOf R
* @since v0.15.0
* @category Relation
* @sig a -> a -> Boolean
* @param {*} a
* @param {*} b
* @return {Boolean}
* @example
*
* var o = {};
* R.identical(o, o); //=> true
* R.identical(1, 1); //=> true
* R.identical(1, '1'); //=> false
* R.identical([], []); //=> false
* R.identical(0, -0); //=> false
* R.identical(NaN, NaN); //=> true
*/
// SameValue algorithm
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
// Step 6.a: NaN == NaN
var identical = _curry2(function identical(a, b) {
// SameValue algorithm
if (a === b) {
// Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return a !== 0 || 1 / a === 1 / b;
} else {
// Step 6.a: NaN == NaN
return a !== a && b !== b;
}
});
/**
* A function that does nothing but return the parameter supplied to it. Good
* as a default or placeholder function.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig a -> a
* @param {*} x The value to return.
* @return {*} The input value, `x`.
* @example
*
* R.identity(1); //=> 1
*
* var obj = {};
* R.identity(obj) === obj; //=> true
*/
var identity = _curry1(_identity);
/**
* Creates a function that will process either the `onTrue` or the `onFalse`
* function depending upon the result of the `condition` predicate.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Logic
* @sig (*... -> Boolean) -> (*... -> *) -> (*... -> *) -> (*... -> *)
* @param {Function} condition A predicate function
* @param {Function} onTrue A function to invoke when the `condition` evaluates to a truthy value.
* @param {Function} onFalse A function to invoke when the `condition` evaluates to a falsy value.
* @return {Function} A new unary function that will process either the `onTrue` or the `onFalse`
* function depending upon the result of the `condition` predicate.
* @see R.unless, R.when
* @example
*
* var incCount = R.ifElse(
* R.has('count'),
* R.over(R.lensProp('count'), R.inc),
* R.assoc('count', 1)
* );
* incCount({}); //=> { count: 1 }
* incCount({ count: 1 }); //=> { count: 2 }
*/
var ifElse = _curry3(function ifElse(condition, onTrue, onFalse) {
return curryN(Math.max(condition.length, onTrue.length, onFalse.length), function _ifElse() {
return condition.apply(this, arguments) ? onTrue.apply(this, arguments) : onFalse.apply(this, arguments);
});
});
/**
* Increments its argument.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Math
* @sig Number -> Number
* @param {Number} n
* @return {Number}
* @see R.dec
* @example
*
* R.inc(42); //=> 43
*/
var inc = add(1);
/**
* Inserts the supplied element into the list, at index `index`. _Note that
* this is not destructive_: it returns a copy of the list with the changes.
* <small>No lists have been harmed in the application of this function.</small>
*
* @func
* @memberOf R
* @since v0.2.2
* @category List
* @sig Number -> a -> [a] -> [a]
* @param {Number} index The position to insert the element
* @param {*} elt The element to insert into the Array
* @param {Array} list The list to insert into
* @return {Array} A new Array with `elt` inserted at `index`.
* @example
*
* R.insert(2, 'x', [1,2,3,4]); //=> [1,2,'x',3,4]
*/
var insert = _curry3(function insert(idx, elt, list) {
idx = idx < list.length && idx >= 0 ? idx : list.length;
var result = _slice(list);
result.splice(idx, 0, elt);
return result;
});
/**
* Inserts the sub-list into the list, at index `index`. _Note that this is not
* destructive_: it returns a copy of the list with the changes.
* <small>No lists have been harmed in the application of this function.</small>
*
* @func
* @memberOf R
* @since v0.9.0
* @category List
* @sig Number -> [a] -> [a] -> [a]
* @param {Number} index The position to insert the sub-list
* @param {Array} elts The sub-list to insert into the Array
* @param {Array} list The list to insert the sub-list into
* @return {Array} A new Array with `elts` inserted starting at `index`.
* @example
*
* R.insertAll(2, ['x','y','z'], [1,2,3,4]); //=> [1,2,'x','y','z',3,4]
*/
var insertAll = _curry3(function insertAll(idx, elts, list) {
idx = idx < list.length && idx >= 0 ? idx : list.length;
return _concat(_concat(_slice(list, 0, idx), elts), _slice(list, idx));
});
/**
* Creates a new list with the separator interposed between elements.
*
* Dispatches to the `intersperse` method of the second argument, if present.
*
* @func
* @memberOf R
* @since v0.14.0
* @category List
* @sig a -> [a] -> [a]
* @param {*} separator The element to add to the list.
* @param {Array} list The list to be interposed.
* @return {Array} The new list.
* @example
*
* R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']
*/
var intersperse = _curry2(_checkForMethod('intersperse', function intersperse(separator, list) {
var out = [];
var idx = 0;
var length = list.length;
while (idx < length) {
if (idx === length - 1) {
out.push(list[idx]);
} else {
out.push(list[idx], separator);
}
idx += 1;
}
return out;
}));
/**
* See if an object (`val`) is an instance of the supplied constructor. This
* function will check up the inheritance chain, if any.
*
* @func
* @memberOf R
* @since v0.3.0
* @category Type
* @sig (* -> {*}) -> a -> Boolean
* @param {Object} ctor A constructor
* @param {*} val The value to test
* @return {Boolean}
* @example
*
* R.is(Object, {}); //=> true
* R.is(Number, 1); //=> true
* R.is(Object, 1); //=> false
* R.is(String, 's'); //=> true
* R.is(String, new String('')); //=> true
* R.is(Object, new String('')); //=> true
* R.is(Object, 's'); //=> false
* R.is(Number, {}); //=> false
*/
var is = _curry2(function is(Ctor, val) {
return val != null && val.constructor === Ctor || val instanceof Ctor;
});
/**
* Tests whether or not an object is similar to an array.
*
* @func
* @memberOf R
* @since v0.5.0
* @category Type
* @category List
* @sig * -> Boolean
* @param {*} x The object to test.
* @return {Boolean} `true` if `x` has a numeric length property and extreme indices defined; `false` otherwise.
* @example
*
* R.isArrayLike([]); //=> true
* R.isArrayLike(true); //=> false
* R.isArrayLike({}); //=> false
* R.isArrayLike({length: 10}); //=> false
* R.isArrayLike({0: 'zero', 9: 'nine', length: 10}); //=> true
*/
var isArrayLike = _curry1(function isArrayLike(x) {
if (_isArray(x)) {
return true;
}
if (!x) {
return false;
}
if (typeof x !== 'object') {
return false;
}
if (_isString(x)) {
return false;
}
if (x.nodeType === 1) {
return !!x.length;
}
if (x.length === 0) {
return true;
}
if (x.length > 0) {
return x.hasOwnProperty(0) && x.hasOwnProperty(x.length - 1);
}
return false;
});
/**
* Checks if the input value is `null` or `undefined`.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Type
* @sig * -> Boolean
* @param {*} x The value to test.
* @return {Boolean} `true` if `x` is `undefined` or `null`, otherwise `false`.
* @example
*
* R.isNil(null); //=> true
* R.isNil(undefined); //=> true
* R.isNil(0); //=> false
* R.isNil([]); //=> false
*/
var isNil = _curry1(function isNil(x) {
return x == null;
});
/**
* Returns a list containing the names of all the enumerable own properties of
* the supplied object.
* Note that the order of the output array is not guaranteed to be consistent
* across different JS platforms.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig {k: v} -> [k]
* @param {Object} obj The object to extract properties from
* @return {Array} An array of the object's own properties.
* @example
*
* R.keys({a: 1, b: 2, c: 3}); //=> ['a', 'b', 'c']
*/
// cover IE < 9 keys issues
// Safari bug
var keys = function () {
// cover IE < 9 keys issues
var hasEnumBug = !{ toString: null }.propertyIsEnumerable('toString');
var nonEnumerableProps = [
'constructor',
'valueOf',
'isPrototypeOf',
'toString',
'propertyIsEnumerable',
'hasOwnProperty',
'toLocaleString'
];
// Safari bug
var hasArgsEnumBug = function () {
'use strict';
return arguments.propertyIsEnumerable('length');
}();
var contains = function contains(list, item) {
var idx = 0;
while (idx < list.length) {
if (list[idx] === item) {
return true;
}
idx += 1;
}
return false;
};
return typeof Object.keys === 'function' && !hasArgsEnumBug ? _curry1(function keys(obj) {
return Object(obj) !== obj ? [] : Object.keys(obj);
}) : _curry1(function keys(obj) {
if (Object(obj) !== obj) {
return [];
}
var prop, nIdx;
var ks = [];
var checkArgsLength = hasArgsEnumBug && _isArguments(obj);
for (prop in obj) {
if (_has(prop, obj) && (!checkArgsLength || prop !== 'length')) {
ks[ks.length] = prop;
}
}
if (hasEnumBug) {
nIdx = nonEnumerableProps.length - 1;
while (nIdx >= 0) {
prop = nonEnumerableProps[nIdx];
if (_has(prop, obj) && !contains(ks, prop)) {
ks[ks.length] = prop;
}
nIdx -= 1;
}
}
return ks;
});
}();
/**
* Returns a list containing the names of all the properties of the supplied
* object, including prototype properties.
* Note that the order of the output array is not guaranteed to be consistent
* across different JS platforms.
*
* @func
* @memberOf R
* @since v0.2.0
* @category Object
* @sig {k: v} -> [k]
* @param {Object} obj The object to extract properties from
* @return {Array} An array of the object's own and prototype properties.
* @example
*
* var F = function() { this.x = 'X'; };
* F.prototype.y = 'Y';
* var f = new F();
* R.keysIn(f); //=> ['x', 'y']
*/
var keysIn = _curry1(function keysIn(obj) {
var prop;
var ks = [];
for (prop in obj) {
ks[ks.length] = prop;
}
return ks;
});
/**
* Returns the number of elements in the array by returning `list.length`.
*
* @func
* @memberOf R
* @since v0.3.0
* @category List
* @sig [a] -> Number
* @param {Array} list The array to inspect.
* @return {Number} The length of the array.
* @example
*
* R.length([]); //=> 0
* R.length([1, 2, 3]); //=> 3
*/
var length = _curry1(function length(list) {
return list != null && _isNumber(list.length) ? list.length : NaN;
});
/**
* Returns `true` if the first argument is less than the second; `false`
* otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord a => a -> a -> Boolean
* @param {*} a
* @param {*} b
* @return {Boolean}
* @see R.gt
* @example
*
* R.lt(2, 1); //=> false
* R.lt(2, 2); //=> false
* R.lt(2, 3); //=> true
* R.lt('a', 'z'); //=> true
* R.lt('z', 'a'); //=> false
*/
var lt = _curry2(function lt(a, b) {
return a < b;
});
/**
* Returns `true` if the first argument is less than or equal to the second;
* `false` otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord a => a -> a -> Boolean
* @param {Number} a
* @param {Number} b
* @return {Boolean}
* @see R.gte
* @example
*
* R.lte(2, 1); //=> false
* R.lte(2, 2); //=> true
* R.lte(2, 3); //=> true
* R.lte('a', 'z'); //=> true
* R.lte('z', 'a'); //=> false
*/
var lte = _curry2(function lte(a, b) {
return a <= b;
});
/**
* The mapAccum function behaves like a combination of map and reduce; it
* applies a function to each element of a list, passing an accumulating
* parameter from left to right, and returning a final value of this
* accumulator together with the new list.
*
* The iterator function receives two arguments, *acc* and *value*, and should
* return a tuple *[acc, value]*.
*
* @func
* @memberOf R
* @since v0.10.0
* @category List
* @sig (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
* @param {Function} fn The function to be called on every element of the input `list`.
* @param {*} acc The accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.addIndex
* @example
*
* var digits = ['1', '2', '3', '4'];
* var appender = (a, b) => [a + b, a + b];
*
* R.mapAccum(appender, 0, digits); //=> ['01234', ['01', '012', '0123', '01234']]
*/
var mapAccum = _curry3(function mapAccum(fn, acc, list) {
var idx = 0;
var len = list.length;
var result = [];
var tuple = [acc];
while (idx < len) {
tuple = fn(tuple[0], list[idx]);
result[idx] = tuple[1];
idx += 1;
}
return [
tuple[0],
result
];
});
/**
* The mapAccumRight function behaves like a combination of map and reduce; it
* applies a function to each element of a list, passing an accumulating
* parameter from right to left, and returning a final value of this
* accumulator together with the new list.
*
* Similar to `mapAccum`, except moves through the input list from the right to
* the left.
*
* The iterator function receives two arguments, *acc* and *value*, and should
* return a tuple *[acc, value]*.
*
* @func
* @memberOf R
* @since v0.10.0
* @category List
* @sig (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
* @param {Function} fn The function to be called on every element of the input `list`.
* @param {*} acc The accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.addIndex
* @example
*
* var digits = ['1', '2', '3', '4'];
* var append = (a, b) => [a + b, a + b];
*
* R.mapAccumRight(append, 0, digits); //=> ['04321', ['04321', '0432', '043', '04']]
*/
var mapAccumRight = _curry3(function mapAccumRight(fn, acc, list) {
var idx = list.length - 1;
var result = [];
var tuple = [acc];
while (idx >= 0) {
tuple = fn(tuple[0], list[idx]);
result[idx] = tuple[1];
idx -= 1;
}
return [
tuple[0],
result
];
});
/**
* Tests a regular expression against a String. Note that this function will
* return an empty array when there are no matches. This differs from
* [`String.prototype.match`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match)
* which returns `null` when there are no matches.
*
* @func
* @memberOf R
* @since v0.1.0
* @category String
* @sig RegExp -> String -> [String | Undefined]
* @param {RegExp} rx A regular expression.
* @param {String} str The string to match against
* @return {Array} The list of matches or empty array.
* @see R.test
* @example
*
* R.match(/([a-z]a)/g, 'bananas'); //=> ['ba', 'na', 'na']
* R.match(/a/, 'b'); //=> []
* R.match(/a/, null); //=> TypeError: null does not have a method named "match"
*/
var match = _curry2(function match(rx, str) {
return str.match(rx) || [];
});
/**
* mathMod behaves like the modulo operator should mathematically, unlike the
* `%` operator (and by extension, R.modulo). So while "-17 % 5" is -2,
* mathMod(-17, 5) is 3. mathMod requires Integer arguments, and returns NaN
* when the modulus is zero or negative.
*
* @func
* @memberOf R
* @since v0.3.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} m The dividend.
* @param {Number} p the modulus.
* @return {Number} The result of `b mod a`.
* @example
*
* R.mathMod(-17, 5); //=> 3
* R.mathMod(17, 5); //=> 2
* R.mathMod(17, -5); //=> NaN
* R.mathMod(17, 0); //=> NaN
* R.mathMod(17.2, 5); //=> NaN
* R.mathMod(17, 5.3); //=> NaN
*
* var clock = R.mathMod(R.__, 12);
* clock(15); //=> 3
* clock(24); //=> 0
*
* var seventeenMod = R.mathMod(17);
* seventeenMod(3); //=> 2
* seventeenMod(4); //=> 1
* seventeenMod(10); //=> 7
*/
var mathMod = _curry2(function mathMod(m, p) {
if (!_isInteger(m)) {
return NaN;
}
if (!_isInteger(p) || p < 1) {
return NaN;
}
return (m % p + p) % p;
});
/**
* Returns the larger of its two arguments.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord a => a -> a -> a
* @param {*} a
* @param {*} b
* @return {*}
* @see R.maxBy, R.min
* @example
*
* R.max(789, 123); //=> 789
* R.max('a', 'b'); //=> 'b'
*/
var max = _curry2(function max(a, b) {
return b > a ? b : a;
});
/**
* Takes a function and two values, and returns whichever value produces the
* larger result when passed to the provided function.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Relation
* @sig Ord b => (a -> b) -> a -> a -> a
* @param {Function} f
* @param {*} a
* @param {*} b
* @return {*}
* @see R.max, R.minBy
* @example
*
* // square :: Number -> Number
* var square = n => n * n;
*
* R.maxBy(square, -3, 2); //=> -3
*
* R.reduce(R.maxBy(square), 0, [3, -5, 4, 1, -2]); //=> -5
* R.reduce(R.maxBy(square), 0, []); //=> 0
*/
var maxBy = _curry3(function maxBy(f, a, b) {
return f(b) > f(a) ? b : a;
});
/**
* Create a new object with the own properties of the first object merged with
* the own properties of the second object. If a key exists in both objects,
* the value from the second object will be used.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig {k: v} -> {k: v} -> {k: v}
* @param {Object} l
* @param {Object} r
* @return {Object}
* @see R.mergeWith, R.mergeWithKey
* @example
*
* R.merge({ 'name': 'fred', 'age': 10 }, { 'age': 40 });
* //=> { 'name': 'fred', 'age': 40 }
*
* var resetToDefault = R.merge(R.__, {x: 0});
* resetToDefault({x: 5, y: 2}); //=> {x: 0, y: 2}
*/
var merge = _curry2(function merge(l, r) {
return _assign({}, l, r);
});
/**
* Merges a list of objects together into one object.
*
* @func
* @memberOf R
* @since v0.10.0
* @category List
* @sig [{k: v}] -> {k: v}
* @param {Array} list An array of objects
* @return {Object} A merged object.
* @see R.reduce
* @example
*
* R.mergeAll([{foo:1},{bar:2},{baz:3}]); //=> {foo:1,bar:2,baz:3}
* R.mergeAll([{foo:1},{foo:2},{bar:2}]); //=> {foo:2,bar:2}
*/
var mergeAll = _curry1(function mergeAll(list) {
return _assign.apply(null, [{}].concat(list));
});
/**
* Creates a new object with the own properties of the two provided objects. If
* a key exists in both objects, the provided function is applied to the key
* and the values associated with the key in each object, with the result being
* used as the value associated with the key in the returned object. The key
* will be excluded from the returned object if the resulting value is
* `undefined`.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Object
* @sig (String -> a -> a -> a) -> {a} -> {a} -> {a}
* @param {Function} fn
* @param {Object} l
* @param {Object} r
* @return {Object}
* @see R.merge, R.mergeWith
* @example
*
* let concatValues = (k, l, r) => k == 'values' ? R.concat(l, r) : r
* R.mergeWithKey(concatValues,
* { a: true, thing: 'foo', values: [10, 20] },
* { b: true, thing: 'bar', values: [15, 35] });
* //=> { a: true, b: true, thing: 'bar', values: [10, 20, 15, 35] }
*/
var mergeWithKey = _curry3(function mergeWithKey(fn, l, r) {
var result = {};
var k;
for (k in l) {
if (_has(k, l)) {
result[k] = _has(k, r) ? fn(k, l[k], r[k]) : l[k];
}
}
for (k in r) {
if (_has(k, r) && !_has(k, result)) {
result[k] = r[k];
}
}
return result;
});
/**
* Returns the smaller of its two arguments.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord a => a -> a -> a
* @param {*} a
* @param {*} b
* @return {*}
* @see R.minBy, R.max
* @example
*
* R.min(789, 123); //=> 123
* R.min('a', 'b'); //=> 'a'
*/
var min = _curry2(function min(a, b) {
return b < a ? b : a;
});
/**
* Takes a function and two values, and returns whichever value produces the
* smaller result when passed to the provided function.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Relation
* @sig Ord b => (a -> b) -> a -> a -> a
* @param {Function} f
* @param {*} a
* @param {*} b
* @return {*}
* @see R.min, R.maxBy
* @example
*
* // square :: Number -> Number
* var square = n => n * n;
*
* R.minBy(square, -3, 2); //=> 2
*
* R.reduce(R.minBy(square), Infinity, [3, -5, 4, 1, -2]); //=> 1
* R.reduce(R.minBy(square), Infinity, []); //=> Infinity
*/
var minBy = _curry3(function minBy(f, a, b) {
return f(b) < f(a) ? b : a;
});
/**
* Divides the first parameter by the second and returns the remainder. Note
* that this function preserves the JavaScript-style behavior for modulo. For
* mathematical modulo see `mathMod`.
*
* @func
* @memberOf R
* @since v0.1.1
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a The value to the divide.
* @param {Number} b The pseudo-modulus
* @return {Number} The result of `b % a`.
* @see R.mathMod
* @example
*
* R.modulo(17, 3); //=> 2
* // JS behavior:
* R.modulo(-17, 3); //=> -2
* R.modulo(17, -3); //=> 2
*
* var isOdd = R.modulo(R.__, 2);
* isOdd(42); //=> 0
* isOdd(21); //=> 1
*/
var modulo = _curry2(function modulo(a, b) {
return a % b;
});
/**
* Multiplies two numbers. Equivalent to `a * b` but curried.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a The first value.
* @param {Number} b The second value.
* @return {Number} The result of `a * b`.
* @see R.divide
* @example
*
* var double = R.multiply(2);
* var triple = R.multiply(3);
* double(3); //=> 6
* triple(4); //=> 12
* R.multiply(2, 5); //=> 10
*/
var multiply = _curry2(function multiply(a, b) {
return a * b;
});
/**
* Wraps a function of any arity (including nullary) in a function that accepts
* exactly `n` parameters. Any extraneous parameters will not be passed to the
* supplied function.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig Number -> (* -> a) -> (* -> a)
* @param {Number} n The desired arity of the new function.
* @param {Function} fn The function to wrap.
* @return {Function} A new function wrapping `fn`. The new function is guaranteed to be of
* arity `n`.
* @example
*
* var takesTwoArgs = (a, b) => [a, b];
*
* takesTwoArgs.length; //=> 2
* takesTwoArgs(1, 2); //=> [1, 2]
*
* var takesOneArg = R.nAry(1, takesTwoArgs);
* takesOneArg.length; //=> 1
* // Only `n` arguments are passed to the wrapped function
* takesOneArg(1, 2); //=> [1, undefined]
*/
var nAry = _curry2(function nAry(n, fn) {
switch (n) {
case 0:
return function () {
return fn.call(this);
};
case 1:
return function (a0) {
return fn.call(this, a0);
};
case 2:
return function (a0, a1) {
return fn.call(this, a0, a1);
};
case 3:
return function (a0, a1, a2) {
return fn.call(this, a0, a1, a2);
};
case 4:
return function (a0, a1, a2, a3) {
return fn.call(this, a0, a1, a2, a3);
};
case 5:
return function (a0, a1, a2, a3, a4) {
return fn.call(this, a0, a1, a2, a3, a4);
};
case 6:
return function (a0, a1, a2, a3, a4, a5) {
return fn.call(this, a0, a1, a2, a3, a4, a5);
};
case 7:
return function (a0, a1, a2, a3, a4, a5, a6) {
return fn.call(this, a0, a1, a2, a3, a4, a5, a6);
};
case 8:
return function (a0, a1, a2, a3, a4, a5, a6, a7) {
return fn.call(this, a0, a1, a2, a3, a4, a5, a6, a7);
};
case 9:
return function (a0, a1, a2, a3, a4, a5, a6, a7, a8) {
return fn.call(this, a0, a1, a2, a3, a4, a5, a6, a7, a8);
};
case 10:
return function (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
return fn.call(this, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
};
default:
throw new Error('First argument to nAry must be a non-negative integer no greater than ten');
}
});
/**
* Negates its argument.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Math
* @sig Number -> Number
* @param {Number} n
* @return {Number}
* @example
*
* R.negate(42); //=> -42
*/
var negate = _curry1(function negate(n) {
return -n;
});
/**
* Returns `true` if no elements of the list match the predicate, `false`
* otherwise.
*
* Dispatches to the `any` method of the second argument, if present.
*
* @func
* @memberOf R
* @since v0.12.0
* @category List
* @sig (a -> Boolean) -> [a] -> Boolean
* @param {Function} fn The predicate function.
* @param {Array} list The array to consider.
* @return {Boolean} `true` if the predicate is not satisfied by every element, `false` otherwise.
* @see R.all, R.any
* @example
*
* var isEven = n => n % 2 === 0;
*
* R.none(isEven, [1, 3, 5, 7, 9, 11]); //=> true
* R.none(isEven, [1, 3, 5, 7, 8, 11]); //=> false
*/
var none = _curry2(_complement(_dispatchable('any', _xany, any)));
/**
* A function that returns the `!` of its argument. It will return `true` when
* passed false-y value, and `false` when passed a truth-y one.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Logic
* @sig * -> Boolean
* @param {*} a any value
* @return {Boolean} the logical inverse of passed argument.
* @see R.complement
* @example
*
* R.not(true); //=> false
* R.not(false); //=> true
* R.not(0); //=> true
* R.not(1); //=> false
*/
var not = _curry1(function not(a) {
return !a;
});
/**
* Returns the nth element of the given list or string. If n is negative the
* element at index length + n is returned.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Number -> [a] -> a | Undefined
* @sig Number -> String -> String
* @param {Number} offset
* @param {*} list
* @return {*}
* @example
*
* var list = ['foo', 'bar', 'baz', 'quux'];
* R.nth(1, list); //=> 'bar'
* R.nth(-1, list); //=> 'quux'
* R.nth(-99, list); //=> undefined
*
* R.nth(2, 'abc'); //=> 'c'
* R.nth(3, 'abc'); //=> ''
*/
var nth = _curry2(function nth(offset, list) {
var idx = offset < 0 ? list.length + offset : offset;
return _isString(list) ? list.charAt(idx) : list[idx];
});
/**
* Returns a function which returns its nth argument.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Function
* @sig Number -> *... -> *
* @param {Number} n
* @return {Function}
* @example
*
* R.nthArg(1)('a', 'b', 'c'); //=> 'b'
* R.nthArg(-1)('a', 'b', 'c'); //=> 'c'
*/
var nthArg = _curry1(function nthArg(n) {
var arity = n < 0 ? 1 : n + 1;
return curryN(arity, function () {
return nth(n, arguments);
});
});
/**
* Creates an object containing a single key:value pair.
*
* @func
* @memberOf R
* @since v0.18.0
* @category Object
* @sig String -> a -> {String:a}
* @param {String} key
* @param {*} val
* @return {Object}
* @see R.pair
* @example
*
* var matchPhrases = R.compose(
* R.objOf('must'),
* R.map(R.objOf('match_phrase'))
* );
* matchPhrases(['foo', 'bar', 'baz']); //=> {must: [{match_phrase: 'foo'}, {match_phrase: 'bar'}, {match_phrase: 'baz'}]}
*/
var objOf = _curry2(function objOf(key, val) {
var obj = {};
obj[key] = val;
return obj;
});
/**
* Returns a singleton array containing the value provided.
*
* Note this `of` is different from the ES6 `of`; See
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/of
*
* @func
* @memberOf R
* @since v0.3.0
* @category Function
* @sig a -> [a]
* @param {*} x any value
* @return {Array} An array wrapping `x`.
* @example
*
* R.of(null); //=> [null]
* R.of([42]); //=> [[42]]
*/
var of = _curry1(_of);
/**
* Accepts a function `fn` and returns a function that guards invocation of
* `fn` such that `fn` can only ever be called once, no matter how many times
* the returned function is invoked. The first value calculated is returned in
* subsequent invocations.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (a... -> b) -> (a... -> b)
* @param {Function} fn The function to wrap in a call-only-once wrapper.
* @return {Function} The wrapped function.
* @example
*
* var addOneOnce = R.once(x => x + 1);
* addOneOnce(10); //=> 11
* addOneOnce(addOneOnce(50)); //=> 11
*/
var once = _curry1(function once(fn) {
var called = false;
var result;
return _arity(fn.length, function () {
if (called) {
return result;
}
called = true;
result = fn.apply(this, arguments);
return result;
});
});
/**
* Returns `true` if one or both of its arguments are `true`. Returns `false`
* if both arguments are `false`.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Logic
* @sig * -> * -> *
* @param {Boolean} a A boolean value
* @param {Boolean} b A boolean value
* @return {Boolean} `true` if one or both arguments are `true`, `false` otherwise
* @see R.either
* @example
*
* R.or(true, true); //=> true
* R.or(true, false); //=> true
* R.or(false, true); //=> true
* R.or(false, false); //=> false
*/
var or = _curry2(function or(a, b) {
return a || b;
});
/**
* Returns the result of "setting" the portion of the given data structure
* focused by the given lens to the result of applying the given function to
* the focused value.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig Lens s a -> (a -> a) -> s -> s
* @param {Lens} lens
* @param {*} v
* @param {*} x
* @return {*}
* @see R.prop, R.lensIndex, R.lensProp
* @example
*
* var headLens = R.lensIndex(0);
*
* R.over(headLens, R.toUpper, ['foo', 'bar', 'baz']); //=> ['FOO', 'bar', 'baz']
*/
// `Identity` is a functor that holds a single value, where `map` simply
// transforms the held value with the provided function.
// The value returned by the getter function is first transformed with `f`,
// then set as the value of an `Identity`. This is then mapped over with the
// setter function of the lens.
var over = function () {
// `Identity` is a functor that holds a single value, where `map` simply
// transforms the held value with the provided function.
var Identity = function (x) {
return {
value: x,
map: function (f) {
return Identity(f(x));
}
};
};
return _curry3(function over(lens, f, x) {
// The value returned by the getter function is first transformed with `f`,
// then set as the value of an `Identity`. This is then mapped over with the
// setter function of the lens.
return lens(function (y) {
return Identity(f(y));
})(x).value;
});
}();
/**
* Takes two arguments, `fst` and `snd`, and returns `[fst, snd]`.
*
* @func
* @memberOf R
* @since v0.18.0
* @category List
* @sig a -> b -> (a,b)
* @param {*} fst
* @param {*} snd
* @return {Array}
* @see R.objOf, R.of
* @example
*
* R.pair('foo', 'bar'); //=> ['foo', 'bar']
*/
var pair = _curry2(function pair(fst, snd) {
return [
fst,
snd
];
});
/**
* Retrieve the value at a given path.
*
* @func
* @memberOf R
* @since v0.2.0
* @category Object
* @sig [String] -> {k: v} -> v | Undefined
* @param {Array} path The path to use.
* @param {Object} obj The object to retrieve the nested property from.
* @return {*} The data at `path`.
* @see R.prop
* @example
*
* R.path(['a', 'b'], {a: {b: 2}}); //=> 2
* R.path(['a', 'b'], {c: {b: 2}}); //=> undefined
*/
var path = _curry2(function path(paths, obj) {
var val = obj;
var idx = 0;
while (idx < paths.length) {
if (val == null) {
return;
}
val = val[paths[idx]];
idx += 1;
}
return val;
});
/**
* If the given, non-null object has a value at the given path, returns the
* value at that path. Otherwise returns the provided default value.
*
* @func
* @memberOf R
* @since v0.18.0
* @category Object
* @sig a -> [String] -> Object -> a
* @param {*} d The default value.
* @param {Array} p The path to use.
* @param {Object} obj The object to retrieve the nested property from.
* @return {*} The data at `path` of the supplied object or the default value.
* @example
*
* R.pathOr('N/A', ['a', 'b'], {a: {b: 2}}); //=> 2
* R.pathOr('N/A', ['a', 'b'], {c: {b: 2}}); //=> "N/A"
*/
var pathOr = _curry3(function pathOr(d, p, obj) {
return defaultTo(d, path(p, obj));
});
/**
* Returns `true` if the specified object property at given path satisfies the
* given predicate; `false` otherwise.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Logic
* @sig (a -> Boolean) -> [String] -> Object -> Boolean
* @param {Function} pred
* @param {Array} propPath
* @param {*} obj
* @return {Boolean}
* @see R.propSatisfies, R.path
* @example
*
* R.pathSatisfies(y => y > 0, ['x', 'y'], {x: {y: 2}}); //=> true
*/
var pathSatisfies = _curry3(function pathSatisfies(pred, propPath, obj) {
return propPath.length > 0 && pred(path(propPath, obj));
});
/**
* Returns a partial copy of an object containing only the keys specified. If
* the key does not exist, the property is ignored.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig [k] -> {k: v} -> {k: v}
* @param {Array} names an array of String property names to copy onto a new object
* @param {Object} obj The object to copy from
* @return {Object} A new object with only properties from `names` on it.
* @see R.omit, R.props
* @example
*
* R.pick(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1, d: 4}
* R.pick(['a', 'e', 'f'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1}
*/
var pick = _curry2(function pick(names, obj) {
var result = {};
var idx = 0;
while (idx < names.length) {
if (names[idx] in obj) {
result[names[idx]] = obj[names[idx]];
}
idx += 1;
}
return result;
});
/**
* Similar to `pick` except that this one includes a `key: undefined` pair for
* properties that don't exist.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig [k] -> {k: v} -> {k: v}
* @param {Array} names an array of String property names to copy onto a new object
* @param {Object} obj The object to copy from
* @return {Object} A new object with only properties from `names` on it.
* @see R.pick
* @example
*
* R.pickAll(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1, d: 4}
* R.pickAll(['a', 'e', 'f'], {a: 1, b: 2, c: 3, d: 4}); //=> {a: 1, e: undefined, f: undefined}
*/
var pickAll = _curry2(function pickAll(names, obj) {
var result = {};
var idx = 0;
var len = names.length;
while (idx < len) {
var name = names[idx];
result[name] = obj[name];
idx += 1;
}
return result;
});
/**
* Returns a partial copy of an object containing only the keys that satisfy
* the supplied predicate.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Object
* @sig (v, k -> Boolean) -> {k: v} -> {k: v}
* @param {Function} pred A predicate to determine whether or not a key
* should be included on the output object.
* @param {Object} obj The object to copy from
* @return {Object} A new object with only properties that satisfy `pred`
* on it.
* @see R.pick, R.filter
* @example
*
* var isUpperCase = (val, key) => key.toUpperCase() === key;
* R.pickBy(isUpperCase, {a: 1, b: 2, A: 3, B: 4}); //=> {A: 3, B: 4}
*/
var pickBy = _curry2(function pickBy(test, obj) {
var result = {};
for (var prop in obj) {
if (test(obj[prop], prop, obj)) {
result[prop] = obj[prop];
}
}
return result;
});
/**
* Returns a new list with the given element at the front, followed by the
* contents of the list.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig a -> [a] -> [a]
* @param {*} el The item to add to the head of the output list.
* @param {Array} list The array to add to the tail of the output list.
* @return {Array} A new array.
* @see R.append
* @example
*
* R.prepend('fee', ['fi', 'fo', 'fum']); //=> ['fee', 'fi', 'fo', 'fum']
*/
var prepend = _curry2(function prepend(el, list) {
return _concat([el], list);
});
/**
* Returns a function that when supplied an object returns the indicated
* property of that object, if it exists.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig s -> {s: a} -> a | Undefined
* @param {String} p The property name
* @param {Object} obj The object to query
* @return {*} The value at `obj.p`.
* @see R.path
* @example
*
* R.prop('x', {x: 100}); //=> 100
* R.prop('x', {}); //=> undefined
*/
var prop = _curry2(function prop(p, obj) {
return obj[p];
});
/**
* Returns `true` if the specified object property is of the given type;
* `false` otherwise.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Type
* @sig Type -> String -> Object -> Boolean
* @param {Function} type
* @param {String} name
* @param {*} obj
* @return {Boolean}
* @see R.is, R.propSatisfies
* @example
*
* R.propIs(Number, 'x', {x: 1, y: 2}); //=> true
* R.propIs(Number, 'x', {x: 'foo'}); //=> false
* R.propIs(Number, 'x', {}); //=> false
*/
var propIs = _curry3(function propIs(type, name, obj) {
return is(type, obj[name]);
});
/**
* If the given, non-null object has an own property with the specified name,
* returns the value of that property. Otherwise returns the provided default
* value.
*
* @func
* @memberOf R
* @since v0.6.0
* @category Object
* @sig a -> String -> Object -> a
* @param {*} val The default value.
* @param {String} p The name of the property to return.
* @param {Object} obj The object to query.
* @return {*} The value of given property of the supplied object or the default value.
* @example
*
* var alice = {
* name: 'ALICE',
* age: 101
* };
* var favorite = R.prop('favoriteLibrary');
* var favoriteWithDefault = R.propOr('Ramda', 'favoriteLibrary');
*
* favorite(alice); //=> undefined
* favoriteWithDefault(alice); //=> 'Ramda'
*/
var propOr = _curry3(function propOr(val, p, obj) {
return obj != null && _has(p, obj) ? obj[p] : val;
});
/**
* Returns `true` if the specified object property satisfies the given
* predicate; `false` otherwise.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Logic
* @sig (a -> Boolean) -> String -> {String: a} -> Boolean
* @param {Function} pred
* @param {String} name
* @param {*} obj
* @return {Boolean}
* @see R.propEq, R.propIs
* @example
*
* R.propSatisfies(x => x > 0, 'x', {x: 1, y: 2}); //=> true
*/
var propSatisfies = _curry3(function propSatisfies(pred, name, obj) {
return pred(obj[name]);
});
/**
* Acts as multiple `prop`: array of keys in, array of values out. Preserves
* order.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig [k] -> {k: v} -> [v]
* @param {Array} ps The property names to fetch
* @param {Object} obj The object to query
* @return {Array} The corresponding values or partially applied function.
* @example
*
* R.props(['x', 'y'], {x: 1, y: 2}); //=> [1, 2]
* R.props(['c', 'a', 'b'], {b: 2, a: 1}); //=> [undefined, 1, 2]
*
* var fullName = R.compose(R.join(' '), R.props(['first', 'last']));
* fullName({last: 'Bullet-Tooth', age: 33, first: 'Tony'}); //=> 'Tony Bullet-Tooth'
*/
var props = _curry2(function props(ps, obj) {
var len = ps.length;
var out = [];
var idx = 0;
while (idx < len) {
out[idx] = obj[ps[idx]];
idx += 1;
}
return out;
});
/**
* Returns a list of numbers from `from` (inclusive) to `to` (exclusive).
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Number -> Number -> [Number]
* @param {Number} from The first number in the list.
* @param {Number} to One more than the last number in the list.
* @return {Array} The list of numbers in tthe set `[a, b)`.
* @example
*
* R.range(1, 5); //=> [1, 2, 3, 4]
* R.range(50, 53); //=> [50, 51, 52]
*/
var range = _curry2(function range(from, to) {
if (!(_isNumber(from) && _isNumber(to))) {
throw new TypeError('Both arguments to range must be numbers');
}
var result = [];
var n = from;
while (n < to) {
result.push(n);
n += 1;
}
return result;
});
/**
* Returns a single item by iterating through the list, successively calling
* the iterator function and passing it an accumulator value and the current
* value from the array, and then passing the result to the next call.
*
* Similar to `reduce`, except moves through the input list from the right to
* the left.
*
* The iterator function receives two values: *(acc, value)*
*
* Note: `R.reduceRight` does not skip deleted or unassigned indices (sparse
* arrays), unlike the native `Array.prototype.reduce` method. For more details
* on this behavior, see:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight#Description
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a,b -> a) -> a -> [b] -> a
* @param {Function} fn The iterator function. Receives two values, the accumulator and the
* current element from the array.
* @param {*} acc The accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.addIndex
* @example
*
* var pairs = [ ['a', 1], ['b', 2], ['c', 3] ];
* var flattenPairs = (acc, pair) => acc.concat(pair);
*
* R.reduceRight(flattenPairs, [], pairs); //=> [ 'c', 3, 'b', 2, 'a', 1 ]
*/
var reduceRight = _curry3(function reduceRight(fn, acc, list) {
var idx = list.length - 1;
while (idx >= 0) {
acc = fn(acc, list[idx]);
idx -= 1;
}
return acc;
});
/**
* Returns a value wrapped to indicate that it is the final value of the reduce
* and transduce functions. The returned value should be considered a black
* box: the internal structure is not guaranteed to be stable.
*
* Note: this optimization is unavailable to functions not explicitly listed
* above. For instance, it is not currently supported by reduceRight.
*
* @func
* @memberOf R
* @since v0.15.0
* @category List
* @sig a -> *
* @param {*} x The final value of the reduce.
* @return {*} The wrapped value.
* @see R.reduce, R.transduce
* @example
*
* R.reduce(
* R.pipe(R.add, R.when(R.gte(R.__, 10), R.reduced)),
* 0,
* [1, 2, 3, 4, 5]) // 10
*/
var reduced = _curry1(_reduced);
/**
* Removes the sub-list of `list` starting at index `start` and containing
* `count` elements. _Note that this is not destructive_: it returns a copy of
* the list with the changes.
* <small>No lists have been harmed in the application of this function.</small>
*
* @func
* @memberOf R
* @since v0.2.2
* @category List
* @sig Number -> Number -> [a] -> [a]
* @param {Number} start The position to start removing elements
* @param {Number} count The number of elements to remove
* @param {Array} list The list to remove from
* @return {Array} A new Array with `count` elements from `start` removed.
* @example
*
* R.remove(2, 3, [1,2,3,4,5,6,7,8]); //=> [1,2,6,7,8]
*/
var remove = _curry3(function remove(start, count, list) {
return _concat(_slice(list, 0, Math.min(start, list.length)), _slice(list, Math.min(list.length, start + count)));
});
/**
* Replace a substring or regex match in a string with a replacement.
*
* @func
* @memberOf R
* @since v0.7.0
* @category String
* @sig RegExp|String -> String -> String -> String
* @param {RegExp|String} pattern A regular expression or a substring to match.
* @param {String} replacement The string to replace the matches with.
* @param {String} str The String to do the search and replacement in.
* @return {String} The result.
* @example
*
* R.replace('foo', 'bar', 'foo foo foo'); //=> 'bar foo foo'
* R.replace(/foo/, 'bar', 'foo foo foo'); //=> 'bar foo foo'
*
* // Use the "g" (global) flag to replace all occurrences:
* R.replace(/foo/g, 'bar', 'foo foo foo'); //=> 'bar bar bar'
*/
var replace = _curry3(function replace(regex, replacement, str) {
return str.replace(regex, replacement);
});
/**
* Returns a new list or string with the elements or characters in reverse
* order.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [a]
* @sig String -> String
* @param {Array|String} list
* @return {Array|String}
* @example
*
* R.reverse([1, 2, 3]); //=> [3, 2, 1]
* R.reverse([1, 2]); //=> [2, 1]
* R.reverse([1]); //=> [1]
* R.reverse([]); //=> []
*
* R.reverse('abc'); //=> 'cba'
* R.reverse('ab'); //=> 'ba'
* R.reverse('a'); //=> 'a'
* R.reverse(''); //=> ''
*/
var reverse = _curry1(function reverse(list) {
return _isString(list) ? list.split('').reverse().join('') : _slice(list).reverse();
});
/**
* Scan is similar to reduce, but returns a list of successively reduced values
* from the left
*
* @func
* @memberOf R
* @since v0.10.0
* @category List
* @sig (a,b -> a) -> a -> [b] -> [a]
* @param {Function} fn The iterator function. Receives two values, the accumulator and the
* current element from the array
* @param {*} acc The accumulator value.
* @param {Array} list The list to iterate over.
* @return {Array} A list of all intermediately reduced values.
* @example
*
* var numbers = [1, 2, 3, 4];
* var factorials = R.scan(R.multiply, 1, numbers); //=> [1, 1, 2, 6, 24]
*/
var scan = _curry3(function scan(fn, acc, list) {
var idx = 0;
var len = list.length;
var result = [acc];
while (idx < len) {
acc = fn(acc, list[idx]);
result[idx + 1] = acc;
idx += 1;
}
return result;
});
/**
* Returns the result of "setting" the portion of the given data structure
* focused by the given lens to the given value.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig Lens s a -> a -> s -> s
* @param {Lens} lens
* @param {*} v
* @param {*} x
* @return {*}
* @see R.prop, R.lensIndex, R.lensProp
* @example
*
* var xLens = R.lensProp('x');
*
* R.set(xLens, 4, {x: 1, y: 2}); //=> {x: 4, y: 2}
* R.set(xLens, 8, {x: 1, y: 2}); //=> {x: 8, y: 2}
*/
var set = _curry3(function set(lens, v, x) {
return over(lens, always(v), x);
});
/**
* Returns the elements of the given list or string (or object with a `slice`
* method) from `fromIndex` (inclusive) to `toIndex` (exclusive).
*
* Dispatches to the `slice` method of the third argument, if present.
*
* @func
* @memberOf R
* @since v0.1.4
* @category List
* @sig Number -> Number -> [a] -> [a]
* @sig Number -> Number -> String -> String
* @param {Number} fromIndex The start index (inclusive).
* @param {Number} toIndex The end index (exclusive).
* @param {*} list
* @return {*}
* @example
*
* R.slice(1, 3, ['a', 'b', 'c', 'd']); //=> ['b', 'c']
* R.slice(1, Infinity, ['a', 'b', 'c', 'd']); //=> ['b', 'c', 'd']
* R.slice(0, -1, ['a', 'b', 'c', 'd']); //=> ['a', 'b', 'c']
* R.slice(-3, -1, ['a', 'b', 'c', 'd']); //=> ['b', 'c']
* R.slice(0, 3, 'ramda'); //=> 'ram'
*/
var slice = _curry3(_checkForMethod('slice', function slice(fromIndex, toIndex, list) {
return Array.prototype.slice.call(list, fromIndex, toIndex);
}));
/**
* Returns a copy of the list, sorted according to the comparator function,
* which should accept two values at a time and return a negative number if the
* first value is smaller, a positive number if it's larger, and zero if they
* are equal. Please note that this is a **copy** of the list. It does not
* modify the original.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a,a -> Number) -> [a] -> [a]
* @param {Function} comparator A sorting function :: a -> b -> Int
* @param {Array} list The list to sort
* @return {Array} a new array with its elements sorted by the comparator function.
* @example
*
* var diff = function(a, b) { return a - b; };
* R.sort(diff, [4,2,7,5]); //=> [2, 4, 5, 7]
*/
var sort = _curry2(function sort(comparator, list) {
return _slice(list).sort(comparator);
});
/**
* Sorts the list according to the supplied function.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig Ord b => (a -> b) -> [a] -> [a]
* @param {Function} fn
* @param {Array} list The list to sort.
* @return {Array} A new list sorted by the keys generated by `fn`.
* @example
*
* var sortByFirstItem = R.sortBy(R.prop(0));
* var sortByNameCaseInsensitive = R.sortBy(R.compose(R.toLower, R.prop('name')));
* var pairs = [[-1, 1], [-2, 2], [-3, 3]];
* sortByFirstItem(pairs); //=> [[-3, 3], [-2, 2], [-1, 1]]
* var alice = {
* name: 'ALICE',
* age: 101
* };
* var bob = {
* name: 'Bob',
* age: -10
* };
* var clara = {
* name: 'clara',
* age: 314.159
* };
* var people = [clara, bob, alice];
* sortByNameCaseInsensitive(people); //=> [alice, bob, clara]
*/
var sortBy = _curry2(function sortBy(fn, list) {
return _slice(list).sort(function (a, b) {
var aa = fn(a);
var bb = fn(b);
return aa < bb ? -1 : aa > bb ? 1 : 0;
});
});
/**
* Splits a given list or string at a given index.
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig Number -> [a] -> [[a], [a]]
* @sig Number -> String -> [String, String]
* @param {Number} index The index where the array/string is split.
* @param {Array|String} array The array/string to be split.
* @return {Array}
* @example
*
* R.splitAt(1, [1, 2, 3]); //=> [[1], [2, 3]]
* R.splitAt(5, 'hello world'); //=> ['hello', ' world']
* R.splitAt(-1, 'foobar'); //=> ['fooba', 'r']
*/
var splitAt = _curry2(function splitAt(index, array) {
return [
slice(0, index, array),
slice(index, length(array), array)
];
});
/**
* Splits a collection into slices of the specified length.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig Number -> [a] -> [[a]]
* @sig Number -> String -> [String]
* @param {Number} n
* @param {Array} list
* @return {Array}
* @example
*
* R.splitEvery(3, [1, 2, 3, 4, 5, 6, 7]); //=> [[1, 2, 3], [4, 5, 6], [7]]
* R.splitEvery(3, 'foobarbaz'); //=> ['foo', 'bar', 'baz']
*/
var splitEvery = _curry2(function splitEvery(n, list) {
if (n <= 0) {
throw new Error('First argument to splitEvery must be a positive integer');
}
var result = [];
var idx = 0;
while (idx < list.length) {
result.push(slice(idx, idx += n, list));
}
return result;
});
/**
* Takes a list and a predicate and returns a pair of lists with the following properties:
*
* - the result of concatenating the two output lists is equivalent to the input list;
* - none of the elements of the first output list satisfies the predicate; and
* - if the second output list is non-empty, its first element satisfies the predicate.
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig (a -> Boolean) -> [a] -> [[a], [a]]
* @param {Function} pred The predicate that determines where the array is split.
* @param {Array} list The array to be split.
* @return {Array}
* @example
*
* R.splitWhen(R.equals(2), [1, 2, 3, 1, 2, 3]); //=> [[1], [2, 3, 1, 2, 3]]
*/
var splitWhen = _curry2(function splitWhen(pred, list) {
var idx = 0;
var len = list.length;
var prefix = [];
while (idx < len && !pred(list[idx])) {
prefix.push(list[idx]);
idx += 1;
}
return [
prefix,
_slice(list, idx)
];
});
/**
* Subtracts its second argument from its first argument.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a The first value.
* @param {Number} b The second value.
* @return {Number} The result of `a - b`.
* @see R.add
* @example
*
* R.subtract(10, 8); //=> 2
*
* var minus5 = R.subtract(R.__, 5);
* minus5(17); //=> 12
*
* var complementaryAngle = R.subtract(90);
* complementaryAngle(30); //=> 60
* complementaryAngle(72); //=> 18
*/
var subtract = _curry2(function subtract(a, b) {
return Number(a) - Number(b);
});
/**
* Returns all but the first element of the given list or string (or object
* with a `tail` method).
*
* Dispatches to the `slice` method of the first argument, if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [a]
* @sig String -> String
* @param {*} list
* @return {*}
* @see R.head, R.init, R.last
* @example
*
* R.tail([1, 2, 3]); //=> [2, 3]
* R.tail([1, 2]); //=> [2]
* R.tail([1]); //=> []
* R.tail([]); //=> []
*
* R.tail('abc'); //=> 'bc'
* R.tail('ab'); //=> 'b'
* R.tail('a'); //=> ''
* R.tail(''); //=> ''
*/
var tail = _checkForMethod('tail', slice(1, Infinity));
/**
* Returns the first `n` elements of the given list, string, or
* transducer/transformer (or object with a `take` method).
*
* Dispatches to the `take` method of the second argument, if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Number -> [a] -> [a]
* @sig Number -> String -> String
* @param {Number} n
* @param {*} list
* @return {*}
* @see R.drop
* @example
*
* R.take(1, ['foo', 'bar', 'baz']); //=> ['foo']
* R.take(2, ['foo', 'bar', 'baz']); //=> ['foo', 'bar']
* R.take(3, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
* R.take(4, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
* R.take(3, 'ramda'); //=> 'ram'
*
* var personnel = [
* 'Dave Brubeck',
* 'Paul Desmond',
* 'Eugene Wright',
* 'Joe Morello',
* 'Gerry Mulligan',
* 'Bob Bates',
* 'Joe Dodge',
* 'Ron Crotty'
* ];
*
* var takeFive = R.take(5);
* takeFive(personnel);
* //=> ['Dave Brubeck', 'Paul Desmond', 'Eugene Wright', 'Joe Morello', 'Gerry Mulligan']
*/
var take = _curry2(_dispatchable('take', _xtake, function take(n, xs) {
return slice(0, n < 0 ? Infinity : n, xs);
}));
/**
* Returns a new list containing the last `n` elements of a given list, passing
* each value to the supplied predicate function, and terminating when the
* predicate function returns `false`. Excludes the element that caused the
* predicate function to fail. The predicate function is passed one argument:
* *(value)*.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig (a -> Boolean) -> [a] -> [a]
* @param {Function} fn The function called per iteration.
* @param {Array} list The collection to iterate over.
* @return {Array} A new array.
* @see R.dropLastWhile, R.addIndex
* @example
*
* var isNotOne = x => x !== 1;
*
* R.takeLastWhile(isNotOne, [1, 2, 3, 4]); //=> [2, 3, 4]
*/
var takeLastWhile = _curry2(function takeLastWhile(fn, list) {
var idx = list.length - 1;
while (idx >= 0 && fn(list[idx])) {
idx -= 1;
}
return _slice(list, idx + 1, Infinity);
});
/**
* Returns a new list containing the first `n` elements of a given list,
* passing each value to the supplied predicate function, and terminating when
* the predicate function returns `false`. Excludes the element that caused the
* predicate function to fail. The predicate function is passed one argument:
* *(value)*.
*
* Dispatches to the `takeWhile` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a -> Boolean) -> [a] -> [a]
* @param {Function} fn The function called per iteration.
* @param {Array} list The collection to iterate over.
* @return {Array} A new array.
* @see R.dropWhile, R.transduce, R.addIndex
* @example
*
* var isNotFour = x => x !== 4;
*
* R.takeWhile(isNotFour, [1, 2, 3, 4, 3, 2, 1]); //=> [1, 2, 3]
*/
var takeWhile = _curry2(_dispatchable('takeWhile', _xtakeWhile, function takeWhile(fn, list) {
var idx = 0;
var len = list.length;
while (idx < len && fn(list[idx])) {
idx += 1;
}
return _slice(list, 0, idx);
}));
/**
* Runs the given function with the supplied object, then returns the object.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (a -> *) -> a -> a
* @param {Function} fn The function to call with `x`. The return value of `fn` will be thrown away.
* @param {*} x
* @return {*} `x`.
* @example
*
* var sayX = x => console.log('x is ' + x);
* R.tap(sayX, 100); //=> 100
* // logs 'x is 100'
*/
var tap = _curry2(function tap(fn, x) {
fn(x);
return x;
});
/**
* Calls an input function `n` times, returning an array containing the results
* of those function calls.
*
* `fn` is passed one argument: The current value of `n`, which begins at `0`
* and is gradually incremented to `n - 1`.
*
* @func
* @memberOf R
* @since v0.2.3
* @category List
* @sig (Number -> a) -> Number -> [a]
* @param {Function} fn The function to invoke. Passed one argument, the current value of `n`.
* @param {Number} n A value between `0` and `n - 1`. Increments after each function call.
* @return {Array} An array containing the return values of all calls to `fn`.
* @example
*
* R.times(R.identity, 5); //=> [0, 1, 2, 3, 4]
*/
var times = _curry2(function times(fn, n) {
var len = Number(n);
var idx = 0;
var list;
if (len < 0 || isNaN(len)) {
throw new RangeError('n must be a non-negative number');
}
list = new Array(len);
while (idx < len) {
list[idx] = fn(idx);
idx += 1;
}
return list;
});
/**
* Converts an object into an array of key, value arrays. Only the object's
* own properties are used.
* Note that the order of the output array is not guaranteed to be consistent
* across different JS platforms.
*
* @func
* @memberOf R
* @since v0.4.0
* @category Object
* @sig {String: *} -> [[String,*]]
* @param {Object} obj The object to extract from
* @return {Array} An array of key, value arrays from the object's own properties.
* @see R.fromPairs
* @example
*
* R.toPairs({a: 1, b: 2, c: 3}); //=> [['a', 1], ['b', 2], ['c', 3]]
*/
var toPairs = _curry1(function toPairs(obj) {
var pairs = [];
for (var prop in obj) {
if (_has(prop, obj)) {
pairs[pairs.length] = [
prop,
obj[prop]
];
}
}
return pairs;
});
/**
* Converts an object into an array of key, value arrays. The object's own
* properties and prototype properties are used. Note that the order of the
* output array is not guaranteed to be consistent across different JS
* platforms.
*
* @func
* @memberOf R
* @since v0.4.0
* @category Object
* @sig {String: *} -> [[String,*]]
* @param {Object} obj The object to extract from
* @return {Array} An array of key, value arrays from the object's own
* and prototype properties.
* @example
*
* var F = function() { this.x = 'X'; };
* F.prototype.y = 'Y';
* var f = new F();
* R.toPairsIn(f); //=> [['x','X'], ['y','Y']]
*/
var toPairsIn = _curry1(function toPairsIn(obj) {
var pairs = [];
for (var prop in obj) {
pairs[pairs.length] = [
prop,
obj[prop]
];
}
return pairs;
});
/**
* Transposes the rows and columns of a 2D list.
* When passed a list of `n` lists of length `x`,
* returns a list of `x` lists of length `n`.
*
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig [[a]] -> [[a]]
* @param {Array} list A 2D list
* @return {Array} A 2D list
* @example
*
* R.transpose([[1, 'a'], [2, 'b'], [3, 'c']]) //=> [[1, 2, 3], ['a', 'b', 'c']]
* R.transpose([[1, 2, 3], ['a', 'b', 'c']]) //=> [[1, 'a'], [2, 'b'], [3, 'c']]
*
* If some of the rows are shorter than the following rows, their elements are skipped:
*
* R.transpose([[10, 11], [20], [], [30, 31, 32]]) //=> [[10, 20, 30], [11, 31], [32]]
*/
var transpose = _curry1(function transpose(outerlist) {
var i = 0;
var result = [];
while (i < outerlist.length) {
var innerlist = outerlist[i];
var j = 0;
while (j < innerlist.length) {
if (typeof result[j] === 'undefined') {
result[j] = [];
}
result[j].push(innerlist[j]);
j += 1;
}
i += 1;
}
return result;
});
/**
* Removes (strips) whitespace from both ends of the string.
*
* @func
* @memberOf R
* @since v0.6.0
* @category String
* @sig String -> String
* @param {String} str The string to trim.
* @return {String} Trimmed version of `str`.
* @example
*
* R.trim(' xyz '); //=> 'xyz'
* R.map(R.trim, R.split(',', 'x, y, z')); //=> ['x', 'y', 'z']
*/
var trim = function () {
var ws = '\t\n\x0B\f\r \xA0\u1680\u180E\u2000\u2001\u2002\u2003' + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' + '\u2029\uFEFF';
var zeroWidth = '\u200B';
var hasProtoTrim = typeof String.prototype.trim === 'function';
if (!hasProtoTrim || (ws.trim() || !zeroWidth.trim())) {
return _curry1(function trim(str) {
var beginRx = new RegExp('^[' + ws + '][' + ws + ']*');
var endRx = new RegExp('[' + ws + '][' + ws + ']*$');
return str.replace(beginRx, '').replace(endRx, '');
});
} else {
return _curry1(function trim(str) {
return str.trim();
});
}
}();
/**
* `tryCatch` takes two functions, a `tryer` and a `catcher`. The returned
* function evaluates the `tryer`; if it does not throw, it simply returns the
* result. If the `tryer` *does* throw, the returned function evaluates the
* `catcher` function and returns its result. Note that for effective
* composition with this function, both the `tryer` and `catcher` functions
* must return the same type of results.
*
* @func
* @memberOf R
* @since v0.20.0
* @category Function
* @sig (...x -> a) -> ((e, ...x) -> a) -> (...x -> a)
* @param {Function} tryer The function that may throw.
* @param {Function} catcher The function that will be evaluated if `tryer` throws.
* @return {Function} A new function that will catch exceptions and send then to the catcher.
* @example
*
* R.tryCatch(R.prop('x'), R.F)({x: true}); //=> true
* R.tryCatch(R.prop('x'), R.F)(null); //=> false
*/
var tryCatch = _curry2(function _tryCatch(tryer, catcher) {
return _arity(tryer.length, function () {
try {
return tryer.apply(this, arguments);
} catch (e) {
return catcher.apply(this, _concat([e], arguments));
}
});
});
/**
* Gives a single-word string description of the (native) type of a value,
* returning such answers as 'Object', 'Number', 'Array', or 'Null'. Does not
* attempt to distinguish user Object types any further, reporting them all as
* 'Object'.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Type
* @sig (* -> {*}) -> String
* @param {*} val The value to test
* @return {String}
* @example
*
* R.type({}); //=> "Object"
* R.type(1); //=> "Number"
* R.type(false); //=> "Boolean"
* R.type('s'); //=> "String"
* R.type(null); //=> "Null"
* R.type([]); //=> "Array"
* R.type(/[A-z]/); //=> "RegExp"
*/
var type = _curry1(function type(val) {
return val === null ? 'Null' : val === undefined ? 'Undefined' : Object.prototype.toString.call(val).slice(8, -1);
});
/**
* Takes a function `fn`, which takes a single array argument, and returns a
* function which:
*
* - takes any number of positional arguments;
* - passes these arguments to `fn` as an array; and
* - returns the result.
*
* In other words, R.unapply derives a variadic function from a function which
* takes an array. R.unapply is the inverse of R.apply.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Function
* @sig ([*...] -> a) -> (*... -> a)
* @param {Function} fn
* @return {Function}
* @see R.apply
* @example
*
* R.unapply(JSON.stringify)(1, 2, 3); //=> '[1,2,3]'
*/
var unapply = _curry1(function unapply(fn) {
return function () {
return fn(_slice(arguments));
};
});
/**
* Wraps a function of any arity (including nullary) in a function that accepts
* exactly 1 parameter. Any extraneous parameters will not be passed to the
* supplied function.
*
* @func
* @memberOf R
* @since v0.2.0
* @category Function
* @sig (* -> b) -> (a -> b)
* @param {Function} fn The function to wrap.
* @return {Function} A new function wrapping `fn`. The new function is guaranteed to be of
* arity 1.
* @example
*
* var takesTwoArgs = function(a, b) {
* return [a, b];
* };
* takesTwoArgs.length; //=> 2
* takesTwoArgs(1, 2); //=> [1, 2]
*
* var takesOneArg = R.unary(takesTwoArgs);
* takesOneArg.length; //=> 1
* // Only 1 argument is passed to the wrapped function
* takesOneArg(1, 2); //=> [1, undefined]
*/
var unary = _curry1(function unary(fn) {
return nAry(1, fn);
});
/**
* Returns a function of arity `n` from a (manually) curried function.
*
* @func
* @memberOf R
* @since v0.14.0
* @category Function
* @sig Number -> (a -> b) -> (a -> c)
* @param {Number} length The arity for the returned function.
* @param {Function} fn The function to uncurry.
* @return {Function} A new function.
* @see R.curry
* @example
*
* var addFour = a => b => c => d => a + b + c + d;
*
* var uncurriedAddFour = R.uncurryN(4, addFour);
* uncurriedAddFour(1, 2, 3, 4); //=> 10
*/
var uncurryN = _curry2(function uncurryN(depth, fn) {
return curryN(depth, function () {
var currentDepth = 1;
var value = fn;
var idx = 0;
var endIdx;
while (currentDepth <= depth && typeof value === 'function') {
endIdx = currentDepth === depth ? arguments.length : idx + value.length;
value = value.apply(this, _slice(arguments, idx, endIdx));
currentDepth += 1;
idx = endIdx;
}
return value;
});
});
/**
* Builds a list from a seed value. Accepts an iterator function, which returns
* either false to stop iteration or an array of length 2 containing the value
* to add to the resulting list and the seed to be used in the next call to the
* iterator function.
*
* The iterator function receives one argument: *(seed)*.
*
* @func
* @memberOf R
* @since v0.10.0
* @category List
* @sig (a -> [b]) -> * -> [b]
* @param {Function} fn The iterator function. receives one argument, `seed`, and returns
* either false to quit iteration or an array of length two to proceed. The element
* at index 0 of this array will be added to the resulting array, and the element
* at index 1 will be passed to the next call to `fn`.
* @param {*} seed The seed value.
* @return {Array} The final list.
* @example
*
* var f = n => n > 50 ? false : [-n, n + 10];
* R.unfold(f, 10); //=> [-10, -20, -30, -40, -50]
*/
var unfold = _curry2(function unfold(fn, seed) {
var pair = fn(seed);
var result = [];
while (pair && pair.length) {
result[result.length] = pair[0];
pair = fn(pair[1]);
}
return result;
});
/**
* Returns a new list containing only one copy of each element in the original
* list, based upon the value returned by applying the supplied predicate to
* two list elements. Prefers the first item if two items compare equal based
* on the predicate.
*
* @func
* @memberOf R
* @since v0.2.0
* @category List
* @sig (a, a -> Boolean) -> [a] -> [a]
* @param {Function} pred A predicate used to test whether two items are equal.
* @param {Array} list The array to consider.
* @return {Array} The list of unique items.
* @example
*
* var strEq = R.eqBy(String);
* R.uniqWith(strEq)([1, '1', 2, 1]); //=> [1, 2]
* R.uniqWith(strEq)([{}, {}]); //=> [{}]
* R.uniqWith(strEq)([1, '1', 1]); //=> [1]
* R.uniqWith(strEq)(['1', 1, 1]); //=> ['1']
*/
var uniqWith = _curry2(function uniqWith(pred, list) {
var idx = 0;
var len = list.length;
var result = [];
var item;
while (idx < len) {
item = list[idx];
if (!_containsWith(pred, item, result)) {
result[result.length] = item;
}
idx += 1;
}
return result;
});
/**
* Tests the final argument by passing it to the given predicate function. If
* the predicate is not satisfied, the function will return the result of
* calling the `whenFalseFn` function with the same argument. If the predicate
* is satisfied, the argument is returned as is.
*
* @func
* @memberOf R
* @since v0.18.0
* @category Logic
* @sig (a -> Boolean) -> (a -> a) -> a -> a
* @param {Function} pred A predicate function
* @param {Function} whenFalseFn A function to invoke when the `pred` evaluates
* to a falsy value.
* @param {*} x An object to test with the `pred` function and
* pass to `whenFalseFn` if necessary.
* @return {*} Either `x` or the result of applying `x` to `whenFalseFn`.
* @see R.ifElse, R.when
* @example
*
* // coerceArray :: (a|[a]) -> [a]
* var coerceArray = R.unless(R.isArrayLike, R.of);
* coerceArray([1, 2, 3]); //=> [1, 2, 3]
* coerceArray(1); //=> [1]
*/
var unless = _curry3(function unless(pred, whenFalseFn, x) {
return pred(x) ? x : whenFalseFn(x);
});
/**
* Takes a predicate, a transformation function, and an initial value,
* and returns a value of the same type as the initial value.
* It does so by applying the transformation until the predicate is satisfied,
* at which point it returns the satisfactory value.
*
* @func
* @memberOf R
* @since v0.20.0
* @category Logic
* @sig (a -> Boolean) -> (a -> a) -> a -> a
* @param {Function} pred A predicate function
* @param {Function} fn The iterator function
* @param {*} init Initial value
* @return {*} Final value that satisfies predicate
* @example
*
* R.until(R.gt(R.__, 100), R.multiply(2))(1) // => 128
*/
var until = _curry3(function until(pred, fn, init) {
var val = init;
while (!pred(val)) {
val = fn(val);
}
return val;
});
/**
* Returns a new copy of the array with the element at the provided index
* replaced with the given value.
*
* @func
* @memberOf R
* @since v0.14.0
* @category List
* @sig Number -> a -> [a] -> [a]
* @param {Number} idx The index to update.
* @param {*} x The value to exist at the given index of the returned array.
* @param {Array|Arguments} list The source array-like object to be updated.
* @return {Array} A copy of `list` with the value at index `idx` replaced with `x`.
* @see R.adjust
* @example
*
* R.update(1, 11, [0, 1, 2]); //=> [0, 11, 2]
* R.update(1)(11)([0, 1, 2]); //=> [0, 11, 2]
*/
var update = _curry3(function update(idx, x, list) {
return adjust(always(x), idx, list);
});
/**
* Accepts a function `fn` and a list of transformer functions and returns a
* new curried function. When the new function is invoked, it calls the
* function `fn` with parameters consisting of the result of calling each
* supplied handler on successive arguments to the new function.
*
* If more arguments are passed to the returned function than transformer
* functions, those arguments are passed directly to `fn` as additional
* parameters. If you expect additional arguments that don't need to be
* transformed, although you can ignore them, it's best to pass an identity
* function so that the new function reports the correct arity.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (x1 -> x2 -> ... -> z) -> [(a -> x1), (b -> x2), ...] -> (a -> b -> ... -> z)
* @param {Function} fn The function to wrap.
* @param {Array} transformers A list of transformer functions
* @return {Function} The wrapped function.
* @example
*
* R.useWith(Math.pow, [R.identity, R.identity])(3, 4); //=> 81
* R.useWith(Math.pow, [R.identity, R.identity])(3)(4); //=> 81
* R.useWith(Math.pow, [R.dec, R.inc])(3, 4); //=> 32
* R.useWith(Math.pow, [R.dec, R.inc])(3)(4); //=> 32
*/
var useWith = _curry2(function useWith(fn, transformers) {
return curryN(transformers.length, function () {
var args = [];
var idx = 0;
while (idx < transformers.length) {
args.push(transformers[idx].call(this, arguments[idx]));
idx += 1;
}
return fn.apply(this, args.concat(_slice(arguments, transformers.length)));
});
});
/**
* Returns a list of all the enumerable own properties of the supplied object.
* Note that the order of the output array is not guaranteed across different
* JS platforms.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig {k: v} -> [v]
* @param {Object} obj The object to extract values from
* @return {Array} An array of the values of the object's own properties.
* @example
*
* R.values({a: 1, b: 2, c: 3}); //=> [1, 2, 3]
*/
var values = _curry1(function values(obj) {
var props = keys(obj);
var len = props.length;
var vals = [];
var idx = 0;
while (idx < len) {
vals[idx] = obj[props[idx]];
idx += 1;
}
return vals;
});
/**
* Returns a list of all the properties, including prototype properties, of the
* supplied object.
* Note that the order of the output array is not guaranteed to be consistent
* across different JS platforms.
*
* @func
* @memberOf R
* @since v0.2.0
* @category Object
* @sig {k: v} -> [v]
* @param {Object} obj The object to extract values from
* @return {Array} An array of the values of the object's own and prototype properties.
* @example
*
* var F = function() { this.x = 'X'; };
* F.prototype.y = 'Y';
* var f = new F();
* R.valuesIn(f); //=> ['X', 'Y']
*/
var valuesIn = _curry1(function valuesIn(obj) {
var prop;
var vs = [];
for (prop in obj) {
vs[vs.length] = obj[prop];
}
return vs;
});
/**
* Returns a "view" of the given data structure, determined by the given lens.
* The lens's focus determines which portion of the data structure is visible.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig Lens s a -> s -> a
* @param {Lens} lens
* @param {*} x
* @return {*}
* @see R.prop, R.lensIndex, R.lensProp
* @example
*
* var xLens = R.lensProp('x');
*
* R.view(xLens, {x: 1, y: 2}); //=> 1
* R.view(xLens, {x: 4, y: 2}); //=> 4
*/
// `Const` is a functor that effectively ignores the function given to `map`.
// Using `Const` effectively ignores the setter function of the `lens`,
// leaving the value returned by the getter function unmodified.
var view = function () {
// `Const` is a functor that effectively ignores the function given to `map`.
var Const = function (x) {
return {
value: x,
map: function () {
return this;
}
};
};
return _curry2(function view(lens, x) {
// Using `Const` effectively ignores the setter function of the `lens`,
// leaving the value returned by the getter function unmodified.
return lens(Const)(x).value;
});
}();
/**
* Tests the final argument by passing it to the given predicate function. If
* the predicate is satisfied, the function will return the result of calling
* the `whenTrueFn` function with the same argument. If the predicate is not
* satisfied, the argument is returned as is.
*
* @func
* @memberOf R
* @since v0.18.0
* @category Logic
* @sig (a -> Boolean) -> (a -> a) -> a -> a
* @param {Function} pred A predicate function
* @param {Function} whenTrueFn A function to invoke when the `condition`
* evaluates to a truthy value.
* @param {*} x An object to test with the `pred` function and
* pass to `whenTrueFn` if necessary.
* @return {*} Either `x` or the result of applying `x` to `whenTrueFn`.
* @see R.ifElse, R.unless
* @example
*
* // truncate :: String -> String
* var truncate = R.when(
* R.propSatisfies(R.gt(R.__, 10), 'length'),
* R.pipe(R.take(10), R.append('…'), R.join(''))
* );
* truncate('12345'); //=> '12345'
* truncate('0123456789ABC'); //=> '0123456789…'
*/
var when = _curry3(function when(pred, whenTrueFn, x) {
return pred(x) ? whenTrueFn(x) : x;
});
/**
* Takes a spec object and a test object; returns true if the test satisfies
* the spec. Each of the spec's own properties must be a predicate function.
* Each predicate is applied to the value of the corresponding property of the
* test object. `where` returns true if all the predicates return true, false
* otherwise.
*
* `where` is well suited to declaratively expressing constraints for other
* functions such as `filter` and `find`.
*
* @func
* @memberOf R
* @since v0.1.1
* @category Object
* @sig {String: (* -> Boolean)} -> {String: *} -> Boolean
* @param {Object} spec
* @param {Object} testObj
* @return {Boolean}
* @example
*
* // pred :: Object -> Boolean
* var pred = where({
* a: equals('foo'),
* b: complement(equals('bar')),
* x: gt(__, 10),
* y: lt(__, 20)
* });
*
* pred({a: 'foo', b: 'xxx', x: 11, y: 19}); //=> true
* pred({a: 'xxx', b: 'xxx', x: 11, y: 19}); //=> false
* pred({a: 'foo', b: 'bar', x: 11, y: 19}); //=> false
* pred({a: 'foo', b: 'xxx', x: 10, y: 19}); //=> false
* pred({a: 'foo', b: 'xxx', x: 11, y: 20}); //=> false
*/
var where = _curry2(function where(spec, testObj) {
for (var prop in spec) {
if (_has(prop, spec) && !spec[prop](testObj[prop])) {
return false;
}
}
return true;
});
/**
* Wrap a function inside another to allow you to make adjustments to the
* parameters, or do other processing either before the internal function is
* called or with its results.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (a... -> b) -> ((a... -> b) -> a... -> c) -> (a... -> c)
* @param {Function} fn The function to wrap.
* @param {Function} wrapper The wrapper function.
* @return {Function} The wrapped function.
* @deprecated since v0.22.0
* @example
*
* var greet = name => 'Hello ' + name;
*
* var shoutedGreet = R.wrap(greet, (gr, name) => gr(name).toUpperCase());
*
* shoutedGreet("Kathy"); //=> "HELLO KATHY"
*
* var shortenedGreet = R.wrap(greet, function(gr, name) {
* return gr(name.substring(0, 3));
* });
* shortenedGreet("Robert"); //=> "Hello Rob"
*/
var wrap = _curry2(function wrap(fn, wrapper) {
return curryN(fn.length, function () {
return wrapper.apply(this, _concat([fn], arguments));
});
});
/**
* Creates a new list out of the two supplied by creating each possible pair
* from the lists.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [b] -> [[a,b]]
* @param {Array} as The first list.
* @param {Array} bs The second list.
* @return {Array} The list made by combining each possible pair from
* `as` and `bs` into pairs (`[a, b]`).
* @example
*
* R.xprod([1, 2], ['a', 'b']); //=> [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
*/
// = xprodWith(prepend); (takes about 3 times as long...)
var xprod = _curry2(function xprod(a, b) {
// = xprodWith(prepend); (takes about 3 times as long...)
var idx = 0;
var ilen = a.length;
var j;
var jlen = b.length;
var result = [];
while (idx < ilen) {
j = 0;
while (j < jlen) {
result[result.length] = [
a[idx],
b[j]
];
j += 1;
}
idx += 1;
}
return result;
});
/**
* Creates a new list out of the two supplied by pairing up equally-positioned
* items from both lists. The returned list is truncated to the length of the
* shorter of the two input lists.
* Note: `zip` is equivalent to `zipWith(function(a, b) { return [a, b] })`.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [b] -> [[a,b]]
* @param {Array} list1 The first array to consider.
* @param {Array} list2 The second array to consider.
* @return {Array} The list made by pairing up same-indexed elements of `list1` and `list2`.
* @example
*
* R.zip([1, 2, 3], ['a', 'b', 'c']); //=> [[1, 'a'], [2, 'b'], [3, 'c']]
*/
var zip = _curry2(function zip(a, b) {
var rv = [];
var idx = 0;
var len = Math.min(a.length, b.length);
while (idx < len) {
rv[idx] = [
a[idx],
b[idx]
];
idx += 1;
}
return rv;
});
/**
* Creates a new object out of a list of keys and a list of values.
* Key/value pairing is truncated to the length of the shorter of the two lists.
* Note: `zipObj` is equivalent to `pipe(zipWith(pair), fromPairs)`.
*
* @func
* @memberOf R
* @since v0.3.0
* @category List
* @sig [String] -> [*] -> {String: *}
* @param {Array} keys The array that will be properties on the output object.
* @param {Array} values The list of values on the output object.
* @return {Object} The object made by pairing up same-indexed elements of `keys` and `values`.
* @example
*
* R.zipObj(['a', 'b', 'c'], [1, 2, 3]); //=> {a: 1, b: 2, c: 3}
*/
var zipObj = _curry2(function zipObj(keys, values) {
var idx = 0;
var len = Math.min(keys.length, values.length);
var out = {};
while (idx < len) {
out[keys[idx]] = values[idx];
idx += 1;
}
return out;
});
/**
* Creates a new list out of the two supplied by applying the function to each
* equally-positioned pair in the lists. The returned list is truncated to the
* length of the shorter of the two input lists.
*
* @function
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a,b -> c) -> [a] -> [b] -> [c]
* @param {Function} fn The function used to combine the two elements into one value.
* @param {Array} list1 The first array to consider.
* @param {Array} list2 The second array to consider.
* @return {Array} The list made by combining same-indexed elements of `list1` and `list2`
* using `fn`.
* @example
*
* var f = (x, y) => {
* // ...
* };
* R.zipWith(f, [1, 2, 3], ['a', 'b', 'c']);
* //=> [f(1, 'a'), f(2, 'b'), f(3, 'c')]
*/
var zipWith = _curry3(function zipWith(fn, a, b) {
var rv = [];
var idx = 0;
var len = Math.min(a.length, b.length);
while (idx < len) {
rv[idx] = fn(a[idx], b[idx]);
idx += 1;
}
return rv;
});
/**
* A function that always returns `false`. Any passed in parameters are ignored.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Function
* @sig * -> Boolean
* @param {*}
* @return {Boolean}
* @see R.always, R.T
* @example
*
* R.F(); //=> false
*/
var F = always(false);
/**
* A function that always returns `true`. Any passed in parameters are ignored.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Function
* @sig * -> Boolean
* @param {*}
* @return {Boolean}
* @see R.always, R.F
* @example
*
* R.T(); //=> true
*/
var T = always(true);
/**
* Copies an object.
*
* @private
* @param {*} value The value to be copied
* @param {Array} refFrom Array containing the source references
* @param {Array} refTo Array containing the copied source references
* @param {Boolean} deep Whether or not to perform deep cloning.
* @return {*} The copied value.
*/
var _clone = function _clone(value, refFrom, refTo, deep) {
var copy = function copy(copiedValue) {
var len = refFrom.length;
var idx = 0;
while (idx < len) {
if (value === refFrom[idx]) {
return refTo[idx];
}
idx += 1;
}
refFrom[idx + 1] = value;
refTo[idx + 1] = copiedValue;
for (var key in value) {
copiedValue[key] = deep ? _clone(value[key], refFrom, refTo, true) : value[key];
}
return copiedValue;
};
switch (type(value)) {
case 'Object':
return copy({});
case 'Array':
return copy([]);
case 'Date':
return new Date(value.valueOf());
case 'RegExp':
return _cloneRegExp(value);
default:
return value;
}
};
var _createPartialApplicator = function _createPartialApplicator(concat) {
return _curry2(function (fn, args) {
return _arity(Math.max(0, fn.length - args.length), function () {
return fn.apply(this, concat(args, arguments));
});
});
};
var _dropLast = function dropLast(n, xs) {
return take(n < xs.length ? xs.length - n : 0, xs);
};
// Values of other types are only equal if identical.
var _equals = function _equals(a, b, stackA, stackB) {
if (identical(a, b)) {
return true;
}
if (type(a) !== type(b)) {
return false;
}
if (a == null || b == null) {
return false;
}
if (typeof a.equals === 'function' || typeof b.equals === 'function') {
return typeof a.equals === 'function' && a.equals(b) && typeof b.equals === 'function' && b.equals(a);
}
switch (type(a)) {
case 'Arguments':
case 'Array':
case 'Object':
if (typeof a.constructor === 'function' && _functionName(a.constructor) === 'Promise') {
return a === b;
}
break;
case 'Boolean':
case 'Number':
case 'String':
if (!(typeof a === typeof b && identical(a.valueOf(), b.valueOf()))) {
return false;
}
break;
case 'Date':
if (!identical(a.valueOf(), b.valueOf())) {
return false;
}
break;
case 'Error':
return a.name === b.name && a.message === b.message;
case 'RegExp':
if (!(a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.sticky === b.sticky && a.unicode === b.unicode)) {
return false;
}
break;
case 'Map':
case 'Set':
if (!_equals(_arrayFromIterator(a.entries()), _arrayFromIterator(b.entries()), stackA, stackB)) {
return false;
}
break;
case 'Int8Array':
case 'Uint8Array':
case 'Uint8ClampedArray':
case 'Int16Array':
case 'Uint16Array':
case 'Int32Array':
case 'Uint32Array':
case 'Float32Array':
case 'Float64Array':
break;
case 'ArrayBuffer':
break;
default:
// Values of other types are only equal if identical.
return false;
}
var keysA = keys(a);
if (keysA.length !== keys(b).length) {
return false;
}
var idx = stackA.length - 1;
while (idx >= 0) {
if (stackA[idx] === a) {
return stackB[idx] === b;
}
idx -= 1;
}
stackA.push(a);
stackB.push(b);
idx = keysA.length - 1;
while (idx >= 0) {
var key = keysA[idx];
if (!(_has(key, b) && _equals(b[key], a[key], stackA, stackB))) {
return false;
}
idx -= 1;
}
stackA.pop();
stackB.pop();
return true;
};
/**
* `_makeFlat` is a helper function that returns a one-level or fully recursive
* function based on the flag passed in.
*
* @private
*/
var _makeFlat = function _makeFlat(recursive) {
return function flatt(list) {
var value, jlen, j;
var result = [];
var idx = 0;
var ilen = list.length;
while (idx < ilen) {
if (isArrayLike(list[idx])) {
value = recursive ? flatt(list[idx]) : list[idx];
j = 0;
jlen = value.length;
while (j < jlen) {
result[result.length] = value[j];
j += 1;
}
} else {
result[result.length] = list[idx];
}
idx += 1;
}
return result;
};
};
var _reduce = function () {
function _arrayReduce(xf, acc, list) {
var idx = 0;
var len = list.length;
while (idx < len) {
acc = xf['@@transducer/step'](acc, list[idx]);
if (acc && acc['@@transducer/reduced']) {
acc = acc['@@transducer/value'];
break;
}
idx += 1;
}
return xf['@@transducer/result'](acc);
}
function _iterableReduce(xf, acc, iter) {
var step = iter.next();
while (!step.done) {
acc = xf['@@transducer/step'](acc, step.value);
if (acc && acc['@@transducer/reduced']) {
acc = acc['@@transducer/value'];
break;
}
step = iter.next();
}
return xf['@@transducer/result'](acc);
}
function _methodReduce(xf, acc, obj) {
return xf['@@transducer/result'](obj.reduce(bind(xf['@@transducer/step'], xf), acc));
}
var symIterator = typeof Symbol !== 'undefined' ? Symbol.iterator : '@@iterator';
return function _reduce(fn, acc, list) {
if (typeof fn === 'function') {
fn = _xwrap(fn);
}
if (isArrayLike(list)) {
return _arrayReduce(fn, acc, list);
}
if (typeof list.reduce === 'function') {
return _methodReduce(fn, acc, list);
}
if (list[symIterator] != null) {
return _iterableReduce(fn, acc, list[symIterator]());
}
if (typeof list.next === 'function') {
return _iterableReduce(fn, acc, list);
}
throw new TypeError('reduce: list must be array or iterable');
};
}();
var _stepCat = function () {
var _stepCatArray = {
'@@transducer/init': Array,
'@@transducer/step': function (xs, x) {
xs.push(x);
return xs;
},
'@@transducer/result': _identity
};
var _stepCatString = {
'@@transducer/init': String,
'@@transducer/step': function (a, b) {
return a + b;
},
'@@transducer/result': _identity
};
var _stepCatObject = {
'@@transducer/init': Object,
'@@transducer/step': function (result, input) {
return _assign(result, isArrayLike(input) ? objOf(input[0], input[1]) : input);
},
'@@transducer/result': _identity
};
return function _stepCat(obj) {
if (_isTransformer(obj)) {
return obj;
}
if (isArrayLike(obj)) {
return _stepCatArray;
}
if (typeof obj === 'string') {
return _stepCatString;
}
if (typeof obj === 'object') {
return _stepCatObject;
}
throw new Error('Cannot create transformer for ' + obj);
};
}();
var _xdropLastWhile = function () {
function XDropLastWhile(fn, xf) {
this.f = fn;
this.retained = [];
this.xf = xf;
}
XDropLastWhile.prototype['@@transducer/init'] = _xfBase.init;
XDropLastWhile.prototype['@@transducer/result'] = function (result) {
this.retained = null;
return this.xf['@@transducer/result'](result);
};
XDropLastWhile.prototype['@@transducer/step'] = function (result, input) {
return this.f(input) ? this.retain(result, input) : this.flush(result, input);
};
XDropLastWhile.prototype.flush = function (result, input) {
result = _reduce(this.xf['@@transducer/step'], result, this.retained);
this.retained = [];
return this.xf['@@transducer/step'](result, input);
};
XDropLastWhile.prototype.retain = function (result, input) {
this.retained.push(input);
return result;
};
return _curry2(function _xdropLastWhile(fn, xf) {
return new XDropLastWhile(fn, xf);
});
}();
/**
* Creates a new list iteration function from an existing one by adding two new
* parameters to its callback function: the current index, and the entire list.
*
* This would turn, for instance, Ramda's simple `map` function into one that
* more closely resembles `Array.prototype.map`. Note that this will only work
* for functions in which the iteration callback function is the first
* parameter, and where the list is the last parameter. (This latter might be
* unimportant if the list parameter is not used.)
*
* @func
* @memberOf R
* @since v0.15.0
* @category Function
* @category List
* @sig ((a ... -> b) ... -> [a] -> *) -> (a ..., Int, [a] -> b) ... -> [a] -> *)
* @param {Function} fn A list iteration function that does not pass index or list to its callback
* @return {Function} An altered list iteration function that passes (item, index, list) to its callback
* @example
*
* var mapIndexed = R.addIndex(R.map);
* mapIndexed((val, idx) => idx + '-' + val, ['f', 'o', 'o', 'b', 'a', 'r']);
* //=> ['0-f', '1-o', '2-o', '3-b', '4-a', '5-r']
*/
var addIndex = _curry1(function addIndex(fn) {
return curryN(fn.length, function () {
var idx = 0;
var origFn = arguments[0];
var list = arguments[arguments.length - 1];
var args = _slice(arguments);
args[0] = function () {
var result = origFn.apply(this, _concat(arguments, [
idx,
list
]));
idx += 1;
return result;
};
return fn.apply(this, args);
});
});
/**
* Wraps a function of any arity (including nullary) in a function that accepts
* exactly 2 parameters. Any extraneous parameters will not be passed to the
* supplied function.
*
* @func
* @memberOf R
* @since v0.2.0
* @category Function
* @sig (* -> c) -> (a, b -> c)
* @param {Function} fn The function to wrap.
* @return {Function} A new function wrapping `fn`. The new function is guaranteed to be of
* arity 2.
* @example
*
* var takesThreeArgs = function(a, b, c) {
* return [a, b, c];
* };
* takesThreeArgs.length; //=> 3
* takesThreeArgs(1, 2, 3); //=> [1, 2, 3]
*
* var takesTwoArgs = R.binary(takesThreeArgs);
* takesTwoArgs.length; //=> 2
* // Only 2 arguments are passed to the wrapped function
* takesTwoArgs(1, 2, 3); //=> [1, 2, undefined]
*/
var binary = _curry1(function binary(fn) {
return nAry(2, fn);
});
/**
* Creates a deep copy of the value which may contain (nested) `Array`s and
* `Object`s, `Number`s, `String`s, `Boolean`s and `Date`s. `Function`s are not
* copied, but assigned by their reference.
*
* Dispatches to a `clone` method if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig {*} -> {*}
* @param {*} value The object or array to clone
* @return {*} A new object or array.
* @example
*
* var objects = [{}, {}, {}];
* var objectsClone = R.clone(objects);
* objects[0] === objectsClone[0]; //=> false
*/
var clone = _curry1(function clone(value) {
return value != null && typeof value.clone === 'function' ? value.clone() : _clone(value, [], [], true);
});
/**
* Returns a curried equivalent of the provided function. The curried function
* has two unusual capabilities. First, its arguments needn't be provided one
* at a time. If `f` is a ternary function and `g` is `R.curry(f)`, the
* following are equivalent:
*
* - `g(1)(2)(3)`
* - `g(1)(2, 3)`
* - `g(1, 2)(3)`
* - `g(1, 2, 3)`
*
* Secondly, the special placeholder value `R.__` may be used to specify
* "gaps", allowing partial application of any combination of arguments,
* regardless of their positions. If `g` is as above and `_` is `R.__`, the
* following are equivalent:
*
* - `g(1, 2, 3)`
* - `g(_, 2, 3)(1)`
* - `g(_, _, 3)(1)(2)`
* - `g(_, _, 3)(1, 2)`
* - `g(_, 2)(1)(3)`
* - `g(_, 2)(1, 3)`
* - `g(_, 2)(_, 3)(1)`
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (* -> a) -> (* -> a)
* @param {Function} fn The function to curry.
* @return {Function} A new, curried function.
* @see R.curryN
* @example
*
* var addFourNumbers = (a, b, c, d) => a + b + c + d;
*
* var curriedAddFourNumbers = R.curry(addFourNumbers);
* var f = curriedAddFourNumbers(1, 2);
* var g = f(3);
* g(4); //=> 10
*/
var curry = _curry1(function curry(fn) {
return curryN(fn.length, fn);
});
/**
* Returns all but the first `n` elements of the given list, string, or
* transducer/transformer (or object with a `drop` method).
*
* Dispatches to the `drop` method of the second argument, if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Number -> [a] -> [a]
* @sig Number -> String -> String
* @param {Number} n
* @param {*} list
* @return {*}
* @see R.take, R.transduce
* @example
*
* R.drop(1, ['foo', 'bar', 'baz']); //=> ['bar', 'baz']
* R.drop(2, ['foo', 'bar', 'baz']); //=> ['baz']
* R.drop(3, ['foo', 'bar', 'baz']); //=> []
* R.drop(4, ['foo', 'bar', 'baz']); //=> []
* R.drop(3, 'ramda'); //=> 'da'
*/
var drop = _curry2(_dispatchable('drop', _xdrop, function drop(n, xs) {
return slice(Math.max(0, n), Infinity, xs);
}));
/**
* Returns a list containing all but the last `n` elements of the given `list`.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig Number -> [a] -> [a]
* @sig Number -> String -> String
* @param {Number} n The number of elements of `xs` to skip.
* @param {Array} xs The collection to consider.
* @return {Array}
* @see R.takeLast
* @example
*
* R.dropLast(1, ['foo', 'bar', 'baz']); //=> ['foo', 'bar']
* R.dropLast(2, ['foo', 'bar', 'baz']); //=> ['foo']
* R.dropLast(3, ['foo', 'bar', 'baz']); //=> []
* R.dropLast(4, ['foo', 'bar', 'baz']); //=> []
* R.dropLast(3, 'ramda'); //=> 'ra'
*/
var dropLast = _curry2(_dispatchable('dropLast', _xdropLast, _dropLast));
/**
* Returns a new list excluding all the tailing elements of a given list which
* satisfy the supplied predicate function. It passes each value from the right
* to the supplied predicate function, skipping elements while the predicate
* function returns `true`. The predicate function is applied to one argument:
* *(value)*.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig (a -> Boolean) -> [a] -> [a]
* @param {Function} fn The function called per iteration.
* @param {Array} list The collection to iterate over.
* @return {Array} A new array.
* @see R.takeLastWhile, R.addIndex
* @example
*
* var lteThree = x => x <= 3;
*
* R.dropLastWhile(lteThree, [1, 2, 3, 4, 3, 2, 1]); //=> [1, 2, 3, 4]
*/
var dropLastWhile = _curry2(_dispatchable('dropLastWhile', _xdropLastWhile, _dropLastWhile));
/**
* Returns `true` if its arguments are equivalent, `false` otherwise. Handles
* cyclical data structures.
*
* Dispatches symmetrically to the `equals` methods of both arguments, if
* present.
*
* @func
* @memberOf R
* @since v0.15.0
* @category Relation
* @sig a -> b -> Boolean
* @param {*} a
* @param {*} b
* @return {Boolean}
* @example
*
* R.equals(1, 1); //=> true
* R.equals(1, '1'); //=> false
* R.equals([1, 2, 3], [1, 2, 3]); //=> true
*
* var a = {}; a.v = a;
* var b = {}; b.v = b;
* R.equals(a, b); //=> true
*/
var equals = _curry2(function equals(a, b) {
return _equals(a, b, [], []);
});
/**
* Takes a predicate and a "filterable", and returns a new filterable of the
* same type containing the members of the given filterable which satisfy the
* given predicate.
*
* Dispatches to the `filter` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Filterable f => (a -> Boolean) -> f a -> f a
* @param {Function} pred
* @param {Array} filterable
* @return {Array}
* @see R.reject, R.transduce, R.addIndex
* @example
*
* var isEven = n => n % 2 === 0;
*
* R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
*
* R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
*/
// else
var filter = _curry2(_dispatchable('filter', _xfilter, function (pred, filterable) {
return _isObject(filterable) ? _reduce(function (acc, key) {
if (pred(filterable[key])) {
acc[key] = filterable[key];
}
return acc;
}, {}, keys(filterable)) : // else
_filter(pred, filterable);
}));
/**
* Returns a new list by pulling every item out of it (and all its sub-arrays)
* and putting them in a new array, depth-first.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [b]
* @param {Array} list The array to consider.
* @return {Array} The flattened list.
* @see R.unnest
* @example
*
* R.flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]]);
* //=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
*/
var flatten = _curry1(_makeFlat(true));
/**
* Returns a new function much like the supplied one, except that the first two
* arguments' order is reversed.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (a -> b -> c -> ... -> z) -> (b -> a -> c -> ... -> z)
* @param {Function} fn The function to invoke with its first two parameters reversed.
* @return {*} The result of invoking `fn` with its first two parameters' order reversed.
* @example
*
* var mergeThree = (a, b, c) => [].concat(a, b, c);
*
* mergeThree(1, 2, 3); //=> [1, 2, 3]
*
* R.flip(mergeThree)(1, 2, 3); //=> [2, 1, 3]
*/
var flip = _curry1(function flip(fn) {
return curry(function (a, b) {
var args = _slice(arguments);
args[0] = b;
args[1] = a;
return fn.apply(this, args);
});
});
/**
* Returns the first element of the given list or string. In some libraries
* this function is named `first`.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> a | Undefined
* @sig String -> String
* @param {Array|String} list
* @return {*}
* @see R.tail, R.init, R.last
* @example
*
* R.head(['fi', 'fo', 'fum']); //=> 'fi'
* R.head([]); //=> undefined
*
* R.head('abc'); //=> 'a'
* R.head(''); //=> ''
*/
var head = nth(0);
/**
* Returns all but the last element of the given list or string.
*
* @func
* @memberOf R
* @since v0.9.0
* @category List
* @sig [a] -> [a]
* @sig String -> String
* @param {*} list
* @return {*}
* @see R.last, R.head, R.tail
* @example
*
* R.init([1, 2, 3]); //=> [1, 2]
* R.init([1, 2]); //=> [1]
* R.init([1]); //=> []
* R.init([]); //=> []
*
* R.init('abc'); //=> 'ab'
* R.init('ab'); //=> 'a'
* R.init('a'); //=> ''
* R.init(''); //=> ''
*/
var init = slice(0, -1);
/**
* Combines two lists into a set (i.e. no duplicates) composed of those
* elements common to both lists. Duplication is determined according to the
* value returned by applying the supplied predicate to two list elements.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig (a -> a -> Boolean) -> [*] -> [*] -> [*]
* @param {Function} pred A predicate function that determines whether
* the two supplied elements are equal.
* @param {Array} list1 One list of items to compare
* @param {Array} list2 A second list of items to compare
* @return {Array} A new list containing those elements common to both lists.
* @see R.intersection
* @example
*
* var buffaloSpringfield = [
* {id: 824, name: 'Richie Furay'},
* {id: 956, name: 'Dewey Martin'},
* {id: 313, name: 'Bruce Palmer'},
* {id: 456, name: 'Stephen Stills'},
* {id: 177, name: 'Neil Young'}
* ];
* var csny = [
* {id: 204, name: 'David Crosby'},
* {id: 456, name: 'Stephen Stills'},
* {id: 539, name: 'Graham Nash'},
* {id: 177, name: 'Neil Young'}
* ];
*
* R.intersectionWith(R.eqBy(R.prop('id')), buffaloSpringfield, csny);
* //=> [{id: 456, name: 'Stephen Stills'}, {id: 177, name: 'Neil Young'}]
*/
var intersectionWith = _curry3(function intersectionWith(pred, list1, list2) {
var lookupList, filteredList;
if (list1.length > list2.length) {
lookupList = list1;
filteredList = list2;
} else {
lookupList = list2;
filteredList = list1;
}
var results = [];
var idx = 0;
while (idx < filteredList.length) {
if (_containsWith(pred, filteredList[idx], lookupList)) {
results[results.length] = filteredList[idx];
}
idx += 1;
}
return uniqWith(pred, results);
});
/**
* Transforms the items of the list with the transducer and appends the
* transformed items to the accumulator using an appropriate iterator function
* based on the accumulator type.
*
* The accumulator can be an array, string, object or a transformer. Iterated
* items will be appended to arrays and concatenated to strings. Objects will
* be merged directly or 2-item arrays will be merged as key, value pairs.
*
* The accumulator can also be a transformer object that provides a 2-arity
* reducing iterator function, step, 0-arity initial value function, init, and
* 1-arity result extraction function result. The step function is used as the
* iterator function in reduce. The result function is used to convert the
* final accumulator into the return type and in most cases is R.identity. The
* init function is used to provide the initial accumulator.
*
* The iteration is performed with R.reduce after initializing the transducer.
*
* @func
* @memberOf R
* @since v0.12.0
* @category List
* @sig a -> (b -> b) -> [c] -> a
* @param {*} acc The initial accumulator value.
* @param {Function} xf The transducer function. Receives a transformer and returns a transformer.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @example
*
* var numbers = [1, 2, 3, 4];
* var transducer = R.compose(R.map(R.add(1)), R.take(2));
*
* R.into([], transducer, numbers); //=> [2, 3]
*
* var intoArray = R.into([]);
* intoArray(transducer, numbers); //=> [2, 3]
*/
var into = _curry3(function into(acc, xf, list) {
return _isTransformer(acc) ? _reduce(xf(acc), acc['@@transducer/init'](), list) : _reduce(xf(_stepCat(acc)), _clone(acc, [], [], false), list);
});
/**
* Same as R.invertObj, however this accounts for objects with duplicate values
* by putting the values into an array.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Object
* @sig {s: x} -> {x: [ s, ... ]}
* @param {Object} obj The object or array to invert
* @return {Object} out A new object with keys
* in an array.
* @example
*
* var raceResultsByFirstName = {
* first: 'alice',
* second: 'jake',
* third: 'alice',
* };
* R.invert(raceResultsByFirstName);
* //=> { 'alice': ['first', 'third'], 'jake':['second'] }
*/
var invert = _curry1(function invert(obj) {
var props = keys(obj);
var len = props.length;
var idx = 0;
var out = {};
while (idx < len) {
var key = props[idx];
var val = obj[key];
var list = _has(val, out) ? out[val] : out[val] = [];
list[list.length] = key;
idx += 1;
}
return out;
});
/**
* Returns a new object with the keys of the given object as values, and the
* values of the given object, which are coerced to strings, as keys. Note
* that the last key found is preferred when handling the same value.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Object
* @sig {s: x} -> {x: s}
* @param {Object} obj The object or array to invert
* @return {Object} out A new object
* @example
*
* var raceResults = {
* first: 'alice',
* second: 'jake'
* };
* R.invertObj(raceResults);
* //=> { 'alice': 'first', 'jake':'second' }
*
* // Alternatively:
* var raceResults = ['alice', 'jake'];
* R.invertObj(raceResults);
* //=> { 'alice': '0', 'jake':'1' }
*/
var invertObj = _curry1(function invertObj(obj) {
var props = keys(obj);
var len = props.length;
var idx = 0;
var out = {};
while (idx < len) {
var key = props[idx];
out[obj[key]] = key;
idx += 1;
}
return out;
});
/**
* Returns `true` if the given value is its type's empty value; `false`
* otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Logic
* @sig a -> Boolean
* @param {*} x
* @return {Boolean}
* @see R.empty
* @example
*
* R.isEmpty([1, 2, 3]); //=> false
* R.isEmpty([]); //=> true
* R.isEmpty(''); //=> true
* R.isEmpty(null); //=> false
* R.isEmpty({}); //=> true
* R.isEmpty({length: 0}); //=> false
*/
var isEmpty = _curry1(function isEmpty(x) {
return x != null && equals(x, empty(x));
});
/**
* Returns the last element of the given list or string.
*
* @func
* @memberOf R
* @since v0.1.4
* @category List
* @sig [a] -> a | Undefined
* @sig String -> String
* @param {*} list
* @return {*}
* @see R.init, R.head, R.tail
* @example
*
* R.last(['fi', 'fo', 'fum']); //=> 'fum'
* R.last([]); //=> undefined
*
* R.last('abc'); //=> 'c'
* R.last(''); //=> ''
*/
var last = nth(-1);
/**
* Returns the position of the last occurrence of an item in an array, or -1 if
* the item is not included in the array. `R.equals` is used to determine
* equality.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig a -> [a] -> Number
* @param {*} target The item to find.
* @param {Array} xs The array to search in.
* @return {Number} the index of the target, or -1 if the target is not found.
* @see R.indexOf
* @example
*
* R.lastIndexOf(3, [-1,3,3,0,1,2,3,4]); //=> 6
* R.lastIndexOf(10, [1,2,3,4]); //=> -1
*/
var lastIndexOf = _curry2(function lastIndexOf(target, xs) {
if (typeof xs.lastIndexOf === 'function' && !_isArray(xs)) {
return xs.lastIndexOf(target);
} else {
var idx = xs.length - 1;
while (idx >= 0) {
if (equals(xs[idx], target)) {
return idx;
}
idx -= 1;
}
return -1;
}
});
/**
* Takes a function and
* a [functor](https://github.com/fantasyland/fantasy-land#functor),
* applies the function to each of the functor's values, and returns
* a functor of the same shape.
*
* Ramda provides suitable `map` implementations for `Array` and `Object`,
* so this function may be applied to `[1, 2, 3]` or `{x: 1, y: 2, z: 3}`.
*
* Dispatches to the `map` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* Also treats functions as functors and will compose them together.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Functor f => (a -> b) -> f a -> f b
* @param {Function} fn The function to be called on every element of the input `list`.
* @param {Array} list The list to be iterated over.
* @return {Array} The new list.
* @see R.transduce, R.addIndex
* @example
*
* var double = x => x * 2;
*
* R.map(double, [1, 2, 3]); //=> [2, 4, 6]
*
* R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6}
*/
var map = _curry2(_dispatchable('map', _xmap, function map(fn, functor) {
switch (Object.prototype.toString.call(functor)) {
case '[object Function]':
return curryN(functor.length, function () {
return fn.call(this, functor.apply(this, arguments));
});
case '[object Object]':
return _reduce(function (acc, key) {
acc[key] = fn(functor[key]);
return acc;
}, {}, keys(functor));
default:
return _map(fn, functor);
}
}));
/**
* An Object-specific version of `map`. The function is applied to three
* arguments: *(value, key, obj)*. If only the value is significant, use
* `map` instead.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Object
* @sig ((*, String, Object) -> *) -> Object -> Object
* @param {Function} fn
* @param {Object} obj
* @return {Object}
* @see R.map
* @example
*
* var values = { x: 1, y: 2, z: 3 };
* var prependKeyAndDouble = (num, key, obj) => key + (num * 2);
*
* R.mapObjIndexed(prependKeyAndDouble, values); //=> { x: 'x2', y: 'y4', z: 'z6' }
*/
var mapObjIndexed = _curry2(function mapObjIndexed(fn, obj) {
return _reduce(function (acc, key) {
acc[key] = fn(obj[key], key, obj);
return acc;
}, {}, keys(obj));
});
/**
* Creates a new object with the own properties of the two provided objects. If
* a key exists in both objects, the provided function is applied to the values
* associated with the key in each object, with the result being used as the
* value associated with the key in the returned object. The key will be
* excluded from the returned object if the resulting value is `undefined`.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Object
* @sig (a -> a -> a) -> {a} -> {a} -> {a}
* @param {Function} fn
* @param {Object} l
* @param {Object} r
* @return {Object}
* @see R.merge, R.mergeWithKey
* @example
*
* R.mergeWith(R.concat,
* { a: true, values: [10, 20] },
* { b: true, values: [15, 35] });
* //=> { a: true, b: true, values: [10, 20, 15, 35] }
*/
var mergeWith = _curry3(function mergeWith(fn, l, r) {
return mergeWithKey(function (_, _l, _r) {
return fn(_l, _r);
}, l, r);
});
/**
* Takes a function `f` and a list of arguments, and returns a function `g`.
* When applied, `g` returns the result of applying `f` to the arguments
* provided initially followed by the arguments provided to `g`.
*
* @func
* @memberOf R
* @since v0.10.0
* @category Function
* @sig ((a, b, c, ..., n) -> x) -> [a, b, c, ...] -> ((d, e, f, ..., n) -> x)
* @param {Function} f
* @param {Array} args
* @return {Function}
* @see R.partialRight
* @example
*
* var multiply = (a, b) => a * b;
* var double = R.partial(multiply, [2]);
* double(2); //=> 4
*
* var greet = (salutation, title, firstName, lastName) =>
* salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!';
*
* var sayHello = R.partial(greet, ['Hello']);
* var sayHelloToMs = R.partial(sayHello, ['Ms.']);
* sayHelloToMs('Jane', 'Jones'); //=> 'Hello, Ms. Jane Jones!'
*/
var partial = _createPartialApplicator(_concat);
/**
* Takes a function `f` and a list of arguments, and returns a function `g`.
* When applied, `g` returns the result of applying `f` to the arguments
* provided to `g` followed by the arguments provided initially.
*
* @func
* @memberOf R
* @since v0.10.0
* @category Function
* @sig ((a, b, c, ..., n) -> x) -> [d, e, f, ..., n] -> ((a, b, c, ...) -> x)
* @param {Function} f
* @param {Array} args
* @return {Function}
* @see R.partial
* @example
*
* var greet = (salutation, title, firstName, lastName) =>
* salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!';
*
* var greetMsJaneJones = R.partialRight(greet, ['Ms.', 'Jane', 'Jones']);
*
* greetMsJaneJones('Hello'); //=> 'Hello, Ms. Jane Jones!'
*/
var partialRight = _createPartialApplicator(flip(_concat));
/**
* Determines whether a nested path on an object has a specific value, in
* `R.equals` terms. Most likely used to filter a list.
*
* @func
* @memberOf R
* @since v0.7.0
* @category Relation
* @sig [String] -> * -> {String: *} -> Boolean
* @param {Array} path The path of the nested property to use
* @param {*} val The value to compare the nested property with
* @param {Object} obj The object to check the nested property in
* @return {Boolean} `true` if the value equals the nested object property,
* `false` otherwise.
* @example
*
* var user1 = { address: { zipCode: 90210 } };
* var user2 = { address: { zipCode: 55555 } };
* var user3 = { name: 'Bob' };
* var users = [ user1, user2, user3 ];
* var isFamous = R.pathEq(['address', 'zipCode'], 90210);
* R.filter(isFamous, users); //=> [ user1 ]
*/
var pathEq = _curry3(function pathEq(_path, val, obj) {
return equals(path(_path, obj), val);
});
/**
* Returns a new list by plucking the same named property off all objects in
* the list supplied.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig k -> [{k: v}] -> [v]
* @param {Number|String} key The key name to pluck off of each object.
* @param {Array} list The array to consider.
* @return {Array} The list of values for the given key.
* @see R.props
* @example
*
* R.pluck('a')([{a: 1}, {a: 2}]); //=> [1, 2]
* R.pluck(0)([[1, 2], [3, 4]]); //=> [1, 3]
*/
var pluck = _curry2(function pluck(p, list) {
return map(prop(p), list);
});
/**
* Reasonable analog to SQL `select` statement.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @category Relation
* @sig [k] -> [{k: v}] -> [{k: v}]
* @param {Array} props The property names to project
* @param {Array} objs The objects to query
* @return {Array} An array of objects with just the `props` properties.
* @example
*
* var abby = {name: 'Abby', age: 7, hair: 'blond', grade: 2};
* var fred = {name: 'Fred', age: 12, hair: 'brown', grade: 7};
* var kids = [abby, fred];
* R.project(['name', 'grade'], kids); //=> [{name: 'Abby', grade: 2}, {name: 'Fred', grade: 7}]
*/
// passing `identity` gives correct arity
var project = useWith(_map, [
pickAll,
identity
]);
/**
* Returns `true` if the specified object property is equal, in `R.equals`
* terms, to the given value; `false` otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig String -> a -> Object -> Boolean
* @param {String} name
* @param {*} val
* @param {*} obj
* @return {Boolean}
* @see R.equals, R.propSatisfies
* @example
*
* var abby = {name: 'Abby', age: 7, hair: 'blond'};
* var fred = {name: 'Fred', age: 12, hair: 'brown'};
* var rusty = {name: 'Rusty', age: 10, hair: 'brown'};
* var alois = {name: 'Alois', age: 15, disposition: 'surly'};
* var kids = [abby, fred, rusty, alois];
* var hasBrownHair = R.propEq('hair', 'brown');
* R.filter(hasBrownHair, kids); //=> [fred, rusty]
*/
var propEq = _curry3(function propEq(name, val, obj) {
return equals(val, obj[name]);
});
/**
* Returns a single item by iterating through the list, successively calling
* the iterator function and passing it an accumulator value and the current
* value from the array, and then passing the result to the next call.
*
* The iterator function receives two values: *(acc, value)*. It may use
* `R.reduced` to shortcut the iteration.
*
* Note: `R.reduce` does not skip deleted or unassigned indices (sparse
* arrays), unlike the native `Array.prototype.reduce` method. For more details
* on this behavior, see:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Description
*
* Dispatches to the `reduce` method of the third argument, if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig ((a, b) -> a) -> a -> [b] -> a
* @param {Function} fn The iterator function. Receives two values, the accumulator and the
* current element from the array.
* @param {*} acc The accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.reduced, R.addIndex
* @example
*
* var numbers = [1, 2, 3];
* var plus = (a, b) => a + b;
*
* R.reduce(plus, 10, numbers); //=> 16
*/
var reduce = _curry3(_reduce);
/**
* Groups the elements of the list according to the result of calling
* the String-returning function `keyFn` on each element and reduces the elements
* of each group to a single value via the reducer function `valueFn`.
*
* This function is basically a more general `groupBy` function.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.20.0
* @category List
* @sig ((a, b) -> a) -> a -> (b -> String) -> [b] -> {String: a}
* @param {Function} valueFn The function that reduces the elements of each group to a single
* value. Receives two values, accumulator for a particular group and the current element.
* @param {*} acc The (initial) accumulator value for each group.
* @param {Function} keyFn The function that maps the list's element into a key.
* @param {Array} list The array to group.
* @return {Object} An object with the output of `keyFn` for keys, mapped to the output of
* `valueFn` for elements which produced that key when passed to `keyFn`.
* @see R.groupBy, R.reduce
* @example
*
* var reduceToNamesBy = R.reduceBy((acc, student) => acc.concat(student.name), []);
* var namesByGrade = reduceToNamesBy(function(student) {
* var score = student.score;
* return score < 65 ? 'F' :
* score < 70 ? 'D' :
* score < 80 ? 'C' :
* score < 90 ? 'B' : 'A';
* });
* var students = [{name: 'Lucy', score: 92},
* {name: 'Drew', score: 85},
* // ...
* {name: 'Bart', score: 62}];
* namesByGrade(students);
* // {
* // 'A': ['Lucy'],
* // 'B': ['Drew']
* // // ...,
* // 'F': ['Bart']
* // }
*/
var reduceBy = _curryN(4, [], _dispatchable('reduceBy', _xreduceBy, function reduceBy(valueFn, valueAcc, keyFn, list) {
return _reduce(function (acc, elt) {
var key = keyFn(elt);
acc[key] = valueFn(_has(key, acc) ? acc[key] : valueAcc, elt);
return acc;
}, {}, list);
}));
/**
* Like `reduce`, `reduceWhile` returns a single item by iterating through
* the list, successively calling the iterator function. `reduceWhile` also
* takes a predicate that is evaluated before each step. If the predicate returns
* `false`, it "short-circuits" the iteration and returns the current value
* of the accumulator.
*
* @func
* @memberOf R
* @since v0.22.0
* @category List
* @sig ((a, b) -> Boolean) -> ((a, b) -> a) -> a -> [b] -> a
* @param {Function} pred The predicate. It is passed the accumulator and the
* current element.
* @param {Function} fn The iterator function. Receives two values, the
* accumulator and the current element.
* @param {*} a The accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.reduce, R.reduced
* @example
*
* var isOdd = (acc, x) => x % 2 === 1;
* var xs = [1, 3, 5, 60, 777, 800];
* R.reduceWhile(isOdd, R.add, 0, xs); //=> 9
*
* var ys = [2, 4, 6]
* R.reduceWhile(isOdd, R.add, 111, ys); //=> 111
*/
var reduceWhile = _curryN(4, [], function _reduceWhile(pred, fn, a, list) {
return _reduce(function (acc, x) {
return pred(acc, x) ? fn(acc, x) : _reduced(acc);
}, a, list);
});
/**
* The complement of `filter`.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig Filterable f => (a -> Boolean) -> f a -> f a
* @param {Function} pred
* @param {Array} filterable
* @return {Array}
* @see R.filter, R.transduce, R.addIndex
* @example
*
* var isOdd = (n) => n % 2 === 1;
*
* R.reject(isOdd, [1, 2, 3, 4]); //=> [2, 4]
*
* R.reject(isOdd, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}
*/
var reject = _curry2(function reject(pred, filterable) {
return filter(_complement(pred), filterable);
});
/**
* Returns a fixed list of size `n` containing a specified identical value.
*
* @func
* @memberOf R
* @since v0.1.1
* @category List
* @sig a -> n -> [a]
* @param {*} value The value to repeat.
* @param {Number} n The desired size of the output list.
* @return {Array} A new array containing `n` `value`s.
* @example
*
* R.repeat('hi', 5); //=> ['hi', 'hi', 'hi', 'hi', 'hi']
*
* var obj = {};
* var repeatedObjs = R.repeat(obj, 5); //=> [{}, {}, {}, {}, {}]
* repeatedObjs[0] === repeatedObjs[1]; //=> true
*/
var repeat = _curry2(function repeat(value, n) {
return times(always(value), n);
});
/**
* Adds together all the elements of a list.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig [Number] -> Number
* @param {Array} list An array of numbers
* @return {Number} The sum of all the numbers in the list.
* @see R.reduce
* @example
*
* R.sum([2,4,6,8,100,1]); //=> 121
*/
var sum = reduce(add, 0);
/**
* Returns a new list containing the last `n` elements of the given list.
* If `n > list.length`, returns a list of `list.length` elements.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig Number -> [a] -> [a]
* @sig Number -> String -> String
* @param {Number} n The number of elements to return.
* @param {Array} xs The collection to consider.
* @return {Array}
* @see R.dropLast
* @example
*
* R.takeLast(1, ['foo', 'bar', 'baz']); //=> ['baz']
* R.takeLast(2, ['foo', 'bar', 'baz']); //=> ['bar', 'baz']
* R.takeLast(3, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
* R.takeLast(4, ['foo', 'bar', 'baz']); //=> ['foo', 'bar', 'baz']
* R.takeLast(3, 'ramda'); //=> 'mda'
*/
var takeLast = _curry2(function takeLast(n, xs) {
return drop(n >= 0 ? xs.length - n : 0, xs);
});
/**
* Initializes a transducer using supplied iterator function. Returns a single
* item by iterating through the list, successively calling the transformed
* iterator function and passing it an accumulator value and the current value
* from the array, and then passing the result to the next call.
*
* The iterator function receives two values: *(acc, value)*. It will be
* wrapped as a transformer to initialize the transducer. A transformer can be
* passed directly in place of an iterator function. In both cases, iteration
* may be stopped early with the `R.reduced` function.
*
* A transducer is a function that accepts a transformer and returns a
* transformer and can be composed directly.
*
* A transformer is an an object that provides a 2-arity reducing iterator
* function, step, 0-arity initial value function, init, and 1-arity result
* extraction function, result. The step function is used as the iterator
* function in reduce. The result function is used to convert the final
* accumulator into the return type and in most cases is R.identity. The init
* function can be used to provide an initial accumulator, but is ignored by
* transduce.
*
* The iteration is performed with R.reduce after initializing the transducer.
*
* @func
* @memberOf R
* @since v0.12.0
* @category List
* @sig (c -> c) -> (a,b -> a) -> a -> [b] -> a
* @param {Function} xf The transducer function. Receives a transformer and returns a transformer.
* @param {Function} fn The iterator function. Receives two values, the accumulator and the
* current element from the array. Wrapped as transformer, if necessary, and used to
* initialize the transducer
* @param {*} acc The initial accumulator value.
* @param {Array} list The list to iterate over.
* @return {*} The final, accumulated value.
* @see R.reduce, R.reduced, R.into
* @example
*
* var numbers = [1, 2, 3, 4];
* var transducer = R.compose(R.map(R.add(1)), R.take(2));
*
* R.transduce(transducer, R.flip(R.append), [], numbers); //=> [2, 3]
*/
var transduce = curryN(4, function transduce(xf, fn, acc, list) {
return _reduce(xf(typeof fn === 'function' ? _xwrap(fn) : fn), acc, list);
});
/**
* Combines two lists into a set (i.e. no duplicates) composed of the elements
* of each list. Duplication is determined according to the value returned by
* applying the supplied predicate to two list elements.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig (a -> a -> Boolean) -> [*] -> [*] -> [*]
* @param {Function} pred A predicate used to test whether two items are equal.
* @param {Array} list1 The first list.
* @param {Array} list2 The second list.
* @return {Array} The first and second lists concatenated, with
* duplicates removed.
* @see R.union
* @example
*
* var l1 = [{a: 1}, {a: 2}];
* var l2 = [{a: 1}, {a: 4}];
* R.unionWith(R.eqBy(R.prop('a')), l1, l2); //=> [{a: 1}, {a: 2}, {a: 4}]
*/
var unionWith = _curry3(function unionWith(pred, list1, list2) {
return uniqWith(pred, _concat(list1, list2));
});
/**
* Takes a spec object and a test object; returns true if the test satisfies
* the spec, false otherwise. An object satisfies the spec if, for each of the
* spec's own properties, accessing that property of the object gives the same
* value (in `R.equals` terms) as accessing that property of the spec.
*
* `whereEq` is a specialization of [`where`](#where).
*
* @func
* @memberOf R
* @since v0.14.0
* @category Object
* @sig {String: *} -> {String: *} -> Boolean
* @param {Object} spec
* @param {Object} testObj
* @return {Boolean}
* @see R.where
* @example
*
* // pred :: Object -> Boolean
* var pred = R.whereEq({a: 1, b: 2});
*
* pred({a: 1}); //=> false
* pred({a: 1, b: 2}); //=> true
* pred({a: 1, b: 2, c: 3}); //=> true
* pred({a: 1, b: 1}); //=> false
*/
var whereEq = _curry2(function whereEq(spec, testObj) {
return where(map(equals, spec), testObj);
});
var _flatCat = function () {
var preservingReduced = function (xf) {
return {
'@@transducer/init': _xfBase.init,
'@@transducer/result': function (result) {
return xf['@@transducer/result'](result);
},
'@@transducer/step': function (result, input) {
var ret = xf['@@transducer/step'](result, input);
return ret['@@transducer/reduced'] ? _forceReduced(ret) : ret;
}
};
};
return function _xcat(xf) {
var rxf = preservingReduced(xf);
return {
'@@transducer/init': _xfBase.init,
'@@transducer/result': function (result) {
return rxf['@@transducer/result'](result);
},
'@@transducer/step': function (result, input) {
return !isArrayLike(input) ? _reduce(rxf, result, [input]) : _reduce(rxf, result, input);
}
};
};
}();
// Array.prototype.indexOf doesn't exist below IE9
// manually crawl the list to distinguish between +0 and -0
// NaN
// non-zero numbers can utilise Set
// all these types can utilise Set
// null can utilise Set
// anything else not covered above, defer to R.equals
var _indexOf = function _indexOf(list, a, idx) {
var inf, item;
// Array.prototype.indexOf doesn't exist below IE9
if (typeof list.indexOf === 'function') {
switch (typeof a) {
case 'number':
if (a === 0) {
// manually crawl the list to distinguish between +0 and -0
inf = 1 / a;
while (idx < list.length) {
item = list[idx];
if (item === 0 && 1 / item === inf) {
return idx;
}
idx += 1;
}
return -1;
} else if (a !== a) {
// NaN
while (idx < list.length) {
item = list[idx];
if (typeof item === 'number' && item !== item) {
return idx;
}
idx += 1;
}
return -1;
}
// non-zero numbers can utilise Set
return list.indexOf(a, idx);
// all these types can utilise Set
case 'string':
case 'boolean':
case 'function':
case 'undefined':
return list.indexOf(a, idx);
case 'object':
if (a === null) {
// null can utilise Set
return list.indexOf(a, idx);
}
}
}
// anything else not covered above, defer to R.equals
while (idx < list.length) {
if (equals(list[idx], a)) {
return idx;
}
idx += 1;
}
return -1;
};
var _xchain = _curry2(function _xchain(f, xf) {
return map(f, _flatCat(xf));
});
/**
* Takes a list of predicates and returns a predicate that returns true for a
* given list of arguments if every one of the provided predicates is satisfied
* by those arguments.
*
* The function returned is a curried function whose arity matches that of the
* highest-arity predicate.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Logic
* @sig [(*... -> Boolean)] -> (*... -> Boolean)
* @param {Array} preds
* @return {Function}
* @see R.anyPass
* @example
*
* var isQueen = R.propEq('rank', 'Q');
* var isSpade = R.propEq('suit', '♠︎');
* var isQueenOfSpades = R.allPass([isQueen, isSpade]);
*
* isQueenOfSpades({rank: 'Q', suit: '♣︎'}); //=> false
* isQueenOfSpades({rank: 'Q', suit: '♠︎'}); //=> true
*/
var allPass = _curry1(function allPass(preds) {
return curryN(reduce(max, 0, pluck('length', preds)), function () {
var idx = 0;
var len = preds.length;
while (idx < len) {
if (!preds[idx].apply(this, arguments)) {
return false;
}
idx += 1;
}
return true;
});
});
/**
* Takes a list of predicates and returns a predicate that returns true for a
* given list of arguments if at least one of the provided predicates is
* satisfied by those arguments.
*
* The function returned is a curried function whose arity matches that of the
* highest-arity predicate.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Logic
* @sig [(*... -> Boolean)] -> (*... -> Boolean)
* @param {Array} preds
* @return {Function}
* @see R.allPass
* @example
*
* var gte = R.anyPass([R.gt, R.equals]);
*
* gte(3, 2); //=> true
* gte(2, 2); //=> true
* gte(2, 3); //=> false
*/
var anyPass = _curry1(function anyPass(preds) {
return curryN(reduce(max, 0, pluck('length', preds)), function () {
var idx = 0;
var len = preds.length;
while (idx < len) {
if (preds[idx].apply(this, arguments)) {
return true;
}
idx += 1;
}
return false;
});
});
/**
* ap applies a list of functions to a list of values.
*
* Dispatches to the `ap` method of the second argument, if present. Also
* treats curried functions as applicatives.
*
* @func
* @memberOf R
* @since v0.3.0
* @category Function
* @sig [a -> b] -> [a] -> [b]
* @sig Apply f => f (a -> b) -> f a -> f b
* @param {Array} fns An array of functions
* @param {Array} vs An array of values
* @return {Array} An array of results of applying each of `fns` to all of `vs` in turn.
* @example
*
* R.ap([R.multiply(2), R.add(3)], [1,2,3]); //=> [2, 4, 6, 4, 5, 6]
*/
// else
var ap = _curry2(function ap(applicative, fn) {
return typeof applicative.ap === 'function' ? applicative.ap(fn) : typeof applicative === 'function' ? function (x) {
return applicative(x)(fn(x));
} : // else
_reduce(function (acc, f) {
return _concat(acc, map(f, fn));
}, [], applicative);
});
/**
* Given a spec object recursively mapping properties to functions, creates a
* function producing an object of the same structure, by mapping each property
* to the result of calling its associated function with the supplied arguments.
*
* @func
* @memberOf R
* @since v0.20.0
* @category Function
* @sig {k: ((a, b, ..., m) -> v)} -> ((a, b, ..., m) -> {k: v})
* @param {Object} spec an object recursively mapping properties to functions for
* producing the values for these properties.
* @return {Function} A function that returns an object of the same structure
* as `spec', with each property set to the value returned by calling its
* associated function with the supplied arguments.
* @see R.converge, R.juxt
* @example
*
* var getMetrics = R.applySpec({
* sum: R.add,
* nested: { mul: R.multiply }
* });
* getMetrics(2, 4); // => { sum: 6, nested: { mul: 8 } }
*/
var applySpec = _curry1(function applySpec(spec) {
spec = map(function (v) {
return typeof v == 'function' ? v : applySpec(v);
}, spec);
return curryN(reduce(max, 0, pluck('length', values(spec))), function () {
var args = arguments;
return map(function (f) {
return apply(f, args);
}, spec);
});
});
/**
* Returns the result of calling its first argument with the remaining
* arguments. This is occasionally useful as a converging function for
* `R.converge`: the left branch can produce a function while the right branch
* produces a value to be passed to that function as an argument.
*
* @func
* @memberOf R
* @since v0.9.0
* @category Function
* @sig (*... -> a),*... -> a
* @param {Function} fn The function to apply to the remaining arguments.
* @param {...*} args Any number of positional arguments.
* @return {*}
* @see R.apply
* @example
*
* var indentN = R.pipe(R.times(R.always(' ')),
* R.join(''),
* R.replace(/^(?!$)/gm));
*
* var format = R.converge(R.call, [
* R.pipe(R.prop('indent'), indentN),
* R.prop('value')
* ]);
*
* format({indent: 2, value: 'foo\nbar\nbaz\n'}); //=> ' foo\n bar\n baz\n'
*/
var call = curry(function call(fn) {
return fn.apply(this, _slice(arguments, 1));
});
/**
* `chain` maps a function over a list and concatenates the results. `chain`
* is also known as `flatMap` in some libraries
*
* Dispatches to the `chain` method of the second argument, if present,
* according to the [FantasyLand Chain spec](https://github.com/fantasyland/fantasy-land#chain).
*
* @func
* @memberOf R
* @since v0.3.0
* @category List
* @sig Chain m => (a -> m b) -> m a -> m b
* @param {Function} fn
* @param {Array} list
* @return {Array}
* @example
*
* var duplicate = n => [n, n];
* R.chain(duplicate, [1, 2, 3]); //=> [1, 1, 2, 2, 3, 3]
*/
var chain = _curry2(_dispatchable('chain', _xchain, function chain(fn, monad) {
if (typeof monad === 'function') {
return function () {
return monad.call(this, fn.apply(this, arguments)).apply(this, arguments);
};
}
return _makeFlat(false)(map(fn, monad));
}));
/**
* Returns a function, `fn`, which encapsulates if/else-if/else logic.
* `R.cond` takes a list of [predicate, transform] pairs. All of the arguments
* to `fn` are applied to each of the predicates in turn until one returns a
* "truthy" value, at which point `fn` returns the result of applying its
* arguments to the corresponding transformer. If none of the predicates
* matches, `fn` returns undefined.
*
* @func
* @memberOf R
* @since v0.6.0
* @category Logic
* @sig [[(*... -> Boolean),(*... -> *)]] -> (*... -> *)
* @param {Array} pairs
* @return {Function}
* @example
*
* var fn = R.cond([
* [R.equals(0), R.always('water freezes at 0°C')],
* [R.equals(100), R.always('water boils at 100°C')],
* [R.T, temp => 'nothing special happens at ' + temp + '°C']
* ]);
* fn(0); //=> 'water freezes at 0°C'
* fn(50); //=> 'nothing special happens at 50°C'
* fn(100); //=> 'water boils at 100°C'
*/
var cond = _curry1(function cond(pairs) {
var arity = reduce(max, 0, map(function (pair) {
return pair[0].length;
}, pairs));
return _arity(arity, function () {
var idx = 0;
while (idx < pairs.length) {
if (pairs[idx][0].apply(this, arguments)) {
return pairs[idx][1].apply(this, arguments);
}
idx += 1;
}
});
});
/**
* Wraps a constructor function inside a curried function that can be called
* with the same arguments and returns the same type. The arity of the function
* returned is specified to allow using variadic constructor functions.
*
* @func
* @memberOf R
* @since v0.4.0
* @category Function
* @sig Number -> (* -> {*}) -> (* -> {*})
* @param {Number} n The arity of the constructor function.
* @param {Function} Fn The constructor function to wrap.
* @return {Function} A wrapped, curried constructor function.
* @example
*
* // Variadic constructor function
* var Widget = () => {
* this.children = Array.prototype.slice.call(arguments);
* // ...
* };
* Widget.prototype = {
* // ...
* };
* var allConfigs = [
* // ...
* ];
* R.map(R.constructN(1, Widget), allConfigs); // a list of Widgets
*/
var constructN = _curry2(function constructN(n, Fn) {
if (n > 10) {
throw new Error('Constructor with greater than ten arguments');
}
if (n === 0) {
return function () {
return new Fn();
};
}
return curry(nAry(n, function ($0, $1, $2, $3, $4, $5, $6, $7, $8, $9) {
switch (arguments.length) {
case 1:
return new Fn($0);
case 2:
return new Fn($0, $1);
case 3:
return new Fn($0, $1, $2);
case 4:
return new Fn($0, $1, $2, $3);
case 5:
return new Fn($0, $1, $2, $3, $4);
case 6:
return new Fn($0, $1, $2, $3, $4, $5);
case 7:
return new Fn($0, $1, $2, $3, $4, $5, $6);
case 8:
return new Fn($0, $1, $2, $3, $4, $5, $6, $7);
case 9:
return new Fn($0, $1, $2, $3, $4, $5, $6, $7, $8);
case 10:
return new Fn($0, $1, $2, $3, $4, $5, $6, $7, $8, $9);
}
}));
});
/**
* Accepts a converging function and a list of branching functions and returns
* a new function. When invoked, this new function is applied to some
* arguments, each branching function is applied to those same arguments. The
* results of each branching function are passed as arguments to the converging
* function to produce the return value.
*
* @func
* @memberOf R
* @since v0.4.2
* @category Function
* @sig (x1 -> x2 -> ... -> z) -> [(a -> b -> ... -> x1), (a -> b -> ... -> x2), ...] -> (a -> b -> ... -> z)
* @param {Function} after A function. `after` will be invoked with the return values of
* `fn1` and `fn2` as its arguments.
* @param {Array} functions A list of functions.
* @return {Function} A new function.
* @example
*
* var add = (a, b) => a + b;
* var multiply = (a, b) => a * b;
* var subtract = (a, b) => a - b;
*
* //≅ multiply( add(1, 2), subtract(1, 2) );
* R.converge(multiply, [add, subtract])(1, 2); //=> -3
*
* var add3 = (a, b, c) => a + b + c;
* R.converge(add3, [multiply, add, subtract])(1, 2); //=> 4
*/
var converge = _curry2(function converge(after, fns) {
return curryN(reduce(max, 0, pluck('length', fns)), function () {
var args = arguments;
var context = this;
return after.apply(context, _map(function (fn) {
return fn.apply(context, args);
}, fns));
});
});
/**
* Counts the elements of a list according to how many match each value of a
* key generated by the supplied function. Returns an object mapping the keys
* produced by `fn` to the number of occurrences in the list. Note that all
* keys are coerced to strings because of how JavaScript objects work.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig (a -> String) -> [a] -> {*}
* @param {Function} fn The function used to map values to keys.
* @param {Array} list The list to count elements from.
* @return {Object} An object mapping keys to number of occurrences in the list.
* @example
*
* var numbers = [1.0, 1.1, 1.2, 2.0, 3.0, 2.2];
* var letters = R.split('', 'abcABCaaaBBc');
* R.countBy(Math.floor)(numbers); //=> {'1': 3, '2': 2, '3': 1}
* R.countBy(R.toLower)(letters); //=> {'a': 5, 'b': 4, 'c': 3}
*/
var countBy = reduceBy(function (acc, elem) {
return acc + 1;
}, 0);
/**
* Returns a new list without any consecutively repeating elements. Equality is
* determined by applying the supplied predicate two consecutive elements. The
* first element in a series of equal element is the one being preserved.
*
* Dispatches to the `dropRepeatsWith` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.14.0
* @category List
* @sig (a, a -> Boolean) -> [a] -> [a]
* @param {Function} pred A predicate used to test whether two items are equal.
* @param {Array} list The array to consider.
* @return {Array} `list` without repeating elements.
* @see R.transduce
* @example
*
* var l = [1, -1, 1, 3, 4, -4, -4, -5, 5, 3, 3];
* R.dropRepeatsWith(R.eqBy(Math.abs), l); //=> [1, 3, 4, -5, 3]
*/
var dropRepeatsWith = _curry2(_dispatchable('dropRepeatsWith', _xdropRepeatsWith, function dropRepeatsWith(pred, list) {
var result = [];
var idx = 1;
var len = list.length;
if (len !== 0) {
result[0] = list[0];
while (idx < len) {
if (!pred(last(result), list[idx])) {
result[result.length] = list[idx];
}
idx += 1;
}
}
return result;
}));
/**
* Takes a function and two values in its domain and returns `true` if the
* values map to the same value in the codomain; `false` otherwise.
*
* @func
* @memberOf R
* @since v0.18.0
* @category Relation
* @sig (a -> b) -> a -> a -> Boolean
* @param {Function} f
* @param {*} x
* @param {*} y
* @return {Boolean}
* @example
*
* R.eqBy(Math.abs, 5, -5); //=> true
*/
var eqBy = _curry3(function eqBy(f, x, y) {
return equals(f(x), f(y));
});
/**
* Reports whether two objects have the same value, in `R.equals` terms, for
* the specified property. Useful as a curried predicate.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig k -> {k: v} -> {k: v} -> Boolean
* @param {String} prop The name of the property to compare
* @param {Object} obj1
* @param {Object} obj2
* @return {Boolean}
*
* @example
*
* var o1 = { a: 1, b: 2, c: 3, d: 4 };
* var o2 = { a: 10, b: 20, c: 3, d: 40 };
* R.eqProps('a', o1, o2); //=> false
* R.eqProps('c', o1, o2); //=> true
*/
var eqProps = _curry3(function eqProps(prop, obj1, obj2) {
return equals(obj1[prop], obj2[prop]);
});
/**
* Splits a list into sub-lists stored in an object, based on the result of
* calling a String-returning function on each element, and grouping the
* results according to values returned.
*
* Dispatches to the `groupBy` method of the second argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig (a -> String) -> [a] -> {String: [a]}
* @param {Function} fn Function :: a -> String
* @param {Array} list The array to group
* @return {Object} An object with the output of `fn` for keys, mapped to arrays of elements
* that produced that key when passed to `fn`.
* @see R.transduce
* @example
*
* var byGrade = R.groupBy(function(student) {
* var score = student.score;
* return score < 65 ? 'F' :
* score < 70 ? 'D' :
* score < 80 ? 'C' :
* score < 90 ? 'B' : 'A';
* });
* var students = [{name: 'Abby', score: 84},
* {name: 'Eddy', score: 58},
* // ...
* {name: 'Jack', score: 69}];
* byGrade(students);
* // {
* // 'A': [{name: 'Dianne', score: 99}],
* // 'B': [{name: 'Abby', score: 84}]
* // // ...,
* // 'F': [{name: 'Eddy', score: 58}]
* // }
*/
var groupBy = _curry2(_checkForMethod('groupBy', reduceBy(function (acc, item) {
if (acc == null) {
acc = [];
}
acc.push(item);
return acc;
}, null)));
/**
* Given a function that generates a key, turns a list of objects into an
* object indexing the objects by the given key. Note that if multiple
* objects generate the same value for the indexing key only the last value
* will be included in the generated object.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig (a -> String) -> [{k: v}] -> {k: {k: v}}
* @param {Function} fn Function :: a -> String
* @param {Array} array The array of objects to index
* @return {Object} An object indexing each array element by the given property.
* @example
*
* var list = [{id: 'xyz', title: 'A'}, {id: 'abc', title: 'B'}];
* R.indexBy(R.prop('id'), list);
* //=> {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}}
*/
var indexBy = reduceBy(function (acc, elem) {
return elem;
}, null);
/**
* Returns the position of the first occurrence of an item in an array, or -1
* if the item is not included in the array. `R.equals` is used to determine
* equality.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig a -> [a] -> Number
* @param {*} target The item to find.
* @param {Array} xs The array to search in.
* @return {Number} the index of the target, or -1 if the target is not found.
* @see R.lastIndexOf
* @example
*
* R.indexOf(3, [1,2,3,4]); //=> 2
* R.indexOf(10, [1,2,3,4]); //=> -1
*/
var indexOf = _curry2(function indexOf(target, xs) {
return typeof xs.indexOf === 'function' && !_isArray(xs) ? xs.indexOf(target) : _indexOf(xs, target, 0);
});
/**
* juxt applies a list of functions to a list of values.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Function
* @sig [(a, b, ..., m) -> n] -> ((a, b, ..., m) -> [n])
* @param {Array} fns An array of functions
* @return {Function} A function that returns a list of values after applying each of the original `fns` to its parameters.
* @see R.applySpec
* @example
*
* var getRange = R.juxt([Math.min, Math.max]);
* getRange(3, 4, 9, -3); //=> [-3, 9]
*/
var juxt = _curry1(function juxt(fns) {
return converge(_arrayOf, fns);
});
/**
* Returns a lens for the given getter and setter functions. The getter "gets"
* the value of the focus; the setter "sets" the value of the focus. The setter
* should not mutate the data structure.
*
* @func
* @memberOf R
* @since v0.8.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig (s -> a) -> ((a, s) -> s) -> Lens s a
* @param {Function} getter
* @param {Function} setter
* @return {Lens}
* @see R.view, R.set, R.over, R.lensIndex, R.lensProp
* @example
*
* var xLens = R.lens(R.prop('x'), R.assoc('x'));
*
* R.view(xLens, {x: 1, y: 2}); //=> 1
* R.set(xLens, 4, {x: 1, y: 2}); //=> {x: 4, y: 2}
* R.over(xLens, R.negate, {x: 1, y: 2}); //=> {x: -1, y: 2}
*/
var lens = _curry2(function lens(getter, setter) {
return function (toFunctorFn) {
return function (target) {
return map(function (focus) {
return setter(focus, target);
}, toFunctorFn(getter(target)));
};
};
});
/**
* Returns a lens whose focus is the specified index.
*
* @func
* @memberOf R
* @since v0.14.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig Number -> Lens s a
* @param {Number} n
* @return {Lens}
* @see R.view, R.set, R.over
* @example
*
* var headLens = R.lensIndex(0);
*
* R.view(headLens, ['a', 'b', 'c']); //=> 'a'
* R.set(headLens, 'x', ['a', 'b', 'c']); //=> ['x', 'b', 'c']
* R.over(headLens, R.toUpper, ['a', 'b', 'c']); //=> ['A', 'b', 'c']
*/
var lensIndex = _curry1(function lensIndex(n) {
return lens(nth(n), update(n));
});
/**
* Returns a lens whose focus is the specified path.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig [String] -> Lens s a
* @param {Array} path The path to use.
* @return {Lens}
* @see R.view, R.set, R.over
* @example
*
* var xyLens = R.lensPath(['x', 'y']);
*
* R.view(xyLens, {x: {y: 2, z: 3}}); //=> 2
* R.set(xyLens, 4, {x: {y: 2, z: 3}}); //=> {x: {y: 4, z: 3}}
* R.over(xyLens, R.negate, {x: {y: 2, z: 3}}); //=> {x: {y: -2, z: 3}}
*/
var lensPath = _curry1(function lensPath(p) {
return lens(path(p), assocPath(p));
});
/**
* Returns a lens whose focus is the specified property.
*
* @func
* @memberOf R
* @since v0.14.0
* @category Object
* @typedefn Lens s a = Functor f => (a -> f a) -> s -> f s
* @sig String -> Lens s a
* @param {String} k
* @return {Lens}
* @see R.view, R.set, R.over
* @example
*
* var xLens = R.lensProp('x');
*
* R.view(xLens, {x: 1, y: 2}); //=> 1
* R.set(xLens, 4, {x: 1, y: 2}); //=> {x: 4, y: 2}
* R.over(xLens, R.negate, {x: 1, y: 2}); //=> {x: -1, y: 2}
*/
var lensProp = _curry1(function lensProp(k) {
return lens(prop(k), assoc(k));
});
/**
* "lifts" a function to be the specified arity, so that it may "map over" that
* many lists, Functions or other objects that satisfy the [FantasyLand Apply spec](https://github.com/fantasyland/fantasy-land#apply).
*
* @func
* @memberOf R
* @since v0.7.0
* @category Function
* @sig Number -> (*... -> *) -> ([*]... -> [*])
* @param {Function} fn The function to lift into higher context
* @return {Function} The lifted function.
* @see R.lift, R.ap
* @example
*
* var madd3 = R.liftN(3, R.curryN(3, (...args) => R.sum(args)));
* madd3([1,2,3], [1,2,3], [1]); //=> [3, 4, 5, 4, 5, 6, 5, 6, 7]
*/
var liftN = _curry2(function liftN(arity, fn) {
var lifted = curryN(arity, fn);
return curryN(arity, function () {
return _reduce(ap, map(lifted, arguments[0]), _slice(arguments, 1));
});
});
/**
* Returns the mean of the given list of numbers.
*
* @func
* @memberOf R
* @since v0.14.0
* @category Math
* @sig [Number] -> Number
* @param {Array} list
* @return {Number}
* @example
*
* R.mean([2, 7, 9]); //=> 6
* R.mean([]); //=> NaN
*/
var mean = _curry1(function mean(list) {
return sum(list) / list.length;
});
/**
* Returns the median of the given list of numbers.
*
* @func
* @memberOf R
* @since v0.14.0
* @category Math
* @sig [Number] -> Number
* @param {Array} list
* @return {Number}
* @example
*
* R.median([2, 9, 7]); //=> 7
* R.median([7, 2, 10, 9]); //=> 8
* R.median([]); //=> NaN
*/
var median = _curry1(function median(list) {
var len = list.length;
if (len === 0) {
return NaN;
}
var width = 2 - len % 2;
var idx = (len - width) / 2;
return mean(_slice(list).sort(function (a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}).slice(idx, idx + width));
});
/**
* Takes a predicate and a list or other "filterable" object and returns the
* pair of filterable objects of the same type of elements which do and do not
* satisfy, the predicate, respectively.
*
* @func
* @memberOf R
* @since v0.1.4
* @category List
* @sig Filterable f => (a -> Boolean) -> f a -> [f a, f a]
* @param {Function} pred A predicate to determine which side the element belongs to.
* @param {Array} filterable the list (or other filterable) to partition.
* @return {Array} An array, containing first the subset of elements that satisfy the
* predicate, and second the subset of elements that do not satisfy.
* @see R.filter, R.reject
* @example
*
* R.partition(R.contains('s'), ['sss', 'ttt', 'foo', 'bars']);
* // => [ [ 'sss', 'bars' ], [ 'ttt', 'foo' ] ]
*
* R.partition(R.contains('s'), { a: 'sss', b: 'ttt', foo: 'bars' });
* // => [ { a: 'sss', foo: 'bars' }, { b: 'ttt' } ]
*/
var partition = juxt([
filter,
reject
]);
/**
* Performs left-to-right function composition. The leftmost function may have
* any arity; the remaining functions must be unary.
*
* In some libraries this function is named `sequence`.
*
* **Note:** The result of pipe is not automatically curried.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (((a, b, ..., n) -> o), (o -> p), ..., (x -> y), (y -> z)) -> ((a, b, ..., n) -> z)
* @param {...Function} functions
* @return {Function}
* @see R.compose
* @example
*
* var f = R.pipe(Math.pow, R.negate, R.inc);
*
* f(3, 4); // -(3^4) + 1
*/
var pipe = function pipe() {
if (arguments.length === 0) {
throw new Error('pipe requires at least one argument');
}
return _arity(arguments[0].length, reduce(_pipe, arguments[0], tail(arguments)));
};
/**
* Performs left-to-right composition of one or more Promise-returning
* functions. The leftmost function may have any arity; the remaining functions
* must be unary.
*
* @func
* @memberOf R
* @since v0.10.0
* @category Function
* @sig ((a -> Promise b), (b -> Promise c), ..., (y -> Promise z)) -> (a -> Promise z)
* @param {...Function} functions
* @return {Function}
* @see R.composeP
* @example
*
* // followersForUser :: String -> Promise [User]
* var followersForUser = R.pipeP(db.getUserById, db.getFollowers);
*/
var pipeP = function pipeP() {
if (arguments.length === 0) {
throw new Error('pipeP requires at least one argument');
}
return _arity(arguments[0].length, reduce(_pipeP, arguments[0], tail(arguments)));
};
/**
* Multiplies together all the elements of a list.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig [Number] -> Number
* @param {Array} list An array of numbers
* @return {Number} The product of all the numbers in the list.
* @see R.reduce
* @example
*
* R.product([2,4,6,8,100,1]); //=> 38400
*/
var product = reduce(multiply, 1);
/**
* Transforms a [Traversable](https://github.com/fantasyland/fantasy-land#traversable)
* of [Applicative](https://github.com/fantasyland/fantasy-land#applicative) into an
* Applicative of Traversable.
*
* Dispatches to the `sequence` method of the second argument, if present.
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig (Applicative f, Traversable t) => (a -> f a) -> t (f a) -> f (t a)
* @param {Function} of
* @param {*} traversable
* @return {*}
* @see R.traverse
* @example
*
* R.sequence(Maybe.of, [Just(1), Just(2), Just(3)]); //=> Just([1, 2, 3])
* R.sequence(Maybe.of, [Just(1), Just(2), Nothing()]); //=> Nothing()
*
* R.sequence(R.of, Just([1, 2, 3])); //=> [Just(1), Just(2), Just(3)]
* R.sequence(R.of, Nothing()); //=> [Nothing()]
*/
var sequence = _curry2(function sequence(of, traversable) {
return typeof traversable.sequence === 'function' ? traversable.sequence(of) : reduceRight(function (acc, x) {
return ap(map(prepend, x), acc);
}, of([]), traversable);
});
/**
* Maps an [Applicative](https://github.com/fantasyland/fantasy-land#applicative)-returning
* function over a [Traversable](https://github.com/fantasyland/fantasy-land#traversable),
* then uses [`sequence`](#sequence) to transform the resulting Traversable of Applicative
* into an Applicative of Traversable.
*
* Dispatches to the `sequence` method of the third argument, if present.
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig (Applicative f, Traversable t) => (a -> f a) -> (a -> f b) -> t a -> f (t b)
* @param {Function} of
* @param {Function} f
* @param {*} traversable
* @return {*}
* @see R.sequence
* @example
*
* // Returns `Nothing` if the given divisor is `0`
* safeDiv = n => d => d === 0 ? Nothing() : Just(n / d)
*
* R.traverse(Maybe.of, safeDiv(10), [2, 4, 5]); //=> Just([5, 2.5, 2])
* R.traverse(Maybe.of, safeDiv(10), [2, 0, 5]); //=> Nothing
*/
var traverse = _curry3(function traverse(of, f, traversable) {
return sequence(of, map(f, traversable));
});
/**
* Shorthand for `R.chain(R.identity)`, which removes one level of nesting from
* any [Chain](https://github.com/fantasyland/fantasy-land#chain).
*
* @func
* @memberOf R
* @since v0.3.0
* @category List
* @sig Chain c => c (c a) -> c a
* @param {*} list
* @return {*}
* @see R.flatten, R.chain
* @example
*
* R.unnest([1, [2], [[3]]]); //=> [1, 2, [3]]
* R.unnest([[1, 2], [3, 4], [5, 6]]); //=> [1, 2, 3, 4, 5, 6]
*/
var unnest = chain(_identity);
var _contains = function _contains(a, list) {
return _indexOf(list, a, 0) >= 0;
};
// mapPairs :: (Object, [String]) -> [String]
var _toString = function _toString(x, seen) {
var recur = function recur(y) {
var xs = seen.concat([x]);
return _contains(y, xs) ? '<Circular>' : _toString(y, xs);
};
// mapPairs :: (Object, [String]) -> [String]
var mapPairs = function (obj, keys) {
return _map(function (k) {
return _quote(k) + ': ' + recur(obj[k]);
}, keys.slice().sort());
};
switch (Object.prototype.toString.call(x)) {
case '[object Arguments]':
return '(function() { return arguments; }(' + _map(recur, x).join(', ') + '))';
case '[object Array]':
return '[' + _map(recur, x).concat(mapPairs(x, reject(function (k) {
return /^\d+$/.test(k);
}, keys(x)))).join(', ') + ']';
case '[object Boolean]':
return typeof x === 'object' ? 'new Boolean(' + recur(x.valueOf()) + ')' : x.toString();
case '[object Date]':
return 'new Date(' + (isNaN(x.valueOf()) ? recur(NaN) : _quote(_toISOString(x))) + ')';
case '[object Null]':
return 'null';
case '[object Number]':
return typeof x === 'object' ? 'new Number(' + recur(x.valueOf()) + ')' : 1 / x === -Infinity ? '-0' : x.toString(10);
case '[object String]':
return typeof x === 'object' ? 'new String(' + recur(x.valueOf()) + ')' : _quote(x);
case '[object Undefined]':
return 'undefined';
default:
if (typeof x.toString === 'function') {
var repr = x.toString();
if (repr !== '[object Object]') {
return repr;
}
}
return '{' + mapPairs(x, keys(x)).join(', ') + '}';
}
};
/**
* Performs right-to-left function composition. The rightmost function may have
* any arity; the remaining functions must be unary.
*
* **Note:** The result of compose is not automatically curried.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig ((y -> z), (x -> y), ..., (o -> p), ((a, b, ..., n) -> o)) -> ((a, b, ..., n) -> z)
* @param {...Function} functions
* @return {Function}
* @see R.pipe
* @example
*
* var f = R.compose(R.inc, R.negate, Math.pow);
*
* f(3, 4); // -(3^4) + 1
*/
var compose = function compose() {
if (arguments.length === 0) {
throw new Error('compose requires at least one argument');
}
return pipe.apply(this, reverse(arguments));
};
/**
* Returns the right-to-left Kleisli composition of the provided functions,
* each of which must return a value of a type supported by [`chain`](#chain).
*
* `R.composeK(h, g, f)` is equivalent to `R.compose(R.chain(h), R.chain(g), R.chain(f))`.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Function
* @sig Chain m => ((y -> m z), (x -> m y), ..., (a -> m b)) -> (m a -> m z)
* @param {...Function}
* @return {Function}
* @see R.pipeK
* @example
*
* // parseJson :: String -> Maybe *
* // get :: String -> Object -> Maybe *
*
* // getStateCode :: Maybe String -> Maybe String
* var getStateCode = R.composeK(
* R.compose(Maybe.of, R.toUpper),
* get('state'),
* get('address'),
* get('user'),
* parseJson
* );
*
* getStateCode(Maybe.of('{"user":{"address":{"state":"ny"}}}'));
* //=> Just('NY')
* getStateCode(Maybe.of('[Invalid JSON]'));
* //=> Nothing()
*/
var composeK = function composeK() {
return compose.apply(this, prepend(identity, map(chain, arguments)));
};
/**
* Performs right-to-left composition of one or more Promise-returning
* functions. The rightmost function may have any arity; the remaining
* functions must be unary.
*
* @func
* @memberOf R
* @since v0.10.0
* @category Function
* @sig ((y -> Promise z), (x -> Promise y), ..., (a -> Promise b)) -> (a -> Promise z)
* @param {...Function} functions
* @return {Function}
* @see R.pipeP
* @example
*
* // followersForUser :: String -> Promise [User]
* var followersForUser = R.composeP(db.getFollowers, db.getUserById);
*/
var composeP = function composeP() {
if (arguments.length === 0) {
throw new Error('composeP requires at least one argument');
}
return pipeP.apply(this, reverse(arguments));
};
/**
* Wraps a constructor function inside a curried function that can be called
* with the same arguments and returns the same type.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (* -> {*}) -> (* -> {*})
* @param {Function} Fn The constructor function to wrap.
* @return {Function} A wrapped, curried constructor function.
* @example
*
* // Constructor function
* var Widget = config => {
* // ...
* };
* Widget.prototype = {
* // ...
* };
* var allConfigs = [
* // ...
* ];
* R.map(R.construct(Widget), allConfigs); // a list of Widgets
*/
var construct = _curry1(function construct(Fn) {
return constructN(Fn.length, Fn);
});
/**
* Returns `true` if the specified value is equal, in `R.equals` terms, to at
* least one element of the given list; `false` otherwise.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig a -> [a] -> Boolean
* @param {Object} a The item to compare against.
* @param {Array} list The array to consider.
* @return {Boolean} `true` if the item is in the list, `false` otherwise.
* @see R.any
* @example
*
* R.contains(3, [1, 2, 3]); //=> true
* R.contains(4, [1, 2, 3]); //=> false
* R.contains([42], [[42]]); //=> true
*/
var contains = _curry2(_contains);
/**
* Finds the set (i.e. no duplicates) of all elements in the first list not
* contained in the second list.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig [*] -> [*] -> [*]
* @param {Array} list1 The first list.
* @param {Array} list2 The second list.
* @return {Array} The elements in `list1` that are not in `list2`.
* @see R.differenceWith, R.symmetricDifference, R.symmetricDifferenceWith
* @example
*
* R.difference([1,2,3,4], [7,6,5,4,3]); //=> [1,2]
* R.difference([7,6,5,4,3], [1,2,3,4]); //=> [7,6,5]
*/
var difference = _curry2(function difference(first, second) {
var out = [];
var idx = 0;
var firstLen = first.length;
while (idx < firstLen) {
if (!_contains(first[idx], second) && !_contains(first[idx], out)) {
out[out.length] = first[idx];
}
idx += 1;
}
return out;
});
/**
* Returns a new list without any consecutively repeating elements. `R.equals`
* is used to determine equality.
*
* Dispatches to the `dropRepeats` method of the first argument, if present.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.14.0
* @category List
* @sig [a] -> [a]
* @param {Array} list The array to consider.
* @return {Array} `list` without repeating elements.
* @see R.transduce
* @example
*
* R.dropRepeats([1, 1, 1, 2, 3, 4, 4, 2, 2]); //=> [1, 2, 3, 4, 2]
*/
var dropRepeats = _curry1(_dispatchable('dropRepeats', _xdropRepeatsWith(equals), dropRepeatsWith(equals)));
/**
* "lifts" a function of arity > 1 so that it may "map over" a list, Function or other
* object that satisfies the [FantasyLand Apply spec](https://github.com/fantasyland/fantasy-land#apply).
*
* @func
* @memberOf R
* @since v0.7.0
* @category Function
* @sig (*... -> *) -> ([*]... -> [*])
* @param {Function} fn The function to lift into higher context
* @return {Function} The lifted function.
* @see R.liftN
* @example
*
* var madd3 = R.lift(R.curry((a, b, c) => a + b + c));
*
* madd3([1,2,3], [1,2,3], [1]); //=> [3, 4, 5, 4, 5, 6, 5, 6, 7]
*
* var madd5 = R.lift(R.curry((a, b, c, d, e) => a + b + c + d + e));
*
* madd5([1,2], [3], [4, 5], [6], [7, 8]); //=> [21, 22, 22, 23, 22, 23, 23, 24]
*/
var lift = _curry1(function lift(fn) {
return liftN(fn.length, fn);
});
/**
* Returns a partial copy of an object omitting the keys specified.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Object
* @sig [String] -> {String: *} -> {String: *}
* @param {Array} names an array of String property names to omit from the new object
* @param {Object} obj The object to copy from
* @return {Object} A new object with properties from `names` not on it.
* @see R.pick
* @example
*
* R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}
*/
var omit = _curry2(function omit(names, obj) {
var result = {};
for (var prop in obj) {
if (!_contains(prop, names)) {
result[prop] = obj[prop];
}
}
return result;
});
/**
* Returns the left-to-right Kleisli composition of the provided functions,
* each of which must return a value of a type supported by [`chain`](#chain).
*
* `R.pipeK(f, g, h)` is equivalent to `R.pipe(R.chain(f), R.chain(g), R.chain(h))`.
*
* @func
* @memberOf R
* @since v0.16.0
* @category Function
* @sig Chain m => ((a -> m b), (b -> m c), ..., (y -> m z)) -> (m a -> m z)
* @param {...Function}
* @return {Function}
* @see R.composeK
* @example
*
* // parseJson :: String -> Maybe *
* // get :: String -> Object -> Maybe *
*
* // getStateCode :: Maybe String -> Maybe String
* var getStateCode = R.pipeK(
* parseJson,
* get('user'),
* get('address'),
* get('state'),
* R.compose(Maybe.of, R.toUpper)
* );
*
* getStateCode(Maybe.of('{"user":{"address":{"state":"ny"}}}'));
* //=> Just('NY')
* getStateCode(Maybe.of('[Invalid JSON]'));
* //=> Nothing()
*/
var pipeK = function pipeK() {
return composeK.apply(this, reverse(arguments));
};
/**
* Returns the string representation of the given value. `eval`'ing the output
* should result in a value equivalent to the input value. Many of the built-in
* `toString` methods do not satisfy this requirement.
*
* If the given value is an `[object Object]` with a `toString` method other
* than `Object.prototype.toString`, this method is invoked with no arguments
* to produce the return value. This means user-defined constructor functions
* can provide a suitable `toString` method. For example:
*
* function Point(x, y) {
* this.x = x;
* this.y = y;
* }
*
* Point.prototype.toString = function() {
* return 'new Point(' + this.x + ', ' + this.y + ')';
* };
*
* R.toString(new Point(1, 2)); //=> 'new Point(1, 2)'
*
* @func
* @memberOf R
* @since v0.14.0
* @category String
* @sig * -> String
* @param {*} val
* @return {String}
* @example
*
* R.toString(42); //=> '42'
* R.toString('abc'); //=> '"abc"'
* R.toString([1, 2, 3]); //=> '[1, 2, 3]'
* R.toString({foo: 1, bar: 2, baz: 3}); //=> '{"bar": 2, "baz": 3, "foo": 1}'
* R.toString(new Date('2001-02-03T04:05:06Z')); //=> 'new Date("2001-02-03T04:05:06.000Z")'
*/
var toString = _curry1(function toString(val) {
return _toString(val, []);
});
/**
* Returns a new list without values in the first argument.
* `R.equals` is used to determine equality.
*
* Acts as a transducer if a transformer is given in list position.
*
* @func
* @memberOf R
* @since v0.19.0
* @category List
* @sig [a] -> [a] -> [a]
* @param {Array} list1 The values to be removed from `list2`.
* @param {Array} list2 The array to remove values from.
* @return {Array} The new array without values in `list1`.
* @see R.transduce
* @example
*
* R.without([1, 2], [1, 2, 1, 3, 4]); //=> [3, 4]
*/
var without = _curry2(function (xs, list) {
return reject(flip(_contains)(xs), list);
});
// A simple Set type that honours R.equals semantics
/* globals Set */
// until we figure out why jsdoc chokes on this
// @param item The item to add to the Set
// @returns {boolean} true if the item did not exist prior, otherwise false
//
//
// @param item The item to check for existence in the Set
// @returns {boolean} true if the item exists in the Set, otherwise false
//
//
// Combines the logic for checking whether an item is a member of the set and
// for adding a new item to the set.
//
// @param item The item to check or add to the Set instance.
// @param shouldAdd If true, the item will be added to the set if it doesn't
// already exist.
// @param set The set instance to check or add to.
// @return {boolean} true if the item already existed, otherwise false.
//
// distinguish between +0 and -0
// these types can all utilise the native Set
// set._items['boolean'] holds a two element array
// representing [ falseExists, trueExists ]
// compare functions for reference equality
/* falls through */
// reduce the search size of heterogeneous sets by creating buckets
// for each type.
// scan through all previously applied items
var _Set = function () {
function _Set() {
/* globals Set */
this._nativeSet = typeof Set === 'function' ? new Set() : null;
this._items = {};
}
// until we figure out why jsdoc chokes on this
// @param item The item to add to the Set
// @returns {boolean} true if the item did not exist prior, otherwise false
//
_Set.prototype.add = function (item) {
return !hasOrAdd(item, true, this);
};
//
// @param item The item to check for existence in the Set
// @returns {boolean} true if the item exists in the Set, otherwise false
//
_Set.prototype.has = function (item) {
return hasOrAdd(item, false, this);
};
//
// Combines the logic for checking whether an item is a member of the set and
// for adding a new item to the set.
//
// @param item The item to check or add to the Set instance.
// @param shouldAdd If true, the item will be added to the set if it doesn't
// already exist.
// @param set The set instance to check or add to.
// @return {boolean} true if the item already existed, otherwise false.
//
function hasOrAdd(item, shouldAdd, set) {
var type = typeof item;
var prevSize, newSize;
switch (type) {
case 'string':
case 'number':
// distinguish between +0 and -0
if (item === 0 && 1 / item === -Infinity) {
if (set._items['-0']) {
return true;
} else {
if (shouldAdd) {
set._items['-0'] = true;
}
return false;
}
}
// these types can all utilise the native Set
if (set._nativeSet !== null) {
if (shouldAdd) {
prevSize = set._nativeSet.size;
set._nativeSet.add(item);
newSize = set._nativeSet.size;
return newSize === prevSize;
} else {
return set._nativeSet.has(item);
}
} else {
if (!(type in set._items)) {
if (shouldAdd) {
set._items[type] = {};
set._items[type][item] = true;
}
return false;
} else if (item in set._items[type]) {
return true;
} else {
if (shouldAdd) {
set._items[type][item] = true;
}
return false;
}
}
case 'boolean':
// set._items['boolean'] holds a two element array
// representing [ falseExists, trueExists ]
if (type in set._items) {
var bIdx = item ? 1 : 0;
if (set._items[type][bIdx]) {
return true;
} else {
if (shouldAdd) {
set._items[type][bIdx] = true;
}
return false;
}
} else {
if (shouldAdd) {
set._items[type] = item ? [
false,
true
] : [
true,
false
];
}
return false;
}
case 'function':
// compare functions for reference equality
if (set._nativeSet !== null) {
if (shouldAdd) {
prevSize = set._nativeSet.size;
set._nativeSet.add(item);
newSize = set._nativeSet.size;
return newSize > prevSize;
} else {
return set._nativeSet.has(item);
}
} else {
if (!(type in set._items)) {
if (shouldAdd) {
set._items[type] = [item];
}
return false;
}
if (!_contains(item, set._items[type])) {
if (shouldAdd) {
set._items[type].push(item);
}
return false;
}
return true;
}
case 'undefined':
if (set._items[type]) {
return true;
} else {
if (shouldAdd) {
set._items[type] = true;
}
return false;
}
case 'object':
if (item === null) {
if (!set._items['null']) {
if (shouldAdd) {
set._items['null'] = true;
}
return false;
}
return true;
}
/* falls through */
default:
// reduce the search size of heterogeneous sets by creating buckets
// for each type.
type = Object.prototype.toString.call(item);
if (!(type in set._items)) {
if (shouldAdd) {
set._items[type] = [item];
}
return false;
}
// scan through all previously applied items
if (!_contains(item, set._items[type])) {
if (shouldAdd) {
set._items[type].push(item);
}
return false;
}
return true;
}
}
return _Set;
}();
/**
* A function wrapping calls to the two functions in an `&&` operation,
* returning the result of the first function if it is false-y and the result
* of the second function otherwise. Note that this is short-circuited,
* meaning that the second function will not be invoked if the first returns a
* false-y value.
*
* In addition to functions, `R.both` also accepts any fantasy-land compatible
* applicative functor.
*
* @func
* @memberOf R
* @since v0.12.0
* @category Logic
* @sig (*... -> Boolean) -> (*... -> Boolean) -> (*... -> Boolean)
* @param {Function} f a predicate
* @param {Function} g another predicate
* @return {Function} a function that applies its arguments to `f` and `g` and `&&`s their outputs together.
* @see R.and
* @example
*
* var gt10 = x => x > 10;
* var even = x => x % 2 === 0;
* var f = R.both(gt10, even);
* f(100); //=> true
* f(101); //=> false
*/
var both = _curry2(function both(f, g) {
return _isFunction(f) ? function _both() {
return f.apply(this, arguments) && g.apply(this, arguments);
} : lift(and)(f, g);
});
/**
* Takes a function `f` and returns a function `g` such that:
*
* - applying `g` to zero or more arguments will give __true__ if applying
* the same arguments to `f` gives a logical __false__ value; and
*
* - applying `g` to zero or more arguments will give __false__ if applying
* the same arguments to `f` gives a logical __true__ value.
*
* `R.complement` will work on all other functors as well.
*
* @func
* @memberOf R
* @since v0.12.0
* @category Logic
* @sig (*... -> *) -> (*... -> Boolean)
* @param {Function} f
* @return {Function}
* @see R.not
* @example
*
* var isEven = n => n % 2 === 0;
* var isOdd = R.complement(isEven);
* isOdd(21); //=> true
* isOdd(42); //=> false
*/
var complement = lift(not);
/**
* Returns the result of concatenating the given lists or strings.
*
* Note: `R.concat` expects both arguments to be of the same type,
* unlike the native `Array.prototype.concat` method. It will throw
* an error if you `concat` an Array with a non-Array value.
*
* Dispatches to the `concat` method of the first argument, if present.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [a] -> [a]
* @sig String -> String -> String
* @param {Array|String} a
* @param {Array|String} b
* @return {Array|String}
*
* @example
*
* R.concat([], []); //=> []
* R.concat([4, 5, 6], [1, 2, 3]); //=> [4, 5, 6, 1, 2, 3]
* R.concat('ABC', 'DEF'); // 'ABCDEF'
*/
var concat = _curry2(function concat(a, b) {
if (a == null || !_isFunction(a.concat)) {
throw new TypeError(toString(a) + ' does not have a method named "concat"');
}
if (_isArray(a) && !_isArray(b)) {
throw new TypeError(toString(b) + ' is not an array');
}
return a.concat(b);
});
/**
* A function wrapping calls to the two functions in an `||` operation,
* returning the result of the first function if it is truth-y and the result
* of the second function otherwise. Note that this is short-circuited,
* meaning that the second function will not be invoked if the first returns a
* truth-y value.
*
* In addition to functions, `R.either` also accepts any fantasy-land compatible
* applicative functor.
*
* @func
* @memberOf R
* @since v0.12.0
* @category Logic
* @sig (*... -> Boolean) -> (*... -> Boolean) -> (*... -> Boolean)
* @param {Function} f a predicate
* @param {Function} g another predicate
* @return {Function} a function that applies its arguments to `f` and `g` and `||`s their outputs together.
* @see R.or
* @example
*
* var gt10 = x => x > 10;
* var even = x => x % 2 === 0;
* var f = R.either(gt10, even);
* f(101); //=> true
* f(8); //=> true
*/
var either = _curry2(function either(f, g) {
return _isFunction(f) ? function _either() {
return f.apply(this, arguments) || g.apply(this, arguments);
} : lift(or)(f, g);
});
/**
* Turns a named method with a specified arity into a function that can be
* called directly supplied with arguments and a target object.
*
* The returned function is curried and accepts `arity + 1` parameters where
* the final parameter is the target object.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig Number -> String -> (a -> b -> ... -> n -> Object -> *)
* @param {Number} arity Number of arguments the returned function should take
* before the target object.
* @param {String} method Name of the method to call.
* @return {Function} A new curried function.
* @example
*
* var sliceFrom = R.invoker(1, 'slice');
* sliceFrom(6, 'abcdefghijklm'); //=> 'ghijklm'
* var sliceFrom6 = R.invoker(2, 'slice')(6);
* sliceFrom6(8, 'abcdefghijklm'); //=> 'gh'
*/
var invoker = _curry2(function invoker(arity, method) {
return curryN(arity + 1, function () {
var target = arguments[arity];
if (target != null && _isFunction(target[method])) {
return target[method].apply(target, _slice(arguments, 0, arity));
}
throw new TypeError(toString(target) + ' does not have a method named "' + method + '"');
});
});
/**
* Returns a string made by inserting the `separator` between each element and
* concatenating all the elements into a single string.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig String -> [a] -> String
* @param {Number|String} separator The string used to separate the elements.
* @param {Array} xs The elements to join into a string.
* @return {String} str The string made by concatenating `xs` with `separator`.
* @see R.split
* @example
*
* var spacer = R.join(' ');
* spacer(['a', 2, 3.4]); //=> 'a 2 3.4'
* R.join('|', [1, 2, 3]); //=> '1|2|3'
*/
var join = invoker(1, 'join');
/**
* Creates a new function that, when invoked, caches the result of calling `fn`
* for a given argument set and returns the result. Subsequent calls to the
* memoized `fn` with the same argument set will not result in an additional
* call to `fn`; instead, the cached result for that set of arguments will be
* returned.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Function
* @sig (*... -> a) -> (*... -> a)
* @param {Function} fn The function to memoize.
* @return {Function} Memoized version of `fn`.
* @example
*
* var count = 0;
* var factorial = R.memoize(n => {
* count += 1;
* return R.product(R.range(1, n + 1));
* });
* factorial(5); //=> 120
* factorial(5); //=> 120
* factorial(5); //=> 120
* count; //=> 1
*/
var memoize = _curry1(function memoize(fn) {
var cache = {};
return _arity(fn.length, function () {
var key = toString(arguments);
if (!_has(key, cache)) {
cache[key] = fn.apply(this, arguments);
}
return cache[key];
});
});
/**
* Splits a string into an array of strings based on the given
* separator.
*
* @func
* @memberOf R
* @since v0.1.0
* @category String
* @sig (String | RegExp) -> String -> [String]
* @param {String|RegExp} sep The pattern.
* @param {String} str The string to separate into an array.
* @return {Array} The array of strings from `str` separated by `str`.
* @see R.join
* @example
*
* var pathComponents = R.split('/');
* R.tail(pathComponents('/usr/local/bin/node')); //=> ['usr', 'local', 'bin', 'node']
*
* R.split('.', 'a.b.c.xyz.d'); //=> ['a', 'b', 'c', 'xyz', 'd']
*/
var split = invoker(1, 'split');
/**
* Finds the set (i.e. no duplicates) of all elements contained in the first or
* second list, but not both.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Relation
* @sig [*] -> [*] -> [*]
* @param {Array} list1 The first list.
* @param {Array} list2 The second list.
* @return {Array} The elements in `list1` or `list2`, but not both.
* @see R.symmetricDifferenceWith, R.difference, R.differenceWith
* @example
*
* R.symmetricDifference([1,2,3,4], [7,6,5,4,3]); //=> [1,2,7,6,5]
* R.symmetricDifference([7,6,5,4,3], [1,2,3,4]); //=> [7,6,5,1,2]
*/
var symmetricDifference = _curry2(function symmetricDifference(list1, list2) {
return concat(difference(list1, list2), difference(list2, list1));
});
/**
* Finds the set (i.e. no duplicates) of all elements contained in the first or
* second list, but not both. Duplication is determined according to the value
* returned by applying the supplied predicate to two list elements.
*
* @func
* @memberOf R
* @since v0.19.0
* @category Relation
* @sig (a -> a -> Boolean) -> [a] -> [a] -> [a]
* @param {Function} pred A predicate used to test whether two items are equal.
* @param {Array} list1 The first list.
* @param {Array} list2 The second list.
* @return {Array} The elements in `list1` or `list2`, but not both.
* @see R.symmetricDifference, R.difference, R.differenceWith
* @example
*
* var eqA = R.eqBy(R.prop('a'));
* var l1 = [{a: 1}, {a: 2}, {a: 3}, {a: 4}];
* var l2 = [{a: 3}, {a: 4}, {a: 5}, {a: 6}];
* R.symmetricDifferenceWith(eqA, l1, l2); //=> [{a: 1}, {a: 2}, {a: 5}, {a: 6}]
*/
var symmetricDifferenceWith = _curry3(function symmetricDifferenceWith(pred, list1, list2) {
return concat(differenceWith(pred, list1, list2), differenceWith(pred, list2, list1));
});
/**
* Determines whether a given string matches a given regular expression.
*
* @func
* @memberOf R
* @since v0.12.0
* @category String
* @sig RegExp -> String -> Boolean
* @param {RegExp} pattern
* @param {String} str
* @return {Boolean}
* @see R.match
* @example
*
* R.test(/^x/, 'xyz'); //=> true
* R.test(/^y/, 'xyz'); //=> false
*/
var test = _curry2(function test(pattern, str) {
if (!_isRegExp(pattern)) {
throw new TypeError('\u2018test\u2019 requires a value of type RegExp as its first argument; received ' + toString(pattern));
}
return _cloneRegExp(pattern).test(str);
});
/**
* The lower case version of a string.
*
* @func
* @memberOf R
* @since v0.9.0
* @category String
* @sig String -> String
* @param {String} str The string to lower case.
* @return {String} The lower case version of `str`.
* @see R.toUpper
* @example
*
* R.toLower('XYZ'); //=> 'xyz'
*/
var toLower = invoker(0, 'toLowerCase');
/**
* The upper case version of a string.
*
* @func
* @memberOf R
* @since v0.9.0
* @category String
* @sig String -> String
* @param {String} str The string to upper case.
* @return {String} The upper case version of `str`.
* @see R.toLower
* @example
*
* R.toUpper('abc'); //=> 'ABC'
*/
var toUpper = invoker(0, 'toUpperCase');
/**
* Returns a new list containing only one copy of each element in the original
* list, based upon the value returned by applying the supplied function to
* each list element. Prefers the first item if the supplied function produces
* the same value on two items. `R.equals` is used for comparison.
*
* @func
* @memberOf R
* @since v0.16.0
* @category List
* @sig (a -> b) -> [a] -> [a]
* @param {Function} fn A function used to produce a value to use during comparisons.
* @param {Array} list The array to consider.
* @return {Array} The list of unique items.
* @example
*
* R.uniqBy(Math.abs, [-1, -5, 2, 10, 1, 2]); //=> [-1, -5, 2, 10]
*/
var uniqBy = _curry2(function uniqBy(fn, list) {
var set = new _Set();
var result = [];
var idx = 0;
var appliedItem, item;
while (idx < list.length) {
item = list[idx];
appliedItem = fn(item);
if (set.add(appliedItem)) {
result.push(item);
}
idx += 1;
}
return result;
});
/**
* Returns a new list containing only one copy of each element in the original
* list. `R.equals` is used to determine equality.
*
* @func
* @memberOf R
* @since v0.1.0
* @category List
* @sig [a] -> [a]
* @param {Array} list The array to consider.
* @return {Array} The list of unique items.
* @example
*
* R.uniq([1, 1, 2, 1]); //=> [1, 2]
* R.uniq([1, '1']); //=> [1, '1']
* R.uniq([[42], [42]]); //=> [[42]]
*/
var uniq = uniqBy(identity);
/**
* Combines two lists into a set (i.e. no duplicates) composed of those
* elements common to both lists.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig [*] -> [*] -> [*]
* @param {Array} list1 The first list.
* @param {Array} list2 The second list.
* @return {Array} The list of elements found in both `list1` and `list2`.
* @see R.intersectionWith
* @example
*
* R.intersection([1,2,3,4], [7,6,5,4,3]); //=> [4, 3]
*/
var intersection = _curry2(function intersection(list1, list2) {
var lookupList, filteredList;
if (list1.length > list2.length) {
lookupList = list1;
filteredList = list2;
} else {
lookupList = list2;
filteredList = list1;
}
return uniq(_filter(flip(_contains)(lookupList), filteredList));
});
/**
* Combines two lists into a set (i.e. no duplicates) composed of the elements
* of each list.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Relation
* @sig [*] -> [*] -> [*]
* @param {Array} as The first list.
* @param {Array} bs The second list.
* @return {Array} The first and second lists concatenated, with
* duplicates removed.
* @example
*
* R.union([1, 2, 3], [2, 3, 4]); //=> [1, 2, 3, 4]
*/
var union = _curry2(compose(uniq, _concat));
var R = {
F: F,
T: T,
__: __,
add: add,
addIndex: addIndex,
adjust: adjust,
all: all,
allPass: allPass,
always: always,
and: and,
any: any,
anyPass: anyPass,
ap: ap,
aperture: aperture,
append: append,
apply: apply,
applySpec: applySpec,
assoc: assoc,
assocPath: assocPath,
binary: binary,
bind: bind,
both: both,
call: call,
chain: chain,
clamp: clamp,
clone: clone,
comparator: comparator,
complement: complement,
compose: compose,
composeK: composeK,
composeP: composeP,
concat: concat,
cond: cond,
construct: construct,
constructN: constructN,
contains: contains,
converge: converge,
countBy: countBy,
curry: curry,
curryN: curryN,
dec: dec,
defaultTo: defaultTo,
difference: difference,
differenceWith: differenceWith,
dissoc: dissoc,
dissocPath: dissocPath,
divide: divide,
drop: drop,
dropLast: dropLast,
dropLastWhile: dropLastWhile,
dropRepeats: dropRepeats,
dropRepeatsWith: dropRepeatsWith,
dropWhile: dropWhile,
either: either,
empty: empty,
eqBy: eqBy,
eqProps: eqProps,
equals: equals,
evolve: evolve,
filter: filter,
find: find,
findIndex: findIndex,
findLast: findLast,
findLastIndex: findLastIndex,
flatten: flatten,
flip: flip,
forEach: forEach,
fromPairs: fromPairs,
groupBy: groupBy,
groupWith: groupWith,
gt: gt,
gte: gte,
has: has,
hasIn: hasIn,
head: head,
identical: identical,
identity: identity,
ifElse: ifElse,
inc: inc,
indexBy: indexBy,
indexOf: indexOf,
init: init,
insert: insert,
insertAll: insertAll,
intersection: intersection,
intersectionWith: intersectionWith,
intersperse: intersperse,
into: into,
invert: invert,
invertObj: invertObj,
invoker: invoker,
is: is,
isArrayLike: isArrayLike,
isEmpty: isEmpty,
isNil: isNil,
join: join,
juxt: juxt,
keys: keys,
keysIn: keysIn,
last: last,
lastIndexOf: lastIndexOf,
length: length,
lens: lens,
lensIndex: lensIndex,
lensPath: lensPath,
lensProp: lensProp,
lift: lift,
liftN: liftN,
lt: lt,
lte: lte,
map: map,
mapAccum: mapAccum,
mapAccumRight: mapAccumRight,
mapObjIndexed: mapObjIndexed,
match: match,
mathMod: mathMod,
max: max,
maxBy: maxBy,
mean: mean,
median: median,
memoize: memoize,
merge: merge,
mergeAll: mergeAll,
mergeWith: mergeWith,
mergeWithKey: mergeWithKey,
min: min,
minBy: minBy,
modulo: modulo,
multiply: multiply,
nAry: nAry,
negate: negate,
none: none,
not: not,
nth: nth,
nthArg: nthArg,
objOf: objOf,
of: of,
omit: omit,
once: once,
or: or,
over: over,
pair: pair,
partial: partial,
partialRight: partialRight,
partition: partition,
path: path,
pathEq: pathEq,
pathOr: pathOr,
pathSatisfies: pathSatisfies,
pick: pick,
pickAll: pickAll,
pickBy: pickBy,
pipe: pipe,
pipeK: pipeK,
pipeP: pipeP,
pluck: pluck,
prepend: prepend,
product: product,
project: project,
prop: prop,
propEq: propEq,
propIs: propIs,
propOr: propOr,
propSatisfies: propSatisfies,
props: props,
range: range,
reduce: reduce,
reduceBy: reduceBy,
reduceRight: reduceRight,
reduceWhile: reduceWhile,
reduced: reduced,
reject: reject,
remove: remove,
repeat: repeat,
replace: replace,
reverse: reverse,
scan: scan,
sequence: sequence,
set: set,
slice: slice,
sort: sort,
sortBy: sortBy,
split: split,
splitAt: splitAt,
splitEvery: splitEvery,
splitWhen: splitWhen,
subtract: subtract,
sum: sum,
symmetricDifference: symmetricDifference,
symmetricDifferenceWith: symmetricDifferenceWith,
tail: tail,
take: take,
takeLast: takeLast,
takeLastWhile: takeLastWhile,
takeWhile: takeWhile,
tap: tap,
test: test,
times: times,
toLower: toLower,
toPairs: toPairs,
toPairsIn: toPairsIn,
toString: toString,
toUpper: toUpper,
transduce: transduce,
transpose: transpose,
traverse: traverse,
trim: trim,
tryCatch: tryCatch,
type: type,
unapply: unapply,
unary: unary,
uncurryN: uncurryN,
unfold: unfold,
union: union,
unionWith: unionWith,
uniq: uniq,
uniqBy: uniqBy,
uniqWith: uniqWith,
unless: unless,
unnest: unnest,
until: until,
update: update,
useWith: useWith,
values: values,
valuesIn: valuesIn,
view: view,
when: when,
where: where,
whereEq: whereEq,
without: without,
wrap: wrap,
xprod: xprod,
zip: zip,
zipObj: zipObj,
zipWith: zipWith
};
/* eslint-env amd */
/* TEST_ENTRY_POINT */
if (typeof exports === 'object') {
module.exports = R;
} else if (typeof define === 'function' && define.amd) {
define(function() { return R; });
} else {
this.R = R;
}
}.call(this));
},{}]},{},[])
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImRpc3QvcmFtZGEuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gIFJhbWRhIHYwLjIyLjFcbi8vICBodHRwczovL2dpdGh1Yi5jb20vcmFtZGEvcmFtZGFcbi8vICAoYykgMjAxMy0yMDE2IFNjb3R0IFNhdXlldCwgTWljaGFlbCBIdXJsZXksIGFuZCBEYXZpZCBDaGFtYmVyc1xuLy8gIFJhbWRhIG1heSBiZSBmcmVlbHkgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuXG47KGZ1bmN0aW9uKCkge1xuXG4gICd1c2Ugc3RyaWN0JztcblxuICAvKipcbiAgICAgKiBBIHNwZWNpYWwgcGxhY2Vob2xkZXIgdmFsdWUgdXNlZCB0byBzcGVjaWZ5IFwiZ2Fwc1wiIHdpdGhpbiBjdXJyaWVkIGZ1bmN0aW9ucyxcbiAgICAgKiBhbGxvd2luZyBwYXJ0aWFsIGFwcGxpY2F0aW9uIG9mIGFueSBjb21iaW5hdGlvbiBvZiBhcmd1bWVudHMsIHJlZ2FyZGxlc3Mgb2ZcbiAgICAgKiB0aGVpciBwb3NpdGlvbnMuXG4gICAgICpcbiAgICAgKiBJZiBgZ2AgaXMgYSBjdXJyaWVkIHRlcm5hcnkgZnVuY3Rpb24gYW5kIGBfYCBpcyBgUi5fX2AsIHRoZSBmb2xsb3dpbmcgYXJlXG4gICAgICogZXF1aXZhbGVudDpcbiAgICAgKlxuICAgICAqICAgLSBgZygxLCAyLCAzKWBcbiAgICAgKiAgIC0gYGcoXywgMiwgMykoMSlgXG4gICAgICogICAtIGBnKF8sIF8sIDMpKDEpKDIpYFxuICAgICAqICAgLSBgZyhfLCBfLCAzKSgxLCAyKWBcbiAgICAgKiAgIC0gYGcoXywgMiwgXykoMSwgMylgXG4gICAgICogICAtIGBnKF8sIDIpKDEpKDMpYFxuICAgICAqICAgLSBgZyhfLCAyKSgxLCAzKWBcbiAgICAgKiAgIC0gYGcoXywgMikoXywgMykoMSlgXG4gICAgICpcbiAgICAgKiBAY29uc3RhbnRcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZ3JlZXQgPSBSLnJlcGxhY2UoJ3tuYW1lfScsIFIuX18sICdIZWxsbywge25hbWV9IScpO1xuICAgICAqICAgICAgZ3JlZXQoJ0FsaWNlJyk7IC8vPT4gJ0hlbGxvLCBBbGljZSEnXG4gICAgICovXG4gICAgdmFyIF9fID0geyAnQEBmdW5jdGlvbmFsL3BsYWNlaG9sZGVyJzogdHJ1ZSB9O1xuXG4gICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICB2YXIgX2FyaXR5ID0gZnVuY3Rpb24gX2FyaXR5KG4sIGZuKSB7XG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4gICAgICAgIHN3aXRjaCAobikge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhMCwgYTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTAsIGExLCBhMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhMCwgYTEsIGEyLCBhMykge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhMCwgYTEsIGEyLCBhMywgYTQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhMCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhMCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNiwgYTcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYsIGE3LCBhOCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYsIGE3LCBhOCwgYTkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IHRvIF9hcml0eSBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgbm8gZ3JlYXRlciB0aGFuIHRlbicpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciBfYXJyYXlGcm9tSXRlcmF0b3IgPSBmdW5jdGlvbiBfYXJyYXlGcm9tSXRlcmF0b3IoaXRlcikge1xuICAgICAgICB2YXIgbGlzdCA9IFtdO1xuICAgICAgICB2YXIgbmV4dDtcbiAgICAgICAgd2hpbGUgKCEobmV4dCA9IGl0ZXIubmV4dCgpKS5kb25lKSB7XG4gICAgICAgICAgICBsaXN0LnB1c2gobmV4dC52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfTtcblxuICAgIHZhciBfYXJyYXlPZiA9IGZ1bmN0aW9uIF9hcnJheU9mKCkge1xuICAgICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICB9O1xuXG4gICAgdmFyIF9jbG9uZVJlZ0V4cCA9IGZ1bmN0aW9uIF9jbG9uZVJlZ0V4cChwYXR0ZXJuKSB7XG4gICAgICAgIHJldHVybiBuZXcgUmVnRXhwKHBhdHRlcm4uc291cmNlLCAocGF0dGVybi5nbG9iYWwgPyAnZycgOiAnJykgKyAocGF0dGVybi5pZ25vcmVDYXNlID8gJ2knIDogJycpICsgKHBhdHRlcm4ubXVsdGlsaW5lID8gJ20nIDogJycpICsgKHBhdHRlcm4uc3RpY2t5ID8gJ3knIDogJycpICsgKHBhdHRlcm4udW5pY29kZSA/ICd1JyA6ICcnKSk7XG4gICAgfTtcblxuICAgIHZhciBfY29tcGxlbWVudCA9IGZ1bmN0aW9uIF9jb21wbGVtZW50KGYpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAhZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQcml2YXRlIGBjb25jYXRgIGZ1bmN0aW9uIHRvIG1lcmdlIHR3byBhcnJheS1saWtlIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8QXJndW1lbnRzfSBbc2V0MT1bXV0gQW4gYXJyYXktbGlrZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtBcnJheXxBcmd1bWVudHN9IFtzZXQyPVtdXSBBbiBhcnJheS1saWtlIG9iamVjdC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcsIG1lcmdlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBfY29uY2F0KFs0LCA1LCA2XSwgWzEsIDIsIDNdKTsgLy89PiBbNCwgNSwgNiwgMSwgMiwgM11cbiAgICAgKi9cbiAgICB2YXIgX2NvbmNhdCA9IGZ1bmN0aW9uIF9jb25jYXQoc2V0MSwgc2V0Mikge1xuICAgICAgICBzZXQxID0gc2V0MSB8fCBbXTtcbiAgICAgICAgc2V0MiA9IHNldDIgfHwgW107XG4gICAgICAgIHZhciBpZHg7XG4gICAgICAgIHZhciBsZW4xID0gc2V0MS5sZW5ndGg7XG4gICAgICAgIHZhciBsZW4yID0gc2V0Mi5sZW5ndGg7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgaWR4ID0gMDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbjEpIHtcbiAgICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoXSA9IHNldDFbaWR4XTtcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIGlkeCA9IDA7XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4yKSB7XG4gICAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aF0gPSBzZXQyW2lkeF07XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICB2YXIgX2NvbnRhaW5zV2l0aCA9IGZ1bmN0aW9uIF9jb250YWluc1dpdGgocHJlZCwgeCwgbGlzdCkge1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAocHJlZCh4LCBsaXN0W2lkeF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIHZhciBfZmlsdGVyID0gZnVuY3Rpb24gX2ZpbHRlcihmbiwgbGlzdCkge1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChmbihsaXN0W2lkeF0pKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gbGlzdFtpZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuXG4gICAgdmFyIF9mb3JjZVJlZHVjZWQgPSBmdW5jdGlvbiBfZm9yY2VSZWR1Y2VkKHgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvdmFsdWUnOiB4LFxuICAgICAgICAgICAgJ0BAdHJhbnNkdWNlci9yZWR1Y2VkJzogdHJ1ZVxuICAgICAgICB9O1xuICAgIH07XG5cbiAgICAvLyBTdHJpbmcoeCA9PiB4KSBldmFsdWF0ZXMgdG8gXCJ4ID0+IHhcIiwgc28gdGhlIHBhdHRlcm4gbWF5IG5vdCBtYXRjaC5cbiAgICB2YXIgX2Z1bmN0aW9uTmFtZSA9IGZ1bmN0aW9uIF9mdW5jdGlvbk5hbWUoZikge1xuICAgICAgICAvLyBTdHJpbmcoeCA9PiB4KSBldmFsdWF0ZXMgdG8gXCJ4ID0+IHhcIiwgc28gdGhlIHBhdHRlcm4gbWF5IG5vdCBtYXRjaC5cbiAgICAgICAgdmFyIG1hdGNoID0gU3RyaW5nKGYpLm1hdGNoKC9eZnVuY3Rpb24gKFxcdyopLyk7XG4gICAgICAgIHJldHVybiBtYXRjaCA9PSBudWxsID8gJycgOiBtYXRjaFsxXTtcbiAgICB9O1xuXG4gICAgdmFyIF9oYXMgPSBmdW5jdGlvbiBfaGFzKHByb3AsIG9iaikge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG4gICAgfTtcblxuICAgIHZhciBfaWRlbnRpdHkgPSBmdW5jdGlvbiBfaWRlbnRpdHkoeCkge1xuICAgICAgICByZXR1cm4geDtcbiAgICB9O1xuXG4gICAgdmFyIF9pc0FyZ3VtZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcbiAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoYXJndW1lbnRzKSA9PT0gJ1tvYmplY3QgQXJndW1lbnRzXScgPyBmdW5jdGlvbiBfaXNBcmd1bWVudHMoeCkge1xuICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoeCkgPT09ICdbb2JqZWN0IEFyZ3VtZW50c10nO1xuICAgICAgICB9IDogZnVuY3Rpb24gX2lzQXJndW1lbnRzKHgpIHtcbiAgICAgICAgICAgIHJldHVybiBfaGFzKCdjYWxsZWUnLCB4KTtcbiAgICAgICAgfTtcbiAgICB9KCk7XG5cbiAgICAvKipcbiAgICAgKiBUZXN0cyB3aGV0aGVyIG9yIG5vdCBhbiBvYmplY3QgaXMgYW4gYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsIFRoZSBvYmplY3QgdG8gdGVzdC5cbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgYHZhbGAgaXMgYW4gYXJyYXksIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIF9pc0FycmF5KFtdKTsgLy89PiB0cnVlXG4gICAgICogICAgICBfaXNBcnJheShudWxsKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgX2lzQXJyYXkoe30pOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIF9pc0FycmF5ID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBfaXNBcnJheSh2YWwpIHtcbiAgICAgICAgcmV0dXJuIHZhbCAhPSBudWxsICYmIHZhbC5sZW5ndGggPj0gMCAmJiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICB9O1xuXG4gICAgdmFyIF9pc0Z1bmN0aW9uID0gZnVuY3Rpb24gX2lzRnVuY3Rpb24oeCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHgpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmUgaWYgdGhlIHBhc3NlZCBhcmd1bWVudCBpcyBhbiBpbnRlZ2VyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAY2F0ZWdvcnkgVHlwZVxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICovXG4gICAgdmFyIF9pc0ludGVnZXIgPSBOdW1iZXIuaXNJbnRlZ2VyIHx8IGZ1bmN0aW9uIF9pc0ludGVnZXIobikge1xuICAgICAgICByZXR1cm4gbiA8PCAwID09PSBuO1xuICAgIH07XG5cbiAgICB2YXIgX2lzTnVtYmVyID0gZnVuY3Rpb24gX2lzTnVtYmVyKHgpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSA9PT0gJ1tvYmplY3QgTnVtYmVyXSc7XG4gICAgfTtcblxuICAgIHZhciBfaXNPYmplY3QgPSBmdW5jdGlvbiBfaXNPYmplY3QoeCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHgpID09PSAnW29iamVjdCBPYmplY3RdJztcbiAgICB9O1xuXG4gICAgdmFyIF9pc1BsYWNlaG9sZGVyID0gZnVuY3Rpb24gX2lzUGxhY2Vob2xkZXIoYSkge1xuICAgICAgICByZXR1cm4gYSAhPSBudWxsICYmIHR5cGVvZiBhID09PSAnb2JqZWN0JyAmJiBhWydAQGZ1bmN0aW9uYWwvcGxhY2Vob2xkZXInXSA9PT0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgdmFyIF9pc1JlZ0V4cCA9IGZ1bmN0aW9uIF9pc1JlZ0V4cCh4KSB7XG4gICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoeCkgPT09ICdbb2JqZWN0IFJlZ0V4cF0nO1xuICAgIH07XG5cbiAgICB2YXIgX2lzU3RyaW5nID0gZnVuY3Rpb24gX2lzU3RyaW5nKHgpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSA9PT0gJ1tvYmplY3QgU3RyaW5nXSc7XG4gICAgfTtcblxuICAgIHZhciBfaXNUcmFuc2Zvcm1lciA9IGZ1bmN0aW9uIF9pc1RyYW5zZm9ybWVyKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9ialsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9PT0gJ2Z1bmN0aW9uJztcbiAgICB9O1xuXG4gICAgdmFyIF9tYXAgPSBmdW5jdGlvbiBfbWFwKGZuLCBmdW5jdG9yKSB7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgbGVuID0gZnVuY3Rvci5sZW5ndGg7XG4gICAgICAgIHZhciByZXN1bHQgPSBBcnJheShsZW4pO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICByZXN1bHRbaWR4XSA9IGZuKGZ1bmN0b3JbaWR4XSk7XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICAvLyBCYXNlZCBvbiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9PYmplY3QvYXNzaWduXG4gICAgdmFyIF9vYmplY3RBc3NpZ24gPSBmdW5jdGlvbiBfb2JqZWN0QXNzaWduKHRhcmdldCkge1xuICAgICAgICBpZiAodGFyZ2V0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHVuZGVmaW5lZCBvciBudWxsIHRvIG9iamVjdCcpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvdXRwdXQgPSBPYmplY3QodGFyZ2V0KTtcbiAgICAgICAgdmFyIGlkeCA9IDE7XG4gICAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2lkeF07XG4gICAgICAgICAgICBpZiAoc291cmNlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBuZXh0S2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoX2hhcyhuZXh0S2V5LCBzb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRbbmV4dEtleV0gPSBzb3VyY2VbbmV4dEtleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH07XG5cbiAgICB2YXIgX29mID0gZnVuY3Rpb24gX29mKHgpIHtcbiAgICAgICAgcmV0dXJuIFt4XTtcbiAgICB9O1xuXG4gICAgdmFyIF9waXBlID0gZnVuY3Rpb24gX3BpcGUoZiwgZykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIGcuY2FsbCh0aGlzLCBmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICAgICAgICB9O1xuICAgIH07XG5cbiAgICB2YXIgX3BpcGVQID0gZnVuY3Rpb24gX3BpcGVQKGYsIGcpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjdHggPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIGYuYXBwbHkoY3R4LCBhcmd1bWVudHMpLnRoZW4oZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZy5jYWxsKGN0eCwgeCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9O1xuXG4gICAgLy8gXFxiIG1hdGNoZXMgd29yZCBib3VuZGFyeTsgW1xcYl0gbWF0Y2hlcyBiYWNrc3BhY2VcbiAgICB2YXIgX3F1b3RlID0gZnVuY3Rpb24gX3F1b3RlKHMpIHtcbiAgICAgICAgdmFyIGVzY2FwZWQgPSBzLnJlcGxhY2UoL1xcXFwvZywgJ1xcXFxcXFxcJykucmVwbGFjZSgvW1xcYl0vZywgJ1xcXFxiJykgICAgLy8gXFxiIG1hdGNoZXMgd29yZCBib3VuZGFyeTsgW1xcYl0gbWF0Y2hlcyBiYWNrc3BhY2VcbiAgICAucmVwbGFjZSgvXFxmL2csICdcXFxcZicpLnJlcGxhY2UoL1xcbi9nLCAnXFxcXG4nKS5yZXBsYWNlKC9cXHIvZywgJ1xcXFxyJykucmVwbGFjZSgvXFx0L2csICdcXFxcdCcpLnJlcGxhY2UoL1xcdi9nLCAnXFxcXHYnKS5yZXBsYWNlKC9cXDAvZywgJ1xcXFwwJyk7XG4gICAgICAgIHJldHVybiAnXCInICsgZXNjYXBlZC5yZXBsYWNlKC9cIi9nLCAnXFxcXFwiJykgKyAnXCInO1xuICAgIH07XG5cbiAgICB2YXIgX3JlZHVjZWQgPSBmdW5jdGlvbiBfcmVkdWNlZCh4KSB7XG4gICAgICAgIHJldHVybiB4ICYmIHhbJ0BAdHJhbnNkdWNlci9yZWR1Y2VkJ10gPyB4IDoge1xuICAgICAgICAgICAgJ0BAdHJhbnNkdWNlci92YWx1ZSc6IHgsXG4gICAgICAgICAgICAnQEB0cmFuc2R1Y2VyL3JlZHVjZWQnOiB0cnVlXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFuIG9wdGltaXplZCwgcHJpdmF0ZSBhcnJheSBgc2xpY2VgIGltcGxlbWVudGF0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FyZ3VtZW50c3xBcnJheX0gYXJncyBUaGUgYXJyYXkgb3IgYXJndW1lbnRzIG9iamVjdCB0byBjb25zaWRlci5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW2Zyb209MF0gVGhlIGFycmF5IGluZGV4IHRvIHNsaWNlIGZyb20sIGluY2x1c2l2ZS5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gW3RvPWFyZ3MubGVuZ3RoXSBUaGUgYXJyYXkgaW5kZXggdG8gc2xpY2UgdG8sIGV4Y2x1c2l2ZS5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcsIHNsaWNlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBfc2xpY2UoWzEsIDIsIDMsIDQsIDVdLCAxLCAzKTsgLy89PiBbMiwgM11cbiAgICAgKlxuICAgICAqICAgICAgdmFyIGZpcnN0VGhyZWVBcmdzID0gZnVuY3Rpb24oYSwgYiwgYywgZCkge1xuICAgICAqICAgICAgICByZXR1cm4gX3NsaWNlKGFyZ3VtZW50cywgMCwgMyk7XG4gICAgICogICAgICB9O1xuICAgICAqICAgICAgZmlyc3RUaHJlZUFyZ3MoMSwgMiwgMywgNCk7IC8vPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgdmFyIF9zbGljZSA9IGZ1bmN0aW9uIF9zbGljZShhcmdzLCBmcm9tLCB0bykge1xuICAgICAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuIF9zbGljZShhcmdzLCAwLCBhcmdzLmxlbmd0aCk7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHJldHVybiBfc2xpY2UoYXJncywgZnJvbSwgYXJncy5sZW5ndGgpO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdmFyIGxpc3QgPSBbXTtcbiAgICAgICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICAgICAgdmFyIGxlbiA9IE1hdGgubWF4KDAsIE1hdGgubWluKGFyZ3MubGVuZ3RoLCB0bykgLSBmcm9tKTtcbiAgICAgICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgICAgICBsaXN0W2lkeF0gPSBhcmdzW2Zyb20gKyBpZHhdO1xuICAgICAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUG9seWZpbGwgZnJvbSA8aHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRGF0ZS90b0lTT1N0cmluZz4uXG4gICAgICovXG4gICAgdmFyIF90b0lTT1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHBhZCA9IGZ1bmN0aW9uIHBhZChuKSB7XG4gICAgICAgICAgICByZXR1cm4gKG4gPCAxMCA/ICcwJyA6ICcnKSArIG47XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0eXBlb2YgRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmcgPT09ICdmdW5jdGlvbicgPyBmdW5jdGlvbiBfdG9JU09TdHJpbmcoZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQudG9JU09TdHJpbmcoKTtcbiAgICAgICAgfSA6IGZ1bmN0aW9uIF90b0lTT1N0cmluZyhkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5nZXRVVENGdWxsWWVhcigpICsgJy0nICsgcGFkKGQuZ2V0VVRDTW9udGgoKSArIDEpICsgJy0nICsgcGFkKGQuZ2V0VVRDRGF0ZSgpKSArICdUJyArIHBhZChkLmdldFVUQ0hvdXJzKCkpICsgJzonICsgcGFkKGQuZ2V0VVRDTWludXRlcygpKSArICc6JyArIHBhZChkLmdldFVUQ1NlY29uZHMoKSkgKyAnLicgKyAoZC5nZXRVVENNaWxsaXNlY29uZHMoKSAvIDEwMDApLnRvRml4ZWQoMykuc2xpY2UoMiwgNSkgKyAnWic7XG4gICAgICAgIH07XG4gICAgfSgpO1xuXG4gICAgdmFyIF94ZkJhc2UgPSB7XG4gICAgICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvaW5pdCddKCk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlc3VsdDogZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciBfeHdyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhXcmFwKGZuKSB7XG4gICAgICAgICAgICB0aGlzLmYgPSBmbjtcbiAgICAgICAgfVxuICAgICAgICBYV3JhcC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luaXQgbm90IGltcGxlbWVudGVkIG9uIFhXcmFwJyk7XG4gICAgICAgIH07XG4gICAgICAgIFhXcmFwLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddID0gZnVuY3Rpb24gKGFjYykge1xuICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgfTtcbiAgICAgICAgWFdyYXAucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKGFjYywgeCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZihhY2MsIHgpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gX3h3cmFwKGZuKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhXcmFwKGZuKTtcbiAgICAgICAgfTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX2FwZXJ0dXJlID0gZnVuY3Rpb24gX2FwZXJ0dXJlKG4sIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHZhciBsaW1pdCA9IGxpc3QubGVuZ3RoIC0gKG4gLSAxKTtcbiAgICAgICAgdmFyIGFjYyA9IG5ldyBBcnJheShsaW1pdCA+PSAwID8gbGltaXQgOiAwKTtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxpbWl0KSB7XG4gICAgICAgICAgICBhY2NbaWR4XSA9IF9zbGljZShsaXN0LCBpZHgsIGlkeCArIG4pO1xuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICB9O1xuXG4gICAgdmFyIF9hc3NpZ24gPSB0eXBlb2YgT2JqZWN0LmFzc2lnbiA9PT0gJ2Z1bmN0aW9uJyA/IE9iamVjdC5hc3NpZ24gOiBfb2JqZWN0QXNzaWduO1xuXG4gICAgLyoqXG4gICAgICogU2ltaWxhciB0byBoYXNNZXRob2QsIHRoaXMgY2hlY2tzIHdoZXRoZXIgYSBmdW5jdGlvbiBoYXMgYSBbbWV0aG9kbmFtZV1cbiAgICAgKiBmdW5jdGlvbi4gSWYgaXQgaXNuJ3QgYW4gYXJyYXkgaXQgd2lsbCBleGVjdXRlIHRoYXQgZnVuY3Rpb24gb3RoZXJ3aXNlIGl0XG4gICAgICogd2lsbCBkZWZhdWx0IHRvIHRoZSByYW1kYSBpbXBsZW1lbnRhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gcmFtZGEgaW1wbGVtdGF0aW9uXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZG5hbWUgcHJvcGVydHkgdG8gY2hlY2sgZm9yIGEgY3VzdG9tIGltcGxlbWVudGF0aW9uXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBXaGF0ZXZlciB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBtZXRob2QgaXMuXG4gICAgICovXG4gICAgdmFyIF9jaGVja0Zvck1ldGhvZCA9IGZ1bmN0aW9uIF9jaGVja0Zvck1ldGhvZChtZXRob2RuYW1lLCBmbikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAobGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgb2JqID0gYXJndW1lbnRzW2xlbmd0aCAtIDFdO1xuICAgICAgICAgICAgcmV0dXJuIF9pc0FycmF5KG9iaikgfHwgdHlwZW9mIG9ialttZXRob2RuYW1lXSAhPT0gJ2Z1bmN0aW9uJyA/IGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBvYmpbbWV0aG9kbmFtZV0uYXBwbHkob2JqLCBfc2xpY2UoYXJndW1lbnRzLCAwLCBsZW5ndGggLSAxKSk7XG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIE9wdGltaXplZCBpbnRlcm5hbCBvbmUtYXJpdHkgY3VycnkgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgdmFyIF9jdXJyeTEgPSBmdW5jdGlvbiBfY3VycnkxKGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBmMShhKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCB8fCBfaXNQbGFjZWhvbGRlcihhKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIE9wdGltaXplZCBpbnRlcm5hbCB0d28tYXJpdHkgY3VycnkgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgdmFyIF9jdXJyeTIgPSBmdW5jdGlvbiBfY3VycnkyKGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBmMihhLCBiKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICByZXR1cm4gZjI7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9pc1BsYWNlaG9sZGVyKGEpID8gZjIgOiBfY3VycnkxKGZ1bmN0aW9uIChfYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm4oYSwgX2IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gX2lzUGxhY2Vob2xkZXIoYSkgJiYgX2lzUGxhY2Vob2xkZXIoYikgPyBmMiA6IF9pc1BsYWNlaG9sZGVyKGEpID8gX2N1cnJ5MShmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuKF9hLCBiKTtcbiAgICAgICAgICAgICAgICB9KSA6IF9pc1BsYWNlaG9sZGVyKGIpID8gX2N1cnJ5MShmdW5jdGlvbiAoX2IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuKGEsIF9iKTtcbiAgICAgICAgICAgICAgICB9KSA6IGZuKGEsIGIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBPcHRpbWl6ZWQgaW50ZXJuYWwgdGhyZWUtYXJpdHkgY3VycnkgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGN1cnJpZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgdmFyIF9jdXJyeTMgPSBmdW5jdGlvbiBfY3VycnkzKGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBmMyhhLCBiLCBjKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICByZXR1cm4gZjM7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9pc1BsYWNlaG9sZGVyKGEpID8gZjMgOiBfY3VycnkyKGZ1bmN0aW9uIChfYiwgX2MpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuKGEsIF9iLCBfYyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9pc1BsYWNlaG9sZGVyKGEpICYmIF9pc1BsYWNlaG9sZGVyKGIpID8gZjMgOiBfaXNQbGFjZWhvbGRlcihhKSA/IF9jdXJyeTIoZnVuY3Rpb24gKF9hLCBfYykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm4oX2EsIGIsIF9jKTtcbiAgICAgICAgICAgICAgICB9KSA6IF9pc1BsYWNlaG9sZGVyKGIpID8gX2N1cnJ5MihmdW5jdGlvbiAoX2IsIF9jKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbihhLCBfYiwgX2MpO1xuICAgICAgICAgICAgICAgIH0pIDogX2N1cnJ5MShmdW5jdGlvbiAoX2MpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuKGEsIGIsIF9jKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9pc1BsYWNlaG9sZGVyKGEpICYmIF9pc1BsYWNlaG9sZGVyKGIpICYmIF9pc1BsYWNlaG9sZGVyKGMpID8gZjMgOiBfaXNQbGFjZWhvbGRlcihhKSAmJiBfaXNQbGFjZWhvbGRlcihiKSA/IF9jdXJyeTIoZnVuY3Rpb24gKF9hLCBfYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm4oX2EsIF9iLCBjKTtcbiAgICAgICAgICAgICAgICB9KSA6IF9pc1BsYWNlaG9sZGVyKGEpICYmIF9pc1BsYWNlaG9sZGVyKGMpID8gX2N1cnJ5MihmdW5jdGlvbiAoX2EsIF9jKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbihfYSwgYiwgX2MpO1xuICAgICAgICAgICAgICAgIH0pIDogX2lzUGxhY2Vob2xkZXIoYikgJiYgX2lzUGxhY2Vob2xkZXIoYykgPyBfY3VycnkyKGZ1bmN0aW9uIChfYiwgX2MpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuKGEsIF9iLCBfYyk7XG4gICAgICAgICAgICAgICAgfSkgOiBfaXNQbGFjZWhvbGRlcihhKSA/IF9jdXJyeTEoZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbihfYSwgYiwgYyk7XG4gICAgICAgICAgICAgICAgfSkgOiBfaXNQbGFjZWhvbGRlcihiKSA/IF9jdXJyeTEoZnVuY3Rpb24gKF9iKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbihhLCBfYiwgYyk7XG4gICAgICAgICAgICAgICAgfSkgOiBfaXNQbGFjZWhvbGRlcihjKSA/IF9jdXJyeTEoZnVuY3Rpb24gKF9jKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbihhLCBiLCBfYyk7XG4gICAgICAgICAgICAgICAgfSkgOiBmbihhLCBiLCBjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWwgY3VycnlOIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoIFRoZSBhcml0eSBvZiB0aGUgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSByZWNlaXZlZCBBbiBhcnJheSBvZiBhcmd1bWVudHMgcmVjZWl2ZWQgdGh1cyBmYXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGN1cnJ5LlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICB2YXIgX2N1cnJ5TiA9IGZ1bmN0aW9uIF9jdXJyeU4obGVuZ3RoLCByZWNlaXZlZCwgZm4pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjb21iaW5lZCA9IFtdO1xuICAgICAgICAgICAgdmFyIGFyZ3NJZHggPSAwO1xuICAgICAgICAgICAgdmFyIGxlZnQgPSBsZW5ndGg7XG4gICAgICAgICAgICB2YXIgY29tYmluZWRJZHggPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGNvbWJpbmVkSWR4IDwgcmVjZWl2ZWQubGVuZ3RoIHx8IGFyZ3NJZHggPCBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAoY29tYmluZWRJZHggPCByZWNlaXZlZC5sZW5ndGggJiYgKCFfaXNQbGFjZWhvbGRlcihyZWNlaXZlZFtjb21iaW5lZElkeF0pIHx8IGFyZ3NJZHggPj0gYXJndW1lbnRzLmxlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVjZWl2ZWRbY29tYmluZWRJZHhdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGFyZ3VtZW50c1thcmdzSWR4XTtcbiAgICAgICAgICAgICAgICAgICAgYXJnc0lkeCArPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb21iaW5lZFtjb21iaW5lZElkeF0gPSByZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKCFfaXNQbGFjZWhvbGRlcihyZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgLT0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29tYmluZWRJZHggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBsZWZ0IDw9IDAgPyBmbi5hcHBseSh0aGlzLCBjb21iaW5lZCkgOiBfYXJpdHkobGVmdCwgX2N1cnJ5TihsZW5ndGgsIGNvbWJpbmVkLCBmbikpO1xuICAgICAgICB9O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBkaXNwYXRjaGVzIHdpdGggZGlmZmVyZW50IHN0cmF0ZWdpZXMgYmFzZWQgb24gdGhlXG4gICAgICogb2JqZWN0IGluIGxpc3QgcG9zaXRpb24gKGxhc3QgYXJndW1lbnQpLiBJZiBpdCBpcyBhbiBhcnJheSwgZXhlY3V0ZXMgW2ZuXS5cbiAgICAgKiBPdGhlcndpc2UsIGlmIGl0IGhhcyBhIGZ1bmN0aW9uIHdpdGggW21ldGhvZG5hbWVdLCBpdCB3aWxsIGV4ZWN1dGUgdGhhdFxuICAgICAqIGZ1bmN0aW9uIChmdW5jdG9yIGNhc2UpLiBPdGhlcndpc2UsIGlmIGl0IGlzIGEgdHJhbnNmb3JtZXIsIHVzZXMgdHJhbnNkdWNlclxuICAgICAqIFt4Zl0gdG8gcmV0dXJuIGEgbmV3IHRyYW5zZm9ybWVyICh0cmFuc2R1Y2VyIGNhc2UpLiBPdGhlcndpc2UsIGl0IHdpbGxcbiAgICAgKiBkZWZhdWx0IHRvIGV4ZWN1dGluZyBbZm5dLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kbmFtZSBwcm9wZXJ0eSB0byBjaGVjayBmb3IgYSBjdXN0b20gaW1wbGVtZW50YXRpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB4ZiB0cmFuc2R1Y2VyIHRvIGluaXRpYWxpemUgaWYgb2JqZWN0IGlzIHRyYW5zZm9ybWVyXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gZGVmYXVsdCByYW1kYSBpbXBsZW1lbnRhdGlvblxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRoYXQgZGlzcGF0Y2hlcyBvbiBvYmplY3QgaW4gbGlzdCBwb3NpdGlvblxuICAgICAqL1xuICAgIHZhciBfZGlzcGF0Y2hhYmxlID0gZnVuY3Rpb24gX2Rpc3BhdGNoYWJsZShtZXRob2RuYW1lLCB4ZiwgZm4pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKGxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG9iaiA9IGFyZ3VtZW50c1tsZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGlmICghX2lzQXJyYXkob2JqKSkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gX3NsaWNlKGFyZ3VtZW50cywgMCwgbGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmpbbWV0aG9kbmFtZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9ialttZXRob2RuYW1lXS5hcHBseShvYmosIGFyZ3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX2lzVHJhbnNmb3JtZXIob2JqKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJhbnNkdWNlciA9IHhmLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNkdWNlcihvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH07XG5cbiAgICB2YXIgX2Ryb3BMYXN0V2hpbGUgPSBmdW5jdGlvbiBkcm9wTGFzdFdoaWxlKHByZWQsIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IGxpc3QubGVuZ3RoIC0gMTtcbiAgICAgICAgd2hpbGUgKGlkeCA+PSAwICYmIHByZWQobGlzdFtpZHhdKSkge1xuICAgICAgICAgICAgaWR4IC09IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9zbGljZShsaXN0LCAwLCBpZHggKyAxKTtcbiAgICB9O1xuXG4gICAgdmFyIF94YWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBYQWxsKGYsIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLmYgPSBmO1xuICAgICAgICAgICAgdGhpcy5hbGwgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIFhBbGwucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvaW5pdCddID0gX3hmQmFzZS5pbml0O1xuICAgICAgICBYQWxsLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddID0gZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuYWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXShyZXN1bHQsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgICBYQWxsLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZihpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFsbCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IF9yZWR1Y2VkKHRoaXMueGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10ocmVzdWx0LCBmYWxzZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9jdXJyeTIoZnVuY3Rpb24gX3hhbGwoZiwgeGYpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgWEFsbChmLCB4Zik7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIHZhciBfeGFueSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWEFueShmLCB4Zikge1xuICAgICAgICAgICAgdGhpcy54ZiA9IHhmO1xuICAgICAgICAgICAgdGhpcy5mID0gZjtcbiAgICAgICAgICAgIHRoaXMuYW55ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgWEFueS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhBbnkucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvcmVzdWx0J10gPSBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuYW55KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXShyZXN1bHQsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvcmVzdWx0J10ocmVzdWx0KTtcbiAgICAgICAgfTtcbiAgICAgICAgWEFueS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9zdGVwJ10gPSBmdW5jdGlvbiAocmVzdWx0LCBpbnB1dCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZihpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFueSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gX3JlZHVjZWQodGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXShyZXN1bHQsIHRydWUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfY3VycnkyKGZ1bmN0aW9uIF94YW55KGYsIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhBbnkoZiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX3hhcGVydHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWEFwZXJ0dXJlKG4sIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgICAgICB0aGlzLmZ1bGwgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYWNjID0gbmV3IEFycmF5KG4pO1xuICAgICAgICB9XG4gICAgICAgIFhBcGVydHVyZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhBcGVydHVyZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXSA9IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHRoaXMuYWNjID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvcmVzdWx0J10ocmVzdWx0KTtcbiAgICAgICAgfTtcbiAgICAgICAgWEFwZXJ0dXJlLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLnN0b3JlKGlucHV0KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZ1bGwgPyB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgdGhpcy5nZXRDb3B5KCkpIDogcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgICBYQXBlcnR1cmUucHJvdG90eXBlLnN0b3JlID0gZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLmFjY1t0aGlzLnBvc10gPSBpbnB1dDtcbiAgICAgICAgICAgIHRoaXMucG9zICs9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5wb3MgPT09IHRoaXMuYWNjLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9zID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLmZ1bGwgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBYQXBlcnR1cmUucHJvdG90eXBlLmdldENvcHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX2NvbmNhdChfc2xpY2UodGhpcy5hY2MsIHRoaXMucG9zKSwgX3NsaWNlKHRoaXMuYWNjLCAwLCB0aGlzLnBvcykpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiBfeGFwZXJ0dXJlKG4sIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhBcGVydHVyZShuLCB4Zik7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIHZhciBfeGRyb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhEcm9wKG4sIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLm4gPSBuO1xuICAgICAgICB9XG4gICAgICAgIFhEcm9wLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL2luaXQnXSA9IF94ZkJhc2UuaW5pdDtcbiAgICAgICAgWERyb3AucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvcmVzdWx0J10gPSBfeGZCYXNlLnJlc3VsdDtcbiAgICAgICAgWERyb3AucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLm4gPiAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uIC09IDE7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiBfeGRyb3AobiwgeGYpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgWERyb3AobiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX3hkcm9wTGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWERyb3BMYXN0KG4sIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgICAgICAgICB0aGlzLmZ1bGwgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYWNjID0gbmV3IEFycmF5KG4pO1xuICAgICAgICB9XG4gICAgICAgIFhEcm9wTGFzdC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhEcm9wTGFzdC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXSA9IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHRoaXMuYWNjID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvcmVzdWx0J10ocmVzdWx0KTtcbiAgICAgICAgfTtcbiAgICAgICAgWERyb3BMYXN0LnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5mdWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXShyZXN1bHQsIHRoaXMuYWNjW3RoaXMucG9zXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0b3JlKGlucHV0KTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgICAgIFhEcm9wTGFzdC5wcm90b3R5cGUuc3RvcmUgPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHRoaXMuYWNjW3RoaXMucG9zXSA9IGlucHV0O1xuICAgICAgICAgICAgdGhpcy5wb3MgKz0gMTtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA9PT0gdGhpcy5hY2MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICAgICAgICAgIHRoaXMuZnVsbCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfY3VycnkyKGZ1bmN0aW9uIF94ZHJvcExhc3QobiwgeGYpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgWERyb3BMYXN0KG4sIHhmKTtcbiAgICAgICAgfSk7XG4gICAgfSgpO1xuXG4gICAgdmFyIF94ZHJvcFJlcGVhdHNXaXRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBYRHJvcFJlcGVhdHNXaXRoKHByZWQsIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLnByZWQgPSBwcmVkO1xuICAgICAgICAgICAgdGhpcy5sYXN0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnNlZW5GaXJzdFZhbHVlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgWERyb3BSZXBlYXRzV2l0aC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy54ZlsnQEB0cmFuc2R1Y2VyL2luaXQnXSgpO1xuICAgICAgICB9O1xuICAgICAgICBYRHJvcFJlcGVhdHNXaXRoLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddID0gZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgICBYRHJvcFJlcGVhdHNXaXRoLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICB2YXIgc2FtZUFzTGFzdCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNlZW5GaXJzdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWVuRmlyc3RWYWx1ZSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucHJlZCh0aGlzLmxhc3RWYWx1ZSwgaW5wdXQpKSB7XG4gICAgICAgICAgICAgICAgc2FtZUFzTGFzdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmxhc3RWYWx1ZSA9IGlucHV0O1xuICAgICAgICAgICAgcmV0dXJuIHNhbWVBc0xhc3QgPyByZXN1bHQgOiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiBfeGRyb3BSZXBlYXRzV2l0aChwcmVkLCB4Zikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBYRHJvcFJlcGVhdHNXaXRoKHByZWQsIHhmKTtcbiAgICAgICAgfSk7XG4gICAgfSgpO1xuXG4gICAgdmFyIF94ZHJvcFdoaWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBYRHJvcFdoaWxlKGYsIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLmYgPSBmO1xuICAgICAgICB9XG4gICAgICAgIFhEcm9wV2hpbGUucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvaW5pdCddID0gX3hmQmFzZS5pbml0O1xuICAgICAgICBYRHJvcFdoaWxlLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddID0gX3hmQmFzZS5yZXN1bHQ7XG4gICAgICAgIFhEcm9wV2hpbGUucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmYpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5mKGlucHV0KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmYgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10ocmVzdWx0LCBpbnB1dCk7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfY3VycnkyKGZ1bmN0aW9uIF94ZHJvcFdoaWxlKGYsIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhEcm9wV2hpbGUoZiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX3hmaWx0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhGaWx0ZXIoZiwgeGYpIHtcbiAgICAgICAgICAgIHRoaXMueGYgPSB4ZjtcbiAgICAgICAgICAgIHRoaXMuZiA9IGY7XG4gICAgICAgIH1cbiAgICAgICAgWEZpbHRlci5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhGaWx0ZXIucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvcmVzdWx0J10gPSBfeGZCYXNlLnJlc3VsdDtcbiAgICAgICAgWEZpbHRlci5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9zdGVwJ10gPSBmdW5jdGlvbiAocmVzdWx0LCBpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZihpbnB1dCkgPyB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpIDogcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiBfeGZpbHRlcihmLCB4Zikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBYRmlsdGVyKGYsIHhmKTtcbiAgICAgICAgfSk7XG4gICAgfSgpO1xuXG4gICAgdmFyIF94ZmluZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWEZpbmQoZiwgeGYpIHtcbiAgICAgICAgICAgIHRoaXMueGYgPSB4ZjtcbiAgICAgICAgICAgIHRoaXMuZiA9IGY7XG4gICAgICAgICAgICB0aGlzLmZvdW5kID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgWEZpbmQucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvaW5pdCddID0gX3hmQmFzZS5pbml0O1xuICAgICAgICBYRmluZC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXSA9IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5mb3VuZCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMueGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10ocmVzdWx0LCB2b2lkIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgICBYRmluZC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9zdGVwJ10gPSBmdW5jdGlvbiAocmVzdWx0LCBpbnB1dCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZihpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBfcmVkdWNlZCh0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfY3VycnkyKGZ1bmN0aW9uIF94ZmluZChmLCB4Zikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBYRmluZChmLCB4Zik7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIHZhciBfeGZpbmRJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWEZpbmRJbmRleChmLCB4Zikge1xuICAgICAgICAgICAgdGhpcy54ZiA9IHhmO1xuICAgICAgICAgICAgdGhpcy5mID0gZjtcbiAgICAgICAgICAgIHRoaXMuaWR4ID0gLTE7XG4gICAgICAgICAgICB0aGlzLmZvdW5kID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgWEZpbmRJbmRleC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhGaW5kSW5kZXgucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvcmVzdWx0J10gPSBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZm91bmQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgLTEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgICBYRmluZEluZGV4LnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLmlkeCArPSAxO1xuICAgICAgICAgICAgaWYgKHRoaXMuZihpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBfcmVkdWNlZCh0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgdGhpcy5pZHgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfY3VycnkyKGZ1bmN0aW9uIF94ZmluZEluZGV4KGYsIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhGaW5kSW5kZXgoZiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX3hmaW5kTGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWEZpbmRMYXN0KGYsIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLmYgPSBmO1xuICAgICAgICB9XG4gICAgICAgIFhGaW5kTGFzdC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhGaW5kTGFzdC5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXSA9IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvcmVzdWx0J10odGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXShyZXN1bHQsIHRoaXMubGFzdCkpO1xuICAgICAgICB9O1xuICAgICAgICBYRmluZExhc3QucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmYoaW5wdXQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0ID0gaW5wdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiBfeGZpbmRMYXN0KGYsIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhGaW5kTGFzdChmLCB4Zik7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIHZhciBfeGZpbmRMYXN0SW5kZXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhGaW5kTGFzdEluZGV4KGYsIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLmYgPSBmO1xuICAgICAgICAgICAgdGhpcy5pZHggPSAtMTtcbiAgICAgICAgICAgIHRoaXMubGFzdElkeCA9IC0xO1xuICAgICAgICB9XG4gICAgICAgIFhGaW5kTGFzdEluZGV4LnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL2luaXQnXSA9IF94ZkJhc2UuaW5pdDtcbiAgICAgICAgWEZpbmRMYXN0SW5kZXgucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvcmVzdWx0J10gPSBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddKHRoaXMueGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10ocmVzdWx0LCB0aGlzLmxhc3RJZHgpKTtcbiAgICAgICAgfTtcbiAgICAgICAgWEZpbmRMYXN0SW5kZXgucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgIHRoaXMuaWR4ICs9IDE7XG4gICAgICAgICAgICBpZiAodGhpcy5mKGlucHV0KSkge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdElkeCA9IHRoaXMuaWR4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9jdXJyeTIoZnVuY3Rpb24gX3hmaW5kTGFzdEluZGV4KGYsIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhGaW5kTGFzdEluZGV4KGYsIHhmKTtcbiAgICAgICAgfSk7XG4gICAgfSgpO1xuXG4gICAgdmFyIF94bWFwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBYTWFwKGYsIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLmYgPSBmO1xuICAgICAgICB9XG4gICAgICAgIFhNYXAucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvaW5pdCddID0gX3hmQmFzZS5pbml0O1xuICAgICAgICBYTWFwLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddID0gX3hmQmFzZS5yZXN1bHQ7XG4gICAgICAgIFhNYXAucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgdGhpcy5mKGlucHV0KSk7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBfY3VycnkyKGZ1bmN0aW9uIF94bWFwKGYsIHhmKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFhNYXAoZiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX3hyZWR1Y2VCeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gWFJlZHVjZUJ5KHZhbHVlRm4sIHZhbHVlQWNjLCBrZXlGbiwgeGYpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWVGbiA9IHZhbHVlRm47XG4gICAgICAgICAgICB0aGlzLnZhbHVlQWNjID0gdmFsdWVBY2M7XG4gICAgICAgICAgICB0aGlzLmtleUZuID0ga2V5Rm47XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLmlucHV0cyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIFhSZWR1Y2VCeS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhSZWR1Y2VCeS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXSA9IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHZhciBrZXk7XG4gICAgICAgICAgICBmb3IgKGtleSBpbiB0aGlzLmlucHV0cykge1xuICAgICAgICAgICAgICAgIGlmIChfaGFzKGtleSwgdGhpcy5pbnB1dHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMueGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10ocmVzdWx0LCB0aGlzLmlucHV0c1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdFsnQEB0cmFuc2R1Y2VyL3JlZHVjZWQnXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0WydAQHRyYW5zZHVjZXIvdmFsdWUnXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5pbnB1dHMgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgICBYUmVkdWNlQnkucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvc3RlcCddID0gZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSB0aGlzLmtleUZuKGlucHV0KTtcbiAgICAgICAgICAgIHRoaXMuaW5wdXRzW2tleV0gPSB0aGlzLmlucHV0c1trZXldIHx8IFtcbiAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZUFjY1xuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHRoaXMuaW5wdXRzW2tleV1bMV0gPSB0aGlzLnZhbHVlRm4odGhpcy5pbnB1dHNba2V5XVsxXSwgaW5wdXQpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9jdXJyeU4oNCwgW10sIGZ1bmN0aW9uIF94cmVkdWNlQnkodmFsdWVGbiwgdmFsdWVBY2MsIGtleUZuLCB4Zikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBYUmVkdWNlQnkodmFsdWVGbiwgdmFsdWVBY2MsIGtleUZuLCB4Zik7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIHZhciBfeHRha2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhUYWtlKG4sIHhmKSB7XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgICAgICB0aGlzLm4gPSBuO1xuICAgICAgICAgICAgdGhpcy5pID0gMDtcbiAgICAgICAgfVxuICAgICAgICBYVGFrZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhUYWtlLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddID0gX3hmQmFzZS5yZXN1bHQ7XG4gICAgICAgIFhUYWtlLnByb3RvdHlwZVsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLmkgKz0gMTtcbiAgICAgICAgICAgIHZhciByZXQgPSB0aGlzLm4gPT09IDAgPyByZXN1bHQgOiB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaSA+PSB0aGlzLm4gPyBfcmVkdWNlZChyZXQpIDogcmV0O1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiBfeHRha2UobiwgeGYpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgWFRha2UobiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICB2YXIgX3h0YWtlV2hpbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhUYWtlV2hpbGUoZiwgeGYpIHtcbiAgICAgICAgICAgIHRoaXMueGYgPSB4ZjtcbiAgICAgICAgICAgIHRoaXMuZiA9IGY7XG4gICAgICAgIH1cbiAgICAgICAgWFRha2VXaGlsZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9pbml0J10gPSBfeGZCYXNlLmluaXQ7XG4gICAgICAgIFhUYWtlV2hpbGUucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvcmVzdWx0J10gPSBfeGZCYXNlLnJlc3VsdDtcbiAgICAgICAgWFRha2VXaGlsZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9zdGVwJ10gPSBmdW5jdGlvbiAocmVzdWx0LCBpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZihpbnB1dCkgPyB0aGlzLnhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpIDogX3JlZHVjZWQocmVzdWx0KTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9jdXJyeTIoZnVuY3Rpb24gX3h0YWtlV2hpbGUoZiwgeGYpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgWFRha2VXaGlsZShmLCB4Zik7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgdHdvIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIE51bWJlciAtPiBOdW1iZXIgLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGFcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYlxuICAgICAqIEByZXR1cm4ge051bWJlcn1cbiAgICAgKiBAc2VlIFIuc3VidHJhY3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmFkZCgyLCAzKTsgICAgICAgLy89PiAgNVxuICAgICAqICAgICAgUi5hZGQoNykoMTApOyAgICAgIC8vPT4gMTdcbiAgICAgKi9cbiAgICB2YXIgYWRkID0gX2N1cnJ5MihmdW5jdGlvbiBhZGQoYSwgYikge1xuICAgICAgICByZXR1cm4gTnVtYmVyKGEpICsgTnVtYmVyKGIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyBhIGZ1bmN0aW9uIHRvIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4gaW5kZXggb2YgYW4gYXJyYXksIHJldHVybmluZyBhXG4gICAgICogbmV3IGNvcHkgb2YgdGhlIGFycmF5IHdpdGggdGhlIGVsZW1lbnQgYXQgdGhlIGdpdmVuIGluZGV4IHJlcGxhY2VkIHdpdGggdGhlXG4gICAgICogcmVzdWx0IG9mIHRoZSBmdW5jdGlvbiBhcHBsaWNhdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoYSAtPiBhKSAtPiBOdW1iZXIgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBhcHBseS5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gaWR4IFRoZSBpbmRleC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fEFyZ3VtZW50c30gbGlzdCBBbiBhcnJheS1saWtlIG9iamVjdCB3aG9zZSB2YWx1ZVxuICAgICAqICAgICAgICBhdCB0aGUgc3VwcGxpZWQgaW5kZXggd2lsbCBiZSByZXBsYWNlZC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBjb3B5IG9mIHRoZSBzdXBwbGllZCBhcnJheS1saWtlIG9iamVjdCB3aXRoXG4gICAgICogICAgICAgICB0aGUgZWxlbWVudCBhdCBpbmRleCBgaWR4YCByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZVxuICAgICAqICAgICAgICAgcmV0dXJuZWQgYnkgYXBwbHlpbmcgYGZuYCB0byB0aGUgZXhpc3RpbmcgZWxlbWVudC5cbiAgICAgKiBAc2VlIFIudXBkYXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5hZGp1c3QoUi5hZGQoMTApLCAxLCBbMCwgMSwgMl0pOyAgICAgLy89PiBbMCwgMTEsIDJdXG4gICAgICogICAgICBSLmFkanVzdChSLmFkZCgxMCkpKDEpKFswLCAxLCAyXSk7ICAgICAvLz0+IFswLCAxMSwgMl1cbiAgICAgKi9cbiAgICB2YXIgYWRqdXN0ID0gX2N1cnJ5MyhmdW5jdGlvbiBhZGp1c3QoZm4sIGlkeCwgbGlzdCkge1xuICAgICAgICBpZiAoaWR4ID49IGxpc3QubGVuZ3RoIHx8IGlkeCA8IC1saXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN0YXJ0ID0gaWR4IDwgMCA/IGxpc3QubGVuZ3RoIDogMDtcbiAgICAgICAgdmFyIF9pZHggPSBzdGFydCArIGlkeDtcbiAgICAgICAgdmFyIF9saXN0ID0gX2NvbmNhdChsaXN0KTtcbiAgICAgICAgX2xpc3RbX2lkeF0gPSBmbihsaXN0W19pZHhdKTtcbiAgICAgICAgcmV0dXJuIF9saXN0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIG9mIHRoZSBsaXN0IG1hdGNoIHRoZSBwcmVkaWNhdGUsIGBmYWxzZWAgaWZcbiAgICAgKiB0aGVyZSBhcmUgYW55IHRoYXQgZG9uJ3QuXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgYWxsYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIHByZWRpY2F0ZSBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgdGhlIHByZWRpY2F0ZSBpcyBzYXRpc2ZpZWQgYnkgZXZlcnkgZWxlbWVudCwgYGZhbHNlYFxuICAgICAqICAgICAgICAgb3RoZXJ3aXNlLlxuICAgICAqIEBzZWUgUi5hbnksIFIubm9uZSwgUi50cmFuc2R1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbGVzc1RoYW4yID0gUi5mbGlwKFIubHQpKDIpO1xuICAgICAqICAgICAgdmFyIGxlc3NUaGFuMyA9IFIuZmxpcChSLmx0KSgzKTtcbiAgICAgKiAgICAgIFIuYWxsKGxlc3NUaGFuMikoWzEsIDJdKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5hbGwobGVzc1RoYW4zKShbMSwgMl0pOyAvLz0+IHRydWVcbiAgICAgKi9cbiAgICB2YXIgYWxsID0gX2N1cnJ5MihfZGlzcGF0Y2hhYmxlKCdhbGwnLCBfeGFsbCwgZnVuY3Rpb24gYWxsKGZuLCBsaXN0KSB7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghZm4obGlzdFtpZHhdKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0pKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGFsd2F5cyByZXR1cm5zIHRoZSBnaXZlbiB2YWx1ZS4gTm90ZSB0aGF0IGZvclxuICAgICAqIG5vbi1wcmltaXRpdmVzIHRoZSB2YWx1ZSByZXR1cm5lZCBpcyBhIHJlZmVyZW5jZSB0byB0aGUgb3JpZ2luYWwgdmFsdWUuXG4gICAgICpcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGtub3duIGFzIGBjb25zdGAsIGBjb25zdGFudGAsIG9yIGBLYCAoZm9yIEsgY29tYmluYXRvcikgaW5cbiAgICAgKiBvdGhlciBsYW5ndWFnZXMgYW5kIGxpYnJhcmllcy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyBhIC0+ICgqIC0+IGEpXG4gICAgICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBmdW5jdGlvblxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIEZ1bmN0aW9uIDo6ICogLT4gdmFsLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB0ID0gUi5hbHdheXMoJ1RlZScpO1xuICAgICAqICAgICAgdCgpOyAvLz0+ICdUZWUnXG4gICAgICovXG4gICAgdmFyIGFsd2F5cyA9IF9jdXJyeTEoZnVuY3Rpb24gYWx3YXlzKHZhbCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHRydWVgIGlmIGJvdGggYXJndW1lbnRzIGFyZSBgdHJ1ZWA7IGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTG9naWNcbiAgICAgKiBAc2lnICogLT4gKiAtPiAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBhIEEgYm9vbGVhbiB2YWx1ZVxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gYiBBIGJvb2xlYW4gdmFsdWVcbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgYm90aCBhcmd1bWVudHMgYXJlIGB0cnVlYCwgYGZhbHNlYCBvdGhlcndpc2VcbiAgICAgKiBAc2VlIFIuYm90aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuYW5kKHRydWUsIHRydWUpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIuYW5kKHRydWUsIGZhbHNlKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5hbmQoZmFsc2UsIHRydWUpOyAvLz0+IGZhbHNlXG4gICAgICogICAgICBSLmFuZChmYWxzZSwgZmFsc2UpOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGFuZCA9IF9jdXJyeTIoZnVuY3Rpb24gYW5kKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgJiYgYjtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHRydWVgIGlmIGF0IGxlYXN0IG9uZSBvZiBlbGVtZW50cyBvZiB0aGUgbGlzdCBtYXRjaCB0aGUgcHJlZGljYXRlLFxuICAgICAqIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGFueWAgbWV0aG9kIG9mIHRoZSBzZWNvbmQgYXJndW1lbnQsIGlmIHByZXNlbnQuXG4gICAgICpcbiAgICAgKiBBY3RzIGFzIGEgdHJhbnNkdWNlciBpZiBhIHRyYW5zZm9ybWVyIGlzIGdpdmVuIGluIGxpc3QgcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoYSAtPiBCb29sZWFuKSAtPiBbYV0gLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBwcmVkaWNhdGUgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgYXJyYXkgdG8gY29uc2lkZXIuXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn0gYHRydWVgIGlmIHRoZSBwcmVkaWNhdGUgaXMgc2F0aXNmaWVkIGJ5IGF0IGxlYXN0IG9uZSBlbGVtZW50LCBgZmFsc2VgXG4gICAgICogICAgICAgICBvdGhlcndpc2UuXG4gICAgICogQHNlZSBSLmFsbCwgUi5ub25lLCBSLnRyYW5zZHVjZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBsZXNzVGhhbjAgPSBSLmZsaXAoUi5sdCkoMCk7XG4gICAgICogICAgICB2YXIgbGVzc1RoYW4yID0gUi5mbGlwKFIubHQpKDIpO1xuICAgICAqICAgICAgUi5hbnkobGVzc1RoYW4wKShbMSwgMl0pOyAvLz0+IGZhbHNlXG4gICAgICogICAgICBSLmFueShsZXNzVGhhbjIpKFsxLCAyXSk7IC8vPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBhbnkgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2FueScsIF94YW55LCBmdW5jdGlvbiBhbnkoZm4sIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHdoaWxlIChpZHggPCBsaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKGZuKGxpc3RbaWR4XSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGxpc3QsIGNvbXBvc2VkIG9mIG4tdHVwbGVzIG9mIGNvbnNlY3V0aXZlIGVsZW1lbnRzIElmIGBuYCBpc1xuICAgICAqIGdyZWF0ZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIHRoZSBsaXN0LCBhbiBlbXB0eSBsaXN0IGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGFwZXJ0dXJlYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTIuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBOdW1iZXIgLT4gW2FdIC0+IFtbYV1dXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG4gVGhlIHNpemUgb2YgdGhlIHR1cGxlcyB0byBjcmVhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBsaXN0IHRvIHNwbGl0IGludG8gYG5gLXR1cGxlc1xuICAgICAqIEByZXR1cm4ge0FycmF5fSBUaGUgbmV3IGxpc3QuXG4gICAgICogQHNlZSBSLnRyYW5zZHVjZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuYXBlcnR1cmUoMiwgWzEsIDIsIDMsIDQsIDVdKTsgLy89PiBbWzEsIDJdLCBbMiwgM10sIFszLCA0XSwgWzQsIDVdXVxuICAgICAqICAgICAgUi5hcGVydHVyZSgzLCBbMSwgMiwgMywgNCwgNV0pOyAvLz0+IFtbMSwgMiwgM10sIFsyLCAzLCA0XSwgWzMsIDQsIDVdXVxuICAgICAqICAgICAgUi5hcGVydHVyZSg3LCBbMSwgMiwgMywgNCwgNV0pOyAvLz0+IFtdXG4gICAgICovXG4gICAgdmFyIGFwZXJ0dXJlID0gX2N1cnJ5MihfZGlzcGF0Y2hhYmxlKCdhcGVydHVyZScsIF94YXBlcnR1cmUsIF9hcGVydHVyZSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IGNvbnRhaW5pbmcgdGhlIGNvbnRlbnRzIG9mIHRoZSBnaXZlbiBsaXN0LCBmb2xsb3dlZCBieVxuICAgICAqIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgYSAtPiBbYV0gLT4gW2FdXG4gICAgICogQHBhcmFtIHsqfSBlbCBUaGUgZWxlbWVudCB0byBhZGQgdG8gdGhlIGVuZCBvZiB0aGUgbmV3IGxpc3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB3aG9zZSBjb250ZW50cyB3aWxsIGJlIGFkZGVkIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIG91dHB1dFxuICAgICAqICAgICAgICBsaXN0LlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBIG5ldyBsaXN0IGNvbnRhaW5pbmcgdGhlIGNvbnRlbnRzIG9mIHRoZSBvbGQgbGlzdCBmb2xsb3dlZCBieSBgZWxgLlxuICAgICAqIEBzZWUgUi5wcmVwZW5kXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5hcHBlbmQoJ3Rlc3RzJywgWyd3cml0ZScsICdtb3JlJ10pOyAvLz0+IFsnd3JpdGUnLCAnbW9yZScsICd0ZXN0cyddXG4gICAgICogICAgICBSLmFwcGVuZCgndGVzdHMnLCBbXSk7IC8vPT4gWyd0ZXN0cyddXG4gICAgICogICAgICBSLmFwcGVuZChbJ3Rlc3RzJ10sIFsnd3JpdGUnLCAnbW9yZSddKTsgLy89PiBbJ3dyaXRlJywgJ21vcmUnLCBbJ3Rlc3RzJ11dXG4gICAgICovXG4gICAgdmFyIGFwcGVuZCA9IF9jdXJyeTIoZnVuY3Rpb24gYXBwZW5kKGVsLCBsaXN0KSB7XG4gICAgICAgIHJldHVybiBfY29uY2F0KGxpc3QsIFtlbF0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyBmdW5jdGlvbiBgZm5gIHRvIHRoZSBhcmd1bWVudCBsaXN0IGBhcmdzYC4gVGhpcyBpcyB1c2VmdWwgZm9yXG4gICAgICogY3JlYXRpbmcgYSBmaXhlZC1hcml0eSBmdW5jdGlvbiBmcm9tIGEgdmFyaWFkaWMgZnVuY3Rpb24uIGBmbmAgc2hvdWxkIGJlIGFcbiAgICAgKiBib3VuZCBmdW5jdGlvbiBpZiBjb250ZXh0IGlzIHNpZ25pZmljYW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgqLi4uIC0+IGEpIC0+IFsqXSAtPiBhXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcmdzXG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIuY2FsbCwgUi51bmFwcGx5XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG51bXMgPSBbMSwgMiwgMywgLTk5LCA0MiwgNiwgN107XG4gICAgICogICAgICBSLmFwcGx5KE1hdGgubWF4LCBudW1zKTsgLy89PiA0MlxuICAgICAqL1xuICAgIHZhciBhcHBseSA9IF9jdXJyeTIoZnVuY3Rpb24gYXBwbHkoZm4sIGFyZ3MpIHtcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYSBzaGFsbG93IGNsb25lIG9mIGFuIG9iamVjdCwgc2V0dGluZyBvciBvdmVycmlkaW5nIHRoZSBzcGVjaWZpZWRcbiAgICAgKiBwcm9wZXJ0eSB3aXRoIHRoZSBnaXZlbiB2YWx1ZS4gTm90ZSB0aGF0IHRoaXMgY29waWVzIGFuZCBmbGF0dGVucyBwcm90b3R5cGVcbiAgICAgKiBwcm9wZXJ0aWVzIG9udG8gdGhlIG5ldyBvYmplY3QgYXMgd2VsbC4gQWxsIG5vbi1wcmltaXRpdmUgcHJvcGVydGllcyBhcmVcbiAgICAgKiBjb3BpZWQgYnkgcmVmZXJlbmNlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC44LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyBTdHJpbmcgLT4gYSAtPiB7azogdn0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHByb3AgdGhlIHByb3BlcnR5IG5hbWUgdG8gc2V0XG4gICAgICogQHBhcmFtIHsqfSB2YWwgdGhlIG5ldyB2YWx1ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogdGhlIG9iamVjdCB0byBjbG9uZVxuICAgICAqIEByZXR1cm4ge09iamVjdH0gYSBuZXcgb2JqZWN0IHNpbWlsYXIgdG8gdGhlIG9yaWdpbmFsIGV4Y2VwdCBmb3IgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eS5cbiAgICAgKiBAc2VlIFIuZGlzc29jXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5hc3NvYygnYycsIDMsIHthOiAxLCBiOiAyfSk7IC8vPT4ge2E6IDEsIGI6IDIsIGM6IDN9XG4gICAgICovXG4gICAgdmFyIGFzc29jID0gX2N1cnJ5MyhmdW5jdGlvbiBhc3NvYyhwcm9wLCB2YWwsIG9iaikge1xuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIGZvciAodmFyIHAgaW4gb2JqKSB7XG4gICAgICAgICAgICByZXN1bHRbcF0gPSBvYmpbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0W3Byb3BdID0gdmFsO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYSBzaGFsbG93IGNsb25lIG9mIGFuIG9iamVjdCwgc2V0dGluZyBvciBvdmVycmlkaW5nIHRoZSBub2RlcyByZXF1aXJlZFxuICAgICAqIHRvIGNyZWF0ZSB0aGUgZ2l2ZW4gcGF0aCwgYW5kIHBsYWNpbmcgdGhlIHNwZWNpZmljIHZhbHVlIGF0IHRoZSB0YWlsIGVuZCBvZlxuICAgICAqIHRoYXQgcGF0aC4gTm90ZSB0aGF0IHRoaXMgY29waWVzIGFuZCBmbGF0dGVucyBwcm90b3R5cGUgcHJvcGVydGllcyBvbnRvIHRoZVxuICAgICAqIG5ldyBvYmplY3QgYXMgd2VsbC4gQWxsIG5vbi1wcmltaXRpdmUgcHJvcGVydGllcyBhcmUgY29waWVkIGJ5IHJlZmVyZW5jZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgW1N0cmluZ10gLT4gYSAtPiB7azogdn0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0aCB0aGUgcGF0aCB0byBzZXRcbiAgICAgKiBAcGFyYW0geyp9IHZhbCB0aGUgbmV3IHZhbHVlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiB0aGUgb2JqZWN0IHRvIGNsb25lXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBhIG5ldyBvYmplY3Qgc2ltaWxhciB0byB0aGUgb3JpZ2luYWwgZXhjZXB0IGFsb25nIHRoZSBzcGVjaWZpZWQgcGF0aC5cbiAgICAgKiBAc2VlIFIuZGlzc29jUGF0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuYXNzb2NQYXRoKFsnYScsICdiJywgJ2MnXSwgNDIsIHthOiB7Yjoge2M6IDB9fX0pOyAvLz0+IHthOiB7Yjoge2M6IDQyfX19XG4gICAgICovXG4gICAgdmFyIGFzc29jUGF0aCA9IF9jdXJyeTMoZnVuY3Rpb24gYXNzb2NQYXRoKHBhdGgsIHZhbCwgb2JqKSB7XG4gICAgICAgIHN3aXRjaCAocGF0aC5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuIGFzc29jKHBhdGhbMF0sIHZhbCwgb2JqKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBhc3NvYyhwYXRoWzBdLCBhc3NvY1BhdGgoX3NsaWNlKHBhdGgsIDEpLCB2YWwsIE9iamVjdChvYmpbcGF0aFswXV0pKSwgb2JqKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaXMgYm91bmQgdG8gYSBjb250ZXh0LlxuICAgICAqIE5vdGU6IGBSLmJpbmRgIGRvZXMgbm90IHByb3ZpZGUgdGhlIGFkZGl0aW9uYWwgYXJndW1lbnQtYmluZGluZyBjYXBhYmlsaXRpZXMgb2ZcbiAgICAgKiBbRnVuY3Rpb24ucHJvdG90eXBlLmJpbmRdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Z1bmN0aW9uL2JpbmQpLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyAoKiAtPiAqKSAtPiB7Kn0gLT4gKCogLT4gKilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gYmluZCB0byBjb250ZXh0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IHRoaXNPYmogVGhlIGNvbnRleHQgdG8gYmluZCBgZm5gIHRvXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IEEgZnVuY3Rpb24gdGhhdCB3aWxsIGV4ZWN1dGUgaW4gdGhlIGNvbnRleHQgb2YgYHRoaXNPYmpgLlxuICAgICAqIEBzZWUgUi5wYXJ0aWFsXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGxvZyA9IFIuYmluZChjb25zb2xlLmxvZywgY29uc29sZSk7XG4gICAgICogICAgICBSLnBpcGUoUi5hc3NvYygnYScsIDIpLCBSLnRhcChsb2cpLCBSLmFzc29jKCdhJywgMykpKHthOiAxfSk7IC8vPT4ge2E6IDN9XG4gICAgICogICAgICAvLyBsb2dzIHthOiAyfVxuICAgICAqL1xuICAgIHZhciBiaW5kID0gX2N1cnJ5MihmdW5jdGlvbiBiaW5kKGZuLCB0aGlzT2JqKSB7XG4gICAgICAgIHJldHVybiBfYXJpdHkoZm4ubGVuZ3RoLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpc09iaiwgYXJndW1lbnRzKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXN0cmljdHMgYSBudW1iZXIgdG8gYmUgd2l0aGluIGEgcmFuZ2UuXG4gICAgICpcbiAgICAgKiBBbHNvIHdvcmtzIGZvciBvdGhlciBvcmRlcmVkIHR5cGVzIHN1Y2ggYXMgU3RyaW5ncyBhbmQgRGF0ZXMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjIwLjBcbiAgICAgKiBAY2F0ZWdvcnkgUmVsYXRpb25cbiAgICAgKiBAc2lnIE9yZCBhID0+IGEgLT4gYSAtPiBhIC0+IGFcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbWluaW11bSBudW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbWF4aW11bSBudW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWUgdG8gYmUgY2xhbXBlZFxuICAgICAqIEByZXR1cm4ge051bWJlcn0gUmV0dXJucyB0aGUgY2xhbXBlZCB2YWx1ZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuY2xhbXAoMSwgMTAsIC0xKSAvLyA9PiAxXG4gICAgICogICAgICBSLmNsYW1wKDEsIDEwLCAxMSkgLy8gPT4gMTBcbiAgICAgKiAgICAgIFIuY2xhbXAoMSwgMTAsIDQpICAvLyA9PiA0XG4gICAgICovXG4gICAgdmFyIGNsYW1wID0gX2N1cnJ5MyhmdW5jdGlvbiBjbGFtcChtaW4sIG1heCwgdmFsdWUpIHtcbiAgICAgICAgaWYgKG1pbiA+IG1heCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaW4gbXVzdCBub3QgYmUgZ3JlYXRlciB0aGFuIG1heCBpbiBjbGFtcChtaW4sIG1heCwgdmFsdWUpJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlIDwgbWluID8gbWluIDogdmFsdWUgPiBtYXggPyBtYXggOiB2YWx1ZTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGEgY29tcGFyYXRvciBmdW5jdGlvbiBvdXQgb2YgYSBmdW5jdGlvbiB0aGF0IHJlcG9ydHMgd2hldGhlciB0aGUgZmlyc3RcbiAgICAgKiBlbGVtZW50IGlzIGxlc3MgdGhhbiB0aGUgc2Vjb25kLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIChhLCBiIC0+IEJvb2xlYW4pIC0+IChhLCBiIC0+IE51bWJlcilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkIEEgcHJlZGljYXRlIGZ1bmN0aW9uIG9mIGFyaXR5IHR3by5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBGdW5jdGlvbiA6OiBhIC0+IGIgLT4gSW50IHRoYXQgcmV0dXJucyBgLTFgIGlmIGEgPCBiLCBgMWAgaWYgYiA8IGEsIG90aGVyd2lzZSBgMGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGNtcCA9IFIuY29tcGFyYXRvcigoYSwgYikgPT4gYS5hZ2UgPCBiLmFnZSk7XG4gICAgICogICAgICB2YXIgcGVvcGxlID0gW1xuICAgICAqICAgICAgICAvLyAuLi5cbiAgICAgKiAgICAgIF07XG4gICAgICogICAgICBSLnNvcnQoY21wLCBwZW9wbGUpO1xuICAgICAqL1xuICAgIHZhciBjb21wYXJhdG9yID0gX2N1cnJ5MShmdW5jdGlvbiBjb21wYXJhdG9yKHByZWQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZChhLCBiKSA/IC0xIDogcHJlZChiLCBhKSA/IDEgOiAwO1xuICAgICAgICB9O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGN1cnJpZWQgZXF1aXZhbGVudCBvZiB0aGUgcHJvdmlkZWQgZnVuY3Rpb24sIHdpdGggdGhlIHNwZWNpZmllZFxuICAgICAqIGFyaXR5LiBUaGUgY3VycmllZCBmdW5jdGlvbiBoYXMgdHdvIHVudXN1YWwgY2FwYWJpbGl0aWVzLiBGaXJzdCwgaXRzXG4gICAgICogYXJndW1lbnRzIG5lZWRuJ3QgYmUgcHJvdmlkZWQgb25lIGF0IGEgdGltZS4gSWYgYGdgIGlzIGBSLmN1cnJ5TigzLCBmKWAsIHRoZVxuICAgICAqIGZvbGxvd2luZyBhcmUgZXF1aXZhbGVudDpcbiAgICAgKlxuICAgICAqICAgLSBgZygxKSgyKSgzKWBcbiAgICAgKiAgIC0gYGcoMSkoMiwgMylgXG4gICAgICogICAtIGBnKDEsIDIpKDMpYFxuICAgICAqICAgLSBgZygxLCAyLCAzKWBcbiAgICAgKlxuICAgICAqIFNlY29uZGx5LCB0aGUgc3BlY2lhbCBwbGFjZWhvbGRlciB2YWx1ZSBgUi5fX2AgbWF5IGJlIHVzZWQgdG8gc3BlY2lmeVxuICAgICAqIFwiZ2Fwc1wiLCBhbGxvd2luZyBwYXJ0aWFsIGFwcGxpY2F0aW9uIG9mIGFueSBjb21iaW5hdGlvbiBvZiBhcmd1bWVudHMsXG4gICAgICogcmVnYXJkbGVzcyBvZiB0aGVpciBwb3NpdGlvbnMuIElmIGBnYCBpcyBhcyBhYm92ZSBhbmQgYF9gIGlzIGBSLl9fYCwgdGhlXG4gICAgICogZm9sbG93aW5nIGFyZSBlcXVpdmFsZW50OlxuICAgICAqXG4gICAgICogICAtIGBnKDEsIDIsIDMpYFxuICAgICAqICAgLSBgZyhfLCAyLCAzKSgxKWBcbiAgICAgKiAgIC0gYGcoXywgXywgMykoMSkoMilgXG4gICAgICogICAtIGBnKF8sIF8sIDMpKDEsIDIpYFxuICAgICAqICAgLSBgZyhfLCAyKSgxKSgzKWBcbiAgICAgKiAgIC0gYGcoXywgMikoMSwgMylgXG4gICAgICogICAtIGBnKF8sIDIpKF8sIDMpKDEpYFxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC41LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIE51bWJlciAtPiAoKiAtPiBhKSAtPiAoKiAtPiBhKVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBsZW5ndGggVGhlIGFyaXR5IGZvciB0aGUgcmV0dXJuZWQgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGN1cnJ5LlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIG5ldywgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAc2VlIFIuY3VycnlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgc3VtQXJncyA9ICguLi5hcmdzKSA9PiBSLnN1bShhcmdzKTtcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGN1cnJpZWRBZGRGb3VyTnVtYmVycyA9IFIuY3VycnlOKDQsIHN1bUFyZ3MpO1xuICAgICAqICAgICAgdmFyIGYgPSBjdXJyaWVkQWRkRm91ck51bWJlcnMoMSwgMik7XG4gICAgICogICAgICB2YXIgZyA9IGYoMyk7XG4gICAgICogICAgICBnKDQpOyAvLz0+IDEwXG4gICAgICovXG4gICAgdmFyIGN1cnJ5TiA9IF9jdXJyeTIoZnVuY3Rpb24gY3VycnlOKGxlbmd0aCwgZm4pIHtcbiAgICAgICAgaWYgKGxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIF9jdXJyeTEoZm4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfYXJpdHkobGVuZ3RoLCBfY3VycnlOKGxlbmd0aCwgW10sIGZuKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBEZWNyZW1lbnRzIGl0cyBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIE51bWJlciAtPiBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gblxuICAgICAqIEByZXR1cm4ge051bWJlcn1cbiAgICAgKiBAc2VlIFIuaW5jXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5kZWMoNDIpOyAvLz0+IDQxXG4gICAgICovXG4gICAgdmFyIGRlYyA9IGFkZCgtMSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzZWNvbmQgYXJndW1lbnQgaWYgaXQgaXMgbm90IGBudWxsYCwgYHVuZGVmaW5lZGAgb3IgYE5hTmBcbiAgICAgKiBvdGhlcndpc2UgdGhlIGZpcnN0IGFyZ3VtZW50IGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMC4wXG4gICAgICogQGNhdGVnb3J5IExvZ2ljXG4gICAgICogQHNpZyBhIC0+IGIgLT4gYSB8IGJcbiAgICAgKiBAcGFyYW0ge2F9IHZhbCBUaGUgZGVmYXVsdCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge2J9IHZhbCBUaGUgdmFsdWUgdG8gcmV0dXJuIGlmIGl0IGlzIG5vdCBudWxsIG9yIHVuZGVmaW5lZFxuICAgICAqIEByZXR1cm4geyp9IFRoZSB0aGUgc2Vjb25kIHZhbHVlIG9yIHRoZSBkZWZhdWx0IHZhbHVlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGRlZmF1bHRUbzQyID0gUi5kZWZhdWx0VG8oNDIpO1xuICAgICAqXG4gICAgICogICAgICBkZWZhdWx0VG80MihudWxsKTsgIC8vPT4gNDJcbiAgICAgKiAgICAgIGRlZmF1bHRUbzQyKHVuZGVmaW5lZCk7ICAvLz0+IDQyXG4gICAgICogICAgICBkZWZhdWx0VG80MignUmFtZGEnKTsgIC8vPT4gJ1JhbWRhJ1xuICAgICAqICAgICAgZGVmYXVsdFRvNDIocGFyc2VJbnQoJ3N0cmluZycpKTsgLy89PiA0MlxuICAgICAqL1xuICAgIHZhciBkZWZhdWx0VG8gPSBfY3VycnkyKGZ1bmN0aW9uIGRlZmF1bHRUbyhkLCB2KSB7XG4gICAgICAgIHJldHVybiB2ID09IG51bGwgfHwgdiAhPT0gdiA/IGQgOiB2O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIHNldCAoaS5lLiBubyBkdXBsaWNhdGVzKSBvZiBhbGwgZWxlbWVudHMgaW4gdGhlIGZpcnN0IGxpc3Qgbm90XG4gICAgICogY29udGFpbmVkIGluIHRoZSBzZWNvbmQgbGlzdC4gRHVwbGljYXRpb24gaXMgZGV0ZXJtaW5lZCBhY2NvcmRpbmcgdG8gdGhlXG4gICAgICogdmFsdWUgcmV0dXJuZWQgYnkgYXBwbHlpbmcgdGhlIHN1cHBsaWVkIHByZWRpY2F0ZSB0byB0d28gbGlzdCBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyAoYSAtPiBhIC0+IEJvb2xlYW4pIC0+IFsqXSAtPiBbKl0gLT4gWypdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZCBBIHByZWRpY2F0ZSB1c2VkIHRvIHRlc3Qgd2hldGhlciB0d28gaXRlbXMgYXJlIGVxdWFsLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QxIFRoZSBmaXJzdCBsaXN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QyIFRoZSBzZWNvbmQgbGlzdC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGVsZW1lbnRzIGluIGBsaXN0MWAgdGhhdCBhcmUgbm90IGluIGBsaXN0MmAuXG4gICAgICogQHNlZSBSLmRpZmZlcmVuY2UsIFIuc3ltbWV0cmljRGlmZmVyZW5jZSwgUi5zeW1tZXRyaWNEaWZmZXJlbmNlV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBjbXAgPSAoeCwgeSkgPT4geC5hID09PSB5LmE7XG4gICAgICogICAgICB2YXIgbDEgPSBbe2E6IDF9LCB7YTogMn0sIHthOiAzfV07XG4gICAgICogICAgICB2YXIgbDIgPSBbe2E6IDN9LCB7YTogNH1dO1xuICAgICAqICAgICAgUi5kaWZmZXJlbmNlV2l0aChjbXAsIGwxLCBsMik7IC8vPT4gW3thOiAxfSwge2E6IDJ9XVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlV2l0aCA9IF9jdXJyeTMoZnVuY3Rpb24gZGlmZmVyZW5jZVdpdGgocHJlZCwgZmlyc3QsIHNlY29uZCkge1xuICAgICAgICB2YXIgb3V0ID0gW107XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgZmlyc3RMZW4gPSBmaXJzdC5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpZHggPCBmaXJzdExlbikge1xuICAgICAgICAgICAgaWYgKCFfY29udGFpbnNXaXRoKHByZWQsIGZpcnN0W2lkeF0sIHNlY29uZCkgJiYgIV9jb250YWluc1dpdGgocHJlZCwgZmlyc3RbaWR4XSwgb3V0KSkge1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKGZpcnN0W2lkeF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHRoYXQgZG9lcyBub3QgY29udGFpbiBhIGBwcm9wYCBwcm9wZXJ0eS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIFN0cmluZyAtPiB7azogdn0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHByb3AgdGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIGRpc3NvY2lhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIHRoZSBvYmplY3QgdG8gY2xvbmVcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IGEgbmV3IG9iamVjdCBzaW1pbGFyIHRvIHRoZSBvcmlnaW5hbCBidXQgd2l0aG91dCB0aGUgc3BlY2lmaWVkIHByb3BlcnR5XG4gICAgICogQHNlZSBSLmFzc29jXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5kaXNzb2MoJ2InLCB7YTogMSwgYjogMiwgYzogM30pOyAvLz0+IHthOiAxLCBjOiAzfVxuICAgICAqL1xuICAgIHZhciBkaXNzb2MgPSBfY3VycnkyKGZ1bmN0aW9uIGRpc3NvYyhwcm9wLCBvYmopIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICBmb3IgKHZhciBwIGluIG9iaikge1xuICAgICAgICAgICAgaWYgKHAgIT09IHByb3ApIHtcbiAgICAgICAgICAgICAgICByZXN1bHRbcF0gPSBvYmpbcF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGEgc2hhbGxvdyBjbG9uZSBvZiBhbiBvYmplY3QsIG9taXR0aW5nIHRoZSBwcm9wZXJ0eSBhdCB0aGUgZ2l2ZW4gcGF0aC5cbiAgICAgKiBOb3RlIHRoYXQgdGhpcyBjb3BpZXMgYW5kIGZsYXR0ZW5zIHByb3RvdHlwZSBwcm9wZXJ0aWVzIG9udG8gdGhlIG5ldyBvYmplY3RcbiAgICAgKiBhcyB3ZWxsLiBBbGwgbm9uLXByaW1pdGl2ZSBwcm9wZXJ0aWVzIGFyZSBjb3BpZWQgYnkgcmVmZXJlbmNlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgW1N0cmluZ10gLT4ge2s6IHZ9IC0+IHtrOiB2fVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhdGggdGhlIHBhdGggdG8gc2V0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiB0aGUgb2JqZWN0IHRvIGNsb25lXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBhIG5ldyBvYmplY3Qgd2l0aG91dCB0aGUgcHJvcGVydHkgYXQgcGF0aFxuICAgICAqIEBzZWUgUi5hc3NvY1BhdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmRpc3NvY1BhdGgoWydhJywgJ2InLCAnYyddLCB7YToge2I6IHtjOiA0Mn19fSk7IC8vPT4ge2E6IHtiOiB7fX19XG4gICAgICovXG4gICAgdmFyIGRpc3NvY1BhdGggPSBfY3VycnkyKGZ1bmN0aW9uIGRpc3NvY1BhdGgocGF0aCwgb2JqKSB7XG4gICAgICAgIHN3aXRjaCAocGF0aC5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgcmV0dXJuIGRpc3NvYyhwYXRoWzBdLCBvYmopO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdmFyIGhlYWQgPSBwYXRoWzBdO1xuICAgICAgICAgICAgdmFyIHRhaWwgPSBfc2xpY2UocGF0aCwgMSk7XG4gICAgICAgICAgICByZXR1cm4gb2JqW2hlYWRdID09IG51bGwgPyBvYmogOiBhc3NvYyhoZWFkLCBkaXNzb2NQYXRoKHRhaWwsIG9ialtoZWFkXSksIG9iaik7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIERpdmlkZXMgdHdvIG51bWJlcnMuIEVxdWl2YWxlbnQgdG8gYGEgLyBiYC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIE51bWJlciAtPiBOdW1iZXIgLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGEgVGhlIGZpcnN0IHZhbHVlLlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBiIFRoZSBzZWNvbmQgdmFsdWUuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBUaGUgcmVzdWx0IG9mIGBhIC8gYmAuXG4gICAgICogQHNlZSBSLm11bHRpcGx5XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5kaXZpZGUoNzEsIDEwMCk7IC8vPT4gMC43MVxuICAgICAqXG4gICAgICogICAgICB2YXIgaGFsZiA9IFIuZGl2aWRlKFIuX18sIDIpO1xuICAgICAqICAgICAgaGFsZig0Mik7IC8vPT4gMjFcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHJlY2lwcm9jYWwgPSBSLmRpdmlkZSgxKTtcbiAgICAgKiAgICAgIHJlY2lwcm9jYWwoNCk7ICAgLy89PiAwLjI1XG4gICAgICovXG4gICAgdmFyIGRpdmlkZSA9IF9jdXJyeTIoZnVuY3Rpb24gZGl2aWRlKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgLyBiO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IGV4Y2x1ZGluZyB0aGUgbGVhZGluZyBlbGVtZW50cyBvZiBhIGdpdmVuIGxpc3Qgd2hpY2hcbiAgICAgKiBzYXRpc2Z5IHRoZSBzdXBwbGllZCBwcmVkaWNhdGUgZnVuY3Rpb24uIEl0IHBhc3NlcyBlYWNoIHZhbHVlIHRvIHRoZSBzdXBwbGllZFxuICAgICAqIHByZWRpY2F0ZSBmdW5jdGlvbiwgc2tpcHBpbmcgZWxlbWVudHMgd2hpbGUgdGhlIHByZWRpY2F0ZSBmdW5jdGlvbiByZXR1cm5zXG4gICAgICogYHRydWVgLiBUaGUgcHJlZGljYXRlIGZ1bmN0aW9uIGlzIGFwcGxpZWQgdG8gb25lIGFyZ3VtZW50OiAqKHZhbHVlKSouXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgZHJvcFdoaWxlYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybiB7QXJyYXl9IEEgbmV3IGFycmF5LlxuICAgICAqIEBzZWUgUi50YWtlV2hpbGUsIFIudHJhbnNkdWNlLCBSLmFkZEluZGV4XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGx0ZVR3byA9IHggPT4geCA8PSAyO1xuICAgICAqXG4gICAgICogICAgICBSLmRyb3BXaGlsZShsdGVUd28sIFsxLCAyLCAzLCA0LCAzLCAyLCAxXSk7IC8vPT4gWzMsIDQsIDMsIDIsIDFdXG4gICAgICovXG4gICAgdmFyIGRyb3BXaGlsZSA9IF9jdXJyeTIoX2Rpc3BhdGNoYWJsZSgnZHJvcFdoaWxlJywgX3hkcm9wV2hpbGUsIGZ1bmN0aW9uIGRyb3BXaGlsZShwcmVkLCBsaXN0KSB7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgbGVuID0gbGlzdC5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4gJiYgcHJlZChsaXN0W2lkeF0pKSB7XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3NsaWNlKGxpc3QsIGlkeCk7XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZW1wdHkgdmFsdWUgb2YgaXRzIGFyZ3VtZW50J3MgdHlwZS4gUmFtZGEgZGVmaW5lcyB0aGUgZW1wdHlcbiAgICAgKiB2YWx1ZSBvZiBBcnJheSAoYFtdYCksIE9iamVjdCAoYHt9YCksIFN0cmluZyAoYCcnYCksIGFuZCBBcmd1bWVudHMuIE90aGVyXG4gICAgICogdHlwZXMgYXJlIHN1cHBvcnRlZCBpZiB0aGV5IGRlZmluZSBgPFR5cGU+LmVtcHR5YCBhbmQvb3JcbiAgICAgKiBgPFR5cGU+LnByb3RvdHlwZS5lbXB0eWAuXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgZW1wdHlgIG1ldGhvZCBvZiB0aGUgZmlyc3QgYXJndW1lbnQsIGlmIHByZXNlbnQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjMuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgYSAtPiBhXG4gICAgICogQHBhcmFtIHsqfSB4XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmVtcHR5KEp1c3QoNDIpKTsgICAgICAvLz0+IE5vdGhpbmcoKVxuICAgICAqICAgICAgUi5lbXB0eShbMSwgMiwgM10pOyAgICAgLy89PiBbXVxuICAgICAqICAgICAgUi5lbXB0eSgndW5pY29ybnMnKTsgICAgLy89PiAnJ1xuICAgICAqICAgICAgUi5lbXB0eSh7eDogMSwgeTogMn0pOyAgLy89PiB7fVxuICAgICAqL1xuICAgIC8vIGVsc2VcbiAgICB2YXIgZW1wdHkgPSBfY3VycnkxKGZ1bmN0aW9uIGVtcHR5KHgpIHtcbiAgICAgICAgcmV0dXJuIHggIT0gbnVsbCAmJiB0eXBlb2YgeC5lbXB0eSA9PT0gJ2Z1bmN0aW9uJyA/IHguZW1wdHkoKSA6IHggIT0gbnVsbCAmJiB4LmNvbnN0cnVjdG9yICE9IG51bGwgJiYgdHlwZW9mIHguY29uc3RydWN0b3IuZW1wdHkgPT09ICdmdW5jdGlvbicgPyB4LmNvbnN0cnVjdG9yLmVtcHR5KCkgOiBfaXNBcnJheSh4KSA/IFtdIDogX2lzU3RyaW5nKHgpID8gJycgOiBfaXNPYmplY3QoeCkgPyB7fSA6IF9pc0FyZ3VtZW50cyh4KSA/IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmd1bWVudHM7XG4gICAgICAgIH0oKSA6IC8vIGVsc2VcbiAgICAgICAgdm9pZCAwO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBvYmplY3QgYnkgcmVjdXJzaXZlbHkgZXZvbHZpbmcgYSBzaGFsbG93IGNvcHkgb2YgYG9iamVjdGAsXG4gICAgICogYWNjb3JkaW5nIHRvIHRoZSBgdHJhbnNmb3JtYXRpb25gIGZ1bmN0aW9ucy4gQWxsIG5vbi1wcmltaXRpdmUgcHJvcGVydGllc1xuICAgICAqIGFyZSBjb3BpZWQgYnkgcmVmZXJlbmNlLlxuICAgICAqXG4gICAgICogQSBgdHJhbnNmb3JtYXRpb25gIGZ1bmN0aW9uIHdpbGwgbm90IGJlIGludm9rZWQgaWYgaXRzIGNvcnJlc3BvbmRpbmcga2V5XG4gICAgICogZG9lcyBub3QgZXhpc3QgaW4gdGhlIGV2b2x2ZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC45LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyB7azogKHYgLT4gdil9IC0+IHtrOiB2fSAtPiB7azogdn1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdHJhbnNmb3JtYXRpb25zIFRoZSBvYmplY3Qgc3BlY2lmeWluZyB0cmFuc2Zvcm1hdGlvbiBmdW5jdGlvbnMgdG8gYXBwbHlcbiAgICAgKiAgICAgICAgdG8gdGhlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gYmUgdHJhbnNmb3JtZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgdHJhbnNmb3JtZWQgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB0b21hdG8gID0ge2ZpcnN0TmFtZTogJyAgVG9tYXRvICcsIGRhdGE6IHtlbGFwc2VkOiAxMDAsIHJlbWFpbmluZzogMTQwMH0sIGlkOjEyM307XG4gICAgICogICAgICB2YXIgdHJhbnNmb3JtYXRpb25zID0ge1xuICAgICAqICAgICAgICBmaXJzdE5hbWU6IFIudHJpbSxcbiAgICAgKiAgICAgICAgbGFzdE5hbWU6IFIudHJpbSwgLy8gV2lsbCBub3QgZ2V0IGludm9rZWQuXG4gICAgICogICAgICAgIGRhdGE6IHtlbGFwc2VkOiBSLmFkZCgxKSwgcmVtYWluaW5nOiBSLmFkZCgtMSl9XG4gICAgICogICAgICB9O1xuICAgICAqICAgICAgUi5ldm9sdmUodHJhbnNmb3JtYXRpb25zLCB0b21hdG8pOyAvLz0+IHtmaXJzdE5hbWU6ICdUb21hdG8nLCBkYXRhOiB7ZWxhcHNlZDogMTAxLCByZW1haW5pbmc6IDEzOTl9LCBpZDoxMjN9XG4gICAgICovXG4gICAgdmFyIGV2b2x2ZSA9IF9jdXJyeTIoZnVuY3Rpb24gZXZvbHZlKHRyYW5zZm9ybWF0aW9ucywgb2JqZWN0KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgICAgdmFyIHRyYW5zZm9ybWF0aW9uLCBrZXksIHR5cGU7XG4gICAgICAgIGZvciAoa2V5IGluIG9iamVjdCkge1xuICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24gPSB0cmFuc2Zvcm1hdGlvbnNba2V5XTtcbiAgICAgICAgICAgIHR5cGUgPSB0eXBlb2YgdHJhbnNmb3JtYXRpb247XG4gICAgICAgICAgICByZXN1bHRba2V5XSA9IHR5cGUgPT09ICdmdW5jdGlvbicgPyB0cmFuc2Zvcm1hdGlvbihvYmplY3Rba2V5XSkgOiB0eXBlID09PSAnb2JqZWN0JyA/IGV2b2x2ZSh0cmFuc2Zvcm1hdGlvbnNba2V5XSwgb2JqZWN0W2tleV0pIDogb2JqZWN0W2tleV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGZpcnN0IGVsZW1lbnQgb2YgdGhlIGxpc3Qgd2hpY2ggbWF0Y2hlcyB0aGUgcHJlZGljYXRlLCBvclxuICAgICAqIGB1bmRlZmluZWRgIGlmIG5vIGVsZW1lbnQgbWF0Y2hlcy5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBmaW5kYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBhIHwgdW5kZWZpbmVkXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIHByZWRpY2F0ZSBmdW5jdGlvbiB1c2VkIHRvIGRldGVybWluZSBpZiB0aGUgZWxlbWVudCBpcyB0aGVcbiAgICAgKiAgICAgICAgZGVzaXJlZCBvbmUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgYXJyYXkgdG8gY29uc2lkZXIuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgZWxlbWVudCBmb3VuZCwgb3IgYHVuZGVmaW5lZGAuXG4gICAgICogQHNlZSBSLnRyYW5zZHVjZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB4cyA9IFt7YTogMX0sIHthOiAyfSwge2E6IDN9XTtcbiAgICAgKiAgICAgIFIuZmluZChSLnByb3BFcSgnYScsIDIpKSh4cyk7IC8vPT4ge2E6IDJ9XG4gICAgICogICAgICBSLmZpbmQoUi5wcm9wRXEoJ2EnLCA0KSkoeHMpOyAvLz0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIHZhciBmaW5kID0gX2N1cnJ5MihfZGlzcGF0Y2hhYmxlKCdmaW5kJywgX3hmaW5kLCBmdW5jdGlvbiBmaW5kKGZuLCBsaXN0KSB7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgbGVuID0gbGlzdC5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChmbihsaXN0W2lkeF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpc3RbaWR4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGVsZW1lbnQgb2YgdGhlIGxpc3Qgd2hpY2ggbWF0Y2hlcyB0aGVcbiAgICAgKiBwcmVkaWNhdGUsIG9yIGAtMWAgaWYgbm8gZWxlbWVudCBtYXRjaGVzLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGZpbmRJbmRleGAgbWV0aG9kIG9mIHRoZSBzZWNvbmQgYXJndW1lbnQsIGlmIHByZXNlbnQuXG4gICAgICpcbiAgICAgKiBBY3RzIGFzIGEgdHJhbnNkdWNlciBpZiBhIHRyYW5zZm9ybWVyIGlzIGdpdmVuIGluIGxpc3QgcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMVxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoYSAtPiBCb29sZWFuKSAtPiBbYV0gLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIHByZWRpY2F0ZSBmdW5jdGlvbiB1c2VkIHRvIGRldGVybWluZSBpZiB0aGUgZWxlbWVudCBpcyB0aGVcbiAgICAgKiBkZXNpcmVkIG9uZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCBmb3VuZCwgb3IgYC0xYC5cbiAgICAgKiBAc2VlIFIudHJhbnNkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHhzID0gW3thOiAxfSwge2E6IDJ9LCB7YTogM31dO1xuICAgICAqICAgICAgUi5maW5kSW5kZXgoUi5wcm9wRXEoJ2EnLCAyKSkoeHMpOyAvLz0+IDFcbiAgICAgKiAgICAgIFIuZmluZEluZGV4KFIucHJvcEVxKCdhJywgNCkpKHhzKTsgLy89PiAtMVxuICAgICAqL1xuICAgIHZhciBmaW5kSW5kZXggPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2ZpbmRJbmRleCcsIF94ZmluZEluZGV4LCBmdW5jdGlvbiBmaW5kSW5kZXgoZm4sIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHZhciBsZW4gPSBsaXN0Lmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbikge1xuICAgICAgICAgICAgaWYgKGZuKGxpc3RbaWR4XSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWR4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH0pKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxhc3QgZWxlbWVudCBvZiB0aGUgbGlzdCB3aGljaCBtYXRjaGVzIHRoZSBwcmVkaWNhdGUsIG9yXG4gICAgICogYHVuZGVmaW5lZGAgaWYgbm8gZWxlbWVudCBtYXRjaGVzLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGZpbmRMYXN0YCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4xXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBhIHwgdW5kZWZpbmVkXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIHByZWRpY2F0ZSBmdW5jdGlvbiB1c2VkIHRvIGRldGVybWluZSBpZiB0aGUgZWxlbWVudCBpcyB0aGVcbiAgICAgKiBkZXNpcmVkIG9uZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBlbGVtZW50IGZvdW5kLCBvciBgdW5kZWZpbmVkYC5cbiAgICAgKiBAc2VlIFIudHJhbnNkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHhzID0gW3thOiAxLCBiOiAwfSwge2E6MSwgYjogMX1dO1xuICAgICAqICAgICAgUi5maW5kTGFzdChSLnByb3BFcSgnYScsIDEpKSh4cyk7IC8vPT4ge2E6IDEsIGI6IDF9XG4gICAgICogICAgICBSLmZpbmRMYXN0KFIucHJvcEVxKCdhJywgNCkpKHhzKTsgLy89PiB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB2YXIgZmluZExhc3QgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2ZpbmRMYXN0JywgX3hmaW5kTGFzdCwgZnVuY3Rpb24gZmluZExhc3QoZm4sIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IGxpc3QubGVuZ3RoIC0gMTtcbiAgICAgICAgd2hpbGUgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICBpZiAoZm4obGlzdFtpZHhdKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsaXN0W2lkeF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZHggLT0gMTtcbiAgICAgICAgfVxuICAgIH0pKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBsYXN0IGVsZW1lbnQgb2YgdGhlIGxpc3Qgd2hpY2ggbWF0Y2hlcyB0aGVcbiAgICAgKiBwcmVkaWNhdGUsIG9yIGAtMWAgaWYgbm8gZWxlbWVudCBtYXRjaGVzLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGZpbmRMYXN0SW5kZXhgIG1ldGhvZCBvZiB0aGUgc2Vjb25kIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQWN0cyBhcyBhIHRyYW5zZHVjZXIgaWYgYSB0cmFuc2Zvcm1lciBpcyBnaXZlbiBpbiBsaXN0IHBvc2l0aW9uLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjFcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEgLT4gQm9vbGVhbikgLT4gW2FdIC0+IE51bWJlclxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBwcmVkaWNhdGUgZnVuY3Rpb24gdXNlZCB0byBkZXRlcm1pbmUgaWYgdGhlIGVsZW1lbnQgaXMgdGhlXG4gICAgICogZGVzaXJlZCBvbmUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgYXJyYXkgdG8gY29uc2lkZXIuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgZm91bmQsIG9yIGAtMWAuXG4gICAgICogQHNlZSBSLnRyYW5zZHVjZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB4cyA9IFt7YTogMSwgYjogMH0sIHthOjEsIGI6IDF9XTtcbiAgICAgKiAgICAgIFIuZmluZExhc3RJbmRleChSLnByb3BFcSgnYScsIDEpKSh4cyk7IC8vPT4gMVxuICAgICAqICAgICAgUi5maW5kTGFzdEluZGV4KFIucHJvcEVxKCdhJywgNCkpKHhzKTsgLy89PiAtMVxuICAgICAqL1xuICAgIHZhciBmaW5kTGFzdEluZGV4ID0gX2N1cnJ5MihfZGlzcGF0Y2hhYmxlKCdmaW5kTGFzdEluZGV4JywgX3hmaW5kTGFzdEluZGV4LCBmdW5jdGlvbiBmaW5kTGFzdEluZGV4KGZuLCBsaXN0KSB7XG4gICAgICAgIHZhciBpZHggPSBsaXN0Lmxlbmd0aCAtIDE7XG4gICAgICAgIHdoaWxlIChpZHggPj0gMCkge1xuICAgICAgICAgICAgaWYgKGZuKGxpc3RbaWR4XSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWR4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4IC09IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH0pKTtcblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGUgb3ZlciBhbiBpbnB1dCBgbGlzdGAsIGNhbGxpbmcgYSBwcm92aWRlZCBmdW5jdGlvbiBgZm5gIGZvciBlYWNoXG4gICAgICogZWxlbWVudCBpbiB0aGUgbGlzdC5cbiAgICAgKlxuICAgICAqIGBmbmAgcmVjZWl2ZXMgb25lIGFyZ3VtZW50OiAqKHZhbHVlKSouXG4gICAgICpcbiAgICAgKiBOb3RlOiBgUi5mb3JFYWNoYCBkb2VzIG5vdCBza2lwIGRlbGV0ZWQgb3IgdW5hc3NpZ25lZCBpbmRpY2VzIChzcGFyc2VcbiAgICAgKiBhcnJheXMpLCB1bmxpa2UgdGhlIG5hdGl2ZSBgQXJyYXkucHJvdG90eXBlLmZvckVhY2hgIG1ldGhvZC4gRm9yIG1vcmVcbiAgICAgKiBkZXRhaWxzIG9uIHRoaXMgYmVoYXZpb3IsIHNlZTpcbiAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9mb3JFYWNoI0Rlc2NyaXB0aW9uXG4gICAgICpcbiAgICAgKiBBbHNvIG5vdGUgdGhhdCwgdW5saWtlIGBBcnJheS5wcm90b3R5cGUuZm9yRWFjaGAsIFJhbWRhJ3MgYGZvckVhY2hgIHJldHVybnNcbiAgICAgKiB0aGUgb3JpZ2luYWwgYXJyYXkuIEluIHNvbWUgbGlicmFyaWVzIHRoaXMgZnVuY3Rpb24gaXMgbmFtZWQgYGVhY2hgLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGZvckVhY2hgIG1ldGhvZCBvZiB0aGUgc2Vjb25kIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjFcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEgLT4gKikgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuIFJlY2VpdmVzIG9uZSBhcmd1bWVudCwgYHZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBsaXN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIG9yaWdpbmFsIGxpc3QuXG4gICAgICogQHNlZSBSLmFkZEluZGV4XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHByaW50WFBsdXNGaXZlID0geCA9PiBjb25zb2xlLmxvZyh4ICsgNSk7XG4gICAgICogICAgICBSLmZvckVhY2gocHJpbnRYUGx1c0ZpdmUsIFsxLCAyLCAzXSk7IC8vPT4gWzEsIDIsIDNdXG4gICAgICogICAgICAvLyBsb2dzIDZcbiAgICAgKiAgICAgIC8vIGxvZ3MgN1xuICAgICAqICAgICAgLy8gbG9ncyA4XG4gICAgICovXG4gICAgdmFyIGZvckVhY2ggPSBfY3VycnkyKF9jaGVja0Zvck1ldGhvZCgnZm9yRWFjaCcsIGZ1bmN0aW9uIGZvckVhY2goZm4sIGxpc3QpIHtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbikge1xuICAgICAgICAgICAgZm4obGlzdFtpZHhdKTtcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsaXN0O1xuICAgIH0pKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgb2JqZWN0IGZyb20gYSBsaXN0IGtleS12YWx1ZSBwYWlycy4gSWYgYSBrZXkgYXBwZWFycyBpblxuICAgICAqIG11bHRpcGxlIHBhaXJzLCB0aGUgcmlnaHRtb3N0IHBhaXIgaXMgaW5jbHVkZWQgaW4gdGhlIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMy4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIFtbayx2XV0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFpcnMgQW4gYXJyYXkgb2YgdHdvLWVsZW1lbnQgYXJyYXlzIHRoYXQgd2lsbCBiZSB0aGUga2V5cyBhbmQgdmFsdWVzIG9mIHRoZSBvdXRwdXQgb2JqZWN0LlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIG9iamVjdCBtYWRlIGJ5IHBhaXJpbmcgdXAgYGtleXNgIGFuZCBgdmFsdWVzYC5cbiAgICAgKiBAc2VlIFIudG9QYWlycywgUi5wYWlyXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5mcm9tUGFpcnMoW1snYScsIDFdLCBbJ2InLCAyXSwgWydjJywgM11dKTsgLy89PiB7YTogMSwgYjogMiwgYzogM31cbiAgICAgKi9cbiAgICB2YXIgZnJvbVBhaXJzID0gX2N1cnJ5MShmdW5jdGlvbiBmcm9tUGFpcnMocGFpcnMpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IHBhaXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVzdWx0W3BhaXJzW2lkeF1bMF1dID0gcGFpcnNbaWR4XVsxXTtcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3QgYW5kIHJldHVybnMgYSBsaXN0IG9mIGxpc3RzIHdoZXJlIGVhY2ggc3VibGlzdCdzIGVsZW1lbnRzIGFyZVxuICAgICAqIGFsbCBcImVxdWFsXCIgYWNjb3JkaW5nIHRvIHRoZSBwcm92aWRlZCBlcXVhbGl0eSBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoKGEsIGEpIOKGkiBCb29sZWFuKSDihpIgW2FdIOKGkiBbW2FdXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIGZvciBkZXRlcm1pbmluZyB3aGV0aGVyIHR3byBnaXZlbiAoYWRqYWNlbnQpXG4gICAgICogICAgICAgIGVsZW1lbnRzIHNob3VsZCBiZSBpbiB0aGUgc2FtZSBncm91cFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGFycmF5IHRvIGdyb3VwLiBBbHNvIGFjY2VwdHMgYSBzdHJpbmcsIHdoaWNoIHdpbGwgYmVcbiAgICAgKiAgICAgICAgdHJlYXRlZCBhcyBhIGxpc3Qgb2YgY2hhcmFjdGVycy5cbiAgICAgKiBAcmV0dXJuIHtMaXN0fSBBIGxpc3QgdGhhdCBjb250YWlucyBzdWJsaXN0cyBvZiBlcXVhbCBlbGVtZW50cyxcbiAgICAgKiAgICAgICAgIHdob3NlIGNvbmNhdGVuYXRpb25zIGFyZSBlcXVhbCB0byB0aGUgb3JpZ2luYWwgbGlzdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogUi5ncm91cFdpdGgoUi5lcXVhbHMsIFswLCAxLCAxLCAyLCAzLCA1LCA4LCAxMywgMjFdKVxuICAgICAqIC8vPT4gW1swXSwgWzEsIDFdLCBbMl0sIFszXSwgWzVdLCBbOF0sIFsxM10sIFsyMV1dXG4gICAgICpcbiAgICAgKiBSLmdyb3VwV2l0aCgoYSwgYikgPT4gYSAlIDIgPT09IGIgJSAyLCBbMCwgMSwgMSwgMiwgMywgNSwgOCwgMTMsIDIxXSlcbiAgICAgKiAvLz0+IFtbMF0sIFsxLCAxXSwgWzJdLCBbMywgNV0sIFs4XSwgWzEzLCAyMV1dXG4gICAgICpcbiAgICAgKiBSLmdyb3VwV2l0aChSLmVxQnkoaXNWb3dlbCksICdhZXN0aW91JylcbiAgICAgKiAvLz0+IFsnYWUnLCAnc3QnLCAnaW91J11cbiAgICAgKi9cbiAgICB2YXIgZ3JvdXBXaXRoID0gX2N1cnJ5MihmdW5jdGlvbiAoZm4sIGxpc3QpIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICB2YXIgbmV4dGlkeCA9IGlkeCArIDE7XG4gICAgICAgICAgICB3aGlsZSAobmV4dGlkeCA8IGxlbiAmJiBmbihsaXN0W2lkeF0sIGxpc3RbbmV4dGlkeF0pKSB7XG4gICAgICAgICAgICAgICAgbmV4dGlkeCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzLnB1c2gobGlzdC5zbGljZShpZHgsIG5leHRpZHgpKTtcbiAgICAgICAgICAgIGlkeCA9IG5leHRpZHg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHRydWVgIGlmIHRoZSBmaXJzdCBhcmd1bWVudCBpcyBncmVhdGVyIHRoYW4gdGhlIHNlY29uZDsgYGZhbHNlYFxuICAgICAqIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBPcmQgYSA9PiBhIC0+IGEgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7Kn0gYVxuICAgICAqIEBwYXJhbSB7Kn0gYlxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQHNlZSBSLmx0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5ndCgyLCAxKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmd0KDIsIDIpOyAvLz0+IGZhbHNlXG4gICAgICogICAgICBSLmd0KDIsIDMpOyAvLz0+IGZhbHNlXG4gICAgICogICAgICBSLmd0KCdhJywgJ3onKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5ndCgneicsICdhJyk7IC8vPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBndCA9IF9jdXJyeTIoZnVuY3Rpb24gZ3QoYSwgYikge1xuICAgICAgICByZXR1cm4gYSA+IGI7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZmlyc3QgYXJndW1lbnQgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBzZWNvbmQ7XG4gICAgICogYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgT3JkIGEgPT4gYSAtPiBhIC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBiXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAc2VlIFIubHRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5ndGUoMiwgMSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5ndGUoMiwgMik7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5ndGUoMiwgMyk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuZ3RlKCdhJywgJ3onKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5ndGUoJ3onLCAnYScpOyAvLz0+IHRydWVcbiAgICAgKi9cbiAgICB2YXIgZ3RlID0gX2N1cnJ5MihmdW5jdGlvbiBndGUoYSwgYikge1xuICAgICAgICByZXR1cm4gYSA+PSBiO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCBhbiBvYmplY3QgaGFzIGFuIG93biBwcm9wZXJ0eSB3aXRoIHRoZSBzcGVjaWZpZWQgbmFtZVxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyBzIC0+IHtzOiB4fSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHByb3AgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIGNoZWNrIGZvci5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn0gV2hldGhlciB0aGUgcHJvcGVydHkgZXhpc3RzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBoYXNOYW1lID0gUi5oYXMoJ25hbWUnKTtcbiAgICAgKiAgICAgIGhhc05hbWUoe25hbWU6ICdhbGljZSd9KTsgICAvLz0+IHRydWVcbiAgICAgKiAgICAgIGhhc05hbWUoe25hbWU6ICdib2InfSk7ICAgICAvLz0+IHRydWVcbiAgICAgKiAgICAgIGhhc05hbWUoe30pOyAgICAgICAgICAgICAgICAvLz0+IGZhbHNlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBwb2ludCA9IHt4OiAwLCB5OiAwfTtcbiAgICAgKiAgICAgIHZhciBwb2ludEhhcyA9IFIuaGFzKFIuX18sIHBvaW50KTtcbiAgICAgKiAgICAgIHBvaW50SGFzKCd4Jyk7ICAvLz0+IHRydWVcbiAgICAgKiAgICAgIHBvaW50SGFzKCd5Jyk7ICAvLz0+IHRydWVcbiAgICAgKiAgICAgIHBvaW50SGFzKCd6Jyk7ICAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGhhcyA9IF9jdXJyeTIoX2hhcyk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IGFuIG9iamVjdCBvciBpdHMgcHJvdG90eXBlIGNoYWluIGhhcyBhIHByb3BlcnR5IHdpdGhcbiAgICAgKiB0aGUgc3BlY2lmaWVkIG5hbWVcbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuNy4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgcyAtPiB7czogeH0gLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBjaGVjayBmb3IuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59IFdoZXRoZXIgdGhlIHByb3BlcnR5IGV4aXN0cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBmdW5jdGlvbiBSZWN0YW5nbGUod2lkdGgsIGhlaWdodCkge1xuICAgICAqICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICogICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAqICAgICAgfVxuICAgICAqICAgICAgUmVjdGFuZ2xlLnByb3RvdHlwZS5hcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgICogICAgICAgIHJldHVybiB0aGlzLndpZHRoICogdGhpcy5oZWlnaHQ7XG4gICAgICogICAgICB9O1xuICAgICAqXG4gICAgICogICAgICB2YXIgc3F1YXJlID0gbmV3IFJlY3RhbmdsZSgyLCAyKTtcbiAgICAgKiAgICAgIFIuaGFzSW4oJ3dpZHRoJywgc3F1YXJlKTsgIC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5oYXNJbignYXJlYScsIHNxdWFyZSk7ICAvLz0+IHRydWVcbiAgICAgKi9cbiAgICB2YXIgaGFzSW4gPSBfY3VycnkyKGZ1bmN0aW9uIGhhc0luKHByb3AsIG9iaikge1xuICAgICAgICByZXR1cm4gcHJvcCBpbiBvYmo7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgaXRzIGFyZ3VtZW50cyBhcmUgaWRlbnRpY2FsLCBmYWxzZSBvdGhlcndpc2UuIFZhbHVlcyBhcmVcbiAgICAgKiBpZGVudGljYWwgaWYgdGhleSByZWZlcmVuY2UgdGhlIHNhbWUgbWVtb3J5LiBgTmFOYCBpcyBpZGVudGljYWwgdG8gYE5hTmA7XG4gICAgICogYDBgIGFuZCBgLTBgIGFyZSBub3QgaWRlbnRpY2FsLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBhIC0+IGEgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7Kn0gYVxuICAgICAqIEBwYXJhbSB7Kn0gYlxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG8gPSB7fTtcbiAgICAgKiAgICAgIFIuaWRlbnRpY2FsKG8sIG8pOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIuaWRlbnRpY2FsKDEsIDEpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIuaWRlbnRpY2FsKDEsICcxJyk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuaWRlbnRpY2FsKFtdLCBbXSk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuaWRlbnRpY2FsKDAsIC0wKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5pZGVudGljYWwoTmFOLCBOYU4pOyAvLz0+IHRydWVcbiAgICAgKi9cbiAgICAvLyBTYW1lVmFsdWUgYWxnb3JpdGhtXG4gICAgLy8gU3RlcHMgMS01LCA3LTEwXG4gICAgLy8gU3RlcHMgNi5iLTYuZTogKzAgIT0gLTBcbiAgICAvLyBTdGVwIDYuYTogTmFOID09IE5hTlxuICAgIHZhciBpZGVudGljYWwgPSBfY3VycnkyKGZ1bmN0aW9uIGlkZW50aWNhbChhLCBiKSB7XG4gICAgICAgIC8vIFNhbWVWYWx1ZSBhbGdvcml0aG1cbiAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgIC8vIFN0ZXBzIDEtNSwgNy0xMFxuICAgICAgICAgICAgLy8gU3RlcHMgNi5iLTYuZTogKzAgIT0gLTBcbiAgICAgICAgICAgIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09PSAxIC8gYjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFN0ZXAgNi5hOiBOYU4gPT0gTmFOXG4gICAgICAgICAgICByZXR1cm4gYSAhPT0gYSAmJiBiICE9PSBiO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgZG9lcyBub3RoaW5nIGJ1dCByZXR1cm4gdGhlIHBhcmFtZXRlciBzdXBwbGllZCB0byBpdC4gR29vZFxuICAgICAqIGFzIGEgZGVmYXVsdCBvciBwbGFjZWhvbGRlciBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyBhIC0+IGFcbiAgICAgKiBAcGFyYW0geyp9IHggVGhlIHZhbHVlIHRvIHJldHVybi5cbiAgICAgKiBAcmV0dXJuIHsqfSBUaGUgaW5wdXQgdmFsdWUsIGB4YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmlkZW50aXR5KDEpOyAvLz0+IDFcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG9iaiA9IHt9O1xuICAgICAqICAgICAgUi5pZGVudGl0eShvYmopID09PSBvYmo7IC8vPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBpZGVudGl0eSA9IF9jdXJyeTEoX2lkZW50aXR5KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgcHJvY2VzcyBlaXRoZXIgdGhlIGBvblRydWVgIG9yIHRoZSBgb25GYWxzZWBcbiAgICAgKiBmdW5jdGlvbiBkZXBlbmRpbmcgdXBvbiB0aGUgcmVzdWx0IG9mIHRoZSBgY29uZGl0aW9uYCBwcmVkaWNhdGUuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjguMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgKCouLi4gLT4gQm9vbGVhbikgLT4gKCouLi4gLT4gKikgLT4gKCouLi4gLT4gKikgLT4gKCouLi4gLT4gKilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb25kaXRpb24gQSBwcmVkaWNhdGUgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvblRydWUgQSBmdW5jdGlvbiB0byBpbnZva2Ugd2hlbiB0aGUgYGNvbmRpdGlvbmAgZXZhbHVhdGVzIHRvIGEgdHJ1dGh5IHZhbHVlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9uRmFsc2UgQSBmdW5jdGlvbiB0byBpbnZva2Ugd2hlbiB0aGUgYGNvbmRpdGlvbmAgZXZhbHVhdGVzIHRvIGEgZmFsc3kgdmFsdWUuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IEEgbmV3IHVuYXJ5IGZ1bmN0aW9uIHRoYXQgd2lsbCBwcm9jZXNzIGVpdGhlciB0aGUgYG9uVHJ1ZWAgb3IgdGhlIGBvbkZhbHNlYFxuICAgICAqICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBkZXBlbmRpbmcgdXBvbiB0aGUgcmVzdWx0IG9mIHRoZSBgY29uZGl0aW9uYCBwcmVkaWNhdGUuXG4gICAgICogQHNlZSBSLnVubGVzcywgUi53aGVuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGluY0NvdW50ID0gUi5pZkVsc2UoXG4gICAgICogICAgICAgIFIuaGFzKCdjb3VudCcpLFxuICAgICAqICAgICAgICBSLm92ZXIoUi5sZW5zUHJvcCgnY291bnQnKSwgUi5pbmMpLFxuICAgICAqICAgICAgICBSLmFzc29jKCdjb3VudCcsIDEpXG4gICAgICogICAgICApO1xuICAgICAqICAgICAgaW5jQ291bnQoe30pOyAgICAgICAgICAgLy89PiB7IGNvdW50OiAxIH1cbiAgICAgKiAgICAgIGluY0NvdW50KHsgY291bnQ6IDEgfSk7IC8vPT4geyBjb3VudDogMiB9XG4gICAgICovXG4gICAgdmFyIGlmRWxzZSA9IF9jdXJyeTMoZnVuY3Rpb24gaWZFbHNlKGNvbmRpdGlvbiwgb25UcnVlLCBvbkZhbHNlKSB7XG4gICAgICAgIHJldHVybiBjdXJyeU4oTWF0aC5tYXgoY29uZGl0aW9uLmxlbmd0aCwgb25UcnVlLmxlbmd0aCwgb25GYWxzZS5sZW5ndGgpLCBmdW5jdGlvbiBfaWZFbHNlKCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbmRpdGlvbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpID8gb25UcnVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBvbkZhbHNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSW5jcmVtZW50cyBpdHMgYXJndW1lbnQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjkuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHNpZyBOdW1iZXIgLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAgICogQHNlZSBSLmRlY1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuaW5jKDQyKTsgLy89PiA0M1xuICAgICAqL1xuICAgIHZhciBpbmMgPSBhZGQoMSk7XG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnRzIHRoZSBzdXBwbGllZCBlbGVtZW50IGludG8gdGhlIGxpc3QsIGF0IGluZGV4IGBpbmRleGAuIF9Ob3RlIHRoYXRcbiAgICAgKiB0aGlzIGlzIG5vdCBkZXN0cnVjdGl2ZV86IGl0IHJldHVybnMgYSBjb3B5IG9mIHRoZSBsaXN0IHdpdGggdGhlIGNoYW5nZXMuXG4gICAgICogPHNtYWxsPk5vIGxpc3RzIGhhdmUgYmVlbiBoYXJtZWQgaW4gdGhlIGFwcGxpY2F0aW9uIG9mIHRoaXMgZnVuY3Rpb24uPC9zbWFsbD5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMi4yXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIE51bWJlciAtPiBhIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXggVGhlIHBvc2l0aW9uIHRvIGluc2VydCB0aGUgZWxlbWVudFxuICAgICAqIEBwYXJhbSB7Kn0gZWx0IFRoZSBlbGVtZW50IHRvIGluc2VydCBpbnRvIHRoZSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gaW5zZXJ0IGludG9cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcgQXJyYXkgd2l0aCBgZWx0YCBpbnNlcnRlZCBhdCBgaW5kZXhgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuaW5zZXJ0KDIsICd4JywgWzEsMiwzLDRdKTsgLy89PiBbMSwyLCd4JywzLDRdXG4gICAgICovXG4gICAgdmFyIGluc2VydCA9IF9jdXJyeTMoZnVuY3Rpb24gaW5zZXJ0KGlkeCwgZWx0LCBsaXN0KSB7XG4gICAgICAgIGlkeCA9IGlkeCA8IGxpc3QubGVuZ3RoICYmIGlkeCA+PSAwID8gaWR4IDogbGlzdC5sZW5ndGg7XG4gICAgICAgIHZhciByZXN1bHQgPSBfc2xpY2UobGlzdCk7XG4gICAgICAgIHJlc3VsdC5zcGxpY2UoaWR4LCAwLCBlbHQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSW5zZXJ0cyB0aGUgc3ViLWxpc3QgaW50byB0aGUgbGlzdCwgYXQgaW5kZXggYGluZGV4YC4gX05vdGUgdGhhdCB0aGlzIGlzIG5vdFxuICAgICAqIGRlc3RydWN0aXZlXzogaXQgcmV0dXJucyBhIGNvcHkgb2YgdGhlIGxpc3Qgd2l0aCB0aGUgY2hhbmdlcy5cbiAgICAgKiA8c21hbGw+Tm8gbGlzdHMgaGF2ZSBiZWVuIGhhcm1lZCBpbiB0aGUgYXBwbGljYXRpb24gb2YgdGhpcyBmdW5jdGlvbi48L3NtYWxsPlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC45LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IFthXSAtPiBbYV0gLT4gW2FdXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4IFRoZSBwb3NpdGlvbiB0byBpbnNlcnQgdGhlIHN1Yi1saXN0XG4gICAgICogQHBhcmFtIHtBcnJheX0gZWx0cyBUaGUgc3ViLWxpc3QgdG8gaW5zZXJ0IGludG8gdGhlIEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byBpbnNlcnQgdGhlIHN1Yi1saXN0IGludG9cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcgQXJyYXkgd2l0aCBgZWx0c2AgaW5zZXJ0ZWQgc3RhcnRpbmcgYXQgYGluZGV4YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmluc2VydEFsbCgyLCBbJ3gnLCd5JywneiddLCBbMSwyLDMsNF0pOyAvLz0+IFsxLDIsJ3gnLCd5JywneicsMyw0XVxuICAgICAqL1xuICAgIHZhciBpbnNlcnRBbGwgPSBfY3VycnkzKGZ1bmN0aW9uIGluc2VydEFsbChpZHgsIGVsdHMsIGxpc3QpIHtcbiAgICAgICAgaWR4ID0gaWR4IDwgbGlzdC5sZW5ndGggJiYgaWR4ID49IDAgPyBpZHggOiBsaXN0Lmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIF9jb25jYXQoX2NvbmNhdChfc2xpY2UobGlzdCwgMCwgaWR4KSwgZWx0cyksIF9zbGljZShsaXN0LCBpZHgpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgbGlzdCB3aXRoIHRoZSBzZXBhcmF0b3IgaW50ZXJwb3NlZCBiZXR3ZWVuIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGludGVyc3BlcnNlYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBhIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0geyp9IHNlcGFyYXRvciBUaGUgZWxlbWVudCB0byBhZGQgdG8gdGhlIGxpc3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byBiZSBpbnRlcnBvc2VkLlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBUaGUgbmV3IGxpc3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5pbnRlcnNwZXJzZSgnbicsIFsnYmEnLCAnYScsICdhJ10pOyAvLz0+IFsnYmEnLCAnbicsICdhJywgJ24nLCAnYSddXG4gICAgICovXG4gICAgdmFyIGludGVyc3BlcnNlID0gX2N1cnJ5MihfY2hlY2tGb3JNZXRob2QoJ2ludGVyc3BlcnNlJywgZnVuY3Rpb24gaW50ZXJzcGVyc2Uoc2VwYXJhdG9yLCBsaXN0KSB7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHZhciBsZW5ndGggPSBsaXN0Lmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gbGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKGxpc3RbaWR4XSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKGxpc3RbaWR4XSwgc2VwYXJhdG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogU2VlIGlmIGFuIG9iamVjdCAoYHZhbGApIGlzIGFuIGluc3RhbmNlIG9mIHRoZSBzdXBwbGllZCBjb25zdHJ1Y3Rvci4gVGhpc1xuICAgICAqIGZ1bmN0aW9uIHdpbGwgY2hlY2sgdXAgdGhlIGluaGVyaXRhbmNlIGNoYWluLCBpZiBhbnkuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjMuMFxuICAgICAqIEBjYXRlZ29yeSBUeXBlXG4gICAgICogQHNpZyAoKiAtPiB7Kn0pIC0+IGEgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjdG9yIEEgY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0geyp9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5pcyhPYmplY3QsIHt9KTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmlzKE51bWJlciwgMSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5pcyhPYmplY3QsIDEpOyAvLz0+IGZhbHNlXG4gICAgICogICAgICBSLmlzKFN0cmluZywgJ3MnKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmlzKFN0cmluZywgbmV3IFN0cmluZygnJykpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIuaXMoT2JqZWN0LCBuZXcgU3RyaW5nKCcnKSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5pcyhPYmplY3QsICdzJyk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuaXMoTnVtYmVyLCB7fSk7IC8vPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXMgPSBfY3VycnkyKGZ1bmN0aW9uIGlzKEN0b3IsIHZhbCkge1xuICAgICAgICByZXR1cm4gdmFsICE9IG51bGwgJiYgdmFsLmNvbnN0cnVjdG9yID09PSBDdG9yIHx8IHZhbCBpbnN0YW5jZW9mIEN0b3I7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUZXN0cyB3aGV0aGVyIG9yIG5vdCBhbiBvYmplY3QgaXMgc2ltaWxhciB0byBhbiBhcnJheS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuNS4wXG4gICAgICogQGNhdGVnb3J5IFR5cGVcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKiAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHsqfSB4IFRoZSBvYmplY3QgdG8gdGVzdC5cbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgYHhgIGhhcyBhIG51bWVyaWMgbGVuZ3RoIHByb3BlcnR5IGFuZCBleHRyZW1lIGluZGljZXMgZGVmaW5lZDsgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5pc0FycmF5TGlrZShbXSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5pc0FycmF5TGlrZSh0cnVlKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5pc0FycmF5TGlrZSh7fSk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuaXNBcnJheUxpa2Uoe2xlbmd0aDogMTB9KTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5pc0FycmF5TGlrZSh7MDogJ3plcm8nLCA5OiAnbmluZScsIGxlbmd0aDogMTB9KTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIGlzQXJyYXlMaWtlID0gX2N1cnJ5MShmdW5jdGlvbiBpc0FycmF5TGlrZSh4KSB7XG4gICAgICAgIGlmIChfaXNBcnJheSh4KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF4KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB4ICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChfaXNTdHJpbmcoeCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeC5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuICEheC5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHgubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4geC5oYXNPd25Qcm9wZXJ0eSgwKSAmJiB4Lmhhc093blByb3BlcnR5KHgubGVuZ3RoIC0gMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSBpbnB1dCB2YWx1ZSBpcyBgbnVsbGAgb3IgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjkuMFxuICAgICAqIEBjYXRlZ29yeSBUeXBlXG4gICAgICogQHNpZyAqIC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0geyp9IHggVGhlIHZhbHVlIHRvIHRlc3QuXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn0gYHRydWVgIGlmIGB4YCBpcyBgdW5kZWZpbmVkYCBvciBgbnVsbGAsIG90aGVyd2lzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuaXNOaWwobnVsbCk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5pc05pbCh1bmRlZmluZWQpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIuaXNOaWwoMCk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuaXNOaWwoW10pOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzTmlsID0gX2N1cnJ5MShmdW5jdGlvbiBpc05pbCh4KSB7XG4gICAgICAgIHJldHVybiB4ID09IG51bGw7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbGlzdCBjb250YWluaW5nIHRoZSBuYW1lcyBvZiBhbGwgdGhlIGVudW1lcmFibGUgb3duIHByb3BlcnRpZXMgb2ZcbiAgICAgKiB0aGUgc3VwcGxpZWQgb2JqZWN0LlxuICAgICAqIE5vdGUgdGhhdCB0aGUgb3JkZXIgb2YgdGhlIG91dHB1dCBhcnJheSBpcyBub3QgZ3VhcmFudGVlZCB0byBiZSBjb25zaXN0ZW50XG4gICAgICogYWNyb3NzIGRpZmZlcmVudCBKUyBwbGF0Zm9ybXMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIHtrOiB2fSAtPiBba11cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gZXh0cmFjdCBwcm9wZXJ0aWVzIGZyb21cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgdGhlIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIua2V5cyh7YTogMSwgYjogMiwgYzogM30pOyAvLz0+IFsnYScsICdiJywgJ2MnXVxuICAgICAqL1xuICAgIC8vIGNvdmVyIElFIDwgOSBrZXlzIGlzc3Vlc1xuICAgIC8vIFNhZmFyaSBidWdcbiAgICB2YXIga2V5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gY292ZXIgSUUgPCA5IGtleXMgaXNzdWVzXG4gICAgICAgIHZhciBoYXNFbnVtQnVnID0gIXsgdG9TdHJpbmc6IG51bGwgfS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgndG9TdHJpbmcnKTtcbiAgICAgICAgdmFyIG5vbkVudW1lcmFibGVQcm9wcyA9IFtcbiAgICAgICAgICAgICdjb25zdHJ1Y3RvcicsXG4gICAgICAgICAgICAndmFsdWVPZicsXG4gICAgICAgICAgICAnaXNQcm90b3R5cGVPZicsXG4gICAgICAgICAgICAndG9TdHJpbmcnLFxuICAgICAgICAgICAgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJyxcbiAgICAgICAgICAgICdoYXNPd25Qcm9wZXJ0eScsXG4gICAgICAgICAgICAndG9Mb2NhbGVTdHJpbmcnXG4gICAgICAgIF07XG4gICAgICAgIC8vIFNhZmFyaSBidWdcbiAgICAgICAgdmFyIGhhc0FyZ3NFbnVtQnVnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50cy5wcm9wZXJ0eUlzRW51bWVyYWJsZSgnbGVuZ3RoJyk7XG4gICAgICAgIH0oKTtcbiAgICAgICAgdmFyIGNvbnRhaW5zID0gZnVuY3Rpb24gY29udGFpbnMobGlzdCwgaXRlbSkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoaWR4IDwgbGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpZiAobGlzdFtpZHhdID09PSBpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBPYmplY3Qua2V5cyA9PT0gJ2Z1bmN0aW9uJyAmJiAhaGFzQXJnc0VudW1CdWcgPyBfY3VycnkxKGZ1bmN0aW9uIGtleXMob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0KG9iaikgIT09IG9iaiA/IFtdIDogT2JqZWN0LmtleXMob2JqKTtcbiAgICAgICAgfSkgOiBfY3VycnkxKGZ1bmN0aW9uIGtleXMob2JqKSB7XG4gICAgICAgICAgICBpZiAoT2JqZWN0KG9iaikgIT09IG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwcm9wLCBuSWR4O1xuICAgICAgICAgICAgdmFyIGtzID0gW107XG4gICAgICAgICAgICB2YXIgY2hlY2tBcmdzTGVuZ3RoID0gaGFzQXJnc0VudW1CdWcgJiYgX2lzQXJndW1lbnRzKG9iaik7XG4gICAgICAgICAgICBmb3IgKHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9oYXMocHJvcCwgb2JqKSAmJiAoIWNoZWNrQXJnc0xlbmd0aCB8fCBwcm9wICE9PSAnbGVuZ3RoJykpIHtcbiAgICAgICAgICAgICAgICAgICAga3Nba3MubGVuZ3RoXSA9IHByb3A7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGhhc0VudW1CdWcpIHtcbiAgICAgICAgICAgICAgICBuSWR4ID0gbm9uRW51bWVyYWJsZVByb3BzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG5JZHggPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wID0gbm9uRW51bWVyYWJsZVByb3BzW25JZHhdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoX2hhcyhwcm9wLCBvYmopICYmICFjb250YWlucyhrcywgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtzW2tzLmxlbmd0aF0gPSBwcm9wO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG5JZHggLT0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ga3M7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBsaXN0IGNvbnRhaW5pbmcgdGhlIG5hbWVzIG9mIGFsbCB0aGUgcHJvcGVydGllcyBvZiB0aGUgc3VwcGxpZWRcbiAgICAgKiBvYmplY3QsIGluY2x1ZGluZyBwcm90b3R5cGUgcHJvcGVydGllcy5cbiAgICAgKiBOb3RlIHRoYXQgdGhlIG9yZGVyIG9mIHRoZSBvdXRwdXQgYXJyYXkgaXMgbm90IGd1YXJhbnRlZWQgdG8gYmUgY29uc2lzdGVudFxuICAgICAqIGFjcm9zcyBkaWZmZXJlbnQgSlMgcGxhdGZvcm1zLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyB7azogdn0gLT4gW2tdXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGV4dHJhY3QgcHJvcGVydGllcyBmcm9tXG4gICAgICogQHJldHVybiB7QXJyYXl9IEFuIGFycmF5IG9mIHRoZSBvYmplY3QncyBvd24gYW5kIHByb3RvdHlwZSBwcm9wZXJ0aWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBGID0gZnVuY3Rpb24oKSB7IHRoaXMueCA9ICdYJzsgfTtcbiAgICAgKiAgICAgIEYucHJvdG90eXBlLnkgPSAnWSc7XG4gICAgICogICAgICB2YXIgZiA9IG5ldyBGKCk7XG4gICAgICogICAgICBSLmtleXNJbihmKTsgLy89PiBbJ3gnLCAneSddXG4gICAgICovXG4gICAgdmFyIGtleXNJbiA9IF9jdXJyeTEoZnVuY3Rpb24ga2V5c0luKG9iaikge1xuICAgICAgICB2YXIgcHJvcDtcbiAgICAgICAgdmFyIGtzID0gW107XG4gICAgICAgIGZvciAocHJvcCBpbiBvYmopIHtcbiAgICAgICAgICAgIGtzW2tzLmxlbmd0aF0gPSBwcm9wO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBrcztcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgYXJyYXkgYnkgcmV0dXJuaW5nIGBsaXN0Lmxlbmd0aGAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjMuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBbYV0gLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IFRoZSBsZW5ndGggb2YgdGhlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIubGVuZ3RoKFtdKTsgLy89PiAwXG4gICAgICogICAgICBSLmxlbmd0aChbMSwgMiwgM10pOyAvLz0+IDNcbiAgICAgKi9cbiAgICB2YXIgbGVuZ3RoID0gX2N1cnJ5MShmdW5jdGlvbiBsZW5ndGgobGlzdCkge1xuICAgICAgICByZXR1cm4gbGlzdCAhPSBudWxsICYmIF9pc051bWJlcihsaXN0Lmxlbmd0aCkgPyBsaXN0Lmxlbmd0aCA6IE5hTjtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHRydWVgIGlmIHRoZSBmaXJzdCBhcmd1bWVudCBpcyBsZXNzIHRoYW4gdGhlIHNlY29uZDsgYGZhbHNlYFxuICAgICAqIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBPcmQgYSA9PiBhIC0+IGEgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7Kn0gYVxuICAgICAqIEBwYXJhbSB7Kn0gYlxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQHNlZSBSLmd0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5sdCgyLCAxKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5sdCgyLCAyKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5sdCgyLCAzKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmx0KCdhJywgJ3onKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmx0KCd6JywgJ2EnKTsgLy89PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBsdCA9IF9jdXJyeTIoZnVuY3Rpb24gbHQoYSwgYikge1xuICAgICAgICByZXR1cm4gYSA8IGI7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZmlyc3QgYXJndW1lbnQgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBzZWNvbmQ7XG4gICAgICogYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgT3JkIGEgPT4gYSAtPiBhIC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBiXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAc2VlIFIuZ3RlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5sdGUoMiwgMSk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIubHRlKDIsIDIpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIubHRlKDIsIDMpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIubHRlKCdhJywgJ3onKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmx0ZSgneicsICdhJyk7IC8vPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgbHRlID0gX2N1cnJ5MihmdW5jdGlvbiBsdGUoYSwgYikge1xuICAgICAgICByZXR1cm4gYSA8PSBiO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG1hcEFjY3VtIGZ1bmN0aW9uIGJlaGF2ZXMgbGlrZSBhIGNvbWJpbmF0aW9uIG9mIG1hcCBhbmQgcmVkdWNlOyBpdFxuICAgICAqIGFwcGxpZXMgYSBmdW5jdGlvbiB0byBlYWNoIGVsZW1lbnQgb2YgYSBsaXN0LCBwYXNzaW5nIGFuIGFjY3VtdWxhdGluZ1xuICAgICAqIHBhcmFtZXRlciBmcm9tIGxlZnQgdG8gcmlnaHQsIGFuZCByZXR1cm5pbmcgYSBmaW5hbCB2YWx1ZSBvZiB0aGlzXG4gICAgICogYWNjdW11bGF0b3IgdG9nZXRoZXIgd2l0aCB0aGUgbmV3IGxpc3QuXG4gICAgICpcbiAgICAgKiBUaGUgaXRlcmF0b3IgZnVuY3Rpb24gcmVjZWl2ZXMgdHdvIGFyZ3VtZW50cywgKmFjYyogYW5kICp2YWx1ZSosIGFuZCBzaG91bGRcbiAgICAgKiByZXR1cm4gYSB0dXBsZSAqW2FjYywgdmFsdWVdKi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoYWNjIC0+IHggLT4gKGFjYywgeSkpIC0+IGFjYyAtPiBbeF0gLT4gKGFjYywgW3ldKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gZXZlcnkgZWxlbWVudCBvZiB0aGUgaW5wdXQgYGxpc3RgLlxuICAgICAqIEBwYXJhbSB7Kn0gYWNjIFRoZSBhY2N1bXVsYXRvciB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBsaXN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJuIHsqfSBUaGUgZmluYWwsIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgICAqIEBzZWUgUi5hZGRJbmRleFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBkaWdpdHMgPSBbJzEnLCAnMicsICczJywgJzQnXTtcbiAgICAgKiAgICAgIHZhciBhcHBlbmRlciA9IChhLCBiKSA9PiBbYSArIGIsIGEgKyBiXTtcbiAgICAgKlxuICAgICAqICAgICAgUi5tYXBBY2N1bShhcHBlbmRlciwgMCwgZGlnaXRzKTsgLy89PiBbJzAxMjM0JywgWycwMScsICcwMTInLCAnMDEyMycsICcwMTIzNCddXVxuICAgICAqL1xuICAgIHZhciBtYXBBY2N1bSA9IF9jdXJyeTMoZnVuY3Rpb24gbWFwQWNjdW0oZm4sIGFjYywgbGlzdCkge1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciB0dXBsZSA9IFthY2NdO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICB0dXBsZSA9IGZuKHR1cGxlWzBdLCBsaXN0W2lkeF0pO1xuICAgICAgICAgICAgcmVzdWx0W2lkeF0gPSB0dXBsZVsxXTtcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0dXBsZVswXSxcbiAgICAgICAgICAgIHJlc3VsdFxuICAgICAgICBdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG1hcEFjY3VtUmlnaHQgZnVuY3Rpb24gYmVoYXZlcyBsaWtlIGEgY29tYmluYXRpb24gb2YgbWFwIGFuZCByZWR1Y2U7IGl0XG4gICAgICogYXBwbGllcyBhIGZ1bmN0aW9uIHRvIGVhY2ggZWxlbWVudCBvZiBhIGxpc3QsIHBhc3NpbmcgYW4gYWNjdW11bGF0aW5nXG4gICAgICogcGFyYW1ldGVyIGZyb20gcmlnaHQgdG8gbGVmdCwgYW5kIHJldHVybmluZyBhIGZpbmFsIHZhbHVlIG9mIHRoaXNcbiAgICAgKiBhY2N1bXVsYXRvciB0b2dldGhlciB3aXRoIHRoZSBuZXcgbGlzdC5cbiAgICAgKlxuICAgICAqIFNpbWlsYXIgdG8gYG1hcEFjY3VtYCwgZXhjZXB0IG1vdmVzIHRocm91Z2ggdGhlIGlucHV0IGxpc3QgZnJvbSB0aGUgcmlnaHQgdG9cbiAgICAgKiB0aGUgbGVmdC5cbiAgICAgKlxuICAgICAqIFRoZSBpdGVyYXRvciBmdW5jdGlvbiByZWNlaXZlcyB0d28gYXJndW1lbnRzLCAqYWNjKiBhbmQgKnZhbHVlKiwgYW5kIHNob3VsZFxuICAgICAqIHJldHVybiBhIHR1cGxlICpbYWNjLCB2YWx1ZV0qLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMC4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhY2MgLT4geCAtPiAoYWNjLCB5KSkgLT4gYWNjIC0+IFt4XSAtPiAoYWNjLCBbeV0pXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBvbiBldmVyeSBlbGVtZW50IG9mIHRoZSBpbnB1dCBgbGlzdGAuXG4gICAgICogQHBhcmFtIHsqfSBhY2MgVGhlIGFjY3VtdWxhdG9yIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBmaW5hbCwgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQHNlZSBSLmFkZEluZGV4XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGRpZ2l0cyA9IFsnMScsICcyJywgJzMnLCAnNCddO1xuICAgICAqICAgICAgdmFyIGFwcGVuZCA9IChhLCBiKSA9PiBbYSArIGIsIGEgKyBiXTtcbiAgICAgKlxuICAgICAqICAgICAgUi5tYXBBY2N1bVJpZ2h0KGFwcGVuZCwgMCwgZGlnaXRzKTsgLy89PiBbJzA0MzIxJywgWycwNDMyMScsICcwNDMyJywgJzA0MycsICcwNCddXVxuICAgICAqL1xuICAgIHZhciBtYXBBY2N1bVJpZ2h0ID0gX2N1cnJ5MyhmdW5jdGlvbiBtYXBBY2N1bVJpZ2h0KGZuLCBhY2MsIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IGxpc3QubGVuZ3RoIC0gMTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIgdHVwbGUgPSBbYWNjXTtcbiAgICAgICAgd2hpbGUgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICB0dXBsZSA9IGZuKHR1cGxlWzBdLCBsaXN0W2lkeF0pO1xuICAgICAgICAgICAgcmVzdWx0W2lkeF0gPSB0dXBsZVsxXTtcbiAgICAgICAgICAgIGlkeCAtPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0dXBsZVswXSxcbiAgICAgICAgICAgIHJlc3VsdFxuICAgICAgICBdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGVzdHMgYSByZWd1bGFyIGV4cHJlc3Npb24gYWdhaW5zdCBhIFN0cmluZy4gTm90ZSB0aGF0IHRoaXMgZnVuY3Rpb24gd2lsbFxuICAgICAqIHJldHVybiBhbiBlbXB0eSBhcnJheSB3aGVuIHRoZXJlIGFyZSBubyBtYXRjaGVzLiBUaGlzIGRpZmZlcnMgZnJvbVxuICAgICAqIFtgU3RyaW5nLnByb3RvdHlwZS5tYXRjaGBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9tYXRjaClcbiAgICAgKiB3aGljaCByZXR1cm5zIGBudWxsYCB3aGVuIHRoZXJlIGFyZSBubyBtYXRjaGVzLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHNpZyBSZWdFeHAgLT4gU3RyaW5nIC0+IFtTdHJpbmcgfCBVbmRlZmluZWRdXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IHJ4IEEgcmVndWxhciBleHByZXNzaW9uLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBtYXRjaCBhZ2FpbnN0XG4gICAgICogQHJldHVybiB7QXJyYXl9IFRoZSBsaXN0IG9mIG1hdGNoZXMgb3IgZW1wdHkgYXJyYXkuXG4gICAgICogQHNlZSBSLnRlc3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLm1hdGNoKC8oW2Etel1hKS9nLCAnYmFuYW5hcycpOyAvLz0+IFsnYmEnLCAnbmEnLCAnbmEnXVxuICAgICAqICAgICAgUi5tYXRjaCgvYS8sICdiJyk7IC8vPT4gW11cbiAgICAgKiAgICAgIFIubWF0Y2goL2EvLCBudWxsKTsgLy89PiBUeXBlRXJyb3I6IG51bGwgZG9lcyBub3QgaGF2ZSBhIG1ldGhvZCBuYW1lZCBcIm1hdGNoXCJcbiAgICAgKi9cbiAgICB2YXIgbWF0Y2ggPSBfY3VycnkyKGZ1bmN0aW9uIG1hdGNoKHJ4LCBzdHIpIHtcbiAgICAgICAgcmV0dXJuIHN0ci5tYXRjaChyeCkgfHwgW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBtYXRoTW9kIGJlaGF2ZXMgbGlrZSB0aGUgbW9kdWxvIG9wZXJhdG9yIHNob3VsZCBtYXRoZW1hdGljYWxseSwgdW5saWtlIHRoZVxuICAgICAqIGAlYCBvcGVyYXRvciAoYW5kIGJ5IGV4dGVuc2lvbiwgUi5tb2R1bG8pLiBTbyB3aGlsZSBcIi0xNyAlIDVcIiBpcyAtMixcbiAgICAgKiBtYXRoTW9kKC0xNywgNSkgaXMgMy4gbWF0aE1vZCByZXF1aXJlcyBJbnRlZ2VyIGFyZ3VtZW50cywgYW5kIHJldHVybnMgTmFOXG4gICAgICogd2hlbiB0aGUgbW9kdWx1cyBpcyB6ZXJvIG9yIG5lZ2F0aXZlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IE51bWJlciAtPiBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbSBUaGUgZGl2aWRlbmQuXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHAgdGhlIG1vZHVsdXMuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBUaGUgcmVzdWx0IG9mIGBiIG1vZCBhYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLm1hdGhNb2QoLTE3LCA1KTsgIC8vPT4gM1xuICAgICAqICAgICAgUi5tYXRoTW9kKDE3LCA1KTsgICAvLz0+IDJcbiAgICAgKiAgICAgIFIubWF0aE1vZCgxNywgLTUpOyAgLy89PiBOYU5cbiAgICAgKiAgICAgIFIubWF0aE1vZCgxNywgMCk7ICAgLy89PiBOYU5cbiAgICAgKiAgICAgIFIubWF0aE1vZCgxNy4yLCA1KTsgLy89PiBOYU5cbiAgICAgKiAgICAgIFIubWF0aE1vZCgxNywgNS4zKTsgLy89PiBOYU5cbiAgICAgKlxuICAgICAqICAgICAgdmFyIGNsb2NrID0gUi5tYXRoTW9kKFIuX18sIDEyKTtcbiAgICAgKiAgICAgIGNsb2NrKDE1KTsgLy89PiAzXG4gICAgICogICAgICBjbG9jaygyNCk7IC8vPT4gMFxuICAgICAqXG4gICAgICogICAgICB2YXIgc2V2ZW50ZWVuTW9kID0gUi5tYXRoTW9kKDE3KTtcbiAgICAgKiAgICAgIHNldmVudGVlbk1vZCgzKTsgIC8vPT4gMlxuICAgICAqICAgICAgc2V2ZW50ZWVuTW9kKDQpOyAgLy89PiAxXG4gICAgICogICAgICBzZXZlbnRlZW5Nb2QoMTApOyAvLz0+IDdcbiAgICAgKi9cbiAgICB2YXIgbWF0aE1vZCA9IF9jdXJyeTIoZnVuY3Rpb24gbWF0aE1vZChtLCBwKSB7XG4gICAgICAgIGlmICghX2lzSW50ZWdlcihtKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIV9pc0ludGVnZXIocCkgfHwgcCA8IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChtICUgcCArIHApICUgcDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxhcmdlciBvZiBpdHMgdHdvIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBPcmQgYSA9PiBhIC0+IGEgLT4gYVxuICAgICAqIEBwYXJhbSB7Kn0gYVxuICAgICAqIEBwYXJhbSB7Kn0gYlxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHNlZSBSLm1heEJ5LCBSLm1pblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIubWF4KDc4OSwgMTIzKTsgLy89PiA3ODlcbiAgICAgKiAgICAgIFIubWF4KCdhJywgJ2InKTsgLy89PiAnYidcbiAgICAgKi9cbiAgICB2YXIgbWF4ID0gX2N1cnJ5MihmdW5jdGlvbiBtYXgoYSwgYikge1xuICAgICAgICByZXR1cm4gYiA+IGEgPyBiIDogYTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgZnVuY3Rpb24gYW5kIHR3byB2YWx1ZXMsIGFuZCByZXR1cm5zIHdoaWNoZXZlciB2YWx1ZSBwcm9kdWNlcyB0aGVcbiAgICAgKiBsYXJnZXIgcmVzdWx0IHdoZW4gcGFzc2VkIHRvIHRoZSBwcm92aWRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOC4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBPcmQgYiA9PiAoYSAtPiBiKSAtPiBhIC0+IGEgLT4gYVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZcbiAgICAgKiBAcGFyYW0geyp9IGFcbiAgICAgKiBAcGFyYW0geyp9IGJcbiAgICAgKiBAcmV0dXJuIHsqfVxuICAgICAqIEBzZWUgUi5tYXgsIFIubWluQnlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyAgc3F1YXJlIDo6IE51bWJlciAtPiBOdW1iZXJcbiAgICAgKiAgICAgIHZhciBzcXVhcmUgPSBuID0+IG4gKiBuO1xuICAgICAqXG4gICAgICogICAgICBSLm1heEJ5KHNxdWFyZSwgLTMsIDIpOyAvLz0+IC0zXG4gICAgICpcbiAgICAgKiAgICAgIFIucmVkdWNlKFIubWF4Qnkoc3F1YXJlKSwgMCwgWzMsIC01LCA0LCAxLCAtMl0pOyAvLz0+IC01XG4gICAgICogICAgICBSLnJlZHVjZShSLm1heEJ5KHNxdWFyZSksIDAsIFtdKTsgLy89PiAwXG4gICAgICovXG4gICAgdmFyIG1heEJ5ID0gX2N1cnJ5MyhmdW5jdGlvbiBtYXhCeShmLCBhLCBiKSB7XG4gICAgICAgIHJldHVybiBmKGIpID4gZihhKSA/IGIgOiBhO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbmV3IG9iamVjdCB3aXRoIHRoZSBvd24gcHJvcGVydGllcyBvZiB0aGUgZmlyc3Qgb2JqZWN0IG1lcmdlZCB3aXRoXG4gICAgICogdGhlIG93biBwcm9wZXJ0aWVzIG9mIHRoZSBzZWNvbmQgb2JqZWN0LiBJZiBhIGtleSBleGlzdHMgaW4gYm90aCBvYmplY3RzLFxuICAgICAqIHRoZSB2YWx1ZSBmcm9tIHRoZSBzZWNvbmQgb2JqZWN0IHdpbGwgYmUgdXNlZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcge2s6IHZ9IC0+IHtrOiB2fSAtPiB7azogdn1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByXG4gICAgICogQHJldHVybiB7T2JqZWN0fVxuICAgICAqIEBzZWUgUi5tZXJnZVdpdGgsIFIubWVyZ2VXaXRoS2V5XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5tZXJnZSh7ICduYW1lJzogJ2ZyZWQnLCAnYWdlJzogMTAgfSwgeyAnYWdlJzogNDAgfSk7XG4gICAgICogICAgICAvLz0+IHsgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiA0MCB9XG4gICAgICpcbiAgICAgKiAgICAgIHZhciByZXNldFRvRGVmYXVsdCA9IFIubWVyZ2UoUi5fXywge3g6IDB9KTtcbiAgICAgKiAgICAgIHJlc2V0VG9EZWZhdWx0KHt4OiA1LCB5OiAyfSk7IC8vPT4ge3g6IDAsIHk6IDJ9XG4gICAgICovXG4gICAgdmFyIG1lcmdlID0gX2N1cnJ5MihmdW5jdGlvbiBtZXJnZShsLCByKSB7XG4gICAgICAgIHJldHVybiBfYXNzaWduKHt9LCBsLCByKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIE1lcmdlcyBhIGxpc3Qgb2Ygb2JqZWN0cyB0b2dldGhlciBpbnRvIG9uZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEwLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgW3trOiB2fV0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBBbiBhcnJheSBvZiBvYmplY3RzXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBIG1lcmdlZCBvYmplY3QuXG4gICAgICogQHNlZSBSLnJlZHVjZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIubWVyZ2VBbGwoW3tmb286MX0se2JhcjoyfSx7YmF6OjN9XSk7IC8vPT4ge2ZvbzoxLGJhcjoyLGJhejozfVxuICAgICAqICAgICAgUi5tZXJnZUFsbChbe2ZvbzoxfSx7Zm9vOjJ9LHtiYXI6Mn1dKTsgLy89PiB7Zm9vOjIsYmFyOjJ9XG4gICAgICovXG4gICAgdmFyIG1lcmdlQWxsID0gX2N1cnJ5MShmdW5jdGlvbiBtZXJnZUFsbChsaXN0KSB7XG4gICAgICAgIHJldHVybiBfYXNzaWduLmFwcGx5KG51bGwsIFt7fV0uY29uY2F0KGxpc3QpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgb2JqZWN0IHdpdGggdGhlIG93biBwcm9wZXJ0aWVzIG9mIHRoZSB0d28gcHJvdmlkZWQgb2JqZWN0cy4gSWZcbiAgICAgKiBhIGtleSBleGlzdHMgaW4gYm90aCBvYmplY3RzLCB0aGUgcHJvdmlkZWQgZnVuY3Rpb24gaXMgYXBwbGllZCB0byB0aGUga2V5XG4gICAgICogYW5kIHRoZSB2YWx1ZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBrZXkgaW4gZWFjaCBvYmplY3QsIHdpdGggdGhlIHJlc3VsdCBiZWluZ1xuICAgICAqIHVzZWQgYXMgdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUga2V5IGluIHRoZSByZXR1cm5lZCBvYmplY3QuIFRoZSBrZXlcbiAgICAgKiB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gdGhlIHJldHVybmVkIG9iamVjdCBpZiB0aGUgcmVzdWx0aW5nIHZhbHVlIGlzXG4gICAgICogYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyAoU3RyaW5nIC0+IGEgLT4gYSAtPiBhKSAtPiB7YX0gLT4ge2F9IC0+IHthfVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gclxuICAgICAqIEByZXR1cm4ge09iamVjdH1cbiAgICAgKiBAc2VlIFIubWVyZ2UsIFIubWVyZ2VXaXRoXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgbGV0IGNvbmNhdFZhbHVlcyA9IChrLCBsLCByKSA9PiBrID09ICd2YWx1ZXMnID8gUi5jb25jYXQobCwgcikgOiByXG4gICAgICogICAgICBSLm1lcmdlV2l0aEtleShjb25jYXRWYWx1ZXMsXG4gICAgICogICAgICAgICAgICAgICAgICAgICB7IGE6IHRydWUsIHRoaW5nOiAnZm9vJywgdmFsdWVzOiBbMTAsIDIwXSB9LFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgeyBiOiB0cnVlLCB0aGluZzogJ2JhcicsIHZhbHVlczogWzE1LCAzNV0gfSk7XG4gICAgICogICAgICAvLz0+IHsgYTogdHJ1ZSwgYjogdHJ1ZSwgdGhpbmc6ICdiYXInLCB2YWx1ZXM6IFsxMCwgMjAsIDE1LCAzNV0gfVxuICAgICAqL1xuICAgIHZhciBtZXJnZVdpdGhLZXkgPSBfY3VycnkzKGZ1bmN0aW9uIG1lcmdlV2l0aEtleShmbiwgbCwgcikge1xuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIHZhciBrO1xuICAgICAgICBmb3IgKGsgaW4gbCkge1xuICAgICAgICAgICAgaWYgKF9oYXMoaywgbCkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRba10gPSBfaGFzKGssIHIpID8gZm4oaywgbFtrXSwgcltrXSkgOiBsW2tdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAoayBpbiByKSB7XG4gICAgICAgICAgICBpZiAoX2hhcyhrLCByKSAmJiAhX2hhcyhrLCByZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2tdID0gcltrXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgc21hbGxlciBvZiBpdHMgdHdvIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBPcmQgYSA9PiBhIC0+IGEgLT4gYVxuICAgICAqIEBwYXJhbSB7Kn0gYVxuICAgICAqIEBwYXJhbSB7Kn0gYlxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHNlZSBSLm1pbkJ5LCBSLm1heFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIubWluKDc4OSwgMTIzKTsgLy89PiAxMjNcbiAgICAgKiAgICAgIFIubWluKCdhJywgJ2InKTsgLy89PiAnYSdcbiAgICAgKi9cbiAgICB2YXIgbWluID0gX2N1cnJ5MihmdW5jdGlvbiBtaW4oYSwgYikge1xuICAgICAgICByZXR1cm4gYiA8IGEgPyBiIDogYTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgZnVuY3Rpb24gYW5kIHR3byB2YWx1ZXMsIGFuZCByZXR1cm5zIHdoaWNoZXZlciB2YWx1ZSBwcm9kdWNlcyB0aGVcbiAgICAgKiBzbWFsbGVyIHJlc3VsdCB3aGVuIHBhc3NlZCB0byB0aGUgcHJvdmlkZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjguMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgT3JkIGIgPT4gKGEgLT4gYikgLT4gYSAtPiBhIC0+IGFcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmXG4gICAgICogQHBhcmFtIHsqfSBhXG4gICAgICogQHBhcmFtIHsqfSBiXG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIubWluLCBSLm1heEJ5XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgLy8gIHNxdWFyZSA6OiBOdW1iZXIgLT4gTnVtYmVyXG4gICAgICogICAgICB2YXIgc3F1YXJlID0gbiA9PiBuICogbjtcbiAgICAgKlxuICAgICAqICAgICAgUi5taW5CeShzcXVhcmUsIC0zLCAyKTsgLy89PiAyXG4gICAgICpcbiAgICAgKiAgICAgIFIucmVkdWNlKFIubWluQnkoc3F1YXJlKSwgSW5maW5pdHksIFszLCAtNSwgNCwgMSwgLTJdKTsgLy89PiAxXG4gICAgICogICAgICBSLnJlZHVjZShSLm1pbkJ5KHNxdWFyZSksIEluZmluaXR5LCBbXSk7IC8vPT4gSW5maW5pdHlcbiAgICAgKi9cbiAgICB2YXIgbWluQnkgPSBfY3VycnkzKGZ1bmN0aW9uIG1pbkJ5KGYsIGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGYoYikgPCBmKGEpID8gYiA6IGE7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBEaXZpZGVzIHRoZSBmaXJzdCBwYXJhbWV0ZXIgYnkgdGhlIHNlY29uZCBhbmQgcmV0dXJucyB0aGUgcmVtYWluZGVyLiBOb3RlXG4gICAgICogdGhhdCB0aGlzIGZ1bmN0aW9uIHByZXNlcnZlcyB0aGUgSmF2YVNjcmlwdC1zdHlsZSBiZWhhdmlvciBmb3IgbW9kdWxvLiBGb3JcbiAgICAgKiBtYXRoZW1hdGljYWwgbW9kdWxvIHNlZSBgbWF0aE1vZGAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMVxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHNpZyBOdW1iZXIgLT4gTnVtYmVyIC0+IE51bWJlclxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBhIFRoZSB2YWx1ZSB0byB0aGUgZGl2aWRlLlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBiIFRoZSBwc2V1ZG8tbW9kdWx1c1xuICAgICAqIEByZXR1cm4ge051bWJlcn0gVGhlIHJlc3VsdCBvZiBgYiAlIGFgLlxuICAgICAqIEBzZWUgUi5tYXRoTW9kXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5tb2R1bG8oMTcsIDMpOyAvLz0+IDJcbiAgICAgKiAgICAgIC8vIEpTIGJlaGF2aW9yOlxuICAgICAqICAgICAgUi5tb2R1bG8oLTE3LCAzKTsgLy89PiAtMlxuICAgICAqICAgICAgUi5tb2R1bG8oMTcsIC0zKTsgLy89PiAyXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBpc09kZCA9IFIubW9kdWxvKFIuX18sIDIpO1xuICAgICAqICAgICAgaXNPZGQoNDIpOyAvLz0+IDBcbiAgICAgKiAgICAgIGlzT2RkKDIxKTsgLy89PiAxXG4gICAgICovXG4gICAgdmFyIG1vZHVsbyA9IF9jdXJyeTIoZnVuY3Rpb24gbW9kdWxvKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgJSBiO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogTXVsdGlwbGllcyB0d28gbnVtYmVycy4gRXF1aXZhbGVudCB0byBgYSAqIGJgIGJ1dCBjdXJyaWVkLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IE51bWJlciAtPiBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYSBUaGUgZmlyc3QgdmFsdWUuXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGIgVGhlIHNlY29uZCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IFRoZSByZXN1bHQgb2YgYGEgKiBiYC5cbiAgICAgKiBAc2VlIFIuZGl2aWRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGRvdWJsZSA9IFIubXVsdGlwbHkoMik7XG4gICAgICogICAgICB2YXIgdHJpcGxlID0gUi5tdWx0aXBseSgzKTtcbiAgICAgKiAgICAgIGRvdWJsZSgzKTsgICAgICAgLy89PiAgNlxuICAgICAqICAgICAgdHJpcGxlKDQpOyAgICAgICAvLz0+IDEyXG4gICAgICogICAgICBSLm11bHRpcGx5KDIsIDUpOyAgLy89PiAxMFxuICAgICAqL1xuICAgIHZhciBtdWx0aXBseSA9IF9jdXJyeTIoZnVuY3Rpb24gbXVsdGlwbHkoYSwgYikge1xuICAgICAgICByZXR1cm4gYSAqIGI7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBXcmFwcyBhIGZ1bmN0aW9uIG9mIGFueSBhcml0eSAoaW5jbHVkaW5nIG51bGxhcnkpIGluIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzXG4gICAgICogZXhhY3RseSBgbmAgcGFyYW1ldGVycy4gQW55IGV4dHJhbmVvdXMgcGFyYW1ldGVycyB3aWxsIG5vdCBiZSBwYXNzZWQgdG8gdGhlXG4gICAgICogc3VwcGxpZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgTnVtYmVyIC0+ICgqIC0+IGEpIC0+ICgqIC0+IGEpXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG4gVGhlIGRlc2lyZWQgYXJpdHkgb2YgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBuZXcgZnVuY3Rpb24gd3JhcHBpbmcgYGZuYC4gVGhlIG5ldyBmdW5jdGlvbiBpcyBndWFyYW50ZWVkIHRvIGJlIG9mXG4gICAgICogICAgICAgICBhcml0eSBgbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHRha2VzVHdvQXJncyA9IChhLCBiKSA9PiBbYSwgYl07XG4gICAgICpcbiAgICAgKiAgICAgIHRha2VzVHdvQXJncy5sZW5ndGg7IC8vPT4gMlxuICAgICAqICAgICAgdGFrZXNUd29BcmdzKDEsIDIpOyAvLz0+IFsxLCAyXVxuICAgICAqXG4gICAgICogICAgICB2YXIgdGFrZXNPbmVBcmcgPSBSLm5BcnkoMSwgdGFrZXNUd29BcmdzKTtcbiAgICAgKiAgICAgIHRha2VzT25lQXJnLmxlbmd0aDsgLy89PiAxXG4gICAgICogICAgICAvLyBPbmx5IGBuYCBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byB0aGUgd3JhcHBlZCBmdW5jdGlvblxuICAgICAqICAgICAgdGFrZXNPbmVBcmcoMSwgMik7IC8vPT4gWzEsIHVuZGVmaW5lZF1cbiAgICAgKi9cbiAgICB2YXIgbkFyeSA9IF9jdXJyeTIoZnVuY3Rpb24gbkFyeShuLCBmbikge1xuICAgICAgICBzd2l0Y2ggKG4pIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBhMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIGEwLCBhMSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSwgYTIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBhMCwgYTEsIGEyKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTAsIGExLCBhMiwgYTMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBhMCwgYTEsIGEyLCBhMyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSwgYTIsIGEzLCBhNCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIGEwLCBhMSwgYTIsIGEzLCBhNCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSwgYTIsIGEzLCBhNCwgYTUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBhMCwgYTEsIGEyLCBhMywgYTQsIGE1KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYTAsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBhMCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNik7XG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2LCBhNykge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5jYWxsKHRoaXMsIGEwLCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2LCBhNyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2LCBhNywgYTgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbCh0aGlzLCBhMCwgYTEsIGEyLCBhMywgYTQsIGE1LCBhNiwgYTcsIGE4KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGEwLCBhMSwgYTIsIGEzLCBhNCwgYTUsIGE2LCBhNywgYTgsIGE5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZuLmNhbGwodGhpcywgYTAsIGExLCBhMiwgYTMsIGE0LCBhNSwgYTYsIGE3LCBhOCwgYTkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRmlyc3QgYXJndW1lbnQgdG8gbkFyeSBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIgbm8gZ3JlYXRlciB0aGFuIHRlbicpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBOZWdhdGVzIGl0cyBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIE51bWJlciAtPiBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gblxuICAgICAqIEByZXR1cm4ge051bWJlcn1cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLm5lZ2F0ZSg0Mik7IC8vPT4gLTQyXG4gICAgICovXG4gICAgdmFyIG5lZ2F0ZSA9IF9jdXJyeTEoZnVuY3Rpb24gbmVnYXRlKG4pIHtcbiAgICAgICAgcmV0dXJuIC1uO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgbm8gZWxlbWVudHMgb2YgdGhlIGxpc3QgbWF0Y2ggdGhlIHByZWRpY2F0ZSwgYGZhbHNlYFxuICAgICAqIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBhbnlgIG1ldGhvZCBvZiB0aGUgc2Vjb25kIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMi4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIHByZWRpY2F0ZSBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgdGhlIHByZWRpY2F0ZSBpcyBub3Qgc2F0aXNmaWVkIGJ5IGV2ZXJ5IGVsZW1lbnQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqIEBzZWUgUi5hbGwsIFIuYW55XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGlzRXZlbiA9IG4gPT4gbiAlIDIgPT09IDA7XG4gICAgICpcbiAgICAgKiAgICAgIFIubm9uZShpc0V2ZW4sIFsxLCAzLCA1LCA3LCA5LCAxMV0pOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIubm9uZShpc0V2ZW4sIFsxLCAzLCA1LCA3LCA4LCAxMV0pOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIG5vbmUgPSBfY3VycnkyKF9jb21wbGVtZW50KF9kaXNwYXRjaGFibGUoJ2FueScsIF94YW55LCBhbnkpKSk7XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgYCFgIG9mIGl0cyBhcmd1bWVudC4gSXQgd2lsbCByZXR1cm4gYHRydWVgIHdoZW5cbiAgICAgKiBwYXNzZWQgZmFsc2UteSB2YWx1ZSwgYW5kIGBmYWxzZWAgd2hlbiBwYXNzZWQgYSB0cnV0aC15IG9uZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExvZ2ljXG4gICAgICogQHNpZyAqIC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0geyp9IGEgYW55IHZhbHVlXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn0gdGhlIGxvZ2ljYWwgaW52ZXJzZSBvZiBwYXNzZWQgYXJndW1lbnQuXG4gICAgICogQHNlZSBSLmNvbXBsZW1lbnRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLm5vdCh0cnVlKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5ub3QoZmFsc2UpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIubm90KDApOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIubm90KDEpOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIG5vdCA9IF9jdXJyeTEoZnVuY3Rpb24gbm90KGEpIHtcbiAgICAgICAgcmV0dXJuICFhO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbnRoIGVsZW1lbnQgb2YgdGhlIGdpdmVuIGxpc3Qgb3Igc3RyaW5nLiBJZiBuIGlzIG5lZ2F0aXZlIHRoZVxuICAgICAqIGVsZW1lbnQgYXQgaW5kZXggbGVuZ3RoICsgbiBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIE51bWJlciAtPiBbYV0gLT4gYSB8IFVuZGVmaW5lZFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0XG4gICAgICogQHBhcmFtIHsqfSBsaXN0XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbGlzdCA9IFsnZm9vJywgJ2JhcicsICdiYXonLCAncXV1eCddO1xuICAgICAqICAgICAgUi5udGgoMSwgbGlzdCk7IC8vPT4gJ2JhcidcbiAgICAgKiAgICAgIFIubnRoKC0xLCBsaXN0KTsgLy89PiAncXV1eCdcbiAgICAgKiAgICAgIFIubnRoKC05OSwgbGlzdCk7IC8vPT4gdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiAgICAgIFIubnRoKDIsICdhYmMnKTsgLy89PiAnYydcbiAgICAgKiAgICAgIFIubnRoKDMsICdhYmMnKTsgLy89PiAnJ1xuICAgICAqL1xuICAgIHZhciBudGggPSBfY3VycnkyKGZ1bmN0aW9uIG50aChvZmZzZXQsIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IG9mZnNldCA8IDAgPyBsaXN0Lmxlbmd0aCArIG9mZnNldCA6IG9mZnNldDtcbiAgICAgICAgcmV0dXJuIF9pc1N0cmluZyhsaXN0KSA/IGxpc3QuY2hhckF0KGlkeCkgOiBsaXN0W2lkeF07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBpdHMgbnRoIGFyZ3VtZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC45LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIE51bWJlciAtPiAqLi4uIC0+ICpcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gblxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIubnRoQXJnKDEpKCdhJywgJ2InLCAnYycpOyAvLz0+ICdiJ1xuICAgICAqICAgICAgUi5udGhBcmcoLTEpKCdhJywgJ2InLCAnYycpOyAvLz0+ICdjJ1xuICAgICAqL1xuICAgIHZhciBudGhBcmcgPSBfY3VycnkxKGZ1bmN0aW9uIG50aEFyZyhuKSB7XG4gICAgICAgIHZhciBhcml0eSA9IG4gPCAwID8gMSA6IG4gKyAxO1xuICAgICAgICByZXR1cm4gY3VycnlOKGFyaXR5LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnRoKG4sIGFyZ3VtZW50cyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29udGFpbmluZyBhIHNpbmdsZSBrZXk6dmFsdWUgcGFpci5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTguMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIFN0cmluZyAtPiBhIC0+IHtTdHJpbmc6YX1cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAgICogQHBhcmFtIHsqfSB2YWxcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAgICogQHNlZSBSLnBhaXJcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbWF0Y2hQaHJhc2VzID0gUi5jb21wb3NlKFxuICAgICAqICAgICAgICBSLm9iak9mKCdtdXN0JyksXG4gICAgICogICAgICAgIFIubWFwKFIub2JqT2YoJ21hdGNoX3BocmFzZScpKVxuICAgICAqICAgICAgKTtcbiAgICAgKiAgICAgIG1hdGNoUGhyYXNlcyhbJ2ZvbycsICdiYXInLCAnYmF6J10pOyAvLz0+IHttdXN0OiBbe21hdGNoX3BocmFzZTogJ2Zvbyd9LCB7bWF0Y2hfcGhyYXNlOiAnYmFyJ30sIHttYXRjaF9waHJhc2U6ICdiYXonfV19XG4gICAgICovXG4gICAgdmFyIG9iak9mID0gX2N1cnJ5MihmdW5jdGlvbiBvYmpPZihrZXksIHZhbCkge1xuICAgICAgICB2YXIgb2JqID0ge307XG4gICAgICAgIG9ialtrZXldID0gdmFsO1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHNpbmdsZXRvbiBhcnJheSBjb250YWluaW5nIHRoZSB2YWx1ZSBwcm92aWRlZC5cbiAgICAgKlxuICAgICAqIE5vdGUgdGhpcyBgb2ZgIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBFUzYgYG9mYDsgU2VlXG4gICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvb2ZcbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMy4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyBhIC0+IFthXVxuICAgICAqIEBwYXJhbSB7Kn0geCBhbnkgdmFsdWVcbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgd3JhcHBpbmcgYHhgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIub2YobnVsbCk7IC8vPT4gW251bGxdXG4gICAgICogICAgICBSLm9mKFs0Ml0pOyAvLz0+IFtbNDJdXVxuICAgICAqL1xuICAgIHZhciBvZiA9IF9jdXJyeTEoX29mKTtcblxuICAgIC8qKlxuICAgICAqIEFjY2VwdHMgYSBmdW5jdGlvbiBgZm5gIGFuZCByZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBndWFyZHMgaW52b2NhdGlvbiBvZlxuICAgICAqIGBmbmAgc3VjaCB0aGF0IGBmbmAgY2FuIG9ubHkgZXZlciBiZSBjYWxsZWQgb25jZSwgbm8gbWF0dGVyIGhvdyBtYW55IHRpbWVzXG4gICAgICogdGhlIHJldHVybmVkIGZ1bmN0aW9uIGlzIGludm9rZWQuIFRoZSBmaXJzdCB2YWx1ZSBjYWxjdWxhdGVkIGlzIHJldHVybmVkIGluXG4gICAgICogc3Vic2VxdWVudCBpbnZvY2F0aW9ucy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoYS4uLiAtPiBiKSAtPiAoYS4uLiAtPiBiKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byB3cmFwIGluIGEgY2FsbC1vbmx5LW9uY2Ugd3JhcHBlci5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGFkZE9uZU9uY2UgPSBSLm9uY2UoeCA9PiB4ICsgMSk7XG4gICAgICogICAgICBhZGRPbmVPbmNlKDEwKTsgLy89PiAxMVxuICAgICAqICAgICAgYWRkT25lT25jZShhZGRPbmVPbmNlKDUwKSk7IC8vPT4gMTFcbiAgICAgKi9cbiAgICB2YXIgb25jZSA9IF9jdXJyeTEoZnVuY3Rpb24gb25jZShmbikge1xuICAgICAgICB2YXIgY2FsbGVkID0gZmFsc2U7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIHJldHVybiBfYXJpdHkoZm4ubGVuZ3RoLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2FsbGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICAgICAgICByZXN1bHQgPSBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiBvbmUgb3IgYm90aCBvZiBpdHMgYXJndW1lbnRzIGFyZSBgdHJ1ZWAuIFJldHVybnMgYGZhbHNlYFxuICAgICAqIGlmIGJvdGggYXJndW1lbnRzIGFyZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTG9naWNcbiAgICAgKiBAc2lnICogLT4gKiAtPiAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBhIEEgYm9vbGVhbiB2YWx1ZVxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gYiBBIGJvb2xlYW4gdmFsdWVcbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufSBgdHJ1ZWAgaWYgb25lIG9yIGJvdGggYXJndW1lbnRzIGFyZSBgdHJ1ZWAsIGBmYWxzZWAgb3RoZXJ3aXNlXG4gICAgICogQHNlZSBSLmVpdGhlclxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIub3IodHJ1ZSwgdHJ1ZSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5vcih0cnVlLCBmYWxzZSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5vcihmYWxzZSwgdHJ1ZSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5vcihmYWxzZSwgZmFsc2UpOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIG9yID0gX2N1cnJ5MihmdW5jdGlvbiBvcihhLCBiKSB7XG4gICAgICAgIHJldHVybiBhIHx8IGI7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByZXN1bHQgb2YgXCJzZXR0aW5nXCIgdGhlIHBvcnRpb24gb2YgdGhlIGdpdmVuIGRhdGEgc3RydWN0dXJlXG4gICAgICogZm9jdXNlZCBieSB0aGUgZ2l2ZW4gbGVucyB0byB0aGUgcmVzdWx0IG9mIGFwcGx5aW5nIHRoZSBnaXZlbiBmdW5jdGlvbiB0b1xuICAgICAqIHRoZSBmb2N1c2VkIHZhbHVlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNi4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEB0eXBlZGVmbiBMZW5zIHMgYSA9IEZ1bmN0b3IgZiA9PiAoYSAtPiBmIGEpIC0+IHMgLT4gZiBzXG4gICAgICogQHNpZyBMZW5zIHMgYSAtPiAoYSAtPiBhKSAtPiBzIC0+IHNcbiAgICAgKiBAcGFyYW0ge0xlbnN9IGxlbnNcbiAgICAgKiBAcGFyYW0geyp9IHZcbiAgICAgKiBAcGFyYW0geyp9IHhcbiAgICAgKiBAcmV0dXJuIHsqfVxuICAgICAqIEBzZWUgUi5wcm9wLCBSLmxlbnNJbmRleCwgUi5sZW5zUHJvcFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBoZWFkTGVucyA9IFIubGVuc0luZGV4KDApO1xuICAgICAqXG4gICAgICogICAgICBSLm92ZXIoaGVhZExlbnMsIFIudG9VcHBlciwgWydmb28nLCAnYmFyJywgJ2JheiddKTsgLy89PiBbJ0ZPTycsICdiYXInLCAnYmF6J11cbiAgICAgKi9cbiAgICAvLyBgSWRlbnRpdHlgIGlzIGEgZnVuY3RvciB0aGF0IGhvbGRzIGEgc2luZ2xlIHZhbHVlLCB3aGVyZSBgbWFwYCBzaW1wbHlcbiAgICAvLyB0cmFuc2Zvcm1zIHRoZSBoZWxkIHZhbHVlIHdpdGggdGhlIHByb3ZpZGVkIGZ1bmN0aW9uLlxuICAgIC8vIFRoZSB2YWx1ZSByZXR1cm5lZCBieSB0aGUgZ2V0dGVyIGZ1bmN0aW9uIGlzIGZpcnN0IHRyYW5zZm9ybWVkIHdpdGggYGZgLFxuICAgIC8vIHRoZW4gc2V0IGFzIHRoZSB2YWx1ZSBvZiBhbiBgSWRlbnRpdHlgLiBUaGlzIGlzIHRoZW4gbWFwcGVkIG92ZXIgd2l0aCB0aGVcbiAgICAvLyBzZXR0ZXIgZnVuY3Rpb24gb2YgdGhlIGxlbnMuXG4gICAgdmFyIG92ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGBJZGVudGl0eWAgaXMgYSBmdW5jdG9yIHRoYXQgaG9sZHMgYSBzaW5nbGUgdmFsdWUsIHdoZXJlIGBtYXBgIHNpbXBseVxuICAgICAgICAvLyB0cmFuc2Zvcm1zIHRoZSBoZWxkIHZhbHVlIHdpdGggdGhlIHByb3ZpZGVkIGZ1bmN0aW9uLlxuICAgICAgICB2YXIgSWRlbnRpdHkgPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogeCxcbiAgICAgICAgICAgICAgICBtYXA6IGZ1bmN0aW9uIChmKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBJZGVudGl0eShmKHgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MyhmdW5jdGlvbiBvdmVyKGxlbnMsIGYsIHgpIHtcbiAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSByZXR1cm5lZCBieSB0aGUgZ2V0dGVyIGZ1bmN0aW9uIGlzIGZpcnN0IHRyYW5zZm9ybWVkIHdpdGggYGZgLFxuICAgICAgICAgICAgLy8gdGhlbiBzZXQgYXMgdGhlIHZhbHVlIG9mIGFuIGBJZGVudGl0eWAuIFRoaXMgaXMgdGhlbiBtYXBwZWQgb3ZlciB3aXRoIHRoZVxuICAgICAgICAgICAgLy8gc2V0dGVyIGZ1bmN0aW9uIG9mIHRoZSBsZW5zLlxuICAgICAgICAgICAgcmV0dXJuIGxlbnMoZnVuY3Rpb24gKHkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gSWRlbnRpdHkoZih5KSk7XG4gICAgICAgICAgICB9KSh4KS52YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgfSgpO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgdHdvIGFyZ3VtZW50cywgYGZzdGAgYW5kIGBzbmRgLCBhbmQgcmV0dXJucyBgW2ZzdCwgc25kXWAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE4LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgYSAtPiBiIC0+IChhLGIpXG4gICAgICogQHBhcmFtIHsqfSBmc3RcbiAgICAgKiBAcGFyYW0geyp9IHNuZFxuICAgICAqIEByZXR1cm4ge0FycmF5fVxuICAgICAqIEBzZWUgUi5vYmpPZiwgUi5vZlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucGFpcignZm9vJywgJ2JhcicpOyAvLz0+IFsnZm9vJywgJ2JhciddXG4gICAgICovXG4gICAgdmFyIHBhaXIgPSBfY3VycnkyKGZ1bmN0aW9uIHBhaXIoZnN0LCBzbmQpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIGZzdCxcbiAgICAgICAgICAgIHNuZFxuICAgICAgICBdO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmUgdGhlIHZhbHVlIGF0IGEgZ2l2ZW4gcGF0aC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMi4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgW1N0cmluZ10gLT4ge2s6IHZ9IC0+IHYgfCBVbmRlZmluZWRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXRoIFRoZSBwYXRoIHRvIHVzZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcmV0cmlldmUgdGhlIG5lc3RlZCBwcm9wZXJ0eSBmcm9tLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBkYXRhIGF0IGBwYXRoYC5cbiAgICAgKiBAc2VlIFIucHJvcFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucGF0aChbJ2EnLCAnYiddLCB7YToge2I6IDJ9fSk7IC8vPT4gMlxuICAgICAqICAgICAgUi5wYXRoKFsnYScsICdiJ10sIHtjOiB7YjogMn19KTsgLy89PiB1bmRlZmluZWRcbiAgICAgKi9cbiAgICB2YXIgcGF0aCA9IF9jdXJyeTIoZnVuY3Rpb24gcGF0aChwYXRocywgb2JqKSB7XG4gICAgICAgIHZhciB2YWwgPSBvYmo7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB3aGlsZSAoaWR4IDwgcGF0aHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAodmFsID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWwgPSB2YWxbcGF0aHNbaWR4XV07XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSWYgdGhlIGdpdmVuLCBub24tbnVsbCBvYmplY3QgaGFzIGEgdmFsdWUgYXQgdGhlIGdpdmVuIHBhdGgsIHJldHVybnMgdGhlXG4gICAgICogdmFsdWUgYXQgdGhhdCBwYXRoLiBPdGhlcndpc2UgcmV0dXJucyB0aGUgcHJvdmlkZWQgZGVmYXVsdCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTguMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIGEgLT4gW1N0cmluZ10gLT4gT2JqZWN0IC0+IGFcbiAgICAgKiBAcGFyYW0geyp9IGQgVGhlIGRlZmF1bHQgdmFsdWUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gcCBUaGUgcGF0aCB0byB1c2UuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHJldHJpZXZlIHRoZSBuZXN0ZWQgcHJvcGVydHkgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHsqfSBUaGUgZGF0YSBhdCBgcGF0aGAgb2YgdGhlIHN1cHBsaWVkIG9iamVjdCBvciB0aGUgZGVmYXVsdCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnBhdGhPcignTi9BJywgWydhJywgJ2InXSwge2E6IHtiOiAyfX0pOyAvLz0+IDJcbiAgICAgKiAgICAgIFIucGF0aE9yKCdOL0EnLCBbJ2EnLCAnYiddLCB7Yzoge2I6IDJ9fSk7IC8vPT4gXCJOL0FcIlxuICAgICAqL1xuICAgIHZhciBwYXRoT3IgPSBfY3VycnkzKGZ1bmN0aW9uIHBhdGhPcihkLCBwLCBvYmopIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRUbyhkLCBwYXRoKHAsIG9iaikpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHNwZWNpZmllZCBvYmplY3QgcHJvcGVydHkgYXQgZ2l2ZW4gcGF0aCBzYXRpc2ZpZXMgdGhlXG4gICAgICogZ2l2ZW4gcHJlZGljYXRlOyBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTkuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgKGEgLT4gQm9vbGVhbikgLT4gW1N0cmluZ10gLT4gT2JqZWN0IC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJvcFBhdGhcbiAgICAgKiBAcGFyYW0geyp9IG9ialxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQHNlZSBSLnByb3BTYXRpc2ZpZXMsIFIucGF0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucGF0aFNhdGlzZmllcyh5ID0+IHkgPiAwLCBbJ3gnLCAneSddLCB7eDoge3k6IDJ9fSk7IC8vPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBwYXRoU2F0aXNmaWVzID0gX2N1cnJ5MyhmdW5jdGlvbiBwYXRoU2F0aXNmaWVzKHByZWQsIHByb3BQYXRoLCBvYmopIHtcbiAgICAgICAgcmV0dXJuIHByb3BQYXRoLmxlbmd0aCA+IDAgJiYgcHJlZChwYXRoKHByb3BQYXRoLCBvYmopKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBwYXJ0aWFsIGNvcHkgb2YgYW4gb2JqZWN0IGNvbnRhaW5pbmcgb25seSB0aGUga2V5cyBzcGVjaWZpZWQuIElmXG4gICAgICogdGhlIGtleSBkb2VzIG5vdCBleGlzdCwgdGhlIHByb3BlcnR5IGlzIGlnbm9yZWQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIFtrXSAtPiB7azogdn0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtBcnJheX0gbmFtZXMgYW4gYXJyYXkgb2YgU3RyaW5nIHByb3BlcnR5IG5hbWVzIHRvIGNvcHkgb250byBhIG5ldyBvYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gY29weSBmcm9tXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBIG5ldyBvYmplY3Qgd2l0aCBvbmx5IHByb3BlcnRpZXMgZnJvbSBgbmFtZXNgIG9uIGl0LlxuICAgICAqIEBzZWUgUi5vbWl0LCBSLnByb3BzXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5waWNrKFsnYScsICdkJ10sIHthOiAxLCBiOiAyLCBjOiAzLCBkOiA0fSk7IC8vPT4ge2E6IDEsIGQ6IDR9XG4gICAgICogICAgICBSLnBpY2soWydhJywgJ2UnLCAnZiddLCB7YTogMSwgYjogMiwgYzogMywgZDogNH0pOyAvLz0+IHthOiAxfVxuICAgICAqL1xuICAgIHZhciBwaWNrID0gX2N1cnJ5MihmdW5jdGlvbiBwaWNrKG5hbWVzLCBvYmopIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IG5hbWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKG5hbWVzW2lkeF0gaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W25hbWVzW2lkeF1dID0gb2JqW25hbWVzW2lkeF1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNpbWlsYXIgdG8gYHBpY2tgIGV4Y2VwdCB0aGF0IHRoaXMgb25lIGluY2x1ZGVzIGEgYGtleTogdW5kZWZpbmVkYCBwYWlyIGZvclxuICAgICAqIHByb3BlcnRpZXMgdGhhdCBkb24ndCBleGlzdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgW2tdIC0+IHtrOiB2fSAtPiB7azogdn1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBuYW1lcyBhbiBhcnJheSBvZiBTdHJpbmcgcHJvcGVydHkgbmFtZXMgdG8gY29weSBvbnRvIGEgbmV3IG9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjb3B5IGZyb21cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEEgbmV3IG9iamVjdCB3aXRoIG9ubHkgcHJvcGVydGllcyBmcm9tIGBuYW1lc2Agb24gaXQuXG4gICAgICogQHNlZSBSLnBpY2tcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnBpY2tBbGwoWydhJywgJ2QnXSwge2E6IDEsIGI6IDIsIGM6IDMsIGQ6IDR9KTsgLy89PiB7YTogMSwgZDogNH1cbiAgICAgKiAgICAgIFIucGlja0FsbChbJ2EnLCAnZScsICdmJ10sIHthOiAxLCBiOiAyLCBjOiAzLCBkOiA0fSk7IC8vPT4ge2E6IDEsIGU6IHVuZGVmaW5lZCwgZjogdW5kZWZpbmVkfVxuICAgICAqL1xuICAgIHZhciBwaWNrQWxsID0gX2N1cnJ5MihmdW5jdGlvbiBwaWNrQWxsKG5hbWVzLCBvYmopIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IG5hbWVzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbikge1xuICAgICAgICAgICAgdmFyIG5hbWUgPSBuYW1lc1tpZHhdO1xuICAgICAgICAgICAgcmVzdWx0W25hbWVdID0gb2JqW25hbWVdO1xuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBwYXJ0aWFsIGNvcHkgb2YgYW4gb2JqZWN0IGNvbnRhaW5pbmcgb25seSB0aGUga2V5cyB0aGF0IHNhdGlzZnlcbiAgICAgKiB0aGUgc3VwcGxpZWQgcHJlZGljYXRlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC44LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyAodiwgayAtPiBCb29sZWFuKSAtPiB7azogdn0gLT4ge2s6IHZ9XG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZCBBIHByZWRpY2F0ZSB0byBkZXRlcm1pbmUgd2hldGhlciBvciBub3QgYSBrZXlcbiAgICAgKiAgICAgICAgc2hvdWxkIGJlIGluY2x1ZGVkIG9uIHRoZSBvdXRwdXQgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjb3B5IGZyb21cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEEgbmV3IG9iamVjdCB3aXRoIG9ubHkgcHJvcGVydGllcyB0aGF0IHNhdGlzZnkgYHByZWRgXG4gICAgICogICAgICAgICBvbiBpdC5cbiAgICAgKiBAc2VlIFIucGljaywgUi5maWx0ZXJcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNVcHBlckNhc2UgPSAodmFsLCBrZXkpID0+IGtleS50b1VwcGVyQ2FzZSgpID09PSBrZXk7XG4gICAgICogICAgICBSLnBpY2tCeShpc1VwcGVyQ2FzZSwge2E6IDEsIGI6IDIsIEE6IDMsIEI6IDR9KTsgLy89PiB7QTogMywgQjogNH1cbiAgICAgKi9cbiAgICB2YXIgcGlja0J5ID0gX2N1cnJ5MihmdW5jdGlvbiBwaWNrQnkodGVzdCwgb2JqKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmICh0ZXN0KG9ialtwcm9wXSwgcHJvcCwgb2JqKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtwcm9wXSA9IG9ialtwcm9wXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IHdpdGggdGhlIGdpdmVuIGVsZW1lbnQgYXQgdGhlIGZyb250LCBmb2xsb3dlZCBieSB0aGVcbiAgICAgKiBjb250ZW50cyBvZiB0aGUgbGlzdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIGEgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7Kn0gZWwgVGhlIGl0ZW0gdG8gYWRkIHRvIHRoZSBoZWFkIG9mIHRoZSBvdXRwdXQgbGlzdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBhZGQgdG8gdGhlIHRhaWwgb2YgdGhlIG91dHB1dCBsaXN0LlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBIG5ldyBhcnJheS5cbiAgICAgKiBAc2VlIFIuYXBwZW5kXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5wcmVwZW5kKCdmZWUnLCBbJ2ZpJywgJ2ZvJywgJ2Z1bSddKTsgLy89PiBbJ2ZlZScsICdmaScsICdmbycsICdmdW0nXVxuICAgICAqL1xuICAgIHZhciBwcmVwZW5kID0gX2N1cnJ5MihmdW5jdGlvbiBwcmVwZW5kKGVsLCBsaXN0KSB7XG4gICAgICAgIHJldHVybiBfY29uY2F0KFtlbF0sIGxpc3QpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2hlbiBzdXBwbGllZCBhbiBvYmplY3QgcmV0dXJucyB0aGUgaW5kaWNhdGVkXG4gICAgICogcHJvcGVydHkgb2YgdGhhdCBvYmplY3QsIGlmIGl0IGV4aXN0cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgcyAtPiB7czogYX0gLT4gYSB8IFVuZGVmaW5lZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBwIFRoZSBwcm9wZXJ0eSBuYW1lXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHF1ZXJ5XG4gICAgICogQHJldHVybiB7Kn0gVGhlIHZhbHVlIGF0IGBvYmoucGAuXG4gICAgICogQHNlZSBSLnBhdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnByb3AoJ3gnLCB7eDogMTAwfSk7IC8vPT4gMTAwXG4gICAgICogICAgICBSLnByb3AoJ3gnLCB7fSk7IC8vPT4gdW5kZWZpbmVkXG4gICAgICovXG4gICAgdmFyIHByb3AgPSBfY3VycnkyKGZ1bmN0aW9uIHByb3AocCwgb2JqKSB7XG4gICAgICAgIHJldHVybiBvYmpbcF07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgc3BlY2lmaWVkIG9iamVjdCBwcm9wZXJ0eSBpcyBvZiB0aGUgZ2l2ZW4gdHlwZTtcbiAgICAgKiBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTYuMFxuICAgICAqIEBjYXRlZ29yeSBUeXBlXG4gICAgICogQHNpZyBUeXBlIC0+IFN0cmluZyAtPiBPYmplY3QgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHR5cGVcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgICAqIEBwYXJhbSB7Kn0gb2JqXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAc2VlIFIuaXMsIFIucHJvcFNhdGlzZmllc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucHJvcElzKE51bWJlciwgJ3gnLCB7eDogMSwgeTogMn0pOyAgLy89PiB0cnVlXG4gICAgICogICAgICBSLnByb3BJcyhOdW1iZXIsICd4Jywge3g6ICdmb28nfSk7ICAgIC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIucHJvcElzKE51bWJlciwgJ3gnLCB7fSk7ICAgICAgICAgICAgLy89PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBwcm9wSXMgPSBfY3VycnkzKGZ1bmN0aW9uIHByb3BJcyh0eXBlLCBuYW1lLCBvYmopIHtcbiAgICAgICAgcmV0dXJuIGlzKHR5cGUsIG9ialtuYW1lXSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBJZiB0aGUgZ2l2ZW4sIG5vbi1udWxsIG9iamVjdCBoYXMgYW4gb3duIHByb3BlcnR5IHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLFxuICAgICAqIHJldHVybnMgdGhlIHZhbHVlIG9mIHRoYXQgcHJvcGVydHkuIE90aGVyd2lzZSByZXR1cm5zIHRoZSBwcm92aWRlZCBkZWZhdWx0XG4gICAgICogdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjYuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIGEgLT4gU3RyaW5nIC0+IE9iamVjdCAtPiBhXG4gICAgICogQHBhcmFtIHsqfSB2YWwgVGhlIGRlZmF1bHQgdmFsdWUuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHAgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHVybi5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybiB7Kn0gVGhlIHZhbHVlIG9mIGdpdmVuIHByb3BlcnR5IG9mIHRoZSBzdXBwbGllZCBvYmplY3Qgb3IgdGhlIGRlZmF1bHQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGFsaWNlID0ge1xuICAgICAqICAgICAgICBuYW1lOiAnQUxJQ0UnLFxuICAgICAqICAgICAgICBhZ2U6IDEwMVxuICAgICAqICAgICAgfTtcbiAgICAgKiAgICAgIHZhciBmYXZvcml0ZSA9IFIucHJvcCgnZmF2b3JpdGVMaWJyYXJ5Jyk7XG4gICAgICogICAgICB2YXIgZmF2b3JpdGVXaXRoRGVmYXVsdCA9IFIucHJvcE9yKCdSYW1kYScsICdmYXZvcml0ZUxpYnJhcnknKTtcbiAgICAgKlxuICAgICAqICAgICAgZmF2b3JpdGUoYWxpY2UpOyAgLy89PiB1bmRlZmluZWRcbiAgICAgKiAgICAgIGZhdm9yaXRlV2l0aERlZmF1bHQoYWxpY2UpOyAgLy89PiAnUmFtZGEnXG4gICAgICovXG4gICAgdmFyIHByb3BPciA9IF9jdXJyeTMoZnVuY3Rpb24gcHJvcE9yKHZhbCwgcCwgb2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogIT0gbnVsbCAmJiBfaGFzKHAsIG9iaikgPyBvYmpbcF0gOiB2YWw7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgc3BlY2lmaWVkIG9iamVjdCBwcm9wZXJ0eSBzYXRpc2ZpZXMgdGhlIGdpdmVuXG4gICAgICogcHJlZGljYXRlOyBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTYuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgKGEgLT4gQm9vbGVhbikgLT4gU3RyaW5nIC0+IHtTdHJpbmc6IGF9IC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0geyp9IG9ialxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQHNlZSBSLnByb3BFcSwgUi5wcm9wSXNcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnByb3BTYXRpc2ZpZXMoeCA9PiB4ID4gMCwgJ3gnLCB7eDogMSwgeTogMn0pOyAvLz0+IHRydWVcbiAgICAgKi9cbiAgICB2YXIgcHJvcFNhdGlzZmllcyA9IF9jdXJyeTMoZnVuY3Rpb24gcHJvcFNhdGlzZmllcyhwcmVkLCBuYW1lLCBvYmopIHtcbiAgICAgICAgcmV0dXJuIHByZWQob2JqW25hbWVdKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEFjdHMgYXMgbXVsdGlwbGUgYHByb3BgOiBhcnJheSBvZiBrZXlzIGluLCBhcnJheSBvZiB2YWx1ZXMgb3V0LiBQcmVzZXJ2ZXNcbiAgICAgKiBvcmRlci5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgW2tdIC0+IHtrOiB2fSAtPiBbdl1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwcyBUaGUgcHJvcGVydHkgbmFtZXMgdG8gZmV0Y2hcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcXVlcnlcbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVzIG9yIHBhcnRpYWxseSBhcHBsaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucHJvcHMoWyd4JywgJ3knXSwge3g6IDEsIHk6IDJ9KTsgLy89PiBbMSwgMl1cbiAgICAgKiAgICAgIFIucHJvcHMoWydjJywgJ2EnLCAnYiddLCB7YjogMiwgYTogMX0pOyAvLz0+IFt1bmRlZmluZWQsIDEsIDJdXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBmdWxsTmFtZSA9IFIuY29tcG9zZShSLmpvaW4oJyAnKSwgUi5wcm9wcyhbJ2ZpcnN0JywgJ2xhc3QnXSkpO1xuICAgICAqICAgICAgZnVsbE5hbWUoe2xhc3Q6ICdCdWxsZXQtVG9vdGgnLCBhZ2U6IDMzLCBmaXJzdDogJ1RvbnknfSk7IC8vPT4gJ1RvbnkgQnVsbGV0LVRvb3RoJ1xuICAgICAqL1xuICAgIHZhciBwcm9wcyA9IF9jdXJyeTIoZnVuY3Rpb24gcHJvcHMocHMsIG9iaikge1xuICAgICAgICB2YXIgbGVuID0gcHMubGVuZ3RoO1xuICAgICAgICB2YXIgb3V0ID0gW107XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICBvdXRbaWR4XSA9IG9ialtwc1tpZHhdXTtcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbGlzdCBvZiBudW1iZXJzIGZyb20gYGZyb21gIChpbmNsdXNpdmUpIHRvIGB0b2AgKGV4Y2x1c2l2ZSkuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBOdW1iZXIgLT4gTnVtYmVyIC0+IFtOdW1iZXJdXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGZyb20gVGhlIGZpcnN0IG51bWJlciBpbiB0aGUgbGlzdC5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gdG8gT25lIG1vcmUgdGhhbiB0aGUgbGFzdCBudW1iZXIgaW4gdGhlIGxpc3QuXG4gICAgICogQHJldHVybiB7QXJyYXl9IFRoZSBsaXN0IG9mIG51bWJlcnMgaW4gdHRoZSBzZXQgYFthLCBiKWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5yYW5nZSgxLCA1KTsgICAgLy89PiBbMSwgMiwgMywgNF1cbiAgICAgKiAgICAgIFIucmFuZ2UoNTAsIDUzKTsgIC8vPT4gWzUwLCA1MSwgNTJdXG4gICAgICovXG4gICAgdmFyIHJhbmdlID0gX2N1cnJ5MihmdW5jdGlvbiByYW5nZShmcm9tLCB0bykge1xuICAgICAgICBpZiAoIShfaXNOdW1iZXIoZnJvbSkgJiYgX2lzTnVtYmVyKHRvKSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0JvdGggYXJndW1lbnRzIHRvIHJhbmdlIG11c3QgYmUgbnVtYmVycycpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdmFyIG4gPSBmcm9tO1xuICAgICAgICB3aGlsZSAobiA8IHRvKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaChuKTtcbiAgICAgICAgICAgIG4gKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHNpbmdsZSBpdGVtIGJ5IGl0ZXJhdGluZyB0aHJvdWdoIHRoZSBsaXN0LCBzdWNjZXNzaXZlbHkgY2FsbGluZ1xuICAgICAqIHRoZSBpdGVyYXRvciBmdW5jdGlvbiBhbmQgcGFzc2luZyBpdCBhbiBhY2N1bXVsYXRvciB2YWx1ZSBhbmQgdGhlIGN1cnJlbnRcbiAgICAgKiB2YWx1ZSBmcm9tIHRoZSBhcnJheSwgYW5kIHRoZW4gcGFzc2luZyB0aGUgcmVzdWx0IHRvIHRoZSBuZXh0IGNhbGwuXG4gICAgICpcbiAgICAgKiBTaW1pbGFyIHRvIGByZWR1Y2VgLCBleGNlcHQgbW92ZXMgdGhyb3VnaCB0aGUgaW5wdXQgbGlzdCBmcm9tIHRoZSByaWdodCB0b1xuICAgICAqIHRoZSBsZWZ0LlxuICAgICAqXG4gICAgICogVGhlIGl0ZXJhdG9yIGZ1bmN0aW9uIHJlY2VpdmVzIHR3byB2YWx1ZXM6ICooYWNjLCB2YWx1ZSkqXG4gICAgICpcbiAgICAgKiBOb3RlOiBgUi5yZWR1Y2VSaWdodGAgZG9lcyBub3Qgc2tpcCBkZWxldGVkIG9yIHVuYXNzaWduZWQgaW5kaWNlcyAoc3BhcnNlXG4gICAgICogYXJyYXlzKSwgdW5saWtlIHRoZSBuYXRpdmUgYEFycmF5LnByb3RvdHlwZS5yZWR1Y2VgIG1ldGhvZC4gRm9yIG1vcmUgZGV0YWlsc1xuICAgICAqIG9uIHRoaXMgYmVoYXZpb3IsIHNlZTpcbiAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9yZWR1Y2VSaWdodCNEZXNjcmlwdGlvblxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEsYiAtPiBhKSAtPiBhIC0+IFtiXSAtPiBhXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLiBSZWNlaXZlcyB0d28gdmFsdWVzLCB0aGUgYWNjdW11bGF0b3IgYW5kIHRoZVxuICAgICAqICAgICAgICBjdXJyZW50IGVsZW1lbnQgZnJvbSB0aGUgYXJyYXkuXG4gICAgICogQHBhcmFtIHsqfSBhY2MgVGhlIGFjY3VtdWxhdG9yIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBmaW5hbCwgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQHNlZSBSLmFkZEluZGV4XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHBhaXJzID0gWyBbJ2EnLCAxXSwgWydiJywgMl0sIFsnYycsIDNdIF07XG4gICAgICogICAgICB2YXIgZmxhdHRlblBhaXJzID0gKGFjYywgcGFpcikgPT4gYWNjLmNvbmNhdChwYWlyKTtcbiAgICAgKlxuICAgICAqICAgICAgUi5yZWR1Y2VSaWdodChmbGF0dGVuUGFpcnMsIFtdLCBwYWlycyk7IC8vPT4gWyAnYycsIDMsICdiJywgMiwgJ2EnLCAxIF1cbiAgICAgKi9cbiAgICB2YXIgcmVkdWNlUmlnaHQgPSBfY3VycnkzKGZ1bmN0aW9uIHJlZHVjZVJpZ2h0KGZuLCBhY2MsIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IGxpc3QubGVuZ3RoIC0gMTtcbiAgICAgICAgd2hpbGUgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICBhY2MgPSBmbihhY2MsIGxpc3RbaWR4XSk7XG4gICAgICAgICAgICBpZHggLT0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWNjO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHZhbHVlIHdyYXBwZWQgdG8gaW5kaWNhdGUgdGhhdCBpdCBpcyB0aGUgZmluYWwgdmFsdWUgb2YgdGhlIHJlZHVjZVxuICAgICAqIGFuZCB0cmFuc2R1Y2UgZnVuY3Rpb25zLiBUaGUgcmV0dXJuZWQgdmFsdWUgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYSBibGFja1xuICAgICAqIGJveDogdGhlIGludGVybmFsIHN0cnVjdHVyZSBpcyBub3QgZ3VhcmFudGVlZCB0byBiZSBzdGFibGUuXG4gICAgICpcbiAgICAgKiBOb3RlOiB0aGlzIG9wdGltaXphdGlvbiBpcyB1bmF2YWlsYWJsZSB0byBmdW5jdGlvbnMgbm90IGV4cGxpY2l0bHkgbGlzdGVkXG4gICAgICogYWJvdmUuIEZvciBpbnN0YW5jZSwgaXQgaXMgbm90IGN1cnJlbnRseSBzdXBwb3J0ZWQgYnkgcmVkdWNlUmlnaHQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE1LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgYSAtPiAqXG4gICAgICogQHBhcmFtIHsqfSB4IFRoZSBmaW5hbCB2YWx1ZSBvZiB0aGUgcmVkdWNlLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSB3cmFwcGVkIHZhbHVlLlxuICAgICAqIEBzZWUgUi5yZWR1Y2UsIFIudHJhbnNkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5yZWR1Y2UoXG4gICAgICogICAgICAgIFIucGlwZShSLmFkZCwgUi53aGVuKFIuZ3RlKFIuX18sIDEwKSwgUi5yZWR1Y2VkKSksXG4gICAgICogICAgICAgIDAsXG4gICAgICogICAgICAgIFsxLCAyLCAzLCA0LCA1XSkgLy8gMTBcbiAgICAgKi9cbiAgICB2YXIgcmVkdWNlZCA9IF9jdXJyeTEoX3JlZHVjZWQpO1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgc3ViLWxpc3Qgb2YgYGxpc3RgIHN0YXJ0aW5nIGF0IGluZGV4IGBzdGFydGAgYW5kIGNvbnRhaW5pbmdcbiAgICAgKiBgY291bnRgIGVsZW1lbnRzLiBfTm90ZSB0aGF0IHRoaXMgaXMgbm90IGRlc3RydWN0aXZlXzogaXQgcmV0dXJucyBhIGNvcHkgb2ZcbiAgICAgKiB0aGUgbGlzdCB3aXRoIHRoZSBjaGFuZ2VzLlxuICAgICAqIDxzbWFsbD5ObyBsaXN0cyBoYXZlIGJlZW4gaGFybWVkIGluIHRoZSBhcHBsaWNhdGlvbiBvZiB0aGlzIGZ1bmN0aW9uLjwvc21hbGw+XG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjIuMlxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBOdW1iZXIgLT4gTnVtYmVyIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gc3RhcnQgVGhlIHBvc2l0aW9uIHRvIHN0YXJ0IHJlbW92aW5nIGVsZW1lbnRzXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGNvdW50IFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gcmVtb3ZlXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byByZW1vdmUgZnJvbVxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBIG5ldyBBcnJheSB3aXRoIGBjb3VudGAgZWxlbWVudHMgZnJvbSBgc3RhcnRgIHJlbW92ZWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5yZW1vdmUoMiwgMywgWzEsMiwzLDQsNSw2LDcsOF0pOyAvLz0+IFsxLDIsNiw3LDhdXG4gICAgICovXG4gICAgdmFyIHJlbW92ZSA9IF9jdXJyeTMoZnVuY3Rpb24gcmVtb3ZlKHN0YXJ0LCBjb3VudCwgbGlzdCkge1xuICAgICAgICByZXR1cm4gX2NvbmNhdChfc2xpY2UobGlzdCwgMCwgTWF0aC5taW4oc3RhcnQsIGxpc3QubGVuZ3RoKSksIF9zbGljZShsaXN0LCBNYXRoLm1pbihsaXN0Lmxlbmd0aCwgc3RhcnQgKyBjb3VudCkpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJlcGxhY2UgYSBzdWJzdHJpbmcgb3IgcmVnZXggbWF0Y2ggaW4gYSBzdHJpbmcgd2l0aCBhIHJlcGxhY2VtZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHNpZyBSZWdFeHB8U3RyaW5nIC0+IFN0cmluZyAtPiBTdHJpbmcgLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBwYXR0ZXJuIEEgcmVndWxhciBleHByZXNzaW9uIG9yIGEgc3Vic3RyaW5nIHRvIG1hdGNoLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSByZXBsYWNlbWVudCBUaGUgc3RyaW5nIHRvIHJlcGxhY2UgdGhlIG1hdGNoZXMgd2l0aC5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBTdHJpbmcgdG8gZG8gdGhlIHNlYXJjaCBhbmQgcmVwbGFjZW1lbnQgaW4uXG4gICAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgcmVzdWx0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucmVwbGFjZSgnZm9vJywgJ2JhcicsICdmb28gZm9vIGZvbycpOyAvLz0+ICdiYXIgZm9vIGZvbydcbiAgICAgKiAgICAgIFIucmVwbGFjZSgvZm9vLywgJ2JhcicsICdmb28gZm9vIGZvbycpOyAvLz0+ICdiYXIgZm9vIGZvbydcbiAgICAgKlxuICAgICAqICAgICAgLy8gVXNlIHRoZSBcImdcIiAoZ2xvYmFsKSBmbGFnIHRvIHJlcGxhY2UgYWxsIG9jY3VycmVuY2VzOlxuICAgICAqICAgICAgUi5yZXBsYWNlKC9mb28vZywgJ2JhcicsICdmb28gZm9vIGZvbycpOyAvLz0+ICdiYXIgYmFyIGJhcidcbiAgICAgKi9cbiAgICB2YXIgcmVwbGFjZSA9IF9jdXJyeTMoZnVuY3Rpb24gcmVwbGFjZShyZWdleCwgcmVwbGFjZW1lbnQsIHN0cikge1xuICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UocmVnZXgsIHJlcGxhY2VtZW50KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgbGlzdCBvciBzdHJpbmcgd2l0aCB0aGUgZWxlbWVudHMgb3IgY2hhcmFjdGVycyBpbiByZXZlcnNlXG4gICAgICogb3JkZXIuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBbYV0gLT4gW2FdXG4gICAgICogQHNpZyBTdHJpbmcgLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHtBcnJheXxTdHJpbmd9IGxpc3RcbiAgICAgKiBAcmV0dXJuIHtBcnJheXxTdHJpbmd9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5yZXZlcnNlKFsxLCAyLCAzXSk7ICAvLz0+IFszLCAyLCAxXVxuICAgICAqICAgICAgUi5yZXZlcnNlKFsxLCAyXSk7ICAgICAvLz0+IFsyLCAxXVxuICAgICAqICAgICAgUi5yZXZlcnNlKFsxXSk7ICAgICAgICAvLz0+IFsxXVxuICAgICAqICAgICAgUi5yZXZlcnNlKFtdKTsgICAgICAgICAvLz0+IFtdXG4gICAgICpcbiAgICAgKiAgICAgIFIucmV2ZXJzZSgnYWJjJyk7ICAgICAgLy89PiAnY2JhJ1xuICAgICAqICAgICAgUi5yZXZlcnNlKCdhYicpOyAgICAgICAvLz0+ICdiYSdcbiAgICAgKiAgICAgIFIucmV2ZXJzZSgnYScpOyAgICAgICAgLy89PiAnYSdcbiAgICAgKiAgICAgIFIucmV2ZXJzZSgnJyk7ICAgICAgICAgLy89PiAnJ1xuICAgICAqL1xuICAgIHZhciByZXZlcnNlID0gX2N1cnJ5MShmdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgICAgICAgcmV0dXJuIF9pc1N0cmluZyhsaXN0KSA/IGxpc3Quc3BsaXQoJycpLnJldmVyc2UoKS5qb2luKCcnKSA6IF9zbGljZShsaXN0KS5yZXZlcnNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBTY2FuIGlzIHNpbWlsYXIgdG8gcmVkdWNlLCBidXQgcmV0dXJucyBhIGxpc3Qgb2Ygc3VjY2Vzc2l2ZWx5IHJlZHVjZWQgdmFsdWVzXG4gICAgICogZnJvbSB0aGUgbGVmdFxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMC4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhLGIgLT4gYSkgLT4gYSAtPiBbYl0gLT4gW2FdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLiBSZWNlaXZlcyB0d28gdmFsdWVzLCB0aGUgYWNjdW11bGF0b3IgYW5kIHRoZVxuICAgICAqICAgICAgICBjdXJyZW50IGVsZW1lbnQgZnJvbSB0aGUgYXJyYXlcbiAgICAgKiBAcGFyYW0geyp9IGFjYyBUaGUgYWNjdW11bGF0b3IgdmFsdWUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybiB7QXJyYXl9IEEgbGlzdCBvZiBhbGwgaW50ZXJtZWRpYXRlbHkgcmVkdWNlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG51bWJlcnMgPSBbMSwgMiwgMywgNF07XG4gICAgICogICAgICB2YXIgZmFjdG9yaWFscyA9IFIuc2NhbihSLm11bHRpcGx5LCAxLCBudW1iZXJzKTsgLy89PiBbMSwgMSwgMiwgNiwgMjRdXG4gICAgICovXG4gICAgdmFyIHNjYW4gPSBfY3VycnkzKGZ1bmN0aW9uIHNjYW4oZm4sIGFjYywgbGlzdCkge1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB2YXIgcmVzdWx0ID0gW2FjY107XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgIGFjYyA9IGZuKGFjYywgbGlzdFtpZHhdKTtcbiAgICAgICAgICAgIHJlc3VsdFtpZHggKyAxXSA9IGFjYztcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByZXN1bHQgb2YgXCJzZXR0aW5nXCIgdGhlIHBvcnRpb24gb2YgdGhlIGdpdmVuIGRhdGEgc3RydWN0dXJlXG4gICAgICogZm9jdXNlZCBieSB0aGUgZ2l2ZW4gbGVucyB0byB0aGUgZ2l2ZW4gdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE2LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHR5cGVkZWZuIExlbnMgcyBhID0gRnVuY3RvciBmID0+IChhIC0+IGYgYSkgLT4gcyAtPiBmIHNcbiAgICAgKiBAc2lnIExlbnMgcyBhIC0+IGEgLT4gcyAtPiBzXG4gICAgICogQHBhcmFtIHtMZW5zfSBsZW5zXG4gICAgICogQHBhcmFtIHsqfSB2XG4gICAgICogQHBhcmFtIHsqfSB4XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIucHJvcCwgUi5sZW5zSW5kZXgsIFIubGVuc1Byb3BcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgeExlbnMgPSBSLmxlbnNQcm9wKCd4Jyk7XG4gICAgICpcbiAgICAgKiAgICAgIFIuc2V0KHhMZW5zLCA0LCB7eDogMSwgeTogMn0pOyAgLy89PiB7eDogNCwgeTogMn1cbiAgICAgKiAgICAgIFIuc2V0KHhMZW5zLCA4LCB7eDogMSwgeTogMn0pOyAgLy89PiB7eDogOCwgeTogMn1cbiAgICAgKi9cbiAgICB2YXIgc2V0ID0gX2N1cnJ5MyhmdW5jdGlvbiBzZXQobGVucywgdiwgeCkge1xuICAgICAgICByZXR1cm4gb3ZlcihsZW5zLCBhbHdheXModiksIHgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZWxlbWVudHMgb2YgdGhlIGdpdmVuIGxpc3Qgb3Igc3RyaW5nIChvciBvYmplY3Qgd2l0aCBhIGBzbGljZWBcbiAgICAgKiBtZXRob2QpIGZyb20gYGZyb21JbmRleGAgKGluY2x1c2l2ZSkgdG8gYHRvSW5kZXhgIChleGNsdXNpdmUpLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYHNsaWNlYCBtZXRob2Qgb2YgdGhlIHRoaXJkIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjRcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IE51bWJlciAtPiBbYV0gLT4gW2FdXG4gICAgICogQHNpZyBOdW1iZXIgLT4gTnVtYmVyIC0+IFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gZnJvbUluZGV4IFRoZSBzdGFydCBpbmRleCAoaW5jbHVzaXZlKS5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gdG9JbmRleCBUaGUgZW5kIGluZGV4IChleGNsdXNpdmUpLlxuICAgICAqIEBwYXJhbSB7Kn0gbGlzdFxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5zbGljZSgxLCAzLCBbJ2EnLCAnYicsICdjJywgJ2QnXSk7ICAgICAgICAvLz0+IFsnYicsICdjJ11cbiAgICAgKiAgICAgIFIuc2xpY2UoMSwgSW5maW5pdHksIFsnYScsICdiJywgJ2MnLCAnZCddKTsgLy89PiBbJ2InLCAnYycsICdkJ11cbiAgICAgKiAgICAgIFIuc2xpY2UoMCwgLTEsIFsnYScsICdiJywgJ2MnLCAnZCddKTsgICAgICAgLy89PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKiAgICAgIFIuc2xpY2UoLTMsIC0xLCBbJ2EnLCAnYicsICdjJywgJ2QnXSk7ICAgICAgLy89PiBbJ2InLCAnYyddXG4gICAgICogICAgICBSLnNsaWNlKDAsIDMsICdyYW1kYScpOyAgICAgICAgICAgICAgICAgICAgIC8vPT4gJ3JhbSdcbiAgICAgKi9cbiAgICB2YXIgc2xpY2UgPSBfY3VycnkzKF9jaGVja0Zvck1ldGhvZCgnc2xpY2UnLCBmdW5jdGlvbiBzbGljZShmcm9tSW5kZXgsIHRvSW5kZXgsIGxpc3QpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGxpc3QsIGZyb21JbmRleCwgdG9JbmRleCk7XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGNvcHkgb2YgdGhlIGxpc3QsIHNvcnRlZCBhY2NvcmRpbmcgdG8gdGhlIGNvbXBhcmF0b3IgZnVuY3Rpb24sXG4gICAgICogd2hpY2ggc2hvdWxkIGFjY2VwdCB0d28gdmFsdWVzIGF0IGEgdGltZSBhbmQgcmV0dXJuIGEgbmVnYXRpdmUgbnVtYmVyIGlmIHRoZVxuICAgICAqIGZpcnN0IHZhbHVlIGlzIHNtYWxsZXIsIGEgcG9zaXRpdmUgbnVtYmVyIGlmIGl0J3MgbGFyZ2VyLCBhbmQgemVybyBpZiB0aGV5XG4gICAgICogYXJlIGVxdWFsLiBQbGVhc2Ugbm90ZSB0aGF0IHRoaXMgaXMgYSAqKmNvcHkqKiBvZiB0aGUgbGlzdC4gSXQgZG9lcyBub3RcbiAgICAgKiBtb2RpZnkgdGhlIG9yaWdpbmFsLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEsYSAtPiBOdW1iZXIpIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb21wYXJhdG9yIEEgc29ydGluZyBmdW5jdGlvbiA6OiBhIC0+IGIgLT4gSW50XG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byBzb3J0XG4gICAgICogQHJldHVybiB7QXJyYXl9IGEgbmV3IGFycmF5IHdpdGggaXRzIGVsZW1lbnRzIHNvcnRlZCBieSB0aGUgY29tcGFyYXRvciBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZGlmZiA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEgLSBiOyB9O1xuICAgICAqICAgICAgUi5zb3J0KGRpZmYsIFs0LDIsNyw1XSk7IC8vPT4gWzIsIDQsIDUsIDddXG4gICAgICovXG4gICAgdmFyIHNvcnQgPSBfY3VycnkyKGZ1bmN0aW9uIHNvcnQoY29tcGFyYXRvciwgbGlzdCkge1xuICAgICAgICByZXR1cm4gX3NsaWNlKGxpc3QpLnNvcnQoY29tcGFyYXRvcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBTb3J0cyB0aGUgbGlzdCBhY2NvcmRpbmcgdG8gdGhlIHN1cHBsaWVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgUmVsYXRpb25cbiAgICAgKiBAc2lnIE9yZCBiID0+IChhIC0+IGIpIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gc29ydC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcgbGlzdCBzb3J0ZWQgYnkgdGhlIGtleXMgZ2VuZXJhdGVkIGJ5IGBmbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHNvcnRCeUZpcnN0SXRlbSA9IFIuc29ydEJ5KFIucHJvcCgwKSk7XG4gICAgICogICAgICB2YXIgc29ydEJ5TmFtZUNhc2VJbnNlbnNpdGl2ZSA9IFIuc29ydEJ5KFIuY29tcG9zZShSLnRvTG93ZXIsIFIucHJvcCgnbmFtZScpKSk7XG4gICAgICogICAgICB2YXIgcGFpcnMgPSBbWy0xLCAxXSwgWy0yLCAyXSwgWy0zLCAzXV07XG4gICAgICogICAgICBzb3J0QnlGaXJzdEl0ZW0ocGFpcnMpOyAvLz0+IFtbLTMsIDNdLCBbLTIsIDJdLCBbLTEsIDFdXVxuICAgICAqICAgICAgdmFyIGFsaWNlID0ge1xuICAgICAqICAgICAgICBuYW1lOiAnQUxJQ0UnLFxuICAgICAqICAgICAgICBhZ2U6IDEwMVxuICAgICAqICAgICAgfTtcbiAgICAgKiAgICAgIHZhciBib2IgPSB7XG4gICAgICogICAgICAgIG5hbWU6ICdCb2InLFxuICAgICAqICAgICAgICBhZ2U6IC0xMFxuICAgICAqICAgICAgfTtcbiAgICAgKiAgICAgIHZhciBjbGFyYSA9IHtcbiAgICAgKiAgICAgICAgbmFtZTogJ2NsYXJhJyxcbiAgICAgKiAgICAgICAgYWdlOiAzMTQuMTU5XG4gICAgICogICAgICB9O1xuICAgICAqICAgICAgdmFyIHBlb3BsZSA9IFtjbGFyYSwgYm9iLCBhbGljZV07XG4gICAgICogICAgICBzb3J0QnlOYW1lQ2FzZUluc2Vuc2l0aXZlKHBlb3BsZSk7IC8vPT4gW2FsaWNlLCBib2IsIGNsYXJhXVxuICAgICAqL1xuICAgIHZhciBzb3J0QnkgPSBfY3VycnkyKGZ1bmN0aW9uIHNvcnRCeShmbiwgbGlzdCkge1xuICAgICAgICByZXR1cm4gX3NsaWNlKGxpc3QpLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIHZhciBhYSA9IGZuKGEpO1xuICAgICAgICAgICAgdmFyIGJiID0gZm4oYik7XG4gICAgICAgICAgICByZXR1cm4gYWEgPCBiYiA/IC0xIDogYWEgPiBiYiA/IDEgOiAwO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBhIGdpdmVuIGxpc3Qgb3Igc3RyaW5nIGF0IGEgZ2l2ZW4gaW5kZXguXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IFthXSAtPiBbW2FdLCBbYV1dXG4gICAgICogQHNpZyBOdW1iZXIgLT4gU3RyaW5nIC0+IFtTdHJpbmcsIFN0cmluZ11cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXggVGhlIGluZGV4IHdoZXJlIHRoZSBhcnJheS9zdHJpbmcgaXMgc3BsaXQuXG4gICAgICogQHBhcmFtIHtBcnJheXxTdHJpbmd9IGFycmF5IFRoZSBhcnJheS9zdHJpbmcgdG8gYmUgc3BsaXQuXG4gICAgICogQHJldHVybiB7QXJyYXl9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5zcGxpdEF0KDEsIFsxLCAyLCAzXSk7ICAgICAgICAgIC8vPT4gW1sxXSwgWzIsIDNdXVxuICAgICAqICAgICAgUi5zcGxpdEF0KDUsICdoZWxsbyB3b3JsZCcpOyAgICAgIC8vPT4gWydoZWxsbycsICcgd29ybGQnXVxuICAgICAqICAgICAgUi5zcGxpdEF0KC0xLCAnZm9vYmFyJyk7ICAgICAgICAgIC8vPT4gWydmb29iYScsICdyJ11cbiAgICAgKi9cbiAgICB2YXIgc3BsaXRBdCA9IF9jdXJyeTIoZnVuY3Rpb24gc3BsaXRBdChpbmRleCwgYXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHNsaWNlKDAsIGluZGV4LCBhcnJheSksXG4gICAgICAgICAgICBzbGljZShpbmRleCwgbGVuZ3RoKGFycmF5KSwgYXJyYXkpXG4gICAgICAgIF07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBTcGxpdHMgYSBjb2xsZWN0aW9uIGludG8gc2xpY2VzIG9mIHRoZSBzcGVjaWZpZWQgbGVuZ3RoLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNi4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIE51bWJlciAtPiBbYV0gLT4gW1thXV1cbiAgICAgKiBAc2lnIE51bWJlciAtPiBTdHJpbmcgLT4gW1N0cmluZ11cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gblxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3RcbiAgICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnNwbGl0RXZlcnkoMywgWzEsIDIsIDMsIDQsIDUsIDYsIDddKTsgLy89PiBbWzEsIDIsIDNdLCBbNCwgNSwgNl0sIFs3XV1cbiAgICAgKiAgICAgIFIuc3BsaXRFdmVyeSgzLCAnZm9vYmFyYmF6Jyk7IC8vPT4gWydmb28nLCAnYmFyJywgJ2JheiddXG4gICAgICovXG4gICAgdmFyIHNwbGl0RXZlcnkgPSBfY3VycnkyKGZ1bmN0aW9uIHNwbGl0RXZlcnkobiwgbGlzdCkge1xuICAgICAgICBpZiAobiA8PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IHRvIHNwbGl0RXZlcnkgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXInKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHNsaWNlKGlkeCwgaWR4ICs9IG4sIGxpc3QpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IGFuZCBhIHByZWRpY2F0ZSBhbmQgcmV0dXJucyBhIHBhaXIgb2YgbGlzdHMgd2l0aCB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gICAgICpcbiAgICAgKiAgLSB0aGUgcmVzdWx0IG9mIGNvbmNhdGVuYXRpbmcgdGhlIHR3byBvdXRwdXQgbGlzdHMgaXMgZXF1aXZhbGVudCB0byB0aGUgaW5wdXQgbGlzdDtcbiAgICAgKiAgLSBub25lIG9mIHRoZSBlbGVtZW50cyBvZiB0aGUgZmlyc3Qgb3V0cHV0IGxpc3Qgc2F0aXNmaWVzIHRoZSBwcmVkaWNhdGU7IGFuZFxuICAgICAqICAtIGlmIHRoZSBzZWNvbmQgb3V0cHV0IGxpc3QgaXMgbm9uLWVtcHR5LCBpdHMgZmlyc3QgZWxlbWVudCBzYXRpc2ZpZXMgdGhlIHByZWRpY2F0ZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTkuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoYSAtPiBCb29sZWFuKSAtPiBbYV0gLT4gW1thXSwgW2FdXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWQgVGhlIHByZWRpY2F0ZSB0aGF0IGRldGVybWluZXMgd2hlcmUgdGhlIGFycmF5IGlzIHNwbGl0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGFycmF5IHRvIGJlIHNwbGl0LlxuICAgICAqIEByZXR1cm4ge0FycmF5fVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuc3BsaXRXaGVuKFIuZXF1YWxzKDIpLCBbMSwgMiwgMywgMSwgMiwgM10pOyAgIC8vPT4gW1sxXSwgWzIsIDMsIDEsIDIsIDNdXVxuICAgICAqL1xuICAgIHZhciBzcGxpdFdoZW4gPSBfY3VycnkyKGZ1bmN0aW9uIHNwbGl0V2hlbihwcmVkLCBsaXN0KSB7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgbGVuID0gbGlzdC5sZW5ndGg7XG4gICAgICAgIHZhciBwcmVmaXggPSBbXTtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbiAmJiAhcHJlZChsaXN0W2lkeF0pKSB7XG4gICAgICAgICAgICBwcmVmaXgucHVzaChsaXN0W2lkeF0pO1xuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHByZWZpeCxcbiAgICAgICAgICAgIF9zbGljZShsaXN0LCBpZHgpXG4gICAgICAgIF07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJ0cmFjdHMgaXRzIHNlY29uZCBhcmd1bWVudCBmcm9tIGl0cyBmaXJzdCBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIE51bWJlciAtPiBOdW1iZXIgLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGEgVGhlIGZpcnN0IHZhbHVlLlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBiIFRoZSBzZWNvbmQgdmFsdWUuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBUaGUgcmVzdWx0IG9mIGBhIC0gYmAuXG4gICAgICogQHNlZSBSLmFkZFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuc3VidHJhY3QoMTAsIDgpOyAvLz0+IDJcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG1pbnVzNSA9IFIuc3VidHJhY3QoUi5fXywgNSk7XG4gICAgICogICAgICBtaW51czUoMTcpOyAvLz0+IDEyXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBjb21wbGVtZW50YXJ5QW5nbGUgPSBSLnN1YnRyYWN0KDkwKTtcbiAgICAgKiAgICAgIGNvbXBsZW1lbnRhcnlBbmdsZSgzMCk7IC8vPT4gNjBcbiAgICAgKiAgICAgIGNvbXBsZW1lbnRhcnlBbmdsZSg3Mik7IC8vPT4gMThcbiAgICAgKi9cbiAgICB2YXIgc3VidHJhY3QgPSBfY3VycnkyKGZ1bmN0aW9uIHN1YnRyYWN0KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlcihhKSAtIE51bWJlcihiKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYWxsIGJ1dCB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgZ2l2ZW4gbGlzdCBvciBzdHJpbmcgKG9yIG9iamVjdFxuICAgICAqIHdpdGggYSBgdGFpbGAgbWV0aG9kKS5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBzbGljZWAgbWV0aG9kIG9mIHRoZSBmaXJzdCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIFthXSAtPiBbYV1cbiAgICAgKiBAc2lnIFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0geyp9IGxpc3RcbiAgICAgKiBAcmV0dXJuIHsqfVxuICAgICAqIEBzZWUgUi5oZWFkLCBSLmluaXQsIFIubGFzdFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudGFpbChbMSwgMiwgM10pOyAgLy89PiBbMiwgM11cbiAgICAgKiAgICAgIFIudGFpbChbMSwgMl0pOyAgICAgLy89PiBbMl1cbiAgICAgKiAgICAgIFIudGFpbChbMV0pOyAgICAgICAgLy89PiBbXVxuICAgICAqICAgICAgUi50YWlsKFtdKTsgICAgICAgICAvLz0+IFtdXG4gICAgICpcbiAgICAgKiAgICAgIFIudGFpbCgnYWJjJyk7ICAvLz0+ICdiYydcbiAgICAgKiAgICAgIFIudGFpbCgnYWInKTsgICAvLz0+ICdiJ1xuICAgICAqICAgICAgUi50YWlsKCdhJyk7ICAgIC8vPT4gJydcbiAgICAgKiAgICAgIFIudGFpbCgnJyk7ICAgICAvLz0+ICcnXG4gICAgICovXG4gICAgdmFyIHRhaWwgPSBfY2hlY2tGb3JNZXRob2QoJ3RhaWwnLCBzbGljZSgxLCBJbmZpbml0eSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZmlyc3QgYG5gIGVsZW1lbnRzIG9mIHRoZSBnaXZlbiBsaXN0LCBzdHJpbmcsIG9yXG4gICAgICogdHJhbnNkdWNlci90cmFuc2Zvcm1lciAob3Igb2JqZWN0IHdpdGggYSBgdGFrZWAgbWV0aG9kKS5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGB0YWtlYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIE51bWJlciAtPiBbYV0gLT4gW2FdXG4gICAgICogQHNpZyBOdW1iZXIgLT4gU3RyaW5nIC0+IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gICAgICogQHBhcmFtIHsqfSBsaXN0XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIuZHJvcFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudGFrZSgxLCBbJ2ZvbycsICdiYXInLCAnYmF6J10pOyAvLz0+IFsnZm9vJ11cbiAgICAgKiAgICAgIFIudGFrZSgyLCBbJ2ZvbycsICdiYXInLCAnYmF6J10pOyAvLz0+IFsnZm9vJywgJ2JhciddXG4gICAgICogICAgICBSLnRha2UoMywgWydmb28nLCAnYmFyJywgJ2JheiddKTsgLy89PiBbJ2ZvbycsICdiYXInLCAnYmF6J11cbiAgICAgKiAgICAgIFIudGFrZSg0LCBbJ2ZvbycsICdiYXInLCAnYmF6J10pOyAvLz0+IFsnZm9vJywgJ2JhcicsICdiYXonXVxuICAgICAqICAgICAgUi50YWtlKDMsICdyYW1kYScpOyAgICAgICAgICAgICAgIC8vPT4gJ3JhbSdcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHBlcnNvbm5lbCA9IFtcbiAgICAgKiAgICAgICAgJ0RhdmUgQnJ1YmVjaycsXG4gICAgICogICAgICAgICdQYXVsIERlc21vbmQnLFxuICAgICAqICAgICAgICAnRXVnZW5lIFdyaWdodCcsXG4gICAgICogICAgICAgICdKb2UgTW9yZWxsbycsXG4gICAgICogICAgICAgICdHZXJyeSBNdWxsaWdhbicsXG4gICAgICogICAgICAgICdCb2IgQmF0ZXMnLFxuICAgICAqICAgICAgICAnSm9lIERvZGdlJyxcbiAgICAgKiAgICAgICAgJ1JvbiBDcm90dHknXG4gICAgICogICAgICBdO1xuICAgICAqXG4gICAgICogICAgICB2YXIgdGFrZUZpdmUgPSBSLnRha2UoNSk7XG4gICAgICogICAgICB0YWtlRml2ZShwZXJzb25uZWwpO1xuICAgICAqICAgICAgLy89PiBbJ0RhdmUgQnJ1YmVjaycsICdQYXVsIERlc21vbmQnLCAnRXVnZW5lIFdyaWdodCcsICdKb2UgTW9yZWxsbycsICdHZXJyeSBNdWxsaWdhbiddXG4gICAgICovXG4gICAgdmFyIHRha2UgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ3Rha2UnLCBfeHRha2UsIGZ1bmN0aW9uIHRha2UobiwgeHMpIHtcbiAgICAgICAgcmV0dXJuIHNsaWNlKDAsIG4gPCAwID8gSW5maW5pdHkgOiBuLCB4cyk7XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IGNvbnRhaW5pbmcgdGhlIGxhc3QgYG5gIGVsZW1lbnRzIG9mIGEgZ2l2ZW4gbGlzdCwgcGFzc2luZ1xuICAgICAqIGVhY2ggdmFsdWUgdG8gdGhlIHN1cHBsaWVkIHByZWRpY2F0ZSBmdW5jdGlvbiwgYW5kIHRlcm1pbmF0aW5nIHdoZW4gdGhlXG4gICAgICogcHJlZGljYXRlIGZ1bmN0aW9uIHJldHVybnMgYGZhbHNlYC4gRXhjbHVkZXMgdGhlIGVsZW1lbnQgdGhhdCBjYXVzZWQgdGhlXG4gICAgICogcHJlZGljYXRlIGZ1bmN0aW9uIHRvIGZhaWwuIFRoZSBwcmVkaWNhdGUgZnVuY3Rpb24gaXMgcGFzc2VkIG9uZSBhcmd1bWVudDpcbiAgICAgKiAqKHZhbHVlKSouXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE2LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEgLT4gQm9vbGVhbikgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcgYXJyYXkuXG4gICAgICogQHNlZSBSLmRyb3BMYXN0V2hpbGUsIFIuYWRkSW5kZXhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNOb3RPbmUgPSB4ID0+IHggIT09IDE7XG4gICAgICpcbiAgICAgKiAgICAgIFIudGFrZUxhc3RXaGlsZShpc05vdE9uZSwgWzEsIDIsIDMsIDRdKTsgLy89PiBbMiwgMywgNF1cbiAgICAgKi9cbiAgICB2YXIgdGFrZUxhc3RXaGlsZSA9IF9jdXJyeTIoZnVuY3Rpb24gdGFrZUxhc3RXaGlsZShmbiwgbGlzdCkge1xuICAgICAgICB2YXIgaWR4ID0gbGlzdC5sZW5ndGggLSAxO1xuICAgICAgICB3aGlsZSAoaWR4ID49IDAgJiYgZm4obGlzdFtpZHhdKSkge1xuICAgICAgICAgICAgaWR4IC09IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9zbGljZShsaXN0LCBpZHggKyAxLCBJbmZpbml0eSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGxpc3QgY29udGFpbmluZyB0aGUgZmlyc3QgYG5gIGVsZW1lbnRzIG9mIGEgZ2l2ZW4gbGlzdCxcbiAgICAgKiBwYXNzaW5nIGVhY2ggdmFsdWUgdG8gdGhlIHN1cHBsaWVkIHByZWRpY2F0ZSBmdW5jdGlvbiwgYW5kIHRlcm1pbmF0aW5nIHdoZW5cbiAgICAgKiB0aGUgcHJlZGljYXRlIGZ1bmN0aW9uIHJldHVybnMgYGZhbHNlYC4gRXhjbHVkZXMgdGhlIGVsZW1lbnQgdGhhdCBjYXVzZWQgdGhlXG4gICAgICogcHJlZGljYXRlIGZ1bmN0aW9uIHRvIGZhaWwuIFRoZSBwcmVkaWNhdGUgZnVuY3Rpb24gaXMgcGFzc2VkIG9uZSBhcmd1bWVudDpcbiAgICAgKiAqKHZhbHVlKSouXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgdGFrZVdoaWxlYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybiB7QXJyYXl9IEEgbmV3IGFycmF5LlxuICAgICAqIEBzZWUgUi5kcm9wV2hpbGUsIFIudHJhbnNkdWNlLCBSLmFkZEluZGV4XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGlzTm90Rm91ciA9IHggPT4geCAhPT0gNDtcbiAgICAgKlxuICAgICAqICAgICAgUi50YWtlV2hpbGUoaXNOb3RGb3VyLCBbMSwgMiwgMywgNCwgMywgMiwgMV0pOyAvLz0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIHZhciB0YWtlV2hpbGUgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ3Rha2VXaGlsZScsIF94dGFrZVdoaWxlLCBmdW5jdGlvbiB0YWtlV2hpbGUoZm4sIGxpc3QpIHtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHZhciBsZW4gPSBsaXN0Lmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGxlbiAmJiBmbihsaXN0W2lkeF0pKSB7XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3NsaWNlKGxpc3QsIDAsIGlkeCk7XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogUnVucyB0aGUgZ2l2ZW4gZnVuY3Rpb24gd2l0aCB0aGUgc3VwcGxpZWQgb2JqZWN0LCB0aGVuIHJldHVybnMgdGhlIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoYSAtPiAqKSAtPiBhIC0+IGFcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aXRoIGB4YC4gVGhlIHJldHVybiB2YWx1ZSBvZiBgZm5gIHdpbGwgYmUgdGhyb3duIGF3YXkuXG4gICAgICogQHBhcmFtIHsqfSB4XG4gICAgICogQHJldHVybiB7Kn0gYHhgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBzYXlYID0geCA9PiBjb25zb2xlLmxvZygneCBpcyAnICsgeCk7XG4gICAgICogICAgICBSLnRhcChzYXlYLCAxMDApOyAvLz0+IDEwMFxuICAgICAqICAgICAgLy8gbG9ncyAneCBpcyAxMDAnXG4gICAgICovXG4gICAgdmFyIHRhcCA9IF9jdXJyeTIoZnVuY3Rpb24gdGFwKGZuLCB4KSB7XG4gICAgICAgIGZuKHgpO1xuICAgICAgICByZXR1cm4geDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENhbGxzIGFuIGlucHV0IGZ1bmN0aW9uIGBuYCB0aW1lcywgcmV0dXJuaW5nIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHJlc3VsdHNcbiAgICAgKiBvZiB0aG9zZSBmdW5jdGlvbiBjYWxscy5cbiAgICAgKlxuICAgICAqIGBmbmAgaXMgcGFzc2VkIG9uZSBhcmd1bWVudDogVGhlIGN1cnJlbnQgdmFsdWUgb2YgYG5gLCB3aGljaCBiZWdpbnMgYXQgYDBgXG4gICAgICogYW5kIGlzIGdyYWR1YWxseSBpbmNyZW1lbnRlZCB0byBgbiAtIDFgLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4yLjNcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKE51bWJlciAtPiBhKSAtPiBOdW1iZXIgLT4gW2FdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGludm9rZS4gUGFzc2VkIG9uZSBhcmd1bWVudCwgdGhlIGN1cnJlbnQgdmFsdWUgb2YgYG5gLlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuIEEgdmFsdWUgYmV0d2VlbiBgMGAgYW5kIGBuIC0gMWAuIEluY3JlbWVudHMgYWZ0ZXIgZWFjaCBmdW5jdGlvbiBjYWxsLlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBjb250YWluaW5nIHRoZSByZXR1cm4gdmFsdWVzIG9mIGFsbCBjYWxscyB0byBgZm5gLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudGltZXMoUi5pZGVudGl0eSwgNSk7IC8vPT4gWzAsIDEsIDIsIDMsIDRdXG4gICAgICovXG4gICAgdmFyIHRpbWVzID0gX2N1cnJ5MihmdW5jdGlvbiB0aW1lcyhmbiwgbikge1xuICAgICAgICB2YXIgbGVuID0gTnVtYmVyKG4pO1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxpc3Q7XG4gICAgICAgIGlmIChsZW4gPCAwIHx8IGlzTmFOKGxlbikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCduIG11c3QgYmUgYSBub24tbmVnYXRpdmUgbnVtYmVyJyk7XG4gICAgICAgIH1cbiAgICAgICAgbGlzdCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICBsaXN0W2lkeF0gPSBmbihpZHgpO1xuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBhbiBvYmplY3QgaW50byBhbiBhcnJheSBvZiBrZXksIHZhbHVlIGFycmF5cy4gT25seSB0aGUgb2JqZWN0J3NcbiAgICAgKiBvd24gcHJvcGVydGllcyBhcmUgdXNlZC5cbiAgICAgKiBOb3RlIHRoYXQgdGhlIG9yZGVyIG9mIHRoZSBvdXRwdXQgYXJyYXkgaXMgbm90IGd1YXJhbnRlZWQgdG8gYmUgY29uc2lzdGVudFxuICAgICAqIGFjcm9zcyBkaWZmZXJlbnQgSlMgcGxhdGZvcm1zLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC40LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyB7U3RyaW5nOiAqfSAtPiBbW1N0cmluZywqXV1cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gZXh0cmFjdCBmcm9tXG4gICAgICogQHJldHVybiB7QXJyYXl9IEFuIGFycmF5IG9mIGtleSwgdmFsdWUgYXJyYXlzIGZyb20gdGhlIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLlxuICAgICAqIEBzZWUgUi5mcm9tUGFpcnNcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnRvUGFpcnMoe2E6IDEsIGI6IDIsIGM6IDN9KTsgLy89PiBbWydhJywgMV0sIFsnYicsIDJdLCBbJ2MnLCAzXV1cbiAgICAgKi9cbiAgICB2YXIgdG9QYWlycyA9IF9jdXJyeTEoZnVuY3Rpb24gdG9QYWlycyhvYmopIHtcbiAgICAgICAgdmFyIHBhaXJzID0gW107XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZiAoX2hhcyhwcm9wLCBvYmopKSB7XG4gICAgICAgICAgICAgICAgcGFpcnNbcGFpcnMubGVuZ3RoXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgcHJvcCxcbiAgICAgICAgICAgICAgICAgICAgb2JqW3Byb3BdXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFpcnM7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBhbiBvYmplY3QgaW50byBhbiBhcnJheSBvZiBrZXksIHZhbHVlIGFycmF5cy4gVGhlIG9iamVjdCdzIG93blxuICAgICAqIHByb3BlcnRpZXMgYW5kIHByb3RvdHlwZSBwcm9wZXJ0aWVzIGFyZSB1c2VkLiBOb3RlIHRoYXQgdGhlIG9yZGVyIG9mIHRoZVxuICAgICAqIG91dHB1dCBhcnJheSBpcyBub3QgZ3VhcmFudGVlZCB0byBiZSBjb25zaXN0ZW50IGFjcm9zcyBkaWZmZXJlbnQgSlNcbiAgICAgKiBwbGF0Zm9ybXMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjQuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAc2lnIHtTdHJpbmc6ICp9IC0+IFtbU3RyaW5nLCpdXVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBleHRyYWN0IGZyb21cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2Yga2V5LCB2YWx1ZSBhcnJheXMgZnJvbSB0aGUgb2JqZWN0J3Mgb3duXG4gICAgICogICAgICAgICBhbmQgcHJvdG90eXBlIHByb3BlcnRpZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIEYgPSBmdW5jdGlvbigpIHsgdGhpcy54ID0gJ1gnOyB9O1xuICAgICAqICAgICAgRi5wcm90b3R5cGUueSA9ICdZJztcbiAgICAgKiAgICAgIHZhciBmID0gbmV3IEYoKTtcbiAgICAgKiAgICAgIFIudG9QYWlyc0luKGYpOyAvLz0+IFtbJ3gnLCdYJ10sIFsneScsJ1knXV1cbiAgICAgKi9cbiAgICB2YXIgdG9QYWlyc0luID0gX2N1cnJ5MShmdW5jdGlvbiB0b1BhaXJzSW4ob2JqKSB7XG4gICAgICAgIHZhciBwYWlycyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIG9iaikge1xuICAgICAgICAgICAgcGFpcnNbcGFpcnMubGVuZ3RoXSA9IFtcbiAgICAgICAgICAgICAgICBwcm9wLFxuICAgICAgICAgICAgICAgIG9ialtwcm9wXVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFpcnM7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUcmFuc3Bvc2VzIHRoZSByb3dzIGFuZCBjb2x1bW5zIG9mIGEgMkQgbGlzdC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIGxpc3Qgb2YgYG5gIGxpc3RzIG9mIGxlbmd0aCBgeGAsXG4gICAgICogcmV0dXJucyBhIGxpc3Qgb2YgYHhgIGxpc3RzIG9mIGxlbmd0aCBgbmAuXG4gICAgICpcbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTkuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBbW2FdXSAtPiBbW2FdXVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgQSAyRCBsaXN0XG4gICAgICogQHJldHVybiB7QXJyYXl9IEEgMkQgbGlzdFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudHJhbnNwb3NlKFtbMSwgJ2EnXSwgWzIsICdiJ10sIFszLCAnYyddXSkgLy89PiBbWzEsIDIsIDNdLCBbJ2EnLCAnYicsICdjJ11dXG4gICAgICogICAgICBSLnRyYW5zcG9zZShbWzEsIDIsIDNdLCBbJ2EnLCAnYicsICdjJ11dKSAvLz0+IFtbMSwgJ2EnXSwgWzIsICdiJ10sIFszLCAnYyddXVxuICAgICAqXG4gICAgICogSWYgc29tZSBvZiB0aGUgcm93cyBhcmUgc2hvcnRlciB0aGFuIHRoZSBmb2xsb3dpbmcgcm93cywgdGhlaXIgZWxlbWVudHMgYXJlIHNraXBwZWQ6XG4gICAgICpcbiAgICAgKiAgICAgIFIudHJhbnNwb3NlKFtbMTAsIDExXSwgWzIwXSwgW10sIFszMCwgMzEsIDMyXV0pIC8vPT4gW1sxMCwgMjAsIDMwXSwgWzExLCAzMV0sIFszMl1dXG4gICAgICovXG4gICAgdmFyIHRyYW5zcG9zZSA9IF9jdXJyeTEoZnVuY3Rpb24gdHJhbnNwb3NlKG91dGVybGlzdCkge1xuICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgd2hpbGUgKGkgPCBvdXRlcmxpc3QubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgaW5uZXJsaXN0ID0gb3V0ZXJsaXN0W2ldO1xuICAgICAgICAgICAgdmFyIGogPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGogPCBpbm5lcmxpc3QubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXN1bHRbal0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtqXSA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXN1bHRbal0ucHVzaChpbm5lcmxpc3Rbal0pO1xuICAgICAgICAgICAgICAgIGogKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyAoc3RyaXBzKSB3aGl0ZXNwYWNlIGZyb20gYm90aCBlbmRzIG9mIHRoZSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjYuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAc2lnIFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IFRyaW1tZWQgdmVyc2lvbiBvZiBgc3RyYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnRyaW0oJyAgIHh5eiAgJyk7IC8vPT4gJ3h5eidcbiAgICAgKiAgICAgIFIubWFwKFIudHJpbSwgUi5zcGxpdCgnLCcsICd4LCB5LCB6JykpOyAvLz0+IFsneCcsICd5JywgJ3onXVxuICAgICAqL1xuICAgIHZhciB0cmltID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgd3MgPSAnXFx0XFxuXFx4MEJcXGZcXHIgXFx4QTBcXHUxNjgwXFx1MTgwRVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDMnICsgJ1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTMwMDBcXHUyMDI4JyArICdcXHUyMDI5XFx1RkVGRic7XG4gICAgICAgIHZhciB6ZXJvV2lkdGggPSAnXFx1MjAwQic7XG4gICAgICAgIHZhciBoYXNQcm90b1RyaW0gPSB0eXBlb2YgU3RyaW5nLnByb3RvdHlwZS50cmltID09PSAnZnVuY3Rpb24nO1xuICAgICAgICBpZiAoIWhhc1Byb3RvVHJpbSB8fCAod3MudHJpbSgpIHx8ICF6ZXJvV2lkdGgudHJpbSgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIF9jdXJyeTEoZnVuY3Rpb24gdHJpbShzdHIpIHtcbiAgICAgICAgICAgICAgICB2YXIgYmVnaW5SeCA9IG5ldyBSZWdFeHAoJ15bJyArIHdzICsgJ11bJyArIHdzICsgJ10qJyk7XG4gICAgICAgICAgICAgICAgdmFyIGVuZFJ4ID0gbmV3IFJlZ0V4cCgnWycgKyB3cyArICddWycgKyB3cyArICddKiQnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoYmVnaW5SeCwgJycpLnJlcGxhY2UoZW5kUngsICcnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIF9jdXJyeTEoZnVuY3Rpb24gdHJpbShzdHIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3RyLnRyaW0oKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSgpO1xuXG4gICAgLyoqXG4gICAgICogYHRyeUNhdGNoYCB0YWtlcyB0d28gZnVuY3Rpb25zLCBhIGB0cnllcmAgYW5kIGEgYGNhdGNoZXJgLiBUaGUgcmV0dXJuZWRcbiAgICAgKiBmdW5jdGlvbiBldmFsdWF0ZXMgdGhlIGB0cnllcmA7IGlmIGl0IGRvZXMgbm90IHRocm93LCBpdCBzaW1wbHkgcmV0dXJucyB0aGVcbiAgICAgKiByZXN1bHQuIElmIHRoZSBgdHJ5ZXJgICpkb2VzKiB0aHJvdywgdGhlIHJldHVybmVkIGZ1bmN0aW9uIGV2YWx1YXRlcyB0aGVcbiAgICAgKiBgY2F0Y2hlcmAgZnVuY3Rpb24gYW5kIHJldHVybnMgaXRzIHJlc3VsdC4gTm90ZSB0aGF0IGZvciBlZmZlY3RpdmVcbiAgICAgKiBjb21wb3NpdGlvbiB3aXRoIHRoaXMgZnVuY3Rpb24sIGJvdGggdGhlIGB0cnllcmAgYW5kIGBjYXRjaGVyYCBmdW5jdGlvbnNcbiAgICAgKiBtdXN0IHJldHVybiB0aGUgc2FtZSB0eXBlIG9mIHJlc3VsdHMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjIwLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICguLi54IC0+IGEpIC0+ICgoZSwgLi4ueCkgLT4gYSkgLT4gKC4uLnggLT4gYSlcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0cnllciBUaGUgZnVuY3Rpb24gdGhhdCBtYXkgdGhyb3cuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2F0Y2hlciBUaGUgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV2YWx1YXRlZCBpZiBgdHJ5ZXJgIHRocm93cy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBuZXcgZnVuY3Rpb24gdGhhdCB3aWxsIGNhdGNoIGV4Y2VwdGlvbnMgYW5kIHNlbmQgdGhlbiB0byB0aGUgY2F0Y2hlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnRyeUNhdGNoKFIucHJvcCgneCcpLCBSLkYpKHt4OiB0cnVlfSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi50cnlDYXRjaChSLnByb3AoJ3gnKSwgUi5GKShudWxsKTsgICAgICAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIHRyeUNhdGNoID0gX2N1cnJ5MihmdW5jdGlvbiBfdHJ5Q2F0Y2godHJ5ZXIsIGNhdGNoZXIpIHtcbiAgICAgICAgcmV0dXJuIF9hcml0eSh0cnllci5sZW5ndGgsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyeWVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhdGNoZXIuYXBwbHkodGhpcywgX2NvbmNhdChbZV0sIGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEdpdmVzIGEgc2luZ2xlLXdvcmQgc3RyaW5nIGRlc2NyaXB0aW9uIG9mIHRoZSAobmF0aXZlKSB0eXBlIG9mIGEgdmFsdWUsXG4gICAgICogcmV0dXJuaW5nIHN1Y2ggYW5zd2VycyBhcyAnT2JqZWN0JywgJ051bWJlcicsICdBcnJheScsIG9yICdOdWxsJy4gRG9lcyBub3RcbiAgICAgKiBhdHRlbXB0IHRvIGRpc3Rpbmd1aXNoIHVzZXIgT2JqZWN0IHR5cGVzIGFueSBmdXJ0aGVyLCByZXBvcnRpbmcgdGhlbSBhbGwgYXNcbiAgICAgKiAnT2JqZWN0Jy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOC4wXG4gICAgICogQGNhdGVnb3J5IFR5cGVcbiAgICAgKiBAc2lnICgqIC0+IHsqfSkgLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi50eXBlKHt9KTsgLy89PiBcIk9iamVjdFwiXG4gICAgICogICAgICBSLnR5cGUoMSk7IC8vPT4gXCJOdW1iZXJcIlxuICAgICAqICAgICAgUi50eXBlKGZhbHNlKTsgLy89PiBcIkJvb2xlYW5cIlxuICAgICAqICAgICAgUi50eXBlKCdzJyk7IC8vPT4gXCJTdHJpbmdcIlxuICAgICAqICAgICAgUi50eXBlKG51bGwpOyAvLz0+IFwiTnVsbFwiXG4gICAgICogICAgICBSLnR5cGUoW10pOyAvLz0+IFwiQXJyYXlcIlxuICAgICAqICAgICAgUi50eXBlKC9bQS16XS8pOyAvLz0+IFwiUmVnRXhwXCJcbiAgICAgKi9cbiAgICB2YXIgdHlwZSA9IF9jdXJyeTEoZnVuY3Rpb24gdHlwZSh2YWwpIHtcbiAgICAgICAgcmV0dXJuIHZhbCA9PT0gbnVsbCA/ICdOdWxsJyA6IHZhbCA9PT0gdW5kZWZpbmVkID8gJ1VuZGVmaW5lZCcgOiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsKS5zbGljZSg4LCAtMSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGZ1bmN0aW9uIGBmbmAsIHdoaWNoIHRha2VzIGEgc2luZ2xlIGFycmF5IGFyZ3VtZW50LCBhbmQgcmV0dXJucyBhXG4gICAgICogZnVuY3Rpb24gd2hpY2g6XG4gICAgICpcbiAgICAgKiAgIC0gdGFrZXMgYW55IG51bWJlciBvZiBwb3NpdGlvbmFsIGFyZ3VtZW50cztcbiAgICAgKiAgIC0gcGFzc2VzIHRoZXNlIGFyZ3VtZW50cyB0byBgZm5gIGFzIGFuIGFycmF5OyBhbmRcbiAgICAgKiAgIC0gcmV0dXJucyB0aGUgcmVzdWx0LlxuICAgICAqXG4gICAgICogSW4gb3RoZXIgd29yZHMsIFIudW5hcHBseSBkZXJpdmVzIGEgdmFyaWFkaWMgZnVuY3Rpb24gZnJvbSBhIGZ1bmN0aW9uIHdoaWNoXG4gICAgICogdGFrZXMgYW4gYXJyYXkuIFIudW5hcHBseSBpcyB0aGUgaW52ZXJzZSBvZiBSLmFwcGx5LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC44LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIChbKi4uLl0gLT4gYSkgLT4gKCouLi4gLT4gYSlcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICAgICAqIEBzZWUgUi5hcHBseVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudW5hcHBseShKU09OLnN0cmluZ2lmeSkoMSwgMiwgMyk7IC8vPT4gJ1sxLDIsM10nXG4gICAgICovXG4gICAgdmFyIHVuYXBwbHkgPSBfY3VycnkxKGZ1bmN0aW9uIHVuYXBwbHkoZm4pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBmbihfc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBXcmFwcyBhIGZ1bmN0aW9uIG9mIGFueSBhcml0eSAoaW5jbHVkaW5nIG51bGxhcnkpIGluIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzXG4gICAgICogZXhhY3RseSAxIHBhcmFtZXRlci4gQW55IGV4dHJhbmVvdXMgcGFyYW1ldGVycyB3aWxsIG5vdCBiZSBwYXNzZWQgdG8gdGhlXG4gICAgICogc3VwcGxpZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjIuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgKCogLT4gYikgLT4gKGEgLT4gYilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBuZXcgZnVuY3Rpb24gd3JhcHBpbmcgYGZuYC4gVGhlIG5ldyBmdW5jdGlvbiBpcyBndWFyYW50ZWVkIHRvIGJlIG9mXG4gICAgICogICAgICAgICBhcml0eSAxLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB0YWtlc1R3b0FyZ3MgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgICogICAgICAgIHJldHVybiBbYSwgYl07XG4gICAgICogICAgICB9O1xuICAgICAqICAgICAgdGFrZXNUd29BcmdzLmxlbmd0aDsgLy89PiAyXG4gICAgICogICAgICB0YWtlc1R3b0FyZ3MoMSwgMik7IC8vPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB0YWtlc09uZUFyZyA9IFIudW5hcnkodGFrZXNUd29BcmdzKTtcbiAgICAgKiAgICAgIHRha2VzT25lQXJnLmxlbmd0aDsgLy89PiAxXG4gICAgICogICAgICAvLyBPbmx5IDEgYXJndW1lbnQgaXMgcGFzc2VkIHRvIHRoZSB3cmFwcGVkIGZ1bmN0aW9uXG4gICAgICogICAgICB0YWtlc09uZUFyZygxLCAyKTsgLy89PiBbMSwgdW5kZWZpbmVkXVxuICAgICAqL1xuICAgIHZhciB1bmFyeSA9IF9jdXJyeTEoZnVuY3Rpb24gdW5hcnkoZm4pIHtcbiAgICAgICAgcmV0dXJuIG5BcnkoMSwgZm4pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGZ1bmN0aW9uIG9mIGFyaXR5IGBuYCBmcm9tIGEgKG1hbnVhbGx5KSBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyBOdW1iZXIgLT4gKGEgLT4gYikgLT4gKGEgLT4gYylcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoIFRoZSBhcml0eSBmb3IgdGhlIHJldHVybmVkIGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byB1bmN1cnJ5LlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAc2VlIFIuY3VycnlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgYWRkRm91ciA9IGEgPT4gYiA9PiBjID0+IGQgPT4gYSArIGIgKyBjICsgZDtcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHVuY3VycmllZEFkZEZvdXIgPSBSLnVuY3VycnlOKDQsIGFkZEZvdXIpO1xuICAgICAqICAgICAgdW5jdXJyaWVkQWRkRm91cigxLCAyLCAzLCA0KTsgLy89PiAxMFxuICAgICAqL1xuICAgIHZhciB1bmN1cnJ5TiA9IF9jdXJyeTIoZnVuY3Rpb24gdW5jdXJyeU4oZGVwdGgsIGZuKSB7XG4gICAgICAgIHJldHVybiBjdXJyeU4oZGVwdGgsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50RGVwdGggPSAxO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gZm47XG4gICAgICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgICAgIHZhciBlbmRJZHg7XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudERlcHRoIDw9IGRlcHRoICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGVuZElkeCA9IGN1cnJlbnREZXB0aCA9PT0gZGVwdGggPyBhcmd1bWVudHMubGVuZ3RoIDogaWR4ICsgdmFsdWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuYXBwbHkodGhpcywgX3NsaWNlKGFyZ3VtZW50cywgaWR4LCBlbmRJZHgpKTtcbiAgICAgICAgICAgICAgICBjdXJyZW50RGVwdGggKz0gMTtcbiAgICAgICAgICAgICAgICBpZHggPSBlbmRJZHg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQnVpbGRzIGEgbGlzdCBmcm9tIGEgc2VlZCB2YWx1ZS4gQWNjZXB0cyBhbiBpdGVyYXRvciBmdW5jdGlvbiwgd2hpY2ggcmV0dXJuc1xuICAgICAqIGVpdGhlciBmYWxzZSB0byBzdG9wIGl0ZXJhdGlvbiBvciBhbiBhcnJheSBvZiBsZW5ndGggMiBjb250YWluaW5nIHRoZSB2YWx1ZVxuICAgICAqIHRvIGFkZCB0byB0aGUgcmVzdWx0aW5nIGxpc3QgYW5kIHRoZSBzZWVkIHRvIGJlIHVzZWQgaW4gdGhlIG5leHQgY2FsbCB0byB0aGVcbiAgICAgKiBpdGVyYXRvciBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIFRoZSBpdGVyYXRvciBmdW5jdGlvbiByZWNlaXZlcyBvbmUgYXJndW1lbnQ6ICooc2VlZCkqLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMC4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IFtiXSkgLT4gKiAtPiBbYl1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgaXRlcmF0b3IgZnVuY3Rpb24uIHJlY2VpdmVzIG9uZSBhcmd1bWVudCwgYHNlZWRgLCBhbmQgcmV0dXJuc1xuICAgICAqICAgICAgICBlaXRoZXIgZmFsc2UgdG8gcXVpdCBpdGVyYXRpb24gb3IgYW4gYXJyYXkgb2YgbGVuZ3RoIHR3byB0byBwcm9jZWVkLiBUaGUgZWxlbWVudFxuICAgICAqICAgICAgICBhdCBpbmRleCAwIG9mIHRoaXMgYXJyYXkgd2lsbCBiZSBhZGRlZCB0byB0aGUgcmVzdWx0aW5nIGFycmF5LCBhbmQgdGhlIGVsZW1lbnRcbiAgICAgKiAgICAgICAgYXQgaW5kZXggMSB3aWxsIGJlIHBhc3NlZCB0byB0aGUgbmV4dCBjYWxsIHRvIGBmbmAuXG4gICAgICogQHBhcmFtIHsqfSBzZWVkIFRoZSBzZWVkIHZhbHVlLlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBUaGUgZmluYWwgbGlzdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZiA9IG4gPT4gbiA+IDUwID8gZmFsc2UgOiBbLW4sIG4gKyAxMF07XG4gICAgICogICAgICBSLnVuZm9sZChmLCAxMCk7IC8vPT4gWy0xMCwgLTIwLCAtMzAsIC00MCwgLTUwXVxuICAgICAqL1xuICAgIHZhciB1bmZvbGQgPSBfY3VycnkyKGZ1bmN0aW9uIHVuZm9sZChmbiwgc2VlZCkge1xuICAgICAgICB2YXIgcGFpciA9IGZuKHNlZWQpO1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHdoaWxlIChwYWlyICYmIHBhaXIubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aF0gPSBwYWlyWzBdO1xuICAgICAgICAgICAgcGFpciA9IGZuKHBhaXJbMV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGxpc3QgY29udGFpbmluZyBvbmx5IG9uZSBjb3B5IG9mIGVhY2ggZWxlbWVudCBpbiB0aGUgb3JpZ2luYWxcbiAgICAgKiBsaXN0LCBiYXNlZCB1cG9uIHRoZSB2YWx1ZSByZXR1cm5lZCBieSBhcHBseWluZyB0aGUgc3VwcGxpZWQgcHJlZGljYXRlIHRvXG4gICAgICogdHdvIGxpc3QgZWxlbWVudHMuIFByZWZlcnMgdGhlIGZpcnN0IGl0ZW0gaWYgdHdvIGl0ZW1zIGNvbXBhcmUgZXF1YWwgYmFzZWRcbiAgICAgKiBvbiB0aGUgcHJlZGljYXRlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEsIGEgLT4gQm9vbGVhbikgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWQgQSBwcmVkaWNhdGUgdXNlZCB0byB0ZXN0IHdoZXRoZXIgdHdvIGl0ZW1zIGFyZSBlcXVhbC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3Qgb2YgdW5pcXVlIGl0ZW1zLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBzdHJFcSA9IFIuZXFCeShTdHJpbmcpO1xuICAgICAqICAgICAgUi51bmlxV2l0aChzdHJFcSkoWzEsICcxJywgMiwgMV0pOyAvLz0+IFsxLCAyXVxuICAgICAqICAgICAgUi51bmlxV2l0aChzdHJFcSkoW3t9LCB7fV0pOyAgICAgICAvLz0+IFt7fV1cbiAgICAgKiAgICAgIFIudW5pcVdpdGgoc3RyRXEpKFsxLCAnMScsIDFdKTsgICAgLy89PiBbMV1cbiAgICAgKiAgICAgIFIudW5pcVdpdGgoc3RyRXEpKFsnMScsIDEsIDFdKTsgICAgLy89PiBbJzEnXVxuICAgICAqL1xuICAgIHZhciB1bmlxV2l0aCA9IF9jdXJyeTIoZnVuY3Rpb24gdW5pcVdpdGgocHJlZCwgbGlzdCkge1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBpdGVtO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICBpdGVtID0gbGlzdFtpZHhdO1xuICAgICAgICAgICAgaWYgKCFfY29udGFpbnNXaXRoKHByZWQsIGl0ZW0sIHJlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aF0gPSBpdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRlc3RzIHRoZSBmaW5hbCBhcmd1bWVudCBieSBwYXNzaW5nIGl0IHRvIHRoZSBnaXZlbiBwcmVkaWNhdGUgZnVuY3Rpb24uIElmXG4gICAgICogdGhlIHByZWRpY2F0ZSBpcyBub3Qgc2F0aXNmaWVkLCB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gdGhlIHJlc3VsdCBvZlxuICAgICAqIGNhbGxpbmcgdGhlIGB3aGVuRmFsc2VGbmAgZnVuY3Rpb24gd2l0aCB0aGUgc2FtZSBhcmd1bWVudC4gSWYgdGhlIHByZWRpY2F0ZVxuICAgICAqIGlzIHNhdGlzZmllZCwgdGhlIGFyZ3VtZW50IGlzIHJldHVybmVkIGFzIGlzLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xOC4wXG4gICAgICogQGNhdGVnb3J5IExvZ2ljXG4gICAgICogQHNpZyAoYSAtPiBCb29sZWFuKSAtPiAoYSAtPiBhKSAtPiBhIC0+IGFcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkICAgICAgICBBIHByZWRpY2F0ZSBmdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdoZW5GYWxzZUZuIEEgZnVuY3Rpb24gdG8gaW52b2tlIHdoZW4gdGhlIGBwcmVkYCBldmFsdWF0ZXNcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIGZhbHN5IHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gICAgICAgIHggICAgICAgICAgIEFuIG9iamVjdCB0byB0ZXN0IHdpdGggdGhlIGBwcmVkYCBmdW5jdGlvbiBhbmRcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXNzIHRvIGB3aGVuRmFsc2VGbmAgaWYgbmVjZXNzYXJ5LlxuICAgICAqIEByZXR1cm4geyp9IEVpdGhlciBgeGAgb3IgdGhlIHJlc3VsdCBvZiBhcHBseWluZyBgeGAgdG8gYHdoZW5GYWxzZUZuYC5cbiAgICAgKiBAc2VlIFIuaWZFbHNlLCBSLndoZW5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyBjb2VyY2VBcnJheSA6OiAoYXxbYV0pIC0+IFthXVxuICAgICAqICAgICAgdmFyIGNvZXJjZUFycmF5ID0gUi51bmxlc3MoUi5pc0FycmF5TGlrZSwgUi5vZik7XG4gICAgICogICAgICBjb2VyY2VBcnJheShbMSwgMiwgM10pOyAvLz0+IFsxLCAyLCAzXVxuICAgICAqICAgICAgY29lcmNlQXJyYXkoMSk7ICAgICAgICAgLy89PiBbMV1cbiAgICAgKi9cbiAgICB2YXIgdW5sZXNzID0gX2N1cnJ5MyhmdW5jdGlvbiB1bmxlc3MocHJlZCwgd2hlbkZhbHNlRm4sIHgpIHtcbiAgICAgICAgcmV0dXJuIHByZWQoeCkgPyB4IDogd2hlbkZhbHNlRm4oeCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIHByZWRpY2F0ZSwgYSB0cmFuc2Zvcm1hdGlvbiBmdW5jdGlvbiwgYW5kIGFuIGluaXRpYWwgdmFsdWUsXG4gICAgICogYW5kIHJldHVybnMgYSB2YWx1ZSBvZiB0aGUgc2FtZSB0eXBlIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEl0IGRvZXMgc28gYnkgYXBwbHlpbmcgdGhlIHRyYW5zZm9ybWF0aW9uIHVudGlsIHRoZSBwcmVkaWNhdGUgaXMgc2F0aXNmaWVkLFxuICAgICAqIGF0IHdoaWNoIHBvaW50IGl0IHJldHVybnMgdGhlIHNhdGlzZmFjdG9yeSB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMjAuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgKGEgLT4gQm9vbGVhbikgLT4gKGEgLT4gYSkgLT4gYSAtPiBhXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZCBBIHByZWRpY2F0ZSBmdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBpdGVyYXRvciBmdW5jdGlvblxuICAgICAqIEBwYXJhbSB7Kn0gaW5pdCBJbml0aWFsIHZhbHVlXG4gICAgICogQHJldHVybiB7Kn0gRmluYWwgdmFsdWUgdGhhdCBzYXRpc2ZpZXMgcHJlZGljYXRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi51bnRpbChSLmd0KFIuX18sIDEwMCksIFIubXVsdGlwbHkoMikpKDEpIC8vID0+IDEyOFxuICAgICAqL1xuICAgIHZhciB1bnRpbCA9IF9jdXJyeTMoZnVuY3Rpb24gdW50aWwocHJlZCwgZm4sIGluaXQpIHtcbiAgICAgICAgdmFyIHZhbCA9IGluaXQ7XG4gICAgICAgIHdoaWxlICghcHJlZCh2YWwpKSB7XG4gICAgICAgICAgICB2YWwgPSBmbih2YWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGNvcHkgb2YgdGhlIGFycmF5IHdpdGggdGhlIGVsZW1lbnQgYXQgdGhlIHByb3ZpZGVkIGluZGV4XG4gICAgICogcmVwbGFjZWQgd2l0aCB0aGUgZ2l2ZW4gdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE0LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgTnVtYmVyIC0+IGEgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBpZHggVGhlIGluZGV4IHRvIHVwZGF0ZS5cbiAgICAgKiBAcGFyYW0geyp9IHggVGhlIHZhbHVlIHRvIGV4aXN0IGF0IHRoZSBnaXZlbiBpbmRleCBvZiB0aGUgcmV0dXJuZWQgYXJyYXkuXG4gICAgICogQHBhcmFtIHtBcnJheXxBcmd1bWVudHN9IGxpc3QgVGhlIHNvdXJjZSBhcnJheS1saWtlIG9iamVjdCB0byBiZSB1cGRhdGVkLlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBIGNvcHkgb2YgYGxpc3RgIHdpdGggdGhlIHZhbHVlIGF0IGluZGV4IGBpZHhgIHJlcGxhY2VkIHdpdGggYHhgLlxuICAgICAqIEBzZWUgUi5hZGp1c3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnVwZGF0ZSgxLCAxMSwgWzAsIDEsIDJdKTsgICAgIC8vPT4gWzAsIDExLCAyXVxuICAgICAqICAgICAgUi51cGRhdGUoMSkoMTEpKFswLCAxLCAyXSk7ICAgICAvLz0+IFswLCAxMSwgMl1cbiAgICAgKi9cbiAgICB2YXIgdXBkYXRlID0gX2N1cnJ5MyhmdW5jdGlvbiB1cGRhdGUoaWR4LCB4LCBsaXN0KSB7XG4gICAgICAgIHJldHVybiBhZGp1c3QoYWx3YXlzKHgpLCBpZHgsIGxpc3QpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQWNjZXB0cyBhIGZ1bmN0aW9uIGBmbmAgYW5kIGEgbGlzdCBvZiB0cmFuc2Zvcm1lciBmdW5jdGlvbnMgYW5kIHJldHVybnMgYVxuICAgICAqIG5ldyBjdXJyaWVkIGZ1bmN0aW9uLiBXaGVuIHRoZSBuZXcgZnVuY3Rpb24gaXMgaW52b2tlZCwgaXQgY2FsbHMgdGhlXG4gICAgICogZnVuY3Rpb24gYGZuYCB3aXRoIHBhcmFtZXRlcnMgY29uc2lzdGluZyBvZiB0aGUgcmVzdWx0IG9mIGNhbGxpbmcgZWFjaFxuICAgICAqIHN1cHBsaWVkIGhhbmRsZXIgb24gc3VjY2Vzc2l2ZSBhcmd1bWVudHMgdG8gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIElmIG1vcmUgYXJndW1lbnRzIGFyZSBwYXNzZWQgdG8gdGhlIHJldHVybmVkIGZ1bmN0aW9uIHRoYW4gdHJhbnNmb3JtZXJcbiAgICAgKiBmdW5jdGlvbnMsIHRob3NlIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGRpcmVjdGx5IHRvIGBmbmAgYXMgYWRkaXRpb25hbFxuICAgICAqIHBhcmFtZXRlcnMuIElmIHlvdSBleHBlY3QgYWRkaXRpb25hbCBhcmd1bWVudHMgdGhhdCBkb24ndCBuZWVkIHRvIGJlXG4gICAgICogdHJhbnNmb3JtZWQsIGFsdGhvdWdoIHlvdSBjYW4gaWdub3JlIHRoZW0sIGl0J3MgYmVzdCB0byBwYXNzIGFuIGlkZW50aXR5XG4gICAgICogZnVuY3Rpb24gc28gdGhhdCB0aGUgbmV3IGZ1bmN0aW9uIHJlcG9ydHMgdGhlIGNvcnJlY3QgYXJpdHkuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgKHgxIC0+IHgyIC0+IC4uLiAtPiB6KSAtPiBbKGEgLT4geDEpLCAoYiAtPiB4MiksIC4uLl0gLT4gKGEgLT4gYiAtPiAuLi4gLT4geilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB0cmFuc2Zvcm1lcnMgQSBsaXN0IG9mIHRyYW5zZm9ybWVyIGZ1bmN0aW9uc1xuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnVzZVdpdGgoTWF0aC5wb3csIFtSLmlkZW50aXR5LCBSLmlkZW50aXR5XSkoMywgNCk7IC8vPT4gODFcbiAgICAgKiAgICAgIFIudXNlV2l0aChNYXRoLnBvdywgW1IuaWRlbnRpdHksIFIuaWRlbnRpdHldKSgzKSg0KTsgLy89PiA4MVxuICAgICAqICAgICAgUi51c2VXaXRoKE1hdGgucG93LCBbUi5kZWMsIFIuaW5jXSkoMywgNCk7IC8vPT4gMzJcbiAgICAgKiAgICAgIFIudXNlV2l0aChNYXRoLnBvdywgW1IuZGVjLCBSLmluY10pKDMpKDQpOyAvLz0+IDMyXG4gICAgICovXG4gICAgdmFyIHVzZVdpdGggPSBfY3VycnkyKGZ1bmN0aW9uIHVzZVdpdGgoZm4sIHRyYW5zZm9ybWVycykge1xuICAgICAgICByZXR1cm4gY3VycnlOKHRyYW5zZm9ybWVycy5sZW5ndGgsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChpZHggPCB0cmFuc2Zvcm1lcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgYXJncy5wdXNoKHRyYW5zZm9ybWVyc1tpZHhdLmNhbGwodGhpcywgYXJndW1lbnRzW2lkeF0pKTtcbiAgICAgICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmdzLmNvbmNhdChfc2xpY2UoYXJndW1lbnRzLCB0cmFuc2Zvcm1lcnMubGVuZ3RoKSkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBsaXN0IG9mIGFsbCB0aGUgZW51bWVyYWJsZSBvd24gcHJvcGVydGllcyBvZiB0aGUgc3VwcGxpZWQgb2JqZWN0LlxuICAgICAqIE5vdGUgdGhhdCB0aGUgb3JkZXIgb2YgdGhlIG91dHB1dCBhcnJheSBpcyBub3QgZ3VhcmFudGVlZCBhY3Jvc3MgZGlmZmVyZW50XG4gICAgICogSlMgcGxhdGZvcm1zLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyB7azogdn0gLT4gW3ZdXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGV4dHJhY3QgdmFsdWVzIGZyb21cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgdGhlIHZhbHVlcyBvZiB0aGUgb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi52YWx1ZXMoe2E6IDEsIGI6IDIsIGM6IDN9KTsgLy89PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICB2YXIgdmFsdWVzID0gX2N1cnJ5MShmdW5jdGlvbiB2YWx1ZXMob2JqKSB7XG4gICAgICAgIHZhciBwcm9wcyA9IGtleXMob2JqKTtcbiAgICAgICAgdmFyIGxlbiA9IHByb3BzLmxlbmd0aDtcbiAgICAgICAgdmFyIHZhbHMgPSBbXTtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgIHZhbHNbaWR4XSA9IG9ialtwcm9wc1tpZHhdXTtcbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWxzO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGxpc3Qgb2YgYWxsIHRoZSBwcm9wZXJ0aWVzLCBpbmNsdWRpbmcgcHJvdG90eXBlIHByb3BlcnRpZXMsIG9mIHRoZVxuICAgICAqIHN1cHBsaWVkIG9iamVjdC5cbiAgICAgKiBOb3RlIHRoYXQgdGhlIG9yZGVyIG9mIHRoZSBvdXRwdXQgYXJyYXkgaXMgbm90IGd1YXJhbnRlZWQgdG8gYmUgY29uc2lzdGVudFxuICAgICAqIGFjcm9zcyBkaWZmZXJlbnQgSlMgcGxhdGZvcm1zLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyB7azogdn0gLT4gW3ZdXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGV4dHJhY3QgdmFsdWVzIGZyb21cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2YgdGhlIHZhbHVlcyBvZiB0aGUgb2JqZWN0J3Mgb3duIGFuZCBwcm90b3R5cGUgcHJvcGVydGllcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgRiA9IGZ1bmN0aW9uKCkgeyB0aGlzLnggPSAnWCc7IH07XG4gICAgICogICAgICBGLnByb3RvdHlwZS55ID0gJ1knO1xuICAgICAqICAgICAgdmFyIGYgPSBuZXcgRigpO1xuICAgICAqICAgICAgUi52YWx1ZXNJbihmKTsgLy89PiBbJ1gnLCAnWSddXG4gICAgICovXG4gICAgdmFyIHZhbHVlc0luID0gX2N1cnJ5MShmdW5jdGlvbiB2YWx1ZXNJbihvYmopIHtcbiAgICAgICAgdmFyIHByb3A7XG4gICAgICAgIHZhciB2cyA9IFtdO1xuICAgICAgICBmb3IgKHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgICB2c1t2cy5sZW5ndGhdID0gb2JqW3Byb3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2cztcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBcInZpZXdcIiBvZiB0aGUgZ2l2ZW4gZGF0YSBzdHJ1Y3R1cmUsIGRldGVybWluZWQgYnkgdGhlIGdpdmVuIGxlbnMuXG4gICAgICogVGhlIGxlbnMncyBmb2N1cyBkZXRlcm1pbmVzIHdoaWNoIHBvcnRpb24gb2YgdGhlIGRhdGEgc3RydWN0dXJlIGlzIHZpc2libGUuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE2LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHR5cGVkZWZuIExlbnMgcyBhID0gRnVuY3RvciBmID0+IChhIC0+IGYgYSkgLT4gcyAtPiBmIHNcbiAgICAgKiBAc2lnIExlbnMgcyBhIC0+IHMgLT4gYVxuICAgICAqIEBwYXJhbSB7TGVuc30gbGVuc1xuICAgICAqIEBwYXJhbSB7Kn0geFxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHNlZSBSLnByb3AsIFIubGVuc0luZGV4LCBSLmxlbnNQcm9wXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHhMZW5zID0gUi5sZW5zUHJvcCgneCcpO1xuICAgICAqXG4gICAgICogICAgICBSLnZpZXcoeExlbnMsIHt4OiAxLCB5OiAyfSk7ICAvLz0+IDFcbiAgICAgKiAgICAgIFIudmlldyh4TGVucywge3g6IDQsIHk6IDJ9KTsgIC8vPT4gNFxuICAgICAqL1xuICAgIC8vIGBDb25zdGAgaXMgYSBmdW5jdG9yIHRoYXQgZWZmZWN0aXZlbHkgaWdub3JlcyB0aGUgZnVuY3Rpb24gZ2l2ZW4gdG8gYG1hcGAuXG4gICAgLy8gVXNpbmcgYENvbnN0YCBlZmZlY3RpdmVseSBpZ25vcmVzIHRoZSBzZXR0ZXIgZnVuY3Rpb24gb2YgdGhlIGBsZW5zYCxcbiAgICAvLyBsZWF2aW5nIHRoZSB2YWx1ZSByZXR1cm5lZCBieSB0aGUgZ2V0dGVyIGZ1bmN0aW9uIHVubW9kaWZpZWQuXG4gICAgdmFyIHZpZXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGBDb25zdGAgaXMgYSBmdW5jdG9yIHRoYXQgZWZmZWN0aXZlbHkgaWdub3JlcyB0aGUgZnVuY3Rpb24gZ2l2ZW4gdG8gYG1hcGAuXG4gICAgICAgIHZhciBDb25zdCA9IGZ1bmN0aW9uICh4KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHZhbHVlOiB4LFxuICAgICAgICAgICAgICAgIG1hcDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiB2aWV3KGxlbnMsIHgpIHtcbiAgICAgICAgICAgIC8vIFVzaW5nIGBDb25zdGAgZWZmZWN0aXZlbHkgaWdub3JlcyB0aGUgc2V0dGVyIGZ1bmN0aW9uIG9mIHRoZSBgbGVuc2AsXG4gICAgICAgICAgICAvLyBsZWF2aW5nIHRoZSB2YWx1ZSByZXR1cm5lZCBieSB0aGUgZ2V0dGVyIGZ1bmN0aW9uIHVubW9kaWZpZWQuXG4gICAgICAgICAgICByZXR1cm4gbGVucyhDb25zdCkoeCkudmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH0oKTtcblxuICAgIC8qKlxuICAgICAqIFRlc3RzIHRoZSBmaW5hbCBhcmd1bWVudCBieSBwYXNzaW5nIGl0IHRvIHRoZSBnaXZlbiBwcmVkaWNhdGUgZnVuY3Rpb24uIElmXG4gICAgICogdGhlIHByZWRpY2F0ZSBpcyBzYXRpc2ZpZWQsIHRoZSBmdW5jdGlvbiB3aWxsIHJldHVybiB0aGUgcmVzdWx0IG9mIGNhbGxpbmdcbiAgICAgKiB0aGUgYHdoZW5UcnVlRm5gIGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgYXJndW1lbnQuIElmIHRoZSBwcmVkaWNhdGUgaXMgbm90XG4gICAgICogc2F0aXNmaWVkLCB0aGUgYXJndW1lbnQgaXMgcmV0dXJuZWQgYXMgaXMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE4LjBcbiAgICAgKiBAY2F0ZWdvcnkgTG9naWNcbiAgICAgKiBAc2lnIChhIC0+IEJvb2xlYW4pIC0+IChhIC0+IGEpIC0+IGEgLT4gYVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWQgICAgICAgQSBwcmVkaWNhdGUgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB3aGVuVHJ1ZUZuIEEgZnVuY3Rpb24gdG8gaW52b2tlIHdoZW4gdGhlIGBjb25kaXRpb25gXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmFsdWF0ZXMgdG8gYSB0cnV0aHkgdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSAgICAgICAgeCAgICAgICAgICBBbiBvYmplY3QgdG8gdGVzdCB3aXRoIHRoZSBgcHJlZGAgZnVuY3Rpb24gYW5kXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXNzIHRvIGB3aGVuVHJ1ZUZuYCBpZiBuZWNlc3NhcnkuXG4gICAgICogQHJldHVybiB7Kn0gRWl0aGVyIGB4YCBvciB0aGUgcmVzdWx0IG9mIGFwcGx5aW5nIGB4YCB0byBgd2hlblRydWVGbmAuXG4gICAgICogQHNlZSBSLmlmRWxzZSwgUi51bmxlc3NcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyB0cnVuY2F0ZSA6OiBTdHJpbmcgLT4gU3RyaW5nXG4gICAgICogICAgICB2YXIgdHJ1bmNhdGUgPSBSLndoZW4oXG4gICAgICogICAgICAgIFIucHJvcFNhdGlzZmllcyhSLmd0KFIuX18sIDEwKSwgJ2xlbmd0aCcpLFxuICAgICAqICAgICAgICBSLnBpcGUoUi50YWtlKDEwKSwgUi5hcHBlbmQoJ+KApicpLCBSLmpvaW4oJycpKVxuICAgICAqICAgICAgKTtcbiAgICAgKiAgICAgIHRydW5jYXRlKCcxMjM0NScpOyAgICAgICAgIC8vPT4gJzEyMzQ1J1xuICAgICAqICAgICAgdHJ1bmNhdGUoJzAxMjM0NTY3ODlBQkMnKTsgLy89PiAnMDEyMzQ1Njc4OeKApidcbiAgICAgKi9cbiAgICB2YXIgd2hlbiA9IF9jdXJyeTMoZnVuY3Rpb24gd2hlbihwcmVkLCB3aGVuVHJ1ZUZuLCB4KSB7XG4gICAgICAgIHJldHVybiBwcmVkKHgpID8gd2hlblRydWVGbih4KSA6IHg7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIHNwZWMgb2JqZWN0IGFuZCBhIHRlc3Qgb2JqZWN0OyByZXR1cm5zIHRydWUgaWYgdGhlIHRlc3Qgc2F0aXNmaWVzXG4gICAgICogdGhlIHNwZWMuIEVhY2ggb2YgdGhlIHNwZWMncyBvd24gcHJvcGVydGllcyBtdXN0IGJlIGEgcHJlZGljYXRlIGZ1bmN0aW9uLlxuICAgICAqIEVhY2ggcHJlZGljYXRlIGlzIGFwcGxpZWQgdG8gdGhlIHZhbHVlIG9mIHRoZSBjb3JyZXNwb25kaW5nIHByb3BlcnR5IG9mIHRoZVxuICAgICAqIHRlc3Qgb2JqZWN0LiBgd2hlcmVgIHJldHVybnMgdHJ1ZSBpZiBhbGwgdGhlIHByZWRpY2F0ZXMgcmV0dXJuIHRydWUsIGZhbHNlXG4gICAgICogb3RoZXJ3aXNlLlxuICAgICAqXG4gICAgICogYHdoZXJlYCBpcyB3ZWxsIHN1aXRlZCB0byBkZWNsYXJhdGl2ZWx5IGV4cHJlc3NpbmcgY29uc3RyYWludHMgZm9yIG90aGVyXG4gICAgICogZnVuY3Rpb25zIHN1Y2ggYXMgYGZpbHRlcmAgYW5kIGBmaW5kYC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4xXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcge1N0cmluZzogKCogLT4gQm9vbGVhbil9IC0+IHtTdHJpbmc6ICp9IC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3BlY1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB0ZXN0T2JqXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyBwcmVkIDo6IE9iamVjdCAtPiBCb29sZWFuXG4gICAgICogICAgICB2YXIgcHJlZCA9IHdoZXJlKHtcbiAgICAgKiAgICAgICAgYTogZXF1YWxzKCdmb28nKSxcbiAgICAgKiAgICAgICAgYjogY29tcGxlbWVudChlcXVhbHMoJ2JhcicpKSxcbiAgICAgKiAgICAgICAgeDogZ3QoX18sIDEwKSxcbiAgICAgKiAgICAgICAgeTogbHQoX18sIDIwKVxuICAgICAqICAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgIHByZWQoe2E6ICdmb28nLCBiOiAneHh4JywgeDogMTEsIHk6IDE5fSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgcHJlZCh7YTogJ3h4eCcsIGI6ICd4eHgnLCB4OiAxMSwgeTogMTl9KTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgcHJlZCh7YTogJ2ZvbycsIGI6ICdiYXInLCB4OiAxMSwgeTogMTl9KTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgcHJlZCh7YTogJ2ZvbycsIGI6ICd4eHgnLCB4OiAxMCwgeTogMTl9KTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgcHJlZCh7YTogJ2ZvbycsIGI6ICd4eHgnLCB4OiAxMSwgeTogMjB9KTsgLy89PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciB3aGVyZSA9IF9jdXJyeTIoZnVuY3Rpb24gd2hlcmUoc3BlYywgdGVzdE9iaikge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNwZWMpIHtcbiAgICAgICAgICAgIGlmIChfaGFzKHByb3AsIHNwZWMpICYmICFzcGVjW3Byb3BdKHRlc3RPYmpbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogV3JhcCBhIGZ1bmN0aW9uIGluc2lkZSBhbm90aGVyIHRvIGFsbG93IHlvdSB0byBtYWtlIGFkanVzdG1lbnRzIHRvIHRoZVxuICAgICAqIHBhcmFtZXRlcnMsIG9yIGRvIG90aGVyIHByb2Nlc3NpbmcgZWl0aGVyIGJlZm9yZSB0aGUgaW50ZXJuYWwgZnVuY3Rpb24gaXNcbiAgICAgKiBjYWxsZWQgb3Igd2l0aCBpdHMgcmVzdWx0cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoYS4uLiAtPiBiKSAtPiAoKGEuLi4gLT4gYikgLT4gYS4uLiAtPiBjKSAtPiAoYS4uLiAtPiBjKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBwZXIgVGhlIHdyYXBwZXIgZnVuY3Rpb24uXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqIEBkZXByZWNhdGVkIHNpbmNlIHYwLjIyLjBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZ3JlZXQgPSBuYW1lID0+ICdIZWxsbyAnICsgbmFtZTtcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHNob3V0ZWRHcmVldCA9IFIud3JhcChncmVldCwgKGdyLCBuYW1lKSA9PiBncihuYW1lKS50b1VwcGVyQ2FzZSgpKTtcbiAgICAgKlxuICAgICAqICAgICAgc2hvdXRlZEdyZWV0KFwiS2F0aHlcIik7IC8vPT4gXCJIRUxMTyBLQVRIWVwiXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBzaG9ydGVuZWRHcmVldCA9IFIud3JhcChncmVldCwgZnVuY3Rpb24oZ3IsIG5hbWUpIHtcbiAgICAgKiAgICAgICAgcmV0dXJuIGdyKG5hbWUuc3Vic3RyaW5nKDAsIDMpKTtcbiAgICAgKiAgICAgIH0pO1xuICAgICAqICAgICAgc2hvcnRlbmVkR3JlZXQoXCJSb2JlcnRcIik7IC8vPT4gXCJIZWxsbyBSb2JcIlxuICAgICAqL1xuICAgIHZhciB3cmFwID0gX2N1cnJ5MihmdW5jdGlvbiB3cmFwKGZuLCB3cmFwcGVyKSB7XG4gICAgICAgIHJldHVybiBjdXJyeU4oZm4ubGVuZ3RoLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gd3JhcHBlci5hcHBseSh0aGlzLCBfY29uY2F0KFtmbl0sIGFyZ3VtZW50cykpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgbGlzdCBvdXQgb2YgdGhlIHR3byBzdXBwbGllZCBieSBjcmVhdGluZyBlYWNoIHBvc3NpYmxlIHBhaXJcbiAgICAgKiBmcm9tIHRoZSBsaXN0cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIFthXSAtPiBbYl0gLT4gW1thLGJdXVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFzIFRoZSBmaXJzdCBsaXN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJzIFRoZSBzZWNvbmQgbGlzdC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3QgbWFkZSBieSBjb21iaW5pbmcgZWFjaCBwb3NzaWJsZSBwYWlyIGZyb21cbiAgICAgKiAgICAgICAgIGBhc2AgYW5kIGBic2AgaW50byBwYWlycyAoYFthLCBiXWApLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIueHByb2QoWzEsIDJdLCBbJ2EnLCAnYiddKTsgLy89PiBbWzEsICdhJ10sIFsxLCAnYiddLCBbMiwgJ2EnXSwgWzIsICdiJ11dXG4gICAgICovXG4gICAgLy8gPSB4cHJvZFdpdGgocHJlcGVuZCk7ICh0YWtlcyBhYm91dCAzIHRpbWVzIGFzIGxvbmcuLi4pXG4gICAgdmFyIHhwcm9kID0gX2N1cnJ5MihmdW5jdGlvbiB4cHJvZChhLCBiKSB7XG4gICAgICAgIC8vID0geHByb2RXaXRoKHByZXBlbmQpOyAodGFrZXMgYWJvdXQgMyB0aW1lcyBhcyBsb25nLi4uKVxuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGlsZW4gPSBhLmxlbmd0aDtcbiAgICAgICAgdmFyIGo7XG4gICAgICAgIHZhciBqbGVuID0gYi5sZW5ndGg7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgd2hpbGUgKGlkeCA8IGlsZW4pIHtcbiAgICAgICAgICAgIGogPSAwO1xuICAgICAgICAgICAgd2hpbGUgKGogPCBqbGVuKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gW1xuICAgICAgICAgICAgICAgICAgICBhW2lkeF0sXG4gICAgICAgICAgICAgICAgICAgIGJbal1cbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgIGogKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGxpc3Qgb3V0IG9mIHRoZSB0d28gc3VwcGxpZWQgYnkgcGFpcmluZyB1cCBlcXVhbGx5LXBvc2l0aW9uZWRcbiAgICAgKiBpdGVtcyBmcm9tIGJvdGggbGlzdHMuIFRoZSByZXR1cm5lZCBsaXN0IGlzIHRydW5jYXRlZCB0byB0aGUgbGVuZ3RoIG9mIHRoZVxuICAgICAqIHNob3J0ZXIgb2YgdGhlIHR3byBpbnB1dCBsaXN0cy5cbiAgICAgKiBOb3RlOiBgemlwYCBpcyBlcXVpdmFsZW50IHRvIGB6aXBXaXRoKGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIFthLCBiXSB9KWAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBbYV0gLT4gW2JdIC0+IFtbYSxiXV1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MSBUaGUgZmlyc3QgYXJyYXkgdG8gY29uc2lkZXIuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdDIgVGhlIHNlY29uZCBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3QgbWFkZSBieSBwYWlyaW5nIHVwIHNhbWUtaW5kZXhlZCBlbGVtZW50cyBvZiBgbGlzdDFgIGFuZCBgbGlzdDJgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuemlwKFsxLCAyLCAzXSwgWydhJywgJ2InLCAnYyddKTsgLy89PiBbWzEsICdhJ10sIFsyLCAnYiddLCBbMywgJ2MnXV1cbiAgICAgKi9cbiAgICB2YXIgemlwID0gX2N1cnJ5MihmdW5jdGlvbiB6aXAoYSwgYikge1xuICAgICAgICB2YXIgcnYgPSBbXTtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbihhLmxlbmd0aCwgYi5sZW5ndGgpO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICBydltpZHhdID0gW1xuICAgICAgICAgICAgICAgIGFbaWR4XSxcbiAgICAgICAgICAgICAgICBiW2lkeF1cbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcnY7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IG9iamVjdCBvdXQgb2YgYSBsaXN0IG9mIGtleXMgYW5kIGEgbGlzdCBvZiB2YWx1ZXMuXG4gICAgICogS2V5L3ZhbHVlIHBhaXJpbmcgaXMgdHJ1bmNhdGVkIHRvIHRoZSBsZW5ndGggb2YgdGhlIHNob3J0ZXIgb2YgdGhlIHR3byBsaXN0cy5cbiAgICAgKiBOb3RlOiBgemlwT2JqYCBpcyBlcXVpdmFsZW50IHRvIGBwaXBlKHppcFdpdGgocGFpciksIGZyb21QYWlycylgLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgW1N0cmluZ10gLT4gWypdIC0+IHtTdHJpbmc6ICp9XG4gICAgICogQHBhcmFtIHtBcnJheX0ga2V5cyBUaGUgYXJyYXkgdGhhdCB3aWxsIGJlIHByb3BlcnRpZXMgb24gdGhlIG91dHB1dCBvYmplY3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSBsaXN0IG9mIHZhbHVlcyBvbiB0aGUgb3V0cHV0IG9iamVjdC5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBvYmplY3QgbWFkZSBieSBwYWlyaW5nIHVwIHNhbWUtaW5kZXhlZCBlbGVtZW50cyBvZiBga2V5c2AgYW5kIGB2YWx1ZXNgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuemlwT2JqKFsnYScsICdiJywgJ2MnXSwgWzEsIDIsIDNdKTsgLy89PiB7YTogMSwgYjogMiwgYzogM31cbiAgICAgKi9cbiAgICB2YXIgemlwT2JqID0gX2N1cnJ5MihmdW5jdGlvbiB6aXBPYmooa2V5cywgdmFsdWVzKSB7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgbGVuID0gTWF0aC5taW4oa2V5cy5sZW5ndGgsIHZhbHVlcy5sZW5ndGgpO1xuICAgICAgICB2YXIgb3V0ID0ge307XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgIG91dFtrZXlzW2lkeF1dID0gdmFsdWVzW2lkeF07XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBsaXN0IG91dCBvZiB0aGUgdHdvIHN1cHBsaWVkIGJ5IGFwcGx5aW5nIHRoZSBmdW5jdGlvbiB0byBlYWNoXG4gICAgICogZXF1YWxseS1wb3NpdGlvbmVkIHBhaXIgaW4gdGhlIGxpc3RzLiBUaGUgcmV0dXJuZWQgbGlzdCBpcyB0cnVuY2F0ZWQgdG8gdGhlXG4gICAgICogbGVuZ3RoIG9mIHRoZSBzaG9ydGVyIG9mIHRoZSB0d28gaW5wdXQgbGlzdHMuXG4gICAgICpcbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEsYiAtPiBjKSAtPiBbYV0gLT4gW2JdIC0+IFtjXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB1c2VkIHRvIGNvbWJpbmUgdGhlIHR3byBlbGVtZW50cyBpbnRvIG9uZSB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MSBUaGUgZmlyc3QgYXJyYXkgdG8gY29uc2lkZXIuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdDIgVGhlIHNlY29uZCBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3QgbWFkZSBieSBjb21iaW5pbmcgc2FtZS1pbmRleGVkIGVsZW1lbnRzIG9mIGBsaXN0MWAgYW5kIGBsaXN0MmBcbiAgICAgKiAgICAgICAgIHVzaW5nIGBmbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGYgPSAoeCwgeSkgPT4ge1xuICAgICAqICAgICAgICAvLyAuLi5cbiAgICAgKiAgICAgIH07XG4gICAgICogICAgICBSLnppcFdpdGgoZiwgWzEsIDIsIDNdLCBbJ2EnLCAnYicsICdjJ10pO1xuICAgICAqICAgICAgLy89PiBbZigxLCAnYScpLCBmKDIsICdiJyksIGYoMywgJ2MnKV1cbiAgICAgKi9cbiAgICB2YXIgemlwV2l0aCA9IF9jdXJyeTMoZnVuY3Rpb24gemlwV2l0aChmbiwgYSwgYikge1xuICAgICAgICB2YXIgcnYgPSBbXTtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbihhLmxlbmd0aCwgYi5sZW5ndGgpO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICBydltpZHhdID0gZm4oYVtpZHhdLCBiW2lkeF0pO1xuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJ2O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQSBmdW5jdGlvbiB0aGF0IGFsd2F5cyByZXR1cm5zIGBmYWxzZWAuIEFueSBwYXNzZWQgaW4gcGFyYW1ldGVycyBhcmUgaWdub3JlZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAqIC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0geyp9XG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAc2VlIFIuYWx3YXlzLCBSLlRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLkYoKTsgLy89PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBGID0gYWx3YXlzKGZhbHNlKTtcblxuICAgIC8qKlxuICAgICAqIEEgZnVuY3Rpb24gdGhhdCBhbHdheXMgcmV0dXJucyBgdHJ1ZWAuIEFueSBwYXNzZWQgaW4gcGFyYW1ldGVycyBhcmUgaWdub3JlZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAqIC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0geyp9XG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAc2VlIFIuYWx3YXlzLCBSLkZcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLlQoKTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIFQgPSBhbHdheXModHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBiZSBjb3BpZWRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSByZWZGcm9tIEFycmF5IGNvbnRhaW5pbmcgdGhlIHNvdXJjZSByZWZlcmVuY2VzXG4gICAgICogQHBhcmFtIHtBcnJheX0gcmVmVG8gQXJyYXkgY29udGFpbmluZyB0aGUgY29waWVkIHNvdXJjZSByZWZlcmVuY2VzXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBkZWVwIFdoZXRoZXIgb3Igbm90IHRvIHBlcmZvcm0gZGVlcCBjbG9uaW5nLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBjb3BpZWQgdmFsdWUuXG4gICAgICovXG4gICAgdmFyIF9jbG9uZSA9IGZ1bmN0aW9uIF9jbG9uZSh2YWx1ZSwgcmVmRnJvbSwgcmVmVG8sIGRlZXApIHtcbiAgICAgICAgdmFyIGNvcHkgPSBmdW5jdGlvbiBjb3B5KGNvcGllZFZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgbGVuID0gcmVmRnJvbS5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT09IHJlZkZyb21baWR4XSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVmVG9baWR4XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZWZGcm9tW2lkeCArIDFdID0gdmFsdWU7XG4gICAgICAgICAgICByZWZUb1tpZHggKyAxXSA9IGNvcGllZFZhbHVlO1xuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgY29waWVkVmFsdWVba2V5XSA9IGRlZXAgPyBfY2xvbmUodmFsdWVba2V5XSwgcmVmRnJvbSwgcmVmVG8sIHRydWUpIDogdmFsdWVba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjb3BpZWRWYWx1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgc3dpdGNoICh0eXBlKHZhbHVlKSkge1xuICAgICAgICBjYXNlICdPYmplY3QnOlxuICAgICAgICAgICAgcmV0dXJuIGNvcHkoe30pO1xuICAgICAgICBjYXNlICdBcnJheSc6XG4gICAgICAgICAgICByZXR1cm4gY29weShbXSk7XG4gICAgICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHZhbHVlLnZhbHVlT2YoKSk7XG4gICAgICAgIGNhc2UgJ1JlZ0V4cCc6XG4gICAgICAgICAgICByZXR1cm4gX2Nsb25lUmVnRXhwKHZhbHVlKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgX2NyZWF0ZVBhcnRpYWxBcHBsaWNhdG9yID0gZnVuY3Rpb24gX2NyZWF0ZVBhcnRpYWxBcHBsaWNhdG9yKGNvbmNhdCkge1xuICAgICAgICByZXR1cm4gX2N1cnJ5MihmdW5jdGlvbiAoZm4sIGFyZ3MpIHtcbiAgICAgICAgICAgIHJldHVybiBfYXJpdHkoTWF0aC5tYXgoMCwgZm4ubGVuZ3RoIC0gYXJncy5sZW5ndGgpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGNvbmNhdChhcmdzLCBhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgdmFyIF9kcm9wTGFzdCA9IGZ1bmN0aW9uIGRyb3BMYXN0KG4sIHhzKSB7XG4gICAgICAgIHJldHVybiB0YWtlKG4gPCB4cy5sZW5ndGggPyB4cy5sZW5ndGggLSBuIDogMCwgeHMpO1xuICAgIH07XG5cbiAgICAvLyBWYWx1ZXMgb2Ygb3RoZXIgdHlwZXMgYXJlIG9ubHkgZXF1YWwgaWYgaWRlbnRpY2FsLlxuICAgIHZhciBfZXF1YWxzID0gZnVuY3Rpb24gX2VxdWFscyhhLCBiLCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgICBpZiAoaWRlbnRpY2FsKGEsIGIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZShhKSAhPT0gdHlwZShiKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhID09IG51bGwgfHwgYiA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBhLmVxdWFscyA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgYi5lcXVhbHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2YgYS5lcXVhbHMgPT09ICdmdW5jdGlvbicgJiYgYS5lcXVhbHMoYikgJiYgdHlwZW9mIGIuZXF1YWxzID09PSAnZnVuY3Rpb24nICYmIGIuZXF1YWxzKGEpO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAodHlwZShhKSkge1xuICAgICAgICBjYXNlICdBcmd1bWVudHMnOlxuICAgICAgICBjYXNlICdBcnJheSc6XG4gICAgICAgIGNhc2UgJ09iamVjdCc6XG4gICAgICAgICAgICBpZiAodHlwZW9mIGEuY29uc3RydWN0b3IgPT09ICdmdW5jdGlvbicgJiYgX2Z1bmN0aW9uTmFtZShhLmNvbnN0cnVjdG9yKSA9PT0gJ1Byb21pc2UnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPT09IGI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnQm9vbGVhbic6XG4gICAgICAgIGNhc2UgJ051bWJlcic6XG4gICAgICAgIGNhc2UgJ1N0cmluZyc6XG4gICAgICAgICAgICBpZiAoISh0eXBlb2YgYSA9PT0gdHlwZW9mIGIgJiYgaWRlbnRpY2FsKGEudmFsdWVPZigpLCBiLnZhbHVlT2YoKSkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0RhdGUnOlxuICAgICAgICAgICAgaWYgKCFpZGVudGljYWwoYS52YWx1ZU9mKCksIGIudmFsdWVPZigpKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdFcnJvcic6XG4gICAgICAgICAgICByZXR1cm4gYS5uYW1lID09PSBiLm5hbWUgJiYgYS5tZXNzYWdlID09PSBiLm1lc3NhZ2U7XG4gICAgICAgIGNhc2UgJ1JlZ0V4cCc6XG4gICAgICAgICAgICBpZiAoIShhLnNvdXJjZSA9PT0gYi5zb3VyY2UgJiYgYS5nbG9iYWwgPT09IGIuZ2xvYmFsICYmIGEuaWdub3JlQ2FzZSA9PT0gYi5pZ25vcmVDYXNlICYmIGEubXVsdGlsaW5lID09PSBiLm11bHRpbGluZSAmJiBhLnN0aWNreSA9PT0gYi5zdGlja3kgJiYgYS51bmljb2RlID09PSBiLnVuaWNvZGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ01hcCc6XG4gICAgICAgIGNhc2UgJ1NldCc6XG4gICAgICAgICAgICBpZiAoIV9lcXVhbHMoX2FycmF5RnJvbUl0ZXJhdG9yKGEuZW50cmllcygpKSwgX2FycmF5RnJvbUl0ZXJhdG9yKGIuZW50cmllcygpKSwgc3RhY2tBLCBzdGFja0IpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0ludDhBcnJheSc6XG4gICAgICAgIGNhc2UgJ1VpbnQ4QXJyYXknOlxuICAgICAgICBjYXNlICdVaW50OENsYW1wZWRBcnJheSc6XG4gICAgICAgIGNhc2UgJ0ludDE2QXJyYXknOlxuICAgICAgICBjYXNlICdVaW50MTZBcnJheSc6XG4gICAgICAgIGNhc2UgJ0ludDMyQXJyYXknOlxuICAgICAgICBjYXNlICdVaW50MzJBcnJheSc6XG4gICAgICAgIGNhc2UgJ0Zsb2F0MzJBcnJheSc6XG4gICAgICAgIGNhc2UgJ0Zsb2F0NjRBcnJheSc6XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnQXJyYXlCdWZmZXInOlxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAvLyBWYWx1ZXMgb2Ygb3RoZXIgdHlwZXMgYXJlIG9ubHkgZXF1YWwgaWYgaWRlbnRpY2FsLlxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBrZXlzQSA9IGtleXMoYSk7XG4gICAgICAgIGlmIChrZXlzQS5sZW5ndGggIT09IGtleXMoYikubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGlkeCA9IHN0YWNrQS5sZW5ndGggLSAxO1xuICAgICAgICB3aGlsZSAoaWR4ID49IDApIHtcbiAgICAgICAgICAgIGlmIChzdGFja0FbaWR4XSA9PT0gYSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdGFja0JbaWR4XSA9PT0gYjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCAtPSAxO1xuICAgICAgICB9XG4gICAgICAgIHN0YWNrQS5wdXNoKGEpO1xuICAgICAgICBzdGFja0IucHVzaChiKTtcbiAgICAgICAgaWR4ID0ga2V5c0EubGVuZ3RoIC0gMTtcbiAgICAgICAgd2hpbGUgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0ga2V5c0FbaWR4XTtcbiAgICAgICAgICAgIGlmICghKF9oYXMoa2V5LCBiKSAmJiBfZXF1YWxzKGJba2V5XSwgYVtrZXldLCBzdGFja0EsIHN0YWNrQikpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4IC09IDE7XG4gICAgICAgIH1cbiAgICAgICAgc3RhY2tBLnBvcCgpO1xuICAgICAgICBzdGFja0IucG9wKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBgX21ha2VGbGF0YCBpcyBhIGhlbHBlciBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBvbmUtbGV2ZWwgb3IgZnVsbHkgcmVjdXJzaXZlXG4gICAgICogZnVuY3Rpb24gYmFzZWQgb24gdGhlIGZsYWcgcGFzc2VkIGluLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB2YXIgX21ha2VGbGF0ID0gZnVuY3Rpb24gX21ha2VGbGF0KHJlY3Vyc2l2ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gZmxhdHQobGlzdCkge1xuICAgICAgICAgICAgdmFyIHZhbHVlLCBqbGVuLCBqO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgICAgICB2YXIgaWxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGlkeCA8IGlsZW4pIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheUxpa2UobGlzdFtpZHhdKSkge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHJlY3Vyc2l2ZSA/IGZsYXR0KGxpc3RbaWR4XSkgOiBsaXN0W2lkeF07XG4gICAgICAgICAgICAgICAgICAgIGogPSAwO1xuICAgICAgICAgICAgICAgICAgICBqbGVuID0gdmFsdWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaiA8IGpsZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoXSA9IHZhbHVlW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaiArPSAxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGhdID0gbGlzdFtpZHhdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIHZhciBfcmVkdWNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBfYXJyYXlSZWR1Y2UoeGYsIGFjYywgbGlzdCkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgICAgICB2YXIgbGVuID0gbGlzdC5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICAgICAgYWNjID0geGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10oYWNjLCBsaXN0W2lkeF0pO1xuICAgICAgICAgICAgICAgIGlmIChhY2MgJiYgYWNjWydAQHRyYW5zZHVjZXIvcmVkdWNlZCddKSB7XG4gICAgICAgICAgICAgICAgICAgIGFjYyA9IGFjY1snQEB0cmFuc2R1Y2VyL3ZhbHVlJ107XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB4ZlsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddKGFjYyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX2l0ZXJhYmxlUmVkdWNlKHhmLCBhY2MsIGl0ZXIpIHtcbiAgICAgICAgICAgIHZhciBzdGVwID0gaXRlci5uZXh0KCk7XG4gICAgICAgICAgICB3aGlsZSAoIXN0ZXAuZG9uZSkge1xuICAgICAgICAgICAgICAgIGFjYyA9IHhmWydAQHRyYW5zZHVjZXIvc3RlcCddKGFjYywgc3RlcC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKGFjYyAmJiBhY2NbJ0BAdHJhbnNkdWNlci9yZWR1Y2VkJ10pIHtcbiAgICAgICAgICAgICAgICAgICAgYWNjID0gYWNjWydAQHRyYW5zZHVjZXIvdmFsdWUnXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0ZXAgPSBpdGVyLm5leHQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB4ZlsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddKGFjYyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX21ldGhvZFJlZHVjZSh4ZiwgYWNjLCBvYmopIHtcbiAgICAgICAgICAgIHJldHVybiB4ZlsnQEB0cmFuc2R1Y2VyL3Jlc3VsdCddKG9iai5yZWR1Y2UoYmluZCh4ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXSwgeGYpLCBhY2MpKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3ltSXRlcmF0b3IgPSB0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyA/IFN5bWJvbC5pdGVyYXRvciA6ICdAQGl0ZXJhdG9yJztcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIF9yZWR1Y2UoZm4sIGFjYywgbGlzdCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGZuID0gX3h3cmFwKGZuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0FycmF5TGlrZShsaXN0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfYXJyYXlSZWR1Y2UoZm4sIGFjYywgbGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIGxpc3QucmVkdWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9tZXRob2RSZWR1Y2UoZm4sIGFjYywgbGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGlzdFtzeW1JdGVyYXRvcl0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfaXRlcmFibGVSZWR1Y2UoZm4sIGFjYywgbGlzdFtzeW1JdGVyYXRvcl0oKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIGxpc3QubmV4dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBfaXRlcmFibGVSZWR1Y2UoZm4sIGFjYywgbGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWR1Y2U6IGxpc3QgbXVzdCBiZSBhcnJheSBvciBpdGVyYWJsZScpO1xuICAgICAgICB9O1xuICAgIH0oKTtcblxuICAgIHZhciBfc3RlcENhdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9zdGVwQ2F0QXJyYXkgPSB7XG4gICAgICAgICAgICAnQEB0cmFuc2R1Y2VyL2luaXQnOiBBcnJheSxcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvc3RlcCc6IGZ1bmN0aW9uICh4cywgeCkge1xuICAgICAgICAgICAgICAgIHhzLnB1c2goeCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvcmVzdWx0JzogX2lkZW50aXR5XG4gICAgICAgIH07XG4gICAgICAgIHZhciBfc3RlcENhdFN0cmluZyA9IHtcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvaW5pdCc6IFN0cmluZyxcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvc3RlcCc6IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgKyBiO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvcmVzdWx0JzogX2lkZW50aXR5XG4gICAgICAgIH07XG4gICAgICAgIHZhciBfc3RlcENhdE9iamVjdCA9IHtcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvaW5pdCc6IE9iamVjdCxcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvc3RlcCc6IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9hc3NpZ24ocmVzdWx0LCBpc0FycmF5TGlrZShpbnB1dCkgPyBvYmpPZihpbnB1dFswXSwgaW5wdXRbMV0pIDogaW5wdXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvcmVzdWx0JzogX2lkZW50aXR5XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBfc3RlcENhdChvYmopIHtcbiAgICAgICAgICAgIGlmIChfaXNUcmFuc2Zvcm1lcihvYmopKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0FycmF5TGlrZShvYmopKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9zdGVwQ2F0QXJyYXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3N0ZXBDYXRTdHJpbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3N0ZXBDYXRPYmplY3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjcmVhdGUgdHJhbnNmb3JtZXIgZm9yICcgKyBvYmopO1xuICAgICAgICB9O1xuICAgIH0oKTtcblxuICAgIHZhciBfeGRyb3BMYXN0V2hpbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFhEcm9wTGFzdFdoaWxlKGZuLCB4Zikge1xuICAgICAgICAgICAgdGhpcy5mID0gZm47XG4gICAgICAgICAgICB0aGlzLnJldGFpbmVkID0gW107XG4gICAgICAgICAgICB0aGlzLnhmID0geGY7XG4gICAgICAgIH1cbiAgICAgICAgWERyb3BMYXN0V2hpbGUucHJvdG90eXBlWydAQHRyYW5zZHVjZXIvaW5pdCddID0gX3hmQmFzZS5pbml0O1xuICAgICAgICBYRHJvcExhc3RXaGlsZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXSA9IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHRoaXMucmV0YWluZWQgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMueGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgICBYRHJvcExhc3RXaGlsZS5wcm90b3R5cGVbJ0BAdHJhbnNkdWNlci9zdGVwJ10gPSBmdW5jdGlvbiAocmVzdWx0LCBpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZihpbnB1dCkgPyB0aGlzLnJldGFpbihyZXN1bHQsIGlucHV0KSA6IHRoaXMuZmx1c2gocmVzdWx0LCBpbnB1dCk7XG4gICAgICAgIH07XG4gICAgICAgIFhEcm9wTGFzdFdoaWxlLnByb3RvdHlwZS5mbHVzaCA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICByZXN1bHQgPSBfcmVkdWNlKHRoaXMueGZbJ0BAdHJhbnNkdWNlci9zdGVwJ10sIHJlc3VsdCwgdGhpcy5yZXRhaW5lZCk7XG4gICAgICAgICAgICB0aGlzLnJldGFpbmVkID0gW107XG4gICAgICAgICAgICByZXR1cm4gdGhpcy54ZlsnQEB0cmFuc2R1Y2VyL3N0ZXAnXShyZXN1bHQsIGlucHV0KTtcbiAgICAgICAgfTtcbiAgICAgICAgWERyb3BMYXN0V2hpbGUucHJvdG90eXBlLnJldGFpbiA9IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICB0aGlzLnJldGFpbmVkLnB1c2goaW5wdXQpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9jdXJyeTIoZnVuY3Rpb24gX3hkcm9wTGFzdFdoaWxlKGZuLCB4Zikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBYRHJvcExhc3RXaGlsZShmbiwgeGYpO1xuICAgICAgICB9KTtcbiAgICB9KCk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGxpc3QgaXRlcmF0aW9uIGZ1bmN0aW9uIGZyb20gYW4gZXhpc3Rpbmcgb25lIGJ5IGFkZGluZyB0d28gbmV3XG4gICAgICogcGFyYW1ldGVycyB0byBpdHMgY2FsbGJhY2sgZnVuY3Rpb246IHRoZSBjdXJyZW50IGluZGV4LCBhbmQgdGhlIGVudGlyZSBsaXN0LlxuICAgICAqXG4gICAgICogVGhpcyB3b3VsZCB0dXJuLCBmb3IgaW5zdGFuY2UsIFJhbWRhJ3Mgc2ltcGxlIGBtYXBgIGZ1bmN0aW9uIGludG8gb25lIHRoYXRcbiAgICAgKiBtb3JlIGNsb3NlbHkgcmVzZW1ibGVzIGBBcnJheS5wcm90b3R5cGUubWFwYC4gTm90ZSB0aGF0IHRoaXMgd2lsbCBvbmx5IHdvcmtcbiAgICAgKiBmb3IgZnVuY3Rpb25zIGluIHdoaWNoIHRoZSBpdGVyYXRpb24gY2FsbGJhY2sgZnVuY3Rpb24gaXMgdGhlIGZpcnN0XG4gICAgICogcGFyYW1ldGVyLCBhbmQgd2hlcmUgdGhlIGxpc3QgaXMgdGhlIGxhc3QgcGFyYW1ldGVyLiAoVGhpcyBsYXR0ZXIgbWlnaHQgYmVcbiAgICAgKiB1bmltcG9ydGFudCBpZiB0aGUgbGlzdCBwYXJhbWV0ZXIgaXMgbm90IHVzZWQuKVxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnICgoYSAuLi4gLT4gYikgLi4uIC0+IFthXSAtPiAqKSAtPiAoYSAuLi4sIEludCwgW2FdIC0+IGIpIC4uLiAtPiBbYV0gLT4gKilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBBIGxpc3QgaXRlcmF0aW9uIGZ1bmN0aW9uIHRoYXQgZG9lcyBub3QgcGFzcyBpbmRleCBvciBsaXN0IHRvIGl0cyBjYWxsYmFja1xuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBbiBhbHRlcmVkIGxpc3QgaXRlcmF0aW9uIGZ1bmN0aW9uIHRoYXQgcGFzc2VzIChpdGVtLCBpbmRleCwgbGlzdCkgdG8gaXRzIGNhbGxiYWNrXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG1hcEluZGV4ZWQgPSBSLmFkZEluZGV4KFIubWFwKTtcbiAgICAgKiAgICAgIG1hcEluZGV4ZWQoKHZhbCwgaWR4KSA9PiBpZHggKyAnLScgKyB2YWwsIFsnZicsICdvJywgJ28nLCAnYicsICdhJywgJ3InXSk7XG4gICAgICogICAgICAvLz0+IFsnMC1mJywgJzEtbycsICcyLW8nLCAnMy1iJywgJzQtYScsICc1LXInXVxuICAgICAqL1xuICAgIHZhciBhZGRJbmRleCA9IF9jdXJyeTEoZnVuY3Rpb24gYWRkSW5kZXgoZm4pIHtcbiAgICAgICAgcmV0dXJuIGN1cnJ5Tihmbi5sZW5ndGgsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICAgICAgdmFyIG9yaWdGbiA9IGFyZ3VtZW50c1swXTtcbiAgICAgICAgICAgIHZhciBsaXN0ID0gYXJndW1lbnRzW2FyZ3VtZW50cy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIHZhciBhcmdzID0gX3NsaWNlKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICBhcmdzWzBdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBvcmlnRm4uYXBwbHkodGhpcywgX2NvbmNhdChhcmd1bWVudHMsIFtcbiAgICAgICAgICAgICAgICAgICAgaWR4LFxuICAgICAgICAgICAgICAgICAgICBsaXN0XG4gICAgICAgICAgICAgICAgXSkpO1xuICAgICAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFdyYXBzIGEgZnVuY3Rpb24gb2YgYW55IGFyaXR5IChpbmNsdWRpbmcgbnVsbGFyeSkgaW4gYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHNcbiAgICAgKiBleGFjdGx5IDIgcGFyYW1ldGVycy4gQW55IGV4dHJhbmVvdXMgcGFyYW1ldGVycyB3aWxsIG5vdCBiZSBwYXNzZWQgdG8gdGhlXG4gICAgICogc3VwcGxpZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjIuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgKCogLT4gYykgLT4gKGEsIGIgLT4gYylcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBuZXcgZnVuY3Rpb24gd3JhcHBpbmcgYGZuYC4gVGhlIG5ldyBmdW5jdGlvbiBpcyBndWFyYW50ZWVkIHRvIGJlIG9mXG4gICAgICogICAgICAgICBhcml0eSAyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB0YWtlc1RocmVlQXJncyA9IGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgICAgICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiAgICAgIH07XG4gICAgICogICAgICB0YWtlc1RocmVlQXJncy5sZW5ndGg7IC8vPT4gM1xuICAgICAqICAgICAgdGFrZXNUaHJlZUFyZ3MoMSwgMiwgMyk7IC8vPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB0YWtlc1R3b0FyZ3MgPSBSLmJpbmFyeSh0YWtlc1RocmVlQXJncyk7XG4gICAgICogICAgICB0YWtlc1R3b0FyZ3MubGVuZ3RoOyAvLz0+IDJcbiAgICAgKiAgICAgIC8vIE9ubHkgMiBhcmd1bWVudHMgYXJlIHBhc3NlZCB0byB0aGUgd3JhcHBlZCBmdW5jdGlvblxuICAgICAqICAgICAgdGFrZXNUd29BcmdzKDEsIDIsIDMpOyAvLz0+IFsxLCAyLCB1bmRlZmluZWRdXG4gICAgICovXG4gICAgdmFyIGJpbmFyeSA9IF9jdXJyeTEoZnVuY3Rpb24gYmluYXJ5KGZuKSB7XG4gICAgICAgIHJldHVybiBuQXJ5KDIsIGZuKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBkZWVwIGNvcHkgb2YgdGhlIHZhbHVlIHdoaWNoIG1heSBjb250YWluIChuZXN0ZWQpIGBBcnJheWBzIGFuZFxuICAgICAqIGBPYmplY3RgcywgYE51bWJlcmBzLCBgU3RyaW5nYHMsIGBCb29sZWFuYHMgYW5kIGBEYXRlYHMuIGBGdW5jdGlvbmBzIGFyZSBub3RcbiAgICAgKiBjb3BpZWQsIGJ1dCBhc3NpZ25lZCBieSB0aGVpciByZWZlcmVuY2UuXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIGEgYGNsb25lYCBtZXRob2QgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgeyp9IC0+IHsqfVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIG9iamVjdCBvciBhcnJheSB0byBjbG9uZVxuICAgICAqIEByZXR1cm4geyp9IEEgbmV3IG9iamVjdCBvciBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgb2JqZWN0cyA9IFt7fSwge30sIHt9XTtcbiAgICAgKiAgICAgIHZhciBvYmplY3RzQ2xvbmUgPSBSLmNsb25lKG9iamVjdHMpO1xuICAgICAqICAgICAgb2JqZWN0c1swXSA9PT0gb2JqZWN0c0Nsb25lWzBdOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGNsb25lID0gX2N1cnJ5MShmdW5jdGlvbiBjbG9uZSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUuY2xvbmUgPT09ICdmdW5jdGlvbicgPyB2YWx1ZS5jbG9uZSgpIDogX2Nsb25lKHZhbHVlLCBbXSwgW10sIHRydWUpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGN1cnJpZWQgZXF1aXZhbGVudCBvZiB0aGUgcHJvdmlkZWQgZnVuY3Rpb24uIFRoZSBjdXJyaWVkIGZ1bmN0aW9uXG4gICAgICogaGFzIHR3byB1bnVzdWFsIGNhcGFiaWxpdGllcy4gRmlyc3QsIGl0cyBhcmd1bWVudHMgbmVlZG4ndCBiZSBwcm92aWRlZCBvbmVcbiAgICAgKiBhdCBhIHRpbWUuIElmIGBmYCBpcyBhIHRlcm5hcnkgZnVuY3Rpb24gYW5kIGBnYCBpcyBgUi5jdXJyeShmKWAsIHRoZVxuICAgICAqIGZvbGxvd2luZyBhcmUgZXF1aXZhbGVudDpcbiAgICAgKlxuICAgICAqICAgLSBgZygxKSgyKSgzKWBcbiAgICAgKiAgIC0gYGcoMSkoMiwgMylgXG4gICAgICogICAtIGBnKDEsIDIpKDMpYFxuICAgICAqICAgLSBgZygxLCAyLCAzKWBcbiAgICAgKlxuICAgICAqIFNlY29uZGx5LCB0aGUgc3BlY2lhbCBwbGFjZWhvbGRlciB2YWx1ZSBgUi5fX2AgbWF5IGJlIHVzZWQgdG8gc3BlY2lmeVxuICAgICAqIFwiZ2Fwc1wiLCBhbGxvd2luZyBwYXJ0aWFsIGFwcGxpY2F0aW9uIG9mIGFueSBjb21iaW5hdGlvbiBvZiBhcmd1bWVudHMsXG4gICAgICogcmVnYXJkbGVzcyBvZiB0aGVpciBwb3NpdGlvbnMuIElmIGBnYCBpcyBhcyBhYm92ZSBhbmQgYF9gIGlzIGBSLl9fYCwgdGhlXG4gICAgICogZm9sbG93aW5nIGFyZSBlcXVpdmFsZW50OlxuICAgICAqXG4gICAgICogICAtIGBnKDEsIDIsIDMpYFxuICAgICAqICAgLSBgZyhfLCAyLCAzKSgxKWBcbiAgICAgKiAgIC0gYGcoXywgXywgMykoMSkoMilgXG4gICAgICogICAtIGBnKF8sIF8sIDMpKDEsIDIpYFxuICAgICAqICAgLSBgZyhfLCAyKSgxKSgzKWBcbiAgICAgKiAgIC0gYGcoXywgMikoMSwgMylgXG4gICAgICogICAtIGBnKF8sIDIpKF8sIDMpKDEpYFxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgqIC0+IGEpIC0+ICgqIC0+IGEpXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGN1cnJ5LlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIG5ldywgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAc2VlIFIuY3VycnlOXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGFkZEZvdXJOdW1iZXJzID0gKGEsIGIsIGMsIGQpID0+IGEgKyBiICsgYyArIGQ7XG4gICAgICpcbiAgICAgKiAgICAgIHZhciBjdXJyaWVkQWRkRm91ck51bWJlcnMgPSBSLmN1cnJ5KGFkZEZvdXJOdW1iZXJzKTtcbiAgICAgKiAgICAgIHZhciBmID0gY3VycmllZEFkZEZvdXJOdW1iZXJzKDEsIDIpO1xuICAgICAqICAgICAgdmFyIGcgPSBmKDMpO1xuICAgICAqICAgICAgZyg0KTsgLy89PiAxMFxuICAgICAqL1xuICAgIHZhciBjdXJyeSA9IF9jdXJyeTEoZnVuY3Rpb24gY3VycnkoZm4pIHtcbiAgICAgICAgcmV0dXJuIGN1cnJ5Tihmbi5sZW5ndGgsIGZuKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYWxsIGJ1dCB0aGUgZmlyc3QgYG5gIGVsZW1lbnRzIG9mIHRoZSBnaXZlbiBsaXN0LCBzdHJpbmcsIG9yXG4gICAgICogdHJhbnNkdWNlci90cmFuc2Zvcm1lciAob3Igb2JqZWN0IHdpdGggYSBgZHJvcGAgbWV0aG9kKS5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBkcm9wYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIE51bWJlciAtPiBbYV0gLT4gW2FdXG4gICAgICogQHNpZyBOdW1iZXIgLT4gU3RyaW5nIC0+IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuXG4gICAgICogQHBhcmFtIHsqfSBsaXN0XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIudGFrZSwgUi50cmFuc2R1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmRyb3AoMSwgWydmb28nLCAnYmFyJywgJ2JheiddKTsgLy89PiBbJ2JhcicsICdiYXonXVxuICAgICAqICAgICAgUi5kcm9wKDIsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gWydiYXonXVxuICAgICAqICAgICAgUi5kcm9wKDMsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gW11cbiAgICAgKiAgICAgIFIuZHJvcCg0LCBbJ2ZvbycsICdiYXInLCAnYmF6J10pOyAvLz0+IFtdXG4gICAgICogICAgICBSLmRyb3AoMywgJ3JhbWRhJyk7ICAgICAgICAgICAgICAgLy89PiAnZGEnXG4gICAgICovXG4gICAgdmFyIGRyb3AgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2Ryb3AnLCBfeGRyb3AsIGZ1bmN0aW9uIGRyb3AobiwgeHMpIHtcbiAgICAgICAgcmV0dXJuIHNsaWNlKE1hdGgubWF4KDAsIG4pLCBJbmZpbml0eSwgeHMpO1xuICAgIH0pKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBsaXN0IGNvbnRhaW5pbmcgYWxsIGJ1dCB0aGUgbGFzdCBgbmAgZWxlbWVudHMgb2YgdGhlIGdpdmVuIGBsaXN0YC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTYuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBOdW1iZXIgLT4gW2FdIC0+IFthXVxuICAgICAqIEBzaWcgTnVtYmVyIC0+IFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIG9mIGB4c2AgdG8gc2tpcC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB4cyBUaGUgY29sbGVjdGlvbiB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICAgKiBAc2VlIFIudGFrZUxhc3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmRyb3BMYXN0KDEsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gWydmb28nLCAnYmFyJ11cbiAgICAgKiAgICAgIFIuZHJvcExhc3QoMiwgWydmb28nLCAnYmFyJywgJ2JheiddKTsgLy89PiBbJ2ZvbyddXG4gICAgICogICAgICBSLmRyb3BMYXN0KDMsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gW11cbiAgICAgKiAgICAgIFIuZHJvcExhc3QoNCwgWydmb28nLCAnYmFyJywgJ2JheiddKTsgLy89PiBbXVxuICAgICAqICAgICAgUi5kcm9wTGFzdCgzLCAncmFtZGEnKTsgICAgICAgICAgICAgICAvLz0+ICdyYSdcbiAgICAgKi9cbiAgICB2YXIgZHJvcExhc3QgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2Ryb3BMYXN0JywgX3hkcm9wTGFzdCwgX2Ryb3BMYXN0KSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGxpc3QgZXhjbHVkaW5nIGFsbCB0aGUgdGFpbGluZyBlbGVtZW50cyBvZiBhIGdpdmVuIGxpc3Qgd2hpY2hcbiAgICAgKiBzYXRpc2Z5IHRoZSBzdXBwbGllZCBwcmVkaWNhdGUgZnVuY3Rpb24uIEl0IHBhc3NlcyBlYWNoIHZhbHVlIGZyb20gdGhlIHJpZ2h0XG4gICAgICogdG8gdGhlIHN1cHBsaWVkIHByZWRpY2F0ZSBmdW5jdGlvbiwgc2tpcHBpbmcgZWxlbWVudHMgd2hpbGUgdGhlIHByZWRpY2F0ZVxuICAgICAqIGZ1bmN0aW9uIHJldHVybnMgYHRydWVgLiBUaGUgcHJlZGljYXRlIGZ1bmN0aW9uIGlzIGFwcGxpZWQgdG8gb25lIGFyZ3VtZW50OlxuICAgICAqICoodmFsdWUpKi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTYuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoYSAtPiBCb29sZWFuKSAtPiBbYV0gLT4gW2FdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBIG5ldyBhcnJheS5cbiAgICAgKiBAc2VlIFIudGFrZUxhc3RXaGlsZSwgUi5hZGRJbmRleFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBsdGVUaHJlZSA9IHggPT4geCA8PSAzO1xuICAgICAqXG4gICAgICogICAgICBSLmRyb3BMYXN0V2hpbGUobHRlVGhyZWUsIFsxLCAyLCAzLCA0LCAzLCAyLCAxXSk7IC8vPT4gWzEsIDIsIDMsIDRdXG4gICAgICovXG4gICAgdmFyIGRyb3BMYXN0V2hpbGUgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2Ryb3BMYXN0V2hpbGUnLCBfeGRyb3BMYXN0V2hpbGUsIF9kcm9wTGFzdFdoaWxlKSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiBpdHMgYXJndW1lbnRzIGFyZSBlcXVpdmFsZW50LCBgZmFsc2VgIG90aGVyd2lzZS4gSGFuZGxlc1xuICAgICAqIGN5Y2xpY2FsIGRhdGEgc3RydWN0dXJlcy5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgc3ltbWV0cmljYWxseSB0byB0aGUgYGVxdWFsc2AgbWV0aG9kcyBvZiBib3RoIGFyZ3VtZW50cywgaWZcbiAgICAgKiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBhIC0+IGIgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7Kn0gYVxuICAgICAqIEBwYXJhbSB7Kn0gYlxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5lcXVhbHMoMSwgMSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5lcXVhbHMoMSwgJzEnKTsgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5lcXVhbHMoWzEsIDIsIDNdLCBbMSwgMiwgM10pOyAvLz0+IHRydWVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGEgPSB7fTsgYS52ID0gYTtcbiAgICAgKiAgICAgIHZhciBiID0ge307IGIudiA9IGI7XG4gICAgICogICAgICBSLmVxdWFscyhhLCBiKTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIGVxdWFscyA9IF9jdXJyeTIoZnVuY3Rpb24gZXF1YWxzKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIF9lcXVhbHMoYSwgYiwgW10sIFtdKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgcHJlZGljYXRlIGFuZCBhIFwiZmlsdGVyYWJsZVwiLCBhbmQgcmV0dXJucyBhIG5ldyBmaWx0ZXJhYmxlIG9mIHRoZVxuICAgICAqIHNhbWUgdHlwZSBjb250YWluaW5nIHRoZSBtZW1iZXJzIG9mIHRoZSBnaXZlbiBmaWx0ZXJhYmxlIHdoaWNoIHNhdGlzZnkgdGhlXG4gICAgICogZ2l2ZW4gcHJlZGljYXRlLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGZpbHRlcmAgbWV0aG9kIG9mIHRoZSBzZWNvbmQgYXJndW1lbnQsIGlmIHByZXNlbnQuXG4gICAgICpcbiAgICAgKiBBY3RzIGFzIGEgdHJhbnNkdWNlciBpZiBhIHRyYW5zZm9ybWVyIGlzIGdpdmVuIGluIGxpc3QgcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBGaWx0ZXJhYmxlIGYgPT4gKGEgLT4gQm9vbGVhbikgLT4gZiBhIC0+IGYgYVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXJhYmxlXG4gICAgICogQHJldHVybiB7QXJyYXl9XG4gICAgICogQHNlZSBSLnJlamVjdCwgUi50cmFuc2R1Y2UsIFIuYWRkSW5kZXhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNFdmVuID0gbiA9PiBuICUgMiA9PT0gMDtcbiAgICAgKlxuICAgICAqICAgICAgUi5maWx0ZXIoaXNFdmVuLCBbMSwgMiwgMywgNF0pOyAvLz0+IFsyLCA0XVxuICAgICAqXG4gICAgICogICAgICBSLmZpbHRlcihpc0V2ZW4sIHthOiAxLCBiOiAyLCBjOiAzLCBkOiA0fSk7IC8vPT4ge2I6IDIsIGQ6IDR9XG4gICAgICovXG4gICAgLy8gZWxzZVxuICAgIHZhciBmaWx0ZXIgPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2ZpbHRlcicsIF94ZmlsdGVyLCBmdW5jdGlvbiAocHJlZCwgZmlsdGVyYWJsZSkge1xuICAgICAgICByZXR1cm4gX2lzT2JqZWN0KGZpbHRlcmFibGUpID8gX3JlZHVjZShmdW5jdGlvbiAoYWNjLCBrZXkpIHtcbiAgICAgICAgICAgIGlmIChwcmVkKGZpbHRlcmFibGVba2V5XSkpIHtcbiAgICAgICAgICAgICAgICBhY2Nba2V5XSA9IGZpbHRlcmFibGVba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIH0sIHt9LCBrZXlzKGZpbHRlcmFibGUpKSA6IC8vIGVsc2VcbiAgICAgICAgX2ZpbHRlcihwcmVkLCBmaWx0ZXJhYmxlKTtcbiAgICB9KSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGxpc3QgYnkgcHVsbGluZyBldmVyeSBpdGVtIG91dCBvZiBpdCAoYW5kIGFsbCBpdHMgc3ViLWFycmF5cylcbiAgICAgKiBhbmQgcHV0dGluZyB0aGVtIGluIGEgbmV3IGFycmF5LCBkZXB0aC1maXJzdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIFthXSAtPiBbYl1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGZsYXR0ZW5lZCBsaXN0LlxuICAgICAqIEBzZWUgUi51bm5lc3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmZsYXR0ZW4oWzEsIDIsIFszLCA0XSwgNSwgWzYsIFs3LCA4LCBbOSwgWzEwLCAxMV0sIDEyXV1dXSk7XG4gICAgICogICAgICAvLz0+IFsxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyXVxuICAgICAqL1xuICAgIHZhciBmbGF0dGVuID0gX2N1cnJ5MShfbWFrZUZsYXQodHJ1ZSkpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBmdW5jdGlvbiBtdWNoIGxpa2UgdGhlIHN1cHBsaWVkIG9uZSwgZXhjZXB0IHRoYXQgdGhlIGZpcnN0IHR3b1xuICAgICAqIGFyZ3VtZW50cycgb3JkZXIgaXMgcmV2ZXJzZWQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgKGEgLT4gYiAtPiBjIC0+IC4uLiAtPiB6KSAtPiAoYiAtPiBhIC0+IGMgLT4gLi4uIC0+IHopXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGludm9rZSB3aXRoIGl0cyBmaXJzdCB0d28gcGFyYW1ldGVycyByZXZlcnNlZC5cbiAgICAgKiBAcmV0dXJuIHsqfSBUaGUgcmVzdWx0IG9mIGludm9raW5nIGBmbmAgd2l0aCBpdHMgZmlyc3QgdHdvIHBhcmFtZXRlcnMnIG9yZGVyIHJldmVyc2VkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBtZXJnZVRocmVlID0gKGEsIGIsIGMpID0+IFtdLmNvbmNhdChhLCBiLCBjKTtcbiAgICAgKlxuICAgICAqICAgICAgbWVyZ2VUaHJlZSgxLCAyLCAzKTsgLy89PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqICAgICAgUi5mbGlwKG1lcmdlVGhyZWUpKDEsIDIsIDMpOyAvLz0+IFsyLCAxLCAzXVxuICAgICAqL1xuICAgIHZhciBmbGlwID0gX2N1cnJ5MShmdW5jdGlvbiBmbGlwKGZuKSB7XG4gICAgICAgIHJldHVybiBjdXJyeShmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBfc2xpY2UoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGFyZ3NbMF0gPSBiO1xuICAgICAgICAgICAgYXJnc1sxXSA9IGE7XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgZ2l2ZW4gbGlzdCBvciBzdHJpbmcuIEluIHNvbWUgbGlicmFyaWVzXG4gICAgICogdGhpcyBmdW5jdGlvbiBpcyBuYW1lZCBgZmlyc3RgLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgW2FdIC0+IGEgfCBVbmRlZmluZWRcbiAgICAgKiBAc2lnIFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge0FycmF5fFN0cmluZ30gbGlzdFxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHNlZSBSLnRhaWwsIFIuaW5pdCwgUi5sYXN0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5oZWFkKFsnZmknLCAnZm8nLCAnZnVtJ10pOyAvLz0+ICdmaSdcbiAgICAgKiAgICAgIFIuaGVhZChbXSk7IC8vPT4gdW5kZWZpbmVkXG4gICAgICpcbiAgICAgKiAgICAgIFIuaGVhZCgnYWJjJyk7IC8vPT4gJ2EnXG4gICAgICogICAgICBSLmhlYWQoJycpOyAvLz0+ICcnXG4gICAgICovXG4gICAgdmFyIGhlYWQgPSBudGgoMCk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFsbCBidXQgdGhlIGxhc3QgZWxlbWVudCBvZiB0aGUgZ2l2ZW4gbGlzdCBvciBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjkuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBbYV0gLT4gW2FdXG4gICAgICogQHNpZyBTdHJpbmcgLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHsqfSBsaXN0XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIubGFzdCwgUi5oZWFkLCBSLnRhaWxcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmluaXQoWzEsIDIsIDNdKTsgIC8vPT4gWzEsIDJdXG4gICAgICogICAgICBSLmluaXQoWzEsIDJdKTsgICAgIC8vPT4gWzFdXG4gICAgICogICAgICBSLmluaXQoWzFdKTsgICAgICAgIC8vPT4gW11cbiAgICAgKiAgICAgIFIuaW5pdChbXSk7ICAgICAgICAgLy89PiBbXVxuICAgICAqXG4gICAgICogICAgICBSLmluaXQoJ2FiYycpOyAgLy89PiAnYWInXG4gICAgICogICAgICBSLmluaXQoJ2FiJyk7ICAgLy89PiAnYSdcbiAgICAgKiAgICAgIFIuaW5pdCgnYScpOyAgICAvLz0+ICcnXG4gICAgICogICAgICBSLmluaXQoJycpOyAgICAgLy89PiAnJ1xuICAgICAqL1xuICAgIHZhciBpbml0ID0gc2xpY2UoMCwgLTEpO1xuXG4gICAgLyoqXG4gICAgICogQ29tYmluZXMgdHdvIGxpc3RzIGludG8gYSBzZXQgKGkuZS4gbm8gZHVwbGljYXRlcykgY29tcG9zZWQgb2YgdGhvc2VcbiAgICAgKiBlbGVtZW50cyBjb21tb24gdG8gYm90aCBsaXN0cy4gRHVwbGljYXRpb24gaXMgZGV0ZXJtaW5lZCBhY2NvcmRpbmcgdG8gdGhlXG4gICAgICogdmFsdWUgcmV0dXJuZWQgYnkgYXBwbHlpbmcgdGhlIHN1cHBsaWVkIHByZWRpY2F0ZSB0byB0d28gbGlzdCBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyAoYSAtPiBhIC0+IEJvb2xlYW4pIC0+IFsqXSAtPiBbKl0gLT4gWypdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZCBBIHByZWRpY2F0ZSBmdW5jdGlvbiB0aGF0IGRldGVybWluZXMgd2hldGhlclxuICAgICAqICAgICAgICB0aGUgdHdvIHN1cHBsaWVkIGVsZW1lbnRzIGFyZSBlcXVhbC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MSBPbmUgbGlzdCBvZiBpdGVtcyB0byBjb21wYXJlXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdDIgQSBzZWNvbmQgbGlzdCBvZiBpdGVtcyB0byBjb21wYXJlXG4gICAgICogQHJldHVybiB7QXJyYXl9IEEgbmV3IGxpc3QgY29udGFpbmluZyB0aG9zZSBlbGVtZW50cyBjb21tb24gdG8gYm90aCBsaXN0cy5cbiAgICAgKiBAc2VlIFIuaW50ZXJzZWN0aW9uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGJ1ZmZhbG9TcHJpbmdmaWVsZCA9IFtcbiAgICAgKiAgICAgICAge2lkOiA4MjQsIG5hbWU6ICdSaWNoaWUgRnVyYXknfSxcbiAgICAgKiAgICAgICAge2lkOiA5NTYsIG5hbWU6ICdEZXdleSBNYXJ0aW4nfSxcbiAgICAgKiAgICAgICAge2lkOiAzMTMsIG5hbWU6ICdCcnVjZSBQYWxtZXInfSxcbiAgICAgKiAgICAgICAge2lkOiA0NTYsIG5hbWU6ICdTdGVwaGVuIFN0aWxscyd9LFxuICAgICAqICAgICAgICB7aWQ6IDE3NywgbmFtZTogJ05laWwgWW91bmcnfVxuICAgICAqICAgICAgXTtcbiAgICAgKiAgICAgIHZhciBjc255ID0gW1xuICAgICAqICAgICAgICB7aWQ6IDIwNCwgbmFtZTogJ0RhdmlkIENyb3NieSd9LFxuICAgICAqICAgICAgICB7aWQ6IDQ1NiwgbmFtZTogJ1N0ZXBoZW4gU3RpbGxzJ30sXG4gICAgICogICAgICAgIHtpZDogNTM5LCBuYW1lOiAnR3JhaGFtIE5hc2gnfSxcbiAgICAgKiAgICAgICAge2lkOiAxNzcsIG5hbWU6ICdOZWlsIFlvdW5nJ31cbiAgICAgKiAgICAgIF07XG4gICAgICpcbiAgICAgKiAgICAgIFIuaW50ZXJzZWN0aW9uV2l0aChSLmVxQnkoUi5wcm9wKCdpZCcpKSwgYnVmZmFsb1NwcmluZ2ZpZWxkLCBjc255KTtcbiAgICAgKiAgICAgIC8vPT4gW3tpZDogNDU2LCBuYW1lOiAnU3RlcGhlbiBTdGlsbHMnfSwge2lkOiAxNzcsIG5hbWU6ICdOZWlsIFlvdW5nJ31dXG4gICAgICovXG4gICAgdmFyIGludGVyc2VjdGlvbldpdGggPSBfY3VycnkzKGZ1bmN0aW9uIGludGVyc2VjdGlvbldpdGgocHJlZCwgbGlzdDEsIGxpc3QyKSB7XG4gICAgICAgIHZhciBsb29rdXBMaXN0LCBmaWx0ZXJlZExpc3Q7XG4gICAgICAgIGlmIChsaXN0MS5sZW5ndGggPiBsaXN0Mi5sZW5ndGgpIHtcbiAgICAgICAgICAgIGxvb2t1cExpc3QgPSBsaXN0MTtcbiAgICAgICAgICAgIGZpbHRlcmVkTGlzdCA9IGxpc3QyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9va3VwTGlzdCA9IGxpc3QyO1xuICAgICAgICAgICAgZmlsdGVyZWRMaXN0ID0gbGlzdDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgIHdoaWxlIChpZHggPCBmaWx0ZXJlZExpc3QubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoX2NvbnRhaW5zV2l0aChwcmVkLCBmaWx0ZXJlZExpc3RbaWR4XSwgbG9va3VwTGlzdCkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRzW3Jlc3VsdHMubGVuZ3RoXSA9IGZpbHRlcmVkTGlzdFtpZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuaXFXaXRoKHByZWQsIHJlc3VsdHMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVHJhbnNmb3JtcyB0aGUgaXRlbXMgb2YgdGhlIGxpc3Qgd2l0aCB0aGUgdHJhbnNkdWNlciBhbmQgYXBwZW5kcyB0aGVcbiAgICAgKiB0cmFuc2Zvcm1lZCBpdGVtcyB0byB0aGUgYWNjdW11bGF0b3IgdXNpbmcgYW4gYXBwcm9wcmlhdGUgaXRlcmF0b3IgZnVuY3Rpb25cbiAgICAgKiBiYXNlZCBvbiB0aGUgYWNjdW11bGF0b3IgdHlwZS5cbiAgICAgKlxuICAgICAqIFRoZSBhY2N1bXVsYXRvciBjYW4gYmUgYW4gYXJyYXksIHN0cmluZywgb2JqZWN0IG9yIGEgdHJhbnNmb3JtZXIuIEl0ZXJhdGVkXG4gICAgICogaXRlbXMgd2lsbCBiZSBhcHBlbmRlZCB0byBhcnJheXMgYW5kIGNvbmNhdGVuYXRlZCB0byBzdHJpbmdzLiBPYmplY3RzIHdpbGxcbiAgICAgKiBiZSBtZXJnZWQgZGlyZWN0bHkgb3IgMi1pdGVtIGFycmF5cyB3aWxsIGJlIG1lcmdlZCBhcyBrZXksIHZhbHVlIHBhaXJzLlxuICAgICAqXG4gICAgICogVGhlIGFjY3VtdWxhdG9yIGNhbiBhbHNvIGJlIGEgdHJhbnNmb3JtZXIgb2JqZWN0IHRoYXQgcHJvdmlkZXMgYSAyLWFyaXR5XG4gICAgICogcmVkdWNpbmcgaXRlcmF0b3IgZnVuY3Rpb24sIHN0ZXAsIDAtYXJpdHkgaW5pdGlhbCB2YWx1ZSBmdW5jdGlvbiwgaW5pdCwgYW5kXG4gICAgICogMS1hcml0eSByZXN1bHQgZXh0cmFjdGlvbiBmdW5jdGlvbiByZXN1bHQuIFRoZSBzdGVwIGZ1bmN0aW9uIGlzIHVzZWQgYXMgdGhlXG4gICAgICogaXRlcmF0b3IgZnVuY3Rpb24gaW4gcmVkdWNlLiBUaGUgcmVzdWx0IGZ1bmN0aW9uIGlzIHVzZWQgdG8gY29udmVydCB0aGVcbiAgICAgKiBmaW5hbCBhY2N1bXVsYXRvciBpbnRvIHRoZSByZXR1cm4gdHlwZSBhbmQgaW4gbW9zdCBjYXNlcyBpcyBSLmlkZW50aXR5LiBUaGVcbiAgICAgKiBpbml0IGZ1bmN0aW9uIGlzIHVzZWQgdG8gcHJvdmlkZSB0aGUgaW5pdGlhbCBhY2N1bXVsYXRvci5cbiAgICAgKlxuICAgICAqIFRoZSBpdGVyYXRpb24gaXMgcGVyZm9ybWVkIHdpdGggUi5yZWR1Y2UgYWZ0ZXIgaW5pdGlhbGl6aW5nIHRoZSB0cmFuc2R1Y2VyLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMi4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIGEgLT4gKGIgLT4gYikgLT4gW2NdIC0+IGFcbiAgICAgKiBAcGFyYW0geyp9IGFjYyBUaGUgaW5pdGlhbCBhY2N1bXVsYXRvciB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB4ZiBUaGUgdHJhbnNkdWNlciBmdW5jdGlvbi4gUmVjZWl2ZXMgYSB0cmFuc2Zvcm1lciBhbmQgcmV0dXJucyBhIHRyYW5zZm9ybWVyLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBmaW5hbCwgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG51bWJlcnMgPSBbMSwgMiwgMywgNF07XG4gICAgICogICAgICB2YXIgdHJhbnNkdWNlciA9IFIuY29tcG9zZShSLm1hcChSLmFkZCgxKSksIFIudGFrZSgyKSk7XG4gICAgICpcbiAgICAgKiAgICAgIFIuaW50byhbXSwgdHJhbnNkdWNlciwgbnVtYmVycyk7IC8vPT4gWzIsIDNdXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBpbnRvQXJyYXkgPSBSLmludG8oW10pO1xuICAgICAqICAgICAgaW50b0FycmF5KHRyYW5zZHVjZXIsIG51bWJlcnMpOyAvLz0+IFsyLCAzXVxuICAgICAqL1xuICAgIHZhciBpbnRvID0gX2N1cnJ5MyhmdW5jdGlvbiBpbnRvKGFjYywgeGYsIGxpc3QpIHtcbiAgICAgICAgcmV0dXJuIF9pc1RyYW5zZm9ybWVyKGFjYykgPyBfcmVkdWNlKHhmKGFjYyksIGFjY1snQEB0cmFuc2R1Y2VyL2luaXQnXSgpLCBsaXN0KSA6IF9yZWR1Y2UoeGYoX3N0ZXBDYXQoYWNjKSksIF9jbG9uZShhY2MsIFtdLCBbXSwgZmFsc2UpLCBsaXN0KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNhbWUgYXMgUi5pbnZlcnRPYmosIGhvd2V2ZXIgdGhpcyBhY2NvdW50cyBmb3Igb2JqZWN0cyB3aXRoIGR1cGxpY2F0ZSB2YWx1ZXNcbiAgICAgKiBieSBwdXR0aW5nIHRoZSB2YWx1ZXMgaW50byBhbiBhcnJheS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcge3M6IHh9IC0+IHt4OiBbIHMsIC4uLiBdfVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCBvciBhcnJheSB0byBpbnZlcnRcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IG91dCBBIG5ldyBvYmplY3Qgd2l0aCBrZXlzXG4gICAgICogaW4gYW4gYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHJhY2VSZXN1bHRzQnlGaXJzdE5hbWUgPSB7XG4gICAgICogICAgICAgIGZpcnN0OiAnYWxpY2UnLFxuICAgICAqICAgICAgICBzZWNvbmQ6ICdqYWtlJyxcbiAgICAgKiAgICAgICAgdGhpcmQ6ICdhbGljZScsXG4gICAgICogICAgICB9O1xuICAgICAqICAgICAgUi5pbnZlcnQocmFjZVJlc3VsdHNCeUZpcnN0TmFtZSk7XG4gICAgICogICAgICAvLz0+IHsgJ2FsaWNlJzogWydmaXJzdCcsICd0aGlyZCddLCAnamFrZSc6WydzZWNvbmQnXSB9XG4gICAgICovXG4gICAgdmFyIGludmVydCA9IF9jdXJyeTEoZnVuY3Rpb24gaW52ZXJ0KG9iaikge1xuICAgICAgICB2YXIgcHJvcHMgPSBrZXlzKG9iaik7XG4gICAgICAgIHZhciBsZW4gPSBwcm9wcy5sZW5ndGg7XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgb3V0ID0ge307XG4gICAgICAgIHdoaWxlIChpZHggPCBsZW4pIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSBwcm9wc1tpZHhdO1xuICAgICAgICAgICAgdmFyIHZhbCA9IG9ialtrZXldO1xuICAgICAgICAgICAgdmFyIGxpc3QgPSBfaGFzKHZhbCwgb3V0KSA/IG91dFt2YWxdIDogb3V0W3ZhbF0gPSBbXTtcbiAgICAgICAgICAgIGxpc3RbbGlzdC5sZW5ndGhdID0ga2V5O1xuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggdGhlIGtleXMgb2YgdGhlIGdpdmVuIG9iamVjdCBhcyB2YWx1ZXMsIGFuZCB0aGVcbiAgICAgKiB2YWx1ZXMgb2YgdGhlIGdpdmVuIG9iamVjdCwgd2hpY2ggYXJlIGNvZXJjZWQgdG8gc3RyaW5ncywgYXMga2V5cy4gTm90ZVxuICAgICAqIHRoYXQgdGhlIGxhc3Qga2V5IGZvdW5kIGlzIHByZWZlcnJlZCB3aGVuIGhhbmRsaW5nIHRoZSBzYW1lIHZhbHVlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC45LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyB7czogeH0gLT4ge3g6IHN9XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IG9yIGFycmF5IHRvIGludmVydFxuICAgICAqIEByZXR1cm4ge09iamVjdH0gb3V0IEEgbmV3IG9iamVjdFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciByYWNlUmVzdWx0cyA9IHtcbiAgICAgKiAgICAgICAgZmlyc3Q6ICdhbGljZScsXG4gICAgICogICAgICAgIHNlY29uZDogJ2pha2UnXG4gICAgICogICAgICB9O1xuICAgICAqICAgICAgUi5pbnZlcnRPYmoocmFjZVJlc3VsdHMpO1xuICAgICAqICAgICAgLy89PiB7ICdhbGljZSc6ICdmaXJzdCcsICdqYWtlJzonc2Vjb25kJyB9XG4gICAgICpcbiAgICAgKiAgICAgIC8vIEFsdGVybmF0aXZlbHk6XG4gICAgICogICAgICB2YXIgcmFjZVJlc3VsdHMgPSBbJ2FsaWNlJywgJ2pha2UnXTtcbiAgICAgKiAgICAgIFIuaW52ZXJ0T2JqKHJhY2VSZXN1bHRzKTtcbiAgICAgKiAgICAgIC8vPT4geyAnYWxpY2UnOiAnMCcsICdqYWtlJzonMScgfVxuICAgICAqL1xuICAgIHZhciBpbnZlcnRPYmogPSBfY3VycnkxKGZ1bmN0aW9uIGludmVydE9iaihvYmopIHtcbiAgICAgICAgdmFyIHByb3BzID0ga2V5cyhvYmopO1xuICAgICAgICB2YXIgbGVuID0gcHJvcHMubGVuZ3RoO1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIG91dCA9IHt9O1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gcHJvcHNbaWR4XTtcbiAgICAgICAgICAgIG91dFtvYmpba2V5XV0gPSBrZXk7XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHZhbHVlIGlzIGl0cyB0eXBlJ3MgZW1wdHkgdmFsdWU7IGBmYWxzZWBcbiAgICAgKiBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgYSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHsqfSB4XG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiBAc2VlIFIuZW1wdHlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmlzRW1wdHkoWzEsIDIsIDNdKTsgICAvLz0+IGZhbHNlXG4gICAgICogICAgICBSLmlzRW1wdHkoW10pOyAgICAgICAgICAvLz0+IHRydWVcbiAgICAgKiAgICAgIFIuaXNFbXB0eSgnJyk7ICAgICAgICAgIC8vPT4gdHJ1ZVxuICAgICAqICAgICAgUi5pc0VtcHR5KG51bGwpOyAgICAgICAgLy89PiBmYWxzZVxuICAgICAqICAgICAgUi5pc0VtcHR5KHt9KTsgICAgICAgICAgLy89PiB0cnVlXG4gICAgICogICAgICBSLmlzRW1wdHkoe2xlbmd0aDogMH0pOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzRW1wdHkgPSBfY3VycnkxKGZ1bmN0aW9uIGlzRW1wdHkoeCkge1xuICAgICAgICByZXR1cm4geCAhPSBudWxsICYmIGVxdWFscyh4LCBlbXB0eSh4KSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBsYXN0IGVsZW1lbnQgb2YgdGhlIGdpdmVuIGxpc3Qgb3Igc3RyaW5nLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjRcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgW2FdIC0+IGEgfCBVbmRlZmluZWRcbiAgICAgKiBAc2lnIFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0geyp9IGxpc3RcbiAgICAgKiBAcmV0dXJuIHsqfVxuICAgICAqIEBzZWUgUi5pbml0LCBSLmhlYWQsIFIudGFpbFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIubGFzdChbJ2ZpJywgJ2ZvJywgJ2Z1bSddKTsgLy89PiAnZnVtJ1xuICAgICAqICAgICAgUi5sYXN0KFtdKTsgLy89PiB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqICAgICAgUi5sYXN0KCdhYmMnKTsgLy89PiAnYydcbiAgICAgKiAgICAgIFIubGFzdCgnJyk7IC8vPT4gJydcbiAgICAgKi9cbiAgICB2YXIgbGFzdCA9IG50aCgtMSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIGFuIGl0ZW0gaW4gYW4gYXJyYXksIG9yIC0xIGlmXG4gICAgICogdGhlIGl0ZW0gaXMgbm90IGluY2x1ZGVkIGluIHRoZSBhcnJheS4gYFIuZXF1YWxzYCBpcyB1c2VkIHRvIGRldGVybWluZVxuICAgICAqIGVxdWFsaXR5LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgYSAtPiBbYV0gLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHsqfSB0YXJnZXQgVGhlIGl0ZW0gdG8gZmluZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB4cyBUaGUgYXJyYXkgdG8gc2VhcmNoIGluLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gdGhlIGluZGV4IG9mIHRoZSB0YXJnZXQsIG9yIC0xIGlmIHRoZSB0YXJnZXQgaXMgbm90IGZvdW5kLlxuICAgICAqIEBzZWUgUi5pbmRleE9mXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5sYXN0SW5kZXhPZigzLCBbLTEsMywzLDAsMSwyLDMsNF0pOyAvLz0+IDZcbiAgICAgKiAgICAgIFIubGFzdEluZGV4T2YoMTAsIFsxLDIsMyw0XSk7IC8vPT4gLTFcbiAgICAgKi9cbiAgICB2YXIgbGFzdEluZGV4T2YgPSBfY3VycnkyKGZ1bmN0aW9uIGxhc3RJbmRleE9mKHRhcmdldCwgeHMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB4cy5sYXN0SW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJyAmJiAhX2lzQXJyYXkoeHMpKSB7XG4gICAgICAgICAgICByZXR1cm4geHMubGFzdEluZGV4T2YodGFyZ2V0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBpZHggPSB4cy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUgKGlkeCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVxdWFscyh4c1tpZHhdLCB0YXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpZHg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlkeCAtPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGZ1bmN0aW9uIGFuZFxuICAgICAqIGEgW2Z1bmN0b3JdKGh0dHBzOi8vZ2l0aHViLmNvbS9mYW50YXN5bGFuZC9mYW50YXN5LWxhbmQjZnVuY3RvciksXG4gICAgICogYXBwbGllcyB0aGUgZnVuY3Rpb24gdG8gZWFjaCBvZiB0aGUgZnVuY3RvcidzIHZhbHVlcywgYW5kIHJldHVybnNcbiAgICAgKiBhIGZ1bmN0b3Igb2YgdGhlIHNhbWUgc2hhcGUuXG4gICAgICpcbiAgICAgKiBSYW1kYSBwcm92aWRlcyBzdWl0YWJsZSBgbWFwYCBpbXBsZW1lbnRhdGlvbnMgZm9yIGBBcnJheWAgYW5kIGBPYmplY3RgLFxuICAgICAqIHNvIHRoaXMgZnVuY3Rpb24gbWF5IGJlIGFwcGxpZWQgdG8gYFsxLCAyLCAzXWAgb3IgYHt4OiAxLCB5OiAyLCB6OiAzfWAuXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgbWFwYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEFsc28gdHJlYXRzIGZ1bmN0aW9ucyBhcyBmdW5jdG9ycyBhbmQgd2lsbCBjb21wb3NlIHRoZW0gdG9nZXRoZXIuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBGdW5jdG9yIGYgPT4gKGEgLT4gYikgLT4gZiBhIC0+IGYgYlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb24gZXZlcnkgZWxlbWVudCBvZiB0aGUgaW5wdXQgYGxpc3RgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gYmUgaXRlcmF0ZWQgb3Zlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIG5ldyBsaXN0LlxuICAgICAqIEBzZWUgUi50cmFuc2R1Y2UsIFIuYWRkSW5kZXhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZG91YmxlID0geCA9PiB4ICogMjtcbiAgICAgKlxuICAgICAqICAgICAgUi5tYXAoZG91YmxlLCBbMSwgMiwgM10pOyAvLz0+IFsyLCA0LCA2XVxuICAgICAqXG4gICAgICogICAgICBSLm1hcChkb3VibGUsIHt4OiAxLCB5OiAyLCB6OiAzfSk7IC8vPT4ge3g6IDIsIHk6IDQsIHo6IDZ9XG4gICAgICovXG4gICAgdmFyIG1hcCA9IF9jdXJyeTIoX2Rpc3BhdGNoYWJsZSgnbWFwJywgX3htYXAsIGZ1bmN0aW9uIG1hcChmbiwgZnVuY3Rvcikge1xuICAgICAgICBzd2l0Y2ggKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChmdW5jdG9yKSkge1xuICAgICAgICBjYXNlICdbb2JqZWN0IEZ1bmN0aW9uXSc6XG4gICAgICAgICAgICByZXR1cm4gY3VycnlOKGZ1bmN0b3IubGVuZ3RoLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZuLmNhbGwodGhpcywgZnVuY3Rvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlICdbb2JqZWN0IE9iamVjdF0nOlxuICAgICAgICAgICAgcmV0dXJuIF9yZWR1Y2UoZnVuY3Rpb24gKGFjYywga2V5KSB7XG4gICAgICAgICAgICAgICAgYWNjW2tleV0gPSBmbihmdW5jdG9yW2tleV0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgICB9LCB7fSwga2V5cyhmdW5jdG9yKSk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gX21hcChmbiwgZnVuY3Rvcik7XG4gICAgICAgIH1cbiAgICB9KSk7XG5cbiAgICAvKipcbiAgICAgKiBBbiBPYmplY3Qtc3BlY2lmaWMgdmVyc2lvbiBvZiBgbWFwYC4gVGhlIGZ1bmN0aW9uIGlzIGFwcGxpZWQgdG8gdGhyZWVcbiAgICAgKiBhcmd1bWVudHM6ICoodmFsdWUsIGtleSwgb2JqKSouIElmIG9ubHkgdGhlIHZhbHVlIGlzIHNpZ25pZmljYW50LCB1c2VcbiAgICAgKiBgbWFwYCBpbnN0ZWFkLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC45LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyAoKCosIFN0cmluZywgT2JqZWN0KSAtPiAqKSAtPiBPYmplY3QgLT4gT2JqZWN0XG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gICAgICogQHJldHVybiB7T2JqZWN0fVxuICAgICAqIEBzZWUgUi5tYXBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgdmFsdWVzID0geyB4OiAxLCB5OiAyLCB6OiAzIH07XG4gICAgICogICAgICB2YXIgcHJlcGVuZEtleUFuZERvdWJsZSA9IChudW0sIGtleSwgb2JqKSA9PiBrZXkgKyAobnVtICogMik7XG4gICAgICpcbiAgICAgKiAgICAgIFIubWFwT2JqSW5kZXhlZChwcmVwZW5kS2V5QW5kRG91YmxlLCB2YWx1ZXMpOyAvLz0+IHsgeDogJ3gyJywgeTogJ3k0JywgejogJ3o2JyB9XG4gICAgICovXG4gICAgdmFyIG1hcE9iakluZGV4ZWQgPSBfY3VycnkyKGZ1bmN0aW9uIG1hcE9iakluZGV4ZWQoZm4sIG9iaikge1xuICAgICAgICByZXR1cm4gX3JlZHVjZShmdW5jdGlvbiAoYWNjLCBrZXkpIHtcbiAgICAgICAgICAgIGFjY1trZXldID0gZm4ob2JqW2tleV0sIGtleSwgb2JqKTtcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIH0sIHt9LCBrZXlzKG9iaikpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgb3duIHByb3BlcnRpZXMgb2YgdGhlIHR3byBwcm92aWRlZCBvYmplY3RzLiBJZlxuICAgICAqIGEga2V5IGV4aXN0cyBpbiBib3RoIG9iamVjdHMsIHRoZSBwcm92aWRlZCBmdW5jdGlvbiBpcyBhcHBsaWVkIHRvIHRoZSB2YWx1ZXNcbiAgICAgKiBhc3NvY2lhdGVkIHdpdGggdGhlIGtleSBpbiBlYWNoIG9iamVjdCwgd2l0aCB0aGUgcmVzdWx0IGJlaW5nIHVzZWQgYXMgdGhlXG4gICAgICogdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIG9iamVjdC4gVGhlIGtleSB3aWxsIGJlXG4gICAgICogZXhjbHVkZWQgZnJvbSB0aGUgcmV0dXJuZWQgb2JqZWN0IGlmIHRoZSByZXN1bHRpbmcgdmFsdWUgaXMgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHNpZyAoYSAtPiBhIC0+IGEpIC0+IHthfSAtPiB7YX0gLT4ge2F9XG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSByXG4gICAgICogQHJldHVybiB7T2JqZWN0fVxuICAgICAqIEBzZWUgUi5tZXJnZSwgUi5tZXJnZVdpdGhLZXlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLm1lcmdlV2l0aChSLmNvbmNhdCxcbiAgICAgKiAgICAgICAgICAgICAgICAgIHsgYTogdHJ1ZSwgdmFsdWVzOiBbMTAsIDIwXSB9LFxuICAgICAqICAgICAgICAgICAgICAgICAgeyBiOiB0cnVlLCB2YWx1ZXM6IFsxNSwgMzVdIH0pO1xuICAgICAqICAgICAgLy89PiB7IGE6IHRydWUsIGI6IHRydWUsIHZhbHVlczogWzEwLCAyMCwgMTUsIDM1XSB9XG4gICAgICovXG4gICAgdmFyIG1lcmdlV2l0aCA9IF9jdXJyeTMoZnVuY3Rpb24gbWVyZ2VXaXRoKGZuLCBsLCByKSB7XG4gICAgICAgIHJldHVybiBtZXJnZVdpdGhLZXkoZnVuY3Rpb24gKF8sIF9sLCBfcikge1xuICAgICAgICAgICAgcmV0dXJuIGZuKF9sLCBfcik7XG4gICAgICAgIH0sIGwsIHIpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBmdW5jdGlvbiBgZmAgYW5kIGEgbGlzdCBvZiBhcmd1bWVudHMsIGFuZCByZXR1cm5zIGEgZnVuY3Rpb24gYGdgLlxuICAgICAqIFdoZW4gYXBwbGllZCwgYGdgIHJldHVybnMgdGhlIHJlc3VsdCBvZiBhcHBseWluZyBgZmAgdG8gdGhlIGFyZ3VtZW50c1xuICAgICAqIHByb3ZpZGVkIGluaXRpYWxseSBmb2xsb3dlZCBieSB0aGUgYXJndW1lbnRzIHByb3ZpZGVkIHRvIGBnYC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgKChhLCBiLCBjLCAuLi4sIG4pIC0+IHgpIC0+IFthLCBiLCBjLCAuLi5dIC0+ICgoZCwgZSwgZiwgLi4uLCBuKSAtPiB4KVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcmdzXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259XG4gICAgICogQHNlZSBSLnBhcnRpYWxSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBtdWx0aXBseSA9IChhLCBiKSA9PiBhICogYjtcbiAgICAgKiAgICAgIHZhciBkb3VibGUgPSBSLnBhcnRpYWwobXVsdGlwbHksIFsyXSk7XG4gICAgICogICAgICBkb3VibGUoMik7IC8vPT4gNFxuICAgICAqXG4gICAgICogICAgICB2YXIgZ3JlZXQgPSAoc2FsdXRhdGlvbiwgdGl0bGUsIGZpcnN0TmFtZSwgbGFzdE5hbWUpID0+XG4gICAgICogICAgICAgIHNhbHV0YXRpb24gKyAnLCAnICsgdGl0bGUgKyAnICcgKyBmaXJzdE5hbWUgKyAnICcgKyBsYXN0TmFtZSArICchJztcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHNheUhlbGxvID0gUi5wYXJ0aWFsKGdyZWV0LCBbJ0hlbGxvJ10pO1xuICAgICAqICAgICAgdmFyIHNheUhlbGxvVG9NcyA9IFIucGFydGlhbChzYXlIZWxsbywgWydNcy4nXSk7XG4gICAgICogICAgICBzYXlIZWxsb1RvTXMoJ0phbmUnLCAnSm9uZXMnKTsgLy89PiAnSGVsbG8sIE1zLiBKYW5lIEpvbmVzISdcbiAgICAgKi9cbiAgICB2YXIgcGFydGlhbCA9IF9jcmVhdGVQYXJ0aWFsQXBwbGljYXRvcihfY29uY2F0KTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgZnVuY3Rpb24gYGZgIGFuZCBhIGxpc3Qgb2YgYXJndW1lbnRzLCBhbmQgcmV0dXJucyBhIGZ1bmN0aW9uIGBnYC5cbiAgICAgKiBXaGVuIGFwcGxpZWQsIGBnYCByZXR1cm5zIHRoZSByZXN1bHQgb2YgYXBwbHlpbmcgYGZgIHRvIHRoZSBhcmd1bWVudHNcbiAgICAgKiBwcm92aWRlZCB0byBgZ2AgZm9sbG93ZWQgYnkgdGhlIGFyZ3VtZW50cyBwcm92aWRlZCBpbml0aWFsbHkuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEwLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgoYSwgYiwgYywgLi4uLCBuKSAtPiB4KSAtPiBbZCwgZSwgZiwgLi4uLCBuXSAtPiAoKGEsIGIsIGMsIC4uLikgLT4geClcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJnc1xuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICAgICAqIEBzZWUgUi5wYXJ0aWFsXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGdyZWV0ID0gKHNhbHV0YXRpb24sIHRpdGxlLCBmaXJzdE5hbWUsIGxhc3ROYW1lKSA9PlxuICAgICAqICAgICAgICBzYWx1dGF0aW9uICsgJywgJyArIHRpdGxlICsgJyAnICsgZmlyc3ROYW1lICsgJyAnICsgbGFzdE5hbWUgKyAnISc7XG4gICAgICpcbiAgICAgKiAgICAgIHZhciBncmVldE1zSmFuZUpvbmVzID0gUi5wYXJ0aWFsUmlnaHQoZ3JlZXQsIFsnTXMuJywgJ0phbmUnLCAnSm9uZXMnXSk7XG4gICAgICpcbiAgICAgKiAgICAgIGdyZWV0TXNKYW5lSm9uZXMoJ0hlbGxvJyk7IC8vPT4gJ0hlbGxvLCBNcy4gSmFuZSBKb25lcyEnXG4gICAgICovXG4gICAgdmFyIHBhcnRpYWxSaWdodCA9IF9jcmVhdGVQYXJ0aWFsQXBwbGljYXRvcihmbGlwKF9jb25jYXQpKTtcblxuICAgIC8qKlxuICAgICAqIERldGVybWluZXMgd2hldGhlciBhIG5lc3RlZCBwYXRoIG9uIGFuIG9iamVjdCBoYXMgYSBzcGVjaWZpYyB2YWx1ZSwgaW5cbiAgICAgKiBgUi5lcXVhbHNgIHRlcm1zLiBNb3N0IGxpa2VseSB1c2VkIHRvIGZpbHRlciBhIGxpc3QuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjcuMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgW1N0cmluZ10gLT4gKiAtPiB7U3RyaW5nOiAqfSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbmVzdGVkIHByb3BlcnR5IHRvIHVzZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byBjb21wYXJlIHRoZSBuZXN0ZWQgcHJvcGVydHkgd2l0aFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBjaGVjayB0aGUgbmVzdGVkIHByb3BlcnR5IGluXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn0gYHRydWVgIGlmIHRoZSB2YWx1ZSBlcXVhbHMgdGhlIG5lc3RlZCBvYmplY3QgcHJvcGVydHksXG4gICAgICogICAgICAgICBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgdXNlcjEgPSB7IGFkZHJlc3M6IHsgemlwQ29kZTogOTAyMTAgfSB9O1xuICAgICAqICAgICAgdmFyIHVzZXIyID0geyBhZGRyZXNzOiB7IHppcENvZGU6IDU1NTU1IH0gfTtcbiAgICAgKiAgICAgIHZhciB1c2VyMyA9IHsgbmFtZTogJ0JvYicgfTtcbiAgICAgKiAgICAgIHZhciB1c2VycyA9IFsgdXNlcjEsIHVzZXIyLCB1c2VyMyBdO1xuICAgICAqICAgICAgdmFyIGlzRmFtb3VzID0gUi5wYXRoRXEoWydhZGRyZXNzJywgJ3ppcENvZGUnXSwgOTAyMTApO1xuICAgICAqICAgICAgUi5maWx0ZXIoaXNGYW1vdXMsIHVzZXJzKTsgLy89PiBbIHVzZXIxIF1cbiAgICAgKi9cbiAgICB2YXIgcGF0aEVxID0gX2N1cnJ5MyhmdW5jdGlvbiBwYXRoRXEoX3BhdGgsIHZhbCwgb2JqKSB7XG4gICAgICAgIHJldHVybiBlcXVhbHMocGF0aChfcGF0aCwgb2JqKSwgdmFsKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgbGlzdCBieSBwbHVja2luZyB0aGUgc2FtZSBuYW1lZCBwcm9wZXJ0eSBvZmYgYWxsIG9iamVjdHMgaW5cbiAgICAgKiB0aGUgbGlzdCBzdXBwbGllZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIGsgLT4gW3trOiB2fV0gLT4gW3ZdXG4gICAgICogQHBhcmFtIHtOdW1iZXJ8U3RyaW5nfSBrZXkgVGhlIGtleSBuYW1lIHRvIHBsdWNrIG9mZiBvZiBlYWNoIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3Qgb2YgdmFsdWVzIGZvciB0aGUgZ2l2ZW4ga2V5LlxuICAgICAqIEBzZWUgUi5wcm9wc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucGx1Y2soJ2EnKShbe2E6IDF9LCB7YTogMn1dKTsgLy89PiBbMSwgMl1cbiAgICAgKiAgICAgIFIucGx1Y2soMCkoW1sxLCAyXSwgWzMsIDRdXSk7ICAgLy89PiBbMSwgM11cbiAgICAgKi9cbiAgICB2YXIgcGx1Y2sgPSBfY3VycnkyKGZ1bmN0aW9uIHBsdWNrKHAsIGxpc3QpIHtcbiAgICAgICAgcmV0dXJuIG1hcChwcm9wKHApLCBsaXN0KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJlYXNvbmFibGUgYW5hbG9nIHRvIFNRTCBgc2VsZWN0YCBzdGF0ZW1lbnQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAY2F0ZWdvcnkgUmVsYXRpb25cbiAgICAgKiBAc2lnIFtrXSAtPiBbe2s6IHZ9XSAtPiBbe2s6IHZ9XVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBwcm9qZWN0XG4gICAgICogQHBhcmFtIHtBcnJheX0gb2JqcyBUaGUgb2JqZWN0cyB0byBxdWVyeVxuICAgICAqIEByZXR1cm4ge0FycmF5fSBBbiBhcnJheSBvZiBvYmplY3RzIHdpdGgganVzdCB0aGUgYHByb3BzYCBwcm9wZXJ0aWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBhYmJ5ID0ge25hbWU6ICdBYmJ5JywgYWdlOiA3LCBoYWlyOiAnYmxvbmQnLCBncmFkZTogMn07XG4gICAgICogICAgICB2YXIgZnJlZCA9IHtuYW1lOiAnRnJlZCcsIGFnZTogMTIsIGhhaXI6ICdicm93bicsIGdyYWRlOiA3fTtcbiAgICAgKiAgICAgIHZhciBraWRzID0gW2FiYnksIGZyZWRdO1xuICAgICAqICAgICAgUi5wcm9qZWN0KFsnbmFtZScsICdncmFkZSddLCBraWRzKTsgLy89PiBbe25hbWU6ICdBYmJ5JywgZ3JhZGU6IDJ9LCB7bmFtZTogJ0ZyZWQnLCBncmFkZTogN31dXG4gICAgICovXG4gICAgLy8gcGFzc2luZyBgaWRlbnRpdHlgIGdpdmVzIGNvcnJlY3QgYXJpdHlcbiAgICB2YXIgcHJvamVjdCA9IHVzZVdpdGgoX21hcCwgW1xuICAgICAgICBwaWNrQWxsLFxuICAgICAgICBpZGVudGl0eVxuICAgIF0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHNwZWNpZmllZCBvYmplY3QgcHJvcGVydHkgaXMgZXF1YWwsIGluIGBSLmVxdWFsc2BcbiAgICAgKiB0ZXJtcywgdG8gdGhlIGdpdmVuIHZhbHVlOyBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBTdHJpbmcgLT4gYSAtPiBPYmplY3QgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAgICogQHBhcmFtIHsqfSB2YWxcbiAgICAgKiBAcGFyYW0geyp9IG9ialxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQHNlZSBSLmVxdWFscywgUi5wcm9wU2F0aXNmaWVzXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGFiYnkgPSB7bmFtZTogJ0FiYnknLCBhZ2U6IDcsIGhhaXI6ICdibG9uZCd9O1xuICAgICAqICAgICAgdmFyIGZyZWQgPSB7bmFtZTogJ0ZyZWQnLCBhZ2U6IDEyLCBoYWlyOiAnYnJvd24nfTtcbiAgICAgKiAgICAgIHZhciBydXN0eSA9IHtuYW1lOiAnUnVzdHknLCBhZ2U6IDEwLCBoYWlyOiAnYnJvd24nfTtcbiAgICAgKiAgICAgIHZhciBhbG9pcyA9IHtuYW1lOiAnQWxvaXMnLCBhZ2U6IDE1LCBkaXNwb3NpdGlvbjogJ3N1cmx5J307XG4gICAgICogICAgICB2YXIga2lkcyA9IFthYmJ5LCBmcmVkLCBydXN0eSwgYWxvaXNdO1xuICAgICAqICAgICAgdmFyIGhhc0Jyb3duSGFpciA9IFIucHJvcEVxKCdoYWlyJywgJ2Jyb3duJyk7XG4gICAgICogICAgICBSLmZpbHRlcihoYXNCcm93bkhhaXIsIGtpZHMpOyAvLz0+IFtmcmVkLCBydXN0eV1cbiAgICAgKi9cbiAgICB2YXIgcHJvcEVxID0gX2N1cnJ5MyhmdW5jdGlvbiBwcm9wRXEobmFtZSwgdmFsLCBvYmopIHtcbiAgICAgICAgcmV0dXJuIGVxdWFscyh2YWwsIG9ialtuYW1lXSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgc2luZ2xlIGl0ZW0gYnkgaXRlcmF0aW5nIHRocm91Z2ggdGhlIGxpc3QsIHN1Y2Nlc3NpdmVseSBjYWxsaW5nXG4gICAgICogdGhlIGl0ZXJhdG9yIGZ1bmN0aW9uIGFuZCBwYXNzaW5nIGl0IGFuIGFjY3VtdWxhdG9yIHZhbHVlIGFuZCB0aGUgY3VycmVudFxuICAgICAqIHZhbHVlIGZyb20gdGhlIGFycmF5LCBhbmQgdGhlbiBwYXNzaW5nIHRoZSByZXN1bHQgdG8gdGhlIG5leHQgY2FsbC5cbiAgICAgKlxuICAgICAqIFRoZSBpdGVyYXRvciBmdW5jdGlvbiByZWNlaXZlcyB0d28gdmFsdWVzOiAqKGFjYywgdmFsdWUpKi4gSXQgbWF5IHVzZVxuICAgICAqIGBSLnJlZHVjZWRgIHRvIHNob3J0Y3V0IHRoZSBpdGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBOb3RlOiBgUi5yZWR1Y2VgIGRvZXMgbm90IHNraXAgZGVsZXRlZCBvciB1bmFzc2lnbmVkIGluZGljZXMgKHNwYXJzZVxuICAgICAqIGFycmF5cyksIHVubGlrZSB0aGUgbmF0aXZlIGBBcnJheS5wcm90b3R5cGUucmVkdWNlYCBtZXRob2QuIEZvciBtb3JlIGRldGFpbHNcbiAgICAgKiBvbiB0aGlzIGJlaGF2aW9yLCBzZWU6XG4gICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvcmVkdWNlI0Rlc2NyaXB0aW9uXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgcmVkdWNlYCBtZXRob2Qgb2YgdGhlIHRoaXJkIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKChhLCBiKSAtPiBhKSAtPiBhIC0+IFtiXSAtPiBhXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLiBSZWNlaXZlcyB0d28gdmFsdWVzLCB0aGUgYWNjdW11bGF0b3IgYW5kIHRoZVxuICAgICAqICAgICAgICBjdXJyZW50IGVsZW1lbnQgZnJvbSB0aGUgYXJyYXkuXG4gICAgICogQHBhcmFtIHsqfSBhY2MgVGhlIGFjY3VtdWxhdG9yIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBmaW5hbCwgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQHNlZSBSLnJlZHVjZWQsIFIuYWRkSW5kZXhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbnVtYmVycyA9IFsxLCAyLCAzXTtcbiAgICAgKiAgICAgIHZhciBwbHVzID0gKGEsIGIpID0+IGEgKyBiO1xuICAgICAqXG4gICAgICogICAgICBSLnJlZHVjZShwbHVzLCAxMCwgbnVtYmVycyk7IC8vPT4gMTZcbiAgICAgKi9cbiAgICB2YXIgcmVkdWNlID0gX2N1cnJ5MyhfcmVkdWNlKTtcblxuICAgIC8qKlxuICAgICAqIEdyb3VwcyB0aGUgZWxlbWVudHMgb2YgdGhlIGxpc3QgYWNjb3JkaW5nIHRvIHRoZSByZXN1bHQgb2YgY2FsbGluZ1xuICAgICAqIHRoZSBTdHJpbmctcmV0dXJuaW5nIGZ1bmN0aW9uIGBrZXlGbmAgb24gZWFjaCBlbGVtZW50IGFuZCByZWR1Y2VzIHRoZSBlbGVtZW50c1xuICAgICAqIG9mIGVhY2ggZ3JvdXAgdG8gYSBzaW5nbGUgdmFsdWUgdmlhIHRoZSByZWR1Y2VyIGZ1bmN0aW9uIGB2YWx1ZUZuYC5cbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgYmFzaWNhbGx5IGEgbW9yZSBnZW5lcmFsIGBncm91cEJ5YCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMjAuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoKGEsIGIpIC0+IGEpIC0+IGEgLT4gKGIgLT4gU3RyaW5nKSAtPiBbYl0gLT4ge1N0cmluZzogYX1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB2YWx1ZUZuIFRoZSBmdW5jdGlvbiB0aGF0IHJlZHVjZXMgdGhlIGVsZW1lbnRzIG9mIGVhY2ggZ3JvdXAgdG8gYSBzaW5nbGVcbiAgICAgKiAgICAgICAgdmFsdWUuIFJlY2VpdmVzIHR3byB2YWx1ZXMsIGFjY3VtdWxhdG9yIGZvciBhIHBhcnRpY3VsYXIgZ3JvdXAgYW5kIHRoZSBjdXJyZW50IGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHsqfSBhY2MgVGhlIChpbml0aWFsKSBhY2N1bXVsYXRvciB2YWx1ZSBmb3IgZWFjaCBncm91cC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlGbiBUaGUgZnVuY3Rpb24gdGhhdCBtYXBzIHRoZSBsaXN0J3MgZWxlbWVudCBpbnRvIGEga2V5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGFycmF5IHRvIGdyb3VwLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQW4gb2JqZWN0IHdpdGggdGhlIG91dHB1dCBvZiBga2V5Rm5gIGZvciBrZXlzLCBtYXBwZWQgdG8gdGhlIG91dHB1dCBvZlxuICAgICAqICAgICAgICAgYHZhbHVlRm5gIGZvciBlbGVtZW50cyB3aGljaCBwcm9kdWNlZCB0aGF0IGtleSB3aGVuIHBhc3NlZCB0byBga2V5Rm5gLlxuICAgICAqIEBzZWUgUi5ncm91cEJ5LCBSLnJlZHVjZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciByZWR1Y2VUb05hbWVzQnkgPSBSLnJlZHVjZUJ5KChhY2MsIHN0dWRlbnQpID0+IGFjYy5jb25jYXQoc3R1ZGVudC5uYW1lKSwgW10pO1xuICAgICAqICAgICAgdmFyIG5hbWVzQnlHcmFkZSA9IHJlZHVjZVRvTmFtZXNCeShmdW5jdGlvbihzdHVkZW50KSB7XG4gICAgICogICAgICAgIHZhciBzY29yZSA9IHN0dWRlbnQuc2NvcmU7XG4gICAgICogICAgICAgIHJldHVybiBzY29yZSA8IDY1ID8gJ0YnIDpcbiAgICAgKiAgICAgICAgICAgICAgIHNjb3JlIDwgNzAgPyAnRCcgOlxuICAgICAqICAgICAgICAgICAgICAgc2NvcmUgPCA4MCA/ICdDJyA6XG4gICAgICogICAgICAgICAgICAgICBzY29yZSA8IDkwID8gJ0InIDogJ0EnO1xuICAgICAqICAgICAgfSk7XG4gICAgICogICAgICB2YXIgc3R1ZGVudHMgPSBbe25hbWU6ICdMdWN5Jywgc2NvcmU6IDkyfSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICB7bmFtZTogJ0RyZXcnLCBzY29yZTogODV9LFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIC8vIC4uLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIHtuYW1lOiAnQmFydCcsIHNjb3JlOiA2Mn1dO1xuICAgICAqICAgICAgbmFtZXNCeUdyYWRlKHN0dWRlbnRzKTtcbiAgICAgKiAgICAgIC8vIHtcbiAgICAgKiAgICAgIC8vICAgJ0EnOiBbJ0x1Y3knXSxcbiAgICAgKiAgICAgIC8vICAgJ0InOiBbJ0RyZXcnXVxuICAgICAqICAgICAgLy8gICAvLyAuLi4sXG4gICAgICogICAgICAvLyAgICdGJzogWydCYXJ0J11cbiAgICAgKiAgICAgIC8vIH1cbiAgICAgKi9cbiAgICB2YXIgcmVkdWNlQnkgPSBfY3VycnlOKDQsIFtdLCBfZGlzcGF0Y2hhYmxlKCdyZWR1Y2VCeScsIF94cmVkdWNlQnksIGZ1bmN0aW9uIHJlZHVjZUJ5KHZhbHVlRm4sIHZhbHVlQWNjLCBrZXlGbiwgbGlzdCkge1xuICAgICAgICByZXR1cm4gX3JlZHVjZShmdW5jdGlvbiAoYWNjLCBlbHQpIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSBrZXlGbihlbHQpO1xuICAgICAgICAgICAgYWNjW2tleV0gPSB2YWx1ZUZuKF9oYXMoa2V5LCBhY2MpID8gYWNjW2tleV0gOiB2YWx1ZUFjYywgZWx0KTtcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIH0sIHt9LCBsaXN0KTtcbiAgICB9KSk7XG5cbiAgICAvKipcbiAgICAgKiBMaWtlIGByZWR1Y2VgLCBgcmVkdWNlV2hpbGVgIHJldHVybnMgYSBzaW5nbGUgaXRlbSBieSBpdGVyYXRpbmcgdGhyb3VnaFxuICAgICAqIHRoZSBsaXN0LCBzdWNjZXNzaXZlbHkgY2FsbGluZyB0aGUgaXRlcmF0b3IgZnVuY3Rpb24uIGByZWR1Y2VXaGlsZWAgYWxzb1xuICAgICAqIHRha2VzIGEgcHJlZGljYXRlIHRoYXQgaXMgZXZhbHVhdGVkIGJlZm9yZSBlYWNoIHN0ZXAuIElmIHRoZSBwcmVkaWNhdGUgcmV0dXJuc1xuICAgICAqIGBmYWxzZWAsIGl0IFwic2hvcnQtY2lyY3VpdHNcIiB0aGUgaXRlcmF0aW9uIGFuZCByZXR1cm5zIHRoZSBjdXJyZW50IHZhbHVlXG4gICAgICogb2YgdGhlIGFjY3VtdWxhdG9yLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4yMi4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnICgoYSwgYikgLT4gQm9vbGVhbikgLT4gKChhLCBiKSAtPiBhKSAtPiBhIC0+IFtiXSAtPiBhXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZCBUaGUgcHJlZGljYXRlLiBJdCBpcyBwYXNzZWQgdGhlIGFjY3VtdWxhdG9yIGFuZCB0aGVcbiAgICAgKiAgICAgICAgY3VycmVudCBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBpdGVyYXRvciBmdW5jdGlvbi4gUmVjZWl2ZXMgdHdvIHZhbHVlcywgdGhlXG4gICAgICogICAgICAgIGFjY3VtdWxhdG9yIGFuZCB0aGUgY3VycmVudCBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7Kn0gYSBUaGUgYWNjdW11bGF0b3IgdmFsdWUuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybiB7Kn0gVGhlIGZpbmFsLCBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAc2VlIFIucmVkdWNlLCBSLnJlZHVjZWRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNPZGQgPSAoYWNjLCB4KSA9PiB4ICUgMiA9PT0gMTtcbiAgICAgKiAgICAgIHZhciB4cyA9IFsxLCAzLCA1LCA2MCwgNzc3LCA4MDBdO1xuICAgICAqICAgICAgUi5yZWR1Y2VXaGlsZShpc09kZCwgUi5hZGQsIDAsIHhzKTsgLy89PiA5XG4gICAgICpcbiAgICAgKiAgICAgIHZhciB5cyA9IFsyLCA0LCA2XVxuICAgICAqICAgICAgUi5yZWR1Y2VXaGlsZShpc09kZCwgUi5hZGQsIDExMSwgeXMpOyAvLz0+IDExMVxuICAgICAqL1xuICAgIHZhciByZWR1Y2VXaGlsZSA9IF9jdXJyeU4oNCwgW10sIGZ1bmN0aW9uIF9yZWR1Y2VXaGlsZShwcmVkLCBmbiwgYSwgbGlzdCkge1xuICAgICAgICByZXR1cm4gX3JlZHVjZShmdW5jdGlvbiAoYWNjLCB4KSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZChhY2MsIHgpID8gZm4oYWNjLCB4KSA6IF9yZWR1Y2VkKGFjYyk7XG4gICAgICAgIH0sIGEsIGxpc3QpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGNvbXBsZW1lbnQgb2YgYGZpbHRlcmAuXG4gICAgICpcbiAgICAgKiBBY3RzIGFzIGEgdHJhbnNkdWNlciBpZiBhIHRyYW5zZm9ybWVyIGlzIGdpdmVuIGluIGxpc3QgcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBGaWx0ZXJhYmxlIGYgPT4gKGEgLT4gQm9vbGVhbikgLT4gZiBhIC0+IGYgYVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXJhYmxlXG4gICAgICogQHJldHVybiB7QXJyYXl9XG4gICAgICogQHNlZSBSLmZpbHRlciwgUi50cmFuc2R1Y2UsIFIuYWRkSW5kZXhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNPZGQgPSAobikgPT4gbiAlIDIgPT09IDE7XG4gICAgICpcbiAgICAgKiAgICAgIFIucmVqZWN0KGlzT2RkLCBbMSwgMiwgMywgNF0pOyAvLz0+IFsyLCA0XVxuICAgICAqXG4gICAgICogICAgICBSLnJlamVjdChpc09kZCwge2E6IDEsIGI6IDIsIGM6IDMsIGQ6IDR9KTsgLy89PiB7YjogMiwgZDogNH1cbiAgICAgKi9cbiAgICB2YXIgcmVqZWN0ID0gX2N1cnJ5MihmdW5jdGlvbiByZWplY3QocHJlZCwgZmlsdGVyYWJsZSkge1xuICAgICAgICByZXR1cm4gZmlsdGVyKF9jb21wbGVtZW50KHByZWQpLCBmaWx0ZXJhYmxlKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBmaXhlZCBsaXN0IG9mIHNpemUgYG5gIGNvbnRhaW5pbmcgYSBzcGVjaWZpZWQgaWRlbnRpY2FsIHZhbHVlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjFcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgYSAtPiBuIC0+IFthXVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHJlcGVhdC5cbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgZGVzaXJlZCBzaXplIG9mIHRoZSBvdXRwdXQgbGlzdC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gQSBuZXcgYXJyYXkgY29udGFpbmluZyBgbmAgYHZhbHVlYHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5yZXBlYXQoJ2hpJywgNSk7IC8vPT4gWydoaScsICdoaScsICdoaScsICdoaScsICdoaSddXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBvYmogPSB7fTtcbiAgICAgKiAgICAgIHZhciByZXBlYXRlZE9ianMgPSBSLnJlcGVhdChvYmosIDUpOyAvLz0+IFt7fSwge30sIHt9LCB7fSwge31dXG4gICAgICogICAgICByZXBlYXRlZE9ianNbMF0gPT09IHJlcGVhdGVkT2Jqc1sxXTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIHJlcGVhdCA9IF9jdXJyeTIoZnVuY3Rpb24gcmVwZWF0KHZhbHVlLCBuKSB7XG4gICAgICAgIHJldHVybiB0aW1lcyhhbHdheXModmFsdWUpLCBuKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgdG9nZXRoZXIgYWxsIHRoZSBlbGVtZW50cyBvZiBhIGxpc3QuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHNpZyBbTnVtYmVyXSAtPiBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IEFuIGFycmF5IG9mIG51bWJlcnNcbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9IFRoZSBzdW0gb2YgYWxsIHRoZSBudW1iZXJzIGluIHRoZSBsaXN0LlxuICAgICAqIEBzZWUgUi5yZWR1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnN1bShbMiw0LDYsOCwxMDAsMV0pOyAvLz0+IDEyMVxuICAgICAqL1xuICAgIHZhciBzdW0gPSByZWR1Y2UoYWRkLCAwKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgbGlzdCBjb250YWluaW5nIHRoZSBsYXN0IGBuYCBlbGVtZW50cyBvZiB0aGUgZ2l2ZW4gbGlzdC5cbiAgICAgKiBJZiBgbiA+IGxpc3QubGVuZ3RoYCwgcmV0dXJucyBhIGxpc3Qgb2YgYGxpc3QubGVuZ3RoYCBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTYuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBOdW1iZXIgLT4gW2FdIC0+IFthXVxuICAgICAqIEBzaWcgTnVtYmVyIC0+IFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHJldHVybi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB4cyBUaGUgY29sbGVjdGlvbiB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICAgKiBAc2VlIFIuZHJvcExhc3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnRha2VMYXN0KDEsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gWydiYXonXVxuICAgICAqICAgICAgUi50YWtlTGFzdCgyLCBbJ2ZvbycsICdiYXInLCAnYmF6J10pOyAvLz0+IFsnYmFyJywgJ2JheiddXG4gICAgICogICAgICBSLnRha2VMYXN0KDMsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gWydmb28nLCAnYmFyJywgJ2JheiddXG4gICAgICogICAgICBSLnRha2VMYXN0KDQsIFsnZm9vJywgJ2JhcicsICdiYXonXSk7IC8vPT4gWydmb28nLCAnYmFyJywgJ2JheiddXG4gICAgICogICAgICBSLnRha2VMYXN0KDMsICdyYW1kYScpOyAgICAgICAgICAgICAgIC8vPT4gJ21kYSdcbiAgICAgKi9cbiAgICB2YXIgdGFrZUxhc3QgPSBfY3VycnkyKGZ1bmN0aW9uIHRha2VMYXN0KG4sIHhzKSB7XG4gICAgICAgIHJldHVybiBkcm9wKG4gPj0gMCA/IHhzLmxlbmd0aCAtIG4gOiAwLCB4cyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhIHRyYW5zZHVjZXIgdXNpbmcgc3VwcGxpZWQgaXRlcmF0b3IgZnVuY3Rpb24uIFJldHVybnMgYSBzaW5nbGVcbiAgICAgKiBpdGVtIGJ5IGl0ZXJhdGluZyB0aHJvdWdoIHRoZSBsaXN0LCBzdWNjZXNzaXZlbHkgY2FsbGluZyB0aGUgdHJhbnNmb3JtZWRcbiAgICAgKiBpdGVyYXRvciBmdW5jdGlvbiBhbmQgcGFzc2luZyBpdCBhbiBhY2N1bXVsYXRvciB2YWx1ZSBhbmQgdGhlIGN1cnJlbnQgdmFsdWVcbiAgICAgKiBmcm9tIHRoZSBhcnJheSwgYW5kIHRoZW4gcGFzc2luZyB0aGUgcmVzdWx0IHRvIHRoZSBuZXh0IGNhbGwuXG4gICAgICpcbiAgICAgKiBUaGUgaXRlcmF0b3IgZnVuY3Rpb24gcmVjZWl2ZXMgdHdvIHZhbHVlczogKihhY2MsIHZhbHVlKSouIEl0IHdpbGwgYmVcbiAgICAgKiB3cmFwcGVkIGFzIGEgdHJhbnNmb3JtZXIgdG8gaW5pdGlhbGl6ZSB0aGUgdHJhbnNkdWNlci4gQSB0cmFuc2Zvcm1lciBjYW4gYmVcbiAgICAgKiBwYXNzZWQgZGlyZWN0bHkgaW4gcGxhY2Ugb2YgYW4gaXRlcmF0b3IgZnVuY3Rpb24uIEluIGJvdGggY2FzZXMsIGl0ZXJhdGlvblxuICAgICAqIG1heSBiZSBzdG9wcGVkIGVhcmx5IHdpdGggdGhlIGBSLnJlZHVjZWRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQSB0cmFuc2R1Y2VyIGlzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIGEgdHJhbnNmb3JtZXIgYW5kIHJldHVybnMgYVxuICAgICAqIHRyYW5zZm9ybWVyIGFuZCBjYW4gYmUgY29tcG9zZWQgZGlyZWN0bHkuXG4gICAgICpcbiAgICAgKiBBIHRyYW5zZm9ybWVyIGlzIGFuIGFuIG9iamVjdCB0aGF0IHByb3ZpZGVzIGEgMi1hcml0eSByZWR1Y2luZyBpdGVyYXRvclxuICAgICAqIGZ1bmN0aW9uLCBzdGVwLCAwLWFyaXR5IGluaXRpYWwgdmFsdWUgZnVuY3Rpb24sIGluaXQsIGFuZCAxLWFyaXR5IHJlc3VsdFxuICAgICAqIGV4dHJhY3Rpb24gZnVuY3Rpb24sIHJlc3VsdC4gVGhlIHN0ZXAgZnVuY3Rpb24gaXMgdXNlZCBhcyB0aGUgaXRlcmF0b3JcbiAgICAgKiBmdW5jdGlvbiBpbiByZWR1Y2UuIFRoZSByZXN1bHQgZnVuY3Rpb24gaXMgdXNlZCB0byBjb252ZXJ0IHRoZSBmaW5hbFxuICAgICAqIGFjY3VtdWxhdG9yIGludG8gdGhlIHJldHVybiB0eXBlIGFuZCBpbiBtb3N0IGNhc2VzIGlzIFIuaWRlbnRpdHkuIFRoZSBpbml0XG4gICAgICogZnVuY3Rpb24gY2FuIGJlIHVzZWQgdG8gcHJvdmlkZSBhbiBpbml0aWFsIGFjY3VtdWxhdG9yLCBidXQgaXMgaWdub3JlZCBieVxuICAgICAqIHRyYW5zZHVjZS5cbiAgICAgKlxuICAgICAqIFRoZSBpdGVyYXRpb24gaXMgcGVyZm9ybWVkIHdpdGggUi5yZWR1Y2UgYWZ0ZXIgaW5pdGlhbGl6aW5nIHRoZSB0cmFuc2R1Y2VyLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMi4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChjIC0+IGMpIC0+IChhLGIgLT4gYSkgLT4gYSAtPiBbYl0gLT4gYVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHhmIFRoZSB0cmFuc2R1Y2VyIGZ1bmN0aW9uLiBSZWNlaXZlcyBhIHRyYW5zZm9ybWVyIGFuZCByZXR1cm5zIGEgdHJhbnNmb3JtZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGl0ZXJhdG9yIGZ1bmN0aW9uLiBSZWNlaXZlcyB0d28gdmFsdWVzLCB0aGUgYWNjdW11bGF0b3IgYW5kIHRoZVxuICAgICAqICAgICAgICBjdXJyZW50IGVsZW1lbnQgZnJvbSB0aGUgYXJyYXkuIFdyYXBwZWQgYXMgdHJhbnNmb3JtZXIsIGlmIG5lY2Vzc2FyeSwgYW5kIHVzZWQgdG9cbiAgICAgKiAgICAgICAgaW5pdGlhbGl6ZSB0aGUgdHJhbnNkdWNlclxuICAgICAqIEBwYXJhbSB7Kn0gYWNjIFRoZSBpbml0aWFsIGFjY3VtdWxhdG9yIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGxpc3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm4geyp9IFRoZSBmaW5hbCwgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQHNlZSBSLnJlZHVjZSwgUi5yZWR1Y2VkLCBSLmludG9cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbnVtYmVycyA9IFsxLCAyLCAzLCA0XTtcbiAgICAgKiAgICAgIHZhciB0cmFuc2R1Y2VyID0gUi5jb21wb3NlKFIubWFwKFIuYWRkKDEpKSwgUi50YWtlKDIpKTtcbiAgICAgKlxuICAgICAqICAgICAgUi50cmFuc2R1Y2UodHJhbnNkdWNlciwgUi5mbGlwKFIuYXBwZW5kKSwgW10sIG51bWJlcnMpOyAvLz0+IFsyLCAzXVxuICAgICAqL1xuICAgIHZhciB0cmFuc2R1Y2UgPSBjdXJyeU4oNCwgZnVuY3Rpb24gdHJhbnNkdWNlKHhmLCBmbiwgYWNjLCBsaXN0KSB7XG4gICAgICAgIHJldHVybiBfcmVkdWNlKHhmKHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyA/IF94d3JhcChmbikgOiBmbiksIGFjYywgbGlzdCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21iaW5lcyB0d28gbGlzdHMgaW50byBhIHNldCAoaS5lLiBubyBkdXBsaWNhdGVzKSBjb21wb3NlZCBvZiB0aGUgZWxlbWVudHNcbiAgICAgKiBvZiBlYWNoIGxpc3QuIER1cGxpY2F0aW9uIGlzIGRldGVybWluZWQgYWNjb3JkaW5nIHRvIHRoZSB2YWx1ZSByZXR1cm5lZCBieVxuICAgICAqIGFwcGx5aW5nIHRoZSBzdXBwbGllZCBwcmVkaWNhdGUgdG8gdHdvIGxpc3QgZWxlbWVudHMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgKGEgLT4gYSAtPiBCb29sZWFuKSAtPiBbKl0gLT4gWypdIC0+IFsqXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWQgQSBwcmVkaWNhdGUgdXNlZCB0byB0ZXN0IHdoZXRoZXIgdHdvIGl0ZW1zIGFyZSBlcXVhbC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MSBUaGUgZmlyc3QgbGlzdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MiBUaGUgc2Vjb25kIGxpc3QuXG4gICAgICogQHJldHVybiB7QXJyYXl9IFRoZSBmaXJzdCBhbmQgc2Vjb25kIGxpc3RzIGNvbmNhdGVuYXRlZCwgd2l0aFxuICAgICAqICAgICAgICAgZHVwbGljYXRlcyByZW1vdmVkLlxuICAgICAqIEBzZWUgUi51bmlvblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBsMSA9IFt7YTogMX0sIHthOiAyfV07XG4gICAgICogICAgICB2YXIgbDIgPSBbe2E6IDF9LCB7YTogNH1dO1xuICAgICAqICAgICAgUi51bmlvbldpdGgoUi5lcUJ5KFIucHJvcCgnYScpKSwgbDEsIGwyKTsgLy89PiBbe2E6IDF9LCB7YTogMn0sIHthOiA0fV1cbiAgICAgKi9cbiAgICB2YXIgdW5pb25XaXRoID0gX2N1cnJ5MyhmdW5jdGlvbiB1bmlvbldpdGgocHJlZCwgbGlzdDEsIGxpc3QyKSB7XG4gICAgICAgIHJldHVybiB1bmlxV2l0aChwcmVkLCBfY29uY2F0KGxpc3QxLCBsaXN0MikpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBzcGVjIG9iamVjdCBhbmQgYSB0ZXN0IG9iamVjdDsgcmV0dXJucyB0cnVlIGlmIHRoZSB0ZXN0IHNhdGlzZmllc1xuICAgICAqIHRoZSBzcGVjLCBmYWxzZSBvdGhlcndpc2UuIEFuIG9iamVjdCBzYXRpc2ZpZXMgdGhlIHNwZWMgaWYsIGZvciBlYWNoIG9mIHRoZVxuICAgICAqIHNwZWMncyBvd24gcHJvcGVydGllcywgYWNjZXNzaW5nIHRoYXQgcHJvcGVydHkgb2YgdGhlIG9iamVjdCBnaXZlcyB0aGUgc2FtZVxuICAgICAqIHZhbHVlIChpbiBgUi5lcXVhbHNgIHRlcm1zKSBhcyBhY2Nlc3NpbmcgdGhhdCBwcm9wZXJ0eSBvZiB0aGUgc3BlYy5cbiAgICAgKlxuICAgICAqIGB3aGVyZUVxYCBpcyBhIHNwZWNpYWxpemF0aW9uIG9mIFtgd2hlcmVgXSgjd2hlcmUpLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcge1N0cmluZzogKn0gLT4ge1N0cmluZzogKn0gLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzcGVjXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHRlc3RPYmpcbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgICAqIEBzZWUgUi53aGVyZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIC8vIHByZWQgOjogT2JqZWN0IC0+IEJvb2xlYW5cbiAgICAgKiAgICAgIHZhciBwcmVkID0gUi53aGVyZUVxKHthOiAxLCBiOiAyfSk7XG4gICAgICpcbiAgICAgKiAgICAgIHByZWQoe2E6IDF9KTsgICAgICAgICAgICAgIC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIHByZWQoe2E6IDEsIGI6IDJ9KTsgICAgICAgIC8vPT4gdHJ1ZVxuICAgICAqICAgICAgcHJlZCh7YTogMSwgYjogMiwgYzogM30pOyAgLy89PiB0cnVlXG4gICAgICogICAgICBwcmVkKHthOiAxLCBiOiAxfSk7ICAgICAgICAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIHdoZXJlRXEgPSBfY3VycnkyKGZ1bmN0aW9uIHdoZXJlRXEoc3BlYywgdGVzdE9iaikge1xuICAgICAgICByZXR1cm4gd2hlcmUobWFwKGVxdWFscywgc3BlYyksIHRlc3RPYmopO1xuICAgIH0pO1xuXG4gICAgdmFyIF9mbGF0Q2F0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcHJlc2VydmluZ1JlZHVjZWQgPSBmdW5jdGlvbiAoeGYpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgJ0BAdHJhbnNkdWNlci9pbml0JzogX3hmQmFzZS5pbml0LFxuICAgICAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvcmVzdWx0JzogZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geGZbJ0BAdHJhbnNkdWNlci9yZXN1bHQnXShyZXN1bHQpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ0BAdHJhbnNkdWNlci9zdGVwJzogZnVuY3Rpb24gKHJlc3VsdCwgaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJldCA9IHhmWydAQHRyYW5zZHVjZXIvc3RlcCddKHJlc3VsdCwgaW5wdXQpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmV0WydAQHRyYW5zZHVjZXIvcmVkdWNlZCddID8gX2ZvcmNlUmVkdWNlZChyZXQpIDogcmV0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBfeGNhdCh4Zikge1xuICAgICAgICAgICAgdmFyIHJ4ZiA9IHByZXNlcnZpbmdSZWR1Y2VkKHhmKTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgJ0BAdHJhbnNkdWNlci9pbml0JzogX3hmQmFzZS5pbml0LFxuICAgICAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvcmVzdWx0JzogZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcnhmWydAQHRyYW5zZHVjZXIvcmVzdWx0J10ocmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICdAQHRyYW5zZHVjZXIvc3RlcCc6IGZ1bmN0aW9uIChyZXN1bHQsIGlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhaXNBcnJheUxpa2UoaW5wdXQpID8gX3JlZHVjZShyeGYsIHJlc3VsdCwgW2lucHV0XSkgOiBfcmVkdWNlKHJ4ZiwgcmVzdWx0LCBpbnB1dCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICB9KCk7XG5cbiAgICAvLyBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiBkb2Vzbid0IGV4aXN0IGJlbG93IElFOVxuICAgIC8vIG1hbnVhbGx5IGNyYXdsIHRoZSBsaXN0IHRvIGRpc3Rpbmd1aXNoIGJldHdlZW4gKzAgYW5kIC0wXG4gICAgLy8gTmFOXG4gICAgLy8gbm9uLXplcm8gbnVtYmVycyBjYW4gdXRpbGlzZSBTZXRcbiAgICAvLyBhbGwgdGhlc2UgdHlwZXMgY2FuIHV0aWxpc2UgU2V0XG4gICAgLy8gbnVsbCBjYW4gdXRpbGlzZSBTZXRcbiAgICAvLyBhbnl0aGluZyBlbHNlIG5vdCBjb3ZlcmVkIGFib3ZlLCBkZWZlciB0byBSLmVxdWFsc1xuICAgIHZhciBfaW5kZXhPZiA9IGZ1bmN0aW9uIF9pbmRleE9mKGxpc3QsIGEsIGlkeCkge1xuICAgICAgICB2YXIgaW5mLCBpdGVtO1xuICAgICAgICAvLyBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiBkb2Vzbid0IGV4aXN0IGJlbG93IElFOVxuICAgICAgICBpZiAodHlwZW9mIGxpc3QuaW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlb2YgYSkge1xuICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBtYW51YWxseSBjcmF3bCB0aGUgbGlzdCB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuICswIGFuZCAtMFxuICAgICAgICAgICAgICAgICAgICBpbmYgPSAxIC8gYTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGlkeCA8IGxpc3QubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtID0gbGlzdFtpZHhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0gPT09IDAgJiYgMSAvIGl0ZW0gPT09IGluZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpZHg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhICE9PSBhKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5hTlxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaWR4IDwgbGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0gPSBsaXN0W2lkeF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdudW1iZXInICYmIGl0ZW0gIT09IGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBub24temVybyBudW1iZXJzIGNhbiB1dGlsaXNlIFNldFxuICAgICAgICAgICAgICAgIHJldHVybiBsaXN0LmluZGV4T2YoYSwgaWR4KTtcbiAgICAgICAgICAgIC8vIGFsbCB0aGVzZSB0eXBlcyBjYW4gdXRpbGlzZSBTZXRcbiAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgICBjYXNlICdib29sZWFuJzpcbiAgICAgICAgICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgICAgICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpc3QuaW5kZXhPZihhLCBpZHgpO1xuICAgICAgICAgICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBudWxsIGNhbiB1dGlsaXNlIFNldFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbGlzdC5pbmRleE9mKGEsIGlkeCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGFueXRoaW5nIGVsc2Ugbm90IGNvdmVyZWQgYWJvdmUsIGRlZmVyIHRvIFIuZXF1YWxzXG4gICAgICAgIHdoaWxlIChpZHggPCBsaXN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKGVxdWFscyhsaXN0W2lkeF0sIGEpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlkeDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9O1xuXG4gICAgdmFyIF94Y2hhaW4gPSBfY3VycnkyKGZ1bmN0aW9uIF94Y2hhaW4oZiwgeGYpIHtcbiAgICAgICAgcmV0dXJuIG1hcChmLCBfZmxhdENhdCh4ZikpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBsaXN0IG9mIHByZWRpY2F0ZXMgYW5kIHJldHVybnMgYSBwcmVkaWNhdGUgdGhhdCByZXR1cm5zIHRydWUgZm9yIGFcbiAgICAgKiBnaXZlbiBsaXN0IG9mIGFyZ3VtZW50cyBpZiBldmVyeSBvbmUgb2YgdGhlIHByb3ZpZGVkIHByZWRpY2F0ZXMgaXMgc2F0aXNmaWVkXG4gICAgICogYnkgdGhvc2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogVGhlIGZ1bmN0aW9uIHJldHVybmVkIGlzIGEgY3VycmllZCBmdW5jdGlvbiB3aG9zZSBhcml0eSBtYXRjaGVzIHRoYXQgb2YgdGhlXG4gICAgICogaGlnaGVzdC1hcml0eSBwcmVkaWNhdGUuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjkuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgWygqLi4uIC0+IEJvb2xlYW4pXSAtPiAoKi4uLiAtPiBCb29sZWFuKVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByZWRzXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259XG4gICAgICogQHNlZSBSLmFueVBhc3NcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNRdWVlbiA9IFIucHJvcEVxKCdyYW5rJywgJ1EnKTtcbiAgICAgKiAgICAgIHZhciBpc1NwYWRlID0gUi5wcm9wRXEoJ3N1aXQnLCAn4pmg77iOJyk7XG4gICAgICogICAgICB2YXIgaXNRdWVlbk9mU3BhZGVzID0gUi5hbGxQYXNzKFtpc1F1ZWVuLCBpc1NwYWRlXSk7XG4gICAgICpcbiAgICAgKiAgICAgIGlzUXVlZW5PZlNwYWRlcyh7cmFuazogJ1EnLCBzdWl0OiAn4pmj77iOJ30pOyAvLz0+IGZhbHNlXG4gICAgICogICAgICBpc1F1ZWVuT2ZTcGFkZXMoe3Jhbms6ICdRJywgc3VpdDogJ+KZoO+4jid9KTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIGFsbFBhc3MgPSBfY3VycnkxKGZ1bmN0aW9uIGFsbFBhc3MocHJlZHMpIHtcbiAgICAgICAgcmV0dXJuIGN1cnJ5TihyZWR1Y2UobWF4LCAwLCBwbHVjaygnbGVuZ3RoJywgcHJlZHMpKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgICAgICB2YXIgbGVuID0gcHJlZHMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGlkeCA8IGxlbikge1xuICAgICAgICAgICAgICAgIGlmICghcHJlZHNbaWR4XS5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBhIGxpc3Qgb2YgcHJlZGljYXRlcyBhbmQgcmV0dXJucyBhIHByZWRpY2F0ZSB0aGF0IHJldHVybnMgdHJ1ZSBmb3IgYVxuICAgICAqIGdpdmVuIGxpc3Qgb2YgYXJndW1lbnRzIGlmIGF0IGxlYXN0IG9uZSBvZiB0aGUgcHJvdmlkZWQgcHJlZGljYXRlcyBpc1xuICAgICAqIHNhdGlzZmllZCBieSB0aG9zZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBUaGUgZnVuY3Rpb24gcmV0dXJuZWQgaXMgYSBjdXJyaWVkIGZ1bmN0aW9uIHdob3NlIGFyaXR5IG1hdGNoZXMgdGhhdCBvZiB0aGVcbiAgICAgKiBoaWdoZXN0LWFyaXR5IHByZWRpY2F0ZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IExvZ2ljXG4gICAgICogQHNpZyBbKCouLi4gLT4gQm9vbGVhbildIC0+ICgqLi4uIC0+IEJvb2xlYW4pXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHJlZHNcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAgICAgKiBAc2VlIFIuYWxsUGFzc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBndGUgPSBSLmFueVBhc3MoW1IuZ3QsIFIuZXF1YWxzXSk7XG4gICAgICpcbiAgICAgKiAgICAgIGd0ZSgzLCAyKTsgLy89PiB0cnVlXG4gICAgICogICAgICBndGUoMiwgMik7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgZ3RlKDIsIDMpOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGFueVBhc3MgPSBfY3VycnkxKGZ1bmN0aW9uIGFueVBhc3MocHJlZHMpIHtcbiAgICAgICAgcmV0dXJuIGN1cnJ5TihyZWR1Y2UobWF4LCAwLCBwbHVjaygnbGVuZ3RoJywgcHJlZHMpKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgICAgICB2YXIgbGVuID0gcHJlZHMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKGlkeCA8IGxlbikge1xuICAgICAgICAgICAgICAgIGlmIChwcmVkc1tpZHhdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIGFwIGFwcGxpZXMgYSBsaXN0IG9mIGZ1bmN0aW9ucyB0byBhIGxpc3Qgb2YgdmFsdWVzLlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGFwYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC4gQWxzb1xuICAgICAqIHRyZWF0cyBjdXJyaWVkIGZ1bmN0aW9ucyBhcyBhcHBsaWNhdGl2ZXMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjMuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgW2EgLT4gYl0gLT4gW2FdIC0+IFtiXVxuICAgICAqIEBzaWcgQXBwbHkgZiA9PiBmIChhIC0+IGIpIC0+IGYgYSAtPiBmIGJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmbnMgQW4gYXJyYXkgb2YgZnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheX0gdnMgQW4gYXJyYXkgb2YgdmFsdWVzXG4gICAgICogQHJldHVybiB7QXJyYXl9IEFuIGFycmF5IG9mIHJlc3VsdHMgb2YgYXBwbHlpbmcgZWFjaCBvZiBgZm5zYCB0byBhbGwgb2YgYHZzYCBpbiB0dXJuLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuYXAoW1IubXVsdGlwbHkoMiksIFIuYWRkKDMpXSwgWzEsMiwzXSk7IC8vPT4gWzIsIDQsIDYsIDQsIDUsIDZdXG4gICAgICovXG4gICAgLy8gZWxzZVxuICAgIHZhciBhcCA9IF9jdXJyeTIoZnVuY3Rpb24gYXAoYXBwbGljYXRpdmUsIGZuKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgYXBwbGljYXRpdmUuYXAgPT09ICdmdW5jdGlvbicgPyBhcHBsaWNhdGl2ZS5hcChmbikgOiB0eXBlb2YgYXBwbGljYXRpdmUgPT09ICdmdW5jdGlvbicgPyBmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgcmV0dXJuIGFwcGxpY2F0aXZlKHgpKGZuKHgpKTtcbiAgICAgICAgfSA6IC8vIGVsc2VcbiAgICAgICAgX3JlZHVjZShmdW5jdGlvbiAoYWNjLCBmKSB7XG4gICAgICAgICAgICByZXR1cm4gX2NvbmNhdChhY2MsIG1hcChmLCBmbikpO1xuICAgICAgICB9LCBbXSwgYXBwbGljYXRpdmUpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBzcGVjIG9iamVjdCByZWN1cnNpdmVseSBtYXBwaW5nIHByb3BlcnRpZXMgdG8gZnVuY3Rpb25zLCBjcmVhdGVzIGFcbiAgICAgKiBmdW5jdGlvbiBwcm9kdWNpbmcgYW4gb2JqZWN0IG9mIHRoZSBzYW1lIHN0cnVjdHVyZSwgYnkgbWFwcGluZyBlYWNoIHByb3BlcnR5XG4gICAgICogdG8gdGhlIHJlc3VsdCBvZiBjYWxsaW5nIGl0cyBhc3NvY2lhdGVkIGZ1bmN0aW9uIHdpdGggdGhlIHN1cHBsaWVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcge2s6ICgoYSwgYiwgLi4uLCBtKSAtPiB2KX0gLT4gKChhLCBiLCAuLi4sIG0pIC0+IHtrOiB2fSlcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3BlYyBhbiBvYmplY3QgcmVjdXJzaXZlbHkgbWFwcGluZyBwcm9wZXJ0aWVzIHRvIGZ1bmN0aW9ucyBmb3JcbiAgICAgKiAgICAgICAgcHJvZHVjaW5nIHRoZSB2YWx1ZXMgZm9yIHRoZXNlIHByb3BlcnRpZXMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGFuIG9iamVjdCBvZiB0aGUgc2FtZSBzdHJ1Y3R1cmVcbiAgICAgKiBhcyBgc3BlYycsIHdpdGggZWFjaCBwcm9wZXJ0eSBzZXQgdG8gdGhlIHZhbHVlIHJldHVybmVkIGJ5IGNhbGxpbmcgaXRzXG4gICAgICogYXNzb2NpYXRlZCBmdW5jdGlvbiB3aXRoIHRoZSBzdXBwbGllZCBhcmd1bWVudHMuXG4gICAgICogQHNlZSBSLmNvbnZlcmdlLCBSLmp1eHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZ2V0TWV0cmljcyA9IFIuYXBwbHlTcGVjKHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtOiBSLmFkZCxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmVzdGVkOiB7IG11bDogUi5tdWx0aXBseSB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAqICAgICAgZ2V0TWV0cmljcygyLCA0KTsgLy8gPT4geyBzdW06IDYsIG5lc3RlZDogeyBtdWw6IDggfSB9XG4gICAgICovXG4gICAgdmFyIGFwcGx5U3BlYyA9IF9jdXJyeTEoZnVuY3Rpb24gYXBwbHlTcGVjKHNwZWMpIHtcbiAgICAgICAgc3BlYyA9IG1hcChmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB2ID09ICdmdW5jdGlvbicgPyB2IDogYXBwbHlTcGVjKHYpO1xuICAgICAgICB9LCBzcGVjKTtcbiAgICAgICAgcmV0dXJuIGN1cnJ5TihyZWR1Y2UobWF4LCAwLCBwbHVjaygnbGVuZ3RoJywgdmFsdWVzKHNwZWMpKSksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgcmV0dXJuIG1hcChmdW5jdGlvbiAoZikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseShmLCBhcmdzKTtcbiAgICAgICAgICAgIH0sIHNwZWMpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIGl0cyBmaXJzdCBhcmd1bWVudCB3aXRoIHRoZSByZW1haW5pbmdcbiAgICAgKiBhcmd1bWVudHMuIFRoaXMgaXMgb2NjYXNpb25hbGx5IHVzZWZ1bCBhcyBhIGNvbnZlcmdpbmcgZnVuY3Rpb24gZm9yXG4gICAgICogYFIuY29udmVyZ2VgOiB0aGUgbGVmdCBicmFuY2ggY2FuIHByb2R1Y2UgYSBmdW5jdGlvbiB3aGlsZSB0aGUgcmlnaHQgYnJhbmNoXG4gICAgICogcHJvZHVjZXMgYSB2YWx1ZSB0byBiZSBwYXNzZWQgdG8gdGhhdCBmdW5jdGlvbiBhcyBhbiBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuOS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoKi4uLiAtPiBhKSwqLi4uIC0+IGFcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gYXBwbHkgdG8gdGhlIHJlbWFpbmluZyBhcmd1bWVudHMuXG4gICAgICogQHBhcmFtIHsuLi4qfSBhcmdzIEFueSBudW1iZXIgb2YgcG9zaXRpb25hbCBhcmd1bWVudHMuXG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIuYXBwbHlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaW5kZW50TiA9IFIucGlwZShSLnRpbWVzKFIuYWx3YXlzKCcgJykpLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgUi5qb2luKCcnKSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIFIucmVwbGFjZSgvXig/ISQpL2dtKSk7XG4gICAgICpcbiAgICAgKiAgICAgIHZhciBmb3JtYXQgPSBSLmNvbnZlcmdlKFIuY2FsbCwgW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFIucGlwZShSLnByb3AoJ2luZGVudCcpLCBpbmRlbnROKSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSLnByb3AoJ3ZhbHVlJylcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAqXG4gICAgICogICAgICBmb3JtYXQoe2luZGVudDogMiwgdmFsdWU6ICdmb29cXG5iYXJcXG5iYXpcXG4nfSk7IC8vPT4gJyAgZm9vXFxuICBiYXJcXG4gIGJhelxcbidcbiAgICAgKi9cbiAgICB2YXIgY2FsbCA9IGN1cnJ5KGZ1bmN0aW9uIGNhbGwoZm4pIHtcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIF9zbGljZShhcmd1bWVudHMsIDEpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIGBjaGFpbmAgbWFwcyBhIGZ1bmN0aW9uIG92ZXIgYSBsaXN0IGFuZCBjb25jYXRlbmF0ZXMgdGhlIHJlc3VsdHMuIGBjaGFpbmBcbiAgICAgKiBpcyBhbHNvIGtub3duIGFzIGBmbGF0TWFwYCBpbiBzb21lIGxpYnJhcmllc1xuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGNoYWluYCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudCxcbiAgICAgKiBhY2NvcmRpbmcgdG8gdGhlIFtGYW50YXN5TGFuZCBDaGFpbiBzcGVjXShodHRwczovL2dpdGh1Yi5jb20vZmFudGFzeWxhbmQvZmFudGFzeS1sYW5kI2NoYWluKS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMy4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIENoYWluIG0gPT4gKGEgLT4gbSBiKSAtPiBtIGEgLT4gbSBiXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0XG4gICAgICogQHJldHVybiB7QXJyYXl9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGR1cGxpY2F0ZSA9IG4gPT4gW24sIG5dO1xuICAgICAqICAgICAgUi5jaGFpbihkdXBsaWNhdGUsIFsxLCAyLCAzXSk7IC8vPT4gWzEsIDEsIDIsIDIsIDMsIDNdXG4gICAgICovXG4gICAgdmFyIGNoYWluID0gX2N1cnJ5MihfZGlzcGF0Y2hhYmxlKCdjaGFpbicsIF94Y2hhaW4sIGZ1bmN0aW9uIGNoYWluKGZuLCBtb25hZCkge1xuICAgICAgICBpZiAodHlwZW9mIG1vbmFkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtb25hZC5jYWxsKHRoaXMsIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfbWFrZUZsYXQoZmFsc2UpKG1hcChmbiwgbW9uYWQpKTtcbiAgICB9KSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgZnVuY3Rpb24sIGBmbmAsIHdoaWNoIGVuY2Fwc3VsYXRlcyBpZi9lbHNlLWlmL2Vsc2UgbG9naWMuXG4gICAgICogYFIuY29uZGAgdGFrZXMgYSBsaXN0IG9mIFtwcmVkaWNhdGUsIHRyYW5zZm9ybV0gcGFpcnMuIEFsbCBvZiB0aGUgYXJndW1lbnRzXG4gICAgICogdG8gYGZuYCBhcmUgYXBwbGllZCB0byBlYWNoIG9mIHRoZSBwcmVkaWNhdGVzIGluIHR1cm4gdW50aWwgb25lIHJldHVybnMgYVxuICAgICAqIFwidHJ1dGh5XCIgdmFsdWUsIGF0IHdoaWNoIHBvaW50IGBmbmAgcmV0dXJucyB0aGUgcmVzdWx0IG9mIGFwcGx5aW5nIGl0c1xuICAgICAqIGFyZ3VtZW50cyB0byB0aGUgY29ycmVzcG9uZGluZyB0cmFuc2Zvcm1lci4gSWYgbm9uZSBvZiB0aGUgcHJlZGljYXRlc1xuICAgICAqIG1hdGNoZXMsIGBmbmAgcmV0dXJucyB1bmRlZmluZWQuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjYuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgW1soKi4uLiAtPiBCb29sZWFuKSwoKi4uLiAtPiAqKV1dIC0+ICgqLi4uIC0+ICopXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGFpcnNcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZm4gPSBSLmNvbmQoW1xuICAgICAqICAgICAgICBbUi5lcXVhbHMoMCksICAgUi5hbHdheXMoJ3dhdGVyIGZyZWV6ZXMgYXQgMMKwQycpXSxcbiAgICAgKiAgICAgICAgW1IuZXF1YWxzKDEwMCksIFIuYWx3YXlzKCd3YXRlciBib2lscyBhdCAxMDDCsEMnKV0sXG4gICAgICogICAgICAgIFtSLlQsICAgICAgICAgICB0ZW1wID0+ICdub3RoaW5nIHNwZWNpYWwgaGFwcGVucyBhdCAnICsgdGVtcCArICfCsEMnXVxuICAgICAqICAgICAgXSk7XG4gICAgICogICAgICBmbigwKTsgLy89PiAnd2F0ZXIgZnJlZXplcyBhdCAwwrBDJ1xuICAgICAqICAgICAgZm4oNTApOyAvLz0+ICdub3RoaW5nIHNwZWNpYWwgaGFwcGVucyBhdCA1MMKwQydcbiAgICAgKiAgICAgIGZuKDEwMCk7IC8vPT4gJ3dhdGVyIGJvaWxzIGF0IDEwMMKwQydcbiAgICAgKi9cbiAgICB2YXIgY29uZCA9IF9jdXJyeTEoZnVuY3Rpb24gY29uZChwYWlycykge1xuICAgICAgICB2YXIgYXJpdHkgPSByZWR1Y2UobWF4LCAwLCBtYXAoZnVuY3Rpb24gKHBhaXIpIHtcbiAgICAgICAgICAgIHJldHVybiBwYWlyWzBdLmxlbmd0aDtcbiAgICAgICAgfSwgcGFpcnMpKTtcbiAgICAgICAgcmV0dXJuIF9hcml0eShhcml0eSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoaWR4IDwgcGFpcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhaXJzW2lkeF1bMF0uYXBwbHkodGhpcywgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFpcnNbaWR4XVsxXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBXcmFwcyBhIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGluc2lkZSBhIGN1cnJpZWQgZnVuY3Rpb24gdGhhdCBjYW4gYmUgY2FsbGVkXG4gICAgICogd2l0aCB0aGUgc2FtZSBhcmd1bWVudHMgYW5kIHJldHVybnMgdGhlIHNhbWUgdHlwZS4gVGhlIGFyaXR5IG9mIHRoZSBmdW5jdGlvblxuICAgICAqIHJldHVybmVkIGlzIHNwZWNpZmllZCB0byBhbGxvdyB1c2luZyB2YXJpYWRpYyBjb25zdHJ1Y3RvciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjQuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgTnVtYmVyIC0+ICgqIC0+IHsqfSkgLT4gKCogLT4geyp9KVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuIFRoZSBhcml0eSBvZiB0aGUgY29uc3RydWN0b3IgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gRm4gVGhlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IEEgd3JhcHBlZCwgY3VycmllZCBjb25zdHJ1Y3RvciBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyBWYXJpYWRpYyBjb25zdHJ1Y3RvciBmdW5jdGlvblxuICAgICAqICAgICAgdmFyIFdpZGdldCA9ICgpID0+IHtcbiAgICAgKiAgICAgICAgdGhpcy5jaGlsZHJlbiA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICogICAgICAgIC8vIC4uLlxuICAgICAqICAgICAgfTtcbiAgICAgKiAgICAgIFdpZGdldC5wcm90b3R5cGUgPSB7XG4gICAgICogICAgICAgIC8vIC4uLlxuICAgICAqICAgICAgfTtcbiAgICAgKiAgICAgIHZhciBhbGxDb25maWdzID0gW1xuICAgICAqICAgICAgICAvLyAuLi5cbiAgICAgKiAgICAgIF07XG4gICAgICogICAgICBSLm1hcChSLmNvbnN0cnVjdE4oMSwgV2lkZ2V0KSwgYWxsQ29uZmlncyk7IC8vIGEgbGlzdCBvZiBXaWRnZXRzXG4gICAgICovXG4gICAgdmFyIGNvbnN0cnVjdE4gPSBfY3VycnkyKGZ1bmN0aW9uIGNvbnN0cnVjdE4obiwgRm4pIHtcbiAgICAgICAgaWYgKG4gPiAxMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb25zdHJ1Y3RvciB3aXRoIGdyZWF0ZXIgdGhhbiB0ZW4gYXJndW1lbnRzJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4gPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBGbigpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3VycnkobkFyeShuLCBmdW5jdGlvbiAoJDAsICQxLCAkMiwgJDMsICQ0LCAkNSwgJDYsICQ3LCAkOCwgJDkpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm4oJDApO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm4oJDAsICQxKTtcbiAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZuKCQwLCAkMSwgJDIpO1xuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm4oJDAsICQxLCAkMiwgJDMpO1xuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm4oJDAsICQxLCAkMiwgJDMsICQ0KTtcbiAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZuKCQwLCAkMSwgJDIsICQzLCAkNCwgJDUpO1xuICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm4oJDAsICQxLCAkMiwgJDMsICQ0LCAkNSwgJDYpO1xuICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRm4oJDAsICQxLCAkMiwgJDMsICQ0LCAkNSwgJDYsICQ3KTtcbiAgICAgICAgICAgIGNhc2UgOTpcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZuKCQwLCAkMSwgJDIsICQzLCAkNCwgJDUsICQ2LCAkNywgJDgpO1xuICAgICAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZuKCQwLCAkMSwgJDIsICQzLCAkNCwgJDUsICQ2LCAkNywgJDgsICQ5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQWNjZXB0cyBhIGNvbnZlcmdpbmcgZnVuY3Rpb24gYW5kIGEgbGlzdCBvZiBicmFuY2hpbmcgZnVuY3Rpb25zIGFuZCByZXR1cm5zXG4gICAgICogYSBuZXcgZnVuY3Rpb24uIFdoZW4gaW52b2tlZCwgdGhpcyBuZXcgZnVuY3Rpb24gaXMgYXBwbGllZCB0byBzb21lXG4gICAgICogYXJndW1lbnRzLCBlYWNoIGJyYW5jaGluZyBmdW5jdGlvbiBpcyBhcHBsaWVkIHRvIHRob3NlIHNhbWUgYXJndW1lbnRzLiBUaGVcbiAgICAgKiByZXN1bHRzIG9mIGVhY2ggYnJhbmNoaW5nIGZ1bmN0aW9uIGFyZSBwYXNzZWQgYXMgYXJndW1lbnRzIHRvIHRoZSBjb252ZXJnaW5nXG4gICAgICogZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgcmV0dXJuIHZhbHVlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC40LjJcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICh4MSAtPiB4MiAtPiAuLi4gLT4geikgLT4gWyhhIC0+IGIgLT4gLi4uIC0+IHgxKSwgKGEgLT4gYiAtPiAuLi4gLT4geDIpLCAuLi5dIC0+IChhIC0+IGIgLT4gLi4uIC0+IHopXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYWZ0ZXIgQSBmdW5jdGlvbi4gYGFmdGVyYCB3aWxsIGJlIGludm9rZWQgd2l0aCB0aGUgcmV0dXJuIHZhbHVlcyBvZlxuICAgICAqICAgICAgICBgZm4xYCBhbmQgYGZuMmAgYXMgaXRzIGFyZ3VtZW50cy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmdW5jdGlvbnMgQSBsaXN0IG9mIGZ1bmN0aW9ucy5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGFkZCA9IChhLCBiKSA9PiBhICsgYjtcbiAgICAgKiAgICAgIHZhciBtdWx0aXBseSA9IChhLCBiKSA9PiBhICogYjtcbiAgICAgKiAgICAgIHZhciBzdWJ0cmFjdCA9IChhLCBiKSA9PiBhIC0gYjtcbiAgICAgKlxuICAgICAqICAgICAgLy/iiYUgbXVsdGlwbHkoIGFkZCgxLCAyKSwgc3VidHJhY3QoMSwgMikgKTtcbiAgICAgKiAgICAgIFIuY29udmVyZ2UobXVsdGlwbHksIFthZGQsIHN1YnRyYWN0XSkoMSwgMik7IC8vPT4gLTNcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGFkZDMgPSAoYSwgYiwgYykgPT4gYSArIGIgKyBjO1xuICAgICAqICAgICAgUi5jb252ZXJnZShhZGQzLCBbbXVsdGlwbHksIGFkZCwgc3VidHJhY3RdKSgxLCAyKTsgLy89PiA0XG4gICAgICovXG4gICAgdmFyIGNvbnZlcmdlID0gX2N1cnJ5MihmdW5jdGlvbiBjb252ZXJnZShhZnRlciwgZm5zKSB7XG4gICAgICAgIHJldHVybiBjdXJyeU4ocmVkdWNlKG1heCwgMCwgcGx1Y2soJ2xlbmd0aCcsIGZucykpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgIHZhciBjb250ZXh0ID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiBhZnRlci5hcHBseShjb250ZXh0LCBfbWFwKGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmbi5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIH0sIGZucykpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvdW50cyB0aGUgZWxlbWVudHMgb2YgYSBsaXN0IGFjY29yZGluZyB0byBob3cgbWFueSBtYXRjaCBlYWNoIHZhbHVlIG9mIGFcbiAgICAgKiBrZXkgZ2VuZXJhdGVkIGJ5IHRoZSBzdXBwbGllZCBmdW5jdGlvbi4gUmV0dXJucyBhbiBvYmplY3QgbWFwcGluZyB0aGUga2V5c1xuICAgICAqIHByb2R1Y2VkIGJ5IGBmbmAgdG8gdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyBpbiB0aGUgbGlzdC4gTm90ZSB0aGF0IGFsbFxuICAgICAqIGtleXMgYXJlIGNvZXJjZWQgdG8gc3RyaW5ncyBiZWNhdXNlIG9mIGhvdyBKYXZhU2NyaXB0IG9iamVjdHMgd29yay5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyAoYSAtPiBTdHJpbmcpIC0+IFthXSAtPiB7Kn1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdXNlZCB0byBtYXAgdmFsdWVzIHRvIGtleXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgbGlzdCB0byBjb3VudCBlbGVtZW50cyBmcm9tLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQW4gb2JqZWN0IG1hcHBpbmcga2V5cyB0byBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgaW4gdGhlIGxpc3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG51bWJlcnMgPSBbMS4wLCAxLjEsIDEuMiwgMi4wLCAzLjAsIDIuMl07XG4gICAgICogICAgICB2YXIgbGV0dGVycyA9IFIuc3BsaXQoJycsICdhYmNBQkNhYWFCQmMnKTtcbiAgICAgKiAgICAgIFIuY291bnRCeShNYXRoLmZsb29yKShudW1iZXJzKTsgICAgLy89PiB7JzEnOiAzLCAnMic6IDIsICczJzogMX1cbiAgICAgKiAgICAgIFIuY291bnRCeShSLnRvTG93ZXIpKGxldHRlcnMpOyAgIC8vPT4geydhJzogNSwgJ2InOiA0LCAnYyc6IDN9XG4gICAgICovXG4gICAgdmFyIGNvdW50QnkgPSByZWR1Y2VCeShmdW5jdGlvbiAoYWNjLCBlbGVtKSB7XG4gICAgICAgIHJldHVybiBhY2MgKyAxO1xuICAgIH0sIDApO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IHdpdGhvdXQgYW55IGNvbnNlY3V0aXZlbHkgcmVwZWF0aW5nIGVsZW1lbnRzLiBFcXVhbGl0eSBpc1xuICAgICAqIGRldGVybWluZWQgYnkgYXBwbHlpbmcgdGhlIHN1cHBsaWVkIHByZWRpY2F0ZSB0d28gY29uc2VjdXRpdmUgZWxlbWVudHMuIFRoZVxuICAgICAqIGZpcnN0IGVsZW1lbnQgaW4gYSBzZXJpZXMgb2YgZXF1YWwgZWxlbWVudCBpcyB0aGUgb25lIGJlaW5nIHByZXNlcnZlZC5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBkcm9wUmVwZWF0c1dpdGhgIG1ldGhvZCBvZiB0aGUgc2Vjb25kIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQWN0cyBhcyBhIHRyYW5zZHVjZXIgaWYgYSB0cmFuc2Zvcm1lciBpcyBnaXZlbiBpbiBsaXN0IHBvc2l0aW9uLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhLCBhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkIEEgcHJlZGljYXRlIHVzZWQgdG8gdGVzdCB3aGV0aGVyIHR3byBpdGVtcyBhcmUgZXF1YWwuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdCBUaGUgYXJyYXkgdG8gY29uc2lkZXIuXG4gICAgICogQHJldHVybiB7QXJyYXl9IGBsaXN0YCB3aXRob3V0IHJlcGVhdGluZyBlbGVtZW50cy5cbiAgICAgKiBAc2VlIFIudHJhbnNkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGwgPSBbMSwgLTEsIDEsIDMsIDQsIC00LCAtNCwgLTUsIDUsIDMsIDNdO1xuICAgICAqICAgICAgUi5kcm9wUmVwZWF0c1dpdGgoUi5lcUJ5KE1hdGguYWJzKSwgbCk7IC8vPT4gWzEsIDMsIDQsIC01LCAzXVxuICAgICAqL1xuICAgIHZhciBkcm9wUmVwZWF0c1dpdGggPSBfY3VycnkyKF9kaXNwYXRjaGFibGUoJ2Ryb3BSZXBlYXRzV2l0aCcsIF94ZHJvcFJlcGVhdHNXaXRoLCBmdW5jdGlvbiBkcm9wUmVwZWF0c1dpdGgocHJlZCwgbGlzdCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBpZHggPSAxO1xuICAgICAgICB2YXIgbGVuID0gbGlzdC5sZW5ndGg7XG4gICAgICAgIGlmIChsZW4gIT09IDApIHtcbiAgICAgICAgICAgIHJlc3VsdFswXSA9IGxpc3RbMF07XG4gICAgICAgICAgICB3aGlsZSAoaWR4IDwgbGVuKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFwcmVkKGxhc3QocmVzdWx0KSwgbGlzdFtpZHhdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aF0gPSBsaXN0W2lkeF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlkeCArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSkpO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBmdW5jdGlvbiBhbmQgdHdvIHZhbHVlcyBpbiBpdHMgZG9tYWluIGFuZCByZXR1cm5zIGB0cnVlYCBpZiB0aGVcbiAgICAgKiB2YWx1ZXMgbWFwIHRvIHRoZSBzYW1lIHZhbHVlIGluIHRoZSBjb2RvbWFpbjsgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE4LjBcbiAgICAgKiBAY2F0ZWdvcnkgUmVsYXRpb25cbiAgICAgKiBAc2lnIChhIC0+IGIpIC0+IGEgLT4gYSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZlxuICAgICAqIEBwYXJhbSB7Kn0geFxuICAgICAqIEBwYXJhbSB7Kn0geVxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5lcUJ5KE1hdGguYWJzLCA1LCAtNSk7IC8vPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBlcUJ5ID0gX2N1cnJ5MyhmdW5jdGlvbiBlcUJ5KGYsIHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIGVxdWFscyhmKHgpLCBmKHkpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJlcG9ydHMgd2hldGhlciB0d28gb2JqZWN0cyBoYXZlIHRoZSBzYW1lIHZhbHVlLCBpbiBgUi5lcXVhbHNgIHRlcm1zLCBmb3JcbiAgICAgKiB0aGUgc3BlY2lmaWVkIHByb3BlcnR5LiBVc2VmdWwgYXMgYSBjdXJyaWVkIHByZWRpY2F0ZS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgayAtPiB7azogdn0gLT4ge2s6IHZ9IC0+IEJvb2xlYW5cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcCBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gY29tcGFyZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmoxXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iajJcbiAgICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIG8xID0geyBhOiAxLCBiOiAyLCBjOiAzLCBkOiA0IH07XG4gICAgICogICAgICB2YXIgbzIgPSB7IGE6IDEwLCBiOiAyMCwgYzogMywgZDogNDAgfTtcbiAgICAgKiAgICAgIFIuZXFQcm9wcygnYScsIG8xLCBvMik7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuZXFQcm9wcygnYycsIG8xLCBvMik7IC8vPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBlcVByb3BzID0gX2N1cnJ5MyhmdW5jdGlvbiBlcVByb3BzKHByb3AsIG9iajEsIG9iajIpIHtcbiAgICAgICAgcmV0dXJuIGVxdWFscyhvYmoxW3Byb3BdLCBvYmoyW3Byb3BdKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFNwbGl0cyBhIGxpc3QgaW50byBzdWItbGlzdHMgc3RvcmVkIGluIGFuIG9iamVjdCwgYmFzZWQgb24gdGhlIHJlc3VsdCBvZlxuICAgICAqIGNhbGxpbmcgYSBTdHJpbmctcmV0dXJuaW5nIGZ1bmN0aW9uIG9uIGVhY2ggZWxlbWVudCwgYW5kIGdyb3VwaW5nIHRoZVxuICAgICAqIHJlc3VsdHMgYWNjb3JkaW5nIHRvIHZhbHVlcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBncm91cEJ5YCBtZXRob2Qgb2YgdGhlIHNlY29uZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEFjdHMgYXMgYSB0cmFuc2R1Y2VyIGlmIGEgdHJhbnNmb3JtZXIgaXMgZ2l2ZW4gaW4gbGlzdCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IFN0cmluZykgLT4gW2FdIC0+IHtTdHJpbmc6IFthXX1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiA6OiBhIC0+IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGFycmF5IHRvIGdyb3VwXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbiBvYmplY3Qgd2l0aCB0aGUgb3V0cHV0IG9mIGBmbmAgZm9yIGtleXMsIG1hcHBlZCB0byBhcnJheXMgb2YgZWxlbWVudHNcbiAgICAgKiAgICAgICAgIHRoYXQgcHJvZHVjZWQgdGhhdCBrZXkgd2hlbiBwYXNzZWQgdG8gYGZuYC5cbiAgICAgKiBAc2VlIFIudHJhbnNkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGJ5R3JhZGUgPSBSLmdyb3VwQnkoZnVuY3Rpb24oc3R1ZGVudCkge1xuICAgICAqICAgICAgICB2YXIgc2NvcmUgPSBzdHVkZW50LnNjb3JlO1xuICAgICAqICAgICAgICByZXR1cm4gc2NvcmUgPCA2NSA/ICdGJyA6XG4gICAgICogICAgICAgICAgICAgICBzY29yZSA8IDcwID8gJ0QnIDpcbiAgICAgKiAgICAgICAgICAgICAgIHNjb3JlIDwgODAgPyAnQycgOlxuICAgICAqICAgICAgICAgICAgICAgc2NvcmUgPCA5MCA/ICdCJyA6ICdBJztcbiAgICAgKiAgICAgIH0pO1xuICAgICAqICAgICAgdmFyIHN0dWRlbnRzID0gW3tuYW1lOiAnQWJieScsIHNjb3JlOiA4NH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAge25hbWU6ICdFZGR5Jywgc2NvcmU6IDU4fSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAvLyAuLi5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICB7bmFtZTogJ0phY2snLCBzY29yZTogNjl9XTtcbiAgICAgKiAgICAgIGJ5R3JhZGUoc3R1ZGVudHMpO1xuICAgICAqICAgICAgLy8ge1xuICAgICAqICAgICAgLy8gICAnQSc6IFt7bmFtZTogJ0RpYW5uZScsIHNjb3JlOiA5OX1dLFxuICAgICAqICAgICAgLy8gICAnQic6IFt7bmFtZTogJ0FiYnknLCBzY29yZTogODR9XVxuICAgICAqICAgICAgLy8gICAvLyAuLi4sXG4gICAgICogICAgICAvLyAgICdGJzogW3tuYW1lOiAnRWRkeScsIHNjb3JlOiA1OH1dXG4gICAgICogICAgICAvLyB9XG4gICAgICovXG4gICAgdmFyIGdyb3VwQnkgPSBfY3VycnkyKF9jaGVja0Zvck1ldGhvZCgnZ3JvdXBCeScsIHJlZHVjZUJ5KGZ1bmN0aW9uIChhY2MsIGl0ZW0pIHtcbiAgICAgICAgaWYgKGFjYyA9PSBudWxsKSB7XG4gICAgICAgICAgICBhY2MgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBhY2MucHVzaChpdGVtKTtcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCBudWxsKSkpO1xuXG4gICAgLyoqXG4gICAgICogR2l2ZW4gYSBmdW5jdGlvbiB0aGF0IGdlbmVyYXRlcyBhIGtleSwgdHVybnMgYSBsaXN0IG9mIG9iamVjdHMgaW50byBhblxuICAgICAqIG9iamVjdCBpbmRleGluZyB0aGUgb2JqZWN0cyBieSB0aGUgZ2l2ZW4ga2V5LiBOb3RlIHRoYXQgaWYgbXVsdGlwbGVcbiAgICAgKiBvYmplY3RzIGdlbmVyYXRlIHRoZSBzYW1lIHZhbHVlIGZvciB0aGUgaW5kZXhpbmcga2V5IG9ubHkgdGhlIGxhc3QgdmFsdWVcbiAgICAgKiB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBnZW5lcmF0ZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQWN0cyBhcyBhIHRyYW5zZHVjZXIgaWYgYSB0cmFuc2Zvcm1lciBpcyBnaXZlbiBpbiBsaXN0IHBvc2l0aW9uLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xOS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChhIC0+IFN0cmluZykgLT4gW3trOiB2fV0gLT4ge2s6IHtrOiB2fX1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBGdW5jdGlvbiA6OiBhIC0+IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSBvZiBvYmplY3RzIHRvIGluZGV4XG4gICAgICogQHJldHVybiB7T2JqZWN0fSBBbiBvYmplY3QgaW5kZXhpbmcgZWFjaCBhcnJheSBlbGVtZW50IGJ5IHRoZSBnaXZlbiBwcm9wZXJ0eS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbGlzdCA9IFt7aWQ6ICd4eXonLCB0aXRsZTogJ0EnfSwge2lkOiAnYWJjJywgdGl0bGU6ICdCJ31dO1xuICAgICAqICAgICAgUi5pbmRleEJ5KFIucHJvcCgnaWQnKSwgbGlzdCk7XG4gICAgICogICAgICAvLz0+IHthYmM6IHtpZDogJ2FiYycsIHRpdGxlOiAnQid9LCB4eXo6IHtpZDogJ3h5eicsIHRpdGxlOiAnQSd9fVxuICAgICAqL1xuICAgIHZhciBpbmRleEJ5ID0gcmVkdWNlQnkoZnVuY3Rpb24gKGFjYywgZWxlbSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICB9LCBudWxsKTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGFuIGl0ZW0gaW4gYW4gYXJyYXksIG9yIC0xXG4gICAgICogaWYgdGhlIGl0ZW0gaXMgbm90IGluY2x1ZGVkIGluIHRoZSBhcnJheS4gYFIuZXF1YWxzYCBpcyB1c2VkIHRvIGRldGVybWluZVxuICAgICAqIGVxdWFsaXR5LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgYSAtPiBbYV0gLT4gTnVtYmVyXG4gICAgICogQHBhcmFtIHsqfSB0YXJnZXQgVGhlIGl0ZW0gdG8gZmluZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB4cyBUaGUgYXJyYXkgdG8gc2VhcmNoIGluLlxuICAgICAqIEByZXR1cm4ge051bWJlcn0gdGhlIGluZGV4IG9mIHRoZSB0YXJnZXQsIG9yIC0xIGlmIHRoZSB0YXJnZXQgaXMgbm90IGZvdW5kLlxuICAgICAqIEBzZWUgUi5sYXN0SW5kZXhPZlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuaW5kZXhPZigzLCBbMSwyLDMsNF0pOyAvLz0+IDJcbiAgICAgKiAgICAgIFIuaW5kZXhPZigxMCwgWzEsMiwzLDRdKTsgLy89PiAtMVxuICAgICAqL1xuICAgIHZhciBpbmRleE9mID0gX2N1cnJ5MihmdW5jdGlvbiBpbmRleE9mKHRhcmdldCwgeHMpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB4cy5pbmRleE9mID09PSAnZnVuY3Rpb24nICYmICFfaXNBcnJheSh4cykgPyB4cy5pbmRleE9mKHRhcmdldCkgOiBfaW5kZXhPZih4cywgdGFyZ2V0LCAwKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIGp1eHQgYXBwbGllcyBhIGxpc3Qgb2YgZnVuY3Rpb25zIHRvIGEgbGlzdCBvZiB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIFsoYSwgYiwgLi4uLCBtKSAtPiBuXSAtPiAoKGEsIGIsIC4uLiwgbSkgLT4gW25dKVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGZucyBBbiBhcnJheSBvZiBmdW5jdGlvbnNcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBsaXN0IG9mIHZhbHVlcyBhZnRlciBhcHBseWluZyBlYWNoIG9mIHRoZSBvcmlnaW5hbCBgZm5zYCB0byBpdHMgcGFyYW1ldGVycy5cbiAgICAgKiBAc2VlIFIuYXBwbHlTcGVjXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGdldFJhbmdlID0gUi5qdXh0KFtNYXRoLm1pbiwgTWF0aC5tYXhdKTtcbiAgICAgKiAgICAgIGdldFJhbmdlKDMsIDQsIDksIC0zKTsgLy89PiBbLTMsIDldXG4gICAgICovXG4gICAgdmFyIGp1eHQgPSBfY3VycnkxKGZ1bmN0aW9uIGp1eHQoZm5zKSB7XG4gICAgICAgIHJldHVybiBjb252ZXJnZShfYXJyYXlPZiwgZm5zKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBsZW5zIGZvciB0aGUgZ2l2ZW4gZ2V0dGVyIGFuZCBzZXR0ZXIgZnVuY3Rpb25zLiBUaGUgZ2V0dGVyIFwiZ2V0c1wiXG4gICAgICogdGhlIHZhbHVlIG9mIHRoZSBmb2N1czsgdGhlIHNldHRlciBcInNldHNcIiB0aGUgdmFsdWUgb2YgdGhlIGZvY3VzLiBUaGUgc2V0dGVyXG4gICAgICogc2hvdWxkIG5vdCBtdXRhdGUgdGhlIGRhdGEgc3RydWN0dXJlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC44LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHR5cGVkZWZuIExlbnMgcyBhID0gRnVuY3RvciBmID0+IChhIC0+IGYgYSkgLT4gcyAtPiBmIHNcbiAgICAgKiBAc2lnIChzIC0+IGEpIC0+ICgoYSwgcykgLT4gcykgLT4gTGVucyBzIGFcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBnZXR0ZXJcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXJcbiAgICAgKiBAcmV0dXJuIHtMZW5zfVxuICAgICAqIEBzZWUgUi52aWV3LCBSLnNldCwgUi5vdmVyLCBSLmxlbnNJbmRleCwgUi5sZW5zUHJvcFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB4TGVucyA9IFIubGVucyhSLnByb3AoJ3gnKSwgUi5hc3NvYygneCcpKTtcbiAgICAgKlxuICAgICAqICAgICAgUi52aWV3KHhMZW5zLCB7eDogMSwgeTogMn0pOyAgICAgICAgICAgIC8vPT4gMVxuICAgICAqICAgICAgUi5zZXQoeExlbnMsIDQsIHt4OiAxLCB5OiAyfSk7ICAgICAgICAgIC8vPT4ge3g6IDQsIHk6IDJ9XG4gICAgICogICAgICBSLm92ZXIoeExlbnMsIFIubmVnYXRlLCB7eDogMSwgeTogMn0pOyAgLy89PiB7eDogLTEsIHk6IDJ9XG4gICAgICovXG4gICAgdmFyIGxlbnMgPSBfY3VycnkyKGZ1bmN0aW9uIGxlbnMoZ2V0dGVyLCBzZXR0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICh0b0Z1bmN0b3JGbikge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWFwKGZ1bmN0aW9uIChmb2N1cykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2V0dGVyKGZvY3VzLCB0YXJnZXQpO1xuICAgICAgICAgICAgICAgIH0sIHRvRnVuY3RvckZuKGdldHRlcih0YXJnZXQpKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGxlbnMgd2hvc2UgZm9jdXMgaXMgdGhlIHNwZWNpZmllZCBpbmRleC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAdHlwZWRlZm4gTGVucyBzIGEgPSBGdW5jdG9yIGYgPT4gKGEgLT4gZiBhKSAtPiBzIC0+IGYgc1xuICAgICAqIEBzaWcgTnVtYmVyIC0+IExlbnMgcyBhXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG5cbiAgICAgKiBAcmV0dXJuIHtMZW5zfVxuICAgICAqIEBzZWUgUi52aWV3LCBSLnNldCwgUi5vdmVyXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGhlYWRMZW5zID0gUi5sZW5zSW5kZXgoMCk7XG4gICAgICpcbiAgICAgKiAgICAgIFIudmlldyhoZWFkTGVucywgWydhJywgJ2InLCAnYyddKTsgICAgICAgICAgICAvLz0+ICdhJ1xuICAgICAqICAgICAgUi5zZXQoaGVhZExlbnMsICd4JywgWydhJywgJ2InLCAnYyddKTsgICAgICAgIC8vPT4gWyd4JywgJ2InLCAnYyddXG4gICAgICogICAgICBSLm92ZXIoaGVhZExlbnMsIFIudG9VcHBlciwgWydhJywgJ2InLCAnYyddKTsgLy89PiBbJ0EnLCAnYicsICdjJ11cbiAgICAgKi9cbiAgICB2YXIgbGVuc0luZGV4ID0gX2N1cnJ5MShmdW5jdGlvbiBsZW5zSW5kZXgobikge1xuICAgICAgICByZXR1cm4gbGVucyhudGgobiksIHVwZGF0ZShuKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbGVucyB3aG9zZSBmb2N1cyBpcyB0aGUgc3BlY2lmaWVkIHBhdGguXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHR5cGVkZWZuIExlbnMgcyBhID0gRnVuY3RvciBmID0+IChhIC0+IGYgYSkgLT4gcyAtPiBmIHNcbiAgICAgKiBAc2lnIFtTdHJpbmddIC0+IExlbnMgcyBhXG4gICAgICogQHBhcmFtIHtBcnJheX0gcGF0aCBUaGUgcGF0aCB0byB1c2UuXG4gICAgICogQHJldHVybiB7TGVuc31cbiAgICAgKiBAc2VlIFIudmlldywgUi5zZXQsIFIub3ZlclxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciB4eUxlbnMgPSBSLmxlbnNQYXRoKFsneCcsICd5J10pO1xuICAgICAqXG4gICAgICogICAgICBSLnZpZXcoeHlMZW5zLCB7eDoge3k6IDIsIHo6IDN9fSk7ICAgICAgICAgICAgLy89PiAyXG4gICAgICogICAgICBSLnNldCh4eUxlbnMsIDQsIHt4OiB7eTogMiwgejogM319KTsgICAgICAgICAgLy89PiB7eDoge3k6IDQsIHo6IDN9fVxuICAgICAqICAgICAgUi5vdmVyKHh5TGVucywgUi5uZWdhdGUsIHt4OiB7eTogMiwgejogM319KTsgIC8vPT4ge3g6IHt5OiAtMiwgejogM319XG4gICAgICovXG4gICAgdmFyIGxlbnNQYXRoID0gX2N1cnJ5MShmdW5jdGlvbiBsZW5zUGF0aChwKSB7XG4gICAgICAgIHJldHVybiBsZW5zKHBhdGgocCksIGFzc29jUGF0aChwKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbGVucyB3aG9zZSBmb2N1cyBpcyB0aGUgc3BlY2lmaWVkIHByb3BlcnR5LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEB0eXBlZGVmbiBMZW5zIHMgYSA9IEZ1bmN0b3IgZiA9PiAoYSAtPiBmIGEpIC0+IHMgLT4gZiBzXG4gICAgICogQHNpZyBTdHJpbmcgLT4gTGVucyBzIGFcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30ga1xuICAgICAqIEByZXR1cm4ge0xlbnN9XG4gICAgICogQHNlZSBSLnZpZXcsIFIuc2V0LCBSLm92ZXJcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgeExlbnMgPSBSLmxlbnNQcm9wKCd4Jyk7XG4gICAgICpcbiAgICAgKiAgICAgIFIudmlldyh4TGVucywge3g6IDEsIHk6IDJ9KTsgICAgICAgICAgICAvLz0+IDFcbiAgICAgKiAgICAgIFIuc2V0KHhMZW5zLCA0LCB7eDogMSwgeTogMn0pOyAgICAgICAgICAvLz0+IHt4OiA0LCB5OiAyfVxuICAgICAqICAgICAgUi5vdmVyKHhMZW5zLCBSLm5lZ2F0ZSwge3g6IDEsIHk6IDJ9KTsgIC8vPT4ge3g6IC0xLCB5OiAyfVxuICAgICAqL1xuICAgIHZhciBsZW5zUHJvcCA9IF9jdXJyeTEoZnVuY3Rpb24gbGVuc1Byb3Aoaykge1xuICAgICAgICByZXR1cm4gbGVucyhwcm9wKGspLCBhc3NvYyhrKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBcImxpZnRzXCIgYSBmdW5jdGlvbiB0byBiZSB0aGUgc3BlY2lmaWVkIGFyaXR5LCBzbyB0aGF0IGl0IG1heSBcIm1hcCBvdmVyXCIgdGhhdFxuICAgICAqIG1hbnkgbGlzdHMsIEZ1bmN0aW9ucyBvciBvdGhlciBvYmplY3RzIHRoYXQgc2F0aXNmeSB0aGUgW0ZhbnRhc3lMYW5kIEFwcGx5IHNwZWNdKGh0dHBzOi8vZ2l0aHViLmNvbS9mYW50YXN5bGFuZC9mYW50YXN5LWxhbmQjYXBwbHkpLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIE51bWJlciAtPiAoKi4uLiAtPiAqKSAtPiAoWypdLi4uIC0+IFsqXSlcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gbGlmdCBpbnRvIGhpZ2hlciBjb250ZXh0XG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBsaWZ0ZWQgZnVuY3Rpb24uXG4gICAgICogQHNlZSBSLmxpZnQsIFIuYXBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbWFkZDMgPSBSLmxpZnROKDMsIFIuY3VycnlOKDMsICguLi5hcmdzKSA9PiBSLnN1bShhcmdzKSkpO1xuICAgICAqICAgICAgbWFkZDMoWzEsMiwzXSwgWzEsMiwzXSwgWzFdKTsgLy89PiBbMywgNCwgNSwgNCwgNSwgNiwgNSwgNiwgN11cbiAgICAgKi9cbiAgICB2YXIgbGlmdE4gPSBfY3VycnkyKGZ1bmN0aW9uIGxpZnROKGFyaXR5LCBmbikge1xuICAgICAgICB2YXIgbGlmdGVkID0gY3VycnlOKGFyaXR5LCBmbik7XG4gICAgICAgIHJldHVybiBjdXJyeU4oYXJpdHksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfcmVkdWNlKGFwLCBtYXAobGlmdGVkLCBhcmd1bWVudHNbMF0pLCBfc2xpY2UoYXJndW1lbnRzLCAxKSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbWVhbiBvZiB0aGUgZ2l2ZW4gbGlzdCBvZiBudW1iZXJzLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIFtOdW1iZXJdIC0+IE51bWJlclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3RcbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5tZWFuKFsyLCA3LCA5XSk7IC8vPT4gNlxuICAgICAqICAgICAgUi5tZWFuKFtdKTsgLy89PiBOYU5cbiAgICAgKi9cbiAgICB2YXIgbWVhbiA9IF9jdXJyeTEoZnVuY3Rpb24gbWVhbihsaXN0KSB7XG4gICAgICAgIHJldHVybiBzdW0obGlzdCkgLyBsaXN0Lmxlbmd0aDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG1lZGlhbiBvZiB0aGUgZ2l2ZW4gbGlzdCBvZiBudW1iZXJzLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIFtOdW1iZXJdIC0+IE51bWJlclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3RcbiAgICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5tZWRpYW4oWzIsIDksIDddKTsgLy89PiA3XG4gICAgICogICAgICBSLm1lZGlhbihbNywgMiwgMTAsIDldKTsgLy89PiA4XG4gICAgICogICAgICBSLm1lZGlhbihbXSk7IC8vPT4gTmFOXG4gICAgICovXG4gICAgdmFyIG1lZGlhbiA9IF9jdXJyeTEoZnVuY3Rpb24gbWVkaWFuKGxpc3QpIHtcbiAgICAgICAgdmFyIGxlbiA9IGxpc3QubGVuZ3RoO1xuICAgICAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHZhciB3aWR0aCA9IDIgLSBsZW4gJSAyO1xuICAgICAgICB2YXIgaWR4ID0gKGxlbiAtIHdpZHRoKSAvIDI7XG4gICAgICAgIHJldHVybiBtZWFuKF9zbGljZShsaXN0KS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gYSA8IGIgPyAtMSA6IGEgPiBiID8gMSA6IDA7XG4gICAgICAgIH0pLnNsaWNlKGlkeCwgaWR4ICsgd2lkdGgpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgcHJlZGljYXRlIGFuZCBhIGxpc3Qgb3Igb3RoZXIgXCJmaWx0ZXJhYmxlXCIgb2JqZWN0IGFuZCByZXR1cm5zIHRoZVxuICAgICAqIHBhaXIgb2YgZmlsdGVyYWJsZSBvYmplY3RzIG9mIHRoZSBzYW1lIHR5cGUgb2YgZWxlbWVudHMgd2hpY2ggZG8gYW5kIGRvIG5vdFxuICAgICAqIHNhdGlzZnksIHRoZSBwcmVkaWNhdGUsIHJlc3BlY3RpdmVseS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS40XG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIEZpbHRlcmFibGUgZiA9PiAoYSAtPiBCb29sZWFuKSAtPiBmIGEgLT4gW2YgYSwgZiBhXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWQgQSBwcmVkaWNhdGUgdG8gZGV0ZXJtaW5lIHdoaWNoIHNpZGUgdGhlIGVsZW1lbnQgYmVsb25ncyB0by5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBmaWx0ZXJhYmxlIHRoZSBsaXN0IChvciBvdGhlciBmaWx0ZXJhYmxlKSB0byBwYXJ0aXRpb24uXG4gICAgICogQHJldHVybiB7QXJyYXl9IEFuIGFycmF5LCBjb250YWluaW5nIGZpcnN0IHRoZSBzdWJzZXQgb2YgZWxlbWVudHMgdGhhdCBzYXRpc2Z5IHRoZVxuICAgICAqICAgICAgICAgcHJlZGljYXRlLCBhbmQgc2Vjb25kIHRoZSBzdWJzZXQgb2YgZWxlbWVudHMgdGhhdCBkbyBub3Qgc2F0aXNmeS5cbiAgICAgKiBAc2VlIFIuZmlsdGVyLCBSLnJlamVjdFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIucGFydGl0aW9uKFIuY29udGFpbnMoJ3MnKSwgWydzc3MnLCAndHR0JywgJ2ZvbycsICdiYXJzJ10pO1xuICAgICAqICAgICAgLy8gPT4gWyBbICdzc3MnLCAnYmFycycgXSwgIFsgJ3R0dCcsICdmb28nIF0gXVxuICAgICAqXG4gICAgICogICAgICBSLnBhcnRpdGlvbihSLmNvbnRhaW5zKCdzJyksIHsgYTogJ3NzcycsIGI6ICd0dHQnLCBmb286ICdiYXJzJyB9KTtcbiAgICAgKiAgICAgIC8vID0+IFsgeyBhOiAnc3NzJywgZm9vOiAnYmFycycgfSwgeyBiOiAndHR0JyB9ICBdXG4gICAgICovXG4gICAgdmFyIHBhcnRpdGlvbiA9IGp1eHQoW1xuICAgICAgICBmaWx0ZXIsXG4gICAgICAgIHJlamVjdFxuICAgIF0pO1xuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgbGVmdC10by1yaWdodCBmdW5jdGlvbiBjb21wb3NpdGlvbi4gVGhlIGxlZnRtb3N0IGZ1bmN0aW9uIG1heSBoYXZlXG4gICAgICogYW55IGFyaXR5OyB0aGUgcmVtYWluaW5nIGZ1bmN0aW9ucyBtdXN0IGJlIHVuYXJ5LlxuICAgICAqXG4gICAgICogSW4gc29tZSBsaWJyYXJpZXMgdGhpcyBmdW5jdGlvbiBpcyBuYW1lZCBgc2VxdWVuY2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoZSByZXN1bHQgb2YgcGlwZSBpcyBub3QgYXV0b21hdGljYWxseSBjdXJyaWVkLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgoKGEsIGIsIC4uLiwgbikgLT4gbyksIChvIC0+IHApLCAuLi4sICh4IC0+IHkpLCAoeSAtPiB6KSkgLT4gKChhLCBiLCAuLi4sIG4pIC0+IHopXG4gICAgICogQHBhcmFtIHsuLi5GdW5jdGlvbn0gZnVuY3Rpb25zXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259XG4gICAgICogQHNlZSBSLmNvbXBvc2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZiA9IFIucGlwZShNYXRoLnBvdywgUi5uZWdhdGUsIFIuaW5jKTtcbiAgICAgKlxuICAgICAqICAgICAgZigzLCA0KTsgLy8gLSgzXjQpICsgMVxuICAgICAqL1xuICAgIHZhciBwaXBlID0gZnVuY3Rpb24gcGlwZSgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncGlwZSByZXF1aXJlcyBhdCBsZWFzdCBvbmUgYXJndW1lbnQnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX2FyaXR5KGFyZ3VtZW50c1swXS5sZW5ndGgsIHJlZHVjZShfcGlwZSwgYXJndW1lbnRzWzBdLCB0YWlsKGFyZ3VtZW50cykpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgbGVmdC10by1yaWdodCBjb21wb3NpdGlvbiBvZiBvbmUgb3IgbW9yZSBQcm9taXNlLXJldHVybmluZ1xuICAgICAqIGZ1bmN0aW9ucy4gVGhlIGxlZnRtb3N0IGZ1bmN0aW9uIG1heSBoYXZlIGFueSBhcml0eTsgdGhlIHJlbWFpbmluZyBmdW5jdGlvbnNcbiAgICAgKiBtdXN0IGJlIHVuYXJ5LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoKGEgLT4gUHJvbWlzZSBiKSwgKGIgLT4gUHJvbWlzZSBjKSwgLi4uLCAoeSAtPiBQcm9taXNlIHopKSAtPiAoYSAtPiBQcm9taXNlIHopXG4gICAgICogQHBhcmFtIHsuLi5GdW5jdGlvbn0gZnVuY3Rpb25zXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259XG4gICAgICogQHNlZSBSLmNvbXBvc2VQXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgLy8gIGZvbGxvd2Vyc0ZvclVzZXIgOjogU3RyaW5nIC0+IFByb21pc2UgW1VzZXJdXG4gICAgICogICAgICB2YXIgZm9sbG93ZXJzRm9yVXNlciA9IFIucGlwZVAoZGIuZ2V0VXNlckJ5SWQsIGRiLmdldEZvbGxvd2Vycyk7XG4gICAgICovXG4gICAgdmFyIHBpcGVQID0gZnVuY3Rpb24gcGlwZVAoKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BpcGVQIHJlcXVpcmVzIGF0IGxlYXN0IG9uZSBhcmd1bWVudCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfYXJpdHkoYXJndW1lbnRzWzBdLmxlbmd0aCwgcmVkdWNlKF9waXBlUCwgYXJndW1lbnRzWzBdLCB0YWlsKGFyZ3VtZW50cykpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTXVsdGlwbGllcyB0b2dldGhlciBhbGwgdGhlIGVsZW1lbnRzIG9mIGEgbGlzdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAc2lnIFtOdW1iZXJdIC0+IE51bWJlclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgQW4gYXJyYXkgb2YgbnVtYmVyc1xuICAgICAqIEByZXR1cm4ge051bWJlcn0gVGhlIHByb2R1Y3Qgb2YgYWxsIHRoZSBudW1iZXJzIGluIHRoZSBsaXN0LlxuICAgICAqIEBzZWUgUi5yZWR1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnByb2R1Y3QoWzIsNCw2LDgsMTAwLDFdKTsgLy89PiAzODQwMFxuICAgICAqL1xuICAgIHZhciBwcm9kdWN0ID0gcmVkdWNlKG11bHRpcGx5LCAxKTtcblxuICAgIC8qKlxuICAgICAqIFRyYW5zZm9ybXMgYSBbVHJhdmVyc2FibGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9mYW50YXN5bGFuZC9mYW50YXN5LWxhbmQjdHJhdmVyc2FibGUpXG4gICAgICogb2YgW0FwcGxpY2F0aXZlXShodHRwczovL2dpdGh1Yi5jb20vZmFudGFzeWxhbmQvZmFudGFzeS1sYW5kI2FwcGxpY2F0aXZlKSBpbnRvIGFuXG4gICAgICogQXBwbGljYXRpdmUgb2YgVHJhdmVyc2FibGUuXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgc2VxdWVuY2VgIG1ldGhvZCBvZiB0aGUgc2Vjb25kIGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xOS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIChBcHBsaWNhdGl2ZSBmLCBUcmF2ZXJzYWJsZSB0KSA9PiAoYSAtPiBmIGEpIC0+IHQgKGYgYSkgLT4gZiAodCBhKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9mXG4gICAgICogQHBhcmFtIHsqfSB0cmF2ZXJzYWJsZVxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHNlZSBSLnRyYXZlcnNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5zZXF1ZW5jZShNYXliZS5vZiwgW0p1c3QoMSksIEp1c3QoMiksIEp1c3QoMyldKTsgICAvLz0+IEp1c3QoWzEsIDIsIDNdKVxuICAgICAqICAgICAgUi5zZXF1ZW5jZShNYXliZS5vZiwgW0p1c3QoMSksIEp1c3QoMiksIE5vdGhpbmcoKV0pOyAvLz0+IE5vdGhpbmcoKVxuICAgICAqXG4gICAgICogICAgICBSLnNlcXVlbmNlKFIub2YsIEp1c3QoWzEsIDIsIDNdKSk7IC8vPT4gW0p1c3QoMSksIEp1c3QoMiksIEp1c3QoMyldXG4gICAgICogICAgICBSLnNlcXVlbmNlKFIub2YsIE5vdGhpbmcoKSk7ICAgICAgIC8vPT4gW05vdGhpbmcoKV1cbiAgICAgKi9cbiAgICB2YXIgc2VxdWVuY2UgPSBfY3VycnkyKGZ1bmN0aW9uIHNlcXVlbmNlKG9mLCB0cmF2ZXJzYWJsZSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHRyYXZlcnNhYmxlLnNlcXVlbmNlID09PSAnZnVuY3Rpb24nID8gdHJhdmVyc2FibGUuc2VxdWVuY2Uob2YpIDogcmVkdWNlUmlnaHQoZnVuY3Rpb24gKGFjYywgeCkge1xuICAgICAgICAgICAgcmV0dXJuIGFwKG1hcChwcmVwZW5kLCB4KSwgYWNjKTtcbiAgICAgICAgfSwgb2YoW10pLCB0cmF2ZXJzYWJsZSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBNYXBzIGFuIFtBcHBsaWNhdGl2ZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZhbnRhc3lsYW5kL2ZhbnRhc3ktbGFuZCNhcHBsaWNhdGl2ZSktcmV0dXJuaW5nXG4gICAgICogZnVuY3Rpb24gb3ZlciBhIFtUcmF2ZXJzYWJsZV0oaHR0cHM6Ly9naXRodWIuY29tL2ZhbnRhc3lsYW5kL2ZhbnRhc3ktbGFuZCN0cmF2ZXJzYWJsZSksXG4gICAgICogdGhlbiB1c2VzIFtgc2VxdWVuY2VgXSgjc2VxdWVuY2UpIHRvIHRyYW5zZm9ybSB0aGUgcmVzdWx0aW5nIFRyYXZlcnNhYmxlIG9mIEFwcGxpY2F0aXZlXG4gICAgICogaW50byBhbiBBcHBsaWNhdGl2ZSBvZiBUcmF2ZXJzYWJsZS5cbiAgICAgKlxuICAgICAqIERpc3BhdGNoZXMgdG8gdGhlIGBzZXF1ZW5jZWAgbWV0aG9kIG9mIHRoZSB0aGlyZCBhcmd1bWVudCwgaWYgcHJlc2VudC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTkuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyAoQXBwbGljYXRpdmUgZiwgVHJhdmVyc2FibGUgdCkgPT4gKGEgLT4gZiBhKSAtPiAoYSAtPiBmIGIpIC0+IHQgYSAtPiBmICh0IGIpXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb2ZcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmXG4gICAgICogQHBhcmFtIHsqfSB0cmF2ZXJzYWJsZVxuICAgICAqIEByZXR1cm4geyp9XG4gICAgICogQHNlZSBSLnNlcXVlbmNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgLy8gUmV0dXJucyBgTm90aGluZ2AgaWYgdGhlIGdpdmVuIGRpdmlzb3IgaXMgYDBgXG4gICAgICogICAgICBzYWZlRGl2ID0gbiA9PiBkID0+IGQgPT09IDAgPyBOb3RoaW5nKCkgOiBKdXN0KG4gLyBkKVxuICAgICAqXG4gICAgICogICAgICBSLnRyYXZlcnNlKE1heWJlLm9mLCBzYWZlRGl2KDEwKSwgWzIsIDQsIDVdKTsgLy89PiBKdXN0KFs1LCAyLjUsIDJdKVxuICAgICAqICAgICAgUi50cmF2ZXJzZShNYXliZS5vZiwgc2FmZURpdigxMCksIFsyLCAwLCA1XSk7IC8vPT4gTm90aGluZ1xuICAgICAqL1xuICAgIHZhciB0cmF2ZXJzZSA9IF9jdXJyeTMoZnVuY3Rpb24gdHJhdmVyc2Uob2YsIGYsIHRyYXZlcnNhYmxlKSB7XG4gICAgICAgIHJldHVybiBzZXF1ZW5jZShvZiwgbWFwKGYsIHRyYXZlcnNhYmxlKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBTaG9ydGhhbmQgZm9yIGBSLmNoYWluKFIuaWRlbnRpdHkpYCwgd2hpY2ggcmVtb3ZlcyBvbmUgbGV2ZWwgb2YgbmVzdGluZyBmcm9tXG4gICAgICogYW55IFtDaGFpbl0oaHR0cHM6Ly9naXRodWIuY29tL2ZhbnRhc3lsYW5kL2ZhbnRhc3ktbGFuZCNjaGFpbikuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjMuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBDaGFpbiBjID0+IGMgKGMgYSkgLT4gYyBhXG4gICAgICogQHBhcmFtIHsqfSBsaXN0XG4gICAgICogQHJldHVybiB7Kn1cbiAgICAgKiBAc2VlIFIuZmxhdHRlbiwgUi5jaGFpblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudW5uZXN0KFsxLCBbMl0sIFtbM11dXSk7IC8vPT4gWzEsIDIsIFszXV1cbiAgICAgKiAgICAgIFIudW5uZXN0KFtbMSwgMl0sIFszLCA0XSwgWzUsIDZdXSk7IC8vPT4gWzEsIDIsIDMsIDQsIDUsIDZdXG4gICAgICovXG4gICAgdmFyIHVubmVzdCA9IGNoYWluKF9pZGVudGl0eSk7XG5cbiAgICB2YXIgX2NvbnRhaW5zID0gZnVuY3Rpb24gX2NvbnRhaW5zKGEsIGxpc3QpIHtcbiAgICAgICAgcmV0dXJuIF9pbmRleE9mKGxpc3QsIGEsIDApID49IDA7XG4gICAgfTtcblxuICAgIC8vICBtYXBQYWlycyA6OiAoT2JqZWN0LCBbU3RyaW5nXSkgLT4gW1N0cmluZ11cbiAgICB2YXIgX3RvU3RyaW5nID0gZnVuY3Rpb24gX3RvU3RyaW5nKHgsIHNlZW4pIHtcbiAgICAgICAgdmFyIHJlY3VyID0gZnVuY3Rpb24gcmVjdXIoeSkge1xuICAgICAgICAgICAgdmFyIHhzID0gc2Vlbi5jb25jYXQoW3hdKTtcbiAgICAgICAgICAgIHJldHVybiBfY29udGFpbnMoeSwgeHMpID8gJzxDaXJjdWxhcj4nIDogX3RvU3RyaW5nKHksIHhzKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gIG1hcFBhaXJzIDo6IChPYmplY3QsIFtTdHJpbmddKSAtPiBbU3RyaW5nXVxuICAgICAgICB2YXIgbWFwUGFpcnMgPSBmdW5jdGlvbiAob2JqLCBrZXlzKSB7XG4gICAgICAgICAgICByZXR1cm4gX21hcChmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBfcXVvdGUoaykgKyAnOiAnICsgcmVjdXIob2JqW2tdKTtcbiAgICAgICAgICAgIH0sIGtleXMuc2xpY2UoKS5zb3J0KCkpO1xuICAgICAgICB9O1xuICAgICAgICBzd2l0Y2ggKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSkge1xuICAgICAgICBjYXNlICdbb2JqZWN0IEFyZ3VtZW50c10nOlxuICAgICAgICAgICAgcmV0dXJuICcoZnVuY3Rpb24oKSB7IHJldHVybiBhcmd1bWVudHM7IH0oJyArIF9tYXAocmVjdXIsIHgpLmpvaW4oJywgJykgKyAnKSknO1xuICAgICAgICBjYXNlICdbb2JqZWN0IEFycmF5XSc6XG4gICAgICAgICAgICByZXR1cm4gJ1snICsgX21hcChyZWN1ciwgeCkuY29uY2F0KG1hcFBhaXJzKHgsIHJlamVjdChmdW5jdGlvbiAoaykge1xuICAgICAgICAgICAgICAgIHJldHVybiAvXlxcZCskLy50ZXN0KGspO1xuICAgICAgICAgICAgfSwga2V5cyh4KSkpKS5qb2luKCcsICcpICsgJ10nO1xuICAgICAgICBjYXNlICdbb2JqZWN0IEJvb2xlYW5dJzpcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgPyAnbmV3IEJvb2xlYW4oJyArIHJlY3VyKHgudmFsdWVPZigpKSArICcpJyA6IHgudG9TdHJpbmcoKTtcbiAgICAgICAgY2FzZSAnW29iamVjdCBEYXRlXSc6XG4gICAgICAgICAgICByZXR1cm4gJ25ldyBEYXRlKCcgKyAoaXNOYU4oeC52YWx1ZU9mKCkpID8gcmVjdXIoTmFOKSA6IF9xdW90ZShfdG9JU09TdHJpbmcoeCkpKSArICcpJztcbiAgICAgICAgY2FzZSAnW29iamVjdCBOdWxsXSc6XG4gICAgICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgICAgICBjYXNlICdbb2JqZWN0IE51bWJlcl0nOlxuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyA/ICduZXcgTnVtYmVyKCcgKyByZWN1cih4LnZhbHVlT2YoKSkgKyAnKScgOiAxIC8geCA9PT0gLUluZmluaXR5ID8gJy0wJyA6IHgudG9TdHJpbmcoMTApO1xuICAgICAgICBjYXNlICdbb2JqZWN0IFN0cmluZ10nOlxuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyA/ICduZXcgU3RyaW5nKCcgKyByZWN1cih4LnZhbHVlT2YoKSkgKyAnKScgOiBfcXVvdGUoeCk7XG4gICAgICAgIGNhc2UgJ1tvYmplY3QgVW5kZWZpbmVkXSc6XG4gICAgICAgICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBpZiAodHlwZW9mIHgudG9TdHJpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVwciA9IHgudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICBpZiAocmVwciAhPT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcHI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICd7JyArIG1hcFBhaXJzKHgsIGtleXMoeCkpLmpvaW4oJywgJykgKyAnfSc7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgcmlnaHQtdG8tbGVmdCBmdW5jdGlvbiBjb21wb3NpdGlvbi4gVGhlIHJpZ2h0bW9zdCBmdW5jdGlvbiBtYXkgaGF2ZVxuICAgICAqIGFueSBhcml0eTsgdGhlIHJlbWFpbmluZyBmdW5jdGlvbnMgbXVzdCBiZSB1bmFyeS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGUgcmVzdWx0IG9mIGNvbXBvc2UgaXMgbm90IGF1dG9tYXRpY2FsbHkgY3VycmllZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoKHkgLT4geiksICh4IC0+IHkpLCAuLi4sIChvIC0+IHApLCAoKGEsIGIsIC4uLiwgbikgLT4gbykpIC0+ICgoYSwgYiwgLi4uLCBuKSAtPiB6KVxuICAgICAqIEBwYXJhbSB7Li4uRnVuY3Rpb259IGZ1bmN0aW9uc1xuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICAgICAqIEBzZWUgUi5waXBlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGYgPSBSLmNvbXBvc2UoUi5pbmMsIFIubmVnYXRlLCBNYXRoLnBvdyk7XG4gICAgICpcbiAgICAgKiAgICAgIGYoMywgNCk7IC8vIC0oM140KSArIDFcbiAgICAgKi9cbiAgICB2YXIgY29tcG9zZSA9IGZ1bmN0aW9uIGNvbXBvc2UoKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbXBvc2UgcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50Jyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBpcGUuYXBwbHkodGhpcywgcmV2ZXJzZShhcmd1bWVudHMpKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcmlnaHQtdG8tbGVmdCBLbGVpc2xpIGNvbXBvc2l0aW9uIG9mIHRoZSBwcm92aWRlZCBmdW5jdGlvbnMsXG4gICAgICogZWFjaCBvZiB3aGljaCBtdXN0IHJldHVybiBhIHZhbHVlIG9mIGEgdHlwZSBzdXBwb3J0ZWQgYnkgW2BjaGFpbmBdKCNjaGFpbikuXG4gICAgICpcbiAgICAgKiBgUi5jb21wb3NlSyhoLCBnLCBmKWAgaXMgZXF1aXZhbGVudCB0byBgUi5jb21wb3NlKFIuY2hhaW4oaCksIFIuY2hhaW4oZyksIFIuY2hhaW4oZikpYC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTYuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgQ2hhaW4gbSA9PiAoKHkgLT4gbSB6KSwgKHggLT4gbSB5KSwgLi4uLCAoYSAtPiBtIGIpKSAtPiAobSBhIC0+IG0geilcbiAgICAgKiBAcGFyYW0gey4uLkZ1bmN0aW9ufVxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICAgICAqIEBzZWUgUi5waXBlS1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIC8vICBwYXJzZUpzb24gOjogU3RyaW5nIC0+IE1heWJlICpcbiAgICAgKiAgICAgIC8vICBnZXQgOjogU3RyaW5nIC0+IE9iamVjdCAtPiBNYXliZSAqXG4gICAgICpcbiAgICAgKiAgICAgIC8vICBnZXRTdGF0ZUNvZGUgOjogTWF5YmUgU3RyaW5nIC0+IE1heWJlIFN0cmluZ1xuICAgICAqICAgICAgdmFyIGdldFN0YXRlQ29kZSA9IFIuY29tcG9zZUsoXG4gICAgICogICAgICAgIFIuY29tcG9zZShNYXliZS5vZiwgUi50b1VwcGVyKSxcbiAgICAgKiAgICAgICAgZ2V0KCdzdGF0ZScpLFxuICAgICAqICAgICAgICBnZXQoJ2FkZHJlc3MnKSxcbiAgICAgKiAgICAgICAgZ2V0KCd1c2VyJyksXG4gICAgICogICAgICAgIHBhcnNlSnNvblxuICAgICAqICAgICAgKTtcbiAgICAgKlxuICAgICAqICAgICAgZ2V0U3RhdGVDb2RlKE1heWJlLm9mKCd7XCJ1c2VyXCI6e1wiYWRkcmVzc1wiOntcInN0YXRlXCI6XCJueVwifX19JykpO1xuICAgICAqICAgICAgLy89PiBKdXN0KCdOWScpXG4gICAgICogICAgICBnZXRTdGF0ZUNvZGUoTWF5YmUub2YoJ1tJbnZhbGlkIEpTT05dJykpO1xuICAgICAqICAgICAgLy89PiBOb3RoaW5nKClcbiAgICAgKi9cbiAgICB2YXIgY29tcG9zZUsgPSBmdW5jdGlvbiBjb21wb3NlSygpIHtcbiAgICAgICAgcmV0dXJuIGNvbXBvc2UuYXBwbHkodGhpcywgcHJlcGVuZChpZGVudGl0eSwgbWFwKGNoYWluLCBhcmd1bWVudHMpKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIHJpZ2h0LXRvLWxlZnQgY29tcG9zaXRpb24gb2Ygb25lIG9yIG1vcmUgUHJvbWlzZS1yZXR1cm5pbmdcbiAgICAgKiBmdW5jdGlvbnMuIFRoZSByaWdodG1vc3QgZnVuY3Rpb24gbWF5IGhhdmUgYW55IGFyaXR5OyB0aGUgcmVtYWluaW5nXG4gICAgICogZnVuY3Rpb25zIG11c3QgYmUgdW5hcnkuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEwLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgoeSAtPiBQcm9taXNlIHopLCAoeCAtPiBQcm9taXNlIHkpLCAuLi4sIChhIC0+IFByb21pc2UgYikpIC0+IChhIC0+IFByb21pc2UgeilcbiAgICAgKiBAcGFyYW0gey4uLkZ1bmN0aW9ufSBmdW5jdGlvbnNcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAgICAgKiBAc2VlIFIucGlwZVBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyAgZm9sbG93ZXJzRm9yVXNlciA6OiBTdHJpbmcgLT4gUHJvbWlzZSBbVXNlcl1cbiAgICAgKiAgICAgIHZhciBmb2xsb3dlcnNGb3JVc2VyID0gUi5jb21wb3NlUChkYi5nZXRGb2xsb3dlcnMsIGRiLmdldFVzZXJCeUlkKTtcbiAgICAgKi9cbiAgICB2YXIgY29tcG9zZVAgPSBmdW5jdGlvbiBjb21wb3NlUCgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY29tcG9zZVAgcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50Jyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBpcGVQLmFwcGx5KHRoaXMsIHJldmVyc2UoYXJndW1lbnRzKSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFdyYXBzIGEgY29uc3RydWN0b3IgZnVuY3Rpb24gaW5zaWRlIGEgY3VycmllZCBmdW5jdGlvbiB0aGF0IGNhbiBiZSBjYWxsZWRcbiAgICAgKiB3aXRoIHRoZSBzYW1lIGFyZ3VtZW50cyBhbmQgcmV0dXJucyB0aGUgc2FtZSB0eXBlLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgqIC0+IHsqfSkgLT4gKCogLT4geyp9KVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IEZuIFRoZSBjb25zdHJ1Y3RvciBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIHdyYXBwZWQsIGN1cnJpZWQgY29uc3RydWN0b3IgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgLy8gQ29uc3RydWN0b3IgZnVuY3Rpb25cbiAgICAgKiAgICAgIHZhciBXaWRnZXQgPSBjb25maWcgPT4ge1xuICAgICAqICAgICAgICAvLyAuLi5cbiAgICAgKiAgICAgIH07XG4gICAgICogICAgICBXaWRnZXQucHJvdG90eXBlID0ge1xuICAgICAqICAgICAgICAvLyAuLi5cbiAgICAgKiAgICAgIH07XG4gICAgICogICAgICB2YXIgYWxsQ29uZmlncyA9IFtcbiAgICAgKiAgICAgICAgLy8gLi4uXG4gICAgICogICAgICBdO1xuICAgICAqICAgICAgUi5tYXAoUi5jb25zdHJ1Y3QoV2lkZ2V0KSwgYWxsQ29uZmlncyk7IC8vIGEgbGlzdCBvZiBXaWRnZXRzXG4gICAgICovXG4gICAgdmFyIGNvbnN0cnVjdCA9IF9jdXJyeTEoZnVuY3Rpb24gY29uc3RydWN0KEZuKSB7XG4gICAgICAgIHJldHVybiBjb25zdHJ1Y3ROKEZuLmxlbmd0aCwgRm4pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHNwZWNpZmllZCB2YWx1ZSBpcyBlcXVhbCwgaW4gYFIuZXF1YWxzYCB0ZXJtcywgdG8gYXRcbiAgICAgKiBsZWFzdCBvbmUgZWxlbWVudCBvZiB0aGUgZ2l2ZW4gbGlzdDsgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBhIC0+IFthXSAtPiBCb29sZWFuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGEgVGhlIGl0ZW0gdG8gY29tcGFyZSBhZ2FpbnN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QgVGhlIGFycmF5IHRvIGNvbnNpZGVyLlxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgaXRlbSBpcyBpbiB0aGUgbGlzdCwgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICogQHNlZSBSLmFueVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuY29udGFpbnMoMywgWzEsIDIsIDNdKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLmNvbnRhaW5zKDQsIFsxLCAyLCAzXSk7IC8vPT4gZmFsc2VcbiAgICAgKiAgICAgIFIuY29udGFpbnMoWzQyXSwgW1s0Ml1dKTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIGNvbnRhaW5zID0gX2N1cnJ5MihfY29udGFpbnMpO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIHNldCAoaS5lLiBubyBkdXBsaWNhdGVzKSBvZiBhbGwgZWxlbWVudHMgaW4gdGhlIGZpcnN0IGxpc3Qgbm90XG4gICAgICogY29udGFpbmVkIGluIHRoZSBzZWNvbmQgbGlzdC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyBbKl0gLT4gWypdIC0+IFsqXVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QxIFRoZSBmaXJzdCBsaXN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QyIFRoZSBzZWNvbmQgbGlzdC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGVsZW1lbnRzIGluIGBsaXN0MWAgdGhhdCBhcmUgbm90IGluIGBsaXN0MmAuXG4gICAgICogQHNlZSBSLmRpZmZlcmVuY2VXaXRoLCBSLnN5bW1ldHJpY0RpZmZlcmVuY2UsIFIuc3ltbWV0cmljRGlmZmVyZW5jZVdpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLmRpZmZlcmVuY2UoWzEsMiwzLDRdLCBbNyw2LDUsNCwzXSk7IC8vPT4gWzEsMl1cbiAgICAgKiAgICAgIFIuZGlmZmVyZW5jZShbNyw2LDUsNCwzXSwgWzEsMiwzLDRdKTsgLy89PiBbNyw2LDVdXG4gICAgICovXG4gICAgdmFyIGRpZmZlcmVuY2UgPSBfY3VycnkyKGZ1bmN0aW9uIGRpZmZlcmVuY2UoZmlyc3QsIHNlY29uZCkge1xuICAgICAgICB2YXIgb3V0ID0gW107XG4gICAgICAgIHZhciBpZHggPSAwO1xuICAgICAgICB2YXIgZmlyc3RMZW4gPSBmaXJzdC5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpZHggPCBmaXJzdExlbikge1xuICAgICAgICAgICAgaWYgKCFfY29udGFpbnMoZmlyc3RbaWR4XSwgc2Vjb25kKSAmJiAhX2NvbnRhaW5zKGZpcnN0W2lkeF0sIG91dCkpIHtcbiAgICAgICAgICAgICAgICBvdXRbb3V0Lmxlbmd0aF0gPSBmaXJzdFtpZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWR4ICs9IDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgbGlzdCB3aXRob3V0IGFueSBjb25zZWN1dGl2ZWx5IHJlcGVhdGluZyBlbGVtZW50cy4gYFIuZXF1YWxzYFxuICAgICAqIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIGVxdWFsaXR5LlxuICAgICAqXG4gICAgICogRGlzcGF0Y2hlcyB0byB0aGUgYGRyb3BSZXBlYXRzYCBtZXRob2Qgb2YgdGhlIGZpcnN0IGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQWN0cyBhcyBhIHRyYW5zZHVjZXIgaWYgYSB0cmFuc2Zvcm1lciBpcyBnaXZlbiBpbiBsaXN0IHBvc2l0aW9uLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xNC4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gYGxpc3RgIHdpdGhvdXQgcmVwZWF0aW5nIGVsZW1lbnRzLlxuICAgICAqIEBzZWUgUi50cmFuc2R1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgIFIuZHJvcFJlcGVhdHMoWzEsIDEsIDEsIDIsIDMsIDQsIDQsIDIsIDJdKTsgLy89PiBbMSwgMiwgMywgNCwgMl1cbiAgICAgKi9cbiAgICB2YXIgZHJvcFJlcGVhdHMgPSBfY3VycnkxKF9kaXNwYXRjaGFibGUoJ2Ryb3BSZXBlYXRzJywgX3hkcm9wUmVwZWF0c1dpdGgoZXF1YWxzKSwgZHJvcFJlcGVhdHNXaXRoKGVxdWFscykpKTtcblxuICAgIC8qKlxuICAgICAqIFwibGlmdHNcIiBhIGZ1bmN0aW9uIG9mIGFyaXR5ID4gMSBzbyB0aGF0IGl0IG1heSBcIm1hcCBvdmVyXCIgYSBsaXN0LCBGdW5jdGlvbiBvciBvdGhlclxuICAgICAqIG9iamVjdCB0aGF0IHNhdGlzZmllcyB0aGUgW0ZhbnRhc3lMYW5kIEFwcGx5IHNwZWNdKGh0dHBzOi8vZ2l0aHViLmNvbS9mYW50YXN5bGFuZC9mYW50YXN5LWxhbmQjYXBwbHkpLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnICgqLi4uIC0+ICopIC0+IChbKl0uLi4gLT4gWypdKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBsaWZ0IGludG8gaGlnaGVyIGNvbnRleHRcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGxpZnRlZCBmdW5jdGlvbi5cbiAgICAgKiBAc2VlIFIubGlmdE5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgbWFkZDMgPSBSLmxpZnQoUi5jdXJyeSgoYSwgYiwgYykgPT4gYSArIGIgKyBjKSk7XG4gICAgICpcbiAgICAgKiAgICAgIG1hZGQzKFsxLDIsM10sIFsxLDIsM10sIFsxXSk7IC8vPT4gWzMsIDQsIDUsIDQsIDUsIDYsIDUsIDYsIDddXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBtYWRkNSA9IFIubGlmdChSLmN1cnJ5KChhLCBiLCBjLCBkLCBlKSA9PiBhICsgYiArIGMgKyBkICsgZSkpO1xuICAgICAqXG4gICAgICogICAgICBtYWRkNShbMSwyXSwgWzNdLCBbNCwgNV0sIFs2XSwgWzcsIDhdKTsgLy89PiBbMjEsIDIyLCAyMiwgMjMsIDIyLCAyMywgMjMsIDI0XVxuICAgICAqL1xuICAgIHZhciBsaWZ0ID0gX2N1cnJ5MShmdW5jdGlvbiBsaWZ0KGZuKSB7XG4gICAgICAgIHJldHVybiBsaWZ0Tihmbi5sZW5ndGgsIGZuKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBwYXJ0aWFsIGNvcHkgb2YgYW4gb2JqZWN0IG9taXR0aW5nIHRoZSBrZXlzIHNwZWNpZmllZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBzaWcgW1N0cmluZ10gLT4ge1N0cmluZzogKn0gLT4ge1N0cmluZzogKn1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBuYW1lcyBhbiBhcnJheSBvZiBTdHJpbmcgcHJvcGVydHkgbmFtZXMgdG8gb21pdCBmcm9tIHRoZSBuZXcgb2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGNvcHkgZnJvbVxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQSBuZXcgb2JqZWN0IHdpdGggcHJvcGVydGllcyBmcm9tIGBuYW1lc2Agbm90IG9uIGl0LlxuICAgICAqIEBzZWUgUi5waWNrXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi5vbWl0KFsnYScsICdkJ10sIHthOiAxLCBiOiAyLCBjOiAzLCBkOiA0fSk7IC8vPT4ge2I6IDIsIGM6IDN9XG4gICAgICovXG4gICAgdmFyIG9taXQgPSBfY3VycnkyKGZ1bmN0aW9uIG9taXQobmFtZXMsIG9iaikge1xuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZiAoIV9jb250YWlucyhwcm9wLCBuYW1lcykpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRbcHJvcF0gPSBvYmpbcHJvcF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxlZnQtdG8tcmlnaHQgS2xlaXNsaSBjb21wb3NpdGlvbiBvZiB0aGUgcHJvdmlkZWQgZnVuY3Rpb25zLFxuICAgICAqIGVhY2ggb2Ygd2hpY2ggbXVzdCByZXR1cm4gYSB2YWx1ZSBvZiBhIHR5cGUgc3VwcG9ydGVkIGJ5IFtgY2hhaW5gXSgjY2hhaW4pLlxuICAgICAqXG4gICAgICogYFIucGlwZUsoZiwgZywgaClgIGlzIGVxdWl2YWxlbnQgdG8gYFIucGlwZShSLmNoYWluKGYpLCBSLmNoYWluKGcpLCBSLmNoYWluKGgpKWAuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE2LjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAc2lnIENoYWluIG0gPT4gKChhIC0+IG0gYiksIChiIC0+IG0gYyksIC4uLiwgKHkgLT4gbSB6KSkgLT4gKG0gYSAtPiBtIHopXG4gICAgICogQHBhcmFtIHsuLi5GdW5jdGlvbn1cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAgICAgKiBAc2VlIFIuY29tcG9zZUtcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICAvLyAgcGFyc2VKc29uIDo6IFN0cmluZyAtPiBNYXliZSAqXG4gICAgICogICAgICAvLyAgZ2V0IDo6IFN0cmluZyAtPiBPYmplY3QgLT4gTWF5YmUgKlxuICAgICAqXG4gICAgICogICAgICAvLyAgZ2V0U3RhdGVDb2RlIDo6IE1heWJlIFN0cmluZyAtPiBNYXliZSBTdHJpbmdcbiAgICAgKiAgICAgIHZhciBnZXRTdGF0ZUNvZGUgPSBSLnBpcGVLKFxuICAgICAqICAgICAgICBwYXJzZUpzb24sXG4gICAgICogICAgICAgIGdldCgndXNlcicpLFxuICAgICAqICAgICAgICBnZXQoJ2FkZHJlc3MnKSxcbiAgICAgKiAgICAgICAgZ2V0KCdzdGF0ZScpLFxuICAgICAqICAgICAgICBSLmNvbXBvc2UoTWF5YmUub2YsIFIudG9VcHBlcilcbiAgICAgKiAgICAgICk7XG4gICAgICpcbiAgICAgKiAgICAgIGdldFN0YXRlQ29kZShNYXliZS5vZigne1widXNlclwiOntcImFkZHJlc3NcIjp7XCJzdGF0ZVwiOlwibnlcIn19fScpKTtcbiAgICAgKiAgICAgIC8vPT4gSnVzdCgnTlknKVxuICAgICAqICAgICAgZ2V0U3RhdGVDb2RlKE1heWJlLm9mKCdbSW52YWxpZCBKU09OXScpKTtcbiAgICAgKiAgICAgIC8vPT4gTm90aGluZygpXG4gICAgICovXG4gICAgdmFyIHBpcGVLID0gZnVuY3Rpb24gcGlwZUsoKSB7XG4gICAgICAgIHJldHVybiBjb21wb3NlSy5hcHBseSh0aGlzLCByZXZlcnNlKGFyZ3VtZW50cykpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIHZhbHVlLiBgZXZhbGAnaW5nIHRoZSBvdXRwdXRcbiAgICAgKiBzaG91bGQgcmVzdWx0IGluIGEgdmFsdWUgZXF1aXZhbGVudCB0byB0aGUgaW5wdXQgdmFsdWUuIE1hbnkgb2YgdGhlIGJ1aWx0LWluXG4gICAgICogYHRvU3RyaW5nYCBtZXRob2RzIGRvIG5vdCBzYXRpc2Z5IHRoaXMgcmVxdWlyZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYW4gYFtvYmplY3QgT2JqZWN0XWAgd2l0aCBhIGB0b1N0cmluZ2AgbWV0aG9kIG90aGVyXG4gICAgICogdGhhbiBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AsIHRoaXMgbWV0aG9kIGlzIGludm9rZWQgd2l0aCBubyBhcmd1bWVudHNcbiAgICAgKiB0byBwcm9kdWNlIHRoZSByZXR1cm4gdmFsdWUuIFRoaXMgbWVhbnMgdXNlci1kZWZpbmVkIGNvbnN0cnVjdG9yIGZ1bmN0aW9uc1xuICAgICAqIGNhbiBwcm92aWRlIGEgc3VpdGFibGUgYHRvU3RyaW5nYCBtZXRob2QuIEZvciBleGFtcGxlOlxuICAgICAqXG4gICAgICogICAgIGZ1bmN0aW9uIFBvaW50KHgsIHkpIHtcbiAgICAgKiAgICAgICB0aGlzLnggPSB4O1xuICAgICAqICAgICAgIHRoaXMueSA9IHk7XG4gICAgICogICAgIH1cbiAgICAgKlxuICAgICAqICAgICBQb2ludC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgKiAgICAgICByZXR1cm4gJ25ldyBQb2ludCgnICsgdGhpcy54ICsgJywgJyArIHRoaXMueSArICcpJztcbiAgICAgKiAgICAgfTtcbiAgICAgKlxuICAgICAqICAgICBSLnRvU3RyaW5nKG5ldyBQb2ludCgxLCAyKSk7IC8vPT4gJ25ldyBQb2ludCgxLCAyKSdcbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAc2lnICogLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWxcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi50b1N0cmluZyg0Mik7IC8vPT4gJzQyJ1xuICAgICAqICAgICAgUi50b1N0cmluZygnYWJjJyk7IC8vPT4gJ1wiYWJjXCInXG4gICAgICogICAgICBSLnRvU3RyaW5nKFsxLCAyLCAzXSk7IC8vPT4gJ1sxLCAyLCAzXSdcbiAgICAgKiAgICAgIFIudG9TdHJpbmcoe2ZvbzogMSwgYmFyOiAyLCBiYXo6IDN9KTsgLy89PiAne1wiYmFyXCI6IDIsIFwiYmF6XCI6IDMsIFwiZm9vXCI6IDF9J1xuICAgICAqICAgICAgUi50b1N0cmluZyhuZXcgRGF0ZSgnMjAwMS0wMi0wM1QwNDowNTowNlonKSk7IC8vPT4gJ25ldyBEYXRlKFwiMjAwMS0wMi0wM1QwNDowNTowNi4wMDBaXCIpJ1xuICAgICAqL1xuICAgIHZhciB0b1N0cmluZyA9IF9jdXJyeTEoZnVuY3Rpb24gdG9TdHJpbmcodmFsKSB7XG4gICAgICAgIHJldHVybiBfdG9TdHJpbmcodmFsLCBbXSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IGxpc3Qgd2l0aG91dCB2YWx1ZXMgaW4gdGhlIGZpcnN0IGFyZ3VtZW50LlxuICAgICAqIGBSLmVxdWFsc2AgaXMgdXNlZCB0byBkZXRlcm1pbmUgZXF1YWxpdHkuXG4gICAgICpcbiAgICAgKiBBY3RzIGFzIGEgdHJhbnNkdWNlciBpZiBhIHRyYW5zZm9ybWVyIGlzIGdpdmVuIGluIGxpc3QgcG9zaXRpb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgW2FdIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MSBUaGUgdmFsdWVzIHRvIGJlIHJlbW92ZWQgZnJvbSBgbGlzdDJgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QyIFRoZSBhcnJheSB0byByZW1vdmUgdmFsdWVzIGZyb20uXG4gICAgICogQHJldHVybiB7QXJyYXl9IFRoZSBuZXcgYXJyYXkgd2l0aG91dCB2YWx1ZXMgaW4gYGxpc3QxYC5cbiAgICAgKiBAc2VlIFIudHJhbnNkdWNlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi53aXRob3V0KFsxLCAyXSwgWzEsIDIsIDEsIDMsIDRdKTsgLy89PiBbMywgNF1cbiAgICAgKi9cbiAgICB2YXIgd2l0aG91dCA9IF9jdXJyeTIoZnVuY3Rpb24gKHhzLCBsaXN0KSB7XG4gICAgICAgIHJldHVybiByZWplY3QoZmxpcChfY29udGFpbnMpKHhzKSwgbGlzdCk7XG4gICAgfSk7XG5cbiAgICAvLyBBIHNpbXBsZSBTZXQgdHlwZSB0aGF0IGhvbm91cnMgUi5lcXVhbHMgc2VtYW50aWNzXG4gICAgLyogZ2xvYmFscyBTZXQgKi9cbiAgICAvLyB1bnRpbCB3ZSBmaWd1cmUgb3V0IHdoeSBqc2RvYyBjaG9rZXMgb24gdGhpc1xuICAgIC8vIEBwYXJhbSBpdGVtIFRoZSBpdGVtIHRvIGFkZCB0byB0aGUgU2V0XG4gICAgLy8gQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgdGhlIGl0ZW0gZGlkIG5vdCBleGlzdCBwcmlvciwgb3RoZXJ3aXNlIGZhbHNlXG4gICAgLy9cbiAgICAvL1xuICAgIC8vIEBwYXJhbSBpdGVtIFRoZSBpdGVtIHRvIGNoZWNrIGZvciBleGlzdGVuY2UgaW4gdGhlIFNldFxuICAgIC8vIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSBpdGVtIGV4aXN0cyBpbiB0aGUgU2V0LCBvdGhlcndpc2UgZmFsc2VcbiAgICAvL1xuICAgIC8vXG4gICAgLy8gQ29tYmluZXMgdGhlIGxvZ2ljIGZvciBjaGVja2luZyB3aGV0aGVyIGFuIGl0ZW0gaXMgYSBtZW1iZXIgb2YgdGhlIHNldCBhbmRcbiAgICAvLyBmb3IgYWRkaW5nIGEgbmV3IGl0ZW0gdG8gdGhlIHNldC5cbiAgICAvL1xuICAgIC8vIEBwYXJhbSBpdGVtICAgICAgIFRoZSBpdGVtIHRvIGNoZWNrIG9yIGFkZCB0byB0aGUgU2V0IGluc3RhbmNlLlxuICAgIC8vIEBwYXJhbSBzaG91bGRBZGQgIElmIHRydWUsIHRoZSBpdGVtIHdpbGwgYmUgYWRkZWQgdG8gdGhlIHNldCBpZiBpdCBkb2Vzbid0XG4gICAgLy8gICAgICAgICAgICAgICAgICAgYWxyZWFkeSBleGlzdC5cbiAgICAvLyBAcGFyYW0gc2V0ICAgICAgICBUaGUgc2V0IGluc3RhbmNlIHRvIGNoZWNrIG9yIGFkZCB0by5cbiAgICAvLyBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHRoZSBpdGVtIGFscmVhZHkgZXhpc3RlZCwgb3RoZXJ3aXNlIGZhbHNlLlxuICAgIC8vXG4gICAgLy8gZGlzdGluZ3Vpc2ggYmV0d2VlbiArMCBhbmQgLTBcbiAgICAvLyB0aGVzZSB0eXBlcyBjYW4gYWxsIHV0aWxpc2UgdGhlIG5hdGl2ZSBTZXRcbiAgICAvLyBzZXQuX2l0ZW1zWydib29sZWFuJ10gaG9sZHMgYSB0d28gZWxlbWVudCBhcnJheVxuICAgIC8vIHJlcHJlc2VudGluZyBbIGZhbHNlRXhpc3RzLCB0cnVlRXhpc3RzIF1cbiAgICAvLyBjb21wYXJlIGZ1bmN0aW9ucyBmb3IgcmVmZXJlbmNlIGVxdWFsaXR5XG4gICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIC8vIHJlZHVjZSB0aGUgc2VhcmNoIHNpemUgb2YgaGV0ZXJvZ2VuZW91cyBzZXRzIGJ5IGNyZWF0aW5nIGJ1Y2tldHNcbiAgICAvLyBmb3IgZWFjaCB0eXBlLlxuICAgIC8vIHNjYW4gdGhyb3VnaCBhbGwgcHJldmlvdXNseSBhcHBsaWVkIGl0ZW1zXG4gICAgdmFyIF9TZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIF9TZXQoKSB7XG4gICAgICAgICAgICAvKiBnbG9iYWxzIFNldCAqL1xuICAgICAgICAgICAgdGhpcy5fbmF0aXZlU2V0ID0gdHlwZW9mIFNldCA9PT0gJ2Z1bmN0aW9uJyA/IG5ldyBTZXQoKSA6IG51bGw7XG4gICAgICAgICAgICB0aGlzLl9pdGVtcyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIC8vIHVudGlsIHdlIGZpZ3VyZSBvdXQgd2h5IGpzZG9jIGNob2tlcyBvbiB0aGlzXG4gICAgICAgIC8vIEBwYXJhbSBpdGVtIFRoZSBpdGVtIHRvIGFkZCB0byB0aGUgU2V0XG4gICAgICAgIC8vIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSBpdGVtIGRpZCBub3QgZXhpc3QgcHJpb3IsIG90aGVyd2lzZSBmYWxzZVxuICAgICAgICAvL1xuICAgICAgICBfU2V0LnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgcmV0dXJuICFoYXNPckFkZChpdGVtLCB0cnVlLCB0aGlzKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy9cbiAgICAgICAgLy8gQHBhcmFtIGl0ZW0gVGhlIGl0ZW0gdG8gY2hlY2sgZm9yIGV4aXN0ZW5jZSBpbiB0aGUgU2V0XG4gICAgICAgIC8vIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSBpdGVtIGV4aXN0cyBpbiB0aGUgU2V0LCBvdGhlcndpc2UgZmFsc2VcbiAgICAgICAgLy9cbiAgICAgICAgX1NldC5wcm90b3R5cGUuaGFzID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgIHJldHVybiBoYXNPckFkZChpdGVtLCBmYWxzZSwgdGhpcyk7XG4gICAgICAgIH07XG4gICAgICAgIC8vXG4gICAgICAgIC8vIENvbWJpbmVzIHRoZSBsb2dpYyBmb3IgY2hlY2tpbmcgd2hldGhlciBhbiBpdGVtIGlzIGEgbWVtYmVyIG9mIHRoZSBzZXQgYW5kXG4gICAgICAgIC8vIGZvciBhZGRpbmcgYSBuZXcgaXRlbSB0byB0aGUgc2V0LlxuICAgICAgICAvL1xuICAgICAgICAvLyBAcGFyYW0gaXRlbSAgICAgICBUaGUgaXRlbSB0byBjaGVjayBvciBhZGQgdG8gdGhlIFNldCBpbnN0YW5jZS5cbiAgICAgICAgLy8gQHBhcmFtIHNob3VsZEFkZCAgSWYgdHJ1ZSwgdGhlIGl0ZW0gd2lsbCBiZSBhZGRlZCB0byB0aGUgc2V0IGlmIGl0IGRvZXNuJ3RcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgYWxyZWFkeSBleGlzdC5cbiAgICAgICAgLy8gQHBhcmFtIHNldCAgICAgICAgVGhlIHNldCBpbnN0YW5jZSB0byBjaGVjayBvciBhZGQgdG8uXG4gICAgICAgIC8vIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgdGhlIGl0ZW0gYWxyZWFkeSBleGlzdGVkLCBvdGhlcndpc2UgZmFsc2UuXG4gICAgICAgIC8vXG4gICAgICAgIGZ1bmN0aW9uIGhhc09yQWRkKGl0ZW0sIHNob3VsZEFkZCwgc2V0KSB7XG4gICAgICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBpdGVtO1xuICAgICAgICAgICAgdmFyIHByZXZTaXplLCBuZXdTaXplO1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgICAgICAgICAvLyBkaXN0aW5ndWlzaCBiZXR3ZWVuICswIGFuZCAtMFxuICAgICAgICAgICAgICAgIGlmIChpdGVtID09PSAwICYmIDEgLyBpdGVtID09PSAtSW5maW5pdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNldC5faXRlbXNbJy0wJ10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNob3VsZEFkZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldC5faXRlbXNbJy0wJ10gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHRoZXNlIHR5cGVzIGNhbiBhbGwgdXRpbGlzZSB0aGUgbmF0aXZlIFNldFxuICAgICAgICAgICAgICAgIGlmIChzZXQuX25hdGl2ZVNldCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2U2l6ZSA9IHNldC5fbmF0aXZlU2V0LnNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQuX25hdGl2ZVNldC5hZGQoaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdTaXplID0gc2V0Ll9uYXRpdmVTZXQuc2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXdTaXplID09PSBwcmV2U2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzZXQuX25hdGl2ZVNldC5oYXMoaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISh0eXBlIGluIHNldC5faXRlbXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Ll9pdGVtc1t0eXBlXSA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldC5faXRlbXNbdHlwZV1baXRlbV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGl0ZW0gaW4gc2V0Ll9pdGVtc1t0eXBlXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Ll9pdGVtc1t0eXBlXVtpdGVtXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdib29sZWFuJzpcbiAgICAgICAgICAgICAgICAvLyBzZXQuX2l0ZW1zWydib29sZWFuJ10gaG9sZHMgYSB0d28gZWxlbWVudCBhcnJheVxuICAgICAgICAgICAgICAgIC8vIHJlcHJlc2VudGluZyBbIGZhbHNlRXhpc3RzLCB0cnVlRXhpc3RzIF1cbiAgICAgICAgICAgICAgICBpZiAodHlwZSBpbiBzZXQuX2l0ZW1zKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBiSWR4ID0gaXRlbSA/IDEgOiAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2V0Ll9pdGVtc1t0eXBlXVtiSWR4XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Ll9pdGVtc1t0eXBlXVtiSWR4XSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQuX2l0ZW1zW3R5cGVdID0gaXRlbSA/IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgICBdIDogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgICAgICAgICAgICAvLyBjb21wYXJlIGZ1bmN0aW9ucyBmb3IgcmVmZXJlbmNlIGVxdWFsaXR5XG4gICAgICAgICAgICAgICAgaWYgKHNldC5fbmF0aXZlU2V0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzaG91bGRBZGQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZTaXplID0gc2V0Ll9uYXRpdmVTZXQuc2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldC5fbmF0aXZlU2V0LmFkZChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1NpemUgPSBzZXQuX25hdGl2ZVNldC5zaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ld1NpemUgPiBwcmV2U2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzZXQuX25hdGl2ZVNldC5oYXMoaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoISh0eXBlIGluIHNldC5faXRlbXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Ll9pdGVtc1t0eXBlXSA9IFtpdGVtXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIV9jb250YWlucyhpdGVtLCBzZXQuX2l0ZW1zW3R5cGVdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNob3VsZEFkZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldC5faXRlbXNbdHlwZV0ucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICd1bmRlZmluZWQnOlxuICAgICAgICAgICAgICAgIGlmIChzZXQuX2l0ZW1zW3R5cGVdKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzaG91bGRBZGQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldC5faXRlbXNbdHlwZV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdvYmplY3QnOlxuICAgICAgICAgICAgICAgIGlmIChpdGVtID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2V0Ll9pdGVtc1snbnVsbCddKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Ll9pdGVtc1snbnVsbCddID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIC8vIHJlZHVjZSB0aGUgc2VhcmNoIHNpemUgb2YgaGV0ZXJvZ2VuZW91cyBzZXRzIGJ5IGNyZWF0aW5nIGJ1Y2tldHNcbiAgICAgICAgICAgICAgICAvLyBmb3IgZWFjaCB0eXBlLlxuICAgICAgICAgICAgICAgIHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaXRlbSk7XG4gICAgICAgICAgICAgICAgaWYgKCEodHlwZSBpbiBzZXQuX2l0ZW1zKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQuX2l0ZW1zW3R5cGVdID0gW2l0ZW1dO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gc2NhbiB0aHJvdWdoIGFsbCBwcmV2aW91c2x5IGFwcGxpZWQgaXRlbXNcbiAgICAgICAgICAgICAgICBpZiAoIV9jb250YWlucyhpdGVtLCBzZXQuX2l0ZW1zW3R5cGVdKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkQWRkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQuX2l0ZW1zW3R5cGVdLnB1c2goaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX1NldDtcbiAgICB9KCk7XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHdyYXBwaW5nIGNhbGxzIHRvIHRoZSB0d28gZnVuY3Rpb25zIGluIGFuIGAmJmAgb3BlcmF0aW9uLFxuICAgICAqIHJldHVybmluZyB0aGUgcmVzdWx0IG9mIHRoZSBmaXJzdCBmdW5jdGlvbiBpZiBpdCBpcyBmYWxzZS15IGFuZCB0aGUgcmVzdWx0XG4gICAgICogb2YgdGhlIHNlY29uZCBmdW5jdGlvbiBvdGhlcndpc2UuIE5vdGUgdGhhdCB0aGlzIGlzIHNob3J0LWNpcmN1aXRlZCxcbiAgICAgKiBtZWFuaW5nIHRoYXQgdGhlIHNlY29uZCBmdW5jdGlvbiB3aWxsIG5vdCBiZSBpbnZva2VkIGlmIHRoZSBmaXJzdCByZXR1cm5zIGFcbiAgICAgKiBmYWxzZS15IHZhbHVlLlxuICAgICAqXG4gICAgICogSW4gYWRkaXRpb24gdG8gZnVuY3Rpb25zLCBgUi5ib3RoYCBhbHNvIGFjY2VwdHMgYW55IGZhbnRhc3ktbGFuZCBjb21wYXRpYmxlXG4gICAgICogYXBwbGljYXRpdmUgZnVuY3Rvci5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTIuMFxuICAgICAqIEBjYXRlZ29yeSBMb2dpY1xuICAgICAqIEBzaWcgKCouLi4gLT4gQm9vbGVhbikgLT4gKCouLi4gLT4gQm9vbGVhbikgLT4gKCouLi4gLT4gQm9vbGVhbilcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmIGEgcHJlZGljYXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZyBhbm90aGVyIHByZWRpY2F0ZVxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBhIGZ1bmN0aW9uIHRoYXQgYXBwbGllcyBpdHMgYXJndW1lbnRzIHRvIGBmYCBhbmQgYGdgIGFuZCBgJiZgcyB0aGVpciBvdXRwdXRzIHRvZ2V0aGVyLlxuICAgICAqIEBzZWUgUi5hbmRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZ3QxMCA9IHggPT4geCA+IDEwO1xuICAgICAqICAgICAgdmFyIGV2ZW4gPSB4ID0+IHggJSAyID09PSAwO1xuICAgICAqICAgICAgdmFyIGYgPSBSLmJvdGgoZ3QxMCwgZXZlbik7XG4gICAgICogICAgICBmKDEwMCk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgZigxMDEpOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGJvdGggPSBfY3VycnkyKGZ1bmN0aW9uIGJvdGgoZiwgZykge1xuICAgICAgICByZXR1cm4gX2lzRnVuY3Rpb24oZikgPyBmdW5jdGlvbiBfYm90aCgpIHtcbiAgICAgICAgICAgIHJldHVybiBmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgJiYgZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9IDogbGlmdChhbmQpKGYsIGcpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGFrZXMgYSBmdW5jdGlvbiBgZmAgYW5kIHJldHVybnMgYSBmdW5jdGlvbiBgZ2Agc3VjaCB0aGF0OlxuICAgICAqXG4gICAgICogICAtIGFwcGx5aW5nIGBnYCB0byB6ZXJvIG9yIG1vcmUgYXJndW1lbnRzIHdpbGwgZ2l2ZSBfX3RydWVfXyBpZiBhcHBseWluZ1xuICAgICAqICAgICB0aGUgc2FtZSBhcmd1bWVudHMgdG8gYGZgIGdpdmVzIGEgbG9naWNhbCBfX2ZhbHNlX18gdmFsdWU7IGFuZFxuICAgICAqXG4gICAgICogICAtIGFwcGx5aW5nIGBnYCB0byB6ZXJvIG9yIG1vcmUgYXJndW1lbnRzIHdpbGwgZ2l2ZSBfX2ZhbHNlX18gaWYgYXBwbHlpbmdcbiAgICAgKiAgICAgdGhlIHNhbWUgYXJndW1lbnRzIHRvIGBmYCBnaXZlcyBhIGxvZ2ljYWwgX190cnVlX18gdmFsdWUuXG4gICAgICpcbiAgICAgKiBgUi5jb21wbGVtZW50YCB3aWxsIHdvcmsgb24gYWxsIG90aGVyIGZ1bmN0b3JzIGFzIHdlbGwuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEyLjBcbiAgICAgKiBAY2F0ZWdvcnkgTG9naWNcbiAgICAgKiBAc2lnICgqLi4uIC0+ICopIC0+ICgqLi4uIC0+IEJvb2xlYW4pXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICAgICAqIEBzZWUgUi5ub3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgaXNFdmVuID0gbiA9PiBuICUgMiA9PT0gMDtcbiAgICAgKiAgICAgIHZhciBpc09kZCA9IFIuY29tcGxlbWVudChpc0V2ZW4pO1xuICAgICAqICAgICAgaXNPZGQoMjEpOyAvLz0+IHRydWVcbiAgICAgKiAgICAgIGlzT2RkKDQyKTsgLy89PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBjb21wbGVtZW50ID0gbGlmdChub3QpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcmVzdWx0IG9mIGNvbmNhdGVuYXRpbmcgdGhlIGdpdmVuIGxpc3RzIG9yIHN0cmluZ3MuXG4gICAgICpcbiAgICAgKiBOb3RlOiBgUi5jb25jYXRgIGV4cGVjdHMgYm90aCBhcmd1bWVudHMgdG8gYmUgb2YgdGhlIHNhbWUgdHlwZSxcbiAgICAgKiB1bmxpa2UgdGhlIG5hdGl2ZSBgQXJyYXkucHJvdG90eXBlLmNvbmNhdGAgbWV0aG9kLiBJdCB3aWxsIHRocm93XG4gICAgICogYW4gZXJyb3IgaWYgeW91IGBjb25jYXRgIGFuIEFycmF5IHdpdGggYSBub24tQXJyYXkgdmFsdWUuXG4gICAgICpcbiAgICAgKiBEaXNwYXRjaGVzIHRvIHRoZSBgY29uY2F0YCBtZXRob2Qgb2YgdGhlIGZpcnN0IGFyZ3VtZW50LCBpZiBwcmVzZW50LlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgW2FdIC0+IFthXSAtPiBbYV1cbiAgICAgKiBAc2lnIFN0cmluZyAtPiBTdHJpbmcgLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHtBcnJheXxTdHJpbmd9IGFcbiAgICAgKiBAcGFyYW0ge0FycmF5fFN0cmluZ30gYlxuICAgICAqIEByZXR1cm4ge0FycmF5fFN0cmluZ31cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuY29uY2F0KFtdLCBbXSk7IC8vPT4gW11cbiAgICAgKiAgICAgIFIuY29uY2F0KFs0LCA1LCA2XSwgWzEsIDIsIDNdKTsgLy89PiBbNCwgNSwgNiwgMSwgMiwgM11cbiAgICAgKiAgICAgIFIuY29uY2F0KCdBQkMnLCAnREVGJyk7IC8vICdBQkNERUYnXG4gICAgICovXG4gICAgdmFyIGNvbmNhdCA9IF9jdXJyeTIoZnVuY3Rpb24gY29uY2F0KGEsIGIpIHtcbiAgICAgICAgaWYgKGEgPT0gbnVsbCB8fCAhX2lzRnVuY3Rpb24oYS5jb25jYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHRvU3RyaW5nKGEpICsgJyBkb2VzIG5vdCBoYXZlIGEgbWV0aG9kIG5hbWVkIFwiY29uY2F0XCInKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoX2lzQXJyYXkoYSkgJiYgIV9pc0FycmF5KGIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHRvU3RyaW5nKGIpICsgJyBpcyBub3QgYW4gYXJyYXknKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYS5jb25jYXQoYik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBBIGZ1bmN0aW9uIHdyYXBwaW5nIGNhbGxzIHRvIHRoZSB0d28gZnVuY3Rpb25zIGluIGFuIGB8fGAgb3BlcmF0aW9uLFxuICAgICAqIHJldHVybmluZyB0aGUgcmVzdWx0IG9mIHRoZSBmaXJzdCBmdW5jdGlvbiBpZiBpdCBpcyB0cnV0aC15IGFuZCB0aGUgcmVzdWx0XG4gICAgICogb2YgdGhlIHNlY29uZCBmdW5jdGlvbiBvdGhlcndpc2UuIE5vdGUgdGhhdCB0aGlzIGlzIHNob3J0LWNpcmN1aXRlZCxcbiAgICAgKiBtZWFuaW5nIHRoYXQgdGhlIHNlY29uZCBmdW5jdGlvbiB3aWxsIG5vdCBiZSBpbnZva2VkIGlmIHRoZSBmaXJzdCByZXR1cm5zIGFcbiAgICAgKiB0cnV0aC15IHZhbHVlLlxuICAgICAqXG4gICAgICogSW4gYWRkaXRpb24gdG8gZnVuY3Rpb25zLCBgUi5laXRoZXJgIGFsc28gYWNjZXB0cyBhbnkgZmFudGFzeS1sYW5kIGNvbXBhdGlibGVcbiAgICAgKiBhcHBsaWNhdGl2ZSBmdW5jdG9yLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xMi4wXG4gICAgICogQGNhdGVnb3J5IExvZ2ljXG4gICAgICogQHNpZyAoKi4uLiAtPiBCb29sZWFuKSAtPiAoKi4uLiAtPiBCb29sZWFuKSAtPiAoKi4uLiAtPiBCb29sZWFuKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGYgYSBwcmVkaWNhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBnIGFub3RoZXIgcHJlZGljYXRlXG4gICAgICogQHJldHVybiB7RnVuY3Rpb259IGEgZnVuY3Rpb24gdGhhdCBhcHBsaWVzIGl0cyBhcmd1bWVudHMgdG8gYGZgIGFuZCBgZ2AgYW5kIGB8fGBzIHRoZWlyIG91dHB1dHMgdG9nZXRoZXIuXG4gICAgICogQHNlZSBSLm9yXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGd0MTAgPSB4ID0+IHggPiAxMDtcbiAgICAgKiAgICAgIHZhciBldmVuID0geCA9PiB4ICUgMiA9PT0gMDtcbiAgICAgKiAgICAgIHZhciBmID0gUi5laXRoZXIoZ3QxMCwgZXZlbik7XG4gICAgICogICAgICBmKDEwMSk7IC8vPT4gdHJ1ZVxuICAgICAqICAgICAgZig4KTsgLy89PiB0cnVlXG4gICAgICovXG4gICAgdmFyIGVpdGhlciA9IF9jdXJyeTIoZnVuY3Rpb24gZWl0aGVyKGYsIGcpIHtcbiAgICAgICAgcmV0dXJuIF9pc0Z1bmN0aW9uKGYpID8gZnVuY3Rpb24gX2VpdGhlcigpIHtcbiAgICAgICAgICAgIHJldHVybiBmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9IDogbGlmdChvcikoZiwgZyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUdXJucyBhIG5hbWVkIG1ldGhvZCB3aXRoIGEgc3BlY2lmaWVkIGFyaXR5IGludG8gYSBmdW5jdGlvbiB0aGF0IGNhbiBiZVxuICAgICAqIGNhbGxlZCBkaXJlY3RseSBzdXBwbGllZCB3aXRoIGFyZ3VtZW50cyBhbmQgYSB0YXJnZXQgb2JqZWN0LlxuICAgICAqXG4gICAgICogVGhlIHJldHVybmVkIGZ1bmN0aW9uIGlzIGN1cnJpZWQgYW5kIGFjY2VwdHMgYGFyaXR5ICsgMWAgcGFyYW1ldGVycyB3aGVyZVxuICAgICAqIHRoZSBmaW5hbCBwYXJhbWV0ZXIgaXMgdGhlIHRhcmdldCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBzaWcgTnVtYmVyIC0+IFN0cmluZyAtPiAoYSAtPiBiIC0+IC4uLiAtPiBuIC0+IE9iamVjdCAtPiAqKVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBhcml0eSBOdW1iZXIgb2YgYXJndW1lbnRzIHRoZSByZXR1cm5lZCBmdW5jdGlvbiBzaG91bGQgdGFrZVxuICAgICAqICAgICAgICBiZWZvcmUgdGhlIHRhcmdldCBvYmplY3QuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZCBOYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQSBuZXcgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgc2xpY2VGcm9tID0gUi5pbnZva2VyKDEsICdzbGljZScpO1xuICAgICAqICAgICAgc2xpY2VGcm9tKDYsICdhYmNkZWZnaGlqa2xtJyk7IC8vPT4gJ2doaWprbG0nXG4gICAgICogICAgICB2YXIgc2xpY2VGcm9tNiA9IFIuaW52b2tlcigyLCAnc2xpY2UnKSg2KTtcbiAgICAgKiAgICAgIHNsaWNlRnJvbTYoOCwgJ2FiY2RlZmdoaWprbG0nKTsgLy89PiAnZ2gnXG4gICAgICovXG4gICAgdmFyIGludm9rZXIgPSBfY3VycnkyKGZ1bmN0aW9uIGludm9rZXIoYXJpdHksIG1ldGhvZCkge1xuICAgICAgICByZXR1cm4gY3VycnlOKGFyaXR5ICsgMSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHRhcmdldCA9IGFyZ3VtZW50c1thcml0eV07XG4gICAgICAgICAgICBpZiAodGFyZ2V0ICE9IG51bGwgJiYgX2lzRnVuY3Rpb24odGFyZ2V0W21ldGhvZF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldFttZXRob2RdLmFwcGx5KHRhcmdldCwgX3NsaWNlKGFyZ3VtZW50cywgMCwgYXJpdHkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IodG9TdHJpbmcodGFyZ2V0KSArICcgZG9lcyBub3QgaGF2ZSBhIG1ldGhvZCBuYW1lZCBcIicgKyBtZXRob2QgKyAnXCInKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgc3RyaW5nIG1hZGUgYnkgaW5zZXJ0aW5nIHRoZSBgc2VwYXJhdG9yYCBiZXR3ZWVuIGVhY2ggZWxlbWVudCBhbmRcbiAgICAgKiBjb25jYXRlbmF0aW5nIGFsbCB0aGUgZWxlbWVudHMgaW50byBhIHNpbmdsZSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMaXN0XG4gICAgICogQHNpZyBTdHJpbmcgLT4gW2FdIC0+IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7TnVtYmVyfFN0cmluZ30gc2VwYXJhdG9yIFRoZSBzdHJpbmcgdXNlZCB0byBzZXBhcmF0ZSB0aGUgZWxlbWVudHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0geHMgVGhlIGVsZW1lbnRzIHRvIGpvaW4gaW50byBhIHN0cmluZy5cbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IHN0ciBUaGUgc3RyaW5nIG1hZGUgYnkgY29uY2F0ZW5hdGluZyBgeHNgIHdpdGggYHNlcGFyYXRvcmAuXG4gICAgICogQHNlZSBSLnNwbGl0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIHNwYWNlciA9IFIuam9pbignICcpO1xuICAgICAqICAgICAgc3BhY2VyKFsnYScsIDIsIDMuNF0pOyAgIC8vPT4gJ2EgMiAzLjQnXG4gICAgICogICAgICBSLmpvaW4oJ3wnLCBbMSwgMiwgM10pOyAgICAvLz0+ICcxfDJ8MydcbiAgICAgKi9cbiAgICB2YXIgam9pbiA9IGludm9rZXIoMSwgJ2pvaW4nKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgZnVuY3Rpb24gdGhhdCwgd2hlbiBpbnZva2VkLCBjYWNoZXMgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIGBmbmBcbiAgICAgKiBmb3IgYSBnaXZlbiBhcmd1bWVudCBzZXQgYW5kIHJldHVybnMgdGhlIHJlc3VsdC4gU3Vic2VxdWVudCBjYWxscyB0byB0aGVcbiAgICAgKiBtZW1vaXplZCBgZm5gIHdpdGggdGhlIHNhbWUgYXJndW1lbnQgc2V0IHdpbGwgbm90IHJlc3VsdCBpbiBhbiBhZGRpdGlvbmFsXG4gICAgICogY2FsbCB0byBgZm5gOyBpbnN0ZWFkLCB0aGUgY2FjaGVkIHJlc3VsdCBmb3IgdGhhdCBzZXQgb2YgYXJndW1lbnRzIHdpbGwgYmVcbiAgICAgKiByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHNpZyAoKi4uLiAtPiBhKSAtPiAoKi4uLiAtPiBhKVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtZW1vaXplLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBNZW1vaXplZCB2ZXJzaW9uIG9mIGBmbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgdmFyIGNvdW50ID0gMDtcbiAgICAgKiAgICAgIHZhciBmYWN0b3JpYWwgPSBSLm1lbW9pemUobiA9PiB7XG4gICAgICogICAgICAgIGNvdW50ICs9IDE7XG4gICAgICogICAgICAgIHJldHVybiBSLnByb2R1Y3QoUi5yYW5nZSgxLCBuICsgMSkpO1xuICAgICAqICAgICAgfSk7XG4gICAgICogICAgICBmYWN0b3JpYWwoNSk7IC8vPT4gMTIwXG4gICAgICogICAgICBmYWN0b3JpYWwoNSk7IC8vPT4gMTIwXG4gICAgICogICAgICBmYWN0b3JpYWwoNSk7IC8vPT4gMTIwXG4gICAgICogICAgICBjb3VudDsgLy89PiAxXG4gICAgICovXG4gICAgdmFyIG1lbW9pemUgPSBfY3VycnkxKGZ1bmN0aW9uIG1lbW9pemUoZm4pIHtcbiAgICAgICAgdmFyIGNhY2hlID0ge307XG4gICAgICAgIHJldHVybiBfYXJpdHkoZm4ubGVuZ3RoLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gdG9TdHJpbmcoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGlmICghX2hhcyhrZXksIGNhY2hlKSkge1xuICAgICAgICAgICAgICAgIGNhY2hlW2tleV0gPSBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlW2tleV07XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyBiYXNlZCBvbiB0aGUgZ2l2ZW5cbiAgICAgKiBzZXBhcmF0b3IuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAc2lnIChTdHJpbmcgfCBSZWdFeHApIC0+IFN0cmluZyAtPiBbU3RyaW5nXVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gc2VwIFRoZSBwYXR0ZXJuLlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBzZXBhcmF0ZSBpbnRvIGFuIGFycmF5LlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBUaGUgYXJyYXkgb2Ygc3RyaW5ncyBmcm9tIGBzdHJgIHNlcGFyYXRlZCBieSBgc3RyYC5cbiAgICAgKiBAc2VlIFIuam9pblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIHZhciBwYXRoQ29tcG9uZW50cyA9IFIuc3BsaXQoJy8nKTtcbiAgICAgKiAgICAgIFIudGFpbChwYXRoQ29tcG9uZW50cygnL3Vzci9sb2NhbC9iaW4vbm9kZScpKTsgLy89PiBbJ3VzcicsICdsb2NhbCcsICdiaW4nLCAnbm9kZSddXG4gICAgICpcbiAgICAgKiAgICAgIFIuc3BsaXQoJy4nLCAnYS5iLmMueHl6LmQnKTsgLy89PiBbJ2EnLCAnYicsICdjJywgJ3h5eicsICdkJ11cbiAgICAgKi9cbiAgICB2YXIgc3BsaXQgPSBpbnZva2VyKDEsICdzcGxpdCcpO1xuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIHNldCAoaS5lLiBubyBkdXBsaWNhdGVzKSBvZiBhbGwgZWxlbWVudHMgY29udGFpbmVkIGluIHRoZSBmaXJzdCBvclxuICAgICAqIHNlY29uZCBsaXN0LCBidXQgbm90IGJvdGguXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE5LjBcbiAgICAgKiBAY2F0ZWdvcnkgUmVsYXRpb25cbiAgICAgKiBAc2lnIFsqXSAtPiBbKl0gLT4gWypdXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdDEgVGhlIGZpcnN0IGxpc3QuXG4gICAgICogQHBhcmFtIHtBcnJheX0gbGlzdDIgVGhlIHNlY29uZCBsaXN0LlxuICAgICAqIEByZXR1cm4ge0FycmF5fSBUaGUgZWxlbWVudHMgaW4gYGxpc3QxYCBvciBgbGlzdDJgLCBidXQgbm90IGJvdGguXG4gICAgICogQHNlZSBSLnN5bW1ldHJpY0RpZmZlcmVuY2VXaXRoLCBSLmRpZmZlcmVuY2UsIFIuZGlmZmVyZW5jZVdpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnN5bW1ldHJpY0RpZmZlcmVuY2UoWzEsMiwzLDRdLCBbNyw2LDUsNCwzXSk7IC8vPT4gWzEsMiw3LDYsNV1cbiAgICAgKiAgICAgIFIuc3ltbWV0cmljRGlmZmVyZW5jZShbNyw2LDUsNCwzXSwgWzEsMiwzLDRdKTsgLy89PiBbNyw2LDUsMSwyXVxuICAgICAqL1xuICAgIHZhciBzeW1tZXRyaWNEaWZmZXJlbmNlID0gX2N1cnJ5MihmdW5jdGlvbiBzeW1tZXRyaWNEaWZmZXJlbmNlKGxpc3QxLCBsaXN0Mikge1xuICAgICAgICByZXR1cm4gY29uY2F0KGRpZmZlcmVuY2UobGlzdDEsIGxpc3QyKSwgZGlmZmVyZW5jZShsaXN0MiwgbGlzdDEpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBzZXQgKGkuZS4gbm8gZHVwbGljYXRlcykgb2YgYWxsIGVsZW1lbnRzIGNvbnRhaW5lZCBpbiB0aGUgZmlyc3Qgb3JcbiAgICAgKiBzZWNvbmQgbGlzdCwgYnV0IG5vdCBib3RoLiBEdXBsaWNhdGlvbiBpcyBkZXRlcm1pbmVkIGFjY29yZGluZyB0byB0aGUgdmFsdWVcbiAgICAgKiByZXR1cm5lZCBieSBhcHBseWluZyB0aGUgc3VwcGxpZWQgcHJlZGljYXRlIHRvIHR3byBsaXN0IGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC4xOS4wXG4gICAgICogQGNhdGVnb3J5IFJlbGF0aW9uXG4gICAgICogQHNpZyAoYSAtPiBhIC0+IEJvb2xlYW4pIC0+IFthXSAtPiBbYV0gLT4gW2FdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZCBBIHByZWRpY2F0ZSB1c2VkIHRvIHRlc3Qgd2hldGhlciB0d28gaXRlbXMgYXJlIGVxdWFsLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QxIFRoZSBmaXJzdCBsaXN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGxpc3QyIFRoZSBzZWNvbmQgbGlzdC5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGVsZW1lbnRzIGluIGBsaXN0MWAgb3IgYGxpc3QyYCwgYnV0IG5vdCBib3RoLlxuICAgICAqIEBzZWUgUi5zeW1tZXRyaWNEaWZmZXJlbmNlLCBSLmRpZmZlcmVuY2UsIFIuZGlmZmVyZW5jZVdpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICB2YXIgZXFBID0gUi5lcUJ5KFIucHJvcCgnYScpKTtcbiAgICAgKiAgICAgIHZhciBsMSA9IFt7YTogMX0sIHthOiAyfSwge2E6IDN9LCB7YTogNH1dO1xuICAgICAqICAgICAgdmFyIGwyID0gW3thOiAzfSwge2E6IDR9LCB7YTogNX0sIHthOiA2fV07XG4gICAgICogICAgICBSLnN5bW1ldHJpY0RpZmZlcmVuY2VXaXRoKGVxQSwgbDEsIGwyKTsgLy89PiBbe2E6IDF9LCB7YTogMn0sIHthOiA1fSwge2E6IDZ9XVxuICAgICAqL1xuICAgIHZhciBzeW1tZXRyaWNEaWZmZXJlbmNlV2l0aCA9IF9jdXJyeTMoZnVuY3Rpb24gc3ltbWV0cmljRGlmZmVyZW5jZVdpdGgocHJlZCwgbGlzdDEsIGxpc3QyKSB7XG4gICAgICAgIHJldHVybiBjb25jYXQoZGlmZmVyZW5jZVdpdGgocHJlZCwgbGlzdDEsIGxpc3QyKSwgZGlmZmVyZW5jZVdpdGgocHJlZCwgbGlzdDIsIGxpc3QxKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgYSBnaXZlbiBzdHJpbmcgbWF0Y2hlcyBhIGdpdmVuIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMTIuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAc2lnIFJlZ0V4cCAtPiBTdHJpbmcgLT4gQm9vbGVhblxuICAgICAqIEBwYXJhbSB7UmVnRXhwfSBwYXR0ZXJuXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICAgICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAgICogQHNlZSBSLm1hdGNoXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi50ZXN0KC9eeC8sICd4eXonKTsgLy89PiB0cnVlXG4gICAgICogICAgICBSLnRlc3QoL155LywgJ3h5eicpOyAvLz0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIHRlc3QgPSBfY3VycnkyKGZ1bmN0aW9uIHRlc3QocGF0dGVybiwgc3RyKSB7XG4gICAgICAgIGlmICghX2lzUmVnRXhwKHBhdHRlcm4pKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXHUyMDE4dGVzdFxcdTIwMTkgcmVxdWlyZXMgYSB2YWx1ZSBvZiB0eXBlIFJlZ0V4cCBhcyBpdHMgZmlyc3QgYXJndW1lbnQ7IHJlY2VpdmVkICcgKyB0b1N0cmluZyhwYXR0ZXJuKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9jbG9uZVJlZ0V4cChwYXR0ZXJuKS50ZXN0KHN0cik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbG93ZXIgY2FzZSB2ZXJzaW9uIG9mIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQGZ1bmNcbiAgICAgKiBAbWVtYmVyT2YgUlxuICAgICAqIEBzaW5jZSB2MC45LjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHNpZyBTdHJpbmcgLT4gU3RyaW5nXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBUaGUgc3RyaW5nIHRvIGxvd2VyIGNhc2UuXG4gICAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgbG93ZXIgY2FzZSB2ZXJzaW9uIG9mIGBzdHJgLlxuICAgICAqIEBzZWUgUi50b1VwcGVyXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqICAgICAgUi50b0xvd2VyKCdYWVonKTsgLy89PiAneHl6J1xuICAgICAqL1xuICAgIHZhciB0b0xvd2VyID0gaW52b2tlcigwLCAndG9Mb3dlckNhc2UnKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSB1cHBlciBjYXNlIHZlcnNpb24gb2YgYSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjkuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAc2lnIFN0cmluZyAtPiBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gdXBwZXIgY2FzZS5cbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSB1cHBlciBjYXNlIHZlcnNpb24gb2YgYHN0cmAuXG4gICAgICogQHNlZSBSLnRvTG93ZXJcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogICAgICBSLnRvVXBwZXIoJ2FiYycpOyAvLz0+ICdBQkMnXG4gICAgICovXG4gICAgdmFyIHRvVXBwZXIgPSBpbnZva2VyKDAsICd0b1VwcGVyQ2FzZScpO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IGNvbnRhaW5pbmcgb25seSBvbmUgY29weSBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIG9yaWdpbmFsXG4gICAgICogbGlzdCwgYmFzZWQgdXBvbiB0aGUgdmFsdWUgcmV0dXJuZWQgYnkgYXBwbHlpbmcgdGhlIHN1cHBsaWVkIGZ1bmN0aW9uIHRvXG4gICAgICogZWFjaCBsaXN0IGVsZW1lbnQuIFByZWZlcnMgdGhlIGZpcnN0IGl0ZW0gaWYgdGhlIHN1cHBsaWVkIGZ1bmN0aW9uIHByb2R1Y2VzXG4gICAgICogdGhlIHNhbWUgdmFsdWUgb24gdHdvIGl0ZW1zLiBgUi5lcXVhbHNgIGlzIHVzZWQgZm9yIGNvbXBhcmlzb24uXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjE2LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGlzdFxuICAgICAqIEBzaWcgKGEgLT4gYikgLT4gW2FdIC0+IFthXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEEgZnVuY3Rpb24gdXNlZCB0byBwcm9kdWNlIGEgdmFsdWUgdG8gdXNlIGR1cmluZyBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3Qgb2YgdW5pcXVlIGl0ZW1zLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudW5pcUJ5KE1hdGguYWJzLCBbLTEsIC01LCAyLCAxMCwgMSwgMl0pOyAvLz0+IFstMSwgLTUsIDIsIDEwXVxuICAgICAqL1xuICAgIHZhciB1bmlxQnkgPSBfY3VycnkyKGZ1bmN0aW9uIHVuaXFCeShmbiwgbGlzdCkge1xuICAgICAgICB2YXIgc2V0ID0gbmV3IF9TZXQoKTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIgaWR4ID0gMDtcbiAgICAgICAgdmFyIGFwcGxpZWRJdGVtLCBpdGVtO1xuICAgICAgICB3aGlsZSAoaWR4IDwgbGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGl0ZW0gPSBsaXN0W2lkeF07XG4gICAgICAgICAgICBhcHBsaWVkSXRlbSA9IGZuKGl0ZW0pO1xuICAgICAgICAgICAgaWYgKHNldC5hZGQoYXBwbGllZEl0ZW0pKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZHggKz0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIG5ldyBsaXN0IGNvbnRhaW5pbmcgb25seSBvbmUgY29weSBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIG9yaWdpbmFsXG4gICAgICogbGlzdC4gYFIuZXF1YWxzYCBpcyB1c2VkIHRvIGRldGVybWluZSBlcXVhbGl0eS5cbiAgICAgKlxuICAgICAqIEBmdW5jXG4gICAgICogQG1lbWJlck9mIFJcbiAgICAgKiBAc2luY2UgdjAuMS4wXG4gICAgICogQGNhdGVnb3J5IExpc3RcbiAgICAgKiBAc2lnIFthXSAtPiBbYV1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0IFRoZSBhcnJheSB0byBjb25zaWRlci5cbiAgICAgKiBAcmV0dXJuIHtBcnJheX0gVGhlIGxpc3Qgb2YgdW5pcXVlIGl0ZW1zLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudW5pcShbMSwgMSwgMiwgMV0pOyAvLz0+IFsxLCAyXVxuICAgICAqICAgICAgUi51bmlxKFsxLCAnMSddKTsgICAgIC8vPT4gWzEsICcxJ11cbiAgICAgKiAgICAgIFIudW5pcShbWzQyXSwgWzQyXV0pOyAvLz0+IFtbNDJdXVxuICAgICAqL1xuICAgIHZhciB1bmlxID0gdW5pcUJ5KGlkZW50aXR5KTtcblxuICAgIC8qKlxuICAgICAqIENvbWJpbmVzIHR3byBsaXN0cyBpbnRvIGEgc2V0IChpLmUuIG5vIGR1cGxpY2F0ZXMpIGNvbXBvc2VkIG9mIHRob3NlXG4gICAgICogZWxlbWVudHMgY29tbW9uIHRvIGJvdGggbGlzdHMuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgWypdIC0+IFsqXSAtPiBbKl1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MSBUaGUgZmlyc3QgbGlzdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBsaXN0MiBUaGUgc2Vjb25kIGxpc3QuXG4gICAgICogQHJldHVybiB7QXJyYXl9IFRoZSBsaXN0IG9mIGVsZW1lbnRzIGZvdW5kIGluIGJvdGggYGxpc3QxYCBhbmQgYGxpc3QyYC5cbiAgICAgKiBAc2VlIFIuaW50ZXJzZWN0aW9uV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIuaW50ZXJzZWN0aW9uKFsxLDIsMyw0XSwgWzcsNiw1LDQsM10pOyAvLz0+IFs0LCAzXVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb24gPSBfY3VycnkyKGZ1bmN0aW9uIGludGVyc2VjdGlvbihsaXN0MSwgbGlzdDIpIHtcbiAgICAgICAgdmFyIGxvb2t1cExpc3QsIGZpbHRlcmVkTGlzdDtcbiAgICAgICAgaWYgKGxpc3QxLmxlbmd0aCA+IGxpc3QyLmxlbmd0aCkge1xuICAgICAgICAgICAgbG9va3VwTGlzdCA9IGxpc3QxO1xuICAgICAgICAgICAgZmlsdGVyZWRMaXN0ID0gbGlzdDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb29rdXBMaXN0ID0gbGlzdDI7XG4gICAgICAgICAgICBmaWx0ZXJlZExpc3QgPSBsaXN0MTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5pcShfZmlsdGVyKGZsaXAoX2NvbnRhaW5zKShsb29rdXBMaXN0KSwgZmlsdGVyZWRMaXN0KSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21iaW5lcyB0d28gbGlzdHMgaW50byBhIHNldCAoaS5lLiBubyBkdXBsaWNhdGVzKSBjb21wb3NlZCBvZiB0aGUgZWxlbWVudHNcbiAgICAgKiBvZiBlYWNoIGxpc3QuXG4gICAgICpcbiAgICAgKiBAZnVuY1xuICAgICAqIEBtZW1iZXJPZiBSXG4gICAgICogQHNpbmNlIHYwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBSZWxhdGlvblxuICAgICAqIEBzaWcgWypdIC0+IFsqXSAtPiBbKl1cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcyBUaGUgZmlyc3QgbGlzdC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBicyBUaGUgc2Vjb25kIGxpc3QuXG4gICAgICogQHJldHVybiB7QXJyYXl9IFRoZSBmaXJzdCBhbmQgc2Vjb25kIGxpc3RzIGNvbmNhdGVuYXRlZCwgd2l0aFxuICAgICAqICAgICAgICAgZHVwbGljYXRlcyByZW1vdmVkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAgICAgIFIudW5pb24oWzEsIDIsIDNdLCBbMiwgMywgNF0pOyAvLz0+IFsxLCAyLCAzLCA0XVxuICAgICAqL1xuICAgIHZhciB1bmlvbiA9IF9jdXJyeTIoY29tcG9zZSh1bmlxLCBfY29uY2F0KSk7XG5cbiAgICB2YXIgUiA9IHtcbiAgICAgICAgRjogRixcbiAgICAgICAgVDogVCxcbiAgICAgICAgX186IF9fLFxuICAgICAgICBhZGQ6IGFkZCxcbiAgICAgICAgYWRkSW5kZXg6IGFkZEluZGV4LFxuICAgICAgICBhZGp1c3Q6IGFkanVzdCxcbiAgICAgICAgYWxsOiBhbGwsXG4gICAgICAgIGFsbFBhc3M6IGFsbFBhc3MsXG4gICAgICAgIGFsd2F5czogYWx3YXlzLFxuICAgICAgICBhbmQ6IGFuZCxcbiAgICAgICAgYW55OiBhbnksXG4gICAgICAgIGFueVBhc3M6IGFueVBhc3MsXG4gICAgICAgIGFwOiBhcCxcbiAgICAgICAgYXBlcnR1cmU6IGFwZXJ0dXJlLFxuICAgICAgICBhcHBlbmQ6IGFwcGVuZCxcbiAgICAgICAgYXBwbHk6IGFwcGx5LFxuICAgICAgICBhcHBseVNwZWM6IGFwcGx5U3BlYyxcbiAgICAgICAgYXNzb2M6IGFzc29jLFxuICAgICAgICBhc3NvY1BhdGg6IGFzc29jUGF0aCxcbiAgICAgICAgYmluYXJ5OiBiaW5hcnksXG4gICAgICAgIGJpbmQ6IGJpbmQsXG4gICAgICAgIGJvdGg6IGJvdGgsXG4gICAgICAgIGNhbGw6IGNhbGwsXG4gICAgICAgIGNoYWluOiBjaGFpbixcbiAgICAgICAgY2xhbXA6IGNsYW1wLFxuICAgICAgICBjbG9uZTogY2xvbmUsXG4gICAgICAgIGNvbXBhcmF0b3I6IGNvbXBhcmF0b3IsXG4gICAgICAgIGNvbXBsZW1lbnQ6IGNvbXBsZW1lbnQsXG4gICAgICAgIGNvbXBvc2U6IGNvbXBvc2UsXG4gICAgICAgIGNvbXBvc2VLOiBjb21wb3NlSyxcbiAgICAgICAgY29tcG9zZVA6IGNvbXBvc2VQLFxuICAgICAgICBjb25jYXQ6IGNvbmNhdCxcbiAgICAgICAgY29uZDogY29uZCxcbiAgICAgICAgY29uc3RydWN0OiBjb25zdHJ1Y3QsXG4gICAgICAgIGNvbnN0cnVjdE46IGNvbnN0cnVjdE4sXG4gICAgICAgIGNvbnRhaW5zOiBjb250YWlucyxcbiAgICAgICAgY29udmVyZ2U6IGNvbnZlcmdlLFxuICAgICAgICBjb3VudEJ5OiBjb3VudEJ5LFxuICAgICAgICBjdXJyeTogY3VycnksXG4gICAgICAgIGN1cnJ5TjogY3VycnlOLFxuICAgICAgICBkZWM6IGRlYyxcbiAgICAgICAgZGVmYXVsdFRvOiBkZWZhdWx0VG8sXG4gICAgICAgIGRpZmZlcmVuY2U6IGRpZmZlcmVuY2UsXG4gICAgICAgIGRpZmZlcmVuY2VXaXRoOiBkaWZmZXJlbmNlV2l0aCxcbiAgICAgICAgZGlzc29jOiBkaXNzb2MsXG4gICAgICAgIGRpc3NvY1BhdGg6IGRpc3NvY1BhdGgsXG4gICAgICAgIGRpdmlkZTogZGl2aWRlLFxuICAgICAgICBkcm9wOiBkcm9wLFxuICAgICAgICBkcm9wTGFzdDogZHJvcExhc3QsXG4gICAgICAgIGRyb3BMYXN0V2hpbGU6IGRyb3BMYXN0V2hpbGUsXG4gICAgICAgIGRyb3BSZXBlYXRzOiBkcm9wUmVwZWF0cyxcbiAgICAgICAgZHJvcFJlcGVhdHNXaXRoOiBkcm9wUmVwZWF0c1dpdGgsXG4gICAgICAgIGRyb3BXaGlsZTogZHJvcFdoaWxlLFxuICAgICAgICBlaXRoZXI6IGVpdGhlcixcbiAgICAgICAgZW1wdHk6IGVtcHR5LFxuICAgICAgICBlcUJ5OiBlcUJ5LFxuICAgICAgICBlcVByb3BzOiBlcVByb3BzLFxuICAgICAgICBlcXVhbHM6IGVxdWFscyxcbiAgICAgICAgZXZvbHZlOiBldm9sdmUsXG4gICAgICAgIGZpbHRlcjogZmlsdGVyLFxuICAgICAgICBmaW5kOiBmaW5kLFxuICAgICAgICBmaW5kSW5kZXg6IGZpbmRJbmRleCxcbiAgICAgICAgZmluZExhc3Q6IGZpbmRMYXN0LFxuICAgICAgICBmaW5kTGFzdEluZGV4OiBmaW5kTGFzdEluZGV4LFxuICAgICAgICBmbGF0dGVuOiBmbGF0dGVuLFxuICAgICAgICBmbGlwOiBmbGlwLFxuICAgICAgICBmb3JFYWNoOiBmb3JFYWNoLFxuICAgICAgICBmcm9tUGFpcnM6IGZyb21QYWlycyxcbiAgICAgICAgZ3JvdXBCeTogZ3JvdXBCeSxcbiAgICAgICAgZ3JvdXBXaXRoOiBncm91cFdpdGgsXG4gICAgICAgIGd0OiBndCxcbiAgICAgICAgZ3RlOiBndGUsXG4gICAgICAgIGhhczogaGFzLFxuICAgICAgICBoYXNJbjogaGFzSW4sXG4gICAgICAgIGhlYWQ6IGhlYWQsXG4gICAgICAgIGlkZW50aWNhbDogaWRlbnRpY2FsLFxuICAgICAgICBpZGVudGl0eTogaWRlbnRpdHksXG4gICAgICAgIGlmRWxzZTogaWZFbHNlLFxuICAgICAgICBpbmM6IGluYyxcbiAgICAgICAgaW5kZXhCeTogaW5kZXhCeSxcbiAgICAgICAgaW5kZXhPZjogaW5kZXhPZixcbiAgICAgICAgaW5pdDogaW5pdCxcbiAgICAgICAgaW5zZXJ0OiBpbnNlcnQsXG4gICAgICAgIGluc2VydEFsbDogaW5zZXJ0QWxsLFxuICAgICAgICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbixcbiAgICAgICAgaW50ZXJzZWN0aW9uV2l0aDogaW50ZXJzZWN0aW9uV2l0aCxcbiAgICAgICAgaW50ZXJzcGVyc2U6IGludGVyc3BlcnNlLFxuICAgICAgICBpbnRvOiBpbnRvLFxuICAgICAgICBpbnZlcnQ6IGludmVydCxcbiAgICAgICAgaW52ZXJ0T2JqOiBpbnZlcnRPYmosXG4gICAgICAgIGludm9rZXI6IGludm9rZXIsXG4gICAgICAgIGlzOiBpcyxcbiAgICAgICAgaXNBcnJheUxpa2U6IGlzQXJyYXlMaWtlLFxuICAgICAgICBpc0VtcHR5OiBpc0VtcHR5LFxuICAgICAgICBpc05pbDogaXNOaWwsXG4gICAgICAgIGpvaW46IGpvaW4sXG4gICAgICAgIGp1eHQ6IGp1eHQsXG4gICAgICAgIGtleXM6IGtleXMsXG4gICAgICAgIGtleXNJbjoga2V5c0luLFxuICAgICAgICBsYXN0OiBsYXN0LFxuICAgICAgICBsYXN0SW5kZXhPZjogbGFzdEluZGV4T2YsXG4gICAgICAgIGxlbmd0aDogbGVuZ3RoLFxuICAgICAgICBsZW5zOiBsZW5zLFxuICAgICAgICBsZW5zSW5kZXg6IGxlbnNJbmRleCxcbiAgICAgICAgbGVuc1BhdGg6IGxlbnNQYXRoLFxuICAgICAgICBsZW5zUHJvcDogbGVuc1Byb3AsXG4gICAgICAgIGxpZnQ6IGxpZnQsXG4gICAgICAgIGxpZnROOiBsaWZ0TixcbiAgICAgICAgbHQ6IGx0LFxuICAgICAgICBsdGU6IGx0ZSxcbiAgICAgICAgbWFwOiBtYXAsXG4gICAgICAgIG1hcEFjY3VtOiBtYXBBY2N1bSxcbiAgICAgICAgbWFwQWNjdW1SaWdodDogbWFwQWNjdW1SaWdodCxcbiAgICAgICAgbWFwT2JqSW5kZXhlZDogbWFwT2JqSW5kZXhlZCxcbiAgICAgICAgbWF0Y2g6IG1hdGNoLFxuICAgICAgICBtYXRoTW9kOiBtYXRoTW9kLFxuICAgICAgICBtYXg6IG1heCxcbiAgICAgICAgbWF4Qnk6IG1heEJ5LFxuICAgICAgICBtZWFuOiBtZWFuLFxuICAgICAgICBtZWRpYW46IG1lZGlhbixcbiAgICAgICAgbWVtb2l6ZTogbWVtb2l6ZSxcbiAgICAgICAgbWVyZ2U6IG1lcmdlLFxuICAgICAgICBtZXJnZUFsbDogbWVyZ2VBbGwsXG4gICAgICAgIG1lcmdlV2l0aDogbWVyZ2VXaXRoLFxuICAgICAgICBtZXJnZVdpdGhLZXk6IG1lcmdlV2l0aEtleSxcbiAgICAgICAgbWluOiBtaW4sXG4gICAgICAgIG1pbkJ5OiBtaW5CeSxcbiAgICAgICAgbW9kdWxvOiBtb2R1bG8sXG4gICAgICAgIG11bHRpcGx5OiBtdWx0aXBseSxcbiAgICAgICAgbkFyeTogbkFyeSxcbiAgICAgICAgbmVnYXRlOiBuZWdhdGUsXG4gICAgICAgIG5vbmU6IG5vbmUsXG4gICAgICAgIG5vdDogbm90LFxuICAgICAgICBudGg6IG50aCxcbiAgICAgICAgbnRoQXJnOiBudGhBcmcsXG4gICAgICAgIG9iak9mOiBvYmpPZixcbiAgICAgICAgb2Y6IG9mLFxuICAgICAgICBvbWl0OiBvbWl0LFxuICAgICAgICBvbmNlOiBvbmNlLFxuICAgICAgICBvcjogb3IsXG4gICAgICAgIG92ZXI6IG92ZXIsXG4gICAgICAgIHBhaXI6IHBhaXIsXG4gICAgICAgIHBhcnRpYWw6IHBhcnRpYWwsXG4gICAgICAgIHBhcnRpYWxSaWdodDogcGFydGlhbFJpZ2h0LFxuICAgICAgICBwYXJ0aXRpb246IHBhcnRpdGlvbixcbiAgICAgICAgcGF0aDogcGF0aCxcbiAgICAgICAgcGF0aEVxOiBwYXRoRXEsXG4gICAgICAgIHBhdGhPcjogcGF0aE9yLFxuICAgICAgICBwYXRoU2F0aXNmaWVzOiBwYXRoU2F0aXNmaWVzLFxuICAgICAgICBwaWNrOiBwaWNrLFxuICAgICAgICBwaWNrQWxsOiBwaWNrQWxsLFxuICAgICAgICBwaWNrQnk6IHBpY2tCeSxcbiAgICAgICAgcGlwZTogcGlwZSxcbiAgICAgICAgcGlwZUs6IHBpcGVLLFxuICAgICAgICBwaXBlUDogcGlwZVAsXG4gICAgICAgIHBsdWNrOiBwbHVjayxcbiAgICAgICAgcHJlcGVuZDogcHJlcGVuZCxcbiAgICAgICAgcHJvZHVjdDogcHJvZHVjdCxcbiAgICAgICAgcHJvamVjdDogcHJvamVjdCxcbiAgICAgICAgcHJvcDogcHJvcCxcbiAgICAgICAgcHJvcEVxOiBwcm9wRXEsXG4gICAgICAgIHByb3BJczogcHJvcElzLFxuICAgICAgICBwcm9wT3I6IHByb3BPcixcbiAgICAgICAgcHJvcFNhdGlzZmllczogcHJvcFNhdGlzZmllcyxcbiAgICAgICAgcHJvcHM6IHByb3BzLFxuICAgICAgICByYW5nZTogcmFuZ2UsXG4gICAgICAgIHJlZHVjZTogcmVkdWNlLFxuICAgICAgICByZWR1Y2VCeTogcmVkdWNlQnksXG4gICAgICAgIHJlZHVjZVJpZ2h0OiByZWR1Y2VSaWdodCxcbiAgICAgICAgcmVkdWNlV2hpbGU6IHJlZHVjZVdoaWxlLFxuICAgICAgICByZWR1Y2VkOiByZWR1Y2VkLFxuICAgICAgICByZWplY3Q6IHJlamVjdCxcbiAgICAgICAgcmVtb3ZlOiByZW1vdmUsXG4gICAgICAgIHJlcGVhdDogcmVwZWF0LFxuICAgICAgICByZXBsYWNlOiByZXBsYWNlLFxuICAgICAgICByZXZlcnNlOiByZXZlcnNlLFxuICAgICAgICBzY2FuOiBzY2FuLFxuICAgICAgICBzZXF1ZW5jZTogc2VxdWVuY2UsXG4gICAgICAgIHNldDogc2V0LFxuICAgICAgICBzbGljZTogc2xpY2UsXG4gICAgICAgIHNvcnQ6IHNvcnQsXG4gICAgICAgIHNvcnRCeTogc29ydEJ5LFxuICAgICAgICBzcGxpdDogc3BsaXQsXG4gICAgICAgIHNwbGl0QXQ6IHNwbGl0QXQsXG4gICAgICAgIHNwbGl0RXZlcnk6IHNwbGl0RXZlcnksXG4gICAgICAgIHNwbGl0V2hlbjogc3BsaXRXaGVuLFxuICAgICAgICBzdWJ0cmFjdDogc3VidHJhY3QsXG4gICAgICAgIHN1bTogc3VtLFxuICAgICAgICBzeW1tZXRyaWNEaWZmZXJlbmNlOiBzeW1tZXRyaWNEaWZmZXJlbmNlLFxuICAgICAgICBzeW1tZXRyaWNEaWZmZXJlbmNlV2l0aDogc3ltbWV0cmljRGlmZmVyZW5jZVdpdGgsXG4gICAgICAgIHRhaWw6IHRhaWwsXG4gICAgICAgIHRha2U6IHRha2UsXG4gICAgICAgIHRha2VMYXN0OiB0YWtlTGFzdCxcbiAgICAgICAgdGFrZUxhc3RXaGlsZTogdGFrZUxhc3RXaGlsZSxcbiAgICAgICAgdGFrZVdoaWxlOiB0YWtlV2hpbGUsXG4gICAgICAgIHRhcDogdGFwLFxuICAgICAgICB0ZXN0OiB0ZXN0LFxuICAgICAgICB0aW1lczogdGltZXMsXG4gICAgICAgIHRvTG93ZXI6IHRvTG93ZXIsXG4gICAgICAgIHRvUGFpcnM6IHRvUGFpcnMsXG4gICAgICAgIHRvUGFpcnNJbjogdG9QYWlyc0luLFxuICAgICAgICB0b1N0cmluZzogdG9TdHJpbmcsXG4gICAgICAgIHRvVXBwZXI6IHRvVXBwZXIsXG4gICAgICAgIHRyYW5zZHVjZTogdHJhbnNkdWNlLFxuICAgICAgICB0cmFuc3Bvc2U6IHRyYW5zcG9zZSxcbiAgICAgICAgdHJhdmVyc2U6IHRyYXZlcnNlLFxuICAgICAgICB0cmltOiB0cmltLFxuICAgICAgICB0cnlDYXRjaDogdHJ5Q2F0Y2gsXG4gICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgIHVuYXBwbHk6IHVuYXBwbHksXG4gICAgICAgIHVuYXJ5OiB1bmFyeSxcbiAgICAgICAgdW5jdXJyeU46IHVuY3VycnlOLFxuICAgICAgICB1bmZvbGQ6IHVuZm9sZCxcbiAgICAgICAgdW5pb246IHVuaW9uLFxuICAgICAgICB1bmlvbldpdGg6IHVuaW9uV2l0aCxcbiAgICAgICAgdW5pcTogdW5pcSxcbiAgICAgICAgdW5pcUJ5OiB1bmlxQnksXG4gICAgICAgIHVuaXFXaXRoOiB1bmlxV2l0aCxcbiAgICAgICAgdW5sZXNzOiB1bmxlc3MsXG4gICAgICAgIHVubmVzdDogdW5uZXN0LFxuICAgICAgICB1bnRpbDogdW50aWwsXG4gICAgICAgIHVwZGF0ZTogdXBkYXRlLFxuICAgICAgICB1c2VXaXRoOiB1c2VXaXRoLFxuICAgICAgICB2YWx1ZXM6IHZhbHVlcyxcbiAgICAgICAgdmFsdWVzSW46IHZhbHVlc0luLFxuICAgICAgICB2aWV3OiB2aWV3LFxuICAgICAgICB3aGVuOiB3aGVuLFxuICAgICAgICB3aGVyZTogd2hlcmUsXG4gICAgICAgIHdoZXJlRXE6IHdoZXJlRXEsXG4gICAgICAgIHdpdGhvdXQ6IHdpdGhvdXQsXG4gICAgICAgIHdyYXA6IHdyYXAsXG4gICAgICAgIHhwcm9kOiB4cHJvZCxcbiAgICAgICAgemlwOiB6aXAsXG4gICAgICAgIHppcE9iajogemlwT2JqLFxuICAgICAgICB6aXBXaXRoOiB6aXBXaXRoXG4gICAgfTtcbiAgLyogZXNsaW50LWVudiBhbWQgKi9cblxuICAvKiBURVNUX0VOVFJZX1BPSU5UICovXG5cbiAgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gUjtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7IHJldHVybiBSOyB9KTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLlIgPSBSO1xuICB9XG5cbn0uY2FsbCh0aGlzKSk7XG4iXX0=
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function (global){
(function(global, f){
'use strict';
/*istanbul ignore next*/
if(typeof module !== 'undefined'){
module.exports = f();
}
else if(typeof global.define === 'function' && global.define.amd){
global.define([], f);
}
else{
global.inspectf = f();
}
}(/*istanbul ignore next*/(global || window || this), function(){
'use strict';
function checkn(n){
if(typeof n !== 'number') throw new TypeError(
'inspectf expects its first argument to be a number'
);
}
function checkf(f){
if(typeof f !== 'function') throw new TypeError(
'inspectf expects its second argument to be a function'
);
}
const RSPACE = /^ */;
const RCODE = /\s*[^\s]/;
const RTABS = /\t/g;
const REOL = /\n\r?/;
function getPadding(line){
return line.match(RSPACE)[0].length;
}
function guessIndentation(lines){
const filtered = lines.filter(x => RCODE.test(x));
const paddings = filtered.map(getPadding);
const depth = paddings.reduce((a, b) => Math.min(a, b), Infinity);
const tabsize = paddings.map(x => x - depth).find(x => x > 1) || 2;
return {depth, tabsize};
}
function pad(n){
return (new Array(n + 1)).join(' ');
}
function show(f, indentation){
return f.toString().replace(RTABS, indentation);
}
function toLines(s){
return s.split(REOL);
}
function fixIndentation(lines, indentation){
const info = guessIndentation(lines.slice(1));
const RPAD = new RegExp(pad(info.tabsize), 'g');
return lines.map(line =>
line.slice(Math.min(info.depth, getPadding(line)))
.replace(RPAD, '\t').replace(RTABS, indentation)
).join('\n');
}
return function inspectf(n, f){
checkn(n);
if(arguments.length < 2) return f => inspectf(n, f);
checkf(f);
if(f.toString !== Function.prototype.toString) return f.toString();
const i = pad(n), shown = show(f, i), lines = toLines(shown, i);
if(lines.length < 2) return shown;
return fixIndentation(lines, i);
}
}));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9pbnNwZWN0LWYvaW5zcGVjdC1mLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oZ2xvYmFsLCBmKXtcblxuICAndXNlIHN0cmljdCc7XG5cbiAgLyppc3RhbmJ1bCBpZ25vcmUgbmV4dCovXG4gIGlmKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnKXtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGYoKTtcbiAgfVxuXG4gIGVsc2UgaWYodHlwZW9mIGdsb2JhbC5kZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZ2xvYmFsLmRlZmluZS5hbWQpe1xuICAgIGdsb2JhbC5kZWZpbmUoW10sIGYpO1xuICB9XG5cbiAgZWxzZXtcbiAgICBnbG9iYWwuaW5zcGVjdGYgPSBmKCk7XG4gIH1cblxufSgvKmlzdGFuYnVsIGlnbm9yZSBuZXh0Ki8oZ2xvYmFsIHx8IHdpbmRvdyB8fCB0aGlzKSwgZnVuY3Rpb24oKXtcblxuICAndXNlIHN0cmljdCc7XG5cbiAgZnVuY3Rpb24gY2hlY2tuKG4pe1xuICAgIGlmKHR5cGVvZiBuICE9PSAnbnVtYmVyJykgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdpbnNwZWN0ZiBleHBlY3RzIGl0cyBmaXJzdCBhcmd1bWVudCB0byBiZSBhIG51bWJlcidcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tmKGYpe1xuICAgIGlmKHR5cGVvZiBmICE9PSAnZnVuY3Rpb24nKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ2luc3BlY3RmIGV4cGVjdHMgaXRzIHNlY29uZCBhcmd1bWVudCB0byBiZSBhIGZ1bmN0aW9uJ1xuICAgICk7XG4gIH1cblxuICBjb25zdCBSU1BBQ0UgPSAvXiAqLztcbiAgY29uc3QgUkNPREUgPSAvXFxzKlteXFxzXS87XG4gIGNvbnN0IFJUQUJTID0gL1xcdC9nO1xuICBjb25zdCBSRU9MID0gL1xcblxccj8vO1xuXG4gIGZ1bmN0aW9uIGdldFBhZGRpbmcobGluZSl7XG4gICAgcmV0dXJuIGxpbmUubWF0Y2goUlNQQUNFKVswXS5sZW5ndGg7XG4gIH1cblxuICBmdW5jdGlvbiBndWVzc0luZGVudGF0aW9uKGxpbmVzKXtcbiAgICBjb25zdCBmaWx0ZXJlZCA9IGxpbmVzLmZpbHRlcih4ID0+IFJDT0RFLnRlc3QoeCkpO1xuICAgIGNvbnN0IHBhZGRpbmdzID0gZmlsdGVyZWQubWFwKGdldFBhZGRpbmcpO1xuICAgIGNvbnN0IGRlcHRoID0gcGFkZGluZ3MucmVkdWNlKChhLCBiKSA9PiBNYXRoLm1pbihhLCBiKSwgSW5maW5pdHkpO1xuICAgIGNvbnN0IHRhYnNpemUgPSBwYWRkaW5ncy5tYXAoeCA9PiB4IC0gZGVwdGgpLmZpbmQoeCA9PiB4ID4gMSkgfHwgMjtcbiAgICByZXR1cm4ge2RlcHRoLCB0YWJzaXplfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhZChuKXtcbiAgICByZXR1cm4gKG5ldyBBcnJheShuICsgMSkpLmpvaW4oJyAnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3coZiwgaW5kZW50YXRpb24pe1xuICAgIHJldHVybiBmLnRvU3RyaW5nKCkucmVwbGFjZShSVEFCUywgaW5kZW50YXRpb24pO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9MaW5lcyhzKXtcbiAgICByZXR1cm4gcy5zcGxpdChSRU9MKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpeEluZGVudGF0aW9uKGxpbmVzLCBpbmRlbnRhdGlvbil7XG4gICAgY29uc3QgaW5mbyA9IGd1ZXNzSW5kZW50YXRpb24obGluZXMuc2xpY2UoMSkpO1xuICAgIGNvbnN0IFJQQUQgPSBuZXcgUmVnRXhwKHBhZChpbmZvLnRhYnNpemUpLCAnZycpO1xuICAgIHJldHVybiBsaW5lcy5tYXAobGluZSA9PlxuICAgICAgbGluZS5zbGljZShNYXRoLm1pbihpbmZvLmRlcHRoLCBnZXRQYWRkaW5nKGxpbmUpKSlcbiAgICAgIC5yZXBsYWNlKFJQQUQsICdcXHQnKS5yZXBsYWNlKFJUQUJTLCBpbmRlbnRhdGlvbilcbiAgICApLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIGluc3BlY3RmKG4sIGYpe1xuICAgIGNoZWNrbihuKTtcbiAgICBpZihhcmd1bWVudHMubGVuZ3RoIDwgMikgcmV0dXJuIGYgPT4gaW5zcGVjdGYobiwgZik7XG4gICAgY2hlY2tmKGYpO1xuICAgIGlmKGYudG9TdHJpbmcgIT09IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZykgcmV0dXJuIGYudG9TdHJpbmcoKTtcbiAgICBjb25zdCBpID0gcGFkKG4pLCBzaG93biA9IHNob3coZiwgaSksIGxpbmVzID0gdG9MaW5lcyhzaG93biwgaSk7XG4gICAgaWYobGluZXMubGVuZ3RoIDwgMikgcmV0dXJuIHNob3duO1xuICAgIHJldHVybiBmaXhJbmRlbnRhdGlvbihsaW5lcywgaSk7XG4gIH1cblxufSkpO1xuIl19
},{}],"fluture":[function(require,module,exports){
(function (global){
//// ____ _ _
//// / ___| | | |_
//// | |__ | | _ _ | _\ _ ___ ___
//// | __|| || | | || || | | || _// _ \
//// | | | || |_| || || |_| || | | __/
//// |_| |_| \__,_||_| \__,_||_| \___\
////
(function(global, f){
'use strict';
/*istanbul ignore next*/
if(module && typeof module.exports !== 'undefined'){
module.exports = f(require('inspect-f'));
}
else{
global.Fluture = f(global.inspectf);
}
}(/*istanbul ignore next*/(global || window || this), function(inspectf){
'use strict';
///////////////////
// Type checking //
///////////////////
const TYPEOF_FUTURE = 'fluture/Future';
const FL = {
map: 'fantasy-land/map',
bimap: 'fantasy-land/bimap',
chain: 'fantasy-land/chain',
chainRec: 'fantasy-land/chainRec',
ap: 'fantasy-land/ap',
of: 'fantasy-land/of'
};
function isForkable(m){
return Boolean(m) && typeof m.fork === 'function' && m.fork.length >= 2;
}
function isFuture(m){
return (m instanceof FutureClass) || Boolean(m) && m['@@type'] === TYPEOF_FUTURE;
}
function isFunction(f){
return typeof f === 'function';
}
function isBinary(f){
return f.length >= 2;
}
function isTernary(f){
return f.length >= 3;
}
function isPositiveInteger(n){
return n === Infinity || (typeof n === 'number' && n > 0 && n % 1 === 0 && n === n);
}
function isObject(o){
return o !== null && typeof o === 'object';
}
function isIterator(i){
return isObject(i) && typeof i.next === 'function';
}
function isIteration(o){
return isObject(o) && typeof o.done === 'boolean';
}
///////////////
// Utilities //
///////////////
//A small string representing a value, but not containing the whole value.
const preview = x =>
typeof x === 'string'
? JSON.stringify(x)
: Array.isArray(x)
? `[Array: ${x.length}]`
: typeof x === 'function'
? typeof x.name === 'string' && x.name.length > 0
? `[Function: ${x.name}]`
: /*istanbul ignore next*/ '[Function]' //Only for older JS engines.
: x && typeof x === 'object'
? `[Object: ${Object.keys(x).map(String).join(', ')}]`
: String(x);
//A show function to provide a slightly more meaningful representation of values.
const show = x =>
typeof x === 'string'
? preview(x)
: Array.isArray(x)
? `[${x.map(preview).join(', ')}]`
: x && (typeof x.toString === 'function')
? x.toString === Object.prototype.toString
? `{${Object.keys(x).reduce((o, k) => o.concat(`${preview(k)}: ${preview(x[k])}`), []).join(', ')}}`
: x.toString()
: preview(x);
const noop = function noop(){};
const call = function call(f){f()};
const padf = (sf, s) => s.replace(/^/gm, sf).replace(sf, '');
const showf = f => padf(' ', inspectf(2, f));
const fid = f => f.name ? f.name : '<anonymous>';
const ordinal = ['first', 'second', 'third', 'fourth', 'fifth'];
const Next = x => ({done: false, value: x});
const Done = x => ({done: true, value: x});
//Partially apply a function with a single argument.
function unaryPartial(f, a){
return function partial(b, c, d){
switch(arguments.length){
case 1: return f(a, b);
case 2: return f(a, b, c);
default: return f(a, b, c, d);
}
};
}
//Partially apply a function with two arguments.
function binaryPartial(f, a, b){
return function partial(c, d){ return arguments.length === 1 ? f(a, b, c) : f(a, b, c, d) };
}
//Partially apply a function with three arguments.
function ternaryPartial(f, a, b, c){
return function partial(d){ return f(a, b, c, d) };
}
////////////
// Errors //
////////////
function error$invalidArgument(it, at, expected, actual){
throw new TypeError(
`${it} expects its ${ordinal[at]} argument to ${expected}\n Actual: ${show(actual)}`
);
}
function error$invalidContext(it, actual){
throw new TypeError(
`${it} was invoked outside the context of a Future. You might want to use`
+ ` a dispatcher instead\n Called on: ${show(actual)}`
)
}
function check$Future(fork){
if(!isFunction(fork)) error$invalidArgument('Future', 0, 'be a function', fork);
}
function check$fork(it, rej, res){
if(!isFuture(it)) error$invalidContext('Future#fork', it);
if(!isFunction(rej)) error$invalidArgument('Future#fork', 0, 'be a function', rej);
if(!isFunction(res)) error$invalidArgument('Future#fork', 1, 'be a function', res);
}
function check$fork$f(f, c){
if(!(f === undefined || (isFunction(f) && f.length === 0))) throw new TypeError(
'Future#fork expected the computation to return a nullary function or void'
+ `\n Actual: ${show(f)}\n From calling: ${showf(c)}`
);
}
function check$chain(it, f){
if(!isFuture(it)) error$invalidContext('Future#chain', it);
if(!isFunction(f)) error$invalidArgument('Future#chain', 0, 'be a function', f);
}
function check$chainRec(f){
if(!isFunction(f)) error$invalidArgument('Future.chainRec', 0, 'be a function', f);
}
function check$chainRec$f(m, f, i, x){
if(!isFuture(m)) throw new TypeError(
'Future.chainRec expects the function its given to return a Future every'
+ ' time it is called. The value returned from'
+ (ordinal[i] ? ` the ${ordinal[i]} call` : ` call ${i}`)
+ ' was not a Future.'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: (Next, Done, ${show(x)})`
);
}
function check$chainRec$it(it, i){
if(!isIteration(it)) throw new TypeError(
'Future.chainRec expects the function its given to return a Future of an'
+ ' Iteration every time it is called. The Future returned from'
+ (ordinal[i] ? ` the ${ordinal[i]} call` : ` call ${i}`)
+ ' did not resolve to a member of Iteration.'
+ '\n You can create an uncomplete or complete Iteration using the next'
+ ' or done functions respectively. These are passed into your callback'
+ ' as first and second arguments.'
+ `\n Actual: Future.of(${show(it)})`
);
}
function check$recur(it, f){
if(!isFuture(it)) error$invalidContext('Future#recur', it);
if(!isFunction(f)) error$invalidArgument('Future#recur', 0, 'be a function', f);
}
function check$chain$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#chain expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function check$recur$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#recur expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function check$chainRej(it, f){
if(!isFuture(it)) error$invalidContext('Future.chainRej', it);
if(!isFunction(f)) error$invalidArgument('Future.chainRej', 0, 'a function', f);
}
function check$chainRej$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future.chainRej expects the function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function check$map(it, f){
if(!isFuture(it)) error$invalidContext('Future#map', it);
if(!isFunction(f)) error$invalidArgument('Future#map', 0, 'be a function', f);
}
function check$mapRej(it, f){
if(!isFuture(it)) error$invalidContext('Future#mapRej', it);
if(!isFunction(f)) error$invalidArgument('Future#mapRej', 0, 'be a function', f);
}
function check$bimap(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#bimap', it);
if(!isFunction(f)) error$invalidArgument('Future#bimap', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#bimap', 1, 'be a function', g);
}
function check$ap(it, m){
if(!isFuture(it)) error$invalidContext('Future#ap', it);
if(!isFuture(m)) error$invalidArgument('Future#ap', 0, 'be a Future', m);
}
function check$ap$f(f){
if(!isFunction(f)) throw new TypeError(
'Future#ap expects its first argument to be a Future of a Function'
+ `\n Actual: Future.of(${show(f)})`
);
}
function check$swap(it){
if(!isFuture(it)) error$invalidContext('Future#swap', it);
}
function check$race(it, m){
if(!isFuture(it)) error$invalidContext('Future#race', it);
if(!isFuture(m)) error$invalidArgument('Future#race', 0, 'be a Future', m);
}
function check$or(it, m){
if(!isFuture(it)) error$invalidContext('Future#or', it);
if(!isFuture(m)) error$invalidArgument('Future#or', 0, 'be a Future', m);
}
function check$fold(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#fold', it);
if(!isFunction(f)) error$invalidArgument('Future#fold', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#fold', 1, 'be a function', g);
}
function check$hook(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#hook', it);
if(!isFunction(f)) error$invalidArgument('Future#hook', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#hook', 1, 'be a function', g);
}
function check$hook$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the first function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function check$hook$g(m, g, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the second function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(g)}\n With: ${show(x)}`
);
}
function check$finally(it, m){
if(!isFuture(it)) error$invalidContext('Future#finally', it);
if(!isFuture(m)) error$invalidArgument('Future#finally', 0, 'be a Future', m);
}
function check$value(it, f){
if(!isFuture(it)) error$invalidContext('Future#value', it);
if(!isFunction(f)) error$invalidArgument('Future#value', 0, 'be a function', f);
}
function check$promise(it){
if(!isFuture(it)) error$invalidContext('Future#promise', it);
}
function check$cache(it){
if(!isFuture(it)) error$invalidContext('Future#cache', it);
}
function check$after(n){
if(typeof n !== 'number') error$invalidArgument('Future.after', 0, 'be a number', n);
}
function check$cast(m){
if(!isForkable(m)) error$invalidArgument('Future.cast', 0, 'be a Forkable', m);
}
function check$encase(f){
if(!isFunction(f)) error$invalidArgument('Future.encase', 0, 'be a function', f);
}
function check$encase2(f){
if(!isFunction(f)) error$invalidArgument('Future.encase2', 0, 'be a function', f);
if(!isBinary(f)) error$invalidArgument('Future.encase2', 0, 'take two arguments', f);
}
function check$encase3(f){
if(!isFunction(f)) error$invalidArgument('Future.encase3', 0, 'be a function', f);
if(!isTernary(f)) error$invalidArgument('Future.encase3', 0, 'take three arguments', f);
}
function check$node(f){
if(!isFunction(f)) error$invalidArgument('Future.node', 0, 'be a function', f);
}
function check$parallel(i, ms){
if(!isPositiveInteger(i)) error$invalidArgument('Future.parallel', 0, 'be a positive integer', i);
if(!Array.isArray(ms)) error$invalidArgument('Future.parallel', 1, 'be an array', ms);
}
function check$parallel$m(m, i){
if(!isFuture(m)) throw new TypeError(
'Future.parallel expects its second argument to be an array of Futures.'
+ ` The value at position ${i} in the array was not a Future\n Actual: ${show(m)}`
);
}
function check$do(f){
if(!isFunction(f)) error$invalidArgument('Future.do', 0, 'be a function', f);
}
function check$do$g(g){
if(!isIterator(g)) error$invalidArgument(
'Future.do', 0, 'return an iterator, maybe you forgot the "*"', g
);
}
function check$do$next(o){
if(!isIteration(o)) throw new TypeError(
'Future.do was given an invalid generator:'
+ ' Its iterator did not return a valid iteration from iterator.next()'
+ `\n Actual: ${show(o)}`
);
if(!o.done && !isFuture(o.value)) throw new TypeError(
'A non-Future was produced by iterator.next() in Future.do.'
+ ' If you\'re using a generator, make sure you always `yield` a Future'
+ `\n Actual: ${o.value}`
);
}
////////////
// Future //
////////////
function FutureClass(safe, f){
this._f = safe === true ? Future$safeFork : f;
this._raw = f;
}
function Future(f){
check$Future(f);
return new FutureClass(true, f);
}
function Future$of(x){
return new FutureClass(false, function Future$of$fork(rej, res){
res(x);
return noop;
});
}
function Future$chainRec(f, init){
if(arguments.length === 1) return unaryPartial(Future$chainRec, f);
check$chainRec(f);
return new FutureClass(false, function(rej, res){
let cancel = noop, i = 0;
(function Future$chainRec$recur(state){
let isSync = null;
function Future$chainRec$res(it){
check$chainRec$it(it, i);
i = i + 1;
if(isSync === null){
isSync = true;
state = it;
}else{
Future$chainRec$recur(it);
}
}
while(!state.done){
isSync = null;
const m = f(Next, Done, state.value);
check$chainRec$f(m, f, i, state.value);
cancel = m._f(rej, Future$chainRec$res);
if(isSync === true){
continue;
}else{
isSync = false;
return;
}
}
res(state.value);
}(Next(init)));
return function Future$chainRec$cancel(){ cancel() };
});
}
function Future$fork(rej, res){
check$fork(this, rej, res);
return this._f(rej, res);
}
function Future$safeFork(rej, res){
let open = true;
const f = this._raw(function Future$safeFork$rej(x){
if(open){
open = false;
rej(x);
}
}, function Future$safeFork$res(x){
if(open){
open = false;
res(x);
}
});
check$fork$f(f, this._raw);
return function Future$safeFork$cancel(){
open && f && f();
open = false;
};
}
function Future$chain(f){
check$chain(this, f);
const _this = this;
return new FutureClass(false, function Future$chain$fork(rej, res){
let cancel;
const r = _this._f(rej, function Future$chain$res(x){
const m = f(x);
check$chain$f(m, f, x);
cancel = m._f(rej, res);
});
return cancel ? cancel : (cancel = r, function Future$chain$cancel(){ cancel() });
});
}
function Future$recur(f){
check$recur(this, f);
const _this = this;
return new FutureClass(false, function Future$chain$fork(rej, res){
return _this._f(rej, function Future$chain$res(x){
const m = f(x);
check$recur$f(m, f, x);
m._f(rej, res);
});
});
}
function Future$chainRej(f){
check$chainRej(this, f);
const _this = this;
return new FutureClass(false, function Future$chainRej$fork(rej, res){
let cancel;
const r = _this._f(function Future$chainRej$rej(x){
const m = f(x);
check$chainRej$f(m, f, x);
cancel = m._f(rej, res);
}, res);
return cancel ? cancel : (cancel = r, function Future$chainRej$cancel(){ cancel() });
});
}
function Future$map(f){
check$map(this, f);
const _this = this;
return new FutureClass(false, function Future$map$fork(rej, res){
return _this._f(rej, function Future$map$res(x){
res(f(x));
});
});
}
function Future$mapRej(f){
check$mapRej(this, f);
const _this = this;
return new FutureClass(false, function Future$mapRej$fork(rej, res){
return _this._f(function Future$mapRej$rej(x){
rej(f(x));
}, res);
});
}
function Future$bimap(f, g){
check$bimap(this, f, g);
const _this = this;
return new FutureClass(false, function Future$bimap$fork(rej, res){
return _this._f(function Future$bimap$rej(x){
rej(f(x));
}, function Future$bimap$res(x){
res(g(x));
});
});
}
function Future$ap(m){
check$ap(this, m);
const _this = this;
return new FutureClass(false, function Future$ap$fork(g, res){
let _f, _x, ok1, ok2, ko;
const rej = x => ko || (ko = 1, g(x));
const c1 = _this._f(rej, function Future$ap$resThis(x){
if(!ok1) return void (ok2 = 1, _x = x)
check$ap$f(_f);
res(_f(x));
});
const c2 = m._f(rej, function Future$ap$resThat(f){
if(!ok2) return void (ok1 = 1, _f = f);
check$ap$f(f);
res(f(_x));
});
return function Future$ap$cancel(){ c1(); c2() };
});
}
function Future$swap(){
check$swap(this);
const _this = this;
return new FutureClass(false, function Future$swap$fork(rej, res){
return _this._f(res, rej);
});
}
function Future$toString(){
return `Future(${this._raw.toString()})`;
}
function Future$race(m){
check$race(this, m);
const _this = this;
return new FutureClass(false, function Future$race$fork(rej, res){
let settled = false, c1 = noop, c2 = noop;
const once = f => a => settled || (settled = true, c1(), c2(), f(a));
c1 = _this._f(once(rej), once(res));
c2 = m._f(once(rej), once(res));
return function Future$race$cancel(){ c1(); c2() };
});
}
function Future$or(m){
check$or(this, m);
const _this = this;
return new FutureClass(false, function Future$or$fork(rej, res){
let ok = false, ko = false, val, err;
const c1 = _this._f(
() => ko ? rej(err) : ok ? res(val) : (ko = true),
x => (ok = true, res(x))
);
const c2 = m._f(
e => ok || (ko ? rej(e) : (err = e, ko = true)),
x => ok || (ko ? res(x) : (val = x, ok = true))
);
return function Future$or$cancel(){ c1(); c2() };
});
}
function Future$fold(f, g){
check$fold(this, f, g);
const _this = this;
return new FutureClass(false, function Future$fold$fork(rej, res){
return _this._f(e => res(f(e)), x => res(g(x)));
});
}
function Future$hook(dispose, consume){
check$hook(this, dispose, consume);
const _this = this;
return new FutureClass(false, function Future$hook$fork(rej, res){
let cancel;
const ret = _this._f(rej, function Future$hook$res(resource){
const m = consume(resource);
check$hook$g(m, consume, resource);
cancel = m._f(e => {
const c = dispose(resource);
check$hook$f(c, dispose, resource);
c._f(rej, _ => rej(e));
}, x => {
const c = dispose(resource);
check$hook$f(c, dispose, resource);
c._f(rej, _ => res(x));
});
});
cancel = cancel || ret;
return function Future$hook$cancel(){ cancel() };
});
}
function Future$finally(m){
check$finally(this, m);
const _this = this;
return new FutureClass(false, function Future$finally$fork(rej, res){
let cancel;
const r = _this._f(function Future$finally$rej(e){
cancel = m._f(rej, function Future$finally$rej$res(){ rej(e) });
}, function Future$finally$res(x){
cancel = m._f(rej, function Future$finally$res$res(){ res(x) });
});
return cancel ? cancel : (cancel = r, function Future$finally$cancel(){ cancel() });
});
}
function Future$value(f){
check$value(this, f);
return this._f(
function Future$value$rej(e){
throw new Error(
`Future#value was called on a rejected Future\n Actual: Future.reject(${show(e)})`
);
},
f
);
}
function Future$promise(){
check$promise(this);
const _this = this;
return new Promise(function Future$promise$do(resolve, reject){
_this._f(reject, resolve);
});
}
function Future$cache(){
check$cache(this);
const _this = this;
let que = [];
let value, state;
const settleWith = newState => function Future$cache$settle(newValue){
value = newValue; state = newState;
for(let i = 0, l = que.length; i < l; i++){
que[i][state](value);
que[i] = undefined;
}
que = undefined;
};
return new FutureClass(false, function Future$cache$fork(rej, res){
let cancel = noop;
switch(state){
case 1: que.push({2: rej, 3: res}); break;
case 2: rej(value); break;
case 3: res(value); break;
default:
state = 1;
que.push({2: rej, 3: res});
cancel = _this._f(settleWith(2), settleWith(3));
}
return function Future$cache$cancel(){
que = [];
value = undefined;
state = undefined;
cancel();
};
});
}
FutureClass.prototype = Future.prototype = {
'@@type': TYPEOF_FUTURE,
_f: null,
fork: Future$fork,
[FL.of]: Future$of,
of: Future$of,
[FL.chainRec]: Future$chainRec,
[FL.chain]: Future$chain,
chain: Future$chain,
recur: Future$recur,
chainRej: Future$chainRej,
[FL.map]: Future$map,
map: Future$map,
mapRej: Future$mapRej,
[FL.bimap]: Future$bimap,
bimap: Future$bimap,
[FL.ap]: Future$ap,
ap: Future$ap,
swap: Future$swap,
toString: Future$toString,
inspect: Future$toString,
race: Future$race,
or: Future$or,
fold: Future$fold,
hook: Future$hook,
finally: Future$finally,
value: Future$value,
promise: Future$promise,
cache: Future$cache
};
Future[FL.of] = Future.of = Future$of;
Future[FL.chainRec] = Future.chainRec = Future$chainRec;
Future.Future = Future;
Future.util = {
Next,
Done,
isForkable,
isFuture,
isFunction,
isBinary,
isTernary,
isPositiveInteger,
isObject,
isIterator,
isIteration,
preview,
show,
padf,
showf,
fid,
unaryPartial,
binaryPartial,
ternaryPartial
};
/////////////////
// Dispatchers //
/////////////////
//Creates a dispatcher for a nullary method.
function createNullaryDispatcher(method){
return function nullaryDispatch(m){
if(m && typeof m[method] === 'function') return m[method]();
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
};
}
//Creates a dispatcher for a unary method.
function createUnaryDispatcher(method){
return function unaryDispatch(a, m){
if(arguments.length === 1) return unaryPartial(unaryDispatch, a);
if(m && typeof m[method] === 'function') return m[method](a);
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
};
}
//Creates a dispatcher for a binary method.
function createBinaryDispatcher(method){
return function binaryDispatch(a, b, m){
if(arguments.length === 1) return unaryPartial(binaryDispatch, a);
if(arguments.length === 2) return binaryPartial(binaryDispatch, a, b);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 2, `have a "${method}" method`, m);
};
}
//Creates a dispatcher for a binary method, but takes the object first rather than last.
function createInvertedBinaryDispatcher(method){
return function invertedBinaryDispatch(m, a, b){
if(arguments.length === 1) return unaryPartial(invertedBinaryDispatch, m);
if(arguments.length === 2) return binaryPartial(invertedBinaryDispatch, m, a);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 0, `have a "${method}" method`, m);
};
}
Future.chain = createUnaryDispatcher(FL.chain);
Future.recur = createUnaryDispatcher('recur');
Future.chainRej = createUnaryDispatcher('chainRej');
Future.map = createUnaryDispatcher(FL.map);
Future.mapRej = createUnaryDispatcher('mapRej');
Future.bimap = createBinaryDispatcher(FL.bimap);
Future.ap = createUnaryDispatcher(FL.ap);
Future.swap = createNullaryDispatcher('swap');
Future.fork = createBinaryDispatcher('fork');
Future.race = createUnaryDispatcher('race');
Future.or = createUnaryDispatcher('or');
Future.fold = createBinaryDispatcher('fold');
Future.hook = createInvertedBinaryDispatcher('hook');
Future.finally = createUnaryDispatcher('finally');
Future.value = createUnaryDispatcher('value');
Future.promise = createNullaryDispatcher('promise');
Future.cache = createNullaryDispatcher('cache');
/////////////////////
// Other functions //
/////////////////////
Future.isFuture = isFuture;
Future.isForkable = isForkable;
Future.reject = function Future$reject(x){
return new FutureClass(false, function Future$reject$fork(rej){
rej(x);
return noop;
});
};
Future.after = function Future$after(n, x){
if(arguments.length === 1) return unaryPartial(Future.after, n);
check$after(n);
return new FutureClass(false, function Future$after$fork(rej, res){
const t = setTimeout(res, n, x);
return function Future$after$cancel(){ clearTimeout(t) };
});
};
Future.cast = function Future$cast(m){
check$cast(m);
return new FutureClass(true, function Future$cast$fork(rej, res){
m.fork(rej, res);
});
};
Future.encase = function Future$encase(f, x){
check$encase(f);
if(arguments.length === 1) return unaryPartial(Future.encase, f);
return new FutureClass(false, function Future$encase$fork(rej, res){
let r;
try{ r = f(x) }catch(e){ return void rej(e) }
res(r);
return noop;
});
};
Future.encase2 = function Future$encase2(f, x, y){
check$encase2(f);
if(arguments.length === 1) return unaryPartial(Future.encase2, f);
if(arguments.length === 2) return binaryPartial(Future.encase2, f, x);
return new FutureClass(false, function Future$encase2$fork(rej, res){
let r;
try{ r = f(x, y) }catch(e){ return void rej(e) }
res(r);
return noop;
});
};
Future.encase3 = function Future$encase3(f, x, y, z){
check$encase3(f);
if(arguments.length === 1) return unaryPartial(Future.encase3, f);
if(arguments.length === 2) return binaryPartial(Future.encase3, f, x);
if(arguments.length === 3) return ternaryPartial(Future.encase3, f, x, y);
return new FutureClass(false, function Future$encase3$fork(rej, res){
let r;
try{ r = f(x, y, z) }catch(e){ return void rej(e) }
res(r);
return noop;
});
};
Future.try = function Future$try(f){
return Future.encase(f, undefined);
};
Future.node = function Future$node(f){
check$node(f);
return new FutureClass(true, function Future$node$fork(rej, res){
f(function Future$node$done(a, b){
a ? rej(a) : res(b);
});
});
};
Future.parallel = function Future$parallel(i, ms){
if(arguments.length === 1) return unaryPartial(Future.parallel, i);
check$parallel(i, ms);
const l = ms.length;
return l < 1 ? Future$of([]) : new FutureClass(false, function Future$parallel$fork(rej, res){
let ko = false;
let ok = 0;
const cs = [];
const out = new Array(l);
const next = j => i < l ? fork(ms[i], i++) : (j === l && res(out));
const fork = (m, j) => (check$parallel$m(m, j), cs[j] = m._f(
e => ko || (rej(e), ko = true),
x => ko || (out[j] = x, next(++ok))
));
ms.slice(0, i).forEach(fork);
return function Future$parallel$cancel(){ cs.forEach(call) };
});
};
Future.do = function Future$do(f){
check$do(f);
return new FutureClass(false, function Future$do$fork(rej, res){
const g = f();
check$do$g(g);
return Future$chainRec(function Future$do$next(next, _, x){
const o = g.next(x);
check$do$next(o);
return o.done ? Future$of(o) : o.value.map(next);
}, undefined)._f(rej, res);
});
};
return Future;
}));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZsdXR1cmUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiLy8vLyAgICAgIF9fX18gXyAgICAgICAgIF9cbi8vLy8gICAgIC8gX19ffCB8ICAgICAgIHwgfF9cbi8vLy8gICAgfCB8X18gfCB8IF8gICBfIHwgIF9cXCAgIF8gIF9fXyAgX19fXG4vLy8vICAgIHwgIF9ffHwgfHwgfCB8IHx8IHx8IHwgfCB8fCAgXy8vIF8gXFxcbi8vLy8gICAgfCB8ICAgfCB8fCB8X3wgfHwgfHwgfF98IHx8IHwgfCAgX18vXG4vLy8vICAgIHxffCAgIHxffCBcXF9fLF98fF98IFxcX18sX3x8X3wgIFxcX19fXFxcbi8vLy9cbihmdW5jdGlvbihnbG9iYWwsIGYpe1xuXG4gICd1c2Ugc3RyaWN0JztcblxuICAvKmlzdGFuYnVsIGlnbm9yZSBuZXh0Ki9cbiAgaWYobW9kdWxlICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpe1xuICAgIG1vZHVsZS5leHBvcnRzID0gZihyZXF1aXJlKCdpbnNwZWN0LWYnKSk7XG4gIH1cblxuICBlbHNle1xuICAgIGdsb2JhbC5GbHV0dXJlID0gZihnbG9iYWwuaW5zcGVjdGYpO1xuICB9XG5cbn0oLyppc3RhbmJ1bCBpZ25vcmUgbmV4dCovKGdsb2JhbCB8fCB3aW5kb3cgfHwgdGhpcyksIGZ1bmN0aW9uKGluc3BlY3RmKXtcblxuICAndXNlIHN0cmljdCc7XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBUeXBlIGNoZWNraW5nIC8vXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBjb25zdCBUWVBFT0ZfRlVUVVJFID0gJ2ZsdXR1cmUvRnV0dXJlJztcbiAgY29uc3QgRkwgPSB7XG4gICAgbWFwOiAnZmFudGFzeS1sYW5kL21hcCcsXG4gICAgYmltYXA6ICdmYW50YXN5LWxhbmQvYmltYXAnLFxuICAgIGNoYWluOiAnZmFudGFzeS1sYW5kL2NoYWluJyxcbiAgICBjaGFpblJlYzogJ2ZhbnRhc3ktbGFuZC9jaGFpblJlYycsXG4gICAgYXA6ICdmYW50YXN5LWxhbmQvYXAnLFxuICAgIG9mOiAnZmFudGFzeS1sYW5kL29mJ1xuICB9O1xuXG4gIGZ1bmN0aW9uIGlzRm9ya2FibGUobSl7XG4gICAgcmV0dXJuIEJvb2xlYW4obSkgJiYgdHlwZW9mIG0uZm9yayA9PT0gJ2Z1bmN0aW9uJyAmJiBtLmZvcmsubGVuZ3RoID49IDI7XG4gIH1cblxuICBmdW5jdGlvbiBpc0Z1dHVyZShtKXtcbiAgICByZXR1cm4gKG0gaW5zdGFuY2VvZiBGdXR1cmVDbGFzcykgfHwgQm9vbGVhbihtKSAmJiBtWydAQHR5cGUnXSA9PT0gVFlQRU9GX0ZVVFVSRTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRnVuY3Rpb24oZil7XG4gICAgcmV0dXJuIHR5cGVvZiBmID09PSAnZnVuY3Rpb24nO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNCaW5hcnkoZil7XG4gICAgcmV0dXJuIGYubGVuZ3RoID49IDI7XG4gIH1cblxuICBmdW5jdGlvbiBpc1Rlcm5hcnkoZil7XG4gICAgcmV0dXJuIGYubGVuZ3RoID49IDM7XG4gIH1cblxuICBmdW5jdGlvbiBpc1Bvc2l0aXZlSW50ZWdlcihuKXtcbiAgICByZXR1cm4gbiA9PT0gSW5maW5pdHkgfHwgKHR5cGVvZiBuID09PSAnbnVtYmVyJyAmJiBuID4gMCAmJiBuICUgMSA9PT0gMCAmJiBuID09PSBuKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzT2JqZWN0KG8pe1xuICAgIHJldHVybiBvICE9PSBudWxsICYmIHR5cGVvZiBvID09PSAnb2JqZWN0JztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzSXRlcmF0b3IoaSl7XG4gICAgcmV0dXJuIGlzT2JqZWN0KGkpICYmIHR5cGVvZiBpLm5leHQgPT09ICdmdW5jdGlvbic7XG4gIH1cblxuICBmdW5jdGlvbiBpc0l0ZXJhdGlvbihvKXtcbiAgICByZXR1cm4gaXNPYmplY3QobykgJiYgdHlwZW9mIG8uZG9uZSA9PT0gJ2Jvb2xlYW4nO1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFV0aWxpdGllcyAvL1xuICAvLy8vLy8vLy8vLy8vLy9cblxuICAvL0Egc21hbGwgc3RyaW5nIHJlcHJlc2VudGluZyBhIHZhbHVlLCBidXQgbm90IGNvbnRhaW5pbmcgdGhlIHdob2xlIHZhbHVlLlxuICBjb25zdCBwcmV2aWV3ID0geCA9PlxuICAgIHR5cGVvZiB4ID09PSAnc3RyaW5nJ1xuICAgID8gSlNPTi5zdHJpbmdpZnkoeClcbiAgICA6IEFycmF5LmlzQXJyYXkoeClcbiAgICA/IGBbQXJyYXk6ICR7eC5sZW5ndGh9XWBcbiAgICA6IHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nXG4gICAgPyB0eXBlb2YgeC5uYW1lID09PSAnc3RyaW5nJyAmJiB4Lm5hbWUubGVuZ3RoID4gMFxuICAgID8gYFtGdW5jdGlvbjogJHt4Lm5hbWV9XWBcbiAgICA6IC8qaXN0YW5idWwgaWdub3JlIG5leHQqLyAnW0Z1bmN0aW9uXScgLy9Pbmx5IGZvciBvbGRlciBKUyBlbmdpbmVzLlxuICAgIDogeCAmJiB0eXBlb2YgeCA9PT0gJ29iamVjdCdcbiAgICA/IGBbT2JqZWN0OiAke09iamVjdC5rZXlzKHgpLm1hcChTdHJpbmcpLmpvaW4oJywgJyl9XWBcbiAgICA6IFN0cmluZyh4KTtcblxuICAvL0Egc2hvdyBmdW5jdGlvbiB0byBwcm92aWRlIGEgc2xpZ2h0bHkgbW9yZSBtZWFuaW5nZnVsIHJlcHJlc2VudGF0aW9uIG9mIHZhbHVlcy5cbiAgY29uc3Qgc2hvdyA9IHggPT5cbiAgICB0eXBlb2YgeCA9PT0gJ3N0cmluZydcbiAgICA/IHByZXZpZXcoeClcbiAgICA6IEFycmF5LmlzQXJyYXkoeClcbiAgICA/IGBbJHt4Lm1hcChwcmV2aWV3KS5qb2luKCcsICcpfV1gXG4gICAgOiB4ICYmICh0eXBlb2YgeC50b1N0cmluZyA9PT0gJ2Z1bmN0aW9uJylcbiAgICA/IHgudG9TdHJpbmcgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdcbiAgICA/IGB7JHtPYmplY3Qua2V5cyh4KS5yZWR1Y2UoKG8sIGspID0+IG8uY29uY2F0KGAke3ByZXZpZXcoayl9OiAke3ByZXZpZXcoeFtrXSl9YCksIFtdKS5qb2luKCcsICcpfX1gXG4gICAgOiB4LnRvU3RyaW5nKClcbiAgICA6IHByZXZpZXcoeCk7XG5cbiAgY29uc3Qgbm9vcCA9IGZ1bmN0aW9uIG5vb3AoKXt9O1xuICBjb25zdCBjYWxsID0gZnVuY3Rpb24gY2FsbChmKXtmKCl9O1xuICBjb25zdCBwYWRmID0gKHNmLCBzKSA9PiBzLnJlcGxhY2UoL14vZ20sIHNmKS5yZXBsYWNlKHNmLCAnJyk7XG4gIGNvbnN0IHNob3dmID0gZiA9PiBwYWRmKCcgICcsIGluc3BlY3RmKDIsIGYpKTtcbiAgY29uc3QgZmlkID0gZiA9PiBmLm5hbWUgPyBmLm5hbWUgOiAnPGFub255bW91cz4nO1xuICBjb25zdCBvcmRpbmFsID0gWydmaXJzdCcsICdzZWNvbmQnLCAndGhpcmQnLCAnZm91cnRoJywgJ2ZpZnRoJ107XG4gIGNvbnN0IE5leHQgPSB4ID0+ICh7ZG9uZTogZmFsc2UsIHZhbHVlOiB4fSk7XG4gIGNvbnN0IERvbmUgPSB4ID0+ICh7ZG9uZTogdHJ1ZSwgdmFsdWU6IHh9KTtcblxuICAvL1BhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIHdpdGggYSBzaW5nbGUgYXJndW1lbnQuXG4gIGZ1bmN0aW9uIHVuYXJ5UGFydGlhbChmLCBhKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gcGFydGlhbChiLCBjLCBkKXtcbiAgICAgIHN3aXRjaChhcmd1bWVudHMubGVuZ3RoKXtcbiAgICAgICAgY2FzZSAxOiByZXR1cm4gZihhLCBiKTtcbiAgICAgICAgY2FzZSAyOiByZXR1cm4gZihhLCBiLCBjKTtcbiAgICAgICAgZGVmYXVsdDogcmV0dXJuIGYoYSwgYiwgYywgZCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8vUGFydGlhbGx5IGFwcGx5IGEgZnVuY3Rpb24gd2l0aCB0d28gYXJndW1lbnRzLlxuICBmdW5jdGlvbiBiaW5hcnlQYXJ0aWFsKGYsIGEsIGIpe1xuICAgIHJldHVybiBmdW5jdGlvbiBwYXJ0aWFsKGMsIGQpeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGYoYSwgYiwgYykgOiBmKGEsIGIsIGMsIGQpIH07XG4gIH1cblxuICAvL1BhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIHdpdGggdGhyZWUgYXJndW1lbnRzLlxuICBmdW5jdGlvbiB0ZXJuYXJ5UGFydGlhbChmLCBhLCBiLCBjKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gcGFydGlhbChkKXsgcmV0dXJuIGYoYSwgYiwgYywgZCkgfTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vL1xuICAvLyBFcnJvcnMgLy9cbiAgLy8vLy8vLy8vLy8vXG5cbiAgZnVuY3Rpb24gZXJyb3IkaW52YWxpZEFyZ3VtZW50KGl0LCBhdCwgZXhwZWN0ZWQsIGFjdHVhbCl7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgIGAke2l0fSBleHBlY3RzIGl0cyAke29yZGluYWxbYXRdfSBhcmd1bWVudCB0byAke2V4cGVjdGVkfVxcbiAgQWN0dWFsOiAke3Nob3coYWN0dWFsKX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVycm9yJGludmFsaWRDb250ZXh0KGl0LCBhY3R1YWwpe1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICBgJHtpdH0gd2FzIGludm9rZWQgb3V0c2lkZSB0aGUgY29udGV4dCBvZiBhIEZ1dHVyZS4gWW91IG1pZ2h0IHdhbnQgdG8gdXNlYFxuICAgICAgKyBgIGEgZGlzcGF0Y2hlciBpbnN0ZWFkXFxuICBDYWxsZWQgb246ICR7c2hvdyhhY3R1YWwpfWBcbiAgICApXG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRGdXR1cmUoZm9yayl7XG4gICAgaWYoIWlzRnVuY3Rpb24oZm9yaykpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmb3JrKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGZvcmsoaXQsIHJlaiwgcmVzKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2ZvcmsnLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24ocmVqKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjZm9yaycsIDAsICdiZSBhIGZ1bmN0aW9uJywgcmVqKTtcbiAgICBpZighaXNGdW5jdGlvbihyZXMpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNmb3JrJywgMSwgJ2JlIGEgZnVuY3Rpb24nLCByZXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skZm9yayRmKGYsIGMpe1xuICAgIGlmKCEoZiA9PT0gdW5kZWZpbmVkIHx8IChpc0Z1bmN0aW9uKGYpICYmIGYubGVuZ3RoID09PSAwKSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlI2ZvcmsgZXhwZWN0ZWQgdGhlIGNvbXB1dGF0aW9uIHRvIHJldHVybiBhIG51bGxhcnkgZnVuY3Rpb24gb3Igdm9pZCdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke3Nob3coZil9XFxuICBGcm9tIGNhbGxpbmc6ICR7c2hvd2YoYyl9YFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRjaGFpbihpdCwgZil7XG4gICAgaWYoIWlzRnV0dXJlKGl0KSkgZXJyb3IkaW52YWxpZENvbnRleHQoJ0Z1dHVyZSNjaGFpbicsIGl0KTtcbiAgICBpZighaXNGdW5jdGlvbihmKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjY2hhaW4nLCAwLCAnYmUgYSBmdW5jdGlvbicsIGYpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skY2hhaW5SZWMoZil7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLmNoYWluUmVjJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNoYWluUmVjJGYobSwgZiwgaSwgeCl7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZS5jaGFpblJlYyBleHBlY3RzIHRoZSBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlIGV2ZXJ5J1xuICAgICAgKyAnIHRpbWUgaXQgaXMgY2FsbGVkLiBUaGUgdmFsdWUgcmV0dXJuZWQgZnJvbSdcbiAgICAgICsgKG9yZGluYWxbaV0gPyBgIHRoZSAke29yZGluYWxbaV19IGNhbGxgIDogYCBjYWxsICR7aX1gKVxuICAgICAgKyAnIHdhcyBub3QgYSBGdXR1cmUuJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6IChOZXh0LCBEb25lLCAke3Nob3coeCl9KWBcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skY2hhaW5SZWMkaXQoaXQsIGkpe1xuICAgIGlmKCFpc0l0ZXJhdGlvbihpdCkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlLmNoYWluUmVjIGV4cGVjdHMgdGhlIGZ1bmN0aW9uIGl0cyBnaXZlbiB0byByZXR1cm4gYSBGdXR1cmUgb2YgYW4nXG4gICAgICArICcgSXRlcmF0aW9uIGV2ZXJ5IHRpbWUgaXQgaXMgY2FsbGVkLiBUaGUgRnV0dXJlIHJldHVybmVkIGZyb20nXG4gICAgICArIChvcmRpbmFsW2ldID8gYCB0aGUgJHtvcmRpbmFsW2ldfSBjYWxsYCA6IGAgY2FsbCAke2l9YClcbiAgICAgICsgJyBkaWQgbm90IHJlc29sdmUgdG8gYSBtZW1iZXIgb2YgSXRlcmF0aW9uLidcbiAgICAgICsgJ1xcbiAgWW91IGNhbiBjcmVhdGUgYW4gdW5jb21wbGV0ZSBvciBjb21wbGV0ZSBJdGVyYXRpb24gdXNpbmcgdGhlIG5leHQnXG4gICAgICArICcgb3IgZG9uZSBmdW5jdGlvbnMgcmVzcGVjdGl2ZWx5LiBUaGVzZSBhcmUgcGFzc2VkIGludG8geW91ciBjYWxsYmFjaydcbiAgICAgICsgJyBhcyBmaXJzdCBhbmQgc2Vjb25kIGFyZ3VtZW50cy4nXG4gICAgICArIGBcXG4gIEFjdHVhbDogRnV0dXJlLm9mKCR7c2hvdyhpdCl9KWBcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skcmVjdXIoaXQsIGYpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjcmVjdXInLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI3JlY3VyJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNoYWluJGYobSwgZiwgeCl7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZSNjaGFpbiBleHBlY3RzIHRoZSBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6ICR7c2hvdyh4KX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJHJlY3VyJGYobSwgZiwgeCl7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZSNyZWN1ciBleHBlY3RzIHRoZSBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6ICR7c2hvdyh4KX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNoYWluUmVqKGl0LCBmKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlLmNoYWluUmVqJywgaXQpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5jaGFpblJlaicsIDAsICdhIGZ1bmN0aW9uJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRjaGFpblJlaiRmKG0sIGYsIHgpe1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdGdXR1cmUuY2hhaW5SZWogZXhwZWN0cyB0aGUgZnVuY3Rpb24gaXRzIGdpdmVuIHRvIHJldHVybiBhIEZ1dHVyZSdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke3Nob3cobSl9XFxuICBGcm9tIGNhbGxpbmc6ICR7c2hvd2YoZil9XFxuICBXaXRoOiAke3Nob3coeCl9YFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRtYXAoaXQsIGYpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjbWFwJywgaXQpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNtYXAnLCAwLCAnYmUgYSBmdW5jdGlvbicsIGYpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skbWFwUmVqKGl0LCBmKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI21hcFJlaicsIGl0KTtcbiAgICBpZighaXNGdW5jdGlvbihmKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjbWFwUmVqJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGJpbWFwKGl0LCBmLCBnKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2JpbWFwJywgaXQpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNiaW1hcCcsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gICAgaWYoIWlzRnVuY3Rpb24oZykpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI2JpbWFwJywgMSwgJ2JlIGEgZnVuY3Rpb24nLCBnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGFwKGl0LCBtKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2FwJywgaXQpO1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjYXAnLCAwLCAnYmUgYSBGdXR1cmUnLCBtKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGFwJGYoZil7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlI2FwIGV4cGVjdHMgaXRzIGZpcnN0IGFyZ3VtZW50IHRvIGJlIGEgRnV0dXJlIG9mIGEgRnVuY3Rpb24nXG4gICAgICArIGBcXG4gIEFjdHVhbDogRnV0dXJlLm9mKCR7c2hvdyhmKX0pYFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRzd2FwKGl0KXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI3N3YXAnLCBpdCk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRyYWNlKGl0LCBtKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI3JhY2UnLCBpdCk7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNyYWNlJywgMCwgJ2JlIGEgRnV0dXJlJywgbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRvcihpdCwgbSl7XG4gICAgaWYoIWlzRnV0dXJlKGl0KSkgZXJyb3IkaW52YWxpZENvbnRleHQoJ0Z1dHVyZSNvcicsIGl0KTtcbiAgICBpZighaXNGdXR1cmUobSkpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI29yJywgMCwgJ2JlIGEgRnV0dXJlJywgbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRmb2xkKGl0LCBmLCBnKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2ZvbGQnLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI2ZvbGQnLCAwLCAnYmUgYSBmdW5jdGlvbicsIGYpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGcpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNmb2xkJywgMSwgJ2JlIGEgZnVuY3Rpb24nLCBnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGhvb2soaXQsIGYsIGcpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjaG9vaycsIGl0KTtcbiAgICBpZighaXNGdW5jdGlvbihmKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjaG9vaycsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gICAgaWYoIWlzRnVuY3Rpb24oZykpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI2hvb2snLCAxLCAnYmUgYSBmdW5jdGlvbicsIGcpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skaG9vayRmKG0sIGYsIHgpe1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdGdXR1cmUjaG9vayBleHBlY3RzIHRoZSBmaXJzdCBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6ICR7c2hvdyh4KX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGhvb2skZyhtLCBnLCB4KXtcbiAgICBpZighaXNGdXR1cmUobSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlI2hvb2sgZXhwZWN0cyB0aGUgc2Vjb25kIGZ1bmN0aW9uIGl0cyBnaXZlbiB0byByZXR1cm4gYSBGdXR1cmUnXG4gICAgICArIGBcXG4gIEFjdHVhbDogJHtzaG93KG0pfVxcbiAgRnJvbSBjYWxsaW5nOiAke3Nob3dmKGcpfVxcbiAgV2l0aDogJHtzaG93KHgpfWBcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skZmluYWxseShpdCwgbSl7XG4gICAgaWYoIWlzRnV0dXJlKGl0KSkgZXJyb3IkaW52YWxpZENvbnRleHQoJ0Z1dHVyZSNmaW5hbGx5JywgaXQpO1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjZmluYWxseScsIDAsICdiZSBhIEZ1dHVyZScsIG0pO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skdmFsdWUoaXQsIGYpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjdmFsdWUnLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI3ZhbHVlJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJHByb21pc2UoaXQpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjcHJvbWlzZScsIGl0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNhY2hlKGl0KXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2NhY2hlJywgaXQpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skYWZ0ZXIobil7XG4gICAgaWYodHlwZW9mIG4gIT09ICdudW1iZXInKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5hZnRlcicsIDAsICdiZSBhIG51bWJlcicsIG4pO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skY2FzdChtKXtcbiAgICBpZighaXNGb3JrYWJsZShtKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUuY2FzdCcsIDAsICdiZSBhIEZvcmthYmxlJywgbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRlbmNhc2UoZil7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLmVuY2FzZScsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRlbmNhc2UyKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5lbmNhc2UyJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgICBpZighaXNCaW5hcnkoZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLmVuY2FzZTInLCAwLCAndGFrZSB0d28gYXJndW1lbnRzJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRlbmNhc2UzKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5lbmNhc2UzJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgICBpZighaXNUZXJuYXJ5KGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5lbmNhc2UzJywgMCwgJ3Rha2UgdGhyZWUgYXJndW1lbnRzJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRub2RlKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5ub2RlJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJHBhcmFsbGVsKGksIG1zKXtcbiAgICBpZighaXNQb3NpdGl2ZUludGVnZXIoaSkpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLnBhcmFsbGVsJywgMCwgJ2JlIGEgcG9zaXRpdmUgaW50ZWdlcicsIGkpO1xuICAgIGlmKCFBcnJheS5pc0FycmF5KG1zKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUucGFyYWxsZWwnLCAxLCAnYmUgYW4gYXJyYXknLCBtcyk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRwYXJhbGxlbCRtKG0sIGkpe1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdGdXR1cmUucGFyYWxsZWwgZXhwZWN0cyBpdHMgc2Vjb25kIGFyZ3VtZW50IHRvIGJlIGFuIGFycmF5IG9mIEZ1dHVyZXMuJ1xuICAgICAgKyBgIFRoZSB2YWx1ZSBhdCBwb3NpdGlvbiAke2l9IGluIHRoZSBhcnJheSB3YXMgbm90IGEgRnV0dXJlXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGRvKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5kbycsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRkbyRnKGcpe1xuICAgIGlmKCFpc0l0ZXJhdG9yKGcpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoXG4gICAgICAnRnV0dXJlLmRvJywgMCwgJ3JldHVybiBhbiBpdGVyYXRvciwgbWF5YmUgeW91IGZvcmdvdCB0aGUgXCIqXCInLCBnXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGRvJG5leHQobyl7XG4gICAgaWYoIWlzSXRlcmF0aW9uKG8pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZS5kbyB3YXMgZ2l2ZW4gYW4gaW52YWxpZCBnZW5lcmF0b3I6J1xuICAgICAgKyAnIEl0cyBpdGVyYXRvciBkaWQgbm90IHJldHVybiBhIHZhbGlkIGl0ZXJhdGlvbiBmcm9tIGl0ZXJhdG9yLm5leHQoKSdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke3Nob3cobyl9YFxuICAgICk7XG4gICAgaWYoIW8uZG9uZSAmJiAhaXNGdXR1cmUoby52YWx1ZSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnQSBub24tRnV0dXJlIHdhcyBwcm9kdWNlZCBieSBpdGVyYXRvci5uZXh0KCkgaW4gRnV0dXJlLmRvLidcbiAgICAgICsgJyBJZiB5b3VcXCdyZSB1c2luZyBhIGdlbmVyYXRvciwgbWFrZSBzdXJlIHlvdSBhbHdheXMgYHlpZWxkYCBhIEZ1dHVyZSdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke28udmFsdWV9YFxuICAgICk7XG4gIH1cblxuICAvLy8vLy8vLy8vLy9cbiAgLy8gRnV0dXJlIC8vXG4gIC8vLy8vLy8vLy8vL1xuXG4gIGZ1bmN0aW9uIEZ1dHVyZUNsYXNzKHNhZmUsIGYpe1xuICAgIHRoaXMuX2YgPSBzYWZlID09PSB0cnVlID8gRnV0dXJlJHNhZmVGb3JrIDogZjtcbiAgICB0aGlzLl9yYXcgPSBmO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlKGYpe1xuICAgIGNoZWNrJEZ1dHVyZShmKTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKHRydWUsIGYpO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJG9mKHgpe1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRvZiRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJlcyh4KTtcbiAgICAgIHJldHVybiBub29wO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGNoYWluUmVjKGYsIGluaXQpe1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoRnV0dXJlJGNoYWluUmVjLCBmKTtcbiAgICBjaGVjayRjaGFpblJlYyhmKTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbihyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsID0gbm9vcCwgaSA9IDA7XG4gICAgICAoZnVuY3Rpb24gRnV0dXJlJGNoYWluUmVjJHJlY3VyKHN0YXRlKXtcbiAgICAgICAgbGV0IGlzU3luYyA9IG51bGw7XG4gICAgICAgIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlYyRyZXMoaXQpe1xuICAgICAgICAgIGNoZWNrJGNoYWluUmVjJGl0KGl0LCBpKTtcbiAgICAgICAgICBpID0gaSArIDE7XG4gICAgICAgICAgaWYoaXNTeW5jID09PSBudWxsKXtcbiAgICAgICAgICAgIGlzU3luYyA9IHRydWU7XG4gICAgICAgICAgICBzdGF0ZSA9IGl0O1xuICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgRnV0dXJlJGNoYWluUmVjJHJlY3VyKGl0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUoIXN0YXRlLmRvbmUpe1xuICAgICAgICAgIGlzU3luYyA9IG51bGw7XG4gICAgICAgICAgY29uc3QgbSA9IGYoTmV4dCwgRG9uZSwgc3RhdGUudmFsdWUpO1xuICAgICAgICAgIGNoZWNrJGNoYWluUmVjJGYobSwgZiwgaSwgc3RhdGUudmFsdWUpO1xuICAgICAgICAgIGNhbmNlbCA9IG0uX2YocmVqLCBGdXR1cmUkY2hhaW5SZWMkcmVzKTtcbiAgICAgICAgICBpZihpc1N5bmMgPT09IHRydWUpe1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICBpc1N5bmMgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzKHN0YXRlLnZhbHVlKTtcbiAgICAgIH0oTmV4dChpbml0KSkpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlYyRjYW5jZWwoKXsgY2FuY2VsKCkgfTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRmb3JrKHJlaiwgcmVzKXtcbiAgICBjaGVjayRmb3JrKHRoaXMsIHJlaiwgcmVzKTtcbiAgICByZXR1cm4gdGhpcy5fZihyZWosIHJlcyk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkc2FmZUZvcmsocmVqLCByZXMpe1xuICAgIGxldCBvcGVuID0gdHJ1ZTtcbiAgICBjb25zdCBmID0gdGhpcy5fcmF3KGZ1bmN0aW9uIEZ1dHVyZSRzYWZlRm9yayRyZWooeCl7XG4gICAgICBpZihvcGVuKXtcbiAgICAgICAgb3BlbiA9IGZhbHNlO1xuICAgICAgICByZWooeCk7XG4gICAgICB9XG4gICAgfSwgZnVuY3Rpb24gRnV0dXJlJHNhZmVGb3JrJHJlcyh4KXtcbiAgICAgIGlmKG9wZW4pe1xuICAgICAgICBvcGVuID0gZmFsc2U7XG4gICAgICAgIHJlcyh4KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjaGVjayRmb3JrJGYoZiwgdGhpcy5fcmF3KTtcbiAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJHNhZmVGb3JrJGNhbmNlbCgpe1xuICAgICAgb3BlbiAmJiBmICYmIGYoKTtcbiAgICAgIG9wZW4gPSBmYWxzZTtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGNoYWluKGYpe1xuICAgIGNoZWNrJGNoYWluKHRoaXMsIGYpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkY2hhaW4kZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsO1xuICAgICAgY29uc3QgciA9IF90aGlzLl9mKHJlaiwgZnVuY3Rpb24gRnV0dXJlJGNoYWluJHJlcyh4KXtcbiAgICAgICAgY29uc3QgbSA9IGYoeCk7XG4gICAgICAgIGNoZWNrJGNoYWluJGYobSwgZiwgeCk7XG4gICAgICAgIGNhbmNlbCA9IG0uX2YocmVqLCByZXMpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gY2FuY2VsID8gY2FuY2VsIDogKGNhbmNlbCA9IHIsIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpbiRjYW5jZWwoKXsgY2FuY2VsKCkgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkcmVjdXIoZil7XG4gICAgY2hlY2skcmVjdXIodGhpcywgZik7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpbiRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJldHVybiBfdGhpcy5fZihyZWosIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpbiRyZXMoeCl7XG4gICAgICAgIGNvbnN0IG0gPSBmKHgpO1xuICAgICAgICBjaGVjayRyZWN1ciRmKG0sIGYsIHgpO1xuICAgICAgICBtLl9mKHJlaiwgcmVzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGNoYWluUmVqKGYpe1xuICAgIGNoZWNrJGNoYWluUmVqKHRoaXMsIGYpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkY2hhaW5SZWokZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsO1xuICAgICAgY29uc3QgciA9IF90aGlzLl9mKGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlaiRyZWooeCl7XG4gICAgICAgIGNvbnN0IG0gPSBmKHgpO1xuICAgICAgICBjaGVjayRjaGFpblJlaiRmKG0sIGYsIHgpO1xuICAgICAgICBjYW5jZWwgPSBtLl9mKHJlaiwgcmVzKTtcbiAgICAgIH0sIHJlcyk7XG4gICAgICByZXR1cm4gY2FuY2VsID8gY2FuY2VsIDogKGNhbmNlbCA9IHIsIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlaiRjYW5jZWwoKXsgY2FuY2VsKCkgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkbWFwKGYpe1xuICAgIGNoZWNrJG1hcCh0aGlzLCBmKTtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJG1hcCRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJldHVybiBfdGhpcy5fZihyZWosIGZ1bmN0aW9uIEZ1dHVyZSRtYXAkcmVzKHgpe1xuICAgICAgICByZXMoZih4KSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRtYXBSZWooZil7XG4gICAgY2hlY2skbWFwUmVqKHRoaXMsIGYpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkbWFwUmVqJGZvcmsocmVqLCByZXMpe1xuICAgICAgcmV0dXJuIF90aGlzLl9mKGZ1bmN0aW9uIEZ1dHVyZSRtYXBSZWokcmVqKHgpe1xuICAgICAgICByZWooZih4KSk7XG4gICAgICB9LCByZXMpO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGJpbWFwKGYsIGcpe1xuICAgIGNoZWNrJGJpbWFwKHRoaXMsIGYsIGcpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkYmltYXAkZm9yayhyZWosIHJlcyl7XG4gICAgICByZXR1cm4gX3RoaXMuX2YoZnVuY3Rpb24gRnV0dXJlJGJpbWFwJHJlaih4KXtcbiAgICAgICAgcmVqKGYoeCkpO1xuICAgICAgfSwgZnVuY3Rpb24gRnV0dXJlJGJpbWFwJHJlcyh4KXtcbiAgICAgICAgcmVzKGcoeCkpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkYXAobSl7XG4gICAgY2hlY2skYXAodGhpcywgbSk7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRhcCRmb3JrKGcsIHJlcyl7XG4gICAgICBsZXQgX2YsIF94LCBvazEsIG9rMiwga287XG4gICAgICBjb25zdCByZWogPSB4ID0+IGtvIHx8IChrbyA9IDEsIGcoeCkpO1xuICAgICAgY29uc3QgYzEgPSBfdGhpcy5fZihyZWosIGZ1bmN0aW9uIEZ1dHVyZSRhcCRyZXNUaGlzKHgpe1xuICAgICAgICBpZighb2sxKSByZXR1cm4gdm9pZCAob2syID0gMSwgX3ggPSB4KVxuICAgICAgICBjaGVjayRhcCRmKF9mKTtcbiAgICAgICAgcmVzKF9mKHgpKTtcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYzIgPSBtLl9mKHJlaiwgZnVuY3Rpb24gRnV0dXJlJGFwJHJlc1RoYXQoZil7XG4gICAgICAgIGlmKCFvazIpIHJldHVybiB2b2lkIChvazEgPSAxLCBfZiA9IGYpO1xuICAgICAgICBjaGVjayRhcCRmKGYpO1xuICAgICAgICByZXMoZihfeCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJGFwJGNhbmNlbCgpeyBjMSgpOyBjMigpIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkc3dhcCgpe1xuICAgIGNoZWNrJHN3YXAodGhpcyk7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRzd2FwJGZvcmsocmVqLCByZXMpe1xuICAgICAgcmV0dXJuIF90aGlzLl9mKHJlcywgcmVqKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSR0b1N0cmluZygpe1xuICAgIHJldHVybiBgRnV0dXJlKCR7dGhpcy5fcmF3LnRvU3RyaW5nKCl9KWA7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkcmFjZShtKXtcbiAgICBjaGVjayRyYWNlKHRoaXMsIG0pO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkcmFjZSRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCBzZXR0bGVkID0gZmFsc2UsIGMxID0gbm9vcCwgYzIgPSBub29wO1xuICAgICAgY29uc3Qgb25jZSA9IGYgPT4gYSA9PiBzZXR0bGVkIHx8IChzZXR0bGVkID0gdHJ1ZSwgYzEoKSwgYzIoKSwgZihhKSk7XG4gICAgICBjMSA9IF90aGlzLl9mKG9uY2UocmVqKSwgb25jZShyZXMpKTtcbiAgICAgIGMyID0gbS5fZihvbmNlKHJlaiksIG9uY2UocmVzKSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJHJhY2UkY2FuY2VsKCl7IGMxKCk7IGMyKCkgfTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRvcihtKXtcbiAgICBjaGVjayRvcih0aGlzLCBtKTtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJG9yJGZvcmsocmVqLCByZXMpe1xuICAgICAgbGV0IG9rID0gZmFsc2UsIGtvID0gZmFsc2UsIHZhbCwgZXJyO1xuICAgICAgY29uc3QgYzEgPSBfdGhpcy5fZihcbiAgICAgICAgKCkgPT4ga28gPyByZWooZXJyKSA6IG9rID8gcmVzKHZhbCkgOiAoa28gPSB0cnVlKSxcbiAgICAgICAgeCA9PiAob2sgPSB0cnVlLCByZXMoeCkpXG4gICAgICApO1xuICAgICAgY29uc3QgYzIgPSBtLl9mKFxuICAgICAgICBlID0+IG9rIHx8IChrbyA/IHJlaihlKSA6IChlcnIgPSBlLCBrbyA9IHRydWUpKSxcbiAgICAgICAgeCA9PiBvayB8fCAoa28gPyByZXMoeCkgOiAodmFsID0geCwgb2sgPSB0cnVlKSlcbiAgICAgICk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJG9yJGNhbmNlbCgpeyBjMSgpOyBjMigpIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkZm9sZChmLCBnKXtcbiAgICBjaGVjayRmb2xkKHRoaXMsIGYsIGcpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkZm9sZCRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJldHVybiBfdGhpcy5fZihlID0+IHJlcyhmKGUpKSwgeCA9PiByZXMoZyh4KSkpO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGhvb2soZGlzcG9zZSwgY29uc3VtZSl7XG4gICAgY2hlY2skaG9vayh0aGlzLCBkaXNwb3NlLCBjb25zdW1lKTtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGhvb2skZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsO1xuICAgICAgY29uc3QgcmV0ID0gX3RoaXMuX2YocmVqLCBmdW5jdGlvbiBGdXR1cmUkaG9vayRyZXMocmVzb3VyY2Upe1xuICAgICAgICBjb25zdCBtID0gY29uc3VtZShyZXNvdXJjZSk7XG4gICAgICAgIGNoZWNrJGhvb2skZyhtLCBjb25zdW1lLCByZXNvdXJjZSk7XG4gICAgICAgIGNhbmNlbCA9IG0uX2YoZSA9PiB7XG4gICAgICAgICAgY29uc3QgYyA9IGRpc3Bvc2UocmVzb3VyY2UpO1xuICAgICAgICAgIGNoZWNrJGhvb2skZihjLCBkaXNwb3NlLCByZXNvdXJjZSk7XG4gICAgICAgICAgYy5fZihyZWosIF8gPT4gcmVqKGUpKTtcbiAgICAgICAgfSwgeCA9PiB7XG4gICAgICAgICAgY29uc3QgYyA9IGRpc3Bvc2UocmVzb3VyY2UpO1xuICAgICAgICAgIGNoZWNrJGhvb2skZihjLCBkaXNwb3NlLCByZXNvdXJjZSk7XG4gICAgICAgICAgYy5fZihyZWosIF8gPT4gcmVzKHgpKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIGNhbmNlbCA9IGNhbmNlbCB8fCByZXQ7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJGhvb2skY2FuY2VsKCl7IGNhbmNlbCgpIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkZmluYWxseShtKXtcbiAgICBjaGVjayRmaW5hbGx5KHRoaXMsIG0pO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCBjYW5jZWw7XG4gICAgICBjb25zdCByID0gX3RoaXMuX2YoZnVuY3Rpb24gRnV0dXJlJGZpbmFsbHkkcmVqKGUpe1xuICAgICAgICBjYW5jZWwgPSBtLl9mKHJlaiwgZnVuY3Rpb24gRnV0dXJlJGZpbmFsbHkkcmVqJHJlcygpeyByZWooZSkgfSk7XG4gICAgICB9LCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRyZXMoeCl7XG4gICAgICAgIGNhbmNlbCA9IG0uX2YocmVqLCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRyZXMkcmVzKCl7IHJlcyh4KSB9KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGNhbmNlbCA/IGNhbmNlbCA6IChjYW5jZWwgPSByLCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRjYW5jZWwoKXsgY2FuY2VsKCkgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkdmFsdWUoZil7XG4gICAgY2hlY2skdmFsdWUodGhpcywgZik7XG4gICAgcmV0dXJuIHRoaXMuX2YoXG4gICAgICBmdW5jdGlvbiBGdXR1cmUkdmFsdWUkcmVqKGUpe1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZ1dHVyZSN2YWx1ZSB3YXMgY2FsbGVkIG9uIGEgcmVqZWN0ZWQgRnV0dXJlXFxuICBBY3R1YWw6IEZ1dHVyZS5yZWplY3QoJHtzaG93KGUpfSlgXG4gICAgICAgICk7XG4gICAgICB9LFxuICAgICAgZlxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkcHJvbWlzZSgpe1xuICAgIGNoZWNrJHByb21pc2UodGhpcyk7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiBGdXR1cmUkcHJvbWlzZSRkbyhyZXNvbHZlLCByZWplY3Qpe1xuICAgICAgX3RoaXMuX2YocmVqZWN0LCByZXNvbHZlKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRjYWNoZSgpe1xuICAgIGNoZWNrJGNhY2hlKHRoaXMpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICBsZXQgcXVlID0gW107XG4gICAgbGV0IHZhbHVlLCBzdGF0ZTtcbiAgICBjb25zdCBzZXR0bGVXaXRoID0gbmV3U3RhdGUgPT4gZnVuY3Rpb24gRnV0dXJlJGNhY2hlJHNldHRsZShuZXdWYWx1ZSl7XG4gICAgICB2YWx1ZSA9IG5ld1ZhbHVlOyBzdGF0ZSA9IG5ld1N0YXRlO1xuICAgICAgZm9yKGxldCBpID0gMCwgbCA9IHF1ZS5sZW5ndGg7IGkgPCBsOyBpKyspe1xuICAgICAgICBxdWVbaV1bc3RhdGVdKHZhbHVlKTtcbiAgICAgICAgcXVlW2ldID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcXVlID0gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGNhY2hlJGZvcmsocmVqLCByZXMpe1xuICAgICAgbGV0IGNhbmNlbCA9IG5vb3A7XG4gICAgICBzd2l0Y2goc3RhdGUpe1xuICAgICAgICBjYXNlIDE6IHF1ZS5wdXNoKHsyOiByZWosIDM6IHJlc30pOyBicmVhaztcbiAgICAgICAgY2FzZSAyOiByZWoodmFsdWUpOyBicmVhaztcbiAgICAgICAgY2FzZSAzOiByZXModmFsdWUpOyBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBzdGF0ZSA9IDE7XG4gICAgICAgICAgcXVlLnB1c2goezI6IHJlaiwgMzogcmVzfSk7XG4gICAgICAgICAgY2FuY2VsID0gX3RoaXMuX2Yoc2V0dGxlV2l0aCgyKSwgc2V0dGxlV2l0aCgzKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJGNhY2hlJGNhbmNlbCgpe1xuICAgICAgICBxdWUgPSBbXTtcbiAgICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHN0YXRlID0gdW5kZWZpbmVkO1xuICAgICAgICBjYW5jZWwoKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBGdXR1cmVDbGFzcy5wcm90b3R5cGUgPSBGdXR1cmUucHJvdG90eXBlID0ge1xuICAgICdAQHR5cGUnOiBUWVBFT0ZfRlVUVVJFLFxuICAgIF9mOiBudWxsLFxuICAgIGZvcms6IEZ1dHVyZSRmb3JrLFxuICAgIFtGTC5vZl06IEZ1dHVyZSRvZixcbiAgICBvZjogRnV0dXJlJG9mLFxuICAgIFtGTC5jaGFpblJlY106IEZ1dHVyZSRjaGFpblJlYyxcbiAgICBbRkwuY2hhaW5dOiBGdXR1cmUkY2hhaW4sXG4gICAgY2hhaW46IEZ1dHVyZSRjaGFpbixcbiAgICByZWN1cjogRnV0dXJlJHJlY3VyLFxuICAgIGNoYWluUmVqOiBGdXR1cmUkY2hhaW5SZWosXG4gICAgW0ZMLm1hcF06IEZ1dHVyZSRtYXAsXG4gICAgbWFwOiBGdXR1cmUkbWFwLFxuICAgIG1hcFJlajogRnV0dXJlJG1hcFJlaixcbiAgICBbRkwuYmltYXBdOiBGdXR1cmUkYmltYXAsXG4gICAgYmltYXA6IEZ1dHVyZSRiaW1hcCxcbiAgICBbRkwuYXBdOiBGdXR1cmUkYXAsXG4gICAgYXA6IEZ1dHVyZSRhcCxcbiAgICBzd2FwOiBGdXR1cmUkc3dhcCxcbiAgICB0b1N0cmluZzogRnV0dXJlJHRvU3RyaW5nLFxuICAgIGluc3BlY3Q6IEZ1dHVyZSR0b1N0cmluZyxcbiAgICByYWNlOiBGdXR1cmUkcmFjZSxcbiAgICBvcjogRnV0dXJlJG9yLFxuICAgIGZvbGQ6IEZ1dHVyZSRmb2xkLFxuICAgIGhvb2s6IEZ1dHVyZSRob29rLFxuICAgIGZpbmFsbHk6IEZ1dHVyZSRmaW5hbGx5LFxuICAgIHZhbHVlOiBGdXR1cmUkdmFsdWUsXG4gICAgcHJvbWlzZTogRnV0dXJlJHByb21pc2UsXG4gICAgY2FjaGU6IEZ1dHVyZSRjYWNoZVxuICB9O1xuXG4gIEZ1dHVyZVtGTC5vZl0gPSBGdXR1cmUub2YgPSBGdXR1cmUkb2Y7XG4gIEZ1dHVyZVtGTC5jaGFpblJlY10gPSBGdXR1cmUuY2hhaW5SZWMgPSBGdXR1cmUkY2hhaW5SZWM7XG4gIEZ1dHVyZS5GdXR1cmUgPSBGdXR1cmU7XG5cbiAgRnV0dXJlLnV0aWwgPSB7XG4gICAgTmV4dCxcbiAgICBEb25lLFxuICAgIGlzRm9ya2FibGUsXG4gICAgaXNGdXR1cmUsXG4gICAgaXNGdW5jdGlvbixcbiAgICBpc0JpbmFyeSxcbiAgICBpc1Rlcm5hcnksXG4gICAgaXNQb3NpdGl2ZUludGVnZXIsXG4gICAgaXNPYmplY3QsXG4gICAgaXNJdGVyYXRvcixcbiAgICBpc0l0ZXJhdGlvbixcbiAgICBwcmV2aWV3LFxuICAgIHNob3csXG4gICAgcGFkZixcbiAgICBzaG93ZixcbiAgICBmaWQsXG4gICAgdW5hcnlQYXJ0aWFsLFxuICAgIGJpbmFyeVBhcnRpYWwsXG4gICAgdGVybmFyeVBhcnRpYWxcbiAgfTtcblxuICAvLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBEaXNwYXRjaGVycyAvL1xuICAvLy8vLy8vLy8vLy8vLy8vL1xuXG4gIC8vQ3JlYXRlcyBhIGRpc3BhdGNoZXIgZm9yIGEgbnVsbGFyeSBtZXRob2QuXG4gIGZ1bmN0aW9uIGNyZWF0ZU51bGxhcnlEaXNwYXRjaGVyKG1ldGhvZCl7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIG51bGxhcnlEaXNwYXRjaChtKXtcbiAgICAgIGlmKG0gJiYgdHlwZW9mIG1bbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1bbWV0aG9kXSgpO1xuICAgICAgZXJyb3IkaW52YWxpZEFyZ3VtZW50KGBGdXR1cmUuJHttZXRob2R9YCwgMSwgYGhhdmUgYSBcIiR7bWV0aG9kfVwiIG1ldGhvZGAsIG0pO1xuICAgIH07XG4gIH1cblxuICAvL0NyZWF0ZXMgYSBkaXNwYXRjaGVyIGZvciBhIHVuYXJ5IG1ldGhvZC5cbiAgZnVuY3Rpb24gY3JlYXRlVW5hcnlEaXNwYXRjaGVyKG1ldGhvZCl7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHVuYXJ5RGlzcGF0Y2goYSwgbSl7XG4gICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAxKSByZXR1cm4gdW5hcnlQYXJ0aWFsKHVuYXJ5RGlzcGF0Y2gsIGEpO1xuICAgICAgaWYobSAmJiB0eXBlb2YgbVttZXRob2RdID09PSAnZnVuY3Rpb24nKSByZXR1cm4gbVttZXRob2RdKGEpO1xuICAgICAgZXJyb3IkaW52YWxpZEFyZ3VtZW50KGBGdXR1cmUuJHttZXRob2R9YCwgMSwgYGhhdmUgYSBcIiR7bWV0aG9kfVwiIG1ldGhvZGAsIG0pO1xuICAgIH07XG4gIH1cblxuICAvL0NyZWF0ZXMgYSBkaXNwYXRjaGVyIGZvciBhIGJpbmFyeSBtZXRob2QuXG4gIGZ1bmN0aW9uIGNyZWF0ZUJpbmFyeURpc3BhdGNoZXIobWV0aG9kKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gYmluYXJ5RGlzcGF0Y2goYSwgYiwgbSl7XG4gICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAxKSByZXR1cm4gdW5hcnlQYXJ0aWFsKGJpbmFyeURpc3BhdGNoLCBhKTtcbiAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHJldHVybiBiaW5hcnlQYXJ0aWFsKGJpbmFyeURpc3BhdGNoLCBhLCBiKTtcbiAgICAgIGlmKG0gJiYgdHlwZW9mIG1bbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1bbWV0aG9kXShhLCBiKTtcbiAgICAgIGVycm9yJGludmFsaWRBcmd1bWVudChgRnV0dXJlLiR7bWV0aG9kfWAsIDIsIGBoYXZlIGEgXCIke21ldGhvZH1cIiBtZXRob2RgLCBtKTtcbiAgICB9O1xuICB9XG5cbiAgLy9DcmVhdGVzIGEgZGlzcGF0Y2hlciBmb3IgYSBiaW5hcnkgbWV0aG9kLCBidXQgdGFrZXMgdGhlIG9iamVjdCBmaXJzdCByYXRoZXIgdGhhbiBsYXN0LlxuICBmdW5jdGlvbiBjcmVhdGVJbnZlcnRlZEJpbmFyeURpc3BhdGNoZXIobWV0aG9kKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gaW52ZXJ0ZWRCaW5hcnlEaXNwYXRjaChtLCBhLCBiKXtcbiAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoaW52ZXJ0ZWRCaW5hcnlEaXNwYXRjaCwgbSk7XG4gICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAyKSByZXR1cm4gYmluYXJ5UGFydGlhbChpbnZlcnRlZEJpbmFyeURpc3BhdGNoLCBtLCBhKTtcbiAgICAgIGlmKG0gJiYgdHlwZW9mIG1bbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1bbWV0aG9kXShhLCBiKTtcbiAgICAgIGVycm9yJGludmFsaWRBcmd1bWVudChgRnV0dXJlLiR7bWV0aG9kfWAsIDAsIGBoYXZlIGEgXCIke21ldGhvZH1cIiBtZXRob2RgLCBtKTtcbiAgICB9O1xuICB9XG5cbiAgRnV0dXJlLmNoYWluID0gY3JlYXRlVW5hcnlEaXNwYXRjaGVyKEZMLmNoYWluKTtcbiAgRnV0dXJlLnJlY3VyID0gY3JlYXRlVW5hcnlEaXNwYXRjaGVyKCdyZWN1cicpO1xuICBGdXR1cmUuY2hhaW5SZWogPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoJ2NoYWluUmVqJyk7XG4gIEZ1dHVyZS5tYXAgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoRkwubWFwKTtcbiAgRnV0dXJlLm1hcFJlaiA9IGNyZWF0ZVVuYXJ5RGlzcGF0Y2hlcignbWFwUmVqJyk7XG4gIEZ1dHVyZS5iaW1hcCA9IGNyZWF0ZUJpbmFyeURpc3BhdGNoZXIoRkwuYmltYXApO1xuICBGdXR1cmUuYXAgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoRkwuYXApO1xuICBGdXR1cmUuc3dhcCA9IGNyZWF0ZU51bGxhcnlEaXNwYXRjaGVyKCdzd2FwJyk7XG4gIEZ1dHVyZS5mb3JrID0gY3JlYXRlQmluYXJ5RGlzcGF0Y2hlcignZm9yaycpO1xuICBGdXR1cmUucmFjZSA9IGNyZWF0ZVVuYXJ5RGlzcGF0Y2hlcigncmFjZScpO1xuICBGdXR1cmUub3IgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoJ29yJyk7XG4gIEZ1dHVyZS5mb2xkID0gY3JlYXRlQmluYXJ5RGlzcGF0Y2hlcignZm9sZCcpO1xuICBGdXR1cmUuaG9vayA9IGNyZWF0ZUludmVydGVkQmluYXJ5RGlzcGF0Y2hlcignaG9vaycpO1xuICBGdXR1cmUuZmluYWxseSA9IGNyZWF0ZVVuYXJ5RGlzcGF0Y2hlcignZmluYWxseScpO1xuICBGdXR1cmUudmFsdWUgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoJ3ZhbHVlJyk7XG4gIEZ1dHVyZS5wcm9taXNlID0gY3JlYXRlTnVsbGFyeURpc3BhdGNoZXIoJ3Byb21pc2UnKTtcbiAgRnV0dXJlLmNhY2hlID0gY3JlYXRlTnVsbGFyeURpc3BhdGNoZXIoJ2NhY2hlJyk7XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIE90aGVyIGZ1bmN0aW9ucyAvL1xuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBGdXR1cmUuaXNGdXR1cmUgPSBpc0Z1dHVyZTtcbiAgRnV0dXJlLmlzRm9ya2FibGUgPSBpc0ZvcmthYmxlO1xuXG4gIEZ1dHVyZS5yZWplY3QgPSBmdW5jdGlvbiBGdXR1cmUkcmVqZWN0KHgpe1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRyZWplY3QkZm9yayhyZWope1xuICAgICAgcmVqKHgpO1xuICAgICAgcmV0dXJuIG5vb3A7XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLmFmdGVyID0gZnVuY3Rpb24gRnV0dXJlJGFmdGVyKG4sIHgpe1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoRnV0dXJlLmFmdGVyLCBuKTtcbiAgICBjaGVjayRhZnRlcihuKTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkYWZ0ZXIkZm9yayhyZWosIHJlcyl7XG4gICAgICBjb25zdCB0ID0gc2V0VGltZW91dChyZXMsIG4sIHgpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIEZ1dHVyZSRhZnRlciRjYW5jZWwoKXsgY2xlYXJUaW1lb3V0KHQpIH07XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLmNhc3QgPSBmdW5jdGlvbiBGdXR1cmUkY2FzdChtKXtcbiAgICBjaGVjayRjYXN0KG0pO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3ModHJ1ZSwgZnVuY3Rpb24gRnV0dXJlJGNhc3QkZm9yayhyZWosIHJlcyl7XG4gICAgICBtLmZvcmsocmVqLCByZXMpO1xuICAgIH0pO1xuICB9O1xuXG4gIEZ1dHVyZS5lbmNhc2UgPSBmdW5jdGlvbiBGdXR1cmUkZW5jYXNlKGYsIHgpe1xuICAgIGNoZWNrJGVuY2FzZShmKTtcbiAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAxKSByZXR1cm4gdW5hcnlQYXJ0aWFsKEZ1dHVyZS5lbmNhc2UsIGYpO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRlbmNhc2UkZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgcjtcbiAgICAgIHRyeXsgciA9IGYoeCkgfWNhdGNoKGUpeyByZXR1cm4gdm9pZCByZWooZSkgfVxuICAgICAgcmVzKHIpO1xuICAgICAgcmV0dXJuIG5vb3A7XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLmVuY2FzZTIgPSBmdW5jdGlvbiBGdXR1cmUkZW5jYXNlMihmLCB4LCB5KXtcbiAgICBjaGVjayRlbmNhc2UyKGYpO1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoRnV0dXJlLmVuY2FzZTIsIGYpO1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHJldHVybiBiaW5hcnlQYXJ0aWFsKEZ1dHVyZS5lbmNhc2UyLCBmLCB4KTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkZW5jYXNlMiRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCByO1xuICAgICAgdHJ5eyByID0gZih4LCB5KSB9Y2F0Y2goZSl7IHJldHVybiB2b2lkIHJlaihlKSB9XG4gICAgICByZXMocik7XG4gICAgICByZXR1cm4gbm9vcDtcbiAgICB9KTtcbiAgfTtcblxuICBGdXR1cmUuZW5jYXNlMyA9IGZ1bmN0aW9uIEZ1dHVyZSRlbmNhc2UzKGYsIHgsIHksIHope1xuICAgIGNoZWNrJGVuY2FzZTMoZik7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHVuYXJ5UGFydGlhbChGdXR1cmUuZW5jYXNlMywgZik7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgcmV0dXJuIGJpbmFyeVBhcnRpYWwoRnV0dXJlLmVuY2FzZTMsIGYsIHgpO1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpIHJldHVybiB0ZXJuYXJ5UGFydGlhbChGdXR1cmUuZW5jYXNlMywgZiwgeCwgeSk7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGVuY2FzZTMkZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgcjtcbiAgICAgIHRyeXsgciA9IGYoeCwgeSwgeikgfWNhdGNoKGUpeyByZXR1cm4gdm9pZCByZWooZSkgfVxuICAgICAgcmVzKHIpO1xuICAgICAgcmV0dXJuIG5vb3A7XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLnRyeSA9IGZ1bmN0aW9uIEZ1dHVyZSR0cnkoZil7XG4gICAgcmV0dXJuIEZ1dHVyZS5lbmNhc2UoZiwgdW5kZWZpbmVkKTtcbiAgfTtcblxuICBGdXR1cmUubm9kZSA9IGZ1bmN0aW9uIEZ1dHVyZSRub2RlKGYpe1xuICAgIGNoZWNrJG5vZGUoZik7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyh0cnVlLCBmdW5jdGlvbiBGdXR1cmUkbm9kZSRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGYoZnVuY3Rpb24gRnV0dXJlJG5vZGUkZG9uZShhLCBiKXtcbiAgICAgICAgYSA/IHJlaihhKSA6IHJlcyhiKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIEZ1dHVyZS5wYXJhbGxlbCA9IGZ1bmN0aW9uIEZ1dHVyZSRwYXJhbGxlbChpLCBtcyl7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHVuYXJ5UGFydGlhbChGdXR1cmUucGFyYWxsZWwsIGkpO1xuICAgIGNoZWNrJHBhcmFsbGVsKGksIG1zKTtcbiAgICBjb25zdCBsID0gbXMubGVuZ3RoO1xuICAgIHJldHVybiBsIDwgMSA/IEZ1dHVyZSRvZihbXSkgOiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRwYXJhbGxlbCRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCBrbyA9IGZhbHNlO1xuICAgICAgbGV0IG9rID0gMDtcbiAgICAgIGNvbnN0IGNzID0gW107XG4gICAgICBjb25zdCBvdXQgPSBuZXcgQXJyYXkobCk7XG4gICAgICBjb25zdCBuZXh0ID0gaiA9PiBpIDwgbCA/IGZvcmsobXNbaV0sIGkrKykgOiAoaiA9PT0gbCAmJiByZXMob3V0KSk7XG4gICAgICBjb25zdCBmb3JrID0gKG0sIGopID0+IChjaGVjayRwYXJhbGxlbCRtKG0sIGopLCBjc1tqXSA9IG0uX2YoXG4gICAgICAgIGUgPT4ga28gfHwgKHJlaihlKSwga28gPSB0cnVlKSxcbiAgICAgICAgeCA9PiBrbyB8fCAob3V0W2pdID0geCwgbmV4dCgrK29rKSlcbiAgICAgICkpO1xuICAgICAgbXMuc2xpY2UoMCwgaSkuZm9yRWFjaChmb3JrKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbiBGdXR1cmUkcGFyYWxsZWwkY2FuY2VsKCl7IGNzLmZvckVhY2goY2FsbCkgfTtcbiAgICB9KTtcbiAgfTtcblxuICBGdXR1cmUuZG8gPSBmdW5jdGlvbiBGdXR1cmUkZG8oZil7XG4gICAgY2hlY2skZG8oZik7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGRvJGZvcmsocmVqLCByZXMpe1xuICAgICAgY29uc3QgZyA9IGYoKTtcbiAgICAgIGNoZWNrJGRvJGcoZyk7XG4gICAgICByZXR1cm4gRnV0dXJlJGNoYWluUmVjKGZ1bmN0aW9uIEZ1dHVyZSRkbyRuZXh0KG5leHQsIF8sIHgpe1xuICAgICAgICBjb25zdCBvID0gZy5uZXh0KHgpO1xuICAgICAgICBjaGVjayRkbyRuZXh0KG8pO1xuICAgICAgICByZXR1cm4gby5kb25lID8gRnV0dXJlJG9mKG8pIDogby52YWx1ZS5tYXAobmV4dCk7XG4gICAgICB9LCB1bmRlZmluZWQpLl9mKHJlaiwgcmVzKTtcbiAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gRnV0dXJlO1xuXG59KSk7XG4iXX0=
},{"inspect-f":1}]},{},[])
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9pbnNwZWN0LWYvaW5zcGVjdC1mLmpzIiwiZmx1dHVyZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4oZnVuY3Rpb24oZ2xvYmFsLCBmKXtcblxuICAndXNlIHN0cmljdCc7XG5cbiAgLyppc3RhbmJ1bCBpZ25vcmUgbmV4dCovXG4gIGlmKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnKXtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGYoKTtcbiAgfVxuXG4gIGVsc2UgaWYodHlwZW9mIGdsb2JhbC5kZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZ2xvYmFsLmRlZmluZS5hbWQpe1xuICAgIGdsb2JhbC5kZWZpbmUoW10sIGYpO1xuICB9XG5cbiAgZWxzZXtcbiAgICBnbG9iYWwuaW5zcGVjdGYgPSBmKCk7XG4gIH1cblxufSgvKmlzdGFuYnVsIGlnbm9yZSBuZXh0Ki8oZ2xvYmFsIHx8IHdpbmRvdyB8fCB0aGlzKSwgZnVuY3Rpb24oKXtcblxuICAndXNlIHN0cmljdCc7XG5cbiAgZnVuY3Rpb24gY2hlY2tuKG4pe1xuICAgIGlmKHR5cGVvZiBuICE9PSAnbnVtYmVyJykgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdpbnNwZWN0ZiBleHBlY3RzIGl0cyBmaXJzdCBhcmd1bWVudCB0byBiZSBhIG51bWJlcidcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tmKGYpe1xuICAgIGlmKHR5cGVvZiBmICE9PSAnZnVuY3Rpb24nKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ2luc3BlY3RmIGV4cGVjdHMgaXRzIHNlY29uZCBhcmd1bWVudCB0byBiZSBhIGZ1bmN0aW9uJ1xuICAgICk7XG4gIH1cblxuICBjb25zdCBSU1BBQ0UgPSAvXiAqLztcbiAgY29uc3QgUkNPREUgPSAvXFxzKlteXFxzXS87XG4gIGNvbnN0IFJUQUJTID0gL1xcdC9nO1xuICBjb25zdCBSRU9MID0gL1xcblxccj8vO1xuXG4gIGZ1bmN0aW9uIGdldFBhZGRpbmcobGluZSl7XG4gICAgcmV0dXJuIGxpbmUubWF0Y2goUlNQQUNFKVswXS5sZW5ndGg7XG4gIH1cblxuICBmdW5jdGlvbiBndWVzc0luZGVudGF0aW9uKGxpbmVzKXtcbiAgICBjb25zdCBmaWx0ZXJlZCA9IGxpbmVzLmZpbHRlcih4ID0+IFJDT0RFLnRlc3QoeCkpO1xuICAgIGNvbnN0IHBhZGRpbmdzID0gZmlsdGVyZWQubWFwKGdldFBhZGRpbmcpO1xuICAgIGNvbnN0IGRlcHRoID0gcGFkZGluZ3MucmVkdWNlKChhLCBiKSA9PiBNYXRoLm1pbihhLCBiKSwgSW5maW5pdHkpO1xuICAgIGNvbnN0IHRhYnNpemUgPSBwYWRkaW5ncy5tYXAoeCA9PiB4IC0gZGVwdGgpLmZpbmQoeCA9PiB4ID4gMSkgfHwgMjtcbiAgICByZXR1cm4ge2RlcHRoLCB0YWJzaXplfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhZChuKXtcbiAgICByZXR1cm4gKG5ldyBBcnJheShuICsgMSkpLmpvaW4oJyAnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3coZiwgaW5kZW50YXRpb24pe1xuICAgIHJldHVybiBmLnRvU3RyaW5nKCkucmVwbGFjZShSVEFCUywgaW5kZW50YXRpb24pO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9MaW5lcyhzKXtcbiAgICByZXR1cm4gcy5zcGxpdChSRU9MKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpeEluZGVudGF0aW9uKGxpbmVzLCBpbmRlbnRhdGlvbil7XG4gICAgY29uc3QgaW5mbyA9IGd1ZXNzSW5kZW50YXRpb24obGluZXMuc2xpY2UoMSkpO1xuICAgIGNvbnN0IFJQQUQgPSBuZXcgUmVnRXhwKHBhZChpbmZvLnRhYnNpemUpLCAnZycpO1xuICAgIHJldHVybiBsaW5lcy5tYXAobGluZSA9PlxuICAgICAgbGluZS5zbGljZShNYXRoLm1pbihpbmZvLmRlcHRoLCBnZXRQYWRkaW5nKGxpbmUpKSlcbiAgICAgIC5yZXBsYWNlKFJQQUQsICdcXHQnKS5yZXBsYWNlKFJUQUJTLCBpbmRlbnRhdGlvbilcbiAgICApLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIGluc3BlY3RmKG4sIGYpe1xuICAgIGNoZWNrbihuKTtcbiAgICBpZihhcmd1bWVudHMubGVuZ3RoIDwgMikgcmV0dXJuIGYgPT4gaW5zcGVjdGYobiwgZik7XG4gICAgY2hlY2tmKGYpO1xuICAgIGlmKGYudG9TdHJpbmcgIT09IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZykgcmV0dXJuIGYudG9TdHJpbmcoKTtcbiAgICBjb25zdCBpID0gcGFkKG4pLCBzaG93biA9IHNob3coZiwgaSksIGxpbmVzID0gdG9MaW5lcyhzaG93biwgaSk7XG4gICAgaWYobGluZXMubGVuZ3RoIDwgMikgcmV0dXJuIHNob3duO1xuICAgIHJldHVybiBmaXhJbmRlbnRhdGlvbihsaW5lcywgaSk7XG4gIH1cblxufSkpO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSlcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtjaGFyc2V0OnV0Zi04O2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYkltNXZaR1ZmYlc5a2RXeGxjeTlwYm5Od1pXTjBMV1l2YVc1emNHVmpkQzFtTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkJRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQklpd2labWxzWlNJNkltZGxibVZ5WVhSbFpDNXFjeUlzSW5OdmRYSmpaVkp2YjNRaU9pSWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUlvWm5WdVkzUnBiMjRvWjJ4dlltRnNMQ0JtS1h0Y2JseHVJQ0FuZFhObElITjBjbWxqZENjN1hHNWNiaUFnTHlwcGMzUmhibUoxYkNCcFoyNXZjbVVnYm1WNGRDb3ZYRzRnSUdsbUtIUjVjR1Z2WmlCdGIyUjFiR1VnSVQwOUlDZDFibVJsWm1sdVpXUW5LWHRjYmlBZ0lDQnRiMlIxYkdVdVpYaHdiM0owY3lBOUlHWW9LVHRjYmlBZ2ZWeHVYRzRnSUdWc2MyVWdhV1lvZEhsd1pXOW1JR2RzYjJKaGJDNWtaV1pwYm1VZ1BUMDlJQ2RtZFc1amRHbHZiaWNnSmlZZ1oyeHZZbUZzTG1SbFptbHVaUzVoYldRcGUxeHVJQ0FnSUdkc2IySmhiQzVrWldacGJtVW9XMTBzSUdZcE8xeHVJQ0I5WEc1Y2JpQWdaV3h6Wlh0Y2JpQWdJQ0JuYkc5aVlXd3VhVzV6Y0dWamRHWWdQU0JtS0NrN1hHNGdJSDFjYmx4dWZTZ3ZLbWx6ZEdGdVluVnNJR2xuYm05eVpTQnVaWGgwS2k4b1oyeHZZbUZzSUh4OElIZHBibVJ2ZHlCOGZDQjBhR2x6S1N3Z1puVnVZM1JwYjI0b0tYdGNibHh1SUNBbmRYTmxJSE4wY21samRDYzdYRzVjYmlBZ1puVnVZM1JwYjI0Z1kyaGxZMnR1S0c0cGUxeHVJQ0FnSUdsbUtIUjVjR1Z2WmlCdUlDRTlQU0FuYm5WdFltVnlKeWtnZEdoeWIzY2dibVYzSUZSNWNHVkZjbkp2Y2loY2JpQWdJQ0FnSUNkcGJuTndaV04wWmlCbGVIQmxZM1J6SUdsMGN5Qm1hWEp6ZENCaGNtZDFiV1Z1ZENCMGJ5QmlaU0JoSUc1MWJXSmxjaWRjYmlBZ0lDQXBPMXh1SUNCOVhHNWNiaUFnWm5WdVkzUnBiMjRnWTJobFkydG1LR1lwZTF4dUlDQWdJR2xtS0hSNWNHVnZaaUJtSUNFOVBTQW5ablZ1WTNScGIyNG5LU0IwYUhKdmR5QnVaWGNnVkhsd1pVVnljbTl5S0Z4dUlDQWdJQ0FnSjJsdWMzQmxZM1JtSUdWNGNHVmpkSE1nYVhSeklITmxZMjl1WkNCaGNtZDFiV1Z1ZENCMGJ5QmlaU0JoSUdaMWJtTjBhVzl1SjF4dUlDQWdJQ2s3WEc0Z0lIMWNibHh1SUNCamIyNXpkQ0JTVTFCQlEwVWdQU0F2WGlBcUx6dGNiaUFnWTI5dWMzUWdVa05QUkVVZ1BTQXZYRnh6S2x0ZVhGeHpYUzg3WEc0Z0lHTnZibk4wSUZKVVFVSlRJRDBnTDF4Y2RDOW5PMXh1SUNCamIyNXpkQ0JTUlU5TUlEMGdMMXhjYmx4Y2NqOHZPMXh1WEc0Z0lHWjFibU4wYVc5dUlHZGxkRkJoWkdScGJtY29iR2x1WlNsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYm1VdWJXRjBZMmdvVWxOUVFVTkZLVnN3WFM1c1pXNW5kR2c3WEc0Z0lIMWNibHh1SUNCbWRXNWpkR2x2YmlCbmRXVnpjMGx1WkdWdWRHRjBhVzl1S0d4cGJtVnpLWHRjYmlBZ0lDQmpiMjV6ZENCbWFXeDBaWEpsWkNBOUlHeHBibVZ6TG1acGJIUmxjaWg0SUQwK0lGSkRUMFJGTG5SbGMzUW9lQ2twTzF4dUlDQWdJR052Ym5OMElIQmhaR1JwYm1keklEMGdabWxzZEdWeVpXUXViV0Z3S0dkbGRGQmhaR1JwYm1jcE8xeHVJQ0FnSUdOdmJuTjBJR1JsY0hSb0lEMGdjR0ZrWkdsdVozTXVjbVZrZFdObEtDaGhMQ0JpS1NBOVBpQk5ZWFJvTG0xcGJpaGhMQ0JpS1N3Z1NXNW1hVzVwZEhrcE8xeHVJQ0FnSUdOdmJuTjBJSFJoWW5OcGVtVWdQU0J3WVdSa2FXNW5jeTV0WVhBb2VDQTlQaUI0SUMwZ1pHVndkR2dwTG1acGJtUW9lQ0E5UGlCNElENGdNU2tnZkh3Z01qdGNiaUFnSUNCeVpYUjFjbTRnZTJSbGNIUm9MQ0IwWVdKemFYcGxmVHRjYmlBZ2ZWeHVYRzRnSUdaMWJtTjBhVzl1SUhCaFpDaHVLWHRjYmlBZ0lDQnlaWFIxY200Z0tHNWxkeUJCY25KaGVTaHVJQ3NnTVNrcExtcHZhVzRvSnlBbktUdGNiaUFnZlZ4dVhHNGdJR1oxYm1OMGFXOXVJSE5vYjNjb1ppd2dhVzVrWlc1MFlYUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQm1MblJ2VTNSeWFXNW5LQ2t1Y21Wd2JHRmpaU2hTVkVGQ1V5d2dhVzVrWlc1MFlYUnBiMjRwTzF4dUlDQjlYRzVjYmlBZ1puVnVZM1JwYjI0Z2RHOU1hVzVsY3loektYdGNiaUFnSUNCeVpYUjFjbTRnY3k1emNHeHBkQ2hTUlU5TUtUdGNiaUFnZlZ4dVhHNGdJR1oxYm1OMGFXOXVJR1pwZUVsdVpHVnVkR0YwYVc5dUtHeHBibVZ6TENCcGJtUmxiblJoZEdsdmJpbDdYRzRnSUNBZ1kyOXVjM1FnYVc1bWJ5QTlJR2QxWlhOelNXNWtaVzUwWVhScGIyNG9iR2x1WlhNdWMyeHBZMlVvTVNrcE8xeHVJQ0FnSUdOdmJuTjBJRkpRUVVRZ1BTQnVaWGNnVW1WblJYaHdLSEJoWkNocGJtWnZMblJoWW5OcGVtVXBMQ0FuWnljcE8xeHVJQ0FnSUhKbGRIVnliaUJzYVc1bGN5NXRZWEFvYkdsdVpTQTlQbHh1SUNBZ0lDQWdiR2x1WlM1emJHbGpaU2hOWVhSb0xtMXBiaWhwYm1adkxtUmxjSFJvTENCblpYUlFZV1JrYVc1bktHeHBibVVwS1NsY2JpQWdJQ0FnSUM1eVpYQnNZV05sS0ZKUVFVUXNJQ2RjWEhRbktTNXlaWEJzWVdObEtGSlVRVUpUTENCcGJtUmxiblJoZEdsdmJpbGNiaUFnSUNBcExtcHZhVzRvSjF4Y2JpY3BPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVJR2x1YzNCbFkzUm1LRzRzSUdZcGUxeHVJQ0FnSUdOb1pXTnJiaWh1S1R0Y2JpQWdJQ0JwWmloaGNtZDFiV1Z1ZEhNdWJHVnVaM1JvSUR3Z01pa2djbVYwZFhKdUlHWWdQVDRnYVc1emNHVmpkR1lvYml3Z1ppazdYRzRnSUNBZ1kyaGxZMnRtS0dZcE8xeHVJQ0FnSUdsbUtHWXVkRzlUZEhKcGJtY2dJVDA5SUVaMWJtTjBhVzl1TG5CeWIzUnZkSGx3WlM1MGIxTjBjbWx1WnlrZ2NtVjBkWEp1SUdZdWRHOVRkSEpwYm1jb0tUdGNiaUFnSUNCamIyNXpkQ0JwSUQwZ2NHRmtLRzRwTENCemFHOTNiaUE5SUhOb2IzY29aaXdnYVNrc0lHeHBibVZ6SUQwZ2RHOU1hVzVsY3loemFHOTNiaXdnYVNrN1hHNGdJQ0FnYVdZb2JHbHVaWE11YkdWdVozUm9JRHdnTWlrZ2NtVjBkWEp1SUhOb2IzZHVPMXh1SUNBZ0lISmxkSFZ5YmlCbWFYaEpibVJsYm5SaGRHbHZiaWhzYVc1bGN5d2dhU2s3WEc0Z0lIMWNibHh1ZlNrcE8xeHVJbDE5IiwiKGZ1bmN0aW9uIChnbG9iYWwpe1xuLy8vLyAgICAgIF9fX18gXyAgICAgICAgIF9cbi8vLy8gICAgIC8gX19ffCB8ICAgICAgIHwgfF9cbi8vLy8gICAgfCB8X18gfCB8IF8gICBfIHwgIF9cXCAgIF8gIF9fXyAgX19fXG4vLy8vICAgIHwgIF9ffHwgfHwgfCB8IHx8IHx8IHwgfCB8fCAgXy8vIF8gXFxcbi8vLy8gICAgfCB8ICAgfCB8fCB8X3wgfHwgfHwgfF98IHx8IHwgfCAgX18vXG4vLy8vICAgIHxffCAgIHxffCBcXF9fLF98fF98IFxcX18sX3x8X3wgIFxcX19fXFxcbi8vLy9cbihmdW5jdGlvbihnbG9iYWwsIGYpe1xuXG4gICd1c2Ugc3RyaWN0JztcblxuICAvKmlzdGFuYnVsIGlnbm9yZSBuZXh0Ki9cbiAgaWYobW9kdWxlICYmIHR5cGVvZiBtb2R1bGUuZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpe1xuICAgIG1vZHVsZS5leHBvcnRzID0gZihyZXF1aXJlKCdpbnNwZWN0LWYnKSk7XG4gIH1cblxuICBlbHNle1xuICAgIGdsb2JhbC5GbHV0dXJlID0gZihnbG9iYWwuaW5zcGVjdGYpO1xuICB9XG5cbn0oLyppc3RhbmJ1bCBpZ25vcmUgbmV4dCovKGdsb2JhbCB8fCB3aW5kb3cgfHwgdGhpcyksIGZ1bmN0aW9uKGluc3BlY3RmKXtcblxuICAndXNlIHN0cmljdCc7XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBUeXBlIGNoZWNraW5nIC8vXG4gIC8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBjb25zdCBUWVBFT0ZfRlVUVVJFID0gJ2ZsdXR1cmUvRnV0dXJlJztcbiAgY29uc3QgRkwgPSB7XG4gICAgbWFwOiAnZmFudGFzeS1sYW5kL21hcCcsXG4gICAgYmltYXA6ICdmYW50YXN5LWxhbmQvYmltYXAnLFxuICAgIGNoYWluOiAnZmFudGFzeS1sYW5kL2NoYWluJyxcbiAgICBjaGFpblJlYzogJ2ZhbnRhc3ktbGFuZC9jaGFpblJlYycsXG4gICAgYXA6ICdmYW50YXN5LWxhbmQvYXAnLFxuICAgIG9mOiAnZmFudGFzeS1sYW5kL29mJ1xuICB9O1xuXG4gIGZ1bmN0aW9uIGlzRm9ya2FibGUobSl7XG4gICAgcmV0dXJuIEJvb2xlYW4obSkgJiYgdHlwZW9mIG0uZm9yayA9PT0gJ2Z1bmN0aW9uJyAmJiBtLmZvcmsubGVuZ3RoID49IDI7XG4gIH1cblxuICBmdW5jdGlvbiBpc0Z1dHVyZShtKXtcbiAgICByZXR1cm4gKG0gaW5zdGFuY2VvZiBGdXR1cmVDbGFzcykgfHwgQm9vbGVhbihtKSAmJiBtWydAQHR5cGUnXSA9PT0gVFlQRU9GX0ZVVFVSRTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRnVuY3Rpb24oZil7XG4gICAgcmV0dXJuIHR5cGVvZiBmID09PSAnZnVuY3Rpb24nO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNCaW5hcnkoZil7XG4gICAgcmV0dXJuIGYubGVuZ3RoID49IDI7XG4gIH1cblxuICBmdW5jdGlvbiBpc1Rlcm5hcnkoZil7XG4gICAgcmV0dXJuIGYubGVuZ3RoID49IDM7XG4gIH1cblxuICBmdW5jdGlvbiBpc1Bvc2l0aXZlSW50ZWdlcihuKXtcbiAgICByZXR1cm4gbiA9PT0gSW5maW5pdHkgfHwgKHR5cGVvZiBuID09PSAnbnVtYmVyJyAmJiBuID4gMCAmJiBuICUgMSA9PT0gMCAmJiBuID09PSBuKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzT2JqZWN0KG8pe1xuICAgIHJldHVybiBvICE9PSBudWxsICYmIHR5cGVvZiBvID09PSAnb2JqZWN0JztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzSXRlcmF0b3IoaSl7XG4gICAgcmV0dXJuIGlzT2JqZWN0KGkpICYmIHR5cGVvZiBpLm5leHQgPT09ICdmdW5jdGlvbic7XG4gIH1cblxuICBmdW5jdGlvbiBpc0l0ZXJhdGlvbihvKXtcbiAgICByZXR1cm4gaXNPYmplY3QobykgJiYgdHlwZW9mIG8uZG9uZSA9PT0gJ2Jvb2xlYW4nO1xuICB9XG5cbiAgLy8vLy8vLy8vLy8vLy8vXG4gIC8vIFV0aWxpdGllcyAvL1xuICAvLy8vLy8vLy8vLy8vLy9cblxuICAvL0Egc21hbGwgc3RyaW5nIHJlcHJlc2VudGluZyBhIHZhbHVlLCBidXQgbm90IGNvbnRhaW5pbmcgdGhlIHdob2xlIHZhbHVlLlxuICBjb25zdCBwcmV2aWV3ID0geCA9PlxuICAgIHR5cGVvZiB4ID09PSAnc3RyaW5nJ1xuICAgID8gSlNPTi5zdHJpbmdpZnkoeClcbiAgICA6IEFycmF5LmlzQXJyYXkoeClcbiAgICA/IGBbQXJyYXk6ICR7eC5sZW5ndGh9XWBcbiAgICA6IHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nXG4gICAgPyB0eXBlb2YgeC5uYW1lID09PSAnc3RyaW5nJyAmJiB4Lm5hbWUubGVuZ3RoID4gMFxuICAgID8gYFtGdW5jdGlvbjogJHt4Lm5hbWV9XWBcbiAgICA6IC8qaXN0YW5idWwgaWdub3JlIG5leHQqLyAnW0Z1bmN0aW9uXScgLy9Pbmx5IGZvciBvbGRlciBKUyBlbmdpbmVzLlxuICAgIDogeCAmJiB0eXBlb2YgeCA9PT0gJ29iamVjdCdcbiAgICA/IGBbT2JqZWN0OiAke09iamVjdC5rZXlzKHgpLm1hcChTdHJpbmcpLmpvaW4oJywgJyl9XWBcbiAgICA6IFN0cmluZyh4KTtcblxuICAvL0Egc2hvdyBmdW5jdGlvbiB0byBwcm92aWRlIGEgc2xpZ2h0bHkgbW9yZSBtZWFuaW5nZnVsIHJlcHJlc2VudGF0aW9uIG9mIHZhbHVlcy5cbiAgY29uc3Qgc2hvdyA9IHggPT5cbiAgICB0eXBlb2YgeCA9PT0gJ3N0cmluZydcbiAgICA/IHByZXZpZXcoeClcbiAgICA6IEFycmF5LmlzQXJyYXkoeClcbiAgICA/IGBbJHt4Lm1hcChwcmV2aWV3KS5qb2luKCcsICcpfV1gXG4gICAgOiB4ICYmICh0eXBlb2YgeC50b1N0cmluZyA9PT0gJ2Z1bmN0aW9uJylcbiAgICA/IHgudG9TdHJpbmcgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdcbiAgICA/IGB7JHtPYmplY3Qua2V5cyh4KS5yZWR1Y2UoKG8sIGspID0+IG8uY29uY2F0KGAke3ByZXZpZXcoayl9OiAke3ByZXZpZXcoeFtrXSl9YCksIFtdKS5qb2luKCcsICcpfX1gXG4gICAgOiB4LnRvU3RyaW5nKClcbiAgICA6IHByZXZpZXcoeCk7XG5cbiAgY29uc3Qgbm9vcCA9IGZ1bmN0aW9uIG5vb3AoKXt9O1xuICBjb25zdCBjYWxsID0gZnVuY3Rpb24gY2FsbChmKXtmKCl9O1xuICBjb25zdCBwYWRmID0gKHNmLCBzKSA9PiBzLnJlcGxhY2UoL14vZ20sIHNmKS5yZXBsYWNlKHNmLCAnJyk7XG4gIGNvbnN0IHNob3dmID0gZiA9PiBwYWRmKCcgICcsIGluc3BlY3RmKDIsIGYpKTtcbiAgY29uc3QgZmlkID0gZiA9PiBmLm5hbWUgPyBmLm5hbWUgOiAnPGFub255bW91cz4nO1xuICBjb25zdCBvcmRpbmFsID0gWydmaXJzdCcsICdzZWNvbmQnLCAndGhpcmQnLCAnZm91cnRoJywgJ2ZpZnRoJ107XG4gIGNvbnN0IE5leHQgPSB4ID0+ICh7ZG9uZTogZmFsc2UsIHZhbHVlOiB4fSk7XG4gIGNvbnN0IERvbmUgPSB4ID0+ICh7ZG9uZTogdHJ1ZSwgdmFsdWU6IHh9KTtcblxuICAvL1BhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIHdpdGggYSBzaW5nbGUgYXJndW1lbnQuXG4gIGZ1bmN0aW9uIHVuYXJ5UGFydGlhbChmLCBhKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gcGFydGlhbChiLCBjLCBkKXtcbiAgICAgIHN3aXRjaChhcmd1bWVudHMubGVuZ3RoKXtcbiAgICAgICAgY2FzZSAxOiByZXR1cm4gZihhLCBiKTtcbiAgICAgICAgY2FzZSAyOiByZXR1cm4gZihhLCBiLCBjKTtcbiAgICAgICAgZGVmYXVsdDogcmV0dXJuIGYoYSwgYiwgYywgZCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8vUGFydGlhbGx5IGFwcGx5IGEgZnVuY3Rpb24gd2l0aCB0d28gYXJndW1lbnRzLlxuICBmdW5jdGlvbiBiaW5hcnlQYXJ0aWFsKGYsIGEsIGIpe1xuICAgIHJldHVybiBmdW5jdGlvbiBwYXJ0aWFsKGMsIGQpeyByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGYoYSwgYiwgYykgOiBmKGEsIGIsIGMsIGQpIH07XG4gIH1cblxuICAvL1BhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIHdpdGggdGhyZWUgYXJndW1lbnRzLlxuICBmdW5jdGlvbiB0ZXJuYXJ5UGFydGlhbChmLCBhLCBiLCBjKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gcGFydGlhbChkKXsgcmV0dXJuIGYoYSwgYiwgYywgZCkgfTtcbiAgfVxuXG4gIC8vLy8vLy8vLy8vL1xuICAvLyBFcnJvcnMgLy9cbiAgLy8vLy8vLy8vLy8vXG5cbiAgZnVuY3Rpb24gZXJyb3IkaW52YWxpZEFyZ3VtZW50KGl0LCBhdCwgZXhwZWN0ZWQsIGFjdHVhbCl7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgIGAke2l0fSBleHBlY3RzIGl0cyAke29yZGluYWxbYXRdfSBhcmd1bWVudCB0byAke2V4cGVjdGVkfVxcbiAgQWN0dWFsOiAke3Nob3coYWN0dWFsKX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVycm9yJGludmFsaWRDb250ZXh0KGl0LCBhY3R1YWwpe1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICBgJHtpdH0gd2FzIGludm9rZWQgb3V0c2lkZSB0aGUgY29udGV4dCBvZiBhIEZ1dHVyZS4gWW91IG1pZ2h0IHdhbnQgdG8gdXNlYFxuICAgICAgKyBgIGEgZGlzcGF0Y2hlciBpbnN0ZWFkXFxuICBDYWxsZWQgb246ICR7c2hvdyhhY3R1YWwpfWBcbiAgICApXG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRGdXR1cmUoZm9yayl7XG4gICAgaWYoIWlzRnVuY3Rpb24oZm9yaykpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmb3JrKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGZvcmsoaXQsIHJlaiwgcmVzKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2ZvcmsnLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24ocmVqKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjZm9yaycsIDAsICdiZSBhIGZ1bmN0aW9uJywgcmVqKTtcbiAgICBpZighaXNGdW5jdGlvbihyZXMpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNmb3JrJywgMSwgJ2JlIGEgZnVuY3Rpb24nLCByZXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skZm9yayRmKGYsIGMpe1xuICAgIGlmKCEoZiA9PT0gdW5kZWZpbmVkIHx8IChpc0Z1bmN0aW9uKGYpICYmIGYubGVuZ3RoID09PSAwKSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlI2ZvcmsgZXhwZWN0ZWQgdGhlIGNvbXB1dGF0aW9uIHRvIHJldHVybiBhIG51bGxhcnkgZnVuY3Rpb24gb3Igdm9pZCdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke3Nob3coZil9XFxuICBGcm9tIGNhbGxpbmc6ICR7c2hvd2YoYyl9YFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRjaGFpbihpdCwgZil7XG4gICAgaWYoIWlzRnV0dXJlKGl0KSkgZXJyb3IkaW52YWxpZENvbnRleHQoJ0Z1dHVyZSNjaGFpbicsIGl0KTtcbiAgICBpZighaXNGdW5jdGlvbihmKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjY2hhaW4nLCAwLCAnYmUgYSBmdW5jdGlvbicsIGYpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skY2hhaW5SZWMoZil7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLmNoYWluUmVjJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNoYWluUmVjJGYobSwgZiwgaSwgeCl7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZS5jaGFpblJlYyBleHBlY3RzIHRoZSBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlIGV2ZXJ5J1xuICAgICAgKyAnIHRpbWUgaXQgaXMgY2FsbGVkLiBUaGUgdmFsdWUgcmV0dXJuZWQgZnJvbSdcbiAgICAgICsgKG9yZGluYWxbaV0gPyBgIHRoZSAke29yZGluYWxbaV19IGNhbGxgIDogYCBjYWxsICR7aX1gKVxuICAgICAgKyAnIHdhcyBub3QgYSBGdXR1cmUuJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6IChOZXh0LCBEb25lLCAke3Nob3coeCl9KWBcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skY2hhaW5SZWMkaXQoaXQsIGkpe1xuICAgIGlmKCFpc0l0ZXJhdGlvbihpdCkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlLmNoYWluUmVjIGV4cGVjdHMgdGhlIGZ1bmN0aW9uIGl0cyBnaXZlbiB0byByZXR1cm4gYSBGdXR1cmUgb2YgYW4nXG4gICAgICArICcgSXRlcmF0aW9uIGV2ZXJ5IHRpbWUgaXQgaXMgY2FsbGVkLiBUaGUgRnV0dXJlIHJldHVybmVkIGZyb20nXG4gICAgICArIChvcmRpbmFsW2ldID8gYCB0aGUgJHtvcmRpbmFsW2ldfSBjYWxsYCA6IGAgY2FsbCAke2l9YClcbiAgICAgICsgJyBkaWQgbm90IHJlc29sdmUgdG8gYSBtZW1iZXIgb2YgSXRlcmF0aW9uLidcbiAgICAgICsgJ1xcbiAgWW91IGNhbiBjcmVhdGUgYW4gdW5jb21wbGV0ZSBvciBjb21wbGV0ZSBJdGVyYXRpb24gdXNpbmcgdGhlIG5leHQnXG4gICAgICArICcgb3IgZG9uZSBmdW5jdGlvbnMgcmVzcGVjdGl2ZWx5LiBUaGVzZSBhcmUgcGFzc2VkIGludG8geW91ciBjYWxsYmFjaydcbiAgICAgICsgJyBhcyBmaXJzdCBhbmQgc2Vjb25kIGFyZ3VtZW50cy4nXG4gICAgICArIGBcXG4gIEFjdHVhbDogRnV0dXJlLm9mKCR7c2hvdyhpdCl9KWBcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skcmVjdXIoaXQsIGYpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjcmVjdXInLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI3JlY3VyJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNoYWluJGYobSwgZiwgeCl7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZSNjaGFpbiBleHBlY3RzIHRoZSBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6ICR7c2hvdyh4KX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJHJlY3VyJGYobSwgZiwgeCl7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZSNyZWN1ciBleHBlY3RzIHRoZSBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6ICR7c2hvdyh4KX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNoYWluUmVqKGl0LCBmKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlLmNoYWluUmVqJywgaXQpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5jaGFpblJlaicsIDAsICdhIGZ1bmN0aW9uJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRjaGFpblJlaiRmKG0sIGYsIHgpe1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdGdXR1cmUuY2hhaW5SZWogZXhwZWN0cyB0aGUgZnVuY3Rpb24gaXRzIGdpdmVuIHRvIHJldHVybiBhIEZ1dHVyZSdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke3Nob3cobSl9XFxuICBGcm9tIGNhbGxpbmc6ICR7c2hvd2YoZil9XFxuICBXaXRoOiAke3Nob3coeCl9YFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRtYXAoaXQsIGYpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjbWFwJywgaXQpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNtYXAnLCAwLCAnYmUgYSBmdW5jdGlvbicsIGYpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skbWFwUmVqKGl0LCBmKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI21hcFJlaicsIGl0KTtcbiAgICBpZighaXNGdW5jdGlvbihmKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjbWFwUmVqJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGJpbWFwKGl0LCBmLCBnKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2JpbWFwJywgaXQpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNiaW1hcCcsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gICAgaWYoIWlzRnVuY3Rpb24oZykpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI2JpbWFwJywgMSwgJ2JlIGEgZnVuY3Rpb24nLCBnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGFwKGl0LCBtKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2FwJywgaXQpO1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjYXAnLCAwLCAnYmUgYSBGdXR1cmUnLCBtKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGFwJGYoZil7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlI2FwIGV4cGVjdHMgaXRzIGZpcnN0IGFyZ3VtZW50IHRvIGJlIGEgRnV0dXJlIG9mIGEgRnVuY3Rpb24nXG4gICAgICArIGBcXG4gIEFjdHVhbDogRnV0dXJlLm9mKCR7c2hvdyhmKX0pYFxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRzd2FwKGl0KXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI3N3YXAnLCBpdCk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRyYWNlKGl0LCBtKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI3JhY2UnLCBpdCk7XG4gICAgaWYoIWlzRnV0dXJlKG0pKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNyYWNlJywgMCwgJ2JlIGEgRnV0dXJlJywgbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRvcihpdCwgbSl7XG4gICAgaWYoIWlzRnV0dXJlKGl0KSkgZXJyb3IkaW52YWxpZENvbnRleHQoJ0Z1dHVyZSNvcicsIGl0KTtcbiAgICBpZighaXNGdXR1cmUobSkpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI29yJywgMCwgJ2JlIGEgRnV0dXJlJywgbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRmb2xkKGl0LCBmLCBnKXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2ZvbGQnLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI2ZvbGQnLCAwLCAnYmUgYSBmdW5jdGlvbicsIGYpO1xuICAgIGlmKCFpc0Z1bmN0aW9uKGcpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZSNmb2xkJywgMSwgJ2JlIGEgZnVuY3Rpb24nLCBnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGhvb2soaXQsIGYsIGcpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjaG9vaycsIGl0KTtcbiAgICBpZighaXNGdW5jdGlvbihmKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjaG9vaycsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gICAgaWYoIWlzRnVuY3Rpb24oZykpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI2hvb2snLCAxLCAnYmUgYSBmdW5jdGlvbicsIGcpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skaG9vayRmKG0sIGYsIHgpe1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdGdXR1cmUjaG9vayBleHBlY3RzIHRoZSBmaXJzdCBmdW5jdGlvbiBpdHMgZ2l2ZW4gdG8gcmV0dXJuIGEgRnV0dXJlJ1xuICAgICAgKyBgXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1cXG4gIEZyb20gY2FsbGluZzogJHtzaG93ZihmKX1cXG4gIFdpdGg6ICR7c2hvdyh4KX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGhvb2skZyhtLCBnLCB4KXtcbiAgICBpZighaXNGdXR1cmUobSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnRnV0dXJlI2hvb2sgZXhwZWN0cyB0aGUgc2Vjb25kIGZ1bmN0aW9uIGl0cyBnaXZlbiB0byByZXR1cm4gYSBGdXR1cmUnXG4gICAgICArIGBcXG4gIEFjdHVhbDogJHtzaG93KG0pfVxcbiAgRnJvbSBjYWxsaW5nOiAke3Nob3dmKGcpfVxcbiAgV2l0aDogJHtzaG93KHgpfWBcbiAgICApO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skZmluYWxseShpdCwgbSl7XG4gICAgaWYoIWlzRnV0dXJlKGl0KSkgZXJyb3IkaW52YWxpZENvbnRleHQoJ0Z1dHVyZSNmaW5hbGx5JywgaXQpO1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUjZmluYWxseScsIDAsICdiZSBhIEZ1dHVyZScsIG0pO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skdmFsdWUoaXQsIGYpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjdmFsdWUnLCBpdCk7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlI3ZhbHVlJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJHByb21pc2UoaXQpe1xuICAgIGlmKCFpc0Z1dHVyZShpdCkpIGVycm9yJGludmFsaWRDb250ZXh0KCdGdXR1cmUjcHJvbWlzZScsIGl0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGNhY2hlKGl0KXtcbiAgICBpZighaXNGdXR1cmUoaXQpKSBlcnJvciRpbnZhbGlkQ29udGV4dCgnRnV0dXJlI2NhY2hlJywgaXQpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skYWZ0ZXIobil7XG4gICAgaWYodHlwZW9mIG4gIT09ICdudW1iZXInKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5hZnRlcicsIDAsICdiZSBhIG51bWJlcicsIG4pO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2skY2FzdChtKXtcbiAgICBpZighaXNGb3JrYWJsZShtKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUuY2FzdCcsIDAsICdiZSBhIEZvcmthYmxlJywgbSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRlbmNhc2UoZil7XG4gICAgaWYoIWlzRnVuY3Rpb24oZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLmVuY2FzZScsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRlbmNhc2UyKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5lbmNhc2UyJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgICBpZighaXNCaW5hcnkoZikpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLmVuY2FzZTInLCAwLCAndGFrZSB0d28gYXJndW1lbnRzJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRlbmNhc2UzKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5lbmNhc2UzJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgICBpZighaXNUZXJuYXJ5KGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5lbmNhc2UzJywgMCwgJ3Rha2UgdGhyZWUgYXJndW1lbnRzJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRub2RlKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5ub2RlJywgMCwgJ2JlIGEgZnVuY3Rpb24nLCBmKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJHBhcmFsbGVsKGksIG1zKXtcbiAgICBpZighaXNQb3NpdGl2ZUludGVnZXIoaSkpIGVycm9yJGludmFsaWRBcmd1bWVudCgnRnV0dXJlLnBhcmFsbGVsJywgMCwgJ2JlIGEgcG9zaXRpdmUgaW50ZWdlcicsIGkpO1xuICAgIGlmKCFBcnJheS5pc0FycmF5KG1zKSkgZXJyb3IkaW52YWxpZEFyZ3VtZW50KCdGdXR1cmUucGFyYWxsZWwnLCAxLCAnYmUgYW4gYXJyYXknLCBtcyk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRwYXJhbGxlbCRtKG0sIGkpe1xuICAgIGlmKCFpc0Z1dHVyZShtKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdGdXR1cmUucGFyYWxsZWwgZXhwZWN0cyBpdHMgc2Vjb25kIGFyZ3VtZW50IHRvIGJlIGFuIGFycmF5IG9mIEZ1dHVyZXMuJ1xuICAgICAgKyBgIFRoZSB2YWx1ZSBhdCBwb3NpdGlvbiAke2l9IGluIHRoZSBhcnJheSB3YXMgbm90IGEgRnV0dXJlXFxuICBBY3R1YWw6ICR7c2hvdyhtKX1gXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGRvKGYpe1xuICAgIGlmKCFpc0Z1bmN0aW9uKGYpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoJ0Z1dHVyZS5kbycsIDAsICdiZSBhIGZ1bmN0aW9uJywgZik7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVjayRkbyRnKGcpe1xuICAgIGlmKCFpc0l0ZXJhdG9yKGcpKSBlcnJvciRpbnZhbGlkQXJndW1lbnQoXG4gICAgICAnRnV0dXJlLmRvJywgMCwgJ3JldHVybiBhbiBpdGVyYXRvciwgbWF5YmUgeW91IGZvcmdvdCB0aGUgXCIqXCInLCBnXG4gICAgKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrJGRvJG5leHQobyl7XG4gICAgaWYoIWlzSXRlcmF0aW9uKG8pKSB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ0Z1dHVyZS5kbyB3YXMgZ2l2ZW4gYW4gaW52YWxpZCBnZW5lcmF0b3I6J1xuICAgICAgKyAnIEl0cyBpdGVyYXRvciBkaWQgbm90IHJldHVybiBhIHZhbGlkIGl0ZXJhdGlvbiBmcm9tIGl0ZXJhdG9yLm5leHQoKSdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke3Nob3cobyl9YFxuICAgICk7XG4gICAgaWYoIW8uZG9uZSAmJiAhaXNGdXR1cmUoby52YWx1ZSkpIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnQSBub24tRnV0dXJlIHdhcyBwcm9kdWNlZCBieSBpdGVyYXRvci5uZXh0KCkgaW4gRnV0dXJlLmRvLidcbiAgICAgICsgJyBJZiB5b3VcXCdyZSB1c2luZyBhIGdlbmVyYXRvciwgbWFrZSBzdXJlIHlvdSBhbHdheXMgYHlpZWxkYCBhIEZ1dHVyZSdcbiAgICAgICsgYFxcbiAgQWN0dWFsOiAke28udmFsdWV9YFxuICAgICk7XG4gIH1cblxuICAvLy8vLy8vLy8vLy9cbiAgLy8gRnV0dXJlIC8vXG4gIC8vLy8vLy8vLy8vL1xuXG4gIGZ1bmN0aW9uIEZ1dHVyZUNsYXNzKHNhZmUsIGYpe1xuICAgIHRoaXMuX2YgPSBzYWZlID09PSB0cnVlID8gRnV0dXJlJHNhZmVGb3JrIDogZjtcbiAgICB0aGlzLl9yYXcgPSBmO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlKGYpe1xuICAgIGNoZWNrJEZ1dHVyZShmKTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKHRydWUsIGYpO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJG9mKHgpe1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRvZiRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJlcyh4KTtcbiAgICAgIHJldHVybiBub29wO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGNoYWluUmVjKGYsIGluaXQpe1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoRnV0dXJlJGNoYWluUmVjLCBmKTtcbiAgICBjaGVjayRjaGFpblJlYyhmKTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbihyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsID0gbm9vcCwgaSA9IDA7XG4gICAgICAoZnVuY3Rpb24gRnV0dXJlJGNoYWluUmVjJHJlY3VyKHN0YXRlKXtcbiAgICAgICAgbGV0IGlzU3luYyA9IG51bGw7XG4gICAgICAgIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlYyRyZXMoaXQpe1xuICAgICAgICAgIGNoZWNrJGNoYWluUmVjJGl0KGl0LCBpKTtcbiAgICAgICAgICBpID0gaSArIDE7XG4gICAgICAgICAgaWYoaXNTeW5jID09PSBudWxsKXtcbiAgICAgICAgICAgIGlzU3luYyA9IHRydWU7XG4gICAgICAgICAgICBzdGF0ZSA9IGl0O1xuICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgRnV0dXJlJGNoYWluUmVjJHJlY3VyKGl0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUoIXN0YXRlLmRvbmUpe1xuICAgICAgICAgIGlzU3luYyA9IG51bGw7XG4gICAgICAgICAgY29uc3QgbSA9IGYoTmV4dCwgRG9uZSwgc3RhdGUudmFsdWUpO1xuICAgICAgICAgIGNoZWNrJGNoYWluUmVjJGYobSwgZiwgaSwgc3RhdGUudmFsdWUpO1xuICAgICAgICAgIGNhbmNlbCA9IG0uX2YocmVqLCBGdXR1cmUkY2hhaW5SZWMkcmVzKTtcbiAgICAgICAgICBpZihpc1N5bmMgPT09IHRydWUpe1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICBpc1N5bmMgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzKHN0YXRlLnZhbHVlKTtcbiAgICAgIH0oTmV4dChpbml0KSkpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlYyRjYW5jZWwoKXsgY2FuY2VsKCkgfTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRmb3JrKHJlaiwgcmVzKXtcbiAgICBjaGVjayRmb3JrKHRoaXMsIHJlaiwgcmVzKTtcbiAgICByZXR1cm4gdGhpcy5fZihyZWosIHJlcyk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkc2FmZUZvcmsocmVqLCByZXMpe1xuICAgIGxldCBvcGVuID0gdHJ1ZTtcbiAgICBjb25zdCBmID0gdGhpcy5fcmF3KGZ1bmN0aW9uIEZ1dHVyZSRzYWZlRm9yayRyZWooeCl7XG4gICAgICBpZihvcGVuKXtcbiAgICAgICAgb3BlbiA9IGZhbHNlO1xuICAgICAgICByZWooeCk7XG4gICAgICB9XG4gICAgfSwgZnVuY3Rpb24gRnV0dXJlJHNhZmVGb3JrJHJlcyh4KXtcbiAgICAgIGlmKG9wZW4pe1xuICAgICAgICBvcGVuID0gZmFsc2U7XG4gICAgICAgIHJlcyh4KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBjaGVjayRmb3JrJGYoZiwgdGhpcy5fcmF3KTtcbiAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJHNhZmVGb3JrJGNhbmNlbCgpe1xuICAgICAgb3BlbiAmJiBmICYmIGYoKTtcbiAgICAgIG9wZW4gPSBmYWxzZTtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGNoYWluKGYpe1xuICAgIGNoZWNrJGNoYWluKHRoaXMsIGYpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkY2hhaW4kZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsO1xuICAgICAgY29uc3QgciA9IF90aGlzLl9mKHJlaiwgZnVuY3Rpb24gRnV0dXJlJGNoYWluJHJlcyh4KXtcbiAgICAgICAgY29uc3QgbSA9IGYoeCk7XG4gICAgICAgIGNoZWNrJGNoYWluJGYobSwgZiwgeCk7XG4gICAgICAgIGNhbmNlbCA9IG0uX2YocmVqLCByZXMpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gY2FuY2VsID8gY2FuY2VsIDogKGNhbmNlbCA9IHIsIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpbiRjYW5jZWwoKXsgY2FuY2VsKCkgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkcmVjdXIoZil7XG4gICAgY2hlY2skcmVjdXIodGhpcywgZik7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpbiRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJldHVybiBfdGhpcy5fZihyZWosIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpbiRyZXMoeCl7XG4gICAgICAgIGNvbnN0IG0gPSBmKHgpO1xuICAgICAgICBjaGVjayRyZWN1ciRmKG0sIGYsIHgpO1xuICAgICAgICBtLl9mKHJlaiwgcmVzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGNoYWluUmVqKGYpe1xuICAgIGNoZWNrJGNoYWluUmVqKHRoaXMsIGYpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkY2hhaW5SZWokZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsO1xuICAgICAgY29uc3QgciA9IF90aGlzLl9mKGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlaiRyZWooeCl7XG4gICAgICAgIGNvbnN0IG0gPSBmKHgpO1xuICAgICAgICBjaGVjayRjaGFpblJlaiRmKG0sIGYsIHgpO1xuICAgICAgICBjYW5jZWwgPSBtLl9mKHJlaiwgcmVzKTtcbiAgICAgIH0sIHJlcyk7XG4gICAgICByZXR1cm4gY2FuY2VsID8gY2FuY2VsIDogKGNhbmNlbCA9IHIsIGZ1bmN0aW9uIEZ1dHVyZSRjaGFpblJlaiRjYW5jZWwoKXsgY2FuY2VsKCkgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkbWFwKGYpe1xuICAgIGNoZWNrJG1hcCh0aGlzLCBmKTtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJG1hcCRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJldHVybiBfdGhpcy5fZihyZWosIGZ1bmN0aW9uIEZ1dHVyZSRtYXAkcmVzKHgpe1xuICAgICAgICByZXMoZih4KSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRtYXBSZWooZil7XG4gICAgY2hlY2skbWFwUmVqKHRoaXMsIGYpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkbWFwUmVqJGZvcmsocmVqLCByZXMpe1xuICAgICAgcmV0dXJuIF90aGlzLl9mKGZ1bmN0aW9uIEZ1dHVyZSRtYXBSZWokcmVqKHgpe1xuICAgICAgICByZWooZih4KSk7XG4gICAgICB9LCByZXMpO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGJpbWFwKGYsIGcpe1xuICAgIGNoZWNrJGJpbWFwKHRoaXMsIGYsIGcpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkYmltYXAkZm9yayhyZWosIHJlcyl7XG4gICAgICByZXR1cm4gX3RoaXMuX2YoZnVuY3Rpb24gRnV0dXJlJGJpbWFwJHJlaih4KXtcbiAgICAgICAgcmVqKGYoeCkpO1xuICAgICAgfSwgZnVuY3Rpb24gRnV0dXJlJGJpbWFwJHJlcyh4KXtcbiAgICAgICAgcmVzKGcoeCkpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkYXAobSl7XG4gICAgY2hlY2skYXAodGhpcywgbSk7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRhcCRmb3JrKGcsIHJlcyl7XG4gICAgICBsZXQgX2YsIF94LCBvazEsIG9rMiwga287XG4gICAgICBjb25zdCByZWogPSB4ID0+IGtvIHx8IChrbyA9IDEsIGcoeCkpO1xuICAgICAgY29uc3QgYzEgPSBfdGhpcy5fZihyZWosIGZ1bmN0aW9uIEZ1dHVyZSRhcCRyZXNUaGlzKHgpe1xuICAgICAgICBpZighb2sxKSByZXR1cm4gdm9pZCAob2syID0gMSwgX3ggPSB4KVxuICAgICAgICBjaGVjayRhcCRmKF9mKTtcbiAgICAgICAgcmVzKF9mKHgpKTtcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYzIgPSBtLl9mKHJlaiwgZnVuY3Rpb24gRnV0dXJlJGFwJHJlc1RoYXQoZil7XG4gICAgICAgIGlmKCFvazIpIHJldHVybiB2b2lkIChvazEgPSAxLCBfZiA9IGYpO1xuICAgICAgICBjaGVjayRhcCRmKGYpO1xuICAgICAgICByZXMoZihfeCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJGFwJGNhbmNlbCgpeyBjMSgpOyBjMigpIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkc3dhcCgpe1xuICAgIGNoZWNrJHN3YXAodGhpcyk7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRzd2FwJGZvcmsocmVqLCByZXMpe1xuICAgICAgcmV0dXJuIF90aGlzLl9mKHJlcywgcmVqKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSR0b1N0cmluZygpe1xuICAgIHJldHVybiBgRnV0dXJlKCR7dGhpcy5fcmF3LnRvU3RyaW5nKCl9KWA7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkcmFjZShtKXtcbiAgICBjaGVjayRyYWNlKHRoaXMsIG0pO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkcmFjZSRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCBzZXR0bGVkID0gZmFsc2UsIGMxID0gbm9vcCwgYzIgPSBub29wO1xuICAgICAgY29uc3Qgb25jZSA9IGYgPT4gYSA9PiBzZXR0bGVkIHx8IChzZXR0bGVkID0gdHJ1ZSwgYzEoKSwgYzIoKSwgZihhKSk7XG4gICAgICBjMSA9IF90aGlzLl9mKG9uY2UocmVqKSwgb25jZShyZXMpKTtcbiAgICAgIGMyID0gbS5fZihvbmNlKHJlaiksIG9uY2UocmVzKSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJHJhY2UkY2FuY2VsKCl7IGMxKCk7IGMyKCkgfTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRvcihtKXtcbiAgICBjaGVjayRvcih0aGlzLCBtKTtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJG9yJGZvcmsocmVqLCByZXMpe1xuICAgICAgbGV0IG9rID0gZmFsc2UsIGtvID0gZmFsc2UsIHZhbCwgZXJyO1xuICAgICAgY29uc3QgYzEgPSBfdGhpcy5fZihcbiAgICAgICAgKCkgPT4ga28gPyByZWooZXJyKSA6IG9rID8gcmVzKHZhbCkgOiAoa28gPSB0cnVlKSxcbiAgICAgICAgeCA9PiAob2sgPSB0cnVlLCByZXMoeCkpXG4gICAgICApO1xuICAgICAgY29uc3QgYzIgPSBtLl9mKFxuICAgICAgICBlID0+IG9rIHx8IChrbyA/IHJlaihlKSA6IChlcnIgPSBlLCBrbyA9IHRydWUpKSxcbiAgICAgICAgeCA9PiBvayB8fCAoa28gPyByZXMoeCkgOiAodmFsID0geCwgb2sgPSB0cnVlKSlcbiAgICAgICk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJG9yJGNhbmNlbCgpeyBjMSgpOyBjMigpIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkZm9sZChmLCBnKXtcbiAgICBjaGVjayRmb2xkKHRoaXMsIGYsIGcpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkZm9sZCRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIHJldHVybiBfdGhpcy5fZihlID0+IHJlcyhmKGUpKSwgeCA9PiByZXMoZyh4KSkpO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gRnV0dXJlJGhvb2soZGlzcG9zZSwgY29uc3VtZSl7XG4gICAgY2hlY2skaG9vayh0aGlzLCBkaXNwb3NlLCBjb25zdW1lKTtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGhvb2skZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgY2FuY2VsO1xuICAgICAgY29uc3QgcmV0ID0gX3RoaXMuX2YocmVqLCBmdW5jdGlvbiBGdXR1cmUkaG9vayRyZXMocmVzb3VyY2Upe1xuICAgICAgICBjb25zdCBtID0gY29uc3VtZShyZXNvdXJjZSk7XG4gICAgICAgIGNoZWNrJGhvb2skZyhtLCBjb25zdW1lLCByZXNvdXJjZSk7XG4gICAgICAgIGNhbmNlbCA9IG0uX2YoZSA9PiB7XG4gICAgICAgICAgY29uc3QgYyA9IGRpc3Bvc2UocmVzb3VyY2UpO1xuICAgICAgICAgIGNoZWNrJGhvb2skZihjLCBkaXNwb3NlLCByZXNvdXJjZSk7XG4gICAgICAgICAgYy5fZihyZWosIF8gPT4gcmVqKGUpKTtcbiAgICAgICAgfSwgeCA9PiB7XG4gICAgICAgICAgY29uc3QgYyA9IGRpc3Bvc2UocmVzb3VyY2UpO1xuICAgICAgICAgIGNoZWNrJGhvb2skZihjLCBkaXNwb3NlLCByZXNvdXJjZSk7XG4gICAgICAgICAgYy5fZihyZWosIF8gPT4gcmVzKHgpKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIGNhbmNlbCA9IGNhbmNlbCB8fCByZXQ7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJGhvb2skY2FuY2VsKCl7IGNhbmNlbCgpIH07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkZmluYWxseShtKXtcbiAgICBjaGVjayRmaW5hbGx5KHRoaXMsIG0pO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCBjYW5jZWw7XG4gICAgICBjb25zdCByID0gX3RoaXMuX2YoZnVuY3Rpb24gRnV0dXJlJGZpbmFsbHkkcmVqKGUpe1xuICAgICAgICBjYW5jZWwgPSBtLl9mKHJlaiwgZnVuY3Rpb24gRnV0dXJlJGZpbmFsbHkkcmVqJHJlcygpeyByZWooZSkgfSk7XG4gICAgICB9LCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRyZXMoeCl7XG4gICAgICAgIGNhbmNlbCA9IG0uX2YocmVqLCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRyZXMkcmVzKCl7IHJlcyh4KSB9KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGNhbmNlbCA/IGNhbmNlbCA6IChjYW5jZWwgPSByLCBmdW5jdGlvbiBGdXR1cmUkZmluYWxseSRjYW5jZWwoKXsgY2FuY2VsKCkgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkdmFsdWUoZil7XG4gICAgY2hlY2skdmFsdWUodGhpcywgZik7XG4gICAgcmV0dXJuIHRoaXMuX2YoXG4gICAgICBmdW5jdGlvbiBGdXR1cmUkdmFsdWUkcmVqKGUpe1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZ1dHVyZSN2YWx1ZSB3YXMgY2FsbGVkIG9uIGEgcmVqZWN0ZWQgRnV0dXJlXFxuICBBY3R1YWw6IEZ1dHVyZS5yZWplY3QoJHtzaG93KGUpfSlgXG4gICAgICAgICk7XG4gICAgICB9LFxuICAgICAgZlxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBGdXR1cmUkcHJvbWlzZSgpe1xuICAgIGNoZWNrJHByb21pc2UodGhpcyk7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiBGdXR1cmUkcHJvbWlzZSRkbyhyZXNvbHZlLCByZWplY3Qpe1xuICAgICAgX3RoaXMuX2YocmVqZWN0LCByZXNvbHZlKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZ1dHVyZSRjYWNoZSgpe1xuICAgIGNoZWNrJGNhY2hlKHRoaXMpO1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICBsZXQgcXVlID0gW107XG4gICAgbGV0IHZhbHVlLCBzdGF0ZTtcbiAgICBjb25zdCBzZXR0bGVXaXRoID0gbmV3U3RhdGUgPT4gZnVuY3Rpb24gRnV0dXJlJGNhY2hlJHNldHRsZShuZXdWYWx1ZSl7XG4gICAgICB2YWx1ZSA9IG5ld1ZhbHVlOyBzdGF0ZSA9IG5ld1N0YXRlO1xuICAgICAgZm9yKGxldCBpID0gMCwgbCA9IHF1ZS5sZW5ndGg7IGkgPCBsOyBpKyspe1xuICAgICAgICBxdWVbaV1bc3RhdGVdKHZhbHVlKTtcbiAgICAgICAgcXVlW2ldID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgcXVlID0gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGNhY2hlJGZvcmsocmVqLCByZXMpe1xuICAgICAgbGV0IGNhbmNlbCA9IG5vb3A7XG4gICAgICBzd2l0Y2goc3RhdGUpe1xuICAgICAgICBjYXNlIDE6IHF1ZS5wdXNoKHsyOiByZWosIDM6IHJlc30pOyBicmVhaztcbiAgICAgICAgY2FzZSAyOiByZWoodmFsdWUpOyBicmVhaztcbiAgICAgICAgY2FzZSAzOiByZXModmFsdWUpOyBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBzdGF0ZSA9IDE7XG4gICAgICAgICAgcXVlLnB1c2goezI6IHJlaiwgMzogcmVzfSk7XG4gICAgICAgICAgY2FuY2VsID0gX3RoaXMuX2Yoc2V0dGxlV2l0aCgyKSwgc2V0dGxlV2l0aCgzKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24gRnV0dXJlJGNhY2hlJGNhbmNlbCgpe1xuICAgICAgICBxdWUgPSBbXTtcbiAgICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHN0YXRlID0gdW5kZWZpbmVkO1xuICAgICAgICBjYW5jZWwoKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBGdXR1cmVDbGFzcy5wcm90b3R5cGUgPSBGdXR1cmUucHJvdG90eXBlID0ge1xuICAgICdAQHR5cGUnOiBUWVBFT0ZfRlVUVVJFLFxuICAgIF9mOiBudWxsLFxuICAgIGZvcms6IEZ1dHVyZSRmb3JrLFxuICAgIFtGTC5vZl06IEZ1dHVyZSRvZixcbiAgICBvZjogRnV0dXJlJG9mLFxuICAgIFtGTC5jaGFpblJlY106IEZ1dHVyZSRjaGFpblJlYyxcbiAgICBbRkwuY2hhaW5dOiBGdXR1cmUkY2hhaW4sXG4gICAgY2hhaW46IEZ1dHVyZSRjaGFpbixcbiAgICByZWN1cjogRnV0dXJlJHJlY3VyLFxuICAgIGNoYWluUmVqOiBGdXR1cmUkY2hhaW5SZWosXG4gICAgW0ZMLm1hcF06IEZ1dHVyZSRtYXAsXG4gICAgbWFwOiBGdXR1cmUkbWFwLFxuICAgIG1hcFJlajogRnV0dXJlJG1hcFJlaixcbiAgICBbRkwuYmltYXBdOiBGdXR1cmUkYmltYXAsXG4gICAgYmltYXA6IEZ1dHVyZSRiaW1hcCxcbiAgICBbRkwuYXBdOiBGdXR1cmUkYXAsXG4gICAgYXA6IEZ1dHVyZSRhcCxcbiAgICBzd2FwOiBGdXR1cmUkc3dhcCxcbiAgICB0b1N0cmluZzogRnV0dXJlJHRvU3RyaW5nLFxuICAgIGluc3BlY3Q6IEZ1dHVyZSR0b1N0cmluZyxcbiAgICByYWNlOiBGdXR1cmUkcmFjZSxcbiAgICBvcjogRnV0dXJlJG9yLFxuICAgIGZvbGQ6IEZ1dHVyZSRmb2xkLFxuICAgIGhvb2s6IEZ1dHVyZSRob29rLFxuICAgIGZpbmFsbHk6IEZ1dHVyZSRmaW5hbGx5LFxuICAgIHZhbHVlOiBGdXR1cmUkdmFsdWUsXG4gICAgcHJvbWlzZTogRnV0dXJlJHByb21pc2UsXG4gICAgY2FjaGU6IEZ1dHVyZSRjYWNoZVxuICB9O1xuXG4gIEZ1dHVyZVtGTC5vZl0gPSBGdXR1cmUub2YgPSBGdXR1cmUkb2Y7XG4gIEZ1dHVyZVtGTC5jaGFpblJlY10gPSBGdXR1cmUuY2hhaW5SZWMgPSBGdXR1cmUkY2hhaW5SZWM7XG4gIEZ1dHVyZS5GdXR1cmUgPSBGdXR1cmU7XG5cbiAgRnV0dXJlLnV0aWwgPSB7XG4gICAgTmV4dCxcbiAgICBEb25lLFxuICAgIGlzRm9ya2FibGUsXG4gICAgaXNGdXR1cmUsXG4gICAgaXNGdW5jdGlvbixcbiAgICBpc0JpbmFyeSxcbiAgICBpc1Rlcm5hcnksXG4gICAgaXNQb3NpdGl2ZUludGVnZXIsXG4gICAgaXNPYmplY3QsXG4gICAgaXNJdGVyYXRvcixcbiAgICBpc0l0ZXJhdGlvbixcbiAgICBwcmV2aWV3LFxuICAgIHNob3csXG4gICAgcGFkZixcbiAgICBzaG93ZixcbiAgICBmaWQsXG4gICAgdW5hcnlQYXJ0aWFsLFxuICAgIGJpbmFyeVBhcnRpYWwsXG4gICAgdGVybmFyeVBhcnRpYWxcbiAgfTtcblxuICAvLy8vLy8vLy8vLy8vLy8vL1xuICAvLyBEaXNwYXRjaGVycyAvL1xuICAvLy8vLy8vLy8vLy8vLy8vL1xuXG4gIC8vQ3JlYXRlcyBhIGRpc3BhdGNoZXIgZm9yIGEgbnVsbGFyeSBtZXRob2QuXG4gIGZ1bmN0aW9uIGNyZWF0ZU51bGxhcnlEaXNwYXRjaGVyKG1ldGhvZCl7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIG51bGxhcnlEaXNwYXRjaChtKXtcbiAgICAgIGlmKG0gJiYgdHlwZW9mIG1bbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1bbWV0aG9kXSgpO1xuICAgICAgZXJyb3IkaW52YWxpZEFyZ3VtZW50KGBGdXR1cmUuJHttZXRob2R9YCwgMSwgYGhhdmUgYSBcIiR7bWV0aG9kfVwiIG1ldGhvZGAsIG0pO1xuICAgIH07XG4gIH1cblxuICAvL0NyZWF0ZXMgYSBkaXNwYXRjaGVyIGZvciBhIHVuYXJ5IG1ldGhvZC5cbiAgZnVuY3Rpb24gY3JlYXRlVW5hcnlEaXNwYXRjaGVyKG1ldGhvZCl7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHVuYXJ5RGlzcGF0Y2goYSwgbSl7XG4gICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAxKSByZXR1cm4gdW5hcnlQYXJ0aWFsKHVuYXJ5RGlzcGF0Y2gsIGEpO1xuICAgICAgaWYobSAmJiB0eXBlb2YgbVttZXRob2RdID09PSAnZnVuY3Rpb24nKSByZXR1cm4gbVttZXRob2RdKGEpO1xuICAgICAgZXJyb3IkaW52YWxpZEFyZ3VtZW50KGBGdXR1cmUuJHttZXRob2R9YCwgMSwgYGhhdmUgYSBcIiR7bWV0aG9kfVwiIG1ldGhvZGAsIG0pO1xuICAgIH07XG4gIH1cblxuICAvL0NyZWF0ZXMgYSBkaXNwYXRjaGVyIGZvciBhIGJpbmFyeSBtZXRob2QuXG4gIGZ1bmN0aW9uIGNyZWF0ZUJpbmFyeURpc3BhdGNoZXIobWV0aG9kKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gYmluYXJ5RGlzcGF0Y2goYSwgYiwgbSl7XG4gICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAxKSByZXR1cm4gdW5hcnlQYXJ0aWFsKGJpbmFyeURpc3BhdGNoLCBhKTtcbiAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHJldHVybiBiaW5hcnlQYXJ0aWFsKGJpbmFyeURpc3BhdGNoLCBhLCBiKTtcbiAgICAgIGlmKG0gJiYgdHlwZW9mIG1bbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1bbWV0aG9kXShhLCBiKTtcbiAgICAgIGVycm9yJGludmFsaWRBcmd1bWVudChgRnV0dXJlLiR7bWV0aG9kfWAsIDIsIGBoYXZlIGEgXCIke21ldGhvZH1cIiBtZXRob2RgLCBtKTtcbiAgICB9O1xuICB9XG5cbiAgLy9DcmVhdGVzIGEgZGlzcGF0Y2hlciBmb3IgYSBiaW5hcnkgbWV0aG9kLCBidXQgdGFrZXMgdGhlIG9iamVjdCBmaXJzdCByYXRoZXIgdGhhbiBsYXN0LlxuICBmdW5jdGlvbiBjcmVhdGVJbnZlcnRlZEJpbmFyeURpc3BhdGNoZXIobWV0aG9kKXtcbiAgICByZXR1cm4gZnVuY3Rpb24gaW52ZXJ0ZWRCaW5hcnlEaXNwYXRjaChtLCBhLCBiKXtcbiAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoaW52ZXJ0ZWRCaW5hcnlEaXNwYXRjaCwgbSk7XG4gICAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAyKSByZXR1cm4gYmluYXJ5UGFydGlhbChpbnZlcnRlZEJpbmFyeURpc3BhdGNoLCBtLCBhKTtcbiAgICAgIGlmKG0gJiYgdHlwZW9mIG1bbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIG1bbWV0aG9kXShhLCBiKTtcbiAgICAgIGVycm9yJGludmFsaWRBcmd1bWVudChgRnV0dXJlLiR7bWV0aG9kfWAsIDAsIGBoYXZlIGEgXCIke21ldGhvZH1cIiBtZXRob2RgLCBtKTtcbiAgICB9O1xuICB9XG5cbiAgRnV0dXJlLmNoYWluID0gY3JlYXRlVW5hcnlEaXNwYXRjaGVyKEZMLmNoYWluKTtcbiAgRnV0dXJlLnJlY3VyID0gY3JlYXRlVW5hcnlEaXNwYXRjaGVyKCdyZWN1cicpO1xuICBGdXR1cmUuY2hhaW5SZWogPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoJ2NoYWluUmVqJyk7XG4gIEZ1dHVyZS5tYXAgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoRkwubWFwKTtcbiAgRnV0dXJlLm1hcFJlaiA9IGNyZWF0ZVVuYXJ5RGlzcGF0Y2hlcignbWFwUmVqJyk7XG4gIEZ1dHVyZS5iaW1hcCA9IGNyZWF0ZUJpbmFyeURpc3BhdGNoZXIoRkwuYmltYXApO1xuICBGdXR1cmUuYXAgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoRkwuYXApO1xuICBGdXR1cmUuc3dhcCA9IGNyZWF0ZU51bGxhcnlEaXNwYXRjaGVyKCdzd2FwJyk7XG4gIEZ1dHVyZS5mb3JrID0gY3JlYXRlQmluYXJ5RGlzcGF0Y2hlcignZm9yaycpO1xuICBGdXR1cmUucmFjZSA9IGNyZWF0ZVVuYXJ5RGlzcGF0Y2hlcigncmFjZScpO1xuICBGdXR1cmUub3IgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoJ29yJyk7XG4gIEZ1dHVyZS5mb2xkID0gY3JlYXRlQmluYXJ5RGlzcGF0Y2hlcignZm9sZCcpO1xuICBGdXR1cmUuaG9vayA9IGNyZWF0ZUludmVydGVkQmluYXJ5RGlzcGF0Y2hlcignaG9vaycpO1xuICBGdXR1cmUuZmluYWxseSA9IGNyZWF0ZVVuYXJ5RGlzcGF0Y2hlcignZmluYWxseScpO1xuICBGdXR1cmUudmFsdWUgPSBjcmVhdGVVbmFyeURpc3BhdGNoZXIoJ3ZhbHVlJyk7XG4gIEZ1dHVyZS5wcm9taXNlID0gY3JlYXRlTnVsbGFyeURpc3BhdGNoZXIoJ3Byb21pc2UnKTtcbiAgRnV0dXJlLmNhY2hlID0gY3JlYXRlTnVsbGFyeURpc3BhdGNoZXIoJ2NhY2hlJyk7XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIE90aGVyIGZ1bmN0aW9ucyAvL1xuICAvLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuICBGdXR1cmUuaXNGdXR1cmUgPSBpc0Z1dHVyZTtcbiAgRnV0dXJlLmlzRm9ya2FibGUgPSBpc0ZvcmthYmxlO1xuXG4gIEZ1dHVyZS5yZWplY3QgPSBmdW5jdGlvbiBGdXR1cmUkcmVqZWN0KHgpe1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRyZWplY3QkZm9yayhyZWope1xuICAgICAgcmVqKHgpO1xuICAgICAgcmV0dXJuIG5vb3A7XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLmFmdGVyID0gZnVuY3Rpb24gRnV0dXJlJGFmdGVyKG4sIHgpe1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoRnV0dXJlLmFmdGVyLCBuKTtcbiAgICBjaGVjayRhZnRlcihuKTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkYWZ0ZXIkZm9yayhyZWosIHJlcyl7XG4gICAgICBjb25zdCB0ID0gc2V0VGltZW91dChyZXMsIG4sIHgpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uIEZ1dHVyZSRhZnRlciRjYW5jZWwoKXsgY2xlYXJUaW1lb3V0KHQpIH07XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLmNhc3QgPSBmdW5jdGlvbiBGdXR1cmUkY2FzdChtKXtcbiAgICBjaGVjayRjYXN0KG0pO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3ModHJ1ZSwgZnVuY3Rpb24gRnV0dXJlJGNhc3QkZm9yayhyZWosIHJlcyl7XG4gICAgICBtLmZvcmsocmVqLCByZXMpO1xuICAgIH0pO1xuICB9O1xuXG4gIEZ1dHVyZS5lbmNhc2UgPSBmdW5jdGlvbiBGdXR1cmUkZW5jYXNlKGYsIHgpe1xuICAgIGNoZWNrJGVuY2FzZShmKTtcbiAgICBpZihhcmd1bWVudHMubGVuZ3RoID09PSAxKSByZXR1cm4gdW5hcnlQYXJ0aWFsKEZ1dHVyZS5lbmNhc2UsIGYpO1xuICAgIHJldHVybiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRlbmNhc2UkZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgcjtcbiAgICAgIHRyeXsgciA9IGYoeCkgfWNhdGNoKGUpeyByZXR1cm4gdm9pZCByZWooZSkgfVxuICAgICAgcmVzKHIpO1xuICAgICAgcmV0dXJuIG5vb3A7XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLmVuY2FzZTIgPSBmdW5jdGlvbiBGdXR1cmUkZW5jYXNlMihmLCB4LCB5KXtcbiAgICBjaGVjayRlbmNhc2UyKGYpO1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB1bmFyeVBhcnRpYWwoRnV0dXJlLmVuY2FzZTIsIGYpO1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHJldHVybiBiaW5hcnlQYXJ0aWFsKEZ1dHVyZS5lbmNhc2UyLCBmLCB4KTtcbiAgICByZXR1cm4gbmV3IEZ1dHVyZUNsYXNzKGZhbHNlLCBmdW5jdGlvbiBGdXR1cmUkZW5jYXNlMiRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCByO1xuICAgICAgdHJ5eyByID0gZih4LCB5KSB9Y2F0Y2goZSl7IHJldHVybiB2b2lkIHJlaihlKSB9XG4gICAgICByZXMocik7XG4gICAgICByZXR1cm4gbm9vcDtcbiAgICB9KTtcbiAgfTtcblxuICBGdXR1cmUuZW5jYXNlMyA9IGZ1bmN0aW9uIEZ1dHVyZSRlbmNhc2UzKGYsIHgsIHksIHope1xuICAgIGNoZWNrJGVuY2FzZTMoZik7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHVuYXJ5UGFydGlhbChGdXR1cmUuZW5jYXNlMywgZik7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgcmV0dXJuIGJpbmFyeVBhcnRpYWwoRnV0dXJlLmVuY2FzZTMsIGYsIHgpO1xuICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpIHJldHVybiB0ZXJuYXJ5UGFydGlhbChGdXR1cmUuZW5jYXNlMywgZiwgeCwgeSk7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGVuY2FzZTMkZm9yayhyZWosIHJlcyl7XG4gICAgICBsZXQgcjtcbiAgICAgIHRyeXsgciA9IGYoeCwgeSwgeikgfWNhdGNoKGUpeyByZXR1cm4gdm9pZCByZWooZSkgfVxuICAgICAgcmVzKHIpO1xuICAgICAgcmV0dXJuIG5vb3A7XG4gICAgfSk7XG4gIH07XG5cbiAgRnV0dXJlLnRyeSA9IGZ1bmN0aW9uIEZ1dHVyZSR0cnkoZil7XG4gICAgcmV0dXJuIEZ1dHVyZS5lbmNhc2UoZiwgdW5kZWZpbmVkKTtcbiAgfTtcblxuICBGdXR1cmUubm9kZSA9IGZ1bmN0aW9uIEZ1dHVyZSRub2RlKGYpe1xuICAgIGNoZWNrJG5vZGUoZik7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyh0cnVlLCBmdW5jdGlvbiBGdXR1cmUkbm9kZSRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGYoZnVuY3Rpb24gRnV0dXJlJG5vZGUkZG9uZShhLCBiKXtcbiAgICAgICAgYSA/IHJlaihhKSA6IHJlcyhiKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIEZ1dHVyZS5wYXJhbGxlbCA9IGZ1bmN0aW9uIEZ1dHVyZSRwYXJhbGxlbChpLCBtcyl7XG4gICAgaWYoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHVuYXJ5UGFydGlhbChGdXR1cmUucGFyYWxsZWwsIGkpO1xuICAgIGNoZWNrJHBhcmFsbGVsKGksIG1zKTtcbiAgICBjb25zdCBsID0gbXMubGVuZ3RoO1xuICAgIHJldHVybiBsIDwgMSA/IEZ1dHVyZSRvZihbXSkgOiBuZXcgRnV0dXJlQ2xhc3MoZmFsc2UsIGZ1bmN0aW9uIEZ1dHVyZSRwYXJhbGxlbCRmb3JrKHJlaiwgcmVzKXtcbiAgICAgIGxldCBrbyA9IGZhbHNlO1xuICAgICAgbGV0IG9rID0gMDtcbiAgICAgIGNvbnN0IGNzID0gW107XG4gICAgICBjb25zdCBvdXQgPSBuZXcgQXJyYXkobCk7XG4gICAgICBjb25zdCBuZXh0ID0gaiA9PiBpIDwgbCA/IGZvcmsobXNbaV0sIGkrKykgOiAoaiA9PT0gbCAmJiByZXMob3V0KSk7XG4gICAgICBjb25zdCBmb3JrID0gKG0sIGopID0+IChjaGVjayRwYXJhbGxlbCRtKG0sIGopLCBjc1tqXSA9IG0uX2YoXG4gICAgICAgIGUgPT4ga28gfHwgKHJlaihlKSwga28gPSB0cnVlKSxcbiAgICAgICAgeCA9PiBrbyB8fCAob3V0W2pdID0geCwgbmV4dCgrK29rKSlcbiAgICAgICkpO1xuICAgICAgbXMuc2xpY2UoMCwgaSkuZm9yRWFjaChmb3JrKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbiBGdXR1cmUkcGFyYWxsZWwkY2FuY2VsKCl7IGNzLmZvckVhY2goY2FsbCkgfTtcbiAgICB9KTtcbiAgfTtcblxuICBGdXR1cmUuZG8gPSBmdW5jdGlvbiBGdXR1cmUkZG8oZil7XG4gICAgY2hlY2skZG8oZik7XG4gICAgcmV0dXJuIG5ldyBGdXR1cmVDbGFzcyhmYWxzZSwgZnVuY3Rpb24gRnV0dXJlJGRvJGZvcmsocmVqLCByZXMpe1xuICAgICAgY29uc3QgZyA9IGYoKTtcbiAgICAgIGNoZWNrJGRvJGcoZyk7XG4gICAgICByZXR1cm4gRnV0dXJlJGNoYWluUmVjKGZ1bmN0aW9uIEZ1dHVyZSRkbyRuZXh0KG5leHQsIF8sIHgpe1xuICAgICAgICBjb25zdCBvID0gZy5uZXh0KHgpO1xuICAgICAgICBjaGVjayRkbyRuZXh0KG8pO1xuICAgICAgICByZXR1cm4gby5kb25lID8gRnV0dXJlJG9mKG8pIDogby52YWx1ZS5tYXAobmV4dCk7XG4gICAgICB9LCB1bmRlZmluZWQpLl9mKHJlaiwgcmVzKTtcbiAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gRnV0dXJlO1xuXG59KSk7XG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ6dXRmLTg7YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1ac2RYUjFjbVV1YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWp0QlFVRkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRU0lzSW1acGJHVWlPaUpuWlc1bGNtRjBaV1F
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment