14215 lines
1.9 MiB
14215 lines
1.9 MiB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||
exports = module.exports = stringify
|
||
exports.getSerialize = serializer
|
||
|
||
function stringify(obj, replacer, spaces, cycleReplacer) {
|
||
return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
|
||
}
|
||
|
||
function serializer(replacer, cycleReplacer) {
|
||
var stack = [], keys = []
|
||
|
||
if (cycleReplacer == null) cycleReplacer = function(key, value) {
|
||
if (stack[0] === value) return "[Circular ~]"
|
||
return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
|
||
}
|
||
|
||
return function(key, value) {
|
||
if (stack.length > 0) {
|
||
var thisPos = stack.indexOf(this)
|
||
~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
|
||
~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
|
||
if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
|
||
}
|
||
else stack.push(value)
|
||
|
||
return replacer == null ? value : replacer.call(this, key, value)
|
||
}
|
||
}
|
||
|
||
},{}],2:[function(require,module,exports){
|
||
/*
|
||
* random-seed
|
||
* https://github.com/skratchdot/random-seed
|
||
*
|
||
* This code was originally written by Steve Gibson and can be found here:
|
||
*
|
||
* https://www.grc.com/otg/uheprng.htm
|
||
*
|
||
* It was slightly modified for use in node, to pass jshint, and a few additional
|
||
* helper functions were added.
|
||
*
|
||
* Copyright (c) 2013 skratchdot
|
||
* Dual Licensed under the MIT license and the original GRC copyright/license
|
||
* included below.
|
||
*/
|
||
/* ============================================================================
|
||
Gibson Research Corporation
|
||
UHEPRNG - Ultra High Entropy Pseudo-Random Number Generator
|
||
============================================================================
|
||
LICENSE AND COPYRIGHT: THIS CODE IS HEREBY RELEASED INTO THE PUBLIC DOMAIN
|
||
Gibson Research Corporation releases and disclaims ALL RIGHTS AND TITLE IN
|
||
THIS CODE OR ANY DERIVATIVES. Anyone may be freely use it for any purpose.
|
||
============================================================================
|
||
This is GRC's cryptographically strong PRNG (pseudo-random number generator)
|
||
for JavaScript. It is driven by 1536 bits of entropy, stored in an array of
|
||
48, 32-bit JavaScript variables. Since many applications of this generator,
|
||
including ours with the "Off The Grid" Latin Square generator, may require
|
||
the deteriministic re-generation of a sequence of PRNs, this PRNG's initial
|
||
entropic state can be read and written as a static whole, and incrementally
|
||
evolved by pouring new source entropy into the generator's internal state.
|
||
----------------------------------------------------------------------------
|
||
ENDLESS THANKS are due Johannes Baagoe for his careful development of highly
|
||
robust JavaScript implementations of JS PRNGs. This work was based upon his
|
||
JavaScript "Alea" PRNG which is based upon the extremely robust Multiply-
|
||
With-Carry (MWC) PRNG invented by George Marsaglia. MWC Algorithm References:
|
||
http://www.GRC.com/otg/Marsaglia_PRNGs.pdf
|
||
http://www.GRC.com/otg/Marsaglia_MWC_Generators.pdf
|
||
----------------------------------------------------------------------------
|
||
The quality of this algorithm's pseudo-random numbers have been verified by
|
||
multiple independent researchers. It handily passes the fermilab.ch tests as
|
||
well as the "diehard" and "dieharder" test suites. For individuals wishing
|
||
to further verify the quality of this algorithm's pseudo-random numbers, a
|
||
256-megabyte file of this algorithm's output may be downloaded from GRC.com,
|
||
and a Microsoft Windows scripting host (WSH) version of this algorithm may be
|
||
downloaded and run from the Windows command prompt to generate unique files
|
||
of any size:
|
||
The Fermilab "ENT" tests: http://fourmilab.ch/random/
|
||
The 256-megabyte sample PRN file at GRC: https://www.GRC.com/otg/uheprng.bin
|
||
The Windows scripting host version: https://www.GRC.com/otg/wsh-uheprng.js
|
||
----------------------------------------------------------------------------
|
||
Qualifying MWC multipliers are: 187884, 686118, 898134, 1104375, 1250205,
|
||
1460910 and 1768863. (We use the largest one that's < 2^21)
|
||
============================================================================ */
|
||
'use strict';
|
||
var stringify = require('json-stringify-safe');
|
||
|
||
/* ============================================================================
|
||
This is based upon Johannes Baagoe's carefully designed and efficient hash
|
||
function for use with JavaScript. It has a proven "avalanche" effect such
|
||
that every bit of the input affects every bit of the output 50% of the time,
|
||
which is good. See: http://baagoe.com/en/RandomMusings/hash/avalanche.xhtml
|
||
============================================================================
|
||
*/
|
||
var Mash = function () {
|
||
var n = 0xefc8249d;
|
||
var mash = function (data) {
|
||
if (data) {
|
||
data = data.toString();
|
||
for (var i = 0; i < data.length; i++) {
|
||
n += data.charCodeAt(i);
|
||
var h = 0.02519603282416938 * n;
|
||
n = h >>> 0;
|
||
h -= n;
|
||
h *= n;
|
||
n = h >>> 0;
|
||
h -= n;
|
||
n += h * 0x100000000; // 2^32
|
||
}
|
||
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
||
} else {
|
||
n = 0xefc8249d;
|
||
}
|
||
};
|
||
return mash;
|
||
};
|
||
|
||
var uheprng = function (seed) {
|
||
return (function () {
|
||
var o = 48; // set the 'order' number of ENTROPY-holding 32-bit values
|
||
var c = 1; // init the 'carry' used by the multiply-with-carry (MWC) algorithm
|
||
var p = o; // init the 'phase' (max-1) of the intermediate variable pointer
|
||
var s = new Array(o); // declare our intermediate variables array
|
||
var i; // general purpose local
|
||
var j; // general purpose local
|
||
var k = 0; // general purpose local
|
||
|
||
// when our "uheprng" is initially invoked our PRNG state is initialized from the
|
||
// browser's own local PRNG. This is okay since although its generator might not
|
||
// be wonderful, it's useful for establishing large startup entropy for our usage.
|
||
var mash = new Mash(); // get a pointer to our high-performance "Mash" hash
|
||
|
||
// fill the array with initial mash hash values
|
||
for (i = 0; i < o; i++) {
|
||
s[i] = mash(Math.random());
|
||
}
|
||
|
||
// this PRIVATE (internal access only) function is the heart of the multiply-with-carry
|
||
// (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a
|
||
// 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default
|
||
// [0-1] return function, and by the random 'string(n)' function which returns 'n'
|
||
// characters from 33 to 126.
|
||
var rawprng = function () {
|
||
if (++p >= o) {
|
||
p = 0;
|
||
}
|
||
var t = 1768863 * s[p] + c * 2.3283064365386963e-10; // 2^-32
|
||
return s[p] = t - (c = t | 0);
|
||
};
|
||
|
||
// this EXPORTED function is the default function returned by this library.
|
||
// The values returned are integers in the range from 0 to range-1. We first
|
||
// obtain two 32-bit fractions (from rawprng) to synthesize a single high
|
||
// resolution 53-bit prng (0 to <1), then we multiply this by the caller's
|
||
// "range" param and take the "floor" to return a equally probable integer.
|
||
var random = function (range) {
|
||
return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16)); // 2^-53
|
||
};
|
||
|
||
// this EXPORTED function 'string(n)' returns a pseudo-random string of
|
||
// 'n' printable characters ranging from chr(33) to chr(126) inclusive.
|
||
random.string = function (count) {
|
||
var i;
|
||
var s = '';
|
||
for (i = 0; i < count; i++) {
|
||
s += String.fromCharCode(33 + random(94));
|
||
}
|
||
return s;
|
||
};
|
||
|
||
// this PRIVATE "hash" function is used to evolve the generator's internal
|
||
// entropy state. It is also called by the EXPORTED addEntropy() function
|
||
// which is used to pour entropy into the PRNG.
|
||
var hash = function () {
|
||
var args = Array.prototype.slice.call(arguments);
|
||
for (i = 0; i < args.length; i++) {
|
||
for (j = 0; j < o; j++) {
|
||
s[j] -= mash(args[i]);
|
||
if (s[j] < 0) {
|
||
s[j] += 1;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
// this EXPORTED "clean string" function removes leading and trailing spaces and non-printing
|
||
// control characters, including any embedded carriage-return (CR) and line-feed (LF) characters,
|
||
// from any string it is handed. this is also used by the 'hashstring' function (below) to help
|
||
// users always obtain the same EFFECTIVE uheprng seeding key.
|
||
random.cleanString = function (inStr) {
|
||
inStr = inStr.replace(/(^\s*)|(\s*$)/gi, ''); // remove any/all leading spaces
|
||
inStr = inStr.replace(/[\x00-\x1F]/gi, ''); // remove any/all control characters
|
||
inStr = inStr.replace(/\n /, '\n'); // remove any/all trailing spaces
|
||
return inStr; // return the cleaned up result
|
||
};
|
||
|
||
// this EXPORTED "hash string" function hashes the provided character string after first removing
|
||
// any leading or trailing spaces and ignoring any embedded carriage returns (CR) or Line Feeds (LF)
|
||
random.hashString = function (inStr) {
|
||
inStr = random.cleanString(inStr);
|
||
mash(inStr); // use the string to evolve the 'mash' state
|
||
for (i = 0; i < inStr.length; i++) { // scan through the characters in our string
|
||
k = inStr.charCodeAt(i); // get the character code at the location
|
||
for (j = 0; j < o; j++) { // "mash" it into the UHEPRNG state
|
||
s[j] -= mash(k);
|
||
if (s[j] < 0) {
|
||
s[j] += 1;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
// this EXPORTED function allows you to seed the random generator.
|
||
random.seed = function (seed) {
|
||
if (typeof seed === 'undefined' || seed === null) {
|
||
seed = Math.random();
|
||
}
|
||
if (typeof seed !== 'string') {
|
||
seed = stringify(seed, function (key, value) {
|
||
if (typeof value === 'function') {
|
||
return (value).toString();
|
||
}
|
||
return value;
|
||
});
|
||
}
|
||
random.initState();
|
||
random.hashString(seed);
|
||
};
|
||
|
||
// this handy exported function is used to add entropy to our uheprng at any time
|
||
random.addEntropy = function ( /* accept zero or more arguments */ ) {
|
||
var args = [];
|
||
for (i = 0; i < arguments.length; i++) {
|
||
args.push(arguments[i]);
|
||
}
|
||
hash((k++) + (new Date().getTime()) + args.join('') + Math.random());
|
||
};
|
||
|
||
// if we want to provide a deterministic startup context for our PRNG,
|
||
// but without directly setting the internal state variables, this allows
|
||
// us to initialize the mash hash and PRNG's internal state before providing
|
||
// some hashing input
|
||
random.initState = function () {
|
||
mash(); // pass a null arg to force mash hash to init
|
||
for (i = 0; i < o; i++) {
|
||
s[i] = mash(' '); // fill the array with initial mash hash values
|
||
}
|
||
c = 1; // init our multiply-with-carry carry
|
||
p = o; // init our phase
|
||
};
|
||
|
||
// we use this (optional) exported function to signal the JavaScript interpreter
|
||
// that we're finished using the "Mash" hash function so that it can free up the
|
||
// local "instance variables" is will have been maintaining. It's not strictly
|
||
// necessary, of course, but it's good JavaScript citizenship.
|
||
random.done = function () {
|
||
mash = null;
|
||
};
|
||
|
||
// if we called "uheprng" with a seed value, then execute random.seed() before returning
|
||
if (typeof seed !== 'undefined') {
|
||
random.seed(seed);
|
||
}
|
||
|
||
// Returns a random integer between 0 (inclusive) and range (exclusive)
|
||
random.range = function (range) {
|
||
return random(range);
|
||
};
|
||
|
||
// Returns a random float between 0 (inclusive) and 1 (exclusive)
|
||
random.random = function () {
|
||
return random(Number.MAX_VALUE - 1) / Number.MAX_VALUE;
|
||
};
|
||
|
||
// Returns a random float between min (inclusive) and max (exclusive)
|
||
random.floatBetween = function (min, max) {
|
||
return random.random() * (max - min) + min;
|
||
};
|
||
|
||
// Returns a random integer between min (inclusive) and max (inclusive)
|
||
random.intBetween = function (min, max) {
|
||
return Math.floor(random.random() * (max - min + 1)) + min;
|
||
};
|
||
|
||
// when our main outer "uheprng" function is called, after setting up our
|
||
// initial variables and entropic state, we return an "instance pointer"
|
||
// to the internal anonymous function which can then be used to access
|
||
// the uheprng's various exported functions. As with the ".done" function
|
||
// above, we should set the returned value to 'null' once we're finished
|
||
// using any of these functions.
|
||
return random;
|
||
}());
|
||
};
|
||
|
||
// Modification for use in node:
|
||
uheprng.create = function (seed) {
|
||
return new uheprng(seed);
|
||
};
|
||
module.exports = uheprng;
|
||
|
||
},{"json-stringify-safe":1}],3:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../DataTypes/Map");
|
||
/**
|
||
* A manager class for all of the AI in a scene.
|
||
* Keeps a list of registered actors and handles AI generation for actors.
|
||
*/
|
||
class AIManager {
|
||
constructor() {
|
||
this.actors = new Array();
|
||
this.registeredAI = new Map_1.default();
|
||
}
|
||
/**
|
||
* Registers an actor with the AIManager
|
||
* @param actor The actor to register
|
||
*/
|
||
registerActor(actor) {
|
||
this.actors.push(actor);
|
||
}
|
||
removeActor(actor) {
|
||
let index = this.actors.indexOf(actor);
|
||
if (index !== -1) {
|
||
this.actors.splice(index, 1);
|
||
}
|
||
}
|
||
/**
|
||
* Registers an AI with the AIManager for use later on
|
||
* @param name The name of the AI to register
|
||
* @param constr The constructor for the AI
|
||
*/
|
||
registerAI(name, constr) {
|
||
this.registeredAI.add(name, constr);
|
||
}
|
||
/**
|
||
* Generates an AI instance from its name
|
||
* @param name The name of the AI to add
|
||
* @returns A new AI instance
|
||
*/
|
||
generateAI(name) {
|
||
if (this.registeredAI.has(name)) {
|
||
return new (this.registeredAI.get(name))();
|
||
}
|
||
else {
|
||
throw `Cannot create AI with name ${name}, no AI with that name is registered`;
|
||
}
|
||
}
|
||
update(deltaT) {
|
||
// Run the ai for every active actor
|
||
this.actors.forEach(actor => { if (actor.aiActive)
|
||
actor.ai.update(deltaT); });
|
||
}
|
||
}
|
||
exports.default = AIManager;
|
||
|
||
},{"../DataTypes/Map":10}],4:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const StateMachine_1 = require("../DataTypes/State/StateMachine");
|
||
/**
|
||
* A version of a @reference[StateMachine] that is configured to work as an AI controller for a @reference[GameNode]
|
||
*/
|
||
class StateMachineAI extends StateMachine_1.default {
|
||
// @implemented
|
||
initializeAI(owner, config) { }
|
||
// @implemented
|
||
destroy() {
|
||
// Get rid of our reference to the owner
|
||
delete this.owner;
|
||
this.receiver.destroy();
|
||
}
|
||
// @implemented
|
||
activate(options) { }
|
||
}
|
||
exports.default = StateMachineAI;
|
||
|
||
},{"../DataTypes/State/StateMachine":21}],5:[function(require,module,exports){
|
||
"use strict";
|
||
// @ignorePage
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/**
|
||
* A placeholder function for No Operation. Does nothing
|
||
*/
|
||
const NullFunc = () => { };
|
||
exports.default = NullFunc;
|
||
|
||
},{}],6:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/**
|
||
* A linked-list for the edges in a @reference[Graph].
|
||
*/
|
||
class EdgeNode {
|
||
/**
|
||
* Creates a new EdgeNode
|
||
* @param index The index of the node this edge connects to
|
||
* @param weight The weight of this edge
|
||
*/
|
||
constructor(index, weight) {
|
||
this.y = index;
|
||
this.next = null;
|
||
this.weight = weight ? weight : 1;
|
||
}
|
||
}
|
||
exports.default = EdgeNode;
|
||
|
||
},{}],7:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.MAX_V = void 0;
|
||
const EdgeNode_1 = require("./EdgeNode");
|
||
exports.MAX_V = 100;
|
||
/**
|
||
* An implementation of a graph data structure using edge lists. Inspired by The Algorithm Design Manual.
|
||
*/
|
||
class Graph {
|
||
/**
|
||
* Constructs a new graph
|
||
* @param directed Whether or not this graph is directed
|
||
*/
|
||
constructor(directed = false) {
|
||
this.directed = directed;
|
||
this.weighted = false;
|
||
this.numVertices = 0;
|
||
this.numEdges = 0;
|
||
this.edges = new Array(exports.MAX_V);
|
||
this.degree = new Array(exports.MAX_V);
|
||
}
|
||
/** Adds a node to this graph and returns the index of it
|
||
* @returns The index of the new node
|
||
*/
|
||
addNode() {
|
||
this.numVertices++;
|
||
return this.numVertices;
|
||
}
|
||
/** Adds an edge between node x and y, with an optional weight
|
||
* @param x The index of the start of the edge
|
||
* @param y The index of the end of the edge
|
||
* @param weight The optional weight of the new edge
|
||
*/
|
||
addEdge(x, y, weight) {
|
||
let edge = new EdgeNode_1.default(y, weight);
|
||
if (this.edges[x]) {
|
||
edge.next = this.edges[x];
|
||
}
|
||
this.edges[x] = edge;
|
||
if (!this.directed) {
|
||
edge = new EdgeNode_1.default(x, weight);
|
||
if (this.edges[y]) {
|
||
edge.next = this.edges[y];
|
||
}
|
||
this.edges[y] = edge;
|
||
}
|
||
this.numEdges += 1;
|
||
}
|
||
/**
|
||
* Checks whether or not an edge exists between two nodes.
|
||
* This check is directional if this is a directed graph.
|
||
* @param x The first node
|
||
* @param y The second node
|
||
* @returns true if an edge exists, false otherwise
|
||
*/
|
||
edgeExists(x, y) {
|
||
let edge = this.edges[x];
|
||
while (edge !== null) {
|
||
if (edge.y === y) {
|
||
return true;
|
||
}
|
||
edge = edge.next;
|
||
}
|
||
}
|
||
/**
|
||
* Gets the edge list associated with node x
|
||
* @param x The index of the node
|
||
* @returns The head of a linked-list of edges
|
||
*/
|
||
getEdges(x) {
|
||
return this.edges[x];
|
||
}
|
||
/**
|
||
* Gets the degree associated with node x
|
||
* @param x The index of the node
|
||
*/
|
||
getDegree(x) {
|
||
return this.degree[x];
|
||
}
|
||
/**
|
||
* Converts the specifed node into a string
|
||
* @param index The index of the node to convert to a string
|
||
* @returns The string representation of the node: "Node x"
|
||
*/
|
||
nodeToString(index) {
|
||
return "Node " + index;
|
||
}
|
||
/**
|
||
* Converts the Graph into a string format
|
||
* @returns The graph as a string
|
||
*/
|
||
toString() {
|
||
let retval = "";
|
||
for (let i = 0; i < this.numVertices; i++) {
|
||
let edge = this.edges[i];
|
||
let edgeStr = "";
|
||
while (edge !== undefined && edge !== null) {
|
||
edgeStr += edge.y.toString();
|
||
if (this.weighted) {
|
||
edgeStr += " (" + edge.weight + ")";
|
||
}
|
||
if (edge.next !== null) {
|
||
edgeStr += ", ";
|
||
}
|
||
edge = edge.next;
|
||
}
|
||
retval += this.nodeToString(i) + ": " + edgeStr + "\n";
|
||
}
|
||
return retval;
|
||
}
|
||
}
|
||
exports.default = Graph;
|
||
|
||
},{"./EdgeNode":6}],8:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Graph_1 = require("./Graph");
|
||
/**
|
||
* An extension of Graph that has nodes with positions in 2D space.
|
||
* This is a weighted graph (though not inherently directd)
|
||
*/
|
||
class PositionGraph extends Graph_1.default {
|
||
/**
|
||
* Createes a new PositionGraph
|
||
* @param directed Whether or not this graph is directed
|
||
*/
|
||
constructor(directed = false) {
|
||
super(directed);
|
||
this.debugRender = () => {
|
||
// for(let point of this.positions){
|
||
// ctx.fillRect((point.x - origin.x - 4)*zoom, (point.y - origin.y - 4)*zoom, 8, 8);
|
||
// }
|
||
};
|
||
this.positions = new Array(Graph_1.MAX_V);
|
||
}
|
||
/**
|
||
* Adds a positioned node to this graph
|
||
* @param position The position of the node to add
|
||
* @returns The index of the added node
|
||
*/
|
||
addPositionedNode(position) {
|
||
this.positions[this.numVertices] = position;
|
||
return this.addNode();
|
||
}
|
||
/**
|
||
* Changes the position of a node.
|
||
* Automatically adjusts the weights of the graph tied to this node.
|
||
* As such, be warned that this function has an O(n + m) running time, and use it sparingly.
|
||
* @param index The index of the node
|
||
* @param position The new position of the node
|
||
*/
|
||
setNodePosition(index, position) {
|
||
this.positions[index] = position;
|
||
// Recalculate all weights associated with this index
|
||
for (let i = 0; i < this.numEdges; i++) {
|
||
let edge = this.edges[i];
|
||
while (edge !== null) {
|
||
// If this node is on either side of the edge, recalculate weight
|
||
if (i === index || edge.y === index) {
|
||
edge.weight = this.positions[i].distanceTo(this.positions[edge.y]);
|
||
}
|
||
edge = edge.next;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Gets the position of a node
|
||
* @param index The index of the node
|
||
* @returns The position of the node
|
||
*/
|
||
getNodePosition(index) {
|
||
return this.positions[index];
|
||
}
|
||
/**
|
||
* Adds an edge to this graph between node x and y.
|
||
* Automatically calculates the weight of the edge as the distance between the nodes.
|
||
* @param x The beginning of the edge
|
||
* @param y The end of the edge
|
||
*/
|
||
addEdge(x, y) {
|
||
if (!this.positions[x] || !this.positions[y]) {
|
||
throw "Can't add edge to un-positioned node!";
|
||
}
|
||
// Weight is the distance between the nodes
|
||
let weight = this.positions[x].distanceTo(this.positions[y]);
|
||
super.addEdge(x, y, weight);
|
||
}
|
||
// @override
|
||
nodeToString(index) {
|
||
return "Node " + index + " - " + this.positions[index].toString();
|
||
}
|
||
}
|
||
exports.default = PositionGraph;
|
||
|
||
},{"./Graph":7}],9:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.isRegion = void 0;
|
||
function isRegion(arg) {
|
||
return arg && arg.size && arg.scale && arg.boundary;
|
||
}
|
||
exports.isRegion = isRegion;
|
||
|
||
},{}],10:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/**
|
||
* Associates strings with elements of type T
|
||
*/
|
||
class Map {
|
||
/** Creates a new map */
|
||
constructor() {
|
||
this.map = {};
|
||
}
|
||
/**
|
||
* Adds a value T stored at a key.
|
||
* @param key The key of the item to be stored
|
||
* @param value The item to be stored
|
||
*/
|
||
add(key, value) {
|
||
this.map[key] = value;
|
||
}
|
||
/**
|
||
* Get the value associated with a key.
|
||
* @param key The key of the item
|
||
* @returns The item at the key or undefined
|
||
*/
|
||
get(key) {
|
||
return this.map[key];
|
||
}
|
||
/**
|
||
* An alias of add. Sets the value stored at key to the new specified value
|
||
* @param key The key of the item to be stored
|
||
* @param value The item to be stored
|
||
*/
|
||
set(key, value) {
|
||
this.add(key, value);
|
||
}
|
||
/**
|
||
* Returns true if there is a value stored at the specified key, false otherwise.
|
||
* @param key The key to check
|
||
* @returns A boolean representing whether or not there is an item at the given key.
|
||
*/
|
||
has(key) {
|
||
return this.map[key] !== undefined;
|
||
}
|
||
/**
|
||
* Returns an array of all of the keys in this map.
|
||
* @returns An array containing all keys in the map.
|
||
*/
|
||
keys() {
|
||
return Object.keys(this.map);
|
||
}
|
||
// @implemented
|
||
forEach(func) {
|
||
Object.keys(this.map).forEach(key => func(key));
|
||
}
|
||
/**
|
||
* Deletes an item associated with a key
|
||
* @param key The key at which to delete an item
|
||
*/
|
||
delete(key) {
|
||
delete this.map[key];
|
||
}
|
||
// @implemented
|
||
clear() {
|
||
this.forEach(key => delete this.map[key]);
|
||
}
|
||
/**
|
||
* Converts this map to a string representation.
|
||
* @returns The string representation of this map.
|
||
*/
|
||
toString() {
|
||
let str = "";
|
||
this.forEach((key) => str += key + " -> " + this.get(key).toString() + "\n");
|
||
return str;
|
||
}
|
||
}
|
||
exports.default = Map;
|
||
|
||
},{}],11:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("./Vec2");
|
||
/** A 4x4 matrix0 */
|
||
class Mat4x4 {
|
||
constructor() {
|
||
this.mat = new Float32Array([
|
||
0, 0, 0, 0,
|
||
0, 0, 0, 0,
|
||
0, 0, 0, 0,
|
||
0, 0, 0, 0
|
||
]);
|
||
}
|
||
// Static members
|
||
static get IDENTITY() {
|
||
return new Mat4x4().identity();
|
||
}
|
||
static get ZERO() {
|
||
return new Mat4x4().zero();
|
||
}
|
||
// Accessors
|
||
set _00(x) {
|
||
this.mat[0] = x;
|
||
}
|
||
set(col, row, value) {
|
||
if (col < 0 || col > 3 || row < 0 || row > 3) {
|
||
throw `Error - index (${col}, ${row}) is out of bounds for Mat4x4`;
|
||
}
|
||
this.mat[row * 4 + col] = value;
|
||
return this;
|
||
}
|
||
get(col, row) {
|
||
return this.mat[row * 4 + col];
|
||
}
|
||
setAll(...items) {
|
||
this.mat.set(items);
|
||
return this;
|
||
}
|
||
identity() {
|
||
return this.setAll(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||
}
|
||
zero() {
|
||
return this.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||
}
|
||
/**
|
||
* Makes this Mat4x4 a rotation matrix of the specified number of radians ccw
|
||
* @param zRadians The number of radians to rotate
|
||
* @returns this Mat4x4
|
||
*/
|
||
rotate(zRadians) {
|
||
return this.setAll(Math.cos(zRadians), -Math.sin(zRadians), 0, 0, Math.sin(zRadians), Math.cos(zRadians), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||
}
|
||
/**
|
||
* Turns this Mat4x4 into a translation matrix of the specified translation
|
||
* @param translation The translation in x and y
|
||
* @returns this Mat4x4
|
||
*/
|
||
translate(translation) {
|
||
// If translation is a vec, get its array
|
||
if (translation instanceof Vec2_1.default) {
|
||
translation = translation.toArray();
|
||
}
|
||
return this.setAll(1, 0, 0, translation[0], 0, 1, 0, translation[1], 0, 0, 1, 0, 0, 0, 0, 1);
|
||
}
|
||
scale(scale) {
|
||
// Make sure scale is a float32Array
|
||
if (scale instanceof Vec2_1.default) {
|
||
scale = scale.toArray();
|
||
}
|
||
else if (!(scale instanceof Float32Array)) {
|
||
scale = new Float32Array([scale, scale]);
|
||
}
|
||
return this.setAll(scale[0], 0, 0, 0, 0, scale[1], 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||
}
|
||
/**
|
||
* Returns a new Mat4x4 that represents the right side multiplication THIS x OTHER
|
||
* @param other The other Mat4x4 to multiply by
|
||
* @returns a new Mat4x4 containing the product of these two Mat4x4s
|
||
*/
|
||
mult(other, out) {
|
||
let temp = new Float32Array(16);
|
||
for (let i = 0; i < 4; i++) {
|
||
for (let j = 0; j < 4; j++) {
|
||
let value = 0;
|
||
for (let k = 0; k < 4; k++) {
|
||
value += this.get(k, i) * other.get(j, k);
|
||
}
|
||
temp[j * 4 + i] = value;
|
||
}
|
||
}
|
||
if (out !== undefined) {
|
||
return out.setAll(...temp);
|
||
}
|
||
else {
|
||
return new Mat4x4().setAll(...temp);
|
||
}
|
||
}
|
||
/**
|
||
* Multiplies all given matricies in order. e.g. MULT(A, B, C) -> A*B*C
|
||
* @param mats A list of Mat4x4s to multiply in order
|
||
* @returns A new Mat4x4 holding the result of the operation
|
||
*/
|
||
static MULT(...mats) {
|
||
// Create a new array
|
||
let temp = Mat4x4.IDENTITY;
|
||
// Multiply by every array in order, in place
|
||
for (let i = 0; i < mats.length; i++) {
|
||
temp.mult(mats[i], temp);
|
||
}
|
||
return temp;
|
||
}
|
||
toArray() {
|
||
return this.mat;
|
||
}
|
||
toString() {
|
||
return `|${this.mat[0].toFixed(2)}, ${this.mat[1].toFixed(2)}, ${this.mat[2].toFixed(2)}, ${this.mat[3].toFixed(2)}|\n` +
|
||
`|${this.mat[4].toFixed(2)}, ${this.mat[5].toFixed(2)}, ${this.mat[6].toFixed(2)}, ${this.mat[7].toFixed(2)}|\n` +
|
||
`|${this.mat[8].toFixed(2)}, ${this.mat[9].toFixed(2)}, ${this.mat[10].toFixed(2)}, ${this.mat[11].toFixed(2)}|\n` +
|
||
`|${this.mat[12].toFixed(2)}, ${this.mat[13].toFixed(2)}, ${this.mat[14].toFixed(2)}, ${this.mat[15].toFixed(2)}|`;
|
||
}
|
||
}
|
||
exports.default = Mat4x4;
|
||
|
||
},{"./Vec2":24}],12:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/**
|
||
* A class that contains the area of overlap of two colliding objects to allow for sorting by the physics system.
|
||
*/
|
||
class AreaCollision {
|
||
/**
|
||
* Creates a new AreaCollision object
|
||
* @param area The area of the collision
|
||
* @param collider The other collider
|
||
*/
|
||
constructor(area, collider, other, type, tile) {
|
||
this.area = area;
|
||
this.collider = collider;
|
||
this.other = other;
|
||
this.type = type;
|
||
this.tile = tile;
|
||
}
|
||
}
|
||
exports.default = AreaCollision;
|
||
|
||
},{}],13:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../Vec2");
|
||
/**
|
||
* An object representing the data collected from a physics hit between two geometric objects.
|
||
* Inspired by the helpful collision documentation @link(here)(https://noonat.github.io/intersect/).
|
||
*/
|
||
class Hit {
|
||
constructor() {
|
||
/** The near times of the collision */
|
||
this.nearTimes = Vec2_1.default.ZERO;
|
||
/** The position of the collision */
|
||
this.pos = Vec2_1.default.ZERO;
|
||
/** The overlap distance of the hit */
|
||
this.delta = Vec2_1.default.ZERO;
|
||
/** The normal vector of the hit */
|
||
this.normal = Vec2_1.default.ZERO;
|
||
}
|
||
}
|
||
exports.default = Hit;
|
||
|
||
},{"../Vec2":24}],14:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/**
|
||
* A FIFO queue with elements of type T
|
||
*/
|
||
class Queue {
|
||
/**
|
||
* Constructs a new queue
|
||
* @param maxElements The maximum size of the stack
|
||
*/
|
||
constructor(maxElements = 100) {
|
||
this.MAX_ELEMENTS = maxElements;
|
||
this.q = new Array(this.MAX_ELEMENTS);
|
||
this.head = 0;
|
||
this.tail = 0;
|
||
this.size = 0;
|
||
}
|
||
/**
|
||
* Adds an item to the back of the queue
|
||
* @param item The item to add to the back of the queue
|
||
*/
|
||
enqueue(item) {
|
||
if ((this.tail + 1) % this.MAX_ELEMENTS === this.head) {
|
||
throw new Error("Queue full - cannot add element");
|
||
}
|
||
this.size += 1;
|
||
this.q[this.tail] = item;
|
||
this.tail = (this.tail + 1) % this.MAX_ELEMENTS;
|
||
}
|
||
/**
|
||
* Retrieves an item from the front of the queue
|
||
* @returns The item at the front of the queue
|
||
*/
|
||
dequeue() {
|
||
if (this.head === this.tail) {
|
||
throw new Error("Queue empty - cannot remove element");
|
||
}
|
||
this.size -= 1;
|
||
let item = this.q[this.head];
|
||
// Now delete the item
|
||
delete this.q[this.head];
|
||
this.head = (this.head + 1) % this.MAX_ELEMENTS;
|
||
return item;
|
||
}
|
||
/**
|
||
* Returns the item at the front of the queue, but does not remove it
|
||
* @returns The item at the front of the queue
|
||
*/
|
||
peekNext() {
|
||
if (this.head === this.tail) {
|
||
throw "Queue empty - cannot get element";
|
||
}
|
||
let item = this.q[this.head];
|
||
return item;
|
||
}
|
||
/**
|
||
* Returns true if the queue has items in it, false otherwise
|
||
* @returns A boolean representing whether or not this queue has items
|
||
*/
|
||
hasItems() {
|
||
return this.head !== this.tail;
|
||
}
|
||
/**
|
||
* Returns the number of elements in the queue.
|
||
* @returns The size of the queue
|
||
*/
|
||
getSize() {
|
||
return this.size;
|
||
}
|
||
// @implemented
|
||
clear() {
|
||
this.forEach((item, index) => delete this.q[index]);
|
||
this.size = 0;
|
||
this.head = this.tail;
|
||
}
|
||
// @implemented
|
||
forEach(func) {
|
||
let i = this.head;
|
||
while (i !== this.tail) {
|
||
func(this.q[i], i);
|
||
i = (i + 1) % this.MAX_ELEMENTS;
|
||
}
|
||
}
|
||
/**
|
||
* Converts this queue into a string format
|
||
* @returns A string representing this queue
|
||
*/
|
||
toString() {
|
||
let retval = "";
|
||
this.forEach((item, index) => {
|
||
let str = item.toString();
|
||
if (index !== 0) {
|
||
str += " -> ";
|
||
}
|
||
retval = str + retval;
|
||
});
|
||
return "Top -> " + retval;
|
||
}
|
||
}
|
||
exports.default = Queue;
|
||
|
||
},{}],15:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/** A container for info about a webGL shader program */
|
||
class WebGLProgramType {
|
||
/**
|
||
* Deletes this shader program
|
||
*/
|
||
delete(gl) {
|
||
// Clean up all aspects of this program
|
||
if (this.program) {
|
||
gl.deleteProgram(this.program);
|
||
}
|
||
if (this.vertexShader) {
|
||
gl.deleteShader(this.vertexShader);
|
||
}
|
||
if (this.fragmentShader) {
|
||
gl.deleteShader(this.fragmentShader);
|
||
}
|
||
}
|
||
}
|
||
exports.default = WebGLProgramType;
|
||
|
||
},{}],16:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Shape_1 = require("./Shape");
|
||
const Vec2_1 = require("../Vec2");
|
||
const MathUtils_1 = require("../../Utils/MathUtils");
|
||
const Circle_1 = require("./Circle");
|
||
const Hit_1 = require("../Physics/Hit");
|
||
/**
|
||
* An Axis-Aligned Bounding Box. In other words, a rectangle that is always aligned to the x-y grid.
|
||
* Inspired by the helpful collision documentation @link(here)(https://noonat.github.io/intersect/).
|
||
*/
|
||
class AABB extends Shape_1.default {
|
||
/**
|
||
* Creates a new AABB
|
||
* @param center The center of the AABB
|
||
* @param halfSize The half size of the AABB - The distance from the center to an edge in x and y
|
||
*/
|
||
constructor(center, halfSize) {
|
||
super();
|
||
this.center = center ? center : new Vec2_1.default(0, 0);
|
||
this.halfSize = halfSize ? halfSize : new Vec2_1.default(0, 0);
|
||
}
|
||
/** Returns a point representing the top left corner of the AABB */
|
||
get topLeft() {
|
||
return new Vec2_1.default(this.left, this.top);
|
||
}
|
||
/** Returns a point representing the top right corner of the AABB */
|
||
get topRight() {
|
||
return new Vec2_1.default(this.right, this.top);
|
||
}
|
||
/** Returns a point representing the bottom left corner of the AABB */
|
||
get bottomLeft() {
|
||
return new Vec2_1.default(this.left, this.bottom);
|
||
}
|
||
/** Returns a point representing the bottom right corner of the AABB */
|
||
get bottomRight() {
|
||
return new Vec2_1.default(this.right, this.bottom);
|
||
}
|
||
// @override
|
||
getBoundingRect() {
|
||
return this.clone();
|
||
}
|
||
// @override
|
||
getBoundingCircle() {
|
||
let r = Math.max(this.hw, this.hh);
|
||
return new Circle_1.default(this.center.clone(), r);
|
||
}
|
||
// @deprecated
|
||
getHalfSize() {
|
||
return this.halfSize;
|
||
}
|
||
// @deprecated
|
||
setHalfSize(halfSize) {
|
||
this.halfSize = halfSize;
|
||
}
|
||
// TODO - move these all to the Shape class
|
||
/**
|
||
* A simple boolean check of whether this AABB contains a point
|
||
* @param point The point to check
|
||
* @returns A boolean representing whether this AABB contains the specified point
|
||
*/
|
||
containsPoint(point) {
|
||
return point.x >= this.x - this.hw && point.x <= this.x + this.hw
|
||
&& point.y >= this.y - this.hh && point.y <= this.y + this.hh;
|
||
}
|
||
/**
|
||
* A simple boolean check of whether this AABB contains a point
|
||
* @param point The point to check
|
||
* @returns A boolean representing whether this AABB contains the specified point
|
||
*/
|
||
intersectPoint(point) {
|
||
let dx = point.x - this.x;
|
||
let px = this.hw - Math.abs(dx);
|
||
if (px <= 0) {
|
||
return false;
|
||
}
|
||
let dy = point.y - this.y;
|
||
let py = this.hh - Math.abs(dy);
|
||
if (py <= 0) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
/**
|
||
* A boolean check of whether this AABB contains a point with soft left and top boundaries.
|
||
* In other words, if the top left is (0, 0), the point (0, 0) is not in the AABB
|
||
* @param point The point to check
|
||
* @returns A boolean representing whether this AABB contains the specified point
|
||
*/
|
||
containsPointSoft(point) {
|
||
return point.x > this.x - this.hw && point.x <= this.x + this.hw
|
||
&& point.y > this.y - this.hh && point.y <= this.y + this.hh;
|
||
}
|
||
/**
|
||
* Returns the data from the intersection of this AABB with a line segment from a point in a direction
|
||
* @param point The point that the line segment starts from
|
||
* @param delta The direction and distance of the segment
|
||
* @param padding Pads the AABB to make it wider for the intersection test
|
||
* @returns The Hit object representing the intersection, or null if there was no intersection
|
||
*/
|
||
intersectSegment(point, delta, padding) {
|
||
let paddingX = padding ? padding.x : 0;
|
||
let paddingY = padding ? padding.y : 0;
|
||
let scaleX = 1 / delta.x;
|
||
let scaleY = 1 / delta.y;
|
||
let signX = MathUtils_1.default.sign(scaleX);
|
||
let signY = MathUtils_1.default.sign(scaleY);
|
||
let tnearx = scaleX * (this.x - signX * (this.hw + paddingX) - point.x);
|
||
let tneary = scaleY * (this.y - signY * (this.hh + paddingY) - point.y);
|
||
let tfarx = scaleX * (this.x + signX * (this.hw + paddingX) - point.x);
|
||
let tfary = scaleY * (this.y + signY * (this.hh + paddingY) - point.y);
|
||
if (tnearx > tfary || tneary > tfarx) {
|
||
// We aren't colliding - we clear one axis before intersecting another
|
||
return null;
|
||
}
|
||
let tnear = Math.max(tnearx, tneary);
|
||
// Double check for NaNs
|
||
if (tnearx !== tnearx) {
|
||
tnear = tneary;
|
||
}
|
||
else if (tneary !== tneary) {
|
||
tnear = tnearx;
|
||
}
|
||
let tfar = Math.min(tfarx, tfary);
|
||
if (tnear === -Infinity) {
|
||
return null;
|
||
}
|
||
if (tnear >= 1 || tfar <= 0) {
|
||
return null;
|
||
}
|
||
// We are colliding
|
||
let hit = new Hit_1.default();
|
||
hit.time = MathUtils_1.default.clamp01(tnear);
|
||
hit.nearTimes.x = tnearx;
|
||
hit.nearTimes.y = tneary;
|
||
if (tnearx > tneary) {
|
||
// We hit on the left or right size
|
||
hit.normal.x = -signX;
|
||
hit.normal.y = 0;
|
||
}
|
||
else if (Math.abs(tnearx - tneary) < 0.0001) {
|
||
// We hit on the corner
|
||
hit.normal.x = -signX;
|
||
hit.normal.y = -signY;
|
||
hit.normal.normalize();
|
||
}
|
||
else {
|
||
// We hit on the top or bottom
|
||
hit.normal.x = 0;
|
||
hit.normal.y = -signY;
|
||
}
|
||
hit.delta.x = (1.0 - hit.time) * -delta.x;
|
||
hit.delta.y = (1.0 - hit.time) * -delta.y;
|
||
hit.pos.x = point.x + delta.x * hit.time;
|
||
hit.pos.y = point.y + delta.y * hit.time;
|
||
return hit;
|
||
}
|
||
// @override
|
||
overlaps(other) {
|
||
if (other instanceof AABB) {
|
||
return this.overlapsAABB(other);
|
||
}
|
||
throw "Overlap not defined between these shapes.";
|
||
}
|
||
/**
|
||
* A simple boolean check of whether this AABB overlaps another
|
||
* @param other The other AABB to check against
|
||
* @returns True if this AABB overlaps the other, false otherwise
|
||
*/
|
||
overlapsAABB(other) {
|
||
let dx = other.x - this.x;
|
||
let px = this.hw + other.hw - Math.abs(dx);
|
||
if (px <= 0) {
|
||
return false;
|
||
}
|
||
let dy = other.y - this.y;
|
||
let py = this.hh + other.hh - Math.abs(dy);
|
||
if (py <= 0) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
/**
|
||
* Determines whether these AABBs are JUST touching - not overlapping.
|
||
* Vec2.x is -1 if the other is to the left, 1 if to the right.
|
||
* Likewise, Vec2.y is -1 if the other is on top, 1 if on bottom.
|
||
* @param other The other AABB to check
|
||
* @returns The collision sides stored in a Vec2 if the AABBs are touching, null otherwise
|
||
*/
|
||
touchesAABB(other) {
|
||
let dx = other.x - this.x;
|
||
let px = this.hw + other.hw - Math.abs(dx);
|
||
let dy = other.y - this.y;
|
||
let py = this.hh + other.hh - Math.abs(dy);
|
||
// If one axis is just touching and the other is overlapping, true
|
||
if ((px === 0 && py >= 0) || (py === 0 && px >= 0)) {
|
||
let ret = new Vec2_1.default();
|
||
if (px === 0) {
|
||
ret.x = other.x < this.x ? -1 : 1;
|
||
}
|
||
if (py === 0) {
|
||
ret.y = other.y < this.y ? -1 : 1;
|
||
}
|
||
return ret;
|
||
}
|
||
else {
|
||
return null;
|
||
}
|
||
}
|
||
/**
|
||
* Determines whether these AABBs are JUST touching - not overlapping.
|
||
* Also, if they are only touching corners, they are considered not touching.
|
||
* Vec2.x is -1 if the other is to the left, 1 if to the right.
|
||
* Likewise, Vec2.y is -1 if the other is on top, 1 if on bottom.
|
||
* @param other The other AABB to check
|
||
* @returns The side of the touch, stored as a Vec2, or null if there is no touch
|
||
*/
|
||
touchesAABBWithoutCorners(other) {
|
||
let dx = other.x - this.x;
|
||
let px = this.hw + other.hw - Math.abs(dx);
|
||
let dy = other.y - this.y;
|
||
let py = this.hh + other.hh - Math.abs(dy);
|
||
// If one axis is touching, and the other is strictly overlapping
|
||
if ((px === 0 && py > 0) || (py === 0 && px > 0)) {
|
||
let ret = new Vec2_1.default();
|
||
if (px === 0) {
|
||
ret.x = other.x < this.x ? -1 : 1;
|
||
}
|
||
else {
|
||
ret.y = other.y < this.y ? -1 : 1;
|
||
}
|
||
return ret;
|
||
}
|
||
else {
|
||
return null;
|
||
}
|
||
}
|
||
/**
|
||
* Calculates the area of the overlap between this AABB and another
|
||
* @param other The other AABB
|
||
* @returns The area of the overlap between the AABBs
|
||
*/
|
||
overlapArea(other) {
|
||
let leftx = Math.max(this.x - this.hw, other.x - other.hw);
|
||
let rightx = Math.min(this.x + this.hw, other.x + other.hw);
|
||
let dx = rightx - leftx;
|
||
let lefty = Math.max(this.y - this.hh, other.y - other.hh);
|
||
let righty = Math.min(this.y + this.hh, other.y + other.hh);
|
||
let dy = righty - lefty;
|
||
if (dx < 0 || dy < 0)
|
||
return 0;
|
||
return dx * dy;
|
||
}
|
||
/**
|
||
* Moves and resizes this rect from its current position to the position specified
|
||
* @param velocity The movement of the rect from its position
|
||
* @param fromPosition A position specified to be the starting point of sweeping
|
||
* @param halfSize The halfSize of the sweeping rect
|
||
*/
|
||
sweep(velocity, fromPosition, halfSize) {
|
||
if (!fromPosition) {
|
||
fromPosition = this.center;
|
||
}
|
||
if (!halfSize) {
|
||
halfSize = this.halfSize;
|
||
}
|
||
let centerX = fromPosition.x + velocity.x / 2;
|
||
let centerY = fromPosition.y + velocity.y / 2;
|
||
let minX = Math.min(fromPosition.x - halfSize.x, fromPosition.x + velocity.x - halfSize.x);
|
||
let minY = Math.min(fromPosition.y - halfSize.y, fromPosition.y + velocity.y - halfSize.y);
|
||
this.center.set(centerX, centerY);
|
||
this.halfSize.set(centerX - minX, centerY - minY);
|
||
}
|
||
// @override
|
||
clone() {
|
||
return new AABB(this.center.clone(), this.halfSize.clone());
|
||
}
|
||
/**
|
||
* Converts this AABB to a string format
|
||
* @returns (center: (x, y), halfSize: (x, y))
|
||
*/
|
||
toString() {
|
||
return "(center: " + this.center.toString() + ", half-size: " + this.halfSize.toString() + ")";
|
||
}
|
||
}
|
||
exports.default = AABB;
|
||
|
||
},{"../../Utils/MathUtils":102,"../Physics/Hit":13,"../Vec2":24,"./Circle":17,"./Shape":18}],17:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../Vec2");
|
||
const AABB_1 = require("./AABB");
|
||
const Shape_1 = require("./Shape");
|
||
/**
|
||
* A Circle
|
||
*/
|
||
class Circle extends Shape_1.default {
|
||
/**
|
||
* Creates a new Circle
|
||
* @param center The center of the circle
|
||
* @param radius The radius of the circle
|
||
*/
|
||
constructor(center, radius) {
|
||
super();
|
||
this._center = center ? center : new Vec2_1.default(0, 0);
|
||
this.radius = radius ? radius : 0;
|
||
}
|
||
get center() {
|
||
return this._center;
|
||
}
|
||
set center(center) {
|
||
this._center = center;
|
||
}
|
||
get halfSize() {
|
||
return new Vec2_1.default(this.radius, this.radius);
|
||
}
|
||
get r() {
|
||
return this.radius;
|
||
}
|
||
set r(radius) {
|
||
this.radius = radius;
|
||
}
|
||
// @override
|
||
/**
|
||
* A simple boolean check of whether this AABB contains a point
|
||
* @param point The point to check
|
||
* @returns A boolean representing whether this AABB contains the specified point
|
||
*/
|
||
containsPoint(point) {
|
||
return this.center.distanceSqTo(point) <= this.radius * this.radius;
|
||
}
|
||
// @override
|
||
getBoundingRect() {
|
||
return new AABB_1.default(this._center.clone(), new Vec2_1.default(this.radius, this.radius));
|
||
}
|
||
// @override
|
||
getBoundingCircle() {
|
||
return this.clone();
|
||
}
|
||
// @override
|
||
overlaps(other) {
|
||
throw new Error("Method not implemented.");
|
||
}
|
||
// @override
|
||
clone() {
|
||
return new Circle(this._center.clone(), this.radius);
|
||
}
|
||
toString() {
|
||
return "(center: " + this.center.toString() + ", radius: " + this.radius + ")";
|
||
}
|
||
}
|
||
exports.default = Circle;
|
||
|
||
},{"../Vec2":24,"./AABB":16,"./Shape":18}],18:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../Vec2");
|
||
const AABB_1 = require("./AABB");
|
||
/**
|
||
* An abstract Shape class that acts as an interface for better interactions with subclasses.
|
||
*/
|
||
class Shape {
|
||
get x() {
|
||
return this.center.x;
|
||
}
|
||
get y() {
|
||
return this.center.y;
|
||
}
|
||
get hw() {
|
||
return this.halfSize.x;
|
||
}
|
||
get hh() {
|
||
return this.halfSize.y;
|
||
}
|
||
get top() {
|
||
return this.y - this.hh;
|
||
}
|
||
get bottom() {
|
||
return this.y + this.hh;
|
||
}
|
||
get left() {
|
||
return this.x - this.hw;
|
||
}
|
||
get right() {
|
||
return this.x + this.hw;
|
||
}
|
||
static getTimeOfCollision(A, velA, B, velB) {
|
||
if (A instanceof AABB_1.default && B instanceof AABB_1.default) {
|
||
return Shape.getTimeOfCollision_AABB_AABB(A, velA, B, velB);
|
||
}
|
||
}
|
||
static getTimeOfCollision_AABB_AABB(A, velA, B, velB) {
|
||
let posSmaller = A.center;
|
||
let posLarger = B.center;
|
||
let sizeSmaller = A.halfSize;
|
||
let sizeLarger = B.halfSize;
|
||
let firstContact = new Vec2_1.default(0, 0);
|
||
let lastContact = new Vec2_1.default(0, 0);
|
||
let collidingX = false;
|
||
let collidingY = false;
|
||
// Sort by position
|
||
if (posLarger.x < posSmaller.x) {
|
||
// Swap, because smaller is further right than larger
|
||
let temp;
|
||
temp = sizeSmaller;
|
||
sizeSmaller = sizeLarger;
|
||
sizeLarger = temp;
|
||
temp = posSmaller;
|
||
posSmaller = posLarger;
|
||
posLarger = temp;
|
||
temp = velA;
|
||
velA = velB;
|
||
velB = temp;
|
||
}
|
||
// A is left, B is right
|
||
firstContact.x = Infinity;
|
||
lastContact.x = Infinity;
|
||
if (posLarger.x - sizeLarger.x >= posSmaller.x + sizeSmaller.x) {
|
||
// If we aren't currently colliding
|
||
let relVel = velA.x - velB.x;
|
||
if (relVel > 0) {
|
||
// If they are moving towards each other
|
||
firstContact.x = ((posLarger.x - sizeLarger.x) - (posSmaller.x + sizeSmaller.x)) / (relVel);
|
||
lastContact.x = ((posLarger.x + sizeLarger.x) - (posSmaller.x - sizeSmaller.x)) / (relVel);
|
||
}
|
||
}
|
||
else {
|
||
collidingX = true;
|
||
}
|
||
if (posLarger.y < posSmaller.y) {
|
||
// Swap, because smaller is further up than larger
|
||
let temp;
|
||
temp = sizeSmaller;
|
||
sizeSmaller = sizeLarger;
|
||
sizeLarger = temp;
|
||
temp = posSmaller;
|
||
posSmaller = posLarger;
|
||
posLarger = temp;
|
||
temp = velA;
|
||
velA = velB;
|
||
velB = temp;
|
||
}
|
||
// A is top, B is bottom
|
||
firstContact.y = Infinity;
|
||
lastContact.y = Infinity;
|
||
if (posLarger.y - sizeLarger.y >= posSmaller.y + sizeSmaller.y) {
|
||
// If we aren't currently colliding
|
||
let relVel = velA.y - velB.y;
|
||
if (relVel > 0) {
|
||
// If they are moving towards each other
|
||
firstContact.y = ((posLarger.y - sizeLarger.y) - (posSmaller.y + sizeSmaller.y)) / (relVel);
|
||
lastContact.y = ((posLarger.y + sizeLarger.y) - (posSmaller.y - sizeSmaller.y)) / (relVel);
|
||
}
|
||
}
|
||
else {
|
||
collidingY = true;
|
||
}
|
||
return [firstContact, lastContact, collidingX, collidingY];
|
||
}
|
||
}
|
||
exports.default = Shape;
|
||
|
||
},{"../Vec2":24,"./AABB":16}],19:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/**
|
||
* A LIFO stack with items of type T
|
||
*/
|
||
class Stack {
|
||
/**
|
||
* Constructs a new stack
|
||
* @param maxElements The maximum size of the stack
|
||
*/
|
||
constructor(maxElements = 100) {
|
||
this.MAX_ELEMENTS = maxElements;
|
||
this.stack = new Array(this.MAX_ELEMENTS);
|
||
this.head = -1;
|
||
}
|
||
/**
|
||
* Adds an item to the top of the stack
|
||
* @param item The new item to add to the stack
|
||
*/
|
||
push(item) {
|
||
if (this.head + 1 === this.MAX_ELEMENTS) {
|
||
throw "Stack full - cannot add element";
|
||
}
|
||
this.head += 1;
|
||
this.stack[this.head] = item;
|
||
}
|
||
/**
|
||
* Removes an item from the top of the stack
|
||
* @returns The item at the top of the stack
|
||
*/
|
||
pop() {
|
||
if (this.head === -1) {
|
||
throw "Stack empty - cannot remove element";
|
||
}
|
||
this.head -= 1;
|
||
return this.stack[this.head + 1];
|
||
}
|
||
/**
|
||
* Returns the element currently at the top of the stack
|
||
* @returns The item at the top of the stack
|
||
*/
|
||
peek() {
|
||
if (this.head === -1) {
|
||
throw "Stack empty - cannot get element";
|
||
}
|
||
return this.stack[this.head];
|
||
}
|
||
/** Returns true if this stack is empty
|
||
* @returns A boolean that represents whether or not the stack is empty
|
||
*/
|
||
isEmpty() {
|
||
return this.head === -1;
|
||
}
|
||
// @implemented
|
||
clear() {
|
||
this.forEach((item, index) => delete this.stack[index]);
|
||
this.head = -1;
|
||
}
|
||
/**
|
||
* Returns the number of items currently in the stack
|
||
* @returns The number of items in the stack
|
||
*/
|
||
size() {
|
||
return this.head + 1;
|
||
}
|
||
// @implemented
|
||
forEach(func) {
|
||
let i = 0;
|
||
while (i <= this.head) {
|
||
func(this.stack[i], i);
|
||
i += 1;
|
||
}
|
||
}
|
||
/**
|
||
* Converts this stack into a string format
|
||
* @returns A string representing this stack
|
||
*/
|
||
toString() {
|
||
let retval = "";
|
||
this.forEach((item, index) => {
|
||
let str = item.toString();
|
||
if (index !== 0) {
|
||
str += " -> ";
|
||
}
|
||
retval = str + retval;
|
||
});
|
||
return "Top -> " + retval;
|
||
}
|
||
}
|
||
exports.default = Stack;
|
||
|
||
},{}],20:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Emitter_1 = require("../../Events/Emitter");
|
||
/**
|
||
* An abstract implementation of a state for a @reference[StateMachine].
|
||
* This class should be extended to allow for custom state behaviors.
|
||
*/
|
||
class State {
|
||
/**
|
||
* Constructs a new State
|
||
* @param parent The parent StateMachine of this state
|
||
*/
|
||
constructor(parent) {
|
||
this.parent = parent;
|
||
this.emitter = new Emitter_1.default();
|
||
}
|
||
/**
|
||
* Tells the state machine that this state has ended, and makes it transition to the new state specified
|
||
* @param stateName The name of the state to transition to
|
||
*/
|
||
finished(stateName) {
|
||
this.parent.changeState(stateName);
|
||
}
|
||
}
|
||
exports.default = State;
|
||
|
||
},{"../../Events/Emitter":27}],21:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Stack_1 = require("../Stack");
|
||
const Map_1 = require("../Map");
|
||
const Receiver_1 = require("../../Events/Receiver");
|
||
const Emitter_1 = require("../../Events/Emitter");
|
||
/**
|
||
* An implementation of a Push Down Automata State machine. States can also be hierarchical
|
||
* for more flexibility, as described in @link(Game Programming Patterns)(https://gameprogrammingpatterns.com/state.html).
|
||
*/
|
||
class StateMachine {
|
||
/**
|
||
* Creates a new StateMachine
|
||
*/
|
||
constructor() {
|
||
this.stack = new Stack_1.default();
|
||
this.stateMap = new Map_1.default();
|
||
this.receiver = new Receiver_1.default();
|
||
this.emitter = new Emitter_1.default();
|
||
this.emitEventOnStateChange = false;
|
||
}
|
||
/**
|
||
* Sets the activity state of this state machine
|
||
* @param flag True if you want to set this machine running, false otherwise
|
||
*/
|
||
setActive(flag) {
|
||
this.active = flag;
|
||
}
|
||
/**
|
||
* Makes this state machine emit an event any time its state changes
|
||
* @param stateChangeEventName The name of the event to emit
|
||
*/
|
||
setEmitEventOnStateChange(stateChangeEventName) {
|
||
this.emitEventOnStateChange = true;
|
||
this.stateChangeEventName = stateChangeEventName;
|
||
}
|
||
/**
|
||
* Stops this state machine from emitting events on state change.
|
||
*/
|
||
cancelEmitEventOnStateChange() {
|
||
this.emitEventOnStateChange = false;
|
||
}
|
||
/**
|
||
* Initializes this state machine with an initial state and sets it running
|
||
* @param initialState The name of initial state of the state machine
|
||
*/
|
||
initialize(initialState, options) {
|
||
this.stack.push(this.stateMap.get(initialState));
|
||
this.currentState = this.stack.peek();
|
||
this.currentState.onEnter(options);
|
||
this.setActive(true);
|
||
}
|
||
/**
|
||
* Adds a state to this state machine
|
||
* @param stateName The name of the state to add
|
||
* @param state The state to add
|
||
*/
|
||
addState(stateName, state) {
|
||
this.stateMap.add(stateName, state);
|
||
}
|
||
/**
|
||
* Changes the state of this state machine to the provided string
|
||
* @param state The string name of the state to change to
|
||
*/
|
||
changeState(state) {
|
||
// Exit the current state
|
||
let options = this.currentState.onExit();
|
||
// Make sure the correct state is at the top of the stack
|
||
if (state === "previous") {
|
||
// Pop the current state off the stack
|
||
this.stack.pop();
|
||
}
|
||
else {
|
||
// Retrieve the new state from the statemap and put it at the top of the stack
|
||
this.stack.pop();
|
||
this.stack.push(this.stateMap.get(state));
|
||
}
|
||
// Retreive the new state from the stack
|
||
this.currentState = this.stack.peek();
|
||
// Emit an event if turned on
|
||
if (this.emitEventOnStateChange) {
|
||
this.emitter.fireEvent(this.stateChangeEventName, { state: this.currentState });
|
||
}
|
||
// Enter the new state
|
||
this.currentState.onEnter(options);
|
||
}
|
||
/**
|
||
* Handles input. This happens at the very beginning of this state machine's update cycle.
|
||
* @param event The game event to process
|
||
*/
|
||
handleEvent(event) {
|
||
if (this.active) {
|
||
this.currentState.handleInput(event);
|
||
}
|
||
}
|
||
// @implemented
|
||
update(deltaT) {
|
||
// Distribute events
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
this.handleEvent(event);
|
||
}
|
||
// Delegate the update to the current state
|
||
this.currentState.update(deltaT);
|
||
}
|
||
}
|
||
exports.default = StateMachine;
|
||
|
||
},{"../../Events/Emitter":27,"../../Events/Receiver":31,"../Map":10,"../Stack":19}],22:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.TiledCollectionTile = exports.TiledObject = exports.TiledLayerData = exports.TiledTilesetData = exports.TiledLayerProperty = exports.TiledTilemapData = void 0;
|
||
// @ignorePage
|
||
/**
|
||
* a representation of Tiled's tilemap data
|
||
*/
|
||
class TiledTilemapData {
|
||
}
|
||
exports.TiledTilemapData = TiledTilemapData;
|
||
/**
|
||
* A representation of a custom layer property in a Tiled tilemap
|
||
*/
|
||
class TiledLayerProperty {
|
||
}
|
||
exports.TiledLayerProperty = TiledLayerProperty;
|
||
/**
|
||
* A representation of a tileset in a Tiled tilemap
|
||
*/
|
||
class TiledTilesetData {
|
||
}
|
||
exports.TiledTilesetData = TiledTilesetData;
|
||
/**
|
||
* A representation of a layer in a Tiled tilemap
|
||
*/
|
||
class TiledLayerData {
|
||
}
|
||
exports.TiledLayerData = TiledLayerData;
|
||
class TiledObject {
|
||
;
|
||
}
|
||
exports.TiledObject = TiledObject;
|
||
class TiledCollectionTile {
|
||
}
|
||
exports.TiledCollectionTile = TiledCollectionTile;
|
||
|
||
},{}],23:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const Vec2_1 = require("../Vec2");
|
||
/**
|
||
* The data representation of a Tileset for the game engine. This represents one image,
|
||
* with a startIndex if required (as it is with Tiled using two images in one tilset).
|
||
*/
|
||
class Tileset {
|
||
// TODO: Change this to be more general and work with other tileset formats
|
||
constructor(tilesetData) {
|
||
// Defer handling of the data to a helper class
|
||
this.initFromTiledData(tilesetData);
|
||
}
|
||
/**
|
||
* Initialize the tileset from the data from a Tiled json file
|
||
* @param tiledData The parsed object from a Tiled json file
|
||
*/
|
||
initFromTiledData(tiledData) {
|
||
this.numRows = tiledData.tilecount / tiledData.columns;
|
||
this.numCols = tiledData.columns;
|
||
this.startIndex = tiledData.firstgid;
|
||
this.endIndex = this.startIndex + tiledData.tilecount - 1;
|
||
this.tileSize = new Vec2_1.default(tiledData.tilewidth, tiledData.tilewidth);
|
||
this.imageKey = tiledData.image;
|
||
this.imageSize = new Vec2_1.default(tiledData.imagewidth, tiledData.imageheight);
|
||
}
|
||
/**
|
||
* Gets the image key associated with this tilemap
|
||
* @returns The image key of this tilemap
|
||
*/
|
||
getImageKey() {
|
||
return this.imageKey;
|
||
}
|
||
/**
|
||
* Returns a Vec2 containing the left and top offset from the image origin for this tile.
|
||
* @param tileIndex The index of the tile from startIndex to endIndex of this tileset
|
||
* @returns A Vec2 containing the offset for the specified tile.
|
||
*/
|
||
getImageOffsetForTile(tileIndex) {
|
||
// Get the true index
|
||
let index = tileIndex - this.startIndex;
|
||
let row = Math.floor(index / this.numCols);
|
||
let col = index % this.numCols;
|
||
let width = this.tileSize.x;
|
||
let height = this.tileSize.y;
|
||
// Calculate the position to start a crop in the tileset image
|
||
let left = col * width;
|
||
let top = row * height;
|
||
return new Vec2_1.default(left, top);
|
||
}
|
||
/**
|
||
* Gets the start index
|
||
* @returns The start index
|
||
*/
|
||
getStartIndex() {
|
||
return this.startIndex;
|
||
}
|
||
/**
|
||
* Gets the tile set
|
||
* @returns A Vec2 containing the tile size
|
||
*/
|
||
getTileSize() {
|
||
return this.tileSize;
|
||
}
|
||
/**
|
||
* Gets the number of rows in the tileset
|
||
* @returns The number of rows
|
||
*/
|
||
getNumRows() {
|
||
return this.numRows;
|
||
}
|
||
/**
|
||
* Gets the number of columns in the tilset
|
||
* @returns The number of columns
|
||
*/
|
||
getNumCols() {
|
||
return this.numCols;
|
||
}
|
||
getTileCount() {
|
||
return this.endIndex - this.startIndex + 1;
|
||
}
|
||
/**
|
||
* Checks whether or not this tilset contains the specified tile index. This is used for rendering.
|
||
* @param tileIndex The index of the tile to check
|
||
* @returns A boolean representing whether or not this tilset uses the specified index
|
||
*/
|
||
hasTile(tileIndex) {
|
||
return tileIndex >= this.startIndex && tileIndex <= this.endIndex;
|
||
}
|
||
/**
|
||
* Render a singular tile with index tileIndex from the tileset located at position dataIndex
|
||
* @param ctx The rendering context
|
||
* @param tileIndex The value of the tile to render
|
||
* @param dataIndex The index of the tile in the data array
|
||
* @param worldSize The size of the world
|
||
* @param origin The viewport origin in the current layer
|
||
* @param scale The scale of the tilemap
|
||
*/
|
||
renderTile(ctx, tileIndex, dataIndex, maxCols, origin, scale, zoom) {
|
||
let image = ResourceManager_1.default.getInstance().getImage(this.imageKey);
|
||
// Get the true index
|
||
let index = tileIndex - this.startIndex;
|
||
let row = Math.floor(index / this.numCols);
|
||
let col = index % this.numCols;
|
||
let width = this.tileSize.x;
|
||
let height = this.tileSize.y;
|
||
// Calculate the position to start a crop in the tileset image
|
||
let left = col * width;
|
||
let top = row * height;
|
||
// Calculate the position in the world to render the tile
|
||
let x = Math.floor((dataIndex % maxCols) * width * scale.x);
|
||
let y = Math.floor(Math.floor(dataIndex / maxCols) * height * scale.y);
|
||
ctx.drawImage(image, left, top, width, height, Math.floor((x - origin.x) * zoom), Math.floor((y - origin.y) * zoom), Math.ceil(width * scale.x * zoom), Math.ceil(height * scale.y * zoom));
|
||
}
|
||
}
|
||
exports.default = Tileset;
|
||
|
||
},{"../../ResourceManager/ResourceManager":83,"../Vec2":24}],24:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const MathUtils_1 = require("../Utils/MathUtils");
|
||
/**
|
||
* A two-dimensional vector (x, y)
|
||
*/
|
||
class Vec2 {
|
||
/**
|
||
* Creates a new Vec2
|
||
* @param x The x value of the vector
|
||
* @param y The y value of the vector
|
||
*/
|
||
constructor(x = 0, y = 0) {
|
||
/**
|
||
* When this vector changes its value, do something
|
||
*/
|
||
this.onChange = () => { };
|
||
this.vec = new Float32Array(2);
|
||
this.vec[0] = x;
|
||
this.vec[1] = y;
|
||
}
|
||
// Expose x and y with getters and setters
|
||
get x() {
|
||
return this.vec[0];
|
||
}
|
||
set x(x) {
|
||
this.vec[0] = x;
|
||
if (this.onChange) {
|
||
this.onChange();
|
||
}
|
||
}
|
||
get y() {
|
||
return this.vec[1];
|
||
}
|
||
set y(y) {
|
||
this.vec[1] = y;
|
||
if (this.onChange) {
|
||
this.onChange();
|
||
}
|
||
}
|
||
static get ZERO() {
|
||
return new Vec2(0, 0);
|
||
}
|
||
static get INF() {
|
||
return new Vec2(Infinity, Infinity);
|
||
}
|
||
static get UP() {
|
||
return new Vec2(0, -1);
|
||
}
|
||
static get DOWN() {
|
||
return new Vec2(0, 1);
|
||
}
|
||
static get LEFT() {
|
||
return new Vec2(-1, 0);
|
||
}
|
||
static get RIGHT() {
|
||
return new Vec2(1, 0);
|
||
}
|
||
/**
|
||
* The squared magnitude of the vector. This tends to be faster, so use it in situations where taking the
|
||
* square root doesn't matter, like for comparing distances.
|
||
* @returns The squared magnitude of the vector
|
||
*/
|
||
magSq() {
|
||
return this.x * this.x + this.y * this.y;
|
||
}
|
||
/**
|
||
* The magnitude of the vector.
|
||
* @returns The magnitude of the vector.
|
||
*/
|
||
mag() {
|
||
return Math.sqrt(this.magSq());
|
||
}
|
||
/**
|
||
* Divdes x and y by the magnitude to obtain the unit vector in the direction of this vector.
|
||
* @returns This vector as a unit vector.
|
||
*/
|
||
normalize() {
|
||
if (this.x === 0 && this.y === 0)
|
||
return this;
|
||
let mag = this.mag();
|
||
this.x /= mag;
|
||
this.y /= mag;
|
||
return this;
|
||
}
|
||
/**
|
||
* Works like normalize(), but returns a new Vec2
|
||
* @returns A new vector that is the unit vector for this one
|
||
*/
|
||
normalized() {
|
||
if (this.isZero()) {
|
||
return this;
|
||
}
|
||
let mag = this.mag();
|
||
return new Vec2(this.x / mag, this.y / mag);
|
||
}
|
||
/**
|
||
* Sets the x and y elements of this vector to zero.
|
||
* @returns This vector, with x and y set to zero.
|
||
*/
|
||
zero() {
|
||
return this.set(0, 0);
|
||
}
|
||
/**
|
||
* Sets the vector's x and y based on the angle provided. Goes counter clockwise.
|
||
* @param angle The angle in radians
|
||
* @param radius The magnitude of the vector at the specified angle
|
||
* @returns This vector.
|
||
*/
|
||
setToAngle(angle, radius = 1) {
|
||
this.x = MathUtils_1.default.floorToPlace(Math.cos(angle) * radius, 5);
|
||
this.y = MathUtils_1.default.floorToPlace(-Math.sin(angle) * radius, 5);
|
||
return this;
|
||
}
|
||
/**
|
||
* Returns a vector that point from this vector to another one
|
||
* @param other The vector to point to
|
||
* @returns A new Vec2 that points from this vector to the one provided
|
||
*/
|
||
vecTo(other) {
|
||
return new Vec2(other.x - this.x, other.y - this.y);
|
||
}
|
||
/**
|
||
* Returns a vector containing the direction from this vector to another
|
||
* @param other The vector to point to
|
||
* @returns A new Vec2 that points from this vector to the one provided. This new Vec2 will be a unit vector.
|
||
*/
|
||
dirTo(other) {
|
||
return this.vecTo(other).normalize();
|
||
}
|
||
/**
|
||
* Keeps the vector's direction, but sets its magnitude to be the provided magnitude
|
||
* @param magnitude The magnitude the vector should be
|
||
* @returns This vector with its magnitude set to the new magnitude
|
||
*/
|
||
scaleTo(magnitude) {
|
||
return this.normalize().scale(magnitude);
|
||
}
|
||
/**
|
||
* Scales x and y by the number provided, or if two number are provided, scales them individually.
|
||
* @param factor The scaling factor for the vector, or for only the x-component if yFactor is provided
|
||
* @param yFactor The scaling factor for the y-component of the vector
|
||
* @returns This vector after scaling
|
||
*/
|
||
scale(factor, yFactor = null) {
|
||
if (yFactor !== null) {
|
||
this.x *= factor;
|
||
this.y *= yFactor;
|
||
return this;
|
||
}
|
||
this.x *= factor;
|
||
this.y *= factor;
|
||
return this;
|
||
}
|
||
/**
|
||
* Returns a scaled version of this vector without modifying it.
|
||
* @param factor The scaling factor for the vector, or for only the x-component if yFactor is provided
|
||
* @param yFactor The scaling factor for the y-component of the vector
|
||
* @returns A new vector that has the values of this vector after scaling
|
||
*/
|
||
scaled(factor, yFactor = null) {
|
||
return this.clone().scale(factor, yFactor);
|
||
}
|
||
/**
|
||
* Rotates the vector counter-clockwise by the angle amount specified
|
||
* @param angle The angle to rotate by in radians
|
||
* @returns This vector after rotation.
|
||
*/
|
||
rotateCCW(angle) {
|
||
let cs = Math.cos(angle);
|
||
let sn = Math.sin(angle);
|
||
let tempX = this.x * cs - this.y * sn;
|
||
let tempY = this.x * sn + this.y * cs;
|
||
this.x = tempX;
|
||
this.y = tempY;
|
||
return this;
|
||
}
|
||
/**
|
||
* Sets the vectors coordinates to be the ones provided
|
||
* @param x The new x value for this vector
|
||
* @param y The new y value for this vector
|
||
* @returns This vector
|
||
*/
|
||
set(x, y) {
|
||
this.x = x;
|
||
this.y = y;
|
||
return this;
|
||
}
|
||
/**
|
||
* Copies the values of the other Vec2 into this one.
|
||
* @param other The Vec2 to copy
|
||
* @returns This vector with its values set to the vector provided
|
||
*/
|
||
copy(other) {
|
||
return this.set(other.x, other.y);
|
||
}
|
||
/**
|
||
* Adds this vector the another vector
|
||
* @param other The Vec2 to add to this one
|
||
* @returns This vector after adding the one provided
|
||
*/
|
||
add(other) {
|
||
this.x += other.x;
|
||
this.y += other.y;
|
||
return this;
|
||
}
|
||
/**
|
||
* Increments the fields of this vector. Both are incremented with a, if only a is provided.
|
||
* @param a The first number to increment by
|
||
* @param b The second number to increment by
|
||
* @returnss This vector after incrementing
|
||
*/
|
||
inc(a, b) {
|
||
if (b === undefined) {
|
||
this.x += a;
|
||
this.y += a;
|
||
}
|
||
else {
|
||
this.x += a;
|
||
this.y += b;
|
||
}
|
||
return this;
|
||
}
|
||
/**
|
||
* Subtracts another vector from this vector
|
||
* @param other The Vec2 to subtract from this one
|
||
* @returns This vector after subtracting the one provided
|
||
*/
|
||
sub(other) {
|
||
this.x -= other.x;
|
||
this.y -= other.y;
|
||
return this;
|
||
}
|
||
/**
|
||
* Multiplies this vector with another vector element-wise. In other words, this.x *= other.x and this.y *= other.y
|
||
* @param other The Vec2 to multiply this one by
|
||
* @returns This vector after multiplying its components by this one
|
||
*/
|
||
mult(other) {
|
||
this.x *= other.x;
|
||
this.y *= other.y;
|
||
return this;
|
||
}
|
||
/**
|
||
* Divides this vector with another vector element-wise. In other words, this.x /= other.x and this.y /= other.y
|
||
* @param other The vector to divide this one by
|
||
* @returns This vector after division
|
||
*/
|
||
div(other) {
|
||
if (other.x === 0 || other.y === 0)
|
||
throw "Divide by zero error";
|
||
this.x /= other.x;
|
||
this.y /= other.y;
|
||
return this;
|
||
}
|
||
/**
|
||
* Does an element wise remainder operation on this vector. this.x %= other.x and this.y %= other.y
|
||
* @param other The other vector
|
||
* @returns this vector
|
||
*/
|
||
remainder(other) {
|
||
this.x = this.x % other.x;
|
||
this.y = this.y % other.y;
|
||
return this;
|
||
}
|
||
/**
|
||
* Returns the squared distance between this vector and another vector
|
||
* @param other The vector to compute distance squared to
|
||
* @returns The squared distance between this vector and the one provided
|
||
*/
|
||
distanceSqTo(other) {
|
||
return (this.x - other.x) * (this.x - other.x) + (this.y - other.y) * (this.y - other.y);
|
||
}
|
||
/**
|
||
* Returns the distance between this vector and another vector
|
||
* @param other The vector to compute distance to
|
||
* @returns The distance between this vector and the one provided
|
||
*/
|
||
distanceTo(other) {
|
||
return Math.sqrt(this.distanceSqTo(other));
|
||
}
|
||
/**
|
||
* Returns the dot product of this vector and another
|
||
* @param other The vector to compute the dot product with
|
||
* @returns The dot product of this vector and the one provided.
|
||
*/
|
||
dot(other) {
|
||
return this.x * other.x + this.y * other.y;
|
||
}
|
||
/**
|
||
* Returns the angle counter-clockwise in radians from this vector to another vector
|
||
* @param other The vector to compute the angle to
|
||
* @returns The angle, rotating CCW, from this vector to the other vector
|
||
*/
|
||
angleToCCW(other) {
|
||
let dot = this.dot(other);
|
||
let det = this.x * other.y - this.y * other.x;
|
||
let angle = -Math.atan2(det, dot);
|
||
if (angle < 0) {
|
||
angle += 2 * Math.PI;
|
||
}
|
||
return angle;
|
||
}
|
||
/**
|
||
* Returns a string representation of this vector rounded to 1 decimal point
|
||
* @returns This vector as a string
|
||
*/
|
||
toString() {
|
||
return this.toFixed();
|
||
}
|
||
/**
|
||
* Returns a string representation of this vector rounded to the specified number of decimal points
|
||
* @param numDecimalPoints The number of decimal points to create a string to
|
||
* @returns This vector as a string
|
||
*/
|
||
toFixed(numDecimalPoints = 1) {
|
||
return "(" + this.x.toFixed(numDecimalPoints) + ", " + this.y.toFixed(numDecimalPoints) + ")";
|
||
}
|
||
/**
|
||
* Returns a new vector with the same coordinates as this one.
|
||
* @returns A new Vec2 with the same values as this one
|
||
*/
|
||
clone() {
|
||
return new Vec2(this.x, this.y);
|
||
}
|
||
/**
|
||
* Returns true if this vector and other have the EXACT same x and y (not assured to be safe for floats)
|
||
* @param other The vector to check against
|
||
* @returns A boolean representing the equality of the two vectors
|
||
*/
|
||
strictEquals(other) {
|
||
return this.x === other.x && this.y === other.y;
|
||
}
|
||
/**
|
||
* Returns true if this vector and other have the same x and y
|
||
* @param other The vector to check against
|
||
* @returns A boolean representing the equality of the two vectors
|
||
*/
|
||
equals(other) {
|
||
let xEq = Math.abs(this.x - other.x) < 0.0000001;
|
||
let yEq = Math.abs(this.y - other.y) < 0.0000001;
|
||
return xEq && yEq;
|
||
}
|
||
/**
|
||
* Returns true if this vector is the zero vector exactly (not assured to be safe for floats).
|
||
* @returns A boolean representing the equality of this vector and the zero vector
|
||
*/
|
||
strictIsZero() {
|
||
return this.x === 0 && this.y === 0;
|
||
}
|
||
/**
|
||
* Returns true if this x and y for this vector are both zero.
|
||
* @returns A boolean representing the equality of this vector and the zero vector
|
||
*/
|
||
isZero() {
|
||
return Math.abs(this.x) < 0.0000001 && Math.abs(this.y) < 0.0000001;
|
||
}
|
||
/**
|
||
* Sets the function that is called whenever this vector is changed.
|
||
* @param f The function to be called
|
||
*/
|
||
setOnChange(f) {
|
||
this.onChange = f;
|
||
}
|
||
toArray() {
|
||
return this.vec;
|
||
}
|
||
/**
|
||
* Performs linear interpolation between two vectors
|
||
* @param a The first vector
|
||
* @param b The second vector
|
||
* @param t The time of the lerp, with 0 being vector A, and 1 being vector B
|
||
* @returns A new Vec2 representing the lerp between vector a and b.
|
||
*/
|
||
static lerp(a, b, t) {
|
||
return new Vec2(MathUtils_1.default.lerp(a.x, b.x, t), MathUtils_1.default.lerp(a.y, b.y, t));
|
||
}
|
||
}
|
||
exports.default = Vec2;
|
||
Vec2.ZERO_STATIC = new Vec2(0, 0);
|
||
|
||
},{"../Utils/MathUtils":102}],25:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const Color_1 = require("../Utils/Color");
|
||
/**
|
||
* A util class for rendering Debug messages to the canvas.
|
||
*/
|
||
class Debug {
|
||
/**
|
||
* Add a message to display on the debug screen
|
||
* @param id A unique ID for this message
|
||
* @param messages The messages to print to the debug screen
|
||
*/
|
||
static log(id, ...messages) {
|
||
// let message = "";
|
||
// for(let i = 0; i < messages.length; i++){
|
||
// message += messages[i].toString();
|
||
// }
|
||
// Join all messages with spaces
|
||
let message = messages.map((m) => m.toString()).join(" ");
|
||
this.logMessages.add(id, message);
|
||
}
|
||
/**
|
||
* Deletes a a key from the log and stops it from keeping up space on the screen
|
||
* @param id The id of the log item to clear
|
||
*/
|
||
static clearLogItem(id) {
|
||
this.logMessages.delete(id);
|
||
}
|
||
/**
|
||
* Sets the list of nodes to render with the debugger
|
||
* @param nodes The new list of nodes
|
||
*/
|
||
static setNodes(nodes) {
|
||
this.nodes = nodes;
|
||
}
|
||
/**
|
||
* Draws a box at the specified position
|
||
* @param center The center of the box
|
||
* @param halfSize The dimensions of the box
|
||
* @param filled A boolean for whether or not the box is filled
|
||
* @param color The color of the box to draw
|
||
*/
|
||
static drawBox(center, halfSize, filled, color) {
|
||
let alpha = this.debugRenderingContext.globalAlpha;
|
||
this.debugRenderingContext.globalAlpha = color.a;
|
||
if (filled) {
|
||
this.debugRenderingContext.fillStyle = color.toString();
|
||
this.debugRenderingContext.fillRect(center.x - halfSize.x, center.y - halfSize.y, halfSize.x * 2, halfSize.y * 2);
|
||
}
|
||
else {
|
||
let lineWidth = 2;
|
||
this.debugRenderingContext.lineWidth = lineWidth;
|
||
this.debugRenderingContext.strokeStyle = color.toString();
|
||
this.debugRenderingContext.strokeRect(center.x - halfSize.x, center.y - halfSize.y, halfSize.x * 2, halfSize.y * 2);
|
||
}
|
||
this.debugRenderingContext.globalAlpha = alpha;
|
||
}
|
||
/**
|
||
* Draws a circle at the specified position
|
||
* @param center The center of the circle
|
||
* @param radius The dimensions of the box
|
||
* @param filled A boolean for whether or not the circle is filled
|
||
* @param color The color of the circle
|
||
*/
|
||
static drawCircle(center, radius, filled, color) {
|
||
let alpha = this.debugRenderingContext.globalAlpha;
|
||
this.debugRenderingContext.globalAlpha = color.a;
|
||
if (filled) {
|
||
this.debugRenderingContext.fillStyle = color.toString();
|
||
this.debugRenderingContext.beginPath();
|
||
this.debugRenderingContext.arc(center.x, center.y, radius, 0, 2 * Math.PI);
|
||
this.debugRenderingContext.closePath();
|
||
this.debugRenderingContext.fill();
|
||
}
|
||
else {
|
||
let lineWidth = 2;
|
||
this.debugRenderingContext.lineWidth = lineWidth;
|
||
this.debugRenderingContext.strokeStyle = color.toString();
|
||
this.debugRenderingContext.beginPath();
|
||
this.debugRenderingContext.arc(center.x, center.y, radius, 0, 2 * Math.PI);
|
||
this.debugRenderingContext.closePath();
|
||
this.debugRenderingContext.stroke();
|
||
}
|
||
this.debugRenderingContext.globalAlpha = alpha;
|
||
}
|
||
/**
|
||
* Draws a ray at the specified position
|
||
* @param from The starting position of the ray
|
||
* @param to The ending position of the ray
|
||
* @param color The color of the ray
|
||
*/
|
||
static drawRay(from, to, color) {
|
||
this.debugRenderingContext.lineWidth = 2;
|
||
this.debugRenderingContext.strokeStyle = color.toString();
|
||
this.debugRenderingContext.beginPath();
|
||
this.debugRenderingContext.moveTo(from.x, from.y);
|
||
this.debugRenderingContext.lineTo(to.x, to.y);
|
||
this.debugRenderingContext.closePath();
|
||
this.debugRenderingContext.stroke();
|
||
}
|
||
/**
|
||
* Draws a point at the specified position
|
||
* @param pos The position of the point
|
||
* @param color The color of the point
|
||
*/
|
||
static drawPoint(pos, color) {
|
||
let pointSize = 6;
|
||
this.debugRenderingContext.fillStyle = color.toString();
|
||
this.debugRenderingContext.fillRect(pos.x - pointSize / 2, pos.y - pointSize / 2, pointSize, pointSize);
|
||
}
|
||
/**
|
||
* Sets the default rendering color for text for the debugger
|
||
* @param color The color to render the text
|
||
*/
|
||
static setDefaultTextColor(color) {
|
||
this.defaultTextColor = color;
|
||
}
|
||
/**
|
||
* Performs any necessary setup operations on the Debug canvas
|
||
* @param canvas The debug canvas
|
||
* @param width The desired width of the canvas
|
||
* @param height The desired height of the canvas
|
||
* @returns The rendering context extracted from the canvas
|
||
*/
|
||
static initializeDebugCanvas(canvas, width, height) {
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
this.debugCanvasSize = new Vec2_1.default(width, height);
|
||
this.debugRenderingContext = canvas.getContext("2d");
|
||
return this.debugRenderingContext;
|
||
}
|
||
/** Clears the debug canvas */
|
||
static clearCanvas() {
|
||
this.debugRenderingContext.clearRect(0, 0, this.debugCanvasSize.x, this.debugCanvasSize.y);
|
||
}
|
||
/** Renders the text and nodes sent to the Debug system */
|
||
static render() {
|
||
this.renderText();
|
||
this.renderNodes();
|
||
}
|
||
/** Renders the text sent to the Debug canvas */
|
||
static renderText() {
|
||
let y = 20;
|
||
this.debugRenderingContext.font = "20px Arial";
|
||
this.debugRenderingContext.fillStyle = this.defaultTextColor.toString();
|
||
// Draw all of the text
|
||
this.logMessages.forEach((key) => {
|
||
this.debugRenderingContext.fillText(this.logMessages.get(key), 10, y);
|
||
y += 30;
|
||
});
|
||
}
|
||
/** Renders the nodes registered with the debug canvas */
|
||
static renderNodes() {
|
||
if (this.nodes) {
|
||
this.nodes.forEach(node => {
|
||
node.debugRender();
|
||
});
|
||
}
|
||
}
|
||
}
|
||
exports.default = Debug;
|
||
/** A map of log messages to display on the screen */
|
||
Debug.logMessages = new Map_1.default();
|
||
/** The rendering color for text */
|
||
Debug.defaultTextColor = Color_1.default.WHITE;
|
||
|
||
},{"../DataTypes/Map":10,"../DataTypes/Vec2":24,"../Utils/Color":99}],26:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Color_1 = require("../Utils/Color");
|
||
// @ignorePage
|
||
class Stats extends Object {
|
||
static initStats() {
|
||
let canvas = document.getElementById("stats-canvas");
|
||
canvas.width = this.CANVAS_WIDTH;
|
||
canvas.height = this.CANVAS_HEIGHT;
|
||
this.ctx = canvas.getContext("2d");
|
||
this.statsDiv = document.getElementById("stats-display");
|
||
this.prevfps = new Array();
|
||
this.prevClearTimes = new Array();
|
||
this.SGClearTimes = new Array();
|
||
this.avgSGClearTime = 0;
|
||
this.prevFillTimes = new Array();
|
||
this.SGFillTimes = new Array();
|
||
this.avgSGFillTime = 0;
|
||
this.prevUpdateTimes = new Array();
|
||
this.SGUpdateTimes = new Array();
|
||
this.avgSGUpdateTime = 0;
|
||
this.prevQueryTimes = new Array();
|
||
this.SGQueryTimes = new Array();
|
||
this.avgSGQueryTime = 0;
|
||
let clearTime = document.createElement("span");
|
||
clearTime.setAttribute("id", "sgclear");
|
||
let fillTime = document.createElement("span");
|
||
fillTime.setAttribute("id", "sgfill");
|
||
let updateTime = document.createElement("span");
|
||
updateTime.setAttribute("id", "sgupdate");
|
||
let queryTime = document.createElement("span");
|
||
queryTime.setAttribute("id", "sgquery");
|
||
let br1 = document.createElement("br");
|
||
let br2 = document.createElement("br");
|
||
let br3 = document.createElement("br");
|
||
this.statsDiv.append(clearTime, br1, fillTime, br2, updateTime, br3, queryTime);
|
||
this.graphChoices = document.getElementById("chart-option");
|
||
let option1 = document.createElement("option");
|
||
option1.value = "prevfps";
|
||
option1.label = "FPS";
|
||
let option2 = document.createElement("option");
|
||
option2.value = "prevClearTimes";
|
||
option2.label = "Clear Time";
|
||
let option3 = document.createElement("option");
|
||
option3.value = "prevFillTimes";
|
||
option3.label = "Fill time";
|
||
let option4 = document.createElement("option");
|
||
option4.value = "prevUpdateTimes";
|
||
option4.label = "Update time";
|
||
let option5 = document.createElement("option");
|
||
option5.value = "prevQueryTimes";
|
||
option5.label = "Query Time";
|
||
let optionAll = document.createElement("option");
|
||
optionAll.value = "all";
|
||
optionAll.label = "All";
|
||
this.graphChoices.append(option1, option2, option3, option4, option5, optionAll);
|
||
}
|
||
static updateFPS(fps) {
|
||
this.prevfps.push(fps);
|
||
if (this.prevfps.length > Stats.NUM_POINTS) {
|
||
this.prevfps.shift();
|
||
}
|
||
if (this.SGClearTimes.length > 0) {
|
||
this.prevClearTimes.push(this.avgSGClearTime);
|
||
if (this.prevClearTimes.length > this.NUM_POINTS) {
|
||
this.prevClearTimes.shift();
|
||
}
|
||
}
|
||
if (this.SGFillTimes.length > 0) {
|
||
this.prevFillTimes.push(this.avgSGFillTime);
|
||
if (this.prevFillTimes.length > this.NUM_POINTS) {
|
||
this.prevFillTimes.shift();
|
||
}
|
||
}
|
||
if (this.SGUpdateTimes.length > 0) {
|
||
this.prevUpdateTimes.push(this.avgSGUpdateTime);
|
||
if (this.prevUpdateTimes.length > this.NUM_POINTS) {
|
||
this.prevUpdateTimes.shift();
|
||
}
|
||
}
|
||
if (this.SGQueryTimes.length > 0) {
|
||
this.prevQueryTimes.push(this.avgSGQueryTime);
|
||
if (this.prevQueryTimes.length > this.NUM_POINTS) {
|
||
this.prevQueryTimes.shift();
|
||
}
|
||
}
|
||
this.updateSGStats();
|
||
}
|
||
static log(key, data) {
|
||
if (key === "sgclear") {
|
||
this.SGClearTimes.push(data);
|
||
if (this.SGClearTimes.length > 100) {
|
||
this.SGClearTimes.shift();
|
||
}
|
||
}
|
||
else if (key === "sgfill") {
|
||
this.SGFillTimes.push(data);
|
||
if (this.SGFillTimes.length > 100) {
|
||
this.SGFillTimes.shift();
|
||
}
|
||
}
|
||
else if (key === "sgupdate") {
|
||
this.SGUpdateTimes.push(data);
|
||
if (this.SGUpdateTimes.length > 100) {
|
||
this.SGUpdateTimes.shift();
|
||
}
|
||
}
|
||
else if (key === "sgquery") {
|
||
this.SGQueryTimes.push(data);
|
||
if (this.SGQueryTimes.length > 1000) {
|
||
this.SGQueryTimes.shift();
|
||
}
|
||
}
|
||
}
|
||
static render() {
|
||
// Display stats
|
||
this.drawCharts();
|
||
}
|
||
static drawCharts() {
|
||
this.ctx.clearRect(0, 0, this.CANVAS_WIDTH, this.CANVAS_HEIGHT);
|
||
let paramString = this.graphChoices.value;
|
||
if (paramString === "prevfps" || paramString === "all") {
|
||
let param = this.prevfps;
|
||
let color = Color_1.default.BLUE.toString();
|
||
this.drawChart(param, color);
|
||
}
|
||
if (paramString === "prevClearTimes" || paramString === "all") {
|
||
let param = this.prevClearTimes;
|
||
let color = Color_1.default.RED.toString();
|
||
this.drawChart(param, color);
|
||
}
|
||
if (paramString === "prevFillTimes" || paramString === "all") {
|
||
let param = this.prevFillTimes;
|
||
let color = Color_1.default.GREEN.toString();
|
||
this.drawChart(param, color);
|
||
}
|
||
if (paramString === "prevUpdateTimes" || paramString === "all") {
|
||
let param = this.prevUpdateTimes;
|
||
let color = Color_1.default.CYAN.toString();
|
||
this.drawChart(param, color);
|
||
}
|
||
if (paramString === "prevQueryTimes" || paramString === "all") {
|
||
let param = this.prevQueryTimes;
|
||
let color = Color_1.default.ORANGE.toString();
|
||
this.drawChart(param, color);
|
||
}
|
||
}
|
||
static drawChart(param, color) {
|
||
this.ctx.strokeStyle = Color_1.default.BLACK.toString();
|
||
this.ctx.beginPath();
|
||
this.ctx.moveTo(10, 10);
|
||
this.ctx.lineTo(10, this.CANVAS_HEIGHT - 10);
|
||
this.ctx.closePath();
|
||
this.ctx.stroke();
|
||
this.ctx.beginPath();
|
||
this.ctx.moveTo(10, this.CANVAS_HEIGHT - 10);
|
||
this.ctx.lineTo(this.CANVAS_WIDTH - 10, this.CANVAS_HEIGHT - 10);
|
||
this.ctx.closePath();
|
||
this.ctx.stroke();
|
||
let max = Math.max(...param);
|
||
let prevX = 10;
|
||
let prevY = this.CANVAS_HEIGHT - 10 - param[0] / max * (this.CANVAS_HEIGHT - 20);
|
||
this.ctx.strokeStyle = color;
|
||
for (let i = 1; i < param.length; i++) {
|
||
let fps = param[i];
|
||
let x = 10 + i * (this.CANVAS_WIDTH - 20) / this.NUM_POINTS;
|
||
let y = this.CANVAS_HEIGHT - 10 - fps / max * (this.CANVAS_HEIGHT - 20);
|
||
this.ctx.beginPath();
|
||
this.ctx.moveTo(prevX, prevY);
|
||
this.ctx.lineTo(x, y);
|
||
this.ctx.closePath();
|
||
this.ctx.stroke();
|
||
prevX = x;
|
||
prevY = y;
|
||
}
|
||
}
|
||
static updateSGStats() {
|
||
if (this.SGClearTimes.length > 0) {
|
||
this.avgSGClearTime = this.SGClearTimes.reduce((acc, val) => acc + val) / this.SGClearTimes.length;
|
||
}
|
||
if (this.SGFillTimes.length > 0) {
|
||
this.avgSGFillTime = this.SGFillTimes.reduce((acc, val) => acc + val) / this.SGFillTimes.length;
|
||
}
|
||
if (this.SGUpdateTimes.length > 0) {
|
||
this.avgSGUpdateTime = this.SGUpdateTimes.reduce((acc, val) => acc + val) / this.SGUpdateTimes.length;
|
||
}
|
||
if (this.SGQueryTimes.length > 0) {
|
||
this.avgSGQueryTime = this.SGQueryTimes.reduce((acc, val) => acc + val) / this.SGQueryTimes.length;
|
||
}
|
||
document.getElementById("sgclear").innerHTML = "Avg SG clear time: " + this.avgSGClearTime;
|
||
document.getElementById("sgfill").innerHTML = "Avg SG fill time: " + this.avgSGFillTime;
|
||
document.getElementById("sgupdate").innerHTML = "Avg SG update time: " + this.avgSGUpdateTime;
|
||
document.getElementById("sgquery").innerHTML = "Avg SG query time: " + this.avgSGQueryTime;
|
||
}
|
||
}
|
||
exports.default = Stats;
|
||
Stats.NUM_POINTS = 60;
|
||
Stats.CANVAS_WIDTH = 300;
|
||
Stats.CANVAS_HEIGHT = 300;
|
||
|
||
},{"../Utils/Color":99}],27:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EventQueue_1 = require("./EventQueue");
|
||
const GameEvent_1 = require("./GameEvent");
|
||
/**
|
||
* An event emitter object other systems can use to hook into the EventQueue.
|
||
* Provides an easy interface for firing off events.
|
||
*/
|
||
class Emitter {
|
||
/** Creates a new Emitter */
|
||
constructor() {
|
||
this.eventQueue = EventQueue_1.default.getInstance();
|
||
}
|
||
/**
|
||
* Emit and event of type eventType with the data packet data
|
||
* @param eventType The name of the event to fire off
|
||
* @param data A @reference[Map] or record containing any data about the event
|
||
*/
|
||
fireEvent(eventType, data = null) {
|
||
this.eventQueue.addEvent(new GameEvent_1.default(eventType, data));
|
||
}
|
||
}
|
||
exports.default = Emitter;
|
||
|
||
},{"./EventQueue":28,"./GameEvent":29}],28:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Queue_1 = require("../DataTypes/Queue");
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const GameEventType_1 = require("./GameEventType");
|
||
/**
|
||
* The main event system of the game engine.
|
||
* Events are sent to the EventQueue, which handles distribution to any systems that are listening for those events.
|
||
* This allows for handling of input without having classes directly hook into javascript event handles,
|
||
* and allows otherwise separate classes to communicate with each other cleanly, such as a Player object
|
||
* requesting a sound be played by the audio system.
|
||
*
|
||
* The distribution of @reference[GameEvent]s happens as follows:
|
||
*
|
||
* Events are recieved throughout a frame and are queued up by the EventQueue.
|
||
* At the beginning of the next frame, events are sent out to any receivers that are hooked into the event type.
|
||
* @reference[Receiver]s are then free to process events as they see fit.
|
||
*
|
||
* Overall, the EventQueue can be considered as something similar to an email server,
|
||
* and the @reference[Receiver]s can be considered as the client inboxes.
|
||
*
|
||
* See @link(Game Programming Patterns)(https://gameprogrammingpatterns.com/event-queue.html) for more discussion on EventQueues
|
||
*/
|
||
class EventQueue {
|
||
constructor() {
|
||
this.MAX_SIZE = 100;
|
||
this.q = new Queue_1.default(this.MAX_SIZE);
|
||
this.receivers = new Map_1.default();
|
||
}
|
||
/** Retrieves the instance of the Singleton EventQueue */
|
||
static getInstance() {
|
||
if (this.instance === null) {
|
||
this.instance = new EventQueue();
|
||
}
|
||
return this.instance;
|
||
}
|
||
/** Adds an event to the EventQueue.
|
||
* This is exposed to the rest of the game engine through the @reference[Emitter] class */
|
||
addEvent(event) {
|
||
this.q.enqueue(event);
|
||
}
|
||
/**
|
||
* Associates a receiver with a type of event. Every time this event appears in the future,
|
||
* it will be given to the receiver (and any others watching that type).
|
||
* This is exposed to the rest of the game engine through the @reference[Receiver] class
|
||
* @param receiver The event receiver
|
||
* @param type The type or types of events to subscribe to
|
||
*/
|
||
subscribe(receiver, type) {
|
||
if (type instanceof Array) {
|
||
// If it is an array, subscribe to all event types
|
||
for (let t of type) {
|
||
this.addListener(receiver, t);
|
||
}
|
||
}
|
||
else {
|
||
this.addListener(receiver, type);
|
||
}
|
||
}
|
||
/**
|
||
* Unsubscribes the specified receiver from all events, or from whatever events are provided
|
||
* @param receiver The receiver to unsubscribe
|
||
* @param keys The events to unsubscribe from. If none are provided, unsubscribe from all
|
||
*/
|
||
unsubscribe(receiver, ...events) {
|
||
this.receivers.forEach(eventName => {
|
||
// If keys were provided, only continue if this key is one of them
|
||
if (events.length > 0 && events.indexOf(eventName) === -1)
|
||
return;
|
||
// Find the index of our receiver for this key
|
||
let index = this.receivers.get(eventName).indexOf(receiver);
|
||
// If an index was found, remove the receiver
|
||
if (index !== -1) {
|
||
this.receivers.get(eventName).splice(index, 1);
|
||
}
|
||
});
|
||
}
|
||
// Associate the receiver and the type
|
||
addListener(receiver, type) {
|
||
if (this.receivers.has(type)) {
|
||
this.receivers.get(type).push(receiver);
|
||
}
|
||
else {
|
||
this.receivers.add(type, [receiver]);
|
||
}
|
||
}
|
||
update(deltaT) {
|
||
while (this.q.hasItems()) {
|
||
// Retrieve each event
|
||
let event = this.q.dequeue();
|
||
// If a receiver has this event type, send it the event
|
||
if (this.receivers.has(event.type)) {
|
||
for (let receiver of this.receivers.get(event.type)) {
|
||
receiver.receive(event);
|
||
}
|
||
}
|
||
// If a receiver is subscribed to all events, send it the event
|
||
if (this.receivers.has(GameEventType_1.GameEventType.ALL)) {
|
||
for (let receiver of this.receivers.get(GameEventType_1.GameEventType.ALL)) {
|
||
receiver.receive(event);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = EventQueue;
|
||
EventQueue.instance = null;
|
||
|
||
},{"../DataTypes/Map":10,"../DataTypes/Queue":14,"./GameEventType":30}],29:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../DataTypes/Map");
|
||
/**
|
||
* A representation of an in-game event that is passed through the @reference[EventQueue]
|
||
*/
|
||
class GameEvent {
|
||
/**
|
||
* Creates a new GameEvent.
|
||
* This is handled implicitly through the @reference[Emitter] class
|
||
* @param type The type of the GameEvent
|
||
* @param data The data contained by the GameEvent
|
||
*/
|
||
constructor(type, data = null) {
|
||
// Parse the game event data
|
||
if (data === null) {
|
||
this.data = new Map_1.default();
|
||
}
|
||
else if (!(data instanceof Map_1.default)) {
|
||
// data is a raw object, unpack
|
||
this.data = new Map_1.default();
|
||
for (let key in data) {
|
||
this.data.add(key, data[key]);
|
||
}
|
||
}
|
||
else {
|
||
this.data = data;
|
||
}
|
||
this.type = type;
|
||
this.time = Date.now();
|
||
}
|
||
/**
|
||
* Checks the type of the GameEvent
|
||
* @param type The type to check
|
||
* @returns True if the GameEvent is the specified type, false otherwise.
|
||
*/
|
||
isType(type) {
|
||
return this.type === type;
|
||
}
|
||
/**
|
||
* Returns this GameEvent as a string
|
||
* @returns The string representation of the GameEvent
|
||
*/
|
||
toString() {
|
||
return this.type + ": @" + this.time;
|
||
}
|
||
}
|
||
exports.default = GameEvent;
|
||
|
||
},{"../DataTypes/Map":10}],30:[function(require,module,exports){
|
||
"use strict";
|
||
// @ignorePage
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.GameEventType = void 0;
|
||
var GameEventType;
|
||
(function (GameEventType) {
|
||
/**
|
||
* Mouse Down event. Has data: {position: Vec2 - Mouse Position}
|
||
*/
|
||
GameEventType["MOUSE_DOWN"] = "mouse_down";
|
||
/**
|
||
* Mouse Up event. Has data: {position: Vec2 - Mouse Position}
|
||
*/
|
||
GameEventType["MOUSE_UP"] = "mouse_up";
|
||
/**
|
||
* Mouse Move event. Has data: {position: Vec2 - Mouse Position}
|
||
*/
|
||
GameEventType["MOUSE_MOVE"] = "mouse_move";
|
||
/**
|
||
* Key Down event. Has data: {key: string - The key that is down}
|
||
*/
|
||
GameEventType["KEY_DOWN"] = "key_down";
|
||
/**
|
||
* Key Up event. Has data: {key: string - The key that is up}
|
||
*/
|
||
GameEventType["KEY_UP"] = "key_up";
|
||
/**
|
||
* Canvas Blur event. Has data: {}
|
||
*/
|
||
GameEventType["CANVAS_BLUR"] = "canvas_blur";
|
||
/**
|
||
* Mouse wheel up event. Has data: {}
|
||
*/
|
||
GameEventType["WHEEL_UP"] = "wheel_up";
|
||
/**
|
||
* Mouse wheel down event. Has data: {}
|
||
*/
|
||
GameEventType["WHEEL_DOWN"] = "wheel_down";
|
||
/**
|
||
* Start Recording event. Has data: {}
|
||
*/
|
||
GameEventType["START_RECORDING"] = "start_recording";
|
||
/**
|
||
* Stop Recording event. Has data: {}
|
||
*/
|
||
GameEventType["STOP_RECORDING"] = "stop_recording";
|
||
/**
|
||
* Play Recording event. Has data: {}
|
||
*/
|
||
GameEventType["PLAY_RECORDING"] = "play_recording";
|
||
/**
|
||
* Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean }
|
||
*/
|
||
GameEventType["PLAY_SOUND"] = "play_sound";
|
||
/**
|
||
* Play Sound event. Has data: {key: string}
|
||
*/
|
||
GameEventType["STOP_SOUND"] = "stop_sound";
|
||
/**
|
||
* Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean, channel: AudioChannelType }
|
||
*/
|
||
GameEventType["PLAY_SFX"] = "play_sfx";
|
||
/**
|
||
* Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean }
|
||
*/
|
||
GameEventType["PLAY_MUSIC"] = "play_music";
|
||
/**
|
||
* Mute audio channel event. Has data: {channel: AudioChannelType}
|
||
*/
|
||
GameEventType["MUTE_CHANNEL"] = "mute_channel";
|
||
/**
|
||
* Unmute audio channel event. Has data: {channel: AudioChannelType}
|
||
*/
|
||
GameEventType["UNMUTE_CHANNEL"] = "unmute_channel";
|
||
/**
|
||
* Encompasses all event types. Used for receivers only.
|
||
*/
|
||
GameEventType["ALL"] = "all";
|
||
})(GameEventType = exports.GameEventType || (exports.GameEventType = {}));
|
||
|
||
},{}],31:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Queue_1 = require("../DataTypes/Queue");
|
||
const EventQueue_1 = require("./EventQueue");
|
||
/**
|
||
* Receives subscribed events from the EventQueue.
|
||
*/
|
||
class Receiver {
|
||
/** Creates a new Receiver */
|
||
constructor() {
|
||
this.MAX_SIZE = 100;
|
||
this.q = new Queue_1.default(this.MAX_SIZE);
|
||
}
|
||
destroy() {
|
||
EventQueue_1.default.getInstance().unsubscribe(this);
|
||
}
|
||
/**
|
||
* Adds these types of events to this receiver's queue every update.
|
||
* @param eventTypes The types of events this receiver will be subscribed to
|
||
*/
|
||
subscribe(eventTypes) {
|
||
EventQueue_1.default.getInstance().subscribe(this, eventTypes);
|
||
this.q.clear();
|
||
}
|
||
/**
|
||
* Adds an event to the queue of this reciever. This is used by the @reference[EventQueue] to distribute events
|
||
* @param event The event to receive
|
||
*/
|
||
receive(event) {
|
||
try {
|
||
this.q.enqueue(event);
|
||
}
|
||
catch (e) {
|
||
console.warn("Receiver overflow for event " + event.toString());
|
||
throw e;
|
||
}
|
||
}
|
||
/**
|
||
* Retrieves the next event from the receiver's queue
|
||
* @returns The next GameEvent
|
||
*/
|
||
getNextEvent() {
|
||
return this.q.dequeue();
|
||
}
|
||
/**
|
||
* Looks at the next event in the receiver's queue, but doesn't remove it from the queue
|
||
* @returns The next GameEvent
|
||
*/
|
||
peekNextEvent() {
|
||
return this.q.peekNext();
|
||
}
|
||
/**
|
||
* Returns true if the receiver has any events in its queue
|
||
* @returns True if the receiver has another event, false otherwise
|
||
*/
|
||
hasNextEvent() {
|
||
return this.q.hasItems();
|
||
}
|
||
/**
|
||
* Ignore all events this frame
|
||
*/
|
||
ignoreEvents() {
|
||
this.q.clear();
|
||
}
|
||
}
|
||
exports.default = Receiver;
|
||
|
||
},{"../DataTypes/Queue":14,"./EventQueue":28}],32:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Receiver_1 = require("../Events/Receiver");
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const EventQueue_1 = require("../Events/EventQueue");
|
||
const GameEventType_1 = require("../Events/GameEventType");
|
||
/**
|
||
* Receives input events from the @reference[EventQueue] and allows for easy access of information about input by other systems
|
||
*/
|
||
class Input {
|
||
/**
|
||
* Initializes the Input object
|
||
* @param viewport A reference to the viewport of the game
|
||
*/
|
||
static initialize(viewport, keyMap) {
|
||
Input.viewport = viewport;
|
||
Input.mousePressed = false;
|
||
Input.mouseJustPressed = false;
|
||
Input.receiver = new Receiver_1.default();
|
||
Input.keyJustPressed = new Map_1.default();
|
||
Input.keyPressed = new Map_1.default();
|
||
Input.mousePosition = new Vec2_1.default(0, 0);
|
||
Input.mousePressPosition = new Vec2_1.default(0, 0);
|
||
Input.scrollDirection = 0;
|
||
Input.justScrolled = false;
|
||
Input.keysDisabled = false;
|
||
Input.mouseDisabled = false;
|
||
// Initialize the keymap
|
||
Input.keyMap = new Map_1.default();
|
||
// Add all keys to the keymap
|
||
for (let entry in keyMap) {
|
||
let name = keyMap[entry].name;
|
||
let keys = keyMap[entry].keys;
|
||
Input.keyMap.add(name, keys);
|
||
}
|
||
Input.eventQueue = EventQueue_1.default.getInstance();
|
||
// Subscribe to all input events
|
||
Input.eventQueue.subscribe(Input.receiver, [GameEventType_1.GameEventType.MOUSE_DOWN, GameEventType_1.GameEventType.MOUSE_UP, GameEventType_1.GameEventType.MOUSE_MOVE,
|
||
GameEventType_1.GameEventType.KEY_DOWN, GameEventType_1.GameEventType.KEY_UP, GameEventType_1.GameEventType.CANVAS_BLUR, GameEventType_1.GameEventType.WHEEL_UP, GameEventType_1.GameEventType.WHEEL_DOWN]);
|
||
}
|
||
static update(deltaT) {
|
||
// Reset the justPressed values to false
|
||
Input.mouseJustPressed = false;
|
||
Input.keyJustPressed.forEach((key) => Input.keyJustPressed.set(key, false));
|
||
Input.justScrolled = false;
|
||
Input.scrollDirection = 0;
|
||
while (Input.receiver.hasNextEvent()) {
|
||
let event = Input.receiver.getNextEvent();
|
||
// Handle each event type
|
||
if (event.type === GameEventType_1.GameEventType.MOUSE_DOWN) {
|
||
Input.mouseJustPressed = true;
|
||
Input.mousePressed = true;
|
||
Input.mousePressPosition = event.data.get("position");
|
||
Input.mouseButtonPressed = event.data.get("button");
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.MOUSE_UP) {
|
||
Input.mousePressed = false;
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.MOUSE_MOVE) {
|
||
Input.mousePosition = event.data.get("position");
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.KEY_DOWN) {
|
||
let key = event.data.get("key");
|
||
// Handle space bar
|
||
if (key === " ") {
|
||
key = "space";
|
||
}
|
||
if (!Input.keyPressed.get(key)) {
|
||
Input.keyJustPressed.set(key, true);
|
||
Input.keyPressed.set(key, true);
|
||
}
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.KEY_UP) {
|
||
let key = event.data.get("key");
|
||
// Handle space bar
|
||
if (key === " ") {
|
||
key = "space";
|
||
}
|
||
Input.keyPressed.set(key, false);
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.CANVAS_BLUR) {
|
||
Input.clearKeyPresses();
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.WHEEL_UP) {
|
||
Input.scrollDirection = -1;
|
||
Input.justScrolled = true;
|
||
}
|
||
else if (event.type === GameEventType_1.GameEventType.WHEEL_DOWN) {
|
||
Input.scrollDirection = 1;
|
||
Input.justScrolled = true;
|
||
}
|
||
}
|
||
}
|
||
static clearKeyPresses() {
|
||
Input.keyJustPressed.forEach((key) => Input.keyJustPressed.set(key, false));
|
||
Input.keyPressed.forEach((key) => Input.keyPressed.set(key, false));
|
||
}
|
||
/**
|
||
* Returns whether or not a key was newly pressed Input frame.
|
||
* If the key is still pressed from last frame and wasn't re-pressed, Input will return false.
|
||
* @param key The key
|
||
* @returns True if the key was just pressed, false otherwise
|
||
*/
|
||
static isKeyJustPressed(key) {
|
||
if (Input.keysDisabled)
|
||
return false;
|
||
if (Input.keyJustPressed.has(key)) {
|
||
return Input.keyJustPressed.get(key);
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
/**
|
||
* Returns an array of all of the keys that are newly pressed Input frame.
|
||
* If a key is still pressed from last frame and wasn't re-pressed, it will not be in Input list.
|
||
* @returns An array of all of the newly pressed keys.
|
||
*/
|
||
static getKeysJustPressed() {
|
||
if (Input.keysDisabled)
|
||
return [];
|
||
let keys = Array();
|
||
Input.keyJustPressed.forEach(key => {
|
||
if (Input.keyJustPressed.get(key)) {
|
||
keys.push(key);
|
||
}
|
||
});
|
||
return keys;
|
||
}
|
||
/**
|
||
* Returns whether or not a key is being pressed.
|
||
* @param key The key
|
||
* @returns True if the key is currently pressed, false otherwise
|
||
*/
|
||
static isKeyPressed(key) {
|
||
if (Input.keysDisabled)
|
||
return false;
|
||
if (Input.keyPressed.has(key)) {
|
||
return Input.keyPressed.get(key);
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
/**
|
||
* Changes the binding of an input name to keys
|
||
* @param inputName The name of the input
|
||
* @param keys The corresponding keys
|
||
*/
|
||
static changeKeyBinding(inputName, keys) {
|
||
Input.keyMap.set(inputName, keys);
|
||
}
|
||
/**
|
||
* Clears all key bindings
|
||
*/
|
||
static clearAllKeyBindings() {
|
||
Input.keyMap.clear();
|
||
}
|
||
/**
|
||
* Returns whether or not an input was just pressed this frame
|
||
* @param inputName The name of the input
|
||
* @returns True if the input was just pressed, false otherwise
|
||
*/
|
||
static isJustPressed(inputName) {
|
||
if (Input.keysDisabled)
|
||
return false;
|
||
if (Input.keyMap.has(inputName)) {
|
||
const keys = Input.keyMap.get(inputName);
|
||
let justPressed = false;
|
||
for (let key of keys) {
|
||
justPressed = justPressed || Input.isKeyJustPressed(key);
|
||
}
|
||
return justPressed;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
/**
|
||
* Returns whether or not an input is currently pressed
|
||
* @param inputName The name of the input
|
||
* @returns True if the input is pressed, false otherwise
|
||
*/
|
||
static isPressed(inputName) {
|
||
if (Input.keysDisabled)
|
||
return false;
|
||
if (Input.keyMap.has(inputName)) {
|
||
const keys = Input.keyMap.get(inputName);
|
||
let pressed = false;
|
||
for (let key of keys) {
|
||
pressed = pressed || Input.isKeyPressed(key);
|
||
}
|
||
return pressed;
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
}
|
||
/**
|
||
*
|
||
* Returns whether or not the mouse was newly pressed Input frame.
|
||
* @param mouseButton Optionally specify which mouse click you want to know was pressed.
|
||
* 0 for left click, 1 for middle click, 2 for right click.
|
||
* @returns True if the mouse was just pressed, false otherwise
|
||
*/
|
||
static isMouseJustPressed(mouseButton) {
|
||
if (mouseButton !== undefined) {
|
||
return Input.mouseJustPressed && !Input.mouseDisabled && mouseButton == this.mouseButtonPressed;
|
||
}
|
||
return Input.mouseJustPressed && !Input.mouseDisabled;
|
||
}
|
||
/**
|
||
* Returns whether or not the mouse is currently pressed
|
||
* @param mouseButton Optionally specify which mouse click you want to know was pressed.
|
||
* 0 for left click, 1 for middle click, 2 for right click.
|
||
* @returns True if the mouse is currently pressed, false otherwise
|
||
*/
|
||
static isMousePressed(mouseButton) {
|
||
if (mouseButton !== undefined) {
|
||
return Input.mousePressed && !Input.mouseDisabled && mouseButton == this.mouseButtonPressed;
|
||
}
|
||
return Input.mousePressed && !Input.mouseDisabled;
|
||
}
|
||
/**
|
||
* Returns whether the user scrolled or not
|
||
* @returns True if the user just scrolled Input frame, false otherwise
|
||
*/
|
||
static didJustScroll() {
|
||
return Input.justScrolled && !Input.mouseDisabled;
|
||
}
|
||
/**
|
||
* Gets the direction of the scroll
|
||
* @returns -1 if the user scrolled up, 1 if they scrolled down
|
||
*/
|
||
static getScrollDirection() {
|
||
return Input.scrollDirection;
|
||
}
|
||
/**
|
||
* Gets the position of the player's mouse
|
||
* @returns The mouse position stored as a Vec2
|
||
*/
|
||
static getMousePosition() {
|
||
return Input.mousePosition.scaled(1 / this.viewport.getZoomLevel());
|
||
}
|
||
/**
|
||
* Gets the position of the player's mouse in the game world,
|
||
* taking into consideration the scrolling of the viewport
|
||
* @returns The mouse position stored as a Vec2
|
||
*/
|
||
static getGlobalMousePosition() {
|
||
return Input.mousePosition.clone().scale(1 / this.viewport.getZoomLevel()).add(Input.viewport.getOrigin());
|
||
}
|
||
/**
|
||
* Gets the position of the last mouse press
|
||
* @returns The mouse position stored as a Vec2
|
||
*/
|
||
static getMousePressPosition() {
|
||
return Input.getMousePosition();
|
||
}
|
||
/**
|
||
* Gets the position of the last mouse press in the game world,
|
||
* taking into consideration the scrolling of the viewport
|
||
* @returns The mouse position stored as a Vec2
|
||
*/
|
||
static getGlobalMousePressPosition() {
|
||
return Input.mousePressPosition.clone().add(Input.viewport.getOrigin());
|
||
}
|
||
/**
|
||
* Disables all keypress and mouse click inputs
|
||
*/
|
||
static disableInput() {
|
||
Input.keysDisabled = true;
|
||
Input.mouseDisabled = true;
|
||
}
|
||
/**
|
||
* Enables all keypress and mouse click inputs
|
||
*/
|
||
static enableInput() {
|
||
Input.keysDisabled = false;
|
||
Input.mouseDisabled = false;
|
||
}
|
||
}
|
||
exports.default = Input;
|
||
|
||
},{"../DataTypes/Map":10,"../DataTypes/Vec2":24,"../Events/EventQueue":28,"../Events/GameEventType":30,"../Events/Receiver":31}],33:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EventQueue_1 = require("../Events/EventQueue");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const GameEvent_1 = require("../Events/GameEvent");
|
||
const GameEventType_1 = require("../Events/GameEventType");
|
||
/**
|
||
* Handles communication with the web browser to receive asynchronous events and send them to the @reference[EventQueue]
|
||
*/
|
||
class InputHandler {
|
||
/**
|
||
* Creates a new InputHandler
|
||
* @param canvas The game canvas
|
||
*/
|
||
constructor(canvas) {
|
||
this.handleMouseDown = (event, canvas) => {
|
||
let pos = this.getMousePosition(event, canvas);
|
||
let button = event.button;
|
||
let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.MOUSE_DOWN, { position: pos, button: button });
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.handleMouseUp = (event, canvas) => {
|
||
let pos = this.getMousePosition(event, canvas);
|
||
let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.MOUSE_UP, { position: pos });
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.handleMouseMove = (event, canvas) => {
|
||
let pos = this.getMousePosition(event, canvas);
|
||
let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.MOUSE_MOVE, { position: pos });
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.handleKeyDown = (event) => {
|
||
let key = this.getKey(event);
|
||
let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.KEY_DOWN, { key: key });
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.handleKeyUp = (event) => {
|
||
let key = this.getKey(event);
|
||
let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.KEY_UP, { key: key });
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.handleBlur = (event) => {
|
||
let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.CANVAS_BLUR, {});
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.handleContextMenu = (event) => {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
};
|
||
this.handleWheel = (event) => {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
let gameEvent;
|
||
if (event.deltaY < 0) {
|
||
gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.WHEEL_UP, {});
|
||
}
|
||
else {
|
||
gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.WHEEL_DOWN, {});
|
||
}
|
||
this.eventQueue.addEvent(gameEvent);
|
||
};
|
||
this.eventQueue = EventQueue_1.default.getInstance();
|
||
canvas.onmousedown = (event) => this.handleMouseDown(event, canvas);
|
||
canvas.onmouseup = (event) => this.handleMouseUp(event, canvas);
|
||
canvas.oncontextmenu = this.handleContextMenu;
|
||
canvas.onmousemove = (event) => this.handleMouseMove(event, canvas);
|
||
document.onkeydown = this.handleKeyDown;
|
||
document.onkeyup = this.handleKeyUp;
|
||
document.onblur = this.handleBlur;
|
||
document.oncontextmenu = this.handleBlur;
|
||
document.onwheel = this.handleWheel;
|
||
}
|
||
getKey(keyEvent) {
|
||
return keyEvent.key.toLowerCase();
|
||
}
|
||
getMousePosition(mouseEvent, canvas) {
|
||
let rect = canvas.getBoundingClientRect();
|
||
let x = mouseEvent.clientX - rect.left;
|
||
let y = mouseEvent.clientY - rect.top;
|
||
return new Vec2_1.default(x, y);
|
||
}
|
||
}
|
||
exports.default = InputHandler;
|
||
|
||
},{"../DataTypes/Vec2":24,"../Events/EventQueue":28,"../Events/GameEvent":29,"../Events/GameEventType":30}],34:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
// @ignorePage
|
||
/**
|
||
* Sets up the environment of the game engine
|
||
*/
|
||
class EnvironmentInitializer {
|
||
static setup() {
|
||
CanvasRenderingContext2D.prototype.roundedRect = function (x, y, w, h, r) {
|
||
// Clamp the radius between 0 and the min of the width or height
|
||
if (r < 0)
|
||
r = 0;
|
||
if (r > Math.min(w, h))
|
||
r = Math.min(w, h);
|
||
// Draw the rounded rect
|
||
this.beginPath();
|
||
// Top
|
||
this.moveTo(x + r, y);
|
||
this.lineTo(x + w - r, y);
|
||
this.arcTo(x + w, y, x + w, y + r, r);
|
||
// Right
|
||
this.lineTo(x + w, y + h - r);
|
||
this.arcTo(x + w, y + h, x + w - r, y + h, r);
|
||
// Bottom
|
||
this.lineTo(x + r, y + h);
|
||
this.arcTo(x, y + h, x, y + h - r, r);
|
||
// Left
|
||
this.lineTo(x, y + r);
|
||
this.arcTo(x, y, x + r, y, r);
|
||
this.closePath();
|
||
};
|
||
CanvasRenderingContext2D.prototype.strokeRoundedRect = function (x, y, w, h, r) {
|
||
this.roundedRect(x, y, w, h, r);
|
||
this.stroke();
|
||
};
|
||
CanvasRenderingContext2D.prototype.fillRoundedRect = function (x, y, w, h, r) {
|
||
this.roundedRect(x, y, w, h, r);
|
||
this.fill();
|
||
};
|
||
}
|
||
}
|
||
exports.default = EnvironmentInitializer;
|
||
|
||
},{}],35:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const GameLoop_1 = require("./GameLoop");
|
||
const Debug_1 = require("../Debug/Debug");
|
||
const Stats_1 = require("../Debug/Stats");
|
||
/**
|
||
* A game loop with a fixed update time and a variable render time.
|
||
* Every frame, the game updates until all time since the last frame has been processed.
|
||
* If too much time has passed, such as if the last update was too slow,
|
||
* or if the browser was put into the background, the loop will panic and discard time.
|
||
* A render happens at the end of every frame. This happens as fast as possible unless specified.
|
||
* A loop of this type allows for deterministic behavior - No matter what the frame rate is, the update should behave the same,
|
||
* as it is occuring in a fixed interval.
|
||
*/
|
||
class FixedUpdateGameLoop extends GameLoop_1.default {
|
||
constructor() {
|
||
super();
|
||
/**
|
||
* The main loop of the game. Updates until the current time is reached. Renders once
|
||
* @param timestamp The current time in ms
|
||
*/
|
||
this.doFrame = (timestamp) => {
|
||
// If a pause was executed, stop doing the loop.
|
||
if (this.paused) {
|
||
return;
|
||
}
|
||
// Request animation frame to prepare for another update or render
|
||
window.requestAnimationFrame((t) => this.doFrame(t));
|
||
// If we are trying to render too soon, do nothing.
|
||
if (timestamp < this.lastFrameTime + this.minFrameDelay) {
|
||
return;
|
||
}
|
||
// A frame is actually happening
|
||
this.startFrame(timestamp);
|
||
// Update while there is still time to make up. If we do too many update steps, panic and exit the loop.
|
||
this.numUpdateSteps = 0;
|
||
let panic = false;
|
||
while (this.frameDelta >= this.updateTimestep) {
|
||
// Do an update
|
||
this._doUpdate(this.updateTimestep / 1000);
|
||
// Remove the update step time from the time we have to process
|
||
this.frameDelta -= this.updateTimestep;
|
||
// Increment steps and check if we've done too many
|
||
this.numUpdateSteps++;
|
||
if (this.numUpdateSteps > 100) {
|
||
panic = true;
|
||
break;
|
||
}
|
||
}
|
||
// Updates are done, render
|
||
this._doRender();
|
||
// Wrap up the frame
|
||
this.finishFrame(panic);
|
||
};
|
||
this.maxUpdateFPS = 60;
|
||
this.updateTimestep = Math.floor(1000 / this.maxUpdateFPS);
|
||
this.frameDelta = 0;
|
||
this.lastFrameTime = 0;
|
||
this.minFrameDelay = 0;
|
||
this.frame = 0;
|
||
this.fps = this.maxUpdateFPS; // Initialize the fps to the max allowed fps
|
||
this.fpsUpdateInterval = 1000;
|
||
this.lastFpsUpdate = 0;
|
||
this.framesSinceLastFpsUpdate = 0;
|
||
this.started = false;
|
||
this.paused = false;
|
||
this.running = false;
|
||
this.numUpdateSteps = 0;
|
||
}
|
||
getFPS() {
|
||
return 0;
|
||
}
|
||
/**
|
||
* Updates the frame count and sum of time for the framerate of the game
|
||
* @param timestep The current time in ms
|
||
*/
|
||
updateFPS(timestamp) {
|
||
this.fps = 0.9 * this.framesSinceLastFpsUpdate * 1000 / (timestamp - this.lastFpsUpdate) + (1 - 0.9) * this.fps;
|
||
this.lastFpsUpdate = timestamp;
|
||
this.framesSinceLastFpsUpdate = 0;
|
||
Debug_1.default.log("fps", "FPS: " + this.fps.toFixed(1));
|
||
Stats_1.default.updateFPS(this.fps);
|
||
}
|
||
/**
|
||
* Changes the maximum allowed physics framerate of the game
|
||
* @param initMax The max framerate
|
||
*/
|
||
setMaxUpdateFPS(initMax) {
|
||
this.maxUpdateFPS = initMax;
|
||
this.updateTimestep = Math.floor(1000 / this.maxUpdateFPS);
|
||
}
|
||
/**
|
||
* Sets the maximum rendering framerate
|
||
* @param maxFPS The max framerate
|
||
*/
|
||
setMaxFPS(maxFPS) {
|
||
this.minFrameDelay = 1000 / maxFPS;
|
||
}
|
||
/**
|
||
* This function is called when the game loop panics, i.e. it tries to process too much time in an entire frame.
|
||
* This will reset the amount of time back to zero.
|
||
* @returns The amount of time we are discarding from processing.
|
||
*/
|
||
resetFrameDelta() {
|
||
let oldFrameDelta = this.frameDelta;
|
||
this.frameDelta = 0;
|
||
return oldFrameDelta;
|
||
}
|
||
/**
|
||
* Starts up the game loop and calls the first requestAnimationFrame
|
||
*/
|
||
start() {
|
||
if (!this.started) {
|
||
this.started = true;
|
||
window.requestAnimationFrame((timestamp) => this.doFirstFrame(timestamp));
|
||
}
|
||
}
|
||
pause() {
|
||
this.paused = true;
|
||
}
|
||
resume() {
|
||
this.paused = false;
|
||
}
|
||
/**
|
||
* The first game frame - initializes the first frame time and begins the render
|
||
* @param timestamp The current time in ms
|
||
*/
|
||
doFirstFrame(timestamp) {
|
||
this.running = true;
|
||
this._doRender();
|
||
this.lastFrameTime = timestamp;
|
||
this.lastFpsUpdate = timestamp;
|
||
this.framesSinceLastFpsUpdate = 0;
|
||
window.requestAnimationFrame((t) => this.doFrame(t));
|
||
}
|
||
/**
|
||
* Handles any processing that needs to be done at the start of the frame
|
||
* @param timestamp The time of the frame in ms
|
||
*/
|
||
startFrame(timestamp) {
|
||
// Update the amount of time we need our update to process
|
||
this.frameDelta += timestamp - this.lastFrameTime;
|
||
// Set the new time of the last frame
|
||
this.lastFrameTime = timestamp;
|
||
// Update the estimate of the framerate
|
||
if (timestamp > this.lastFpsUpdate + this.fpsUpdateInterval) {
|
||
this.updateFPS(timestamp);
|
||
}
|
||
// Increment the number of frames
|
||
this.frame++;
|
||
this.framesSinceLastFpsUpdate++;
|
||
}
|
||
/**
|
||
* Wraps up the frame and handles the panic state if there is one
|
||
* @param panic Whether or not the loop panicked
|
||
*/
|
||
finishFrame(panic) {
|
||
if (panic) {
|
||
var discardedTime = Math.round(this.resetFrameDelta());
|
||
console.warn('Main loop panicked, probably because the browser tab was put in the background. Discarding ' + discardedTime + 'ms');
|
||
}
|
||
}
|
||
}
|
||
exports.default = FixedUpdateGameLoop;
|
||
|
||
},{"../Debug/Debug":25,"../Debug/Stats":26,"./GameLoop":37}],36:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EventQueue_1 = require("../Events/EventQueue");
|
||
const Input_1 = require("../Input/Input");
|
||
const InputHandler_1 = require("../Input/InputHandler");
|
||
const Recorder_1 = require("../Playback/Recorder");
|
||
const Debug_1 = require("../Debug/Debug");
|
||
const ResourceManager_1 = require("../ResourceManager/ResourceManager");
|
||
const Viewport_1 = require("../SceneGraph/Viewport");
|
||
const SceneManager_1 = require("../Scene/SceneManager");
|
||
const AudioManager_1 = require("../Sound/AudioManager");
|
||
const Stats_1 = require("../Debug/Stats");
|
||
const CanvasRenderer_1 = require("../Rendering/CanvasRenderer");
|
||
const Color_1 = require("../Utils/Color");
|
||
const GameOptions_1 = require("./GameOptions");
|
||
const FixedUpdateGameLoop_1 = require("./FixedUpdateGameLoop");
|
||
const EnvironmentInitializer_1 = require("./EnvironmentInitializer");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const RegistryManager_1 = require("../Registry/RegistryManager");
|
||
const WebGLRenderer_1 = require("../Rendering/WebGLRenderer");
|
||
/**
|
||
* The main loop of the game engine.
|
||
* Handles the update order, and initializes all subsystems.
|
||
* The Game manages the update cycle, and requests animation frames to render to the browser.
|
||
*/
|
||
class Game {
|
||
/**
|
||
* Creates a new Game
|
||
* @param options The options for Game initialization
|
||
*/
|
||
constructor(options) {
|
||
// Before anything else, build the environment
|
||
EnvironmentInitializer_1.default.setup();
|
||
// Typecast the config object to a GameConfig object
|
||
this.gameOptions = GameOptions_1.default.parse(options);
|
||
this.showDebug = this.gameOptions.showDebug;
|
||
this.showStats = this.gameOptions.showStats;
|
||
// Create an instance of a game loop
|
||
this.loop = new FixedUpdateGameLoop_1.default();
|
||
// Get the game canvas and give it a background color
|
||
this.GAME_CANVAS = document.getElementById("game-canvas");
|
||
this.DEBUG_CANVAS = document.getElementById("debug-canvas");
|
||
// Give the canvas a size and get the rendering context
|
||
this.WIDTH = this.gameOptions.canvasSize.x;
|
||
this.HEIGHT = this.gameOptions.canvasSize.y;
|
||
// This step MUST happen before the resource manager does anything
|
||
if (this.gameOptions.useWebGL) {
|
||
this.renderingManager = new WebGLRenderer_1.default();
|
||
}
|
||
else {
|
||
this.renderingManager = new CanvasRenderer_1.default();
|
||
}
|
||
this.initializeGameWindow();
|
||
this.ctx = this.renderingManager.initializeCanvas(this.GAME_CANVAS, this.WIDTH, this.HEIGHT);
|
||
this.clearColor = new Color_1.default(this.gameOptions.clearColor.r, this.gameOptions.clearColor.g, this.gameOptions.clearColor.b);
|
||
// Initialize debugging and stats
|
||
Debug_1.default.initializeDebugCanvas(this.DEBUG_CANVAS, this.WIDTH, this.HEIGHT);
|
||
Stats_1.default.initStats();
|
||
if (this.gameOptions.showStats) {
|
||
// Find the stats output and make it no longer hidden
|
||
document.getElementById("stats").hidden = false;
|
||
}
|
||
// Size the viewport to the game canvas
|
||
const canvasSize = new Vec2_1.default(this.WIDTH, this.HEIGHT);
|
||
this.viewport = new Viewport_1.default(canvasSize, this.gameOptions.zoomLevel);
|
||
// Initialize all necessary game subsystems
|
||
this.eventQueue = EventQueue_1.default.getInstance();
|
||
this.inputHandler = new InputHandler_1.default(this.GAME_CANVAS);
|
||
Input_1.default.initialize(this.viewport, this.gameOptions.inputs);
|
||
this.recorder = new Recorder_1.default();
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
this.sceneManager = new SceneManager_1.default(this.viewport, this.renderingManager);
|
||
this.audioManager = AudioManager_1.default.getInstance();
|
||
}
|
||
/**
|
||
* Set up the game window that holds the canvases
|
||
*/
|
||
initializeGameWindow() {
|
||
const gameWindow = document.getElementById("game-window");
|
||
// Set the height of the game window
|
||
gameWindow.style.width = this.WIDTH + "px";
|
||
gameWindow.style.height = this.HEIGHT + "px";
|
||
}
|
||
/**
|
||
* Retreives the SceneManager from the Game
|
||
* @returns The SceneManager
|
||
*/
|
||
getSceneManager() {
|
||
return this.sceneManager;
|
||
}
|
||
/**
|
||
* Starts the game
|
||
*/
|
||
start(InitialScene, options) {
|
||
// Set the update function of the loop
|
||
this.loop.doUpdate = (deltaT) => this.update(deltaT);
|
||
// Set the render function of the loop
|
||
this.loop.doRender = () => this.render();
|
||
// Preload registry items
|
||
RegistryManager_1.default.preload();
|
||
// Load the items with the resource manager
|
||
this.resourceManager.loadResourcesFromQueue(() => {
|
||
// When we're done loading, start the loop
|
||
console.log("Finished Preload - loading first scene");
|
||
this.sceneManager.changeToScene(InitialScene, {}, options);
|
||
this.loop.start();
|
||
});
|
||
}
|
||
/**
|
||
* Updates all necessary subsystems of the game. Defers scene updates to the sceneManager
|
||
* @param deltaT The time sine the last update
|
||
*/
|
||
update(deltaT) {
|
||
try {
|
||
// Handle all events that happened since the start of the last loop
|
||
this.eventQueue.update(deltaT);
|
||
// Update the input data structures so game objects can see the input
|
||
Input_1.default.update(deltaT);
|
||
// Update the recording of the game
|
||
this.recorder.update(deltaT);
|
||
// Update all scenes
|
||
this.sceneManager.update(deltaT);
|
||
// Update all sounds
|
||
this.audioManager.update(deltaT);
|
||
// Load or unload any resources if needed
|
||
this.resourceManager.update(deltaT);
|
||
}
|
||
catch (e) {
|
||
this.loop.pause();
|
||
console.warn("Uncaught Error in Update - Crashing gracefully");
|
||
console.error(e);
|
||
}
|
||
}
|
||
/**
|
||
* Clears the canvas and defers scene rendering to the sceneManager. Renders the debug canvas
|
||
*/
|
||
render() {
|
||
try {
|
||
// Clear the canvases
|
||
Debug_1.default.clearCanvas();
|
||
this.renderingManager.clear(this.clearColor);
|
||
this.sceneManager.render();
|
||
// Hacky debug mode
|
||
if (Input_1.default.isKeyJustPressed("g")) {
|
||
this.showDebug = !this.showDebug;
|
||
}
|
||
// Debug render
|
||
if (this.showDebug) {
|
||
Debug_1.default.render();
|
||
}
|
||
if (this.showStats) {
|
||
Stats_1.default.render();
|
||
}
|
||
}
|
||
catch (e) {
|
||
this.loop.pause();
|
||
console.warn("Uncaught Error in Render - Crashing gracefully");
|
||
console.error(e);
|
||
}
|
||
}
|
||
}
|
||
exports.default = Game;
|
||
|
||
},{"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Debug/Stats":26,"../Events/EventQueue":28,"../Input/Input":32,"../Input/InputHandler":33,"../Playback/Recorder":62,"../Registry/RegistryManager":65,"../Rendering/CanvasRenderer":71,"../Rendering/WebGLRenderer":76,"../ResourceManager/ResourceManager":83,"../Scene/SceneManager":91,"../SceneGraph/Viewport":95,"../Sound/AudioManager":96,"../Utils/Color":99,"./EnvironmentInitializer":34,"./FixedUpdateGameLoop":35,"./GameOptions":38}],37:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const NullFunc_1 = require("../DataTypes/Functions/NullFunc");
|
||
/**
|
||
* The main game loop of the game. Keeps track of fps and handles scheduling of updates and rendering.
|
||
* This class is left abstract, so that a subclass can handle exactly how the loop is scheduled.
|
||
* For an example of different types of game loop scheduling, check out @link(Game Programming Patterns)(https://gameprogrammingpatterns.com/game-loop.html)
|
||
*/
|
||
class GameLoop {
|
||
constructor() {
|
||
/** The function to call when an update occurs */
|
||
this._doUpdate = NullFunc_1.default;
|
||
/** The function to call when a render occurs */
|
||
this._doRender = NullFunc_1.default;
|
||
}
|
||
set doUpdate(update) {
|
||
this._doUpdate = update;
|
||
}
|
||
set doRender(render) {
|
||
this._doRender = render;
|
||
}
|
||
}
|
||
exports.default = GameLoop;
|
||
|
||
},{"../DataTypes/Functions/NullFunc":5}],38:[function(require,module,exports){
|
||
"use strict";
|
||
// @ignorePage
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/** The options for initializing the @reference[GameLoop] */
|
||
class GameOptions {
|
||
/**
|
||
* Parses the data in the raw options object
|
||
* @param options The game options as a Record
|
||
* @returns A version of the options converted to a GameOptions object
|
||
*/
|
||
static parse(options) {
|
||
let gOpt = new GameOptions();
|
||
gOpt.canvasSize = options.canvasSize ? options.canvasSize : { x: 800, y: 600 };
|
||
gOpt.zoomLevel = options.zoomLevel ? options.zoomLevel : 1;
|
||
gOpt.clearColor = options.clearColor ? options.clearColor : { r: 255, g: 255, b: 255 };
|
||
gOpt.inputs = options.inputs ? options.inputs : [];
|
||
gOpt.showDebug = !!options.showDebug;
|
||
gOpt.showStats = !!options.showStats;
|
||
gOpt.useWebGL = !!options.useWebGL;
|
||
return gOpt;
|
||
}
|
||
}
|
||
exports.default = GameOptions;
|
||
|
||
},{}],39:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const GameNode_1 = require("./GameNode");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const AABB_1 = require("../DataTypes/Shapes/AABB");
|
||
const Debug_1 = require("../Debug/Debug");
|
||
const Color_1 = require("../Utils/Color");
|
||
/**
|
||
* The representation of an object in the game world that can be drawn to the screen
|
||
*/
|
||
class CanvasNode extends GameNode_1.default {
|
||
constructor() {
|
||
super();
|
||
/** A flag for whether or not the CanvasNode is visible */
|
||
this.visible = true;
|
||
this._size = new Vec2_1.default(0, 0);
|
||
this._size.setOnChange(() => this.sizeChanged());
|
||
this._scale = new Vec2_1.default(1, 1);
|
||
this._scale.setOnChange(() => this.scaleChanged());
|
||
this._boundary = new AABB_1.default();
|
||
this.updateBoundary();
|
||
this._hasCustomShader = false;
|
||
}
|
||
get alpha() {
|
||
return this._alpha;
|
||
}
|
||
set alpha(a) {
|
||
this._alpha = a;
|
||
}
|
||
get size() {
|
||
return this._size;
|
||
}
|
||
set size(size) {
|
||
this._size = size;
|
||
// Enter as a lambda to bind "this"
|
||
this._size.setOnChange(() => this.sizeChanged());
|
||
this.sizeChanged();
|
||
}
|
||
get scale() {
|
||
return this._scale;
|
||
}
|
||
set scale(scale) {
|
||
this._scale = scale;
|
||
// Enter as a lambda to bind "this"
|
||
this._scale.setOnChange(() => this.scaleChanged());
|
||
this.scaleChanged();
|
||
}
|
||
set scaleX(value) {
|
||
this.scale.x = value;
|
||
}
|
||
set scaleY(value) {
|
||
this.scale.y = value;
|
||
}
|
||
get hasCustomShader() {
|
||
return this._hasCustomShader;
|
||
}
|
||
get customShaderKey() {
|
||
return this._customShaderKey;
|
||
}
|
||
// @override
|
||
positionChanged() {
|
||
super.positionChanged();
|
||
this.updateBoundary();
|
||
}
|
||
/** Called if the size vector is changed or replaced. */
|
||
sizeChanged() {
|
||
this.updateBoundary();
|
||
}
|
||
/** Called if the scale vector is changed or replaced */
|
||
scaleChanged() {
|
||
this.updateBoundary();
|
||
}
|
||
// @docIgnore
|
||
/** Called if the position, size, or scale of the CanvasNode is changed. Updates the boundary. */
|
||
updateBoundary() {
|
||
this._boundary.center.set(this.position.x, this.position.y);
|
||
this._boundary.halfSize.set(this.size.x * this.scale.x / 2, this.size.y * this.scale.y / 2);
|
||
}
|
||
get boundary() {
|
||
return this._boundary;
|
||
}
|
||
get sizeWithZoom() {
|
||
let zoom = this.scene.getViewScale();
|
||
return this.boundary.halfSize.clone().scaled(zoom, zoom);
|
||
}
|
||
/**
|
||
* Adds a custom shader to this CanvasNode
|
||
* @param key The registry key of the ShaderType
|
||
*/
|
||
useCustomShader(key) {
|
||
this._hasCustomShader = true;
|
||
this._customShaderKey = key;
|
||
}
|
||
/**
|
||
* Returns true if the point (x, y) is inside of this canvas object
|
||
* @param x The x position of the point
|
||
* @param y The y position of the point
|
||
* @returns A flag representing whether or not this node contains the point.
|
||
*/
|
||
contains(x, y) {
|
||
return this._boundary.containsPoint(new Vec2_1.default(x, y));
|
||
}
|
||
// @implemented
|
||
debugRender() {
|
||
Debug_1.default.drawBox(this.relativePosition, this.sizeWithZoom, false, Color_1.default.BLUE);
|
||
super.debugRender();
|
||
}
|
||
}
|
||
exports.default = CanvasNode;
|
||
|
||
},{"../DataTypes/Shapes/AABB":16,"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Utils/Color":99,"./GameNode":40}],40:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.TweenableProperties = void 0;
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const Receiver_1 = require("../Events/Receiver");
|
||
const Emitter_1 = require("../Events/Emitter");
|
||
const Region_1 = require("../DataTypes/Interfaces/Region");
|
||
const AABB_1 = require("../DataTypes/Shapes/AABB");
|
||
const TweenController_1 = require("../Rendering/Animations/TweenController");
|
||
const Debug_1 = require("../Debug/Debug");
|
||
const Color_1 = require("../Utils/Color");
|
||
const Circle_1 = require("../DataTypes/Shapes/Circle");
|
||
/**
|
||
* The representation of an object in the game world.
|
||
* To construct GameNodes, see the @reference[Scene] documentation.
|
||
*/
|
||
class GameNode {
|
||
// Constructor docs are ignored, as the user should NOT create new GameNodes with a raw constructor
|
||
constructor() {
|
||
/*---------- PHYSICAL ----------*/
|
||
this.hasPhysics = false;
|
||
this.moving = false;
|
||
this.frozen = false;
|
||
this.onGround = false;
|
||
this.onWall = false;
|
||
this.onCeiling = false;
|
||
this.active = false;
|
||
this.isColliding = false;
|
||
this.pathfinding = false;
|
||
this._position = new Vec2_1.default(0, 0);
|
||
this._position.setOnChange(() => this.positionChanged());
|
||
this.receiver = new Receiver_1.default();
|
||
this.emitter = new Emitter_1.default();
|
||
this.tweens = new TweenController_1.default(this);
|
||
this.rotation = 0;
|
||
}
|
||
destroy() {
|
||
this.tweens.destroy();
|
||
this.receiver.destroy();
|
||
if (this.hasPhysics) {
|
||
this.removePhysics();
|
||
}
|
||
if (this._ai) {
|
||
this._ai.destroy();
|
||
delete this._ai;
|
||
this.scene.getAIManager().removeActor(this);
|
||
}
|
||
this.scene.remove(this);
|
||
this.layer.removeNode(this);
|
||
}
|
||
/*---------- POSITIONED ----------*/
|
||
get position() {
|
||
return this._position;
|
||
}
|
||
set position(pos) {
|
||
this._position = pos;
|
||
this._position.setOnChange(() => this.positionChanged());
|
||
this.positionChanged();
|
||
}
|
||
get relativePosition() {
|
||
return this.inRelativeCoordinates(this.position);
|
||
}
|
||
/**
|
||
* Converts a point to coordinates relative to the zoom and origin of this node
|
||
* @param point The point to conver
|
||
* @returns A new Vec2 representing the point in relative coordinates
|
||
*/
|
||
inRelativeCoordinates(point) {
|
||
let origin = this.scene.getViewTranslation(this);
|
||
let zoom = this.scene.getViewScale();
|
||
return point.clone().sub(origin).scale(zoom);
|
||
}
|
||
/*---------- UNIQUE ----------*/
|
||
get id() {
|
||
return this._id;
|
||
}
|
||
set id(id) {
|
||
// id can only be set once
|
||
if (this._id === undefined) {
|
||
this._id = id;
|
||
}
|
||
else {
|
||
throw "Attempted to assign id to object that already has id.";
|
||
}
|
||
}
|
||
/*---------- PHYSICAL ----------*/
|
||
// @implemented
|
||
/**
|
||
* @param velocity The velocity with which to move the object.
|
||
*/
|
||
move(velocity) {
|
||
if (this.frozen)
|
||
return;
|
||
this.moving = true;
|
||
this._velocity = velocity;
|
||
}
|
||
;
|
||
moveOnPath(speed, path) {
|
||
if (this.frozen)
|
||
return;
|
||
this.path = path;
|
||
let dir = path.getMoveDirection(this);
|
||
this.moving = true;
|
||
this.pathfinding = true;
|
||
this._velocity = dir.scale(speed);
|
||
}
|
||
// @implemented
|
||
/**
|
||
* @param velocity The velocity with which the object will move.
|
||
*/
|
||
finishMove() {
|
||
this.moving = false;
|
||
this.position.add(this._velocity);
|
||
if (this.pathfinding) {
|
||
this.path.handlePathProgress(this);
|
||
this.path = null;
|
||
this.pathfinding = false;
|
||
}
|
||
}
|
||
// @implemented
|
||
/**
|
||
* @param collisionShape The collider for this object. If this has a region (implements Region),
|
||
* it will be used when no collision shape is specified (or if collision shape is null).
|
||
* @param isCollidable Whether this is collidable or not. True by default.
|
||
* @param isStatic Whether this is static or not. False by default
|
||
*/
|
||
addPhysics(collisionShape, colliderOffset, isCollidable = true, isStatic = false) {
|
||
// Initialize the physics variables
|
||
this.hasPhysics = true;
|
||
this.moving = false;
|
||
this.onGround = false;
|
||
this.onWall = false;
|
||
this.onCeiling = false;
|
||
this.active = true;
|
||
this.isCollidable = isCollidable;
|
||
this.isStatic = isStatic;
|
||
this.isTrigger = false;
|
||
this.triggerMask = 0;
|
||
this.triggerEnters = new Array(32);
|
||
this.triggerExits = new Array(32);
|
||
this._velocity = Vec2_1.default.ZERO;
|
||
this.sweptRect = new AABB_1.default();
|
||
this.collidedWithTilemap = false;
|
||
this.group = -1; // The default group, collides with everything
|
||
// Set the collision shape if provided, or simply use the the region if there is one.
|
||
if (collisionShape) {
|
||
this.collisionShape = collisionShape;
|
||
this.collisionShape.center = this.position;
|
||
}
|
||
else if (Region_1.isRegion(this)) {
|
||
// If the gamenode has a region and no other is specified, use that
|
||
this.collisionShape = this.boundary.clone();
|
||
}
|
||
else {
|
||
throw "No collision shape specified for physics object.";
|
||
}
|
||
// If we were provided with a collider offset, set it. Otherwise there is no offset, so use the zero vector
|
||
if (colliderOffset) {
|
||
this.colliderOffset = colliderOffset;
|
||
}
|
||
else {
|
||
this.colliderOffset = Vec2_1.default.ZERO;
|
||
}
|
||
// Initialize the swept rect
|
||
this.sweptRect = this.collisionShape.getBoundingRect();
|
||
// Register the object with physics
|
||
this.scene.getPhysicsManager().registerObject(this);
|
||
}
|
||
/** Removes this object from the physics system */
|
||
removePhysics() {
|
||
// Remove this from the physics manager
|
||
this.scene.getPhysicsManager().deregisterObject(this);
|
||
// Nullify all physics fields
|
||
this.hasPhysics = false;
|
||
this.moving = false;
|
||
this.onGround = false;
|
||
this.onWall = false;
|
||
this.onCeiling = false;
|
||
this.active = false;
|
||
this.isCollidable = false;
|
||
this.isStatic = false;
|
||
this.isTrigger = false;
|
||
this.triggerMask = 0;
|
||
this.triggerEnters = null;
|
||
this.triggerExits = null;
|
||
this._velocity = Vec2_1.default.ZERO;
|
||
this.sweptRect = null;
|
||
this.collidedWithTilemap = false;
|
||
this.group = -1;
|
||
this.collisionShape = null;
|
||
this.colliderOffset = Vec2_1.default.ZERO;
|
||
this.sweptRect = null;
|
||
}
|
||
/** Disables physics movement for this node */
|
||
freeze() {
|
||
this.frozen = true;
|
||
}
|
||
/** Reenables physics movement for this node */
|
||
unfreeze() {
|
||
this.frozen = false;
|
||
}
|
||
/** Prevents this object from participating in all collisions and triggers. It can still move. */
|
||
disablePhysics() {
|
||
this.active = false;
|
||
}
|
||
/** Enables this object to participate in collisions and triggers. This is only necessary if disablePhysics was called */
|
||
enablePhysics() {
|
||
this.active = true;
|
||
}
|
||
/**
|
||
* Sets the collider for this GameNode
|
||
* @param collider The new collider to use
|
||
*/
|
||
setCollisionShape(collider) {
|
||
this.collisionShape = collider;
|
||
this.collisionShape.center.copy(this.position);
|
||
}
|
||
// @implemented
|
||
/**
|
||
* Sets this object to be a trigger for a specific group
|
||
* @param group The name of the group that activates the trigger
|
||
* @param onEnter The name of the event to send when this trigger is activated
|
||
* @param onExit The name of the event to send when this trigger stops being activated
|
||
*/
|
||
setTrigger(group, onEnter, onExit) {
|
||
// Make this object a trigger
|
||
this.isTrigger = true;
|
||
// Get the number of the physics layer
|
||
let layerNumber = this.scene.getPhysicsManager().getGroupNumber(group);
|
||
if (layerNumber === 0) {
|
||
console.warn(`Trigger for GameNode ${this.id} not set - group "${group}" was not recognized by the physics manager.`);
|
||
return;
|
||
}
|
||
// Add this to the trigger mask
|
||
this.triggerMask |= layerNumber;
|
||
// Layer numbers are bits, so get which bit it is
|
||
let index = Math.log2(layerNumber);
|
||
// Set the event names
|
||
this.triggerEnters[index] = onEnter;
|
||
this.triggerExits[index] = onExit;
|
||
}
|
||
;
|
||
// @implemented
|
||
/**
|
||
* @param group The physics group this node should belong to
|
||
*/
|
||
setGroup(group) {
|
||
this.scene.getPhysicsManager().setGroup(this, group);
|
||
}
|
||
// @implemened
|
||
getLastVelocity() {
|
||
return this._velocity;
|
||
}
|
||
/*---------- ACTOR ----------*/
|
||
get ai() {
|
||
return this._ai;
|
||
}
|
||
set ai(ai) {
|
||
if (!this._ai) {
|
||
// If we haven't been previously had an ai, register us with the ai manager
|
||
this.scene.getAIManager().registerActor(this);
|
||
}
|
||
this._ai = ai;
|
||
this.aiActive = true;
|
||
}
|
||
// @implemented
|
||
addAI(ai, options, type) {
|
||
if (!this._ai) {
|
||
this.scene.getAIManager().registerActor(this);
|
||
}
|
||
if (typeof ai === "string") {
|
||
this._ai = this.scene.getAIManager().generateAI(ai);
|
||
}
|
||
else {
|
||
this._ai = new ai();
|
||
}
|
||
// Question, how much do we want different type of AI to be handled the same, i.e. should GoapAI and AI similar methods and signatures for the sake of unity
|
||
this._ai.initializeAI(this, options);
|
||
this.aiActive = true;
|
||
}
|
||
// @implemented
|
||
setAIActive(active, options) {
|
||
this.aiActive = active;
|
||
if (this.aiActive) {
|
||
this.ai.activate(options);
|
||
}
|
||
}
|
||
/*---------- TWEENABLE PROPERTIES ----------*/
|
||
set positionX(value) {
|
||
this.position.x = value;
|
||
}
|
||
set positionY(value) {
|
||
this.position.y = value;
|
||
}
|
||
/*---------- GAME NODE ----------*/
|
||
/**
|
||
* Sets the scene for this object.
|
||
* @param scene The scene this object belongs to.
|
||
*/
|
||
setScene(scene) {
|
||
this.scene = scene;
|
||
}
|
||
/**
|
||
* Gets the scene this object is in.
|
||
* @returns The scene this object belongs to
|
||
*/
|
||
getScene() {
|
||
return this.scene;
|
||
}
|
||
/**
|
||
* Sets the layer of this object.
|
||
* @param layer The layer this object will be on.
|
||
*/
|
||
setLayer(layer) {
|
||
this.layer = layer;
|
||
}
|
||
/**
|
||
* Returns the layer this object is on.
|
||
* @returns This layer this object is on.
|
||
*/
|
||
getLayer() {
|
||
return this.layer;
|
||
}
|
||
/** Called if the position vector is modified or replaced */
|
||
positionChanged() {
|
||
if (this.collisionShape) {
|
||
if (this.colliderOffset) {
|
||
this.collisionShape.center = this.position.clone().add(this.colliderOffset);
|
||
}
|
||
else {
|
||
this.collisionShape.center = this.position.clone();
|
||
}
|
||
}
|
||
}
|
||
;
|
||
/**
|
||
* Updates this GameNode
|
||
* @param deltaT The timestep of the update.
|
||
*/
|
||
update(deltaT) {
|
||
// Defer event handling to AI.
|
||
while (this.receiver.hasNextEvent()) {
|
||
this._ai.handleEvent(this.receiver.getNextEvent());
|
||
}
|
||
}
|
||
// @implemented
|
||
debugRender() {
|
||
// Draw the position of this GameNode
|
||
Debug_1.default.drawPoint(this.relativePosition, Color_1.default.BLUE);
|
||
// If velocity is not zero, draw a vector for it
|
||
if (this._velocity && !this._velocity.isZero()) {
|
||
Debug_1.default.drawRay(this.relativePosition, this._velocity.clone().scaleTo(20).add(this.relativePosition), Color_1.default.BLUE);
|
||
}
|
||
// If this has a collider, draw it
|
||
if (this.collisionShape) {
|
||
let color = this.isColliding ? Color_1.default.RED : Color_1.default.GREEN;
|
||
if (this.isTrigger) {
|
||
color = Color_1.default.MAGENTA;
|
||
}
|
||
color.a = 0.2;
|
||
if (this.collisionShape instanceof AABB_1.default) {
|
||
Debug_1.default.drawBox(this.inRelativeCoordinates(this.collisionShape.center), this.collisionShape.halfSize.scaled(this.scene.getViewScale()), true, color);
|
||
}
|
||
else if (this.collisionShape instanceof Circle_1.default) {
|
||
Debug_1.default.drawCircle(this.inRelativeCoordinates(this.collisionShape.center), this.collisionShape.hw * this.scene.getViewScale(), true, color);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = GameNode;
|
||
var TweenableProperties;
|
||
(function (TweenableProperties) {
|
||
TweenableProperties["posX"] = "positionX";
|
||
TweenableProperties["posY"] = "positionY";
|
||
TweenableProperties["scaleX"] = "scaleX";
|
||
TweenableProperties["scaleY"] = "scaleY";
|
||
TweenableProperties["rotation"] = "rotation";
|
||
TweenableProperties["alpha"] = "alpha";
|
||
})(TweenableProperties = exports.TweenableProperties || (exports.TweenableProperties = {}));
|
||
|
||
},{"../DataTypes/Interfaces/Region":9,"../DataTypes/Shapes/AABB":16,"../DataTypes/Shapes/Circle":17,"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Events/Emitter":27,"../Events/Receiver":31,"../Rendering/Animations/TweenController":69,"../Utils/Color":99}],41:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const CanvasNode_1 = require("./CanvasNode");
|
||
const Color_1 = require("../Utils/Color");
|
||
/**
|
||
* The representation of a game object that doesn't rely on any resources to render - it is drawn to the screen by the canvas
|
||
*/
|
||
class Graphic extends CanvasNode_1.default {
|
||
constructor() {
|
||
super();
|
||
this.color = Color_1.default.RED;
|
||
}
|
||
get alpha() {
|
||
return this.color.a;
|
||
}
|
||
set alpha(a) {
|
||
this.color.a = a;
|
||
}
|
||
// @deprecated
|
||
/**
|
||
* Sets the color of the Graphic. DEPRECATED
|
||
* @param color The new color of the Graphic.
|
||
*/
|
||
setColor(color) {
|
||
this.color = color;
|
||
}
|
||
set colorR(r) {
|
||
this.color.r = r;
|
||
}
|
||
get colorR() {
|
||
return this.color.r;
|
||
}
|
||
set colorG(g) {
|
||
this.color.g = g;
|
||
}
|
||
get colorG() {
|
||
return this.color.g;
|
||
}
|
||
set colorB(b) {
|
||
this.color.b = b;
|
||
}
|
||
get colorB() {
|
||
return this.color.b;
|
||
}
|
||
}
|
||
exports.default = Graphic;
|
||
|
||
},{"../Utils/Color":99,"./CanvasNode":39}],42:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.GraphicType = void 0;
|
||
var GraphicType;
|
||
(function (GraphicType) {
|
||
GraphicType["POINT"] = "POINT";
|
||
GraphicType["RECT"] = "RECT";
|
||
GraphicType["LINE"] = "LINE";
|
||
GraphicType["PARTICLE"] = "PARTICLE";
|
||
})(GraphicType = exports.GraphicType || (exports.GraphicType = {}));
|
||
|
||
},{}],43:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Graphic_1 = require("../Graphic");
|
||
class Line extends Graphic_1.default {
|
||
constructor(start, end) {
|
||
super();
|
||
this.start = start;
|
||
this.end = end;
|
||
this.thickness = 2;
|
||
// Does this really have a meaning for lines?
|
||
this.size.set(5, 5);
|
||
}
|
||
set start(pos) {
|
||
this.position = pos;
|
||
}
|
||
get start() {
|
||
return this.position;
|
||
}
|
||
set end(pos) {
|
||
this._end = pos;
|
||
}
|
||
get end() {
|
||
return this._end;
|
||
}
|
||
}
|
||
exports.default = Line;
|
||
|
||
},{"../Graphic":41}],44:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Point_1 = require("./Point");
|
||
/**
|
||
* - Position X
|
||
- Velocity (speed and direction) X
|
||
- Color X
|
||
- Lifetime
|
||
- Age can be handled as lifetime
|
||
- Shape X
|
||
- Size X
|
||
- Transparency X
|
||
*/
|
||
class Particle extends Point_1.default {
|
||
constructor(position, size, mass) {
|
||
// Are we making this a circle?
|
||
super(position);
|
||
this.inUse = false;
|
||
this.mass = mass;
|
||
}
|
||
setParticleActive(lifetime, position) {
|
||
this.age = lifetime;
|
||
this.inUse = true;
|
||
this.visible = true;
|
||
this.position = position;
|
||
}
|
||
decrementAge(decay) {
|
||
this.age -= decay;
|
||
}
|
||
setParticleInactive() {
|
||
this.inUse = false;
|
||
this.visible = false;
|
||
}
|
||
set velY(y) {
|
||
this.vel.y = y;
|
||
}
|
||
get velY() {
|
||
return this.vel.y;
|
||
}
|
||
}
|
||
exports.default = Particle;
|
||
|
||
},{"./Point":45}],45:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Graphic_1 = require("../Graphic");
|
||
/** A basic point to be drawn on the screen. */
|
||
class Point extends Graphic_1.default {
|
||
constructor(position) {
|
||
// Are we making this a circle?
|
||
super();
|
||
this.position = position;
|
||
this.size.set(5, 5);
|
||
}
|
||
}
|
||
exports.default = Point;
|
||
|
||
},{"../Graphic":41}],46:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Graphic_1 = require("../Graphic");
|
||
const Color_1 = require("../../Utils/Color");
|
||
/** A basic rectangle to be drawn on the screen. */
|
||
class Rect extends Graphic_1.default {
|
||
constructor(position, size) {
|
||
super();
|
||
this.position = position;
|
||
this.size = size;
|
||
this.borderColor = Color_1.default.TRANSPARENT;
|
||
this.borderWidth = 0;
|
||
this.fillWidth = null;
|
||
}
|
||
/**
|
||
* Sets the border color of this rectangle
|
||
* @param color The border color
|
||
*/
|
||
setBorderColor(color) {
|
||
this.borderColor = color;
|
||
}
|
||
// @deprecated
|
||
getBorderColor() {
|
||
return this.borderColor;
|
||
}
|
||
/**
|
||
* Sets the border width of this rectangle
|
||
* @param width The width of the rectangle in pixels
|
||
*/
|
||
setBorderWidth(width) {
|
||
this.borderWidth = width;
|
||
}
|
||
getBorderWidth() {
|
||
return this.borderWidth;
|
||
}
|
||
}
|
||
exports.default = Rect;
|
||
|
||
},{"../../Utils/Color":99,"../Graphic":41}],47:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Sprite_1 = require("./Sprite");
|
||
const AnimationManager_1 = require("../../Rendering/Animations/AnimationManager");
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
/** An sprite with specified animation frames. */
|
||
class AnimatedSprite extends Sprite_1.default {
|
||
constructor(spritesheet) {
|
||
super(spritesheet.name);
|
||
this.numCols = spritesheet.columns;
|
||
this.numRows = spritesheet.rows;
|
||
// Set the size of the sprite to the sprite size specified by the spritesheet
|
||
this.size.set(spritesheet.spriteWidth, spritesheet.spriteHeight);
|
||
this.animation = new AnimationManager_1.default(this);
|
||
// Add the animations to the animated sprite
|
||
for (let animation of spritesheet.animations) {
|
||
this.animation.add(animation.name, animation);
|
||
}
|
||
}
|
||
get cols() {
|
||
return this.numCols;
|
||
}
|
||
get rows() {
|
||
return this.numRows;
|
||
}
|
||
/**
|
||
* Gets the image offset for the current index of animation
|
||
* @param index The index we're at in the animation
|
||
* @returns A Vec2 containing the image offset
|
||
*/
|
||
getAnimationOffset(index) {
|
||
return new Vec2_1.default((index % this.numCols) * this.size.x, Math.floor(index / this.numCols) * this.size.y);
|
||
}
|
||
}
|
||
exports.default = AnimatedSprite;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../Rendering/Animations/AnimationManager":66,"./Sprite":48}],48:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const CanvasNode_1 = require("../CanvasNode");
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
/**
|
||
* The representation of a sprite - an in-game image
|
||
*/
|
||
class Sprite extends CanvasNode_1.default {
|
||
constructor(imageId) {
|
||
super();
|
||
this.imageId = imageId;
|
||
let image = ResourceManager_1.default.getInstance().getImage(this.imageId);
|
||
this.size = new Vec2_1.default(image.width, image.height);
|
||
this.imageOffset = Vec2_1.default.ZERO;
|
||
this.invertX = false;
|
||
this.invertY = false;
|
||
}
|
||
/**
|
||
* Sets the offset of the sprite from (0, 0) in the image's coordinates
|
||
* @param offset The offset of the sprite from (0, 0) in image coordinates
|
||
*/
|
||
setImageOffset(offset) {
|
||
this.imageOffset = offset;
|
||
}
|
||
}
|
||
exports.default = Sprite;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../ResourceManager/ResourceManager":83,"../CanvasNode":39}],49:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const CanvasNode_1 = require("./CanvasNode");
|
||
/**
|
||
* The representation of a tilemap - this can consist of a combination of tilesets in one layer
|
||
*/
|
||
class Tilemap extends CanvasNode_1.default {
|
||
// TODO: Make this no longer be specific to Tiled
|
||
constructor(tilemapData, layer, tilesets, scale) {
|
||
super();
|
||
this.tilesets = tilesets;
|
||
this.tileSize = new Vec2_1.default(0, 0);
|
||
this.name = layer.name;
|
||
let tilecount = 0;
|
||
for (let tileset of tilesets) {
|
||
tilecount += tileset.getTileCount() + 1;
|
||
}
|
||
this.collisionMap = new Array(tilecount);
|
||
for (let i = 0; i < this.collisionMap.length; i++) {
|
||
this.collisionMap[i] = false;
|
||
}
|
||
// Defer parsing of the data to child classes - this allows for isometric vs. orthographic tilemaps and handling of Tiled data or other data
|
||
this.parseTilemapData(tilemapData, layer);
|
||
this.scale.set(scale.x, scale.y);
|
||
}
|
||
/**
|
||
* Returns an array of the tilesets associated with this tilemap
|
||
* @returns An array of all of the tilesets assocaited with this tilemap.
|
||
*/
|
||
getTilesets() {
|
||
return this.tilesets;
|
||
}
|
||
/**
|
||
* Returns the size of tiles in this tilemap as they appear in the game world after scaling
|
||
* @returns A vector containing the size of tiles in this tilemap as they appear in the game world after scaling.
|
||
*/
|
||
getTileSize() {
|
||
return this.tileSize.scaled(this.scale.x, this.scale.y);
|
||
}
|
||
/**
|
||
* Gets the tile size taking zoom into account
|
||
* @returns The tile size with zoom
|
||
*/
|
||
getTileSizeWithZoom() {
|
||
let zoom = this.scene.getViewScale();
|
||
return this.getTileSize().scale(zoom);
|
||
}
|
||
/**
|
||
* Adds this tilemap to the physics system
|
||
*/
|
||
addPhysics() {
|
||
this.hasPhysics = true;
|
||
this.active = true;
|
||
this.group = -1;
|
||
this.scene.getPhysicsManager().registerTilemap(this);
|
||
}
|
||
}
|
||
exports.default = Tilemap;
|
||
|
||
},{"../DataTypes/Vec2":24,"./CanvasNode":39}],50:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Tilemap_1 = require("../Tilemap");
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const Debug_1 = require("../../Debug/Debug");
|
||
const Color_1 = require("../../Utils/Color");
|
||
/**
|
||
* The representation of an orthogonal tilemap - i.e. a top down or platformer tilemap
|
||
*/
|
||
class OrthogonalTilemap extends Tilemap_1.default {
|
||
// @override
|
||
parseTilemapData(tilemapData, layer) {
|
||
// The size of the tilemap in local space
|
||
this.numCols = tilemapData.width;
|
||
this.numRows = tilemapData.height;
|
||
// The size of tiles
|
||
this.tileSize.set(tilemapData.tilewidth, tilemapData.tileheight);
|
||
// The size of the tilemap on the canvas
|
||
this.size.set(this.numCols * this.tileSize.x, this.numRows * this.tileSize.y);
|
||
this.position.copy(this.size.scaled(0.5));
|
||
this.data = layer.data;
|
||
this.visible = layer.visible;
|
||
// Whether the tilemap is collidable or not
|
||
this.isCollidable = false;
|
||
if (layer.properties) {
|
||
for (let item of layer.properties) {
|
||
if (item.name === "Collidable") {
|
||
this.isCollidable = item.value;
|
||
// Set all tiles besides "empty: 0" to be collidable
|
||
for (let i = 1; i < this.collisionMap.length; i++) {
|
||
this.collisionMap[i] = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Gets the dimensions of the tilemap
|
||
* @returns A Vec2 containing the number of columns and the number of rows in the tilemap.
|
||
*/
|
||
getDimensions() {
|
||
return new Vec2_1.default(this.numCols, this.numRows);
|
||
}
|
||
/**
|
||
* Gets the data value of the tile at the specified world position
|
||
* @param worldCoords The coordinates in world space
|
||
* @returns The data value of the tile
|
||
*/
|
||
getTileAtWorldPosition(worldCoords) {
|
||
let localCoords = this.getColRowAt(worldCoords);
|
||
return this.getTileAtRowCol(localCoords);
|
||
}
|
||
/**
|
||
* Get the tile at the specified row and column
|
||
* @param rowCol The coordinates in tilemap space
|
||
* @returns The data value of the tile
|
||
*/
|
||
getTileAtRowCol(rowCol) {
|
||
if (rowCol.x < 0 || rowCol.x >= this.numCols || rowCol.y < 0 || rowCol.y >= this.numRows) {
|
||
return -1;
|
||
}
|
||
return this.data[rowCol.y * this.numCols + rowCol.x];
|
||
}
|
||
/**
|
||
* Gets the world position of the tile at the specified index
|
||
* @param index The index of the tile
|
||
* @returns A Vec2 containing the world position of the tile
|
||
*/
|
||
getTileWorldPosition(index) {
|
||
// Get the local position
|
||
let col = index % this.numCols;
|
||
let row = Math.floor(index / this.numCols);
|
||
// Get the world position
|
||
let x = col * this.tileSize.x * this.scale.x;
|
||
let y = row * this.tileSize.y * this.scale.y;
|
||
return new Vec2_1.default(x, y);
|
||
}
|
||
/**
|
||
* Gets the data value of the tile at the specified index
|
||
* @param index The index of the tile
|
||
* @returns The data value of the tile
|
||
*/
|
||
getTile(index) {
|
||
return this.data[index];
|
||
}
|
||
// @override
|
||
setTile(index, type) {
|
||
this.data[index] = type;
|
||
}
|
||
/**
|
||
* Sets the tile at the specified row and column
|
||
* @param rowCol The position of the tile in tilemap space
|
||
* @param type The new data value of the tile
|
||
*/
|
||
setTileAtRowCol(rowCol, type) {
|
||
let index = rowCol.y * this.numCols + rowCol.x;
|
||
this.setTile(index, type);
|
||
}
|
||
/**
|
||
* Returns true if the tile at the specified row and column of the tilemap is collidable
|
||
* @param indexOrCol The index of the tile or the column it is in
|
||
* @param row The row the tile is in
|
||
* @returns A flag representing whether or not the tile is collidable.
|
||
*/
|
||
isTileCollidable(indexOrCol, row) {
|
||
// The value of the tile
|
||
let tile = 0;
|
||
if (row) {
|
||
// We have a column and a row
|
||
tile = this.getTileAtRowCol(new Vec2_1.default(indexOrCol, row));
|
||
if (tile < 0) {
|
||
return false;
|
||
}
|
||
}
|
||
else {
|
||
if (indexOrCol < 0 || indexOrCol >= this.data.length) {
|
||
// Tiles that don't exist aren't collidable
|
||
return false;
|
||
}
|
||
// We have an index
|
||
tile = this.getTile(indexOrCol);
|
||
}
|
||
return this.collisionMap[tile];
|
||
}
|
||
/**
|
||
* Takes in world coordinates and returns the row and column of the tile at that position
|
||
* @param worldCoords The coordinates of the potential tile in world space
|
||
* @returns A Vec2 containing the coordinates of the potential tile in tilemap space
|
||
*/
|
||
getColRowAt(worldCoords) {
|
||
let col = Math.floor(worldCoords.x / this.tileSize.x / this.scale.x);
|
||
let row = Math.floor(worldCoords.y / this.tileSize.y / this.scale.y);
|
||
return new Vec2_1.default(col, row);
|
||
}
|
||
// @override
|
||
update(deltaT) { }
|
||
// @override
|
||
debugRender() {
|
||
// Half of the tile size
|
||
let zoomedHalfTileSize = this.getTileSizeWithZoom().scaled(0.5);
|
||
let halfTileSize = this.getTileSize().scaled(0.5);
|
||
// The center of the top left tile
|
||
let topLeft = this.position.clone().sub(this.size.scaled(0.5));
|
||
// A vec to store the center
|
||
let center = Vec2_1.default.ZERO;
|
||
for (let col = 0; col < this.numCols; col++) {
|
||
// Calculate the x-position
|
||
center.x = topLeft.x + col * 2 * halfTileSize.x + halfTileSize.x;
|
||
for (let row = 0; row < this.numRows; row++) {
|
||
if (this.isCollidable && this.isTileCollidable(col, row)) {
|
||
// Calculate the y-position
|
||
center.y = topLeft.y + row * 2 * halfTileSize.y + halfTileSize.y;
|
||
// Draw a box for this tile
|
||
Debug_1.default.drawBox(this.inRelativeCoordinates(center), zoomedHalfTileSize, false, Color_1.default.BLUE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = OrthogonalTilemap;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../Debug/Debug":25,"../../Utils/Color":99,"../Tilemap":49}],51:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const CanvasNode_1 = require("./CanvasNode");
|
||
const Color_1 = require("../Utils/Color");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const Input_1 = require("../Input/Input");
|
||
/**
|
||
* The representation of a UIElement - the parent class of things like buttons
|
||
*/
|
||
class UIElement extends CanvasNode_1.default {
|
||
constructor(position) {
|
||
super();
|
||
this.position = position;
|
||
this.backgroundColor = new Color_1.default(0, 0, 0, 0);
|
||
this.borderColor = new Color_1.default(0, 0, 0, 0);
|
||
this.borderRadius = 5;
|
||
this.borderWidth = 1;
|
||
this.padding = Vec2_1.default.ZERO;
|
||
this.onClick = null;
|
||
this.onClickEventId = null;
|
||
this.onRelease = null;
|
||
this.onReleaseEventId = null;
|
||
this.onEnter = null;
|
||
this.onEnterEventId = null;
|
||
this.onLeave = null;
|
||
this.onLeaveEventId = null;
|
||
this.isClicked = false;
|
||
this.isEntered = false;
|
||
}
|
||
// @deprecated
|
||
setBackgroundColor(color) {
|
||
this.backgroundColor = color;
|
||
}
|
||
// @deprecated
|
||
setPadding(padding) {
|
||
this.padding.copy(padding);
|
||
}
|
||
update(deltaT) {
|
||
super.update(deltaT);
|
||
// See of this object was just clicked
|
||
if (Input_1.default.isMouseJustPressed()) {
|
||
let clickPos = Input_1.default.getMousePressPosition();
|
||
if (this.contains(clickPos.x, clickPos.y) && this.visible && !this.layer.isHidden()) {
|
||
this.isClicked = true;
|
||
if (this.onClick !== null) {
|
||
this.onClick();
|
||
}
|
||
if (this.onClickEventId !== null) {
|
||
let data = {};
|
||
this.emitter.fireEvent(this.onClickEventId, data);
|
||
}
|
||
}
|
||
}
|
||
// If the mouse wasn't just pressed, then we definitely weren't clicked
|
||
if (!Input_1.default.isMousePressed()) {
|
||
if (this.isClicked) {
|
||
this.isClicked = false;
|
||
}
|
||
}
|
||
// Check if the mouse is hovering over this element
|
||
let mousePos = Input_1.default.getMousePosition();
|
||
if (mousePos && this.contains(mousePos.x, mousePos.y)) {
|
||
this.isEntered = true;
|
||
if (this.onEnter !== null) {
|
||
this.onEnter();
|
||
}
|
||
if (this.onEnterEventId !== null) {
|
||
let data = {};
|
||
this.emitter.fireEvent(this.onEnterEventId, data);
|
||
}
|
||
}
|
||
else if (this.isEntered) {
|
||
this.isEntered = false;
|
||
if (this.onLeave !== null) {
|
||
this.onLeave();
|
||
}
|
||
if (this.onLeaveEventId !== null) {
|
||
let data = {};
|
||
this.emitter.fireEvent(this.onLeaveEventId, data);
|
||
}
|
||
}
|
||
else if (this.isClicked) {
|
||
// If mouse is dragged off of element while down, it is not clicked anymore
|
||
this.isClicked = false;
|
||
}
|
||
}
|
||
/**
|
||
* Overridable method for calculating background color - useful for elements that want to be colored on different after certain events
|
||
* @returns The background color of the UIElement
|
||
*/
|
||
calculateBackgroundColor() {
|
||
return this.backgroundColor;
|
||
}
|
||
/**
|
||
* Overridable method for calculating border color - useful for elements that want to be colored on different after certain events
|
||
* @returns The border color of the UIElement
|
||
*/
|
||
calculateBorderColor() {
|
||
return this.borderColor;
|
||
}
|
||
}
|
||
exports.default = UIElement;
|
||
|
||
},{"../DataTypes/Vec2":24,"../Input/Input":32,"../Utils/Color":99,"./CanvasNode":39}],52:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Label_1 = require("./Label");
|
||
const Color_1 = require("../../Utils/Color");
|
||
/** A clickable button UIElement */
|
||
class Button extends Label_1.default {
|
||
constructor(position, text) {
|
||
super(position, text);
|
||
this.backgroundColor = new Color_1.default(150, 75, 203);
|
||
this.borderColor = new Color_1.default(41, 46, 30);
|
||
this.textColor = new Color_1.default(255, 255, 255);
|
||
}
|
||
// @override
|
||
calculateBackgroundColor() {
|
||
// Change the background color if clicked or hovered
|
||
if (this.isEntered && !this.isClicked) {
|
||
return this.backgroundColor.lighten();
|
||
}
|
||
else if (this.isClicked) {
|
||
return this.backgroundColor.darken();
|
||
}
|
||
else {
|
||
return this.backgroundColor;
|
||
}
|
||
}
|
||
}
|
||
exports.default = Button;
|
||
|
||
},{"../../Utils/Color":99,"./Label":53}],53:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.HAlign = exports.VAlign = void 0;
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const Color_1 = require("../../Utils/Color");
|
||
const UIElement_1 = require("../UIElement");
|
||
/** A basic text-containing label */
|
||
class Label extends UIElement_1.default {
|
||
constructor(position, text) {
|
||
super(position);
|
||
this.text = text;
|
||
this.textColor = new Color_1.default(0, 0, 0, 1);
|
||
this.font = "Arial";
|
||
this.fontSize = 30;
|
||
this.hAlign = "center";
|
||
this.vAlign = "center";
|
||
this.sizeAssigned = false;
|
||
}
|
||
// @deprecated
|
||
setText(text) {
|
||
this.text = text;
|
||
}
|
||
// @deprecated
|
||
setTextColor(color) {
|
||
this.textColor = color;
|
||
}
|
||
/**
|
||
* Gets a string containg the font details for rendering
|
||
* @returns A string containing the font details
|
||
*/
|
||
getFontString() {
|
||
return this.fontSize + "px " + this.font;
|
||
}
|
||
/**
|
||
* Overridable method for calculating text color - useful for elements that want to be colored on different after certain events
|
||
* @returns a string containg the text color
|
||
*/
|
||
calculateTextColor() {
|
||
return this.textColor.toStringRGBA();
|
||
}
|
||
/**
|
||
* Uses the canvas to calculate the width of the text
|
||
* @param ctx The rendering context
|
||
* @returns A number representing the rendered text width
|
||
*/
|
||
calculateTextWidth(ctx) {
|
||
ctx.font = this.fontSize + "px " + this.font;
|
||
return ctx.measureText(this.text).width;
|
||
}
|
||
setHAlign(align) {
|
||
this.hAlign = align;
|
||
}
|
||
setVAlign(align) {
|
||
this.vAlign = align;
|
||
}
|
||
/**
|
||
* Calculate the offset of the text - this is used for rendering text with different alignments
|
||
* @param ctx The rendering context
|
||
* @returns The offset of the text in a Vec2
|
||
*/
|
||
calculateTextOffset(ctx) {
|
||
let textWidth = this.calculateTextWidth(ctx);
|
||
let offset = new Vec2_1.default(0, 0);
|
||
let hDiff = this.size.x - textWidth;
|
||
if (this.hAlign === HAlign.CENTER) {
|
||
offset.x = hDiff / 2;
|
||
}
|
||
else if (this.hAlign === HAlign.RIGHT) {
|
||
offset.x = hDiff;
|
||
}
|
||
if (this.vAlign === VAlign.TOP) {
|
||
ctx.textBaseline = "top";
|
||
offset.y = 0;
|
||
}
|
||
else if (this.vAlign === VAlign.BOTTOM) {
|
||
ctx.textBaseline = "bottom";
|
||
offset.y = this.size.y;
|
||
}
|
||
else {
|
||
ctx.textBaseline = "middle";
|
||
offset.y = this.size.y / 2;
|
||
}
|
||
return offset;
|
||
}
|
||
sizeChanged() {
|
||
super.sizeChanged();
|
||
this.sizeAssigned = true;
|
||
}
|
||
/**
|
||
* Automatically sizes the element to the text within it
|
||
* @param ctx The rendering context
|
||
*/
|
||
autoSize(ctx) {
|
||
let width = this.calculateTextWidth(ctx);
|
||
let height = this.fontSize;
|
||
this.size.set(width + this.padding.x * 2, height + this.padding.y * 2);
|
||
this.sizeAssigned = true;
|
||
}
|
||
/**
|
||
* Initially assigns a size to the UIElement if none is provided
|
||
* @param ctx The rendering context
|
||
*/
|
||
handleInitialSizing(ctx) {
|
||
if (!this.sizeAssigned) {
|
||
this.autoSize(ctx);
|
||
}
|
||
}
|
||
/** On the next render, size this element to it's current text using its current font size */
|
||
sizeToText() {
|
||
this.sizeAssigned = false;
|
||
}
|
||
}
|
||
exports.default = Label;
|
||
var VAlign;
|
||
(function (VAlign) {
|
||
VAlign["TOP"] = "top";
|
||
VAlign["CENTER"] = "center";
|
||
VAlign["BOTTOM"] = "bottom";
|
||
})(VAlign = exports.VAlign || (exports.VAlign = {}));
|
||
var HAlign;
|
||
(function (HAlign) {
|
||
HAlign["LEFT"] = "left";
|
||
HAlign["CENTER"] = "center";
|
||
HAlign["RIGHT"] = "right";
|
||
})(HAlign = exports.HAlign || (exports.HAlign = {}));
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../Utils/Color":99,"../UIElement":51}],54:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const Input_1 = require("../../Input/Input");
|
||
const Color_1 = require("../../Utils/Color");
|
||
const MathUtils_1 = require("../../Utils/MathUtils");
|
||
const UIElement_1 = require("../UIElement");
|
||
/** A slider UIElement */
|
||
class Slider extends UIElement_1.default {
|
||
constructor(position, initValue) {
|
||
super(position);
|
||
this.value = initValue;
|
||
this.nibColor = Color_1.default.RED;
|
||
this.sliderColor = Color_1.default.BLACK;
|
||
this.backgroundColor = Color_1.default.TRANSPARENT;
|
||
this.borderColor = Color_1.default.TRANSPARENT;
|
||
this.nibSize = new Vec2_1.default(10, 20);
|
||
// Set a default size
|
||
this.size.set(200, 20);
|
||
}
|
||
/**
|
||
* Retrieves the value of the slider
|
||
* @returns The value of the slider
|
||
*/
|
||
getValue() {
|
||
return this.value;
|
||
}
|
||
/** A method called in response to the value changing */
|
||
valueChanged() {
|
||
if (this.onValueChange) {
|
||
this.onValueChange(this.value);
|
||
}
|
||
if (this.onValueChangeEventId) {
|
||
this.emitter.fireEvent(this.onValueChangeEventId, { target: this, value: this.value });
|
||
}
|
||
}
|
||
update(deltaT) {
|
||
super.update(deltaT);
|
||
if (this.isClicked) {
|
||
let val = MathUtils_1.default.invLerp(this.position.x - this.size.x / 2, this.position.x + this.size.x / 2, Input_1.default.getMousePosition().x);
|
||
this.value = MathUtils_1.default.clamp01(val);
|
||
this.valueChanged();
|
||
}
|
||
}
|
||
}
|
||
exports.default = Slider;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../Input/Input":32,"../../Utils/Color":99,"../../Utils/MathUtils":102,"../UIElement":51}],55:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Color_1 = require("../../Utils/Color");
|
||
const Label_1 = require("./Label");
|
||
const Input_1 = require("../../Input/Input");
|
||
/** A text input UIElement */
|
||
class TextInput extends Label_1.default {
|
||
constructor(position) {
|
||
super(position, "");
|
||
this.focused = false;
|
||
this.cursorCounter = 0;
|
||
// Give a default size to the x only
|
||
this.size.set(200, this.fontSize);
|
||
this.hAlign = "left";
|
||
this.borderColor = Color_1.default.BLACK;
|
||
this.backgroundColor = Color_1.default.WHITE;
|
||
}
|
||
update(deltaT) {
|
||
super.update(deltaT);
|
||
if (Input_1.default.isMouseJustPressed()) {
|
||
let clickPos = Input_1.default.getMousePressPosition();
|
||
if (this.contains(clickPos.x, clickPos.y)) {
|
||
this.focused = true;
|
||
this.cursorCounter = 30;
|
||
}
|
||
else {
|
||
this.focused = false;
|
||
}
|
||
}
|
||
if (this.focused) {
|
||
let keys = Input_1.default.getKeysJustPressed();
|
||
let nums = "1234567890";
|
||
let specialChars = "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?";
|
||
let letters = "qwertyuiopasdfghjklzxcvbnm";
|
||
let mask = nums + specialChars + letters;
|
||
keys = keys.filter(key => mask.includes(key));
|
||
let shiftPressed = Input_1.default.isKeyPressed("shift");
|
||
let backspacePressed = Input_1.default.isKeyJustPressed("backspace");
|
||
let spacePressed = Input_1.default.isKeyJustPressed("space");
|
||
if (backspacePressed) {
|
||
this.text = this.text.substring(0, this.text.length - 1);
|
||
}
|
||
else if (spacePressed) {
|
||
this.text += " ";
|
||
}
|
||
else if (keys.length > 0) {
|
||
if (shiftPressed) {
|
||
this.text += keys[0].toUpperCase();
|
||
}
|
||
else {
|
||
this.text += keys[0];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = TextInput;
|
||
|
||
},{"../../Input/Input":32,"../../Utils/Color":99,"./Label":53}],56:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.UIElementType = void 0;
|
||
var UIElementType;
|
||
(function (UIElementType) {
|
||
UIElementType["BUTTON"] = "BUTTON";
|
||
UIElementType["LABEL"] = "LABEL";
|
||
UIElementType["SLIDER"] = "SLIDER";
|
||
UIElementType["TEXT_INPUT"] = "TEXTINPUT";
|
||
})(UIElementType = exports.UIElementType || (exports.UIElementType = {}));
|
||
|
||
},{}],57:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../DataTypes/Map");
|
||
/**
|
||
* The manager class for navigation.
|
||
* Handles all navigable entities, such and allows them to be accessed by outside systems by requesting a path
|
||
* from one position to another.
|
||
*/
|
||
class NavigationManager {
|
||
constructor() {
|
||
this.navigableEntities = new Map_1.default();
|
||
}
|
||
/**
|
||
* Adds a navigable entity to the NavigationManager
|
||
* @param navName The name of the navigable entitry
|
||
* @param nav The actual Navigable instance
|
||
*/
|
||
addNavigableEntity(navName, nav) {
|
||
this.navigableEntities.add(navName, nav);
|
||
}
|
||
/**
|
||
* Gets a path frome one point to another using a specified Navigable object
|
||
* @param navName The name of the registered Navigable object
|
||
* @param fromPosition The starting position of navigation
|
||
* @param toPosition The ending position of Navigation
|
||
* @param direct If true, go direct from fromPosition to toPosition, don't use NavMesh
|
||
* @returns A NavigationPath containing the route to take over the Navigable entity to get between the provided positions.
|
||
*/
|
||
getPath(navName, fromPosition, toPosition, direct) {
|
||
let nav = this.navigableEntities.get(navName);
|
||
return nav.getNavigationPath(fromPosition.clone(), toPosition.clone(), direct);
|
||
}
|
||
}
|
||
exports.default = NavigationManager;
|
||
|
||
},{"../DataTypes/Map":10}],58:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
/**
|
||
* A path that AIs can follow. Uses finishMove() in Physical to determine progress on the route
|
||
*/
|
||
class NavigationPath {
|
||
/**
|
||
* Constructs a new NavigationPath
|
||
* @param path The path of nodes to take
|
||
*/
|
||
constructor(path) {
|
||
this.path = path;
|
||
this.currentMoveDirection = Vec2_1.default.ZERO;
|
||
this.distanceThreshold = 4;
|
||
}
|
||
/**
|
||
* Returns the status of navigation along this NavigationPath
|
||
* @returns True if the node has reached the end of the path, false otherwise
|
||
*/
|
||
isDone() {
|
||
return this.path.isEmpty();
|
||
}
|
||
/**
|
||
* Gets the movement direction in the current position along the path
|
||
* @param node The node to move along the path
|
||
* @returns The movement direction as a Vec2
|
||
*/
|
||
getMoveDirection(node) {
|
||
// Return direction to next point in the nav
|
||
return node.position.dirTo(this.path.peek());
|
||
}
|
||
/**
|
||
* Updates this NavigationPath to the current state of the GameNode
|
||
* @param node The node moving along the path
|
||
*/
|
||
handlePathProgress(node) {
|
||
if (node.position.distanceSqTo(this.path.peek()) < this.distanceThreshold * this.distanceThreshold) {
|
||
// We've reached our node, move on to the next destination
|
||
this.path.pop();
|
||
}
|
||
}
|
||
toString() {
|
||
return this.path.toString();
|
||
}
|
||
}
|
||
exports.default = NavigationPath;
|
||
|
||
},{"../DataTypes/Vec2":24}],59:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Stack_1 = require("../DataTypes/Stack");
|
||
const GraphUtils_1 = require("../Utils/GraphUtils");
|
||
const NavigationPath_1 = require("./NavigationPath");
|
||
/**
|
||
* An implementation of a Navmesh. Navmeshes are graphs in the game world along which nodes can move.
|
||
*/
|
||
class Navmesh {
|
||
/**
|
||
* Creates a new Navmesh from the points in the speecified graph
|
||
* @param graph The graph to construct a navmesh from
|
||
*/
|
||
constructor(graph) {
|
||
this.graph = graph;
|
||
}
|
||
// @implemented
|
||
getNavigationPath(fromPosition, toPosition, direct) {
|
||
let start = this.getClosestNode(fromPosition);
|
||
let end = this.getClosestNode(toPosition);
|
||
let pathStack = new Stack_1.default(this.graph.numVertices);
|
||
// Push the final position and the final position in the graph
|
||
pathStack.push(toPosition.clone());
|
||
if (direct) {
|
||
return new NavigationPath_1.default(pathStack);
|
||
}
|
||
pathStack.push(this.graph.positions[end]);
|
||
let parent = GraphUtils_1.default.djikstra(this.graph, start);
|
||
// Add all parents along the path
|
||
let i = end;
|
||
while (parent[i] !== -1) {
|
||
pathStack.push(this.graph.positions[parent[i]]);
|
||
i = parent[i];
|
||
}
|
||
return new NavigationPath_1.default(pathStack);
|
||
}
|
||
/**
|
||
* Gets the closest node in this Navmesh to the specified position
|
||
* @param position The position to query
|
||
* @returns The index of the closest node in the Navmesh to the position
|
||
*/
|
||
getClosestNode(position) {
|
||
let n = this.graph.numVertices;
|
||
let i = 1;
|
||
let index = 0;
|
||
let dist = position.distanceSqTo(this.graph.positions[0]);
|
||
while (i < n) {
|
||
let d = position.distanceSqTo(this.graph.positions[i]);
|
||
if (d < dist) {
|
||
dist = d;
|
||
index = i;
|
||
}
|
||
i++;
|
||
}
|
||
return index;
|
||
}
|
||
}
|
||
exports.default = Navmesh;
|
||
|
||
},{"../DataTypes/Stack":19,"../Utils/GraphUtils":101,"./NavigationPath":58}],60:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const PhysicsManager_1 = require("./PhysicsManager");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const AABB_1 = require("../DataTypes/Shapes/AABB");
|
||
const OrthogonalTilemap_1 = require("../Nodes/Tilemaps/OrthogonalTilemap");
|
||
const AreaCollision_1 = require("../DataTypes/Physics/AreaCollision");
|
||
/**
|
||
* ALGORITHM:
|
||
* In an effort to keep things simple and working effectively, each dynamic node will resolve its
|
||
* collisions considering the rest of the world as static.
|
||
*
|
||
* Collision detecting will happen first. This can be considered a broad phase, but it is not especially
|
||
* efficient, as it does not need to be for this game engine. Every dynamic node is checked against every
|
||
* other node for collision area. If collision area is non-zero (meaning the current node sweeps into another),
|
||
* it is added to a list of hits.
|
||
*
|
||
* INITIALIZATION:
|
||
* - Physics constants are reset
|
||
* - Swept shapes are recalculated. If a node isn't moving, it is skipped.
|
||
*
|
||
* COLLISION DETECTION:
|
||
* - For a node, collision area will be calculated using the swept AABB of the node against every other AABB in a static state
|
||
* - These collisions will be sorted by area in descending order
|
||
*
|
||
* COLLISION RESOLUTION:
|
||
* - For each hit, time of collision is calculated using a swept line through the AABB of the static node expanded
|
||
* with minkowski sums (discretely, but the concept is there)
|
||
* - The collision is resolved based on the near time of the collision (from method of separated axes)
|
||
* - X is resolved by near x, Y by near y.
|
||
* - There is some fudging to allow for sliding along walls of separate colliders. Sorting by area also helps with this.
|
||
* - Corner to corner collisions are resolve to favor x-movement. This is in consideration of platformers, to give
|
||
* the player some help with jumps
|
||
*
|
||
* Pros:
|
||
* - Everything happens with a consistent time. There is a distinct before and after for each resolution.
|
||
* - No back-tracking needs to be done. Once we resolve a node, it is definitively resolved.
|
||
*
|
||
* Cons:
|
||
* - Nodes that are processed early have movement priority over other nodes. This can lead to some undesirable interactions.
|
||
*/
|
||
class BasicPhysicsManager extends PhysicsManager_1.default {
|
||
constructor(options) {
|
||
super();
|
||
this.staticNodes = new Array();
|
||
this.dynamicNodes = new Array();
|
||
this.tilemaps = new Array();
|
||
this.collisionMasks = new Array(32);
|
||
// Parse options
|
||
this.parseOptions(options);
|
||
}
|
||
/**
|
||
* Parses the options for constructing the physics manager
|
||
* @param options A record of options
|
||
*/
|
||
parseOptions(options) {
|
||
if (options.groupNames !== undefined && options.collisions !== undefined) {
|
||
for (let i = 0; i < options.groupNames.length; i++) {
|
||
let group = options.groupNames[i];
|
||
// Register the group name and number
|
||
this.groupNames[i] = group;
|
||
this.groupMap.set(group, 1 << i);
|
||
let collisionMask = 0;
|
||
for (let j = 0; j < options.collisions[i].length; j++) {
|
||
if (options.collisions[i][j]) {
|
||
collisionMask |= 1 << j;
|
||
}
|
||
}
|
||
this.collisionMasks[i] = collisionMask;
|
||
}
|
||
}
|
||
}
|
||
// @override
|
||
registerObject(node) {
|
||
if (node.isStatic) {
|
||
// Static and not collidable
|
||
this.staticNodes.push(node);
|
||
}
|
||
else {
|
||
// Dynamic and not collidable
|
||
this.dynamicNodes.push(node);
|
||
}
|
||
}
|
||
// @override
|
||
deregisterObject(node) {
|
||
if (node.isStatic) {
|
||
// Remove the node from the static list
|
||
const index = this.staticNodes.indexOf(node);
|
||
this.staticNodes.splice(index, 1);
|
||
}
|
||
else {
|
||
// Remove the node from the dynamic list
|
||
const index = this.dynamicNodes.indexOf(node);
|
||
this.dynamicNodes.splice(index, 1);
|
||
}
|
||
}
|
||
// @override
|
||
registerTilemap(tilemap) {
|
||
this.tilemaps.push(tilemap);
|
||
}
|
||
// @override
|
||
deregisterTilemap(tilemap) {
|
||
const index = this.tilemaps.indexOf(tilemap);
|
||
this.tilemaps.splice(index, 1);
|
||
}
|
||
// @override
|
||
update(deltaT) {
|
||
for (let node of this.dynamicNodes) {
|
||
/*---------- INITIALIZATION PHASE ----------*/
|
||
// Clear frame dependent boolean values for each node
|
||
node.onGround = false;
|
||
node.onCeiling = false;
|
||
node.onWall = false;
|
||
node.collidedWithTilemap = false;
|
||
node.isColliding = false;
|
||
// If this node is not active, don't process it
|
||
if (!node.active) {
|
||
continue;
|
||
}
|
||
// Update the swept shapes of each node
|
||
if (node.moving) {
|
||
// If moving, reflect that in the swept shape
|
||
node.sweptRect.sweep(node._velocity, node.collisionShape.center, node.collisionShape.halfSize);
|
||
}
|
||
else {
|
||
// If our node isn't moving, don't bother to check it (other nodes will detect if they run into it)
|
||
node._velocity.zero();
|
||
continue;
|
||
}
|
||
/*---------- DETECTION PHASE ----------*/
|
||
// Gather a set of overlaps
|
||
let overlaps = new Array();
|
||
let groupIndex = node.group === -1 ? -1 : Math.log2(node.group);
|
||
// First, check this node against every static node (order doesn't actually matter here, since we sort anyways)
|
||
for (let other of this.staticNodes) {
|
||
// Ignore inactive nodes
|
||
if (!other.active)
|
||
continue;
|
||
let collider = other.collisionShape.getBoundingRect();
|
||
let area = node.sweptRect.overlapArea(collider);
|
||
if (area > 0) {
|
||
// We had a collision
|
||
overlaps.push(new AreaCollision_1.default(area, collider, other, "GameNode", null));
|
||
}
|
||
}
|
||
// Then, check it against every dynamic node
|
||
for (let other of this.dynamicNodes) {
|
||
// Ignore ourselves
|
||
if (node === other)
|
||
continue;
|
||
// Ignore inactive nodes
|
||
if (!other.active)
|
||
continue;
|
||
let collider = other.collisionShape.getBoundingRect();
|
||
let area = node.sweptRect.overlapArea(collider);
|
||
if (area > 0) {
|
||
// We had a collision
|
||
overlaps.push(new AreaCollision_1.default(area, collider, other, "GameNode", null));
|
||
}
|
||
}
|
||
// Lastly, gather a set of AABBs from the tilemap.
|
||
// This step involves the most extra work, so it is abstracted into a method
|
||
for (let tilemap of this.tilemaps) {
|
||
// Ignore inactive tilemaps
|
||
if (!tilemap.active)
|
||
continue;
|
||
if (tilemap instanceof OrthogonalTilemap_1.default) {
|
||
this.collideWithOrthogonalTilemap(node, tilemap, overlaps);
|
||
}
|
||
}
|
||
// Sort the overlaps by area
|
||
overlaps = overlaps.sort((a, b) => b.area - a.area);
|
||
// Keep track of hits to use later
|
||
let hits = [];
|
||
/*---------- RESOLUTION PHASE ----------*/
|
||
// For every overlap, determine if we need to collide with it and when
|
||
for (let overlap of overlaps) {
|
||
// Ignore nodes we don't interact with
|
||
if (groupIndex !== -1 && overlap.other.group !== -1 && ((this.collisionMasks[groupIndex] & overlap.other.group) === 0))
|
||
continue;
|
||
// Do a swept line test on the static AABB with this AABB size as padding (this is basically using a minkowski sum!)
|
||
// Start the sweep at the position of this node with a delta of _velocity
|
||
const point = node.collisionShape.center;
|
||
const delta = node._velocity;
|
||
const padding = node.collisionShape.halfSize;
|
||
const otherAABB = overlap.collider;
|
||
const hit = otherAABB.intersectSegment(node.collisionShape.center, node._velocity, node.collisionShape.halfSize);
|
||
overlap.hit = hit;
|
||
if (hit !== null) {
|
||
hits.push(hit);
|
||
// We got a hit, resolve with the time inside of the hit
|
||
let tnearx = hit.nearTimes.x;
|
||
let tneary = hit.nearTimes.y;
|
||
// Allow edge clipping (edge overlaps don't count, only area overlaps)
|
||
// Importantly don't allow both cases to be true. Then we clip through corners. Favor x to help players land jumps
|
||
if (tnearx < 1.0 && (point.y === otherAABB.top - padding.y || point.y === otherAABB.bottom + padding.y) && delta.x !== 0) {
|
||
tnearx = 1.0;
|
||
}
|
||
else if (tneary < 1.0 && (point.x === otherAABB.left - padding.x || point.x === otherAABB.right + padding.x) && delta.y !== 0) {
|
||
tneary = 1.0;
|
||
}
|
||
if (hit.nearTimes.x >= 0 && hit.nearTimes.x < 1) {
|
||
// Any tilemap objects that made it here are collidable
|
||
if (overlap.type === "Tilemap" || overlap.other.isCollidable) {
|
||
node._velocity.x = node._velocity.x * tnearx;
|
||
node.isColliding = true;
|
||
}
|
||
}
|
||
if (hit.nearTimes.y >= 0 && hit.nearTimes.y < 1) {
|
||
// Any tilemap objects that made it here are collidable
|
||
if (overlap.type === "Tilemap" || overlap.other.isCollidable) {
|
||
node._velocity.y = node._velocity.y * tneary;
|
||
node.isColliding = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/*---------- INFORMATION/TRIGGER PHASE ----------*/
|
||
// Check if we ended up on the ground, ceiling or wall
|
||
// Also check for triggers
|
||
for (let overlap of overlaps) {
|
||
// Check for a trigger. If we care about the trigger, react
|
||
if (overlap.other.isTrigger && (overlap.other.triggerMask & node.group) && node.group != -1) {
|
||
// Get the bit that this group is represented by
|
||
let index = Math.floor(Math.log2(node.group));
|
||
// Extract the triggerEnter event name
|
||
this.emitter.fireEvent(overlap.other.triggerEnters[index], {
|
||
node: node.id,
|
||
other: overlap.other.id
|
||
});
|
||
}
|
||
// Ignore collision sides for nodes we don't interact with
|
||
if (groupIndex !== -1 && overlap.other.group !== -1 && ((this.collisionMasks[groupIndex] & overlap.other.group) === 0))
|
||
continue;
|
||
// Only check for direction if the overlap was collidable
|
||
if (overlap.type === "Tilemap" || overlap.other.isCollidable) {
|
||
let collisionSide = overlap.collider.touchesAABBWithoutCorners(node.collisionShape.getBoundingRect());
|
||
if (collisionSide !== null) {
|
||
// If we touch, not including corner cases, check the collision normal
|
||
if (overlap.hit !== null) {
|
||
// If we hit a tilemap, keep track of it
|
||
if (overlap.type == "Tilemap") {
|
||
node.collidedWithTilemap = true;
|
||
}
|
||
if (collisionSide.y === -1) {
|
||
// Node is on top of overlap, so onGround
|
||
node.onGround = true;
|
||
}
|
||
else if (collisionSide.y === 1) {
|
||
// Node is on bottom of overlap, so onCeiling
|
||
node.onCeiling = true;
|
||
}
|
||
else {
|
||
// Node wasn't touching on y, so it is touching on x
|
||
node.onWall = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Resolve the collision with the node, and move it
|
||
node.finishMove();
|
||
}
|
||
}
|
||
/**
|
||
* Handles a collision between this node and an orthogonal tilemap
|
||
* @param node The node
|
||
* @param tilemap The tilemap the node may be colliding with
|
||
* @param overlaps The list of overlaps
|
||
*/
|
||
collideWithOrthogonalTilemap(node, tilemap, overlaps) {
|
||
// Get the min and max x and y coordinates of the moving node
|
||
let min = new Vec2_1.default(node.sweptRect.left, node.sweptRect.top);
|
||
let max = new Vec2_1.default(node.sweptRect.right, node.sweptRect.bottom);
|
||
// Convert the min/max x/y to the min and max row/col in the tilemap array
|
||
let minIndex = tilemap.getColRowAt(min);
|
||
let maxIndex = tilemap.getColRowAt(max);
|
||
let tileSize = tilemap.getTileSize();
|
||
// Loop over all possible tiles (which isn't many in the scope of the velocity per frame)
|
||
for (let col = minIndex.x; col <= maxIndex.x; col++) {
|
||
for (let row = minIndex.y; row <= maxIndex.y; row++) {
|
||
if (tilemap.isTileCollidable(col, row)) {
|
||
// Get the position of this tile
|
||
let tilePos = new Vec2_1.default(col * tileSize.x + tileSize.x / 2, row * tileSize.y + tileSize.y / 2);
|
||
// Create a new collider for this tile
|
||
let collider = new AABB_1.default(tilePos, tileSize.scaled(1 / 2));
|
||
// Calculate collision area between the node and the tile
|
||
let area = node.sweptRect.overlapArea(collider);
|
||
if (area > 0) {
|
||
// We had a collision
|
||
overlaps.push(new AreaCollision_1.default(area, collider, tilemap, "Tilemap", new Vec2_1.default(col, row)));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = BasicPhysicsManager;
|
||
|
||
},{"../DataTypes/Physics/AreaCollision":12,"../DataTypes/Shapes/AABB":16,"../DataTypes/Vec2":24,"../Nodes/Tilemaps/OrthogonalTilemap":50,"./PhysicsManager":61}],61:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Receiver_1 = require("../Events/Receiver");
|
||
const Emitter_1 = require("../Events/Emitter");
|
||
const Map_1 = require("../DataTypes/Map");
|
||
/**
|
||
* An abstract physics manager.
|
||
* This class exposes functions for subclasses to implement that should allow for a working physics system to be created.
|
||
*/
|
||
class PhysicsManager {
|
||
constructor() {
|
||
this.receiver = new Receiver_1.default();
|
||
this.emitter = new Emitter_1.default();
|
||
// The creation and implementation of layers is deferred to the subclass
|
||
this.groupMap = new Map_1.default();
|
||
this.groupNames = new Array();
|
||
}
|
||
destroy() {
|
||
this.receiver.destroy();
|
||
}
|
||
/**
|
||
* Sets the physics layer of the GameNode
|
||
* @param node The GameNode
|
||
* @param group The group that the GameNode should be on
|
||
*/
|
||
setGroup(node, group) {
|
||
node.group = this.groupMap.get(group);
|
||
}
|
||
/**
|
||
* Retrieves the layer number associated with the provided name
|
||
* @param layer The name of the layer
|
||
* @returns The layer number, or 0 if there is not a layer with that name registered
|
||
*/
|
||
getGroupNumber(group) {
|
||
if (this.groupMap.has(group)) {
|
||
return this.groupMap.get(group);
|
||
}
|
||
else {
|
||
return 0;
|
||
}
|
||
}
|
||
/**
|
||
* Gets all group names associated with the number provided
|
||
* @param groups A mask of groups
|
||
* @returns All groups contained in the mask
|
||
*/
|
||
getGroupNames(groups) {
|
||
if (groups === -1) {
|
||
return [PhysicsManager.DEFAULT_GROUP];
|
||
}
|
||
else {
|
||
let g = 1;
|
||
let names = [];
|
||
for (let i = 0; i < 32; i++) {
|
||
if (g & groups) {
|
||
// This group is in the groups number
|
||
names.push(this.groupNames[i]);
|
||
}
|
||
// Shift the bit over
|
||
g = g << 1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = PhysicsManager;
|
||
/** The default group name */
|
||
PhysicsManager.DEFAULT_GROUP = "Default";
|
||
|
||
},{"../DataTypes/Map":10,"../Events/Emitter":27,"../Events/Receiver":31}],62:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Queue_1 = require("../DataTypes/Queue");
|
||
const Receiver_1 = require("../Events/Receiver");
|
||
const EventQueue_1 = require("../Events/EventQueue");
|
||
const GameEventType_1 = require("../Events/GameEventType");
|
||
// @ignorePage
|
||
class Recorder {
|
||
constructor() {
|
||
this.receiver = new Receiver_1.default();
|
||
this.log = new Queue_1.default(1000);
|
||
this.recording = false;
|
||
this.playing = false;
|
||
this.frame = 0;
|
||
this.eventQueue = EventQueue_1.default.getInstance();
|
||
this.eventQueue.subscribe(this.receiver, "all");
|
||
}
|
||
update(deltaT) {
|
||
if (this.recording) {
|
||
this.frame += 1;
|
||
}
|
||
if (this.playing) {
|
||
// If playing, ignore events, just feed the record to the event queue
|
||
this.receiver.ignoreEvents();
|
||
/*
|
||
While there is a next item, and while it should occur in this frame,
|
||
send the event. i.e., while current_frame * current_delta_t is greater
|
||
than recorded_frame * recorded_delta_t
|
||
*/
|
||
while (this.log.hasItems()
|
||
&& this.log.peekNext().frame * this.log.peekNext().delta < this.frame * deltaT) {
|
||
let event = this.log.dequeue().event;
|
||
console.log(event);
|
||
this.eventQueue.addEvent(event);
|
||
}
|
||
if (!this.log.hasItems()) {
|
||
this.playing = false;
|
||
}
|
||
this.frame += 1;
|
||
}
|
||
else {
|
||
// If not playing, handle events
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
if (event.type === GameEventType_1.GameEventType.STOP_RECORDING) {
|
||
this.recording = false;
|
||
}
|
||
if (this.recording) {
|
||
this.log.enqueue(new LogItem(this.frame, deltaT, event));
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.START_RECORDING) {
|
||
this.log.clear();
|
||
this.recording = true;
|
||
this.frame = 0;
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.PLAY_RECORDING) {
|
||
this.frame = 0;
|
||
this.recording = false;
|
||
this.playing = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = Recorder;
|
||
class LogItem {
|
||
constructor(frame, deltaT, event) {
|
||
this.frame = frame;
|
||
this.delta = deltaT;
|
||
this.event = event;
|
||
}
|
||
}
|
||
|
||
},{"../DataTypes/Queue":14,"../Events/EventQueue":28,"../Events/GameEventType":30,"../Events/Receiver":31}],63:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../../DataTypes/Map");
|
||
/** */
|
||
class Registry extends Map_1.default {
|
||
}
|
||
exports.default = Registry;
|
||
|
||
},{"../../DataTypes/Map":10}],64:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const LabelShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/LabelShaderType");
|
||
const PointShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/PointShaderType");
|
||
const RectShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/RectShaderType");
|
||
const SpriteShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/SpriteShaderType");
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const Registry_1 = require("./Registry");
|
||
/**
|
||
* A registry that handles shaders
|
||
*/
|
||
class ShaderRegistry extends Registry_1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.registryItems = new Array();
|
||
}
|
||
/**
|
||
* Preloads all built-in shaders
|
||
*/
|
||
preload() {
|
||
// Get the resourceManager and queue all built-in shaders for preloading
|
||
const rm = ResourceManager_1.default.getInstance();
|
||
// Queue a load for the point shader
|
||
this.registerAndPreloadItem(ShaderRegistry.POINT_SHADER, PointShaderType_1.default, "builtin/shaders/point.vshader", "builtin/shaders/point.fshader");
|
||
// Queue a load for the rect shader
|
||
this.registerAndPreloadItem(ShaderRegistry.RECT_SHADER, RectShaderType_1.default, "builtin/shaders/rect.vshader", "builtin/shaders/rect.fshader");
|
||
// Queue a load for the sprite shader
|
||
this.registerAndPreloadItem(ShaderRegistry.SPRITE_SHADER, SpriteShaderType_1.default, "builtin/shaders/sprite.vshader", "builtin/shaders/sprite.fshader");
|
||
// Queue a load for the label shader
|
||
this.registerAndPreloadItem(ShaderRegistry.LABEL_SHADER, LabelShaderType_1.default, "builtin/shaders/label.vshader", "builtin/shaders/label.fshader");
|
||
// Queue a load for any preloaded items
|
||
for (let item of this.registryItems) {
|
||
const shader = new item.constr(item.key);
|
||
shader.initBufferObject();
|
||
this.add(item.key, shader);
|
||
// Load if desired
|
||
if (item.preload !== undefined) {
|
||
rm.shader(item.key, item.preload.vshaderLocation, item.preload.fshaderLocation);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Registers a shader in the registry and loads it before the game begins
|
||
* @param key The key you wish to assign to the shader
|
||
* @param constr The constructor of the ShaderType
|
||
* @param vshaderLocation The location of the vertex shader
|
||
* @param fshaderLocation the location of the fragment shader
|
||
*/
|
||
registerAndPreloadItem(key, constr, vshaderLocation, fshaderLocation) {
|
||
let shaderPreload = new ShaderPreload();
|
||
shaderPreload.vshaderLocation = vshaderLocation;
|
||
shaderPreload.fshaderLocation = fshaderLocation;
|
||
let registryItem = new ShaderRegistryItem();
|
||
registryItem.key = key;
|
||
registryItem.constr = constr;
|
||
registryItem.preload = shaderPreload;
|
||
this.registryItems.push(registryItem);
|
||
}
|
||
/**
|
||
* Registers a shader in the registry. NOTE: If you use this, you MUST load the shader before use.
|
||
* If you wish to preload the shader, use registerAndPreloadItem()
|
||
* @param key The key you wish to assign to the shader
|
||
* @param constr The constructor of the ShaderType
|
||
*/
|
||
registerItem(key, constr) {
|
||
let registryItem = new ShaderRegistryItem();
|
||
registryItem.key = key;
|
||
registryItem.constr = constr;
|
||
this.registryItems.push(registryItem);
|
||
}
|
||
}
|
||
exports.default = ShaderRegistry;
|
||
// Shader names
|
||
ShaderRegistry.POINT_SHADER = "point";
|
||
ShaderRegistry.RECT_SHADER = "rect";
|
||
ShaderRegistry.SPRITE_SHADER = "sprite";
|
||
ShaderRegistry.LABEL_SHADER = "label";
|
||
class ShaderRegistryItem {
|
||
}
|
||
class ShaderPreload {
|
||
}
|
||
|
||
},{"../../Rendering/WebGLRendering/ShaderTypes/LabelShaderType":78,"../../Rendering/WebGLRendering/ShaderTypes/PointShaderType":79,"../../Rendering/WebGLRendering/ShaderTypes/RectShaderType":81,"../../Rendering/WebGLRendering/ShaderTypes/SpriteShaderType":82,"../../ResourceManager/ResourceManager":83,"./Registry":63}],65:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const ShaderRegistry_1 = require("./Registries/ShaderRegistry");
|
||
/**
|
||
* The Registry is the system's way of converting classes and types into string
|
||
* representations for use elsewhere in the application.
|
||
* It allows classes to be accessed without explicitly using constructors in code,
|
||
* and for resources to be loaded at Game creation time.
|
||
*/
|
||
class RegistryManager {
|
||
static preload() {
|
||
this.shaders.preload();
|
||
this.registries.forEach((key) => this.registries.get(key).preload());
|
||
}
|
||
static addCustomRegistry(name, registry) {
|
||
this.registries.add(name, registry);
|
||
}
|
||
static getRegistry(key) {
|
||
return this.registries.get(key);
|
||
}
|
||
}
|
||
exports.default = RegistryManager;
|
||
RegistryManager.shaders = new ShaderRegistry_1.default();
|
||
/** Additional custom registries to add to the registry manager */
|
||
RegistryManager.registries = new Map_1.default();
|
||
|
||
},{"../DataTypes/Map":10,"./Registries/ShaderRegistry":64}],66:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../../DataTypes/Map");
|
||
const Emitter_1 = require("../../Events/Emitter");
|
||
const AnimationTypes_1 = require("./AnimationTypes");
|
||
/**
|
||
* An animation manager class for an animated CanvasNode.
|
||
* This class keeps track of the possible animations, as well as the current animation state,
|
||
* and abstracts all interactions with playing, pausing, and stopping animations as well as
|
||
* creating new animations from the CanvasNode.
|
||
*/
|
||
class AnimationManager {
|
||
/**
|
||
* Creates a new AnimationManager
|
||
* @param owner The owner of the AnimationManager
|
||
*/
|
||
constructor(owner) {
|
||
this.owner = owner;
|
||
this.animationState = AnimationTypes_1.AnimationState.STOPPED;
|
||
this.currentAnimation = "";
|
||
this.currentFrame = 0;
|
||
this.frameProgress = 0;
|
||
this.loop = false;
|
||
this.animations = new Map_1.default();
|
||
this.onEndEvent = null;
|
||
this.emitter = new Emitter_1.default();
|
||
}
|
||
/**
|
||
* Add an animation to this sprite
|
||
* @param key The unique key of the animation
|
||
* @param animation The animation data
|
||
*/
|
||
add(key, animation) {
|
||
this.animations.add(key, animation);
|
||
}
|
||
/**
|
||
* Gets the index specified by the current animation and current frame
|
||
* @returns The index in the current animation
|
||
*/
|
||
getIndex() {
|
||
if (this.animations.has(this.currentAnimation)) {
|
||
return this.animations.get(this.currentAnimation).frames[this.currentFrame].index;
|
||
}
|
||
else {
|
||
// No current animation, warn the user
|
||
console.warn(`Animation index was requested, but the current animation: ${this.currentAnimation} was invalid`);
|
||
return 0;
|
||
}
|
||
}
|
||
/**
|
||
* Determines whether the specified animation is currently playing
|
||
* @param key The key of the animation to check
|
||
* @returns true if the specified animation is playing, false otherwise
|
||
*/
|
||
isPlaying(key) {
|
||
return this.currentAnimation === key && this.animationState === AnimationTypes_1.AnimationState.PLAYING;
|
||
}
|
||
/**
|
||
* Retrieves the current animation index and advances the animation frame
|
||
* @returns The index of the animation frame
|
||
*/
|
||
getIndexAndAdvanceAnimation() {
|
||
// If we aren't playing, we won't be advancing the animation
|
||
if (!(this.animationState === AnimationTypes_1.AnimationState.PLAYING)) {
|
||
return this.getIndex();
|
||
}
|
||
if (this.animations.has(this.currentAnimation)) {
|
||
let currentAnimation = this.animations.get(this.currentAnimation);
|
||
let index = currentAnimation.frames[this.currentFrame].index;
|
||
// Advance the animation
|
||
this.frameProgress += 1;
|
||
if (this.frameProgress >= currentAnimation.frames[this.currentFrame].duration) {
|
||
// We have been on this frame for its whole duration, go to the next one
|
||
this.frameProgress = 0;
|
||
this.currentFrame += 1;
|
||
if (this.currentFrame >= currentAnimation.frames.length) {
|
||
// We have reached the end of this animation
|
||
if (this.loop) {
|
||
this.currentFrame = 0;
|
||
this.frameProgress = 0;
|
||
}
|
||
else {
|
||
this.endCurrentAnimation();
|
||
}
|
||
}
|
||
}
|
||
// Return the current index
|
||
return index;
|
||
}
|
||
else {
|
||
// No current animation, can't advance. Warn the user
|
||
console.warn(`Animation index and advance was requested, but the current animation (${this.currentAnimation}) in node with id: ${this.owner.id} was invalid`);
|
||
return 0;
|
||
}
|
||
}
|
||
/** Ends the current animation and fires any necessary events, as well as starting any new animations */
|
||
endCurrentAnimation() {
|
||
this.currentFrame = 0;
|
||
this.animationState = AnimationTypes_1.AnimationState.STOPPED;
|
||
if (this.onEndEvent !== null) {
|
||
this.emitter.fireEvent(this.onEndEvent, { owner: this.owner.id, animation: this.currentAnimation });
|
||
}
|
||
// If there is a pending animation, play it
|
||
if (this.pendingAnimation !== null) {
|
||
this.play(this.pendingAnimation, this.pendingLoop, this.pendingOnEnd);
|
||
}
|
||
}
|
||
/**
|
||
* Plays the specified animation. Does not restart it if it is already playing
|
||
* @param animation The name of the animation to play
|
||
* @param loop Whether or not to loop the animation. False by default
|
||
* @param onEnd The name of an event to send when this animation naturally stops playing. This only matters if loop is false.
|
||
*/
|
||
playIfNotAlready(animation, loop, onEnd) {
|
||
if (this.currentAnimation !== animation) {
|
||
this.play(animation, loop, onEnd);
|
||
}
|
||
}
|
||
/**
|
||
* Plays the specified animation
|
||
* @param animation The name of the animation to play
|
||
* @param loop Whether or not to loop the animation. False by default
|
||
* @param onEnd The name of an event to send when this animation naturally stops playing. This only matters if loop is false.
|
||
*/
|
||
play(animation, loop, onEnd) {
|
||
this.currentAnimation = animation;
|
||
this.currentFrame = 0;
|
||
this.frameProgress = 0;
|
||
this.animationState = AnimationTypes_1.AnimationState.PLAYING;
|
||
// If loop arg was provided, use that
|
||
if (loop !== undefined) {
|
||
this.loop = loop;
|
||
}
|
||
else {
|
||
// Otherwise, use what the json file specified
|
||
this.loop = this.animations.get(animation).repeat;
|
||
}
|
||
if (onEnd !== undefined) {
|
||
this.onEndEvent = onEnd;
|
||
}
|
||
else {
|
||
this.onEndEvent = null;
|
||
}
|
||
// Reset pending animation
|
||
this.pendingAnimation = null;
|
||
}
|
||
/**
|
||
* Queues a single animation to be played after the current one. Does NOT stack.
|
||
* Queueing additional animations past 1 will just replace the queued animation
|
||
* @param animation The animation to queue
|
||
* @param loop Whether or not the loop the queued animation
|
||
* @param onEnd The event to fire when the queued animation ends
|
||
*/
|
||
queue(animation, loop = false, onEnd) {
|
||
this.pendingAnimation = animation;
|
||
this.pendingLoop = loop;
|
||
if (onEnd !== undefined) {
|
||
this.pendingOnEnd = onEnd;
|
||
}
|
||
else {
|
||
this.pendingOnEnd = null;
|
||
}
|
||
}
|
||
/** Pauses the current animation */
|
||
pause() {
|
||
this.animationState = AnimationTypes_1.AnimationState.PAUSED;
|
||
}
|
||
/** Resumes the current animation if possible */
|
||
resume() {
|
||
if (this.animationState === AnimationTypes_1.AnimationState.PAUSED) {
|
||
this.animationState = AnimationTypes_1.AnimationState.PLAYING;
|
||
}
|
||
}
|
||
/** Stops the current animation. The animation cannot be resumed after this. */
|
||
stop() {
|
||
this.animationState = AnimationTypes_1.AnimationState.STOPPED;
|
||
}
|
||
}
|
||
exports.default = AnimationManager;
|
||
|
||
},{"../../DataTypes/Map":10,"../../Events/Emitter":27,"./AnimationTypes":67}],67:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.TweenData = exports.TweenEffect = exports.AnimationData = exports.AnimationState = void 0;
|
||
// @ignorePage
|
||
var AnimationState;
|
||
(function (AnimationState) {
|
||
AnimationState[AnimationState["STOPPED"] = 0] = "STOPPED";
|
||
AnimationState[AnimationState["PAUSED"] = 1] = "PAUSED";
|
||
AnimationState[AnimationState["PLAYING"] = 2] = "PLAYING";
|
||
})(AnimationState = exports.AnimationState || (exports.AnimationState = {}));
|
||
class AnimationData {
|
||
constructor() {
|
||
this.repeat = false;
|
||
}
|
||
}
|
||
exports.AnimationData = AnimationData;
|
||
class TweenEffect {
|
||
}
|
||
exports.TweenEffect = TweenEffect;
|
||
class TweenData {
|
||
}
|
||
exports.TweenData = TweenData;
|
||
|
||
},{}],68:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class ParticleSystemManager {
|
||
constructor() {
|
||
this.particleSystems = new Array();
|
||
}
|
||
static getInstance() {
|
||
if (ParticleSystemManager.instance === null) {
|
||
ParticleSystemManager.instance = new ParticleSystemManager();
|
||
}
|
||
return ParticleSystemManager.instance;
|
||
}
|
||
registerParticleSystem(system) {
|
||
this.particleSystems.push(system);
|
||
}
|
||
deregisterParticleSystem(system) {
|
||
let index = this.particleSystems.indexOf(system);
|
||
this.particleSystems.splice(index, 1);
|
||
}
|
||
clearParticleSystems() {
|
||
this.particleSystems = new Array();
|
||
}
|
||
update(deltaT) {
|
||
for (let particleSystem of this.particleSystems) {
|
||
particleSystem.update(deltaT);
|
||
}
|
||
}
|
||
}
|
||
exports.default = ParticleSystemManager;
|
||
ParticleSystemManager.instance = null;
|
||
|
||
},{}],69:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../../DataTypes/Map");
|
||
const AnimationTypes_1 = require("./AnimationTypes");
|
||
const EaseFunctions_1 = require("../../Utils/EaseFunctions");
|
||
const MathUtils_1 = require("../../Utils/MathUtils");
|
||
const TweenManager_1 = require("./TweenManager");
|
||
const Emitter_1 = require("../../Events/Emitter");
|
||
/**
|
||
* A manager for the tweens of a GameNode.
|
||
* Tweens are short animations played by interpolating between two properties using an easing function.
|
||
* For a good visual representation of easing functions, check out @link(https://easings.net/)(https://easings.net/).
|
||
* Multiple tween can be played at the same time, as long as they don't change the same property.
|
||
* This allows for some interesting polishes or animations that may be very difficult to do with sprite work alone
|
||
* - especially pixel art (such as rotations or scaling).
|
||
*/
|
||
class TweenController {
|
||
/**
|
||
* Creates a new TweenController
|
||
* @param owner The owner of the TweenController
|
||
*/
|
||
constructor(owner) {
|
||
this.owner = owner;
|
||
this.tweens = new Map_1.default();
|
||
this.emitter = new Emitter_1.default();
|
||
// Give ourselves to the TweenManager
|
||
TweenManager_1.default.getInstance().registerTweenController(this);
|
||
}
|
||
/**
|
||
* Destroys this TweenController
|
||
*/
|
||
destroy() {
|
||
// Only the gamenode and the tween manager should have a reference to this
|
||
delete this.owner.tweens;
|
||
TweenManager_1.default.getInstance().deregisterTweenController(this);
|
||
}
|
||
/**
|
||
* Add a tween to this game node
|
||
* @param key The name of the tween
|
||
* @param tween The data of the tween
|
||
*/
|
||
add(key, tween) {
|
||
let typedTween = tween;
|
||
// Initialize members that we need (and the user didn't provide)
|
||
typedTween.progress = 0;
|
||
typedTween.elapsedTime = 0;
|
||
typedTween.animationState = AnimationTypes_1.AnimationState.STOPPED;
|
||
this.tweens.add(key, typedTween);
|
||
}
|
||
/**
|
||
* Play a tween with a certain name
|
||
* @param key The name of the tween to play
|
||
* @param loop Whether or not the tween should loop
|
||
*/
|
||
play(key, loop) {
|
||
if (this.tweens.has(key)) {
|
||
let tween = this.tweens.get(key);
|
||
// Set loop if needed
|
||
if (loop !== undefined) {
|
||
tween.loop = loop;
|
||
}
|
||
// Set the initial values
|
||
for (let effect of tween.effects) {
|
||
if (effect.resetOnComplete) {
|
||
effect.initialValue = this.owner[effect.property];
|
||
}
|
||
}
|
||
// Start the tween running
|
||
tween.animationState = AnimationTypes_1.AnimationState.PLAYING;
|
||
tween.elapsedTime = 0;
|
||
tween.progress = 0;
|
||
tween.reversing = false;
|
||
}
|
||
else {
|
||
console.warn(`Tried to play tween "${key}" on node with id ${this.owner.id}, but no such tween exists`);
|
||
}
|
||
}
|
||
/**
|
||
* Pauses a playing tween. Does not affect tweens that are stopped.
|
||
* @param key The name of the tween to pause.
|
||
*/
|
||
pause(key) {
|
||
if (this.tweens.has(key)) {
|
||
this.tweens.get(key).animationState = AnimationTypes_1.AnimationState.PAUSED;
|
||
}
|
||
}
|
||
/**
|
||
* Resumes a paused tween.
|
||
* @param key The name of the tween to resume
|
||
*/
|
||
resume(key) {
|
||
if (this.tweens.has(key)) {
|
||
let tween = this.tweens.get(key);
|
||
if (tween.animationState === AnimationTypes_1.AnimationState.PAUSED)
|
||
tween.animationState = AnimationTypes_1.AnimationState.PLAYING;
|
||
}
|
||
}
|
||
/**
|
||
* Stops a currently playing tween
|
||
* @param key The key of the tween
|
||
*/
|
||
stop(key) {
|
||
if (this.tweens.has(key)) {
|
||
let tween = this.tweens.get(key);
|
||
tween.animationState = AnimationTypes_1.AnimationState.STOPPED;
|
||
// Return to the initial values
|
||
for (let effect of tween.effects) {
|
||
if (effect.resetOnComplete) {
|
||
this.owner[effect.property] = effect.initialValue;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* The natural stop of a currently playing tween
|
||
* @param key The key of the tween
|
||
*/
|
||
end(key) {
|
||
this.stop(key);
|
||
if (this.tweens.has(key)) {
|
||
// Get the tween
|
||
let tween = this.tweens.get(key);
|
||
// If it has an onEnd, send an event
|
||
if (tween.onEnd) {
|
||
let data = { key: key, node: this.owner.id };
|
||
// If it has onEnd event data, add each entry, as long as the key is not named 'key' or 'node'
|
||
if (tween.onEndData) {
|
||
Object.keys(tween.onEndData).forEach(key => {
|
||
if (key !== "key" && key !== "node") {
|
||
data[key] = tween.onEndData[key];
|
||
}
|
||
});
|
||
}
|
||
this.emitter.fireEvent(tween.onEnd, data);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Stops all currently playing tweens
|
||
*/
|
||
stopAll() {
|
||
this.tweens.forEach(key => this.stop(key));
|
||
}
|
||
update(deltaT) {
|
||
this.tweens.forEach(key => {
|
||
let tween = this.tweens.get(key);
|
||
if (tween.animationState === AnimationTypes_1.AnimationState.PLAYING) {
|
||
// Update the progress of the tween
|
||
tween.elapsedTime += deltaT * 1000;
|
||
// If we're past the startDelay, do the tween
|
||
if (tween.elapsedTime >= tween.startDelay) {
|
||
if (!tween.reversing && tween.elapsedTime >= tween.startDelay + tween.duration) {
|
||
// If we're over time, stop the tween, loop, or reverse
|
||
if (tween.reverseOnComplete) {
|
||
// If we're over time and can reverse, do so
|
||
tween.reversing = true;
|
||
}
|
||
else if (tween.loop) {
|
||
// If we can't reverse and can loop, do so
|
||
tween.elapsedTime -= tween.duration;
|
||
}
|
||
else {
|
||
// We aren't looping and can't reverse, so stop
|
||
this.end(key);
|
||
}
|
||
}
|
||
// Check for the end of reversing
|
||
if (tween.reversing && tween.elapsedTime >= tween.startDelay + 2 * tween.duration) {
|
||
if (tween.loop) {
|
||
tween.reversing = false;
|
||
tween.elapsedTime -= 2 * tween.duration;
|
||
}
|
||
else {
|
||
this.end(key);
|
||
}
|
||
}
|
||
// Update the progress, make sure it is between 0 and 1. Errors from this should never be large
|
||
if (tween.reversing) {
|
||
tween.progress = MathUtils_1.default.clamp01((2 * tween.duration - (tween.elapsedTime - tween.startDelay)) / tween.duration);
|
||
}
|
||
else {
|
||
tween.progress = MathUtils_1.default.clamp01((tween.elapsedTime - tween.startDelay) / tween.duration);
|
||
}
|
||
for (let effect of tween.effects) {
|
||
// Get the value from the ease function that corresponds to our progress
|
||
let ease = EaseFunctions_1.default[effect.ease](tween.progress);
|
||
// Use the value to lerp the property
|
||
let value = MathUtils_1.default.lerp(effect.start, effect.end, ease);
|
||
// Assign the value of the property
|
||
this.owner[effect.property] = value;
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
}
|
||
exports.default = TweenController;
|
||
|
||
},{"../../DataTypes/Map":10,"../../Events/Emitter":27,"../../Utils/EaseFunctions":100,"../../Utils/MathUtils":102,"./AnimationTypes":67,"./TweenManager":70}],70:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class TweenManager {
|
||
constructor() {
|
||
this.tweenControllers = new Array();
|
||
}
|
||
static getInstance() {
|
||
if (TweenManager.instance === null) {
|
||
TweenManager.instance = new TweenManager();
|
||
}
|
||
return TweenManager.instance;
|
||
}
|
||
registerTweenController(controller) {
|
||
this.tweenControllers.push(controller);
|
||
}
|
||
deregisterTweenController(controller) {
|
||
let index = this.tweenControllers.indexOf(controller);
|
||
this.tweenControllers.splice(index, 1);
|
||
}
|
||
clearTweenControllers() {
|
||
this.tweenControllers = new Array();
|
||
}
|
||
update(deltaT) {
|
||
for (let tweenController of this.tweenControllers) {
|
||
tweenController.update(deltaT);
|
||
}
|
||
}
|
||
}
|
||
exports.default = TweenManager;
|
||
TweenManager.instance = null;
|
||
|
||
},{}],71:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Graphic_1 = require("../Nodes/Graphic");
|
||
const Point_1 = require("../Nodes/Graphics/Point");
|
||
const Rect_1 = require("../Nodes/Graphics/Rect");
|
||
const Sprite_1 = require("../Nodes/Sprites/Sprite");
|
||
const OrthogonalTilemap_1 = require("../Nodes/Tilemaps/OrthogonalTilemap");
|
||
const UIElement_1 = require("../Nodes/UIElement");
|
||
const GraphicRenderer_1 = require("./CanvasRendering/GraphicRenderer");
|
||
const RenderingManager_1 = require("./RenderingManager");
|
||
const TilemapRenderer_1 = require("./CanvasRendering/TilemapRenderer");
|
||
const UIElementRenderer_1 = require("./CanvasRendering/UIElementRenderer");
|
||
const Label_1 = require("../Nodes/UIElements/Label");
|
||
const Button_1 = require("../Nodes/UIElements/Button");
|
||
const Slider_1 = require("../Nodes/UIElements/Slider");
|
||
const TextInput_1 = require("../Nodes/UIElements/TextInput");
|
||
const AnimatedSprite_1 = require("../Nodes/Sprites/AnimatedSprite");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const Line_1 = require("../Nodes/Graphics/Line");
|
||
/**
|
||
* An implementation of the RenderingManager class using CanvasRenderingContext2D.
|
||
*/
|
||
class CanvasRenderer extends RenderingManager_1.default {
|
||
constructor() {
|
||
super();
|
||
}
|
||
// @override
|
||
setScene(scene) {
|
||
this.scene = scene;
|
||
this.graphicRenderer.setScene(scene);
|
||
this.tilemapRenderer.setScene(scene);
|
||
this.uiElementRenderer.setScene(scene);
|
||
}
|
||
// @override
|
||
initializeCanvas(canvas, width, height) {
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
this.worldSize = new Vec2_1.default(width, height);
|
||
this.ctx = canvas.getContext("2d");
|
||
this.graphicRenderer = new GraphicRenderer_1.default(this.ctx);
|
||
this.tilemapRenderer = new TilemapRenderer_1.default(this.ctx);
|
||
this.uiElementRenderer = new UIElementRenderer_1.default(this.ctx);
|
||
// For crisp pixel art
|
||
this.ctx.imageSmoothingEnabled = false;
|
||
return this.ctx;
|
||
}
|
||
// @override
|
||
render(visibleSet, tilemaps, uiLayers) {
|
||
// Sort by depth, then by visible set by y-value
|
||
visibleSet.sort((a, b) => {
|
||
if (a.getLayer().getDepth() === b.getLayer().getDepth()) {
|
||
return (a.boundary.bottom) - (b.boundary.bottom);
|
||
}
|
||
else {
|
||
return a.getLayer().getDepth() - b.getLayer().getDepth();
|
||
}
|
||
});
|
||
let tilemapIndex = 0;
|
||
let tilemapLength = tilemaps.length;
|
||
let visibleSetIndex = 0;
|
||
let visibleSetLength = visibleSet.length;
|
||
while (tilemapIndex < tilemapLength || visibleSetIndex < visibleSetLength) {
|
||
// Check conditions where we've already reached the edge of one list
|
||
if (tilemapIndex >= tilemapLength) {
|
||
// Only render the remaining visible set
|
||
let node = visibleSet[visibleSetIndex++];
|
||
if (node.visible) {
|
||
this.renderNode(node);
|
||
}
|
||
continue;
|
||
}
|
||
if (visibleSetIndex >= visibleSetLength) {
|
||
// Only render tilemaps
|
||
this.renderTilemap(tilemaps[tilemapIndex++]);
|
||
continue;
|
||
}
|
||
// Render whichever is further down
|
||
if (tilemaps[tilemapIndex].getLayer().getDepth() <= visibleSet[visibleSetIndex].getLayer().getDepth()) {
|
||
this.renderTilemap(tilemaps[tilemapIndex++]);
|
||
}
|
||
else {
|
||
let node = visibleSet[visibleSetIndex++];
|
||
if (node.visible) {
|
||
this.renderNode(node);
|
||
}
|
||
}
|
||
}
|
||
// Render the uiLayers on top of everything else
|
||
let sortedUILayers = new Array();
|
||
uiLayers.forEach(key => sortedUILayers.push(uiLayers.get(key)));
|
||
sortedUILayers = sortedUILayers.sort((ui1, ui2) => ui1.getDepth() - ui2.getDepth());
|
||
sortedUILayers.forEach(uiLayer => {
|
||
if (!uiLayer.isHidden())
|
||
uiLayer.getItems().forEach(node => {
|
||
if (node.visible) {
|
||
this.renderNode(node);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Renders a specified CanvasNode
|
||
* @param node The CanvasNode to render
|
||
*/
|
||
renderNode(node) {
|
||
// Calculate the origin of the viewport according to this sprite
|
||
this.origin = this.scene.getViewTranslation(node);
|
||
// Get the zoom level of the scene
|
||
this.zoom = this.scene.getViewScale();
|
||
// Move the canvas to the position of the node and rotate
|
||
let xScale = 1;
|
||
let yScale = 1;
|
||
if (node instanceof Sprite_1.default) {
|
||
xScale = node.invertX ? -1 : 1;
|
||
yScale = node.invertY ? -1 : 1;
|
||
}
|
||
this.ctx.setTransform(xScale, 0, 0, yScale, (node.position.x - this.origin.x) * this.zoom, (node.position.y - this.origin.y) * this.zoom);
|
||
this.ctx.rotate(-node.rotation);
|
||
let globalAlpha = this.ctx.globalAlpha;
|
||
// if(node instanceof Rect){
|
||
// Debug.log("node" + node.id, "Node" + node.id + " Alpha: " + node.alpha);
|
||
// }
|
||
this.ctx.globalAlpha = node.alpha;
|
||
if (node instanceof AnimatedSprite_1.default) {
|
||
this.renderAnimatedSprite(node);
|
||
}
|
||
else if (node instanceof Sprite_1.default) {
|
||
this.renderSprite(node);
|
||
}
|
||
else if (node instanceof Graphic_1.default) {
|
||
this.renderGraphic(node);
|
||
}
|
||
else if (node instanceof UIElement_1.default) {
|
||
this.renderUIElement(node);
|
||
}
|
||
this.ctx.globalAlpha = globalAlpha;
|
||
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||
}
|
||
// @override
|
||
renderSprite(sprite) {
|
||
// Get the image from the resource manager
|
||
let image = this.resourceManager.getImage(sprite.imageId);
|
||
/*
|
||
Coordinates in the space of the image:
|
||
image crop start -> x, y
|
||
image crop size -> w, h
|
||
Coordinates in the space of the world
|
||
image draw start -> x, y
|
||
image draw size -> w, h
|
||
*/
|
||
this.ctx.drawImage(image, sprite.imageOffset.x, sprite.imageOffset.y, sprite.size.x, sprite.size.y, (-sprite.size.x * sprite.scale.x / 2) * this.zoom, (-sprite.size.y * sprite.scale.y / 2) * this.zoom, sprite.size.x * sprite.scale.x * this.zoom, sprite.size.y * sprite.scale.y * this.zoom);
|
||
}
|
||
// @override
|
||
renderAnimatedSprite(sprite) {
|
||
// Get the image from the resource manager
|
||
let image = this.resourceManager.getImage(sprite.imageId);
|
||
let animationIndex = sprite.animation.getIndexAndAdvanceAnimation();
|
||
let animationOffset = sprite.getAnimationOffset(animationIndex);
|
||
/*
|
||
Coordinates in the space of the image:
|
||
image crop start -> x, y
|
||
image crop size -> w, h
|
||
Coordinates in the space of the world (given we moved)
|
||
image draw start -> -w/2, -h/2
|
||
image draw size -> w, h
|
||
*/
|
||
this.ctx.drawImage(image, sprite.imageOffset.x + animationOffset.x, sprite.imageOffset.y + animationOffset.y, sprite.size.x, sprite.size.y, (-sprite.size.x * sprite.scale.x / 2) * this.zoom, (-sprite.size.y * sprite.scale.y / 2) * this.zoom, sprite.size.x * sprite.scale.x * this.zoom, sprite.size.y * sprite.scale.y * this.zoom);
|
||
}
|
||
// @override
|
||
renderGraphic(graphic) {
|
||
if (graphic instanceof Point_1.default) {
|
||
this.graphicRenderer.renderPoint(graphic, this.zoom);
|
||
}
|
||
else if (graphic instanceof Line_1.default) {
|
||
this.graphicRenderer.renderLine(graphic, this.origin, this.zoom);
|
||
}
|
||
else if (graphic instanceof Rect_1.default) {
|
||
this.graphicRenderer.renderRect(graphic, this.zoom);
|
||
}
|
||
}
|
||
// @override
|
||
renderTilemap(tilemap) {
|
||
if (tilemap instanceof OrthogonalTilemap_1.default) {
|
||
this.tilemapRenderer.renderOrthogonalTilemap(tilemap);
|
||
}
|
||
}
|
||
// @override
|
||
renderUIElement(uiElement) {
|
||
if (uiElement instanceof Label_1.default) {
|
||
this.uiElementRenderer.renderLabel(uiElement);
|
||
}
|
||
else if (uiElement instanceof Button_1.default) {
|
||
this.uiElementRenderer.renderButton(uiElement);
|
||
}
|
||
else if (uiElement instanceof Slider_1.default) {
|
||
this.uiElementRenderer.renderSlider(uiElement);
|
||
}
|
||
else if (uiElement instanceof TextInput_1.default) {
|
||
this.uiElementRenderer.renderTextInput(uiElement);
|
||
}
|
||
}
|
||
clear(clearColor) {
|
||
this.ctx.clearRect(0, 0, this.worldSize.x, this.worldSize.y);
|
||
this.ctx.fillStyle = clearColor.toString();
|
||
this.ctx.fillRect(0, 0, this.worldSize.x, this.worldSize.y);
|
||
}
|
||
}
|
||
exports.default = CanvasRenderer;
|
||
|
||
},{"../DataTypes/Vec2":24,"../Nodes/Graphic":41,"../Nodes/Graphics/Line":43,"../Nodes/Graphics/Point":45,"../Nodes/Graphics/Rect":46,"../Nodes/Sprites/AnimatedSprite":47,"../Nodes/Sprites/Sprite":48,"../Nodes/Tilemaps/OrthogonalTilemap":50,"../Nodes/UIElement":51,"../Nodes/UIElements/Button":52,"../Nodes/UIElements/Label":53,"../Nodes/UIElements/Slider":54,"../Nodes/UIElements/TextInput":55,"./CanvasRendering/GraphicRenderer":72,"./CanvasRendering/TilemapRenderer":73,"./CanvasRendering/UIElementRenderer":74,"./RenderingManager":75}],72:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
/**
|
||
* A utility class to help the @reference[CanvasRenderer] render @reference[Graphic]s
|
||
*/
|
||
class GraphicRenderer {
|
||
constructor(ctx) {
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
this.ctx = ctx;
|
||
}
|
||
/**
|
||
* Sets the scene of this GraphicRenderer
|
||
* @param scene The current scene
|
||
*/
|
||
setScene(scene) {
|
||
this.scene = scene;
|
||
}
|
||
/**
|
||
* Renders a point
|
||
* @param point The point to render
|
||
* @param zoom The zoom level
|
||
*/
|
||
renderPoint(point, zoom) {
|
||
this.ctx.fillStyle = point.color.toStringRGBA();
|
||
this.ctx.fillRect((-point.size.x / 2) * zoom, (-point.size.y / 2) * zoom, point.size.x * zoom, point.size.y * zoom);
|
||
}
|
||
renderLine(line, origin, zoom) {
|
||
this.ctx.strokeStyle = line.color.toStringRGBA();
|
||
this.ctx.lineWidth = line.thickness;
|
||
this.ctx.beginPath();
|
||
this.ctx.moveTo(0, 0);
|
||
this.ctx.lineTo((line.end.x - line.start.x) * zoom, (line.end.y - line.start.y) * zoom);
|
||
this.ctx.closePath();
|
||
this.ctx.stroke();
|
||
}
|
||
/**
|
||
* Renders a rect
|
||
* @param rect The rect to render
|
||
* @param zoom The zoom level
|
||
*/
|
||
renderRect(rect, zoom) {
|
||
// Draw the interior of the rect
|
||
if (rect.color.a !== 0) {
|
||
this.ctx.fillStyle = rect.color.toStringRGB();
|
||
if (rect.fillWidth !== null) {
|
||
this.ctx.fillRect((-rect.size.x / 2) * zoom, (-rect.size.y / 2) * zoom, rect.fillWidth * zoom, rect.size.y * zoom);
|
||
}
|
||
else {
|
||
this.ctx.fillRect((-rect.size.x / 2) * zoom, (-rect.size.y / 2) * zoom, rect.size.x * zoom, rect.size.y * zoom);
|
||
}
|
||
}
|
||
// Draw the border of the rect if it isn't transparent
|
||
if (rect.borderColor.a !== 0) {
|
||
this.ctx.strokeStyle = rect.getBorderColor().toStringRGB();
|
||
this.ctx.lineWidth = rect.getBorderWidth();
|
||
this.ctx.strokeRect((-rect.size.x / 2) * zoom, (-rect.size.y / 2) * zoom, rect.size.x * zoom, rect.size.y * zoom);
|
||
}
|
||
}
|
||
}
|
||
exports.default = GraphicRenderer;
|
||
|
||
},{"../../ResourceManager/ResourceManager":83}],73:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
/**
|
||
* A utility class for the @reference[CanvasRenderer] to render @reference[Tilemap]s
|
||
*/
|
||
class TilemapRenderer {
|
||
constructor(ctx) {
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
this.ctx = ctx;
|
||
}
|
||
/**
|
||
* Sets the scene of this TilemapRenderer
|
||
* @param scene The current scene
|
||
*/
|
||
setScene(scene) {
|
||
this.scene = scene;
|
||
}
|
||
/**
|
||
* Renders an orthogonal tilemap
|
||
* @param tilemap The tilemap to render
|
||
*/
|
||
renderOrthogonalTilemap(tilemap) {
|
||
let previousAlpha = this.ctx.globalAlpha;
|
||
this.ctx.globalAlpha = tilemap.getLayer().getAlpha();
|
||
let origin = this.scene.getViewTranslation(tilemap);
|
||
let size = this.scene.getViewport().getHalfSize();
|
||
let zoom = this.scene.getViewScale();
|
||
let bottomRight = origin.clone().add(size.scaled(2 * zoom));
|
||
if (tilemap.visible) {
|
||
let minColRow = tilemap.getColRowAt(origin);
|
||
let maxColRow = tilemap.getColRowAt(bottomRight);
|
||
for (let x = minColRow.x; x <= maxColRow.x; x++) {
|
||
for (let y = minColRow.y; y <= maxColRow.y; y++) {
|
||
// Get the tile at this position
|
||
let tile = tilemap.getTileAtRowCol(new Vec2_1.default(x, y));
|
||
// Extract the rot/flip parameters if there are any
|
||
const mask = (0xE << 28);
|
||
const rotFlip = ((mask & tile) >> 28) & 0xF;
|
||
tile = tile & ~mask;
|
||
// Find the tileset that owns this tile index and render
|
||
for (let tileset of tilemap.getTilesets()) {
|
||
if (tileset.hasTile(tile)) {
|
||
this.renderTile(tileset, tile, x, y, origin, tilemap.scale, zoom, rotFlip);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
this.ctx.globalAlpha = previousAlpha;
|
||
}
|
||
/**
|
||
* Renders a tile
|
||
* @param tileset The tileset this tile belongs to
|
||
* @param tileIndex The index of the tile
|
||
* @param tilemapRow The row of the tile in the tilemap
|
||
* @param tilemapCol The column of the tile in the tilemap
|
||
* @param origin The origin of the viewport
|
||
* @param scale The scale of the tilemap
|
||
* @param zoom The zoom level of the viewport
|
||
*/
|
||
renderTile(tileset, tileIndex, tilemapRow, tilemapCol, origin, scale, zoom, rotFlip) {
|
||
let image = this.resourceManager.getImage(tileset.getImageKey());
|
||
// Get the true index
|
||
let index = tileIndex - tileset.getStartIndex();
|
||
// Get the row and col of the tile in image space
|
||
let row = Math.floor(index / tileset.getNumCols());
|
||
let col = index % tileset.getNumCols();
|
||
let width = tileset.getTileSize().x;
|
||
let height = tileset.getTileSize().y;
|
||
// Calculate the position to start a crop in the tileset image
|
||
let left = col * width;
|
||
let top = row * height;
|
||
// Calculate the position in the world to render the tile
|
||
let x = Math.floor(tilemapRow * width * scale.x);
|
||
let y = Math.floor(tilemapCol * height * scale.y);
|
||
let worldX = Math.floor((x - origin.x) * zoom);
|
||
let worldY = Math.floor((y - origin.y) * zoom);
|
||
let worldWidth = Math.ceil(width * scale.x * zoom);
|
||
let worldHeight = Math.ceil(height * scale.y * zoom);
|
||
if (rotFlip !== 0) {
|
||
let scaleX = 1;
|
||
let scaleY = 1;
|
||
let shearX = 0;
|
||
let shearY = 0;
|
||
// Flip on the x-axis
|
||
if (rotFlip & 8) {
|
||
scaleX = -1;
|
||
}
|
||
// Flip on the y-axis
|
||
if (rotFlip & 4) {
|
||
scaleY = -1;
|
||
}
|
||
// Flip over the line y=x
|
||
if (rotFlip & 2) {
|
||
shearX = scaleY;
|
||
shearY = scaleX;
|
||
scaleX = 0;
|
||
scaleY = 0;
|
||
}
|
||
this.ctx.setTransform(scaleX, shearX, shearY, scaleY, worldX + worldWidth / 2, worldY + worldHeight / 2);
|
||
// Render the tile
|
||
this.ctx.drawImage(image, left, top, width, height, -worldWidth / 2, -worldHeight / 2, worldWidth, worldHeight);
|
||
if (rotFlip !== 0) {
|
||
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||
}
|
||
}
|
||
else {
|
||
// No rotations, don't do the calculations, just render the tile
|
||
// Render the tile
|
||
this.ctx.drawImage(image, left, top, width, height, worldX, worldY, worldWidth, worldHeight);
|
||
}
|
||
}
|
||
}
|
||
exports.default = TilemapRenderer;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../ResourceManager/ResourceManager":83}],74:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const MathUtils_1 = require("../../Utils/MathUtils");
|
||
/**
|
||
* A utility class to help the @reference[CanvasRenderer] render @reference[UIElement]s
|
||
*/
|
||
class UIElementRenderer {
|
||
constructor(ctx) {
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
this.ctx = ctx;
|
||
}
|
||
/**
|
||
* Sets the scene of this UIElementRenderer
|
||
* @param scene The current scene
|
||
*/
|
||
setScene(scene) {
|
||
this.scene = scene;
|
||
}
|
||
/**
|
||
* Renders a label
|
||
* @param label The label to render
|
||
*/
|
||
renderLabel(label) {
|
||
// // If the size is unassigned (by the user or automatically) assign it
|
||
// label.handleInitialSizing(this.ctx);
|
||
// // Grab the global alpha so we can adjust it for this render
|
||
// let previousAlpha = this.ctx.globalAlpha;
|
||
// // Get the font and text position in label
|
||
// this.ctx.font = label.getFontString();
|
||
// let offset = label.calculateTextOffset(this.ctx);
|
||
// // Stroke and fill a rounded rect and give it text
|
||
// this.ctx.globalAlpha = label.backgroundColor.a;
|
||
// this.ctx.fillStyle = label.calculateBackgroundColor().toStringRGBA();
|
||
// this.ctx.fillRoundedRect(-label.size.x/2, -label.size.y/2,
|
||
// label.size.x, label.size.y, label.borderRadius);
|
||
// this.ctx.strokeStyle = label.calculateBorderColor().toStringRGBA();
|
||
// this.ctx.globalAlpha = label.borderColor.a;
|
||
// this.ctx.lineWidth = label.borderWidth;
|
||
// this.ctx.strokeRoundedRect(-label.size.x/2, -label.size.y/2,
|
||
// label.size.x, label.size.y, label.borderRadius);
|
||
// this.ctx.fillStyle = label.calculateTextColor();
|
||
// this.ctx.globalAlpha = label.textColor.a;
|
||
// this.ctx.fillText(label.text, offset.x - label.size.x/2, offset.y - label.size.y/2);
|
||
// this.ctx.globalAlpha = previousAlpha;
|
||
// If the size is unassigned (by the user or automatically) assign it
|
||
let lines = label.text.split('\n');
|
||
let tempText = label.text;
|
||
if (lines.length > 1) {
|
||
let max = 0;
|
||
let maxLengthIndex = 0;
|
||
for (let i = 0; i < lines.length; i++) {
|
||
if (lines[i].length > max) {
|
||
max = lines[i].length;
|
||
maxLengthIndex = i;
|
||
}
|
||
}
|
||
label.text = lines[maxLengthIndex];
|
||
}
|
||
label.handleInitialSizing(this.ctx);
|
||
// Grab the global alpha so we can adjust it for this render
|
||
let previousAlpha = this.ctx.globalAlpha;
|
||
// Get the font and text position in label
|
||
this.ctx.font = label.getFontString();
|
||
let offset = label.calculateTextOffset(this.ctx);
|
||
// Stroke and fill a rounded rect and give it text
|
||
this.ctx.globalAlpha = label.backgroundColor.a;
|
||
this.ctx.fillStyle = label.calculateBackgroundColor().toStringRGBA();
|
||
this.ctx.fillRoundedRect(-label.size.x / 2, -label.size.y / 2, label.size.x, label.size.y, label.borderRadius);
|
||
this.ctx.strokeStyle = label.calculateBorderColor().toStringRGBA();
|
||
this.ctx.globalAlpha = label.borderColor.a;
|
||
this.ctx.lineWidth = label.borderWidth;
|
||
this.ctx.strokeRoundedRect(-label.size.x / 2, -label.size.y / 2, label.size.x, label.size.y + ((lines.length - 1) * label.fontSize), label.borderRadius);
|
||
this.ctx.fillStyle = label.calculateTextColor();
|
||
this.ctx.globalAlpha = label.textColor.a;
|
||
if (lines.length === 1) {
|
||
this.ctx.fillText(label.text, offset.x - label.size.x / 2, (offset.y - label.size.y / 2));
|
||
}
|
||
else {
|
||
for (let i = 0; i < lines.length; i++) {
|
||
let additionalY = i * (label.size.y / 2 + (label.fontSize === 40 ? 20 : 10));
|
||
label.text = lines[i];
|
||
offset = label.calculateTextOffset(this.ctx);
|
||
this.ctx.fillText(lines[i], (offset.x - label.size.x / 2), (offset.y - label.size.y / 2 + additionalY));
|
||
}
|
||
}
|
||
this.ctx.globalAlpha = previousAlpha;
|
||
label.text = tempText;
|
||
}
|
||
/**
|
||
* Renders a button
|
||
* @param button The button to render
|
||
*/
|
||
renderButton(button) {
|
||
this.renderLabel(button);
|
||
}
|
||
/**
|
||
* Renders a slider
|
||
* @param slider The slider to render
|
||
*/
|
||
renderSlider(slider) {
|
||
// Grab the global alpha so we can adjust it for this render
|
||
let previousAlpha = this.ctx.globalAlpha;
|
||
this.ctx.globalAlpha = slider.getLayer().getAlpha();
|
||
// Calcualate the slider size
|
||
let sliderSize = new Vec2_1.default(slider.size.x, 2);
|
||
// Draw the slider
|
||
this.ctx.fillStyle = slider.sliderColor.toString();
|
||
this.ctx.fillRoundedRect(-sliderSize.x / 2, -sliderSize.y / 2, sliderSize.x, sliderSize.y, slider.borderRadius);
|
||
// Calculate the nib size and position
|
||
let x = MathUtils_1.default.lerp(-slider.size.x / 2, slider.size.x / 2, slider.getValue());
|
||
// Draw the nib
|
||
this.ctx.fillStyle = slider.nibColor.toString();
|
||
this.ctx.fillRoundedRect(x - slider.nibSize.x / 2, -slider.nibSize.y / 2, slider.nibSize.x, slider.nibSize.y, slider.borderRadius);
|
||
// Reset the alpha
|
||
this.ctx.globalAlpha = previousAlpha;
|
||
}
|
||
/**
|
||
* Renders a textInput
|
||
* @param textInput The textInput to render
|
||
*/
|
||
renderTextInput(textInput) {
|
||
// Show a cursor sometimes
|
||
if (textInput.focused && textInput.cursorCounter % 60 > 30) {
|
||
textInput.text += "|";
|
||
}
|
||
this.renderLabel(textInput);
|
||
if (textInput.focused) {
|
||
if (textInput.cursorCounter % 60 > 30) {
|
||
textInput.text = textInput.text.substring(0, textInput.text.length - 1);
|
||
}
|
||
textInput.cursorCounter += 1;
|
||
if (textInput.cursorCounter >= 60) {
|
||
textInput.cursorCounter = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = UIElementRenderer;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../ResourceManager/ResourceManager":83,"../../Utils/MathUtils":102}],75:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../ResourceManager/ResourceManager");
|
||
/**
|
||
* An abstract framework to put all rendering in once place in the application
|
||
*/
|
||
class RenderingManager {
|
||
constructor() {
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
/**
|
||
* Sets the scene currently being rendered
|
||
* @param scene The current Scene
|
||
*/
|
||
setScene(scene) {
|
||
this.scene = scene;
|
||
}
|
||
}
|
||
exports.default = RenderingManager;
|
||
|
||
},{"../ResourceManager/ResourceManager":83}],76:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const Graphic_1 = require("../Nodes/Graphic");
|
||
const Point_1 = require("../Nodes/Graphics/Point");
|
||
const Rect_1 = require("../Nodes/Graphics/Rect");
|
||
const AnimatedSprite_1 = require("../Nodes/Sprites/AnimatedSprite");
|
||
const Sprite_1 = require("../Nodes/Sprites/Sprite");
|
||
const UIElement_1 = require("../Nodes/UIElement");
|
||
const Label_1 = require("../Nodes/UIElements/Label");
|
||
const ShaderRegistry_1 = require("../Registry/Registries/ShaderRegistry");
|
||
const RegistryManager_1 = require("../Registry/RegistryManager");
|
||
const ResourceManager_1 = require("../ResourceManager/ResourceManager");
|
||
const ParallaxLayer_1 = require("../Scene/Layers/ParallaxLayer");
|
||
const RenderingManager_1 = require("./RenderingManager");
|
||
class WebGLRenderer extends RenderingManager_1.default {
|
||
initializeCanvas(canvas, width, height) {
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
this.worldSize = Vec2_1.default.ZERO;
|
||
this.worldSize.x = width;
|
||
this.worldSize.y = height;
|
||
// Get the WebGL context
|
||
this.gl = canvas.getContext("webgl");
|
||
this.gl.viewport(0, 0, canvas.width, canvas.height);
|
||
this.gl.disable(this.gl.DEPTH_TEST);
|
||
this.gl.enable(this.gl.BLEND);
|
||
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
|
||
this.gl.enable(this.gl.CULL_FACE);
|
||
// Tell the resource manager we're using WebGL
|
||
ResourceManager_1.default.getInstance().useWebGL(true, this.gl);
|
||
// Show the text canvas and get its context
|
||
let textCanvas = document.getElementById("text-canvas");
|
||
textCanvas.hidden = false;
|
||
this.textCtx = textCanvas.getContext("2d");
|
||
// Size the text canvas to be the same as the game canvas
|
||
textCanvas.height = height;
|
||
textCanvas.width = width;
|
||
return this.gl;
|
||
}
|
||
render(visibleSet, tilemaps, uiLayers) {
|
||
for (let node of visibleSet) {
|
||
this.renderNode(node);
|
||
}
|
||
uiLayers.forEach(key => {
|
||
if (!uiLayers.get(key).isHidden())
|
||
uiLayers.get(key).getItems().forEach(node => this.renderNode(node));
|
||
});
|
||
}
|
||
clear(color) {
|
||
this.gl.clearColor(color.r, color.g, color.b, color.a);
|
||
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
||
this.textCtx.clearRect(0, 0, this.worldSize.x, this.worldSize.y);
|
||
}
|
||
renderNode(node) {
|
||
// Calculate the origin of the viewport according to this sprite
|
||
this.origin = this.scene.getViewTranslation(node);
|
||
// Get the zoom level of the scene
|
||
this.zoom = this.scene.getViewScale();
|
||
if (node.hasCustomShader) {
|
||
// If the node has a custom shader, render using that
|
||
this.renderCustom(node);
|
||
}
|
||
else if (node instanceof Graphic_1.default) {
|
||
this.renderGraphic(node);
|
||
}
|
||
else if (node instanceof Sprite_1.default) {
|
||
if (node instanceof AnimatedSprite_1.default) {
|
||
this.renderAnimatedSprite(node);
|
||
}
|
||
else {
|
||
this.renderSprite(node);
|
||
}
|
||
}
|
||
else if (node instanceof UIElement_1.default) {
|
||
this.renderUIElement(node);
|
||
}
|
||
}
|
||
renderSprite(sprite) {
|
||
let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.SPRITE_SHADER);
|
||
let options = this.addOptions(shader.getOptions(sprite), sprite);
|
||
shader.render(this.gl, options);
|
||
}
|
||
renderAnimatedSprite(sprite) {
|
||
let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.SPRITE_SHADER);
|
||
let options = this.addOptions(shader.getOptions(sprite), sprite);
|
||
shader.render(this.gl, options);
|
||
}
|
||
renderGraphic(graphic) {
|
||
if (graphic instanceof Point_1.default) {
|
||
let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.POINT_SHADER);
|
||
let options = this.addOptions(shader.getOptions(graphic), graphic);
|
||
shader.render(this.gl, options);
|
||
}
|
||
else if (graphic instanceof Rect_1.default) {
|
||
let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.RECT_SHADER);
|
||
let options = this.addOptions(shader.getOptions(graphic), graphic);
|
||
shader.render(this.gl, options);
|
||
}
|
||
}
|
||
renderTilemap(tilemap) {
|
||
throw new Error("Method not implemented.");
|
||
}
|
||
renderUIElement(uiElement) {
|
||
if (uiElement instanceof Label_1.default) {
|
||
let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.LABEL_SHADER);
|
||
let options = this.addOptions(shader.getOptions(uiElement), uiElement);
|
||
shader.render(this.gl, options);
|
||
this.textCtx.setTransform(1, 0, 0, 1, (uiElement.position.x - this.origin.x) * this.zoom, (uiElement.position.y - this.origin.y) * this.zoom);
|
||
this.textCtx.rotate(-uiElement.rotation);
|
||
let globalAlpha = this.textCtx.globalAlpha;
|
||
this.textCtx.globalAlpha = uiElement.alpha;
|
||
// Render text
|
||
this.textCtx.font = uiElement.getFontString();
|
||
let offset = uiElement.calculateTextOffset(this.textCtx);
|
||
this.textCtx.fillStyle = uiElement.calculateTextColor();
|
||
this.textCtx.globalAlpha = uiElement.textColor.a;
|
||
this.textCtx.fillText(uiElement.text, offset.x - uiElement.size.x / 2, offset.y - uiElement.size.y / 2);
|
||
this.textCtx.globalAlpha = globalAlpha;
|
||
this.textCtx.setTransform(1, 0, 0, 1, 0, 0);
|
||
}
|
||
}
|
||
renderCustom(node) {
|
||
let shader = RegistryManager_1.default.shaders.get(node.customShaderKey);
|
||
let options = this.addOptions(shader.getOptions(node), node);
|
||
shader.render(this.gl, options);
|
||
}
|
||
addOptions(options, node) {
|
||
// Give the shader access to the world size
|
||
options.worldSize = this.worldSize;
|
||
// Adjust the origin position to the parallax
|
||
let layer = node.getLayer();
|
||
let parallax = new Vec2_1.default(1, 1);
|
||
if (layer instanceof ParallaxLayer_1.default) {
|
||
parallax = layer.parallax;
|
||
}
|
||
options.origin = this.origin.clone().mult(parallax);
|
||
return options;
|
||
}
|
||
}
|
||
exports.default = WebGLRenderer;
|
||
|
||
},{"../DataTypes/Vec2":24,"../Nodes/Graphic":41,"../Nodes/Graphics/Point":45,"../Nodes/Graphics/Rect":46,"../Nodes/Sprites/AnimatedSprite":47,"../Nodes/Sprites/Sprite":48,"../Nodes/UIElement":51,"../Nodes/UIElements/Label":53,"../Registry/Registries/ShaderRegistry":64,"../Registry/RegistryManager":65,"../ResourceManager/ResourceManager":83,"../Scene/Layers/ParallaxLayer":88,"./RenderingManager":75}],77:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
/**
|
||
* A wrapper class for WebGL shaders.
|
||
* This class is a singleton, and there is only one for each shader type.
|
||
* All objects that use this shader type will refer to and modify this same type.
|
||
*/
|
||
class ShaderType {
|
||
constructor(programKey) {
|
||
this.programKey = programKey;
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
/**
|
||
* Extracts the options from the CanvasNode and gives them to the render function
|
||
* @param node The node to get options from
|
||
* @returns An object containing the options that should be passed to the render function
|
||
*/
|
||
getOptions(node) { return {}; }
|
||
}
|
||
exports.default = ShaderType;
|
||
|
||
},{"../../ResourceManager/ResourceManager":83}],78:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Mat4x4_1 = require("../../../DataTypes/Mat4x4");
|
||
const Vec2_1 = require("../../../DataTypes/Vec2");
|
||
const ResourceManager_1 = require("../../../ResourceManager/ResourceManager");
|
||
const QuadShaderType_1 = require("./QuadShaderType");
|
||
/** */
|
||
class LabelShaderType extends QuadShaderType_1.default {
|
||
constructor(programKey) {
|
||
super(programKey);
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
initBufferObject() {
|
||
this.bufferObjectKey = "label";
|
||
this.resourceManager.createBuffer(this.bufferObjectKey);
|
||
}
|
||
render(gl, options) {
|
||
const backgroundColor = options.backgroundColor.toWebGL();
|
||
const borderColor = options.borderColor.toWebGL();
|
||
const program = this.resourceManager.getShaderProgram(this.programKey);
|
||
const buffer = this.resourceManager.getBuffer(this.bufferObjectKey);
|
||
gl.useProgram(program);
|
||
const vertexData = this.getVertices(options.size.x, options.size.y);
|
||
const FSIZE = vertexData.BYTES_PER_ELEMENT;
|
||
// Bind the buffer
|
||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
|
||
// Attributes
|
||
const a_Position = gl.getAttribLocation(program, "a_Position");
|
||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 2 * FSIZE, 0 * FSIZE);
|
||
gl.enableVertexAttribArray(a_Position);
|
||
// Uniforms
|
||
const u_BackgroundColor = gl.getUniformLocation(program, "u_BackgroundColor");
|
||
gl.uniform4fv(u_BackgroundColor, backgroundColor);
|
||
const u_BorderColor = gl.getUniformLocation(program, "u_BorderColor");
|
||
gl.uniform4fv(u_BorderColor, borderColor);
|
||
const u_MaxSize = gl.getUniformLocation(program, "u_MaxSize");
|
||
gl.uniform2f(u_MaxSize, -vertexData[0], vertexData[1]);
|
||
// Get transformation matrix
|
||
// We want a square for our rendering space, so get the maximum dimension of our quad
|
||
let maxDimension = Math.max(options.size.x, options.size.y);
|
||
const u_BorderWidth = gl.getUniformLocation(program, "u_BorderWidth");
|
||
gl.uniform1f(u_BorderWidth, options.borderWidth / maxDimension);
|
||
const u_BorderRadius = gl.getUniformLocation(program, "u_BorderRadius");
|
||
gl.uniform1f(u_BorderRadius, options.borderRadius / maxDimension);
|
||
// The size of the rendering space will be a square with this maximum dimension
|
||
let size = new Vec2_1.default(maxDimension, maxDimension).scale(2 / options.worldSize.x, 2 / options.worldSize.y);
|
||
// Center our translations around (0, 0)
|
||
const translateX = (options.position.x - options.origin.x - options.worldSize.x / 2) / maxDimension;
|
||
const translateY = -(options.position.y - options.origin.y - options.worldSize.y / 2) / maxDimension;
|
||
// Create our transformation matrix
|
||
this.translation.translate(new Float32Array([translateX, translateY]));
|
||
this.scale.scale(size);
|
||
this.rotation.rotate(options.rotation);
|
||
let transformation = Mat4x4_1.default.MULT(this.translation, this.scale, this.rotation);
|
||
// Pass the translation matrix to our shader
|
||
const u_Transform = gl.getUniformLocation(program, "u_Transform");
|
||
gl.uniformMatrix4fv(u_Transform, false, transformation.toArray());
|
||
// Draw the quad
|
||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||
}
|
||
/**
|
||
* The rendering space always has to be a square, so make sure its square w.r.t to the largest dimension
|
||
* @param w The width of the quad in pixels
|
||
* @param h The height of the quad in pixels
|
||
* @returns An array of the vertices of the quad
|
||
*/
|
||
getVertices(w, h) {
|
||
let x, y;
|
||
if (h > w) {
|
||
y = 0.5;
|
||
x = w / (2 * h);
|
||
}
|
||
else {
|
||
x = 0.5;
|
||
y = h / (2 * w);
|
||
}
|
||
return new Float32Array([
|
||
-x, y,
|
||
-x, -y,
|
||
x, y,
|
||
x, -y
|
||
]);
|
||
}
|
||
getOptions(rect) {
|
||
let options = {
|
||
position: rect.position,
|
||
backgroundColor: rect.calculateBackgroundColor(),
|
||
borderColor: rect.calculateBorderColor(),
|
||
borderWidth: rect.borderWidth,
|
||
borderRadius: rect.borderRadius,
|
||
size: rect.size,
|
||
rotation: rect.rotation
|
||
};
|
||
return options;
|
||
}
|
||
}
|
||
exports.default = LabelShaderType;
|
||
|
||
},{"../../../DataTypes/Mat4x4":11,"../../../DataTypes/Vec2":24,"../../../ResourceManager/ResourceManager":83,"./QuadShaderType":80}],79:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const RenderingUtils_1 = require("../../../Utils/RenderingUtils");
|
||
const ShaderType_1 = require("../ShaderType");
|
||
class PointShaderType extends ShaderType_1.default {
|
||
constructor(programKey) {
|
||
super(programKey);
|
||
}
|
||
initBufferObject() {
|
||
this.bufferObjectKey = "point";
|
||
this.resourceManager.createBuffer(this.bufferObjectKey);
|
||
}
|
||
render(gl, options) {
|
||
let position = RenderingUtils_1.default.toWebGLCoords(options.position, options.origin, options.worldSize);
|
||
let color = RenderingUtils_1.default.toWebGLColor(options.color);
|
||
const program = this.resourceManager.getShaderProgram(this.programKey);
|
||
const buffer = this.resourceManager.getBuffer(this.bufferObjectKey);
|
||
gl.useProgram(program);
|
||
const vertexData = position;
|
||
const FSIZE = vertexData.BYTES_PER_ELEMENT;
|
||
// Bind the buffer
|
||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
|
||
// Attributes
|
||
const a_Position = gl.getAttribLocation(program, "a_Position");
|
||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 2 * FSIZE, 0 * FSIZE);
|
||
gl.enableVertexAttribArray(a_Position);
|
||
// Uniforms
|
||
const u_Color = gl.getUniformLocation(program, "u_Color");
|
||
gl.uniform4fv(u_Color, color);
|
||
const u_PointSize = gl.getUniformLocation(program, "u_PointSize");
|
||
gl.uniform1f(u_PointSize, options.pointSize);
|
||
gl.drawArrays(gl.POINTS, 0, 1);
|
||
}
|
||
getOptions(point) {
|
||
let options = {
|
||
position: point.position,
|
||
color: point.color,
|
||
pointSize: point.size,
|
||
};
|
||
return options;
|
||
}
|
||
}
|
||
exports.default = PointShaderType;
|
||
|
||
},{"../../../Utils/RenderingUtils":103,"../ShaderType":77}],80:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Mat4x4_1 = require("../../../DataTypes/Mat4x4");
|
||
const ShaderType_1 = require("../ShaderType");
|
||
/** Represents any WebGL objects that have a quad mesh (i.e. a rectangular game object composed of only two triangles) */
|
||
class QuadShaderType extends ShaderType_1.default {
|
||
constructor(programKey) {
|
||
super(programKey);
|
||
this.scale = Mat4x4_1.default.IDENTITY;
|
||
this.rotation = Mat4x4_1.default.IDENTITY;
|
||
this.translation = Mat4x4_1.default.IDENTITY;
|
||
}
|
||
}
|
||
exports.default = QuadShaderType;
|
||
|
||
},{"../../../DataTypes/Mat4x4":11,"../ShaderType":77}],81:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Mat4x4_1 = require("../../../DataTypes/Mat4x4");
|
||
const Vec2_1 = require("../../../DataTypes/Vec2");
|
||
const ResourceManager_1 = require("../../../ResourceManager/ResourceManager");
|
||
const QuadShaderType_1 = require("./QuadShaderType");
|
||
/** */
|
||
class RectShaderType extends QuadShaderType_1.default {
|
||
constructor(programKey) {
|
||
super(programKey);
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
initBufferObject() {
|
||
this.bufferObjectKey = "rect";
|
||
this.resourceManager.createBuffer(this.bufferObjectKey);
|
||
}
|
||
render(gl, options) {
|
||
const color = options.color.toWebGL();
|
||
const program = this.resourceManager.getShaderProgram(this.programKey);
|
||
const buffer = this.resourceManager.getBuffer(this.bufferObjectKey);
|
||
gl.useProgram(program);
|
||
const vertexData = this.getVertices(options.size.x, options.size.y);
|
||
const FSIZE = vertexData.BYTES_PER_ELEMENT;
|
||
// Bind the buffer
|
||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
|
||
// Attributes
|
||
const a_Position = gl.getAttribLocation(program, "a_Position");
|
||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 2 * FSIZE, 0 * FSIZE);
|
||
gl.enableVertexAttribArray(a_Position);
|
||
// Uniforms
|
||
const u_Color = gl.getUniformLocation(program, "u_Color");
|
||
gl.uniform4fv(u_Color, color);
|
||
// Get transformation matrix
|
||
// We want a square for our rendering space, so get the maximum dimension of our quad
|
||
let maxDimension = Math.max(options.size.x, options.size.y);
|
||
// The size of the rendering space will be a square with this maximum dimension
|
||
let size = new Vec2_1.default(maxDimension, maxDimension).scale(2 / options.worldSize.x, 2 / options.worldSize.y);
|
||
// Center our translations around (0, 0)
|
||
const translateX = (options.position.x - options.origin.x - options.worldSize.x / 2) / maxDimension;
|
||
const translateY = -(options.position.y - options.origin.y - options.worldSize.y / 2) / maxDimension;
|
||
// Create our transformation matrix
|
||
this.translation.translate(new Float32Array([translateX, translateY]));
|
||
this.scale.scale(size);
|
||
this.rotation.rotate(options.rotation);
|
||
let transformation = Mat4x4_1.default.MULT(this.translation, this.scale, this.rotation);
|
||
// Pass the translation matrix to our shader
|
||
const u_Transform = gl.getUniformLocation(program, "u_Transform");
|
||
gl.uniformMatrix4fv(u_Transform, false, transformation.toArray());
|
||
// Draw the quad
|
||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||
}
|
||
/*
|
||
So as it turns out, WebGL has an issue with non-square quads.
|
||
It doesn't like when you don't have a 1-1 scale, and rotations are entirely messed up if this is not the case.
|
||
To solve this, I used the scale of the LARGEST dimension of the quad to make a square, then adjusted the vertex coordinates inside of that.
|
||
A diagram of the solution follows.
|
||
|
||
There is a bounding square for the quad with dimensions hxh (in this case, since height is the largest dimension).
|
||
The offset in the vertical direction is therefore 0.5, as it is normally.
|
||
However, the offset in the horizontal direction is not so straightforward, but isn't conceptually hard.
|
||
All we really have to do is a range change from [0, height/2] to [0, 0.5], where our value is t = width/2, and 0 <= t <= height/2.
|
||
|
||
So now we have our rect, in a space scaled with respect to the largest dimension.
|
||
Rotations work as you would expect, even for long rectangles.
|
||
|
||
0.5
|
||
__ __ __ __ __ __ __
|
||
| |88888888888| |
|
||
| |88888888888| |
|
||
| |88888888888| |
|
||
-0.5|_ _|88888888888|_ _|0.5
|
||
| |88888888888| |
|
||
| |88888888888| |
|
||
| |88888888888| |
|
||
|___|88888888888|___|
|
||
-0.5
|
||
|
||
The getVertices function below does as described, and converts the range
|
||
*/
|
||
/**
|
||
* The rendering space always has to be a square, so make sure its square w.r.t to the largest dimension
|
||
* @param w The width of the quad in pixels
|
||
* @param h The height of the quad in pixels
|
||
* @returns An array of the vertices of the quad
|
||
*/
|
||
getVertices(w, h) {
|
||
let x, y;
|
||
if (h > w) {
|
||
y = 0.5;
|
||
x = w / (2 * h);
|
||
}
|
||
else {
|
||
x = 0.5;
|
||
y = h / (2 * w);
|
||
}
|
||
return new Float32Array([
|
||
-x, y,
|
||
-x, -y,
|
||
x, y,
|
||
x, -y
|
||
]);
|
||
}
|
||
getOptions(rect) {
|
||
let options = {
|
||
position: rect.position,
|
||
color: rect.color,
|
||
size: rect.size,
|
||
rotation: rect.rotation
|
||
};
|
||
return options;
|
||
}
|
||
}
|
||
exports.default = RectShaderType;
|
||
|
||
},{"../../../DataTypes/Mat4x4":11,"../../../DataTypes/Vec2":24,"../../../ResourceManager/ResourceManager":83,"./QuadShaderType":80}],82:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Mat4x4_1 = require("../../../DataTypes/Mat4x4");
|
||
const Vec2_1 = require("../../../DataTypes/Vec2");
|
||
const AnimatedSprite_1 = require("../../../Nodes/Sprites/AnimatedSprite");
|
||
const ResourceManager_1 = require("../../../ResourceManager/ResourceManager");
|
||
const QuadShaderType_1 = require("./QuadShaderType");
|
||
/** A shader for sprites and animated sprites */
|
||
class SpriteShaderType extends QuadShaderType_1.default {
|
||
constructor(programKey) {
|
||
super(programKey);
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
initBufferObject() {
|
||
this.bufferObjectKey = "sprite";
|
||
this.resourceManager.createBuffer(this.bufferObjectKey);
|
||
}
|
||
render(gl, options) {
|
||
const program = this.resourceManager.getShaderProgram(this.programKey);
|
||
const buffer = this.resourceManager.getBuffer(this.bufferObjectKey);
|
||
const texture = this.resourceManager.getTexture(options.imageKey);
|
||
gl.useProgram(program);
|
||
const vertexData = this.getVertices(options.size.x, options.size.y, options.scale);
|
||
const FSIZE = vertexData.BYTES_PER_ELEMENT;
|
||
// Bind the buffer
|
||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
|
||
// Attributes
|
||
const a_Position = gl.getAttribLocation(program, "a_Position");
|
||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0 * FSIZE);
|
||
gl.enableVertexAttribArray(a_Position);
|
||
const a_TexCoord = gl.getAttribLocation(program, "a_TexCoord");
|
||
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE);
|
||
gl.enableVertexAttribArray(a_TexCoord);
|
||
// Uniforms
|
||
// Get transformation matrix
|
||
// We want a square for our rendering space, so get the maximum dimension of our quad
|
||
let maxDimension = Math.max(options.size.x, options.size.y);
|
||
// The size of the rendering space will be a square with this maximum dimension
|
||
let size = new Vec2_1.default(maxDimension, maxDimension).scale(2 / options.worldSize.x, 2 / options.worldSize.y);
|
||
// Center our translations around (0, 0)
|
||
const translateX = (options.position.x - options.origin.x - options.worldSize.x / 2) / maxDimension;
|
||
const translateY = -(options.position.y - options.origin.y - options.worldSize.y / 2) / maxDimension;
|
||
// Create our transformation matrix
|
||
this.translation.translate(new Float32Array([translateX, translateY]));
|
||
this.scale.scale(size);
|
||
this.rotation.rotate(options.rotation);
|
||
let transformation = Mat4x4_1.default.MULT(this.translation, this.scale, this.rotation);
|
||
// Pass the translation matrix to our shader
|
||
const u_Transform = gl.getUniformLocation(program, "u_Transform");
|
||
gl.uniformMatrix4fv(u_Transform, false, transformation.toArray());
|
||
// Set up our sampler with our assigned texture unit
|
||
const u_Sampler = gl.getUniformLocation(program, "u_Sampler");
|
||
gl.uniform1i(u_Sampler, texture);
|
||
// Pass in texShift
|
||
const u_texShift = gl.getUniformLocation(program, "u_texShift");
|
||
gl.uniform2fv(u_texShift, options.texShift);
|
||
// Pass in texScale
|
||
const u_texScale = gl.getUniformLocation(program, "u_texScale");
|
||
gl.uniform2fv(u_texScale, options.texScale);
|
||
// Draw the quad
|
||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||
}
|
||
/**
|
||
* The rendering space always has to be a square, so make sure its square w.r.t to the largest dimension
|
||
* @param w The width of the quad in pixels
|
||
* @param h The height of the quad in pixels
|
||
* @returns An array of the vertices of the quad
|
||
*/
|
||
getVertices(w, h, scale) {
|
||
let x, y;
|
||
if (h > w) {
|
||
y = 0.5;
|
||
x = w / (2 * h);
|
||
}
|
||
else {
|
||
x = 0.5;
|
||
y = h / (2 * w);
|
||
}
|
||
// Scale the rendering space if needed
|
||
x *= scale[0];
|
||
y *= scale[1];
|
||
return new Float32Array([
|
||
-x, y, 0.0, 0.0,
|
||
-x, -y, 0.0, 1.0,
|
||
x, y, 1.0, 0.0,
|
||
x, -y, 1.0, 1.0
|
||
]);
|
||
}
|
||
getOptions(sprite) {
|
||
let texShift;
|
||
let texScale;
|
||
if (sprite instanceof AnimatedSprite_1.default) {
|
||
let animationIndex = sprite.animation.getIndexAndAdvanceAnimation();
|
||
let offset = sprite.getAnimationOffset(animationIndex);
|
||
texShift = new Float32Array([offset.x / (sprite.cols * sprite.size.x), offset.y / (sprite.rows * sprite.size.y)]);
|
||
texScale = new Float32Array([1 / (sprite.cols), 1 / (sprite.rows)]);
|
||
}
|
||
else {
|
||
texShift = new Float32Array([0, 0]);
|
||
texScale = new Float32Array([1, 1]);
|
||
}
|
||
let options = {
|
||
position: sprite.position,
|
||
rotation: sprite.rotation,
|
||
size: sprite.size,
|
||
scale: sprite.scale.toArray(),
|
||
imageKey: sprite.imageId,
|
||
texShift,
|
||
texScale
|
||
};
|
||
return options;
|
||
}
|
||
}
|
||
exports.default = SpriteShaderType;
|
||
|
||
},{"../../../DataTypes/Mat4x4":11,"../../../DataTypes/Vec2":24,"../../../Nodes/Sprites/AnimatedSprite":47,"../../../ResourceManager/ResourceManager":83,"./QuadShaderType":80}],83:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const Queue_1 = require("../DataTypes/Queue");
|
||
const StringUtils_1 = require("../Utils/StringUtils");
|
||
const AudioManager_1 = require("../Sound/AudioManager");
|
||
const WebGLProgramType_1 = require("../DataTypes/Rendering/WebGLProgramType");
|
||
/**
|
||
* The resource manager for the game engine.
|
||
* The resource manager interfaces with the loadable assets of a game such as images, data files,
|
||
* and sounds, which are all found in the dist folder.
|
||
* This class controls loading and updates the @reference[Scene] with the loading progress, so that the scene does
|
||
* not start before all necessary assets are loaded.
|
||
*/
|
||
class ResourceManager {
|
||
constructor() {
|
||
this.loading = false;
|
||
this.justLoaded = false;
|
||
this.loadonly_imagesLoaded = 0;
|
||
this.loadonly_imagesToLoad = 0;
|
||
this.loadonly_imageLoadingQueue = new Queue_1.default();
|
||
this.images = new Map_1.default();
|
||
this.loadonly_spritesheetsLoaded = 0;
|
||
this.loadonly_spritesheetsToLoad = 0;
|
||
this.loadonly_spritesheetLoadingQueue = new Queue_1.default();
|
||
this.spritesheets = new Map_1.default();
|
||
this.loadonly_tilemapsLoaded = 0;
|
||
this.loadonly_tilemapsToLoad = 0;
|
||
this.loadonly_tilemapLoadingQueue = new Queue_1.default();
|
||
this.tilemaps = new Map_1.default();
|
||
this.loadonly_audioLoaded = 0;
|
||
this.loadonly_audioToLoad = 0;
|
||
this.loadonly_audioLoadingQueue = new Queue_1.default();
|
||
this.audioBuffers = new Map_1.default();
|
||
this.loadonly_jsonLoaded = 0;
|
||
this.loadonly_jsonToLoad = 0;
|
||
this.loadonly_jsonLoadingQueue = new Queue_1.default();
|
||
this.jsonObjects = new Map_1.default();
|
||
this.loadonly_gl_ShaderProgramsLoaded = 0;
|
||
this.loadonly_gl_ShaderProgramsToLoad = 0;
|
||
this.loadonly_gl_ShaderLoadingQueue = new Queue_1.default();
|
||
this.gl_ShaderPrograms = new Map_1.default();
|
||
this.gl_Textures = new Map_1.default();
|
||
this.gl_NextTextureID = 0;
|
||
this.gl_Buffers = new Map_1.default();
|
||
this.resourcesToUnload = new Array();
|
||
this.resourcesToKeep = new Array();
|
||
this.loadonly_tilemapObjectToLoad = 0;
|
||
this.loadonly_tilemapObjectToLoad = 0;
|
||
this.loadonly_tilemapObjectLoadingQueue = new Queue_1.default();
|
||
}
|
||
;
|
||
/* ######################################## SINGLETON ########################################*/
|
||
/**
|
||
* Returns the current instance of this class or a new instance if none exist
|
||
* @returns The resource manager
|
||
*/
|
||
static getInstance() {
|
||
if (!this.instance) {
|
||
this.instance = new ResourceManager();
|
||
}
|
||
return this.instance;
|
||
}
|
||
/* ######################################## PUBLIC FUNCTION ########################################*/
|
||
/**
|
||
* Activates or deactivates the use of WebGL
|
||
* @param flag True if WebGL should be used, false otherwise
|
||
* @param gl The instance of the graphics context, if applicable
|
||
*/
|
||
useWebGL(flag, gl) {
|
||
this.gl_WebGLActive = flag;
|
||
if (this.gl_WebGLActive) {
|
||
this.gl = gl;
|
||
}
|
||
}
|
||
/**
|
||
* Loads an image from file
|
||
* @param key The key to associate the loaded image with
|
||
* @param path The path to the image to load
|
||
*/
|
||
image(key, path) {
|
||
this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path });
|
||
}
|
||
/**
|
||
* Tells the resource manager to keep this resource
|
||
* @param key The key of the resource
|
||
*/
|
||
keepImage(key) {
|
||
this.keepResource(key, ResourceType.IMAGE);
|
||
}
|
||
/**
|
||
* Retrieves a loaded image
|
||
* @param key The key of the loaded image
|
||
* @returns The image element associated with this key
|
||
*/
|
||
getImage(key) {
|
||
let image = this.images.get(key);
|
||
// if (image === undefined) {
|
||
// throw `There is no image associated with key "${key}"`
|
||
// }
|
||
return image;
|
||
}
|
||
/**
|
||
* Loads a spritesheet from file
|
||
* @param key The key to associate the loaded spritesheet with
|
||
* @param path The path to the spritesheet to load
|
||
*/
|
||
spritesheet(key, path) {
|
||
this.loadonly_spritesheetLoadingQueue.enqueue({ key: key, path: path });
|
||
}
|
||
/**
|
||
* Tells the resource manager to keep this resource
|
||
* @param key The key of the resource
|
||
*/
|
||
keepSpritesheet(key) {
|
||
this.keepResource(key, ResourceType.SPRITESHEET);
|
||
}
|
||
/**
|
||
* Retrieves a loaded spritesheet
|
||
* @param key The key of the spritesheet to load
|
||
* @returns The loaded Spritesheet
|
||
*/
|
||
getSpritesheet(key) {
|
||
return this.spritesheets.get(key);
|
||
}
|
||
/**
|
||
* Loads an audio file
|
||
* @param key The key to associate with the loaded audio file
|
||
* @param path The path to the audio file to load
|
||
*/
|
||
audio(key, path) {
|
||
this.loadonly_audioLoadingQueue.enqueue({ key: key, path: path });
|
||
}
|
||
/**
|
||
* Tells the resource manager to keep this resource
|
||
* @param key The key of the resource
|
||
*/
|
||
keepAudio(key) {
|
||
this.keepResource(key, ResourceType.AUDIO);
|
||
}
|
||
/**
|
||
* Retrieves a loaded audio file
|
||
* @param key The key of the audio file to load
|
||
* @returns The AudioBuffer created from the loaded audio fle
|
||
*/
|
||
getAudio(key) {
|
||
return this.audioBuffers.get(key);
|
||
}
|
||
/**
|
||
* Load a tilemap from a json file. Automatically loads related images
|
||
* @param key The key to associate with the loaded tilemap
|
||
* @param path The path to the tilemap to load
|
||
*/
|
||
tilemap(key, path) {
|
||
this.loadonly_tilemapLoadingQueue.enqueue({ key: key, path: path });
|
||
}
|
||
/**
|
||
* Tells the resource manager to keep this resource
|
||
* @param key The key of the resource
|
||
*/
|
||
keepTilemap(key) {
|
||
this.keepResource(key, ResourceType.TILEMAP);
|
||
}
|
||
/**
|
||
* Retreives a loaded tilemap
|
||
* @param key The key of the loaded tilemap
|
||
* @returns The tilemap data associated with the key
|
||
*/
|
||
getTilemap(key) {
|
||
return this.tilemaps.get(key);
|
||
}
|
||
/**
|
||
* Loads an object from a json file.
|
||
* @param key The key to associate with the loaded object
|
||
* @param path The path to the json file to load
|
||
*/
|
||
object(key, path) {
|
||
this.loadonly_jsonLoadingQueue.enqueue({ key: key, path: path });
|
||
}
|
||
/**
|
||
* Tells the resource manager to keep this resource
|
||
* @param key The key of the resource
|
||
*/
|
||
keepObject(key) {
|
||
this.keepResource(key, ResourceType.JSON);
|
||
}
|
||
/**
|
||
* Retreives a loaded object
|
||
* @param key The key of the loaded object
|
||
* @returns The object data associated with the key
|
||
*/
|
||
getObject(key) {
|
||
return this.jsonObjects.get(key);
|
||
}
|
||
/* ######################################## LOAD FUNCTION ########################################*/
|
||
/**
|
||
* Loads all resources currently in the queue
|
||
* @param callback The function to cal when the resources are finished loading
|
||
*/
|
||
loadResourcesFromQueue(callback) {
|
||
this.loadonly_typesToLoad = 5;
|
||
this.loading = true;
|
||
// Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue
|
||
this.loadTilemapObjectFromQueue(() => {
|
||
console.log("Loaded TilemapObjects");
|
||
this.loadTilemapsFromQueue(() => {
|
||
console.log("Loaded Tilemaps");
|
||
this.loadSpritesheetsFromQueue(() => {
|
||
console.log("Loaded Spritesheets");
|
||
this.loadImagesFromQueue(() => {
|
||
console.log("Loaded Images");
|
||
this.loadAudioFromQueue(() => {
|
||
console.log("Loaded Audio");
|
||
this.loadObjectsFromQueue(() => {
|
||
console.log("Loaded Objects");
|
||
if (this.gl_WebGLActive) {
|
||
this.gl_LoadShadersFromQueue(() => {
|
||
console.log("Loaded Shaders");
|
||
this.finishLoading(callback);
|
||
});
|
||
}
|
||
else {
|
||
this.finishLoading(callback);
|
||
}
|
||
});
|
||
});
|
||
});
|
||
});
|
||
});
|
||
});
|
||
}
|
||
finishLoading(callback) {
|
||
// Done loading
|
||
this.loading = false;
|
||
this.justLoaded = true;
|
||
callback();
|
||
}
|
||
/* ######################################## UNLOAD FUNCTION ########################################*/
|
||
keepResource(key, type) {
|
||
console.log("Keep resource...");
|
||
for (let i = 0; i < this.resourcesToUnload.length; i++) {
|
||
let resource = this.resourcesToUnload[i];
|
||
if (resource.key === key && resource.resourceType === type) {
|
||
console.log("Found resource " + key + " of type " + type + ". Keeping.");
|
||
let resourceToMove = this.resourcesToUnload.splice(i, 1);
|
||
this.resourcesToKeep.push(...resourceToMove);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Deletes references to all resources in the resource manager
|
||
*/
|
||
unloadAllResources() {
|
||
this.loading = false;
|
||
this.justLoaded = false;
|
||
for (let resource of this.resourcesToUnload) {
|
||
// Unload the resource
|
||
this.unloadResource(resource);
|
||
}
|
||
}
|
||
unloadResource(resource) {
|
||
// Delete the resource itself
|
||
switch (resource.resourceType) {
|
||
case ResourceType.IMAGE:
|
||
this.images.delete(resource.key);
|
||
if (this.gl_WebGLActive) {
|
||
this.gl_Textures.delete(resource.key);
|
||
}
|
||
break;
|
||
case ResourceType.TILEMAP:
|
||
this.tilemaps.delete(resource.key);
|
||
break;
|
||
case ResourceType.SPRITESHEET:
|
||
this.spritesheets.delete(resource.key);
|
||
break;
|
||
case ResourceType.AUDIO:
|
||
this.audioBuffers.delete(resource.key);
|
||
break;
|
||
case ResourceType.JSON:
|
||
this.jsonObjects.delete(resource.key);
|
||
break;
|
||
/*case ResourceType.SHADER:
|
||
this.gl_ShaderPrograms.get(resource.key).delete(this.gl);
|
||
this.gl_ShaderPrograms.delete(resource.key);
|
||
break;*/
|
||
}
|
||
// Delete any dependencies
|
||
for (let dependency of resource.dependencies) {
|
||
this.unloadResource(dependency);
|
||
}
|
||
}
|
||
/* ######################################## WORK FUNCTIONS ########################################*/
|
||
/**
|
||
* Loads all tilemaps currently in the tilemap loading queue
|
||
* @param onFinishLoading The function to call when loading is complete
|
||
*/
|
||
loadTilemapsFromQueue(onFinishLoading) {
|
||
this.loadonly_tilemapsToLoad = this.loadonly_tilemapLoadingQueue.getSize();
|
||
this.loadonly_tilemapsLoaded = 0;
|
||
// If no items to load, we're finished
|
||
if (this.loadonly_tilemapsToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_tilemapLoadingQueue.hasItems()) {
|
||
let tilemap = this.loadonly_tilemapLoadingQueue.dequeue();
|
||
this.loadTilemap(tilemap.key, tilemap.path, onFinishLoading);
|
||
}
|
||
}
|
||
/**
|
||
* Loads a singular tilemap
|
||
* @param key The key of the tilemap
|
||
* @param pathToTilemapJSON The path to the tilemap JSON file
|
||
* @param callbackIfLast The function to call if this is the last tilemap to load
|
||
*/
|
||
loadTilemap(key, pathToTilemapJSON, callbackIfLast) {
|
||
this.loadTextFile(pathToTilemapJSON, (fileText) => {
|
||
let tilemapObject = JSON.parse(fileText);
|
||
// We can parse the object later - it's much faster than loading
|
||
this.tilemaps.add(key, tilemapObject);
|
||
let resource = new ResourceReference(key, ResourceType.TILEMAP);
|
||
// Grab the tileset images we need to load and add them to the imageloading queue
|
||
for (let tileset of tilemapObject.tilesets) {
|
||
if (tileset.image) {
|
||
let key = tileset.image;
|
||
let path = StringUtils_1.default.getPathFromFilePath(pathToTilemapJSON) + key;
|
||
this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path, isDependency: true });
|
||
// Add this image as a dependency to the tilemap
|
||
resource.addDependency(new ResourceReference(key, ResourceType.IMAGE));
|
||
}
|
||
else if (tileset.tiles) {
|
||
for (let tile of tileset.tiles) {
|
||
let key = tile.image;
|
||
let path = StringUtils_1.default.getPathFromFilePath(pathToTilemapJSON) + key;
|
||
this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path, isDependency: true });
|
||
// Add this image as a dependency to the tilemap
|
||
resource.addDependency(new ResourceReference(key, ResourceType.IMAGE));
|
||
}
|
||
}
|
||
}
|
||
// Add the resource reference to the list of resource to unload
|
||
this.resourcesToUnload.push(resource);
|
||
// Finish loading
|
||
this.finishLoadingTilemap(callbackIfLast);
|
||
});
|
||
}
|
||
/**
|
||
* Finish loading a tilemap. Calls the callback function if this is the last tilemap being loaded
|
||
* @param callback The function to call if this is the last tilemap to load
|
||
*/
|
||
finishLoadingTilemap(callback) {
|
||
this.loadonly_tilemapsLoaded += 1;
|
||
if (this.loadonly_tilemapsLoaded === this.loadonly_tilemapsToLoad) {
|
||
// We're done loading tilemaps
|
||
callback();
|
||
}
|
||
}
|
||
/**
|
||
* Loads all spritesheets currently in the spritesheet loading queue
|
||
* @param onFinishLoading The function to call when the spritesheets are done loading
|
||
*/
|
||
loadSpritesheetsFromQueue(onFinishLoading) {
|
||
this.loadonly_spritesheetsToLoad = this.loadonly_spritesheetLoadingQueue.getSize();
|
||
this.loadonly_spritesheetsLoaded = 0;
|
||
// If no items to load, we're finished
|
||
if (this.loadonly_spritesheetsToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_spritesheetLoadingQueue.hasItems()) {
|
||
let spritesheet = this.loadonly_spritesheetLoadingQueue.dequeue();
|
||
this.loadSpritesheet(spritesheet.key, spritesheet.path, onFinishLoading);
|
||
}
|
||
}
|
||
/**
|
||
* Loads a singular spritesheet
|
||
* @param key The key of the spritesheet to load
|
||
* @param pathToSpritesheetJSON The path to the spritesheet JSON file
|
||
* @param callbackIfLast The function to call if this is the last spritesheet
|
||
*/
|
||
loadSpritesheet(key, pathToSpritesheetJSON, callbackIfLast) {
|
||
this.loadTextFile(pathToSpritesheetJSON, (fileText) => {
|
||
let spritesheet = JSON.parse(fileText);
|
||
// We can parse the object later - it's much faster than loading
|
||
this.spritesheets.add(key, spritesheet);
|
||
let resource = new ResourceReference(key, ResourceType.SPRITESHEET);
|
||
// Grab the image we need to load and add it to the imageloading queue
|
||
let path = StringUtils_1.default.getPathFromFilePath(pathToSpritesheetJSON) + spritesheet.spriteSheetImage;
|
||
this.loadonly_imageLoadingQueue.enqueue({ key: spritesheet.name, path: path, isDependency: true });
|
||
resource.addDependency(new ResourceReference(spritesheet.name, ResourceType.IMAGE));
|
||
this.resourcesToUnload.push(resource);
|
||
// Finish loading
|
||
this.finishLoadingSpritesheet(callbackIfLast);
|
||
});
|
||
}
|
||
/**
|
||
* Finish loading a spritesheet. Calls the callback function if this is the last spritesheet being loaded
|
||
* @param callback The function to call if this is the last spritesheet to load
|
||
*/
|
||
finishLoadingSpritesheet(callback) {
|
||
this.loadonly_spritesheetsLoaded += 1;
|
||
if (this.loadonly_spritesheetsLoaded === this.loadonly_spritesheetsToLoad) {
|
||
// We're done loading spritesheets
|
||
callback();
|
||
}
|
||
}
|
||
/**
|
||
* Loads all images currently in the image loading queue
|
||
* @param onFinishLoading The function to call when there are no more images to load
|
||
*/
|
||
loadImagesFromQueue(onFinishLoading) {
|
||
this.loadonly_imagesToLoad = this.loadonly_imageLoadingQueue.getSize();
|
||
this.loadonly_imagesLoaded = 0;
|
||
// If no items to load, we're finished
|
||
if (this.loadonly_imagesToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_imageLoadingQueue.hasItems()) {
|
||
let image = this.loadonly_imageLoadingQueue.dequeue();
|
||
this.loadImage(image.key, image.path, image.isDependency, onFinishLoading);
|
||
}
|
||
}
|
||
/**
|
||
* Loads a singular image
|
||
* @param key The key of the image to load
|
||
* @param path The path to the image to load
|
||
* @param callbackIfLast The function to call if this is the last image
|
||
*/
|
||
loadImage(key, path, isDependency, callbackIfLast) {
|
||
var image = new Image();
|
||
image.onload = () => {
|
||
// Add to loaded images
|
||
this.images.add(key, image);
|
||
// If not a dependency, push it to the unload list. Otherwise it's managed by something else
|
||
if (!isDependency) {
|
||
this.resourcesToUnload.push(new ResourceReference(key, ResourceType.IMAGE));
|
||
}
|
||
// If WebGL is active, create a texture
|
||
if (this.gl_WebGLActive) {
|
||
this.createWebGLTexture(key, image);
|
||
}
|
||
// Finish image load
|
||
this.finishLoadingImage(callbackIfLast);
|
||
};
|
||
image.src = path;
|
||
}
|
||
/**
|
||
* Finish loading an image. If this is the last image, it calls the callback function
|
||
* @param callback The function to call if this is the last image
|
||
*/
|
||
finishLoadingImage(callback) {
|
||
this.loadonly_imagesLoaded += 1;
|
||
if (this.loadonly_imagesLoaded === this.loadonly_imagesToLoad) {
|
||
// We're done loading images
|
||
callback();
|
||
}
|
||
}
|
||
/**
|
||
* Loads all audio currently in the tilemap loading queue
|
||
* @param onFinishLoading The function to call when tilemaps are done loading
|
||
*/
|
||
loadAudioFromQueue(onFinishLoading) {
|
||
this.loadonly_audioToLoad = this.loadonly_audioLoadingQueue.getSize();
|
||
this.loadonly_audioLoaded = 0;
|
||
// If no items to load, we're finished
|
||
if (this.loadonly_audioToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_audioLoadingQueue.hasItems()) {
|
||
let audio = this.loadonly_audioLoadingQueue.dequeue();
|
||
this.loadAudio(audio.key, audio.path, onFinishLoading);
|
||
}
|
||
}
|
||
/**
|
||
* Load a singular audio file
|
||
* @param key The key to the audio file to load
|
||
* @param path The path to the audio file to load
|
||
* @param callbackIfLast The function to call if this is the last audio file to load
|
||
*/
|
||
loadAudio(key, path, callbackIfLast) {
|
||
let audioCtx = AudioManager_1.default.getInstance().getAudioContext();
|
||
let request = new XMLHttpRequest();
|
||
request.open('GET', path, true);
|
||
request.responseType = 'arraybuffer';
|
||
request.onload = () => {
|
||
audioCtx.decodeAudioData(request.response, (buffer) => {
|
||
// Add to list of audio buffers
|
||
this.audioBuffers.add(key, buffer);
|
||
this.resourcesToUnload.push(new ResourceReference(key, ResourceType.AUDIO));
|
||
// Finish loading sound
|
||
this.finishLoadingAudio(callbackIfLast);
|
||
}, (error) => {
|
||
throw "Error loading sound";
|
||
});
|
||
};
|
||
request.send();
|
||
}
|
||
/**
|
||
* Finish loading an audio file. Calls the callback functon if this is the last audio sample being loaded.
|
||
* @param callback The function to call if this is the last audio file to load
|
||
*/
|
||
finishLoadingAudio(callback) {
|
||
this.loadonly_audioLoaded += 1;
|
||
if (this.loadonly_audioLoaded === this.loadonly_audioToLoad) {
|
||
// We're done loading audio
|
||
callback();
|
||
}
|
||
}
|
||
/**
|
||
* Loads all objects currently in the object loading queue
|
||
* @param onFinishLoading The function to call when there are no more objects to load
|
||
*/
|
||
loadObjectsFromQueue(onFinishLoading) {
|
||
this.loadonly_jsonToLoad = this.loadonly_jsonLoadingQueue.getSize();
|
||
this.loadonly_jsonLoaded = 0;
|
||
// If no items to load, we're finished
|
||
if (this.loadonly_jsonToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_jsonLoadingQueue.hasItems()) {
|
||
let obj = this.loadonly_jsonLoadingQueue.dequeue();
|
||
this.loadObject(obj.key, obj.path, onFinishLoading);
|
||
}
|
||
}
|
||
/**
|
||
* Loads a singular object
|
||
* @param key The key of the object to load
|
||
* @param path The path to the object to load
|
||
* @param callbackIfLast The function to call if this is the last object
|
||
*/
|
||
loadObject(key, path, callbackIfLast) {
|
||
this.loadTextFile(path, (fileText) => {
|
||
let obj = JSON.parse(fileText);
|
||
this.jsonObjects.add(key, obj);
|
||
this.resourcesToUnload.push(new ResourceReference(key, ResourceType.JSON));
|
||
this.finishLoadingObject(callbackIfLast);
|
||
});
|
||
}
|
||
/**
|
||
* Finish loading an object. If this is the last object, it calls the callback function
|
||
* @param callback The function to call if this is the last object
|
||
*/
|
||
finishLoadingObject(callback) {
|
||
this.loadonly_jsonLoaded += 1;
|
||
if (this.loadonly_jsonLoaded === this.loadonly_jsonToLoad) {
|
||
// We're done loading objects
|
||
callback();
|
||
}
|
||
}
|
||
/* ########## WEBGL SPECIFIC FUNCTIONS ########## */
|
||
getTexture(key) {
|
||
return this.gl_Textures.get(key);
|
||
}
|
||
getShaderProgram(key) {
|
||
return this.gl_ShaderPrograms.get(key).program;
|
||
}
|
||
getBuffer(key) {
|
||
return this.gl_Buffers.get(key);
|
||
}
|
||
createWebGLTexture(imageKey, image) {
|
||
// Get the texture ID
|
||
const textureID = this.getTextureID(this.gl_NextTextureID);
|
||
// Create the texture
|
||
const texture = this.gl.createTexture();
|
||
// Set up the texture
|
||
// Enable texture0
|
||
this.gl.activeTexture(textureID);
|
||
// Bind our texture to texture 0
|
||
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
||
// Set the texture parameters
|
||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
||
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
||
// Set the texture image
|
||
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);
|
||
// Add the texture to our map with the same key as the image
|
||
this.gl_Textures.add(imageKey, this.gl_NextTextureID);
|
||
// Increment the key
|
||
this.gl_NextTextureID += 1;
|
||
}
|
||
getTextureID(id) {
|
||
// Start with 9 cases - this can be expanded if needed, but for the best performance,
|
||
// Textures should be stitched into an atlas
|
||
switch (id) {
|
||
case 0: return this.gl.TEXTURE0;
|
||
case 1: return this.gl.TEXTURE1;
|
||
case 2: return this.gl.TEXTURE2;
|
||
case 3: return this.gl.TEXTURE3;
|
||
case 4: return this.gl.TEXTURE4;
|
||
case 5: return this.gl.TEXTURE5;
|
||
case 6: return this.gl.TEXTURE6;
|
||
case 7: return this.gl.TEXTURE7;
|
||
case 8: return this.gl.TEXTURE8;
|
||
default: return this.gl.TEXTURE9;
|
||
}
|
||
}
|
||
createBuffer(key) {
|
||
if (this.gl_WebGLActive) {
|
||
let buffer = this.gl.createBuffer();
|
||
this.gl_Buffers.add(key, buffer);
|
||
}
|
||
}
|
||
/**
|
||
* Enqueues loading of a new shader program
|
||
* @param key The key of the shader program
|
||
* @param vShaderFilepath
|
||
* @param fShaderFilepath
|
||
*/
|
||
shader(key, vShaderFilepath, fShaderFilepath) {
|
||
let splitPath = vShaderFilepath.split(".");
|
||
let end = splitPath[splitPath.length - 1];
|
||
if (end !== "vshader") {
|
||
throw `${vShaderFilepath} is not a valid vertex shader - must end in ".vshader`;
|
||
}
|
||
splitPath = fShaderFilepath.split(".");
|
||
end = splitPath[splitPath.length - 1];
|
||
if (end !== "fshader") {
|
||
throw `${fShaderFilepath} is not a valid vertex shader - must end in ".fshader`;
|
||
}
|
||
let paths = new KeyPath_Shader();
|
||
paths.key = key;
|
||
paths.vpath = vShaderFilepath;
|
||
paths.fpath = fShaderFilepath;
|
||
this.loadonly_gl_ShaderLoadingQueue.enqueue(paths);
|
||
}
|
||
/**
|
||
* Tells the resource manager to keep this resource
|
||
* @param key The key of the resource
|
||
*/
|
||
keepShader(key) {
|
||
this.keepResource(key, ResourceType.IMAGE);
|
||
}
|
||
gl_LoadShadersFromQueue(onFinishLoading) {
|
||
this.loadonly_gl_ShaderProgramsToLoad = this.loadonly_gl_ShaderLoadingQueue.getSize();
|
||
this.loadonly_gl_ShaderProgramsLoaded = 0;
|
||
// If webGL isn'active or there are no items to load, we're finished
|
||
if (!this.gl_WebGLActive || this.loadonly_gl_ShaderProgramsToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_gl_ShaderLoadingQueue.hasItems()) {
|
||
let shader = this.loadonly_gl_ShaderLoadingQueue.dequeue();
|
||
this.gl_LoadShader(shader.key, shader.vpath, shader.fpath, onFinishLoading);
|
||
}
|
||
}
|
||
gl_LoadShader(key, vpath, fpath, callbackIfLast) {
|
||
this.loadTextFile(vpath, (vFileText) => {
|
||
const vShader = vFileText;
|
||
this.loadTextFile(fpath, (fFileText) => {
|
||
const fShader = fFileText;
|
||
// Extract the program and shaders
|
||
const [shaderProgram, vertexShader, fragmentShader] = this.createShaderProgram(vShader, fShader);
|
||
// Create a wrapper type
|
||
const programWrapper = new WebGLProgramType_1.default();
|
||
programWrapper.program = shaderProgram;
|
||
programWrapper.vertexShader = vertexShader;
|
||
programWrapper.fragmentShader = fragmentShader;
|
||
// Add to our map
|
||
this.gl_ShaderPrograms.add(key, programWrapper);
|
||
this.resourcesToUnload.push(new ResourceReference(key, ResourceType.SHADER));
|
||
// Finish loading
|
||
this.gl_FinishLoadingShader(callbackIfLast);
|
||
});
|
||
});
|
||
}
|
||
gl_FinishLoadingShader(callback) {
|
||
this.loadonly_gl_ShaderProgramsLoaded += 1;
|
||
if (this.loadonly_gl_ShaderProgramsLoaded === this.loadonly_gl_ShaderProgramsToLoad) {
|
||
// We're done loading shaders
|
||
callback();
|
||
}
|
||
}
|
||
createShaderProgram(vShaderSource, fShaderSource) {
|
||
const vertexShader = this.loadVertexShader(vShaderSource);
|
||
const fragmentShader = this.loadFragmentShader(fShaderSource);
|
||
if (vertexShader === null || fragmentShader === null) {
|
||
// We had a problem intializing - error
|
||
return null;
|
||
}
|
||
// Create a shader program
|
||
const program = this.gl.createProgram();
|
||
if (!program) {
|
||
// Error creating
|
||
console.warn("Failed to create program");
|
||
return null;
|
||
}
|
||
// Attach our vertex and fragment shader
|
||
this.gl.attachShader(program, vertexShader);
|
||
this.gl.attachShader(program, fragmentShader);
|
||
// Link
|
||
this.gl.linkProgram(program);
|
||
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
||
// Error linking
|
||
const error = this.gl.getProgramInfoLog(program);
|
||
console.warn("Failed to link program: " + error);
|
||
// Clean up
|
||
this.gl.deleteProgram(program);
|
||
this.gl.deleteShader(vertexShader);
|
||
this.gl.deleteShader(fragmentShader);
|
||
return null;
|
||
}
|
||
// We successfully create a program
|
||
return [program, vertexShader, fragmentShader];
|
||
}
|
||
loadVertexShader(shaderSource) {
|
||
// Create a new vertex shader
|
||
return this.loadShader(this.gl.VERTEX_SHADER, shaderSource);
|
||
}
|
||
loadFragmentShader(shaderSource) {
|
||
// Create a new fragment shader
|
||
return this.loadShader(this.gl.FRAGMENT_SHADER, shaderSource);
|
||
}
|
||
loadShader(type, shaderSource) {
|
||
const shader = this.gl.createShader(type);
|
||
// If we couldn't create the shader, error
|
||
if (shader === null) {
|
||
console.warn("Unable to create shader");
|
||
return null;
|
||
}
|
||
// Add the source to the shader and compile
|
||
this.gl.shaderSource(shader, shaderSource);
|
||
this.gl.compileShader(shader);
|
||
// Make sure there were no errors during this process
|
||
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
||
// Not compiled - error
|
||
const error = this.gl.getShaderInfoLog(shader);
|
||
console.warn("Failed to compile shader: " + error);
|
||
// Clean up
|
||
this.gl.deleteShader(shader);
|
||
return null;
|
||
}
|
||
// Sucess, so return the shader
|
||
return shader;
|
||
}
|
||
/* ########## GENERAL LOADING FUNCTIONS ########## */
|
||
loadTextFile(textFilePath, callback) {
|
||
let xobj = new XMLHttpRequest();
|
||
xobj.overrideMimeType("application/json");
|
||
xobj.open('GET', textFilePath, true);
|
||
xobj.onreadystatechange = function () {
|
||
if ((xobj.readyState == 4) && (xobj.status == 200)) {
|
||
callback(xobj.responseText);
|
||
}
|
||
};
|
||
xobj.send(null);
|
||
}
|
||
/* ########## LOADING BAR INFO ########## */
|
||
getLoadPercent() {
|
||
return (this.loadonly_tilemapsLoaded / this.loadonly_tilemapsToLoad
|
||
+ this.loadonly_spritesheetsLoaded / this.loadonly_spritesheetsToLoad
|
||
+ this.loadonly_imagesLoaded / this.loadonly_imagesToLoad
|
||
+ this.loadonly_audioLoaded / this.loadonly_audioToLoad)
|
||
/ this.loadonly_typesToLoad;
|
||
}
|
||
// Customized funtions below
|
||
// These funtions are NOT well tested!!!
|
||
// Only used for shattered sword specific purpose!!!
|
||
// Use them carefully!!!
|
||
tilemapFromObject(key, tilemap) {
|
||
this.loadonly_tilemapObjectLoadingQueue.enqueue({ key: key, map: tilemap });
|
||
}
|
||
loadTilemapObjectFromQueue(onFinishLoading) {
|
||
this.loadonly_tilemapObjectToLoad = this.loadonly_tilemapObjectLoadingQueue.getSize();
|
||
this.loadonly_tilemapObjectLoaded = 0;
|
||
// If no items to load, we're finished
|
||
if (this.loadonly_tilemapObjectToLoad === 0) {
|
||
onFinishLoading();
|
||
return;
|
||
}
|
||
while (this.loadonly_tilemapObjectLoadingQueue.hasItems()) {
|
||
let map = this.loadonly_tilemapObjectLoadingQueue.dequeue();
|
||
this.loadTilemapFromObject(map.key, map.map, onFinishLoading);
|
||
}
|
||
}
|
||
loadTilemapFromObject(key, tiledMap, callbackIfLast) {
|
||
// We can parse the object later - it's much faster than loading
|
||
this.tilemaps.add(key, tiledMap);
|
||
let resource = new ResourceReference(key, ResourceType.TILEMAP);
|
||
// Grab the tileset images we need to load and add them to the imageloading queue
|
||
for (let tileset of tiledMap.tilesets) {
|
||
if (tileset.image) {
|
||
let key = tileset.image;
|
||
let path = key;
|
||
this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path, isDependency: true });
|
||
// Add this image as a dependency to the tilemap
|
||
resource.addDependency(new ResourceReference(key, ResourceType.IMAGE));
|
||
}
|
||
}
|
||
// Add the resource reference to the list of resource to unload
|
||
this.resourcesToUnload.push(resource);
|
||
this.finishLoadingTilemapObject(callbackIfLast);
|
||
}
|
||
finishLoadingTilemapObject(callback) {
|
||
this.loadonly_tilemapObjectLoaded += 1;
|
||
if (this.loadonly_tilemapObjectLoaded === this.loadonly_tilemapObjectToLoad) {
|
||
// We're done loading tilemaps
|
||
callback();
|
||
}
|
||
}
|
||
singleImage(key, path, callbackIfLast) {
|
||
var image = new Image();
|
||
image.onload = () => {
|
||
// Add to loaded images
|
||
this.images.add(key, image);
|
||
this.resourcesToUnload.push(new ResourceReference(key, ResourceType.IMAGE));
|
||
// If WebGL is active, create a texture
|
||
if (this.gl_WebGLActive) {
|
||
this.createWebGLTexture(key, image);
|
||
}
|
||
// Finish image load
|
||
this.finishLoadingSingleObject(callbackIfLast);
|
||
};
|
||
image.src = path;
|
||
}
|
||
singleAudio(key, path, callbackIfLast) {
|
||
let audioCtx = AudioManager_1.default.getInstance().getAudioContext();
|
||
let request = new XMLHttpRequest();
|
||
request.open('GET', path, true);
|
||
request.responseType = 'arraybuffer';
|
||
request.onload = () => {
|
||
audioCtx.decodeAudioData(request.response, (buffer) => {
|
||
// Add to list of audio buffers
|
||
this.audioBuffers.add(key, buffer);
|
||
this.resourcesToUnload.push(new ResourceReference(key, ResourceType.AUDIO));
|
||
// Finish loading sound
|
||
this.finishLoadingSingleObject(callbackIfLast);
|
||
}, (error) => {
|
||
throw "Error loading sound";
|
||
});
|
||
};
|
||
request.send();
|
||
}
|
||
finishLoadingSingleObject(callback) {
|
||
callback();
|
||
}
|
||
update(deltaT) {
|
||
if (this.loading) {
|
||
if (this.onLoadProgress) {
|
||
this.onLoadProgress(this.getLoadPercent());
|
||
}
|
||
}
|
||
else if (this.justLoaded) {
|
||
this.justLoaded = false;
|
||
if (this.onLoadComplete) {
|
||
this.onLoadComplete();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = ResourceManager;
|
||
/**
|
||
* A class representing a reference to a resource.
|
||
* This is used for the exemption list to assure assets and their dependencies don't get
|
||
* destroyed if they are still needed.
|
||
*/
|
||
class ResourceReference {
|
||
constructor(key, resourceType) {
|
||
this.key = key;
|
||
this.resourceType = resourceType;
|
||
this.dependencies = new Array();
|
||
}
|
||
addDependency(resource) {
|
||
this.dependencies.push(resource);
|
||
}
|
||
}
|
||
var ResourceType;
|
||
(function (ResourceType) {
|
||
ResourceType["IMAGE"] = "IMAGE";
|
||
ResourceType["TILEMAP"] = "TILEMAP";
|
||
ResourceType["SPRITESHEET"] = "SPRITESHEET";
|
||
ResourceType["AUDIO"] = "AUDIO";
|
||
ResourceType["JSON"] = "JSON";
|
||
ResourceType["SHADER"] = "SHADER";
|
||
})(ResourceType || (ResourceType = {}));
|
||
/**
|
||
* A pair representing a key and the path of the resource to load
|
||
*/
|
||
class KeyPathPair {
|
||
constructor() {
|
||
this.isDependency = false;
|
||
}
|
||
}
|
||
class KeyMapPair {
|
||
}
|
||
class KeyPath_Shader {
|
||
}
|
||
|
||
},{"../DataTypes/Map":10,"../DataTypes/Queue":14,"../DataTypes/Rendering/WebGLProgramType":15,"../Sound/AudioManager":96,"../Utils/StringUtils":104}],84:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Sprite_1 = require("../../Nodes/Sprites/Sprite");
|
||
const AnimatedSprite_1 = require("../../Nodes/Sprites/AnimatedSprite");
|
||
const GraphicTypes_1 = require("../../Nodes/Graphics/GraphicTypes");
|
||
const UIElementTypes_1 = require("../../Nodes/UIElements/UIElementTypes");
|
||
const Point_1 = require("../../Nodes/Graphics/Point");
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const Button_1 = require("../../Nodes/UIElements/Button");
|
||
const Label_1 = require("../../Nodes/UIElements/Label");
|
||
const Slider_1 = require("../../Nodes/UIElements/Slider");
|
||
const TextInput_1 = require("../../Nodes/UIElements/TextInput");
|
||
const Rect_1 = require("../../Nodes/Graphics/Rect");
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const Line_1 = require("../../Nodes/Graphics/Line");
|
||
const Particle_1 = require("../../Nodes/Graphics/Particle");
|
||
// @ignorePage
|
||
/**
|
||
* A factory that abstracts adding @reference[CanvasNode]s to the @reference[Scene].
|
||
* Access methods in this factory through Scene.add.[methodName]().
|
||
*/
|
||
class CanvasNodeFactory {
|
||
constructor() {
|
||
/**
|
||
* Adds an instance of a UIElement to the current scene - i.e. any class that extends UIElement
|
||
* @param type The type of UIElement to add
|
||
* @param layerName The layer to add the UIElement to
|
||
* @param options Any additional arguments to feed to the constructor
|
||
* @returns A new UIElement
|
||
*/
|
||
this.addUIElement = (type, layerName, options) => {
|
||
// Get the layer
|
||
let layer = this.scene.getLayer(layerName);
|
||
let instance;
|
||
switch (type) {
|
||
case UIElementTypes_1.UIElementType.BUTTON:
|
||
instance = this.buildButton(options);
|
||
break;
|
||
case UIElementTypes_1.UIElementType.LABEL:
|
||
instance = this.buildLabel(options);
|
||
break;
|
||
case UIElementTypes_1.UIElementType.SLIDER:
|
||
instance = this.buildSlider(options);
|
||
break;
|
||
case UIElementTypes_1.UIElementType.TEXT_INPUT:
|
||
instance = this.buildTextInput(options);
|
||
break;
|
||
default:
|
||
throw `UIElementType '${type}' does not exist, or is registered incorrectly.`;
|
||
}
|
||
instance.setScene(this.scene);
|
||
instance.id = this.scene.generateId();
|
||
this.scene.getSceneGraph().addNode(instance);
|
||
// Add instance to layer
|
||
layer.addNode(instance);
|
||
return instance;
|
||
};
|
||
/**
|
||
* Adds a sprite to the current scene
|
||
* @param key The key of the image the sprite will represent
|
||
* @param layerName The layer on which to add the sprite
|
||
* @returns A new Sprite
|
||
*/
|
||
this.addSprite = (key, layerName) => {
|
||
let layer = this.scene.getLayer(layerName);
|
||
let instance = new Sprite_1.default(key);
|
||
// Add instance to scene
|
||
instance.setScene(this.scene);
|
||
instance.id = this.scene.generateId();
|
||
if (!(this.scene.isParallaxLayer(layerName) || this.scene.isUILayer(layerName))) {
|
||
this.scene.getSceneGraph().addNode(instance);
|
||
}
|
||
// Add instance to layer
|
||
layer.addNode(instance);
|
||
return instance;
|
||
};
|
||
/**
|
||
* Adds an AnimatedSprite to the current scene
|
||
* @param key The key of the image the sprite will represent
|
||
* @param layerName The layer on which to add the sprite
|
||
* @returns A new AnimatedSprite
|
||
*/
|
||
this.addAnimatedSprite = (key, layerName) => {
|
||
let layer = this.scene.getLayer(layerName);
|
||
let spritesheet = this.resourceManager.getSpritesheet(key);
|
||
let instance = new AnimatedSprite_1.default(spritesheet);
|
||
// Add instance fo scene
|
||
instance.setScene(this.scene);
|
||
instance.id = this.scene.generateId();
|
||
if (!(this.scene.isParallaxLayer(layerName) || this.scene.isUILayer(layerName))) {
|
||
this.scene.getSceneGraph().addNode(instance);
|
||
}
|
||
// Add instance to layer
|
||
layer.addNode(instance);
|
||
return instance;
|
||
};
|
||
/**
|
||
* Adds a new graphic element to the current Scene
|
||
* @param type The type of graphic to add
|
||
* @param layerName The layer on which to add the graphic
|
||
* @param options Any additional arguments to send to the graphic constructor
|
||
* @returns A new Graphic
|
||
*/
|
||
this.addGraphic = (type, layerName, options) => {
|
||
// Get the layer
|
||
let layer = this.scene.getLayer(layerName);
|
||
let instance;
|
||
switch (type) {
|
||
case GraphicTypes_1.GraphicType.POINT:
|
||
instance = this.buildPoint(options);
|
||
break;
|
||
case GraphicTypes_1.GraphicType.LINE:
|
||
instance = this.buildLine(options);
|
||
break;
|
||
case GraphicTypes_1.GraphicType.RECT:
|
||
instance = this.buildRect(options);
|
||
break;
|
||
case GraphicTypes_1.GraphicType.PARTICLE:
|
||
instance = this.buildParticle(options);
|
||
break;
|
||
default:
|
||
throw `GraphicType '${type}' does not exist, or is registered incorrectly.`;
|
||
}
|
||
// Add instance to scene
|
||
instance.setScene(this.scene);
|
||
instance.id = this.scene.generateId();
|
||
if (!(this.scene.isParallaxLayer(layerName) || this.scene.isUILayer(layerName))) {
|
||
this.scene.getSceneGraph().addNode(instance);
|
||
}
|
||
// Add instance to layer
|
||
layer.addNode(instance);
|
||
return instance;
|
||
};
|
||
}
|
||
init(scene) {
|
||
this.scene = scene;
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
/* ---------- BUILDERS ---------- */
|
||
buildButton(options) {
|
||
this.checkIfPropExists("Button", options, "position", Vec2_1.default, "Vec2");
|
||
this.checkIfPropExists("Button", options, "text", "string");
|
||
return new Button_1.default(options.position, options.text);
|
||
}
|
||
buildLabel(options) {
|
||
this.checkIfPropExists("Label", options, "position", Vec2_1.default, "Vec2");
|
||
this.checkIfPropExists("Label", options, "text", "string");
|
||
return new Label_1.default(options.position, options.text);
|
||
}
|
||
buildSlider(options) {
|
||
this.checkIfPropExists("Slider", options, "position", Vec2_1.default, "Vec2");
|
||
let initValue = 0;
|
||
if (options.value !== undefined) {
|
||
initValue = options.value;
|
||
}
|
||
return new Slider_1.default(options.position, initValue);
|
||
}
|
||
buildTextInput(options) {
|
||
this.checkIfPropExists("TextInput", options, "position", Vec2_1.default, "Vec2");
|
||
return new TextInput_1.default(options.position);
|
||
}
|
||
buildPoint(options) {
|
||
this.checkIfPropExists("Point", options, "position", Vec2_1.default, "Vec2");
|
||
return new Point_1.default(options.position);
|
||
}
|
||
buildParticle(options) {
|
||
this.checkIfPropExists("Particle", options, "position", Vec2_1.default, "Vec2");
|
||
this.checkIfPropExists("Particle", options, "size", Vec2_1.default, "Vec2");
|
||
this.checkIfPropExists("Particle", options, "mass", "number", "number");
|
||
//Changed for testing
|
||
return new Particle_1.default(options.position, options.size, options.mass);
|
||
}
|
||
buildLine(options) {
|
||
this.checkIfPropExists("Line", options, "start", Vec2_1.default, "Vec2");
|
||
this.checkIfPropExists("Line", options, "end", Vec2_1.default, "Vec2");
|
||
return new Line_1.default(options.start, options.end);
|
||
}
|
||
buildRect(options) {
|
||
this.checkIfPropExists("Rect", options, "position", Vec2_1.default, "Vec2");
|
||
this.checkIfPropExists("Rect", options, "size", Vec2_1.default, "Vec2");
|
||
return new Rect_1.default(options.position, options.size);
|
||
}
|
||
/* ---------- ERROR HANDLING ---------- */
|
||
checkIfPropExists(objectName, options, prop, type, typeName) {
|
||
if (!options || options[prop] === undefined) {
|
||
// Check that the options object has the property
|
||
throw `${objectName} object requires argument ${prop} of type ${typeName}, but none was provided.`;
|
||
}
|
||
else {
|
||
// Check that the property has the correct type
|
||
if ((typeof type) === "string") {
|
||
if (!(typeof options[prop] === type)) {
|
||
throw `${objectName} object requires argument ${prop} of type ${type}, but provided ${prop} was not of type ${type}.`;
|
||
}
|
||
}
|
||
else if (type instanceof Function) {
|
||
// If type is a constructor, check against that
|
||
if (!(options[prop] instanceof type)) {
|
||
throw `${objectName} object requires argument ${prop} of type ${typeName}, but provided ${prop} was not of type ${typeName}.`;
|
||
}
|
||
}
|
||
else {
|
||
throw `${objectName} object requires argument ${prop} of type ${typeName}, but provided ${prop} was not of type ${typeName}.`;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = CanvasNodeFactory;
|
||
|
||
},{"../../DataTypes/Vec2":24,"../../Nodes/Graphics/GraphicTypes":42,"../../Nodes/Graphics/Line":43,"../../Nodes/Graphics/Particle":44,"../../Nodes/Graphics/Point":45,"../../Nodes/Graphics/Rect":46,"../../Nodes/Sprites/AnimatedSprite":47,"../../Nodes/Sprites/Sprite":48,"../../Nodes/UIElements/Button":52,"../../Nodes/UIElements/Label":53,"../../Nodes/UIElements/Slider":54,"../../Nodes/UIElements/TextInput":55,"../../Nodes/UIElements/UIElementTypes":56,"../../ResourceManager/ResourceManager":83}],85:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const CanvasNodeFactory_1 = require("./CanvasNodeFactory");
|
||
const TilemapFactory_1 = require("./TilemapFactory");
|
||
/**
|
||
* The manager of all factories used for adding @reference[GameNode]s to the @reference[Scene].
|
||
*/
|
||
class FactoryManager {
|
||
constructor(scene, tilemaps) {
|
||
// Constructors are called here to allow assignment of their functions to functions in this class
|
||
this.canvasNodeFactory = new CanvasNodeFactory_1.default();
|
||
this.tilemapFactory = new TilemapFactory_1.default();
|
||
this.canvasNodeFactory.init(scene);
|
||
this.tilemapFactory.init(scene, tilemaps);
|
||
}
|
||
// Expose all of the factories through the factory manager
|
||
/**
|
||
* Adds an instance of a UIElement to the current scene - i.e. any class that extends UIElement
|
||
* @param type The type of UIElement to add
|
||
* @param layerName The layer to add the UIElement to
|
||
* @param options Any additional arguments to feed to the constructor
|
||
* @returns A new UIElement
|
||
*/
|
||
uiElement(type, layerName, options) {
|
||
return this.canvasNodeFactory.addUIElement(type, layerName, options);
|
||
}
|
||
/**
|
||
* Adds a sprite to the current scene
|
||
* @param key The key of the image the sprite will represent
|
||
* @param layerName The layer on which to add the sprite
|
||
* @returns A new Sprite
|
||
*/
|
||
sprite(key, layerName) {
|
||
return this.canvasNodeFactory.addSprite(key, layerName);
|
||
}
|
||
/**
|
||
* Adds an AnimatedSprite to the current scene
|
||
* @param key The key of the image the sprite will represent
|
||
* @param layerName The layer on which to add the sprite
|
||
* @returns A new AnimatedSprite
|
||
*/
|
||
animatedSprite(key, layerName) {
|
||
return this.canvasNodeFactory.addAnimatedSprite(key, layerName);
|
||
}
|
||
/**
|
||
* Adds a new graphic element to the current Scene
|
||
* @param type The type of graphic to add
|
||
* @param layerName The layer on which to add the graphic
|
||
* @param options Any additional arguments to send to the graphic constructor
|
||
* @returns A new Graphic
|
||
*/
|
||
graphic(type, layerName, options) {
|
||
return this.canvasNodeFactory.addGraphic(type, layerName, options);
|
||
}
|
||
/**
|
||
* Adds a tilemap to the scene
|
||
* @param key The key of the loaded tilemap to load
|
||
* @param constr The constructor of the desired tilemap
|
||
* @param args Additional arguments to send to the tilemap constructor
|
||
* @returns An array of Layers, each of which contains a layer of the tilemap as its own Tilemap instance.
|
||
*/
|
||
tilemap(key, scale) {
|
||
return this.tilemapFactory.add(key, scale);
|
||
}
|
||
}
|
||
exports.default = FactoryManager;
|
||
|
||
},{"./CanvasNodeFactory":84,"./TilemapFactory":86}],86:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../../ResourceManager/ResourceManager");
|
||
const OrthogonalTilemap_1 = require("../../Nodes/Tilemaps/OrthogonalTilemap");
|
||
const Tileset_1 = require("../../DataTypes/Tilesets/Tileset");
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const PositionGraph_1 = require("../../DataTypes/Graphs/PositionGraph");
|
||
const Navmesh_1 = require("../../Pathfinding/Navmesh");
|
||
// @ignorePage
|
||
/**
|
||
* A factory that abstracts adding @reference[Tilemap]s to the @reference[Scene].
|
||
* Access methods in this factory through Scene.add.[methodName]().
|
||
*/
|
||
class TilemapFactory {
|
||
constructor() {
|
||
// TODO - This is specifically catered to Tiled tilemaps right now. In the future,
|
||
// it would be good to have a "parseTilemap" function that would convert the tilemap
|
||
// data into a standard format. This could allow for support from other programs
|
||
// or the development of an internal level builder tool
|
||
/**
|
||
* Adds a tilemap to the scene
|
||
* @param key The key of the loaded tilemap to load
|
||
* @param constr The constructor of the desired tilemap
|
||
* @param args Additional arguments to send to the tilemap constructor
|
||
* @returns An array of Layers, each of which contains a layer of the tilemap as its own Tilemap instance.
|
||
*/
|
||
this.add = (key, scale = new Vec2_1.default(1, 1)) => {
|
||
// Get Tilemap Data
|
||
let tilemapData = this.resourceManager.getTilemap(key);
|
||
// Set the constructor for this tilemap to either be orthographic or isometric
|
||
let constr;
|
||
if (tilemapData.orientation === "orthographic") {
|
||
constr = OrthogonalTilemap_1.default;
|
||
}
|
||
else {
|
||
// No isometric tilemap support right now, so Orthographic tilemap
|
||
constr = OrthogonalTilemap_1.default;
|
||
}
|
||
// Initialize the return value array
|
||
let sceneLayers = new Array();
|
||
// Create all of the tilesets for this tilemap
|
||
let tilesets = new Array();
|
||
let collectionTiles = new Array();
|
||
for (let tileset of tilemapData.tilesets) {
|
||
if (tileset.image) {
|
||
// If this is a standard tileset and not a collection, create a tileset for it.
|
||
// TODO - We are ignoring collection tilesets for now. This is likely not a great idea in practice,
|
||
// as theoretically someone could want to use one for a standard tilemap. We are assuming for now
|
||
// that we only want to use them for object layers
|
||
tilesets.push(new Tileset_1.default(tileset));
|
||
}
|
||
else {
|
||
tileset.tiles.forEach(tile => tile.id += tileset.firstgid);
|
||
collectionTiles.push(...tileset.tiles);
|
||
}
|
||
}
|
||
// Loop over the layers of the tilemap and create tiledlayers or object layers
|
||
for (let layer of tilemapData.layers) {
|
||
let sceneLayer;
|
||
let isParallaxLayer = false;
|
||
let depth = 0;
|
||
if (layer.properties) {
|
||
for (let prop of layer.properties) {
|
||
if (prop.name === "Parallax") {
|
||
isParallaxLayer = prop.value;
|
||
}
|
||
else if (prop.name === "Depth") {
|
||
depth = prop.value;
|
||
}
|
||
}
|
||
}
|
||
if (isParallaxLayer) {
|
||
sceneLayer = this.scene.addParallaxLayer(layer.name, new Vec2_1.default(1, 1), depth);
|
||
}
|
||
else {
|
||
sceneLayer = this.scene.addLayer(layer.name, depth);
|
||
}
|
||
if (layer.type === "tilelayer") {
|
||
// Create a new tilemap object for the layer
|
||
let tilemap = new constr(tilemapData, layer, tilesets, scale);
|
||
tilemap.id = this.scene.generateId();
|
||
tilemap.setScene(this.scene);
|
||
// Add tilemap to scene
|
||
this.tilemaps.push(tilemap);
|
||
sceneLayer.addNode(tilemap);
|
||
// Register tilemap with physics if it's collidable
|
||
if (tilemap.isCollidable) {
|
||
tilemap.addPhysics();
|
||
if (layer.properties) {
|
||
for (let item of layer.properties) {
|
||
if (item.name === "Group") {
|
||
tilemap.setGroup(item.value);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
let isNavmeshPoints = false;
|
||
let navmeshName;
|
||
let edges;
|
||
if (layer.properties) {
|
||
for (let prop of layer.properties) {
|
||
if (prop.name === "NavmeshPoints") {
|
||
isNavmeshPoints = true;
|
||
}
|
||
else if (prop.name === "name") {
|
||
navmeshName = prop.value;
|
||
}
|
||
else if (prop.name === "edges") {
|
||
edges = prop.value;
|
||
}
|
||
}
|
||
}
|
||
if (isNavmeshPoints) {
|
||
let g = new PositionGraph_1.default();
|
||
for (let obj of layer.objects) {
|
||
g.addPositionedNode(new Vec2_1.default(obj.x, obj.y));
|
||
}
|
||
for (let edge of edges) {
|
||
g.addEdge(edge.from, edge.to);
|
||
}
|
||
this.scene.getNavigationManager().addNavigableEntity(navmeshName, new Navmesh_1.default(g));
|
||
continue;
|
||
}
|
||
// Layer is an object layer, so add each object as a sprite to a new layer
|
||
for (let obj of layer.objects) {
|
||
// Check if obj is collidable
|
||
let hasPhysics = false;
|
||
let isCollidable = false;
|
||
let isTrigger = false;
|
||
let onEnter = null;
|
||
let onExit = null;
|
||
let triggerGroup = null;
|
||
let group = "";
|
||
if (obj.properties) {
|
||
for (let prop of obj.properties) {
|
||
if (prop.name === "HasPhysics") {
|
||
hasPhysics = prop.value;
|
||
}
|
||
else if (prop.name === "Collidable") {
|
||
isCollidable = prop.value;
|
||
}
|
||
else if (prop.name === "Group") {
|
||
group = prop.value;
|
||
}
|
||
else if (prop.name === "IsTrigger") {
|
||
isTrigger = prop.value;
|
||
}
|
||
else if (prop.name === "TriggerGroup") {
|
||
triggerGroup = prop.value;
|
||
}
|
||
else if (prop.name === "TriggerOnEnter") {
|
||
onEnter = prop.value;
|
||
}
|
||
else if (prop.name === "TriggerOnExit") {
|
||
onExit = prop.value;
|
||
}
|
||
}
|
||
}
|
||
let sprite;
|
||
// Check if obj is a tile from a tileset
|
||
for (let tileset of tilesets) {
|
||
if (tileset.hasTile(obj.gid)) {
|
||
// The object is a tile from this set
|
||
let imageKey = tileset.getImageKey();
|
||
let offset = tileset.getImageOffsetForTile(obj.gid);
|
||
sprite = this.scene.add.sprite(imageKey, layer.name);
|
||
let size = tileset.getTileSize().clone();
|
||
sprite.position.set((obj.x + size.x / 2) * scale.x, (obj.y - size.y / 2) * scale.y);
|
||
sprite.setImageOffset(offset);
|
||
sprite.size.copy(size);
|
||
sprite.scale.set(scale.x, scale.y);
|
||
}
|
||
}
|
||
// Not in a tileset, must correspond to a collection
|
||
if (!sprite) {
|
||
for (let tile of collectionTiles) {
|
||
if (obj.gid === tile.id) {
|
||
let imageKey = tile.image;
|
||
sprite = this.scene.add.sprite(imageKey, layer.name);
|
||
sprite.position.set((obj.x + tile.imagewidth / 2) * scale.x, (obj.y - tile.imageheight / 2) * scale.y);
|
||
sprite.scale.set(scale.x, scale.y);
|
||
}
|
||
}
|
||
}
|
||
// Now we have sprite. Associate it with our physics object if there is one
|
||
if (hasPhysics) {
|
||
// Make the sprite a static physics object
|
||
sprite.addPhysics(sprite.boundary.clone(), Vec2_1.default.ZERO, isCollidable, true);
|
||
sprite.setGroup(group);
|
||
if (isTrigger && triggerGroup !== null) {
|
||
sprite.setTrigger(triggerGroup, onEnter, onExit);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Update the return value
|
||
sceneLayers.push(sceneLayer);
|
||
}
|
||
return sceneLayers;
|
||
};
|
||
}
|
||
init(scene, tilemaps) {
|
||
this.scene = scene;
|
||
this.tilemaps = tilemaps;
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
}
|
||
}
|
||
exports.default = TilemapFactory;
|
||
|
||
},{"../../DataTypes/Graphs/PositionGraph":8,"../../DataTypes/Tilesets/Tileset":23,"../../DataTypes/Vec2":24,"../../Nodes/Tilemaps/OrthogonalTilemap":50,"../../Pathfinding/Navmesh":59,"../../ResourceManager/ResourceManager":83}],87:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const MathUtils_1 = require("../Utils/MathUtils");
|
||
/**
|
||
* A layer in the scene. Layers are used for sorting @reference[GameNode]s by depth.
|
||
*/
|
||
class Layer {
|
||
/**
|
||
* Creates a new layer. To do this in a game, use the addLayer() method in @refrence[Scene]
|
||
* @param scene The scene to add the layer to
|
||
* @param name The name of the layer
|
||
*/
|
||
constructor(scene, name) {
|
||
this.scene = scene;
|
||
this.name = name;
|
||
this.paused = false;
|
||
this.hidden = false;
|
||
this.alpha = 1;
|
||
this.items = new Array();
|
||
this.ySort = false;
|
||
this.depth = 0;
|
||
}
|
||
/**
|
||
* Retreives the name of the layer
|
||
* @returns The name of the layer
|
||
*/
|
||
getName() {
|
||
return this.name;
|
||
}
|
||
/**
|
||
* Pauses/Unpauses the layer. Affects all elements in this layer
|
||
* @param pauseValue True if the layer should be paused, false if not
|
||
*/
|
||
setPaused(pauseValue) {
|
||
this.paused = pauseValue;
|
||
}
|
||
/**
|
||
* Returns whether or not the layer is paused
|
||
*/
|
||
isPaused() {
|
||
return this.paused;
|
||
}
|
||
/**
|
||
* Sets the opacity of the layer
|
||
* @param alpha The new opacity value in the range [0, 1]
|
||
*/
|
||
setAlpha(alpha) {
|
||
this.alpha = MathUtils_1.default.clamp(alpha, 0, 1);
|
||
}
|
||
/**
|
||
* Gets the opacity of the layer
|
||
* @returns The opacity
|
||
*/
|
||
getAlpha() {
|
||
return this.alpha;
|
||
}
|
||
/**
|
||
* Sets the layer's hidden value. If hidden, a layer will not be rendered, but will still update
|
||
* @param hidden The hidden value of the layer
|
||
*/
|
||
setHidden(hidden) {
|
||
this.hidden = hidden;
|
||
}
|
||
/**
|
||
* Returns the hideen value of the lyaer
|
||
* @returns True if the scene is hidden, false otherwise
|
||
*/
|
||
isHidden() {
|
||
return this.hidden;
|
||
}
|
||
/** Pauses this scene and hides it */
|
||
disable() {
|
||
this.paused = true;
|
||
this.hidden = true;
|
||
}
|
||
/** Unpauses this layer and makes it visible */
|
||
enable() {
|
||
this.paused = false;
|
||
this.hidden = false;
|
||
}
|
||
/**
|
||
* Sets whether or not the scene will ySort automatically.
|
||
* ySorting means that CanvasNodes on this layer will have their depth sorted depending on their y-value.
|
||
* This means that if an object is "higher" in the scene, it will sort behind objects that are "lower".
|
||
* This is useful for 3/4 view games, or similar situations, where you sometimes want to be in front of objects,
|
||
* and other times want to be behind the same objects.
|
||
* @param ySort True if ySorting should be active, false if not
|
||
*/
|
||
setYSort(ySort) {
|
||
this.ySort = ySort;
|
||
}
|
||
/**
|
||
* Gets the ySort status of the scene
|
||
* @returns True if ySorting is occurring, false otherwise
|
||
*/
|
||
getYSort() {
|
||
return this.ySort;
|
||
}
|
||
/**
|
||
* Sets the depth of the layer compared to other layers. A larger number means the layer will be closer to the screen.
|
||
* @param depth The depth of the layer.
|
||
*/
|
||
setDepth(depth) {
|
||
this.depth = depth;
|
||
}
|
||
/**
|
||
* Retrieves the depth of the layer.
|
||
* @returns The depth
|
||
*/
|
||
getDepth() {
|
||
return this.depth;
|
||
}
|
||
/**
|
||
* Adds a node to this layer
|
||
* @param node The node to add to this layer.
|
||
*/
|
||
addNode(node) {
|
||
this.items.push(node);
|
||
node.setLayer(this);
|
||
}
|
||
/**
|
||
* Removes a node from this layer
|
||
* @param node The node to remove
|
||
* @returns true if the node was removed, false otherwise
|
||
*/
|
||
removeNode(node) {
|
||
// Find and remove the node
|
||
let index = this.items.indexOf(node);
|
||
if (index !== -1) {
|
||
this.items.splice(index, 1);
|
||
node.setLayer(undefined);
|
||
}
|
||
}
|
||
/**
|
||
* Retreives all GameNodes from this layer
|
||
* @returns an Array that contains all of the GameNodes in this layer.
|
||
*/
|
||
getItems() {
|
||
return this.items;
|
||
}
|
||
}
|
||
exports.default = Layer;
|
||
|
||
},{"../Utils/MathUtils":102}],88:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Layer_1 = require("../Layer");
|
||
/**
|
||
* An extension of a Layer that has a parallax value.
|
||
*/
|
||
class ParallaxLayer extends Layer_1.default {
|
||
/**
|
||
* Creates a new ParallaxLayer.
|
||
* Use addParallaxLayer() in @reference[Scene] to add a layer of this type to your game.
|
||
* @param scene The Scene to add this ParallaxLayer to
|
||
* @param name The name of the ParallaxLayer
|
||
* @param parallax The parallax level
|
||
*/
|
||
constructor(scene, name, parallax) {
|
||
super(scene, name);
|
||
this.parallax = parallax;
|
||
}
|
||
}
|
||
exports.default = ParallaxLayer;
|
||
|
||
},{"../Layer":87}],89:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../DataTypes/Vec2");
|
||
const ParallaxLayer_1 = require("./ParallaxLayer");
|
||
/**
|
||
* A Layer strictly to be used for managing UIElements.
|
||
* This is intended to be a Layer that always stays in the same place,
|
||
* and thus renders things like a HUD or an inventory without taking into consideration the \reference[Viewport] scroll.
|
||
*/
|
||
class UILayer extends ParallaxLayer_1.default {
|
||
/**
|
||
* Creates a new UILayer.
|
||
* Use addUILayer() in @reference[Scene] to add a layer of this type to your game.
|
||
* @param scene The Scene to add this UILayer to
|
||
* @param name The name of the UILayer
|
||
*/
|
||
constructor(scene, name) {
|
||
super(scene, name, Vec2_1.default.ZERO);
|
||
}
|
||
}
|
||
exports.default = UILayer;
|
||
|
||
},{"../../DataTypes/Vec2":24,"./ParallaxLayer":88}],90:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Layer_1 = require("./Layer");
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const BasicPhysicsManager_1 = require("../Physics/BasicPhysicsManager");
|
||
const SceneGraphArray_1 = require("../SceneGraph/SceneGraphArray");
|
||
const FactoryManager_1 = require("./Factories/FactoryManager");
|
||
const ResourceManager_1 = require("../ResourceManager/ResourceManager");
|
||
const Receiver_1 = require("../Events/Receiver");
|
||
const Emitter_1 = require("../Events/Emitter");
|
||
const NavigationManager_1 = require("../Pathfinding/NavigationManager");
|
||
const AIManager_1 = require("../AI/AIManager");
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const ParallaxLayer_1 = require("./Layers/ParallaxLayer");
|
||
const UILayer_1 = require("./Layers/UILayer");
|
||
const CanvasNode_1 = require("../Nodes/CanvasNode");
|
||
const SceneOptions_1 = require("./SceneOptions");
|
||
const Debug_1 = require("../Debug/Debug");
|
||
const TimerManager_1 = require("../Timing/TimerManager");
|
||
const TweenManager_1 = require("../Rendering/Animations/TweenManager");
|
||
const ParticleSystemManager_1 = require("../Rendering/Animations/ParticleSystemManager");
|
||
/**
|
||
* Scenes are the main container in the game engine.
|
||
* Your main scene is the current level or menu of the game, and will contain all of the GameNodes needed.
|
||
* Scenes provide an easy way to load assets, add assets to the game world, and unload assets,
|
||
* and have lifecycle methods exposed for these functions.
|
||
*/
|
||
class Scene {
|
||
/**
|
||
* Creates a new Scene. To add a new Scene in your game, use changeToScene() in @reference[SceneManager]
|
||
* @param viewport The viewport of the game
|
||
* @param sceneManager The SceneManager that owns this Scene
|
||
* @param renderingManager The RenderingManager that will handle this Scene's rendering
|
||
* @param game The instance of the Game
|
||
* @param options The options for Scene initialization
|
||
*/
|
||
constructor(viewport, sceneManager, renderingManager, options) {
|
||
this.sceneOptions = SceneOptions_1.default.parse(options === undefined ? {} : options);
|
||
this.worldSize = new Vec2_1.default(500, 500);
|
||
this.viewport = viewport;
|
||
this.viewport.setBounds(0, 0, 2560, 1280);
|
||
this.running = false;
|
||
this.sceneManager = sceneManager;
|
||
this.receiver = new Receiver_1.default();
|
||
this.emitter = new Emitter_1.default();
|
||
this.tilemaps = new Array();
|
||
this.sceneGraph = new SceneGraphArray_1.default(this.viewport, this);
|
||
this.layers = new Map_1.default();
|
||
this.uiLayers = new Map_1.default();
|
||
this.parallaxLayers = new Map_1.default();
|
||
this.physicsManager = new BasicPhysicsManager_1.default(this.sceneOptions.physics);
|
||
this.navManager = new NavigationManager_1.default();
|
||
this.aiManager = new AIManager_1.default();
|
||
this.renderingManager = renderingManager;
|
||
this.add = new FactoryManager_1.default(this, this.tilemaps);
|
||
this.load = ResourceManager_1.default.getInstance();
|
||
this.resourceManager = this.load;
|
||
// Get the timer manager and clear any existing timers
|
||
TimerManager_1.default.getInstance().clearTimers();
|
||
}
|
||
/** A lifecycle method that gets called immediately after a new scene is created, before anything else. */
|
||
initScene(init) { }
|
||
/** A lifecycle method that gets called when a new scene is created. Load all files you wish to access in the scene here. */
|
||
loadScene() { }
|
||
/** A lifecycle method called strictly after loadScene(). Create any game objects you wish to use in the scene here. */
|
||
startScene() { }
|
||
/**
|
||
* A lifecycle method called every frame of the game. This is where you can dynamically do things like add in new enemies
|
||
* @param delta The time this frame represents
|
||
*/
|
||
updateScene(deltaT) { }
|
||
/** A lifecycle method that gets called on scene destruction. Specify which files you no longer need for garbage collection. */
|
||
unloadScene() { }
|
||
update(deltaT) {
|
||
this.updateScene(deltaT);
|
||
// Do time updates
|
||
TimerManager_1.default.getInstance().update(deltaT);
|
||
// Do all AI updates
|
||
this.aiManager.update(deltaT);
|
||
// Update all physics objects
|
||
this.physicsManager.update(deltaT);
|
||
// Update all canvas objects
|
||
this.sceneGraph.update(deltaT);
|
||
// Update all tilemaps
|
||
this.tilemaps.forEach(tilemap => {
|
||
if (!tilemap.getLayer().isPaused()) {
|
||
tilemap.update(deltaT);
|
||
}
|
||
});
|
||
// Update all tweens
|
||
TweenManager_1.default.getInstance().update(deltaT);
|
||
// Update all particle systems
|
||
ParticleSystemManager_1.default.getInstance().update(deltaT);
|
||
// Update viewport
|
||
this.viewport.update(deltaT);
|
||
}
|
||
/**
|
||
* Collects renderable sets and coordinates with the RenderingManager to draw the Scene
|
||
*/
|
||
render() {
|
||
// Get the visible set of nodes
|
||
let visibleSet = this.sceneGraph.getVisibleSet();
|
||
// Add parallax layer items to the visible set (we're rendering them all for now)
|
||
this.parallaxLayers.forEach(key => {
|
||
let pLayer = this.parallaxLayers.get(key);
|
||
for (let node of pLayer.getItems()) {
|
||
if (node instanceof CanvasNode_1.default) {
|
||
visibleSet.push(node);
|
||
}
|
||
}
|
||
});
|
||
// Send the visible set, tilemaps, and uiLayers to the renderer
|
||
this.renderingManager.render(visibleSet, this.tilemaps, this.uiLayers);
|
||
let nodes = this.sceneGraph.getAllNodes();
|
||
this.tilemaps.forEach(tilemap => tilemap.visible ? nodes.push(tilemap) : 0);
|
||
Debug_1.default.setNodes(nodes);
|
||
}
|
||
/**
|
||
* Sets the scene as running or not
|
||
* @param running True if the Scene should be running, false if not
|
||
*/
|
||
setRunning(running) {
|
||
this.running = running;
|
||
}
|
||
/**
|
||
* Returns whether or not the Scene is running
|
||
* @returns True if the scene is running, false otherwise
|
||
*/
|
||
isRunning() {
|
||
return this.running;
|
||
}
|
||
/**
|
||
* Removes a node from this Scene
|
||
* @param node The node to remove
|
||
*/
|
||
remove(node) {
|
||
// Remove from the scene graph
|
||
if (node instanceof CanvasNode_1.default) {
|
||
this.sceneGraph.removeNode(node);
|
||
}
|
||
}
|
||
/** Destroys this scene and all nodes in it */
|
||
destroy() {
|
||
for (let node of this.sceneGraph.getAllNodes()) {
|
||
node.destroy();
|
||
}
|
||
for (let tilemap of this.tilemaps) {
|
||
tilemap.destroy();
|
||
}
|
||
this.receiver.destroy();
|
||
delete this.sceneGraph;
|
||
delete this.physicsManager;
|
||
delete this.navManager;
|
||
delete this.aiManager;
|
||
delete this.receiver;
|
||
}
|
||
/**
|
||
* Adds a new layer to the scene and returns it
|
||
* @param name The name of the new layer
|
||
* @param depth The depth of the layer
|
||
* @returns The newly created Layer
|
||
*/
|
||
addLayer(name, depth) {
|
||
if (this.layers.has(name) || this.parallaxLayers.has(name) || this.uiLayers.has(name)) {
|
||
throw `Layer with name ${name} already exists`;
|
||
}
|
||
let layer = new Layer_1.default(this, name);
|
||
this.layers.add(name, layer);
|
||
if (depth) {
|
||
layer.setDepth(depth);
|
||
}
|
||
return layer;
|
||
}
|
||
/**
|
||
* Adds a new parallax layer to this scene and returns it
|
||
* @param name The name of the parallax layer
|
||
* @param parallax The parallax level
|
||
* @param depth The depth of the layer
|
||
* @returns The newly created ParallaxLayer
|
||
*/
|
||
addParallaxLayer(name, parallax, depth) {
|
||
if (this.layers.has(name) || this.parallaxLayers.has(name) || this.uiLayers.has(name)) {
|
||
throw `Layer with name ${name} already exists`;
|
||
}
|
||
let layer = new ParallaxLayer_1.default(this, name, parallax);
|
||
this.parallaxLayers.add(name, layer);
|
||
if (depth) {
|
||
layer.setDepth(depth);
|
||
}
|
||
return layer;
|
||
}
|
||
/**
|
||
* Adds a new UILayer to the scene
|
||
* @param name The name of the new UIlayer
|
||
* @returns The newly created UILayer
|
||
*/
|
||
addUILayer(name) {
|
||
if (this.layers.has(name) || this.parallaxLayers.has(name) || this.uiLayers.has(name)) {
|
||
throw `Layer with name ${name} already exists`;
|
||
}
|
||
let layer = new UILayer_1.default(this, name);
|
||
this.uiLayers.add(name, layer);
|
||
return layer;
|
||
}
|
||
/**
|
||
* Gets a layer from the scene by name if it exists.
|
||
* This can be a Layer or any of its subclasses
|
||
* @param name The name of the layer
|
||
* @returns The Layer found with that name
|
||
*/
|
||
getLayer(name) {
|
||
if (this.layers.has(name)) {
|
||
return this.layers.get(name);
|
||
}
|
||
else if (this.parallaxLayers.has(name)) {
|
||
return this.parallaxLayers.get(name);
|
||
}
|
||
else if (this.uiLayers.has(name)) {
|
||
return this.uiLayers.get(name);
|
||
}
|
||
else {
|
||
throw `Requested layer ${name} does not exist.`;
|
||
}
|
||
}
|
||
/**
|
||
* Returns true if this layer is a ParallaxLayer
|
||
* @param name The name of the layer
|
||
* @returns True if this layer is a ParallaxLayer
|
||
*/
|
||
isParallaxLayer(name) {
|
||
return this.parallaxLayers.has(name);
|
||
}
|
||
/**
|
||
* Returns true if this layer is a UILayer
|
||
* @param name The name of the layer
|
||
* @returns True if this layer is ParallaxLayer
|
||
*/
|
||
isUILayer(name) {
|
||
return this.uiLayers.has(name);
|
||
}
|
||
/**
|
||
* Returns the translation of this node with respect to camera space (due to the viewport moving).
|
||
* This value is affected by the parallax level of the @reference[Layer] the node is on.
|
||
* @param node The node to check the viewport with respect to
|
||
* @returns A Vec2 containing the translation of viewport with respect to this node.
|
||
*/
|
||
getViewTranslation(node) {
|
||
let layer = node.getLayer();
|
||
if (layer instanceof ParallaxLayer_1.default || layer instanceof UILayer_1.default) {
|
||
return this.viewport.getOrigin().mult(layer.parallax);
|
||
}
|
||
else {
|
||
return this.viewport.getOrigin();
|
||
}
|
||
}
|
||
/**
|
||
* Returns the scale level of the view
|
||
* @returns The zoom level of the viewport
|
||
*/
|
||
getViewScale() {
|
||
return this.viewport.getZoomLevel();
|
||
}
|
||
/**
|
||
* Returns the Viewport associated with this scene
|
||
* @returns The current Viewport
|
||
*/
|
||
getViewport() {
|
||
return this.viewport;
|
||
}
|
||
/**
|
||
* Gets the world size of this Scene
|
||
* @returns The world size in a Vec2
|
||
*/
|
||
getWorldSize() {
|
||
return this.worldSize;
|
||
}
|
||
/**
|
||
* Gets the SceneGraph associated with this Scene
|
||
* @returns The SceneGraph
|
||
*/
|
||
getSceneGraph() {
|
||
return this.sceneGraph;
|
||
}
|
||
/**
|
||
* Gets the PhysicsManager associated with this Scene
|
||
* @returns The PhysicsManager
|
||
*/
|
||
getPhysicsManager() {
|
||
return this.physicsManager;
|
||
}
|
||
/**
|
||
* Gets the NavigationManager associated with this Scene
|
||
* @returns The NavigationManager
|
||
*/
|
||
getNavigationManager() {
|
||
return this.navManager;
|
||
}
|
||
/**
|
||
* Gets the AIManager associated with this Scene
|
||
* @returns The AIManager
|
||
*/
|
||
getAIManager() {
|
||
return this.aiManager;
|
||
}
|
||
/**
|
||
* Generates an ID for a GameNode
|
||
* @returns The new ID
|
||
*/
|
||
generateId() {
|
||
return this.sceneManager.generateId();
|
||
}
|
||
/**
|
||
* Retrieves a Tilemap in this Scene
|
||
* @param name The name of the Tilemap
|
||
* @returns The Tilemap, if one this name exists, otherwise null
|
||
*/
|
||
getTilemap(name) {
|
||
for (let tilemap of this.tilemaps) {
|
||
if (tilemap.name === name) {
|
||
return tilemap;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
exports.default = Scene;
|
||
|
||
},{"../AI/AIManager":3,"../DataTypes/Map":10,"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Events/Emitter":27,"../Events/Receiver":31,"../Nodes/CanvasNode":39,"../Pathfinding/NavigationManager":57,"../Physics/BasicPhysicsManager":60,"../Rendering/Animations/ParticleSystemManager":68,"../Rendering/Animations/TweenManager":70,"../ResourceManager/ResourceManager":83,"../SceneGraph/SceneGraphArray":94,"../Timing/TimerManager":98,"./Factories/FactoryManager":85,"./Layer":87,"./Layers/ParallaxLayer":88,"./Layers/UILayer":89,"./SceneOptions":92}],91:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const ResourceManager_1 = require("../ResourceManager/ResourceManager");
|
||
/**
|
||
* The SceneManager acts as an interface to create Scenes, and handles the lifecycle methods of Scenes.
|
||
* It gives Scenes access to information they need from the @reference[Game] class while keeping a layer of separation.
|
||
*/
|
||
class SceneManager {
|
||
/**
|
||
* Creates a new SceneManager
|
||
* @param viewport The Viewport of the game
|
||
* @param game The Game instance
|
||
* @param renderingManager The RenderingManager of the game
|
||
*/
|
||
constructor(viewport, renderingManager) {
|
||
this.resourceManager = ResourceManager_1.default.getInstance();
|
||
this.viewport = viewport;
|
||
this.renderingManager = renderingManager;
|
||
this.idCounter = 0;
|
||
this.pendingScene = null;
|
||
}
|
||
/**
|
||
* Add a scene as the main scene.
|
||
* Use this method if you've created a subclass of Scene, and you want to add it as the main Scene.
|
||
* @param constr The constructor of the scene to add
|
||
* @param init An object to pass to the init function of the new scene
|
||
*/
|
||
changeToScene(constr, init, options) {
|
||
console.log("Creating the new scene - change is pending until next update");
|
||
this.pendingScene = new constr(this.viewport, this, this.renderingManager, options);
|
||
this.pendingSceneInit = init;
|
||
}
|
||
doSceneChange() {
|
||
console.log("Performing scene change");
|
||
this.viewport.setCenter(this.viewport.getHalfSize().x, this.viewport.getHalfSize().y);
|
||
if (this.currentScene) {
|
||
console.log("Unloading old scene");
|
||
this.currentScene.unloadScene();
|
||
console.log("Destroying old scene");
|
||
this.currentScene.destroy();
|
||
}
|
||
console.log("Unloading old resources...");
|
||
this.resourceManager.unloadAllResources();
|
||
// Make the pending scene the current one
|
||
this.currentScene = this.pendingScene;
|
||
// Make the pending scene null
|
||
this.pendingScene = null;
|
||
// Init the scene
|
||
this.currentScene.initScene(this.pendingSceneInit);
|
||
// Enqueue all scene asset loads
|
||
this.currentScene.loadScene();
|
||
// Load all assets
|
||
console.log("Starting Scene Load");
|
||
this.resourceManager.loadResourcesFromQueue(() => {
|
||
console.log("Starting Scene");
|
||
this.currentScene.startScene();
|
||
this.currentScene.setRunning(true);
|
||
});
|
||
this.renderingManager.setScene(this.currentScene);
|
||
}
|
||
/**
|
||
* Generates a unique ID
|
||
* @returns A new ID
|
||
*/
|
||
generateId() {
|
||
return this.idCounter++;
|
||
}
|
||
/**
|
||
* Renders the current Scene
|
||
*/
|
||
render() {
|
||
if (this.currentScene) {
|
||
this.currentScene.render();
|
||
}
|
||
}
|
||
/**
|
||
* Updates the current Scene
|
||
* @param deltaT The timestep of the Scene
|
||
*/
|
||
update(deltaT) {
|
||
if (this.pendingScene !== null) {
|
||
this.doSceneChange();
|
||
}
|
||
if (this.currentScene && this.currentScene.isRunning()) {
|
||
this.currentScene.update(deltaT);
|
||
}
|
||
}
|
||
}
|
||
exports.default = SceneManager;
|
||
|
||
},{"../ResourceManager/ResourceManager":83}],92:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
// @ignorePage
|
||
/**
|
||
* The options to give a @reference[Scene] for initialization
|
||
*/
|
||
class SceneOptions {
|
||
static parse(options) {
|
||
let sOpt = new SceneOptions();
|
||
if (options.physics === undefined) {
|
||
sOpt.physics = { groups: undefined, collisions: undefined };
|
||
}
|
||
else {
|
||
sOpt.physics = options.physics;
|
||
}
|
||
return sOpt;
|
||
}
|
||
}
|
||
exports.default = SceneOptions;
|
||
|
||
},{}],93:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
/**
|
||
* An abstract interface of a SceneGraph.
|
||
* Exposes methods for use by other code, but leaves the implementation up to the subclasses.
|
||
* The SceneGraph manages the positions of all GameNodes, and can easily prune a visible set for rendering.
|
||
*/
|
||
class SceneGraph {
|
||
/**
|
||
* Creates a new SceneGraph
|
||
* @param viewport The viewport
|
||
* @param scene The Scene this SceneGraph belongs to
|
||
*/
|
||
constructor(viewport, scene) {
|
||
this.viewport = viewport;
|
||
this.scene = scene;
|
||
this.nodeMap = new Array();
|
||
this.idCounter = 0;
|
||
}
|
||
/**
|
||
* Add a node to the SceneGraph
|
||
* @param node The CanvasNode to add to the SceneGraph
|
||
* @returns The SceneGraph ID of this newly added CanvasNode
|
||
*/
|
||
addNode(node) {
|
||
this.nodeMap[node.id] = node;
|
||
this.addNodeSpecific(node, this.idCounter);
|
||
this.idCounter += 1;
|
||
return this.idCounter - 1;
|
||
}
|
||
;
|
||
/**
|
||
* Removes a node from the SceneGraph
|
||
* @param node The node to remove
|
||
*/
|
||
removeNode(node) {
|
||
// Find and remove node in O(n)
|
||
this.nodeMap[node.id] = undefined;
|
||
this.removeNodeSpecific(node, node.id);
|
||
}
|
||
;
|
||
/**
|
||
* Get a specific node using its id
|
||
* @param id The id of the CanvasNode to retrieve
|
||
* @returns The node with this ID
|
||
*/
|
||
getNode(id) {
|
||
return this.nodeMap[id];
|
||
}
|
||
/**
|
||
* Returns the nodes at specific coordinates
|
||
* @param vecOrX The x-coordinate of the position, or the coordinates in a Vec2
|
||
* @param y The y-coordinate of the position
|
||
* @returns An array of nodes found at the position provided
|
||
*/
|
||
getNodesAt(vecOrX, y = null) {
|
||
if (vecOrX instanceof Vec2_1.default) {
|
||
return this.getNodesAtCoords(vecOrX.x, vecOrX.y);
|
||
}
|
||
else {
|
||
return this.getNodesAtCoords(vecOrX, y);
|
||
}
|
||
}
|
||
/**
|
||
* Returns all nodes in the SceneGraph
|
||
* @returns An Array containing all nodes in the SceneGraph
|
||
*/
|
||
getAllNodes() {
|
||
let arr = new Array();
|
||
for (let i = 0; i < this.nodeMap.length; i++) {
|
||
if (this.nodeMap[i] !== undefined) {
|
||
arr.push(this.nodeMap[i]);
|
||
}
|
||
}
|
||
return arr;
|
||
}
|
||
}
|
||
exports.default = SceneGraph;
|
||
|
||
},{"../DataTypes/Vec2":24}],94:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const SceneGraph_1 = require("./SceneGraph");
|
||
const Stats_1 = require("../Debug/Stats");
|
||
/**
|
||
* An implementation of a SceneGraph that simply stored CanvasNodes in an array.
|
||
*/
|
||
class SceneGraphArray extends SceneGraph_1.default {
|
||
/**
|
||
* Creates a new SceneGraphArray
|
||
* @param viewport The Viewport
|
||
* @param scene The Scene this SceneGraph belongs to
|
||
*/
|
||
constructor(viewport, scene) {
|
||
super(viewport, scene);
|
||
this.nodeList = new Array();
|
||
}
|
||
// @override
|
||
addNodeSpecific(node, id) {
|
||
this.nodeList.push(node);
|
||
}
|
||
// @override
|
||
removeNodeSpecific(node, id) {
|
||
let index = this.nodeList.indexOf(node);
|
||
if (index > -1) {
|
||
this.nodeList.splice(index, 1);
|
||
}
|
||
}
|
||
// @override
|
||
getNodesAtCoords(x, y) {
|
||
let results = [];
|
||
for (let node of this.nodeList) {
|
||
if (node.contains(x, y)) {
|
||
results.push(node);
|
||
}
|
||
}
|
||
return results;
|
||
}
|
||
// @override
|
||
getNodesInRegion(boundary) {
|
||
let t0 = performance.now();
|
||
let results = [];
|
||
for (let node of this.nodeList) {
|
||
if (boundary.overlaps(node.boundary)) {
|
||
results.push(node);
|
||
}
|
||
}
|
||
let t1 = performance.now();
|
||
Stats_1.default.log("sgquery", (t1 - t0));
|
||
return results;
|
||
}
|
||
update(deltaT) {
|
||
let t0 = performance.now();
|
||
for (let node of this.nodeList) {
|
||
if (!node.getLayer().isPaused()) {
|
||
node.update(deltaT);
|
||
}
|
||
}
|
||
let t1 = performance.now();
|
||
Stats_1.default.log("sgupdate", (t1 - t0));
|
||
}
|
||
render(ctx) { }
|
||
// @override
|
||
getVisibleSet() {
|
||
let visibleSet = new Array();
|
||
for (let node of this.nodeList) {
|
||
if (!node.getLayer().isHidden() && node.visible && this.viewport.includes(node)) {
|
||
visibleSet.push(node);
|
||
}
|
||
}
|
||
return visibleSet;
|
||
}
|
||
}
|
||
exports.default = SceneGraphArray;
|
||
|
||
},{"../Debug/Stats":26,"./SceneGraph":93}],95:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../DataTypes/Vec2");
|
||
const MathUtils_1 = require("../Utils/MathUtils");
|
||
const Queue_1 = require("../DataTypes/Queue");
|
||
const AABB_1 = require("../DataTypes/Shapes/AABB");
|
||
const Input_1 = require("../Input/Input");
|
||
const ParallaxLayer_1 = require("../Scene/Layers/ParallaxLayer");
|
||
const UILayer_1 = require("../Scene/Layers/UILayer");
|
||
/**
|
||
* The viewport of the game. Corresponds to the visible window displayed in the browser.
|
||
* The viewport keeps track of its position in the game world, and can act as a camera to follow objects.
|
||
*/
|
||
class Viewport {
|
||
constructor(canvasSize, zoomLevel) {
|
||
/** The amount that is zoomed in or out. */
|
||
this.ZOOM_FACTOR = 1.2;
|
||
this.view = new AABB_1.default(Vec2_1.default.ZERO, Vec2_1.default.ZERO);
|
||
this.boundary = new AABB_1.default(Vec2_1.default.ZERO, Vec2_1.default.ZERO);
|
||
this.lastPositions = new Queue_1.default();
|
||
this.smoothingFactor = 10;
|
||
this.scrollZoomEnabled = false;
|
||
this.canvasSize = Vec2_1.default.ZERO;
|
||
this.focus = Vec2_1.default.ZERO;
|
||
// Set the size of the canvas
|
||
this.setCanvasSize(canvasSize);
|
||
// Set the size of the viewport
|
||
this.setSize(canvasSize);
|
||
this.setZoomLevel(zoomLevel);
|
||
// Set the center (and make the viewport stay there)
|
||
this.setCenter(this.view.halfSize.clone());
|
||
this.setFocus(this.view.halfSize.clone());
|
||
}
|
||
/** Enables the viewport to zoom in and out */
|
||
enableZoom() {
|
||
this.scrollZoomEnabled = true;
|
||
}
|
||
/**
|
||
* Returns the position of the viewport
|
||
* @returns The center of the viewport as a Vec2
|
||
*/
|
||
getCenter() {
|
||
return this.view.center;
|
||
}
|
||
/**
|
||
* Returns a new Vec2 with the origin of the viewport
|
||
* @returns The top left cornder of the Vieport as a Vec2
|
||
*/
|
||
getOrigin() {
|
||
return new Vec2_1.default(this.view.left, this.view.top);
|
||
}
|
||
/**
|
||
* Returns the region visible to this viewport
|
||
* @returns The AABB containing the region visible to the viewport
|
||
*/
|
||
getView() {
|
||
return this.view;
|
||
}
|
||
/**
|
||
* Set the position of the viewport
|
||
* @param vecOrX The new position or the x-coordinate of the new position
|
||
* @param y The y-coordinate of the new position
|
||
*/
|
||
setCenter(vecOrX, y = null) {
|
||
let pos;
|
||
if (vecOrX instanceof Vec2_1.default) {
|
||
pos = vecOrX;
|
||
}
|
||
else {
|
||
pos = new Vec2_1.default(vecOrX, y);
|
||
}
|
||
this.view.center = pos;
|
||
}
|
||
/**
|
||
* Returns the size of the viewport as a Vec2
|
||
* @returns The half-size of the viewport as a Vec2
|
||
*/
|
||
getHalfSize() {
|
||
return this.view.getHalfSize();
|
||
}
|
||
/**
|
||
* Sets the size of the viewport
|
||
* @param vecOrX The new width of the viewport or the new size as a Vec2
|
||
* @param y The new height of the viewport
|
||
*/
|
||
setSize(vecOrX, y = null) {
|
||
if (vecOrX instanceof Vec2_1.default) {
|
||
this.view.setHalfSize(vecOrX.scaled(1 / 2));
|
||
}
|
||
else {
|
||
this.view.setHalfSize(new Vec2_1.default(vecOrX / 2, y / 2));
|
||
}
|
||
}
|
||
/**
|
||
* Sets the half-size of the viewport
|
||
* @param vecOrX The new half-width of the viewport or the new half-size as a Vec2
|
||
* @param y The new height of the viewport
|
||
*/
|
||
setHalfSize(vecOrX, y = null) {
|
||
if (vecOrX instanceof Vec2_1.default) {
|
||
this.view.setHalfSize(vecOrX.clone());
|
||
}
|
||
else {
|
||
this.view.setHalfSize(new Vec2_1.default(vecOrX, y));
|
||
}
|
||
}
|
||
/**
|
||
* Updates the viewport with the size of the current Canvas
|
||
* @param vecOrX The width of the canvas, or the canvas size as a Vec2
|
||
* @param y The height of the canvas
|
||
*/
|
||
setCanvasSize(vecOrX, y = null) {
|
||
if (vecOrX instanceof Vec2_1.default) {
|
||
this.canvasSize = vecOrX.clone();
|
||
}
|
||
else {
|
||
this.canvasSize = new Vec2_1.default(vecOrX, y);
|
||
}
|
||
}
|
||
/**
|
||
* Sets the zoom level of the viewport
|
||
* @param zoom The zoom level
|
||
*/
|
||
setZoomLevel(zoom) {
|
||
this.view.halfSize.copy(this.canvasSize.scaled(1 / zoom / 2));
|
||
}
|
||
/**
|
||
* Gets the zoom level of the viewport
|
||
* @returns The zoom level
|
||
*/
|
||
getZoomLevel() {
|
||
return this.canvasSize.x / this.view.hw / 2;
|
||
}
|
||
/**
|
||
* Sets the smoothing factor for the viewport movement.
|
||
* @param smoothingFactor The smoothing factor for the viewport
|
||
*/
|
||
setSmoothingFactor(smoothingFactor) {
|
||
if (smoothingFactor < 1)
|
||
smoothingFactor = 1;
|
||
this.smoothingFactor = smoothingFactor;
|
||
}
|
||
/**
|
||
* Tells the viewport to focus on a point. Overidden by "following".
|
||
* @param focus The point the viewport should focus on
|
||
*/
|
||
setFocus(focus) {
|
||
this.focus.copy(focus);
|
||
}
|
||
/**
|
||
* Returns true if the CanvasNode is inside of the viewport
|
||
* @param node The node to check
|
||
* @returns True if the node is currently visible in the viewport, false if not
|
||
*/
|
||
includes(node) {
|
||
let parallax = node.getLayer() instanceof ParallaxLayer_1.default || node.getLayer() instanceof UILayer_1.default ? node.getLayer().parallax : new Vec2_1.default(1, 1);
|
||
let center = this.view.center.clone();
|
||
this.view.center.mult(parallax);
|
||
let overlaps = this.view.overlaps(node.boundary);
|
||
this.view.center = center;
|
||
return overlaps;
|
||
}
|
||
// TODO: Put some error handling on this for trying to make the bounds too small for the viewport
|
||
// TODO: This should probably be done automatically, or should consider the aspect ratio or something
|
||
/**
|
||
* Sets the bounds of the viewport
|
||
* @param lowerX The left edge of the viewport
|
||
* @param lowerY The top edge of the viewport
|
||
* @param upperX The right edge of the viewport
|
||
* @param upperY The bottom edge of the viewport
|
||
*/
|
||
setBounds(lowerX, lowerY, upperX, upperY) {
|
||
let hwidth = (upperX - lowerX) / 2;
|
||
let hheight = (upperY - lowerY) / 2;
|
||
let x = lowerX + hwidth;
|
||
let y = lowerY + hheight;
|
||
this.boundary.center.set(x, y);
|
||
this.boundary.halfSize.set(hwidth, hheight);
|
||
}
|
||
/**
|
||
* Make the viewport follow the specified GameNode
|
||
* @param node The GameNode to follow
|
||
*/
|
||
follow(node) {
|
||
this.following = node;
|
||
}
|
||
updateView() {
|
||
if (this.lastPositions.getSize() > this.smoothingFactor) {
|
||
this.lastPositions.dequeue();
|
||
}
|
||
// Get the average of the last 10 positions
|
||
let pos = Vec2_1.default.ZERO;
|
||
this.lastPositions.forEach(position => pos.add(position));
|
||
pos.scale(1 / this.lastPositions.getSize());
|
||
// Set this position either to the object or to its bounds
|
||
pos.x = MathUtils_1.default.clamp(pos.x, this.boundary.left + this.view.hw, this.boundary.right - this.view.hw);
|
||
pos.y = MathUtils_1.default.clamp(pos.y, this.boundary.top + this.view.hh, this.boundary.bottom - this.view.hh);
|
||
// Assure there are no lines in the tilemap
|
||
pos.x = Math.floor(pos.x);
|
||
pos.y = Math.floor(pos.y);
|
||
this.view.center.copy(pos);
|
||
}
|
||
update(deltaT) {
|
||
// If zoom is enabled
|
||
if (this.scrollZoomEnabled) {
|
||
if (Input_1.default.didJustScroll()) {
|
||
let currentSize = this.view.getHalfSize().clone();
|
||
if (Input_1.default.getScrollDirection() < 0) {
|
||
// Zoom in
|
||
currentSize.scale(1 / this.ZOOM_FACTOR);
|
||
}
|
||
else {
|
||
// Zoom out
|
||
currentSize.scale(this.ZOOM_FACTOR);
|
||
}
|
||
if (currentSize.x > this.boundary.hw) {
|
||
let factor = this.boundary.hw / currentSize.x;
|
||
currentSize.x = this.boundary.hw;
|
||
currentSize.y *= factor;
|
||
}
|
||
if (currentSize.y > this.boundary.hh) {
|
||
let factor = this.boundary.hh / currentSize.y;
|
||
currentSize.y = this.boundary.hh;
|
||
currentSize.x *= factor;
|
||
}
|
||
this.view.setHalfSize(currentSize);
|
||
}
|
||
}
|
||
// If viewport is following an object
|
||
if (this.following) {
|
||
// Update our list of previous positions
|
||
this.lastPositions.enqueue(this.following.position.clone());
|
||
}
|
||
else {
|
||
this.lastPositions.enqueue(this.focus);
|
||
}
|
||
this.updateView();
|
||
}
|
||
}
|
||
exports.default = Viewport;
|
||
|
||
},{"../DataTypes/Queue":14,"../DataTypes/Shapes/AABB":16,"../DataTypes/Vec2":24,"../Input/Input":32,"../Scene/Layers/ParallaxLayer":88,"../Scene/Layers/UILayer":89,"../Utils/MathUtils":102}],96:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.MAX_AUDIO_CHANNELS = exports.AudioChannelType = void 0;
|
||
const Map_1 = require("../DataTypes/Map");
|
||
const Receiver_1 = require("../Events/Receiver");
|
||
const ResourceManager_1 = require("../ResourceManager/ResourceManager");
|
||
const GameEventType_1 = require("../Events/GameEventType");
|
||
/**
|
||
* Manages any sounds or music needed for the game.
|
||
* Through the EventQueue, exposes interface to play sounds so GameNodes can activate sounds without
|
||
* needing direct references to the audio system
|
||
*/
|
||
class AudioManager {
|
||
constructor() {
|
||
this.initAudio();
|
||
this.receiver = new Receiver_1.default();
|
||
this.receiver.subscribe([
|
||
GameEventType_1.GameEventType.PLAY_SOUND,
|
||
GameEventType_1.GameEventType.STOP_SOUND,
|
||
GameEventType_1.GameEventType.PLAY_MUSIC,
|
||
GameEventType_1.GameEventType.PLAY_SFX,
|
||
GameEventType_1.GameEventType.MUTE_CHANNEL,
|
||
GameEventType_1.GameEventType.UNMUTE_CHANNEL
|
||
]);
|
||
this.currentSounds = new Map_1.default();
|
||
this.gainNodes = new Array(exports.MAX_AUDIO_CHANNELS);
|
||
this.initGainNodes();
|
||
}
|
||
/**
|
||
* Get the instance of the AudioManager class or create a new one if none exists
|
||
* @returns The AudioManager
|
||
*/
|
||
static getInstance() {
|
||
if (!this.instance) {
|
||
this.instance = new AudioManager();
|
||
}
|
||
return this.instance;
|
||
}
|
||
/**
|
||
* Initializes the webAudio context
|
||
*/
|
||
initAudio() {
|
||
try {
|
||
window.AudioContext = window.AudioContext; // || window.webkitAudioContext;
|
||
this.audioCtx = new AudioContext();
|
||
console.log('Web Audio API successfully loaded');
|
||
}
|
||
catch (e) {
|
||
console.warn('Web Audio API is not supported in this browser');
|
||
}
|
||
}
|
||
initGainNodes() {
|
||
for (let i = 0; i < exports.MAX_AUDIO_CHANNELS; i++) {
|
||
this.gainNodes[i] = this.audioCtx.createGain();
|
||
}
|
||
}
|
||
/**
|
||
* Returns the current audio context
|
||
* @returns The AudioContext
|
||
*/
|
||
getAudioContext() {
|
||
return this.audioCtx;
|
||
}
|
||
/*
|
||
According to the MDN, create a new sound for every call:
|
||
|
||
An AudioBufferSourceNode can only be played once; after each call to start(), you have to create a new node
|
||
if you want to play the same sound again. Fortunately, these nodes are very inexpensive to create, and the
|
||
actual AudioBuffers can be reused for multiple plays of the sound. Indeed, you can use these nodes in a
|
||
"fire and forget" manner: create the node, call start() to begin playing the sound, and don't even bother to
|
||
hold a reference to it. It will automatically be garbage-collected at an appropriate time, which won't be
|
||
until sometime after the sound has finished playing.
|
||
*/
|
||
/**
|
||
* Creates a new sound from the key of a loaded audio file
|
||
* @param key The key of the loaded audio file to create a new sound for
|
||
* @returns The newly created AudioBuffer
|
||
*/
|
||
createSound(key, holdReference, channel, options) {
|
||
// Get audio buffer
|
||
let buffer = ResourceManager_1.default.getInstance().getAudio(key);
|
||
// Create a sound source
|
||
var source = this.audioCtx.createBufferSource();
|
||
// Tell the source which sound to play
|
||
source.buffer = buffer;
|
||
// Add any additional nodes
|
||
const nodes = [source];
|
||
// Do any additional nodes here?
|
||
// Of course, there aren't any supported yet...
|
||
// Add the gain node for this channel
|
||
nodes.push(this.gainNodes[channel]);
|
||
// Connect any nodes along the path
|
||
for (let i = 1; i < nodes.length; i++) {
|
||
nodes[i - 1].connect(nodes[i]);
|
||
}
|
||
// Connect the source to the context's destination
|
||
nodes[nodes.length - 1].connect(this.audioCtx.destination);
|
||
return source;
|
||
}
|
||
/**
|
||
* Play the sound specified by the key
|
||
* @param key The key of the sound to play
|
||
* @param loop A boolean for whether or not to loop the sound
|
||
* @param holdReference A boolean for whether or not we want to hold on to a reference of the audio node. This is good for playing music on a loop that will eventually need to be stopped.
|
||
*/
|
||
playSound(key, loop, holdReference, channel, options) {
|
||
let sound = this.createSound(key, holdReference, channel, options);
|
||
if (loop) {
|
||
sound.loop = true;
|
||
}
|
||
// Add a reference of the new sound to a map. This will allow us to stop a looping or long sound at a later time
|
||
if (holdReference) {
|
||
this.currentSounds.add(key, sound);
|
||
}
|
||
sound.start();
|
||
}
|
||
/**
|
||
* Stop the sound specified by the key
|
||
*/
|
||
stopSound(key) {
|
||
let sound = this.currentSounds.get(key);
|
||
if (sound) {
|
||
sound.stop();
|
||
this.currentSounds.delete(key);
|
||
}
|
||
}
|
||
muteChannel(channel) {
|
||
this.gainNodes[channel].gain.setValueAtTime(0, this.audioCtx.currentTime);
|
||
}
|
||
unmuteChannel(channel) {
|
||
this.gainNodes[channel].gain.setValueAtTime(1, this.audioCtx.currentTime);
|
||
}
|
||
/**
|
||
* Sets the volume of a channel using the GainNode for that channel. For more
|
||
* information on GainNodes, see https://developer.mozilla.org/en-US/docs/Web/API/GainNode
|
||
* @param channel The audio channel to set the volume for
|
||
* @param volume The volume of the channel. 0 is muted. Values below zero will be set to zero.
|
||
*/
|
||
static setVolume(channel, volume) {
|
||
if (volume < 0) {
|
||
volume = 0;
|
||
}
|
||
const am = AudioManager.getInstance();
|
||
am.gainNodes[channel].gain.setValueAtTime(volume, am.audioCtx.currentTime);
|
||
}
|
||
/**
|
||
* Returns the GainNode for this channel.
|
||
* Learn more about GainNodes here https://developer.mozilla.org/en-US/docs/Web/API/GainNode
|
||
* DON'T USE THIS UNLESS YOU KNOW WHAT YOU'RE DOING
|
||
* @param channel The channel
|
||
* @returns The GainNode for the specified channel
|
||
*/
|
||
getChannelGainNode(channel) {
|
||
return this.gainNodes[channel];
|
||
}
|
||
update(deltaT) {
|
||
// Play each audio clip requested
|
||
// TODO - Add logic to merge sounds if there are multiple of the same key
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
if (event.type === GameEventType_1.GameEventType.PLAY_SOUND || event.type === GameEventType_1.GameEventType.PLAY_MUSIC || event.type === GameEventType_1.GameEventType.PLAY_SFX) {
|
||
let soundKey = event.data.get("key");
|
||
let loop = event.data.get("loop");
|
||
let holdReference = event.data.get("holdReference");
|
||
let channel = AudioChannelType.DEFAULT;
|
||
if (event.type === GameEventType_1.GameEventType.PLAY_MUSIC) {
|
||
channel = AudioChannelType.MUSIC;
|
||
}
|
||
else if (GameEventType_1.GameEventType.PLAY_SFX) {
|
||
channel = AudioChannelType.SFX;
|
||
}
|
||
else if (event.data.has("channel")) {
|
||
channel = event.data.get("channel");
|
||
}
|
||
this.playSound(soundKey, loop, holdReference, channel, event.data);
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.STOP_SOUND) {
|
||
let soundKey = event.data.get("key");
|
||
this.stopSound(soundKey);
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.MUTE_CHANNEL) {
|
||
this.muteChannel(event.data.get("channel"));
|
||
}
|
||
if (event.type === GameEventType_1.GameEventType.UNMUTE_CHANNEL) {
|
||
this.unmuteChannel(event.data.get("channel"));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = AudioManager;
|
||
var AudioChannelType;
|
||
(function (AudioChannelType) {
|
||
AudioChannelType[AudioChannelType["DEFAULT"] = 0] = "DEFAULT";
|
||
AudioChannelType[AudioChannelType["SFX"] = 1] = "SFX";
|
||
AudioChannelType[AudioChannelType["MUSIC"] = 2] = "MUSIC";
|
||
AudioChannelType[AudioChannelType["CUSTOM_1"] = 3] = "CUSTOM_1";
|
||
AudioChannelType[AudioChannelType["CUSTOM_2"] = 4] = "CUSTOM_2";
|
||
AudioChannelType[AudioChannelType["CUSTOM_3"] = 5] = "CUSTOM_3";
|
||
AudioChannelType[AudioChannelType["CUSTOM_4"] = 6] = "CUSTOM_4";
|
||
AudioChannelType[AudioChannelType["CUSTOM_5"] = 7] = "CUSTOM_5";
|
||
AudioChannelType[AudioChannelType["CUSTOM_6"] = 8] = "CUSTOM_6";
|
||
AudioChannelType[AudioChannelType["CUSTOM_7"] = 9] = "CUSTOM_7";
|
||
AudioChannelType[AudioChannelType["CUSTOM_8"] = 10] = "CUSTOM_8";
|
||
AudioChannelType[AudioChannelType["CUSTOM_9"] = 11] = "CUSTOM_9";
|
||
})(AudioChannelType = exports.AudioChannelType || (exports.AudioChannelType = {}));
|
||
exports.MAX_AUDIO_CHANNELS = 12;
|
||
|
||
},{"../DataTypes/Map":10,"../Events/GameEventType":30,"../Events/Receiver":31,"../ResourceManager/ResourceManager":83}],97:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.TimerState = void 0;
|
||
const sword_enums_1 = require("../../shattered_sword/sword_enums");
|
||
const InputWrapper_1 = require("../../shattered_sword/Tools/InputWrapper");
|
||
const MathUtils_1 = require("../Utils/MathUtils");
|
||
const TimerManager_1 = require("./TimerManager");
|
||
/** */
|
||
class Timer {
|
||
constructor(time, onEnd, loop = false) {
|
||
// Register this timer
|
||
TimerManager_1.default.getInstance().addTimer(this);
|
||
this.totalTime = time;
|
||
this.timeLeft = 0;
|
||
this.onEnd = onEnd;
|
||
this.loop = loop;
|
||
this.state = TimerState.STOPPED;
|
||
this.numRuns = 0;
|
||
}
|
||
isStopped() {
|
||
return this.state === TimerState.STOPPED;
|
||
}
|
||
isPaused() {
|
||
return this.state === TimerState.PAUSED;
|
||
}
|
||
/**
|
||
* Returns whether or not this timer has been run before
|
||
* @returns true if it has been run at least once (after the latest reset), and false otherwise
|
||
*/
|
||
hasRun() {
|
||
return this.numRuns > 0;
|
||
}
|
||
start(time) {
|
||
if (time !== undefined) {
|
||
this.totalTime = time;
|
||
}
|
||
this.state = TimerState.ACTIVE;
|
||
this.timeLeft = this.totalTime;
|
||
}
|
||
/** Resets this timer. Sets the progress back to zero, and sets the number of runs back to zero */
|
||
reset() {
|
||
this.timeLeft = this.totalTime;
|
||
this.numRuns = 0;
|
||
}
|
||
pause() {
|
||
this.state = TimerState.PAUSED;
|
||
}
|
||
update(deltaT) {
|
||
if (this.state === TimerState.ACTIVE && InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) {
|
||
this.timeLeft -= deltaT * 1000;
|
||
if (this.timeLeft <= 0) {
|
||
this.timeLeft = MathUtils_1.default.clampLow0(this.timeLeft);
|
||
this.end();
|
||
}
|
||
}
|
||
}
|
||
end() {
|
||
// Update the state
|
||
this.state = TimerState.STOPPED;
|
||
this.numRuns += 1;
|
||
// Call the end function if there is one
|
||
if (this.onEnd) {
|
||
this.onEnd();
|
||
}
|
||
// Loop if we want to
|
||
if (this.loop) {
|
||
this.state = TimerState.ACTIVE;
|
||
this.timeLeft = this.totalTime;
|
||
}
|
||
}
|
||
toString() {
|
||
return "Timer: " + this.state + " - Time Left: " + this.timeLeft + "ms of " + this.totalTime + "ms";
|
||
}
|
||
}
|
||
exports.default = Timer;
|
||
var TimerState;
|
||
(function (TimerState) {
|
||
TimerState["ACTIVE"] = "ACTIVE";
|
||
TimerState["PAUSED"] = "PAUSED";
|
||
TimerState["STOPPED"] = "STOPPED";
|
||
})(TimerState = exports.TimerState || (exports.TimerState = {}));
|
||
|
||
},{"../../shattered_sword/Tools/InputWrapper":140,"../../shattered_sword/sword_enums":144,"../Utils/MathUtils":102,"./TimerManager":98}],98:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class TimerManager {
|
||
constructor() {
|
||
this.timers = new Array();
|
||
}
|
||
static getInstance() {
|
||
if (!this.instance) {
|
||
this.instance = new TimerManager();
|
||
}
|
||
return this.instance;
|
||
}
|
||
addTimer(timer) {
|
||
this.timers.push(timer);
|
||
}
|
||
clearTimers() {
|
||
this.timers = new Array();
|
||
}
|
||
update(deltaT) {
|
||
this.timers.forEach(timer => timer.update(deltaT));
|
||
}
|
||
}
|
||
exports.default = TimerManager;
|
||
|
||
},{}],99:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const MathUtils_1 = require("./MathUtils");
|
||
// TODO: This should be moved to the datatypes folder
|
||
/**
|
||
* A Color util class that keeps track of colors like a vector, but can be converted into a string format
|
||
*/
|
||
class Color {
|
||
/**
|
||
* Creates a new color
|
||
* @param r Red
|
||
* @param g Green
|
||
* @param b Blue
|
||
* @param a Alpha
|
||
*/
|
||
constructor(r = 0, g = 0, b = 0, a = 1) {
|
||
this.r = r;
|
||
this.g = g;
|
||
this.b = b;
|
||
this.a = a;
|
||
}
|
||
/**
|
||
* Transparent color
|
||
* @returns rgba(0, 0, 0, 0)
|
||
*/
|
||
static get TRANSPARENT() {
|
||
return new Color(0, 0, 0, 0);
|
||
}
|
||
/**
|
||
* Red color
|
||
* @returns rgb(255, 0, 0)
|
||
*/
|
||
static get RED() {
|
||
return new Color(255, 0, 0, 1);
|
||
}
|
||
/**
|
||
* Green color
|
||
* @returns rgb(0, 255, 0)
|
||
*/
|
||
static get GREEN() {
|
||
return new Color(0, 255, 0, 1);
|
||
}
|
||
/**
|
||
* Blue color
|
||
* @returns rgb(0, 0, 255)
|
||
*/
|
||
static get BLUE() {
|
||
return new Color(0, 0, 255, 1);
|
||
}
|
||
/**
|
||
* Yellow color
|
||
* @returns rgb(255, 255, 0)
|
||
*/
|
||
static get YELLOW() {
|
||
return new Color(255, 255, 0, 1);
|
||
}
|
||
/**
|
||
* Magenta color
|
||
* @returns rgb(255, 0, 255)
|
||
*/
|
||
static get MAGENTA() {
|
||
return new Color(255, 0, 255, 1);
|
||
}
|
||
/**
|
||
* Cyan color
|
||
* @returns rgb(0, 255, 255)
|
||
*/
|
||
static get CYAN() {
|
||
return new Color(0, 255, 255, 1);
|
||
}
|
||
/**
|
||
* White color
|
||
* @returns rgb(255, 255, 255)
|
||
*/
|
||
static get WHITE() {
|
||
return new Color(255, 255, 255, 1);
|
||
}
|
||
/**
|
||
* Black color
|
||
* @returns rgb(0, 0, 0)
|
||
*/
|
||
static get BLACK() {
|
||
return new Color(0, 0, 0, 1);
|
||
}
|
||
/**
|
||
* Orange color
|
||
* @returns rgb(255, 100, 0)
|
||
*/
|
||
static get ORANGE() {
|
||
return new Color(255, 100, 0, 1);
|
||
}
|
||
/**
|
||
* Sets the color to the values provided
|
||
* @param r Red
|
||
* @param g Green
|
||
* @param b Blue
|
||
* @param a Alpha
|
||
*/
|
||
set(r, g, b, a = 1) {
|
||
this.r = r;
|
||
this.g = g;
|
||
this.b = b;
|
||
this.a = a;
|
||
}
|
||
/**
|
||
* Returns a new color slightly lighter than the current color
|
||
* @returns A new lighter Color
|
||
*/
|
||
lighten() {
|
||
return new Color(MathUtils_1.default.clamp(this.r + 40, 0, 255), MathUtils_1.default.clamp(this.g + 40, 0, 255), MathUtils_1.default.clamp(this.b + 40, 0, 255), MathUtils_1.default.clamp(this.a + 10, 0, 255));
|
||
}
|
||
/**
|
||
* Returns a new color slightly darker than the current color
|
||
* @returns A new darker Color
|
||
*/
|
||
darken() {
|
||
return new Color(MathUtils_1.default.clamp(this.r - 40, 0, 255), MathUtils_1.default.clamp(this.g - 40, 0, 255), MathUtils_1.default.clamp(this.b - 40, 0, 255), MathUtils_1.default.clamp(this.a + 10, 0, 255));
|
||
}
|
||
/**
|
||
* Returns this color as an array
|
||
* @returns [r, g, b, a]
|
||
*/
|
||
toArray() {
|
||
return [this.r, this.g, this.b, this.a];
|
||
}
|
||
/**
|
||
* Returns the color as a string of the form #RRGGBB
|
||
* @returns #RRGGBB
|
||
*/
|
||
toString() {
|
||
return "#" + MathUtils_1.default.toHex(this.r, 2) + MathUtils_1.default.toHex(this.g, 2) + MathUtils_1.default.toHex(this.b, 2);
|
||
}
|
||
/**
|
||
* Returns the color as a string of the form rgb(r, g, b)
|
||
* @returns rgb(r, g, b)
|
||
*/
|
||
toStringRGB() {
|
||
return "rgb(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ")";
|
||
}
|
||
/**
|
||
* Returns the color as a string of the form rgba(r, g, b, a)
|
||
* @returns rgba(r, g, b, a)
|
||
*/
|
||
toStringRGBA() {
|
||
if (this.a === 0) {
|
||
return this.toStringRGB();
|
||
}
|
||
return "rgba(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ", " + this.a.toString() + ")";
|
||
}
|
||
/**
|
||
* Turns this color into a float32Array and changes color range to [0.0, 1.0]
|
||
* @returns a Float32Array containing the color
|
||
*/
|
||
toWebGL() {
|
||
return new Float32Array([
|
||
this.r / 255,
|
||
this.g / 255,
|
||
this.b / 255,
|
||
this.a
|
||
]);
|
||
}
|
||
static fromStringHex(str) {
|
||
let i = 0;
|
||
if (str.charAt(0) == "#")
|
||
i += 1;
|
||
let r = MathUtils_1.default.fromHex(str.substring(i, i + 2));
|
||
let g = MathUtils_1.default.fromHex(str.substring(i + 2, i + 4));
|
||
let b = MathUtils_1.default.fromHex(str.substring(i + 4, i + 6));
|
||
return new Color(r, g, b);
|
||
}
|
||
}
|
||
exports.default = Color;
|
||
|
||
},{"./MathUtils":102}],100:[function(require,module,exports){
|
||
"use strict";
|
||
// @ignorePage
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.EaseFunctionType = void 0;
|
||
class EaseFunctions {
|
||
static easeInOutSine(x) {
|
||
return -(Math.cos(Math.PI * x) - 1) / 2;
|
||
}
|
||
static easeOutInSine(x) {
|
||
return x < 0.5 ? -Math.cos(Math.PI * (x + 0.5)) / 2 : -Math.cos(Math.PI * (x - 0.5)) / 2 + 1;
|
||
}
|
||
static easeOutSine(x) {
|
||
return Math.sin((x * Math.PI) / 2);
|
||
}
|
||
static easeInSine(x) {
|
||
return 1 - Math.cos((x * Math.PI) / 2);
|
||
}
|
||
static easeInOutQuint(x) {
|
||
return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2;
|
||
}
|
||
static easeInOutQuad(x) {
|
||
return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
|
||
}
|
||
static easeOutInQuad(x) {
|
||
return x < 0.5 ? this.easeOutIn_OutPow(x, 2) : this.easeOutIn_InPow(x, 2);
|
||
}
|
||
static easeOutIn_OutPow(x, pow) {
|
||
return 0.5 - Math.pow(-2 * x + 1, pow) / 2;
|
||
}
|
||
static easeOutIn_InPow(x, pow) {
|
||
return 0.5 + Math.pow(2 * x - 1, pow) / 2;
|
||
}
|
||
}
|
||
exports.default = EaseFunctions;
|
||
var EaseFunctionType;
|
||
(function (EaseFunctionType) {
|
||
// SINE
|
||
EaseFunctionType["IN_OUT_SINE"] = "easeInOutSine";
|
||
EaseFunctionType["OUT_IN_SINE"] = "easeOutInSine";
|
||
EaseFunctionType["IN_SINE"] = "easeInSine";
|
||
EaseFunctionType["OUT_SINE"] = "easeOutSine";
|
||
// QUAD
|
||
EaseFunctionType["IN_OUT_QUAD"] = "easeInOutQuad";
|
||
EaseFunctionType["OUT_IN_QUAD"] = "easeOutInQuad";
|
||
// QUINT
|
||
EaseFunctionType["IN_OUT_QUINT"] = "easeInOutQuint";
|
||
})(EaseFunctionType = exports.EaseFunctionType || (exports.EaseFunctionType = {}));
|
||
|
||
},{}],101:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/** A class to provides some utility functions for graphs */
|
||
class GraphUtils {
|
||
/**
|
||
* An implementation of Djikstra's shortest path algorithm based on the one described in The Algorithm Design Manual.
|
||
* @param g The graph
|
||
* @param start The number to start the shortest path from
|
||
* @returns An array containing the parent of each node of the Graph in the shortest path.
|
||
*/
|
||
static djikstra(g, start) {
|
||
let i; // Counter
|
||
let p; // Pointer to edgenode
|
||
let inTree = new Array(g.numVertices);
|
||
let distance = new Array(g.numVertices);
|
||
let parent = new Array(g.numVertices);
|
||
let v; // Current vertex to process
|
||
let w; // Candidate for next vertex
|
||
let weight; // Edge weight
|
||
let dist; // Best current distance from start
|
||
for (i = 0; i < g.numVertices; i++) {
|
||
inTree[i] = false;
|
||
distance[i] = Infinity;
|
||
parent[i] = -1;
|
||
}
|
||
distance[start] = 0;
|
||
v = start;
|
||
while (!inTree[v]) {
|
||
inTree[v] = true;
|
||
p = g.edges[v];
|
||
while (p !== null) {
|
||
w = p.y;
|
||
weight = p.weight;
|
||
if (distance[w] > distance[v] + weight) {
|
||
distance[w] = distance[v] + weight;
|
||
parent[w] = v;
|
||
}
|
||
p = p.next;
|
||
}
|
||
v = 0;
|
||
dist = Infinity;
|
||
for (i = 0; i <= g.numVertices; i++) {
|
||
if (!inTree[i] && dist > distance[i]) {
|
||
dist = distance;
|
||
v = i;
|
||
}
|
||
}
|
||
}
|
||
return parent;
|
||
}
|
||
}
|
||
exports.default = GraphUtils;
|
||
|
||
},{}],102:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/** A class containing some utility functions for math operations */
|
||
class MathUtils {
|
||
/**
|
||
* Returns the sign of the value provided
|
||
* @param x The value to extract the sign from
|
||
* @returns -1 if the number is less than 0, 1 otherwise
|
||
*/
|
||
static sign(x) {
|
||
return x < 0 ? -1 : 1;
|
||
}
|
||
/**
|
||
* Returns whether or not x is between a and b
|
||
* @param a The min bound
|
||
* @param b The max bound
|
||
* @param x The value to check
|
||
* @param exclusive Whether or not a and b are exclusive bounds
|
||
* @returns True if x is between a and b, false otherwise
|
||
*/
|
||
static between(a, b, x, exclusive) {
|
||
if (exclusive) {
|
||
return (a < x) && (x < b);
|
||
}
|
||
else {
|
||
return (a <= x) && (x <= b);
|
||
}
|
||
}
|
||
/**
|
||
* Clamps the value x to the range [min, max], rounding up or down if needed
|
||
* @param x The value to be clamped
|
||
* @param min The min of the range
|
||
* @param max The max of the range
|
||
* @returns x, if it is between min and max, or min/max if it exceeds their bounds
|
||
*/
|
||
static clamp(x, min, max) {
|
||
if (x < min)
|
||
return min;
|
||
if (x > max)
|
||
return max;
|
||
return x;
|
||
}
|
||
/**
|
||
* Clamps the value x to the range between 0 and 1
|
||
* @param x The value to be clamped
|
||
* @returns x, if it is between 0 and 1, or 0/1 if it exceeds their bounds
|
||
*/
|
||
static clamp01(x) {
|
||
return MathUtils.clamp(x, 0, 1);
|
||
}
|
||
/**
|
||
* Clamps the lower end of the value of x to the range to min
|
||
* @param x The value to be clamped
|
||
* @param min The minimum allowed value of x
|
||
* @returns x, if it is greater than min, otherwise min
|
||
*/
|
||
static clampLow(x, min) {
|
||
return x < min ? min : x;
|
||
}
|
||
/**
|
||
* Clamps the lower end of the value of x to zero
|
||
* @param x The value to be clamped
|
||
* @returns x, if it is greater than 0, otherwise 0
|
||
*/
|
||
static clampLow0(x) {
|
||
return MathUtils.clampLow(x, 0);
|
||
}
|
||
static clampMagnitude(v, m) {
|
||
if (v.magSq() > m * m) {
|
||
return v.scaleTo(m);
|
||
}
|
||
else {
|
||
return v;
|
||
}
|
||
}
|
||
static changeRange(x, min, max, newMin, newMax) {
|
||
return this.lerp(newMin, newMax, this.invLerp(min, max, x));
|
||
}
|
||
/**
|
||
* Linear Interpolation
|
||
* @param a The first value for the interpolation bound
|
||
* @param b The second value for the interpolation bound
|
||
* @param t The time we are interpolating to
|
||
* @returns The value between a and b at time t
|
||
*/
|
||
static lerp(a, b, t) {
|
||
return a + t * (b - a);
|
||
}
|
||
/**
|
||
* Inverse Linear Interpolation. Finds the time at which a value between a and b would occur
|
||
* @param a The first value for the interpolation bound
|
||
* @param b The second value for the interpolation bound
|
||
* @param value The current value
|
||
* @returns The time at which the current value occurs between a and b
|
||
*/
|
||
static invLerp(a, b, value) {
|
||
return (value - a) / (b - a);
|
||
}
|
||
/**
|
||
* Cuts off decimal points of a number after a specified place
|
||
* @param num The number to floor
|
||
* @param place The last decimal place of the new number
|
||
* @returns The floored number
|
||
*/
|
||
static floorToPlace(num, place) {
|
||
if (place === 0) {
|
||
return Math.floor(num);
|
||
}
|
||
let factor = 10;
|
||
while (place > 1) {
|
||
factor != 10;
|
||
place--;
|
||
}
|
||
return Math.floor(num * factor) / factor;
|
||
}
|
||
/**
|
||
* Returns a number from a hex string
|
||
* @param str the string containing the hex number
|
||
* @returns the number in decimal represented by the hex string
|
||
*/
|
||
static fromHex(str) {
|
||
return parseInt(str, 16);
|
||
}
|
||
/**
|
||
* Returns the number as a hexadecimal
|
||
* @param num The number to convert to hex
|
||
* @param minLength The length of the returned hex string (adds zero padding if needed)
|
||
* @returns The hex representation of the number as a string
|
||
*/
|
||
static toHex(num, minLength = null) {
|
||
let factor = 1;
|
||
while (factor * 16 < num) {
|
||
factor *= 16;
|
||
}
|
||
let hexStr = "";
|
||
while (factor >= 1) {
|
||
let digit = Math.floor(num / factor);
|
||
hexStr += MathUtils.toHexDigit(digit);
|
||
num -= digit * factor;
|
||
factor /= 16;
|
||
}
|
||
if (minLength !== null) {
|
||
while (hexStr.length < minLength) {
|
||
hexStr = "0" + hexStr;
|
||
}
|
||
}
|
||
return hexStr;
|
||
}
|
||
/**
|
||
* Converts a digit to hexadecimal. In this case, a digit is between 0 and 15 inclusive
|
||
* @param num The digit to convert to hexadecimal
|
||
* @returns The hex representation of the digit as a string
|
||
*/
|
||
static toHexDigit(num) {
|
||
if (num < 10) {
|
||
return "" + num;
|
||
}
|
||
else {
|
||
return String.fromCharCode(65 + num - 10);
|
||
}
|
||
}
|
||
}
|
||
exports.default = MathUtils;
|
||
|
||
},{}],103:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const MathUtils_1 = require("./MathUtils");
|
||
class RenderingUtils {
|
||
static toWebGLCoords(point, origin, worldSize) {
|
||
return new Float32Array([
|
||
MathUtils_1.default.changeRange(point.x, origin.x, origin.x + worldSize.x, -1, 1),
|
||
MathUtils_1.default.changeRange(point.y, origin.y, origin.y + worldSize.y, 1, -1)
|
||
]);
|
||
}
|
||
static toWebGLScale(size, worldSize) {
|
||
return new Float32Array([
|
||
2 * size.x / worldSize.x,
|
||
2 * size.y / worldSize.y,
|
||
]);
|
||
}
|
||
static toWebGLColor(color) {
|
||
return new Float32Array([
|
||
MathUtils_1.default.changeRange(color.r, 0, 255, 0, 1),
|
||
MathUtils_1.default.changeRange(color.g, 0, 255, 0, 1),
|
||
MathUtils_1.default.changeRange(color.b, 0, 255, 0, 1),
|
||
color.a
|
||
]);
|
||
}
|
||
}
|
||
exports.default = RenderingUtils;
|
||
|
||
},{"./MathUtils":102}],104:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
/** Some utility functions for dealing with strings */
|
||
class StringUtils {
|
||
/**
|
||
* Extracts the path from a filepath that includes the file
|
||
* @param filePath the filepath to extract the path from
|
||
* @returns The path portion of the filepath provided
|
||
*/
|
||
static getPathFromFilePath(filePath) {
|
||
let splitPath = filePath.split("/");
|
||
splitPath.pop();
|
||
splitPath.push("");
|
||
return splitPath.join("/");
|
||
}
|
||
}
|
||
exports.default = StringUtils;
|
||
|
||
},{}],105:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Game_1 = require("./Wolfie2D/Loop/Game");
|
||
const RegistryManager_1 = require("./Wolfie2D/Registry/RegistryManager");
|
||
const WeaponRegistry_1 = require("./shattered_sword/Registry/WeaponRegistry");
|
||
const WeaponTypeRegistry_1 = require("./shattered_sword/Registry/WeaponTypeRegistry");
|
||
const SplashScreen_1 = require("./shattered_sword/Scenes/SplashScreen");
|
||
// The main function is your entrypoint into Wolfie2D. Specify your first scene and any options here.
|
||
(function main() {
|
||
// Run any tests
|
||
runTests();
|
||
// Set up options for our game
|
||
let options = {
|
||
canvasSize: { x: 1280, y: 720 },
|
||
//canvasSize: {x: window.innerWidth, y: window.innerHeight}, // The size of the game
|
||
clearColor: { r: 0, g: 0, b: 0 },
|
||
inputs: [
|
||
{ name: "left", keys: ["a", "arrowleft"] },
|
||
{ name: "right", keys: ["d", "arrowright"] },
|
||
{ name: "up", keys: ["w", "arrowup"] },
|
||
{ name: "down", keys: ["s", "arrowdown"] },
|
||
{ name: "jump", keys: ["z", "space"] },
|
||
{ name: "attack", keys: ["j", "x", "enter"] },
|
||
{ name: "dash", keys: ["k", "c"] },
|
||
{ name: "skill", keys: ["l", "v"] },
|
||
{ name: "inventory", keys: ["i", "b"] },
|
||
{ name: "pause", keys: ["escape"] },
|
||
{ name: "tab", keys: ["tab"] },
|
||
{ name: "buff1", keys: ["1"] },
|
||
{ name: "buff2", keys: ["2"] },
|
||
{ name: "buff3", keys: ["3"] }
|
||
],
|
||
useWebGL: false,
|
||
showDebug: false // Whether to show debug messages. You can change this to true if you want
|
||
};
|
||
// Set up custom registries
|
||
let weaponTemplateRegistry = new WeaponRegistry_1.default();
|
||
RegistryManager_1.default.addCustomRegistry("weaponTemplates", weaponTemplateRegistry);
|
||
let weaponTypeRegistry = new WeaponTypeRegistry_1.default();
|
||
RegistryManager_1.default.addCustomRegistry("weaponTypes", weaponTypeRegistry);
|
||
// Create a game with the options specified
|
||
const game = new Game_1.default(options);
|
||
// Start our game
|
||
game.start(SplashScreen_1.default, {});
|
||
//TODO - change to splash screen once available
|
||
//game.start(SplashScreen,{});
|
||
})();
|
||
function runTests() { }
|
||
;
|
||
|
||
},{"./Wolfie2D/Loop/Game":36,"./Wolfie2D/Registry/RegistryManager":65,"./shattered_sword/Registry/WeaponRegistry":129,"./shattered_sword/Registry/WeaponTypeRegistry":130,"./shattered_sword/Scenes/SplashScreen":137}],106:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.EnemyStates = void 0;
|
||
const StateMachineAI_1 = require("../../Wolfie2D/AI/StateMachineAI");
|
||
const AABB_1 = require("../../Wolfie2D/DataTypes/Shapes/AABB");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const Patrol_1 = require("./EnemyStates/Patrol");
|
||
const Alert_1 = require("./EnemyStates/Alert");
|
||
const SlimeAttack_1 = require("./EnemyStates/SlimeAttack");
|
||
const sword_enums_1 = require("../sword_enums");
|
||
const sword_enums_2 = require("../sword_enums");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
const Timer_1 = require("../../Wolfie2D/Timing/Timer");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
class EnemyAI extends StateMachineAI_1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
/** The default movement speed of this AI */
|
||
this.speed = 20;
|
||
this.maxSpeed = 40;
|
||
this.velocity = Vec2_1.default.ZERO;
|
||
this.exp_val = 100; //exp value to give player when this dies
|
||
this.poisonCounter = 0;
|
||
this.burnCounter = 0;
|
||
this.bleedCounter = 0;
|
||
this.isAttaking = false;
|
||
}
|
||
initializeAI(owner, options) {
|
||
this.owner = owner;
|
||
//add states
|
||
// Patrol mode
|
||
this.addState(EnemyStates.PATROL, new Patrol_1.default(this, owner));
|
||
this.addState(EnemyStates.ALERT, new Alert_1.default(this, owner));
|
||
this.addState(EnemyStates.ATTACK, new SlimeAttack_1.default(this, owner));
|
||
this.maxHealth = options.health;
|
||
this.CURRENT_HP = options.health;
|
||
this.player = options.player;
|
||
this.exp_val = options.exp;
|
||
//TODO - get correct tilemap
|
||
this.tilemap = this.owner.getScene().getLayer("Wall").getItems()[0];
|
||
// Initialize to the default state
|
||
this.initialize(EnemyStates.PATROL);
|
||
this.direction = 1; //default moving to the right
|
||
//TODO - dots every 1 sec? can change
|
||
this.burnTimer = new Timer_1.default(1000);
|
||
this.bleedTimer = new Timer_1.default(1000);
|
||
this.poisonTimer = new Timer_1.default(1000);
|
||
this.attackTimer = new Timer_1.default(2500);
|
||
this.damageTimer = new Timer_1.default(400);
|
||
}
|
||
damage(damage) {
|
||
// enemy already dead, do not send new event
|
||
if (this.CURRENT_HP <= 0) {
|
||
return;
|
||
}
|
||
console.log(damage + " damage taken, " + this.CURRENT_HP + " hp left");
|
||
this.CURRENT_HP -= damage;
|
||
//TODO -
|
||
if (!this.isAttaking) {
|
||
this.owner.animation.play("HURT", false);
|
||
}
|
||
console.log(damage + " damage taken, " + this.CURRENT_HP + " hp left");
|
||
// If health goes below 0, disable AI and fire enemyDied event
|
||
if (this.CURRENT_HP <= 0) {
|
||
this.owner.setAIActive(false, {});
|
||
this.owner.isCollidable = false;
|
||
this.owner.visible = false;
|
||
if (this.healthBar) {
|
||
this.healthBar.destroy();
|
||
this.healthBar = undefined;
|
||
}
|
||
if (this.poisonStat) {
|
||
this.poisonStat.destroy();
|
||
this.poisonStat = undefined;
|
||
}
|
||
if (this.burnStat) {
|
||
this.burnStat.destroy();
|
||
this.burnStat = undefined;
|
||
}
|
||
if (this.bleedStat) {
|
||
this.bleedStat.destroy();
|
||
this.bleedStat = undefined;
|
||
}
|
||
this.emitter.fireEvent(sword_enums_2.Player_Events.ENEMY_KILLED, { owner: this.owner.id, ai: this });
|
||
}
|
||
this.damageTimer.start();
|
||
}
|
||
collideWithPlayer(player) {
|
||
player.damage(10);
|
||
}
|
||
canAttack(position) {
|
||
return this.attackTimer.isStopped() && this.owner.position.distanceTo(position) <= 32;
|
||
}
|
||
//TODO - need to modify for side view
|
||
isPlayerVisible(pos) {
|
||
//Check ifplayer is visible, taking into account walls
|
||
// Get the new player location
|
||
let start = this.owner.position.clone();
|
||
let delta = pos.clone().sub(start);
|
||
if (delta.mag() >= 640) {
|
||
return null;
|
||
}
|
||
// Iterate through the tilemap region until we find a collision
|
||
let minX = Math.min(start.x, pos.x);
|
||
let maxX = Math.max(start.x, pos.x);
|
||
let minY = Math.min(start.y, pos.y);
|
||
let maxY = Math.max(start.y, pos.y);
|
||
// Get the wall tilemap
|
||
let walls = this.tilemap;
|
||
let minIndex = walls.getColRowAt(new Vec2_1.default(minX, minY));
|
||
let maxIndex = walls.getColRowAt(new Vec2_1.default(maxX, maxY));
|
||
let tileSize = walls.getTileSize();
|
||
for (let col = minIndex.x; col <= maxIndex.x; col++) {
|
||
for (let row = minIndex.y; row <= maxIndex.y; row++) {
|
||
if (walls.isTileCollidable(col, row)) {
|
||
// Get the position of this tile
|
||
let tilePos = new Vec2_1.default(col * tileSize.x + tileSize.x / 2, row * tileSize.y + tileSize.y / 2);
|
||
// Create a collider for this tile
|
||
let collider = new AABB_1.default(tilePos, tileSize.scaled(1 / 2));
|
||
let hit = collider.intersectSegment(start, delta, Vec2_1.default.ZERO);
|
||
if (hit !== null && start.distanceSqTo(hit.pos) < start.distanceSqTo(pos)) {
|
||
// We hit a wall, we can't see the player
|
||
//console.log("player not visible")
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return pos;
|
||
}
|
||
/**
|
||
* gets the position of the player
|
||
* @returns position of the player if visible, else null
|
||
*/
|
||
getPlayerPosition() {
|
||
return this.isPlayerVisible(this.player.position);
|
||
}
|
||
update(deltaT) {
|
||
if (InputWrapper_1.default.getState() != sword_enums_1.GameState.GAMING) {
|
||
this.owner.animation.pause();
|
||
return;
|
||
}
|
||
this.owner.animation.resume();
|
||
super.update(deltaT);
|
||
if (this.burnTimer.isStopped() && this.burnCounter > 0) {
|
||
this.burnCounter--;
|
||
this.burnTimer.start();
|
||
this.damage(12 + this.player._ai.extraDotDmg);
|
||
}
|
||
if (this.poisonTimer.isStopped() && this.poisonCounter > 0) {
|
||
this.poisonCounter--;
|
||
this.poisonTimer.start();
|
||
this.damage(Math.round(this.CURRENT_HP / 20) + this.player._ai.extraDotDmg);
|
||
}
|
||
if (this.bleedTimer.isStopped() && this.bleedCounter > 0) {
|
||
this.bleedCounter--;
|
||
this.bleedTimer.start();
|
||
this.damage(3 + Math.round(this.CURRENT_HP / 33) + this.player._ai.extraDotDmg);
|
||
}
|
||
if (this.healthBar) {
|
||
this.healthBar.position = this.owner.collisionShape.center.clone().add(new Vec2_1.default(0, -(this.owner.collisionShape.hh + 5)));
|
||
this.healthBar.fillWidth = this.CURRENT_HP / this.maxHealth * this.owner.collisionShape.hw * 3;
|
||
if (this.CURRENT_HP / this.maxHealth >= 2 / 3) {
|
||
this.healthBar.color = Color_1.default.GREEN;
|
||
}
|
||
else if (this.CURRENT_HP / this.maxHealth >= 1 / 3) {
|
||
this.healthBar.color = Color_1.default.YELLOW;
|
||
}
|
||
else {
|
||
this.healthBar.color = Color_1.default.RED;
|
||
}
|
||
}
|
||
if (this.poisonStat) {
|
||
this.poisonStat.position = this.owner.collisionShape.center.clone().add(new Vec2_1.default(-(this.owner.collisionShape.hw) * 1.5 + 10, -(this.owner.collisionShape.hh + 15)));
|
||
this.poisonStat.visible = this.poisonCounter > 0;
|
||
}
|
||
if (this.burnStat) {
|
||
this.burnStat.position = this.poisonStat.position.clone().add(new Vec2_1.default(15, 0));
|
||
this.burnStat.visible = this.burnCounter > 0;
|
||
}
|
||
if (this.bleedStat) {
|
||
this.bleedStat.position = this.poisonStat.position.clone().add(new Vec2_1.default(30, 0));
|
||
this.bleedStat.visible = this.bleedCounter > 0;
|
||
}
|
||
if (this.owner.position.y > this.tilemap.getDimensions().y * this.tilemap.getTileSize().y) {
|
||
this.CURRENT_HP = -1;
|
||
this.emitter.fireEvent(sword_enums_2.Player_Events.ENEMY_KILLED, { owner: this.owner.id, ai: this });
|
||
}
|
||
}
|
||
}
|
||
exports.default = EnemyAI;
|
||
var EnemyStates;
|
||
(function (EnemyStates) {
|
||
EnemyStates["PATROL"] = "patrol";
|
||
EnemyStates["ALERT"] = "alert";
|
||
EnemyStates["ATTACK"] = "attack";
|
||
})(EnemyStates = exports.EnemyStates || (exports.EnemyStates = {}));
|
||
|
||
},{"../../Wolfie2D/AI/StateMachineAI":4,"../../Wolfie2D/DataTypes/Shapes/AABB":16,"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Timing/Timer":97,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"../sword_enums":144,"./EnemyStates/Alert":107,"./EnemyStates/Patrol":110,"./EnemyStates/SlimeAttack":111}],107:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyAI_1 = require("../EnemyAI");
|
||
const EnemyState_1 = require("./EnemyState");
|
||
class Alert extends EnemyState_1.default {
|
||
onEnter(options) {
|
||
this.owner.animation.playIfNotAlready("WALK", true);
|
||
}
|
||
update(deltaT) {
|
||
let position = this.parent.getPlayerPosition();
|
||
if (position) {
|
||
this.parent.velocity.x = this.parent.maxSpeed * Math.sign(position.x - this.owner.position.x);
|
||
this.parent.direction = this.parent.velocity.x >= 0 ? 1 : -1;
|
||
if (this.parent.canAttack(position)) {
|
||
this.finished(EnemyAI_1.EnemyStates.ATTACK);
|
||
}
|
||
}
|
||
else {
|
||
this.parent.velocity.x = 0;
|
||
this.finished(EnemyAI_1.EnemyStates.PATROL);
|
||
}
|
||
if (!this.canWalk()) {
|
||
this.parent.velocity.x = 0;
|
||
}
|
||
this.owner.invertX = this.parent.direction === 1 ? true : false;
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.owner.animation.stop();
|
||
return null;
|
||
}
|
||
}
|
||
exports.default = Alert;
|
||
|
||
},{"../EnemyAI":106,"./EnemyState":109}],108:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyState_1 = require("./EnemyState");
|
||
class Attack extends EnemyState_1.default {
|
||
onEnter(options) {
|
||
this.parent.attackTimer.start();
|
||
this.parent.velocity.x = 0;
|
||
this.parent.isAttaking = true;
|
||
this.charged = this.owner.id + "charged";
|
||
this.attacked = this.owner.id + "attacked";
|
||
// TODO replace DYING with CHARGING
|
||
this.owner.animation.play("CHARGE", false, this.charged);
|
||
this.receiver.subscribe(this.charged);
|
||
this.receiver.subscribe(this.attacked);
|
||
}
|
||
update(deltaT) {
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.parent.isAttaking = false;
|
||
this.owner.animation.stop();
|
||
return null;
|
||
}
|
||
}
|
||
exports.default = Attack;
|
||
|
||
},{"./EnemyState":109}],109:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const State_1 = require("../../../Wolfie2D/DataTypes/State/State");
|
||
const Vec2_1 = require("../../../Wolfie2D/DataTypes/Vec2");
|
||
const Receiver_1 = require("../../../Wolfie2D/Events/Receiver");
|
||
class EnemyState extends State_1.default {
|
||
constructor(parent, owner) {
|
||
super(parent);
|
||
this.gravity = 1500; //TODO - can change later
|
||
this.owner = owner;
|
||
this.receiver = new Receiver_1.default();
|
||
}
|
||
handleInput(event) { }
|
||
canWalk() {
|
||
let collision = this.owner.collisionShape;
|
||
let colrow = this.parent.tilemap.getColRowAt(collision.center.clone().add(new Vec2_1.default(this.parent.direction * (collision.hw + 2))));
|
||
return !this.parent.tilemap.isTileCollidable(colrow.x, colrow.y) && this.parent.tilemap.isTileCollidable(colrow.x, colrow.y + 1);
|
||
}
|
||
update(deltaT) {
|
||
if (!this.parent.damageTimer.isStopped() && !this.parent.isAttaking) {
|
||
this.parent.velocity.x = 0;
|
||
}
|
||
// Do gravity
|
||
this.parent.velocity.y += this.gravity * deltaT;
|
||
this.owner.move(this.parent.velocity.scaled(deltaT));
|
||
}
|
||
}
|
||
exports.default = EnemyState;
|
||
|
||
},{"../../../Wolfie2D/DataTypes/State/State":20,"../../../Wolfie2D/DataTypes/Vec2":24,"../../../Wolfie2D/Events/Receiver":31}],110:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyAI_1 = require("../EnemyAI");
|
||
const EnemyState_1 = require("./EnemyState");
|
||
class Patrol extends EnemyState_1.default {
|
||
onEnter(options) {
|
||
this.owner.animation.playIfNotAlready("IDLE", true);
|
||
}
|
||
update(deltaT) {
|
||
if (!this.canWalk()) {
|
||
this.parent.direction *= -1;
|
||
}
|
||
//move
|
||
this.parent.velocity.x = this.parent.direction * this.parent.speed;
|
||
this.owner.invertX = this.parent.direction === 1 ? true : false;
|
||
if (this.parent.getPlayerPosition()) {
|
||
this.finished(EnemyAI_1.EnemyStates.ALERT);
|
||
}
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.owner.animation.stop();
|
||
return null;
|
||
}
|
||
}
|
||
exports.default = Patrol;
|
||
|
||
},{"../EnemyAI":106,"./EnemyState":109}],111:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyAI_1 = require("../EnemyAI");
|
||
const Attack_1 = require("./Attack");
|
||
class SlimeAttack extends Attack_1.default {
|
||
onEnter(options) {
|
||
}
|
||
update(deltaT) {
|
||
this.finished(EnemyAI_1.EnemyStates.ALERT);
|
||
}
|
||
onExit() {
|
||
return null;
|
||
}
|
||
}
|
||
exports.default = SlimeAttack;
|
||
|
||
},{"../EnemyAI":106,"./Attack":108}],112:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyAI_1 = require("../EnemyAI");
|
||
const Attack_1 = require("./Attack");
|
||
class SnakeAttack extends Attack_1.default {
|
||
update(deltaT) {
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent().type;
|
||
switch (event) {
|
||
case this.charged:
|
||
this.owner.animation.play("ATTACK", false, this.attacked);
|
||
this.owner.collisionShape.halfSize.x += 3.5;
|
||
break;
|
||
case this.attacked:
|
||
this.owner.collisionShape.halfSize.x -= 3.5;
|
||
this.finished(EnemyAI_1.EnemyStates.ALERT);
|
||
break;
|
||
}
|
||
}
|
||
this.owner.invertX = this.parent.direction === 1 ? true : false;
|
||
}
|
||
}
|
||
exports.default = SnakeAttack;
|
||
|
||
},{"../EnemyAI":106,"./Attack":108}],113:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyAI_1 = require("./EnemyAI");
|
||
const SlimeAttack_1 = require("./EnemyStates/SlimeAttack");
|
||
class SlimeAI extends EnemyAI_1.default {
|
||
initializeAI(owner, options) {
|
||
super.initializeAI(owner, options);
|
||
this.addState(EnemyAI_1.EnemyStates.ATTACK, new SlimeAttack_1.default(this, owner));
|
||
}
|
||
}
|
||
exports.default = SlimeAI;
|
||
|
||
},{"./EnemyAI":106,"./EnemyStates/SlimeAttack":111}],114:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const EnemyAI_1 = require("./EnemyAI");
|
||
const SnakeAttack_1 = require("./EnemyStates/SnakeAttack");
|
||
class SnakeAI extends EnemyAI_1.default {
|
||
initializeAI(owner, options) {
|
||
super.initializeAI(owner, options);
|
||
this.addState(EnemyAI_1.EnemyStates.ATTACK, new SnakeAttack_1.default(this, owner));
|
||
}
|
||
}
|
||
exports.default = SnakeAI;
|
||
|
||
},{"./EnemyAI":106,"./EnemyStates/SnakeAttack":112}],115:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class BattleManager {
|
||
handleInteraction(attackerType, weapon, user) {
|
||
//may be unneeded since we are controlling the player -
|
||
//we determine enemy collision there
|
||
if (attackerType === "player") {
|
||
// Check for collisions with enemies
|
||
if (this.enemies.length != 0) {
|
||
for (let enemy of this.enemies) {
|
||
if (weapon.hits(enemy.owner)) {
|
||
let player = this.players[0];
|
||
if (player.fullHpBonus) {
|
||
enemy.damage(Math.round(weapon.type.damage * this.players[0].CURRENT_ATK / 10));
|
||
}
|
||
else {
|
||
enemy.damage(Math.round(weapon.type.damage * this.players[0].CURRENT_ATK / 100));
|
||
}
|
||
//console.log("enemy took dmg");
|
||
//add checking for each onhit buff here
|
||
//DOTS
|
||
if (player.hasBleed) {
|
||
enemy.bleedCounter += 3;
|
||
}
|
||
if (player.hasPoison) {
|
||
enemy.poisonCounter = 5;
|
||
}
|
||
if (player.hasBurn) {
|
||
enemy.burnCounter = 5;
|
||
}
|
||
if (player.hasLifesteal) {
|
||
player.addHealth(Math.round(weapon.type.damage * player.CURRENT_ATK / 100 * player.lifestealratio));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
// Check for collision with player
|
||
for (let player of this.players) {
|
||
if (weapon.hits(player.owner)) {
|
||
player.damage(weapon.type.damage, user);
|
||
if (player.hasShield) {
|
||
player.addShield(weapon.type.damage * .5); //half of dmg taken is converted to shield
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
setPlayers(player) {
|
||
this.players = player;
|
||
}
|
||
setEnemies(enemies) {
|
||
this.enemies = enemies;
|
||
}
|
||
addEnemy(enemy) {
|
||
this.enemies.push(enemy);
|
||
}
|
||
removeEnemy(enemy) {
|
||
this.enemies = this.enemies.filter(item => item !== enemy);
|
||
if (this.enemies.length == 0) {
|
||
this.enemies = new Array();
|
||
}
|
||
return this.enemies;
|
||
}
|
||
}
|
||
exports.default = BattleManager;
|
||
|
||
},{}],116:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const GraphicTypes_1 = require("../../Wolfie2D/Nodes/Graphics/GraphicTypes");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
class InventoryManager {
|
||
constructor(scene, size, inventorySlot, position, padding, slotLayer, itemLayer) {
|
||
this.items = new Array(size);
|
||
this.inventorySlots = new Array(size);
|
||
this.padding = padding;
|
||
this.position = position;
|
||
this.currentSlot = 0;
|
||
// Add layers
|
||
this.slotLayer = slotLayer;
|
||
scene.addUILayer(this.slotLayer).setDepth(100);
|
||
this.itemLayer = itemLayer;
|
||
scene.addUILayer(this.itemLayer).setDepth(101);
|
||
// Create the inventory slots
|
||
for (let i = 0; i < size; i++) {
|
||
this.inventorySlots[i] = scene.add.sprite(inventorySlot, this.slotLayer);
|
||
}
|
||
this.slotSize = this.inventorySlots[0].size.clone();
|
||
// Position the inventory slots
|
||
for (let i = 0; i < size; i++) {
|
||
this.inventorySlots[i].position.set(position.x + i * (this.slotSize.x + this.padding), position.y);
|
||
}
|
||
// Add a rect for the selected slot
|
||
this.selectedSlot = scene.add.graphic(GraphicTypes_1.GraphicType.RECT, slotLayer, { position: this.position.clone(), size: this.slotSize.clone().inc(-2) });
|
||
this.selectedSlot.color = Color_1.default.WHITE;
|
||
this.selectedSlot.color.a = 0.2;
|
||
}
|
||
getItem() {
|
||
return this.items[this.currentSlot];
|
||
}
|
||
/**
|
||
* Changes the currently selected slot
|
||
*/
|
||
changeSlot(slot) {
|
||
this.currentSlot = slot;
|
||
this.selectedSlot.position.copy(this.inventorySlots[slot].position);
|
||
}
|
||
/**
|
||
* Gets the currently selected slot
|
||
*/
|
||
getSlot() {
|
||
return this.currentSlot;
|
||
}
|
||
/**
|
||
* Adds an item to the currently selected slot
|
||
*/
|
||
addItem(item) {
|
||
if (!this.items[this.currentSlot]) {
|
||
// Add the item to the inventory
|
||
this.items[this.currentSlot] = item;
|
||
// Update the gui
|
||
item.moveSprite(new Vec2_1.default(this.position.x + this.currentSlot * (this.slotSize.x + this.padding), this.position.y), this.itemLayer);
|
||
return true;
|
||
}
|
||
// Failed to add item, something was already in the slot
|
||
return false;
|
||
}
|
||
/**
|
||
* Removes and returns an item from the the currently selected slot, if possible
|
||
*/
|
||
removeItem() {
|
||
let item = this.items[this.currentSlot];
|
||
this.items[this.currentSlot] = null;
|
||
if (item) {
|
||
return item;
|
||
}
|
||
else {
|
||
return null;
|
||
}
|
||
}
|
||
setActive(active) {
|
||
if (active) {
|
||
this.inventorySlots.forEach(slot => slot.alpha = 1.0);
|
||
}
|
||
else {
|
||
this.inventorySlots.forEach(slot => slot.alpha = 0.5);
|
||
}
|
||
}
|
||
}
|
||
exports.default = InventoryManager;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/Graphics/GraphicTypes":42,"../../Wolfie2D/Utils/Color":99}],117:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class Item {
|
||
constructor(sprite) {
|
||
this.sprite = sprite;
|
||
}
|
||
moveSprite(position, layer) {
|
||
// Change the layer if needed
|
||
if (layer) {
|
||
let currentLayer = this.sprite.getLayer();
|
||
currentLayer.removeNode(this.sprite);
|
||
let newLayer = this.sprite.getScene().getLayer(layer);
|
||
newLayer.addNode(this.sprite);
|
||
this.sprite.setLayer(newLayer);
|
||
}
|
||
// Move the sprite
|
||
this.sprite.position.copy(position);
|
||
}
|
||
}
|
||
exports.default = Item;
|
||
|
||
},{}],118:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
//TODO import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
|
||
const Emitter_1 = require("../../../Wolfie2D/Events/Emitter");
|
||
const Timer_1 = require("../../../Wolfie2D/Timing/Timer");
|
||
const Item_1 = require("./Item");
|
||
const GameEventType_1 = require("../../../Wolfie2D/Events/GameEventType");
|
||
class Weapon extends Item_1.default {
|
||
constructor(sprite, type, battleManager) {
|
||
super(sprite);
|
||
this.cooldown = 0;
|
||
// Set the weapon type
|
||
this.type = type.clone();
|
||
// Keep a reference to the sprite of this weapon
|
||
this.sprite = sprite;
|
||
// Create an event emitter
|
||
this.emitter = new Emitter_1.default();
|
||
// Save a reference to the battler manager
|
||
this.battleManager = battleManager;
|
||
// Create the cooldown timer
|
||
this.cooldownTimer = new Timer_1.default(type.cooldown);
|
||
this.cooldown = type.cooldown;
|
||
this.EXTRA_DAMAGE = 0;
|
||
this.EXTRA_RANGE = 0;
|
||
}
|
||
// @override
|
||
/**
|
||
* Uses this weapon in the specified direction.
|
||
* This only works if the cooldown timer has ended
|
||
*/
|
||
use(user, userType, direction) {
|
||
// If the cooldown timer is still running, we can't use the weapon
|
||
if (!this.cooldownTimer.isStopped()) {
|
||
return false;
|
||
}
|
||
// Rely on the weapon type to create any necessary assets
|
||
this.assets = this.type.createRequiredAssets(this.sprite.getScene());
|
||
// Do a type specific weapon animation
|
||
this.type.doAnimation(user, direction, this.EXTRA_RANGE, ...this.assets);
|
||
// Apply damage
|
||
this.battleManager.handleInteraction(userType, this, user);
|
||
// Reset the cooldown timer
|
||
this.cooldownTimer.start();
|
||
//TODO - may have to move elsewhere
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "sword", loop: false, holdReference: false });
|
||
return true;
|
||
}
|
||
/**
|
||
* A check for whether or not this weapon hit a node
|
||
*/
|
||
hits(node) {
|
||
return this.type.hits(node, ...this.assets);
|
||
}
|
||
}
|
||
exports.default = Weapon;
|
||
|
||
},{"../../../Wolfie2D/Events/Emitter":27,"../../../Wolfie2D/Events/GameEventType":30,"../../../Wolfie2D/Timing/Timer":97,"./Item":117}],119:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../../../Wolfie2D/DataTypes/Vec2");
|
||
const WeaponType_1 = require("./WeaponType");
|
||
class Slice extends WeaponType_1.default {
|
||
initialize(options) {
|
||
this.damage = options.damage;
|
||
this.cooldown = options.cooldown;
|
||
this.displayName = options.displayName;
|
||
this.spriteKey = options.spriteKey;
|
||
this.useVolume = options.useVolume;
|
||
}
|
||
doAnimation(attacker, direction, extraRange, sliceSprite) {
|
||
// Rotate this with the game node
|
||
// TODO - need to rotate the anim properly
|
||
//sliceSprite.rotation = attacker.rotation;
|
||
//sliceSprite.rotation = (<Sprite>attacker).invertX? .5* Math.PI : 1.5 * Math.PI;
|
||
sliceSprite.invertX = attacker.invertX;
|
||
//TODO-
|
||
//4 to scale up the default sprite - may be different later depending on atk anim
|
||
sliceSprite.scaleX = 2 * (1 + extraRange); //might have to add extra range to y as well
|
||
sliceSprite.scaleY = 2;
|
||
// Move the slice out from the player
|
||
//scale = num of pixels between center of sprite and atk anim
|
||
sliceSprite.position = attacker.position.clone().add(direction.scaled(32));
|
||
sliceSprite.position = sliceSprite.position.add(new Vec2_1.default(0, 16)); //make it go down a bit
|
||
// Play the slice animation w/o loop, but queue the normal animation
|
||
sliceSprite.animation.play("SLICE");
|
||
sliceSprite.animation.queue("NORMAL", true);
|
||
}
|
||
createRequiredAssets(scene) {
|
||
let slice = scene.add.animatedSprite("slice", "primary");
|
||
slice.animation.play("NORMAL", true);
|
||
return [slice];
|
||
}
|
||
hits(node, sliceSprite) {
|
||
return sliceSprite.boundary.overlaps(node.collisionShape);
|
||
}
|
||
clone() {
|
||
let newType = new Slice();
|
||
newType.initialize({ damage: this.damage, cooldown: this.cooldown, displayName: this.displayName, spriteKey: this.spriteKey, useVolume: this.useVolume });
|
||
return newType;
|
||
}
|
||
}
|
||
exports.default = Slice;
|
||
|
||
},{"../../../../Wolfie2D/DataTypes/Vec2":24,"./WeaponType":120}],120:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class WeaponType {
|
||
}
|
||
exports.default = WeaponType;
|
||
|
||
},{}],121:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.BuffCategory = exports.Buff = exports.BuffType = exports.PlayerStates = exports.PlayerType = void 0;
|
||
const StateMachineAI_1 = require("../../Wolfie2D/AI/StateMachineAI");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const sword_enums_1 = require("../sword_enums");
|
||
const Fall_1 = require("./PlayerStates/Fall");
|
||
const Idle_1 = require("./PlayerStates/Idle");
|
||
const InAir_1 = require("./PlayerStates/InAir");
|
||
const Jump_1 = require("./PlayerStates/Jump");
|
||
const Walk_1 = require("./PlayerStates/Walk");
|
||
const Debug_1 = require("../../Wolfie2D/Debug/Debug");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
const Timer_1 = require("../../Wolfie2D/Timing/Timer");
|
||
const PlayerState_1 = require("./PlayerStates/PlayerState");
|
||
const GameEventType_1 = require("../../Wolfie2D/Events/GameEventType");
|
||
var PlayerType;
|
||
(function (PlayerType) {
|
||
PlayerType["PLATFORMER"] = "platformer";
|
||
PlayerType["TOPDOWN"] = "topdown";
|
||
})(PlayerType = exports.PlayerType || (exports.PlayerType = {}));
|
||
var PlayerStates;
|
||
(function (PlayerStates) {
|
||
PlayerStates["IDLE"] = "idle";
|
||
PlayerStates["WALK"] = "walk";
|
||
PlayerStates["JUMP"] = "jump";
|
||
PlayerStates["FALL"] = "fall";
|
||
PlayerStates["PREVIOUS"] = "previous";
|
||
})(PlayerStates = exports.PlayerStates || (exports.PlayerStates = {}));
|
||
var BuffType;
|
||
(function (BuffType) {
|
||
BuffType["FLAT_ATK"] = "attack";
|
||
BuffType["PERCENT_ATK"] = "percent_attack";
|
||
BuffType["DEF"] = "defence";
|
||
BuffType["FLAT_HEALTH"] = "health";
|
||
BuffType["PERCENT_HEALTH"] = "percent_health";
|
||
BuffType["SPEED"] = "speed";
|
||
BuffType["RANGE"] = "range";
|
||
BuffType["ATKSPEED"] = "attackspeed";
|
||
BuffType["POISON"] = "poison";
|
||
BuffType["BLEED"] = "bleed";
|
||
BuffType["BURN"] = "burn";
|
||
BuffType["EXTRA_DOT"] = "extradot";
|
||
BuffType["SHIELD"] = "shield";
|
||
BuffType["SHIELD_DMG"] = "shielddmg";
|
||
BuffType["LIFESTEAL"] = "lifesteal";
|
||
BuffType["LIFESTEALBUFF"] = "lifestealbuff";
|
||
BuffType["EXTRALIFE"] = "extralife";
|
||
BuffType["ONESHOT"] = "oneshot";
|
||
BuffType["FULLHPBONUSDMG"] = "fullhpbonusdmg";
|
||
})(BuffType = exports.BuffType || (exports.BuffType = {}));
|
||
class Buff {
|
||
}
|
||
exports.Buff = Buff;
|
||
//TODO - need better names
|
||
var BuffCategory;
|
||
(function (BuffCategory) {
|
||
BuffCategory["ATTACK"] = "ATTACK";
|
||
BuffCategory["DOT"] = "DOT";
|
||
BuffCategory["SHIELD"] = "SHIELD";
|
||
BuffCategory["HEALTH"] = "HEALTH";
|
||
BuffCategory["EXTRA"] = "EXTRA";
|
||
})(BuffCategory = exports.BuffCategory || (exports.BuffCategory = {}));
|
||
//TODO - discuss max stats during refinement, unused for now
|
||
class PlayerController extends StateMachineAI_1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.velocity = Vec2_1.default.ZERO;
|
||
//will need to discuss redundant stats
|
||
this.speed = 200;
|
||
this.MIN_SPEED = 200;
|
||
this.MAX_SPEED = 300;
|
||
this.BASE_HP = 100;
|
||
this.MAX_HP = 100;
|
||
this.CURRENT_HP = 100;
|
||
this.BASE_ATK = 100;
|
||
this.CURRENT_ATK = 100;
|
||
this.damage_multiplier = 1;
|
||
this.CURRENT_EXP = 0;
|
||
this.MAX_EXP = 100;
|
||
this.CURRENT_SHIELD = 0;
|
||
this.MAX_SHIELD = 20;
|
||
this.invincible = false;
|
||
this.level = 1;
|
||
this.godMode = false;
|
||
//for doublejumps maybe = # of jumps in air allowed
|
||
this.MAX_airjumps = 1;
|
||
this.airjumps = 0;
|
||
//add to current_buffs later
|
||
this.hasBleed = false;
|
||
this.hasPoison = false;
|
||
this.hasBurn = false;
|
||
this.hasShield = false;
|
||
this.shieldDamage = 1;
|
||
this.hasLifesteal = false;
|
||
this.lifestealratio = 0; //percent of damage to steal
|
||
this.hasOneShot = false;
|
||
this.extraDotDmg = 0;
|
||
this.lives = 1;
|
||
this.cooldownMultiplier = 1;
|
||
this.fullHpBonus = false;
|
||
this.poisonCounter = 0;
|
||
this.burnCounter = 0;
|
||
this.bleedCounter = 0;
|
||
this.enemiesKilled = 0;
|
||
}
|
||
//TODO - get the correct tilemap
|
||
initializeAI(owner, options) {
|
||
this.owner = owner;
|
||
this.initializePlatformer();
|
||
this.tilemap = this.owner.getScene().getTilemap(options.tilemap);
|
||
this.inventory = options.inventory;
|
||
this.lookDirection = new Vec2_1.default();
|
||
//i frame timer
|
||
PlayerController.invincibilityTimer = new Timer_1.default(2000);
|
||
//initialize the buff pool - each has same weight at first
|
||
PlayerController.buffPool = new Array();
|
||
for (let i = 0; i < 4; i++) {
|
||
PlayerController.buffPool.push(BuffCategory.ATTACK);
|
||
PlayerController.buffPool.push(BuffCategory.EXTRA);
|
||
PlayerController.buffPool.push(BuffCategory.DOT);
|
||
PlayerController.buffPool.push(BuffCategory.SHIELD);
|
||
PlayerController.buffPool.push(BuffCategory.HEALTH);
|
||
}
|
||
//initialize dot timers
|
||
this.burnTimer = new Timer_1.default(1000);
|
||
this.bleedTimer = new Timer_1.default(1000);
|
||
this.poisonTimer = new Timer_1.default(1000);
|
||
//to test the buffs
|
||
//this.addBuff( {type:BuffType.HEALTH, value:1} );
|
||
//this.addBuff({type:BuffType.BURN, value:1, category:BuffCategory.DOT});
|
||
//this.addBuff({type:BuffType.BLEED, value:1, category:BuffCategory.DOT});
|
||
//this.addBuff({type:BuffType.POISON, value:1, category:BuffCategory.DOT});
|
||
}
|
||
initializePlatformer() {
|
||
this.speed = 400;
|
||
let idle = new Idle_1.default(this, this.owner);
|
||
this.addState(PlayerStates.IDLE, idle);
|
||
let walk = new Walk_1.default(this, this.owner);
|
||
this.addState(PlayerStates.WALK, walk);
|
||
let jump = new Jump_1.default(this, this.owner);
|
||
this.addState(PlayerStates.JUMP, jump);
|
||
let fall = new Fall_1.default(this, this.owner);
|
||
this.addState(PlayerStates.FALL, fall);
|
||
this.initialize(PlayerStates.IDLE);
|
||
}
|
||
changeState(stateName) {
|
||
// If we jump or fall, push the state so we can go back to our current state later
|
||
// unless we're going from jump to fall or something
|
||
if ((stateName === PlayerStates.JUMP || stateName === PlayerStates.FALL) && !(this.stack.peek() instanceof InAir_1.default)) {
|
||
this.stack.push(this.stateMap.get(stateName));
|
||
}
|
||
super.changeState(stateName);
|
||
}
|
||
update(deltaT) {
|
||
super.update(deltaT);
|
||
if (PlayerController.invincibilityTimer.isStopped()) {
|
||
this.invincible = false;
|
||
}
|
||
if (this.currentState instanceof Jump_1.default) {
|
||
Debug_1.default.log("playerstate", "Player State: Jump");
|
||
}
|
||
else if (this.currentState instanceof Walk_1.default) {
|
||
Debug_1.default.log("playerstate", "Player State: Walk");
|
||
}
|
||
else if (this.currentState instanceof Idle_1.default) {
|
||
Debug_1.default.log("playerstate", "Player State: Idle");
|
||
}
|
||
else if (this.currentState instanceof Fall_1.default) {
|
||
Debug_1.default.log("playerstate", "Player State: Fall");
|
||
}
|
||
Debug_1.default.log("player speed", "player speed: x: " + this.velocity.x + ", y:" + this.velocity.y);
|
||
Debug_1.default.log("player Coords:", "Player Coords:" + this.owner.position);
|
||
//testing the attacks here, may be moved to another place later
|
||
if (InputWrapper_1.default.isAttackJustPressed()) {
|
||
let item = this.inventory.getItem();
|
||
this.owner.animation.play("ATTACK", true);
|
||
//TODO - get proper look direction
|
||
this.lookDirection.x = this.owner.invertX ? -1 : 1;
|
||
// If there is an item in the current slot, use it
|
||
if (item) {
|
||
item.use(this.owner, "player", this.lookDirection);
|
||
//this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "sword", loop: false, holdReference: false});
|
||
}
|
||
}
|
||
//check dot effects
|
||
if (this.burnTimer.isStopped() && this.burnCounter > 0) {
|
||
this.burnCounter--;
|
||
this.burnTimer.start();
|
||
this.damage(5);
|
||
}
|
||
if (this.poisonTimer.isStopped() && this.poisonCounter > 0) {
|
||
this.poisonCounter--;
|
||
this.poisonTimer.start();
|
||
this.damage(Math.round(this.CURRENT_HP / 33));
|
||
}
|
||
if (this.bleedTimer.isStopped() && this.bleedCounter > 0) {
|
||
this.bleedCounter--;
|
||
this.bleedTimer.start();
|
||
this.damage(2 + Math.round(this.CURRENT_HP / 50));
|
||
}
|
||
}
|
||
// TODO - figure out attacker
|
||
damage(damage, attacker) {
|
||
if (this.godMode) {
|
||
//console.log("godmode");
|
||
return;
|
||
}
|
||
if (!this.invincible && PlayerState_1.default.dashTimer.isStopped()) {
|
||
//console.log("take damage");
|
||
//i frame here
|
||
PlayerController.invincibilityTimer.start();
|
||
this.invincible = true;
|
||
//shield absorbs the damage and sends dmg back to attacker
|
||
if (this.CURRENT_SHIELD > 0) {
|
||
let newshield = Math.max(0, this.CURRENT_SHIELD - damage); //calculate the new shield value
|
||
if (attacker !== undefined) {
|
||
attacker._ai.damage((this.CURRENT_SHIELD - newshield) * this.shieldDamage); //damage the attacker the dmg taken to shield
|
||
}
|
||
this.CURRENT_SHIELD = newshield; //update shield value
|
||
}
|
||
else {
|
||
//i frame here
|
||
PlayerController.invincibilityTimer.start();
|
||
this.invincible = true;
|
||
//console.log("hurt anim");
|
||
this.owner.animation.play("HURT");
|
||
damage *= this.damage_multiplier;
|
||
damage = parseFloat(damage.toPrecision(2));
|
||
this.CURRENT_HP -= damage;
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "hurt", loop: false, holdReference: false });
|
||
//if player has shield buff give them shield when damaged
|
||
if (this.hasShield) {
|
||
this.CURRENT_SHIELD += damage * .5;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
//console.log("player is invincible");
|
||
}
|
||
if (this.CURRENT_HP <= 0) {
|
||
this.lives--;
|
||
this.owner.animation.play("DYING");
|
||
this.owner.animation.queue("DEAD", true, sword_enums_1.Player_Events.PLAYER_KILLED);
|
||
this.emitter.fireEvent(sword_enums_1.Player_Events.PLAYER_KILLED);
|
||
}
|
||
}
|
||
/**
|
||
* gives the player a certain amount of shield
|
||
* @param shield amount of shield to add to player
|
||
*/
|
||
addShield(shield) {
|
||
this.CURRENT_SHIELD = (this.CURRENT_SHIELD + shield) % this.MAX_SHIELD;
|
||
}
|
||
/**
|
||
* gives health to the player
|
||
* @param health health to give player
|
||
*/
|
||
addHealth(health) {
|
||
this.CURRENT_HP += health;
|
||
if (this.CURRENT_HP > this.MAX_HP) {
|
||
this.CURRENT_HP = this.MAX_HP;
|
||
}
|
||
}
|
||
/**
|
||
* gives the player exp
|
||
* @param exp amount of exp to give the player
|
||
*/
|
||
giveExp(exp) {
|
||
this.CURRENT_EXP += exp;
|
||
//if > than max exp level up (give buff)
|
||
if (this.CURRENT_EXP >= this.MAX_EXP) {
|
||
this.CURRENT_EXP -= this.MAX_EXP;
|
||
this.MAX_EXP += 50; //increase max exp needed for level up
|
||
this.level++;
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "level_up", loop: false, holdReference: false });
|
||
this.emitter.fireEvent(sword_enums_1.Player_Events.GIVE_REGULAR_BUFF);
|
||
}
|
||
}
|
||
/**
|
||
* generates an array of regular buffs
|
||
* @param val optional value to give buff
|
||
* @returns array of three buffs
|
||
*/
|
||
generateRegularBuffs(val) {
|
||
//random number from 5 to 15 if no value given
|
||
let num = Math.floor(Math.random() * 10) + 5;
|
||
num = Math.round(num);
|
||
if (typeof val !== 'undefined') {
|
||
num = val;
|
||
}
|
||
let buffs = new Array();
|
||
buffs.push({ type: BuffType.FLAT_ATK, value: num, category: BuffCategory.EXTRA }, { type: BuffType.SPEED, value: num, category: BuffCategory.EXTRA }, { type: BuffType.FLAT_HEALTH, value: num, category: BuffCategory.SHIELD }, { type: BuffType.RANGE, value: num / 100, category: BuffCategory.ATTACK, string: "\n\nIncrease range \nby " + num + "%" }, { type: BuffType.ATKSPEED, value: num, category: BuffCategory.ATTACK });
|
||
//shuffle pool of buffs
|
||
buffs.sort(() => 0.5 - Math.random());
|
||
// Get sub-array of first 3 elements after shuffled
|
||
let selected = buffs.slice(0, 3); //3 buff categories
|
||
return selected;
|
||
}
|
||
/**
|
||
* generates an array of special buffs
|
||
* @param val optional value to give the buff
|
||
* @returns array of 3 Buffs
|
||
*/
|
||
generateSpecialBuffs(val) {
|
||
//shuffle pool of buff categories
|
||
PlayerController.buffPool.sort(() => 0.5 - Math.random());
|
||
// Get sub-array of first 3 elements after shuffled
|
||
let shuffled = PlayerController.buffPool.slice(0, 3); //3 buff categories
|
||
//random number from 5 to 15 if no value given
|
||
let num = Math.floor(Math.random() * 10) + 5;
|
||
num = Math.round(num);
|
||
if (typeof val !== 'undefined') {
|
||
num = val;
|
||
}
|
||
//TODO - implement better buff genertion - some buffs dont want multiple of
|
||
let attackBuffs = [
|
||
{ type: BuffType.PERCENT_ATK, value: num / 100, category: BuffCategory.ATTACK, string: "\n\nIncrease Attack \nby" + num + "%" }
|
||
];
|
||
let dotBuffs = [];
|
||
if (!this.hasBleed) {
|
||
dotBuffs.push({ type: BuffType.BLEED, value: 1, category: BuffCategory.DOT, string: "\n\nYour hits \napply Bleed" });
|
||
}
|
||
if (!this.hasBurn) {
|
||
dotBuffs.push({ type: BuffType.BURN, value: 1, category: BuffCategory.DOT, string: "\n\nYour hits \napply Burn" });
|
||
}
|
||
if (!this.hasPoison) {
|
||
dotBuffs.push({ type: BuffType.POISON, value: 1, category: BuffCategory.DOT, string: "\n\nYour hits \napply poison" });
|
||
}
|
||
//only add extra dot if at least one dot is acquired
|
||
for (let i = dotBuffs.length; i < 3; i++) {
|
||
dotBuffs.push({ type: BuffType.EXTRA_DOT, value: num, category: BuffCategory.DOT, string: "\n\nIncrease your \nDOT damage" });
|
||
}
|
||
let shieldBuffs = [
|
||
{ type: BuffType.PERCENT_HEALTH, value: num / 100, category: BuffCategory.SHIELD, string: "\n\nIncrease max hp \nby " + num + "%" },
|
||
];
|
||
//if player doesnt have shield buff, give them the option, otherwise give buff shield option
|
||
if (!this.hasShield) {
|
||
shieldBuffs.push({ type: BuffType.SHIELD, value: 1, category: BuffCategory.SHIELD, string: "\n\nGain Shield \nWhen Damaged \n Shields return \nthe damage taken \nto attacker" });
|
||
}
|
||
else {
|
||
shieldBuffs.push({ type: BuffType.SHIELD_DMG, value: num, category: BuffCategory.SHIELD, string: "\n\nIncrease damage \nreturned by shield" });
|
||
}
|
||
let healthBuffs = [
|
||
{ type: BuffType.DEF, value: num / 100, category: BuffCategory.HEALTH, string: "\n\nDecrease damage \ntaken by " + num + "%" }
|
||
];
|
||
if (!this.fullHpBonus) {
|
||
healthBuffs.push({ type: BuffType.FULLHPBONUSDMG, value: 1, category: BuffCategory.HEALTH, string: "\n\nDeal 10x damage \n when at full HP" });
|
||
}
|
||
if (!this.hasLifesteal) {
|
||
healthBuffs.push({ type: BuffType.LIFESTEAL, value: 1, category: BuffCategory.HEALTH, string: "\n\nGain lifesteal" });
|
||
}
|
||
else {
|
||
healthBuffs.push({ type: BuffType.LIFESTEALBUFF, value: num / 100, category: BuffCategory.HEALTH, string: "\n\nIncrease Lifesteal \nstrength by " + num + "%" });
|
||
}
|
||
let extraBuffs = [
|
||
{ type: BuffType.EXTRALIFE, value: 1, category: BuffCategory.EXTRA, string: "\n\nGain an \nExtra Life" },
|
||
];
|
||
if (!this.hasOneShot) { //only add oneshot buff if it isnt already included
|
||
extraBuffs.push({ type: BuffType.ONESHOT, value: 1, category: BuffCategory.EXTRA, string: "\n\nYour hits hurt \n100x more but \nyour max health \nis set to 1 " });
|
||
}
|
||
;
|
||
let selected = new Array();
|
||
while (shuffled.length != 0) {
|
||
let cat = shuffled.pop();
|
||
switch (cat) {
|
||
case BuffCategory.ATTACK:
|
||
attackBuffs.sort(() => 0.5 - Math.random());
|
||
if (attackBuffs.length == 0) {
|
||
selected.push({ type: BuffType.PERCENT_HEALTH, value: num / 100, category: BuffCategory.ATTACK, string: "\n\nIncrease attack \nby" + num + "%" });
|
||
}
|
||
else {
|
||
selected.push(attackBuffs.pop());
|
||
}
|
||
break;
|
||
case BuffCategory.DOT:
|
||
dotBuffs.sort(() => 0.5 - Math.random());
|
||
if (dotBuffs.length == 0) {
|
||
selected.push({ type: BuffType.EXTRA_DOT, value: num, category: BuffCategory.DOT, string: "\n\nIncrease your \nDOT damage" });
|
||
}
|
||
else {
|
||
selected.push(dotBuffs.pop());
|
||
}
|
||
break;
|
||
case BuffCategory.EXTRA:
|
||
extraBuffs.sort(() => 0.5 - Math.random());
|
||
if (extraBuffs.length == 0) {
|
||
selected.push({ type: BuffType.EXTRALIFE, value: 1, category: BuffCategory.EXTRA, string: "\n\nGain an \nExtra Life" });
|
||
}
|
||
else {
|
||
selected.push(extraBuffs.pop());
|
||
}
|
||
break;
|
||
case BuffCategory.HEALTH:
|
||
healthBuffs.sort(() => 0.5 - Math.random());
|
||
if (healthBuffs.length == 0) {
|
||
selected.push({ type: BuffType.DEF, value: num / 100, category: BuffCategory.HEALTH, string: "\n\nDecrease damage\n taken by " + num + "%" });
|
||
}
|
||
else {
|
||
selected.push(healthBuffs.pop());
|
||
}
|
||
break;
|
||
case BuffCategory.SHIELD:
|
||
shieldBuffs.sort(() => 0.5 - Math.random());
|
||
if (shieldBuffs.length == 0) {
|
||
selected.push({ type: BuffType.FLAT_HEALTH, value: num, category: BuffCategory.SHIELD });
|
||
}
|
||
else {
|
||
selected.push(shieldBuffs.pop());
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return selected;
|
||
}
|
||
/**
|
||
* Add given buff to the player
|
||
* @param buff Given buff
|
||
* @param init whether or not this is being used during the initialization of the player
|
||
*/
|
||
addBuff(buff, init) {
|
||
//add buff to array of applied buffs if not being used to init
|
||
if (init === undefined) {
|
||
//increase weight of selected buff category
|
||
PlayerController.buffPool.push(buff.category);
|
||
PlayerController.appliedBuffs.push(buff);
|
||
}
|
||
else if (!init) {
|
||
//increase weight of selected buff category
|
||
PlayerController.buffPool.push(buff.category);
|
||
PlayerController.appliedBuffs.push(buff);
|
||
}
|
||
// TODO
|
||
let item = this.inventory.getItem();
|
||
switch (buff.type) {
|
||
case BuffType.FLAT_HEALTH:
|
||
//this.CURRENT_BUFFS.hp += buff.value;
|
||
this.CURRENT_HP += buff.value;
|
||
this.MAX_HP += buff.value;
|
||
break;
|
||
case BuffType.PERCENT_HEALTH:
|
||
this.CURRENT_HP *= (1 + buff.value);
|
||
this.MAX_HP *= (1 + buff.value);
|
||
this.CURRENT_HP = Math.round(this.CURRENT_HP);
|
||
this.MAX_HP = Math.round(this.MAX_HP);
|
||
break;
|
||
case BuffType.FLAT_ATK:
|
||
this.CURRENT_ATK += buff.value;
|
||
break;
|
||
case BuffType.PERCENT_ATK:
|
||
this.CURRENT_ATK *= buff.value;
|
||
this.CURRENT_ATK = Math.round(this.CURRENT_ATK);
|
||
break;
|
||
case BuffType.SPEED:
|
||
this.speed += buff.value;
|
||
break;
|
||
case BuffType.DEF:
|
||
this.damage_multiplier *= (1 - buff.value);
|
||
break;
|
||
case BuffType.RANGE:
|
||
if (item) {
|
||
item.EXTRA_RANGE += buff.value;
|
||
}
|
||
break;
|
||
case BuffType.BLEED:
|
||
this.hasBleed = true;
|
||
break;
|
||
case BuffType.BURN:
|
||
this.hasBurn = true;
|
||
break;
|
||
case BuffType.POISON:
|
||
this.hasPoison = true;
|
||
break;
|
||
case BuffType.EXTRA_DOT:
|
||
this.extraDotDmg += buff.value;
|
||
break;
|
||
case BuffType.SHIELD:
|
||
this.hasShield = true;
|
||
break;
|
||
case BuffType.ATKSPEED:
|
||
if (item) {
|
||
this.cooldownMultiplier -= buff.value;
|
||
//reduce cooldowntimer
|
||
item.cooldownTimer = new Timer_1.default(item.cooldown * this.cooldownMultiplier);
|
||
}
|
||
break;
|
||
case BuffType.SHIELD_DMG:
|
||
this.shieldDamage += buff.value;
|
||
break;
|
||
case BuffType.EXTRALIFE:
|
||
this.lives++;
|
||
break;
|
||
case BuffType.LIFESTEAL:
|
||
this.hasLifesteal = true;
|
||
this.lifestealratio = .2; //20% lifesteal
|
||
break;
|
||
case BuffType.LIFESTEALBUFF:
|
||
this.lifestealratio += buff.value;
|
||
break;
|
||
case BuffType.ONESHOT:
|
||
this.MAX_HP = 1;
|
||
this.CURRENT_HP = 1;
|
||
this.CURRENT_ATK *= 100;
|
||
break;
|
||
case BuffType.FULLHPBONUSDMG:
|
||
this.fullHpBonus = true;
|
||
break;
|
||
}
|
||
}
|
||
/**
|
||
*
|
||
* @returns record of the player stats
|
||
*/
|
||
getStats() {
|
||
let stats = {};
|
||
stats.CURRENT_HP = this.CURRENT_HP;
|
||
stats.CURRENT_ATK = this.CURRENT_ATK;
|
||
stats.CURRENT_SHIELD = this.CURRENT_SHIELD;
|
||
stats.CURRENT_EXP = this.CURRENT_EXP;
|
||
return;
|
||
}
|
||
toString() {
|
||
let s = "HP: " + this.CURRENT_HP + "/" + this.MAX_HP +
|
||
"\nATK: " + this.CURRENT_ATK +
|
||
"\nSpeed: " + this.speed +
|
||
"\nDamage Ratio: " + this.damage_multiplier +
|
||
"\nEnemies Killed: " + this.enemiesKilled +
|
||
"\nSword Effects:" +
|
||
(this.hasBleed ? "\n Bleed," : " ") +
|
||
(this.hasBurn ? " Burn," : "") +
|
||
(this.hasPoison ? " Poison," : "") +
|
||
(this.hasShield ? " Shield," : "") +
|
||
(this.fullHpBonus ? " FullHealth deal x10 Dmg" : "") +
|
||
(this.hasLifesteal ? " Lifesteal," : "") +
|
||
(this.hasOneShot ? " Atk x 100, maxhp set to 1" : "");
|
||
return s;
|
||
}
|
||
}
|
||
exports.default = PlayerController;
|
||
PlayerController.buffPool = new Array();
|
||
PlayerController.appliedBuffs = new Array();
|
||
|
||
},{"../../Wolfie2D/AI/StateMachineAI":4,"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Debug/Debug":25,"../../Wolfie2D/Events/GameEventType":30,"../../Wolfie2D/Timing/Timer":97,"../Tools/InputWrapper":140,"../sword_enums":144,"./PlayerStates/Fall":122,"./PlayerStates/Idle":123,"./PlayerStates/InAir":124,"./PlayerStates/Jump":125,"./PlayerStates/PlayerState":127,"./PlayerStates/Walk":128}],122:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const InAir_1 = require("./InAir");
|
||
const InputWrapper_1 = require("../../Tools/InputWrapper");
|
||
const PlayerState_1 = require("./PlayerState");
|
||
const GameEventType_1 = require("../../../Wolfie2D/Events/GameEventType");
|
||
const sword_enums_1 = require("../../sword_enums");
|
||
class Fall extends InAir_1.default {
|
||
onEnter(options) {
|
||
// this.owner.animation.play("FALL", true);
|
||
}
|
||
update(deltaT) {
|
||
if (!PlayerState_1.default.dashTimer.isStopped()) {
|
||
if (InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "dash", loop: false, holdReference: false });
|
||
}
|
||
this.owner.animation.playIfNotAlready("DASH");
|
||
}
|
||
else {
|
||
if (this.parent.invincible) {
|
||
this.owner.animation.playIfNotAlready("HURT");
|
||
}
|
||
else {
|
||
this.owner.animation.playIfNotAlready("FALL", true);
|
||
}
|
||
}
|
||
//TODO - testing doublejump, may have to move to InAir instead
|
||
// If we jump, move to the Jump state, give a burst of upwards velocity
|
||
if (this.parent.airjumps > 0 && InputWrapper_1.default.isJumpJustPressed()) {
|
||
this.parent.airjumps--;
|
||
this.finished("jump");
|
||
this.parent.velocity.y = -600; // basically jump height
|
||
}
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.owner.animation.stop();
|
||
return {};
|
||
}
|
||
}
|
||
exports.default = Fall;
|
||
|
||
},{"../../../Wolfie2D/Events/GameEventType":30,"../../Tools/InputWrapper":140,"../../sword_enums":144,"./InAir":124,"./PlayerState":127}],123:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const PlayerController_1 = require("../PlayerController");
|
||
const OnGround_1 = require("./OnGround");
|
||
const PlayerState_1 = require("./PlayerState");
|
||
class Idle extends OnGround_1.default {
|
||
onEnter(options) {
|
||
this.parent.speed = this.parent.MIN_SPEED;
|
||
}
|
||
update(deltaT) {
|
||
//("idle anim");
|
||
if (!PlayerState_1.default.dashTimer.isStopped()) {
|
||
console.log("Playing dash");
|
||
this.owner.animation.playIfNotAlready("DASH");
|
||
}
|
||
else {
|
||
this.owner.animation.playIfNotAlready("IDLE", true);
|
||
}
|
||
let dir = this.getInputDirection();
|
||
if (!dir.isZero() && dir.y === 0) {
|
||
this.finished(PlayerController_1.PlayerStates.WALK);
|
||
}
|
||
this.parent.velocity.x = 0;
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.owner.animation.stop();
|
||
return {};
|
||
}
|
||
}
|
||
exports.default = Idle;
|
||
|
||
},{"../PlayerController":121,"./OnGround":126,"./PlayerState":127}],124:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const MathUtils_1 = require("../../../Wolfie2D/Utils/MathUtils");
|
||
const PlayerController_1 = require("../PlayerController");
|
||
const PlayerState_1 = require("./PlayerState");
|
||
class InAir extends PlayerState_1.default {
|
||
update(deltaT) {
|
||
super.update(deltaT);
|
||
let dir = this.getInputDirection();
|
||
if (dir.x !== 0) {
|
||
this.owner.invertX = MathUtils_1.default.sign(dir.x) < 0;
|
||
}
|
||
this.parent.velocity.x += dir.x * (this.parent.speed) / 3.5 - 0.3 * this.parent.velocity.x;
|
||
if (this.owner.onGround) {
|
||
this.finished(PlayerController_1.PlayerStates.PREVIOUS);
|
||
}
|
||
}
|
||
}
|
||
exports.default = InAir;
|
||
|
||
},{"../../../Wolfie2D/Utils/MathUtils":102,"../PlayerController":121,"./PlayerState":127}],125:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const GameEventType_1 = require("../../../Wolfie2D/Events/GameEventType");
|
||
const InputWrapper_1 = require("../../Tools/InputWrapper");
|
||
const PlayerController_1 = require("../PlayerController");
|
||
const InAir_1 = require("./InAir");
|
||
const PlayerState_1 = require("./PlayerState");
|
||
const sword_enums_1 = require("../../sword_enums");
|
||
class Jump extends InAir_1.default {
|
||
onEnter(options) {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "jump", loop: false, holdReference: false });
|
||
}
|
||
update(deltaT) {
|
||
if (!PlayerState_1.default.dashTimer.isStopped()) {
|
||
if (InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "dash", loop: false, holdReference: false });
|
||
}
|
||
this.owner.animation.playIfNotAlready("DASH");
|
||
}
|
||
else {
|
||
if (this.parent.invincible) {
|
||
this.owner.animation.playIfNotAlready("HURT");
|
||
}
|
||
else {
|
||
this.owner.animation.playIfNotAlready("JUMP", true);
|
||
}
|
||
}
|
||
if (this.owner.onCeiling) {
|
||
this.parent.velocity.y = 0;
|
||
}
|
||
//TODO - testing doublejump, may have to move to InAir instead
|
||
// If we jump, move to the Jump state, give a burst of upwards velocity
|
||
if (this.parent.airjumps > 0 && InputWrapper_1.default.isJumpJustPressed()) {
|
||
this.parent.airjumps--;
|
||
this.finished("jump");
|
||
this.parent.velocity.y = -600; // basically jump height
|
||
}
|
||
// If we're falling, go to the fall state
|
||
if (this.parent.velocity.y >= 0) {
|
||
this.finished(PlayerController_1.PlayerStates.FALL);
|
||
}
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.owner.animation.stop();
|
||
return {};
|
||
}
|
||
}
|
||
exports.default = Jump;
|
||
|
||
},{"../../../Wolfie2D/Events/GameEventType":30,"../../Tools/InputWrapper":140,"../../sword_enums":144,"../PlayerController":121,"./InAir":124,"./PlayerState":127}],126:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const MathUtils_1 = require("../../../Wolfie2D/Utils/MathUtils");
|
||
const sword_enums_1 = require("../../sword_enums");
|
||
const InputWrapper_1 = require("../../Tools/InputWrapper");
|
||
const PlayerState_1 = require("./PlayerState");
|
||
class OnGround extends PlayerState_1.default {
|
||
onEnter(options) { }
|
||
update(deltaT) {
|
||
//reset airjumps
|
||
this.parent.airjumps = this.parent.MAX_airjumps;
|
||
if (this.parent.velocity.y > 0) {
|
||
this.parent.velocity.y = 0;
|
||
}
|
||
let direction = this.getInputDirection();
|
||
if (direction.x !== 0) {
|
||
this.owner.invertX = MathUtils_1.default.sign(direction.x) < 0;
|
||
}
|
||
// If we jump, move to the Jump state, give a burst of upwards velocity
|
||
if (InputWrapper_1.default.isJumpJustPressed()) {
|
||
this.finished("jump");
|
||
this.parent.velocity.y = -600; // basically jump height
|
||
}
|
||
else if (!this.owner.onGround && InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) {
|
||
this.finished("fall");
|
||
}
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
return {};
|
||
}
|
||
}
|
||
exports.default = OnGround;
|
||
|
||
},{"../../../Wolfie2D/Utils/MathUtils":102,"../../Tools/InputWrapper":140,"../../sword_enums":144,"./PlayerState":127}],127:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const State_1 = require("../../../Wolfie2D/DataTypes/State/State");
|
||
const Vec2_1 = require("../../../Wolfie2D/DataTypes/Vec2");
|
||
const Timer_1 = require("../../../Wolfie2D/Timing/Timer");
|
||
const sword_enums_1 = require("../../sword_enums");
|
||
const InputWrapper_1 = require("../../Tools/InputWrapper");
|
||
class PlayerState extends State_1.default {
|
||
constructor(parent, owner) {
|
||
super(parent);
|
||
this.gravity = 1500; //TODO - can change later
|
||
this.owner = owner;
|
||
this.positionTimer = new Timer_1.default(250);
|
||
this.positionTimer.start();
|
||
PlayerState.dashTimer = new Timer_1.default(100);
|
||
PlayerState.dashCoolDownTimer = new Timer_1.default(600);
|
||
}
|
||
handleInput(event) {
|
||
}
|
||
doDash() {
|
||
if (PlayerState.dashCoolDownTimer.isStopped()) {
|
||
//TODO - decide how to implement dash - could be a flash - maybe allow in air as well
|
||
//play dash anim maybe
|
||
//TODO - might give buffed speed stat to dash speed
|
||
//TODO - give player i frame
|
||
PlayerState.dashCoolDownTimer.start();
|
||
PlayerState.dashTimer.start();
|
||
}
|
||
}
|
||
/**
|
||
* Get the inputs from the keyboard, or Vec2.Zero if nothing is being pressed
|
||
*/
|
||
getInputDirection() {
|
||
let direction = Vec2_1.default.ZERO;
|
||
direction.x = (InputWrapper_1.default.isLeftPressed() ? -1 : 0) + (InputWrapper_1.default.isRightPressed() ? 1 : 0);
|
||
direction.y = (InputWrapper_1.default.isJumpJustPressed() ? -1 : 0);
|
||
return direction;
|
||
}
|
||
update(deltaT) {
|
||
// Do gravity
|
||
if (this.positionTimer.isStopped()) {
|
||
this.emitter.fireEvent(sword_enums_1.Player_Events.PLAYER_MOVE, { position: this.owner.position.clone() });
|
||
this.positionTimer.start();
|
||
}
|
||
if (InputWrapper_1.default.isDashJustPressed()) {
|
||
this.doDash();
|
||
}
|
||
if (!PlayerState.dashTimer.isStopped()) {
|
||
this.parent.velocity.x = this.owner.invertX ? -800 : 800;
|
||
}
|
||
if (InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) {
|
||
this.parent.owner.animation.resume();
|
||
this.parent.velocity.y += this.gravity * deltaT;
|
||
this.owner.move(this.parent.velocity.scaled(deltaT));
|
||
}
|
||
else {
|
||
this.parent.owner.animation.pause();
|
||
}
|
||
}
|
||
}
|
||
exports.default = PlayerState;
|
||
|
||
},{"../../../Wolfie2D/DataTypes/State/State":20,"../../../Wolfie2D/DataTypes/Vec2":24,"../../../Wolfie2D/Timing/Timer":97,"../../Tools/InputWrapper":140,"../../sword_enums":144}],128:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const InputWrapper_1 = require("../../Tools/InputWrapper");
|
||
const PlayerController_1 = require("../PlayerController");
|
||
const OnGround_1 = require("./OnGround");
|
||
const PlayerState_1 = require("./PlayerState");
|
||
const GameEventType_1 = require("../../../Wolfie2D/Events/GameEventType");
|
||
const sword_enums_1 = require("../../sword_enums");
|
||
class Walk extends OnGround_1.default {
|
||
onEnter(options) {
|
||
this.parent.speed = this.parent.MIN_SPEED;
|
||
}
|
||
update(deltaT) {
|
||
if (!PlayerState_1.default.dashTimer.isStopped()) {
|
||
if (InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "dash", loop: false, holdReference: false });
|
||
}
|
||
this.owner.animation.playIfNotAlready("DASH");
|
||
}
|
||
else {
|
||
if (this.parent.invincible) {
|
||
this.owner.animation.playIfNotAlready("HURT");
|
||
}
|
||
else {
|
||
this.owner.animation.playIfNotAlready("WALK", true);
|
||
}
|
||
}
|
||
let dir = this.getInputDirection();
|
||
if (dir.isZero()) {
|
||
this.finished(PlayerController_1.PlayerStates.IDLE);
|
||
}
|
||
this.parent.velocity.x = dir.x * (this.parent.speed);
|
||
super.update(deltaT);
|
||
}
|
||
onExit() {
|
||
this.owner.animation.stop();
|
||
return {};
|
||
}
|
||
}
|
||
exports.default = Walk;
|
||
|
||
},{"../../../Wolfie2D/Events/GameEventType":30,"../../Tools/InputWrapper":140,"../../sword_enums":144,"../PlayerController":121,"./OnGround":126,"./PlayerState":127}],129:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Registry_1 = require("../../Wolfie2D/Registry/Registries/Registry");
|
||
const ResourceManager_1 = require("../../Wolfie2D/ResourceManager/ResourceManager");
|
||
const Slice_1 = require("../GameSystems/items/WeaponTypes/Slice");
|
||
class WeaponTemplateRegistry extends Registry_1.default {
|
||
preload() {
|
||
const rm = ResourceManager_1.default.getInstance();
|
||
//TODO -
|
||
// Load sprites for each weapon
|
||
//rm.image("something", "shattered_sword_assets/sprites/something.png");
|
||
rm.image("knife", "shattered_sword_assets/sprites/knife.png");
|
||
// Load spritesheets
|
||
//rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json");
|
||
rm.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
|
||
// Register default types
|
||
//this.registerItem("itemtype", itemTypefile);
|
||
this.registerItem("slice", Slice_1.default);
|
||
}
|
||
registerAndPreloadItem(key) { }
|
||
registerItem(key, constr) {
|
||
this.add(key, constr);
|
||
}
|
||
}
|
||
exports.default = WeaponTemplateRegistry;
|
||
|
||
},{"../../Wolfie2D/Registry/Registries/Registry":63,"../../Wolfie2D/ResourceManager/ResourceManager":83,"../GameSystems/items/WeaponTypes/Slice":119}],130:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Registry_1 = require("../../Wolfie2D/Registry/Registries/Registry");
|
||
class WeaponTypeRegistry extends Registry_1.default {
|
||
preload() { }
|
||
// We don't need this for this assignment
|
||
registerAndPreloadItem(key) { }
|
||
registerItem(key, type) {
|
||
this.add(key, type);
|
||
}
|
||
}
|
||
exports.default = WeaponTypeRegistry;
|
||
|
||
},{"../../Wolfie2D/Registry/Registries/Registry":63}],131:[function(require,module,exports){
|
||
"use strict";
|
||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const AABB_1 = require("../../Wolfie2D/DataTypes/Shapes/AABB");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const GameEventType_1 = require("../../Wolfie2D/Events/GameEventType");
|
||
const GraphicTypes_1 = require("../../Wolfie2D/Nodes/Graphics/GraphicTypes");
|
||
const Label_1 = require("../../Wolfie2D/Nodes/UIElements/Label");
|
||
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
||
const Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
const PlayerController_1 = require("../Player/PlayerController");
|
||
const sword_enums_1 = require("../sword_enums");
|
||
const RegistryManager_1 = require("../../Wolfie2D/Registry/RegistryManager");
|
||
const Weapon_1 = require("../GameSystems/items/Weapon");
|
||
const BattleManager_1 = require("../GameSystems/BattleManager");
|
||
const EnemyAI_1 = require("../AI/EnemyAI");
|
||
const SnakeAI_1 = require("../AI/SnakeAI");
|
||
const SlimeAI_1 = require("../AI/SlimeAI");
|
||
const InventoryManager_1 = require("../GameSystems/InventoryManager");
|
||
const Stack_1 = require("../../Wolfie2D/DataTypes/Stack");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
const GameOver_1 = require("./GameOver");
|
||
const MainMenu_1 = require("./MainMenu");
|
||
// TODO
|
||
/**
|
||
* Add in some level music.
|
||
* This can be done here in the base GameLevel class or individual level files
|
||
*/
|
||
class GameLevel extends Scene_1.default {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.touchedStartCheckPoint = false;
|
||
this.touchedEndCheckPoint = false;
|
||
this.gameStarted = false;
|
||
this.levelEnded = false;
|
||
}
|
||
loadScene() {
|
||
//can load player sprite here
|
||
this.load.spritesheet("player", "shattered_sword_assets/spritesheets/Hiro.json");
|
||
// TODO - change when done testing
|
||
this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
|
||
// Load the scene info
|
||
this.load.object("weaponData", "shattered_sword_assets/data/weaponData.json");
|
||
// Load in the enemy info
|
||
//this.load.object("enemyData", "shattered_sword_assets/data/enemy.json");
|
||
// Load in item info
|
||
//this.load.object("itemData", "shattered_sword_assets/data/items.json");
|
||
this.load.audio("jump", "shattered_sword_assets/sounds/jump2.wav");
|
||
this.load.audio("hurt", "shattered_sword_assets/sounds/hurt.wav");
|
||
this.load.audio("die", "shattered_sword_assets/sounds/die.wav");
|
||
this.load.audio("dash", "shattered_sword_assets/sounds/dash.wav");
|
||
this.load.audio("level_up", "shattered_sword_assets/sounds/level_up.wav");
|
||
//神社(じんじゃ)祭(まつり) by Second Dimension Imagination Group
|
||
this.load.audio("level_music", "shattered_sword_assets/sounds/bgm1.mp3");
|
||
this.load.audio("sword", "shattered_sword_assets/sounds/sword_ding1.m4a");
|
||
this.load.image("knife", "shattered_sword_assets/sprites/knife.png");
|
||
this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png");
|
||
this.load.image("black", "shattered_sword_assets/images/black.png");
|
||
this.load.image("poisoning", "shattered_sword_assets/images/poisoning.png");
|
||
this.load.image("burning", "shattered_sword_assets/images/burning.png");
|
||
this.load.image("bleeding", "shattered_sword_assets/images/bleeding.png");
|
||
//TODO - choose spritesheet for slice - modify the slice.json
|
||
this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
|
||
this.load.spritesheet("test_dummy", "shattered_sword_assets/spritesheets/test_dummy.json");
|
||
this.enemies = new Array();
|
||
this.battleManager = new BattleManager_1.default();
|
||
}
|
||
unloadScene() {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.STOP_SOUND, { key: "level_music" });
|
||
}
|
||
startScene() {
|
||
this.add.tilemap("map", new Vec2_1.default(2, 2));
|
||
console.log("width,height:" + this.map.width, this.map.height);
|
||
this.viewport.setBounds(0, 0, this.map.width * 32, this.map.height * 32);
|
||
this.viewport.follow(this.player);
|
||
this.playerSpawn = this.rmg.getPlayer().scale(32);
|
||
console.log(this.playerSpawn);
|
||
this.startpos = this.rmg.getPlayer().scale(32);
|
||
// Do the game level standard initializations
|
||
this.initViewport();
|
||
this.initLayers();
|
||
// Create the battle manager
|
||
// TODO
|
||
this.initializeWeapons();
|
||
// Initialize the items array - this represents items that are in the game world
|
||
this.items = new Array();
|
||
this.initPlayer();
|
||
//subscribe to relevant events
|
||
this.subscribeToEvents();
|
||
this.addUI();
|
||
let startCheckPoint = this.rmg.getStartCheckPoint();
|
||
this.startCheckPoint = this.addCheckPoint(new Vec2_1.default(startCheckPoint[0], startCheckPoint[1]), new Vec2_1.default(startCheckPoint[2], startCheckPoint[3]), "startStory", "startTimer");
|
||
let endCheckPoint = this.rmg.getEndCheckPoint();
|
||
this.endCheckPoint = this.addCheckPoint(new Vec2_1.default(endCheckPoint[0], endCheckPoint[1]), new Vec2_1.default(endCheckPoint[2], endCheckPoint[3]), "endStory", "nextLevel");
|
||
// Create an enemies array
|
||
// Send the player and enemies to the battle manager
|
||
this.battleManager.setPlayers([this.player._ai]);
|
||
// Initialize all enemies
|
||
//this.initializeEnemies();
|
||
this.battleManager.setEnemies(this.enemies.map(enemy => enemy._ai));
|
||
let enemies = this.rmg.getEnemies();
|
||
//may have to move this to start scene in gameLevel
|
||
this.initializeEnemies(enemies);
|
||
this.gameStateStack = new Stack_1.default();
|
||
this.setGameState(sword_enums_1.GameState.GAMING);
|
||
InputWrapper_1.default.enableInput();
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "level_music", loop: true, holdReference: true });
|
||
}
|
||
updateScene(deltaT) {
|
||
if (this.gameStateStack.peek() === sword_enums_1.GameState.GAMING) {
|
||
if (this.gameStarted) {
|
||
GameLevel.gameTimer += deltaT;
|
||
this.timerLable.textColor = Color_1.default.BLACK;
|
||
}
|
||
else {
|
||
this.timerLable.textColor = Color_1.default.RED;
|
||
}
|
||
let minutes = Math.floor(GameLevel.gameTimer / 60);
|
||
if (minutes >= 10) {
|
||
this.timerLable.text = minutes.toString();
|
||
}
|
||
else {
|
||
this.timerLable.text = "0" + minutes.toString();
|
||
}
|
||
let seconds = Math.floor(GameLevel.gameTimer % 60);
|
||
if (seconds >= 10) {
|
||
this.timerLable.text += ":" + seconds.toString();
|
||
}
|
||
else {
|
||
this.timerLable.text += ":0" + seconds.toString();
|
||
}
|
||
}
|
||
// Handle events and update the UI if needed
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
if (this.gameStateStack.peek() === sword_enums_1.GameState.GAMING) {
|
||
switch (event.type) {
|
||
case sword_enums_1.Player_Events.PLAYER_COLLIDE:
|
||
let n = this.sceneGraph.getNode(event.data.get("node"));
|
||
let other = this.sceneGraph.getNode(event.data.get("other"));
|
||
if (n === this.player) {
|
||
// Node is player, other is enemy
|
||
this.handlePlayerEnemyCollision(n, other);
|
||
}
|
||
else {
|
||
// Other is player, node is balloon
|
||
this.handlePlayerEnemyCollision(other, n);
|
||
}
|
||
break;
|
||
case sword_enums_1.Player_Events.ENEMY_KILLED:
|
||
let node = this.sceneGraph.getNode(event.data.get("owner")); //get enemy id
|
||
//remove enemy from enemies
|
||
this.enemies = this.enemies.filter(item => item !== event.data.get("ai"));
|
||
this.battleManager.removeEnemy(event.data.get("ai"));
|
||
//give the player the exp value of the enemy killed
|
||
if (event.data.get("ai").exp_val !== undefined) {
|
||
this.player._ai.giveExp(event.data.get("ai").exp_val);
|
||
}
|
||
node.destroy(); //destroy enemy node
|
||
this.player._ai.enemiesKilled++;
|
||
break;
|
||
case sword_enums_1.Player_Events.GIVE_REGULAR_BUFF:
|
||
this.buffs = this.player._ai.generateRegularBuffs();
|
||
if (this.buffs[0].string === undefined) {
|
||
this.buffLabel1.text = "\n\nIncrease " + this.buffs[0].type + "\n by " + this.buffs[0].value;
|
||
}
|
||
else {
|
||
this.buffLabel1.text = this.buffs[0].string;
|
||
}
|
||
if (this.buffs[1].string === undefined) {
|
||
this.buffLabel2.text = "\n\nIncrease " + this.buffs[1].type + "\n by " + this.buffs[1].value;
|
||
}
|
||
else {
|
||
this.buffLabel2.text = this.buffs[1].string;
|
||
}
|
||
if (this.buffs[2].string === undefined) {
|
||
this.buffLabel3.text = "\n\nIncrease " + this.buffs[2].type + "\n by " + this.buffs[2].value;
|
||
}
|
||
else {
|
||
this.buffLabel3.text = this.buffs[2].string;
|
||
}
|
||
//pause game here
|
||
this.setGameState(sword_enums_1.GameState.BUFF);
|
||
this.buffLayer.enable();
|
||
break;
|
||
case sword_enums_1.Player_Events.GIVE_SPECIAL_BUFF:
|
||
this.buffs = this.player._ai.generateSpecialBuffs();
|
||
if (this.buffs[0].string === undefined) {
|
||
this.buffLabel1.text = "\n\nIncrease " + this.buffs[0].type + "\n by " + this.buffs[0].value;
|
||
}
|
||
else {
|
||
this.buffLabel1.text = this.buffs[0].string;
|
||
}
|
||
if (this.buffs[1].string === undefined) {
|
||
this.buffLabel2.text = "\n\nIncrease " + this.buffs[1].type + "\n by " + this.buffs[1].value;
|
||
}
|
||
else {
|
||
this.buffLabel2.text = this.buffs[1].string;
|
||
}
|
||
if (this.buffs[2].string === undefined) {
|
||
this.buffLabel3.text = "\n\nIncrease " + this.buffs[2].type + "\n by " + this.buffs[2].value;
|
||
}
|
||
else {
|
||
this.buffLabel3.text = this.buffs[2].string;
|
||
}
|
||
//pause game here
|
||
this.setGameState(sword_enums_1.GameState.BUFF);
|
||
this.buffLayer.enable();
|
||
break;
|
||
case sword_enums_1.Player_Events.PLAYER_KILLED:
|
||
//respawn player if he has lives, otherwise end game
|
||
console.log("player Died");
|
||
this.player.animation.play("DEAD", false);
|
||
InputWrapper_1.default.disableInput();
|
||
if (this.player._ai.lives > 0) {
|
||
this.respawnPlayer();
|
||
}
|
||
else { //no more lives
|
||
this.viewport.setZoomLevel(1);
|
||
this.sceneManager.changeToScene(GameOver_1.default, {});
|
||
InputWrapper_1.default.enableInput();
|
||
}
|
||
break;
|
||
case "startStory":
|
||
this.playStartStory();
|
||
break;
|
||
case "endStory":
|
||
this.playEndStory();
|
||
break;
|
||
case "startTimer":
|
||
this.startTimer();
|
||
break;
|
||
case "nextLevel":
|
||
this.goToNextLevel();
|
||
break;
|
||
}
|
||
}
|
||
else if (this.gameStateStack.peek() === sword_enums_1.GameState.BUFF) {
|
||
switch (event.type) {
|
||
case "buff1":
|
||
this.player._ai.addBuff(this.buffs[0]);
|
||
this.buffLayer.disable();
|
||
this.setGameState();
|
||
if (this.levelEnded) {
|
||
this.goToNextLevel();
|
||
}
|
||
break;
|
||
case "buff2":
|
||
this.player._ai.addBuff(this.buffs[1]);
|
||
this.buffLayer.disable();
|
||
this.setGameState();
|
||
if (this.levelEnded) {
|
||
this.goToNextLevel();
|
||
}
|
||
break;
|
||
case "buff3":
|
||
this.player._ai.addBuff(this.buffs[2]);
|
||
this.buffLayer.disable();
|
||
this.setGameState();
|
||
if (this.levelEnded) {
|
||
this.goToNextLevel();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (event.type === "cheat") {
|
||
this.enableCheat();
|
||
}
|
||
if (event.type === "MainMenu") {
|
||
this.viewport.setZoomLevel(1);
|
||
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
||
InputWrapper_1.default.enableInput();
|
||
}
|
||
}
|
||
if (this.gameStateStack.peek() === sword_enums_1.GameState.STORY) {
|
||
if (InputWrapper_1.default.isNextJustPressed() && this.gameStateStack.peek() === sword_enums_1.GameState.STORY) {
|
||
this.updateStory();
|
||
}
|
||
}
|
||
if (InputWrapper_1.default.isPauseJustPressed()) {
|
||
this.pauseText.text = this.player._ai.toString();
|
||
if (this.gameStateStack.peek() === sword_enums_1.GameState.GAMING) {
|
||
this.setGameState(sword_enums_1.GameState.PAUSE);
|
||
this.pauseLayer.enable();
|
||
}
|
||
else if (this.gameStateStack.peek() === sword_enums_1.GameState.PAUSE) {
|
||
this.setGameState();
|
||
this.pauseLayer.disable();
|
||
}
|
||
}
|
||
if (InputWrapper_1.default.isBuff1JustPresed()) {
|
||
this.emitter.fireEvent("buff1");
|
||
}
|
||
if (InputWrapper_1.default.isBuff2JustPresed()) {
|
||
this.emitter.fireEvent("buff2");
|
||
}
|
||
if (InputWrapper_1.default.isBuff3JustPresed()) {
|
||
this.emitter.fireEvent("buff3");
|
||
}
|
||
//update health UI
|
||
let playerAI = this.player.ai;
|
||
this.healthLabel.text = "Health: " + Math.round(playerAI.CURRENT_HP) + '/' + Math.round(playerAI.MAX_HP);
|
||
this.healthBar.size.set(playerAI.MAX_HP * 1.5, 10);
|
||
this.healthBar.position.set(playerAI.MAX_HP * 0.75 + 20, 20);
|
||
this.healthBar.fillWidth = playerAI.CURRENT_HP * 1.5;
|
||
if (playerAI.CURRENT_HP / playerAI.MAX_HP >= 2 / 3) {
|
||
this.healthBar.color = Color_1.default.GREEN;
|
||
this.healthLabel.textColor = Color_1.default.GREEN;
|
||
}
|
||
else if (playerAI.CURRENT_HP / playerAI.MAX_HP >= 1 / 3) {
|
||
this.healthBar.color = Color_1.default.YELLOW;
|
||
this.healthLabel.textColor = Color_1.default.YELLOW;
|
||
}
|
||
else {
|
||
this.healthBar.color = Color_1.default.RED;
|
||
this.healthLabel.textColor = Color_1.default.RED;
|
||
}
|
||
// this.healthLabel.sizeToText();
|
||
//update shield ui
|
||
this.shieldLabel.text = "Shield: " + Math.round(playerAI.CURRENT_SHIELD) + '/' + Math.round(playerAI.MAX_SHIELD);
|
||
this.shieldBar.size.set(playerAI.CURRENT_SHIELD * 1.5, 10);
|
||
this.shieldBar.position.set(playerAI.CURRENT_SHIELD * 0.75 + 20, 50);
|
||
// this.shieldLabel.sizeToText();
|
||
//update exp ui
|
||
this.expLabel.text = "EXP: " + Math.round(playerAI.CURRENT_EXP) + '/' + Math.round(playerAI.MAX_EXP);
|
||
this.expBar.fillWidth = (playerAI.CURRENT_EXP / playerAI.MAX_EXP) * 150;
|
||
// this.expLabel.sizeToText();
|
||
//update level ui
|
||
this.playerLevelLabel.text = "Lv." + playerAI.level;
|
||
//update lives ui
|
||
this.livesCountLabel.text = "Lives: " + playerAI.lives;
|
||
//move background
|
||
// Get the viewport center and padded size
|
||
const viewportCenter = this.viewport.getCenter().clone();
|
||
const baseViewportSize = this.viewport.getHalfSize().scaled(2);
|
||
//check position of player
|
||
this.playerFalloff(viewportCenter, baseViewportSize);
|
||
}
|
||
// TODO put UI changes in here
|
||
setGameState(gameState) {
|
||
if (gameState) {
|
||
this.gameStateStack.push(gameState);
|
||
InputWrapper_1.default.setState(gameState);
|
||
}
|
||
else {
|
||
this.gameStateStack.pop();
|
||
InputWrapper_1.default.setState(this.gameStateStack.peek());
|
||
}
|
||
}
|
||
/**
|
||
* Initialzes the layers
|
||
*/
|
||
initLayers() {
|
||
// Add a layer for UI
|
||
this.addUILayer("UI");
|
||
// Add a layer for players and enemies
|
||
this.addLayer("primary", 1);
|
||
this.buffLayer = this.addUILayer("buffLayer");
|
||
this.storyLayer = this.addUILayer("story");
|
||
this.storyLayer.disable();
|
||
this.pauseLayer = this.addUILayer("pause");
|
||
this.pauseLayer.disable();
|
||
this.receiver.subscribe("loadStory");
|
||
}
|
||
/**
|
||
* Initializes the viewport
|
||
*/
|
||
initViewport() {
|
||
this.viewport.setZoomLevel(2);
|
||
}
|
||
/**
|
||
* Handles all subscriptions to events
|
||
*/
|
||
subscribeToEvents() {
|
||
this.receiver.subscribe([
|
||
sword_enums_1.Player_Events.PLAYER_COLLIDE,
|
||
sword_enums_1.Player_Events.PLAYER_HIT_ENEMY,
|
||
sword_enums_1.Player_Events.ENEMY_KILLED,
|
||
sword_enums_1.Player_Events.LEVEL_START,
|
||
sword_enums_1.Player_Events.LEVEL_END,
|
||
sword_enums_1.Player_Events.PLAYER_KILLED,
|
||
sword_enums_1.Player_Events.GIVE_REGULAR_BUFF,
|
||
sword_enums_1.Player_Events.GIVE_SPECIAL_BUFF
|
||
]);
|
||
this.receiver.subscribe("buff1");
|
||
this.receiver.subscribe("buff2");
|
||
this.receiver.subscribe("buff3");
|
||
this.receiver.subscribe("cheat");
|
||
this.receiver.subscribe("startStory");
|
||
this.receiver.subscribe("startTimer");
|
||
this.receiver.subscribe("endStory");
|
||
this.receiver.subscribe("nextLevel");
|
||
this.receiver.subscribe("MainMenu");
|
||
}
|
||
// TODO -
|
||
/**
|
||
* Adds in any necessary UI to the game
|
||
*/
|
||
addUI() {
|
||
// In-game labels
|
||
this.healthLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(70, 35), text: "Player Health: " + this.player.ai.CURRENT_HP });
|
||
this.healthLabel.size.set(200, 50);
|
||
this.healthLabel.setHAlign(Label_1.HAlign.LEFT);
|
||
this.healthLabel.textColor = Color_1.default.GREEN;
|
||
this.healthLabel.font = "PixelSimple";
|
||
this.healthLabel.fontSize = 25;
|
||
this.healthBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(0, 0), size: new Vec2_1.default(0, 0) });
|
||
this.healthBar.borderColor = Color_1.default.BLACK;
|
||
this.healthBar.borderWidth = 3;
|
||
this.healthBar.color = Color_1.default.GREEN;
|
||
// this.poisonStat = this.add.sprite("poisoning", "UI");
|
||
// this.poisonStat.position.set(55, 25);
|
||
// this.poisonStat.scale.set(0.3, 0.3);
|
||
// this.burnStat = this.add.sprite("burning", "UI");
|
||
// this.burnStat.position.set(70, 25);
|
||
// this.burnStat.scale.set(0.3, 0.3);
|
||
// this.bleedStat = this.add.sprite("bleeding", "UI");
|
||
// this.bleedStat.position.set(85, 25);
|
||
// this.bleedStat.scale.set(0.3, 0.3);
|
||
this.shieldLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(70, 65), text: "shield: " + this.player.ai.CURRENT_SHIELD });
|
||
this.shieldLabel.size.set(200, 50);
|
||
this.shieldLabel.setHAlign(Label_1.HAlign.LEFT);
|
||
this.shieldLabel.textColor = Color_1.default.ORANGE;
|
||
this.shieldLabel.font = "PixelSimple";
|
||
this.shieldLabel.fontSize = 25;
|
||
this.shieldBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(0, 0), size: new Vec2_1.default(0, 0) });
|
||
this.shieldBar.borderColor = Color_1.default.BLACK;
|
||
this.shieldBar.borderWidth = 3;
|
||
this.shieldBar.color = Color_1.default.ORANGE;
|
||
this.playerLevelLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(20, 95), text: "Lv. " + this.player.ai.level });
|
||
this.playerLevelLabel.size.set(0, 50);
|
||
this.playerLevelLabel.setHAlign(Label_1.HAlign.LEFT);
|
||
this.playerLevelLabel.textColor = Color_1.default.BLUE;
|
||
this.playerLevelLabel.font = "PixelSimple";
|
||
this.playerLevelLabel.fontSize = 25;
|
||
this.expLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(100, 95), text: "EXP: " + this.player.ai.CURRENT_EXP });
|
||
this.expLabel.size.set(200, 50);
|
||
this.expLabel.setHAlign(Label_1.HAlign.LEFT);
|
||
this.expLabel.textColor = Color_1.default.BLUE;
|
||
this.expLabel.font = "PixelSimple";
|
||
this.expLabel.fontSize = 25;
|
||
this.expBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(95, 80), size: new Vec2_1.default(150, 10) });
|
||
this.expBar.borderColor = Color_1.default.BLACK;
|
||
this.expBar.borderWidth = 3;
|
||
this.expBar.color = Color_1.default.BLUE;
|
||
//seed label
|
||
//worldsize.x doesnt work how i want it to
|
||
this.seedLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(70, Math.floor(this.viewport.getHalfSize().y * 2 - 30)), text: "Seed: " + InputWrapper_1.default.randomSeed });
|
||
this.seedLabel.size.set(200, 50);
|
||
this.seedLabel.setHAlign(Label_1.HAlign.LEFT);
|
||
this.seedLabel.textColor = Color_1.default.BLACK;
|
||
this.seedLabel.font = "PixelSimple";
|
||
this.add.sprite("black", "pause");
|
||
this.add.sprite("black", "story");
|
||
this.add.sprite("black", "buffLayer");
|
||
//TODO -
|
||
//determine button location
|
||
this.buffButton1 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "buffLayer", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x * 2 / 3 - 180 / 2), Math.floor(this.viewport.getHalfSize().y)), text: "" });
|
||
this.buffButton1.size.set(180, 200);
|
||
this.buffButton1.borderWidth = 5;
|
||
this.buffButton1.borderColor = Color_1.default.RED;
|
||
this.buffButton1.backgroundColor = Color_1.default.WHITE;
|
||
this.buffButton1.textColor = Color_1.default.BLACK;
|
||
this.buffButton1.onClickEventId = "buff1";
|
||
this.buffButton1.fontSize = 20;
|
||
this.buffLabel1 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "buffLayer", { position: new Vec2_1.default(this.buffButton1.position.x, this.buffButton1.position.y - 40), text: "buffLabel1" });
|
||
this.buffLabel1.fontSize = 20;
|
||
this.buffButton2 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "buffLayer", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x), Math.floor(this.viewport.getHalfSize().y)), text: "" });
|
||
this.buffButton2.size.set(180, 200);
|
||
this.buffButton2.borderWidth = 5;
|
||
this.buffButton2.borderColor = Color_1.default.RED;
|
||
this.buffButton2.backgroundColor = Color_1.default.WHITE;
|
||
this.buffButton2.textColor = Color_1.default.BLACK;
|
||
this.buffButton2.onClickEventId = "buff2";
|
||
this.buffButton2.fontSize = 20;
|
||
this.buffLabel2 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "buffLayer", { position: new Vec2_1.default(this.buffButton2.position.x, this.buffButton2.position.y - 40), text: "buffLabel2" });
|
||
this.buffLabel2.fontSize = 20;
|
||
this.buffButton3 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "buffLayer", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x * 4 / 3 + 180 / 2), Math.floor(this.viewport.getHalfSize().y)), text: "" });
|
||
this.buffButton3.size.set(180, 200);
|
||
this.buffButton3.borderWidth = 5;
|
||
this.buffButton3.borderColor = Color_1.default.RED;
|
||
this.buffButton3.backgroundColor = Color_1.default.WHITE;
|
||
this.buffButton3.textColor = Color_1.default.BLACK;
|
||
this.buffButton3.onClickEventId = "buff3";
|
||
this.buffButton3.fontSize = 20;
|
||
this.buffLabel3 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "buffLayer", { position: new Vec2_1.default(this.buffButton3.position.x, this.buffButton3.position.y - 40), text: "buffLabel3" });
|
||
this.buffLabel3.fontSize = 20;
|
||
this.buffs = this.player._ai.generateRegularBuffs();
|
||
this.buffLayer.disable();
|
||
this.pauseText = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x - 120), Math.floor(this.viewport.getHalfSize().y - 100)), text: "" });
|
||
this.pauseInput = this.add.uiElement(UIElementTypes_1.UIElementType.TEXT_INPUT, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x - 20), Math.floor(this.viewport.getHalfSize().y + 100)), text: "" });
|
||
this.pauseCheatText = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x - 120), Math.floor(this.viewport.getHalfSize().y + 80)), text: "⬇️⬇️⬇️Cheat Code⬇️⬇️⬇️" });
|
||
this.pauseSubmit = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x + 120), Math.floor(this.viewport.getHalfSize().y + 100)), text: "Submit" });
|
||
this.pauseLayer.setAlpha(0.5);
|
||
this.pauseText.textColor = Color_1.default.WHITE;
|
||
this.pauseText.setHAlign(Label_1.HAlign.LEFT);
|
||
this.pauseText.size = new Vec2_1.default(0, 40);
|
||
this.pauseText.text = "HP:\nATK:\nDamage Ratio:\nBuff1:\nBuff2:\nBuff3:\nBuff4:\nBuff5:\nBuff6:\nEnemy Killed:\n";
|
||
this.pauseCheatText.textColor = Color_1.default.WHITE;
|
||
this.pauseCheatText.size = new Vec2_1.default(0, 40);
|
||
this.pauseCheatText.setHAlign(Label_1.HAlign.LEFT);
|
||
this.pauseInput.size.set(400, 30);
|
||
this.pauseSubmit.textColor = Color_1.default.BLACK;
|
||
this.pauseSubmit.borderColor = Color_1.default.BLACK;
|
||
this.pauseSubmit.backgroundColor = Color_1.default.WHITE;
|
||
this.pauseSubmit.onClickEventId = "cheat";
|
||
this.pauseSubmit.borderWidth = 3;
|
||
this.mainMenuButton = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x), Math.floor(this.viewport.getHalfSize().y + 150)), text: "Main Menu" });
|
||
this.mainMenuButton.size.set(180, 50);
|
||
this.mainMenuButton.borderWidth = 5;
|
||
this.mainMenuButton.borderColor = Color_1.default.BLACK;
|
||
this.mainMenuButton.backgroundColor = Color_1.default.WHITE;
|
||
this.mainMenuButton.textColor = Color_1.default.BLACK;
|
||
this.mainMenuButton.onClickEventId = "MainMenu";
|
||
this.mainMenuButton.fontSize = 20;
|
||
this.livesCountLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(this.viewport.getHalfSize().x * 2 - 100, 30), text: "Lives: " });
|
||
this.livesCountLabel.textColor = Color_1.default.YELLOW;
|
||
this.livesCountLabel.fontSize = 25;
|
||
this.timerLable = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x), 30), text: "00:00" });
|
||
this.timerLable.fontSize = 60;
|
||
}
|
||
//TODO - determine whether we will have weapon datatype
|
||
/**
|
||
*
|
||
* Creates and returns a new weapon
|
||
* @param type The weaponType of the weapon, as a string
|
||
*/
|
||
createWeapon(type) {
|
||
let weaponType = RegistryManager_1.default.getRegistry("weaponTypes").get(type);
|
||
let sprite = this.add.sprite(weaponType.spriteKey, "primary");
|
||
return new Weapon_1.default(sprite, weaponType, this.battleManager);
|
||
}
|
||
/**
|
||
* Initalizes all weapon types based of data from weaponData.json
|
||
*/
|
||
initializeWeapons() {
|
||
let weaponData = this.load.getObject("weaponData");
|
||
for (let i = 0; i < weaponData.numWeapons; i++) {
|
||
let weapon = weaponData.weapons[i];
|
||
// Get the constructor of the prototype
|
||
let constr = RegistryManager_1.default.getRegistry("weaponTemplates").get(weapon.weaponType);
|
||
// Create a weapon type
|
||
let weaponType = new constr();
|
||
// Initialize the weapon type
|
||
weaponType.initialize(weapon);
|
||
// Register the weapon type
|
||
RegistryManager_1.default.getRegistry("weaponTypes").registerItem(weapon.name, weaponType);
|
||
}
|
||
}
|
||
/**
|
||
* Initializes the player
|
||
*/
|
||
initPlayer() {
|
||
//create the inventory
|
||
let inventory = new InventoryManager_1.default(this, 1, "inventorySlot", new Vec2_1.default(16, 16), 4, "slots1", "items1");
|
||
//add starting weapon to inventory
|
||
let startingWeapon = this.createWeapon("knife");
|
||
inventory.addItem(startingWeapon); //using slice to test right now
|
||
// Add the player
|
||
this.player = this.add.animatedSprite("player", "primary");
|
||
this.player.scale.set(1, 1);
|
||
if (!this.playerSpawn) {
|
||
console.warn("Player spawn was never set - setting spawn to (0, 0)");
|
||
this.playerSpawn = Vec2_1.default.ZERO;
|
||
}
|
||
this.startpos = this.playerSpawn;
|
||
this.player.position.copy(this.playerSpawn);
|
||
this.player.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, new Vec2_1.default(14, 16))); //sets the collision shape
|
||
this.player.colliderOffset.set(0, 16);
|
||
this.player.addAI(PlayerController_1.default, {
|
||
playerType: "platformer",
|
||
tilemap: "Main",
|
||
speed: 100,
|
||
health: 10,
|
||
inventory: inventory,
|
||
items: this.items,
|
||
inputEnabled: false,
|
||
range: 100
|
||
});
|
||
this.player.setGroup("player");
|
||
this.viewport.follow(this.player);
|
||
}
|
||
//TODO -
|
||
/**
|
||
* Adds an Enemy into the game
|
||
* @param spriteKey The key of the Enemy sprite
|
||
* @param tilePos The tilemap position to add the Enemy to
|
||
* @param aiOptions The options for the Enemy AI
|
||
*/
|
||
addEnemy(spriteKey, tilePos, ai, aiOptions) {
|
||
let enemy = this.add.animatedSprite(spriteKey, "primary");
|
||
//enemy.position.set(tilePos.x*32, tilePos.y*32);
|
||
enemy.position.copy(tilePos);
|
||
if ("scale" in aiOptions) {
|
||
enemy.scale.set(aiOptions.scale, aiOptions.scale);
|
||
}
|
||
else {
|
||
enemy.scale.set(2, 2);
|
||
}
|
||
//TODO - add custom collision shape for each enemy in an option variable
|
||
if ("size" in aiOptions) {
|
||
enemy.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, aiOptions.size.clone()));
|
||
}
|
||
else {
|
||
enemy.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, new Vec2_1.default(16, 25)));
|
||
}
|
||
if ("offset" in aiOptions) {
|
||
enemy.colliderOffset.set(aiOptions.offset.x, aiOptions.offset.y);
|
||
}
|
||
else {
|
||
enemy.colliderOffset.set(0, 6);
|
||
}
|
||
enemy.addAI(ai, aiOptions); //TODO - add individual enemy AI
|
||
enemy._ai.healthBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "primary", { position: enemy.collisionShape.center.clone().add(new Vec2_1.default(0, -(enemy.collisionShape.hh + 5))), size: new Vec2_1.default(enemy.collisionShape.hw * 3, 5) });
|
||
enemy._ai.healthBar.borderColor = Color_1.default.BLACK;
|
||
enemy._ai.healthBar.borderWidth = 1;
|
||
enemy._ai.healthBar.color = Color_1.default.GREEN;
|
||
enemy._ai.poisonStat = this.add.sprite("poisoning", "primary");
|
||
enemy._ai.poisonStat.position = enemy.collisionShape.center.clone().add(new Vec2_1.default(((enemy.collisionShape.hw) * -1, -(enemy.collisionShape.hh + 5))));
|
||
enemy._ai.poisonStat.scale.set(1, 1);
|
||
enemy._ai.burnStat = this.add.sprite("burning", "primary");
|
||
enemy._ai.burnStat.position = enemy._ai.poisonStat.position.clone().add(new Vec2_1.default(15, 0));
|
||
enemy._ai.burnStat.scale.set(1, 1);
|
||
enemy._ai.bleedStat = this.add.sprite("bleeding", "primary");
|
||
enemy._ai.bleedStat.position = enemy._ai.poisonStat.position.clone().add(new Vec2_1.default(30, 0));
|
||
enemy._ai.bleedStat.scale.set(1, 1);
|
||
enemy.setGroup("Enemy");
|
||
enemy.setTrigger("player", sword_enums_1.Player_Events.PLAYER_COLLIDE, null);
|
||
//add enemy to the enemy array
|
||
this.enemies.push(enemy);
|
||
//this.battleManager.setEnemies(this.enemies.map(enemy => <BattlerAI>enemy._ai));
|
||
this.battleManager.addEnemy(enemy._ai);
|
||
}
|
||
//TODO - give each enemy unique weapon
|
||
initializeEnemies(enemies) {
|
||
for (let enemy of enemies) {
|
||
switch (enemy.type) {
|
||
case "Snake": //Snake enemies drop from sky("trees")? or could just be very abundant
|
||
this.addEnemy("Snake", enemy.position.scale(32), SnakeAI_1.default, {
|
||
player: this.player,
|
||
health: 50,
|
||
tilemap: "Main",
|
||
size: new Vec2_1.default(14, 10),
|
||
offset: new Vec2_1.default(0, 22),
|
||
exp: 50,
|
||
});
|
||
break;
|
||
case "Tiger": //Tiger can be miniboss for now?
|
||
this.addEnemy("Tiger", enemy.position.scale(32), EnemyAI_1.default, {
|
||
player: this.player,
|
||
health: 200,
|
||
tilemap: "Main",
|
||
exp: 100,
|
||
});
|
||
break;
|
||
case "remus_werewolf":
|
||
this.addEnemy("remus_werewolf", enemy.position.scale(32), EnemyAI_1.default, {
|
||
player: this.player,
|
||
health: 200,
|
||
tilemap: "Main",
|
||
exp: 50,
|
||
});
|
||
break;
|
||
case "black_pudding":
|
||
this.addEnemy("black_pudding", enemy.position.scale(32), SlimeAI_1.default, {
|
||
player: this.player,
|
||
health: 200,
|
||
tilemap: "Main",
|
||
//actions:actions,
|
||
scale: .25,
|
||
size: new Vec2_1.default(16, 10),
|
||
offset: new Vec2_1.default(0, 6),
|
||
exp: 50,
|
||
weapon: this.createWeapon("knife"),
|
||
});
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
addCheckPoint(startingTile, size, enter, exit) {
|
||
let checkPoint = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "primary", { position: startingTile.scale(32), size: size.scale(32) });
|
||
checkPoint.addPhysics(undefined, undefined, false, true);
|
||
checkPoint.setTrigger("player", enter, null);
|
||
checkPoint.color = new Color_1.default(0, 0, 0, 0);
|
||
return checkPoint;
|
||
}
|
||
/**
|
||
* damages the player if they collide with an enemy
|
||
* @param player player sprite
|
||
* @param enemy enemy sprite
|
||
*/
|
||
handlePlayerEnemyCollision(player, enemy) {
|
||
if (enemy === undefined) {
|
||
console.log("undefined enemy");
|
||
return;
|
||
}
|
||
if (player === undefined) {
|
||
console.log("undefined player");
|
||
return;
|
||
}
|
||
if (typeof enemy != undefined && typeof player != undefined) {
|
||
//damage the player
|
||
enemy._ai.collideWithPlayer(this.player._ai);
|
||
}
|
||
}
|
||
/**
|
||
* Increments the amount of life the player has
|
||
* @param amt The amount to add to the player life
|
||
*/
|
||
/*
|
||
protected incPlayerLife(amt: number): void {
|
||
GameLevel.livesCount += amt;
|
||
this.livesCountLabel.text = "Lives: " + GameLevel.livesCount;
|
||
if (GameLevel.livesCount === 0){
|
||
InputWrapper.disableInput();
|
||
this.player.disablePhysics();
|
||
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "player_death", loop: false, holdReference: false});
|
||
this.player.tweens.play("death");
|
||
}
|
||
}
|
||
*/
|
||
/**
|
||
* Returns the player to spawn
|
||
*/
|
||
respawnPlayer() {
|
||
InputWrapper_1.default.enableInput();
|
||
this.player.position.copy(this.startpos);
|
||
this.player._ai.CURRENT_HP = this.player._ai.MAX_HP;
|
||
//(<PlayerController>this.player._ai).lives --;
|
||
}
|
||
/**
|
||
*
|
||
* handles the player falling off the map
|
||
*
|
||
* @param viewportCenter The center of the viewport
|
||
* @param viewportSize The size of the viewport
|
||
*/
|
||
playerFalloff(viewportCenter, viewportSize) {
|
||
if (this.player.position.y >= viewportCenter.y + viewportSize.y / 2.0) {
|
||
this.player.position.set(this.playerSpawn.x, this.playerSpawn.y);
|
||
//TODO - decrease player health or can kill player here
|
||
//(<PlayerController>this.player._ai).CURRENT_HP *= .75;
|
||
//this.emitter.fireEvent(Player_Events.PLAYER_KILLED);
|
||
}
|
||
}
|
||
playStartStory() {
|
||
if (!this.touchedStartCheckPoint) {
|
||
this.touchedStartCheckPoint = true;
|
||
this.storyLoader("shattered_sword_assets/jsons/story.json");
|
||
this.startTimer();
|
||
}
|
||
}
|
||
playEndStory() {
|
||
if (!this.touchedEndCheckPoint) {
|
||
this.touchedEndCheckPoint = true;
|
||
this.storyLoader("shattered_sword_assets/jsons/story.json");
|
||
this.endTimer();
|
||
this.levelEnded = true;
|
||
}
|
||
}
|
||
startTimer() {
|
||
this.gameStarted = true;
|
||
}
|
||
endTimer() {
|
||
this.gameStarted = false;
|
||
}
|
||
goToNextLevel() {
|
||
// this.sceneManager.changeToScene(Porcelain);
|
||
}
|
||
storyLoader(storyPath) {
|
||
return __awaiter(this, void 0, void 0, function* () {
|
||
if (this.gameStateStack.peek() === sword_enums_1.GameState.STORY) {
|
||
return;
|
||
}
|
||
this.setGameState(sword_enums_1.GameState.STORY);
|
||
const response = yield (yield fetch(storyPath)).json();
|
||
this.story = response;
|
||
console.log("story:", this.story);
|
||
if (this.story.bgm) {
|
||
this.storyBGMs = new Array;
|
||
this.story.bgm.forEach((bgm) => {
|
||
if (this.load.getAudio(bgm.key)) {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: bgm.key, loop: false, holdReference: true });
|
||
}
|
||
else {
|
||
this.load.singleAudio(bgm.key, bgm.path, () => {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: bgm.key, loop: false, holdReference: true });
|
||
});
|
||
}
|
||
this.storyBGMs.push(bgm.key);
|
||
});
|
||
}
|
||
this.currentSpeaker = this.story.texts[0].speaker;
|
||
this.currentContent = this.story.texts[0].content;
|
||
this.storyLayer.enable();
|
||
this.storytextLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "story", { position: new Vec2_1.default(50, this.viewport.getHalfSize().y + 80), text: "" });
|
||
this.storytextLabel.size = new Vec2_1.default(0, 25);
|
||
this.storytextLabel.textColor = Color_1.default.WHITE;
|
||
this.storytextLabel.font = "PixelSimple";
|
||
this.storytextLabel.fontSize = 25;
|
||
this.storytextLabel.setHAlign(Label_1.HAlign.LEFT);
|
||
this.storyProgress = -1;
|
||
this.storySprites = new Array;
|
||
this.updateStory();
|
||
});
|
||
}
|
||
hasNextStory() {
|
||
return this.gameStateStack.peek() === sword_enums_1.GameState.STORY && this.storyProgress + 1 < this.story.texts.length;
|
||
}
|
||
updateStory() {
|
||
if (this.hasNextStory()) {
|
||
this.storyProgress++;
|
||
let tmp = undefined;
|
||
if (this.story.texts[this.storyProgress].actions) {
|
||
this.story.texts[this.storyProgress].actions.forEach(action => {
|
||
switch (action.type) {
|
||
case "loadSprite":
|
||
if (this.load.getImage(action.key)) {
|
||
tmp = this.add.sprite(action.key, "story");
|
||
tmp.position.set(action.positon[0], action.positon[1]);
|
||
tmp.scale.set(action.scale[0], action.scale[1]);
|
||
this.storySprites.push(tmp);
|
||
}
|
||
else {
|
||
this.load.singleImage(action.key, action.path, () => {
|
||
tmp = this.add.sprite(action.key, "story");
|
||
tmp.position.set(action.positon[0], action.positon[1]);
|
||
tmp.scale.set(action.scale[0], action.scale[1]);
|
||
this.storySprites.push(tmp);
|
||
});
|
||
}
|
||
break;
|
||
case "moveSprite":
|
||
tmp = this.storySprites.find(function (sprite) {
|
||
return sprite.imageId === action.key;
|
||
});
|
||
tmp.position.set(action.positon[0], action.positon[1]);
|
||
tmp.scale.set(action.scale[0], action.scale[1]);
|
||
break;
|
||
case "showSprite":
|
||
tmp = this.storySprites.find(function (sprite) {
|
||
return sprite.imageId === action.key;
|
||
});
|
||
tmp.visible = true;
|
||
break;
|
||
case "hideSprite":
|
||
tmp = this.storySprites.find(function (sprite) {
|
||
return sprite.imageId === action.key;
|
||
});
|
||
tmp.visible = false;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
this.currentSpeaker = this.story.texts[this.storyProgress].speaker;
|
||
this.currentContent = this.story.texts[this.storyProgress].content;
|
||
this.storytextLabel.text = (this.currentSpeaker ? (this.currentSpeaker + ":") : ("")) + '\n' + this.currentContent;
|
||
}
|
||
else {
|
||
this.setGameState();
|
||
this.storyProgress = Infinity;
|
||
this.storytextLabel.destroy();
|
||
if (this.storySprites) {
|
||
this.storySprites.forEach((sprite) => {
|
||
sprite.visible = false;
|
||
sprite.destroy();
|
||
});
|
||
}
|
||
if (this.storyBGMs) {
|
||
this.storyBGMs.forEach((bgm) => {
|
||
this.emitter.fireEvent(GameEventType_1.GameEventType.STOP_SOUND, { key: bgm });
|
||
console.log("sound stopped:", bgm);
|
||
});
|
||
}
|
||
this.storyLayer.disable();
|
||
this.storyBGMs = undefined;
|
||
this.storySprites = undefined;
|
||
this.story = undefined;
|
||
this.storytextLabel = undefined;
|
||
// this.storyLayer = undefined;
|
||
if (this.levelEnded) {
|
||
this.emitter.fireEvent(sword_enums_1.Player_Events.GIVE_SPECIAL_BUFF, {});
|
||
}
|
||
}
|
||
}
|
||
// Cheat
|
||
enableCheat() {
|
||
if (this.pauseInput.text.toUpperCase() === "UUDDLRLRBABA") {
|
||
this.player._ai.godMode = true;
|
||
}
|
||
else {
|
||
let commands = this.pauseInput.text.split(' ');
|
||
console.log(commands);
|
||
if (commands.length === 3) {
|
||
if (commands[0].toUpperCase() === "SET") {
|
||
switch (commands[1].toUpperCase()) {
|
||
case "ATK":
|
||
this.player._ai.CURRENT_ATK = parseInt(commands[2]);
|
||
break;
|
||
case "HP":
|
||
this.player._ai.CURRENT_HP = parseInt(commands[2]);
|
||
break;
|
||
case "EXP":
|
||
this.player._ai.CURRENT_EXP = parseInt(commands[2]);
|
||
break;
|
||
case "SLD":
|
||
this.player._ai.CURRENT_SHIELD = parseInt(commands[2]);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
this.player._ai.godMode = false;
|
||
}
|
||
this.pauseInput.text = "";
|
||
}
|
||
}
|
||
exports.default = GameLevel;
|
||
// Labels for the UI
|
||
//TODO - lives here or in playercontroller
|
||
GameLevel.livesCount = 3;
|
||
GameLevel.gameTimer = 0;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Shapes/AABB":16,"../../Wolfie2D/DataTypes/Stack":19,"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Events/GameEventType":30,"../../Wolfie2D/Nodes/Graphics/GraphicTypes":42,"../../Wolfie2D/Nodes/UIElements/Label":53,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Registry/RegistryManager":65,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../AI/EnemyAI":106,"../AI/SlimeAI":113,"../AI/SnakeAI":114,"../GameSystems/BattleManager":115,"../GameSystems/InventoryManager":116,"../GameSystems/items/Weapon":118,"../Player/PlayerController":121,"../Tools/InputWrapper":140,"../sword_enums":144,"./GameOver":132,"./MainMenu":135}],132:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
||
const Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
const sword_enums_1 = require("../sword_enums");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
const MainMenu_1 = require("./MainMenu");
|
||
class GameOver extends Scene_1.default {
|
||
startScene() {
|
||
InputWrapper_1.default.setState(sword_enums_1.GameState.PAUSE);
|
||
InputWrapper_1.default.randomSeed = undefined;
|
||
const center = this.viewport.getCenter();
|
||
this.addUILayer("primary");
|
||
const gameOver = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "primary", { position: new Vec2_1.default(center.x, center.y), text: "YOU DIED" });
|
||
gameOver.textColor = Color_1.default.RED;
|
||
gameOver.fontSize = 100;
|
||
const hint = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "primary", { position: new Vec2_1.default(center.x, center.y + 100), text: "Click to go back to Main Menu" });
|
||
hint.textColor = Color_1.default.WHITE;
|
||
}
|
||
updateScene() {
|
||
if (InputWrapper_1.default.isLeftMouseJustPressed()) {
|
||
this.sceneManager.changeToScene(MainMenu_1.default);
|
||
}
|
||
}
|
||
}
|
||
exports.default = GameOver;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"../sword_enums":144,"./MainMenu":135}],133:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const RandomMapGenerator_1 = require("../Tools/RandomMapGenerator");
|
||
const GameLevel_1 = require("./GameLevel");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
class Greatwall extends GameLevel_1.default {
|
||
loadScene() {
|
||
super.loadScene();
|
||
this.rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/greatwall_template.json", InputWrapper_1.default.randomSeed);
|
||
this.map = this.rmg.getMap();
|
||
console.log(this.map);
|
||
this.load.tilemapFromObject("map", this.map);
|
||
//load enemies
|
||
//can load enemy sprite here
|
||
//sprites obtained from cse380 sprite wesbite
|
||
// this.load.spritesheet("black_pudding","shattered_sword_assets/spritesheets/black_pudding.json");
|
||
//load music here
|
||
}
|
||
}
|
||
exports.default = Greatwall;
|
||
|
||
},{"../Tools/InputWrapper":140,"../Tools/RandomMapGenerator":142,"./GameLevel":131}],134:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
const MainMenu_1 = require("./MainMenu");
|
||
const Tutorial_1 = require("./Tutorial");
|
||
const Porcelain_1 = require("./Porcelain");
|
||
const Greatwall_1 = require("./Greatwall");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
class Levels extends Scene_1.default {
|
||
// TODO
|
||
loadScene() { }
|
||
startScene() {
|
||
const center = this.viewport.getCenter();
|
||
// The main menu
|
||
this.primary = this.addUILayer("primary");
|
||
const seedHint = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "primary", { position: new Vec2_1.default(center.x, center.y - 200), text: "Enter seed or leave it blank to randomly generate one" });
|
||
seedHint.textColor = Color_1.default.WHITE;
|
||
this.seedInput = this.add.uiElement(UIElementTypes_1.UIElementType.TEXT_INPUT, "primary", { position: new Vec2_1.default(center.x, center.y - 150), text: "" });
|
||
this.seedInput.size.set(200, 50);
|
||
const start = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y - 100), text: "Start Game" });
|
||
start.size.set(200, 50);
|
||
start.borderWidth = 2;
|
||
start.borderColor = Color_1.default.WHITE;
|
||
start.backgroundColor = Color_1.default.TRANSPARENT;
|
||
start.onClickEventId = "start";
|
||
const porcelain = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y), text: "porcelain(Test)" });
|
||
porcelain.size.set(200, 50);
|
||
porcelain.borderWidth = 2;
|
||
porcelain.borderColor = Color_1.default.WHITE;
|
||
porcelain.backgroundColor = Color_1.default.TRANSPARENT;
|
||
porcelain.onClickEventId = "porcelain";
|
||
const greatwall = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 100), text: "greatwall(Test)" });
|
||
greatwall.size.set(200, 50);
|
||
greatwall.borderWidth = 2;
|
||
greatwall.borderColor = Color_1.default.WHITE;
|
||
greatwall.backgroundColor = Color_1.default.TRANSPARENT;
|
||
greatwall.onClickEventId = "greatwall";
|
||
const back = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 200), text: "Back" });
|
||
back.size.set(200, 50);
|
||
back.borderWidth = 2;
|
||
back.borderColor = Color_1.default.WHITE;
|
||
back.backgroundColor = Color_1.default.TRANSPARENT;
|
||
back.onClickEventId = "back";
|
||
this.receiver.subscribe("start");
|
||
this.receiver.subscribe("porcelain");
|
||
this.receiver.subscribe("greatwall");
|
||
this.receiver.subscribe("back");
|
||
}
|
||
updateScene() {
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
console.log(event);
|
||
if (event.type === "start") {
|
||
if (this.seedInput.text) {
|
||
InputWrapper_1.default.randomSeed = this.seedInput.text;
|
||
this.seedInput.text = "";
|
||
}
|
||
else {
|
||
InputWrapper_1.default.randomSeed = Math.floor(Math.random() * 10000000000).toString();
|
||
}
|
||
let sceneOptions = {
|
||
physics: {
|
||
groupNames: ["ground", "player", "enemies"],
|
||
collisions: [
|
||
[0, 1, 1],
|
||
[1, 0, 0],
|
||
[1, 0, 0]
|
||
]
|
||
}
|
||
};
|
||
this.sceneManager.changeToScene(Tutorial_1.default, {}, sceneOptions);
|
||
}
|
||
if (event.type === "porcelain") {
|
||
let sceneOptions = {
|
||
physics: {
|
||
groupNames: ["ground", "player", "enemies"],
|
||
collisions: [
|
||
[0, 1, 1],
|
||
[1, 0, 0],
|
||
[1, 0, 0]
|
||
]
|
||
}
|
||
};
|
||
this.sceneManager.changeToScene(Porcelain_1.default, {}, sceneOptions);
|
||
}
|
||
if (event.type === "greatwall") {
|
||
let sceneOptions = {
|
||
physics: {
|
||
groupNames: ["ground", "player", "enemies"],
|
||
collisions: [
|
||
[0, 1, 1],
|
||
[1, 0, 0],
|
||
[1, 0, 0]
|
||
]
|
||
}
|
||
};
|
||
this.sceneManager.changeToScene(Greatwall_1.default, {}, sceneOptions);
|
||
}
|
||
if (event.type === "back") {
|
||
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = Levels;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"./Greatwall":133,"./MainMenu":135,"./Porcelain":136,"./Tutorial":138}],135:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
const Levels_1 = require("./Levels");
|
||
const GameLevel_1 = require("./GameLevel");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
class MainMenu extends Scene_1.default {
|
||
// private rmg: RandomMapGenerator;
|
||
loadScene() {
|
||
// Load the menu song
|
||
//this.load.audio("menu", "shattered_sword_assets/music/menu.mp3");
|
||
}
|
||
//TODO
|
||
startScene() {
|
||
GameLevel_1.default.gameTimer = 0;
|
||
InputWrapper_1.default.randomSeed = undefined;
|
||
const center = this.viewport.getCenter();
|
||
// The main menu
|
||
this.mainMenu = this.addUILayer("mainMenu");
|
||
// Add map button, and give it an event to emit on press
|
||
const map = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y - 100), text: "Map" });
|
||
map.size.set(200, 50);
|
||
map.borderWidth = 2;
|
||
map.borderColor = Color_1.default.WHITE;
|
||
map.backgroundColor = Color_1.default.TRANSPARENT;
|
||
map.onClickEventId = "map";
|
||
// Add about button
|
||
const about = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y + 100), text: "About" });
|
||
about.size.set(200, 50);
|
||
about.borderWidth = 2;
|
||
about.borderColor = Color_1.default.WHITE;
|
||
about.backgroundColor = Color_1.default.TRANSPARENT;
|
||
about.onClickEventId = "about";
|
||
// Add about button
|
||
const form = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y + 200), text: "Google Form" });
|
||
form.size.set(200, 50);
|
||
form.borderWidth = 2;
|
||
form.borderColor = Color_1.default.WHITE;
|
||
form.backgroundColor = Color_1.default.TRANSPARENT;
|
||
form.onClick = function () {
|
||
window.open("https://forms.gle/Ku7RmUdNn7b9m5ch6");
|
||
};
|
||
// Add control button, and give it an event to emit on press
|
||
const control = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y), text: "Controls" });
|
||
control.size.set(200, 50);
|
||
control.borderWidth = 2;
|
||
control.borderColor = Color_1.default.WHITE;
|
||
control.backgroundColor = Color_1.default.TRANSPARENT;
|
||
control.onClickEventId = "control";
|
||
/* ########## ABOUT SCREEN ########## */
|
||
this.about = this.addUILayer("about");
|
||
this.about.setHidden(true);
|
||
const aboutHeader = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y - 250), text: "About" });
|
||
aboutHeader.textColor = Color_1.default.WHITE;
|
||
const text1 = "This game was created by Henry Chen, Kelly Peng, and Renge";
|
||
const text2 = "using the Wolfie2D game engine, a TypeScript game engine created by";
|
||
const text3 = "Joe Weaver and Richard McKenna.";
|
||
const line1 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y - 50), text: text1 });
|
||
const line2 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y), text: text2 });
|
||
const line3 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y + 50), text: text3 });
|
||
line1.textColor = Color_1.default.WHITE;
|
||
line2.textColor = Color_1.default.WHITE;
|
||
line3.textColor = Color_1.default.WHITE;
|
||
const aboutBack = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "about", { position: new Vec2_1.default(center.x, center.y + 250), text: "Back" });
|
||
aboutBack.size.set(200, 50);
|
||
aboutBack.borderWidth = 2;
|
||
aboutBack.borderColor = Color_1.default.WHITE;
|
||
aboutBack.backgroundColor = Color_1.default.TRANSPARENT;
|
||
aboutBack.onClickEventId = "menu";
|
||
// Subscribe to the button events
|
||
this.receiver.subscribe("map");
|
||
this.receiver.subscribe("about");
|
||
this.receiver.subscribe("menu");
|
||
this.receiver.subscribe("control");
|
||
//Control screen
|
||
this.control = this.addUILayer("control");
|
||
this.control.setHidden(true);
|
||
const header = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 250), text: "Controls" });
|
||
header.textColor = Color_1.default.WHITE;
|
||
const lc = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 150), text: "A/D - Move Left/Right" });
|
||
lc.textColor = Color_1.default.WHITE;
|
||
const rc = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 100), text: "W/S - Look Up/Down" });
|
||
rc.textColor = Color_1.default.WHITE;
|
||
const wasd = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 50), text: "J/Z/Enter - Confirm Attack" });
|
||
wasd.textColor = Color_1.default.WHITE;
|
||
const e = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y), text: "SPACE/X - Jump" });
|
||
e.textColor = Color_1.default.WHITE;
|
||
const q = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 50), text: "K/C - Dash" });
|
||
q.textColor = Color_1.default.WHITE;
|
||
const oneTwo = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 100), text: "L/V - Use Skill" });
|
||
oneTwo.textColor = Color_1.default.WHITE;
|
||
const zx = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 150), text: "I/B - open Backpack" });
|
||
zx.textColor = Color_1.default.WHITE;
|
||
const tb = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 200), text: "ESC - Pause" });
|
||
tb.textColor = Color_1.default.WHITE;
|
||
const back = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "control", { position: new Vec2_1.default(center.x, center.y + 300), text: "Back" });
|
||
back.size.set(200, 50);
|
||
back.borderWidth = 2;
|
||
back.borderColor = Color_1.default.WHITE;
|
||
back.backgroundColor = Color_1.default.TRANSPARENT;
|
||
back.onClickEventId = "menu";
|
||
}
|
||
unloadScene() {
|
||
// The scene is being destroyed, so we can stop playing the song
|
||
//this.emitter.fireEvent(GameEventType.STOP_SOUND, {key: "menu"});
|
||
}
|
||
updateScene() {
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
console.log(event);
|
||
if (event.type === "map") {
|
||
this.sceneManager.changeToScene(Levels_1.default, {});
|
||
}
|
||
if (event.type === "about") {
|
||
this.about.setHidden(false);
|
||
this.mainMenu.setHidden(true);
|
||
}
|
||
if (event.type === "menu") {
|
||
this.mainMenu.setHidden(false);
|
||
this.about.setHidden(true);
|
||
this.control.setHidden(true);
|
||
}
|
||
if (event.type === "control") {
|
||
this.mainMenu.setHidden(true);
|
||
this.control.setHidden(false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = MainMenu;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"./GameLevel":131,"./Levels":134}],136:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const RandomMapGenerator_1 = require("../Tools/RandomMapGenerator");
|
||
const GameLevel_1 = require("./GameLevel");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
class Porcelain extends GameLevel_1.default {
|
||
loadScene() {
|
||
super.loadScene();
|
||
this.rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/porcelain_template.json", InputWrapper_1.default.randomSeed);
|
||
this.map = this.rmg.getMap();
|
||
console.log(this.map);
|
||
this.load.tilemapFromObject("map", this.map);
|
||
// //load enemies
|
||
// this.load.spritesheet("Snake","shattered_sword_assets/spritesheets/Snake.json");
|
||
// this.load.spritesheet("Tiger","shattered_sword_assets/spritesheets/Tiger.json");
|
||
// //can load enemy sprite here
|
||
// //sprites obtained from cse380 sprite wesbite
|
||
// this.load.spritesheet("remus_werewolf","shattered_sword_assets/spritesheets/remus_werewolf.json");
|
||
// this.load.spritesheet("black_pudding","shattered_sword_assets/spritesheets/black_pudding.json");
|
||
//load music here
|
||
}
|
||
}
|
||
exports.default = Porcelain;
|
||
|
||
},{"../Tools/InputWrapper":140,"../Tools/RandomMapGenerator":142,"./GameLevel":131}],137:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
||
const ConfigManager_1 = require("../Tools/ConfigManager");
|
||
const SaveManager_1 = require("../Tools/SaveManager");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
||
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
const MainMenu_1 = require("./MainMenu");
|
||
class SplashScreen extends Scene_1.default {
|
||
loadScene() {
|
||
//load images
|
||
this.load.image("backgroundImage", "shattered_sword_assets/images/logo.png");
|
||
this.load.image("logo", "shattered_sword_assets/images/brown.png");
|
||
// Load the menu song
|
||
//this.load.audio("menu", "assets/music/menu.mp3");
|
||
}
|
||
//TODO
|
||
startScene() {
|
||
this.config = new ConfigManager_1.default();
|
||
this.save = new SaveManager_1.default();
|
||
// Scene has started, so start playing music
|
||
//this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "menu", loop: true, holdReference: true});
|
||
const center = this.viewport.getCenter();
|
||
let size = this.viewport.getHalfSize();
|
||
this.viewport.setFocus(size);
|
||
this.viewport.setZoomLevel(1);
|
||
let backgroundLayer = this.addUILayer("background");
|
||
backgroundLayer.setDepth(0);
|
||
let frontLayer = this.addUILayer("frontground");
|
||
frontLayer.setDepth(1);
|
||
this.clickLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "frontground", { position: new Vec2_1.default(size.x, size.y + 300), text: "\"Click anywhere to start\"" });
|
||
this.clickLabel.textColor = new Color_1.default(0, 0, 0, 1);
|
||
this.clickLabel.font = "Arial";
|
||
this.clickLabel.fontSize = 70;
|
||
let background = this.add.sprite("backgroundImage", "background");
|
||
background.position.set(size.x, size.y);
|
||
let logo = this.add.sprite("logo", "frontground");
|
||
logo.position.set(size.x, size.y + 20);
|
||
logo.scale.set(4, 4);
|
||
}
|
||
unloadScene() {
|
||
// The scene is being destroyed, so we can stop playing the song
|
||
//this.emitter.fireEvent(GameEventType.STOP_SOUND, {key: "menu"});
|
||
}
|
||
updateScene() {
|
||
if (InputWrapper_1.default.isLeftMouseJustPressed()) { //if left click
|
||
this.sceneManager.changeToScene(MainMenu_1.default, {}, {});
|
||
}
|
||
while (this.receiver.hasNextEvent()) {
|
||
let event = this.receiver.getNextEvent();
|
||
console.log(event);
|
||
if (InputWrapper_1.default.isLeftMouseJustPressed()) { //if left click
|
||
this.sceneManager.changeToScene(MainMenu_1.default, {}, {});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
exports.default = SplashScreen;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/ConfigManager":139,"../Tools/InputWrapper":140,"../Tools/SaveManager":143,"./MainMenu":135}],138:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
const RandomMapGenerator_1 = require("../Tools/RandomMapGenerator");
|
||
const GameLevel_1 = require("./GameLevel");
|
||
const SnakeAI_1 = require("../AI/SnakeAI");
|
||
const Porcelain_1 = require("./Porcelain");
|
||
const InputWrapper_1 = require("../Tools/InputWrapper");
|
||
class Tutorial extends GameLevel_1.default {
|
||
loadScene() {
|
||
super.loadScene();
|
||
this.rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/forest_template.json", InputWrapper_1.default.randomSeed);
|
||
this.map = this.rmg.getMap();
|
||
this.load.tilemapFromObject("map", this.map);
|
||
//load enemies
|
||
this.load.spritesheet("Snake", "shattered_sword_assets/spritesheets/Snake.json");
|
||
this.load.spritesheet("Tiger", "shattered_sword_assets/spritesheets/Tiger.json");
|
||
//can load enemy sprite here
|
||
//sprites obtained from cse380 sprite wesbite
|
||
this.load.spritesheet("remus_werewolf", "shattered_sword_assets/spritesheets/remus_werewolf.json");
|
||
this.load.spritesheet("black_pudding", "shattered_sword_assets/spritesheets/black_pudding.json");
|
||
//load music here
|
||
}
|
||
updateScene(deltaT) {
|
||
super.updateScene(deltaT);
|
||
//spawn snake()
|
||
if (Math.random() < .0001 && this.gameStarted) {
|
||
console.log("RANDOM SNAKE!");
|
||
this.addEnemy("Snake", this.player.position.clone().add(new Vec2_1.default(0, -320)), SnakeAI_1.default, {
|
||
player: this.player,
|
||
health: 50,
|
||
tilemap: "Main",
|
||
size: new Vec2_1.default(14, 10),
|
||
offset: new Vec2_1.default(0, 22),
|
||
exp: 50,
|
||
});
|
||
}
|
||
}
|
||
goToNextLevel() {
|
||
this.viewport.setZoomLevel(1);
|
||
this.sceneManager.changeToScene(Porcelain_1.default);
|
||
}
|
||
playStartStory() {
|
||
if (!this.touchedStartCheckPoint) {
|
||
this.touchedStartCheckPoint = true;
|
||
this.storyLoader("shattered_sword_assets/jsons/level1story.json");
|
||
this.startTimer();
|
||
}
|
||
}
|
||
}
|
||
exports.default = Tutorial;
|
||
|
||
},{"../../Wolfie2D/DataTypes/Vec2":24,"../AI/SnakeAI":114,"../Tools/InputWrapper":140,"../Tools/RandomMapGenerator":142,"./GameLevel":131,"./Porcelain":136}],139:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const LocalStorageDB_1 = require("./LocalStorageDB");
|
||
class ConfigManager {
|
||
constructor() {
|
||
this.db = new LocalStorageDB_1.default("config");
|
||
this.loadConfig();
|
||
if (!ConfigManager.config)
|
||
this.initConfig();
|
||
}
|
||
getVolume() {
|
||
return ConfigManager.config.volume;
|
||
}
|
||
setVolume(volume) {
|
||
ConfigManager.config.volume = volume;
|
||
this.saveConfig();
|
||
}
|
||
// TODOs
|
||
// add more functions if needed
|
||
resetConfig(callback) {
|
||
this.initConfig();
|
||
callback(ConfigManager.config);
|
||
}
|
||
loadConfig() {
|
||
ConfigManager.config = this.db.loadJSON();
|
||
}
|
||
saveConfig() {
|
||
this.db.saveJSON(ConfigManager.config);
|
||
}
|
||
initConfig() {
|
||
this.db.readJSON("shattered_sword_assets/jsons/sampleconfig.json", (config) => {
|
||
if (!config)
|
||
throw new Error("Fail to load config file");
|
||
ConfigManager.config = config;
|
||
console.log("Initializing Local Storage(config): ", ConfigManager.config);
|
||
this.saveConfig();
|
||
});
|
||
}
|
||
}
|
||
exports.default = ConfigManager;
|
||
|
||
},{"./LocalStorageDB":141}],140:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Input_1 = require("../../Wolfie2D/Input/Input");
|
||
const sword_enums_1 = require("../sword_enums");
|
||
class InputWrapper {
|
||
static isUpPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isPressed("up")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isDownPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isPressed("down")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isLeftPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isPressed("left")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isRightPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isPressed("right")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isJumpJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("jump")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Returns whether or not the attack key is currently pressed
|
||
* @returns True if the attack key is pressed, false otherwise
|
||
*/
|
||
static isAttackJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("attack")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isDashJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("dash")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isSkillJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("skill")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isInventoryJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("inventory")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isBuff1JustPresed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.BUFF) {
|
||
return false;
|
||
}
|
||
return Input_1.default.isJustPressed("buff1");
|
||
}
|
||
static isBuff2JustPresed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.BUFF) {
|
||
return false;
|
||
}
|
||
return Input_1.default.isJustPressed("buff2");
|
||
}
|
||
static isBuff3JustPresed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.BUFF) {
|
||
return false;
|
||
}
|
||
return Input_1.default.isJustPressed("buff3");
|
||
}
|
||
static isPauseJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.GAMING && InputWrapper.gameState != sword_enums_1.GameState.PAUSE) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("pause")) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isNextJustPressed() {
|
||
if (InputWrapper.gameState != sword_enums_1.GameState.STORY) {
|
||
return false;
|
||
}
|
||
if (Input_1.default.isJustPressed("attack") || Input_1.default.isMouseJustPressed()) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
static isLeftMouseJustPressed() {
|
||
return Input_1.default.isMouseJustPressed(0);
|
||
}
|
||
static disableInput() {
|
||
Input_1.default.disableInput();
|
||
}
|
||
static enableInput() {
|
||
Input_1.default.enableInput();
|
||
}
|
||
// DO NOT call this function directly
|
||
static setState(gameState) {
|
||
InputWrapper.gameState = gameState;
|
||
}
|
||
static getState() {
|
||
return InputWrapper.gameState;
|
||
}
|
||
}
|
||
exports.default = InputWrapper;
|
||
InputWrapper.gameState = sword_enums_1.GameState.GAMING;
|
||
|
||
},{"../../Wolfie2D/Input/Input":32,"../sword_enums":144}],141:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
class LocalStorageDB {
|
||
constructor(key) {
|
||
this.key = key;
|
||
}
|
||
/**
|
||
* Read a json file from a path
|
||
* @param JSONFilePath The path to the JSON file
|
||
* @param callback Function to run after getting the JSON
|
||
*/
|
||
readJSON(JSONFilePath, callback) {
|
||
let xobj = new XMLHttpRequest();
|
||
xobj.overrideMimeType("application/json");
|
||
xobj.open('GET', JSONFilePath, false);
|
||
// xobj.onreadystatechange = function () {
|
||
// if ((xobj.readyState == 4) && (xobj.status == 200)) {
|
||
// callback(JSON.parse(xobj.responseText));
|
||
// }
|
||
// };
|
||
xobj.send(null);
|
||
callback(JSON.parse(xobj.responseText));
|
||
}
|
||
loadJSON() {
|
||
return JSON.parse(localStorage.getItem(this.key));
|
||
}
|
||
saveJSON(value) {
|
||
localStorage.setItem(this.key, JSON.stringify(value));
|
||
}
|
||
}
|
||
exports.default = LocalStorageDB;
|
||
|
||
},{}],142:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.Enemy = void 0;
|
||
const TiledData_1 = require("../../Wolfie2D/DataTypes/Tilesets/TiledData");
|
||
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
||
class RandomMapGenerator {
|
||
constructor(JSONFilePath, seed) {
|
||
let xhr = new XMLHttpRequest();
|
||
xhr.overrideMimeType("application/json");
|
||
xhr.open('GET', JSONFilePath, false);
|
||
xhr.send(null);
|
||
this.template = JSON.parse(xhr.responseText);
|
||
this.roomWithLeftEntrance = new Array();
|
||
this.roomWithRightEntrance = new Array();
|
||
this.roomWithUpEntrance = new Array();
|
||
this.roomWithDownEntrance = new Array();
|
||
this.minX = this.minY = this.maxX = this.maxY =
|
||
this.roomWithLeftEntranceWeight = this.roomWithRightEntranceWeight =
|
||
this.roomWithUpEntranceWeight = this.roomWithDownEntranceWeight = 0;
|
||
this.map = new TiledData_1.TiledTilemapData();
|
||
this.rooms = new Array();
|
||
this.enemies = new Array();
|
||
this.player = new Vec2_1.default();
|
||
this.startCheckPoint = [0, 0, 0, 0];
|
||
this.endCheckPoint = [0, 0, 0, 0];
|
||
let gen = require('random-seed');
|
||
this.gen = new gen(seed);
|
||
this.hasExit = false;
|
||
this.minRoom = this.template.minroom;
|
||
this.roomPlaced = 0;
|
||
this.exitFacing = this.getEntranceFacing(this.template.exit.entrances[0], this.template.exit.width);
|
||
for (let room of this.template.rooms) {
|
||
let left = false, right = false, up = false, down = false;
|
||
for (let entrance of room.entrances) {
|
||
let facing = this.getEntranceFacing(entrance, room.width);
|
||
switch (facing) {
|
||
case Facing.LEFT:
|
||
left = true;
|
||
break;
|
||
case Facing.RIGHT:
|
||
right = true;
|
||
break;
|
||
case Facing.UP:
|
||
up = true;
|
||
break;
|
||
case Facing.DOWN:
|
||
down = true;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
if (left) {
|
||
this.roomWithLeftEntrance.push(room);
|
||
this.roomWithLeftEntranceWeight += room.weight;
|
||
}
|
||
if (right) {
|
||
this.roomWithRightEntrance.push(room);
|
||
this.roomWithRightEntranceWeight += room.weight;
|
||
}
|
||
if (up) {
|
||
this.roomWithUpEntrance.push(room);
|
||
this.roomWithUpEntranceWeight += room.weight;
|
||
}
|
||
if (down) {
|
||
this.roomWithDownEntrance.push(room);
|
||
this.roomWithDownEntranceWeight += room.weight;
|
||
}
|
||
}
|
||
}
|
||
getMap() {
|
||
let room = this.copyRoom(this.template.entrance, 0, 0);
|
||
let facing = this.getEntranceFacing(this.template.entrance.entrances[0], this.template.entrance.width);
|
||
let position = new Vec2_1.default(this.template.entrance.entrances[0].x, this.template.entrance.entrances[0].y);
|
||
// this.removeEntrance(room, this.template.entrance.entrances[0], facing);
|
||
this.rooms.push(room);
|
||
this.putNextRoom(position, this.getOppositeFacing(facing));
|
||
if (!this.hasExit)
|
||
throw new Error("Fail to generate a map with exit!");
|
||
this.fillData();
|
||
console.log("Generated map:", this.map);
|
||
return this.map;
|
||
}
|
||
getPlayer() {
|
||
return new Vec2_1.default(this.player.x - this.minX, this.player.y - this.minY);
|
||
}
|
||
getStartCheckPoint() {
|
||
return [this.startCheckPoint[0] - this.minX, this.startCheckPoint[1] - this.minY, this.startCheckPoint[2], this.startCheckPoint[3]];
|
||
}
|
||
getEndCheckPoint() {
|
||
return [this.endCheckPoint[0] - this.minX, this.endCheckPoint[1] - this.minY, this.endCheckPoint[2], this.endCheckPoint[3]];
|
||
}
|
||
getEnemies() {
|
||
return this.enemies;
|
||
}
|
||
putNextRoom(position, facing) {
|
||
switch (facing) {
|
||
case Facing.LEFT:
|
||
position.x += 1;
|
||
break;
|
||
case Facing.RIGHT:
|
||
position.x -= 1;
|
||
break;
|
||
case Facing.UP:
|
||
position.y += 1;
|
||
break;
|
||
case Facing.DOWN:
|
||
position.y -= 1;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (this.roomPlaced >= this.minRoom && facing == this.exitFacing && !this.hasExit) {
|
||
this.putExitRoom(position);
|
||
return true;
|
||
}
|
||
let nextRoom = this.getRandomRoom(facing);
|
||
let nextPosition = undefined;
|
||
let thisEntrance = undefined;
|
||
for (let entrance of nextRoom.entrances) {
|
||
if (this.getEntranceFacing(entrance, nextRoom.width) == facing) {
|
||
let tmpPosition = new Vec2_1.default(position.x - entrance.x, position.y - entrance.y);
|
||
if (this.isValidRoom(tmpPosition, new Vec2_1.default(tmpPosition.x + nextRoom.width - 1, tmpPosition.y + nextRoom.height - 1))) {
|
||
thisEntrance = entrance;
|
||
nextPosition = tmpPosition;
|
||
}
|
||
}
|
||
}
|
||
if (!thisEntrance) {
|
||
if (!this.hasExit) {
|
||
throw new Error("Wrong order in map template" + facing);
|
||
}
|
||
return false;
|
||
}
|
||
let room = this.copyRoom(nextRoom, nextPosition.x, nextPosition.y);
|
||
this.removeEntrance(room, thisEntrance, facing);
|
||
this.rooms.push(room);
|
||
this.roomPlaced += 1;
|
||
if (this.hasExit && this.gen.random() <= 0.3) {
|
||
return true;
|
||
}
|
||
for (let entrance of nextRoom.entrances) {
|
||
if (entrance != thisEntrance) {
|
||
let facing = this.getEntranceFacing(entrance, nextRoom.width);
|
||
let position = new Vec2_1.default(nextPosition.x + entrance.x, nextPosition.y + entrance.y);
|
||
if (this.putNextRoom(position, this.getOppositeFacing(facing))) {
|
||
this.removeEntrance(room, entrance, facing);
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
putExitRoom(position) {
|
||
position = new Vec2_1.default(position.x - this.template.exit.entrances[0].x, position.y - this.template.exit.entrances[0].y);
|
||
if (!this.isValidRoom(position, new Vec2_1.default(position.x + this.template.exit.width - 1, position.y + this.template.exit.height - 1))) {
|
||
throw new Error("Cannot put exit room!!! Position is invalid!!! Please check order of entrances in map template.");
|
||
}
|
||
let room = this.copyRoom(this.template.exit, position.x, position.y);
|
||
this.rooms.push(room);
|
||
this.hasExit = true;
|
||
}
|
||
removeEntrance(room, entrance, facing) {
|
||
let width = room.bottomRight.x - room.topLeft.x + 1;
|
||
if (facing == Facing.LEFT || facing == Facing.RIGHT) {
|
||
for (let index = 0; index < entrance.width; index++)
|
||
room.topLayer[(entrance.y + index) * width + entrance.x] = 0;
|
||
if (entrance.y > 0)
|
||
room.topLayer[(entrance.y - 1) * width + entrance.x] = entrance.alt_tile[0];
|
||
if (entrance.y + entrance.width <= (room.bottomRight.y - room.topLeft.y))
|
||
room.topLayer[(entrance.y + entrance.width) * width + entrance.x] = entrance.alt_tile[1];
|
||
}
|
||
else {
|
||
for (let index = 0; index < entrance.width; index++)
|
||
room.topLayer[(entrance.y) * width + entrance.x + index] = 0;
|
||
if (entrance.x > 0)
|
||
room.topLayer[(entrance.y) * width + entrance.x - 1] = entrance.alt_tile[0];
|
||
if (entrance.x + entrance.width <= (room.bottomRight.x - room.topLeft.x))
|
||
room.topLayer[(entrance.y) * width + entrance.x + entrance.width] = entrance.alt_tile[1];
|
||
}
|
||
}
|
||
fillData() {
|
||
let width = this.maxX - this.minX + 1;
|
||
let height = this.maxY - this.minY + 1;
|
||
this.map.layers = new Array(2);
|
||
this.map.layers[0] = new TiledData_1.TiledLayerData;
|
||
this.map.layers[1] = new TiledData_1.TiledLayerData;
|
||
this.map.width = this.map.layers[0].width = this.map.layers[1].width = width;
|
||
this.map.height = this.map.layers[0].height = this.map.layers[1].height = height;
|
||
this.map.tileheight = this.template.tileheight;
|
||
this.map.tilewidth = this.template.tilewidth;
|
||
this.map.orientation = "orthogonal";
|
||
this.map.layers[0].x = this.map.layers[0].y = this.map.layers[1].x = this.map.layers[1].y = 0;
|
||
this.map.layers[0].opacity = this.map.layers[1].opacity = 1;
|
||
this.map.layers[0].visible = this.map.layers[1].visible = true;
|
||
this.map.layers[0].type = this.map.layers[1].type = "tilelayer";
|
||
this.map.layers[0].name = "Floor";
|
||
this.map.layers[1].name = "Wall";
|
||
this.map.layers[0].properties = [{
|
||
name: "Collidable",
|
||
type: "bool",
|
||
value: false
|
||
}];
|
||
this.map.layers[1].properties = [{
|
||
name: "Collidable",
|
||
type: "bool",
|
||
value: true
|
||
}];
|
||
this.map.tilesets = [{
|
||
columns: this.template.columns,
|
||
tilewidth: this.template.tilewidth,
|
||
tileheight: this.template.tileheight,
|
||
tilecount: this.template.tilecount,
|
||
firstgid: this.template.firstgid,
|
||
imageheight: this.template.imageheight,
|
||
imagewidth: this.template.imagewidth,
|
||
margin: this.template.margin,
|
||
spacing: this.template.spacing,
|
||
name: this.template.name,
|
||
image: this.template.image
|
||
}];
|
||
this.map.layers[0].data = new Array(width * height).fill(this.template.background);
|
||
this.map.layers[1].data = new Array(width * height);
|
||
for (let room of this.rooms) {
|
||
let roomWidth = room.bottomRight.x - room.topLeft.x + 1;
|
||
let roomHeight = room.bottomRight.y - room.topLeft.y + 1;
|
||
room.topLeft.x -= this.minX;
|
||
room.topLeft.y -= this.minY;
|
||
for (let i = 0; i < roomHeight; i++)
|
||
for (let j = 0; j < roomWidth; j++) {
|
||
this.map.layers[0].data[(room.topLeft.y + i) * width + room.topLeft.x + j] = room.bottomLayer[i * roomWidth + j];
|
||
this.map.layers[1].data[(room.topLeft.y + i) * width + room.topLeft.x + j] = room.topLayer[i * roomWidth + j];
|
||
}
|
||
if (room.enemies)
|
||
for (let enemy of room.enemies) {
|
||
enemy.position.x += room.topLeft.x;
|
||
enemy.position.y += room.topLeft.y;
|
||
this.enemies.push(enemy);
|
||
}
|
||
}
|
||
}
|
||
isValidRoom(topLeft, bottomRight) {
|
||
for (let room of this.rooms) {
|
||
if (room.topLeft.x <= bottomRight.x &&
|
||
room.bottomRight.x >= topLeft.x &&
|
||
room.topLeft.y <= bottomRight.y &&
|
||
room.bottomRight.y >= topLeft.y) {
|
||
console.warn("Found an invalid room! TopLeft:", topLeft.toString(), "BottomRight:", bottomRight.toString());
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
getEntranceFacing(entrance, width) {
|
||
if (entrance.x === 0)
|
||
return Facing.LEFT;
|
||
else if (entrance.x === width - 1)
|
||
return Facing.RIGHT;
|
||
else if (entrance.y === 0)
|
||
return Facing.UP;
|
||
return Facing.DOWN;
|
||
}
|
||
getOppositeFacing(facing) {
|
||
switch (facing) {
|
||
case Facing.LEFT:
|
||
return Facing.RIGHT;
|
||
case Facing.RIGHT:
|
||
return Facing.LEFT;
|
||
case Facing.UP:
|
||
return Facing.DOWN;
|
||
case Facing.DOWN:
|
||
return Facing.UP;
|
||
}
|
||
}
|
||
getRandomRoom(facing) {
|
||
let array = this.getRoomArray(facing), weight = this.getRoomWeight(facing);
|
||
let value = this.gen(weight);
|
||
if (value >= weight)
|
||
throw new Error("Random number " + value + " is larger than total weight " + weight);
|
||
for (let room of array) {
|
||
if (value < room.weight)
|
||
return room;
|
||
value -= room.weight;
|
||
}
|
||
throw new Error("Cannot find Room! \nValue: " + value + "\nRooms: " + JSON.stringify(array));
|
||
}
|
||
getRoomArray(facing) {
|
||
switch (facing) {
|
||
case Facing.LEFT:
|
||
return this.roomWithLeftEntrance;
|
||
case Facing.RIGHT:
|
||
return this.roomWithRightEntrance;
|
||
case Facing.UP:
|
||
return this.roomWithUpEntrance;
|
||
case Facing.DOWN:
|
||
return this.roomWithDownEntrance;
|
||
}
|
||
}
|
||
getRoomWeight(facing) {
|
||
switch (facing) {
|
||
case Facing.LEFT:
|
||
return this.roomWithLeftEntranceWeight;
|
||
case Facing.RIGHT:
|
||
return this.roomWithRightEntranceWeight;
|
||
case Facing.UP:
|
||
return this.roomWithUpEntranceWeight;
|
||
case Facing.DOWN:
|
||
return this.roomWithDownEntranceWeight;
|
||
}
|
||
}
|
||
copyRoom(old, posX, posY) {
|
||
let room = new Room();
|
||
room.topLeft = new Vec2_1.default(posX, posY);
|
||
room.bottomRight = new Vec2_1.default(posX + old.width - 1, posY + old.height - 1);
|
||
room.topLayer = [...old.topLayer];
|
||
room.bottomLayer = [...old.bottomLayer];
|
||
room.enemies = new Array();
|
||
if (old.sprites) {
|
||
for (let sprite of old.sprites) {
|
||
if (sprite.type === 'player') {
|
||
this.player.x = sprite.x + posX;
|
||
this.player.y = sprite.y + posY;
|
||
}
|
||
else {
|
||
if (this.gen.random() <= sprite.possibility) {
|
||
let tmp = new Enemy();
|
||
tmp.type = sprite.type;
|
||
tmp.position = new Vec2_1.default(sprite.x, sprite.y);
|
||
room.enemies.push(tmp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (old.startCheckPoint) {
|
||
this.startCheckPoint = [...old.startCheckPoint];
|
||
this.startCheckPoint[0] += posX;
|
||
this.startCheckPoint[1] += posY;
|
||
}
|
||
if (old.endCheckPoint) {
|
||
this.endCheckPoint = [...old.endCheckPoint];
|
||
this.endCheckPoint[0] += posX;
|
||
this.endCheckPoint[1] += posY;
|
||
}
|
||
if (posX < this.minX)
|
||
this.minX = posX;
|
||
if (posY < this.minY)
|
||
this.minY = posY;
|
||
if (posX + old.width - 1 > this.maxX)
|
||
this.maxX = posX + old.width - 1;
|
||
if (posY + old.height - 1 > this.maxY)
|
||
this.maxY = posY + old.height - 1;
|
||
return room;
|
||
}
|
||
}
|
||
exports.default = RandomMapGenerator;
|
||
class Room {
|
||
}
|
||
class Enemy {
|
||
}
|
||
exports.Enemy = Enemy;
|
||
var Facing;
|
||
(function (Facing) {
|
||
Facing["LEFT"] = "left";
|
||
Facing["RIGHT"] = "right";
|
||
Facing["UP"] = "up";
|
||
Facing["DOWN"] = "down";
|
||
})(Facing || (Facing = {}));
|
||
|
||
},{"../../Wolfie2D/DataTypes/Tilesets/TiledData":22,"../../Wolfie2D/DataTypes/Vec2":24,"random-seed":2}],143:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const LocalStorageDB_1 = require("./LocalStorageDB");
|
||
class SaveManager {
|
||
constructor() {
|
||
this.db = new LocalStorageDB_1.default("save");
|
||
this.loadSave();
|
||
if (!SaveManager.save)
|
||
this.initSave();
|
||
}
|
||
getLevel() {
|
||
return SaveManager.save.level;
|
||
}
|
||
setLevel(level) {
|
||
SaveManager.save.level = level;
|
||
this.saveSave();
|
||
}
|
||
getName() {
|
||
return SaveManager.save.name;
|
||
}
|
||
setName(name) {
|
||
SaveManager.save.name = name;
|
||
this.saveSave();
|
||
}
|
||
// TODOs
|
||
// add more functions if needed
|
||
resetSave(callback) {
|
||
this.initSave();
|
||
callback(SaveManager.save);
|
||
}
|
||
loadSave() {
|
||
SaveManager.save = this.db.loadJSON();
|
||
}
|
||
saveSave() {
|
||
this.db.saveJSON(SaveManager.save);
|
||
}
|
||
initSave() {
|
||
this.db.readJSON("shattered_sword_assets/jsons/samplesave.json", (save) => {
|
||
if (!save)
|
||
throw new Error("Fail to load save file");
|
||
SaveManager.save = save;
|
||
console.log("Initializing Local Storage(save): ", SaveManager.save);
|
||
this.saveSave();
|
||
});
|
||
}
|
||
}
|
||
exports.default = SaveManager;
|
||
|
||
},{"./LocalStorageDB":141}],144:[function(require,module,exports){
|
||
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.GameState = exports.Statuses = exports.Damage_Type = exports.Player_Events = void 0;
|
||
var Player_Events;
|
||
(function (Player_Events) {
|
||
Player_Events["PLAYER_MOVE"] = "PlayerMove";
|
||
Player_Events["PLAYER_JUMP"] = "PlayerJump";
|
||
Player_Events["PLAYER_ATTACK"] = "PlayerAttack";
|
||
Player_Events["PLAYER_DASH"] = "PlayerDash";
|
||
Player_Events["PLAYER_HEAL"] = "PlayerHeal";
|
||
Player_Events["LEVEL_START"] = "LevelStart";
|
||
Player_Events["LEVEL_END"] = "LevelEnd";
|
||
Player_Events["PLAYER_KILLED"] = "PlayerKilled";
|
||
Player_Events["ENEMY_KILLED"] = "EnemyKilled";
|
||
Player_Events["PLAYER_HIT_ENEMY"] = "PlayerHitEnemy";
|
||
Player_Events["BOSS_KILLED"] = "BossKilled";
|
||
Player_Events["GIVE_REGULAR_BUFF"] = "GiveRegularBuff";
|
||
Player_Events["GIVE_SPECIAL_BUFF"] = "GiveSpecialBuff";
|
||
Player_Events["PLAYER_COLLIDE"] = "PlayerCollide";
|
||
})(Player_Events = exports.Player_Events || (exports.Player_Events = {}));
|
||
var Damage_Type;
|
||
(function (Damage_Type) {
|
||
Damage_Type["NORMAL_DAMAGE"] = "NormalDamage";
|
||
Damage_Type["ENVIRONMENT_DAMAGE"] = "EnvironmentDamage";
|
||
Damage_Type["DOT_DAMAGE"] = "DOTDamage";
|
||
})(Damage_Type = exports.Damage_Type || (exports.Damage_Type = {}));
|
||
var Statuses;
|
||
(function (Statuses) {
|
||
Statuses["IN_RANGE"] = "IN_RANGE";
|
||
Statuses["LOW_HEALTH"] = "LOW_HEALTH";
|
||
Statuses["CAN_RETREAT"] = "CAN_RETREAT";
|
||
Statuses["REACHED_GOAL"] = "GOAL";
|
||
Statuses["CAN_BERSERK"] = "CAN_BERSERK";
|
||
})(Statuses = exports.Statuses || (exports.Statuses = {}));
|
||
var GameState;
|
||
(function (GameState) {
|
||
GameState["GAMING"] = "gaming";
|
||
GameState["STORY"] = "story";
|
||
GameState["BUFF"] = "buff";
|
||
GameState["PAUSE"] = "pause";
|
||
})(GameState = exports.GameState || (exports.GameState = {}));
|
||
|
||
},{}]},{},[105])
|
||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvanNvbi1zdHJpbmdpZnktc2FmZS9zdHJpbmdpZnkuanMiLCJub2RlX21vZHVsZXMvcmFuZG9tLXNlZWQvaW5kZXguanMiLCJzcmMvV29sZmllMkQvQUkvQUlNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL0FJL1N0YXRlTWFjaGluZUFJLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9GdW5jdGlvbnMvTnVsbEZ1bmMudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL0dyYXBocy9FZGdlTm9kZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9HcmFwaHMvUG9zaXRpb25HcmFwaC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvSW50ZXJmYWNlcy9SZWdpb24udHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL01hcC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvTWF0NHg0LnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9QaHlzaWNzL0FyZWFDb2xsaXNpb24udHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1BoeXNpY3MvSGl0LnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9RdWV1ZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvUmVuZGVyaW5nL1dlYkdMUHJvZ3JhbVR5cGUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQ2lyY2xlLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvU2hhcGUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1N0YWNrLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvU3RhdGUvU3RhdGVNYWNoaW5lLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGEudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVzZXQudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1ZlYzIudHMiLCJzcmMvV29sZmllMkQvRGVidWcvRGVidWcudHMiLCJzcmMvV29sZmllMkQvRGVidWcvU3RhdHMudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0VtaXR0ZXIudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0V2ZW50UXVldWUudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudC50cyIsInNyYy9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZS50cyIsInNyYy9Xb2xmaWUyRC9FdmVudHMvUmVjZWl2ZXIudHMiLCJzcmMvV29sZmllMkQvSW5wdXQvSW5wdXQudHMiLCJzcmMvV29sZmllMkQvSW5wdXQvSW5wdXRIYW5kbGVyLnRzIiwic3JjL1dvbGZpZTJEL0xvb3AvRW52aXJvbm1lbnRJbml0aWFsaXplci50cyIsInNyYy9Xb2xmaWUyRC9Mb29wL0ZpeGVkVXBkYXRlR2FtZUxvb3AudHMiLCJzcmMvV29sZmllMkQvTG9vcC9HYW1lLnRzIiwic3JjL1dvbGZpZTJEL0xvb3AvR2FtZUxvb3AudHMiLCJzcmMvV29sZmllMkQvTG9vcC9HYW1lT3B0aW9ucy50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9DYW52YXNOb2RlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWMudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvR3JhcGhpY1R5cGVzLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL0xpbmUudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUGFydGljbGUudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUG9pbnQudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUmVjdC50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1RpbGVtYXAudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVGlsZW1hcHMvT3J0aG9nb25hbFRpbGVtYXAudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50LnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvTGFiZWwudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9TbGlkZXIudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9UZXh0SW5wdXQudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9VSUVsZW1lbnRUeXBlcy50cyIsInNyYy9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZpZ2F0aW9uTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZpZ2F0aW9uUGF0aC50cyIsInNyYy9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZtZXNoLnRzIiwic3JjL1dvbGZpZTJEL1BoeXNpY3MvQmFzaWNQaHlzaWNzTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9QaHlzaWNzL1BoeXNpY3NNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1BsYXliYWNrL1JlY29yZGVyLnRzIiwic3JjL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvUmVnaXN0cnkudHMiLCJzcmMvV29sZmllMkQvUmVnaXN0cnkvUmVnaXN0cmllcy9TaGFkZXJSZWdpc3RyeS50cyIsInNyYy9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0FuaW1hdGlvbnMvQW5pbWF0aW9uTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQW5pbWF0aW9ucy9BbmltYXRpb25UeXBlcy50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQW5pbWF0aW9ucy9QYXJ0aWNsZVN5c3RlbU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0FuaW1hdGlvbnMvVHdlZW5Db250cm9sbGVyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9BbmltYXRpb25zL1R3ZWVuTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQ2FudmFzUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmluZy9HcmFwaGljUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmluZy9UaWxlbWFwUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmluZy9VSUVsZW1lbnRSZW5kZXJlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvUmVuZGVyaW5nTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvTGFiZWxTaGFkZXJUeXBlLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9Qb2ludFNoYWRlclR5cGUudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL1F1YWRTaGFkZXJUeXBlLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9SZWN0U2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvU3ByaXRlU2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0ZhY3Rvcmllcy9DYW52YXNOb2RlRmFjdG9yeS50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9GYWN0b3JpZXMvRmFjdG9yeU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvU2NlbmUvRmFjdG9yaWVzL1RpbGVtYXBGYWN0b3J5LnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0xheWVyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0xheWVycy9QYXJhbGxheExheWVyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0xheWVycy9VSUxheWVyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL1NjZW5lLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL1NjZW5lTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9TY2VuZU9wdGlvbnMudHMiLCJzcmMvV29sZmllMkQvU2NlbmVHcmFwaC9TY2VuZUdyYXBoLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lR3JhcGgvU2NlbmVHcmFwaEFycmF5LnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lR3JhcGgvVmlld3BvcnQudHMiLCJzcmMvV29sZmllMkQvU291bmQvQXVkaW9NYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1RpbWluZy9UaW1lci50cyIsInNyYy9Xb2xmaWUyRC9UaW1pbmcvVGltZXJNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL0NvbG9yLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL0Vhc2VGdW5jdGlvbnMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvR3JhcGhVdGlscy50cyIsInNyYy9Xb2xmaWUyRC9VdGlscy9NYXRoVXRpbHMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvUmVuZGVyaW5nVXRpbHMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvU3RyaW5nVXRpbHMudHMiLCJzcmMvbWFpbi50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlBSS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvQWxlcnQudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL0VuZW15U3RhdGVzL0F0dGFjay50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvRW5lbXlTdGF0ZS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvUGF0cm9sLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9BSS9FbmVteVN0YXRlcy9TbGltZUF0dGFjay50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvU25ha2VBdHRhY2sudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL1NsaW1lQUkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL1NuYWtlQUkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL0JhdHRsZU1hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL0ludmVudG9yeU1hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL2l0ZW1zL0l0ZW0udHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvbi50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvU2xpY2UudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblR5cGVzL1dlYXBvblR5cGUudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJDb250cm9sbGVyLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL0ZhbGwudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJTdGF0ZXMvSWRsZS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUGxheWVyL1BsYXllclN0YXRlcy9JbkFpci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUGxheWVyL1BsYXllclN0YXRlcy9KdW1wLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL09uR3JvdW5kLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL1BsYXllclN0YXRlLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL1dhbGsudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1JlZ2lzdHJ5L1dlYXBvblJlZ2lzdHJ5LnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9SZWdpc3RyeS9XZWFwb25UeXBlUmVnaXN0cnkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9HYW1lTGV2ZWwudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9HYW1lT3Zlci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL0dyZWF0d2FsbC50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL0xldmVscy50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL01haW5NZW51LnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvUG9yY2VsYWluLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvU3BsYXNoU2NyZWVuLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvVHV0b3JpYWwudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1Rvb2xzL0NvbmZpZ01hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1Rvb2xzL0lucHV0V3JhcHBlci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvVG9vbHMvTG9jYWxTdG9yYWdlREIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1Rvb2xzL1JhbmRvbU1hcEdlbmVyYXRvci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvVG9vbHMvU2F2ZU1hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL3N3b3JkX2VudW1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN4UUEsMENBQW1DO0FBRW5DOzs7R0FHRztBQUNILE1BQXFCLFNBQVM7SUFNN0I7UUFDQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLGFBQUcsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7O09BR0c7SUFDSCxhQUFhLENBQUMsS0FBWTtRQUN6QixJQUFJLENBQUMs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Q0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFdEMsUUFBUTtZQUNSLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFOUMsU0FBUztZQUNULElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFdEMsT0FBTztZQUNQLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN0QixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFFN0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3JCLENBQUMsQ0FBQTtRQUVELHdCQUF3QixDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsR0FBRyxVQUFTLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxF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TyxFQUFFLEVBQUMsUUFBUSxFQUFFLElBQUksY0FBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUMsQ0FBQyxDQUFDO1FBQzNNLElBQUksQ0FBQyxVQUFVLEdBQWMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsOEJBQWEsQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLEVBQUMsUUFBUSxFQUFFLElBQUksY0FBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUMsQ0FBQyxDQUFDO1FBQ3BOLElBQUksQ0FBQyxjQUFjLEdBQVUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsOEJBQWEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUMsUUFBUSxFQUFFLElBQUksY0FBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSx3QkFBd0IsRUFBQyxDQUFDLENBQUM7UUFDck8sSUFBSSxDQUFDLFdBQVcsR0FBVSxJQUFJLENBQUMsR0FBRyxD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R0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqSyxLQUFLLENBQUMsR0FBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN0QyxLQUFLLENBQUMsR0FBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDNUQsS0FBSyxDQUFDLEdBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFhLEtBQUssQ0FBQyxHQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxjQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsS0FBSyxDQUFDLEdBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEMsS0FBSyxDQUFDLEdBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzlELEtBQUssQ0FBQyxHQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsR0FBYSxLQUFLLENBQUMsR0FBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksY0FBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RHLEtBQUssQ0FBQyxHQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQy9DLEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEIsS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsMkJBQWEsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFL0QsOEJBQThCO1FB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QUFLLENBQUMsS0FBSyxDQUFDO1FBQzNCLE1BQU0sSUFBSSxHQUFVLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLDhCQUFhLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFDLFFBQVEsRUFBRSxJQUFJLGNBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLDRCQUE0QixFQUFDLENBQUMsQ0FBQztRQUMxSixJQUFJLENBQUMsU0FBUyxHQUFHLGVBQUssQ0FBQyxLQUFLLENBQUM7UUFFN0IsTUFBTSxDQUFDLEdBQVUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsOEJBQWEsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLEVBQUMsUUFBUSxFQUFFLElBQUksY0FBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBQyxDQUFDLENBQUM7UUFDdEksQ0FBQyxDQUFDLFNBQVMsR0FBRyxlQUFLLENBQUMsS0FBSyxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxHQUFVLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLDhCQUFhLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFDLFFBQVEsRUFBRSxJQUFJLGNBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBQyxDQUFDLENBQUM7UUFDdkksQ0FBQyxDQUFDLFNBQVMsR0FBRyxlQUFLLENBQUMsS0FBSyxDQUFDO1FBQzFCLE1BQU0sTUFBTSxHQUFVLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLDhCQUFhLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFDLFFBQVEsRUFBRSxJQUFJLGNBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLEdBQUcsR0FBRyxD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QUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakUsSUFBSSxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUM7Z0JBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hGLElBQUksUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ3BFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEc7YUFDSTtZQUNELEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtnQkFDL0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakUsSUFBSSxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUM7Z0JBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hGLElBQUksUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ3BFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEc7SUFDTCxDQUFDO0lBRU8sUUFBUTtRQUNaLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7UUFDdEMsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLDBCQUFjLENBQUM7UUFDeEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSwwQkFBYyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQzdFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ2pGLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDO1FBQy9DLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO1FBQzdDLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxHQUFHLFlBQVksQ0FBQztRQUNwQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxP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Q0FBd0IsQ0FBQTtBQUM1QixDQUFDLEVBSlcsV0FBVyxHQUFYLG1CQUFXLEtBQVgsbUJBQVcsUUFJdEI7QUFFRCxJQUFZLFFBTVg7QUFORCxXQUFZLFFBQVE7SUFDaEIsaUNBQXFCLENBQUE7SUFDckIscUNBQXlCLENBQUE7SUFDekIsdUNBQTJCLENBQUE7SUFDM0IsaUNBQXFCLENBQUE7SUFDckIsdUNBQTJCLENBQUE7QUFDL0IsQ0FBQyxFQU5XLFFBQVEsR0FBUixnQkFBUSxLQUFSLGdCQUFRLFFBTW5CO0FBRUQsSUFBWSxTQUtYO0FBTEQsV0FBWSxTQUFTO0lBQ2pCLDhCQUFpQixDQUFBO0lBQ2pCLDRCQUFlLENBQUE7SUFDZiwwQkFBYSxDQUFBO0lBQ2IsNEJBQWUsQ0FBQTtBQUNuQixDQUFDLEVBTFcsU0FBUyxHQUFULGlCQUFTLEtBQVQsaUJBQVMsUUFLcEIiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCJleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBzdHJpbmdpZnlcbmV4cG9ydHMuZ2V0U2VyaWFsaXplID0gc2VyaWFsaXplclxuXG5mdW5jdGlvbiBzdHJpbmdpZnkob2JqLCByZXBsYWNlciwgc3BhY2VzLCBjeWNsZVJlcGxhY2VyKSB7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIHNlcmlhbGl6ZXIocmVwbGFjZXIsIGN5Y2xlUmVwbGFjZXIpLCBzcGFjZXMpXG59XG5cbmZ1bmN0aW9uIHNlcmlhbGl6ZXIocmVwbGFjZXIsIGN5Y2xlUmVwbGFjZXIpIHtcbiAgdmFyIHN0YWNrID0gW10sIGtleXMgPSBbXVxuXG4gIGlmIChjeWNsZVJlcGxhY2VyID09IG51bGwpIGN5Y2xlUmVwbGFjZXIgPSBmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgaWYgKHN0YWNrWzBdID09PSB2YWx1ZSkgcmV0dXJuIFwiW0NpcmN1bGFyIH5dXCJcbiAgICByZXR1cm4gXCJbQ2lyY3VsYXIgfi5cIiArIGtleXMuc2xpY2UoMCwgc3RhY2suaW5kZXhPZih2YWx1ZSkpLmpvaW4oXCIuXCIpICsgXCJdXCJcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgaWYgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIHZhciB0aGlzUG9zID0gc3RhY2suaW5kZXhPZih0aGlzKVxuICAgICAgfnRoaXNQb3MgPyBzdGFjay5zcGxpY2UodGhpc1BvcyArIDEpIDogc3RhY2sucHVzaCh0aGlzKVxuICAgICAgfnRoaXNQb3MgPyBrZXlzLnNwbGljZSh0aGlzUG9zLCBJbmZpbml0eSwga2V5KSA6IGtleXMucHVzaChrZXkpXG4gICAgICBpZiAofnN0YWNrLmluZGV4T2YodmFsdWUpKSB2YWx1ZSA9IGN5Y2xlUmVwbGFjZXIuY2FsbCh0aGlzLCBrZXksIHZhbHVlKVxuICAgIH1cbiAgICBlbHNlIHN0YWNrLnB1c2godmFsdWUpXG5cbiAgICByZXR1cm4gcmVwbGFjZXIgPT0gbnVsbCA/IHZhbHVlIDogcmVwbGFjZXIuY2FsbCh0aGlzLCBrZXksIHZhbHVlKVxuICB9XG59XG4iLCIvKlxuICogcmFuZG9tLXNlZWRcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9za3JhdGNoZG90L3JhbmRvbS1zZWVkXG4gKlxuICogVGhpcyBjb2RlIHdhcyBvcmlnaW5hbGx5IHdyaXR0ZW4gYnkgU3RldmUgR2lic29uIGFuZCBjYW4gYmUgZm91bmQgaGVyZTpcbiAqXG4gKiBodHRwczovL3d3dy5ncmMuY29tL290Zy91aGVwcm5nLmh0bVxuICpcbiAqIEl0IHdhcyBzbGlnaHRseSBtb2RpZmllZCBmb3IgdXNlIGluIG5vZGUsIHRvIHBhc3MganNoaW50LCBhbmQgYSBmZXcgYWRkaXRpb25hbFxuICogaGVscGVyIGZ1bmN0aW9ucyB3ZXJlIGFkZGVkLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMyBza3JhdGNoZG90XG4gKiBEdWFsIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBhbmQgdGhlIG9yaWdpbmFsIEdSQyBjb3B5cmlnaHQvbGljZW5zZVxuICogaW5jbHVkZWQgYmVsb3cuXG4gKi9cbi8qXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cdFx0XHRcdFx0XHRcdFx0XHRHaWJzb24gUmVzZWFyY2ggQ29ycG9yYXRpb25cblx0XHRcdFx0VUhFUFJORyAtIFVsdHJhIEhpZ2ggRW50cm9weSBQc2V1ZG8tUmFuZG9tIE51bWJlciBHZW5lcmF0b3Jcblx0PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXHRMSUNFTlNFIEFORCBDT1BZUklHSFQ6ICBUSElTIENPREUgSVMgSEVSRUJZIFJFTEVBU0VEIElOVE8gVEhFIFBVQkxJQyBET01BSU5cblx0R2lic29uIFJlc2VhcmNoIENvcnBvcmF0aW9uIHJlbGVhc2VzIGFuZCBkaXNjbGFpbXMgQUxMIFJJR0hUUyBBTkQgVElUTEUgSU5cblx0VEhJUyBDT0RFIE9SIEFOWSBERVJJVkFUSVZFUy4gQW55b25lIG1heSBiZSBmcmVlbHkgdXNlIGl0IGZvciBhbnkgcHVycG9zZS5cblx0PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXHRUaGlzIGlzIEdSQydzIGNyeXB0b2dyYXBoaWNhbGx5IHN0cm9uZyBQUk5HIChwc2V1ZG8tcmFuZG9tIG51bWJlciBnZW5lcmF0b3IpXG5cdGZvciBKYXZhU2NyaXB0LiBJdCBpcyBkcml2ZW4gYnkgMTUzNiBiaXRzIG9mIGVudHJvcHksIHN0b3JlZCBpbiBhbiBhcnJheSBvZlxuXHQ0OCwgMzItYml0IEphdmFTY3JpcHQgdmFyaWFibGVzLiAgU2luY2UgbWFueSBhcHBsaWNhdGlvbnMgb2YgdGhpcyBnZW5lcmF0b3IsXG5cdGluY2x1ZGluZyBvdXJzIHdpdGggdGhlIFwiT2ZmIFRoZSBHcmlkXCIgTGF0aW4gU3F1YXJlIGdlbmVyYXRvciwgbWF5IHJlcXVpcmVcblx0dGhlIGRldGVyaW1pbmlzdGljIHJlLWdlbmVyYXRpb24gb2YgYSBzZXF1ZW5jZSBvZiBQUk5zLCB0aGlzIFBSTkcncyBpbml0aWFsXG5cdGVudHJvcGljIHN0YXRlIGNhbiBiZSByZWFkIGFuZCB3cml0dGVuIGFzIGEgc3RhdGljIHdob2xlLCBhbmQgaW5jcmVtZW50YWxseVxuXHRldm9sdmVkIGJ5IHBvdXJpbmcgbmV3IHNvdXJjZSBlbnRyb3B5IGludG8gdGhlIGdlbmVyYXRvcidzIGludGVybmFsIHN0YXRlLlxuXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdEVORExFU1MgVEhBTktTIGFyZSBkdWUgSm9oYW5uZXMgQmFhZ29lIGZvciBoaXMgY2FyZWZ1bCBkZXZlbG9wbWVudCBvZiBoaWdobHlcblx0cm9idXN0IEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb25zIG9mIEpTIFBSTkdzLiAgVGhpcyB3b3JrIHdhcyBiYXNlZCB1cG9uIGhpc1xuXHRKYXZhU2NyaXB0IFwiQWxlYVwiIFBSTkcgd2hpY2ggaXMgYmFzZWQgdXBvbiB0aGUgZXh0cmVtZWx5IHJvYnVzdCBNdWx0aXBseS1cblx0V2l0aC1DYXJyeSAoTVdDKSBQUk5HIGludmVudGVkIGJ5IEdlb3JnZSBNYXJzYWdsaWEuIE1XQyBBbGdvcml0aG0gUmVmZXJlbmNlczpcblx0aHR0cDovL3d3dy5HUkMuY29tL290Zy9NYXJzYWdsaWFfUFJOR3MucGRmXG5cdGh0dHA6Ly93d3cuR1JDLmNvbS9vdGcvTWFyc2FnbGlhX01XQ19HZW5lcmF0b3JzLnBkZlxuXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdFRoZSBxdWFsaXR5IG9mIHRoaXMgYWxnb3JpdGhtJ3MgcHNldWRvLXJhbmRvbSBudW1iZXJzIGhhdmUgYmVlbiB2ZXJpZmllZCBieVxuXHRtdWx0aXBsZSBpbmRlcGVuZGVudCByZXNlYXJjaGVycy4gSXQgaGFuZGlseSBwYXNzZXMgdGhlIGZlcm1pbGFiLmNoIHRlc3RzIGFzXG5cdHdlbGwgYXMgdGhlIFwiZGllaGFyZFwiIGFuZCBcImRpZWhhcmRlclwiIHRlc3Qgc3VpdGVzLiAgRm9yIGluZGl2aWR1YWxzIHdpc2hpbmdcblx0dG8gZnVydGhlciB2ZXJpZnkgdGhlIHF1YWxpdHkgb2YgdGhpcyBhbGdvcml0aG0ncyBwc2V1ZG8tcmFuZG9tIG51bWJlcnMsIGFcblx0MjU2LW1lZ2FieXRlIGZpbGUgb2YgdGhpcyBhbGdvcml0aG0ncyBvdXRwdXQgbWF5IGJlIGRvd25sb2FkZWQgZnJvbSBHUkMuY29tLFxuXHRhbmQgYSBNaWNyb3NvZnQgV2luZG93cyBzY3JpcHRpbmcgaG9zdCAoV1NIKSB2ZXJzaW9uIG9mIHRoaXMgYWxnb3JpdGhtIG1heSBiZVxuXHRkb3dubG9hZGVkIGFuZCBydW4gZnJvbSB0aGUgV2luZG93cyBjb21tYW5kIHByb21wdCB0byBnZW5lcmF0ZSB1bmlxdWUgZmlsZXNcblx0b2YgYW55IHNpemU6XG5cdFRoZSBGZXJtaWxhYiBcIkVOVFwiIHRlc3RzOiBodHRwOi8vZm91cm1pbGFiLmNoL3JhbmRvbS9cblx0VGhlIDI1Ni1tZWdhYnl0ZSBzYW1wbGUgUFJOIGZpbGUgYXQgR1JDOiBodHRwczovL3d3dy5HUkMuY29tL290Zy91aGVwcm5nLmJpblxuXHRUaGUgV2luZG93cyBzY3JpcHRpbmcgaG9zdCB2ZXJzaW9uOiBodHRwczovL3d3dy5HUkMuY29tL290Zy93c2gtdWhlcHJuZy5qc1xuXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdFF1YWxpZnlpbmcgTVdDIG11bHRpcGxpZXJzIGFyZTogMTg3ODg0LCA2ODYxMTgsIDg5ODEzNCwgMTEwNDM3NSwgMTI1MDIwNSxcblx0MTQ2MDkxMCBhbmQgMTc2ODg2My4gKFdlIHVzZSB0aGUgbGFyZ2VzdCBvbmUgdGhhdCdzIDwgMl4yMSlcblx0PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuJ3VzZSBzdHJpY3QnO1xudmFyIHN0cmluZ2lmeSA9IHJlcXVpcmUoJ2pzb24tc3RyaW5naWZ5LXNhZmUnKTtcblxuLypcdD09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblRoaXMgaXMgYmFzZWQgdXBvbiBKb2hhbm5lcyBCYWFnb2UncyBjYXJlZnVsbHkgZGVzaWduZWQgYW5kIGVmZmljaWVudCBoYXNoXG5mdW5jdGlvbiBmb3IgdXNlIHdpdGggSmF2YVNjcmlwdC4gIEl0IGhhcyBhIHByb3ZlbiBcImF2YWxhbmNoZVwiIGVmZmVjdCBzdWNoXG50aGF0IGV2ZXJ5IGJpdCBvZiB0aGUgaW5wdXQgYWZmZWN0cyBldmVyeSBiaXQgb2YgdGhlIG91dHB1dCA1MCUgb2YgdGhlIHRpbWUsXG53aGljaCBpcyBnb29kLlx0U2VlOiBodHRwOi8vYmFhZ29lLmNvbS9lbi9SYW5kb21NdXNpbmdzL2hhc2gvYXZhbGFuY2hlLnhodG1sXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4qL1xudmFyIE1hc2ggPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBuID0gMHhlZmM4MjQ5ZDtcblx0dmFyIG1hc2ggPSBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdGlmIChkYXRhKSB7XG5cdFx0XHRkYXRhID0gZGF0YS50b1N0cmluZygpO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdG4gKz0gZGF0YS5jaGFyQ29kZUF0KGkpO1xuXHRcdFx0XHR2YXIgaCA9IDAuMDI1MTk2MDMyODI0MTY5MzggKiBuO1xuXHRcdFx0XHRuID0gaCA+Pj4gMDtcblx0XHRcdFx0aCAtPSBuO1xuXHRcdFx0XHRoICo9IG47XG5cdFx0XHRcdG4gPSBoID4+PiAwO1xuXHRcdFx0XHRoIC09IG47XG5cdFx0XHRcdG4gKz0gaCAqIDB4MTAwMDAwMDAwOyAvLyAyXjMyXG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gKG4gPj4+IDApICogMi4zMjgzMDY0MzY1Mzg2OTYzZS0xMDsgLy8gMl4tMzJcblx0XHR9IGVsc2Uge1xuXHRcdFx0biA9IDB4ZWZjODI0OWQ7XG5cdFx0fVxuXHR9O1xuXHRyZXR1cm4gbWFzaDtcbn07XG5cbnZhciB1aGVwcm5nID0gZnVuY3Rpb24gKHNlZWQpIHtcblx0cmV0dXJuIChmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG8gPSA0ODsgLy8gc2V0IHRoZSAnb3JkZXInIG51bWJlciBvZiBFTlRST1BZLWhvbGRpbmcgMzItYml0IHZhbHVlc1xuXHRcdHZhciBjID0gMTsgLy8gaW5pdCB0aGUgJ2NhcnJ5JyB1c2VkIGJ5IHRoZSBtdWx0aXBseS13aXRoLWNhcnJ5IChNV0MpIGFsZ29yaXRobVxuXHRcdHZhciBwID0gbzsgLy8gaW5pdCB0aGUgJ3BoYXNlJyAobWF4LTEpIG9mIHRoZSBpbnRlcm1lZGlhdGUgdmFyaWFibGUgcG9pbnRlclxuXHRcdHZhciBzID0gbmV3IEFycmF5KG8pOyAvLyBkZWNsYXJlIG91ciBpbnRlcm1lZGlhdGUgdmFyaWFibGVzIGFycmF5XG5cdFx0dmFyIGk7IC8vIGdlbmVyYWwgcHVycG9zZSBsb2NhbFxuXHRcdHZhciBqOyAvLyBnZW5lcmFsIHB1cnBvc2UgbG9jYWxcblx0XHR2YXIgayA9IDA7IC8vIGdlbmVyYWwgcHVycG9zZSBsb2NhbFxuXG5cdFx0Ly8gd2hlbiBvdXIgXCJ1aGVwcm5nXCIgaXMgaW5pdGlhbGx5IGludm9rZWQgb3VyIFBSTkcgc3RhdGUgaXMgaW5pdGlhbGl6ZWQgZnJvbSB0aGVcblx0XHQvLyBicm93c2VyJ3Mgb3duIGxvY2FsIFBSTkcuIFRoaXMgaXMgb2theSBzaW5jZSBhbHRob3VnaCBpdHMgZ2VuZXJhdG9yIG1pZ2h0IG5vdFxuXHRcdC8vIGJlIHdvbmRlcmZ1bCwgaXQncyB1c2VmdWwgZm9yIGVzdGFibGlzaGluZyBsYXJnZSBzdGFydHVwIGVudHJvcHkgZm9yIG91ciB1c2FnZS5cblx0XHR2YXIgbWFzaCA9IG5ldyBNYXNoKCk7IC8vIGdldCBhIHBvaW50ZXIgdG8gb3VyIGhpZ2gtcGVyZm9ybWFuY2UgXCJNYXNoXCIgaGFzaFxuXG5cdFx0Ly8gZmlsbCB0aGUgYXJyYXkgd2l0aCBpbml0aWFsIG1hc2ggaGFzaCB2YWx1ZXNcblx0XHRmb3IgKGkgPSAwOyBpIDwgbzsgaSsrKSB7XG5cdFx0XHRzW2ldID0gbWFzaChNYXRoLnJhbmRvbSgpKTtcblx0XHR9XG5cblx0XHQvLyB0aGlzIFBSSVZBVEUgKGludGVybmFsIGFjY2VzcyBvbmx5KSBmdW5jdGlvbiBpcyB0aGUgaGVhcnQgb2YgdGhlIG11bHRpcGx5LXdpdGgtY2Fycnlcblx0XHQvLyAoTVdDKSBQUk5HIGFsZ29yaXRobS4gV2hlbiBjYWxsZWQgaXQgcmV0dXJucyBhIHBzZXVkby1yYW5kb20gbnVtYmVyIGluIHRoZSBmb3JtIG9mIGFcblx0XHQvLyAzMi1iaXQgSmF2YVNjcmlwdCBmcmFjdGlvbiAoMC4wIHRvIDwxLjApIGl0IGlzIGEgUFJJVkFURSBmdW5jdGlvbiB1c2VkIGJ5IHRoZSBkZWZhdWx0XG5cdFx0Ly8gWzAtMV0gcmV0dXJuIGZ1bmN0aW9uLCBhbmQgYnkgdGhlIHJhbmRvbSAnc3RyaW5nKG4pJyBmdW5jdGlvbiB3aGljaCByZXR1cm5zICduJ1xuXHRcdC8vIGNoYXJhY3RlcnMgZnJvbSAzMyB0byAxMjYuXG5cdFx0dmFyIHJhd3BybmcgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAoKytwID49IG8pIHtcblx0XHRcdFx0cCA9IDA7XG5cdFx0XHR9XG5cdFx0XHR2YXIgdCA9IDE3Njg4NjMgKiBzW3BdICsgYyAqIDIuMzI4MzA2NDM2NTM4Njk2M2UtMTA7IC8vIDJeLTMyXG5cdFx0XHRyZXR1cm4gc1twXSA9IHQgLSAoYyA9IHQgfCAwKTtcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBmdW5jdGlvbiBpcyB0aGUgZGVmYXVsdCBmdW5jdGlvbiByZXR1cm5lZCBieSB0aGlzIGxpYnJhcnkuXG5cdFx0Ly8gVGhlIHZhbHVlcyByZXR1cm5lZCBhcmUgaW50ZWdlcnMgaW4gdGhlIHJhbmdlIGZyb20gMCB0byByYW5nZS0xLiBXZSBmaXJzdFxuXHRcdC8vIG9idGFpbiB0d28gMzItYml0IGZyYWN0aW9ucyAoZnJvbSByYXdwcm5nKSB0byBzeW50aGVzaXplIGEgc2luZ2xlIGhpZ2hcblx0XHQvLyByZXNvbHV0aW9uIDUzLWJpdCBwcm5nICgwIHRvIDwxKSwgdGhlbiB3ZSBtdWx0aXBseSB0aGlzIGJ5IHRoZSBjYWxsZXInc1xuXHRcdC8vIFwicmFuZ2VcIiBwYXJhbSBhbmQgdGFrZSB0aGUgXCJmbG9vclwiIHRvIHJldHVybiBhIGVxdWFsbHkgcHJvYmFibGUgaW50ZWdlci5cblx0XHR2YXIgcmFuZG9tID0gZnVuY3Rpb24gKHJhbmdlKSB7XG5cdFx0XHRyZXR1cm4gTWF0aC5mbG9vcihyYW5nZSAqIChyYXdwcm5nKCkgKyAocmF3cHJuZygpICogMHgyMDAwMDAgfCAwKSAqIDEuMTEwMjIzMDI0NjI1MTU2NWUtMTYpKTsgLy8gMl4tNTNcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBmdW5jdGlvbiAnc3RyaW5nKG4pJyByZXR1cm5zIGEgcHNldWRvLXJhbmRvbSBzdHJpbmcgb2Zcblx0XHQvLyAnbicgcHJpbnRhYmxlIGNoYXJhY3RlcnMgcmFuZ2luZyBmcm9tIGNocigzMykgdG8gY2hyKDEyNikgaW5jbHVzaXZlLlxuXHRcdHJhbmRvbS5zdHJpbmcgPSBmdW5jdGlvbiAoY291bnQpIHtcblx0XHRcdHZhciBpO1xuXHRcdFx0dmFyIHMgPSAnJztcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG5cdFx0XHRcdHMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgzMyArIHJhbmRvbSg5NCkpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHM7XG5cdFx0fTtcblxuXHRcdC8vIHRoaXMgUFJJVkFURSBcImhhc2hcIiBmdW5jdGlvbiBpcyB1c2VkIHRvIGV2b2x2ZSB0aGUgZ2VuZXJhdG9yJ3MgaW50ZXJuYWxcblx0XHQvLyBlbnRyb3B5IHN0YXRlLiBJdCBpcyBhbHNvIGNhbGxlZCBieSB0aGUgRVhQT1JURUQgYWRkRW50cm9weSgpIGZ1bmN0aW9uXG5cdFx0Ly8gd2hpY2ggaXMgdXNlZCB0byBwb3VyIGVudHJvcHkgaW50byB0aGUgUFJORy5cblx0XHR2YXIgaGFzaCA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCBvOyBqKyspIHtcblx0XHRcdFx0XHRzW2pdIC09IG1hc2goYXJnc1tpXSk7XG5cdFx0XHRcdFx0aWYgKHNbal0gPCAwKSB7XG5cdFx0XHRcdFx0XHRzW2pdICs9IDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdC8vIHRoaXMgRVhQT1JURUQgXCJjbGVhbiBzdHJpbmdcIiBmdW5jdGlvbiByZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHNwYWNlcyBhbmQgbm9uLXByaW50aW5nXG5cdFx0Ly8gY29udHJvbCBjaGFyYWN0ZXJzLCBpbmNsdWRpbmcgYW55IGVtYmVkZGVkIGNhcnJpYWdlLXJldHVybiAoQ1IpIGFuZCBsaW5lLWZlZWQgKExGKSBjaGFyYWN0ZXJzLFxuXHRcdC8vIGZyb20gYW55IHN0cmluZyBpdCBpcyBoYW5kZWQuIHRoaXMgaXMgYWxzbyB1c2VkIGJ5IHRoZSAnaGFzaHN0cmluZycgZnVuY3Rpb24gKGJlbG93KSB0byBoZWxwXG5cdFx0Ly8gdXNlcnMgYWx3YXlzIG9idGFpbiB0aGUgc2FtZSBFRkZFQ1RJVkUgdWhlcHJuZyBzZWVkaW5nIGtleS5cblx0XHRyYW5kb20uY2xlYW5TdHJpbmcgPSBmdW5jdGlvbiAoaW5TdHIpIHtcblx0XHRcdGluU3RyID0gaW5TdHIucmVwbGFjZSgvKF5cXHMqKXwoXFxzKiQpL2dpLCAnJyk7IC8vIHJlbW92ZSBhbnkvYWxsIGxlYWRpbmcgc3BhY2VzXG5cdFx0XHRpblN0ciA9IGluU3RyLnJlcGxhY2UoL1tcXHgwMC1cXHgxRl0vZ2ksICcnKTsgLy8gcmVtb3ZlIGFueS9hbGwgY29udHJvbCBjaGFyYWN0ZXJzXG5cdFx0XHRpblN0ciA9IGluU3RyLnJlcGxhY2UoL1xcbiAvLCAnXFxuJyk7IC8vIHJlbW92ZSBhbnkvYWxsIHRyYWlsaW5nIHNwYWNlc1xuXHRcdFx0cmV0dXJuIGluU3RyOyAvLyByZXR1cm4gdGhlIGNsZWFuZWQgdXAgcmVzdWx0XG5cdFx0fTtcblxuXHRcdC8vIHRoaXMgRVhQT1JURUQgXCJoYXNoIHN0cmluZ1wiIGZ1bmN0aW9uIGhhc2hlcyB0aGUgcHJvdmlkZWQgY2hhcmFjdGVyIHN0cmluZyBhZnRlciBmaXJzdCByZW1vdmluZ1xuXHRcdC8vIGFueSBsZWFkaW5nIG9yIHRyYWlsaW5nIHNwYWNlcyBhbmQgaWdub3JpbmcgYW55IGVtYmVkZGVkIGNhcnJpYWdlIHJldHVybnMgKENSKSBvciBMaW5lIEZlZWRzIChMRilcblx0XHRyYW5kb20uaGFzaFN0cmluZyA9IGZ1bmN0aW9uIChpblN0cikge1xuXHRcdFx0aW5TdHIgPSByYW5kb20uY2xlYW5TdHJpbmcoaW5TdHIpO1xuXHRcdFx0bWFzaChpblN0cik7IC8vIHVzZSB0aGUgc3RyaW5nIHRvIGV2b2x2ZSB0aGUgJ21hc2gnIHN0YXRlXG5cdFx0XHRmb3IgKGkgPSAwOyBpIDwgaW5TdHIubGVuZ3RoOyBpKyspIHsgLy8gc2NhbiB0aHJvdWdoIHRoZSBjaGFyYWN0ZXJzIGluIG91ciBzdHJpbmdcblx0XHRcdFx0ayA9IGluU3RyLmNoYXJDb2RlQXQoaSk7IC8vIGdldCB0aGUgY2hhcmFjdGVyIGNvZGUgYXQgdGhlIGxvY2F0aW9uXG5cdFx0XHRcdGZvciAoaiA9IDA7IGogPCBvOyBqKyspIHsgLy9cdFwibWFzaFwiIGl0IGludG8gdGhlIFVIRVBSTkcgc3RhdGVcblx0XHRcdFx0XHRzW2pdIC09IG1hc2goayk7XG5cdFx0XHRcdFx0aWYgKHNbal0gPCAwKSB7XG5cdFx0XHRcdFx0XHRzW2pdICs9IDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdC8vIHRoaXMgRVhQT1JURUQgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byBzZWVkIHRoZSByYW5kb20gZ2VuZXJhdG9yLlxuXHRcdHJhbmRvbS5zZWVkID0gZnVuY3Rpb24gKHNlZWQpIHtcblx0XHRcdGlmICh0eXBlb2Ygc2VlZCA9PT0gJ3VuZGVmaW5lZCcgfHwgc2VlZCA9PT0gbnVsbCkge1xuXHRcdFx0XHRzZWVkID0gTWF0aC5yYW5kb20oKTtcblx0XHRcdH1cblx0XHRcdGlmICh0eXBlb2Ygc2VlZCAhPT0gJ3N0cmluZycpIHtcblx0XHRcdFx0c2VlZCA9IHN0cmluZ2lmeShzZWVkLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuXHRcdFx0XHRcdGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRcdHJldHVybiAodmFsdWUpLnRvU3RyaW5nKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB2YWx1ZTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHRyYW5kb20uaW5pdFN0YXRlKCk7XG5cdFx0XHRyYW5kb20uaGFzaFN0cmluZyhzZWVkKTtcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBoYW5keSBleHBvcnRlZCBmdW5jdGlvbiBpcyB1c2VkIHRvIGFkZCBlbnRyb3B5IHRvIG91ciB1aGVwcm5nIGF0IGFueSB0aW1lXG5cdFx0cmFuZG9tLmFkZEVudHJvcHkgPSBmdW5jdGlvbiAoIC8qIGFjY2VwdCB6ZXJvIG9yIG1vcmUgYXJndW1lbnRzICovICkge1xuXHRcdFx0dmFyIGFyZ3MgPSBbXTtcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0YXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG5cdFx0XHR9XG5cdFx0XHRoYXNoKChrKyspICsgKG5ldyBEYXRlKCkuZ2V0VGltZSgpKSArIGFyZ3Muam9pbignJykgKyBNYXRoLnJhbmRvbSgpKTtcblx0XHR9O1xuXG5cdFx0Ly8gaWYgd2Ugd2FudCB0byBwcm92aWRlIGEgZGV0ZXJtaW5pc3RpYyBzdGFydHVwIGNvbnRleHQgZm9yIG91ciBQUk5HLFxuXHRcdC8vIGJ1dCB3aXRob3V0IGRpcmVjdGx5IHNldHRpbmcgdGhlIGludGVybmFsIHN0YXRlIHZhcmlhYmxlcywgdGhpcyBhbGxvd3Ncblx0XHQvLyB1cyB0byBpbml0aWFsaXplIHRoZSBtYXNoIGhhc2ggYW5kIFBSTkcncyBpbnRlcm5hbCBzdGF0ZSBiZWZvcmUgcHJvdmlkaW5nXG5cdFx0Ly8gc29tZSBoYXNoaW5nIGlucHV0XG5cdFx0cmFuZG9tLmluaXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdG1hc2goKTsgLy8gcGFzcyBhIG51bGwgYXJnIHRvIGZvcmNlIG1hc2ggaGFzaCB0byBpbml0XG5cdFx0XHRmb3IgKGkgPSAwOyBpIDwgbzsgaSsrKSB7XG5cdFx0XHRcdHNbaV0gPSBtYXNoKCcgJyk7IC8vIGZpbGwgdGhlIGFycmF5IHdpdGggaW5pdGlhbCBtYXNoIGhhc2ggdmFsdWVzXG5cdFx0XHR9XG5cdFx0XHRjID0gMTsgLy8gaW5pdCBvdXIgbXVsdGlwbHktd2l0aC1jYXJyeSBjYXJyeVxuXHRcdFx0cCA9IG87IC8vIGluaXQgb3VyIHBoYXNlXG5cdFx0fTtcblxuXHRcdC8vIHdlIHVzZSB0aGlzIChvcHRpb25hbCkgZXhwb3J0ZWQgZnVuY3Rpb24gdG8gc2lnbmFsIHRoZSBKYXZhU2NyaXB0IGludGVycHJldGVyXG5cdFx0Ly8gdGhhdCB3ZSdyZSBmaW5pc2hlZCB1c2luZyB0aGUgXCJNYXNoXCIgaGFzaCBmdW5jdGlvbiBzbyB0aGF0IGl0IGNhbiBmcmVlIHVwIHRoZVxuXHRcdC8vIGxvY2FsIFwiaW5zdGFuY2UgdmFyaWFibGVzXCIgaXMgd2lsbCBoYXZlIGJlZW4gbWFpbnRhaW5pbmcuICBJdCdzIG5vdCBzdHJpY3RseVxuXHRcdC8vIG5lY2Vzc2FyeSwgb2YgY291cnNlLCBidXQgaXQncyBnb29kIEphdmFTY3JpcHQgY2l0aXplbnNoaXAuXG5cdFx0cmFuZG9tLmRvbmUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRtYXNoID0gbnVsbDtcblx0XHR9O1xuXG5cdFx0Ly8gaWYgd2UgY2FsbGVkIFwidWhlcHJuZ1wiIHdpdGggYSBzZWVkIHZhbHVlLCB0aGVuIGV4ZWN1dGUgcmFuZG9tLnNlZWQoKSBiZWZvcmUgcmV0dXJuaW5nXG5cdFx0aWYgKHR5cGVvZiBzZWVkICE9PSAndW5kZWZpbmVkJykge1xuXHRcdFx0cmFuZG9tLnNlZWQoc2VlZCk7XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJucyBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gMCAoaW5jbHVzaXZlKSBhbmQgcmFuZ2UgKGV4Y2x1c2l2ZSlcblx0XHRyYW5kb20ucmFuZ2UgPSBmdW5jdGlvbiAocmFuZ2UpIHtcblx0XHRcdHJldHVybiByYW5kb20ocmFuZ2UpO1xuXHRcdH07XG5cblx0XHQvLyBSZXR1cm5zIGEgcmFuZG9tIGZsb2F0IGJldHdlZW4gMCAoaW5jbHVzaXZlKSBhbmQgMSAoZXhjbHVzaXZlKVxuXHRcdHJhbmRvbS5yYW5kb20gPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4gcmFuZG9tKE51bWJlci5NQVhfVkFMVUUgLSAxKSAvIE51bWJlci5NQVhfVkFMVUU7XG5cdFx0fTtcblxuXHRcdC8vIFJldHVybnMgYSByYW5kb20gZmxvYXQgYmV0d2VlbiBtaW4gKGluY2x1c2l2ZSkgYW5kIG1heCAoZXhjbHVzaXZlKVxuXHRcdHJhbmRvbS5mbG9hdEJldHdlZW4gPSBmdW5jdGlvbiAobWluLCBtYXgpIHtcblx0XHRcdHJldHVybiByYW5kb20ucmFuZG9tKCkgKiAobWF4IC0gbWluKSArIG1pbjtcblx0XHR9O1xuXG5cdFx0Ly8gUmV0dXJucyBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gbWluIChpbmNsdXNpdmUpIGFuZCBtYXggKGluY2x1c2l2ZSlcblx0XHRyYW5kb20uaW50QmV0d2VlbiA9IGZ1bmN0aW9uIChtaW4sIG1heCkge1xuXHRcdFx0cmV0dXJuIE1hdGguZmxvb3IocmFuZG9tLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKSArIG1pbjtcblx0XHR9O1xuXG5cdFx0Ly8gd2hlbiBvdXIgbWFpbiBvdXRlciBcInVoZXBybmdcIiBmdW5jdGlvbiBpcyBjYWxsZWQsIGFmdGVyIHNldHRpbmcgdXAgb3VyXG5cdFx0Ly8gaW5pdGlhbCB2YXJpYWJsZXMgYW5kIGVudHJvcGljIHN0YXRlLCB3ZSByZXR1cm4gYW4gXCJpbnN0YW5jZSBwb2ludGVyXCJcblx0XHQvLyB0byB0aGUgaW50ZXJuYWwgYW5vbnltb3VzIGZ1bmN0aW9uIHdoaWNoIGNhbiB0aGVuIGJlIHVzZWQgdG8gYWNjZXNzXG5cdFx0Ly8gdGhlIHVoZXBybmcncyB2YXJpb3VzIGV4cG9ydGVkIGZ1bmN0aW9ucy4gIEFzIHdpdGggdGhlIFwiLmRvbmVcIiBmdW5jdGlvblxuXHRcdC8vIGFib3ZlLCB3ZSBzaG91bGQgc2V0IHRoZSByZXR1cm5lZCB2YWx1ZSB0byAnbnVsbCcgb25jZSB3ZSdyZSBmaW5pc2hlZFxuXHRcdC8vIHVzaW5nIGFueSBvZiB0aGVzZSBmdW5jdGlvbnMuXG5cdFx0cmV0dXJuIHJhbmRvbTtcblx0fSgpKTtcbn07XG5cbi8vIE1vZGlmaWNhdGlvbiBmb3IgdXNlIGluIG5vZGU6XG51aGVwcm5nLmNyZWF0ZSA9IGZ1bmN0aW9uIChzZWVkKSB7XG5cdHJldHVybiBuZXcgdWhlcHJuZyhzZWVkKTtcbn07XG5tb2R1bGUuZXhwb3J0cyA9IHVoZXBybmc7XG4iLCJpbXBvcnQgQWN0b3IgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FjdG9yXCI7XG5pbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IEFJIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9BSVwiO1xuaW1wb3J0IEdvYXBBSSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvR29hcEFJXCJcbmltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcblxuLyoqXG4gKiBBIG1hbmFnZXIgY2xhc3MgZm9yIGFsbCBvZiB0aGUgQUkgaW4gYSBzY2VuZS5cbiAqIEtlZXBzIGEgbGlzdCBvZiByZWdpc3RlcmVkIGFjdG9ycyBhbmQgaGFuZGxlcyBBSSBnZW5lcmF0aW9uIGZvciBhY3RvcnMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFJTWFuYWdlciBpbXBsZW1lbnRzIFVwZGF0ZWFibGUge1xuXHQvKiogVGhlIGFycmF5IG9mIHJlZ2lzdGVyZWQgYWN0b3JzICovXG5cdGFjdG9yczogQXJyYXk8QWN0b3I+O1xuXHQvKiogTWFwcyBBSSBuYW1lcyB0byB0aGVpciBjb25zdHJ1Y3RvcnMgKi9cblx0cmVnaXN0ZXJlZEFJOiBNYXA8QUlDb25zdHJ1Y3Rvcj47XG5cblx0Y29uc3RydWN0b3IoKXtcblx0XHR0aGlzLmFjdG9ycyA9IG5ldyBBcnJheSgpO1xuXHRcdHRoaXMucmVnaXN0ZXJlZEFJID0gbmV3IE1hcCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhbiBhY3RvciB3aXRoIHRoZSBBSU1hbmFnZXJcblx0ICogQHBhcmFtIGFjdG9yIFRoZSBhY3RvciB0byByZWdpc3RlclxuXHQgKi9cblx0cmVnaXN0ZXJBY3RvcihhY3RvcjogQWN0b3IpOiB2b2lkIHtcblx0XHR0aGlzLmFjdG9ycy5wdXNoKGFjdG9yKTtcblx0fVxuXG5cdHJlbW92ZUFjdG9yKGFjdG9yOiBBY3Rvcik6IHZvaWQge1xuXHRcdGxldCBpbmRleCA9IHRoaXMuYWN0b3JzLmluZGV4T2YoYWN0b3IpO1xuXG5cdFx0aWYoaW5kZXggIT09IC0xKXtcblx0XHRcdHRoaXMuYWN0b3JzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhbiBBSSB3aXRoIHRoZSBBSU1hbmFnZXIgZm9yIHVzZSBsYXRlciBvblxuXHQgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgQUkgdG8gcmVnaXN0ZXJcblx0ICogQHBhcmFtIGNvbnN0ciBUaGUgY29uc3RydWN0b3IgZm9yIHRoZSBBSVxuXHQgKi9cblx0cmVnaXN0ZXJBSShuYW1lOiBzdHJpbmcsIGNvbnN0cjogbmV3IDxUIGV4dGVuZHMgQUkgfCBHb2FwQUk+KCkgPT4gVCApOiB2b2lkIHtcblx0XHR0aGlzLnJlZ2lzdGVyZWRBSS5hZGQobmFtZSwgY29uc3RyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgYW4gQUkgaW5zdGFuY2UgZnJvbSBpdHMgbmFtZVxuXHQgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgQUkgdG8gYWRkXG5cdCAqIEByZXR1cm5zIEEgbmV3IEFJIGluc3RhbmNlXG5cdCAqL1xuXHRnZW5lcmF0ZUFJKG5hbWU6IHN0cmluZyk6IEFJIHwgR29hcEFJIHtcblx0XHRpZih0aGlzLnJlZ2lzdGVyZWRBSS5oYXMobmFtZSkpe1xuXHRcdFx0cmV0dXJuIG5ldyAodGhpcy5yZWdpc3RlcmVkQUkuZ2V0KG5hbWUpKSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aHJvdyBgQ2Fubm90IGNyZWF0ZSBBSSB3aXRoIG5hbWUgJHtuYW1lfSwgbm8gQUkgd2l0aCB0aGF0IG5hbWUgaXMgcmVnaXN0ZXJlZGA7XG5cdFx0fVxuXHR9XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Ly8gUnVuIHRoZSBhaSBmb3IgZXZlcnkgYWN0aXZlIGFjdG9yXG5cdFx0dGhpcy5hY3RvcnMuZm9yRWFjaChhY3RvciA9PiB7IGlmKGFjdG9yLmFpQWN0aXZlKSBhY3Rvci5haS51cGRhdGUoZGVsdGFUKSB9KTtcblx0fVxufVxuXG50eXBlIEFJQ29uc3RydWN0b3IgPSBuZXcgPFQgZXh0ZW5kcyBBST4oKSA9PiBUOyIsImltcG9ydCBBSSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvQUlcIjtcbmltcG9ydCBTdGF0ZU1hY2hpbmUgZnJvbSBcIi4uL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZU1hY2hpbmVcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vTm9kZXMvR2FtZU5vZGVcIjtcblxuLyoqXG4gKiBBIHZlcnNpb24gb2YgYSBAcmVmZXJlbmNlW1N0YXRlTWFjaGluZV0gdGhhdCBpcyBjb25maWd1cmVkIHRvIHdvcmsgYXMgYW4gQUkgY29udHJvbGxlciBmb3IgYSBAcmVmZXJlbmNlW0dhbWVOb2RlXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTdGF0ZU1hY2hpbmVBSSBleHRlbmRzIFN0YXRlTWFjaGluZSBpbXBsZW1lbnRzIEFJIHtcblx0LyoqXHRUaGUgR2FtZU5vZGUgdGhhdCB1c2VzIHRoaXMgU3RhdGVNYWNoaW5lIGZvciBpdHMgQUkgKi9cblx0cHJvdGVjdGVkIG93bmVyOiBHYW1lTm9kZTtcblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0aW5pdGlhbGl6ZUFJKG93bmVyOiBHYW1lTm9kZSwgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRkZXN0cm95KCl7XG5cdFx0Ly8gR2V0IHJpZCBvZiBvdXIgcmVmZXJlbmNlIHRvIHRoZSBvd25lclxuXHRcdGRlbGV0ZSB0aGlzLm93bmVyO1xuXHRcdHRoaXMucmVjZWl2ZXIuZGVzdHJveSgpO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGFjdGl2YXRlKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHt9XG59IiwiLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBBIHBsYWNlaG9sZGVyIGZ1bmN0aW9uIGZvciBObyBPcGVyYXRpb24uIERvZXMgbm90aGluZ1xuICovXG5jb25zdCBOdWxsRnVuYyA9ICgpID0+IHt9O1xuXG5leHBvcnQgZGVmYXVsdCBOdWxsRnVuYzsiLCIvKipcbiAqIEEgbGlua2VkLWxpc3QgZm9yIHRoZSBlZGdlcyBpbiBhIEByZWZlcmVuY2VbR3JhcGhdLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFZGdlTm9kZSB7XG4gICAgLyoqIFRoZSBub2RlIGluIHRoZSBHcmFwaCB0aGlzIGVkZ2UgY29ubmVjdHMgdG8gKi9cbiAgICB5OiBudW1iZXI7XG4gICAgLyoqIFRoZSB3ZWlnaHQgb2YgdGhpcyBFZGdlTm9kZSAqL1xuXHR3ZWlnaHQ6IG51bWJlcjtcbiAgICAvKiogVGhlIG5leHQgRWRnZU5vZGUgaW4gdGhlIGxpbmtlZC1saXN0ICovXG4gICAgbmV4dDogRWRnZU5vZGU7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEVkZ2VOb2RlXG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbm9kZSB0aGlzIGVkZ2UgY29ubmVjdHMgdG9cbiAgICAgKiBAcGFyYW0gd2VpZ2h0IFRoZSB3ZWlnaHQgb2YgdGhpcyBlZGdlXG4gICAgICovXG5cdGNvbnN0cnVjdG9yKGluZGV4OiBudW1iZXIsIHdlaWdodD86IG51bWJlcil7XG5cdFx0dGhpcy55ID0gaW5kZXg7XG5cdFx0dGhpcy5uZXh0ID0gbnVsbDtcblx0XHR0aGlzLndlaWdodCA9IHdlaWdodCA/IHdlaWdodCA6IDE7XG5cdH1cbn0iLCJpbXBvcnQgRWRnZU5vZGUgZnJvbSBcIi4vRWRnZU5vZGVcIjtcblxuZXhwb3J0IGNvbnN0IE1BWF9WID0gMTAwO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIGEgZ3JhcGggZGF0YSBzdHJ1Y3R1cmUgdXNpbmcgZWRnZSBsaXN0cy4gSW5zcGlyZWQgYnkgVGhlIEFsZ29yaXRobSBEZXNpZ24gTWFudWFsLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHcmFwaCB7XG5cdC8qKiBBbiBhcnJheSBvZiBlZGdlcyBhdCB0aGUgbm9kZSBzcGVjaWZpZWQgYnkgdGhlIGluZGV4ICovXG5cdGVkZ2VzOiBBcnJheTxFZGdlTm9kZT47XG5cdC8qKiBBbiBhcnJheSByZXByZXNlbnRpbmcgdGhlIGRlZ3JlZSBvZiB0aGUgbm9kZSBzcGVjaWZpZWQgYnkgdGhlIGluZGV4ICovXG5cdGRlZ3JlZTogQXJyYXk8bnVtYmVyPjtcblx0LyoqIFRoZSBudW1iZXIgb2YgdmVydGljZXMgaW4gdGhlIGdyYXBoICovXG5cdG51bVZlcnRpY2VzOiBudW1iZXI7XG5cdC8qKiBUaGUgbnVtYmVyIG9mIGVkZ2VzIGluIHRoZSBncmFwaCAqL1xuXHRudW1FZGdlczogbnVtYmVyO1xuXHQvKiogV2hldGhlciBvciBub3QgdGhlIGdyYXBoIGlzIGRpcmVjdGVkICovXG5cdGRpcmVjdGVkOiBib29sZWFuO1xuXHQvKiogV2hldGhlciBvciBub3QgdGhlIGdyYXBoIGlzIHdlaWdodGVkICovXG5cdHdlaWdodGVkOiBib29sZWFuO1xuXG5cdC8qKlxuXHQgKiBDb25zdHJ1Y3RzIGEgbmV3IGdyYXBoXG5cdCAqIEBwYXJhbSBkaXJlY3RlZCBXaGV0aGVyIG9yIG5vdCB0aGlzIGdyYXBoIGlzIGRpcmVjdGVkXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihkaXJlY3RlZDogYm9vbGVhbiA9IGZhbHNlKXtcblx0XHR0aGlzLmRpcmVjdGVkID0gZGlyZWN0ZWQ7XG5cdFx0dGhpcy53ZWlnaHRlZCA9IGZhbHNlO1xuXG5cdFx0dGhpcy5udW1WZXJ0aWNlcyA9IDA7XG5cdFx0dGhpcy5udW1FZGdlcyA9IDA7XG5cblx0XHR0aGlzLmVkZ2VzID0gbmV3IEFycmF5KE1BWF9WKTtcblx0XHR0aGlzLmRlZ3JlZSA9IG5ldyBBcnJheShNQVhfVik7XG5cdH1cblxuXHQvKiogQWRkcyBhIG5vZGUgdG8gdGhpcyBncmFwaCBhbmQgcmV0dXJucyB0aGUgaW5kZXggb2YgaXRcblx0ICogQHJldHVybnMgVGhlIGluZGV4IG9mIHRoZSBuZXcgbm9kZVxuXHQqL1xuXHRhZGROb2RlKCk6IG51bWJlciB7XG5cdFx0dGhpcy5udW1WZXJ0aWNlcysrO1xuXHRcdHJldHVybiB0aGlzLm51bVZlcnRpY2VzO1xuXHR9XG5cblx0LyoqIEFkZHMgYW4gZWRnZSBiZXR3ZWVuIG5vZGUgeCBhbmQgeSwgd2l0aCBhbiBvcHRpb25hbCB3ZWlnaHRcblx0ICogQHBhcmFtIHggVGhlIGluZGV4IG9mIHRoZSBzdGFydCBvZiB0aGUgZWRnZVxuXHQgKiBAcGFyYW0geSBUaGUgaW5kZXggb2YgdGhlIGVuZCBvZiB0aGUgZWRnZVxuXHQgKiBAcGFyYW0gd2VpZ2h0IFRoZSBvcHRpb25hbCB3ZWlnaHQgb2YgdGhlIG5ldyBlZGdlXG5cdCovXG5cdGFkZEVkZ2UoeDogbnVtYmVyLCB5OiBudW1iZXIsIHdlaWdodD86IG51bWJlcik6IHZvaWQge1xuXHRcdGxldCBlZGdlID0gbmV3IEVkZ2VOb2RlKHksIHdlaWdodCk7XG5cblxuXG5cdFx0aWYodGhpcy5lZGdlc1t4XSl7XG5cdFx0XHRlZGdlLm5leHQgPSB0aGlzLmVkZ2VzW3hdO1xuXHRcdH1cblx0XHRcblx0XHR0aGlzLmVkZ2VzW3hdID0gZWRnZTtcblxuXHRcdGlmKCF0aGlzLmRpcmVjdGVkKXtcblx0XHRcdGVkZ2UgPSBuZXcgRWRnZU5vZGUoeCwgd2VpZ2h0KTtcblxuXHRcdFx0aWYodGhpcy5lZGdlc1t5XSl7XG5cdFx0XHRcdGVkZ2UubmV4dCA9IHRoaXMuZWRnZXNbeV07XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdHRoaXMuZWRnZXNbeV0gPSBlZGdlO1xuXHRcdH1cblxuXHRcdHRoaXMubnVtRWRnZXMgKz0gMTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3Mgd2hldGhlciBvciBub3QgYW4gZWRnZSBleGlzdHMgYmV0d2VlbiB0d28gbm9kZXMuXG5cdCAqIFRoaXMgY2hlY2sgaXMgZGlyZWN0aW9uYWwgaWYgdGhpcyBpcyBhIGRpcmVjdGVkIGdyYXBoLlxuXHQgKiBAcGFyYW0geCBUaGUgZmlyc3Qgbm9kZVxuXHQgKiBAcGFyYW0geSBUaGUgc2Vjb25kIG5vZGVcblx0ICogQHJldHVybnMgdHJ1ZSBpZiBhbiBlZGdlIGV4aXN0cywgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRlZGdlRXhpc3RzKHg6IG51bWJlciwgeTogbnVtYmVyKTogYm9vbGVhbiB7XG5cdFx0bGV0IGVkZ2UgPSB0aGlzLmVkZ2VzW3hdO1xuXG5cdFx0d2hpbGUoZWRnZSAhPT0gbnVsbCl7XG5cdFx0XHRpZihlZGdlLnkgPT09IHkpe1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdGVkZ2UgPSBlZGdlLm5leHQ7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGVkZ2UgbGlzdCBhc3NvY2lhdGVkIHdpdGggbm9kZSB4XG5cdCAqIEBwYXJhbSB4IFRoZSBpbmRleCBvZiB0aGUgbm9kZVxuXHQgKiBAcmV0dXJucyBUaGUgaGVhZCBvZiBhIGxpbmtlZC1saXN0IG9mIGVkZ2VzXG5cdCAqL1xuXHRnZXRFZGdlcyh4OiBudW1iZXIpOiBFZGdlTm9kZSB7XG5cdFx0cmV0dXJuIHRoaXMuZWRnZXNbeF07XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZGVncmVlIGFzc29jaWF0ZWQgd2l0aCBub2RlIHhcblx0ICogQHBhcmFtIHggVGhlIGluZGV4IG9mIHRoZSBub2RlXG5cdCAqL1xuXHRnZXREZWdyZWUoeDogbnVtYmVyKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5kZWdyZWVbeF07XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGhlIHNwZWNpZmVkIG5vZGUgaW50byBhIHN0cmluZ1xuXHQgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBub2RlIHRvIGNvbnZlcnQgdG8gYSBzdHJpbmdcblx0ICogQHJldHVybnMgVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgbm9kZTogXCJOb2RlIHhcIlxuXHQgKi9cblx0cHJvdGVjdGVkIG5vZGVUb1N0cmluZyhpbmRleDogbnVtYmVyKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gXCJOb2RlIFwiICsgaW5kZXg7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGhlIEdyYXBoIGludG8gYSBzdHJpbmcgZm9ybWF0XG5cdCAqIEByZXR1cm5zIFRoZSBncmFwaCBhcyBhIHN0cmluZ1xuXHQgKi9cblx0dG9TdHJpbmcoKTogc3RyaW5nIHtcblx0XHRsZXQgcmV0dmFsID0gXCJcIjtcblxuXHRcdGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLm51bVZlcnRpY2VzOyBpKyspe1xuXHRcdFx0bGV0IGVkZ2UgPSB0aGlzLmVkZ2VzW2ldO1xuXHRcdFx0bGV0IGVkZ2VTdHIgPSBcIlwiO1xuXHRcdFx0d2hpbGUoZWRnZSAhPT0gdW5kZWZpbmVkICYmIGVkZ2UgIT09IG51bGwpe1xuXHRcdFx0XHRlZGdlU3RyICs9IGVkZ2UueS50b1N0cmluZygpO1xuXHRcdFx0XHRpZih0aGlzLndlaWdodGVkKXtcblx0XHRcdFx0XHRlZGdlU3RyICs9IFwiIChcIiArIGVkZ2Uud2VpZ2h0ICsgXCIpXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYoZWRnZS5uZXh0ICE9PSBudWxsKXtcblx0XHRcdFx0XHRlZGdlU3RyICs9IFwiLCBcIjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGVkZ2UgPSBlZGdlLm5leHQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHZhbCArPSB0aGlzLm5vZGVUb1N0cmluZyhpKSArIFwiOiBcIiArIGVkZ2VTdHIgKyBcIlxcblwiO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXR2YWw7XG5cdH1cbn0iLCJpbXBvcnQgR3JhcGgsIHsgTUFYX1YgfSBmcm9tIFwiLi9HcmFwaFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL1ZlYzJcIjtcbmltcG9ydCBEZWJ1Z1JlbmRlcmFibGUgZnJvbSBcIi4uL0ludGVyZmFjZXMvRGVidWdSZW5kZXJhYmxlXCI7XG5cbi8qKlxuICogQW4gZXh0ZW5zaW9uIG9mIEdyYXBoIHRoYXQgaGFzIG5vZGVzIHdpdGggcG9zaXRpb25zIGluIDJEIHNwYWNlLlxuICogVGhpcyBpcyBhIHdlaWdodGVkIGdyYXBoICh0aG91Z2ggbm90IGluaGVyZW50bHkgZGlyZWN0ZClcbiovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQb3NpdGlvbkdyYXBoIGV4dGVuZHMgR3JhcGggaW1wbGVtZW50cyBEZWJ1Z1JlbmRlcmFibGUge1xuXHQvKiogQW4gYXJyYXkgb2YgdGhlIHBvc2l0aW9ucyBvZiB0aGUgbm9kZXMgaW4gdGhpcyBncmFwaCAqL1xuXHRwb3NpdGlvbnM6IEFycmF5PFZlYzI+O1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVlcyBhIG5ldyBQb3NpdGlvbkdyYXBoXG5cdCAqIEBwYXJhbSBkaXJlY3RlZCBXaGV0aGVyIG9yIG5vdCB0aGlzIGdyYXBoIGlzIGRpcmVjdGVkXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihkaXJlY3RlZDogYm9vbGVhbiA9IGZhbHNlKXtcblx0XHRzdXBlcihkaXJlY3RlZCk7XG5cdFx0dGhpcy5wb3NpdGlvbnMgPSBuZXcgQXJyYXkoTUFYX1YpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBwb3NpdGlvbmVkIG5vZGUgdG8gdGhpcyBncmFwaFxuXHQgKiBAcGFyYW0gcG9zaXRpb24gVGhlIHBvc2l0aW9uIG9mIHRoZSBub2RlIHRvIGFkZFxuXHQgKiBAcmV0dXJucyBUaGUgaW5kZXggb2YgdGhlIGFkZGVkIG5vZGVcblx0ICovXG5cdGFkZFBvc2l0aW9uZWROb2RlKHBvc2l0aW9uOiBWZWMyKTogbnVtYmVyIHtcblx0XHR0aGlzLnBvc2l0aW9uc1t0aGlzLm51bVZlcnRpY2VzXSA9IHBvc2l0aW9uO1xuXHRcdHJldHVybiB0aGlzLmFkZE5vZGUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGFuZ2VzIHRoZSBwb3NpdGlvbiBvZiBhIG5vZGUuXG5cdCAqIEF1dG9tYXRpY2FsbHkgYWRqdXN0cyB0aGUgd2VpZ2h0cyBvZiB0aGUgZ3JhcGggdGllZCB0byB0aGlzIG5vZGUuXG5cdCAqIEFzIHN1Y2gsIGJlIHdhcm5lZCB0aGF0IHRoaXMgZnVuY3Rpb24gaGFzIGFuIE8obiArIG0pIHJ1bm5pbmcgdGltZSwgYW5kIHVzZSBpdCBzcGFyaW5nbHkuXG5cdCAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG5vZGVcblx0ICogQHBhcmFtIHBvc2l0aW9uIFRoZSBuZXcgcG9zaXRpb24gb2YgdGhlIG5vZGVcblx0ICovXG5cdHNldE5vZGVQb3NpdGlvbihpbmRleDogbnVtYmVyLCBwb3NpdGlvbjogVmVjMik6IHZvaWQge1xuXHRcdHRoaXMucG9zaXRpb25zW2luZGV4XSA9IHBvc2l0aW9uO1xuXG5cdFx0Ly8gUmVjYWxjdWxhdGUgYWxsIHdlaWdodHMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgaW5kZXhcblx0XHRmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5udW1FZGdlczsgaSsrKXtcblxuXHRcdFx0bGV0IGVkZ2UgPSB0aGlzLmVkZ2VzW2ldO1xuXG5cdFx0XHR3aGlsZShlZGdlICE9PSBudWxsKXtcblx0XHRcdFx0Ly8gSWYgdGhpcyBub2RlIGlzIG9uIGVpdGhlciBzaWRlIG9mIHRoZSBlZGdlLCByZWNhbGN1bGF0ZSB3ZWlnaHRcblx0XHRcdFx0aWYoaSA9PT0gaW5kZXggfHwgZWRnZS55ID09PSBpbmRleCl7XG5cdFx0XHRcdFx0ZWRnZS53ZWlnaHQgPSB0aGlzLnBvc2l0aW9uc1tpXS5kaXN0YW5jZVRvKHRoaXMucG9zaXRpb25zW2VkZ2UueV0pO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZWRnZSA9IGVkZ2UubmV4dDtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9zaXRpb24gb2YgYSBub2RlXG5cdCAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG5vZGVcblx0ICogQHJldHVybnMgVGhlIHBvc2l0aW9uIG9mIHRoZSBub2RlXG5cdCAqL1xuXHRnZXROb2RlUG9zaXRpb24oaW5kZXg6IG51bWJlcik6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLnBvc2l0aW9uc1tpbmRleF07XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhbiBlZGdlIHRvIHRoaXMgZ3JhcGggYmV0d2VlbiBub2RlIHggYW5kIHkuXG5cdCAqIEF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlcyB0aGUgd2VpZ2h0IG9mIHRoZSBlZGdlIGFzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBub2Rlcy5cblx0ICogQHBhcmFtIHggVGhlIGJlZ2lubmluZyBvZiB0aGUgZWRnZVxuXHQgKiBAcGFyYW0geSBUaGUgZW5kIG9mIHRoZSBlZGdlXG5cdCAqL1xuXHRhZGRFZGdlKHg6IG51bWJlciwgeTogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYoIXRoaXMucG9zaXRpb25zW3hdIHx8ICF0aGlzLnBvc2l0aW9uc1t5XSl7XG5cdFx0XHR0aHJvdyBcIkNhbid0IGFkZCBlZGdlIHRvIHVuLXBvc2l0aW9uZWQgbm9kZSFcIjtcblx0XHR9XG5cblx0XHQvLyBXZWlnaHQgaXMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIG5vZGVzXG5cdFx0bGV0IHdlaWdodCA9IHRoaXMucG9zaXRpb25zW3hdLmRpc3RhbmNlVG8odGhpcy5wb3NpdGlvbnNbeV0pO1xuXG5cdFx0c3VwZXIuYWRkRWRnZSh4LCB5LCB3ZWlnaHQpO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdHByb3RlY3RlZCBub2RlVG9TdHJpbmcoaW5kZXg6IG51bWJlcik6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiTm9kZSBcIiArIGluZGV4ICsgXCIgLSBcIiArIHRoaXMucG9zaXRpb25zW2luZGV4XS50b1N0cmluZygpO1xuXHR9XG5cblx0ZGVidWdSZW5kZXIgPSAoKTogdm9pZCA9PiB7XG5cdFx0Ly8gZm9yKGxldCBwb2ludCBvZiB0aGlzLnBvc2l0aW9ucyl7XG5cdFx0Ly8gXHRjdHguZmlsbFJlY3QoKHBvaW50LnggLSBvcmlnaW4ueCAtIDQpKnpvb20sIChwb2ludC55IC0gb3JpZ2luLnkgLSA0KSp6b29tLCA4LCA4KTtcblx0XHQvLyB9XG5cdH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vVmVjMlwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL1NoYXBlcy9BQUJCXCI7XG5cbi8qKiBBbiBvYmplY3QgdGhhdCBpcyBhIHJlZ2lvbiwgd2l0aCBhIHNpemUsIHNjYWxlLCBhbmQgYm91bmRhcnkuICovXG5leHBvcnQgZGVmYXVsdCBpbnRlcmZhY2UgUmVnaW9uIHtcbiAgICAvKiogVGhlIHNpemUgb2YgdGhpcyBvYmplY3QuICovXG4gICAgc2l6ZTogVmVjMjtcblxuICAgIC8qKiBUaGUgc2NhbGUgb2YgdGhpcyBvYmplY3QuICovXG4gICAgc2NhbGU6IFZlYzI7XG5cbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIG9iamVjdCB0YWtpbmcgaW50byBhY2NvdW50IHRoZSB6b29tIGFuZCBzY2FsZSAqL1xuICAgIHJlYWRvbmx5IHNpemVXaXRoWm9vbTogVmVjMjtcblxuICAgIC8qKiBUaGUgYm91bmRpbmcgYm94IG9mIHRoaXMgb2JqZWN0LiAqL1xuICAgIGJvdW5kYXJ5OiBBQUJCO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNSZWdpb24oYXJnOiBhbnkpOiBib29sZWFuIHtcbiAgICByZXR1cm4gYXJnICYmIGFyZy5zaXplICYmIGFyZy5zY2FsZSAmJiBhcmcuYm91bmRhcnk7XG59IiwiaW1wb3J0IENvbGxlY3Rpb24gZnJvbSBcIi4vQ29sbGVjdGlvblwiO1xuXG4vKipcbiAqIEFzc29jaWF0ZXMgc3RyaW5ncyB3aXRoIGVsZW1lbnRzIG9mIHR5cGUgVFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNYXA8VD4gaW1wbGVtZW50cyBDb2xsZWN0aW9uIHtcblx0cHJpdmF0ZSBtYXA6IFJlY29yZDxzdHJpbmcsIFQ+O1xuXG5cdC8qKiBDcmVhdGVzIGEgbmV3IG1hcCAqL1xuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMubWFwID0ge307XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIHZhbHVlIFQgc3RvcmVkIGF0IGEga2V5LlxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGl0ZW0gdG8gYmUgc3RvcmVkXG5cdCAqIEBwYXJhbSB2YWx1ZSBUaGUgaXRlbSB0byBiZSBzdG9yZWRcblx0ICovXG5cdGFkZChrZXk6IHN0cmluZywgdmFsdWU6IFQpOiB2b2lkIHtcblx0XHR0aGlzLm1hcFtrZXldID0gdmFsdWU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggYSBrZXkuXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaXRlbVxuXHQgKiBAcmV0dXJucyBUaGUgaXRlbSBhdCB0aGUga2V5IG9yIHVuZGVmaW5lZFxuXHQgKi9cblx0Z2V0KGtleTogc3RyaW5nKTogVCB7XG5cdFx0cmV0dXJuIHRoaXMubWFwW2tleV07XG5cdH1cblxuXHQvKipcblx0ICogQW4gYWxpYXMgb2YgYWRkLiBTZXRzIHRoZSB2YWx1ZSBzdG9yZWQgYXQga2V5IHRvIHRoZSBuZXcgc3BlY2lmaWVkIHZhbHVlXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaXRlbSB0byBiZSBzdG9yZWRcblx0ICogQHBhcmFtIHZhbHVlIFRoZSBpdGVtIHRvIGJlIHN0b3JlZFxuXHQgKi9cblx0c2V0KGtleTogc3RyaW5nLCB2YWx1ZTogVCk6IHZvaWQge1xuXHRcdHRoaXMuYWRkKGtleSwgdmFsdWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGVyZSBpcyBhIHZhbHVlIHN0b3JlZCBhdCB0aGUgc3BlY2lmaWVkIGtleSwgZmFsc2Ugb3RoZXJ3aXNlLlxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gY2hlY2tcblx0ICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGVyZSBpcyBhbiBpdGVtIGF0IHRoZSBnaXZlbiBrZXkuXG5cdCAqL1xuXHRoYXMoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5tYXBba2V5XSAhPT0gdW5kZWZpbmVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYW4gYXJyYXkgb2YgYWxsIG9mIHRoZSBrZXlzIGluIHRoaXMgbWFwLlxuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBjb250YWluaW5nIGFsbCBrZXlzIGluIHRoZSBtYXAuXG5cdCAqL1xuXHRrZXlzKCk6IEFycmF5PHN0cmluZz4ge1xuXHRcdHJldHVybiBPYmplY3Qua2V5cyh0aGlzLm1hcCk7XG5cdH1cblx0XG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRmb3JFYWNoKGZ1bmM6IChrZXk6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xuXHRcdE9iamVjdC5rZXlzKHRoaXMubWFwKS5mb3JFYWNoKGtleSA9PiBmdW5jKGtleSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERlbGV0ZXMgYW4gaXRlbSBhc3NvY2lhdGVkIHdpdGggYSBrZXlcblx0ICogQHBhcmFtIGtleSBUaGUga2V5IGF0IHdoaWNoIHRvIGRlbGV0ZSBhbiBpdGVtXG5cdCAqL1xuXHRkZWxldGUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcblx0XHRkZWxldGUgdGhpcy5tYXBba2V5XTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRjbGVhcigpOiB2b2lkIHtcblx0XHR0aGlzLmZvckVhY2goa2V5ID0+IGRlbGV0ZSB0aGlzLm1hcFtrZXldKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyB0aGlzIG1hcCB0byBhIHN0cmluZyByZXByZXNlbnRhdGlvbi5cblx0ICogQHJldHVybnMgVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIG1hcC5cblx0ICovXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0bGV0IHN0ciA9IFwiXCI7XG5cblx0XHR0aGlzLmZvckVhY2goKGtleSkgPT4gc3RyICs9IGtleSArIFwiIC0+IFwiICsgdGhpcy5nZXQoa2V5KS50b1N0cmluZygpICsgXCJcXG5cIik7XG5cblx0XHRyZXR1cm4gc3RyO1xuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4vVmVjMlwiO1xuXG4vKiogQSA0eDQgbWF0cml4MCAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWF0NHg0IHtcblx0cHJpdmF0ZSBtYXQ6IEZsb2F0MzJBcnJheTtcblxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMubWF0ID0gbmV3IEZsb2F0MzJBcnJheShbXG5cdFx0XHQwLCAwLCAwLCAwLFxuXHRcdFx0MCwgMCwgMCwgMCxcblx0XHRcdDAsIDAsIDAsIDAsXG5cdFx0XHQwLCAwLCAwLCAwXG5cdFx0XSk7XG5cdH1cblxuXHQvLyBTdGF0aWMgbWVtYmVyc1xuXHRzdGF0aWMgZ2V0IElERU5USVRZKCk6IE1hdDR4NCB7XG5cdFx0cmV0dXJuIG5ldyBNYXQ0eDQoKS5pZGVudGl0eSgpO1xuXHR9XG5cblx0c3RhdGljIGdldCBaRVJPKCk6IE1hdDR4NCB7XG5cdFx0cmV0dXJuIG5ldyBNYXQ0eDQoKS56ZXJvKCk7XG5cdH1cblxuXHQvLyBBY2Nlc3NvcnNcblx0c2V0IF8wMCh4OiBudW1iZXIpIHtcblx0XHR0aGlzLm1hdFswXSA9IHg7XG5cdH1cblxuXHRzZXQoY29sOiBudW1iZXIsIHJvdzogbnVtYmVyLCB2YWx1ZTogbnVtYmVyKTogTWF0NHg0IHtcblx0XHRpZihjb2wgPCAwIHx8IGNvbCA+IDMgfHwgcm93IDwgMCB8fCByb3cgPiAzKXtcblx0XHRcdHRocm93IGBFcnJvciAtIGluZGV4ICgke2NvbH0sICR7cm93fSkgaXMgb3V0IG9mIGJvdW5kcyBmb3IgTWF0NHg0YFxuXHRcdH1cblx0XHR0aGlzLm1hdFtyb3cqNCArIGNvbF0gPSB2YWx1ZTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0Z2V0KGNvbDogbnVtYmVyLCByb3c6IG51bWJlcik6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMubWF0W3Jvdyo0ICsgY29sXTtcblx0fVxuXG5cdHNldEFsbCguLi5pdGVtczogQXJyYXk8bnVtYmVyPik6IE1hdDR4NCB7XG5cdFx0dGhpcy5tYXQuc2V0KGl0ZW1zKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdGlkZW50aXR5KCk6IE1hdDR4NCB7XG5cdFx0cmV0dXJuIHRoaXMuc2V0QWxsKFxuXHRcdFx0MSwgMCwgMCwgMCxcblx0XHRcdDAsIDEsIDAsIDAsXG5cdFx0XHQwLCAwLCAxLCAwLFxuXHRcdFx0MCwgMCwgMCwgMVxuXHRcdClcblx0fVxuXG5cdHplcm8oKTogTWF0NHg0IHtcblx0XHRyZXR1cm4gdGhpcy5zZXRBbGwoXG5cdFx0XHQwLCAwLCAwLCAwLFxuXHRcdFx0MCwgMCwgMCwgMCxcblx0XHRcdDAsIDAsIDAsIDAsXG5cdFx0XHQwLCAwLCAwLCAwXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNYWtlcyB0aGlzIE1hdDR4NCBhIHJvdGF0aW9uIG1hdHJpeCBvZiB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiByYWRpYW5zIGNjd1xuXHQgKiBAcGFyYW0gelJhZGlhbnMgVGhlIG51bWJlciBvZiByYWRpYW5zIHRvIHJvdGF0ZVxuXHQgKiBAcmV0dXJucyB0aGlzIE1hdDR4NFxuXHQgKi9cblx0cm90YXRlKHpSYWRpYW5zOiBudW1iZXIpOiBNYXQ0eDQge1xuXHRcdHJldHVybiB0aGlzLnNldEFsbChcblx0XHRcdE1hdGguY29zKHpSYWRpYW5zKSwgLU1hdGguc2luKHpSYWRpYW5zKSwgXHQwLCAwLFxuXHRcdFx0TWF0aC5zaW4oelJhZGlhbnMpLCBNYXRoLmNvcyh6UmFkaWFucyksIFx0MCwgMCxcblx0XHRcdDAsIFx0XHRcdFx0XHQwLCBcdFx0XHRcdFx0XHQxLCAwLFxuXHRcdFx0MCwgXHRcdFx0XHRcdDAsIFx0XHRcdFx0XHRcdDAsIDFcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFR1cm5zIHRoaXMgTWF0NHg0IGludG8gYSB0cmFuc2xhdGlvbiBtYXRyaXggb2YgdGhlIHNwZWNpZmllZCB0cmFuc2xhdGlvblxuXHQgKiBAcGFyYW0gdHJhbnNsYXRpb24gVGhlIHRyYW5zbGF0aW9uIGluIHggYW5kIHlcblx0ICogQHJldHVybnMgdGhpcyBNYXQ0eDRcblx0ICovXG5cdHRyYW5zbGF0ZSh0cmFuc2xhdGlvbjogVmVjMiB8IEZsb2F0MzJBcnJheSk6IE1hdDR4NCB7XG5cdFx0Ly8gSWYgdHJhbnNsYXRpb24gaXMgYSB2ZWMsIGdldCBpdHMgYXJyYXlcblx0XHRpZih0cmFuc2xhdGlvbiBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0dHJhbnNsYXRpb24gPSB0cmFuc2xhdGlvbi50b0FycmF5KCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuc2V0QWxsKFxuXHRcdFx0MSwgMCwgMCwgdHJhbnNsYXRpb25bMF0sXG5cdFx0XHQwLCAxLCAwLCB0cmFuc2xhdGlvblsxXSxcblx0XHRcdDAsIDAsIDEsIDAsXG5cdFx0XHQwLCAwLCAwLCAxXG5cdFx0KTtcblx0fVxuXG5cdHNjYWxlKHNjYWxlOiBWZWMyIHwgRmxvYXQzMkFycmF5IHwgbnVtYmVyKTogTWF0NHg0IHtcblx0XHQvLyBNYWtlIHN1cmUgc2NhbGUgaXMgYSBmbG9hdDMyQXJyYXlcblx0XHRpZihzY2FsZSBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0c2NhbGUgPSBzY2FsZS50b0FycmF5KCk7XG5cdFx0fSBlbHNlIGlmKCEoc2NhbGUgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpKXtcblx0XHRcdHNjYWxlID0gbmV3IEZsb2F0MzJBcnJheShbc2NhbGUsIHNjYWxlXSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuc2V0QWxsKFxuXHRcdFx0c2NhbGVbMF0sIDAsIFx0XHQwLCAwLFxuXHRcdFx0MCwgXHRcdCAgc2NhbGVbMV0sIDAsIDAsXG5cdFx0XHQwLCBcdFx0ICAwLFx0XHQxLCAwLFxuXHRcdFx0MCwgXHRcdCAgMCxcdFx0MCwgMVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIG5ldyBNYXQ0eDQgdGhhdCByZXByZXNlbnRzIHRoZSByaWdodCBzaWRlIG11bHRpcGxpY2F0aW9uIFRISVMgeCBPVEhFUlxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIG90aGVyIE1hdDR4NCB0byBtdWx0aXBseSBieVxuXHQgKiBAcmV0dXJucyBhIG5ldyBNYXQ0eDQgY29udGFpbmluZyB0aGUgcHJvZHVjdCBvZiB0aGVzZSB0d28gTWF0NHg0c1xuXHQgKi9cblx0bXVsdChvdGhlcjogTWF0NHg0LCBvdXQ/OiBNYXQ0eDQpOiBNYXQ0eDQge1xuXHRcdGxldCB0ZW1wID0gbmV3IEZsb2F0MzJBcnJheSgxNik7XG5cblx0XHRmb3IobGV0IGkgPSAwOyBpIDwgNDsgaSsrKXtcblx0XHRcdGZvcihsZXQgaiA9IDA7IGogPCA0OyBqKyspe1xuXHRcdFx0XHRsZXQgdmFsdWUgPSAwO1xuXHRcdFx0XHRmb3IobGV0IGsgPSAwOyBrIDwgNDsgaysrKXtcblx0XHRcdFx0XHR2YWx1ZSArPSB0aGlzLmdldChrLCBpKSAqIG90aGVyLmdldChqLCBrKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0ZW1wW2oqNCArIGldICA9IHZhbHVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmKG91dCAhPT0gdW5kZWZpbmVkKXtcblx0XHRcdHJldHVybiBvdXQuc2V0QWxsKC4uLnRlbXApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gbmV3IE1hdDR4NCgpLnNldEFsbCguLi50ZW1wKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogTXVsdGlwbGllcyBhbGwgZ2l2ZW4gbWF0cmljaWVzIGluIG9yZGVyLiBlLmcuIE1VTFQoQSwgQiwgQykgLT4gQSpCKkNcblx0ICogQHBhcmFtIG1hdHMgQSBsaXN0IG9mIE1hdDR4NHMgdG8gbXVsdGlwbHkgaW4gb3JkZXJcblx0ICogQHJldHVybnMgQSBuZXcgTWF0NHg0IGhvbGRpbmcgdGhlIHJlc3VsdCBvZiB0aGUgb3BlcmF0aW9uXG5cdCAqL1xuXHRzdGF0aWMgTVVMVCguLi5tYXRzOiBBcnJheTxNYXQ0eDQ+KTogTWF0NHg0IHtcblx0XHQvLyBDcmVhdGUgYSBuZXcgYXJyYXlcblx0XHRsZXQgdGVtcCA9IE1hdDR4NC5JREVOVElUWTtcblxuXHRcdC8vIE11bHRpcGx5IGJ5IGV2ZXJ5IGFycmF5IGluIG9yZGVyLCBpbiBwbGFjZVxuXHRcdGZvcihsZXQgaSA9IDA7IGkgPCBtYXRzLmxlbmd0aDsgaSsrKXtcblx0XHRcdHRlbXAubXVsdChtYXRzW2ldLCB0ZW1wKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGVtcDtcblx0fVxuXG5cdHRvQXJyYXkoKTogRmxvYXQzMkFycmF5IHtcblx0XHRyZXR1cm4gdGhpcy5tYXQ7XG5cdH1cblxuXHR0b1N0cmluZygpOiBzdHJpbmcge1xuXHRcdHJldHVybiAgYHwke3RoaXMubWF0WzBdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzFdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzJdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzNdLnRvRml4ZWQoMil9fFxcbmAgKyBcblx0XHRcdFx0YHwke3RoaXMubWF0WzRdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzVdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzZdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzddLnRvRml4ZWQoMil9fFxcbmAgK1xuXHRcdFx0XHRgfCR7dGhpcy5tYXRbOF0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbOV0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbMTBdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzExXS50b0ZpeGVkKDIpfXxcXG5gICtcblx0XHRcdFx0YHwke3RoaXMubWF0WzEyXS50b0ZpeGVkKDIpfSwgJHt0aGlzLm1hdFsxM10udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbMTRdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzE1XS50b0ZpeGVkKDIpfXxgO1xuXHR9XG59IiwiaW1wb3J0IFBoeXNpY2FsIGZyb20gXCIuLi9JbnRlcmZhY2VzL1BoeXNpY2FsXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9WZWMyXCI7XG5pbXBvcnQgSGl0IGZyb20gXCIuL0hpdFwiO1xuXG4vKipcbiAqIEEgY2xhc3MgdGhhdCBjb250YWlucyB0aGUgYXJlYSBvZiBvdmVybGFwIG9mIHR3byBjb2xsaWRpbmcgb2JqZWN0cyB0byBhbGxvdyBmb3Igc29ydGluZyBieSB0aGUgcGh5c2ljcyBzeXN0ZW0uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFyZWFDb2xsaXNpb24ge1xuICAgIC8qKiBUaGUgYXJlYSBvZiB0aGUgb3ZlcmxhcCBmb3IgdGhlIGNvbGxpZGluZyBvYmplY3RzICovXG4gICAgYXJlYTogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBBQUJCIG9mIHRoZSBvdGhlciBjb2xsaWRlciBpbiB0aGlzIGNvbGxpc2lvbiAqL1xuICAgIGNvbGxpZGVyOiBBQUJCO1xuXG4gICAgLyoqIFR5cGUgb2YgdGhlIGNvbGxpc2lvbiAqL1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIC8qKiBUaGVyIG90aGVyIG9iamVjdCBpbiB0aGUgY29sbGlzaW9uICovXG4gICAgb3RoZXI6IFBoeXNpY2FsO1xuXG4gICAgLyoqIFRoZSB0aWxlLCBpZiB0aGlzIHdhcyBhIHRpbGVtYXAgY29sbGlzaW9uICovXG4gICAgdGlsZTogVmVjMjtcblxuICAgIC8qKiBUaGUgcGh5c2ljcyBoaXQgZm9yIHRoaXMgb2JqZWN0ICovXG4gICAgaGl0OiBIaXQ7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEFyZWFDb2xsaXNpb24gb2JqZWN0XG4gICAgICogQHBhcmFtIGFyZWEgVGhlIGFyZWEgb2YgdGhlIGNvbGxpc2lvblxuICAgICAqIEBwYXJhbSBjb2xsaWRlciBUaGUgb3RoZXIgY29sbGlkZXJcbiAgICAgKi9cblx0Y29uc3RydWN0b3IoYXJlYTogbnVtYmVyLCBjb2xsaWRlcjogQUFCQiwgb3RoZXI6IFBoeXNpY2FsLCB0eXBlOiBzdHJpbmcsIHRpbGU6IFZlYzIpe1xuXHRcdHRoaXMuYXJlYSA9IGFyZWE7XG4gICAgICAgIHRoaXMuY29sbGlkZXIgPSBjb2xsaWRlcjtcbiAgICAgICAgdGhpcy5vdGhlciA9IG90aGVyO1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLnRpbGUgPSB0aWxlO1xuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL1ZlYzJcIjtcblxuLyoqXG4gKiBBbiBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBkYXRhIGNvbGxlY3RlZCBmcm9tIGEgcGh5c2ljcyBoaXQgYmV0d2VlbiB0d28gZ2VvbWV0cmljIG9iamVjdHMuXG4gKiBJbnNwaXJlZCBieSB0aGUgaGVscGZ1bCBjb2xsaXNpb24gZG9jdW1lbnRhdGlvbiBAbGluayhoZXJlKShodHRwczovL25vb25hdC5naXRodWIuaW8vaW50ZXJzZWN0LykuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEhpdCB7XG4gICAgLyoqIFRoZSB0aW1lIG9mIHRoZSBjb2xsaXNpb24uIE9ubHkgbnVtYmVycyAwIHRocm91Z2ggMSBoYXBwZW4gaW4gdGhpcyBmcmFtZS4gKi9cbiAgICB0aW1lOiBudW1iZXI7XG4gICAgLyoqIFRoZSBuZWFyIHRpbWVzIG9mIHRoZSBjb2xsaXNpb24gKi9cbiAgICBuZWFyVGltZXM6IFZlYzIgPSBWZWMyLlpFUk87XG4gICAgLyoqIFRoZSBwb3NpdGlvbiBvZiB0aGUgY29sbGlzaW9uICovXG4gICAgcG9zOiBWZWMyID0gVmVjMi5aRVJPO1xuICAgIC8qKiBUaGUgb3ZlcmxhcCBkaXN0YW5jZSBvZiB0aGUgaGl0ICovXG4gICAgZGVsdGE6IFZlYzIgPSBWZWMyLlpFUk87XG4gICAgLyoqIFRoZSBub3JtYWwgdmVjdG9yIG9mIHRoZSBoaXQgKi9cbiAgICBub3JtYWw6IFZlYzIgPSBWZWMyLlpFUk87XG59IiwiaW1wb3J0IENvbGxlY3Rpb24gZnJvbSBcIi4vQ29sbGVjdGlvblwiO1xuXG4vKipcbiAqIEEgRklGTyBxdWV1ZSB3aXRoIGVsZW1lbnRzIG9mIHR5cGUgVFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBRdWV1ZTxUPiBpbXBsZW1lbnRzIENvbGxlY3Rpb24ge1xuICAgIC8qKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIFF1ZXVlICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBNQVhfRUxFTUVOVFM6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIHF1ZXVlICovXG4gICAgcHJpdmF0ZSBxOiBBcnJheTxUPjtcbiAgICBcbiAgICAvKiogVGhlIGhlYWQgb2YgdGhlIHF1ZXVlICovXG4gICAgcHJpdmF0ZSBoZWFkOiBudW1iZXI7XG4gICAgXG4gICAgLyoqIFRoZSB0YWlsIG9mIHRoZSBxdWV1ZSAqL1xuICAgIHByaXZhdGUgdGFpbDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBjdXJyZW50IG51bWJlciBvZiBpdGVtcyBpbiB0aGUgcXVldWUgKi9cbiAgICBwcml2YXRlIHNpemU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdHMgYSBuZXcgcXVldWVcbiAgICAgKiBAcGFyYW0gbWF4RWxlbWVudHMgVGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgc3RhY2tcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihtYXhFbGVtZW50czogbnVtYmVyID0gMTAwKXtcbiAgICAgICAgdGhpcy5NQVhfRUxFTUVOVFMgPSBtYXhFbGVtZW50cztcbiAgICAgICAgdGhpcy5xID0gbmV3IEFycmF5KHRoaXMuTUFYX0VMRU1FTlRTKTtcbiAgICAgICAgdGhpcy5oZWFkID0gMDtcbiAgICAgICAgdGhpcy50YWlsID0gMDtcbiAgICAgICAgdGhpcy5zaXplID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGFuIGl0ZW0gdG8gdGhlIGJhY2sgb2YgdGhlIHF1ZXVlXG4gICAgICogQHBhcmFtIGl0ZW0gVGhlIGl0ZW0gdG8gYWRkIHRvIHRoZSBiYWNrIG9mIHRoZSBxdWV1ZVxuICAgICAqL1xuICAgIGVucXVldWUoaXRlbTogVCk6IHZvaWR7XG4gICAgICAgIGlmKCh0aGlzLnRhaWwgKyAxKSAlIHRoaXMuTUFYX0VMRU1FTlRTID09PSB0aGlzLmhlYWQpe1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUXVldWUgZnVsbCAtIGNhbm5vdCBhZGQgZWxlbWVudFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2l6ZSArPSAxO1xuICAgICAgICB0aGlzLnFbdGhpcy50YWlsXSA9IGl0ZW07XG4gICAgICAgIHRoaXMudGFpbCA9ICh0aGlzLnRhaWwgKyAxKSAlIHRoaXMuTUFYX0VMRU1FTlRTO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBpdGVtIGZyb20gdGhlIGZyb250IG9mIHRoZSBxdWV1ZVxuICAgICAqIEByZXR1cm5zIFRoZSBpdGVtIGF0IHRoZSBmcm9udCBvZiB0aGUgcXVldWVcbiAgICAgKi9cbiAgICBkZXF1ZXVlKCk6IFQge1xuICAgICAgICBpZih0aGlzLmhlYWQgPT09IHRoaXMudGFpbCl7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJRdWV1ZSBlbXB0eSAtIGNhbm5vdCByZW1vdmUgZWxlbWVudFwiKTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgdGhpcy5zaXplIC09IDE7XG4gICAgICAgIGxldCBpdGVtID0gdGhpcy5xW3RoaXMuaGVhZF07XG4gICAgICAgIC8vIE5vdyBkZWxldGUgdGhlIGl0ZW1cbiAgICAgICAgZGVsZXRlIHRoaXMucVt0aGlzLmhlYWRdO1xuICAgICAgICB0aGlzLmhlYWQgPSAodGhpcy5oZWFkICsgMSkgJSB0aGlzLk1BWF9FTEVNRU5UUztcbiAgICAgICAgXG4gICAgICAgIHJldHVybiBpdGVtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGl0ZW0gYXQgdGhlIGZyb250IG9mIHRoZSBxdWV1ZSwgYnV0IGRvZXMgbm90IHJlbW92ZSBpdFxuICAgICAqIEByZXR1cm5zIFRoZSBpdGVtIGF0IHRoZSBmcm9udCBvZiB0aGUgcXVldWVcbiAgICAgKi9cbiAgICBwZWVrTmV4dCgpOiBUIHtcbiAgICAgICAgaWYodGhpcy5oZWFkID09PSB0aGlzLnRhaWwpe1xuICAgICAgICAgICAgdGhyb3cgXCJRdWV1ZSBlbXB0eSAtIGNhbm5vdCBnZXQgZWxlbWVudFwiXG4gICAgICAgIH1cblxuICAgICAgICBsZXQgaXRlbSA9IHRoaXMucVt0aGlzLmhlYWRdO1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSBxdWV1ZSBoYXMgaXRlbXMgaW4gaXQsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgd2hldGhlciBvciBub3QgdGhpcyBxdWV1ZSBoYXMgaXRlbXNcbiAgICAgKi9cbiAgICBoYXNJdGVtcygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGVhZCAhPT0gdGhpcy50YWlsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgcXVldWUuXG4gICAgICogQHJldHVybnMgVGhlIHNpemUgb2YgdGhlIHF1ZXVlXG4gICAgICovXG4gICAgZ2V0U2l6ZSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zaXplO1xuICAgIH1cblxuICAgIC8vIEBpbXBsZW1lbnRlZFxuICAgIGNsZWFyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmZvckVhY2goKGl0ZW0sIGluZGV4KSA9PiBkZWxldGUgdGhpcy5xW2luZGV4XSk7XG4gICAgICAgIHRoaXMuc2l6ZSA9IDA7XG4gICAgICAgIHRoaXMuaGVhZCA9IHRoaXMudGFpbDtcbiAgICB9XG5cbiAgICAvLyBAaW1wbGVtZW50ZWRcbiAgICBmb3JFYWNoKGZ1bmM6IChpdGVtOiBULCBpbmRleD86IG51bWJlcikgPT4gdm9pZCk6IHZvaWQge1xuICAgICAgICBsZXQgaSA9IHRoaXMuaGVhZDtcbiAgICAgICAgd2hpbGUoaSAhPT0gdGhpcy50YWlsKXtcbiAgICAgICAgICAgIGZ1bmModGhpcy5xW2ldLCBpKTtcbiAgICAgICAgICAgIGkgPSAoaSArIDEpICUgdGhpcy5NQVhfRUxFTUVOVFM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGlzIHF1ZXVlIGludG8gYSBzdHJpbmcgZm9ybWF0XG4gICAgICogQHJldHVybnMgQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoaXMgcXVldWVcbiAgICAgKi9cbiAgICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgICAgICBsZXQgcmV0dmFsID0gXCJcIjtcblxuICAgICAgICB0aGlzLmZvckVhY2goIChpdGVtLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgbGV0IHN0ciA9IGl0ZW0udG9TdHJpbmcoKVxuICAgICAgICAgICAgaWYoaW5kZXggIT09IDApe1xuICAgICAgICAgICAgICAgIHN0ciArPSBcIiAtPiBcIlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dmFsID0gc3RyICsgcmV0dmFsO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gXCJUb3AgLT4gXCIgKyByZXR2YWw7XG4gICAgfVxufSIsIi8qKiBBIGNvbnRhaW5lciBmb3IgaW5mbyBhYm91dCBhIHdlYkdMIHNoYWRlciBwcm9ncmFtICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWJHTFByb2dyYW1UeXBlIHtcblx0LyoqIEEgd2ViR0wgcHJvZ3JhbSAqL1xuXHRwcm9ncmFtOiBXZWJHTFByb2dyYW07XG5cdFxuXHQvKiogQSB2ZXJ0ZXggc2hhZGVyICovXG5cdHZlcnRleFNoYWRlcjogV2ViR0xTaGFkZXI7XG5cblx0LyoqIEEgZnJhZ21lbnQgc2hhZGVyICovXG5cdGZyYWdtZW50U2hhZGVyOiBXZWJHTFNoYWRlcjtcblxuXHQvKipcblx0ICogRGVsZXRlcyB0aGlzIHNoYWRlciBwcm9ncmFtXG5cdCAqL1xuXHRkZWxldGUoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IHZvaWQge1xuXHRcdC8vIENsZWFuIHVwIGFsbCBhc3BlY3RzIG9mIHRoaXMgcHJvZ3JhbVxuXHRcdGlmKHRoaXMucHJvZ3JhbSl7XG5cdFx0XHRnbC5kZWxldGVQcm9ncmFtKHRoaXMucHJvZ3JhbSk7XG5cdFx0fVxuXHRcdFx0XG5cdFx0aWYodGhpcy52ZXJ0ZXhTaGFkZXIpe1xuXHRcdFx0Z2wuZGVsZXRlU2hhZGVyKHRoaXMudmVydGV4U2hhZGVyKTtcblx0XHR9XG5cblx0XHRpZih0aGlzLmZyYWdtZW50U2hhZGVyKXtcblx0XHRcdGdsLmRlbGV0ZVNoYWRlcih0aGlzLmZyYWdtZW50U2hhZGVyKTtcblx0XHR9XG5cdH1cbn0iLCJpbXBvcnQgU2hhcGUgZnJvbSBcIi4vU2hhcGVcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9WZWMyXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCBDaXJjbGUgZnJvbSBcIi4vQ2lyY2xlXCI7XG5pbXBvcnQgSGl0IGZyb20gXCIuLi9QaHlzaWNzL0hpdFwiO1xuXG4vKipcbiAqIEFuIEF4aXMtQWxpZ25lZCBCb3VuZGluZyBCb3guIEluIG90aGVyIHdvcmRzLCBhIHJlY3RhbmdsZSB0aGF0IGlzIGFsd2F5cyBhbGlnbmVkIHRvIHRoZSB4LXkgZ3JpZC5cbiAqIEluc3BpcmVkIGJ5IHRoZSBoZWxwZnVsIGNvbGxpc2lvbiBkb2N1bWVudGF0aW9uIEBsaW5rKGhlcmUpKGh0dHBzOi8vbm9vbmF0LmdpdGh1Yi5pby9pbnRlcnNlY3QvKS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQUFCQiBleHRlbmRzIFNoYXBlIHtcbiAgICBjZW50ZXI6IFZlYzI7XG4gICAgaGFsZlNpemU6IFZlYzI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEFBQkJcbiAgICAgKiBAcGFyYW0gY2VudGVyIFRoZSBjZW50ZXIgb2YgdGhlIEFBQkJcbiAgICAgKiBAcGFyYW0gaGFsZlNpemUgVGhlIGhhbGYgc2l6ZSBvZiB0aGUgQUFCQiAtIFRoZSBkaXN0YW5jZSBmcm9tIHRoZSBjZW50ZXIgdG8gYW4gZWRnZSBpbiB4IGFuZCB5XG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2VudGVyPzogVmVjMiwgaGFsZlNpemU/OiBWZWMyKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5jZW50ZXIgPSBjZW50ZXIgPyBjZW50ZXIgOiBuZXcgVmVjMigwLCAwKTtcbiAgICAgICAgdGhpcy5oYWxmU2l6ZSA9IGhhbGZTaXplID8gaGFsZlNpemUgOiBuZXcgVmVjMigwLCAwKTtcbiAgICB9XG5cbiAgICAvKiogUmV0dXJucyBhIHBvaW50IHJlcHJlc2VudGluZyB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSBBQUJCICovXG4gICAgZ2V0IHRvcExlZnQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLmxlZnQsIHRoaXMudG9wKVxuICAgIH1cblxuICAgIC8qKiBSZXR1cm5zIGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSB0b3AgcmlnaHQgY29ybmVyIG9mIHRoZSBBQUJCICovXG4gICAgZ2V0IHRvcFJpZ2h0KCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy5yaWdodCwgdGhpcy50b3ApXG4gICAgfVxuXG4gICAgLyoqIFJldHVybnMgYSBwb2ludCByZXByZXNlbnRpbmcgdGhlIGJvdHRvbSBsZWZ0IGNvcm5lciBvZiB0aGUgQUFCQiAqL1xuICAgIGdldCBib3R0b21MZWZ0KCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy5sZWZ0LCB0aGlzLmJvdHRvbSlcbiAgICB9XG5cbiAgICAvKiogUmV0dXJucyBhIHBvaW50IHJlcHJlc2VudGluZyB0aGUgYm90dG9tIHJpZ2h0IGNvcm5lciBvZiB0aGUgQUFCQiAqL1xuICAgIGdldCBib3R0b21SaWdodCgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMucmlnaHQsIHRoaXMuYm90dG9tKVxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGdldEJvdW5kaW5nUmVjdCgpOiBBQUJCIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xvbmUoKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBnZXRCb3VuZGluZ0NpcmNsZSgpOiBDaXJjbGUge1xuICAgICAgICBsZXQgciA9IE1hdGgubWF4KHRoaXMuaHcsIHRoaXMuaGgpXG4gICAgICAgIHJldHVybiBuZXcgQ2lyY2xlKHRoaXMuY2VudGVyLmNsb25lKCksIHIpO1xuICAgIH1cblxuICAgIC8vIEBkZXByZWNhdGVkXG4gICAgZ2V0SGFsZlNpemUoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbGZTaXplO1xuICAgIH1cblxuICAgIC8vIEBkZXByZWNhdGVkXG4gICAgc2V0SGFsZlNpemUoaGFsZlNpemU6IFZlYzIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5oYWxmU2l6ZSA9IGhhbGZTaXplO1xuICAgIH1cblxuICAgIC8vIFRPRE8gLSBtb3ZlIHRoZXNlIGFsbCB0byB0aGUgU2hhcGUgY2xhc3NcbiAgICAvKipcbiAgICAgKiBBIHNpbXBsZSBib29sZWFuIGNoZWNrIG9mIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIGEgcG9pbnRcbiAgICAgKiBAcGFyYW0gcG9pbnQgVGhlIHBvaW50IHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoaXMgQUFCQiBjb250YWlucyB0aGUgc3BlY2lmaWVkIHBvaW50XG4gICAgICovXG4gICAgY29udGFpbnNQb2ludChwb2ludDogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gcG9pbnQueCA+PSB0aGlzLnggLSB0aGlzLmh3ICYmIHBvaW50LnggPD0gdGhpcy54ICsgdGhpcy5od1xuICAgICAgICAgICAgJiYgcG9pbnQueSA+PSB0aGlzLnkgLSB0aGlzLmhoICYmIHBvaW50LnkgPD0gdGhpcy55ICsgdGhpcy5oaFxuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBBIHNpbXBsZSBib29sZWFuIGNoZWNrIG9mIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIGEgcG9pbnRcbiAgICAgKiBAcGFyYW0gcG9pbnQgVGhlIHBvaW50IHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoaXMgQUFCQiBjb250YWlucyB0aGUgc3BlY2lmaWVkIHBvaW50XG4gICAgICovXG4gICAgaW50ZXJzZWN0UG9pbnQocG9pbnQ6IFZlYzIpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IGR4ID0gcG9pbnQueCAtIHRoaXMueDtcbiAgICAgICAgbGV0IHB4ID0gdGhpcy5odyAtIE1hdGguYWJzKGR4KTtcbiAgICAgICAgXG4gICAgICAgIGlmKHB4IDw9IDApe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGR5ID0gcG9pbnQueSAtIHRoaXMueTtcbiAgICAgICAgbGV0IHB5ID0gdGhpcy5oaCAtIE1hdGguYWJzKGR5KTtcblxuICAgICAgICBpZihweSA8PSAwKXtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgYm9vbGVhbiBjaGVjayBvZiB3aGV0aGVyIHRoaXMgQUFCQiBjb250YWlucyBhIHBvaW50IHdpdGggc29mdCBsZWZ0IGFuZCB0b3AgYm91bmRhcmllcy5cbiAgICAgKiBJbiBvdGhlciB3b3JkcywgaWYgdGhlIHRvcCBsZWZ0IGlzICgwLCAwKSwgdGhlIHBvaW50ICgwLCAwKSBpcyBub3QgaW4gdGhlIEFBQkJcbiAgICAgKiBAcGFyYW0gcG9pbnQgVGhlIHBvaW50IHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoaXMgQUFCQiBjb250YWlucyB0aGUgc3BlY2lmaWVkIHBvaW50XG4gICAgICovXG4gICAgY29udGFpbnNQb2ludFNvZnQocG9pbnQ6IFZlYzIpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHBvaW50LnggPiB0aGlzLnggLSB0aGlzLmh3ICYmIHBvaW50LnggPD0gdGhpcy54ICsgdGhpcy5od1xuICAgICAgICAgICAgJiYgcG9pbnQueSA+IHRoaXMueSAtIHRoaXMuaGggJiYgcG9pbnQueSA8PSB0aGlzLnkgKyB0aGlzLmhoXG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBkYXRhIGZyb20gdGhlIGludGVyc2VjdGlvbiBvZiB0aGlzIEFBQkIgd2l0aCBhIGxpbmUgc2VnbWVudCBmcm9tIGEgcG9pbnQgaW4gYSBkaXJlY3Rpb25cbiAgICAgKiBAcGFyYW0gcG9pbnQgVGhlIHBvaW50IHRoYXQgdGhlIGxpbmUgc2VnbWVudCBzdGFydHMgZnJvbVxuICAgICAqIEBwYXJhbSBkZWx0YSBUaGUgZGlyZWN0aW9uIGFuZCBkaXN0YW5jZSBvZiB0aGUgc2VnbWVudFxuICAgICAqIEBwYXJhbSBwYWRkaW5nIFBhZHMgdGhlIEFBQkIgdG8gbWFrZSBpdCB3aWRlciBmb3IgdGhlIGludGVyc2VjdGlvbiB0ZXN0XG4gICAgICogQHJldHVybnMgVGhlIEhpdCBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBpbnRlcnNlY3Rpb24sIG9yIG51bGwgaWYgdGhlcmUgd2FzIG5vIGludGVyc2VjdGlvblxuICAgICAqL1xuICAgIGludGVyc2VjdFNlZ21lbnQocG9pbnQ6IFZlYzIsIGRlbHRhOiBWZWMyLCBwYWRkaW5nPzogVmVjMik6IEhpdCB7XG4gICAgICAgIGxldCBwYWRkaW5nWCA9IHBhZGRpbmcgPyBwYWRkaW5nLnggOiAwO1xuICAgICAgICBsZXQgcGFkZGluZ1kgPSBwYWRkaW5nID8gcGFkZGluZy55IDogMDtcblxuICAgICAgICBsZXQgc2NhbGVYID0gMS9kZWx0YS54O1xuICAgICAgICBsZXQgc2NhbGVZID0gMS9kZWx0YS55O1xuXG4gICAgICAgIGxldCBzaWduWCA9IE1hdGhVdGlscy5zaWduKHNjYWxlWCk7XG4gICAgICAgIGxldCBzaWduWSA9IE1hdGhVdGlscy5zaWduKHNjYWxlWSk7XG5cbiAgICAgICAgbGV0IHRuZWFyeCA9IHNjYWxlWCoodGhpcy54IC0gc2lnblgqKHRoaXMuaHcgKyBwYWRkaW5nWCkgLSBwb2ludC54KTtcbiAgICAgICAgbGV0IHRuZWFyeSA9IHNjYWxlWSoodGhpcy55IC0gc2lnblkqKHRoaXMuaGggKyBwYWRkaW5nWSkgLSBwb2ludC55KTtcbiAgICAgICAgbGV0IHRmYXJ4ID0gc2NhbGVYKih0aGlzLnggKyBzaWduWCoodGhpcy5odyArIHBhZGRpbmdYKSAtIHBvaW50LngpO1xuICAgICAgICBsZXQgdGZhcnkgPSBzY2FsZVkqKHRoaXMueSArIHNpZ25ZKih0aGlzLmhoICsgcGFkZGluZ1kpIC0gcG9pbnQueSk7XG4gICAgICAgIFxuICAgICAgICBpZih0bmVhcnggPiB0ZmFyeSB8fCB0bmVhcnkgPiB0ZmFyeCl7XG4gICAgICAgICAgICAvLyBXZSBhcmVuJ3QgY29sbGlkaW5nIC0gd2UgY2xlYXIgb25lIGF4aXMgYmVmb3JlIGludGVyc2VjdGluZyBhbm90aGVyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0bmVhciA9IE1hdGgubWF4KHRuZWFyeCwgdG5lYXJ5KTtcblxuICAgICAgICAvLyBEb3VibGUgY2hlY2sgZm9yIE5hTnNcbiAgICAgICAgaWYodG5lYXJ4ICE9PSB0bmVhcngpe1xuICAgICAgICAgICAgdG5lYXIgPSB0bmVhcnk7XG4gICAgICAgIH0gZWxzZSBpZiAodG5lYXJ5ICE9PSB0bmVhcnkpe1xuICAgICAgICAgICAgdG5lYXIgPSB0bmVhcng7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdGZhciA9IE1hdGgubWluKHRmYXJ4LCB0ZmFyeSk7XG5cbiAgICAgICAgaWYodG5lYXIgPT09IC1JbmZpbml0eSl7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRuZWFyID49IDEgfHwgdGZhciA8PSAwKXtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2UgYXJlIGNvbGxpZGluZ1xuICAgICAgICBsZXQgaGl0ID0gbmV3IEhpdCgpO1xuICAgICAgICBoaXQudGltZSA9IE1hdGhVdGlscy5jbGFtcDAxKHRuZWFyKTtcbiAgICAgICAgaGl0Lm5lYXJUaW1lcy54ID0gdG5lYXJ4O1xuICAgICAgICBoaXQubmVhclRpbWVzLnkgPSB0bmVhcnk7XG5cbiAgICAgICAgaWYodG5lYXJ4ID4gdG5lYXJ5KXtcbiAgICAgICAgICAgIC8vIFdlIGhpdCBvbiB0aGUgbGVmdCBvciByaWdodCBzaXplXG4gICAgICAgICAgICBoaXQubm9ybWFsLnggPSAtc2lnblg7XG4gICAgICAgICAgICBoaXQubm9ybWFsLnkgPSAwO1xuICAgICAgICB9IGVsc2UgaWYoTWF0aC5hYnModG5lYXJ4IC0gdG5lYXJ5KSA8IDAuMDAwMSl7XG4gICAgICAgICAgICAvLyBXZSBoaXQgb24gdGhlIGNvcm5lclxuICAgICAgICAgICAgaGl0Lm5vcm1hbC54ID0gLXNpZ25YO1xuICAgICAgICAgICAgaGl0Lm5vcm1hbC55ID0gLXNpZ25ZO1xuICAgICAgICAgICAgaGl0Lm5vcm1hbC5ub3JtYWxpemUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFdlIGhpdCBvbiB0aGUgdG9wIG9yIGJvdHRvbVxuICAgICAgICAgICAgaGl0Lm5vcm1hbC54ID0gMDtcbiAgICAgICAgICAgIGhpdC5ub3JtYWwueSA9IC1zaWduWTtcbiAgICAgICAgfVxuXG4gICAgICAgIGhpdC5kZWx0YS54ID0gKDEuMCAtIGhpdC50aW1lKSAqIC1kZWx0YS54O1xuICAgICAgICBoaXQuZGVsdGEueSA9ICgxLjAgLSBoaXQudGltZSkgKiAtZGVsdGEueTtcbiAgICAgICAgaGl0LnBvcy54ID0gcG9pbnQueCArIGRlbHRhLnggKiBoaXQudGltZTtcbiAgICAgICAgaGl0LnBvcy55ID0gcG9pbnQueSArIGRlbHRhLnkgKiBoaXQudGltZTtcblxuICAgICAgICByZXR1cm4gaGl0O1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIG92ZXJsYXBzKG90aGVyOiBTaGFwZSk6IGJvb2xlYW4ge1xuICAgICAgICBpZihvdGhlciBpbnN0YW5jZW9mIEFBQkIpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub3ZlcmxhcHNBQUJCKG90aGVyKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBcIk92ZXJsYXAgbm90IGRlZmluZWQgYmV0d2VlbiB0aGVzZSBzaGFwZXMuXCJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNpbXBsZSBib29sZWFuIGNoZWNrIG9mIHdoZXRoZXIgdGhpcyBBQUJCIG92ZXJsYXBzIGFub3RoZXJcbiAgICAgKiBAcGFyYW0gb3RoZXIgVGhlIG90aGVyIEFBQkIgdG8gY2hlY2sgYWdhaW5zdFxuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhpcyBBQUJCIG92ZXJsYXBzIHRoZSBvdGhlciwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgcHJvdGVjdGVkIG92ZXJsYXBzQUFCQihvdGhlcjogQUFCQik6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgZHggPSBvdGhlci54IC0gdGhpcy54O1xuICAgICAgICBsZXQgcHggPSB0aGlzLmh3ICsgb3RoZXIuaHcgLSBNYXRoLmFicyhkeCk7XG4gICAgICAgIFxuICAgICAgICBpZihweCA8PSAwKXtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBkeSA9IG90aGVyLnkgLSB0aGlzLnk7XG4gICAgICAgIGxldCBweSA9IHRoaXMuaGggKyBvdGhlci5oaCAtIE1hdGguYWJzKGR5KTtcblxuICAgICAgICBpZihweSA8PSAwKXtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERldGVybWluZXMgd2hldGhlciB0aGVzZSBBQUJCcyBhcmUgSlVTVCB0b3VjaGluZyAtIG5vdCBvdmVybGFwcGluZy5cbiAgICAgKiBWZWMyLnggaXMgLTEgaWYgdGhlIG90aGVyIGlzIHRvIHRoZSBsZWZ0LCAxIGlmIHRvIHRoZSByaWdodC5cbiAgICAgKiBMaWtld2lzZSwgVmVjMi55IGlzIC0xIGlmIHRoZSBvdGhlciBpcyBvbiB0b3AsIDEgaWYgb24gYm90dG9tLlxuICAgICAqIEBwYXJhbSBvdGhlciBUaGUgb3RoZXIgQUFCQiB0byBjaGVja1xuICAgICAqIEByZXR1cm5zIFRoZSBjb2xsaXNpb24gc2lkZXMgc3RvcmVkIGluIGEgVmVjMiBpZiB0aGUgQUFCQnMgYXJlIHRvdWNoaW5nLCBudWxsIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHRvdWNoZXNBQUJCKG90aGVyOiBBQUJCKTogVmVjMiB7XG4gICAgICAgIGxldCBkeCA9IG90aGVyLnggLSB0aGlzLng7XG4gICAgICAgIGxldCBweCA9IHRoaXMuaHcgKyBvdGhlci5odyAtIE1hdGguYWJzKGR4KTtcblxuICAgICAgICBsZXQgZHkgPSBvdGhlci55IC0gdGhpcy55O1xuICAgICAgICBsZXQgcHkgPSB0aGlzLmhoICsgb3RoZXIuaGggLSBNYXRoLmFicyhkeSk7XG5cbiAgICAgICAgLy8gSWYgb25lIGF4aXMgaXMganVzdCB0b3VjaGluZyBhbmQgdGhlIG90aGVyIGlzIG92ZXJsYXBwaW5nLCB0cnVlXG4gICAgICAgIGlmKChweCA9PT0gMCAmJiBweSA+PSAwKSB8fCAocHkgPT09IDAgJiYgcHggPj0gMCkpe1xuICAgICAgICAgICAgbGV0IHJldCA9IG5ldyBWZWMyKCk7XG5cbiAgICAgICAgICAgIGlmKHB4ID09PSAwKXtcbiAgICAgICAgICAgICAgICByZXQueCA9IG90aGVyLnggPCB0aGlzLnggPyAtMSA6IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKHB5ID09PSAwKXtcbiAgICAgICAgICAgICAgICByZXQueSA9IG90aGVyLnkgPCB0aGlzLnkgPyAtMSA6IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERldGVybWluZXMgd2hldGhlciB0aGVzZSBBQUJCcyBhcmUgSlVTVCB0b3VjaGluZyAtIG5vdCBvdmVybGFwcGluZy5cbiAgICAgKiBBbHNvLCBpZiB0aGV5IGFyZSBvbmx5IHRvdWNoaW5nIGNvcm5lcnMsIHRoZXkgYXJlIGNvbnNpZGVyZWQgbm90IHRvdWNoaW5nLlxuICAgICAqIFZlYzIueCBpcyAtMSBpZiB0aGUgb3RoZXIgaXMgdG8gdGhlIGxlZnQsIDEgaWYgdG8gdGhlIHJpZ2h0LlxuICAgICAqIExpa2V3aXNlLCBWZWMyLnkgaXMgLTEgaWYgdGhlIG90aGVyIGlzIG9uIHRvcCwgMSBpZiBvbiBib3R0b20uXG4gICAgICogQHBhcmFtIG90aGVyIFRoZSBvdGhlciBBQUJCIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgVGhlIHNpZGUgb2YgdGhlIHRvdWNoLCBzdG9yZWQgYXMgYSBWZWMyLCBvciBudWxsIGlmIHRoZXJlIGlzIG5vIHRvdWNoXG4gICAgICovXG4gICAgdG91Y2hlc0FBQkJXaXRob3V0Q29ybmVycyhvdGhlcjogQUFCQik6IFZlYzIge1xuICAgICAgICBsZXQgZHggPSBvdGhlci54IC0gdGhpcy54O1xuICAgICAgICBsZXQgcHggPSB0aGlzLmh3ICsgb3RoZXIuaHcgLSBNYXRoLmFicyhkeCk7XG5cbiAgICAgICAgbGV0IGR5ID0gb3RoZXIueSAtIHRoaXMueTtcbiAgICAgICAgbGV0IHB5ID0gdGhpcy5oaCArIG90aGVyLmhoIC0gTWF0aC5hYnMoZHkpO1xuXG4gICAgICAgIC8vIElmIG9uZSBheGlzIGlzIHRvdWNoaW5nLCBhbmQgdGhlIG90aGVyIGlzIHN0cmljdGx5IG92ZXJsYXBwaW5nXG4gICAgICAgIGlmKChweCA9PT0gMCAmJiBweSA+IDApIHx8IChweSA9PT0gMCAmJiBweCA+IDApKXtcbiAgICAgICAgICAgIGxldCByZXQgPSBuZXcgVmVjMigpO1xuXG4gICAgICAgICAgICBpZihweCA9PT0gMCl7XG4gICAgICAgICAgICAgICAgcmV0LnggPSBvdGhlci54IDwgdGhpcy54ID8gLTEgOiAxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXQueSA9IG90aGVyLnkgPCB0aGlzLnkgPyAtMSA6IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXQ7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgYXJlYSBvZiB0aGUgb3ZlcmxhcCBiZXR3ZWVuIHRoaXMgQUFCQiBhbmQgYW5vdGhlclxuICAgICAqIEBwYXJhbSBvdGhlciBUaGUgb3RoZXIgQUFCQlxuICAgICAqIEByZXR1cm5zIFRoZSBhcmVhIG9mIHRoZSBvdmVybGFwIGJldHdlZW4gdGhlIEFBQkJzXG4gICAgICovXG4gICAgb3ZlcmxhcEFyZWEob3RoZXI6IEFBQkIpOiBudW1iZXIge1xuICAgICAgICBsZXQgbGVmdHggPSBNYXRoLm1heCh0aGlzLnggLSB0aGlzLmh3LCBvdGhlci54IC0gb3RoZXIuaHcpO1xuICAgICAgICBsZXQgcmlnaHR4ID0gTWF0aC5taW4odGhpcy54ICsgdGhpcy5odywgb3RoZXIueCArIG90aGVyLmh3KTtcbiAgICAgICAgbGV0IGR4ID0gcmlnaHR4IC0gbGVmdHg7XG5cbiAgICAgICAgbGV0IGxlZnR5ID0gTWF0aC5tYXgodGhpcy55IC0gdGhpcy5oaCwgb3RoZXIueSAtIG90aGVyLmhoKTtcbiAgICAgICAgbGV0IHJpZ2h0eSA9IE1hdGgubWluKHRoaXMueSArIHRoaXMuaGgsIG90aGVyLnkgKyBvdGhlci5oaCk7XG4gICAgICAgIGxldCBkeSA9IHJpZ2h0eSAtIGxlZnR5O1xuXG4gICAgICAgIGlmKGR4IDwgMCB8fCBkeSA8IDApIHJldHVybiAwO1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGR4KmR5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vdmVzIGFuZCByZXNpemVzIHRoaXMgcmVjdCBmcm9tIGl0cyBjdXJyZW50IHBvc2l0aW9uIHRvIHRoZSBwb3NpdGlvbiBzcGVjaWZpZWRcbiAgICAgKiBAcGFyYW0gdmVsb2NpdHkgVGhlIG1vdmVtZW50IG9mIHRoZSByZWN0IGZyb20gaXRzIHBvc2l0aW9uXG4gICAgICogQHBhcmFtIGZyb21Qb3NpdGlvbiBBIHBvc2l0aW9uIHNwZWNpZmllZCB0byBiZSB0aGUgc3RhcnRpbmcgcG9pbnQgb2Ygc3dlZXBpbmdcbiAgICAgKiBAcGFyYW0gaGFsZlNpemUgVGhlIGhhbGZTaXplIG9mIHRoZSBzd2VlcGluZyByZWN0IFxuICAgICAqL1xuICAgIHN3ZWVwKHZlbG9jaXR5OiBWZWMyLCBmcm9tUG9zaXRpb24/OiBWZWMyLCBoYWxmU2l6ZT86IFZlYzIpOiB2b2lkIHtcbiAgICAgICAgaWYoIWZyb21Qb3NpdGlvbil7XG4gICAgICAgICAgICBmcm9tUG9zaXRpb24gPSB0aGlzLmNlbnRlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFoYWxmU2l6ZSl7XG4gICAgICAgICAgICBoYWxmU2l6ZSA9IHRoaXMuaGFsZlNpemU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgY2VudGVyWCA9IGZyb21Qb3NpdGlvbi54ICsgdmVsb2NpdHkueC8yO1xuICAgICAgICBsZXQgY2VudGVyWSA9IGZyb21Qb3NpdGlvbi55ICsgdmVsb2NpdHkueS8yO1xuXG4gICAgICAgIGxldCBtaW5YID0gTWF0aC5taW4oZnJvbVBvc2l0aW9uLnggLSBoYWxmU2l6ZS54LCBmcm9tUG9zaXRpb24ueCArIHZlbG9jaXR5LnggLSBoYWxmU2l6ZS54KTtcbiAgICAgICAgbGV0IG1pblkgPSBNYXRoLm1pbihmcm9tUG9zaXRpb24ueSAtIGhhbGZTaXplLnksIGZyb21Qb3NpdGlvbi55ICsgdmVsb2NpdHkueSAtIGhhbGZTaXplLnkpO1xuXG4gICAgICAgIHRoaXMuY2VudGVyLnNldChjZW50ZXJYLCBjZW50ZXJZKTtcbiAgICAgICAgdGhpcy5oYWxmU2l6ZS5zZXQoY2VudGVyWCAtIG1pblgsIGNlbnRlclkgLSBtaW5ZKTtcbiAgICB9XG4gICAgXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgY2xvbmUoKTogQUFCQiB7XG4gICAgICAgIHJldHVybiBuZXcgQUFCQih0aGlzLmNlbnRlci5jbG9uZSgpLCB0aGlzLmhhbGZTaXplLmNsb25lKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoaXMgQUFCQiB0byBhIHN0cmluZyBmb3JtYXRcbiAgICAgKiBAcmV0dXJucyAoY2VudGVyOiAoeCwgeSksIGhhbGZTaXplOiAoeCwgeSkpXG4gICAgICovXG4gICAgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIFwiKGNlbnRlcjogXCIgKyB0aGlzLmNlbnRlci50b1N0cmluZygpICsgXCIsIGhhbGYtc2l6ZTogXCIgKyB0aGlzLmhhbGZTaXplLnRvU3RyaW5nKCkgKyBcIilcIlxuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vVmVjMlwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4vQUFCQlwiO1xuaW1wb3J0IFNoYXBlIGZyb20gXCIuL1NoYXBlXCI7XG5cbi8qKlxuICogQSBDaXJjbGVcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2lyY2xlIGV4dGVuZHMgU2hhcGUge1xuXHRwcml2YXRlIF9jZW50ZXI6IFZlYzI7XG5cdHJhZGl1czogbnVtYmVyO1xuXHRcblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgQ2lyY2xlXG5cdCAqIEBwYXJhbSBjZW50ZXIgVGhlIGNlbnRlciBvZiB0aGUgY2lyY2xlXG5cdCAqIEBwYXJhbSByYWRpdXMgVGhlIHJhZGl1cyBvZiB0aGUgY2lyY2xlXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihjZW50ZXI6IFZlYzIsIHJhZGl1czogbnVtYmVyKSB7XG5cdFx0c3VwZXIoKTtcbiAgICAgICAgdGhpcy5fY2VudGVyID0gY2VudGVyID8gY2VudGVyIDogbmV3IFZlYzIoMCwgMCk7XG4gICAgICAgIHRoaXMucmFkaXVzID0gcmFkaXVzID8gcmFkaXVzIDogMDtcblx0fVxuXG5cdGdldCBjZW50ZXIoKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuX2NlbnRlcjtcblx0fVxuXG5cdHNldCBjZW50ZXIoY2VudGVyOiBWZWMyKSB7XG5cdFx0dGhpcy5fY2VudGVyID0gY2VudGVyO1xuXHR9XG5cblx0Z2V0IGhhbGZTaXplKCk6IFZlYzIge1xuXHRcdHJldHVybiBuZXcgVmVjMih0aGlzLnJhZGl1cywgdGhpcy5yYWRpdXMpO1xuXHR9XG5cblx0Z2V0IHIoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5yYWRpdXM7XG5cdH1cblxuXHRzZXQgcihyYWRpdXM6IG51bWJlcikge1xuXHRcdHRoaXMucmFkaXVzID0gcmFkaXVzO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdC8qKlxuICAgICAqIEEgc2ltcGxlIGJvb2xlYW4gY2hlY2sgb2Ygd2hldGhlciB0aGlzIEFBQkIgY29udGFpbnMgYSBwb2ludFxuICAgICAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIHRoZSBzcGVjaWZpZWQgcG9pbnRcbiAgICAgKi9cbiAgICBjb250YWluc1BvaW50KHBvaW50OiBWZWMyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbnRlci5kaXN0YW5jZVNxVG8ocG9pbnQpIDw9IHRoaXMucmFkaXVzKnRoaXMucmFkaXVzO1xuICAgIH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0Z2V0Qm91bmRpbmdSZWN0KCk6IEFBQkIge1xuXHRcdHJldHVybiBuZXcgQUFCQih0aGlzLl9jZW50ZXIuY2xvbmUoKSwgbmV3IFZlYzIodGhpcy5yYWRpdXMsIHRoaXMucmFkaXVzKSk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0Z2V0Qm91bmRpbmdDaXJjbGUoKTogQ2lyY2xlIHtcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdG92ZXJsYXBzKG90aGVyOiBTaGFwZSk6IGJvb2xlYW4ge1xuXHRcdHRocm93IG5ldyBFcnJvcihcIk1ldGhvZCBub3QgaW1wbGVtZW50ZWQuXCIpO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdGNsb25lKCk6IENpcmNsZSB7XG5cdFx0cmV0dXJuIG5ldyBDaXJjbGUodGhpcy5fY2VudGVyLmNsb25lKCksIHRoaXMucmFkaXVzKTtcblx0fVxuXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiKGNlbnRlcjogXCIgKyB0aGlzLmNlbnRlci50b1N0cmluZygpICsgXCIsIHJhZGl1czogXCIgKyB0aGlzLnJhZGl1cyArIFwiKVwiO1xuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL1ZlYzJcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuL0FBQkJcIjtcbmltcG9ydCBDaXJjbGUgZnJvbSBcIi4vQ2lyY2xlXCI7XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgU2hhcGUgY2xhc3MgdGhhdCBhY3RzIGFzIGFuIGludGVyZmFjZSBmb3IgYmV0dGVyIGludGVyYWN0aW9ucyB3aXRoIHN1YmNsYXNzZXMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFNoYXBlIHtcbiAgICBhYnN0cmFjdCBnZXQgY2VudGVyKCk6IFZlYzI7XG5cbiAgICBhYnN0cmFjdCBzZXQgY2VudGVyKGNlbnRlcjogVmVjMik7XG5cbiAgICBhYnN0cmFjdCBnZXQgaGFsZlNpemUoKTogVmVjMjtcblxuICAgIGdldCB4KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbnRlci54O1xuICAgIH1cblxuICAgIGdldCB5KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbnRlci55O1xuICAgIH1cblxuICAgIGdldCBodygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5oYWxmU2l6ZS54O1xuICAgIH1cblxuICAgIGdldCBoaCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5oYWxmU2l6ZS55O1xuICAgIH1cblxuICAgIGdldCB0b3AoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueSAtIHRoaXMuaGg7XG4gICAgfVxuXG4gICAgZ2V0IGJvdHRvbSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy55ICsgdGhpcy5oaDtcbiAgICB9XG5cbiAgICBnZXQgbGVmdCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy54IC0gdGhpcy5odztcbiAgICB9XG5cbiAgICBnZXQgcmlnaHQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueCArIHRoaXMuaHc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGJvdW5kaW5nIHJlY3RhbmdsZSBmb3IgdGhpcyBzaGFwZS4gV2FybmluZyAtIG1heSBiZSB0aGUgc2FtZSBhcyB0aGlzIFNoYXBlLlxuICAgICAqIEZvciBpbnN0YW5jZSwgdGhlIGJvdW5kaW5nIGNpcmNsZSBvZiBhbiBBQUJCIGlzIGl0c2VsZi4gVXNlIGNsb25lKCkgaWYgeW91IG5lZWQgYSBuZXcgc2hhcGUuXG4gICAgICogQHJldHVybnMgQW4gQUFCQiB0aGF0IGJvdW5kcyB0aGlzIHNoYXBlXG4gICAgICovXG4gICAgYWJzdHJhY3QgZ2V0Qm91bmRpbmdSZWN0KCk6IEFBQkI7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgYm91bmRpbmcgY2lyY2xlIGZvciB0aGlzIHNoYXBlLiBXYXJuaW5nIC0gbWF5IGJlIHRoZSBzYW1lIGFzIHRoaXMgU2hhcGUuXG4gICAgICogRm9yIGluc3RhbmNlLCB0aGUgYm91bmRpbmcgY2lyY2xlIG9mIGEgQ2lyY2xlIGlzIGl0c2VsZi4gVXNlIGNsb25lKCkgaWYgeW91IG5lZWQgYSBuZXcgc2hhcGUuXG4gICAgICogQHJldHVybnMgQSBDaXJjbGUgdGhhdCBib3VuZHMgdGhpcyBzaGFwZVxuICAgICAqL1xuICAgIGFic3RyYWN0IGdldEJvdW5kaW5nQ2lyY2xlKCk6IENpcmNsZTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBjb3B5IG9mIHRoaXMgU2hhcGVcbiAgICAgKiBAcmV0dXJucyBBIG5ldyBjb3B5IG9mIHRoaXMgc2hhcGVcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBjbG9uZSgpOiBTaGFwZTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0aGlzIHNoYXBlIG92ZXJsYXBzIGFub3RoZXJcbiAgICAgKiBAcGFyYW0gb3RoZXIgVGhlIG90aGVyIHNoYXBlIHRvIGNoZWNrIGFnYWluc3RcbiAgICAgKiBAcmV0dXJucyBhIGJvb2xlYW4gdGhhdCByZXByZXNlbnRzIHdoZXRoZXIgdGhpcyBTaGFwZSBvdmVybGFwcyB0aGUgb3RoZXIgb25lXG4gICAgICovXG4gICAgYWJzdHJhY3Qgb3ZlcmxhcHMob3RoZXI6IFNoYXBlKTogYm9vbGVhbjtcblxuICAgICAvKipcbiAgICAgKiBBIHNpbXBsZSBib29sZWFuIGNoZWNrIG9mIHdoZXRoZXIgdGhpcyBTaGFwZSBjb250YWlucyBhIHBvaW50XG4gICAgICogQHBhcmFtIHBvaW50IFRoZSBwb2ludCB0byBjaGVja1xuICAgICAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgd2hldGhlciB0aGlzIFNoYXBlIGNvbnRhaW5zIHRoZSBzcGVjaWZpZWQgcG9pbnRcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBjb250YWluc1BvaW50KHBvaW50OiBWZWMyKTogYm9vbGVhbjtcblxuICAgIHN0YXRpYyBnZXRUaW1lT2ZDb2xsaXNpb24oQTogU2hhcGUsIHZlbEE6IFZlYzIsIEI6IFNoYXBlLCB2ZWxCOiBWZWMyKTogW1ZlYzIsIFZlYzIsIGJvb2xlYW4sIGJvb2xlYW5dIHtcblx0XHRpZihBIGluc3RhbmNlb2YgQUFCQiAmJiBCIGluc3RhbmNlb2YgQUFCQil7XG5cdFx0XHRyZXR1cm4gU2hhcGUuZ2V0VGltZU9mQ29sbGlzaW9uX0FBQkJfQUFCQihBLCB2ZWxBLCBCLCB2ZWxCKTtcblx0XHR9XG4gICAgfVxuICAgIFxuICAgIHByaXZhdGUgc3RhdGljIGdldFRpbWVPZkNvbGxpc2lvbl9BQUJCX0FBQkIoQTogQUFCQiwgdmVsQTogVmVjMiwgQjogU2hhcGUsIHZlbEI6IFZlYzIpOiBbVmVjMiwgVmVjMiwgYm9vbGVhbiwgYm9vbGVhbl0ge1xuICAgICAgICBsZXQgcG9zU21hbGxlciA9IEEuY2VudGVyO1xuICAgICAgICBsZXQgcG9zTGFyZ2VyID0gQi5jZW50ZXI7XG4gICAgICAgIFxuICAgICAgICBsZXQgc2l6ZVNtYWxsZXIgPSBBLmhhbGZTaXplO1xuICAgICAgICBsZXQgc2l6ZUxhcmdlciA9IEIuaGFsZlNpemU7XG4gICAgXG4gICAgICAgIGxldCBmaXJzdENvbnRhY3QgPSBuZXcgVmVjMigwLCAwKTtcbiAgICAgICAgbGV0IGxhc3RDb250YWN0ID0gbmV3IFZlYzIoMCwgMCk7XG4gICAgXG4gICAgICAgIGxldCBjb2xsaWRpbmdYID0gZmFsc2U7XG4gICAgICAgIGxldCBjb2xsaWRpbmdZID0gZmFsc2U7XG4gICAgXG4gICAgICAgIC8vIFNvcnQgYnkgcG9zaXRpb25cbiAgICAgICAgaWYocG9zTGFyZ2VyLnggPCBwb3NTbWFsbGVyLngpe1xuICAgICAgICAgICAgLy8gU3dhcCwgYmVjYXVzZSBzbWFsbGVyIGlzIGZ1cnRoZXIgcmlnaHQgdGhhbiBsYXJnZXJcbiAgICAgICAgICAgIGxldCB0ZW1wOiBWZWMyO1xuICAgICAgICAgICAgdGVtcCA9IHNpemVTbWFsbGVyO1xuICAgICAgICAgICAgc2l6ZVNtYWxsZXIgPSBzaXplTGFyZ2VyO1xuICAgICAgICAgICAgc2l6ZUxhcmdlciA9IHRlbXA7XG4gICAgXG4gICAgICAgICAgICB0ZW1wID0gcG9zU21hbGxlcjtcbiAgICAgICAgICAgIHBvc1NtYWxsZXIgPSBwb3NMYXJnZXI7XG4gICAgICAgICAgICBwb3NMYXJnZXIgPSB0ZW1wO1xuICAgIFxuICAgICAgICAgICAgdGVtcCA9IHZlbEE7XG4gICAgICAgICAgICB2ZWxBID0gdmVsQjtcbiAgICAgICAgICAgIHZlbEIgPSB0ZW1wO1xuICAgICAgICB9XG4gICAgXG4gICAgICAgIC8vIEEgaXMgbGVmdCwgQiBpcyByaWdodFxuICAgICAgICBmaXJzdENvbnRhY3QueCA9IEluZmluaXR5O1xuICAgICAgICBsYXN0Q29udGFjdC54ID0gSW5maW5pdHk7XG4gICAgXG4gICAgICAgIGlmIChwb3NMYXJnZXIueCAtIHNpemVMYXJnZXIueCA+PSBwb3NTbWFsbGVyLnggKyBzaXplU21hbGxlci54KXtcbiAgICAgICAgICAgIC8vIElmIHdlIGFyZW4ndCBjdXJyZW50bHkgY29sbGlkaW5nXG4gICAgICAgICAgICBsZXQgcmVsVmVsID0gdmVsQS54IC0gdmVsQi54O1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZihyZWxWZWwgPiAwKXtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGV5IGFyZSBtb3ZpbmcgdG93YXJkcyBlYWNoIG90aGVyXG4gICAgICAgICAgICAgICAgZmlyc3RDb250YWN0LnggPSAoKHBvc0xhcmdlci54IC0gc2l6ZUxhcmdlci54KSAtIChwb3NTbWFsbGVyLnggKyBzaXplU21hbGxlci54KSkvKHJlbFZlbCk7XG4gICAgICAgICAgICAgICAgbGFzdENvbnRhY3QueCA9ICgocG9zTGFyZ2VyLnggKyBzaXplTGFyZ2VyLngpIC0gKHBvc1NtYWxsZXIueCAtIHNpemVTbWFsbGVyLngpKS8ocmVsVmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbGxpZGluZ1ggPSB0cnVlO1xuICAgICAgICB9XG4gICAgXG4gICAgICAgIGlmKHBvc0xhcmdlci55IDwgcG9zU21hbGxlci55KXtcbiAgICAgICAgICAgIC8vIFN3YXAsIGJlY2F1c2Ugc21hbGxlciBpcyBmdXJ0aGVyIHVwIHRoYW4gbGFyZ2VyXG4gICAgICAgICAgICBsZXQgdGVtcDogVmVjMjtcbiAgICAgICAgICAgIHRlbXAgPSBzaXplU21hbGxlcjtcbiAgICAgICAgICAgIHNpemVTbWFsbGVyID0gc2l6ZUxhcmdlcjtcbiAgICAgICAgICAgIHNpemVMYXJnZXIgPSB0ZW1wO1xuICAgIFxuICAgICAgICAgICAgdGVtcCA9IHBvc1NtYWxsZXI7XG4gICAgICAgICAgICBwb3NTbWFsbGVyID0gcG9zTGFyZ2VyO1xuICAgICAgICAgICAgcG9zTGFyZ2VyID0gdGVtcDtcbiAgICBcbiAgICAgICAgICAgIHRlbXAgPSB2ZWxBO1xuICAgICAgICAgICAgdmVsQSA9IHZlbEI7XG4gICAgICAgICAgICB2ZWxCID0gdGVtcDtcbiAgICAgICAgfVxuICAgIFxuICAgICAgICAvLyBBIGlzIHRvcCwgQiBpcyBib3R0b21cbiAgICAgICAgZmlyc3RDb250YWN0LnkgPSBJbmZpbml0eTtcbiAgICAgICAgbGFzdENvbnRhY3QueSA9IEluZmluaXR5O1xuICAgIFxuICAgICAgICBpZiAocG9zTGFyZ2VyLnkgLSBzaXplTGFyZ2VyLnkgPj0gcG9zU21hbGxlci55ICsgc2l6ZVNtYWxsZXIueSl7XG4gICAgICAgICAgICAvLyBJZiB3ZSBhcmVuJ3QgY3VycmVudGx5IGNvbGxpZGluZ1xuICAgICAgICAgICAgbGV0IHJlbFZlbCA9IHZlbEEueSAtIHZlbEIueTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYocmVsVmVsID4gMCl7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhleSBhcmUgbW92aW5nIHRvd2FyZHMgZWFjaCBvdGhlclxuICAgICAgICAgICAgICAgIGZpcnN0Q29udGFjdC55ID0gKChwb3NMYXJnZXIueSAtIHNpemVMYXJnZXIueSkgLSAocG9zU21hbGxlci55ICsgc2l6ZVNtYWxsZXIueSkpLyhyZWxWZWwpO1xuICAgICAgICAgICAgICAgIGxhc3RDb250YWN0LnkgPSAoKHBvc0xhcmdlci55ICsgc2l6ZUxhcmdlci55KSAtIChwb3NTbWFsbGVyLnkgLSBzaXplU21hbGxlci55KSkvKHJlbFZlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb2xsaWRpbmdZID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIFxuICAgICAgICByZXR1cm4gW2ZpcnN0Q29udGFjdCwgbGFzdENvbnRhY3QsIGNvbGxpZGluZ1gsIGNvbGxpZGluZ1ldO1xuICAgIH1cbn0iLCJpbXBvcnQgQ29sbGVjdGlvbiBmcm9tIFwiLi9Db2xsZWN0aW9uXCI7XG5cbi8qKlxuICogQSBMSUZPIHN0YWNrIHdpdGggaXRlbXMgb2YgdHlwZSBUXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN0YWNrPFQ+IGltcGxlbWVudHMgQ29sbGVjdGlvbiB7XG4gICAgLyoqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgU3RhY2sgKi9cbiAgICBwcml2YXRlIE1BWF9FTEVNRU5UUzogbnVtYmVyO1xuICAgIFxuICAgIC8qKiBUaGUgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIHN0YWNrICovXG4gICAgcHJpdmF0ZSBzdGFjazogQXJyYXk8VD47XG4gICAgXG4gICAgLyoqIFRoZSBoZWFkIG9mIHRoZSBzdGFjayAqL1xuXHRwcml2YXRlIGhlYWQ6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdHMgYSBuZXcgc3RhY2tcbiAgICAgKiBAcGFyYW0gbWF4RWxlbWVudHMgVGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgc3RhY2tcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihtYXhFbGVtZW50czogbnVtYmVyID0gMTAwKXtcbiAgICAgICAgdGhpcy5NQVhfRUxFTUVOVFMgPSBtYXhFbGVtZW50cztcbiAgICAgICAgdGhpcy5zdGFjayA9IG5ldyBBcnJheTxUPih0aGlzLk1BWF9FTEVNRU5UUyk7XG4gICAgICAgIHRoaXMuaGVhZCA9IC0xO1xuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBBZGRzIGFuIGl0ZW0gdG8gdGhlIHRvcCBvZiB0aGUgc3RhY2tcbiAgICAgKiBAcGFyYW0gaXRlbSBUaGUgbmV3IGl0ZW0gdG8gYWRkIHRvIHRoZSBzdGFja1xuICAgICAqL1xuICAgIHB1c2goaXRlbTogVCk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLmhlYWQgKyAxID09PSB0aGlzLk1BWF9FTEVNRU5UUyl7XG4gICAgICAgICAgICB0aHJvdyBcIlN0YWNrIGZ1bGwgLSBjYW5ub3QgYWRkIGVsZW1lbnRcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmhlYWQgKz0gMTtcbiAgICAgICAgdGhpcy5zdGFja1t0aGlzLmhlYWRdID0gaXRlbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFuIGl0ZW0gZnJvbSB0aGUgdG9wIG9mIHRoZSBzdGFja1xuICAgICAqIEByZXR1cm5zIFRoZSBpdGVtIGF0IHRoZSB0b3Agb2YgdGhlIHN0YWNrXG4gICAgICovXG4gICAgcG9wKCk6IFQge1xuICAgICAgICBpZih0aGlzLmhlYWQgPT09IC0xKXtcbiAgICAgICAgICAgIHRocm93IFwiU3RhY2sgZW1wdHkgLSBjYW5ub3QgcmVtb3ZlIGVsZW1lbnRcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmhlYWQgLT0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhY2tbdGhpcy5oZWFkICsgMV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgZWxlbWVudCBjdXJyZW50bHkgYXQgdGhlIHRvcCBvZiB0aGUgc3RhY2tcbiAgICAgKiBAcmV0dXJucyBUaGUgaXRlbSBhdCB0aGUgdG9wIG9mIHRoZSBzdGFja1xuICAgICAqL1xuICAgIHBlZWsoKTogVCB7XG4gICAgICAgIGlmKHRoaXMuaGVhZCA9PT0gLTEpe1xuICAgICAgICAgICAgdGhyb3cgXCJTdGFjayBlbXB0eSAtIGNhbm5vdCBnZXQgZWxlbWVudFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnN0YWNrW3RoaXMuaGVhZF07XG4gICAgfVxuXG4gICAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIHN0YWNrIGlzIGVtcHR5XG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHRoYXQgcmVwcmVzZW50cyB3aGV0aGVyIG9yIG5vdCB0aGUgc3RhY2sgaXMgZW1wdHlcbiAgICAqL1xuICAgIGlzRW1wdHkoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhlYWQgPT09IC0xO1xuICAgIH1cblxuICAgIC8vIEBpbXBsZW1lbnRlZFxuICAgIGNsZWFyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmZvckVhY2goKGl0ZW0sIGluZGV4KSA9PiBkZWxldGUgdGhpcy5zdGFja1tpbmRleF0pO1xuICAgICAgICB0aGlzLmhlYWQgPSAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgaXRlbXMgY3VycmVudGx5IGluIHRoZSBzdGFja1xuICAgICAqIEByZXR1cm5zIFRoZSBudW1iZXIgb2YgaXRlbXMgaW4gdGhlIHN0YWNrXG4gICAgICovXG4gICAgc2l6ZSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5oZWFkICsgMTtcbiAgICB9XG5cbiAgICAvLyBAaW1wbGVtZW50ZWRcbiAgICBmb3JFYWNoKGZ1bmM6IChpdGVtOiBULCBpbmRleD86IG51bWJlcikgPT4gdm9pZCk6IHZvaWR7XG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgd2hpbGUoaSA8PSB0aGlzLmhlYWQpe1xuICAgICAgICAgICAgZnVuYyh0aGlzLnN0YWNrW2ldLCBpKTtcbiAgICAgICAgICAgIGkgKz0gMTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoaXMgc3RhY2sgaW50byBhIHN0cmluZyBmb3JtYXRcbiAgICAgKiBAcmV0dXJucyBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhpcyBzdGFja1xuICAgICAqL1xuICAgIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgICAgIGxldCByZXR2YWwgPSBcIlwiO1xuXG4gICAgICAgIHRoaXMuZm9yRWFjaCggKGl0ZW0sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBsZXQgc3RyID0gaXRlbS50b1N0cmluZygpXG4gICAgICAgICAgICBpZihpbmRleCAhPT0gMCl7XG4gICAgICAgICAgICAgICAgc3RyICs9IFwiIC0+IFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR2YWwgPSBzdHIgKyByZXR2YWw7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBcIlRvcCAtPiBcIiArIHJldHZhbDtcbiAgICB9XG59IiwiaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uLy4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi8uLi9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgU3RhdGVNYWNoaW5lIGZyb20gXCIuL1N0YXRlTWFjaGluZVwiO1xuXG4vKipcbiAqIEFuIGFic3RyYWN0IGltcGxlbWVudGF0aW9uIG9mIGEgc3RhdGUgZm9yIGEgQHJlZmVyZW5jZVtTdGF0ZU1hY2hpbmVdLlxuICogVGhpcyBjbGFzcyBzaG91bGQgYmUgZXh0ZW5kZWQgdG8gYWxsb3cgZm9yIGN1c3RvbSBzdGF0ZSBiZWhhdmlvcnMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFN0YXRlIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG4gICAgLyoqIFRoZSBTdGF0ZU1hY2hpbmUgdGhhdCB1c2VzIHRoaXMgU3RhdGUgKi9cbiAgICBwcm90ZWN0ZWQgcGFyZW50OiBTdGF0ZU1hY2hpbmU7XG5cbiAgICAvKiogQW4gZXZlbnQgZW1pdHRlciAqL1xuICAgIHByb3RlY3RlZCBlbWl0dGVyOiBFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBTdGF0ZVxuICAgICAqIEBwYXJhbSBwYXJlbnQgVGhlIHBhcmVudCBTdGF0ZU1hY2hpbmUgb2YgdGhpcyBzdGF0ZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHBhcmVudDogU3RhdGVNYWNoaW5lKSB7XG4gICAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgbWV0aG9kIHRoYXQgaXMgY2FsbGVkIHdoZW4gdGhpcyBzdGF0ZSBpcyBlbnRlcmVkLiBVc2UgdGhpcyB0byBpbml0aWFsaXplIGFueSB2YXJpYWJsZXMgYmVmb3JlIHVwZGF0ZXMgb2NjdXIuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgSW5mb3JtYXRpb24gdG8gcGFzcyB0byB0aGlzIHN0YXRlXG4gICAgICovXG4gICAgYWJzdHJhY3Qgb25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIEEgbGlmZWN5Y2xlIG1ldGhvZCB0aGF0IGhhbmRsZXMgYW4gaW5wdXQgZXZlbnQsIHN1Y2ggYXMgdGFraW5nIGRhbWFnZS5cbiAgICAgKiBAcGFyYW0gZXZlbnQgVGhlIEdhbWVFdmVudCB0byBwcm9jZXNzXG4gICAgICovXG4gICAgYWJzdHJhY3QgaGFuZGxlSW5wdXQoZXZlbnQ6IEdhbWVFdmVudCk6IHZvaWQ7XG5cbiAgICAvLyBAaW1wbGVtZW50ZWRcbiAgICBhYnN0cmFjdCB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogVGVsbHMgdGhlIHN0YXRlIG1hY2hpbmUgdGhhdCB0aGlzIHN0YXRlIGhhcyBlbmRlZCwgYW5kIG1ha2VzIGl0IHRyYW5zaXRpb24gdG8gdGhlIG5ldyBzdGF0ZSBzcGVjaWZpZWRcbiAgICAgKiBAcGFyYW0gc3RhdGVOYW1lIFRoZSBuYW1lIG9mIHRoZSBzdGF0ZSB0byB0cmFuc2l0aW9uIHRvXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGZpbmlzaGVkKHN0YXRlTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGFyZW50LmNoYW5nZVN0YXRlKHN0YXRlTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBsaWZlY3ljbGUgbWV0aG9kIGlzIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBpcyBlbmRpbmcuXG4gICAgICogQHJldHVybnMgaW5mbyB0byBwYXNzIHRvIHRoZSBuZXh0IHN0YXRlXG4gICAgICovXG4gICAgYWJzdHJhY3Qgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT47XG59IiwiaW1wb3J0IFN0YWNrIGZyb20gXCIuLi9TdGFja1wiO1xuaW1wb3J0IFN0YXRlIGZyb20gXCIuL1N0YXRlXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9NYXBcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBSZWNlaXZlciBmcm9tIFwiLi4vLi4vRXZlbnRzL1JlY2VpdmVyXCI7XG5pbXBvcnQgRW1pdHRlciBmcm9tIFwiLi4vLi4vRXZlbnRzL0VtaXR0ZXJcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9JbnRlcmZhY2VzL1VwZGF0ZWFibGVcIjtcblxuLyoqXG4gKiBBbiBpbXBsZW1lbnRhdGlvbiBvZiBhIFB1c2ggRG93biBBdXRvbWF0YSBTdGF0ZSBtYWNoaW5lLiBTdGF0ZXMgY2FuIGFsc28gYmUgaGllcmFyY2hpY2FsXG4gKiBmb3IgbW9yZSBmbGV4aWJpbGl0eSwgYXMgZGVzY3JpYmVkIGluIEBsaW5rKEdhbWUgUHJvZ3JhbW1pbmcgUGF0dGVybnMpKGh0dHBzOi8vZ2FtZXByb2dyYW1taW5ncGF0dGVybnMuY29tL3N0YXRlLmh0bWwpLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTdGF0ZU1hY2hpbmUgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcbiAgICAvKiogQSBzdGFjayBvZiB0aGUgY3VycmVudCBzdGF0ZXMgKi9cbiAgICBwcm90ZWN0ZWQgc3RhY2s6IFN0YWNrPFN0YXRlPjtcbiAgICAvKiogQSBtYXBlIG9mIHN0YXRlIGtleXMgdG8gYWN0dWFsIHN0YXRlIGluc3RhbmNlcyAqL1xuICAgIHByb3RlY3RlZCBzdGF0ZU1hcDogTWFwPFN0YXRlPjtcbiAgICAvKiogVGhlIGN1cnJlbnQgc3RhdGUgKi9cbiAgICBwcm90ZWN0ZWQgY3VycmVudFN0YXRlOiBTdGF0ZTtcbiAgICAvKiogQW4gZXZlbnQgcmVjZWl2ZXIgKi9cbiAgICBwcm90ZWN0ZWQgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuICAgIC8qKiBBbiBldmVudCBlbWl0dGVyICovXG4gICAgcHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG4gICAgLyoqIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgd2hldGhlciBvciBub3QgdGhpcyBTdGF0ZU1hY2hpbmUgaXMgY3VycmVudGx5IGFjdGl2ZSAqL1xuICAgIHByb3RlY3RlZCBhY3RpdmU6IGJvb2xlYW47XG4gICAgLyoqIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgd2hldGhlciBvciBub3QgdGhpcyBTdGF0ZU1hY2hpbmUgc2hvdWxkIGVtaXQgYW4gZXZlbnQgb24gc3RhdGUgY2hhbmdlICovXG4gICAgcHJvdGVjdGVkIGVtaXRFdmVudE9uU3RhdGVDaGFuZ2U6IGJvb2xlYW47XG4gICAgLyoqIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBiZSBlbWl0dGVkIG9uIHN0YXRlIGNoYW5nZSAqL1xuICAgIHByb3RlY3RlZCBzdGF0ZUNoYW5nZUV2ZW50TmFtZTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBTdGF0ZU1hY2hpbmVcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgICAgIHRoaXMuc3RhdGVNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIgPSBuZXcgUmVjZWl2ZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0RXZlbnRPblN0YXRlQ2hhbmdlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYWN0aXZpdHkgc3RhdGUgb2YgdGhpcyBzdGF0ZSBtYWNoaW5lXG4gICAgICogQHBhcmFtIGZsYWcgVHJ1ZSBpZiB5b3Ugd2FudCB0byBzZXQgdGhpcyBtYWNoaW5lIHJ1bm5pbmcsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHNldEFjdGl2ZShmbGFnOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWN0aXZlID0gZmxhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyB0aGlzIHN0YXRlIG1hY2hpbmUgZW1pdCBhbiBldmVudCBhbnkgdGltZSBpdHMgc3RhdGUgY2hhbmdlc1xuICAgICAqIEBwYXJhbSBzdGF0ZUNoYW5nZUV2ZW50TmFtZSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdFxuICAgICAqL1xuICAgIHNldEVtaXRFdmVudE9uU3RhdGVDaGFuZ2Uoc3RhdGVDaGFuZ2VFdmVudE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmVtaXRFdmVudE9uU3RhdGVDaGFuZ2UgPSB0cnVlO1xuICAgICAgICB0aGlzLnN0YXRlQ2hhbmdlRXZlbnROYW1lID0gc3RhdGVDaGFuZ2VFdmVudE5hbWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RvcHMgdGhpcyBzdGF0ZSBtYWNoaW5lIGZyb20gZW1pdHRpbmcgZXZlbnRzIG9uIHN0YXRlIGNoYW5nZS5cbiAgICAgKi9cbiAgICBjYW5jZWxFbWl0RXZlbnRPblN0YXRlQ2hhbmdlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmVtaXRFdmVudE9uU3RhdGVDaGFuZ2UgPSBmYWxzZTtcbiAgICB9XG4gICAgXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhpcyBzdGF0ZSBtYWNoaW5lIHdpdGggYW4gaW5pdGlhbCBzdGF0ZSBhbmQgc2V0cyBpdCBydW5uaW5nXG4gICAgICogQHBhcmFtIGluaXRpYWxTdGF0ZSBUaGUgbmFtZSBvZiBpbml0aWFsIHN0YXRlIG9mIHRoZSBzdGF0ZSBtYWNoaW5lXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZShpbml0aWFsU3RhdGU6IHN0cmluZywgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdGFjay5wdXNoKHRoaXMuc3RhdGVNYXAuZ2V0KGluaXRpYWxTdGF0ZSkpO1xuICAgICAgICB0aGlzLmN1cnJlbnRTdGF0ZSA9IHRoaXMuc3RhY2sucGVlaygpO1xuICAgICAgICB0aGlzLmN1cnJlbnRTdGF0ZS5vbkVudGVyKG9wdGlvbnMpO1xuICAgICAgICB0aGlzLnNldEFjdGl2ZSh0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgc3RhdGUgdG8gdGhpcyBzdGF0ZSBtYWNoaW5lXG4gICAgICogQHBhcmFtIHN0YXRlTmFtZSBUaGUgbmFtZSBvZiB0aGUgc3RhdGUgdG8gYWRkXG4gICAgICogQHBhcmFtIHN0YXRlIFRoZSBzdGF0ZSB0byBhZGRcbiAgICAgKi9cbiAgICBhZGRTdGF0ZShzdGF0ZU5hbWU6IHN0cmluZywgc3RhdGU6IFN0YXRlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RhdGVNYXAuYWRkKHN0YXRlTmFtZSwgc3RhdGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIHN0YXRlIG9mIHRoaXMgc3RhdGUgbWFjaGluZSB0byB0aGUgcHJvdmlkZWQgc3RyaW5nXG4gICAgICogQHBhcmFtIHN0YXRlIFRoZSBzdHJpbmcgbmFtZSBvZiB0aGUgc3RhdGUgdG8gY2hhbmdlIHRvXG4gICAgICovXG4gICAgY2hhbmdlU3RhdGUoc3RhdGU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICAvLyBFeGl0IHRoZSBjdXJyZW50IHN0YXRlXG4gICAgICAgIGxldCBvcHRpb25zID0gdGhpcy5jdXJyZW50U3RhdGUub25FeGl0KCk7XG5cbiAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBjb3JyZWN0IHN0YXRlIGlzIGF0IHRoZSB0b3Agb2YgdGhlIHN0YWNrXG4gICAgICAgIGlmKHN0YXRlID09PSBcInByZXZpb3VzXCIpe1xuICAgICAgICAgICAgLy8gUG9wIHRoZSBjdXJyZW50IHN0YXRlIG9mZiB0aGUgc3RhY2tcbiAgICAgICAgICAgIHRoaXMuc3RhY2sucG9wKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgbmV3IHN0YXRlIGZyb20gdGhlIHN0YXRlbWFwIGFuZCBwdXQgaXQgYXQgdGhlIHRvcCBvZiB0aGUgc3RhY2tcbiAgICAgICAgICAgIHRoaXMuc3RhY2sucG9wKCk7XG4gICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5zdGF0ZU1hcC5nZXQoc3RhdGUpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldHJlaXZlIHRoZSBuZXcgc3RhdGUgZnJvbSB0aGUgc3RhY2tcbiAgICAgICAgdGhpcy5jdXJyZW50U3RhdGUgPSB0aGlzLnN0YWNrLnBlZWsoKTtcblxuICAgICAgICAvLyBFbWl0IGFuIGV2ZW50IGlmIHR1cm5lZCBvblxuICAgICAgICBpZih0aGlzLmVtaXRFdmVudE9uU3RhdGVDaGFuZ2Upe1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0aGlzLnN0YXRlQ2hhbmdlRXZlbnROYW1lLCB7c3RhdGU6IHRoaXMuY3VycmVudFN0YXRlfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbnRlciB0aGUgbmV3IHN0YXRlXG4gICAgICAgIHRoaXMuY3VycmVudFN0YXRlLm9uRW50ZXIob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyBpbnB1dC4gVGhpcyBoYXBwZW5zIGF0IHRoZSB2ZXJ5IGJlZ2lubmluZyBvZiB0aGlzIHN0YXRlIG1hY2hpbmUncyB1cGRhdGUgY3ljbGUuXG4gICAgICogQHBhcmFtIGV2ZW50IFRoZSBnYW1lIGV2ZW50IHRvIHByb2Nlc3NcbiAgICAgKi9cbiAgICBoYW5kbGVFdmVudChldmVudDogR2FtZUV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMuYWN0aXZlKXtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFN0YXRlLmhhbmRsZUlucHV0KGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEBpbXBsZW1lbnRlZFxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBEaXN0cmlidXRlIGV2ZW50c1xuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUV2ZW50KGV2ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlbGVnYXRlIHRoZSB1cGRhdGUgdG8gdGhlIGN1cnJlbnQgc3RhdGVcbiAgICAgICAgdGhpcy5jdXJyZW50U3RhdGUudXBkYXRlKGRlbHRhVCk7XG4gICAgfVxufSIsIi8vIEBpZ25vcmVQYWdlXG4vKipcbiAqIGEgcmVwcmVzZW50YXRpb24gb2YgVGlsZWQncyB0aWxlbWFwIGRhdGFcbiAqL1xuZXhwb3J0IGNsYXNzIFRpbGVkVGlsZW1hcERhdGEge1xuICAgIGhlaWdodDogbnVtYmVyO1xuICAgIHdpZHRoOiBudW1iZXI7XG4gICAgdGlsZWhlaWdodDogbnVtYmVyO1xuICAgIHRpbGV3aWR0aDogbnVtYmVyO1xuICAgIG9yaWVudGF0aW9uOiBzdHJpbmc7XG4gICAgbGF5ZXJzOiBBcnJheTxUaWxlZExheWVyRGF0YT47XG4gICAgdGlsZXNldHM6IEFycmF5PFRpbGVkVGlsZXNldERhdGE+O1xufVxuXG4vKipcbiAqIEEgcmVwcmVzZW50YXRpb24gb2YgYSBjdXN0b20gbGF5ZXIgcHJvcGVydHkgaW4gYSBUaWxlZCB0aWxlbWFwXG4gKi9cbmV4cG9ydCBjbGFzcyBUaWxlZExheWVyUHJvcGVydHkge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB0eXBlOiBzdHJpbmc7XG4gICAgdmFsdWU6IGFueTtcbn1cblxuLyoqXG4gKiBBIHJlcHJlc2VudGF0aW9uIG9mIGEgdGlsZXNldCBpbiBhIFRpbGVkIHRpbGVtYXBcbiAqL1xuZXhwb3J0IGNsYXNzIFRpbGVkVGlsZXNldERhdGEge1xuICAgIGNvbHVtbnM6IG51bWJlcjtcbiAgICB0aWxld2lkdGg6IG51bWJlcjtcbiAgICB0aWxlaGVpZ2h0OiBudW1iZXI7XG4gICAgdGlsZWNvdW50OiBudW1iZXI7XG4gICAgZmlyc3RnaWQ6IG51bWJlcjtcbiAgICBpbWFnZWhlaWdodDogbnVtYmVyO1xuICAgIGltYWdld2lkdGg6IG51bWJlcjtcbiAgICBtYXJnaW46IG51bWJlcjtcbiAgICBzcGFjaW5nOiBudW1iZXI7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGltYWdlOiBzdHJpbmc7XG4gICAgdGlsZXM/OiBBcnJheTxUaWxlZENvbGxlY3Rpb25UaWxlPlxufVxuXG4vKipcbiAqIEEgcmVwcmVzZW50YXRpb24gb2YgYSBsYXllciBpbiBhIFRpbGVkIHRpbGVtYXBcbiAqL1xuZXhwb3J0IGNsYXNzIFRpbGVkTGF5ZXJEYXRhIHtcbiAgICBkYXRhOiBudW1iZXJbXTtcbiAgICB4OiBudW1iZXI7XG4gICAgeTogbnVtYmVyO1xuICAgIHdpZHRoOiBudW1iZXI7XG4gICAgaGVpZ2h0OiBudW1iZXI7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIG9wYWNpdHk6IG51bWJlcjtcbiAgICB2aXNpYmxlOiBib29sZWFuO1xuICAgIHByb3BlcnRpZXM6IFRpbGVkTGF5ZXJQcm9wZXJ0eVtdO1xuICAgIHR5cGU6IHN0cmluZztcbiAgICBvYmplY3RzPzogQXJyYXk8VGlsZWRPYmplY3Q+O1xufVxuXG5leHBvcnQgY2xhc3MgVGlsZWRPYmplY3Qge1xuICAgIGdpZDogbnVtYmVyO1xuICAgIGhlaWdodDogbnVtYmVyO1xuICAgIHdpZHRoOiBudW1iZXI7XG4gICAgaWQ6IG51bWJlcjtcbiAgICBuYW1lOiBzdHJpbmc7O1xuICAgIHByb3BlcnRpZXM6IEFycmF5PFRpbGVkTGF5ZXJQcm9wZXJ0eT47XG4gICAgcm90YXRpb246IG51bWJlcjtcbiAgICB0eXBlOiBzdHJpbmc7XG4gICAgdmlzaWJsZTogYm9vbGVhbjtcbiAgICB4OiBudW1iZXI7XG4gICAgeTogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgVGlsZWRDb2xsZWN0aW9uVGlsZSB7XG4gICAgaWQ6IG51bWJlcjtcbiAgICBpbWFnZTogc3RyaW5nO1xuICAgIGltYWdlaGVpZ2h0OiBudW1iZXI7XG4gICAgaW1hZ2V3aWR0aDogbnVtYmVyO1xufVxuIiwiaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL1ZlYzJcIjtcbmltcG9ydCB7IFRpbGVkVGlsZXNldERhdGEgfSBmcm9tIFwiLi9UaWxlZERhdGFcIjtcblxuLyoqXG4gKiBUaGUgZGF0YSByZXByZXNlbnRhdGlvbiBvZiBhIFRpbGVzZXQgZm9yIHRoZSBnYW1lIGVuZ2luZS4gVGhpcyByZXByZXNlbnRzIG9uZSBpbWFnZSxcbiAqIHdpdGggYSBzdGFydEluZGV4IGlmIHJlcXVpcmVkIChhcyBpdCBpcyB3aXRoIFRpbGVkIHVzaW5nIHR3byBpbWFnZXMgaW4gb25lIHRpbHNldCkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRpbGVzZXQge1xuICAgIC8qKiBUaGUga2V5IG9mIHRoZSBpbWFnZSB1c2VkIGJ5IHRoaXMgdGlsZXNldCAqL1xuICAgIHByb3RlY3RlZCBpbWFnZUtleTogc3RyaW5nO1xuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgdGlsZXNldCBpbWFnZSAqL1xuICAgIHByb3RlY3RlZCBpbWFnZVNpemU6IFZlYzI7XG4gICAgLyoqIFRoZSBpbmRleCBvZiAwdGggaW1hZ2Ugb2YgdGhpcyB0aWxlc2V0ICovXG4gICAgcHJvdGVjdGVkIHN0YXJ0SW5kZXg6IG51bWJlcjtcbiAgICAvKiogVGhlIGluZGV4IG9mIHRoZSBsYXN0IGltYWdlIG9mIHRoaXMgdGlsc2V0ICovXG4gICAgcHJvdGVjdGVkIGVuZEluZGV4OiBudW1iZXI7XG4gICAgLyoqIFRoZSBzaXplIG9mIHRoZSB0aWxlcyBpbiB0aGlzIHRpbGVzZXQgKi9cbiAgICBwcm90ZWN0ZWQgdGlsZVNpemU6IFZlYzI7XG4gICAgLyoqIFRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGlzIHRpbGVzZXQgKi9cbiAgICBwcm90ZWN0ZWQgbnVtUm93czogbnVtYmVyO1xuICAgIC8qKiBUaGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhpcyB0aWxlc2V0ICovXG4gICAgcHJvdGVjdGVkIG51bUNvbHM6IG51bWJlcjtcblxuICAgIC8vIFRPRE86IENoYW5nZSB0aGlzIHRvIGJlIG1vcmUgZ2VuZXJhbCBhbmQgd29yayB3aXRoIG90aGVyIHRpbGVzZXQgZm9ybWF0c1xuICAgIGNvbnN0cnVjdG9yKHRpbGVzZXREYXRhOiBUaWxlZFRpbGVzZXREYXRhKXtcbiAgICAgICAgLy8gRGVmZXIgaGFuZGxpbmcgb2YgdGhlIGRhdGEgdG8gYSBoZWxwZXIgY2xhc3NcbiAgICAgICAgdGhpcy5pbml0RnJvbVRpbGVkRGF0YSh0aWxlc2V0RGF0YSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgdGlsZXNldCBmcm9tIHRoZSBkYXRhIGZyb20gYSBUaWxlZCBqc29uIGZpbGVcbiAgICAgKiBAcGFyYW0gdGlsZWREYXRhIFRoZSBwYXJzZWQgb2JqZWN0IGZyb20gYSBUaWxlZCBqc29uIGZpbGVcbiAgICAgKi9cbiAgICBpbml0RnJvbVRpbGVkRGF0YSh0aWxlZERhdGE6IFRpbGVkVGlsZXNldERhdGEpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5udW1Sb3dzID0gdGlsZWREYXRhLnRpbGVjb3VudC90aWxlZERhdGEuY29sdW1ucztcbiAgICAgICAgdGhpcy5udW1Db2xzID0gdGlsZWREYXRhLmNvbHVtbnM7XG4gICAgICAgIHRoaXMuc3RhcnRJbmRleCA9IHRpbGVkRGF0YS5maXJzdGdpZDtcbiAgICAgICAgdGhpcy5lbmRJbmRleCA9IHRoaXMuc3RhcnRJbmRleCArIHRpbGVkRGF0YS50aWxlY291bnQgLSAxO1xuICAgICAgICB0aGlzLnRpbGVTaXplID0gbmV3IFZlYzIodGlsZWREYXRhLnRpbGV3aWR0aCwgdGlsZWREYXRhLnRpbGV3aWR0aCk7XG4gICAgICAgIHRoaXMuaW1hZ2VLZXkgPSB0aWxlZERhdGEuaW1hZ2U7XG4gICAgICAgIHRoaXMuaW1hZ2VTaXplID0gbmV3IFZlYzIodGlsZWREYXRhLmltYWdld2lkdGgsIHRpbGVkRGF0YS5pbWFnZWhlaWdodCk7XG4gICAgfVxuXG4gICAgLyoqIFxuICAgICAqIEdldHMgdGhlIGltYWdlIGtleSBhc3NvY2lhdGVkIHdpdGggdGhpcyB0aWxlbWFwXG4gICAgICogQHJldHVybnMgVGhlIGltYWdlIGtleSBvZiB0aGlzIHRpbGVtYXBcbiAgICAgKi9cbiAgICBnZXRJbWFnZUtleSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5pbWFnZUtleTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgVmVjMiBjb250YWluaW5nIHRoZSBsZWZ0IGFuZCB0b3Agb2Zmc2V0IGZyb20gdGhlIGltYWdlIG9yaWdpbiBmb3IgdGhpcyB0aWxlLlxuICAgICAqIEBwYXJhbSB0aWxlSW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlIGZyb20gc3RhcnRJbmRleCB0byBlbmRJbmRleCBvZiB0aGlzIHRpbGVzZXRcbiAgICAgKiBAcmV0dXJucyBBIFZlYzIgY29udGFpbmluZyB0aGUgb2Zmc2V0IGZvciB0aGUgc3BlY2lmaWVkIHRpbGUuXG4gICAgICovXG4gICAgZ2V0SW1hZ2VPZmZzZXRGb3JUaWxlKHRpbGVJbmRleDogbnVtYmVyKTogVmVjMiB7XG4gICAgICAgIC8vIEdldCB0aGUgdHJ1ZSBpbmRleFxuICAgICAgICBsZXQgaW5kZXggPSB0aWxlSW5kZXggLSB0aGlzLnN0YXJ0SW5kZXg7XG4gICAgICAgIGxldCByb3cgPSBNYXRoLmZsb29yKGluZGV4IC8gdGhpcy5udW1Db2xzKTtcbiAgICAgICAgbGV0IGNvbCA9IGluZGV4ICUgdGhpcy5udW1Db2xzO1xuICAgICAgICBsZXQgd2lkdGggPSB0aGlzLnRpbGVTaXplLng7XG4gICAgICAgIGxldCBoZWlnaHQgPSB0aGlzLnRpbGVTaXplLnk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBwb3NpdGlvbiB0byBzdGFydCBhIGNyb3AgaW4gdGhlIHRpbGVzZXQgaW1hZ2VcbiAgICAgICAgbGV0IGxlZnQgPSBjb2wgKiB3aWR0aDtcbiAgICAgICAgbGV0IHRvcCA9IHJvdyAqIGhlaWdodDtcblxuICAgICAgICByZXR1cm4gbmV3IFZlYzIobGVmdCwgdG9wKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBzdGFydCBpbmRleFxuICAgICAqIEByZXR1cm5zIFRoZSBzdGFydCBpbmRleFxuICAgICAqL1xuICAgIGdldFN0YXJ0SW5kZXgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRJbmRleDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB0aWxlIHNldFxuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSB0aWxlIHNpemVcbiAgICAgKi9cbiAgICBnZXRUaWxlU2l6ZSgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIHRpbGVzZXRcbiAgICAgKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIHJvd3NcbiAgICAgKi9cbiAgICBnZXROdW1Sb3dzKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLm51bVJvd3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIHRpbHNldFxuICAgICAqIEByZXR1cm5zIFRoZSBudW1iZXIgb2YgY29sdW1uc1xuICAgICAqL1xuICAgIGdldE51bUNvbHMoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubnVtQ29scztcbiAgICB9XG5cbiAgICBnZXRUaWxlQ291bnQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5kSW5kZXggLSB0aGlzLnN0YXJ0SW5kZXggKyAxO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIG9yIG5vdCB0aGlzIHRpbHNldCBjb250YWlucyB0aGUgc3BlY2lmaWVkIHRpbGUgaW5kZXguIFRoaXMgaXMgdXNlZCBmb3IgcmVuZGVyaW5nLlxuICAgICAqIEBwYXJhbSB0aWxlSW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGlzIHRpbHNldCB1c2VzIHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKi9cbiAgICBoYXNUaWxlKHRpbGVJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aWxlSW5kZXggPj0gdGhpcy5zdGFydEluZGV4ICYmIHRpbGVJbmRleCA8PSB0aGlzLmVuZEluZGV4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlciBhIHNpbmd1bGFyIHRpbGUgd2l0aCBpbmRleCB0aWxlSW5kZXggZnJvbSB0aGUgdGlsZXNldCBsb2NhdGVkIGF0IHBvc2l0aW9uIGRhdGFJbmRleFxuICAgICAqIEBwYXJhbSBjdHggVGhlIHJlbmRlcmluZyBjb250ZXh0XG4gICAgICogQHBhcmFtIHRpbGVJbmRleCBUaGUgdmFsdWUgb2YgdGhlIHRpbGUgdG8gcmVuZGVyXG4gICAgICogQHBhcmFtIGRhdGFJbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGUgaW4gdGhlIGRhdGEgYXJyYXlcbiAgICAgKiBAcGFyYW0gd29ybGRTaXplIFRoZSBzaXplIG9mIHRoZSB3b3JsZFxuICAgICAqIEBwYXJhbSBvcmlnaW4gVGhlIHZpZXdwb3J0IG9yaWdpbiBpbiB0aGUgY3VycmVudCBsYXllclxuICAgICAqIEBwYXJhbSBzY2FsZSBUaGUgc2NhbGUgb2YgdGhlIHRpbGVtYXBcbiAgICAgKi9cbiAgICByZW5kZXJUaWxlKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELCB0aWxlSW5kZXg6IG51bWJlciwgZGF0YUluZGV4OiBudW1iZXIsIG1heENvbHM6IG51bWJlciwgb3JpZ2luOiBWZWMyLCBzY2FsZTogVmVjMiwgem9vbTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGxldCBpbWFnZSA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpLmdldEltYWdlKHRoaXMuaW1hZ2VLZXkpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgdHJ1ZSBpbmRleFxuICAgICAgICBsZXQgaW5kZXggPSB0aWxlSW5kZXggLSB0aGlzLnN0YXJ0SW5kZXg7XG4gICAgICAgIGxldCByb3cgPSBNYXRoLmZsb29yKGluZGV4IC8gdGhpcy5udW1Db2xzKTtcbiAgICAgICAgbGV0IGNvbCA9IGluZGV4ICUgdGhpcy5udW1Db2xzO1xuICAgICAgICBsZXQgd2lkdGggPSB0aGlzLnRpbGVTaXplLng7XG4gICAgICAgIGxldCBoZWlnaHQgPSB0aGlzLnRpbGVTaXplLnk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBwb3NpdGlvbiB0byBzdGFydCBhIGNyb3AgaW4gdGhlIHRpbGVzZXQgaW1hZ2VcbiAgICAgICAgbGV0IGxlZnQgPSBjb2wgKiB3aWR0aDtcbiAgICAgICAgbGV0IHRvcCA9IHJvdyAqIGhlaWdodDtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHBvc2l0aW9uIGluIHRoZSB3b3JsZCB0byByZW5kZXIgdGhlIHRpbGVcbiAgICAgICAgbGV0IHggPSBNYXRoLmZsb29yKChkYXRhSW5kZXggJSBtYXhDb2xzKSAqIHdpZHRoICogc2NhbGUueCk7XG4gICAgICAgIGxldCB5ID0gTWF0aC5mbG9vcihNYXRoLmZsb29yKGRhdGFJbmRleCAvIG1heENvbHMpICogaGVpZ2h0ICogc2NhbGUueSk7XG4gICAgICAgIGN0eC5kcmF3SW1hZ2UoaW1hZ2UsIGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCwgTWF0aC5mbG9vcigoeCAtIG9yaWdpbi54KSp6b29tKSwgTWF0aC5mbG9vcigoeSAtIG9yaWdpbi55KSp6b29tKSwgTWF0aC5jZWlsKHdpZHRoICogc2NhbGUueCAqIHpvb20pLCBNYXRoLmNlaWwoaGVpZ2h0ICogc2NhbGUueSAqIHpvb20pKTtcbiAgICB9XG59IiwiaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5cbi8qKlxuICogQSB0d28tZGltZW5zaW9uYWwgdmVjdG9yICh4LCB5KVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWZWMyIHtcblxuXHQvLyBTdG9yZSB4IGFuZCB5IGluIGFuIGFycmF5XG5cdC8qKiBUaGUgYXJyYXkgdGhhdCBzdG9yZXMgdGhlIGFjdHVhbCB2ZWN0b3IgdmFsdWVzIHggYW5kIHkgKi9cblx0cHJpdmF0ZSB2ZWM6IEZsb2F0MzJBcnJheTtcblxuXHQvKipcdFxuXHQgKiBXaGVuIHRoaXMgdmVjdG9yIGNoYW5nZXMgaXRzIHZhbHVlLCBkbyBzb21ldGhpbmdcblx0ICovXG5cdHByaXZhdGUgb25DaGFuZ2U6IEZ1bmN0aW9uID0gKCkgPT4ge307XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgVmVjMlxuXHQgKiBAcGFyYW0geCBUaGUgeCB2YWx1ZSBvZiB0aGUgdmVjdG9yXG5cdCAqIEBwYXJhbSB5IFRoZSB5IHZhbHVlIG9mIHRoZSB2ZWN0b3Jcblx0ICovXG5cdGNvbnN0cnVjdG9yKHg6IG51bWJlciA9IDAsIHk6IG51bWJlciA9IDApIHtcblx0XHR0aGlzLnZlYyA9IG5ldyBGbG9hdDMyQXJyYXkoMik7XG5cdFx0dGhpcy52ZWNbMF0gPSB4O1xuXHRcdHRoaXMudmVjWzFdID0geTtcblx0fVxuXG5cdC8vIEV4cG9zZSB4IGFuZCB5IHdpdGggZ2V0dGVycyBhbmQgc2V0dGVyc1xuXHRnZXQgeCgpIHtcblx0XHRyZXR1cm4gdGhpcy52ZWNbMF07XG5cdH1cblxuXHRzZXQgeCh4OiBudW1iZXIpIHtcblx0XHR0aGlzLnZlY1swXSA9IHg7XG5cblx0XHRpZih0aGlzLm9uQ2hhbmdlKXtcblx0XHRcdHRoaXMub25DaGFuZ2UoKTtcblx0XHR9XG5cdH1cblxuXHRnZXQgeSgpIHtcblx0XHRyZXR1cm4gdGhpcy52ZWNbMV07XG5cdH1cblxuXHRzZXQgeSh5OiBudW1iZXIpIHtcblx0XHR0aGlzLnZlY1sxXSA9IHk7XG5cblx0XHRpZih0aGlzLm9uQ2hhbmdlKXtcblx0XHRcdHRoaXMub25DaGFuZ2UoKTtcblx0XHR9XG5cdH1cblxuXHRzdGF0aWMgZ2V0IFpFUk8oKSB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKDAsIDApO1xuXHR9XG5cblx0c3RhdGljIHJlYWRvbmx5IFpFUk9fU1RBVElDID0gbmV3IFZlYzIoMCwgMCk7XG5cblx0c3RhdGljIGdldCBJTkYoKSB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKEluZmluaXR5LCBJbmZpbml0eSk7XG5cdH1cblxuXHRzdGF0aWMgZ2V0IFVQKCkge1xuXHRcdHJldHVybiBuZXcgVmVjMigwLCAtMSk7XG5cdH1cblxuXHRzdGF0aWMgZ2V0IERPV04oKSB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKDAsIDEpO1xuXHR9XG5cblx0c3RhdGljIGdldCBMRUZUKCkge1xuXHRcdHJldHVybiBuZXcgVmVjMigtMSwgMCk7XG5cdH1cblxuXHRzdGF0aWMgZ2V0IFJJR0hUKCkge1xuXHRcdHJldHVybiBuZXcgVmVjMigxLCAwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgc3F1YXJlZCBtYWduaXR1ZGUgb2YgdGhlIHZlY3Rvci4gVGhpcyB0ZW5kcyB0byBiZSBmYXN0ZXIsIHNvIHVzZSBpdCBpbiBzaXR1YXRpb25zIHdoZXJlIHRha2luZyB0aGVcblx0ICogc3F1YXJlIHJvb3QgZG9lc24ndCBtYXR0ZXIsIGxpa2UgZm9yIGNvbXBhcmluZyBkaXN0YW5jZXMuXG5cdCAqIEByZXR1cm5zIFRoZSBzcXVhcmVkIG1hZ25pdHVkZSBvZiB0aGUgdmVjdG9yXG5cdCAqL1xuXHRtYWdTcSgpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLngqdGhpcy54ICsgdGhpcy55KnRoaXMueTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgbWFnbml0dWRlIG9mIHRoZSB2ZWN0b3IuXG5cdCAqIEByZXR1cm5zIFRoZSBtYWduaXR1ZGUgb2YgdGhlIHZlY3Rvci5cblx0ICovXG5cdG1hZygpOiBudW1iZXIge1xuXHRcdHJldHVybiBNYXRoLnNxcnQodGhpcy5tYWdTcSgpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXZkZXMgeCBhbmQgeSBieSB0aGUgbWFnbml0dWRlIHRvIG9idGFpbiB0aGUgdW5pdCB2ZWN0b3IgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGlzIHZlY3Rvci5cblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IgYXMgYSB1bml0IHZlY3Rvci5cblx0ICovXG5cdG5vcm1hbGl6ZSgpOiBWZWMyIHtcblx0XHRpZih0aGlzLnggPT09IDAgJiYgdGhpcy55ID09PSAwKSByZXR1cm4gdGhpcztcblx0XHRsZXQgbWFnID0gdGhpcy5tYWcoKTtcblx0XHR0aGlzLnggLz0gbWFnO1xuXHRcdHRoaXMueSAvPSBtYWc7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogV29ya3MgbGlrZSBub3JtYWxpemUoKSwgYnV0IHJldHVybnMgYSBuZXcgVmVjMlxuXHQgKiBAcmV0dXJucyBBIG5ldyB2ZWN0b3IgdGhhdCBpcyB0aGUgdW5pdCB2ZWN0b3IgZm9yIHRoaXMgb25lXG5cdCAqL1xuXHRub3JtYWxpemVkKCk6IFZlYzIge1xuXHRcdGlmKHRoaXMuaXNaZXJvKCkpe1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdFxuXHRcdGxldCBtYWcgPSB0aGlzLm1hZygpO1xuXHRcdHJldHVybiBuZXcgVmVjMih0aGlzLngvbWFnLCB0aGlzLnkvbWFnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB4IGFuZCB5IGVsZW1lbnRzIG9mIHRoaXMgdmVjdG9yIHRvIHplcm8uXG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yLCB3aXRoIHggYW5kIHkgc2V0IHRvIHplcm8uXG5cdCAqL1xuXHR6ZXJvKCk6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLnNldCgwLCAwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2ZWN0b3IncyB4IGFuZCB5IGJhc2VkIG9uIHRoZSBhbmdsZSBwcm92aWRlZC4gR29lcyBjb3VudGVyIGNsb2Nrd2lzZS5cblx0ICogQHBhcmFtIGFuZ2xlIFRoZSBhbmdsZSBpbiByYWRpYW5zXG5cdCAqIEBwYXJhbSByYWRpdXMgVGhlIG1hZ25pdHVkZSBvZiB0aGUgdmVjdG9yIGF0IHRoZSBzcGVjaWZpZWQgYW5nbGVcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IuXG5cdCAqL1xuXHRzZXRUb0FuZ2xlKGFuZ2xlOiBudW1iZXIsIHJhZGl1czogbnVtYmVyID0gMSk6IFZlYzIge1xuXHRcdHRoaXMueCA9IE1hdGhVdGlscy5mbG9vclRvUGxhY2UoTWF0aC5jb3MoYW5nbGUpKnJhZGl1cywgNSk7XG5cdFx0dGhpcy55ID0gTWF0aFV0aWxzLmZsb29yVG9QbGFjZSgtTWF0aC5zaW4oYW5nbGUpKnJhZGl1cywgNSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIHZlY3RvciB0aGF0IHBvaW50IGZyb20gdGhpcyB2ZWN0b3IgdG8gYW5vdGhlciBvbmVcblx0ICogQHBhcmFtIG90aGVyIFRoZSB2ZWN0b3IgdG8gcG9pbnQgdG9cblx0ICogQHJldHVybnMgQSBuZXcgVmVjMiB0aGF0IHBvaW50cyBmcm9tIHRoaXMgdmVjdG9yIHRvIHRoZSBvbmUgcHJvdmlkZWRcblx0ICovXG5cdHZlY1RvKG90aGVyOiBWZWMyKTogVmVjMiB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKG90aGVyLnggLSB0aGlzLngsIG90aGVyLnkgLSB0aGlzLnkpO1xuXHR9XG5cdFxuXHQvKipcblx0ICogUmV0dXJucyBhIHZlY3RvciBjb250YWluaW5nIHRoZSBkaXJlY3Rpb24gZnJvbSB0aGlzIHZlY3RvciB0byBhbm90aGVyXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgdmVjdG9yIHRvIHBvaW50IHRvXG5cdCAqIEByZXR1cm5zIEEgbmV3IFZlYzIgdGhhdCBwb2ludHMgZnJvbSB0aGlzIHZlY3RvciB0byB0aGUgb25lIHByb3ZpZGVkLiBUaGlzIG5ldyBWZWMyIHdpbGwgYmUgYSB1bml0IHZlY3Rvci5cblx0ICovXG5cdGRpclRvKG90aGVyOiBWZWMyKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMudmVjVG8ob3RoZXIpLm5vcm1hbGl6ZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEtlZXBzIHRoZSB2ZWN0b3IncyBkaXJlY3Rpb24sIGJ1dCBzZXRzIGl0cyBtYWduaXR1ZGUgdG8gYmUgdGhlIHByb3ZpZGVkIG1hZ25pdHVkZVxuXHQgKiBAcGFyYW0gbWFnbml0dWRlIFRoZSBtYWduaXR1ZGUgdGhlIHZlY3RvciBzaG91bGQgYmVcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3Igd2l0aCBpdHMgbWFnbml0dWRlIHNldCB0byB0aGUgbmV3IG1hZ25pdHVkZVxuXHQgKi9cblx0c2NhbGVUbyhtYWduaXR1ZGU6IG51bWJlcik6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLm5vcm1hbGl6ZSgpLnNjYWxlKG1hZ25pdHVkZSk7XG5cdH1cblxuXHQvKipcblx0ICogU2NhbGVzIHggYW5kIHkgYnkgdGhlIG51bWJlciBwcm92aWRlZCwgb3IgaWYgdHdvIG51bWJlciBhcmUgcHJvdmlkZWQsIHNjYWxlcyB0aGVtIGluZGl2aWR1YWxseS5cblx0ICogQHBhcmFtIGZhY3RvciBUaGUgc2NhbGluZyBmYWN0b3IgZm9yIHRoZSB2ZWN0b3IsIG9yIGZvciBvbmx5IHRoZSB4LWNvbXBvbmVudCBpZiB5RmFjdG9yIGlzIHByb3ZpZGVkXG5cdCAqIEBwYXJhbSB5RmFjdG9yIFRoZSBzY2FsaW5nIGZhY3RvciBmb3IgdGhlIHktY29tcG9uZW50IG9mIHRoZSB2ZWN0b3Jcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IgYWZ0ZXIgc2NhbGluZ1xuXHQgKi9cblx0c2NhbGUoZmFjdG9yOiBudW1iZXIsIHlGYWN0b3I6IG51bWJlciA9IG51bGwpOiBWZWMyIHtcblx0XHRpZih5RmFjdG9yICE9PSBudWxsKXtcblx0XHRcdHRoaXMueCAqPSBmYWN0b3I7XG5cdFx0XHR0aGlzLnkgKj0geUZhY3Rvcjtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHR0aGlzLnggKj0gZmFjdG9yO1xuXHRcdHRoaXMueSAqPSBmYWN0b3I7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIHNjYWxlZCB2ZXJzaW9uIG9mIHRoaXMgdmVjdG9yIHdpdGhvdXQgbW9kaWZ5aW5nIGl0LlxuXHQgKiBAcGFyYW0gZmFjdG9yIFRoZSBzY2FsaW5nIGZhY3RvciBmb3IgdGhlIHZlY3Rvciwgb3IgZm9yIG9ubHkgdGhlIHgtY29tcG9uZW50IGlmIHlGYWN0b3IgaXMgcHJvdmlkZWRcblx0ICogQHBhcmFtIHlGYWN0b3IgVGhlIHNjYWxpbmcgZmFjdG9yIGZvciB0aGUgeS1jb21wb25lbnQgb2YgdGhlIHZlY3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyB2ZWN0b3IgdGhhdCBoYXMgdGhlIHZhbHVlcyBvZiB0aGlzIHZlY3RvciBhZnRlciBzY2FsaW5nXG5cdCAqL1xuXHRzY2FsZWQoZmFjdG9yOiBudW1iZXIsIHlGYWN0b3I6IG51bWJlciA9IG51bGwpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLnNjYWxlKGZhY3RvciwgeUZhY3Rvcik7XG5cdH1cblxuXHQvKipcblx0ICogUm90YXRlcyB0aGUgdmVjdG9yIGNvdW50ZXItY2xvY2t3aXNlIGJ5IHRoZSBhbmdsZSBhbW91bnQgc3BlY2lmaWVkXG5cdCAqIEBwYXJhbSBhbmdsZSBUaGUgYW5nbGUgdG8gcm90YXRlIGJ5IGluIHJhZGlhbnNcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IgYWZ0ZXIgcm90YXRpb24uXG5cdCAqL1xuXHRyb3RhdGVDQ1coYW5nbGU6IG51bWJlcik6IFZlYzIge1xuXHRcdGxldCBjcyA9IE1hdGguY29zKGFuZ2xlKTtcblx0XHRsZXQgc24gPSBNYXRoLnNpbihhbmdsZSk7XG5cdFx0bGV0IHRlbXBYID0gdGhpcy54KmNzIC0gdGhpcy55KnNuO1xuXHRcdGxldCB0ZW1wWSA9IHRoaXMueCpzbiArIHRoaXMueSpjcztcblx0XHR0aGlzLnggPSB0ZW1wWDtcblx0XHR0aGlzLnkgPSB0ZW1wWTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB2ZWN0b3JzIGNvb3JkaW5hdGVzIHRvIGJlIHRoZSBvbmVzIHByb3ZpZGVkXG5cdCAqIEBwYXJhbSB4IFRoZSBuZXcgeCB2YWx1ZSBmb3IgdGhpcyB2ZWN0b3Jcblx0ICogQHBhcmFtIHkgVGhlIG5ldyB5IHZhbHVlIGZvciB0aGlzIHZlY3RvclxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvclxuXHQgKi9cblx0c2V0KHg6IG51bWJlciwgeTogbnVtYmVyKTogVmVjMiB7XG5cdFx0dGhpcy54ID0geDtcblx0XHR0aGlzLnkgPSB5O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvcGllcyB0aGUgdmFsdWVzIG9mIHRoZSBvdGhlciBWZWMyIGludG8gdGhpcyBvbmUuXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgVmVjMiB0byBjb3B5XG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yIHdpdGggaXRzIHZhbHVlcyBzZXQgdG8gdGhlIHZlY3RvciBwcm92aWRlZFxuXHQgKi9cblx0Y29weShvdGhlcjogVmVjMik6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLnNldChvdGhlci54LCBvdGhlci55KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIHRoaXMgdmVjdG9yIHRoZSBhbm90aGVyIHZlY3RvclxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIFZlYzIgdG8gYWRkIHRvIHRoaXMgb25lXG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yIGFmdGVyIGFkZGluZyB0aGUgb25lIHByb3ZpZGVkXG5cdCAqL1xuXHRhZGQob3RoZXI6IFZlYzIpOiBWZWMyIHtcblx0XHR0aGlzLnggKz0gb3RoZXIueDtcblx0XHR0aGlzLnkgKz0gb3RoZXIueTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBJbmNyZW1lbnRzIHRoZSBmaWVsZHMgb2YgdGhpcyB2ZWN0b3IuIEJvdGggYXJlIGluY3JlbWVudGVkIHdpdGggYSwgaWYgb25seSBhIGlzIHByb3ZpZGVkLlxuXHQgKiBAcGFyYW0gYSBUaGUgZmlyc3QgbnVtYmVyIHRvIGluY3JlbWVudCBieVxuXHQgKiBAcGFyYW0gYiBUaGUgc2Vjb25kIG51bWJlciB0byBpbmNyZW1lbnQgYnlcblx0ICogQHJldHVybnNzIFRoaXMgdmVjdG9yIGFmdGVyIGluY3JlbWVudGluZ1xuXHQgKi9cblx0aW5jKGE6IG51bWJlciwgYj86IG51bWJlcik6IFZlYzIge1xuXHRcdGlmKGIgPT09IHVuZGVmaW5lZCl7XG5cdFx0XHR0aGlzLnggKz0gYTtcblx0XHRcdHRoaXMueSArPSBhO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnggKz0gYTtcblx0XHRcdHRoaXMueSArPSBiO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTdWJ0cmFjdHMgYW5vdGhlciB2ZWN0b3IgZnJvbSB0aGlzIHZlY3RvclxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIFZlYzIgdG8gc3VidHJhY3QgZnJvbSB0aGlzIG9uZVxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhZnRlciBzdWJ0cmFjdGluZyB0aGUgb25lIHByb3ZpZGVkXG5cdCAqL1xuXHRzdWIob3RoZXI6IFZlYzIpOiBWZWMyIHtcblx0XHR0aGlzLnggLT0gb3RoZXIueDtcblx0XHR0aGlzLnkgLT0gb3RoZXIueTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBNdWx0aXBsaWVzIHRoaXMgdmVjdG9yIHdpdGggYW5vdGhlciB2ZWN0b3IgZWxlbWVudC13aXNlLiBJbiBvdGhlciB3b3JkcywgdGhpcy54ICo9IG90aGVyLnggYW5kIHRoaXMueSAqPSBvdGhlci55XG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgVmVjMiB0byBtdWx0aXBseSB0aGlzIG9uZSBieVxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhZnRlciBtdWx0aXBseWluZyBpdHMgY29tcG9uZW50cyBieSB0aGlzIG9uZVxuXHQgKi9cblx0bXVsdChvdGhlcjogVmVjMik6IFZlYzIge1xuXHRcdHRoaXMueCAqPSBvdGhlci54O1xuXHRcdHRoaXMueSAqPSBvdGhlci55O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpdmlkZXMgdGhpcyB2ZWN0b3Igd2l0aCBhbm90aGVyIHZlY3RvciBlbGVtZW50LXdpc2UuIEluIG90aGVyIHdvcmRzLCB0aGlzLnggLz0gb3RoZXIueCBhbmQgdGhpcy55IC89IG90aGVyLnlcblx0ICogQHBhcmFtIG90aGVyIFRoZSB2ZWN0b3IgdG8gZGl2aWRlIHRoaXMgb25lIGJ5XG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yIGFmdGVyIGRpdmlzaW9uXG5cdCAqL1xuXHRkaXYob3RoZXI6IFZlYzIpOiBWZWMyIHtcblx0XHRpZihvdGhlci54ID09PSAwIHx8IG90aGVyLnkgPT09IDApIHRocm93IFwiRGl2aWRlIGJ5IHplcm8gZXJyb3JcIjtcblx0XHR0aGlzLnggLz0gb3RoZXIueDtcblx0XHR0aGlzLnkgLz0gb3RoZXIueTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBEb2VzIGFuIGVsZW1lbnQgd2lzZSByZW1haW5kZXIgb3BlcmF0aW9uIG9uIHRoaXMgdmVjdG9yLiB0aGlzLnggJT0gb3RoZXIueCBhbmQgdGhpcy55ICU9IG90aGVyLnlcblx0ICogQHBhcmFtIG90aGVyIFRoZSBvdGhlciB2ZWN0b3Jcblx0ICogQHJldHVybnMgdGhpcyB2ZWN0b3Jcblx0ICovXG5cdHJlbWFpbmRlcihvdGhlcjogVmVjMik6IFZlYzIge1xuXHRcdHRoaXMueCA9IHRoaXMueCAlIG90aGVyLng7XG5cdFx0dGhpcy55ID0gdGhpcy55ICUgb3RoZXIueTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gdGhpcyB2ZWN0b3IgYW5kIGFub3RoZXIgdmVjdG9yXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgdmVjdG9yIHRvIGNvbXB1dGUgZGlzdGFuY2Ugc3F1YXJlZCB0b1xuXHQgKiBAcmV0dXJucyBUaGUgc3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIHRoaXMgdmVjdG9yIGFuZCB0aGUgb25lIHByb3ZpZGVkXG5cdCAqL1xuXHRkaXN0YW5jZVNxVG8ob3RoZXI6IFZlYzIpOiBudW1iZXIge1xuXHRcdHJldHVybiAodGhpcy54IC0gb3RoZXIueCkqKHRoaXMueCAtIG90aGVyLngpICsgKHRoaXMueSAtIG90aGVyLnkpKih0aGlzLnkgLSBvdGhlci55KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoaXMgdmVjdG9yIGFuZCBhbm90aGVyIHZlY3RvclxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBjb21wdXRlIGRpc3RhbmNlIHRvXG5cdCAqIEByZXR1cm5zIFRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoaXMgdmVjdG9yIGFuZCB0aGUgb25lIHByb3ZpZGVkXG5cdCAqL1xuXHRkaXN0YW5jZVRvKG90aGVyOiBWZWMyKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gTWF0aC5zcXJ0KHRoaXMuZGlzdGFuY2VTcVRvKG90aGVyKSk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZG90IHByb2R1Y3Qgb2YgdGhpcyB2ZWN0b3IgYW5kIGFub3RoZXJcblx0ICogQHBhcmFtIG90aGVyIFRoZSB2ZWN0b3IgdG8gY29tcHV0ZSB0aGUgZG90IHByb2R1Y3Qgd2l0aFxuXHQgKiBAcmV0dXJucyBUaGUgZG90IHByb2R1Y3Qgb2YgdGhpcyB2ZWN0b3IgYW5kIHRoZSBvbmUgcHJvdmlkZWQuXG5cdCAqL1xuXHRkb3Qob3RoZXI6IFZlYzIpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLngqb3RoZXIueCArIHRoaXMueSpvdGhlci55O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGFuZ2xlIGNvdW50ZXItY2xvY2t3aXNlIGluIHJhZGlhbnMgZnJvbSB0aGlzIHZlY3RvciB0byBhbm90aGVyIHZlY3RvclxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBjb21wdXRlIHRoZSBhbmdsZSB0b1xuXHQgKiBAcmV0dXJucyBUaGUgYW5nbGUsIHJvdGF0aW5nIENDVywgZnJvbSB0aGlzIHZlY3RvciB0byB0aGUgb3RoZXIgdmVjdG9yXG5cdCAqL1xuXHRhbmdsZVRvQ0NXKG90aGVyOiBWZWMyKTogbnVtYmVyIHtcblx0XHRsZXQgZG90ID0gdGhpcy5kb3Qob3RoZXIpO1xuXHRcdGxldCBkZXQgPSB0aGlzLngqb3RoZXIueSAtIHRoaXMueSpvdGhlci54O1xuXHRcdGxldCBhbmdsZSA9IC1NYXRoLmF0YW4yKGRldCwgZG90KTtcblxuXHRcdGlmKGFuZ2xlIDwgMCl7XG5cdFx0XHRhbmdsZSArPSAyKk1hdGguUEk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFuZ2xlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB2ZWN0b3Igcm91bmRlZCB0byAxIGRlY2ltYWwgcG9pbnRcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IgYXMgYSBzdHJpbmdcblx0ICovXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMudG9GaXhlZCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB2ZWN0b3Igcm91bmRlZCB0byB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBkZWNpbWFsIHBvaW50c1xuXHQgKiBAcGFyYW0gbnVtRGVjaW1hbFBvaW50cyBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcG9pbnRzIHRvIGNyZWF0ZSBhIHN0cmluZyB0b1xuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhcyBhIHN0cmluZ1xuXHQgKi9cblx0dG9GaXhlZChudW1EZWNpbWFsUG9pbnRzOiBudW1iZXIgPSAxKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gXCIoXCIgKyB0aGlzLngudG9GaXhlZChudW1EZWNpbWFsUG9pbnRzKSArIFwiLCBcIiArIHRoaXMueS50b0ZpeGVkKG51bURlY2ltYWxQb2ludHMpICsgXCIpXCI7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIG5ldyB2ZWN0b3Igd2l0aCB0aGUgc2FtZSBjb29yZGluYXRlcyBhcyB0aGlzIG9uZS5cblx0ICogQHJldHVybnMgQSBuZXcgVmVjMiB3aXRoIHRoZSBzYW1lIHZhbHVlcyBhcyB0aGlzIG9uZVxuXHQgKi9cblx0Y2xvbmUoKTogVmVjMiB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKHRoaXMueCwgdGhpcy55KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyB2ZWN0b3IgYW5kIG90aGVyIGhhdmUgdGhlIEVYQUNUIHNhbWUgeCBhbmQgeSAobm90IGFzc3VyZWQgdG8gYmUgc2FmZSBmb3IgZmxvYXRzKVxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBjaGVjayBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIGVxdWFsaXR5IG9mIHRoZSB0d28gdmVjdG9yc1xuXHQgKi9cblx0c3RyaWN0RXF1YWxzKG90aGVyOiBWZWMyKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMueCA9PT0gb3RoZXIueCAmJiB0aGlzLnkgPT09IG90aGVyLnk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoaXMgdmVjdG9yIGFuZCBvdGhlciBoYXZlIHRoZSBzYW1lIHggYW5kIHlcblx0ICogQHBhcmFtIG90aGVyIFRoZSB2ZWN0b3IgdG8gY2hlY2sgYWdhaW5zdFxuXHQgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSBlcXVhbGl0eSBvZiB0aGUgdHdvIHZlY3RvcnNcblx0ICovXG5cdGVxdWFscyhvdGhlcjogVmVjMik6IGJvb2xlYW4ge1xuXHRcdGxldCB4RXEgPSBNYXRoLmFicyh0aGlzLnggLSBvdGhlci54KSA8IDAuMDAwMDAwMTtcblx0XHRsZXQgeUVxID0gTWF0aC5hYnModGhpcy55IC0gb3RoZXIueSkgPCAwLjAwMDAwMDE7XG5cblx0XHRyZXR1cm4geEVxICYmIHlFcTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyB2ZWN0b3IgaXMgdGhlIHplcm8gdmVjdG9yIGV4YWN0bHkgKG5vdCBhc3N1cmVkIHRvIGJlIHNhZmUgZm9yIGZsb2F0cykuXG5cdCAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIGVxdWFsaXR5IG9mIHRoaXMgdmVjdG9yIGFuZCB0aGUgemVybyB2ZWN0b3Jcblx0ICovXG5cdHN0cmljdElzWmVybygpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy54ID09PSAwICYmIHRoaXMueSA9PT0gMDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyB4IGFuZCB5IGZvciB0aGlzIHZlY3RvciBhcmUgYm90aCB6ZXJvLlxuXHQgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSBlcXVhbGl0eSBvZiB0aGlzIHZlY3RvciBhbmQgdGhlIHplcm8gdmVjdG9yXG5cdCAqL1xuXHRpc1plcm8oKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIE1hdGguYWJzKHRoaXMueCkgPCAwLjAwMDAwMDEgJiYgTWF0aC5hYnModGhpcy55KSA8IDAuMDAwMDAwMTtcblx0fVxuXHRcblx0LyoqXG5cdCAqIFNldHMgdGhlIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW5ldmVyIHRoaXMgdmVjdG9yIGlzIGNoYW5nZWQuXG5cdCAqIEBwYXJhbSBmIFRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICovXG5cdHNldE9uQ2hhbmdlKGY6IEZ1bmN0aW9uKTogdm9pZCB7XG5cdFx0dGhpcy5vbkNoYW5nZSA9IGY7XG5cdH1cblxuXHR0b0FycmF5KCk6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIHRoaXMudmVjO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBlcmZvcm1zIGxpbmVhciBpbnRlcnBvbGF0aW9uIGJldHdlZW4gdHdvIHZlY3RvcnNcblx0ICogQHBhcmFtIGEgVGhlIGZpcnN0IHZlY3RvclxuXHQgKiBAcGFyYW0gYiBUaGUgc2Vjb25kIHZlY3RvclxuXHQgKiBAcGFyYW0gdCBUaGUgdGltZSBvZiB0aGUgbGVycCwgd2l0aCAwIGJlaW5nIHZlY3RvciBBLCBhbmQgMSBiZWluZyB2ZWN0b3IgQlxuXHQgKiBAcmV0dXJucyBBIG5ldyBWZWMyIHJlcHJlc2VudGluZyB0aGUgbGVycCBiZXR3ZWVuIHZlY3RvciBhIGFuZCBiLlxuXHQgKi9cblx0c3RhdGljIGxlcnAoYTogVmVjMiwgYjogVmVjMiwgdDogbnVtYmVyKTogVmVjMiB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKE1hdGhVdGlscy5sZXJwKGEueCwgYi54LCB0KSwgTWF0aFV0aWxzLmxlcnAoYS55LCBiLnksIHQpKTtcblx0fVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuXG4vKipcbiAqIEEgdXRpbCBjbGFzcyBmb3IgcmVuZGVyaW5nIERlYnVnIG1lc3NhZ2VzIHRvIHRoZSBjYW52YXMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERlYnVnIHtcblxuXHQvKiogQSBtYXAgb2YgbG9nIG1lc3NhZ2VzIHRvIGRpc3BsYXkgb24gdGhlIHNjcmVlbiAqLyBcblx0cHJpdmF0ZSBzdGF0aWMgbG9nTWVzc2FnZXM6IE1hcDxzdHJpbmc+ID0gbmV3IE1hcCgpO1xuXG5cdC8qKiBBbiBhcnJheSBvZiBnYW1lIG5vZGVzIHRvIHJlbmRlciBkZWJ1ZyBpbmZvIGZvciAqL1xuXHRwcml2YXRlIHN0YXRpYyBub2RlczogQXJyYXk8R2FtZU5vZGU+O1xuXG5cdC8qKiBUaGUgcmVuZGVyaW5nIGNvbnRleHQgZm9yIGFueSBkZWJ1ZyBtZXNzYWdlcyAqL1xuXHRwcml2YXRlIHN0YXRpYyBkZWJ1Z1JlbmRlcmluZ0NvbnRleHQ6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblxuXHQvKipcdFRoZSBzaXplIG9mIHRoZSBkZWJ1ZyBjYW52YXMgKi9cblx0cHJpdmF0ZSBzdGF0aWMgZGVidWdDYW52YXNTaXplOiBWZWMyO1xuXG5cdC8qKiBUaGUgcmVuZGVyaW5nIGNvbG9yIGZvciB0ZXh0ICovXG5cdHByaXZhdGUgc3RhdGljIGRlZmF1bHRUZXh0Q29sb3I6IENvbG9yID0gQ29sb3IuV0hJVEU7XG5cblx0LyoqXG5cdCAqIEFkZCBhIG1lc3NhZ2UgdG8gZGlzcGxheSBvbiB0aGUgZGVidWcgc2NyZWVuXG5cdCAqIEBwYXJhbSBpZCBBIHVuaXF1ZSBJRCBmb3IgdGhpcyBtZXNzYWdlXG5cdCAqIEBwYXJhbSBtZXNzYWdlcyBUaGUgbWVzc2FnZXMgdG8gcHJpbnQgdG8gdGhlIGRlYnVnIHNjcmVlblxuXHQgKi9cblx0c3RhdGljIGxvZyhpZDogc3RyaW5nLCAuLi5tZXNzYWdlczogYW55KTogdm9pZCB7XG5cdFx0Ly8gbGV0IG1lc3NhZ2UgPSBcIlwiO1xuXHRcdC8vIGZvcihsZXQgaSA9IDA7IGkgPCBtZXNzYWdlcy5sZW5ndGg7IGkrKyl7XG5cdFx0Ly8gXHRtZXNzYWdlICs9IG1lc3NhZ2VzW2ldLnRvU3RyaW5nKCk7XG5cdFx0Ly8gfVxuXHRcdC8vIEpvaW4gYWxsIG1lc3NhZ2VzIHdpdGggc3BhY2VzXG5cdFx0bGV0IG1lc3NhZ2UgPSBtZXNzYWdlcy5tYXAoKG06IGFueSkgPT4gbS50b1N0cmluZygpKS5qb2luKFwiIFwiKTtcblx0XHR0aGlzLmxvZ01lc3NhZ2VzLmFkZChpZCwgbWVzc2FnZSk7XG5cdH1cblxuXHQvKipcblx0ICogRGVsZXRlcyBhIGEga2V5IGZyb20gdGhlIGxvZyBhbmQgc3RvcHMgaXQgZnJvbSBrZWVwaW5nIHVwIHNwYWNlIG9uIHRoZSBzY3JlZW5cblx0ICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgbG9nIGl0ZW0gdG8gY2xlYXJcblx0ICovXG5cdHN0YXRpYyBjbGVhckxvZ0l0ZW0oaWQ6IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMubG9nTWVzc2FnZXMuZGVsZXRlKGlkKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBsaXN0IG9mIG5vZGVzIHRvIHJlbmRlciB3aXRoIHRoZSBkZWJ1Z2dlclxuXHQgKiBAcGFyYW0gbm9kZXMgVGhlIG5ldyBsaXN0IG9mIG5vZGVzXG5cdCAqL1xuXHRzdGF0aWMgc2V0Tm9kZXMobm9kZXM6IEFycmF5PEdhbWVOb2RlPik6IHZvaWQge1xuXHRcdHRoaXMubm9kZXMgPSBub2Rlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBEcmF3cyBhIGJveCBhdCB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uXG5cdCAqIEBwYXJhbSBjZW50ZXIgVGhlIGNlbnRlciBvZiB0aGUgYm94XG5cdCAqIEBwYXJhbSBoYWxmU2l6ZSBUaGUgZGltZW5zaW9ucyBvZiB0aGUgYm94XG5cdCAqIEBwYXJhbSBmaWxsZWQgQSBib29sZWFuIGZvciB3aGV0aGVyIG9yIG5vdCB0aGUgYm94IGlzIGZpbGxlZFxuXHQgKiBAcGFyYW0gY29sb3IgVGhlIGNvbG9yIG9mIHRoZSBib3ggdG8gZHJhd1xuXHQgKi9cblx0c3RhdGljIGRyYXdCb3goY2VudGVyOiBWZWMyLCBoYWxmU2l6ZTogVmVjMiwgZmlsbGVkOiBib29sZWFuLCBjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHRsZXQgYWxwaGEgPSB0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5nbG9iYWxBbHBoYTtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5nbG9iYWxBbHBoYSA9IGNvbG9yLmE7XG5cblx0XHRpZihmaWxsZWQpe1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZmlsbFN0eWxlID0gY29sb3IudG9TdHJpbmcoKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmZpbGxSZWN0KGNlbnRlci54IC0gaGFsZlNpemUueCwgY2VudGVyLnkgLSBoYWxmU2l6ZS55LCBoYWxmU2l6ZS54KjIsIGhhbGZTaXplLnkqMik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxldCBsaW5lV2lkdGggPSAyO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQubGluZVdpZHRoID0gbGluZVdpZHRoO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuc3Ryb2tlU3R5bGUgPSBjb2xvci50b1N0cmluZygpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuc3Ryb2tlUmVjdChjZW50ZXIueCAtIGhhbGZTaXplLngsIGNlbnRlci55IC0gaGFsZlNpemUueSwgaGFsZlNpemUueCoyLCBoYWxmU2l6ZS55KjIpO1xuXHRcdH1cblxuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lmdsb2JhbEFscGhhID0gYWxwaGE7XG5cdH1cblxuXHQvKipcblx0ICogRHJhd3MgYSBjaXJjbGUgYXQgdGhlIHNwZWNpZmllZCBwb3NpdGlvblxuXHQgKiBAcGFyYW0gY2VudGVyIFRoZSBjZW50ZXIgb2YgdGhlIGNpcmNsZVxuXHQgKiBAcGFyYW0gcmFkaXVzIFRoZSBkaW1lbnNpb25zIG9mIHRoZSBib3hcblx0ICogQHBhcmFtIGZpbGxlZCBBIGJvb2xlYW4gZm9yIHdoZXRoZXIgb3Igbm90IHRoZSBjaXJjbGUgaXMgZmlsbGVkXG5cdCAqIEBwYXJhbSBjb2xvciBUaGUgY29sb3Igb2YgdGhlIGNpcmNsZVxuXHQgKi9cblx0c3RhdGljIGRyYXdDaXJjbGUoY2VudGVyOiBWZWMyLCByYWRpdXM6IG51bWJlciwgZmlsbGVkOiBib29sZWFuLCBjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHRsZXQgYWxwaGEgPSB0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5nbG9iYWxBbHBoYTtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5nbG9iYWxBbHBoYSA9IGNvbG9yLmE7XG5cblx0XHRpZihmaWxsZWQpe1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZmlsbFN0eWxlID0gY29sb3IudG9TdHJpbmcoKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmJlZ2luUGF0aCgpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuYXJjKGNlbnRlci54LCBjZW50ZXIueSwgcmFkaXVzLCAwLCAyICogTWF0aC5QSSk7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5jbG9zZVBhdGgoKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmZpbGwoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IGxpbmVXaWR0aCA9IDI7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5zdHJva2VTdHlsZSA9IGNvbG9yLnRvU3RyaW5nKCk7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5iZWdpblBhdGgoKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmFyYyhjZW50ZXIueCwgY2VudGVyLnksIHJhZGl1cywgMCwgMiAqIE1hdGguUEkpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuY2xvc2VQYXRoKCk7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5zdHJva2UoKTtcblx0XHR9XG5cblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5nbG9iYWxBbHBoYSA9IGFscGhhO1xuXHR9XG5cblx0LyoqXG5cdCAqIERyYXdzIGEgcmF5IGF0IHRoZSBzcGVjaWZpZWQgcG9zaXRpb25cblx0ICogQHBhcmFtIGZyb20gVGhlIHN0YXJ0aW5nIHBvc2l0aW9uIG9mIHRoZSByYXlcblx0ICogQHBhcmFtIHRvIFRoZSBlbmRpbmcgcG9zaXRpb24gb2YgdGhlIHJheVxuXHQgKiBAcGFyYW0gY29sb3IgVGhlIGNvbG9yIG9mIHRoZSByYXlcblx0ICovXG5cdHN0YXRpYyBkcmF3UmF5KGZyb206IFZlYzIsIHRvOiBWZWMyLCBjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5saW5lV2lkdGggPSAyO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LnN0cm9rZVN0eWxlID0gY29sb3IudG9TdHJpbmcoKTtcblxuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmJlZ2luUGF0aCgpO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lm1vdmVUbyhmcm9tLngsIGZyb20ueSk7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQubGluZVRvKHRvLngsIHRvLnkpO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmNsb3NlUGF0aCgpO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LnN0cm9rZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERyYXdzIGEgcG9pbnQgYXQgdGhlIHNwZWNpZmllZCBwb3NpdGlvblxuXHQgKiBAcGFyYW0gcG9zIFRoZSBwb3NpdGlvbiBvZiB0aGUgcG9pbnRcblx0ICogQHBhcmFtIGNvbG9yIFRoZSBjb2xvciBvZiB0aGUgcG9pbnRcblx0ICovXG5cdHN0YXRpYyBkcmF3UG9pbnQocG9zOiBWZWMyLCBjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHRsZXQgcG9pbnRTaXplID0gNjtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5maWxsU3R5bGUgPSBjb2xvci50b1N0cmluZygpO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmZpbGxSZWN0KHBvcy54IC0gcG9pbnRTaXplLzIsIHBvcy55IC0gcG9pbnRTaXplLzIsIHBvaW50U2l6ZSwgcG9pbnRTaXplKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBkZWZhdWx0IHJlbmRlcmluZyBjb2xvciBmb3IgdGV4dCBmb3IgdGhlIGRlYnVnZ2VyXG5cdCAqIEBwYXJhbSBjb2xvciBUaGUgY29sb3IgdG8gcmVuZGVyIHRoZSB0ZXh0XG5cdCAqL1xuXHRzdGF0aWMgc2V0RGVmYXVsdFRleHRDb2xvcihjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHR0aGlzLmRlZmF1bHRUZXh0Q29sb3IgPSBjb2xvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBQZXJmb3JtcyBhbnkgbmVjZXNzYXJ5IHNldHVwIG9wZXJhdGlvbnMgb24gdGhlIERlYnVnIGNhbnZhc1xuXHQgKiBAcGFyYW0gY2FudmFzIFRoZSBkZWJ1ZyBjYW52YXNcblx0ICogQHBhcmFtIHdpZHRoIFRoZSBkZXNpcmVkIHdpZHRoIG9mIHRoZSBjYW52YXNcblx0ICogQHBhcmFtIGhlaWdodCBUaGUgZGVzaXJlZCBoZWlnaHQgb2YgdGhlIGNhbnZhc1xuXHQgKiBAcmV0dXJucyBUaGUgcmVuZGVyaW5nIGNvbnRleHQgZXh0cmFjdGVkIGZyb20gdGhlIGNhbnZhc1xuXHQgKi9cblx0c3RhdGljIGluaXRpYWxpemVEZWJ1Z0NhbnZhcyhjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCB7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuXHRcdGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cdFx0XG5cdFx0dGhpcy5kZWJ1Z0NhbnZhc1NpemUgPSBuZXcgVmVjMih3aWR0aCwgaGVpZ2h0KTtcblxuICAgICAgICB0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0O1xuXHR9XG5cblx0LyoqIENsZWFycyB0aGUgZGVidWcgY2FudmFzICovXG5cdHN0YXRpYyBjbGVhckNhbnZhcygpOiB2b2lkIHtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5jbGVhclJlY3QoMCwgMCwgdGhpcy5kZWJ1Z0NhbnZhc1NpemUueCwgdGhpcy5kZWJ1Z0NhbnZhc1NpemUueSk7XG5cdH1cblxuXHQvKiogUmVuZGVycyB0aGUgdGV4dCBhbmQgbm9kZXMgc2VudCB0byB0aGUgRGVidWcgc3lzdGVtICovXG5cdHN0YXRpYyByZW5kZXIoKTogdm9pZCB7XG5cdFx0dGhpcy5yZW5kZXJUZXh0KCk7XG5cdFx0dGhpcy5yZW5kZXJOb2RlcygpO1xuXHR9XG5cblx0LyoqIFJlbmRlcnMgdGhlIHRleHQgc2VudCB0byB0aGUgRGVidWcgY2FudmFzICovXG5cdHN0YXRpYyByZW5kZXJUZXh0KCk6IHZvaWQge1xuXHRcdGxldCB5ID0gMjA7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZm9udCA9IFwiMjBweCBBcmlhbFwiO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmZpbGxTdHlsZSA9IHRoaXMuZGVmYXVsdFRleHRDb2xvci50b1N0cmluZygpO1xuXG5cdFx0Ly8gRHJhdyBhbGwgb2YgdGhlIHRleHRcblx0XHR0aGlzLmxvZ01lc3NhZ2VzLmZvckVhY2goKGtleTogc3RyaW5nKSA9PiB7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5maWxsVGV4dCh0aGlzLmxvZ01lc3NhZ2VzLmdldChrZXkpLCAxMCwgeSlcblx0XHRcdHkgKz0gMzA7XHRcblx0XHR9KTtcblx0fVxuXG5cdC8qKiBSZW5kZXJzIHRoZSBub2RlcyByZWdpc3RlcmVkIHdpdGggdGhlIGRlYnVnIGNhbnZhcyAqL1xuXHRzdGF0aWMgcmVuZGVyTm9kZXMoKTogdm9pZCB7XG5cdFx0aWYodGhpcy5ub2Rlcyl7XG5cdFx0XHR0aGlzLm5vZGVzLmZvckVhY2gobm9kZSA9PiB7XG5cdFx0XHRcdG5vZGUuZGVidWdSZW5kZXIoKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufSIsImltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcblxuLy8gQGlnbm9yZVBhZ2VcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN0YXRzIGV4dGVuZHMgT2JqZWN0IHtcbiAgICAvLyBUaGUgZnBzIG9mIHRoZSBnYW1lLlxuICAgIHByaXZhdGUgc3RhdGljIHByZXZmcHM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTlVNX1BPSU5UUzogbnVtYmVyID0gNjA7XG4gICAgcHJpdmF0ZSBzdGF0aWMgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG4gICAgcHJpdmF0ZSBzdGF0aWMgQ0FOVkFTX1dJRFRIOiBudW1iZXIgPSAzMDA7XG4gICAgcHJpdmF0ZSBzdGF0aWMgQ0FOVkFTX0hFSUdIVDogbnVtYmVyID0gMzAwO1xuICAgIHByaXZhdGUgc3RhdGljIHN0YXRzRGl2OiBIVE1MRGl2RWxlbWVudDtcbiAgICBwcml2YXRlIHN0YXRpYyBncmFwaENob2ljZXM6IEhUTUxTZWxlY3RFbGVtZW50O1xuXG4gICAgLy8gUXVhZHRyZWUgc3RhdHNcbiAgICBwcml2YXRlIHN0YXRpYyBwcmV2Q2xlYXJUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBTR0NsZWFyVGltZXM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgYXZnU0dDbGVhclRpbWU6IG51bWJlcjtcblxuICAgIHByaXZhdGUgc3RhdGljIHByZXZGaWxsVGltZXM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgU0dGaWxsVGltZXM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgYXZnU0dGaWxsVGltZTogbnVtYmVyO1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgcHJldlVwZGF0ZVRpbWVzOiBBcnJheTxudW1iZXI+O1xuICAgIHByaXZhdGUgc3RhdGljIFNHVXBkYXRlVGltZXM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgYXZnU0dVcGRhdGVUaW1lOiBudW1iZXI7XG5cbiAgICBwcml2YXRlIHN0YXRpYyBwcmV2UXVlcnlUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBTR1F1ZXJ5VGltZXM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgYXZnU0dRdWVyeVRpbWU6IG51bWJlcjtcblxuICAgIHN0YXRpYyBpbml0U3RhdHMoKTogdm9pZCB7XG4gICAgICAgIGxldCBjYW52YXMgPSA8SFRNTENhbnZhc0VsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdGF0cy1jYW52YXNcIik7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHRoaXMuQ0FOVkFTX1dJRFRIO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gdGhpcy5DQU5WQVNfSEVJR0hUO1xuICAgICAgICB0aGlzLmN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICAgICAgdGhpcy5zdGF0c0RpdiA9IDxIVE1MRGl2RWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXRzLWRpc3BsYXlcIik7XG5cbiAgICAgICAgdGhpcy5wcmV2ZnBzID0gbmV3IEFycmF5KCk7XG5cbiAgICAgICAgdGhpcy5wcmV2Q2xlYXJUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLlNHQ2xlYXJUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLmF2Z1NHQ2xlYXJUaW1lID0gMDtcblxuICAgICAgICB0aGlzLnByZXZGaWxsVGltZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5TR0ZpbGxUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLmF2Z1NHRmlsbFRpbWUgPSAwO1xuXG4gICAgICAgIHRoaXMucHJldlVwZGF0ZVRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuU0dVcGRhdGVUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLmF2Z1NHVXBkYXRlVGltZSA9IDA7XG5cbiAgICAgICAgdGhpcy5wcmV2UXVlcnlUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLlNHUXVlcnlUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLmF2Z1NHUXVlcnlUaW1lID0gMDtcblxuICAgICAgICBsZXQgY2xlYXJUaW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIGNsZWFyVGltZS5zZXRBdHRyaWJ1dGUoXCJpZFwiLCBcInNnY2xlYXJcIik7XG4gICAgICAgIGxldCBmaWxsVGltZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICBmaWxsVGltZS5zZXRBdHRyaWJ1dGUoXCJpZFwiLCBcInNnZmlsbFwiKTtcbiAgICAgICAgbGV0IHVwZGF0ZVRpbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdXBkYXRlVGltZS5zZXRBdHRyaWJ1dGUoXCJpZFwiLCBcInNndXBkYXRlXCIpO1xuICAgICAgICBsZXQgcXVlcnlUaW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIHF1ZXJ5VGltZS5zZXRBdHRyaWJ1dGUoXCJpZFwiLCBcInNncXVlcnlcIik7XG4gICAgICAgIGxldCBicjEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYnJcIik7XG4gICAgICAgIGxldCBicjIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYnJcIik7XG4gICAgICAgIGxldCBicjMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYnJcIik7XG5cbiAgICAgICAgdGhpcy5zdGF0c0Rpdi5hcHBlbmQoY2xlYXJUaW1lLCBicjEsIGZpbGxUaW1lLCBicjIsIHVwZGF0ZVRpbWUsIGJyMywgcXVlcnlUaW1lKTtcblxuICAgICAgICB0aGlzLmdyYXBoQ2hvaWNlcyA9IDxIVE1MU2VsZWN0RWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImNoYXJ0LW9wdGlvblwiKTtcbiAgICAgICAgbGV0IG9wdGlvbjEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwib3B0aW9uXCIpO1xuICAgICAgICBvcHRpb24xLnZhbHVlID0gXCJwcmV2ZnBzXCI7XG4gICAgICAgIG9wdGlvbjEubGFiZWwgPSBcIkZQU1wiO1xuICAgICAgICBsZXQgb3B0aW9uMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbjIudmFsdWUgPSBcInByZXZDbGVhclRpbWVzXCI7XG4gICAgICAgIG9wdGlvbjIubGFiZWwgPSBcIkNsZWFyIFRpbWVcIjtcbiAgICAgICAgbGV0IG9wdGlvbjMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwib3B0aW9uXCIpO1xuICAgICAgICBvcHRpb24zLnZhbHVlID0gXCJwcmV2RmlsbFRpbWVzXCI7XG4gICAgICAgIG9wdGlvbjMubGFiZWwgPSBcIkZpbGwgdGltZVwiO1xuICAgICAgICBsZXQgb3B0aW9uNCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbjQudmFsdWUgPSBcInByZXZVcGRhdGVUaW1lc1wiO1xuICAgICAgICBvcHRpb240LmxhYmVsID0gXCJVcGRhdGUgdGltZVwiO1xuICAgICAgICBsZXQgb3B0aW9uNSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbjUudmFsdWUgPSBcInByZXZRdWVyeVRpbWVzXCI7XG4gICAgICAgIG9wdGlvbjUubGFiZWwgPSBcIlF1ZXJ5IFRpbWVcIjtcbiAgICAgICAgbGV0IG9wdGlvbkFsbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbkFsbC52YWx1ZSA9IFwiYWxsXCI7XG4gICAgICAgIG9wdGlvbkFsbC5sYWJlbCA9IFwiQWxsXCI7XG4gICAgICAgIHRoaXMuZ3JhcGhDaG9pY2VzLmFwcGVuZChvcHRpb24xLCBvcHRpb24yLCBvcHRpb24zLCBvcHRpb240LCBvcHRpb241LCBvcHRpb25BbGwpO1xuICAgIH1cblxuICAgIHN0YXRpYyB1cGRhdGVGUFMoZnBzOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wcmV2ZnBzLnB1c2goZnBzKTtcbiAgICAgICAgaWYodGhpcy5wcmV2ZnBzLmxlbmd0aCA+IFN0YXRzLk5VTV9QT0lOVFMpe1xuICAgICAgICAgICAgdGhpcy5wcmV2ZnBzLnNoaWZ0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLlNHQ2xlYXJUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgIHRoaXMucHJldkNsZWFyVGltZXMucHVzaCh0aGlzLmF2Z1NHQ2xlYXJUaW1lKTtcbiAgICAgICAgICAgIGlmKHRoaXMucHJldkNsZWFyVGltZXMubGVuZ3RoID4gdGhpcy5OVU1fUE9JTlRTKXtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZDbGVhclRpbWVzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYodGhpcy5TR0ZpbGxUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgIHRoaXMucHJldkZpbGxUaW1lcy5wdXNoKHRoaXMuYXZnU0dGaWxsVGltZSk7XG4gICAgICAgICAgICBpZih0aGlzLnByZXZGaWxsVGltZXMubGVuZ3RoID4gdGhpcy5OVU1fUE9JTlRTKXtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZGaWxsVGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLlNHVXBkYXRlVGltZXMubGVuZ3RoID4gMCl7XG4gICAgICAgICAgICB0aGlzLnByZXZVcGRhdGVUaW1lcy5wdXNoKHRoaXMuYXZnU0dVcGRhdGVUaW1lKTtcbiAgICAgICAgICAgIGlmKHRoaXMucHJldlVwZGF0ZVRpbWVzLmxlbmd0aCA+IHRoaXMuTlVNX1BPSU5UUyl7XG4gICAgICAgICAgICAgICAgdGhpcy5wcmV2VXBkYXRlVGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLlNHUXVlcnlUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgIHRoaXMucHJldlF1ZXJ5VGltZXMucHVzaCh0aGlzLmF2Z1NHUXVlcnlUaW1lKTtcbiAgICAgICAgICAgIGlmKHRoaXMucHJldlF1ZXJ5VGltZXMubGVuZ3RoID4gdGhpcy5OVU1fUE9JTlRTKXtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZRdWVyeVRpbWVzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnVwZGF0ZVNHU3RhdHMoKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgbG9nKGtleTogc3RyaW5nLCBkYXRhOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgaWYoa2V5ID09PSBcInNnY2xlYXJcIil7XG4gICAgICAgICAgICB0aGlzLlNHQ2xlYXJUaW1lcy5wdXNoKGRhdGEpO1xuICAgICAgICAgICAgaWYodGhpcy5TR0NsZWFyVGltZXMubGVuZ3RoID4gMTAwKXtcbiAgICAgICAgICAgICAgICB0aGlzLlNHQ2xlYXJUaW1lcy5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoa2V5ID09PSBcInNnZmlsbFwiKXtcbiAgICAgICAgICAgIHRoaXMuU0dGaWxsVGltZXMucHVzaChkYXRhKTtcbiAgICAgICAgICAgIGlmKHRoaXMuU0dGaWxsVGltZXMubGVuZ3RoID4gMTAwKXtcbiAgICAgICAgICAgICAgICB0aGlzLlNHRmlsbFRpbWVzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihrZXkgPT09IFwic2d1cGRhdGVcIil7XG4gICAgICAgICAgICB0aGlzLlNHVXBkYXRlVGltZXMucHVzaChkYXRhKTtcbiAgICAgICAgICAgIGlmKHRoaXMuU0dVcGRhdGVUaW1lcy5sZW5ndGggPiAxMDApe1xuICAgICAgICAgICAgICAgIHRoaXMuU0dVcGRhdGVUaW1lcy5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoa2V5ID09PSBcInNncXVlcnlcIil7XG4gICAgICAgICAgICB0aGlzLlNHUXVlcnlUaW1lcy5wdXNoKGRhdGEpO1xuICAgICAgICAgICAgaWYodGhpcy5TR1F1ZXJ5VGltZXMubGVuZ3RoID4gMTAwMCl7XG4gICAgICAgICAgICAgICAgdGhpcy5TR1F1ZXJ5VGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgc3RhdGljIHJlbmRlcigpOiB2b2lkIHtcbiAgICAgICAgLy8gRGlzcGxheSBzdGF0c1xuICAgICAgICB0aGlzLmRyYXdDaGFydHMoKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZHJhd0NoYXJ0cygpe1xuICAgICAgICB0aGlzLmN0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5DQU5WQVNfV0lEVEgsIHRoaXMuQ0FOVkFTX0hFSUdIVCk7XG5cbiAgICAgICAgbGV0IHBhcmFtU3RyaW5nID0gdGhpcy5ncmFwaENob2ljZXMudmFsdWU7XG5cbiAgICAgICAgaWYocGFyYW1TdHJpbmcgPT09IFwicHJldmZwc1wiIHx8IHBhcmFtU3RyaW5nID09PSBcImFsbFwiKXtcbiAgICAgICAgICAgIGxldCBwYXJhbSA9IHRoaXMucHJldmZwcztcbiAgICAgICAgICAgIGxldCBjb2xvciA9IENvbG9yLkJMVUUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NoYXJ0KHBhcmFtLCBjb2xvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYocGFyYW1TdHJpbmcgPT09IFwicHJldkNsZWFyVGltZXNcIiB8fCBwYXJhbVN0cmluZyA9PT0gXCJhbGxcIil7XG4gICAgICAgICAgICBsZXQgcGFyYW0gPSB0aGlzLnByZXZDbGVhclRpbWVzO1xuICAgICAgICAgICAgbGV0IGNvbG9yID0gQ29sb3IuUkVELnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB0aGlzLmRyYXdDaGFydChwYXJhbSwgY29sb3IpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHBhcmFtU3RyaW5nID09PSBcInByZXZGaWxsVGltZXNcIiB8fCBwYXJhbVN0cmluZyA9PT0gXCJhbGxcIil7XG4gICAgICAgICAgICBsZXQgcGFyYW0gPSB0aGlzLnByZXZGaWxsVGltZXM7XG4gICAgICAgICAgICBsZXQgY29sb3IgPSBDb2xvci5HUkVFTi50b1N0cmluZygpO1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2hhcnQocGFyYW0sIGNvbG9yKTtcbiAgICAgICAgfVxuICAgICAgICBpZihwYXJhbVN0cmluZyA9PT0gXCJwcmV2VXBkYXRlVGltZXNcIiB8fCBwYXJhbVN0cmluZyA9PT0gXCJhbGxcIil7XG4gICAgICAgICAgICBsZXQgcGFyYW0gPSB0aGlzLnByZXZVcGRhdGVUaW1lcztcbiAgICAgICAgICAgIGxldCBjb2xvciA9IENvbG9yLkNZQU4udG9TdHJpbmcoKTtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NoYXJ0KHBhcmFtLCBjb2xvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYocGFyYW1TdHJpbmcgPT09IFwicHJldlF1ZXJ5VGltZXNcIiB8fCBwYXJhbVN0cmluZyA9PT0gXCJhbGxcIil7XG4gICAgICAgICAgICBsZXQgcGFyYW0gPSB0aGlzLnByZXZRdWVyeVRpbWVzO1xuICAgICAgICAgICAgbGV0IGNvbG9yID0gQ29sb3IuT1JBTkdFLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB0aGlzLmRyYXdDaGFydChwYXJhbSwgY29sb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGRyYXdDaGFydChwYXJhbTogQXJyYXk8bnVtYmVyPiwgY29sb3I6IHN0cmluZyl7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gQ29sb3IuQkxBQ0sudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4Lm1vdmVUbygxMCwgMTApO1xuICAgICAgICB0aGlzLmN0eC5saW5lVG8oMTAsIHRoaXMuQ0FOVkFTX0hFSUdIVCAtIDEwKTtcbiAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZSgpO1xuICAgICAgICB0aGlzLmN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHgubW92ZVRvKDEwLCB0aGlzLkNBTlZBU19IRUlHSFQgLSAxMCk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVUbyh0aGlzLkNBTlZBU19XSURUSCAtIDEwLCB0aGlzLkNBTlZBU19IRUlHSFQgLSAxMCk7XG4gICAgICAgIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcblxuICAgICAgICBsZXQgbWF4ID0gTWF0aC5tYXgoLi4ucGFyYW0pO1xuICAgICAgICBsZXQgcHJldlggPSAxMDtcbiAgICAgICAgbGV0IHByZXZZID0gdGhpcy5DQU5WQVNfSEVJR0hUIC0gMTAgLSBwYXJhbVswXS9tYXgqKHRoaXMuQ0FOVkFTX0hFSUdIVC0yMCk7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gY29sb3I7XG5cbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IHBhcmFtLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIGxldCBmcHMgPSBwYXJhbVtpXTtcbiAgICAgICAgICAgIGxldCB4ID0gMTAgKyBpKih0aGlzLkNBTlZBU19XSURUSCAtIDIwKS90aGlzLk5VTV9QT0lOVFM7XG4gICAgICAgICAgICBsZXQgeSA9IHRoaXMuQ0FOVkFTX0hFSUdIVCAtIDEwIC0gZnBzL21heCoodGhpcy5DQU5WQVNfSEVJR0hULTIwKVxuICAgICAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5tb3ZlVG8ocHJldlgsIHByZXZZKTtcbiAgICAgICAgICAgIHRoaXMuY3R4LmxpbmVUbyh4LCB5KTtcbiAgICAgICAgICAgIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICAgICAgdGhpcy5jdHguc3Ryb2tlKCk7XG5cbiAgICAgICAgICAgIHByZXZYID0geDtcbiAgICAgICAgICAgIHByZXZZID0geTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyB1cGRhdGVTR1N0YXRzKCl7XG4gICAgICAgIGlmKHRoaXMuU0dDbGVhclRpbWVzLmxlbmd0aCA+IDApe1xuICAgICAgICAgICAgdGhpcy5hdmdTR0NsZWFyVGltZSA9IHRoaXMuU0dDbGVhclRpbWVzLnJlZHVjZSgoYWNjLCB2YWwpID0+IGFjYyArIHZhbCkvdGhpcy5TR0NsZWFyVGltZXMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5TR0ZpbGxUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgIHRoaXMuYXZnU0dGaWxsVGltZSA9IHRoaXMuU0dGaWxsVGltZXMucmVkdWNlKChhY2MsIHZhbCkgPT4gYWNjICsgdmFsKS90aGlzLlNHRmlsbFRpbWVzLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMuU0dVcGRhdGVUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgdGhpcy5hdmdTR1VwZGF0ZVRpbWUgPSB0aGlzLlNHVXBkYXRlVGltZXMucmVkdWNlKChhY2MsIHZhbCkgPT4gYWNjICsgdmFsKS90aGlzLlNHVXBkYXRlVGltZXMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5TR1F1ZXJ5VGltZXMubGVuZ3RoID4gMCl7XG4gICAgICAgICAgICB0aGlzLmF2Z1NHUXVlcnlUaW1lID0gdGhpcy5TR1F1ZXJ5VGltZXMucmVkdWNlKChhY2MsIHZhbCkgPT4gYWNjICsgdmFsKS90aGlzLlNHUXVlcnlUaW1lcy5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNnY2xlYXJcIikuaW5uZXJIVE1MID0gXCJBdmcgU0cgY2xlYXIgdGltZTogXCIgKyB0aGlzLmF2Z1NHQ2xlYXJUaW1lO1xuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNnZmlsbFwiKS5pbm5lckhUTUwgPSBcIkF2ZyBTRyBmaWxsIHRpbWU6IFwiICsgdGhpcy5hdmdTR0ZpbGxUaW1lO1xuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNndXBkYXRlXCIpLmlubmVySFRNTCA9IFwiQXZnIFNHIHVwZGF0ZSB0aW1lOiBcIiArIHRoaXMuYXZnU0dVcGRhdGVUaW1lO1xuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInNncXVlcnlcIikuaW5uZXJIVE1MID0gXCJBdmcgU0cgcXVlcnkgdGltZTogXCIgKyB0aGlzLmF2Z1NHUXVlcnlUaW1lO1xuICAgIH1cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgRXZlbnRRdWV1ZSBmcm9tIFwiLi9FdmVudFF1ZXVlXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuL0dhbWVFdmVudFwiO1xuXG4vKipcbiAqIEFuIGV2ZW50IGVtaXR0ZXIgb2JqZWN0IG90aGVyIHN5c3RlbXMgY2FuIHVzZSB0byBob29rIGludG8gdGhlIEV2ZW50UXVldWUuXG4gKiBQcm92aWRlcyBhbiBlYXN5IGludGVyZmFjZSBmb3IgZmlyaW5nIG9mZiBldmVudHMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEVtaXR0ZXIge1xuXHQvKiogQSByZWZlcmVuY2UgdG8gdGhlIEV2ZW50UXVldWUgKi9cblx0cHJpdmF0ZSBldmVudFF1ZXVlOiBFdmVudFF1ZXVlO1xuXG5cdC8qKiBDcmVhdGVzIGEgbmV3IEVtaXR0ZXIgKi9cblx0Y29uc3RydWN0b3IoKXtcblx0XHR0aGlzLmV2ZW50UXVldWUgPSBFdmVudFF1ZXVlLmdldEluc3RhbmNlKCk7XG5cdH1cblxuXHQvKipcblx0ICogRW1pdCBhbmQgZXZlbnQgb2YgdHlwZSBldmVudFR5cGUgd2l0aCB0aGUgZGF0YSBwYWNrZXQgZGF0YVxuXHQgKiBAcGFyYW0gZXZlbnRUeXBlIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBmaXJlIG9mZlxuXHQgKiBAcGFyYW0gZGF0YSBBIEByZWZlcmVuY2VbTWFwXSBvciByZWNvcmQgY29udGFpbmluZyBhbnkgZGF0YSBhYm91dCB0aGUgZXZlbnRcblx0ICovXG5cdGZpcmVFdmVudChldmVudFR5cGU6IHN0cmluZywgZGF0YTogTWFwPGFueT4gfCBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gbnVsbCk6IHZvaWQge1xuXHRcdHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChuZXcgR2FtZUV2ZW50KGV2ZW50VHlwZSwgZGF0YSkpO1xuXHR9XG59IiwiaW1wb3J0IFF1ZXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvUXVldWVcIjtcbmltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4vR2FtZUV2ZW50XCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4vUmVjZWl2ZXJcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi9HYW1lRXZlbnRUeXBlXCI7XG5cbi8qKlxuICogVGhlIG1haW4gZXZlbnQgc3lzdGVtIG9mIHRoZSBnYW1lIGVuZ2luZS5cbiAqIEV2ZW50cyBhcmUgc2VudCB0byB0aGUgRXZlbnRRdWV1ZSwgd2hpY2ggaGFuZGxlcyBkaXN0cmlidXRpb24gdG8gYW55IHN5c3RlbXMgdGhhdCBhcmUgbGlzdGVuaW5nIGZvciB0aG9zZSBldmVudHMuXG4gKiBUaGlzIGFsbG93cyBmb3IgaGFuZGxpbmcgb2YgaW5wdXQgd2l0aG91dCBoYXZpbmcgY2xhc3NlcyBkaXJlY3RseSBob29rIGludG8gamF2YXNjcmlwdCBldmVudCBoYW5kbGVzLCBcbiAqIGFuZCBhbGxvd3Mgb3RoZXJ3aXNlIHNlcGFyYXRlIGNsYXNzZXMgdG8gY29tbXVuaWNhdGUgd2l0aCBlYWNoIG90aGVyIGNsZWFubHksIHN1Y2ggYXMgYSBQbGF5ZXIgb2JqZWN0IFxuICogcmVxdWVzdGluZyBhIHNvdW5kIGJlIHBsYXllZCBieSB0aGUgYXVkaW8gc3lzdGVtLlxuICogXG4gKiBUaGUgZGlzdHJpYnV0aW9uIG9mIEByZWZlcmVuY2VbR2FtZUV2ZW50XXMgaGFwcGVucyBhcyBmb2xsb3dzOlxuICogXG4gKiBFdmVudHMgYXJlIHJlY2lldmVkIHRocm91Z2hvdXQgYSBmcmFtZSBhbmQgYXJlIHF1ZXVlZCB1cCBieSB0aGUgRXZlbnRRdWV1ZS5cbiAqIEF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIG5leHQgZnJhbWUsIGV2ZW50cyBhcmUgc2VudCBvdXQgdG8gYW55IHJlY2VpdmVycyB0aGF0IGFyZSBob29rZWQgaW50byB0aGUgZXZlbnQgdHlwZS5cbiAqIEByZWZlcmVuY2VbUmVjZWl2ZXJdcyBhcmUgdGhlbiBmcmVlIHRvIHByb2Nlc3MgZXZlbnRzIGFzIHRoZXkgc2VlIGZpdC5cbiAqIFxuICogT3ZlcmFsbCwgdGhlIEV2ZW50UXVldWUgY2FuIGJlIGNvbnNpZGVyZWQgYXMgc29tZXRoaW5nIHNpbWlsYXIgdG8gYW4gZW1haWwgc2VydmVyLFxuICogYW5kIHRoZSBAcmVmZXJlbmNlW1JlY2VpdmVyXXMgY2FuIGJlIGNvbnNpZGVyZWQgYXMgdGhlIGNsaWVudCBpbmJveGVzLlxuICogXG4gKiBTZWUgQGxpbmsoR2FtZSBQcm9ncmFtbWluZyBQYXR0ZXJucykoaHR0cHM6Ly9nYW1lcHJvZ3JhbW1pbmdwYXR0ZXJucy5jb20vZXZlbnQtcXVldWUuaHRtbCkgZm9yIG1vcmUgZGlzY3Vzc2lvbiBvbiBFdmVudFF1ZXVlc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFdmVudFF1ZXVlIHtcbiAgICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogRXZlbnRRdWV1ZSA9IG51bGw7XG4gICAgXG4gICAgLyoqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBldmVudHMgdmlzaWJsZSAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgTUFYX1NJWkU6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIGFjdHVhbCBxdWV1ZSBvZiBldmVudHMgKi9cbiAgICBwcml2YXRlIHE6IFF1ZXVlPEdhbWVFdmVudD47XG4gICAgXG4gICAgLyoqIFRoZSBtYXAgb2YgcmVjZWl2ZXJzIHJlZ2lzdGVyZWQgZm9yIGFuIGV2ZW50IG5hbWUgKi9cblx0cHJpdmF0ZSByZWNlaXZlcnM6IE1hcDxBcnJheTxSZWNlaXZlcj4+O1xuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLk1BWF9TSVpFID0gMTAwO1xuICAgICAgICB0aGlzLnEgPSBuZXcgUXVldWU8R2FtZUV2ZW50Pih0aGlzLk1BWF9TSVpFKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlcnMgPSBuZXcgTWFwPEFycmF5PFJlY2VpdmVyPj4oKTtcblx0fVxuICAgIFxuICAgIC8qKiBSZXRyaWV2ZXMgdGhlIGluc3RhbmNlIG9mIHRoZSBTaW5nbGV0b24gRXZlbnRRdWV1ZSAqL1xuXHRzdGF0aWMgZ2V0SW5zdGFuY2UoKTogRXZlbnRRdWV1ZSB7XG5cdFx0aWYodGhpcy5pbnN0YW5jZSA9PT0gbnVsbCl7XG5cdFx0XHR0aGlzLmluc3RhbmNlID0gbmV3IEV2ZW50UXVldWUoKTtcblx0XHR9XG5cdFx0XG5cdFx0cmV0dXJuIHRoaXMuaW5zdGFuY2U7XG5cdH1cblxuICAgIC8qKiBBZGRzIGFuIGV2ZW50IHRvIHRoZSBFdmVudFF1ZXVlLlxuICAgICAqIFRoaXMgaXMgZXhwb3NlZCB0byB0aGUgcmVzdCBvZiB0aGUgZ2FtZSBlbmdpbmUgdGhyb3VnaCB0aGUgQHJlZmVyZW5jZVtFbWl0dGVyXSBjbGFzcyAqL1xuICAgIGFkZEV2ZW50KGV2ZW50OiBHYW1lRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5xLmVucXVldWUoZXZlbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzc29jaWF0ZXMgYSByZWNlaXZlciB3aXRoIGEgdHlwZSBvZiBldmVudC4gRXZlcnkgdGltZSB0aGlzIGV2ZW50IGFwcGVhcnMgaW4gdGhlIGZ1dHVyZSxcbiAgICAgKiBpdCB3aWxsIGJlIGdpdmVuIHRvIHRoZSByZWNlaXZlciAoYW5kIGFueSBvdGhlcnMgd2F0Y2hpbmcgdGhhdCB0eXBlKS5cbiAgICAgKiBUaGlzIGlzIGV4cG9zZWQgdG8gdGhlIHJlc3Qgb2YgdGhlIGdhbWUgZW5naW5lIHRocm91Z2ggdGhlIEByZWZlcmVuY2VbUmVjZWl2ZXJdIGNsYXNzXG4gICAgICogQHBhcmFtIHJlY2VpdmVyIFRoZSBldmVudCByZWNlaXZlclxuICAgICAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9yIHR5cGVzIG9mIGV2ZW50cyB0byBzdWJzY3JpYmUgdG9cbiAgICAgKi9cbiAgICBzdWJzY3JpYmUocmVjZWl2ZXI6IFJlY2VpdmVyLCB0eXBlOiBzdHJpbmcgfCBBcnJheTxzdHJpbmc+KTogdm9pZCB7XG4gICAgICAgIGlmKHR5cGUgaW5zdGFuY2VvZiBBcnJheSl7XG4gICAgICAgICAgICAvLyBJZiBpdCBpcyBhbiBhcnJheSwgc3Vic2NyaWJlIHRvIGFsbCBldmVudCB0eXBlc1xuICAgICAgICAgICAgZm9yKGxldCB0IG9mIHR5cGUpe1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkTGlzdGVuZXIocmVjZWl2ZXIsIHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZGRMaXN0ZW5lcihyZWNlaXZlciwgdHlwZSk7XG4gICAgICAgIH1cblx0fVxuXG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIHRoZSBzcGVjaWZpZWQgcmVjZWl2ZXIgZnJvbSBhbGwgZXZlbnRzLCBvciBmcm9tIHdoYXRldmVyIGV2ZW50cyBhcmUgcHJvdmlkZWRcbiAgICAgKiBAcGFyYW0gcmVjZWl2ZXIgVGhlIHJlY2VpdmVyIHRvIHVuc3Vic2NyaWJlXG4gICAgICogQHBhcmFtIGtleXMgVGhlIGV2ZW50cyB0byB1bnN1YnNjcmliZSBmcm9tLiBJZiBub25lIGFyZSBwcm92aWRlZCwgdW5zdWJzY3JpYmUgZnJvbSBhbGxcbiAgICAgKi9cbiAgICB1bnN1YnNjcmliZShyZWNlaXZlcjogUmVjZWl2ZXIsIC4uLmV2ZW50czogQXJyYXk8c3RyaW5nPik6IHZvaWQge1xuICAgICAgICB0aGlzLnJlY2VpdmVycy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICAvLyBJZiBrZXlzIHdlcmUgcHJvdmlkZWQsIG9ubHkgY29udGludWUgaWYgdGhpcyBrZXkgaXMgb25lIG9mIHRoZW1cbiAgICAgICAgICAgIGlmKGV2ZW50cy5sZW5ndGggPiAwICYmIGV2ZW50cy5pbmRleE9mKGV2ZW50TmFtZSkgPT09IC0xKSByZXR1cm47XG5cbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIGluZGV4IG9mIG91ciByZWNlaXZlciBmb3IgdGhpcyBrZXlcbiAgICAgICAgICAgIGxldCBpbmRleCA9IHRoaXMucmVjZWl2ZXJzLmdldChldmVudE5hbWUpLmluZGV4T2YocmVjZWl2ZXIpO1xuXG4gICAgICAgICAgICAvLyBJZiBhbiBpbmRleCB3YXMgZm91bmQsIHJlbW92ZSB0aGUgcmVjZWl2ZXJcbiAgICAgICAgICAgIGlmKGluZGV4ICE9PSAtMSl7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWNlaXZlcnMuZ2V0KGV2ZW50TmFtZSkuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQXNzb2NpYXRlIHRoZSByZWNlaXZlciBhbmQgdGhlIHR5cGVcblx0cHJpdmF0ZSBhZGRMaXN0ZW5lcihyZWNlaXZlcjogUmVjZWl2ZXIsIHR5cGU6IHN0cmluZyk6IHZvaWQge1xuXHRcdGlmKHRoaXMucmVjZWl2ZXJzLmhhcyh0eXBlKSl7XG5cdFx0XHR0aGlzLnJlY2VpdmVycy5nZXQodHlwZSkucHVzaChyZWNlaXZlcik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucmVjZWl2ZXJzLmFkZCh0eXBlLCBbcmVjZWl2ZXJdKTtcblx0XHR9XG5cdH1cbiAgICBcbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgd2hpbGUodGhpcy5xLmhhc0l0ZW1zKCkpe1xuICAgICAgICAgICAgLy8gUmV0cmlldmUgZWFjaCBldmVudFxuXHRcdFx0bGV0IGV2ZW50ID0gdGhpcy5xLmRlcXVldWUoKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gSWYgYSByZWNlaXZlciBoYXMgdGhpcyBldmVudCB0eXBlLCBzZW5kIGl0IHRoZSBldmVudFxuICAgICAgICAgICAgaWYodGhpcy5yZWNlaXZlcnMuaGFzKGV2ZW50LnR5cGUpKXtcbiAgICAgICAgICAgICAgICBmb3IobGV0IHJlY2VpdmVyIG9mIHRoaXMucmVjZWl2ZXJzLmdldChldmVudC50eXBlKSl7XG4gICAgICAgICAgICAgICAgICAgIHJlY2VpdmVyLnJlY2VpdmUoZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cblx0XHRcdH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gSWYgYSByZWNlaXZlciBpcyBzdWJzY3JpYmVkIHRvIGFsbCBldmVudHMsIHNlbmQgaXQgdGhlIGV2ZW50XG4gICAgICAgICAgICBpZih0aGlzLnJlY2VpdmVycy5oYXMoR2FtZUV2ZW50VHlwZS5BTEwpKXtcbiAgICAgICAgICAgICAgICBmb3IobGV0IHJlY2VpdmVyIG9mIHRoaXMucmVjZWl2ZXJzLmdldChHYW1lRXZlbnRUeXBlLkFMTCkpe1xuICAgICAgICAgICAgICAgICAgICByZWNlaXZlci5yZWNlaXZlKGV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiXG5cbi8qKlxuICogQSByZXByZXNlbnRhdGlvbiBvZiBhbiBpbi1nYW1lIGV2ZW50IHRoYXQgaXMgcGFzc2VkIHRocm91Z2ggdGhlIEByZWZlcmVuY2VbRXZlbnRRdWV1ZV1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2FtZUV2ZW50IHtcbiAgICAvKiogVGhlIHR5cGUgb2YgdGhlIGV2ZW50ICovXG4gICAgcHVibGljIHR5cGU6IHN0cmluZztcbiAgICAvKiogVGhlIGRhdGEgY29udGFpbmVkIGJ5IHRoZSBldmVudCAqL1xuICAgIHB1YmxpYyBkYXRhOiBNYXA8YW55PjtcbiAgICAvKiogVGhlIHRpbWUgb2YgdGhlIGV2ZW50IGluIG1zICovXG5cdHB1YmxpYyB0aW1lOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEdhbWVFdmVudC5cbiAgICAgKiBUaGlzIGlzIGhhbmRsZWQgaW1wbGljaXRseSB0aHJvdWdoIHRoZSBAcmVmZXJlbmNlW0VtaXR0ZXJdIGNsYXNzXG4gICAgICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgb2YgdGhlIEdhbWVFdmVudFxuICAgICAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIGNvbnRhaW5lZCBieSB0aGUgR2FtZUV2ZW50XG4gICAgICovXG4gICAgY29uc3RydWN0b3IodHlwZTogc3RyaW5nLCBkYXRhOiBNYXA8YW55PiB8IFJlY29yZDxzdHJpbmcsIGFueT4gPSBudWxsKSB7XG4gICAgICAgIC8vIFBhcnNlIHRoZSBnYW1lIGV2ZW50IGRhdGFcbiAgICAgICAgaWYgKGRhdGEgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IG5ldyBNYXA8YW55PigpO1xuICAgICAgICB9IGVsc2UgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIE1hcCkpe1xuICAgICAgICAgICAgLy8gZGF0YSBpcyBhIHJhdyBvYmplY3QsIHVucGFja1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gbmV3IE1hcDxhbnk+KCk7XG4gICAgICAgICAgICBmb3IobGV0IGtleSBpbiBkYXRhKXtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEuYWRkKGtleSwgZGF0YVtrZXldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLnRpbWUgPSBEYXRlLm5vdygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB0aGUgdHlwZSBvZiB0aGUgR2FtZUV2ZW50XG4gICAgICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBHYW1lRXZlbnQgaXMgdGhlIHNwZWNpZmllZCB0eXBlLCBmYWxzZSBvdGhlcndpc2UuXG4gICAgICovXG4gICAgaXNUeXBlKHR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy50eXBlID09PSB0eXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhpcyBHYW1lRXZlbnQgYXMgYSBzdHJpbmdcbiAgICAgKiBAcmV0dXJucyBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBHYW1lRXZlbnRcbiAgICAgKi9cbiAgICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy50eXBlICsgXCI6IEBcIiArIHRoaXMudGltZTtcbiAgICB9XG59IiwiLy8gQGlnbm9yZVBhZ2VcblxuZXhwb3J0IGVudW0gR2FtZUV2ZW50VHlwZSB7XG5cdC8qKlxuXHQgKiBNb3VzZSBEb3duIGV2ZW50LiBIYXMgZGF0YToge3Bvc2l0aW9uOiBWZWMyIC0gTW91c2UgUG9zaXRpb259XG5cdCAqL1xuXHRNT1VTRV9ET1dOID0gXCJtb3VzZV9kb3duXCIsXG5cdC8qKlxuXHQgKiBNb3VzZSBVcCBldmVudC4gSGFzIGRhdGE6IHtwb3NpdGlvbjogVmVjMiAtIE1vdXNlIFBvc2l0aW9ufVxuXHQgKi9cblx0TU9VU0VfVVAgPSBcIm1vdXNlX3VwXCIsXG5cdC8qKlxuXHQgKiBNb3VzZSBNb3ZlIGV2ZW50LiBIYXMgZGF0YToge3Bvc2l0aW9uOiBWZWMyIC0gTW91c2UgUG9zaXRpb259XG5cdCAqL1xuXHRNT1VTRV9NT1ZFID0gXCJtb3VzZV9tb3ZlXCIsXG5cblx0LyoqXG5cdCAqIEtleSBEb3duIGV2ZW50LiBIYXMgZGF0YToge2tleTogc3RyaW5nIC0gVGhlIGtleSB0aGF0IGlzIGRvd259XG5cdCAqL1xuXHRLRVlfRE9XTiA9IFwia2V5X2Rvd25cIixcblxuXHQvKipcblx0ICogS2V5IFVwIGV2ZW50LiBIYXMgZGF0YToge2tleTogc3RyaW5nIC0gVGhlIGtleSB0aGF0IGlzIHVwfVxuXHQgKi9cblx0S0VZX1VQID0gXCJrZXlfdXBcIixcblxuXHQvKipcblx0ICogQ2FudmFzIEJsdXIgZXZlbnQuIEhhcyBkYXRhOiB7fVxuXHQgKi9cblx0Q0FOVkFTX0JMVVIgPSBcImNhbnZhc19ibHVyXCIsXG5cblx0LyoqXG5cdCAqIE1vdXNlIHdoZWVsIHVwIGV2ZW50LiBIYXMgZGF0YToge31cblx0ICovXG5cdFdIRUVMX1VQID0gXCJ3aGVlbF91cFwiLFxuXG5cdC8qKlxuXHQgKiBNb3VzZSB3aGVlbCBkb3duIGV2ZW50LiBIYXMgZGF0YToge31cblx0ICovXG5cdFdIRUVMX0RPV04gPSBcIndoZWVsX2Rvd25cIixcblxuXHQvKipcblx0ICogU3RhcnQgUmVjb3JkaW5nIGV2ZW50LiBIYXMgZGF0YToge31cblx0ICovXG5cdFNUQVJUX1JFQ09SRElORyA9IFwic3RhcnRfcmVjb3JkaW5nXCIsXG5cblx0LyoqXG5cdCAqIFN0b3AgUmVjb3JkaW5nIGV2ZW50LiBIYXMgZGF0YToge31cblx0ICovXG5cdFNUT1BfUkVDT1JESU5HID0gXCJzdG9wX3JlY29yZGluZ1wiLFxuXHRcblx0LyoqXG5cdCAqIFBsYXkgUmVjb3JkaW5nIGV2ZW50LiBIYXMgZGF0YToge31cblx0ICovXG5cdFBMQVlfUkVDT1JESU5HID0gXCJwbGF5X3JlY29yZGluZ1wiLFxuXG5cdC8qKlxuXHQgKiBQbGF5IFNvdW5kIGV2ZW50LiBIYXMgZGF0YToge2tleTogc3RyaW5nLCBsb29wOiBib29sZWFuLCBob2xkUmVmZXJlbmNlOiBib29sZWFuIH1cblx0ICovXG5cdFBMQVlfU09VTkQgPSBcInBsYXlfc291bmRcIixcblxuXHQvKipcblx0ICogUGxheSBTb3VuZCBldmVudC4gSGFzIGRhdGE6IHtrZXk6IHN0cmluZ31cblx0ICovXG5cdFNUT1BfU09VTkQgPSBcInN0b3Bfc291bmRcIixcblxuXHQvKipcblx0ICogUGxheSBTb3VuZCBldmVudC4gSGFzIGRhdGE6IHtrZXk6IHN0cmluZywgbG9vcDogYm9vbGVhbiwgaG9sZFJlZmVyZW5jZTogYm9vbGVhbiwgY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSB9XG5cdCAqL1xuIFx0UExBWV9TRlggPSBcInBsYXlfc2Z4XCIsXG5cbiBcdC8qKlxuXHQgKiBQbGF5IFNvdW5kIGV2ZW50LiBIYXMgZGF0YToge2tleTogc3RyaW5nLCBsb29wOiBib29sZWFuLCBob2xkUmVmZXJlbmNlOiBib29sZWFuIH1cblx0ICovXG4gIFx0UExBWV9NVVNJQyA9IFwicGxheV9tdXNpY1wiLFxuXG5cdC8qKlxuXHQgKiBNdXRlIGF1ZGlvIGNoYW5uZWwgZXZlbnQuIEhhcyBkYXRhOiB7Y2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZX1cblx0ICovXG5cdE1VVEVfQ0hBTk5FTCA9IFwibXV0ZV9jaGFubmVsXCIsXG5cblx0LyoqXG5cdCAqIFVubXV0ZSBhdWRpbyBjaGFubmVsIGV2ZW50LiBIYXMgZGF0YToge2NoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGV9XG5cdCAqL1xuXHRVTk1VVEVfQ0hBTk5FTCA9IFwidW5tdXRlX2NoYW5uZWxcIixcblxuXHQvKipcblx0ICogRW5jb21wYXNzZXMgYWxsIGV2ZW50IHR5cGVzLiBVc2VkIGZvciByZWNlaXZlcnMgb25seS5cblx0ICovXG5cdEFMTCA9IFwiYWxsXCIsXG59IiwiaW1wb3J0IFF1ZXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvUXVldWVcIjtcbmltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuL0V2ZW50UXVldWVcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4vR2FtZUV2ZW50XCI7XG5cbi8qKlxuICogUmVjZWl2ZXMgc3Vic2NyaWJlZCBldmVudHMgZnJvbSB0aGUgRXZlbnRRdWV1ZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVjZWl2ZXIge1xuXHQvKiogVGhlIG1heGltdW0gbnVtYmVyIG9mIGV2ZW50cyB0aGlzIFJlY2VpdmVyIGNhbiBob2xkIGF0IG9uZSB0aW1lICovXG5cdHJlYWRvbmx5IE1BWF9TSVpFOiBudW1iZXI7XG5cblx0LyoqIFRoZSBpbmJveCBvZiB0aGUgUmVjZWl2ZXIgKi9cblx0cHJpdmF0ZSBxOiBRdWV1ZTxHYW1lRXZlbnQ+O1xuXG5cdC8qKiBDcmVhdGVzIGEgbmV3IFJlY2VpdmVyICovXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5NQVhfU0laRSA9IDEwMDtcbiAgICAgICAgdGhpcy5xID0gbmV3IFF1ZXVlKHRoaXMuTUFYX1NJWkUpO1xuXHR9XG5cblx0ZGVzdHJveSgpe1xuXHRcdEV2ZW50UXVldWUuZ2V0SW5zdGFuY2UoKS51bnN1YnNjcmliZSh0aGlzKTtcblx0fVxuXHRcblx0LyoqXG5cdCAqIEFkZHMgdGhlc2UgdHlwZXMgb2YgZXZlbnRzIHRvIHRoaXMgcmVjZWl2ZXIncyBxdWV1ZSBldmVyeSB1cGRhdGUuXG5cdCAqIEBwYXJhbSBldmVudFR5cGVzIFRoZSB0eXBlcyBvZiBldmVudHMgdGhpcyByZWNlaXZlciB3aWxsIGJlIHN1YnNjcmliZWQgdG9cblx0ICovXG5cdHN1YnNjcmliZShldmVudFR5cGVzOiBzdHJpbmcgfCBBcnJheTxzdHJpbmc+KTogdm9pZCB7XG5cdFx0RXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpLnN1YnNjcmliZSh0aGlzLCBldmVudFR5cGVzKTtcblx0XHR0aGlzLnEuY2xlYXIoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFuIGV2ZW50IHRvIHRoZSBxdWV1ZSBvZiB0aGlzIHJlY2lldmVyLiBUaGlzIGlzIHVzZWQgYnkgdGhlIEByZWZlcmVuY2VbRXZlbnRRdWV1ZV0gdG8gZGlzdHJpYnV0ZSBldmVudHNcblx0ICogQHBhcmFtIGV2ZW50IFRoZSBldmVudCB0byByZWNlaXZlXG5cdCAqL1xuXHRyZWNlaXZlKGV2ZW50OiBHYW1lRXZlbnQpOiB2b2lkIHtcblx0XHR0cnl7XG5cdFx0dGhpcy5xLmVucXVldWUoZXZlbnQpO1xuXHRcdH0gY2F0Y2goZSl7XG5cdFx0XHRjb25zb2xlLndhcm4oXCJSZWNlaXZlciBvdmVyZmxvdyBmb3IgZXZlbnQgXCIgKyBldmVudC50b1N0cmluZygpKTtcblx0XHRcdHRocm93IGU7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHJpZXZlcyB0aGUgbmV4dCBldmVudCBmcm9tIHRoZSByZWNlaXZlcidzIHF1ZXVlXG5cdCAqIEByZXR1cm5zIFRoZSBuZXh0IEdhbWVFdmVudFxuXHQgKi9cblx0Z2V0TmV4dEV2ZW50KCk6IEdhbWVFdmVudCB7XG5cdFx0cmV0dXJuIHRoaXMucS5kZXF1ZXVlKCk7XG5cdH1cblxuXHQvKipcblx0ICogTG9va3MgYXQgdGhlIG5leHQgZXZlbnQgaW4gdGhlIHJlY2VpdmVyJ3MgcXVldWUsIGJ1dCBkb2Vzbid0IHJlbW92ZSBpdCBmcm9tIHRoZSBxdWV1ZVxuXHQgKiBAcmV0dXJucyBUaGUgbmV4dCBHYW1lRXZlbnRcblx0ICovXG5cdHBlZWtOZXh0RXZlbnQoKTogR2FtZUV2ZW50IHtcblx0XHRyZXR1cm4gdGhpcy5xLnBlZWtOZXh0KClcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHJlY2VpdmVyIGhhcyBhbnkgZXZlbnRzIGluIGl0cyBxdWV1ZVxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSByZWNlaXZlciBoYXMgYW5vdGhlciBldmVudCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRoYXNOZXh0RXZlbnQoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMucS5oYXNJdGVtcygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIElnbm9yZSBhbGwgZXZlbnRzIHRoaXMgZnJhbWVcblx0ICovXG5cdGlnbm9yZUV2ZW50cygpOiB2b2lkIHtcblx0XHR0aGlzLnEuY2xlYXIoKTtcblx0fVxufSIsImltcG9ydCBSZWNlaXZlciBmcm9tIFwiLi4vRXZlbnRzL1JlY2VpdmVyXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuLi9FdmVudHMvRXZlbnRRdWV1ZVwiO1xuaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuLi9TY2VuZUdyYXBoL1ZpZXdwb3J0XCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5cbi8qKlxuICogUmVjZWl2ZXMgaW5wdXQgZXZlbnRzIGZyb20gdGhlIEByZWZlcmVuY2VbRXZlbnRRdWV1ZV0gYW5kIGFsbG93cyBmb3IgZWFzeSBhY2Nlc3Mgb2YgaW5mb3JtYXRpb24gYWJvdXQgaW5wdXQgYnkgb3RoZXIgc3lzdGVtc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnB1dCB7XG5cdHByaXZhdGUgc3RhdGljIG1vdXNlUHJlc3NlZDogYm9vbGVhbjtcblx0cHJpdmF0ZSBzdGF0aWMgbW91c2VKdXN0UHJlc3NlZDogYm9vbGVhbjtcblx0cHJpdmF0ZSBzdGF0aWMgbW91c2VCdXR0b25QcmVzc2VkOiBudW1iZXI7XG5cblx0cHJpdmF0ZSBzdGF0aWMga2V5SnVzdFByZXNzZWQ6IE1hcDxib29sZWFuPjtcblx0cHJpdmF0ZSBzdGF0aWMga2V5UHJlc3NlZDogTWFwPGJvb2xlYW4+O1xuXG5cdHByaXZhdGUgc3RhdGljIG1vdXNlUG9zaXRpb246IFZlYzI7XG5cdHByaXZhdGUgc3RhdGljIG1vdXNlUHJlc3NQb3NpdGlvbjogVmVjMjtcblxuXHRwcml2YXRlIHN0YXRpYyBzY3JvbGxEaXJlY3Rpb246IG51bWJlcjtcblx0cHJpdmF0ZSBzdGF0aWMganVzdFNjcm9sbGVkOiBib29sZWFuO1xuXG5cdHByaXZhdGUgc3RhdGljIGV2ZW50UXVldWU6IEV2ZW50UXVldWU7XG5cdHByaXZhdGUgc3RhdGljIHJlY2VpdmVyOiBSZWNlaXZlcjtcblx0cHJpdmF0ZSBzdGF0aWMgdmlld3BvcnQ6IFZpZXdwb3J0O1xuXG5cdHByaXZhdGUgc3RhdGljIGtleU1hcDogTWFwPEFycmF5PHN0cmluZz4+O1xuXG5cdHByaXZhdGUgc3RhdGljIGtleXNEaXNhYmxlZDogYm9vbGVhbjtcblx0cHJpdmF0ZSBzdGF0aWMgbW91c2VEaXNhYmxlZDogYm9vbGVhbjtcblxuXHQvKipcblx0ICogSW5pdGlhbGl6ZXMgdGhlIElucHV0IG9iamVjdFxuXHQgKiBAcGFyYW0gdmlld3BvcnQgQSByZWZlcmVuY2UgdG8gdGhlIHZpZXdwb3J0IG9mIHRoZSBnYW1lXG5cdCAqL1xuXHRzdGF0aWMgaW5pdGlhbGl6ZSh2aWV3cG9ydDogVmlld3BvcnQsIGtleU1hcDogQXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj4pIHtcblx0XHRJbnB1dC52aWV3cG9ydCA9IHZpZXdwb3J0O1xuXHRcdElucHV0Lm1vdXNlUHJlc3NlZCA9IGZhbHNlO1xuXHRcdElucHV0Lm1vdXNlSnVzdFByZXNzZWQgPSBmYWxzZTtcblx0XHRJbnB1dC5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuXHRcdElucHV0LmtleUp1c3RQcmVzc2VkID0gbmV3IE1hcDxib29sZWFuPigpO1xuXHRcdElucHV0LmtleVByZXNzZWQgPSBuZXcgTWFwPGJvb2xlYW4+KCk7XG5cdFx0SW5wdXQubW91c2VQb3NpdGlvbiA9IG5ldyBWZWMyKDAsIDApO1xuXHRcdElucHV0Lm1vdXNlUHJlc3NQb3NpdGlvbiA9IG5ldyBWZWMyKDAsIDApO1xuXHRcdElucHV0LnNjcm9sbERpcmVjdGlvbiA9IDA7XG5cdFx0SW5wdXQuanVzdFNjcm9sbGVkID0gZmFsc2U7XG5cdFx0SW5wdXQua2V5c0Rpc2FibGVkID0gZmFsc2U7XG5cdFx0SW5wdXQubW91c2VEaXNhYmxlZCA9IGZhbHNlO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aGUga2V5bWFwXG5cdFx0SW5wdXQua2V5TWFwID0gbmV3IE1hcCgpO1xuXG5cdFx0Ly8gQWRkIGFsbCBrZXlzIHRvIHRoZSBrZXltYXBcblx0XHRmb3IgKGxldCBlbnRyeSBpbiBrZXlNYXApIHtcblx0XHRcdGxldCBuYW1lID0ga2V5TWFwW2VudHJ5XS5uYW1lO1xuXHRcdFx0bGV0IGtleXMgPSBrZXlNYXBbZW50cnldLmtleXM7XG5cdFx0XHRJbnB1dC5rZXlNYXAuYWRkKG5hbWUsIGtleXMpO1xuXHRcdH1cblxuXHRcdElucHV0LmV2ZW50UXVldWUgPSBFdmVudFF1ZXVlLmdldEluc3RhbmNlKCk7XG5cdFx0Ly8gU3Vic2NyaWJlIHRvIGFsbCBpbnB1dCBldmVudHNcblx0XHRJbnB1dC5ldmVudFF1ZXVlLnN1YnNjcmliZShJbnB1dC5yZWNlaXZlciwgW0dhbWVFdmVudFR5cGUuTU9VU0VfRE9XTiwgR2FtZUV2ZW50VHlwZS5NT1VTRV9VUCwgR2FtZUV2ZW50VHlwZS5NT1VTRV9NT1ZFLFxuXHRcdEdhbWVFdmVudFR5cGUuS0VZX0RPV04sIEdhbWVFdmVudFR5cGUuS0VZX1VQLCBHYW1lRXZlbnRUeXBlLkNBTlZBU19CTFVSLCBHYW1lRXZlbnRUeXBlLldIRUVMX1VQLCBHYW1lRXZlbnRUeXBlLldIRUVMX0RPV05dKTtcblx0fVxuXG5cdHN0YXRpYyB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHQvLyBSZXNldCB0aGUganVzdFByZXNzZWQgdmFsdWVzIHRvIGZhbHNlXG5cdFx0SW5wdXQubW91c2VKdXN0UHJlc3NlZCA9IGZhbHNlO1xuXHRcdElucHV0LmtleUp1c3RQcmVzc2VkLmZvckVhY2goKGtleTogc3RyaW5nKSA9PiBJbnB1dC5rZXlKdXN0UHJlc3NlZC5zZXQoa2V5LCBmYWxzZSkpO1xuXHRcdElucHV0Lmp1c3RTY3JvbGxlZCA9IGZhbHNlO1xuXHRcdElucHV0LnNjcm9sbERpcmVjdGlvbiA9IDA7XG5cblx0XHR3aGlsZSAoSW5wdXQucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpIHtcblx0XHRcdGxldCBldmVudCA9IElucHV0LnJlY2VpdmVyLmdldE5leHRFdmVudCgpO1xuXG5cdFx0XHQvLyBIYW5kbGUgZWFjaCBldmVudCB0eXBlXG5cdFx0XHRpZiAoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5NT1VTRV9ET1dOKSB7XG5cdFx0XHRcdElucHV0Lm1vdXNlSnVzdFByZXNzZWQgPSB0cnVlO1xuXHRcdFx0XHRJbnB1dC5tb3VzZVByZXNzZWQgPSB0cnVlO1xuXHRcdFx0XHRJbnB1dC5tb3VzZVByZXNzUG9zaXRpb24gPSBldmVudC5kYXRhLmdldChcInBvc2l0aW9uXCIpO1xuXHRcdFx0XHRJbnB1dC5tb3VzZUJ1dHRvblByZXNzZWQgPSBldmVudC5kYXRhLmdldChcImJ1dHRvblwiKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuTU9VU0VfVVApIHtcblx0XHRcdFx0SW5wdXQubW91c2VQcmVzc2VkID0gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLk1PVVNFX01PVkUpIHtcblx0XHRcdFx0SW5wdXQubW91c2VQb3NpdGlvbiA9IGV2ZW50LmRhdGEuZ2V0KFwicG9zaXRpb25cIik7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLktFWV9ET1dOKSB7XG5cdFx0XHRcdGxldCBrZXkgPSBldmVudC5kYXRhLmdldChcImtleVwiKTtcblx0XHRcdFx0Ly8gSGFuZGxlIHNwYWNlIGJhclxuXHRcdFx0XHRpZiAoa2V5ID09PSBcIiBcIikge1xuXHRcdFx0XHRcdGtleSA9IFwic3BhY2VcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIUlucHV0LmtleVByZXNzZWQuZ2V0KGtleSkpIHtcblx0XHRcdFx0XHRJbnB1dC5rZXlKdXN0UHJlc3NlZC5zZXQoa2V5LCB0cnVlKTtcblx0XHRcdFx0XHRJbnB1dC5rZXlQcmVzc2VkLnNldChrZXksIHRydWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLktFWV9VUCkge1xuXHRcdFx0XHRsZXQga2V5ID0gZXZlbnQuZGF0YS5nZXQoXCJrZXlcIik7XG5cdFx0XHRcdC8vIEhhbmRsZSBzcGFjZSBiYXJcblx0XHRcdFx0aWYgKGtleSA9PT0gXCIgXCIpIHtcblx0XHRcdFx0XHRrZXkgPSBcInNwYWNlXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0SW5wdXQua2V5UHJlc3NlZC5zZXQoa2V5LCBmYWxzZSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLkNBTlZBU19CTFVSKSB7XG5cdFx0XHRcdElucHV0LmNsZWFyS2V5UHJlc3NlcygpXG5cdFx0XHR9XG5cblx0XHRcdGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLldIRUVMX1VQKSB7XG5cdFx0XHRcdElucHV0LnNjcm9sbERpcmVjdGlvbiA9IC0xO1xuXHRcdFx0XHRJbnB1dC5qdXN0U2Nyb2xsZWQgPSB0cnVlO1xuXHRcdFx0fSBlbHNlIGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLldIRUVMX0RPV04pIHtcblx0XHRcdFx0SW5wdXQuc2Nyb2xsRGlyZWN0aW9uID0gMTtcblx0XHRcdFx0SW5wdXQuanVzdFNjcm9sbGVkID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIHN0YXRpYyBjbGVhcktleVByZXNzZXMoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5SnVzdFByZXNzZWQuZm9yRWFjaCgoa2V5OiBzdHJpbmcpID0+IElucHV0LmtleUp1c3RQcmVzc2VkLnNldChrZXksIGZhbHNlKSk7XG5cdFx0SW5wdXQua2V5UHJlc3NlZC5mb3JFYWNoKChrZXk6IHN0cmluZykgPT4gSW5wdXQua2V5UHJlc3NlZC5zZXQoa2V5LCBmYWxzZSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgd2hldGhlciBvciBub3QgYSBrZXkgd2FzIG5ld2x5IHByZXNzZWQgSW5wdXQgZnJhbWUuXG5cdCAqIElmIHRoZSBrZXkgaXMgc3RpbGwgcHJlc3NlZCBmcm9tIGxhc3QgZnJhbWUgYW5kIHdhc24ndCByZS1wcmVzc2VkLCBJbnB1dCB3aWxsIHJldHVybiBmYWxzZS5cblx0ICogQHBhcmFtIGtleSBUaGUga2V5XG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGtleSB3YXMganVzdCBwcmVzc2VkLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBpc0tleUp1c3RQcmVzc2VkKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG5cdFx0aWYgKElucHV0LmtleXNEaXNhYmxlZCkgcmV0dXJuIGZhbHNlO1xuXG5cdFx0aWYgKElucHV0LmtleUp1c3RQcmVzc2VkLmhhcyhrZXkpKSB7XG5cdFx0XHRyZXR1cm4gSW5wdXQua2V5SnVzdFByZXNzZWQuZ2V0KGtleSlcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGFuIGFycmF5IG9mIGFsbCBvZiB0aGUga2V5cyB0aGF0IGFyZSBuZXdseSBwcmVzc2VkIElucHV0IGZyYW1lLlxuXHQgKiBJZiBhIGtleSBpcyBzdGlsbCBwcmVzc2VkIGZyb20gbGFzdCBmcmFtZSBhbmQgd2Fzbid0IHJlLXByZXNzZWQsIGl0IHdpbGwgbm90IGJlIGluIElucHV0IGxpc3QuXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IG9mIGFsbCBvZiB0aGUgbmV3bHkgcHJlc3NlZCBrZXlzLlxuXHQgKi9cblx0c3RhdGljIGdldEtleXNKdXN0UHJlc3NlZCgpOiBBcnJheTxzdHJpbmc+IHtcblx0XHRpZiAoSW5wdXQua2V5c0Rpc2FibGVkKSByZXR1cm4gW107XG5cblx0XHRsZXQga2V5cyA9IEFycmF5PHN0cmluZz4oKTtcblx0XHRJbnB1dC5rZXlKdXN0UHJlc3NlZC5mb3JFYWNoKGtleSA9PiB7XG5cdFx0XHRpZiAoSW5wdXQua2V5SnVzdFByZXNzZWQuZ2V0KGtleSkpIHtcblx0XHRcdFx0a2V5cy5wdXNoKGtleSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0cmV0dXJuIGtleXM7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCBhIGtleSBpcyBiZWluZyBwcmVzc2VkLlxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXlcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUga2V5IGlzIGN1cnJlbnRseSBwcmVzc2VkLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBpc0tleVByZXNzZWQoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRpZiAoSW5wdXQua2V5c0Rpc2FibGVkKSByZXR1cm4gZmFsc2U7XG5cblx0XHRpZiAoSW5wdXQua2V5UHJlc3NlZC5oYXMoa2V5KSkge1xuXHRcdFx0cmV0dXJuIElucHV0LmtleVByZXNzZWQuZ2V0KGtleSlcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGFuZ2VzIHRoZSBiaW5kaW5nIG9mIGFuIGlucHV0IG5hbWUgdG8ga2V5c1xuXHQgKiBAcGFyYW0gaW5wdXROYW1lIFRoZSBuYW1lIG9mIHRoZSBpbnB1dFxuXHQgKiBAcGFyYW0ga2V5cyBUaGUgY29ycmVzcG9uZGluZyBrZXlzXG5cdCAqL1xuXHRzdGF0aWMgY2hhbmdlS2V5QmluZGluZyhpbnB1dE5hbWU6IHN0cmluZywga2V5czogQXJyYXk8c3RyaW5nPik6IHZvaWQge1xuXHRcdElucHV0LmtleU1hcC5zZXQoaW5wdXROYW1lLCBrZXlzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhcnMgYWxsIGtleSBiaW5kaW5nc1xuXHQgKi9cblx0c3RhdGljIGNsZWFyQWxsS2V5QmluZGluZ3MoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5TWFwLmNsZWFyKCk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCBhbiBpbnB1dCB3YXMganVzdCBwcmVzc2VkIHRoaXMgZnJhbWVcblx0ICogQHBhcmFtIGlucHV0TmFtZSBUaGUgbmFtZSBvZiB0aGUgaW5wdXRcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgaW5wdXQgd2FzIGp1c3QgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgaXNKdXN0UHJlc3NlZChpbnB1dE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdGlmIChJbnB1dC5rZXlzRGlzYWJsZWQpIHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChJbnB1dC5rZXlNYXAuaGFzKGlucHV0TmFtZSkpIHtcblx0XHRcdGNvbnN0IGtleXMgPSBJbnB1dC5rZXlNYXAuZ2V0KGlucHV0TmFtZSk7XG5cdFx0XHRsZXQganVzdFByZXNzZWQgPSBmYWxzZTtcblxuXHRcdFx0Zm9yIChsZXQga2V5IG9mIGtleXMpIHtcblx0XHRcdFx0anVzdFByZXNzZWQgPSBqdXN0UHJlc3NlZCB8fCBJbnB1dC5pc0tleUp1c3RQcmVzc2VkKGtleSk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBqdXN0UHJlc3NlZDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IGFuIGlucHV0IGlzIGN1cnJlbnRseSBwcmVzc2VkXG5cdCAqIEBwYXJhbSBpbnB1dE5hbWUgVGhlIG5hbWUgb2YgdGhlIGlucHV0XG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGlucHV0IGlzIHByZXNzZWQsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cblx0c3RhdGljIGlzUHJlc3NlZChpbnB1dE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdGlmIChJbnB1dC5rZXlzRGlzYWJsZWQpIHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChJbnB1dC5rZXlNYXAuaGFzKGlucHV0TmFtZSkpIHtcblx0XHRcdGNvbnN0IGtleXMgPSBJbnB1dC5rZXlNYXAuZ2V0KGlucHV0TmFtZSk7XG5cdFx0XHRsZXQgcHJlc3NlZCA9IGZhbHNlO1xuXG5cdFx0XHRmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuXHRcdFx0XHRwcmVzc2VkID0gcHJlc3NlZCB8fCBJbnB1dC5pc0tleVByZXNzZWQoa2V5KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHByZXNzZWQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblx0LyoqXG5cdCAqIFxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBtb3VzZSB3YXMgbmV3bHkgcHJlc3NlZCBJbnB1dCBmcmFtZS5cblx0ICogQHBhcmFtIG1vdXNlQnV0dG9uIE9wdGlvbmFsbHkgc3BlY2lmeSB3aGljaCBtb3VzZSBjbGljayB5b3Ugd2FudCB0byBrbm93IHdhcyBwcmVzc2VkLiBcblx0ICogMCBmb3IgbGVmdCBjbGljaywgMSBmb3IgbWlkZGxlIGNsaWNrLCAyIGZvciByaWdodCBjbGljay5cblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbW91c2Ugd2FzIGp1c3QgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgaXNNb3VzZUp1c3RQcmVzc2VkKG1vdXNlQnV0dG9uPzogbnVtYmVyKTogYm9vbGVhbiB7XG5cdFx0aWYgKG1vdXNlQnV0dG9uICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdHJldHVybiBJbnB1dC5tb3VzZUp1c3RQcmVzc2VkICYmICFJbnB1dC5tb3VzZURpc2FibGVkICYmIG1vdXNlQnV0dG9uID09IHRoaXMubW91c2VCdXR0b25QcmVzc2VkO1xuXHRcdH1cblx0XHRyZXR1cm4gSW5wdXQubW91c2VKdXN0UHJlc3NlZCAmJiAhSW5wdXQubW91c2VEaXNhYmxlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBtb3VzZSBpcyBjdXJyZW50bHkgcHJlc3NlZFxuXHQgKiBAcGFyYW0gbW91c2VCdXR0b24gT3B0aW9uYWxseSBzcGVjaWZ5IHdoaWNoIG1vdXNlIGNsaWNrIHlvdSB3YW50IHRvIGtub3cgd2FzIHByZXNzZWQuIFxuXHQgKiAwIGZvciBsZWZ0IGNsaWNrLCAxIGZvciBtaWRkbGUgY2xpY2ssIDIgZm9yIHJpZ2h0IGNsaWNrLlxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBtb3VzZSBpcyBjdXJyZW50bHkgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgaXNNb3VzZVByZXNzZWQobW91c2VCdXR0b24/OiBudW1iZXIpOiBib29sZWFuIHtcblx0XHRpZiAobW91c2VCdXR0b24gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuIElucHV0Lm1vdXNlUHJlc3NlZCAmJiAhSW5wdXQubW91c2VEaXNhYmxlZCAmJiBtb3VzZUJ1dHRvbiA9PSB0aGlzLm1vdXNlQnV0dG9uUHJlc3NlZDtcblx0XHR9XG5cdFx0cmV0dXJuIElucHV0Lm1vdXNlUHJlc3NlZCAmJiAhSW5wdXQubW91c2VEaXNhYmxlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHVzZXIgc2Nyb2xsZWQgb3Igbm90XG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHVzZXIganVzdCBzY3JvbGxlZCBJbnB1dCBmcmFtZSwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgZGlkSnVzdFNjcm9sbCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gSW5wdXQuanVzdFNjcm9sbGVkICYmICFJbnB1dC5tb3VzZURpc2FibGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGRpcmVjdGlvbiBvZiB0aGUgc2Nyb2xsXG5cdCAqIEByZXR1cm5zIC0xIGlmIHRoZSB1c2VyIHNjcm9sbGVkIHVwLCAxIGlmIHRoZXkgc2Nyb2xsZWQgZG93blxuXHQgKi9cblx0c3RhdGljIGdldFNjcm9sbERpcmVjdGlvbigpOiBudW1iZXIge1xuXHRcdHJldHVybiBJbnB1dC5zY3JvbGxEaXJlY3Rpb247XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIHBsYXllcidzIG1vdXNlXG5cdCAqIEByZXR1cm5zIFRoZSBtb3VzZSBwb3NpdGlvbiBzdG9yZWQgYXMgYSBWZWMyXG5cdCAqL1xuXHRzdGF0aWMgZ2V0TW91c2VQb3NpdGlvbigpOiBWZWMyIHtcblx0XHRyZXR1cm4gSW5wdXQubW91c2VQb3NpdGlvbi5zY2FsZWQoMSAvIHRoaXMudmlld3BvcnQuZ2V0Wm9vbUxldmVsKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBvc2l0aW9uIG9mIHRoZSBwbGF5ZXIncyBtb3VzZSBpbiB0aGUgZ2FtZSB3b3JsZCxcblx0ICogdGFraW5nIGludG8gY29uc2lkZXJhdGlvbiB0aGUgc2Nyb2xsaW5nIG9mIHRoZSB2aWV3cG9ydFxuXHQgKiBAcmV0dXJucyBUaGUgbW91c2UgcG9zaXRpb24gc3RvcmVkIGFzIGEgVmVjMlxuXHQgKi9cblx0c3RhdGljIGdldEdsb2JhbE1vdXNlUG9zaXRpb24oKTogVmVjMiB7XG5cdFx0cmV0dXJuIElucHV0Lm1vdXNlUG9zaXRpb24uY2xvbmUoKS5zY2FsZSgxIC8gdGhpcy52aWV3cG9ydC5nZXRab29tTGV2ZWwoKSkuYWRkKElucHV0LnZpZXdwb3J0LmdldE9yaWdpbigpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgbGFzdCBtb3VzZSBwcmVzc1xuXHQgKiBAcmV0dXJucyBUaGUgbW91c2UgcG9zaXRpb24gc3RvcmVkIGFzIGEgVmVjMlxuXHQgKi9cblx0c3RhdGljIGdldE1vdXNlUHJlc3NQb3NpdGlvbigpOiBWZWMyIHtcblx0XHRyZXR1cm4gSW5wdXQuZ2V0TW91c2VQb3NpdGlvbigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBvc2l0aW9uIG9mIHRoZSBsYXN0IG1vdXNlIHByZXNzIGluIHRoZSBnYW1lIHdvcmxkLFxuXHQgKiB0YWtpbmcgaW50byBjb25zaWRlcmF0aW9uIHRoZSBzY3JvbGxpbmcgb2YgdGhlIHZpZXdwb3J0XG5cdCAqIEByZXR1cm5zIFRoZSBtb3VzZSBwb3NpdGlvbiBzdG9yZWQgYXMgYSBWZWMyXG5cdCAqL1xuXHRzdGF0aWMgZ2V0R2xvYmFsTW91c2VQcmVzc1Bvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiBJbnB1dC5tb3VzZVByZXNzUG9zaXRpb24uY2xvbmUoKS5hZGQoSW5wdXQudmlld3BvcnQuZ2V0T3JpZ2luKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc2FibGVzIGFsbCBrZXlwcmVzcyBhbmQgbW91c2UgY2xpY2sgaW5wdXRzXG5cdCAqL1xuXHRzdGF0aWMgZGlzYWJsZUlucHV0KCk6IHZvaWQge1xuXHRcdElucHV0LmtleXNEaXNhYmxlZCA9IHRydWU7XG5cdFx0SW5wdXQubW91c2VEaXNhYmxlZCA9IHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogRW5hYmxlcyBhbGwga2V5cHJlc3MgYW5kIG1vdXNlIGNsaWNrIGlucHV0c1xuXHQgKi9cblx0c3RhdGljIGVuYWJsZUlucHV0KCk6IHZvaWQge1xuXHRcdElucHV0LmtleXNEaXNhYmxlZCA9IGZhbHNlO1xuXHRcdElucHV0Lm1vdXNlRGlzYWJsZWQgPSBmYWxzZTtcblx0fVxufSIsImltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuLi9FdmVudHMvRXZlbnRRdWV1ZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5cbi8qKlxuICogSGFuZGxlcyBjb21tdW5pY2F0aW9uIHdpdGggdGhlIHdlYiBicm93c2VyIHRvIHJlY2VpdmUgYXN5bmNocm9ub3VzIGV2ZW50cyBhbmQgc2VuZCB0aGVtIHRvIHRoZSBAcmVmZXJlbmNlW0V2ZW50UXVldWVdXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElucHV0SGFuZGxlciB7XG5cdHByaXZhdGUgZXZlbnRRdWV1ZTogRXZlbnRRdWV1ZTtcbiAgICAgXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBJbnB1dEhhbmRsZXJcbiAgICAgKiBAcGFyYW0gY2FudmFzIFRoZSBnYW1lIGNhbnZhc1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpe1xuXHRcdHRoaXMuZXZlbnRRdWV1ZSA9IEV2ZW50UXVldWUuZ2V0SW5zdGFuY2UoKTtcblx0XHRcbiAgICAgICAgY2FudmFzLm9ubW91c2Vkb3duID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU1vdXNlRG93bihldmVudCwgY2FudmFzKTtcbiAgICAgICAgY2FudmFzLm9ubW91c2V1cCA9IChldmVudCkgPT4gdGhpcy5oYW5kbGVNb3VzZVVwKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBjYW52YXMub25jb250ZXh0bWVudSA9IHRoaXMuaGFuZGxlQ29udGV4dE1lbnU7XG4gICAgICAgIGNhbnZhcy5vbm1vdXNlbW92ZSA9IChldmVudCkgPT4gdGhpcy5oYW5kbGVNb3VzZU1vdmUoZXZlbnQsIGNhbnZhcyk7XG4gICAgICAgIGRvY3VtZW50Lm9ua2V5ZG93biA9IHRoaXMuaGFuZGxlS2V5RG93bjtcbiAgICAgICAgZG9jdW1lbnQub25rZXl1cCA9IHRoaXMuaGFuZGxlS2V5VXA7XG4gICAgICAgIGRvY3VtZW50Lm9uYmx1ciA9IHRoaXMuaGFuZGxlQmx1cjtcbiAgICAgICAgZG9jdW1lbnQub25jb250ZXh0bWVudSA9IHRoaXMuaGFuZGxlQmx1cjtcbiAgICAgICAgZG9jdW1lbnQub253aGVlbCA9IHRoaXMuaGFuZGxlV2hlZWw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVNb3VzZURvd24gPSAoZXZlbnQ6IE1vdXNlRXZlbnQsIGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiB2b2lkID0+IHtcblx0XHRsZXQgcG9zID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBsZXQgYnV0dG9uID0gZXZlbnQuYnV0dG9uO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLk1PVVNFX0RPV04sIHtwb3NpdGlvbjogcG9zLCBidXR0b246IGJ1dHRvbn0pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZU1vdXNlVXAgPSAoZXZlbnQ6IE1vdXNlRXZlbnQsIGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiB2b2lkID0+IHtcbiAgICAgICAgbGV0IHBvcyA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCwgY2FudmFzKTtcbiAgICAgICAgbGV0IGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5NT1VTRV9VUCwge3Bvc2l0aW9uOiBwb3N9KTtcbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KGdhbWVFdmVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVNb3VzZU1vdmUgPSAoZXZlbnQ6IE1vdXNlRXZlbnQsIGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiB2b2lkID0+IHtcbiAgICAgICAgbGV0IHBvcyA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCwgY2FudmFzKTtcbiAgICAgICAgbGV0IGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5NT1VTRV9NT1ZFLCB7cG9zaXRpb246IHBvc30pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUtleURvd24gPSAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgbGV0IGtleSA9IHRoaXMuZ2V0S2V5KGV2ZW50KTtcbiAgICAgICAgbGV0IGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5LRVlfRE9XTiwge2tleToga2V5fSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlS2V5VXAgPSAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgbGV0IGtleSA9IHRoaXMuZ2V0S2V5KGV2ZW50KTtcbiAgICAgICAgbGV0IGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5LRVlfVVAsIHtrZXk6IGtleX0pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUJsdXIgPSAoZXZlbnQ6IEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGxldCBnYW1lRXZlbnQgPSBuZXcgR2FtZUV2ZW50KEdhbWVFdmVudFR5cGUuQ0FOVkFTX0JMVVIsIHt9KTtcbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KGdhbWVFdmVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVDb250ZXh0TWVudSA9IChldmVudDogRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVXaGVlbCA9IChldmVudDogV2hlZWxFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgXG4gICAgICAgIGxldCBnYW1lRXZlbnQ6IEdhbWVFdmVudDtcbiAgICAgICAgaWYoZXZlbnQuZGVsdGFZIDwgMCl7XG4gICAgICAgICAgICBnYW1lRXZlbnQgPSBuZXcgR2FtZUV2ZW50KEdhbWVFdmVudFR5cGUuV0hFRUxfVVAsIHt9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5XSEVFTF9ET1dOLCB7fSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KGdhbWVFdmVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRLZXkoa2V5RXZlbnQ6IEtleWJvYXJkRXZlbnQpe1xuICAgICAgICByZXR1cm4ga2V5RXZlbnQua2V5LnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRNb3VzZVBvc2l0aW9uKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQsIGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiBWZWMyIHtcbiAgICAgICAgbGV0IHJlY3QgPSBjYW52YXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGxldCB4ID0gbW91c2VFdmVudC5jbGllbnRYIC0gcmVjdC5sZWZ0O1xuICAgICAgICBsZXQgeSA9IG1vdXNlRXZlbnQuY2xpZW50WSAtIHJlY3QudG9wO1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIoeCwgeSk7XG4gICAgfVxufSIsImltcG9ydCB7fSBmcm9tIFwiLi4vLi4vaW5kZXhcIjsgIC8vIFRoaXMgaW1wb3J0IGFsbG93cyB1cyB0byBtb2RpZnkgdGhlIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCB0byBhZGQgZXh0cmEgZnVuY3Rpb25hbGl0eVxuLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBTZXRzIHVwIHRoZSBlbnZpcm9ubWVudCBvZiB0aGUgZ2FtZSBlbmdpbmVcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRW52aXJvbm1lbnRJbml0aWFsaXplciB7XG4gICAgc3RhdGljIHNldHVwKCl7XG4gICAgICAgIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5wcm90b3R5cGUucm91bmRlZFJlY3QgPSBmdW5jdGlvbih4OiBudW1iZXIsIHk6IG51bWJlciwgdzogbnVtYmVyLCBoOiBudW1iZXIsIHI6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAgICAgLy8gQ2xhbXAgdGhlIHJhZGl1cyBiZXR3ZWVuIDAgYW5kIHRoZSBtaW4gb2YgdGhlIHdpZHRoIG9yIGhlaWdodFxuICAgICAgICAgICAgaWYociA8IDApIHIgPSAwO1xuICAgICAgICAgICAgaWYociA+IE1hdGgubWluKHcsIGgpKSByID0gTWF0aC5taW4odywgaCk7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gRHJhdyB0aGUgcm91bmRlZCByZWN0XG4gICAgICAgICAgICB0aGlzLmJlZ2luUGF0aCgpO1xuICAgICAgICBcbiAgICAgICAgICAgIC8vIFRvcFxuICAgICAgICAgICAgdGhpcy5tb3ZlVG8oeCArIHIsIHkpO1xuICAgICAgICAgICAgdGhpcy5saW5lVG8oeCArIHcgLSByLCB5KTtcbiAgICAgICAgICAgIHRoaXMuYXJjVG8oeCArIHcsIHksIHggKyB3LCB5ICsgciwgcik7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gUmlnaHRcbiAgICAgICAgICAgIHRoaXMubGluZVRvKHggKyB3LCB5ICsgaCAtIHIpO1xuICAgICAgICAgICAgdGhpcy5hcmNUbyh4ICsgdywgeSArIGgsIHggKyB3IC0gciwgeSArIGgsIHIpO1xuICAgICAgICBcbiAgICAgICAgICAgIC8vIEJvdHRvbVxuICAgICAgICAgICAgdGhpcy5saW5lVG8oeCArIHIsIHkgKyBoKTtcbiAgICAgICAgICAgIHRoaXMuYXJjVG8oeCwgeSArIGgsIHgsIHkgKyBoIC0gciwgcik7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gTGVmdFxuICAgICAgICAgICAgdGhpcy5saW5lVG8oeCwgeSArIHIpO1xuICAgICAgICAgICAgdGhpcy5hcmNUbyh4LCB5LCB4ICsgciwgeSwgcilcbiAgICAgICAgXG4gICAgICAgICAgICB0aGlzLmNsb3NlUGF0aCgpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQucHJvdG90eXBlLnN0cm9rZVJvdW5kZWRSZWN0ID0gZnVuY3Rpb24oeCwgeSwgdywgaCwgcil7XG4gICAgICAgICAgICB0aGlzLnJvdW5kZWRSZWN0KHgsIHksIHcsIGgsIHIpO1xuICAgICAgICAgICAgdGhpcy5zdHJva2UoKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELnByb3RvdHlwZS5maWxsUm91bmRlZFJlY3QgPSBmdW5jdGlvbih4LCB5LCB3LCBoLCByKXtcbiAgICAgICAgICAgIHRoaXMucm91bmRlZFJlY3QoeCwgeSwgdywgaCwgcik7XG4gICAgICAgICAgICB0aGlzLmZpbGwoKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgR2FtZUxvb3AgZnJvbSBcIi4vR2FtZUxvb3BcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBTdGF0cyBmcm9tIFwiLi4vRGVidWcvU3RhdHNcIjtcblxuLyoqXG4gKiBBIGdhbWUgbG9vcCB3aXRoIGEgZml4ZWQgdXBkYXRlIHRpbWUgYW5kIGEgdmFyaWFibGUgcmVuZGVyIHRpbWUuXG4gKiBFdmVyeSBmcmFtZSwgdGhlIGdhbWUgdXBkYXRlcyB1bnRpbCBhbGwgdGltZSBzaW5jZSB0aGUgbGFzdCBmcmFtZSBoYXMgYmVlbiBwcm9jZXNzZWQuXG4gKiBJZiB0b28gbXVjaCB0aW1lIGhhcyBwYXNzZWQsIHN1Y2ggYXMgaWYgdGhlIGxhc3QgdXBkYXRlIHdhcyB0b28gc2xvdywgXG4gKiBvciBpZiB0aGUgYnJvd3NlciB3YXMgcHV0IGludG8gdGhlIGJhY2tncm91bmQsIHRoZSBsb29wIHdpbGwgcGFuaWMgYW5kIGRpc2NhcmQgdGltZS5cbiAqIEEgcmVuZGVyIGhhcHBlbnMgYXQgdGhlIGVuZCBvZiBldmVyeSBmcmFtZS4gVGhpcyBoYXBwZW5zIGFzIGZhc3QgYXMgcG9zc2libGUgdW5sZXNzIHNwZWNpZmllZC5cbiAqIEEgbG9vcCBvZiB0aGlzIHR5cGUgYWxsb3dzIGZvciBkZXRlcm1pbmlzdGljIGJlaGF2aW9yIC0gTm8gbWF0dGVyIHdoYXQgdGhlIGZyYW1lIHJhdGUgaXMsIHRoZSB1cGRhdGUgc2hvdWxkIGJlaGF2ZSB0aGUgc2FtZSwgXG4gKiBhcyBpdCBpcyBvY2N1cmluZyBpbiBhIGZpeGVkIGludGVydmFsLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGaXhlZFVwZGF0ZUdhbWVMb29wIGV4dGVuZHMgR2FtZUxvb3Age1xuXG5cdC8qKiBUaGUgbWF4IGFsbG93ZWQgdXBkYXRlIGZwcy4qL1xuICAgIHByaXZhdGUgbWF4VXBkYXRlRlBTOiBudW1iZXI7XG4gICAgXG4gICAgLyoqIFRoZSB0aW1lc3RlcCBmb3IgZWFjaCB1cGRhdGUuIFRoaXMgaXMgdGhlIGRlbHRhVCBwYXNzZWQgdG8gdXBkYXRlIGNhbGxzLiAqL1xuXHRwcml2YXRlIHVwZGF0ZVRpbWVzdGVwOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIGFtb3VudCBvZiB0aW1lIHdlIGFyZSB5ZXQgdG8gc2ltdWxhdGUuICovXG4gICAgcHJpdmF0ZSBmcmFtZURlbHRhOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHRpbWUgd2hlbiB0aGUgbGFzdCBmcmFtZSB3YXMgZHJhd24uICovXG4gICAgcHJpdmF0ZSBsYXN0RnJhbWVUaW1lOiBudW1iZXI7XG4gICAgXG4gICAgLyoqIFRoZSBtaW5pbXVtIHRpbWUgd2Ugd2FudCB0byB3YWl0IGJldHdlZW4gZ2FtZSBmcmFtZXMuICovXG4gICAgcHJpdmF0ZSBtaW5GcmFtZURlbGF5OiBudW1iZXI7XG5cblx0LyoqIFRoZSBjdXJyZW50IGZyYW1lIG9mIHRoZSBnYW1lLiAqL1xuXHRwcml2YXRlIGZyYW1lOiBudW1iZXI7XG5cblx0LyoqIFRoZSBhY3R1YWwgZnBzIG9mIHRoZSBnYW1lLiAqL1xuICAgIHByaXZhdGUgZnBzOiBudW1iZXI7XG4gICAgXG4gICAgLyoqIFRoZSB0aW1lIGJldHdlZW4gZnBzIG1lYXN1cmVtZW50IHVwZGF0ZXMuICovXG4gICAgcHJpdmF0ZSBmcHNVcGRhdGVJbnRlcnZhbDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSB0aW1lIG9mIHRoZSBsYXN0IGZwcyB1cGRhdGUuICovXG4gICAgcHJpdmF0ZSBsYXN0RnBzVXBkYXRlOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIG51bWJlciBvZiBmcmFtZXMgc2luY2UgdGhlIGxhc3QgZnBzIHVwZGF0ZSB3YXMgZG9uZS4gKi9cbiAgICBwcml2YXRlIGZyYW1lc1NpbmNlTGFzdEZwc1VwZGF0ZTogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBzdGF0dXMgb2Ygd2hldGhlciBvciBub3QgdGhlIGdhbWUgbG9vcCBoYXMgc3RhcnRlZC4gKi9cbiAgICBwcml2YXRlIHN0YXJ0ZWQ6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIHN0YXR1cyBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgZ2FtZSBsb29wIGlzIHBhdXNlZCAqL1xuICAgIHByaXZhdGUgcGF1c2VkOiBib29sZWFuO1xuICAgIFxuICAgIC8qKiBUaGUgc3RhdHVzIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBnYW1lIGxvb3AgaXMgY3VycmVudGx5IHJ1bm5pbmcuICovXG4gICAgcHJpdmF0ZSBydW5uaW5nOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBudW1iZXIgb2YgdXBkYXRlIHN0ZXBzIHRoaXMgaXRlcmF0aW9uIG9mIHRoZSBnYW1lIGxvb3AuICovXG4gICAgcHJpdmF0ZSBudW1VcGRhdGVTdGVwczogbnVtYmVyO1xuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHN1cGVyKCk7XG4gICAgICAgIHRoaXMubWF4VXBkYXRlRlBTID0gNjA7XG4gICAgICAgIHRoaXMudXBkYXRlVGltZXN0ZXAgPSBNYXRoLmZsb29yKDEwMDAvdGhpcy5tYXhVcGRhdGVGUFMpO1xuICAgICAgICB0aGlzLmZyYW1lRGVsdGEgPSAwO1xuICAgICAgICB0aGlzLmxhc3RGcmFtZVRpbWUgPSAwO1xuICAgICAgICB0aGlzLm1pbkZyYW1lRGVsYXkgPSAwO1xuICAgICAgICB0aGlzLmZyYW1lID0gMDtcbiAgICAgICAgdGhpcy5mcHMgPSB0aGlzLm1heFVwZGF0ZUZQUzsgICAvLyBJbml0aWFsaXplIHRoZSBmcHMgdG8gdGhlIG1heCBhbGxvd2VkIGZwc1xuICAgICAgICB0aGlzLmZwc1VwZGF0ZUludGVydmFsID0gMTAwMDtcbiAgICAgICAgdGhpcy5sYXN0RnBzVXBkYXRlID0gMDtcbiAgICAgICAgdGhpcy5mcmFtZXNTaW5jZUxhc3RGcHNVcGRhdGUgPSAwO1xuICAgICAgICB0aGlzLnN0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ydW5uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMubnVtVXBkYXRlU3RlcHMgPSAwO1xuXHR9XG5cblx0Z2V0RlBTKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIDA7XG5cdH1cblxuXHQvKipcbiAgICAgKiBVcGRhdGVzIHRoZSBmcmFtZSBjb3VudCBhbmQgc3VtIG9mIHRpbWUgZm9yIHRoZSBmcmFtZXJhdGUgb2YgdGhlIGdhbWVcbiAgICAgKiBAcGFyYW0gdGltZXN0ZXAgVGhlIGN1cnJlbnQgdGltZSBpbiBtc1xuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGRhdGVGUFModGltZXN0YW1wOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mcHMgPSAwLjkgKiB0aGlzLmZyYW1lc1NpbmNlTGFzdEZwc1VwZGF0ZSAqIDEwMDAgLyAodGltZXN0YW1wIC0gdGhpcy5sYXN0RnBzVXBkYXRlKSArKDEgLSAwLjkpICogdGhpcy5mcHM7XG4gICAgICAgIHRoaXMubGFzdEZwc1VwZGF0ZSA9IHRpbWVzdGFtcDtcbiAgICAgICAgdGhpcy5mcmFtZXNTaW5jZUxhc3RGcHNVcGRhdGUgPSAwO1xuXG4gICAgICAgIERlYnVnLmxvZyhcImZwc1wiLCBcIkZQUzogXCIgKyB0aGlzLmZwcy50b0ZpeGVkKDEpKTtcbiAgICAgICAgU3RhdHMudXBkYXRlRlBTKHRoaXMuZnBzKTtcbiAgICB9XG5cblx0ICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIG1heGltdW0gYWxsb3dlZCBwaHlzaWNzIGZyYW1lcmF0ZSBvZiB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSBpbml0TWF4IFRoZSBtYXggZnJhbWVyYXRlXG4gICAgICovXG4gICAgc2V0TWF4VXBkYXRlRlBTKGluaXRNYXg6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLm1heFVwZGF0ZUZQUyA9IGluaXRNYXg7XG4gICAgICAgIHRoaXMudXBkYXRlVGltZXN0ZXAgPSBNYXRoLmZsb29yKDEwMDAvdGhpcy5tYXhVcGRhdGVGUFMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1heGltdW0gcmVuZGVyaW5nIGZyYW1lcmF0ZVxuICAgICAqIEBwYXJhbSBtYXhGUFMgVGhlIG1heCBmcmFtZXJhdGVcbiAgICAgKi9cbiAgICBzZXRNYXhGUFMobWF4RlBTOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5taW5GcmFtZURlbGF5ID0gMTAwMC9tYXhGUFM7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIHRoZSBnYW1lIGxvb3AgcGFuaWNzLCBpLmUuIGl0IHRyaWVzIHRvIHByb2Nlc3MgdG9vIG11Y2ggdGltZSBpbiBhbiBlbnRpcmUgZnJhbWUuXG5cdCAqIFRoaXMgd2lsbCByZXNldCB0aGUgYW1vdW50IG9mIHRpbWUgYmFjayB0byB6ZXJvLlxuXHQgKiBAcmV0dXJucyBUaGUgYW1vdW50IG9mIHRpbWUgd2UgYXJlIGRpc2NhcmRpbmcgZnJvbSBwcm9jZXNzaW5nLlxuXHQgKi9cblx0cmVzZXRGcmFtZURlbHRhKCkgOiBudW1iZXIge1xuICAgICAgICBsZXQgb2xkRnJhbWVEZWx0YSA9IHRoaXMuZnJhbWVEZWx0YTtcbiAgICAgICAgdGhpcy5mcmFtZURlbHRhID0gMDtcbiAgICAgICAgcmV0dXJuIG9sZEZyYW1lRGVsdGE7XG4gICAgfVxuXG5cdC8qKlxuICAgICAqIFN0YXJ0cyB1cCB0aGUgZ2FtZSBsb29wIGFuZCBjYWxscyB0aGUgZmlyc3QgcmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gICAgICovXG5cdHN0YXJ0KCk6IHZvaWQge1xuICAgICAgICBpZighdGhpcy5zdGFydGVkKXtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKHRpbWVzdGFtcCkgPT4gdGhpcy5kb0ZpcnN0RnJhbWUodGltZXN0YW1wKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwYXVzZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHJlc3VtZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICB9XG5cblx0LyoqXG4gICAgICogVGhlIGZpcnN0IGdhbWUgZnJhbWUgLSBpbml0aWFsaXplcyB0aGUgZmlyc3QgZnJhbWUgdGltZSBhbmQgYmVnaW5zIHRoZSByZW5kZXJcbiAgICAgKiBAcGFyYW0gdGltZXN0YW1wIFRoZSBjdXJyZW50IHRpbWUgaW4gbXNcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZG9GaXJzdEZyYW1lKHRpbWVzdGFtcDogbnVtYmVyKTogdm9pZCAge1xuICAgICAgICB0aGlzLnJ1bm5pbmcgPSB0cnVlO1xuXG4gICAgICAgIHRoaXMuX2RvUmVuZGVyKCk7XG5cbiAgICAgICAgdGhpcy5sYXN0RnJhbWVUaW1lID0gdGltZXN0YW1wO1xuICAgICAgICB0aGlzLmxhc3RGcHNVcGRhdGUgPSB0aW1lc3RhbXA7XG4gICAgICAgIHRoaXMuZnJhbWVzU2luY2VMYXN0RnBzVXBkYXRlID0gMDtcblxuICAgICAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCh0KSA9PiB0aGlzLmRvRnJhbWUodCkpO1xuICAgIH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBhbnkgcHJvY2Vzc2luZyB0aGF0IG5lZWRzIHRvIGJlIGRvbmUgYXQgdGhlIHN0YXJ0IG9mIHRoZSBmcmFtZVxuXHQgKiBAcGFyYW0gdGltZXN0YW1wIFRoZSB0aW1lIG9mIHRoZSBmcmFtZSBpbiBtc1xuXHQgKi9cblx0cHJvdGVjdGVkIHN0YXJ0RnJhbWUodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkIHtcblx0XHQvLyBVcGRhdGUgdGhlIGFtb3VudCBvZiB0aW1lIHdlIG5lZWQgb3VyIHVwZGF0ZSB0byBwcm9jZXNzXG5cdFx0dGhpcy5mcmFtZURlbHRhICs9IHRpbWVzdGFtcCAtIHRoaXMubGFzdEZyYW1lVGltZTtcblxuXHRcdC8vIFNldCB0aGUgbmV3IHRpbWUgb2YgdGhlIGxhc3QgZnJhbWVcbiAgICAgICAgdGhpcy5sYXN0RnJhbWVUaW1lID0gdGltZXN0YW1wO1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgZXN0aW1hdGUgb2YgdGhlIGZyYW1lcmF0ZVxuICAgICAgICBpZih0aW1lc3RhbXAgPiB0aGlzLmxhc3RGcHNVcGRhdGUgKyB0aGlzLmZwc1VwZGF0ZUludGVydmFsKXtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlRlBTKHRpbWVzdGFtcCk7XG4gICAgICAgIH1cblxuXHRcdC8vIEluY3JlbWVudCB0aGUgbnVtYmVyIG9mIGZyYW1lc1xuICAgICAgICB0aGlzLmZyYW1lKys7XG4gICAgICAgIHRoaXMuZnJhbWVzU2luY2VMYXN0RnBzVXBkYXRlKys7XG5cdH1cblxuXHQvKipcbiAgICAgKiBUaGUgbWFpbiBsb29wIG9mIHRoZSBnYW1lLiBVcGRhdGVzIHVudGlsIHRoZSBjdXJyZW50IHRpbWUgaXMgcmVhY2hlZC4gUmVuZGVycyBvbmNlXG4gICAgICogQHBhcmFtIHRpbWVzdGFtcCBUaGUgY3VycmVudCB0aW1lIGluIG1zXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGRvRnJhbWUgPSAodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkID0+IHtcbiAgICAgICAgLy8gSWYgYSBwYXVzZSB3YXMgZXhlY3V0ZWQsIHN0b3AgZG9pbmcgdGhlIGxvb3AuXG4gICAgICAgIGlmKHRoaXMucGF1c2VkKXsgXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXF1ZXN0IGFuaW1hdGlvbiBmcmFtZSB0byBwcmVwYXJlIGZvciBhbm90aGVyIHVwZGF0ZSBvciByZW5kZXJcbiAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgodCkgPT4gdGhpcy5kb0ZyYW1lKHQpKTtcblxuICAgICAgICAvLyBJZiB3ZSBhcmUgdHJ5aW5nIHRvIHJlbmRlciB0b28gc29vbiwgZG8gbm90aGluZy5cbiAgICAgICAgaWYodGltZXN0YW1wIDwgdGhpcy5sYXN0RnJhbWVUaW1lICsgdGhpcy5taW5GcmFtZURlbGF5KXtcbiAgICAgICAgICAgIHJldHVybjtcblx0XHR9XG5cdFx0XG5cdFx0Ly8gQSBmcmFtZSBpcyBhY3R1YWxseSBoYXBwZW5pbmdcblx0XHR0aGlzLnN0YXJ0RnJhbWUodGltZXN0YW1wKTtcblxuXHRcdC8vIFVwZGF0ZSB3aGlsZSB0aGVyZSBpcyBzdGlsbCB0aW1lIHRvIG1ha2UgdXAuIElmIHdlIGRvIHRvbyBtYW55IHVwZGF0ZSBzdGVwcywgcGFuaWMgYW5kIGV4aXQgdGhlIGxvb3AuXG5cdFx0dGhpcy5udW1VcGRhdGVTdGVwcyA9IDA7XG5cdFx0bGV0IHBhbmljID0gZmFsc2U7XG5cbiAgICAgICAgd2hpbGUodGhpcy5mcmFtZURlbHRhID49IHRoaXMudXBkYXRlVGltZXN0ZXApe1xuXHRcdFx0Ly8gRG8gYW4gdXBkYXRlXG5cdFx0XHR0aGlzLl9kb1VwZGF0ZSh0aGlzLnVwZGF0ZVRpbWVzdGVwLzEwMDApO1xuXHRcdFx0XG5cdFx0XHQvLyBSZW1vdmUgdGhlIHVwZGF0ZSBzdGVwIHRpbWUgZnJvbSB0aGUgdGltZSB3ZSBoYXZlIHRvIHByb2Nlc3NcbiAgICAgICAgICAgIHRoaXMuZnJhbWVEZWx0YSAtPSB0aGlzLnVwZGF0ZVRpbWVzdGVwO1xuXG5cdFx0XHQvLyBJbmNyZW1lbnQgc3RlcHMgYW5kIGNoZWNrIGlmIHdlJ3ZlIGRvbmUgdG9vIG1hbnlcbiAgICAgICAgICAgIHRoaXMubnVtVXBkYXRlU3RlcHMrKztcbiAgICAgICAgICAgIGlmKHRoaXMubnVtVXBkYXRlU3RlcHMgPiAxMDApe1xuICAgICAgICAgICAgICAgIHBhbmljID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZXMgYXJlIGRvbmUsIHJlbmRlclxuICAgICAgICB0aGlzLl9kb1JlbmRlcigpO1xuXG4gICAgICAgIC8vIFdyYXAgdXAgdGhlIGZyYW1lXG4gICAgICAgIHRoaXMuZmluaXNoRnJhbWUocGFuaWMpO1xuICAgIH1cblxuXHQvKipcblx0ICogV3JhcHMgdXAgdGhlIGZyYW1lIGFuZCBoYW5kbGVzIHRoZSBwYW5pYyBzdGF0ZSBpZiB0aGVyZSBpcyBvbmVcblx0ICogQHBhcmFtIHBhbmljIFdoZXRoZXIgb3Igbm90IHRoZSBsb29wIHBhbmlja2VkXG5cdCAqL1xuXHRwcm90ZWN0ZWQgZmluaXNoRnJhbWUocGFuaWM6IGJvb2xlYW4pOiB2b2lkIHtcblx0XHRpZihwYW5pYykge1xuICAgICAgICAgICAgdmFyIGRpc2NhcmRlZFRpbWUgPSBNYXRoLnJvdW5kKHRoaXMucmVzZXRGcmFtZURlbHRhKCkpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdNYWluIGxvb3AgcGFuaWNrZWQsIHByb2JhYmx5IGJlY2F1c2UgdGhlIGJyb3dzZXIgdGFiIHdhcyBwdXQgaW4gdGhlIGJhY2tncm91bmQuIERpc2NhcmRpbmcgJyArIGRpc2NhcmRlZFRpbWUgKyAnbXMnKTtcbiAgICAgICAgfVxuXHR9XG5cbn0iLCJpbXBvcnQgRXZlbnRRdWV1ZSBmcm9tIFwiLi4vRXZlbnRzL0V2ZW50UXVldWVcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vSW5wdXQvSW5wdXRcIjtcbmltcG9ydCBJbnB1dEhhbmRsZXIgZnJvbSBcIi4uL0lucHV0L0lucHV0SGFuZGxlclwiO1xuaW1wb3J0IFJlY29yZGVyIGZyb20gXCIuLi9QbGF5YmFjay9SZWNvcmRlclwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuLi9TY2VuZUdyYXBoL1ZpZXdwb3J0XCI7XG5pbXBvcnQgU2NlbmVNYW5hZ2VyIGZyb20gXCIuLi9TY2VuZS9TY2VuZU1hbmFnZXJcIjtcbmltcG9ydCBBdWRpb01hbmFnZXIgZnJvbSBcIi4uL1NvdW5kL0F1ZGlvTWFuYWdlclwiO1xuaW1wb3J0IFN0YXRzIGZyb20gXCIuLi9EZWJ1Zy9TdGF0c1wiO1xuaW1wb3J0IFJlbmRlcmluZ01hbmFnZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9SZW5kZXJpbmdNYW5hZ2VyXCI7XG5pbXBvcnQgQ2FudmFzUmVuZGVyZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9DYW52YXNSZW5kZXJlclwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IEdhbWVPcHRpb25zIGZyb20gXCIuL0dhbWVPcHRpb25zXCI7XG5pbXBvcnQgR2FtZUxvb3AgZnJvbSBcIi4vR2FtZUxvb3BcIjtcbmltcG9ydCBGaXhlZFVwZGF0ZUdhbWVMb29wIGZyb20gXCIuL0ZpeGVkVXBkYXRlR2FtZUxvb3BcIjtcbmltcG9ydCBFbnZpcm9ubWVudEluaXRpYWxpemVyIGZyb20gXCIuL0Vudmlyb25tZW50SW5pdGlhbGl6ZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFJlZ2lzdHJ5TWFuYWdlciBmcm9tIFwiLi4vUmVnaXN0cnkvUmVnaXN0cnlNYW5hZ2VyXCI7XG5pbXBvcnQgV2ViR0xSZW5kZXJlciBmcm9tIFwiLi4vUmVuZGVyaW5nL1dlYkdMUmVuZGVyZXJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmUvU2NlbmVcIjtcblxuLyoqXG4gKiBUaGUgbWFpbiBsb29wIG9mIHRoZSBnYW1lIGVuZ2luZS5cbiAqIEhhbmRsZXMgdGhlIHVwZGF0ZSBvcmRlciwgYW5kIGluaXRpYWxpemVzIGFsbCBzdWJzeXN0ZW1zLlxuICogVGhlIEdhbWUgbWFuYWdlcyB0aGUgdXBkYXRlIGN5Y2xlLCBhbmQgcmVxdWVzdHMgYW5pbWF0aW9uIGZyYW1lcyB0byByZW5kZXIgdG8gdGhlIGJyb3dzZXIuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdhbWUge1xuICAgIGdhbWVPcHRpb25zOiBHYW1lT3B0aW9ucztcbiAgICBwcml2YXRlIHNob3dEZWJ1ZzogYm9vbGVhbjtcbiAgICBwcml2YXRlIHNob3dTdGF0czogYm9vbGVhbjtcblxuICAgIC8vIFRoZSBnYW1lIGxvb3BcbiAgICBwcml2YXRlIGxvb3A6IEdhbWVMb29wO1xuXG4gICAgLy8gR2FtZSBjYW52YXMgYW5kIGl0cyB3aWR0aCBhbmQgaGVpZ2h0XG4gICAgcmVhZG9ubHkgR0FNRV9DQU5WQVM6IEhUTUxDYW52YXNFbGVtZW50O1xuICAgIHJlYWRvbmx5IERFQlVHX0NBTlZBUzogSFRNTENhbnZhc0VsZW1lbnQ7XG5cdHJlYWRvbmx5IFdJRFRIOiBudW1iZXI7XG4gICAgcmVhZG9ubHkgSEVJR0hUOiBudW1iZXI7XG4gICAgcHJpdmF0ZSB2aWV3cG9ydDogVmlld3BvcnQ7XG4gICAgcHJpdmF0ZSBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCB8IFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcbiAgICBwcml2YXRlIGNsZWFyQ29sb3I6IENvbG9yO1xuICAgIFxuICAgIC8vIEFsbCBvZiB0aGUgbmVjZXNzYXJ5IHN1YnN5c3RlbXMgdGhhdCBuZWVkIHRvIHJ1biBoZXJlXG5cdHByaXZhdGUgZXZlbnRRdWV1ZTogRXZlbnRRdWV1ZTtcblx0cHJpdmF0ZSBpbnB1dEhhbmRsZXI6IElucHV0SGFuZGxlcjtcblx0cHJpdmF0ZSByZWNvcmRlcjogUmVjb3JkZXI7XG4gICAgcHJpdmF0ZSByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcbiAgICBwcml2YXRlIHNjZW5lTWFuYWdlcjogU2NlbmVNYW5hZ2VyO1xuICAgIHByaXZhdGUgYXVkaW9NYW5hZ2VyOiBBdWRpb01hbmFnZXI7XG4gICAgcHJpdmF0ZSByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBHYW1lXG4gICAgICogQHBhcmFtIG9wdGlvbnMgVGhlIG9wdGlvbnMgZm9yIEdhbWUgaW5pdGlhbGl6YXRpb25cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pil7XG4gICAgICAgIC8vIEJlZm9yZSBhbnl0aGluZyBlbHNlLCBidWlsZCB0aGUgZW52aXJvbm1lbnRcbiAgICAgICAgRW52aXJvbm1lbnRJbml0aWFsaXplci5zZXR1cCgpO1xuXG4gICAgICAgIC8vIFR5cGVjYXN0IHRoZSBjb25maWcgb2JqZWN0IHRvIGEgR2FtZUNvbmZpZyBvYmplY3RcbiAgICAgICAgdGhpcy5nYW1lT3B0aW9ucyA9IEdhbWVPcHRpb25zLnBhcnNlKG9wdGlvbnMpO1xuXG4gICAgICAgIHRoaXMuc2hvd0RlYnVnID0gdGhpcy5nYW1lT3B0aW9ucy5zaG93RGVidWc7XG4gICAgICAgIHRoaXMuc2hvd1N0YXRzID0gdGhpcy5nYW1lT3B0aW9ucy5zaG93U3RhdHM7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFuIGluc3RhbmNlIG9mIGEgZ2FtZSBsb29wXG4gICAgICAgIHRoaXMubG9vcCA9IG5ldyBGaXhlZFVwZGF0ZUdhbWVMb29wKCk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBnYW1lIGNhbnZhcyBhbmQgZ2l2ZSBpdCBhIGJhY2tncm91bmQgY29sb3JcbiAgICAgICAgdGhpcy5HQU1FX0NBTlZBUyA9IDxIVE1MQ2FudmFzRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImdhbWUtY2FudmFzXCIpO1xuICAgICAgICB0aGlzLkRFQlVHX0NBTlZBUyA9IDxIVE1MQ2FudmFzRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImRlYnVnLWNhbnZhc1wiKTtcbiAgICBcbiAgICAgICAgLy8gR2l2ZSB0aGUgY2FudmFzIGEgc2l6ZSBhbmQgZ2V0IHRoZSByZW5kZXJpbmcgY29udGV4dFxuICAgICAgICB0aGlzLldJRFRIID0gdGhpcy5nYW1lT3B0aW9ucy5jYW52YXNTaXplLng7XG4gICAgICAgIHRoaXMuSEVJR0hUID0gdGhpcy5nYW1lT3B0aW9ucy5jYW52YXNTaXplLnk7XG5cbiAgICAgICAgLy8gVGhpcyBzdGVwIE1VU1QgaGFwcGVuIGJlZm9yZSB0aGUgcmVzb3VyY2UgbWFuYWdlciBkb2VzIGFueXRoaW5nXG4gICAgICAgIGlmKHRoaXMuZ2FtZU9wdGlvbnMudXNlV2ViR0wpe1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyID0gbmV3IFdlYkdMUmVuZGVyZXIoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyaW5nTWFuYWdlciA9IG5ldyBDYW52YXNSZW5kZXJlcigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZUdhbWVXaW5kb3coKTtcbiAgICAgICAgdGhpcy5jdHggPSB0aGlzLnJlbmRlcmluZ01hbmFnZXIuaW5pdGlhbGl6ZUNhbnZhcyh0aGlzLkdBTUVfQ0FOVkFTLCB0aGlzLldJRFRILCB0aGlzLkhFSUdIVCk7XG4gICAgICAgIHRoaXMuY2xlYXJDb2xvciA9IG5ldyBDb2xvcih0aGlzLmdhbWVPcHRpb25zLmNsZWFyQ29sb3IuciwgdGhpcy5nYW1lT3B0aW9ucy5jbGVhckNvbG9yLmcsIHRoaXMuZ2FtZU9wdGlvbnMuY2xlYXJDb2xvci5iKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIGRlYnVnZ2luZyBhbmQgc3RhdHNcbiAgICAgICAgRGVidWcuaW5pdGlhbGl6ZURlYnVnQ2FudmFzKHRoaXMuREVCVUdfQ0FOVkFTLCB0aGlzLldJRFRILCB0aGlzLkhFSUdIVCk7XG4gICAgICAgIFN0YXRzLmluaXRTdGF0cygpO1xuXG4gICAgICAgIGlmKHRoaXMuZ2FtZU9wdGlvbnMuc2hvd1N0YXRzKSB7XG4gICAgICAgICAgICAvLyBGaW5kIHRoZSBzdGF0cyBvdXRwdXQgYW5kIG1ha2UgaXQgbm8gbG9uZ2VyIGhpZGRlblxuICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdGF0c1wiKS5oaWRkZW4gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNpemUgdGhlIHZpZXdwb3J0IHRvIHRoZSBnYW1lIGNhbnZhc1xuICAgICAgICBjb25zdCBjYW52YXNTaXplID0gbmV3IFZlYzIodGhpcy5XSURUSCwgdGhpcy5IRUlHSFQpO1xuICAgICAgICB0aGlzLnZpZXdwb3J0ID0gbmV3IFZpZXdwb3J0KGNhbnZhc1NpemUsIHRoaXMuZ2FtZU9wdGlvbnMuem9vbUxldmVsKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIGFsbCBuZWNlc3NhcnkgZ2FtZSBzdWJzeXN0ZW1zXG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZSA9IEV2ZW50UXVldWUuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5pbnB1dEhhbmRsZXIgPSBuZXcgSW5wdXRIYW5kbGVyKHRoaXMuR0FNRV9DQU5WQVMpO1xuICAgICAgICBJbnB1dC5pbml0aWFsaXplKHRoaXMudmlld3BvcnQsIHRoaXMuZ2FtZU9wdGlvbnMuaW5wdXRzKTtcbiAgICAgICAgdGhpcy5yZWNvcmRlciA9IG5ldyBSZWNvcmRlcigpO1xuICAgICAgICB0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLnNjZW5lTWFuYWdlciA9IG5ldyBTY2VuZU1hbmFnZXIodGhpcy52aWV3cG9ydCwgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyKTtcbiAgICAgICAgdGhpcy5hdWRpb01hbmFnZXIgPSBBdWRpb01hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdXAgdGhlIGdhbWUgd2luZG93IHRoYXQgaG9sZHMgdGhlIGNhbnZhc2VzXG4gICAgICovXG4gICAgcHJpdmF0ZSBpbml0aWFsaXplR2FtZVdpbmRvdygpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZ2FtZVdpbmRvdyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiZ2FtZS13aW5kb3dcIik7XG4gICAgICAgIFxuICAgICAgICAvLyBTZXQgdGhlIGhlaWdodCBvZiB0aGUgZ2FtZSB3aW5kb3dcbiAgICAgICAgZ2FtZVdpbmRvdy5zdHlsZS53aWR0aCA9IHRoaXMuV0lEVEggKyBcInB4XCI7XG4gICAgICAgIGdhbWVXaW5kb3cuc3R5bGUuaGVpZ2h0ID0gdGhpcy5IRUlHSFQgKyBcInB4XCI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmVpdmVzIHRoZSBTY2VuZU1hbmFnZXIgZnJvbSB0aGUgR2FtZVxuICAgICAqIEByZXR1cm5zIFRoZSBTY2VuZU1hbmFnZXJcbiAgICAgKi9cbiAgICBnZXRTY2VuZU1hbmFnZXIoKTogU2NlbmVNYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2NlbmVNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0cyB0aGUgZ2FtZVxuICAgICAqL1xuICAgIHN0YXJ0KEluaXRpYWxTY2VuZTogbmV3ICguLi5hcmdzOiBhbnkpID0+IFNjZW5lLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG4gICAgICAgIC8vIFNldCB0aGUgdXBkYXRlIGZ1bmN0aW9uIG9mIHRoZSBsb29wXG4gICAgICAgIHRoaXMubG9vcC5kb1VwZGF0ZSA9IChkZWx0YVQ6IG51bWJlcikgPT4gdGhpcy51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBTZXQgdGhlIHJlbmRlciBmdW5jdGlvbiBvZiB0aGUgbG9vcFxuICAgICAgICB0aGlzLmxvb3AuZG9SZW5kZXIgPSAoKSA9PiB0aGlzLnJlbmRlcigpO1xuXG4gICAgICAgIC8vIFByZWxvYWQgcmVnaXN0cnkgaXRlbXNcbiAgICAgICAgUmVnaXN0cnlNYW5hZ2VyLnByZWxvYWQoKTtcblxuICAgICAgICAvLyBMb2FkIHRoZSBpdGVtcyB3aXRoIHRoZSByZXNvdXJjZSBtYW5hZ2VyXG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyLmxvYWRSZXNvdXJjZXNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSdyZSBkb25lIGxvYWRpbmcsIHN0YXJ0IHRoZSBsb29wXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkZpbmlzaGVkIFByZWxvYWQgLSBsb2FkaW5nIGZpcnN0IHNjZW5lXCIpO1xuICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShJbml0aWFsU2NlbmUsIHt9LCBvcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMubG9vcC5zdGFydCgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIGFsbCBuZWNlc3Nhcnkgc3Vic3lzdGVtcyBvZiB0aGUgZ2FtZS4gRGVmZXJzIHNjZW5lIHVwZGF0ZXMgdG8gdGhlIHNjZW5lTWFuYWdlclxuICAgICAqIEBwYXJhbSBkZWx0YVQgVGhlIHRpbWUgc2luZSB0aGUgbGFzdCB1cGRhdGVcbiAgICAgKi9cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdHJ5e1xuICAgICAgICAgICAgLy8gSGFuZGxlIGFsbCBldmVudHMgdGhhdCBoYXBwZW5lZCBzaW5jZSB0aGUgc3RhcnQgb2YgdGhlIGxhc3QgbG9vcFxuICAgICAgICAgICAgdGhpcy5ldmVudFF1ZXVlLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGlucHV0IGRhdGEgc3RydWN0dXJlcyBzbyBnYW1lIG9iamVjdHMgY2FuIHNlZSB0aGUgaW5wdXRcbiAgICAgICAgICAgIElucHV0LnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJlY29yZGluZyBvZiB0aGUgZ2FtZVxuICAgICAgICAgICAgdGhpcy5yZWNvcmRlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAgICAgLy8gVXBkYXRlIGFsbCBzY2VuZXNcbiAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgYWxsIHNvdW5kc1xuICAgICAgICAgICAgdGhpcy5hdWRpb01hbmFnZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIExvYWQgb3IgdW5sb2FkIGFueSByZXNvdXJjZXMgaWYgbmVlZGVkXG4gICAgICAgICAgICB0aGlzLnJlc291cmNlTWFuYWdlci51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIHRoaXMubG9vcC5wYXVzZSgpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiVW5jYXVnaHQgRXJyb3IgaW4gVXBkYXRlIC0gQ3Jhc2hpbmcgZ3JhY2VmdWxseVwiKTtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgdGhlIGNhbnZhcyBhbmQgZGVmZXJzIHNjZW5lIHJlbmRlcmluZyB0byB0aGUgc2NlbmVNYW5hZ2VyLiBSZW5kZXJzIHRoZSBkZWJ1ZyBjYW52YXNcbiAgICAgKi9cbiAgICByZW5kZXIoKTogdm9pZCB7XG4gICAgICAgIHRyeXtcbiAgICAgICAgICAgIC8vIENsZWFyIHRoZSBjYW52YXNlc1xuICAgICAgICAgICAgRGVidWcuY2xlYXJDYW52YXMoKTtcblxuICAgICAgICAgICAgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyLmNsZWFyKHRoaXMuY2xlYXJDb2xvcik7XG5cbiAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLnJlbmRlcigpO1xuXG4gICAgICAgICAgICAvLyBIYWNreSBkZWJ1ZyBtb2RlXG4gICAgICAgICAgICBpZihJbnB1dC5pc0tleUp1c3RQcmVzc2VkKFwiZ1wiKSl7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93RGVidWcgPSAhdGhpcy5zaG93RGVidWc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIERlYnVnIHJlbmRlclxuICAgICAgICAgICAgaWYodGhpcy5zaG93RGVidWcpe1xuICAgICAgICAgICAgICAgIERlYnVnLnJlbmRlcigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZih0aGlzLnNob3dTdGF0cyl7XG4gICAgICAgICAgICAgICAgU3RhdHMucmVuZGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICB0aGlzLmxvb3AucGF1c2UoKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlVuY2F1Z2h0IEVycm9yIGluIFJlbmRlciAtIENyYXNoaW5nIGdyYWNlZnVsbHlcIik7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBOdWxsRnVuYyBmcm9tIFwiLi4vRGF0YVR5cGVzL0Z1bmN0aW9ucy9OdWxsRnVuY1wiO1xuXG4vKipcbiAqIFRoZSBtYWluIGdhbWUgbG9vcCBvZiB0aGUgZ2FtZS4gS2VlcHMgdHJhY2sgb2YgZnBzIGFuZCBoYW5kbGVzIHNjaGVkdWxpbmcgb2YgdXBkYXRlcyBhbmQgcmVuZGVyaW5nLlxuICogVGhpcyBjbGFzcyBpcyBsZWZ0IGFic3RyYWN0LCBzbyB0aGF0IGEgc3ViY2xhc3MgY2FuIGhhbmRsZSBleGFjdGx5IGhvdyB0aGUgbG9vcCBpcyBzY2hlZHVsZWQuXG4gKiBGb3IgYW4gZXhhbXBsZSBvZiBkaWZmZXJlbnQgdHlwZXMgb2YgZ2FtZSBsb29wIHNjaGVkdWxpbmcsIGNoZWNrIG91dCBAbGluayhHYW1lIFByb2dyYW1taW5nIFBhdHRlcm5zKShodHRwczovL2dhbWVwcm9ncmFtbWluZ3BhdHRlcm5zLmNvbS9nYW1lLWxvb3AuaHRtbClcbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgR2FtZUxvb3Age1xuXG5cdC8qKiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIGFuIHVwZGF0ZSBvY2N1cnMgKi9cblx0cHJvdGVjdGVkIF9kb1VwZGF0ZTogRnVuY3Rpb24gPSBOdWxsRnVuYztcblxuXHRzZXQgZG9VcGRhdGUodXBkYXRlOiBGdW5jdGlvbil7XG5cdFx0dGhpcy5fZG9VcGRhdGUgPSB1cGRhdGU7XG5cdH1cblxuXHQvKiogVGhlIGZ1bmN0aW9uIHRvIGNhbGwgd2hlbiBhIHJlbmRlciBvY2N1cnMgKi9cblx0cHJvdGVjdGVkIF9kb1JlbmRlcjogRnVuY3Rpb24gPSBOdWxsRnVuYztcblxuXG5cdHNldCBkb1JlbmRlcihyZW5kZXI6IEZ1bmN0aW9uKXtcblx0XHR0aGlzLl9kb1JlbmRlciA9IHJlbmRlcjtcblx0fVxuXHRcblx0LyoqXG5cdCAqIFJldHJpZXZlcyB0aGUgY3VycmVudCBGUFMgb2YgdGhlIGdhbWVcblx0ICovXG5cdGFic3RyYWN0IGdldEZQUygpOiBudW1iZXI7XG5cblx0LyoqXG4gICAgICogU3RhcnRzIHVwIHRoZSBnYW1lIGxvb3BcbiAgICAgKi9cblx0YWJzdHJhY3Qgc3RhcnQoKTogdm9pZDtcblxuXHQvKipcblx0ICogUGF1c2VzIHRoZSBnYW1lIGxvb3AsIHVzdWFsbHkgZm9yIGFuIGVycm9yIGNvbmRpdGlvbi5cblx0ICovXG5cdGFic3RyYWN0IHBhdXNlKCk6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJlc3VtZXMgdGhlIGdhbWUgbG9vcC5cblx0ICovXG5cdGFic3RyYWN0IHJlc3VtZSgpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBSdW5zIHRoZSBmaXJzdCBmcmFtZSBvZiB0aGUgZ2FtZS4gTm8gdXBkYXRlIG9jY3VycyBoZXJlLCBvbmx5IGEgcmVuZGVyLlxuXHQgKiBUaGlzIGlzIG5lZWRlZCB0byBpbml0aWFsaXplIGRlbHRhIHRpbWUgdmFsdWVzXG5cdCAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIHRpbWVzdGFtcCBvZiB0aGUgZnJhbWUuIFRoaXMgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgYnJvd3NlclxuXHQgKi9cblx0cHJvdGVjdGVkIGFic3RyYWN0IGRvRmlyc3RGcmFtZSh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJ1biBiZWZvcmUgYW55IHVwZGF0ZXMgb3IgdGhlIHJlbmRlciBvZiBhIGZyYW1lLlxuXHQgKiBAcGFyYW0gdGltZXN0YW1wIFRoZSB0aW1lc3RhbXAgb2YgdGhlIGZyYW1lLiBUaGlzIGlzIHJlY2VpdmVkIGZyb20gdGhlIGJyb3dzZXJcblx0ICovXG5cdHByb3RlY3RlZCBhYnN0cmFjdCBzdGFydEZyYW1lKHRpbWVzdGFtcDogbnVtYmVyKTogdm9pZDtcblxuXHQvKipcblx0ICogVGhlIGNvcmUgb2YgdGhlIGZyYW1lLCB3aGVyZSBhbnkgbmVjZXNzYXJ5IHVwZGF0ZXMgb2NjdXIsIGFuZCB3aGVyZSBhIHJlbmRlciBoYXBwZW5zXG5cdCAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIHRpbWVzdGFtcCBvZiB0aGUgZnJhbWUuIFRoaXMgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgYnJvd3NlclxuXHQgKi9cblx0cHJvdGVjdGVkIGFic3RyYWN0IGRvRnJhbWUodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBXcmFwcyB1cCB0aGUgZnJhbWVcblx0ICogQHBhcmFtIHBhbmljIFdoZXRoZXIgb3Igbm90IHRoZSB1cGRhdGUgY3ljbGUgcGFuaWNrZWQuIFRoaXMgaGFwcGVucyB3aGVuIHRvbyBtYW55IHVwZGF0ZXMgdHJ5IHRvIGhhcHBlbiBpbiBhIHNpbmdsZSBmcmFtZVxuXHQgKi9cblx0cHJvdGVjdGVkIGFic3RyYWN0IGZpbmlzaEZyYW1lKHBhbmljOiBib29sZWFuKTogdm9pZDtcbn0iLCIvLyBAaWdub3JlUGFnZVxuXG4vKiogVGhlIG9wdGlvbnMgZm9yIGluaXRpYWxpemluZyB0aGUgQHJlZmVyZW5jZVtHYW1lTG9vcF0gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdhbWVPcHRpb25zIHtcbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0ICovXG4gICAgY2FudmFzU2l6ZToge3g6IG51bWJlciwgeTogbnVtYmVyfTtcblxuICAgIC8qIFRoZSBkZWZhdWx0IGxldmVsIG9mIHpvb20gKi9cbiAgICB6b29tTGV2ZWw6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgY29sb3IgdG8gY2xlYXIgdGhlIGNhbnZhcyB0byBlYWNoIGZyYW1lICovXG4gICAgY2xlYXJDb2xvcjoge3I6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXJ9XG5cbiAgICAvKiBBIGxpc3Qgb2YgaW5wdXQgYmluZGluZ3MgKi9cbiAgICBpbnB1dHM6IEFycmF5PHtuYW1lOiBzdHJpbmcsIGtleXM6IEFycmF5PHN0cmluZz59PjtcblxuICAgIC8qIFdoZXRoZXIgb3Igbm90IHRoZSBkZWJ1ZyByZW5kZXJpbmcgc2hvdWxkIG9jY3VyICovXG4gICAgc2hvd0RlYnVnOiBib29sZWFuO1xuXG4gICAgLyogV2hldGhlciBvciBub3QgdGhlIHN0YXRzIHJlbmRlcmluZyBzaG91bGQgb2NjdXIgKi9cbiAgICBzaG93U3RhdHM6IGJvb2xlYW47XG5cbiAgICAvKiBXaGV0aGVyIG9yIG5vdCB0byB1c2Ugd2ViR0wgKi9cbiAgICB1c2VXZWJHTDogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIFBhcnNlcyB0aGUgZGF0YSBpbiB0aGUgcmF3IG9wdGlvbnMgb2JqZWN0XG4gICAgICogQHBhcmFtIG9wdGlvbnMgVGhlIGdhbWUgb3B0aW9ucyBhcyBhIFJlY29yZFxuICAgICAqIEByZXR1cm5zIEEgdmVyc2lvbiBvZiB0aGUgb3B0aW9ucyBjb252ZXJ0ZWQgdG8gYSBHYW1lT3B0aW9ucyBvYmplY3RcbiAgICAgKi9cbiAgICBzdGF0aWMgcGFyc2Uob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IEdhbWVPcHRpb25zIHtcbiAgICAgICAgbGV0IGdPcHQgPSBuZXcgR2FtZU9wdGlvbnMoKTtcblxuICAgICAgICBnT3B0LmNhbnZhc1NpemUgPSBvcHRpb25zLmNhbnZhc1NpemUgPyBvcHRpb25zLmNhbnZhc1NpemUgOiB7eDogODAwLCB5OiA2MDB9O1xuICAgICAgICBnT3B0Lnpvb21MZXZlbCA9IG9wdGlvbnMuem9vbUxldmVsID8gb3B0aW9ucy56b29tTGV2ZWwgOiAxO1xuICAgICAgICBnT3B0LmNsZWFyQ29sb3IgPSBvcHRpb25zLmNsZWFyQ29sb3IgPyBvcHRpb25zLmNsZWFyQ29sb3IgOiB7cjogMjU1LCBnOiAyNTUsIGI6IDI1NX07XG4gICAgICAgIGdPcHQuaW5wdXRzID0gb3B0aW9ucy5pbnB1dHMgPyBvcHRpb25zLmlucHV0cyA6IFtdO1xuICAgICAgICBnT3B0LnNob3dEZWJ1ZyA9ICEhb3B0aW9ucy5zaG93RGVidWc7XG4gICAgICAgIGdPcHQuc2hvd1N0YXRzID0gISFvcHRpb25zLnNob3dTdGF0cztcbiAgICAgICAgZ09wdC51c2VXZWJHTCA9ICEhb3B0aW9ucy51c2VXZWJHTDtcblxuICAgICAgICByZXR1cm4gZ09wdDtcbiAgICB9XG59IiwiaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuL0dhbWVOb2RlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBSZWdpb24gZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1JlZ2lvblwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhbiBvYmplY3QgaW4gdGhlIGdhbWUgd29ybGQgdGhhdCBjYW4gYmUgZHJhd24gdG8gdGhlIHNjcmVlblxuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBDYW52YXNOb2RlIGV4dGVuZHMgR2FtZU5vZGUgaW1wbGVtZW50cyBSZWdpb24ge1xuXHRwcml2YXRlIF9zaXplOiBWZWMyO1xuXHRwcml2YXRlIF9zY2FsZTogVmVjMjtcblx0cHJpdmF0ZSBfYm91bmRhcnk6IEFBQkI7XG5cdHByaXZhdGUgX2hhc0N1c3RvbVNoYWRlcjogYm9vbGVhbjtcblx0cHJpdmF0ZSBfY3VzdG9tU2hhZGVyS2V5OiBzdHJpbmc7XG5cdHByaXZhdGUgX2FscGhhOiBudW1iZXI7XG5cblx0LyoqIEEgZmxhZyBmb3Igd2hldGhlciBvciBub3QgdGhlIENhbnZhc05vZGUgaXMgdmlzaWJsZSAqL1xuXHR2aXNpYmxlOiBib29sZWFuID0gdHJ1ZTtcblx0XG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLl9zaXplID0gbmV3IFZlYzIoMCwgMCk7XG5cdFx0dGhpcy5fc2l6ZS5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnNpemVDaGFuZ2VkKCkpO1xuXHRcdHRoaXMuX3NjYWxlID0gbmV3IFZlYzIoMSwgMSk7XG5cdFx0dGhpcy5fc2NhbGUuc2V0T25DaGFuZ2UoKCkgPT4gdGhpcy5zY2FsZUNoYW5nZWQoKSk7XG5cdFx0dGhpcy5fYm91bmRhcnkgPSBuZXcgQUFCQigpO1xuXHRcdHRoaXMudXBkYXRlQm91bmRhcnkoKTtcblxuXHRcdHRoaXMuX2hhc0N1c3RvbVNoYWRlciA9IGZhbHNlO1xuXHR9XG5cblx0Z2V0IGFscGhhKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMuX2FscGhhO1xuXHR9XG5cblx0c2V0IGFscGhhKGE6IG51bWJlcikge1xuXHRcdHRoaXMuX2FscGhhID0gYTtcblx0fVxuXG5cdGdldCBzaXplKCk6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLl9zaXplO1xuXHR9XG5cblx0c2V0IHNpemUoc2l6ZTogVmVjMil7XG5cdFx0dGhpcy5fc2l6ZSA9IHNpemU7XG5cdFx0Ly8gRW50ZXIgYXMgYSBsYW1iZGEgdG8gYmluZCBcInRoaXNcIlxuXHRcdHRoaXMuX3NpemUuc2V0T25DaGFuZ2UoKCkgPT4gdGhpcy5zaXplQ2hhbmdlZCgpKTtcblx0XHR0aGlzLnNpemVDaGFuZ2VkKCk7XG5cdH1cblxuXHRnZXQgc2NhbGUoKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuX3NjYWxlO1xuXHR9XG5cblx0c2V0IHNjYWxlKHNjYWxlOiBWZWMyKXtcblx0XHR0aGlzLl9zY2FsZSA9IHNjYWxlO1xuXHRcdC8vIEVudGVyIGFzIGEgbGFtYmRhIHRvIGJpbmQgXCJ0aGlzXCJcblx0XHR0aGlzLl9zY2FsZS5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnNjYWxlQ2hhbmdlZCgpKTtcblx0XHR0aGlzLnNjYWxlQ2hhbmdlZCgpO1xuXHR9XG5cblx0c2V0IHNjYWxlWCh2YWx1ZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5zY2FsZS54ID0gdmFsdWU7XG5cdH1cblxuXHRzZXQgc2NhbGVZKHZhbHVlOiBudW1iZXIpIHtcblx0XHR0aGlzLnNjYWxlLnkgPSB2YWx1ZTtcblx0fVxuXG5cdGdldCBoYXNDdXN0b21TaGFkZXIoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2hhc0N1c3RvbVNoYWRlcjtcblx0fVxuXG5cdGdldCBjdXN0b21TaGFkZXJLZXkoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy5fY3VzdG9tU2hhZGVyS2V5O1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdHByb3RlY3RlZCBwb3NpdGlvbkNoYW5nZWQoKTogdm9pZCB7XG5cdFx0c3VwZXIucG9zaXRpb25DaGFuZ2VkKCk7XG5cdFx0dGhpcy51cGRhdGVCb3VuZGFyeSgpO1xuXHR9XG5cblx0LyoqIENhbGxlZCBpZiB0aGUgc2l6ZSB2ZWN0b3IgaXMgY2hhbmdlZCBvciByZXBsYWNlZC4gKi9cblx0cHJvdGVjdGVkIHNpemVDaGFuZ2VkKCk6IHZvaWQge1xuXHRcdHRoaXMudXBkYXRlQm91bmRhcnkoKTtcblx0fVxuXG5cdC8qKiBDYWxsZWQgaWYgdGhlIHNjYWxlIHZlY3RvciBpcyBjaGFuZ2VkIG9yIHJlcGxhY2VkICovXG5cdHByb3RlY3RlZCBzY2FsZUNoYW5nZWQoKTogdm9pZCB7XG5cdFx0dGhpcy51cGRhdGVCb3VuZGFyeSgpO1xuXHR9XG5cblx0Ly8gQGRvY0lnbm9yZVxuXHQvKiogQ2FsbGVkIGlmIHRoZSBwb3NpdGlvbiwgc2l6ZSwgb3Igc2NhbGUgb2YgdGhlIENhbnZhc05vZGUgaXMgY2hhbmdlZC4gVXBkYXRlcyB0aGUgYm91bmRhcnkuICovXG5cdHByaXZhdGUgdXBkYXRlQm91bmRhcnkoKTogdm9pZCB7XG5cdFx0dGhpcy5fYm91bmRhcnkuY2VudGVyLnNldCh0aGlzLnBvc2l0aW9uLngsIHRoaXMucG9zaXRpb24ueSk7XG5cdFx0dGhpcy5fYm91bmRhcnkuaGFsZlNpemUuc2V0KHRoaXMuc2l6ZS54KnRoaXMuc2NhbGUueC8yLCB0aGlzLnNpemUueSp0aGlzLnNjYWxlLnkvMik7XG5cdH1cblxuXHRnZXQgYm91bmRhcnkoKTogQUFCQiB7XG5cdFx0cmV0dXJuIHRoaXMuX2JvdW5kYXJ5O1xuXHR9XG5cblx0Z2V0IHNpemVXaXRoWm9vbSgpOiBWZWMyIHtcblx0XHRsZXQgem9vbSA9IHRoaXMuc2NlbmUuZ2V0Vmlld1NjYWxlKCk7XG5cblx0XHRyZXR1cm4gdGhpcy5ib3VuZGFyeS5oYWxmU2l6ZS5jbG9uZSgpLnNjYWxlZCh6b29tLCB6b29tKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgY3VzdG9tIHNoYWRlciB0byB0aGlzIENhbnZhc05vZGVcblx0ICogQHBhcmFtIGtleSBUaGUgcmVnaXN0cnkga2V5IG9mIHRoZSBTaGFkZXJUeXBlXG5cdCAqL1xuXHR1c2VDdXN0b21TaGFkZXIoa2V5OiBzdHJpbmcpOiB2b2lkIHtcblx0XHR0aGlzLl9oYXNDdXN0b21TaGFkZXIgPSB0cnVlO1xuXHRcdHRoaXMuX2N1c3RvbVNoYWRlcktleSA9IGtleTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHBvaW50ICh4LCB5KSBpcyBpbnNpZGUgb2YgdGhpcyBjYW52YXMgb2JqZWN0XG5cdCAqIEBwYXJhbSB4IFRoZSB4IHBvc2l0aW9uIG9mIHRoZSBwb2ludFxuXHQgKiBAcGFyYW0geSBUaGUgeSBwb3NpdGlvbiBvZiB0aGUgcG9pbnRcblx0ICogQHJldHVybnMgQSBmbGFnIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGlzIG5vZGUgY29udGFpbnMgdGhlIHBvaW50LlxuXHQgKi9cblx0Y29udGFpbnMoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5fYm91bmRhcnkuY29udGFpbnNQb2ludChuZXcgVmVjMih4LCB5KSk7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0ZGVidWdSZW5kZXIoKTogdm9pZCB7XG5cdFx0RGVidWcuZHJhd0JveCh0aGlzLnJlbGF0aXZlUG9zaXRpb24sIHRoaXMuc2l6ZVdpdGhab29tLCBmYWxzZSwgQ29sb3IuQkxVRSk7XG5cdFx0c3VwZXIuZGVidWdSZW5kZXIoKTtcblx0fVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi9FdmVudHMvRW1pdHRlclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IExheWVyIGZyb20gXCIuLi9TY2VuZS9MYXllclwiO1xuaW1wb3J0IEFJIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9BSVwiO1xuaW1wb3J0IFBoeXNpY2FsIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9QaHlzaWNhbFwiO1xuaW1wb3J0IFBvc2l0aW9uZWQgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1Bvc2l0aW9uZWRcIjtcbmltcG9ydCB7IGlzUmVnaW9uIH0gZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1JlZ2lvblwiO1xuaW1wb3J0IFVuaXF1ZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVW5pcXVlXCI7XG5pbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IERlYnVnUmVuZGVyYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvRGVidWdSZW5kZXJhYmxlXCI7XG5pbXBvcnQgQWN0b3IgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FjdG9yXCI7XG5pbXBvcnQgU2hhcGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvU2hhcGVcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuLi9EYXRhVHlwZXMvU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBOYXZpZ2F0aW9uUGF0aCBmcm9tIFwiLi4vUGF0aGZpbmRpbmcvTmF2aWdhdGlvblBhdGhcIjtcbmltcG9ydCBUd2VlbkNvbnRyb2xsZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9BbmltYXRpb25zL1R3ZWVuQ29udHJvbGxlclwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IENpcmNsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9DaXJjbGVcIjtcbmltcG9ydCBHb2FwQUkgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0dvYXBBSVwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhbiBvYmplY3QgaW4gdGhlIGdhbWUgd29ybGQuXG4gKiBUbyBjb25zdHJ1Y3QgR2FtZU5vZGVzLCBzZWUgdGhlIEByZWZlcmVuY2VbU2NlbmVdIGRvY3VtZW50YXRpb24uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIEdhbWVOb2RlIGltcGxlbWVudHMgUG9zaXRpb25lZCwgVW5pcXVlLCBVcGRhdGVhYmxlLCBQaHlzaWNhbCwgQWN0b3IsIERlYnVnUmVuZGVyYWJsZSB7XG5cdC8qLS0tLS0tLS0tLSBQT1NJVElPTkVEIC0tLS0tLS0tLS0qL1xuXHRwcml2YXRlIF9wb3NpdGlvbjogVmVjMjtcblxuXHQvKi0tLS0tLS0tLS0gVU5JUVVFIC0tLS0tLS0tLS0qL1xuXHRwcml2YXRlIF9pZDogbnVtYmVyO1xuXG5cdC8qLS0tLS0tLS0tLSBQSFlTSUNBTCAtLS0tLS0tLS0tKi9cblx0aGFzUGh5c2ljczogYm9vbGVhbiA9IGZhbHNlO1xuXHRtb3Zpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblx0ZnJvemVuOiBib29sZWFuID0gZmFsc2U7XG5cdG9uR3JvdW5kOiBib29sZWFuID0gZmFsc2U7XG5cdG9uV2FsbDogYm9vbGVhbiA9IGZhbHNlO1xuXHRvbkNlaWxpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblx0YWN0aXZlOiBib29sZWFuID0gZmFsc2U7XG5cdGNvbGxpc2lvblNoYXBlOiBTaGFwZTtcblx0Y29sbGlkZXJPZmZzZXQ6IFZlYzI7XG5cdGlzU3RhdGljOiBib29sZWFuO1xuXHRpc0NvbGxpZGFibGU6IGJvb2xlYW47XG5cdGlzVHJpZ2dlcjogYm9vbGVhbjtcblx0dHJpZ2dlck1hc2s6IG51bWJlcjtcblx0dHJpZ2dlckVudGVyczogQXJyYXk8c3RyaW5nPjtcblx0dHJpZ2dlckV4aXRzOiBBcnJheTxzdHJpbmc+O1xuXHRfdmVsb2NpdHk6IFZlYzI7XG5cdHN3ZXB0UmVjdDogQUFCQjtcblx0Y29sbGlkZWRXaXRoVGlsZW1hcDogYm9vbGVhbjtcblx0Z3JvdXA6IG51bWJlcjtcblx0aXNQbGF5ZXI6IGJvb2xlYW47XG5cdGlzQ29sbGlkaW5nOiBib29sZWFuID0gZmFsc2U7XG5cblx0LyotLS0tLS0tLS0tIEFDVE9SIC0tLS0tLS0tLS0qL1xuXHRfYWk6IEFJIHwgR29hcEFJO1xuXHRhaUFjdGl2ZTogYm9vbGVhbjtcblx0cGF0aDogTmF2aWdhdGlvblBhdGg7XG5cdHBhdGhmaW5kaW5nOiBib29sZWFuID0gZmFsc2U7XG5cblx0LyotLS0tLS0tLS0tIEdFTkVSQUwgLS0tLS0tLS0tLSovXG5cdC8qKiBBbiBldmVudCByZWNlaXZlci4gKi9cblx0cHJvdGVjdGVkIHJlY2VpdmVyOiBSZWNlaXZlcjtcblx0LyoqIEFuIGV2ZW50IGVtaXR0ZXIuICovXG5cdHByb3RlY3RlZCBlbWl0dGVyOiBFbWl0dGVyO1xuXHQvKiogQSByZWZlcmVuY2UgdG8gdGhlIHNjZW5lIHRoaXMgR2FtZU5vZGUgaXMgYSBwYXJ0IG9mLiAqL1xuXHRwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuXHQvKiogVGhlIHZpc3VhbCBsYXllciB0aGlzIEdhbWVOb2RlIHJlc2lkZXMgaW4uICovXG5cdHByb3RlY3RlZCBsYXllcjogTGF5ZXI7XG5cdC8qKiBBIHV0aWxpdHkgdGhhdCBhbGxvd3MgdGhlIHVzZSBvZiB0d2VlbnMgb24gdGhpcyBHYW1lTm9kZSAqL1xuXHR0d2VlbnM6IFR3ZWVuQ29udHJvbGxlcjtcblx0LyoqIEEgdHdlZW5hYmxlIHByb3BlcnR5IGZvciByb3RhdGlvbi4gRG9lcyBub3QgYWZmZWN0IHRoZSBib3VuZGluZyBib3ggb2YgdGhpcyBHYW1lTm9kZSAtIE9ubHkgcmVuZGVyaW5nLiAqL1xuXHRyb3RhdGlvbjogbnVtYmVyO1xuXHQvKiogVGhlIG9wYWNpdHkgdmFsdWUgb2YgdGhpcyBHYW1lTm9kZSAqL1xuXHRhYnN0cmFjdCBzZXQgYWxwaGEoYTogbnVtYmVyKTtcblxuXHRhYnN0cmFjdCBnZXQgYWxwaGEoKTogbnVtYmVyO1xuXG5cdC8vIENvbnN0cnVjdG9yIGRvY3MgYXJlIGlnbm9yZWQsIGFzIHRoZSB1c2VyIHNob3VsZCBOT1QgY3JlYXRlIG5ldyBHYW1lTm9kZXMgd2l0aCBhIHJhdyBjb25zdHJ1Y3RvclxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMuX3Bvc2l0aW9uID0gbmV3IFZlYzIoMCwgMCk7XG5cdFx0dGhpcy5fcG9zaXRpb24uc2V0T25DaGFuZ2UoKCkgPT4gdGhpcy5wb3NpdGlvbkNoYW5nZWQoKSk7XG5cdFx0dGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuXHRcdHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG5cdFx0dGhpcy50d2VlbnMgPSBuZXcgVHdlZW5Db250cm9sbGVyKHRoaXMpO1xuXHRcdHRoaXMucm90YXRpb24gPSAwO1xuXHR9XG5cblx0ZGVzdHJveSgpe1xuXHRcdHRoaXMudHdlZW5zLmRlc3Ryb3koKTtcblx0XHR0aGlzLnJlY2VpdmVyLmRlc3Ryb3koKTtcblxuXHRcdGlmKHRoaXMuaGFzUGh5c2ljcyl7XG5cdFx0XHR0aGlzLnJlbW92ZVBoeXNpY3MoKTtcblx0XHR9XG5cblx0XHRpZih0aGlzLl9haSl7XG5cdFx0XHR0aGlzLl9haS5kZXN0cm95KCk7XG5cdFx0XHRkZWxldGUgdGhpcy5fYWk7XG5cdFx0XHR0aGlzLnNjZW5lLmdldEFJTWFuYWdlcigpLnJlbW92ZUFjdG9yKHRoaXMpO1xuXHRcdH1cblxuXHRcdHRoaXMuc2NlbmUucmVtb3ZlKHRoaXMpO1xuXG5cdFx0dGhpcy5sYXllci5yZW1vdmVOb2RlKHRoaXMpO1xuXHR9XG5cblx0LyotLS0tLS0tLS0tIFBPU0lUSU9ORUQgLS0tLS0tLS0tLSovXG5cdGdldCBwb3NpdGlvbigpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5fcG9zaXRpb247XG5cdH1cblxuXHRzZXQgcG9zaXRpb24ocG9zOiBWZWMyKSB7XG5cdFx0dGhpcy5fcG9zaXRpb24gPSBwb3M7XG5cdFx0dGhpcy5fcG9zaXRpb24uc2V0T25DaGFuZ2UoKCkgPT4gdGhpcy5wb3NpdGlvbkNoYW5nZWQoKSk7XG5cdFx0dGhpcy5wb3NpdGlvbkNoYW5nZWQoKTtcblx0fVxuXG5cdGdldCByZWxhdGl2ZVBvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLmluUmVsYXRpdmVDb29yZGluYXRlcyh0aGlzLnBvc2l0aW9uKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIHBvaW50IHRvIGNvb3JkaW5hdGVzIHJlbGF0aXZlIHRvIHRoZSB6b29tIGFuZCBvcmlnaW4gb2YgdGhpcyBub2RlXG5cdCAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdG8gY29udmVyXG5cdCAqIEByZXR1cm5zIEEgbmV3IFZlYzIgcmVwcmVzZW50aW5nIHRoZSBwb2ludCBpbiByZWxhdGl2ZSBjb29yZGluYXRlc1xuXHQgKi9cblx0aW5SZWxhdGl2ZUNvb3JkaW5hdGVzKHBvaW50OiBWZWMyKTogVmVjMiB7XG5cdFx0bGV0IG9yaWdpbiA9IHRoaXMuc2NlbmUuZ2V0Vmlld1RyYW5zbGF0aW9uKHRoaXMpO1xuXHRcdGxldCB6b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcblx0XHRyZXR1cm4gcG9pbnQuY2xvbmUoKS5zdWIob3JpZ2luKS5zY2FsZSh6b29tKTtcblx0fVxuXG5cdC8qLS0tLS0tLS0tLSBVTklRVUUgLS0tLS0tLS0tLSovXG5cdGdldCBpZCgpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLl9pZDtcblx0fVxuXG5cdHNldCBpZChpZDogbnVtYmVyKSB7XG5cdFx0Ly8gaWQgY2FuIG9ubHkgYmUgc2V0IG9uY2Vcblx0XHRpZih0aGlzLl9pZCA9PT0gdW5kZWZpbmVkKXtcblx0XHRcdHRoaXMuX2lkID0gaWQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRocm93IFwiQXR0ZW1wdGVkIHRvIGFzc2lnbiBpZCB0byBvYmplY3QgdGhhdCBhbHJlYWR5IGhhcyBpZC5cIlxuXHRcdH1cblx0fVxuXG5cdC8qLS0tLS0tLS0tLSBQSFlTSUNBTCAtLS0tLS0tLS0tKi9cblx0Ly8gQGltcGxlbWVudGVkXG5cdC8qKlxuICAgICAqIEBwYXJhbSB2ZWxvY2l0eSBUaGUgdmVsb2NpdHkgd2l0aCB3aGljaCB0byBtb3ZlIHRoZSBvYmplY3QuXG4gICAgICovXG5cdG1vdmUodmVsb2NpdHk6IFZlYzIpOiB2b2lkIHtcblx0XHRpZih0aGlzLmZyb3plbikgcmV0dXJuO1xuXHRcdHRoaXMubW92aW5nID0gdHJ1ZTtcblx0XHR0aGlzLl92ZWxvY2l0eSA9IHZlbG9jaXR5O1xuXHR9O1xuXG5cdG1vdmVPblBhdGgoc3BlZWQ6IG51bWJlciwgcGF0aDogTmF2aWdhdGlvblBhdGgpOiB2b2lkIHtcblx0XHRpZih0aGlzLmZyb3plbikgcmV0dXJuO1xuXHRcdHRoaXMucGF0aCA9IHBhdGg7XG5cdFx0bGV0IGRpciA9IHBhdGguZ2V0TW92ZURpcmVjdGlvbih0aGlzKTtcblx0XHR0aGlzLm1vdmluZyA9IHRydWU7XG5cdFx0dGhpcy5wYXRoZmluZGluZyA9IHRydWU7XG5cdFx0dGhpcy5fdmVsb2NpdHkgPSBkaXIuc2NhbGUoc3BlZWQpO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHZlbG9jaXR5IFRoZSB2ZWxvY2l0eSB3aXRoIHdoaWNoIHRoZSBvYmplY3Qgd2lsbCBtb3ZlLlxuICAgICAqL1xuXHRmaW5pc2hNb3ZlKCk6IHZvaWQge1xuXHRcdHRoaXMubW92aW5nID0gZmFsc2U7XG5cdFx0dGhpcy5wb3NpdGlvbi5hZGQodGhpcy5fdmVsb2NpdHkpO1xuXHRcdGlmKHRoaXMucGF0aGZpbmRpbmcpe1xuXHRcdFx0dGhpcy5wYXRoLmhhbmRsZVBhdGhQcm9ncmVzcyh0aGlzKTtcblx0XHRcdHRoaXMucGF0aCA9IG51bGw7XG5cdFx0XHR0aGlzLnBhdGhmaW5kaW5nID0gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdC8qKlxuXHQgKiBAcGFyYW0gY29sbGlzaW9uU2hhcGUgVGhlIGNvbGxpZGVyIGZvciB0aGlzIG9iamVjdC4gSWYgdGhpcyBoYXMgYSByZWdpb24gKGltcGxlbWVudHMgUmVnaW9uKSxcblx0ICogaXQgd2lsbCBiZSB1c2VkIHdoZW4gbm8gY29sbGlzaW9uIHNoYXBlIGlzIHNwZWNpZmllZCAob3IgaWYgY29sbGlzaW9uIHNoYXBlIGlzIG51bGwpLlxuXHQgKiBAcGFyYW0gaXNDb2xsaWRhYmxlIFdoZXRoZXIgdGhpcyBpcyBjb2xsaWRhYmxlIG9yIG5vdC4gVHJ1ZSBieSBkZWZhdWx0LlxuXHQgKiBAcGFyYW0gaXNTdGF0aWMgV2hldGhlciB0aGlzIGlzIHN0YXRpYyBvciBub3QuIEZhbHNlIGJ5IGRlZmF1bHRcblx0ICovXG5cdGFkZFBoeXNpY3MoY29sbGlzaW9uU2hhcGU/OiBTaGFwZSwgY29sbGlkZXJPZmZzZXQ/OiBWZWMyLCBpc0NvbGxpZGFibGU6IGJvb2xlYW4gPSB0cnVlLCBpc1N0YXRpYzogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aGUgcGh5c2ljcyB2YXJpYWJsZXNcblx0XHR0aGlzLmhhc1BoeXNpY3MgPSB0cnVlO1xuXHRcdHRoaXMubW92aW5nID0gZmFsc2U7XG5cdFx0dGhpcy5vbkdyb3VuZCA9IGZhbHNlO1xuXHRcdHRoaXMub25XYWxsID0gZmFsc2U7XG5cdFx0dGhpcy5vbkNlaWxpbmcgPSBmYWxzZTtcblx0XHR0aGlzLmFjdGl2ZSA9IHRydWU7XG5cdFx0dGhpcy5pc0NvbGxpZGFibGUgPSBpc0NvbGxpZGFibGU7XG5cdFx0dGhpcy5pc1N0YXRpYyA9IGlzU3RhdGljO1xuXHRcdHRoaXMuaXNUcmlnZ2VyID0gZmFsc2U7XG5cdFx0dGhpcy50cmlnZ2VyTWFzayA9IDA7XG5cdFx0dGhpcy50cmlnZ2VyRW50ZXJzID0gbmV3IEFycmF5KDMyKTtcblx0XHR0aGlzLnRyaWdnZXJFeGl0cyA9IG5ldyBBcnJheSgzMik7XG5cdFx0dGhpcy5fdmVsb2NpdHkgPSBWZWMyLlpFUk87XG5cdFx0dGhpcy5zd2VwdFJlY3QgPSBuZXcgQUFCQigpO1xuXHRcdHRoaXMuY29sbGlkZWRXaXRoVGlsZW1hcCA9IGZhbHNlO1xuXHRcdHRoaXMuZ3JvdXAgPSAtMTtcdFx0XHRcdFx0Ly8gVGhlIGRlZmF1bHQgZ3JvdXAsIGNvbGxpZGVzIHdpdGggZXZlcnl0aGluZ1xuXG5cdFx0Ly8gU2V0IHRoZSBjb2xsaXNpb24gc2hhcGUgaWYgcHJvdmlkZWQsIG9yIHNpbXBseSB1c2UgdGhlIHRoZSByZWdpb24gaWYgdGhlcmUgaXMgb25lLlxuXHRcdGlmKGNvbGxpc2lvblNoYXBlKXtcblx0XHRcdHRoaXMuY29sbGlzaW9uU2hhcGUgPSBjb2xsaXNpb25TaGFwZTtcblx0XHRcdHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyID0gdGhpcy5wb3NpdGlvbjtcblx0XHR9IGVsc2UgaWYgKGlzUmVnaW9uKHRoaXMpKSB7XG5cdFx0XHQvLyBJZiB0aGUgZ2FtZW5vZGUgaGFzIGEgcmVnaW9uIGFuZCBubyBvdGhlciBpcyBzcGVjaWZpZWQsIHVzZSB0aGF0XG5cdFx0XHR0aGlzLmNvbGxpc2lvblNoYXBlID0gKDxhbnk+dGhpcykuYm91bmRhcnkuY2xvbmUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgXCJObyBjb2xsaXNpb24gc2hhcGUgc3BlY2lmaWVkIGZvciBwaHlzaWNzIG9iamVjdC5cIlxuXHRcdH1cblxuXHRcdC8vIElmIHdlIHdlcmUgcHJvdmlkZWQgd2l0aCBhIGNvbGxpZGVyIG9mZnNldCwgc2V0IGl0LiBPdGhlcndpc2UgdGhlcmUgaXMgbm8gb2Zmc2V0LCBzbyB1c2UgdGhlIHplcm8gdmVjdG9yXG5cdFx0aWYoY29sbGlkZXJPZmZzZXQpe1xuXHRcdFx0dGhpcy5jb2xsaWRlck9mZnNldCA9IGNvbGxpZGVyT2Zmc2V0O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmNvbGxpZGVyT2Zmc2V0ID0gVmVjMi5aRVJPO1xuXHRcdH1cblxuXHRcdC8vIEluaXRpYWxpemUgdGhlIHN3ZXB0IHJlY3Rcblx0XHR0aGlzLnN3ZXB0UmVjdCA9IHRoaXMuY29sbGlzaW9uU2hhcGUuZ2V0Qm91bmRpbmdSZWN0KCk7XG5cblx0XHQvLyBSZWdpc3RlciB0aGUgb2JqZWN0IHdpdGggcGh5c2ljc1xuXHRcdHRoaXMuc2NlbmUuZ2V0UGh5c2ljc01hbmFnZXIoKS5yZWdpc3Rlck9iamVjdCh0aGlzKTtcblx0fVxuXG5cdC8qKiBSZW1vdmVzIHRoaXMgb2JqZWN0IGZyb20gdGhlIHBoeXNpY3Mgc3lzdGVtICovXG4gICAgcmVtb3ZlUGh5c2ljcygpOiB2b2lkIHtcblx0XHQvLyBSZW1vdmUgdGhpcyBmcm9tIHRoZSBwaHlzaWNzIG1hbmFnZXJcblx0XHR0aGlzLnNjZW5lLmdldFBoeXNpY3NNYW5hZ2VyKCkuZGVyZWdpc3Rlck9iamVjdCh0aGlzKTtcblxuXHRcdC8vIE51bGxpZnkgYWxsIHBoeXNpY3MgZmllbGRzXG5cdFx0dGhpcy5oYXNQaHlzaWNzID0gZmFsc2U7XG5cdFx0dGhpcy5tb3ZpbmcgPSBmYWxzZTtcblx0XHR0aGlzLm9uR3JvdW5kID0gZmFsc2U7XG5cdFx0dGhpcy5vbldhbGwgPSBmYWxzZTtcblx0XHR0aGlzLm9uQ2VpbGluZyA9IGZhbHNlO1xuXHRcdHRoaXMuYWN0aXZlID0gZmFsc2U7XG5cdFx0dGhpcy5pc0NvbGxpZGFibGUgPSBmYWxzZTtcblx0XHR0aGlzLmlzU3RhdGljID0gZmFsc2U7XG5cdFx0dGhpcy5pc1RyaWdnZXIgPSBmYWxzZTtcblx0XHR0aGlzLnRyaWdnZXJNYXNrID0gMDtcblx0XHR0aGlzLnRyaWdnZXJFbnRlcnMgPSBudWxsO1xuXHRcdHRoaXMudHJpZ2dlckV4aXRzID0gbnVsbDtcblx0XHR0aGlzLl92ZWxvY2l0eSA9IFZlYzIuWkVSTztcblx0XHR0aGlzLnN3ZXB0UmVjdCA9IG51bGw7XG5cdFx0dGhpcy5jb2xsaWRlZFdpdGhUaWxlbWFwID0gZmFsc2U7XG5cdFx0dGhpcy5ncm91cCA9IC0xO1xuXHRcdHRoaXMuY29sbGlzaW9uU2hhcGUgPSBudWxsO1xuXHRcdHRoaXMuY29sbGlkZXJPZmZzZXQgPSBWZWMyLlpFUk87XG5cdFx0dGhpcy5zd2VwdFJlY3QgPSBudWxsO1xuXHR9XG5cblx0LyoqIERpc2FibGVzIHBoeXNpY3MgbW92ZW1lbnQgZm9yIHRoaXMgbm9kZSAqL1xuXHRmcmVlemUoKTogdm9pZCB7XG5cdFx0dGhpcy5mcm96ZW4gPSB0cnVlO1xuXHR9XG5cblx0LyoqIFJlZW5hYmxlcyBwaHlzaWNzIG1vdmVtZW50IGZvciB0aGlzIG5vZGUgKi9cblx0dW5mcmVlemUoKTogdm9pZCB7XG5cdFx0dGhpcy5mcm96ZW4gPSBmYWxzZTtcblx0fVxuXG4gICAgLyoqIFByZXZlbnRzIHRoaXMgb2JqZWN0IGZyb20gcGFydGljaXBhdGluZyBpbiBhbGwgY29sbGlzaW9ucyBhbmQgdHJpZ2dlcnMuIEl0IGNhbiBzdGlsbCBtb3ZlLiAqL1xuICAgIGRpc2FibGVQaHlzaWNzKCk6IHZvaWQge1xuXHRcdHRoaXMuYWN0aXZlID0gZmFsc2U7XG5cdH1cblxuICAgIC8qKiBFbmFibGVzIHRoaXMgb2JqZWN0IHRvIHBhcnRpY2lwYXRlIGluIGNvbGxpc2lvbnMgYW5kIHRyaWdnZXJzLiBUaGlzIGlzIG9ubHkgbmVjZXNzYXJ5IGlmIGRpc2FibGVQaHlzaWNzIHdhcyBjYWxsZWQgKi9cbiAgICBlbmFibGVQaHlzaWNzKCk6IHZvaWQge1xuXHRcdHRoaXMuYWN0aXZlID0gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBjb2xsaWRlciBmb3IgdGhpcyBHYW1lTm9kZVxuXHQgKiBAcGFyYW0gY29sbGlkZXIgVGhlIG5ldyBjb2xsaWRlciB0byB1c2Vcblx0ICovXG5cdHNldENvbGxpc2lvblNoYXBlKGNvbGxpZGVyOiBTaGFwZSk6IHZvaWQge1xuXHRcdHRoaXMuY29sbGlzaW9uU2hhcGUgPSBjb2xsaWRlcjtcblx0XHR0aGlzLmNvbGxpc2lvblNoYXBlLmNlbnRlci5jb3B5KHRoaXMucG9zaXRpb24pO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdC8qKlxuICAgICAqIFNldHMgdGhpcyBvYmplY3QgdG8gYmUgYSB0cmlnZ2VyIGZvciBhIHNwZWNpZmljIGdyb3VwXG4gICAgICogQHBhcmFtIGdyb3VwIFRoZSBuYW1lIG9mIHRoZSBncm91cCB0aGF0IGFjdGl2YXRlcyB0aGUgdHJpZ2dlclxuICAgICAqIEBwYXJhbSBvbkVudGVyIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kIHdoZW4gdGhpcyB0cmlnZ2VyIGlzIGFjdGl2YXRlZFxuICAgICAqIEBwYXJhbSBvbkV4aXQgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQgd2hlbiB0aGlzIHRyaWdnZXIgc3RvcHMgYmVpbmcgYWN0aXZhdGVkXG4gICAgICovXG4gICAgc2V0VHJpZ2dlcihncm91cDogc3RyaW5nLCBvbkVudGVyOiBzdHJpbmcsIG9uRXhpdDogc3RyaW5nKTogdm9pZCB7XG5cdFx0Ly8gTWFrZSB0aGlzIG9iamVjdCBhIHRyaWdnZXJcblx0XHR0aGlzLmlzVHJpZ2dlciA9IHRydWU7XG5cblx0XHQvLyBHZXQgdGhlIG51bWJlciBvZiB0aGUgcGh5c2ljcyBsYXllclxuXHRcdGxldCBsYXllck51bWJlciA9IHRoaXMuc2NlbmUuZ2V0UGh5c2ljc01hbmFnZXIoKS5nZXRHcm91cE51bWJlcihncm91cCk7XG5cblx0XHRpZihsYXllck51bWJlciA9PT0gMCl7XG5cdFx0XHRjb25zb2xlLndhcm4oYFRyaWdnZXIgZm9yIEdhbWVOb2RlICR7dGhpcy5pZH0gbm90IHNldCAtIGdyb3VwIFwiJHtncm91cH1cIiB3YXMgbm90IHJlY29nbml6ZWQgYnkgdGhlIHBoeXNpY3MgbWFuYWdlci5gKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBBZGQgdGhpcyB0byB0aGUgdHJpZ2dlciBtYXNrXG5cdFx0dGhpcy50cmlnZ2VyTWFzayB8PSBsYXllck51bWJlcjtcblxuXHRcdC8vIExheWVyIG51bWJlcnMgYXJlIGJpdHMsIHNvIGdldCB3aGljaCBiaXQgaXQgaXNcblx0XHRsZXQgaW5kZXggPSBNYXRoLmxvZzIobGF5ZXJOdW1iZXIpO1xuXG5cdFx0Ly8gU2V0IHRoZSBldmVudCBuYW1lc1xuXHRcdHRoaXMudHJpZ2dlckVudGVyc1tpbmRleF0gPSBvbkVudGVyO1xuXHRcdHRoaXMudHJpZ2dlckV4aXRzW2luZGV4XSA9IG9uRXhpdDtcblx0fTtcblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG5cdCAqIEBwYXJhbSBncm91cCBUaGUgcGh5c2ljcyBncm91cCB0aGlzIG5vZGUgc2hvdWxkIGJlbG9uZyB0b1xuXHQgKi9cblx0c2V0R3JvdXAoZ3JvdXA6IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMuc2NlbmUuZ2V0UGh5c2ljc01hbmFnZXIoKS5zZXRHcm91cCh0aGlzLCBncm91cCk7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW5lZFxuXHRnZXRMYXN0VmVsb2NpdHkoKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuX3ZlbG9jaXR5O1xuXHR9XG5cblx0LyotLS0tLS0tLS0tIEFDVE9SIC0tLS0tLS0tLS0qL1xuXHRnZXQgYWkoKTogQUkgfCBHb2FwQUkge1xuXHRcdHJldHVybiB0aGlzLl9haTtcblx0fVxuXG5cdHNldCBhaShhaTogQUkgfCBHb2FwQUkpIHtcblx0XHRpZighdGhpcy5fYWkpe1xuXHRcdFx0Ly8gSWYgd2UgaGF2ZW4ndCBiZWVuIHByZXZpb3VzbHkgaGFkIGFuIGFpLCByZWdpc3RlciB1cyB3aXRoIHRoZSBhaSBtYW5hZ2VyXG5cdFx0XHR0aGlzLnNjZW5lLmdldEFJTWFuYWdlcigpLnJlZ2lzdGVyQWN0b3IodGhpcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fYWkgPSBhaTtcblx0XHR0aGlzLmFpQWN0aXZlID0gdHJ1ZTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRhZGRBSTxUIGV4dGVuZHMgQUkgfCBHb2FwQUk+KGFpOiBzdHJpbmcgfCAobmV3ICgpID0+IFQpLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55PiwgdHlwZT86IG51bWJlcik6IHZvaWQge1xuXHRcdGlmKCF0aGlzLl9haSl7XG5cdFx0XHR0aGlzLnNjZW5lLmdldEFJTWFuYWdlcigpLnJlZ2lzdGVyQWN0b3IodGhpcyk7XG5cdFx0fVxuXG5cdFx0aWYodHlwZW9mIGFpID09PSBcInN0cmluZ1wiKXtcblx0XHRcdHRoaXMuX2FpID0gdGhpcy5zY2VuZS5nZXRBSU1hbmFnZXIoKS5nZW5lcmF0ZUFJKGFpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fYWkgPSBuZXcgYWkoKTtcblx0XHR9XG5cblx0XHQvLyBRdWVzdGlvbiwgaG93IG11Y2ggZG8gd2Ugd2FudCBkaWZmZXJlbnQgdHlwZSBvZiBBSSB0byBiZSBoYW5kbGVkIHRoZSBzYW1lLCBpLmUuIHNob3VsZCBHb2FwQUkgYW5kIEFJIHNpbWlsYXIgbWV0aG9kcyBhbmQgc2lnbmF0dXJlcyBmb3IgdGhlIHNha2Ugb2YgdW5pdHlcblx0XHR0aGlzLl9haS5pbml0aWFsaXplQUkodGhpcywgb3B0aW9ucyk7XG5cblx0XHR0aGlzLmFpQWN0aXZlID0gdHJ1ZTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRzZXRBSUFjdGl2ZShhY3RpdmU6IGJvb2xlYW4sIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHR0aGlzLmFpQWN0aXZlID0gYWN0aXZlO1xuXHRcdGlmKHRoaXMuYWlBY3RpdmUpe1xuXHRcdFx0dGhpcy5haS5hY3RpdmF0ZShvcHRpb25zKTtcblx0XHR9XG5cdH1cblxuXHQvKi0tLS0tLS0tLS0gVFdFRU5BQkxFIFBST1BFUlRJRVMgLS0tLS0tLS0tLSovXG5cdHNldCBwb3NpdGlvblgodmFsdWU6IG51bWJlcikge1xuXHRcdHRoaXMucG9zaXRpb24ueCA9IHZhbHVlO1xuXHR9XG5cblx0c2V0IHBvc2l0aW9uWSh2YWx1ZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5wb3NpdGlvbi55ID0gdmFsdWU7XG5cdH1cblxuXHRhYnN0cmFjdCBzZXQgc2NhbGVYKHZhbHVlOiBudW1iZXIpO1xuXG5cdGFic3RyYWN0IHNldCBzY2FsZVkodmFsdWU6IG51bWJlcik7XG5cblx0LyotLS0tLS0tLS0tIEdBTUUgTk9ERSAtLS0tLS0tLS0tKi9cblx0LyoqXG5cdCAqIFNldHMgdGhlIHNjZW5lIGZvciB0aGlzIG9iamVjdC5cblx0ICogQHBhcmFtIHNjZW5lIFRoZSBzY2VuZSB0aGlzIG9iamVjdCBiZWxvbmdzIHRvLlxuXHQgKi9cblx0c2V0U2NlbmUoc2NlbmU6IFNjZW5lKTogdm9pZCB7XG5cdFx0dGhpcy5zY2VuZSA9IHNjZW5lO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHNjZW5lIHRoaXMgb2JqZWN0IGlzIGluLiBcblx0ICogQHJldHVybnMgVGhlIHNjZW5lIHRoaXMgb2JqZWN0IGJlbG9uZ3MgdG9cblx0Ki9cblx0Z2V0U2NlbmUoKTogU2NlbmUge1xuXHRcdHJldHVybiB0aGlzLnNjZW5lO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGxheWVyIG9mIHRoaXMgb2JqZWN0LlxuXHQgKiBAcGFyYW0gbGF5ZXIgVGhlIGxheWVyIHRoaXMgb2JqZWN0IHdpbGwgYmUgb24uXG5cdCAqL1xuXHRzZXRMYXllcihsYXllcjogTGF5ZXIpOiB2b2lkIHtcblx0XHR0aGlzLmxheWVyID0gbGF5ZXI7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgbGF5ZXIgdGhpcyBvYmplY3QgaXMgb24uXG5cdCAqIEByZXR1cm5zIFRoaXMgbGF5ZXIgdGhpcyBvYmplY3QgaXMgb24uXG5cdCovXG5cdGdldExheWVyKCk6IExheWVyIHtcblx0XHRyZXR1cm4gdGhpcy5sYXllcjtcblx0fVxuXG5cdC8qKiBDYWxsZWQgaWYgdGhlIHBvc2l0aW9uIHZlY3RvciBpcyBtb2RpZmllZCBvciByZXBsYWNlZCAqL1xuXHRwcm90ZWN0ZWQgcG9zaXRpb25DaGFuZ2VkKCk6IHZvaWQge1xuXHRcdGlmKHRoaXMuY29sbGlzaW9uU2hhcGUpe1xuXHRcdFx0aWYodGhpcy5jb2xsaWRlck9mZnNldCl7XG5cdFx0XHRcdHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyID0gdGhpcy5wb3NpdGlvbi5jbG9uZSgpLmFkZCh0aGlzLmNvbGxpZGVyT2Zmc2V0KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyID0gdGhpcy5wb3NpdGlvbi5jbG9uZSgpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoaXMgR2FtZU5vZGVcblx0ICogQHBhcmFtIGRlbHRhVCBUaGUgdGltZXN0ZXAgb2YgdGhlIHVwZGF0ZS5cblx0ICovXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIERlZmVyIGV2ZW50IGhhbmRsaW5nIHRvIEFJLlxuXHRcdHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuXHRcdFx0dGhpcy5fYWkuaGFuZGxlRXZlbnQodGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKSk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGRlYnVnUmVuZGVyKCk6IHZvaWQge1xuXHRcdC8vIERyYXcgdGhlIHBvc2l0aW9uIG9mIHRoaXMgR2FtZU5vZGVcblx0XHREZWJ1Zy5kcmF3UG9pbnQodGhpcy5yZWxhdGl2ZVBvc2l0aW9uLCBDb2xvci5CTFVFKTtcblxuXHRcdC8vIElmIHZlbG9jaXR5IGlzIG5vdCB6ZXJvLCBkcmF3IGEgdmVjdG9yIGZvciBpdFxuXHRcdGlmKHRoaXMuX3ZlbG9jaXR5ICYmICF0aGlzLl92ZWxvY2l0eS5pc1plcm8oKSl7XG5cdFx0XHREZWJ1Zy5kcmF3UmF5KHRoaXMucmVsYXRpdmVQb3NpdGlvbiwgdGhpcy5fdmVsb2NpdHkuY2xvbmUoKS5zY2FsZVRvKDIwKS5hZGQodGhpcy5yZWxhdGl2ZVBvc2l0aW9uKSwgQ29sb3IuQkxVRSk7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhpcyBoYXMgYSBjb2xsaWRlciwgZHJhdyBpdFxuXHRcdGlmKHRoaXMuY29sbGlzaW9uU2hhcGUpe1xuXHRcdFx0bGV0IGNvbG9yID0gdGhpcy5pc0NvbGxpZGluZyA/IENvbG9yLlJFRCA6IENvbG9yLkdSRUVOO1xuXG5cdFx0XHRpZih0aGlzLmlzVHJpZ2dlcil7XG5cdFx0XHRcdGNvbG9yID0gQ29sb3IuTUFHRU5UQTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0Y29sb3IuYSA9IDAuMjtcblxuXHRcdFx0aWYodGhpcy5jb2xsaXNpb25TaGFwZSBpbnN0YW5jZW9mIEFBQkIpe1xuXHRcdFx0XHREZWJ1Zy5kcmF3Qm94KHRoaXMuaW5SZWxhdGl2ZUNvb3JkaW5hdGVzKHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyKSwgdGhpcy5jb2xsaXNpb25TaGFwZS5oYWxmU2l6ZS5zY2FsZWQodGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKSksIHRydWUsIGNvbG9yKTtcblx0XHRcdH0gZWxzZSBpZih0aGlzLmNvbGxpc2lvblNoYXBlIGluc3RhbmNlb2YgQ2lyY2xlKXtcblx0XHRcdFx0RGVidWcuZHJhd0NpcmNsZSh0aGlzLmluUmVsYXRpdmVDb29yZGluYXRlcyh0aGlzLmNvbGxpc2lvblNoYXBlLmNlbnRlciksIHRoaXMuY29sbGlzaW9uU2hhcGUuaHcqdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKSwgdHJ1ZSwgY29sb3IpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgZW51bSBUd2VlbmFibGVQcm9wZXJ0aWVze1xuXHRwb3NYID0gXCJwb3NpdGlvblhcIixcblx0cG9zWSA9IFwicG9zaXRpb25ZXCIsXG5cdHNjYWxlWCA9IFwic2NhbGVYXCIsXG5cdHNjYWxlWSA9IFwic2NhbGVZXCIsXG5cdHJvdGF0aW9uID0gXCJyb3RhdGlvblwiLFxuXHRhbHBoYSA9IFwiYWxwaGFcIlxufSIsImltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuL0NhbnZhc05vZGVcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcblxuLyoqXG4gKiBUaGUgcmVwcmVzZW50YXRpb24gb2YgYSBnYW1lIG9iamVjdCB0aGF0IGRvZXNuJ3QgcmVseSBvbiBhbnkgcmVzb3VyY2VzIHRvIHJlbmRlciAtIGl0IGlzIGRyYXduIHRvIHRoZSBzY3JlZW4gYnkgdGhlIGNhbnZhc1xuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBHcmFwaGljIGV4dGVuZHMgQ2FudmFzTm9kZSB7XG4gICAgLyoqIFRoZSBjb2xvciBvZiB0aGUgR3JhcGhpYyAqL1xuICAgIGNvbG9yOiBDb2xvcjtcblxuICAgIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuY29sb3IgPSBDb2xvci5SRUQ7XG4gICAgfVxuXG4gICAgZ2V0IGFscGhhKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMuY29sb3IuYTtcblx0fVxuXG5cdHNldCBhbHBoYShhOiBudW1iZXIpIHtcblx0XHR0aGlzLmNvbG9yLmEgPSBhO1xuXHR9XG5cbiAgICAvLyBAZGVwcmVjYXRlZFxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGNvbG9yIG9mIHRoZSBHcmFwaGljLiBERVBSRUNBVEVEXG4gICAgICogQHBhcmFtIGNvbG9yIFRoZSBuZXcgY29sb3Igb2YgdGhlIEdyYXBoaWMuXG4gICAgICovXG4gICAgc2V0Q29sb3IoY29sb3I6IENvbG9yKXtcbiAgICAgICAgdGhpcy5jb2xvciA9IGNvbG9yO1xuICAgIH1cblxuICAgIHNldCBjb2xvclIocjogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5jb2xvci5yID0gcjtcbiAgICB9XG5cbiAgICBnZXQgY29sb3JSKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbG9yLnI7XG4gICAgfVxuXG4gICAgc2V0IGNvbG9yRyhnOiBudW1iZXIpe1xuICAgICAgICB0aGlzLmNvbG9yLmcgPSBnO1xuICAgIH1cblxuICAgIGdldCBjb2xvckcoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sb3IuZztcbiAgICB9XG5cbiAgICBzZXQgY29sb3JCKGI6IG51bWJlcil7XG4gICAgICAgIHRoaXMuY29sb3IuYiA9IGI7XG4gICAgfVxuXG4gICAgZ2V0IGNvbG9yQigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xvci5iO1xuICAgIH1cbn0iLCJleHBvcnQgZW51bSBHcmFwaGljVHlwZSB7XG5cdFBPSU5UID0gXCJQT0lOVFwiLFxuXHRSRUNUID0gXCJSRUNUXCIsXG5cdExJTkUgPSBcIkxJTkVcIixcblx0UEFSVElDTEUgPSBcIlBBUlRJQ0xFXCJcbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9HcmFwaGljXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpbmUgZXh0ZW5kcyBHcmFwaGljIHtcbiAgICBwcm90ZWN0ZWQgX2VuZDogVmVjMjtcbiAgICB0aGlja25lc3M6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHN0YXJ0OiBWZWMyLCBlbmQ6IFZlYzIpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnN0YXJ0ID0gc3RhcnQ7XG4gICAgICAgIHRoaXMuZW5kID0gZW5kO1xuICAgICAgICB0aGlzLnRoaWNrbmVzcyA9IDI7XG5cbiAgICAgICAgLy8gRG9lcyB0aGlzIHJlYWxseSBoYXZlIGEgbWVhbmluZyBmb3IgbGluZXM/XG4gICAgICAgIHRoaXMuc2l6ZS5zZXQoNSwgNSk7XG4gICAgfVxuXG4gICAgc2V0IHN0YXJ0KHBvczogVmVjMil7XG4gICAgICAgIHRoaXMucG9zaXRpb24gPSBwb3M7XG4gICAgfVxuXG4gICAgZ2V0IHN0YXJ0KCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbjtcbiAgICB9XG5cbiAgICBzZXQgZW5kKHBvczogVmVjMil7XG4gICAgICAgIHRoaXMuX2VuZCA9IHBvcztcbiAgICB9XG5cbiAgICBnZXQgZW5kKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5kO1xuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi9Qb2ludFwiO1xuXG4vKipcbiAqIC0gUG9zaXRpb24gWFxuLSBWZWxvY2l0eSAoc3BlZWQgYW5kIGRpcmVjdGlvbikgWFxuLSBDb2xvciBYXG4tIExpZmV0aW1lIFxuLSBBZ2UgY2FuIGJlIGhhbmRsZWQgYXMgbGlmZXRpbWVcbi0gU2hhcGUgWFxuLSBTaXplIFhcbi0gVHJhbnNwYXJlbmN5IFhcbiAqL1xuXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBhcnRpY2xlIGV4dGVuZHMgUG9pbnQge1xuICAgIGFnZTogbnVtYmVyO1xuXG4gICAgaW5Vc2U6IGJvb2xlYW47XG5cbiAgICB2ZWw6IFZlYzI7XG5cbiAgICBtYXNzOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMiwgc2l6ZTogVmVjMiwgbWFzczogbnVtYmVyKSB7XG4gICAgICAgIC8vIEFyZSB3ZSBtYWtpbmcgdGhpcyBhIGNpcmNsZT9cbiAgICAgICAgc3VwZXIocG9zaXRpb24pO1xuICAgICAgICB0aGlzLmluVXNlID0gZmFsc2U7XG4gICAgICAgIHRoaXMubWFzcyA9IG1hc3M7XG4gICAgfVxuXG4gICAgc2V0UGFydGljbGVBY3RpdmUobGlmZXRpbWU6IG51bWJlciwgcG9zaXRpb246IFZlYzIpIHtcbiAgICAgICAgdGhpcy5hZ2UgPSBsaWZldGltZTtcbiAgICAgICAgdGhpcy5pblVzZSA9IHRydWU7XG4gICAgICAgIHRoaXMudmlzaWJsZSA9IHRydWU7XG4gICAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcbiAgICB9XG5cbiAgICBkZWNyZW1lbnRBZ2UoZGVjYXk6IG51bWJlcikge1xuICAgICAgICB0aGlzLmFnZSAtPSBkZWNheTtcbiAgICB9XG5cbiAgICBzZXRQYXJ0aWNsZUluYWN0aXZlKCl7XG4gICAgICAgIHRoaXMuaW5Vc2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy52aXNpYmxlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgc2V0IHZlbFkoeTogbnVtYmVyKXtcbiAgICAgICAgdGhpcy52ZWwueSA9IHk7XG4gICAgfVxuXG4gICAgZ2V0IHZlbFkoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmVsLnk7XG4gICAgfVxuXG5cbn0iLCJpbXBvcnQgR3JhcGhpYyBmcm9tIFwiLi4vR3JhcGhpY1wiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5cbi8qKiBBIGJhc2ljIHBvaW50IHRvIGJlIGRyYXduIG9uIHRoZSBzY3JlZW4uICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQb2ludCBleHRlbmRzIEdyYXBoaWMge1xuXG4gICAgY29uc3RydWN0b3IocG9zaXRpb246IFZlYzIpIHtcbiAgICAgICAgLy8gQXJlIHdlIG1ha2luZyB0aGlzIGEgY2lyY2xlP1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnBvc2l0aW9uID0gcG9zaXRpb247XG4gICAgICAgIHRoaXMuc2l6ZS5zZXQoNSwgNSk7XG4gICAgfVxufSIsImltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9HcmFwaGljXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vVXRpbHMvQ29sb3JcIjtcblxuLyoqIEEgYmFzaWMgcmVjdGFuZ2xlIHRvIGJlIGRyYXduIG9uIHRoZSBzY3JlZW4uICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWN0IGV4dGVuZHMgR3JhcGhpYyB7XG5cbiAgICAvKiogVGhlIGJvcmRlciBjb2xvciBvZiB0aGUgUmVjdCAqL1xuICAgIGJvcmRlckNvbG9yOiBDb2xvcjtcblxuICAgIC8qKiBUaGUgd2lkdGggb2YgdGhlIGJvcmRlciAqL1xuICAgIGJvcmRlcldpZHRoOiBudW1iZXI7XG5cbiAgICBmaWxsV2lkdGg6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCBzaXplOiBWZWMyKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuICAgICAgICB0aGlzLnNpemUgPSBzaXplO1xuICAgICAgICB0aGlzLmJvcmRlckNvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHRoaXMuYm9yZGVyV2lkdGggPSAwO1xuICAgICAgICB0aGlzLmZpbGxXaWR0aCA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYm9yZGVyIGNvbG9yIG9mIHRoaXMgcmVjdGFuZ2xlXG4gICAgICogQHBhcmFtIGNvbG9yIFRoZSBib3JkZXIgY29sb3JcbiAgICAgKi9cbiAgICBzZXRCb3JkZXJDb2xvcihjb2xvcjogQ29sb3IpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5ib3JkZXJDb2xvciA9IGNvbG9yO1xuICAgIH1cblxuICAgIC8vIEBkZXByZWNhdGVkXG4gICAgZ2V0Qm9yZGVyQ29sb3IoKTogQ29sb3Ige1xuICAgICAgICByZXR1cm4gdGhpcy5ib3JkZXJDb2xvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBib3JkZXIgd2lkdGggb2YgdGhpcyByZWN0YW5nbGVcbiAgICAgKiBAcGFyYW0gd2lkdGggVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUgaW4gcGl4ZWxzXG4gICAgICovXG4gICAgc2V0Qm9yZGVyV2lkdGgod2lkdGg6IG51bWJlcil7XG4gICAgICAgIHRoaXMuYm9yZGVyV2lkdGggPSB3aWR0aDtcbiAgICB9XG5cbiAgICBnZXRCb3JkZXJXaWR0aCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5ib3JkZXJXaWR0aDtcbiAgICB9XG59IiwiaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi9TcHJpdGVcIjtcbmltcG9ydCBBbmltYXRpb25NYW5hZ2VyIGZyb20gXCIuLi8uLi9SZW5kZXJpbmcvQW5pbWF0aW9ucy9BbmltYXRpb25NYW5hZ2VyXCI7XG5pbXBvcnQgU3ByaXRlc2hlZXQgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9TcHJpdGVzaGVldFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5cbi8qKiBBbiBzcHJpdGUgd2l0aCBzcGVjaWZpZWQgYW5pbWF0aW9uIGZyYW1lcy4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFuaW1hdGVkU3ByaXRlIGV4dGVuZHMgU3ByaXRlIHtcbiAgICAvKiogVGhlIG51bWJlciBvZiBjb2x1bW5zIGluIHRoaXMgc3ByaXRlIHNoZWV0ICovXG4gICAgcHJvdGVjdGVkIG51bUNvbHM6IG51bWJlcjtcblxuICAgIGdldCBjb2xzKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLm51bUNvbHM7XG4gICAgfVxuXG4gICAgLyoqIFRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGlzIHNwcml0ZSBzaGVldCAqL1xuICAgIHByb3RlY3RlZCBudW1Sb3dzOiBudW1iZXI7XG5cbiAgICBnZXQgcm93cygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5udW1Sb3dzO1xuICAgIH1cblxuICAgIC8qKiBUaGUgYW5pbWF0aW9uTWFuYWdlciBmb3IgdGhpcyBzcHJpdGUgKi9cbiAgICBhbmltYXRpb246IEFuaW1hdGlvbk1hbmFnZXI7XG5cbiAgICBjb25zdHJ1Y3RvcihzcHJpdGVzaGVldDogU3ByaXRlc2hlZXQpe1xuICAgICAgICBzdXBlcihzcHJpdGVzaGVldC5uYW1lKTtcbiAgICAgICAgdGhpcy5udW1Db2xzID0gc3ByaXRlc2hlZXQuY29sdW1ucztcbiAgICAgICAgdGhpcy5udW1Sb3dzID0gc3ByaXRlc2hlZXQucm93cztcblxuICAgICAgICAvLyBTZXQgdGhlIHNpemUgb2YgdGhlIHNwcml0ZSB0byB0aGUgc3ByaXRlIHNpemUgc3BlY2lmaWVkIGJ5IHRoZSBzcHJpdGVzaGVldFxuICAgICAgICB0aGlzLnNpemUuc2V0KHNwcml0ZXNoZWV0LnNwcml0ZVdpZHRoLCBzcHJpdGVzaGVldC5zcHJpdGVIZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuYW5pbWF0aW9uID0gbmV3IEFuaW1hdGlvbk1hbmFnZXIodGhpcyk7XG5cbiAgICAgICAgLy8gQWRkIHRoZSBhbmltYXRpb25zIHRvIHRoZSBhbmltYXRlZCBzcHJpdGVcbiAgICAgICAgZm9yKGxldCBhbmltYXRpb24gb2Ygc3ByaXRlc2hlZXQuYW5pbWF0aW9ucyl7XG4gICAgICAgICAgICB0aGlzLmFuaW1hdGlvbi5hZGQoYW5pbWF0aW9uLm5hbWUsIGFuaW1hdGlvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbWFnZSBvZmZzZXQgZm9yIHRoZSBjdXJyZW50IGluZGV4IG9mIGFuaW1hdGlvblxuICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggd2UncmUgYXQgaW4gdGhlIGFuaW1hdGlvblxuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSBpbWFnZSBvZmZzZXRcbiAgICAgKi9cbiAgICBnZXRBbmltYXRpb25PZmZzZXQoaW5kZXg6IG51bWJlcik6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIoKGluZGV4ICUgdGhpcy5udW1Db2xzKSAqIHRoaXMuc2l6ZS54LCBNYXRoLmZsb29yKGluZGV4IC8gdGhpcy5udW1Db2xzKSAqIHRoaXMuc2l6ZS55KTtcbiAgICB9XG59IiwiaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL0NhbnZhc05vZGVcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhIHNwcml0ZSAtIGFuIGluLWdhbWUgaW1hZ2VcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3ByaXRlIGV4dGVuZHMgQ2FudmFzTm9kZSB7XG4gICAgLyoqIFRoZSBpZCBvZiB0aGUgaW1hZ2UgZnJvbSB0aGUgcmVzb3VyY2VNYW5hZ2VyICovXG4gICAgaW1hZ2VJZDogc3RyaW5nO1xuICAgIC8qKiBUaGUgb2Zmc2V0IG9mIHRoZSBzcHJpdGUgaW4gYW4gYXRsYXMgaW1hZ2UgKi9cbiAgICBpbWFnZU9mZnNldDogVmVjMjtcbiAgICAvKiogV2hldGhlciBvciBub3QgdGhlIHgtYXhpcyBzaG91bGQgYmUgaW52ZXJ0ZWQgb24gcmVuZGVyICovXG4gICAgaW52ZXJ0WDogYm9vbGVhbjtcbiAgICAvKiogV2hldGhlciBvciBub3QgdGhlIHktYXhpcyBzaG91bGQgYmUgaW52ZXJ0ZWQgb24gcmVuZGVyICovXG4gICAgaW52ZXJ0WTogYm9vbGVhbjtcblxuICAgIGNvbnN0cnVjdG9yKGltYWdlSWQ6IHN0cmluZyl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuaW1hZ2VJZCA9IGltYWdlSWQ7XG4gICAgICAgIGxldCBpbWFnZSA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpLmdldEltYWdlKHRoaXMuaW1hZ2VJZCk7XG4gICAgICAgIHRoaXMuc2l6ZSA9IG5ldyBWZWMyKGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQpO1xuICAgICAgICB0aGlzLmltYWdlT2Zmc2V0ID0gVmVjMi5aRVJPO1xuICAgICAgICB0aGlzLmludmVydFggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pbnZlcnRZID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgb2Zmc2V0IG9mIHRoZSBzcHJpdGUgZnJvbSAoMCwgMCkgaW4gdGhlIGltYWdlJ3MgY29vcmRpbmF0ZXNcbiAgICAgKiBAcGFyYW0gb2Zmc2V0IFRoZSBvZmZzZXQgb2YgdGhlIHNwcml0ZSBmcm9tICgwLCAwKSBpbiBpbWFnZSBjb29yZGluYXRlc1xuICAgICAqL1xuICAgIHNldEltYWdlT2Zmc2V0KG9mZnNldDogVmVjMik6IHZvaWQge1xuICAgICAgICB0aGlzLmltYWdlT2Zmc2V0ID0gb2Zmc2V0O1xuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBUaWxlc2V0IGZyb20gXCIuLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZXNldFwiO1xuaW1wb3J0IHsgVGlsZWRUaWxlbWFwRGF0YSwgVGlsZWRMYXllckRhdGEgfSBmcm9tIFwiLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiXG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi9DYW52YXNOb2RlXCI7XG5pbXBvcnQgUGh5c2ljc01hbmFnZXIgZnJvbSBcIi4uL1BoeXNpY3MvUGh5c2ljc01hbmFnZXJcIjtcblxuLyoqXG4gKiBUaGUgcmVwcmVzZW50YXRpb24gb2YgYSB0aWxlbWFwIC0gdGhpcyBjYW4gY29uc2lzdCBvZiBhIGNvbWJpbmF0aW9uIG9mIHRpbGVzZXRzIGluIG9uZSBsYXllclxuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBUaWxlbWFwIGV4dGVuZHMgQ2FudmFzTm9kZSB7XG4gICAgLyoqIEFuIGFycmF5IG9mIHRoZSB0aWxlc2V0cyB0aGF0IHRoaXMgdGlsZW1hcCB1c2VzICovXG4gICAgcHJvdGVjdGVkIHRpbGVzZXRzOiBBcnJheTxUaWxlc2V0PjtcblxuICAgIC8qKiBUaGUgc2l6ZSBvZiBhIHRpbGUgaW4gdGhpcyB0aWxlbWFwICovXG4gICAgcHJvdGVjdGVkIHRpbGVTaXplOiBWZWMyO1xuXG4gICAgLyoqIEFuIGFycmF5IG9mIHRpbGUgZGF0YSAqL1xuICAgIHByb3RlY3RlZCBkYXRhOiBBcnJheTxudW1iZXI+O1xuXG4gICAgLyoqIEFuIGFycmF5IG9mIHRpbGUgY29sbGlzaW9uIGRhdGEgKi9cbiAgICBwcm90ZWN0ZWQgY29sbGlzaW9uTWFwOiBBcnJheTxib29sZWFuPjtcblxuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgdGlsZW1hcCAqL1xuICAgIG5hbWU6IHN0cmluZztcblxuICAgIC8vIFRPRE86IE1ha2UgdGhpcyBubyBsb25nZXIgYmUgc3BlY2lmaWMgdG8gVGlsZWRcbiAgICBjb25zdHJ1Y3Rvcih0aWxlbWFwRGF0YTogVGlsZWRUaWxlbWFwRGF0YSwgbGF5ZXI6IFRpbGVkTGF5ZXJEYXRhLCB0aWxlc2V0czogQXJyYXk8VGlsZXNldD4sIHNjYWxlOiBWZWMyKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMudGlsZXNldHMgPSB0aWxlc2V0cztcbiAgICAgICAgdGhpcy50aWxlU2l6ZSA9IG5ldyBWZWMyKDAsIDApO1xuICAgICAgICB0aGlzLm5hbWUgPSBsYXllci5uYW1lO1xuXG4gICAgICAgIGxldCB0aWxlY291bnQgPSAwO1xuICAgICAgICBmb3IobGV0IHRpbGVzZXQgb2YgdGlsZXNldHMpe1xuICAgICAgICAgICAgdGlsZWNvdW50ICs9IHRpbGVzZXQuZ2V0VGlsZUNvdW50KCkgKyAxO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb2xsaXNpb25NYXAgPSBuZXcgQXJyYXkodGlsZWNvdW50KTtcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHRoaXMuY29sbGlzaW9uTWFwLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIHRoaXMuY29sbGlzaW9uTWFwW2ldID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZlciBwYXJzaW5nIG9mIHRoZSBkYXRhIHRvIGNoaWxkIGNsYXNzZXMgLSB0aGlzIGFsbG93cyBmb3IgaXNvbWV0cmljIHZzLiBvcnRob2dyYXBoaWMgdGlsZW1hcHMgYW5kIGhhbmRsaW5nIG9mIFRpbGVkIGRhdGEgb3Igb3RoZXIgZGF0YVxuICAgICAgICB0aGlzLnBhcnNlVGlsZW1hcERhdGEodGlsZW1hcERhdGEsIGxheWVyKTtcbiAgICAgICAgdGhpcy5zY2FsZS5zZXQoc2NhbGUueCwgc2NhbGUueSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSBvZiB0aGUgdGlsZXNldHMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGlsZW1hcFxuICAgICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIGFsbCBvZiB0aGUgdGlsZXNldHMgYXNzb2NhaXRlZCB3aXRoIHRoaXMgdGlsZW1hcC5cbiAgICAgKi9cbiAgICBnZXRUaWxlc2V0cygpOiBUaWxlc2V0W10ge1xuICAgICAgICByZXR1cm4gdGhpcy50aWxlc2V0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzaXplIG9mIHRpbGVzIGluIHRoaXMgdGlsZW1hcCBhcyB0aGV5IGFwcGVhciBpbiB0aGUgZ2FtZSB3b3JsZCBhZnRlciBzY2FsaW5nXG4gICAgICogQHJldHVybnMgQSB2ZWN0b3IgY29udGFpbmluZyB0aGUgc2l6ZSBvZiB0aWxlcyBpbiB0aGlzIHRpbGVtYXAgYXMgdGhleSBhcHBlYXIgaW4gdGhlIGdhbWUgd29ybGQgYWZ0ZXIgc2NhbGluZy5cbiAgICAgKi9cbiAgICBnZXRUaWxlU2l6ZSgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemUuc2NhbGVkKHRoaXMuc2NhbGUueCwgdGhpcy5zY2FsZS55KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB0aWxlIHNpemUgdGFraW5nIHpvb20gaW50byBhY2NvdW50XG4gICAgICogQHJldHVybnMgVGhlIHRpbGUgc2l6ZSB3aXRoIHpvb21cbiAgICAqL1xuICAgIGdldFRpbGVTaXplV2l0aFpvb20oKTogVmVjMiB7XG4gICAgICAgIGxldCB6b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRUaWxlU2l6ZSgpLnNjYWxlKHpvb20pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgdGhpcyB0aWxlbWFwIHRvIHRoZSBwaHlzaWNzIHN5c3RlbVxuICAgICovXG4gICAgYWRkUGh5c2ljcygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5oYXNQaHlzaWNzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5hY3RpdmUgPSB0cnVlO1xuICAgICAgICB0aGlzLmdyb3VwID0gLTE7XG4gICAgICAgIHRoaXMuc2NlbmUuZ2V0UGh5c2ljc01hbmFnZXIoKS5yZWdpc3RlclRpbGVtYXAodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdmFsdWUgb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBwb3NpdGlvblxuICAgICAqIEBwYXJhbSB3b3JsZENvb3JkcyBUaGUgcG9zaXRpb24gaW4gd29ybGQgY29vcmRpbmF0ZXNcbiAgICAgKiBAcmV0dXJucyBBIG51bWJlciB0aGF0IHJlcHJlc2VudHMgdGhlIGRhdGEgdmFsdWUgb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCB3b3JsZCBwb3NpdGlvbi5cbiAgICAgKi9cbiAgICBhYnN0cmFjdCBnZXRUaWxlQXRXb3JsZFBvc2l0aW9uKHdvcmxkQ29vcmRzOiBWZWMyKTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgd29ybGQgcG9zaXRpb24gb2YgdGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4XG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZSBpbiB0aGUgdGlsZURhdGEgYXJyYXlcbiAgICAgKiBAcmV0dXJucyBUaGUgd29ybGQgcG9zaXRpb24gb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqL1xuICAgIGFic3RyYWN0IGdldFRpbGVXb3JsZFBvc2l0aW9uKGluZGV4OiBudW1iZXIpOiBWZWMyO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdmFsdWUgb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGUgaW4gdGhlIHRpbGVEYXRhIGFycmF5XG4gICAgICogQHJldHVybnMgVGhlIHZhbHVlIG9mIHRoZSB0aWxlIGluIHRoZSB0aWxlRGF0YSBhcnJheVxuICAgICAqL1xuICAgIGFic3RyYWN0IGdldFRpbGUoaW5kZXg6IG51bWJlcik6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGVcbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgbmV3IGRhdGEgdmFsdWUgb2YgdGhlIHRpbGVcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBzZXRUaWxlKGluZGV4OiBudW1iZXIsIHR5cGU6IG51bWJlcik6IHZvaWQ7XG5cbiAgICAvLyBUT0RPOiBUaGlzIHNob3VsZG4ndCB1c2UgdGlsZWQgZGF0YSBzcGVjaWZpY2FsbHkgLSBpdCBzaG91bGQgYmUgbW9yZSBnZW5lcmFsXG4gICAgLyoqXG4gICAgICogU2V0cyB1cCB0aGUgdGlsZXNldCB1c2luZyB0aGUgZGF0YSBsb2FkZWQgZnJvbSBmaWxlXG4gICAgICogQHBhcmFtIHRpbGVtYXBEYXRhIFRoZSB0aWxlbWFwIGRhdGEgZnJvbSBmaWxlXG4gICAgICogQHBhcmFtIGxheWVyIFRoZSBsYXllciBkYXRhIGZyb20gZmlsZVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBwYXJzZVRpbGVtYXBEYXRhKHRpbGVtYXBEYXRhOiBUaWxlZFRpbGVtYXBEYXRhLCBsYXllcjogVGlsZWRMYXllckRhdGEpOiB2b2lkO1xufSIsImltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi9UaWxlbWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCB7IFRpbGVkVGlsZW1hcERhdGEsIFRpbGVkTGF5ZXJEYXRhIH0gZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vVXRpbHMvQ29sb3JcIjtcblxuLyoqXG4gKiBUaGUgcmVwcmVzZW50YXRpb24gb2YgYW4gb3J0aG9nb25hbCB0aWxlbWFwIC0gaS5lLiBhIHRvcCBkb3duIG9yIHBsYXRmb3JtZXIgdGlsZW1hcFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBPcnRob2dvbmFsVGlsZW1hcCBleHRlbmRzIFRpbGVtYXAge1xuICAgIC8qKiBUaGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIHRpbGVtYXAgKi9cbiAgICBwcm90ZWN0ZWQgbnVtQ29sczogbnVtYmVyO1xuICAgIC8qKiBUaGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIHRpbGVtYXAgKi9cbiAgICBwcm90ZWN0ZWQgbnVtUm93czogbnVtYmVyO1xuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHBhcnNlVGlsZW1hcERhdGEodGlsZW1hcERhdGE6IFRpbGVkVGlsZW1hcERhdGEsIGxheWVyOiBUaWxlZExheWVyRGF0YSk6IHZvaWQge1xuICAgICAgICAvLyBUaGUgc2l6ZSBvZiB0aGUgdGlsZW1hcCBpbiBsb2NhbCBzcGFjZVxuICAgICAgICB0aGlzLm51bUNvbHMgPSB0aWxlbWFwRGF0YS53aWR0aDtcbiAgICAgICAgdGhpcy5udW1Sb3dzID0gdGlsZW1hcERhdGEuaGVpZ2h0O1xuXG4gICAgICAgIC8vIFRoZSBzaXplIG9mIHRpbGVzXG4gICAgICAgIHRoaXMudGlsZVNpemUuc2V0KHRpbGVtYXBEYXRhLnRpbGV3aWR0aCwgdGlsZW1hcERhdGEudGlsZWhlaWdodCk7XG5cbiAgICAgICAgLy8gVGhlIHNpemUgb2YgdGhlIHRpbGVtYXAgb24gdGhlIGNhbnZhc1xuICAgICAgICB0aGlzLnNpemUuc2V0KHRoaXMubnVtQ29scyAqIHRoaXMudGlsZVNpemUueCwgdGhpcy5udW1Sb3dzICogdGhpcy50aWxlU2l6ZS55KTtcbiAgICAgICAgdGhpcy5wb3NpdGlvbi5jb3B5KHRoaXMuc2l6ZS5zY2FsZWQoMC41KSk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGxheWVyLmRhdGE7XG4gICAgICAgIHRoaXMudmlzaWJsZSA9IGxheWVyLnZpc2libGU7XG5cbiAgICAgICAgLy8gV2hldGhlciB0aGUgdGlsZW1hcCBpcyBjb2xsaWRhYmxlIG9yIG5vdFxuICAgICAgICB0aGlzLmlzQ29sbGlkYWJsZSA9IGZhbHNlO1xuICAgICAgICBpZihsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgIGZvcihsZXQgaXRlbSBvZiBsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICBpZihpdGVtLm5hbWUgPT09IFwiQ29sbGlkYWJsZVwiKXtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0NvbGxpZGFibGUgPSBpdGVtLnZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNldCBhbGwgdGlsZXMgYmVzaWRlcyBcImVtcHR5OiAwXCIgdG8gYmUgY29sbGlkYWJsZVxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAxOyBpIDwgdGhpcy5jb2xsaXNpb25NYXAubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2xsaXNpb25NYXBbaV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZGltZW5zaW9ucyBvZiB0aGUgdGlsZW1hcFxuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSBudW1iZXIgb2YgY29sdW1ucyBhbmQgdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSB0aWxlbWFwLlxuICAgICAqL1xuICAgIGdldERpbWVuc2lvbnMoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLm51bUNvbHMsIHRoaXMubnVtUm93cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIHdvcmxkIHBvc2l0aW9uXG4gICAgICogQHBhcmFtIHdvcmxkQ29vcmRzIFRoZSBjb29yZGluYXRlcyBpbiB3b3JsZCBzcGFjZVxuICAgICAqIEByZXR1cm5zIFRoZSBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlXG4gICAgICovXG4gICAgZ2V0VGlsZUF0V29ybGRQb3NpdGlvbih3b3JsZENvb3JkczogVmVjMik6IG51bWJlciB7XG4gICAgICAgIGxldCBsb2NhbENvb3JkcyA9IHRoaXMuZ2V0Q29sUm93QXQod29ybGRDb29yZHMpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRUaWxlQXRSb3dDb2wobG9jYWxDb29yZHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIHJvdyBhbmQgY29sdW1uXG4gICAgICogQHBhcmFtIHJvd0NvbCBUaGUgY29vcmRpbmF0ZXMgaW4gdGlsZW1hcCBzcGFjZVxuICAgICAqIEByZXR1cm5zIFRoZSBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlXG4gICAgICovXG4gICAgZ2V0VGlsZUF0Um93Q29sKHJvd0NvbDogVmVjMik6IG51bWJlciB7XG4gICAgICAgIGlmKHJvd0NvbC54IDwgMCB8fCByb3dDb2wueCA+PSB0aGlzLm51bUNvbHMgfHwgcm93Q29sLnkgPCAwIHx8IHJvd0NvbC55ID49IHRoaXMubnVtUm93cyl7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5kYXRhW3Jvd0NvbC55ICogdGhpcy5udW1Db2xzICsgcm93Q29sLnhdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHdvcmxkIHBvc2l0aW9uIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlXG4gICAgICogQHJldHVybnMgQSBWZWMyIGNvbnRhaW5pbmcgdGhlIHdvcmxkIHBvc2l0aW9uIG9mIHRoZSB0aWxlXG4gICAgICovXG4gICAgZ2V0VGlsZVdvcmxkUG9zaXRpb24oaW5kZXg6IG51bWJlcik6IFZlYzIge1xuICAgICAgICAvLyBHZXQgdGhlIGxvY2FsIHBvc2l0aW9uXG4gICAgICAgIGxldCBjb2wgPSBpbmRleCAlIHRoaXMubnVtQ29scztcbiAgICAgICAgbGV0IHJvdyA9IE1hdGguZmxvb3IoaW5kZXggLyB0aGlzLm51bUNvbHMpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgd29ybGQgcG9zaXRpb25cbiAgICAgICAgbGV0IHggPSBjb2wgKiB0aGlzLnRpbGVTaXplLnggKiB0aGlzLnNjYWxlLng7XG4gICAgICAgIGxldCB5ID0gcm93ICogdGhpcy50aWxlU2l6ZS55ICogdGhpcy5zY2FsZS55O1xuXG4gICAgICAgIHJldHVybiBuZXcgVmVjMih4LCB5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlXG4gICAgICogQHJldHVybnMgVGhlIGRhdGEgdmFsdWUgb2YgdGhlIHRpbGVcbiAgICAgKi9cbiAgICBnZXRUaWxlKGluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRhW2luZGV4XTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBzZXRUaWxlKGluZGV4OiBudW1iZXIsIHR5cGU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRhdGFbaW5kZXhdID0gdHlwZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgcm93IGFuZCBjb2x1bW5cbiAgICAgKiBAcGFyYW0gcm93Q29sIFRoZSBwb3NpdGlvbiBvZiB0aGUgdGlsZSBpbiB0aWxlbWFwIHNwYWNlXG4gICAgICogQHBhcmFtIHR5cGUgVGhlIG5ldyBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlXG4gICAgICovXG4gICAgc2V0VGlsZUF0Um93Q29sKHJvd0NvbDogVmVjMiwgdHlwZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGxldCBpbmRleCA9IHJvd0NvbC55ICogdGhpcy5udW1Db2xzICsgcm93Q29sLng7XG4gICAgICAgIHRoaXMuc2V0VGlsZShpbmRleCwgdHlwZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgcm93IGFuZCBjb2x1bW4gb2YgdGhlIHRpbGVtYXAgaXMgY29sbGlkYWJsZVxuICAgICAqIEBwYXJhbSBpbmRleE9yQ29sIFRoZSBpbmRleCBvZiB0aGUgdGlsZSBvciB0aGUgY29sdW1uIGl0IGlzIGluXG4gICAgICogQHBhcmFtIHJvdyBUaGUgcm93IHRoZSB0aWxlIGlzIGluXG4gICAgICogQHJldHVybnMgQSBmbGFnIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGUgdGlsZSBpcyBjb2xsaWRhYmxlLlxuICAgICAqL1xuICAgIGlzVGlsZUNvbGxpZGFibGUoaW5kZXhPckNvbDogbnVtYmVyLCByb3c/OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgLy8gVGhlIHZhbHVlIG9mIHRoZSB0aWxlXG4gICAgICAgIGxldCB0aWxlID0gMDtcblxuICAgICAgICBpZihyb3cpe1xuICAgICAgICAgICAgLy8gV2UgaGF2ZSBhIGNvbHVtbiBhbmQgYSByb3dcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLmdldFRpbGVBdFJvd0NvbChuZXcgVmVjMihpbmRleE9yQ29sLCByb3cpKTtcblxuICAgICAgICAgICAgaWYodGlsZSA8IDApe1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKGluZGV4T3JDb2wgPCAwIHx8IGluZGV4T3JDb2wgPj0gdGhpcy5kYXRhLmxlbmd0aCl7XG4gICAgICAgICAgICAgICAgLy8gVGlsZXMgdGhhdCBkb24ndCBleGlzdCBhcmVuJ3QgY29sbGlkYWJsZVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlIGhhdmUgYW4gaW5kZXhcbiAgICAgICAgICAgIHRpbGUgPSB0aGlzLmdldFRpbGUoaW5kZXhPckNvbCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5jb2xsaXNpb25NYXBbdGlsZV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGFrZXMgaW4gd29ybGQgY29vcmRpbmF0ZXMgYW5kIHJldHVybnMgdGhlIHJvdyBhbmQgY29sdW1uIG9mIHRoZSB0aWxlIGF0IHRoYXQgcG9zaXRpb25cbiAgICAgKiBAcGFyYW0gd29ybGRDb29yZHMgVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb3RlbnRpYWwgdGlsZSBpbiB3b3JsZCBzcGFjZVxuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgcG90ZW50aWFsIHRpbGUgaW4gdGlsZW1hcCBzcGFjZVxuICAgICAqL1xuICAgIGdldENvbFJvd0F0KHdvcmxkQ29vcmRzOiBWZWMyKTogVmVjMiB7XG4gICAgICAgIGxldCBjb2wgPSBNYXRoLmZsb29yKHdvcmxkQ29vcmRzLnggLyB0aGlzLnRpbGVTaXplLnggLyB0aGlzLnNjYWxlLngpO1xuICAgICAgICBsZXQgcm93ID0gTWF0aC5mbG9vcih3b3JsZENvb3Jkcy55IC8gdGhpcy50aWxlU2l6ZS55IC8gdGhpcy5zY2FsZS55KTtcblxuICAgICAgICByZXR1cm4gbmV3IFZlYzIoY29sLCByb3cpO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge31cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGRlYnVnUmVuZGVyKCl7XG4gICAgICAgIC8vIEhhbGYgb2YgdGhlIHRpbGUgc2l6ZVxuICAgICAgICBsZXQgem9vbWVkSGFsZlRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZVdpdGhab29tKCkuc2NhbGVkKDAuNSk7XG4gICAgICAgIGxldCBoYWxmVGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCkuc2NhbGVkKDAuNSk7XG5cbiAgICAgICAgLy8gVGhlIGNlbnRlciBvZiB0aGUgdG9wIGxlZnQgdGlsZVxuICAgICAgICBsZXQgdG9wTGVmdCA9IHRoaXMucG9zaXRpb24uY2xvbmUoKS5zdWIodGhpcy5zaXplLnNjYWxlZCgwLjUpKTtcbiAgICAgICAgXG4gICAgICAgIC8vIEEgdmVjIHRvIHN0b3JlIHRoZSBjZW50ZXJcbiAgICAgICAgbGV0IGNlbnRlciA9IFZlYzIuWkVSTztcblxuICAgICAgICBmb3IobGV0IGNvbCA9IDA7IGNvbCA8IHRoaXMubnVtQ29sczsgY29sKyspe1xuICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSB4LXBvc2l0aW9uXG4gICAgICAgICAgICBjZW50ZXIueCA9IHRvcExlZnQueCArIGNvbCoyKmhhbGZUaWxlU2l6ZS54ICsgaGFsZlRpbGVTaXplLng7XG5cbiAgICAgICAgICAgIGZvcihsZXQgcm93ID0gMDsgcm93IDwgdGhpcy5udW1Sb3dzOyByb3crKyl7XG4gICAgICAgICAgICAgICAgaWYodGhpcy5pc0NvbGxpZGFibGUgJiYgdGhpcy5pc1RpbGVDb2xsaWRhYmxlKGNvbCwgcm93KSl7XG4gICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgeS1wb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBjZW50ZXIueSA9IHRvcExlZnQueSArIHJvdyoyKmhhbGZUaWxlU2l6ZS55ICsgaGFsZlRpbGVTaXplLnk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRHJhdyBhIGJveCBmb3IgdGhpcyB0aWxlXG4gICAgICAgICAgICAgICAgICAgIERlYnVnLmRyYXdCb3godGhpcy5pblJlbGF0aXZlQ29vcmRpbmF0ZXMoY2VudGVyKSwgem9vbWVkSGFsZlRpbGVTaXplLCBmYWxzZSwgQ29sb3IuQkxVRSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuL0NhbnZhc05vZGVcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi9JbnB1dC9JbnB1dFwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhIFVJRWxlbWVudCAtIHRoZSBwYXJlbnQgY2xhc3Mgb2YgdGhpbmdzIGxpa2UgYnV0dG9uc1xuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBVSUVsZW1lbnQgZXh0ZW5kcyBDYW52YXNOb2RlIHtcblx0Ly8gU3R5bGUgYXR0cmlidXRlcyAtIFRPRE8gLSBhYnN0cmFjdCB0aGlzIGludG8gYSBzdHlsZSBvYmplY3QvaW50ZXJmYWNlXG5cdC8qKiBUaGUgYmFja2dvdW5kIGNvbG9yICovXG5cdGJhY2tncm91bmRDb2xvcjogQ29sb3I7XG5cdC8qKiBUaGUgYm9yZGVyIGNvbG9yICovXG5cdGJvcmRlckNvbG9yOiBDb2xvcjtcblx0LyoqIFRoZSBib3JkZXIgcmFkaXVzICovXG5cdGJvcmRlclJhZGl1czogbnVtYmVyO1xuXHQvKiogVGhlIGJvcmRlciB3aWR0aCAqL1xuXHRib3JkZXJXaWR0aDogbnVtYmVyO1xuXHQvKiogVGhlIHBhZGRpbmcgKi9cblx0cGFkZGluZzogVmVjMjtcblxuXHQvLyBFdmVudEF0dHJpYnV0ZXNcblx0LyoqIFRoZSByZWFjdGlvbiBvZiB0aGlzIFVJRWxlbWVudCBvbiBhIGNsaWNrICovXG5cdG9uQ2xpY2s6IEZ1bmN0aW9uO1xuXHQvKiogVGhlIGV2ZW50IHByb3BhZ2F0ZWQgb24gY2xpY2sgKi9cblx0b25DbGlja0V2ZW50SWQ6IHN0cmluZztcblx0LyoqIFRoZSByZWFjdGlvbiB0byB0aGUgcmVsZWFzZSBvZiBhIGNsaWNrICovXG5cdG9uUmVsZWFzZTogRnVuY3Rpb247XG5cdC8qKiBUaGUgZXZlbnQgcHJvcGFnYXRlZCBvbiB0aGUgcmVsZWFzZSBvZiBhIGNsaWNrICovXG5cdG9uUmVsZWFzZUV2ZW50SWQ6IHN0cmluZztcblx0LyoqIFRoZSByZWFjdGlvbiB3aGVuIGEgbW91c2UgZW50ZXJzIHRoaXMgVUlFbGVtZW50ICovXG5cdG9uRW50ZXI6IEZ1bmN0aW9uO1xuXHQvKiogVGhlIGV2ZW50IHByb3BhZ2F0ZWQgd2hlbiBhIG1vdXNlIGVudGVycyB0aGlzIFVJRWxlbWVudCAqL1xuXHRvbkVudGVyRXZlbnRJZDogc3RyaW5nO1xuXHQvKiogVGhlIHJlYWN0aW9uIHdoZW4gYSBtb3VzZSBsZWF2ZXMgdGhpcyBVSUVsZW1lbnQgKi9cblx0b25MZWF2ZTogRnVuY3Rpb247XG5cdC8qKiBUaGUgZXZlbnQgcHJvcG9nYXRlZCB3aGVuIGEgbW91c2UgbGVhdmVzIHRoaXMgVUlFbGVtZW50ICovXG5cdG9uTGVhdmVFdmVudElkOiBzdHJpbmc7XG5cblx0LyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgVUlFbGVtZW50IGlzIGN1cnJlbnRseSBjbGlja2VkIG9uICovXG5cdHByb3RlY3RlZCBpc0NsaWNrZWQ6IGJvb2xlYW47XG5cdC8qKiBXaGV0aGVyIG9yIG5vdCB0aGlzIFVJRWxlbWVudCBpcyBjdXJyZW50bHkgaG92ZXJlZCBvdmVyICovXG5cdHByb3RlY3RlZCBpc0VudGVyZWQ6IGJvb2xlYW47XG5cblx0Y29uc3RydWN0b3IocG9zaXRpb246IFZlYzIpe1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuXHRcdFxuXHRcdHRoaXMuYmFja2dyb3VuZENvbG9yID0gbmV3IENvbG9yKDAsIDAsIDAsIDApO1xuXHRcdHRoaXMuYm9yZGVyQ29sb3IgPSBuZXcgQ29sb3IoMCwgMCwgMCwgMCk7XG5cdFx0dGhpcy5ib3JkZXJSYWRpdXMgPSA1O1xuXHRcdHRoaXMuYm9yZGVyV2lkdGggPSAxO1xuXHRcdHRoaXMucGFkZGluZyA9IFZlYzIuWkVSTztcblxuXHRcdHRoaXMub25DbGljayA9IG51bGw7XG5cdFx0dGhpcy5vbkNsaWNrRXZlbnRJZCA9IG51bGw7XG5cdFx0dGhpcy5vblJlbGVhc2UgPSBudWxsO1xuXHRcdHRoaXMub25SZWxlYXNlRXZlbnRJZCA9IG51bGw7XG5cblx0XHR0aGlzLm9uRW50ZXIgPSBudWxsO1xuXHRcdHRoaXMub25FbnRlckV2ZW50SWQgPSBudWxsO1xuXHRcdHRoaXMub25MZWF2ZSA9IG51bGw7XG5cdFx0dGhpcy5vbkxlYXZlRXZlbnRJZCA9IG51bGw7XG5cblx0XHR0aGlzLmlzQ2xpY2tlZCA9IGZhbHNlO1xuXHRcdHRoaXMuaXNFbnRlcmVkID0gZmFsc2U7XG5cdH1cblxuXHQvLyBAZGVwcmVjYXRlZFxuXHRzZXRCYWNrZ3JvdW5kQ29sb3IoY29sb3I6IENvbG9yKTogdm9pZCB7XG5cdFx0dGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBjb2xvcjtcblx0fVxuXG5cdC8vIEBkZXByZWNhdGVkXG5cdHNldFBhZGRpbmcocGFkZGluZzogVmVjMik6IHZvaWQge1xuXHRcdHRoaXMucGFkZGluZy5jb3B5KHBhZGRpbmcpO1xuXHR9XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0c3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cblx0XHQvLyBTZWUgb2YgdGhpcyBvYmplY3Qgd2FzIGp1c3QgY2xpY2tlZFxuXHRcdGlmKElucHV0LmlzTW91c2VKdXN0UHJlc3NlZCgpKXtcblx0XHRcdGxldCBjbGlja1BvcyA9IElucHV0LmdldE1vdXNlUHJlc3NQb3NpdGlvbigpO1xuXHRcdFx0aWYodGhpcy5jb250YWlucyhjbGlja1Bvcy54LCBjbGlja1Bvcy55KSAmJiB0aGlzLnZpc2libGUgJiYgIXRoaXMubGF5ZXIuaXNIaWRkZW4oKSl7XG5cdFx0XHRcdHRoaXMuaXNDbGlja2VkID0gdHJ1ZTtcblxuXHRcdFx0XHRpZih0aGlzLm9uQ2xpY2sgIT09IG51bGwpe1xuXHRcdFx0XHRcdHRoaXMub25DbGljaygpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmKHRoaXMub25DbGlja0V2ZW50SWQgIT09IG51bGwpe1xuXHRcdFx0XHRcdGxldCBkYXRhID0ge307XG5cdFx0XHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0aGlzLm9uQ2xpY2tFdmVudElkLCBkYXRhKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIElmIHRoZSBtb3VzZSB3YXNuJ3QganVzdCBwcmVzc2VkLCB0aGVuIHdlIGRlZmluaXRlbHkgd2VyZW4ndCBjbGlja2VkXG5cdFx0aWYoIUlucHV0LmlzTW91c2VQcmVzc2VkKCkpe1xuXHRcdFx0aWYodGhpcy5pc0NsaWNrZWQpe1xuXHRcdFx0XHR0aGlzLmlzQ2xpY2tlZCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENoZWNrIGlmIHRoZSBtb3VzZSBpcyBob3ZlcmluZyBvdmVyIHRoaXMgZWxlbWVudFxuXHRcdGxldCBtb3VzZVBvcyA9IElucHV0LmdldE1vdXNlUG9zaXRpb24oKTtcblx0XHRpZihtb3VzZVBvcyAmJiB0aGlzLmNvbnRhaW5zKG1vdXNlUG9zLngsIG1vdXNlUG9zLnkpKXtcblx0XHRcdHRoaXMuaXNFbnRlcmVkID0gdHJ1ZTtcblxuXHRcdFx0aWYodGhpcy5vbkVudGVyICE9PSBudWxsKXtcblx0XHRcdFx0dGhpcy5vbkVudGVyKCk7XG5cdFx0XHR9XG5cdFx0XHRpZih0aGlzLm9uRW50ZXJFdmVudElkICE9PSBudWxsKXtcblx0XHRcdFx0bGV0IGRhdGEgPSB7fTtcblx0XHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0aGlzLm9uRW50ZXJFdmVudElkLCBkYXRhKTtcblx0XHRcdH1cblxuXHRcdH0gZWxzZSBpZih0aGlzLmlzRW50ZXJlZCkge1xuXHRcdFx0dGhpcy5pc0VudGVyZWQgPSBmYWxzZTtcblxuXHRcdFx0aWYodGhpcy5vbkxlYXZlICE9PSBudWxsKXtcblx0XHRcdFx0dGhpcy5vbkxlYXZlKCk7XG5cdFx0XHR9XG5cdFx0XHRpZih0aGlzLm9uTGVhdmVFdmVudElkICE9PSBudWxsKXtcblx0XHRcdFx0bGV0IGRhdGEgPSB7fTtcblx0XHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0aGlzLm9uTGVhdmVFdmVudElkLCBkYXRhKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYodGhpcy5pc0NsaWNrZWQpIHtcblx0XHRcdC8vIElmIG1vdXNlIGlzIGRyYWdnZWQgb2ZmIG9mIGVsZW1lbnQgd2hpbGUgZG93biwgaXQgaXMgbm90IGNsaWNrZWQgYW55bW9yZVxuXHRcdFx0dGhpcy5pc0NsaWNrZWQgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogT3ZlcnJpZGFibGUgbWV0aG9kIGZvciBjYWxjdWxhdGluZyBiYWNrZ3JvdW5kIGNvbG9yIC0gdXNlZnVsIGZvciBlbGVtZW50cyB0aGF0IHdhbnQgdG8gYmUgY29sb3JlZCBvbiBkaWZmZXJlbnQgYWZ0ZXIgY2VydGFpbiBldmVudHNcblx0ICogQHJldHVybnMgVGhlIGJhY2tncm91bmQgY29sb3Igb2YgdGhlIFVJRWxlbWVudFxuXHQgKi9cblx0Y2FsY3VsYXRlQmFja2dyb3VuZENvbG9yKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gdGhpcy5iYWNrZ3JvdW5kQ29sb3I7XG5cdH1cblxuXHQvKipcblx0ICogT3ZlcnJpZGFibGUgbWV0aG9kIGZvciBjYWxjdWxhdGluZyBib3JkZXIgY29sb3IgLSB1c2VmdWwgZm9yIGVsZW1lbnRzIHRoYXQgd2FudCB0byBiZSBjb2xvcmVkIG9uIGRpZmZlcmVudCBhZnRlciBjZXJ0YWluIGV2ZW50c1xuXHQgKiBAcmV0dXJucyBUaGUgYm9yZGVyIGNvbG9yIG9mIHRoZSBVSUVsZW1lbnRcblx0ICovXG5cdGNhbGN1bGF0ZUJvcmRlckNvbG9yKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gdGhpcy5ib3JkZXJDb2xvcjtcblx0fVxufSIsImltcG9ydCBMYWJlbCBmcm9tIFwiLi9MYWJlbFwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5cbi8qKiBBIGNsaWNrYWJsZSBidXR0b24gVUlFbGVtZW50ICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCdXR0b24gZXh0ZW5kcyBMYWJlbCB7XG5cblx0Y29uc3RydWN0b3IocG9zaXRpb246IFZlYzIsIHRleHQ6IHN0cmluZyl7XG5cdFx0c3VwZXIocG9zaXRpb24sIHRleHQpO1xuXHRcdFxuXHRcdHRoaXMuYmFja2dyb3VuZENvbG9yID0gbmV3IENvbG9yKDE1MCwgNzUsIDIwMyk7XG5cdFx0dGhpcy5ib3JkZXJDb2xvciA9IG5ldyBDb2xvcig0MSwgNDYsIDMwKTtcblx0XHR0aGlzLnRleHRDb2xvciA9IG5ldyBDb2xvcigyNTUsIDI1NSwgMjU1KTtcblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHRjYWxjdWxhdGVCYWNrZ3JvdW5kQ29sb3IoKTogQ29sb3Ige1xuXHRcdC8vIENoYW5nZSB0aGUgYmFja2dyb3VuZCBjb2xvciBpZiBjbGlja2VkIG9yIGhvdmVyZWRcblx0XHRpZih0aGlzLmlzRW50ZXJlZCAmJiAhdGhpcy5pc0NsaWNrZWQpe1xuXHRcdFx0cmV0dXJuIHRoaXMuYmFja2dyb3VuZENvbG9yLmxpZ2h0ZW4oKTtcblx0XHR9IGVsc2UgaWYodGhpcy5pc0NsaWNrZWQpe1xuXHRcdFx0cmV0dXJuIHRoaXMuYmFja2dyb3VuZENvbG9yLmRhcmtlbigpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5iYWNrZ3JvdW5kQ29sb3I7XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgVUlFbGVtZW50IGZyb20gXCIuLi9VSUVsZW1lbnRcIjtcblxuLyoqIEEgYmFzaWMgdGV4dC1jb250YWluaW5nIGxhYmVsICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMYWJlbCBleHRlbmRzIFVJRWxlbWVudHtcblx0LyoqIFRoZSBjb2xvciBvZiB0aGUgdGV4dCBvZiB0aGlzIFVJRWxlbWVudCAqL1xuXHR0ZXh0Q29sb3I6IENvbG9yO1xuXHQvKiogVGhlIHZhbHVlIG9mIHRoZSB0ZXh0IG9mIHRoaXMgVUlFbGVtZW50ICovXG5cdHRleHQ6IHN0cmluZztcblx0LyoqIFRoZSBuYW1lIG9mIHRoZSBmb250ICovXG5cdGZvbnQ6IHN0cmluZztcblx0LyoqIFRoZSBzaXplIG9mIHRoZSBmb250ICovXG5cdGZvbnRTaXplOiBudW1iZXI7XG5cdC8qKiBUaGUgaG9yaXpvbnRhbCBhbGlnbm1lbnQgb2YgdGhlIHRleHQgd2l0aGluIHRoZSBsYWJlbCAqL1xuXHRwcm90ZWN0ZWQgaEFsaWduOiBzdHJpbmc7XG5cdC8qKiBUaGUgdmVydGljYWwgYWxpZ25tZW50IG9mIHRleHQgd2l0aGluIHRoZSBsYWJlbCAqL1xuXHRwcm90ZWN0ZWQgdkFsaWduOiBzdHJpbmc7XG5cblx0LyoqIEEgZmxhZyBmb3IgaWYgdGhlIHdpZHRoIG9mIHRoZSB0ZXh0IGhhcyBiZWVuIG1lYXN1cmVkIG9uIHRoZSBjYW52YXMgZm9yIGF1dG8gd2lkdGggYXNzaWdubWVudCAqL1xuXHRwcm90ZWN0ZWQgc2l6ZUFzc2lnbmVkOiBib29sZWFuO1xuXG5cdGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCB0ZXh0OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHBvc2l0aW9uKTtcblx0XHR0aGlzLnRleHQgPSB0ZXh0O1xuXHRcdHRoaXMudGV4dENvbG9yID0gbmV3IENvbG9yKDAsIDAsIDAsIDEpO1xuXHRcdHRoaXMuZm9udCA9IFwiQXJpYWxcIjtcblx0XHR0aGlzLmZvbnRTaXplID0gMzA7XG5cdFx0dGhpcy5oQWxpZ24gPSBcImNlbnRlclwiO1xuXHRcdHRoaXMudkFsaWduID0gXCJjZW50ZXJcIjtcblxuXHRcdHRoaXMuc2l6ZUFzc2lnbmVkID0gZmFsc2U7XG5cdH1cblxuXHQvLyBAZGVwcmVjYXRlZFxuXHRzZXRUZXh0KHRleHQ6IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMudGV4dCA9IHRleHQ7XG5cdH1cblxuXHQvLyBAZGVwcmVjYXRlZFxuXHRzZXRUZXh0Q29sb3IoY29sb3I6IENvbG9yKTogdm9pZCB7XG5cdFx0dGhpcy50ZXh0Q29sb3IgPSBjb2xvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGEgc3RyaW5nIGNvbnRhaW5nIHRoZSBmb250IGRldGFpbHMgZm9yIHJlbmRlcmluZ1xuXHQgKiBAcmV0dXJucyBBIHN0cmluZyBjb250YWluaW5nIHRoZSBmb250IGRldGFpbHNcblx0ICovXG5cdGdldEZvbnRTdHJpbmcoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy5mb250U2l6ZSArIFwicHggXCIgKyB0aGlzLmZvbnQ7XG5cdH1cblxuXHQvKipcblx0ICogT3ZlcnJpZGFibGUgbWV0aG9kIGZvciBjYWxjdWxhdGluZyB0ZXh0IGNvbG9yIC0gdXNlZnVsIGZvciBlbGVtZW50cyB0aGF0IHdhbnQgdG8gYmUgY29sb3JlZCBvbiBkaWZmZXJlbnQgYWZ0ZXIgY2VydGFpbiBldmVudHNcblx0ICogQHJldHVybnMgYSBzdHJpbmcgY29udGFpbmcgdGhlIHRleHQgY29sb3Jcblx0ICovXG5cdGNhbGN1bGF0ZVRleHRDb2xvcigpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLnRleHRDb2xvci50b1N0cmluZ1JHQkEoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVc2VzIHRoZSBjYW52YXMgdG8gY2FsY3VsYXRlIHRoZSB3aWR0aCBvZiB0aGUgdGV4dFxuXHQgKiBAcGFyYW0gY3R4IFRoZSByZW5kZXJpbmcgY29udGV4dFxuXHQgKiBAcmV0dXJucyBBIG51bWJlciByZXByZXNlbnRpbmcgdGhlIHJlbmRlcmVkIHRleHQgd2lkdGhcblx0ICovXG5cdHByb3RlY3RlZCBjYWxjdWxhdGVUZXh0V2lkdGgoY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpOiBudW1iZXIge1xuXHRcdGN0eC5mb250ID0gdGhpcy5mb250U2l6ZSArIFwicHggXCIgKyB0aGlzLmZvbnQ7XG5cdFx0cmV0dXJuIGN0eC5tZWFzdXJlVGV4dCh0aGlzLnRleHQpLndpZHRoO1xuXHR9XG5cblx0c2V0SEFsaWduKGFsaWduOiBzdHJpbmcpOiB2b2lkIHtcblx0XHR0aGlzLmhBbGlnbiA9IGFsaWduO1xuXHR9XG5cblx0c2V0VkFsaWduKGFsaWduOiBzdHJpbmcpOiB2b2lkIHtcblx0XHR0aGlzLnZBbGlnbiA9IGFsaWduO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZSB0aGUgb2Zmc2V0IG9mIHRoZSB0ZXh0IC0gdGhpcyBpcyB1c2VkIGZvciByZW5kZXJpbmcgdGV4dCB3aXRoIGRpZmZlcmVudCBhbGlnbm1lbnRzXG5cdCAqIEBwYXJhbSBjdHggVGhlIHJlbmRlcmluZyBjb250ZXh0XG5cdCAqIEByZXR1cm5zIFRoZSBvZmZzZXQgb2YgdGhlIHRleHQgaW4gYSBWZWMyXG5cdCAqL1xuXHRjYWxjdWxhdGVUZXh0T2Zmc2V0KGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogVmVjMiB7XG5cdFx0bGV0IHRleHRXaWR0aCA9IHRoaXMuY2FsY3VsYXRlVGV4dFdpZHRoKGN0eCk7XG5cblx0XHRsZXQgb2Zmc2V0ID0gbmV3IFZlYzIoMCwgMCk7XG5cblx0XHRsZXQgaERpZmYgPSB0aGlzLnNpemUueCAtIHRleHRXaWR0aDtcblx0XHRpZih0aGlzLmhBbGlnbiA9PT0gSEFsaWduLkNFTlRFUil7XG5cdFx0XHRvZmZzZXQueCA9IGhEaWZmLzI7XG5cdFx0fSBlbHNlIGlmICh0aGlzLmhBbGlnbiA9PT0gSEFsaWduLlJJR0hUKXtcblx0XHRcdG9mZnNldC54ID0gaERpZmY7XG5cdFx0fVxuXG5cdFx0aWYodGhpcy52QWxpZ24gPT09IFZBbGlnbi5UT1Ape1xuXHRcdFx0Y3R4LnRleHRCYXNlbGluZSA9IFwidG9wXCI7XG5cdFx0XHRvZmZzZXQueSA9IDA7XG5cdFx0fSBlbHNlIGlmICh0aGlzLnZBbGlnbiA9PT0gVkFsaWduLkJPVFRPTSl7XG5cdFx0XHRjdHgudGV4dEJhc2VsaW5lID0gXCJib3R0b21cIjtcblx0XHRcdG9mZnNldC55ID0gdGhpcy5zaXplLnk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGN0eC50ZXh0QmFzZWxpbmUgPSBcIm1pZGRsZVwiO1xuXHRcdFx0b2Zmc2V0LnkgPSB0aGlzLnNpemUueS8yO1xuXHRcdH1cblxuXHRcdHJldHVybiBvZmZzZXQ7XG5cdH1cblxuXHRwcm90ZWN0ZWQgc2l6ZUNoYW5nZWQoKTogdm9pZCB7XG5cdFx0c3VwZXIuc2l6ZUNoYW5nZWQoKTtcblx0XHR0aGlzLnNpemVBc3NpZ25lZCA9IHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogQXV0b21hdGljYWxseSBzaXplcyB0aGUgZWxlbWVudCB0byB0aGUgdGV4dCB3aXRoaW4gaXRcblx0ICogQHBhcmFtIGN0eCBUaGUgcmVuZGVyaW5nIGNvbnRleHRcblx0ICovXG5cdHByb3RlY3RlZCBhdXRvU2l6ZShjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk6IHZvaWQge1xuXHRcdGxldCB3aWR0aCA9IHRoaXMuY2FsY3VsYXRlVGV4dFdpZHRoKGN0eCk7XG5cdFx0bGV0IGhlaWdodCA9IHRoaXMuZm9udFNpemU7XG5cdFx0dGhpcy5zaXplLnNldCh3aWR0aCArIHRoaXMucGFkZGluZy54KjIsIGhlaWdodCArIHRoaXMucGFkZGluZy55KjIpO1xuXHRcdHRoaXMuc2l6ZUFzc2lnbmVkID0gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0aWFsbHkgYXNzaWducyBhIHNpemUgdG8gdGhlIFVJRWxlbWVudCBpZiBub25lIGlzIHByb3ZpZGVkXG5cdCAqIEBwYXJhbSBjdHggVGhlIHJlbmRlcmluZyBjb250ZXh0XG5cdCAqL1xuXHRoYW5kbGVJbml0aWFsU2l6aW5nKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZCB7XG5cdFx0aWYoIXRoaXMuc2l6ZUFzc2lnbmVkKXtcblx0XHRcdHRoaXMuYXV0b1NpemUoY3R4KTtcblx0XHR9XG5cdH1cblxuXHQvKiogT24gdGhlIG5leHQgcmVuZGVyLCBzaXplIHRoaXMgZWxlbWVudCB0byBpdCdzIGN1cnJlbnQgdGV4dCB1c2luZyBpdHMgY3VycmVudCBmb250IHNpemUgKi9cblx0c2l6ZVRvVGV4dCgpOiB2b2lkIHtcblx0XHR0aGlzLnNpemVBc3NpZ25lZCA9IGZhbHNlO1xuXHR9XG59XG5cbmV4cG9ydCBlbnVtIFZBbGlnbiB7XG5cdFRPUCA9IFwidG9wXCIsXG5cdENFTlRFUiA9IFwiY2VudGVyXCIsXG5cdEJPVFRPTSA9IFwiYm90dG9tXCJcbn1cblxuZXhwb3J0IGVudW0gSEFsaWduIHtcblx0TEVGVCA9IFwibGVmdFwiLFxuXHRDRU5URVIgPSBcImNlbnRlclwiLFxuXHRSSUdIVCA9IFwicmlnaHRcIlxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi8uLi9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgVUlFbGVtZW50IGZyb20gXCIuLi9VSUVsZW1lbnRcIjtcblxuLyoqIEEgc2xpZGVyIFVJRWxlbWVudCAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2xpZGVyIGV4dGVuZHMgVUlFbGVtZW50IHtcbiAgICAvKiogVGhlIHZhbHVlIG9mIHRoZSBzbGlkZXIgZnJvbSBbMCwgMV0gKi9cbiAgICBwcm90ZWN0ZWQgdmFsdWU6IG51bWJlcjtcbiAgICAvKiogVGhlIGNvbG9yIG9mIHRoZSBzbGlkZXIgbmliICovXG4gICAgcHVibGljIG5pYkNvbG9yOiBDb2xvcjtcbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIG5pYiAqL1xuICAgIHB1YmxpYyBuaWJTaXplOiBWZWMyO1xuICAgIC8qKiBUaGUgY29sb3Igb2YgdGhlIHNsaWRlciB0cmFjayAqL1xuICAgIHB1YmxpYyBzbGlkZXJDb2xvcjogQ29sb3I7XG4gICAgLyoqIFRoZSByZWFjdGlvbiBvZiB0aGlzIFVJRWxlbWVudCB0byBhIHZhbHVlIGNoYW5nZSAqL1xuICAgIHB1YmxpYyBvblZhbHVlQ2hhbmdlOiBGdW5jdGlvbjtcbiAgICAvKiogVGhlIGV2ZW50IHByb3BhZ2F0ZWQgYnkgdGhpcyBVSUVsZW1lbnQgd2hlbiB2YWx1ZSBjaGFuZ2VzICovXG4gICAgcHVibGljIG9uVmFsdWVDaGFuZ2VFdmVudElkOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMiwgaW5pdFZhbHVlOiBudW1iZXIpe1xuICAgICAgICBzdXBlcihwb3NpdGlvbik7XG5cbiAgICAgICAgdGhpcy52YWx1ZSA9IGluaXRWYWx1ZTtcbiAgICAgICAgdGhpcy5uaWJDb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgdGhpcy5zbGlkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICB0aGlzLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICB0aGlzLmJvcmRlckNvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHRoaXMubmliU2l6ZSA9IG5ldyBWZWMyKDEwLCAyMCk7XG5cbiAgICAgICAgLy8gU2V0IGEgZGVmYXVsdCBzaXplXG4gICAgICAgIHRoaXMuc2l6ZS5zZXQoMjAwLCAyMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBvZiB0aGUgc2xpZGVyXG4gICAgICogQHJldHVybnMgVGhlIHZhbHVlIG9mIHRoZSBzbGlkZXJcbiAgICAgKi9cbiAgICBnZXRWYWx1ZSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICB9XG5cbiAgICAvKiogQSBtZXRob2QgY2FsbGVkIGluIHJlc3BvbnNlIHRvIHRoZSB2YWx1ZSBjaGFuZ2luZyAqL1xuICAgIHByb3RlY3RlZCB2YWx1ZUNoYW5nZWQoKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMub25WYWx1ZUNoYW5nZSl7XG4gICAgICAgICAgICB0aGlzLm9uVmFsdWVDaGFuZ2UodGhpcy52YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLm9uVmFsdWVDaGFuZ2VFdmVudElkKXtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQodGhpcy5vblZhbHVlQ2hhbmdlRXZlbnRJZCwge3RhcmdldDogdGhpcywgdmFsdWU6IHRoaXMudmFsdWV9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBzdXBlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICBpZih0aGlzLmlzQ2xpY2tlZCl7XG4gICAgICAgICAgICBsZXQgdmFsID0gTWF0aFV0aWxzLmludkxlcnAodGhpcy5wb3NpdGlvbi54IC0gdGhpcy5zaXplLngvMiwgdGhpcy5wb3NpdGlvbi54ICsgdGhpcy5zaXplLngvMiwgSW5wdXQuZ2V0TW91c2VQb3NpdGlvbigpLngpO1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IE1hdGhVdGlscy5jbGFtcDAxKHZhbCk7XG4gICAgICAgICAgICB0aGlzLnZhbHVlQ2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuL0xhYmVsXCI7XG5pbXBvcnQgSW5wdXQgZnJvbSBcIi4uLy4uL0lucHV0L0lucHV0XCI7XG5cbi8qKiBBIHRleHQgaW5wdXQgVUlFbGVtZW50ICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUZXh0SW5wdXQgZXh0ZW5kcyBMYWJlbCB7XG4gICAgLyoqIEEgZmxhZyB0aGUgcmVwcmVzZW50cyB3aGV0aGVyIHRoZSB1c2VyIGNhbiB0eXBlIGluIHRoaXMgVGV4dElucHV0ICovXG4gICAgZm9jdXNlZDogYm9vbGVhbjtcbiAgICAvKiogVGhlIHBvc2l0aW9uIG9mIHRoZSBjdXJzb3IgaW4gdGhpcyBUZXh0SW5wdXQgKi9cbiAgICBjdXJzb3JDb3VudGVyOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMil7XG4gICAgICAgIHN1cGVyKHBvc2l0aW9uLCBcIlwiKTtcblxuICAgICAgICB0aGlzLmZvY3VzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jdXJzb3JDb3VudGVyID0gMDtcblxuICAgICAgICAvLyBHaXZlIGEgZGVmYXVsdCBzaXplIHRvIHRoZSB4IG9ubHlcbiAgICAgICAgdGhpcy5zaXplLnNldCgyMDAsIHRoaXMuZm9udFNpemUpO1xuICAgICAgICB0aGlzLmhBbGlnbiA9IFwibGVmdFwiO1xuXG4gICAgICAgIHRoaXMuYm9yZGVyQ29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgc3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgaWYoSW5wdXQuaXNNb3VzZUp1c3RQcmVzc2VkKCkpe1xuXHRcdFx0bGV0IGNsaWNrUG9zID0gSW5wdXQuZ2V0TW91c2VQcmVzc1Bvc2l0aW9uKCk7XG5cdFx0XHRpZih0aGlzLmNvbnRhaW5zKGNsaWNrUG9zLngsIGNsaWNrUG9zLnkpKXtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuY3Vyc29yQ291bnRlciA9IDMwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMuZm9jdXNlZCl7XG4gICAgICAgICAgICBsZXQga2V5cyA9IElucHV0LmdldEtleXNKdXN0UHJlc3NlZCgpO1xuICAgICAgICAgICAgbGV0IG51bXMgPSBcIjEyMzQ1Njc4OTBcIjtcbiAgICAgICAgICAgIGxldCBzcGVjaWFsQ2hhcnMgPSBcImB+IUAjJCVeJiooKS1fPStbe119XFxcXHw7OidcXFwiLDwuPi8/XCI7XG4gICAgICAgICAgICBsZXQgbGV0dGVycyA9IFwicXdlcnR5dWlvcGFzZGZnaGprbHp4Y3Zibm1cIjtcbiAgICAgICAgICAgIGxldCBtYXNrID0gbnVtcyArIHNwZWNpYWxDaGFycyArIGxldHRlcnM7XG4gICAgICAgICAgICBrZXlzID0ga2V5cy5maWx0ZXIoa2V5ID0+IG1hc2suaW5jbHVkZXMoa2V5KSk7XG4gICAgICAgICAgICBsZXQgc2hpZnRQcmVzc2VkID0gSW5wdXQuaXNLZXlQcmVzc2VkKFwic2hpZnRcIik7XG4gICAgICAgICAgICBsZXQgYmFja3NwYWNlUHJlc3NlZCA9IElucHV0LmlzS2V5SnVzdFByZXNzZWQoXCJiYWNrc3BhY2VcIik7XG4gICAgICAgICAgICBsZXQgc3BhY2VQcmVzc2VkID0gSW5wdXQuaXNLZXlKdXN0UHJlc3NlZChcInNwYWNlXCIpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZihiYWNrc3BhY2VQcmVzc2VkKXtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSB0aGlzLnRleHQuc3Vic3RyaW5nKDAsIHRoaXMudGV4dC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihzcGFjZVByZXNzZWQpe1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCArPSBcIiBcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZihrZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBpZihzaGlmdFByZXNzZWQpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHQgKz0ga2V5c1swXS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dCArPSBrZXlzWzBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJleHBvcnQgZW51bSBVSUVsZW1lbnRUeXBlIHtcblx0QlVUVE9OID0gXCJCVVRUT05cIixcblx0TEFCRUwgPSBcIkxBQkVMXCIsXG5cdFNMSURFUiA9IFwiU0xJREVSXCIsXG5cdFRFWFRfSU5QVVQgPSBcIlRFWFRJTlBVVFwiXG59IiwiaW1wb3J0IE5hdmlnYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvTmF2aWdhYmxlXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBOYXZpZ2F0aW9uUGF0aCBmcm9tIFwiLi9OYXZpZ2F0aW9uUGF0aFwiO1xuXG4vKipcbiAqIFRoZSBtYW5hZ2VyIGNsYXNzIGZvciBuYXZpZ2F0aW9uLlxuICogSGFuZGxlcyBhbGwgbmF2aWdhYmxlIGVudGl0aWVzLCBzdWNoIGFuZCBhbGxvd3MgdGhlbSB0byBiZSBhY2Nlc3NlZCBieSBvdXRzaWRlIHN5c3RlbXMgYnkgcmVxdWVzdGluZyBhIHBhdGhcbiAqIGZyb20gb25lIHBvc2l0aW9uIHRvIGFub3RoZXIuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE5hdmlnYXRpb25NYW5hZ2VyIHtcblx0LyoqIFRoZSBsaXN0IG9mIGFsbCBuYXZpZ2FibGUgZW50aXRpZXMgKi9cblx0cHJvdGVjdGVkIG5hdmlnYWJsZUVudGl0aWVzOiBNYXA8TmF2aWdhYmxlPjtcblxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMubmF2aWdhYmxlRW50aXRpZXMgPSBuZXcgTWFwKCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIG5hdmlnYWJsZSBlbnRpdHkgdG8gdGhlIE5hdmlnYXRpb25NYW5hZ2VyXG5cdCAqIEBwYXJhbSBuYXZOYW1lIFRoZSBuYW1lIG9mIHRoZSBuYXZpZ2FibGUgZW50aXRyeVxuXHQgKiBAcGFyYW0gbmF2IFRoZSBhY3R1YWwgTmF2aWdhYmxlIGluc3RhbmNlXG5cdCAqL1xuXHRhZGROYXZpZ2FibGVFbnRpdHkobmF2TmFtZTogc3RyaW5nLCBuYXY6IE5hdmlnYWJsZSk6IHZvaWQge1xuXHRcdHRoaXMubmF2aWdhYmxlRW50aXRpZXMuYWRkKG5hdk5hbWUsIG5hdik7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBhIHBhdGggZnJvbWUgb25lIHBvaW50IHRvIGFub3RoZXIgdXNpbmcgYSBzcGVjaWZpZWQgTmF2aWdhYmxlIG9iamVjdFxuXHQgKiBAcGFyYW0gbmF2TmFtZSBUaGUgbmFtZSBvZiB0aGUgcmVnaXN0ZXJlZCBOYXZpZ2FibGUgb2JqZWN0XG5cdCAqIEBwYXJhbSBmcm9tUG9zaXRpb24gVGhlIHN0YXJ0aW5nIHBvc2l0aW9uIG9mIG5hdmlnYXRpb25cblx0ICogQHBhcmFtIHRvUG9zaXRpb24gVGhlIGVuZGluZyBwb3NpdGlvbiBvZiBOYXZpZ2F0aW9uXG5cdCAqIEBwYXJhbSBkaXJlY3QgSWYgdHJ1ZSwgZ28gZGlyZWN0IGZyb20gZnJvbVBvc2l0aW9uIHRvIHRvUG9zaXRpb24sIGRvbid0IHVzZSBOYXZNZXNoXG5cdCAqIEByZXR1cm5zIEEgTmF2aWdhdGlvblBhdGggY29udGFpbmluZyB0aGUgcm91dGUgdG8gdGFrZSBvdmVyIHRoZSBOYXZpZ2FibGUgZW50aXR5IHRvIGdldCBiZXR3ZWVuIHRoZSBwcm92aWRlZCBwb3NpdGlvbnMuXG5cdCAqL1xuXHRnZXRQYXRoKG5hdk5hbWU6IHN0cmluZywgZnJvbVBvc2l0aW9uOiBWZWMyLCB0b1Bvc2l0aW9uOiBWZWMyLCBkaXJlY3Q/OiBib29sZWFuKTogTmF2aWdhdGlvblBhdGgge1xuXHRcdGxldCBuYXYgPSB0aGlzLm5hdmlnYWJsZUVudGl0aWVzLmdldChuYXZOYW1lKTtcblx0XHRyZXR1cm4gbmF2LmdldE5hdmlnYXRpb25QYXRoKGZyb21Qb3NpdGlvbi5jbG9uZSgpLCB0b1Bvc2l0aW9uLmNsb25lKCksIGRpcmVjdCk7XG5cdH1cbn0iLCJpbXBvcnQgU3RhY2sgZnJvbSBcIi4uL0RhdGFUeXBlcy9TdGFja1wiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5cbi8qKlxuICogQSBwYXRoIHRoYXQgQUlzIGNhbiBmb2xsb3cuIFVzZXMgZmluaXNoTW92ZSgpIGluIFBoeXNpY2FsIHRvIGRldGVybWluZSBwcm9ncmVzcyBvbiB0aGUgcm91dGVcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTmF2aWdhdGlvblBhdGgge1xuXHQvKiogVGhlIG5hdmlnYXRpb24gcGF0aCwgc3RvcmVkIGFzIGEgc3RhY2sgb2YgbmV4dCBwb3NpdGlvbnMgKi9cblx0cHJvdGVjdGVkIHBhdGg6IFN0YWNrPFZlYzI+O1xuXHQvKiogVGhlIGN1cnJlbnQgZGlyZWN0aW9uIG9mIG1vdmVtZW50ICovXG5cdHByb3RlY3RlZCBjdXJyZW50TW92ZURpcmVjdGlvbjogVmVjMjtcblx0LyoqIFRoZSBkaXN0YW5jZSBhIG5vZGUgbXVzdCBiZSB0byBhIHBvaW50IHRvIGNvbnNpZGVyIGl0IGFzIGhhdmluZyBhcnJpdmVkICovXG5cdHByb3RlY3RlZCBkaXN0YW5jZVRocmVzaG9sZDogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBDb25zdHJ1Y3RzIGEgbmV3IE5hdmlnYXRpb25QYXRoXG5cdCAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIG9mIG5vZGVzIHRvIHRha2Vcblx0ICovXG5cdGNvbnN0cnVjdG9yKHBhdGg6IFN0YWNrPFZlYzI+KXtcblx0XHR0aGlzLnBhdGggPSBwYXRoO1xuXHRcdHRoaXMuY3VycmVudE1vdmVEaXJlY3Rpb24gPSBWZWMyLlpFUk87XG5cdFx0dGhpcy5kaXN0YW5jZVRocmVzaG9sZCA9IDQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgc3RhdHVzIG9mIG5hdmlnYXRpb24gYWxvbmcgdGhpcyBOYXZpZ2F0aW9uUGF0aFxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBub2RlIGhhcyByZWFjaGVkIHRoZSBlbmQgb2YgdGhlIHBhdGgsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cblx0aXNEb25lKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLnBhdGguaXNFbXB0eSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIG1vdmVtZW50IGRpcmVjdGlvbiBpbiB0aGUgY3VycmVudCBwb3NpdGlvbiBhbG9uZyB0aGUgcGF0aFxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byBtb3ZlIGFsb25nIHRoZSBwYXRoXG5cdCAqIEByZXR1cm5zIFRoZSBtb3ZlbWVudCBkaXJlY3Rpb24gYXMgYSBWZWMyXG5cdCAqL1xuXHRnZXRNb3ZlRGlyZWN0aW9uKG5vZGU6IEdhbWVOb2RlKTogVmVjMiB7XG5cdFx0Ly8gUmV0dXJuIGRpcmVjdGlvbiB0byBuZXh0IHBvaW50IGluIHRoZSBuYXZcblx0XHRyZXR1cm4gbm9kZS5wb3NpdGlvbi5kaXJUbyh0aGlzLnBhdGgucGVlaygpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoaXMgTmF2aWdhdGlvblBhdGggdG8gdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIEdhbWVOb2RlXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlIG1vdmluZyBhbG9uZyB0aGUgcGF0aFxuXHQgKi9cblx0aGFuZGxlUGF0aFByb2dyZXNzKG5vZGU6IEdhbWVOb2RlKTogdm9pZCB7XG5cdFx0aWYobm9kZS5wb3NpdGlvbi5kaXN0YW5jZVNxVG8odGhpcy5wYXRoLnBlZWsoKSkgPCB0aGlzLmRpc3RhbmNlVGhyZXNob2xkKnRoaXMuZGlzdGFuY2VUaHJlc2hvbGQpe1xuXHRcdFx0Ly8gV2UndmUgcmVhY2hlZCBvdXIgbm9kZSwgbW92ZSBvbiB0byB0aGUgbmV4dCBkZXN0aW5hdGlvblxuXHRcdFx0dGhpcy5wYXRoLnBvcCgpO1xuXHRcdH1cblx0fVxuXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMucGF0aC50b1N0cmluZygpXG5cdH1cbn0iLCJpbXBvcnQgUG9zaXRpb25HcmFwaCBmcm9tIFwiLi4vRGF0YVR5cGVzL0dyYXBocy9Qb3NpdGlvbkdyYXBoXCI7XG5pbXBvcnQgTmF2aWdhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9OYXZpZ2FibGVcIjtcbmltcG9ydCBTdGFjayBmcm9tIFwiLi4vRGF0YVR5cGVzL1N0YWNrXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHcmFwaFV0aWxzIGZyb20gXCIuLi9VdGlscy9HcmFwaFV0aWxzXCI7XG5pbXBvcnQgTmF2aWdhdGlvblBhdGggZnJvbSBcIi4vTmF2aWdhdGlvblBhdGhcIjtcblxuLyoqXG4gKiBBbiBpbXBsZW1lbnRhdGlvbiBvZiBhIE5hdm1lc2guIE5hdm1lc2hlcyBhcmUgZ3JhcGhzIGluIHRoZSBnYW1lIHdvcmxkIGFsb25nIHdoaWNoIG5vZGVzIGNhbiBtb3ZlLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZtZXNoIGltcGxlbWVudHMgTmF2aWdhYmxlIHtcblx0LyoqIFRoZSBncmFwaCBvZiBwb2ludHMgaW4gdGhlIE5hdk1lc2ggKi9cblx0cHJvdGVjdGVkIGdyYXBoOiBQb3NpdGlvbkdyYXBoO1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IE5hdm1lc2ggZnJvbSB0aGUgcG9pbnRzIGluIHRoZSBzcGVlY2lmaWVkIGdyYXBoXG5cdCAqIEBwYXJhbSBncmFwaCBUaGUgZ3JhcGggdG8gY29uc3RydWN0IGEgbmF2bWVzaCBmcm9tXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihncmFwaDogUG9zaXRpb25HcmFwaCl7XG5cdFx0dGhpcy5ncmFwaCA9IGdyYXBoO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGdldE5hdmlnYXRpb25QYXRoKGZyb21Qb3NpdGlvbjogVmVjMiwgdG9Qb3NpdGlvbjogVmVjMiwgZGlyZWN0OiBib29sZWFuKTogTmF2aWdhdGlvblBhdGgge1xuXHRcdGxldCBzdGFydCA9IHRoaXMuZ2V0Q2xvc2VzdE5vZGUoZnJvbVBvc2l0aW9uKTtcblx0XHRsZXQgZW5kID0gdGhpcy5nZXRDbG9zZXN0Tm9kZSh0b1Bvc2l0aW9uKTtcblxuXHRcdGxldCBwYXRoU3RhY2sgPSBuZXcgU3RhY2s8VmVjMj4odGhpcy5ncmFwaC5udW1WZXJ0aWNlcyk7XG5cdFx0XG5cdFx0Ly8gUHVzaCB0aGUgZmluYWwgcG9zaXRpb24gYW5kIHRoZSBmaW5hbCBwb3NpdGlvbiBpbiB0aGUgZ3JhcGhcblx0XHRwYXRoU3RhY2sucHVzaCh0b1Bvc2l0aW9uLmNsb25lKCkpO1xuXG5cdFx0aWYgKGRpcmVjdCkge1xuXHRcdFx0cmV0dXJuIG5ldyBOYXZpZ2F0aW9uUGF0aChwYXRoU3RhY2spO1xuXHRcdH1cblxuXHRcdHBhdGhTdGFjay5wdXNoKHRoaXMuZ3JhcGgucG9zaXRpb25zW2VuZF0pO1xuXG5cdFx0bGV0IHBhcmVudCA9IEdyYXBoVXRpbHMuZGppa3N0cmEodGhpcy5ncmFwaCwgc3RhcnQpO1xuXG5cdFx0Ly8gQWRkIGFsbCBwYXJlbnRzIGFsb25nIHRoZSBwYXRoXG5cdFx0bGV0IGkgPSBlbmQ7XG5cdFx0d2hpbGUocGFyZW50W2ldICE9PSAtMSl7XG5cdFx0XHRwYXRoU3RhY2sucHVzaCh0aGlzLmdyYXBoLnBvc2l0aW9uc1twYXJlbnRbaV1dKTtcblx0XHRcdGkgPSBwYXJlbnRbaV07XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBOYXZpZ2F0aW9uUGF0aChwYXRoU3RhY2spO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGNsb3Nlc3Qgbm9kZSBpbiB0aGlzIE5hdm1lc2ggdG8gdGhlIHNwZWNpZmllZCBwb3NpdGlvblxuXHQgKiBAcGFyYW0gcG9zaXRpb24gVGhlIHBvc2l0aW9uIHRvIHF1ZXJ5XG5cdCAqIEByZXR1cm5zIFRoZSBpbmRleCBvZiB0aGUgY2xvc2VzdCBub2RlIGluIHRoZSBOYXZtZXNoIHRvIHRoZSBwb3NpdGlvblxuXHQgKi9cblx0cHJvdGVjdGVkIGdldENsb3Nlc3ROb2RlKHBvc2l0aW9uOiBWZWMyKTogbnVtYmVyIHtcblx0XHRsZXQgbiA9IHRoaXMuZ3JhcGgubnVtVmVydGljZXM7XG5cdFx0bGV0IGkgPSAxO1xuXHRcdGxldCBpbmRleCA9IDA7XG5cdFx0bGV0IGRpc3QgPSBwb3NpdGlvbi5kaXN0YW5jZVNxVG8odGhpcy5ncmFwaC5wb3NpdGlvbnNbMF0pO1xuXHRcdHdoaWxlKGkgPCBuKXtcblx0XHRcdGxldCBkID0gcG9zaXRpb24uZGlzdGFuY2VTcVRvKHRoaXMuZ3JhcGgucG9zaXRpb25zW2ldKTtcblx0XHRcdGlmKGQgPCBkaXN0KXtcblx0XHRcdFx0ZGlzdCA9IGQ7XG5cdFx0XHRcdGluZGV4ID0gaTtcblx0XHRcdH1cblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaW5kZXg7XG5cdH1cbn0iLCJpbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgUGh5c2ljYWwgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1BoeXNpY2FsXCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IFBoeXNpY3NNYW5hZ2VyIGZyb20gXCIuL1BoeXNpY3NNYW5hZ2VyXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuLi9EYXRhVHlwZXMvU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBPcnRob2dvbmFsVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcHMvT3J0aG9nb25hbFRpbGVtYXBcIjtcbmltcG9ydCBBcmVhQ29sbGlzaW9uIGZyb20gXCIuLi9EYXRhVHlwZXMvUGh5c2ljcy9BcmVhQ29sbGlzaW9uXCI7XG5pbXBvcnQgVW5pcXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VbmlxdWVcIjtcblxuLyoqXG4gKiBBTEdPUklUSE06XG4gKiBcdEluIGFuIGVmZm9ydCB0byBrZWVwIHRoaW5ncyBzaW1wbGUgYW5kIHdvcmtpbmcgZWZmZWN0aXZlbHksIGVhY2ggZHluYW1pYyBub2RlIHdpbGwgcmVzb2x2ZSBpdHNcbiAqIFx0Y29sbGlzaW9ucyBjb25zaWRlcmluZyB0aGUgcmVzdCBvZiB0aGUgd29ybGQgYXMgc3RhdGljLlxuICogXG4gKiBcdENvbGxpc2lvbiBkZXRlY3Rpbmcgd2lsbCBoYXBwZW4gZmlyc3QuIFRoaXMgY2FuIGJlIGNvbnNpZGVyZWQgYSBicm9hZCBwaGFzZSwgYnV0IGl0IGlzIG5vdCBlc3BlY2lhbGx5XG4gKiBcdGVmZmljaWVudCwgYXMgaXQgZG9lcyBub3QgbmVlZCB0byBiZSBmb3IgdGhpcyBnYW1lIGVuZ2luZS4gRXZlcnkgZHluYW1pYyBub2RlIGlzIGNoZWNrZWQgYWdhaW5zdCBldmVyeVxuICogXHRvdGhlciBub2RlIGZvciBjb2xsaXNpb24gYXJlYS4gSWYgY29sbGlzaW9uIGFyZWEgaXMgbm9uLXplcm8gKG1lYW5pbmcgdGhlIGN1cnJlbnQgbm9kZSBzd2VlcHMgaW50byBhbm90aGVyKSxcbiAqIFx0aXQgaXMgYWRkZWQgdG8gYSBsaXN0IG9mIGhpdHMuXG4gKiBcbiAqIFx0SU5JVElBTElaQVRJT046XG4gKiBcdFx0LSBQaHlzaWNzIGNvbnN0YW50cyBhcmUgcmVzZXRcbiAqIFx0XHQtIFN3ZXB0IHNoYXBlcyBhcmUgcmVjYWxjdWxhdGVkLiBJZiBhIG5vZGUgaXNuJ3QgbW92aW5nLCBpdCBpcyBza2lwcGVkLlxuICogXG4gKiBcdENPTExJU0lPTiBERVRFQ1RJT046XG4gKiBcdFx0LSBGb3IgYSBub2RlLCBjb2xsaXNpb24gYXJlYSB3aWxsIGJlIGNhbGN1bGF0ZWQgdXNpbmcgdGhlIHN3ZXB0IEFBQkIgb2YgdGhlIG5vZGUgYWdhaW5zdCBldmVyeSBvdGhlciBBQUJCIGluIGEgc3RhdGljIHN0YXRlXG4gKiBcdFx0LSBUaGVzZSBjb2xsaXNpb25zIHdpbGwgYmUgc29ydGVkIGJ5IGFyZWEgaW4gZGVzY2VuZGluZyBvcmRlclxuICogXHRcbiAqIFx0Q09MTElTSU9OIFJFU09MVVRJT046XG4gKiBcdFx0LSBGb3IgZWFjaCBoaXQsIHRpbWUgb2YgY29sbGlzaW9uIGlzIGNhbGN1bGF0ZWQgdXNpbmcgYSBzd2VwdCBsaW5lIHRocm91Z2ggdGhlIEFBQkIgb2YgdGhlIHN0YXRpYyBub2RlIGV4cGFuZGVkXG4gKiBcdFx0XHR3aXRoIG1pbmtvd3NraSBzdW1zIChkaXNjcmV0ZWx5LCBidXQgdGhlIGNvbmNlcHQgaXMgdGhlcmUpXG4gKiBcdFx0LSBUaGUgY29sbGlzaW9uIGlzIHJlc29sdmVkIGJhc2VkIG9uIHRoZSBuZWFyIHRpbWUgb2YgdGhlIGNvbGxpc2lvbiAoZnJvbSBtZXRob2Qgb2Ygc2VwYXJhdGVkIGF4ZXMpXG4gKiBcdFx0XHQtIFggaXMgcmVzb2x2ZWQgYnkgbmVhciB4LCBZIGJ5IG5lYXIgeS5cbiAqIFx0XHRcdC0gVGhlcmUgaXMgc29tZSBmdWRnaW5nIHRvIGFsbG93IGZvciBzbGlkaW5nIGFsb25nIHdhbGxzIG9mIHNlcGFyYXRlIGNvbGxpZGVycy4gU29ydGluZyBieSBhcmVhIGFsc28gaGVscHMgd2l0aCB0aGlzLlxuICogXHRcdFx0LSBDb3JuZXIgdG8gY29ybmVyIGNvbGxpc2lvbnMgYXJlIHJlc29sdmUgdG8gZmF2b3IgeC1tb3ZlbWVudC4gVGhpcyBpcyBpbiBjb25zaWRlcmF0aW9uIG9mIHBsYXRmb3JtZXJzLCB0byBnaXZlXG4gKiBcdFx0XHRcdHRoZSBwbGF5ZXIgc29tZSBoZWxwIHdpdGgganVtcHNcbiAqIFxuICogXHRQcm9zOlxuICogXHRcdC0gRXZlcnl0aGluZyBoYXBwZW5zIHdpdGggYSBjb25zaXN0ZW50IHRpbWUuIFRoZXJlIGlzIGEgZGlzdGluY3QgYmVmb3JlIGFuZCBhZnRlciBmb3IgZWFjaCByZXNvbHV0aW9uLlxuICogXHRcdC0gTm8gYmFjay10cmFja2luZyBuZWVkcyB0byBiZSBkb25lLiBPbmNlIHdlIHJlc29sdmUgYSBub2RlLCBpdCBpcyBkZWZpbml0aXZlbHkgcmVzb2x2ZWQuXG4gKiBcdFxuICogXHRDb25zOlxuICogXHRcdC0gTm9kZXMgdGhhdCBhcmUgcHJvY2Vzc2VkIGVhcmx5IGhhdmUgbW92ZW1lbnQgcHJpb3JpdHkgb3ZlciBvdGhlciBub2Rlcy4gVGhpcyBjYW4gbGVhZCB0byBzb21lIHVuZGVzaXJhYmxlIGludGVyYWN0aW9ucy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzaWNQaHlzaWNzTWFuYWdlciBleHRlbmRzIFBoeXNpY3NNYW5hZ2VyIHtcblxuXHQvKiogVGhlIGFycmF5IG9mIHN0YXRpYyBub2RlcyAqL1xuXHRwcm90ZWN0ZWQgc3RhdGljTm9kZXM6IEFycmF5PFBoeXNpY2FsPjtcblxuXHQvKiogVGhlIGFycmF5IG9mIGR5bmFtaWMgbm9kZXMgKi9cblx0cHJvdGVjdGVkIGR5bmFtaWNOb2RlczogQXJyYXk8UGh5c2ljYWw+O1xuXG5cdC8qKiBUaGUgYXJyYXkgb2YgdGlsZW1hcHMgKi9cblx0cHJvdGVjdGVkIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPjtcblxuXHQvKiogQW4gYXJyYXkgb2YgdGhlIGNvbGxpc2lvbiBtYXNrcyBmb3IgZWFjaCBncm91cCAqL1xuXHRwcm90ZWN0ZWQgY29sbGlzaW9uTWFza3M6IEFycmF5PG51bWJlcj47XG5cblx0Y29uc3RydWN0b3Iob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pil7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLnN0YXRpY05vZGVzID0gbmV3IEFycmF5KCk7XG5cdFx0dGhpcy5keW5hbWljTm9kZXMgPSBuZXcgQXJyYXkoKTtcblx0XHR0aGlzLnRpbGVtYXBzID0gbmV3IEFycmF5KCk7XG5cdFx0dGhpcy5jb2xsaXNpb25NYXNrcyA9IG5ldyBBcnJheSgzMik7XG5cblx0XHQvLyBQYXJzZSBvcHRpb25zXG5cdFx0dGhpcy5wYXJzZU9wdGlvbnMob3B0aW9ucyk7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIHRoZSBvcHRpb25zIGZvciBjb25zdHJ1Y3RpbmcgdGhlIHBoeXNpY3MgbWFuYWdlclxuXHQgKiBAcGFyYW0gb3B0aW9ucyBBIHJlY29yZCBvZiBvcHRpb25zXG5cdCAqL1xuXHRwcm90ZWN0ZWQgcGFyc2VPcHRpb25zKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRpZihvcHRpb25zLmdyb3VwTmFtZXMgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLmNvbGxpc2lvbnMgIT09IHVuZGVmaW5lZCl7XG5cdFx0XHRmb3IobGV0IGkgPSAwOyBpIDwgb3B0aW9ucy5ncm91cE5hbWVzLmxlbmd0aDsgaSsrKXtcblx0XHRcdFx0bGV0IGdyb3VwID0gb3B0aW9ucy5ncm91cE5hbWVzW2ldO1xuXG5cdFx0XHRcdC8vIFJlZ2lzdGVyIHRoZSBncm91cCBuYW1lIGFuZCBudW1iZXJcblx0XHRcdFx0dGhpcy5ncm91cE5hbWVzW2ldID0gZ3JvdXA7XG5cblx0XHRcdFx0dGhpcy5ncm91cE1hcC5zZXQoZ3JvdXAsIDEgPDwgaSk7XG5cblx0XHRcdFx0bGV0IGNvbGxpc2lvbk1hc2sgPSAwO1xuXG5cdFx0XHRcdGZvcihsZXQgaiA9IDA7IGogPCBvcHRpb25zLmNvbGxpc2lvbnNbaV0ubGVuZ3RoOyBqKyspe1xuXHRcdFx0XHRcdGlmKG9wdGlvbnMuY29sbGlzaW9uc1tpXVtqXSl7XG5cdFx0XHRcdFx0XHRjb2xsaXNpb25NYXNrIHw9IDEgPDwgajtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aGlzLmNvbGxpc2lvbk1hc2tzW2ldID0gY29sbGlzaW9uTWFzaztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0cmVnaXN0ZXJPYmplY3Qobm9kZTogUGh5c2ljYWwpOiB2b2lkIHtcblx0XHRpZihub2RlLmlzU3RhdGljKXtcblx0XHRcdC8vIFN0YXRpYyBhbmQgbm90IGNvbGxpZGFibGVcblx0XHRcdHRoaXMuc3RhdGljTm9kZXMucHVzaChub2RlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gRHluYW1pYyBhbmQgbm90IGNvbGxpZGFibGVcblx0XHRcdHRoaXMuZHluYW1pY05vZGVzLnB1c2gobm9kZSk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdGRlcmVnaXN0ZXJPYmplY3Qobm9kZTogUGh5c2ljYWwpOiB2b2lkIHtcblx0XHRpZihub2RlLmlzU3RhdGljKXtcblx0XHRcdC8vIFJlbW92ZSB0aGUgbm9kZSBmcm9tIHRoZSBzdGF0aWMgbGlzdFxuXHRcdFx0Y29uc3QgaW5kZXggPSB0aGlzLnN0YXRpY05vZGVzLmluZGV4T2Yobm9kZSk7XG5cdFx0XHR0aGlzLnN0YXRpY05vZGVzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFJlbW92ZSB0aGUgbm9kZSBmcm9tIHRoZSBkeW5hbWljIGxpc3Rcblx0XHRcdGNvbnN0IGluZGV4ID0gdGhpcy5keW5hbWljTm9kZXMuaW5kZXhPZihub2RlKTtcblx0XHRcdHRoaXMuZHluYW1pY05vZGVzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdHJlZ2lzdGVyVGlsZW1hcCh0aWxlbWFwOiBUaWxlbWFwKTogdm9pZCB7XG5cdFx0dGhpcy50aWxlbWFwcy5wdXNoKHRpbGVtYXApO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdGRlcmVnaXN0ZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkIHtcblx0XHRjb25zdCBpbmRleCA9IHRoaXMudGlsZW1hcHMuaW5kZXhPZih0aWxlbWFwKTtcblx0XHR0aGlzLnRpbGVtYXBzLnNwbGljZShpbmRleCwgMSk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Zm9yKGxldCBub2RlIG9mIHRoaXMuZHluYW1pY05vZGVzKXtcblx0XHRcdC8qLS0tLS0tLS0tLSBJTklUSUFMSVpBVElPTiBQSEFTRSAtLS0tLS0tLS0tKi9cblx0XHRcdC8vIENsZWFyIGZyYW1lIGRlcGVuZGVudCBib29sZWFuIHZhbHVlcyBmb3IgZWFjaCBub2RlXG5cdFx0XHRub2RlLm9uR3JvdW5kID0gZmFsc2U7XG5cdFx0XHRub2RlLm9uQ2VpbGluZyA9IGZhbHNlO1xuXHRcdFx0bm9kZS5vbldhbGwgPSBmYWxzZTtcblx0XHRcdG5vZGUuY29sbGlkZWRXaXRoVGlsZW1hcCA9IGZhbHNlO1xuXHRcdFx0bm9kZS5pc0NvbGxpZGluZyA9IGZhbHNlO1xuXG5cdFx0XHQvLyBJZiB0aGlzIG5vZGUgaXMgbm90IGFjdGl2ZSwgZG9uJ3QgcHJvY2VzcyBpdFxuXHRcdFx0aWYoIW5vZGUuYWN0aXZlKXtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFVwZGF0ZSB0aGUgc3dlcHQgc2hhcGVzIG9mIGVhY2ggbm9kZVxuXHRcdFx0aWYobm9kZS5tb3Zpbmcpe1xuXHRcdFx0XHQvLyBJZiBtb3ZpbmcsIHJlZmxlY3QgdGhhdCBpbiB0aGUgc3dlcHQgc2hhcGVcblx0XHRcdFx0bm9kZS5zd2VwdFJlY3Quc3dlZXAobm9kZS5fdmVsb2NpdHksIG5vZGUuY29sbGlzaW9uU2hhcGUuY2VudGVyLCBub2RlLmNvbGxpc2lvblNoYXBlLmhhbGZTaXplKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIElmIG91ciBub2RlIGlzbid0IG1vdmluZywgZG9uJ3QgYm90aGVyIHRvIGNoZWNrIGl0IChvdGhlciBub2RlcyB3aWxsIGRldGVjdCBpZiB0aGV5IHJ1biBpbnRvIGl0KVxuXHRcdFx0XHRub2RlLl92ZWxvY2l0eS56ZXJvKCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvKi0tLS0tLS0tLS0gREVURUNUSU9OIFBIQVNFIC0tLS0tLS0tLS0qL1xuXHRcdFx0Ly8gR2F0aGVyIGEgc2V0IG9mIG92ZXJsYXBzXG5cdFx0XHRsZXQgb3ZlcmxhcHMgPSBuZXcgQXJyYXk8QXJlYUNvbGxpc2lvbj4oKTtcblxuXHRcdFx0bGV0IGdyb3VwSW5kZXggPSBub2RlLmdyb3VwID09PSAtMSA/IC0xIDogTWF0aC5sb2cyKG5vZGUuZ3JvdXApO1xuXG5cdFx0XHQvLyBGaXJzdCwgY2hlY2sgdGhpcyBub2RlIGFnYWluc3QgZXZlcnkgc3RhdGljIG5vZGUgKG9yZGVyIGRvZXNuJ3QgYWN0dWFsbHkgbWF0dGVyIGhlcmUsIHNpbmNlIHdlIHNvcnQgYW55d2F5cylcblx0XHRcdGZvcihsZXQgb3RoZXIgb2YgdGhpcy5zdGF0aWNOb2Rlcyl7XG5cdFx0XHRcdC8vIElnbm9yZSBpbmFjdGl2ZSBub2Rlc1xuXHRcdFx0XHRpZighb3RoZXIuYWN0aXZlKSBjb250aW51ZTtcblxuXHRcdFx0XHRsZXQgY29sbGlkZXIgPSBvdGhlci5jb2xsaXNpb25TaGFwZS5nZXRCb3VuZGluZ1JlY3QoKTtcblx0XHRcdFx0bGV0IGFyZWEgPSBub2RlLnN3ZXB0UmVjdC5vdmVybGFwQXJlYShjb2xsaWRlcik7XG5cdFx0XHRcdGlmKGFyZWEgPiAwKXtcblx0XHRcdFx0XHQvLyBXZSBoYWQgYSBjb2xsaXNpb25cblx0XHRcdFx0XHRvdmVybGFwcy5wdXNoKG5ldyBBcmVhQ29sbGlzaW9uKGFyZWEsIGNvbGxpZGVyLCBvdGhlciwgXCJHYW1lTm9kZVwiLCBudWxsKSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gVGhlbiwgY2hlY2sgaXQgYWdhaW5zdCBldmVyeSBkeW5hbWljIG5vZGVcblx0XHRcdGZvcihsZXQgb3RoZXIgb2YgdGhpcy5keW5hbWljTm9kZXMpe1xuXHRcdFx0XHQvLyBJZ25vcmUgb3Vyc2VsdmVzXG5cdFx0XHRcdGlmKG5vZGUgPT09IG90aGVyKSBjb250aW51ZTtcblxuXHRcdFx0XHQvLyBJZ25vcmUgaW5hY3RpdmUgbm9kZXNcblx0XHRcdFx0aWYoIW90aGVyLmFjdGl2ZSkgY29udGludWU7XG5cblx0XHRcdFx0bGV0IGNvbGxpZGVyID0gb3RoZXIuY29sbGlzaW9uU2hhcGUuZ2V0Qm91bmRpbmdSZWN0KCk7XG5cdFx0XHRcdGxldCBhcmVhID0gbm9kZS5zd2VwdFJlY3Qub3ZlcmxhcEFyZWEoY29sbGlkZXIpO1xuXHRcdFx0XHRpZihhcmVhID4gMCl7XG5cdFx0XHRcdFx0Ly8gV2UgaGFkIGEgY29sbGlzaW9uXG5cdFx0XHRcdFx0b3ZlcmxhcHMucHVzaChuZXcgQXJlYUNvbGxpc2lvbihhcmVhLCBjb2xsaWRlciwgb3RoZXIsIFwiR2FtZU5vZGVcIiwgbnVsbCkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIExhc3RseSwgZ2F0aGVyIGEgc2V0IG9mIEFBQkJzIGZyb20gdGhlIHRpbGVtYXAuXG5cdFx0XHQvLyBUaGlzIHN0ZXAgaW52b2x2ZXMgdGhlIG1vc3QgZXh0cmEgd29yaywgc28gaXQgaXMgYWJzdHJhY3RlZCBpbnRvIGEgbWV0aG9kXG5cdFx0XHRmb3IobGV0IHRpbGVtYXAgb2YgdGhpcy50aWxlbWFwcyl7XG5cdFx0XHRcdC8vIElnbm9yZSBpbmFjdGl2ZSB0aWxlbWFwc1xuXHRcdFx0XHRpZighdGlsZW1hcC5hY3RpdmUpIGNvbnRpbnVlO1xuXG5cdFx0XHRcdGlmKHRpbGVtYXAgaW5zdGFuY2VvZiBPcnRob2dvbmFsVGlsZW1hcCl7XG5cdFx0XHRcdFx0dGhpcy5jb2xsaWRlV2l0aE9ydGhvZ29uYWxUaWxlbWFwKG5vZGUsIHRpbGVtYXAsIG92ZXJsYXBzKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTb3J0IHRoZSBvdmVybGFwcyBieSBhcmVhXG5cdFx0XHRvdmVybGFwcyA9IG92ZXJsYXBzLnNvcnQoKGEsIGIpID0+IGIuYXJlYSAtIGEuYXJlYSk7XG5cblx0XHRcdC8vIEtlZXAgdHJhY2sgb2YgaGl0cyB0byB1c2UgbGF0ZXJcblx0XHRcdGxldCBoaXRzID0gW107XG5cblx0XHRcdC8qLS0tLS0tLS0tLSBSRVNPTFVUSU9OIFBIQVNFIC0tLS0tLS0tLS0qL1xuXHRcdFx0Ly8gRm9yIGV2ZXJ5IG92ZXJsYXAsIGRldGVybWluZSBpZiB3ZSBuZWVkIHRvIGNvbGxpZGUgd2l0aCBpdCBhbmQgd2hlblxuXHRcdFx0Zm9yKGxldCBvdmVybGFwIG9mIG92ZXJsYXBzKXtcblx0XHRcdFx0Ly8gSWdub3JlIG5vZGVzIHdlIGRvbid0IGludGVyYWN0IHdpdGhcblx0XHRcdFx0aWYoIGdyb3VwSW5kZXggIT09IC0xICYmIG92ZXJsYXAub3RoZXIuZ3JvdXAgIT09IC0xICYmICgodGhpcy5jb2xsaXNpb25NYXNrc1tncm91cEluZGV4XSAmIG92ZXJsYXAub3RoZXIuZ3JvdXApID09PSAwKSApIGNvbnRpbnVlO1xuXG5cdFx0XHRcdC8vIERvIGEgc3dlcHQgbGluZSB0ZXN0IG9uIHRoZSBzdGF0aWMgQUFCQiB3aXRoIHRoaXMgQUFCQiBzaXplIGFzIHBhZGRpbmcgKHRoaXMgaXMgYmFzaWNhbGx5IHVzaW5nIGEgbWlua293c2tpIHN1bSEpXG5cdFx0XHRcdC8vIFN0YXJ0IHRoZSBzd2VlcCBhdCB0aGUgcG9zaXRpb24gb2YgdGhpcyBub2RlIHdpdGggYSBkZWx0YSBvZiBfdmVsb2NpdHlcblx0XHRcdFx0Y29uc3QgcG9pbnQgPSBub2RlLmNvbGxpc2lvblNoYXBlLmNlbnRlcjtcblx0XHRcdFx0Y29uc3QgZGVsdGEgPSBub2RlLl92ZWxvY2l0eTtcblx0XHRcdFx0Y29uc3QgcGFkZGluZyA9IG5vZGUuY29sbGlzaW9uU2hhcGUuaGFsZlNpemU7XG5cdFx0XHRcdGNvbnN0IG90aGVyQUFCQiA9IG92ZXJsYXAuY29sbGlkZXI7XG5cblxuXHRcdFx0XHRjb25zdCBoaXQgPSBvdGhlckFBQkIuaW50ZXJzZWN0U2VnbWVudChub2RlLmNvbGxpc2lvblNoYXBlLmNlbnRlciwgbm9kZS5fdmVsb2NpdHksIG5vZGUuY29sbGlzaW9uU2hhcGUuaGFsZlNpemUpO1xuXG5cdFx0XHRcdG92ZXJsYXAuaGl0ID0gaGl0O1xuXG5cdFx0XHRcdGlmKGhpdCAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0aGl0cy5wdXNoKGhpdCk7XG5cblx0XHRcdFx0XHQvLyBXZSBnb3QgYSBoaXQsIHJlc29sdmUgd2l0aCB0aGUgdGltZSBpbnNpZGUgb2YgdGhlIGhpdFxuXHRcdFx0XHRcdGxldCB0bmVhcnggPSBoaXQubmVhclRpbWVzLng7XG5cdFx0XHRcdFx0bGV0IHRuZWFyeSA9IGhpdC5uZWFyVGltZXMueTtcblxuXHRcdFx0XHRcdC8vIEFsbG93IGVkZ2UgY2xpcHBpbmcgKGVkZ2Ugb3ZlcmxhcHMgZG9uJ3QgY291bnQsIG9ubHkgYXJlYSBvdmVybGFwcylcblx0XHRcdFx0XHQvLyBJbXBvcnRhbnRseSBkb24ndCBhbGxvdyBib3RoIGNhc2VzIHRvIGJlIHRydWUuIFRoZW4gd2UgY2xpcCB0aHJvdWdoIGNvcm5lcnMuIEZhdm9yIHggdG8gaGVscCBwbGF5ZXJzIGxhbmQganVtcHNcblx0XHRcdFx0XHRpZih0bmVhcnggPCAxLjAgJiYgKHBvaW50LnkgPT09IG90aGVyQUFCQi50b3AgLSBwYWRkaW5nLnkgfHwgcG9pbnQueSA9PT0gb3RoZXJBQUJCLmJvdHRvbSArIHBhZGRpbmcueSkgJiYgZGVsdGEueCAhPT0gMCkge1xuXHRcdFx0XHRcdFx0dG5lYXJ4ID0gMS4wO1xuXHRcdFx0XHRcdH0gZWxzZSBpZih0bmVhcnkgPCAxLjAgJiYgKHBvaW50LnggPT09IG90aGVyQUFCQi5sZWZ0IC0gcGFkZGluZy54IHx8IHBvaW50LnggPT09IG90aGVyQUFCQi5yaWdodCArIHBhZGRpbmcueCkgJiYgZGVsdGEueSAhPT0gMCkge1xuXHRcdFx0XHRcdFx0dG5lYXJ5ID0gMS4wO1xuXHRcdFx0XHRcdH1cblxuXG5cdFx0XHRcdFx0aWYoaGl0Lm5lYXJUaW1lcy54ID49IDAgJiYgaGl0Lm5lYXJUaW1lcy54IDwgMSl7XG5cdFx0XHRcdFx0XHQvLyBBbnkgdGlsZW1hcCBvYmplY3RzIHRoYXQgbWFkZSBpdCBoZXJlIGFyZSBjb2xsaWRhYmxlXG5cdFx0XHRcdFx0XHRpZihvdmVybGFwLnR5cGUgPT09IFwiVGlsZW1hcFwiIHx8IG92ZXJsYXAub3RoZXIuaXNDb2xsaWRhYmxlKXtcblx0XHRcdFx0XHRcdFx0bm9kZS5fdmVsb2NpdHkueCA9IG5vZGUuX3ZlbG9jaXR5LnggKiB0bmVhcng7XG5cdFx0XHRcdFx0XHRcdG5vZGUuaXNDb2xsaWRpbmcgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmKGhpdC5uZWFyVGltZXMueSA+PSAwICYmIGhpdC5uZWFyVGltZXMueSA8IDEpe1xuXHRcdFx0XHRcdFx0Ly8gQW55IHRpbGVtYXAgb2JqZWN0cyB0aGF0IG1hZGUgaXQgaGVyZSBhcmUgY29sbGlkYWJsZVxuXHRcdFx0XHRcdFx0aWYob3ZlcmxhcC50eXBlID09PSBcIlRpbGVtYXBcIiB8fCBvdmVybGFwLm90aGVyLmlzQ29sbGlkYWJsZSl7XG5cdFx0XHRcdFx0XHRcdG5vZGUuX3ZlbG9jaXR5LnkgPSBub2RlLl92ZWxvY2l0eS55ICogdG5lYXJ5O1xuXHRcdFx0XHRcdFx0XHRub2RlLmlzQ29sbGlkaW5nID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0LyotLS0tLS0tLS0tIElORk9STUFUSU9OL1RSSUdHRVIgUEhBU0UgLS0tLS0tLS0tLSovXG5cdFx0XHQvLyBDaGVjayBpZiB3ZSBlbmRlZCB1cCBvbiB0aGUgZ3JvdW5kLCBjZWlsaW5nIG9yIHdhbGxcblx0XHRcdC8vIEFsc28gY2hlY2sgZm9yIHRyaWdnZXJzXG5cdFx0XHRmb3IobGV0IG92ZXJsYXAgb2Ygb3ZlcmxhcHMpe1xuXHRcdFx0XHQvLyBDaGVjayBmb3IgYSB0cmlnZ2VyLiBJZiB3ZSBjYXJlIGFib3V0IHRoZSB0cmlnZ2VyLCByZWFjdFxuXHRcdFx0XHRpZihvdmVybGFwLm90aGVyLmlzVHJpZ2dlciAmJiAob3ZlcmxhcC5vdGhlci50cmlnZ2VyTWFzayAmIG5vZGUuZ3JvdXApICYmIG5vZGUuZ3JvdXAgIT0gLTEpe1xuXHRcdFx0XHRcdC8vIEdldCB0aGUgYml0IHRoYXQgdGhpcyBncm91cCBpcyByZXByZXNlbnRlZCBieVxuXHRcdFx0XHRcdGxldCBpbmRleCA9IE1hdGguZmxvb3IoTWF0aC5sb2cyKG5vZGUuZ3JvdXApKTtcblxuXHRcdFx0XHRcdC8vIEV4dHJhY3QgdGhlIHRyaWdnZXJFbnRlciBldmVudCBuYW1lXG5cdFx0XHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudChvdmVybGFwLm90aGVyLnRyaWdnZXJFbnRlcnNbaW5kZXhdLCB7XG5cdFx0XHRcdFx0XHRub2RlOiAoPEdhbWVOb2RlPm5vZGUpLmlkLFxuXHRcdFx0XHRcdFx0b3RoZXI6ICg8R2FtZU5vZGU+b3ZlcmxhcC5vdGhlcikuaWRcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIElnbm9yZSBjb2xsaXNpb24gc2lkZXMgZm9yIG5vZGVzIHdlIGRvbid0IGludGVyYWN0IHdpdGhcblx0XHRcdFx0aWYoIGdyb3VwSW5kZXggIT09IC0xICYmIG92ZXJsYXAub3RoZXIuZ3JvdXAgIT09IC0xICYmICgodGhpcy5jb2xsaXNpb25NYXNrc1tncm91cEluZGV4XSAmIG92ZXJsYXAub3RoZXIuZ3JvdXApID09PSAwKSkgY29udGludWU7XG5cblx0XHRcdFx0Ly8gT25seSBjaGVjayBmb3IgZGlyZWN0aW9uIGlmIHRoZSBvdmVybGFwIHdhcyBjb2xsaWRhYmxlXG5cdFx0XHRcdGlmKG92ZXJsYXAudHlwZSA9PT0gXCJUaWxlbWFwXCIgfHwgb3ZlcmxhcC5vdGhlci5pc0NvbGxpZGFibGUpe1xuXHRcdFx0XHRcdGxldCBjb2xsaXNpb25TaWRlID0gb3ZlcmxhcC5jb2xsaWRlci50b3VjaGVzQUFCQldpdGhvdXRDb3JuZXJzKG5vZGUuY29sbGlzaW9uU2hhcGUuZ2V0Qm91bmRpbmdSZWN0KCkpO1xuXHRcdFx0XHRcdGlmKGNvbGxpc2lvblNpZGUgIT09IG51bGwpe1xuXHRcdFx0XHRcdFx0Ly8gSWYgd2UgdG91Y2gsIG5vdCBpbmNsdWRpbmcgY29ybmVyIGNhc2VzLCBjaGVjayB0aGUgY29sbGlzaW9uIG5vcm1hbFxuXHRcdFx0XHRcdFx0aWYob3ZlcmxhcC5oaXQgIT09IG51bGwpe1xuXHRcdFx0XHRcdFx0XHQvLyBJZiB3ZSBoaXQgYSB0aWxlbWFwLCBrZWVwIHRyYWNrIG9mIGl0XG5cdFx0XHRcdFx0XHRcdGlmKG92ZXJsYXAudHlwZSA9PSBcIlRpbGVtYXBcIil7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZS5jb2xsaWRlZFdpdGhUaWxlbWFwID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGlmKGNvbGxpc2lvblNpZGUueSA9PT0gLTEpe1xuXHRcdFx0XHRcdFx0XHRcdC8vIE5vZGUgaXMgb24gdG9wIG9mIG92ZXJsYXAsIHNvIG9uR3JvdW5kXG5cdFx0XHRcdFx0XHRcdFx0bm9kZS5vbkdyb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZihjb2xsaXNpb25TaWRlLnkgPT09IDEpe1xuXHRcdFx0XHRcdFx0XHRcdC8vIE5vZGUgaXMgb24gYm90dG9tIG9mIG92ZXJsYXAsIHNvIG9uQ2VpbGluZ1xuXHRcdFx0XHRcdFx0XHRcdG5vZGUub25DZWlsaW5nID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBOb2RlIHdhc24ndCB0b3VjaGluZyBvbiB5LCBzbyBpdCBpcyB0b3VjaGluZyBvbiB4XG5cdFx0XHRcdFx0XHRcdFx0bm9kZS5vbldhbGwgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJlc29sdmUgdGhlIGNvbGxpc2lvbiB3aXRoIHRoZSBub2RlLCBhbmQgbW92ZSBpdFxuXHRcdFx0bm9kZS5maW5pc2hNb3ZlKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEhhbmRsZXMgYSBjb2xsaXNpb24gYmV0d2VlbiB0aGlzIG5vZGUgYW5kIGFuIG9ydGhvZ29uYWwgdGlsZW1hcFxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZVxuXHQgKiBAcGFyYW0gdGlsZW1hcCBUaGUgdGlsZW1hcCB0aGUgbm9kZSBtYXkgYmUgY29sbGlkaW5nIHdpdGhcblx0ICogQHBhcmFtIG92ZXJsYXBzIFRoZSBsaXN0IG9mIG92ZXJsYXBzXG5cdCAqL1xuXHRwcm90ZWN0ZWQgY29sbGlkZVdpdGhPcnRob2dvbmFsVGlsZW1hcChub2RlOiBQaHlzaWNhbCwgdGlsZW1hcDogT3J0aG9nb25hbFRpbGVtYXAsIG92ZXJsYXBzOiBBcnJheTxBcmVhQ29sbGlzaW9uPik6IHZvaWQge1xuXHRcdC8vIEdldCB0aGUgbWluIGFuZCBtYXggeCBhbmQgeSBjb29yZGluYXRlcyBvZiB0aGUgbW92aW5nIG5vZGVcblx0XHRsZXQgbWluID0gbmV3IFZlYzIobm9kZS5zd2VwdFJlY3QubGVmdCwgbm9kZS5zd2VwdFJlY3QudG9wKTtcblx0XHRsZXQgbWF4ID0gbmV3IFZlYzIobm9kZS5zd2VwdFJlY3QucmlnaHQsIG5vZGUuc3dlcHRSZWN0LmJvdHRvbSk7XG5cblx0XHQvLyBDb252ZXJ0IHRoZSBtaW4vbWF4IHgveSB0byB0aGUgbWluIGFuZCBtYXggcm93L2NvbCBpbiB0aGUgdGlsZW1hcCBhcnJheVxuXHRcdGxldCBtaW5JbmRleCA9IHRpbGVtYXAuZ2V0Q29sUm93QXQobWluKTtcblx0XHRsZXQgbWF4SW5kZXggPSB0aWxlbWFwLmdldENvbFJvd0F0KG1heCk7XG5cblx0XHRsZXQgdGlsZVNpemUgPSB0aWxlbWFwLmdldFRpbGVTaXplKCk7XG5cblx0XHQvLyBMb29wIG92ZXIgYWxsIHBvc3NpYmxlIHRpbGVzICh3aGljaCBpc24ndCBtYW55IGluIHRoZSBzY29wZSBvZiB0aGUgdmVsb2NpdHkgcGVyIGZyYW1lKVxuXHRcdGZvcihsZXQgY29sID0gbWluSW5kZXgueDsgY29sIDw9IG1heEluZGV4Lng7IGNvbCsrKXtcblx0XHRcdGZvcihsZXQgcm93ID0gbWluSW5kZXgueTsgcm93IDw9IG1heEluZGV4Lnk7IHJvdysrKXtcblx0XHRcdFx0aWYodGlsZW1hcC5pc1RpbGVDb2xsaWRhYmxlKGNvbCwgcm93KSl7XG5cdFx0XHRcdFx0Ly8gR2V0IHRoZSBwb3NpdGlvbiBvZiB0aGlzIHRpbGVcblx0XHRcdFx0XHRsZXQgdGlsZVBvcyA9IG5ldyBWZWMyKGNvbCAqIHRpbGVTaXplLnggKyB0aWxlU2l6ZS54LzIsIHJvdyAqIHRpbGVTaXplLnkgKyB0aWxlU2l6ZS55LzIpO1xuXG5cdFx0XHRcdFx0Ly8gQ3JlYXRlIGEgbmV3IGNvbGxpZGVyIGZvciB0aGlzIHRpbGVcblx0XHRcdFx0XHRsZXQgY29sbGlkZXIgPSBuZXcgQUFCQih0aWxlUG9zLCB0aWxlU2l6ZS5zY2FsZWQoMS8yKSk7XG5cblx0XHRcdFx0XHQvLyBDYWxjdWxhdGUgY29sbGlzaW9uIGFyZWEgYmV0d2VlbiB0aGUgbm9kZSBhbmQgdGhlIHRpbGVcblx0XHRcdFx0XHRsZXQgYXJlYSA9IG5vZGUuc3dlcHRSZWN0Lm92ZXJsYXBBcmVhKGNvbGxpZGVyKTtcblx0XHRcdFx0XHRpZihhcmVhID4gMCl7XG5cdFx0XHRcdFx0XHQvLyBXZSBoYWQgYSBjb2xsaXNpb25cblx0XHRcdFx0XHRcdG92ZXJsYXBzLnB1c2gobmV3IEFyZWFDb2xsaXNpb24oYXJlYSwgY29sbGlkZXIsIHRpbGVtYXAsIFwiVGlsZW1hcFwiLCBuZXcgVmVjMihjb2wsIHJvdykpKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn0iLCJpbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBSZWNlaXZlciBmcm9tIFwiLi4vRXZlbnRzL1JlY2VpdmVyXCI7XG5pbXBvcnQgRW1pdHRlciBmcm9tIFwiLi4vRXZlbnRzL0VtaXR0ZXJcIjtcbmltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBQaHlzaWNhbCBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUGh5c2ljYWxcIjtcblxuLyoqXG4gKiBBbiBhYnN0cmFjdCBwaHlzaWNzIG1hbmFnZXIuXG4gKiBUaGlzIGNsYXNzIGV4cG9zZXMgZnVuY3Rpb25zIGZvciBzdWJjbGFzc2VzIHRvIGltcGxlbWVudCB0aGF0IHNob3VsZCBhbGxvdyBmb3IgYSB3b3JraW5nIHBoeXNpY3Mgc3lzdGVtIHRvIGJlIGNyZWF0ZWQuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFBoeXNpY3NNYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cdC8qKiBUaGUgZXZlbnQgcmVjZWl2ZXIgZm9yIHRoZSBwaHlzaWNzIHN5c3RlbSAqL1xuXHRwcm90ZWN0ZWQgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuXHQvKiogVGhlIGV2ZW50IGVtaXR0ZXIgZm9yIHRoZSBwaHlzaWNzIHN5c3RlbSAqL1xuXHRwcm90ZWN0ZWQgZW1pdHRlcjogRW1pdHRlcjtcblxuXHQvKiogTWFwcyBsYXllciBuYW1lcyB0byBudW1iZXJzICovXG5cdHByb3RlY3RlZCBncm91cE1hcDogTWFwPG51bWJlcj47XG5cblx0LyoqIE1hcHMgbGF5ZXIgbnVtYmVycyB0byBuYW1lcyAqL1xuXHRwcm90ZWN0ZWQgZ3JvdXBOYW1lczogQXJyYXk8c3RyaW5nPjtcblxuXHQvKiogVGhlIGRlZmF1bHQgZ3JvdXAgbmFtZSAqL1xuXHRwcm90ZWN0ZWQgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfR1JPVVA6IHN0cmluZyA9IFwiRGVmYXVsdFwiO1xuXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuXHRcdHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG5cblx0XHQvLyBUaGUgY3JlYXRpb24gYW5kIGltcGxlbWVudGF0aW9uIG9mIGxheWVycyBpcyBkZWZlcnJlZCB0byB0aGUgc3ViY2xhc3Ncblx0XHR0aGlzLmdyb3VwTWFwID0gbmV3IE1hcCgpO1xuXHRcdHRoaXMuZ3JvdXBOYW1lcyA9IG5ldyBBcnJheSgpO1xuXHR9XG5cblx0ZGVzdHJveSgpOiB2b2lkIHtcblx0XHR0aGlzLnJlY2VpdmVyLmRlc3Ryb3koKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSBnYW1lbm9kZSB3aXRoIHRoaXMgcGh5c2ljcyBtYW5hZ2VyXG5cdCAqIEBwYXJhbSBvYmplY3QgVGhlIG9iamVjdCB0byByZWdpc3RlclxuXHQgKi9cblx0YWJzdHJhY3QgcmVnaXN0ZXJPYmplY3Qob2JqZWN0OiBQaHlzaWNhbCk6IHZvaWQ7XG5cblxuXHQvKipcblx0ICogUmVtb3ZlcyByZWZlcmVuY2VzIHRvIHRoaXMgb2JqZWN0IGZyb20gdGhlIHBoeXNpY3MgbWFuYWdlcnJcblx0ICogQHBhcmFtIG9iamVjdCBUaGUgb2JqZWN0IHRvIGRlcmVnaXN0ZXJcblx0ICovXG5cdGFic3RyYWN0IGRlcmVnaXN0ZXJPYmplY3Qob2JqZWN0OiBQaHlzaWNhbCk6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhIHRpbGVtYXAgd2l0aCB0aGlzIHBoeXNpY3MgbWFuYWdlclxuXHQgKiBAcGFyYW0gdGlsZW1hcCBUaGUgdGlsZW1hcCB0byByZWdpc3RlclxuXHQgKi9cblx0YWJzdHJhY3QgcmVnaXN0ZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHJlZmVyZW5jZXMgdG8gdGhpcyB0aWxlbWFwIGZyb20gdGhlIHBoeXNpY3MgbWFuYWdlcnJcblx0ICogQHBhcmFtIHRpbGVtYXAgVGhlIG9iamVjdCB0byBkZXJlZ2lzdGVyXG5cdCAqL1xuXHRhYnN0cmFjdCBkZXJlZ2lzdGVyVGlsZW1hcCh0aWxlbWFwOiBUaWxlbWFwKTogdm9pZDtcblxuXHRhYnN0cmFjdCB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBwaHlzaWNzIGxheWVyIG9mIHRoZSBHYW1lTm9kZVxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgR2FtZU5vZGVcblx0ICogQHBhcmFtIGdyb3VwIFRoZSBncm91cCB0aGF0IHRoZSBHYW1lTm9kZSBzaG91bGQgYmUgb25cblx0ICovXG5cdHNldEdyb3VwKG5vZGU6IFBoeXNpY2FsLCBncm91cDogc3RyaW5nKTogdm9pZCB7XG5cdFx0bm9kZS5ncm91cCA9IHRoaXMuZ3JvdXBNYXAuZ2V0KGdyb3VwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXRyaWV2ZXMgdGhlIGxheWVyIG51bWJlciBhc3NvY2lhdGVkIHdpdGggdGhlIHByb3ZpZGVkIG5hbWVcblx0ICogQHBhcmFtIGxheWVyIFRoZSBuYW1lIG9mIHRoZSBsYXllclxuXHQgKiBAcmV0dXJucyBUaGUgbGF5ZXIgbnVtYmVyLCBvciAwIGlmIHRoZXJlIGlzIG5vdCBhIGxheWVyIHdpdGggdGhhdCBuYW1lIHJlZ2lzdGVyZWRcblx0ICovXG5cdGdldEdyb3VwTnVtYmVyKGdyb3VwOiBzdHJpbmcpOiBudW1iZXIge1xuXHRcdGlmKHRoaXMuZ3JvdXBNYXAuaGFzKGdyb3VwKSl7XG5cdFx0XHRyZXR1cm4gdGhpcy5ncm91cE1hcC5nZXQoZ3JvdXApO1xuXHRcdH0gZWxzZXtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGFsbCBncm91cCBuYW1lcyBhc3NvY2lhdGVkIHdpdGggdGhlIG51bWJlciBwcm92aWRlZFxuXHQgKiBAcGFyYW0gZ3JvdXBzIEEgbWFzayBvZiBncm91cHNcblx0ICogQHJldHVybnMgQWxsIGdyb3VwcyBjb250YWluZWQgaW4gdGhlIG1hc2tcblx0ICovXG5cdGdldEdyb3VwTmFtZXMoZ3JvdXBzOiBudW1iZXIpOiBBcnJheTxzdHJpbmc+IHtcblx0XHRpZihncm91cHMgPT09IC0xKXtcblx0XHRcdHJldHVybiBbUGh5c2ljc01hbmFnZXIuREVGQVVMVF9HUk9VUF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxldCBnID0gMTtcblx0XHRcdGxldCBuYW1lcyA9IFtdO1xuXG5cdFx0XHRmb3IobGV0IGkgPSAwOyBpIDwgMzI7IGkrKyl7XG5cdFx0XHRcdGlmKGcgJiBncm91cHMpe1xuXHRcdFx0XHRcdC8vIFRoaXMgZ3JvdXAgaXMgaW4gdGhlIGdyb3VwcyBudW1iZXJcblx0XHRcdFx0XHRuYW1lcy5wdXNoKHRoaXMuZ3JvdXBOYW1lc1tpXSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBTaGlmdCB0aGUgYml0IG92ZXJcblx0XHRcdFx0ZyA9IGcgPDwgMTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0iLCJpbXBvcnQgUXVldWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9RdWV1ZVwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuLi9FdmVudHMvRXZlbnRRdWV1ZVwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuXG4vLyBAaWdub3JlUGFnZVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWNvcmRlciB7XG5cdHByaXZhdGUgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuXHRwcml2YXRlIGxvZzogUXVldWU8TG9nSXRlbT47XG5cdHByaXZhdGUgcmVjb3JkaW5nOiBib29sZWFuO1xuXHRwcml2YXRlIGV2ZW50UXVldWU6IEV2ZW50UXVldWU7XG5cdHByaXZhdGUgZnJhbWU6IG51bWJlcjtcblx0cHJpdmF0ZSBwbGF5aW5nOiBib29sZWFuO1xuXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuXHRcdHRoaXMubG9nID0gbmV3IFF1ZXVlKDEwMDApO1xuXHRcdHRoaXMucmVjb3JkaW5nID0gZmFsc2U7XG5cdFx0dGhpcy5wbGF5aW5nID0gZmFsc2U7XG5cdFx0dGhpcy5mcmFtZSA9IDA7XG5cblx0XHR0aGlzLmV2ZW50UXVldWUgPSBFdmVudFF1ZXVlLmdldEluc3RhbmNlKCk7XG5cdFx0dGhpcy5ldmVudFF1ZXVlLnN1YnNjcmliZSh0aGlzLnJlY2VpdmVyLCBcImFsbFwiKTtcblx0fVxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdGlmKHRoaXMucmVjb3JkaW5nKXtcblx0XHRcdHRoaXMuZnJhbWUgKz0gMTtcblx0XHR9XG5cblx0XHRpZih0aGlzLnBsYXlpbmcpe1xuXHRcdFx0Ly8gSWYgcGxheWluZywgaWdub3JlIGV2ZW50cywganVzdCBmZWVkIHRoZSByZWNvcmQgdG8gdGhlIGV2ZW50IHF1ZXVlXG5cdFx0XHR0aGlzLnJlY2VpdmVyLmlnbm9yZUV2ZW50cygpO1xuXG5cdFx0XHQvKlxuXHRcdFx0XHRXaGlsZSB0aGVyZSBpcyBhIG5leHQgaXRlbSwgYW5kIHdoaWxlIGl0IHNob3VsZCBvY2N1ciBpbiB0aGlzIGZyYW1lLFxuXHRcdFx0XHRzZW5kIHRoZSBldmVudC4gaS5lLiwgd2hpbGUgY3VycmVudF9mcmFtZSAqIGN1cnJlbnRfZGVsdGFfdCBpcyBncmVhdGVyXG5cdFx0XHRcdHRoYW4gcmVjb3JkZWRfZnJhbWUgKiByZWNvcmRlZF9kZWx0YV90XG5cdFx0XHQqL1xuXHRcdFx0d2hpbGUodGhpcy5sb2cuaGFzSXRlbXMoKVxuXHRcdFx0XHRcdCYmIHRoaXMubG9nLnBlZWtOZXh0KCkuZnJhbWUgKiB0aGlzLmxvZy5wZWVrTmV4dCgpLmRlbHRhIDwgdGhpcy5mcmFtZSAqIGRlbHRhVCl7XG5cdFx0XHRcdGxldCBldmVudCA9IHRoaXMubG9nLmRlcXVldWUoKS5ldmVudDtcblx0XHRcdFx0Y29uc29sZS5sb2coZXZlbnQpO1xuXHRcdFx0XHR0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZXZlbnQpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZighdGhpcy5sb2cuaGFzSXRlbXMoKSl7XG5cdFx0XHRcdHRoaXMucGxheWluZyA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmZyYW1lICs9IDE7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIElmIG5vdCBwbGF5aW5nLCBoYW5kbGUgZXZlbnRzXG5cdFx0XHR3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcblx0XHRcdFx0bGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcblxuXHRcdFx0XHRpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlNUT1BfUkVDT1JESU5HKXtcblx0XHRcdFx0XHR0aGlzLnJlY29yZGluZyA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYodGhpcy5yZWNvcmRpbmcpe1xuXHRcdFx0XHRcdHRoaXMubG9nLmVucXVldWUobmV3IExvZ0l0ZW0odGhpcy5mcmFtZSwgZGVsdGFULCBldmVudCkpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5TVEFSVF9SRUNPUkRJTkcpe1xuXHRcdFx0XHRcdHRoaXMubG9nLmNsZWFyKCk7XG5cdFx0XHRcdFx0dGhpcy5yZWNvcmRpbmcgPSB0cnVlO1xuXHRcdFx0XHRcdHRoaXMuZnJhbWUgPSAwXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlBMQVlfUkVDT1JESU5HKXtcblx0XHRcdFx0XHR0aGlzLmZyYW1lID0gMDtcblx0XHRcdFx0XHR0aGlzLnJlY29yZGluZyA9IGZhbHNlO1xuXHRcdFx0XHRcdHRoaXMucGxheWluZyA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuY2xhc3MgTG9nSXRlbSB7XG5cdGZyYW1lOiBudW1iZXI7XG5cdGRlbHRhOiBudW1iZXI7XG5cdGV2ZW50OiBHYW1lRXZlbnQ7XG5cblx0Y29uc3RydWN0b3IoZnJhbWU6IG51bWJlciwgZGVsdGFUOiBudW1iZXIsIGV2ZW50OiBHYW1lRXZlbnQpe1xuXHRcdHRoaXMuZnJhbWUgPSBmcmFtZTtcblx0XHR0aGlzLmRlbHRhID0gZGVsdGFUO1xuXHRcdHRoaXMuZXZlbnQgPSBldmVudDtcblx0fVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9NYXBcIjtcblxuLyoqICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBSZWdpc3RyeTxUPiBleHRlbmRzIE1hcDxUPntcblxuICAgIC8qKiBQcmVsb2FkcyByZWdpc3RyeSBkYXRhICovXG4gICAgcHVibGljIGFic3RyYWN0IHByZWxvYWQoKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhbiBpdGVtIGFuZCBwcmVsb2FkcyBhbnkgbmVjZXNzYXJ5IGZpbGVzXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHJlZ2lzdGVyIHRoaXMgaXRlbSB3aXRoXG4gICAgICogQHBhcmFtIGFyZ3MgQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIG5lZWRlZCBmb3IgcmVnaXN0cmF0aW9uXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IHJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oa2V5OiBzdHJpbmcsIC4uLmFyZ3M6IGFueSk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYW4gaXRlbSBhbmQgcHJlbG9hZHMgYW55IG5lY2Vzc2FyeSBmaWxlc1xuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byByZWdpc3RlciB0aGlzIGl0ZW0gd2l0aFxuICAgICAqIEBwYXJhbSBhcmdzIEFueSBhZGl0aW9uYWwgYXJndW1lbnRzIG5lZWRlZCBmb3IgcmVnaXN0cmF0aW9uXG4gICAgICovXG4gICAgcHVibGljIGFic3RyYWN0IHJlZ2lzdGVySXRlbShrZXk6IHN0cmluZywgLi4uYXJnczogYW55KTogdm9pZDtcbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgU2hhZGVyVHlwZSBmcm9tIFwiLi4vLi4vUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVcIjtcbmltcG9ydCBMYWJlbFNoYWRlclR5cGUgZnJvbSBcIi4uLy4uL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9MYWJlbFNoYWRlclR5cGVcIjtcbmltcG9ydCBQb2ludFNoYWRlclR5cGUgZnJvbSBcIi4uLy4uL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9Qb2ludFNoYWRlclR5cGVcIjtcbmltcG9ydCBSZWN0U2hhZGVyVHlwZSBmcm9tIFwiLi4vLi4vUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL1JlY3RTaGFkZXJUeXBlXCI7XG5pbXBvcnQgU3ByaXRlU2hhZGVyVHlwZSBmcm9tIFwiLi4vLi4vUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL1Nwcml0ZVNoYWRlclR5cGVcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBSZWdpc3RyeSBmcm9tIFwiLi9SZWdpc3RyeVwiO1xuXG4vKipcbiAqIEEgcmVnaXN0cnkgdGhhdCBoYW5kbGVzIHNoYWRlcnNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2hhZGVyUmVnaXN0cnkgZXh0ZW5kcyBSZWdpc3RyeTxTaGFkZXJUeXBlPiB7XG5cblx0Ly8gU2hhZGVyIG5hbWVzXG5cdHB1YmxpYyBzdGF0aWMgUE9JTlRfU0hBREVSID0gXCJwb2ludFwiO1xuXHRwdWJsaWMgc3RhdGljIFJFQ1RfU0hBREVSID0gXCJyZWN0XCI7XG5cdHB1YmxpYyBzdGF0aWMgU1BSSVRFX1NIQURFUiA9IFwic3ByaXRlXCI7XG5cdHB1YmxpYyBzdGF0aWMgTEFCRUxfU0hBREVSID0gXCJsYWJlbFwiO1xuXG5cdHByaXZhdGUgcmVnaXN0cnlJdGVtczogQXJyYXk8U2hhZGVyUmVnaXN0cnlJdGVtPiA9IG5ldyBBcnJheSgpO1xuXG5cdC8qKlxuXHQgKiBQcmVsb2FkcyBhbGwgYnVpbHQtaW4gc2hhZGVyc1xuXHQgKi9cblx0cHVibGljIHByZWxvYWQoKXtcblx0XHQvLyBHZXQgdGhlIHJlc291cmNlTWFuYWdlciBhbmQgcXVldWUgYWxsIGJ1aWx0LWluIHNoYWRlcnMgZm9yIHByZWxvYWRpbmdcblx0XHRjb25zdCBybSA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXG5cdFx0Ly8gUXVldWUgYSBsb2FkIGZvciB0aGUgcG9pbnQgc2hhZGVyXG5cdFx0dGhpcy5yZWdpc3RlckFuZFByZWxvYWRJdGVtKFNoYWRlclJlZ2lzdHJ5LlBPSU5UX1NIQURFUiwgUG9pbnRTaGFkZXJUeXBlLCBcImJ1aWx0aW4vc2hhZGVycy9wb2ludC52c2hhZGVyXCIsIFwiYnVpbHRpbi9zaGFkZXJzL3BvaW50LmZzaGFkZXJcIik7XG5cblx0XHQvLyBRdWV1ZSBhIGxvYWQgZm9yIHRoZSByZWN0IHNoYWRlclxuXHRcdHRoaXMucmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShTaGFkZXJSZWdpc3RyeS5SRUNUX1NIQURFUiwgUmVjdFNoYWRlclR5cGUsIFwiYnVpbHRpbi9zaGFkZXJzL3JlY3QudnNoYWRlclwiLCBcImJ1aWx0aW4vc2hhZGVycy9yZWN0LmZzaGFkZXJcIik7XG5cblx0XHQvLyBRdWV1ZSBhIGxvYWQgZm9yIHRoZSBzcHJpdGUgc2hhZGVyXG5cdFx0dGhpcy5yZWdpc3RlckFuZFByZWxvYWRJdGVtKFNoYWRlclJlZ2lzdHJ5LlNQUklURV9TSEFERVIsIFNwcml0ZVNoYWRlclR5cGUsIFwiYnVpbHRpbi9zaGFkZXJzL3Nwcml0ZS52c2hhZGVyXCIsIFwiYnVpbHRpbi9zaGFkZXJzL3Nwcml0ZS5mc2hhZGVyXCIpO1xuXHRcblx0XHQvLyBRdWV1ZSBhIGxvYWQgZm9yIHRoZSBsYWJlbCBzaGFkZXJcblx0XHR0aGlzLnJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oU2hhZGVyUmVnaXN0cnkuTEFCRUxfU0hBREVSLCBMYWJlbFNoYWRlclR5cGUsIFwiYnVpbHRpbi9zaGFkZXJzL2xhYmVsLnZzaGFkZXJcIiwgXCJidWlsdGluL3NoYWRlcnMvbGFiZWwuZnNoYWRlclwiKTtcblxuXHRcdC8vIFF1ZXVlIGEgbG9hZCBmb3IgYW55IHByZWxvYWRlZCBpdGVtc1xuXHRcdGZvcihsZXQgaXRlbSBvZiB0aGlzLnJlZ2lzdHJ5SXRlbXMpe1xuXHRcdFx0Y29uc3Qgc2hhZGVyID0gbmV3IGl0ZW0uY29uc3RyKGl0ZW0ua2V5KTtcblx0XHRcdHNoYWRlci5pbml0QnVmZmVyT2JqZWN0KCk7XG5cdFx0XHR0aGlzLmFkZChpdGVtLmtleSwgc2hhZGVyKTtcblxuXHRcdFx0Ly8gTG9hZCBpZiBkZXNpcmVkXG5cdFx0XHRpZihpdGVtLnByZWxvYWQgIT09IHVuZGVmaW5lZCl7XG5cdFx0XHRcdHJtLnNoYWRlcihpdGVtLmtleSwgaXRlbS5wcmVsb2FkLnZzaGFkZXJMb2NhdGlvbiwgaXRlbS5wcmVsb2FkLmZzaGFkZXJMb2NhdGlvbik7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhIHNoYWRlciBpbiB0aGUgcmVnaXN0cnkgYW5kIGxvYWRzIGl0IGJlZm9yZSB0aGUgZ2FtZSBiZWdpbnNcblx0ICogQHBhcmFtIGtleSBUaGUga2V5IHlvdSB3aXNoIHRvIGFzc2lnbiB0byB0aGUgc2hhZGVyXG5cdCAqIEBwYXJhbSBjb25zdHIgVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBTaGFkZXJUeXBlXG5cdCAqIEBwYXJhbSB2c2hhZGVyTG9jYXRpb24gVGhlIGxvY2F0aW9uIG9mIHRoZSB2ZXJ0ZXggc2hhZGVyXG5cdCAqIEBwYXJhbSBmc2hhZGVyTG9jYXRpb24gdGhlIGxvY2F0aW9uIG9mIHRoZSBmcmFnbWVudCBzaGFkZXJcblx0ICovXG5cdHB1YmxpYyByZWdpc3RlckFuZFByZWxvYWRJdGVtKGtleTogc3RyaW5nLCBjb25zdHI6IG5ldyAocHJvZ3JhbUtleTogc3RyaW5nKSA9PiBTaGFkZXJUeXBlLCB2c2hhZGVyTG9jYXRpb246IHN0cmluZywgZnNoYWRlckxvY2F0aW9uOiBzdHJpbmcpOiB2b2lkIHtcblx0XHRsZXQgc2hhZGVyUHJlbG9hZCA9IG5ldyBTaGFkZXJQcmVsb2FkKCk7XG5cdFx0c2hhZGVyUHJlbG9hZC52c2hhZGVyTG9jYXRpb24gPSB2c2hhZGVyTG9jYXRpb247XG5cdFx0c2hhZGVyUHJlbG9hZC5mc2hhZGVyTG9jYXRpb24gPSBmc2hhZGVyTG9jYXRpb247XG5cblx0XHRsZXQgcmVnaXN0cnlJdGVtID0gbmV3IFNoYWRlclJlZ2lzdHJ5SXRlbSgpO1xuXHRcdHJlZ2lzdHJ5SXRlbS5rZXkgPSBrZXk7XG5cdFx0cmVnaXN0cnlJdGVtLmNvbnN0ciA9IGNvbnN0cjtcblx0XHRyZWdpc3RyeUl0ZW0ucHJlbG9hZCA9IHNoYWRlclByZWxvYWQ7XG5cblx0XHR0aGlzLnJlZ2lzdHJ5SXRlbXMucHVzaChyZWdpc3RyeUl0ZW0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhIHNoYWRlciBpbiB0aGUgcmVnaXN0cnkuIE5PVEU6IElmIHlvdSB1c2UgdGhpcywgeW91IE1VU1QgbG9hZCB0aGUgc2hhZGVyIGJlZm9yZSB1c2UuXG5cdCAqIElmIHlvdSB3aXNoIHRvIHByZWxvYWQgdGhlIHNoYWRlciwgdXNlIHJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oKVxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgeW91IHdpc2ggdG8gYXNzaWduIHRvIHRoZSBzaGFkZXJcblx0ICogQHBhcmFtIGNvbnN0ciBUaGUgY29uc3RydWN0b3Igb2YgdGhlIFNoYWRlclR5cGVcblx0ICovXG5cdHB1YmxpYyByZWdpc3Rlckl0ZW0oa2V5OiBzdHJpbmcsIGNvbnN0cjogbmV3IChwcm9ncmFtS2V5OiBzdHJpbmcpID0+IFNoYWRlclR5cGUpOiB2b2lkIHtcblx0XHRsZXQgcmVnaXN0cnlJdGVtID0gbmV3IFNoYWRlclJlZ2lzdHJ5SXRlbSgpO1xuXHRcdHJlZ2lzdHJ5SXRlbS5rZXkgPSBrZXk7XG5cdFx0cmVnaXN0cnlJdGVtLmNvbnN0ciA9IGNvbnN0cjtcblxuXHRcdHRoaXMucmVnaXN0cnlJdGVtcy5wdXNoKHJlZ2lzdHJ5SXRlbSk7XG5cdH1cbn1cblxuY2xhc3MgU2hhZGVyUmVnaXN0cnlJdGVtIHtcblx0a2V5OiBzdHJpbmc7XG5cdGNvbnN0cjogbmV3IChwcm9ncmFtS2V5OiBzdHJpbmcpID0+IFNoYWRlclR5cGU7XG5cdHByZWxvYWQ6IFNoYWRlclByZWxvYWQ7XG59XG5cbmNsYXNzIFNoYWRlclByZWxvYWQge1xuXHR2c2hhZGVyTG9jYXRpb246IHN0cmluZztcblx0ZnNoYWRlckxvY2F0aW9uOiBzdHJpbmc7XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFJlZ2lzdHJ5IGZyb20gXCIuL1JlZ2lzdHJpZXMvUmVnaXN0cnlcIjtcbmltcG9ydCBTaGFkZXJSZWdpc3RyeSBmcm9tIFwiLi9SZWdpc3RyaWVzL1NoYWRlclJlZ2lzdHJ5XCI7XG5cbi8qKlxuICogVGhlIFJlZ2lzdHJ5IGlzIHRoZSBzeXN0ZW0ncyB3YXkgb2YgY29udmVydGluZyBjbGFzc2VzIGFuZCB0eXBlcyBpbnRvIHN0cmluZ1xuICogcmVwcmVzZW50YXRpb25zIGZvciB1c2UgZWxzZXdoZXJlIGluIHRoZSBhcHBsaWNhdGlvbi5cbiAqIEl0IGFsbG93cyBjbGFzc2VzIHRvIGJlIGFjY2Vzc2VkIHdpdGhvdXQgZXhwbGljaXRseSB1c2luZyBjb25zdHJ1Y3RvcnMgaW4gY29kZSxcbiAqIGFuZCBmb3IgcmVzb3VyY2VzIHRvIGJlIGxvYWRlZCBhdCBHYW1lIGNyZWF0aW9uIHRpbWUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlZ2lzdHJ5TWFuYWdlciB7XG5cblx0cHVibGljIHN0YXRpYyBzaGFkZXJzID0gbmV3IFNoYWRlclJlZ2lzdHJ5KCk7XG5cblx0LyoqIEFkZGl0aW9uYWwgY3VzdG9tIHJlZ2lzdHJpZXMgdG8gYWRkIHRvIHRoZSByZWdpc3RyeSBtYW5hZ2VyICovXG5cdHByb3RlY3RlZCBzdGF0aWMgcmVnaXN0cmllczogTWFwPFJlZ2lzdHJ5PGFueT4+ID0gbmV3IE1hcCgpO1xuXG5cdHN0YXRpYyBwcmVsb2FkKCl7XG5cdFx0dGhpcy5zaGFkZXJzLnByZWxvYWQoKTtcblxuXHRcdHRoaXMucmVnaXN0cmllcy5mb3JFYWNoKChrZXk6IHN0cmluZykgPT4gdGhpcy5yZWdpc3RyaWVzLmdldChrZXkpLnByZWxvYWQoKSk7XG5cdH1cblxuXHRzdGF0aWMgYWRkQ3VzdG9tUmVnaXN0cnkobmFtZTogc3RyaW5nLCByZWdpc3RyeTogUmVnaXN0cnk8YW55Pil7XG5cdFx0dGhpcy5yZWdpc3RyaWVzLmFkZChuYW1lLCByZWdpc3RyeSk7XG5cdH1cblxuXHRzdGF0aWMgZ2V0UmVnaXN0cnkoa2V5OiBzdHJpbmcpe1xuXHRcdHJldHVybiB0aGlzLnJlZ2lzdHJpZXMuZ2V0KGtleSk7XG5cdH1cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgRW1pdHRlciBmcm9tIFwiLi4vLi4vRXZlbnRzL0VtaXR0ZXJcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi8uLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgeyBBbmltYXRpb25EYXRhLCBBbmltYXRpb25TdGF0ZSB9IGZyb20gXCIuL0FuaW1hdGlvblR5cGVzXCI7XG5cbi8qKlxuICogQW4gYW5pbWF0aW9uIG1hbmFnZXIgY2xhc3MgZm9yIGFuIGFuaW1hdGVkIENhbnZhc05vZGUuXG4gKiBUaGlzIGNsYXNzIGtlZXBzIHRyYWNrIG9mIHRoZSBwb3NzaWJsZSBhbmltYXRpb25zLCBhcyB3ZWxsIGFzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBzdGF0ZSxcbiAqIGFuZCBhYnN0cmFjdHMgYWxsIGludGVyYWN0aW9ucyB3aXRoIHBsYXlpbmcsIHBhdXNpbmcsIGFuZCBzdG9wcGluZyBhbmltYXRpb25zIGFzIHdlbGwgYXMgXG4gKiBjcmVhdGluZyBuZXcgYW5pbWF0aW9ucyBmcm9tIHRoZSBDYW52YXNOb2RlLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbmltYXRpb25NYW5hZ2VyIHtcbiAgICAvKiogVGhlIG93bmVyIG9mIHRoaXMgYW5pbWF0aW9uIG1hbmFnZXIgKi9cbiAgICBwcm90ZWN0ZWQgb3duZXI6IENhbnZhc05vZGU7XG4gICAgXG4gICAgLyoqIFRoZSBjdXJyZW50IGFuaW1hdGlvbiBzdGF0ZSBvZiB0aGlzIHNwcml0ZSAqL1xuICAgIHByb3RlY3RlZCBhbmltYXRpb25TdGF0ZTogQW5pbWF0aW9uU3RhdGU7XG5cbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIG9mIHRoaXMgc3ByaXRlICovXG4gICAgcHJvdGVjdGVkIGN1cnJlbnRBbmltYXRpb246IHN0cmluZztcblxuICAgIC8qKiBUaGUgY3VycmVudCBmcmFtZSBvZiB0aGlzIGFuaW1hdGlvbiAqL1xuICAgIHByb3RlY3RlZCBjdXJyZW50RnJhbWU6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgcHJvZ3Jlc3Mgb2YgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIHRocm91Z2ggdGhlIGN1cnJlbnQgZnJhbWUgKi9cbiAgICBwcm90ZWN0ZWQgZnJhbWVQcm9ncmVzczogbnVtYmVyO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIGlzIGxvb3Bpbmcgb3Igbm90ICovXG4gICAgcHJvdGVjdGVkIGxvb3A6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIG1hcCBvZiBhbmltYXRpb25zICovXG4gICAgcHJvdGVjdGVkIGFuaW1hdGlvbnM6IE1hcDxBbmltYXRpb25EYXRhPjtcblxuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgKGlmIGFueSkgdG8gc2VuZCB3aGVuIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBzdG9wcyBwbGF5aW5nLiAqL1xuICAgIHByb3RlY3RlZCBvbkVuZEV2ZW50OiBzdHJpbmc7XG5cbiAgICAvKiogVGhlIGV2ZW50IGVtaXR0ZXIgZm9yIHRoaXMgYW5pbWF0aW9uIG1hbmFnZXIgKi9cbiAgICBwcm90ZWN0ZWQgZW1pdHRlcjogRW1pdHRlcjtcblxuICAgIC8qKiBBIHF1ZXVlZCBhbmltYXRpb24gKi9cbiAgICBwcm90ZWN0ZWQgcGVuZGluZ0FuaW1hdGlvbjogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSBsb29wIHN0YXR1cyBvZiBhIHBlbmRpbmcgYW5pbWF0aW9uICovXG4gICAgcHJvdGVjdGVkIHBlbmRpbmdMb29wOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBvbkVuZCBldmVudCBvZiBhIHBlbmRpbmcgYW5pbWF0aW9uICovXG4gICAgcHJvdGVjdGVkIHBlbmRpbmdPbkVuZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBBbmltYXRpb25NYW5hZ2VyXG4gICAgICogQHBhcmFtIG93bmVyIFRoZSBvd25lciBvZiB0aGUgQW5pbWF0aW9uTWFuYWdlclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG93bmVyOiBDYW52YXNOb2RlKXtcbiAgICAgICAgdGhpcy5vd25lciA9IG93bmVyO1xuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuU1RPUFBFRDtcbiAgICAgICAgdGhpcy5jdXJyZW50QW5pbWF0aW9uID0gXCJcIjtcbiAgICAgICAgdGhpcy5jdXJyZW50RnJhbWUgPSAwO1xuICAgICAgICB0aGlzLmZyYW1lUHJvZ3Jlc3MgPSAwO1xuICAgICAgICB0aGlzLmxvb3AgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hbmltYXRpb25zID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLm9uRW5kRXZlbnQgPSBudWxsO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhbiBhbmltYXRpb24gdG8gdGhpcyBzcHJpdGVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSB1bmlxdWUga2V5IG9mIHRoZSBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBhbmltYXRpb24gZGF0YVxuICAgICAqL1xuICAgIGFkZChrZXk6IHN0cmluZywgYW5pbWF0aW9uOiBBbmltYXRpb25EYXRhKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9ucy5hZGQoa2V5LCBhbmltYXRpb24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGluZGV4IHNwZWNpZmllZCBieSB0aGUgY3VycmVudCBhbmltYXRpb24gYW5kIGN1cnJlbnQgZnJhbWVcbiAgICAgKiBAcmV0dXJucyBUaGUgaW5kZXggaW4gdGhlIGN1cnJlbnQgYW5pbWF0aW9uXG4gICAgICovXG4gICAgZ2V0SW5kZXgoKTogbnVtYmVyIHtcbiAgICAgICAgaWYodGhpcy5hbmltYXRpb25zLmhhcyh0aGlzLmN1cnJlbnRBbmltYXRpb24pKXtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFuaW1hdGlvbnMuZ2V0KHRoaXMuY3VycmVudEFuaW1hdGlvbikuZnJhbWVzW3RoaXMuY3VycmVudEZyYW1lXS5pbmRleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE5vIGN1cnJlbnQgYW5pbWF0aW9uLCB3YXJuIHRoZSB1c2VyXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYEFuaW1hdGlvbiBpbmRleCB3YXMgcmVxdWVzdGVkLCBidXQgdGhlIGN1cnJlbnQgYW5pbWF0aW9uOiAke3RoaXMuY3VycmVudEFuaW1hdGlvbn0gd2FzIGludmFsaWRgKTtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgYW5pbWF0aW9uIGlzIGN1cnJlbnRseSBwbGF5aW5nXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBhbmltYXRpb24gdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBzcGVjaWZpZWQgYW5pbWF0aW9uIGlzIHBsYXlpbmcsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGlzUGxheWluZyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50QW5pbWF0aW9uID09PSBrZXkgJiYgdGhpcy5hbmltYXRpb25TdGF0ZSA9PT0gQW5pbWF0aW9uU3RhdGUuUExBWUlORztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIGluZGV4IGFuZCBhZHZhbmNlcyB0aGUgYW5pbWF0aW9uIGZyYW1lXG4gICAgICogQHJldHVybnMgVGhlIGluZGV4IG9mIHRoZSBhbmltYXRpb24gZnJhbWVcbiAgICAgKi9cbiAgICBnZXRJbmRleEFuZEFkdmFuY2VBbmltYXRpb24oKTogbnVtYmVyIHtcbiAgICAgICAgLy8gSWYgd2UgYXJlbid0IHBsYXlpbmcsIHdlIHdvbid0IGJlIGFkdmFuY2luZyB0aGUgYW5pbWF0aW9uXG4gICAgICAgIGlmKCEodGhpcy5hbmltYXRpb25TdGF0ZSA9PT0gQW5pbWF0aW9uU3RhdGUuUExBWUlORykpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SW5kZXgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMuYW5pbWF0aW9ucy5oYXModGhpcy5jdXJyZW50QW5pbWF0aW9uKSl7XG4gICAgICAgICAgICBsZXQgY3VycmVudEFuaW1hdGlvbiA9IHRoaXMuYW5pbWF0aW9ucy5nZXQodGhpcy5jdXJyZW50QW5pbWF0aW9uKTtcbiAgICAgICAgICAgIGxldCBpbmRleCA9IGN1cnJlbnRBbmltYXRpb24uZnJhbWVzW3RoaXMuY3VycmVudEZyYW1lXS5pbmRleDtcblxuICAgICAgICAgICAgLy8gQWR2YW5jZSB0aGUgYW5pbWF0aW9uXG4gICAgICAgICAgICB0aGlzLmZyYW1lUHJvZ3Jlc3MgKz0gMTtcbiAgICAgICAgICAgIGlmKHRoaXMuZnJhbWVQcm9ncmVzcyA+PSBjdXJyZW50QW5pbWF0aW9uLmZyYW1lc1t0aGlzLmN1cnJlbnRGcmFtZV0uZHVyYXRpb24pe1xuICAgICAgICAgICAgICAgIC8vIFdlIGhhdmUgYmVlbiBvbiB0aGlzIGZyYW1lIGZvciBpdHMgd2hvbGUgZHVyYXRpb24sIGdvIHRvIHRoZSBuZXh0IG9uZVxuICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVQcm9ncmVzcyA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50RnJhbWUgKz0gMTtcblxuICAgICAgICAgICAgICAgIGlmKHRoaXMuY3VycmVudEZyYW1lID49IGN1cnJlbnRBbmltYXRpb24uZnJhbWVzLmxlbmd0aCl7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGhhdmUgcmVhY2hlZCB0aGUgZW5kIG9mIHRoaXMgYW5pbWF0aW9uXG4gICAgICAgICAgICAgICAgICAgIGlmKHRoaXMubG9vcCl7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRGcmFtZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUHJvZ3Jlc3MgPSAwO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmRDdXJyZW50QW5pbWF0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJldHVybiB0aGUgY3VycmVudCBpbmRleFxuICAgICAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm8gY3VycmVudCBhbmltYXRpb24sIGNhbid0IGFkdmFuY2UuIFdhcm4gdGhlIHVzZXJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgQW5pbWF0aW9uIGluZGV4IGFuZCBhZHZhbmNlIHdhcyByZXF1ZXN0ZWQsIGJ1dCB0aGUgY3VycmVudCBhbmltYXRpb24gKCR7dGhpcy5jdXJyZW50QW5pbWF0aW9ufSkgaW4gbm9kZSB3aXRoIGlkOiAke3RoaXMub3duZXIuaWR9IHdhcyBpbnZhbGlkYCk7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBFbmRzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBhbmQgZmlyZXMgYW55IG5lY2Vzc2FyeSBldmVudHMsIGFzIHdlbGwgYXMgc3RhcnRpbmcgYW55IG5ldyBhbmltYXRpb25zICovXG4gICAgcHJvdGVjdGVkIGVuZEN1cnJlbnRBbmltYXRpb24oKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY3VycmVudEZyYW1lID0gMDtcbiAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlNUT1BQRUQ7XG5cbiAgICAgICAgaWYodGhpcy5vbkVuZEV2ZW50ICE9PSBudWxsKXtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQodGhpcy5vbkVuZEV2ZW50LCB7b3duZXI6IHRoaXMub3duZXIuaWQsIGFuaW1hdGlvbjogdGhpcy5jdXJyZW50QW5pbWF0aW9ufSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIHBlbmRpbmcgYW5pbWF0aW9uLCBwbGF5IGl0XG4gICAgICAgIGlmKHRoaXMucGVuZGluZ0FuaW1hdGlvbiAhPT0gbnVsbCl7XG4gICAgICAgICAgICB0aGlzLnBsYXkodGhpcy5wZW5kaW5nQW5pbWF0aW9uLCB0aGlzLnBlbmRpbmdMb29wLCB0aGlzLnBlbmRpbmdPbkVuZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQbGF5cyB0aGUgc3BlY2lmaWVkIGFuaW1hdGlvbi4gRG9lcyBub3QgcmVzdGFydCBpdCBpZiBpdCBpcyBhbHJlYWR5IHBsYXlpbmdcbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBuYW1lIG9mIHRoZSBhbmltYXRpb24gdG8gcGxheVxuICAgICAqIEBwYXJhbSBsb29wIFdoZXRoZXIgb3Igbm90IHRvIGxvb3AgdGhlIGFuaW1hdGlvbi4gRmFsc2UgYnkgZGVmYXVsdFxuICAgICAqIEBwYXJhbSBvbkVuZCBUaGUgbmFtZSBvZiBhbiBldmVudCB0byBzZW5kIHdoZW4gdGhpcyBhbmltYXRpb24gbmF0dXJhbGx5IHN0b3BzIHBsYXlpbmcuIFRoaXMgb25seSBtYXR0ZXJzIGlmIGxvb3AgaXMgZmFsc2UuXG4gICAgICovXG4gICAgcGxheUlmTm90QWxyZWFkeShhbmltYXRpb246IHN0cmluZywgbG9vcD86IGJvb2xlYW4sIG9uRW5kPzogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMuY3VycmVudEFuaW1hdGlvbiAhPT0gYW5pbWF0aW9uKXtcbiAgICAgICAgICAgIHRoaXMucGxheShhbmltYXRpb24sIGxvb3AsIG9uRW5kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBsYXlzIHRoZSBzcGVjaWZpZWQgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIGFuaW1hdGlvbiBUaGUgbmFtZSBvZiB0aGUgYW5pbWF0aW9uIHRvIHBsYXlcbiAgICAgKiBAcGFyYW0gbG9vcCBXaGV0aGVyIG9yIG5vdCB0byBsb29wIHRoZSBhbmltYXRpb24uIEZhbHNlIGJ5IGRlZmF1bHRcbiAgICAgKiBAcGFyYW0gb25FbmQgVGhlIG5hbWUgb2YgYW4gZXZlbnQgdG8gc2VuZCB3aGVuIHRoaXMgYW5pbWF0aW9uIG5hdHVyYWxseSBzdG9wcyBwbGF5aW5nLiBUaGlzIG9ubHkgbWF0dGVycyBpZiBsb29wIGlzIGZhbHNlLlxuICAgICAqL1xuICAgIHBsYXkoYW5pbWF0aW9uOiBzdHJpbmcsIGxvb3A/OiBib29sZWFuLCBvbkVuZD86IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmN1cnJlbnRBbmltYXRpb24gPSBhbmltYXRpb247XG4gICAgICAgIHRoaXMuY3VycmVudEZyYW1lID0gMDtcbiAgICAgICAgdGhpcy5mcmFtZVByb2dyZXNzID0gMDtcbiAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlBMQVlJTkc7XG5cbiAgICAgICAgLy8gSWYgbG9vcCBhcmcgd2FzIHByb3ZpZGVkLCB1c2UgdGhhdFxuICAgICAgICBpZihsb29wICE9PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgdGhpcy5sb29wID0gbG9vcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSwgdXNlIHdoYXQgdGhlIGpzb24gZmlsZSBzcGVjaWZpZWRcbiAgICAgICAgICAgIHRoaXMubG9vcCA9IHRoaXMuYW5pbWF0aW9ucy5nZXQoYW5pbWF0aW9uKS5yZXBlYXQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZihvbkVuZCAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHRoaXMub25FbmRFdmVudCA9IG9uRW5kO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vbkVuZEV2ZW50ID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlc2V0IHBlbmRpbmcgYW5pbWF0aW9uXG4gICAgICAgIHRoaXMucGVuZGluZ0FuaW1hdGlvbiA9IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVldWVzIGEgc2luZ2xlIGFuaW1hdGlvbiB0byBiZSBwbGF5ZWQgYWZ0ZXIgdGhlIGN1cnJlbnQgb25lLiBEb2VzIE5PVCBzdGFjay5cbiAgICAgKiBRdWV1ZWluZyBhZGRpdGlvbmFsIGFuaW1hdGlvbnMgcGFzdCAxIHdpbGwganVzdCByZXBsYWNlIHRoZSBxdWV1ZWQgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIGFuaW1hdGlvbiBUaGUgYW5pbWF0aW9uIHRvIHF1ZXVlXG4gICAgICogQHBhcmFtIGxvb3AgV2hldGhlciBvciBub3QgdGhlIGxvb3AgdGhlIHF1ZXVlZCBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0gb25FbmQgVGhlIGV2ZW50IHRvIGZpcmUgd2hlbiB0aGUgcXVldWVkIGFuaW1hdGlvbiBlbmRzXG4gICAgICovXG4gICAgcXVldWUoYW5pbWF0aW9uOiBzdHJpbmcsIGxvb3A6IGJvb2xlYW4gPSBmYWxzZSwgb25FbmQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wZW5kaW5nQW5pbWF0aW9uID0gYW5pbWF0aW9uO1xuICAgICAgICB0aGlzLnBlbmRpbmdMb29wID0gbG9vcDtcbiAgICAgICAgaWYob25FbmQgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdPbkVuZCA9IG9uRW5kO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nT25FbmQgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFBhdXNlcyB0aGUgY3VycmVudCBhbmltYXRpb24gKi9cbiAgICBwYXVzZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlBBVVNFRDtcbiAgICB9XG5cbiAgICAvKiogUmVzdW1lcyB0aGUgY3VycmVudCBhbmltYXRpb24gaWYgcG9zc2libGUgKi9cbiAgICByZXN1bWUoKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMuYW5pbWF0aW9uU3RhdGUgPT09IEFuaW1hdGlvblN0YXRlLlBBVVNFRCl7XG4gICAgICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuUExBWUlORztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBTdG9wcyB0aGUgY3VycmVudCBhbmltYXRpb24uIFRoZSBhbmltYXRpb24gY2Fubm90IGJlIHJlc3VtZWQgYWZ0ZXIgdGhpcy4gKi9cbiAgICBzdG9wKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuU1RPUFBFRDtcbiAgICB9XG59IiwiaW1wb3J0IHsgVHdlZW5hYmxlUHJvcGVydGllcyB9IGZyb20gXCIuLi8uLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IHsgRWFzZUZ1bmN0aW9uVHlwZSB9IGZyb20gXCIuLi8uLi9VdGlscy9FYXNlRnVuY3Rpb25zXCI7XG5cbi8vIEBpZ25vcmVQYWdlXG5cbmV4cG9ydCBlbnVtIEFuaW1hdGlvblN0YXRlIHtcbiAgICBTVE9QUEVEID0gMCxcbiAgICBQQVVTRUQgPSAxLFxuICAgIFBMQVlJTkcgPSAyLFxufVxuXG5leHBvcnQgY2xhc3MgQW5pbWF0aW9uRGF0YSB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGZyYW1lczogQXJyYXk8e2luZGV4OiBudW1iZXIsIGR1cmF0aW9uOiBudW1iZXJ9PjtcbiAgICByZXBlYXQ6IGJvb2xlYW4gPSBmYWxzZTtcbn1cblxuZXhwb3J0IGNsYXNzIFR3ZWVuRWZmZWN0IHtcbiAgICAvKiogVGhlIHByb3BlcnR5IHRvIHR3ZWVuICovXG4gICAgcHJvcGVydHk6IFR3ZWVuYWJsZVByb3BlcnRpZXM7XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdGhlIFR3ZWVuIHNob3VsZCByZXNldCB0aGUgcHJvcGVydHkgdG8gaXRzIG9yaWdpbmFsIHZhbHVlIGFmdGVyIHBsYXlpbmcgKi9cbiAgICByZXNldE9uQ29tcGxldGU6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIHN0YXJ0aW5nIHZhbHVlIGZvciB0aGUgdHdlZW4gKi9cbiAgICBzdGFydDogYW55O1xuXG4gICAgLyoqIFRoZSBlbmRpbmcgdmFsdWUgZm9yIHRoZSB0d2VlbiAqL1xuICAgIGVuZDogYW55O1xuXG4gICAgLyoqIFRoZSBlYXNlIGZ1bmN0aW9uIHRvIHVzZSAqL1xuICAgIGVhc2U6IEVhc2VGdW5jdGlvblR5cGU7XG5cbiAgICAvKiogRE8gTk9UIE1PRElGWSAtIFRoZSBvcmlnaW5hbCB2YWx1ZSBvZiB0aGUgcHJvcGVydHkgLSBzZXQgYXV0b21hdGljYWxseSAqL1xuICAgIGluaXRpYWxWYWx1ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgVHdlZW5EYXRhIHtcbiAgICAvLyBNZW1iZXJzIGZvciBpbml0aWFsaXphdGlvbiBieSB0aGUgdXNlclxuICAgIC8qKiBUaGUgYW1vdW50IG9mIHRpbWUgaW4gbXMgdG8gd2FpdCBiZWZvcmUgZXhlY3V0aW5nIHRoZSB0d2VlbiAqL1xuICAgIHN0YXJ0RGVsYXk6IG51bWJlcjtcbiAgICAvKiogVGhlIGR1cmF0aW9uIG9mIHRpbWUgb3ZlciB3aGljaCB0aGUgdmFsdWUgd2l0aCBjaGFuZ2UgZnJvbSBzdGFydCB0byBlbmQgKi9cbiAgICBkdXJhdGlvbjogbnVtYmVyO1xuICAgIC8qKiBBbiBhcnJheSBvZiB0aGUgZWZmZWN0cyBvbiB0aGUgcHJvcGVydGllcyBvZiB0aGUgb2JqZWN0ICovXG4gICAgZWZmZWN0czogQXJyYXk8VHdlZW5FZmZlY3Q+O1xuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGlzIHR3ZWVuIHNob3VsZCByZXZlcnNlIGZyb20gZW5kIHRvIHN0YXJ0IGZvciBlYWNoIHByb3BlcnR5IHdoZW4gaXQgZmluaXNoZXMgKi9cbiAgICByZXZlcnNlT25Db21wbGV0ZTogYm9vbGVhbjtcbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyB0d2VlbiBzaG91bGQgbG9vcCB3aGVuIGl0IGNvbXBsZXRlcyAqL1xuICAgIGxvb3A6IGJvb2xlYW47XG4gICAgLyoqIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kIChpZiBhbnkpIHdoZW4gdGhlIHR3ZWVuIGZpbmlzaGVzIHBsYXlpbmcgKi9cbiAgICBvbkVuZDogc3RyaW5nXG5cbiAgICAvKiogRXh0cmEgZGF0YSB0byBiZSBzZW50IHdoZW4gdGhlIG9uRW5kIGV2ZW50IGlzIGZpcmVkLiBLZXlzIHdpdGggdGhlIG5hbWUgJ2tleScgb3IgJ25vZGUnIGFyZSByZXNlcnZlZCBhbmQgY2FuJ3QgYmUgdXNlZCBhcyBuYW1lcyBmb3IgeW91ciBleHRyYSBkYXRhICovXG4gICAgb25FbmREYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIFxuICAgIC8vIE1lbWJlcnMgZm9yIG1hbmFnZW1lbnQgYnkgdGhlIHR3ZWVuIG1hbmFnZXJcbiAgICAvKiogVGhlIHByb2dyZXNzIG9mIHRoaXMgdHdlZW4gdGhyb3VnaCBpdHMgZWZmZWN0cyAqL1xuICAgIHByb2dyZXNzOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIGFtb3VudCBvZiB0aW1lIGluIG1zIHRoYXQgaGFzIHBhc3NlZCBmcm9tIHdoZW4gdGhpcyB0d2VlbiBzdGFydGVkIHJ1bm5pbmcgKi9cbiAgICBlbGFwc2VkVGltZTogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBzdGF0ZSBvZiB0aGlzIHR3ZWVuICovXG4gICAgYW5pbWF0aW9uU3RhdGU6IEFuaW1hdGlvblN0YXRlO1xuXG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgdHdlZW4gaXMgY3VycmVudGx5IHJldmVyc2luZyAqL1xuICAgIHJldmVyc2luZzogYm9vbGVhbjtcbn0iLCJpbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IFBhcnRpY2xlU3lzdGVtIGZyb20gXCIuL1BhcnRpY2xlU3lzdGVtXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBhcnRpY2xlU3lzdGVtTWFuYWdlciBpbXBsZW1lbnRzIFVwZGF0ZWFibGUge1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IFBhcnRpY2xlU3lzdGVtTWFuYWdlciA9IG51bGw7XG4gICAgXG4gICAgcHJvdGVjdGVkIHBhcnRpY2xlU3lzdGVtczogQXJyYXk8UGFydGljbGVTeXN0ZW0+O1xuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnBhcnRpY2xlU3lzdGVtcyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIge1xuICAgICAgICBpZihQYXJ0aWNsZVN5c3RlbU1hbmFnZXIuaW5zdGFuY2UgPT09IG51bGwpe1xuICAgICAgICAgICAgUGFydGljbGVTeXN0ZW1NYW5hZ2VyLmluc3RhbmNlID0gbmV3IFBhcnRpY2xlU3lzdGVtTWFuYWdlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFBhcnRpY2xlU3lzdGVtTWFuYWdlci5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICByZWdpc3RlclBhcnRpY2xlU3lzdGVtKHN5c3RlbTogUGFydGljbGVTeXN0ZW0pe1xuICAgICAgICB0aGlzLnBhcnRpY2xlU3lzdGVtcy5wdXNoKHN5c3RlbSk7XG4gICAgfVxuXG4gICAgZGVyZWdpc3RlclBhcnRpY2xlU3lzdGVtKHN5c3RlbTogUGFydGljbGVTeXN0ZW0pe1xuICAgICAgICBsZXQgaW5kZXggPSB0aGlzLnBhcnRpY2xlU3lzdGVtcy5pbmRleE9mKHN5c3RlbSk7XG4gICAgICAgIHRoaXMucGFydGljbGVTeXN0ZW1zLnNwbGljZShpbmRleCwgMSk7XG4gICAgfVxuXG4gICAgY2xlYXJQYXJ0aWNsZVN5c3RlbXMoKXtcbiAgICAgICAgdGhpcy5wYXJ0aWNsZVN5c3RlbXMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgZm9yKGxldCBwYXJ0aWNsZVN5c3RlbSBvZiB0aGlzLnBhcnRpY2xlU3lzdGVtcyl7XG4gICAgICAgICAgICBwYXJ0aWNsZVN5c3RlbS51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgeyBBbmltYXRpb25TdGF0ZSwgVHdlZW5EYXRhIH0gZnJvbSBcIi4vQW5pbWF0aW9uVHlwZXNcIjtcbmltcG9ydCBFYXNlRnVuY3Rpb25zIGZyb20gXCIuLi8uLi9VdGlscy9FYXNlRnVuY3Rpb25zXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCBUd2Vlbk1hbmFnZXIgZnJvbSBcIi4vVHdlZW5NYW5hZ2VyXCI7XG5pbXBvcnQgRW1pdHRlciBmcm9tIFwiLi4vLi4vRXZlbnRzL0VtaXR0ZXJcIjtcblxuLyoqXG4gKiBBIG1hbmFnZXIgZm9yIHRoZSB0d2VlbnMgb2YgYSBHYW1lTm9kZS5cbiAqIFR3ZWVucyBhcmUgc2hvcnQgYW5pbWF0aW9ucyBwbGF5ZWQgYnkgaW50ZXJwb2xhdGluZyBiZXR3ZWVuIHR3byBwcm9wZXJ0aWVzIHVzaW5nIGFuIGVhc2luZyBmdW5jdGlvbi5cbiAqIEZvciBhIGdvb2QgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIGVhc2luZyBmdW5jdGlvbnMsIGNoZWNrIG91dCBAbGluayhodHRwczovL2Vhc2luZ3MubmV0LykoaHR0cHM6Ly9lYXNpbmdzLm5ldC8pLlxuICogTXVsdGlwbGUgdHdlZW4gY2FuIGJlIHBsYXllZCBhdCB0aGUgc2FtZSB0aW1lLCBhcyBsb25nIGFzIHRoZXkgZG9uJ3QgY2hhbmdlIHRoZSBzYW1lIHByb3BlcnR5LlxuICogVGhpcyBhbGxvd3MgZm9yIHNvbWUgaW50ZXJlc3RpbmcgcG9saXNoZXMgb3IgYW5pbWF0aW9ucyB0aGF0IG1heSBiZSB2ZXJ5IGRpZmZpY3VsdCB0byBkbyB3aXRoIHNwcml0ZSB3b3JrIGFsb25lXG4gKiAtIGVzcGVjaWFsbHkgcGl4ZWwgYXJ0IChzdWNoIGFzIHJvdGF0aW9ucyBvciBzY2FsaW5nKS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVHdlZW5Db250cm9sbGVyIHtcbiAgICAvKiogVGhlIEdhbWVOb2RlIHRoaXMgVHdlZW5Db250cm9sbGVyIGFjdHMgdXBvbiAqL1xuICAgIHByb3RlY3RlZCBvd25lcjogR2FtZU5vZGU7XG4gICAgLyoqIFRoZSBsaXN0IG9mIGNyZWF0ZWQgdHdlZW5zICovXG4gICAgcHJvdGVjdGVkIHR3ZWVuczogTWFwPFR3ZWVuRGF0YT47XG4gICAgLyoqIEFuIGV2ZW50IGVtaXR0ZXIgKi9cbiAgICBwcm90ZWN0ZWQgZW1pdHRlcjogRW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgVHdlZW5Db250cm9sbGVyXG4gICAgICogQHBhcmFtIG93bmVyIFRoZSBvd25lciBvZiB0aGUgVHdlZW5Db250cm9sbGVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3duZXI6IEdhbWVOb2RlKXtcbiAgICAgICAgdGhpcy5vd25lciA9IG93bmVyO1xuICAgICAgICB0aGlzLnR3ZWVucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcblxuICAgICAgICAvLyBHaXZlIG91cnNlbHZlcyB0byB0aGUgVHdlZW5NYW5hZ2VyXG4gICAgICAgIFR3ZWVuTWFuYWdlci5nZXRJbnN0YW5jZSgpLnJlZ2lzdGVyVHdlZW5Db250cm9sbGVyKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlc3Ryb3lzIHRoaXMgVHdlZW5Db250cm9sbGVyXG4gICAgICovXG4gICAgZGVzdHJveSgpe1xuICAgICAgICAvLyBPbmx5IHRoZSBnYW1lbm9kZSBhbmQgdGhlIHR3ZWVuIG1hbmFnZXIgc2hvdWxkIGhhdmUgYSByZWZlcmVuY2UgdG8gdGhpc1xuICAgICAgICBkZWxldGUgdGhpcy5vd25lci50d2VlbnM7XG4gICAgICAgIFR3ZWVuTWFuYWdlci5nZXRJbnN0YW5jZSgpLmRlcmVnaXN0ZXJUd2VlbkNvbnRyb2xsZXIodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgdHdlZW4gdG8gdGhpcyBnYW1lIG5vZGVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBuYW1lIG9mIHRoZSB0d2VlblxuICAgICAqIEBwYXJhbSB0d2VlbiBUaGUgZGF0YSBvZiB0aGUgdHdlZW5cbiAgICAgKi9cbiAgICBhZGQoa2V5OiBzdHJpbmcsIHR3ZWVuOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgVHdlZW5EYXRhKTogdm9pZCB7XG4gICAgICAgIGxldCB0eXBlZFR3ZWVuID0gPFR3ZWVuRGF0YT50d2VlbjtcblxuICAgICAgICAvLyBJbml0aWFsaXplIG1lbWJlcnMgdGhhdCB3ZSBuZWVkIChhbmQgdGhlIHVzZXIgZGlkbid0IHByb3ZpZGUpXG4gICAgICAgIHR5cGVkVHdlZW4ucHJvZ3Jlc3MgPSAwO1xuICAgICAgICB0eXBlZFR3ZWVuLmVsYXBzZWRUaW1lID0gMDtcbiAgICAgICAgdHlwZWRUd2Vlbi5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlNUT1BQRUQ7XG5cbiAgICAgICAgdGhpcy50d2VlbnMuYWRkKGtleSwgdHlwZWRUd2Vlbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheSBhIHR3ZWVuIHdpdGggYSBjZXJ0YWluIG5hbWVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBuYW1lIG9mIHRoZSB0d2VlbiB0byBwbGF5XG4gICAgICogQHBhcmFtIGxvb3AgV2hldGhlciBvciBub3QgdGhlIHR3ZWVuIHNob3VsZCBsb29wXG4gICAgICovXG4gICAgcGxheShrZXk6IHN0cmluZywgbG9vcD86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy50d2VlbnMuaGFzKGtleSkpe1xuICAgICAgICAgICAgbGV0IHR3ZWVuID0gdGhpcy50d2VlbnMuZ2V0KGtleSk7XG5cbiAgICAgICAgICAgIC8vIFNldCBsb29wIGlmIG5lZWRlZFxuICAgICAgICAgICAgaWYobG9vcCAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICB0d2Vlbi5sb29wID0gbG9vcDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2V0IHRoZSBpbml0aWFsIHZhbHVlc1xuICAgICAgICAgICAgZm9yKGxldCBlZmZlY3Qgb2YgdHdlZW4uZWZmZWN0cyl7XG4gICAgICAgICAgICAgICAgaWYoZWZmZWN0LnJlc2V0T25Db21wbGV0ZSl7XG4gICAgICAgICAgICAgICAgICAgIGVmZmVjdC5pbml0aWFsVmFsdWUgPSB0aGlzLm93bmVyW2VmZmVjdC5wcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTdGFydCB0aGUgdHdlZW4gcnVubmluZ1xuICAgICAgICAgICAgdHdlZW4uYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HO1xuICAgICAgICAgICAgdHdlZW4uZWxhcHNlZFRpbWUgPSAwO1xuICAgICAgICAgICAgdHdlZW4ucHJvZ3Jlc3MgPSAwO1xuICAgICAgICAgICAgdHdlZW4ucmV2ZXJzaW5nID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYFRyaWVkIHRvIHBsYXkgdHdlZW4gXCIke2tleX1cIiBvbiBub2RlIHdpdGggaWQgJHt0aGlzLm93bmVyLmlkfSwgYnV0IG5vIHN1Y2ggdHdlZW4gZXhpc3RzYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMgYSBwbGF5aW5nIHR3ZWVuLiBEb2VzIG5vdCBhZmZlY3QgdHdlZW5zIHRoYXQgYXJlIHN0b3BwZWQuXG4gICAgICogQHBhcmFtIGtleSBUaGUgbmFtZSBvZiB0aGUgdHdlZW4gdG8gcGF1c2UuXG4gICAgICovXG4gICAgcGF1c2Uoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy50d2VlbnMuaGFzKGtleSkpe1xuICAgICAgICAgICAgdGhpcy50d2VlbnMuZ2V0KGtleSkuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5QQVVTRUQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXN1bWVzIGEgcGF1c2VkIHR3ZWVuLlxuICAgICAqIEBwYXJhbSBrZXkgVGhlIG5hbWUgb2YgdGhlIHR3ZWVuIHRvIHJlc3VtZVxuICAgICAqL1xuICAgIHJlc3VtZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLnR3ZWVucy5oYXMoa2V5KSl7XG4gICAgICAgICAgICBsZXQgdHdlZW4gPSB0aGlzLnR3ZWVucy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmKHR3ZWVuLmFuaW1hdGlvblN0YXRlID09PSBBbmltYXRpb25TdGF0ZS5QQVVTRUQpXG4gICAgICAgICAgICAgICAgdHdlZW4uYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RvcHMgYSBjdXJyZW50bHkgcGxheWluZyB0d2VlblxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgdHdlZW5cbiAgICAgKi9cbiAgICBzdG9wKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMudHdlZW5zLmhhcyhrZXkpKXtcbiAgICAgICAgICAgIGxldCB0d2VlbiA9IHRoaXMudHdlZW5zLmdldChrZXkpO1xuICAgICAgICAgICAgdHdlZW4uYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5TVE9QUEVEO1xuXG4gICAgICAgICAgICAvLyBSZXR1cm4gdG8gdGhlIGluaXRpYWwgdmFsdWVzXG4gICAgICAgICAgICBmb3IobGV0IGVmZmVjdCBvZiB0d2Vlbi5lZmZlY3RzKXtcbiAgICAgICAgICAgICAgICBpZihlZmZlY3QucmVzZXRPbkNvbXBsZXRlKXtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vd25lcltlZmZlY3QucHJvcGVydHldID0gZWZmZWN0LmluaXRpYWxWYWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgbmF0dXJhbCBzdG9wIG9mIGEgY3VycmVudGx5IHBsYXlpbmcgdHdlZW5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHR3ZWVuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGVuZChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLnN0b3Aoa2V5KTtcbiAgICAgICAgaWYodGhpcy50d2VlbnMuaGFzKGtleSkpe1xuICAgICAgICAgICAgLy8gR2V0IHRoZSB0d2VlblxuICAgICAgICAgICAgbGV0IHR3ZWVuID0gdGhpcy50d2VlbnMuZ2V0KGtleSk7XG5cbiAgICAgICAgICAgIC8vIElmIGl0IGhhcyBhbiBvbkVuZCwgc2VuZCBhbiBldmVudFxuICAgICAgICAgICAgaWYodHdlZW4ub25FbmQpe1xuICAgICAgICAgICAgICAgIGxldCBkYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge2tleToga2V5LCBub2RlOiB0aGlzLm93bmVyLmlkfVxuICAgICAgICAgICAgICAgIC8vIElmIGl0IGhhcyBvbkVuZCBldmVudCBkYXRhLCBhZGQgZWFjaCBlbnRyeSwgYXMgbG9uZyBhcyB0aGUga2V5IGlzIG5vdCBuYW1lZCAna2V5JyBvciAnbm9kZSdcbiAgICAgICAgICAgICAgICBpZiAodHdlZW4ub25FbmREYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHR3ZWVuLm9uRW5kRGF0YSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJrZXlcIiAmJiBrZXkgIT09IFwibm9kZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtrZXldID0gdHdlZW4ub25FbmREYXRhW2tleV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQodHdlZW4ub25FbmQsIGRhdGEpOyBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0b3BzIGFsbCBjdXJyZW50bHkgcGxheWluZyB0d2VlbnNcbiAgICAgKi9cbiAgICBzdG9wQWxsKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnR3ZWVucy5mb3JFYWNoKGtleSA9PiB0aGlzLnN0b3Aoa2V5KSk7XG4gICAgfVxuICAgIFxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnR3ZWVucy5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICBsZXQgdHdlZW4gPSB0aGlzLnR3ZWVucy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmKHR3ZWVuLmFuaW1hdGlvblN0YXRlID09PSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HKXtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHByb2dyZXNzIG9mIHRoZSB0d2VlblxuICAgICAgICAgICAgICAgIHR3ZWVuLmVsYXBzZWRUaW1lICs9IGRlbHRhVCoxMDAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgd2UncmUgcGFzdCB0aGUgc3RhcnREZWxheSwgZG8gdGhlIHR3ZWVuXG4gICAgICAgICAgICAgICAgaWYodHdlZW4uZWxhcHNlZFRpbWUgPj0gdHdlZW4uc3RhcnREZWxheSl7XG4gICAgICAgICAgICAgICAgICAgIGlmKCF0d2Vlbi5yZXZlcnNpbmcgJiYgdHdlZW4uZWxhcHNlZFRpbWUgPj0gdHdlZW4uc3RhcnREZWxheSArIHR3ZWVuLmR1cmF0aW9uKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlJ3JlIG92ZXIgdGltZSwgc3RvcCB0aGUgdHdlZW4sIGxvb3AsIG9yIHJldmVyc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHR3ZWVuLnJldmVyc2VPbkNvbXBsZXRlKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSdyZSBvdmVyIHRpbWUgYW5kIGNhbiByZXZlcnNlLCBkbyBzb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR3ZWVuLnJldmVyc2luZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYodHdlZW4ubG9vcCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UgY2FuJ3QgcmV2ZXJzZSBhbmQgY2FuIGxvb3AsIGRvIHNvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHdlZW4uZWxhcHNlZFRpbWUgLT0gdHdlZW4uZHVyYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZW4ndCBsb29waW5nIGFuZCBjYW4ndCByZXZlcnNlLCBzbyBzdG9wXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmQoa2V5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGZvciB0aGUgZW5kIG9mIHJldmVyc2luZ1xuICAgICAgICAgICAgICAgICAgICBpZih0d2Vlbi5yZXZlcnNpbmcgJiYgdHdlZW4uZWxhcHNlZFRpbWUgPj0gdHdlZW4uc3RhcnREZWxheSArIDIqdHdlZW4uZHVyYXRpb24pe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodHdlZW4ubG9vcCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHdlZW4ucmV2ZXJzaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHdlZW4uZWxhcHNlZFRpbWUgLT0gMip0d2Vlbi5kdXJhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmQoa2V5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcHJvZ3Jlc3MsIG1ha2Ugc3VyZSBpdCBpcyBiZXR3ZWVuIDAgYW5kIDEuIEVycm9ycyBmcm9tIHRoaXMgc2hvdWxkIG5ldmVyIGJlIGxhcmdlXG4gICAgICAgICAgICAgICAgICAgIGlmKHR3ZWVuLnJldmVyc2luZyl7XG4gICAgICAgICAgICAgICAgICAgICAgICB0d2Vlbi5wcm9ncmVzcyA9IE1hdGhVdGlscy5jbGFtcDAxKCgyKnR3ZWVuLmR1cmF0aW9uIC0gKHR3ZWVuLmVsYXBzZWRUaW1lLSB0d2Vlbi5zdGFydERlbGF5KSkvdHdlZW4uZHVyYXRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHdlZW4ucHJvZ3Jlc3MgPSBNYXRoVXRpbHMuY2xhbXAwMSgodHdlZW4uZWxhcHNlZFRpbWUgLSB0d2Vlbi5zdGFydERlbGF5KS90d2Vlbi5kdXJhdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGVmZmVjdCBvZiB0d2Vlbi5lZmZlY3RzKXtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSB2YWx1ZSBmcm9tIHRoZSBlYXNlIGZ1bmN0aW9uIHRoYXQgY29ycmVzcG9uZHMgdG8gb3VyIHByb2dyZXNzXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZWFzZSA9IEVhc2VGdW5jdGlvbnNbZWZmZWN0LmVhc2VdKHR3ZWVuLnByb2dyZXNzKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSB2YWx1ZSB0byBsZXJwIHRoZSBwcm9wZXJ0eVxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gTWF0aFV0aWxzLmxlcnAoZWZmZWN0LnN0YXJ0LCBlZmZlY3QuZW5kLCBlYXNlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXNzaWduIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHlcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3duZXJbZWZmZWN0LnByb3BlcnR5XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59IiwiaW1wb3J0IFVwZGF0ZWFibGUgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1VwZGF0ZWFibGVcIjtcbmltcG9ydCBUd2VlbkNvbnRyb2xsZXIgZnJvbSBcIi4vVHdlZW5Db250cm9sbGVyXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFR3ZWVuTWFuYWdlciBpbXBsZW1lbnRzIFVwZGF0ZWFibGUge1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IFR3ZWVuTWFuYWdlciA9IG51bGw7XG4gICAgXG4gICAgcHJvdGVjdGVkIHR3ZWVuQ29udHJvbGxlcnM6IEFycmF5PFR3ZWVuQ29udHJvbGxlcj47XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMudHdlZW5Db250cm9sbGVycyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBUd2Vlbk1hbmFnZXIge1xuICAgICAgICBpZihUd2Vlbk1hbmFnZXIuaW5zdGFuY2UgPT09IG51bGwpe1xuICAgICAgICAgICAgVHdlZW5NYW5hZ2VyLmluc3RhbmNlID0gbmV3IFR3ZWVuTWFuYWdlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFR3ZWVuTWFuYWdlci5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICByZWdpc3RlclR3ZWVuQ29udHJvbGxlcihjb250cm9sbGVyOiBUd2VlbkNvbnRyb2xsZXIpe1xuICAgICAgICB0aGlzLnR3ZWVuQ29udHJvbGxlcnMucHVzaChjb250cm9sbGVyKTtcbiAgICB9XG5cbiAgICBkZXJlZ2lzdGVyVHdlZW5Db250cm9sbGVyKGNvbnRyb2xsZXI6IFR3ZWVuQ29udHJvbGxlcil7XG4gICAgICAgIGxldCBpbmRleCA9IHRoaXMudHdlZW5Db250cm9sbGVycy5pbmRleE9mKGNvbnRyb2xsZXIpO1xuICAgICAgICB0aGlzLnR3ZWVuQ29udHJvbGxlcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG5cbiAgICBjbGVhclR3ZWVuQ29udHJvbGxlcnMoKXtcbiAgICAgICAgdGhpcy50d2VlbkNvbnRyb2xsZXJzID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGZvcihsZXQgdHdlZW5Db250cm9sbGVyIG9mIHRoaXMudHdlZW5Db250cm9sbGVycyl7XG4gICAgICAgICAgICB0d2VlbkNvbnRyb2xsZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgVUlFbGVtZW50IGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRcIjtcbmltcG9ydCBVSUxheWVyIGZyb20gXCIuLi9TY2VuZS9MYXllcnMvVUlMYXllclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IEdyYXBoaWNSZW5kZXJlciBmcm9tIFwiLi9DYW52YXNSZW5kZXJpbmcvR3JhcGhpY1JlbmRlcmVyXCI7XG5pbXBvcnQgUmVuZGVyaW5nTWFuYWdlciBmcm9tIFwiLi9SZW5kZXJpbmdNYW5hZ2VyXCJcbmltcG9ydCBUaWxlbWFwUmVuZGVyZXIgZnJvbSBcIi4vQ2FudmFzUmVuZGVyaW5nL1RpbGVtYXBSZW5kZXJlclwiO1xuaW1wb3J0IFVJRWxlbWVudFJlbmRlcmVyIGZyb20gXCIuL0NhbnZhc1JlbmRlcmluZy9VSUVsZW1lbnRSZW5kZXJlclwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgQnV0dG9uIGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvblwiO1xuaW1wb3J0IFNsaWRlciBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50cy9TbGlkZXJcIjtcbmltcG9ydCBUZXh0SW5wdXQgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudHMvVGV4dElucHV0XCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IExpbmUgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL0xpbmVcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vRGVidWcvRGVidWdcIjtcblxuLyoqXG4gKiBBbiBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgUmVuZGVyaW5nTWFuYWdlciBjbGFzcyB1c2luZyBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhbnZhc1JlbmRlcmVyIGV4dGVuZHMgUmVuZGVyaW5nTWFuYWdlciB7XG4gICAgcHJvdGVjdGVkIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuICAgIHByb3RlY3RlZCBncmFwaGljUmVuZGVyZXI6IEdyYXBoaWNSZW5kZXJlcjtcbiAgICBwcm90ZWN0ZWQgdGlsZW1hcFJlbmRlcmVyOiBUaWxlbWFwUmVuZGVyZXI7XG4gICAgcHJvdGVjdGVkIHVpRWxlbWVudFJlbmRlcmVyOiBVSUVsZW1lbnRSZW5kZXJlcjtcblxuICAgIHByb3RlY3RlZCBvcmlnaW46IFZlYzI7XG4gICAgcHJvdGVjdGVkIHpvb206IG51bWJlcjtcblxuICAgIHByb3RlY3RlZCB3b3JsZFNpemU6IFZlYzI7XG5cbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICBzdXBlcigpO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHNldFNjZW5lKHNjZW5lOiBTY2VuZSl7XG4gICAgICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICAgICAgdGhpcy5ncmFwaGljUmVuZGVyZXIuc2V0U2NlbmUoc2NlbmUpO1xuICAgICAgICB0aGlzLnRpbGVtYXBSZW5kZXJlci5zZXRTY2VuZShzY2VuZSk7XG4gICAgICAgIHRoaXMudWlFbGVtZW50UmVuZGVyZXIuc2V0U2NlbmUoc2NlbmUpO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGluaXRpYWxpemVDYW52YXMoY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQge1xuICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcblxuICAgICAgICB0aGlzLndvcmxkU2l6ZSA9IG5ldyBWZWMyKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuY3R4ID0gY2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcblxuICAgICAgICB0aGlzLmdyYXBoaWNSZW5kZXJlciA9IG5ldyBHcmFwaGljUmVuZGVyZXIodGhpcy5jdHgpO1xuICAgICAgICB0aGlzLnRpbGVtYXBSZW5kZXJlciA9IG5ldyBUaWxlbWFwUmVuZGVyZXIodGhpcy5jdHgpO1xuICAgICAgICB0aGlzLnVpRWxlbWVudFJlbmRlcmVyID0gbmV3IFVJRWxlbWVudFJlbmRlcmVyKHRoaXMuY3R4KVxuXG4gICAgICAgIC8vIEZvciBjcmlzcCBwaXhlbCBhcnRcbiAgICAgICAgdGhpcy5jdHguaW1hZ2VTbW9vdGhpbmdFbmFibGVkID0gZmFsc2U7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY3R4O1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHJlbmRlcih2aXNpYmxlU2V0OiBDYW52YXNOb2RlW10sIHRpbGVtYXBzOiBUaWxlbWFwW10sIHVpTGF5ZXJzOiBNYXA8VUlMYXllcj4pOiB2b2lkIHtcbiAgICAgICAgLy8gU29ydCBieSBkZXB0aCwgdGhlbiBieSB2aXNpYmxlIHNldCBieSB5LXZhbHVlXG4gICAgICAgIHZpc2libGVTZXQuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgaWYoYS5nZXRMYXllcigpLmdldERlcHRoKCkgPT09IGIuZ2V0TGF5ZXIoKS5nZXREZXB0aCgpKXtcbiAgICAgICAgICAgICAgICByZXR1cm4gKGEuYm91bmRhcnkuYm90dG9tKSAtIChiLmJvdW5kYXJ5LmJvdHRvbSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBhLmdldExheWVyKCkuZ2V0RGVwdGgoKSAtIGIuZ2V0TGF5ZXIoKS5nZXREZXB0aCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBsZXQgdGlsZW1hcEluZGV4ID0gMDtcbiAgICAgICAgbGV0IHRpbGVtYXBMZW5ndGggPSB0aWxlbWFwcy5sZW5ndGg7XG5cbiAgICAgICAgbGV0IHZpc2libGVTZXRJbmRleCA9IDA7XG4gICAgICAgIGxldCB2aXNpYmxlU2V0TGVuZ3RoID0gdmlzaWJsZVNldC5sZW5ndGg7XG5cbiAgICAgICAgd2hpbGUodGlsZW1hcEluZGV4IDwgdGlsZW1hcExlbmd0aCB8fCB2aXNpYmxlU2V0SW5kZXggPCB2aXNpYmxlU2V0TGVuZ3RoKXtcbiAgICAgICAgICAgIC8vIENoZWNrIGNvbmRpdGlvbnMgd2hlcmUgd2UndmUgYWxyZWFkeSByZWFjaGVkIHRoZSBlZGdlIG9mIG9uZSBsaXN0XG4gICAgICAgICAgICBpZih0aWxlbWFwSW5kZXggPj0gdGlsZW1hcExlbmd0aCl7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW5kZXIgdGhlIHJlbWFpbmluZyB2aXNpYmxlIHNldFxuICAgICAgICAgICAgICAgIGxldCBub2RlID0gdmlzaWJsZVNldFt2aXNpYmxlU2V0SW5kZXgrK107XG4gICAgICAgICAgICAgICAgaWYobm9kZS52aXNpYmxlKXtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJOb2RlKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYodmlzaWJsZVNldEluZGV4ID49IHZpc2libGVTZXRMZW5ndGgpe1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVuZGVyIHRpbGVtYXBzXG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJUaWxlbWFwKHRpbGVtYXBzW3RpbGVtYXBJbmRleCsrXSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJlbmRlciB3aGljaGV2ZXIgaXMgZnVydGhlciBkb3duXG4gICAgICAgICAgICBpZih0aWxlbWFwc1t0aWxlbWFwSW5kZXhdLmdldExheWVyKCkuZ2V0RGVwdGgoKSA8PSB2aXNpYmxlU2V0W3Zpc2libGVTZXRJbmRleF0uZ2V0TGF5ZXIoKS5nZXREZXB0aCgpKXtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclRpbGVtYXAodGlsZW1hcHNbdGlsZW1hcEluZGV4KytdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IG5vZGUgPSB2aXNpYmxlU2V0W3Zpc2libGVTZXRJbmRleCsrXTtcbiAgICAgICAgICAgICAgICBpZihub2RlLnZpc2libGUpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlck5vZGUobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVuZGVyIHRoZSB1aUxheWVycyBvbiB0b3Agb2YgZXZlcnl0aGluZyBlbHNlXG4gICAgICAgIGxldCBzb3J0ZWRVSUxheWVycyA9IG5ldyBBcnJheTxVSUxheWVyPigpO1xuXG4gICAgICAgIHVpTGF5ZXJzLmZvckVhY2goa2V5ID0+IHNvcnRlZFVJTGF5ZXJzLnB1c2godWlMYXllcnMuZ2V0KGtleSkpKTtcblxuICAgICAgICBzb3J0ZWRVSUxheWVycyA9IHNvcnRlZFVJTGF5ZXJzLnNvcnQoKHVpMSwgdWkyKSA9PiB1aTEuZ2V0RGVwdGgoKSAtIHVpMi5nZXREZXB0aCgpKTtcblxuICAgICAgICBzb3J0ZWRVSUxheWVycy5mb3JFYWNoKHVpTGF5ZXIgPT4ge1xuXHRcdFx0aWYoIXVpTGF5ZXIuaXNIaWRkZW4oKSlcblx0XHRcdFx0dWlMYXllci5nZXRJdGVtcygpLmZvckVhY2gobm9kZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCg8Q2FudmFzTm9kZT5ub2RlKS52aXNpYmxlKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyTm9kZSg8Q2FudmFzTm9kZT5ub2RlKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcblx0XHR9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgc3BlY2lmaWVkIENhbnZhc05vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgQ2FudmFzTm9kZSB0byByZW5kZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVuZGVyTm9kZShub2RlOiBDYW52YXNOb2RlKTogdm9pZCB7XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgb3JpZ2luIG9mIHRoZSB2aWV3cG9ydCBhY2NvcmRpbmcgdG8gdGhpcyBzcHJpdGVcbiAgICAgICAgdGhpcy5vcmlnaW4gPSB0aGlzLnNjZW5lLmdldFZpZXdUcmFuc2xhdGlvbihub2RlKTtcblxuICAgICAgICAvLyBHZXQgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHNjZW5lXG4gICAgICAgIHRoaXMuem9vbSA9IHRoaXMuc2NlbmUuZ2V0Vmlld1NjYWxlKCk7XG4gICAgICAgIFxuICAgICAgICAvLyBNb3ZlIHRoZSBjYW52YXMgdG8gdGhlIHBvc2l0aW9uIG9mIHRoZSBub2RlIGFuZCByb3RhdGVcbiAgICAgICAgbGV0IHhTY2FsZSA9IDE7XG4gICAgICAgIGxldCB5U2NhbGUgPSAxO1xuICAgICAgICBcbiAgICAgICAgaWYobm9kZSBpbnN0YW5jZW9mIFNwcml0ZSl7XG4gICAgICAgICAgICB4U2NhbGUgPSBub2RlLmludmVydFggPyAtMSA6IDE7XG4gICAgICAgICAgICB5U2NhbGUgPSBub2RlLmludmVydFkgPyAtMSA6IDE7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN0eC5zZXRUcmFuc2Zvcm0oeFNjYWxlLCAwLCAwLCB5U2NhbGUsIChub2RlLnBvc2l0aW9uLnggLSB0aGlzLm9yaWdpbi54KSp0aGlzLnpvb20sIChub2RlLnBvc2l0aW9uLnkgLSB0aGlzLm9yaWdpbi55KSp0aGlzLnpvb20pO1xuICAgICAgICB0aGlzLmN0eC5yb3RhdGUoLW5vZGUucm90YXRpb24pO1xuICAgICAgICBsZXQgZ2xvYmFsQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcbiAgICAgICAgLy8gaWYobm9kZSBpbnN0YW5jZW9mIFJlY3Qpe1xuICAgICAgICAgICAgLy8gRGVidWcubG9nKFwibm9kZVwiICsgbm9kZS5pZCwgXCJOb2RlXCIgKyBub2RlLmlkICsgXCIgQWxwaGE6IFwiICsgbm9kZS5hbHBoYSk7XG4gICAgICAgIC8vIH1cbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBub2RlLmFscGhhO1xuICAgICAgICBcbiAgICAgICAgaWYobm9kZSBpbnN0YW5jZW9mIEFuaW1hdGVkU3ByaXRlKXtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyQW5pbWF0ZWRTcHJpdGUoPEFuaW1hdGVkU3ByaXRlPm5vZGUpO1xuICAgICAgICB9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIFNwcml0ZSl7XG4gICAgICAgICAgICB0aGlzLnJlbmRlclNwcml0ZSg8U3ByaXRlPm5vZGUpO1xuICAgICAgICB9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIEdyYXBoaWMpe1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJHcmFwaGljKDxHcmFwaGljPm5vZGUpO1xuICAgICAgICB9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIFVJRWxlbWVudCl7XG4gICAgICAgICAgICB0aGlzLnJlbmRlclVJRWxlbWVudCg8VUlFbGVtZW50Pm5vZGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBnbG9iYWxBbHBoYTtcbiAgICAgICAgdGhpcy5jdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCByZW5kZXJTcHJpdGUoc3ByaXRlOiBTcHJpdGUpOiB2b2lkIHtcbiAgICAgICAgLy8gR2V0IHRoZSBpbWFnZSBmcm9tIHRoZSByZXNvdXJjZSBtYW5hZ2VyXG4gICAgICAgIGxldCBpbWFnZSA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldEltYWdlKHNwcml0ZS5pbWFnZUlkKTtcblxuICAgICAgICAvKlxuICAgICAgICAgICAgQ29vcmRpbmF0ZXMgaW4gdGhlIHNwYWNlIG9mIHRoZSBpbWFnZTpcbiAgICAgICAgICAgICAgICBpbWFnZSBjcm9wIHN0YXJ0IC0+IHgsIHlcbiAgICAgICAgICAgICAgICBpbWFnZSBjcm9wIHNpemUgIC0+IHcsIGhcbiAgICAgICAgICAgIENvb3JkaW5hdGVzIGluIHRoZSBzcGFjZSBvZiB0aGUgd29ybGRcbiAgICAgICAgICAgICAgICBpbWFnZSBkcmF3IHN0YXJ0IC0+IHgsIHlcbiAgICAgICAgICAgICAgICBpbWFnZSBkcmF3IHNpemUgIC0+IHcsIGhcbiAgICAgICAgKi9cbiAgICAgICAgdGhpcy5jdHguZHJhd0ltYWdlKGltYWdlLFxuICAgICAgICAgICAgc3ByaXRlLmltYWdlT2Zmc2V0LngsIHNwcml0ZS5pbWFnZU9mZnNldC55LFxuICAgICAgICAgICAgc3ByaXRlLnNpemUueCwgc3ByaXRlLnNpemUueSxcbiAgICAgICAgICAgICgtc3ByaXRlLnNpemUueCpzcHJpdGUuc2NhbGUueC8yKSp0aGlzLnpvb20sICgtc3ByaXRlLnNpemUueSpzcHJpdGUuc2NhbGUueS8yKSp0aGlzLnpvb20sXG4gICAgICAgICAgICBzcHJpdGUuc2l6ZS54ICogc3ByaXRlLnNjYWxlLngqdGhpcy56b29tLCBzcHJpdGUuc2l6ZS55ICogc3ByaXRlLnNjYWxlLnkqdGhpcy56b29tKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVuZGVyQW5pbWF0ZWRTcHJpdGUoc3ByaXRlOiBBbmltYXRlZFNwcml0ZSk6IHZvaWQge1xuICAgICAgICAvLyBHZXQgdGhlIGltYWdlIGZyb20gdGhlIHJlc291cmNlIG1hbmFnZXJcbiAgICAgICAgbGV0IGltYWdlID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0SW1hZ2Uoc3ByaXRlLmltYWdlSWQpO1xuXG4gICAgICAgIGxldCBhbmltYXRpb25JbmRleCA9IHNwcml0ZS5hbmltYXRpb24uZ2V0SW5kZXhBbmRBZHZhbmNlQW5pbWF0aW9uKCk7XG5cbiAgICAgICAgbGV0IGFuaW1hdGlvbk9mZnNldCA9IHNwcml0ZS5nZXRBbmltYXRpb25PZmZzZXQoYW5pbWF0aW9uSW5kZXgpO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAgICBDb29yZGluYXRlcyBpbiB0aGUgc3BhY2Ugb2YgdGhlIGltYWdlOlxuICAgICAgICAgICAgICAgIGltYWdlIGNyb3Agc3RhcnQgLT4geCwgeVxuICAgICAgICAgICAgICAgIGltYWdlIGNyb3Agc2l6ZSAgLT4gdywgaFxuICAgICAgICAgICAgQ29vcmRpbmF0ZXMgaW4gdGhlIHNwYWNlIG9mIHRoZSB3b3JsZCAoZ2l2ZW4gd2UgbW92ZWQpXG4gICAgICAgICAgICAgICAgaW1hZ2UgZHJhdyBzdGFydCAtPiAtdy8yLCAtaC8yXG4gICAgICAgICAgICAgICAgaW1hZ2UgZHJhdyBzaXplICAtPiB3LCBoXG4gICAgICAgICovXG4gICAgICAgIHRoaXMuY3R4LmRyYXdJbWFnZShpbWFnZSxcbiAgICAgICAgICAgIHNwcml0ZS5pbWFnZU9mZnNldC54ICsgYW5pbWF0aW9uT2Zmc2V0LngsIHNwcml0ZS5pbWFnZU9mZnNldC55ICsgYW5pbWF0aW9uT2Zmc2V0LnksXG4gICAgICAgICAgICBzcHJpdGUuc2l6ZS54LCBzcHJpdGUuc2l6ZS55LFxuICAgICAgICAgICAgKC1zcHJpdGUuc2l6ZS54KnNwcml0ZS5zY2FsZS54LzIpKnRoaXMuem9vbSwgKC1zcHJpdGUuc2l6ZS55KnNwcml0ZS5zY2FsZS55LzIpKnRoaXMuem9vbSxcbiAgICAgICAgICAgIHNwcml0ZS5zaXplLnggKiBzcHJpdGUuc2NhbGUueCp0aGlzLnpvb20sIHNwcml0ZS5zaXplLnkgKiBzcHJpdGUuc2NhbGUueSp0aGlzLnpvb20pO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCByZW5kZXJHcmFwaGljKGdyYXBoaWM6IEdyYXBoaWMpOiB2b2lkIHtcbiAgICAgICAgaWYoZ3JhcGhpYyBpbnN0YW5jZW9mIFBvaW50KXtcbiAgICAgICAgICAgIHRoaXMuZ3JhcGhpY1JlbmRlcmVyLnJlbmRlclBvaW50KDxQb2ludD5ncmFwaGljLCB0aGlzLnpvb20pO1xuICAgICAgICB9IGVsc2UgaWYoZ3JhcGhpYyBpbnN0YW5jZW9mIExpbmUpe1xuICAgICAgICAgICAgdGhpcy5ncmFwaGljUmVuZGVyZXIucmVuZGVyTGluZSg8TGluZT5ncmFwaGljLCB0aGlzLm9yaWdpbiwgdGhpcy56b29tKTtcbiAgICAgICAgfSBlbHNlIGlmKGdyYXBoaWMgaW5zdGFuY2VvZiBSZWN0KXtcbiAgICAgICAgICAgIHRoaXMuZ3JhcGhpY1JlbmRlcmVyLnJlbmRlclJlY3QoPFJlY3Q+Z3JhcGhpYywgdGhpcy56b29tKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCByZW5kZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkIHtcbiAgICAgICAgaWYodGlsZW1hcCBpbnN0YW5jZW9mIE9ydGhvZ29uYWxUaWxlbWFwKXtcbiAgICAgICAgICAgIHRoaXMudGlsZW1hcFJlbmRlcmVyLnJlbmRlck9ydGhvZ29uYWxUaWxlbWFwKDxPcnRob2dvbmFsVGlsZW1hcD50aWxlbWFwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCByZW5kZXJVSUVsZW1lbnQodWlFbGVtZW50OiBVSUVsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYodWlFbGVtZW50IGluc3RhbmNlb2YgTGFiZWwpe1xuICAgICAgICAgICAgdGhpcy51aUVsZW1lbnRSZW5kZXJlci5yZW5kZXJMYWJlbCh1aUVsZW1lbnQpO1xuICAgICAgICB9IGVsc2UgaWYodWlFbGVtZW50IGluc3RhbmNlb2YgQnV0dG9uKXtcbiAgICAgICAgICAgIHRoaXMudWlFbGVtZW50UmVuZGVyZXIucmVuZGVyQnV0dG9uKHVpRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSBpZih1aUVsZW1lbnQgaW5zdGFuY2VvZiBTbGlkZXIpe1xuICAgICAgICAgICAgdGhpcy51aUVsZW1lbnRSZW5kZXJlci5yZW5kZXJTbGlkZXIodWlFbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmKHVpRWxlbWVudCBpbnN0YW5jZW9mIFRleHRJbnB1dCl7XG4gICAgICAgICAgICB0aGlzLnVpRWxlbWVudFJlbmRlcmVyLnJlbmRlclRleHRJbnB1dCh1aUVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2xlYXIoY2xlYXJDb2xvcjogQ29sb3IpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdHguY2xlYXJSZWN0KDAsIDAsIHRoaXMud29ybGRTaXplLngsIHRoaXMud29ybGRTaXplLnkpO1xuICAgICAgICB0aGlzLmN0eC5maWxsU3R5bGUgPSBjbGVhckNvbG9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxSZWN0KDAsIDAsIHRoaXMud29ybGRTaXplLngsIHRoaXMud29ybGRTaXplLnkpO1xuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBMaW5lIGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9MaW5lXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9TY2VuZS9TY2VuZVwiO1xuXG4vKipcbiAqIEEgdXRpbGl0eSBjbGFzcyB0byBoZWxwIHRoZSBAcmVmZXJlbmNlW0NhbnZhc1JlbmRlcmVyXSByZW5kZXIgQHJlZmVyZW5jZVtHcmFwaGljXXNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR3JhcGhpY1JlbmRlcmVyIHtcbiAgICAvKiogVGhlIHJlc291cmNlIG1hbmFnZXIgb2YgdGhlIGdhbWUgZW5naW5lICovXG4gICAgcHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuICAgIC8qKiBUaGUgY3VycmVudCBzY2VuZSAqL1xuICAgIHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG4gICAgLyoqIFRoZSByZW5kZXJpbmcgY29udGV4dCAqL1xuICAgIHByb3RlY3RlZCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblxuICAgIGNvbnN0cnVjdG9yKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKXtcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5jdHggPSBjdHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2NlbmUgb2YgdGhpcyBHcmFwaGljUmVuZGVyZXJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGN1cnJlbnQgc2NlbmVcbiAgICAgKi9cbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBwb2ludFxuICAgICAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdG8gcmVuZGVyXG4gICAgICogQHBhcmFtIHpvb20gVGhlIHpvb20gbGV2ZWxcbiAgICAgKi9cbiAgICByZW5kZXJQb2ludChwb2ludDogUG9pbnQsIHpvb206IG51bWJlcik6IHZvaWQge1xuXHRcdHRoaXMuY3R4LmZpbGxTdHlsZSA9IHBvaW50LmNvbG9yLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUmVjdCgoLXBvaW50LnNpemUueC8yKSp6b29tLCAoLXBvaW50LnNpemUueS8yKSp6b29tLFxuICAgICAgICBwb2ludC5zaXplLngqem9vbSwgcG9pbnQuc2l6ZS55Knpvb20pO1xuICAgIH1cblxuICAgIHJlbmRlckxpbmUobGluZTogTGluZSwgb3JpZ2luOiBWZWMyLCB6b29tOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBsaW5lLmNvbG9yLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICB0aGlzLmN0eC5saW5lV2lkdGggPSBsaW5lLnRoaWNrbmVzcztcbiAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4Lm1vdmVUbygwLCAwKTtcbiAgICAgICAgdGhpcy5jdHgubGluZVRvKChsaW5lLmVuZC54IC0gbGluZS5zdGFydC54KSp6b29tLCAobGluZS5lbmQueSAtIGxpbmUuc3RhcnQueSkqem9vbSk7XG4gICAgICAgIHRoaXMuY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgcmVjdFxuICAgICAqIEBwYXJhbSByZWN0IFRoZSByZWN0IHRvIHJlbmRlclxuICAgICAqIEBwYXJhbSB6b29tIFRoZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgcmVuZGVyUmVjdChyZWN0OiBSZWN0LCB6b29tOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gRHJhdyB0aGUgaW50ZXJpb3Igb2YgdGhlIHJlY3RcbiAgICAgICAgaWYocmVjdC5jb2xvci5hICE9PSAwKXtcbiAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHJlY3QuY29sb3IudG9TdHJpbmdSR0IoKTtcbiAgICAgICAgICAgIGlmIChyZWN0LmZpbGxXaWR0aCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxSZWN0KCgtcmVjdC5zaXplLngvMikqem9vbSwgKC1yZWN0LnNpemUueS8yKSp6b29tLCByZWN0LmZpbGxXaWR0aCp6b29tLCByZWN0LnNpemUueSp6b29tKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsbFJlY3QoKC1yZWN0LnNpemUueC8yKSp6b29tLCAoLXJlY3Quc2l6ZS55LzIpKnpvb20sIHJlY3Quc2l6ZS54Knpvb20sIHJlY3Quc2l6ZS55Knpvb20pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgYm9yZGVyIG9mIHRoZSByZWN0IGlmIGl0IGlzbid0IHRyYW5zcGFyZW50XG4gICAgICAgIGlmKHJlY3QuYm9yZGVyQ29sb3IuYSAhPT0gMCl7XG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9IHJlY3QuZ2V0Qm9yZGVyQ29sb3IoKS50b1N0cmluZ1JHQigpO1xuICAgICAgICAgICAgdGhpcy5jdHgubGluZVdpZHRoID0gcmVjdC5nZXRCb3JkZXJXaWR0aCgpO1xuICAgICAgICAgICAgdGhpcy5jdHguc3Ryb2tlUmVjdCgoLXJlY3Quc2l6ZS54LzIpKnpvb20sICgtcmVjdC5zaXplLnkvMikqem9vbSwgcmVjdC5zaXplLngqem9vbSwgcmVjdC5zaXplLnkqem9vbSk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IE9ydGhvZ29uYWxUaWxlbWFwIGZyb20gXCIuLi8uLi9Ob2Rlcy9UaWxlbWFwcy9PcnRob2dvbmFsVGlsZW1hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgVGlsZXNldCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVzZXRcIjtcblxuLyoqXG4gKiBBIHV0aWxpdHkgY2xhc3MgZm9yIHRoZSBAcmVmZXJlbmNlW0NhbnZhc1JlbmRlcmVyXSB0byByZW5kZXIgQHJlZmVyZW5jZVtUaWxlbWFwXXNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGlsZW1hcFJlbmRlcmVyIHtcbiAgICBwcm90ZWN0ZWQgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG4gICAgcHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcbiAgICBwcm90ZWN0ZWQgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG5cbiAgICBjb25zdHJ1Y3RvcihjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCl7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuY3R4ID0gY3R4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIG9mIHRoaXMgVGlsZW1hcFJlbmRlcmVyXG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBjdXJyZW50IHNjZW5lXG4gICAgICovXG4gICAgc2V0U2NlbmUoc2NlbmU6IFNjZW5lKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGFuIG9ydGhvZ29uYWwgdGlsZW1hcFxuICAgICAqIEBwYXJhbSB0aWxlbWFwIFRoZSB0aWxlbWFwIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHJlbmRlck9ydGhvZ29uYWxUaWxlbWFwKHRpbGVtYXA6IE9ydGhvZ29uYWxUaWxlbWFwKTogdm9pZCB7XG4gICAgICAgIGxldCBwcmV2aW91c0FscGhhID0gdGhpcy5jdHguZ2xvYmFsQWxwaGE7XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gdGlsZW1hcC5nZXRMYXllcigpLmdldEFscGhhKCk7XG4gICAgICAgIFxuICAgICAgICBsZXQgb3JpZ2luID0gdGhpcy5zY2VuZS5nZXRWaWV3VHJhbnNsYXRpb24odGlsZW1hcCk7XG4gICAgICAgIGxldCBzaXplID0gdGhpcy5zY2VuZS5nZXRWaWV3cG9ydCgpLmdldEhhbGZTaXplKCk7XG4gICAgICAgIGxldCB6b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcbiAgICAgICAgbGV0IGJvdHRvbVJpZ2h0ID0gb3JpZ2luLmNsb25lKCkuYWRkKHNpemUuc2NhbGVkKDIqem9vbSkpO1xuXG4gICAgICAgIGlmKHRpbGVtYXAudmlzaWJsZSl7XG4gICAgICAgICAgICBsZXQgbWluQ29sUm93ID0gdGlsZW1hcC5nZXRDb2xSb3dBdChvcmlnaW4pO1xuICAgICAgICAgICAgbGV0IG1heENvbFJvdyA9IHRpbGVtYXAuZ2V0Q29sUm93QXQoYm90dG9tUmlnaHQpO1xuXG4gICAgICAgICAgICBmb3IobGV0IHggPSBtaW5Db2xSb3cueDsgeCA8PSBtYXhDb2xSb3cueDsgeCsrKXtcbiAgICAgICAgICAgICAgICBmb3IobGV0IHkgPSBtaW5Db2xSb3cueTsgeSA8PSBtYXhDb2xSb3cueTsgeSsrKXtcbiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSB0aWxlIGF0IHRoaXMgcG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgbGV0IHRpbGUgPSB0aWxlbWFwLmdldFRpbGVBdFJvd0NvbChuZXcgVmVjMih4LCB5KSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRXh0cmFjdCB0aGUgcm90L2ZsaXAgcGFyYW1ldGVycyBpZiB0aGVyZSBhcmUgYW55XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hc2sgPSAoMHhFIDw8IDI4KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgcm90RmxpcCA9ICgobWFzayAmIHRpbGUpID4+IDI4KSAmIDB4RjtcbiAgICAgICAgICAgICAgICAgICAgdGlsZSA9IHRpbGUgJiB+bWFzaztcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaW5kIHRoZSB0aWxlc2V0IHRoYXQgb3ducyB0aGlzIHRpbGUgaW5kZXggYW5kIHJlbmRlclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHRpbGVzZXQgb2YgdGlsZW1hcC5nZXRUaWxlc2V0cygpKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRpbGVzZXQuaGFzVGlsZSh0aWxlKSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJUaWxlKHRpbGVzZXQsIHRpbGUsIHgsIHksIG9yaWdpbiwgdGlsZW1hcC5zY2FsZSwgem9vbSwgcm90RmxpcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IHByZXZpb3VzQWxwaGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIHRpbGVcbiAgICAgKiBAcGFyYW0gdGlsZXNldCBUaGUgdGlsZXNldCB0aGlzIHRpbGUgYmVsb25ncyB0byBcbiAgICAgKiBAcGFyYW0gdGlsZUluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZVxuICAgICAqIEBwYXJhbSB0aWxlbWFwUm93IFRoZSByb3cgb2YgdGhlIHRpbGUgaW4gdGhlIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gdGlsZW1hcENvbCBUaGUgY29sdW1uIG9mIHRoZSB0aWxlIGluIHRoZSB0aWxlbWFwXG4gICAgICogQHBhcmFtIG9yaWdpbiBUaGUgb3JpZ2luIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSBzY2FsZSBUaGUgc2NhbGUgb2YgdGhlIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gem9vbSBUaGUgem9vbSBsZXZlbCBvZiB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVuZGVyVGlsZSh0aWxlc2V0OiBUaWxlc2V0LCB0aWxlSW5kZXg6IG51bWJlciwgdGlsZW1hcFJvdzogbnVtYmVyLCB0aWxlbWFwQ29sOiBudW1iZXIsIG9yaWdpbjogVmVjMiwgc2NhbGU6IFZlYzIsIHpvb206IG51bWJlciwgcm90RmxpcDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGxldCBpbWFnZSA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldEltYWdlKHRpbGVzZXQuZ2V0SW1hZ2VLZXkoKSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB0cnVlIGluZGV4XG4gICAgICAgIGxldCBpbmRleCA9IHRpbGVJbmRleCAtIHRpbGVzZXQuZ2V0U3RhcnRJbmRleCgpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgcm93IGFuZCBjb2wgb2YgdGhlIHRpbGUgaW4gaW1hZ2Ugc3BhY2VcbiAgICAgICAgbGV0IHJvdyA9IE1hdGguZmxvb3IoaW5kZXggLyB0aWxlc2V0LmdldE51bUNvbHMoKSk7XG4gICAgICAgIGxldCBjb2wgPSBpbmRleCAlIHRpbGVzZXQuZ2V0TnVtQ29scygpO1xuICAgICAgICBsZXQgd2lkdGggPSB0aWxlc2V0LmdldFRpbGVTaXplKCkueDtcbiAgICAgICAgbGV0IGhlaWdodCA9IHRpbGVzZXQuZ2V0VGlsZVNpemUoKS55O1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgcG9zaXRpb24gdG8gc3RhcnQgYSBjcm9wIGluIHRoZSB0aWxlc2V0IGltYWdlXG4gICAgICAgIGxldCBsZWZ0ID0gY29sICogd2lkdGg7XG4gICAgICAgIGxldCB0b3AgPSByb3cgKiBoZWlnaHQ7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBwb3NpdGlvbiBpbiB0aGUgd29ybGQgdG8gcmVuZGVyIHRoZSB0aWxlXG4gICAgICAgIGxldCB4ID0gTWF0aC5mbG9vcih0aWxlbWFwUm93ICogd2lkdGggKiBzY2FsZS54KTtcbiAgICAgICAgbGV0IHkgPSBNYXRoLmZsb29yKHRpbGVtYXBDb2wgKiBoZWlnaHQgKiBzY2FsZS55KTtcblxuICAgICAgICBsZXQgd29ybGRYID0gTWF0aC5mbG9vcigoeCAtIG9yaWdpbi54KSp6b29tKTtcbiAgICAgICAgbGV0IHdvcmxkWSA9IE1hdGguZmxvb3IoKHkgLSBvcmlnaW4ueSkqem9vbSk7XG4gICAgICAgIGxldCB3b3JsZFdpZHRoID0gTWF0aC5jZWlsKHdpZHRoICogc2NhbGUueCAqIHpvb20pO1xuICAgICAgICBsZXQgd29ybGRIZWlnaHQgPSBNYXRoLmNlaWwoaGVpZ2h0ICogc2NhbGUueSAqIHpvb20pO1xuXG4gICAgICAgIGlmKHJvdEZsaXAgIT09IDApe1xuICAgICAgICAgICAgbGV0IHNjYWxlWCA9IDE7XG4gICAgICAgICAgICBsZXQgc2NhbGVZID0gMTtcbiAgICAgICAgICAgIGxldCBzaGVhclggPSAwO1xuICAgICAgICAgICAgbGV0IHNoZWFyWSA9IDA7XG5cbiAgICAgICAgICAgIC8vIEZsaXAgb24gdGhlIHgtYXhpc1xuICAgICAgICAgICAgaWYocm90RmxpcCAmIDgpe1xuICAgICAgICAgICAgICAgIHNjYWxlWCA9IC0xO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGbGlwIG9uIHRoZSB5LWF4aXNcbiAgICAgICAgICAgIGlmKHJvdEZsaXAgJiA0KXtcbiAgICAgICAgICAgICAgICBzY2FsZVkgPSAtMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRmxpcCBvdmVyIHRoZSBsaW5lIHk9eFxuICAgICAgICAgICAgaWYocm90RmxpcCAmIDIpe1xuICAgICAgICAgICAgICAgIHNoZWFyWCA9IHNjYWxlWTtcbiAgICAgICAgICAgICAgICBzaGVhclkgPSBzY2FsZVg7XG4gICAgICAgICAgICAgICAgc2NhbGVYID0gMDtcbiAgICAgICAgICAgICAgICBzY2FsZVkgPSAwO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmN0eC5zZXRUcmFuc2Zvcm0oc2NhbGVYLCBzaGVhclgsIHNoZWFyWSwgc2NhbGVZLCB3b3JsZFggKyB3b3JsZFdpZHRoLzIsIHdvcmxkWSArIHdvcmxkSGVpZ2h0LzIpO1xuICAgICAgICBcbiAgICAgICAgICAgIC8vIFJlbmRlciB0aGUgdGlsZVxuICAgICAgICAgICAgdGhpcy5jdHguZHJhd0ltYWdlKGltYWdlLFxuICAgICAgICAgICAgICAgIGxlZnQsIHRvcCxcbiAgICAgICAgICAgICAgICB3aWR0aCwgaGVpZ2h0LFxuICAgICAgICAgICAgICAgIC13b3JsZFdpZHRoLzIsIC13b3JsZEhlaWdodC8yLFxuICAgICAgICAgICAgICAgIHdvcmxkV2lkdGgsIHdvcmxkSGVpZ2h0KTtcblxuICAgICAgICAgICAgaWYocm90RmxpcCAhPT0gMCl7XG4gICAgICAgICAgICAgICAgdGhpcy5jdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm8gcm90YXRpb25zLCBkb24ndCBkbyB0aGUgY2FsY3VsYXRpb25zLCBqdXN0IHJlbmRlciB0aGUgdGlsZVxuICAgICAgICAgICAgLy8gUmVuZGVyIHRoZSB0aWxlXG4gICAgICAgICAgICB0aGlzLmN0eC5kcmF3SW1hZ2UoaW1hZ2UsXG4gICAgICAgICAgICAgICAgbGVmdCwgdG9wLFxuICAgICAgICAgICAgICAgIHdpZHRoLCBoZWlnaHQsXG4gICAgICAgICAgICAgICAgd29ybGRYLCB3b3JsZFksXG4gICAgICAgICAgICAgICAgd29ybGRXaWR0aCwgd29ybGRIZWlnaHQpO1xuICAgICAgICB9XG5cblxuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBTbGlkZXIgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvU2xpZGVyXCI7XG5pbXBvcnQgVGV4dElucHV0IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1RleHRJbnB1dFwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5cbi8qKlxuICogQSB1dGlsaXR5IGNsYXNzIHRvIGhlbHAgdGhlIEByZWZlcmVuY2VbQ2FudmFzUmVuZGVyZXJdIHJlbmRlciBAcmVmZXJlbmNlW1VJRWxlbWVudF1zXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFVJRWxlbWVudFJlbmRlcmVyIHtcbiAgICBwcm90ZWN0ZWQgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG4gICAgcHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcbiAgICBwcm90ZWN0ZWQgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG5cbiAgICBjb25zdHJ1Y3RvcihjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCkge1xuICAgICAgICB0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLmN0eCA9IGN0eDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzY2VuZSBvZiB0aGlzIFVJRWxlbWVudFJlbmRlcmVyXG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBjdXJyZW50IHNjZW5lXG4gICAgICovXG4gICAgc2V0U2NlbmUoc2NlbmU6IFNjZW5lKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgbGFiZWxcbiAgICAgKiBAcGFyYW0gbGFiZWwgVGhlIGxhYmVsIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHJlbmRlckxhYmVsKGxhYmVsOiBMYWJlbCk6IHZvaWQge1xuICAgICAgICAvLyAvLyBJZiB0aGUgc2l6ZSBpcyB1bmFzc2lnbmVkIChieSB0aGUgdXNlciBvciBhdXRvbWF0aWNhbGx5KSBhc3NpZ24gaXRcbiAgICAgICAgLy8gbGFiZWwuaGFuZGxlSW5pdGlhbFNpemluZyh0aGlzLmN0eCk7XG5cbiAgICAgICAgLy8gLy8gR3JhYiB0aGUgZ2xvYmFsIGFscGhhIHNvIHdlIGNhbiBhZGp1c3QgaXQgZm9yIHRoaXMgcmVuZGVyXG4gICAgICAgIC8vIGxldCBwcmV2aW91c0FscGhhID0gdGhpcy5jdHguZ2xvYmFsQWxwaGE7XG5cbiAgICAgICAgLy8gLy8gR2V0IHRoZSBmb250IGFuZCB0ZXh0IHBvc2l0aW9uIGluIGxhYmVsXG4gICAgICAgIC8vIHRoaXMuY3R4LmZvbnQgPSBsYWJlbC5nZXRGb250U3RyaW5nKCk7XG4gICAgICAgIC8vIGxldCBvZmZzZXQgPSBsYWJlbC5jYWxjdWxhdGVUZXh0T2Zmc2V0KHRoaXMuY3R4KTtcblxuICAgICAgICAvLyAvLyBTdHJva2UgYW5kIGZpbGwgYSByb3VuZGVkIHJlY3QgYW5kIGdpdmUgaXQgdGV4dFxuICAgICAgICAvLyB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLmJhY2tncm91bmRDb2xvci5hO1xuICAgICAgICAvLyB0aGlzLmN0eC5maWxsU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVCYWNrZ3JvdW5kQ29sb3IoKS50b1N0cmluZ1JHQkEoKTtcbiAgICAgICAgLy8gdGhpcy5jdHguZmlsbFJvdW5kZWRSZWN0KC1sYWJlbC5zaXplLngvMiwgLWxhYmVsLnNpemUueS8yLFxuICAgICAgICAvLyBcdGxhYmVsLnNpemUueCwgbGFiZWwuc2l6ZS55LCBsYWJlbC5ib3JkZXJSYWRpdXMpO1xuXG4gICAgICAgIC8vIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gbGFiZWwuY2FsY3VsYXRlQm9yZGVyQ29sb3IoKS50b1N0cmluZ1JHQkEoKTtcbiAgICAgICAgLy8gdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBsYWJlbC5ib3JkZXJDb2xvci5hO1xuICAgICAgICAvLyB0aGlzLmN0eC5saW5lV2lkdGggPSBsYWJlbC5ib3JkZXJXaWR0aDtcbiAgICAgICAgLy8gdGhpcy5jdHguc3Ryb2tlUm91bmRlZFJlY3QoLWxhYmVsLnNpemUueC8yLCAtbGFiZWwuc2l6ZS55LzIsXG4gICAgICAgIC8vIFx0bGFiZWwuc2l6ZS54LCBsYWJlbC5zaXplLnksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgLy8gdGhpcy5jdHguZmlsbFN0eWxlID0gbGFiZWwuY2FsY3VsYXRlVGV4dENvbG9yKCk7XG4gICAgICAgIC8vIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwudGV4dENvbG9yLmE7XG4gICAgICAgIC8vIHRoaXMuY3R4LmZpbGxUZXh0KGxhYmVsLnRleHQsIG9mZnNldC54IC0gbGFiZWwuc2l6ZS54LzIsIG9mZnNldC55IC0gbGFiZWwuc2l6ZS55LzIpO1xuXG4gICAgICAgIC8vIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gcHJldmlvdXNBbHBoYTtcbiAgICAgICAgLy8gSWYgdGhlIHNpemUgaXMgdW5hc3NpZ25lZCAoYnkgdGhlIHVzZXIgb3IgYXV0b21hdGljYWxseSkgYXNzaWduIGl0XG4gICAgICAgIGxldCBsaW5lcyA9IGxhYmVsLnRleHQuc3BsaXQoJ1xcbicpO1xuICAgICAgICBsZXQgdGVtcFRleHQgPSBsYWJlbC50ZXh0O1xuICAgICAgICBpZiAobGluZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgbGV0IG1heCA9IDA7XG4gICAgICAgICAgICBsZXQgbWF4TGVuZ3RoSW5kZXggPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChsaW5lc1tpXS5sZW5ndGggPiBtYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4ID0gbGluZXNbaV0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBtYXhMZW5ndGhJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGFiZWwudGV4dCA9IGxpbmVzW21heExlbmd0aEluZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBsYWJlbC5oYW5kbGVJbml0aWFsU2l6aW5nKHRoaXMuY3R4KTtcbiAgICAgICAgLy8gR3JhYiB0aGUgZ2xvYmFsIGFscGhhIHNvIHdlIGNhbiBhZGp1c3QgaXQgZm9yIHRoaXMgcmVuZGVyXG4gICAgICAgIGxldCBwcmV2aW91c0FscGhhID0gdGhpcy5jdHguZ2xvYmFsQWxwaGE7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBmb250IGFuZCB0ZXh0IHBvc2l0aW9uIGluIGxhYmVsXG4gICAgICAgIHRoaXMuY3R4LmZvbnQgPSBsYWJlbC5nZXRGb250U3RyaW5nKCk7XG4gICAgICAgIGxldCBvZmZzZXQgPSBsYWJlbC5jYWxjdWxhdGVUZXh0T2Zmc2V0KHRoaXMuY3R4KTtcblxuICAgICAgICAvLyBTdHJva2UgYW5kIGZpbGwgYSByb3VuZGVkIHJlY3QgYW5kIGdpdmUgaXQgdGV4dFxuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLmJhY2tncm91bmRDb2xvci5hO1xuICAgICAgICB0aGlzLmN0eC5maWxsU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVCYWNrZ3JvdW5kQ29sb3IoKS50b1N0cmluZ1JHQkEoKTtcbiAgICAgICAgdGhpcy5jdHguZmlsbFJvdW5kZWRSZWN0KC1sYWJlbC5zaXplLnggLyAyLCAtbGFiZWwuc2l6ZS55IC8gMixcbiAgICAgICAgICAgIGxhYmVsLnNpemUueCwgbGFiZWwuc2l6ZS55LCBsYWJlbC5ib3JkZXJSYWRpdXMpO1xuXG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gbGFiZWwuY2FsY3VsYXRlQm9yZGVyQ29sb3IoKS50b1N0cmluZ1JHQkEoKTtcbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBsYWJlbC5ib3JkZXJDb2xvci5hO1xuICAgICAgICB0aGlzLmN0eC5saW5lV2lkdGggPSBsYWJlbC5ib3JkZXJXaWR0aDtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlUm91bmRlZFJlY3QoLWxhYmVsLnNpemUueCAvIDIsIC1sYWJlbC5zaXplLnkgLyAyLFxuICAgICAgICAgICAgbGFiZWwuc2l6ZS54LCBsYWJlbC5zaXplLnkgKyAoKGxpbmVzLmxlbmd0aCAtIDEpICogbGFiZWwuZm9udFNpemUpLCBsYWJlbC5ib3JkZXJSYWRpdXMpO1xuXG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGxhYmVsLmNhbGN1bGF0ZVRleHRDb2xvcigpO1xuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLnRleHRDb2xvci5hO1xuICAgICAgICBpZiAobGluZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICB0aGlzLmN0eC5maWxsVGV4dChsYWJlbC50ZXh0LCBvZmZzZXQueCAtIGxhYmVsLnNpemUueCAvIDIsIChvZmZzZXQueSAtIGxhYmVsLnNpemUueSAvIDIpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZXQgYWRkaXRpb25hbFkgPSBpICogKGxhYmVsLnNpemUueSAvIDIgKyAobGFiZWwuZm9udFNpemUgPT09IDQwID8gMjAgOiAxMCkpO1xuICAgICAgICAgICAgICAgIGxhYmVsLnRleHQgPSBsaW5lc1tpXTtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSBsYWJlbC5jYWxjdWxhdGVUZXh0T2Zmc2V0KHRoaXMuY3R4KTtcbiAgICAgICAgICAgICAgICB0aGlzLmN0eC5maWxsVGV4dChsaW5lc1tpXSwgKG9mZnNldC54IC0gbGFiZWwuc2l6ZS54IC8gMiksIChvZmZzZXQueSAtIGxhYmVsLnNpemUueSAvIDIgKyBhZGRpdGlvbmFsWSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gcHJldmlvdXNBbHBoYTtcbiAgICAgICAgbGFiZWwudGV4dCA9IHRlbXBUZXh0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBidXR0b25cbiAgICAgKiBAcGFyYW0gYnV0dG9uIFRoZSBidXR0b24gdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyQnV0dG9uKGJ1dHRvbjogQnV0dG9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVuZGVyTGFiZWwoYnV0dG9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgc2xpZGVyXG4gICAgICogQHBhcmFtIHNsaWRlciBUaGUgc2xpZGVyIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHJlbmRlclNsaWRlcihzbGlkZXI6IFNsaWRlcik6IHZvaWQge1xuICAgICAgICAvLyBHcmFiIHRoZSBnbG9iYWwgYWxwaGEgc28gd2UgY2FuIGFkanVzdCBpdCBmb3IgdGhpcyByZW5kZXJcbiAgICAgICAgbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBzbGlkZXIuZ2V0TGF5ZXIoKS5nZXRBbHBoYSgpO1xuXG4gICAgICAgIC8vIENhbGN1YWxhdGUgdGhlIHNsaWRlciBzaXplXG4gICAgICAgIGxldCBzbGlkZXJTaXplID0gbmV3IFZlYzIoc2xpZGVyLnNpemUueCwgMik7XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgc2xpZGVyXG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHNsaWRlci5zbGlkZXJDb2xvci50b1N0cmluZygpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoLXNsaWRlclNpemUueCAvIDIsIC1zbGlkZXJTaXplLnkgLyAyLFxuICAgICAgICAgICAgc2xpZGVyU2l6ZS54LCBzbGlkZXJTaXplLnksIHNsaWRlci5ib3JkZXJSYWRpdXMpO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmliIHNpemUgYW5kIHBvc2l0aW9uXG4gICAgICAgIGxldCB4ID0gTWF0aFV0aWxzLmxlcnAoLXNsaWRlci5zaXplLnggLyAyLCBzbGlkZXIuc2l6ZS54IC8gMiwgc2xpZGVyLmdldFZhbHVlKCkpO1xuXG4gICAgICAgIC8vIERyYXcgdGhlIG5pYlxuICAgICAgICB0aGlzLmN0eC5maWxsU3R5bGUgPSBzbGlkZXIubmliQ29sb3IudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5jdHguZmlsbFJvdW5kZWRSZWN0KHggLSBzbGlkZXIubmliU2l6ZS54IC8gMiwgLXNsaWRlci5uaWJTaXplLnkgLyAyLFxuICAgICAgICAgICAgc2xpZGVyLm5pYlNpemUueCwgc2xpZGVyLm5pYlNpemUueSwgc2xpZGVyLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgLy8gUmVzZXQgdGhlIGFscGhhXG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gcHJldmlvdXNBbHBoYTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgdGV4dElucHV0XG4gICAgICogQHBhcmFtIHRleHRJbnB1dCBUaGUgdGV4dElucHV0IHRvIHJlbmRlclxuICAgICAqL1xuICAgIHJlbmRlclRleHRJbnB1dCh0ZXh0SW5wdXQ6IFRleHRJbnB1dCk6IHZvaWQge1xuICAgICAgICAvLyBTaG93IGEgY3Vyc29yIHNvbWV0aW1lc1xuICAgICAgICBpZiAodGV4dElucHV0LmZvY3VzZWQgJiYgdGV4dElucHV0LmN1cnNvckNvdW50ZXIgJSA2MCA+IDMwKSB7XG4gICAgICAgICAgICB0ZXh0SW5wdXQudGV4dCArPSBcInxcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVuZGVyTGFiZWwodGV4dElucHV0KTtcblxuICAgICAgICBpZiAodGV4dElucHV0LmZvY3VzZWQpIHtcbiAgICAgICAgICAgIGlmICh0ZXh0SW5wdXQuY3Vyc29yQ291bnRlciAlIDYwID4gMzApIHtcbiAgICAgICAgICAgICAgICB0ZXh0SW5wdXQudGV4dCA9IHRleHRJbnB1dC50ZXh0LnN1YnN0cmluZygwLCB0ZXh0SW5wdXQudGV4dC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGV4dElucHV0LmN1cnNvckNvdW50ZXIgKz0gMTtcbiAgICAgICAgICAgIGlmICh0ZXh0SW5wdXQuY3Vyc29yQ291bnRlciA+PSA2MCkge1xuICAgICAgICAgICAgICAgIHRleHRJbnB1dC5jdXJzb3JDb3VudGVyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgR3JhcGhpYyBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY1wiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFVJTGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9VSUxheWVyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgZnJhbWV3b3JrIHRvIHB1dCBhbGwgcmVuZGVyaW5nIGluIG9uY2UgcGxhY2UgaW4gdGhlIGFwcGxpY2F0aW9uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFJlbmRlcmluZ01hbmFnZXIge1xuICAgIC8qKiBUaGUgUmVzb3VyY2VNYW5hZ2VyICovXG4gICAgcHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG4gICAgLyoqIFRoZSBzY2VuZSBjdXJyZW50bHkgYmVpbmcgcmVuZGVyZWQgKi9cbiAgICBwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuXG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzY2VuZSBjdXJyZW50bHkgYmVpbmcgcmVuZGVyZWRcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGN1cnJlbnQgU2NlbmVcbiAgICAgKi9cbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIGNhbnZhcyBmb3IgdGhlIGdhbWVcbiAgICAgKiBAcGFyYW0gY2FudmFzIFRoZSBjYW52YXMgZWxlbWVudFxuICAgICAqIEBwYXJhbSB3aWR0aCBUaGUgZGVzaXJlZCB3aWR0aCBvZiB0aGUgY2FudmFzXG4gICAgICogQHBhcmFtIGhlaWdodCBUaGUgZGVzaXJlZCBoZWlnaHQgb2YgdGhlIGNhbnZhc1xuICAgICAqIEByZXR1cm5zIFRoZSByZW5kZXJpbmcgY29udGV4dCBvZiB0aGUgY2FudmFzXG4gICAgICovXG4gICAgYWJzdHJhY3QgaW5pdGlhbGl6ZUNhbnZhcyhjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IGFueTtcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgdGhlIHZpc2libGUgc2V0IG9mIENhbnZhc05vZGVzIGFuZCB2aXNpYmxlIHBvcnRpb25zIG9mIHRpbGVtYXBzLCBhcyB3ZWxsIGFzIGFueSBVSUVsZW1lbnQgaW4gVUlMYXllcnNcbiAgICAgKiBAcGFyYW0gdmlzaWJsZVNldCBUaGUgdmlzaWJsZSBzZXQgb2YgQ2FudmFzTm9kZXNcbiAgICAgKiBAcGFyYW0gdGlsZW1hcHMgVGhlIHRpbGVtYXBzIHVzZWQgaW4gdGhlIGFwcGxpY2F0aW9uXG4gICAgICogQHBhcmFtIHVpTGF5ZXJzIFRoZSB1c2VyIGludGVyZmFjZSBsYXllcnNcbiAgICAgKi9cbiAgICBhYnN0cmFjdCByZW5kZXIodmlzaWJsZVNldDogQXJyYXk8Q2FudmFzTm9kZT4sIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPiwgdWlMYXllcnM6IE1hcDxVSUxheWVyPik6IHZvaWQ7XG5cbiAgICAvKiogQ2xlYXJzIHRoZSBjYW52YXMgKi9cbiAgICBhYnN0cmFjdCBjbGVhcihjb2xvcjogQ29sb3IpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIHNwcml0ZVxuICAgICAqIEBwYXJhbSBzcHJpdGUgVGhlIHNwcml0ZSB0byByZW5kZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVuZGVyU3ByaXRlKHNwcml0ZTogU3ByaXRlKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYW4gYW5pbWF0ZWQgc3ByaXRlXG4gICAgICogQHBhcmFtIHNwcml0ZSBUaGUgYW5pbWF0ZWQgc3ByaXRlIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCByZW5kZXJBbmltYXRlZFNwcml0ZShzcHJpdGU6IEFuaW1hdGVkU3ByaXRlKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBncmFwaGljXG4gICAgICogQHBhcmFtIGdyYXBoaWMgVGhlIGdyYXBoaWMgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlckdyYXBoaWMoZ3JhcGhpYzogR3JhcGhpYyk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgdGlsZW1hcFxuICAgICAqIEBwYXJhbSB0aWxlbWFwIFRoZSB0aWxlbWFwIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCByZW5kZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkO1xuXG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgVUlFbGVtZW50XG4gICAgICogQHBhcmFtIHVpRWxlbWVudCBUaGUgVUlFbGVtZW50IHRvIHJlbmRlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCByZW5kZXJVSUVsZW1lbnQodWlFbGVtZW50OiBVSUVsZW1lbnQpOiB2b2lkO1xufSIsImltcG9ydCBHcmFwaCBmcm9tIFwiLi4vRGF0YVR5cGVzL0dyYXBocy9HcmFwaFwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNcIjtcbmltcG9ydCB7IEdyYXBoaWNUeXBlIH0gZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlc1wiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljcy9Qb2ludFwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgVUlFbGVtZW50IGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IFNoYWRlclJlZ2lzdHJ5IGZyb20gXCIuLi9SZWdpc3RyeS9SZWdpc3RyaWVzL1NoYWRlclJlZ2lzdHJ5XCI7XG5pbXBvcnQgUmVnaXN0cnlNYW5hZ2VyIGZyb20gXCIuLi9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXJcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBQYXJhbGxheExheWVyIGZyb20gXCIuLi9TY2VuZS9MYXllcnMvUGFyYWxsYXhMYXllclwiO1xuaW1wb3J0IFVJTGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9VSUxheWVyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgUmVuZGVyaW5nVXRpbHMgZnJvbSBcIi4uL1V0aWxzL1JlbmRlcmluZ1V0aWxzXCI7XG5pbXBvcnQgUmVuZGVyaW5nTWFuYWdlciBmcm9tIFwiLi9SZW5kZXJpbmdNYW5hZ2VyXCI7XG5pbXBvcnQgU2hhZGVyVHlwZSBmcm9tIFwiLi9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdlYkdMUmVuZGVyZXIgZXh0ZW5kcyBSZW5kZXJpbmdNYW5hZ2VyIHtcblxuXHRwcm90ZWN0ZWQgb3JpZ2luOiBWZWMyO1xuXHRwcm90ZWN0ZWQgem9vbTogbnVtYmVyO1xuXHRwcm90ZWN0ZWQgd29ybGRTaXplOiBWZWMyO1xuXG5cdHByb3RlY3RlZCBnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0O1xuXHRwcm90ZWN0ZWQgdGV4dEN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuXG5cdGluaXRpYWxpemVDYW52YXMoY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQge1xuXHRcdGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG5cdFx0dGhpcy53b3JsZFNpemUgPSBWZWMyLlpFUk87XG5cdFx0dGhpcy53b3JsZFNpemUueCA9IHdpZHRoO1xuXHRcdHRoaXMud29ybGRTaXplLnkgPSBoZWlnaHQ7XG5cblx0XHQvLyBHZXQgdGhlIFdlYkdMIGNvbnRleHRcbiAgICAgICAgdGhpcy5nbCA9IGNhbnZhcy5nZXRDb250ZXh0KFwid2ViZ2xcIik7XG5cblx0XHR0aGlzLmdsLnZpZXdwb3J0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG5cblx0XHR0aGlzLmdsLmRpc2FibGUodGhpcy5nbC5ERVBUSF9URVNUKTtcbiAgICAgICAgdGhpcy5nbC5lbmFibGUodGhpcy5nbC5CTEVORCk7XG4gICAgICAgIHRoaXMuZ2wuYmxlbmRGdW5jKHRoaXMuZ2wuU1JDX0FMUEhBLCB0aGlzLmdsLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xuICAgICAgICB0aGlzLmdsLmVuYWJsZSh0aGlzLmdsLkNVTExfRkFDRSk7XG5cblx0XHQvLyBUZWxsIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHdlJ3JlIHVzaW5nIFdlYkdMXG5cdFx0UmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCkudXNlV2ViR0wodHJ1ZSwgdGhpcy5nbCk7XG5cblx0XHQvLyBTaG93IHRoZSB0ZXh0IGNhbnZhcyBhbmQgZ2V0IGl0cyBjb250ZXh0XG5cdFx0bGV0IHRleHRDYW52YXMgPSA8SFRNTENhbnZhc0VsZW1lbnQ+ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJ0ZXh0LWNhbnZhc1wiKTtcblx0XHR0ZXh0Q2FudmFzLmhpZGRlbiA9IGZhbHNlO1xuXHRcdHRoaXMudGV4dEN0eCA9IHRleHRDYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xuXG5cdFx0Ly8gU2l6ZSB0aGUgdGV4dCBjYW52YXMgdG8gYmUgdGhlIHNhbWUgYXMgdGhlIGdhbWUgY2FudmFzXG5cdFx0dGV4dENhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cdFx0dGV4dENhbnZhcy53aWR0aCA9IHdpZHRoO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmdsO1xuXHR9XG5cblx0cmVuZGVyKHZpc2libGVTZXQ6IENhbnZhc05vZGVbXSwgdGlsZW1hcHM6IFRpbGVtYXBbXSwgdWlMYXllcnM6IE1hcDxVSUxheWVyPik6IHZvaWQge1xuXHRcdGZvcihsZXQgbm9kZSBvZiB2aXNpYmxlU2V0KXtcblx0XHRcdHRoaXMucmVuZGVyTm9kZShub2RlKTtcblx0XHR9XG5cblx0XHR1aUxheWVycy5mb3JFYWNoKGtleSA9PiB7XG5cdFx0XHRpZighdWlMYXllcnMuZ2V0KGtleSkuaXNIaWRkZW4oKSlcblx0XHRcdFx0dWlMYXllcnMuZ2V0KGtleSkuZ2V0SXRlbXMoKS5mb3JFYWNoKG5vZGUgPT4gdGhpcy5yZW5kZXJOb2RlKDxDYW52YXNOb2RlPm5vZGUpKVxuXHRcdH0pO1xuXHR9XG5cblx0Y2xlYXIoY29sb3I6IENvbG9yKTogdm9pZCB7XG5cdFx0dGhpcy5nbC5jbGVhckNvbG9yKGNvbG9yLnIsIGNvbG9yLmcsIGNvbG9yLmIsIGNvbG9yLmEpO1xuXHRcdHRoaXMuZ2wuY2xlYXIodGhpcy5nbC5DT0xPUl9CVUZGRVJfQklUIHwgdGhpcy5nbC5ERVBUSF9CVUZGRVJfQklUKTtcblxuXHRcdHRoaXMudGV4dEN0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy53b3JsZFNpemUueCwgdGhpcy53b3JsZFNpemUueSk7XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyTm9kZShub2RlOiBDYW52YXNOb2RlKTogdm9pZCB7XG5cdFx0Ly8gQ2FsY3VsYXRlIHRoZSBvcmlnaW4gb2YgdGhlIHZpZXdwb3J0IGFjY29yZGluZyB0byB0aGlzIHNwcml0ZVxuICAgICAgICB0aGlzLm9yaWdpbiA9IHRoaXMuc2NlbmUuZ2V0Vmlld1RyYW5zbGF0aW9uKG5vZGUpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgem9vbSBsZXZlbCBvZiB0aGUgc2NlbmVcbiAgICAgICAgdGhpcy56b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcblx0XHRcblx0XHRpZihub2RlLmhhc0N1c3RvbVNoYWRlcil7XG5cdFx0XHQvLyBJZiB0aGUgbm9kZSBoYXMgYSBjdXN0b20gc2hhZGVyLCByZW5kZXIgdXNpbmcgdGhhdFxuXHRcdFx0dGhpcy5yZW5kZXJDdXN0b20obm9kZSk7XG5cdFx0fSBlbHNlIGlmKG5vZGUgaW5zdGFuY2VvZiBHcmFwaGljKXtcblx0XHRcdHRoaXMucmVuZGVyR3JhcGhpYyhub2RlKTtcblx0XHR9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIFNwcml0ZSl7XG5cdFx0XHRpZihub2RlIGluc3RhbmNlb2YgQW5pbWF0ZWRTcHJpdGUpe1xuXHRcdFx0XHR0aGlzLnJlbmRlckFuaW1hdGVkU3ByaXRlKG5vZGUpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5yZW5kZXJTcHJpdGUobm9kZSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmKG5vZGUgaW5zdGFuY2VvZiBVSUVsZW1lbnQpe1xuXHRcdFx0dGhpcy5yZW5kZXJVSUVsZW1lbnQobm9kZSk7XG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIHJlbmRlclNwcml0ZShzcHJpdGU6IFNwcml0ZSk6IHZvaWQge1xuXHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQoU2hhZGVyUmVnaXN0cnkuU1BSSVRFX1NIQURFUik7XG5cdFx0bGV0IG9wdGlvbnMgPSB0aGlzLmFkZE9wdGlvbnMoc2hhZGVyLmdldE9wdGlvbnMoc3ByaXRlKSwgc3ByaXRlKTtcblx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHR9XG5cblx0cHJvdGVjdGVkIHJlbmRlckFuaW1hdGVkU3ByaXRlKHNwcml0ZTogQW5pbWF0ZWRTcHJpdGUpOiB2b2lkIHtcblx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KFNoYWRlclJlZ2lzdHJ5LlNQUklURV9TSEFERVIpO1xuXHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKHNwcml0ZSksIHNwcml0ZSk7XG5cdFx0c2hhZGVyLnJlbmRlcih0aGlzLmdsLCBvcHRpb25zKTtcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJHcmFwaGljKGdyYXBoaWM6IEdyYXBoaWMpOiB2b2lkIHtcblxuXHRcdGlmKGdyYXBoaWMgaW5zdGFuY2VvZiBQb2ludCl7XG5cdFx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KFNoYWRlclJlZ2lzdHJ5LlBPSU5UX1NIQURFUik7XG5cdFx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyhncmFwaGljKSwgZ3JhcGhpYyk7XG5cdFx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHRcdH0gZWxzZSBpZihncmFwaGljIGluc3RhbmNlb2YgUmVjdCkge1xuXHRcdFx0bGV0IHNoYWRlciA9IFJlZ2lzdHJ5TWFuYWdlci5zaGFkZXJzLmdldChTaGFkZXJSZWdpc3RyeS5SRUNUX1NIQURFUik7XG5cdFx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyhncmFwaGljKSwgZ3JhcGhpYyk7XG5cdFx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHRcdH0gXG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyVGlsZW1hcCh0aWxlbWFwOiBUaWxlbWFwKTogdm9pZCB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC5cIik7XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyVUlFbGVtZW50KHVpRWxlbWVudDogVUlFbGVtZW50KTogdm9pZCB7XG5cdFx0aWYodWlFbGVtZW50IGluc3RhbmNlb2YgTGFiZWwpe1xuXHRcdFx0bGV0IHNoYWRlciA9IFJlZ2lzdHJ5TWFuYWdlci5zaGFkZXJzLmdldChTaGFkZXJSZWdpc3RyeS5MQUJFTF9TSEFERVIpO1xuXHRcdFx0bGV0IG9wdGlvbnMgPSB0aGlzLmFkZE9wdGlvbnMoc2hhZGVyLmdldE9wdGlvbnModWlFbGVtZW50KSwgdWlFbGVtZW50KTtcblx0XHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cblx0XHRcdHRoaXMudGV4dEN0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgKHVpRWxlbWVudC5wb3NpdGlvbi54IC0gdGhpcy5vcmlnaW4ueCkqdGhpcy56b29tLCAodWlFbGVtZW50LnBvc2l0aW9uLnkgLSB0aGlzLm9yaWdpbi55KSp0aGlzLnpvb20pO1xuXHRcdFx0dGhpcy50ZXh0Q3R4LnJvdGF0ZSgtdWlFbGVtZW50LnJvdGF0aW9uKTtcblx0XHRcdGxldCBnbG9iYWxBbHBoYSA9IHRoaXMudGV4dEN0eC5nbG9iYWxBbHBoYTtcblx0XHRcdHRoaXMudGV4dEN0eC5nbG9iYWxBbHBoYSA9IHVpRWxlbWVudC5hbHBoYTtcblxuXHRcdFx0Ly8gUmVuZGVyIHRleHRcblx0XHRcdHRoaXMudGV4dEN0eC5mb250ID0gdWlFbGVtZW50LmdldEZvbnRTdHJpbmcoKTtcblx0XHRcdGxldCBvZmZzZXQgPSB1aUVsZW1lbnQuY2FsY3VsYXRlVGV4dE9mZnNldCh0aGlzLnRleHRDdHgpO1xuXHRcdFx0dGhpcy50ZXh0Q3R4LmZpbGxTdHlsZSA9IHVpRWxlbWVudC5jYWxjdWxhdGVUZXh0Q29sb3IoKTtcblx0XHRcdHRoaXMudGV4dEN0eC5nbG9iYWxBbHBoYSA9IHVpRWxlbWVudC50ZXh0Q29sb3IuYTtcblx0XHRcdHRoaXMudGV4dEN0eC5maWxsVGV4dCh1aUVsZW1lbnQudGV4dCwgb2Zmc2V0LnggLSB1aUVsZW1lbnQuc2l6ZS54LzIsIG9mZnNldC55IC0gdWlFbGVtZW50LnNpemUueS8yKTtcblxuXHRcdFx0dGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhID0gZ2xvYmFsQWxwaGE7XG4gICAgICAgIFx0dGhpcy50ZXh0Q3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyQ3VzdG9tKG5vZGU6IENhbnZhc05vZGUpOiB2b2lkIHtcblx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KG5vZGUuY3VzdG9tU2hhZGVyS2V5KTtcblx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyhub2RlKSwgbm9kZSk7XG5cdFx0c2hhZGVyLnJlbmRlcih0aGlzLmdsLCBvcHRpb25zKTtcblx0fVxuXG5cdHByb3RlY3RlZCBhZGRPcHRpb25zKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4sIG5vZGU6IENhbnZhc05vZGUpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHQvLyBHaXZlIHRoZSBzaGFkZXIgYWNjZXNzIHRvIHRoZSB3b3JsZCBzaXplXG5cdFx0b3B0aW9ucy53b3JsZFNpemUgPSB0aGlzLndvcmxkU2l6ZTtcblxuXHRcdC8vIEFkanVzdCB0aGUgb3JpZ2luIHBvc2l0aW9uIHRvIHRoZSBwYXJhbGxheFxuXHRcdGxldCBsYXllciA9IG5vZGUuZ2V0TGF5ZXIoKTtcblx0XHRsZXQgcGFyYWxsYXggPSBuZXcgVmVjMigxLCAxKTtcblx0XHRpZihsYXllciBpbnN0YW5jZW9mIFBhcmFsbGF4TGF5ZXIpe1xuXHRcdFx0cGFyYWxsYXggPSAoPFBhcmFsbGF4TGF5ZXI+bGF5ZXIpLnBhcmFsbGF4O1xuXHRcdH1cblxuXHRcdG9wdGlvbnMub3JpZ2luID0gdGhpcy5vcmlnaW4uY2xvbmUoKS5tdWx0KHBhcmFsbGF4KTtcblxuXHRcdHJldHVybiBvcHRpb25zO1xuXHR9XG5cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuXG4vKipcbiAqIEEgd3JhcHBlciBjbGFzcyBmb3IgV2ViR0wgc2hhZGVycy5cbiAqIFRoaXMgY2xhc3MgaXMgYSBzaW5nbGV0b24sIGFuZCB0aGVyZSBpcyBvbmx5IG9uZSBmb3IgZWFjaCBzaGFkZXIgdHlwZS5cbiAqIEFsbCBvYmplY3RzIHRoYXQgdXNlIHRoaXMgc2hhZGVyIHR5cGUgd2lsbCByZWZlciB0byBhbmQgbW9kaWZ5IHRoaXMgc2FtZSB0eXBlLlxuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBTaGFkZXJUeXBlIHtcblx0LyoqIFRoZSBuYW1lIG9mIHRoaXMgc2hhZGVyICovXG5cdHByb3RlY3RlZCBuYW1lOiBzdHJpbmc7XG5cblx0LyoqIFRoZSBrZXkgdG8gdGhlIFdlYkdMUHJvZ3JhbSBpbiB0aGUgUmVzb3VyY2VNYW5hZ2VyICovXG5cdHByb3RlY3RlZCBwcm9ncmFtS2V5OiBzdHJpbmc7XG5cblx0LyoqIEEgcmVmZXJlbmNlIHRvIHRoZSByZXNvdXJjZSBtYW5hZ2VyICovXG5cdHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHRoaXMucHJvZ3JhbUtleSA9IHByb2dyYW1LZXk7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0aWFsaXplcyBhbnkgYnVmZmVyIG9iamVjdHMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgc2hhZGVyIHR5cGUuXG5cdCAqIEBwYXJhbSBnbCBUaGUgV2ViR0wgcmVuZGVyaW5nIGNvbnRleHRcblx0ICovXG5cdGFic3RyYWN0IGluaXRCdWZmZXJPYmplY3QoKTogdm9pZDtcblxuXHQvKipcblx0ICogTG9hZHMgYW55IHVuaWZvcm1zXG5cdCAqIEBwYXJhbSBnbCBUaGUgV2ViR0wgcmVuZGVyaW5nIGNvbnRleHRcblx0ICogQHBhcmFtIG9wdGlvbnMgSW5mb3JtYXRpb24gYWJvdXQgdGhlIG9iamVjdCB3ZSdyZSBjdXJyZW50bHkgcmVuZGVyaW5nXG5cdCAqL1xuXHRhYnN0cmFjdCByZW5kZXIoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHRoZSBvcHRpb25zIGZyb20gdGhlIENhbnZhc05vZGUgYW5kIGdpdmVzIHRoZW0gdG8gdGhlIHJlbmRlciBmdW5jdGlvblxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byBnZXQgb3B0aW9ucyBmcm9tXG5cdCAqIEByZXR1cm5zIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBvcHRpb25zIHRoYXQgc2hvdWxkIGJlIHBhc3NlZCB0byB0aGUgcmVuZGVyIGZ1bmN0aW9uXG5cdCAqL1xuXHRnZXRPcHRpb25zKG5vZGU6IENhbnZhc05vZGUpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtyZXR1cm4ge307fVxufSIsImltcG9ydCBNYXQ0eDQgZnJvbSBcIi4uLy4uLy4uL0RhdGFUeXBlcy9NYXQ0eDRcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi8uLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uLy4uLy4uL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFF1YWRTaGFkZXJUeXBlIGZyb20gXCIuL1F1YWRTaGFkZXJUeXBlXCI7XG5cbi8qKiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGFiZWxTaGFkZXJUeXBlIGV4dGVuZHMgUXVhZFNoYWRlclR5cGUge1xuXG5cdGNvbnN0cnVjdG9yKHByb2dyYW1LZXk6IHN0cmluZyl7XG5cdFx0c3VwZXIocHJvZ3JhbUtleSk7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcblx0fVxuXG5cdGluaXRCdWZmZXJPYmplY3QoKTogdm9pZCB7XG5cdFx0dGhpcy5idWZmZXJPYmplY3RLZXkgPSBcImxhYmVsXCI7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIuY3JlYXRlQnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblx0fVxuXG5cdHJlbmRlcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0Y29uc3QgYmFja2dyb3VuZENvbG9yID0gb3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3IudG9XZWJHTCgpO1xuXHRcdGNvbnN0IGJvcmRlckNvbG9yID0gb3B0aW9ucy5ib3JkZXJDb2xvci50b1dlYkdMKCk7XG5cblx0XHRjb25zdCBwcm9ncmFtID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0U2hhZGVyUHJvZ3JhbSh0aGlzLnByb2dyYW1LZXkpO1xuXHRcdGNvbnN0IGJ1ZmZlciA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldEJ1ZmZlcih0aGlzLmJ1ZmZlck9iamVjdEtleSk7XG5cblx0XHRnbC51c2VQcm9ncmFtKHByb2dyYW0pO1xuXG5cdFx0Y29uc3QgdmVydGV4RGF0YSA9IHRoaXMuZ2V0VmVydGljZXMob3B0aW9ucy5zaXplLngsIG9wdGlvbnMuc2l6ZS55KTtcblxuXHRcdGNvbnN0IEZTSVpFID0gdmVydGV4RGF0YS5CWVRFU19QRVJfRUxFTUVOVDtcblxuXHRcdC8vIEJpbmQgdGhlIGJ1ZmZlclxuXHRcdGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBidWZmZXIpO1xuXHRcdGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCB2ZXJ0ZXhEYXRhLCBnbC5TVEFUSUNfRFJBVyk7XG5cblx0XHQvLyBBdHRyaWJ1dGVzXG5cdFx0Y29uc3QgYV9Qb3NpdGlvbiA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIFwiYV9Qb3NpdGlvblwiKTtcblx0XHRnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGFfUG9zaXRpb24sIDIsIGdsLkZMT0FULCBmYWxzZSwgMiAqIEZTSVpFLCAwICogRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfUG9zaXRpb24pO1xuXG5cdFx0Ly8gVW5pZm9ybXNcblx0XHRjb25zdCB1X0JhY2tncm91bmRDb2xvciA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQmFja2dyb3VuZENvbG9yXCIpO1xuXHRcdGdsLnVuaWZvcm00ZnYodV9CYWNrZ3JvdW5kQ29sb3IsIGJhY2tncm91bmRDb2xvcik7XG5cbiAgICAgICAgY29uc3QgdV9Cb3JkZXJDb2xvciA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQm9yZGVyQ29sb3JcIik7XG5cdFx0Z2wudW5pZm9ybTRmdih1X0JvcmRlckNvbG9yLCBib3JkZXJDb2xvcik7XG5cbiAgICAgICAgY29uc3QgdV9NYXhTaXplID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9NYXhTaXplXCIpO1xuICAgICAgICBnbC51bmlmb3JtMmYodV9NYXhTaXplLCAtdmVydGV4RGF0YVswXSwgdmVydGV4RGF0YVsxXSk7XG5cblx0XHQvLyBHZXQgdHJhbnNmb3JtYXRpb24gbWF0cml4XG5cdFx0Ly8gV2Ugd2FudCBhIHNxdWFyZSBmb3Igb3VyIHJlbmRlcmluZyBzcGFjZSwgc28gZ2V0IHRoZSBtYXhpbXVtIGRpbWVuc2lvbiBvZiBvdXIgcXVhZFxuXHRcdGxldCBtYXhEaW1lbnNpb24gPSBNYXRoLm1heChvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG4gICAgICAgIGNvbnN0IHVfQm9yZGVyV2lkdGggPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X0JvcmRlcldpZHRoXCIpO1xuXHRcdGdsLnVuaWZvcm0xZih1X0JvcmRlcldpZHRoLCBvcHRpb25zLmJvcmRlcldpZHRoL21heERpbWVuc2lvbik7XG5cbiAgICAgICAgY29uc3QgdV9Cb3JkZXJSYWRpdXMgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X0JvcmRlclJhZGl1c1wiKTtcblx0XHRnbC51bmlmb3JtMWYodV9Cb3JkZXJSYWRpdXMsIG9wdGlvbnMuYm9yZGVyUmFkaXVzL21heERpbWVuc2lvbik7XG5cblx0XHQvLyBUaGUgc2l6ZSBvZiB0aGUgcmVuZGVyaW5nIHNwYWNlIHdpbGwgYmUgYSBzcXVhcmUgd2l0aCB0aGlzIG1heGltdW0gZGltZW5zaW9uXG5cdFx0bGV0IHNpemUgPSBuZXcgVmVjMihtYXhEaW1lbnNpb24sIG1heERpbWVuc2lvbikuc2NhbGUoMi9vcHRpb25zLndvcmxkU2l6ZS54LCAyL29wdGlvbnMud29ybGRTaXplLnkpO1xuXG5cdFx0Ly8gQ2VudGVyIG91ciB0cmFuc2xhdGlvbnMgYXJvdW5kICgwLCAwKVxuXHRcdGNvbnN0IHRyYW5zbGF0ZVggPSAob3B0aW9ucy5wb3NpdGlvbi54IC0gb3B0aW9ucy5vcmlnaW4ueCAtIG9wdGlvbnMud29ybGRTaXplLngvMikvbWF4RGltZW5zaW9uO1xuXHRcdGNvbnN0IHRyYW5zbGF0ZVkgPSAtKG9wdGlvbnMucG9zaXRpb24ueSAtIG9wdGlvbnMub3JpZ2luLnkgLSBvcHRpb25zLndvcmxkU2l6ZS55LzIpL21heERpbWVuc2lvbjtcblxuXHRcdC8vIENyZWF0ZSBvdXIgdHJhbnNmb3JtYXRpb24gbWF0cml4XG5cdFx0dGhpcy50cmFuc2xhdGlvbi50cmFuc2xhdGUobmV3IEZsb2F0MzJBcnJheShbdHJhbnNsYXRlWCwgdHJhbnNsYXRlWV0pKTtcblx0XHR0aGlzLnNjYWxlLnNjYWxlKHNpemUpO1xuXHRcdHRoaXMucm90YXRpb24ucm90YXRlKG9wdGlvbnMucm90YXRpb24pO1xuXHRcdGxldCB0cmFuc2Zvcm1hdGlvbiA9IE1hdDR4NC5NVUxUKHRoaXMudHJhbnNsYXRpb24sIHRoaXMuc2NhbGUsIHRoaXMucm90YXRpb24pO1xuXG5cdFx0Ly8gUGFzcyB0aGUgdHJhbnNsYXRpb24gbWF0cml4IHRvIG91ciBzaGFkZXJcblx0XHRjb25zdCB1X1RyYW5zZm9ybSA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfVHJhbnNmb3JtXCIpO1xuXHRcdGdsLnVuaWZvcm1NYXRyaXg0ZnYodV9UcmFuc2Zvcm0sIGZhbHNlLCB0cmFuc2Zvcm1hdGlvbi50b0FycmF5KCkpO1xuXG5cdFx0Ly8gRHJhdyB0aGUgcXVhZFxuXHRcdGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSByZW5kZXJpbmcgc3BhY2UgYWx3YXlzIGhhcyB0byBiZSBhIHNxdWFyZSwgc28gbWFrZSBzdXJlIGl0cyBzcXVhcmUgdy5yLnQgdG8gdGhlIGxhcmdlc3QgZGltZW5zaW9uXG5cdCAqIEBwYXJhbSB3IFRoZSB3aWR0aCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHBhcmFtIGggVGhlIGhlaWdodCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2YgdGhlIHZlcnRpY2VzIG9mIHRoZSBxdWFkXG5cdCAqL1xuXHRnZXRWZXJ0aWNlcyh3OiBudW1iZXIsIGg6IG51bWJlcik6IEZsb2F0MzJBcnJheSB7XG5cdFx0bGV0IHgsIHk7XG5cblx0XHRpZihoID4gdyl7XG5cdFx0XHR5ID0gMC41O1xuXHRcdFx0eCA9IHcvKDIqaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHggPSAwLjU7XG5cdFx0XHR5ID0gaC8oMip3KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEZsb2F0MzJBcnJheShbXG5cdFx0XHQteCwgIHksXG5cdFx0XHQteCwgLXksXG5cdFx0XHQgeCwgIHksXG5cdFx0XHQgeCwgLXlcblx0XHRdKTtcblx0fVxuXG5cdGdldE9wdGlvbnMocmVjdDogTGFiZWwpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRsZXQgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiA9IHtcblx0XHRcdHBvc2l0aW9uOiByZWN0LnBvc2l0aW9uLFxuXHRcdFx0YmFja2dyb3VuZENvbG9yOiByZWN0LmNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpLFxuICAgICAgICAgICAgYm9yZGVyQ29sb3I6IHJlY3QuY2FsY3VsYXRlQm9yZGVyQ29sb3IoKSxcbiAgICAgICAgICAgIGJvcmRlcldpZHRoOiByZWN0LmJvcmRlcldpZHRoLFxuICAgICAgICAgICAgYm9yZGVyUmFkaXVzOiByZWN0LmJvcmRlclJhZGl1cyxcblx0XHRcdHNpemU6IHJlY3Quc2l6ZSxcblx0XHRcdHJvdGF0aW9uOiByZWN0LnJvdGF0aW9uXG5cdFx0fVxuXG5cdFx0cmV0dXJuIG9wdGlvbnM7XG5cdH1cbn0iLCJpbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uLy4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uLy4uLy4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUmVuZGVyaW5nVXRpbHMgZnJvbSBcIi4uLy4uLy4uL1V0aWxzL1JlbmRlcmluZ1V0aWxzXCI7XG5pbXBvcnQgU2hhZGVyVHlwZSBmcm9tIFwiLi4vU2hhZGVyVHlwZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQb2ludFNoYWRlclR5cGUgZXh0ZW5kcyBTaGFkZXJUeXBlIHtcblxuXHRwcm90ZWN0ZWQgYnVmZmVyT2JqZWN0S2V5OiBzdHJpbmc7XG5cblx0Y29uc3RydWN0b3IocHJvZ3JhbUtleTogc3RyaW5nKXtcblx0XHRzdXBlcihwcm9ncmFtS2V5KTtcblx0fVxuXG5cdGluaXRCdWZmZXJPYmplY3QoKTogdm9pZCB7XG5cdFx0dGhpcy5idWZmZXJPYmplY3RLZXkgPSBcInBvaW50XCI7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIuY3JlYXRlQnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblx0fVxuXG5cdHJlbmRlcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0bGV0IHBvc2l0aW9uID0gUmVuZGVyaW5nVXRpbHMudG9XZWJHTENvb3JkcyhvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLm9yaWdpbiwgb3B0aW9ucy53b3JsZFNpemUpO1xuXHRcdGxldCBjb2xvciA9IFJlbmRlcmluZ1V0aWxzLnRvV2ViR0xDb2xvcihvcHRpb25zLmNvbG9yKTtcblxuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gcG9zaXRpb247XG5cblx0XHRjb25zdCBGU0laRSA9IHZlcnRleERhdGEuQllURVNfUEVSX0VMRU1FTlQ7XG5cblx0XHQvLyBCaW5kIHRoZSBidWZmZXJcblx0XHRnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgYnVmZmVyKTtcblx0XHRnbC5idWZmZXJEYXRhKGdsLkFSUkFZX0JVRkZFUiwgdmVydGV4RGF0YSwgZ2wuU1RBVElDX0RSQVcpO1xuXG5cdFx0Ly8gQXR0cmlidXRlc1xuXHRcdGNvbnN0IGFfUG9zaXRpb24gPSBnbC5nZXRBdHRyaWJMb2NhdGlvbihwcm9ncmFtLCBcImFfUG9zaXRpb25cIik7XG5cdFx0Z2wudmVydGV4QXR0cmliUG9pbnRlcihhX1Bvc2l0aW9uLCAyLCBnbC5GTE9BVCwgZmFsc2UsIDIgKiBGU0laRSwgMCAqIEZTSVpFKTtcblx0XHRnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShhX1Bvc2l0aW9uKTtcblxuXHRcdC8vIFVuaWZvcm1zXG5cdFx0Y29uc3QgdV9Db2xvciA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQ29sb3JcIik7XG5cdFx0Z2wudW5pZm9ybTRmdih1X0NvbG9yLCBjb2xvcik7XG5cblx0XHRjb25zdCB1X1BvaW50U2l6ZSA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfUG9pbnRTaXplXCIpO1xuXHRcdGdsLnVuaWZvcm0xZih1X1BvaW50U2l6ZSwgb3B0aW9ucy5wb2ludFNpemUpO1xuXG5cdFx0Z2wuZHJhd0FycmF5cyhnbC5QT0lOVFMsIDAsIDEpO1xuXHR9XG5cblx0Z2V0T3B0aW9ucyhwb2ludDogUG9pbnQpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRsZXQgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiA9IHtcblx0XHRcdHBvc2l0aW9uOiBwb2ludC5wb3NpdGlvbixcblx0XHRcdGNvbG9yOiBwb2ludC5jb2xvcixcblx0XHRcdHBvaW50U2l6ZTogcG9pbnQuc2l6ZSxcblx0XHR9XG5cblx0XHRyZXR1cm4gb3B0aW9ucztcblx0fVxufSIsImltcG9ydCBNYXQ0eDQgZnJvbSBcIi4uLy4uLy4uL0RhdGFUeXBlcy9NYXQ0eDRcIjtcbmltcG9ydCBTaGFkZXJUeXBlIGZyb20gXCIuLi9TaGFkZXJUeXBlXCI7XG5cbi8qKiBSZXByZXNlbnRzIGFueSBXZWJHTCBvYmplY3RzIHRoYXQgaGF2ZSBhIHF1YWQgbWVzaCAoaS5lLiBhIHJlY3Rhbmd1bGFyIGdhbWUgb2JqZWN0IGNvbXBvc2VkIG9mIG9ubHkgdHdvIHRyaWFuZ2xlcykgKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFF1YWRTaGFkZXJUeXBlIGV4dGVuZHMgU2hhZGVyVHlwZSB7XG5cdC8qKiBUaGUga2V5IHRvIHRoZSBidWZmZXIgb2JqZWN0IGZvciB0aGlzIHNoYWRlciAqL1xuXHRwcm90ZWN0ZWQgYnVmZmVyT2JqZWN0S2V5OiBzdHJpbmc7XG5cblx0LyoqIFRoZSBzY2FsZSBtYXRyaWMgKi9cblx0cHJvdGVjdGVkIHNjYWxlOiBNYXQ0eDQ7XG5cblx0LyoqIFRoZSByb3RhdGlvbiBtYXRyaXggKi9cblx0cHJvdGVjdGVkIHJvdGF0aW9uOiBNYXQ0eDQ7XG5cblx0LyoqIFRoZSB0cmFuc2xhdGlvbiBtYXRyaXggKi9cblx0cHJvdGVjdGVkIHRyYW5zbGF0aW9uOiBNYXQ0eDQ7XG5cblx0Y29uc3RydWN0b3IocHJvZ3JhbUtleTogc3RyaW5nKXtcblx0XHRzdXBlcihwcm9ncmFtS2V5KTtcblxuXHRcdHRoaXMuc2NhbGUgPSBNYXQ0eDQuSURFTlRJVFk7XG5cdFx0dGhpcy5yb3RhdGlvbiA9IE1hdDR4NC5JREVOVElUWTtcblx0XHR0aGlzLnRyYW5zbGF0aW9uID0gTWF0NHg0LklERU5USVRZO1xuXHR9XG59IiwiaW1wb3J0IE1hdDR4NCBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL01hdDR4NFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFF1YWRTaGFkZXJUeXBlIGZyb20gXCIuL1F1YWRTaGFkZXJUeXBlXCI7XG5cbi8qKiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVjdFNoYWRlclR5cGUgZXh0ZW5kcyBRdWFkU2hhZGVyVHlwZSB7XG5cblx0Y29uc3RydWN0b3IocHJvZ3JhbUtleTogc3RyaW5nKXtcblx0XHRzdXBlcihwcm9ncmFtS2V5KTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHR9XG5cblx0aW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkIHtcblx0XHR0aGlzLmJ1ZmZlck9iamVjdEtleSA9IFwicmVjdFwiO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyLmNyZWF0ZUJ1ZmZlcih0aGlzLmJ1ZmZlck9iamVjdEtleSk7XG5cdH1cblxuXHRyZW5kZXIoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdGNvbnN0IGNvbG9yID0gb3B0aW9ucy5jb2xvci50b1dlYkdMKCk7XG5cblx0XHRjb25zdCBwcm9ncmFtID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0U2hhZGVyUHJvZ3JhbSh0aGlzLnByb2dyYW1LZXkpO1xuXHRcdGNvbnN0IGJ1ZmZlciA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldEJ1ZmZlcih0aGlzLmJ1ZmZlck9iamVjdEtleSk7XG5cblx0XHRnbC51c2VQcm9ncmFtKHByb2dyYW0pO1xuXG5cdFx0Y29uc3QgdmVydGV4RGF0YSA9IHRoaXMuZ2V0VmVydGljZXMob3B0aW9ucy5zaXplLngsIG9wdGlvbnMuc2l6ZS55KTtcblxuXHRcdGNvbnN0IEZTSVpFID0gdmVydGV4RGF0YS5CWVRFU19QRVJfRUxFTUVOVDtcblxuXHRcdC8vIEJpbmQgdGhlIGJ1ZmZlclxuXHRcdGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBidWZmZXIpO1xuXHRcdGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCB2ZXJ0ZXhEYXRhLCBnbC5TVEFUSUNfRFJBVyk7XG5cblx0XHQvLyBBdHRyaWJ1dGVzXG5cdFx0Y29uc3QgYV9Qb3NpdGlvbiA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIFwiYV9Qb3NpdGlvblwiKTtcblx0XHRnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGFfUG9zaXRpb24sIDIsIGdsLkZMT0FULCBmYWxzZSwgMiAqIEZTSVpFLCAwICogRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfUG9zaXRpb24pO1xuXG5cdFx0Ly8gVW5pZm9ybXNcblx0XHRjb25zdCB1X0NvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Db2xvclwiKTtcblx0XHRnbC51bmlmb3JtNGZ2KHVfQ29sb3IsIGNvbG9yKTtcblxuXHRcdC8vIEdldCB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHQvLyBXZSB3YW50IGEgc3F1YXJlIGZvciBvdXIgcmVuZGVyaW5nIHNwYWNlLCBzbyBnZXQgdGhlIG1heGltdW0gZGltZW5zaW9uIG9mIG91ciBxdWFkXG5cdFx0bGV0IG1heERpbWVuc2lvbiA9IE1hdGgubWF4KG9wdGlvbnMuc2l6ZS54LCBvcHRpb25zLnNpemUueSk7XG5cblx0XHQvLyBUaGUgc2l6ZSBvZiB0aGUgcmVuZGVyaW5nIHNwYWNlIHdpbGwgYmUgYSBzcXVhcmUgd2l0aCB0aGlzIG1heGltdW0gZGltZW5zaW9uXG5cdFx0bGV0IHNpemUgPSBuZXcgVmVjMihtYXhEaW1lbnNpb24sIG1heERpbWVuc2lvbikuc2NhbGUoMi9vcHRpb25zLndvcmxkU2l6ZS54LCAyL29wdGlvbnMud29ybGRTaXplLnkpO1xuXG5cdFx0Ly8gQ2VudGVyIG91ciB0cmFuc2xhdGlvbnMgYXJvdW5kICgwLCAwKVxuXHRcdGNvbnN0IHRyYW5zbGF0ZVggPSAob3B0aW9ucy5wb3NpdGlvbi54IC0gb3B0aW9ucy5vcmlnaW4ueCAtIG9wdGlvbnMud29ybGRTaXplLngvMikvbWF4RGltZW5zaW9uO1xuXHRcdGNvbnN0IHRyYW5zbGF0ZVkgPSAtKG9wdGlvbnMucG9zaXRpb24ueSAtIG9wdGlvbnMub3JpZ2luLnkgLSBvcHRpb25zLndvcmxkU2l6ZS55LzIpL21heERpbWVuc2lvbjtcblxuXHRcdC8vIENyZWF0ZSBvdXIgdHJhbnNmb3JtYXRpb24gbWF0cml4XG5cdFx0dGhpcy50cmFuc2xhdGlvbi50cmFuc2xhdGUobmV3IEZsb2F0MzJBcnJheShbdHJhbnNsYXRlWCwgdHJhbnNsYXRlWV0pKTtcblx0XHR0aGlzLnNjYWxlLnNjYWxlKHNpemUpO1xuXHRcdHRoaXMucm90YXRpb24ucm90YXRlKG9wdGlvbnMucm90YXRpb24pO1xuXHRcdGxldCB0cmFuc2Zvcm1hdGlvbiA9IE1hdDR4NC5NVUxUKHRoaXMudHJhbnNsYXRpb24sIHRoaXMuc2NhbGUsIHRoaXMucm90YXRpb24pO1xuXG5cdFx0Ly8gUGFzcyB0aGUgdHJhbnNsYXRpb24gbWF0cml4IHRvIG91ciBzaGFkZXJcblx0XHRjb25zdCB1X1RyYW5zZm9ybSA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfVHJhbnNmb3JtXCIpO1xuXHRcdGdsLnVuaWZvcm1NYXRyaXg0ZnYodV9UcmFuc2Zvcm0sIGZhbHNlLCB0cmFuc2Zvcm1hdGlvbi50b0FycmF5KCkpO1xuXG5cdFx0Ly8gRHJhdyB0aGUgcXVhZFxuXHRcdGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpO1xuXHR9XG5cblxuXHQvKlxuXHRcdFNvIGFzIGl0IHR1cm5zIG91dCwgV2ViR0wgaGFzIGFuIGlzc3VlIHdpdGggbm9uLXNxdWFyZSBxdWFkcy5cblx0XHRJdCBkb2Vzbid0IGxpa2Ugd2hlbiB5b3UgZG9uJ3QgaGF2ZSBhIDEtMSBzY2FsZSwgYW5kIHJvdGF0aW9ucyBhcmUgZW50aXJlbHkgbWVzc2VkIHVwIGlmIHRoaXMgaXMgbm90IHRoZSBjYXNlLlxuXHRcdFRvIHNvbHZlIHRoaXMsIEkgdXNlZCB0aGUgc2NhbGUgb2YgdGhlIExBUkdFU1QgZGltZW5zaW9uIG9mIHRoZSBxdWFkIHRvIG1ha2UgYSBzcXVhcmUsIHRoZW4gYWRqdXN0ZWQgdGhlIHZlcnRleCBjb29yZGluYXRlcyBpbnNpZGUgb2YgdGhhdC5cblx0XHRBIGRpYWdyYW0gb2YgdGhlIHNvbHV0aW9uIGZvbGxvd3MuXG5cblx0XHRUaGVyZSBpcyBhIGJvdW5kaW5nIHNxdWFyZSBmb3IgdGhlIHF1YWQgd2l0aCBkaW1lbnNpb25zIGh4aCAoaW4gdGhpcyBjYXNlLCBzaW5jZSBoZWlnaHQgaXMgdGhlIGxhcmdlc3QgZGltZW5zaW9uKS5cblx0XHRUaGUgb2Zmc2V0IGluIHRoZSB2ZXJ0aWNhbCBkaXJlY3Rpb24gaXMgdGhlcmVmb3JlIDAuNSwgYXMgaXQgaXMgbm9ybWFsbHkuXG5cdFx0SG93ZXZlciwgdGhlIG9mZnNldCBpbiB0aGUgaG9yaXpvbnRhbCBkaXJlY3Rpb24gaXMgbm90IHNvIHN0cmFpZ2h0Zm9yd2FyZCwgYnV0IGlzbid0IGNvbmNlcHR1YWxseSBoYXJkLlxuXHRcdEFsbCB3ZSByZWFsbHkgaGF2ZSB0byBkbyBpcyBhIHJhbmdlIGNoYW5nZSBmcm9tIFswLCBoZWlnaHQvMl0gdG8gWzAsIDAuNV0sIHdoZXJlIG91ciB2YWx1ZSBpcyB0ID0gd2lkdGgvMiwgYW5kIDAgPD0gdCA8PSBoZWlnaHQvMi5cblxuXHRcdFNvIG5vdyB3ZSBoYXZlIG91ciByZWN0LCBpbiBhIHNwYWNlIHNjYWxlZCB3aXRoIHJlc3BlY3QgdG8gdGhlIGxhcmdlc3QgZGltZW5zaW9uLlxuXHRcdFJvdGF0aW9ucyB3b3JrIGFzIHlvdSB3b3VsZCBleHBlY3QsIGV2ZW4gZm9yIGxvbmcgcmVjdGFuZ2xlcy5cblxuXHRcdFx0XHRcdDAuNVxuXHRcdFx0X18gX18gX18gX18gX18gX18gX19cblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHQtMC41fF8gX3w4ODg4ODg4ODg4OHxfIF98MC41XG5cdFx0XHR8XHR8ODg4ODg4ODg4ODh8XHR8XG5cdFx0XHR8XHR8ODg4ODg4ODg4ODh8XHR8XG5cdFx0XHR8XHR8ODg4ODg4ODg4ODh8XHR8XG5cdCAgXHRcdHxfX198ODg4ODg4ODg4ODh8X19ffFxuXHRcdFx0ICBcdFx0LTAuNVxuXG5cdFx0VGhlIGdldFZlcnRpY2VzIGZ1bmN0aW9uIGJlbG93IGRvZXMgYXMgZGVzY3JpYmVkLCBhbmQgY29udmVydHMgdGhlIHJhbmdlXG5cdCovXG5cdC8qKlxuXHQgKiBUaGUgcmVuZGVyaW5nIHNwYWNlIGFsd2F5cyBoYXMgdG8gYmUgYSBzcXVhcmUsIHNvIG1ha2Ugc3VyZSBpdHMgc3F1YXJlIHcuci50IHRvIHRoZSBsYXJnZXN0IGRpbWVuc2lvblxuXHQgKiBAcGFyYW0gdyBUaGUgd2lkdGggb2YgdGhlIHF1YWQgaW4gcGl4ZWxzXG5cdCAqIEBwYXJhbSBoIFRoZSBoZWlnaHQgb2YgdGhlIHF1YWQgaW4gcGl4ZWxzXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHRoZSB2ZXJ0aWNlcyBvZiB0aGUgcXVhZFxuXHQgKi9cblx0Z2V0VmVydGljZXModzogbnVtYmVyLCBoOiBudW1iZXIpOiBGbG9hdDMyQXJyYXkge1xuXHRcdGxldCB4LCB5O1xuXG5cdFx0aWYoaCA+IHcpe1xuXHRcdFx0eSA9IDAuNTtcblx0XHRcdHggPSB3LygyKmgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR4ID0gMC41O1xuXHRcdFx0eSA9IGgvKDIqdyk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0LXgsICB5LFxuXHRcdFx0LXgsIC15LFxuXHRcdFx0IHgsICB5LFxuXHRcdFx0IHgsIC15XG5cdFx0XSk7XG5cdH1cblxuXHRnZXRPcHRpb25zKHJlY3Q6IFJlY3QpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRsZXQgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiA9IHtcblx0XHRcdHBvc2l0aW9uOiByZWN0LnBvc2l0aW9uLFxuXHRcdFx0Y29sb3I6IHJlY3QuY29sb3IsXG5cdFx0XHRzaXplOiByZWN0LnNpemUsXG5cdFx0XHRyb3RhdGlvbjogcmVjdC5yb3RhdGlvblxuXHRcdH1cblxuXHRcdHJldHVybiBvcHRpb25zO1xuXHR9XG59IiwiaW1wb3J0IE1hdDR4NCBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL01hdDR4NFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uLy4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUXVhZFNoYWRlclR5cGUgZnJvbSBcIi4vUXVhZFNoYWRlclR5cGVcIjtcblxuLyoqIEEgc2hhZGVyIGZvciBzcHJpdGVzIGFuZCBhbmltYXRlZCBzcHJpdGVzICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcHJpdGVTaGFkZXJUeXBlIGV4dGVuZHMgUXVhZFNoYWRlclR5cGUge1xuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdH1cblxuXHRpbml0QnVmZmVyT2JqZWN0KCk6IHZvaWQge1xuXHRcdHRoaXMuYnVmZmVyT2JqZWN0S2V5ID0gXCJzcHJpdGVcIjtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5jcmVhdGVCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXHR9XG5cblx0cmVuZGVyKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRjb25zdCBwcm9ncmFtID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0U2hhZGVyUHJvZ3JhbSh0aGlzLnByb2dyYW1LZXkpO1xuXHRcdGNvbnN0IGJ1ZmZlciA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldEJ1ZmZlcih0aGlzLmJ1ZmZlck9iamVjdEtleSk7XG5cdFx0Y29uc3QgdGV4dHVyZSA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldFRleHR1cmUob3B0aW9ucy5pbWFnZUtleSk7XG5cblx0XHRnbC51c2VQcm9ncmFtKHByb2dyYW0pO1xuXG5cdFx0Y29uc3QgdmVydGV4RGF0YSA9IHRoaXMuZ2V0VmVydGljZXMob3B0aW9ucy5zaXplLngsIG9wdGlvbnMuc2l6ZS55LCBvcHRpb25zLnNjYWxlKTtcblxuXHRcdGNvbnN0IEZTSVpFID0gdmVydGV4RGF0YS5CWVRFU19QRVJfRUxFTUVOVDtcblxuXHRcdC8vIEJpbmQgdGhlIGJ1ZmZlclxuXHRcdGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBidWZmZXIpO1xuXHRcdGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCB2ZXJ0ZXhEYXRhLCBnbC5TVEFUSUNfRFJBVyk7XG5cblx0XHQvLyBBdHRyaWJ1dGVzXG5cdFx0Y29uc3QgYV9Qb3NpdGlvbiA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIFwiYV9Qb3NpdGlvblwiKTtcblx0XHRnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGFfUG9zaXRpb24sIDIsIGdsLkZMT0FULCBmYWxzZSwgNCAqIEZTSVpFLCAwICogRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfUG9zaXRpb24pO1xuXG5cdFx0Y29uc3QgYV9UZXhDb29yZCA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIFwiYV9UZXhDb29yZFwiKTtcblx0XHRnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGFfVGV4Q29vcmQsIDIsIGdsLkZMT0FULCBmYWxzZSwgNCAqIEZTSVpFLCAyKkZTSVpFKTtcblx0XHRnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShhX1RleENvb3JkKTtcblxuXHRcdC8vIFVuaWZvcm1zXG5cdFx0Ly8gR2V0IHRyYW5zZm9ybWF0aW9uIG1hdHJpeFxuXHRcdC8vIFdlIHdhbnQgYSBzcXVhcmUgZm9yIG91ciByZW5kZXJpbmcgc3BhY2UsIHNvIGdldCB0aGUgbWF4aW11bSBkaW1lbnNpb24gb2Ygb3VyIHF1YWRcblx0XHRsZXQgbWF4RGltZW5zaW9uID0gTWF0aC5tYXgob3B0aW9ucy5zaXplLngsIG9wdGlvbnMuc2l6ZS55KTtcblxuXHRcdC8vIFRoZSBzaXplIG9mIHRoZSByZW5kZXJpbmcgc3BhY2Ugd2lsbCBiZSBhIHNxdWFyZSB3aXRoIHRoaXMgbWF4aW11bSBkaW1lbnNpb25cblx0XHRsZXQgc2l6ZSA9IG5ldyBWZWMyKG1heERpbWVuc2lvbiwgbWF4RGltZW5zaW9uKS5zY2FsZSgyL29wdGlvbnMud29ybGRTaXplLngsIDIvb3B0aW9ucy53b3JsZFNpemUueSk7XG5cblx0XHQvLyBDZW50ZXIgb3VyIHRyYW5zbGF0aW9ucyBhcm91bmQgKDAsIDApXG5cdFx0Y29uc3QgdHJhbnNsYXRlWCA9IChvcHRpb25zLnBvc2l0aW9uLnggLSBvcHRpb25zLm9yaWdpbi54IC0gb3B0aW9ucy53b3JsZFNpemUueC8yKS9tYXhEaW1lbnNpb247XG5cdFx0Y29uc3QgdHJhbnNsYXRlWSA9IC0ob3B0aW9ucy5wb3NpdGlvbi55IC0gb3B0aW9ucy5vcmlnaW4ueSAtIG9wdGlvbnMud29ybGRTaXplLnkvMikvbWF4RGltZW5zaW9uO1xuXG5cdFx0Ly8gQ3JlYXRlIG91ciB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHR0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShuZXcgRmxvYXQzMkFycmF5KFt0cmFuc2xhdGVYLCB0cmFuc2xhdGVZXSkpO1xuXHRcdHRoaXMuc2NhbGUuc2NhbGUoc2l6ZSk7XG5cdFx0dGhpcy5yb3RhdGlvbi5yb3RhdGUob3B0aW9ucy5yb3RhdGlvbik7XG5cdFx0bGV0IHRyYW5zZm9ybWF0aW9uID0gTWF0NHg0Lk1VTFQodGhpcy50cmFuc2xhdGlvbiwgdGhpcy5zY2FsZSwgdGhpcy5yb3RhdGlvbik7XG5cblx0XHQvLyBQYXNzIHRoZSB0cmFuc2xhdGlvbiBtYXRyaXggdG8gb3VyIHNoYWRlclxuXHRcdGNvbnN0IHVfVHJhbnNmb3JtID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9UcmFuc2Zvcm1cIik7XG5cdFx0Z2wudW5pZm9ybU1hdHJpeDRmdih1X1RyYW5zZm9ybSwgZmFsc2UsIHRyYW5zZm9ybWF0aW9uLnRvQXJyYXkoKSk7XG5cblx0XHQvLyBTZXQgdXAgb3VyIHNhbXBsZXIgd2l0aCBvdXIgYXNzaWduZWQgdGV4dHVyZSB1bml0XG5cdFx0Y29uc3QgdV9TYW1wbGVyID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9TYW1wbGVyXCIpO1xuXHRcdGdsLnVuaWZvcm0xaSh1X1NhbXBsZXIsIHRleHR1cmUpO1xuXG5cdFx0Ly8gUGFzcyBpbiB0ZXhTaGlmdFxuXHRcdGNvbnN0IHVfdGV4U2hpZnQgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X3RleFNoaWZ0XCIpO1xuXHRcdGdsLnVuaWZvcm0yZnYodV90ZXhTaGlmdCwgb3B0aW9ucy50ZXhTaGlmdCk7XG5cblx0XHQvLyBQYXNzIGluIHRleFNjYWxlXG5cdFx0Y29uc3QgdV90ZXhTY2FsZSA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfdGV4U2NhbGVcIik7XG5cdFx0Z2wudW5pZm9ybTJmdih1X3RleFNjYWxlLCBvcHRpb25zLnRleFNjYWxlKTtcblxuXHRcdC8vIERyYXcgdGhlIHF1YWRcblx0XHRnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFX1NUUklQLCAwLCA0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgcmVuZGVyaW5nIHNwYWNlIGFsd2F5cyBoYXMgdG8gYmUgYSBzcXVhcmUsIHNvIG1ha2Ugc3VyZSBpdHMgc3F1YXJlIHcuci50IHRvIHRoZSBsYXJnZXN0IGRpbWVuc2lvblxuXHQgKiBAcGFyYW0gdyBUaGUgd2lkdGggb2YgdGhlIHF1YWQgaW4gcGl4ZWxzXG5cdCAqIEBwYXJhbSBoIFRoZSBoZWlnaHQgb2YgdGhlIHF1YWQgaW4gcGl4ZWxzXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHRoZSB2ZXJ0aWNlcyBvZiB0aGUgcXVhZFxuXHQgKi9cblx0Z2V0VmVydGljZXModzogbnVtYmVyLCBoOiBudW1iZXIsIHNjYWxlOiBGbG9hdDMyQXJyYXkpOiBGbG9hdDMyQXJyYXkge1xuXHRcdGxldCB4LCB5O1xuXG5cdFx0aWYoaCA+IHcpe1xuXHRcdFx0eSA9IDAuNTtcblx0XHRcdHggPSB3LygyKmgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR4ID0gMC41O1xuXHRcdFx0eSA9IGgvKDIqdyk7XG5cdFx0fVxuXG5cdFx0Ly8gU2NhbGUgdGhlIHJlbmRlcmluZyBzcGFjZSBpZiBuZWVkZWRcblx0XHR4ICo9IHNjYWxlWzBdO1xuXHRcdHkgKj0gc2NhbGVbMV07XG5cblx0XHRyZXR1cm4gbmV3IEZsb2F0MzJBcnJheShbXG5cdFx0XHQteCwgIHksIDAuMCwgMC4wLFxuXHRcdFx0LXgsIC15LCAwLjAsIDEuMCxcblx0XHRcdCB4LCAgeSwgMS4wLCAwLjAsXG5cdFx0XHQgeCwgLXksIDEuMCwgMS4wXG5cdFx0XSk7XG5cdH1cblxuXHRnZXRPcHRpb25zKHNwcml0ZTogU3ByaXRlKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG5cdFx0bGV0IHRleFNoaWZ0O1xuXHRcdGxldCB0ZXhTY2FsZTtcblxuXHRcdGlmKHNwcml0ZSBpbnN0YW5jZW9mIEFuaW1hdGVkU3ByaXRlKXtcblx0XHRcdGxldCBhbmltYXRpb25JbmRleCA9IHNwcml0ZS5hbmltYXRpb24uZ2V0SW5kZXhBbmRBZHZhbmNlQW5pbWF0aW9uKCk7XG5cdFx0XHRsZXQgb2Zmc2V0ID0gc3ByaXRlLmdldEFuaW1hdGlvbk9mZnNldChhbmltYXRpb25JbmRleCk7XG5cdFx0XHR0ZXhTaGlmdCA9IG5ldyBGbG9hdDMyQXJyYXkoW29mZnNldC54IC8gKHNwcml0ZS5jb2xzICogc3ByaXRlLnNpemUueCksIG9mZnNldC55IC8gKHNwcml0ZS5yb3dzICogc3ByaXRlLnNpemUueSldKTtcblx0XHRcdHRleFNjYWxlID0gbmV3IEZsb2F0MzJBcnJheShbMS8oc3ByaXRlLmNvbHMpLCAxLyhzcHJpdGUucm93cyldKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGV4U2hpZnQgPSBuZXcgRmxvYXQzMkFycmF5KFswLCAwXSk7XG5cdFx0XHR0ZXhTY2FsZSA9IG5ldyBGbG9hdDMyQXJyYXkoWzEsIDFdKTtcblx0XHR9XG5cblx0XHRsZXQgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiA9IHtcblx0XHRcdHBvc2l0aW9uOiBzcHJpdGUucG9zaXRpb24sXG5cdFx0XHRyb3RhdGlvbjogc3ByaXRlLnJvdGF0aW9uLFxuXHRcdFx0c2l6ZTogc3ByaXRlLnNpemUsXG5cdFx0XHRzY2FsZTogc3ByaXRlLnNjYWxlLnRvQXJyYXkoKSxcblx0XHRcdGltYWdlS2V5OiBzcHJpdGUuaW1hZ2VJZCxcblx0XHRcdHRleFNoaWZ0LFxuXHRcdFx0dGV4U2NhbGVcblx0XHR9XG5cblx0XHRyZXR1cm4gb3B0aW9ucztcblx0fVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBRdWV1ZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1F1ZXVlXCI7XG5pbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhIH0gZnJvbSBcIi4uL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBTdHJpbmdVdGlscyBmcm9tIFwiLi4vVXRpbHMvU3RyaW5nVXRpbHNcIjtcbmltcG9ydCBBdWRpb01hbmFnZXIgZnJvbSBcIi4uL1NvdW5kL0F1ZGlvTWFuYWdlclwiO1xuaW1wb3J0IFNwcml0ZXNoZWV0IGZyb20gXCIuLi9EYXRhVHlwZXMvU3ByaXRlc2hlZXRcIjtcbmltcG9ydCBXZWJHTFByb2dyYW1UeXBlIGZyb20gXCIuLi9EYXRhVHlwZXMvUmVuZGVyaW5nL1dlYkdMUHJvZ3JhbVR5cGVcIjtcblxuLyoqXG4gKiBUaGUgcmVzb3VyY2UgbWFuYWdlciBmb3IgdGhlIGdhbWUgZW5naW5lLlxuICogVGhlIHJlc291cmNlIG1hbmFnZXIgaW50ZXJmYWNlcyB3aXRoIHRoZSBsb2FkYWJsZSBhc3NldHMgb2YgYSBnYW1lIHN1Y2ggYXMgaW1hZ2VzLCBkYXRhIGZpbGVzLFxuICogYW5kIHNvdW5kcywgd2hpY2ggYXJlIGFsbCBmb3VuZCBpbiB0aGUgZGlzdCBmb2xkZXIuXG4gKiBUaGlzIGNsYXNzIGNvbnRyb2xzIGxvYWRpbmcgYW5kIHVwZGF0ZXMgdGhlIEByZWZlcmVuY2VbU2NlbmVdIHdpdGggdGhlIGxvYWRpbmcgcHJvZ3Jlc3MsIHNvIHRoYXQgdGhlIHNjZW5lIGRvZXMgXG4gKiBub3Qgc3RhcnQgYmVmb3JlIGFsbCBuZWNlc3NhcnkgYXNzZXRzIGFyZSBsb2FkZWQuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlc291cmNlTWFuYWdlciB7XG4gICAgLy8gSW5zdGFuY2UgZm9yIHRoZSBzaW5nbGV0b24gY2xhc3NcbiAgICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogUmVzb3VyY2VNYW5hZ2VyO1xuXG4gICAgLy8gQm9vbGVhbnMgdG8ga2VlcCB0cmFjayBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgUmVzb3VyY2VNYW5hZ2VyIGlzIGN1cnJlbnRseSBsb2FkaW5nIHNvbWV0aGluZ1xuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCBhbnkgcmVzb3VyY2VzIGFyZSBsb2FkaW5nICovXG4gICAgcHJpdmF0ZSBsb2FkaW5nOiBib29sZWFuO1xuICAgIC8qKiBBIGJvb2xlYW4gdG8gaW5kaWNhdGUgdGhhdCB0aGUgYXNzZXRzIGp1c3QgZmluaXNoZWQgbG9hZGluZyAqL1xuICAgIHByaXZhdGUganVzdExvYWRlZDogYm9vbGVhbjtcblxuICAgIC8vIEZ1bmN0aW9ucyB0byBkbyBzb21ldGhpbmcgd2hlbiBsb2FkaW5nIHByb2dyZXNzZXMgb3IgaXMgY29tcGxldGVkIHN1Y2ggYXMgcmVuZGVyIGEgbG9hZGluZyBzY3JlZW5cbiAgICAvKiogQSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIGxvYWRpbmcgcHJvZ3Jlc3NlcyAqL1xuICAgIHB1YmxpYyBvbkxvYWRQcm9ncmVzczogRnVuY3Rpb247XG4gICAgLyoqIEEgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiBsb2FkaW5nIGNvbXBsZXRlcyAqL1xuICAgIHB1YmxpYyBvbkxvYWRDb21wbGV0ZTogRnVuY3Rpb247XG5cblxuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSBpbWFnZXMgbmVlZCB0byBiZSBsb2FkZWQqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfaW1hZ2VzTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IGltYWdlcyBhcmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9pbWFnZXNUb0xvYWQ6IG51bWJlcjtcbiAgICAvKiogVGhlIHF1ZXVlIG9mIGltYWdlcyB3ZSBtdXN0IGxvYWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlOiBRdWV1ZTxLZXlQYXRoUGFpcj47XG4gICAgLyoqIEEgbWFwIG9mIHRoZSBpbWFnZXMgdGhhdCBhcmUgY3VycmVudGx5IGxvYWRlZCBhbmQgYmVpbmcgdXNlZCBieSB0aGUgc2NlbmUuIFRoZSByZWZlcmVuY2UgdG8gdGhlc2UgaW1hZ2VzIG9ubHkgZXhpc3QgaGVyZSBmb3IgZWFzeSBjbGVhbnVwLiAqL1xuICAgIHByaXZhdGUgaW1hZ2VzOiBNYXA8SFRNTEltYWdlRWxlbWVudD47XG5cbiAgICAvKiogTnVtYmVyIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgdGlsZW1hcHMgbmVlZCB0byBiZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3Nwcml0ZXNoZWV0c0xvYWRlZDogbnVtYmVyO1xuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSB0aWxlbWFwcyBhcmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9zcHJpdGVzaGVldHNUb0xvYWQ6IG51bWJlcjtcbiAgICAvKiogVGhlIHF1ZXVlIG9mIHRpbGVtYXBzIHdlIG11c3QgbG9hZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIHRpbGVtYXBzIHRoYXQgYXJlIGN1cnJlbnRseSBsb2FkZWQgYW5kIChwcmVzdW1hYmx5KSBiZWluZyB1c2VkIGJ5IHRoZSBzY2VuZSAqL1xuICAgIHByaXZhdGUgc3ByaXRlc2hlZXRzOiBNYXA8U3ByaXRlc2hlZXQ+O1xuXG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRpbGVtYXBzIG5lZWQgdG8gYmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV90aWxlbWFwc0xvYWRlZDogbnVtYmVyO1xuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSB0aWxlbWFwcyBhcmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV90aWxlbWFwc1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2YgdGlsZW1hcHMgd2UgbXVzdCBsb2FkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV90aWxlbWFwTG9hZGluZ1F1ZXVlOiBRdWV1ZTxLZXlQYXRoUGFpcj47XG4gICAgLyoqIEEgbWFwIG9mIHRoZSB0aWxlbWFwcyB0aGF0IGFyZSBjdXJyZW50bHkgbG9hZGVkIGFuZCAocHJlc3VtYWJseSkgYmVpbmcgdXNlZCBieSB0aGUgc2NlbmUgKi9cbiAgICBwcml2YXRlIHRpbGVtYXBzOiBNYXA8VGlsZWRUaWxlbWFwRGF0YT47XG5cbiAgICAvKiogTnVtYmVyIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgc291bmRzIG5lZWQgdG8gYmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9hdWRpb0xvYWRlZDogbnVtYmVyO1xuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSBzb3VuZHMgYXJlIGxvYWRlZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfYXVkaW9Ub0xvYWQ6IG51bWJlcjtcbiAgICAvKiogVGhlIHF1ZXVlIG9mIHNvdW5kcyB3ZSBtdXN0IGxvYWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X2F1ZGlvTG9hZGluZ1F1ZXVlOiBRdWV1ZTxLZXlQYXRoUGFpcj47XG4gICAgLyoqIEEgbWFwIG9mIHRoZSBzb3VuZHMgdGhhdCBhcmUgY3VycmVudGx5IGxvYWRlZCBhbmQgKHByZXN1bWFibHkpIGJlaW5nIHVzZWQgYnkgdGhlIHNjZW5lICovXG4gICAgcHJpdmF0ZSBhdWRpb0J1ZmZlcnM6IE1hcDxBdWRpb0J1ZmZlcj47XG5cbiAgICAvKiogVGhlIHRvdGFsIG51bWJlciBvZiBcInR5cGVzXCIgb2YgdGhpbmdzIHRoYXQgbmVlZCB0byBiZSBsb2FkZWQgKGkuZS4gaW1hZ2VzIGFuZCB0aWxlbWFwcykgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3R5cGVzVG9Mb2FkOiBudW1iZXI7XG5cbiAgICBwcml2YXRlIGxvYWRvbmx5X2pzb25Mb2FkZWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGxvYWRvbmx5X2pzb25Ub0xvYWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGxvYWRvbmx5X2pzb25Mb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICBwcml2YXRlIGpzb25PYmplY3RzOiBNYXA8UmVjb3JkPHN0cmluZywgYW55Pj47XG5cbiAgICAvKiAjIyMjIyMjIyMjIElORk9STUFUSU9OIFNQRUNJQUwgVE8gV0VCR0wgIyMjIyMjIyMjIyAqL1xuICAgIHByaXZhdGUgZ2xfV2ViR0xBY3RpdmU6IGJvb2xlYW47XG5cbiAgICBwcml2YXRlIGxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zTG9hZGVkOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBsb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc1RvTG9hZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfZ2xfU2hhZGVyTG9hZGluZ1F1ZXVlOiBRdWV1ZTxLZXlQYXRoX1NoYWRlcj47XG5cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkZWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWU6IFF1ZXVlPEtleU1hcFBhaXI+O1xuXG4gICAgcHJpdmF0ZSBnbF9TaGFkZXJQcm9ncmFtczogTWFwPFdlYkdMUHJvZ3JhbVR5cGU+O1xuXG4gICAgcHJpdmF0ZSBnbF9UZXh0dXJlczogTWFwPG51bWJlcj47XG4gICAgcHJpdmF0ZSBnbF9OZXh0VGV4dHVyZUlEOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBnbF9CdWZmZXJzOiBNYXA8V2ViR0xCdWZmZXI+O1xuXG4gICAgcHJpdmF0ZSBnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0O1xuXG4gICAgLyogIyMjIyMjIyMjIyBVTkxPQURJTkcgQU5EIEVYQ0xVU0lPTiBMSVNUICMjIyMjIyMjIyMgKi9cbiAgICAvKiogQSBsaXN0IG9mIHJlc291cmNlcyB0aGF0IHdpbGwgYmUgdW5sb2FkZWQgYXQgdGhlIGVuZCBvZiB0aGUgY3VycmVudCBzY2VuZSAqL1xuICAgIHByaXZhdGUgcmVzb3VyY2VzVG9VbmxvYWQ6IEFycmF5PFJlc291cmNlUmVmZXJlbmNlPjtcblxuICAgIC8qKiBBIGxpc3Qgb2YgcmVzb3VyY2VzIHRvIGtlZXAgdW50aWwgZnVydGhlciBub3RpY2UgKi9cbiAgICBwcml2YXRlIHJlc291cmNlc1RvS2VlcDogQXJyYXk8UmVzb3VyY2VSZWZlcmVuY2U+O1xuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuanVzdExvYWRlZCA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VzTG9hZGVkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZXNUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgICAgIHRoaXMuaW1hZ2VzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0TG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgICAgIHRoaXMuc3ByaXRlc2hlZXRzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNMb2FkZWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwTG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgICAgIHRoaXMudGlsZW1hcHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRlZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfYXVkaW9Ub0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgICAgIHRoaXMuYXVkaW9CdWZmZXJzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfanNvbkxvYWRlZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfanNvblRvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfanNvbkxvYWRpbmdRdWV1ZSA9IG5ldyBRdWV1ZSgpO1xuICAgICAgICB0aGlzLmpzb25PYmplY3RzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zVG9Mb2FkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcblxuICAgICAgICB0aGlzLmdsX1NoYWRlclByb2dyYW1zID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMuZ2xfVGV4dHVyZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZ2xfTmV4dFRleHR1cmVJRCA9IDA7XG4gICAgICAgIHRoaXMuZ2xfQnVmZmVycyA9IG5ldyBNYXAoKTtcblxuICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMucmVzb3VyY2VzVG9LZWVwID0gbmV3IEFycmF5KCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgfTtcblxuICAgIC8qICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgU0lOR0xFVE9OICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMqL1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhpcyBjbGFzcyBvciBhIG5ldyBpbnN0YW5jZSBpZiBub25lIGV4aXN0XG4gICAgICogQHJldHVybnMgVGhlIHJlc291cmNlIG1hbmFnZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogUmVzb3VyY2VNYW5hZ2VyIHtcbiAgICAgICAgaWYgKCF0aGlzLmluc3RhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLmluc3RhbmNlID0gbmV3IFJlc291cmNlTWFuYWdlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBQVUJMSUMgRlVOQ1RJT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG4gICAgLyoqXG4gICAgICogQWN0aXZhdGVzIG9yIGRlYWN0aXZhdGVzIHRoZSB1c2Ugb2YgV2ViR0xcbiAgICAgKiBAcGFyYW0gZmxhZyBUcnVlIGlmIFdlYkdMIHNob3VsZCBiZSB1c2VkLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKiBAcGFyYW0gZ2wgVGhlIGluc3RhbmNlIG9mIHRoZSBncmFwaGljcyBjb250ZXh0LCBpZiBhcHBsaWNhYmxlXG4gICAgICovXG4gICAgcHVibGljIHVzZVdlYkdMKGZsYWc6IGJvb2xlYW4sIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nbF9XZWJHTEFjdGl2ZSA9IGZsYWc7XG5cbiAgICAgICAgaWYgKHRoaXMuZ2xfV2ViR0xBY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuZ2wgPSBnbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFuIGltYWdlIGZyb20gZmlsZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgdGhlIGxvYWRlZCBpbWFnZSB3aXRoXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIGltYWdlIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwdWJsaWMgaW1hZ2Uoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZWxscyB0aGUgcmVzb3VyY2UgbWFuYWdlciB0byBrZWVwIHRoaXMgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHJlc291cmNlXG4gICAgICovXG4gICAgcHVibGljIGtlZXBJbWFnZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmtlZXBSZXNvdXJjZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGEgbG9hZGVkIGltYWdlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBsb2FkZWQgaW1hZ2VcbiAgICAgKiBAcmV0dXJucyBUaGUgaW1hZ2UgZWxlbWVudCBhc3NvY2lhdGVkIHdpdGggdGhpcyBrZXlcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0SW1hZ2Uoa2V5OiBzdHJpbmcpOiBIVE1MSW1hZ2VFbGVtZW50IHtcbiAgICAgICAgbGV0IGltYWdlID0gdGhpcy5pbWFnZXMuZ2V0KGtleSk7XG4gICAgICAgIC8vIGlmIChpbWFnZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vICAgICB0aHJvdyBgVGhlcmUgaXMgbm8gaW1hZ2UgYXNzb2NpYXRlZCB3aXRoIGtleSBcIiR7a2V5fVwiYFxuICAgICAgICAvLyB9XG4gICAgICAgIHJldHVybiBpbWFnZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHNwcml0ZXNoZWV0IGZyb20gZmlsZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgdGhlIGxvYWRlZCBzcHJpdGVzaGVldCB3aXRoXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIHNwcml0ZXNoZWV0IHRvIGxvYWRcbiAgICAgKi9cbiAgICBwdWJsaWMgc3ByaXRlc2hlZXQoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0TG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZWxscyB0aGUgcmVzb3VyY2UgbWFuYWdlciB0byBrZWVwIHRoaXMgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHJlc291cmNlXG4gICAgICovXG4gICAgcHVibGljIGtlZXBTcHJpdGVzaGVldChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmtlZXBSZXNvdXJjZShrZXksIFJlc291cmNlVHlwZS5TUFJJVEVTSEVFVCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGEgbG9hZGVkIHNwcml0ZXNoZWV0XG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBzcHJpdGVzaGVldCB0byBsb2FkXG4gICAgICogQHJldHVybnMgVGhlIGxvYWRlZCBTcHJpdGVzaGVldFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTcHJpdGVzaGVldChrZXk6IHN0cmluZyk6IFNwcml0ZXNoZWV0IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3ByaXRlc2hlZXRzLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFuIGF1ZGlvIGZpbGVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGxvYWRlZCBhdWRpbyBmaWxlXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIGF1ZGlvIGZpbGUgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBhdWRpbyhrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcEF1ZGlvKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2VlcFJlc291cmNlKGtleSwgUmVzb3VyY2VUeXBlLkFVRElPKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBsb2FkZWQgYXVkaW8gZmlsZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICogQHJldHVybnMgVGhlIEF1ZGlvQnVmZmVyIGNyZWF0ZWQgZnJvbSB0aGUgbG9hZGVkIGF1ZGlvIGZsZVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRBdWRpbyhrZXk6IHN0cmluZyk6IEF1ZGlvQnVmZmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXVkaW9CdWZmZXJzLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWQgYSB0aWxlbWFwIGZyb20gYSBqc29uIGZpbGUuIEF1dG9tYXRpY2FsbHkgbG9hZHMgcmVsYXRlZCBpbWFnZXNcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGxvYWRlZCB0aWxlbWFwXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIHRpbGVtYXAgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyB0aWxlbWFwKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZWxscyB0aGUgcmVzb3VyY2UgbWFuYWdlciB0byBrZWVwIHRoaXMgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHJlc291cmNlXG4gICAgICovXG4gICAgcHVibGljIGtlZXBUaWxlbWFwKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2VlcFJlc291cmNlKGtleSwgUmVzb3VyY2VUeXBlLlRJTEVNQVApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJlaXZlcyBhIGxvYWRlZCB0aWxlbWFwXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBsb2FkZWQgdGlsZW1hcFxuICAgICAqIEByZXR1cm5zIFRoZSB0aWxlbWFwIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBrZXlcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VGlsZW1hcChrZXk6IHN0cmluZyk6IFRpbGVkVGlsZW1hcERhdGEge1xuICAgICAgICByZXR1cm4gdGhpcy50aWxlbWFwcy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbiBvYmplY3QgZnJvbSBhIGpzb24gZmlsZS5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGxvYWRlZCBvYmplY3RcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUganNvbiBmaWxlIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwdWJsaWMgb2JqZWN0KGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZWxscyB0aGUgcmVzb3VyY2UgbWFuYWdlciB0byBrZWVwIHRoaXMgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHJlc291cmNlXG4gICAgICovXG4gICAgcHVibGljIGtlZXBPYmplY3Qoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwUmVzb3VyY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSlNPTik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmVpdmVzIGEgbG9hZGVkIG9iamVjdFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgbG9hZGVkIG9iamVjdFxuICAgICAqIEByZXR1cm5zIFRoZSBvYmplY3QgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlIGtleVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRPYmplY3Qoa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuanNvbk9iamVjdHMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBMT0FEIEZVTkNUSU9OICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMqL1xuICAgIC8qKlxuICAgICAqIExvYWRzIGFsbCByZXNvdXJjZXMgY3VycmVudGx5IGluIHRoZSBxdWV1ZVxuICAgICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gY2FsIHdoZW4gdGhlIHJlc291cmNlcyBhcmUgZmluaXNoZWQgbG9hZGluZ1xuICAgICAqL1xuICAgIGxvYWRSZXNvdXJjZXNGcm9tUXVldWUoY2FsbGJhY2s6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdHlwZXNUb0xvYWQgPSA1O1xuXG4gICAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG5cbiAgICAgICAgLy8gTG9hZCBldmVyeXRoaW5nIGluIHRoZSBxdWV1ZXMuIFRpbGVtYXBzIGhhdmUgdG8gY29tZSBiZWZvcmUgaW1hZ2VzIGJlY2F1c2UgdGhleSB3aWxsIGFkZCBuZXcgaW1hZ2VzIHRvIHRoZSBxdWV1ZVxuXG4gICAgICAgIHRoaXMubG9hZFRpbGVtYXBPYmplY3RGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgVGlsZW1hcE9iamVjdHNcIik7XG4gICAgICAgICAgICB0aGlzLmxvYWRUaWxlbWFwc0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgVGlsZW1hcHNcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkU3ByaXRlc2hlZXRzRnJvbVF1ZXVlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgU3ByaXRlc2hlZXRzXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRJbWFnZXNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgSW1hZ2VzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkQXVkaW9Gcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGVkIEF1ZGlvXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZE9iamVjdHNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBPYmplY3RzXCIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdsX0xvYWRTaGFkZXJzRnJvbVF1ZXVlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBTaGFkZXJzXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoTG9hZGluZyhjYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoTG9hZGluZyhjYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZmluaXNoTG9hZGluZyhjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgLy8gRG9uZSBsb2FkaW5nXG4gICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmp1c3RMb2FkZWQgPSB0cnVlO1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIC8qICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgVU5MT0FEIEZVTkNUSU9OICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMqL1xuXG4gICAgcHJpdmF0ZSBrZWVwUmVzb3VyY2Uoa2V5OiBzdHJpbmcsIHR5cGU6IFJlc291cmNlVHlwZSk6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZyhcIktlZXAgcmVzb3VyY2UuLi5cIik7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IHJlc291cmNlID0gdGhpcy5yZXNvdXJjZXNUb1VubG9hZFtpXTtcbiAgICAgICAgICAgIGlmIChyZXNvdXJjZS5rZXkgPT09IGtleSAmJiByZXNvdXJjZS5yZXNvdXJjZVR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkZvdW5kIHJlc291cmNlIFwiICsga2V5ICsgXCIgb2YgdHlwZSBcIiArIHR5cGUgKyBcIi4gS2VlcGluZy5cIik7XG4gICAgICAgICAgICAgICAgbGV0IHJlc291cmNlVG9Nb3ZlID0gdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb0tlZXAucHVzaCguLi5yZXNvdXJjZVRvTW92ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVsZXRlcyByZWZlcmVuY2VzIHRvIGFsbCByZXNvdXJjZXMgaW4gdGhlIHJlc291cmNlIG1hbmFnZXJcbiAgICAgKi9cbiAgICB1bmxvYWRBbGxSZXNvdXJjZXMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmp1c3RMb2FkZWQgPSBmYWxzZTtcblxuICAgICAgICBmb3IgKGxldCByZXNvdXJjZSBvZiB0aGlzLnJlc291cmNlc1RvVW5sb2FkKSB7XG4gICAgICAgICAgICAvLyBVbmxvYWQgdGhlIHJlc291cmNlXG4gICAgICAgICAgICB0aGlzLnVubG9hZFJlc291cmNlKHJlc291cmNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgdW5sb2FkUmVzb3VyY2UocmVzb3VyY2U6IFJlc291cmNlUmVmZXJlbmNlKTogdm9pZCB7XG4gICAgICAgIC8vIERlbGV0ZSB0aGUgcmVzb3VyY2UgaXRzZWxmXG4gICAgICAgIHN3aXRjaCAocmVzb3VyY2UucmVzb3VyY2VUeXBlKSB7XG4gICAgICAgICAgICBjYXNlIFJlc291cmNlVHlwZS5JTUFHRTpcbiAgICAgICAgICAgICAgICB0aGlzLmltYWdlcy5kZWxldGUocmVzb3VyY2Uua2V5KTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5nbF9XZWJHTEFjdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdsX1RleHR1cmVzLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUmVzb3VyY2VUeXBlLlRJTEVNQVA6XG4gICAgICAgICAgICAgICAgdGhpcy50aWxlbWFwcy5kZWxldGUocmVzb3VyY2Uua2V5KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUmVzb3VyY2VUeXBlLlNQUklURVNIRUVUOlxuICAgICAgICAgICAgICAgIHRoaXMuc3ByaXRlc2hlZXRzLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSZXNvdXJjZVR5cGUuQVVESU86XG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0J1ZmZlcnMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFJlc291cmNlVHlwZS5KU09OOlxuICAgICAgICAgICAgICAgIHRoaXMuanNvbk9iamVjdHMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvKmNhc2UgUmVzb3VyY2VUeXBlLlNIQURFUjpcbiAgICAgICAgICAgICAgICB0aGlzLmdsX1NoYWRlclByb2dyYW1zLmdldChyZXNvdXJjZS5rZXkpLmRlbGV0ZSh0aGlzLmdsKTtcbiAgICAgICAgICAgICAgICB0aGlzLmdsX1NoYWRlclByb2dyYW1zLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIGJyZWFrOyovXG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWxldGUgYW55IGRlcGVuZGVuY2llc1xuICAgICAgICBmb3IgKGxldCBkZXBlbmRlbmN5IG9mIHJlc291cmNlLmRlcGVuZGVuY2llcykge1xuICAgICAgICAgICAgdGhpcy51bmxvYWRSZXNvdXJjZShkZXBlbmRlbmN5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgV09SSyBGVU5DVElPTlMgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIHRpbGVtYXBzIGN1cnJlbnRseSBpbiB0aGUgdGlsZW1hcCBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIGxvYWRpbmcgaXMgY29tcGxldGVcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRUaWxlbWFwc0Zyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWQgPSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBzTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV90aWxlbWFwc1RvTG9hZCA9PT0gMCkge1xuICAgICAgICAgICAgb25GaW5pc2hMb2FkaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAodGhpcy5sb2Fkb25seV90aWxlbWFwTG9hZGluZ1F1ZXVlLmhhc0l0ZW1zKCkpIHtcbiAgICAgICAgICAgIGxldCB0aWxlbWFwID0gdGhpcy5sb2Fkb25seV90aWxlbWFwTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZFRpbGVtYXAodGlsZW1hcC5rZXksIHRpbGVtYXAucGF0aCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGEgc2luZ3VsYXIgdGlsZW1hcCBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gcGF0aFRvVGlsZW1hcEpTT04gVGhlIHBhdGggdG8gdGhlIHRpbGVtYXAgSlNPTiBmaWxlXG4gICAgICogQHBhcmFtIGNhbGxiYWNrSWZMYXN0IFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgdGlsZW1hcCB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBsb2FkVGlsZW1hcChrZXk6IHN0cmluZywgcGF0aFRvVGlsZW1hcEpTT046IHN0cmluZywgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZFRleHRGaWxlKHBhdGhUb1RpbGVtYXBKU09OLCAoZmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHRpbGVtYXBPYmplY3QgPSA8VGlsZWRUaWxlbWFwRGF0YT5KU09OLnBhcnNlKGZpbGVUZXh0KTtcblxuICAgICAgICAgICAgLy8gV2UgY2FuIHBhcnNlIHRoZSBvYmplY3QgbGF0ZXIgLSBpdCdzIG11Y2ggZmFzdGVyIHRoYW4gbG9hZGluZ1xuICAgICAgICAgICAgdGhpcy50aWxlbWFwcy5hZGQoa2V5LCB0aWxlbWFwT2JqZWN0KTtcbiAgICAgICAgICAgIGxldCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5USUxFTUFQKTtcblxuICAgICAgICAgICAgLy8gR3JhYiB0aGUgdGlsZXNldCBpbWFnZXMgd2UgbmVlZCB0byBsb2FkIGFuZCBhZGQgdGhlbSB0byB0aGUgaW1hZ2Vsb2FkaW5nIHF1ZXVlXG4gICAgICAgICAgICBmb3IgKGxldCB0aWxlc2V0IG9mIHRpbGVtYXBPYmplY3QudGlsZXNldHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGlsZXNldC5pbWFnZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQga2V5ID0gdGlsZXNldC5pbWFnZTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHBhdGggPSBTdHJpbmdVdGlscy5nZXRQYXRoRnJvbUZpbGVQYXRoKHBhdGhUb1RpbGVtYXBKU09OKSArIGtleTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZUxvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIHBhdGg6IHBhdGgsIGlzRGVwZW5kZW5jeTogdHJ1ZSB9KTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBBZGQgdGhpcyBpbWFnZSBhcyBhIGRlcGVuZGVuY3kgdG8gdGhlIHRpbGVtYXBcbiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2UuYWRkRGVwZW5kZW5jeShuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRpbGVzZXQudGlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgdGlsZSBvZiB0aWxlc2V0LnRpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQga2V5ID0gdGlsZS5pbWFnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwYXRoID0gU3RyaW5nVXRpbHMuZ2V0UGF0aEZyb21GaWxlUGF0aChwYXRoVG9UaWxlbWFwSlNPTikgKyBrZXk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCwgaXNEZXBlbmRlbmN5OiB0cnVlIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgdGhpcyBpbWFnZSBhcyBhIGRlcGVuZGVuY3kgdG8gdGhlIHRpbGVtYXBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc291cmNlLmFkZERlcGVuZGVuY3kobmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLklNQUdFKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFkZCB0aGUgcmVzb3VyY2UgcmVmZXJlbmNlIHRvIHRoZSBsaXN0IG9mIHJlc291cmNlIHRvIHVubG9hZFxuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKHJlc291cmNlKTtcblxuICAgICAgICAgICAgLy8gRmluaXNoIGxvYWRpbmdcbiAgICAgICAgICAgIHRoaXMuZmluaXNoTG9hZGluZ1RpbGVtYXAoY2FsbGJhY2tJZkxhc3QpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2ggbG9hZGluZyBhIHRpbGVtYXAuIENhbGxzIHRoZSBjYWxsYmFjayBmdW5jdGlvbiBpZiB0aGlzIGlzIHRoZSBsYXN0IHRpbGVtYXAgYmVpbmcgbG9hZGVkXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgdGlsZW1hcCB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nVGlsZW1hcChjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwc0xvYWRlZCArPSAxO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBzTG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgdGlsZW1hcHNcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgc3ByaXRlc2hlZXRzIGN1cnJlbnRseSBpbiB0aGUgc3ByaXRlc2hlZXQgbG9hZGluZyBxdWV1ZVxuICAgICAqIEBwYXJhbSBvbkZpbmlzaExvYWRpbmcgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgd2hlbiB0aGUgc3ByaXRlc2hlZXRzIGFyZSBkb25lIGxvYWRpbmdcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRTcHJpdGVzaGVldHNGcm9tUXVldWUob25GaW5pc2hMb2FkaW5nOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c0xvYWRlZCA9IDA7XG5cbiAgICAgICAgLy8gSWYgbm8gaXRlbXMgdG8gbG9hZCwgd2UncmUgZmluaXNoZWRcbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0TG9hZGluZ1F1ZXVlLmhhc0l0ZW1zKCkpIHtcbiAgICAgICAgICAgIGxldCBzcHJpdGVzaGVldCA9IHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5sb2FkU3ByaXRlc2hlZXQoc3ByaXRlc2hlZXQua2V5LCBzcHJpdGVzaGVldC5wYXRoLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYSBzaW5ndWxhciBzcHJpdGVzaGVldCBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHNwcml0ZXNoZWV0IHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gcGF0aFRvU3ByaXRlc2hlZXRKU09OIFRoZSBwYXRoIHRvIHRoZSBzcHJpdGVzaGVldCBKU09OIGZpbGVcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tJZkxhc3QgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBzcHJpdGVzaGVldFxuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZFNwcml0ZXNoZWV0KGtleTogc3RyaW5nLCBwYXRoVG9TcHJpdGVzaGVldEpTT046IHN0cmluZywgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZFRleHRGaWxlKHBhdGhUb1Nwcml0ZXNoZWV0SlNPTiwgKGZpbGVUZXh0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGxldCBzcHJpdGVzaGVldCA9IDxTcHJpdGVzaGVldD5KU09OLnBhcnNlKGZpbGVUZXh0KTtcblxuICAgICAgICAgICAgLy8gV2UgY2FuIHBhcnNlIHRoZSBvYmplY3QgbGF0ZXIgLSBpdCdzIG11Y2ggZmFzdGVyIHRoYW4gbG9hZGluZ1xuICAgICAgICAgICAgdGhpcy5zcHJpdGVzaGVldHMuYWRkKGtleSwgc3ByaXRlc2hlZXQpO1xuXG4gICAgICAgICAgICBsZXQgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuU1BSSVRFU0hFRVQpO1xuXG4gICAgICAgICAgICAvLyBHcmFiIHRoZSBpbWFnZSB3ZSBuZWVkIHRvIGxvYWQgYW5kIGFkZCBpdCB0byB0aGUgaW1hZ2Vsb2FkaW5nIHF1ZXVlXG4gICAgICAgICAgICBsZXQgcGF0aCA9IFN0cmluZ1V0aWxzLmdldFBhdGhGcm9tRmlsZVBhdGgocGF0aFRvU3ByaXRlc2hlZXRKU09OKSArIHNwcml0ZXNoZWV0LnNwcml0ZVNoZWV0SW1hZ2U7XG4gICAgICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IHNwcml0ZXNoZWV0Lm5hbWUsIHBhdGg6IHBhdGgsIGlzRGVwZW5kZW5jeTogdHJ1ZSB9KTtcblxuICAgICAgICAgICAgcmVzb3VyY2UuYWRkRGVwZW5kZW5jeShuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoc3ByaXRlc2hlZXQubmFtZSwgUmVzb3VyY2VUeXBlLklNQUdFKSk7XG4gICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnB1c2gocmVzb3VyY2UpO1xuXG4gICAgICAgICAgICAvLyBGaW5pc2ggbG9hZGluZ1xuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nU3ByaXRlc2hlZXQoY2FsbGJhY2tJZkxhc3QpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2ggbG9hZGluZyBhIHNwcml0ZXNoZWV0LiBDYWxscyB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gaWYgdGhpcyBpcyB0aGUgbGFzdCBzcHJpdGVzaGVldCBiZWluZyBsb2FkZWRcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBzcHJpdGVzaGVldCB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nU3ByaXRlc2hlZXQoY2FsbGJhY2s6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkICs9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZCkge1xuICAgICAgICAgICAgLy8gV2UncmUgZG9uZSBsb2FkaW5nIHNwcml0ZXNoZWV0c1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFsbCBpbWFnZXMgY3VycmVudGx5IGluIHRoZSBpbWFnZSBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZXJlIGFyZSBubyBtb3JlIGltYWdlcyB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBsb2FkSW1hZ2VzRnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZXNUb0xvYWQgPSB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmdldFNpemUoKTtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZXNMb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2ltYWdlc1RvTG9hZCA9PT0gMCkge1xuICAgICAgICAgICAgb25GaW5pc2hMb2FkaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAodGhpcy5sb2Fkb25seV9pbWFnZUxvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgaW1hZ2UgPSB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZEltYWdlKGltYWdlLmtleSwgaW1hZ2UucGF0aCwgaW1hZ2UuaXNEZXBlbmRlbmN5LCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYSBzaW5ndWxhciBpbWFnZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBpbWFnZSB0byBsb2FkXG4gICAgICogQHBhcmFtIGNhbGxiYWNrSWZMYXN0IFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgaW1hZ2VcbiAgICAgKi9cbiAgICBwdWJsaWMgbG9hZEltYWdlKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGlzRGVwZW5kZW5jeTogYm9vbGVhbiwgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHZhciBpbWFnZSA9IG5ldyBJbWFnZSgpO1xuXG4gICAgICAgIGltYWdlLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICAgIC8vIEFkZCB0byBsb2FkZWQgaW1hZ2VzXG4gICAgICAgICAgICB0aGlzLmltYWdlcy5hZGQoa2V5LCBpbWFnZSk7XG5cbiAgICAgICAgICAgIC8vIElmIG5vdCBhIGRlcGVuZGVuY3ksIHB1c2ggaXQgdG8gdGhlIHVubG9hZCBsaXN0LiBPdGhlcndpc2UgaXQncyBtYW5hZ2VkIGJ5IHNvbWV0aGluZyBlbHNlXG4gICAgICAgICAgICBpZiAoIWlzRGVwZW5kZW5jeSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgV2ViR0wgaXMgYWN0aXZlLCBjcmVhdGUgYSB0ZXh0dXJlXG4gICAgICAgICAgICBpZiAodGhpcy5nbF9XZWJHTEFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlV2ViR0xUZXh0dXJlKGtleSwgaW1hZ2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGaW5pc2ggaW1hZ2UgbG9hZFxuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nSW1hZ2UoY2FsbGJhY2tJZkxhc3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaW1hZ2Uuc3JjID0gcGF0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2ggbG9hZGluZyBhbiBpbWFnZS4gSWYgdGhpcyBpcyB0aGUgbGFzdCBpbWFnZSwgaXQgY2FsbHMgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgaW1hZ2VcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdJbWFnZShjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZXNMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9pbWFnZXNMb2FkZWQgPT09IHRoaXMubG9hZG9ubHlfaW1hZ2VzVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgaW1hZ2VzXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIGF1ZGlvIGN1cnJlbnRseSBpbiB0aGUgdGlsZW1hcCBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRpbGVtYXBzIGFyZSBkb25lIGxvYWRpbmdcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRBdWRpb0Zyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfYXVkaW9Ub0xvYWQgPSB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGluZ1F1ZXVlLmdldFNpemUoKTtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRlZCA9IDA7XG5cbiAgICAgICAgLy8gSWYgbm8gaXRlbXMgdG8gbG9hZCwgd2UncmUgZmluaXNoZWRcbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfYXVkaW9Ub0xvYWQgPT09IDApIHtcbiAgICAgICAgICAgIG9uRmluaXNoTG9hZGluZygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IGF1ZGlvID0gdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRpbmdRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRBdWRpbyhhdWRpby5rZXksIGF1ZGlvLnBhdGgsIG9uRmluaXNoTG9hZGluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkIGEgc2luZ3VsYXIgYXVkaW8gZmlsZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byB0aGUgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIGF1ZGlvIGZpbGUgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBjYWxsYmFja0lmTGFzdCBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IGF1ZGlvIGZpbGUgdG8gbG9hZFxuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZEF1ZGlvKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGNhbGxiYWNrSWZMYXN0OiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICBsZXQgYXVkaW9DdHggPSBBdWRpb01hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRBdWRpb0NvbnRleHQoKTtcblxuICAgICAgICBsZXQgcmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICByZXF1ZXN0Lm9wZW4oJ0dFVCcsIHBhdGgsIHRydWUpO1xuICAgICAgICByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7XG5cbiAgICAgICAgcmVxdWVzdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICBhdWRpb0N0eC5kZWNvZGVBdWRpb0RhdGEocmVxdWVzdC5yZXNwb25zZSwgKGJ1ZmZlcikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEFkZCB0byBsaXN0IG9mIGF1ZGlvIGJ1ZmZlcnNcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQnVmZmVycy5hZGQoa2V5LCBidWZmZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuQVVESU8pKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nIHNvdW5kXG4gICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nQXVkaW8oY2FsbGJhY2tJZkxhc3QpO1xuICAgICAgICAgICAgfSwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJFcnJvciBsb2FkaW5nIHNvdW5kXCI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXF1ZXN0LnNlbmQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2ggbG9hZGluZyBhbiBhdWRpbyBmaWxlLiBDYWxscyB0aGUgY2FsbGJhY2sgZnVuY3RvbiBpZiB0aGlzIGlzIHRoZSBsYXN0IGF1ZGlvIHNhbXBsZSBiZWluZyBsb2FkZWQuXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nQXVkaW8oY2FsbGJhY2s6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9hdWRpb0xvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCkge1xuICAgICAgICAgICAgLy8gV2UncmUgZG9uZSBsb2FkaW5nIGF1ZGlvXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIG9iamVjdHMgY3VycmVudGx5IGluIHRoZSBvYmplY3QgbG9hZGluZyBxdWV1ZVxuICAgICAqIEBwYXJhbSBvbkZpbmlzaExvYWRpbmcgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgd2hlbiB0aGVyZSBhcmUgbm8gbW9yZSBvYmplY3RzIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRPYmplY3RzRnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uVG9Mb2FkID0gdGhpcy5sb2Fkb25seV9qc29uTG9hZGluZ1F1ZXVlLmdldFNpemUoKTtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9qc29uVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X2pzb25Mb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IG9iaiA9IHRoaXMubG9hZG9ubHlfanNvbkxvYWRpbmdRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRPYmplY3Qob2JqLmtleSwgb2JqLnBhdGgsIG9uRmluaXNoTG9hZGluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHNpbmd1bGFyIG9iamVjdFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgb2JqZWN0IHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgb2JqZWN0IHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tJZkxhc3QgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBvYmplY3RcbiAgICAgKi9cbiAgICBwdWJsaWMgbG9hZE9iamVjdChrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUocGF0aCwgKGZpbGVUZXh0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGxldCBvYmogPSBKU09OLnBhcnNlKGZpbGVUZXh0KTtcbiAgICAgICAgICAgIHRoaXMuanNvbk9iamVjdHMuYWRkKGtleSwgb2JqKTtcblxuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5KU09OKSk7XG5cbiAgICAgICAgICAgIHRoaXMuZmluaXNoTG9hZGluZ09iamVjdChjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGFuIG9iamVjdC4gSWYgdGhpcyBpcyB0aGUgbGFzdCBvYmplY3QsIGl0IGNhbGxzIHRoZSBjYWxsYmFjayBmdW5jdGlvblxuICAgICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IG9iamVjdFxuICAgICAqL1xuICAgIHByaXZhdGUgZmluaXNoTG9hZGluZ09iamVjdChjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGVkICs9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfanNvbkxvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV9qc29uVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgb2JqZWN0c1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qICMjIyMjIyMjIyMgV0VCR0wgU1BFQ0lGSUMgRlVOQ1RJT05TICMjIyMjIyMjIyMgKi9cblxuICAgIHB1YmxpYyBnZXRUZXh0dXJlKGtleTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2xfVGV4dHVyZXMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNoYWRlclByb2dyYW0oa2V5OiBzdHJpbmcpOiBXZWJHTFByb2dyYW0ge1xuICAgICAgICByZXR1cm4gdGhpcy5nbF9TaGFkZXJQcm9ncmFtcy5nZXQoa2V5KS5wcm9ncmFtO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRCdWZmZXIoa2V5OiBzdHJpbmcpOiBXZWJHTEJ1ZmZlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmdsX0J1ZmZlcnMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjcmVhdGVXZWJHTFRleHR1cmUoaW1hZ2VLZXk6IHN0cmluZywgaW1hZ2U6IEhUTUxJbWFnZUVsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgLy8gR2V0IHRoZSB0ZXh0dXJlIElEXG4gICAgICAgIGNvbnN0IHRleHR1cmVJRCA9IHRoaXMuZ2V0VGV4dHVyZUlEKHRoaXMuZ2xfTmV4dFRleHR1cmVJRCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSB0ZXh0dXJlXG4gICAgICAgIGNvbnN0IHRleHR1cmUgPSB0aGlzLmdsLmNyZWF0ZVRleHR1cmUoKTtcblxuICAgICAgICAvLyBTZXQgdXAgdGhlIHRleHR1cmVcbiAgICAgICAgLy8gRW5hYmxlIHRleHR1cmUwXG4gICAgICAgIHRoaXMuZ2wuYWN0aXZlVGV4dHVyZSh0ZXh0dXJlSUQpO1xuXG4gICAgICAgIC8vIEJpbmQgb3VyIHRleHR1cmUgdG8gdGV4dHVyZSAwXG4gICAgICAgIHRoaXMuZ2wuYmluZFRleHR1cmUodGhpcy5nbC5URVhUVVJFXzJELCB0ZXh0dXJlKTtcblxuICAgICAgICAvLyBTZXQgdGhlIHRleHR1cmUgcGFyYW1ldGVyc1xuICAgICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLmdsLlRFWFRVUkVfTUlOX0ZJTFRFUiwgdGhpcy5nbC5MSU5FQVIpO1xuICAgICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLmdsLlRFWFRVUkVfV1JBUF9TLCB0aGlzLmdsLkNMQU1QX1RPX0VER0UpO1xuICAgICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLmdsLlRFWFRVUkVfV1JBUF9ULCB0aGlzLmdsLkNMQU1QX1RPX0VER0UpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgdGV4dHVyZSBpbWFnZVxuICAgICAgICB0aGlzLmdsLnRleEltYWdlMkQodGhpcy5nbC5URVhUVVJFXzJELCAwLCB0aGlzLmdsLlJHQkEsIHRoaXMuZ2wuUkdCQSwgdGhpcy5nbC5VTlNJR05FRF9CWVRFLCBpbWFnZSk7XG5cbiAgICAgICAgLy8gQWRkIHRoZSB0ZXh0dXJlIHRvIG91ciBtYXAgd2l0aCB0aGUgc2FtZSBrZXkgYXMgdGhlIGltYWdlXG4gICAgICAgIHRoaXMuZ2xfVGV4dHVyZXMuYWRkKGltYWdlS2V5LCB0aGlzLmdsX05leHRUZXh0dXJlSUQpO1xuXG4gICAgICAgIC8vIEluY3JlbWVudCB0aGUga2V5XG4gICAgICAgIHRoaXMuZ2xfTmV4dFRleHR1cmVJRCArPSAxO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VGV4dHVyZUlEKGlkOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICAvLyBTdGFydCB3aXRoIDkgY2FzZXMgLSB0aGlzIGNhbiBiZSBleHBhbmRlZCBpZiBuZWVkZWQsIGJ1dCBmb3IgdGhlIGJlc3QgcGVyZm9ybWFuY2UsXG4gICAgICAgIC8vIFRleHR1cmVzIHNob3VsZCBiZSBzdGl0Y2hlZCBpbnRvIGFuIGF0bGFzXG4gICAgICAgIHN3aXRjaCAoaWQpIHtcbiAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTA7XG4gICAgICAgICAgICBjYXNlIDE6IHJldHVybiB0aGlzLmdsLlRFWFRVUkUxO1xuICAgICAgICAgICAgY2FzZSAyOiByZXR1cm4gdGhpcy5nbC5URVhUVVJFMjtcbiAgICAgICAgICAgIGNhc2UgMzogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTM7XG4gICAgICAgICAgICBjYXNlIDQ6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU0O1xuICAgICAgICAgICAgY2FzZSA1OiByZXR1cm4gdGhpcy5nbC5URVhUVVJFNTtcbiAgICAgICAgICAgIGNhc2UgNjogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTY7XG4gICAgICAgICAgICBjYXNlIDc6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU3O1xuICAgICAgICAgICAgY2FzZSA4OiByZXR1cm4gdGhpcy5nbC5URVhUVVJFODtcbiAgICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNyZWF0ZUJ1ZmZlcihrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5nbF9XZWJHTEFjdGl2ZSkge1xuICAgICAgICAgICAgbGV0IGJ1ZmZlciA9IHRoaXMuZ2wuY3JlYXRlQnVmZmVyKCk7XG5cbiAgICAgICAgICAgIHRoaXMuZ2xfQnVmZmVycy5hZGQoa2V5LCBidWZmZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5xdWV1ZXMgbG9hZGluZyBvZiBhIG5ldyBzaGFkZXIgcHJvZ3JhbVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgc2hhZGVyIHByb2dyYW1cbiAgICAgKiBAcGFyYW0gdlNoYWRlckZpbGVwYXRoIFxuICAgICAqIEBwYXJhbSBmU2hhZGVyRmlsZXBhdGggXG4gICAgICovXG4gICAgcHVibGljIHNoYWRlcihrZXk6IHN0cmluZywgdlNoYWRlckZpbGVwYXRoOiBzdHJpbmcsIGZTaGFkZXJGaWxlcGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGxldCBzcGxpdFBhdGggPSB2U2hhZGVyRmlsZXBhdGguc3BsaXQoXCIuXCIpO1xuICAgICAgICBsZXQgZW5kID0gc3BsaXRQYXRoW3NwbGl0UGF0aC5sZW5ndGggLSAxXTtcblxuICAgICAgICBpZiAoZW5kICE9PSBcInZzaGFkZXJcIikge1xuICAgICAgICAgICAgdGhyb3cgYCR7dlNoYWRlckZpbGVwYXRofSBpcyBub3QgYSB2YWxpZCB2ZXJ0ZXggc2hhZGVyIC0gbXVzdCBlbmQgaW4gXCIudnNoYWRlcmA7XG4gICAgICAgIH1cblxuICAgICAgICBzcGxpdFBhdGggPSBmU2hhZGVyRmlsZXBhdGguc3BsaXQoXCIuXCIpO1xuICAgICAgICBlbmQgPSBzcGxpdFBhdGhbc3BsaXRQYXRoLmxlbmd0aCAtIDFdO1xuXG4gICAgICAgIGlmIChlbmQgIT09IFwiZnNoYWRlclwiKSB7XG4gICAgICAgICAgICB0aHJvdyBgJHtmU2hhZGVyRmlsZXBhdGh9IGlzIG5vdCBhIHZhbGlkIHZlcnRleCBzaGFkZXIgLSBtdXN0IGVuZCBpbiBcIi5mc2hhZGVyYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBwYXRocyA9IG5ldyBLZXlQYXRoX1NoYWRlcigpO1xuICAgICAgICBwYXRocy5rZXkgPSBrZXk7XG4gICAgICAgIHBhdGhzLnZwYXRoID0gdlNoYWRlckZpbGVwYXRoO1xuICAgICAgICBwYXRocy5mcGF0aCA9IGZTaGFkZXJGaWxlcGF0aDtcblxuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZS5lbnF1ZXVlKHBhdGhzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZWxscyB0aGUgcmVzb3VyY2UgbWFuYWdlciB0byBrZWVwIHRoaXMgcmVzb3VyY2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHJlc291cmNlXG4gICAgICovXG4gICAgcHVibGljIGtlZXBTaGFkZXIoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwUmVzb3VyY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSU1BR0UpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2xfTG9hZFNoYWRlcnNGcm9tUXVldWUob25GaW5pc2hMb2FkaW5nOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zVG9Mb2FkID0gdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiB3ZWJHTCBpc24nYWN0aXZlIG9yIHRoZXJlIGFyZSBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAoIXRoaXMuZ2xfV2ViR0xBY3RpdmUgfHwgdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc1RvTG9hZCA9PT0gMCkge1xuICAgICAgICAgICAgb25GaW5pc2hMb2FkaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAodGhpcy5sb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IHNoYWRlciA9IHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMuZ2xfTG9hZFNoYWRlcihzaGFkZXIua2V5LCBzaGFkZXIudnBhdGgsIHNoYWRlci5mcGF0aCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2xfTG9hZFNoYWRlcihrZXk6IHN0cmluZywgdnBhdGg6IHN0cmluZywgZnBhdGg6IHN0cmluZywgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZFRleHRGaWxlKHZwYXRoLCAodkZpbGVUZXh0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHZTaGFkZXIgPSB2RmlsZVRleHQ7XG5cbiAgICAgICAgICAgIHRoaXMubG9hZFRleHRGaWxlKGZwYXRoLCAoZkZpbGVUZXh0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmU2hhZGVyID0gZkZpbGVUZXh0XG5cbiAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IHRoZSBwcm9ncmFtIGFuZCBzaGFkZXJzXG4gICAgICAgICAgICAgICAgY29uc3QgW3NoYWRlclByb2dyYW0sIHZlcnRleFNoYWRlciwgZnJhZ21lbnRTaGFkZXJdID0gdGhpcy5jcmVhdGVTaGFkZXJQcm9ncmFtKHZTaGFkZXIsIGZTaGFkZXIpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgd3JhcHBlciB0eXBlXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvZ3JhbVdyYXBwZXIgPSBuZXcgV2ViR0xQcm9ncmFtVHlwZSgpO1xuICAgICAgICAgICAgICAgIHByb2dyYW1XcmFwcGVyLnByb2dyYW0gPSBzaGFkZXJQcm9ncmFtO1xuICAgICAgICAgICAgICAgIHByb2dyYW1XcmFwcGVyLnZlcnRleFNoYWRlciA9IHZlcnRleFNoYWRlcjtcbiAgICAgICAgICAgICAgICBwcm9ncmFtV3JhcHBlci5mcmFnbWVudFNoYWRlciA9IGZyYWdtZW50U2hhZGVyO1xuXG4gICAgICAgICAgICAgICAgLy8gQWRkIHRvIG91ciBtYXBcbiAgICAgICAgICAgICAgICB0aGlzLmdsX1NoYWRlclByb2dyYW1zLmFkZChrZXksIHByb2dyYW1XcmFwcGVyKTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuU0hBREVSKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBGaW5pc2ggbG9hZGluZ1xuICAgICAgICAgICAgICAgIHRoaXMuZ2xfRmluaXNoTG9hZGluZ1NoYWRlcihjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnbF9GaW5pc2hMb2FkaW5nU2hhZGVyKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zTG9hZGVkICs9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQgPT09IHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyBzaGFkZXJzXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjcmVhdGVTaGFkZXJQcm9ncmFtKHZTaGFkZXJTb3VyY2U6IHN0cmluZywgZlNoYWRlclNvdXJjZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHZlcnRleFNoYWRlciA9IHRoaXMubG9hZFZlcnRleFNoYWRlcih2U2hhZGVyU291cmNlKTtcbiAgICAgICAgY29uc3QgZnJhZ21lbnRTaGFkZXIgPSB0aGlzLmxvYWRGcmFnbWVudFNoYWRlcihmU2hhZGVyU291cmNlKTtcblxuICAgICAgICBpZiAodmVydGV4U2hhZGVyID09PSBudWxsIHx8IGZyYWdtZW50U2hhZGVyID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBXZSBoYWQgYSBwcm9ibGVtIGludGlhbGl6aW5nIC0gZXJyb3JcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIGEgc2hhZGVyIHByb2dyYW1cbiAgICAgICAgY29uc3QgcHJvZ3JhbSA9IHRoaXMuZ2wuY3JlYXRlUHJvZ3JhbSgpO1xuICAgICAgICBpZiAoIXByb2dyYW0pIHtcbiAgICAgICAgICAgIC8vIEVycm9yIGNyZWF0aW5nXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJGYWlsZWQgdG8gY3JlYXRlIHByb2dyYW1cIik7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEF0dGFjaCBvdXIgdmVydGV4IGFuZCBmcmFnbWVudCBzaGFkZXJcbiAgICAgICAgdGhpcy5nbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgdmVydGV4U2hhZGVyKTtcbiAgICAgICAgdGhpcy5nbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnJhZ21lbnRTaGFkZXIpO1xuXG4gICAgICAgIC8vIExpbmtcbiAgICAgICAgdGhpcy5nbC5saW5rUHJvZ3JhbShwcm9ncmFtKTtcbiAgICAgICAgaWYgKCF0aGlzLmdsLmdldFByb2dyYW1QYXJhbWV0ZXIocHJvZ3JhbSwgdGhpcy5nbC5MSU5LX1NUQVRVUykpIHtcbiAgICAgICAgICAgIC8vIEVycm9yIGxpbmtpbmdcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5nbC5nZXRQcm9ncmFtSW5mb0xvZyhwcm9ncmFtKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkZhaWxlZCB0byBsaW5rIHByb2dyYW06IFwiICsgZXJyb3IpO1xuXG4gICAgICAgICAgICAvLyBDbGVhbiB1cFxuICAgICAgICAgICAgdGhpcy5nbC5kZWxldGVQcm9ncmFtKHByb2dyYW0pO1xuICAgICAgICAgICAgdGhpcy5nbC5kZWxldGVTaGFkZXIodmVydGV4U2hhZGVyKTtcbiAgICAgICAgICAgIHRoaXMuZ2wuZGVsZXRlU2hhZGVyKGZyYWdtZW50U2hhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2Ugc3VjY2Vzc2Z1bGx5IGNyZWF0ZSBhIHByb2dyYW1cbiAgICAgICAgcmV0dXJuIFtwcm9ncmFtLCB2ZXJ0ZXhTaGFkZXIsIGZyYWdtZW50U2hhZGVyXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRWZXJ0ZXhTaGFkZXIoc2hhZGVyU291cmNlOiBzdHJpbmcpOiBXZWJHTFNoYWRlciB7XG4gICAgICAgIC8vIENyZWF0ZSBhIG5ldyB2ZXJ0ZXggc2hhZGVyXG4gICAgICAgIHJldHVybiB0aGlzLmxvYWRTaGFkZXIodGhpcy5nbC5WRVJURVhfU0hBREVSLCBzaGFkZXJTb3VyY2UpO1xuICAgIH1cblxuICAgIHByaXZhdGUgbG9hZEZyYWdtZW50U2hhZGVyKHNoYWRlclNvdXJjZTogc3RyaW5nKTogV2ViR0xTaGFkZXIge1xuICAgICAgICAvLyBDcmVhdGUgYSBuZXcgZnJhZ21lbnQgc2hhZGVyXG4gICAgICAgIHJldHVybiB0aGlzLmxvYWRTaGFkZXIodGhpcy5nbC5GUkFHTUVOVF9TSEFERVIsIHNoYWRlclNvdXJjZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkU2hhZGVyKHR5cGU6IG51bWJlciwgc2hhZGVyU291cmNlOiBzdHJpbmcpOiBXZWJHTFNoYWRlciB7XG4gICAgICAgIGNvbnN0IHNoYWRlciA9IHRoaXMuZ2wuY3JlYXRlU2hhZGVyKHR5cGUpO1xuXG4gICAgICAgIC8vIElmIHdlIGNvdWxkbid0IGNyZWF0ZSB0aGUgc2hhZGVyLCBlcnJvclxuICAgICAgICBpZiAoc2hhZGVyID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJVbmFibGUgdG8gY3JlYXRlIHNoYWRlclwiKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHRoZSBzb3VyY2UgdG8gdGhlIHNoYWRlciBhbmQgY29tcGlsZVxuICAgICAgICB0aGlzLmdsLnNoYWRlclNvdXJjZShzaGFkZXIsIHNoYWRlclNvdXJjZSk7XG4gICAgICAgIHRoaXMuZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpO1xuXG4gICAgICAgIC8vIE1ha2Ugc3VyZSB0aGVyZSB3ZXJlIG5vIGVycm9ycyBkdXJpbmcgdGhpcyBwcm9jZXNzXG4gICAgICAgIGlmICghdGhpcy5nbC5nZXRTaGFkZXJQYXJhbWV0ZXIoc2hhZGVyLCB0aGlzLmdsLkNPTVBJTEVfU1RBVFVTKSkge1xuICAgICAgICAgICAgLy8gTm90IGNvbXBpbGVkIC0gZXJyb3JcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5nbC5nZXRTaGFkZXJJbmZvTG9nKHNoYWRlcik7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJGYWlsZWQgdG8gY29tcGlsZSBzaGFkZXI6IFwiICsgZXJyb3IpO1xuXG4gICAgICAgICAgICAvLyBDbGVhbiB1cFxuICAgICAgICAgICAgdGhpcy5nbC5kZWxldGVTaGFkZXIoc2hhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3VjZXNzLCBzbyByZXR1cm4gdGhlIHNoYWRlclxuICAgICAgICByZXR1cm4gc2hhZGVyO1xuICAgIH1cblxuICAgIC8qICMjIyMjIyMjIyMgR0VORVJBTCBMT0FESU5HIEZVTkNUSU9OUyAjIyMjIyMjIyMjICovXG5cbiAgICBwcml2YXRlIGxvYWRUZXh0RmlsZSh0ZXh0RmlsZVBhdGg6IHN0cmluZywgY2FsbGJhY2s6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIGxldCB4b2JqOiBYTUxIdHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICB4b2JqLm92ZXJyaWRlTWltZVR5cGUoXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuICAgICAgICB4b2JqLm9wZW4oJ0dFVCcsIHRleHRGaWxlUGF0aCwgdHJ1ZSk7XG4gICAgICAgIHhvYmoub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCh4b2JqLnJlYWR5U3RhdGUgPT0gNCkgJiYgKHhvYmouc3RhdHVzID09IDIwMCkpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh4b2JqLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHhvYmouc2VuZChudWxsKTtcbiAgICB9XG5cbiAgICAvKiAjIyMjIyMjIyMjIExPQURJTkcgQkFSIElORk8gIyMjIyMjIyMjIyAqL1xuXG4gICAgcHJpdmF0ZSBnZXRMb2FkUGVyY2VudCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gKHRoaXMubG9hZG9ubHlfdGlsZW1hcHNMb2FkZWQgLyB0aGlzLmxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkXG4gICAgICAgICAgICArIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkIC8gdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNUb0xvYWRcbiAgICAgICAgICAgICsgdGhpcy5sb2Fkb25seV9pbWFnZXNMb2FkZWQgLyB0aGlzLmxvYWRvbmx5X2ltYWdlc1RvTG9hZFxuICAgICAgICAgICAgKyB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkIC8gdGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZClcbiAgICAgICAgICAgIC8gdGhpcy5sb2Fkb25seV90eXBlc1RvTG9hZDtcbiAgICB9XG5cbiAgICAvLyBDdXN0b21pemVkIGZ1bnRpb25zIGJlbG93XG4gICAgLy8gVGhlc2UgZnVudGlvbnMgYXJlIE5PVCB3ZWxsIHRlc3RlZCEhIVxuICAgIC8vIE9ubHkgdXNlZCBmb3Igc2hhdHRlcmVkIHN3b3JkIHNwZWNpZmljIHB1cnBvc2UhISFcbiAgICAvLyBVc2UgdGhlbSBjYXJlZnVsbHkhISFcblxuICAgIHB1YmxpYyB0aWxlbWFwRnJvbU9iamVjdChrZXk6IHN0cmluZywgdGlsZW1hcDogVGlsZWRUaWxlbWFwRGF0YSk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBtYXA6IHRpbGVtYXAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkVGlsZW1hcE9iamVjdEZyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdFRvTG9hZCA9IHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRlZCA9IDA7XG5cbiAgICAgICAgLy8gSWYgbm8gaXRlbXMgdG8gbG9hZCwgd2UncmUgZmluaXNoZWRcbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdFRvTG9hZCA9PT0gMCkge1xuICAgICAgICAgICAgb25GaW5pc2hMb2FkaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAodGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGluZ1F1ZXVlLmhhc0l0ZW1zKCkpIHtcbiAgICAgICAgICAgIGxldCBtYXAgPSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5sb2FkVGlsZW1hcEZyb21PYmplY3QobWFwLmtleSwgbWFwLm1hcCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbG9hZFRpbGVtYXBGcm9tT2JqZWN0KGtleTogc3RyaW5nLCB0aWxlZE1hcDogVGlsZWRUaWxlbWFwRGF0YSwgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIC8vIFdlIGNhbiBwYXJzZSB0aGUgb2JqZWN0IGxhdGVyIC0gaXQncyBtdWNoIGZhc3RlciB0aGFuIGxvYWRpbmdcblxuICAgICAgICB0aGlzLnRpbGVtYXBzLmFkZChrZXksIHRpbGVkTWFwKTtcbiAgICAgICAgbGV0IHJlc291cmNlID0gbmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLlRJTEVNQVApO1xuXG4gICAgICAgIC8vIEdyYWIgdGhlIHRpbGVzZXQgaW1hZ2VzIHdlIG5lZWQgdG8gbG9hZCBhbmQgYWRkIHRoZW0gdG8gdGhlIGltYWdlbG9hZGluZyBxdWV1ZVxuICAgICAgICBmb3IgKGxldCB0aWxlc2V0IG9mIHRpbGVkTWFwLnRpbGVzZXRzKSB7XG4gICAgICAgICAgICBpZiAodGlsZXNldC5pbWFnZSkge1xuICAgICAgICAgICAgICAgIGxldCBrZXkgPSB0aWxlc2V0LmltYWdlO1xuICAgICAgICAgICAgICAgIGxldCBwYXRoID0ga2V5O1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoLCBpc0RlcGVuZGVuY3k6IHRydWUgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgdGhpcyBpbWFnZSBhcyBhIGRlcGVuZGVuY3kgdG8gdGhlIHRpbGVtYXBcbiAgICAgICAgICAgICAgICByZXNvdXJjZS5hZGREZXBlbmRlbmN5KG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHRoZSByZXNvdXJjZSByZWZlcmVuY2UgdG8gdGhlIGxpc3Qgb2YgcmVzb3VyY2UgdG8gdW5sb2FkXG4gICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChyZXNvdXJjZSk7XG5cbiAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nVGlsZW1hcE9iamVjdChjYWxsYmFja0lmTGFzdCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nVGlsZW1hcE9iamVjdChjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGVkICs9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgdGlsZW1hcHNcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgc2luZ2xlSW1hZ2Uoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZywgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHZhciBpbWFnZSA9IG5ldyBJbWFnZSgpO1xuXG4gICAgICAgIGltYWdlLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICAgIC8vIEFkZCB0byBsb2FkZWQgaW1hZ2VzXG4gICAgICAgICAgICB0aGlzLmltYWdlcy5hZGQoa2V5LCBpbWFnZSk7XG5cbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcblxuICAgICAgICAgICAgLy8gSWYgV2ViR0wgaXMgYWN0aXZlLCBjcmVhdGUgYSB0ZXh0dXJlXG4gICAgICAgICAgICBpZiAodGhpcy5nbF9XZWJHTEFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRlV2ViR0xUZXh0dXJlKGtleSwgaW1hZ2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGaW5pc2ggaW1hZ2UgbG9hZFxuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nU2luZ2xlT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgfVxuICAgICAgICBpbWFnZS5zcmMgPSBwYXRoO1xuICAgIH1cblxuICAgIHB1YmxpYyBzaW5nbGVBdWRpbyhrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgbGV0IGF1ZGlvQ3R4ID0gQXVkaW9NYW5hZ2VyLmdldEluc3RhbmNlKCkuZ2V0QXVkaW9Db250ZXh0KCk7XG5cbiAgICAgICAgbGV0IHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgcmVxdWVzdC5vcGVuKCdHRVQnLCBwYXRoLCB0cnVlKTtcbiAgICAgICAgcmVxdWVzdC5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuXG4gICAgICAgIHJlcXVlc3Qub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgYXVkaW9DdHguZGVjb2RlQXVkaW9EYXRhKHJlcXVlc3QucmVzcG9uc2UsIChidWZmZXIpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBBZGQgdG8gbGlzdCBvZiBhdWRpbyBidWZmZXJzXG4gICAgICAgICAgICAgICAgdGhpcy5hdWRpb0J1ZmZlcnMuYWRkKGtleSwgYnVmZmVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnB1c2gobmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLkFVRElPKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBGaW5pc2ggbG9hZGluZyBzb3VuZFxuICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoTG9hZGluZ1NpbmdsZU9iamVjdChjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIkVycm9yIGxvYWRpbmcgc291bmRcIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJlcXVlc3Quc2VuZCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZmluaXNoTG9hZGluZ1NpbmdsZU9iamVjdChjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubG9hZGluZykge1xuICAgICAgICAgICAgaWYgKHRoaXMub25Mb2FkUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uTG9hZFByb2dyZXNzKHRoaXMuZ2V0TG9hZFBlcmNlbnQoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5qdXN0TG9hZGVkKSB7XG4gICAgICAgICAgICB0aGlzLmp1c3RMb2FkZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLm9uTG9hZENvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkxvYWRDb21wbGV0ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIEEgY2xhc3MgcmVwcmVzZW50aW5nIGEgcmVmZXJlbmNlIHRvIGEgcmVzb3VyY2UuXG4gKiBUaGlzIGlzIHVzZWQgZm9yIHRoZSBleGVtcHRpb24gbGlzdCB0byBhc3N1cmUgYXNzZXRzIGFuZCB0aGVpciBkZXBlbmRlbmNpZXMgZG9uJ3QgZ2V0XG4gKiBkZXN0cm95ZWQgaWYgdGhleSBhcmUgc3RpbGwgbmVlZGVkLlxuICovXG5jbGFzcyBSZXNvdXJjZVJlZmVyZW5jZSB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgcmVzb3VyY2VUeXBlOiBSZXNvdXJjZVR5cGU7XG4gICAgZGVwZW5kZW5jaWVzOiBBcnJheTxSZXNvdXJjZVJlZmVyZW5jZT47XG5cbiAgICBjb25zdHJ1Y3RvcihrZXk6IHN0cmluZywgcmVzb3VyY2VUeXBlOiBSZXNvdXJjZVR5cGUpIHtcbiAgICAgICAgdGhpcy5rZXkgPSBrZXk7XG4gICAgICAgIHRoaXMucmVzb3VyY2VUeXBlID0gcmVzb3VyY2VUeXBlO1xuICAgICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIGFkZERlcGVuZGVuY3kocmVzb3VyY2U6IFJlc291cmNlUmVmZXJlbmNlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzLnB1c2gocmVzb3VyY2UpO1xuICAgIH1cbn1cblxuXG5lbnVtIFJlc291cmNlVHlwZSB7XG4gICAgSU1BR0UgPSBcIklNQUdFXCIsXG4gICAgVElMRU1BUCA9IFwiVElMRU1BUFwiLFxuICAgIFNQUklURVNIRUVUID0gXCJTUFJJVEVTSEVFVFwiLFxuICAgIEFVRElPID0gXCJBVURJT1wiLFxuICAgIEpTT04gPSBcIkpTT05cIixcbiAgICBTSEFERVIgPSBcIlNIQURFUlwiXG59XG5cbi8qKlxuICogQSBwYWlyIHJlcHJlc2VudGluZyBhIGtleSBhbmQgdGhlIHBhdGggb2YgdGhlIHJlc291cmNlIHRvIGxvYWRcbiAqL1xuY2xhc3MgS2V5UGF0aFBhaXIge1xuICAgIGtleTogc3RyaW5nO1xuICAgIHBhdGg6IHN0cmluZztcbiAgICBpc0RlcGVuZGVuY3k/OiBib29sZWFuID0gZmFsc2U7XG59XG5cbmNsYXNzIEtleU1hcFBhaXIge1xuICAgIGtleTogc3RyaW5nO1xuICAgIG1hcDogVGlsZWRUaWxlbWFwRGF0YTtcbn1cblxuY2xhc3MgS2V5UGF0aF9TaGFkZXIge1xuICAgIGtleTogc3RyaW5nO1xuICAgIHZwYXRoOiBzdHJpbmc7XG4gICAgZnBhdGg6IHN0cmluZztcbn0iLCJpbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lXCI7XG5pbXBvcnQgVUlFbGVtZW50IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRcIjtcbmltcG9ydCBHcmFwaGljIGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgeyBHcmFwaGljVHlwZSB9IGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9HcmFwaGljVHlwZXNcIjtcbmltcG9ydCB7IFVJRWxlbWVudFR5cGUgfSBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9VSUVsZW1lbnRUeXBlc1wiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9Qb2ludFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgQnV0dG9uIGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvblwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgU2xpZGVyIGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1NsaWRlclwiO1xuaW1wb3J0IFRleHRJbnB1dCBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9UZXh0SW5wdXRcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgTGluZSBmcm9tIFwiLi4vLi4vTm9kZXMvR3JhcGhpY3MvTGluZVwiO1xuaW1wb3J0IFBhcnRpY2xlIGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9QYXJ0aWNsZVwiO1xuXG4vLyBAaWdub3JlUGFnZVxuXG4vKipcbiAqIEEgZmFjdG9yeSB0aGF0IGFic3RyYWN0cyBhZGRpbmcgQHJlZmVyZW5jZVtDYW52YXNOb2RlXXMgdG8gdGhlIEByZWZlcmVuY2VbU2NlbmVdLlxuICogQWNjZXNzIG1ldGhvZHMgaW4gdGhpcyBmYWN0b3J5IHRocm91Z2ggU2NlbmUuYWRkLlttZXRob2ROYW1lXSgpLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDYW52YXNOb2RlRmFjdG9yeSB7XG5cdHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cdHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcblxuXHRpbml0KHNjZW5lOiBTY2VuZSk6IHZvaWQge1xuXHRcdHRoaXMuc2NlbmUgPSBzY2VuZTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYW4gaW5zdGFuY2Ugb2YgYSBVSUVsZW1lbnQgdG8gdGhlIGN1cnJlbnQgc2NlbmUgLSBpLmUuIGFueSBjbGFzcyB0aGF0IGV4dGVuZHMgVUlFbGVtZW50XG5cdCAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9mIFVJRWxlbWVudCB0byBhZGRcblx0ICogQHBhcmFtIGxheWVyTmFtZSBUaGUgbGF5ZXIgdG8gYWRkIHRoZSBVSUVsZW1lbnQgdG9cblx0ICogQHBhcmFtIG9wdGlvbnMgQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIGZlZWQgdG8gdGhlIGNvbnN0cnVjdG9yXG5cdCAqIEByZXR1cm5zIEEgbmV3IFVJRWxlbWVudFxuXHQgKi9cblx0YWRkVUlFbGVtZW50ID0gKHR5cGU6IHN0cmluZyB8IFVJRWxlbWVudFR5cGUsIGxheWVyTmFtZTogc3RyaW5nLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IFVJRWxlbWVudCA9PiB7XG5cdFx0Ly8gR2V0IHRoZSBsYXllclxuXHRcdGxldCBsYXllciA9IHRoaXMuc2NlbmUuZ2V0TGF5ZXIobGF5ZXJOYW1lKTtcblxuXHRcdGxldCBpbnN0YW5jZTogVUlFbGVtZW50O1xuXG5cdFx0c3dpdGNoKHR5cGUpe1xuXHRcdFx0Y2FzZSBVSUVsZW1lbnRUeXBlLkJVVFRPTjpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkQnV0dG9uKG9wdGlvbnMpO1xuXHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFVJRWxlbWVudFR5cGUuTEFCRUw6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZExhYmVsKG9wdGlvbnMpO1xuXHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFVJRWxlbWVudFR5cGUuU0xJREVSOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRTbGlkZXIob3B0aW9ucyk7XG5cdFx0XHRicmVhaztcblx0XHRcdGNhc2UgVUlFbGVtZW50VHlwZS5URVhUX0lOUFVUOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRUZXh0SW5wdXQob3B0aW9ucyk7XG5cdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHRocm93IGBVSUVsZW1lbnRUeXBlICcke3R5cGV9JyBkb2VzIG5vdCBleGlzdCwgb3IgaXMgcmVnaXN0ZXJlZCBpbmNvcnJlY3RseS5gXG5cdFx0fVxuXG5cdFx0aW5zdGFuY2Uuc2V0U2NlbmUodGhpcy5zY2VuZSk7XG5cdFx0aW5zdGFuY2UuaWQgPSB0aGlzLnNjZW5lLmdlbmVyYXRlSWQoKTtcblx0XHR0aGlzLnNjZW5lLmdldFNjZW5lR3JhcGgoKS5hZGROb2RlKGluc3RhbmNlKTtcblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBsYXllclxuXHRcdGxheWVyLmFkZE5vZGUoaW5zdGFuY2UpXG5cblx0XHRyZXR1cm4gaW5zdGFuY2U7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIHNwcml0ZSB0byB0aGUgY3VycmVudCBzY2VuZVxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGltYWdlIHRoZSBzcHJpdGUgd2lsbCByZXByZXNlbnRcblx0ICogQHBhcmFtIGxheWVyTmFtZSBUaGUgbGF5ZXIgb24gd2hpY2ggdG8gYWRkIHRoZSBzcHJpdGVcblx0ICogQHJldHVybnMgQSBuZXcgU3ByaXRlXG5cdCAqL1xuXHRhZGRTcHJpdGUgPSAoa2V5OiBzdHJpbmcsIGxheWVyTmFtZTogc3RyaW5nKTogU3ByaXRlID0+IHtcblx0XHRsZXQgbGF5ZXIgPSB0aGlzLnNjZW5lLmdldExheWVyKGxheWVyTmFtZSk7XG5cblx0XHRsZXQgaW5zdGFuY2UgPSBuZXcgU3ByaXRlKGtleSk7XG5cblx0XHQvLyBBZGQgaW5zdGFuY2UgdG8gc2NlbmVcblx0XHRpbnN0YW5jZS5zZXRTY2VuZSh0aGlzLnNjZW5lKTtcblx0XHRpbnN0YW5jZS5pZCA9IHRoaXMuc2NlbmUuZ2VuZXJhdGVJZCgpO1xuXG5cdFx0aWYoISh0aGlzLnNjZW5lLmlzUGFyYWxsYXhMYXllcihsYXllck5hbWUpIHx8IHRoaXMuc2NlbmUuaXNVSUxheWVyKGxheWVyTmFtZSkpKXtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0U2NlbmVHcmFwaCgpLmFkZE5vZGUoaW5zdGFuY2UpO1xuXHRcdH1cblx0XHRcblx0XHQvLyBBZGQgaW5zdGFuY2UgdG8gbGF5ZXJcblx0XHRsYXllci5hZGROb2RlKGluc3RhbmNlKTtcblxuXHRcdHJldHVybiBpbnN0YW5jZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFuIEFuaW1hdGVkU3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBBbmltYXRlZFNwcml0ZVxuXHQgKi9cblx0YWRkQW5pbWF0ZWRTcHJpdGUgPSAoa2V5OiBzdHJpbmcsIGxheWVyTmFtZTogc3RyaW5nKTogQW5pbWF0ZWRTcHJpdGUgPT4ge1xuXHRcdGxldCBsYXllciA9IHRoaXMuc2NlbmUuZ2V0TGF5ZXIobGF5ZXJOYW1lKTtcblx0XHRsZXQgc3ByaXRlc2hlZXQgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTcHJpdGVzaGVldChrZXkpO1xuXHRcdGxldCBpbnN0YW5jZSA9IG5ldyBBbmltYXRlZFNwcml0ZShzcHJpdGVzaGVldCk7XG5cblx0XHQvLyBBZGQgaW5zdGFuY2UgZm8gc2NlbmVcblx0XHRpbnN0YW5jZS5zZXRTY2VuZSh0aGlzLnNjZW5lKTtcblx0XHRpbnN0YW5jZS5pZCA9IHRoaXMuc2NlbmUuZ2VuZXJhdGVJZCgpO1xuXHRcdFxuXHRcdGlmKCEodGhpcy5zY2VuZS5pc1BhcmFsbGF4TGF5ZXIobGF5ZXJOYW1lKSB8fCB0aGlzLnNjZW5lLmlzVUlMYXllcihsYXllck5hbWUpKSl7XG5cdFx0XHR0aGlzLnNjZW5lLmdldFNjZW5lR3JhcGgoKS5hZGROb2RlKGluc3RhbmNlKTtcblx0XHR9XG5cblx0XHQvLyBBZGQgaW5zdGFuY2UgdG8gbGF5ZXJcblx0XHRsYXllci5hZGROb2RlKGluc3RhbmNlKTtcblxuXHRcdHJldHVybiBpbnN0YW5jZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbmV3IGdyYXBoaWMgZWxlbWVudCB0byB0aGUgY3VycmVudCBTY2VuZVxuXHQgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiBncmFwaGljIHRvIGFkZFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIGdyYXBoaWNcblx0ICogQHBhcmFtIG9wdGlvbnMgQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHNlbmQgdG8gdGhlIGdyYXBoaWMgY29uc3RydWN0b3Jcblx0ICogQHJldHVybnMgQSBuZXcgR3JhcGhpY1xuXHQgKi9cblx0YWRkR3JhcGhpYyA9ICh0eXBlOiBHcmFwaGljVHlwZSB8IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcsIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR3JhcGhpYyA9PiB7XG5cdFx0Ly8gR2V0IHRoZSBsYXllclxuXHRcdGxldCBsYXllciA9IHRoaXMuc2NlbmUuZ2V0TGF5ZXIobGF5ZXJOYW1lKTtcblxuXHRcdGxldCBpbnN0YW5jZTogR3JhcGhpYztcblxuXHRcdHN3aXRjaCh0eXBlKXtcblx0XHRcdGNhc2UgR3JhcGhpY1R5cGUuUE9JTlQ6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZFBvaW50KG9wdGlvbnMpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgR3JhcGhpY1R5cGUuTElORTpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkTGluZShvcHRpb25zKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIEdyYXBoaWNUeXBlLlJFQ1Q6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZFJlY3Qob3B0aW9ucyk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBHcmFwaGljVHlwZS5QQVJUSUNMRTpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkUGFydGljbGUob3B0aW9ucyk7XG5cdFx0XHRcdGJyZWFrO1x0XHRcdFx0XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHR0aHJvdyBgR3JhcGhpY1R5cGUgJyR7dHlwZX0nIGRvZXMgbm90IGV4aXN0LCBvciBpcyByZWdpc3RlcmVkIGluY29ycmVjdGx5LmBcblx0XHR9XG5cblx0XHQvLyBBZGQgaW5zdGFuY2UgdG8gc2NlbmVcblx0XHRpbnN0YW5jZS5zZXRTY2VuZSh0aGlzLnNjZW5lKTtcblx0XHRpbnN0YW5jZS5pZCA9IHRoaXMuc2NlbmUuZ2VuZXJhdGVJZCgpO1xuXG5cdFx0aWYoISh0aGlzLnNjZW5lLmlzUGFyYWxsYXhMYXllcihsYXllck5hbWUpIHx8IHRoaXMuc2NlbmUuaXNVSUxheWVyKGxheWVyTmFtZSkpKXtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0U2NlbmVHcmFwaCgpLmFkZE5vZGUoaW5zdGFuY2UpO1xuXHRcdH1cblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBsYXllclxuXHRcdGxheWVyLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0cmV0dXJuIGluc3RhbmNlO1xuXHR9XG5cblx0LyogLS0tLS0tLS0tLSBCVUlMREVSUyAtLS0tLS0tLS0tICovXG5cblx0YnVpbGRCdXR0b24ob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBCdXR0b24ge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJCdXR0b25cIiwgb3B0aW9ucywgXCJwb3NpdGlvblwiLCBWZWMyLCBcIlZlYzJcIik7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIkJ1dHRvblwiLCBvcHRpb25zLCBcInRleHRcIiwgXCJzdHJpbmdcIik7XG5cblx0XHRyZXR1cm4gbmV3IEJ1dHRvbihvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLnRleHQpO1xuXHR9XG5cblx0YnVpbGRMYWJlbChvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IExhYmVsIHtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGFiZWxcIiwgb3B0aW9ucywgXCJwb3NpdGlvblwiLCBWZWMyLCBcIlZlYzJcIik7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIkxhYmVsXCIsIG9wdGlvbnMsIFwidGV4dFwiLCBcInN0cmluZ1wiKTtcblxuXHRcdHJldHVybiBuZXcgTGFiZWwob3B0aW9ucy5wb3NpdGlvbiwgb3B0aW9ucy50ZXh0KVxuXHR9XG5cblx0YnVpbGRTbGlkZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IFNsaWRlciB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlNsaWRlclwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblxuXHRcdGxldCBpbml0VmFsdWUgPSAwO1xuXHRcdGlmKG9wdGlvbnMudmFsdWUgIT09IHVuZGVmaW5lZCl7XG5cdFx0XHRpbml0VmFsdWUgPSBvcHRpb25zLnZhbHVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgU2xpZGVyKG9wdGlvbnMucG9zaXRpb24sIGluaXRWYWx1ZSk7XG5cdH1cblxuXHRidWlsZFRleHRJbnB1dChvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogVGV4dElucHV0IHtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiVGV4dElucHV0XCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXG5cdFx0cmV0dXJuIG5ldyBUZXh0SW5wdXQob3B0aW9ucy5wb3NpdGlvbik7XG5cdH1cblxuXHRidWlsZFBvaW50KG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogUG9pbnQge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJQb2ludFwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblxuXHRcdHJldHVybiBuZXcgUG9pbnQob3B0aW9ucy5wb3NpdGlvbik7XG5cdH1cblxuXHRidWlsZFBhcnRpY2xlKG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogUG9pbnQge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJQYXJ0aWNsZVwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiUGFydGljbGVcIiwgb3B0aW9ucywgXCJzaXplXCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiUGFydGljbGVcIiwgb3B0aW9ucywgXCJtYXNzXCIsIFwibnVtYmVyXCIsIFwibnVtYmVyXCIpO1xuXG5cdFx0Ly9DaGFuZ2VkIGZvciB0ZXN0aW5nXG5cdFx0cmV0dXJuIG5ldyBQYXJ0aWNsZShvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLnNpemUsIG9wdGlvbnMubWFzcyk7XG5cdH1cblxuXHRidWlsZExpbmUob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQb2ludCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIkxpbmVcIiwgb3B0aW9ucywgXCJzdGFydFwiLCBWZWMyLCBcIlZlYzJcIik7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIkxpbmVcIiwgb3B0aW9ucywgXCJlbmRcIiwgVmVjMiwgXCJWZWMyXCIpO1xuXG5cdFx0cmV0dXJuIG5ldyBMaW5lKG9wdGlvbnMuc3RhcnQsIG9wdGlvbnMuZW5kKTtcblx0fVxuXG5cdGJ1aWxkUmVjdChvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IFJlY3Qge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJSZWN0XCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJSZWN0XCIsIG9wdGlvbnMsIFwic2l6ZVwiLCBWZWMyLCBcIlZlYzJcIik7XG5cblx0XHRyZXR1cm4gbmV3IFJlY3Qob3B0aW9ucy5wb3NpdGlvbiwgb3B0aW9ucy5zaXplKTtcblx0fVxuXG5cdC8qIC0tLS0tLS0tLS0gRVJST1IgSEFORExJTkcgLS0tLS0tLS0tLSAqL1xuXG5cdGNoZWNrSWZQcm9wRXhpc3RzPFQ+KG9iamVjdE5hbWU6IHN0cmluZywgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55PiwgcHJvcDogc3RyaW5nLCB0eXBlOiAobmV3ICguLi5hcmdzOiBhbnkpID0+IFQpIHwgc3RyaW5nLCB0eXBlTmFtZT86IHN0cmluZyl7XG5cdFx0aWYoIW9wdGlvbnMgfHwgb3B0aW9uc1twcm9wXSA9PT0gdW5kZWZpbmVkKXtcblx0XHRcdC8vIENoZWNrIHRoYXQgdGhlIG9wdGlvbnMgb2JqZWN0IGhhcyB0aGUgcHJvcGVydHlcblx0XHRcdHRocm93IGAke29iamVjdE5hbWV9IG9iamVjdCByZXF1aXJlcyBhcmd1bWVudCAke3Byb3B9IG9mIHR5cGUgJHt0eXBlTmFtZX0sIGJ1dCBub25lIHdhcyBwcm92aWRlZC5gO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBDaGVjayB0aGF0IHRoZSBwcm9wZXJ0eSBoYXMgdGhlIGNvcnJlY3QgdHlwZVxuXHRcdFx0aWYoKHR5cGVvZiB0eXBlKSA9PT0gXCJzdHJpbmdcIil7XG5cdFx0XHRcdGlmKCEodHlwZW9mIG9wdGlvbnNbcHJvcF0gPT09IHR5cGUpKXtcblx0XHRcdFx0XHR0aHJvdyBgJHtvYmplY3ROYW1lfSBvYmplY3QgcmVxdWlyZXMgYXJndW1lbnQgJHtwcm9wfSBvZiB0eXBlICR7dHlwZX0sIGJ1dCBwcm92aWRlZCAke3Byb3B9IHdhcyBub3Qgb2YgdHlwZSAke3R5cGV9LmA7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZih0eXBlIGluc3RhbmNlb2YgRnVuY3Rpb24pe1xuXHRcdFx0XHQvLyBJZiB0eXBlIGlzIGEgY29uc3RydWN0b3IsIGNoZWNrIGFnYWluc3QgdGhhdFxuXHRcdFx0XHRpZighKG9wdGlvbnNbcHJvcF0gaW5zdGFuY2VvZiB0eXBlKSl7XG5cdFx0XHRcdFx0dGhyb3cgYCR7b2JqZWN0TmFtZX0gb2JqZWN0IHJlcXVpcmVzIGFyZ3VtZW50ICR7cHJvcH0gb2YgdHlwZSAke3R5cGVOYW1lfSwgYnV0IHByb3ZpZGVkICR7cHJvcH0gd2FzIG5vdCBvZiB0eXBlICR7dHlwZU5hbWV9LmA7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRocm93IGAke29iamVjdE5hbWV9IG9iamVjdCByZXF1aXJlcyBhcmd1bWVudCAke3Byb3B9IG9mIHR5cGUgJHt0eXBlTmFtZX0sIGJ1dCBwcm92aWRlZCAke3Byb3B9IHdhcyBub3Qgb2YgdHlwZSAke3R5cGVOYW1lfS5gO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcbmltcG9ydCBDYW52YXNOb2RlRmFjdG9yeSBmcm9tIFwiLi9DYW52YXNOb2RlRmFjdG9yeVwiO1xuaW1wb3J0IFRpbGVtYXBGYWN0b3J5IGZyb20gXCIuL1RpbGVtYXBGYWN0b3J5XCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgVUlFbGVtZW50IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgeyBHcmFwaGljVHlwZSB9IGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9HcmFwaGljVHlwZXNcIjtcbmltcG9ydCBHcmFwaGljIGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IExheWVyIGZyb20gXCIuLi9MYXllclwiO1xuXG4vKipcbiAqIFRoZSBtYW5hZ2VyIG9mIGFsbCBmYWN0b3JpZXMgdXNlZCBmb3IgYWRkaW5nIEByZWZlcmVuY2VbR2FtZU5vZGVdcyB0byB0aGUgQHJlZmVyZW5jZVtTY2VuZV0uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZhY3RvcnlNYW5hZ2VyIHtcblxuICAgIC8vIENvbnN0cnVjdG9ycyBhcmUgY2FsbGVkIGhlcmUgdG8gYWxsb3cgYXNzaWdubWVudCBvZiB0aGVpciBmdW5jdGlvbnMgdG8gZnVuY3Rpb25zIGluIHRoaXMgY2xhc3NcbiAgICBwcml2YXRlIGNhbnZhc05vZGVGYWN0b3J5OiBDYW52YXNOb2RlRmFjdG9yeSA9IG5ldyBDYW52YXNOb2RlRmFjdG9yeSgpO1xuICAgIHByaXZhdGUgdGlsZW1hcEZhY3Rvcnk6IFRpbGVtYXBGYWN0b3J5ID0gbmV3IFRpbGVtYXBGYWN0b3J5KCk7XG5cbiAgICBjb25zdHJ1Y3RvcihzY2VuZTogU2NlbmUsIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPil7XG4gICAgICAgIHRoaXMuY2FudmFzTm9kZUZhY3RvcnkuaW5pdChzY2VuZSk7XG4gICAgICAgIHRoaXMudGlsZW1hcEZhY3RvcnkuaW5pdChzY2VuZSwgdGlsZW1hcHMpO1xuICAgIH1cblxuICAgIC8vIEV4cG9zZSBhbGwgb2YgdGhlIGZhY3RvcmllcyB0aHJvdWdoIHRoZSBmYWN0b3J5IG1hbmFnZXJcbiAgICAvKipcblx0ICogQWRkcyBhbiBpbnN0YW5jZSBvZiBhIFVJRWxlbWVudCB0byB0aGUgY3VycmVudCBzY2VuZSAtIGkuZS4gYW55IGNsYXNzIHRoYXQgZXh0ZW5kcyBVSUVsZW1lbnRcblx0ICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgb2YgVUlFbGVtZW50IHRvIGFkZFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciB0byBhZGQgdGhlIFVJRWxlbWVudCB0b1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gZmVlZCB0byB0aGUgY29uc3RydWN0b3Jcblx0ICogQHJldHVybnMgQSBuZXcgVUlFbGVtZW50XG5cdCAqL1xuICAgIHVpRWxlbWVudCh0eXBlOiBzdHJpbmcgfCBVSUVsZW1lbnRUeXBlLCBsYXllck5hbWU6IHN0cmluZywgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBVSUVsZW1lbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5hZGRVSUVsZW1lbnQodHlwZSwgbGF5ZXJOYW1lLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICAvKipcblx0ICogQWRkcyBhIHNwcml0ZSB0byB0aGUgY3VycmVudCBzY2VuZVxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGltYWdlIHRoZSBzcHJpdGUgd2lsbCByZXByZXNlbnRcblx0ICogQHBhcmFtIGxheWVyTmFtZSBUaGUgbGF5ZXIgb24gd2hpY2ggdG8gYWRkIHRoZSBzcHJpdGVcblx0ICogQHJldHVybnMgQSBuZXcgU3ByaXRlXG5cdCAqL1xuXHRzcHJpdGUoa2V5OiBzdHJpbmcsIGxheWVyTmFtZTogc3RyaW5nKTogU3ByaXRlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FudmFzTm9kZUZhY3RvcnkuYWRkU3ByaXRlKGtleSwgbGF5ZXJOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcblx0ICogQWRkcyBhbiBBbmltYXRlZFNwcml0ZSB0byB0aGUgY3VycmVudCBzY2VuZVxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGltYWdlIHRoZSBzcHJpdGUgd2lsbCByZXByZXNlbnRcblx0ICogQHBhcmFtIGxheWVyTmFtZSBUaGUgbGF5ZXIgb24gd2hpY2ggdG8gYWRkIHRoZSBzcHJpdGVcblx0ICogQHJldHVybnMgQSBuZXcgQW5pbWF0ZWRTcHJpdGVcblx0ICovXG5cdGFuaW1hdGVkU3ByaXRlKGtleTogc3RyaW5nLCBsYXllck5hbWU6IHN0cmluZyk6IEFuaW1hdGVkU3ByaXRlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FudmFzTm9kZUZhY3RvcnkuYWRkQW5pbWF0ZWRTcHJpdGUoa2V5LCBsYXllck5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBBZGRzIGEgbmV3IGdyYXBoaWMgZWxlbWVudCB0byB0aGUgY3VycmVudCBTY2VuZVxuXHQgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiBncmFwaGljIHRvIGFkZFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIGdyYXBoaWNcblx0ICogQHBhcmFtIG9wdGlvbnMgQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHNlbmQgdG8gdGhlIGdyYXBoaWMgY29uc3RydWN0b3Jcblx0ICogQHJldHVybnMgQSBuZXcgR3JhcGhpY1xuXHQgKi9cblx0Z3JhcGhpYyh0eXBlOiBHcmFwaGljVHlwZSB8IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcsIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR3JhcGhpYyB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhc05vZGVGYWN0b3J5LmFkZEdyYXBoaWModHlwZSwgbGF5ZXJOYW1lLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgdGlsZW1hcCB0byB0aGUgc2NlbmVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBvZiB0aGUgZGVzaXJlZCB0aWxlbWFwXG4gICAgICogQHBhcmFtIGFyZ3MgQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgdGlsZW1hcCBjb25zdHJ1Y3RvclxuICAgICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIExheWVycywgZWFjaCBvZiB3aGljaCBjb250YWlucyBhIGxheWVyIG9mIHRoZSB0aWxlbWFwIGFzIGl0cyBvd24gVGlsZW1hcCBpbnN0YW5jZS5cbiAgICAgKi9cblx0dGlsZW1hcChrZXk6IHN0cmluZywgc2NhbGU/OiBWZWMyKTogQXJyYXk8TGF5ZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZW1hcEZhY3RvcnkuYWRkKGtleSwgc2NhbGUpO1xuICAgIH1cbn0iLCJpbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lXCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IE9ydGhvZ29uYWxUaWxlbWFwIGZyb20gXCIuLi8uLi9Ob2Rlcy9UaWxlbWFwcy9PcnRob2dvbmFsVGlsZW1hcFwiO1xuaW1wb3J0IExheWVyIGZyb20gXCIuLi9MYXllclwiO1xuaW1wb3J0IFRpbGVzZXQgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlc2V0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCB7IFRpbGVkQ29sbGVjdGlvblRpbGUgfSBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBQb3NpdGlvbkdyYXBoIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvR3JhcGhzL1Bvc2l0aW9uR3JhcGhcIjtcbmltcG9ydCBOYXZtZXNoIGZyb20gXCIuLi8uLi9QYXRoZmluZGluZy9OYXZtZXNoXCI7XG5cbi8vIEBpZ25vcmVQYWdlXG5cbi8qKlxuICogQSBmYWN0b3J5IHRoYXQgYWJzdHJhY3RzIGFkZGluZyBAcmVmZXJlbmNlW1RpbGVtYXBdcyB0byB0aGUgQHJlZmVyZW5jZVtTY2VuZV0uXG4gKiBBY2Nlc3MgbWV0aG9kcyBpbiB0aGlzIGZhY3RvcnkgdGhyb3VnaCBTY2VuZS5hZGQuW21ldGhvZE5hbWVdKCkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRpbGVtYXBGYWN0b3J5IHtcbiAgICBwcml2YXRlIHNjZW5lOiBTY2VuZTtcbiAgICBwcml2YXRlIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPjtcbiAgICBwcml2YXRlIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuICAgIFxuICAgIGluaXQoc2NlbmU6IFNjZW5lLCB0aWxlbWFwczogQXJyYXk8VGlsZW1hcD4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgICAgICB0aGlzLnRpbGVtYXBzID0gdGlsZW1hcHM7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgfVxuXG4gICAgLy8gVE9ETyAtIFRoaXMgaXMgc3BlY2lmaWNhbGx5IGNhdGVyZWQgdG8gVGlsZWQgdGlsZW1hcHMgcmlnaHQgbm93LiBJbiB0aGUgZnV0dXJlLFxuICAgIC8vIGl0IHdvdWxkIGJlIGdvb2QgdG8gaGF2ZSBhIFwicGFyc2VUaWxlbWFwXCIgZnVuY3Rpb24gdGhhdCB3b3VsZCBjb252ZXJ0IHRoZSB0aWxlbWFwXG4gICAgLy8gZGF0YSBpbnRvIGEgc3RhbmRhcmQgZm9ybWF0LiBUaGlzIGNvdWxkIGFsbG93IGZvciBzdXBwb3J0IGZyb20gb3RoZXIgcHJvZ3JhbXNcbiAgICAvLyBvciB0aGUgZGV2ZWxvcG1lbnQgb2YgYW4gaW50ZXJuYWwgbGV2ZWwgYnVpbGRlciB0b29sXG4gICAgLyoqXG4gICAgICogQWRkcyBhIHRpbGVtYXAgdG8gdGhlIHNjZW5lXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBsb2FkZWQgdGlsZW1hcCB0byBsb2FkXG4gICAgICogQHBhcmFtIGNvbnN0ciBUaGUgY29uc3RydWN0b3Igb2YgdGhlIGRlc2lyZWQgdGlsZW1hcFxuICAgICAqIEBwYXJhbSBhcmdzIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHNlbmQgdG8gdGhlIHRpbGVtYXAgY29uc3RydWN0b3JcbiAgICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBMYXllcnMsIGVhY2ggb2Ygd2hpY2ggY29udGFpbnMgYSBsYXllciBvZiB0aGUgdGlsZW1hcCBhcyBpdHMgb3duIFRpbGVtYXAgaW5zdGFuY2UuXG4gICAgICovXG5cdGFkZCA9IChrZXk6IHN0cmluZywgc2NhbGU6IFZlYzIgPSBuZXcgVmVjMigxLCAxKSk6IEFycmF5PExheWVyPiA9PiB7XG4gICAgICAgIC8vIEdldCBUaWxlbWFwIERhdGFcbiAgICAgICAgbGV0IHRpbGVtYXBEYXRhID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0VGlsZW1hcChrZXkpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgY29uc3RydWN0b3IgZm9yIHRoaXMgdGlsZW1hcCB0byBlaXRoZXIgYmUgb3J0aG9ncmFwaGljIG9yIGlzb21ldHJpY1xuICAgICAgICBsZXQgY29uc3RyOiBuZXcoLi4uYXJnczogYW55KSA9PiBUaWxlbWFwO1xuICAgICAgICBpZih0aWxlbWFwRGF0YS5vcmllbnRhdGlvbiA9PT0gXCJvcnRob2dyYXBoaWNcIil7XG4gICAgICAgICAgICBjb25zdHIgPSBPcnRob2dvbmFsVGlsZW1hcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE5vIGlzb21ldHJpYyB0aWxlbWFwIHN1cHBvcnQgcmlnaHQgbm93LCBzbyBPcnRob2dyYXBoaWMgdGlsZW1hcFxuICAgICAgICAgICAgY29uc3RyID0gT3J0aG9nb25hbFRpbGVtYXA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSByZXR1cm4gdmFsdWUgYXJyYXlcbiAgICAgICAgbGV0IHNjZW5lTGF5ZXJzID0gbmV3IEFycmF5PExheWVyPigpO1xuXG4gICAgICAgIC8vIENyZWF0ZSBhbGwgb2YgdGhlIHRpbGVzZXRzIGZvciB0aGlzIHRpbGVtYXBcbiAgICAgICAgbGV0IHRpbGVzZXRzID0gbmV3IEFycmF5PFRpbGVzZXQ+KCk7XG5cbiAgICAgICAgbGV0IGNvbGxlY3Rpb25UaWxlcyA9IG5ldyBBcnJheTxUaWxlZENvbGxlY3Rpb25UaWxlPigpO1xuXG4gICAgICAgIGZvcihsZXQgdGlsZXNldCBvZiB0aWxlbWFwRGF0YS50aWxlc2V0cyl7XG4gICAgICAgICAgICBpZih0aWxlc2V0LmltYWdlKXtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGlzIGEgc3RhbmRhcmQgdGlsZXNldCBhbmQgbm90IGEgY29sbGVjdGlvbiwgY3JlYXRlIGEgdGlsZXNldCBmb3IgaXQuXG4gICAgICAgICAgICAgICAgLy8gVE9ETyAtIFdlIGFyZSBpZ25vcmluZyBjb2xsZWN0aW9uIHRpbGVzZXRzIGZvciBub3cuIFRoaXMgaXMgbGlrZWx5IG5vdCBhIGdyZWF0IGlkZWEgaW4gcHJhY3RpY2UsXG4gICAgICAgICAgICAgICAgLy8gYXMgdGhlb3JldGljYWxseSBzb21lb25lIGNvdWxkIHdhbnQgdG8gdXNlIG9uZSBmb3IgYSBzdGFuZGFyZCB0aWxlbWFwLiBXZSBhcmUgYXNzdW1pbmcgZm9yIG5vd1xuICAgICAgICAgICAgICAgIC8vIHRoYXQgd2Ugb25seSB3YW50IHRvIHVzZSB0aGVtIGZvciBvYmplY3QgbGF5ZXJzXG4gICAgICAgICAgICAgICAgdGlsZXNldHMucHVzaChuZXcgVGlsZXNldCh0aWxlc2V0KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRpbGVzZXQudGlsZXMuZm9yRWFjaCh0aWxlID0+IHRpbGUuaWQgKz0gdGlsZXNldC5maXJzdGdpZCk7XG4gICAgICAgICAgICAgICAgY29sbGVjdGlvblRpbGVzLnB1c2goLi4udGlsZXNldC50aWxlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMb29wIG92ZXIgdGhlIGxheWVycyBvZiB0aGUgdGlsZW1hcCBhbmQgY3JlYXRlIHRpbGVkbGF5ZXJzIG9yIG9iamVjdCBsYXllcnNcbiAgICAgICAgZm9yKGxldCBsYXllciBvZiB0aWxlbWFwRGF0YS5sYXllcnMpe1xuXG4gICAgICAgICAgICBsZXQgc2NlbmVMYXllcjtcbiAgICAgICAgICAgIGxldCBpc1BhcmFsbGF4TGF5ZXIgPSBmYWxzZTtcbiAgICAgICAgICAgIGxldCBkZXB0aCA9IDA7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgIGZvcihsZXQgcHJvcCBvZiBsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICAgICAgaWYocHJvcC5uYW1lID09PSBcIlBhcmFsbGF4XCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNQYXJhbGxheExheWVyID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJEZXB0aFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXB0aCA9IHByb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzUGFyYWxsYXhMYXllcil7XG4gICAgICAgICAgICAgICAgc2NlbmVMYXllciA9IHRoaXMuc2NlbmUuYWRkUGFyYWxsYXhMYXllcihsYXllci5uYW1lLCBuZXcgVmVjMigxLCAxKSwgZGVwdGgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzY2VuZUxheWVyID0gdGhpcy5zY2VuZS5hZGRMYXllcihsYXllci5uYW1lLCBkZXB0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKGxheWVyLnR5cGUgPT09IFwidGlsZWxheWVyXCIpe1xuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIG5ldyB0aWxlbWFwIG9iamVjdCBmb3IgdGhlIGxheWVyXG4gICAgICAgICAgICAgICAgbGV0IHRpbGVtYXAgPSBuZXcgY29uc3RyKHRpbGVtYXBEYXRhLCBsYXllciwgdGlsZXNldHMsIHNjYWxlKTtcbiAgICAgICAgICAgICAgICB0aWxlbWFwLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG4gICAgICAgICAgICAgICAgdGlsZW1hcC5zZXRTY2VuZSh0aGlzLnNjZW5lKTtcbiAgICBcbiAgICAgICAgICAgICAgICAvLyBBZGQgdGlsZW1hcCB0byBzY2VuZVxuICAgICAgICAgICAgICAgIHRoaXMudGlsZW1hcHMucHVzaCh0aWxlbWFwKTtcbiAgICBcbiAgICAgICAgICAgICAgICBzY2VuZUxheWVyLmFkZE5vZGUodGlsZW1hcCk7XG4gICAgXG4gICAgICAgICAgICAgICAgLy8gUmVnaXN0ZXIgdGlsZW1hcCB3aXRoIHBoeXNpY3MgaWYgaXQncyBjb2xsaWRhYmxlXG4gICAgICAgICAgICAgICAgaWYodGlsZW1hcC5pc0NvbGxpZGFibGUpe1xuICAgICAgICAgICAgICAgICAgICB0aWxlbWFwLmFkZFBoeXNpY3MoKTtcblxuICAgICAgICAgICAgICAgICAgICBpZihsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcihsZXQgaXRlbSBvZiBsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihpdGVtLm5hbWUgPT09IFwiR3JvdXBcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVtYXAuc2V0R3JvdXAoaXRlbS52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgIGxldCBpc05hdm1lc2hQb2ludHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBsZXQgbmF2bWVzaE5hbWU7XG4gICAgICAgICAgICAgICAgbGV0IGVkZ2VzO1xuICAgICAgICAgICAgICAgIGlmKGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHByb3Agb2YgbGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihwcm9wLm5hbWUgPT09IFwiTmF2bWVzaFBvaW50c1wiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc05hdm1lc2hQb2ludHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJuYW1lXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdm1lc2hOYW1lID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiZWRnZXNcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRnZXMgPSBwcm9wLnZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgaWYoaXNOYXZtZXNoUG9pbnRzKXtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGcgPSBuZXcgUG9zaXRpb25HcmFwaCgpO1xuXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgb2JqIG9mIGxheWVyLm9iamVjdHMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgZy5hZGRQb3NpdGlvbmVkTm9kZShuZXcgVmVjMihvYmoueCwgb2JqLnkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgZWRnZSBvZiBlZGdlcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBnLmFkZEVkZ2UoZWRnZS5mcm9tLCBlZGdlLnRvKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2NlbmUuZ2V0TmF2aWdhdGlvbk1hbmFnZXIoKS5hZGROYXZpZ2FibGVFbnRpdHkobmF2bWVzaE5hbWUsIG5ldyBOYXZtZXNoKGcpKTtcblxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBMYXllciBpcyBhbiBvYmplY3QgbGF5ZXIsIHNvIGFkZCBlYWNoIG9iamVjdCBhcyBhIHNwcml0ZSB0byBhIG5ldyBsYXllclxuICAgICAgICAgICAgICAgIGZvcihsZXQgb2JqIG9mIGxheWVyLm9iamVjdHMpe1xuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBvYmogaXMgY29sbGlkYWJsZVxuICAgICAgICAgICAgICAgICAgICBsZXQgaGFzUGh5c2ljcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgaXNDb2xsaWRhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpc1RyaWdnZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG9uRW50ZXIgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb25FeGl0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRyaWdnZXJHcm91cCA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGxldCBncm91cCA9IFwiXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYob2JqLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBwcm9wIG9mIG9iai5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihwcm9wLm5hbWUgPT09IFwiSGFzUGh5c2ljc1wiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzUGh5c2ljcyA9IHByb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJDb2xsaWRhYmxlXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0NvbGxpZGFibGUgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiR3JvdXBcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIklzVHJpZ2dlclwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNUcmlnZ2VyID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIlRyaWdnZXJHcm91cFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckdyb3VwID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIlRyaWdnZXJPbkVudGVyXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkVudGVyID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIlRyaWdnZXJPbkV4aXRcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uRXhpdCA9IHByb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IHNwcml0ZTogU3ByaXRlO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIG9iaiBpcyBhIHRpbGUgZnJvbSBhIHRpbGVzZXRcbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCB0aWxlc2V0IG9mIHRpbGVzZXRzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRpbGVzZXQuaGFzVGlsZShvYmouZ2lkKSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIG9iamVjdCBpcyBhIHRpbGUgZnJvbSB0aGlzIHNldFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbWFnZUtleSA9IHRpbGVzZXQuZ2V0SW1hZ2VLZXkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0ID0gdGlsZXNldC5nZXRJbWFnZU9mZnNldEZvclRpbGUob2JqLmdpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlID0gdGhpcy5zY2VuZS5hZGQuc3ByaXRlKGltYWdlS2V5LCBsYXllci5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2l6ZSA9IHRpbGVzZXQuZ2V0VGlsZVNpemUoKS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5wb3NpdGlvbi5zZXQoKG9iai54ICsgc2l6ZS54LzIpKnNjYWxlLngsIChvYmoueSAtIHNpemUueS8yKSpzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUuc2V0SW1hZ2VPZmZzZXQob2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUuc2l6ZS5jb3B5KHNpemUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zY2FsZS5zZXQoc2NhbGUueCwgc2NhbGUueSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBOb3QgaW4gYSB0aWxlc2V0LCBtdXN0IGNvcnJlc3BvbmQgdG8gYSBjb2xsZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIGlmKCFzcHJpdGUpe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGxldCB0aWxlIG9mIGNvbGxlY3Rpb25UaWxlcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYob2JqLmdpZCA9PT0gdGlsZS5pZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbWFnZUtleSA9IHRpbGUuaW1hZ2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZSA9IHRoaXMuc2NlbmUuYWRkLnNwcml0ZShpbWFnZUtleSwgbGF5ZXIubmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5wb3NpdGlvbi5zZXQoKG9iai54ICsgdGlsZS5pbWFnZXdpZHRoLzIpKnNjYWxlLngsIChvYmoueSAtIHRpbGUuaW1hZ2VoZWlnaHQvMikqc2NhbGUueSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zY2FsZS5zZXQoc2NhbGUueCwgc2NhbGUueSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTm93IHdlIGhhdmUgc3ByaXRlLiBBc3NvY2lhdGUgaXQgd2l0aCBvdXIgcGh5c2ljcyBvYmplY3QgaWYgdGhlcmUgaXMgb25lXG4gICAgICAgICAgICAgICAgICAgIGlmKGhhc1BoeXNpY3Mpe1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSB0aGUgc3ByaXRlIGEgc3RhdGljIHBoeXNpY3Mgb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUuYWRkUGh5c2ljcyhzcHJpdGUuYm91bmRhcnkuY2xvbmUoKSwgVmVjMi5aRVJPLCBpc0NvbGxpZGFibGUsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNldEdyb3VwKGdyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzVHJpZ2dlciAmJiB0cmlnZ2VyR3JvdXAgIT09IG51bGwpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zZXRUcmlnZ2VyKHRyaWdnZXJHcm91cCwgb25FbnRlciwgb25FeGl0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSByZXR1cm4gdmFsdWVcbiAgICAgICAgICAgIHNjZW5lTGF5ZXJzLnB1c2goc2NlbmVMYXllcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2NlbmVMYXllcnM7XG5cdH1cbn0iLCJpbXBvcnQgU2NlbmUgZnJvbSBcIi4vU2NlbmVcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuXG5cbi8qKlxuICogQSBsYXllciBpbiB0aGUgc2NlbmUuIExheWVycyBhcmUgdXNlZCBmb3Igc29ydGluZyBAcmVmZXJlbmNlW0dhbWVOb2RlXXMgYnkgZGVwdGguXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExheWVyIHtcbiAgICAvKiogVGhlIHNjZW5lIHRoaXMgbGF5ZXIgYmVsb25ncyB0byAqL1xuICAgIHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cbiAgICAvKiogVGhlIG5hbWUgb2YgdGhpcyBsYXllciAqL1xuICAgIHByb3RlY3RlZCBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKiogV2hldGhlciB0aGlzIGxheWVyIGlzIHBhdXNlZCBvciBub3QgKi9cbiAgICBwcm90ZWN0ZWQgcGF1c2VkOiBib29sZWFuO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhpcyBsYXllciBpcyBoaWRkZW4gZnJvbSBiZWluZyByZW5kZXJlZCBvciBub3QgKi9cbiAgICBwcm90ZWN0ZWQgaGlkZGVuOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBnbG9iYWwgYWxwaGEgbGV2ZWwgb2YgdGhpcyBsYXllciAqL1xuICAgIHByb3RlY3RlZCBhbHBoYTogbnVtYmVyO1xuXG4gICAgLyoqIEFuIGFycmF5IG9mIHRoZSBHYW1lTm9kZXMgdGhhdCBiZWxvbmcgdG8gdGhpcyBsYXllciAqL1xuICAgIHByb3RlY3RlZCBpdGVtczogQXJyYXk8R2FtZU5vZGU+O1xuXG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgbGF5ZXIgc2hvdWxkIGJlIHlzb3J0ZWQgKi9cbiAgICBwcm90ZWN0ZWQgeVNvcnQ6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIGRlcHRoIG9mIHRoaXMgbGF5ZXIgY29tcGFyZWQgdG8gb3RoZXIgbGF5ZXJzICovXG4gICAgcHJvdGVjdGVkIGRlcHRoOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGxheWVyLiBUbyBkbyB0aGlzIGluIGEgZ2FtZSwgdXNlIHRoZSBhZGRMYXllcigpIG1ldGhvZCBpbiBAcmVmcmVuY2VbU2NlbmVdXG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBzY2VuZSB0byBhZGQgdGhlIGxheWVyIHRvXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3Ioc2NlbmU6IFNjZW5lLCBuYW1lOiBzdHJpbmcpe1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMucGF1c2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaGlkZGVuID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWxwaGEgPSAxO1xuICAgICAgICB0aGlzLml0ZW1zID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMueVNvcnQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5kZXB0aCA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmVpdmVzIHRoZSBuYW1lIG9mIHRoZSBsYXllclxuICAgICAqIEByZXR1cm5zIFRoZSBuYW1lIG9mIHRoZSBsYXllclxuICAgICAqL1xuICAgIGdldE5hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXVzZXMvVW5wYXVzZXMgdGhlIGxheWVyLiBBZmZlY3RzIGFsbCBlbGVtZW50cyBpbiB0aGlzIGxheWVyXG4gICAgICogQHBhcmFtIHBhdXNlVmFsdWUgVHJ1ZSBpZiB0aGUgbGF5ZXIgc2hvdWxkIGJlIHBhdXNlZCwgZmFsc2UgaWYgbm90XG4gICAgICovXG4gICAgc2V0UGF1c2VkKHBhdXNlVmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBwYXVzZVZhbHVlO1xuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBsYXllciBpcyBwYXVzZWRcbiAgICAgKi9cbiAgICBpc1BhdXNlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGF1c2VkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG9wYWNpdHkgb2YgdGhlIGxheWVyXG4gICAgICogQHBhcmFtIGFscGhhIFRoZSBuZXcgb3BhY2l0eSB2YWx1ZSBpbiB0aGUgcmFuZ2UgWzAsIDFdXG4gICAgICovXG4gICAgc2V0QWxwaGEoYWxwaGE6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmFscGhhID0gTWF0aFV0aWxzLmNsYW1wKGFscGhhLCAwLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBvcGFjaXR5IG9mIHRoZSBsYXllclxuICAgICAqIEByZXR1cm5zIFRoZSBvcGFjaXR5XG4gICAgICovXG4gICAgZ2V0QWxwaGEoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWxwaGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbGF5ZXIncyBoaWRkZW4gdmFsdWUuIElmIGhpZGRlbiwgYSBsYXllciB3aWxsIG5vdCBiZSByZW5kZXJlZCwgYnV0IHdpbGwgc3RpbGwgdXBkYXRlXG4gICAgICogQHBhcmFtIGhpZGRlbiBUaGUgaGlkZGVuIHZhbHVlIG9mIHRoZSBsYXllclxuICAgICAqL1xuICAgIHNldEhpZGRlbihoaWRkZW46IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5oaWRkZW4gPSBoaWRkZW47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaGlkZWVuIHZhbHVlIG9mIHRoZSBseWFlclxuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHNjZW5lIGlzIGhpZGRlbiwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaXNIaWRkZW4oKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmhpZGRlbjtcbiAgICB9XG5cbiAgICAvKiogUGF1c2VzIHRoaXMgc2NlbmUgYW5kIGhpZGVzIGl0ICovXG4gICAgZGlzYWJsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmhpZGRlbiA9IHRydWU7XG4gICAgfVxuXG4gICAgLyoqIFVucGF1c2VzIHRoaXMgbGF5ZXIgYW5kIG1ha2VzIGl0IHZpc2libGUgKi9cbiAgICBlbmFibGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGF1c2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaGlkZGVuID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB3aGV0aGVyIG9yIG5vdCB0aGUgc2NlbmUgd2lsbCB5U29ydCBhdXRvbWF0aWNhbGx5LlxuICAgICAqIHlTb3J0aW5nIG1lYW5zIHRoYXQgQ2FudmFzTm9kZXMgb24gdGhpcyBsYXllciB3aWxsIGhhdmUgdGhlaXIgZGVwdGggc29ydGVkIGRlcGVuZGluZyBvbiB0aGVpciB5LXZhbHVlLlxuICAgICAqIFRoaXMgbWVhbnMgdGhhdCBpZiBhbiBvYmplY3QgaXMgXCJoaWdoZXJcIiBpbiB0aGUgc2NlbmUsIGl0IHdpbGwgc29ydCBiZWhpbmQgb2JqZWN0cyB0aGF0IGFyZSBcImxvd2VyXCIuXG4gICAgICogVGhpcyBpcyB1c2VmdWwgZm9yIDMvNCB2aWV3IGdhbWVzLCBvciBzaW1pbGFyIHNpdHVhdGlvbnMsIHdoZXJlIHlvdSBzb21ldGltZXMgd2FudCB0byBiZSBpbiBmcm9udCBvZiBvYmplY3RzLFxuICAgICAqIGFuZCBvdGhlciB0aW1lcyB3YW50IHRvIGJlIGJlaGluZCB0aGUgc2FtZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB5U29ydCBUcnVlIGlmIHlTb3J0aW5nIHNob3VsZCBiZSBhY3RpdmUsIGZhbHNlIGlmIG5vdFxuICAgICAqL1xuICAgIHNldFlTb3J0KHlTb3J0OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMueVNvcnQgPSB5U29ydDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB5U29ydCBzdGF0dXMgb2YgdGhlIHNjZW5lXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB5U29ydGluZyBpcyBvY2N1cnJpbmcsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGdldFlTb3J0KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy55U29ydDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBkZXB0aCBvZiB0aGUgbGF5ZXIgY29tcGFyZWQgdG8gb3RoZXIgbGF5ZXJzLiBBIGxhcmdlciBudW1iZXIgbWVhbnMgdGhlIGxheWVyIHdpbGwgYmUgY2xvc2VyIHRvIHRoZSBzY3JlZW4uXG4gICAgICogQHBhcmFtIGRlcHRoIFRoZSBkZXB0aCBvZiB0aGUgbGF5ZXIuXG4gICAgICovXG4gICAgc2V0RGVwdGgoZGVwdGg6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmRlcHRoID0gZGVwdGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBkZXB0aCBvZiB0aGUgbGF5ZXIuXG4gICAgICogQHJldHVybnMgVGhlIGRlcHRoXG4gICAgICovXG4gICAgZ2V0RGVwdGgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVwdGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIG5vZGUgdG8gdGhpcyBsYXllclxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIGFkZCB0byB0aGlzIGxheWVyLlxuICAgICAqL1xuICAgIGFkZE5vZGUobm9kZTogR2FtZU5vZGUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pdGVtcy5wdXNoKG5vZGUpO1xuICAgICAgICBub2RlLnNldExheWVyKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBub2RlIGZyb20gdGhpcyBsYXllclxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIHJlbW92ZVxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIG5vZGUgd2FzIHJlbW92ZWQsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHJlbW92ZU5vZGUobm9kZTogR2FtZU5vZGUpOiB2b2lkIHtcbiAgICAgICAgLy8gRmluZCBhbmQgcmVtb3ZlIHRoZSBub2RlXG4gICAgICAgIGxldCBpbmRleCA9IHRoaXMuaXRlbXMuaW5kZXhPZihub2RlKTtcblxuICAgICAgICBpZihpbmRleCAhPT0gLTEpe1xuICAgICAgICAgICAgdGhpcy5pdGVtcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgbm9kZS5zZXRMYXllcih1bmRlZmluZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmVpdmVzIGFsbCBHYW1lTm9kZXMgZnJvbSB0aGlzIGxheWVyXG4gICAgICogQHJldHVybnMgYW4gQXJyYXkgdGhhdCBjb250YWlucyBhbGwgb2YgdGhlIEdhbWVOb2RlcyBpbiB0aGlzIGxheWVyLlxuICAgICAqL1xuICAgIGdldEl0ZW1zKCk6IEFycmF5PEdhbWVOb2RlPiB7XG4gICAgICAgIHJldHVybiB0aGlzLml0ZW1zO1xuICAgIH1cbn0iLCJpbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL0xheWVyXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcblxuLyoqXG4gKiBBbiBleHRlbnNpb24gb2YgYSBMYXllciB0aGF0IGhhcyBhIHBhcmFsbGF4IHZhbHVlLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYXJhbGxheExheWVyIGV4dGVuZHMgTGF5ZXIge1xuXHQvKiogVGhlIHZhbHVlIG9mIHRoZSBwYXJhbGxheCBvZiB0aGUgTGF5ZXIgKi9cblx0cGFyYWxsYXg6IFZlYzI7XG5cdFxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBQYXJhbGxheExheWVyLlxuXHQgKiBVc2UgYWRkUGFyYWxsYXhMYXllcigpIGluIEByZWZlcmVuY2VbU2NlbmVdIHRvIGFkZCBhIGxheWVyIG9mIHRoaXMgdHlwZSB0byB5b3VyIGdhbWUuXG5cdCAqIEBwYXJhbSBzY2VuZSBUaGUgU2NlbmUgdG8gYWRkIHRoaXMgUGFyYWxsYXhMYXllciB0b1xuXHQgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgUGFyYWxsYXhMYXllclxuXHQgKiBAcGFyYW0gcGFyYWxsYXggVGhlIHBhcmFsbGF4IGxldmVsXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihzY2VuZTogU2NlbmUsIG5hbWU6IHN0cmluZywgcGFyYWxsYXg6IFZlYzIpe1xuXHRcdHN1cGVyKHNjZW5lLCBuYW1lKTtcblx0XHR0aGlzLnBhcmFsbGF4ID0gcGFyYWxsYXg7XG5cdH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcbmltcG9ydCBQYXJhbGxheExheWVyIGZyb20gXCIuL1BhcmFsbGF4TGF5ZXJcIjtcblxuLyoqXG4gKiBBIExheWVyIHN0cmljdGx5IHRvIGJlIHVzZWQgZm9yIG1hbmFnaW5nIFVJRWxlbWVudHMuXG4gKiBUaGlzIGlzIGludGVuZGVkIHRvIGJlIGEgTGF5ZXIgdGhhdCBhbHdheXMgc3RheXMgaW4gdGhlIHNhbWUgcGxhY2UsXG4gKiBhbmQgdGh1cyByZW5kZXJzIHRoaW5ncyBsaWtlIGEgSFVEIG9yIGFuIGludmVudG9yeSB3aXRob3V0IHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gdGhlIFxccmVmZXJlbmNlW1ZpZXdwb3J0XSBzY3JvbGwuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFVJTGF5ZXIgZXh0ZW5kcyBQYXJhbGxheExheWVyIHtcblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgVUlMYXllci5cblx0ICogVXNlIGFkZFVJTGF5ZXIoKSBpbiBAcmVmZXJlbmNlW1NjZW5lXSB0byBhZGQgYSBsYXllciBvZiB0aGlzIHR5cGUgdG8geW91ciBnYW1lLlxuXHQgKiBAcGFyYW0gc2NlbmUgVGhlIFNjZW5lIHRvIGFkZCB0aGlzIFVJTGF5ZXIgdG9cblx0ICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIFVJTGF5ZXJcblx0ICovXG5cdGNvbnN0cnVjdG9yKHNjZW5lOiBTY2VuZSwgbmFtZTogc3RyaW5nKXtcblx0XHRzdXBlcihzY2VuZSwgbmFtZSwgVmVjMi5aRVJPKTtcblx0fVxufSIsImltcG9ydCBMYXllciBmcm9tIFwiLi9MYXllclwiO1xuaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuLi9TY2VuZUdyYXBoL1ZpZXdwb3J0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBTY2VuZUdyYXBoIGZyb20gXCIuLi9TY2VuZUdyYXBoL1NjZW5lR3JhcGhcIjtcbmltcG9ydCBQaHlzaWNzTWFuYWdlciBmcm9tIFwiLi4vUGh5c2ljcy9QaHlzaWNzTWFuYWdlclwiO1xuaW1wb3J0IEJhc2ljUGh5c2ljc01hbmFnZXIgZnJvbSBcIi4uL1BoeXNpY3MvQmFzaWNQaHlzaWNzTWFuYWdlclwiO1xuaW1wb3J0IFNjZW5lR3JhcGhBcnJheSBmcm9tIFwiLi4vU2NlbmVHcmFwaC9TY2VuZUdyYXBoQXJyYXlcIjtcbmltcG9ydCBGYWN0b3J5TWFuYWdlciBmcm9tIFwiLi9GYWN0b3JpZXMvRmFjdG9yeU1hbmFnZXJcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgR2FtZSBmcm9tIFwiLi4vTG9vcC9HYW1lXCI7XG5pbXBvcnQgU2NlbmVNYW5hZ2VyIGZyb20gXCIuL1NjZW5lTWFuYWdlclwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi9FdmVudHMvRW1pdHRlclwiO1xuaW1wb3J0IFVwZGF0ZWFibGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1VwZGF0ZWFibGVcIjtcbmltcG9ydCBOYXZpZ2F0aW9uTWFuYWdlciBmcm9tIFwiLi4vUGF0aGZpbmRpbmcvTmF2aWdhdGlvbk1hbmFnZXJcIjtcbmltcG9ydCBBSU1hbmFnZXIgZnJvbSBcIi4uL0FJL0FJTWFuYWdlclwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4vTGF5ZXJzL1BhcmFsbGF4TGF5ZXJcIjtcbmltcG9ydCBVSUxheWVyIGZyb20gXCIuL0xheWVycy9VSUxheWVyXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IFNjZW5lT3B0aW9ucyBmcm9tIFwiLi9TY2VuZU9wdGlvbnNcIjtcbmltcG9ydCBSZW5kZXJpbmdNYW5hZ2VyIGZyb20gXCIuLi9SZW5kZXJpbmcvUmVuZGVyaW5nTWFuYWdlclwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IFRpbWVyTWFuYWdlciBmcm9tIFwiLi4vVGltaW5nL1RpbWVyTWFuYWdlclwiO1xuaW1wb3J0IFR3ZWVuTWFuYWdlciBmcm9tIFwiLi4vUmVuZGVyaW5nL0FuaW1hdGlvbnMvVHdlZW5NYW5hZ2VyXCI7XG5pbXBvcnQgUGFydGljbGVTeXN0ZW1NYW5hZ2VyIGZyb20gXCIuLi9SZW5kZXJpbmcvQW5pbWF0aW9ucy9QYXJ0aWNsZVN5c3RlbU1hbmFnZXJcIjtcblxuLyoqXG4gKiBTY2VuZXMgYXJlIHRoZSBtYWluIGNvbnRhaW5lciBpbiB0aGUgZ2FtZSBlbmdpbmUuXG4gKiBZb3VyIG1haW4gc2NlbmUgaXMgdGhlIGN1cnJlbnQgbGV2ZWwgb3IgbWVudSBvZiB0aGUgZ2FtZSwgYW5kIHdpbGwgY29udGFpbiBhbGwgb2YgdGhlIEdhbWVOb2RlcyBuZWVkZWQuXG4gKiBTY2VuZXMgcHJvdmlkZSBhbiBlYXN5IHdheSB0byBsb2FkIGFzc2V0cywgYWRkIGFzc2V0cyB0byB0aGUgZ2FtZSB3b3JsZCwgYW5kIHVubG9hZCBhc3NldHMsXG4gKiBhbmQgaGF2ZSBsaWZlY3ljbGUgbWV0aG9kcyBleHBvc2VkIGZvciB0aGVzZSBmdW5jdGlvbnMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG4gICAgLyoqIFRoZSBzaXplIG9mIHRoZSBnYW1lIHdvcmxkLiAqL1xuICAgIHByb3RlY3RlZCB3b3JsZFNpemU6IFZlYzI7XG5cbiAgICAvKiogVGhlIHZpZXdwb3J0LiAqL1xuICAgIHByb3RlY3RlZCB2aWV3cG9ydDogVmlld3BvcnQ7XG5cbiAgICAvKiogQSBmbGFnIHRoYXQgcmVwcmVzZW50cyB3aGV0aGVyIHRoaXMgc2NlbmUgaXMgcnVubmluZyBvciBub3QuICovXG4gICAgcHJvdGVjdGVkIHJ1bm5pbmc6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIG1hbmFnZXIgb2YgdGhpcyBzY2VuZS4gKi9cbiAgICBwcm90ZWN0ZWQgc2NlbmVNYW5hZ2VyOiBTY2VuZU1hbmFnZXI7XG5cbiAgICAvKiogVGhlIHJlY2VpdmVyIGZvciB0aGlzIHNjZW5lLiAqL1xuICAgIHByb3RlY3RlZCByZWNlaXZlcjogUmVjZWl2ZXI7XG5cbiAgICAvKiogVGhlIGVtaXR0ZXIgZm9yIHRoaXMgc2NlbmUuICovXG4gICAgcHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cbiAgICAvKiogVGhpcyBsaXN0IG9mIHRpbGVtYXBzIGluIHRoaXMgc2NlbmUuICovXG4gICAgcHJvdGVjdGVkIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPjtcblxuICAgIC8qKiBBIG1hcCBmcm9tIGxheWVyIG5hbWVzIHRvIHRoZSBsYXllcnMgdGhlbXNlbHZlcyAqL1xuICAgIHByb3RlY3RlZCBsYXllcnM6IE1hcDxMYXllcj47XG5cbiAgICAvKiogQSBtYXAgZnJvbSBwYXJhbGxheCBsYXllciBuYW1lcyB0byB0aGUgcGFyYWxsYXggbGF5ZXJzIHRoZW1zZWx2ZXMgKi9cbiAgICBwcm90ZWN0ZWQgcGFyYWxsYXhMYXllcnM6IE1hcDxQYXJhbGxheExheWVyPjtcblxuICAgIC8qKiBBIG1hcCBmcm9tIHVpTGF5ZXIgbmFtZXMgdG8gdGhlIHVpTGF5ZXJzIHRoZW1zZWx2ZXMgKi9cbiAgICBwcm90ZWN0ZWQgdWlMYXllcnM6IE1hcDxVSUxheWVyPjtcblxuICAgIC8qKiBUaGUgc2NlbmUgZ3JhcGggb2YgdGhlIFNjZW5lKi9cbiAgICBwcm90ZWN0ZWQgc2NlbmVHcmFwaDogU2NlbmVHcmFwaDtcblxuICAgIC8qKiBUaGUgcGh5c2ljcyBtYW5hZ2VyIG9mIHRoZSBTY2VuZSAqL1xuICAgIHByb3RlY3RlZCBwaHlzaWNzTWFuYWdlcjogUGh5c2ljc01hbmFnZXI7XG4gICAgXG4gICAgLyoqIFRoZSBuYXZpZ2F0aW9uIG1hbmFnZXIgb2YgdGhlIFNjZW5lICovXG4gICAgcHJvdGVjdGVkIG5hdk1hbmFnZXI6IE5hdmlnYXRpb25NYW5hZ2VyO1xuXG4gICAgLyoqIFRoZSBBSSBtYW5hZ2VyIG9mIHRoZSBTY2VuZSAqL1xuICAgIHByb3RlY3RlZCBhaU1hbmFnZXI6IEFJTWFuYWdlcjtcblxuICAgIC8qKiBUaGUgcmVuZGVyaW5nTWFuYWdlciBvZiB0aGUgc2NlbmUgKi9cbiAgICBwcm90ZWN0ZWQgcmVuZGVyaW5nTWFuYWdlcjogUmVuZGVyaW5nTWFuYWdlcjtcblxuICAgIC8qKiBBbiBpbnRlcmZhY2UgdGhhdCBhbGxvd3MgdGhlIGFkZGluZyBvZiBkaWZmZXJlbnQgbm9kZXMgdG8gdGhlIHNjZW5lICovXG4gICAgcHVibGljIGFkZDogRmFjdG9yeU1hbmFnZXI7XG5cbiAgICAvKiogQW4gaW50ZXJmYWNlIHRoYXQgYWxsb3dzIHRoZSBsb2FkaW5nIG9mIGRpZmZlcmVudCBmaWxlcyBmb3IgdXNlIGluIHRoZSBzY2VuZS4gQW4gYWxpYXMgZm9yIHJlc291cmNlTWFuYWdlciAqL1xuICAgIHB1YmxpYyBsb2FkOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvKiogQW4gaW50ZXJmYWNlIHRoYXQgYWxsb3dzIHRoZSBsb2FkaW5nIGFuZCB1bmxvYWRpbmcgb2YgZGlmZmVyZW50IGZpbGVzIGZvciB1c2UgaW4gdGhlIHNjZW5lICovXG4gICAgcHVibGljIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG4gICAgLyoqIFRoZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoaXMgc2NlbmUgKi9cbiAgICBwdWJsaWMgc2NlbmVPcHRpb25zOiBTY2VuZU9wdGlvbnM7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IFNjZW5lLiBUbyBhZGQgYSBuZXcgU2NlbmUgaW4geW91ciBnYW1lLCB1c2UgY2hhbmdlVG9TY2VuZSgpIGluIEByZWZlcmVuY2VbU2NlbmVNYW5hZ2VyXVxuICAgICAqIEBwYXJhbSB2aWV3cG9ydCBUaGUgdmlld3BvcnQgb2YgdGhlIGdhbWVcbiAgICAgKiBAcGFyYW0gc2NlbmVNYW5hZ2VyIFRoZSBTY2VuZU1hbmFnZXIgdGhhdCBvd25zIHRoaXMgU2NlbmVcbiAgICAgKiBAcGFyYW0gcmVuZGVyaW5nTWFuYWdlciBUaGUgUmVuZGVyaW5nTWFuYWdlciB0aGF0IHdpbGwgaGFuZGxlIHRoaXMgU2NlbmUncyByZW5kZXJpbmdcbiAgICAgKiBAcGFyYW0gZ2FtZSBUaGUgaW5zdGFuY2Ugb2YgdGhlIEdhbWVcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgb3B0aW9ucyBmb3IgU2NlbmUgaW5pdGlhbGl6YXRpb25cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih2aWV3cG9ydDogVmlld3BvcnQsIHNjZW5lTWFuYWdlcjogU2NlbmVNYW5hZ2VyLCByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KXtcbiAgICAgICAgdGhpcy5zY2VuZU9wdGlvbnMgPSBTY2VuZU9wdGlvbnMucGFyc2Uob3B0aW9ucyA9PT0gdW5kZWZpbmVkID8ge30gOiBvcHRpb25zKTtcblxuICAgICAgICB0aGlzLndvcmxkU2l6ZSA9IG5ldyBWZWMyKDUwMCwgNTAwKTtcbiAgICAgICAgdGhpcy52aWV3cG9ydCA9IHZpZXdwb3J0O1xuICAgICAgICB0aGlzLnZpZXdwb3J0LnNldEJvdW5kcygwLCAwLCAyNTYwLCAxMjgwKTtcbiAgICAgICAgdGhpcy5ydW5uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyID0gc2NlbmVNYW5hZ2VyO1xuICAgICAgICB0aGlzLnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG5cbiAgICAgICAgdGhpcy50aWxlbWFwcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLnNjZW5lR3JhcGggPSBuZXcgU2NlbmVHcmFwaEFycmF5KHRoaXMudmlld3BvcnQsIHRoaXMpO1xuXG4gICAgICAgIHRoaXMubGF5ZXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnVpTGF5ZXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnBhcmFsbGF4TGF5ZXJzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMucGh5c2ljc01hbmFnZXIgPSBuZXcgQmFzaWNQaHlzaWNzTWFuYWdlcih0aGlzLnNjZW5lT3B0aW9ucy5waHlzaWNzKTtcbiAgICAgICAgdGhpcy5uYXZNYW5hZ2VyID0gbmV3IE5hdmlnYXRpb25NYW5hZ2VyKCk7XG4gICAgICAgIHRoaXMuYWlNYW5hZ2VyID0gbmV3IEFJTWFuYWdlcigpO1xuICAgICAgICB0aGlzLnJlbmRlcmluZ01hbmFnZXIgPSByZW5kZXJpbmdNYW5hZ2VyO1xuXG4gICAgICAgIHRoaXMuYWRkID0gbmV3IEZhY3RvcnlNYW5hZ2VyKHRoaXMsIHRoaXMudGlsZW1hcHMpO1xuXG4gICAgICAgIHRoaXMubG9hZCA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpXG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gdGhpcy5sb2FkO1xuXG4gICAgICAgIC8vIEdldCB0aGUgdGltZXIgbWFuYWdlciBhbmQgY2xlYXIgYW55IGV4aXN0aW5nIHRpbWVyc1xuICAgICAgICBUaW1lck1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5jbGVhclRpbWVycygpO1xuICAgIH1cblxuICAgIC8qKiBBIGxpZmVjeWNsZSBtZXRob2QgdGhhdCBnZXRzIGNhbGxlZCBpbW1lZGlhdGVseSBhZnRlciBhIG5ldyBzY2VuZSBpcyBjcmVhdGVkLCBiZWZvcmUgYW55dGhpbmcgZWxzZS4gKi9cbiAgICBpbml0U2NlbmUoaW5pdDogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge31cblxuICAgIC8qKiBBIGxpZmVjeWNsZSBtZXRob2QgdGhhdCBnZXRzIGNhbGxlZCB3aGVuIGEgbmV3IHNjZW5lIGlzIGNyZWF0ZWQuIExvYWQgYWxsIGZpbGVzIHlvdSB3aXNoIHRvIGFjY2VzcyBpbiB0aGUgc2NlbmUgaGVyZS4gKi9cbiAgICBsb2FkU2NlbmUoKTogdm9pZCB7fVxuXG4gICAgLyoqIEEgbGlmZWN5Y2xlIG1ldGhvZCBjYWxsZWQgc3RyaWN0bHkgYWZ0ZXIgbG9hZFNjZW5lKCkuIENyZWF0ZSBhbnkgZ2FtZSBvYmplY3RzIHlvdSB3aXNoIHRvIHVzZSBpbiB0aGUgc2NlbmUgaGVyZS4gKi9cbiAgICBzdGFydFNjZW5lKCk6IHZvaWQge31cblxuICAgIC8qKlxuICAgICAqIEEgbGlmZWN5Y2xlIG1ldGhvZCBjYWxsZWQgZXZlcnkgZnJhbWUgb2YgdGhlIGdhbWUuIFRoaXMgaXMgd2hlcmUgeW91IGNhbiBkeW5hbWljYWxseSBkbyB0aGluZ3MgbGlrZSBhZGQgaW4gbmV3IGVuZW1pZXNcbiAgICAgKiBAcGFyYW0gZGVsdGEgVGhlIHRpbWUgdGhpcyBmcmFtZSByZXByZXNlbnRzXG4gICAgICovXG4gICAgdXBkYXRlU2NlbmUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHt9XG5cbiAgICAvKiogQSBsaWZlY3ljbGUgbWV0aG9kIHRoYXQgZ2V0cyBjYWxsZWQgb24gc2NlbmUgZGVzdHJ1Y3Rpb24uIFNwZWNpZnkgd2hpY2ggZmlsZXMgeW91IG5vIGxvbmdlciBuZWVkIGZvciBnYXJiYWdlIGNvbGxlY3Rpb24uICovXG4gICAgdW5sb2FkU2NlbmUoKTogdm9pZCB7fVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXBkYXRlU2NlbmUoZGVsdGFUKTtcblxuICAgICAgICAvLyBEbyB0aW1lIHVwZGF0ZXNcbiAgICAgICAgVGltZXJNYW5hZ2VyLmdldEluc3RhbmNlKCkudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgLy8gRG8gYWxsIEFJIHVwZGF0ZXNcbiAgICAgICAgdGhpcy5haU1hbmFnZXIudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIGFsbCBwaHlzaWNzIG9iamVjdHNcbiAgICAgICAgdGhpcy5waHlzaWNzTWFuYWdlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBVcGRhdGUgYWxsIGNhbnZhcyBvYmplY3RzXG4gICAgICAgIHRoaXMuc2NlbmVHcmFwaC51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBVcGRhdGUgYWxsIHRpbGVtYXBzXG4gICAgICAgIHRoaXMudGlsZW1hcHMuZm9yRWFjaCh0aWxlbWFwID0+IHtcbiAgICAgICAgICAgIGlmKCF0aWxlbWFwLmdldExheWVyKCkuaXNQYXVzZWQoKSl7XG4gICAgICAgICAgICAgICAgdGlsZW1hcC51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgICAgIH0gXG4gICAgICAgIH0pO1xuICAgICAgICBcbiAgICAgICAgLy8gVXBkYXRlIGFsbCB0d2VlbnNcbiAgICAgICAgVHdlZW5NYW5hZ2VyLmdldEluc3RhbmNlKCkudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIGFsbCBwYXJ0aWNsZSBzeXN0ZW1zXG4gICAgICAgIFBhcnRpY2xlU3lzdGVtTWFuYWdlci5nZXRJbnN0YW5jZSgpLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSB2aWV3cG9ydFxuICAgICAgICB0aGlzLnZpZXdwb3J0LnVwZGF0ZShkZWx0YVQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbGxlY3RzIHJlbmRlcmFibGUgc2V0cyBhbmQgY29vcmRpbmF0ZXMgd2l0aCB0aGUgUmVuZGVyaW5nTWFuYWdlciB0byBkcmF3IHRoZSBTY2VuZVxuICAgICAqL1xuICAgIHJlbmRlcigpOiB2b2lkIHtcbiAgICAgICAgLy8gR2V0IHRoZSB2aXNpYmxlIHNldCBvZiBub2Rlc1xuICAgICAgICBsZXQgdmlzaWJsZVNldCA9IHRoaXMuc2NlbmVHcmFwaC5nZXRWaXNpYmxlU2V0KCk7XG5cbiAgICAgICAgLy8gQWRkIHBhcmFsbGF4IGxheWVyIGl0ZW1zIHRvIHRoZSB2aXNpYmxlIHNldCAod2UncmUgcmVuZGVyaW5nIHRoZW0gYWxsIGZvciBub3cpXG4gICAgICAgIHRoaXMucGFyYWxsYXhMYXllcnMuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgbGV0IHBMYXllciA9IHRoaXMucGFyYWxsYXhMYXllcnMuZ2V0KGtleSk7XG4gICAgICAgICAgICBmb3IobGV0IG5vZGUgb2YgcExheWVyLmdldEl0ZW1zKCkpe1xuICAgICAgICAgICAgICAgIGlmKG5vZGUgaW5zdGFuY2VvZiBDYW52YXNOb2RlKXtcbiAgICAgICAgICAgICAgICAgICAgdmlzaWJsZVNldC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2VuZCB0aGUgdmlzaWJsZSBzZXQsIHRpbGVtYXBzLCBhbmQgdWlMYXllcnMgdG8gdGhlIHJlbmRlcmVyXG4gICAgICAgIHRoaXMucmVuZGVyaW5nTWFuYWdlci5yZW5kZXIodmlzaWJsZVNldCwgdGhpcy50aWxlbWFwcywgdGhpcy51aUxheWVycyk7XG5cbiAgICAgICAgbGV0IG5vZGVzID0gdGhpcy5zY2VuZUdyYXBoLmdldEFsbE5vZGVzKCk7XG4gICAgICAgIHRoaXMudGlsZW1hcHMuZm9yRWFjaCh0aWxlbWFwID0+IHRpbGVtYXAudmlzaWJsZSA/IG5vZGVzLnB1c2godGlsZW1hcCkgOiAwKTtcbiAgICAgICAgRGVidWcuc2V0Tm9kZXMobm9kZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIGFzIHJ1bm5pbmcgb3Igbm90XG4gICAgICogQHBhcmFtIHJ1bm5pbmcgVHJ1ZSBpZiB0aGUgU2NlbmUgc2hvdWxkIGJlIHJ1bm5pbmcsIGZhbHNlIGlmIG5vdFxuICAgICAqL1xuICAgIHNldFJ1bm5pbmcocnVubmluZzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnJ1bm5pbmcgPSBydW5uaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIFNjZW5lIGlzIHJ1bm5pbmdcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBzY2VuZSBpcyBydW5uaW5nLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpc1J1bm5pbmcoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnJ1bm5pbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIG5vZGUgZnJvbSB0aGlzIFNjZW5lXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG4gICAgICovXG4gICAgcmVtb3ZlKG5vZGU6IEdhbWVOb2RlKTogdm9pZCB7XG4gICAgICAgIC8vIFJlbW92ZSBmcm9tIHRoZSBzY2VuZSBncmFwaFxuICAgICAgICBpZihub2RlIGluc3RhbmNlb2YgQ2FudmFzTm9kZSl7XG4gICAgICAgICAgICB0aGlzLnNjZW5lR3JhcGgucmVtb3ZlTm9kZShub2RlKTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgLyoqIERlc3Ryb3lzIHRoaXMgc2NlbmUgYW5kIGFsbCBub2RlcyBpbiBpdCAqL1xuICAgIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIGZvcihsZXQgbm9kZSBvZiB0aGlzLnNjZW5lR3JhcGguZ2V0QWxsTm9kZXMoKSl7XG4gICAgICAgICAgICBub2RlLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihsZXQgdGlsZW1hcCBvZiB0aGlzLnRpbGVtYXBzKXtcbiAgICAgICAgICAgIHRpbGVtYXAuZGVzdHJveSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZWNlaXZlci5kZXN0cm95KCk7XG5cbiAgICAgICAgZGVsZXRlIHRoaXMuc2NlbmVHcmFwaDtcbiAgICAgICAgZGVsZXRlIHRoaXMucGh5c2ljc01hbmFnZXI7XG4gICAgICAgIGRlbGV0ZSB0aGlzLm5hdk1hbmFnZXI7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmFpTWFuYWdlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMucmVjZWl2ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIG5ldyBsYXllciB0byB0aGUgc2NlbmUgYW5kIHJldHVybnMgaXRcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbmV3IGxheWVyXG4gICAgICogQHBhcmFtIGRlcHRoIFRoZSBkZXB0aCBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBUaGUgbmV3bHkgY3JlYXRlZCBMYXllclxuICAgICAqL1xuICAgIGFkZExheWVyKG5hbWU6IHN0cmluZywgZGVwdGg/OiBudW1iZXIpOiBMYXllciB7XG4gICAgICAgIGlmKHRoaXMubGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnBhcmFsbGF4TGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnVpTGF5ZXJzLmhhcyhuYW1lKSl7XG4gICAgICAgICAgICB0aHJvdyBgTGF5ZXIgd2l0aCBuYW1lICR7bmFtZX0gYWxyZWFkeSBleGlzdHNgO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxheWVyID0gbmV3IExheWVyKHRoaXMsIG5hbWUpO1xuXG4gICAgICAgIHRoaXMubGF5ZXJzLmFkZChuYW1lLCBsYXllcik7XG5cbiAgICAgICAgaWYoZGVwdGgpe1xuICAgICAgICAgICAgbGF5ZXIuc2V0RGVwdGgoZGVwdGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGxheWVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBuZXcgcGFyYWxsYXggbGF5ZXIgdG8gdGhpcyBzY2VuZSBhbmQgcmV0dXJucyBpdFxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBwYXJhbGxheCBsYXllclxuICAgICAqIEBwYXJhbSBwYXJhbGxheCBUaGUgcGFyYWxsYXggbGV2ZWxcbiAgICAgKiBAcGFyYW0gZGVwdGggVGhlIGRlcHRoIG9mIHRoZSBsYXllclxuICAgICAqIEByZXR1cm5zIFRoZSBuZXdseSBjcmVhdGVkIFBhcmFsbGF4TGF5ZXJcbiAgICAgKi9cbiAgICBhZGRQYXJhbGxheExheWVyKG5hbWU6IHN0cmluZywgcGFyYWxsYXg6IFZlYzIsIGRlcHRoPzogbnVtYmVyKTogUGFyYWxsYXhMYXllciB7XG4gICAgICAgIGlmKHRoaXMubGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnBhcmFsbGF4TGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnVpTGF5ZXJzLmhhcyhuYW1lKSl7XG4gICAgICAgICAgICB0aHJvdyBgTGF5ZXIgd2l0aCBuYW1lICR7bmFtZX0gYWxyZWFkeSBleGlzdHNgO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxheWVyID0gbmV3IFBhcmFsbGF4TGF5ZXIodGhpcywgbmFtZSwgcGFyYWxsYXgpO1xuXG4gICAgICAgIHRoaXMucGFyYWxsYXhMYXllcnMuYWRkKG5hbWUsIGxheWVyKTtcblxuICAgICAgICBpZihkZXB0aCl7XG4gICAgICAgICAgICBsYXllci5zZXREZXB0aChkZXB0aCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIG5ldyBVSUxheWVyIHRvIHRoZSBzY2VuZVxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBuZXcgVUlsYXllclxuICAgICAqIEByZXR1cm5zIFRoZSBuZXdseSBjcmVhdGVkIFVJTGF5ZXJcbiAgICAgKi9cbiAgICBhZGRVSUxheWVyKG5hbWU6IHN0cmluZyk6IFVJTGF5ZXIge1xuICAgICAgICBpZih0aGlzLmxheWVycy5oYXMobmFtZSkgfHwgdGhpcy5wYXJhbGxheExheWVycy5oYXMobmFtZSkgfHwgdGhpcy51aUxheWVycy5oYXMobmFtZSkpe1xuICAgICAgICAgICAgdGhyb3cgYExheWVyIHdpdGggbmFtZSAke25hbWV9IGFscmVhZHkgZXhpc3RzYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsYXllciA9IG5ldyBVSUxheWVyKHRoaXMsIG5hbWUpO1xuXG4gICAgICAgIHRoaXMudWlMYXllcnMuYWRkKG5hbWUsIGxheWVyKTtcblxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIGxheWVyIGZyb20gdGhlIHNjZW5lIGJ5IG5hbWUgaWYgaXQgZXhpc3RzLlxuICAgICAqIFRoaXMgY2FuIGJlIGEgTGF5ZXIgb3IgYW55IG9mIGl0cyBzdWJjbGFzc2VzXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIExheWVyIGZvdW5kIHdpdGggdGhhdCBuYW1lXG4gICAgICovXG4gICAgZ2V0TGF5ZXIobmFtZTogc3RyaW5nKTogTGF5ZXIge1xuICAgICAgICBpZih0aGlzLmxheWVycy5oYXMobmFtZSkpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGF5ZXJzLmdldChuYW1lKTtcbiAgICAgICAgfSBlbHNlIGlmKHRoaXMucGFyYWxsYXhMYXllcnMuaGFzKG5hbWUpKXtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFsbGF4TGF5ZXJzLmdldChuYW1lKTtcbiAgICAgICAgfSBlbHNlIGlmKHRoaXMudWlMYXllcnMuaGFzKG5hbWUpKXtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnVpTGF5ZXJzLmdldChuYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGBSZXF1ZXN0ZWQgbGF5ZXIgJHtuYW1lfSBkb2VzIG5vdCBleGlzdC5gO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoaXMgbGF5ZXIgaXMgYSBQYXJhbGxheExheWVyXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIGxheWVyIGlzIGEgUGFyYWxsYXhMYXllclxuICAgICAqL1xuICAgIGlzUGFyYWxsYXhMYXllcihuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyYWxsYXhMYXllcnMuaGFzKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIGxheWVyIGlzIGEgVUlMYXllclxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBsYXllclxuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhpcyBsYXllciBpcyBQYXJhbGxheExheWVyXG4gICAgICovXG4gICAgaXNVSUxheWVyKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy51aUxheWVycy5oYXMobmFtZSk7XG4gICAgfSAgICBcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHRyYW5zbGF0aW9uIG9mIHRoaXMgbm9kZSB3aXRoIHJlc3BlY3QgdG8gY2FtZXJhIHNwYWNlIChkdWUgdG8gdGhlIHZpZXdwb3J0IG1vdmluZykuXG4gICAgICogVGhpcyB2YWx1ZSBpcyBhZmZlY3RlZCBieSB0aGUgcGFyYWxsYXggbGV2ZWwgb2YgdGhlIEByZWZlcmVuY2VbTGF5ZXJdIHRoZSBub2RlIGlzIG9uLlxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIGNoZWNrIHRoZSB2aWV3cG9ydCB3aXRoIHJlc3BlY3QgdG9cbiAgICAgKiBAcmV0dXJucyBBIFZlYzIgY29udGFpbmluZyB0aGUgdHJhbnNsYXRpb24gb2Ygdmlld3BvcnQgd2l0aCByZXNwZWN0IHRvIHRoaXMgbm9kZS5cbiAgICAgKi9cbiAgICBnZXRWaWV3VHJhbnNsYXRpb24obm9kZTogR2FtZU5vZGUpOiBWZWMyIHtcbiAgICAgICAgbGV0IGxheWVyID0gbm9kZS5nZXRMYXllcigpO1xuXG4gICAgICAgIGlmKGxheWVyIGluc3RhbmNlb2YgUGFyYWxsYXhMYXllciB8fCBsYXllciBpbnN0YW5jZW9mIFVJTGF5ZXIpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmlld3BvcnQuZ2V0T3JpZ2luKCkubXVsdChsYXllci5wYXJhbGxheCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52aWV3cG9ydC5nZXRPcmlnaW4oKTtcbiAgICAgICAgfVxuXHR9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzY2FsZSBsZXZlbCBvZiB0aGUgdmlld1xuICAgICAqIEByZXR1cm5zIFRoZSB6b29tIGxldmVsIG9mIHRoZSB2aWV3cG9ydFxuICAgICovXG5cdGdldFZpZXdTY2FsZSgpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLnZpZXdwb3J0LmdldFpvb21MZXZlbCgpO1xuXHR9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBWaWV3cG9ydCBhc3NvY2lhdGVkIHdpdGggdGhpcyBzY2VuZVxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IFZpZXdwb3J0XG4gICAgICovXG4gICAgZ2V0Vmlld3BvcnQoKTogVmlld3BvcnQge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3cG9ydDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB3b3JsZCBzaXplIG9mIHRoaXMgU2NlbmVcbiAgICAgKiBAcmV0dXJucyBUaGUgd29ybGQgc2l6ZSBpbiBhIFZlYzJcbiAgICAgKi9cbiAgICBnZXRXb3JsZFNpemUoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLndvcmxkU2l6ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBTY2VuZUdyYXBoIGFzc29jaWF0ZWQgd2l0aCB0aGlzIFNjZW5lXG4gICAgICogQHJldHVybnMgVGhlIFNjZW5lR3JhcGhcbiAgICAgKi9cbiAgICBnZXRTY2VuZUdyYXBoKCk6IFNjZW5lR3JhcGgge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2VuZUdyYXBoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIFBoeXNpY3NNYW5hZ2VyIGFzc29jaWF0ZWQgd2l0aCB0aGlzIFNjZW5lXG4gICAgICogQHJldHVybnMgVGhlIFBoeXNpY3NNYW5hZ2VyXG4gICAgICovXG4gICAgZ2V0UGh5c2ljc01hbmFnZXIoKTogUGh5c2ljc01hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5waHlzaWNzTWFuYWdlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBOYXZpZ2F0aW9uTWFuYWdlciBhc3NvY2lhdGVkIHdpdGggdGhpcyBTY2VuZVxuICAgICAqIEByZXR1cm5zIFRoZSBOYXZpZ2F0aW9uTWFuYWdlclxuICAgICAqL1xuICAgIGdldE5hdmlnYXRpb25NYW5hZ2VyKCk6IE5hdmlnYXRpb25NYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmF2TWFuYWdlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBBSU1hbmFnZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgU2NlbmVcbiAgICAgKiBAcmV0dXJucyBUaGUgQUlNYW5hZ2VyXG4gICAgICovXG4gICAgZ2V0QUlNYW5hZ2VyKCk6IEFJTWFuYWdlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmFpTWFuYWdlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZXMgYW4gSUQgZm9yIGEgR2FtZU5vZGVcbiAgICAgKiBAcmV0dXJucyBUaGUgbmV3IElEXG4gICAgICovXG4gICAgZ2VuZXJhdGVJZCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2VuZU1hbmFnZXIuZ2VuZXJhdGVJZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhIFRpbGVtYXAgaW4gdGhpcyBTY2VuZVxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBUaWxlbWFwXG4gICAgICogQHJldHVybnMgVGhlIFRpbGVtYXAsIGlmIG9uZSB0aGlzIG5hbWUgZXhpc3RzLCBvdGhlcndpc2UgbnVsbFxuICAgICAqL1xuICAgIGdldFRpbGVtYXAobmFtZTogc3RyaW5nKTogVGlsZW1hcCB7XG4gICAgICAgIGZvcihsZXQgdGlsZW1hcCBvZiB0aGlzIC50aWxlbWFwcyl7XG4gICAgICAgICAgICBpZih0aWxlbWFwLm5hbWUgPT09IG5hbWUpe1xuICAgICAgICAgICAgICAgIHJldHVybiB0aWxlbWFwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi9TY2VuZVwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuLi9TY2VuZUdyYXBoL1ZpZXdwb3J0XCI7XG5pbXBvcnQgUmVuZGVyaW5nTWFuYWdlciBmcm9tIFwiLi4vUmVuZGVyaW5nL1JlbmRlcmluZ01hbmFnZXJcIjtcbmltcG9ydCBNZW1vcnlVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWVtb3J5VXRpbHNcIjtcblxuLyoqXG4gKiBUaGUgU2NlbmVNYW5hZ2VyIGFjdHMgYXMgYW4gaW50ZXJmYWNlIHRvIGNyZWF0ZSBTY2VuZXMsIGFuZCBoYW5kbGVzIHRoZSBsaWZlY3ljbGUgbWV0aG9kcyBvZiBTY2VuZXMuXG4gKiBJdCBnaXZlcyBTY2VuZXMgYWNjZXNzIHRvIGluZm9ybWF0aW9uIHRoZXkgbmVlZCBmcm9tIHRoZSBAcmVmZXJlbmNlW0dhbWVdIGNsYXNzIHdoaWxlIGtlZXBpbmcgYSBsYXllciBvZiBzZXBhcmF0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTY2VuZU1hbmFnZXIge1xuXHQvKiogVGhlIGN1cnJlbnQgU2NlbmUgb2YgdGhlIGdhbWUgKi9cblx0cHJvdGVjdGVkIGN1cnJlbnRTY2VuZTogU2NlbmU7XG5cblx0LyoqIFRoZSBWaWV3cG9ydCBvZiB0aGUgZ2FtZSAqL1xuXHRwcm90ZWN0ZWQgdmlld3BvcnQ6IFZpZXdwb3J0O1xuXG5cdC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgUmVzb3VyY2VNYW5hZ2VyICovXG5cdHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcblxuXHQvKiogQSBjb3VudGVyIHRvIGtlZXAgdHJhY2sgb2YgZ2FtZSBpZHMgKi9cblx0cHJvdGVjdGVkIGlkQ291bnRlcjogbnVtYmVyO1xuXG5cdC8qKiBUaGUgUmVuZGVyaW5nTWFuYWdlciBvZiB0aGUgZ2FtZSAqL1xuXHRwcm90ZWN0ZWQgcmVuZGVyaW5nTWFuYWdlcjogUmVuZGVyaW5nTWFuYWdlcjtcblxuXHQvKiogRm9yIGNvbnNpc3RlbmN5LCBvbmx5IGNoYW5nZSBzY2VuZXMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgdXBkYXRlIGN5Y2xlICovXG5cdHByb3RlY3RlZCBwZW5kaW5nU2NlbmU6IFNjZW5lO1xuXHRwcm90ZWN0ZWQgcGVuZGluZ1NjZW5lSW5pdDogUmVjb3JkPHN0cmluZywgYW55PjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBTY2VuZU1hbmFnZXJcblx0ICogQHBhcmFtIHZpZXdwb3J0IFRoZSBWaWV3cG9ydCBvZiB0aGUgZ2FtZVxuXHQgKiBAcGFyYW0gZ2FtZSBUaGUgR2FtZSBpbnN0YW5jZVxuXHQgKiBAcGFyYW0gcmVuZGVyaW5nTWFuYWdlciBUaGUgUmVuZGVyaW5nTWFuYWdlciBvZiB0aGUgZ2FtZVxuXHQgKi9cblx0Y29uc3RydWN0b3Iodmlld3BvcnQ6IFZpZXdwb3J0LCByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyKXtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHRcdHRoaXMudmlld3BvcnQgPSB2aWV3cG9ydDtcblx0XHR0aGlzLnJlbmRlcmluZ01hbmFnZXIgPSByZW5kZXJpbmdNYW5hZ2VyO1xuXHRcdHRoaXMuaWRDb3VudGVyID0gMDtcblx0XHR0aGlzLnBlbmRpbmdTY2VuZSA9IG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogQWRkIGEgc2NlbmUgYXMgdGhlIG1haW4gc2NlbmUuXG5cdCAqIFVzZSB0aGlzIG1ldGhvZCBpZiB5b3UndmUgY3JlYXRlZCBhIHN1YmNsYXNzIG9mIFNjZW5lLCBhbmQgeW91IHdhbnQgdG8gYWRkIGl0IGFzIHRoZSBtYWluIFNjZW5lLlxuXHQgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBvZiB0aGUgc2NlbmUgdG8gYWRkXG5cdCAqIEBwYXJhbSBpbml0IEFuIG9iamVjdCB0byBwYXNzIHRvIHRoZSBpbml0IGZ1bmN0aW9uIG9mIHRoZSBuZXcgc2NlbmVcblx0ICovXG5cdHB1YmxpYyBjaGFuZ2VUb1NjZW5lPFQgZXh0ZW5kcyBTY2VuZT4oY29uc3RyOiBuZXcgKC4uLmFyZ3M6IGFueSkgPT4gVCwgaW5pdD86IFJlY29yZDxzdHJpbmcsIGFueT4sIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0Y29uc29sZS5sb2coXCJDcmVhdGluZyB0aGUgbmV3IHNjZW5lIC0gY2hhbmdlIGlzIHBlbmRpbmcgdW50aWwgbmV4dCB1cGRhdGVcIik7XG5cdFx0dGhpcy5wZW5kaW5nU2NlbmUgPSBuZXcgY29uc3RyKHRoaXMudmlld3BvcnQsIHRoaXMsIHRoaXMucmVuZGVyaW5nTWFuYWdlciwgb3B0aW9ucyk7XG5cdFx0dGhpcy5wZW5kaW5nU2NlbmVJbml0ID0gaW5pdDtcblx0fVxuXG5cdHByb3RlY3RlZCBkb1NjZW5lQ2hhbmdlKCl7XG5cdFx0Y29uc29sZS5sb2coXCJQZXJmb3JtaW5nIHNjZW5lIGNoYW5nZVwiKTtcblx0XHR0aGlzLnZpZXdwb3J0LnNldENlbnRlcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCwgdGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkpO1xuXHRcdFxuXHRcdGlmKHRoaXMuY3VycmVudFNjZW5lKXtcblx0XHRcdGNvbnNvbGUubG9nKFwiVW5sb2FkaW5nIG9sZCBzY2VuZVwiKVxuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUudW5sb2FkU2NlbmUoKTtcblxuXHRcdFx0Y29uc29sZS5sb2coXCJEZXN0cm95aW5nIG9sZCBzY2VuZVwiKTtcblx0XHRcdHRoaXMuY3VycmVudFNjZW5lLmRlc3Ryb3koKTtcblx0XHR9XG5cblx0XHRjb25zb2xlLmxvZyhcIlVubG9hZGluZyBvbGQgcmVzb3VyY2VzLi4uXCIpO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyLnVubG9hZEFsbFJlc291cmNlcygpO1xuXG5cdFx0Ly8gTWFrZSB0aGUgcGVuZGluZyBzY2VuZSB0aGUgY3VycmVudCBvbmVcblx0XHR0aGlzLmN1cnJlbnRTY2VuZSA9IHRoaXMucGVuZGluZ1NjZW5lO1xuXG5cdFx0Ly8gTWFrZSB0aGUgcGVuZGluZyBzY2VuZSBudWxsXG5cdFx0dGhpcy5wZW5kaW5nU2NlbmUgPSBudWxsO1xuXG5cdFx0Ly8gSW5pdCB0aGUgc2NlbmVcblx0XHR0aGlzLmN1cnJlbnRTY2VuZS5pbml0U2NlbmUodGhpcy5wZW5kaW5nU2NlbmVJbml0KTtcblxuXHRcdC8vIEVucXVldWUgYWxsIHNjZW5lIGFzc2V0IGxvYWRzXG5cdFx0dGhpcy5jdXJyZW50U2NlbmUubG9hZFNjZW5lKCk7XG5cblx0XHQvLyBMb2FkIGFsbCBhc3NldHNcblx0XHRjb25zb2xlLmxvZyhcIlN0YXJ0aW5nIFNjZW5lIExvYWRcIik7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIubG9hZFJlc291cmNlc0Zyb21RdWV1ZSgoKSA9PiB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIlN0YXJ0aW5nIFNjZW5lXCIpO1xuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUuc3RhcnRTY2VuZSgpO1xuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUuc2V0UnVubmluZyh0cnVlKTtcblx0XHR9KTtcblxuXHRcdHRoaXMucmVuZGVyaW5nTWFuYWdlci5zZXRTY2VuZSh0aGlzLmN1cnJlbnRTY2VuZSk7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSURcblx0ICogQHJldHVybnMgQSBuZXcgSURcblx0ICovXG5cdHB1YmxpYyBnZW5lcmF0ZUlkKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMuaWRDb3VudGVyKys7XG5cdH1cblxuXHQvKipcblx0ICogUmVuZGVycyB0aGUgY3VycmVudCBTY2VuZVxuXHQgKi9cblx0cHVibGljIHJlbmRlcigpOiB2b2lkIHtcblx0XHRpZih0aGlzLmN1cnJlbnRTY2VuZSl7XG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS5yZW5kZXIoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlcyB0aGUgY3VycmVudCBTY2VuZVxuXHQgKiBAcGFyYW0gZGVsdGFUIFRoZSB0aW1lc3RlcCBvZiB0aGUgU2NlbmVcblx0ICovXG5cdHB1YmxpYyB1cGRhdGUoZGVsdGFUOiBudW1iZXIpe1xuXHRcdGlmKHRoaXMucGVuZGluZ1NjZW5lICE9PSBudWxsKXtcblx0XHRcdHRoaXMuZG9TY2VuZUNoYW5nZSgpO1xuXHRcdH1cblxuXHRcdGlmKHRoaXMuY3VycmVudFNjZW5lICYmIHRoaXMuY3VycmVudFNjZW5lLmlzUnVubmluZygpKXtcblx0XHRcdHRoaXMuY3VycmVudFNjZW5lLnVwZGF0ZShkZWx0YVQpO1xuXHRcdH1cblx0fVxufSIsImltcG9ydCBBcnJheVV0aWxzIGZyb20gXCIuLi9VdGlscy9BcnJheVV0aWxzXCI7XG5cbi8vIEBpZ25vcmVQYWdlXG5cbi8qKlxuICogVGhlIG9wdGlvbnMgdG8gZ2l2ZSBhIEByZWZlcmVuY2VbU2NlbmVdIGZvciBpbml0aWFsaXphdGlvblxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTY2VuZU9wdGlvbnMge1xuICAgIHBoeXNpY3M6IHtcbiAgICAgICAgZ3JvdXBzOiBBcnJheTxzdHJpbmc+LFxuICAgICAgICBjb2xsaXNpb25zOiBBcnJheTxBcnJheTxudW1iZXI+PjtcbiAgICB9XG5cbiAgICBzdGF0aWMgcGFyc2Uob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IFNjZW5lT3B0aW9uc3tcbiAgICAgICAgbGV0IHNPcHQgPSBuZXcgU2NlbmVPcHRpb25zKCk7XG5cbiAgICAgICAgaWYob3B0aW9ucy5waHlzaWNzID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgc09wdC5waHlzaWNzID0ge2dyb3VwczogdW5kZWZpbmVkLCBjb2xsaXNpb25zOiB1bmRlZmluZWR9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc09wdC5waHlzaWNzID0gb3B0aW9ucy5waHlzaWNzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNPcHQ7XG4gICAgfVxufSIsImltcG9ydCBWaWV3cG9ydCBmcm9tIFwiLi9WaWV3cG9ydFwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuXG4vKipcbiAqIEFuIGFic3RyYWN0IGludGVyZmFjZSBvZiBhIFNjZW5lR3JhcGguXG4gKiBFeHBvc2VzIG1ldGhvZHMgZm9yIHVzZSBieSBvdGhlciBjb2RlLCBidXQgbGVhdmVzIHRoZSBpbXBsZW1lbnRhdGlvbiB1cCB0byB0aGUgc3ViY2xhc3Nlcy5cbiAqIFRoZSBTY2VuZUdyYXBoIG1hbmFnZXMgdGhlIHBvc2l0aW9ucyBvZiBhbGwgR2FtZU5vZGVzLCBhbmQgY2FuIGVhc2lseSBwcnVuZSBhIHZpc2libGUgc2V0IGZvciByZW5kZXJpbmcuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFNjZW5lR3JhcGgge1xuXHQvKipcdEEgcmVmZXJlbmNlIHRvIHRoZSB2aWV3cG9ydCAqL1xuXHRwcm90ZWN0ZWQgdmlld3BvcnQ6IFZpZXdwb3J0O1xuXHQvKipcdEEgbWFwIG9mIENhbnZhc05vZGVzIGluIHRoaXMgU2NlbmVHcmFwaCAqL1xuXHRwcm90ZWN0ZWQgbm9kZU1hcDogQXJyYXk8Q2FudmFzTm9kZT47XG5cdC8qKiBBIGNvdW50ZXIgb2YgSURzIGZvciBub2RlcyBpbiB0aGlzIFNjZW5lR3JhcGggKi9cblx0cHJvdGVjdGVkIGlkQ291bnRlcjogbnVtYmVyO1xuXHQvKiogQSByZWZlcmVuY2UgdG8gdGhlIFNjZW5lIHRoaXMgU2NlbmVHcmFwaCBiZWxvbmdzIHRvICovXG5cdHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgU2NlbmVHcmFwaFxuXHQgKiBAcGFyYW0gdmlld3BvcnQgVGhlIHZpZXdwb3J0XG5cdCAqIEBwYXJhbSBzY2VuZSBUaGUgU2NlbmUgdGhpcyBTY2VuZUdyYXBoIGJlbG9uZ3MgdG9cblx0ICovXG4gICAgY29uc3RydWN0b3Iodmlld3BvcnQ6IFZpZXdwb3J0LCBzY2VuZTogU2NlbmUpe1xuXHRcdHRoaXMudmlld3BvcnQgPSB2aWV3cG9ydDtcblx0XHR0aGlzLnNjZW5lID0gc2NlbmU7XG5cdFx0dGhpcy5ub2RlTWFwID0gbmV3IEFycmF5KCk7XG5cdFx0dGhpcy5pZENvdW50ZXIgPSAwO1xuICAgIH1cblxuXHQvKipcblx0ICogQWRkIGEgbm9kZSB0byB0aGUgU2NlbmVHcmFwaFxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgQ2FudmFzTm9kZSB0byBhZGQgdG8gdGhlIFNjZW5lR3JhcGhcblx0ICogQHJldHVybnMgVGhlIFNjZW5lR3JhcGggSUQgb2YgdGhpcyBuZXdseSBhZGRlZCBDYW52YXNOb2RlXG5cdCAqL1xuICAgIGFkZE5vZGUobm9kZTogQ2FudmFzTm9kZSk6IG51bWJlciB7XG5cdFx0dGhpcy5ub2RlTWFwW25vZGUuaWRdID0gbm9kZTtcblx0XHR0aGlzLmFkZE5vZGVTcGVjaWZpYyhub2RlLCB0aGlzLmlkQ291bnRlcik7XG5cdFx0dGhpcy5pZENvdW50ZXIgKz0gMTtcblx0XHRyZXR1cm4gdGhpcy5pZENvdW50ZXIgLSAxO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBBbiBvdmVycmlkYWJsZSBtZXRob2QgdG8gYWRkIGEgQ2FudmFzTm9kZSB0byB0aGUgc3BlY2lmaWMgZGF0YSBzdHJ1Y3R1cmUgb2YgdGhlIFNjZW5lR3JhcGhcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gYWRkIHRvIHRoZSBkYXRhIHN0cnVjdHVyZVxuXHQgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBDYW52YXNOb2RlXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgYWRkTm9kZVNwZWNpZmljKG5vZGU6IENhbnZhc05vZGUsIGlkOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIGEgbm9kZSBmcm9tIHRoZSBTY2VuZUdyYXBoXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIHJlbW92ZVxuXHQgKi9cbiAgICByZW1vdmVOb2RlKG5vZGU6IENhbnZhc05vZGUpOiB2b2lkIHtcblx0XHQvLyBGaW5kIGFuZCByZW1vdmUgbm9kZSBpbiBPKG4pXG5cdFx0dGhpcy5ub2RlTWFwW25vZGUuaWRdID0gdW5kZWZpbmVkO1xuXHRcdHRoaXMucmVtb3ZlTm9kZVNwZWNpZmljKG5vZGUsIG5vZGUuaWQpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBUaGUgc3BlY2lmaWMgaW1wbGVtZW50YXRpb24gb2YgcmVtb3ZpbmcgYSBub2RlXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIHJlbW92ZVxuXHQgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBub2RlIHRvIHJlbW92ZVxuXHQgKi9cblx0cHJvdGVjdGVkIGFic3RyYWN0IHJlbW92ZU5vZGVTcGVjaWZpYyhub2RlOiBDYW52YXNOb2RlLCBpZDogbnVtYmVyKTogdm9pZDtcblxuXHQvKipcblx0ICogR2V0IGEgc3BlY2lmaWMgbm9kZSB1c2luZyBpdHMgaWRcblx0ICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgQ2FudmFzTm9kZSB0byByZXRyaWV2ZVxuXHQgKiBAcmV0dXJucyBUaGUgbm9kZSB3aXRoIHRoaXMgSURcblx0ICovXG5cdGdldE5vZGUoaWQ6IG51bWJlcik6IENhbnZhc05vZGUge1xuXHRcdHJldHVybiB0aGlzLm5vZGVNYXBbaWRdO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG5vZGVzIGF0IHNwZWNpZmljIGNvb3JkaW5hdGVzXG5cdCAqIEBwYXJhbSB2ZWNPclggVGhlIHgtY29vcmRpbmF0ZSBvZiB0aGUgcG9zaXRpb24sIG9yIHRoZSBjb29yZGluYXRlcyBpbiBhIFZlYzJcblx0ICogQHBhcmFtIHkgVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgcG9zaXRpb25cblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2Ygbm9kZXMgZm91bmQgYXQgdGhlIHBvc2l0aW9uIHByb3ZpZGVkXG5cdCAqL1xuICAgIGdldE5vZGVzQXQodmVjT3JYOiBWZWMyIHwgbnVtYmVyLCB5OiBudW1iZXIgPSBudWxsKTogQXJyYXk8Q2FudmFzTm9kZT4ge1xuXHRcdGlmKHZlY09yWCBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0cmV0dXJuIHRoaXMuZ2V0Tm9kZXNBdENvb3Jkcyh2ZWNPclgueCwgdmVjT3JYLnkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5nZXROb2Rlc0F0Q29vcmRzKHZlY09yWCwgeSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG5vZGVzIHRoYXQgb3ZlcmxhcCBhIHNwZWNpZmljIGJvdW5kYXJ5XG5cdCAqIEBwYXJhbSBib3VuZGFyeSBUaGUgcmVnaW9uIHRvIGNoZWNrXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IG9mIG5vZGVzIGZvdW5kIG92ZXJsYXBwaW5nIHRoZSBwcm92aWRlZCBib3VuZGFyeVxuXHQgKi9cblx0YWJzdHJhY3QgZ2V0Tm9kZXNJblJlZ2lvbihib3VuZGFyeTogQUFCQik6IEFycmF5PENhbnZhc05vZGU+O1xuXHRcblx0LyoqXG5cdCAqIFJldHVybnMgYWxsIG5vZGVzIGluIHRoZSBTY2VuZUdyYXBoXG5cdCAqIEByZXR1cm5zIEFuIEFycmF5IGNvbnRhaW5pbmcgYWxsIG5vZGVzIGluIHRoZSBTY2VuZUdyYXBoXG5cdCAqL1xuXHRnZXRBbGxOb2RlcygpOiBBcnJheTxDYW52YXNOb2RlPiB7XG5cdFx0bGV0IGFyciA9IG5ldyBBcnJheTxDYW52YXNOb2RlPigpO1xuXHRcdGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLm5vZGVNYXAubGVuZ3RoOyBpKyspe1xuXHRcdFx0aWYodGhpcy5ub2RlTWFwW2ldICE9PSB1bmRlZmluZWQpe1xuXHRcdFx0XHRhcnIucHVzaCh0aGlzLm5vZGVNYXBbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gYXJyO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBzcGVjaWZpYyBpbXBsZW1lbnRhdGlvbiBvZiBnZXR0aW5nIGEgbm9kZSBhdCBjZXJ0YWluIGNvb3JkaW5hdGVzXG5cdCAqIEBwYXJhbSB4IFRoZSB4LWNvb3JkaW5hdGVzIG9mIHRoZSBub2RlXG5cdCAqIEBwYXJhbSB5IFRoZSB5LWNvb3JkaW5hdGVzIG9mIHRoZSBub2RlXG5cdCAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCBnZXROb2Rlc0F0Q29vcmRzKHg6IG51bWJlciwgeTogbnVtYmVyKTogQXJyYXk8Q2FudmFzTm9kZT47XG5cblx0YWJzdHJhY3QgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZDtcblx0XG5cdGFic3RyYWN0IHJlbmRlcihjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHZpc2libGUgc2V0IG9mIENhbnZhc05vZGVzIGJhc2VkIG9uIHRoZSBAcmVmZXJlbmNlW1ZpZXdwb3J0XVxuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBjb250YWluaW5nIGFsbCB2aXNpYmxlIG5vZGVzIGluIHRoZSBTY2VuZUdyYXBoXG5cdCAqL1xuICAgIGFic3RyYWN0IGdldFZpc2libGVTZXQoKTogQXJyYXk8Q2FudmFzTm9kZT47XG59IiwiaW1wb3J0IFNjZW5lR3JhcGggZnJvbSBcIi4vU2NlbmVHcmFwaFwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBWaWV3cG9ydCBmcm9tIFwiLi9WaWV3cG9ydFwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IFN0YXRzIGZyb20gXCIuLi9EZWJ1Zy9TdGF0c1wiO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIGEgU2NlbmVHcmFwaCB0aGF0IHNpbXBseSBzdG9yZWQgQ2FudmFzTm9kZXMgaW4gYW4gYXJyYXkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lR3JhcGhBcnJheSBleHRlbmRzIFNjZW5lR3JhcGgge1xuICAgIC8qKiBUaGUgbGlzdCBvZiBDYW52YXNOb2RlcyBpbiB0aGlzIFNjZW5lR3JhcGggKi9cbiAgICBwcml2YXRlIG5vZGVMaXN0OiBBcnJheTxDYW52YXNOb2RlPjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgU2NlbmVHcmFwaEFycmF5XG4gICAgICogQHBhcmFtIHZpZXdwb3J0IFRoZSBWaWV3cG9ydFxuICAgICAqIEBwYXJhbSBzY2VuZSBUaGUgU2NlbmUgdGhpcyBTY2VuZUdyYXBoIGJlbG9uZ3MgdG9cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih2aWV3cG9ydDogVmlld3BvcnQsIHNjZW5lOiBTY2VuZSl7XG4gICAgICAgIHN1cGVyKHZpZXdwb3J0LCBzY2VuZSk7XG5cbiAgICAgICAgdGhpcy5ub2RlTGlzdCA9IG5ldyBBcnJheTxDYW52YXNOb2RlPigpO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCBhZGROb2RlU3BlY2lmaWMobm9kZTogQ2FudmFzTm9kZSwgaWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLm5vZGVMaXN0LnB1c2gobm9kZSk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHJlbW92ZU5vZGVTcGVjaWZpYyhub2RlOiBDYW52YXNOb2RlLCBpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGxldCBpbmRleCA9IHRoaXMubm9kZUxpc3QuaW5kZXhPZihub2RlKTtcbiAgICAgICAgaWYoaW5kZXggPiAtMSl7XG4gICAgICAgICAgICB0aGlzLm5vZGVMaXN0LnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBnZXROb2Rlc0F0Q29vcmRzKHg6IG51bWJlciwgeTogbnVtYmVyKTogQXJyYXk8Q2FudmFzTm9kZT4ge1xuICAgICAgICBsZXQgcmVzdWx0cyA9IFtdO1xuXG4gICAgICAgIGZvcihsZXQgbm9kZSBvZiB0aGlzLm5vZGVMaXN0KXtcbiAgICAgICAgICAgIGlmKG5vZGUuY29udGFpbnMoeCwgeSkpe1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGdldE5vZGVzSW5SZWdpb24oYm91bmRhcnk6IEFBQkIpOiBBcnJheTxDYW52YXNOb2RlPiB7XG4gICAgICAgIGxldCB0MCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgICAgICBsZXQgcmVzdWx0cyA9IFtdO1xuXG4gICAgICAgIGZvcihsZXQgbm9kZSBvZiB0aGlzLm5vZGVMaXN0KXtcbiAgICAgICAgICAgIGlmKGJvdW5kYXJ5Lm92ZXJsYXBzKG5vZGUuYm91bmRhcnkpKXtcbiAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2gobm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHQxID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIFN0YXRzLmxvZyhcInNncXVlcnlcIiwgKHQxLXQwKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGxldCB0MCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICAgICAgICBmb3IobGV0IG5vZGUgb2YgdGhpcy5ub2RlTGlzdCl7XG4gICAgICAgICAgICBpZighbm9kZS5nZXRMYXllcigpLmlzUGF1c2VkKCkpe1xuICAgICAgICAgICAgICAgIG5vZGUudXBkYXRlKGRlbHRhVCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHQxID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIFN0YXRzLmxvZyhcInNndXBkYXRlXCIsICh0MS10MCkpO1xuICAgIH1cblxuICAgIHJlbmRlcihjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk6IHZvaWQge31cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGdldFZpc2libGVTZXQoKTogQXJyYXk8Q2FudmFzTm9kZT4ge1xuICAgICAgICBsZXQgdmlzaWJsZVNldCA9IG5ldyBBcnJheTxDYW52YXNOb2RlPigpO1xuXG4gICAgICAgIGZvcihsZXQgbm9kZSBvZiB0aGlzLm5vZGVMaXN0KXtcbiAgICAgICAgICAgIGlmKCFub2RlLmdldExheWVyKCkuaXNIaWRkZW4oKSAmJiBub2RlLnZpc2libGUgJiYgdGhpcy52aWV3cG9ydC5pbmNsdWRlcyhub2RlKSl7XG4gICAgICAgICAgICAgICAgdmlzaWJsZVNldC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHZpc2libGVTZXQ7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IFF1ZXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvUXVldWVcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuLi9EYXRhVHlwZXMvU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vSW5wdXQvSW5wdXRcIjtcbmltcG9ydCBQYXJhbGxheExheWVyIGZyb20gXCIuLi9TY2VuZS9MYXllcnMvUGFyYWxsYXhMYXllclwiO1xuaW1wb3J0IFVJTGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9VSUxheWVyXCI7XG5cbi8qKlxuICogVGhlIHZpZXdwb3J0IG9mIHRoZSBnYW1lLiBDb3JyZXNwb25kcyB0byB0aGUgdmlzaWJsZSB3aW5kb3cgZGlzcGxheWVkIGluIHRoZSBicm93c2VyLlxuICogVGhlIHZpZXdwb3J0IGtlZXBzIHRyYWNrIG9mIGl0cyBwb3NpdGlvbiBpbiB0aGUgZ2FtZSB3b3JsZCwgYW5kIGNhbiBhY3QgYXMgYSBjYW1lcmEgdG8gZm9sbG93IG9iamVjdHMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZpZXdwb3J0IHtcbiAgICAvKiogVGhlIEFBQkIgdGhhdCBjb250YWlucyB0aGUgcG9zaXRpb24gYW5kIHNpemUgb2YgdGhlIHZpZXdwb3J0IHZpZXcgKi9cbiAgICBwcml2YXRlIHZpZXc6IEFBQkI7XG4gICAgLyoqIFRoZSBib3VuZGFyeSBmb3IgdGhlIHZpZXdwb3J0LiBUaGlzIHJlcHJlc2VudHMgdGhlIGxpbWl0cyB0byB3aGVyZSB0aGUgdmlld3BvcnQgY2FuIGdvICovXG4gICAgcHJpdmF0ZSBib3VuZGFyeTogQUFCQjtcbiAgICAvKiogVGhlIEdhbWVOb2RlIHRoZSBWaWV3cG9ydCBpcyBmb2xsb3dpbmcgKi9cbiAgICBwcml2YXRlIGZvbGxvd2luZzogR2FtZU5vZGU7XG4gICAgLyoqIFRoZSBwb3NpdGlvbiB0aGUgR2FtZU5vZGUgaXMgZm9jdXNpbmcgb24uIFRoaXMgaXMgb3ZlcnJpZGRlbiBpZiBcImZvbGxvd2luZ1wiIGlzIHNldC4gKi9cbiAgICBwcml2YXRlIGZvY3VzOiBWZWMyO1xuXG4gICAgLyoqIEEgcXVldWUgb2YgcHJldmlvdXMgcG9zaXRpb25zIG9mIHdoYXQgdGhpcyB2aWV3cG9ydCBpcyBmb2xsb3dpbmcuIFVzZWQgZm9yIHNtb290aGluZyB2aWV3cG9ydCBtb3ZlbWVudCAqL1xuICAgIHByaXZhdGUgbGFzdFBvc2l0aW9uczogUXVldWU8VmVjMj47XG5cbiAgICAvKiogVGhlIG51bWJlciBvZiBwcmV2aW91cyBwb3NpdGlvbnMgdGhpcyB2aWV3cG9ydCB0cmFja3MgKi9cbiAgICBwcml2YXRlIHNtb290aGluZ0ZhY3RvcjogbnVtYmVyO1xuXG4gICAgLyoqIEEgYm9vbGVhbiB0aGEgcmVwcmVzZW50cyB3aGV0aGVyIHRoZSBwbGF5ZXIgY2FuIHpvb20gYnkgc2Nyb2xsaW5nIHdpdGggdGhlIG1vdXNlIHdoZWVsICovXG4gICAgcHJpdmF0ZSBzY3JvbGxab29tRW5hYmxlZDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgYW1vdW50IHRoYXQgaXMgem9vbWVkIGluIG9yIG91dC4gKi9cbiAgICBwcml2YXRlIFpPT01fRkFDVE9SOiBudW1iZXIgPSAxLjI7XG5cbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIGNhbnZhcyAqL1xuICAgIHByaXZhdGUgY2FudmFzU2l6ZTogVmVjMjtcblxuICAgIGNvbnN0cnVjdG9yKGNhbnZhc1NpemU6IFZlYzIsIHpvb21MZXZlbDogbnVtYmVyKXtcbiAgICAgICAgdGhpcy52aWV3ID0gbmV3IEFBQkIoVmVjMi5aRVJPLCBWZWMyLlpFUk8pO1xuICAgICAgICB0aGlzLmJvdW5kYXJ5ID0gbmV3IEFBQkIoVmVjMi5aRVJPLCBWZWMyLlpFUk8pO1xuICAgICAgICB0aGlzLmxhc3RQb3NpdGlvbnMgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5zbW9vdGhpbmdGYWN0b3IgPSAxMDtcbiAgICAgICAgdGhpcy5zY3JvbGxab29tRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmNhbnZhc1NpemUgPSBWZWMyLlpFUk87XG4gICAgICAgIHRoaXMuZm9jdXMgPSBWZWMyLlpFUk87XG5cbiAgICAgICAgLy8gU2V0IHRoZSBzaXplIG9mIHRoZSBjYW52YXNcbiAgICAgICAgdGhpcy5zZXRDYW52YXNTaXplKGNhbnZhc1NpemUpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgc2l6ZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgICAgdGhpcy5zZXRTaXplKGNhbnZhc1NpemUpO1xuICAgICAgICB0aGlzLnNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgY2VudGVyIChhbmQgbWFrZSB0aGUgdmlld3BvcnQgc3RheSB0aGVyZSlcbiAgICAgICAgdGhpcy5zZXRDZW50ZXIodGhpcy52aWV3LmhhbGZTaXplLmNsb25lKCkpO1xuICAgICAgICB0aGlzLnNldEZvY3VzKHRoaXMudmlldy5oYWxmU2l6ZS5jbG9uZSgpKTtcbiAgICB9XG5cbiAgICAvKiogRW5hYmxlcyB0aGUgdmlld3BvcnQgdG8gem9vbSBpbiBhbmQgb3V0ICovXG4gICAgZW5hYmxlWm9vbSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY3JvbGxab29tRW5hYmxlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcG9zaXRpb24gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHJldHVybnMgVGhlIGNlbnRlciBvZiB0aGUgdmlld3BvcnQgYXMgYSBWZWMyXG4gICAgICovXG4gICAgZ2V0Q2VudGVyKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3LmNlbnRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbmV3IFZlYzIgd2l0aCB0aGUgb3JpZ2luIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEByZXR1cm5zIFRoZSB0b3AgbGVmdCBjb3JuZGVyIG9mIHRoZSBWaWVwb3J0IGFzIGEgVmVjMlxuICAgICAqL1xuICAgIGdldE9yaWdpbigpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMudmlldy5sZWZ0LCB0aGlzLnZpZXcudG9wKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByZWdpb24gdmlzaWJsZSB0byB0aGlzIHZpZXdwb3J0XG4gICAgICogQHJldHVybnMgVGhlIEFBQkIgY29udGFpbmluZyB0aGUgcmVnaW9uIHZpc2libGUgdG8gdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgZ2V0VmlldygpOiBBQUJCIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlldztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHBvc2l0aW9uIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB2ZWNPclggVGhlIG5ldyBwb3NpdGlvbiBvciB0aGUgeC1jb29yZGluYXRlIG9mIHRoZSBuZXcgcG9zaXRpb25cbiAgICAgKiBAcGFyYW0geSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBuZXcgcG9zaXRpb25cbiAgICAgKi9cbiAgICBzZXRDZW50ZXIodmVjT3JYOiBWZWMyIHwgbnVtYmVyLCB5OiBudW1iZXIgPSBudWxsKTogdm9pZCB7XG4gICAgICAgIGxldCBwb3M6IFZlYzI7XG5cdFx0aWYodmVjT3JYIGluc3RhbmNlb2YgVmVjMil7XG4gICAgICAgICAgICBwb3MgPSB2ZWNPclg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb3MgPSBuZXcgVmVjMih2ZWNPclgsIHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWV3LmNlbnRlciA9IHBvcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydCBhcyBhIFZlYzJcbiAgICAgKiBAcmV0dXJucyBUaGUgaGFsZi1zaXplIG9mIHRoZSB2aWV3cG9ydCBhcyBhIFZlYzJcbiAgICAgKi9cbiAgICBnZXRIYWxmU2l6ZSgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlldy5nZXRIYWxmU2l6ZSgpO1xuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB2ZWNPclggVGhlIG5ldyB3aWR0aCBvZiB0aGUgdmlld3BvcnQgb3IgdGhlIG5ldyBzaXplIGFzIGEgVmVjMlxuICAgICAqIEBwYXJhbSB5IFRoZSBuZXcgaGVpZ2h0IG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHNldFNpemUodmVjT3JYOiBWZWMyIHwgbnVtYmVyLCB5OiBudW1iZXIgPSBudWxsKTogdm9pZCB7XG5cdFx0aWYodmVjT3JYIGluc3RhbmNlb2YgVmVjMil7XG5cdFx0XHR0aGlzLnZpZXcuc2V0SGFsZlNpemUodmVjT3JYLnNjYWxlZCgxLzIpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy52aWV3LnNldEhhbGZTaXplKG5ldyBWZWMyKHZlY09yWC8yLCB5LzIpKTtcblx0XHR9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgaGFsZi1zaXplIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB2ZWNPclggVGhlIG5ldyBoYWxmLXdpZHRoIG9mIHRoZSB2aWV3cG9ydCBvciB0aGUgbmV3IGhhbGYtc2l6ZSBhcyBhIFZlYzJcbiAgICAgKiBAcGFyYW0geSBUaGUgbmV3IGhlaWdodCBvZiB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBzZXRIYWxmU2l6ZSh2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiB2b2lkIHtcblx0XHRpZih2ZWNPclggaW5zdGFuY2VvZiBWZWMyKXtcblx0XHRcdHRoaXMudmlldy5zZXRIYWxmU2l6ZSh2ZWNPclguY2xvbmUoKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMudmlldy5zZXRIYWxmU2l6ZShuZXcgVmVjMih2ZWNPclgsIHkpKTtcblx0XHR9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgdmlld3BvcnQgd2l0aCB0aGUgc2l6ZSBvZiB0aGUgY3VycmVudCBDYW52YXNcbiAgICAgKiBAcGFyYW0gdmVjT3JYIFRoZSB3aWR0aCBvZiB0aGUgY2FudmFzLCBvciB0aGUgY2FudmFzIHNpemUgYXMgYSBWZWMyXG4gICAgICogQHBhcmFtIHkgVGhlIGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgICovXG4gICAgc2V0Q2FudmFzU2l6ZSh2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiB2b2lkIHtcblx0XHRpZih2ZWNPclggaW5zdGFuY2VvZiBWZWMyKXtcblx0XHRcdHRoaXMuY2FudmFzU2l6ZSA9IHZlY09yWC5jbG9uZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmNhbnZhc1NpemUgPSBuZXcgVmVjMih2ZWNPclgsIHkpO1xuXHRcdH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB6b29tIFRoZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgc2V0Wm9vbUxldmVsKHpvb206IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnZpZXcuaGFsZlNpemUuY29weSh0aGlzLmNhbnZhc1NpemUuc2NhbGVkKDEvem9vbS8yKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcmV0dXJucyBUaGUgem9vbSBsZXZlbFxuICAgICAqL1xuICAgIGdldFpvb21MZXZlbCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXNTaXplLngvdGhpcy52aWV3Lmh3LzJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzbW9vdGhpbmcgZmFjdG9yIGZvciB0aGUgdmlld3BvcnQgbW92ZW1lbnQuXG4gICAgICogQHBhcmFtIHNtb290aGluZ0ZhY3RvciBUaGUgc21vb3RoaW5nIGZhY3RvciBmb3IgdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgc2V0U21vb3RoaW5nRmFjdG9yKHNtb290aGluZ0ZhY3RvcjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGlmKHNtb290aGluZ0ZhY3RvciA8IDEpIHNtb290aGluZ0ZhY3RvciA9IDE7XG4gICAgICAgIHRoaXMuc21vb3RoaW5nRmFjdG9yID0gc21vb3RoaW5nRmFjdG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSB2aWV3cG9ydCB0byBmb2N1cyBvbiBhIHBvaW50LiBPdmVyaWRkZW4gYnkgXCJmb2xsb3dpbmdcIi5cbiAgICAgKiBAcGFyYW0gZm9jdXMgVGhlIHBvaW50IHRoZSAgdmlld3BvcnQgc2hvdWxkIGZvY3VzIG9uXG4gICAgICovXG4gICAgc2V0Rm9jdXMoZm9jdXM6IFZlYzIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb2N1cy5jb3B5KGZvY3VzKTtcbiAgICB9XG4gICAgXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSBDYW52YXNOb2RlIGlzIGluc2lkZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byBjaGVja1xuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIG5vZGUgaXMgY3VycmVudGx5IHZpc2libGUgaW4gdGhlIHZpZXdwb3J0LCBmYWxzZSBpZiBub3RcbiAgICAgKi9cbiAgICBpbmNsdWRlcyhub2RlOiBDYW52YXNOb2RlKTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBwYXJhbGxheCA9IG5vZGUuZ2V0TGF5ZXIoKSBpbnN0YW5jZW9mIFBhcmFsbGF4TGF5ZXIgfHwgbm9kZS5nZXRMYXllcigpIGluc3RhbmNlb2YgVUlMYXllciA/ICg8UGFyYWxsYXhMYXllcj5ub2RlLmdldExheWVyKCkpLnBhcmFsbGF4IDogbmV3IFZlYzIoMSwgMSk7XG4gICAgICAgIGxldCBjZW50ZXIgPSB0aGlzLnZpZXcuY2VudGVyLmNsb25lKCk7XG4gICAgICAgIHRoaXMudmlldy5jZW50ZXIubXVsdChwYXJhbGxheCk7XG4gICAgICAgIGxldCBvdmVybGFwcyA9IHRoaXMudmlldy5vdmVybGFwcyhub2RlLmJvdW5kYXJ5KTtcbiAgICAgICAgdGhpcy52aWV3LmNlbnRlciA9IGNlbnRlclxuICAgICAgICByZXR1cm4gb3ZlcmxhcHM7XG4gICAgfVxuXG5cdC8vIFRPRE86IFB1dCBzb21lIGVycm9yIGhhbmRsaW5nIG9uIHRoaXMgZm9yIHRyeWluZyB0byBtYWtlIHRoZSBib3VuZHMgdG9vIHNtYWxsIGZvciB0aGUgdmlld3BvcnRcbiAgICAvLyBUT0RPOiBUaGlzIHNob3VsZCBwcm9iYWJseSBiZSBkb25lIGF1dG9tYXRpY2FsbHksIG9yIHNob3VsZCBjb25zaWRlciB0aGUgYXNwZWN0IHJhdGlvIG9yIHNvbWV0aGluZ1xuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGJvdW5kcyBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gbG93ZXJYIFRoZSBsZWZ0IGVkZ2Ugb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIGxvd2VyWSBUaGUgdG9wIGVkZ2Ugb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHVwcGVyWCBUaGUgcmlnaHQgZWRnZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gdXBwZXJZIFRoZSBib3R0b20gZWRnZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBzZXRCb3VuZHMobG93ZXJYOiBudW1iZXIsIGxvd2VyWTogbnVtYmVyLCB1cHBlclg6IG51bWJlciwgdXBwZXJZOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGh3aWR0aCA9ICh1cHBlclggLSBsb3dlclgpLzI7XG4gICAgICAgIGxldCBoaGVpZ2h0ID0gKHVwcGVyWSAtIGxvd2VyWSkvMjtcbiAgICAgICAgbGV0IHggPSBsb3dlclggKyBod2lkdGg7XG4gICAgICAgIGxldCB5ID0gbG93ZXJZICsgaGhlaWdodDtcbiAgICAgICAgdGhpcy5ib3VuZGFyeS5jZW50ZXIuc2V0KHgsIHkpO1xuICAgICAgICB0aGlzLmJvdW5kYXJ5LmhhbGZTaXplLnNldChod2lkdGgsIGhoZWlnaHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2UgdGhlIHZpZXdwb3J0IGZvbGxvdyB0aGUgc3BlY2lmaWVkIEdhbWVOb2RlXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIEdhbWVOb2RlIHRvIGZvbGxvd1xuICAgICAqL1xuICAgIGZvbGxvdyhub2RlOiBHYW1lTm9kZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmZvbGxvd2luZyA9IG5vZGU7XG4gICAgfVxuXG4gICAgdXBkYXRlVmlldygpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy5sYXN0UG9zaXRpb25zLmdldFNpemUoKSA+IHRoaXMuc21vb3RoaW5nRmFjdG9yKXtcbiAgICAgICAgICAgIHRoaXMubGFzdFBvc2l0aW9ucy5kZXF1ZXVlKCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIEdldCB0aGUgYXZlcmFnZSBvZiB0aGUgbGFzdCAxMCBwb3NpdGlvbnNcbiAgICAgICAgbGV0IHBvcyA9IFZlYzIuWkVSTztcbiAgICAgICAgdGhpcy5sYXN0UG9zaXRpb25zLmZvckVhY2gocG9zaXRpb24gPT4gcG9zLmFkZChwb3NpdGlvbikpO1xuICAgICAgICBwb3Muc2NhbGUoMS90aGlzLmxhc3RQb3NpdGlvbnMuZ2V0U2l6ZSgpKTtcblxuICAgICAgICAvLyBTZXQgdGhpcyBwb3NpdGlvbiBlaXRoZXIgdG8gdGhlIG9iamVjdCBvciB0byBpdHMgYm91bmRzXG4gICAgICAgIHBvcy54ID0gTWF0aFV0aWxzLmNsYW1wKHBvcy54LCB0aGlzLmJvdW5kYXJ5LmxlZnQgKyB0aGlzLnZpZXcuaHcsIHRoaXMuYm91bmRhcnkucmlnaHQgLSB0aGlzLnZpZXcuaHcpO1xuICAgICAgICBwb3MueSA9IE1hdGhVdGlscy5jbGFtcChwb3MueSwgdGhpcy5ib3VuZGFyeS50b3AgKyB0aGlzLnZpZXcuaGgsIHRoaXMuYm91bmRhcnkuYm90dG9tIC0gdGhpcy52aWV3LmhoKTtcblxuICAgICAgICAvLyBBc3N1cmUgdGhlcmUgYXJlIG5vIGxpbmVzIGluIHRoZSB0aWxlbWFwXG4gICAgICAgIHBvcy54ID0gTWF0aC5mbG9vcihwb3MueCk7XG4gICAgICAgIHBvcy55ID0gTWF0aC5mbG9vcihwb3MueSk7XG4gICAgICAgIFxuICAgICAgICB0aGlzLnZpZXcuY2VudGVyLmNvcHkocG9zKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gSWYgem9vbSBpcyBlbmFibGVkXG4gICAgICAgIGlmKHRoaXMuc2Nyb2xsWm9vbUVuYWJsZWQpe1xuICAgICAgICAgICAgaWYoSW5wdXQuZGlkSnVzdFNjcm9sbCgpKXtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudFNpemUgPSB0aGlzLnZpZXcuZ2V0SGFsZlNpemUoKS5jbG9uZSgpO1xuICAgICAgICAgICAgICAgIGlmKElucHV0LmdldFNjcm9sbERpcmVjdGlvbigpIDwgMCl7XG4gICAgICAgICAgICAgICAgICAgIC8vIFpvb20gaW5cbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNpemUuc2NhbGUoMS90aGlzLlpPT01fRkFDVE9SKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBab29tIG91dFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2l6ZS5zY2FsZSh0aGlzLlpPT01fRkFDVE9SKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihjdXJyZW50U2l6ZS54ID4gdGhpcy5ib3VuZGFyeS5odyl7XG4gICAgICAgICAgICAgICAgICAgIGxldCBmYWN0b3IgPSB0aGlzLmJvdW5kYXJ5Lmh3L2N1cnJlbnRTaXplLng7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnggPSB0aGlzLmJvdW5kYXJ5Lmh3O1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2l6ZS55ICo9IGZhY3RvcjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihjdXJyZW50U2l6ZS55ID4gdGhpcy5ib3VuZGFyeS5oaCl7XG4gICAgICAgICAgICAgICAgICAgIGxldCBmYWN0b3IgPSB0aGlzLmJvdW5kYXJ5LmhoL2N1cnJlbnRTaXplLnk7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnkgPSB0aGlzLmJvdW5kYXJ5LmhoO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2l6ZS54ICo9IGZhY3RvcjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZpZXcuc2V0SGFsZlNpemUoY3VycmVudFNpemUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdmlld3BvcnQgaXMgZm9sbG93aW5nIGFuIG9iamVjdFxuICAgICAgICBpZih0aGlzLmZvbGxvd2luZyl7XG4gICAgICAgICAgICAvLyBVcGRhdGUgb3VyIGxpc3Qgb2YgcHJldmlvdXMgcG9zaXRpb25zXG4gICAgICAgICAgICB0aGlzLmxhc3RQb3NpdGlvbnMuZW5xdWV1ZSh0aGlzLmZvbGxvd2luZy5wb3NpdGlvbi5jbG9uZSgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubGFzdFBvc2l0aW9ucy5lbnF1ZXVlKHRoaXMuZm9jdXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVWaWV3KCk7XG4gICAgfVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBSZWNlaXZlciBmcm9tIFwiLi4vRXZlbnRzL1JlY2VpdmVyXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5cbi8qKlxuICogTWFuYWdlcyBhbnkgc291bmRzIG9yIG11c2ljIG5lZWRlZCBmb3IgdGhlIGdhbWUuXG4gKiBUaHJvdWdoIHRoZSBFdmVudFF1ZXVlLCBleHBvc2VzIGludGVyZmFjZSB0byBwbGF5IHNvdW5kcyBzbyBHYW1lTm9kZXMgY2FuIGFjdGl2YXRlIHNvdW5kcyB3aXRob3V0XG4gKiBuZWVkaW5nIGRpcmVjdCByZWZlcmVuY2VzIHRvIHRoZSBhdWRpbyBzeXN0ZW1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQXVkaW9NYW5hZ2VyIHtcbiAgICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogQXVkaW9NYW5hZ2VyO1xuXG4gICAgLyoqIFRoZSBldmVudCByZWNlaXZlciBvZiB0aGlzIEF1ZGlvTWFuYWdlciAqL1xuICAgIHByaXZhdGUgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuXG4gICAgLyoqIEEgTWFwIG9mIHRoZSBuYW1lcyBvZiBjdXJyZW50bHkgcGxheWluZyAob3IgcGF1c2VkKSBzb3VuZHMgdG8gdGhlaXIgQXVkaW9CdWZmZXJzICovXG4gICAgcHJpdmF0ZSBjdXJyZW50U291bmRzOiBNYXA8QXVkaW9CdWZmZXJTb3VyY2VOb2RlPjtcblxuICAgIHByaXZhdGUgYXVkaW9DdHg6IEF1ZGlvQ29udGV4dDtcblxuICAgIHByaXZhdGUgZ2Fpbk5vZGVzOiBBcnJheTxHYWluTm9kZT47XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMuaW5pdEF1ZGlvKCk7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIgPSBuZXcgUmVjZWl2ZXIoKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoW1xuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELFxuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELFxuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5QTEFZX01VU0lDLFxuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5QTEFZX1NGWCxcbiAgICAgICAgICAgIEdhbWVFdmVudFR5cGUuTVVURV9DSEFOTkVMLFxuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5VTk1VVEVfQ0hBTk5FTFxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5jdXJyZW50U291bmRzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMuZ2Fpbk5vZGVzID0gbmV3IEFycmF5PEdhaW5Ob2RlPihNQVhfQVVESU9fQ0hBTk5FTFMpO1xuICAgICAgICB0aGlzLmluaXRHYWluTm9kZXMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGluc3RhbmNlIG9mIHRoZSBBdWRpb01hbmFnZXIgY2xhc3Mgb3IgY3JlYXRlIGEgbmV3IG9uZSBpZiBub25lIGV4aXN0c1xuICAgICAqIEByZXR1cm5zIFRoZSBBdWRpb01hbmFnZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIGdldEluc3RhbmNlKCk6IEF1ZGlvTWFuYWdlciB7XG4gICAgICAgIGlmKCF0aGlzLmluc3RhbmNlKXtcbiAgICAgICAgICAgIHRoaXMuaW5zdGFuY2UgPSBuZXcgQXVkaW9NYW5hZ2VyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIHdlYkF1ZGlvIGNvbnRleHRcbiAgICAgKi9cbiAgICBwcml2YXRlIGluaXRBdWRpbygpOiB2b2lkIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdpbmRvdy5BdWRpb0NvbnRleHQgPSB3aW5kb3cuQXVkaW9Db250ZXh0Oy8vIHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7IFxuICAgICAgICAgICAgdGhpcy5hdWRpb0N0eCA9IG5ldyBBdWRpb0NvbnRleHQoKTsgXG4gICAgICAgICAgICBjb25zb2xlLmxvZygnV2ViIEF1ZGlvIEFQSSBzdWNjZXNzZnVsbHkgbG9hZGVkJyk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdXZWIgQXVkaW8gQVBJIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBicm93c2VyJyk7IFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0R2Fpbk5vZGVzKCk6IHZvaWQge1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgTUFYX0FVRElPX0NIQU5ORUxTOyBpKyspe1xuICAgICAgICAgICAgdGhpcy5nYWluTm9kZXNbaV0gPSB0aGlzLmF1ZGlvQ3R4LmNyZWF0ZUdhaW4oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgYXVkaW8gY29udGV4dFxuICAgICAqIEByZXR1cm5zIFRoZSBBdWRpb0NvbnRleHRcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0QXVkaW9Db250ZXh0KCk6IEF1ZGlvQ29udGV4dCB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1ZGlvQ3R4O1xuICAgIH1cblxuICAgIC8qXG4gICAgICAgIEFjY29yZGluZyB0byB0aGUgTUROLCBjcmVhdGUgYSBuZXcgc291bmQgZm9yIGV2ZXJ5IGNhbGw6XG5cbiAgICAgICAgQW4gQXVkaW9CdWZmZXJTb3VyY2VOb2RlIGNhbiBvbmx5IGJlIHBsYXllZCBvbmNlOyBhZnRlciBlYWNoIGNhbGwgdG8gc3RhcnQoKSwgeW91IGhhdmUgdG8gY3JlYXRlIGEgbmV3IG5vZGVcbiAgICAgICAgaWYgeW91IHdhbnQgdG8gcGxheSB0aGUgc2FtZSBzb3VuZCBhZ2Fpbi4gRm9ydHVuYXRlbHksIHRoZXNlIG5vZGVzIGFyZSB2ZXJ5IGluZXhwZW5zaXZlIHRvIGNyZWF0ZSwgYW5kIHRoZVxuICAgICAgICBhY3R1YWwgQXVkaW9CdWZmZXJzIGNhbiBiZSByZXVzZWQgZm9yIG11bHRpcGxlIHBsYXlzIG9mIHRoZSBzb3VuZC4gSW5kZWVkLCB5b3UgY2FuIHVzZSB0aGVzZSBub2RlcyBpbiBhXG4gICAgICAgIFwiZmlyZSBhbmQgZm9yZ2V0XCIgbWFubmVyOiBjcmVhdGUgdGhlIG5vZGUsIGNhbGwgc3RhcnQoKSB0byBiZWdpbiBwbGF5aW5nIHRoZSBzb3VuZCwgYW5kIGRvbid0IGV2ZW4gYm90aGVyIHRvXG4gICAgICAgIGhvbGQgYSByZWZlcmVuY2UgdG8gaXQuIEl0IHdpbGwgYXV0b21hdGljYWxseSBiZSBnYXJiYWdlLWNvbGxlY3RlZCBhdCBhbiBhcHByb3ByaWF0ZSB0aW1lLCB3aGljaCB3b24ndCBiZVxuICAgICAgICB1bnRpbCBzb21ldGltZSBhZnRlciB0aGUgc291bmQgaGFzIGZpbmlzaGVkIHBsYXlpbmcuXG4gICAgKi9cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHNvdW5kIGZyb20gdGhlIGtleSBvZiBhIGxvYWRlZCBhdWRpbyBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBsb2FkZWQgYXVkaW8gZmlsZSB0byBjcmVhdGUgYSBuZXcgc291bmQgZm9yXG4gICAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgQXVkaW9CdWZmZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY3JlYXRlU291bmQoa2V5OiBzdHJpbmcsIGhvbGRSZWZlcmVuY2U6IGJvb2xlYW4sIGNoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGUsIG9wdGlvbnM6IE1hcDxhbnk+KTogQXVkaW9CdWZmZXJTb3VyY2VOb2RlIHtcbiAgICAgICAgLy8gR2V0IGF1ZGlvIGJ1ZmZlclxuICAgICAgICBsZXQgYnVmZmVyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCkuZ2V0QXVkaW8oa2V5KTtcblxuICAgICAgICAvLyBDcmVhdGUgYSBzb3VuZCBzb3VyY2VcbiAgICAgICAgdmFyIHNvdXJjZSA9IHRoaXMuYXVkaW9DdHguY3JlYXRlQnVmZmVyU291cmNlKCk7IFxuICAgICAgXG4gICAgICAgIC8vIFRlbGwgdGhlIHNvdXJjZSB3aGljaCBzb3VuZCB0byBwbGF5XG4gICAgICAgIHNvdXJjZS5idWZmZXIgPSBidWZmZXI7ICAgICAgICAgICAgICAgXG4gICAgICBcbiAgICAgICAgLy8gQWRkIGFueSBhZGRpdGlvbmFsIG5vZGVzXG4gICAgICAgIGNvbnN0IG5vZGVzOiBBcnJheTxBdWRpb05vZGU+ID0gW3NvdXJjZV07XG5cbiAgICAgICAgLy8gRG8gYW55IGFkZGl0aW9uYWwgbm9kZXMgaGVyZT9cbiAgICAgICAgLy8gT2YgY291cnNlLCB0aGVyZSBhcmVuJ3QgYW55IHN1cHBvcnRlZCB5ZXQuLi5cblxuICAgICAgICAvLyBBZGQgdGhlIGdhaW4gbm9kZSBmb3IgdGhpcyBjaGFubmVsXG4gICAgICAgIG5vZGVzLnB1c2godGhpcy5nYWluTm9kZXNbY2hhbm5lbF0pO1xuXG4gICAgICAgIC8vIENvbm5lY3QgYW55IG5vZGVzIGFsb25nIHRoZSBwYXRoXG4gICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICBub2Rlc1tpLTFdLmNvbm5lY3Qobm9kZXNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29ubmVjdCB0aGUgc291cmNlIHRvIHRoZSBjb250ZXh0J3MgZGVzdGluYXRpb25cbiAgICAgICAgbm9kZXNbbm9kZXMubGVuZ3RoIC0gMV0uY29ubmVjdCh0aGlzLmF1ZGlvQ3R4LmRlc3RpbmF0aW9uKTtcbiAgICAgICAgXG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheSB0aGUgc291bmQgc3BlY2lmaWVkIGJ5IHRoZSBrZXlcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHNvdW5kIHRvIHBsYXlcbiAgICAgKiBAcGFyYW0gbG9vcCBBIGJvb2xlYW4gZm9yIHdoZXRoZXIgb3Igbm90IHRvIGxvb3AgdGhlIHNvdW5kXG4gICAgICogQHBhcmFtIGhvbGRSZWZlcmVuY2UgQSBib29sZWFuIGZvciB3aGV0aGVyIG9yIG5vdCB3ZSB3YW50IHRvIGhvbGQgb24gdG8gYSByZWZlcmVuY2Ugb2YgdGhlIGF1ZGlvIG5vZGUuIFRoaXMgaXMgZ29vZCBmb3IgcGxheWluZyBtdXNpYyBvbiBhIGxvb3AgdGhhdCB3aWxsIGV2ZW50dWFsbHkgbmVlZCB0byBiZSBzdG9wcGVkLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBwbGF5U291bmQoa2V5OiBzdHJpbmcsIGxvb3A6IGJvb2xlYW4sIGhvbGRSZWZlcmVuY2U6IGJvb2xlYW4sIGNoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGUsIG9wdGlvbnM6IE1hcDxhbnk+KTogdm9pZCB7XG4gICAgICAgIGxldCBzb3VuZCA9IHRoaXMuY3JlYXRlU291bmQoa2V5LCBob2xkUmVmZXJlbmNlLCBjaGFubmVsLCBvcHRpb25zKTtcblxuICAgICAgICBpZihsb29wKXtcbiAgICAgICAgICAgIHNvdW5kLmxvb3AgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIGEgcmVmZXJlbmNlIG9mIHRoZSBuZXcgc291bmQgdG8gYSBtYXAuIFRoaXMgd2lsbCBhbGxvdyB1cyB0byBzdG9wIGEgbG9vcGluZyBvciBsb25nIHNvdW5kIGF0IGEgbGF0ZXIgdGltZVxuICAgICAgICBpZihob2xkUmVmZXJlbmNlKXtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFNvdW5kcy5hZGQoa2V5LCBzb3VuZCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHNvdW5kLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RvcCB0aGUgc291bmQgc3BlY2lmaWVkIGJ5IHRoZSBrZXlcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc3RvcFNvdW5kKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGxldCBzb3VuZCA9IHRoaXMuY3VycmVudFNvdW5kcy5nZXQoa2V5KTtcbiAgICAgICAgaWYoc291bmQpe1xuICAgICAgICAgICAgc291bmQuc3RvcCgpO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50U291bmRzLmRlbGV0ZShrZXkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIG11dGVDaGFubmVsKGNoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGUpe1xuICAgICAgICB0aGlzLmdhaW5Ob2Rlc1tjaGFubmVsXS5nYWluLnNldFZhbHVlQXRUaW1lKDAsIHRoaXMuYXVkaW9DdHguY3VycmVudFRpbWUpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCB1bm11dGVDaGFubmVsKGNoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGUpe1xuICAgICAgICB0aGlzLmdhaW5Ob2Rlc1tjaGFubmVsXS5nYWluLnNldFZhbHVlQXRUaW1lKDEsIHRoaXMuYXVkaW9DdHguY3VycmVudFRpbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZvbHVtZSBvZiBhIGNoYW5uZWwgdXNpbmcgdGhlIEdhaW5Ob2RlIGZvciB0aGF0IGNoYW5uZWwuIEZvciBtb3JlXG4gICAgICogaW5mb3JtYXRpb24gb24gR2Fpbk5vZGVzLCBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0dhaW5Ob2RlXG4gICAgICogQHBhcmFtIGNoYW5uZWwgVGhlIGF1ZGlvIGNoYW5uZWwgdG8gc2V0IHRoZSB2b2x1bWUgZm9yXG4gICAgICogQHBhcmFtIHZvbHVtZSBUaGUgdm9sdW1lIG9mIHRoZSBjaGFubmVsLiAwIGlzIG11dGVkLiBWYWx1ZXMgYmVsb3cgemVybyB3aWxsIGJlIHNldCB0byB6ZXJvLlxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRWb2x1bWUoY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSwgdm9sdW1lOiBudW1iZXIpe1xuICAgICAgICBpZih2b2x1bWUgPCAwKXtcbiAgICAgICAgICAgIHZvbHVtZSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBhbSA9IEF1ZGlvTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgICAgICBhbS5nYWluTm9kZXNbY2hhbm5lbF0uZ2Fpbi5zZXRWYWx1ZUF0VGltZSh2b2x1bWUsIGFtLmF1ZGlvQ3R4LmN1cnJlbnRUaW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBHYWluTm9kZSBmb3IgdGhpcyBjaGFubmVsLlxuICAgICAqIExlYXJuIG1vcmUgYWJvdXQgR2Fpbk5vZGVzIGhlcmUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0dhaW5Ob2RlXG4gICAgICogRE9OJ1QgVVNFIFRISVMgVU5MRVNTIFlPVSBLTk9XIFdIQVQgWU9VJ1JFIERPSU5HXG4gICAgICogQHBhcmFtIGNoYW5uZWwgVGhlIGNoYW5uZWxcbiAgICAgKiBAcmV0dXJucyBUaGUgR2Fpbk5vZGUgZm9yIHRoZSBzcGVjaWZpZWQgY2hhbm5lbFxuICAgICAqL1xuICAgIGdldENoYW5uZWxHYWluTm9kZShjaGFubmVsOiBBdWRpb0NoYW5uZWxUeXBlKXtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2Fpbk5vZGVzW2NoYW5uZWxdO1xuICAgIH1cbiAgICBcbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gUGxheSBlYWNoIGF1ZGlvIGNsaXAgcmVxdWVzdGVkXG4gICAgICAgIC8vIFRPRE8gLSBBZGQgbG9naWMgdG8gbWVyZ2Ugc291bmRzIGlmIHRoZXJlIGFyZSBtdWx0aXBsZSBvZiB0aGUgc2FtZSBrZXlcbiAgICAgICAgd2hpbGUodGhpcy5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSl7XG4gICAgICAgICAgICBsZXQgZXZlbnQgPSB0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpO1xuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5EIHx8IGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuUExBWV9NVVNJQyB8fCBldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlBMQVlfU0ZYKXtcbiAgICAgICAgICAgICAgICBsZXQgc291bmRLZXkgPSBldmVudC5kYXRhLmdldChcImtleVwiKTtcbiAgICAgICAgICAgICAgICBsZXQgbG9vcCA9IGV2ZW50LmRhdGEuZ2V0KFwibG9vcFwiKTtcbiAgICAgICAgICAgICAgICBsZXQgaG9sZFJlZmVyZW5jZSA9IGV2ZW50LmRhdGEuZ2V0KFwiaG9sZFJlZmVyZW5jZVwiKTtcblxuICAgICAgICAgICAgICAgIGxldCBjaGFubmVsID0gQXVkaW9DaGFubmVsVHlwZS5ERUZBVUxUO1xuXG4gICAgICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5QTEFZX01VU0lDKXtcbiAgICAgICAgICAgICAgICAgICAgY2hhbm5lbCA9IEF1ZGlvQ2hhbm5lbFR5cGUuTVVTSUM7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKEdhbWVFdmVudFR5cGUuUExBWV9TRlgpe1xuICAgICAgICAgICAgICAgICAgICBjaGFubmVsID0gQXVkaW9DaGFubmVsVHlwZS5TRlg7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGV2ZW50LmRhdGEuaGFzKFwiY2hhbm5lbFwiKSl7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5uZWwgPSBldmVudC5kYXRhLmdldChcImNoYW5uZWxcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5wbGF5U291bmQoc291bmRLZXksIGxvb3AsIGhvbGRSZWZlcmVuY2UsIGNoYW5uZWwsIGV2ZW50LmRhdGEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlNUT1BfU09VTkQpe1xuICAgICAgICAgICAgICAgIGxldCBzb3VuZEtleSA9IGV2ZW50LmRhdGEuZ2V0KFwia2V5XCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcFNvdW5kKHNvdW5kS2V5KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5NVVRFX0NIQU5ORUwpe1xuICAgICAgICAgICAgICAgIHRoaXMubXV0ZUNoYW5uZWwoZXZlbnQuZGF0YS5nZXQoXCJjaGFubmVsXCIpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5VTk1VVEVfQ0hBTk5FTCl7XG4gICAgICAgICAgICAgICAgdGhpcy51bm11dGVDaGFubmVsKGV2ZW50LmRhdGEuZ2V0KFwiY2hhbm5lbFwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBlbnVtIEF1ZGlvQ2hhbm5lbFR5cGUge1xuICAgIERFRkFVTFQgPSAwLFxuICAgIFNGWCA9IDEsXG4gICAgTVVTSUMgPSAyLFxuICAgIENVU1RPTV8xID0gMyxcbiAgICBDVVNUT01fMiA9IDQsXG4gICAgQ1VTVE9NXzMgPSA1LFxuICAgIENVU1RPTV80ID0gNixcbiAgICBDVVNUT01fNSA9IDcsXG4gICAgQ1VTVE9NXzYgPSA4LFxuICAgIENVU1RPTV83ID0gOSxcbiAgICBDVVNUT01fOCA9IDEwLFxuICAgIENVU1RPTV85ID0gMTEsXG59XG5cbmV4cG9ydCBjb25zdCBNQVhfQVVESU9fQ0hBTk5FTFMgPSAxMjsiLCJpbXBvcnQgeyBHYW1lU3RhdGUgfSBmcm9tIFwiLi4vLi4vc2hhdHRlcmVkX3N3b3JkL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi8uLi9zaGF0dGVyZWRfc3dvcmQvVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgVGltZXJNYW5hZ2VyIGZyb20gXCIuL1RpbWVyTWFuYWdlclwiO1xuXG4vKiogKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRpbWVyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cbiAgICAvKiogVGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhpcyB0aW1lciAqL1xuICAgIHByb3RlY3RlZCBzdGF0ZTogVGltZXJTdGF0ZTtcbiAgICBcbiAgICAvKiogVGhlIGZ1bmN0aW9uIHRvIGNhbGwgd2hlbiB0aGlzIHRpbWVyIGVuZHMgKi9cbiAgICBwcm90ZWN0ZWQgb25FbmQ6IEZ1bmN0aW9uO1xuXG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgdGltZXIgc2hvdWxkIGxvb3AgKi9cbiAgICBwcm90ZWN0ZWQgbG9vcDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgdG90YWwgYW1vdW50IG9mIHRpbWUgdGhpcyB0aW1lciBydW5zIGZvciAqL1xuICAgIHByb3RlY3RlZCB0b3RhbFRpbWU6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgYW1vdW50IG9mIHRpbWUgbGVmdCBvbiB0aGUgY3VycmVudCBydW4gKi9cbiAgICBwcm90ZWN0ZWQgdGltZUxlZnQ6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgbnVtYmVyIG9mIHRpbWVzIHRoaXMgdGltZXIgaGFzIGJlZW4gcnVuICovXG4gICAgcHJvdGVjdGVkIG51bVJ1bnM6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHRpbWU6IG51bWJlciwgb25FbmQ/OiBGdW5jdGlvbiwgbG9vcDogYm9vbGVhbiA9IGZhbHNlKXtcbiAgICAgICAgLy8gUmVnaXN0ZXIgdGhpcyB0aW1lclxuICAgICAgICBUaW1lck1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5hZGRUaW1lcih0aGlzKTtcbiAgICAgICAgXG4gICAgICAgIHRoaXMudG90YWxUaW1lID0gdGltZTtcbiAgICAgICAgdGhpcy50aW1lTGVmdCA9IDA7XG4gICAgICAgIHRoaXMub25FbmQgPSBvbkVuZDtcbiAgICAgICAgdGhpcy5sb29wID0gbG9vcDtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IFRpbWVyU3RhdGUuU1RPUFBFRDtcbiAgICAgICAgdGhpcy5udW1SdW5zID0gMDtcbiAgICB9XG5cbiAgICBpc1N0b3BwZWQoKXtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGUgPT09IFRpbWVyU3RhdGUuU1RPUFBFRDtcbiAgICB9XG5cbiAgICBpc1BhdXNlZCgpe1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZSA9PT0gVGltZXJTdGF0ZS5QQVVTRUQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGlzIHRpbWVyIGhhcyBiZWVuIHJ1biBiZWZvcmVcbiAgICAgKiBAcmV0dXJucyB0cnVlIGlmIGl0IGhhcyBiZWVuIHJ1biBhdCBsZWFzdCBvbmNlIChhZnRlciB0aGUgbGF0ZXN0IHJlc2V0KSwgYW5kIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGhhc1J1bigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubnVtUnVucyA+IDA7XG4gICAgfVxuXG4gICAgc3RhcnQodGltZT86IG51bWJlcil7XG4gICAgICAgIGlmKHRpbWUgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICB0aGlzLnRvdGFsVGltZSA9IHRpbWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0ZSA9IFRpbWVyU3RhdGUuQUNUSVZFO1xuICAgICAgICB0aGlzLnRpbWVMZWZ0ID0gdGhpcy50b3RhbFRpbWU7XG4gICAgfVxuXG4gICAgLyoqIFJlc2V0cyB0aGlzIHRpbWVyLiBTZXRzIHRoZSBwcm9ncmVzcyBiYWNrIHRvIHplcm8sIGFuZCBzZXRzIHRoZSBudW1iZXIgb2YgcnVucyBiYWNrIHRvIHplcm8gKi9cbiAgICByZXNldCgpe1xuICAgICAgICB0aGlzLnRpbWVMZWZ0ID0gdGhpcy50b3RhbFRpbWU7XG4gICAgICAgIHRoaXMubnVtUnVucyA9IDA7XG4gICAgfVxuXG4gICAgcGF1c2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBUaW1lclN0YXRlLlBBVVNFRDtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpe1xuICAgICAgICBpZih0aGlzLnN0YXRlID09PSBUaW1lclN0YXRlLkFDVElWRSAmJiBJbnB1dFdyYXBwZXIuZ2V0U3RhdGUoKSA9PT0gR2FtZVN0YXRlLkdBTUlORyl7XG4gICAgICAgICAgICB0aGlzLnRpbWVMZWZ0IC09IGRlbHRhVCoxMDAwO1xuXG4gICAgICAgICAgICBpZih0aGlzLnRpbWVMZWZ0IDw9IDApe1xuICAgICAgICAgICAgICAgIHRoaXMudGltZUxlZnQgPSBNYXRoVXRpbHMuY2xhbXBMb3cwKHRoaXMudGltZUxlZnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZW5kKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZW5kKCl7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgc3RhdGVcbiAgICAgICAgdGhpcy5zdGF0ZSA9IFRpbWVyU3RhdGUuU1RPUFBFRDtcbiAgICAgICAgdGhpcy5udW1SdW5zICs9IDE7XG5cbiAgICAgICAgLy8gQ2FsbCB0aGUgZW5kIGZ1bmN0aW9uIGlmIHRoZXJlIGlzIG9uZVxuICAgICAgICBpZih0aGlzLm9uRW5kKXtcbiAgICAgICAgICAgIHRoaXMub25FbmQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExvb3AgaWYgd2Ugd2FudCB0b1xuICAgICAgICBpZih0aGlzLmxvb3Ape1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IFRpbWVyU3RhdGUuQUNUSVZFO1xuICAgICAgICAgICAgdGhpcy50aW1lTGVmdCA9IHRoaXMudG90YWxUaW1lO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdG9TdHJpbmcoKTogc3RyaW5ne1xuICAgICAgICByZXR1cm4gXCJUaW1lcjogXCIgKyB0aGlzLnN0YXRlICsgXCIgLSBUaW1lIExlZnQ6IFwiICsgdGhpcy50aW1lTGVmdCArIFwibXMgb2YgXCIgKyB0aGlzLnRvdGFsVGltZSArIFwibXNcIjtcbiAgICB9XG59XG5cbmV4cG9ydCBlbnVtIFRpbWVyU3RhdGUge1xuICAgIEFDVElWRSA9IFwiQUNUSVZFXCIsXG4gICAgUEFVU0VEID0gXCJQQVVTRURcIixcbiAgICBTVE9QUEVEID0gXCJTVE9QUEVEXCJcbn0iLCJpbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IFRpbWVyIGZyb20gXCIuL1RpbWVyXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRpbWVyTWFuYWdlciBpbXBsZW1lbnRzIFVwZGF0ZWFibGUge1xuXG4gICAgcHJvdGVjdGVkIHRpbWVyczogQXJyYXk8VGltZXI+O1xuXG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy50aW1lcnMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RhdGljIGluc3RhbmNlOiBUaW1lck1hbmFnZXI7XG5cbiAgICBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogVGltZXJNYW5hZ2VyIHtcbiAgICAgICAgaWYoIXRoaXMuaW5zdGFuY2Upe1xuICAgICAgICAgICAgdGhpcy5pbnN0YW5jZSA9IG5ldyBUaW1lck1hbmFnZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmluc3RhbmNlO1xuICAgIH1cblxuICAgIGFkZFRpbWVyKHRpbWVyOiBUaW1lcil7XG4gICAgICAgIHRoaXMudGltZXJzLnB1c2godGltZXIpO1xuICAgIH1cblxuICAgIGNsZWFyVGltZXJzKCl7XG4gICAgICAgIHRoaXMudGltZXJzID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGltZXJzLmZvckVhY2godGltZXIgPT4gdGltZXIudXBkYXRlKGRlbHRhVCkpO1xuICAgIH1cbn0iLCJpbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuL01hdGhVdGlsc1wiO1xuXG4vLyBUT0RPOiBUaGlzIHNob3VsZCBiZSBtb3ZlZCB0byB0aGUgZGF0YXR5cGVzIGZvbGRlclxuLyoqXG4gKiBBIENvbG9yIHV0aWwgY2xhc3MgdGhhdCBrZWVwcyB0cmFjayBvZiBjb2xvcnMgbGlrZSBhIHZlY3RvciwgYnV0IGNhbiBiZSBjb252ZXJ0ZWQgaW50byBhIHN0cmluZyBmb3JtYXRcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29sb3Ige1xuXHQvKiogVGhlIHJlZCB2YWx1ZSAqL1xuXHRwdWJsaWMgcjogbnVtYmVyO1xuXHQvKiogVGhlIGdyZWVuIHZhbHVlICovXG5cdHB1YmxpYyBnOiBudW1iZXI7XG5cdC8qKiBUaGUgYmx1ZSB2YWx1ZSAqL1xuXHRwdWJsaWMgYjogbnVtYmVyO1xuXHQvKiogVGhlIGFscGhhIHZhbHVlICovXG5cdHB1YmxpYyBhOiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgY29sb3Jcblx0ICogQHBhcmFtIHIgUmVkXG5cdCAqIEBwYXJhbSBnIEdyZWVuXG5cdCAqIEBwYXJhbSBiIEJsdWVcblx0ICogQHBhcmFtIGEgQWxwaGFcblx0ICovXG5cdGNvbnN0cnVjdG9yKHI6IG51bWJlciA9IDAsIGc6IG51bWJlciA9IDAsIGI6IG51bWJlciA9IDAsIGE6IG51bWJlciA9IDEpe1xuICAgICAgICB0aGlzLnIgPSByO1xuICAgICAgICB0aGlzLmcgPSBnO1xuICAgICAgICB0aGlzLmIgPSBiO1xuICAgICAgICB0aGlzLmEgPSBhO1xuXHR9XG5cblx0LyoqXHRcblx0ICogVHJhbnNwYXJlbnQgY29sb3Jcblx0ICogQHJldHVybnMgcmdiYSgwLCAwLCAwLCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBUUkFOU1BBUkVOVCgpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigwLCAwLCAwLCAwKTtcblx0fVxuXHRcblx0LyoqXHRcblx0ICogUmVkIGNvbG9yXG5cdCAqIEByZXR1cm5zIHJnYigyNTUsIDAsIDApXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IFJFRCgpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigyNTUsIDAsIDAsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogR3JlZW4gY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDAsIDI1NSwgMClcblx0ICovXG5cdHN0YXRpYyBnZXQgR1JFRU4oKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMCwgMjU1LCAwLCAxKTtcblx0fVxuXG5cdC8qKlx0XG5cdCAqIEJsdWUgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDAsIDAsIDI1NSlcblx0ICovXG5cdHN0YXRpYyBnZXQgQkxVRSgpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigwLCAwLCAyNTUsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogWWVsbG93IGNvbG9yXG5cdCAqIEByZXR1cm5zIHJnYigyNTUsIDI1NSwgMClcblx0ICovXG5cdHN0YXRpYyBnZXQgWUVMTE9XKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDI1NSwgMjU1LCAwLCAxKTtcblx0fVxuXG5cdC8qKlx0XG5cdCAqIE1hZ2VudGEgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMCwgMjU1KVxuXHQgKi9cblx0c3RhdGljIGdldCBNQUdFTlRBKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDI1NSwgMCwgMjU1LCAxKTtcblx0fVxuXG5cdC8qKlx0XG5cdCAqIEN5YW4gY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDAsIDI1NSwgMjU1KVxuXHQgKi9cblx0c3RhdGljIGdldCBDWUFOKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDAsIDI1NSwgMjU1LCAxKTtcblx0fVxuXG5cdC8qKlx0XG5cdCAqIFdoaXRlIGNvbG9yXG5cdCAqIEByZXR1cm5zIHJnYigyNTUsIDI1NSwgMjU1KVxuXHQgKi9cblx0c3RhdGljIGdldCBXSElURSgpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigyNTUsIDI1NSwgMjU1LCAxKTtcblx0fSBcblxuXHQvKipcdFxuXHQgKiBCbGFjayBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMCwgMClcblx0ICovXG5cdHN0YXRpYyBnZXQgQkxBQ0soKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMCwgMCwgMCwgMSk7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBPcmFuZ2UgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMTAwLCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBPUkFOR0UoKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMjU1LCAxMDAsIDAsIDEpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGNvbG9yIHRvIHRoZSB2YWx1ZXMgcHJvdmlkZWRcblx0ICogQHBhcmFtIHIgUmVkXG5cdCAqIEBwYXJhbSBnIEdyZWVuXG5cdCAqIEBwYXJhbSBiIEJsdWVcblx0ICogQHBhcmFtIGEgQWxwaGFcblx0ICovXG5cdHNldChyOiBudW1iZXIsIGc6IG51bWJlciwgYjogbnVtYmVyLCBhOiBudW1iZXIgPSAxKTogdm9pZCB7XG5cdFx0dGhpcy5yID0gcjtcblx0XHR0aGlzLmcgPSBnO1xuXHRcdHRoaXMuYiA9IGI7XG5cdFx0dGhpcy5hID0gYTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IGNvbG9yIHNsaWdodGx5IGxpZ2h0ZXIgdGhhbiB0aGUgY3VycmVudCBjb2xvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBsaWdodGVyIENvbG9yXG5cdCAqL1xuXHRsaWdodGVuKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKE1hdGhVdGlscy5jbGFtcCh0aGlzLnIgKyA0MCwgMCwgMjU1KSwgTWF0aFV0aWxzLmNsYW1wKHRoaXMuZyArIDQwLCAwLCAyNTUpLCBNYXRoVXRpbHMuY2xhbXAodGhpcy5iICsgNDAsIDAsIDI1NSksIE1hdGhVdGlscy5jbGFtcCh0aGlzLmEgKyAxMCwgMCwgMjU1KSk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIG5ldyBjb2xvciBzbGlnaHRseSBkYXJrZXIgdGhhbiB0aGUgY3VycmVudCBjb2xvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBkYXJrZXIgQ29sb3Jcblx0ICovXG5cdGRhcmtlbigpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcihNYXRoVXRpbHMuY2xhbXAodGhpcy5yIC0gNDAsIDAsIDI1NSksIE1hdGhVdGlscy5jbGFtcCh0aGlzLmcgLSA0MCwgMCwgMjU1KSwgTWF0aFV0aWxzLmNsYW1wKHRoaXMuYiAtIDQwLCAwLCAyNTUpLCBNYXRoVXRpbHMuY2xhbXAodGhpcy5hICsgMTAsIDAsIDI1NSkpO1xuXHR9XG5cdFxuXHQvKipcblx0ICogUmV0dXJucyB0aGlzIGNvbG9yIGFzIGFuIGFycmF5XG5cdCAqIEByZXR1cm5zIFtyLCBnLCBiLCBhXVxuXHQgKi9cblx0dG9BcnJheSgpOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSB7XG5cdFx0cmV0dXJuIFt0aGlzLnIsIHRoaXMuZywgdGhpcy5iLCB0aGlzLmFdO1xuXHR9XG5cdFxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY29sb3IgYXMgYSBzdHJpbmcgb2YgdGhlIGZvcm0gI1JSR0dCQlxuXHQgKiBAcmV0dXJucyAjUlJHR0JCXG5cdCAqL1xuXHR0b1N0cmluZygpOiBzdHJpbmcge1xuXHRcdHJldHVybiBcIiNcIiArIE1hdGhVdGlscy50b0hleCh0aGlzLnIsIDIpICsgTWF0aFV0aWxzLnRvSGV4KHRoaXMuZywgMikgKyBNYXRoVXRpbHMudG9IZXgodGhpcy5iLCAyKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBjb2xvciBhcyBhIHN0cmluZyBvZiB0aGUgZm9ybSByZ2IociwgZywgYilcblx0ICogQHJldHVybnMgcmdiKHIsIGcsIGIpXG5cdCAqL1xuXHR0b1N0cmluZ1JHQigpOiBzdHJpbmcge1xuXHRcdHJldHVybiBcInJnYihcIiArIHRoaXMuci50b1N0cmluZygpICsgXCIsIFwiICsgdGhpcy5nLnRvU3RyaW5nKCkgKyBcIiwgXCIgKyB0aGlzLmIudG9TdHJpbmcoKSArIFwiKVwiO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGNvbG9yIGFzIGEgc3RyaW5nIG9mIHRoZSBmb3JtIHJnYmEociwgZywgYiwgYSlcblx0ICogQHJldHVybnMgcmdiYShyLCBnLCBiLCBhKVxuXHQgKi9cblx0dG9TdHJpbmdSR0JBKCk6IHN0cmluZyB7XG5cdFx0aWYodGhpcy5hID09PSAwKXtcblx0XHRcdHJldHVybiB0aGlzLnRvU3RyaW5nUkdCKCk7XG5cdFx0fVxuXHRcdHJldHVybiBcInJnYmEoXCIgKyB0aGlzLnIudG9TdHJpbmcoKSArIFwiLCBcIiArIHRoaXMuZy50b1N0cmluZygpICsgXCIsIFwiICsgdGhpcy5iLnRvU3RyaW5nKCkgKyBcIiwgXCIgKyB0aGlzLmEudG9TdHJpbmcoKSArXCIpXCJcblx0fVxuXG5cdC8qKlxuXHQgKiBUdXJucyB0aGlzIGNvbG9yIGludG8gYSBmbG9hdDMyQXJyYXkgYW5kIGNoYW5nZXMgY29sb3IgcmFuZ2UgdG8gWzAuMCwgMS4wXVxuXHQgKiBAcmV0dXJucyBhIEZsb2F0MzJBcnJheSBjb250YWluaW5nIHRoZSBjb2xvclxuXHQgKi9cblx0dG9XZWJHTCgpOiBGbG9hdDMyQXJyYXkge1xuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdHRoaXMuci8yNTUsXG5cdFx0XHR0aGlzLmcvMjU1LFxuXHRcdFx0dGhpcy5iLzI1NSxcblx0XHRcdHRoaXMuYVxuXHRcdF0pO1xuXHR9XG5cblx0c3RhdGljIGZyb21TdHJpbmdIZXgoc3RyOiBzdHJpbmcpOiBDb2xvciB7XG5cdFx0bGV0IGkgPSAwO1xuXHRcdGlmKHN0ci5jaGFyQXQoMCkgPT0gXCIjXCIpIGkrPSAxO1xuXHRcdGxldCByID0gTWF0aFV0aWxzLmZyb21IZXgoc3RyLnN1YnN0cmluZyhpLCBpKzIpKTtcblx0XHRsZXQgZyA9IE1hdGhVdGlscy5mcm9tSGV4KHN0ci5zdWJzdHJpbmcoaSsyLCBpKzQpKTtcblx0XHRsZXQgYiA9IE1hdGhVdGlscy5mcm9tSGV4KHN0ci5zdWJzdHJpbmcoaSs0LCBpKzYpKTtcblx0XHRyZXR1cm4gbmV3IENvbG9yKHIsIGcsIGIpO1xuXHR9XG59IiwiLy8gQGlnbm9yZVBhZ2VcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRWFzZUZ1bmN0aW9ucyB7XG5cbiAgICBzdGF0aWMgZWFzZUluT3V0U2luZSh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gLShNYXRoLmNvcyhNYXRoLlBJICogeCkgLSAxKSAvIDI7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VPdXRJblNpbmUoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwLjUgPyAtTWF0aC5jb3MoTWF0aC5QSSooeCArIDAuNSkpLzIgOiAtTWF0aC5jb3MoTWF0aC5QSSooeCAtIDAuNSkpLzIgKyAxO1xuICAgIH1cblxuICAgIHN0YXRpYyBlYXNlT3V0U2luZSh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTWF0aC5zaW4oKHggKiBNYXRoLlBJKSAvIDIpO1xuICAgIH1cblxuICAgIHN0YXRpYyBlYXNlSW5TaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiAxIC0gTWF0aC5jb3MoKHggKiBNYXRoLlBJKSAvIDIpOyBcbiAgICB9XG5cbiAgICBzdGF0aWMgZWFzZUluT3V0UXVpbnQoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwLjUgPyAxNiAqIHggKiB4ICogeCAqIHggKiB4IDogMSAtIE1hdGgucG93KC0yICogeCArIDIsIDUpIC8gMjsgICAgXG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VJbk91dFF1YWQoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwLjUgPyAyICogeCAqIHggOiAxIC0gTWF0aC5wb3coLTIgKiB4ICsgMiwgMikgLyAyO1xuICAgIH1cblxuICAgIHN0YXRpYyBlYXNlT3V0SW5RdWFkKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB4IDwgMC41ID8gdGhpcy5lYXNlT3V0SW5fT3V0UG93KHgsIDIpIDogdGhpcy5lYXNlT3V0SW5fSW5Qb3coeCwgMik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZWFzZU91dEluX091dFBvdyh4OiBudW1iZXIsIHBvdzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIDAuNSAtIE1hdGgucG93KC0yICogeCArIDEsIHBvdykgLyAyO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGVhc2VPdXRJbl9JblBvdyh4OiBudW1iZXIsIHBvdzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIDAuNSArIE1hdGgucG93KDIgKiB4IC0gMSwgcG93KSAvIDI7XG4gICAgfVxufVxuXG5leHBvcnQgZW51bSBFYXNlRnVuY3Rpb25UeXBlIHtcbiAgICAvLyBTSU5FXG4gICAgSU5fT1VUX1NJTkUgPSBcImVhc2VJbk91dFNpbmVcIixcbiAgICBPVVRfSU5fU0lORSA9IFwiZWFzZU91dEluU2luZVwiLFxuICAgIElOX1NJTkUgPSBcImVhc2VJblNpbmVcIixcbiAgICBPVVRfU0lORSA9IFwiZWFzZU91dFNpbmVcIixcblxuICAgIC8vIFFVQURcbiAgICBJTl9PVVRfUVVBRCA9IFwiZWFzZUluT3V0UXVhZFwiLFxuICAgIE9VVF9JTl9RVUFEID0gXCJlYXNlT3V0SW5RdWFkXCIsXG5cbiAgICAvLyBRVUlOVFxuICAgIElOX09VVF9RVUlOVCA9IFwiZWFzZUluT3V0UXVpbnRcIlxufSIsImltcG9ydCBHcmFwaCBmcm9tIFwiLi4vRGF0YVR5cGVzL0dyYXBocy9HcmFwaFwiO1xuaW1wb3J0IEVkZ2VOb2RlIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL0VkZ2VOb2RlXCI7XG5cbi8qKiBBIGNsYXNzIHRvIHByb3ZpZGVzIHNvbWUgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIGdyYXBocyAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR3JhcGhVdGlscyB7XG5cblx0LyoqXG5cdCAqIEFuIGltcGxlbWVudGF0aW9uIG9mIERqaWtzdHJhJ3Mgc2hvcnRlc3QgcGF0aCBhbGdvcml0aG0gYmFzZWQgb24gdGhlIG9uZSBkZXNjcmliZWQgaW4gVGhlIEFsZ29yaXRobSBEZXNpZ24gTWFudWFsLlxuXHQgKiBAcGFyYW0gZyBUaGUgZ3JhcGhcblx0ICogQHBhcmFtIHN0YXJ0IFRoZSBudW1iZXIgdG8gc3RhcnQgdGhlIHNob3J0ZXN0IHBhdGggZnJvbVxuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBjb250YWluaW5nIHRoZSBwYXJlbnQgb2YgZWFjaCBub2RlIG9mIHRoZSBHcmFwaCBpbiB0aGUgc2hvcnRlc3QgcGF0aC5cblx0ICovXG5cdHN0YXRpYyBkamlrc3RyYShnOiBHcmFwaCwgc3RhcnQ6IG51bWJlcik6IEFycmF5PG51bWJlcj4ge1xuXHRcdGxldCBpOiBudW1iZXI7XHRcdC8vIENvdW50ZXJcblx0XHRsZXQgcDogRWRnZU5vZGU7XHQvLyBQb2ludGVyIHRvIGVkZ2Vub2RlXG5cdFx0bGV0IGluVHJlZTogQXJyYXk8Ym9vbGVhbj4gPSBuZXcgQXJyYXkoZy5udW1WZXJ0aWNlcyk7XG5cdFx0bGV0IGRpc3RhbmNlOiBBcnJheTxudW1iZXI+ID0gbmV3IEFycmF5KGcubnVtVmVydGljZXMpO1xuXHRcdGxldCBwYXJlbnQ6IEFycmF5PG51bWJlcj4gPSBuZXcgQXJyYXkoZy5udW1WZXJ0aWNlcyk7XG5cdFx0bGV0IHY6IG51bWJlcjtcdFx0Ly8gQ3VycmVudCB2ZXJ0ZXggdG8gcHJvY2Vzc1xuXHRcdGxldCB3OiBudW1iZXI7IFx0XHQvLyBDYW5kaWRhdGUgZm9yIG5leHQgdmVydGV4XG5cdFx0bGV0IHdlaWdodDogbnVtYmVyO1x0Ly8gRWRnZSB3ZWlnaHRcblx0XHRsZXQgZGlzdDtcdFx0XHQvLyBCZXN0IGN1cnJlbnQgZGlzdGFuY2UgZnJvbSBzdGFydFxuXG5cdFx0Zm9yKGkgPSAwOyBpIDwgZy5udW1WZXJ0aWNlczsgaSsrKXtcblx0XHRcdGluVHJlZVtpXSA9IGZhbHNlO1xuXHRcdFx0ZGlzdGFuY2VbaV0gPSBJbmZpbml0eTtcblx0XHRcdHBhcmVudFtpXSA9IC0xO1xuXHRcdH1cblxuXHRcdGRpc3RhbmNlW3N0YXJ0XSA9IDA7XG5cdFx0diA9IHN0YXJ0O1xuXG5cdFx0d2hpbGUoIWluVHJlZVt2XSl7XG5cdFx0XHRpblRyZWVbdl0gPSB0cnVlO1xuXHRcdFx0cCA9IGcuZWRnZXNbdl07XG5cblx0XHRcdHdoaWxlKHAgIT09IG51bGwpe1xuXHRcdFx0XHR3ID0gcC55O1xuXHRcdFx0XHR3ZWlnaHQgPSBwLndlaWdodDtcblxuXHRcdFx0XHRpZihkaXN0YW5jZVt3XSA+IGRpc3RhbmNlW3ZdICsgd2VpZ2h0KXtcblx0XHRcdFx0XHRkaXN0YW5jZVt3XSA9IGRpc3RhbmNlW3ZdICsgd2VpZ2h0O1xuXHRcdFx0XHRcdHBhcmVudFt3XSA9IHY7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRwID0gcC5uZXh0O1xuXHRcdFx0fVxuXG5cdFx0XHR2ID0gMDtcblxuXHRcdFx0ZGlzdCA9IEluZmluaXR5O1xuXG5cdFx0XHRmb3IoaSA9IDA7IGkgPD0gZy5udW1WZXJ0aWNlczsgaSsrKXtcblx0XHRcdFx0aWYoIWluVHJlZVtpXSAmJiBkaXN0ID4gZGlzdGFuY2VbaV0pe1xuXHRcdFx0XHRcdGRpc3QgPSBkaXN0YW5jZTtcblx0XHRcdFx0XHR2ID0gaTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBwYXJlbnQ7XG5cblx0fVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuXG4vKiogQSBjbGFzcyBjb250YWluaW5nIHNvbWUgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIG1hdGggb3BlcmF0aW9ucyAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWF0aFV0aWxzIHtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzaWduIG9mIHRoZSB2YWx1ZSBwcm92aWRlZFxuICAgICAqIEBwYXJhbSB4IFRoZSB2YWx1ZSB0byBleHRyYWN0IHRoZSBzaWduIGZyb21cbiAgICAgKiBAcmV0dXJucyAtMSBpZiB0aGUgbnVtYmVyIGlzIGxlc3MgdGhhbiAwLCAxIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHN0YXRpYyBzaWduKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB4IDwgMCA/IC0xIDogMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHggaXMgYmV0d2VlbiBhIGFuZCBiXG4gICAgICogQHBhcmFtIGEgVGhlIG1pbiBib3VuZFxuICAgICAqIEBwYXJhbSBiIFRoZSBtYXggYm91bmRcbiAgICAgKiBAcGFyYW0geCBUaGUgdmFsdWUgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0gZXhjbHVzaXZlIFdoZXRoZXIgb3Igbm90IGEgYW5kIGIgYXJlIGV4Y2x1c2l2ZSBib3VuZHNcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHggaXMgYmV0d2VlbiBhIGFuZCBiLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgYmV0d2VlbihhOiBudW1iZXIsIGI6IG51bWJlciwgeDogbnVtYmVyLCBleGNsdXNpdmU/OiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgICAgIGlmKGV4Y2x1c2l2ZSl7XG4gICAgICAgICAgICByZXR1cm4gKGEgPCB4KSAmJiAoeCA8IGIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIChhIDw9IHgpICYmICh4IDw9IGIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xhbXBzIHRoZSB2YWx1ZSB4IHRvIHRoZSByYW5nZSBbbWluLCBtYXhdLCByb3VuZGluZyB1cCBvciBkb3duIGlmIG5lZWRlZFxuICAgICAqIEBwYXJhbSB4IFRoZSB2YWx1ZSB0byBiZSBjbGFtcGVkXG4gICAgICogQHBhcmFtIG1pbiBUaGUgbWluIG9mIHRoZSByYW5nZVxuICAgICAqIEBwYXJhbSBtYXggVGhlIG1heCBvZiB0aGUgcmFuZ2VcbiAgICAgKiBAcmV0dXJucyB4LCBpZiBpdCBpcyBiZXR3ZWVuIG1pbiBhbmQgbWF4LCBvciBtaW4vbWF4IGlmIGl0IGV4Y2VlZHMgdGhlaXIgYm91bmRzXG4gICAgICovXG4gICAgc3RhdGljIGNsYW1wKHg6IG51bWJlciwgbWluOiBudW1iZXIsIG1heDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgaWYoeCA8IG1pbikgcmV0dXJuIG1pbjtcbiAgICAgICAgaWYoeCA+IG1heCkgcmV0dXJuIG1heDtcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xhbXBzIHRoZSB2YWx1ZSB4IHRvIHRoZSByYW5nZSBiZXR3ZWVuIDAgYW5kIDFcbiAgICAgKiBAcGFyYW0geCBUaGUgdmFsdWUgdG8gYmUgY2xhbXBlZFxuICAgICAqIEByZXR1cm5zIHgsIGlmIGl0IGlzIGJldHdlZW4gMCBhbmQgMSwgb3IgMC8xIGlmIGl0IGV4Y2VlZHMgdGhlaXIgYm91bmRzXG4gICAgICovXG4gICAgc3RhdGljIGNsYW1wMDEoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5jbGFtcCh4LCAwLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgdGhlIGxvd2VyIGVuZCBvZiB0aGUgdmFsdWUgb2YgeCB0byB0aGUgcmFuZ2UgdG8gbWluXG4gICAgICogQHBhcmFtIHggVGhlIHZhbHVlIHRvIGJlIGNsYW1wZWRcbiAgICAgKiBAcGFyYW0gbWluIFRoZSBtaW5pbXVtIGFsbG93ZWQgdmFsdWUgb2YgeFxuICAgICAqIEByZXR1cm5zIHgsIGlmIGl0IGlzIGdyZWF0ZXIgdGhhbiBtaW4sIG90aGVyd2lzZSBtaW5cbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXBMb3coeDogbnVtYmVyLCBtaW46IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB4IDwgbWluID8gbWluIDogeDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgdGhlIGxvd2VyIGVuZCBvZiB0aGUgdmFsdWUgb2YgeCB0byB6ZXJvXG4gICAgICogQHBhcmFtIHggVGhlIHZhbHVlIHRvIGJlIGNsYW1wZWRcbiAgICAgKiBAcmV0dXJucyB4LCBpZiBpdCBpcyBncmVhdGVyIHRoYW4gMCwgb3RoZXJ3aXNlIDBcbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXBMb3cwKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBNYXRoVXRpbHMuY2xhbXBMb3coeCwgMCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNsYW1wTWFnbml0dWRlKHY6IFZlYzIsIG06IG51bWJlcik6IFZlYzIge1xuICAgICAgICBpZih2Lm1hZ1NxKCkgPiBtKm0pe1xuICAgICAgICAgICAgcmV0dXJuIHYuc2NhbGVUbyhtKTtcbiAgICAgICAgfSBlbHNle1xuICAgICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgY2hhbmdlUmFuZ2UoeDogbnVtYmVyLCBtaW46IG51bWJlciwgbWF4OiBudW1iZXIsIG5ld01pbjogbnVtYmVyLCBuZXdNYXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmxlcnAobmV3TWluLCBuZXdNYXgsIHRoaXMuaW52TGVycChtaW4sIG1heCwgeCkpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBMaW5lYXIgSW50ZXJwb2xhdGlvblxuXHQgKiBAcGFyYW0gYSBUaGUgZmlyc3QgdmFsdWUgZm9yIHRoZSBpbnRlcnBvbGF0aW9uIGJvdW5kXG5cdCAqIEBwYXJhbSBiIFRoZSBzZWNvbmQgdmFsdWUgZm9yIHRoZSBpbnRlcnBvbGF0aW9uIGJvdW5kXG5cdCAqIEBwYXJhbSB0IFRoZSB0aW1lIHdlIGFyZSBpbnRlcnBvbGF0aW5nIHRvXG4gICAgICogQHJldHVybnMgVGhlIHZhbHVlIGJldHdlZW4gYSBhbmQgYiBhdCB0aW1lIHRcblx0ICovXG5cdHN0YXRpYyBsZXJwKGE6IG51bWJlciwgYjogbnVtYmVyLCB0OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gYSArIHQgKiAoYiAtIGEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludmVyc2UgTGluZWFyIEludGVycG9sYXRpb24uIEZpbmRzIHRoZSB0aW1lIGF0IHdoaWNoIGEgdmFsdWUgYmV0d2VlbiBhIGFuZCBiIHdvdWxkIG9jY3VyXG4gICAgICogQHBhcmFtIGEgVGhlIGZpcnN0IHZhbHVlIGZvciB0aGUgaW50ZXJwb2xhdGlvbiBib3VuZFxuICAgICAqIEBwYXJhbSBiIFRoZSBzZWNvbmQgdmFsdWUgZm9yIHRoZSBpbnRlcnBvbGF0aW9uIGJvdW5kXG4gICAgICogQHBhcmFtIHZhbHVlIFRoZSBjdXJyZW50IHZhbHVlXG4gICAgICogQHJldHVybnMgVGhlIHRpbWUgYXQgd2hpY2ggdGhlIGN1cnJlbnQgdmFsdWUgb2NjdXJzIGJldHdlZW4gYSBhbmQgYlxuICAgICAqL1xuICAgIHN0YXRpYyBpbnZMZXJwKGE6IG51bWJlciwgYjogbnVtYmVyLCB2YWx1ZTogbnVtYmVyKXtcbiAgICAgICAgcmV0dXJuICh2YWx1ZSAtIGEpLyhiIC0gYSk7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIEN1dHMgb2ZmIGRlY2ltYWwgcG9pbnRzIG9mIGEgbnVtYmVyIGFmdGVyIGEgc3BlY2lmaWVkIHBsYWNlXG4gICAgICogQHBhcmFtIG51bSBUaGUgbnVtYmVyIHRvIGZsb29yXG4gICAgICogQHBhcmFtIHBsYWNlIFRoZSBsYXN0IGRlY2ltYWwgcGxhY2Ugb2YgdGhlIG5ldyBudW1iZXJcbiAgICAgKiBAcmV0dXJucyBUaGUgZmxvb3JlZCBudW1iZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgZmxvb3JUb1BsYWNlKG51bTogbnVtYmVyLCBwbGFjZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgaWYocGxhY2UgPT09IDApe1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobnVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBmYWN0b3IgPSAxMDtcbiAgICAgICAgd2hpbGUocGxhY2UgPiAxKXtcbiAgICAgICAgICAgIGZhY3RvciAhPSAxMDtcbiAgICAgICAgICAgIHBsYWNlLS07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihudW0qZmFjdG9yKS9mYWN0b3I7XG5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbnVtYmVyIGZyb20gYSBoZXggc3RyaW5nXG4gICAgICogQHBhcmFtIHN0ciB0aGUgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGhleCBudW1iZXJcbiAgICAgKiBAcmV0dXJucyB0aGUgbnVtYmVyIGluIGRlY2ltYWwgcmVwcmVzZW50ZWQgYnkgdGhlIGhleCBzdHJpbmdcbiAgICAgKi9cbiAgICBzdGF0aWMgZnJvbUhleChzdHI6IHN0cmluZyk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBwYXJzZUludChzdHIsIDE2KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgYXMgYSBoZXhhZGVjaW1hbFxuICAgICAqIEBwYXJhbSBudW0gVGhlIG51bWJlciB0byBjb252ZXJ0IHRvIGhleFxuICAgICAqIEBwYXJhbSBtaW5MZW5ndGggVGhlIGxlbmd0aCBvZiB0aGUgcmV0dXJuZWQgaGV4IHN0cmluZyAoYWRkcyB6ZXJvIHBhZGRpbmcgaWYgbmVlZGVkKVxuICAgICAqIEByZXR1cm5zIFRoZSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIG51bWJlciBhcyBhIHN0cmluZ1xuICAgICAqL1xuICAgIHN0YXRpYyB0b0hleChudW06IG51bWJlciwgbWluTGVuZ3RoOiBudW1iZXIgPSBudWxsKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IGZhY3RvciA9IDE7XG4gICAgICAgIHdoaWxlKGZhY3RvcioxNiA8IG51bSl7XG4gICAgICAgICAgICBmYWN0b3IgKj0gMTY7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGhleFN0ciA9IFwiXCI7XG4gICAgICAgIHdoaWxlKGZhY3RvciA+PSAxKXtcbiAgICAgICAgICAgIGxldCBkaWdpdCA9IE1hdGguZmxvb3IobnVtL2ZhY3Rvcik7XG4gICAgICAgICAgICBoZXhTdHIgKz0gTWF0aFV0aWxzLnRvSGV4RGlnaXQoZGlnaXQpO1xuICAgICAgICAgICAgbnVtIC09IGRpZ2l0ICogZmFjdG9yO1xuICAgICAgICAgICAgZmFjdG9yIC89IDE2O1xuXHRcdH1cblx0XHRcblx0XHRpZihtaW5MZW5ndGggIT09IG51bGwpe1xuXHRcdFx0d2hpbGUoaGV4U3RyLmxlbmd0aCA8IG1pbkxlbmd0aCl7XG5cdFx0XHRcdGhleFN0ciA9IFwiMFwiICsgaGV4U3RyO1xuXHRcdFx0fVxuXHRcdH1cblxuICAgICAgICByZXR1cm4gaGV4U3RyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGEgZGlnaXQgdG8gaGV4YWRlY2ltYWwuIEluIHRoaXMgY2FzZSwgYSBkaWdpdCBpcyBiZXR3ZWVuIDAgYW5kIDE1IGluY2x1c2l2ZVxuICAgICAqIEBwYXJhbSBudW0gVGhlIGRpZ2l0IHRvIGNvbnZlcnQgdG8gaGV4YWRlY2ltYWxcbiAgICAgKiBAcmV0dXJucyBUaGUgaGV4IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkaWdpdCBhcyBhIHN0cmluZ1xuICAgICAqL1xuICAgIHN0YXRpYyB0b0hleERpZ2l0KG51bTogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAgICAgaWYobnVtIDwgMTApe1xuICAgICAgICAgICAgcmV0dXJuIFwiXCIgKyBudW07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSg2NSArIG51bSAtIDEwKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi9Db2xvclwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi9NYXRoVXRpbHNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVuZGVyaW5nVXRpbHMge1xuXHRzdGF0aWMgdG9XZWJHTENvb3Jkcyhwb2ludDogVmVjMiwgb3JpZ2luOiBWZWMyLCB3b3JsZFNpemU6IFZlYzIpOiBGbG9hdDMyQXJyYXkge1xuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdE1hdGhVdGlscy5jaGFuZ2VSYW5nZShwb2ludC54LCBvcmlnaW4ueCwgb3JpZ2luLnggKyB3b3JsZFNpemUueCwgLTEsIDEpLFxuXHRcdFx0TWF0aFV0aWxzLmNoYW5nZVJhbmdlKHBvaW50LnksIG9yaWdpbi55LCBvcmlnaW4ueSArIHdvcmxkU2l6ZS55LCAxLCAtMSlcblx0XHRdKTtcblx0fVxuXG5cdHN0YXRpYyB0b1dlYkdMU2NhbGUoc2l6ZTogVmVjMiwgd29ybGRTaXplOiBWZWMyKTogRmxvYXQzMkFycmF5IHtcblx0XHRyZXR1cm4gbmV3IEZsb2F0MzJBcnJheShbXG5cdFx0XHQyKnNpemUueC93b3JsZFNpemUueCxcblx0XHRcdDIqc2l6ZS55L3dvcmxkU2l6ZS55LFxuXHRcdF0pO1xuXHR9XG5cblx0c3RhdGljIHRvV2ViR0xDb2xvcihjb2xvcjogQ29sb3IpOiBGbG9hdDMyQXJyYXkge1xuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdE1hdGhVdGlscy5jaGFuZ2VSYW5nZShjb2xvci5yLCAwLCAyNTUsIDAsIDEpLFxuXHRcdFx0TWF0aFV0aWxzLmNoYW5nZVJhbmdlKGNvbG9yLmcsIDAsIDI1NSwgMCwgMSksXG5cdFx0XHRNYXRoVXRpbHMuY2hhbmdlUmFuZ2UoY29sb3IuYiwgMCwgMjU1LCAwLCAxKSxcblx0XHRcdGNvbG9yLmFcblx0XHRdKTtcblx0fVxufSIsIi8qKiBTb21lIHV0aWxpdHkgZnVuY3Rpb25zIGZvciBkZWFsaW5nIHdpdGggc3RyaW5ncyAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3RyaW5nVXRpbHMge1xuICAgIC8qKlxuICAgICAqIEV4dHJhY3RzIHRoZSBwYXRoIGZyb20gYSBmaWxlcGF0aCB0aGF0IGluY2x1ZGVzIHRoZSBmaWxlXG4gICAgICogQHBhcmFtIGZpbGVQYXRoIHRoZSBmaWxlcGF0aCB0byBleHRyYWN0IHRoZSBwYXRoIGZyb21cbiAgICAgKiBAcmV0dXJucyBUaGUgcGF0aCBwb3J0aW9uIG9mIHRoZSBmaWxlcGF0aCBwcm92aWRlZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRQYXRoRnJvbUZpbGVQYXRoKGZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBsZXQgc3BsaXRQYXRoID0gZmlsZVBhdGguc3BsaXQoXCIvXCIpO1xuICAgICAgICBzcGxpdFBhdGgucG9wKCk7XG4gICAgICAgIHNwbGl0UGF0aC5wdXNoKFwiXCIpO1xuICAgICAgICByZXR1cm4gc3BsaXRQYXRoLmpvaW4oXCIvXCIpO1xuICAgIH1cbn0iLCJcbmltcG9ydCBHYW1lIGZyb20gXCIuL1dvbGZpZTJEL0xvb3AvR2FtZVwiO1xuaW1wb3J0IE1haW5NZW51IGZyb20gXCIuL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvTWFpbk1lbnVcIjtcbmltcG9ydCBSZWdpc3RyeU1hbmFnZXIgZnJvbSBcIi4vV29sZmllMkQvUmVnaXN0cnkvUmVnaXN0cnlNYW5hZ2VyXCI7XG5pbXBvcnQgV2VhcG9uVGVtcGxhdGVSZWdpc3RyeSBmcm9tIFwiLi9zaGF0dGVyZWRfc3dvcmQvUmVnaXN0cnkvV2VhcG9uUmVnaXN0cnlcIjtcbmltcG9ydCBXZWFwb25UeXBlUmVnaXN0cnkgZnJvbSBcIi4vc2hhdHRlcmVkX3N3b3JkL1JlZ2lzdHJ5L1dlYXBvblR5cGVSZWdpc3RyeVwiO1xuaW1wb3J0IFNwbGFzaFNjcmVlbiBmcm9tIFwiLi9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL1NwbGFzaFNjcmVlblwiO1xuLy8gVGhlIG1haW4gZnVuY3Rpb24gaXMgeW91ciBlbnRyeXBvaW50IGludG8gV29sZmllMkQuIFNwZWNpZnkgeW91ciBmaXJzdCBzY2VuZSBhbmQgYW55IG9wdGlvbnMgaGVyZS5cbihmdW5jdGlvbiBtYWluKCl7XG4gICAgLy8gUnVuIGFueSB0ZXN0c1xuICAgIHJ1blRlc3RzKCk7XG5cbiAgICAvLyBTZXQgdXAgb3B0aW9ucyBmb3Igb3VyIGdhbWVcbiAgICBsZXQgb3B0aW9ucyA9IHtcbiAgICAgICAgY2FudmFzU2l6ZToge3ggOiAxMjgwLCB5OjcyMH0sXG4gICAgICAgIC8vY2FudmFzU2l6ZToge3g6IHdpbmRvdy5pbm5lcldpZHRoLCB5OiB3aW5kb3cuaW5uZXJIZWlnaHR9LCAgICAgICAgICAvLyBUaGUgc2l6ZSBvZiB0aGUgZ2FtZVxuICAgICAgICBjbGVhckNvbG9yOiB7cjogMCwgZzogMCwgYjogMH0sICAgLy8gVGhlIGNvbG9yIHRoZSBnYW1lIGNsZWFycyB0b1xuICAgICAgICBpbnB1dHM6IFtcbiAgICAgICAgICAgIHtuYW1lOiBcImxlZnRcIiwga2V5czogW1wiYVwiLCBcImFycm93bGVmdFwiXX0sICAgIC8vVE9ETyAtIGFkZCBhcnJvdyBrZXlzXG4gICAgICAgICAgICB7bmFtZTogXCJyaWdodFwiLCBrZXlzOiBbXCJkXCIsIFwiYXJyb3dyaWdodFwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJ1cFwiLCBrZXlzOiBbXCJ3XCIsIFwiYXJyb3d1cFwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJkb3duXCIsIGtleXM6IFtcInNcIiwgXCJhcnJvd2Rvd25cIl19LFxuICAgICAgICAgICAge25hbWU6IFwianVtcFwiLCBrZXlzOiBbXCJ6XCIsIFwic3BhY2VcIl19LFxuICAgICAgICAgICAge25hbWU6IFwiYXR0YWNrXCIsIGtleXM6IFtcImpcIixcInhcIixcImVudGVyXCJdfSwgIFxuICAgICAgICAgICAge25hbWU6IFwiZGFzaFwiLCBrZXlzOiBbXCJrXCIsXCJjXCJdfSwgICAgLy9cbiAgICAgICAgICAgIHtuYW1lOiBcInNraWxsXCIsIGtleXM6IFtcImxcIixcInZcIl19LFxuICAgICAgICAgICAge25hbWU6IFwiaW52ZW50b3J5XCIsIGtleXM6IFtcImlcIixcImJcIl19LFxuICAgICAgICAgICAge25hbWU6IFwicGF1c2VcIiwga2V5czogW1wiZXNjYXBlXCJdfSwgICAgXG4gICAgICAgICAgICB7bmFtZTogXCJ0YWJcIiwga2V5czogW1widGFiXCJdfSxcbiAgICAgICAgICAgIHtuYW1lOiBcImJ1ZmYxXCIsIGtleXM6IFtcIjFcIl19LFxuICAgICAgICAgICAge25hbWU6IFwiYnVmZjJcIiwga2V5czogW1wiMlwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJidWZmM1wiLCBrZXlzOiBbXCIzXCJdfVxuICAgICAgICBdLFxuICAgICAgICB1c2VXZWJHTDogZmFsc2UsICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGVsbCB0aGUgZ2FtZSB3ZSB3YW50IHRvIHVzZSB3ZWJnbFxuICAgICAgICBzaG93RGVidWc6IGZhbHNlICAgICAgICAgICAgICAgICAgICAgIC8vIFdoZXRoZXIgdG8gc2hvdyBkZWJ1ZyBtZXNzYWdlcy4gWW91IGNhbiBjaGFuZ2UgdGhpcyB0byB0cnVlIGlmIHlvdSB3YW50XG4gICAgfVxuXG5cbiAgICAvLyBTZXQgdXAgY3VzdG9tIHJlZ2lzdHJpZXNcbiAgICBsZXQgd2VhcG9uVGVtcGxhdGVSZWdpc3RyeSA9IG5ldyBXZWFwb25UZW1wbGF0ZVJlZ2lzdHJ5KCk7XG4gICAgUmVnaXN0cnlNYW5hZ2VyLmFkZEN1c3RvbVJlZ2lzdHJ5KFwid2VhcG9uVGVtcGxhdGVzXCIsIHdlYXBvblRlbXBsYXRlUmVnaXN0cnkpO1xuICAgIFxuICAgIGxldCB3ZWFwb25UeXBlUmVnaXN0cnkgPSBuZXcgV2VhcG9uVHlwZVJlZ2lzdHJ5KCk7XG4gICAgUmVnaXN0cnlNYW5hZ2VyLmFkZEN1c3RvbVJlZ2lzdHJ5KFwid2VhcG9uVHlwZXNcIiwgd2VhcG9uVHlwZVJlZ2lzdHJ5KTtcblxuICAgIC8vIENyZWF0ZSBhIGdhbWUgd2l0aCB0aGUgb3B0aW9ucyBzcGVjaWZpZWRcbiAgICBjb25zdCBnYW1lID0gbmV3IEdhbWUob3B0aW9ucyk7XG5cbiAgICAvLyBTdGFydCBvdXIgZ2FtZVxuICAgIGdhbWUuc3RhcnQoU3BsYXNoU2NyZWVuLCB7fSk7ICAgXG4gICAgLy9UT0RPIC0gY2hhbmdlIHRvIHNwbGFzaCBzY3JlZW4gb25jZSBhdmFpbGFibGVcbiAgICAvL2dhbWUuc3RhcnQoU3BsYXNoU2NyZWVuLHt9KTtcbn0pKCk7XG5cbmZ1bmN0aW9uIHJ1blRlc3RzKCl7fTsiLCJpbXBvcnQgU3RhdGVNYWNoaW5lQUkgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0FJL1N0YXRlTWFjaGluZUFJXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IE9ydGhvZ29uYWxUaWxlbWFwIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9UaWxlbWFwcy9PcnRob2dvbmFsVGlsZW1hcFwiO1xuaW1wb3J0IEJhdHRsZXJBSSBmcm9tIFwiLi9CYXR0bGVyQUlcIjtcblxuaW1wb3J0IFBhdHJvbCBmcm9tIFwiLi9FbmVteVN0YXRlcy9QYXRyb2xcIjtcbmltcG9ydCBBbGVydCBmcm9tIFwiLi9FbmVteVN0YXRlcy9BbGVydFwiO1xuaW1wb3J0IFNsaW1lQXR0YWNrIGZyb20gXCIuL0VuZW15U3RhdGVzL1NsaW1lQXR0YWNrXCI7XG5pbXBvcnQgeyBHYW1lU3RhdGUsIFN0YXR1c2VzIH0gZnJvbSBcIi4uL3N3b3JkX2VudW1zXCI7XG5cbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5cbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IFRpbWVyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9UaW1pbmcvVGltZXJcIjtcbmltcG9ydCBQbGF5ZXJDb250cm9sbGVyIGZyb20gXCIuLi9QbGF5ZXIvUGxheWVyQ29udHJvbGxlclwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvQ29sb3JcIjtcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEVuZW15QUkgZXh0ZW5kcyBTdGF0ZU1hY2hpbmVBSSBpbXBsZW1lbnRzIEJhdHRsZXJBSSB7XG4gICAgLyoqIFRoZSBvd25lciBvZiB0aGlzIEFJICovXG4gICAgb3duZXI6IEFuaW1hdGVkU3ByaXRlO1xuXG4gICAgLyoqIFRoZSB0b3RhbCBwb3NzaWJsZSBhbW91bnQgb2YgaGVhbHRoIHRoaXMgZW50aXR5IGhhcyAqL1xuICAgIG1heEhlYWx0aDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBjdXJyZW50IGFtb3VudCBvZiBoZWFsdGggdGhpcyBlbnRpdHkgaGFzICovXG4gICAgQ1VSUkVOVF9IUDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBkZWZhdWx0IG1vdmVtZW50IHNwZWVkIG9mIHRoaXMgQUkgKi9cbiAgICBzcGVlZDogbnVtYmVyID0gMjA7XG5cbiAgICBtYXhTcGVlZDogbnVtYmVyID0gNDA7XG5cbiAgICAvKiogQSByZWZlcmVuY2UgdG8gdGhlIHBsYXllciBvYmplY3QgKi9cbiAgICBwbGF5ZXI6IEdhbWVOb2RlO1xuXG4gICAgLy8gVGhlIGN1cnJlbnQga25vd24gcG9zaXRpb24gb2YgdGhlIHBsYXllclxuICAgIHBsYXllclBvczogVmVjMjtcblxuICAgIHRpbGVtYXA6IE9ydGhvZ29uYWxUaWxlbWFwO1xuXG4gICAgdmVsb2NpdHk6IFZlYzIgPSBWZWMyLlpFUk87XG5cbiAgICBkaXJlY3Rpb246IG51bWJlcjsgLy8xIGZvciByaWdodCwgLTEgZm9yIGxlZnRcblxuICAgIGV4cF92YWw6IG51bWJlciA9IDEwMDsgLy9leHAgdmFsdWUgdG8gZ2l2ZSBwbGF5ZXIgd2hlbiB0aGlzIGRpZXNcblxuICAgIHBvaXNvblRpbWVyIDogVGltZXI7XG4gICAgcG9pc29uQ291bnRlciA6IG51bWJlciA9IDA7XG5cbiAgICBidXJuVGltZXIgOiBUaW1lciA7XG4gICAgYnVybkNvdW50ZXIgOiBudW1iZXIgPTA7XG5cbiAgICBibGVlZFRpbWVyIDogVGltZXI7XG4gICAgYmxlZWRDb3VudGVyIDpudW1iZXIgPSAwO1xuXG4gICAgaGVhbHRoQmFyOiBSZWN0O1xuICAgIHBvaXNvblN0YXQ6IFNwcml0ZTtcbiAgICBidXJuU3RhdDogU3ByaXRlO1xuICAgIGJsZWVkU3RhdDogU3ByaXRlO1xuXG4gICAgYXR0YWNrVGltZXIgOiBUaW1lcjtcbiAgICBpc0F0dGFraW5nOiBib29sZWFuID0gZmFsc2U7XG4gICAgZGFtYWdlVGltZXI6IFRpbWVyO1xuXG5cbiAgICBpbml0aWFsaXplQUkob3duZXI6IEFuaW1hdGVkU3ByaXRlLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7IFxuICAgICAgICB0aGlzLm93bmVyID0gb3duZXI7XG5cbiAgICAgICAgLy9hZGQgc3RhdGVzXG4gICAgICAgICAvLyBQYXRyb2wgbW9kZVxuICAgICAgICB0aGlzLmFkZFN0YXRlKEVuZW15U3RhdGVzLlBBVFJPTCwgbmV3IFBhdHJvbCh0aGlzLCBvd25lcikpO1xuICAgICAgICB0aGlzLmFkZFN0YXRlKEVuZW15U3RhdGVzLkFMRVJULCBuZXcgQWxlcnQodGhpcywgb3duZXIpKTtcbiAgICAgICAgdGhpcy5hZGRTdGF0ZShFbmVteVN0YXRlcy5BVFRBQ0ssIG5ldyBTbGltZUF0dGFjayh0aGlzLCBvd25lcikpO1xuICAgICAgICBcbiAgICAgICAgdGhpcy5tYXhIZWFsdGggPSBvcHRpb25zLmhlYWx0aDtcblxuICAgICAgICB0aGlzLkNVUlJFTlRfSFAgPSBvcHRpb25zLmhlYWx0aDtcblxuICAgICAgICB0aGlzLnBsYXllciA9IG9wdGlvbnMucGxheWVyO1xuXG4gICAgICAgIHRoaXMuZXhwX3ZhbCA9IG9wdGlvbnMuZXhwO1xuXG4gICAgICAgIC8vVE9ETyAtIGdldCBjb3JyZWN0IHRpbGVtYXBcbiAgICAgICAgdGhpcy50aWxlbWFwID0gPE9ydGhvZ29uYWxUaWxlbWFwPnRoaXMub3duZXIuZ2V0U2NlbmUoKS5nZXRMYXllcihcIldhbGxcIikuZ2V0SXRlbXMoKVswXTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0byB0aGUgZGVmYXVsdCBzdGF0ZVxuICAgICAgICB0aGlzLmluaXRpYWxpemUoRW5lbXlTdGF0ZXMuUEFUUk9MKTtcblxuICAgICAgICB0aGlzLmRpcmVjdGlvbiA9IDE7IC8vZGVmYXVsdCBtb3ZpbmcgdG8gdGhlIHJpZ2h0XG5cbiAgICAgICAgLy9UT0RPIC0gZG90cyBldmVyeSAxIHNlYz8gY2FuIGNoYW5nZVxuICAgICAgICB0aGlzLmJ1cm5UaW1lciA9IG5ldyBUaW1lcigxMDAwKTtcbiAgICAgICAgdGhpcy5ibGVlZFRpbWVyID0gbmV3IFRpbWVyKDEwMDApO1xuICAgICAgICB0aGlzLnBvaXNvblRpbWVyID0gbmV3IFRpbWVyKDEwMDApO1xuXG4gICAgICAgIHRoaXMuYXR0YWNrVGltZXIgPSBuZXcgVGltZXIoMjUwMCk7XG4gICAgICAgIHRoaXMuZGFtYWdlVGltZXIgPSBuZXcgVGltZXIoNDAwKTtcbiAgICB9XG5cbiAgICBkYW1hZ2UoZGFtYWdlOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gZW5lbXkgYWxyZWFkeSBkZWFkLCBkbyBub3Qgc2VuZCBuZXcgZXZlbnRcbiAgICAgICAgaWYgKHRoaXMuQ1VSUkVOVF9IUCA8PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5sb2coZGFtYWdlICtcIiBkYW1hZ2UgdGFrZW4sIFwiK3RoaXMuQ1VSUkVOVF9IUCtcIiBocCBsZWZ0XCIpO1xuICAgICAgICB0aGlzLkNVUlJFTlRfSFAgLT0gZGFtYWdlO1xuICAgICAgICAvL1RPRE8gLVxuICAgICAgICBpZiAoIXRoaXMuaXNBdHRha2luZykge1xuICAgICAgICAgICAgdGhpcy5vd25lci5hbmltYXRpb24ucGxheShcIkhVUlRcIixmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGNvbnNvbGUubG9nKGRhbWFnZSArXCIgZGFtYWdlIHRha2VuLCBcIit0aGlzLkNVUlJFTlRfSFArXCIgaHAgbGVmdFwiKTtcblxuICAgICAgICAvLyBJZiBoZWFsdGggZ29lcyBiZWxvdyAwLCBkaXNhYmxlIEFJIGFuZCBmaXJlIGVuZW15RGllZCBldmVudFxuICAgICAgICBpZiAodGhpcy5DVVJSRU5UX0hQIDw9IDApIHtcbiAgICAgICAgICAgIHRoaXMub3duZXIuc2V0QUlBY3RpdmUoZmFsc2UsIHt9KTtcbiAgICAgICAgICAgIHRoaXMub3duZXIuaXNDb2xsaWRhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLm93bmVyLnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLmhlYWx0aEJhcikge1xuICAgICAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB0aGlzLmhlYWx0aEJhciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLnBvaXNvblN0YXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBvaXNvblN0YXQuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIHRoaXMucG9pc29uU3RhdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmJ1cm5TdGF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5idXJuU3RhdC5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5idXJuU3RhdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmJsZWVkU3RhdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYmxlZWRTdGF0LmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB0aGlzLmJsZWVkU3RhdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChQbGF5ZXJfRXZlbnRzLkVORU1ZX0tJTExFRCwge293bmVyOiB0aGlzLm93bmVyLmlkLCBhaTp0aGlzfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kYW1hZ2VUaW1lci5zdGFydCgpO1xuICAgIH1cblxuICAgIGNvbGxpZGVXaXRoUGxheWVyKHBsYXllcjogUGxheWVyQ29udHJvbGxlcik6IHZvaWQge1xuICAgICAgICBwbGF5ZXIuZGFtYWdlKDEwKTtcbiAgICB9XG5cbiAgICBjYW5BdHRhY2socG9zaXRpb246IFZlYzIpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXR0YWNrVGltZXIuaXNTdG9wcGVkKCkgJiYgdGhpcy5vd25lci5wb3NpdGlvbi5kaXN0YW5jZVRvKHBvc2l0aW9uKTw9MzI7XG4gICAgfVxuXG4gICAgLy9UT0RPIC0gbmVlZCB0byBtb2RpZnkgZm9yIHNpZGUgdmlld1xuICAgIGlzUGxheWVyVmlzaWJsZShwb3M6IFZlYzIpOiBWZWMye1xuICAgICAgICAvL0NoZWNrIGlmcGxheWVyIGlzIHZpc2libGUsIHRha2luZyBpbnRvIGFjY291bnQgd2FsbHNcblxuICAgICAgICAvLyBHZXQgdGhlIG5ldyBwbGF5ZXIgbG9jYXRpb25cbiAgICAgICAgbGV0IHN0YXJ0ID0gdGhpcy5vd25lci5wb3NpdGlvbi5jbG9uZSgpO1xuICAgICAgICBsZXQgZGVsdGEgPSBwb3MuY2xvbmUoKS5zdWIoc3RhcnQpO1xuXG4gICAgICAgIGlmIChkZWx0YS5tYWcoKSA+PSA2NDApIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIHRoZSB0aWxlbWFwIHJlZ2lvbiB1bnRpbCB3ZSBmaW5kIGEgY29sbGlzaW9uXG4gICAgICAgIGxldCBtaW5YID0gTWF0aC5taW4oc3RhcnQueCwgcG9zLngpO1xuICAgICAgICBsZXQgbWF4WCA9IE1hdGgubWF4KHN0YXJ0LngsIHBvcy54KTtcbiAgICAgICAgbGV0IG1pblkgPSBNYXRoLm1pbihzdGFydC55LCBwb3MueSk7XG4gICAgICAgIGxldCBtYXhZID0gTWF0aC5tYXgoc3RhcnQueSwgcG9zLnkpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgd2FsbCB0aWxlbWFwXG4gICAgICAgIGxldCB3YWxscyA9IHRoaXMudGlsZW1hcFxuXG4gICAgICAgIGxldCBtaW5JbmRleCA9IHdhbGxzLmdldENvbFJvd0F0KG5ldyBWZWMyKG1pblgsIG1pblkpKTtcbiAgICAgICAgbGV0IG1heEluZGV4ID0gd2FsbHMuZ2V0Q29sUm93QXQobmV3IFZlYzIobWF4WCwgbWF4WSkpO1xuXG4gICAgICAgIGxldCB0aWxlU2l6ZSA9IHdhbGxzLmdldFRpbGVTaXplKCk7XG5cbiAgICAgICAgZm9yIChsZXQgY29sID0gbWluSW5kZXgueDsgY29sIDw9IG1heEluZGV4Lng7IGNvbCsrKSB7XG4gICAgICAgICAgICBmb3IgKGxldCByb3cgPSBtaW5JbmRleC55OyByb3cgPD0gbWF4SW5kZXgueTsgcm93KyspIHtcbiAgICAgICAgICAgICAgICBpZiAod2FsbHMuaXNUaWxlQ29sbGlkYWJsZShjb2wsIHJvdykpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBwb3NpdGlvbiBvZiB0aGlzIHRpbGVcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRpbGVQb3MgPSBuZXcgVmVjMihjb2wgKiB0aWxlU2l6ZS54ICsgdGlsZVNpemUueCAvIDIsIHJvdyAqIHRpbGVTaXplLnkgKyB0aWxlU2l6ZS55IC8gMik7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgY29sbGlkZXIgZm9yIHRoaXMgdGlsZVxuICAgICAgICAgICAgICAgICAgICBsZXQgY29sbGlkZXIgPSBuZXcgQUFCQih0aWxlUG9zLCB0aWxlU2l6ZS5zY2FsZWQoMSAvIDIpKTtcblxuICAgICAgICAgICAgICAgICAgICBsZXQgaGl0ID0gY29sbGlkZXIuaW50ZXJzZWN0U2VnbWVudChzdGFydCwgZGVsdGEsIFZlYzIuWkVSTyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGhpdCAhPT0gbnVsbCAmJiBzdGFydC5kaXN0YW5jZVNxVG8oaGl0LnBvcykgPCBzdGFydC5kaXN0YW5jZVNxVG8ocG9zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGl0IGEgd2FsbCwgd2UgY2FuJ3Qgc2VlIHRoZSBwbGF5ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJwbGF5ZXIgbm90IHZpc2libGVcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwb3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZ2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIHBsYXllclxuICAgICAqIEByZXR1cm5zIHBvc2l0aW9uIG9mIHRoZSBwbGF5ZXIgaWYgdmlzaWJsZSwgZWxzZSBudWxsXG4gICAgICovXG4gICAgZ2V0UGxheWVyUG9zaXRpb24oKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzUGxheWVyVmlzaWJsZSh0aGlzLnBsYXllci5wb3NpdGlvbik7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKXtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nZXRTdGF0ZSgpICE9IEdhbWVTdGF0ZS5HQU1JTkcpIHtcbiAgICAgICAgICAgIHRoaXMub3duZXIuYW5pbWF0aW9uLnBhdXNlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vd25lci5hbmltYXRpb24ucmVzdW1lKCk7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIGlmKHRoaXMuYnVyblRpbWVyLmlzU3RvcHBlZCgpICYmIHRoaXMuYnVybkNvdW50ZXIgPjApe1xuICAgICAgICAgICAgdGhpcy5idXJuQ291bnRlciAtLTtcbiAgICAgICAgICAgIHRoaXMuYnVyblRpbWVyLnN0YXJ0KCk7XG4gICAgICAgICAgICB0aGlzLmRhbWFnZSgxMiArICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmV4dHJhRG90RG1nICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodGhpcy5wb2lzb25UaW1lci5pc1N0b3BwZWQoKSAmJiB0aGlzLnBvaXNvbkNvdW50ZXIgPjApe1xuICAgICAgICAgICAgdGhpcy5wb2lzb25Db3VudGVyIC0tO1xuICAgICAgICAgICAgdGhpcy5wb2lzb25UaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgdGhpcy5kYW1hZ2UoIE1hdGgucm91bmQodGhpcy5DVVJSRU5UX0hQLzIwKSArICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmV4dHJhRG90RG1nICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLmJsZWVkVGltZXIuaXNTdG9wcGVkKCkgJiYgdGhpcy5ibGVlZENvdW50ZXIgPjApe1xuICAgICAgICAgICAgdGhpcy5ibGVlZENvdW50ZXIgLS07XG4gICAgICAgICAgICB0aGlzLmJsZWVkVGltZXIuc3RhcnQoKTtcbiAgICAgICAgICAgIHRoaXMuZGFtYWdlKDMgK01hdGgucm91bmQodGhpcy5DVVJSRU5UX0hQLzMzKSArICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmV4dHJhRG90RG1nICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5oZWFsdGhCYXIpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLnBvc2l0aW9uID0gdGhpcy5vd25lci5jb2xsaXNpb25TaGFwZS5jZW50ZXIuY2xvbmUoKS5hZGQobmV3IFZlYzIoMCwgLSgoPEFBQkI+dGhpcy5vd25lci5jb2xsaXNpb25TaGFwZSkuaGgrNSkpKTtcbiAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmZpbGxXaWR0aCA9IHRoaXMuQ1VSUkVOVF9IUC90aGlzLm1heEhlYWx0aCAqIHRoaXMub3duZXIuY29sbGlzaW9uU2hhcGUuaHcgKiAzO1xuICAgICAgICAgICAgaWYgKHRoaXMuQ1VSUkVOVF9IUC90aGlzLm1heEhlYWx0aCA+PSAyLzMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhlYWx0aEJhci5jb2xvciA9IENvbG9yLkdSRUVOO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5DVVJSRU5UX0hQL3RoaXMubWF4SGVhbHRoID49IDEvMykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmNvbG9yID0gQ29sb3IuWUVMTE9XO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWFsdGhCYXIuY29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucG9pc29uU3RhdCkge1xuICAgICAgICAgICAgdGhpcy5wb2lzb25TdGF0LnBvc2l0aW9uID0gdGhpcy5vd25lci5jb2xsaXNpb25TaGFwZS5jZW50ZXIuY2xvbmUoKS5hZGQobmV3IFZlYzIoLSgoPEFBQkI+dGhpcy5vd25lci5jb2xsaXNpb25TaGFwZSkuaHcpKjEuNSsxMCwgLSgoPEFBQkI+dGhpcy5vd25lci5jb2xsaXNpb25TaGFwZSkuaGgrMTUpKSk7XG4gICAgICAgICAgICB0aGlzLnBvaXNvblN0YXQudmlzaWJsZSA9IHRoaXMucG9pc29uQ291bnRlciA+IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYnVyblN0YXQpIHtcbiAgICAgICAgICAgIHRoaXMuYnVyblN0YXQucG9zaXRpb24gPSB0aGlzLnBvaXNvblN0YXQucG9zaXRpb24uY2xvbmUoKS5hZGQobmV3IFZlYzIoMTUsIDApKTtcbiAgICAgICAgICAgIHRoaXMuYnVyblN0YXQudmlzaWJsZSA9IHRoaXMuYnVybkNvdW50ZXIgPiAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmJsZWVkU3RhdCkge1xuICAgICAgICAgICAgdGhpcy5ibGVlZFN0YXQucG9zaXRpb24gPSB0aGlzLnBvaXNvblN0YXQucG9zaXRpb24uY2xvbmUoKS5hZGQobmV3IFZlYzIoMzAsIDApKTtcbiAgICAgICAgICAgIHRoaXMuYmxlZWRTdGF0LnZpc2libGUgPSB0aGlzLmJsZWVkQ291bnRlciA+IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5vd25lci5wb3NpdGlvbi55ID4gdGhpcy50aWxlbWFwLmdldERpbWVuc2lvbnMoKS55ICogdGhpcy50aWxlbWFwLmdldFRpbGVTaXplKCkueSkge1xuICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0hQID0gLTE7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuRU5FTVlfS0lMTEVELCB7b3duZXI6IHRoaXMub3duZXIuaWQsIGFpOnRoaXN9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGVudW0gRW5lbXlTdGF0ZXMge1xuICAgIFBBVFJPTCA9IFwicGF0cm9sXCIsXG4gICAgQUxFUlQgPSBcImFsZXJ0XCIsXG4gICAgQVRUQUNLID0gXCJhdHRhY2tcIlxufSIsImltcG9ydCBFbmVteUFJLCB7IEVuZW15U3RhdGVzIH0gZnJvbSBcIi4uL0VuZW15QUlcIjtcbmltcG9ydCBFbmVteVN0YXRlIGZyb20gXCIuL0VuZW15U3RhdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWxlcnQgZXh0ZW5kcyBFbmVteVN0YXRlIHtcbiAgICBvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24ucGxheUlmTm90QWxyZWFkeShcIldBTEtcIiwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGxldCBwb3NpdGlvbiA9IHRoaXMucGFyZW50LmdldFBsYXllclBvc2l0aW9uKCk7XG4gICAgICAgIGlmIChwb3NpdGlvbikge1xuICAgICAgICAgICAgdGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IHRoaXMucGFyZW50Lm1heFNwZWVkICogTWF0aC5zaWduKHBvc2l0aW9uLnggLSB0aGlzLm93bmVyLnBvc2l0aW9uLngpO1xuICAgICAgICAgICAgdGhpcy5wYXJlbnQuZGlyZWN0aW9uID0gdGhpcy5wYXJlbnQudmVsb2NpdHkueCA+PSAwID8gMSA6IC0xO1xuICAgICAgICAgICAgaWYgKHRoaXMucGFyZW50LmNhbkF0dGFjayhwb3NpdGlvbikpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmlzaGVkKEVuZW15U3RhdGVzLkFUVEFDSyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gMDtcbiAgICAgICAgICAgIHRoaXMuZmluaXNoZWQoRW5lbXlTdGF0ZXMuUEFUUk9MKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5jYW5XYWxrKCkpIHtcbiAgICAgICAgICAgIHRoaXMucGFyZW50LnZlbG9jaXR5LnggPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgKDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IHRoaXMucGFyZW50LmRpcmVjdGlvbiA9PT0gMSA/IHRydWUgOiBmYWxzZSA7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuICAgIH1cblxuICAgIG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24uc3RvcCgpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59IiwiaW1wb3J0IEVuZW15QUksIHsgRW5lbXlTdGF0ZXMgfSBmcm9tIFwiLi4vRW5lbXlBSVwiO1xuaW1wb3J0IEVuZW15U3RhdGUgZnJvbSBcIi4vRW5lbXlTdGF0ZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEF0dGFjayBleHRlbmRzIEVuZW15U3RhdGUge1xuICAgIHByb3RlY3RlZCBjaGFyZ2VkOiBzdHJpbmc7XG4gICAgcHJvdGVjdGVkIGF0dGFja2VkOiBzdHJpbmc7XG5cbiAgICBvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXJlbnQuYXR0YWNrVGltZXIuc3RhcnQoKTtcbiAgICAgICAgdGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IDA7XG4gICAgICAgIHRoaXMucGFyZW50LmlzQXR0YWtpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLmNoYXJnZWQgPSB0aGlzLm93bmVyLmlkK1wiY2hhcmdlZFwiO1xuICAgICAgICB0aGlzLmF0dGFja2VkID0gdGhpcy5vd25lci5pZCtcImF0dGFja2VkXCI7XG5cbiAgICAgICAgLy8gVE9ETyByZXBsYWNlIERZSU5HIHdpdGggQ0hBUkdJTkdcbiAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24ucGxheShcIkNIQVJHRVwiLCBmYWxzZSwgdGhpcy5jaGFyZ2VkKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUodGhpcy5jaGFyZ2VkKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUodGhpcy5hdHRhY2tlZCk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuICAgIH1cblxuICAgIG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICAgICAgdGhpcy5wYXJlbnQuaXNBdHRha2luZyA9IGZhbHNlO1xuICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5zdG9wKCk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn0iLCJpbXBvcnQgQUFCQiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgU3RhdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgRW5lbXlBSSBmcm9tIFwiLi4vRW5lbXlBSVwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvUmVjZWl2ZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgRW5lbXlTdGF0ZSBleHRlbmRzIFN0YXRlIHtcbiAgcHJvdGVjdGVkIHBhcmVudDogRW5lbXlBSTtcbiAgcHJvdGVjdGVkIG93bmVyOiBHYW1lTm9kZTtcbiAgcHJvdGVjdGVkIHJlY2VpdmVyOiBSZWNlaXZlcjtcbiAgZ3Jhdml0eTogbnVtYmVyID0gMTUwMDsgLy9UT0RPIC0gY2FuIGNoYW5nZSBsYXRlclxuXG4gIGNvbnN0cnVjdG9yKHBhcmVudDogRW5lbXlBSSwgb3duZXI6IEdhbWVOb2RlKSB7XG4gICAgc3VwZXIocGFyZW50KTtcbiAgICB0aGlzLm93bmVyID0gb3duZXI7XG4gICAgdGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuICB9XG5cbiAgaGFuZGxlSW5wdXQoZXZlbnQ6IEdhbWVFdmVudCk6IHZvaWQgeyB9XG5cbiAgY2FuV2FsaygpIHtcbiAgICBsZXQgY29sbGlzaW9uID0gPEFBQkI+dGhpcy5vd25lci5jb2xsaXNpb25TaGFwZTtcbiAgICBsZXQgY29scm93ID0gdGhpcy5wYXJlbnQudGlsZW1hcC5nZXRDb2xSb3dBdChjb2xsaXNpb24uY2VudGVyLmNsb25lKCkuYWRkKG5ldyBWZWMyKHRoaXMucGFyZW50LmRpcmVjdGlvbiAqIChjb2xsaXNpb24uaHcrMikpKSk7XG4gICAgcmV0dXJuICF0aGlzLnBhcmVudC50aWxlbWFwLmlzVGlsZUNvbGxpZGFibGUoY29scm93LngsIGNvbHJvdy55KSAmJiB0aGlzLnBhcmVudC50aWxlbWFwLmlzVGlsZUNvbGxpZGFibGUoY29scm93LngsY29scm93LnkrMSk7XG4gIH1cblxuICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucGFyZW50LmRhbWFnZVRpbWVyLmlzU3RvcHBlZCgpICYmICF0aGlzLnBhcmVudC5pc0F0dGFraW5nKSB7XG4gICAgICB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gMDtcbiAgICB9XG4gICAgLy8gRG8gZ3Jhdml0eVxuICAgIHRoaXMucGFyZW50LnZlbG9jaXR5LnkgKz0gdGhpcy5ncmF2aXR5ICogZGVsdGFUO1xuICAgIHRoaXMub3duZXIubW92ZSh0aGlzLnBhcmVudC52ZWxvY2l0eS5zY2FsZWQoZGVsdGFUKSk7XG4gIH1cbn1cblxuIiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgTmF2aWdhdGlvblBhdGggZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1BhdGhmaW5kaW5nL05hdmlnYXRpb25QYXRoXCI7XG5cbmltcG9ydCBFbmVteUFJLCB7IEVuZW15U3RhdGVzIH0gZnJvbSBcIi4uL0VuZW15QUlcIjtcbmltcG9ydCBFbmVteVN0YXRlIGZyb20gXCIuL0VuZW15U3RhdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYXRyb2wgZXh0ZW5kcyBFbmVteVN0YXRlIHtcbiAgICBvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24ucGxheUlmTm90QWxyZWFkeShcIklETEVcIiwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGlmKCF0aGlzLmNhbldhbGsoKSl7XG4gICAgICAgICAgICB0aGlzLnBhcmVudC5kaXJlY3Rpb24gKj0gLTE7XG4gICAgICAgIH1cblxuICAgICAgICAvL21vdmVcbiAgICAgICAgdGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IHRoaXMucGFyZW50LmRpcmVjdGlvbiAqIHRoaXMucGFyZW50LnNwZWVkO1xuICAgICAgICAoPFNwcml0ZT50aGlzLm93bmVyKS5pbnZlcnRYID0gdGhpcy5wYXJlbnQuZGlyZWN0aW9uID09PSAxID8gdHJ1ZSA6IGZhbHNlIDtcblxuICAgICAgICBpZiAodGhpcy5wYXJlbnQuZ2V0UGxheWVyUG9zaXRpb24oKSkge1xuICAgICAgICAgICAgdGhpcy5maW5pc2hlZChFbmVteVN0YXRlcy5BTEVSVCk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgfVxuXG4gICAgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5zdG9wKCk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn0iLCJpbXBvcnQgRW5lbXlBSSwgeyBFbmVteVN0YXRlcyB9IGZyb20gXCIuLi9FbmVteUFJXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBBdHRhY2sgZnJvbSBcIi4vQXR0YWNrXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNsaW1lQXR0YWNrIGV4dGVuZHMgQXR0YWNrIHtcbiAgICBvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICB9XG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZmluaXNoZWQoRW5lbXlTdGF0ZXMuQUxFUlQpO1xuICAgIH1cbiAgICBvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn0iLCJpbXBvcnQgRW5lbXlBSSwgeyBFbmVteVN0YXRlcyB9IGZyb20gXCIuLi9FbmVteUFJXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgQXR0YWNrIGZyb20gXCIuL0F0dGFja1wiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTbmFrZUF0dGFjayBleHRlbmRzIEF0dGFjayB7XG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHdoaWxlICh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKSB7XG4gICAgICAgICAgICBsZXQgZXZlbnQgPSB0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpLnR5cGU7XG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY2FzZSB0aGlzLmNoYXJnZWQ6XG4gICAgICAgICAgICAgICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnBsYXkoXCJBVFRBQ0tcIiwgZmFsc2UsIHRoaXMuYXR0YWNrZWQpO1xuICAgICAgICAgICAgICAgICAgICAoPEFBQkI+dGhpcy5vd25lci5jb2xsaXNpb25TaGFwZSkuaGFsZlNpemUueCArPSAzLjU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgdGhpcy5hdHRhY2tlZDpcbiAgICAgICAgICAgICAgICAgICAgKDxBQUJCPnRoaXMub3duZXIuY29sbGlzaW9uU2hhcGUpLmhhbGZTaXplLnggLT0gMy41O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbmlzaGVkKEVuZW15U3RhdGVzLkFMRVJUKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgKDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IHRoaXMucGFyZW50LmRpcmVjdGlvbiA9PT0gMSA/IHRydWUgOiBmYWxzZSA7XG4gICAgfVxufSIsImltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEVuZW15QUksIHsgRW5lbXlTdGF0ZXMgfSBmcm9tIFwiLi9FbmVteUFJXCI7XG5pbXBvcnQgU2xpbWVBdHRhY2sgZnJvbSBcIi4vRW5lbXlTdGF0ZXMvU2xpbWVBdHRhY2tcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2xpbWVBSSBleHRlbmRzIEVuZW15QUkge1xuICAgIGluaXRpYWxpemVBSShvd25lcjogQW5pbWF0ZWRTcHJpdGUsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgc3VwZXIuaW5pdGlhbGl6ZUFJKG93bmVyLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5hZGRTdGF0ZShFbmVteVN0YXRlcy5BVFRBQ0ssIG5ldyBTbGltZUF0dGFjayh0aGlzLCBvd25lcikpO1xuICAgIH1cbn0iLCJpbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBFbmVteUFJLCB7IEVuZW15U3RhdGVzIH0gZnJvbSBcIi4vRW5lbXlBSVwiO1xuaW1wb3J0IFNuYWtlQXR0YWNrIGZyb20gXCIuL0VuZW15U3RhdGVzL1NuYWtlQXR0YWNrXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNuYWtlQUkgZXh0ZW5kcyBFbmVteUFJIHtcbiAgICBpbml0aWFsaXplQUkob3duZXI6IEFuaW1hdGVkU3ByaXRlLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG4gICAgICAgIHN1cGVyLmluaXRpYWxpemVBSShvd25lciwgb3B0aW9ucyk7XG4gICAgICAgIHRoaXMuYWRkU3RhdGUoRW5lbXlTdGF0ZXMuQVRUQUNLLCBuZXcgU25ha2VBdHRhY2sodGhpcywgb3duZXIpKTtcbiAgICB9XG59IiwiXG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgQmF0dGxlckFJIGZyb20gXCIuLi9BSS9CYXR0bGVyQUlcIjtcbmltcG9ydCBXZWFwb24gZnJvbSBcIi4vaXRlbXMvV2VhcG9uXCI7XG5pbXBvcnQgUGxheWVyQ29udHJvbGxlciBmcm9tIFwiLi4vUGxheWVyL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBFbmVteUFJIGZyb20gXCIuLi9BSS9FbmVteUFJXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhdHRsZU1hbmFnZXIge1xuICAgIHBsYXllcnM6IEFycmF5PEJhdHRsZXJBST47XG5cbiAgICBlbmVtaWVzOiBBcnJheTxCYXR0bGVyQUk+O1xuXG4gICAgaGFuZGxlSW50ZXJhY3Rpb24oYXR0YWNrZXJUeXBlOiBzdHJpbmcsIHdlYXBvbjogV2VhcG9uLCB1c2VyPzogR2FtZU5vZGUpIHtcbiAgICAgICAgLy9tYXkgYmUgdW5uZWVkZWQgc2luY2Ugd2UgYXJlIGNvbnRyb2xsaW5nIHRoZSBwbGF5ZXIgLSBcbiAgICAgICAgLy93ZSBkZXRlcm1pbmUgZW5lbXkgY29sbGlzaW9uIHRoZXJlXG4gICAgICAgIFxuICAgICAgICBpZiAoYXR0YWNrZXJUeXBlID09PSBcInBsYXllclwiKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgY29sbGlzaW9ucyB3aXRoIGVuZW1pZXNcbiAgICAgICAgICAgIGlmKHRoaXMuZW5lbWllcy5sZW5ndGggIT0gMCl7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZW5lbXkgb2YgdGhpcy5lbmVtaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3ZWFwb24uaGl0cyhlbmVteS5vd25lcikpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBsYXllciA9ICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllcnNbMF0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihwbGF5ZXIuZnVsbEhwQm9udXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZW15LmRhbWFnZShNYXRoLnJvdW5kKCB3ZWFwb24udHlwZS5kYW1hZ2UgKiAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXJzWzBdKS5DVVJSRU5UX0FUSy8xMCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmVteS5kYW1hZ2UoTWF0aC5yb3VuZCh3ZWFwb24udHlwZS5kYW1hZ2UgKiAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXJzWzBdKS5DVVJSRU5UX0FUSy8xMDApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJlbmVteSB0b29rIGRtZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9hZGQgY2hlY2tpbmcgZm9yIGVhY2ggb25oaXQgYnVmZiBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vRE9UU1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYocGxheWVyLmhhc0JsZWVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoPEVuZW15QUk+ZW5lbXkpLmJsZWVkQ291bnRlciArPTM7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihwbGF5ZXIuaGFzUG9pc29uKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoPEVuZW15QUk+ZW5lbXkpLnBvaXNvbkNvdW50ZXIgPTUgO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocGxheWVyLmhhc0J1cm4pe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8RW5lbXlBST5lbmVteSkuYnVybkNvdW50ZXIgPTUgO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHBsYXllci5oYXNMaWZlc3RlYWwpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllci5hZGRIZWFsdGgoTWF0aC5yb3VuZCh3ZWFwb24udHlwZS5kYW1hZ2UgKiBwbGF5ZXIuQ1VSUkVOVF9BVEsvMTAwICogcGxheWVyLmxpZmVzdGVhbHJhdGlvKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgY29sbGlzaW9uIHdpdGggcGxheWVyXG4gICAgICAgICAgICBmb3IgKGxldCBwbGF5ZXIgb2YgdGhpcy5wbGF5ZXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdlYXBvbi5oaXRzKHBsYXllci5vd25lcikpIHtcbiAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnBsYXllcikuZGFtYWdlKHdlYXBvbi50eXBlLmRhbWFnZSwgdXNlcik7XG4gICAgICAgICAgICAgICAgICAgIGlmKCg8UGxheWVyQ29udHJvbGxlcj5wbGF5ZXIpLmhhc1NoaWVsZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+cGxheWVyKS5hZGRTaGllbGQod2VhcG9uLnR5cGUuZGFtYWdlICogLjUpOyAgLy9oYWxmIG9mIGRtZyB0YWtlbiBpcyBjb252ZXJ0ZWQgdG8gc2hpZWxkXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgXG5cbiAgICB9XG5cbiAgICBzZXRQbGF5ZXJzKHBsYXllcjogQXJyYXk8QmF0dGxlckFJPik6IHZvaWQge1xuICAgICAgICB0aGlzLnBsYXllcnMgPSBwbGF5ZXI7XG4gICAgfVxuXG4gICAgc2V0RW5lbWllcyhlbmVtaWVzOiBBcnJheTxCYXR0bGVyQUk+KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW5lbWllcyA9IGVuZW1pZXM7XG4gICAgfVxuXG4gICAgYWRkRW5lbXkoZW5lbXkgOiBCYXR0bGVyQUkpe1xuICAgICAgICB0aGlzLmVuZW1pZXMucHVzaChlbmVteSk7XG4gICAgfVxuXG4gICAgcmVtb3ZlRW5lbXkoZW5lbXkgOiBCYXR0bGVyQUkpe1xuICAgICAgIFxuICAgICAgICBcbiAgICAgICAgdGhpcy5lbmVtaWVzID0gdGhpcy5lbmVtaWVzLmZpbHRlcihpdGVtID0+IGl0ZW0gIT09IGVuZW15KVxuICAgICAgICBpZih0aGlzLmVuZW1pZXMubGVuZ3RoID09IDApe1xuICAgICAgICAgICAgdGhpcy5lbmVtaWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZW5lbWllcztcbiAgICAgICAgICBcbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgeyBHcmFwaGljVHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9HcmFwaGljVHlwZXNcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IEl0ZW0gZnJvbSBcIi4vaXRlbXMvSXRlbVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnZlbnRvcnlNYW5hZ2VyIHtcblxuICAgIHByaXZhdGUgcG9zaXRpb246IFZlYzI7XG4gICAgcHJpdmF0ZSBpdGVtczogQXJyYXk8SXRlbT47XG4gICAgcHJpdmF0ZSBpbnZlbnRvcnlTbG90czogQXJyYXk8U3ByaXRlPjtcbiAgICBwcml2YXRlIHNsb3RTaXplOiBWZWMyO1xuICAgIHByaXZhdGUgcGFkZGluZzogbnVtYmVyO1xuICAgIHByaXZhdGUgY3VycmVudFNsb3Q6IG51bWJlcjtcbiAgICBwcml2YXRlIHNsb3RMYXllcjogc3RyaW5nO1xuICAgIHByaXZhdGUgaXRlbUxheWVyOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBzZWxlY3RlZFNsb3Q6IFJlY3Q7XG5cbiAgICBjb25zdHJ1Y3RvcihzY2VuZTogU2NlbmUsIHNpemU6IG51bWJlciwgaW52ZW50b3J5U2xvdDogc3RyaW5nLCBwb3NpdGlvbjogVmVjMiwgcGFkZGluZzogbnVtYmVyLCBzbG90TGF5ZXI6IHN0cmluZywgaXRlbUxheWVyOiBzdHJpbmcpe1xuICAgICAgICB0aGlzLml0ZW1zID0gbmV3IEFycmF5KHNpemUpO1xuICAgICAgICB0aGlzLmludmVudG9yeVNsb3RzID0gbmV3IEFycmF5KHNpemUpO1xuICAgICAgICB0aGlzLnBhZGRpbmcgPSBwYWRkaW5nO1xuICAgICAgICB0aGlzLnBvc2l0aW9uID0gcG9zaXRpb247XG4gICAgICAgIHRoaXMuY3VycmVudFNsb3QgPSAwO1xuXG4gICAgICAgIC8vIEFkZCBsYXllcnNcbiAgICAgICAgdGhpcy5zbG90TGF5ZXIgPSBzbG90TGF5ZXI7XG4gICAgICAgIHNjZW5lLmFkZFVJTGF5ZXIodGhpcy5zbG90TGF5ZXIpLnNldERlcHRoKDEwMCk7XG4gICAgICAgIHRoaXMuaXRlbUxheWVyID0gaXRlbUxheWVyO1xuICAgICAgICBzY2VuZS5hZGRVSUxheWVyKHRoaXMuaXRlbUxheWVyKS5zZXREZXB0aCgxMDEpO1xuXG4gICAgICAgIC8vIENyZWF0ZSB0aGUgaW52ZW50b3J5IHNsb3RzXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspe1xuICAgICAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90c1tpXSA9IHNjZW5lLmFkZC5zcHJpdGUoaW52ZW50b3J5U2xvdCwgdGhpcy5zbG90TGF5ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zbG90U2l6ZSA9IHRoaXMuaW52ZW50b3J5U2xvdHNbMF0uc2l6ZS5jbG9uZSgpO1xuXG4gICAgICAgIC8vIFBvc2l0aW9uIHRoZSBpbnZlbnRvcnkgc2xvdHNcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKyl7XG4gICAgICAgICAgICB0aGlzLmludmVudG9yeVNsb3RzW2ldLnBvc2l0aW9uLnNldChwb3NpdGlvbi54ICsgaSoodGhpcy5zbG90U2l6ZS54ICsgdGhpcy5wYWRkaW5nKSwgcG9zaXRpb24ueSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYSByZWN0IGZvciB0aGUgc2VsZWN0ZWQgc2xvdFxuICAgICAgICB0aGlzLnNlbGVjdGVkU2xvdCA9IDxSZWN0PnNjZW5lLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIHNsb3RMYXllciwge3Bvc2l0aW9uOiB0aGlzLnBvc2l0aW9uLmNsb25lKCksIHNpemU6IHRoaXMuc2xvdFNpemUuY2xvbmUoKS5pbmMoLTIpfSk7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTbG90LmNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTbG90LmNvbG9yLmEgPSAwLjI7XG4gICAgfVxuXG4gICAgZ2V0SXRlbSgpOiBJdGVtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXNbdGhpcy5jdXJyZW50U2xvdF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNsb3RcbiAgICAgKi9cbiAgICBjaGFuZ2VTbG90KHNsb3Q6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmN1cnJlbnRTbG90ID0gc2xvdDtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFNsb3QucG9zaXRpb24uY29weSh0aGlzLmludmVudG9yeVNsb3RzW3Nsb3RdLnBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgc2xvdFxuICAgICAqL1xuICAgIGdldFNsb3QoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFNsb3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhbiBpdGVtIHRvIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgc2xvdFxuICAgICAqL1xuICAgIGFkZEl0ZW0oaXRlbTogSXRlbSk6IGJvb2xlYW4ge1xuICAgICAgICBpZighdGhpcy5pdGVtc1t0aGlzLmN1cnJlbnRTbG90XSl7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIGl0ZW0gdG8gdGhlIGludmVudG9yeVxuICAgICAgICAgICAgdGhpcy5pdGVtc1t0aGlzLmN1cnJlbnRTbG90XSA9IGl0ZW07XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgZ3VpXG4gICAgICAgICAgICBpdGVtLm1vdmVTcHJpdGUobmV3IFZlYzIodGhpcy5wb3NpdGlvbi54ICsgdGhpcy5jdXJyZW50U2xvdCoodGhpcy5zbG90U2l6ZS54ICsgdGhpcy5wYWRkaW5nKSwgdGhpcy5wb3NpdGlvbi55KSwgdGhpcy5pdGVtTGF5ZXIpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gRmFpbGVkIHRvIGFkZCBpdGVtLCBzb21ldGhpbmcgd2FzIGFscmVhZHkgaW4gdGhlIHNsb3RcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYW5kIHJldHVybnMgYW4gaXRlbSBmcm9tIHRoZSB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNsb3QsIGlmIHBvc3NpYmxlXG4gICAgICovXG4gICAgcmVtb3ZlSXRlbSgpOiBJdGVtIHtcbiAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLml0ZW1zW3RoaXMuY3VycmVudFNsb3RdO1xuXG4gICAgICAgIHRoaXMuaXRlbXNbdGhpcy5jdXJyZW50U2xvdF0gPSBudWxsO1xuXG4gICAgICAgIGlmKGl0ZW0pe1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldEFjdGl2ZShhY3RpdmU6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKGFjdGl2ZSl7XG4gICAgICAgICAgICB0aGlzLmludmVudG9yeVNsb3RzLmZvckVhY2goc2xvdCA9PiBzbG90LmFscGhhID0gMS4wKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90cy5mb3JFYWNoKHNsb3QgPT4gc2xvdC5hbHBoYSA9IDAuNSk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBJdGVtIHtcbiAgICAvKiogVGhlIHNwcml0ZSB0aGF0IHJlcHJlc2VudHMgdGhpcyB3ZWFwb24gaW4gdGhlIHdvcmxkIG9yIGluIGFuIGludmVudG9yeSAqL1xuICAgIHNwcml0ZTogU3ByaXRlO1xuXG4gICAgY29uc3RydWN0b3Ioc3ByaXRlOiBTcHJpdGUpe1xuICAgICAgICB0aGlzLnNwcml0ZSA9IHNwcml0ZTtcbiAgICB9XG5cbiAgICBtb3ZlU3ByaXRlKHBvc2l0aW9uOiBWZWMyLCBsYXllcj86IHN0cmluZyl7XG4gICAgICAgIC8vIENoYW5nZSB0aGUgbGF5ZXIgaWYgbmVlZGVkXG4gICAgICAgIGlmKGxheWVyKXtcbiAgICAgICAgICAgIGxldCBjdXJyZW50TGF5ZXIgPSB0aGlzLnNwcml0ZS5nZXRMYXllcigpO1xuICAgICAgICAgICAgY3VycmVudExheWVyLnJlbW92ZU5vZGUodGhpcy5zcHJpdGUpO1xuICAgICAgICAgICAgbGV0IG5ld0xheWVyID0gdGhpcy5zcHJpdGUuZ2V0U2NlbmUoKS5nZXRMYXllcihsYXllcik7XG4gICAgICAgICAgICBuZXdMYXllci5hZGROb2RlKHRoaXMuc3ByaXRlKTtcbiAgICAgICAgICAgIHRoaXMuc3ByaXRlLnNldExheWVyKG5ld0xheWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1vdmUgdGhlIHNwcml0ZVxuICAgICAgICB0aGlzLnNwcml0ZS5wb3NpdGlvbi5jb3B5KHBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICBhYnN0cmFjdCB1c2UodXNlcjogR2FtZU5vZGUsIC4uLmFyZ3M6IGFueSk6IHZvaWQ7XG59IiwiLy9UT0RPIGltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRpbWVyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9UaW1pbmcvVGltZXJcIjtcbmltcG9ydCBCYXR0bGVNYW5hZ2VyIGZyb20gXCIuLi9CYXR0bGVNYW5hZ2VyXCI7XG5pbXBvcnQgSXRlbSBmcm9tIFwiLi9JdGVtXCI7XG5pbXBvcnQgV2VhcG9uVHlwZSBmcm9tIFwiLi9XZWFwb25UeXBlcy9XZWFwb25UeXBlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2VhcG9uIGV4dGVuZHMgSXRlbSB7XG4gICAgLyoqIFRoZSB0eXBlIG9mIHRoaXMgd2VhcG9uICovXG4gICAgdHlwZTogV2VhcG9uVHlwZTtcblxuICAgIC8qKiBBIGxpc3Qgb2YgYXNzZXRzIHRoaXMgd2VhcG9uIG5lZWRzIHRvIGJlIGFuaW1hdGVkICovXG4gICAgYXNzZXRzOiBBcnJheTxhbnk+O1xuXG4gICAgLyoqIEFuIGV2ZW50IGVtaXR0ZXIgdG8gaG9vayBpbnRvIHRoZSBFdmVudFF1ZXVlICovXG4gICAgZW1pdHRlcjogRW1pdHRlclxuXG4gICAgLyoqIFRoZSBiYXR0bGUgbWFuYWdlciAqL1xuICAgIGJhdHRsZU1hbmFnZXI6IEJhdHRsZU1hbmFnZXI7XG5cbiAgICBjb29sZG93biA6IG51bWJlciA9IDA7XG4gICAgLyoqIFRoZSBjb29sZG93biB0aW1lciBmb3IgdGhpcyB3ZWFwb24ncyB1c2UgKi9cbiAgICBjb29sZG93blRpbWVyOiBUaW1lcjtcblxuICAgIEVYVFJBX0RBTUFHRSA6IG51bWJlcjsgIC8vZmxhdCBleHRyYSBkYW1hZ2UgdmFsdWVcblxuICAgIEVYVFJBX1JBTkdFOiBudW1iZXIgOyAgIC8vcGVyY2VudGFnZSB2YWx1ZSAtPiAuMSA9IDEwJSBleHRyYSByYW5nZVxuXG4gICAgY29uc3RydWN0b3Ioc3ByaXRlOiBTcHJpdGUsIHR5cGU6IFdlYXBvblR5cGUsIGJhdHRsZU1hbmFnZXI6IEJhdHRsZU1hbmFnZXIpe1xuICAgICAgICBzdXBlcihzcHJpdGUpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgd2VhcG9uIHR5cGVcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZS5jbG9uZSgpO1xuXG4gICAgICAgIC8vIEtlZXAgYSByZWZlcmVuY2UgdG8gdGhlIHNwcml0ZSBvZiB0aGlzIHdlYXBvblxuICAgICAgICB0aGlzLnNwcml0ZSA9IHNwcml0ZTtcblxuICAgICAgICAvLyBDcmVhdGUgYW4gZXZlbnQgZW1pdHRlclxuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuXG4gICAgICAgIC8vIFNhdmUgYSByZWZlcmVuY2UgdG8gdGhlIGJhdHRsZXIgbWFuYWdlclxuICAgICAgICB0aGlzLmJhdHRsZU1hbmFnZXIgPSBiYXR0bGVNYW5hZ2VyO1xuXG4gICAgICAgIC8vIENyZWF0ZSB0aGUgY29vbGRvd24gdGltZXJcbiAgICAgICAgdGhpcy5jb29sZG93blRpbWVyID0gbmV3IFRpbWVyKHR5cGUuY29vbGRvd24pOyAgXG4gICAgICAgIHRoaXMuY29vbGRvd24gPSB0eXBlLmNvb2xkb3duO1xuXG4gICAgICAgIHRoaXMuRVhUUkFfREFNQUdFID0gMDtcbiAgICAgICAgdGhpcy5FWFRSQV9SQU5HRT0wOyBcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICAvKipcbiAgICAgKiBVc2VzIHRoaXMgd2VhcG9uIGluIHRoZSBzcGVjaWZpZWQgZGlyZWN0aW9uLlxuICAgICAqIFRoaXMgb25seSB3b3JrcyBpZiB0aGUgY29vbGRvd24gdGltZXIgaGFzIGVuZGVkXG4gICAgICovXG4gICAgdXNlKHVzZXI6IEdhbWVOb2RlLCB1c2VyVHlwZTogc3RyaW5nLCBkaXJlY3Rpb246IFZlYzIpOiBib29sZWFuIHtcbiAgICAgICAgLy8gSWYgdGhlIGNvb2xkb3duIHRpbWVyIGlzIHN0aWxsIHJ1bm5pbmcsIHdlIGNhbid0IHVzZSB0aGUgd2VhcG9uXG4gICAgICAgIGlmKCF0aGlzLmNvb2xkb3duVGltZXIuaXNTdG9wcGVkKCkpe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlbHkgb24gdGhlIHdlYXBvbiB0eXBlIHRvIGNyZWF0ZSBhbnkgbmVjZXNzYXJ5IGFzc2V0c1xuICAgICAgICB0aGlzLmFzc2V0cyA9IHRoaXMudHlwZS5jcmVhdGVSZXF1aXJlZEFzc2V0cyh0aGlzLnNwcml0ZS5nZXRTY2VuZSgpKTtcblxuICAgICAgICAvLyBEbyBhIHR5cGUgc3BlY2lmaWMgd2VhcG9uIGFuaW1hdGlvblxuICAgICAgICB0aGlzLnR5cGUuZG9BbmltYXRpb24odXNlciwgZGlyZWN0aW9uLCB0aGlzLkVYVFJBX1JBTkdFLCAuLi50aGlzLmFzc2V0cyk7XG5cbiAgICAgICAgLy8gQXBwbHkgZGFtYWdlXG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlci5oYW5kbGVJbnRlcmFjdGlvbih1c2VyVHlwZSwgdGhpcywgdXNlcik7XG4gICAgXG4gICAgICAgIC8vIFJlc2V0IHRoZSBjb29sZG93biB0aW1lclxuICAgICAgICB0aGlzLmNvb2xkb3duVGltZXIuc3RhcnQoKTtcbiAgICAgICAgLy9UT0RPIC0gbWF5IGhhdmUgdG8gbW92ZSBlbHNld2hlcmVcbiAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwic3dvcmRcIiwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IGZhbHNlfSk7XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIGNoZWNrIGZvciB3aGV0aGVyIG9yIG5vdCB0aGlzIHdlYXBvbiBoaXQgYSBub2RlXG4gICAgICovXG4gICAgaGl0cyhub2RlOiBHYW1lTm9kZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy50eXBlLmhpdHMobm9kZSwgLi4udGhpcy5hc3NldHMpO1xuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBXZWFwb25UeXBlIGZyb20gXCIuL1dlYXBvblR5cGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2xpY2UgZXh0ZW5kcyBXZWFwb25UeXBlIHtcblxuICAgIGluaXRpYWxpemUob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICB0aGlzLmRhbWFnZSA9IG9wdGlvbnMuZGFtYWdlO1xuICAgICAgICB0aGlzLmNvb2xkb3duID0gb3B0aW9ucy5jb29sZG93bjtcbiAgICAgICAgdGhpcy5kaXNwbGF5TmFtZSA9IG9wdGlvbnMuZGlzcGxheU5hbWU7XG4gICAgICAgIHRoaXMuc3ByaXRlS2V5ID0gb3B0aW9ucy5zcHJpdGVLZXk7XG4gICAgICAgIHRoaXMudXNlVm9sdW1lID0gb3B0aW9ucy51c2VWb2x1bWU7XG4gICAgfVxuXG4gICAgZG9BbmltYXRpb24oYXR0YWNrZXI6IEdhbWVOb2RlLCBkaXJlY3Rpb246IFZlYzIsIGV4dHJhUmFuZ2U6bnVtYmVyLHNsaWNlU3ByaXRlOiBBbmltYXRlZFNwcml0ZSk6IHZvaWQge1xuICAgICAgICBcbiAgICAgICAgLy8gUm90YXRlIHRoaXMgd2l0aCB0aGUgZ2FtZSBub2RlXG4gICAgICAgIC8vIFRPRE8gLSBuZWVkIHRvIHJvdGF0ZSB0aGUgYW5pbSBwcm9wZXJseVxuICAgICAgICAvL3NsaWNlU3ByaXRlLnJvdGF0aW9uID0gYXR0YWNrZXIucm90YXRpb247XG4gICAgICAgIC8vc2xpY2VTcHJpdGUucm90YXRpb24gPSAoPFNwcml0ZT5hdHRhY2tlcikuaW52ZXJ0WD8gLjUqIE1hdGguUEkgOiAxLjUgKiBNYXRoLlBJO1xuICAgICAgICBzbGljZVNwcml0ZS5pbnZlcnRYID0gKDxTcHJpdGU+YXR0YWNrZXIpLmludmVydFg7XG4gICAgICAgIFxuICAgICAgICAvL1RPRE8tIFxuICAgICAgICAvLzQgdG8gc2NhbGUgdXAgdGhlIGRlZmF1bHQgc3ByaXRlIC0gbWF5IGJlIGRpZmZlcmVudCBsYXRlciBkZXBlbmRpbmcgb24gYXRrIGFuaW1cbiAgICAgICAgc2xpY2VTcHJpdGUuc2NhbGVYID0gMiooMStleHRyYVJhbmdlKTsgLy9taWdodCBoYXZlIHRvIGFkZCBleHRyYSByYW5nZSB0byB5IGFzIHdlbGxcbiAgICAgICAgc2xpY2VTcHJpdGUuc2NhbGVZID0gMjtcblxuICAgICAgICBcbiAgICAgICAgLy8gTW92ZSB0aGUgc2xpY2Ugb3V0IGZyb20gdGhlIHBsYXllclxuICAgICAgICAvL3NjYWxlID0gbnVtIG9mIHBpeGVscyBiZXR3ZWVuIGNlbnRlciBvZiBzcHJpdGUgYW5kIGF0ayBhbmltXG4gICAgICAgIHNsaWNlU3ByaXRlLnBvc2l0aW9uID0gYXR0YWNrZXIucG9zaXRpb24uY2xvbmUoKS5hZGQoZGlyZWN0aW9uLnNjYWxlZCgzMikpOyBcbiAgICAgICAgc2xpY2VTcHJpdGUucG9zaXRpb24gPSAgc2xpY2VTcHJpdGUucG9zaXRpb24uYWRkKG5ldyBWZWMyKDAsMTYpKTsgICAgLy9tYWtlIGl0IGdvIGRvd24gYSBiaXRcbiAgICAgICAgXG4gICAgICAgIC8vIFBsYXkgdGhlIHNsaWNlIGFuaW1hdGlvbiB3L28gbG9vcCwgYnV0IHF1ZXVlIHRoZSBub3JtYWwgYW5pbWF0aW9uXG4gICAgICAgIHNsaWNlU3ByaXRlLmFuaW1hdGlvbi5wbGF5KFwiU0xJQ0VcIik7XG4gICAgICAgIHNsaWNlU3ByaXRlLmFuaW1hdGlvbi5xdWV1ZShcIk5PUk1BTFwiLCB0cnVlKTtcbiAgICAgICAgXG4gICAgfVxuXG4gICAgY3JlYXRlUmVxdWlyZWRBc3NldHMoc2NlbmU6IFNjZW5lKTogW0FuaW1hdGVkU3ByaXRlXSB7XG4gICAgICAgIGxldCBzbGljZSA9IHNjZW5lLmFkZC5hbmltYXRlZFNwcml0ZShcInNsaWNlXCIsIFwicHJpbWFyeVwiKTtcbiAgICAgICAgc2xpY2UuYW5pbWF0aW9uLnBsYXkoXCJOT1JNQUxcIiwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIFtzbGljZV07XG4gICAgfVxuXG4gICAgaGl0cyhub2RlOiBHYW1lTm9kZSwgc2xpY2VTcHJpdGU6IEFuaW1hdGVkU3ByaXRlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBzbGljZVNwcml0ZS5ib3VuZGFyeS5vdmVybGFwcyhub2RlLmNvbGxpc2lvblNoYXBlKTtcbiAgICB9XG5cbiAgICBjbG9uZSgpOiBXZWFwb25UeXBlIHtcbiAgICAgICAgbGV0IG5ld1R5cGUgPSBuZXcgU2xpY2UoKTtcbiAgICAgICAgbmV3VHlwZS5pbml0aWFsaXplKHtkYW1hZ2U6IHRoaXMuZGFtYWdlLCBjb29sZG93bjogdGhpcy5jb29sZG93biwgZGlzcGxheU5hbWU6IHRoaXMuZGlzcGxheU5hbWUsIHNwcml0ZUtleTogdGhpcy5zcHJpdGVLZXksIHVzZVZvbHVtZTogdGhpcy51c2VWb2x1bWV9KTtcbiAgICAgICAgcmV0dXJuIG5ld1R5cGU7XG4gICAgfVxufSIsImltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vLi4vLi4vLi4vV29sZmllMkQvU2NlbmUvU2NlbmVcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgV2VhcG9uVHlwZSB7XG4gICAgLyoqIFRoZSBrZXkgZm9yIHRoaXMgc3ByaXRlIGltYWdlICovXG4gICAgc3ByaXRlS2V5OiBzdHJpbmc7XG5cbiAgICAvKiogSG93IG11Y2ggZGFtYWdlIHRoaXMgd2VhcG9uIGRvZXMgKi9cbiAgICBkYW1hZ2U6IG51bWJlcjtcblxuICAgIC8qKiBEaXNwbGF5IG5hbWUgKi9cbiAgICBkaXNwbGF5TmFtZTogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSB1c2UgY29vbGRvd24gb2YgdGhlIHdlYXBvbiAqL1xuICAgIGNvb2xkb3duOiBudW1iZXI7XG5cbiAgICAvKiogSG93IGxvdWQgaXQgaXMgdG8gdXNlIHRoaXMgd2VhcG9uICovXG4gICAgdXNlVm9sdW1lOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGlzIHdlYXBvbiB0eXBlIHdpdGggZGF0YVxuICAgICAqL1xuICAgIGFic3RyYWN0IGluaXRpYWxpemUob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYW5pbWF0aW9uIHRvIGRvIHdoZW4gdGhpcyB3ZWFwb24gaXMgdXNlZFxuICAgICAqL1xuICAgIGFic3RyYWN0IGRvQW5pbWF0aW9uKC4uLmFyZ3M6IGFueSk6IHZvaWQ7XG5cbiAgICBhYnN0cmFjdCBjcmVhdGVSZXF1aXJlZEFzc2V0cyhzY2VuZTogU2NlbmUpOiBBcnJheTxhbnk+O1xuXG4gICAgYWJzdHJhY3QgaGl0cyhub2RlOiBHYW1lTm9kZSwgLi4uYXJnczogYW55KTogYm9vbGVhbjtcblxuICAgIGFic3RyYWN0IGNsb25lKCk6IFdlYXBvblR5cGU7XG59IiwiaW1wb3J0IFN0YXRlTWFjaGluZUFJIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9BSS9TdGF0ZU1hY2hpbmVBSVwiO1xuaW1wb3J0IEdhbWVOb2RlLCB7IFR3ZWVuYWJsZVByb3BlcnRpZXMgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBPcnRob2dvbmFsVGlsZW1hcCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVGlsZW1hcHMvT3J0aG9nb25hbFRpbGVtYXBcIjtcbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBGYWxsIGZyb20gXCIuL1BsYXllclN0YXRlcy9GYWxsXCI7XG5pbXBvcnQgSWRsZSBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvSWRsZVwiO1xuaW1wb3J0IEluQWlyIGZyb20gXCIuL1BsYXllclN0YXRlcy9JbkFpclwiO1xuaW1wb3J0IEp1bXAgZnJvbSBcIi4vUGxheWVyU3RhdGVzL0p1bXBcIjtcbmltcG9ydCBXYWxrIGZyb20gXCIuL1BsYXllclN0YXRlcy9XYWxrXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgSXRlbSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvSXRlbVwiO1xuaW1wb3J0IEludmVudG9yeU1hbmFnZXIgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL0ludmVudG9yeU1hbmFnZXJcIjtcbmltcG9ydCBCYXR0bGVyQUkgZnJvbSBcIi4uL0FJL0JhdHRsZXJBSVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgV2VhcG9uIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9pdGVtcy9XZWFwb25cIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgRW5lbXlBSSBmcm9tIFwiLi4vQUkvRW5lbXlBSVwiO1xuaW1wb3J0IFRpbWVyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9UaW1pbmcvVGltZXJcIjtcbmltcG9ydCBQbGF5ZXJTdGF0ZSBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvUGxheWVyU3RhdGVcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuZXhwb3J0IGVudW0gUGxheWVyVHlwZSB7XG4gICAgUExBVEZPUk1FUiA9IFwicGxhdGZvcm1lclwiLFxuICAgIFRPUERPV04gPSBcInRvcGRvd25cIlxufVxuXG5leHBvcnQgZW51bSBQbGF5ZXJTdGF0ZXMge1xuICAgIElETEUgPSBcImlkbGVcIixcbiAgICBXQUxLID0gXCJ3YWxrXCIsXG5cdEpVTVAgPSBcImp1bXBcIixcbiAgICBGQUxMID0gXCJmYWxsXCIsXG5cdFBSRVZJT1VTID0gXCJwcmV2aW91c1wiXG59XG5cbmV4cG9ydCBlbnVtIEJ1ZmZUeXBlIHtcbiAgICBGTEFUX0FUSyAgPSBcImF0dGFja1wiLFxuICAgIFBFUkNFTlRfQVRLID0gXCJwZXJjZW50X2F0dGFja1wiLFxuICAgIERFRiA9IFwiZGVmZW5jZVwiLFxuICAgIEZMQVRfSEVBTFRIID0gXCJoZWFsdGhcIixcbiAgICBQRVJDRU5UX0hFQUxUSCA9IFwicGVyY2VudF9oZWFsdGhcIixcbiAgICBTUEVFRCA9IFwic3BlZWRcIixcbiAgICBSQU5HRSA9IFwicmFuZ2VcIixcbiAgICBBVEtTUEVFRCA9IFwiYXR0YWNrc3BlZWRcIixcbiAgICBQT0lTT04gPSBcInBvaXNvblwiLFxuICAgIEJMRUVEID0gXCJibGVlZFwiLFxuICAgIEJVUk4gPSBcImJ1cm5cIixcbiAgICBFWFRSQV9ET1QgPSBcImV4dHJhZG90XCIsXG4gICAgU0hJRUxEID0gXCJzaGllbGRcIixcbiAgICBTSElFTERfRE1HID0gXCJzaGllbGRkbWdcIiwgICAvL2luY3JlYXNlIHNoaWVsZCBkbWcgcmF0aW9cbiAgICBMSUZFU1RFQUwgPSBcImxpZmVzdGVhbFwiLFxuICAgIExJRkVTVEVBTEJVRkYgPSBcImxpZmVzdGVhbGJ1ZmZcIixcbiAgICBFWFRSQUxJRkU9IFwiZXh0cmFsaWZlXCIsXG4gICAgT05FU0hPVCA9IFwib25lc2hvdFwiLFxuICAgIEZVTExIUEJPTlVTRE1HID0gXCJmdWxsaHBib251c2RtZ1wiXG59XG5cblxuZXhwb3J0IGNsYXNzIEJ1ZmYgIHtcbiAgICBcInR5cGVcIjogQnVmZlR5cGU7XG4gICAgXCJ2YWx1ZVwiOiBudW1iZXI7XG4gICAgLy9cImJvbnVzXCI6IGJvb2xlYW4sICAgICAgICAgLy9uZWVkIHRvIGRldGVybWluZSB3aGF0IGJvbnVzIGdpdmVzXG4gICAgXCJzdHJpbmdcIj8gOiBzdHJpbmc7XG4gICAgXCJjYXRlZ29yeVwiIDogQnVmZkNhdGVnb3J5XG59XG5cblxuXG4vL1RPRE8gLSBuZWVkIGJldHRlciBuYW1lcyBcbmV4cG9ydCBlbnVtIEJ1ZmZDYXRlZ29yeXtcbiAgICBBVFRBQ0sgPSBcIkFUVEFDS1wiLFxuICAgIERPVCA9IFwiRE9UXCIsXG4gICAgU0hJRUxEID0gXCJTSElFTERcIixcbiAgICBIRUFMVEggPSBcIkhFQUxUSFwiLFxuICAgIEVYVFJBID0gXCJFWFRSQVwiXG59XG5cbi8vVE9ETyAtIGRpc2N1c3MgbWF4IHN0YXRzIGR1cmluZyByZWZpbmVtZW50LCB1bnVzZWQgZm9yIG5vd1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGxheWVyQ29udHJvbGxlciBleHRlbmRzIFN0YXRlTWFjaGluZUFJIGltcGxlbWVudHMgQmF0dGxlckFJe1xuICAgIG93bmVyOiBHYW1lTm9kZTtcbiAgICB2ZWxvY2l0eTogVmVjMiA9IFZlYzIuWkVSTztcbiAgICAvL3dpbGwgbmVlZCB0byBkaXNjdXNzIHJlZHVuZGFudCBzdGF0c1xuXHRzcGVlZDogbnVtYmVyID0gMjAwO1xuXHRNSU5fU1BFRUQ6IG51bWJlciA9IDIwMDtcbiAgICBNQVhfU1BFRUQ6IG51bWJlciA9IDMwMDtcbiAgICBCQVNFX0hQOiBudW1iZXIgPSAxMDA7XG4gICAgTUFYX0hQOiBudW1iZXIgPSAxMDA7XG4gICAgQ1VSUkVOVF9IUDogbnVtYmVyID0gMTAwO1xuICAgIEJBU0VfQVRLOiBudW1iZXIgPSAxMDA7XG4gICAgQ1VSUkVOVF9BVEs6IG51bWJlciA9IDEwMDtcbiAgICBkYW1hZ2VfbXVsdGlwbGllcjogbnVtYmVyID0gMTtcbiAgICBDVVJSRU5UX0VYUCA6IG51bWJlciA9IDA7XG4gICAgTUFYX0VYUCA6IG51bWJlciA9IDEwMDtcbiAgICBDVVJSRU5UX1NISUVMRCA6IG51bWJlciA9MDtcbiAgICBNQVhfU0hJRUxEIDogbnVtYmVyID0gMjA7XG4gICAgaW52aW5jaWJsZSA6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBsZXZlbCA6IG51bWJlciA9IDE7XG5cbiAgICBnb2RNb2RlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICB0aWxlbWFwOiBPcnRob2dvbmFsVGlsZW1hcDtcblxuICAgIC8vZm9yIGRvdWJsZWp1bXBzIG1heWJlID0gIyBvZiBqdW1wcyBpbiBhaXIgYWxsb3dlZFxuICAgIE1BWF9haXJqdW1wczogbnVtYmVyID0gMTtcbiAgICBhaXJqdW1wczpudW1iZXIgPSAwO1xuICAgIFxuICAgIHByaXZhdGUgbG9va0RpcmVjdGlvbjogVmVjMjtcbiAgICAvKiogQSBsaXN0IG9mIGl0ZW1zIGluIHRoZSBnYW1lIHdvcmxkICovXG4gICAgcHJpdmF0ZSBpdGVtczogQXJyYXk8SXRlbT47XG5cbiAgICAvLyBUaGUgaW52ZW50b3J5IG9mIHRoZSBwbGF5ZXJcbiAgICBpbnZlbnRvcnk6IEludmVudG9yeU1hbmFnZXI7XG5cblx0c3RhdGljIGludmluY2liaWxpdHlUaW1lcjogVGltZXI7XG4gICAgXG4gICAgc3RhdGljIGJ1ZmZQb29sIDogQXJyYXk8QnVmZkNhdGVnb3J5PiA9IG5ldyBBcnJheSgpO1xuXG4gICAgc3RhdGljIGFwcGxpZWRCdWZmczogQXJyYXk8QnVmZj4gPSBuZXcgQXJyYXkoKTtcblxuICAgIC8vYWRkIHRvIGN1cnJlbnRfYnVmZnMgbGF0ZXJcbiAgICBoYXNCbGVlZCA6IEJvb2xlYW4gPSBmYWxzZTtcbiAgICBoYXNQb2lzb24gOiBCb29sZWFuID0gZmFsc2U7XG4gICAgaGFzQnVybiA6IEJvb2xlYW4gPSBmYWxzZTtcbiAgICBoYXNTaGllbGQgOiBCb29sZWFuID0gZmFsc2U7XG4gICAgc2hpZWxkRGFtYWdlIDogbnVtYmVyID0gMTtcbiAgICBoYXNMaWZlc3RlYWwgOiBCb29sZWFuID0gZmFsc2U7XG4gICAgbGlmZXN0ZWFscmF0aW8gOiBudW1iZXIgPSAwOyAvL3BlcmNlbnQgb2YgZGFtYWdlIHRvIHN0ZWFsXG4gICAgaGFzT25lU2hvdDogQm9vbGVhbiA9IGZhbHNlO1xuICAgIGV4dHJhRG90RG1nIDogbnVtYmVyID0wO1xuICAgIGxpdmVzOiBudW1iZXIgPSAxO1xuICAgIGNvb2xkb3duTXVsdGlwbGllciA6IG51bWJlciA9IDE7XG4gICAgZnVsbEhwQm9udXM6IEJvb2xlYW4gPSBmYWxzZTtcblxuICAgIHBvaXNvblRpbWVyIDogVGltZXI7XG4gICAgcG9pc29uQ291bnRlciA6IG51bWJlciA9IDA7XG5cbiAgICBidXJuVGltZXIgOiBUaW1lciA7XG4gICAgYnVybkNvdW50ZXIgOiBudW1iZXIgPTA7XG5cbiAgICBibGVlZFRpbWVyIDogVGltZXI7XG4gICAgYmxlZWRDb3VudGVyIDpudW1iZXIgPSAwO1xuXG4gICAgZW5lbWllc0tpbGxlZCA6IG51bWJlciA9MDtcblxuXG4gICAgLy9UT0RPIC0gZ2V0IHRoZSBjb3JyZWN0IHRpbGVtYXBcbiAgICBpbml0aWFsaXplQUkob3duZXI6IEdhbWVOb2RlLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KXtcbiAgICAgICAgdGhpcy5vd25lciA9IG93bmVyO1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVBsYXRmb3JtZXIoKTtcblxuICAgICAgICB0aGlzLnRpbGVtYXAgPSB0aGlzLm93bmVyLmdldFNjZW5lKCkuZ2V0VGlsZW1hcChvcHRpb25zLnRpbGVtYXApIGFzIE9ydGhvZ29uYWxUaWxlbWFwO1xuICAgICAgXG4gICAgICAgIHRoaXMuaW52ZW50b3J5ICA9IG9wdGlvbnMuaW52ZW50b3J5O1xuXG4gICAgICAgIHRoaXMubG9va0RpcmVjdGlvbiA9IG5ldyBWZWMyKCk7XG4gICAgICAgIFxuICAgICAgICAvL2kgZnJhbWUgdGltZXJcbiAgICAgICAgUGxheWVyQ29udHJvbGxlci5pbnZpbmNpYmlsaXR5VGltZXIgPSBuZXcgVGltZXIoMjAwMCk7XG5cbiAgICAgICAgLy9pbml0aWFsaXplIHRoZSBidWZmIHBvb2wgLSBlYWNoIGhhcyBzYW1lIHdlaWdodCBhdCBmaXJzdCBcbiAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbCA9IG5ldyBBcnJheSgpO1xuICAgICAgICBmb3IoIGxldCBpPTAgOyBpPCA0OyBpKyspe1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKEJ1ZmZDYXRlZ29yeS5BVFRBQ0spO1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKEJ1ZmZDYXRlZ29yeS5FWFRSQSk7XG4gICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmJ1ZmZQb29sLnB1c2goQnVmZkNhdGVnb3J5LkRPVCk7XG4gICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmJ1ZmZQb29sLnB1c2goQnVmZkNhdGVnb3J5LlNISUVMRCk7XG4gICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmJ1ZmZQb29sLnB1c2goQnVmZkNhdGVnb3J5LkhFQUxUSCk7XG4gICAgICAgIH1cblxuICAgICAgICAvL2luaXRpYWxpemUgZG90IHRpbWVyc1xuICAgICAgICB0aGlzLmJ1cm5UaW1lciA9IG5ldyBUaW1lcigxMDAwKTtcbiAgICAgICAgdGhpcy5ibGVlZFRpbWVyID0gbmV3IFRpbWVyKDEwMDApO1xuICAgICAgICB0aGlzLnBvaXNvblRpbWVyID0gbmV3IFRpbWVyKDEwMDApO1xuXG4gICAgICAgIC8vdG8gdGVzdCB0aGUgYnVmZnNcbiAgICAgICAgLy90aGlzLmFkZEJ1ZmYoIHt0eXBlOkJ1ZmZUeXBlLkhFQUxUSCwgdmFsdWU6MX0gKTtcbiAgICAgICAgLy90aGlzLmFkZEJ1ZmYoe3R5cGU6QnVmZlR5cGUuQlVSTiwgdmFsdWU6MSwgY2F0ZWdvcnk6QnVmZkNhdGVnb3J5LkRPVH0pO1xuICAgICAgICAvL3RoaXMuYWRkQnVmZih7dHlwZTpCdWZmVHlwZS5CTEVFRCwgdmFsdWU6MSwgY2F0ZWdvcnk6QnVmZkNhdGVnb3J5LkRPVH0pO1xuICAgICAgICAvL3RoaXMuYWRkQnVmZih7dHlwZTpCdWZmVHlwZS5QT0lTT04sIHZhbHVlOjEsIGNhdGVnb3J5OkJ1ZmZDYXRlZ29yeS5ET1R9KTtcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH1cblxuICAgIGluaXRpYWxpemVQbGF0Zm9ybWVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNwZWVkID0gNDAwO1xuXG4gICAgICAgIGxldCBpZGxlID0gbmV3IElkbGUodGhpcywgdGhpcy5vd25lcik7XG5cdFx0dGhpcy5hZGRTdGF0ZShQbGF5ZXJTdGF0ZXMuSURMRSwgaWRsZSk7XG5cdFx0bGV0IHdhbGsgPSBuZXcgV2Fsayh0aGlzLCB0aGlzLm93bmVyKTtcblx0XHR0aGlzLmFkZFN0YXRlKFBsYXllclN0YXRlcy5XQUxLLCB3YWxrKTtcblx0XHRsZXQganVtcCA9IG5ldyBKdW1wKHRoaXMsIHRoaXMub3duZXIpO1xuICAgICAgICB0aGlzLmFkZFN0YXRlKFBsYXllclN0YXRlcy5KVU1QLCBqdW1wKTtcbiAgICAgICAgbGV0IGZhbGwgPSBuZXcgRmFsbCh0aGlzLCB0aGlzLm93bmVyKTtcbiAgICAgICAgdGhpcy5hZGRTdGF0ZShQbGF5ZXJTdGF0ZXMuRkFMTCwgZmFsbCk7XG4gICAgICAgIFxuICAgICAgICB0aGlzLmluaXRpYWxpemUoUGxheWVyU3RhdGVzLklETEUpO1xuICAgIH1cblxuICAgIGNoYW5nZVN0YXRlKHN0YXRlTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIC8vIElmIHdlIGp1bXAgb3IgZmFsbCwgcHVzaCB0aGUgc3RhdGUgc28gd2UgY2FuIGdvIGJhY2sgdG8gb3VyIGN1cnJlbnQgc3RhdGUgbGF0ZXJcbiAgICAgICAgLy8gdW5sZXNzIHdlJ3JlIGdvaW5nIGZyb20ganVtcCB0byBmYWxsIG9yIHNvbWV0aGluZ1xuICAgICAgICBpZigoc3RhdGVOYW1lID09PSBQbGF5ZXJTdGF0ZXMuSlVNUCB8fCBzdGF0ZU5hbWUgPT09IFBsYXllclN0YXRlcy5GQUxMKSAmJiAhKHRoaXMuc3RhY2sucGVlaygpIGluc3RhbmNlb2YgSW5BaXIpKXtcbiAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzLnN0YXRlTWFwLmdldChzdGF0ZU5hbWUpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN1cGVyLmNoYW5nZVN0YXRlKHN0YXRlTmFtZSk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0c3VwZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgICAgIGlmKFBsYXllckNvbnRyb2xsZXIuaW52aW5jaWJpbGl0eVRpbWVyLmlzU3RvcHBlZCgpKXtcbiAgICAgICAgICAgIHRoaXMuaW52aW5jaWJsZSA9IGZhbHNlO1xuICAgICAgICB9XG5cblx0XHRpZih0aGlzLmN1cnJlbnRTdGF0ZSBpbnN0YW5jZW9mIEp1bXApe1xuXHRcdFx0RGVidWcubG9nKFwicGxheWVyc3RhdGVcIiwgXCJQbGF5ZXIgU3RhdGU6IEp1bXBcIik7XG5cdFx0fSBlbHNlIGlmICh0aGlzLmN1cnJlbnRTdGF0ZSBpbnN0YW5jZW9mIFdhbGspe1xuXHRcdFx0RGVidWcubG9nKFwicGxheWVyc3RhdGVcIiwgXCJQbGF5ZXIgU3RhdGU6IFdhbGtcIik7XG5cdFx0fSBlbHNlIGlmICh0aGlzLmN1cnJlbnRTdGF0ZSBpbnN0YW5jZW9mIElkbGUpe1xuXHRcdFx0RGVidWcubG9nKFwicGxheWVyc3RhdGVcIiwgXCJQbGF5ZXIgU3RhdGU6IElkbGVcIik7XG5cdFx0fSBlbHNlIGlmKHRoaXMuY3VycmVudFN0YXRlIGluc3RhbmNlb2YgRmFsbCl7XG4gICAgICAgICAgICBEZWJ1Zy5sb2coXCJwbGF5ZXJzdGF0ZVwiLCBcIlBsYXllciBTdGF0ZTogRmFsbFwiKTtcbiAgICAgICAgfVxuICAgICAgICBEZWJ1Zy5sb2coXCJwbGF5ZXIgc3BlZWRcIiwgXCJwbGF5ZXIgc3BlZWQ6IHg6IFwiICsgdGhpcy52ZWxvY2l0eS54ICsgXCIsIHk6XCIgKyB0aGlzLnZlbG9jaXR5LnkpO1xuICAgICAgICBEZWJ1Zy5sb2coXCJwbGF5ZXIgQ29vcmRzOlwiLCBcIlBsYXllciBDb29yZHM6XCIgK3RoaXMub3duZXIucG9zaXRpb24gKTtcblxuICAgICAgICAvL3Rlc3RpbmcgdGhlIGF0dGFja3MgaGVyZSwgbWF5IGJlIG1vdmVkIHRvIGFub3RoZXIgcGxhY2UgbGF0ZXJcbiAgICAgICAgaWYoSW5wdXRXcmFwcGVyLmlzQXR0YWNrSnVzdFByZXNzZWQoKSl7XG4gICAgICAgICAgICBsZXQgaXRlbSA9IHRoaXMuaW52ZW50b3J5LmdldEl0ZW0oKTtcbiAgICAgICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnBsYXkoXCJBVFRBQ0tcIiwgdHJ1ZSk7XG4gICAgICAgICAgICAvL1RPRE8gLSBnZXQgcHJvcGVyIGxvb2sgZGlyZWN0aW9uIFxuICAgICAgICAgICAgdGhpcy5sb29rRGlyZWN0aW9uLnggPSAoPFNwcml0ZT50aGlzLm93bmVyKS5pbnZlcnRYID8gLTEgOiAxO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgYW4gaXRlbSBpbiB0aGUgY3VycmVudCBzbG90LCB1c2UgaXRcbiAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgaXRlbS51c2UodGhpcy5vd25lciwgXCJwbGF5ZXJcIiwgdGhpcy5sb29rRGlyZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAvL3RoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7a2V5OiBcInN3b3JkXCIsIGxvb3A6IGZhbHNlLCBob2xkUmVmZXJlbmNlOiBmYWxzZX0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy9jaGVjayBkb3QgZWZmZWN0c1xuICAgICAgICBpZih0aGlzLmJ1cm5UaW1lci5pc1N0b3BwZWQoKSAmJiB0aGlzLmJ1cm5Db3VudGVyID4wKXtcbiAgICAgICAgICAgIHRoaXMuYnVybkNvdW50ZXIgLS07XG4gICAgICAgICAgICB0aGlzLmJ1cm5UaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgdGhpcy5kYW1hZ2UoNSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodGhpcy5wb2lzb25UaW1lci5pc1N0b3BwZWQoKSAmJiB0aGlzLnBvaXNvbkNvdW50ZXIgPjApe1xuICAgICAgICAgICAgdGhpcy5wb2lzb25Db3VudGVyIC0tO1xuICAgICAgICAgICAgdGhpcy5wb2lzb25UaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgdGhpcy5kYW1hZ2UoIE1hdGgucm91bmQodGhpcy5DVVJSRU5UX0hQLzMzKSApO1xuICAgICAgICB9XG4gICAgICAgIGlmKHRoaXMuYmxlZWRUaW1lci5pc1N0b3BwZWQoKSAmJiB0aGlzLmJsZWVkQ291bnRlciA+MCl7XG4gICAgICAgICAgICB0aGlzLmJsZWVkQ291bnRlciAtLTtcbiAgICAgICAgICAgIHRoaXMuYmxlZWRUaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgdGhpcy5kYW1hZ2UoIDIgKyBNYXRoLnJvdW5kKHRoaXMuQ1VSUkVOVF9IUC81MCkgKTtcbiAgICAgICAgfVxuICAgICAgICBcblx0fVxuXG4gICAgXG4gICAgLy8gVE9ETyAtIGZpZ3VyZSBvdXQgYXR0YWNrZXIgXG4gICAgZGFtYWdlKGRhbWFnZTogbnVtYmVyLCBhdHRhY2tlcj86IEdhbWVOb2RlKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmdvZE1vZGUpIHtcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJnb2Rtb2RlXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmKCAhdGhpcy5pbnZpbmNpYmxlICYmIFBsYXllclN0YXRlLmRhc2hUaW1lci5pc1N0b3BwZWQoKSl7XG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwidGFrZSBkYW1hZ2VcIik7XG4gICAgICAgICAgICAvL2kgZnJhbWUgaGVyZVxuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5pbnZpbmNpYmlsaXR5VGltZXIuc3RhcnQoKTtcbiAgICAgICAgICAgIHRoaXMuaW52aW5jaWJsZSA9IHRydWU7XG4gICAgICAgICAgICAvL3NoaWVsZCBhYnNvcmJzIHRoZSBkYW1hZ2UgYW5kIHNlbmRzIGRtZyBiYWNrIHRvIGF0dGFja2VyXG4gICAgICAgICAgICBpZih0aGlzLkNVUlJFTlRfU0hJRUxEID4gMCl7XG4gICAgICAgICAgICAgICAgbGV0IG5ld3NoaWVsZCA9IE1hdGgubWF4KDAsIHRoaXMuQ1VSUkVOVF9TSElFTEQgLSBkYW1hZ2UgKTsgLy9jYWxjdWxhdGUgdGhlIG5ldyBzaGllbGQgdmFsdWVcbiAgICAgICAgICAgICAgICBpZiggYXR0YWNrZXIgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgICAgICg8RW5lbXlBST5hdHRhY2tlci5fYWkpLmRhbWFnZSgodGhpcy5DVVJSRU5UX1NISUVMRCAtIG5ld3NoaWVsZCkgKiB0aGlzLnNoaWVsZERhbWFnZSk7IC8vZGFtYWdlIHRoZSBhdHRhY2tlciB0aGUgZG1nIHRha2VuIHRvIHNoaWVsZFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfU0hJRUxEID0gbmV3c2hpZWxkOyAvL3VwZGF0ZSBzaGllbGQgdmFsdWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgLy9pIGZyYW1lIGhlcmVcbiAgICAgICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmludmluY2liaWxpdHlUaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW52aW5jaWJsZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcImh1cnQgYW5pbVwiKTtcbiAgICAgICAgICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5wbGF5KFwiSFVSVFwiICk7XG4gICAgICAgICAgICAgICAgZGFtYWdlICo9IHRoaXMuZGFtYWdlX211bHRpcGxpZXI7XG4gICAgICAgICAgICAgICAgZGFtYWdlID0gcGFyc2VGbG9hdChkYW1hZ2UudG9QcmVjaXNpb24oMikpO1xuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9IUCAtPSBkYW1hZ2U7XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwiaHVydFwiLCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogZmFsc2V9KTtcblxuICAgICAgICAgICAgICAgIC8vaWYgcGxheWVyIGhhcyBzaGllbGQgYnVmZiBnaXZlIHRoZW0gc2hpZWxkIHdoZW4gZGFtYWdlZFxuICAgICAgICAgICAgICAgIGlmKHRoaXMuaGFzU2hpZWxkKXtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX1NISUVMRCArPSBkYW1hZ2UgKiAuNTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgICAgIGVsc2V7XG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwicGxheWVyIGlzIGludmluY2libGVcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLkNVUlJFTlRfSFAgPD0gMCl7XG4gICAgICAgICAgICB0aGlzLmxpdmVzIC0tO1xuICAgICAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24ucGxheShcIkRZSU5HXCIpO1xuICAgICAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24ucXVldWUoXCJERUFEXCIsIHRydWUsIFBsYXllcl9FdmVudHMuUExBWUVSX0tJTExFRCk7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuUExBWUVSX0tJTExFRCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnaXZlcyB0aGUgcGxheWVyIGEgY2VydGFpbiBhbW91bnQgb2Ygc2hpZWxkXG4gICAgICogQHBhcmFtIHNoaWVsZCBhbW91bnQgb2Ygc2hpZWxkIHRvIGFkZCB0byBwbGF5ZXJcbiAgICAgKi9cbiAgICBhZGRTaGllbGQoc2hpZWxkIDogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5DVVJSRU5UX1NISUVMRCA9ICh0aGlzLkNVUlJFTlRfU0hJRUxEICsgc2hpZWxkKSAlIHRoaXMuTUFYX1NISUVMRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnaXZlcyBoZWFsdGggdG8gdGhlIHBsYXllclxuICAgICAqIEBwYXJhbSBoZWFsdGggaGVhbHRoIHRvIGdpdmUgcGxheWVyXG4gICAgICovXG4gICAgYWRkSGVhbHRoKGhlYWx0aCA6IG51bWJlcil7XG4gICAgICAgIHRoaXMuQ1VSUkVOVF9IUCArPSBoZWFsdGg7XG4gICAgICAgIGlmKHRoaXMuQ1VSUkVOVF9IUCA+IHRoaXMuTUFYX0hQICl7XG4gICAgICAgICAgICB0aGlzLkNVUlJFTlRfSFAgPSB0aGlzLk1BWF9IUCA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnaXZlcyB0aGUgcGxheWVyIGV4cFxuICAgICAqIEBwYXJhbSBleHAgYW1vdW50IG9mIGV4cCB0byBnaXZlIHRoZSBwbGF5ZXJcbiAgICAgKi9cbiAgICBnaXZlRXhwKGV4cDogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5DVVJSRU5UX0VYUCArPSBleHA7XG4gICAgICAgIC8vaWYgPiB0aGFuIG1heCBleHAgbGV2ZWwgdXAgKGdpdmUgYnVmZilcbiAgICAgICAgaWYodGhpcy5DVVJSRU5UX0VYUCA+PSB0aGlzLk1BWF9FWFApe1xuICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0VYUCAtPSB0aGlzLk1BWF9FWFA7XG4gICAgICAgICAgICB0aGlzLk1BWF9FWFAgKz0gNTA7IC8vaW5jcmVhc2UgbWF4IGV4cCBuZWVkZWQgZm9yIGxldmVsIHVwXG4gICAgICAgICAgICB0aGlzLmxldmVsKysgO1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwibGV2ZWxfdXBcIiwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IGZhbHNlfSk7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuR0lWRV9SRUdVTEFSX0JVRkYpO1xuICAgICAgICB9XG4gICAgfVxuICAgIFxuXG4gICAgLyoqXG4gICAgICogZ2VuZXJhdGVzIGFuIGFycmF5IG9mIHJlZ3VsYXIgYnVmZnNcbiAgICAgKiBAcGFyYW0gdmFsIG9wdGlvbmFsIHZhbHVlIHRvIGdpdmUgYnVmZlxuICAgICAqIEByZXR1cm5zIGFycmF5IG9mIHRocmVlIGJ1ZmZzXG4gICAgICovXG4gICAgZ2VuZXJhdGVSZWd1bGFyQnVmZnMoIHZhbD8gOiBudW1iZXIpIDogQnVmZltde1xuXG4gICAgICAgIC8vcmFuZG9tIG51bWJlciBmcm9tIDUgdG8gMTUgaWYgbm8gdmFsdWUgZ2l2ZW5cbiAgICAgICAgbGV0IG51bSA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqMTApICs1O1xuICAgICAgICBudW0gPSBNYXRoLnJvdW5kKG51bSk7XG4gICAgICAgIGlmKHR5cGVvZiB2YWwgIT09ICd1bmRlZmluZWQnKXtcbiAgICAgICAgICAgIG51bSA9IHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBidWZmcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICBidWZmcy5wdXNoKHt0eXBlOkJ1ZmZUeXBlLkZMQVRfQVRLLCB2YWx1ZTpudW0sIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRVhUUkF9LFxuICAgICAgICAgICAge3R5cGU6QnVmZlR5cGUuU1BFRUQsIHZhbHVlOm51bSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5FWFRSQX0sXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5GTEFUX0hFQUxUSCwgdmFsdWU6bnVtLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LlNISUVMRH0sXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5SQU5HRSwgdmFsdWU6bnVtLzEwMCwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5BVFRBQ0ssIHN0cmluZzogXCJcXG5cXG5JbmNyZWFzZSByYW5nZSBcXG5ieSBcIitudW0rXCIlXCJ9LFxuICAgICAgICAgICAge3R5cGU6QnVmZlR5cGUuQVRLU1BFRUQsIHZhbHVlOm51bSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5BVFRBQ0t9LFxuICAgICAgICApO1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIC8vc2h1ZmZsZSBwb29sIG9mIGJ1ZmZzXG4gICAgICAgIGJ1ZmZzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSk7XG4gICAgICAgIC8vIEdldCBzdWItYXJyYXkgb2YgZmlyc3QgMyBlbGVtZW50cyBhZnRlciBzaHVmZmxlZFxuICAgICAgICBsZXQgc2VsZWN0ZWQgPSBidWZmcy5zbGljZSgwLCAzKTsgLy8zIGJ1ZmYgY2F0ZWdvcmllc1xuICAgICAgICByZXR1cm4gc2VsZWN0ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZ2VuZXJhdGVzIGFuIGFycmF5IG9mIHNwZWNpYWwgYnVmZnNcbiAgICAgKiBAcGFyYW0gdmFsIG9wdGlvbmFsIHZhbHVlIHRvIGdpdmUgdGhlIGJ1ZmZcbiAgICAgKiBAcmV0dXJucyBhcnJheSBvZiAzIEJ1ZmZzXG4gICAgICovXG4gICAgZ2VuZXJhdGVTcGVjaWFsQnVmZnMoIHZhbD8gOiBudW1iZXIpIDogQnVmZltde1xuICAgICAgICAvL3NodWZmbGUgcG9vbCBvZiBidWZmIGNhdGVnb3JpZXMgXG4gICAgICAgIFBsYXllckNvbnRyb2xsZXIuYnVmZlBvb2wuc29ydCgoKSA9PiAwLjUgLSBNYXRoLnJhbmRvbSgpKTtcblxuICAgICAgICAvLyBHZXQgc3ViLWFycmF5IG9mIGZpcnN0IDMgZWxlbWVudHMgYWZ0ZXIgc2h1ZmZsZWRcbiAgICAgICAgbGV0IHNodWZmbGVkID0gUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5zbGljZSgwLCAzKTsgLy8zIGJ1ZmYgY2F0ZWdvcmllc1xuXG4gICAgICAgIC8vcmFuZG9tIG51bWJlciBmcm9tIDUgdG8gMTUgaWYgbm8gdmFsdWUgZ2l2ZW5cbiAgICAgICAgbGV0IG51bSA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqMTApICs1O1xuICAgICAgICBudW0gPSBNYXRoLnJvdW5kKG51bSk7XG4gICAgICAgIGlmKHR5cGVvZiB2YWwgIT09ICd1bmRlZmluZWQnKXtcbiAgICAgICAgICAgIG51bSA9IHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vVE9ETyAtIGltcGxlbWVudCBiZXR0ZXIgYnVmZiBnZW5lcnRpb24gLSBzb21lIGJ1ZmZzIGRvbnQgd2FudCBtdWx0aXBsZSBvZlxuICAgICAgICBsZXQgYXR0YWNrQnVmZnMgOiBCdWZmW10gPSBbXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5QRVJDRU5UX0FUSywgdmFsdWU6bnVtLzEwMCwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5BVFRBQ0ssIHN0cmluZzpcIlxcblxcbkluY3JlYXNlIEF0dGFjayBcXG5ieVwiK251bStcIiVcIn1cbiAgICAgICAgXTtcblxuICAgICAgICBsZXQgZG90QnVmZnMgOiBCdWZmW10gPSBbXG4gICAgICAgIF07XG4gICAgICAgIGlmKCF0aGlzLmhhc0JsZWVkKXtcbiAgICAgICAgICAgIGRvdEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuQkxFRUQsIHZhbHVlOjEsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRE9ULCBzdHJpbmc6IFwiXFxuXFxuWW91ciBoaXRzIFxcbmFwcGx5IEJsZWVkXCJ9KTtcbiAgICAgICAgfVxuICAgICAgICBpZighdGhpcy5oYXNCdXJuKXtcbiAgICAgICAgICAgIGRvdEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuQlVSTiwgdmFsdWU6MSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5ET1QsIHN0cmluZzogXCJcXG5cXG5Zb3VyIGhpdHMgXFxuYXBwbHkgQnVyblwifSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoIXRoaXMuaGFzUG9pc29uKXtcbiAgICAgICAgICAgIGRvdEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuUE9JU09OLCB2YWx1ZToxLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkRPVCwgc3RyaW5nOiBcIlxcblxcbllvdXIgaGl0cyBcXG5hcHBseSBwb2lzb25cIn0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9vbmx5IGFkZCBleHRyYSBkb3QgaWYgYXQgbGVhc3Qgb25lIGRvdCBpcyBhY3F1aXJlZFxuICAgICAgICBmb3IobGV0IGk9ZG90QnVmZnMubGVuZ3RoOyBpPCAzIDsgaSsrKXtcbiAgICAgICAgICAgIGRvdEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuRVhUUkFfRE9ULCB2YWx1ZTpudW0sIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRE9ULCBzdHJpbmc6IFwiXFxuXFxuSW5jcmVhc2UgeW91ciBcXG5ET1QgZGFtYWdlXCJ9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIFxuICAgICAgICBsZXQgc2hpZWxkQnVmZnMgOiBCdWZmW10gPSBbXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5QRVJDRU5UX0hFQUxUSCwgdmFsdWU6bnVtLzEwMCwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5TSElFTEQsIHN0cmluZzogXCJcXG5cXG5JbmNyZWFzZSBtYXggaHAgXFxuYnkgXCIrbnVtK1wiJVwifSxcbiAgICAgICAgXTtcbiAgICAgICAgLy9pZiBwbGF5ZXIgZG9lc250IGhhdmUgc2hpZWxkIGJ1ZmYsIGdpdmUgdGhlbSB0aGUgb3B0aW9uLCBvdGhlcndpc2UgZ2l2ZSBidWZmIHNoaWVsZCBvcHRpb25cbiAgICAgICAgaWYoIXRoaXMuaGFzU2hpZWxkKXtcbiAgICAgICAgICAgIHNoaWVsZEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuU0hJRUxELCB2YWx1ZToxLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LlNISUVMRCwgc3RyaW5nOiBcIlxcblxcbkdhaW4gU2hpZWxkIFxcbldoZW4gRGFtYWdlZCBcXG4gU2hpZWxkcyByZXR1cm4gXFxudGhlIGRhbWFnZSB0YWtlbiBcXG50byBhdHRhY2tlclwifSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZXtcbiAgICAgICAgICAgIHNoaWVsZEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuU0hJRUxEX0RNRywgdmFsdWU6bnVtLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LlNISUVMRCwgc3RyaW5nOiBcIlxcblxcbkluY3JlYXNlIGRhbWFnZSBcXG5yZXR1cm5lZCBieSBzaGllbGRcIn0pO1xuICAgICAgICB9XG5cblxuICAgICAgICBsZXQgaGVhbHRoQnVmZnMgOiBCdWZmW10gPSBbXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5ERUYsIHZhbHVlOiBudW0vMTAwLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkhFQUxUSCwgc3RyaW5nOiBcIlxcblxcbkRlY3JlYXNlIGRhbWFnZSBcXG50YWtlbiBieSBcIitudW0rXCIlXCJ9XG4gICAgICAgIF07XG4gICAgICAgIGlmKCF0aGlzLmZ1bGxIcEJvbnVzKXtcbiAgICAgICAgICAgIGhlYWx0aEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuRlVMTEhQQk9OVVNETUcsIHZhbHVlOjEsIGNhdGVnb3J5OkJ1ZmZDYXRlZ29yeS5IRUFMVEgsIHN0cmluZzpcIlxcblxcbkRlYWwgMTB4IGRhbWFnZSBcXG4gd2hlbiBhdCBmdWxsIEhQXCJ9KVxuXG4gICAgICAgIH1cbiAgICAgICAgaWYoIXRoaXMuaGFzTGlmZXN0ZWFsKXtcbiAgICAgICAgICAgIGhlYWx0aEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuTElGRVNURUFMLCB2YWx1ZToxLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkhFQUxUSCwgc3RyaW5nOlwiXFxuXFxuR2FpbiBsaWZlc3RlYWxcIn0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2V7XG4gICAgICAgICAgICBoZWFsdGhCdWZmcy5wdXNoKHt0eXBlOkJ1ZmZUeXBlLkxJRkVTVEVBTEJVRkYsIHZhbHVlOm51bS8xMDAsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuSEVBTFRILCBzdHJpbmc6XCJcXG5cXG5JbmNyZWFzZSBMaWZlc3RlYWwgXFxuc3RyZW5ndGggYnkgXCIrIG51bSsgXCIlXCJ9KTtcbiAgICAgICAgfVxuXG5cbiAgICAgICAgbGV0IGV4dHJhQnVmZnMgOiBCdWZmW10gPSBbXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5FWFRSQUxJRkUsIHZhbHVlOjEsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRVhUUkEsIHN0cmluZzogXCJcXG5cXG5HYWluIGFuIFxcbkV4dHJhIExpZmVcIn0sXG4gICAgICAgIF07XG4gICAgICAgIGlmKCF0aGlzLmhhc09uZVNob3QpeyAgIC8vb25seSBhZGQgb25lc2hvdCBidWZmIGlmIGl0IGlzbnQgYWxyZWFkeSBpbmNsdWRlZCBcbiAgICAgICAgICAgIGV4dHJhQnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5PTkVTSE9ULCB2YWx1ZToxLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkVYVFJBLCBzdHJpbmc6IFwiXFxuXFxuWW91ciBoaXRzIGh1cnQgXFxuMTAweCBtb3JlIGJ1dCBcXG55b3VyIG1heCBoZWFsdGggXFxuaXMgc2V0IHRvIDEgXCJ9KTtcbiAgICAgICAgfTtcblxuXG4gICAgICAgIGxldCBzZWxlY3RlZCA9IG5ldyBBcnJheSgpO1xuICAgICAgICB3aGlsZSggc2h1ZmZsZWQubGVuZ3RoICE9IDApe1xuICAgICAgICAgICAgbGV0IGNhdCA9IHNodWZmbGVkLnBvcCgpO1xuICAgICAgICAgICAgc3dpdGNoKGNhdCl7XG4gICAgICAgICAgICAgICAgY2FzZSBCdWZmQ2F0ZWdvcnkuQVRUQUNLOlxuICAgICAgICAgICAgICAgICAgICBhdHRhY2tCdWZmcy5zb3J0KCgpID0+IDAuNSAtIE1hdGgucmFuZG9tKCkpO1xuICAgICAgICAgICAgICAgICAgICBpZihhdHRhY2tCdWZmcy5sZW5ndGggPT0gMCl7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKHt0eXBlOkJ1ZmZUeXBlLlBFUkNFTlRfSEVBTFRILCB2YWx1ZTpudW0vMTAwLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkFUVEFDSywgc3RyaW5nOiBcIlxcblxcbkluY3JlYXNlIGF0dGFjayBcXG5ieVwiK251bStcIiVcIn0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKGF0dGFja0J1ZmZzLnBvcCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEJ1ZmZDYXRlZ29yeS5ET1Q6XG4gICAgICAgICAgICAgICAgICAgIGRvdEJ1ZmZzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRvdEJ1ZmZzLmxlbmd0aCA9PSAwKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goe3R5cGU6QnVmZlR5cGUuRVhUUkFfRE9ULCB2YWx1ZTpudW0sIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRE9ULCBzdHJpbmc6IFwiXFxuXFxuSW5jcmVhc2UgeW91ciBcXG5ET1QgZGFtYWdlXCJ9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQucHVzaChkb3RCdWZmcy5wb3AoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBCdWZmQ2F0ZWdvcnkuRVhUUkE6XG4gICAgICAgICAgICAgICAgICAgIGV4dHJhQnVmZnMuc29ydCgoKSA9PiAwLjUgLSBNYXRoLnJhbmRvbSgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoZXh0cmFCdWZmcy5sZW5ndGggPT0wICl7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKHt0eXBlOkJ1ZmZUeXBlLkVYVFJBTElGRSwgdmFsdWU6MSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5FWFRSQSwgc3RyaW5nOiBcIlxcblxcbkdhaW4gYW4gXFxuRXh0cmEgTGlmZVwifSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goZXh0cmFCdWZmcy5wb3AoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBCdWZmQ2F0ZWdvcnkuSEVBTFRIOlxuICAgICAgICAgICAgICAgICAgICBoZWFsdGhCdWZmcy5zb3J0KCgpID0+IDAuNSAtIE1hdGgucmFuZG9tKCkpO1xuICAgICAgICAgICAgICAgICAgICBpZihoZWFsdGhCdWZmcy5sZW5ndGggPT0gMCl7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKHt0eXBlOkJ1ZmZUeXBlLkRFRiwgdmFsdWU6IG51bS8xMDAsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuSEVBTFRILCBzdHJpbmc6IFwiXFxuXFxuRGVjcmVhc2UgZGFtYWdlXFxuIHRha2VuIGJ5IFwiK251bStcIiVcIn0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKGhlYWx0aEJ1ZmZzLnBvcCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEJ1ZmZDYXRlZ29yeS5TSElFTEQ6XG4gICAgICAgICAgICAgICAgICAgIHNoaWVsZEJ1ZmZzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNoaWVsZEJ1ZmZzLmxlbmd0aCA9PTAgKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goe3R5cGU6QnVmZlR5cGUuRkxBVF9IRUFMVEgsIHZhbHVlOm51bSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5TSElFTER9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQucHVzaChzaGllbGRCdWZmcy5wb3AoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2VsZWN0ZWQ7XG4gICAgfVxuXG5cblxuICAgIFxuICAgIC8qKlxuXHQgKiBBZGQgZ2l2ZW4gYnVmZiB0byB0aGUgcGxheWVyXG5cdCAqIEBwYXJhbSBidWZmIEdpdmVuIGJ1ZmZcbiAgICAgKiBAcGFyYW0gaW5pdCB3aGV0aGVyIG9yIG5vdCB0aGlzIGlzIGJlaW5nIHVzZWQgZHVyaW5nIHRoZSBpbml0aWFsaXphdGlvbiBvZiB0aGUgcGxheWVyXG5cdCAqL1xuICAgIGFkZEJ1ZmYoYnVmZjogQnVmZiwgaW5pdD8gOkJvb2xlYW4gKTogdm9pZCB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgLy9hZGQgYnVmZiB0byBhcnJheSBvZiBhcHBsaWVkIGJ1ZmZzIGlmIG5vdCBiZWluZyB1c2VkIHRvIGluaXRcbiAgICAgICAgaWYoaW5pdCA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIC8vaW5jcmVhc2Ugd2VpZ2h0IG9mIHNlbGVjdGVkIGJ1ZmYgY2F0ZWdvcnlcbiAgICAgICAgICAgIFBsYXllckNvbnRyb2xsZXIuYnVmZlBvb2wucHVzaChidWZmLmNhdGVnb3J5KTtcbiAgICAgICAgICAgIFBsYXllckNvbnRyb2xsZXIuYXBwbGllZEJ1ZmZzLnB1c2goYnVmZik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIWluaXQpe1xuICAgICAgICAgICAgLy9pbmNyZWFzZSB3ZWlnaHQgb2Ygc2VsZWN0ZWQgYnVmZiBjYXRlZ29yeVxuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKGJ1ZmYuY2F0ZWdvcnkpO1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5hcHBsaWVkQnVmZnMucHVzaChidWZmKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUT0RPXG4gICAgICAgIGxldCBpdGVtID0gdGhpcy5pbnZlbnRvcnkuZ2V0SXRlbSgpO1xuICAgICAgICBzd2l0Y2goYnVmZi50eXBlKXtcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuRkxBVF9IRUFMVEg6XG4gICAgICAgICAgICAgICAgLy90aGlzLkNVUlJFTlRfQlVGRlMuaHAgKz0gYnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfSFAgKz0gYnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLk1BWF9IUCArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5QRVJDRU5UX0hFQUxUSDpcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfSFAgKj0gKDErYnVmZi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5NQVhfSFAgKj0gKDErYnVmZi52YWx1ZSkgO1xuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9IUCA9IE1hdGgucm91bmQodGhpcy5DVVJSRU5UX0hQKTtcbiAgICAgICAgICAgICAgICB0aGlzLk1BWF9IUCA9IE1hdGgucm91bmQodGhpcy5NQVhfSFApO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5GTEFUX0FUSzpcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfQVRLICs9YnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuUEVSQ0VOVF9BVEs6XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0FUSyAqPWJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0FUSyA9IE1hdGgucm91bmQodGhpcy5DVVJSRU5UX0FUSyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlNQRUVEOlxuICAgICAgICAgICAgICAgIHRoaXMuc3BlZWQgKz0gYnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuREVGOlxuICAgICAgICAgICAgICAgIHRoaXMuZGFtYWdlX211bHRpcGxpZXIgKj0gKDEtYnVmZi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlJBTkdFOlxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICg8V2VhcG9uPml0ZW0pLkVYVFJBX1JBTkdFICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5CTEVFRDpcbiAgICAgICAgICAgICAgICB0aGlzLmhhc0JsZWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuQlVSTjpcbiAgICAgICAgICAgICAgICB0aGlzLmhhc0J1cm4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5QT0lTT046XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNQb2lzb24gPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5FWFRSQV9ET1Q6XG4gICAgICAgICAgICAgICAgdGhpcy5leHRyYURvdERtZyArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5TSElFTEQ6XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNTaGllbGQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkFUS1NQRUVEOlxuICAgICAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29vbGRvd25NdWx0aXBsaWVyIC09IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIC8vcmVkdWNlIGNvb2xkb3dudGltZXIgXG4gICAgICAgICAgICAgICAgICAgICg8V2VhcG9uPml0ZW0pLmNvb2xkb3duVGltZXIgPSBuZXcgVGltZXIoKDxXZWFwb24+aXRlbSkuY29vbGRvd24gKiB0aGlzLmNvb2xkb3duTXVsdGlwbGllciApXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5TSElFTERfRE1HOlxuICAgICAgICAgICAgICAgIHRoaXMuc2hpZWxkRGFtYWdlICs9IGJ1ZmYudmFsdWUgO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5FWFRSQUxJRkU6XG4gICAgICAgICAgICAgICAgdGhpcy5saXZlcyArKztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuTElGRVNURUFMOlxuICAgICAgICAgICAgICAgIHRoaXMuaGFzTGlmZXN0ZWFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmxpZmVzdGVhbHJhdGlvID0gLjI7IC8vMjAlIGxpZmVzdGVhbFxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5MSUZFU1RFQUxCVUZGOlxuICAgICAgICAgICAgICAgIHRoaXMubGlmZXN0ZWFscmF0aW8gKz0gYnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuT05FU0hPVDpcbiAgICAgICAgICAgICAgICB0aGlzLk1BWF9IUCA9IDE7XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0hQID0gMTtcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfQVRLICo9IDEwMDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuRlVMTEhQQk9OVVNETUc6XG4gICAgICAgICAgICAgICAgdGhpcy5mdWxsSHBCb251cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBcbiAgICAgKiBAcmV0dXJucyByZWNvcmQgb2YgdGhlIHBsYXllciBzdGF0c1xuICAgICAqL1xuICAgIGdldFN0YXRzKCk6IFJlY29yZDxzdHJpbmcsIGFueT57XG4gICAgICAgIGxldCBzdGF0cyA9IHt9IGFzIFJlY29yZDxzdHJpbmcsYW55PjtcbiAgICAgICAgc3RhdHMuQ1VSUkVOVF9IUCA9IHRoaXMuQ1VSUkVOVF9IUDtcbiAgICAgICAgc3RhdHMuQ1VSUkVOVF9BVEsgPSB0aGlzLkNVUlJFTlRfQVRLO1xuICAgICAgICBzdGF0cy5DVVJSRU5UX1NISUVMRCA9IHRoaXMuQ1VSUkVOVF9TSElFTEQ7XG4gICAgICAgIHN0YXRzLkNVUlJFTlRfRVhQID0gdGhpcy5DVVJSRU5UX0VYUDtcblxuICAgICAgICByZXR1cm4gXG4gICAgfVxuICAgICAgICBcblxuICAgIHRvU3RyaW5nKCk6IHN0cmluZ3tcbiAgICAgICAgbGV0IHMgPSBcIkhQOiBcIiArIHRoaXMuQ1VSUkVOVF9IUCArXCIvXCIrdGhpcy5NQVhfSFArXG4gICAgICAgICAgICAgICAgXCJcXG5BVEs6IFwiICsgdGhpcy5DVVJSRU5UX0FUSyArXG4gICAgICAgICAgICAgICAgXCJcXG5TcGVlZDogXCIgKyB0aGlzLnNwZWVkICtcbiAgICAgICAgICAgICAgICBcIlxcbkRhbWFnZSBSYXRpbzogXCIgKyB0aGlzLmRhbWFnZV9tdWx0aXBsaWVyICtcbiAgICAgICAgICAgICAgICBcIlxcbkVuZW1pZXMgS2lsbGVkOiBcIiArIHRoaXMuZW5lbWllc0tpbGxlZCArIFxuICAgICAgICAgICAgICAgIFwiXFxuU3dvcmQgRWZmZWN0czpcIiArXG4gICAgICAgICAgICAgICAgKHRoaXMuaGFzQmxlZWQgPyBcIlxcbiAgQmxlZWQsXCIgOiBcIiAgXCIpICsgXG4gICAgICAgICAgICAgICAgKHRoaXMuaGFzQnVybiA/IFwiIEJ1cm4sXCIgOiBcIlwiKSArIFxuICAgICAgICAgICAgICAgICh0aGlzLmhhc1BvaXNvbiA/IFwiIFBvaXNvbixcIiA6IFwiXCIpICsgXG4gICAgICAgICAgICAgICAgKHRoaXMuaGFzU2hpZWxkID8gXCIgU2hpZWxkLFwiIDpcIlwiKSArIFxuICAgICAgICAgICAgICAgICh0aGlzLmZ1bGxIcEJvbnVzID8gXCIgRnVsbEhlYWx0aCBkZWFsIHgxMCBEbWdcIiA6IFwiXCIpICtcbiAgICAgICAgICAgICAgICAodGhpcy5oYXNMaWZlc3RlYWwgPyBcIiBMaWZlc3RlYWwsXCIgOiBcIlwiKSArXG4gICAgICAgICAgICAgICAgKHRoaXMuaGFzT25lU2hvdCA/IFwiIEF0ayB4IDEwMCwgbWF4aHAgc2V0IHRvIDFcIiA6IFwiXCIpIDtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgSW5BaXIgZnJvbSBcIi4vSW5BaXJcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uLy4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IFBsYXllclN0YXRlIGZyb20gXCIuL1BsYXllclN0YXRlXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgeyBHYW1lU3RhdGUgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFsbCBleHRlbmRzIEluQWlyIHtcbiAgICBvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0Ly8gdGhpcy5vd25lci5hbmltYXRpb24ucGxheShcIkZBTExcIiwgdHJ1ZSk7XG5cdH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHRpZihJbnB1dFdyYXBwZXIuZ2V0U3RhdGUoKSA9PT0gR2FtZVN0YXRlLkdBTUlORyl7XG5cdFx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7a2V5OiBcImRhc2hcIiwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IGZhbHNlfSk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiREFTSFwiKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRpZiAodGhpcy5wYXJlbnQuaW52aW5jaWJsZSkge1xuXHRcdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSFVSVFwiKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiRkFMTFwiLCB0cnVlKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly9UT0RPIC0gdGVzdGluZyBkb3VibGVqdW1wLCBtYXkgaGF2ZSB0byBtb3ZlIHRvIEluQWlyIGluc3RlYWRcblx0XHQvLyBJZiB3ZSBqdW1wLCBtb3ZlIHRvIHRoZSBKdW1wIHN0YXRlLCBnaXZlIGEgYnVyc3Qgb2YgdXB3YXJkcyB2ZWxvY2l0eVxuXHRcdGlmKCB0aGlzLnBhcmVudC5haXJqdW1wcz4wICYmIElucHV0V3JhcHBlci5pc0p1bXBKdXN0UHJlc3NlZCgpKXtcblx0XHRcdHRoaXMucGFyZW50LmFpcmp1bXBzIC0tO1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdH0gXG5cblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcbiAgICB9XG4gICAgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnN0b3AoKTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbn0iLCJpbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCB7IFBsYXllclN0YXRlcyB9IGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgT25Hcm91bmQgZnJvbSBcIi4vT25Hcm91bmRcIjtcbmltcG9ydCBQbGF5ZXJTdGF0ZSBmcm9tIFwiLi9QbGF5ZXJTdGF0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJZGxlIGV4dGVuZHMgT25Hcm91bmQge1xuXHRvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0dGhpcy5wYXJlbnQuc3BlZWQgPSB0aGlzLnBhcmVudC5NSU5fU1BFRUQ7XG5cdH1cblxuXHRcblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0XG4gICAgICAgIC8vKFwiaWRsZSBhbmltXCIpO1xuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIlBsYXlpbmcgZGFzaFwiKTtcblx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJEQVNIXCIpO1xuXHRcdH1cblx0XHRlbHNlIHtcbiAgICAgICAgXHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSURMRVwiLCB0cnVlKTtcblx0XHR9XG5cblx0XHRsZXQgZGlyID0gdGhpcy5nZXRJbnB1dERpcmVjdGlvbigpO1xuXG5cdFx0aWYoIWRpci5pc1plcm8oKSAmJiBkaXIueSA9PT0gMCl7XG5cdFx0XHR0aGlzLmZpbmlzaGVkKFBsYXllclN0YXRlcy5XQUxLKTtcblx0XHR9XG5cdFx0XG5cdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IDA7XG5cdFx0c3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cdH1cblxuXHRvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG5cdFx0dGhpcy5vd25lci5hbmltYXRpb24uc3RvcCgpO1xuXHRcdHJldHVybiB7fTtcblx0fVxufSIsImltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCB7IFBsYXllclN0YXRlcyB9IGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgUGxheWVyU3RhdGUgZnJvbSBcIi4vUGxheWVyU3RhdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgSW5BaXIgZXh0ZW5kcyBQbGF5ZXJTdGF0ZSB7XG4gICAgXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIGxldCBkaXIgPSB0aGlzLmdldElucHV0RGlyZWN0aW9uKCk7XG5cbiAgICAgICAgaWYoZGlyLnggIT09IDApe1xuXHRcdFx0KDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IE1hdGhVdGlscy5zaWduKGRpci54KSA8IDA7XG5cdFx0fVxuICAgICAgICBcblx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS54ICs9IGRpci54ICogKHRoaXMucGFyZW50LnNwZWVkKS8zLjUgLSAwLjMqdGhpcy5wYXJlbnQudmVsb2NpdHkueDtcblxuXG4gICAgICAgIGlmKHRoaXMub3duZXIub25Hcm91bmQpe1xuXHRcdFx0dGhpcy5maW5pc2hlZChQbGF5ZXJTdGF0ZXMuUFJFVklPVVMpO1xuXHRcdH1cbiAgICB9XG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgeyBFYXNlRnVuY3Rpb25UeXBlIH0gZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL0Vhc2VGdW5jdGlvbnNcIjtcbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uLy4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IHsgUGxheWVyU3RhdGVzIH0gZnJvbSBcIi4uL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBJbkFpciBmcm9tIFwiLi9JbkFpclwiO1xuaW1wb3J0IFBsYXllclN0YXRlIGZyb20gXCIuL1BsYXllclN0YXRlXCI7XG5pbXBvcnQgeyBHYW1lU3RhdGUgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEp1bXAgZXh0ZW5kcyBJbkFpciB7XG5cdG93bmVyOiBBbmltYXRlZFNwcml0ZTtcblxuXHRvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHR0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJqdW1wXCIsIGxvb3A6IGZhbHNlLCBob2xkUmVmZXJlbmNlOiBmYWxzZX0pO1xuXHR9XG5cblx0XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYgKCFQbGF5ZXJTdGF0ZS5kYXNoVGltZXIuaXNTdG9wcGVkKCkpIHtcblx0XHRcdGlmKElucHV0V3JhcHBlci5nZXRTdGF0ZSgpID09PSBHYW1lU3RhdGUuR0FNSU5HKXtcblx0XHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwiZGFzaFwiLCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogZmFsc2V9KTtcblx0XHRcdH1cblx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJEQVNIXCIpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmICh0aGlzLnBhcmVudC5pbnZpbmNpYmxlKSB7XG5cdFx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJIVVJUXCIpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJKVU1QXCIsIHRydWUpO1xuXHRcdFx0fVxuXHRcdH1cblxuXG5cdFx0aWYodGhpcy5vd25lci5vbkNlaWxpbmcpe1xuXHRcdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueSA9IDA7XG5cdFx0fVxuXG5cdFx0Ly9UT0RPIC0gdGVzdGluZyBkb3VibGVqdW1wLCBtYXkgaGF2ZSB0byBtb3ZlIHRvIEluQWlyIGluc3RlYWRcblx0XHQvLyBJZiB3ZSBqdW1wLCBtb3ZlIHRvIHRoZSBKdW1wIHN0YXRlLCBnaXZlIGEgYnVyc3Qgb2YgdXB3YXJkcyB2ZWxvY2l0eVxuXHRcdGlmKCB0aGlzLnBhcmVudC5haXJqdW1wcz4wICYmIElucHV0V3JhcHBlci5pc0p1bXBKdXN0UHJlc3NlZCgpKXtcblx0XHRcdHRoaXMucGFyZW50LmFpcmp1bXBzIC0tO1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdFx0XG5cdFx0fSBcblxuXHRcdC8vIElmIHdlJ3JlIGZhbGxpbmcsIGdvIHRvIHRoZSBmYWxsIHN0YXRlXG5cdFx0aWYodGhpcy5wYXJlbnQudmVsb2NpdHkueSA+PSAwKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoUGxheWVyU3RhdGVzLkZBTEwpO1xuXHRcdH1cblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcblx0fVxuXG5cdG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5zdG9wKCk7XG5cdFx0cmV0dXJuIHt9O1xuXHR9XG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IEdhbWUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0xvb3AvR2FtZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IHsgR2FtZVN0YXRlIH0gZnJvbSBcIi4uLy4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi8uLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcbmltcG9ydCBQbGF5ZXJTdGF0ZSBmcm9tIFwiLi9QbGF5ZXJTdGF0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBPbkdyb3VuZCBleHRlbmRzIFBsYXllclN0YXRlIHtcblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vcmVzZXQgYWlyanVtcHNcblx0XHR0aGlzLnBhcmVudC5haXJqdW1wcyA9IHRoaXMucGFyZW50Lk1BWF9haXJqdW1wcztcblxuXHRcdGlmKHRoaXMucGFyZW50LnZlbG9jaXR5LnkgPiAwKXtcblx0XHRcdHRoaXMucGFyZW50LnZlbG9jaXR5LnkgPSAwO1xuXHRcdH1cblxuXG5cdFx0XG5cblx0XHRsZXQgZGlyZWN0aW9uID0gdGhpcy5nZXRJbnB1dERpcmVjdGlvbigpO1xuXG5cdFx0aWYoZGlyZWN0aW9uLnggIT09IDApe1xuXHRcdFx0KDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IE1hdGhVdGlscy5zaWduKGRpcmVjdGlvbi54KSA8IDA7XG5cdFx0fVxuXG5cdFxuXHRcdC8vIElmIHdlIGp1bXAsIG1vdmUgdG8gdGhlIEp1bXAgc3RhdGUsIGdpdmUgYSBidXJzdCBvZiB1cHdhcmRzIHZlbG9jaXR5XG5cdFx0aWYoSW5wdXRXcmFwcGVyLmlzSnVtcEp1c3RQcmVzc2VkKCkpe1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdFx0XG5cdFx0fSBcblx0XHRlbHNlIGlmKCF0aGlzLm93bmVyLm9uR3JvdW5kICYmIElucHV0V3JhcHBlci5nZXRTdGF0ZSgpID09PSBHYW1lU3RhdGUuR0FNSU5HKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoXCJmYWxsXCIpO1xuXHRcdH1cblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcblx0XHRcblx0fVxuXG5cdG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRyZXR1cm4ge307XG5cdH1cbn0iLCJpbXBvcnQgU3RhdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZVwiO1xuaW1wb3J0IFN0YXRlTWFjaGluZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1N0YXRlL1N0YXRlTWFjaGluZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1RpbWluZy9UaW1lclwiO1xuaW1wb3J0IHsgR2FtZVN0YXRlLCBQbGF5ZXJfRXZlbnRzIH0gZnJvbSBcIi4uLy4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi8uLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcbmltcG9ydCBQbGF5ZXJDb250cm9sbGVyIGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5cblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUGxheWVyU3RhdGUgZXh0ZW5kcyBTdGF0ZSB7XG5cdG93bmVyOiBHYW1lTm9kZTtcblx0Z3Jhdml0eTogbnVtYmVyID0gMTUwMDsgLy9UT0RPIC0gY2FuIGNoYW5nZSBsYXRlclxuXHRwYXJlbnQ6IFBsYXllckNvbnRyb2xsZXI7XG5cdHBvc2l0aW9uVGltZXI6IFRpbWVyO1xuXHRzdGF0aWMgZGFzaFRpbWVyOiBUaW1lcjtcblx0c3RhdGljIGRhc2hDb29sRG93blRpbWVyOiBUaW1lcjtcblxuXHRjb25zdHJ1Y3RvcihwYXJlbnQ6IFN0YXRlTWFjaGluZSwgb3duZXI6IEdhbWVOb2RlKXtcblx0XHRzdXBlcihwYXJlbnQpO1xuXHRcdHRoaXMub3duZXIgPSBvd25lcjtcblx0XHR0aGlzLnBvc2l0aW9uVGltZXIgPSBuZXcgVGltZXIoMjUwKTtcblx0XHR0aGlzLnBvc2l0aW9uVGltZXIuc3RhcnQoKTtcblx0XHRQbGF5ZXJTdGF0ZS5kYXNoVGltZXIgPSBuZXcgVGltZXIoMTAwKTtcblx0XHRQbGF5ZXJTdGF0ZS5kYXNoQ29vbERvd25UaW1lciA9IG5ldyBUaW1lcig2MDApO1xuXG5cdH1cblxuXHRcblx0aGFuZGxlSW5wdXQoZXZlbnQ6IEdhbWVFdmVudCk6IHZvaWQge1xuXHRcdFxuXHR9XG5cblx0ZG9EYXNoKCk6IHZvaWQge1xuXHRcdGlmIChQbGF5ZXJTdGF0ZS5kYXNoQ29vbERvd25UaW1lci5pc1N0b3BwZWQoKSkge1xuXHRcdFx0Ly9UT0RPIC0gZGVjaWRlIGhvdyB0byBpbXBsZW1lbnQgZGFzaCAtIGNvdWxkIGJlIGEgZmxhc2ggLSBtYXliZSBhbGxvdyBpbiBhaXIgYXMgd2VsbFxuXHRcdFx0Ly9wbGF5IGRhc2ggYW5pbSBtYXliZVxuXHRcdFx0Ly9UT0RPIC0gbWlnaHQgZ2l2ZSBidWZmZWQgc3BlZWQgc3RhdCB0byBkYXNoIHNwZWVkXG5cdFx0XHQvL1RPRE8gLSBnaXZlIHBsYXllciBpIGZyYW1lXG5cdFx0XHRQbGF5ZXJTdGF0ZS5kYXNoQ29vbERvd25UaW1lci5zdGFydCgpO1xuXHRcdFx0UGxheWVyU3RhdGUuZGFzaFRpbWVyLnN0YXJ0KCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIFxuXHQgKiBHZXQgdGhlIGlucHV0cyBmcm9tIHRoZSBrZXlib2FyZCwgb3IgVmVjMi5aZXJvIGlmIG5vdGhpbmcgaXMgYmVpbmcgcHJlc3NlZFxuXHQgKi9cblx0Z2V0SW5wdXREaXJlY3Rpb24oKTogVmVjMiB7XG5cdFx0bGV0IGRpcmVjdGlvbiA9IFZlYzIuWkVSTztcblx0XHRkaXJlY3Rpb24ueCA9IChJbnB1dFdyYXBwZXIuaXNMZWZ0UHJlc3NlZCgpID8gLTEgOiAwKSArIChJbnB1dFdyYXBwZXIuaXNSaWdodFByZXNzZWQoKSA/IDEgOiAwKTtcblx0XHRkaXJlY3Rpb24ueSA9IChJbnB1dFdyYXBwZXIuaXNKdW1wSnVzdFByZXNzZWQoKSA/IC0xIDogMCk7XG5cdFx0cmV0dXJuIGRpcmVjdGlvbjtcblx0fVxuXG5cdFxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIERvIGdyYXZpdHlcblx0XHRcblx0XHRpZiAodGhpcy5wb3NpdGlvblRpbWVyLmlzU3RvcHBlZCgpKXtcblx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5QTEFZRVJfTU9WRSwge3Bvc2l0aW9uOiB0aGlzLm93bmVyLnBvc2l0aW9uLmNsb25lKCl9KTtcblx0XHRcdHRoaXMucG9zaXRpb25UaW1lci5zdGFydCgpO1xuXHRcdH1cblx0XHRcblxuXHRcdGlmKElucHV0V3JhcHBlci5pc0Rhc2hKdXN0UHJlc3NlZCgpKXtcblx0XHRcdHRoaXMuZG9EYXNoKCk7XG5cdFx0fVxuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gKDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA/IC04MDAgOiA4MDA7XG5cdFx0fVxuXHRcdGlmIChJbnB1dFdyYXBwZXIuZ2V0U3RhdGUoKSA9PT0gR2FtZVN0YXRlLkdBTUlORykge1xuXHRcdFx0KDxBbmltYXRlZFNwcml0ZT50aGlzLnBhcmVudC5vd25lcikuYW5pbWF0aW9uLnJlc3VtZSgpO1xuXHRcdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueSArPSB0aGlzLmdyYXZpdHkqZGVsdGFUO1xuXHRcdFx0dGhpcy5vd25lci5tb3ZlKHRoaXMucGFyZW50LnZlbG9jaXR5LnNjYWxlZChkZWx0YVQpKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHQoPEFuaW1hdGVkU3ByaXRlPnRoaXMucGFyZW50Lm93bmVyKS5hbmltYXRpb24ucGF1c2UoKTtcblx0XHR9XG5cdH1cbn0iLCJpbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uLy4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IHsgUGxheWVyU3RhdGVzIH0gZnJvbSBcIi4uL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBPbkdyb3VuZCBmcm9tIFwiLi9Pbkdyb3VuZFwiO1xuaW1wb3J0IFBsYXllclN0YXRlIGZyb20gXCIuL1BsYXllclN0YXRlXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgeyBHYW1lU3RhdGUgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2FsayBleHRlbmRzIE9uR3JvdW5kIHtcblx0b3duZXI6IEFuaW1hdGVkU3ByaXRlO1xuXG5cdG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdHRoaXMucGFyZW50LnNwZWVkID0gdGhpcy5wYXJlbnQuTUlOX1NQRUVEO1xuICAgICAgICBcblx0fVxuXG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYgKCFQbGF5ZXJTdGF0ZS5kYXNoVGltZXIuaXNTdG9wcGVkKCkpIHtcblx0XHRcdGlmKElucHV0V3JhcHBlci5nZXRTdGF0ZSgpID09PSBHYW1lU3RhdGUuR0FNSU5HKXtcblx0XHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwiZGFzaFwiLCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogZmFsc2V9KTtcblx0XHRcdH1cblx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJEQVNIXCIpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmICh0aGlzLnBhcmVudC5pbnZpbmNpYmxlKSB7XG5cdFx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJIVVJUXCIpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJXQUxLXCIsIHRydWUpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRsZXQgZGlyID0gdGhpcy5nZXRJbnB1dERpcmVjdGlvbigpO1xuXG5cdFx0aWYoZGlyLmlzWmVybygpKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoUGxheWVyU3RhdGVzLklETEUpO1xuXHRcdH0gXG5cdFx0XG5cdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IGRpci54ICogKHRoaXMucGFyZW50LnNwZWVkICk7XG5cdFx0XG5cdFx0c3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cdH1cblxuXHRvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG5cdFx0dGhpcy5vd25lci5hbmltYXRpb24uc3RvcCgpO1xuXHRcdHJldHVybiB7fTtcblx0fVxufSIsImltcG9ydCBSZWdpc3RyeSBmcm9tIFwiLi4vLi4vV29sZmllMkQvUmVnaXN0cnkvUmVnaXN0cmllcy9SZWdpc3RyeVwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vV29sZmllMkQvUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuXG5pbXBvcnQgV2VhcG9uVHlwZSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvV2VhcG9uVHlwZVwiO1xuaW1wb3J0IFNsaWNlIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9pdGVtcy9XZWFwb25UeXBlcy9TbGljZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWFwb25UZW1wbGF0ZVJlZ2lzdHJ5IGV4dGVuZHMgUmVnaXN0cnk8V2VhcG9uQ29uc3RydWN0b3I+IHtcbiAgICBcbiAgICBwdWJsaWMgcHJlbG9hZCgpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgcm0gPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcblxuICAgICAgICAvL1RPRE8gLSBcbiAgICAgICAgLy8gTG9hZCBzcHJpdGVzIGZvciBlYWNoIHdlYXBvbiBcbiAgICAgICAgLy9ybS5pbWFnZShcInNvbWV0aGluZ1wiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlcy9zb21ldGhpbmcucG5nXCIpO1xuICAgICAgICBybS5pbWFnZShcImtuaWZlXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzL2tuaWZlLnBuZ1wiKTtcblxuICAgICAgICAvLyBMb2FkIHNwcml0ZXNoZWV0c1xuICAgICAgICAvL3JtLnNwcml0ZXNoZWV0KFwid2VhcG9uIGFuaW1cIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy93ZWFwb24gYW5pbS5qc29uXCIpO1xuICAgICAgICBybS5zcHJpdGVzaGVldChcInNsaWNlXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvc2xpY2UuanNvblwiKTtcblxuICAgICAgICAvLyBSZWdpc3RlciBkZWZhdWx0IHR5cGVzXG4gICAgICAgIC8vdGhpcy5yZWdpc3Rlckl0ZW0oXCJpdGVtdHlwZVwiLCBpdGVtVHlwZWZpbGUpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVySXRlbShcInNsaWNlXCIsIFNsaWNlKTtcbiAgICAgICAgXG4gICAgfVxuXG4gICAgXG4gICAgcHVibGljIHJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oa2V5OiBzdHJpbmcpOiB2b2lkIHt9XG5cbiAgICBwdWJsaWMgcmVnaXN0ZXJJdGVtKGtleTogc3RyaW5nLCBjb25zdHI6IFdlYXBvbkNvbnN0cnVjdG9yKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWRkKGtleSwgY29uc3RyKTtcbiAgICB9XG59XG5cbnR5cGUgV2VhcG9uQ29uc3RydWN0b3IgPSBuZXcgKC4uLmFyZ3M6IGFueSkgPT4gV2VhcG9uVHlwZTsiLCJpbXBvcnQgUmVnaXN0cnkgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvUmVnaXN0cnlcIjtcbmltcG9ydCBXZWFwb25UeXBlIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9pdGVtcy9XZWFwb25UeXBlcy9XZWFwb25UeXBlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdlYXBvblR5cGVSZWdpc3RyeSBleHRlbmRzIFJlZ2lzdHJ5PFdlYXBvblR5cGU+IHtcbiAgICBcbiAgICBwdWJsaWMgcHJlbG9hZCgpOiB2b2lkIHt9XG5cbiAgICAvLyBXZSBkb24ndCBuZWVkIHRoaXMgZm9yIHRoaXMgYXNzaWdubWVudFxuICAgIHB1YmxpYyByZWdpc3RlckFuZFByZWxvYWRJdGVtKGtleTogc3RyaW5nKTogdm9pZCB7fVxuXG4gICAgcHVibGljIHJlZ2lzdGVySXRlbShrZXk6IHN0cmluZywgdHlwZTogV2VhcG9uVHlwZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmFkZChrZXksIHR5cGUpO1xuICAgIH1cbn0iLCJpbXBvcnQgQUFCQiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGVidWcvRGVidWdcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcbmltcG9ydCB7IFR3ZWVuYWJsZVByb3BlcnRpZXMgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCB7IEdyYXBoaWNUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlc1wiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9Qb2ludFwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IExhYmVsLCB7IEhBbGlnbiB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBUaW1lciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVGltaW5nL1RpbWVyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgeyBFYXNlRnVuY3Rpb25UeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0Vhc2VGdW5jdGlvbnNcIjtcbmltcG9ydCBQbGF5ZXJDb250cm9sbGVyIGZyb20gXCIuLi9QbGF5ZXIvUGxheWVyQ29udHJvbGxlclwiO1xuaW1wb3J0IHsgR2FtZVN0YXRlLCBQbGF5ZXJfRXZlbnRzLCBTdGF0dXNlcyB9IGZyb20gXCIuLi9zd29yZF9lbnVtc1wiO1xuaW1wb3J0IFJlZ2lzdHJ5TWFuYWdlciBmcm9tIFwiLi4vLi4vV29sZmllMkQvUmVnaXN0cnkvUmVnaXN0cnlNYW5hZ2VyXCI7XG5pbXBvcnQgV2VhcG9uVHlwZSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvV2VhcG9uVHlwZVwiO1xuaW1wb3J0IFdlYXBvbiBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uXCI7XG5pbXBvcnQgQmF0dGxlTWFuYWdlciBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvQmF0dGxlTWFuYWdlclwiO1xuaW1wb3J0IEVuZW15QUkgZnJvbSBcIi4uL0FJL0VuZW15QUlcIjtcbmltcG9ydCBTbmFrZUFJIGZyb20gXCIuLi9BSS9TbmFrZUFJXCI7XG5pbXBvcnQgU2xpbWVBSSBmcm9tIFwiLi4vQUkvU2xpbWVBSVwiO1xuaW1wb3J0IEJhdHRsZXJBSSBmcm9tIFwiLi4vQUkvQmF0dGxlckFJXCI7XG5pbXBvcnQgSW52ZW50b3J5TWFuYWdlciBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvSW52ZW50b3J5TWFuYWdlclwiO1xuaW1wb3J0IEl0ZW0gZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL0l0ZW1cIjtcbmltcG9ydCBMYXllciBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvTGF5ZXJcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgeyBCdWZmIH0gZnJvbSBcIi4uL1BsYXllci9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IFJhbmRvbU1hcEdlbmVyYXRvciwgeyBFbmVteSB9IGZyb20gXCIuLi9Ub29scy9SYW5kb21NYXBHZW5lcmF0b3JcIjtcbmltcG9ydCBTdGFjayBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1N0YWNrXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcbmltcG9ydCBTdG9yeSBmcm9tIFwiLi4vVG9vbHMvRGF0YVR5cGVzL1N0b3J5XCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRleHRJbnB1dCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9UZXh0SW5wdXRcIjtcbmltcG9ydCB7IFRpbGVkVGlsZW1hcERhdGEgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiO1xuaW1wb3J0IEdhbWVPdmVyIGZyb20gXCIuL0dhbWVPdmVyXCI7XG5pbXBvcnQgUG9yY2VsYWluIGZyb20gXCIuL1BvcmNlbGFpblwiO1xuaW1wb3J0IFR1dG9yaWFsIGZyb20gXCIuL1R1dG9yaWFsXCI7XG5pbXBvcnQgR3JlYXR3YWxsIGZyb20gXCIuL0dyZWF0d2FsbFwiO1xuaW1wb3J0IE1haW5NZW51IGZyb20gXCIuL01haW5NZW51XCI7XG5cbi8vICBUT0RPXG4vKipcbiAqIEFkZCBpbiBzb21lIGxldmVsIG11c2ljLlxuICogVGhpcyBjYW4gYmUgZG9uZSBoZXJlIGluIHRoZSBiYXNlIEdhbWVMZXZlbCBjbGFzcyBvciBpbmRpdmlkdWFsIGxldmVsIGZpbGVzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdhbWVMZXZlbCBleHRlbmRzIFNjZW5lIHtcbiAgICAvLyBFdmVyeSBsZXZlbCB3aWxsIGhhdmUgYSBwbGF5ZXIsIHdoaWNoIHdpbGwgYmUgYW4gYW5pbWF0ZWQgc3ByaXRlXG4gICAgcHJvdGVjdGVkIHBsYXllclNwYXduOiBWZWMyO1xuICAgIHByb3RlY3RlZCBwbGF5ZXI6IEFuaW1hdGVkU3ByaXRlO1xuICAgIHByb3RlY3RlZCByZXNwYXduVGltZXI6IFRpbWVyO1xuXG4gICAgLy8gTGFiZWxzIGZvciB0aGUgVUlcbiAgICAvL1RPRE8gLSBsaXZlcyBoZXJlIG9yIGluIHBsYXllcmNvbnRyb2xsZXJcbiAgICBwcm90ZWN0ZWQgc3RhdGljIGxpdmVzQ291bnQ6IG51bWJlciA9IDM7XG4gICAgcHJvdGVjdGVkIGxpdmVzQ291bnRMYWJlbDogTGFiZWw7XG5cbiAgICAvLyBTdHVmZiB0byBlbmQgdGhlIGxldmVsIGFuZCBnbyB0byB0aGUgbmV4dCBsZXZlbFxuICAgIHByb3RlY3RlZCBsZXZlbEVuZEFyZWE6IFJlY3Q7XG4gICAgcHJvdGVjdGVkIG5leHRMZXZlbDogbmV3ICguLi5hcmdzOiBhbnkpID0+IEdhbWVMZXZlbDtcbiAgICBwcm90ZWN0ZWQgbGV2ZWxFbmRUaW1lcjogVGltZXI7XG4gICAgcHJvdGVjdGVkIGxldmVsRW5kTGFiZWw6IExhYmVsO1xuICAgIFxuICAgIC8vIFNjcmVlbiBmYWRlIGluL291dCBmb3IgbGV2ZWwgc3RhcnQgYW5kIGVuZFxuICAgIHByb3RlY3RlZCBsZXZlbFRyYW5zaXRpb25UaW1lcjogVGltZXI7XG4gICAgcHJvdGVjdGVkIGxldmVsVHJhbnNpdGlvblNjcmVlbjogUmVjdDtcblxuICAgIC8vIFRoZSBiYXR0bGUgbWFuYWdlciBmb3IgdGhlIHNjZW5lXG4gICAgcHJvdGVjdGVkIGJhdHRsZU1hbmFnZXI6IEJhdHRsZU1hbmFnZXI7XG5cbiAgICAvLyBIZWFsdGggVUlcbiAgICBwcm90ZWN0ZWQgaGVhbHRoTGFiZWw6IExhYmVsO1xuICAgIHByb3RlY3RlZCBoZWFsdGhCYXI6IFJlY3Q7XG4gICAgLy9leHAgbGFiZWxcbiAgICBwcm90ZWN0ZWQgZXhwTGFiZWwgOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgZXhwQmFyOiBSZWN0O1xuXG4gICAgLy9sZXZlbCBsYWJlbFxuICAgIHByb3RlY3RlZCBwbGF5ZXJMZXZlbExhYmVsIDogTGFiZWw7XG5cbiAgICAvL3NoaWVsZCBsYWJlbFxuICAgIHByb3RlY3RlZCBzaGllbGRMYWJlbCA6IExhYmVsO1xuICAgIHByb3RlY3RlZCBzaGllbGRCYXI6IFJlY3Q7XG5cbiAgICBwcm90ZWN0ZWQgcG9pc29uU3RhdDogU3ByaXRlO1xuICAgIHByb3RlY3RlZCBidXJuU3RhdDogU3ByaXRlO1xuICAgIHByb3RlY3RlZCBibGVlZFN0YXQ6IFNwcml0ZTtcblxuICAgIC8vc2VlZCBVSVxuICAgIHByb3RlY3RlZCBzZWVkTGFiZWw6IExhYmVsOyAgIFxuXG4gICAgLy8gQSBsaXN0IG9mIGl0ZW1zIGluIHRoZSBzY2VuZVxuICAgIHByb3RlY3RlZCBpdGVtczogQXJyYXk8SXRlbT47XG5cbiAgICAgLy8gQSBsaXN0IG9mIGVuZW1pZXNcbiAgICBwcm90ZWN0ZWQgZW5lbWllczogQXJyYXk8QW5pbWF0ZWRTcHJpdGU+O1xuXG4gICAgcHJvdGVjdGVkIGdhbWVTdGF0ZVN0YWNrOiBTdGFjazxHYW1lU3RhdGU+O1xuXG4gICAgLy8gU3RvcnlcbiAgICBwcm90ZWN0ZWQgc3Rvcnl0ZXh0TGFiZWw6IExhYmVsO1xuICAgIHByb3RlY3RlZCBzdG9yeUxheWVyOiBMYXllcjtcbiAgICBwcm90ZWN0ZWQgc3Rvcnk6IFN0b3J5O1xuICAgIHByb3RlY3RlZCBzdG9yeVByb2dyZXNzOiBudW1iZXI7XG4gICAgcHJvdGVjdGVkIHN0b3J5U3ByaXRlczogQXJyYXk8U3ByaXRlPjtcbiAgICBwcm90ZWN0ZWQgc3RvcnlCR01zOiBBcnJheTxzdHJpbmc+O1xuICAgIHByb3RlY3RlZCBjdXJyZW50U3BlYWtlcjogc3RyaW5nO1xuICAgIHByb3RlY3RlZCBjdXJyZW50Q29udGVudDogc3RyaW5nO1xuXG4gICAgLy9idWZmcyBsYXllclxuICAgIHByb3RlY3RlZCBidWZmTGF5ZXI6IExheWVyO1xuICAgIHByb3RlY3RlZCBidWZmQnV0dG9uMSA6IEJ1dHRvbjtcbiAgICBwcm90ZWN0ZWQgYnVmZkxhYmVsMSA6IExhYmVsO1xuICAgIHByb3RlY3RlZCBidWZmQnV0dG9uMiA6IEJ1dHRvbjtcbiAgICBwcm90ZWN0ZWQgYnVmZkxhYmVsMiA6IExhYmVsO1xuICAgIHByb3RlY3RlZCBidWZmQnV0dG9uMyA6IEJ1dHRvbjtcbiAgICBwcm90ZWN0ZWQgYnVmZkxhYmVsMzogTGFiZWw7XG4gICAgcHJvdGVjdGVkIGJ1ZmZzOiBBcnJheTxCdWZmPjtcblxuICAgIC8vcGF1c2UgbGF5ZXJcbiAgICBwcm90ZWN0ZWQgcGF1c2VMYXllcjogTGF5ZXI7XG4gICAgcHJvdGVjdGVkIHBhdXNlVGV4dDogTGFiZWw7XG4gICAgcHJvdGVjdGVkIHBhdXNlSW5wdXQ6IFRleHRJbnB1dDtcbiAgICBwcm90ZWN0ZWQgcGF1c2VTdWJtaXQ6IExhYmVsO1xuICAgIHByb3RlY3RlZCBwYXVzZUNoZWF0VGV4dDogTGFiZWw7XG4gICAgcHJvdGVjdGVkIG1haW5NZW51QnV0dG9uOiBCdXR0b247XG5cbiAgICBwcm90ZWN0ZWQgcm1nOiBSYW5kb21NYXBHZW5lcmF0b3I7XG4gICAgcHJvdGVjdGVkIG1hcDogVGlsZWRUaWxlbWFwRGF0YTtcblxuICAgIHByb3RlY3RlZCBzdGFydENoZWNrUG9pbnQ6IFJlY3Q7XG4gICAgcHJvdGVjdGVkIGVuZENoZWNrUG9pbnQ6IFJlY3Q7XG4gICAgcHJvdGVjdGVkIHRvdWNoZWRTdGFydENoZWNrUG9pbnQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgdG91Y2hlZEVuZENoZWNrUG9pbnQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBzdGF0aWMgZ2FtZVRpbWVyOiBudW1iZXIgPSAwO1xuICAgIHByb3RlY3RlZCBnYW1lU3RhcnRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHByb3RlY3RlZCB0aW1lckxhYmxlOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgbGV2ZWxFbmRlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgc3RhcnRwb3M6IFZlYzI7IFxuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy9jYW4gbG9hZCBwbGF5ZXIgc3ByaXRlIGhlcmVcbiAgICAgICAgdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwicGxheWVyXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvSGlyby5qc29uXCIpXG4gICAgICAgIC8vIFRPRE8gLSBjaGFuZ2Ugd2hlbiBkb25lIHRlc3RpbmdcbiAgICAgICAgdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwic2xpY2VcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9zbGljZS5qc29uXCIpO1xuXG4gICAgICAgIC8vIExvYWQgdGhlIHNjZW5lIGluZm9cbiAgICAgICAgdGhpcy5sb2FkLm9iamVjdChcIndlYXBvbkRhdGFcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2RhdGEvd2VhcG9uRGF0YS5qc29uXCIpO1xuXG4gICAgICAgIC8vIExvYWQgaW4gdGhlIGVuZW15IGluZm9cbiAgICAgICAgLy90aGlzLmxvYWQub2JqZWN0KFwiZW5lbXlEYXRhXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9kYXRhL2VuZW15Lmpzb25cIik7XG5cbiAgICAgICAgLy8gTG9hZCBpbiBpdGVtIGluZm9cbiAgICAgICAgLy90aGlzLmxvYWQub2JqZWN0KFwiaXRlbURhdGFcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2RhdGEvaXRlbXMuanNvblwiKTtcblxuICAgICAgICB0aGlzLmxvYWQuYXVkaW8oXCJqdW1wXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zb3VuZHMvanVtcDIud2F2XCIpO1xuICAgICAgICB0aGlzLmxvYWQuYXVkaW8oXCJodXJ0XCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zb3VuZHMvaHVydC53YXZcIik7XG4gICAgICAgIHRoaXMubG9hZC5hdWRpbyhcImRpZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc291bmRzL2RpZS53YXZcIik7XG4gICAgICAgIHRoaXMubG9hZC5hdWRpbyhcImRhc2hcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3NvdW5kcy9kYXNoLndhdlwiKTtcbiAgICAgICAgdGhpcy5sb2FkLmF1ZGlvKFwibGV2ZWxfdXBcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc291bmRzL2xldmVsX3VwLndhdlwiKTtcbiAgICAgICAgLy/npZ7npL7vvIjjgZjjgpPjgZjjgoPvvInnpa3vvIjjgb7jgaTjgorvvInjgIBieSBTZWNvbmQgRGltZW5zaW9uIEltYWdpbmF0aW9uIEdyb3VwXG4gICAgICAgIHRoaXMubG9hZC5hdWRpbyhcImxldmVsX211c2ljXCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3NvdW5kcy9iZ20xLm1wM1wiKTtcbiAgICAgICAgdGhpcy5sb2FkLmF1ZGlvKFwic3dvcmRcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc291bmRzL3N3b3JkX2RpbmcxLm00YVwiKTtcblxuXG5cbiAgICAgICAgdGhpcy5sb2FkLmltYWdlKFwia25pZmVcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXMva25pZmUucG5nXCIpO1xuICAgICAgICB0aGlzLmxvYWQuaW1hZ2UoXCJpbnZlbnRvcnlTbG90XCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzL2ludmVudG9yeS5wbmdcIik7XG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcImJsYWNrXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9pbWFnZXMvYmxhY2sucG5nXCIpO1xuICAgICAgICB0aGlzLmxvYWQuaW1hZ2UoXCJwb2lzb25pbmdcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2ltYWdlcy9wb2lzb25pbmcucG5nXCIpO1xuICAgICAgICB0aGlzLmxvYWQuaW1hZ2UoXCJidXJuaW5nXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9pbWFnZXMvYnVybmluZy5wbmdcIik7XG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcImJsZWVkaW5nXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9pbWFnZXMvYmxlZWRpbmcucG5nXCIpO1xuXG4gICAgICAgIC8vVE9ETyAtIGNob29zZSBzcHJpdGVzaGVldCBmb3Igc2xpY2UgLSBtb2RpZnkgdGhlIHNsaWNlLmpzb25cbiAgICAgICAgdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwic2xpY2VcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9zbGljZS5qc29uXCIpO1xuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJ0ZXN0X2R1bW15XCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy90ZXN0X2R1bW15Lmpzb25cIilcbiAgICAgICAgdGhpcy5lbmVtaWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlciA9IG5ldyBCYXR0bGVNYW5hZ2VyKCk7XG4gICAgfVxuXG4gICAgdW5sb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELCB7a2V5OiBcImxldmVsX211c2ljXCJ9KTtcbiAgICAgfVxuXG4gICAgc3RhcnRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hZGQudGlsZW1hcChcIm1hcFwiLCBuZXcgVmVjMigyLCAyKSk7XG4gICAgICAgIGNvbnNvbGUubG9nKFwid2lkdGgsaGVpZ2h0OlwiICsgdGhpcy5tYXAud2lkdGgsIHRoaXMubWFwLmhlaWdodCk7XG4gICAgICAgIHRoaXMudmlld3BvcnQuc2V0Qm91bmRzKDAsIDAsIHRoaXMubWFwLndpZHRoICogMzIsIHRoaXMubWFwLmhlaWdodCAqIDMyKTtcbiAgICAgICAgdGhpcy52aWV3cG9ydC5mb2xsb3codGhpcy5wbGF5ZXIpO1xuXG4gICAgICAgIHRoaXMucGxheWVyU3Bhd24gPSB0aGlzLnJtZy5nZXRQbGF5ZXIoKS5zY2FsZSgzMik7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMucGxheWVyU3Bhd24pXG5cbiAgICAgICAgdGhpcy5zdGFydHBvcyA9IHRoaXMucm1nLmdldFBsYXllcigpLnNjYWxlKDMyKTtcblxuXG4gICAgICAgIFxuICAgICAgICAvLyBEbyB0aGUgZ2FtZSBsZXZlbCBzdGFuZGFyZCBpbml0aWFsaXphdGlvbnNcbiAgICAgICAgdGhpcy5pbml0Vmlld3BvcnQoKTtcbiAgICAgICAgdGhpcy5pbml0TGF5ZXJzKCk7XG4gICAgICAgIC8vIENyZWF0ZSB0aGUgYmF0dGxlIG1hbmFnZXJcblxuICAgICAgICAvLyBUT0RPXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVdlYXBvbnMoKTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgaXRlbXMgYXJyYXkgLSB0aGlzIHJlcHJlc2VudHMgaXRlbXMgdGhhdCBhcmUgaW4gdGhlIGdhbWUgd29ybGRcbiAgICAgICAgdGhpcy5pdGVtcyA9IG5ldyBBcnJheSgpO1xuXG4gICAgICAgIHRoaXMuaW5pdFBsYXllcigpO1xuICAgICAgICAvL3N1YnNjcmliZSB0byByZWxldmFudCBldmVudHNcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVUb0V2ZW50cygpO1xuICAgICAgICB0aGlzLmFkZFVJKCk7XG5cbiAgICAgICAgbGV0IHN0YXJ0Q2hlY2tQb2ludCA9IHRoaXMucm1nLmdldFN0YXJ0Q2hlY2tQb2ludCgpO1xuICAgICAgICB0aGlzLnN0YXJ0Q2hlY2tQb2ludCA9IHRoaXMuYWRkQ2hlY2tQb2ludChuZXcgVmVjMihzdGFydENoZWNrUG9pbnRbMF0sIHN0YXJ0Q2hlY2tQb2ludFsxXSksIG5ldyBWZWMyKHN0YXJ0Q2hlY2tQb2ludFsyXSwgc3RhcnRDaGVja1BvaW50WzNdKSwgXCJzdGFydFN0b3J5XCIsIFwic3RhcnRUaW1lclwiKTtcbiAgICAgICAgbGV0IGVuZENoZWNrUG9pbnQgPSB0aGlzLnJtZy5nZXRFbmRDaGVja1BvaW50KCk7XG4gICAgICAgIHRoaXMuZW5kQ2hlY2tQb2ludCA9IHRoaXMuYWRkQ2hlY2tQb2ludChuZXcgVmVjMihlbmRDaGVja1BvaW50WzBdLCBlbmRDaGVja1BvaW50WzFdKSwgbmV3IFZlYzIoZW5kQ2hlY2tQb2ludFsyXSwgZW5kQ2hlY2tQb2ludFszXSksIFwiZW5kU3RvcnlcIiwgXCJuZXh0TGV2ZWxcIik7XG4gICAgICAgIFxuICAgICAgICAvLyBDcmVhdGUgYW4gZW5lbWllcyBhcnJheVxuICAgICAgICAvLyBTZW5kIHRoZSBwbGF5ZXIgYW5kIGVuZW1pZXMgdG8gdGhlIGJhdHRsZSBtYW5hZ2VyXG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlci5zZXRQbGF5ZXJzKFs8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWldKTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBhbGwgZW5lbWllc1xuICAgICAgICAvL3RoaXMuaW5pdGlhbGl6ZUVuZW1pZXMoKTtcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyLnNldEVuZW1pZXModGhpcy5lbmVtaWVzLm1hcChlbmVteSA9PiA8QmF0dGxlckFJPmVuZW15Ll9haSkpO1xuXG5cbiAgICAgICAgbGV0IGVuZW1pZXMgPSB0aGlzLnJtZy5nZXRFbmVtaWVzKCk7XG4gICAgICAgIC8vbWF5IGhhdmUgdG8gbW92ZSB0aGlzIHRvIHN0YXJ0IHNjZW5lIGluIGdhbWVMZXZlbFxuICAgICAgICB0aGlzLmluaXRpYWxpemVFbmVtaWVzKGVuZW1pZXMpO1xuXG5cbiAgICAgICAgdGhpcy5nYW1lU3RhdGVTdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZShHYW1lU3RhdGUuR0FNSU5HKTtcbiAgICAgICAgSW5wdXRXcmFwcGVyLmVuYWJsZUlucHV0KCk7XG5cbiAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwibGV2ZWxfbXVzaWNcIiwgbG9vcDogdHJ1ZSwgaG9sZFJlZmVyZW5jZTogdHJ1ZX0pO1xuICAgIH1cblxuXG4gICAgdXBkYXRlU2NlbmUoZGVsdGFUOiBudW1iZXIpe1xuXG4gICAgICAgIGlmICh0aGlzLmdhbWVTdGF0ZVN0YWNrLnBlZWsoKSA9PT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2FtZVN0YXJ0ZWQpIHtcbiAgICAgICAgICAgICAgICBHYW1lTGV2ZWwuZ2FtZVRpbWVyICs9IGRlbHRhVDtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVyTGFibGUudGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVyTGFibGUudGV4dENvbG9yID0gQ29sb3IuUkVEO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKEdhbWVMZXZlbC5nYW1lVGltZXIgLyA2MCk7XG4gICAgICAgICAgICBpZiAobWludXRlcyA+PSAxMCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXJMYWJsZS50ZXh0ID0gbWludXRlcy50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lckxhYmxlLnRleHQgPSBcIjBcIiArIG1pbnV0ZXMudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzZWNvbmRzID0gTWF0aC5mbG9vcihHYW1lTGV2ZWwuZ2FtZVRpbWVyICUgNjApO1xuICAgICAgICAgICAgaWYgKHNlY29uZHMgPj0gMTApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVyTGFibGUudGV4dCArPSBcIjpcIiArIHNlY29uZHMudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXJMYWJsZS50ZXh0ICs9IFwiOjBcIiArIHNlY29uZHMudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIFxuICAgICAgICAvLyBIYW5kbGUgZXZlbnRzIGFuZCB1cGRhdGUgdGhlIFVJIGlmIG5lZWRlZFxuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmdhbWVTdGF0ZVN0YWNrLnBlZWsoKSA9PT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgICAgIHN3aXRjaChldmVudC50eXBlKXtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBQbGF5ZXJfRXZlbnRzLlBMQVlFUl9DT0xMSURFOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG4gPSB0aGlzLnNjZW5lR3JhcGguZ2V0Tm9kZShldmVudC5kYXRhLmdldChcIm5vZGVcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG90aGVyID0gdGhpcy5zY2VuZUdyYXBoLmdldE5vZGUoZXZlbnQuZGF0YS5nZXQoXCJvdGhlclwiKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG4gPT09IHRoaXMucGxheWVyKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOb2RlIGlzIHBsYXllciwgb3RoZXIgaXMgZW5lbXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVBsYXllckVuZW15Q29sbGlzaW9uKDxBbmltYXRlZFNwcml0ZT5uLCA8QW5pbWF0ZWRTcHJpdGU+b3RoZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlciBpcyBwbGF5ZXIsIG5vZGUgaXMgYmFsbG9vblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlUGxheWVyRW5lbXlDb2xsaXNpb24oPEFuaW1hdGVkU3ByaXRlPm90aGVyLDxBbmltYXRlZFNwcml0ZT5uKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgUGxheWVyX0V2ZW50cy5FTkVNWV9LSUxMRUQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBub2RlID0gdGhpcy5zY2VuZUdyYXBoLmdldE5vZGUoZXZlbnQuZGF0YS5nZXQoXCJvd25lclwiKSk7Ly9nZXQgZW5lbXkgaWQgXG4gICAgICAgICAgICAgICAgICAgICAgICAvL3JlbW92ZSBlbmVteSBmcm9tIGVuZW1pZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5lbWllcyA9IHRoaXMuZW5lbWllcy5maWx0ZXIoaXRlbSA9PiBpdGVtICE9PSBldmVudC5kYXRhLmdldChcImFpXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlci5yZW1vdmVFbmVteShldmVudC5kYXRhLmdldChcImFpXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vZ2l2ZSB0aGUgcGxheWVyIHRoZSBleHAgdmFsdWUgb2YgdGhlIGVuZW15IGtpbGxlZFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoZXZlbnQuZGF0YS5nZXQoXCJhaVwiKS5leHBfdmFsICE9PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmdpdmVFeHAoZXZlbnQuZGF0YS5nZXQoXCJhaVwiKS5leHBfdmFsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuZGVzdHJveSgpOyAvL2Rlc3Ryb3kgZW5lbXkgbm9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZW5lbWllc0tpbGxlZCsrIDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgUGxheWVyX0V2ZW50cy5HSVZFX1JFR1VMQVJfQlVGRjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZnMgPSAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5nZW5lcmF0ZVJlZ3VsYXJCdWZmcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5idWZmc1swXS5zdHJpbmcgPT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwxLnRleHQgPSBcIlxcblxcbkluY3JlYXNlIFwiK3RoaXMuYnVmZnNbMF0udHlwZSArIFwiXFxuIGJ5IFwiK3RoaXMuYnVmZnNbMF0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMS50ZXh0ID0gdGhpcy5idWZmc1swXS5zdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRoaXMuYnVmZnNbMV0uc3RyaW5nID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMi50ZXh0ID0gXCJcXG5cXG5JbmNyZWFzZSBcIit0aGlzLmJ1ZmZzWzFdLnR5cGUgKyBcIlxcbiBieSBcIit0aGlzLmJ1ZmZzWzFdLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDIudGV4dCA9IHRoaXMuYnVmZnNbMV0uc3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmJ1ZmZzWzJdLnN0cmluZyA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDMudGV4dCA9IFwiXFxuXFxuSW5jcmVhc2UgXCIrdGhpcy5idWZmc1syXS50eXBlICsgXCJcXG4gYnkgXCIrdGhpcy5idWZmc1syXS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwzLnRleHQgPSB0aGlzLmJ1ZmZzWzJdLnN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9wYXVzZSBnYW1lIGhlcmUgXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZShHYW1lU3RhdGUuQlVGRik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYXllci5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFBsYXllcl9FdmVudHMuR0lWRV9TUEVDSUFMX0JVRkY6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZzID0gKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZ2VuZXJhdGVTcGVjaWFsQnVmZnMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRoaXMuYnVmZnNbMF0uc3RyaW5nID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMS50ZXh0ID0gXCJcXG5cXG5JbmNyZWFzZSBcIit0aGlzLmJ1ZmZzWzBdLnR5cGUgKyBcIlxcbiBieSBcIit0aGlzLmJ1ZmZzWzBdLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDEudGV4dCA9IHRoaXMuYnVmZnNbMF0uc3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmJ1ZmZzWzFdLnN0cmluZyA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDIudGV4dCA9IFwiXFxuXFxuSW5jcmVhc2UgXCIrdGhpcy5idWZmc1sxXS50eXBlICsgXCJcXG4gYnkgXCIrdGhpcy5idWZmc1sxXS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwyLnRleHQgPSB0aGlzLmJ1ZmZzWzFdLnN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5idWZmc1syXS5zdHJpbmcgPT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwzLnRleHQgPSBcIlxcblxcbkluY3JlYXNlIFwiK3RoaXMuYnVmZnNbMl0udHlwZSArIFwiXFxuIGJ5IFwiK3RoaXMuYnVmZnNbMl0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMy50ZXh0ID0gdGhpcy5idWZmc1syXS5zdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vcGF1c2UgZ2FtZSBoZXJlIFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRHYW1lU3RhdGUoR2FtZVN0YXRlLkJVRkYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGF5ZXIuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBQbGF5ZXJfRXZlbnRzLlBMQVlFUl9LSUxMRUQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAvL3Jlc3Bhd24gcGxheWVyIGlmIGhlIGhhcyBsaXZlcywgb3RoZXJ3aXNlIGVuZCBnYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInBsYXllciBEaWVkXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLnBsYXllcikuYW5pbWF0aW9uLnBsYXkoXCJERUFEXCIsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIElucHV0V3JhcHBlci5kaXNhYmxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmxpdmVzID4wKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3Bhd25QbGF5ZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7IC8vbm8gbW9yZSBsaXZlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlld3BvcnQuc2V0Wm9vbUxldmVsKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoR2FtZU92ZXIsIHt9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbnB1dFdyYXBwZXIuZW5hYmxlSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwic3RhcnRTdG9yeVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGF5U3RhcnRTdG9yeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJlbmRTdG9yeVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGF5RW5kU3RvcnkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwic3RhcnRUaW1lclwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGFydFRpbWVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIm5leHRMZXZlbFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nb1RvTmV4dExldmVsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuQlVGRikge1xuICAgICAgICAgICAgICAgIHN3aXRjaChldmVudC50eXBlKXtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImJ1ZmYxXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5hZGRCdWZmKHRoaXMuYnVmZnNbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGF5ZXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRHYW1lU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmxldmVsRW5kZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdvVG9OZXh0TGV2ZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYnVmZjJcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmFkZEJ1ZmYodGhpcy5idWZmc1sxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYXllci5kaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubGV2ZWxFbmRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ29Ub05leHRMZXZlbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJidWZmM1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuYWRkQnVmZih0aGlzLmJ1ZmZzWzJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxheWVyLmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0R2FtZVN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sZXZlbEVuZGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nb1RvTmV4dExldmVsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJjaGVhdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVDaGVhdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJNYWluTWVudVwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdwb3J0LnNldFpvb21MZXZlbCgxKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51LCB7fSk7XG4gICAgICAgICAgICAgICAgSW5wdXRXcmFwcGVyLmVuYWJsZUlucHV0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuU1RPUlkpIHtcbiAgICAgICAgICAgIGlmIChJbnB1dFdyYXBwZXIuaXNOZXh0SnVzdFByZXNzZWQoKSAmJiB0aGlzLmdhbWVTdGF0ZVN0YWNrLnBlZWsoKSA9PT0gR2FtZVN0YXRlLlNUT1JZKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVTdG9yeSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuaXNQYXVzZUp1c3RQcmVzc2VkKCkpIHtcbiAgICAgICAgICAgIHRoaXMucGF1c2VUZXh0LnRleHQgPSAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS50b1N0cmluZygpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRHYW1lU3RhdGUoR2FtZVN0YXRlLlBBVVNFKTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdXNlTGF5ZXIuZW5hYmxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLmdhbWVTdGF0ZVN0YWNrLnBlZWsoKSA9PT0gR2FtZVN0YXRlLlBBVVNFKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRHYW1lU3RhdGUoKTsgICAgXG4gICAgICAgICAgICAgICAgdGhpcy5wYXVzZUxheWVyLmRpc2FibGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuaXNCdWZmMUp1c3RQcmVzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChcImJ1ZmYxXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuaXNCdWZmMkp1c3RQcmVzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChcImJ1ZmYyXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuaXNCdWZmM0p1c3RQcmVzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChcImJ1ZmYzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy91cGRhdGUgaGVhbHRoIFVJIFxuICAgICAgICBsZXQgcGxheWVyQUkgPSAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuYWkpO1xuICAgICAgICB0aGlzLmhlYWx0aExhYmVsLnRleHQgPSBcIkhlYWx0aDogXCIrIE1hdGgucm91bmQocGxheWVyQUkuQ1VSUkVOVF9IUCkgKycvJyArIE1hdGgucm91bmQocGxheWVyQUkuTUFYX0hQICk7XG4gICAgICAgIHRoaXMuaGVhbHRoQmFyLnNpemUuc2V0KHBsYXllckFJLk1BWF9IUCoxLjUsIDEwKTtcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIucG9zaXRpb24uc2V0KHBsYXllckFJLk1BWF9IUCowLjc1KzIwLCAyMCk7XG4gICAgICAgIHRoaXMuaGVhbHRoQmFyLmZpbGxXaWR0aCA9IHBsYXllckFJLkNVUlJFTlRfSFAqMS41O1xuICAgICAgICBpZiAocGxheWVyQUkuQ1VSUkVOVF9IUC9wbGF5ZXJBSS5NQVhfSFAgPj0gMi8zKSB7XG4gICAgICAgICAgICB0aGlzLmhlYWx0aEJhci5jb2xvciA9IENvbG9yLkdSRUVOO1xuICAgICAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5HUkVFTjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChwbGF5ZXJBSS5DVVJSRU5UX0hQL3BsYXllckFJLk1BWF9IUCA+PSAxLzMpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmNvbG9yID0gQ29sb3IuWUVMTE9XO1xuICAgICAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5ZRUxMT1c7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhlYWx0aEJhci5jb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgICAgIHRoaXMuaGVhbHRoTGFiZWwudGV4dENvbG9yID0gQ29sb3IuUkVEO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMuaGVhbHRoTGFiZWwuc2l6ZVRvVGV4dCgpO1xuXG4gICAgICAgIC8vdXBkYXRlIHNoaWVsZCB1aVxuICAgICAgICB0aGlzLnNoaWVsZExhYmVsLnRleHQgPSBcIlNoaWVsZDogXCIrIE1hdGgucm91bmQocGxheWVyQUkuQ1VSUkVOVF9TSElFTEQpICsnLycgKyBNYXRoLnJvdW5kKHBsYXllckFJLk1BWF9TSElFTEQpO1xuICAgICAgICB0aGlzLnNoaWVsZEJhci5zaXplLnNldChwbGF5ZXJBSS5DVVJSRU5UX1NISUVMRCoxLjUsIDEwKTtcbiAgICAgICAgdGhpcy5zaGllbGRCYXIucG9zaXRpb24uc2V0KHBsYXllckFJLkNVUlJFTlRfU0hJRUxEKjAuNzUrMjAsIDUwKTtcbiAgICAgICAgLy8gdGhpcy5zaGllbGRMYWJlbC5zaXplVG9UZXh0KCk7XG5cbiAgICAgICAgLy91cGRhdGUgZXhwIHVpXG4gICAgICAgIHRoaXMuZXhwTGFiZWwudGV4dCA9IFwiRVhQOiBcIisgTWF0aC5yb3VuZChwbGF5ZXJBSS5DVVJSRU5UX0VYUCkgKycvJyArIE1hdGgucm91bmQocGxheWVyQUkuTUFYX0VYUCk7XG4gICAgICAgIHRoaXMuZXhwQmFyLmZpbGxXaWR0aCA9IChwbGF5ZXJBSS5DVVJSRU5UX0VYUC9wbGF5ZXJBSS5NQVhfRVhQKSoxNTA7XG4gICAgICAgIC8vIHRoaXMuZXhwTGFiZWwuc2l6ZVRvVGV4dCgpO1xuXG4gICAgICAgIC8vdXBkYXRlIGxldmVsIHVpXG4gICAgICAgIHRoaXMucGxheWVyTGV2ZWxMYWJlbC50ZXh0ID0gXCJMdi5cIiArIHBsYXllckFJLmxldmVsO1xuICAgICAgICAvL3VwZGF0ZSBsaXZlcyB1aVxuICAgICAgICB0aGlzLmxpdmVzQ291bnRMYWJlbC50ZXh0ID0gXCJMaXZlczogXCIgKyBwbGF5ZXJBSS5saXZlcztcblxuXG4gICAgICAgIC8vbW92ZSBiYWNrZ3JvdW5kXG5cbiAgICAgICAgLy8gR2V0IHRoZSB2aWV3cG9ydCBjZW50ZXIgYW5kIHBhZGRlZCBzaXplXG5cdFx0Y29uc3Qgdmlld3BvcnRDZW50ZXIgPSB0aGlzLnZpZXdwb3J0LmdldENlbnRlcigpLmNsb25lKCk7XG5cdFx0Y29uc3QgYmFzZVZpZXdwb3J0U2l6ZSA9IHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS5zY2FsZWQoMik7XG4gICAgICAgIC8vY2hlY2sgcG9zaXRpb24gb2YgcGxheWVyXG4gICAgICAgIHRoaXMucGxheWVyRmFsbG9mZih2aWV3cG9ydENlbnRlciwgYmFzZVZpZXdwb3J0U2l6ZSk7XG4gICAgfVxuXG4gICAgLy8gVE9ETyBwdXQgVUkgY2hhbmdlcyBpbiBoZXJlXG4gICAgcHJvdGVjdGVkIHNldEdhbWVTdGF0ZShnYW1lU3RhdGU/OiBHYW1lU3RhdGUpIHtcbiAgICAgICAgaWYgKGdhbWVTdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5nYW1lU3RhdGVTdGFjay5wdXNoKGdhbWVTdGF0ZSk7XG4gICAgICAgICAgICBJbnB1dFdyYXBwZXIuc2V0U3RhdGUoZ2FtZVN0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ2FtZVN0YXRlU3RhY2sucG9wKCk7XG4gICAgICAgICAgICBJbnB1dFdyYXBwZXIuc2V0U3RhdGUodGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbHplcyB0aGUgbGF5ZXJzXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGluaXRMYXllcnMoKTogdm9pZCB7XG4gICAgICAgIC8vIEFkZCBhIGxheWVyIGZvciBVSVxuICAgICAgICB0aGlzLmFkZFVJTGF5ZXIoXCJVSVwiKTtcblxuICAgICAgICAvLyBBZGQgYSBsYXllciBmb3IgcGxheWVycyBhbmQgZW5lbWllc1xuICAgICAgICB0aGlzLmFkZExheWVyKFwicHJpbWFyeVwiLCAxKTtcblxuICAgICAgICB0aGlzLmJ1ZmZMYXllciA9IHRoaXMuYWRkVUlMYXllcihcImJ1ZmZMYXllclwiKTsgIFxuICAgIFxuXG4gICAgICAgIHRoaXMuc3RvcnlMYXllciA9IHRoaXMuYWRkVUlMYXllcihcInN0b3J5XCIpO1xuICAgICAgICB0aGlzLnN0b3J5TGF5ZXIuZGlzYWJsZSgpO1xuXG4gICAgICAgIHRoaXMucGF1c2VMYXllciA9IHRoaXMuYWRkVUlMYXllcihcInBhdXNlXCIpO1xuICAgICAgICB0aGlzLnBhdXNlTGF5ZXIuZGlzYWJsZSgpO1xuXG5cbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJsb2FkU3RvcnlcIik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgcHJvdGVjdGVkIGluaXRWaWV3cG9ydCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy52aWV3cG9ydC5zZXRab29tTGV2ZWwoMik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyBhbGwgc3Vic2NyaXB0aW9ucyB0byBldmVudHNcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc3Vic2NyaWJlVG9FdmVudHMoKXtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoW1xuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5QTEFZRVJfQ09MTElERSxcbiAgICAgICAgICAgIFBsYXllcl9FdmVudHMuUExBWUVSX0hJVF9FTkVNWSxcbiAgICAgICAgICAgIFBsYXllcl9FdmVudHMuRU5FTVlfS0lMTEVELFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5MRVZFTF9TVEFSVCxcbiAgICAgICAgICAgIFBsYXllcl9FdmVudHMuTEVWRUxfRU5ELFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5QTEFZRVJfS0lMTEVELFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5HSVZFX1JFR1VMQVJfQlVGRixcbiAgICAgICAgICAgIFBsYXllcl9FdmVudHMuR0lWRV9TUEVDSUFMX0JVRkZcbiAgICAgICAgXSk7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiYnVmZjFcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiYnVmZjJcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiYnVmZjNcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiY2hlYXRcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwic3RhcnRTdG9yeVwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJzdGFydFRpbWVyXCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImVuZFN0b3J5XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcIm5leHRMZXZlbFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJNYWluTWVudVwiKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPIC0gXG4gICAgLyoqXG4gICAgICogQWRkcyBpbiBhbnkgbmVjZXNzYXJ5IFVJIHRvIHRoZSBnYW1lXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFkZFVJKCl7XG4gICAgICAgIC8vIEluLWdhbWUgbGFiZWxzXG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwgPSA8TGFiZWw+IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIse3Bvc2l0aW9uOiBuZXcgVmVjMig3MCwgMzUpLCB0ZXh0OiBcIlBsYXllciBIZWFsdGg6IFwiKyAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuYWkpLkNVUlJFTlRfSFAgfSk7XG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwuc2V0SEFsaWduKEhBbGlnbi5MRUZUKTtcbiAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5HUkVFTjtcbiAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC5mb250ID0gXCJQaXhlbFNpbXBsZVwiO1xuICAgICAgICB0aGlzLmhlYWx0aExhYmVsLmZvbnRTaXplID0gMjU7XG4gICAgICAgIHRoaXMuaGVhbHRoQmFyID0gPFJlY3Q+dGhpcy5hZGQuZ3JhcGhpYyhHcmFwaGljVHlwZS5SRUNULCBcIlVJXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoMCwgMCksIHNpemU6IG5ldyBWZWMyKDAsIDApfSk7XG4gICAgICAgIHRoaXMuaGVhbHRoQmFyLmJvcmRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuaGVhbHRoQmFyLmJvcmRlcldpZHRoID0gMztcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIuY29sb3IgPSBDb2xvci5HUkVFTjtcblxuICAgICAgICAvLyB0aGlzLnBvaXNvblN0YXQgPSB0aGlzLmFkZC5zcHJpdGUoXCJwb2lzb25pbmdcIiwgXCJVSVwiKTtcbiAgICAgICAgLy8gdGhpcy5wb2lzb25TdGF0LnBvc2l0aW9uLnNldCg1NSwgMjUpO1xuICAgICAgICAvLyB0aGlzLnBvaXNvblN0YXQuc2NhbGUuc2V0KDAuMywgMC4zKTtcbiAgICAgICAgLy8gdGhpcy5idXJuU3RhdCA9IHRoaXMuYWRkLnNwcml0ZShcImJ1cm5pbmdcIiwgXCJVSVwiKTtcbiAgICAgICAgLy8gdGhpcy5idXJuU3RhdC5wb3NpdGlvbi5zZXQoNzAsIDI1KTtcbiAgICAgICAgLy8gdGhpcy5idXJuU3RhdC5zY2FsZS5zZXQoMC4zLCAwLjMpO1xuICAgICAgICAvLyB0aGlzLmJsZWVkU3RhdCA9IHRoaXMuYWRkLnNwcml0ZShcImJsZWVkaW5nXCIsIFwiVUlcIik7XG4gICAgICAgIC8vIHRoaXMuYmxlZWRTdGF0LnBvc2l0aW9uLnNldCg4NSwgMjUpO1xuICAgICAgICAvLyB0aGlzLmJsZWVkU3RhdC5zY2FsZS5zZXQoMC4zLCAwLjMpO1xuXG4gICAgICAgIHRoaXMuc2hpZWxkTGFiZWwgPSA8TGFiZWw+IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIse3Bvc2l0aW9uOiBuZXcgVmVjMig3MCwgNjUpLCB0ZXh0OiBcInNoaWVsZDogXCIrICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5haSkuQ1VSUkVOVF9TSElFTEQgfSk7XG4gICAgICAgIHRoaXMuc2hpZWxkTGFiZWwuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIHRoaXMuc2hpZWxkTGFiZWwuc2V0SEFsaWduKEhBbGlnbi5MRUZUKTtcbiAgICAgICAgdGhpcy5zaGllbGRMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5PUkFOR0U7XG4gICAgICAgIHRoaXMuc2hpZWxkTGFiZWwuZm9udCA9IFwiUGl4ZWxTaW1wbGVcIjtcbiAgICAgICAgdGhpcy5zaGllbGRMYWJlbC5mb250U2l6ZSA9IDI1O1xuICAgICAgICB0aGlzLnNoaWVsZEJhciA9IDxSZWN0PnRoaXMuYWRkLmdyYXBoaWMoR3JhcGhpY1R5cGUuUkVDVCwgXCJVSVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKDAsIDApLCBzaXplOiBuZXcgVmVjMigwLCAwKX0pO1xuICAgICAgICB0aGlzLnNoaWVsZEJhci5ib3JkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICB0aGlzLnNoaWVsZEJhci5ib3JkZXJXaWR0aCA9IDM7XG4gICAgICAgIHRoaXMuc2hpZWxkQmFyLmNvbG9yID0gQ29sb3IuT1JBTkdFO1xuXG5cblxuICAgICAgICB0aGlzLnBsYXllckxldmVsTGFiZWwgPSA8TGFiZWw+IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIse3Bvc2l0aW9uOiBuZXcgVmVjMigyMCwgOTUpLCB0ZXh0OiBcIkx2LiBcIisgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLmFpKS5sZXZlbCB9KTtcbiAgICAgICAgdGhpcy5wbGF5ZXJMZXZlbExhYmVsLnNpemUuc2V0KDAsIDUwKTtcbiAgICAgICAgdGhpcy5wbGF5ZXJMZXZlbExhYmVsLnNldEhBbGlnbihIQWxpZ24uTEVGVCk7XG4gICAgICAgIHRoaXMucGxheWVyTGV2ZWxMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5CTFVFO1xuICAgICAgICB0aGlzLnBsYXllckxldmVsTGFiZWwuZm9udCA9IFwiUGl4ZWxTaW1wbGVcIjtcbiAgICAgICAgdGhpcy5wbGF5ZXJMZXZlbExhYmVsLmZvbnRTaXplID0gMjU7XG5cbiAgICAgICAgdGhpcy5leHBMYWJlbCA9IDxMYWJlbD4gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiVUlcIix7cG9zaXRpb246IG5ldyBWZWMyKDEwMCwgOTUpLCB0ZXh0OiBcIkVYUDogXCIrICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5haSkuQ1VSUkVOVF9FWFAgfSk7XG4gICAgICAgIHRoaXMuZXhwTGFiZWwuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIHRoaXMuZXhwTGFiZWwuc2V0SEFsaWduKEhBbGlnbi5MRUZUKTtcbiAgICAgICAgdGhpcy5leHBMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5CTFVFO1xuICAgICAgICB0aGlzLmV4cExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG4gICAgICAgIHRoaXMuZXhwTGFiZWwuZm9udFNpemUgPSAyNTtcbiAgICAgICAgdGhpcy5leHBCYXIgPSA8UmVjdD50aGlzLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIFwiVUlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMig5NSwgODApLCBzaXplOiBuZXcgVmVjMigxNTAsIDEwKX0pO1xuICAgICAgICB0aGlzLmV4cEJhci5ib3JkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICB0aGlzLmV4cEJhci5ib3JkZXJXaWR0aCA9IDM7XG4gICAgICAgIHRoaXMuZXhwQmFyLmNvbG9yID0gQ29sb3IuQkxVRTtcblxuICAgICAgICAvL3NlZWQgbGFiZWxcbiAgICAgICAgLy93b3JsZHNpemUueCBkb2VzbnQgd29yayBob3cgaSB3YW50IGl0IHRvXG4gICAgICAgIHRoaXMuc2VlZExhYmVsID0gPExhYmVsPiB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJVSVwiLHtwb3NpdGlvbjogbmV3IFZlYzIoNzAsIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkqMiAtIDMwKSksIHRleHQ6IFwiU2VlZDogXCIrIElucHV0V3JhcHBlci5yYW5kb21TZWVkIH0pO1xuICAgICAgICB0aGlzLnNlZWRMYWJlbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgdGhpcy5zZWVkTGFiZWwuc2V0SEFsaWduKEhBbGlnbi5MRUZUKTtcbiAgICAgICAgdGhpcy5zZWVkTGFiZWwudGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuc2VlZExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG4gICAgICBcblxuXG4gICAgICAgIHRoaXMuYWRkLnNwcml0ZShcImJsYWNrXCIsIFwicGF1c2VcIik7XG4gICAgICAgIHRoaXMuYWRkLnNwcml0ZShcImJsYWNrXCIsIFwic3RvcnlcIik7XG4gICAgICAgIHRoaXMuYWRkLnNwcml0ZShcImJsYWNrXCIsIFwiYnVmZkxheWVyXCIpO1xuXG4gICAgICAgIC8vVE9ETyAtIFxuICAgICAgICAvL2RldGVybWluZSBidXR0b24gbG9jYXRpb24gXG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjEgPSA8QnV0dG9uPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJidWZmTGF5ZXJcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54KjIvMy0xODAvMiksIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkpKSx0ZXh0OlwiXCJ9KTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS5zaXplLnNldCgxODAsMjAwKTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS5ib3JkZXJXaWR0aCA9IDU7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjEuYm9yZGVyQ29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjEuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjEudGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjEub25DbGlja0V2ZW50SWQgPSBcImJ1ZmYxXCI7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjEuZm9udFNpemUgPSAyMDtcbiAgICAgICAgdGhpcy5idWZmTGFiZWwxID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImJ1ZmZMYXllclwiLCB7cG9zaXRpb246IG5ldyBWZWMyKHRoaXMuYnVmZkJ1dHRvbjEucG9zaXRpb24ueCwgdGhpcy5idWZmQnV0dG9uMS5wb3NpdGlvbi55IC0gNDApLHRleHQ6XCJidWZmTGFiZWwxXCJ9KTtcbiAgICAgICAgdGhpcy5idWZmTGFiZWwxLmZvbnRTaXplID0gMjA7XG5cblxuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24yID0gPEJ1dHRvbj50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwiYnVmZkxheWVyXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCksIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkpKSx0ZXh0OlwiXCJ9KTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi5zaXplLnNldCgxODAsMjAwKTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi5ib3JkZXJXaWR0aCA9IDU7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjIuYm9yZGVyQ29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjIuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjIudGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjIub25DbGlja0V2ZW50SWQgPSBcImJ1ZmYyXCI7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjIuZm9udFNpemUgPSAyMDtcbiAgICAgICAgdGhpcy5idWZmTGFiZWwyID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImJ1ZmZMYXllclwiLCB7cG9zaXRpb246IG5ldyBWZWMyKHRoaXMuYnVmZkJ1dHRvbjIucG9zaXRpb24ueCwgdGhpcy5idWZmQnV0dG9uMi5wb3NpdGlvbi55IC0gNDApLHRleHQ6XCJidWZmTGFiZWwyXCJ9KTtcbiAgICAgICAgdGhpcy5idWZmTGFiZWwyLmZvbnRTaXplID0gMjA7XG5cbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMyA9IDxCdXR0b24+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcImJ1ZmZMYXllclwiLCB7cG9zaXRpb246IG5ldyBWZWMyKE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLngqNC8zKzE4MC8yKSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSkpLCB0ZXh0OlwiXCJ9KTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy5zaXplLnNldCgxODAsMjAwKTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy5ib3JkZXJXaWR0aCA9IDU7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjMuYm9yZGVyQ29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjMuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjMudGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjMub25DbGlja0V2ZW50SWQgPSBcImJ1ZmYzXCI7XG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjMuZm9udFNpemUgPSAyMDtcbiAgICAgICAgdGhpcy5idWZmTGFiZWwzID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImJ1ZmZMYXllclwiLCB7cG9zaXRpb246IG5ldyBWZWMyKHRoaXMuYnVmZkJ1dHRvbjMucG9zaXRpb24ueCwgdGhpcy5idWZmQnV0dG9uMy5wb3NpdGlvbi55IC0gNDApLCB0ZXh0OlwiYnVmZkxhYmVsM1wifSk7XG4gICAgICAgIHRoaXMuYnVmZkxhYmVsMy5mb250U2l6ZSA9IDIwO1xuXG4gICAgICAgIHRoaXMuYnVmZnMgPSAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZ2VuZXJhdGVSZWd1bGFyQnVmZnMoKTtcblxuICAgICAgICB0aGlzLmJ1ZmZMYXllci5kaXNhYmxlKCk7XG5cbiAgICAgICAgdGhpcy5wYXVzZVRleHQgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwicGF1c2VcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54IC0gMTIwKSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSAtIDEwMCkpLCB0ZXh0OiBcIlwifSk7XG4gICAgICAgIHRoaXMucGF1c2VJbnB1dCA9IDxUZXh0SW5wdXQ+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuVEVYVF9JTlBVVCwgXCJwYXVzZVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnggLSAyMCksIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkgKyAxMDApKSwgdGV4dDogXCJcIn0pO1xuICAgICAgICB0aGlzLnBhdXNlQ2hlYXRUZXh0ID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcInBhdXNlXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCAtIDEyMCksIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkgKyA4MCkpLCB0ZXh0OiBcIuKsh++4j+Ksh++4j+Ksh++4j0NoZWF0IENvZGXirIfvuI/irIfvuI/irIfvuI9cIn0pO1xuICAgICAgICB0aGlzLnBhdXNlU3VibWl0ID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcInBhdXNlXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCArIDEyMCksIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkgKyAxMDApKSwgdGV4dDogXCJTdWJtaXRcIn0pO1xuXG4gICAgICAgIFxuICAgICAgICB0aGlzLnBhdXNlTGF5ZXIuc2V0QWxwaGEoMC41KTtcbiAgICAgICAgdGhpcy5wYXVzZVRleHQudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMucGF1c2VUZXh0LnNldEhBbGlnbihIQWxpZ24uTEVGVCk7XG4gICAgICAgIHRoaXMucGF1c2VUZXh0LnNpemUgPSBuZXcgVmVjMigwLCA0MCk7XG4gICAgICAgIHRoaXMucGF1c2VUZXh0LnRleHQgPSBcIkhQOlxcbkFUSzpcXG5EYW1hZ2UgUmF0aW86XFxuQnVmZjE6XFxuQnVmZjI6XFxuQnVmZjM6XFxuQnVmZjQ6XFxuQnVmZjU6XFxuQnVmZjY6XFxuRW5lbXkgS2lsbGVkOlxcblwiXG4gICAgICAgIHRoaXMucGF1c2VDaGVhdFRleHQudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMucGF1c2VDaGVhdFRleHQuc2l6ZSA9IG5ldyBWZWMyKDAsIDQwKTtcbiAgICAgICAgdGhpcy5wYXVzZUNoZWF0VGV4dC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLnBhdXNlSW5wdXQuc2l6ZS5zZXQoNDAwLCAzMCk7XG4gICAgICAgIHRoaXMucGF1c2VTdWJtaXQudGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMucGF1c2VTdWJtaXQuYm9yZGVyQ29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5wYXVzZVN1Ym1pdC5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5wYXVzZVN1Ym1pdC5vbkNsaWNrRXZlbnRJZCA9IFwiY2hlYXRcIjtcbiAgICAgICAgdGhpcy5wYXVzZVN1Ym1pdC5ib3JkZXJXaWR0aCA9IDM7XG5cbiAgICAgICAgdGhpcy5tYWluTWVudUJ1dHRvbiA9IDxCdXR0b24+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInBhdXNlXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCApLCBNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS55ICsgMTUwKSksIHRleHQ6XCJNYWluIE1lbnVcIn0pO1xuICAgICAgICB0aGlzLm1haW5NZW51QnV0dG9uLnNpemUuc2V0KDE4MCw1MCk7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uYm9yZGVyV2lkdGggPSA1O1xuICAgICAgICB0aGlzLm1haW5NZW51QnV0dG9uLmJvcmRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uYmFja2dyb3VuZENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24udGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24ub25DbGlja0V2ZW50SWQgPSBcIk1haW5NZW51XCI7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uZm9udFNpemUgPSAyMDtcbiAgICAgICAgXG5cbiAgICAgICAgdGhpcy5saXZlc0NvdW50TGFiZWwgPSAgPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLngqMiAtIDEwMCwgMzApLCB0ZXh0OlwiTGl2ZXM6IFwifSk7XG4gICAgICAgIHRoaXMubGl2ZXNDb3VudExhYmVsLnRleHRDb2xvciA9IENvbG9yLllFTExPVztcbiAgICAgICAgdGhpcy5saXZlc0NvdW50TGFiZWwuZm9udFNpemUgPSAyNTtcblxuICAgICAgICB0aGlzLnRpbWVyTGFibGUgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiVUlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54KSwgMzApLCB0ZXh0OiBcIjAwOjAwXCJ9KTtcbiAgICAgICAgdGhpcy50aW1lckxhYmxlLmZvbnRTaXplID0gNjA7XG59XG5cbiAgICAvL1RPRE8gLSBkZXRlcm1pbmUgd2hldGhlciB3ZSB3aWxsIGhhdmUgd2VhcG9uIGRhdGF0eXBlXG4gICAgLyoqXG4gICAgICogXG4gICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIG5ldyB3ZWFwb25cbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgd2VhcG9uVHlwZSBvZiB0aGUgd2VhcG9uLCBhcyBhIHN0cmluZ1xuICAgICAqL1xuICAgICBjcmVhdGVXZWFwb24odHlwZTogc3RyaW5nKTogV2VhcG9uIHtcbiAgICAgICAgbGV0IHdlYXBvblR5cGUgPSA8V2VhcG9uVHlwZT5SZWdpc3RyeU1hbmFnZXIuZ2V0UmVnaXN0cnkoXCJ3ZWFwb25UeXBlc1wiKS5nZXQodHlwZSk7XG5cbiAgICAgICAgbGV0IHNwcml0ZSA9IHRoaXMuYWRkLnNwcml0ZSh3ZWFwb25UeXBlLnNwcml0ZUtleSwgXCJwcmltYXJ5XCIpO1xuXG4gICAgICAgIHJldHVybiBuZXcgV2VhcG9uKHNwcml0ZSwgd2VhcG9uVHlwZSwgdGhpcy5iYXR0bGVNYW5hZ2VyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0YWxpemVzIGFsbCB3ZWFwb24gdHlwZXMgYmFzZWQgb2YgZGF0YSBmcm9tIHdlYXBvbkRhdGEuanNvblxuICAgICAqL1xuICAgICBpbml0aWFsaXplV2VhcG9ucygpOiB2b2lke1xuICAgICAgICBsZXQgd2VhcG9uRGF0YSA9IHRoaXMubG9hZC5nZXRPYmplY3QoXCJ3ZWFwb25EYXRhXCIpO1xuXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB3ZWFwb25EYXRhLm51bVdlYXBvbnM7IGkrKyl7XG4gICAgICAgICAgICBsZXQgd2VhcG9uID0gd2VhcG9uRGF0YS53ZWFwb25zW2ldO1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBwcm90b3R5cGVcbiAgICAgICAgICAgIGxldCBjb25zdHIgPSBSZWdpc3RyeU1hbmFnZXIuZ2V0UmVnaXN0cnkoXCJ3ZWFwb25UZW1wbGF0ZXNcIikuZ2V0KHdlYXBvbi53ZWFwb25UeXBlKTtcblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgd2VhcG9uIHR5cGVcbiAgICAgICAgICAgIGxldCB3ZWFwb25UeXBlID0gbmV3IGNvbnN0cigpO1xuXG4gICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICAgICAgd2VhcG9uVHlwZS5pbml0aWFsaXplKHdlYXBvbik7XG5cbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICAgICAgUmVnaXN0cnlNYW5hZ2VyLmdldFJlZ2lzdHJ5KFwid2VhcG9uVHlwZXNcIikucmVnaXN0ZXJJdGVtKHdlYXBvbi5uYW1lLCB3ZWFwb25UeXBlKVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBwbGF5ZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdFBsYXllcigpOiB2b2lkIHtcbiAgICAgICAgLy9jcmVhdGUgdGhlIGludmVudG9yeVxuICAgICAgICBsZXQgaW52ZW50b3J5ID0gbmV3IEludmVudG9yeU1hbmFnZXIodGhpcywgMSwgXCJpbnZlbnRvcnlTbG90XCIsIG5ldyBWZWMyKDE2LCAxNiksIDQsIFwic2xvdHMxXCIsIFwiaXRlbXMxXCIpO1xuICAgICAgICBcblxuICAgICAgICAvL2FkZCBzdGFydGluZyB3ZWFwb24gdG8gaW52ZW50b3J5XG4gICAgICAgIGxldCBzdGFydGluZ1dlYXBvbiA9IHRoaXMuY3JlYXRlV2VhcG9uKFwia25pZmVcIik7XG4gICAgICAgIGludmVudG9yeS5hZGRJdGVtKHN0YXJ0aW5nV2VhcG9uKTsgICAgICAgICAgICAgIC8vdXNpbmcgc2xpY2UgdG8gdGVzdCByaWdodCBub3dcblxuXG4gICAgICAgIC8vIEFkZCB0aGUgcGxheWVyXG4gICAgICAgIHRoaXMucGxheWVyID0gdGhpcy5hZGQuYW5pbWF0ZWRTcHJpdGUoXCJwbGF5ZXJcIiwgXCJwcmltYXJ5XCIpO1xuICAgICAgICB0aGlzLnBsYXllci5zY2FsZS5zZXQoMSwgMSk7XG4gICAgICAgIGlmKCF0aGlzLnBsYXllclNwYXduKXtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlBsYXllciBzcGF3biB3YXMgbmV2ZXIgc2V0IC0gc2V0dGluZyBzcGF3biB0byAoMCwgMClcIik7XG4gICAgICAgICAgICB0aGlzLnBsYXllclNwYXduID0gVmVjMi5aRVJPO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RhcnRwb3MgPSB0aGlzLnBsYXllclNwYXduO1xuICAgICAgICB0aGlzLnBsYXllci5wb3NpdGlvbi5jb3B5KHRoaXMucGxheWVyU3Bhd24pO1xuICAgICAgICB0aGlzLnBsYXllci5hZGRQaHlzaWNzKG5ldyBBQUJCKFZlYzIuWkVSTywgbmV3IFZlYzIoMTQsIDE2KSkpOyAgLy9zZXRzIHRoZSBjb2xsaXNpb24gc2hhcGVcbiAgICAgICAgdGhpcy5wbGF5ZXIuY29sbGlkZXJPZmZzZXQuc2V0KDAsIDE2KTtcbiAgICAgICAgdGhpcy5wbGF5ZXIuYWRkQUkoUGxheWVyQ29udHJvbGxlciwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGxheWVyVHlwZTogXCJwbGF0Zm9ybWVyXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcDogXCJNYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVlZDogMTAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhbHRoOiAxMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGludmVudG9yeTogaW52ZW50b3J5LFxuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXM6IHRoaXMuaXRlbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dEVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IDEwMFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnBsYXllci5zZXRHcm91cChcInBsYXllclwiKTtcblxuICAgICAgICB0aGlzLnZpZXdwb3J0LmZvbGxvdyh0aGlzLnBsYXllcik7XG4gICAgfVxuXG4gICAgXG4gICAgLy9UT0RPIC0gXG4gICAgLyoqXG4gICAgICogQWRkcyBhbiBFbmVteSBpbnRvIHRoZSBnYW1lXG4gICAgICogQHBhcmFtIHNwcml0ZUtleSBUaGUga2V5IG9mIHRoZSBFbmVteSBzcHJpdGVcbiAgICAgKiBAcGFyYW0gdGlsZVBvcyBUaGUgdGlsZW1hcCBwb3NpdGlvbiB0byBhZGQgdGhlIEVuZW15IHRvXG4gICAgICogQHBhcmFtIGFpT3B0aW9ucyBUaGUgb3B0aW9ucyBmb3IgdGhlIEVuZW15IEFJXG4gICAgICovXG4gICAgXG4gICAgcHJvdGVjdGVkIGFkZEVuZW15PFQgZXh0ZW5kcyBFbmVteUFJPihzcHJpdGVLZXk6IHN0cmluZywgdGlsZVBvczogVmVjMiwgYWk6IG5ldygpID0+IFQsIGFpT3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICBsZXQgZW5lbXkgPSB0aGlzLmFkZC5hbmltYXRlZFNwcml0ZShzcHJpdGVLZXksIFwicHJpbWFyeVwiKTtcbiAgICAgICAgLy9lbmVteS5wb3NpdGlvbi5zZXQodGlsZVBvcy54KjMyLCB0aWxlUG9zLnkqMzIpO1xuICAgICAgICBlbmVteS5wb3NpdGlvbi5jb3B5KHRpbGVQb3MpO1xuICAgICAgICBcbiAgICAgICAgaWYoIFwic2NhbGVcIiBpbiBhaU9wdGlvbnMpe1xuICAgICAgICAgICAgZW5lbXkuc2NhbGUuc2V0KGFpT3B0aW9ucy5zY2FsZSxhaU9wdGlvbnMuc2NhbGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2V7XG4gICAgICAgICAgICBlbmVteS5zY2FsZS5zZXQoMiwgMik7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gLSBhZGQgY3VzdG9tIGNvbGxpc2lvbiBzaGFwZSBmb3IgZWFjaCBlbmVteSBpbiBhbiBvcHRpb24gdmFyaWFibGUgXG4gICAgICAgIGlmKCBcInNpemVcIiBpbiBhaU9wdGlvbnMpe1xuICAgICAgICAgICAgZW5lbXkuYWRkUGh5c2ljcyhuZXcgQUFCQihWZWMyLlpFUk8sIGFpT3B0aW9ucy5zaXplLmNsb25lKCkpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgZW5lbXkuYWRkUGh5c2ljcyhuZXcgQUFCQihWZWMyLlpFUk8sIG5ldyBWZWMyKDE2LCAyNSkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFwib2Zmc2V0XCIgaW4gYWlPcHRpb25zKXtcbiAgICAgICAgICAgIGVuZW15LmNvbGxpZGVyT2Zmc2V0LnNldChhaU9wdGlvbnMub2Zmc2V0LngsYWlPcHRpb25zLm9mZnNldC55KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgZW5lbXkuY29sbGlkZXJPZmZzZXQuc2V0KDAsIDYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZW5lbXkuYWRkQUkoYWksIGFpT3B0aW9ucyk7IC8vVE9ETyAtIGFkZCBpbmRpdmlkdWFsIGVuZW15IEFJXG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmhlYWx0aEJhciA9IDxSZWN0PnRoaXMuYWRkLmdyYXBoaWMoR3JhcGhpY1R5cGUuUkVDVCwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogZW5lbXkuY29sbGlzaW9uU2hhcGUuY2VudGVyLmNsb25lKCkuYWRkKG5ldyBWZWMyKDAsIC0oKDxBQUJCPmVuZW15LmNvbGxpc2lvblNoYXBlKS5oaCs1KSkpLCBzaXplOiBuZXcgVmVjMigoPEFBQkI+ZW5lbXkuY29sbGlzaW9uU2hhcGUpLmh3KjMsIDUpfSk7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmhlYWx0aEJhci5ib3JkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5oZWFsdGhCYXIuYm9yZGVyV2lkdGggPSAxO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5oZWFsdGhCYXIuY29sb3IgPSBDb2xvci5HUkVFTjtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkucG9pc29uU3RhdCA9IHRoaXMuYWRkLnNwcml0ZShcInBvaXNvbmluZ1wiLCBcInByaW1hcnlcIik7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLnBvaXNvblN0YXQucG9zaXRpb24gPSBlbmVteS5jb2xsaXNpb25TaGFwZS5jZW50ZXIuY2xvbmUoKS5hZGQobmV3IFZlYzIoKCgoPEFBQkI+ZW5lbXkuY29sbGlzaW9uU2hhcGUpLmh3KSotMSwgLSgoPEFBQkI+ZW5lbXkuY29sbGlzaW9uU2hhcGUpLmhoKzUpKSkpO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5wb2lzb25TdGF0LnNjYWxlLnNldCgxLCAxKTtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkuYnVyblN0YXQgPSB0aGlzLmFkZC5zcHJpdGUoXCJidXJuaW5nXCIsIFwicHJpbWFyeVwiKTtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkuYnVyblN0YXQucG9zaXRpb24gPSAoPEVuZW15QUk+ZW5lbXkuX2FpKS5wb2lzb25TdGF0LnBvc2l0aW9uLmNsb25lKCkuYWRkKG5ldyBWZWMyKDE1LCAwKSk7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmJ1cm5TdGF0LnNjYWxlLnNldCgxLCAxKTtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkuYmxlZWRTdGF0ID0gdGhpcy5hZGQuc3ByaXRlKFwiYmxlZWRpbmdcIiwgXCJwcmltYXJ5XCIpO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5ibGVlZFN0YXQucG9zaXRpb24gPSAoPEVuZW15QUk+ZW5lbXkuX2FpKS5wb2lzb25TdGF0LnBvc2l0aW9uLmNsb25lKCkuYWRkKG5ldyBWZWMyKDMwLCAwKSk7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmJsZWVkU3RhdC5zY2FsZS5zZXQoMSwgMSk7XG4gICAgICAgIGVuZW15LnNldEdyb3VwKFwiRW5lbXlcIik7XG4gICAgICAgIGVuZW15LnNldFRyaWdnZXIoXCJwbGF5ZXJcIiwgUGxheWVyX0V2ZW50cy5QTEFZRVJfQ09MTElERSwgbnVsbCk7XG5cbiAgICAgICAgLy9hZGQgZW5lbXkgdG8gdGhlIGVuZW15IGFycmF5XG4gICAgICAgIHRoaXMuZW5lbWllcy5wdXNoKGVuZW15KTtcbiAgICAgICAgLy90aGlzLmJhdHRsZU1hbmFnZXIuc2V0RW5lbWllcyh0aGlzLmVuZW1pZXMubWFwKGVuZW15ID0+IDxCYXR0bGVyQUk+ZW5lbXkuX2FpKSk7XG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlci5hZGRFbmVteSg8QmF0dGxlckFJPmVuZW15Ll9haSk7XG4gICAgfVxuICAgIFxuXG4gICAgLy9UT0RPIC0gZ2l2ZSBlYWNoIGVuZW15IHVuaXF1ZSB3ZWFwb25cbiAgICBwcm90ZWN0ZWQgaW5pdGlhbGl6ZUVuZW1pZXMoIGVuZW1pZXM6IEVuZW15W10pe1xuICAgICAgICBmb3IgKGxldCBlbmVteSBvZiBlbmVtaWVzKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGVuZW15LnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFwiU25ha2VcIjogICAgICAgLy9TbmFrZSBlbmVtaWVzIGRyb3AgZnJvbSBza3koXCJ0cmVlc1wiKT8gb3IgY291bGQganVzdCBiZSB2ZXJ5IGFidW5kYW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRW5lbXkoXCJTbmFrZVwiLCBlbmVteS5wb3NpdGlvbi5zY2FsZSgzMiksIFNuYWtlQUksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDUwLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcDogXCJNYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplOiBuZXcgVmVjMigxNCwxMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgOiBuZXcgVmVjMigwLCAyMiksXG4gICAgICAgICAgICAgICAgICAgICAgICBleHA6IDUwLFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiVGlnZXJcIjogICAgICAgLy9UaWdlciBjYW4gYmUgbWluaWJvc3MgZm9yIG5vdz8gXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRW5lbXkoXCJUaWdlclwiLCBlbmVteS5wb3NpdGlvbi5zY2FsZSgzMiksIEVuZW15QUksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDIwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVtYXA6IFwiTWFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwOiAxMDAsXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBcInJlbXVzX3dlcmV3b2xmXCI6ICAgICAgIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEVuZW15KFwicmVtdXNfd2VyZXdvbGZcIiwgZW5lbXkucG9zaXRpb24uc2NhbGUoMzIpLCBFbmVteUFJLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwbGF5ZXI6IHRoaXMucGxheWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhbHRoOiAyMDAsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aWxlbWFwOiBcIk1haW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cDogNTAsXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJibGFja19wdWRkaW5nXCI6ICAgICAgIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEVuZW15KFwiYmxhY2tfcHVkZGluZ1wiLCBlbmVteS5wb3NpdGlvbi5zY2FsZSgzMiksIFNsaW1lQUksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDIwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVtYXA6IFwiTWFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9hY3Rpb25zOmFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZTogLjI1LFxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogbmV3IFZlYzIoMTYsMTApLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0IDogbmV3IFZlYzIoMCw2KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cDogNTAsXG4gICAgICAgICAgICAgICAgICAgICAgICB3ZWFwb24gOiB0aGlzLmNyZWF0ZVdlYXBvbihcImtuaWZlXCIpLFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFkZENoZWNrUG9pbnQoc3RhcnRpbmdUaWxlOiBWZWMyLCBzaXplOiBWZWMyLCBlbnRlcjogc3RyaW5nLCBleGl0OiBzdHJpbmcpOiBSZWN0IHtcbiAgICAgICAgbGV0IGNoZWNrUG9pbnQgPSA8UmVjdD50aGlzLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IHN0YXJ0aW5nVGlsZS5zY2FsZSgzMiksIHNpemU6IHNpemUuc2NhbGUoMzIpfSk7XG4gICAgICAgIGNoZWNrUG9pbnQuYWRkUGh5c2ljcyh1bmRlZmluZWQsIHVuZGVmaW5lZCwgZmFsc2UsIHRydWUpO1xuICAgICAgICBjaGVja1BvaW50LnNldFRyaWdnZXIoXCJwbGF5ZXJcIiwgZW50ZXIsIG51bGwpO1xuICAgICAgICBjaGVja1BvaW50LmNvbG9yID0gbmV3IENvbG9yKDAsIDAsIDAsIDApO1xuICAgICAgICByZXR1cm4gY2hlY2tQb2ludDtcbiAgICB9XG5cbiAgIFxuICAgIC8qKlxuICAgICAqIGRhbWFnZXMgdGhlIHBsYXllciBpZiB0aGV5IGNvbGxpZGUgd2l0aCBhbiBlbmVteVxuICAgICAqIEBwYXJhbSBwbGF5ZXIgcGxheWVyIHNwcml0ZVxuICAgICAqIEBwYXJhbSBlbmVteSBlbmVteSBzcHJpdGVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaGFuZGxlUGxheWVyRW5lbXlDb2xsaXNpb24ocGxheWVyOiBBbmltYXRlZFNwcml0ZSwgZW5lbXk6IEFuaW1hdGVkU3ByaXRlKSB7XG4gICAgICAgIGlmKGVuZW15ID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJ1bmRlZmluZWQgZW5lbXlcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYoIHBsYXllciA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidW5kZWZpbmVkIHBsYXllclwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZih0eXBlb2YgZW5lbXkgIT0gdW5kZWZpbmVkICYmIHR5cGVvZiBwbGF5ZXIgIT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAvL2RhbWFnZSB0aGUgcGxheWVyIFxuICAgICAgICAgICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmNvbGxpZGVXaXRoUGxheWVyKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSk7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluY3JlbWVudHMgdGhlIGFtb3VudCBvZiBsaWZlIHRoZSBwbGF5ZXIgaGFzXG4gICAgICogQHBhcmFtIGFtdCBUaGUgYW1vdW50IHRvIGFkZCB0byB0aGUgcGxheWVyIGxpZmVcbiAgICAgKi9cbiAgICAvKlxuICAgIHByb3RlY3RlZCBpbmNQbGF5ZXJMaWZlKGFtdDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIEdhbWVMZXZlbC5saXZlc0NvdW50ICs9IGFtdDtcbiAgICAgICAgdGhpcy5saXZlc0NvdW50TGFiZWwudGV4dCA9IFwiTGl2ZXM6IFwiICsgR2FtZUxldmVsLmxpdmVzQ291bnQ7XG4gICAgICAgIGlmIChHYW1lTGV2ZWwubGl2ZXNDb3VudCA9PT0gMCl7XG4gICAgICAgICAgICBJbnB1dFdyYXBwZXIuZGlzYWJsZUlucHV0KCk7XG4gICAgICAgICAgICB0aGlzLnBsYXllci5kaXNhYmxlUGh5c2ljcygpO1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwicGxheWVyX2RlYXRoXCIsIGxvb3A6IGZhbHNlLCBob2xkUmVmZXJlbmNlOiBmYWxzZX0pO1xuICAgICAgICAgICAgdGhpcy5wbGF5ZXIudHdlZW5zLnBsYXkoXCJkZWF0aFwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBwbGF5ZXIgdG8gc3Bhd25cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVzcGF3blBsYXllcigpOiB2b2lkIHtcbiAgICAgICAgSW5wdXRXcmFwcGVyLmVuYWJsZUlucHV0KCk7XG4gICAgICAgIHRoaXMucGxheWVyLnBvc2l0aW9uLmNvcHkodGhpcy5zdGFydHBvcyk7XG4gICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfSFAgPSAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5NQVhfSFAgO1xuICAgICAgICAvLyg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmxpdmVzIC0tO1xuXG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBcbiAgICAgKiBoYW5kbGVzIHRoZSBwbGF5ZXIgZmFsbGluZyBvZmYgdGhlIG1hcFxuICAgICAqIFxuICAgICAqIEBwYXJhbSB2aWV3cG9ydENlbnRlciBUaGUgY2VudGVyIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB2aWV3cG9ydFNpemUgVGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgcHJvdGVjdGVkIHBsYXllckZhbGxvZmYodmlld3BvcnRDZW50ZXI6IFZlYzIsIHZpZXdwb3J0U2l6ZTogVmVjMik6dm9pZHtcbiAgICAgICAgIGlmKHRoaXMucGxheWVyLnBvc2l0aW9uLnkgPj0gdmlld3BvcnRDZW50ZXIueSArdmlld3BvcnRTaXplLnkvMi4wKXtcblx0XHRcdFxuXHRcdFx0dGhpcy5wbGF5ZXIucG9zaXRpb24uc2V0KHRoaXMucGxheWVyU3Bhd24ueCx0aGlzLnBsYXllclNwYXduLnkpO1xuXG4gICAgICAgICAgICAvL1RPRE8gLSBkZWNyZWFzZSBwbGF5ZXIgaGVhbHRoIG9yIGNhbiBraWxsIHBsYXllciBoZXJlXG4gICAgICAgICAgICAvLyg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfSFAgKj0gLjc1O1xuICAgICAgICAgICAgLy90aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuUExBWUVSX0tJTExFRCk7XG5cdFx0fVxuICAgICAgICBcbiAgICB9XG5cblxuICAgIHByb3RlY3RlZCBwbGF5U3RhcnRTdG9yeSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRvdWNoZWRTdGFydENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMudG91Y2hlZFN0YXJ0Q2hlY2tQb2ludCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnN0b3J5TG9hZGVyKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9zdG9yeS5qc29uXCIpO1xuICAgICAgICAgICAgdGhpcy5zdGFydFRpbWVyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcGxheUVuZFN0b3J5KCkge1xuICAgICAgICBpZiAoIXRoaXMudG91Y2hlZEVuZENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMudG91Y2hlZEVuZENoZWNrUG9pbnQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zdG9yeUxvYWRlcihcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvanNvbnMvc3RvcnkuanNvblwiKTtcbiAgICAgICAgICAgIHRoaXMuZW5kVGltZXIoKTtcbiAgICAgICAgICAgIHRoaXMubGV2ZWxFbmRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RhcnRUaW1lcigpIHtcbiAgICAgICAgdGhpcy5nYW1lU3RhcnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGVuZFRpbWVyKCkge1xuICAgICAgICB0aGlzLmdhbWVTdGFydGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdvVG9OZXh0TGV2ZWwoKSB7XG4gICAgICAgIC8vIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoUG9yY2VsYWluKTtcbiAgICB9XG5cblxuICAgIHByb3RlY3RlZCBhc3luYyBzdG9yeUxvYWRlcihzdG9yeVBhdGg6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09IEdhbWVTdGF0ZS5TVE9SWSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0R2FtZVN0YXRlKEdhbWVTdGF0ZS5TVE9SWSk7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgKGF3YWl0IGZldGNoKHN0b3J5UGF0aCkpLmpzb24oKTtcbiAgICAgICAgdGhpcy5zdG9yeSA9IDxTdG9yeT5yZXNwb25zZTtcbiAgICAgICAgY29uc29sZS5sb2coXCJzdG9yeTpcIiwgdGhpcy5zdG9yeSk7XG4gICAgICAgIGlmICh0aGlzLnN0b3J5LmJnbSkge1xuICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMgPSBuZXcgQXJyYXk7XG4gICAgICAgICAgICB0aGlzLnN0b3J5LmJnbS5mb3JFYWNoKChiZ20pID0+IHtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxvYWQuZ2V0QXVkaW8oYmdtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHsga2V5OiBiZ20ua2V5LCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZC5zaW5nbGVBdWRpbyhiZ20ua2V5LCBiZ20ucGF0aCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHsga2V5OiBiZ20ua2V5LCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMucHVzaChiZ20ua2V5KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdXJyZW50U3BlYWtlciA9IHRoaXMuc3RvcnkudGV4dHNbMF0uc3BlYWtlcjtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udGVudCA9IHRoaXMuc3RvcnkudGV4dHNbMF0uY29udGVudDtcbiAgICAgICAgdGhpcy5zdG9yeUxheWVyLmVuYWJsZSgpO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcInN0b3J5XCIsIHsgcG9zaXRpb246IG5ldyBWZWMyKDUwLCB0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSArIDgwKSwgdGV4dDogXCJcIiB9KTtcbiAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC5zaXplID0gbmV3IFZlYzIoMCwgMjUpO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG4gICAgICAgIHRoaXMuc3Rvcnl0ZXh0TGFiZWwuZm9udFNpemUgPSAyNTtcbiAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLnN0b3J5UHJvZ3Jlc3MgPSAtMTtcbiAgICAgICAgdGhpcy5zdG9yeVNwcml0ZXMgPSBuZXcgQXJyYXk7XG4gICAgICAgIHRoaXMudXBkYXRlU3RvcnkoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaGFzTmV4dFN0b3J5KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09ICBHYW1lU3RhdGUuU1RPUlkgJiYgdGhpcy5zdG9yeVByb2dyZXNzICsgMSA8IHRoaXMuc3RvcnkudGV4dHMubGVuZ3RoO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCB1cGRhdGVTdG9yeSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzTmV4dFN0b3J5KCkpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcnlQcm9ncmVzcysrO1xuICAgICAgICAgICAgbGV0IHRtcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3J5LnRleHRzW3RoaXMuc3RvcnlQcm9ncmVzc10uYWN0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5hY3Rpb25zLmZvckVhY2goYWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImxvYWRTcHJpdGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sb2FkLmdldEltYWdlKGFjdGlvbi5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuYWRkLnNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAucG9zaXRpb24uc2V0KGFjdGlvbi5wb3NpdG9uWzBdLCBhY3Rpb24ucG9zaXRvblsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC5zY2FsZS5zZXQoYWN0aW9uLnNjYWxlWzBdLCBhY3Rpb24uc2NhbGVbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWQuc2luZ2xlSW1hZ2UoYWN0aW9uLmtleSwgYWN0aW9uLnBhdGgsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuYWRkLnNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnBvc2l0aW9uLnNldChhY3Rpb24ucG9zaXRvblswXSwgYWN0aW9uLnBvc2l0b25bMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnNjYWxlLnNldChhY3Rpb24uc2NhbGVbMF0sIGFjdGlvbi5zY2FsZVsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIm1vdmVTcHJpdGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAgPSB0aGlzLnN0b3J5U3ByaXRlcy5maW5kKGZ1bmN0aW9uIChzcHJpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNwcml0ZS5pbWFnZUlkID09PSBhY3Rpb24ua2V5O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC5wb3NpdGlvbi5zZXQoYWN0aW9uLnBvc2l0b25bMF0sIGFjdGlvbi5wb3NpdG9uWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAuc2NhbGUuc2V0KGFjdGlvbi5zY2FsZVswXSwgYWN0aW9uLnNjYWxlWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzaG93U3ByaXRlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gdGhpcy5zdG9yeVNwcml0ZXMuZmluZChmdW5jdGlvbiAoc3ByaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzcHJpdGUuaW1hZ2VJZCA9PT0gYWN0aW9uLmtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAudmlzaWJsZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaGlkZVNwcml0ZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuc3RvcnlTcHJpdGVzLmZpbmQoZnVuY3Rpb24gKHNwcml0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ByaXRlLmltYWdlSWQgPT09IGFjdGlvbi5rZXk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdXJyZW50U3BlYWtlciA9IHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5zcGVha2VyO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q29udGVudCA9IHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5jb250ZW50O1xuICAgICAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC50ZXh0ID0gKHRoaXMuY3VycmVudFNwZWFrZXI/KHRoaXMuY3VycmVudFNwZWFrZXIrXCI6XCIpOihcIlwiKSkgKyAnXFxuJyArIHRoaXMuY3VycmVudENvbnRlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5zdG9yeVByb2dyZXNzID0gSW5maW5pdHk7XG4gICAgICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3J5U3ByaXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnlTcHJpdGVzLmZvckVhY2goKHNwcml0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzcHJpdGUudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBzcHJpdGUuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RvcnlCR01zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMuZm9yRWFjaCgoYmdtKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELCB7IGtleTogYmdtIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInNvdW5kIHN0b3BwZWQ6XCIsIGJnbSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0b3J5TGF5ZXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuc3RvcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgLy8gdGhpcy5zdG9yeUxheWVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKHRoaXMubGV2ZWxFbmRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5HSVZFX1NQRUNJQUxfQlVGRiwge30pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlYXRcbiAgICBwcm90ZWN0ZWQgZW5hYmxlQ2hlYXQoKSB7XG4gICAgICAgIGlmICh0aGlzLnBhdXNlSW5wdXQudGV4dC50b1VwcGVyQ2FzZSgpID09PSBcIlVVRERMUkxSQkFCQVwiKSB7XG4gICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5nb2RNb2RlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxldCBjb21tYW5kcyA9IHRoaXMucGF1c2VJbnB1dC50ZXh0LnNwbGl0KCcgJyk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhjb21tYW5kcyk7XG4gICAgICAgICAgICBpZiAoY29tbWFuZHMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbW1hbmRzWzBdLnRvVXBwZXJDYXNlKCkgPT09IFwiU0VUXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb21tYW5kc1sxXS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiQVRLXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuQ1VSUkVOVF9BVEsgPSBwYXJzZUludChjb21tYW5kc1syXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiSFBcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5DVVJSRU5UX0hQID0gcGFyc2VJbnQoY29tbWFuZHNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkVYUFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfRVhQID0gcGFyc2VJbnQoY29tbWFuZHNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlNMRFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfU0hJRUxEID0gcGFyc2VJbnQoY29tbWFuZHNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmdvZE1vZGUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBhdXNlSW5wdXQudGV4dCA9IFwiXCI7XG4gICAgfVxufVxuICAgIFxuXG4iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgeyBHYW1lU3RhdGUgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IE1haW5NZW51IGZyb20gXCIuL01haW5NZW51XCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdhbWVPdmVyIGV4dGVuZHMgU2NlbmUge1xuXG4gICAgc3RhcnRTY2VuZSgpIHtcbiAgICAgICAgSW5wdXRXcmFwcGVyLnNldFN0YXRlKEdhbWVTdGF0ZS5QQVVTRSk7XG4gICAgICAgIElucHV0V3JhcHBlci5yYW5kb21TZWVkID0gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBjZW50ZXIgPSB0aGlzLnZpZXdwb3J0LmdldENlbnRlcigpO1xuXG4gICAgICAgIHRoaXMuYWRkVUlMYXllcihcInByaW1hcnlcIik7XG5cbiAgICAgICAgY29uc3QgZ2FtZU92ZXIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSksIHRleHQ6IFwiWU9VIERJRURcIn0pO1xuICAgICAgICBnYW1lT3Zlci50ZXh0Q29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgIGdhbWVPdmVyLmZvbnRTaXplID0gMTAwO1xuXG4gICAgICAgIGNvbnN0IGhpbnQgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDEwMCksIHRleHQ6IFwiQ2xpY2sgdG8gZ28gYmFjayB0byBNYWluIE1lbnVcIn0pO1xuICAgICAgICBoaW50LnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgIH1cblxuICAgIHVwZGF0ZVNjZW5lKCl7XG4gICAgICAgIGlmKElucHV0V3JhcHBlci5pc0xlZnRNb3VzZUp1c3RQcmVzc2VkKCkpe1xuICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShNYWluTWVudSk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IHsgVGlsZWRUaWxlbWFwRGF0YSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGVidWcvRGVidWdcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcbmltcG9ydCBSYW5kb21NYXBHZW5lcmF0b3IgZnJvbSBcIi4uL1Rvb2xzL1JhbmRvbU1hcEdlbmVyYXRvclwiO1xuaW1wb3J0IEdhbWVMZXZlbCBmcm9tIFwiLi9HYW1lTGV2ZWxcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgeyBTdGF0dXNlcyB9IGZyb20gXCIuLi9zd29yZF9lbnVtc1wiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IEVuZW15QUkgZnJvbSBcIi4uL0FJL0VuZW15QUlcIjtcbmltcG9ydCBCYXR0bGVyQUkgZnJvbSBcIi4uL0FJL0JhdHRsZXJBSVwiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdyZWF0d2FsbCBleHRlbmRzIEdhbWVMZXZlbCB7XG4gICAgbG9hZFNjZW5lKCk6IHZvaWQge1xuICAgICAgICBzdXBlci5sb2FkU2NlbmUoKTtcbiAgICAgICAgdGhpcy5ybWcgPSBuZXcgUmFuZG9tTWFwR2VuZXJhdG9yKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9ncmVhdHdhbGxfdGVtcGxhdGUuanNvblwiLCBJbnB1dFdyYXBwZXIucmFuZG9tU2VlZCk7XG4gICAgICAgIHRoaXMubWFwID0gdGhpcy5ybWcuZ2V0TWFwKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMubWFwKTtcbiAgICAgICAgdGhpcy5sb2FkLnRpbGVtYXBGcm9tT2JqZWN0KFwibWFwXCIsIHRoaXMubWFwKTtcblxuICAgICAgICAvL2xvYWQgZW5lbWllc1xuXG4gICAgICAgIC8vY2FuIGxvYWQgZW5lbXkgc3ByaXRlIGhlcmVcbiAgICAgICAgLy9zcHJpdGVzIG9idGFpbmVkIGZyb20gY3NlMzgwIHNwcml0ZSB3ZXNiaXRlXG4gICAgICAgIC8vIHRoaXMubG9hZC5zcHJpdGVzaGVldChcImJsYWNrX3B1ZGRpbmdcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL2JsYWNrX3B1ZGRpbmcuanNvblwiKTtcblxuICAgICAgICAvL2xvYWQgbXVzaWMgaGVyZVxuICAgIH1cbn0iLCJcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBDb25maWdNYW5hZ2VyIGZyb20gXCIuLi9Ub29scy9Db25maWdNYW5hZ2VyXCI7XG5pbXBvcnQgU2F2ZU1hbmFnZXIgZnJvbSBcIi4uL1Rvb2xzL1NhdmVNYW5hZ2VyXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEJ1dHRvbiBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9CdXR0b25cIjtcbmltcG9ydCB7IFVJRWxlbWVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9VSUVsZW1lbnRUeXBlc1wiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IExheWVyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9MYXllclwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgTWFpbk1lbnUgZnJvbSBcIi4vTWFpbk1lbnVcIjtcbmltcG9ydCBUdXRvcmlhbCBmcm9tIFwiLi9UdXRvcmlhbFwiO1xuaW1wb3J0IFBvcmNlbGFpbiBmcm9tIFwiLi9Qb3JjZWxhaW5cIjtcbmltcG9ydCBHcmVhdHdhbGwgZnJvbSAnLi9HcmVhdHdhbGwnO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgVGV4dElucHV0IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1RleHRJbnB1dFwiO1xuXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExldmVscyBleHRlbmRzIFNjZW5lIHtcbiAgICBwcml2YXRlIHByaW1hcnk6IExheWVyO1xuICAgIHByaXZhdGUgc2VlZElucHV0OiBUZXh0SW5wdXQ7XG4gICAgLy8gVE9ET1xuICAgIGxvYWRTY2VuZSgpe31cbiAgICBzdGFydFNjZW5lKCl7XG4gICAgICAgIGNvbnN0IGNlbnRlciA9IHRoaXMudmlld3BvcnQuZ2V0Q2VudGVyKCk7XG5cbiAgICAgICAgLy8gVGhlIG1haW4gbWVudVxuICAgICAgICB0aGlzLnByaW1hcnkgPSB0aGlzLmFkZFVJTGF5ZXIoXCJwcmltYXJ5XCIpO1xuXG5cbiAgICAgICAgY29uc3Qgc2VlZEhpbnQgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDIwMCksIHRleHQ6IFwiRW50ZXIgc2VlZCBvciBsZWF2ZSBpdCBibGFuayB0byByYW5kb21seSBnZW5lcmF0ZSBvbmVcIn0pO1xuICAgICAgICBzZWVkSGludC50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgXG4gICAgICAgIHRoaXMuc2VlZElucHV0ID0gPFRleHRJbnB1dD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5URVhUX0lOUFVULCBcInByaW1hcnlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAxNTApLCB0ZXh0OiBcIlwifSlcbiAgICAgICAgdGhpcy5zZWVkSW5wdXQuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIFxuICAgICAgICBjb25zdCBzdGFydCA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMTAwKSwgdGV4dDogXCJTdGFydCBHYW1lXCJ9KTtcbiAgICAgICAgc3RhcnQuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIHN0YXJ0LmJvcmRlcldpZHRoID0gMjtcbiAgICAgICAgc3RhcnQuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgc3RhcnQuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHN0YXJ0Lm9uQ2xpY2tFdmVudElkID0gXCJzdGFydFwiO1xuXG4gICAgICAgIGNvbnN0IHBvcmNlbGFpbiA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogXCJwb3JjZWxhaW4oVGVzdClcIn0pO1xuICAgICAgICBwb3JjZWxhaW4uc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIHBvcmNlbGFpbi5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIHBvcmNlbGFpbi5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBwb3JjZWxhaW4uYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHBvcmNlbGFpbi5vbkNsaWNrRXZlbnRJZCA9IFwicG9yY2VsYWluXCI7XG5cbiAgICAgICAgY29uc3QgZ3JlYXR3YWxsID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInByaW1hcnlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAxMDApLCB0ZXh0OiBcImdyZWF0d2FsbChUZXN0KVwifSk7XG4gICAgICAgIGdyZWF0d2FsbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgZ3JlYXR3YWxsLmJvcmRlcldpZHRoID0gMjtcbiAgICAgICAgZ3JlYXR3YWxsLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGdyZWF0d2FsbC5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgZ3JlYXR3YWxsLm9uQ2xpY2tFdmVudElkID0gXCJncmVhdHdhbGxcIjtcblxuICAgICAgICBjb25zdCBiYWNrID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInByaW1hcnlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAyMDApLCB0ZXh0OiBcIkJhY2tcIn0pO1xuICAgICAgICBiYWNrLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBiYWNrLmJvcmRlcldpZHRoID0gMjtcbiAgICAgICAgYmFjay5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBiYWNrLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBiYWNrLm9uQ2xpY2tFdmVudElkID0gXCJiYWNrXCI7XG4gICAgICAgIFxuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcInN0YXJ0XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcInBvcmNlbGFpblwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJncmVhdHdhbGxcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiYmFja1wiKTtcbiAgICB9XG5cbiAgICB1cGRhdGVTY2VuZSgpe1xuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG5cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGV2ZW50KTtcblxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcInN0YXJ0XCIpe1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlZWRJbnB1dC50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIElucHV0V3JhcHBlci5yYW5kb21TZWVkID0gdGhpcy5zZWVkSW5wdXQudGV4dDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWVkSW5wdXQudGV4dCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBJbnB1dFdyYXBwZXIucmFuZG9tU2VlZCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwMDAwMDAwMDAwKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgc2NlbmVPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBwaHlzaWNzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cE5hbWVzOiBbXCJncm91bmRcIiwgXCJwbGF5ZXJcIiwgXCJlbmVtaWVzXCJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sbGlzaW9uczpcbiAgICAgICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwgMSwgMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWzEsIDAsIDBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsxLCAwLCAwXVxuICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoVHV0b3JpYWwsIHt9LCBzY2VuZU9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcInBvcmNlbGFpblwiKXtcbiAgICAgICAgICAgICAgICBsZXQgc2NlbmVPcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICBwaHlzaWNzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cE5hbWVzOiBbXCJncm91bmRcIiwgXCJwbGF5ZXJcIiwgXCJlbmVtaWVzXCJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sbGlzaW9uczpcbiAgICAgICAgICAgICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwgMSwgMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWzEsIDAsIDBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsxLCAwLCAwXVxuICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoUG9yY2VsYWluLCB7fSwgc2NlbmVPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJncmVhdHdhbGxcIil7XG4gICAgICAgICAgICAgICAgbGV0IHNjZW5lT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgcGh5c2ljczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBOYW1lczogW1wiZ3JvdW5kXCIsIFwicGxheWVyXCIsIFwiZW5lbWllc1wiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbnM6XG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsIDEsIDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsxLCAwLCAwXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMSwgMCwgMF1cbiAgICAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKEdyZWF0d2FsbCwge30sIHNjZW5lT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwiYmFja1wiKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51LCB7fSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgXG4gICAgICAgIH1cbiAgICB9XG5cbn0iLCJpbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQ29uZmlnTWFuYWdlciBmcm9tIFwiLi4vVG9vbHMvQ29uZmlnTWFuYWdlclwiO1xuaW1wb3J0IFNhdmVNYW5hZ2VyIGZyb20gXCIuLi9Ub29scy9TYXZlTWFuYWdlclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBMYXllciBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvTGF5ZXJcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IExldmVscyBmcm9tIFwiLi9MZXZlbHNcIjtcbmltcG9ydCBSYW5kb21NYXBHZW5lcmF0b3IgZnJvbSBcIi4uL1Rvb2xzL1JhbmRvbU1hcEdlbmVyYXRvclwiO1xuaW1wb3J0IEdhbWVMZXZlbCBmcm9tIFwiLi9HYW1lTGV2ZWxcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNYWluTWVudSBleHRlbmRzIFNjZW5lIHtcbiAgICBwcm90ZWN0ZWQgY29uZmlnOiBDb25maWdNYW5hZ2VyO1xuICAgIHByb3RlY3RlZCBzYXZlOiBTYXZlTWFuYWdlcjtcblxuICAgIC8vIExheWVycywgZm9yIG11bHRpcGxlIG1haW4gbWVudSBzY3JlZW5zXG4gICAgcHJpdmF0ZSBtYWluTWVudTogTGF5ZXI7XG4gICAgcHJpdmF0ZSBhYm91dDogTGF5ZXI7XG4gICAgcHJpdmF0ZSBjb250cm9sOiBMYXllcjtcbiAgICAvLyBwcml2YXRlIHJtZzogUmFuZG9tTWFwR2VuZXJhdG9yO1xuXG4gICAgbG9hZFNjZW5lKCk6IHZvaWQge1xuICAgICAgICAvLyBMb2FkIHRoZSBtZW51IHNvbmdcbiAgICAgICAgLy90aGlzLmxvYWQuYXVkaW8oXCJtZW51XCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9tdXNpYy9tZW51Lm1wM1wiKTtcbiAgICB9XG5cbiAgICAvL1RPRE8gXG4gICAgXG4gICAgc3RhcnRTY2VuZSgpOiB2b2lke1xuICAgICAgICBHYW1lTGV2ZWwuZ2FtZVRpbWVyID0gMDtcbiAgICAgICAgSW5wdXRXcmFwcGVyLnJhbmRvbVNlZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGNlbnRlciA9IHRoaXMudmlld3BvcnQuZ2V0Q2VudGVyKCk7XG5cbiAgICAgICAgLy8gVGhlIG1haW4gbWVudVxuICAgICAgICB0aGlzLm1haW5NZW51ID0gdGhpcy5hZGRVSUxheWVyKFwibWFpbk1lbnVcIik7XG5cbiAgICAgICAgLy8gQWRkIG1hcCBidXR0b24sIGFuZCBnaXZlIGl0IGFuIGV2ZW50IHRvIGVtaXQgb24gcHJlc3NcbiAgICAgICAgY29uc3QgbWFwID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcIm1haW5NZW51XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMTAwKSwgdGV4dDogXCJNYXBcIn0pO1xuICAgICAgICBtYXAuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIG1hcC5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIG1hcC5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBtYXAuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIG1hcC5vbkNsaWNrRXZlbnRJZCA9IFwibWFwXCI7XG5cblxuICAgICAgICAvLyBBZGQgYWJvdXQgYnV0dG9uXG4gICAgICAgIGNvbnN0IGFib3V0ID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcIm1haW5NZW51XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMTAwKSwgdGV4dDogXCJBYm91dFwifSk7XG4gICAgICAgIGFib3V0LnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBhYm91dC5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGFib3V0LmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGFib3V0LmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBhYm91dC5vbkNsaWNrRXZlbnRJZCA9IFwiYWJvdXRcIjtcblxuICAgICAgICAvLyBBZGQgYWJvdXQgYnV0dG9uXG4gICAgICAgIGNvbnN0IGZvcm0gPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwibWFpbk1lbnVcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAyMDApLCB0ZXh0OiBcIkdvb2dsZSBGb3JtXCJ9KTtcbiAgICAgICAgZm9ybS5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgZm9ybS5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGZvcm0uYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgZm9ybS5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgZm9ybS5vbkNsaWNrID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB3aW5kb3cub3BlbihcImh0dHBzOi8vZm9ybXMuZ2xlL0t1N1JtVWRObjdiOW01Y2g2XCIpO1xuICAgICAgICB9O1xuICAgICAgICBcbiAgICAgICAgLy8gQWRkIGNvbnRyb2wgYnV0dG9uLCBhbmQgZ2l2ZSBpdCBhbiBldmVudCB0byBlbWl0IG9uIHByZXNzXG4gICAgICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwibWFpbk1lbnVcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkpLCB0ZXh0OiBcIkNvbnRyb2xzXCJ9KTtcbiAgICAgICAgY29udHJvbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgY29udHJvbC5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGNvbnRyb2wuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgY29udHJvbC5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgY29udHJvbC5vbkNsaWNrRXZlbnRJZCA9IFwiY29udHJvbFwiO1xuXG4gICAgICAgIC8qICMjIyMjIyMjIyMgQUJPVVQgU0NSRUVOICMjIyMjIyMjIyMgKi9cbiAgICAgICAgdGhpcy5hYm91dCA9IHRoaXMuYWRkVUlMYXllcihcImFib3V0XCIpO1xuICAgICAgICB0aGlzLmFib3V0LnNldEhpZGRlbih0cnVlKTtcblxuICAgICAgICBjb25zdCBhYm91dEhlYWRlciA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJhYm91dFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDI1MCksIHRleHQ6IFwiQWJvdXRcIn0pO1xuICAgICAgICBhYm91dEhlYWRlci50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcblxuICAgICAgICBcbiAgICAgICAgY29uc3QgdGV4dDEgPSBcIlRoaXMgZ2FtZSB3YXMgY3JlYXRlZCBieSBIZW5yeSBDaGVuLCBLZWxseSBQZW5nLCBhbmQgUmVuZ2VcIjtcbiAgICAgICAgY29uc3QgdGV4dDIgPSBcInVzaW5nIHRoZSBXb2xmaWUyRCBnYW1lIGVuZ2luZSwgYSBUeXBlU2NyaXB0IGdhbWUgZW5naW5lIGNyZWF0ZWQgYnlcIjtcbiAgICAgICAgY29uc3QgdGV4dDMgPSBcIkpvZSBXZWF2ZXIgYW5kIFJpY2hhcmQgTWNLZW5uYS5cIjtcblxuICAgICAgICBjb25zdCBsaW5lMSA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJhYm91dFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDUwKSwgdGV4dDogdGV4dDF9KTtcbiAgICAgICAgY29uc3QgbGluZTIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkpLCB0ZXh0OiB0ZXh0Mn0pO1xuICAgICAgICBjb25zdCBsaW5lMyA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJhYm91dFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDUwKSwgdGV4dDogdGV4dDN9KTtcblxuICAgICAgICBsaW5lMS50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbGluZTIudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGxpbmUzLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuXG4gICAgICAgIGNvbnN0IGFib3V0QmFjayA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJhYm91dFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDI1MCksIHRleHQ6IFwiQmFja1wifSk7XG4gICAgICAgIGFib3V0QmFjay5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgYWJvdXRCYWNrLmJvcmRlcldpZHRoID0gMjtcbiAgICAgICAgYWJvdXRCYWNrLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGFib3V0QmFjay5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgYWJvdXRCYWNrLm9uQ2xpY2tFdmVudElkID0gXCJtZW51XCI7XG5cbiAgICAgICAgLy8gU3Vic2NyaWJlIHRvIHRoZSBidXR0b24gZXZlbnRzXG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwibWFwXCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImFib3V0XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcIm1lbnVcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiY29udHJvbFwiKTtcblxuICAgICAgIFxuICAgICAgICAvL0NvbnRyb2wgc2NyZWVuXG4gICAgICAgIHRoaXMuY29udHJvbCA9IHRoaXMuYWRkVUlMYXllcihcImNvbnRyb2xcIik7XG4gICAgICAgIHRoaXMuY29udHJvbC5zZXRIaWRkZW4odHJ1ZSk7XG5cbiAgICBcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGhlYWRlciA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMjUwKSwgdGV4dDogXCJDb250cm9sc1wifSk7XG4gICAgICAgIGhlYWRlci50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgY29uc3QgbGMgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDE1MCksIHRleHQ6IFwiQS9EIC0gTW92ZSBMZWZ0L1JpZ2h0XCJ9KTtcbiAgICAgICAgbGMudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IHJjID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAxMDApLCB0ZXh0OiBcIlcvUyAtIExvb2sgVXAvRG93blwifSk7XG4gICAgICAgIHJjLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCB3YXNkID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSA1MCksIHRleHQ6IFwiSi9aL0VudGVyIC0gQ29uZmlybSBBdHRhY2tcIn0pO1xuICAgICAgICB3YXNkLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBcbiAgICAgICAgY29uc3QgZSA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogXCJTUEFDRS9YIC0gSnVtcFwifSk7XG4gICAgICAgIGUudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IHEgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDUwKSwgdGV4dDogXCJLL0MgLSBEYXNoXCJ9KTtcbiAgICAgICAgcS50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgY29uc3Qgb25lVHdvID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAxMDApLCB0ZXh0OiBcIkwvViAtIFVzZSBTa2lsbFwifSk7XG4gICAgICAgIG9uZVR3by50ZXh0Q29sb3IgPSBDb2xvci5XSElURVxuICAgICAgICBjb25zdCB6eCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMTUwKSwgdGV4dDogXCJJL0IgLSBvcGVuIEJhY2twYWNrXCJ9KTtcbiAgICAgICAgengudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IHRiID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAyMDApLCB0ZXh0OiBcIkVTQyAtIFBhdXNlXCJ9KTtcbiAgICAgICAgdGIudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG5cbiAgICAgICAgY29uc3QgYmFjayA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMzAwKSwgdGV4dDogXCJCYWNrXCJ9KTtcbiAgICAgICAgYmFjay5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgYmFjay5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGJhY2suYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgYmFjay5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgYmFjay5vbkNsaWNrRXZlbnRJZCA9IFwibWVudVwiO1xuICAgICAgICBcbiAgICB9XG5cbiAgICB1bmxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy8gVGhlIHNjZW5lIGlzIGJlaW5nIGRlc3Ryb3llZCwgc28gd2UgY2FuIHN0b3AgcGxheWluZyB0aGUgc29uZ1xuICAgICAgICAvL3RoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELCB7a2V5OiBcIm1lbnVcIn0pO1xuICAgIH1cblxuICAgIFxuICAgIHVwZGF0ZVNjZW5lKCl7XG4gICAgICAgIHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuICAgICAgICAgICAgbGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcblxuICAgICAgICAgICAgY29uc29sZS5sb2coZXZlbnQpO1xuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcIm1hcFwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKExldmVscywge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcImFib3V0XCIpe1xuICAgICAgICAgICAgICAgIHRoaXMuYWJvdXQuc2V0SGlkZGVuKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW5NZW51LnNldEhpZGRlbih0cnVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJtZW51XCIpe1xuICAgICAgICAgICAgICAgIHRoaXMubWFpbk1lbnUuc2V0SGlkZGVuKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmFib3V0LnNldEhpZGRlbih0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2wuc2V0SGlkZGVuKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJjb250cm9sXCIpe1xuICAgICAgICAgICAgICAgIHRoaXMubWFpbk1lbnUuc2V0SGlkZGVuKHRydWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbC5zZXRIaWRkZW4oZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJpbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IFJhbmRvbU1hcEdlbmVyYXRvciBmcm9tIFwiLi4vVG9vbHMvUmFuZG9tTWFwR2VuZXJhdG9yXCI7XG5pbXBvcnQgR2FtZUxldmVsIGZyb20gXCIuL0dhbWVMZXZlbFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCB7IFN0YXR1c2VzIH0gZnJvbSBcIi4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgRW5lbXlBSSBmcm9tIFwiLi4vQUkvRW5lbXlBSVwiO1xuaW1wb3J0IEJhdHRsZXJBSSBmcm9tIFwiLi4vQUkvQmF0dGxlckFJXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUG9yY2VsYWluIGV4dGVuZHMgR2FtZUxldmVsIHtcbiAgICBsb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLmxvYWRTY2VuZSgpO1xuICAgICAgICB0aGlzLnJtZyA9IG5ldyBSYW5kb21NYXBHZW5lcmF0b3IoXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2pzb25zL3BvcmNlbGFpbl90ZW1wbGF0ZS5qc29uXCIsIElucHV0V3JhcHBlci5yYW5kb21TZWVkKTtcbiAgICAgICAgdGhpcy5tYXAgPSB0aGlzLnJtZy5nZXRNYXAoKTtcbiAgICAgICAgY29uc29sZS5sb2codGhpcy5tYXApO1xuICAgICAgICB0aGlzLmxvYWQudGlsZW1hcEZyb21PYmplY3QoXCJtYXBcIiwgdGhpcy5tYXApO1xuXG4gICAgICAgIC8vIC8vbG9hZCBlbmVtaWVzXG4gICAgICAgIC8vIHRoaXMubG9hZC5zcHJpdGVzaGVldChcIlNuYWtlXCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9TbmFrZS5qc29uXCIpO1xuICAgICAgICAvLyB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJUaWdlclwiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvVGlnZXIuanNvblwiKTtcblxuICAgICAgICAvLyAvL2NhbiBsb2FkIGVuZW15IHNwcml0ZSBoZXJlXG4gICAgICAgIC8vIC8vc3ByaXRlcyBvYnRhaW5lZCBmcm9tIGNzZTM4MCBzcHJpdGUgd2VzYml0ZVxuICAgICAgICAvLyB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJyZW11c193ZXJld29sZlwiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvcmVtdXNfd2VyZXdvbGYuanNvblwiKTtcbiAgICAgICAgLy8gdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwiYmxhY2tfcHVkZGluZ1wiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvYmxhY2tfcHVkZGluZy5qc29uXCIpO1xuXG4gICAgICAgIC8vbG9hZCBtdXNpYyBoZXJlXG4gICAgfVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBDb25maWdNYW5hZ2VyIGZyb20gXCIuLi9Ub29scy9Db25maWdNYW5hZ2VyXCI7XG5pbXBvcnQgU2F2ZU1hbmFnZXIgZnJvbSBcIi4uL1Rvb2xzL1NhdmVNYW5hZ2VyXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEJ1dHRvbiBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9CdXR0b25cIjtcbmltcG9ydCB7IFVJRWxlbWVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9VSUVsZW1lbnRUeXBlc1wiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IExheWVyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9MYXllclwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgTGV2ZWxzIGZyb20gXCIuL0xldmVsc1wiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgTWFpbk1lbnUgZnJvbSBcIi4vTWFpbk1lbnVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3BsYXNoU2NyZWVuIGV4dGVuZHMgU2NlbmUge1xuICAgIHByb3RlY3RlZCBjb25maWc6IENvbmZpZ01hbmFnZXI7XG4gICAgcHJvdGVjdGVkIHNhdmU6IFNhdmVNYW5hZ2VyO1xuXG4gICAgYW5pbWF0ZWRTcHJpdGU6IEFuaW1hdGVkU3ByaXRlO1xuICAgIGNsaWNrTGFiZWw6IExhYmVsO1xuXG4gICAgbG9hZFNjZW5lKCk6IHZvaWQge1xuICAgICAgICAvL2xvYWQgaW1hZ2VzXG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcImJhY2tncm91bmRJbWFnZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvaW1hZ2VzL2xvZ28ucG5nXCIpO1xuICAgICAgICB0aGlzLmxvYWQuaW1hZ2UoXCJsb2dvXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9pbWFnZXMvYnJvd24ucG5nXCIpO1xuICAgICAgICAvLyBMb2FkIHRoZSBtZW51IHNvbmdcbiAgICAgICAgLy90aGlzLmxvYWQuYXVkaW8oXCJtZW51XCIsIFwiYXNzZXRzL211c2ljL21lbnUubXAzXCIpO1xuICAgIH1cblxuICAgIC8vVE9ETyBcbiAgICBcbiAgICBzdGFydFNjZW5lKCk6IHZvaWR7XG4gICAgICAgIHRoaXMuY29uZmlnID0gbmV3IENvbmZpZ01hbmFnZXIoKTtcbiAgICAgICAgdGhpcy5zYXZlID0gbmV3IFNhdmVNYW5hZ2VyKCk7XG5cblxuICAgICAgICAvLyBTY2VuZSBoYXMgc3RhcnRlZCwgc28gc3RhcnQgcGxheWluZyBtdXNpY1xuICAgICAgICAvL3RoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7a2V5OiBcIm1lbnVcIiwgbG9vcDogdHJ1ZSwgaG9sZFJlZmVyZW5jZTogdHJ1ZX0pO1xuXG4gICAgICAgIGNvbnN0IGNlbnRlciA9IHRoaXMudmlld3BvcnQuZ2V0Q2VudGVyKCk7XG5cbiAgICAgICAgbGV0IHNpemUgPSB0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCk7XG4gICAgICAgIHRoaXMudmlld3BvcnQuc2V0Rm9jdXMoc2l6ZSk7XG4gICAgICAgIHRoaXMudmlld3BvcnQuc2V0Wm9vbUxldmVsKDEpO1xuXG4gICAgICAgIGxldCBiYWNrZ3JvdW5kTGF5ZXIgPSB0aGlzLmFkZFVJTGF5ZXIoXCJiYWNrZ3JvdW5kXCIpO1xuICAgICAgICBiYWNrZ3JvdW5kTGF5ZXIuc2V0RGVwdGgoMCk7XG4gICAgICAgIGxldCBmcm9udExheWVyID0gdGhpcy5hZGRVSUxheWVyKFwiZnJvbnRncm91bmRcIik7XG4gICAgICAgIGZyb250TGF5ZXIuc2V0RGVwdGgoMSk7XG5cbiAgICAgICAgdGhpcy5jbGlja0xhYmVsID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImZyb250Z3JvdW5kXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoc2l6ZS54LCBzaXplLnkgKyAzMDApLCB0ZXh0OiBcIlxcXCJDbGljayBhbnl3aGVyZSB0byBzdGFydFxcXCJcIn0pO1xuICAgICAgICB0aGlzLmNsaWNrTGFiZWwudGV4dENvbG9yID0gbmV3IENvbG9yKDAsIDAsIDAsIDEpO1xuICAgICAgICB0aGlzLmNsaWNrTGFiZWwuZm9udCA9IFwiQXJpYWxcIjtcbiAgICAgICAgdGhpcy5jbGlja0xhYmVsLmZvbnRTaXplID0gNzA7XG5cbiAgICAgICAgbGV0IGJhY2tncm91bmQgPSB0aGlzLmFkZC5zcHJpdGUoXCJiYWNrZ3JvdW5kSW1hZ2VcIiwgXCJiYWNrZ3JvdW5kXCIpO1xuICAgICAgICBiYWNrZ3JvdW5kLnBvc2l0aW9uLnNldChzaXplLngsIHNpemUueSk7XG5cbiAgICAgICAgbGV0IGxvZ28gPSB0aGlzLmFkZC5zcHJpdGUoXCJsb2dvXCIsIFwiZnJvbnRncm91bmRcIik7XG4gICAgICAgIGxvZ28ucG9zaXRpb24uc2V0KHNpemUueCwgc2l6ZS55ICsgMjApO1xuICAgICAgICBsb2dvLnNjYWxlLnNldCg0LCA0KTsgXG5cbiAgICB9XG5cbiAgICB1bmxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy8gVGhlIHNjZW5lIGlzIGJlaW5nIGRlc3Ryb3llZCwgc28gd2UgY2FuIHN0b3AgcGxheWluZyB0aGUgc29uZ1xuICAgICAgICAvL3RoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELCB7a2V5OiBcIm1lbnVcIn0pO1xuICAgIH1cblxuICAgIFxuICAgIHVwZGF0ZVNjZW5lKCl7XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuaXNMZWZ0TW91c2VKdXN0UHJlc3NlZCgpKSB7ICAvL2lmIGxlZnQgY2xpY2tcbiAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoTWFpbk1lbnUsIHt9LCB7fSk7XG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhldmVudCk7XG4gICAgICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmlzTGVmdE1vdXNlSnVzdFByZXNzZWQoKSkgeyAgLy9pZiBsZWZ0IGNsaWNrXG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShNYWluTWVudSwge30sIHt9KTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgUmFuZG9tTWFwR2VuZXJhdG9yIGZyb20gXCIuLi9Ub29scy9SYW5kb21NYXBHZW5lcmF0b3JcIjtcbmltcG9ydCBHYW1lTGV2ZWwgZnJvbSBcIi4vR2FtZUxldmVsXCI7XG5pbXBvcnQgU25ha2VBSSBmcm9tIFwiLi4vQUkvU25ha2VBSVwiO1xuaW1wb3J0IFBvcmNlbGFpbiBmcm9tIFwiLi9Qb3JjZWxhaW5cIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUdXRvcmlhbCBleHRlbmRzIEdhbWVMZXZlbCB7XG4gICAgbG9hZFNjZW5lKCk6IHZvaWQge1xuICAgICAgICBzdXBlci5sb2FkU2NlbmUoKTtcbiAgICAgICAgdGhpcy5ybWcgPSBuZXcgUmFuZG9tTWFwR2VuZXJhdG9yKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9mb3Jlc3RfdGVtcGxhdGUuanNvblwiLCBJbnB1dFdyYXBwZXIucmFuZG9tU2VlZCk7XG4gICAgICAgIHRoaXMubWFwID0gdGhpcy5ybWcuZ2V0TWFwKCk7XG4gICAgICAgIHRoaXMubG9hZC50aWxlbWFwRnJvbU9iamVjdChcIm1hcFwiLCB0aGlzLm1hcCk7XG5cbiAgICAgICAgLy9sb2FkIGVuZW1pZXNcbiAgICAgICAgdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwiU25ha2VcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL1NuYWtlLmpzb25cIik7XG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcIlRpZ2VyXCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9UaWdlci5qc29uXCIpO1xuXG4gICAgICAgIC8vY2FuIGxvYWQgZW5lbXkgc3ByaXRlIGhlcmVcbiAgICAgICAgLy9zcHJpdGVzIG9idGFpbmVkIGZyb20gY3NlMzgwIHNwcml0ZSB3ZXNiaXRlXG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcInJlbXVzX3dlcmV3b2xmXCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9yZW11c193ZXJld29sZi5qc29uXCIpO1xuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJibGFja19wdWRkaW5nXCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9ibGFja19wdWRkaW5nLmpzb25cIik7XG5cbiAgICAgICAgLy9sb2FkIG11c2ljIGhlcmVcbiAgICB9XG5cbiAgICB1cGRhdGVTY2VuZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBzdXBlci51cGRhdGVTY2VuZShkZWx0YVQpO1xuICAgICAgICBcbiAgICAgICAgLy9zcGF3biBzbmFrZSgpXG4gICAgICAgIGlmKE1hdGgucmFuZG9tKCkgPCAuMDAwMSAmJiB0aGlzLmdhbWVTdGFydGVkKXtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUkFORE9NIFNOQUtFIVwiKTtcbiAgICAgICAgICAgIHRoaXMuYWRkRW5lbXkoXCJTbmFrZVwiLCB0aGlzLnBsYXllci5wb3NpdGlvbi5jbG9uZSgpLmFkZChuZXcgVmVjMigwLC0zMjApKSwgU25ha2VBSSwge1xuICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDUwLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcDogXCJNYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplOiBuZXcgVmVjMigxNCwxMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgOiBuZXcgVmVjMigwLCAyMiksXG4gICAgICAgICAgICAgICAgICAgICAgICBleHA6IDUwLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBnb1RvTmV4dExldmVsKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnZpZXdwb3J0LnNldFpvb21MZXZlbCgxKTtcbiAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShQb3JjZWxhaW4pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBwbGF5U3RhcnRTdG9yeSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnRvdWNoZWRTdGFydENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMudG91Y2hlZFN0YXJ0Q2hlY2tQb2ludCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnN0b3J5TG9hZGVyKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9sZXZlbDFzdG9yeS5qc29uXCIpO1xuICAgICAgICAgICAgdGhpcy5zdGFydFRpbWVyKCk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IENvbmZpZyBmcm9tIFwiLi9EYXRhVHlwZXMvQ29uZmlnXCI7XG5pbXBvcnQgTG9jYWxTdG9yYWdlREIgZnJvbSBcIi4vTG9jYWxTdG9yYWdlREJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29uZmlnTWFuYWdlciB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgY29uZmlnOiBDb25maWc7XG4gICAgcHJpdmF0ZSBkYjogTG9jYWxTdG9yYWdlREI7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5kYiA9IG5ldyBMb2NhbFN0b3JhZ2VEQihcImNvbmZpZ1wiKTtcbiAgICAgICAgdGhpcy5sb2FkQ29uZmlnKCk7XG5cbiAgICAgICAgaWYgKCFDb25maWdNYW5hZ2VyLmNvbmZpZylcbiAgICAgICAgICAgIHRoaXMuaW5pdENvbmZpZygpO1xuICAgIH1cblxuICAgIGdldFZvbHVtZSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gQ29uZmlnTWFuYWdlci5jb25maWcudm9sdW1lO1xuICAgIH1cblxuICAgIHNldFZvbHVtZSh2b2x1bWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBDb25maWdNYW5hZ2VyLmNvbmZpZy52b2x1bWUgPSB2b2x1bWU7XG4gICAgICAgIHRoaXMuc2F2ZUNvbmZpZygpO1xuICAgIH1cblxuICAgIC8vIFRPRE9zXG4gICAgLy8gYWRkIG1vcmUgZnVuY3Rpb25zIGlmIG5lZWRlZFxuXG4gICAgcmVzZXRDb25maWcoY2FsbGJhY2s/OiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmluaXRDb25maWcoKTtcbiAgICAgICAgY2FsbGJhY2soQ29uZmlnTWFuYWdlci5jb25maWcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgbG9hZENvbmZpZygpOiB2b2lkIHtcbiAgICAgICAgQ29uZmlnTWFuYWdlci5jb25maWcgPSA8Q29uZmlnPnRoaXMuZGIubG9hZEpTT04oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNhdmVDb25maWcoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGIuc2F2ZUpTT04oQ29uZmlnTWFuYWdlci5jb25maWcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdENvbmZpZygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYi5yZWFkSlNPTihcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvanNvbnMvc2FtcGxlY29uZmlnLmpzb25cIiwgKGNvbmZpZzogb2JqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAoIWNvbmZpZylcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsIHRvIGxvYWQgY29uZmlnIGZpbGVcIik7XG4gICAgICAgICAgICBDb25maWdNYW5hZ2VyLmNvbmZpZyA9IDxDb25maWc+Y29uZmlnO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJJbml0aWFsaXppbmcgTG9jYWwgU3RvcmFnZShjb25maWcpOiBcIiwgQ29uZmlnTWFuYWdlci5jb25maWcpO1xuICAgICAgICAgICAgdGhpcy5zYXZlQ29uZmlnKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbn0iLCJpbXBvcnQgSW5wdXQgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0lucHV0L0lucHV0XCI7XG5pbXBvcnQge0dhbWVTdGF0ZX0gZnJvbSBcIi4uL3N3b3JkX2VudW1zXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElucHV0V3JhcHBlciB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2FtZVN0YXRlOiBHYW1lU3RhdGUgPSBHYW1lU3RhdGUuR0FNSU5HO1xuICAgIHN0YXRpYyByYW5kb21TZWVkOiBzdHJpbmc7XG5cbiAgICBzdGF0aWMgaXNVcFByZXNzZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5HQU1JTkcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKElucHV0LmlzUHJlc3NlZChcInVwXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHN0YXRpYyBpc0Rvd25QcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc1ByZXNzZWQoXCJkb3duXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHN0YXRpYyBpc0xlZnRQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc1ByZXNzZWQoXCJsZWZ0XCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHN0YXRpYyBpc1JpZ2h0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNQcmVzc2VkKFwicmlnaHRcIikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgc3RhdGljIGlzSnVtcEp1c3RQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc0p1c3RQcmVzc2VkKFwianVtcFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBhdHRhY2sga2V5IGlzIGN1cnJlbnRseSBwcmVzc2VkXG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGF0dGFjayBrZXkgaXMgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuICAgIHN0YXRpYyBpc0F0dGFja0p1c3RQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc0p1c3RQcmVzc2VkKFwiYXR0YWNrXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzRGFzaEp1c3RQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc0p1c3RQcmVzc2VkKFwiZGFzaFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc1NraWxsSnVzdFByZXNzZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5HQU1JTkcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKElucHV0LmlzSnVzdFByZXNzZWQoXCJza2lsbFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc0ludmVudG9yeUp1c3RQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc0p1c3RQcmVzc2VkKFwiaW52ZW50b3J5XCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzQnVmZjFKdXN0UHJlc2VkKCk6IGJvb2xlYW57XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5CVUZGKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIElucHV0LmlzSnVzdFByZXNzZWQoXCJidWZmMVwiKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNCdWZmMkp1c3RQcmVzZWQoKTogYm9vbGVhbntcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkJVRkYpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gSW5wdXQuaXNKdXN0UHJlc3NlZChcImJ1ZmYyXCIpO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc0J1ZmYzSnVzdFByZXNlZCgpOiBib29sZWFue1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuQlVGRikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBJbnB1dC5pc0p1c3RQcmVzc2VkKFwiYnVmZjNcIik7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzUGF1c2VKdXN0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORyAmJiBJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5QQVVTRSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNKdXN0UHJlc3NlZChcInBhdXNlXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzTmV4dEp1c3RQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuU1RPUlkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKElucHV0LmlzSnVzdFByZXNzZWQoXCJhdHRhY2tcIikgfHwgSW5wdXQuaXNNb3VzZUp1c3RQcmVzc2VkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNMZWZ0TW91c2VKdXN0UHJlc3NlZCgpOiBib29sZWFue1xuICAgICAgICByZXR1cm4gSW5wdXQuaXNNb3VzZUp1c3RQcmVzc2VkKDApO1xuICAgIH1cblxuICAgIHN0YXRpYyBkaXNhYmxlSW5wdXQoKSB7XG4gICAgICAgIElucHV0LmRpc2FibGVJbnB1dCgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBlbmFibGVJbnB1dCgpIHtcbiAgICAgICAgSW5wdXQuZW5hYmxlSW5wdXQoKTtcbiAgICB9XG5cbiAgICAvLyBETyBOT1QgY2FsbCB0aGlzIGZ1bmN0aW9uIGRpcmVjdGx5XG4gICAgc3RhdGljIHNldFN0YXRlKGdhbWVTdGF0ZTogR2FtZVN0YXRlKTogdm9pZCB7XG4gICAgICAgIElucHV0V3JhcHBlci5nYW1lU3RhdGUgPSBnYW1lU3RhdGU7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldFN0YXRlKCk6IEdhbWVTdGF0ZSB7XG4gICAgICAgIHJldHVybiBJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlO1xuICAgIH1cbn0iLCJleHBvcnQgZGVmYXVsdCBjbGFzcyBMb2NhbFN0b3JhZ2VEQiB7XG4gICAgcHJpdmF0ZSBrZXk6IHN0cmluZztcbiAgICBjb25zdHJ1Y3RvcihrZXk6IHN0cmluZykge1xuICAgICAgICB0aGlzLmtleSA9IGtleTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWFkIGEganNvbiBmaWxlIGZyb20gYSBwYXRoXG4gICAgICogQHBhcmFtIEpTT05GaWxlUGF0aCBUaGUgcGF0aCB0byB0aGUgSlNPTiBmaWxlXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIEZ1bmN0aW9uIHRvIHJ1biBhZnRlciBnZXR0aW5nIHRoZSBKU09OXG4gICAgICovXG4gICAgcmVhZEpTT04oSlNPTkZpbGVQYXRoOiBzdHJpbmcsIGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICBsZXQgeG9iajogWE1MSHR0cFJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgeG9iai5vdmVycmlkZU1pbWVUeXBlKFwiYXBwbGljYXRpb24vanNvblwiKTtcbiAgICAgICAgeG9iai5vcGVuKCdHRVQnLCBKU09ORmlsZVBhdGgsIGZhbHNlKTtcbiAgICAgICAgLy8geG9iai5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vICAgICBpZiAoKHhvYmoucmVhZHlTdGF0ZSA9PSA0KSAmJiAoeG9iai5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAvLyAgICAgICAgIGNhbGxiYWNrKEpTT04ucGFyc2UoeG9iai5yZXNwb25zZVRleHQpKTtcbiAgICAgICAgLy8gICAgIH1cbiAgICAgICAgLy8gfTtcbiAgICAgICAgeG9iai5zZW5kKG51bGwpO1xuICAgICAgICBjYWxsYmFjayhKU09OLnBhcnNlKHhvYmoucmVzcG9uc2VUZXh0KSk7XG4gICAgfVxuXG4gICAgbG9hZEpTT04oKTogb2JqZWN0IHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5rZXkpKTtcbiAgICB9XG5cbiAgICBzYXZlSlNPTih2YWx1ZTogb2JqZWN0KTogdm9pZCB7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMua2V5LCBKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xuICAgIH1cblxufSIsImltcG9ydCB7IFRpbGVkTGF5ZXJEYXRhLCBUaWxlZFRpbGVtYXBEYXRhIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IE1hcFRlbXBsYXRlLCB7IEVudHJhbmNlLCBSb29tVGVtcGxhdGUgfSBmcm9tIFwiLi9EYXRhVHlwZXMvTWFwVGVtcGxhdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmFuZG9tTWFwR2VuZXJhdG9yIHtcbiAgICBwcml2YXRlIHRlbXBsYXRlOiBNYXBUZW1wbGF0ZTtcbiAgICBwcml2YXRlIG1pblg6IG51bWJlcjtcbiAgICBwcml2YXRlIG1heFg6IG51bWJlcjtcbiAgICBwcml2YXRlIG1pblk6IG51bWJlcjtcbiAgICBwcml2YXRlIG1heFk6IG51bWJlcjtcbiAgICBwcml2YXRlIG1hcDogVGlsZWRUaWxlbWFwRGF0YTtcbiAgICBwcml2YXRlIHJvb21XaXRoTGVmdEVudHJhbmNlOiBBcnJheTxSb29tVGVtcGxhdGU+O1xuICAgIHByaXZhdGUgcm9vbVdpdGhMZWZ0RW50cmFuY2VXZWlnaHQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHJvb21XaXRoUmlnaHRFbnRyYW5jZTogQXJyYXk8Um9vbVRlbXBsYXRlPjtcbiAgICBwcml2YXRlIHJvb21XaXRoUmlnaHRFbnRyYW5jZVdlaWdodDogbnVtYmVyO1xuICAgIHByaXZhdGUgcm9vbVdpdGhVcEVudHJhbmNlOiBBcnJheTxSb29tVGVtcGxhdGU+O1xuICAgIHByaXZhdGUgcm9vbVdpdGhVcEVudHJhbmNlV2VpZ2h0OiBudW1iZXI7XG4gICAgcHJpdmF0ZSByb29tV2l0aERvd25FbnRyYW5jZTogQXJyYXk8Um9vbVRlbXBsYXRlPjtcbiAgICBwcml2YXRlIHJvb21XaXRoRG93bkVudHJhbmNlV2VpZ2h0OiBudW1iZXI7XG4gICAgcHJpdmF0ZSByb29tczogQXJyYXk8Um9vbT5cbiAgICBwcml2YXRlIGdlbjogYW55O1xuICAgIHByaXZhdGUgaGFzRXhpdDogYm9vbGVhbjtcbiAgICBwcml2YXRlIG1pblJvb206IG51bWJlcjtcbiAgICBwcml2YXRlIHJvb21QbGFjZWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGV4aXRGYWNpbmc6IEZhY2luZztcbiAgICBwcml2YXRlIGVuZW1pZXM6IEFycmF5PEVuZW15PjtcbiAgICBwcml2YXRlIHBsYXllcjogVmVjMjtcbiAgICBwcml2YXRlIHN0YXJ0Q2hlY2tQb2ludDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gICAgcHJpdmF0ZSBlbmRDaGVja1BvaW50OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcblxuICAgIGNvbnN0cnVjdG9yKEpTT05GaWxlUGF0aDogc3RyaW5nLCBzZWVkOiBhbnkpIHtcbiAgICAgICAgbGV0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICB4aHIub3ZlcnJpZGVNaW1lVHlwZShcImFwcGxpY2F0aW9uL2pzb25cIik7XG4gICAgICAgIHhoci5vcGVuKCdHRVQnLCBKU09ORmlsZVBhdGgsIGZhbHNlKTtcbiAgICAgICAgeGhyLnNlbmQobnVsbCk7XG4gICAgICAgIHRoaXMudGVtcGxhdGUgPSBKU09OLnBhcnNlKHhoci5yZXNwb25zZVRleHQpO1xuICAgICAgICB0aGlzLnJvb21XaXRoTGVmdEVudHJhbmNlID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMucm9vbVdpdGhSaWdodEVudHJhbmNlID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMucm9vbVdpdGhVcEVudHJhbmNlID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMucm9vbVdpdGhEb3duRW50cmFuY2UgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5taW5YID0gdGhpcy5taW5ZID0gdGhpcy5tYXhYID0gdGhpcy5tYXhZID1cbiAgICAgICAgICAgIHRoaXMucm9vbVdpdGhMZWZ0RW50cmFuY2VXZWlnaHQgPSB0aGlzLnJvb21XaXRoUmlnaHRFbnRyYW5jZVdlaWdodCA9XG4gICAgICAgICAgICB0aGlzLnJvb21XaXRoVXBFbnRyYW5jZVdlaWdodCA9IHRoaXMucm9vbVdpdGhEb3duRW50cmFuY2VXZWlnaHQgPSAwO1xuXG4gICAgICAgIHRoaXMubWFwID0gbmV3IFRpbGVkVGlsZW1hcERhdGEoKTtcbiAgICAgICAgdGhpcy5yb29tcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLmVuZW1pZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5wbGF5ZXIgPSBuZXcgVmVjMigpO1xuICAgICAgICB0aGlzLnN0YXJ0Q2hlY2tQb2ludCA9IFswLDAsMCwwXTtcbiAgICAgICAgdGhpcy5lbmRDaGVja1BvaW50ID0gWzAsIDAsIDAsIDBdO1xuICAgICAgICBsZXQgZ2VuID0gcmVxdWlyZSgncmFuZG9tLXNlZWQnKTtcbiAgICAgICAgdGhpcy5nZW4gPSBuZXcgZ2VuKHNlZWQpO1xuICAgICAgICB0aGlzLmhhc0V4aXQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5taW5Sb29tID0gdGhpcy50ZW1wbGF0ZS5taW5yb29tO1xuICAgICAgICB0aGlzLnJvb21QbGFjZWQgPSAwO1xuICAgICAgICB0aGlzLmV4aXRGYWNpbmcgPSB0aGlzLmdldEVudHJhbmNlRmFjaW5nKHRoaXMudGVtcGxhdGUuZXhpdC5lbnRyYW5jZXNbMF0sIHRoaXMudGVtcGxhdGUuZXhpdC53aWR0aCk7XG5cblxuICAgICAgICBmb3IgKGxldCByb29tIG9mIHRoaXMudGVtcGxhdGUucm9vbXMpIHtcbiAgICAgICAgICAgIGxldCBsZWZ0ID0gZmFsc2UsIHJpZ2h0ID0gZmFsc2UsIHVwID0gZmFsc2UsIGRvd24gPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAobGV0IGVudHJhbmNlIG9mIHJvb20uZW50cmFuY2VzKSB7XG4gICAgICAgICAgICAgICAgbGV0IGZhY2luZyA9IHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcoZW50cmFuY2UsIHJvb20ud2lkdGgpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoZmFjaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRmFjaW5nLkxFRlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEZhY2luZy5SSUdIVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEZhY2luZy5VUDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHVwID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEZhY2luZy5ET1dOOlxuICAgICAgICAgICAgICAgICAgICAgICAgZG93biA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChsZWZ0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aExlZnRFbnRyYW5jZS5wdXNoKHJvb20pO1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhMZWZ0RW50cmFuY2VXZWlnaHQgKz0gcm9vbS53ZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmlnaHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoUmlnaHRFbnRyYW5jZS5wdXNoKHJvb20pO1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhSaWdodEVudHJhbmNlV2VpZ2h0ICs9IHJvb20ud2VpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aFVwRW50cmFuY2UucHVzaChyb29tKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoVXBFbnRyYW5jZVdlaWdodCArPSByb29tLndlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkb3duKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aERvd25FbnRyYW5jZS5wdXNoKHJvb20pO1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhEb3duRW50cmFuY2VXZWlnaHQgKz0gcm9vbS53ZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRNYXAoKTogVGlsZWRUaWxlbWFwRGF0YSB7XG4gICAgICAgIGxldCByb29tID0gdGhpcy5jb3B5Um9vbSh0aGlzLnRlbXBsYXRlLmVudHJhbmNlLCAwLCAwKTtcbiAgICAgICAgbGV0IGZhY2luZyA9IHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcodGhpcy50ZW1wbGF0ZS5lbnRyYW5jZS5lbnRyYW5jZXNbMF0sIHRoaXMudGVtcGxhdGUuZW50cmFuY2Uud2lkdGgpO1xuICAgICAgICBsZXQgcG9zaXRpb24gPSBuZXcgVmVjMih0aGlzLnRlbXBsYXRlLmVudHJhbmNlLmVudHJhbmNlc1swXS54LCB0aGlzLnRlbXBsYXRlLmVudHJhbmNlLmVudHJhbmNlc1swXS55KTtcbiAgICAgICAgLy8gdGhpcy5yZW1vdmVFbnRyYW5jZShyb29tLCB0aGlzLnRlbXBsYXRlLmVudHJhbmNlLmVudHJhbmNlc1swXSwgZmFjaW5nKTtcbiAgICAgICAgdGhpcy5yb29tcy5wdXNoKHJvb20pO1xuXG4gICAgICAgIFxuXG4gICAgICAgIHRoaXMucHV0TmV4dFJvb20ocG9zaXRpb24sIHRoaXMuZ2V0T3Bwb3NpdGVGYWNpbmcoZmFjaW5nKSk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmhhc0V4aXQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsIHRvIGdlbmVyYXRlIGEgbWFwIHdpdGggZXhpdCFcIik7XG5cbiAgICAgICAgdGhpcy5maWxsRGF0YSgpO1xuICAgICAgICBjb25zb2xlLmxvZyhcIkdlbmVyYXRlZCBtYXA6XCIsIHRoaXMubWFwKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFwO1xuICAgIH1cblxuICAgIGdldFBsYXllcigpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMucGxheWVyLnggLSB0aGlzLm1pblgsIHRoaXMucGxheWVyLnkgLSB0aGlzLm1pblkpO1xuICAgIH1cblxuICAgIGdldFN0YXJ0Q2hlY2tQb2ludCgpOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSB7XG4gICAgICAgIHJldHVybiBbdGhpcy5zdGFydENoZWNrUG9pbnRbMF0gLSB0aGlzLm1pblgsIHRoaXMuc3RhcnRDaGVja1BvaW50WzFdIC0gdGhpcy5taW5ZLCB0aGlzLnN0YXJ0Q2hlY2tQb2ludFsyXSwgdGhpcy5zdGFydENoZWNrUG9pbnRbM11dO1xuICAgIH1cblxuICAgIGdldEVuZENoZWNrUG9pbnQoKTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0ge1xuICAgICAgICByZXR1cm4gW3RoaXMuZW5kQ2hlY2tQb2ludFswXSAtIHRoaXMubWluWCwgdGhpcy5lbmRDaGVja1BvaW50WzFdIC0gdGhpcy5taW5ZLCB0aGlzLmVuZENoZWNrUG9pbnRbMl0sIHRoaXMuZW5kQ2hlY2tQb2ludFszXV07XG4gICAgfVxuXG4gICAgZ2V0RW5lbWllcygpOiBBcnJheTxFbmVteT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5lbmVtaWVzO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHV0TmV4dFJvb20ocG9zaXRpb246IFZlYzIsIGZhY2luZzogRmFjaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHN3aXRjaCAoZmFjaW5nKSB7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5MRUZUOlxuICAgICAgICAgICAgICAgIHBvc2l0aW9uLnggKz0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlJJR0hUOlxuICAgICAgICAgICAgICAgIHBvc2l0aW9uLnggLT0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlVQOlxuICAgICAgICAgICAgICAgIHBvc2l0aW9uLnkgKz0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkRPV046XG4gICAgICAgICAgICAgICAgcG9zaXRpb24ueSAtPSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yb29tUGxhY2VkID49IHRoaXMubWluUm9vbSAmJiBmYWNpbmcgPT0gdGhpcy5leGl0RmFjaW5nICYmICF0aGlzLmhhc0V4aXQpIHtcbiAgICAgICAgICAgIHRoaXMucHV0RXhpdFJvb20ocG9zaXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbmV4dFJvb20gPSB0aGlzLmdldFJhbmRvbVJvb20oZmFjaW5nKTtcbiAgICAgICAgbGV0IG5leHRQb3NpdGlvbjogVmVjMiA9IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHRoaXNFbnRyYW5jZTogRW50cmFuY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZvciAobGV0IGVudHJhbmNlIG9mIG5leHRSb29tLmVudHJhbmNlcykge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcoZW50cmFuY2UsIG5leHRSb29tLndpZHRoKSA9PSBmYWNpbmcpIHtcbiAgICAgICAgICAgICAgICBsZXQgdG1wUG9zaXRpb24gPSBuZXcgVmVjMihwb3NpdGlvbi54IC0gZW50cmFuY2UueCwgcG9zaXRpb24ueSAtIGVudHJhbmNlLnkpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzVmFsaWRSb29tKHRtcFBvc2l0aW9uLCBuZXcgVmVjMih0bXBQb3NpdGlvbi54ICsgbmV4dFJvb20ud2lkdGggLSAxLCB0bXBQb3NpdGlvbi55ICsgbmV4dFJvb20uaGVpZ2h0IC0gMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXNFbnRyYW5jZSA9IGVudHJhbmNlO1xuICAgICAgICAgICAgICAgICAgICBuZXh0UG9zaXRpb24gPSB0bXBQb3NpdGlvbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzRW50cmFuY2UpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5oYXNFeGl0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiV3Jvbmcgb3JkZXIgaW4gbWFwIHRlbXBsYXRlXCIgKyBmYWNpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGxldCByb29tID0gdGhpcy5jb3B5Um9vbShuZXh0Um9vbSwgbmV4dFBvc2l0aW9uLngsIG5leHRQb3NpdGlvbi55KTtcbiAgICAgICAgdGhpcy5yZW1vdmVFbnRyYW5jZShyb29tLCB0aGlzRW50cmFuY2UsIGZhY2luZyk7XG4gICAgICAgIHRoaXMucm9vbXMucHVzaChyb29tKTtcbiAgICAgICAgdGhpcy5yb29tUGxhY2VkICs9IDE7XG4gICAgICAgIGlmICh0aGlzLmhhc0V4aXQgJiYgdGhpcy5nZW4ucmFuZG9tKCkgPD0gMC4zKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBlbnRyYW5jZSBvZiBuZXh0Um9vbS5lbnRyYW5jZXMpIHtcbiAgICAgICAgICAgIGlmIChlbnRyYW5jZSAhPSB0aGlzRW50cmFuY2UpIHtcbiAgICAgICAgICAgICAgICBsZXQgZmFjaW5nID0gdGhpcy5nZXRFbnRyYW5jZUZhY2luZyhlbnRyYW5jZSwgbmV4dFJvb20ud2lkdGgpO1xuICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbiA9IG5ldyBWZWMyKG5leHRQb3NpdGlvbi54ICsgZW50cmFuY2UueCwgbmV4dFBvc2l0aW9uLnkgKyBlbnRyYW5jZS55KTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnB1dE5leHRSb29tKHBvc2l0aW9uLCB0aGlzLmdldE9wcG9zaXRlRmFjaW5nKGZhY2luZykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlRW50cmFuY2Uocm9vbSwgZW50cmFuY2UsIGZhY2luZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHV0RXhpdFJvb20ocG9zaXRpb246IFZlYzIpOiB2b2lkIHtcbiAgICAgICAgcG9zaXRpb24gPSBuZXcgVmVjMihwb3NpdGlvbi54IC0gdGhpcy50ZW1wbGF0ZS5leGl0LmVudHJhbmNlc1swXS54LCBwb3NpdGlvbi55IC0gdGhpcy50ZW1wbGF0ZS5leGl0LmVudHJhbmNlc1swXS55KTtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWRSb29tKHBvc2l0aW9uLCBuZXcgVmVjMihwb3NpdGlvbi54ICsgdGhpcy50ZW1wbGF0ZS5leGl0LndpZHRoIC0gMSwgcG9zaXRpb24ueSArIHRoaXMudGVtcGxhdGUuZXhpdC5oZWlnaHQgLSAxKSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBwdXQgZXhpdCByb29tISEhIFBvc2l0aW9uIGlzIGludmFsaWQhISEgUGxlYXNlIGNoZWNrIG9yZGVyIG9mIGVudHJhbmNlcyBpbiBtYXAgdGVtcGxhdGUuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGxldCByb29tID0gdGhpcy5jb3B5Um9vbSh0aGlzLnRlbXBsYXRlLmV4aXQsIHBvc2l0aW9uLngsIHBvc2l0aW9uLnkpO1xuICAgICAgICB0aGlzLnJvb21zLnB1c2gocm9vbSk7XG4gICAgICAgIHRoaXMuaGFzRXhpdCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZW1vdmVFbnRyYW5jZShyb29tOiBSb29tLCBlbnRyYW5jZTogRW50cmFuY2UsIGZhY2luZzogRmFjaW5nKTogdm9pZCB7XG4gICAgICAgIGxldCB3aWR0aCA9IHJvb20uYm90dG9tUmlnaHQueCAtIHJvb20udG9wTGVmdC54ICsgMTtcbiAgICAgICAgaWYgKGZhY2luZyA9PSBGYWNpbmcuTEVGVCB8fCBmYWNpbmcgPT0gRmFjaW5nLlJJR0hUKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZW50cmFuY2Uud2lkdGg7IGluZGV4KyspXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMYXllclsoZW50cmFuY2UueSArIGluZGV4KSAqIHdpZHRoICsgZW50cmFuY2UueF0gPSAwO1xuICAgICAgICAgICAgaWYgKGVudHJhbmNlLnkgPiAwKVxuICAgICAgICAgICAgICAgIHJvb20udG9wTGF5ZXJbKGVudHJhbmNlLnkgLSAxKSAqIHdpZHRoICsgZW50cmFuY2UueF0gPSBlbnRyYW5jZS5hbHRfdGlsZVswXTtcbiAgICAgICAgICAgIGlmIChlbnRyYW5jZS55ICsgZW50cmFuY2Uud2lkdGggPD0gKHJvb20uYm90dG9tUmlnaHQueSAtIHJvb20udG9wTGVmdC55KSlcbiAgICAgICAgICAgICAgICByb29tLnRvcExheWVyWyhlbnRyYW5jZS55ICsgZW50cmFuY2Uud2lkdGgpICogd2lkdGggKyBlbnRyYW5jZS54XSA9IGVudHJhbmNlLmFsdF90aWxlWzFdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGVudHJhbmNlLndpZHRoOyBpbmRleCsrKVxuICAgICAgICAgICAgICAgIHJvb20udG9wTGF5ZXJbKGVudHJhbmNlLnkpICogd2lkdGggKyBlbnRyYW5jZS54ICsgaW5kZXhdID0gMDtcbiAgICAgICAgICAgIGlmIChlbnRyYW5jZS54ID4gMClcbiAgICAgICAgICAgICAgICByb29tLnRvcExheWVyWyhlbnRyYW5jZS55KSAqIHdpZHRoICsgZW50cmFuY2UueCAtIDFdID0gZW50cmFuY2UuYWx0X3RpbGVbMF07XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UueCArIGVudHJhbmNlLndpZHRoIDw9IChyb29tLmJvdHRvbVJpZ2h0LnggLSByb29tLnRvcExlZnQueCkpXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMYXllclsoZW50cmFuY2UueSkgKiB3aWR0aCArIGVudHJhbmNlLnggKyBlbnRyYW5jZS53aWR0aF0gPSBlbnRyYW5jZS5hbHRfdGlsZVsxXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZmlsbERhdGEoKSB7XG4gICAgICAgIGxldCB3aWR0aCA9IHRoaXMubWF4WCAtIHRoaXMubWluWCArIDE7XG4gICAgICAgIGxldCBoZWlnaHQgPSB0aGlzLm1heFkgLSB0aGlzLm1pblkgKyAxO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnMgPSBuZXcgQXJyYXkoMik7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXSA9IG5ldyBUaWxlZExheWVyRGF0YTtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzFdID0gbmV3IFRpbGVkTGF5ZXJEYXRhO1xuICAgICAgICB0aGlzLm1hcC53aWR0aCA9IHRoaXMubWFwLmxheWVyc1swXS53aWR0aCA9IHRoaXMubWFwLmxheWVyc1sxXS53aWR0aCA9IHdpZHRoO1xuICAgICAgICB0aGlzLm1hcC5oZWlnaHQgPSB0aGlzLm1hcC5sYXllcnNbMF0uaGVpZ2h0ID0gdGhpcy5tYXAubGF5ZXJzWzFdLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdGhpcy5tYXAudGlsZWhlaWdodCA9IHRoaXMudGVtcGxhdGUudGlsZWhlaWdodDtcbiAgICAgICAgdGhpcy5tYXAudGlsZXdpZHRoID0gdGhpcy50ZW1wbGF0ZS50aWxld2lkdGg7XG4gICAgICAgIHRoaXMubWFwLm9yaWVudGF0aW9uID0gXCJvcnRob2dvbmFsXCI7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS54ID0gdGhpcy5tYXAubGF5ZXJzWzBdLnkgPSB0aGlzLm1hcC5sYXllcnNbMV0ueCA9IHRoaXMubWFwLmxheWVyc1sxXS55ID0gMDtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzBdLm9wYWNpdHkgPSB0aGlzLm1hcC5sYXllcnNbMV0ub3BhY2l0eSA9IDE7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS52aXNpYmxlID0gdGhpcy5tYXAubGF5ZXJzWzFdLnZpc2libGUgPSB0cnVlO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0udHlwZSA9IHRoaXMubWFwLmxheWVyc1sxXS50eXBlID0gXCJ0aWxlbGF5ZXJcIjtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzBdLm5hbWUgPSBcIkZsb29yXCI7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1sxXS5uYW1lID0gXCJXYWxsXCI7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5wcm9wZXJ0aWVzID0gW3tcbiAgICAgICAgICAgIG5hbWU6IFwiQ29sbGlkYWJsZVwiLFxuICAgICAgICAgICAgdHlwZTogXCJib29sXCIsXG4gICAgICAgICAgICB2YWx1ZTogZmFsc2VcbiAgICAgICAgfV1cbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzFdLnByb3BlcnRpZXMgPSBbe1xuICAgICAgICAgICAgbmFtZTogXCJDb2xsaWRhYmxlXCIsXG4gICAgICAgICAgICB0eXBlOiBcImJvb2xcIixcbiAgICAgICAgICAgIHZhbHVlOiB0cnVlXG4gICAgICAgIH1dXG4gICAgICAgIHRoaXMubWFwLnRpbGVzZXRzID0gW3tcbiAgICAgICAgICAgIGNvbHVtbnM6IHRoaXMudGVtcGxhdGUuY29sdW1ucyxcbiAgICAgICAgICAgIHRpbGV3aWR0aDogdGhpcy50ZW1wbGF0ZS50aWxld2lkdGgsXG4gICAgICAgICAgICB0aWxlaGVpZ2h0OiB0aGlzLnRlbXBsYXRlLnRpbGVoZWlnaHQsXG4gICAgICAgICAgICB0aWxlY291bnQ6IHRoaXMudGVtcGxhdGUudGlsZWNvdW50LFxuICAgICAgICAgICAgZmlyc3RnaWQ6IHRoaXMudGVtcGxhdGUuZmlyc3RnaWQsXG4gICAgICAgICAgICBpbWFnZWhlaWdodDogdGhpcy50ZW1wbGF0ZS5pbWFnZWhlaWdodCxcbiAgICAgICAgICAgIGltYWdld2lkdGg6IHRoaXMudGVtcGxhdGUuaW1hZ2V3aWR0aCxcbiAgICAgICAgICAgIG1hcmdpbjogdGhpcy50ZW1wbGF0ZS5tYXJnaW4sXG4gICAgICAgICAgICBzcGFjaW5nOiB0aGlzLnRlbXBsYXRlLnNwYWNpbmcsXG4gICAgICAgICAgICBuYW1lOiB0aGlzLnRlbXBsYXRlLm5hbWUsXG4gICAgICAgICAgICBpbWFnZTogdGhpcy50ZW1wbGF0ZS5pbWFnZVxuICAgICAgICB9XVxuXG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5kYXRhID0gbmV3IEFycmF5KHdpZHRoICogaGVpZ2h0KS5maWxsKHRoaXMudGVtcGxhdGUuYmFja2dyb3VuZCk7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1sxXS5kYXRhID0gbmV3IEFycmF5KHdpZHRoICogaGVpZ2h0KTtcblxuICAgICAgICBmb3IgKGxldCByb29tIG9mIHRoaXMucm9vbXMpIHtcbiAgICAgICAgICAgIGxldCByb29tV2lkdGggPSByb29tLmJvdHRvbVJpZ2h0LnggLSByb29tLnRvcExlZnQueCArIDE7XG4gICAgICAgICAgICBsZXQgcm9vbUhlaWdodCA9IHJvb20uYm90dG9tUmlnaHQueSAtIHJvb20udG9wTGVmdC55ICsgMTtcbiAgICAgICAgICAgIHJvb20udG9wTGVmdC54IC09IHRoaXMubWluWDtcbiAgICAgICAgICAgIHJvb20udG9wTGVmdC55IC09IHRoaXMubWluWTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcm9vbUhlaWdodDsgaSsrKVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcm9vbVdpZHRoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzBdLmRhdGFbKHJvb20udG9wTGVmdC55ICsgaSkgKiB3aWR0aCArIHJvb20udG9wTGVmdC54ICsgal0gPSByb29tLmJvdHRvbUxheWVyW2kgKiByb29tV2lkdGggKyBqXTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzFdLmRhdGFbKHJvb20udG9wTGVmdC55ICsgaSkgKiB3aWR0aCArIHJvb20udG9wTGVmdC54ICsgal0gPSByb29tLnRvcExheWVyW2kgKiByb29tV2lkdGggKyBqXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocm9vbS5lbmVtaWVzKVxuICAgICAgICAgICAgICAgIGZvciAobGV0IGVuZW15IG9mIHJvb20uZW5lbWllcykge1xuICAgICAgICAgICAgICAgICAgICBlbmVteS5wb3NpdGlvbi54ICs9IHJvb20udG9wTGVmdC54O1xuICAgICAgICAgICAgICAgICAgICBlbmVteS5wb3NpdGlvbi55ICs9IHJvb20udG9wTGVmdC55O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZW1pZXMucHVzaChlbmVteSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc1ZhbGlkUm9vbSh0b3BMZWZ0OiBWZWMyLCBib3R0b21SaWdodDogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICBmb3IgKGxldCByb29tIG9mIHRoaXMucm9vbXMpIHtcbiAgICAgICAgICAgIGlmIChyb29tLnRvcExlZnQueCA8PSBib3R0b21SaWdodC54ICYmXG4gICAgICAgICAgICAgICAgcm9vbS5ib3R0b21SaWdodC54ID49IHRvcExlZnQueCAmJlxuICAgICAgICAgICAgICAgIHJvb20udG9wTGVmdC55IDw9IGJvdHRvbVJpZ2h0LnkgJiZcbiAgICAgICAgICAgICAgICByb29tLmJvdHRvbVJpZ2h0LnkgPj0gdG9wTGVmdC55KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiRm91bmQgYW4gaW52YWxpZCByb29tISBUb3BMZWZ0OlwiLCB0b3BMZWZ0LnRvU3RyaW5nKCksIFwiQm90dG9tUmlnaHQ6XCIsIGJvdHRvbVJpZ2h0LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEVudHJhbmNlRmFjaW5nKGVudHJhbmNlOiBFbnRyYW5jZSwgd2lkdGg6IG51bWJlcik6IEZhY2luZyB7XG4gICAgICAgIGlmIChlbnRyYW5jZS54ID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5MRUZUO1xuICAgICAgICBlbHNlIGlmIChlbnRyYW5jZS54ID09PSB3aWR0aCAtIDEpXG4gICAgICAgICAgICByZXR1cm4gRmFjaW5nLlJJR0hUXG4gICAgICAgIGVsc2UgaWYgKGVudHJhbmNlLnkgPT09IDApXG4gICAgICAgICAgICByZXR1cm4gRmFjaW5nLlVQO1xuICAgICAgICByZXR1cm4gRmFjaW5nLkRPV047XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRPcHBvc2l0ZUZhY2luZyhmYWNpbmc6IEZhY2luZyk6IEZhY2luZyB7XG4gICAgICAgIHN3aXRjaCAoZmFjaW5nKSB7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5MRUZUOlxuICAgICAgICAgICAgICAgIHJldHVybiBGYWNpbmcuUklHSFQ7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5SSUdIVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gRmFjaW5nLkxFRlQ7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5VUDpcbiAgICAgICAgICAgICAgICByZXR1cm4gRmFjaW5nLkRPV047XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5ET1dOOlxuICAgICAgICAgICAgICAgIHJldHVybiBGYWNpbmcuVVA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFJhbmRvbVJvb20oZmFjaW5nOiBGYWNpbmcpOiBSb29tVGVtcGxhdGUge1xuICAgICAgICBsZXQgYXJyYXkgPSB0aGlzLmdldFJvb21BcnJheShmYWNpbmcpLCB3ZWlnaHQgPSB0aGlzLmdldFJvb21XZWlnaHQoZmFjaW5nKTtcbiAgICAgICAgbGV0IHZhbHVlID0gdGhpcy5nZW4od2VpZ2h0KTtcblxuICAgICAgICBpZiAodmFsdWUgPj0gd2VpZ2h0KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmFuZG9tIG51bWJlciBcIiArIHZhbHVlICsgXCIgaXMgbGFyZ2VyIHRoYW4gdG90YWwgd2VpZ2h0IFwiICsgd2VpZ2h0KTtcblxuICAgICAgICBmb3IgKGxldCByb29tIG9mIGFycmF5KSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgPCByb29tLndlaWdodClcbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vbTtcbiAgICAgICAgICAgIHZhbHVlIC09IHJvb20ud2VpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIFJvb20hIFxcblZhbHVlOiBcIiArIHZhbHVlICsgXCJcXG5Sb29tczogXCIgKyBKU09OLnN0cmluZ2lmeShhcnJheSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Um9vbUFycmF5KGZhY2luZzogRmFjaW5nKTogQXJyYXk8Um9vbVRlbXBsYXRlPiB7XG4gICAgICAgIHN3aXRjaCAoZmFjaW5nKSB7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5MRUZUOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoTGVmdEVudHJhbmNlO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuUklHSFQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhSaWdodEVudHJhbmNlO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuVVA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhVcEVudHJhbmNlO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuRE9XTjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aERvd25FbnRyYW5jZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Um9vbVdlaWdodChmYWNpbmc6IEZhY2luZyk6IG51bWJlciB7XG4gICAgICAgIHN3aXRjaCAoZmFjaW5nKSB7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5MRUZUOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoTGVmdEVudHJhbmNlV2VpZ2h0O1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuUklHSFQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhSaWdodEVudHJhbmNlV2VpZ2h0O1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuVVA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhVcEVudHJhbmNlV2VpZ2h0O1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuRE9XTjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aERvd25FbnRyYW5jZVdlaWdodDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgY29weVJvb20ob2xkOiBSb29tVGVtcGxhdGUsIHBvc1g6IG51bWJlciwgcG9zWTogbnVtYmVyKTogUm9vbSB7XG4gICAgICAgIGxldCByb29tID0gbmV3IFJvb20oKTtcbiAgICAgICAgcm9vbS50b3BMZWZ0ID0gbmV3IFZlYzIocG9zWCwgcG9zWSk7XG4gICAgICAgIHJvb20uYm90dG9tUmlnaHQgPSBuZXcgVmVjMihwb3NYICsgb2xkLndpZHRoIC0gMSwgcG9zWSArIG9sZC5oZWlnaHQgLSAxKTtcbiAgICAgICAgcm9vbS50b3BMYXllciA9IFsuLi5vbGQudG9wTGF5ZXJdO1xuICAgICAgICByb29tLmJvdHRvbUxheWVyID0gWy4uLm9sZC5ib3R0b21MYXllcl07XG4gICAgICAgIHJvb20uZW5lbWllcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICBpZiAob2xkLnNwcml0ZXMpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHNwcml0ZSBvZiBvbGQuc3ByaXRlcykge1xuICAgICAgICAgICAgICAgIGlmIChzcHJpdGUudHlwZSA9PT0gJ3BsYXllcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGF5ZXIueCA9IHNwcml0ZS54ICsgcG9zWDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGF5ZXIueSA9IHNwcml0ZS55ICsgcG9zWTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmdlbi5yYW5kb20oKSA8PSBzcHJpdGUucG9zc2liaWxpdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0bXAgPSBuZXcgRW5lbXkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRtcC50eXBlID0gc3ByaXRlLnR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB0bXAucG9zaXRpb24gPSBuZXcgVmVjMihzcHJpdGUueCwgc3ByaXRlLnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vbS5lbmVtaWVzLnB1c2godG1wKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAob2xkLnN0YXJ0Q2hlY2tQb2ludCkge1xuICAgICAgICAgICAgdGhpcy5zdGFydENoZWNrUG9pbnQgPSBbLi4ub2xkLnN0YXJ0Q2hlY2tQb2ludF07XG4gICAgICAgICAgICB0aGlzLnN0YXJ0Q2hlY2tQb2ludFswXSArPSBwb3NYO1xuICAgICAgICAgICAgdGhpcy5zdGFydENoZWNrUG9pbnRbMV0gKz0gcG9zWTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob2xkLmVuZENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMuZW5kQ2hlY2tQb2ludCA9IFsuLi5vbGQuZW5kQ2hlY2tQb2ludF07XG4gICAgICAgICAgICB0aGlzLmVuZENoZWNrUG9pbnRbMF0gKz0gcG9zWDtcbiAgICAgICAgICAgIHRoaXMuZW5kQ2hlY2tQb2ludFsxXSArPSBwb3NZO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwb3NYIDwgdGhpcy5taW5YKVxuICAgICAgICAgICAgdGhpcy5taW5YID0gcG9zWDtcbiAgICAgICAgaWYgKHBvc1kgPCB0aGlzLm1pblkpXG4gICAgICAgICAgICB0aGlzLm1pblkgPSBwb3NZO1xuICAgICAgICBpZiAocG9zWCArIG9sZC53aWR0aCAtIDEgPiB0aGlzLm1heFgpXG4gICAgICAgICAgICB0aGlzLm1heFggPSBwb3NYICsgb2xkLndpZHRoIC0gMTtcbiAgICAgICAgaWYgKHBvc1kgKyBvbGQuaGVpZ2h0IC0gMSA+IHRoaXMubWF4WSlcbiAgICAgICAgICAgIHRoaXMubWF4WSA9IHBvc1kgKyBvbGQuaGVpZ2h0IC0gMTtcbiAgICAgICAgcmV0dXJuIHJvb207XG4gICAgfVxufVxuXG5jbGFzcyBSb29tIHtcbiAgICB0b3BMZWZ0OiBWZWMyO1xuICAgIGJvdHRvbVJpZ2h0OiBWZWMyO1xuICAgIHRvcExheWVyOiBBcnJheTxudW1iZXI+O1xuICAgIGJvdHRvbUxheWVyOiBBcnJheTxudW1iZXI+O1xuICAgIGVuZW1pZXM6IEFycmF5PEVuZW15PlxufVxuXG5leHBvcnQgY2xhc3MgRW5lbXkge1xuICAgIHR5cGU6IFN0cmluZztcbiAgICBwb3NpdGlvbjogVmVjMjtcbn1cblxuZW51bSBGYWNpbmcge1xuICAgIExFRlQgPSBcImxlZnRcIixcbiAgICBSSUdIVCA9IFwicmlnaHRcIixcbiAgICBVUCA9IFwidXBcIixcbiAgICBET1dOID0gXCJkb3duXCJcbn0iLCJpbXBvcnQgU2F2ZSBmcm9tIFwiLi9EYXRhVHlwZXMvU2F2ZVwiO1xuaW1wb3J0IExvY2FsU3RvcmFnZURCIGZyb20gXCIuL0xvY2FsU3RvcmFnZURCXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNhdmVNYW5hZ2VyIHtcbiAgICBwcml2YXRlIHN0YXRpYyBzYXZlOiBTYXZlO1xuICAgIHByaXZhdGUgZGI6IExvY2FsU3RvcmFnZURCO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZGIgPSBuZXcgTG9jYWxTdG9yYWdlREIoXCJzYXZlXCIpO1xuICAgICAgICB0aGlzLmxvYWRTYXZlKCk7XG5cbiAgICAgICAgaWYgKCFTYXZlTWFuYWdlci5zYXZlKVxuICAgICAgICAgICAgdGhpcy5pbml0U2F2ZSgpO1xuICAgIH1cblxuICAgIGdldExldmVsKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBTYXZlTWFuYWdlci5zYXZlLmxldmVsO1xuICAgIH1cblxuICAgIHNldExldmVsKGxldmVsOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgU2F2ZU1hbmFnZXIuc2F2ZS5sZXZlbCA9IGxldmVsO1xuICAgICAgICB0aGlzLnNhdmVTYXZlKCk7XG4gICAgfVxuXG4gICAgZ2V0TmFtZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gU2F2ZU1hbmFnZXIuc2F2ZS5uYW1lO1xuICAgIH1cblxuICAgIHNldE5hbWUobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIFNhdmVNYW5hZ2VyLnNhdmUubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuc2F2ZVNhdmUoKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPc1xuICAgIC8vIGFkZCBtb3JlIGZ1bmN0aW9ucyBpZiBuZWVkZWRcblxuXG4gICAgcmVzZXRTYXZlKGNhbGxiYWNrPzogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pbml0U2F2ZSgpO1xuICAgICAgICBjYWxsYmFjayhTYXZlTWFuYWdlci5zYXZlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRTYXZlKCk6IHZvaWQge1xuICAgICAgICBTYXZlTWFuYWdlci5zYXZlID0gPFNhdmU+dGhpcy5kYi5sb2FkSlNPTigpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2F2ZVNhdmUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGIuc2F2ZUpTT04oU2F2ZU1hbmFnZXIuc2F2ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0U2F2ZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYi5yZWFkSlNPTihcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvanNvbnMvc2FtcGxlc2F2ZS5qc29uXCIsIChzYXZlOiBvYmplY3QpID0+IHtcbiAgICAgICAgICAgIGlmICghc2F2ZSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsIHRvIGxvYWQgc2F2ZSBmaWxlXCIpO1xuICAgICAgICAgICAgU2F2ZU1hbmFnZXIuc2F2ZSA9IDxTYXZlPnNhdmU7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkluaXRpYWxpemluZyBMb2NhbCBTdG9yYWdlKHNhdmUpOiBcIiwgU2F2ZU1hbmFnZXIuc2F2ZSk7XG4gICAgICAgICAgICB0aGlzLnNhdmVTYXZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbn0iLCJleHBvcnQgZW51bSBQbGF5ZXJfRXZlbnRzIHtcbiAgICBQTEFZRVJfTU9WRSA9IFwiUGxheWVyTW92ZVwiLFxuICAgIFBMQVlFUl9KVU1QID0gXCJQbGF5ZXJKdW1wXCIsXG4gICAgUExBWUVSX0FUVEFDSyA9IFwiUGxheWVyQXR0YWNrXCIsXG4gICAgUExBWUVSX0RBU0ggPSBcIlBsYXllckRhc2hcIixcbiAgICBQTEFZRVJfSEVBTCA9IFwiUGxheWVySGVhbFwiLFxuICAgIExFVkVMX1NUQVJUID0gXCJMZXZlbFN0YXJ0XCIsXG4gICAgTEVWRUxfRU5EID0gXCJMZXZlbEVuZFwiLFxuICAgIFBMQVlFUl9LSUxMRUQgPSBcIlBsYXllcktpbGxlZFwiLFxuICAgIEVORU1ZX0tJTExFRCA9IFwiRW5lbXlLaWxsZWRcIixcbiAgICBQTEFZRVJfSElUX0VORU1ZID0gXCJQbGF5ZXJIaXRFbmVteVwiLFxuICAgIEJPU1NfS0lMTEVEID0gXCJCb3NzS2lsbGVkXCIsXG4gICAgR0lWRV9SRUdVTEFSX0JVRkYgPSBcIkdpdmVSZWd1bGFyQnVmZlwiLFxuICAgIEdJVkVfU1BFQ0lBTF9CVUZGID0gXCJHaXZlU3BlY2lhbEJ1ZmZcIixcbiAgICBQTEFZRVJfQ09MTElERSA9IFwiUGxheWVyQ29sbGlkZVwiXG59XG5leHBvcnQgZW51bSBEYW1hZ2VfVHlwZSB7XG4gICAgTk9STUFMX0RBTUFHRSA9IFwiTm9ybWFsRGFtYWdlXCIsXG4gICAgRU5WSVJPTk1FTlRfREFNQUdFID0gXCJFbnZpcm9ubWVudERhbWFnZVwiLFxuICAgIERPVF9EQU1BR0UgPSBcIkRPVERhbWFnZVwiLFxufVxuXG5leHBvcnQgZW51bSBTdGF0dXNlcyB7XG4gICAgSU5fUkFOR0UgPSBcIklOX1JBTkdFXCIsXG4gICAgTE9XX0hFQUxUSCA9IFwiTE9XX0hFQUxUSFwiLFxuICAgIENBTl9SRVRSRUFUID0gXCJDQU5fUkVUUkVBVFwiLFxuICAgIFJFQUNIRURfR09BTCA9IFwiR09BTFwiLFxuICAgIENBTl9CRVJTRVJLID0gXCJDQU5fQkVSU0VSS1wiXG59XG5cbmV4cG9ydCBlbnVtIEdhbWVTdGF0ZSB7XG4gICAgR0FNSU5HID0gXCJnYW1pbmdcIixcbiAgICBTVE9SWSA9IFwic3RvcnlcIixcbiAgICBCVUZGID0gXCJidWZmXCIsXG4gICAgUEFVU0UgPSBcInBhdXNlXCJcbn0iXX0=
|
||
|