12724 lines
1.6 MiB
12724 lines
1.6 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":12}],4:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Graph_1 = require("../DataTypes/Graphs/Graph");
|
|
const Stack_1 = require("../DataTypes/Stack");
|
|
const GraphUtils_1 = require("../Utils/GraphUtils");
|
|
class GoapActionPlanner {
|
|
plan(goal, possibleActions, currentStatus, actor) {
|
|
this.graph = new Graph_1.default(true);
|
|
this.mapping = new Map();
|
|
//0 is our root
|
|
this.graph.addNode();
|
|
this.mapping.set(0, "Start");
|
|
//1 is the goal
|
|
this.graph.addNode();
|
|
this.mapping.set(1, "Goal");
|
|
this.graph.addEdge(1, 1, Number.POSITIVE_INFINITY);
|
|
//Build tree from 0 to 1
|
|
this.buildTree(0, goal, possibleActions, currentStatus);
|
|
//Run djikstra to find shortest path
|
|
this.path = GraphUtils_1.default.djikstra(this.graph, 0);
|
|
//Push all elements of the plan
|
|
let plan = new Stack_1.default();
|
|
let i = 1;
|
|
while (this.path[i] !== -1) {
|
|
if (this.path[i] !== 0) {
|
|
plan.push(this.mapping.get(this.path[i]));
|
|
}
|
|
i = this.path[i];
|
|
}
|
|
return plan;
|
|
}
|
|
buildTree(root, goal, possibleActions, currentStatus) {
|
|
//For each possible action
|
|
possibleActions.forEach(action => {
|
|
//Can it be performed?
|
|
if (action.checkPreconditions(currentStatus)) {
|
|
//This action can be performed
|
|
//Add effects to currentStatus
|
|
let newStatus = [...currentStatus];
|
|
newStatus.push(...action.effects);
|
|
//Check if the new node is the goal
|
|
if (newStatus.includes(goal)) {
|
|
let newNode = this.graph.addNode() - 1;
|
|
this.mapping.set(newNode, action);
|
|
this.graph.addEdge(root, newNode, action.cost);
|
|
this.graph.addEdge(newNode, 1, 0);
|
|
return;
|
|
}
|
|
//Add node and edge from root
|
|
let newNode = this.graph.addNode() - 1;
|
|
this.mapping.set(newNode, action);
|
|
this.graph.addEdge(root, newNode, action.cost);
|
|
//Recursive call
|
|
let newActions = possibleActions.filter(act => act !== action);
|
|
this.buildTree(newNode, goal, newActions, action.effects);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
exports.default = GoapActionPlanner;
|
|
|
|
},{"../DataTypes/Graphs/Graph":9,"../DataTypes/Stack":21,"../Utils/GraphUtils":103}],5:[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":23}],6:[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 StateMachineGoapAI 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) { }
|
|
changeGoal(goal) { }
|
|
}
|
|
exports.default = StateMachineGoapAI;
|
|
|
|
},{"../DataTypes/State/StateMachine":23}],7:[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;
|
|
|
|
},{}],8:[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;
|
|
|
|
},{}],9:[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":8}],10:[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":9}],11:[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;
|
|
|
|
},{}],12:[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;
|
|
|
|
},{}],13:[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":26}],14:[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;
|
|
|
|
},{}],15:[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":26}],16:[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;
|
|
|
|
},{}],17:[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;
|
|
|
|
},{}],18:[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":104,"../Physics/Hit":15,"../Vec2":26,"./Circle":19,"./Shape":20}],19:[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":26,"./AABB":18,"./Shape":20}],20:[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":26,"./AABB":18}],21:[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;
|
|
|
|
},{}],22:[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":29}],23:[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":29,"../../Events/Receiver":33,"../Map":12,"../Stack":21}],24:[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;
|
|
|
|
},{}],25:[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":85,"../Vec2":26}],26:[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":104}],27:[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":12,"../DataTypes/Vec2":26,"../Utils/Color":101}],28:[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":101}],29:[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":30,"./GameEvent":31}],30:[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":12,"../DataTypes/Queue":16,"./GameEventType":32}],31:[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":12}],32:[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 = {}));
|
|
|
|
},{}],33:[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":16,"./EventQueue":30}],34:[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) {
|
|
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) {
|
|
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.mousePressPosition;
|
|
}
|
|
/**
|
|
* 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":12,"../DataTypes/Vec2":26,"../Events/EventQueue":30,"../Events/GameEventType":32,"../Events/Receiver":33}],35:[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":26,"../Events/EventQueue":30,"../Events/GameEvent":31,"../Events/GameEventType":32}],36:[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;
|
|
|
|
},{}],37:[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":27,"../Debug/Stats":28,"./GameLoop":39}],38:[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":26,"../Debug/Debug":27,"../Debug/Stats":28,"../Events/EventQueue":30,"../Input/Input":34,"../Input/InputHandler":35,"../Playback/Recorder":64,"../Registry/RegistryManager":67,"../Rendering/CanvasRenderer":73,"../Rendering/WebGLRenderer":78,"../ResourceManager/ResourceManager":85,"../Scene/SceneManager":93,"../SceneGraph/Viewport":97,"../Sound/AudioManager":98,"../Utils/Color":101,"./EnvironmentInitializer":36,"./FixedUpdateGameLoop":37,"./GameOptions":40}],39:[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":7}],40:[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;
|
|
|
|
},{}],41:[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":18,"../DataTypes/Vec2":26,"../Debug/Debug":27,"../Utils/Color":101,"./GameNode":42}],42:[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":11,"../DataTypes/Shapes/AABB":18,"../DataTypes/Shapes/Circle":19,"../DataTypes/Vec2":26,"../Debug/Debug":27,"../Events/Emitter":29,"../Events/Receiver":33,"../Rendering/Animations/TweenController":71,"../Utils/Color":101}],43:[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":101,"./CanvasNode":41}],44:[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 = {}));
|
|
|
|
},{}],45:[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":43}],46:[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":47}],47:[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":43}],48:[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;
|
|
}
|
|
/**
|
|
* 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":101,"../Graphic":43}],49:[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":26,"../../Rendering/Animations/AnimationManager":68,"./Sprite":50}],50:[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":26,"../../ResourceManager/ResourceManager":85,"../CanvasNode":41}],51:[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":26,"./CanvasNode":41}],52:[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":26,"../../Debug/Debug":27,"../../Utils/Color":101,"../Tilemap":51}],53:[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":26,"../Input/Input":34,"../Utils/Color":101,"./CanvasNode":41}],54:[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":101,"./Label":55}],55:[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":26,"../../Utils/Color":101,"../UIElement":53}],56:[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":26,"../../Input/Input":34,"../../Utils/Color":101,"../../Utils/MathUtils":104,"../UIElement":53}],57:[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":34,"../../Utils/Color":101,"./Label":55}],58:[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 = {}));
|
|
|
|
},{}],59:[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":12}],60:[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":26}],61:[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":21,"../Utils/GraphUtils":103,"./NavigationPath":60}],62:[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":14,"../DataTypes/Shapes/AABB":18,"../DataTypes/Vec2":26,"../Nodes/Tilemaps/OrthogonalTilemap":52,"./PhysicsManager":63}],63:[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":12,"../Events/Emitter":29,"../Events/Receiver":33}],64:[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":16,"../Events/EventQueue":30,"../Events/GameEventType":32,"../Events/Receiver":33}],65:[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":12}],66:[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":80,"../../Rendering/WebGLRendering/ShaderTypes/PointShaderType":81,"../../Rendering/WebGLRendering/ShaderTypes/RectShaderType":83,"../../Rendering/WebGLRendering/ShaderTypes/SpriteShaderType":84,"../../ResourceManager/ResourceManager":85,"./Registry":65}],67:[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":12,"./Registries/ShaderRegistry":66}],68:[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":12,"../../Events/Emitter":29,"./AnimationTypes":69}],69:[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;
|
|
|
|
},{}],70:[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;
|
|
|
|
},{}],71:[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":12,"../../Events/Emitter":29,"../../Utils/EaseFunctions":102,"../../Utils/MathUtils":104,"./AnimationTypes":69,"./TweenManager":72}],72:[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;
|
|
|
|
},{}],73:[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");
|
|
const Debug_1 = require("../Debug/Debug");
|
|
/**
|
|
* 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_1.default) {
|
|
Debug_1.default.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":26,"../Debug/Debug":27,"../Nodes/Graphic":43,"../Nodes/Graphics/Line":45,"../Nodes/Graphics/Point":47,"../Nodes/Graphics/Rect":48,"../Nodes/Sprites/AnimatedSprite":49,"../Nodes/Sprites/Sprite":50,"../Nodes/Tilemaps/OrthogonalTilemap":52,"../Nodes/UIElement":53,"../Nodes/UIElements/Button":54,"../Nodes/UIElements/Label":55,"../Nodes/UIElements/Slider":56,"../Nodes/UIElements/TextInput":57,"./CanvasRendering/GraphicRenderer":74,"./CanvasRendering/TilemapRenderer":75,"./CanvasRendering/UIElementRenderer":76,"./RenderingManager":77}],74:[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();
|
|
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":85}],75:[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":26,"../../ResourceManager/ResourceManager":85}],76:[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":26,"../../ResourceManager/ResourceManager":85,"../../Utils/MathUtils":104}],77:[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":85}],78:[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":26,"../Nodes/Graphic":43,"../Nodes/Graphics/Point":47,"../Nodes/Graphics/Rect":48,"../Nodes/Sprites/AnimatedSprite":49,"../Nodes/Sprites/Sprite":50,"../Nodes/UIElement":53,"../Nodes/UIElements/Label":55,"../Registry/Registries/ShaderRegistry":66,"../Registry/RegistryManager":67,"../ResourceManager/ResourceManager":85,"../Scene/Layers/ParallaxLayer":90,"./RenderingManager":77}],79:[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":85}],80:[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":13,"../../../DataTypes/Vec2":26,"../../../ResourceManager/ResourceManager":85,"./QuadShaderType":82}],81:[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":105,"../ShaderType":79}],82:[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":13,"../ShaderType":79}],83:[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":13,"../../../DataTypes/Vec2":26,"../../../ResourceManager/ResourceManager":85,"./QuadShaderType":82}],84:[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":13,"../../../DataTypes/Vec2":26,"../../../Nodes/Sprites/AnimatedSprite":49,"../../../ResourceManager/ResourceManager":85,"./QuadShaderType":82}],85:[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":12,"../DataTypes/Queue":16,"../DataTypes/Rendering/WebGLProgramType":17,"../Sound/AudioManager":98,"../Utils/StringUtils":106}],86:[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":26,"../../Nodes/Graphics/GraphicTypes":44,"../../Nodes/Graphics/Line":45,"../../Nodes/Graphics/Particle":46,"../../Nodes/Graphics/Point":47,"../../Nodes/Graphics/Rect":48,"../../Nodes/Sprites/AnimatedSprite":49,"../../Nodes/Sprites/Sprite":50,"../../Nodes/UIElements/Button":54,"../../Nodes/UIElements/Label":55,"../../Nodes/UIElements/Slider":56,"../../Nodes/UIElements/TextInput":57,"../../Nodes/UIElements/UIElementTypes":58,"../../ResourceManager/ResourceManager":85}],87:[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":86,"./TilemapFactory":88}],88:[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":10,"../../DataTypes/Tilesets/Tileset":25,"../../DataTypes/Vec2":26,"../../Nodes/Tilemaps/OrthogonalTilemap":52,"../../Pathfinding/Navmesh":61,"../../ResourceManager/ResourceManager":85}],89:[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":104}],90:[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":89}],91:[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":26,"./ParallaxLayer":90}],92:[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":12,"../DataTypes/Vec2":26,"../Debug/Debug":27,"../Events/Emitter":29,"../Events/Receiver":33,"../Nodes/CanvasNode":41,"../Pathfinding/NavigationManager":59,"../Physics/BasicPhysicsManager":62,"../Rendering/Animations/ParticleSystemManager":70,"../Rendering/Animations/TweenManager":72,"../ResourceManager/ResourceManager":85,"../SceneGraph/SceneGraphArray":96,"../Timing/TimerManager":100,"./Factories/FactoryManager":87,"./Layer":89,"./Layers/ParallaxLayer":90,"./Layers/UILayer":91,"./SceneOptions":94}],93:[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":85}],94:[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;
|
|
|
|
},{}],95:[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":26}],96:[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":28,"./SceneGraph":95}],97:[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":16,"../DataTypes/Shapes/AABB":18,"../DataTypes/Vec2":26,"../Input/Input":34,"../Scene/Layers/ParallaxLayer":90,"../Scene/Layers/UILayer":91,"../Utils/MathUtils":104}],98:[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":12,"../Events/GameEventType":32,"../Events/Receiver":33,"../ResourceManager/ResourceManager":85}],99:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.TimerState = void 0;
|
|
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) {
|
|
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 = {}));
|
|
|
|
},{"../Utils/MathUtils":104,"./TimerManager":100}],100:[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;
|
|
|
|
},{}],101:[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":104}],102:[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 = {}));
|
|
|
|
},{}],103:[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;
|
|
|
|
},{}],104:[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;
|
|
|
|
},{}],105:[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":104}],106:[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;
|
|
|
|
},{}],107:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Game_1 = require("./Wolfie2D/Loop/Game");
|
|
const MainMenu_1 = require("./shattered_sword/Scenes/MainMenu");
|
|
const RegistryManager_1 = require("./Wolfie2D/Registry/RegistryManager");
|
|
const WeaponRegistry_1 = require("./shattered_sword/Registry/WeaponRegistry");
|
|
const WeaponTypeRegistry_1 = require("./shattered_sword/Registry/WeaponTypeRegistry");
|
|
// 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: window.innerWidth, y: window.innerHeight },
|
|
clearColor: { r: 0, g: 0, b: 0 },
|
|
inputs: [
|
|
{ name: "left", keys: ["a", "arrowleft"] },
|
|
{ name: "right", keys: ["d", "arrowright"] },
|
|
{ name: "up", keys: ["w"] },
|
|
{ name: "down", keys: ["s"] },
|
|
{ name: "jump", keys: ["x", "space"] },
|
|
{ name: "attack", keys: ["j", "z", "enter"] },
|
|
{ name: "dash", keys: ["k", "z"] },
|
|
{ name: "skill", keys: ["l", "v"] },
|
|
{ name: "inventory", keys: ["i", "b"] },
|
|
{ name: "pause", keys: ["escape"] },
|
|
{ name: "tab", keys: ["tab"] },
|
|
{ name: "spawn", keys: ["q"] } //debug feature to test enemy spawning, press q to spawn enemy at current location
|
|
],
|
|
useWebGL: false,
|
|
showDebug: true // 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(MainMenu_1.default, {});
|
|
//TODO - change to splash screen once available
|
|
//game.start(SplashScreen,{});
|
|
})();
|
|
function runTests() { }
|
|
;
|
|
|
|
},{"./Wolfie2D/Loop/Game":38,"./Wolfie2D/Registry/RegistryManager":67,"./shattered_sword/Registry/WeaponRegistry":125,"./shattered_sword/Registry/WeaponTypeRegistry":126,"./shattered_sword/Scenes/MainMenu":129}],108:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.EnemyStates = void 0;
|
|
const GoapActionPlanner_1 = require("../../Wolfie2D/AI/GoapActionPlanner");
|
|
const StateMachineGoapAI_1 = require("../../Wolfie2D/AI/StateMachineGoapAI");
|
|
const Stack_1 = require("../../Wolfie2D/DataTypes/Stack");
|
|
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
|
const Patrol_1 = require("./EnemyStates/Patrol");
|
|
const sword_enums_1 = require("../sword_enums");
|
|
class EnemyAI extends StateMachineGoapAI_1.default {
|
|
constructor() {
|
|
super(...arguments);
|
|
/** The default movement speed of this AI */
|
|
this.speed = 20;
|
|
this.velocity = Vec2_1.default.ZERO;
|
|
}
|
|
initializeAI(owner, options) {
|
|
this.owner = owner;
|
|
//add states
|
|
// Patrol mode
|
|
this.addState(EnemyStates.DEFAULT, new Patrol_1.default(this, owner));
|
|
this.maxHealth = options.health;
|
|
this.CURRENT_HP = options.health;
|
|
this.weapon = options.weapon;
|
|
this.player = options.player;
|
|
this.inRange = options.inRange;
|
|
this.goal = options.goal;
|
|
this.currentStatus = options.status;
|
|
this.possibleActions = options.actions;
|
|
this.plan = new Stack_1.default();
|
|
this.planner = new GoapActionPlanner_1.default();
|
|
//TODO - get correct tilemap
|
|
//this.tilemap = this.owner.getScene().getTilemap(options.tilemap) as OrthogonalTilemap;
|
|
this.tilemap = this.owner.getScene().getLayer("Wall").getItems()[0];
|
|
//this.tilemap = <OrthogonalTilemap>this.owner.getScene().getTilemap("Main");
|
|
// Initialize to the default state
|
|
this.initialize(EnemyStates.DEFAULT);
|
|
//this.getPlayerPosition();
|
|
this.direction = 1; //default moving to the right
|
|
}
|
|
activate(options) { }
|
|
damage(damage) {
|
|
this.CURRENT_HP -= damage;
|
|
//TODO -
|
|
this.owner.animation.play("HURT");
|
|
console.log(damage + " damage taken, " + this.CURRENT_HP + " hp left");
|
|
// If we're low enough, add Low Health status to enemy
|
|
if (this.CURRENT_HP <= Math.floor(this.maxHealth / 2)) {
|
|
}
|
|
// 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;
|
|
this.emitter.fireEvent(sword_enums_1.Player_Events.ENEMY_KILLED, { owner: this.owner.id, ai: this });
|
|
if (Math.random() < 0.05) {
|
|
// give buff maybe
|
|
//this.emitter.fireEvent("giveBuff", { position: this.owner.position });
|
|
}
|
|
}
|
|
}
|
|
//TODO - need to modify for side view
|
|
/*
|
|
isPlayerVisible(pos: Vec2): Vec2{
|
|
//Check if one player is visible, taking into account walls
|
|
|
|
// Get the new player location
|
|
let start = this.owner.position.clone();
|
|
let delta = pos.clone().sub(start);
|
|
|
|
// 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 = <OrthogonalTilemap>this.owner.getScene().getLayer("Wall").getItems()[0];
|
|
|
|
let minIndex = walls.getColRowAt(new Vec2(minX, minY));
|
|
let maxIndex = walls.getColRowAt(new Vec2(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(col * tileSize.x + tileSize.x / 2, row * tileSize.y + tileSize.y / 2);
|
|
|
|
// Create a collider for this tile
|
|
let collider = new AABB(tilePos, tileSize.scaled(1 / 2));
|
|
|
|
let hit = collider.intersectSegment(start, delta, Vec2.ZERO);
|
|
|
|
if (hit !== null && start.distanceSqTo(hit.pos) < start.distanceSqTo(pos)) {
|
|
// We hit a wall, we can't see the player
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return pos;
|
|
}
|
|
*/
|
|
update(deltaT) {
|
|
super.update(deltaT);
|
|
// This is the plan that is executed in the Active state, so whenever we don't have a plan, acquire a new one given the current statuses the enemy has
|
|
/*
|
|
if (this.plan.isEmpty()) {
|
|
//get a new plan
|
|
this.plan = this.planner.plan(Statuses.REACHED_GOAL, this.possibleActions, this.currentStatus, null);
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
exports.default = EnemyAI;
|
|
var EnemyStates;
|
|
(function (EnemyStates) {
|
|
EnemyStates["DEFAULT"] = "default";
|
|
EnemyStates["ALERT"] = "alert";
|
|
EnemyStates["PREVIOUS"] = "previous";
|
|
})(EnemyStates = exports.EnemyStates || (exports.EnemyStates = {}));
|
|
|
|
},{"../../Wolfie2D/AI/GoapActionPlanner":4,"../../Wolfie2D/AI/StateMachineGoapAI":6,"../../Wolfie2D/DataTypes/Stack":21,"../../Wolfie2D/DataTypes/Vec2":26,"../sword_enums":133,"./EnemyStates/Patrol":110}],109:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const State_1 = require("../../../Wolfie2D/DataTypes/State/State");
|
|
class EnemyState extends State_1.default {
|
|
constructor(parent, owner) {
|
|
super(parent);
|
|
this.gravity = 1500; //TODO - can change later
|
|
this.owner = owner;
|
|
}
|
|
update(deltaT) {
|
|
// Do gravity
|
|
this.parent.velocity.y += this.gravity * deltaT;
|
|
}
|
|
}
|
|
exports.default = EnemyState;
|
|
|
|
},{"../../../Wolfie2D/DataTypes/State/State":22}],110:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const EnemyState_1 = require("./EnemyState");
|
|
const MathUtils_1 = require("../../../Wolfie2D/Utils/MathUtils");
|
|
class Patrol extends EnemyState_1.default {
|
|
constructor(parent, owner) {
|
|
super(parent, owner);
|
|
}
|
|
onEnter(options) {
|
|
//this.currentPath = this.getNextPath();
|
|
this.owner.animation.play("IDLE", true);
|
|
}
|
|
handleInput(event) { }
|
|
update(deltaT) {
|
|
super.update(deltaT);
|
|
//no goap rn, just adding some moving
|
|
let colrow = this.parent.tilemap.getColRowAt(this.owner.position.clone());
|
|
//check if next tile on walking path is collidable
|
|
if (this.parent.tilemap.isTileCollidable(colrow.x + this.parent.direction, colrow.y)) {
|
|
//turn around
|
|
//console.log(this.parent.tilemap.getTileAtRowCol(colrow));
|
|
this.parent.direction *= -1;
|
|
this.owner.invertX = MathUtils_1.default.sign(1) < 0;
|
|
//console.log("turn around cus wall in front");
|
|
}
|
|
//check if next ground tile is collidable
|
|
else if (this.parent.tilemap.isTileCollidable(colrow.x + this.parent.direction, colrow.y + 1)) {
|
|
//keep moving
|
|
//this.velocity.x = this.speed;
|
|
//console.log("there is floor ahead");
|
|
}
|
|
else {
|
|
//turn around
|
|
this.parent.direction *= -1;
|
|
this.owner.invertX = MathUtils_1.default.sign(1) < 0;
|
|
//console.log("turn around cus no floor in front");
|
|
}
|
|
//move
|
|
this.parent.velocity.x = this.parent.direction * this.parent.speed;
|
|
//move this elsewhere later
|
|
this.owner.move(this.parent.velocity.scaled(deltaT));
|
|
//console.log("enemy moving");
|
|
}
|
|
onExit() {
|
|
return this.retObj;
|
|
}
|
|
}
|
|
exports.default = Patrol;
|
|
|
|
},{"../../../Wolfie2D/Utils/MathUtils":104,"./EnemyState":109}],111:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
class BattleManager {
|
|
handleInteraction(attackerType, weapon) {
|
|
//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)) {
|
|
enemy.damage(weapon.type.damage + weapon.EXTRA_DAMAGE);
|
|
//console.log("enemy took dmg");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Check for collision with player
|
|
for (let player of this.players) {
|
|
if (weapon.hits(player.owner)) {
|
|
player.damage(weapon.type.damage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
|
|
},{}],112:[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":26,"../../Wolfie2D/Nodes/Graphics/GraphicTypes":44,"../../Wolfie2D/Utils/Color":101}],113:[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;
|
|
|
|
},{}],114:[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");
|
|
class Weapon extends Item_1.default {
|
|
constructor(sprite, type, battleManager) {
|
|
super(sprite);
|
|
// 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.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);
|
|
// Reset the cooldown timer
|
|
this.cooldownTimer.start();
|
|
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":29,"../../../Wolfie2D/Timing/Timer":99,"./Item":113}],115:[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) {
|
|
//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;
|
|
// Rotate this with the game node
|
|
// TODO - need to rotate the anim properly
|
|
sliceSprite.rotation = attacker.rotation;
|
|
sliceSprite.rotation = attacker.invertX ? .5 * Math.PI : 1.5 * Math.PI;
|
|
// 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":26,"./WeaponType":116}],116:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
class WeaponType {
|
|
}
|
|
exports.default = WeaponType;
|
|
|
|
},{}],117:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.BuffType = exports.PlayerStates = exports.PlayerType = void 0;
|
|
const StateMachineAI_1 = require("../../Wolfie2D/AI/StateMachineAI");
|
|
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
|
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 Input_1 = require("../../Wolfie2D/Input/Input");
|
|
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["ATK"] = "attack";
|
|
BuffType["DEF"] = "defence";
|
|
BuffType["HEALTH"] = "health";
|
|
BuffType["SPEED"] = "speed";
|
|
BuffType["RANGE"] = "range";
|
|
})(BuffType = exports.BuffType || (exports.BuffType = {}));
|
|
//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.MAX_ATK = 100;
|
|
this.CURRENT_ATK = 100;
|
|
this.BASE_DEF = 100;
|
|
this.MAX_DEF = 100;
|
|
this.CURRENT_DEF = 100;
|
|
}
|
|
// TODO -
|
|
damage(damage) {
|
|
this.CURRENT_HP -= damage;
|
|
}
|
|
/**
|
|
* Returns three legal random generate buffs based on current state
|
|
* @returns Three buffs
|
|
*/
|
|
static getBuffs() {
|
|
// TODO
|
|
return undefined;
|
|
}
|
|
/**
|
|
* Add given buff to the player
|
|
* @param buff Given buff
|
|
*/
|
|
addBuff(buff) {
|
|
// TODO
|
|
let item = this.inventory.getItem();
|
|
switch (buff.type) {
|
|
case BuffType.HEALTH:
|
|
this.CURRENT_BUFFS.hp += buff.value;
|
|
this.CURRENT_HP += buff.value;
|
|
break;
|
|
case BuffType.ATK:
|
|
//TODO - decide what to do with atk stat
|
|
this.CURRENT_BUFFS.atk += buff.value;
|
|
if (item) {
|
|
item.EXTRA_DAMAGE += buff.value;
|
|
}
|
|
break;
|
|
case BuffType.SPEED:
|
|
this.CURRENT_BUFFS.speed += buff.value;
|
|
break;
|
|
case BuffType.DEF:
|
|
this.CURRENT_BUFFS.def += buff.value;
|
|
break;
|
|
case BuffType.RANGE:
|
|
this.CURRENT_BUFFS.range += buff.value;
|
|
if (item) {
|
|
item.EXTRA_RANGE += buff.value;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
//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();
|
|
this.CURRENT_BUFFS = { hp: 0, atk: 0, def: 0, speed: 0, range: 0 };
|
|
//to test the buffs
|
|
//this.addBuff( {type:BuffType.HEALTH, value:1, bonus:false} );
|
|
//this.addBuff( {type:BuffType.RANGE, value:1, bonus:false} );
|
|
}
|
|
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 (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("playerspeed", "x: " + this.velocity.x + ", y:" + this.velocity.y);
|
|
//testing the attacks here, may be moved to another place latera
|
|
if (Input_1.default.isJustPressed("attack")) {
|
|
let item = this.inventory.getItem();
|
|
this.owner.animation.playIfNotAlready("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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
exports.default = PlayerController;
|
|
|
|
},{"../../Wolfie2D/AI/StateMachineAI":5,"../../Wolfie2D/DataTypes/Vec2":26,"../../Wolfie2D/Debug/Debug":27,"../../Wolfie2D/Input/Input":34,"./PlayerStates/Fall":118,"./PlayerStates/Idle":119,"./PlayerStates/InAir":120,"./PlayerStates/Jump":121,"./PlayerStates/Walk":124}],118:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const InAir_1 = require("./InAir");
|
|
class Fall extends InAir_1.default {
|
|
onEnter(options) {
|
|
this.owner.animation.play("FALL", true);
|
|
}
|
|
onExit() {
|
|
this.owner.animation.stop();
|
|
return {};
|
|
}
|
|
}
|
|
exports.default = Fall;
|
|
|
|
},{"./InAir":120}],119:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const PlayerController_1 = require("../PlayerController");
|
|
const OnGround_1 = require("./OnGround");
|
|
class Idle extends OnGround_1.default {
|
|
onEnter(options) {
|
|
this.parent.speed = this.parent.MIN_SPEED;
|
|
}
|
|
update(deltaT) {
|
|
super.update(deltaT);
|
|
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;
|
|
this.owner.move(this.parent.velocity.scaled(deltaT));
|
|
}
|
|
onExit() {
|
|
this.owner.animation.stop();
|
|
return {};
|
|
}
|
|
}
|
|
exports.default = Idle;
|
|
|
|
},{"../PlayerController":117,"./OnGround":122}],120:[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;
|
|
this.owner.move(this.parent.velocity.scaled(deltaT));
|
|
if (this.owner.onGround) {
|
|
this.finished(PlayerController_1.PlayerStates.PREVIOUS);
|
|
}
|
|
}
|
|
}
|
|
exports.default = InAir;
|
|
|
|
},{"../../../Wolfie2D/Utils/MathUtils":104,"../PlayerController":117,"./PlayerState":123}],121:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const GameEventType_1 = require("../../../Wolfie2D/Events/GameEventType");
|
|
const PlayerController_1 = require("../PlayerController");
|
|
const InAir_1 = require("./InAir");
|
|
class Jump extends InAir_1.default {
|
|
onEnter(options) {
|
|
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "jump", loop: false, holdReference: false });
|
|
}
|
|
update(deltaT) {
|
|
super.update(deltaT);
|
|
this.owner.animation.play("JUMP", true);
|
|
if (this.owner.onCeiling) {
|
|
this.parent.velocity.y = 0;
|
|
}
|
|
// If we're falling, go to the fall state
|
|
if (this.parent.velocity.y >= 0) {
|
|
this.finished(PlayerController_1.PlayerStates.FALL);
|
|
}
|
|
}
|
|
onExit() {
|
|
this.owner.animation.stop();
|
|
return {};
|
|
}
|
|
}
|
|
exports.default = Jump;
|
|
|
|
},{"../../../Wolfie2D/Events/GameEventType":32,"../PlayerController":117,"./InAir":120}],122:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const Input_1 = require("../../../Wolfie2D/Input/Input");
|
|
const MathUtils_1 = require("../../../Wolfie2D/Utils/MathUtils");
|
|
const PlayerState_1 = require("./PlayerState");
|
|
class OnGround extends PlayerState_1.default {
|
|
onEnter(options) { }
|
|
update(deltaT) {
|
|
if (this.parent.velocity.y > 0) {
|
|
this.parent.velocity.y = 0;
|
|
}
|
|
super.update(deltaT);
|
|
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 (Input_1.default.isJustPressed("jump")) {
|
|
this.finished("jump");
|
|
this.parent.velocity.y = -600; // basically jump height
|
|
}
|
|
else if (!this.owner.onGround) {
|
|
this.finished("fall");
|
|
}
|
|
}
|
|
onExit() {
|
|
return {};
|
|
}
|
|
}
|
|
exports.default = OnGround;
|
|
|
|
},{"../../../Wolfie2D/Input/Input":34,"../../../Wolfie2D/Utils/MathUtils":104,"./PlayerState":123}],123:[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 Input_1 = require("../../../Wolfie2D/Input/Input");
|
|
const Timer_1 = require("../../../Wolfie2D/Timing/Timer");
|
|
const sword_enums_1 = require("../../sword_enums");
|
|
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();
|
|
}
|
|
handleInput(event) {
|
|
}
|
|
/**
|
|
* Get the inputs from the keyboard, or Vec2.Zero if nothing is being pressed
|
|
*/
|
|
getInputDirection() {
|
|
let direction = Vec2_1.default.ZERO;
|
|
direction.x = (Input_1.default.isPressed("left") ? -1 : 0) + (Input_1.default.isPressed("right") ? 1 : 0);
|
|
direction.y = (Input_1.default.isJustPressed("jump") ? -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();
|
|
}
|
|
this.parent.velocity.y += this.gravity * deltaT;
|
|
}
|
|
}
|
|
exports.default = PlayerState;
|
|
|
|
},{"../../../Wolfie2D/DataTypes/State/State":22,"../../../Wolfie2D/DataTypes/Vec2":26,"../../../Wolfie2D/Input/Input":34,"../../../Wolfie2D/Timing/Timer":99,"../../sword_enums":133}],124:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const PlayerController_1 = require("../PlayerController");
|
|
const OnGround_1 = require("./OnGround");
|
|
class Walk extends OnGround_1.default {
|
|
onEnter(options) {
|
|
this.parent.speed = this.parent.MIN_SPEED;
|
|
}
|
|
update(deltaT) {
|
|
super.update(deltaT);
|
|
//console.log("walking anim");
|
|
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;
|
|
this.owner.move(this.parent.velocity.scaled(deltaT));
|
|
}
|
|
onExit() {
|
|
this.owner.animation.stop();
|
|
return {};
|
|
}
|
|
}
|
|
exports.default = Walk;
|
|
|
|
},{"../PlayerController":117,"./OnGround":122}],125:[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":65,"../../Wolfie2D/ResourceManager/ResourceManager":85,"../GameSystems/items/WeaponTypes/Slice":115}],126:[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":65}],127:[function(require,module,exports){
|
|
"use strict";
|
|
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 Input_1 = require("../../Wolfie2D/Input/Input");
|
|
const GameNode_1 = require("../../Wolfie2D/Nodes/GameNode");
|
|
const GraphicTypes_1 = require("../../Wolfie2D/Nodes/Graphics/GraphicTypes");
|
|
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
|
const Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
|
const Timer_1 = require("../../Wolfie2D/Timing/Timer");
|
|
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
|
const EaseFunctions_1 = require("../../Wolfie2D/Utils/EaseFunctions");
|
|
const PlayerController_1 = require("../Player/PlayerController");
|
|
const MainMenu_1 = require("./MainMenu");
|
|
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 InventoryManager_1 = require("../GameSystems/InventoryManager");
|
|
// 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 {
|
|
loadScene() {
|
|
//can load player sprite here
|
|
//can load enemy sprite here
|
|
// 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.image("knife", "shattered_sword_assets/sprites/knife.png");
|
|
this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
|
|
this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png");
|
|
this.load.spritesheet("test_dummy", "shattered_sword_assets/spritesheets/test_dummy.json");
|
|
}
|
|
startScene() {
|
|
// Do the game level standard initializations
|
|
this.initLayers();
|
|
this.initViewport();
|
|
// Create the battle manager
|
|
this.battleManager = new BattleManager_1.default();
|
|
// TODO
|
|
this.initializeWeapons();
|
|
// Initialize the items array - this represents items that are in the game world
|
|
this.items = new Array();
|
|
// Create an enemies array
|
|
this.enemies = new Array();
|
|
this.initPlayer();
|
|
this.subscribeToEvents();
|
|
this.addUI();
|
|
// 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));
|
|
// Subscribe to relevant events
|
|
//this.receiver.subscribe("");
|
|
// Initialize the timers
|
|
this.respawnTimer = new Timer_1.default(1000, () => {
|
|
if (GameLevel.livesCount === 0) {
|
|
this.sceneManager.changeToScene(MainMenu_1.default);
|
|
}
|
|
else {
|
|
this.respawnPlayer();
|
|
this.player.enablePhysics();
|
|
this.player.unfreeze();
|
|
}
|
|
});
|
|
this.levelTransitionTimer = new Timer_1.default(500);
|
|
this.levelEndTimer = new Timer_1.default(3000, () => {
|
|
// After the level end timer ends, fade to black and then go to the next scene
|
|
this.levelTransitionScreen.tweens.play("fadeIn");
|
|
});
|
|
// Start the black screen fade out
|
|
this.levelTransitionScreen.tweens.play("fadeOut");
|
|
//TODO - uncomment when done testing
|
|
// Initially disable player movement
|
|
//Input.disableInput();
|
|
Input_1.default.enableInput();
|
|
}
|
|
updateScene(deltaT) {
|
|
// Handle events and update the UI if needed
|
|
while (this.receiver.hasNextEvent()) {
|
|
let event = this.receiver.getNextEvent();
|
|
switch (event.type) {
|
|
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"));
|
|
console.log("enemy destroyed");
|
|
node.destroy();
|
|
break;
|
|
}
|
|
}
|
|
//update health UI
|
|
let playerAI = this.player.ai;
|
|
this.healthLabel.text = "Player Health: " + playerAI.CURRENT_HP + '/' + (playerAI.MAX_HP + playerAI.CURRENT_BUFFS.hp);
|
|
//handle collisions - may be in battle manager instead
|
|
//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 - this is for testing
|
|
if (Input_1.default.isJustPressed("spawn")) {
|
|
console.log("trying to spawn enemy");
|
|
this.addEnemy("test_dummy", this.player.position, { player: this.player,
|
|
health: 100,
|
|
tilemap: "Main",
|
|
//actions:actions,
|
|
goal: sword_enums_1.Statuses.REACHED_GOAL,
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* Initialzes the layers
|
|
*/
|
|
initLayers() {
|
|
// Add a layer for UI
|
|
this.addUILayer("UI");
|
|
// Add a layer for players and enemies
|
|
this.addLayer("primary", 1);
|
|
}
|
|
/**
|
|
* Initializes the viewport
|
|
*/
|
|
initViewport() {
|
|
this.viewport.setZoomLevel(2);
|
|
}
|
|
/**
|
|
* Handles all subscriptions to events
|
|
*/
|
|
subscribeToEvents() {
|
|
this.receiver.subscribe([
|
|
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
|
|
]);
|
|
}
|
|
// 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(120, 30), text: "Player Health: " + this.player.ai.CURRENT_HP });
|
|
this.healthLabel.textColor = Color_1.default.WHITE;
|
|
this.healthLabel.font = "PixelSimple";
|
|
//seed label
|
|
//this.seedLabel = <Label> this.add.uiElement(UIElementType.LABEL, "UI",{position: new Vec2(400, 30), text: "Seed: "+ this.randomSeed });
|
|
this.seedLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(this.worldSize.x - 50, 30), text: "Seed: " + this.randomSeed });
|
|
this.seedLabel.textColor = Color_1.default.WHITE;
|
|
this.seedLabel.font = "PixelSimple";
|
|
// End of level label (start off screen)
|
|
this.levelEndLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(-300, 200), text: "Level Complete" });
|
|
this.levelEndLabel.size.set(1200, 60);
|
|
this.levelEndLabel.borderRadius = 0;
|
|
this.levelEndLabel.backgroundColor = new Color_1.default(34, 32, 52);
|
|
this.levelEndLabel.textColor = Color_1.default.WHITE;
|
|
this.levelEndLabel.fontSize = 48;
|
|
this.levelEndLabel.font = "PixelSimple";
|
|
// Add a tween to move the label on screen
|
|
this.levelEndLabel.tweens.add("slideIn", {
|
|
startDelay: 0,
|
|
duration: 1000,
|
|
effects: [
|
|
{
|
|
property: GameNode_1.TweenableProperties.posX,
|
|
start: -300,
|
|
end: 300,
|
|
ease: EaseFunctions_1.EaseFunctionType.OUT_SINE
|
|
}
|
|
]
|
|
});
|
|
this.levelTransitionScreen = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(300, 200), size: new Vec2_1.default(600, 400) });
|
|
this.levelTransitionScreen.color = new Color_1.default(34, 32, 52);
|
|
this.levelTransitionScreen.alpha = 1;
|
|
this.levelTransitionScreen.tweens.add("fadeIn", {
|
|
startDelay: 0,
|
|
duration: 1000,
|
|
effects: [
|
|
{
|
|
property: GameNode_1.TweenableProperties.alpha,
|
|
start: 0,
|
|
end: 1,
|
|
ease: EaseFunctions_1.EaseFunctionType.IN_OUT_QUAD
|
|
}
|
|
],
|
|
onEnd: sword_enums_1.Player_Events.LEVEL_END
|
|
});
|
|
this.levelTransitionScreen.tweens.add("fadeOut", {
|
|
startDelay: 0,
|
|
duration: 1000,
|
|
effects: [
|
|
{
|
|
property: GameNode_1.TweenableProperties.alpha,
|
|
start: 1,
|
|
end: 0,
|
|
ease: EaseFunctions_1.EaseFunctionType.IN_OUT_QUAD
|
|
}
|
|
],
|
|
onEnd: sword_enums_1.Player_Events.LEVEL_START
|
|
});
|
|
}
|
|
//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.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, aiOptions) {
|
|
let enemy = this.add.animatedSprite(spriteKey, "primary");
|
|
//enemy.position.set(tilePos.x*32, tilePos.y*32);
|
|
enemy.position.copy(tilePos);
|
|
enemy.scale.set(2, 2);
|
|
enemy.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, new Vec2_1.default(16, 25)));
|
|
enemy.colliderOffset.set(0, 6);
|
|
enemy.addAI(EnemyAI_1.default, aiOptions); //TODO - add individual enemy AI
|
|
enemy.setGroup("Enemy");
|
|
//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);
|
|
}
|
|
handlePlayerEnemyCollision(player, enemy) {
|
|
//collisions are handled by the battleManager - no need for this in gamelevel for now
|
|
}
|
|
/**
|
|
* Increments the amount of life the player has
|
|
* @param amt The amount to add to the player life
|
|
*/
|
|
incPlayerLife(amt) {
|
|
GameLevel.livesCount += amt;
|
|
this.livesCountLabel.text = "Lives: " + GameLevel.livesCount;
|
|
if (GameLevel.livesCount == 0) {
|
|
Input_1.default.disableInput();
|
|
this.player.disablePhysics();
|
|
this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "player_death", loop: false, holdReference: false });
|
|
this.player.tweens.play("death");
|
|
}
|
|
}
|
|
/**
|
|
* Returns the player to spawn
|
|
*/
|
|
respawnPlayer() {
|
|
GameLevel.livesCount = 3;
|
|
this.emitter.fireEvent(GameEventType_1.GameEventType.STOP_SOUND, { key: "level_music" });
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
Input_1.default.enableInput();
|
|
}
|
|
/**
|
|
*
|
|
* 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);
|
|
}
|
|
}
|
|
}
|
|
exports.default = GameLevel;
|
|
// Labels for the UI
|
|
GameLevel.livesCount = 3;
|
|
|
|
},{"../../Wolfie2D/DataTypes/Shapes/AABB":18,"../../Wolfie2D/DataTypes/Vec2":26,"../../Wolfie2D/Events/GameEventType":32,"../../Wolfie2D/Input/Input":34,"../../Wolfie2D/Nodes/GameNode":42,"../../Wolfie2D/Nodes/Graphics/GraphicTypes":44,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":58,"../../Wolfie2D/Registry/RegistryManager":67,"../../Wolfie2D/Scene/Scene":92,"../../Wolfie2D/Timing/Timer":99,"../../Wolfie2D/Utils/Color":101,"../../Wolfie2D/Utils/EaseFunctions":102,"../AI/EnemyAI":108,"../GameSystems/BattleManager":111,"../GameSystems/InventoryManager":112,"../GameSystems/items/Weapon":114,"../Player/PlayerController":117,"../sword_enums":133,"./MainMenu":129}],128:[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 SceneWithStory_1 = require("./SceneWithStory");
|
|
const Tutorial_1 = require("./Tutorial");
|
|
class Levels extends Scene_1.default {
|
|
// TODO
|
|
loadScene() { }
|
|
startScene() {
|
|
const center = this.viewport.getCenter();
|
|
// The main menu
|
|
this.primary = this.addUILayer("primary");
|
|
const tutorial = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y - 200), text: "tutorial " });
|
|
tutorial.size.set(200, 50);
|
|
tutorial.borderWidth = 2;
|
|
tutorial.borderColor = Color_1.default.WHITE;
|
|
tutorial.backgroundColor = Color_1.default.TRANSPARENT;
|
|
tutorial.onClickEventId = "tutorial";
|
|
const level1 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y - 150), text: "level 1" });
|
|
level1.size.set(200, 50);
|
|
level1.borderWidth = 2;
|
|
level1.borderColor = Color_1.default.WHITE;
|
|
level1.backgroundColor = Color_1.default.TRANSPARENT;
|
|
level1.onClickEventId = "level1";
|
|
const level2 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y - 100), text: "level 2" });
|
|
level2.size.set(200, 50);
|
|
level2.borderWidth = 2;
|
|
level2.borderColor = Color_1.default.WHITE;
|
|
level2.backgroundColor = Color_1.default.TRANSPARENT;
|
|
level2.onClickEventId = "level2";
|
|
const level3 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y - 50), text: "level 3" });
|
|
level3.size.set(200, 50);
|
|
level3.borderWidth = 2;
|
|
level3.borderColor = Color_1.default.WHITE;
|
|
level3.backgroundColor = Color_1.default.TRANSPARENT;
|
|
level3.onClickEventId = "level3";
|
|
const level4 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y), text: "level 4" });
|
|
level4.size.set(200, 50);
|
|
level4.borderWidth = 2;
|
|
level4.borderColor = Color_1.default.WHITE;
|
|
level4.backgroundColor = Color_1.default.TRANSPARENT;
|
|
level4.onClickEventId = "level4";
|
|
const level5 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 50), text: "level 5" });
|
|
level5.size.set(200, 50);
|
|
level5.borderWidth = 2;
|
|
level5.borderColor = Color_1.default.WHITE;
|
|
level5.backgroundColor = Color_1.default.TRANSPARENT;
|
|
level5.onClickEventId = "level5";
|
|
const StorySceneTester = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 100), text: "StorySceneTester" });
|
|
StorySceneTester.size.set(200, 50);
|
|
StorySceneTester.borderWidth = 2;
|
|
StorySceneTester.borderColor = Color_1.default.WHITE;
|
|
StorySceneTester.backgroundColor = Color_1.default.TRANSPARENT;
|
|
StorySceneTester.onClickEventId = "StorySceneTester";
|
|
const back = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 250), 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("tutorial");
|
|
this.receiver.subscribe("level1");
|
|
this.receiver.subscribe("level2");
|
|
this.receiver.subscribe("level3");
|
|
this.receiver.subscribe("level4");
|
|
this.receiver.subscribe("level5");
|
|
this.receiver.subscribe("StorySceneTester");
|
|
this.receiver.subscribe("back");
|
|
}
|
|
updateScene() {
|
|
while (this.receiver.hasNextEvent()) {
|
|
let event = this.receiver.getNextEvent();
|
|
console.log(event);
|
|
if (event.type === "tutorial") {
|
|
this.sceneManager.changeToScene(Tutorial_1.default, {});
|
|
}
|
|
if (event.type === "level1") {
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
}
|
|
if (event.type === "level2") {
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
}
|
|
if (event.type === "level3") {
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
}
|
|
if (event.type === "level4") {
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
}
|
|
if (event.type === "level5") {
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
}
|
|
if (event.type === "StorySceneTester") {
|
|
this.sceneManager.changeToScene(SceneWithStory_1.default, {});
|
|
}
|
|
if (event.type === "back") {
|
|
this.sceneManager.changeToScene(MainMenu_1.default, {});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
exports.default = Levels;
|
|
|
|
},{"../../Wolfie2D/DataTypes/Vec2":26,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":58,"../../Wolfie2D/Scene/Scene":92,"../../Wolfie2D/Utils/Color":101,"./MainMenu":129,"./SceneWithStory":130,"./Tutorial":131}],129:[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");
|
|
class MainMenu extends Scene_1.default {
|
|
loadScene() {
|
|
// Load the menu song
|
|
//this.load.audio("menu", "shattered_sword_assets/music/menu.mp3");
|
|
}
|
|
//TODO
|
|
startScene() {
|
|
// this.config = new ConfigManager();
|
|
// this.save = new SaveManager();
|
|
// console.log(this.config.getVolume());
|
|
// this.config.setVolume(100);
|
|
// console.log(this.config.getVolume());
|
|
// console.log(this.save.getLevel());
|
|
// this.save.setLevel(10);
|
|
// console.log(this.save.getLevel());
|
|
// this.rmg = new RandomMapGenerator("shattered_sword_assets/jsons/forest_template.json", 114514);
|
|
// this.rmg.getMap();
|
|
// Scene has started, so start playing music
|
|
//this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "menu", loop: true, holdReference: true});
|
|
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 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 + 250), 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":26,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":58,"../../Wolfie2D/Scene/Scene":92,"../../Wolfie2D/Utils/Color":101,"./Levels":128}],130:[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 Scene_1 = require("../../Wolfie2D/Scene/Scene");
|
|
const Label_1 = require("../../Wolfie2D/Nodes/UIElements/Label");
|
|
const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes");
|
|
const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2");
|
|
const Color_1 = require("../../Wolfie2D/Utils/Color");
|
|
const GameEventType_1 = require("../../Wolfie2D/Events/GameEventType");
|
|
const Input_1 = require("../../Wolfie2D/Input/Input");
|
|
var Mode;
|
|
(function (Mode) {
|
|
Mode["GAME_MODE"] = "GameMode";
|
|
Mode["STORY_MODE"] = "StoryMode";
|
|
Mode["PAUSE_MODE"] = "PauseMode";
|
|
})(Mode || (Mode = {}));
|
|
class SceneWithStory extends Scene_1.default {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.currentMode = Mode.GAME_MODE;
|
|
}
|
|
startScene() {
|
|
// The code below are for testing only. Please comment them when submit
|
|
this.primary = this.addUILayer("primary");
|
|
const center = this.viewport.getCenter();
|
|
const loadStory = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y), text: "LoadStory" });
|
|
loadStory.size.set(200, 50);
|
|
loadStory.borderWidth = 2;
|
|
loadStory.borderColor = Color_1.default.WHITE;
|
|
loadStory.backgroundColor = Color_1.default.TRANSPARENT;
|
|
loadStory.onClickEventId = "loadStory";
|
|
this.storyLayer = this.addUILayer("story");
|
|
this.storyLayer.disable();
|
|
this.receiver.subscribe("loadStory");
|
|
}
|
|
/**
|
|
* This function load a story JSON from storyPath and auto display it to storyLayer
|
|
* @param storyPath The path to the story JSON
|
|
*/
|
|
storyLoader(storyPath) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// I may want to load multiple stories in a single scene, but this
|
|
// Layer with name story already exists
|
|
// so can i detect whether this layer exists?
|
|
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) => {
|
|
// this.load.audio(bgm.key, bgm.path);
|
|
// console.log("audio:", bgm.key, "path:", bgm.path);
|
|
// this.load.loadResourcesFromQueue(() => {
|
|
// console.log("finished loading audio");
|
|
// this.emitter.fireEvent(GameEventType.PLAY_SOUND, { key: bgm.key, loop: false, holdReference: true });
|
|
// });
|
|
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(this.viewport.getHalfSize().x, this.viewport.getHalfSize().y + 240), text: "" });
|
|
this.storytextLabel.textColor = Color_1.default.WHITE;
|
|
this.storytextLabel.font = "PixelSimple";
|
|
this.storytextLabel.fontSize = 20;
|
|
this.storytextLabel.setHAlign(Label_1.HAlign.LEFT);
|
|
this.storyProgress = -1;
|
|
this.storySprites = new Array;
|
|
this.currentMode = Mode.STORY_MODE;
|
|
this.updateStory();
|
|
});
|
|
}
|
|
/**
|
|
* @returns True if the story has next sentence False otherwise
|
|
*/
|
|
hasNextStory() {
|
|
return this.currentMode === Mode.STORY_MODE && this.storyProgress + 1 < this.story.texts.length;
|
|
}
|
|
/**
|
|
* Go to the next sentence of current story if there is one or clear the storyLayer and exit storyMode
|
|
*/
|
|
updateStory() {
|
|
if (this.currentMode === Mode.STORY_MODE && 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":
|
|
// this.load.image(action.key, action.path);
|
|
// this.load.loadResourcesFromQueue(() => {
|
|
// 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);
|
|
// });
|
|
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 "loadAnimatedSprite":
|
|
// this.load.spritesheet(action.key, action.path);
|
|
// this.load.loadResourcesFromQueue(() => {
|
|
// tmp = this.add.animatedSprite(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.currentMode = Mode.GAME_MODE;
|
|
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;
|
|
}
|
|
}
|
|
updateScene(deltaT) {
|
|
while (this.receiver.hasNextEvent()) {
|
|
let event = this.receiver.getNextEvent();
|
|
// Testing code
|
|
if (event.type === "loadStory" && this.currentMode === Mode.GAME_MODE) {
|
|
this.storyLoader("shattered_sword_assets/jsons/story.json");
|
|
}
|
|
}
|
|
// Testing code
|
|
if (Input_1.default.isMouseJustPressed() && this.currentMode === Mode.STORY_MODE) {
|
|
this.updateStory();
|
|
}
|
|
}
|
|
}
|
|
exports.default = SceneWithStory;
|
|
|
|
},{"../../Wolfie2D/DataTypes/Vec2":26,"../../Wolfie2D/Events/GameEventType":32,"../../Wolfie2D/Input/Input":34,"../../Wolfie2D/Nodes/UIElements/Label":55,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":58,"../../Wolfie2D/Scene/Scene":92,"../../Wolfie2D/Utils/Color":101}],131:[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");
|
|
class Tutorial extends GameLevel_1.default {
|
|
loadScene() {
|
|
super.loadScene();
|
|
// Load resources
|
|
// this.load.tilemap("forest1", "shattered_sword_assets/tilemaps/Tutorial.json");
|
|
// let map = localStorage.getItem("map");
|
|
this.randomSeed = Math.floor(Math.random() * 10000000000);
|
|
let rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/forest_template.json", this.randomSeed);
|
|
this.map = rmg.getMap();
|
|
this.load.tilemapFromObject("forest1", this.map);
|
|
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 music here
|
|
}
|
|
startScene() {
|
|
// Add the level 1 tilemap
|
|
this.add.tilemap("forest1", new Vec2_1.default(2, 2));
|
|
this.viewport.setBounds(0, 0, this.map.width * 32, this.map.height * 32);
|
|
this.viewport.follow(this.player);
|
|
this.playerSpawn = new Vec2_1.default(5 * 32, 9 * 32);
|
|
// Do generic setup for a GameLevel
|
|
super.startScene();
|
|
}
|
|
updateScene(deltaT) {
|
|
super.updateScene(deltaT);
|
|
}
|
|
}
|
|
exports.default = Tutorial;
|
|
|
|
},{"../../Wolfie2D/DataTypes/Vec2":26,"../Tools/RandomMapGenerator":132,"./GameLevel":127}],132:[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();
|
|
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);
|
|
this.rooms.push(room);
|
|
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.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 this.player;
|
|
}
|
|
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.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.weight) == 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) {
|
|
return false;
|
|
}
|
|
let room = this.copyRoom(nextRoom, nextPosition.x, nextPosition.y);
|
|
this.rooms.push(room);
|
|
this.roomPlaced += 1;
|
|
if (this.hasExit && this.gen.range() <= 0.1) {
|
|
return false;
|
|
}
|
|
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;
|
|
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 this.enemies) {
|
|
enemy.position.x -= this.minX;
|
|
enemy.position.y -= this.minY;
|
|
this.enemies.push(enemy);
|
|
}
|
|
}
|
|
this.player.x -= this.minX;
|
|
this.player.y -= this.minY;
|
|
}
|
|
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;
|
|
this.player.y = sprite.y;
|
|
}
|
|
else {
|
|
if (this.gen.random() <= sprite.possibility) {
|
|
let tmp = new Enemy();
|
|
tmp.type = sprite.type;
|
|
tmp.position = new Vec2_1.default(posX + sprite.x, posY + sprite.y);
|
|
room.enemies.push(tmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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":24,"../../Wolfie2D/DataTypes/Vec2":26,"random-seed":2}],133:[function(require,module,exports){
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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 = 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 = exports.Statuses || (exports.Statuses = {}));
|
|
|
|
},{}]},{},[107])
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvanNvbi1zdHJpbmdpZnktc2FmZS9zdHJpbmdpZnkuanMiLCJub2RlX21vZHVsZXMvcmFuZG9tLXNlZWQvaW5kZXguanMiLCJzcmMvV29sZmllMkQvQUkvQUlNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL0FJL0dvYXBBY3Rpb25QbGFubmVyLnRzIiwic3JjL1dvbGZpZTJEL0FJL1N0YXRlTWFjaGluZUFJLnRzIiwic3JjL1dvbGZpZTJEL0FJL1N0YXRlTWFjaGluZUdvYXBBSS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvRnVuY3Rpb25zL051bGxGdW5jLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9HcmFwaHMvRWRnZU5vZGUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL0dyYXBocy9HcmFwaC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvR3JhcGhzL1Bvc2l0aW9uR3JhcGgudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL0ludGVyZmFjZXMvUmVnaW9uLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9NYXAudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL01hdDR4NC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvUGh5c2ljcy9BcmVhQ29sbGlzaW9uLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9QaHlzaWNzL0hpdC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvUXVldWUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1JlbmRlcmluZy9XZWJHTFByb2dyYW1UeXBlLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQi50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvU2hhcGVzL0NpcmNsZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvU2hhcGVzL1NoYXBlLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGFjay50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvU3RhdGUvU3RhdGUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1N0YXRlL1N0YXRlTWFjaGluZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlc2V0LnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyLnRzIiwic3JjL1dvbGZpZTJEL0RlYnVnL0RlYnVnLnRzIiwic3JjL1dvbGZpZTJEL0RlYnVnL1N0YXRzLnRzIiwic3JjL1dvbGZpZTJEL0V2ZW50cy9FbWl0dGVyLnRzIiwic3JjL1dvbGZpZTJEL0V2ZW50cy9FdmVudFF1ZXVlLnRzIiwic3JjL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnQudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGUudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL1JlY2VpdmVyLnRzIiwic3JjL1dvbGZpZTJEL0lucHV0L0lucHV0LnRzIiwic3JjL1dvbGZpZTJEL0lucHV0L0lucHV0SGFuZGxlci50cyIsInNyYy9Xb2xmaWUyRC9Mb29wL0Vudmlyb25tZW50SW5pdGlhbGl6ZXIudHMiLCJzcmMvV29sZmllMkQvTG9vcC9GaXhlZFVwZGF0ZUdhbWVMb29wLnRzIiwic3JjL1dvbGZpZTJEL0xvb3AvR2FtZS50cyIsInNyYy9Xb2xmaWUyRC9Mb29wL0dhbWVMb29wLnRzIiwic3JjL1dvbGZpZTJEL0xvb3AvR2FtZU9wdGlvbnMudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvQ2FudmFzTm9kZS50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZS50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlcy50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9MaW5lLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL1BhcnRpY2xlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL1BvaW50LnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL1JlY3QudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZS50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZS50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9UaWxlbWFwLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudC50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvbi50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvU2xpZGVyLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVGV4dElucHV0LnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXMudHMiLCJzcmMvV29sZmllMkQvUGF0aGZpbmRpbmcvTmF2aWdhdGlvbk1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUGF0aGZpbmRpbmcvTmF2aWdhdGlvblBhdGgudHMiLCJzcmMvV29sZmllMkQvUGF0aGZpbmRpbmcvTmF2bWVzaC50cyIsInNyYy9Xb2xmaWUyRC9QaHlzaWNzL0Jhc2ljUGh5c2ljc01hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUGh5c2ljcy9QaHlzaWNzTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9QbGF5YmFjay9SZWNvcmRlci50cyIsInNyYy9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyaWVzL1JlZ2lzdHJ5LnRzIiwic3JjL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvU2hhZGVyUmVnaXN0cnkudHMiLCJzcmMvV29sZmllMkQvUmVnaXN0cnkvUmVnaXN0cnlNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9BbmltYXRpb25zL0FuaW1hdGlvbk1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0FuaW1hdGlvbnMvQW5pbWF0aW9uVHlwZXMudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0FuaW1hdGlvbnMvUGFydGljbGVTeXN0ZW1NYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9BbmltYXRpb25zL1R3ZWVuQ29udHJvbGxlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQW5pbWF0aW9ucy9Ud2Vlbk1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmVyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9DYW52YXNSZW5kZXJpbmcvR3JhcGhpY1JlbmRlcmVyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9DYW52YXNSZW5kZXJpbmcvVGlsZW1hcFJlbmRlcmVyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9DYW52YXNSZW5kZXJpbmcvVUlFbGVtZW50UmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1JlbmRlcmluZ01hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1dlYkdMUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGUudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL0xhYmVsU2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvUG9pbnRTaGFkZXJUeXBlLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9RdWFkU2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvUmVjdFNoYWRlclR5cGUudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL1Nwcml0ZVNoYWRlclR5cGUudHMiLCJzcmMvV29sZmllMkQvUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9GYWN0b3JpZXMvQ2FudmFzTm9kZUZhY3RvcnkudHMiLCJzcmMvV29sZmllMkQvU2NlbmUvRmFjdG9yaWVzL0ZhY3RvcnlNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0ZhY3Rvcmllcy9UaWxlbWFwRmFjdG9yeS50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9MYXllci50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9MYXllcnMvUGFyYWxsYXhMYXllci50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9MYXllcnMvVUlMYXllci50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9TY2VuZS50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9TY2VuZU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvU2NlbmUvU2NlbmVPcHRpb25zLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lR3JhcGgvU2NlbmVHcmFwaC50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZUdyYXBoL1NjZW5lR3JhcGhBcnJheS50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZUdyYXBoL1ZpZXdwb3J0LnRzIiwic3JjL1dvbGZpZTJEL1NvdW5kL0F1ZGlvTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9UaW1pbmcvVGltZXIudHMiLCJzcmMvV29sZmllMkQvVGltaW5nL1RpbWVyTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9VdGlscy9Db2xvci50cyIsInNyYy9Xb2xmaWUyRC9VdGlscy9FYXNlRnVuY3Rpb25zLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL0dyYXBoVXRpbHMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvTWF0aFV0aWxzLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL1JlbmRlcmluZ1V0aWxzLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL1N0cmluZ1V0aWxzLnRzIiwic3JjL21haW4udHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL0VuZW15QUkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL0VuZW15U3RhdGVzL0VuZW15U3RhdGUudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL0VuZW15U3RhdGVzL1BhdHJvbC50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvQmF0dGxlTWFuYWdlci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvSW52ZW50b3J5TWFuYWdlci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvaXRlbXMvSXRlbS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9HYW1lU3lzdGVtcy9pdGVtcy9XZWFwb25UeXBlcy9TbGljZS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvV2VhcG9uVHlwZS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUGxheWVyL1BsYXllckNvbnRyb2xsZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJTdGF0ZXMvRmFsbC50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUGxheWVyL1BsYXllclN0YXRlcy9JZGxlLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL0luQWlyLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL0p1bXAudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJTdGF0ZXMvT25Hcm91bmQudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJTdGF0ZXMvUGxheWVyU3RhdGUudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJTdGF0ZXMvV2Fsay50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUmVnaXN0cnkvV2VhcG9uUmVnaXN0cnkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1JlZ2lzdHJ5L1dlYXBvblR5cGVSZWdpc3RyeS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL0dhbWVMZXZlbC50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL0xldmVscy50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL01haW5NZW51LnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvU2NlbmVXaXRoU3RvcnkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9UdXRvcmlhbC50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvVG9vbHMvUmFuZG9tTWFwR2VuZXJhdG9yLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9zd29yZF9lbnVtcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakUsSUFBSSxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUM7Z0JBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hGLElBQUksUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ3BFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEc7YUFDSTtZQUNELEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtnQkFDL0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakUsSUFBSSxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUM7Z0JBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hGLElBQUksUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ3BFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEc7SUFDTCxDQUFDO0lBRU8sUUFBUTtRQUNaLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7UUFDdEMsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLDBCQUFjLENBQUM7UUFDeEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSwwQkFBYyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQzdFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ2pGLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDO1FBQy9DLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO1FBQzdDLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxHQUFHLFlBQVksQ0FBQztRQUNwQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUM7UUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxN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Q0FBQTtJQUNuQywyQ0FBMEIsQ0FBQTtBQUM5QixDQUFDLEVBWlcsYUFBYSxHQUFiLHFCQUFhLEtBQWIscUJBQWEsUUFZeEI7QUFDRCxJQUFZLFdBSVg7QUFKRCxXQUFZLFdBQVc7SUFDbkIsNkNBQThCLENBQUE7SUFDOUIsdURBQXdDLENBQUE7SUFDeEMsdUNBQXdCLENBQUE7QUFDNUIsQ0FBQyxFQUpXLFdBQVcsR0FBWCxtQkFBVyxLQUFYLG1CQUFXLFFBSXRCO0FBRUQsSUFBWSxRQUtYO0FBTEQsV0FBWSxRQUFRO0lBQ2hCLGlDQUFxQixDQUFBO0lBQ3JCLHFDQUF5QixDQUFBO0lBQ3pCLHVDQUEyQixDQUFBO0lBQzNCLGlDQUFxQixDQUFBO0FBQ3pCLENBQUMsRUFMVyxRQUFRLEdBQVIsZ0JBQVEsS0FBUixnQkFBUSxRQUtuQiIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsImV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IHN0cmluZ2lmeVxuZXhwb3J0cy5nZXRTZXJpYWxpemUgPSBzZXJpYWxpemVyXG5cbmZ1bmN0aW9uIHN0cmluZ2lmeShvYmosIHJlcGxhY2VyLCBzcGFjZXMsIGN5Y2xlUmVwbGFjZXIpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgc2VyaWFsaXplcihyZXBsYWNlciwgY3ljbGVSZXBsYWNlciksIHNwYWNlcylcbn1cblxuZnVuY3Rpb24gc2VyaWFsaXplcihyZXBsYWNlciwgY3ljbGVSZXBsYWNlcikge1xuICB2YXIgc3RhY2sgPSBbXSwga2V5cyA9IFtdXG5cbiAgaWYgKGN5Y2xlUmVwbGFjZXIgPT0gbnVsbCkgY3ljbGVSZXBsYWNlciA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICBpZiAoc3RhY2tbMF0gPT09IHZhbHVlKSByZXR1cm4gXCJbQ2lyY3VsYXIgfl1cIlxuICAgIHJldHVybiBcIltDaXJjdWxhciB+LlwiICsga2V5cy5zbGljZSgwLCBzdGFjay5pbmRleE9mKHZhbHVlKSkuam9pbihcIi5cIikgKyBcIl1cIlxuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICBpZiAoc3RhY2subGVuZ3RoID4gMCkge1xuICAgICAgdmFyIHRoaXNQb3MgPSBzdGFjay5pbmRleE9mKHRoaXMpXG4gICAgICB+dGhpc1BvcyA/IHN0YWNrLnNwbGljZSh0aGlzUG9zICsgMSkgOiBzdGFjay5wdXNoKHRoaXMpXG4gICAgICB+dGhpc1BvcyA/IGtleXMuc3BsaWNlKHRoaXNQb3MsIEluZmluaXR5LCBrZXkpIDoga2V5cy5wdXNoKGtleSlcbiAgICAgIGlmICh+c3RhY2suaW5kZXhPZih2YWx1ZSkpIHZhbHVlID0gY3ljbGVSZXBsYWNlci5jYWxsKHRoaXMsIGtleSwgdmFsdWUpXG4gICAgfVxuICAgIGVsc2Ugc3RhY2sucHVzaCh2YWx1ZSlcblxuICAgIHJldHVybiByZXBsYWNlciA9PSBudWxsID8gdmFsdWUgOiByZXBsYWNlci5jYWxsKHRoaXMsIGtleSwgdmFsdWUpXG4gIH1cbn1cbiIsIi8qXG4gKiByYW5kb20tc2VlZFxuICogaHR0cHM6Ly9naXRodWIuY29tL3NrcmF0Y2hkb3QvcmFuZG9tLXNlZWRcbiAqXG4gKiBUaGlzIGNvZGUgd2FzIG9yaWdpbmFsbHkgd3JpdHRlbiBieSBTdGV2ZSBHaWJzb24gYW5kIGNhbiBiZSBmb3VuZCBoZXJlOlxuICpcbiAqIGh0dHBzOi8vd3d3LmdyYy5jb20vb3RnL3VoZXBybmcuaHRtXG4gKlxuICogSXQgd2FzIHNsaWdodGx5IG1vZGlmaWVkIGZvciB1c2UgaW4gbm9kZSwgdG8gcGFzcyBqc2hpbnQsIGFuZCBhIGZldyBhZGRpdGlvbmFsXG4gKiBoZWxwZXIgZnVuY3Rpb25zIHdlcmUgYWRkZWQuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzIHNrcmF0Y2hkb3RcbiAqIER1YWwgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGFuZCB0aGUgb3JpZ2luYWwgR1JDIGNvcHlyaWdodC9saWNlbnNlXG4gKiBpbmNsdWRlZCBiZWxvdy5cbiAqL1xuLypcdD09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblx0XHRcdFx0XHRcdFx0XHRcdEdpYnNvbiBSZXNlYXJjaCBDb3Jwb3JhdGlvblxuXHRcdFx0XHRVSEVQUk5HIC0gVWx0cmEgSGlnaCBFbnRyb3B5IFBzZXVkby1SYW5kb20gTnVtYmVyIEdlbmVyYXRvclxuXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cdExJQ0VOU0UgQU5EIENPUFlSSUdIVDogIFRISVMgQ09ERSBJUyBIRVJFQlkgUkVMRUFTRUQgSU5UTyBUSEUgUFVCTElDIERPTUFJTlxuXHRHaWJzb24gUmVzZWFyY2ggQ29ycG9yYXRpb24gcmVsZWFzZXMgYW5kIGRpc2NsYWltcyBBTEwgUklHSFRTIEFORCBUSVRMRSBJTlxuXHRUSElTIENPREUgT1IgQU5ZIERFUklWQVRJVkVTLiBBbnlvbmUgbWF5IGJlIGZyZWVseSB1c2UgaXQgZm9yIGFueSBwdXJwb3NlLlxuXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cdFRoaXMgaXMgR1JDJ3MgY3J5cHRvZ3JhcGhpY2FsbHkgc3Ryb25nIFBSTkcgKHBzZXVkby1yYW5kb20gbnVtYmVyIGdlbmVyYXRvcilcblx0Zm9yIEphdmFTY3JpcHQuIEl0IGlzIGRyaXZlbiBieSAxNTM2IGJpdHMgb2YgZW50cm9weSwgc3RvcmVkIGluIGFuIGFycmF5IG9mXG5cdDQ4LCAzMi1iaXQgSmF2YVNjcmlwdCB2YXJpYWJsZXMuICBTaW5jZSBtYW55IGFwcGxpY2F0aW9ucyBvZiB0aGlzIGdlbmVyYXRvcixcblx0aW5jbHVkaW5nIG91cnMgd2l0aCB0aGUgXCJPZmYgVGhlIEdyaWRcIiBMYXRpbiBTcXVhcmUgZ2VuZXJhdG9yLCBtYXkgcmVxdWlyZVxuXHR0aGUgZGV0ZXJpbWluaXN0aWMgcmUtZ2VuZXJhdGlvbiBvZiBhIHNlcXVlbmNlIG9mIFBSTnMsIHRoaXMgUFJORydzIGluaXRpYWxcblx0ZW50cm9waWMgc3RhdGUgY2FuIGJlIHJlYWQgYW5kIHdyaXR0ZW4gYXMgYSBzdGF0aWMgd2hvbGUsIGFuZCBpbmNyZW1lbnRhbGx5XG5cdGV2b2x2ZWQgYnkgcG91cmluZyBuZXcgc291cmNlIGVudHJvcHkgaW50byB0aGUgZ2VuZXJhdG9yJ3MgaW50ZXJuYWwgc3RhdGUuXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0RU5ETEVTUyBUSEFOS1MgYXJlIGR1ZSBKb2hhbm5lcyBCYWFnb2UgZm9yIGhpcyBjYXJlZnVsIGRldmVsb3BtZW50IG9mIGhpZ2hseVxuXHRyb2J1c3QgSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbnMgb2YgSlMgUFJOR3MuICBUaGlzIHdvcmsgd2FzIGJhc2VkIHVwb24gaGlzXG5cdEphdmFTY3JpcHQgXCJBbGVhXCIgUFJORyB3aGljaCBpcyBiYXNlZCB1cG9uIHRoZSBleHRyZW1lbHkgcm9idXN0IE11bHRpcGx5LVxuXHRXaXRoLUNhcnJ5IChNV0MpIFBSTkcgaW52ZW50ZWQgYnkgR2VvcmdlIE1hcnNhZ2xpYS4gTVdDIEFsZ29yaXRobSBSZWZlcmVuY2VzOlxuXHRodHRwOi8vd3d3LkdSQy5jb20vb3RnL01hcnNhZ2xpYV9QUk5Hcy5wZGZcblx0aHR0cDovL3d3dy5HUkMuY29tL290Zy9NYXJzYWdsaWFfTVdDX0dlbmVyYXRvcnMucGRmXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0VGhlIHF1YWxpdHkgb2YgdGhpcyBhbGdvcml0aG0ncyBwc2V1ZG8tcmFuZG9tIG51bWJlcnMgaGF2ZSBiZWVuIHZlcmlmaWVkIGJ5XG5cdG11bHRpcGxlIGluZGVwZW5kZW50IHJlc2VhcmNoZXJzLiBJdCBoYW5kaWx5IHBhc3NlcyB0aGUgZmVybWlsYWIuY2ggdGVzdHMgYXNcblx0d2VsbCBhcyB0aGUgXCJkaWVoYXJkXCIgYW5kIFwiZGllaGFyZGVyXCIgdGVzdCBzdWl0ZXMuICBGb3IgaW5kaXZpZHVhbHMgd2lzaGluZ1xuXHR0byBmdXJ0aGVyIHZlcmlmeSB0aGUgcXVhbGl0eSBvZiB0aGlzIGFsZ29yaXRobSdzIHBzZXVkby1yYW5kb20gbnVtYmVycywgYVxuXHQyNTYtbWVnYWJ5dGUgZmlsZSBvZiB0aGlzIGFsZ29yaXRobSdzIG91dHB1dCBtYXkgYmUgZG93bmxvYWRlZCBmcm9tIEdSQy5jb20sXG5cdGFuZCBhIE1pY3Jvc29mdCBXaW5kb3dzIHNjcmlwdGluZyBob3N0IChXU0gpIHZlcnNpb24gb2YgdGhpcyBhbGdvcml0aG0gbWF5IGJlXG5cdGRvd25sb2FkZWQgYW5kIHJ1biBmcm9tIHRoZSBXaW5kb3dzIGNvbW1hbmQgcHJvbXB0IHRvIGdlbmVyYXRlIHVuaXF1ZSBmaWxlc1xuXHRvZiBhbnkgc2l6ZTpcblx0VGhlIEZlcm1pbGFiIFwiRU5UXCIgdGVzdHM6IGh0dHA6Ly9mb3VybWlsYWIuY2gvcmFuZG9tL1xuXHRUaGUgMjU2LW1lZ2FieXRlIHNhbXBsZSBQUk4gZmlsZSBhdCBHUkM6IGh0dHBzOi8vd3d3LkdSQy5jb20vb3RnL3VoZXBybmcuYmluXG5cdFRoZSBXaW5kb3dzIHNjcmlwdGluZyBob3N0IHZlcnNpb246IGh0dHBzOi8vd3d3LkdSQy5jb20vb3RnL3dzaC11aGVwcm5nLmpzXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0UXVhbGlmeWluZyBNV0MgbXVsdGlwbGllcnMgYXJlOiAxODc4ODQsIDY4NjExOCwgODk4MTM0LCAxMTA0Mzc1LCAxMjUwMjA1LFxuXHQxNDYwOTEwIGFuZCAxNzY4ODYzLiAoV2UgdXNlIHRoZSBsYXJnZXN0IG9uZSB0aGF0J3MgPCAyXjIxKVxuXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG4ndXNlIHN0cmljdCc7XG52YXIgc3RyaW5naWZ5ID0gcmVxdWlyZSgnanNvbi1zdHJpbmdpZnktc2FmZScpO1xuXG4vKlx0PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuVGhpcyBpcyBiYXNlZCB1cG9uIEpvaGFubmVzIEJhYWdvZSdzIGNhcmVmdWxseSBkZXNpZ25lZCBhbmQgZWZmaWNpZW50IGhhc2hcbmZ1bmN0aW9uIGZvciB1c2Ugd2l0aCBKYXZhU2NyaXB0LiAgSXQgaGFzIGEgcHJvdmVuIFwiYXZhbGFuY2hlXCIgZWZmZWN0IHN1Y2hcbnRoYXQgZXZlcnkgYml0IG9mIHRoZSBpbnB1dCBhZmZlY3RzIGV2ZXJ5IGJpdCBvZiB0aGUgb3V0cHV0IDUwJSBvZiB0aGUgdGltZSxcbndoaWNoIGlzIGdvb2QuXHRTZWU6IGh0dHA6Ly9iYWFnb2UuY29tL2VuL1JhbmRvbU11c2luZ3MvaGFzaC9hdmFsYW5jaGUueGh0bWxcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiovXG52YXIgTWFzaCA9IGZ1bmN0aW9uICgpIHtcblx0dmFyIG4gPSAweGVmYzgyNDlkO1xuXHR2YXIgbWFzaCA9IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0aWYgKGRhdGEpIHtcblx0XHRcdGRhdGEgPSBkYXRhLnRvU3RyaW5nKCk7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0biArPSBkYXRhLmNoYXJDb2RlQXQoaSk7XG5cdFx0XHRcdHZhciBoID0gMC4wMjUxOTYwMzI4MjQxNjkzOCAqIG47XG5cdFx0XHRcdG4gPSBoID4+PiAwO1xuXHRcdFx0XHRoIC09IG47XG5cdFx0XHRcdGggKj0gbjtcblx0XHRcdFx0biA9IGggPj4+IDA7XG5cdFx0XHRcdGggLT0gbjtcblx0XHRcdFx0biArPSBoICogMHgxMDAwMDAwMDA7IC8vIDJeMzJcblx0XHRcdH1cblx0XHRcdHJldHVybiAobiA+Pj4gMCkgKiAyLjMyODMwNjQzNjUzODY5NjNlLTEwOyAvLyAyXi0zMlxuXHRcdH0gZWxzZSB7XG5cdFx0XHRuID0gMHhlZmM4MjQ5ZDtcblx0XHR9XG5cdH07XG5cdHJldHVybiBtYXNoO1xufTtcblxudmFyIHVoZXBybmcgPSBmdW5jdGlvbiAoc2VlZCkge1xuXHRyZXR1cm4gKGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbyA9IDQ4OyAvLyBzZXQgdGhlICdvcmRlcicgbnVtYmVyIG9mIEVOVFJPUFktaG9sZGluZyAzMi1iaXQgdmFsdWVzXG5cdFx0dmFyIGMgPSAxOyAvLyBpbml0IHRoZSAnY2FycnknIHVzZWQgYnkgdGhlIG11bHRpcGx5LXdpdGgtY2FycnkgKE1XQykgYWxnb3JpdGhtXG5cdFx0dmFyIHAgPSBvOyAvLyBpbml0IHRoZSAncGhhc2UnIChtYXgtMSkgb2YgdGhlIGludGVybWVkaWF0ZSB2YXJpYWJsZSBwb2ludGVyXG5cdFx0dmFyIHMgPSBuZXcgQXJyYXkobyk7IC8vIGRlY2xhcmUgb3VyIGludGVybWVkaWF0ZSB2YXJpYWJsZXMgYXJyYXlcblx0XHR2YXIgaTsgLy8gZ2VuZXJhbCBwdXJwb3NlIGxvY2FsXG5cdFx0dmFyIGo7IC8vIGdlbmVyYWwgcHVycG9zZSBsb2NhbFxuXHRcdHZhciBrID0gMDsgLy8gZ2VuZXJhbCBwdXJwb3NlIGxvY2FsXG5cblx0XHQvLyB3aGVuIG91ciBcInVoZXBybmdcIiBpcyBpbml0aWFsbHkgaW52b2tlZCBvdXIgUFJORyBzdGF0ZSBpcyBpbml0aWFsaXplZCBmcm9tIHRoZVxuXHRcdC8vIGJyb3dzZXIncyBvd24gbG9jYWwgUFJORy4gVGhpcyBpcyBva2F5IHNpbmNlIGFsdGhvdWdoIGl0cyBnZW5lcmF0b3IgbWlnaHQgbm90XG5cdFx0Ly8gYmUgd29uZGVyZnVsLCBpdCdzIHVzZWZ1bCBmb3IgZXN0YWJsaXNoaW5nIGxhcmdlIHN0YXJ0dXAgZW50cm9weSBmb3Igb3VyIHVzYWdlLlxuXHRcdHZhciBtYXNoID0gbmV3IE1hc2goKTsgLy8gZ2V0IGEgcG9pbnRlciB0byBvdXIgaGlnaC1wZXJmb3JtYW5jZSBcIk1hc2hcIiBoYXNoXG5cblx0XHQvLyBmaWxsIHRoZSBhcnJheSB3aXRoIGluaXRpYWwgbWFzaCBoYXNoIHZhbHVlc1xuXHRcdGZvciAoaSA9IDA7IGkgPCBvOyBpKyspIHtcblx0XHRcdHNbaV0gPSBtYXNoKE1hdGgucmFuZG9tKCkpO1xuXHRcdH1cblxuXHRcdC8vIHRoaXMgUFJJVkFURSAoaW50ZXJuYWwgYWNjZXNzIG9ubHkpIGZ1bmN0aW9uIGlzIHRoZSBoZWFydCBvZiB0aGUgbXVsdGlwbHktd2l0aC1jYXJyeVxuXHRcdC8vIChNV0MpIFBSTkcgYWxnb3JpdGhtLiBXaGVuIGNhbGxlZCBpdCByZXR1cm5zIGEgcHNldWRvLXJhbmRvbSBudW1iZXIgaW4gdGhlIGZvcm0gb2YgYVxuXHRcdC8vIDMyLWJpdCBKYXZhU2NyaXB0IGZyYWN0aW9uICgwLjAgdG8gPDEuMCkgaXQgaXMgYSBQUklWQVRFIGZ1bmN0aW9uIHVzZWQgYnkgdGhlIGRlZmF1bHRcblx0XHQvLyBbMC0xXSByZXR1cm4gZnVuY3Rpb24sIGFuZCBieSB0aGUgcmFuZG9tICdzdHJpbmcobiknIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgJ24nXG5cdFx0Ly8gY2hhcmFjdGVycyBmcm9tIDMzIHRvIDEyNi5cblx0XHR2YXIgcmF3cHJuZyA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmICgrK3AgPj0gbykge1xuXHRcdFx0XHRwID0gMDtcblx0XHRcdH1cblx0XHRcdHZhciB0ID0gMTc2ODg2MyAqIHNbcF0gKyBjICogMi4zMjgzMDY0MzY1Mzg2OTYzZS0xMDsgLy8gMl4tMzJcblx0XHRcdHJldHVybiBzW3BdID0gdCAtIChjID0gdCB8IDApO1xuXHRcdH07XG5cblx0XHQvLyB0aGlzIEVYUE9SVEVEIGZ1bmN0aW9uIGlzIHRoZSBkZWZhdWx0IGZ1bmN0aW9uIHJldHVybmVkIGJ5IHRoaXMgbGlicmFyeS5cblx0XHQvLyBUaGUgdmFsdWVzIHJldHVybmVkIGFyZSBpbnRlZ2VycyBpbiB0aGUgcmFuZ2UgZnJvbSAwIHRvIHJhbmdlLTEuIFdlIGZpcnN0XG5cdFx0Ly8gb2J0YWluIHR3byAzMi1iaXQgZnJhY3Rpb25zIChmcm9tIHJhd3BybmcpIHRvIHN5bnRoZXNpemUgYSBzaW5nbGUgaGlnaFxuXHRcdC8vIHJlc29sdXRpb24gNTMtYml0IHBybmcgKDAgdG8gPDEpLCB0aGVuIHdlIG11bHRpcGx5IHRoaXMgYnkgdGhlIGNhbGxlcidzXG5cdFx0Ly8gXCJyYW5nZVwiIHBhcmFtIGFuZCB0YWtlIHRoZSBcImZsb29yXCIgdG8gcmV0dXJuIGEgZXF1YWxseSBwcm9iYWJsZSBpbnRlZ2VyLlxuXHRcdHZhciByYW5kb20gPSBmdW5jdGlvbiAocmFuZ2UpIHtcblx0XHRcdHJldHVybiBNYXRoLmZsb29yKHJhbmdlICogKHJhd3BybmcoKSArIChyYXdwcm5nKCkgKiAweDIwMDAwMCB8IDApICogMS4xMTAyMjMwMjQ2MjUxNTY1ZS0xNikpOyAvLyAyXi01M1xuXHRcdH07XG5cblx0XHQvLyB0aGlzIEVYUE9SVEVEIGZ1bmN0aW9uICdzdHJpbmcobiknIHJldHVybnMgYSBwc2V1ZG8tcmFuZG9tIHN0cmluZyBvZlxuXHRcdC8vICduJyBwcmludGFibGUgY2hhcmFjdGVycyByYW5naW5nIGZyb20gY2hyKDMzKSB0byBjaHIoMTI2KSBpbmNsdXNpdmUuXG5cdFx0cmFuZG9tLnN0cmluZyA9IGZ1bmN0aW9uIChjb3VudCkge1xuXHRcdFx0dmFyIGk7XG5cdFx0XHR2YXIgcyA9ICcnO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcblx0XHRcdFx0cyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDMzICsgcmFuZG9tKDk0KSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcztcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBQUklWQVRFIFwiaGFzaFwiIGZ1bmN0aW9uIGlzIHVzZWQgdG8gZXZvbHZlIHRoZSBnZW5lcmF0b3IncyBpbnRlcm5hbFxuXHRcdC8vIGVudHJvcHkgc3RhdGUuIEl0IGlzIGFsc28gY2FsbGVkIGJ5IHRoZSBFWFBPUlRFRCBhZGRFbnRyb3B5KCkgZnVuY3Rpb25cblx0XHQvLyB3aGljaCBpcyB1c2VkIHRvIHBvdXIgZW50cm9weSBpbnRvIHRoZSBQUk5HLlxuXHRcdHZhciBoYXNoID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG87IGorKykge1xuXHRcdFx0XHRcdHNbal0gLT0gbWFzaChhcmdzW2ldKTtcblx0XHRcdFx0XHRpZiAoc1tqXSA8IDApIHtcblx0XHRcdFx0XHRcdHNbal0gKz0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBcImNsZWFuIHN0cmluZ1wiIGZ1bmN0aW9uIHJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgc3BhY2VzIGFuZCBub24tcHJpbnRpbmdcblx0XHQvLyBjb250cm9sIGNoYXJhY3RlcnMsIGluY2x1ZGluZyBhbnkgZW1iZWRkZWQgY2FycmlhZ2UtcmV0dXJuIChDUikgYW5kIGxpbmUtZmVlZCAoTEYpIGNoYXJhY3RlcnMsXG5cdFx0Ly8gZnJvbSBhbnkgc3RyaW5nIGl0IGlzIGhhbmRlZC4gdGhpcyBpcyBhbHNvIHVzZWQgYnkgdGhlICdoYXNoc3RyaW5nJyBmdW5jdGlvbiAoYmVsb3cpIHRvIGhlbHBcblx0XHQvLyB1c2VycyBhbHdheXMgb2J0YWluIHRoZSBzYW1lIEVGRkVDVElWRSB1aGVwcm5nIHNlZWRpbmcga2V5LlxuXHRcdHJhbmRvbS5jbGVhblN0cmluZyA9IGZ1bmN0aW9uIChpblN0cikge1xuXHRcdFx0aW5TdHIgPSBpblN0ci5yZXBsYWNlKC8oXlxccyopfChcXHMqJCkvZ2ksICcnKTsgLy8gcmVtb3ZlIGFueS9hbGwgbGVhZGluZyBzcGFjZXNcblx0XHRcdGluU3RyID0gaW5TdHIucmVwbGFjZSgvW1xceDAwLVxceDFGXS9naSwgJycpOyAvLyByZW1vdmUgYW55L2FsbCBjb250cm9sIGNoYXJhY3RlcnNcblx0XHRcdGluU3RyID0gaW5TdHIucmVwbGFjZSgvXFxuIC8sICdcXG4nKTsgLy8gcmVtb3ZlIGFueS9hbGwgdHJhaWxpbmcgc3BhY2VzXG5cdFx0XHRyZXR1cm4gaW5TdHI7IC8vIHJldHVybiB0aGUgY2xlYW5lZCB1cCByZXN1bHRcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBcImhhc2ggc3RyaW5nXCIgZnVuY3Rpb24gaGFzaGVzIHRoZSBwcm92aWRlZCBjaGFyYWN0ZXIgc3RyaW5nIGFmdGVyIGZpcnN0IHJlbW92aW5nXG5cdFx0Ly8gYW55IGxlYWRpbmcgb3IgdHJhaWxpbmcgc3BhY2VzIGFuZCBpZ25vcmluZyBhbnkgZW1iZWRkZWQgY2FycmlhZ2UgcmV0dXJucyAoQ1IpIG9yIExpbmUgRmVlZHMgKExGKVxuXHRcdHJhbmRvbS5oYXNoU3RyaW5nID0gZnVuY3Rpb24gKGluU3RyKSB7XG5cdFx0XHRpblN0ciA9IHJhbmRvbS5jbGVhblN0cmluZyhpblN0cik7XG5cdFx0XHRtYXNoKGluU3RyKTsgLy8gdXNlIHRoZSBzdHJpbmcgdG8gZXZvbHZlIHRoZSAnbWFzaCcgc3RhdGVcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBpblN0ci5sZW5ndGg7IGkrKykgeyAvLyBzY2FuIHRocm91Z2ggdGhlIGNoYXJhY3RlcnMgaW4gb3VyIHN0cmluZ1xuXHRcdFx0XHRrID0gaW5TdHIuY2hhckNvZGVBdChpKTsgLy8gZ2V0IHRoZSBjaGFyYWN0ZXIgY29kZSBhdCB0aGUgbG9jYXRpb25cblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG87IGorKykgeyAvL1x0XCJtYXNoXCIgaXQgaW50byB0aGUgVUhFUFJORyBzdGF0ZVxuXHRcdFx0XHRcdHNbal0gLT0gbWFzaChrKTtcblx0XHRcdFx0XHRpZiAoc1tqXSA8IDApIHtcblx0XHRcdFx0XHRcdHNbal0gKz0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIHNlZWQgdGhlIHJhbmRvbSBnZW5lcmF0b3IuXG5cdFx0cmFuZG9tLnNlZWQgPSBmdW5jdGlvbiAoc2VlZCkge1xuXHRcdFx0aWYgKHR5cGVvZiBzZWVkID09PSAndW5kZWZpbmVkJyB8fCBzZWVkID09PSBudWxsKSB7XG5cdFx0XHRcdHNlZWQgPSBNYXRoLnJhbmRvbSgpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHR5cGVvZiBzZWVkICE9PSAnc3RyaW5nJykge1xuXHRcdFx0XHRzZWVkID0gc3RyaW5naWZ5KHNlZWQsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG5cdFx0XHRcdFx0aWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRcdFx0cmV0dXJuICh2YWx1ZSkudG9TdHJpbmcoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdHJhbmRvbS5pbml0U3RhdGUoKTtcblx0XHRcdHJhbmRvbS5oYXNoU3RyaW5nKHNlZWQpO1xuXHRcdH07XG5cblx0XHQvLyB0aGlzIGhhbmR5IGV4cG9ydGVkIGZ1bmN0aW9uIGlzIHVzZWQgdG8gYWRkIGVudHJvcHkgdG8gb3VyIHVoZXBybmcgYXQgYW55IHRpbWVcblx0XHRyYW5kb20uYWRkRW50cm9weSA9IGZ1bmN0aW9uICggLyogYWNjZXB0IHplcm8gb3IgbW9yZSBhcmd1bWVudHMgKi8gKSB7XG5cdFx0XHR2YXIgYXJncyA9IFtdO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRhcmdzLnB1c2goYXJndW1lbnRzW2ldKTtcblx0XHRcdH1cblx0XHRcdGhhc2goKGsrKykgKyAobmV3IERhdGUoKS5nZXRUaW1lKCkpICsgYXJncy5qb2luKCcnKSArIE1hdGgucmFuZG9tKCkpO1xuXHRcdH07XG5cblx0XHQvLyBpZiB3ZSB3YW50IHRvIHByb3ZpZGUgYSBkZXRlcm1pbmlzdGljIHN0YXJ0dXAgY29udGV4dCBmb3Igb3VyIFBSTkcsXG5cdFx0Ly8gYnV0IHdpdGhvdXQgZGlyZWN0bHkgc2V0dGluZyB0aGUgaW50ZXJuYWwgc3RhdGUgdmFyaWFibGVzLCB0aGlzIGFsbG93c1xuXHRcdC8vIHVzIHRvIGluaXRpYWxpemUgdGhlIG1hc2ggaGFzaCBhbmQgUFJORydzIGludGVybmFsIHN0YXRlIGJlZm9yZSBwcm92aWRpbmdcblx0XHQvLyBzb21lIGhhc2hpbmcgaW5wdXRcblx0XHRyYW5kb20uaW5pdFN0YXRlID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0bWFzaCgpOyAvLyBwYXNzIGEgbnVsbCBhcmcgdG8gZm9yY2UgbWFzaCBoYXNoIHRvIGluaXRcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBvOyBpKyspIHtcblx0XHRcdFx0c1tpXSA9IG1hc2goJyAnKTsgLy8gZmlsbCB0aGUgYXJyYXkgd2l0aCBpbml0aWFsIG1hc2ggaGFzaCB2YWx1ZXNcblx0XHRcdH1cblx0XHRcdGMgPSAxOyAvLyBpbml0IG91ciBtdWx0aXBseS13aXRoLWNhcnJ5IGNhcnJ5XG5cdFx0XHRwID0gbzsgLy8gaW5pdCBvdXIgcGhhc2Vcblx0XHR9O1xuXG5cdFx0Ly8gd2UgdXNlIHRoaXMgKG9wdGlvbmFsKSBleHBvcnRlZCBmdW5jdGlvbiB0byBzaWduYWwgdGhlIEphdmFTY3JpcHQgaW50ZXJwcmV0ZXJcblx0XHQvLyB0aGF0IHdlJ3JlIGZpbmlzaGVkIHVzaW5nIHRoZSBcIk1hc2hcIiBoYXNoIGZ1bmN0aW9uIHNvIHRoYXQgaXQgY2FuIGZyZWUgdXAgdGhlXG5cdFx0Ly8gbG9jYWwgXCJpbnN0YW5jZSB2YXJpYWJsZXNcIiBpcyB3aWxsIGhhdmUgYmVlbiBtYWludGFpbmluZy4gIEl0J3Mgbm90IHN0cmljdGx5XG5cdFx0Ly8gbmVjZXNzYXJ5LCBvZiBjb3Vyc2UsIGJ1dCBpdCdzIGdvb2QgSmF2YVNjcmlwdCBjaXRpemVuc2hpcC5cblx0XHRyYW5kb20uZG9uZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdG1hc2ggPSBudWxsO1xuXHRcdH07XG5cblx0XHQvLyBpZiB3ZSBjYWxsZWQgXCJ1aGVwcm5nXCIgd2l0aCBhIHNlZWQgdmFsdWUsIHRoZW4gZXhlY3V0ZSByYW5kb20uc2VlZCgpIGJlZm9yZSByZXR1cm5pbmdcblx0XHRpZiAodHlwZW9mIHNlZWQgIT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyYW5kb20uc2VlZChzZWVkKTtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm5zIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiAwIChpbmNsdXNpdmUpIGFuZCByYW5nZSAoZXhjbHVzaXZlKVxuXHRcdHJhbmRvbS5yYW5nZSA9IGZ1bmN0aW9uIChyYW5nZSkge1xuXHRcdFx0cmV0dXJuIHJhbmRvbShyYW5nZSk7XG5cdFx0fTtcblxuXHRcdC8vIFJldHVybnMgYSByYW5kb20gZmxvYXQgYmV0d2VlbiAwIChpbmNsdXNpdmUpIGFuZCAxIChleGNsdXNpdmUpXG5cdFx0cmFuZG9tLnJhbmRvbSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiByYW5kb20oTnVtYmVyLk1BWF9WQUxVRSAtIDEpIC8gTnVtYmVyLk1BWF9WQUxVRTtcblx0XHR9O1xuXG5cdFx0Ly8gUmV0dXJucyBhIHJhbmRvbSBmbG9hdCBiZXR3ZWVuIG1pbiAoaW5jbHVzaXZlKSBhbmQgbWF4IChleGNsdXNpdmUpXG5cdFx0cmFuZG9tLmZsb2F0QmV0d2VlbiA9IGZ1bmN0aW9uIChtaW4sIG1heCkge1xuXHRcdFx0cmV0dXJuIHJhbmRvbS5yYW5kb20oKSAqIChtYXggLSBtaW4pICsgbWluO1xuXHRcdH07XG5cblx0XHQvLyBSZXR1cm5zIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiBtaW4gKGluY2x1c2l2ZSkgYW5kIG1heCAoaW5jbHVzaXZlKVxuXHRcdHJhbmRvbS5pbnRCZXR3ZWVuID0gZnVuY3Rpb24gKG1pbiwgbWF4KSB7XG5cdFx0XHRyZXR1cm4gTWF0aC5mbG9vcihyYW5kb20ucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpICsgbWluO1xuXHRcdH07XG5cblx0XHQvLyB3aGVuIG91ciBtYWluIG91dGVyIFwidWhlcHJuZ1wiIGZ1bmN0aW9uIGlzIGNhbGxlZCwgYWZ0ZXIgc2V0dGluZyB1cCBvdXJcblx0XHQvLyBpbml0aWFsIHZhcmlhYmxlcyBhbmQgZW50cm9waWMgc3RhdGUsIHdlIHJldHVybiBhbiBcImluc3RhbmNlIHBvaW50ZXJcIlxuXHRcdC8vIHRvIHRoZSBpbnRlcm5hbCBhbm9ueW1vdXMgZnVuY3Rpb24gd2hpY2ggY2FuIHRoZW4gYmUgdXNlZCB0byBhY2Nlc3Ncblx0XHQvLyB0aGUgdWhlcHJuZydzIHZhcmlvdXMgZXhwb3J0ZWQgZnVuY3Rpb25zLiAgQXMgd2l0aCB0aGUgXCIuZG9uZVwiIGZ1bmN0aW9uXG5cdFx0Ly8gYWJvdmUsIHdlIHNob3VsZCBzZXQgdGhlIHJldHVybmVkIHZhbHVlIHRvICdudWxsJyBvbmNlIHdlJ3JlIGZpbmlzaGVkXG5cdFx0Ly8gdXNpbmcgYW55IG9mIHRoZXNlIGZ1bmN0aW9ucy5cblx0XHRyZXR1cm4gcmFuZG9tO1xuXHR9KCkpO1xufTtcblxuLy8gTW9kaWZpY2F0aW9uIGZvciB1c2UgaW4gbm9kZTpcbnVoZXBybmcuY3JlYXRlID0gZnVuY3Rpb24gKHNlZWQpIHtcblx0cmV0dXJuIG5ldyB1aGVwcm5nKHNlZWQpO1xufTtcbm1vZHVsZS5leHBvcnRzID0gdWhlcHJuZztcbiIsImltcG9ydCBBY3RvciBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvQWN0b3JcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgQUkgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FJXCI7XG5pbXBvcnQgR29hcEFJIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9Hb2FwQUlcIlxuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuXG4vKipcbiAqIEEgbWFuYWdlciBjbGFzcyBmb3IgYWxsIG9mIHRoZSBBSSBpbiBhIHNjZW5lLlxuICogS2VlcHMgYSBsaXN0IG9mIHJlZ2lzdGVyZWQgYWN0b3JzIGFuZCBoYW5kbGVzIEFJIGdlbmVyYXRpb24gZm9yIGFjdG9ycy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQUlNYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cdC8qKiBUaGUgYXJyYXkgb2YgcmVnaXN0ZXJlZCBhY3RvcnMgKi9cblx0YWN0b3JzOiBBcnJheTxBY3Rvcj47XG5cdC8qKiBNYXBzIEFJIG5hbWVzIHRvIHRoZWlyIGNvbnN0cnVjdG9ycyAqL1xuXHRyZWdpc3RlcmVkQUk6IE1hcDxBSUNvbnN0cnVjdG9yPjtcblxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMuYWN0b3JzID0gbmV3IEFycmF5KCk7XG5cdFx0dGhpcy5yZWdpc3RlcmVkQUkgPSBuZXcgTWFwKCk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGFuIGFjdG9yIHdpdGggdGhlIEFJTWFuYWdlclxuXHQgKiBAcGFyYW0gYWN0b3IgVGhlIGFjdG9yIHRvIHJlZ2lzdGVyXG5cdCAqL1xuXHRyZWdpc3RlckFjdG9yKGFjdG9yOiBBY3Rvcik6IHZvaWQge1xuXHRcdHRoaXMuYWN0b3JzLnB1c2goYWN0b3IpO1xuXHR9XG5cblx0cmVtb3ZlQWN0b3IoYWN0b3I6IEFjdG9yKTogdm9pZCB7XG5cdFx0bGV0IGluZGV4ID0gdGhpcy5hY3RvcnMuaW5kZXhPZihhY3Rvcik7XG5cblx0XHRpZihpbmRleCAhPT0gLTEpe1xuXHRcdFx0dGhpcy5hY3RvcnMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGFuIEFJIHdpdGggdGhlIEFJTWFuYWdlciBmb3IgdXNlIGxhdGVyIG9uXG5cdCAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBBSSB0byByZWdpc3RlclxuXHQgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBmb3IgdGhlIEFJXG5cdCAqL1xuXHRyZWdpc3RlckFJKG5hbWU6IHN0cmluZywgY29uc3RyOiBuZXcgPFQgZXh0ZW5kcyBBSSB8IEdvYXBBST4oKSA9PiBUICk6IHZvaWQge1xuXHRcdHRoaXMucmVnaXN0ZXJlZEFJLmFkZChuYW1lLCBjb25zdHIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdlbmVyYXRlcyBhbiBBSSBpbnN0YW5jZSBmcm9tIGl0cyBuYW1lXG5cdCAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBBSSB0byBhZGRcblx0ICogQHJldHVybnMgQSBuZXcgQUkgaW5zdGFuY2Vcblx0ICovXG5cdGdlbmVyYXRlQUkobmFtZTogc3RyaW5nKTogQUkgfCBHb2FwQUkge1xuXHRcdGlmKHRoaXMucmVnaXN0ZXJlZEFJLmhhcyhuYW1lKSl7XG5cdFx0XHRyZXR1cm4gbmV3ICh0aGlzLnJlZ2lzdGVyZWRBSS5nZXQobmFtZSkpKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRocm93IGBDYW5ub3QgY3JlYXRlIEFJIHdpdGggbmFtZSAke25hbWV9LCBubyBBSSB3aXRoIHRoYXQgbmFtZSBpcyByZWdpc3RlcmVkYDtcblx0XHR9XG5cdH1cblxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHQvLyBSdW4gdGhlIGFpIGZvciBldmVyeSBhY3RpdmUgYWN0b3Jcblx0XHR0aGlzLmFjdG9ycy5mb3JFYWNoKGFjdG9yID0+IHsgaWYoYWN0b3IuYWlBY3RpdmUpIGFjdG9yLmFpLnVwZGF0ZShkZWx0YVQpIH0pO1xuXHR9XG59XG5cbnR5cGUgQUlDb25zdHJ1Y3RvciA9IG5ldyA8VCBleHRlbmRzIEFJPigpID0+IFQ7IiwiaW1wb3J0IEdyYXBoIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoXCI7XG5pbXBvcnQgR29hcEFjdGlvbiBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvR29hcEFjdGlvblwiO1xuaW1wb3J0IEdvYXBBSSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvR29hcEFJXCI7XG5pbXBvcnQgUXVldWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9RdWV1ZVwiO1xuaW1wb3J0IFN0YWNrIGZyb20gXCIuLi9EYXRhVHlwZXMvU3RhY2tcIjtcbmltcG9ydCBHcmFwaFV0aWxzIGZyb20gXCIuLi9VdGlscy9HcmFwaFV0aWxzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdvYXBBY3Rpb25QbGFubmVyIHtcbiAgICBtYXBwaW5nOiBNYXA8bnVtYmVyLEdvYXBBY3Rpb24gfCBzdHJpbmc+O1xuICAgIGdyYXBoOiBHcmFwaDtcbiAgICBwYXRoOiBBcnJheTxudW1iZXI+O1xuXG4gICAgcGxhbihnb2FsOiBzdHJpbmcsIHBvc3NpYmxlQWN0aW9uczogQXJyYXk8R29hcEFjdGlvbj4sIGN1cnJlbnRTdGF0dXM6IEFycmF5PHN0cmluZz4sIGFjdG9yOiBHb2FwQUkpOiBTdGFjazxHb2FwQWN0aW9uPiB7XG4gICAgICAgIHRoaXMuZ3JhcGggPSBuZXcgR3JhcGgodHJ1ZSk7XG4gICAgICAgIHRoaXMubWFwcGluZyA9IG5ldyBNYXAoKTtcblxuICAgICAgICAvLzAgaXMgb3VyIHJvb3RcbiAgICAgICAgdGhpcy5ncmFwaC5hZGROb2RlKCk7XG4gICAgICAgIHRoaXMubWFwcGluZy5zZXQoMCxcIlN0YXJ0XCIpO1xuICAgICAgICAvLzEgaXMgdGhlIGdvYWxcbiAgICAgICAgdGhpcy5ncmFwaC5hZGROb2RlKCk7XG4gICAgICAgIHRoaXMubWFwcGluZy5zZXQoMSxcIkdvYWxcIik7XG4gICAgICAgIHRoaXMuZ3JhcGguYWRkRWRnZSgxLDEsTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZKTtcblxuICAgICAgICAvL0J1aWxkIHRyZWUgZnJvbSAwIHRvIDFcbiAgICAgICAgdGhpcy5idWlsZFRyZWUoMCwgZ29hbCwgcG9zc2libGVBY3Rpb25zLCBjdXJyZW50U3RhdHVzKTtcblxuICAgICAgICAvL1J1biBkamlrc3RyYSB0byBmaW5kIHNob3J0ZXN0IHBhdGhcbiAgICAgICAgdGhpcy5wYXRoID0gR3JhcGhVdGlscy5kamlrc3RyYSh0aGlzLmdyYXBoLCAwKTtcblxuICAgICAgICAvL1B1c2ggYWxsIGVsZW1lbnRzIG9mIHRoZSBwbGFuXG4gICAgICAgIGxldCBwbGFuID0gbmV3IFN0YWNrPEdvYXBBY3Rpb24+KCk7XG5cdFx0XG5cdFx0bGV0IGkgPSAxO1xuXHRcdHdoaWxlKHRoaXMucGF0aFtpXSAhPT0gLTEpe1xuICAgICAgICAgICAgaWYgKHRoaXMucGF0aFtpXSAhPT0gMCl7XG5cdFx0XHQgICAgcGxhbi5wdXNoKDxHb2FwQWN0aW9uPnRoaXMubWFwcGluZy5nZXQodGhpcy5wYXRoW2ldKSk7XG4gICAgICAgICAgICB9XG5cdFx0XHRpID0gdGhpcy5wYXRoW2ldO1xuXHRcdH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBwbGFuO1xuICAgIH1cblxuICAgIGJ1aWxkVHJlZShyb290OiBudW1iZXIsIGdvYWw6c3RyaW5nLCBwb3NzaWJsZUFjdGlvbnM6IEFycmF5PEdvYXBBY3Rpb24+LCBjdXJyZW50U3RhdHVzOiBBcnJheTxzdHJpbmc+KTogdm9pZCB7XG4gICAgICAgIC8vRm9yIGVhY2ggcG9zc2libGUgYWN0aW9uIFxuICAgICAgICBwb3NzaWJsZUFjdGlvbnMuZm9yRWFjaChhY3Rpb24gPT4ge1xuICAgICAgICAgICAgLy9DYW4gaXQgYmUgcGVyZm9ybWVkP1xuICAgICAgICAgICAgaWYgKGFjdGlvbi5jaGVja1ByZWNvbmRpdGlvbnMoY3VycmVudFN0YXR1cykpe1xuICAgICAgICAgICAgICAgIC8vVGhpcyBhY3Rpb24gY2FuIGJlIHBlcmZvcm1lZFxuICAgICAgICAgICAgICAgIC8vQWRkIGVmZmVjdHMgdG8gY3VycmVudFN0YXR1c1xuICAgICAgICAgICAgICAgIGxldCBuZXdTdGF0dXMgPSBbLi4uY3VycmVudFN0YXR1c107XG4gICAgICAgICAgICAgICAgbmV3U3RhdHVzLnB1c2goLi4uYWN0aW9uLmVmZmVjdHMpO1xuXG4gICAgICAgICAgICAgICAgLy9DaGVjayBpZiB0aGUgbmV3IG5vZGUgaXMgdGhlIGdvYWxcbiAgICAgICAgICAgICAgICBpZiAobmV3U3RhdHVzLmluY2x1ZGVzKGdvYWwpKXtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG5ld05vZGUgPSB0aGlzLmdyYXBoLmFkZE5vZGUoKSAtIDE7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWFwcGluZy5zZXQobmV3Tm9kZSwgYWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ncmFwaC5hZGRFZGdlKHJvb3QsIG5ld05vZGUsIGFjdGlvbi5jb3N0KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ncmFwaC5hZGRFZGdlKG5ld05vZGUsIDEsIDApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy9BZGQgbm9kZSBhbmQgZWRnZSBmcm9tIHJvb3RcbiAgICAgICAgICAgICAgICBsZXQgbmV3Tm9kZSA9IHRoaXMuZ3JhcGguYWRkTm9kZSgpIC0gMTtcbiAgICAgICAgICAgICAgICB0aGlzLm1hcHBpbmcuc2V0KG5ld05vZGUsIGFjdGlvbik7XG4gICAgICAgICAgICAgICAgdGhpcy5ncmFwaC5hZGRFZGdlKHJvb3QsIG5ld05vZGUsIGFjdGlvbi5jb3N0KTtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAvL1JlY3Vyc2l2ZSBjYWxsXG4gICAgICAgICAgICAgICAgbGV0IG5ld0FjdGlvbnMgPSBwb3NzaWJsZUFjdGlvbnMuZmlsdGVyKGFjdCA9PiBhY3QgIT09IGFjdGlvbilcbiAgICAgICAgICAgICAgICB0aGlzLmJ1aWxkVHJlZShuZXdOb2RlLCBnb2FsLCBuZXdBY3Rpb25zLCBhY3Rpb24uZWZmZWN0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn0iLCJpbXBvcnQgQUkgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FJXCI7XG5pbXBvcnQgU3RhdGVNYWNoaW5lIGZyb20gXCIuLi9EYXRhVHlwZXMvU3RhdGUvU3RhdGVNYWNoaW5lXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5cbi8qKlxuICogQSB2ZXJzaW9uIG9mIGEgQHJlZmVyZW5jZVtTdGF0ZU1hY2hpbmVdIHRoYXQgaXMgY29uZmlndXJlZCB0byB3b3JrIGFzIGFuIEFJIGNvbnRyb2xsZXIgZm9yIGEgQHJlZmVyZW5jZVtHYW1lTm9kZV1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3RhdGVNYWNoaW5lQUkgZXh0ZW5kcyBTdGF0ZU1hY2hpbmUgaW1wbGVtZW50cyBBSSB7XG5cdC8qKlx0VGhlIEdhbWVOb2RlIHRoYXQgdXNlcyB0aGlzIFN0YXRlTWFjaGluZSBmb3IgaXRzIEFJICovXG5cdHByb3RlY3RlZCBvd25lcjogR2FtZU5vZGU7XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGluaXRpYWxpemVBSShvd25lcjogR2FtZU5vZGUsIGNvbmZpZzogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge31cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0ZGVzdHJveSgpe1xuXHRcdC8vIEdldCByaWQgb2Ygb3VyIHJlZmVyZW5jZSB0byB0aGUgb3duZXJcblx0XHRkZWxldGUgdGhpcy5vd25lcjtcblx0XHR0aGlzLnJlY2VpdmVyLmRlc3Ryb3koKTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRhY3RpdmF0ZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxufSIsImltcG9ydCBHb2FwQWN0aW9uIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9Hb2FwQWN0aW9uXCI7XG5pbXBvcnQgR29hcEFJIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9Hb2FwQUlcIjtcbmltcG9ydCBRdWV1ZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1F1ZXVlXCI7XG5pbXBvcnQgU3RhY2sgZnJvbSBcIi4uL0RhdGFUeXBlcy9TdGFja1wiO1xuaW1wb3J0IFN0YXRlTWFjaGluZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1N0YXRlL1N0YXRlTWFjaGluZVwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IEdvYXBBY3Rpb25QbGFubmVyIGZyb20gXCIuL0dvYXBBY3Rpb25QbGFubmVyXCI7XG5cbi8qKlxuICogQSB2ZXJzaW9uIG9mIGEgQHJlZmVyZW5jZVtTdGF0ZU1hY2hpbmVdIHRoYXQgaXMgY29uZmlndXJlZCB0byB3b3JrIGFzIGFuIEFJIGNvbnRyb2xsZXIgZm9yIGEgQHJlZmVyZW5jZVtHYW1lTm9kZV1cbiAqL1xuIGV4cG9ydCBkZWZhdWx0IGNsYXNzIFN0YXRlTWFjaGluZUdvYXBBSSBleHRlbmRzIFN0YXRlTWFjaGluZSBpbXBsZW1lbnRzIEdvYXBBSSB7XG5cdC8qKlx0VGhlIEdhbWVOb2RlIHRoYXQgdXNlcyB0aGlzIFN0YXRlTWFjaGluZSBmb3IgaXRzIEFJICovXG5cdHByb3RlY3RlZCBvd25lcjogR2FtZU5vZGU7XG5cblx0Z29hbDogc3RyaW5nO1xuXG4gICAgY3VycmVudFN0YXR1czogQXJyYXk8c3RyaW5nPjtcblxuICAgIHBvc3NpYmxlQWN0aW9uczogQXJyYXk8R29hcEFjdGlvbj47XG5cbiAgICBwbGFuOiBTdGFjazxHb2FwQWN0aW9uPjtcbiAgICBcbiAgICBwbGFubmVyOiBHb2FwQWN0aW9uUGxhbm5lcjtcblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0aW5pdGlhbGl6ZUFJKG93bmVyOiBHYW1lTm9kZSwgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRkZXN0cm95KCl7XG5cdFx0Ly8gR2V0IHJpZCBvZiBvdXIgcmVmZXJlbmNlIHRvIHRoZSBvd25lclxuXHRcdGRlbGV0ZSB0aGlzLm93bmVyO1xuXHRcdHRoaXMucmVjZWl2ZXIuZGVzdHJveSgpO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGFjdGl2YXRlKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHt9XG5cblx0Y2hhbmdlR29hbChnb2FsOiBzdHJpbmcpOiB2b2lkIHt9XG59IiwiLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBBIHBsYWNlaG9sZGVyIGZ1bmN0aW9uIGZvciBObyBPcGVyYXRpb24uIERvZXMgbm90aGluZ1xuICovXG5jb25zdCBOdWxsRnVuYyA9ICgpID0+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+IHtcblx0XHRpZiAoSW5wdXQua2V5c0Rpc2FibGVkKSByZXR1cm4gW107XG5cblx0XHRsZXQga2V5cyA9IEFycmF5PHN0cmluZz4oKTtcblx0XHRJbnB1dC5rZXlKdXN0UHJlc3NlZC5mb3JFYWNoKGtleSA9PiB7XG5cdFx0XHRpZiAoSW5wdXQua2V5SnVzdFByZXNzZWQuZ2V0KGtleSkpIHtcblx0XHRcdFx0a2V5cy5wdXNoKGtleSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0cmV0dXJuIGtleXM7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCBhIGtleSBpcyBiZWluZyBwcmVzc2VkLlxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXlcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUga2V5IGlzIGN1cnJlbnRseSBwcmVzc2VkLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBpc0tleVByZXNzZWQoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRpZiAoSW5wdXQua2V5c0Rpc2FibGVkKSByZXR1cm4gZmFsc2U7XG5cblx0XHRpZiAoSW5wdXQua2V5UHJlc3NlZC5oYXMoa2V5KSkge1xuXHRcdFx0cmV0dXJuIElucHV0LmtleVByZXNzZWQuZ2V0KGtleSlcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGFuZ2VzIHRoZSBiaW5kaW5nIG9mIGFuIGlucHV0IG5hbWUgdG8ga2V5c1xuXHQgKiBAcGFyYW0gaW5wdXROYW1lIFRoZSBuYW1lIG9mIHRoZSBpbnB1dFxuXHQgKiBAcGFyYW0ga2V5cyBUaGUgY29ycmVzcG9uZGluZyBrZXlzXG5cdCAqL1xuXHRzdGF0aWMgY2hhbmdlS2V5QmluZGluZyhpbnB1dE5hbWU6IHN0cmluZywga2V5czogQXJyYXk8c3RyaW5nPik6IHZvaWQge1xuXHRcdElucHV0LmtleU1hcC5zZXQoaW5wdXROYW1lLCBrZXlzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhcnMgYWxsIGtleSBiaW5kaW5nc1xuXHQgKi9cblx0c3RhdGljIGNsZWFyQWxsS2V5QmluZGluZ3MoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5TWFwLmNsZWFyKCk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCBhbiBpbnB1dCB3YXMganVzdCBwcmVzc2VkIHRoaXMgZnJhbWVcblx0ICogQHBhcmFtIGlucHV0TmFtZSBUaGUgbmFtZSBvZiB0aGUgaW5wdXRcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgaW5wdXQgd2FzIGp1c3QgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgaXNKdXN0UHJlc3NlZChpbnB1dE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdGlmIChJbnB1dC5rZXlzRGlzYWJsZWQpIHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChJbnB1dC5rZXlNYXAuaGFzKGlucHV0TmFtZSkpIHtcblx0XHRcdGNvbnN0IGtleXMgPSBJbnB1dC5rZXlNYXAuZ2V0KGlucHV0TmFtZSk7XG5cdFx0XHRsZXQganVzdFByZXNzZWQgPSBmYWxzZTtcblxuXHRcdFx0Zm9yIChsZXQga2V5IG9mIGtleXMpIHtcblx0XHRcdFx0anVzdFByZXNzZWQgPSBqdXN0UHJlc3NlZCB8fCBJbnB1dC5pc0tleUp1c3RQcmVzc2VkKGtleSk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBqdXN0UHJlc3NlZDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IGFuIGlucHV0IGlzIGN1cnJlbnRseSBwcmVzc2VkXG5cdCAqIEBwYXJhbSBpbnB1dE5hbWUgVGhlIG5hbWUgb2YgdGhlIGlucHV0XG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGlucHV0IGlzIHByZXNzZWQsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cblx0c3RhdGljIGlzUHJlc3NlZChpbnB1dE5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdGlmIChJbnB1dC5rZXlzRGlzYWJsZWQpIHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChJbnB1dC5rZXlNYXAuaGFzKGlucHV0TmFtZSkpIHtcblx0XHRcdGNvbnN0IGtleXMgPSBJbnB1dC5rZXlNYXAuZ2V0KGlucHV0TmFtZSk7XG5cdFx0XHRsZXQgcHJlc3NlZCA9IGZhbHNlO1xuXG5cdFx0XHRmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuXHRcdFx0XHRwcmVzc2VkID0gcHJlc3NlZCB8fCBJbnB1dC5pc0tleVByZXNzZWQoa2V5KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHByZXNzZWQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblx0LyoqXG5cdCAqIFxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBtb3VzZSB3YXMgbmV3bHkgcHJlc3NlZCBJbnB1dCBmcmFtZS5cblx0ICogQHBhcmFtIG1vdXNlQnV0dG9uIE9wdGlvbmFsbHkgc3BlY2lmeSB3aGljaCBtb3VzZSBjbGljayB5b3Ugd2FudCB0byBrbm93IHdhcyBwcmVzc2VkLiBcblx0ICogMCBmb3IgbGVmdCBjbGljaywgMSBmb3IgbWlkZGxlIGNsaWNrLCAyIGZvciByaWdodCBjbGljay5cblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbW91c2Ugd2FzIGp1c3QgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgaXNNb3VzZUp1c3RQcmVzc2VkKG1vdXNlQnV0dG9uPzogbnVtYmVyKTogYm9vbGVhbiB7XG5cdFx0aWYgKG1vdXNlQnV0dG9uKSB7XG5cdFx0XHRyZXR1cm4gSW5wdXQubW91c2VKdXN0UHJlc3NlZCAmJiAhSW5wdXQubW91c2VEaXNhYmxlZCAmJiBtb3VzZUJ1dHRvbiA9PSB0aGlzLm1vdXNlQnV0dG9uUHJlc3NlZDtcblx0XHR9XG5cdFx0cmV0dXJuIElucHV0Lm1vdXNlSnVzdFByZXNzZWQgJiYgIUlucHV0Lm1vdXNlRGlzYWJsZWQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgbW91c2UgaXMgY3VycmVudGx5IHByZXNzZWRcblx0ICogQHBhcmFtIG1vdXNlQnV0dG9uIE9wdGlvbmFsbHkgc3BlY2lmeSB3aGljaCBtb3VzZSBjbGljayB5b3Ugd2FudCB0byBrbm93IHdhcyBwcmVzc2VkLiBcblx0ICogMCBmb3IgbGVmdCBjbGljaywgMSBmb3IgbWlkZGxlIGNsaWNrLCAyIGZvciByaWdodCBjbGljay5cblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbW91c2UgaXMgY3VycmVudGx5IHByZXNzZWQsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cblx0c3RhdGljIGlzTW91c2VQcmVzc2VkKG1vdXNlQnV0dG9uPzogbnVtYmVyKTogYm9vbGVhbiB7XG5cdFx0aWYgKG1vdXNlQnV0dG9uKSB7XG5cdFx0XHRyZXR1cm4gSW5wdXQubW91c2VQcmVzc2VkICYmICFJbnB1dC5tb3VzZURpc2FibGVkICYmIG1vdXNlQnV0dG9uID09IHRoaXMubW91c2VCdXR0b25QcmVzc2VkO1xuXHRcdH1cblx0XHRyZXR1cm4gSW5wdXQubW91c2VQcmVzc2VkICYmICFJbnB1dC5tb3VzZURpc2FibGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgd2hldGhlciB0aGUgdXNlciBzY3JvbGxlZCBvciBub3Rcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgdXNlciBqdXN0IHNjcm9sbGVkIElucHV0IGZyYW1lLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBkaWRKdXN0U2Nyb2xsKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBJbnB1dC5qdXN0U2Nyb2xsZWQgJiYgIUlucHV0Lm1vdXNlRGlzYWJsZWQ7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZGlyZWN0aW9uIG9mIHRoZSBzY3JvbGxcblx0ICogQHJldHVybnMgLTEgaWYgdGhlIHVzZXIgc2Nyb2xsZWQgdXAsIDEgaWYgdGhleSBzY3JvbGxlZCBkb3duXG5cdCAqL1xuXHRzdGF0aWMgZ2V0U2Nyb2xsRGlyZWN0aW9uKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIElucHV0LnNjcm9sbERpcmVjdGlvbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgcGxheWVyJ3MgbW91c2Vcblx0ICogQHJldHVybnMgVGhlIG1vdXNlIHBvc2l0aW9uIHN0b3JlZCBhcyBhIFZlYzJcblx0ICovXG5cdHN0YXRpYyBnZXRNb3VzZVBvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiBJbnB1dC5tb3VzZVBvc2l0aW9uLnNjYWxlZCgxIC8gdGhpcy52aWV3cG9ydC5nZXRab29tTGV2ZWwoKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIHBsYXllcidzIG1vdXNlIGluIHRoZSBnYW1lIHdvcmxkLFxuXHQgKiB0YWtpbmcgaW50byBjb25zaWRlcmF0aW9uIHRoZSBzY3JvbGxpbmcgb2YgdGhlIHZpZXdwb3J0XG5cdCAqIEByZXR1cm5zIFRoZSBtb3VzZSBwb3NpdGlvbiBzdG9yZWQgYXMgYSBWZWMyXG5cdCAqL1xuXHRzdGF0aWMgZ2V0R2xvYmFsTW91c2VQb3NpdGlvbigpOiBWZWMyIHtcblx0XHRyZXR1cm4gSW5wdXQubW91c2VQb3NpdGlvbi5jbG9uZSgpLnNjYWxlKDEgLyB0aGlzLnZpZXdwb3J0LmdldFpvb21MZXZlbCgpKS5hZGQoSW5wdXQudmlld3BvcnQuZ2V0T3JpZ2luKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBvc2l0aW9uIG9mIHRoZSBsYXN0IG1vdXNlIHByZXNzXG5cdCAqIEByZXR1cm5zIFRoZSBtb3VzZSBwb3NpdGlvbiBzdG9yZWQgYXMgYSBWZWMyXG5cdCAqL1xuXHRzdGF0aWMgZ2V0TW91c2VQcmVzc1Bvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiBJbnB1dC5tb3VzZVByZXNzUG9zaXRpb247XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIGxhc3QgbW91c2UgcHJlc3MgaW4gdGhlIGdhbWUgd29ybGQsXG5cdCAqIHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gdGhlIHNjcm9sbGluZyBvZiB0aGUgdmlld3BvcnRcblx0ICogQHJldHVybnMgVGhlIG1vdXNlIHBvc2l0aW9uIHN0b3JlZCBhcyBhIFZlYzJcblx0ICovXG5cdHN0YXRpYyBnZXRHbG9iYWxNb3VzZVByZXNzUG9zaXRpb24oKTogVmVjMiB7XG5cdFx0cmV0dXJuIElucHV0Lm1vdXNlUHJlc3NQb3NpdGlvbi5jbG9uZSgpLmFkZChJbnB1dC52aWV3cG9ydC5nZXRPcmlnaW4oKSk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzYWJsZXMgYWxsIGtleXByZXNzIGFuZCBtb3VzZSBjbGljayBpbnB1dHNcblx0ICovXG5cdHN0YXRpYyBkaXNhYmxlSW5wdXQoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5c0Rpc2FibGVkID0gdHJ1ZTtcblx0XHRJbnB1dC5tb3VzZURpc2FibGVkID0gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFbmFibGVzIGFsbCBrZXlwcmVzcyBhbmQgbW91c2UgY2xpY2sgaW5wdXRzXG5cdCAqL1xuXHRzdGF0aWMgZW5hYmxlSW5wdXQoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5c0Rpc2FibGVkID0gZmFsc2U7XG5cdFx0SW5wdXQubW91c2VEaXNhYmxlZCA9IGZhbHNlO1xuXHR9XG59IiwiaW1wb3J0IEV2ZW50UXVldWUgZnJvbSBcIi4uL0V2ZW50cy9FdmVudFF1ZXVlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuLyoqXG4gKiBIYW5kbGVzIGNvbW11bmljYXRpb24gd2l0aCB0aGUgd2ViIGJyb3dzZXIgdG8gcmVjZWl2ZSBhc3luY2hyb25vdXMgZXZlbnRzIGFuZCBzZW5kIHRoZW0gdG8gdGhlIEByZWZlcmVuY2VbRXZlbnRRdWV1ZV1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW5wdXRIYW5kbGVyIHtcblx0cHJpdmF0ZSBldmVudFF1ZXVlOiBFdmVudFF1ZXVlO1xuICAgICBcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IElucHV0SGFuZGxlclxuICAgICAqIEBwYXJhbSBjYW52YXMgVGhlIGdhbWUgY2FudmFzXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCl7XG5cdFx0dGhpcy5ldmVudFF1ZXVlID0gRXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpO1xuXHRcdFxuICAgICAgICBjYW52YXMub25tb3VzZWRvd24gPSAoZXZlbnQpID0+IHRoaXMuaGFuZGxlTW91c2VEb3duKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBjYW52YXMub25tb3VzZXVwID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU1vdXNlVXAoZXZlbnQsIGNhbnZhcyk7XG4gICAgICAgIGNhbnZhcy5vbmNvbnRleHRtZW51ID0gdGhpcy5oYW5kbGVDb250ZXh0TWVudTtcbiAgICAgICAgY2FudmFzLm9ubW91c2Vtb3ZlID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU1vdXNlTW92ZShldmVudCwgY2FudmFzKTtcbiAgICAgICAgZG9jdW1lbnQub25rZXlkb3duID0gdGhpcy5oYW5kbGVLZXlEb3duO1xuICAgICAgICBkb2N1bWVudC5vbmtleXVwID0gdGhpcy5oYW5kbGVLZXlVcDtcbiAgICAgICAgZG9jdW1lbnQub25ibHVyID0gdGhpcy5oYW5kbGVCbHVyO1xuICAgICAgICBkb2N1bWVudC5vbmNvbnRleHRtZW51ID0gdGhpcy5oYW5kbGVCbHVyO1xuICAgICAgICBkb2N1bWVudC5vbndoZWVsID0gdGhpcy5oYW5kbGVXaGVlbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZU1vdXNlRG93biA9IChldmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IHZvaWQgPT4ge1xuXHRcdGxldCBwb3MgPSB0aGlzLmdldE1vdXNlUG9zaXRpb24oZXZlbnQsIGNhbnZhcyk7XG4gICAgICAgIGxldCBidXR0b24gPSBldmVudC5idXR0b247XG4gICAgICAgIGxldCBnYW1lRXZlbnQgPSBuZXcgR2FtZUV2ZW50KEdhbWVFdmVudFR5cGUuTU9VU0VfRE9XTiwge3Bvc2l0aW9uOiBwb3MsIGJ1dHRvbjogYnV0dG9ufSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlTW91c2VVcCA9IChldmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQgcG9zID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLk1PVVNFX1VQLCB7cG9zaXRpb246IHBvc30pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZU1vdXNlTW92ZSA9IChldmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQgcG9zID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLk1PVVNFX01PVkUsIHtwb3NpdGlvbjogcG9zfSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlS2V5RG93biA9IChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQga2V5ID0gdGhpcy5nZXRLZXkoZXZlbnQpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLktFWV9ET1dOLCB7a2V5OiBrZXl9KTtcbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KGdhbWVFdmVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVLZXlVcCA9IChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQga2V5ID0gdGhpcy5nZXRLZXkoZXZlbnQpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLktFWV9VUCwge2tleToga2V5fSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlQmx1ciA9IChldmVudDogRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgbGV0IGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5DQU5WQVNfQkxVUiwge30pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUNvbnRleHRNZW51ID0gKGV2ZW50OiBFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZVdoZWVsID0gKGV2ZW50OiBXaGVlbEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBcbiAgICAgICAgbGV0IGdhbWVFdmVudDogR2FtZUV2ZW50O1xuICAgICAgICBpZihldmVudC5kZWx0YVkgPCAwKXtcbiAgICAgICAgICAgIGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5XSEVFTF9VUCwge30pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLldIRUVMX0RPV04sIHt9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEtleShrZXlFdmVudDogS2V5Ym9hcmRFdmVudCl7XG4gICAgICAgIHJldHVybiBrZXlFdmVudC5rZXkudG9Mb3dlckNhc2UoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldE1vdXNlUG9zaXRpb24obW91c2VFdmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IFZlYzIge1xuICAgICAgICBsZXQgcmVjdCA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgbGV0IHggPSBtb3VzZUV2ZW50LmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgICAgIGxldCB5ID0gbW91c2VFdmVudC5jbGllbnRZIC0gcmVjdC50b3A7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih4LCB5KTtcbiAgICB9XG59IiwiaW1wb3J0IHt9IGZyb20gXCIuLi8uLi9pbmRleFwiOyAgLy8gVGhpcyBpbXBvcnQgYWxsb3dzIHVzIHRvIG1vZGlmeSB0aGUgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHRvIGFkZCBleHRyYSBmdW5jdGlvbmFsaXR5XG4vLyBAaWdub3JlUGFnZVxuXG4vKipcbiAqIFNldHMgdXAgdGhlIGVudmlyb25tZW50IG9mIHRoZSBnYW1lIGVuZ2luZVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFbnZpcm9ubWVudEluaXRpYWxpemVyIHtcbiAgICBzdGF0aWMgc2V0dXAoKXtcbiAgICAgICAgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELnByb3RvdHlwZS5yb3VuZGVkUmVjdCA9IGZ1bmN0aW9uKHg6IG51bWJlciwgeTogbnVtYmVyLCB3OiBudW1iZXIsIGg6IG51bWJlciwgcjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgICAgICAvLyBDbGFtcCB0aGUgcmFkaXVzIGJldHdlZW4gMCBhbmQgdGhlIG1pbiBvZiB0aGUgd2lkdGggb3IgaGVpZ2h0XG4gICAgICAgICAgICBpZihyIDwgMCkgciA9IDA7XG4gICAgICAgICAgICBpZihyID4gTWF0aC5taW4odywgaCkpIHIgPSBNYXRoLm1pbih3LCBoKTtcbiAgICAgICAgXG4gICAgICAgICAgICAvLyBEcmF3IHRoZSByb3VuZGVkIHJlY3RcbiAgICAgICAgICAgIHRoaXMuYmVnaW5QYXRoKCk7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gVG9wXG4gICAgICAgICAgICB0aGlzLm1vdmVUbyh4ICsgciwgeSk7XG4gICAgICAgICAgICB0aGlzLmxpbmVUbyh4ICsgdyAtIHIsIHkpO1xuICAgICAgICAgICAgdGhpcy5hcmNUbyh4ICsgdywgeSwgeCArIHcsIHkgKyByLCByKTtcbiAgICAgICAgXG4gICAgICAgICAgICAvLyBSaWdodFxuICAgICAgICAgICAgdGhpcy5saW5lVG8oeCArIHcsIHkgKyBoIC0gcik7XG4gICAgICAgICAgICB0aGlzLmFyY1RvKHggKyB3LCB5ICsgaCwgeCArIHcgLSByLCB5ICsgaCwgcik7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gQm90dG9tXG4gICAgICAgICAgICB0aGlzLmxpbmVUbyh4ICsgciwgeSArIGgpO1xuICAgICAgICAgICAgdGhpcy5hcmNUbyh4LCB5ICsgaCwgeCwgeSArIGggLSByLCByKTtcbiAgICAgICAgXG4gICAgICAgICAgICAvLyBMZWZ0XG4gICAgICAgICAgICB0aGlzLmxpbmVUbyh4LCB5ICsgcik7XG4gICAgICAgICAgICB0aGlzLmFyY1RvKHgsIHksIHggKyByLCB5LCByKVxuICAgICAgICBcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5wcm90b3R5cGUuc3Ryb2tlUm91bmRlZFJlY3QgPSBmdW5jdGlvbih4LCB5LCB3LCBoLCByKXtcbiAgICAgICAgICAgIHRoaXMucm91bmRlZFJlY3QoeCwgeSwgdywgaCwgcik7XG4gICAgICAgICAgICB0aGlzLnN0cm9rZSgpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQucHJvdG90eXBlLmZpbGxSb3VuZGVkUmVjdCA9IGZ1bmN0aW9uKHgsIHksIHcsIGgsIHIpe1xuICAgICAgICAgICAgdGhpcy5yb3VuZGVkUmVjdCh4LCB5LCB3LCBoLCByKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbCgpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBHYW1lTG9vcCBmcm9tIFwiLi9HYW1lTG9vcFwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IFN0YXRzIGZyb20gXCIuLi9EZWJ1Zy9TdGF0c1wiO1xuXG4vKipcbiAqIEEgZ2FtZSBsb29wIHdpdGggYSBmaXhlZCB1cGRhdGUgdGltZSBhbmQgYSB2YXJpYWJsZSByZW5kZXIgdGltZS5cbiAqIEV2ZXJ5IGZyYW1lLCB0aGUgZ2FtZSB1cGRhdGVzIHVudGlsIGFsbCB0aW1lIHNpbmNlIHRoZSBsYXN0IGZyYW1lIGhhcyBiZWVuIHByb2Nlc3NlZC5cbiAqIElmIHRvbyBtdWNoIHRpbWUgaGFzIHBhc3NlZCwgc3VjaCBhcyBpZiB0aGUgbGFzdCB1cGRhdGUgd2FzIHRvbyBzbG93LCBcbiAqIG9yIGlmIHRoZSBicm93c2VyIHdhcyBwdXQgaW50byB0aGUgYmFja2dyb3VuZCwgdGhlIGxvb3Agd2lsbCBwYW5pYyBhbmQgZGlzY2FyZCB0aW1lLlxuICogQSByZW5kZXIgaGFwcGVucyBhdCB0aGUgZW5kIG9mIGV2ZXJ5IGZyYW1lLiBUaGlzIGhhcHBlbnMgYXMgZmFzdCBhcyBwb3NzaWJsZSB1bmxlc3Mgc3BlY2lmaWVkLlxuICogQSBsb29wIG9mIHRoaXMgdHlwZSBhbGxvd3MgZm9yIGRldGVybWluaXN0aWMgYmVoYXZpb3IgLSBObyBtYXR0ZXIgd2hhdCB0aGUgZnJhbWUgcmF0ZSBpcywgdGhlIHVwZGF0ZSBzaG91bGQgYmVoYXZlIHRoZSBzYW1lLCBcbiAqIGFzIGl0IGlzIG9jY3VyaW5nIGluIGEgZml4ZWQgaW50ZXJ2YWwuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZpeGVkVXBkYXRlR2FtZUxvb3AgZXh0ZW5kcyBHYW1lTG9vcCB7XG5cblx0LyoqIFRoZSBtYXggYWxsb3dlZCB1cGRhdGUgZnBzLiovXG4gICAgcHJpdmF0ZSBtYXhVcGRhdGVGUFM6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIHRpbWVzdGVwIGZvciBlYWNoIHVwZGF0ZS4gVGhpcyBpcyB0aGUgZGVsdGFUIHBhc3NlZCB0byB1cGRhdGUgY2FsbHMuICovXG5cdHByaXZhdGUgdXBkYXRlVGltZXN0ZXA6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgYW1vdW50IG9mIHRpbWUgd2UgYXJlIHlldCB0byBzaW11bGF0ZS4gKi9cbiAgICBwcml2YXRlIGZyYW1lRGVsdGE6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgdGltZSB3aGVuIHRoZSBsYXN0IGZyYW1lIHdhcyBkcmF3bi4gKi9cbiAgICBwcml2YXRlIGxhc3RGcmFtZVRpbWU6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIG1pbmltdW0gdGltZSB3ZSB3YW50IHRvIHdhaXQgYmV0d2VlbiBnYW1lIGZyYW1lcy4gKi9cbiAgICBwcml2YXRlIG1pbkZyYW1lRGVsYXk6IG51bWJlcjtcblxuXHQvKiogVGhlIGN1cnJlbnQgZnJhbWUgb2YgdGhlIGdhbWUuICovXG5cdHByaXZhdGUgZnJhbWU6IG51bWJlcjtcblxuXHQvKiogVGhlIGFjdHVhbCBmcHMgb2YgdGhlIGdhbWUuICovXG4gICAgcHJpdmF0ZSBmcHM6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIHRpbWUgYmV0d2VlbiBmcHMgbWVhc3VyZW1lbnQgdXBkYXRlcy4gKi9cbiAgICBwcml2YXRlIGZwc1VwZGF0ZUludGVydmFsOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHRpbWUgb2YgdGhlIGxhc3QgZnBzIHVwZGF0ZS4gKi9cbiAgICBwcml2YXRlIGxhc3RGcHNVcGRhdGU6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgbnVtYmVyIG9mIGZyYW1lcyBzaW5jZSB0aGUgbGFzdCBmcHMgdXBkYXRlIHdhcyBkb25lLiAqL1xuICAgIHByaXZhdGUgZnJhbWVzU2luY2VMYXN0RnBzVXBkYXRlOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHN0YXR1cyBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgZ2FtZSBsb29wIGhhcyBzdGFydGVkLiAqL1xuICAgIHByaXZhdGUgc3RhcnRlZDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgc3RhdHVzIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBnYW1lIGxvb3AgaXMgcGF1c2VkICovXG4gICAgcHJpdmF0ZSBwYXVzZWQ6IGJvb2xlYW47XG4gICAgXG4gICAgLyoqIFRoZSBzdGF0dXMgb2Ygd2hldGhlciBvciBub3QgdGhlIGdhbWUgbG9vcCBpcyBjdXJyZW50bHkgcnVubmluZy4gKi9cbiAgICBwcml2YXRlIHJ1bm5pbmc6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIG51bWJlciBvZiB1cGRhdGUgc3RlcHMgdGhpcyBpdGVyYXRpb24gb2YgdGhlIGdhbWUgbG9vcC4gKi9cbiAgICBwcml2YXRlIG51bVVwZGF0ZVN0ZXBzOiBudW1iZXI7XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcbiAgICAgICAgdGhpcy5tYXhVcGRhdGVGUFMgPSA2MDtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RlcCA9IE1hdGguZmxvb3IoMTAwMC90aGlzLm1heFVwZGF0ZUZQUyk7XG4gICAgICAgIHRoaXMuZnJhbWVEZWx0YSA9IDA7XG4gICAgICAgIHRoaXMubGFzdEZyYW1lVGltZSA9IDA7XG4gICAgICAgIHRoaXMubWluRnJhbWVEZWxheSA9IDA7XG4gICAgICAgIHRoaXMuZnJhbWUgPSAwO1xuICAgICAgICB0aGlzLmZwcyA9IHRoaXMubWF4VXBkYXRlRlBTOyAgIC8vIEluaXRpYWxpemUgdGhlIGZwcyB0byB0aGUgbWF4IGFsbG93ZWQgZnBzXG4gICAgICAgIHRoaXMuZnBzVXBkYXRlSW50ZXJ2YWwgPSAxMDAwO1xuICAgICAgICB0aGlzLmxhc3RGcHNVcGRhdGUgPSAwO1xuICAgICAgICB0aGlzLmZyYW1lc1NpbmNlTGFzdEZwc1VwZGF0ZSA9IDA7XG4gICAgICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhdXNlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJ1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5udW1VcGRhdGVTdGVwcyA9IDA7XG5cdH1cblxuXHRnZXRGUFMoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gMDtcblx0fVxuXG5cdC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIGZyYW1lIGNvdW50IGFuZCBzdW0gb2YgdGltZSBmb3IgdGhlIGZyYW1lcmF0ZSBvZiB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSB0aW1lc3RlcCBUaGUgY3VycmVudCB0aW1lIGluIG1zXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUZQUyh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmZwcyA9IDAuOSAqIHRoaXMuZnJhbWVzU2luY2VMYXN0RnBzVXBkYXRlICogMTAwMCAvICh0aW1lc3RhbXAgLSB0aGlzLmxhc3RGcHNVcGRhdGUpICsoMSAtIDAuOSkgKiB0aGlzLmZwcztcbiAgICAgICAgdGhpcy5sYXN0RnBzVXBkYXRlID0gdGltZXN0YW1wO1xuICAgICAgICB0aGlzLmZyYW1lc1NpbmNlTGFzdEZwc1VwZGF0ZSA9IDA7XG5cbiAgICAgICAgRGVidWcubG9nKFwiZnBzXCIsIFwiRlBTOiBcIiArIHRoaXMuZnBzLnRvRml4ZWQoMSkpO1xuICAgICAgICBTdGF0cy51cGRhdGVGUFModGhpcy5mcHMpO1xuICAgIH1cblxuXHQgICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgbWF4aW11bSBhbGxvd2VkIHBoeXNpY3MgZnJhbWVyYXRlIG9mIHRoZSBnYW1lXG4gICAgICogQHBhcmFtIGluaXRNYXggVGhlIG1heCBmcmFtZXJhdGVcbiAgICAgKi9cbiAgICBzZXRNYXhVcGRhdGVGUFMoaW5pdE1heDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWF4VXBkYXRlRlBTID0gaW5pdE1heDtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RlcCA9IE1hdGguZmxvb3IoMTAwMC90aGlzLm1heFVwZGF0ZUZQUyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbWF4aW11bSByZW5kZXJpbmcgZnJhbWVyYXRlXG4gICAgICogQHBhcmFtIG1heEZQUyBUaGUgbWF4IGZyYW1lcmF0ZVxuICAgICAqL1xuICAgIHNldE1heEZQUyhtYXhGUFM6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLm1pbkZyYW1lRGVsYXkgPSAxMDAwL21heEZQUztcblx0fVxuXHRcblx0LyoqXG5cdCAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gdGhlIGdhbWUgbG9vcCBwYW5pY3MsIGkuZS4gaXQgdHJpZXMgdG8gcHJvY2VzcyB0b28gbXVjaCB0aW1lIGluIGFuIGVudGlyZSBmcmFtZS5cblx0ICogVGhpcyB3aWxsIHJlc2V0IHRoZSBhbW91bnQgb2YgdGltZSBiYWNrIHRvIHplcm8uXG5cdCAqIEByZXR1cm5zIFRoZSBhbW91bnQgb2YgdGltZSB3ZSBhcmUgZGlzY2FyZGluZyBmcm9tIHByb2Nlc3NpbmcuXG5cdCAqL1xuXHRyZXNldEZyYW1lRGVsdGEoKSA6IG51bWJlciB7XG4gICAgICAgIGxldCBvbGRGcmFtZURlbHRhID0gdGhpcy5mcmFtZURlbHRhO1xuICAgICAgICB0aGlzLmZyYW1lRGVsdGEgPSAwO1xuICAgICAgICByZXR1cm4gb2xkRnJhbWVEZWx0YTtcbiAgICB9XG5cblx0LyoqXG4gICAgICogU3RhcnRzIHVwIHRoZSBnYW1lIGxvb3AgYW5kIGNhbGxzIHRoZSBmaXJzdCByZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgICAgKi9cblx0c3RhcnQoKTogdm9pZCB7XG4gICAgICAgIGlmKCF0aGlzLnN0YXJ0ZWQpe1xuICAgICAgICAgICAgdGhpcy5zdGFydGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgodGltZXN0YW1wKSA9PiB0aGlzLmRvRmlyc3RGcmFtZSh0aW1lc3RhbXApKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHBhdXNlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcmVzdW1lKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IGZhbHNlO1xuICAgIH1cblxuXHQvKipcbiAgICAgKiBUaGUgZmlyc3QgZ2FtZSBmcmFtZSAtIGluaXRpYWxpemVzIHRoZSBmaXJzdCBmcmFtZSB0aW1lIGFuZCBiZWdpbnMgdGhlIHJlbmRlclxuICAgICAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIGN1cnJlbnQgdGltZSBpbiBtc1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBkb0ZpcnN0RnJhbWUodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkICB7XG4gICAgICAgIHRoaXMucnVubmluZyA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5fZG9SZW5kZXIoKTtcblxuICAgICAgICB0aGlzLmxhc3RGcmFtZVRpbWUgPSB0aW1lc3RhbXA7XG4gICAgICAgIHRoaXMubGFzdEZwc1VwZGF0ZSA9IHRpbWVzdGFtcDtcbiAgICAgICAgdGhpcy5mcmFtZXNTaW5jZUxhc3RGcHNVcGRhdGUgPSAwO1xuXG4gICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKHQpID0+IHRoaXMuZG9GcmFtZSh0KSk7XG4gICAgfVxuXG5cdC8qKlxuXHQgKiBIYW5kbGVzIGFueSBwcm9jZXNzaW5nIHRoYXQgbmVlZHMgdG8gYmUgZG9uZSBhdCB0aGUgc3RhcnQgb2YgdGhlIGZyYW1lXG5cdCAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIHRpbWUgb2YgdGhlIGZyYW1lIGluIG1zXG5cdCAqL1xuXHRwcm90ZWN0ZWQgc3RhcnRGcmFtZSh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIFVwZGF0ZSB0aGUgYW1vdW50IG9mIHRpbWUgd2UgbmVlZCBvdXIgdXBkYXRlIHRvIHByb2Nlc3Ncblx0XHR0aGlzLmZyYW1lRGVsdGEgKz0gdGltZXN0YW1wIC0gdGhpcy5sYXN0RnJhbWVUaW1lO1xuXG5cdFx0Ly8gU2V0IHRoZSBuZXcgdGltZSBvZiB0aGUgbGFzdCBmcmFtZVxuICAgICAgICB0aGlzLmxhc3RGcmFtZVRpbWUgPSB0aW1lc3RhbXA7XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBlc3RpbWF0ZSBvZiB0aGUgZnJhbWVyYXRlXG4gICAgICAgIGlmKHRpbWVzdGFtcCA+IHRoaXMubGFzdEZwc1VwZGF0ZSArIHRoaXMuZnBzVXBkYXRlSW50ZXJ2YWwpe1xuICAgICAgICAgICAgdGhpcy51cGRhdGVGUFModGltZXN0YW1wKTtcbiAgICAgICAgfVxuXG5cdFx0Ly8gSW5jcmVtZW50IHRoZSBudW1iZXIgb2YgZnJhbWVzXG4gICAgICAgIHRoaXMuZnJhbWUrKztcbiAgICAgICAgdGhpcy5mcmFtZXNTaW5jZUxhc3RGcHNVcGRhdGUrKztcblx0fVxuXG5cdC8qKlxuICAgICAqIFRoZSBtYWluIGxvb3Agb2YgdGhlIGdhbWUuIFVwZGF0ZXMgdW50aWwgdGhlIGN1cnJlbnQgdGltZSBpcyByZWFjaGVkLiBSZW5kZXJzIG9uY2VcbiAgICAgKiBAcGFyYW0gdGltZXN0YW1wIFRoZSBjdXJyZW50IHRpbWUgaW4gbXNcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZG9GcmFtZSA9ICh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQgPT4ge1xuICAgICAgICAvLyBJZiBhIHBhdXNlIHdhcyBleGVjdXRlZCwgc3RvcCBkb2luZyB0aGUgbG9vcC5cbiAgICAgICAgaWYodGhpcy5wYXVzZWQpeyBcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlcXVlc3QgYW5pbWF0aW9uIGZyYW1lIHRvIHByZXBhcmUgZm9yIGFub3RoZXIgdXBkYXRlIG9yIHJlbmRlclxuICAgICAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCh0KSA9PiB0aGlzLmRvRnJhbWUodCkpO1xuXG4gICAgICAgIC8vIElmIHdlIGFyZSB0cnlpbmcgdG8gcmVuZGVyIHRvbyBzb29uLCBkbyBub3RoaW5nLlxuICAgICAgICBpZih0aW1lc3RhbXAgPCB0aGlzLmxhc3RGcmFtZVRpbWUgKyB0aGlzLm1pbkZyYW1lRGVsYXkpe1xuICAgICAgICAgICAgcmV0dXJuO1xuXHRcdH1cblx0XHRcblx0XHQvLyBBIGZyYW1lIGlzIGFjdHVhbGx5IGhhcHBlbmluZ1xuXHRcdHRoaXMuc3RhcnRGcmFtZSh0aW1lc3RhbXApO1xuXG5cdFx0Ly8gVXBkYXRlIHdoaWxlIHRoZXJlIGlzIHN0aWxsIHRpbWUgdG8gbWFrZSB1cC4gSWYgd2UgZG8gdG9vIG1hbnkgdXBkYXRlIHN0ZXBzLCBwYW5pYyBhbmQgZXhpdCB0aGUgbG9vcC5cblx0XHR0aGlzLm51bVVwZGF0ZVN0ZXBzID0gMDtcblx0XHRsZXQgcGFuaWMgPSBmYWxzZTtcblxuICAgICAgICB3aGlsZSh0aGlzLmZyYW1lRGVsdGEgPj0gdGhpcy51cGRhdGVUaW1lc3RlcCl7XG5cdFx0XHQvLyBEbyBhbiB1cGRhdGVcblx0XHRcdHRoaXMuX2RvVXBkYXRlKHRoaXMudXBkYXRlVGltZXN0ZXAvMTAwMCk7XG5cdFx0XHRcblx0XHRcdC8vIFJlbW92ZSB0aGUgdXBkYXRlIHN0ZXAgdGltZSBmcm9tIHRoZSB0aW1lIHdlIGhhdmUgdG8gcHJvY2Vzc1xuICAgICAgICAgICAgdGhpcy5mcmFtZURlbHRhIC09IHRoaXMudXBkYXRlVGltZXN0ZXA7XG5cblx0XHRcdC8vIEluY3JlbWVudCBzdGVwcyBhbmQgY2hlY2sgaWYgd2UndmUgZG9uZSB0b28gbWFueVxuICAgICAgICAgICAgdGhpcy5udW1VcGRhdGVTdGVwcysrO1xuICAgICAgICAgICAgaWYodGhpcy5udW1VcGRhdGVTdGVwcyA+IDEwMCl7XG4gICAgICAgICAgICAgICAgcGFuaWMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlcyBhcmUgZG9uZSwgcmVuZGVyXG4gICAgICAgIHRoaXMuX2RvUmVuZGVyKCk7XG5cbiAgICAgICAgLy8gV3JhcCB1cCB0aGUgZnJhbWVcbiAgICAgICAgdGhpcy5maW5pc2hGcmFtZShwYW5pYyk7XG4gICAgfVxuXG5cdC8qKlxuXHQgKiBXcmFwcyB1cCB0aGUgZnJhbWUgYW5kIGhhbmRsZXMgdGhlIHBhbmljIHN0YXRlIGlmIHRoZXJlIGlzIG9uZVxuXHQgKiBAcGFyYW0gcGFuaWMgV2hldGhlciBvciBub3QgdGhlIGxvb3AgcGFuaWNrZWRcblx0ICovXG5cdHByb3RlY3RlZCBmaW5pc2hGcmFtZShwYW5pYzogYm9vbGVhbik6IHZvaWQge1xuXHRcdGlmKHBhbmljKSB7XG4gICAgICAgICAgICB2YXIgZGlzY2FyZGVkVGltZSA9IE1hdGgucm91bmQodGhpcy5yZXNldEZyYW1lRGVsdGEoKSk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ01haW4gbG9vcCBwYW5pY2tlZCwgcHJvYmFibHkgYmVjYXVzZSB0aGUgYnJvd3NlciB0YWIgd2FzIHB1dCBpbiB0aGUgYmFja2dyb3VuZC4gRGlzY2FyZGluZyAnICsgZGlzY2FyZGVkVGltZSArICdtcycpO1xuICAgICAgICB9XG5cdH1cblxufSIsImltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuLi9FdmVudHMvRXZlbnRRdWV1ZVwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IElucHV0SGFuZGxlciBmcm9tIFwiLi4vSW5wdXQvSW5wdXRIYW5kbGVyXCI7XG5pbXBvcnQgUmVjb3JkZXIgZnJvbSBcIi4uL1BsYXliYWNrL1JlY29yZGVyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBTY2VuZU1hbmFnZXIgZnJvbSBcIi4uL1NjZW5lL1NjZW5lTWFuYWdlclwiO1xuaW1wb3J0IEF1ZGlvTWFuYWdlciBmcm9tIFwiLi4vU291bmQvQXVkaW9NYW5hZ2VyXCI7XG5pbXBvcnQgU3RhdHMgZnJvbSBcIi4uL0RlYnVnL1N0YXRzXCI7XG5pbXBvcnQgUmVuZGVyaW5nTWFuYWdlciBmcm9tIFwiLi4vUmVuZGVyaW5nL1JlbmRlcmluZ01hbmFnZXJcIjtcbmltcG9ydCBDYW52YXNSZW5kZXJlciBmcm9tIFwiLi4vUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmVyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgR2FtZU9wdGlvbnMgZnJvbSBcIi4vR2FtZU9wdGlvbnNcIjtcbmltcG9ydCBHYW1lTG9vcCBmcm9tIFwiLi9HYW1lTG9vcFwiO1xuaW1wb3J0IEZpeGVkVXBkYXRlR2FtZUxvb3AgZnJvbSBcIi4vRml4ZWRVcGRhdGVHYW1lTG9vcFwiO1xuaW1wb3J0IEVudmlyb25tZW50SW5pdGlhbGl6ZXIgZnJvbSBcIi4vRW52aXJvbm1lbnRJbml0aWFsaXplclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgUmVnaXN0cnlNYW5hZ2VyIGZyb20gXCIuLi9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXJcIjtcbmltcG9ydCBXZWJHTFJlbmRlcmVyIGZyb20gXCIuLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJlclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZS9TY2VuZVwiO1xuXG4vKipcbiAqIFRoZSBtYWluIGxvb3Agb2YgdGhlIGdhbWUgZW5naW5lLlxuICogSGFuZGxlcyB0aGUgdXBkYXRlIG9yZGVyLCBhbmQgaW5pdGlhbGl6ZXMgYWxsIHN1YnN5c3RlbXMuXG4gKiBUaGUgR2FtZSBtYW5hZ2VzIHRoZSB1cGRhdGUgY3ljbGUsIGFuZCByZXF1ZXN0cyBhbmltYXRpb24gZnJhbWVzIHRvIHJlbmRlciB0byB0aGUgYnJvd3Nlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2FtZSB7XG4gICAgZ2FtZU9wdGlvbnM6IEdhbWVPcHRpb25zO1xuICAgIHByaXZhdGUgc2hvd0RlYnVnOiBib29sZWFuO1xuICAgIHByaXZhdGUgc2hvd1N0YXRzOiBib29sZWFuO1xuXG4gICAgLy8gVGhlIGdhbWUgbG9vcFxuICAgIHByaXZhdGUgbG9vcDogR2FtZUxvb3A7XG5cbiAgICAvLyBHYW1lIGNhbnZhcyBhbmQgaXRzIHdpZHRoIGFuZCBoZWlnaHRcbiAgICByZWFkb25seSBHQU1FX0NBTlZBUzogSFRNTENhbnZhc0VsZW1lbnQ7XG4gICAgcmVhZG9ubHkgREVCVUdfQ0FOVkFTOiBIVE1MQ2FudmFzRWxlbWVudDtcblx0cmVhZG9ubHkgV0lEVEg6IG51bWJlcjtcbiAgICByZWFkb25seSBIRUlHSFQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHZpZXdwb3J0OiBWaWV3cG9ydDtcbiAgICBwcml2YXRlIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHwgV2ViR0xSZW5kZXJpbmdDb250ZXh0O1xuICAgIHByaXZhdGUgY2xlYXJDb2xvcjogQ29sb3I7XG4gICAgXG4gICAgLy8gQWxsIG9mIHRoZSBuZWNlc3Nhcnkgc3Vic3lzdGVtcyB0aGF0IG5lZWQgdG8gcnVuIGhlcmVcblx0cHJpdmF0ZSBldmVudFF1ZXVlOiBFdmVudFF1ZXVlO1xuXHRwcml2YXRlIGlucHV0SGFuZGxlcjogSW5wdXRIYW5kbGVyO1xuXHRwcml2YXRlIHJlY29yZGVyOiBSZWNvcmRlcjtcbiAgICBwcml2YXRlIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuICAgIHByaXZhdGUgc2NlbmVNYW5hZ2VyOiBTY2VuZU1hbmFnZXI7XG4gICAgcHJpdmF0ZSBhdWRpb01hbmFnZXI6IEF1ZGlvTWFuYWdlcjtcbiAgICBwcml2YXRlIHJlbmRlcmluZ01hbmFnZXI6IFJlbmRlcmluZ01hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEdhbWVcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgb3B0aW9ucyBmb3IgR2FtZSBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KXtcbiAgICAgICAgLy8gQmVmb3JlIGFueXRoaW5nIGVsc2UsIGJ1aWxkIHRoZSBlbnZpcm9ubWVudFxuICAgICAgICBFbnZpcm9ubWVudEluaXRpYWxpemVyLnNldHVwKCk7XG5cbiAgICAgICAgLy8gVHlwZWNhc3QgdGhlIGNvbmZpZyBvYmplY3QgdG8gYSBHYW1lQ29uZmlnIG9iamVjdFxuICAgICAgICB0aGlzLmdhbWVPcHRpb25zID0gR2FtZU9wdGlvbnMucGFyc2Uob3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5zaG93RGVidWcgPSB0aGlzLmdhbWVPcHRpb25zLnNob3dEZWJ1ZztcbiAgICAgICAgdGhpcy5zaG93U3RhdHMgPSB0aGlzLmdhbWVPcHRpb25zLnNob3dTdGF0cztcblxuICAgICAgICAvLyBDcmVhdGUgYW4gaW5zdGFuY2Ugb2YgYSBnYW1lIGxvb3BcbiAgICAgICAgdGhpcy5sb29wID0gbmV3IEZpeGVkVXBkYXRlR2FtZUxvb3AoKTtcblxuICAgICAgICAvLyBHZXQgdGhlIGdhbWUgY2FudmFzIGFuZCBnaXZlIGl0IGEgYmFja2dyb3VuZCBjb2xvclxuICAgICAgICB0aGlzLkdBTUVfQ0FOVkFTID0gPEhUTUxDYW52YXNFbGVtZW50PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiZ2FtZS1jYW52YXNcIik7XG4gICAgICAgIHRoaXMuREVCVUdfQ0FOVkFTID0gPEhUTUxDYW52YXNFbGVtZW50PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiZGVidWctY2FudmFzXCIpO1xuICAgIFxuICAgICAgICAvLyBHaXZlIHRoZSBjYW52YXMgYSBzaXplIGFuZCBnZXQgdGhlIHJlbmRlcmluZyBjb250ZXh0XG4gICAgICAgIHRoaXMuV0lEVEggPSB0aGlzLmdhbWVPcHRpb25zLmNhbnZhc1NpemUueDtcbiAgICAgICAgdGhpcy5IRUlHSFQgPSB0aGlzLmdhbWVPcHRpb25zLmNhbnZhc1NpemUueTtcblxuICAgICAgICAvLyBUaGlzIHN0ZXAgTVVTVCBoYXBwZW4gYmVmb3JlIHRoZSByZXNvdXJjZSBtYW5hZ2VyIGRvZXMgYW55dGhpbmdcbiAgICAgICAgaWYodGhpcy5nYW1lT3B0aW9ucy51c2VXZWJHTCl7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmluZ01hbmFnZXIgPSBuZXcgV2ViR0xSZW5kZXJlcigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyID0gbmV3IENhbnZhc1JlbmRlcmVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbml0aWFsaXplR2FtZVdpbmRvdygpO1xuICAgICAgICB0aGlzLmN0eCA9IHRoaXMucmVuZGVyaW5nTWFuYWdlci5pbml0aWFsaXplQ2FudmFzKHRoaXMuR0FNRV9DQU5WQVMsIHRoaXMuV0lEVEgsIHRoaXMuSEVJR0hUKTtcbiAgICAgICAgdGhpcy5jbGVhckNvbG9yID0gbmV3IENvbG9yKHRoaXMuZ2FtZU9wdGlvbnMuY2xlYXJDb2xvci5yLCB0aGlzLmdhbWVPcHRpb25zLmNsZWFyQ29sb3IuZywgdGhpcy5nYW1lT3B0aW9ucy5jbGVhckNvbG9yLmIpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgZGVidWdnaW5nIGFuZCBzdGF0c1xuICAgICAgICBEZWJ1Zy5pbml0aWFsaXplRGVidWdDYW52YXModGhpcy5ERUJVR19DQU5WQVMsIHRoaXMuV0lEVEgsIHRoaXMuSEVJR0hUKTtcbiAgICAgICAgU3RhdHMuaW5pdFN0YXRzKCk7XG5cbiAgICAgICAgaWYodGhpcy5nYW1lT3B0aW9ucy5zaG93U3RhdHMpIHtcbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIHN0YXRzIG91dHB1dCBhbmQgbWFrZSBpdCBubyBsb25nZXIgaGlkZGVuXG4gICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXRzXCIpLmhpZGRlbiA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2l6ZSB0aGUgdmlld3BvcnQgdG8gdGhlIGdhbWUgY2FudmFzXG4gICAgICAgIGNvbnN0IGNhbnZhc1NpemUgPSBuZXcgVmVjMih0aGlzLldJRFRILCB0aGlzLkhFSUdIVCk7XG4gICAgICAgIHRoaXMudmlld3BvcnQgPSBuZXcgVmlld3BvcnQoY2FudmFzU2l6ZSwgdGhpcy5nYW1lT3B0aW9ucy56b29tTGV2ZWwpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgYWxsIG5lY2Vzc2FyeSBnYW1lIHN1YnN5c3RlbXNcbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlID0gRXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLmlucHV0SGFuZGxlciA9IG5ldyBJbnB1dEhhbmRsZXIodGhpcy5HQU1FX0NBTlZBUyk7XG4gICAgICAgIElucHV0LmluaXRpYWxpemUodGhpcy52aWV3cG9ydCwgdGhpcy5nYW1lT3B0aW9ucy5pbnB1dHMpO1xuICAgICAgICB0aGlzLnJlY29yZGVyID0gbmV3IFJlY29yZGVyKCk7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyID0gbmV3IFNjZW5lTWFuYWdlcih0aGlzLnZpZXdwb3J0LCB0aGlzLnJlbmRlcmluZ01hbmFnZXIpO1xuICAgICAgICB0aGlzLmF1ZGlvTWFuYWdlciA9IEF1ZGlvTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB1cCB0aGUgZ2FtZSB3aW5kb3cgdGhhdCBob2xkcyB0aGUgY2FudmFzZXNcbiAgICAgKi9cbiAgICBwcml2YXRlIGluaXRpYWxpemVHYW1lV2luZG93KCk6IHZvaWQge1xuICAgICAgICBjb25zdCBnYW1lV2luZG93ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJnYW1lLXdpbmRvd1wiKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFNldCB0aGUgaGVpZ2h0IG9mIHRoZSBnYW1lIHdpbmRvd1xuICAgICAgICBnYW1lV2luZG93LnN0eWxlLndpZHRoID0gdGhpcy5XSURUSCArIFwicHhcIjtcbiAgICAgICAgZ2FtZVdpbmRvdy5zdHlsZS5oZWlnaHQgPSB0aGlzLkhFSUdIVCArIFwicHhcIjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgdGhlIFNjZW5lTWFuYWdlciBmcm9tIHRoZSBHYW1lXG4gICAgICogQHJldHVybnMgVGhlIFNjZW5lTWFuYWdlclxuICAgICAqL1xuICAgIGdldFNjZW5lTWFuYWdlcigpOiBTY2VuZU1hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2VuZU1hbmFnZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSBnYW1lXG4gICAgICovXG4gICAgc3RhcnQoSW5pdGlhbFNjZW5lOiBuZXcgKC4uLmFyZ3M6IGFueSkgPT4gU2NlbmUsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgLy8gU2V0IHRoZSB1cGRhdGUgZnVuY3Rpb24gb2YgdGhlIGxvb3BcbiAgICAgICAgdGhpcy5sb29wLmRvVXBkYXRlID0gKGRlbHRhVDogbnVtYmVyKSA9PiB0aGlzLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgcmVuZGVyIGZ1bmN0aW9uIG9mIHRoZSBsb29wXG4gICAgICAgIHRoaXMubG9vcC5kb1JlbmRlciA9ICgpID0+IHRoaXMucmVuZGVyKCk7XG5cbiAgICAgICAgLy8gUHJlbG9hZCByZWdpc3RyeSBpdGVtc1xuICAgICAgICBSZWdpc3RyeU1hbmFnZXIucHJlbG9hZCgpO1xuXG4gICAgICAgIC8vIExvYWQgdGhlIGl0ZW1zIHdpdGggdGhlIHJlc291cmNlIG1hbmFnZXJcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIubG9hZFJlc291cmNlc0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlJ3JlIGRvbmUgbG9hZGluZywgc3RhcnQgdGhlIGxvb3BcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRmluaXNoZWQgUHJlbG9hZCAtIGxvYWRpbmcgZmlyc3Qgc2NlbmVcIik7XG4gICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKEluaXRpYWxTY2VuZSwge30sIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5sb29wLnN0YXJ0KCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgYWxsIG5lY2Vzc2FyeSBzdWJzeXN0ZW1zIG9mIHRoZSBnYW1lLiBEZWZlcnMgc2NlbmUgdXBkYXRlcyB0byB0aGUgc2NlbmVNYW5hZ2VyXG4gICAgICogQHBhcmFtIGRlbHRhVCBUaGUgdGltZSBzaW5lIHRoZSBsYXN0IHVwZGF0ZVxuICAgICAqL1xuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0cnl7XG4gICAgICAgICAgICAvLyBIYW5kbGUgYWxsIGV2ZW50cyB0aGF0IGhhcHBlbmVkIHNpbmNlIHRoZSBzdGFydCBvZiB0aGUgbGFzdCBsb29wXG4gICAgICAgICAgICB0aGlzLmV2ZW50UXVldWUudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgaW5wdXQgZGF0YSBzdHJ1Y3R1cmVzIHNvIGdhbWUgb2JqZWN0cyBjYW4gc2VlIHRoZSBpbnB1dFxuICAgICAgICAgICAgSW5wdXQudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcmVjb3JkaW5nIG9mIHRoZSBnYW1lXG4gICAgICAgICAgICB0aGlzLnJlY29yZGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgYWxsIHNjZW5lc1xuICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSBhbGwgc291bmRzXG4gICAgICAgICAgICB0aGlzLmF1ZGlvTWFuYWdlci51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gTG9hZCBvciB1bmxvYWQgYW55IHJlc291cmNlcyBpZiBuZWVkZWRcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICAgdGhpcy5sb29wLnBhdXNlKCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJVbmNhdWdodCBFcnJvciBpbiBVcGRhdGUgLSBDcmFzaGluZyBncmFjZWZ1bGx5XCIpO1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyB0aGUgY2FudmFzIGFuZCBkZWZlcnMgc2NlbmUgcmVuZGVyaW5nIHRvIHRoZSBzY2VuZU1hbmFnZXIuIFJlbmRlcnMgdGhlIGRlYnVnIGNhbnZhc1xuICAgICAqL1xuICAgIHJlbmRlcigpOiB2b2lkIHtcbiAgICAgICAgdHJ5e1xuICAgICAgICAgICAgLy8gQ2xlYXIgdGhlIGNhbnZhc2VzXG4gICAgICAgICAgICBEZWJ1Zy5jbGVhckNhbnZhcygpO1xuXG4gICAgICAgICAgICB0aGlzLnJlbmRlcmluZ01hbmFnZXIuY2xlYXIodGhpcy5jbGVhckNvbG9yKTtcblxuICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIucmVuZGVyKCk7XG5cbiAgICAgICAgICAgIC8vIEhhY2t5IGRlYnVnIG1vZGVcbiAgICAgICAgICAgIGlmKElucHV0LmlzS2V5SnVzdFByZXNzZWQoXCJnXCIpKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dEZWJ1ZyA9ICF0aGlzLnNob3dEZWJ1ZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRGVidWcgcmVuZGVyXG4gICAgICAgICAgICBpZih0aGlzLnNob3dEZWJ1Zyl7XG4gICAgICAgICAgICAgICAgRGVidWcucmVuZGVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHRoaXMuc2hvd1N0YXRzKXtcbiAgICAgICAgICAgICAgICBTdGF0cy5yZW5kZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIHRoaXMubG9vcC5wYXVzZSgpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiVW5jYXVnaHQgRXJyb3IgaW4gUmVuZGVyIC0gQ3Jhc2hpbmcgZ3JhY2VmdWxseVwiKTtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IE51bGxGdW5jIGZyb20gXCIuLi9EYXRhVHlwZXMvRnVuY3Rpb25zL051bGxGdW5jXCI7XG5cbi8qKlxuICogVGhlIG1haW4gZ2FtZSBsb29wIG9mIHRoZSBnYW1lLiBLZWVwcyB0cmFjayBvZiBmcHMgYW5kIGhhbmRsZXMgc2NoZWR1bGluZyBvZiB1cGRhdGVzIGFuZCByZW5kZXJpbmcuXG4gKiBUaGlzIGNsYXNzIGlzIGxlZnQgYWJzdHJhY3QsIHNvIHRoYXQgYSBzdWJjbGFzcyBjYW4gaGFuZGxlIGV4YWN0bHkgaG93IHRoZSBsb29wIGlzIHNjaGVkdWxlZC5cbiAqIEZvciBhbiBleGFtcGxlIG9mIGRpZmZlcmVudCB0eXBlcyBvZiBnYW1lIGxvb3Agc2NoZWR1bGluZywgY2hlY2sgb3V0IEBsaW5rKEdhbWUgUHJvZ3JhbW1pbmcgUGF0dGVybnMpKGh0dHBzOi8vZ2FtZXByb2dyYW1taW5ncGF0dGVybnMuY29tL2dhbWUtbG9vcC5odG1sKVxuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBHYW1lTG9vcCB7XG5cblx0LyoqIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gYW4gdXBkYXRlIG9jY3VycyAqL1xuXHRwcm90ZWN0ZWQgX2RvVXBkYXRlOiBGdW5jdGlvbiA9IE51bGxGdW5jO1xuXG5cdHNldCBkb1VwZGF0ZSh1cGRhdGU6IEZ1bmN0aW9uKXtcblx0XHR0aGlzLl9kb1VwZGF0ZSA9IHVwZGF0ZTtcblx0fVxuXG5cdC8qKiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIGEgcmVuZGVyIG9jY3VycyAqL1xuXHRwcm90ZWN0ZWQgX2RvUmVuZGVyOiBGdW5jdGlvbiA9IE51bGxGdW5jO1xuXG5cblx0c2V0IGRvUmVuZGVyKHJlbmRlcjogRnVuY3Rpb24pe1xuXHRcdHRoaXMuX2RvUmVuZGVyID0gcmVuZGVyO1xuXHR9XG5cdFxuXHQvKipcblx0ICogUmV0cmlldmVzIHRoZSBjdXJyZW50IEZQUyBvZiB0aGUgZ2FtZVxuXHQgKi9cblx0YWJzdHJhY3QgZ2V0RlBTKCk6IG51bWJlcjtcblxuXHQvKipcbiAgICAgKiBTdGFydHMgdXAgdGhlIGdhbWUgbG9vcFxuICAgICAqL1xuXHRhYnN0cmFjdCBzdGFydCgpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBQYXVzZXMgdGhlIGdhbWUgbG9vcCwgdXN1YWxseSBmb3IgYW4gZXJyb3IgY29uZGl0aW9uLlxuXHQgKi9cblx0YWJzdHJhY3QgcGF1c2UoKTogdm9pZDtcblxuXHQvKipcblx0ICogUmVzdW1lcyB0aGUgZ2FtZSBsb29wLlxuXHQgKi9cblx0YWJzdHJhY3QgcmVzdW1lKCk6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIGZpcnN0IGZyYW1lIG9mIHRoZSBnYW1lLiBObyB1cGRhdGUgb2NjdXJzIGhlcmUsIG9ubHkgYSByZW5kZXIuXG5cdCAqIFRoaXMgaXMgbmVlZGVkIHRvIGluaXRpYWxpemUgZGVsdGEgdGltZSB2YWx1ZXNcblx0ICogQHBhcmFtIHRpbWVzdGFtcCBUaGUgdGltZXN0YW1wIG9mIHRoZSBmcmFtZS4gVGhpcyBpcyByZWNlaXZlZCBmcm9tIHRoZSBicm93c2VyXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgZG9GaXJzdEZyYW1lKHRpbWVzdGFtcDogbnVtYmVyKTogdm9pZDtcblxuXHQvKipcblx0ICogUnVuIGJlZm9yZSBhbnkgdXBkYXRlcyBvciB0aGUgcmVuZGVyIG9mIGEgZnJhbWUuXG5cdCAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIHRpbWVzdGFtcCBvZiB0aGUgZnJhbWUuIFRoaXMgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgYnJvd3NlclxuXHQgKi9cblx0cHJvdGVjdGVkIGFic3RyYWN0IHN0YXJ0RnJhbWUodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBUaGUgY29yZSBvZiB0aGUgZnJhbWUsIHdoZXJlIGFueSBuZWNlc3NhcnkgdXBkYXRlcyBvY2N1ciwgYW5kIHdoZXJlIGEgcmVuZGVyIGhhcHBlbnNcblx0ICogQHBhcmFtIHRpbWVzdGFtcCBUaGUgdGltZXN0YW1wIG9mIHRoZSBmcmFtZS4gVGhpcyBpcyByZWNlaXZlZCBmcm9tIHRoZSBicm93c2VyXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgZG9GcmFtZSh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFdyYXBzIHVwIHRoZSBmcmFtZVxuXHQgKiBAcGFyYW0gcGFuaWMgV2hldGhlciBvciBub3QgdGhlIHVwZGF0ZSBjeWNsZSBwYW5pY2tlZC4gVGhpcyBoYXBwZW5zIHdoZW4gdG9vIG1hbnkgdXBkYXRlcyB0cnkgdG8gaGFwcGVuIGluIGEgc2luZ2xlIGZyYW1lXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgZmluaXNoRnJhbWUocGFuaWM6IGJvb2xlYW4pOiB2b2lkO1xufSIsIi8vIEBpZ25vcmVQYWdlXG5cbi8qKiBUaGUgb3B0aW9ucyBmb3IgaW5pdGlhbGl6aW5nIHRoZSBAcmVmZXJlbmNlW0dhbWVMb29wXSAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2FtZU9wdGlvbnMge1xuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgdmlld3BvcnQgKi9cbiAgICBjYW52YXNTaXplOiB7eDogbnVtYmVyLCB5OiBudW1iZXJ9O1xuXG4gICAgLyogVGhlIGRlZmF1bHQgbGV2ZWwgb2Ygem9vbSAqL1xuICAgIHpvb21MZXZlbDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBjb2xvciB0byBjbGVhciB0aGUgY2FudmFzIHRvIGVhY2ggZnJhbWUgKi9cbiAgICBjbGVhckNvbG9yOiB7cjogbnVtYmVyLCBnOiBudW1iZXIsIGI6IG51bWJlcn1cblxuICAgIC8qIEEgbGlzdCBvZiBpbnB1dCBiaW5kaW5ncyAqL1xuICAgIGlucHV0czogQXJyYXk8e25hbWU6IHN0cmluZywga2V5czogQXJyYXk8c3RyaW5nPn0+O1xuXG4gICAgLyogV2hldGhlciBvciBub3QgdGhlIGRlYnVnIHJlbmRlcmluZyBzaG91bGQgb2NjdXIgKi9cbiAgICBzaG93RGVidWc6IGJvb2xlYW47XG5cbiAgICAvKiBXaGV0aGVyIG9yIG5vdCB0aGUgc3RhdHMgcmVuZGVyaW5nIHNob3VsZCBvY2N1ciAqL1xuICAgIHNob3dTdGF0czogYm9vbGVhbjtcblxuICAgIC8qIFdoZXRoZXIgb3Igbm90IHRvIHVzZSB3ZWJHTCAqL1xuICAgIHVzZVdlYkdMOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogUGFyc2VzIHRoZSBkYXRhIGluIHRoZSByYXcgb3B0aW9ucyBvYmplY3RcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgZ2FtZSBvcHRpb25zIGFzIGEgUmVjb3JkXG4gICAgICogQHJldHVybnMgQSB2ZXJzaW9uIG9mIHRoZSBvcHRpb25zIGNvbnZlcnRlZCB0byBhIEdhbWVPcHRpb25zIG9iamVjdFxuICAgICAqL1xuICAgIHN0YXRpYyBwYXJzZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR2FtZU9wdGlvbnMge1xuICAgICAgICBsZXQgZ09wdCA9IG5ldyBHYW1lT3B0aW9ucygpO1xuXG4gICAgICAgIGdPcHQuY2FudmFzU2l6ZSA9IG9wdGlvbnMuY2FudmFzU2l6ZSA/IG9wdGlvbnMuY2FudmFzU2l6ZSA6IHt4OiA4MDAsIHk6IDYwMH07XG4gICAgICAgIGdPcHQuem9vbUxldmVsID0gb3B0aW9ucy56b29tTGV2ZWwgPyBvcHRpb25zLnpvb21MZXZlbCA6IDE7XG4gICAgICAgIGdPcHQuY2xlYXJDb2xvciA9IG9wdGlvbnMuY2xlYXJDb2xvciA/IG9wdGlvbnMuY2xlYXJDb2xvciA6IHtyOiAyNTUsIGc6IDI1NSwgYjogMjU1fTtcbiAgICAgICAgZ09wdC5pbnB1dHMgPSBvcHRpb25zLmlucHV0cyA/IG9wdGlvbnMuaW5wdXRzIDogW107XG4gICAgICAgIGdPcHQuc2hvd0RlYnVnID0gISFvcHRpb25zLnNob3dEZWJ1ZztcbiAgICAgICAgZ09wdC5zaG93U3RhdHMgPSAhIW9wdGlvbnMuc2hvd1N0YXRzO1xuICAgICAgICBnT3B0LnVzZVdlYkdMID0gISFvcHRpb25zLnVzZVdlYkdMO1xuXG4gICAgICAgIHJldHVybiBnT3B0O1xuICAgIH1cbn0iLCJpbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4vR2FtZU5vZGVcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFJlZ2lvbiBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUmVnaW9uXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdCBpbiB0aGUgZ2FtZSB3b3JsZCB0aGF0IGNhbiBiZSBkcmF3biB0byB0aGUgc2NyZWVuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIENhbnZhc05vZGUgZXh0ZW5kcyBHYW1lTm9kZSBpbXBsZW1lbnRzIFJlZ2lvbiB7XG5cdHByaXZhdGUgX3NpemU6IFZlYzI7XG5cdHByaXZhdGUgX3NjYWxlOiBWZWMyO1xuXHRwcml2YXRlIF9ib3VuZGFyeTogQUFCQjtcblx0cHJpdmF0ZSBfaGFzQ3VzdG9tU2hhZGVyOiBib29sZWFuO1xuXHRwcml2YXRlIF9jdXN0b21TaGFkZXJLZXk6IHN0cmluZztcblx0cHJpdmF0ZSBfYWxwaGE6IG51bWJlcjtcblxuXHQvKiogQSBmbGFnIGZvciB3aGV0aGVyIG9yIG5vdCB0aGUgQ2FudmFzTm9kZSBpcyB2aXNpYmxlICovXG5cdHZpc2libGU6IGJvb2xlYW4gPSB0cnVlO1xuXHRcblx0Y29uc3RydWN0b3IoKXtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMuX3NpemUgPSBuZXcgVmVjMigwLCAwKTtcblx0XHR0aGlzLl9zaXplLnNldE9uQ2hhbmdlKCgpID0+IHRoaXMuc2l6ZUNoYW5nZWQoKSk7XG5cdFx0dGhpcy5fc2NhbGUgPSBuZXcgVmVjMigxLCAxKTtcblx0XHR0aGlzLl9zY2FsZS5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnNjYWxlQ2hhbmdlZCgpKTtcblx0XHR0aGlzLl9ib3VuZGFyeSA9IG5ldyBBQUJCKCk7XG5cdFx0dGhpcy51cGRhdGVCb3VuZGFyeSgpO1xuXG5cdFx0dGhpcy5faGFzQ3VzdG9tU2hhZGVyID0gZmFsc2U7XG5cdH1cblxuXHRnZXQgYWxwaGEoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5fYWxwaGE7XG5cdH1cblxuXHRzZXQgYWxwaGEoYTogbnVtYmVyKSB7XG5cdFx0dGhpcy5fYWxwaGEgPSBhO1xuXHR9XG5cblx0Z2V0IHNpemUoKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuX3NpemU7XG5cdH1cblxuXHRzZXQgc2l6ZShzaXplOiBWZWMyKXtcblx0XHR0aGlzLl9zaXplID0gc2l6ZTtcblx0XHQvLyBFbnRlciBhcyBhIGxhbWJkYSB0byBiaW5kIFwidGhpc1wiXG5cdFx0dGhpcy5fc2l6ZS5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnNpemVDaGFuZ2VkKCkpO1xuXHRcdHRoaXMuc2l6ZUNoYW5nZWQoKTtcblx0fVxuXG5cdGdldCBzY2FsZSgpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5fc2NhbGU7XG5cdH1cblxuXHRzZXQgc2NhbGUoc2NhbGU6IFZlYzIpe1xuXHRcdHRoaXMuX3NjYWxlID0gc2NhbGU7XG5cdFx0Ly8gRW50ZXIgYXMgYSBsYW1iZGEgdG8gYmluZCBcInRoaXNcIlxuXHRcdHRoaXMuX3NjYWxlLnNldE9uQ2hhbmdlKCgpID0+IHRoaXMuc2NhbGVDaGFuZ2VkKCkpO1xuXHRcdHRoaXMuc2NhbGVDaGFuZ2VkKCk7XG5cdH1cblxuXHRzZXQgc2NhbGVYKHZhbHVlOiBudW1iZXIpIHtcblx0XHR0aGlzLnNjYWxlLnggPSB2YWx1ZTtcblx0fVxuXG5cdHNldCBzY2FsZVkodmFsdWU6IG51bWJlcikge1xuXHRcdHRoaXMuc2NhbGUueSA9IHZhbHVlO1xuXHR9XG5cblx0Z2V0IGhhc0N1c3RvbVNoYWRlcigpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5faGFzQ3VzdG9tU2hhZGVyO1xuXHR9XG5cblx0Z2V0IGN1c3RvbVNoYWRlcktleSgpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLl9jdXN0b21TaGFkZXJLZXk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0cHJvdGVjdGVkIHBvc2l0aW9uQ2hhbmdlZCgpOiB2b2lkIHtcblx0XHRzdXBlci5wb3NpdGlvbkNoYW5nZWQoKTtcblx0XHR0aGlzLnVwZGF0ZUJvdW5kYXJ5KCk7XG5cdH1cblxuXHQvKiogQ2FsbGVkIGlmIHRoZSBzaXplIHZlY3RvciBpcyBjaGFuZ2VkIG9yIHJlcGxhY2VkLiAqL1xuXHRwcm90ZWN0ZWQgc2l6ZUNoYW5nZWQoKTogdm9pZCB7XG5cdFx0dGhpcy51cGRhdGVCb3VuZGFyeSgpO1xuXHR9XG5cblx0LyoqIENhbGxlZCBpZiB0aGUgc2NhbGUgdmVjdG9yIGlzIGNoYW5nZWQgb3IgcmVwbGFjZWQgKi9cblx0cHJvdGVjdGVkIHNjYWxlQ2hhbmdlZCgpOiB2b2lkIHtcblx0XHR0aGlzLnVwZGF0ZUJvdW5kYXJ5KCk7XG5cdH1cblxuXHQvLyBAZG9jSWdub3JlXG5cdC8qKiBDYWxsZWQgaWYgdGhlIHBvc2l0aW9uLCBzaXplLCBvciBzY2FsZSBvZiB0aGUgQ2FudmFzTm9kZSBpcyBjaGFuZ2VkLiBVcGRhdGVzIHRoZSBib3VuZGFyeS4gKi9cblx0cHJpdmF0ZSB1cGRhdGVCb3VuZGFyeSgpOiB2b2lkIHtcblx0XHR0aGlzLl9ib3VuZGFyeS5jZW50ZXIuc2V0KHRoaXMucG9zaXRpb24ueCwgdGhpcy5wb3NpdGlvbi55KTtcblx0XHR0aGlzLl9ib3VuZGFyeS5oYWxmU2l6ZS5zZXQodGhpcy5zaXplLngqdGhpcy5zY2FsZS54LzIsIHRoaXMuc2l6ZS55KnRoaXMuc2NhbGUueS8yKTtcblx0fVxuXG5cdGdldCBib3VuZGFyeSgpOiBBQUJCIHtcblx0XHRyZXR1cm4gdGhpcy5fYm91bmRhcnk7XG5cdH1cblxuXHRnZXQgc2l6ZVdpdGhab29tKCk6IFZlYzIge1xuXHRcdGxldCB6b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcblxuXHRcdHJldHVybiB0aGlzLmJvdW5kYXJ5LmhhbGZTaXplLmNsb25lKCkuc2NhbGVkKHpvb20sIHpvb20pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBjdXN0b20gc2hhZGVyIHRvIHRoaXMgQ2FudmFzTm9kZVxuXHQgKiBAcGFyYW0ga2V5IFRoZSByZWdpc3RyeSBrZXkgb2YgdGhlIFNoYWRlclR5cGVcblx0ICovXG5cdHVzZUN1c3RvbVNoYWRlcihrZXk6IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMuX2hhc0N1c3RvbVNoYWRlciA9IHRydWU7XG5cdFx0dGhpcy5fY3VzdG9tU2hhZGVyS2V5ID0ga2V5O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcG9pbnQgKHgsIHkpIGlzIGluc2lkZSBvZiB0aGlzIGNhbnZhcyBvYmplY3Rcblx0ICogQHBhcmFtIHggVGhlIHggcG9zaXRpb24gb2YgdGhlIHBvaW50XG5cdCAqIEBwYXJhbSB5IFRoZSB5IHBvc2l0aW9uIG9mIHRoZSBwb2ludFxuXHQgKiBAcmV0dXJucyBBIGZsYWcgcmVwcmVzZW50aW5nIHdoZXRoZXIgb3Igbm90IHRoaXMgbm9kZSBjb250YWlucyB0aGUgcG9pbnQuXG5cdCAqL1xuXHRjb250YWlucyh4OiBudW1iZXIsIHk6IG51bWJlcik6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLl9ib3VuZGFyeS5jb250YWluc1BvaW50KG5ldyBWZWMyKHgsIHkpKTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRkZWJ1Z1JlbmRlcigpOiB2b2lkIHtcblx0XHREZWJ1Zy5kcmF3Qm94KHRoaXMucmVsYXRpdmVQb3NpdGlvbiwgdGhpcy5zaXplV2l0aFpvb20sIGZhbHNlLCBDb2xvci5CTFVFKTtcblx0XHRzdXBlci5kZWJ1Z1JlbmRlcigpO1xuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uL0V2ZW50cy9SZWNlaXZlclwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVyXCI7XG5pbXBvcnQgQUkgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FJXCI7XG5pbXBvcnQgUGh5c2ljYWwgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1BoeXNpY2FsXCI7XG5pbXBvcnQgUG9zaXRpb25lZCBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUG9zaXRpb25lZFwiO1xuaW1wb3J0IHsgaXNSZWdpb24gfSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUmVnaW9uXCI7XG5pbXBvcnQgVW5pcXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VbmlxdWVcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgRGVidWdSZW5kZXJhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9EZWJ1Z1JlbmRlcmFibGVcIjtcbmltcG9ydCBBY3RvciBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvQWN0b3JcIjtcbmltcG9ydCBTaGFwZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9TaGFwZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IE5hdmlnYXRpb25QYXRoIGZyb20gXCIuLi9QYXRoZmluZGluZy9OYXZpZ2F0aW9uUGF0aFwiO1xuaW1wb3J0IFR3ZWVuQ29udHJvbGxlciBmcm9tIFwiLi4vUmVuZGVyaW5nL0FuaW1hdGlvbnMvVHdlZW5Db250cm9sbGVyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgQ2lyY2xlIGZyb20gXCIuLi9EYXRhVHlwZXMvU2hhcGVzL0NpcmNsZVwiO1xuaW1wb3J0IEdvYXBBSSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvR29hcEFJXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdCBpbiB0aGUgZ2FtZSB3b3JsZC5cbiAqIFRvIGNvbnN0cnVjdCBHYW1lTm9kZXMsIHNlZSB0aGUgQHJlZmVyZW5jZVtTY2VuZV0gZG9jdW1lbnRhdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgR2FtZU5vZGUgaW1wbGVtZW50cyBQb3NpdGlvbmVkLCBVbmlxdWUsIFVwZGF0ZWFibGUsIFBoeXNpY2FsLCBBY3RvciwgRGVidWdSZW5kZXJhYmxlIHtcblx0LyotLS0tLS0tLS0tIFBPU0lUSU9ORUQgLS0tLS0tLS0tLSovXG5cdHByaXZhdGUgX3Bvc2l0aW9uOiBWZWMyO1xuXG5cdC8qLS0tLS0tLS0tLSBVTklRVUUgLS0tLS0tLS0tLSovXG5cdHByaXZhdGUgX2lkOiBudW1iZXI7XG5cblx0LyotLS0tLS0tLS0tIFBIWVNJQ0FMIC0tLS0tLS0tLS0qL1xuXHRoYXNQaHlzaWNzOiBib29sZWFuID0gZmFsc2U7XG5cdG1vdmluZzogYm9vbGVhbiA9IGZhbHNlO1xuXHRmcm96ZW46IGJvb2xlYW4gPSBmYWxzZTtcblx0b25Hcm91bmQ6IGJvb2xlYW4gPSBmYWxzZTtcblx0b25XYWxsOiBib29sZWFuID0gZmFsc2U7XG5cdG9uQ2VpbGluZzogYm9vbGVhbiA9IGZhbHNlO1xuXHRhY3RpdmU6IGJvb2xlYW4gPSBmYWxzZTtcblx0Y29sbGlzaW9uU2hhcGU6IFNoYXBlO1xuXHRjb2xsaWRlck9mZnNldDogVmVjMjtcblx0aXNTdGF0aWM6IGJvb2xlYW47XG5cdGlzQ29sbGlkYWJsZTogYm9vbGVhbjtcblx0aXNUcmlnZ2VyOiBib29sZWFuO1xuXHR0cmlnZ2VyTWFzazogbnVtYmVyO1xuXHR0cmlnZ2VyRW50ZXJzOiBBcnJheTxzdHJpbmc+O1xuXHR0cmlnZ2VyRXhpdHM6IEFycmF5PHN0cmluZz47XG5cdF92ZWxvY2l0eTogVmVjMjtcblx0c3dlcHRSZWN0OiBBQUJCO1xuXHRjb2xsaWRlZFdpdGhUaWxlbWFwOiBib29sZWFuO1xuXHRncm91cDogbnVtYmVyO1xuXHRpc1BsYXllcjogYm9vbGVhbjtcblx0aXNDb2xsaWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHQvKi0tLS0tLS0tLS0gQUNUT1IgLS0tLS0tLS0tLSovXG5cdF9haTogQUkgfCBHb2FwQUk7XG5cdGFpQWN0aXZlOiBib29sZWFuO1xuXHRwYXRoOiBOYXZpZ2F0aW9uUGF0aDtcblx0cGF0aGZpbmRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHQvKi0tLS0tLS0tLS0gR0VORVJBTCAtLS0tLS0tLS0tKi9cblx0LyoqIEFuIGV2ZW50IHJlY2VpdmVyLiAqL1xuXHRwcm90ZWN0ZWQgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuXHQvKiogQW4gZXZlbnQgZW1pdHRlci4gKi9cblx0cHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cdC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgc2NlbmUgdGhpcyBHYW1lTm9kZSBpcyBhIHBhcnQgb2YuICovXG5cdHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cdC8qKiBUaGUgdmlzdWFsIGxheWVyIHRoaXMgR2FtZU5vZGUgcmVzaWRlcyBpbi4gKi9cblx0cHJvdGVjdGVkIGxheWVyOiBMYXllcjtcblx0LyoqIEEgdXRpbGl0eSB0aGF0IGFsbG93cyB0aGUgdXNlIG9mIHR3ZWVucyBvbiB0aGlzIEdhbWVOb2RlICovXG5cdHR3ZWVuczogVHdlZW5Db250cm9sbGVyO1xuXHQvKiogQSB0d2VlbmFibGUgcHJvcGVydHkgZm9yIHJvdGF0aW9uLiBEb2VzIG5vdCBhZmZlY3QgdGhlIGJvdW5kaW5nIGJveCBvZiB0aGlzIEdhbWVOb2RlIC0gT25seSByZW5kZXJpbmcuICovXG5cdHJvdGF0aW9uOiBudW1iZXI7XG5cdC8qKiBUaGUgb3BhY2l0eSB2YWx1ZSBvZiB0aGlzIEdhbWVOb2RlICovXG5cdGFic3RyYWN0IHNldCBhbHBoYShhOiBudW1iZXIpO1xuXG5cdGFic3RyYWN0IGdldCBhbHBoYSgpOiBudW1iZXI7XG5cblx0Ly8gQ29uc3RydWN0b3IgZG9jcyBhcmUgaWdub3JlZCwgYXMgdGhlIHVzZXIgc2hvdWxkIE5PVCBjcmVhdGUgbmV3IEdhbWVOb2RlcyB3aXRoIGEgcmF3IGNvbnN0cnVjdG9yXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5fcG9zaXRpb24gPSBuZXcgVmVjMigwLCAwKTtcblx0XHR0aGlzLl9wb3NpdGlvbi5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnBvc2l0aW9uQ2hhbmdlZCgpKTtcblx0XHR0aGlzLnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG5cdFx0dGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcblx0XHR0aGlzLnR3ZWVucyA9IG5ldyBUd2VlbkNvbnRyb2xsZXIodGhpcyk7XG5cdFx0dGhpcy5yb3RhdGlvbiA9IDA7XG5cdH1cblxuXHRkZXN0cm95KCl7XG5cdFx0dGhpcy50d2VlbnMuZGVzdHJveSgpO1xuXHRcdHRoaXMucmVjZWl2ZXIuZGVzdHJveSgpO1xuXG5cdFx0aWYodGhpcy5oYXNQaHlzaWNzKXtcblx0XHRcdHRoaXMucmVtb3ZlUGh5c2ljcygpO1xuXHRcdH1cblxuXHRcdGlmKHRoaXMuX2FpKXtcblx0XHRcdHRoaXMuX2FpLmRlc3Ryb3koKTtcblx0XHRcdGRlbGV0ZSB0aGlzLl9haTtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0QUlNYW5hZ2VyKCkucmVtb3ZlQWN0b3IodGhpcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zY2VuZS5yZW1vdmUodGhpcyk7XG5cblx0XHR0aGlzLmxheWVyLnJlbW92ZU5vZGUodGhpcyk7XG5cdH1cblxuXHQvKi0tLS0tLS0tLS0gUE9TSVRJT05FRCAtLS0tLS0tLS0tKi9cblx0Z2V0IHBvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLl9wb3NpdGlvbjtcblx0fVxuXG5cdHNldCBwb3NpdGlvbihwb3M6IFZlYzIpIHtcblx0XHR0aGlzLl9wb3NpdGlvbiA9IHBvcztcblx0XHR0aGlzLl9wb3NpdGlvbi5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnBvc2l0aW9uQ2hhbmdlZCgpKTtcblx0XHR0aGlzLnBvc2l0aW9uQ2hhbmdlZCgpO1xuXHR9XG5cblx0Z2V0IHJlbGF0aXZlUG9zaXRpb24oKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuaW5SZWxhdGl2ZUNvb3JkaW5hdGVzKHRoaXMucG9zaXRpb24pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgcG9pbnQgdG8gY29vcmRpbmF0ZXMgcmVsYXRpdmUgdG8gdGhlIHpvb20gYW5kIG9yaWdpbiBvZiB0aGlzIG5vZGVcblx0ICogQHBhcmFtIHBvaW50IFRoZSBwb2ludCB0byBjb252ZXJcblx0ICogQHJldHVybnMgQSBuZXcgVmVjMiByZXByZXNlbnRpbmcgdGhlIHBvaW50IGluIHJlbGF0aXZlIGNvb3JkaW5hdGVzXG5cdCAqL1xuXHRpblJlbGF0aXZlQ29vcmRpbmF0ZXMocG9pbnQ6IFZlYzIpOiBWZWMyIHtcblx0XHRsZXQgb3JpZ2luID0gdGhpcy5zY2VuZS5nZXRWaWV3VHJhbnNsYXRpb24odGhpcyk7XG5cdFx0bGV0IHpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuXHRcdHJldHVybiBwb2ludC5jbG9uZSgpLnN1YihvcmlnaW4pLnNjYWxlKHpvb20pO1xuXHR9XG5cblx0LyotLS0tLS0tLS0tIFVOSVFVRSAtLS0tLS0tLS0tKi9cblx0Z2V0IGlkKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMuX2lkO1xuXHR9XG5cblx0c2V0IGlkKGlkOiBudW1iZXIpIHtcblx0XHQvLyBpZCBjYW4gb25seSBiZSBzZXQgb25jZVxuXHRcdGlmKHRoaXMuX2lkID09PSB1bmRlZmluZWQpe1xuXHRcdFx0dGhpcy5faWQgPSBpZDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgXCJBdHRlbXB0ZWQgdG8gYXNzaWduIGlkIHRvIG9iamVjdCB0aGF0IGFscmVhZHkgaGFzIGlkLlwiXG5cdFx0fVxuXHR9XG5cblx0LyotLS0tLS0tLS0tIFBIWVNJQ0FMIC0tLS0tLS0tLS0qL1xuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG4gICAgICogQHBhcmFtIHZlbG9jaXR5IFRoZSB2ZWxvY2l0eSB3aXRoIHdoaWNoIHRvIG1vdmUgdGhlIG9iamVjdC5cbiAgICAgKi9cblx0bW92ZSh2ZWxvY2l0eTogVmVjMik6IHZvaWQge1xuXHRcdGlmKHRoaXMuZnJvemVuKSByZXR1cm47XG5cdFx0dGhpcy5tb3ZpbmcgPSB0cnVlO1xuXHRcdHRoaXMuX3ZlbG9jaXR5ID0gdmVsb2NpdHk7XG5cdH07XG5cblx0bW92ZU9uUGF0aChzcGVlZDogbnVtYmVyLCBwYXRoOiBOYXZpZ2F0aW9uUGF0aCk6IHZvaWQge1xuXHRcdGlmKHRoaXMuZnJvemVuKSByZXR1cm47XG5cdFx0dGhpcy5wYXRoID0gcGF0aDtcblx0XHRsZXQgZGlyID0gcGF0aC5nZXRNb3ZlRGlyZWN0aW9uKHRoaXMpO1xuXHRcdHRoaXMubW92aW5nID0gdHJ1ZTtcblx0XHR0aGlzLnBhdGhmaW5kaW5nID0gdHJ1ZTtcblx0XHR0aGlzLl92ZWxvY2l0eSA9IGRpci5zY2FsZShzcGVlZCk7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gdmVsb2NpdHkgVGhlIHZlbG9jaXR5IHdpdGggd2hpY2ggdGhlIG9iamVjdCB3aWxsIG1vdmUuXG4gICAgICovXG5cdGZpbmlzaE1vdmUoKTogdm9pZCB7XG5cdFx0dGhpcy5tb3ZpbmcgPSBmYWxzZTtcblx0XHR0aGlzLnBvc2l0aW9uLmFkZCh0aGlzLl92ZWxvY2l0eSk7XG5cdFx0aWYodGhpcy5wYXRoZmluZGluZyl7XG5cdFx0XHR0aGlzLnBhdGguaGFuZGxlUGF0aFByb2dyZXNzKHRoaXMpO1xuXHRcdFx0dGhpcy5wYXRoID0gbnVsbDtcblx0XHRcdHRoaXMucGF0aGZpbmRpbmcgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG5cdCAqIEBwYXJhbSBjb2xsaXNpb25TaGFwZSBUaGUgY29sbGlkZXIgZm9yIHRoaXMgb2JqZWN0LiBJZiB0aGlzIGhhcyBhIHJlZ2lvbiAoaW1wbGVtZW50cyBSZWdpb24pLFxuXHQgKiBpdCB3aWxsIGJlIHVzZWQgd2hlbiBubyBjb2xsaXNpb24gc2hhcGUgaXMgc3BlY2lmaWVkIChvciBpZiBjb2xsaXNpb24gc2hhcGUgaXMgbnVsbCkuXG5cdCAqIEBwYXJhbSBpc0NvbGxpZGFibGUgV2hldGhlciB0aGlzIGlzIGNvbGxpZGFibGUgb3Igbm90LiBUcnVlIGJ5IGRlZmF1bHQuXG5cdCAqIEBwYXJhbSBpc1N0YXRpYyBXaGV0aGVyIHRoaXMgaXMgc3RhdGljIG9yIG5vdC4gRmFsc2UgYnkgZGVmYXVsdFxuXHQgKi9cblx0YWRkUGh5c2ljcyhjb2xsaXNpb25TaGFwZT86IFNoYXBlLCBjb2xsaWRlck9mZnNldD86IFZlYzIsIGlzQ29sbGlkYWJsZTogYm9vbGVhbiA9IHRydWUsIGlzU3RhdGljOiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcblx0XHQvLyBJbml0aWFsaXplIHRoZSBwaHlzaWNzIHZhcmlhYmxlc1xuXHRcdHRoaXMuaGFzUGh5c2ljcyA9IHRydWU7XG5cdFx0dGhpcy5tb3ZpbmcgPSBmYWxzZTtcblx0XHR0aGlzLm9uR3JvdW5kID0gZmFsc2U7XG5cdFx0dGhpcy5vbldhbGwgPSBmYWxzZTtcblx0XHR0aGlzLm9uQ2VpbGluZyA9IGZhbHNlO1xuXHRcdHRoaXMuYWN0aXZlID0gdHJ1ZTtcblx0XHR0aGlzLmlzQ29sbGlkYWJsZSA9IGlzQ29sbGlkYWJsZTtcblx0XHR0aGlzLmlzU3RhdGljID0gaXNTdGF0aWM7XG5cdFx0dGhpcy5pc1RyaWdnZXIgPSBmYWxzZTtcblx0XHR0aGlzLnRyaWdnZXJNYXNrID0gMDtcblx0XHR0aGlzLnRyaWdnZXJFbnRlcnMgPSBuZXcgQXJyYXkoMzIpO1xuXHRcdHRoaXMudHJpZ2dlckV4aXRzID0gbmV3IEFycmF5KDMyKTtcblx0XHR0aGlzLl92ZWxvY2l0eSA9IFZlYzIuWkVSTztcblx0XHR0aGlzLnN3ZXB0UmVjdCA9IG5ldyBBQUJCKCk7XG5cdFx0dGhpcy5jb2xsaWRlZFdpdGhUaWxlbWFwID0gZmFsc2U7XG5cdFx0dGhpcy5ncm91cCA9IC0xO1x0XHRcdFx0XHQvLyBUaGUgZGVmYXVsdCBncm91cCwgY29sbGlkZXMgd2l0aCBldmVyeXRoaW5nXG5cblx0XHQvLyBTZXQgdGhlIGNvbGxpc2lvbiBzaGFwZSBpZiBwcm92aWRlZCwgb3Igc2ltcGx5IHVzZSB0aGUgdGhlIHJlZ2lvbiBpZiB0aGVyZSBpcyBvbmUuXG5cdFx0aWYoY29sbGlzaW9uU2hhcGUpe1xuXHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZSA9IGNvbGxpc2lvblNoYXBlO1xuXHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIgPSB0aGlzLnBvc2l0aW9uO1xuXHRcdH0gZWxzZSBpZiAoaXNSZWdpb24odGhpcykpIHtcblx0XHRcdC8vIElmIHRoZSBnYW1lbm9kZSBoYXMgYSByZWdpb24gYW5kIG5vIG90aGVyIGlzIHNwZWNpZmllZCwgdXNlIHRoYXRcblx0XHRcdHRoaXMuY29sbGlzaW9uU2hhcGUgPSAoPGFueT50aGlzKS5ib3VuZGFyeS5jbG9uZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aHJvdyBcIk5vIGNvbGxpc2lvbiBzaGFwZSBzcGVjaWZpZWQgZm9yIHBoeXNpY3Mgb2JqZWN0LlwiXG5cdFx0fVxuXG5cdFx0Ly8gSWYgd2Ugd2VyZSBwcm92aWRlZCB3aXRoIGEgY29sbGlkZXIgb2Zmc2V0LCBzZXQgaXQuIE90aGVyd2lzZSB0aGVyZSBpcyBubyBvZmZzZXQsIHNvIHVzZSB0aGUgemVybyB2ZWN0b3Jcblx0XHRpZihjb2xsaWRlck9mZnNldCl7XG5cdFx0XHR0aGlzLmNvbGxpZGVyT2Zmc2V0ID0gY29sbGlkZXJPZmZzZXQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuY29sbGlkZXJPZmZzZXQgPSBWZWMyLlpFUk87XG5cdFx0fVxuXG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aGUgc3dlcHQgcmVjdFxuXHRcdHRoaXMuc3dlcHRSZWN0ID0gdGhpcy5jb2xsaXNpb25TaGFwZS5nZXRCb3VuZGluZ1JlY3QoKTtcblxuXHRcdC8vIFJlZ2lzdGVyIHRoZSBvYmplY3Qgd2l0aCBwaHlzaWNzXG5cdFx0dGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLnJlZ2lzdGVyT2JqZWN0KHRoaXMpO1xuXHR9XG5cblx0LyoqIFJlbW92ZXMgdGhpcyBvYmplY3QgZnJvbSB0aGUgcGh5c2ljcyBzeXN0ZW0gKi9cbiAgICByZW1vdmVQaHlzaWNzKCk6IHZvaWQge1xuXHRcdC8vIFJlbW92ZSB0aGlzIGZyb20gdGhlIHBoeXNpY3MgbWFuYWdlclxuXHRcdHRoaXMuc2NlbmUuZ2V0UGh5c2ljc01hbmFnZXIoKS5kZXJlZ2lzdGVyT2JqZWN0KHRoaXMpO1xuXG5cdFx0Ly8gTnVsbGlmeSBhbGwgcGh5c2ljcyBmaWVsZHNcblx0XHR0aGlzLmhhc1BoeXNpY3MgPSBmYWxzZTtcblx0XHR0aGlzLm1vdmluZyA9IGZhbHNlO1xuXHRcdHRoaXMub25Hcm91bmQgPSBmYWxzZTtcblx0XHR0aGlzLm9uV2FsbCA9IGZhbHNlO1xuXHRcdHRoaXMub25DZWlsaW5nID0gZmFsc2U7XG5cdFx0dGhpcy5hY3RpdmUgPSBmYWxzZTtcblx0XHR0aGlzLmlzQ29sbGlkYWJsZSA9IGZhbHNlO1xuXHRcdHRoaXMuaXNTdGF0aWMgPSBmYWxzZTtcblx0XHR0aGlzLmlzVHJpZ2dlciA9IGZhbHNlO1xuXHRcdHRoaXMudHJpZ2dlck1hc2sgPSAwO1xuXHRcdHRoaXMudHJpZ2dlckVudGVycyA9IG51bGw7XG5cdFx0dGhpcy50cmlnZ2VyRXhpdHMgPSBudWxsO1xuXHRcdHRoaXMuX3ZlbG9jaXR5ID0gVmVjMi5aRVJPO1xuXHRcdHRoaXMuc3dlcHRSZWN0ID0gbnVsbDtcblx0XHR0aGlzLmNvbGxpZGVkV2l0aFRpbGVtYXAgPSBmYWxzZTtcblx0XHR0aGlzLmdyb3VwID0gLTE7XG5cdFx0dGhpcy5jb2xsaXNpb25TaGFwZSA9IG51bGw7XG5cdFx0dGhpcy5jb2xsaWRlck9mZnNldCA9IFZlYzIuWkVSTztcblx0XHR0aGlzLnN3ZXB0UmVjdCA9IG51bGw7XG5cdH1cblxuXHQvKiogRGlzYWJsZXMgcGh5c2ljcyBtb3ZlbWVudCBmb3IgdGhpcyBub2RlICovXG5cdGZyZWV6ZSgpOiB2b2lkIHtcblx0XHR0aGlzLmZyb3plbiA9IHRydWU7XG5cdH1cblxuXHQvKiogUmVlbmFibGVzIHBoeXNpY3MgbW92ZW1lbnQgZm9yIHRoaXMgbm9kZSAqL1xuXHR1bmZyZWV6ZSgpOiB2b2lkIHtcblx0XHR0aGlzLmZyb3plbiA9IGZhbHNlO1xuXHR9XG5cbiAgICAvKiogUHJldmVudHMgdGhpcyBvYmplY3QgZnJvbSBwYXJ0aWNpcGF0aW5nIGluIGFsbCBjb2xsaXNpb25zIGFuZCB0cmlnZ2Vycy4gSXQgY2FuIHN0aWxsIG1vdmUuICovXG4gICAgZGlzYWJsZVBoeXNpY3MoKTogdm9pZCB7XG5cdFx0dGhpcy5hY3RpdmUgPSBmYWxzZTtcblx0fVxuXG4gICAgLyoqIEVuYWJsZXMgdGhpcyBvYmplY3QgdG8gcGFydGljaXBhdGUgaW4gY29sbGlzaW9ucyBhbmQgdHJpZ2dlcnMuIFRoaXMgaXMgb25seSBuZWNlc3NhcnkgaWYgZGlzYWJsZVBoeXNpY3Mgd2FzIGNhbGxlZCAqL1xuICAgIGVuYWJsZVBoeXNpY3MoKTogdm9pZCB7XG5cdFx0dGhpcy5hY3RpdmUgPSB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGNvbGxpZGVyIGZvciB0aGlzIEdhbWVOb2RlXG5cdCAqIEBwYXJhbSBjb2xsaWRlciBUaGUgbmV3IGNvbGxpZGVyIHRvIHVzZVxuXHQgKi9cblx0c2V0Q29sbGlzaW9uU2hhcGUoY29sbGlkZXI6IFNoYXBlKTogdm9pZCB7XG5cdFx0dGhpcy5jb2xsaXNpb25TaGFwZSA9IGNvbGxpZGVyO1xuXHRcdHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyLmNvcHkodGhpcy5wb3NpdGlvbik7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG4gICAgICogU2V0cyB0aGlzIG9iamVjdCB0byBiZSBhIHRyaWdnZXIgZm9yIGEgc3BlY2lmaWMgZ3JvdXBcbiAgICAgKiBAcGFyYW0gZ3JvdXAgVGhlIG5hbWUgb2YgdGhlIGdyb3VwIHRoYXQgYWN0aXZhdGVzIHRoZSB0cmlnZ2VyXG4gICAgICogQHBhcmFtIG9uRW50ZXIgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQgd2hlbiB0aGlzIHRyaWdnZXIgaXMgYWN0aXZhdGVkXG4gICAgICogQHBhcmFtIG9uRXhpdCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gc2VuZCB3aGVuIHRoaXMgdHJpZ2dlciBzdG9wcyBiZWluZyBhY3RpdmF0ZWRcbiAgICAgKi9cbiAgICBzZXRUcmlnZ2VyKGdyb3VwOiBzdHJpbmcsIG9uRW50ZXI6IHN0cmluZywgb25FeGl0OiBzdHJpbmcpOiB2b2lkIHtcblx0XHQvLyBNYWtlIHRoaXMgb2JqZWN0IGEgdHJpZ2dlclxuXHRcdHRoaXMuaXNUcmlnZ2VyID0gdHJ1ZTtcblxuXHRcdC8vIEdldCB0aGUgbnVtYmVyIG9mIHRoZSBwaHlzaWNzIGxheWVyXG5cdFx0bGV0IGxheWVyTnVtYmVyID0gdGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLmdldEdyb3VwTnVtYmVyKGdyb3VwKTtcblxuXHRcdGlmKGxheWVyTnVtYmVyID09PSAwKXtcblx0XHRcdGNvbnNvbGUud2FybihgVHJpZ2dlciBmb3IgR2FtZU5vZGUgJHt0aGlzLmlkfSBub3Qgc2V0IC0gZ3JvdXAgXCIke2dyb3VwfVwiIHdhcyBub3QgcmVjb2duaXplZCBieSB0aGUgcGh5c2ljcyBtYW5hZ2VyLmApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIEFkZCB0aGlzIHRvIHRoZSB0cmlnZ2VyIG1hc2tcblx0XHR0aGlzLnRyaWdnZXJNYXNrIHw9IGxheWVyTnVtYmVyO1xuXG5cdFx0Ly8gTGF5ZXIgbnVtYmVycyBhcmUgYml0cywgc28gZ2V0IHdoaWNoIGJpdCBpdCBpc1xuXHRcdGxldCBpbmRleCA9IE1hdGgubG9nMihsYXllck51bWJlcik7XG5cblx0XHQvLyBTZXQgdGhlIGV2ZW50IG5hbWVzXG5cdFx0dGhpcy50cmlnZ2VyRW50ZXJzW2luZGV4XSA9IG9uRW50ZXI7XG5cdFx0dGhpcy50cmlnZ2VyRXhpdHNbaW5kZXhdID0gb25FeGl0O1xuXHR9O1xuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHQvKipcblx0ICogQHBhcmFtIGdyb3VwIFRoZSBwaHlzaWNzIGdyb3VwIHRoaXMgbm9kZSBzaG91bGQgYmVsb25nIHRvXG5cdCAqL1xuXHRzZXRHcm91cChncm91cDogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLnNldEdyb3VwKHRoaXMsIGdyb3VwKTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbmVkXG5cdGdldExhc3RWZWxvY2l0eSgpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5fdmVsb2NpdHk7XG5cdH1cblxuXHQvKi0tLS0tLS0tLS0gQUNUT1IgLS0tLS0tLS0tLSovXG5cdGdldCBhaSgpOiBBSSB8IEdvYXBBSSB7XG5cdFx0cmV0dXJuIHRoaXMuX2FpO1xuXHR9XG5cblx0c2V0IGFpKGFpOiBBSSB8IEdvYXBBSSkge1xuXHRcdGlmKCF0aGlzLl9haSl7XG5cdFx0XHQvLyBJZiB3ZSBoYXZlbid0IGJlZW4gcHJldmlvdXNseSBoYWQgYW4gYWksIHJlZ2lzdGVyIHVzIHdpdGggdGhlIGFpIG1hbmFnZXJcblx0XHRcdHRoaXMuc2NlbmUuZ2V0QUlNYW5hZ2VyKCkucmVnaXN0ZXJBY3Rvcih0aGlzKTtcblx0XHR9XG5cblx0XHR0aGlzLl9haSA9IGFpO1xuXHRcdHRoaXMuYWlBY3RpdmUgPSB0cnVlO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGFkZEFJPFQgZXh0ZW5kcyBBSSB8IEdvYXBBST4oYWk6IHN0cmluZyB8IChuZXcgKCkgPT4gVCksIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCB0eXBlPzogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYoIXRoaXMuX2FpKXtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0QUlNYW5hZ2VyKCkucmVnaXN0ZXJBY3Rvcih0aGlzKTtcblx0XHR9XG5cblx0XHRpZih0eXBlb2YgYWkgPT09IFwic3RyaW5nXCIpe1xuXHRcdFx0dGhpcy5fYWkgPSB0aGlzLnNjZW5lLmdldEFJTWFuYWdlcigpLmdlbmVyYXRlQUkoYWkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9haSA9IG5ldyBhaSgpO1xuXHRcdH1cblxuXHRcdC8vIFF1ZXN0aW9uLCBob3cgbXVjaCBkbyB3ZSB3YW50IGRpZmZlcmVudCB0eXBlIG9mIEFJIHRvIGJlIGhhbmRsZWQgdGhlIHNhbWUsIGkuZS4gc2hvdWxkIEdvYXBBSSBhbmQgQUkgc2ltaWxhciBtZXRob2RzIGFuZCBzaWduYXR1cmVzIGZvciB0aGUgc2FrZSBvZiB1bml0eVxuXHRcdHRoaXMuX2FpLmluaXRpYWxpemVBSSh0aGlzLCBvcHRpb25zKTtcblxuXHRcdHRoaXMuYWlBY3RpdmUgPSB0cnVlO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdHNldEFJQWN0aXZlKGFjdGl2ZTogYm9vbGVhbiwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdHRoaXMuYWlBY3RpdmUgPSBhY3RpdmU7XG5cdFx0aWYodGhpcy5haUFjdGl2ZSl7XG5cdFx0XHR0aGlzLmFpLmFjdGl2YXRlKG9wdGlvbnMpO1xuXHRcdH1cblx0fVxuXG5cdC8qLS0tLS0tLS0tLSBUV0VFTkFCTEUgUFJPUEVSVElFUyAtLS0tLS0tLS0tKi9cblx0c2V0IHBvc2l0aW9uWCh2YWx1ZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5wb3NpdGlvbi54ID0gdmFsdWU7XG5cdH1cblxuXHRzZXQgcG9zaXRpb25ZKHZhbHVlOiBudW1iZXIpIHtcblx0XHR0aGlzLnBvc2l0aW9uLnkgPSB2YWx1ZTtcblx0fVxuXG5cdGFic3RyYWN0IHNldCBzY2FsZVgodmFsdWU6IG51bWJlcik7XG5cblx0YWJzdHJhY3Qgc2V0IHNjYWxlWSh2YWx1ZTogbnVtYmVyKTtcblxuXHQvKi0tLS0tLS0tLS0gR0FNRSBOT0RFIC0tLS0tLS0tLS0qL1xuXHQvKipcblx0ICogU2V0cyB0aGUgc2NlbmUgZm9yIHRoaXMgb2JqZWN0LlxuXHQgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRoaXMgb2JqZWN0IGJlbG9uZ3MgdG8uXG5cdCAqL1xuXHRzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcblx0XHR0aGlzLnNjZW5lID0gc2NlbmU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2NlbmUgdGhpcyBvYmplY3QgaXMgaW4uIFxuXHQgKiBAcmV0dXJucyBUaGUgc2NlbmUgdGhpcyBvYmplY3QgYmVsb25ncyB0b1xuXHQqL1xuXHRnZXRTY2VuZSgpOiBTY2VuZSB7XG5cdFx0cmV0dXJuIHRoaXMuc2NlbmU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbGF5ZXIgb2YgdGhpcyBvYmplY3QuXG5cdCAqIEBwYXJhbSBsYXllciBUaGUgbGF5ZXIgdGhpcyBvYmplY3Qgd2lsbCBiZSBvbi5cblx0ICovXG5cdHNldExheWVyKGxheWVyOiBMYXllcik6IHZvaWQge1xuXHRcdHRoaXMubGF5ZXIgPSBsYXllcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBsYXllciB0aGlzIG9iamVjdCBpcyBvbi5cblx0ICogQHJldHVybnMgVGhpcyBsYXllciB0aGlzIG9iamVjdCBpcyBvbi5cblx0Ki9cblx0Z2V0TGF5ZXIoKTogTGF5ZXIge1xuXHRcdHJldHVybiB0aGlzLmxheWVyO1xuXHR9XG5cblx0LyoqIENhbGxlZCBpZiB0aGUgcG9zaXRpb24gdmVjdG9yIGlzIG1vZGlmaWVkIG9yIHJlcGxhY2VkICovXG5cdHByb3RlY3RlZCBwb3NpdGlvbkNoYW5nZWQoKTogdm9pZCB7XG5cdFx0aWYodGhpcy5jb2xsaXNpb25TaGFwZSl7XG5cdFx0XHRpZih0aGlzLmNvbGxpZGVyT2Zmc2V0KXtcblx0XHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIgPSB0aGlzLnBvc2l0aW9uLmNsb25lKCkuYWRkKHRoaXMuY29sbGlkZXJPZmZzZXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIgPSB0aGlzLnBvc2l0aW9uLmNsb25lKCk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHR9XG5cdH07XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgdGhpcyBHYW1lTm9kZVxuXHQgKiBAcGFyYW0gZGVsdGFUIFRoZSB0aW1lc3RlcCBvZiB0aGUgdXBkYXRlLlxuXHQgKi9cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Ly8gRGVmZXIgZXZlbnQgaGFuZGxpbmcgdG8gQUkuXG5cdFx0d2hpbGUodGhpcy5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSl7XG5cdFx0XHR0aGlzLl9haS5oYW5kbGVFdmVudCh0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpKTtcblx0XHR9XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0ZGVidWdSZW5kZXIoKTogdm9pZCB7XG5cdFx0Ly8gRHJhdyB0aGUgcG9zaXRpb24gb2YgdGhpcyBHYW1lTm9kZVxuXHRcdERlYnVnLmRyYXdQb2ludCh0aGlzLnJlbGF0aXZlUG9zaXRpb24sIENvbG9yLkJMVUUpO1xuXG5cdFx0Ly8gSWYgdmVsb2NpdHkgaXMgbm90IHplcm8sIGRyYXcgYSB2ZWN0b3IgZm9yIGl0XG5cdFx0aWYodGhpcy5fdmVsb2NpdHkgJiYgIXRoaXMuX3ZlbG9jaXR5LmlzWmVybygpKXtcblx0XHRcdERlYnVnLmRyYXdSYXkodGhpcy5yZWxhdGl2ZVBvc2l0aW9uLCB0aGlzLl92ZWxvY2l0eS5jbG9uZSgpLnNjYWxlVG8oMjApLmFkZCh0aGlzLnJlbGF0aXZlUG9zaXRpb24pLCBDb2xvci5CTFVFKTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGlzIGhhcyBhIGNvbGxpZGVyLCBkcmF3IGl0XG5cdFx0aWYodGhpcy5jb2xsaXNpb25TaGFwZSl7XG5cdFx0XHRsZXQgY29sb3IgPSB0aGlzLmlzQ29sbGlkaW5nID8gQ29sb3IuUkVEIDogQ29sb3IuR1JFRU47XG5cblx0XHRcdGlmKHRoaXMuaXNUcmlnZ2VyKXtcblx0XHRcdFx0Y29sb3IgPSBDb2xvci5NQUdFTlRBO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRjb2xvci5hID0gMC4yO1xuXG5cdFx0XHRpZih0aGlzLmNvbGxpc2lvblNoYXBlIGluc3RhbmNlb2YgQUFCQil7XG5cdFx0XHRcdERlYnVnLmRyYXdCb3godGhpcy5pblJlbGF0aXZlQ29vcmRpbmF0ZXModGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIpLCB0aGlzLmNvbGxpc2lvblNoYXBlLmhhbGZTaXplLnNjYWxlZCh0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpKSwgdHJ1ZSwgY29sb3IpO1xuXHRcdFx0fSBlbHNlIGlmKHRoaXMuY29sbGlzaW9uU2hhcGUgaW5zdGFuY2VvZiBDaXJjbGUpe1xuXHRcdFx0XHREZWJ1Zy5kcmF3Q2lyY2xlKHRoaXMuaW5SZWxhdGl2ZUNvb3JkaW5hdGVzKHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyKSwgdGhpcy5jb2xsaXNpb25TaGFwZS5odyp0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpLCB0cnVlLCBjb2xvcik7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBlbnVtIFR3ZWVuYWJsZVByb3BlcnRpZXN7XG5cdHBvc1ggPSBcInBvc2l0aW9uWFwiLFxuXHRwb3NZID0gXCJwb3NpdGlvbllcIixcblx0c2NhbGVYID0gXCJzY2FsZVhcIixcblx0c2NhbGVZID0gXCJzY2FsZVlcIixcblx0cm90YXRpb24gPSBcInJvdGF0aW9uXCIsXG5cdGFscGhhID0gXCJhbHBoYVwiXG59IiwiaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4vQ2FudmFzTm9kZVwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhIGdhbWUgb2JqZWN0IHRoYXQgZG9lc24ndCByZWx5IG9uIGFueSByZXNvdXJjZXMgdG8gcmVuZGVyIC0gaXQgaXMgZHJhd24gdG8gdGhlIHNjcmVlbiBieSB0aGUgY2FudmFzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIEdyYXBoaWMgZXh0ZW5kcyBDYW52YXNOb2RlIHtcbiAgICAvKiogVGhlIGNvbG9yIG9mIHRoZSBHcmFwaGljICovXG4gICAgY29sb3I6IENvbG9yO1xuXG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5jb2xvciA9IENvbG9yLlJFRDtcbiAgICB9XG5cbiAgICBnZXQgYWxwaGEoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5jb2xvci5hO1xuXHR9XG5cblx0c2V0IGFscGhhKGE6IG51bWJlcikge1xuXHRcdHRoaXMuY29sb3IuYSA9IGE7XG5cdH1cblxuICAgIC8vIEBkZXByZWNhdGVkXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY29sb3Igb2YgdGhlIEdyYXBoaWMuIERFUFJFQ0FURURcbiAgICAgKiBAcGFyYW0gY29sb3IgVGhlIG5ldyBjb2xvciBvZiB0aGUgR3JhcGhpYy5cbiAgICAgKi9cbiAgICBzZXRDb2xvcihjb2xvcjogQ29sb3Ipe1xuICAgICAgICB0aGlzLmNvbG9yID0gY29sb3I7XG4gICAgfVxuXG4gICAgc2V0IGNvbG9yUihyOiBudW1iZXIpe1xuICAgICAgICB0aGlzLmNvbG9yLnIgPSByO1xuICAgIH1cblxuICAgIGdldCBjb2xvclIoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sb3IucjtcbiAgICB9XG5cbiAgICBzZXQgY29sb3JHKGc6IG51bWJlcil7XG4gICAgICAgIHRoaXMuY29sb3IuZyA9IGc7XG4gICAgfVxuXG4gICAgZ2V0IGNvbG9yRygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xvci5nO1xuICAgIH1cblxuICAgIHNldCBjb2xvckIoYjogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5jb2xvci5iID0gYjtcbiAgICB9XG5cbiAgICBnZXQgY29sb3JCKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbG9yLmI7XG4gICAgfVxufSIsImV4cG9ydCBlbnVtIEdyYXBoaWNUeXBlIHtcblx0UE9JTlQgPSBcIlBPSU5UXCIsXG5cdFJFQ1QgPSBcIlJFQ1RcIixcblx0TElORSA9IFwiTElORVwiLFxuXHRQQVJUSUNMRSA9IFwiUEFSVElDTEVcIlxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uL0dyYXBoaWNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGluZSBleHRlbmRzIEdyYXBoaWMge1xuICAgIHByb3RlY3RlZCBfZW5kOiBWZWMyO1xuICAgIHRoaWNrbmVzczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3Ioc3RhcnQ6IFZlYzIsIGVuZDogVmVjMil7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuc3RhcnQgPSBzdGFydDtcbiAgICAgICAgdGhpcy5lbmQgPSBlbmQ7XG4gICAgICAgIHRoaXMudGhpY2tuZXNzID0gMjtcblxuICAgICAgICAvLyBEb2VzIHRoaXMgcmVhbGx5IGhhdmUgYSBtZWFuaW5nIGZvciBsaW5lcz9cbiAgICAgICAgdGhpcy5zaXplLnNldCg1LCA1KTtcbiAgICB9XG5cbiAgICBzZXQgc3RhcnQocG9zOiBWZWMyKXtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvcztcbiAgICB9XG5cbiAgICBnZXQgc3RhcnQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uO1xuICAgIH1cblxuICAgIHNldCBlbmQocG9zOiBWZWMyKXtcbiAgICAgICAgdGhpcy5fZW5kID0gcG9zO1xuICAgIH1cblxuICAgIGdldCBlbmQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbmQ7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuL1BvaW50XCI7XG5cbi8qKlxuICogLSBQb3NpdGlvbiBYXG4tIFZlbG9jaXR5IChzcGVlZCBhbmQgZGlyZWN0aW9uKSBYXG4tIENvbG9yIFhcbi0gTGlmZXRpbWUgXG4tIEFnZSBjYW4gYmUgaGFuZGxlZCBhcyBsaWZldGltZVxuLSBTaGFwZSBYXG4tIFNpemUgWFxuLSBUcmFuc3BhcmVuY3kgWFxuICovXG5cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGFydGljbGUgZXh0ZW5kcyBQb2ludCB7XG4gICAgYWdlOiBudW1iZXI7XG5cbiAgICBpblVzZTogYm9vbGVhbjtcblxuICAgIHZlbDogVmVjMjtcblxuICAgIG1hc3M6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCBzaXplOiBWZWMyLCBtYXNzOiBudW1iZXIpIHtcbiAgICAgICAgLy8gQXJlIHdlIG1ha2luZyB0aGlzIGEgY2lyY2xlP1xuICAgICAgICBzdXBlcihwb3NpdGlvbik7XG4gICAgICAgIHRoaXMuaW5Vc2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5tYXNzID0gbWFzcztcbiAgICB9XG5cbiAgICBzZXRQYXJ0aWNsZUFjdGl2ZShsaWZldGltZTogbnVtYmVyLCBwb3NpdGlvbjogVmVjMikge1xuICAgICAgICB0aGlzLmFnZSA9IGxpZmV0aW1lO1xuICAgICAgICB0aGlzLmluVXNlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy52aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuICAgIH1cblxuICAgIGRlY3JlbWVudEFnZShkZWNheTogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuYWdlIC09IGRlY2F5O1xuICAgIH1cblxuICAgIHNldFBhcnRpY2xlSW5hY3RpdmUoKXtcbiAgICAgICAgdGhpcy5pblVzZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnZpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBzZXQgdmVsWSh5OiBudW1iZXIpe1xuICAgICAgICB0aGlzLnZlbC55ID0geTtcbiAgICB9XG5cbiAgICBnZXQgdmVsWSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy52ZWwueTtcbiAgICB9XG5cblxufSIsImltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9HcmFwaGljXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcblxuLyoqIEEgYmFzaWMgcG9pbnQgdG8gYmUgZHJhd24gb24gdGhlIHNjcmVlbi4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvaW50IGV4dGVuZHMgR3JhcGhpYyB7XG5cbiAgICBjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMikge1xuICAgICAgICAvLyBBcmUgd2UgbWFraW5nIHRoaXMgYSBjaXJjbGU/XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcbiAgICAgICAgdGhpcy5zaXplLnNldCg1LCA1KTtcbiAgICB9XG59IiwiaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uL0dyYXBoaWNcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuXG4vKiogQSBiYXNpYyByZWN0YW5nbGUgdG8gYmUgZHJhd24gb24gdGhlIHNjcmVlbi4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlY3QgZXh0ZW5kcyBHcmFwaGljIHtcblxuICAgIC8qKiBUaGUgYm9yZGVyIGNvbG9yIG9mIHRoZSBSZWN0ICovXG4gICAgYm9yZGVyQ29sb3I6IENvbG9yO1xuXG4gICAgLyoqIFRoZSB3aWR0aCBvZiB0aGUgYm9yZGVyICovXG4gICAgYm9yZGVyV2lkdGg6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCBzaXplOiBWZWMyKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuICAgICAgICB0aGlzLnNpemUgPSBzaXplO1xuICAgICAgICB0aGlzLmJvcmRlckNvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHRoaXMuYm9yZGVyV2lkdGggPSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGJvcmRlciBjb2xvciBvZiB0aGlzIHJlY3RhbmdsZVxuICAgICAqIEBwYXJhbSBjb2xvciBUaGUgYm9yZGVyIGNvbG9yXG4gICAgICovXG4gICAgc2V0Qm9yZGVyQ29sb3IoY29sb3I6IENvbG9yKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYm9yZGVyQ29sb3IgPSBjb2xvcjtcbiAgICB9XG5cbiAgICAvLyBAZGVwcmVjYXRlZFxuICAgIGdldEJvcmRlckNvbG9yKCk6IENvbG9yIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm9yZGVyQ29sb3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYm9yZGVyIHdpZHRoIG9mIHRoaXMgcmVjdGFuZ2xlXG4gICAgICogQHBhcmFtIHdpZHRoIFRoZSB3aWR0aCBvZiB0aGUgcmVjdGFuZ2xlIGluIHBpeGVsc1xuICAgICAqL1xuICAgIHNldEJvcmRlcldpZHRoKHdpZHRoOiBudW1iZXIpe1xuICAgICAgICB0aGlzLmJvcmRlcldpZHRoID0gd2lkdGg7XG4gICAgfVxuXG4gICAgZ2V0Qm9yZGVyV2lkdGgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm9yZGVyV2lkdGg7XG4gICAgfVxufSIsImltcG9ydCBTcHJpdGUgZnJvbSBcIi4vU3ByaXRlXCI7XG5pbXBvcnQgQW5pbWF0aW9uTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVuZGVyaW5nL0FuaW1hdGlvbnMvQW5pbWF0aW9uTWFuYWdlclwiO1xuaW1wb3J0IFNwcml0ZXNoZWV0IGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvU3ByaXRlc2hlZXRcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuXG4vKiogQW4gc3ByaXRlIHdpdGggc3BlY2lmaWVkIGFuaW1hdGlvbiBmcmFtZXMuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbmltYXRlZFNwcml0ZSBleHRlbmRzIFNwcml0ZSB7XG4gICAgLyoqIFRoZSBudW1iZXIgb2YgY29sdW1ucyBpbiB0aGlzIHNwcml0ZSBzaGVldCAqL1xuICAgIHByb3RlY3RlZCBudW1Db2xzOiBudW1iZXI7XG5cbiAgICBnZXQgY29scygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5udW1Db2xzO1xuICAgIH1cblxuICAgIC8qKiBUaGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhpcyBzcHJpdGUgc2hlZXQgKi9cbiAgICBwcm90ZWN0ZWQgbnVtUm93czogbnVtYmVyO1xuXG4gICAgZ2V0IHJvd3MoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubnVtUm93cztcbiAgICB9XG5cbiAgICAvKiogVGhlIGFuaW1hdGlvbk1hbmFnZXIgZm9yIHRoaXMgc3ByaXRlICovXG4gICAgYW5pbWF0aW9uOiBBbmltYXRpb25NYW5hZ2VyO1xuXG4gICAgY29uc3RydWN0b3Ioc3ByaXRlc2hlZXQ6IFNwcml0ZXNoZWV0KXtcbiAgICAgICAgc3VwZXIoc3ByaXRlc2hlZXQubmFtZSk7XG4gICAgICAgIHRoaXMubnVtQ29scyA9IHNwcml0ZXNoZWV0LmNvbHVtbnM7XG4gICAgICAgIHRoaXMubnVtUm93cyA9IHNwcml0ZXNoZWV0LnJvd3M7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBzaXplIG9mIHRoZSBzcHJpdGUgdG8gdGhlIHNwcml0ZSBzaXplIHNwZWNpZmllZCBieSB0aGUgc3ByaXRlc2hlZXRcbiAgICAgICAgdGhpcy5zaXplLnNldChzcHJpdGVzaGVldC5zcHJpdGVXaWR0aCwgc3ByaXRlc2hlZXQuc3ByaXRlSGVpZ2h0KTtcblxuICAgICAgICB0aGlzLmFuaW1hdGlvbiA9IG5ldyBBbmltYXRpb25NYW5hZ2VyKHRoaXMpO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgYW5pbWF0aW9ucyB0byB0aGUgYW5pbWF0ZWQgc3ByaXRlXG4gICAgICAgIGZvcihsZXQgYW5pbWF0aW9uIG9mIHNwcml0ZXNoZWV0LmFuaW1hdGlvbnMpe1xuICAgICAgICAgICAgdGhpcy5hbmltYXRpb24uYWRkKGFuaW1hdGlvbi5uYW1lLCBhbmltYXRpb24pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW1hZ2Ugb2Zmc2V0IGZvciB0aGUgY3VycmVudCBpbmRleCBvZiBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHdlJ3JlIGF0IGluIHRoZSBhbmltYXRpb25cbiAgICAgKiBAcmV0dXJucyBBIFZlYzIgY29udGFpbmluZyB0aGUgaW1hZ2Ugb2Zmc2V0XG4gICAgICovXG4gICAgZ2V0QW5pbWF0aW9uT2Zmc2V0KGluZGV4OiBudW1iZXIpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKChpbmRleCAlIHRoaXMubnVtQ29scykgKiB0aGlzLnNpemUueCwgTWF0aC5mbG9vcihpbmRleCAvIHRoaXMubnVtQ29scykgKiB0aGlzLnNpemUueSk7XG4gICAgfVxufSIsImltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9DYW52YXNOb2RlXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcblxuLyoqXG4gKiBUaGUgcmVwcmVzZW50YXRpb24gb2YgYSBzcHJpdGUgLSBhbiBpbi1nYW1lIGltYWdlXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwcml0ZSBleHRlbmRzIENhbnZhc05vZGUge1xuICAgIC8qKiBUaGUgaWQgb2YgdGhlIGltYWdlIGZyb20gdGhlIHJlc291cmNlTWFuYWdlciAqL1xuICAgIGltYWdlSWQ6IHN0cmluZztcbiAgICAvKiogVGhlIG9mZnNldCBvZiB0aGUgc3ByaXRlIGluIGFuIGF0bGFzIGltYWdlICovXG4gICAgaW1hZ2VPZmZzZXQ6IFZlYzI7XG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoZSB4LWF4aXMgc2hvdWxkIGJlIGludmVydGVkIG9uIHJlbmRlciAqL1xuICAgIGludmVydFg6IGJvb2xlYW47XG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoZSB5LWF4aXMgc2hvdWxkIGJlIGludmVydGVkIG9uIHJlbmRlciAqL1xuICAgIGludmVydFk6IGJvb2xlYW47XG5cbiAgICBjb25zdHJ1Y3RvcihpbWFnZUlkOiBzdHJpbmcpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmltYWdlSWQgPSBpbWFnZUlkO1xuICAgICAgICBsZXQgaW1hZ2UgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRJbWFnZSh0aGlzLmltYWdlSWQpO1xuICAgICAgICB0aGlzLnNpemUgPSBuZXcgVmVjMihpbWFnZS53aWR0aCwgaW1hZ2UuaGVpZ2h0KTtcbiAgICAgICAgdGhpcy5pbWFnZU9mZnNldCA9IFZlYzIuWkVSTztcbiAgICAgICAgdGhpcy5pbnZlcnRYID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaW52ZXJ0WSA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG9mZnNldCBvZiB0aGUgc3ByaXRlIGZyb20gKDAsIDApIGluIHRoZSBpbWFnZSdzIGNvb3JkaW5hdGVzXG4gICAgICogQHBhcmFtIG9mZnNldCBUaGUgb2Zmc2V0IG9mIHRoZSBzcHJpdGUgZnJvbSAoMCwgMCkgaW4gaW1hZ2UgY29vcmRpbmF0ZXNcbiAgICAgKi9cbiAgICBzZXRJbWFnZU9mZnNldChvZmZzZXQ6IFZlYzIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pbWFnZU9mZnNldCA9IG9mZnNldDtcbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgVGlsZXNldCBmcm9tIFwiLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVzZXRcIjtcbmltcG9ydCB7IFRpbGVkVGlsZW1hcERhdGEsIFRpbGVkTGF5ZXJEYXRhIH0gZnJvbSBcIi4uL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIlxuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4vQ2FudmFzTm9kZVwiO1xuaW1wb3J0IFBoeXNpY3NNYW5hZ2VyIGZyb20gXCIuLi9QaHlzaWNzL1BoeXNpY3NNYW5hZ2VyXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGEgdGlsZW1hcCAtIHRoaXMgY2FuIGNvbnNpc3Qgb2YgYSBjb21iaW5hdGlvbiBvZiB0aWxlc2V0cyBpbiBvbmUgbGF5ZXJcbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgVGlsZW1hcCBleHRlbmRzIENhbnZhc05vZGUge1xuICAgIC8qKiBBbiBhcnJheSBvZiB0aGUgdGlsZXNldHMgdGhhdCB0aGlzIHRpbGVtYXAgdXNlcyAqL1xuICAgIHByb3RlY3RlZCB0aWxlc2V0czogQXJyYXk8VGlsZXNldD47XG5cbiAgICAvKiogVGhlIHNpemUgb2YgYSB0aWxlIGluIHRoaXMgdGlsZW1hcCAqL1xuICAgIHByb3RlY3RlZCB0aWxlU2l6ZTogVmVjMjtcblxuICAgIC8qKiBBbiBhcnJheSBvZiB0aWxlIGRhdGEgKi9cbiAgICBwcm90ZWN0ZWQgZGF0YTogQXJyYXk8bnVtYmVyPjtcblxuICAgIC8qKiBBbiBhcnJheSBvZiB0aWxlIGNvbGxpc2lvbiBkYXRhICovXG4gICAgcHJvdGVjdGVkIGNvbGxpc2lvbk1hcDogQXJyYXk8Ym9vbGVhbj47XG5cbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIHRpbGVtYXAgKi9cbiAgICBuYW1lOiBzdHJpbmc7XG5cbiAgICAvLyBUT0RPOiBNYWtlIHRoaXMgbm8gbG9uZ2VyIGJlIHNwZWNpZmljIHRvIFRpbGVkXG4gICAgY29uc3RydWN0b3IodGlsZW1hcERhdGE6IFRpbGVkVGlsZW1hcERhdGEsIGxheWVyOiBUaWxlZExheWVyRGF0YSwgdGlsZXNldHM6IEFycmF5PFRpbGVzZXQ+LCBzY2FsZTogVmVjMikge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnRpbGVzZXRzID0gdGlsZXNldHM7XG4gICAgICAgIHRoaXMudGlsZVNpemUgPSBuZXcgVmVjMigwLCAwKTtcbiAgICAgICAgdGhpcy5uYW1lID0gbGF5ZXIubmFtZTtcblxuICAgICAgICBsZXQgdGlsZWNvdW50ID0gMDtcbiAgICAgICAgZm9yKGxldCB0aWxlc2V0IG9mIHRpbGVzZXRzKXtcbiAgICAgICAgICAgIHRpbGVjb3VudCArPSB0aWxlc2V0LmdldFRpbGVDb3VudCgpICsgMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29sbGlzaW9uTWFwID0gbmV3IEFycmF5KHRpbGVjb3VudCk7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLmNvbGxpc2lvbk1hcC5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICB0aGlzLmNvbGxpc2lvbk1hcFtpXSA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmZXIgcGFyc2luZyBvZiB0aGUgZGF0YSB0byBjaGlsZCBjbGFzc2VzIC0gdGhpcyBhbGxvd3MgZm9yIGlzb21ldHJpYyB2cy4gb3J0aG9ncmFwaGljIHRpbGVtYXBzIGFuZCBoYW5kbGluZyBvZiBUaWxlZCBkYXRhIG9yIG90aGVyIGRhdGFcbiAgICAgICAgdGhpcy5wYXJzZVRpbGVtYXBEYXRhKHRpbGVtYXBEYXRhLCBsYXllcik7XG4gICAgICAgIHRoaXMuc2NhbGUuc2V0KHNjYWxlLngsIHNjYWxlLnkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gYXJyYXkgb2YgdGhlIHRpbGVzZXRzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRpbGVtYXBcbiAgICAgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBhbGwgb2YgdGhlIHRpbGVzZXRzIGFzc29jYWl0ZWQgd2l0aCB0aGlzIHRpbGVtYXAuXG4gICAgICovXG4gICAgZ2V0VGlsZXNldHMoKTogVGlsZXNldFtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGlsZXNldHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgc2l6ZSBvZiB0aWxlcyBpbiB0aGlzIHRpbGVtYXAgYXMgdGhleSBhcHBlYXIgaW4gdGhlIGdhbWUgd29ybGQgYWZ0ZXIgc2NhbGluZ1xuICAgICAqIEByZXR1cm5zIEEgdmVjdG9yIGNvbnRhaW5pbmcgdGhlIHNpemUgb2YgdGlsZXMgaW4gdGhpcyB0aWxlbWFwIGFzIHRoZXkgYXBwZWFyIGluIHRoZSBnYW1lIHdvcmxkIGFmdGVyIHNjYWxpbmcuXG4gICAgICovXG4gICAgZ2V0VGlsZVNpemUoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbGVTaXplLnNjYWxlZCh0aGlzLnNjYWxlLngsIHRoaXMuc2NhbGUueSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdGlsZSBzaXplIHRha2luZyB6b29tIGludG8gYWNjb3VudFxuICAgICAqIEByZXR1cm5zIFRoZSB0aWxlIHNpemUgd2l0aCB6b29tXG4gICAgKi9cbiAgICBnZXRUaWxlU2l6ZVdpdGhab29tKCk6IFZlYzIge1xuICAgICAgICBsZXQgem9vbSA9IHRoaXMuc2NlbmUuZ2V0Vmlld1NjYWxlKCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VGlsZVNpemUoKS5zY2FsZSh6b29tKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIHRoaXMgdGlsZW1hcCB0byB0aGUgcGh5c2ljcyBzeXN0ZW1cbiAgICAqL1xuICAgIGFkZFBoeXNpY3MoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaGFzUGh5c2ljcyA9IHRydWU7XG4gICAgICAgIHRoaXMuYWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5ncm91cCA9IC0xO1xuICAgICAgICB0aGlzLnNjZW5lLmdldFBoeXNpY3NNYW5hZ2VyKCkucmVnaXN0ZXJUaWxlbWFwKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgcG9zaXRpb25cbiAgICAgKiBAcGFyYW0gd29ybGRDb29yZHMgVGhlIHBvc2l0aW9uIGluIHdvcmxkIGNvb3JkaW5hdGVzXG4gICAgICogQHJldHVybnMgQSBudW1iZXIgdGhhdCByZXByZXNlbnRzIHRoZSBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgd29ybGQgcG9zaXRpb24uXG4gICAgICovXG4gICAgYWJzdHJhY3QgZ2V0VGlsZUF0V29ybGRQb3NpdGlvbih3b3JsZENvb3JkczogVmVjMik6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHdvcmxkIHBvc2l0aW9uIG9mIHRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGUgaW4gdGhlIHRpbGVEYXRhIGFycmF5XG4gICAgICogQHJldHVybnMgVGhlIHdvcmxkIHBvc2l0aW9uIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBnZXRUaWxlV29ybGRQb3NpdGlvbihpbmRleDogbnVtYmVyKTogVmVjMjtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHZhbHVlIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlIGluIHRoZSB0aWxlRGF0YSBhcnJheVxuICAgICAqIEByZXR1cm5zIFRoZSB2YWx1ZSBvZiB0aGUgdGlsZSBpbiB0aGUgdGlsZURhdGEgYXJyYXlcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBnZXRUaWxlKGluZGV4OiBudW1iZXIpOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlXG4gICAgICogQHBhcmFtIHR5cGUgVGhlIG5ldyBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlXG4gICAgICovXG4gICAgYWJzdHJhY3Qgc2V0VGlsZShpbmRleDogbnVtYmVyLCB0eXBlOiBudW1iZXIpOiB2b2lkO1xuXG4gICAgLy8gVE9ETzogVGhpcyBzaG91bGRuJ3QgdXNlIHRpbGVkIGRhdGEgc3BlY2lmaWNhbGx5IC0gaXQgc2hvdWxkIGJlIG1vcmUgZ2VuZXJhbFxuICAgIC8qKlxuICAgICAqIFNldHMgdXAgdGhlIHRpbGVzZXQgdXNpbmcgdGhlIGRhdGEgbG9hZGVkIGZyb20gZmlsZVxuICAgICAqIEBwYXJhbSB0aWxlbWFwRGF0YSBUaGUgdGlsZW1hcCBkYXRhIGZyb20gZmlsZVxuICAgICAqIEBwYXJhbSBsYXllciBUaGUgbGF5ZXIgZGF0YSBmcm9tIGZpbGVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgcGFyc2VUaWxlbWFwRGF0YSh0aWxlbWFwRGF0YTogVGlsZWRUaWxlbWFwRGF0YSwgbGF5ZXI6IFRpbGVkTGF5ZXJEYXRhKTogdm9pZDtcbn0iLCJpbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vVGlsZW1hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhLCBUaWxlZExheWVyRGF0YSB9IGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1V0aWxzL0NvbG9yXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9ydGhvZ29uYWwgdGlsZW1hcCAtIGkuZS4gYSB0b3AgZG93biBvciBwbGF0Zm9ybWVyIHRpbGVtYXBcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgT3J0aG9nb25hbFRpbGVtYXAgZXh0ZW5kcyBUaWxlbWFwIHtcbiAgICAvKiogVGhlIG51bWJlciBvZiBjb2x1bW5zIGluIHRoZSB0aWxlbWFwICovXG4gICAgcHJvdGVjdGVkIG51bUNvbHM6IG51bWJlcjtcbiAgICAvKiogVGhlIG51bWJlciBvZiByb3dzIGluIHRoZSB0aWxlbWFwICovXG4gICAgcHJvdGVjdGVkIG51bVJvd3M6IG51bWJlcjtcblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCBwYXJzZVRpbGVtYXBEYXRhKHRpbGVtYXBEYXRhOiBUaWxlZFRpbGVtYXBEYXRhLCBsYXllcjogVGlsZWRMYXllckRhdGEpOiB2b2lkIHtcbiAgICAgICAgLy8gVGhlIHNpemUgb2YgdGhlIHRpbGVtYXAgaW4gbG9jYWwgc3BhY2VcbiAgICAgICAgdGhpcy5udW1Db2xzID0gdGlsZW1hcERhdGEud2lkdGg7XG4gICAgICAgIHRoaXMubnVtUm93cyA9IHRpbGVtYXBEYXRhLmhlaWdodDtcblxuICAgICAgICAvLyBUaGUgc2l6ZSBvZiB0aWxlc1xuICAgICAgICB0aGlzLnRpbGVTaXplLnNldCh0aWxlbWFwRGF0YS50aWxld2lkdGgsIHRpbGVtYXBEYXRhLnRpbGVoZWlnaHQpO1xuXG4gICAgICAgIC8vIFRoZSBzaXplIG9mIHRoZSB0aWxlbWFwIG9uIHRoZSBjYW52YXNcbiAgICAgICAgdGhpcy5zaXplLnNldCh0aGlzLm51bUNvbHMgKiB0aGlzLnRpbGVTaXplLngsIHRoaXMubnVtUm93cyAqIHRoaXMudGlsZVNpemUueSk7XG4gICAgICAgIHRoaXMucG9zaXRpb24uY29weSh0aGlzLnNpemUuc2NhbGVkKDAuNSkpO1xuICAgICAgICB0aGlzLmRhdGEgPSBsYXllci5kYXRhO1xuICAgICAgICB0aGlzLnZpc2libGUgPSBsYXllci52aXNpYmxlO1xuXG4gICAgICAgIC8vIFdoZXRoZXIgdGhlIHRpbGVtYXAgaXMgY29sbGlkYWJsZSBvciBub3RcbiAgICAgICAgdGhpcy5pc0NvbGxpZGFibGUgPSBmYWxzZTtcbiAgICAgICAgaWYobGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICBmb3IobGV0IGl0ZW0gb2YgbGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgaWYoaXRlbS5uYW1lID09PSBcIkNvbGxpZGFibGVcIil7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNDb2xsaWRhYmxlID0gaXRlbS52YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgYWxsIHRpbGVzIGJlc2lkZXMgXCJlbXB0eTogMFwiIHRvIGJlIGNvbGxpZGFibGVcbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IHRoaXMuY29sbGlzaW9uTWFwLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29sbGlzaW9uTWFwW2ldID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIHRpbGVtYXBcbiAgICAgKiBAcmV0dXJucyBBIFZlYzIgY29udGFpbmluZyB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgYW5kIHRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGUgdGlsZW1hcC5cbiAgICAgKi9cbiAgICBnZXREaW1lbnNpb25zKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy5udW1Db2xzLCB0aGlzLm51bVJvd3MpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGRhdGEgdmFsdWUgb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCB3b3JsZCBwb3NpdGlvblxuICAgICAqIEBwYXJhbSB3b3JsZENvb3JkcyBUaGUgY29vcmRpbmF0ZXMgaW4gd29ybGQgc3BhY2VcbiAgICAgKiBAcmV0dXJucyBUaGUgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZVxuICAgICAqL1xuICAgIGdldFRpbGVBdFdvcmxkUG9zaXRpb24od29ybGRDb29yZHM6IFZlYzIpOiBudW1iZXIge1xuICAgICAgICBsZXQgbG9jYWxDb29yZHMgPSB0aGlzLmdldENvbFJvd0F0KHdvcmxkQ29vcmRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VGlsZUF0Um93Q29sKGxvY2FsQ29vcmRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCByb3cgYW5kIGNvbHVtblxuICAgICAqIEBwYXJhbSByb3dDb2wgVGhlIGNvb3JkaW5hdGVzIGluIHRpbGVtYXAgc3BhY2VcbiAgICAgKiBAcmV0dXJucyBUaGUgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZVxuICAgICAqL1xuICAgIGdldFRpbGVBdFJvd0NvbChyb3dDb2w6IFZlYzIpOiBudW1iZXIge1xuICAgICAgICBpZihyb3dDb2wueCA8IDAgfHwgcm93Q29sLnggPj0gdGhpcy5udW1Db2xzIHx8IHJvd0NvbC55IDwgMCB8fCByb3dDb2wueSA+PSB0aGlzLm51bVJvd3Mpe1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YVtyb3dDb2wueSAqIHRoaXMubnVtQ29scyArIHJvd0NvbC54XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB3b3JsZCBwb3NpdGlvbiBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4XG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZVxuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSB3b3JsZCBwb3NpdGlvbiBvZiB0aGUgdGlsZVxuICAgICAqL1xuICAgIGdldFRpbGVXb3JsZFBvc2l0aW9uKGluZGV4OiBudW1iZXIpOiBWZWMyIHtcbiAgICAgICAgLy8gR2V0IHRoZSBsb2NhbCBwb3NpdGlvblxuICAgICAgICBsZXQgY29sID0gaW5kZXggJSB0aGlzLm51bUNvbHM7XG4gICAgICAgIGxldCByb3cgPSBNYXRoLmZsb29yKGluZGV4IC8gdGhpcy5udW1Db2xzKTtcblxuICAgICAgICAvLyBHZXQgdGhlIHdvcmxkIHBvc2l0aW9uXG4gICAgICAgIGxldCB4ID0gY29sICogdGhpcy50aWxlU2l6ZS54ICogdGhpcy5zY2FsZS54O1xuICAgICAgICBsZXQgeSA9IHJvdyAqIHRoaXMudGlsZVNpemUueSAqIHRoaXMuc2NhbGUueTtcblxuICAgICAgICByZXR1cm4gbmV3IFZlYzIoeCwgeSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4XG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZVxuICAgICAqIEByZXR1cm5zIFRoZSBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlXG4gICAgICovXG4gICAgZ2V0VGlsZShpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YVtpbmRleF07XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgc2V0VGlsZShpbmRleDogbnVtYmVyLCB0eXBlOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kYXRhW2luZGV4XSA9IHR5cGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIHJvdyBhbmQgY29sdW1uXG4gICAgICogQHBhcmFtIHJvd0NvbCBUaGUgcG9zaXRpb24gb2YgdGhlIHRpbGUgaW4gdGlsZW1hcCBzcGFjZVxuICAgICAqIEBwYXJhbSB0eXBlIFRoZSBuZXcgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZVxuICAgICAqL1xuICAgIHNldFRpbGVBdFJvd0NvbChyb3dDb2w6IFZlYzIsIHR5cGU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBsZXQgaW5kZXggPSByb3dDb2wueSAqIHRoaXMubnVtQ29scyArIHJvd0NvbC54O1xuICAgICAgICB0aGlzLnNldFRpbGUoaW5kZXgsIHR5cGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIHJvdyBhbmQgY29sdW1uIG9mIHRoZSB0aWxlbWFwIGlzIGNvbGxpZGFibGVcbiAgICAgKiBAcGFyYW0gaW5kZXhPckNvbCBUaGUgaW5kZXggb2YgdGhlIHRpbGUgb3IgdGhlIGNvbHVtbiBpdCBpcyBpblxuICAgICAqIEBwYXJhbSByb3cgVGhlIHJvdyB0aGUgdGlsZSBpcyBpblxuICAgICAqIEByZXR1cm5zIEEgZmxhZyByZXByZXNlbnRpbmcgd2hldGhlciBvciBub3QgdGhlIHRpbGUgaXMgY29sbGlkYWJsZS5cbiAgICAgKi9cbiAgICBpc1RpbGVDb2xsaWRhYmxlKGluZGV4T3JDb2w6IG51bWJlciwgcm93PzogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIFRoZSB2YWx1ZSBvZiB0aGUgdGlsZVxuICAgICAgICBsZXQgdGlsZSA9IDA7XG5cbiAgICAgICAgaWYocm93KXtcbiAgICAgICAgICAgIC8vIFdlIGhhdmUgYSBjb2x1bW4gYW5kIGEgcm93XG4gICAgICAgICAgICB0aWxlID0gdGhpcy5nZXRUaWxlQXRSb3dDb2wobmV3IFZlYzIoaW5kZXhPckNvbCwgcm93KSk7XG5cbiAgICAgICAgICAgIGlmKHRpbGUgPCAwKXtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZihpbmRleE9yQ29sIDwgMCB8fCBpbmRleE9yQ29sID49IHRoaXMuZGF0YS5sZW5ndGgpe1xuICAgICAgICAgICAgICAgIC8vIFRpbGVzIHRoYXQgZG9uJ3QgZXhpc3QgYXJlbid0IGNvbGxpZGFibGVcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBXZSBoYXZlIGFuIGluZGV4XG4gICAgICAgICAgICB0aWxlID0gdGhpcy5nZXRUaWxlKGluZGV4T3JDb2wpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29sbGlzaW9uTWFwW3RpbGVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRha2VzIGluIHdvcmxkIGNvb3JkaW5hdGVzIGFuZCByZXR1cm5zIHRoZSByb3cgYW5kIGNvbHVtbiBvZiB0aGUgdGlsZSBhdCB0aGF0IHBvc2l0aW9uXG4gICAgICogQHBhcmFtIHdvcmxkQ29vcmRzIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgcG90ZW50aWFsIHRpbGUgaW4gd29ybGQgc3BhY2VcbiAgICAgKiBAcmV0dXJucyBBIFZlYzIgY29udGFpbmluZyB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIHBvdGVudGlhbCB0aWxlIGluIHRpbGVtYXAgc3BhY2VcbiAgICAgKi9cbiAgICBnZXRDb2xSb3dBdCh3b3JsZENvb3JkczogVmVjMik6IFZlYzIge1xuICAgICAgICBsZXQgY29sID0gTWF0aC5mbG9vcih3b3JsZENvb3Jkcy54IC8gdGhpcy50aWxlU2l6ZS54IC8gdGhpcy5zY2FsZS54KTtcbiAgICAgICAgbGV0IHJvdyA9IE1hdGguZmxvb3Iod29ybGRDb29yZHMueSAvIHRoaXMudGlsZVNpemUueSAvIHRoaXMuc2NhbGUueSk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKGNvbCwgcm93KTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHt9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBkZWJ1Z1JlbmRlcigpe1xuICAgICAgICAvLyBIYWxmIG9mIHRoZSB0aWxlIHNpemVcbiAgICAgICAgbGV0IHpvb21lZEhhbGZUaWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemVXaXRoWm9vbSgpLnNjYWxlZCgwLjUpO1xuICAgICAgICBsZXQgaGFsZlRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpLnNjYWxlZCgwLjUpO1xuXG4gICAgICAgIC8vIFRoZSBjZW50ZXIgb2YgdGhlIHRvcCBsZWZ0IHRpbGVcbiAgICAgICAgbGV0IHRvcExlZnQgPSB0aGlzLnBvc2l0aW9uLmNsb25lKCkuc3ViKHRoaXMuc2l6ZS5zY2FsZWQoMC41KSk7XG4gICAgICAgIFxuICAgICAgICAvLyBBIHZlYyB0byBzdG9yZSB0aGUgY2VudGVyXG4gICAgICAgIGxldCBjZW50ZXIgPSBWZWMyLlpFUk87XG5cbiAgICAgICAgZm9yKGxldCBjb2wgPSAwOyBjb2wgPCB0aGlzLm51bUNvbHM7IGNvbCsrKXtcbiAgICAgICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgeC1wb3NpdGlvblxuICAgICAgICAgICAgY2VudGVyLnggPSB0b3BMZWZ0LnggKyBjb2wqMipoYWxmVGlsZVNpemUueCArIGhhbGZUaWxlU2l6ZS54O1xuXG4gICAgICAgICAgICBmb3IobGV0IHJvdyA9IDA7IHJvdyA8IHRoaXMubnVtUm93czsgcm93Kyspe1xuICAgICAgICAgICAgICAgIGlmKHRoaXMuaXNDb2xsaWRhYmxlICYmIHRoaXMuaXNUaWxlQ29sbGlkYWJsZShjb2wsIHJvdykpe1xuICAgICAgICAgICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHktcG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgY2VudGVyLnkgPSB0b3BMZWZ0LnkgKyByb3cqMipoYWxmVGlsZVNpemUueSArIGhhbGZUaWxlU2l6ZS55O1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIERyYXcgYSBib3ggZm9yIHRoaXMgdGlsZVxuICAgICAgICAgICAgICAgICAgICBEZWJ1Zy5kcmF3Qm94KHRoaXMuaW5SZWxhdGl2ZUNvb3JkaW5hdGVzKGNlbnRlciksIHpvb21lZEhhbGZUaWxlU2l6ZSwgZmFsc2UsIENvbG9yLkJMVUUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi9DYW52YXNOb2RlXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vSW5wdXQvSW5wdXRcIjtcblxuLyoqXG4gKiBUaGUgcmVwcmVzZW50YXRpb24gb2YgYSBVSUVsZW1lbnQgLSB0aGUgcGFyZW50IGNsYXNzIG9mIHRoaW5ncyBsaWtlIGJ1dHRvbnNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgVUlFbGVtZW50IGV4dGVuZHMgQ2FudmFzTm9kZSB7XG5cdC8vIFN0eWxlIGF0dHJpYnV0ZXMgLSBUT0RPIC0gYWJzdHJhY3QgdGhpcyBpbnRvIGEgc3R5bGUgb2JqZWN0L2ludGVyZmFjZVxuXHQvKiogVGhlIGJhY2tnb3VuZCBjb2xvciAqL1xuXHRiYWNrZ3JvdW5kQ29sb3I6IENvbG9yO1xuXHQvKiogVGhlIGJvcmRlciBjb2xvciAqL1xuXHRib3JkZXJDb2xvcjogQ29sb3I7XG5cdC8qKiBUaGUgYm9yZGVyIHJhZGl1cyAqL1xuXHRib3JkZXJSYWRpdXM6IG51bWJlcjtcblx0LyoqIFRoZSBib3JkZXIgd2lkdGggKi9cblx0Ym9yZGVyV2lkdGg6IG51bWJlcjtcblx0LyoqIFRoZSBwYWRkaW5nICovXG5cdHBhZGRpbmc6IFZlYzI7XG5cblx0Ly8gRXZlbnRBdHRyaWJ1dGVzXG5cdC8qKiBUaGUgcmVhY3Rpb24gb2YgdGhpcyBVSUVsZW1lbnQgb24gYSBjbGljayAqL1xuXHRvbkNsaWNrOiBGdW5jdGlvbjtcblx0LyoqIFRoZSBldmVudCBwcm9wYWdhdGVkIG9uIGNsaWNrICovXG5cdG9uQ2xpY2tFdmVudElkOiBzdHJpbmc7XG5cdC8qKiBUaGUgcmVhY3Rpb24gdG8gdGhlIHJlbGVhc2Ugb2YgYSBjbGljayAqL1xuXHRvblJlbGVhc2U6IEZ1bmN0aW9uO1xuXHQvKiogVGhlIGV2ZW50IHByb3BhZ2F0ZWQgb24gdGhlIHJlbGVhc2Ugb2YgYSBjbGljayAqL1xuXHRvblJlbGVhc2VFdmVudElkOiBzdHJpbmc7XG5cdC8qKiBUaGUgcmVhY3Rpb24gd2hlbiBhIG1vdXNlIGVudGVycyB0aGlzIFVJRWxlbWVudCAqL1xuXHRvbkVudGVyOiBGdW5jdGlvbjtcblx0LyoqIFRoZSBldmVudCBwcm9wYWdhdGVkIHdoZW4gYSBtb3VzZSBlbnRlcnMgdGhpcyBVSUVsZW1lbnQgKi9cblx0b25FbnRlckV2ZW50SWQ6IHN0cmluZztcblx0LyoqIFRoZSByZWFjdGlvbiB3aGVuIGEgbW91c2UgbGVhdmVzIHRoaXMgVUlFbGVtZW50ICovXG5cdG9uTGVhdmU6IEZ1bmN0aW9uO1xuXHQvKiogVGhlIGV2ZW50IHByb3BvZ2F0ZWQgd2hlbiBhIG1vdXNlIGxlYXZlcyB0aGlzIFVJRWxlbWVudCAqL1xuXHRvbkxlYXZlRXZlbnRJZDogc3RyaW5nO1xuXG5cdC8qKiBXaGV0aGVyIG9yIG5vdCB0aGlzIFVJRWxlbWVudCBpcyBjdXJyZW50bHkgY2xpY2tlZCBvbiAqL1xuXHRwcm90ZWN0ZWQgaXNDbGlja2VkOiBib29sZWFuO1xuXHQvKiogV2hldGhlciBvciBub3QgdGhpcyBVSUVsZW1lbnQgaXMgY3VycmVudGx5IGhvdmVyZWQgb3ZlciAqL1xuXHRwcm90ZWN0ZWQgaXNFbnRlcmVkOiBib29sZWFuO1xuXG5cdGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyKXtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcblx0XHRcblx0XHR0aGlzLmJhY2tncm91bmRDb2xvciA9IG5ldyBDb2xvcigwLCAwLCAwLCAwKTtcblx0XHR0aGlzLmJvcmRlckNvbG9yID0gbmV3IENvbG9yKDAsIDAsIDAsIDApO1xuXHRcdHRoaXMuYm9yZGVyUmFkaXVzID0gNTtcblx0XHR0aGlzLmJvcmRlcldpZHRoID0gMTtcblx0XHR0aGlzLnBhZGRpbmcgPSBWZWMyLlpFUk87XG5cblx0XHR0aGlzLm9uQ2xpY2sgPSBudWxsO1xuXHRcdHRoaXMub25DbGlja0V2ZW50SWQgPSBudWxsO1xuXHRcdHRoaXMub25SZWxlYXNlID0gbnVsbDtcblx0XHR0aGlzLm9uUmVsZWFzZUV2ZW50SWQgPSBudWxsO1xuXG5cdFx0dGhpcy5vbkVudGVyID0gbnVsbDtcblx0XHR0aGlzLm9uRW50ZXJFdmVudElkID0gbnVsbDtcblx0XHR0aGlzLm9uTGVhdmUgPSBudWxsO1xuXHRcdHRoaXMub25MZWF2ZUV2ZW50SWQgPSBudWxsO1xuXG5cdFx0dGhpcy5pc0NsaWNrZWQgPSBmYWxzZTtcblx0XHR0aGlzLmlzRW50ZXJlZCA9IGZhbHNlO1xuXHR9XG5cblx0Ly8gQGRlcHJlY2F0ZWRcblx0c2V0QmFja2dyb3VuZENvbG9yKGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdHRoaXMuYmFja2dyb3VuZENvbG9yID0gY29sb3I7XG5cdH1cblxuXHQvLyBAZGVwcmVjYXRlZFxuXHRzZXRQYWRkaW5nKHBhZGRpbmc6IFZlYzIpOiB2b2lkIHtcblx0XHR0aGlzLnBhZGRpbmcuY29weShwYWRkaW5nKTtcblx0fVxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG5cdFx0Ly8gU2VlIG9mIHRoaXMgb2JqZWN0IHdhcyBqdXN0IGNsaWNrZWRcblx0XHRpZihJbnB1dC5pc01vdXNlSnVzdFByZXNzZWQoKSl7XG5cdFx0XHRsZXQgY2xpY2tQb3MgPSBJbnB1dC5nZXRNb3VzZVByZXNzUG9zaXRpb24oKTtcblx0XHRcdGlmKHRoaXMuY29udGFpbnMoY2xpY2tQb3MueCwgY2xpY2tQb3MueSkgJiYgdGhpcy52aXNpYmxlICYmICF0aGlzLmxheWVyLmlzSGlkZGVuKCkpe1xuXHRcdFx0XHR0aGlzLmlzQ2xpY2tlZCA9IHRydWU7XG5cblx0XHRcdFx0aWYodGhpcy5vbkNsaWNrICE9PSBudWxsKXtcblx0XHRcdFx0XHR0aGlzLm9uQ2xpY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZih0aGlzLm9uQ2xpY2tFdmVudElkICE9PSBudWxsKXtcblx0XHRcdFx0XHRsZXQgZGF0YSA9IHt9O1xuXHRcdFx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQodGhpcy5vbkNsaWNrRXZlbnRJZCwgZGF0YSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJZiB0aGUgbW91c2Ugd2Fzbid0IGp1c3QgcHJlc3NlZCwgdGhlbiB3ZSBkZWZpbml0ZWx5IHdlcmVuJ3QgY2xpY2tlZFxuXHRcdGlmKCFJbnB1dC5pc01vdXNlUHJlc3NlZCgpKXtcblx0XHRcdGlmKHRoaXMuaXNDbGlja2VkKXtcblx0XHRcdFx0dGhpcy5pc0NsaWNrZWQgPSBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDaGVjayBpZiB0aGUgbW91c2UgaXMgaG92ZXJpbmcgb3ZlciB0aGlzIGVsZW1lbnRcblx0XHRsZXQgbW91c2VQb3MgPSBJbnB1dC5nZXRNb3VzZVBvc2l0aW9uKCk7XG5cdFx0aWYobW91c2VQb3MgJiYgdGhpcy5jb250YWlucyhtb3VzZVBvcy54LCBtb3VzZVBvcy55KSl7XG5cdFx0XHR0aGlzLmlzRW50ZXJlZCA9IHRydWU7XG5cblx0XHRcdGlmKHRoaXMub25FbnRlciAhPT0gbnVsbCl7XG5cdFx0XHRcdHRoaXMub25FbnRlcigpO1xuXHRcdFx0fVxuXHRcdFx0aWYodGhpcy5vbkVudGVyRXZlbnRJZCAhPT0gbnVsbCl7XG5cdFx0XHRcdGxldCBkYXRhID0ge307XG5cdFx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQodGhpcy5vbkVudGVyRXZlbnRJZCwgZGF0YSk7XG5cdFx0XHR9XG5cblx0XHR9IGVsc2UgaWYodGhpcy5pc0VudGVyZWQpIHtcblx0XHRcdHRoaXMuaXNFbnRlcmVkID0gZmFsc2U7XG5cblx0XHRcdGlmKHRoaXMub25MZWF2ZSAhPT0gbnVsbCl7XG5cdFx0XHRcdHRoaXMub25MZWF2ZSgpO1xuXHRcdFx0fVxuXHRcdFx0aWYodGhpcy5vbkxlYXZlRXZlbnRJZCAhPT0gbnVsbCl7XG5cdFx0XHRcdGxldCBkYXRhID0ge307XG5cdFx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQodGhpcy5vbkxlYXZlRXZlbnRJZCwgZGF0YSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmKHRoaXMuaXNDbGlja2VkKSB7XG5cdFx0XHQvLyBJZiBtb3VzZSBpcyBkcmFnZ2VkIG9mZiBvZiBlbGVtZW50IHdoaWxlIGRvd24sIGl0IGlzIG5vdCBjbGlja2VkIGFueW1vcmVcblx0XHRcdHRoaXMuaXNDbGlja2VkID0gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIE92ZXJyaWRhYmxlIG1ldGhvZCBmb3IgY2FsY3VsYXRpbmcgYmFja2dyb3VuZCBjb2xvciAtIHVzZWZ1bCBmb3IgZWxlbWVudHMgdGhhdCB3YW50IHRvIGJlIGNvbG9yZWQgb24gZGlmZmVyZW50IGFmdGVyIGNlcnRhaW4gZXZlbnRzXG5cdCAqIEByZXR1cm5zIFRoZSBiYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSBVSUVsZW1lbnRcblx0ICovXG5cdGNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpOiBDb2xvciB7XG5cdFx0cmV0dXJuIHRoaXMuYmFja2dyb3VuZENvbG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIE92ZXJyaWRhYmxlIG1ldGhvZCBmb3IgY2FsY3VsYXRpbmcgYm9yZGVyIGNvbG9yIC0gdXNlZnVsIGZvciBlbGVtZW50cyB0aGF0IHdhbnQgdG8gYmUgY29sb3JlZCBvbiBkaWZmZXJlbnQgYWZ0ZXIgY2VydGFpbiBldmVudHNcblx0ICogQHJldHVybnMgVGhlIGJvcmRlciBjb2xvciBvZiB0aGUgVUlFbGVtZW50XG5cdCAqL1xuXHRjYWxjdWxhdGVCb3JkZXJDb2xvcigpOiBDb2xvciB7XG5cdFx0cmV0dXJuIHRoaXMuYm9yZGVyQ29sb3I7XG5cdH1cbn0iLCJpbXBvcnQgTGFiZWwgZnJvbSBcIi4vTGFiZWxcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuXG4vKiogQSBjbGlja2FibGUgYnV0dG9uIFVJRWxlbWVudCAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQnV0dG9uIGV4dGVuZHMgTGFiZWwge1xuXG5cdGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCB0ZXh0OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHBvc2l0aW9uLCB0ZXh0KTtcblx0XHRcblx0XHR0aGlzLmJhY2tncm91bmRDb2xvciA9IG5ldyBDb2xvcigxNTAsIDc1LCAyMDMpO1xuXHRcdHRoaXMuYm9yZGVyQ29sb3IgPSBuZXcgQ29sb3IoNDEsIDQ2LCAzMCk7XG5cdFx0dGhpcy50ZXh0Q29sb3IgPSBuZXcgQ29sb3IoMjU1LCAyNTUsIDI1NSk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0Y2FsY3VsYXRlQmFja2dyb3VuZENvbG9yKCk6IENvbG9yIHtcblx0XHQvLyBDaGFuZ2UgdGhlIGJhY2tncm91bmQgY29sb3IgaWYgY2xpY2tlZCBvciBob3ZlcmVkXG5cdFx0aWYodGhpcy5pc0VudGVyZWQgJiYgIXRoaXMuaXNDbGlja2VkKXtcblx0XHRcdHJldHVybiB0aGlzLmJhY2tncm91bmRDb2xvci5saWdodGVuKCk7XG5cdFx0fSBlbHNlIGlmKHRoaXMuaXNDbGlja2VkKXtcblx0XHRcdHJldHVybiB0aGlzLmJhY2tncm91bmRDb2xvci5kYXJrZW4oKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHRoaXMuYmFja2dyb3VuZENvbG9yO1xuXHRcdH1cblx0fVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IFVJRWxlbWVudCBmcm9tIFwiLi4vVUlFbGVtZW50XCI7XG5cbi8qKiBBIGJhc2ljIHRleHQtY29udGFpbmluZyBsYWJlbCAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGFiZWwgZXh0ZW5kcyBVSUVsZW1lbnR7XG5cdC8qKiBUaGUgY29sb3Igb2YgdGhlIHRleHQgb2YgdGhpcyBVSUVsZW1lbnQgKi9cblx0dGV4dENvbG9yOiBDb2xvcjtcblx0LyoqIFRoZSB2YWx1ZSBvZiB0aGUgdGV4dCBvZiB0aGlzIFVJRWxlbWVudCAqL1xuXHR0ZXh0OiBzdHJpbmc7XG5cdC8qKiBUaGUgbmFtZSBvZiB0aGUgZm9udCAqL1xuXHRmb250OiBzdHJpbmc7XG5cdC8qKiBUaGUgc2l6ZSBvZiB0aGUgZm9udCAqL1xuXHRmb250U2l6ZTogbnVtYmVyO1xuXHQvKiogVGhlIGhvcml6b250YWwgYWxpZ25tZW50IG9mIHRoZSB0ZXh0IHdpdGhpbiB0aGUgbGFiZWwgKi9cblx0cHJvdGVjdGVkIGhBbGlnbjogc3RyaW5nO1xuXHQvKiogVGhlIHZlcnRpY2FsIGFsaWdubWVudCBvZiB0ZXh0IHdpdGhpbiB0aGUgbGFiZWwgKi9cblx0cHJvdGVjdGVkIHZBbGlnbjogc3RyaW5nO1xuXG5cdC8qKiBBIGZsYWcgZm9yIGlmIHRoZSB3aWR0aCBvZiB0aGUgdGV4dCBoYXMgYmVlbiBtZWFzdXJlZCBvbiB0aGUgY2FudmFzIGZvciBhdXRvIHdpZHRoIGFzc2lnbm1lbnQgKi9cblx0cHJvdGVjdGVkIHNpemVBc3NpZ25lZDogYm9vbGVhbjtcblxuXHRjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMiwgdGV4dDogc3RyaW5nKXtcblx0XHRzdXBlcihwb3NpdGlvbik7XG5cdFx0dGhpcy50ZXh0ID0gdGV4dDtcblx0XHR0aGlzLnRleHRDb2xvciA9IG5ldyBDb2xvcigwLCAwLCAwLCAxKTtcblx0XHR0aGlzLmZvbnQgPSBcIkFyaWFsXCI7XG5cdFx0dGhpcy5mb250U2l6ZSA9IDMwO1xuXHRcdHRoaXMuaEFsaWduID0gXCJjZW50ZXJcIjtcblx0XHR0aGlzLnZBbGlnbiA9IFwiY2VudGVyXCI7XG5cblx0XHR0aGlzLnNpemVBc3NpZ25lZCA9IGZhbHNlO1xuXHR9XG5cblx0Ly8gQGRlcHJlY2F0ZWRcblx0c2V0VGV4dCh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcblx0XHR0aGlzLnRleHQgPSB0ZXh0O1xuXHR9XG5cblx0Ly8gQGRlcHJlY2F0ZWRcblx0c2V0VGV4dENvbG9yKGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdHRoaXMudGV4dENvbG9yID0gY29sb3I7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBhIHN0cmluZyBjb250YWluZyB0aGUgZm9udCBkZXRhaWxzIGZvciByZW5kZXJpbmdcblx0ICogQHJldHVybnMgQSBzdHJpbmcgY29udGFpbmluZyB0aGUgZm9udCBkZXRhaWxzXG5cdCAqL1xuXHRnZXRGb250U3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMuZm9udFNpemUgKyBcInB4IFwiICsgdGhpcy5mb250O1xuXHR9XG5cblx0LyoqXG5cdCAqIE92ZXJyaWRhYmxlIG1ldGhvZCBmb3IgY2FsY3VsYXRpbmcgdGV4dCBjb2xvciAtIHVzZWZ1bCBmb3IgZWxlbWVudHMgdGhhdCB3YW50IHRvIGJlIGNvbG9yZWQgb24gZGlmZmVyZW50IGFmdGVyIGNlcnRhaW4gZXZlbnRzXG5cdCAqIEByZXR1cm5zIGEgc3RyaW5nIGNvbnRhaW5nIHRoZSB0ZXh0IGNvbG9yXG5cdCAqL1xuXHRjYWxjdWxhdGVUZXh0Q29sb3IoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy50ZXh0Q29sb3IudG9TdHJpbmdSR0JBKCk7XG5cdH1cblxuXHQvKipcblx0ICogVXNlcyB0aGUgY2FudmFzIHRvIGNhbGN1bGF0ZSB0aGUgd2lkdGggb2YgdGhlIHRleHRcblx0ICogQHBhcmFtIGN0eCBUaGUgcmVuZGVyaW5nIGNvbnRleHRcblx0ICogQHJldHVybnMgQSBudW1iZXIgcmVwcmVzZW50aW5nIHRoZSByZW5kZXJlZCB0ZXh0IHdpZHRoXG5cdCAqL1xuXHRwcm90ZWN0ZWQgY2FsY3VsYXRlVGV4dFdpZHRoKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogbnVtYmVyIHtcblx0XHRjdHguZm9udCA9IHRoaXMuZm9udFNpemUgKyBcInB4IFwiICsgdGhpcy5mb250O1xuXHRcdHJldHVybiBjdHgubWVhc3VyZVRleHQodGhpcy50ZXh0KS53aWR0aDtcblx0fVxuXG5cdHNldEhBbGlnbihhbGlnbjogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5oQWxpZ24gPSBhbGlnbjtcblx0fVxuXG5cdHNldFZBbGlnbihhbGlnbjogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy52QWxpZ24gPSBhbGlnbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBDYWxjdWxhdGUgdGhlIG9mZnNldCBvZiB0aGUgdGV4dCAtIHRoaXMgaXMgdXNlZCBmb3IgcmVuZGVyaW5nIHRleHQgd2l0aCBkaWZmZXJlbnQgYWxpZ25tZW50c1xuXHQgKiBAcGFyYW0gY3R4IFRoZSByZW5kZXJpbmcgY29udGV4dFxuXHQgKiBAcmV0dXJucyBUaGUgb2Zmc2V0IG9mIHRoZSB0ZXh0IGluIGEgVmVjMlxuXHQgKi9cblx0Y2FsY3VsYXRlVGV4dE9mZnNldChjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk6IFZlYzIge1xuXHRcdGxldCB0ZXh0V2lkdGggPSB0aGlzLmNhbGN1bGF0ZVRleHRXaWR0aChjdHgpO1xuXG5cdFx0bGV0IG9mZnNldCA9IG5ldyBWZWMyKDAsIDApO1xuXG5cdFx0bGV0IGhEaWZmID0gdGhpcy5zaXplLnggLSB0ZXh0V2lkdGg7XG5cdFx0aWYodGhpcy5oQWxpZ24gPT09IEhBbGlnbi5DRU5URVIpe1xuXHRcdFx0b2Zmc2V0LnggPSBoRGlmZi8yO1xuXHRcdH0gZWxzZSBpZiAodGhpcy5oQWxpZ24gPT09IEhBbGlnbi5SSUdIVCl7XG5cdFx0XHRvZmZzZXQueCA9IGhEaWZmO1xuXHRcdH1cblxuXHRcdGlmKHRoaXMudkFsaWduID09PSBWQWxpZ24uVE9QKXtcblx0XHRcdGN0eC50ZXh0QmFzZWxpbmUgPSBcInRvcFwiO1xuXHRcdFx0b2Zmc2V0LnkgPSAwO1xuXHRcdH0gZWxzZSBpZiAodGhpcy52QWxpZ24gPT09IFZBbGlnbi5CT1RUT00pe1xuXHRcdFx0Y3R4LnRleHRCYXNlbGluZSA9IFwiYm90dG9tXCI7XG5cdFx0XHRvZmZzZXQueSA9IHRoaXMuc2l6ZS55O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjdHgudGV4dEJhc2VsaW5lID0gXCJtaWRkbGVcIjtcblx0XHRcdG9mZnNldC55ID0gdGhpcy5zaXplLnkvMjtcblx0XHR9XG5cblx0XHRyZXR1cm4gb2Zmc2V0O1xuXHR9XG5cblx0cHJvdGVjdGVkIHNpemVDaGFuZ2VkKCk6IHZvaWQge1xuXHRcdHN1cGVyLnNpemVDaGFuZ2VkKCk7XG5cdFx0dGhpcy5zaXplQXNzaWduZWQgPSB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEF1dG9tYXRpY2FsbHkgc2l6ZXMgdGhlIGVsZW1lbnQgdG8gdGhlIHRleHQgd2l0aGluIGl0XG5cdCAqIEBwYXJhbSBjdHggVGhlIHJlbmRlcmluZyBjb250ZXh0XG5cdCAqL1xuXHRwcm90ZWN0ZWQgYXV0b1NpemUoY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpOiB2b2lkIHtcblx0XHRsZXQgd2lkdGggPSB0aGlzLmNhbGN1bGF0ZVRleHRXaWR0aChjdHgpO1xuXHRcdGxldCBoZWlnaHQgPSB0aGlzLmZvbnRTaXplO1xuXHRcdHRoaXMuc2l6ZS5zZXQod2lkdGggKyB0aGlzLnBhZGRpbmcueCoyLCBoZWlnaHQgKyB0aGlzLnBhZGRpbmcueSoyKTtcblx0XHR0aGlzLnNpemVBc3NpZ25lZCA9IHRydWU7XG5cdH1cblxuXHQvKipcblx0ICogSW5pdGlhbGx5IGFzc2lnbnMgYSBzaXplIHRvIHRoZSBVSUVsZW1lbnQgaWYgbm9uZSBpcyBwcm92aWRlZFxuXHQgKiBAcGFyYW0gY3R4IFRoZSByZW5kZXJpbmcgY29udGV4dFxuXHQgKi9cblx0aGFuZGxlSW5pdGlhbFNpemluZyhjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk6IHZvaWQge1xuXHRcdGlmKCF0aGlzLnNpemVBc3NpZ25lZCl7XG5cdFx0XHR0aGlzLmF1dG9TaXplKGN0eCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIE9uIHRoZSBuZXh0IHJlbmRlciwgc2l6ZSB0aGlzIGVsZW1lbnQgdG8gaXQncyBjdXJyZW50IHRleHQgdXNpbmcgaXRzIGN1cnJlbnQgZm9udCBzaXplICovXG5cdHNpemVUb1RleHQoKTogdm9pZCB7XG5cdFx0dGhpcy5zaXplQXNzaWduZWQgPSBmYWxzZTtcblx0fVxufVxuXG5leHBvcnQgZW51bSBWQWxpZ24ge1xuXHRUT1AgPSBcInRvcFwiLFxuXHRDRU5URVIgPSBcImNlbnRlclwiLFxuXHRCT1RUT00gPSBcImJvdHRvbVwiXG59XG5cbmV4cG9ydCBlbnVtIEhBbGlnbiB7XG5cdExFRlQgPSBcImxlZnRcIixcblx0Q0VOVEVSID0gXCJjZW50ZXJcIixcblx0UklHSFQgPSBcInJpZ2h0XCJcbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vLi4vSW5wdXQvSW5wdXRcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IFVJRWxlbWVudCBmcm9tIFwiLi4vVUlFbGVtZW50XCI7XG5cbi8qKiBBIHNsaWRlciBVSUVsZW1lbnQgKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNsaWRlciBleHRlbmRzIFVJRWxlbWVudCB7XG4gICAgLyoqIFRoZSB2YWx1ZSBvZiB0aGUgc2xpZGVyIGZyb20gWzAsIDFdICovXG4gICAgcHJvdGVjdGVkIHZhbHVlOiBudW1iZXI7XG4gICAgLyoqIFRoZSBjb2xvciBvZiB0aGUgc2xpZGVyIG5pYiAqL1xuICAgIHB1YmxpYyBuaWJDb2xvcjogQ29sb3I7XG4gICAgLyoqIFRoZSBzaXplIG9mIHRoZSBuaWIgKi9cbiAgICBwdWJsaWMgbmliU2l6ZTogVmVjMjtcbiAgICAvKiogVGhlIGNvbG9yIG9mIHRoZSBzbGlkZXIgdHJhY2sgKi9cbiAgICBwdWJsaWMgc2xpZGVyQ29sb3I6IENvbG9yO1xuICAgIC8qKiBUaGUgcmVhY3Rpb24gb2YgdGhpcyBVSUVsZW1lbnQgdG8gYSB2YWx1ZSBjaGFuZ2UgKi9cbiAgICBwdWJsaWMgb25WYWx1ZUNoYW5nZTogRnVuY3Rpb247XG4gICAgLyoqIFRoZSBldmVudCBwcm9wYWdhdGVkIGJ5IHRoaXMgVUlFbGVtZW50IHdoZW4gdmFsdWUgY2hhbmdlcyAqL1xuICAgIHB1YmxpYyBvblZhbHVlQ2hhbmdlRXZlbnRJZDogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IocG9zaXRpb246IFZlYzIsIGluaXRWYWx1ZTogbnVtYmVyKXtcbiAgICAgICAgc3VwZXIocG9zaXRpb24pO1xuXG4gICAgICAgIHRoaXMudmFsdWUgPSBpbml0VmFsdWU7XG4gICAgICAgIHRoaXMubmliQ29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgIHRoaXMuc2xpZGVyQ29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgdGhpcy5ib3JkZXJDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICB0aGlzLm5pYlNpemUgPSBuZXcgVmVjMigxMCwgMjApO1xuXG4gICAgICAgIC8vIFNldCBhIGRlZmF1bHQgc2l6ZVxuICAgICAgICB0aGlzLnNpemUuc2V0KDIwMCwgMjApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgb2YgdGhlIHNsaWRlclxuICAgICAqIEByZXR1cm5zIFRoZSB2YWx1ZSBvZiB0aGUgc2xpZGVyXG4gICAgICovXG4gICAgZ2V0VmFsdWUoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfVxuXG4gICAgLyoqIEEgbWV0aG9kIGNhbGxlZCBpbiByZXNwb25zZSB0byB0aGUgdmFsdWUgY2hhbmdpbmcgKi9cbiAgICBwcm90ZWN0ZWQgdmFsdWVDaGFuZ2VkKCk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLm9uVmFsdWVDaGFuZ2Upe1xuICAgICAgICAgICAgdGhpcy5vblZhbHVlQ2hhbmdlKHRoaXMudmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5vblZhbHVlQ2hhbmdlRXZlbnRJZCl7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHRoaXMub25WYWx1ZUNoYW5nZUV2ZW50SWQsIHt0YXJnZXQ6IHRoaXMsIHZhbHVlOiB0aGlzLnZhbHVlfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgc3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgaWYodGhpcy5pc0NsaWNrZWQpe1xuICAgICAgICAgICAgbGV0IHZhbCA9IE1hdGhVdGlscy5pbnZMZXJwKHRoaXMucG9zaXRpb24ueCAtIHRoaXMuc2l6ZS54LzIsIHRoaXMucG9zaXRpb24ueCArIHRoaXMuc2l6ZS54LzIsIElucHV0LmdldE1vdXNlUG9zaXRpb24oKS54KTtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBNYXRoVXRpbHMuY2xhbXAwMSh2YWwpO1xuICAgICAgICAgICAgdGhpcy52YWx1ZUNoYW5nZWQoKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi9MYWJlbFwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi8uLi9JbnB1dC9JbnB1dFwiO1xuXG4vKiogQSB0ZXh0IGlucHV0IFVJRWxlbWVudCAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGV4dElucHV0IGV4dGVuZHMgTGFiZWwge1xuICAgIC8qKiBBIGZsYWcgdGhlIHJlcHJlc2VudHMgd2hldGhlciB0aGUgdXNlciBjYW4gdHlwZSBpbiB0aGlzIFRleHRJbnB1dCAqL1xuICAgIGZvY3VzZWQ6IGJvb2xlYW47XG4gICAgLyoqIFRoZSBwb3NpdGlvbiBvZiB0aGUgY3Vyc29yIGluIHRoaXMgVGV4dElucHV0ICovXG4gICAgY3Vyc29yQ291bnRlcjogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IocG9zaXRpb246IFZlYzIpe1xuICAgICAgICBzdXBlcihwb3NpdGlvbiwgXCJcIik7XG5cbiAgICAgICAgdGhpcy5mb2N1c2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY3Vyc29yQ291bnRlciA9IDA7XG5cbiAgICAgICAgLy8gR2l2ZSBhIGRlZmF1bHQgc2l6ZSB0byB0aGUgeCBvbmx5XG4gICAgICAgIHRoaXMuc2l6ZS5zZXQoMjAwLCB0aGlzLmZvbnRTaXplKTtcbiAgICAgICAgdGhpcy5oQWxpZ24gPSBcImxlZnRcIjtcblxuICAgICAgICB0aGlzLmJvcmRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIGlmKElucHV0LmlzTW91c2VKdXN0UHJlc3NlZCgpKXtcblx0XHRcdGxldCBjbGlja1BvcyA9IElucHV0LmdldE1vdXNlUHJlc3NQb3NpdGlvbigpO1xuXHRcdFx0aWYodGhpcy5jb250YWlucyhjbGlja1Bvcy54LCBjbGlja1Bvcy55KSl7XG4gICAgICAgICAgICAgICAgdGhpcy5mb2N1c2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnNvckNvdW50ZXIgPSAzMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5mb2N1c2VkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLmZvY3VzZWQpe1xuICAgICAgICAgICAgbGV0IGtleXMgPSBJbnB1dC5nZXRLZXlzSnVzdFByZXNzZWQoKTtcbiAgICAgICAgICAgIGxldCBudW1zID0gXCIxMjM0NTY3ODkwXCI7XG4gICAgICAgICAgICBsZXQgc3BlY2lhbENoYXJzID0gXCJgfiFAIyQlXiYqKCktXz0rW3tdfVxcXFx8OzonXFxcIiw8Lj4vP1wiO1xuICAgICAgICAgICAgbGV0IGxldHRlcnMgPSBcInF3ZXJ0eXVpb3Bhc2RmZ2hqa2x6eGN2Ym5tXCI7XG4gICAgICAgICAgICBsZXQgbWFzayA9IG51bXMgKyBzcGVjaWFsQ2hhcnMgKyBsZXR0ZXJzO1xuICAgICAgICAgICAga2V5cyA9IGtleXMuZmlsdGVyKGtleSA9PiBtYXNrLmluY2x1ZGVzKGtleSkpO1xuICAgICAgICAgICAgbGV0IHNoaWZ0UHJlc3NlZCA9IElucHV0LmlzS2V5UHJlc3NlZChcInNoaWZ0XCIpO1xuICAgICAgICAgICAgbGV0IGJhY2tzcGFjZVByZXNzZWQgPSBJbnB1dC5pc0tleUp1c3RQcmVzc2VkKFwiYmFja3NwYWNlXCIpO1xuICAgICAgICAgICAgbGV0IHNwYWNlUHJlc3NlZCA9IElucHV0LmlzS2V5SnVzdFByZXNzZWQoXCJzcGFjZVwiKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYoYmFja3NwYWNlUHJlc3NlZCl7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gdGhpcy50ZXh0LnN1YnN0cmluZygwLCB0aGlzLnRleHQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoc3BhY2VQcmVzc2VkKXtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgKz0gXCIgXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYoa2V5cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgaWYoc2hpZnRQcmVzc2VkKXtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0ICs9IGtleXNbMF0udG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHQgKz0ga2V5c1swXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59IiwiZXhwb3J0IGVudW0gVUlFbGVtZW50VHlwZSB7XG5cdEJVVFRPTiA9IFwiQlVUVE9OXCIsXG5cdExBQkVMID0gXCJMQUJFTFwiLFxuXHRTTElERVIgPSBcIlNMSURFUlwiLFxuXHRURVhUX0lOUFVUID0gXCJURVhUSU5QVVRcIlxufSIsImltcG9ydCBOYXZpZ2FibGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL05hdmlnYWJsZVwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgTmF2aWdhdGlvblBhdGggZnJvbSBcIi4vTmF2aWdhdGlvblBhdGhcIjtcblxuLyoqXG4gKiBUaGUgbWFuYWdlciBjbGFzcyBmb3IgbmF2aWdhdGlvbi5cbiAqIEhhbmRsZXMgYWxsIG5hdmlnYWJsZSBlbnRpdGllcywgc3VjaCBhbmQgYWxsb3dzIHRoZW0gdG8gYmUgYWNjZXNzZWQgYnkgb3V0c2lkZSBzeXN0ZW1zIGJ5IHJlcXVlc3RpbmcgYSBwYXRoXG4gKiBmcm9tIG9uZSBwb3NpdGlvbiB0byBhbm90aGVyLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0aW9uTWFuYWdlciB7XG5cdC8qKiBUaGUgbGlzdCBvZiBhbGwgbmF2aWdhYmxlIGVudGl0aWVzICovXG5cdHByb3RlY3RlZCBuYXZpZ2FibGVFbnRpdGllczogTWFwPE5hdmlnYWJsZT47XG5cblx0Y29uc3RydWN0b3IoKXtcblx0XHR0aGlzLm5hdmlnYWJsZUVudGl0aWVzID0gbmV3IE1hcCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBuYXZpZ2FibGUgZW50aXR5IHRvIHRoZSBOYXZpZ2F0aW9uTWFuYWdlclxuXHQgKiBAcGFyYW0gbmF2TmFtZSBUaGUgbmFtZSBvZiB0aGUgbmF2aWdhYmxlIGVudGl0cnlcblx0ICogQHBhcmFtIG5hdiBUaGUgYWN0dWFsIE5hdmlnYWJsZSBpbnN0YW5jZVxuXHQgKi9cblx0YWRkTmF2aWdhYmxlRW50aXR5KG5hdk5hbWU6IHN0cmluZywgbmF2OiBOYXZpZ2FibGUpOiB2b2lkIHtcblx0XHR0aGlzLm5hdmlnYWJsZUVudGl0aWVzLmFkZChuYXZOYW1lLCBuYXYpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYSBwYXRoIGZyb21lIG9uZSBwb2ludCB0byBhbm90aGVyIHVzaW5nIGEgc3BlY2lmaWVkIE5hdmlnYWJsZSBvYmplY3Rcblx0ICogQHBhcmFtIG5hdk5hbWUgVGhlIG5hbWUgb2YgdGhlIHJlZ2lzdGVyZWQgTmF2aWdhYmxlIG9iamVjdFxuXHQgKiBAcGFyYW0gZnJvbVBvc2l0aW9uIFRoZSBzdGFydGluZyBwb3NpdGlvbiBvZiBuYXZpZ2F0aW9uXG5cdCAqIEBwYXJhbSB0b1Bvc2l0aW9uIFRoZSBlbmRpbmcgcG9zaXRpb24gb2YgTmF2aWdhdGlvblxuXHQgKiBAcGFyYW0gZGlyZWN0IElmIHRydWUsIGdvIGRpcmVjdCBmcm9tIGZyb21Qb3NpdGlvbiB0byB0b1Bvc2l0aW9uLCBkb24ndCB1c2UgTmF2TWVzaFxuXHQgKiBAcmV0dXJucyBBIE5hdmlnYXRpb25QYXRoIGNvbnRhaW5pbmcgdGhlIHJvdXRlIHRvIHRha2Ugb3ZlciB0aGUgTmF2aWdhYmxlIGVudGl0eSB0byBnZXQgYmV0d2VlbiB0aGUgcHJvdmlkZWQgcG9zaXRpb25zLlxuXHQgKi9cblx0Z2V0UGF0aChuYXZOYW1lOiBzdHJpbmcsIGZyb21Qb3NpdGlvbjogVmVjMiwgdG9Qb3NpdGlvbjogVmVjMiwgZGlyZWN0PzogYm9vbGVhbik6IE5hdmlnYXRpb25QYXRoIHtcblx0XHRsZXQgbmF2ID0gdGhpcy5uYXZpZ2FibGVFbnRpdGllcy5nZXQobmF2TmFtZSk7XG5cdFx0cmV0dXJuIG5hdi5nZXROYXZpZ2F0aW9uUGF0aChmcm9tUG9zaXRpb24uY2xvbmUoKSwgdG9Qb3NpdGlvbi5jbG9uZSgpLCBkaXJlY3QpO1xuXHR9XG59IiwiaW1wb3J0IFN0YWNrIGZyb20gXCIuLi9EYXRhVHlwZXMvU3RhY2tcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuXG4vKipcbiAqIEEgcGF0aCB0aGF0IEFJcyBjYW4gZm9sbG93LiBVc2VzIGZpbmlzaE1vdmUoKSBpbiBQaHlzaWNhbCB0byBkZXRlcm1pbmUgcHJvZ3Jlc3Mgb24gdGhlIHJvdXRlXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE5hdmlnYXRpb25QYXRoIHtcblx0LyoqIFRoZSBuYXZpZ2F0aW9uIHBhdGgsIHN0b3JlZCBhcyBhIHN0YWNrIG9mIG5leHQgcG9zaXRpb25zICovXG5cdHByb3RlY3RlZCBwYXRoOiBTdGFjazxWZWMyPjtcblx0LyoqIFRoZSBjdXJyZW50IGRpcmVjdGlvbiBvZiBtb3ZlbWVudCAqL1xuXHRwcm90ZWN0ZWQgY3VycmVudE1vdmVEaXJlY3Rpb246IFZlYzI7XG5cdC8qKiBUaGUgZGlzdGFuY2UgYSBub2RlIG11c3QgYmUgdG8gYSBwb2ludCB0byBjb25zaWRlciBpdCBhcyBoYXZpbmcgYXJyaXZlZCAqL1xuXHRwcm90ZWN0ZWQgZGlzdGFuY2VUaHJlc2hvbGQ6IG51bWJlcjtcblxuXHQvKipcblx0ICogQ29uc3RydWN0cyBhIG5ldyBOYXZpZ2F0aW9uUGF0aFxuXHQgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCBvZiBub2RlcyB0byB0YWtlXG5cdCAqL1xuXHRjb25zdHJ1Y3RvcihwYXRoOiBTdGFjazxWZWMyPil7XG5cdFx0dGhpcy5wYXRoID0gcGF0aDtcblx0XHR0aGlzLmN1cnJlbnRNb3ZlRGlyZWN0aW9uID0gVmVjMi5aRVJPO1xuXHRcdHRoaXMuZGlzdGFuY2VUaHJlc2hvbGQgPSA0O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHN0YXR1cyBvZiBuYXZpZ2F0aW9uIGFsb25nIHRoaXMgTmF2aWdhdGlvblBhdGhcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbm9kZSBoYXMgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBwYXRoLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdGlzRG9uZSgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5wYXRoLmlzRW1wdHkoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBtb3ZlbWVudCBkaXJlY3Rpb24gaW4gdGhlIGN1cnJlbnQgcG9zaXRpb24gYWxvbmcgdGhlIHBhdGhcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gbW92ZSBhbG9uZyB0aGUgcGF0aFxuXHQgKiBAcmV0dXJucyBUaGUgbW92ZW1lbnQgZGlyZWN0aW9uIGFzIGEgVmVjMlxuXHQgKi9cblx0Z2V0TW92ZURpcmVjdGlvbihub2RlOiBHYW1lTm9kZSk6IFZlYzIge1xuXHRcdC8vIFJldHVybiBkaXJlY3Rpb24gdG8gbmV4dCBwb2ludCBpbiB0aGUgbmF2XG5cdFx0cmV0dXJuIG5vZGUucG9zaXRpb24uZGlyVG8odGhpcy5wYXRoLnBlZWsoKSk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlcyB0aGlzIE5hdmlnYXRpb25QYXRoIHRvIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBHYW1lTm9kZVxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSBtb3ZpbmcgYWxvbmcgdGhlIHBhdGhcblx0ICovXG5cdGhhbmRsZVBhdGhQcm9ncmVzcyhub2RlOiBHYW1lTm9kZSk6IHZvaWQge1xuXHRcdGlmKG5vZGUucG9zaXRpb24uZGlzdGFuY2VTcVRvKHRoaXMucGF0aC5wZWVrKCkpIDwgdGhpcy5kaXN0YW5jZVRocmVzaG9sZCp0aGlzLmRpc3RhbmNlVGhyZXNob2xkKXtcblx0XHRcdC8vIFdlJ3ZlIHJlYWNoZWQgb3VyIG5vZGUsIG1vdmUgb24gdG8gdGhlIG5leHQgZGVzdGluYXRpb25cblx0XHRcdHRoaXMucGF0aC5wb3AoKTtcblx0XHR9XG5cdH1cblxuXHR0b1N0cmluZygpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLnBhdGgudG9TdHJpbmcoKVxuXHR9XG59IiwiaW1wb3J0IFBvc2l0aW9uR3JhcGggZnJvbSBcIi4uL0RhdGFUeXBlcy9HcmFwaHMvUG9zaXRpb25HcmFwaFwiO1xuaW1wb3J0IE5hdmlnYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvTmF2aWdhYmxlXCI7XG5pbXBvcnQgU3RhY2sgZnJvbSBcIi4uL0RhdGFUeXBlcy9TdGFja1wiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR3JhcGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvR3JhcGhVdGlsc1wiO1xuaW1wb3J0IE5hdmlnYXRpb25QYXRoIGZyb20gXCIuL05hdmlnYXRpb25QYXRoXCI7XG5cbi8qKlxuICogQW4gaW1wbGVtZW50YXRpb24gb2YgYSBOYXZtZXNoLiBOYXZtZXNoZXMgYXJlIGdyYXBocyBpbiB0aGUgZ2FtZSB3b3JsZCBhbG9uZyB3aGljaCBub2RlcyBjYW4gbW92ZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTmF2bWVzaCBpbXBsZW1lbnRzIE5hdmlnYWJsZSB7XG5cdC8qKiBUaGUgZ3JhcGggb2YgcG9pbnRzIGluIHRoZSBOYXZNZXNoICovXG5cdHByb3RlY3RlZCBncmFwaDogUG9zaXRpb25HcmFwaDtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBOYXZtZXNoIGZyb20gdGhlIHBvaW50cyBpbiB0aGUgc3BlZWNpZmllZCBncmFwaFxuXHQgKiBAcGFyYW0gZ3JhcGggVGhlIGdyYXBoIHRvIGNvbnN0cnVjdCBhIG5hdm1lc2ggZnJvbVxuXHQgKi9cblx0Y29uc3RydWN0b3IoZ3JhcGg6IFBvc2l0aW9uR3JhcGgpe1xuXHRcdHRoaXMuZ3JhcGggPSBncmFwaDtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRnZXROYXZpZ2F0aW9uUGF0aChmcm9tUG9zaXRpb246IFZlYzIsIHRvUG9zaXRpb246IFZlYzIsIGRpcmVjdDogYm9vbGVhbik6IE5hdmlnYXRpb25QYXRoIHtcblx0XHRsZXQgc3RhcnQgPSB0aGlzLmdldENsb3Nlc3ROb2RlKGZyb21Qb3NpdGlvbik7XG5cdFx0bGV0IGVuZCA9IHRoaXMuZ2V0Q2xvc2VzdE5vZGUodG9Qb3NpdGlvbik7XG5cblx0XHRsZXQgcGF0aFN0YWNrID0gbmV3IFN0YWNrPFZlYzI+KHRoaXMuZ3JhcGgubnVtVmVydGljZXMpO1xuXHRcdFxuXHRcdC8vIFB1c2ggdGhlIGZpbmFsIHBvc2l0aW9uIGFuZCB0aGUgZmluYWwgcG9zaXRpb24gaW4gdGhlIGdyYXBoXG5cdFx0cGF0aFN0YWNrLnB1c2godG9Qb3NpdGlvbi5jbG9uZSgpKTtcblxuXHRcdGlmIChkaXJlY3QpIHtcblx0XHRcdHJldHVybiBuZXcgTmF2aWdhdGlvblBhdGgocGF0aFN0YWNrKTtcblx0XHR9XG5cblx0XHRwYXRoU3RhY2sucHVzaCh0aGlzLmdyYXBoLnBvc2l0aW9uc1tlbmRdKTtcblxuXHRcdGxldCBwYXJlbnQgPSBHcmFwaFV0aWxzLmRqaWtzdHJhKHRoaXMuZ3JhcGgsIHN0YXJ0KTtcblxuXHRcdC8vIEFkZCBhbGwgcGFyZW50cyBhbG9uZyB0aGUgcGF0aFxuXHRcdGxldCBpID0gZW5kO1xuXHRcdHdoaWxlKHBhcmVudFtpXSAhPT0gLTEpe1xuXHRcdFx0cGF0aFN0YWNrLnB1c2godGhpcy5ncmFwaC5wb3NpdGlvbnNbcGFyZW50W2ldXSk7XG5cdFx0XHRpID0gcGFyZW50W2ldO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgTmF2aWdhdGlvblBhdGgocGF0aFN0YWNrKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjbG9zZXN0IG5vZGUgaW4gdGhpcyBOYXZtZXNoIHRvIHRoZSBzcGVjaWZpZWQgcG9zaXRpb25cblx0ICogQHBhcmFtIHBvc2l0aW9uIFRoZSBwb3NpdGlvbiB0byBxdWVyeVxuXHQgKiBAcmV0dXJucyBUaGUgaW5kZXggb2YgdGhlIGNsb3Nlc3Qgbm9kZSBpbiB0aGUgTmF2bWVzaCB0byB0aGUgcG9zaXRpb25cblx0ICovXG5cdHByb3RlY3RlZCBnZXRDbG9zZXN0Tm9kZShwb3NpdGlvbjogVmVjMik6IG51bWJlciB7XG5cdFx0bGV0IG4gPSB0aGlzLmdyYXBoLm51bVZlcnRpY2VzO1xuXHRcdGxldCBpID0gMTtcblx0XHRsZXQgaW5kZXggPSAwO1xuXHRcdGxldCBkaXN0ID0gcG9zaXRpb24uZGlzdGFuY2VTcVRvKHRoaXMuZ3JhcGgucG9zaXRpb25zWzBdKTtcblx0XHR3aGlsZShpIDwgbil7XG5cdFx0XHRsZXQgZCA9IHBvc2l0aW9uLmRpc3RhbmNlU3FUbyh0aGlzLmdyYXBoLnBvc2l0aW9uc1tpXSk7XG5cdFx0XHRpZihkIDwgZGlzdCl7XG5cdFx0XHRcdGRpc3QgPSBkO1xuXHRcdFx0XHRpbmRleCA9IGk7XG5cdFx0XHR9XG5cdFx0XHRpKys7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGluZGV4O1xuXHR9XG59IiwiaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IFBoeXNpY2FsIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9QaHlzaWNhbFwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBQaHlzaWNzTWFuYWdlciBmcm9tIFwiLi9QaHlzaWNzTWFuYWdlclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgQXJlYUNvbGxpc2lvbiBmcm9tIFwiLi4vRGF0YVR5cGVzL1BoeXNpY3MvQXJlYUNvbGxpc2lvblwiO1xuaW1wb3J0IFVuaXF1ZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVW5pcXVlXCI7XG5cbi8qKlxuICogQUxHT1JJVEhNOlxuICogXHRJbiBhbiBlZmZvcnQgdG8ga2VlcCB0aGluZ3Mgc2ltcGxlIGFuZCB3b3JraW5nIGVmZmVjdGl2ZWx5LCBlYWNoIGR5bmFtaWMgbm9kZSB3aWxsIHJlc29sdmUgaXRzXG4gKiBcdGNvbGxpc2lvbnMgY29uc2lkZXJpbmcgdGhlIHJlc3Qgb2YgdGhlIHdvcmxkIGFzIHN0YXRpYy5cbiAqIFxuICogXHRDb2xsaXNpb24gZGV0ZWN0aW5nIHdpbGwgaGFwcGVuIGZpcnN0LiBUaGlzIGNhbiBiZSBjb25zaWRlcmVkIGEgYnJvYWQgcGhhc2UsIGJ1dCBpdCBpcyBub3QgZXNwZWNpYWxseVxuICogXHRlZmZpY2llbnQsIGFzIGl0IGRvZXMgbm90IG5lZWQgdG8gYmUgZm9yIHRoaXMgZ2FtZSBlbmdpbmUuIEV2ZXJ5IGR5bmFtaWMgbm9kZSBpcyBjaGVja2VkIGFnYWluc3QgZXZlcnlcbiAqIFx0b3RoZXIgbm9kZSBmb3IgY29sbGlzaW9uIGFyZWEuIElmIGNvbGxpc2lvbiBhcmVhIGlzIG5vbi16ZXJvIChtZWFuaW5nIHRoZSBjdXJyZW50IG5vZGUgc3dlZXBzIGludG8gYW5vdGhlciksXG4gKiBcdGl0IGlzIGFkZGVkIHRvIGEgbGlzdCBvZiBoaXRzLlxuICogXG4gKiBcdElOSVRJQUxJWkFUSU9OOlxuICogXHRcdC0gUGh5c2ljcyBjb25zdGFudHMgYXJlIHJlc2V0XG4gKiBcdFx0LSBTd2VwdCBzaGFwZXMgYXJlIHJlY2FsY3VsYXRlZC4gSWYgYSBub2RlIGlzbid0IG1vdmluZywgaXQgaXMgc2tpcHBlZC5cbiAqIFxuICogXHRDT0xMSVNJT04gREVURUNUSU9OOlxuICogXHRcdC0gRm9yIGEgbm9kZSwgY29sbGlzaW9uIGFyZWEgd2lsbCBiZSBjYWxjdWxhdGVkIHVzaW5nIHRoZSBzd2VwdCBBQUJCIG9mIHRoZSBub2RlIGFnYWluc3QgZXZlcnkgb3RoZXIgQUFCQiBpbiBhIHN0YXRpYyBzdGF0ZVxuICogXHRcdC0gVGhlc2UgY29sbGlzaW9ucyB3aWxsIGJlIHNvcnRlZCBieSBhcmVhIGluIGRlc2NlbmRpbmcgb3JkZXJcbiAqIFx0XG4gKiBcdENPTExJU0lPTiBSRVNPTFVUSU9OOlxuICogXHRcdC0gRm9yIGVhY2ggaGl0LCB0aW1lIG9mIGNvbGxpc2lvbiBpcyBjYWxjdWxhdGVkIHVzaW5nIGEgc3dlcHQgbGluZSB0aHJvdWdoIHRoZSBBQUJCIG9mIHRoZSBzdGF0aWMgbm9kZSBleHBhbmRlZFxuICogXHRcdFx0d2l0aCBtaW5rb3dza2kgc3VtcyAoZGlzY3JldGVseSwgYnV0IHRoZSBjb25jZXB0IGlzIHRoZXJlKVxuICogXHRcdC0gVGhlIGNvbGxpc2lvbiBpcyByZXNvbHZlZCBiYXNlZCBvbiB0aGUgbmVhciB0aW1lIG9mIHRoZSBjb2xsaXNpb24gKGZyb20gbWV0aG9kIG9mIHNlcGFyYXRlZCBheGVzKVxuICogXHRcdFx0LSBYIGlzIHJlc29sdmVkIGJ5IG5lYXIgeCwgWSBieSBuZWFyIHkuXG4gKiBcdFx0XHQtIFRoZXJlIGlzIHNvbWUgZnVkZ2luZyB0byBhbGxvdyBmb3Igc2xpZGluZyBhbG9uZyB3YWxscyBvZiBzZXBhcmF0ZSBjb2xsaWRlcnMuIFNvcnRpbmcgYnkgYXJlYSBhbHNvIGhlbHBzIHdpdGggdGhpcy5cbiAqIFx0XHRcdC0gQ29ybmVyIHRvIGNvcm5lciBjb2xsaXNpb25zIGFyZSByZXNvbHZlIHRvIGZhdm9yIHgtbW92ZW1lbnQuIFRoaXMgaXMgaW4gY29uc2lkZXJhdGlvbiBvZiBwbGF0Zm9ybWVycywgdG8gZ2l2ZVxuICogXHRcdFx0XHR0aGUgcGxheWVyIHNvbWUgaGVscCB3aXRoIGp1bXBzXG4gKiBcbiAqIFx0UHJvczpcbiAqIFx0XHQtIEV2ZXJ5dGhpbmcgaGFwcGVucyB3aXRoIGEgY29uc2lzdGVudCB0aW1lLiBUaGVyZSBpcyBhIGRpc3RpbmN0IGJlZm9yZSBhbmQgYWZ0ZXIgZm9yIGVhY2ggcmVzb2x1dGlvbi5cbiAqIFx0XHQtIE5vIGJhY2stdHJhY2tpbmcgbmVlZHMgdG8gYmUgZG9uZS4gT25jZSB3ZSByZXNvbHZlIGEgbm9kZSwgaXQgaXMgZGVmaW5pdGl2ZWx5IHJlc29sdmVkLlxuICogXHRcbiAqIFx0Q29uczpcbiAqIFx0XHQtIE5vZGVzIHRoYXQgYXJlIHByb2Nlc3NlZCBlYXJseSBoYXZlIG1vdmVtZW50IHByaW9yaXR5IG92ZXIgb3RoZXIgbm9kZXMuIFRoaXMgY2FuIGxlYWQgdG8gc29tZSB1bmRlc2lyYWJsZSBpbnRlcmFjdGlvbnMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2ljUGh5c2ljc01hbmFnZXIgZXh0ZW5kcyBQaHlzaWNzTWFuYWdlciB7XG5cblx0LyoqIFRoZSBhcnJheSBvZiBzdGF0aWMgbm9kZXMgKi9cblx0cHJvdGVjdGVkIHN0YXRpY05vZGVzOiBBcnJheTxQaHlzaWNhbD47XG5cblx0LyoqIFRoZSBhcnJheSBvZiBkeW5hbWljIG5vZGVzICovXG5cdHByb3RlY3RlZCBkeW5hbWljTm9kZXM6IEFycmF5PFBoeXNpY2FsPjtcblxuXHQvKiogVGhlIGFycmF5IG9mIHRpbGVtYXBzICovXG5cdHByb3RlY3RlZCB0aWxlbWFwczogQXJyYXk8VGlsZW1hcD47XG5cblx0LyoqIEFuIGFycmF5IG9mIHRoZSBjb2xsaXNpb24gbWFza3MgZm9yIGVhY2ggZ3JvdXAgKi9cblx0cHJvdGVjdGVkIGNvbGxpc2lvbk1hc2tzOiBBcnJheTxudW1iZXI+O1xuXG5cdGNvbnN0cnVjdG9yKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pe1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5zdGF0aWNOb2RlcyA9IG5ldyBBcnJheSgpO1xuXHRcdHRoaXMuZHluYW1pY05vZGVzID0gbmV3IEFycmF5KCk7XG5cdFx0dGhpcy50aWxlbWFwcyA9IG5ldyBBcnJheSgpO1xuXHRcdHRoaXMuY29sbGlzaW9uTWFza3MgPSBuZXcgQXJyYXkoMzIpO1xuXG5cdFx0Ly8gUGFyc2Ugb3B0aW9uc1xuXHRcdHRoaXMucGFyc2VPcHRpb25zKG9wdGlvbnMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhcnNlcyB0aGUgb3B0aW9ucyBmb3IgY29uc3RydWN0aW5nIHRoZSBwaHlzaWNzIG1hbmFnZXJcblx0ICogQHBhcmFtIG9wdGlvbnMgQSByZWNvcmQgb2Ygb3B0aW9uc1xuXHQgKi9cblx0cHJvdGVjdGVkIHBhcnNlT3B0aW9ucyhvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0aWYob3B0aW9ucy5ncm91cE5hbWVzICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5jb2xsaXNpb25zICE9PSB1bmRlZmluZWQpe1xuXHRcdFx0Zm9yKGxldCBpID0gMDsgaSA8IG9wdGlvbnMuZ3JvdXBOYW1lcy5sZW5ndGg7IGkrKyl7XG5cdFx0XHRcdGxldCBncm91cCA9IG9wdGlvbnMuZ3JvdXBOYW1lc1tpXTtcblxuXHRcdFx0XHQvLyBSZWdpc3RlciB0aGUgZ3JvdXAgbmFtZSBhbmQgbnVtYmVyXG5cdFx0XHRcdHRoaXMuZ3JvdXBOYW1lc1tpXSA9IGdyb3VwO1xuXG5cdFx0XHRcdHRoaXMuZ3JvdXBNYXAuc2V0KGdyb3VwLCAxIDw8IGkpO1xuXG5cdFx0XHRcdGxldCBjb2xsaXNpb25NYXNrID0gMDtcblxuXHRcdFx0XHRmb3IobGV0IGogPSAwOyBqIDwgb3B0aW9ucy5jb2xsaXNpb25zW2ldLmxlbmd0aDsgaisrKXtcblx0XHRcdFx0XHRpZihvcHRpb25zLmNvbGxpc2lvbnNbaV1bal0pe1xuXHRcdFx0XHRcdFx0Y29sbGlzaW9uTWFzayB8PSAxIDw8IGo7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5jb2xsaXNpb25NYXNrc1tpXSA9IGNvbGxpc2lvbk1hc2s7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdHJlZ2lzdGVyT2JqZWN0KG5vZGU6IFBoeXNpY2FsKTogdm9pZCB7XG5cdFx0aWYobm9kZS5pc1N0YXRpYyl7XG5cdFx0XHQvLyBTdGF0aWMgYW5kIG5vdCBjb2xsaWRhYmxlXG5cdFx0XHR0aGlzLnN0YXRpY05vZGVzLnB1c2gobm9kZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIER5bmFtaWMgYW5kIG5vdCBjb2xsaWRhYmxlXG5cdFx0XHR0aGlzLmR5bmFtaWNOb2Rlcy5wdXNoKG5vZGUpO1xuXHRcdH1cblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHRkZXJlZ2lzdGVyT2JqZWN0KG5vZGU6IFBoeXNpY2FsKTogdm9pZCB7XG5cdFx0aWYobm9kZS5pc1N0YXRpYyl7XG5cdFx0XHQvLyBSZW1vdmUgdGhlIG5vZGUgZnJvbSB0aGUgc3RhdGljIGxpc3Rcblx0XHRcdGNvbnN0IGluZGV4ID0gdGhpcy5zdGF0aWNOb2Rlcy5pbmRleE9mKG5vZGUpO1xuXHRcdFx0dGhpcy5zdGF0aWNOb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBSZW1vdmUgdGhlIG5vZGUgZnJvbSB0aGUgZHluYW1pYyBsaXN0XG5cdFx0XHRjb25zdCBpbmRleCA9IHRoaXMuZHluYW1pY05vZGVzLmluZGV4T2Yobm9kZSk7XG5cdFx0XHR0aGlzLmR5bmFtaWNOb2Rlcy5zcGxpY2UoaW5kZXgsIDEpO1xuXHRcdH1cblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHRyZWdpc3RlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQge1xuXHRcdHRoaXMudGlsZW1hcHMucHVzaCh0aWxlbWFwKTtcblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHRkZXJlZ2lzdGVyVGlsZW1hcCh0aWxlbWFwOiBUaWxlbWFwKTogdm9pZCB7XG5cdFx0Y29uc3QgaW5kZXggPSB0aGlzLnRpbGVtYXBzLmluZGV4T2YodGlsZW1hcCk7XG5cdFx0dGhpcy50aWxlbWFwcy5zcGxpY2UoaW5kZXgsIDEpO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdGZvcihsZXQgbm9kZSBvZiB0aGlzLmR5bmFtaWNOb2Rlcyl7XG5cdFx0XHQvKi0tLS0tLS0tLS0gSU5JVElBTElaQVRJT04gUEhBU0UgLS0tLS0tLS0tLSovXG5cdFx0XHQvLyBDbGVhciBmcmFtZSBkZXBlbmRlbnQgYm9vbGVhbiB2YWx1ZXMgZm9yIGVhY2ggbm9kZVxuXHRcdFx0bm9kZS5vbkdyb3VuZCA9IGZhbHNlO1xuXHRcdFx0bm9kZS5vbkNlaWxpbmcgPSBmYWxzZTtcblx0XHRcdG5vZGUub25XYWxsID0gZmFsc2U7XG5cdFx0XHRub2RlLmNvbGxpZGVkV2l0aFRpbGVtYXAgPSBmYWxzZTtcblx0XHRcdG5vZGUuaXNDb2xsaWRpbmcgPSBmYWxzZTtcblxuXHRcdFx0Ly8gSWYgdGhpcyBub2RlIGlzIG5vdCBhY3RpdmUsIGRvbid0IHByb2Nlc3MgaXRcblx0XHRcdGlmKCFub2RlLmFjdGl2ZSl7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBVcGRhdGUgdGhlIHN3ZXB0IHNoYXBlcyBvZiBlYWNoIG5vZGVcblx0XHRcdGlmKG5vZGUubW92aW5nKXtcblx0XHRcdFx0Ly8gSWYgbW92aW5nLCByZWZsZWN0IHRoYXQgaW4gdGhlIHN3ZXB0IHNoYXBlXG5cdFx0XHRcdG5vZGUuc3dlcHRSZWN0LnN3ZWVwKG5vZGUuX3ZlbG9jaXR5LCBub2RlLmNvbGxpc2lvblNoYXBlLmNlbnRlciwgbm9kZS5jb2xsaXNpb25TaGFwZS5oYWxmU2l6ZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBJZiBvdXIgbm9kZSBpc24ndCBtb3ZpbmcsIGRvbid0IGJvdGhlciB0byBjaGVjayBpdCAob3RoZXIgbm9kZXMgd2lsbCBkZXRlY3QgaWYgdGhleSBydW4gaW50byBpdClcblx0XHRcdFx0bm9kZS5fdmVsb2NpdHkuemVybygpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0LyotLS0tLS0tLS0tIERFVEVDVElPTiBQSEFTRSAtLS0tLS0tLS0tKi9cblx0XHRcdC8vIEdhdGhlciBhIHNldCBvZiBvdmVybGFwc1xuXHRcdFx0bGV0IG92ZXJsYXBzID0gbmV3IEFycmF5PEFyZWFDb2xsaXNpb24+KCk7XG5cblx0XHRcdGxldCBncm91cEluZGV4ID0gbm9kZS5ncm91cCA9PT0gLTEgPyAtMSA6IE1hdGgubG9nMihub2RlLmdyb3VwKTtcblxuXHRcdFx0Ly8gRmlyc3QsIGNoZWNrIHRoaXMgbm9kZSBhZ2FpbnN0IGV2ZXJ5IHN0YXRpYyBub2RlIChvcmRlciBkb2Vzbid0IGFjdHVhbGx5IG1hdHRlciBoZXJlLCBzaW5jZSB3ZSBzb3J0IGFueXdheXMpXG5cdFx0XHRmb3IobGV0IG90aGVyIG9mIHRoaXMuc3RhdGljTm9kZXMpe1xuXHRcdFx0XHQvLyBJZ25vcmUgaW5hY3RpdmUgbm9kZXNcblx0XHRcdFx0aWYoIW90aGVyLmFjdGl2ZSkgY29udGludWU7XG5cblx0XHRcdFx0bGV0IGNvbGxpZGVyID0gb3RoZXIuY29sbGlzaW9uU2hhcGUuZ2V0Qm91bmRpbmdSZWN0KCk7XG5cdFx0XHRcdGxldCBhcmVhID0gbm9kZS5zd2VwdFJlY3Qub3ZlcmxhcEFyZWEoY29sbGlkZXIpO1xuXHRcdFx0XHRpZihhcmVhID4gMCl7XG5cdFx0XHRcdFx0Ly8gV2UgaGFkIGEgY29sbGlzaW9uXG5cdFx0XHRcdFx0b3ZlcmxhcHMucHVzaChuZXcgQXJlYUNvbGxpc2lvbihhcmVhLCBjb2xsaWRlciwgb3RoZXIsIFwiR2FtZU5vZGVcIiwgbnVsbCkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRoZW4sIGNoZWNrIGl0IGFnYWluc3QgZXZlcnkgZHluYW1pYyBub2RlXG5cdFx0XHRmb3IobGV0IG90aGVyIG9mIHRoaXMuZHluYW1pY05vZGVzKXtcblx0XHRcdFx0Ly8gSWdub3JlIG91cnNlbHZlc1xuXHRcdFx0XHRpZihub2RlID09PSBvdGhlcikgY29udGludWU7XG5cblx0XHRcdFx0Ly8gSWdub3JlIGluYWN0aXZlIG5vZGVzXG5cdFx0XHRcdGlmKCFvdGhlci5hY3RpdmUpIGNvbnRpbnVlO1xuXG5cdFx0XHRcdGxldCBjb2xsaWRlciA9IG90aGVyLmNvbGxpc2lvblNoYXBlLmdldEJvdW5kaW5nUmVjdCgpO1xuXHRcdFx0XHRsZXQgYXJlYSA9IG5vZGUuc3dlcHRSZWN0Lm92ZXJsYXBBcmVhKGNvbGxpZGVyKTtcblx0XHRcdFx0aWYoYXJlYSA+IDApe1xuXHRcdFx0XHRcdC8vIFdlIGhhZCBhIGNvbGxpc2lvblxuXHRcdFx0XHRcdG92ZXJsYXBzLnB1c2gobmV3IEFyZWFDb2xsaXNpb24oYXJlYSwgY29sbGlkZXIsIG90aGVyLCBcIkdhbWVOb2RlXCIsIG51bGwpKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBMYXN0bHksIGdhdGhlciBhIHNldCBvZiBBQUJCcyBmcm9tIHRoZSB0aWxlbWFwLlxuXHRcdFx0Ly8gVGhpcyBzdGVwIGludm9sdmVzIHRoZSBtb3N0IGV4dHJhIHdvcmssIHNvIGl0IGlzIGFic3RyYWN0ZWQgaW50byBhIG1ldGhvZFxuXHRcdFx0Zm9yKGxldCB0aWxlbWFwIG9mIHRoaXMudGlsZW1hcHMpe1xuXHRcdFx0XHQvLyBJZ25vcmUgaW5hY3RpdmUgdGlsZW1hcHNcblx0XHRcdFx0aWYoIXRpbGVtYXAuYWN0aXZlKSBjb250aW51ZTtcblxuXHRcdFx0XHRpZih0aWxlbWFwIGluc3RhbmNlb2YgT3J0aG9nb25hbFRpbGVtYXApe1xuXHRcdFx0XHRcdHRoaXMuY29sbGlkZVdpdGhPcnRob2dvbmFsVGlsZW1hcChub2RlLCB0aWxlbWFwLCBvdmVybGFwcyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU29ydCB0aGUgb3ZlcmxhcHMgYnkgYXJlYVxuXHRcdFx0b3ZlcmxhcHMgPSBvdmVybGFwcy5zb3J0KChhLCBiKSA9PiBiLmFyZWEgLSBhLmFyZWEpO1xuXG5cdFx0XHQvLyBLZWVwIHRyYWNrIG9mIGhpdHMgdG8gdXNlIGxhdGVyXG5cdFx0XHRsZXQgaGl0cyA9IFtdO1xuXG5cdFx0XHQvKi0tLS0tLS0tLS0gUkVTT0xVVElPTiBQSEFTRSAtLS0tLS0tLS0tKi9cblx0XHRcdC8vIEZvciBldmVyeSBvdmVybGFwLCBkZXRlcm1pbmUgaWYgd2UgbmVlZCB0byBjb2xsaWRlIHdpdGggaXQgYW5kIHdoZW5cblx0XHRcdGZvcihsZXQgb3ZlcmxhcCBvZiBvdmVybGFwcyl7XG5cdFx0XHRcdC8vIElnbm9yZSBub2RlcyB3ZSBkb24ndCBpbnRlcmFjdCB3aXRoXG5cdFx0XHRcdGlmKCBncm91cEluZGV4ICE9PSAtMSAmJiBvdmVybGFwLm90aGVyLmdyb3VwICE9PSAtMSAmJiAoKHRoaXMuY29sbGlzaW9uTWFza3NbZ3JvdXBJbmRleF0gJiBvdmVybGFwLm90aGVyLmdyb3VwKSA9PT0gMCkgKSBjb250aW51ZTtcblxuXHRcdFx0XHQvLyBEbyBhIHN3ZXB0IGxpbmUgdGVzdCBvbiB0aGUgc3RhdGljIEFBQkIgd2l0aCB0aGlzIEFBQkIgc2l6ZSBhcyBwYWRkaW5nICh0aGlzIGlzIGJhc2ljYWxseSB1c2luZyBhIG1pbmtvd3NraSBzdW0hKVxuXHRcdFx0XHQvLyBTdGFydCB0aGUgc3dlZXAgYXQgdGhlIHBvc2l0aW9uIG9mIHRoaXMgbm9kZSB3aXRoIGEgZGVsdGEgb2YgX3ZlbG9jaXR5XG5cdFx0XHRcdGNvbnN0IHBvaW50ID0gbm9kZS5jb2xsaXNpb25TaGFwZS5jZW50ZXI7XG5cdFx0XHRcdGNvbnN0IGRlbHRhID0gbm9kZS5fdmVsb2NpdHk7XG5cdFx0XHRcdGNvbnN0IHBhZGRpbmcgPSBub2RlLmNvbGxpc2lvblNoYXBlLmhhbGZTaXplO1xuXHRcdFx0XHRjb25zdCBvdGhlckFBQkIgPSBvdmVybGFwLmNvbGxpZGVyO1xuXG5cblx0XHRcdFx0Y29uc3QgaGl0ID0gb3RoZXJBQUJCLmludGVyc2VjdFNlZ21lbnQobm9kZS5jb2xsaXNpb25TaGFwZS5jZW50ZXIsIG5vZGUuX3ZlbG9jaXR5LCBub2RlLmNvbGxpc2lvblNoYXBlLmhhbGZTaXplKTtcblxuXHRcdFx0XHRvdmVybGFwLmhpdCA9IGhpdDtcblxuXHRcdFx0XHRpZihoaXQgIT09IG51bGwpe1xuXHRcdFx0XHRcdGhpdHMucHVzaChoaXQpO1xuXG5cdFx0XHRcdFx0Ly8gV2UgZ290IGEgaGl0LCByZXNvbHZlIHdpdGggdGhlIHRpbWUgaW5zaWRlIG9mIHRoZSBoaXRcblx0XHRcdFx0XHRsZXQgdG5lYXJ4ID0gaGl0Lm5lYXJUaW1lcy54O1xuXHRcdFx0XHRcdGxldCB0bmVhcnkgPSBoaXQubmVhclRpbWVzLnk7XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBlZGdlIGNsaXBwaW5nIChlZGdlIG92ZXJsYXBzIGRvbid0IGNvdW50LCBvbmx5IGFyZWEgb3ZlcmxhcHMpXG5cdFx0XHRcdFx0Ly8gSW1wb3J0YW50bHkgZG9uJ3QgYWxsb3cgYm90aCBjYXNlcyB0byBiZSB0cnVlLiBUaGVuIHdlIGNsaXAgdGhyb3VnaCBjb3JuZXJzLiBGYXZvciB4IHRvIGhlbHAgcGxheWVycyBsYW5kIGp1bXBzXG5cdFx0XHRcdFx0aWYodG5lYXJ4IDwgMS4wICYmIChwb2ludC55ID09PSBvdGhlckFBQkIudG9wIC0gcGFkZGluZy55IHx8IHBvaW50LnkgPT09IG90aGVyQUFCQi5ib3R0b20gKyBwYWRkaW5nLnkpICYmIGRlbHRhLnggIT09IDApIHtcblx0XHRcdFx0XHRcdHRuZWFyeCA9IDEuMDtcblx0XHRcdFx0XHR9IGVsc2UgaWYodG5lYXJ5IDwgMS4wICYmIChwb2ludC54ID09PSBvdGhlckFBQkIubGVmdCAtIHBhZGRpbmcueCB8fCBwb2ludC54ID09PSBvdGhlckFBQkIucmlnaHQgKyBwYWRkaW5nLngpICYmIGRlbHRhLnkgIT09IDApIHtcblx0XHRcdFx0XHRcdHRuZWFyeSA9IDEuMDtcblx0XHRcdFx0XHR9XG5cblxuXHRcdFx0XHRcdGlmKGhpdC5uZWFyVGltZXMueCA+PSAwICYmIGhpdC5uZWFyVGltZXMueCA8IDEpe1xuXHRcdFx0XHRcdFx0Ly8gQW55IHRpbGVtYXAgb2JqZWN0cyB0aGF0IG1hZGUgaXQgaGVyZSBhcmUgY29sbGlkYWJsZVxuXHRcdFx0XHRcdFx0aWYob3ZlcmxhcC50eXBlID09PSBcIlRpbGVtYXBcIiB8fCBvdmVybGFwLm90aGVyLmlzQ29sbGlkYWJsZSl7XG5cdFx0XHRcdFx0XHRcdG5vZGUuX3ZlbG9jaXR5LnggPSBub2RlLl92ZWxvY2l0eS54ICogdG5lYXJ4O1xuXHRcdFx0XHRcdFx0XHRub2RlLmlzQ29sbGlkaW5nID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZihoaXQubmVhclRpbWVzLnkgPj0gMCAmJiBoaXQubmVhclRpbWVzLnkgPCAxKXtcblx0XHRcdFx0XHRcdC8vIEFueSB0aWxlbWFwIG9iamVjdHMgdGhhdCBtYWRlIGl0IGhlcmUgYXJlIGNvbGxpZGFibGVcblx0XHRcdFx0XHRcdGlmKG92ZXJsYXAudHlwZSA9PT0gXCJUaWxlbWFwXCIgfHwgb3ZlcmxhcC5vdGhlci5pc0NvbGxpZGFibGUpe1xuXHRcdFx0XHRcdFx0XHRub2RlLl92ZWxvY2l0eS55ID0gbm9kZS5fdmVsb2NpdHkueSAqIHRuZWFyeTtcblx0XHRcdFx0XHRcdFx0bm9kZS5pc0NvbGxpZGluZyA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdC8qLS0tLS0tLS0tLSBJTkZPUk1BVElPTi9UUklHR0VSIFBIQVNFIC0tLS0tLS0tLS0qL1xuXHRcdFx0Ly8gQ2hlY2sgaWYgd2UgZW5kZWQgdXAgb24gdGhlIGdyb3VuZCwgY2VpbGluZyBvciB3YWxsXG5cdFx0XHQvLyBBbHNvIGNoZWNrIGZvciB0cmlnZ2Vyc1xuXHRcdFx0Zm9yKGxldCBvdmVybGFwIG9mIG92ZXJsYXBzKXtcblx0XHRcdFx0Ly8gQ2hlY2sgZm9yIGEgdHJpZ2dlci4gSWYgd2UgY2FyZSBhYm91dCB0aGUgdHJpZ2dlciwgcmVhY3Rcblx0XHRcdFx0aWYob3ZlcmxhcC5vdGhlci5pc1RyaWdnZXIgJiYgKG92ZXJsYXAub3RoZXIudHJpZ2dlck1hc2sgJiBub2RlLmdyb3VwKSAmJiBub2RlLmdyb3VwICE9IC0xKXtcblx0XHRcdFx0XHQvLyBHZXQgdGhlIGJpdCB0aGF0IHRoaXMgZ3JvdXAgaXMgcmVwcmVzZW50ZWQgYnlcblx0XHRcdFx0XHRsZXQgaW5kZXggPSBNYXRoLmZsb29yKE1hdGgubG9nMihub2RlLmdyb3VwKSk7XG5cblx0XHRcdFx0XHQvLyBFeHRyYWN0IHRoZSB0cmlnZ2VyRW50ZXIgZXZlbnQgbmFtZVxuXHRcdFx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQob3ZlcmxhcC5vdGhlci50cmlnZ2VyRW50ZXJzW2luZGV4XSwge1xuXHRcdFx0XHRcdFx0bm9kZTogKDxHYW1lTm9kZT5ub2RlKS5pZCxcblx0XHRcdFx0XHRcdG90aGVyOiAoPEdhbWVOb2RlPm92ZXJsYXAub3RoZXIpLmlkXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBJZ25vcmUgY29sbGlzaW9uIHNpZGVzIGZvciBub2RlcyB3ZSBkb24ndCBpbnRlcmFjdCB3aXRoXG5cdFx0XHRcdGlmKCBncm91cEluZGV4ICE9PSAtMSAmJiBvdmVybGFwLm90aGVyLmdyb3VwICE9PSAtMSAmJiAoKHRoaXMuY29sbGlzaW9uTWFza3NbZ3JvdXBJbmRleF0gJiBvdmVybGFwLm90aGVyLmdyb3VwKSA9PT0gMCkpIGNvbnRpbnVlO1xuXG5cdFx0XHRcdC8vIE9ubHkgY2hlY2sgZm9yIGRpcmVjdGlvbiBpZiB0aGUgb3ZlcmxhcCB3YXMgY29sbGlkYWJsZVxuXHRcdFx0XHRpZihvdmVybGFwLnR5cGUgPT09IFwiVGlsZW1hcFwiIHx8IG92ZXJsYXAub3RoZXIuaXNDb2xsaWRhYmxlKXtcblx0XHRcdFx0XHRsZXQgY29sbGlzaW9uU2lkZSA9IG92ZXJsYXAuY29sbGlkZXIudG91Y2hlc0FBQkJXaXRob3V0Q29ybmVycyhub2RlLmNvbGxpc2lvblNoYXBlLmdldEJvdW5kaW5nUmVjdCgpKTtcblx0XHRcdFx0XHRpZihjb2xsaXNpb25TaWRlICE9PSBudWxsKXtcblx0XHRcdFx0XHRcdC8vIElmIHdlIHRvdWNoLCBub3QgaW5jbHVkaW5nIGNvcm5lciBjYXNlcywgY2hlY2sgdGhlIGNvbGxpc2lvbiBub3JtYWxcblx0XHRcdFx0XHRcdGlmKG92ZXJsYXAuaGl0ICE9PSBudWxsKXtcblx0XHRcdFx0XHRcdFx0Ly8gSWYgd2UgaGl0IGEgdGlsZW1hcCwga2VlcCB0cmFjayBvZiBpdFxuXHRcdFx0XHRcdFx0XHRpZihvdmVybGFwLnR5cGUgPT0gXCJUaWxlbWFwXCIpe1xuXHRcdFx0XHRcdFx0XHRcdG5vZGUuY29sbGlkZWRXaXRoVGlsZW1hcCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRpZihjb2xsaXNpb25TaWRlLnkgPT09IC0xKXtcblx0XHRcdFx0XHRcdFx0XHQvLyBOb2RlIGlzIG9uIHRvcCBvZiBvdmVybGFwLCBzbyBvbkdyb3VuZFxuXHRcdFx0XHRcdFx0XHRcdG5vZGUub25Hcm91bmQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYoY29sbGlzaW9uU2lkZS55ID09PSAxKXtcblx0XHRcdFx0XHRcdFx0XHQvLyBOb2RlIGlzIG9uIGJvdHRvbSBvZiBvdmVybGFwLCBzbyBvbkNlaWxpbmdcblx0XHRcdFx0XHRcdFx0XHRub2RlLm9uQ2VpbGluZyA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gTm9kZSB3YXNuJ3QgdG91Y2hpbmcgb24geSwgc28gaXQgaXMgdG91Y2hpbmcgb24geFxuXHRcdFx0XHRcdFx0XHRcdG5vZGUub25XYWxsID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXNvbHZlIHRoZSBjb2xsaXNpb24gd2l0aCB0aGUgbm9kZSwgYW5kIG1vdmUgaXRcblx0XHRcdG5vZGUuZmluaXNoTW92ZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGVzIGEgY29sbGlzaW9uIGJldHdlZW4gdGhpcyBub2RlIGFuZCBhbiBvcnRob2dvbmFsIHRpbGVtYXBcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGVcblx0ICogQHBhcmFtIHRpbGVtYXAgVGhlIHRpbGVtYXAgdGhlIG5vZGUgbWF5IGJlIGNvbGxpZGluZyB3aXRoXG5cdCAqIEBwYXJhbSBvdmVybGFwcyBUaGUgbGlzdCBvZiBvdmVybGFwc1xuXHQgKi9cblx0cHJvdGVjdGVkIGNvbGxpZGVXaXRoT3J0aG9nb25hbFRpbGVtYXAobm9kZTogUGh5c2ljYWwsIHRpbGVtYXA6IE9ydGhvZ29uYWxUaWxlbWFwLCBvdmVybGFwczogQXJyYXk8QXJlYUNvbGxpc2lvbj4pOiB2b2lkIHtcblx0XHQvLyBHZXQgdGhlIG1pbiBhbmQgbWF4IHggYW5kIHkgY29vcmRpbmF0ZXMgb2YgdGhlIG1vdmluZyBub2RlXG5cdFx0bGV0IG1pbiA9IG5ldyBWZWMyKG5vZGUuc3dlcHRSZWN0LmxlZnQsIG5vZGUuc3dlcHRSZWN0LnRvcCk7XG5cdFx0bGV0IG1heCA9IG5ldyBWZWMyKG5vZGUuc3dlcHRSZWN0LnJpZ2h0LCBub2RlLnN3ZXB0UmVjdC5ib3R0b20pO1xuXG5cdFx0Ly8gQ29udmVydCB0aGUgbWluL21heCB4L3kgdG8gdGhlIG1pbiBhbmQgbWF4IHJvdy9jb2wgaW4gdGhlIHRpbGVtYXAgYXJyYXlcblx0XHRsZXQgbWluSW5kZXggPSB0aWxlbWFwLmdldENvbFJvd0F0KG1pbik7XG5cdFx0bGV0IG1heEluZGV4ID0gdGlsZW1hcC5nZXRDb2xSb3dBdChtYXgpO1xuXG5cdFx0bGV0IHRpbGVTaXplID0gdGlsZW1hcC5nZXRUaWxlU2l6ZSgpO1xuXG5cdFx0Ly8gTG9vcCBvdmVyIGFsbCBwb3NzaWJsZSB0aWxlcyAod2hpY2ggaXNuJ3QgbWFueSBpbiB0aGUgc2NvcGUgb2YgdGhlIHZlbG9jaXR5IHBlciBmcmFtZSlcblx0XHRmb3IobGV0IGNvbCA9IG1pbkluZGV4Lng7IGNvbCA8PSBtYXhJbmRleC54OyBjb2wrKyl7XG5cdFx0XHRmb3IobGV0IHJvdyA9IG1pbkluZGV4Lnk7IHJvdyA8PSBtYXhJbmRleC55OyByb3crKyl7XG5cdFx0XHRcdGlmKHRpbGVtYXAuaXNUaWxlQ29sbGlkYWJsZShjb2wsIHJvdykpe1xuXHRcdFx0XHRcdC8vIEdldCB0aGUgcG9zaXRpb24gb2YgdGhpcyB0aWxlXG5cdFx0XHRcdFx0bGV0IHRpbGVQb3MgPSBuZXcgVmVjMihjb2wgKiB0aWxlU2l6ZS54ICsgdGlsZVNpemUueC8yLCByb3cgKiB0aWxlU2l6ZS55ICsgdGlsZVNpemUueS8yKTtcblxuXHRcdFx0XHRcdC8vIENyZWF0ZSBhIG5ldyBjb2xsaWRlciBmb3IgdGhpcyB0aWxlXG5cdFx0XHRcdFx0bGV0IGNvbGxpZGVyID0gbmV3IEFBQkIodGlsZVBvcywgdGlsZVNpemUuc2NhbGVkKDEvMikpO1xuXG5cdFx0XHRcdFx0Ly8gQ2FsY3VsYXRlIGNvbGxpc2lvbiBhcmVhIGJldHdlZW4gdGhlIG5vZGUgYW5kIHRoZSB0aWxlXG5cdFx0XHRcdFx0bGV0IGFyZWEgPSBub2RlLnN3ZXB0UmVjdC5vdmVybGFwQXJlYShjb2xsaWRlcik7XG5cdFx0XHRcdFx0aWYoYXJlYSA+IDApe1xuXHRcdFx0XHRcdFx0Ly8gV2UgaGFkIGEgY29sbGlzaW9uXG5cdFx0XHRcdFx0XHRvdmVybGFwcy5wdXNoKG5ldyBBcmVhQ29sbGlzaW9uKGFyZWEsIGNvbGxpZGVyLCB0aWxlbWFwLCBcIlRpbGVtYXBcIiwgbmV3IFZlYzIoY29sLCByb3cpKSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IFVwZGF0ZWFibGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1VwZGF0ZWFibGVcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uL0V2ZW50cy9SZWNlaXZlclwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgUGh5c2ljYWwgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1BoeXNpY2FsXCI7XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgcGh5c2ljcyBtYW5hZ2VyLlxuICogVGhpcyBjbGFzcyBleHBvc2VzIGZ1bmN0aW9ucyBmb3Igc3ViY2xhc3NlcyB0byBpbXBsZW1lbnQgdGhhdCBzaG91bGQgYWxsb3cgZm9yIGEgd29ya2luZyBwaHlzaWNzIHN5c3RlbSB0byBiZSBjcmVhdGVkLlxuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBQaHlzaWNzTWFuYWdlciBpbXBsZW1lbnRzIFVwZGF0ZWFibGUge1xuXHQvKiogVGhlIGV2ZW50IHJlY2VpdmVyIGZvciB0aGUgcGh5c2ljcyBzeXN0ZW0gKi9cblx0cHJvdGVjdGVkIHJlY2VpdmVyOiBSZWNlaXZlcjtcblx0LyoqIFRoZSBldmVudCBlbWl0dGVyIGZvciB0aGUgcGh5c2ljcyBzeXN0ZW0gKi9cblx0cHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cblx0LyoqIE1hcHMgbGF5ZXIgbmFtZXMgdG8gbnVtYmVycyAqL1xuXHRwcm90ZWN0ZWQgZ3JvdXBNYXA6IE1hcDxudW1iZXI+O1xuXG5cdC8qKiBNYXBzIGxheWVyIG51bWJlcnMgdG8gbmFtZXMgKi9cblx0cHJvdGVjdGVkIGdyb3VwTmFtZXM6IEFycmF5PHN0cmluZz47XG5cblx0LyoqIFRoZSBkZWZhdWx0IGdyb3VwIG5hbWUgKi9cblx0cHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0dST1VQOiBzdHJpbmcgPSBcIkRlZmF1bHRcIjtcblxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMucmVjZWl2ZXIgPSBuZXcgUmVjZWl2ZXIoKTtcblx0XHR0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuXG5cdFx0Ly8gVGhlIGNyZWF0aW9uIGFuZCBpbXBsZW1lbnRhdGlvbiBvZiBsYXllcnMgaXMgZGVmZXJyZWQgdG8gdGhlIHN1YmNsYXNzXG5cdFx0dGhpcy5ncm91cE1hcCA9IG5ldyBNYXAoKTtcblx0XHR0aGlzLmdyb3VwTmFtZXMgPSBuZXcgQXJyYXkoKTtcblx0fVxuXG5cdGRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy5yZWNlaXZlci5kZXN0cm95KCk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgZ2FtZW5vZGUgd2l0aCB0aGlzIHBoeXNpY3MgbWFuYWdlclxuXHQgKiBAcGFyYW0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcmVnaXN0ZXJcblx0ICovXG5cdGFic3RyYWN0IHJlZ2lzdGVyT2JqZWN0KG9iamVjdDogUGh5c2ljYWwpOiB2b2lkO1xuXG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgcmVmZXJlbmNlcyB0byB0aGlzIG9iamVjdCBmcm9tIHRoZSBwaHlzaWNzIG1hbmFnZXJyXG5cdCAqIEBwYXJhbSBvYmplY3QgVGhlIG9iamVjdCB0byBkZXJlZ2lzdGVyXG5cdCAqL1xuXHRhYnN0cmFjdCBkZXJlZ2lzdGVyT2JqZWN0KG9iamVjdDogUGh5c2ljYWwpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSB0aWxlbWFwIHdpdGggdGhpcyBwaHlzaWNzIG1hbmFnZXJcblx0ICogQHBhcmFtIHRpbGVtYXAgVGhlIHRpbGVtYXAgdG8gcmVnaXN0ZXJcblx0ICovXG5cdGFic3RyYWN0IHJlZ2lzdGVyVGlsZW1hcCh0aWxlbWFwOiBUaWxlbWFwKTogdm9pZDtcblxuXHQvKipcblx0ICogUmVtb3ZlcyByZWZlcmVuY2VzIHRvIHRoaXMgdGlsZW1hcCBmcm9tIHRoZSBwaHlzaWNzIG1hbmFnZXJyXG5cdCAqIEBwYXJhbSB0aWxlbWFwIFRoZSBvYmplY3QgdG8gZGVyZWdpc3RlclxuXHQgKi9cblx0YWJzdHJhY3QgZGVyZWdpc3RlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQ7XG5cblx0YWJzdHJhY3QgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZDtcblxuXHQvKipcblx0ICogU2V0cyB0aGUgcGh5c2ljcyBsYXllciBvZiB0aGUgR2FtZU5vZGVcblx0ICogQHBhcmFtIG5vZGUgVGhlIEdhbWVOb2RlXG5cdCAqIEBwYXJhbSBncm91cCBUaGUgZ3JvdXAgdGhhdCB0aGUgR2FtZU5vZGUgc2hvdWxkIGJlIG9uXG5cdCAqL1xuXHRzZXRHcm91cChub2RlOiBQaHlzaWNhbCwgZ3JvdXA6IHN0cmluZyk6IHZvaWQge1xuXHRcdG5vZGUuZ3JvdXAgPSB0aGlzLmdyb3VwTWFwLmdldChncm91cCk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0cmlldmVzIHRoZSBsYXllciBudW1iZXIgYXNzb2NpYXRlZCB3aXRoIHRoZSBwcm92aWRlZCBuYW1lXG5cdCAqIEBwYXJhbSBsYXllciBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcblx0ICogQHJldHVybnMgVGhlIGxheWVyIG51bWJlciwgb3IgMCBpZiB0aGVyZSBpcyBub3QgYSBsYXllciB3aXRoIHRoYXQgbmFtZSByZWdpc3RlcmVkXG5cdCAqL1xuXHRnZXRHcm91cE51bWJlcihncm91cDogc3RyaW5nKTogbnVtYmVyIHtcblx0XHRpZih0aGlzLmdyb3VwTWFwLmhhcyhncm91cCkpe1xuXHRcdFx0cmV0dXJuIHRoaXMuZ3JvdXBNYXAuZ2V0KGdyb3VwKTtcblx0XHR9IGVsc2V7XG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBhbGwgZ3JvdXAgbmFtZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBudW1iZXIgcHJvdmlkZWRcblx0ICogQHBhcmFtIGdyb3VwcyBBIG1hc2sgb2YgZ3JvdXBzXG5cdCAqIEByZXR1cm5zIEFsbCBncm91cHMgY29udGFpbmVkIGluIHRoZSBtYXNrXG5cdCAqL1xuXHRnZXRHcm91cE5hbWVzKGdyb3VwczogbnVtYmVyKTogQXJyYXk8c3RyaW5nPiB7XG5cdFx0aWYoZ3JvdXBzID09PSAtMSl7XG5cdFx0XHRyZXR1cm4gW1BoeXNpY3NNYW5hZ2VyLkRFRkFVTFRfR1JPVVBdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgZyA9IDE7XG5cdFx0XHRsZXQgbmFtZXMgPSBbXTtcblxuXHRcdFx0Zm9yKGxldCBpID0gMDsgaSA8IDMyOyBpKyspe1xuXHRcdFx0XHRpZihnICYgZ3JvdXBzKXtcblx0XHRcdFx0XHQvLyBUaGlzIGdyb3VwIGlzIGluIHRoZSBncm91cHMgbnVtYmVyXG5cdFx0XHRcdFx0bmFtZXMucHVzaCh0aGlzLmdyb3VwTmFtZXNbaV0pO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gU2hpZnQgdGhlIGJpdCBvdmVyXG5cdFx0XHRcdGcgPSBnIDw8IDE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IFF1ZXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvUXVldWVcIjtcbmltcG9ydCBSZWNlaXZlciBmcm9tIFwiLi4vRXZlbnRzL1JlY2VpdmVyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgRXZlbnRRdWV1ZSBmcm9tIFwiLi4vRXZlbnRzL0V2ZW50UXVldWVcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuLy8gQGlnbm9yZVBhZ2VcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVjb3JkZXIge1xuXHRwcml2YXRlIHJlY2VpdmVyOiBSZWNlaXZlcjtcblx0cHJpdmF0ZSBsb2c6IFF1ZXVlPExvZ0l0ZW0+O1xuXHRwcml2YXRlIHJlY29yZGluZzogYm9vbGVhbjtcblx0cHJpdmF0ZSBldmVudFF1ZXVlOiBFdmVudFF1ZXVlO1xuXHRwcml2YXRlIGZyYW1lOiBudW1iZXI7XG5cdHByaXZhdGUgcGxheWluZzogYm9vbGVhbjtcblxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMucmVjZWl2ZXIgPSBuZXcgUmVjZWl2ZXIoKTtcblx0XHR0aGlzLmxvZyA9IG5ldyBRdWV1ZSgxMDAwKTtcblx0XHR0aGlzLnJlY29yZGluZyA9IGZhbHNlO1xuXHRcdHRoaXMucGxheWluZyA9IGZhbHNlO1xuXHRcdHRoaXMuZnJhbWUgPSAwO1xuXG5cdFx0dGhpcy5ldmVudFF1ZXVlID0gRXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpO1xuXHRcdHRoaXMuZXZlbnRRdWV1ZS5zdWJzY3JpYmUodGhpcy5yZWNlaXZlciwgXCJhbGxcIik7XG5cdH1cblxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHRpZih0aGlzLnJlY29yZGluZyl7XG5cdFx0XHR0aGlzLmZyYW1lICs9IDE7XG5cdFx0fVxuXG5cdFx0aWYodGhpcy5wbGF5aW5nKXtcblx0XHRcdC8vIElmIHBsYXlpbmcsIGlnbm9yZSBldmVudHMsIGp1c3QgZmVlZCB0aGUgcmVjb3JkIHRvIHRoZSBldmVudCBxdWV1ZVxuXHRcdFx0dGhpcy5yZWNlaXZlci5pZ25vcmVFdmVudHMoKTtcblxuXHRcdFx0Lypcblx0XHRcdFx0V2hpbGUgdGhlcmUgaXMgYSBuZXh0IGl0ZW0sIGFuZCB3aGlsZSBpdCBzaG91bGQgb2NjdXIgaW4gdGhpcyBmcmFtZSxcblx0XHRcdFx0c2VuZCB0aGUgZXZlbnQuIGkuZS4sIHdoaWxlIGN1cnJlbnRfZnJhbWUgKiBjdXJyZW50X2RlbHRhX3QgaXMgZ3JlYXRlclxuXHRcdFx0XHR0aGFuIHJlY29yZGVkX2ZyYW1lICogcmVjb3JkZWRfZGVsdGFfdFxuXHRcdFx0Ki9cblx0XHRcdHdoaWxlKHRoaXMubG9nLmhhc0l0ZW1zKClcblx0XHRcdFx0XHQmJiB0aGlzLmxvZy5wZWVrTmV4dCgpLmZyYW1lICogdGhpcy5sb2cucGVla05leHQoKS5kZWx0YSA8IHRoaXMuZnJhbWUgKiBkZWx0YVQpe1xuXHRcdFx0XHRsZXQgZXZlbnQgPSB0aGlzLmxvZy5kZXF1ZXVlKCkuZXZlbnQ7XG5cdFx0XHRcdGNvbnNvbGUubG9nKGV2ZW50KTtcblx0XHRcdFx0dGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KGV2ZW50KTtcblx0XHRcdH1cblxuXHRcdFx0aWYoIXRoaXMubG9nLmhhc0l0ZW1zKCkpe1xuXHRcdFx0XHR0aGlzLnBsYXlpbmcgPSBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5mcmFtZSArPSAxO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBJZiBub3QgcGxheWluZywgaGFuZGxlIGV2ZW50c1xuXHRcdFx0d2hpbGUodGhpcy5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSl7XG5cdFx0XHRcdGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG5cblx0XHRcdFx0aWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5TVE9QX1JFQ09SRElORyl7XG5cdFx0XHRcdFx0dGhpcy5yZWNvcmRpbmcgPSBmYWxzZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmKHRoaXMucmVjb3JkaW5nKXtcblx0XHRcdFx0XHR0aGlzLmxvZy5lbnF1ZXVlKG5ldyBMb2dJdGVtKHRoaXMuZnJhbWUsIGRlbHRhVCwgZXZlbnQpKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuU1RBUlRfUkVDT1JESU5HKXtcblx0XHRcdFx0XHR0aGlzLmxvZy5jbGVhcigpO1xuXHRcdFx0XHRcdHRoaXMucmVjb3JkaW5nID0gdHJ1ZTtcblx0XHRcdFx0XHR0aGlzLmZyYW1lID0gMFxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5QTEFZX1JFQ09SRElORyl7XG5cdFx0XHRcdFx0dGhpcy5mcmFtZSA9IDA7XG5cdFx0XHRcdFx0dGhpcy5yZWNvcmRpbmcgPSBmYWxzZTtcblx0XHRcdFx0XHR0aGlzLnBsYXlpbmcgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmNsYXNzIExvZ0l0ZW0ge1xuXHRmcmFtZTogbnVtYmVyO1xuXHRkZWx0YTogbnVtYmVyO1xuXHRldmVudDogR2FtZUV2ZW50O1xuXG5cdGNvbnN0cnVjdG9yKGZyYW1lOiBudW1iZXIsIGRlbHRhVDogbnVtYmVyLCBldmVudDogR2FtZUV2ZW50KXtcblx0XHR0aGlzLmZyYW1lID0gZnJhbWU7XG5cdFx0dGhpcy5kZWx0YSA9IGRlbHRhVDtcblx0XHR0aGlzLmV2ZW50ID0gZXZlbnQ7XG5cdH1cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvTWFwXCI7XG5cbi8qKiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUmVnaXN0cnk8VD4gZXh0ZW5kcyBNYXA8VD57XG5cbiAgICAvKiogUHJlbG9hZHMgcmVnaXN0cnkgZGF0YSAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBwcmVsb2FkKCk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYW4gaXRlbSBhbmQgcHJlbG9hZHMgYW55IG5lY2Vzc2FyeSBmaWxlc1xuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byByZWdpc3RlciB0aGlzIGl0ZW0gd2l0aFxuICAgICAqIEBwYXJhbSBhcmdzIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBuZWVkZWQgZm9yIHJlZ2lzdHJhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCByZWdpc3RlckFuZFByZWxvYWRJdGVtKGtleTogc3RyaW5nLCAuLi5hcmdzOiBhbnkpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGFuIGl0ZW0gYW5kIHByZWxvYWRzIGFueSBuZWNlc3NhcnkgZmlsZXNcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gcmVnaXN0ZXIgdGhpcyBpdGVtIHdpdGhcbiAgICAgKiBAcGFyYW0gYXJncyBBbnkgYWRpdGlvbmFsIGFyZ3VtZW50cyBuZWVkZWQgZm9yIHJlZ2lzdHJhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCByZWdpc3Rlckl0ZW0oa2V5OiBzdHJpbmcsIC4uLmFyZ3M6IGFueSk6IHZvaWQ7XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFNoYWRlclR5cGUgZnJvbSBcIi4uLy4uL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlXCI7XG5pbXBvcnQgTGFiZWxTaGFkZXJUeXBlIGZyb20gXCIuLi8uLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvTGFiZWxTaGFkZXJUeXBlXCI7XG5pbXBvcnQgUG9pbnRTaGFkZXJUeXBlIGZyb20gXCIuLi8uLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvUG9pbnRTaGFkZXJUeXBlXCI7XG5pbXBvcnQgUmVjdFNoYWRlclR5cGUgZnJvbSBcIi4uLy4uL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9SZWN0U2hhZGVyVHlwZVwiO1xuaW1wb3J0IFNwcml0ZVNoYWRlclR5cGUgZnJvbSBcIi4uLy4uL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9TcHJpdGVTaGFkZXJUeXBlXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUmVnaXN0cnkgZnJvbSBcIi4vUmVnaXN0cnlcIjtcblxuLyoqXG4gKiBBIHJlZ2lzdHJ5IHRoYXQgaGFuZGxlcyBzaGFkZXJzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNoYWRlclJlZ2lzdHJ5IGV4dGVuZHMgUmVnaXN0cnk8U2hhZGVyVHlwZT4ge1xuXG5cdC8vIFNoYWRlciBuYW1lc1xuXHRwdWJsaWMgc3RhdGljIFBPSU5UX1NIQURFUiA9IFwicG9pbnRcIjtcblx0cHVibGljIHN0YXRpYyBSRUNUX1NIQURFUiA9IFwicmVjdFwiO1xuXHRwdWJsaWMgc3RhdGljIFNQUklURV9TSEFERVIgPSBcInNwcml0ZVwiO1xuXHRwdWJsaWMgc3RhdGljIExBQkVMX1NIQURFUiA9IFwibGFiZWxcIjtcblxuXHRwcml2YXRlIHJlZ2lzdHJ5SXRlbXM6IEFycmF5PFNoYWRlclJlZ2lzdHJ5SXRlbT4gPSBuZXcgQXJyYXkoKTtcblxuXHQvKipcblx0ICogUHJlbG9hZHMgYWxsIGJ1aWx0LWluIHNoYWRlcnNcblx0ICovXG5cdHB1YmxpYyBwcmVsb2FkKCl7XG5cdFx0Ly8gR2V0IHRoZSByZXNvdXJjZU1hbmFnZXIgYW5kIHF1ZXVlIGFsbCBidWlsdC1pbiBzaGFkZXJzIGZvciBwcmVsb2FkaW5nXG5cdFx0Y29uc3Qgcm0gPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcblxuXHRcdC8vIFF1ZXVlIGEgbG9hZCBmb3IgdGhlIHBvaW50IHNoYWRlclxuXHRcdHRoaXMucmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShTaGFkZXJSZWdpc3RyeS5QT0lOVF9TSEFERVIsIFBvaW50U2hhZGVyVHlwZSwgXCJidWlsdGluL3NoYWRlcnMvcG9pbnQudnNoYWRlclwiLCBcImJ1aWx0aW4vc2hhZGVycy9wb2ludC5mc2hhZGVyXCIpO1xuXG5cdFx0Ly8gUXVldWUgYSBsb2FkIGZvciB0aGUgcmVjdCBzaGFkZXJcblx0XHR0aGlzLnJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oU2hhZGVyUmVnaXN0cnkuUkVDVF9TSEFERVIsIFJlY3RTaGFkZXJUeXBlLCBcImJ1aWx0aW4vc2hhZGVycy9yZWN0LnZzaGFkZXJcIiwgXCJidWlsdGluL3NoYWRlcnMvcmVjdC5mc2hhZGVyXCIpO1xuXG5cdFx0Ly8gUXVldWUgYSBsb2FkIGZvciB0aGUgc3ByaXRlIHNoYWRlclxuXHRcdHRoaXMucmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShTaGFkZXJSZWdpc3RyeS5TUFJJVEVfU0hBREVSLCBTcHJpdGVTaGFkZXJUeXBlLCBcImJ1aWx0aW4vc2hhZGVycy9zcHJpdGUudnNoYWRlclwiLCBcImJ1aWx0aW4vc2hhZGVycy9zcHJpdGUuZnNoYWRlclwiKTtcblx0XG5cdFx0Ly8gUXVldWUgYSBsb2FkIGZvciB0aGUgbGFiZWwgc2hhZGVyXG5cdFx0dGhpcy5yZWdpc3RlckFuZFByZWxvYWRJdGVtKFNoYWRlclJlZ2lzdHJ5LkxBQkVMX1NIQURFUiwgTGFiZWxTaGFkZXJUeXBlLCBcImJ1aWx0aW4vc2hhZGVycy9sYWJlbC52c2hhZGVyXCIsIFwiYnVpbHRpbi9zaGFkZXJzL2xhYmVsLmZzaGFkZXJcIik7XG5cblx0XHQvLyBRdWV1ZSBhIGxvYWQgZm9yIGFueSBwcmVsb2FkZWQgaXRlbXNcblx0XHRmb3IobGV0IGl0ZW0gb2YgdGhpcy5yZWdpc3RyeUl0ZW1zKXtcblx0XHRcdGNvbnN0IHNoYWRlciA9IG5ldyBpdGVtLmNvbnN0cihpdGVtLmtleSk7XG5cdFx0XHRzaGFkZXIuaW5pdEJ1ZmZlck9iamVjdCgpO1xuXHRcdFx0dGhpcy5hZGQoaXRlbS5rZXksIHNoYWRlcik7XG5cblx0XHRcdC8vIExvYWQgaWYgZGVzaXJlZFxuXHRcdFx0aWYoaXRlbS5wcmVsb2FkICE9PSB1bmRlZmluZWQpe1xuXHRcdFx0XHRybS5zaGFkZXIoaXRlbS5rZXksIGl0ZW0ucHJlbG9hZC52c2hhZGVyTG9jYXRpb24sIGl0ZW0ucHJlbG9hZC5mc2hhZGVyTG9jYXRpb24pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSBzaGFkZXIgaW4gdGhlIHJlZ2lzdHJ5IGFuZCBsb2FkcyBpdCBiZWZvcmUgdGhlIGdhbWUgYmVnaW5zXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSB5b3Ugd2lzaCB0byBhc3NpZ24gdG8gdGhlIHNoYWRlclxuXHQgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBvZiB0aGUgU2hhZGVyVHlwZVxuXHQgKiBAcGFyYW0gdnNoYWRlckxvY2F0aW9uIFRoZSBsb2NhdGlvbiBvZiB0aGUgdmVydGV4IHNoYWRlclxuXHQgKiBAcGFyYW0gZnNoYWRlckxvY2F0aW9uIHRoZSBsb2NhdGlvbiBvZiB0aGUgZnJhZ21lbnQgc2hhZGVyXG5cdCAqL1xuXHRwdWJsaWMgcmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShrZXk6IHN0cmluZywgY29uc3RyOiBuZXcgKHByb2dyYW1LZXk6IHN0cmluZykgPT4gU2hhZGVyVHlwZSwgdnNoYWRlckxvY2F0aW9uOiBzdHJpbmcsIGZzaGFkZXJMb2NhdGlvbjogc3RyaW5nKTogdm9pZCB7XG5cdFx0bGV0IHNoYWRlclByZWxvYWQgPSBuZXcgU2hhZGVyUHJlbG9hZCgpO1xuXHRcdHNoYWRlclByZWxvYWQudnNoYWRlckxvY2F0aW9uID0gdnNoYWRlckxvY2F0aW9uO1xuXHRcdHNoYWRlclByZWxvYWQuZnNoYWRlckxvY2F0aW9uID0gZnNoYWRlckxvY2F0aW9uO1xuXG5cdFx0bGV0IHJlZ2lzdHJ5SXRlbSA9IG5ldyBTaGFkZXJSZWdpc3RyeUl0ZW0oKTtcblx0XHRyZWdpc3RyeUl0ZW0ua2V5ID0ga2V5O1xuXHRcdHJlZ2lzdHJ5SXRlbS5jb25zdHIgPSBjb25zdHI7XG5cdFx0cmVnaXN0cnlJdGVtLnByZWxvYWQgPSBzaGFkZXJQcmVsb2FkO1xuXG5cdFx0dGhpcy5yZWdpc3RyeUl0ZW1zLnB1c2gocmVnaXN0cnlJdGVtKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZWdpc3RlcnMgYSBzaGFkZXIgaW4gdGhlIHJlZ2lzdHJ5LiBOT1RFOiBJZiB5b3UgdXNlIHRoaXMsIHlvdSBNVVNUIGxvYWQgdGhlIHNoYWRlciBiZWZvcmUgdXNlLlxuXHQgKiBJZiB5b3Ugd2lzaCB0byBwcmVsb2FkIHRoZSBzaGFkZXIsIHVzZSByZWdpc3RlckFuZFByZWxvYWRJdGVtKClcblx0ICogQHBhcmFtIGtleSBUaGUga2V5IHlvdSB3aXNoIHRvIGFzc2lnbiB0byB0aGUgc2hhZGVyXG5cdCAqIEBwYXJhbSBjb25zdHIgVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBTaGFkZXJUeXBlXG5cdCAqL1xuXHRwdWJsaWMgcmVnaXN0ZXJJdGVtKGtleTogc3RyaW5nLCBjb25zdHI6IG5ldyAocHJvZ3JhbUtleTogc3RyaW5nKSA9PiBTaGFkZXJUeXBlKTogdm9pZCB7XG5cdFx0bGV0IHJlZ2lzdHJ5SXRlbSA9IG5ldyBTaGFkZXJSZWdpc3RyeUl0ZW0oKTtcblx0XHRyZWdpc3RyeUl0ZW0ua2V5ID0ga2V5O1xuXHRcdHJlZ2lzdHJ5SXRlbS5jb25zdHIgPSBjb25zdHI7XG5cblx0XHR0aGlzLnJlZ2lzdHJ5SXRlbXMucHVzaChyZWdpc3RyeUl0ZW0pO1xuXHR9XG59XG5cbmNsYXNzIFNoYWRlclJlZ2lzdHJ5SXRlbSB7XG5cdGtleTogc3RyaW5nO1xuXHRjb25zdHI6IG5ldyAocHJvZ3JhbUtleTogc3RyaW5nKSA9PiBTaGFkZXJUeXBlO1xuXHRwcmVsb2FkOiBTaGFkZXJQcmVsb2FkO1xufVxuXG5jbGFzcyBTaGFkZXJQcmVsb2FkIHtcblx0dnNoYWRlckxvY2F0aW9uOiBzdHJpbmc7XG5cdGZzaGFkZXJMb2NhdGlvbjogc3RyaW5nO1xufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBSZWdpc3RyeSBmcm9tIFwiLi9SZWdpc3RyaWVzL1JlZ2lzdHJ5XCI7XG5pbXBvcnQgU2hhZGVyUmVnaXN0cnkgZnJvbSBcIi4vUmVnaXN0cmllcy9TaGFkZXJSZWdpc3RyeVwiO1xuXG4vKipcbiAqIFRoZSBSZWdpc3RyeSBpcyB0aGUgc3lzdGVtJ3Mgd2F5IG9mIGNvbnZlcnRpbmcgY2xhc3NlcyBhbmQgdHlwZXMgaW50byBzdHJpbmdcbiAqIHJlcHJlc2VudGF0aW9ucyBmb3IgdXNlIGVsc2V3aGVyZSBpbiB0aGUgYXBwbGljYXRpb24uXG4gKiBJdCBhbGxvd3MgY2xhc3NlcyB0byBiZSBhY2Nlc3NlZCB3aXRob3V0IGV4cGxpY2l0bHkgdXNpbmcgY29uc3RydWN0b3JzIGluIGNvZGUsXG4gKiBhbmQgZm9yIHJlc291cmNlcyB0byBiZSBsb2FkZWQgYXQgR2FtZSBjcmVhdGlvbiB0aW1lLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWdpc3RyeU1hbmFnZXIge1xuXG5cdHB1YmxpYyBzdGF0aWMgc2hhZGVycyA9IG5ldyBTaGFkZXJSZWdpc3RyeSgpO1xuXG5cdC8qKiBBZGRpdGlvbmFsIGN1c3RvbSByZWdpc3RyaWVzIHRvIGFkZCB0byB0aGUgcmVnaXN0cnkgbWFuYWdlciAqL1xuXHRwcm90ZWN0ZWQgc3RhdGljIHJlZ2lzdHJpZXM6IE1hcDxSZWdpc3RyeTxhbnk+PiA9IG5ldyBNYXAoKTtcblxuXHRzdGF0aWMgcHJlbG9hZCgpe1xuXHRcdHRoaXMuc2hhZGVycy5wcmVsb2FkKCk7XG5cblx0XHR0aGlzLnJlZ2lzdHJpZXMuZm9yRWFjaCgoa2V5OiBzdHJpbmcpID0+IHRoaXMucmVnaXN0cmllcy5nZXQoa2V5KS5wcmVsb2FkKCkpO1xuXHR9XG5cblx0c3RhdGljIGFkZEN1c3RvbVJlZ2lzdHJ5KG5hbWU6IHN0cmluZywgcmVnaXN0cnk6IFJlZ2lzdHJ5PGFueT4pe1xuXHRcdHRoaXMucmVnaXN0cmllcy5hZGQobmFtZSwgcmVnaXN0cnkpO1xuXHR9XG5cblx0c3RhdGljIGdldFJlZ2lzdHJ5KGtleTogc3RyaW5nKXtcblx0XHRyZXR1cm4gdGhpcy5yZWdpc3RyaWVzLmdldChrZXkpO1xuXHR9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uLy4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IHsgQW5pbWF0aW9uRGF0YSwgQW5pbWF0aW9uU3RhdGUgfSBmcm9tIFwiLi9BbmltYXRpb25UeXBlc1wiO1xuXG4vKipcbiAqIEFuIGFuaW1hdGlvbiBtYW5hZ2VyIGNsYXNzIGZvciBhbiBhbmltYXRlZCBDYW52YXNOb2RlLlxuICogVGhpcyBjbGFzcyBrZWVwcyB0cmFjayBvZiB0aGUgcG9zc2libGUgYW5pbWF0aW9ucywgYXMgd2VsbCBhcyB0aGUgY3VycmVudCBhbmltYXRpb24gc3RhdGUsXG4gKiBhbmQgYWJzdHJhY3RzIGFsbCBpbnRlcmFjdGlvbnMgd2l0aCBwbGF5aW5nLCBwYXVzaW5nLCBhbmQgc3RvcHBpbmcgYW5pbWF0aW9ucyBhcyB3ZWxsIGFzIFxuICogY3JlYXRpbmcgbmV3IGFuaW1hdGlvbnMgZnJvbSB0aGUgQ2FudmFzTm9kZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQW5pbWF0aW9uTWFuYWdlciB7XG4gICAgLyoqIFRoZSBvd25lciBvZiB0aGlzIGFuaW1hdGlvbiBtYW5hZ2VyICovXG4gICAgcHJvdGVjdGVkIG93bmVyOiBDYW52YXNOb2RlO1xuICAgIFxuICAgIC8qKiBUaGUgY3VycmVudCBhbmltYXRpb24gc3RhdGUgb2YgdGhpcyBzcHJpdGUgKi9cbiAgICBwcm90ZWN0ZWQgYW5pbWF0aW9uU3RhdGU6IEFuaW1hdGlvblN0YXRlO1xuXG4gICAgLyoqIFRoZSBuYW1lIG9mIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBvZiB0aGlzIHNwcml0ZSAqL1xuICAgIHByb3RlY3RlZCBjdXJyZW50QW5pbWF0aW9uOiBzdHJpbmc7XG5cbiAgICAvKiogVGhlIGN1cnJlbnQgZnJhbWUgb2YgdGhpcyBhbmltYXRpb24gKi9cbiAgICBwcm90ZWN0ZWQgY3VycmVudEZyYW1lOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHByb2dyZXNzIG9mIHRoZSBjdXJyZW50IGFuaW1hdGlvbiB0aHJvdWdoIHRoZSBjdXJyZW50IGZyYW1lICovXG4gICAgcHJvdGVjdGVkIGZyYW1lUHJvZ3Jlc3M6IG51bWJlcjtcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBpcyBsb29waW5nIG9yIG5vdCAqL1xuICAgIHByb3RlY3RlZCBsb29wOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBtYXAgb2YgYW5pbWF0aW9ucyAqL1xuICAgIHByb3RlY3RlZCBhbmltYXRpb25zOiBNYXA8QW5pbWF0aW9uRGF0YT47XG5cbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGV2ZW50IChpZiBhbnkpIHRvIHNlbmQgd2hlbiB0aGUgY3VycmVudCBhbmltYXRpb24gc3RvcHMgcGxheWluZy4gKi9cbiAgICBwcm90ZWN0ZWQgb25FbmRFdmVudDogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSBldmVudCBlbWl0dGVyIGZvciB0aGlzIGFuaW1hdGlvbiBtYW5hZ2VyICovXG4gICAgcHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cbiAgICAvKiogQSBxdWV1ZWQgYW5pbWF0aW9uICovXG4gICAgcHJvdGVjdGVkIHBlbmRpbmdBbmltYXRpb246IHN0cmluZztcblxuICAgIC8qKiBUaGUgbG9vcCBzdGF0dXMgb2YgYSBwZW5kaW5nIGFuaW1hdGlvbiAqL1xuICAgIHByb3RlY3RlZCBwZW5kaW5nTG9vcDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgb25FbmQgZXZlbnQgb2YgYSBwZW5kaW5nIGFuaW1hdGlvbiAqL1xuICAgIHByb3RlY3RlZCBwZW5kaW5nT25FbmQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQW5pbWF0aW9uTWFuYWdlclxuICAgICAqIEBwYXJhbSBvd25lciBUaGUgb3duZXIgb2YgdGhlIEFuaW1hdGlvbk1hbmFnZXJcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihvd25lcjogQ2FudmFzTm9kZSl7XG4gICAgICAgIHRoaXMub3duZXIgPSBvd25lcjtcbiAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlNUT1BQRUQ7XG4gICAgICAgIHRoaXMuY3VycmVudEFuaW1hdGlvbiA9IFwiXCI7XG4gICAgICAgIHRoaXMuY3VycmVudEZyYW1lID0gMDtcbiAgICAgICAgdGhpcy5mcmFtZVByb2dyZXNzID0gMDtcbiAgICAgICAgdGhpcy5sb29wID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5vbkVuZEV2ZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYW4gYW5pbWF0aW9uIHRvIHRoaXMgc3ByaXRlXG4gICAgICogQHBhcmFtIGtleSBUaGUgdW5pcXVlIGtleSBvZiB0aGUgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIGFuaW1hdGlvbiBUaGUgYW5pbWF0aW9uIGRhdGFcbiAgICAgKi9cbiAgICBhZGQoa2V5OiBzdHJpbmcsIGFuaW1hdGlvbjogQW5pbWF0aW9uRGF0YSk6IHZvaWQge1xuICAgICAgICB0aGlzLmFuaW1hdGlvbnMuYWRkKGtleSwgYW5pbWF0aW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbmRleCBzcGVjaWZpZWQgYnkgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIGFuZCBjdXJyZW50IGZyYW1lXG4gICAgICogQHJldHVybnMgVGhlIGluZGV4IGluIHRoZSBjdXJyZW50IGFuaW1hdGlvblxuICAgICAqL1xuICAgIGdldEluZGV4KCk6IG51bWJlciB7XG4gICAgICAgIGlmKHRoaXMuYW5pbWF0aW9ucy5oYXModGhpcy5jdXJyZW50QW5pbWF0aW9uKSl7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hbmltYXRpb25zLmdldCh0aGlzLmN1cnJlbnRBbmltYXRpb24pLmZyYW1lc1t0aGlzLmN1cnJlbnRGcmFtZV0uaW5kZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBObyBjdXJyZW50IGFuaW1hdGlvbiwgd2FybiB0aGUgdXNlclxuICAgICAgICAgICAgY29uc29sZS53YXJuKGBBbmltYXRpb24gaW5kZXggd2FzIHJlcXVlc3RlZCwgYnV0IHRoZSBjdXJyZW50IGFuaW1hdGlvbjogJHt0aGlzLmN1cnJlbnRBbmltYXRpb259IHdhcyBpbnZhbGlkYCk7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERldGVybWluZXMgd2hldGhlciB0aGUgc3BlY2lmaWVkIGFuaW1hdGlvbiBpcyBjdXJyZW50bHkgcGxheWluZ1xuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgYW5pbWF0aW9uIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIGFuaW1hdGlvbiBpcyBwbGF5aW5nLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpc1BsYXlpbmcoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudEFuaW1hdGlvbiA9PT0ga2V5ICYmIHRoaXMuYW5pbWF0aW9uU3RhdGUgPT09IEFuaW1hdGlvblN0YXRlLlBMQVlJTkc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBpbmRleCBhbmQgYWR2YW5jZXMgdGhlIGFuaW1hdGlvbiBmcmFtZVxuICAgICAqIEByZXR1cm5zIFRoZSBpbmRleCBvZiB0aGUgYW5pbWF0aW9uIGZyYW1lXG4gICAgICovXG4gICAgZ2V0SW5kZXhBbmRBZHZhbmNlQW5pbWF0aW9uKCk6IG51bWJlciB7XG4gICAgICAgIC8vIElmIHdlIGFyZW4ndCBwbGF5aW5nLCB3ZSB3b24ndCBiZSBhZHZhbmNpbmcgdGhlIGFuaW1hdGlvblxuICAgICAgICBpZighKHRoaXMuYW5pbWF0aW9uU3RhdGUgPT09IEFuaW1hdGlvblN0YXRlLlBMQVlJTkcpKXtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEluZGV4KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLmFuaW1hdGlvbnMuaGFzKHRoaXMuY3VycmVudEFuaW1hdGlvbikpe1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRBbmltYXRpb24gPSB0aGlzLmFuaW1hdGlvbnMuZ2V0KHRoaXMuY3VycmVudEFuaW1hdGlvbik7XG4gICAgICAgICAgICBsZXQgaW5kZXggPSBjdXJyZW50QW5pbWF0aW9uLmZyYW1lc1t0aGlzLmN1cnJlbnRGcmFtZV0uaW5kZXg7XG5cbiAgICAgICAgICAgIC8vIEFkdmFuY2UgdGhlIGFuaW1hdGlvblxuICAgICAgICAgICAgdGhpcy5mcmFtZVByb2dyZXNzICs9IDE7XG4gICAgICAgICAgICBpZih0aGlzLmZyYW1lUHJvZ3Jlc3MgPj0gY3VycmVudEFuaW1hdGlvbi5mcmFtZXNbdGhpcy5jdXJyZW50RnJhbWVdLmR1cmF0aW9uKXtcbiAgICAgICAgICAgICAgICAvLyBXZSBoYXZlIGJlZW4gb24gdGhpcyBmcmFtZSBmb3IgaXRzIHdob2xlIGR1cmF0aW9uLCBnbyB0byB0aGUgbmV4dCBvbmVcbiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lUHJvZ3Jlc3MgPSAwO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudEZyYW1lICs9IDE7XG5cbiAgICAgICAgICAgICAgICBpZih0aGlzLmN1cnJlbnRGcmFtZSA+PSBjdXJyZW50QW5pbWF0aW9uLmZyYW1lcy5sZW5ndGgpe1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBoYXZlIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGlzIGFuaW1hdGlvblxuICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmxvb3Ape1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50RnJhbWUgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mcmFtZVByb2dyZXNzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kQ3VycmVudEFuaW1hdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZXR1cm4gdGhlIGN1cnJlbnQgaW5kZXhcbiAgICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE5vIGN1cnJlbnQgYW5pbWF0aW9uLCBjYW4ndCBhZHZhbmNlLiBXYXJuIHRoZSB1c2VyXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYEFuaW1hdGlvbiBpbmRleCBhbmQgYWR2YW5jZSB3YXMgcmVxdWVzdGVkLCBidXQgdGhlIGN1cnJlbnQgYW5pbWF0aW9uICgke3RoaXMuY3VycmVudEFuaW1hdGlvbn0pIGluIG5vZGUgd2l0aCBpZDogJHt0aGlzLm93bmVyLmlkfSB3YXMgaW52YWxpZGApO1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogRW5kcyB0aGUgY3VycmVudCBhbmltYXRpb24gYW5kIGZpcmVzIGFueSBuZWNlc3NhcnkgZXZlbnRzLCBhcyB3ZWxsIGFzIHN0YXJ0aW5nIGFueSBuZXcgYW5pbWF0aW9ucyAqL1xuICAgIHByb3RlY3RlZCBlbmRDdXJyZW50QW5pbWF0aW9uKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmN1cnJlbnRGcmFtZSA9IDA7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5TVE9QUEVEO1xuXG4gICAgICAgIGlmKHRoaXMub25FbmRFdmVudCAhPT0gbnVsbCl7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHRoaXMub25FbmRFdmVudCwge293bmVyOiB0aGlzLm93bmVyLmlkLCBhbmltYXRpb246IHRoaXMuY3VycmVudEFuaW1hdGlvbn0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgYSBwZW5kaW5nIGFuaW1hdGlvbiwgcGxheSBpdFxuICAgICAgICBpZih0aGlzLnBlbmRpbmdBbmltYXRpb24gIT09IG51bGwpe1xuICAgICAgICAgICAgdGhpcy5wbGF5KHRoaXMucGVuZGluZ0FuaW1hdGlvbiwgdGhpcy5wZW5kaW5nTG9vcCwgdGhpcy5wZW5kaW5nT25FbmQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheXMgdGhlIHNwZWNpZmllZCBhbmltYXRpb24uIERvZXMgbm90IHJlc3RhcnQgaXQgaWYgaXQgaXMgYWxyZWFkeSBwbGF5aW5nXG4gICAgICogQHBhcmFtIGFuaW1hdGlvbiBUaGUgbmFtZSBvZiB0aGUgYW5pbWF0aW9uIHRvIHBsYXlcbiAgICAgKiBAcGFyYW0gbG9vcCBXaGV0aGVyIG9yIG5vdCB0byBsb29wIHRoZSBhbmltYXRpb24uIEZhbHNlIGJ5IGRlZmF1bHRcbiAgICAgKiBAcGFyYW0gb25FbmQgVGhlIG5hbWUgb2YgYW4gZXZlbnQgdG8gc2VuZCB3aGVuIHRoaXMgYW5pbWF0aW9uIG5hdHVyYWxseSBzdG9wcyBwbGF5aW5nLiBUaGlzIG9ubHkgbWF0dGVycyBpZiBsb29wIGlzIGZhbHNlLlxuICAgICAqL1xuICAgIHBsYXlJZk5vdEFscmVhZHkoYW5pbWF0aW9uOiBzdHJpbmcsIGxvb3A/OiBib29sZWFuLCBvbkVuZD86IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLmN1cnJlbnRBbmltYXRpb24gIT09IGFuaW1hdGlvbil7XG4gICAgICAgICAgICB0aGlzLnBsYXkoYW5pbWF0aW9uLCBsb29wLCBvbkVuZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQbGF5cyB0aGUgc3BlY2lmaWVkIGFuaW1hdGlvblxuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIG5hbWUgb2YgdGhlIGFuaW1hdGlvbiB0byBwbGF5XG4gICAgICogQHBhcmFtIGxvb3AgV2hldGhlciBvciBub3QgdG8gbG9vcCB0aGUgYW5pbWF0aW9uLiBGYWxzZSBieSBkZWZhdWx0XG4gICAgICogQHBhcmFtIG9uRW5kIFRoZSBuYW1lIG9mIGFuIGV2ZW50IHRvIHNlbmQgd2hlbiB0aGlzIGFuaW1hdGlvbiBuYXR1cmFsbHkgc3RvcHMgcGxheWluZy4gVGhpcyBvbmx5IG1hdHRlcnMgaWYgbG9vcCBpcyBmYWxzZS5cbiAgICAgKi9cbiAgICBwbGF5KGFuaW1hdGlvbjogc3RyaW5nLCBsb29wPzogYm9vbGVhbiwgb25FbmQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdXJyZW50QW5pbWF0aW9uID0gYW5pbWF0aW9uO1xuICAgICAgICB0aGlzLmN1cnJlbnRGcmFtZSA9IDA7XG4gICAgICAgIHRoaXMuZnJhbWVQcm9ncmVzcyA9IDA7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HO1xuXG4gICAgICAgIC8vIElmIGxvb3AgYXJnIHdhcyBwcm92aWRlZCwgdXNlIHRoYXRcbiAgICAgICAgaWYobG9vcCAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHRoaXMubG9vcCA9IGxvb3A7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UsIHVzZSB3aGF0IHRoZSBqc29uIGZpbGUgc3BlY2lmaWVkXG4gICAgICAgICAgICB0aGlzLmxvb3AgPSB0aGlzLmFuaW1hdGlvbnMuZ2V0KGFuaW1hdGlvbikucmVwZWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob25FbmQgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICB0aGlzLm9uRW5kRXZlbnQgPSBvbkVuZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub25FbmRFdmVudCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXNldCBwZW5kaW5nIGFuaW1hdGlvblxuICAgICAgICB0aGlzLnBlbmRpbmdBbmltYXRpb24gPSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFF1ZXVlcyBhIHNpbmdsZSBhbmltYXRpb24gdG8gYmUgcGxheWVkIGFmdGVyIHRoZSBjdXJyZW50IG9uZS4gRG9lcyBOT1Qgc3RhY2suXG4gICAgICogUXVldWVpbmcgYWRkaXRpb25hbCBhbmltYXRpb25zIHBhc3QgMSB3aWxsIGp1c3QgcmVwbGFjZSB0aGUgcXVldWVkIGFuaW1hdGlvblxuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIGFuaW1hdGlvbiB0byBxdWV1ZVxuICAgICAqIEBwYXJhbSBsb29wIFdoZXRoZXIgb3Igbm90IHRoZSBsb29wIHRoZSBxdWV1ZWQgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIG9uRW5kIFRoZSBldmVudCB0byBmaXJlIHdoZW4gdGhlIHF1ZXVlZCBhbmltYXRpb24gZW5kc1xuICAgICAqL1xuICAgIHF1ZXVlKGFuaW1hdGlvbjogc3RyaW5nLCBsb29wOiBib29sZWFuID0gZmFsc2UsIG9uRW5kPzogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGVuZGluZ0FuaW1hdGlvbiA9IGFuaW1hdGlvbjtcbiAgICAgICAgdGhpcy5wZW5kaW5nTG9vcCA9IGxvb3A7XG4gICAgICAgIGlmKG9uRW5kICE9PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nT25FbmQgPSBvbkVuZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ09uRW5kID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBQYXVzZXMgdGhlIGN1cnJlbnQgYW5pbWF0aW9uICovXG4gICAgcGF1c2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5QQVVTRUQ7XG4gICAgfVxuXG4gICAgLyoqIFJlc3VtZXMgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIGlmIHBvc3NpYmxlICovXG4gICAgcmVzdW1lKCk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLmFuaW1hdGlvblN0YXRlID09PSBBbmltYXRpb25TdGF0ZS5QQVVTRUQpe1xuICAgICAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlBMQVlJTkc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogU3RvcHMgdGhlIGN1cnJlbnQgYW5pbWF0aW9uLiBUaGUgYW5pbWF0aW9uIGNhbm5vdCBiZSByZXN1bWVkIGFmdGVyIHRoaXMuICovXG4gICAgc3RvcCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlNUT1BQRUQ7XG4gICAgfVxufSIsImltcG9ydCB7IFR3ZWVuYWJsZVByb3BlcnRpZXMgfSBmcm9tIFwiLi4vLi4vTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCB7IEVhc2VGdW5jdGlvblR5cGUgfSBmcm9tIFwiLi4vLi4vVXRpbHMvRWFzZUZ1bmN0aW9uc1wiO1xuXG4vLyBAaWdub3JlUGFnZVxuXG5leHBvcnQgZW51bSBBbmltYXRpb25TdGF0ZSB7XG4gICAgU1RPUFBFRCA9IDAsXG4gICAgUEFVU0VEID0gMSxcbiAgICBQTEFZSU5HID0gMixcbn1cblxuZXhwb3J0IGNsYXNzIEFuaW1hdGlvbkRhdGEge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBmcmFtZXM6IEFycmF5PHtpbmRleDogbnVtYmVyLCBkdXJhdGlvbjogbnVtYmVyfT47XG4gICAgcmVwZWF0OiBib29sZWFuID0gZmFsc2U7XG59XG5cbmV4cG9ydCBjbGFzcyBUd2VlbkVmZmVjdCB7XG4gICAgLyoqIFRoZSBwcm9wZXJ0eSB0byB0d2VlbiAqL1xuICAgIHByb3BlcnR5OiBUd2VlbmFibGVQcm9wZXJ0aWVzO1xuXG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoZSBUd2VlbiBzaG91bGQgcmVzZXQgdGhlIHByb3BlcnR5IHRvIGl0cyBvcmlnaW5hbCB2YWx1ZSBhZnRlciBwbGF5aW5nICovXG4gICAgcmVzZXRPbkNvbXBsZXRlOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBzdGFydGluZyB2YWx1ZSBmb3IgdGhlIHR3ZWVuICovXG4gICAgc3RhcnQ6IGFueTtcblxuICAgIC8qKiBUaGUgZW5kaW5nIHZhbHVlIGZvciB0aGUgdHdlZW4gKi9cbiAgICBlbmQ6IGFueTtcblxuICAgIC8qKiBUaGUgZWFzZSBmdW5jdGlvbiB0byB1c2UgKi9cbiAgICBlYXNlOiBFYXNlRnVuY3Rpb25UeXBlO1xuXG4gICAgLyoqIERPIE5PVCBNT0RJRlkgLSBUaGUgb3JpZ2luYWwgdmFsdWUgb2YgdGhlIHByb3BlcnR5IC0gc2V0IGF1dG9tYXRpY2FsbHkgKi9cbiAgICBpbml0aWFsVmFsdWU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIFR3ZWVuRGF0YSB7XG4gICAgLy8gTWVtYmVycyBmb3IgaW5pdGlhbGl6YXRpb24gYnkgdGhlIHVzZXJcbiAgICAvKiogVGhlIGFtb3VudCBvZiB0aW1lIGluIG1zIHRvIHdhaXQgYmVmb3JlIGV4ZWN1dGluZyB0aGUgdHdlZW4gKi9cbiAgICBzdGFydERlbGF5OiBudW1iZXI7XG4gICAgLyoqIFRoZSBkdXJhdGlvbiBvZiB0aW1lIG92ZXIgd2hpY2ggdGhlIHZhbHVlIHdpdGggY2hhbmdlIGZyb20gc3RhcnQgdG8gZW5kICovXG4gICAgZHVyYXRpb246IG51bWJlcjtcbiAgICAvKiogQW4gYXJyYXkgb2YgdGhlIGVmZmVjdHMgb24gdGhlIHByb3BlcnRpZXMgb2YgdGhlIG9iamVjdCAqL1xuICAgIGVmZmVjdHM6IEFycmF5PFR3ZWVuRWZmZWN0PjtcbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyB0d2VlbiBzaG91bGQgcmV2ZXJzZSBmcm9tIGVuZCB0byBzdGFydCBmb3IgZWFjaCBwcm9wZXJ0eSB3aGVuIGl0IGZpbmlzaGVzICovXG4gICAgcmV2ZXJzZU9uQ29tcGxldGU6IGJvb2xlYW47XG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgdHdlZW4gc2hvdWxkIGxvb3Agd2hlbiBpdCBjb21wbGV0ZXMgKi9cbiAgICBsb29wOiBib29sZWFuO1xuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gc2VuZCAoaWYgYW55KSB3aGVuIHRoZSB0d2VlbiBmaW5pc2hlcyBwbGF5aW5nICovXG4gICAgb25FbmQ6IHN0cmluZ1xuXG4gICAgLyoqIEV4dHJhIGRhdGEgdG8gYmUgc2VudCB3aGVuIHRoZSBvbkVuZCBldmVudCBpcyBmaXJlZC4gS2V5cyB3aXRoIHRoZSBuYW1lICdrZXknIG9yICdub2RlJyBhcmUgcmVzZXJ2ZWQgYW5kIGNhbid0IGJlIHVzZWQgYXMgbmFtZXMgZm9yIHlvdXIgZXh0cmEgZGF0YSAqL1xuICAgIG9uRW5kRGF0YTogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICBcbiAgICAvLyBNZW1iZXJzIGZvciBtYW5hZ2VtZW50IGJ5IHRoZSB0d2VlbiBtYW5hZ2VyXG4gICAgLyoqIFRoZSBwcm9ncmVzcyBvZiB0aGlzIHR3ZWVuIHRocm91Z2ggaXRzIGVmZmVjdHMgKi9cbiAgICBwcm9ncmVzczogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBhbW91bnQgb2YgdGltZSBpbiBtcyB0aGF0IGhhcyBwYXNzZWQgZnJvbSB3aGVuIHRoaXMgdHdlZW4gc3RhcnRlZCBydW5uaW5nICovXG4gICAgZWxhcHNlZFRpbWU6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgc3RhdGUgb2YgdGhpcyB0d2VlbiAqL1xuICAgIGFuaW1hdGlvblN0YXRlOiBBbmltYXRpb25TdGF0ZTtcblxuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGlzIHR3ZWVuIGlzIGN1cnJlbnRseSByZXZlcnNpbmcgKi9cbiAgICByZXZlcnNpbmc6IGJvb2xlYW47XG59IiwiaW1wb3J0IFVwZGF0ZWFibGUgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1VwZGF0ZWFibGVcIjtcbmltcG9ydCBQYXJ0aWNsZVN5c3RlbSBmcm9tIFwiLi9QYXJ0aWNsZVN5c3RlbVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcblxuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIgPSBudWxsO1xuICAgIFxuICAgIHByb3RlY3RlZCBwYXJ0aWNsZVN5c3RlbXM6IEFycmF5PFBhcnRpY2xlU3lzdGVtPjtcblxuICAgIHByaXZhdGUgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy5wYXJ0aWNsZVN5c3RlbXMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogUGFydGljbGVTeXN0ZW1NYW5hZ2VyIHtcbiAgICAgICAgaWYoUGFydGljbGVTeXN0ZW1NYW5hZ2VyLmluc3RhbmNlID09PSBudWxsKXtcbiAgICAgICAgICAgIFBhcnRpY2xlU3lzdGVtTWFuYWdlci5pbnN0YW5jZSA9IG5ldyBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJQYXJ0aWNsZVN5c3RlbShzeXN0ZW06IFBhcnRpY2xlU3lzdGVtKXtcbiAgICAgICAgdGhpcy5wYXJ0aWNsZVN5c3RlbXMucHVzaChzeXN0ZW0pO1xuICAgIH1cblxuICAgIGRlcmVnaXN0ZXJQYXJ0aWNsZVN5c3RlbShzeXN0ZW06IFBhcnRpY2xlU3lzdGVtKXtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5wYXJ0aWNsZVN5c3RlbXMuaW5kZXhPZihzeXN0ZW0pO1xuICAgICAgICB0aGlzLnBhcnRpY2xlU3lzdGVtcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cblxuICAgIGNsZWFyUGFydGljbGVTeXN0ZW1zKCl7XG4gICAgICAgIHRoaXMucGFydGljbGVTeXN0ZW1zID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGZvcihsZXQgcGFydGljbGVTeXN0ZW0gb2YgdGhpcy5wYXJ0aWNsZVN5c3RlbXMpe1xuICAgICAgICAgICAgcGFydGljbGVTeXN0ZW0udXBkYXRlKGRlbHRhVCk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IHsgQW5pbWF0aW9uU3RhdGUsIFR3ZWVuRGF0YSB9IGZyb20gXCIuL0FuaW1hdGlvblR5cGVzXCI7XG5pbXBvcnQgRWFzZUZ1bmN0aW9ucyBmcm9tIFwiLi4vLi4vVXRpbHMvRWFzZUZ1bmN0aW9uc1wiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgVHdlZW5NYW5hZ2VyIGZyb20gXCIuL1R3ZWVuTWFuYWdlclwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uLy4uL0V2ZW50cy9FbWl0dGVyXCI7XG5cbi8qKlxuICogQSBtYW5hZ2VyIGZvciB0aGUgdHdlZW5zIG9mIGEgR2FtZU5vZGUuXG4gKiBUd2VlbnMgYXJlIHNob3J0IGFuaW1hdGlvbnMgcGxheWVkIGJ5IGludGVycG9sYXRpbmcgYmV0d2VlbiB0d28gcHJvcGVydGllcyB1c2luZyBhbiBlYXNpbmcgZnVuY3Rpb24uXG4gKiBGb3IgYSBnb29kIHZpc3VhbCByZXByZXNlbnRhdGlvbiBvZiBlYXNpbmcgZnVuY3Rpb25zLCBjaGVjayBvdXQgQGxpbmsoaHR0cHM6Ly9lYXNpbmdzLm5ldC8pKGh0dHBzOi8vZWFzaW5ncy5uZXQvKS5cbiAqIE11bHRpcGxlIHR3ZWVuIGNhbiBiZSBwbGF5ZWQgYXQgdGhlIHNhbWUgdGltZSwgYXMgbG9uZyBhcyB0aGV5IGRvbid0IGNoYW5nZSB0aGUgc2FtZSBwcm9wZXJ0eS5cbiAqIFRoaXMgYWxsb3dzIGZvciBzb21lIGludGVyZXN0aW5nIHBvbGlzaGVzIG9yIGFuaW1hdGlvbnMgdGhhdCBtYXkgYmUgdmVyeSBkaWZmaWN1bHQgdG8gZG8gd2l0aCBzcHJpdGUgd29yayBhbG9uZVxuICogLSBlc3BlY2lhbGx5IHBpeGVsIGFydCAoc3VjaCBhcyByb3RhdGlvbnMgb3Igc2NhbGluZykuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFR3ZWVuQ29udHJvbGxlciB7XG4gICAgLyoqIFRoZSBHYW1lTm9kZSB0aGlzIFR3ZWVuQ29udHJvbGxlciBhY3RzIHVwb24gKi9cbiAgICBwcm90ZWN0ZWQgb3duZXI6IEdhbWVOb2RlO1xuICAgIC8qKiBUaGUgbGlzdCBvZiBjcmVhdGVkIHR3ZWVucyAqL1xuICAgIHByb3RlY3RlZCB0d2VlbnM6IE1hcDxUd2VlbkRhdGE+O1xuICAgIC8qKiBBbiBldmVudCBlbWl0dGVyICovXG4gICAgcHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IFR3ZWVuQ29udHJvbGxlclxuICAgICAqIEBwYXJhbSBvd25lciBUaGUgb3duZXIgb2YgdGhlIFR3ZWVuQ29udHJvbGxlclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG93bmVyOiBHYW1lTm9kZSl7XG4gICAgICAgIHRoaXMub3duZXIgPSBvd25lcjtcbiAgICAgICAgdGhpcy50d2VlbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG5cbiAgICAgICAgLy8gR2l2ZSBvdXJzZWx2ZXMgdG8gdGhlIFR3ZWVuTWFuYWdlclxuICAgICAgICBUd2Vlbk1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5yZWdpc3RlclR3ZWVuQ29udHJvbGxlcih0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXN0cm95cyB0aGlzIFR3ZWVuQ29udHJvbGxlclxuICAgICAqL1xuICAgIGRlc3Ryb3koKXtcbiAgICAgICAgLy8gT25seSB0aGUgZ2FtZW5vZGUgYW5kIHRoZSB0d2VlbiBtYW5hZ2VyIHNob3VsZCBoYXZlIGEgcmVmZXJlbmNlIHRvIHRoaXNcbiAgICAgICAgZGVsZXRlIHRoaXMub3duZXIudHdlZW5zO1xuICAgICAgICBUd2Vlbk1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5kZXJlZ2lzdGVyVHdlZW5Db250cm9sbGVyKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIHR3ZWVuIHRvIHRoaXMgZ2FtZSBub2RlXG4gICAgICogQHBhcmFtIGtleSBUaGUgbmFtZSBvZiB0aGUgdHdlZW5cbiAgICAgKiBAcGFyYW0gdHdlZW4gVGhlIGRhdGEgb2YgdGhlIHR3ZWVuXG4gICAgICovXG4gICAgYWRkKGtleTogc3RyaW5nLCB0d2VlbjogUmVjb3JkPHN0cmluZywgYW55PiB8IFR3ZWVuRGF0YSk6IHZvaWQge1xuICAgICAgICBsZXQgdHlwZWRUd2VlbiA9IDxUd2VlbkRhdGE+dHdlZW47XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBtZW1iZXJzIHRoYXQgd2UgbmVlZCAoYW5kIHRoZSB1c2VyIGRpZG4ndCBwcm92aWRlKVxuICAgICAgICB0eXBlZFR3ZWVuLnByb2dyZXNzID0gMDtcbiAgICAgICAgdHlwZWRUd2Vlbi5lbGFwc2VkVGltZSA9IDA7XG4gICAgICAgIHR5cGVkVHdlZW4uYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5TVE9QUEVEO1xuXG4gICAgICAgIHRoaXMudHdlZW5zLmFkZChrZXksIHR5cGVkVHdlZW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBsYXkgYSB0d2VlbiB3aXRoIGEgY2VydGFpbiBuYW1lXG4gICAgICogQHBhcmFtIGtleSBUaGUgbmFtZSBvZiB0aGUgdHdlZW4gdG8gcGxheVxuICAgICAqIEBwYXJhbSBsb29wIFdoZXRoZXIgb3Igbm90IHRoZSB0d2VlbiBzaG91bGQgbG9vcFxuICAgICAqL1xuICAgIHBsYXkoa2V5OiBzdHJpbmcsIGxvb3A/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMudHdlZW5zLmhhcyhrZXkpKXtcbiAgICAgICAgICAgIGxldCB0d2VlbiA9IHRoaXMudHdlZW5zLmdldChrZXkpO1xuXG4gICAgICAgICAgICAvLyBTZXQgbG9vcCBpZiBuZWVkZWRcbiAgICAgICAgICAgIGlmKGxvb3AgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgdHdlZW4ubG9vcCA9IGxvb3A7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgaW5pdGlhbCB2YWx1ZXNcbiAgICAgICAgICAgIGZvcihsZXQgZWZmZWN0IG9mIHR3ZWVuLmVmZmVjdHMpe1xuICAgICAgICAgICAgICAgIGlmKGVmZmVjdC5yZXNldE9uQ29tcGxldGUpe1xuICAgICAgICAgICAgICAgICAgICBlZmZlY3QuaW5pdGlhbFZhbHVlID0gdGhpcy5vd25lcltlZmZlY3QucHJvcGVydHldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RhcnQgdGhlIHR3ZWVuIHJ1bm5pbmdcbiAgICAgICAgICAgIHR3ZWVuLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuUExBWUlORztcbiAgICAgICAgICAgIHR3ZWVuLmVsYXBzZWRUaW1lID0gMDtcbiAgICAgICAgICAgIHR3ZWVuLnByb2dyZXNzID0gMDtcbiAgICAgICAgICAgIHR3ZWVuLnJldmVyc2luZyA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBUcmllZCB0byBwbGF5IHR3ZWVuIFwiJHtrZXl9XCIgb24gbm9kZSB3aXRoIGlkICR7dGhpcy5vd25lci5pZH0sIGJ1dCBubyBzdWNoIHR3ZWVuIGV4aXN0c2ApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGF1c2VzIGEgcGxheWluZyB0d2Vlbi4gRG9lcyBub3QgYWZmZWN0IHR3ZWVucyB0aGF0IGFyZSBzdG9wcGVkLlxuICAgICAqIEBwYXJhbSBrZXkgVGhlIG5hbWUgb2YgdGhlIHR3ZWVuIHRvIHBhdXNlLlxuICAgICAqL1xuICAgIHBhdXNlKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMudHdlZW5zLmhhcyhrZXkpKXtcbiAgICAgICAgICAgIHRoaXMudHdlZW5zLmdldChrZXkpLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuUEFVU0VEO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzdW1lcyBhIHBhdXNlZCB0d2Vlbi5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBuYW1lIG9mIHRoZSB0d2VlbiB0byByZXN1bWVcbiAgICAgKi9cbiAgICByZXN1bWUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy50d2VlbnMuaGFzKGtleSkpe1xuICAgICAgICAgICAgbGV0IHR3ZWVuID0gdGhpcy50d2VlbnMuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZih0d2Vlbi5hbmltYXRpb25TdGF0ZSA9PT0gQW5pbWF0aW9uU3RhdGUuUEFVU0VEKVxuICAgICAgICAgICAgICAgIHR3ZWVuLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuUExBWUlORztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0b3BzIGEgY3VycmVudGx5IHBsYXlpbmcgdHdlZW5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHR3ZWVuXG4gICAgICovXG4gICAgc3RvcChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLnR3ZWVucy5oYXMoa2V5KSl7XG4gICAgICAgICAgICBsZXQgdHdlZW4gPSB0aGlzLnR3ZWVucy5nZXQoa2V5KTtcbiAgICAgICAgICAgIHR3ZWVuLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuU1RPUFBFRDtcblxuICAgICAgICAgICAgLy8gUmV0dXJuIHRvIHRoZSBpbml0aWFsIHZhbHVlc1xuICAgICAgICAgICAgZm9yKGxldCBlZmZlY3Qgb2YgdHdlZW4uZWZmZWN0cyl7XG4gICAgICAgICAgICAgICAgaWYoZWZmZWN0LnJlc2V0T25Db21wbGV0ZSl7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3duZXJbZWZmZWN0LnByb3BlcnR5XSA9IGVmZmVjdC5pbml0aWFsVmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIG5hdHVyYWwgc3RvcCBvZiBhIGN1cnJlbnRseSBwbGF5aW5nIHR3ZWVuXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSB0d2VlblxuICAgICAqL1xuICAgIHByb3RlY3RlZCBlbmQoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdG9wKGtleSk7XG4gICAgICAgIGlmKHRoaXMudHdlZW5zLmhhcyhrZXkpKXtcbiAgICAgICAgICAgIC8vIEdldCB0aGUgdHdlZW5cbiAgICAgICAgICAgIGxldCB0d2VlbiA9IHRoaXMudHdlZW5zLmdldChrZXkpO1xuXG4gICAgICAgICAgICAvLyBJZiBpdCBoYXMgYW4gb25FbmQsIHNlbmQgYW4gZXZlbnRcbiAgICAgICAgICAgIGlmKHR3ZWVuLm9uRW5kKXtcbiAgICAgICAgICAgICAgICBsZXQgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PiA9IHtrZXk6IGtleSwgbm9kZTogdGhpcy5vd25lci5pZH1cbiAgICAgICAgICAgICAgICAvLyBJZiBpdCBoYXMgb25FbmQgZXZlbnQgZGF0YSwgYWRkIGVhY2ggZW50cnksIGFzIGxvbmcgYXMgdGhlIGtleSBpcyBub3QgbmFtZWQgJ2tleScgb3IgJ25vZGUnXG4gICAgICAgICAgICAgICAgaWYgKHR3ZWVuLm9uRW5kRGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyh0d2Vlbi5vbkVuZERhdGEpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwia2V5XCIgJiYga2V5ICE9PSBcIm5vZGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFba2V5XSA9IHR3ZWVuLm9uRW5kRGF0YVtrZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHR3ZWVuLm9uRW5kLCBkYXRhKTsgXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdG9wcyBhbGwgY3VycmVudGx5IHBsYXlpbmcgdHdlZW5zXG4gICAgICovXG4gICAgc3RvcEFsbCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50d2VlbnMuZm9yRWFjaChrZXkgPT4gdGhpcy5zdG9wKGtleSkpO1xuICAgIH1cbiAgICBcbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50d2VlbnMuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgbGV0IHR3ZWVuID0gdGhpcy50d2VlbnMuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZih0d2Vlbi5hbmltYXRpb25TdGF0ZSA9PT0gQW5pbWF0aW9uU3RhdGUuUExBWUlORyl7XG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBwcm9ncmVzcyBvZiB0aGUgdHdlZW5cbiAgICAgICAgICAgICAgICB0d2Vlbi5lbGFwc2VkVGltZSArPSBkZWx0YVQqMTAwMDtcblxuICAgICAgICAgICAgICAgIC8vIElmIHdlJ3JlIHBhc3QgdGhlIHN0YXJ0RGVsYXksIGRvIHRoZSB0d2VlblxuICAgICAgICAgICAgICAgIGlmKHR3ZWVuLmVsYXBzZWRUaW1lID49IHR3ZWVuLnN0YXJ0RGVsYXkpe1xuICAgICAgICAgICAgICAgICAgICBpZighdHdlZW4ucmV2ZXJzaW5nICYmIHR3ZWVuLmVsYXBzZWRUaW1lID49IHR3ZWVuLnN0YXJ0RGVsYXkgKyB0d2Vlbi5kdXJhdGlvbil7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSdyZSBvdmVyIHRpbWUsIHN0b3AgdGhlIHR3ZWVuLCBsb29wLCBvciByZXZlcnNlXG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0d2Vlbi5yZXZlcnNlT25Db21wbGV0ZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UncmUgb3ZlciB0aW1lIGFuZCBjYW4gcmV2ZXJzZSwgZG8gc29cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0d2Vlbi5yZXZlcnNpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHR3ZWVuLmxvb3Ape1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGNhbid0IHJldmVyc2UgYW5kIGNhbiBsb29wLCBkbyBzb1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR3ZWVuLmVsYXBzZWRUaW1lIC09IHR3ZWVuLmR1cmF0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmVuJ3QgbG9vcGluZyBhbmQgY2FuJ3QgcmV2ZXJzZSwgc28gc3RvcFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kKGtleSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgdGhlIGVuZCBvZiByZXZlcnNpbmdcbiAgICAgICAgICAgICAgICAgICAgaWYodHdlZW4ucmV2ZXJzaW5nICYmIHR3ZWVuLmVsYXBzZWRUaW1lID49IHR3ZWVuLnN0YXJ0RGVsYXkgKyAyKnR3ZWVuLmR1cmF0aW9uKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHR3ZWVuLmxvb3Ape1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR3ZWVuLnJldmVyc2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR3ZWVuLmVsYXBzZWRUaW1lIC09IDIqdHdlZW4uZHVyYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kKGtleSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHByb2dyZXNzLCBtYWtlIHN1cmUgaXQgaXMgYmV0d2VlbiAwIGFuZCAxLiBFcnJvcnMgZnJvbSB0aGlzIHNob3VsZCBuZXZlciBiZSBsYXJnZVxuICAgICAgICAgICAgICAgICAgICBpZih0d2Vlbi5yZXZlcnNpbmcpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHdlZW4ucHJvZ3Jlc3MgPSBNYXRoVXRpbHMuY2xhbXAwMSgoMip0d2Vlbi5kdXJhdGlvbiAtICh0d2Vlbi5lbGFwc2VkVGltZS0gdHdlZW4uc3RhcnREZWxheSkpL3R3ZWVuLmR1cmF0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR3ZWVuLnByb2dyZXNzID0gTWF0aFV0aWxzLmNsYW1wMDEoKHR3ZWVuLmVsYXBzZWRUaW1lIC0gdHdlZW4uc3RhcnREZWxheSkvdHdlZW4uZHVyYXRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBlZmZlY3Qgb2YgdHdlZW4uZWZmZWN0cyl7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgdmFsdWUgZnJvbSB0aGUgZWFzZSBmdW5jdGlvbiB0aGF0IGNvcnJlc3BvbmRzIHRvIG91ciBwcm9ncmVzc1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVhc2UgPSBFYXNlRnVuY3Rpb25zW2VmZmVjdC5lYXNlXSh0d2Vlbi5wcm9ncmVzcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVzZSB0aGUgdmFsdWUgdG8gbGVycCB0aGUgcHJvcGVydHlcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IE1hdGhVdGlscy5sZXJwKGVmZmVjdC5zdGFydCwgZWZmZWN0LmVuZCwgZWFzZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm93bmVyW2VmZmVjdC5wcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufSIsImltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgVHdlZW5Db250cm9sbGVyIGZyb20gXCIuL1R3ZWVuQ29udHJvbGxlclwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUd2Vlbk1hbmFnZXIgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcblxuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBUd2Vlbk1hbmFnZXIgPSBudWxsO1xuICAgIFxuICAgIHByb3RlY3RlZCB0d2VlbkNvbnRyb2xsZXJzOiBBcnJheTxUd2VlbkNvbnRyb2xsZXI+O1xuXG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnR3ZWVuQ29udHJvbGxlcnMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogVHdlZW5NYW5hZ2VyIHtcbiAgICAgICAgaWYoVHdlZW5NYW5hZ2VyLmluc3RhbmNlID09PSBudWxsKXtcbiAgICAgICAgICAgIFR3ZWVuTWFuYWdlci5pbnN0YW5jZSA9IG5ldyBUd2Vlbk1hbmFnZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBUd2Vlbk1hbmFnZXIuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJUd2VlbkNvbnRyb2xsZXIoY29udHJvbGxlcjogVHdlZW5Db250cm9sbGVyKXtcbiAgICAgICAgdGhpcy50d2VlbkNvbnRyb2xsZXJzLnB1c2goY29udHJvbGxlcik7XG4gICAgfVxuXG4gICAgZGVyZWdpc3RlclR3ZWVuQ29udHJvbGxlcihjb250cm9sbGVyOiBUd2VlbkNvbnRyb2xsZXIpe1xuICAgICAgICBsZXQgaW5kZXggPSB0aGlzLnR3ZWVuQ29udHJvbGxlcnMuaW5kZXhPZihjb250cm9sbGVyKTtcbiAgICAgICAgdGhpcy50d2VlbkNvbnRyb2xsZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgfVxuXG4gICAgY2xlYXJUd2VlbkNvbnRyb2xsZXJzKCl7XG4gICAgICAgIHRoaXMudHdlZW5Db250cm9sbGVycyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBmb3IobGV0IHR3ZWVuQ29udHJvbGxlciBvZiB0aGlzLnR3ZWVuQ29udHJvbGxlcnMpe1xuICAgICAgICAgICAgdHdlZW5Db250cm9sbGVyLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgR3JhcGhpYyBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY1wiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljcy9Qb2ludFwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IE9ydGhvZ29uYWxUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwcy9PcnRob2dvbmFsVGlsZW1hcFwiO1xuaW1wb3J0IFVJRWxlbWVudCBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50XCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBHcmFwaGljUmVuZGVyZXIgZnJvbSBcIi4vQ2FudmFzUmVuZGVyaW5nL0dyYXBoaWNSZW5kZXJlclwiO1xuaW1wb3J0IFJlbmRlcmluZ01hbmFnZXIgZnJvbSBcIi4vUmVuZGVyaW5nTWFuYWdlclwiXG5pbXBvcnQgVGlsZW1hcFJlbmRlcmVyIGZyb20gXCIuL0NhbnZhc1JlbmRlcmluZy9UaWxlbWFwUmVuZGVyZXJcIjtcbmltcG9ydCBVSUVsZW1lbnRSZW5kZXJlciBmcm9tIFwiLi9DYW52YXNSZW5kZXJpbmcvVUlFbGVtZW50UmVuZGVyZXJcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IEJ1dHRvbiBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50cy9CdXR0b25cIjtcbmltcG9ydCBTbGlkZXIgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudHMvU2xpZGVyXCI7XG5pbXBvcnQgVGV4dElucHV0IGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRzL1RleHRJbnB1dFwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBMaW5lIGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljcy9MaW5lXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5cbi8qKlxuICogQW4gaW1wbGVtZW50YXRpb24gb2YgdGhlIFJlbmRlcmluZ01hbmFnZXIgY2xhc3MgdXNpbmcgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDYW52YXNSZW5kZXJlciBleHRlbmRzIFJlbmRlcmluZ01hbmFnZXIge1xuICAgIHByb3RlY3RlZCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgICBwcm90ZWN0ZWQgZ3JhcGhpY1JlbmRlcmVyOiBHcmFwaGljUmVuZGVyZXI7XG4gICAgcHJvdGVjdGVkIHRpbGVtYXBSZW5kZXJlcjogVGlsZW1hcFJlbmRlcmVyO1xuICAgIHByb3RlY3RlZCB1aUVsZW1lbnRSZW5kZXJlcjogVUlFbGVtZW50UmVuZGVyZXI7XG5cbiAgICBwcm90ZWN0ZWQgb3JpZ2luOiBWZWMyO1xuICAgIHByb3RlY3RlZCB6b29tOiBudW1iZXI7XG5cbiAgICBwcm90ZWN0ZWQgd29ybGRTaXplOiBWZWMyO1xuXG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpe1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgICAgIHRoaXMuZ3JhcGhpY1JlbmRlcmVyLnNldFNjZW5lKHNjZW5lKTtcbiAgICAgICAgdGhpcy50aWxlbWFwUmVuZGVyZXIuc2V0U2NlbmUoc2NlbmUpO1xuICAgICAgICB0aGlzLnVpRWxlbWVudFJlbmRlcmVyLnNldFNjZW5lKHNjZW5lKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBpbml0aWFsaXplQ2FudmFzKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHtcbiAgICAgICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICAgICAgdGhpcy53b3JsZFNpemUgPSBuZXcgVmVjMih3aWR0aCwgaGVpZ2h0KTtcblxuICAgICAgICB0aGlzLmN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICAgICAgdGhpcy5ncmFwaGljUmVuZGVyZXIgPSBuZXcgR3JhcGhpY1JlbmRlcmVyKHRoaXMuY3R4KTtcbiAgICAgICAgdGhpcy50aWxlbWFwUmVuZGVyZXIgPSBuZXcgVGlsZW1hcFJlbmRlcmVyKHRoaXMuY3R4KTtcbiAgICAgICAgdGhpcy51aUVsZW1lbnRSZW5kZXJlciA9IG5ldyBVSUVsZW1lbnRSZW5kZXJlcih0aGlzLmN0eClcblxuICAgICAgICAvLyBGb3IgY3Jpc3AgcGl4ZWwgYXJ0XG4gICAgICAgIHRoaXMuY3R4LmltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmN0eDtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICByZW5kZXIodmlzaWJsZVNldDogQ2FudmFzTm9kZVtdLCB0aWxlbWFwczogVGlsZW1hcFtdLCB1aUxheWVyczogTWFwPFVJTGF5ZXI+KTogdm9pZCB7XG4gICAgICAgIC8vIFNvcnQgYnkgZGVwdGgsIHRoZW4gYnkgdmlzaWJsZSBzZXQgYnkgeS12YWx1ZVxuICAgICAgICB2aXNpYmxlU2V0LnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgIGlmKGEuZ2V0TGF5ZXIoKS5nZXREZXB0aCgpID09PSBiLmdldExheWVyKCkuZ2V0RGVwdGgoKSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChhLmJvdW5kYXJ5LmJvdHRvbSkgLSAoYi5ib3VuZGFyeS5ib3R0b20pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS5nZXRMYXllcigpLmdldERlcHRoKCkgLSBiLmdldExheWVyKCkuZ2V0RGVwdGgoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IHRpbGVtYXBJbmRleCA9IDA7XG4gICAgICAgIGxldCB0aWxlbWFwTGVuZ3RoID0gdGlsZW1hcHMubGVuZ3RoO1xuXG4gICAgICAgIGxldCB2aXNpYmxlU2V0SW5kZXggPSAwO1xuICAgICAgICBsZXQgdmlzaWJsZVNldExlbmd0aCA9IHZpc2libGVTZXQubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlKHRpbGVtYXBJbmRleCA8IHRpbGVtYXBMZW5ndGggfHwgdmlzaWJsZVNldEluZGV4IDwgdmlzaWJsZVNldExlbmd0aCl7XG4gICAgICAgICAgICAvLyBDaGVjayBjb25kaXRpb25zIHdoZXJlIHdlJ3ZlIGFscmVhZHkgcmVhY2hlZCB0aGUgZWRnZSBvZiBvbmUgbGlzdFxuICAgICAgICAgICAgaWYodGlsZW1hcEluZGV4ID49IHRpbGVtYXBMZW5ndGgpe1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgcmVuZGVyIHRoZSByZW1haW5pbmcgdmlzaWJsZSBzZXRcbiAgICAgICAgICAgICAgICBsZXQgbm9kZSA9IHZpc2libGVTZXRbdmlzaWJsZVNldEluZGV4KytdO1xuICAgICAgICAgICAgICAgIGlmKG5vZGUudmlzaWJsZSl7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyTm9kZShub2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHZpc2libGVTZXRJbmRleCA+PSB2aXNpYmxlU2V0TGVuZ3RoKXtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbmRlciB0aWxlbWFwc1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyVGlsZW1hcCh0aWxlbWFwc1t0aWxlbWFwSW5kZXgrK10pO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZW5kZXIgd2hpY2hldmVyIGlzIGZ1cnRoZXIgZG93blxuICAgICAgICAgICAgaWYodGlsZW1hcHNbdGlsZW1hcEluZGV4XS5nZXRMYXllcigpLmdldERlcHRoKCkgPD0gdmlzaWJsZVNldFt2aXNpYmxlU2V0SW5kZXhdLmdldExheWVyKCkuZ2V0RGVwdGgoKSl7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJUaWxlbWFwKHRpbGVtYXBzW3RpbGVtYXBJbmRleCsrXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGxldCBub2RlID0gdmlzaWJsZVNldFt2aXNpYmxlU2V0SW5kZXgrK107XG4gICAgICAgICAgICAgICAgaWYobm9kZS52aXNpYmxlKXtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJOb2RlKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbmRlciB0aGUgdWlMYXllcnMgb24gdG9wIG9mIGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICBsZXQgc29ydGVkVUlMYXllcnMgPSBuZXcgQXJyYXk8VUlMYXllcj4oKTtcblxuICAgICAgICB1aUxheWVycy5mb3JFYWNoKGtleSA9PiBzb3J0ZWRVSUxheWVycy5wdXNoKHVpTGF5ZXJzLmdldChrZXkpKSk7XG5cbiAgICAgICAgc29ydGVkVUlMYXllcnMgPSBzb3J0ZWRVSUxheWVycy5zb3J0KCh1aTEsIHVpMikgPT4gdWkxLmdldERlcHRoKCkgLSB1aTIuZ2V0RGVwdGgoKSk7XG5cbiAgICAgICAgc29ydGVkVUlMYXllcnMuZm9yRWFjaCh1aUxheWVyID0+IHtcblx0XHRcdGlmKCF1aUxheWVyLmlzSGlkZGVuKCkpXG5cdFx0XHRcdHVpTGF5ZXIuZ2V0SXRlbXMoKS5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZigoPENhbnZhc05vZGU+bm9kZSkudmlzaWJsZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlck5vZGUoPENhbnZhc05vZGU+bm9kZSlcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG5cdFx0fSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIHNwZWNpZmllZCBDYW52YXNOb2RlXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIENhbnZhc05vZGUgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlbmRlck5vZGUobm9kZTogQ2FudmFzTm9kZSk6IHZvaWQge1xuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG9yaWdpbiBvZiB0aGUgdmlld3BvcnQgYWNjb3JkaW5nIHRvIHRoaXMgc3ByaXRlXG4gICAgICAgIHRoaXMub3JpZ2luID0gdGhpcy5zY2VuZS5nZXRWaWV3VHJhbnNsYXRpb24obm9kZSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB6b29tIGxldmVsIG9mIHRoZSBzY2VuZVxuICAgICAgICB0aGlzLnpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuICAgICAgICBcbiAgICAgICAgLy8gTW92ZSB0aGUgY2FudmFzIHRvIHRoZSBwb3NpdGlvbiBvZiB0aGUgbm9kZSBhbmQgcm90YXRlXG4gICAgICAgIGxldCB4U2NhbGUgPSAxO1xuICAgICAgICBsZXQgeVNjYWxlID0gMTtcbiAgICAgICAgXG4gICAgICAgIGlmKG5vZGUgaW5zdGFuY2VvZiBTcHJpdGUpe1xuICAgICAgICAgICAgeFNjYWxlID0gbm9kZS5pbnZlcnRYID8gLTEgOiAxO1xuICAgICAgICAgICAgeVNjYWxlID0gbm9kZS5pbnZlcnRZID8gLTEgOiAxO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jdHguc2V0VHJhbnNmb3JtKHhTY2FsZSwgMCwgMCwgeVNjYWxlLCAobm9kZS5wb3NpdGlvbi54IC0gdGhpcy5vcmlnaW4ueCkqdGhpcy56b29tLCAobm9kZS5wb3NpdGlvbi55IC0gdGhpcy5vcmlnaW4ueSkqdGhpcy56b29tKTtcbiAgICAgICAgdGhpcy5jdHgucm90YXRlKC1ub2RlLnJvdGF0aW9uKTtcbiAgICAgICAgbGV0IGdsb2JhbEFscGhhID0gdGhpcy5jdHguZ2xvYmFsQWxwaGE7XG4gICAgICAgIGlmKG5vZGUgaW5zdGFuY2VvZiBSZWN0KXtcbiAgICAgICAgICAgIERlYnVnLmxvZyhcIm5vZGVcIiArIG5vZGUuaWQsIFwiTm9kZVwiICsgbm9kZS5pZCArIFwiIEFscGhhOiBcIiArIG5vZGUuYWxwaGEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbm9kZS5hbHBoYTtcbiAgICAgICAgXG4gICAgICAgIGlmKG5vZGUgaW5zdGFuY2VvZiBBbmltYXRlZFNwcml0ZSl7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckFuaW1hdGVkU3ByaXRlKDxBbmltYXRlZFNwcml0ZT5ub2RlKTtcbiAgICAgICAgfSBlbHNlIGlmKG5vZGUgaW5zdGFuY2VvZiBTcHJpdGUpe1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJTcHJpdGUoPFNwcml0ZT5ub2RlKTtcbiAgICAgICAgfSBlbHNlIGlmKG5vZGUgaW5zdGFuY2VvZiBHcmFwaGljKXtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyR3JhcGhpYyg8R3JhcGhpYz5ub2RlKTtcbiAgICAgICAgfSBlbHNlIGlmKG5vZGUgaW5zdGFuY2VvZiBVSUVsZW1lbnQpe1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJVSUVsZW1lbnQoPFVJRWxlbWVudD5ub2RlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gZ2xvYmFsQWxwaGE7XG4gICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVuZGVyU3ByaXRlKHNwcml0ZTogU3ByaXRlKTogdm9pZCB7XG4gICAgICAgIC8vIEdldCB0aGUgaW1hZ2UgZnJvbSB0aGUgcmVzb3VyY2UgbWFuYWdlclxuICAgICAgICBsZXQgaW1hZ2UgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRJbWFnZShzcHJpdGUuaW1hZ2VJZCk7XG5cbiAgICAgICAgLypcbiAgICAgICAgICAgIENvb3JkaW5hdGVzIGluIHRoZSBzcGFjZSBvZiB0aGUgaW1hZ2U6XG4gICAgICAgICAgICAgICAgaW1hZ2UgY3JvcCBzdGFydCAtPiB4LCB5XG4gICAgICAgICAgICAgICAgaW1hZ2UgY3JvcCBzaXplICAtPiB3LCBoXG4gICAgICAgICAgICBDb29yZGluYXRlcyBpbiB0aGUgc3BhY2Ugb2YgdGhlIHdvcmxkXG4gICAgICAgICAgICAgICAgaW1hZ2UgZHJhdyBzdGFydCAtPiB4LCB5XG4gICAgICAgICAgICAgICAgaW1hZ2UgZHJhdyBzaXplICAtPiB3LCBoXG4gICAgICAgICovXG4gICAgICAgIHRoaXMuY3R4LmRyYXdJbWFnZShpbWFnZSxcbiAgICAgICAgICAgIHNwcml0ZS5pbWFnZU9mZnNldC54LCBzcHJpdGUuaW1hZ2VPZmZzZXQueSxcbiAgICAgICAgICAgIHNwcml0ZS5zaXplLngsIHNwcml0ZS5zaXplLnksXG4gICAgICAgICAgICAoLXNwcml0ZS5zaXplLngqc3ByaXRlLnNjYWxlLngvMikqdGhpcy56b29tLCAoLXNwcml0ZS5zaXplLnkqc3ByaXRlLnNjYWxlLnkvMikqdGhpcy56b29tLFxuICAgICAgICAgICAgc3ByaXRlLnNpemUueCAqIHNwcml0ZS5zY2FsZS54KnRoaXMuem9vbSwgc3ByaXRlLnNpemUueSAqIHNwcml0ZS5zY2FsZS55KnRoaXMuem9vbSk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHJlbmRlckFuaW1hdGVkU3ByaXRlKHNwcml0ZTogQW5pbWF0ZWRTcHJpdGUpOiB2b2lkIHtcbiAgICAgICAgLy8gR2V0IHRoZSBpbWFnZSBmcm9tIHRoZSByZXNvdXJjZSBtYW5hZ2VyXG4gICAgICAgIGxldCBpbWFnZSA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldEltYWdlKHNwcml0ZS5pbWFnZUlkKTtcblxuICAgICAgICBsZXQgYW5pbWF0aW9uSW5kZXggPSBzcHJpdGUuYW5pbWF0aW9uLmdldEluZGV4QW5kQWR2YW5jZUFuaW1hdGlvbigpO1xuXG4gICAgICAgIGxldCBhbmltYXRpb25PZmZzZXQgPSBzcHJpdGUuZ2V0QW5pbWF0aW9uT2Zmc2V0KGFuaW1hdGlvbkluZGV4KTtcblxuICAgICAgICAvKlxuICAgICAgICAgICAgQ29vcmRpbmF0ZXMgaW4gdGhlIHNwYWNlIG9mIHRoZSBpbWFnZTpcbiAgICAgICAgICAgICAgICBpbWFnZSBjcm9wIHN0YXJ0IC0+IHgsIHlcbiAgICAgICAgICAgICAgICBpbWFnZSBjcm9wIHNpemUgIC0+IHcsIGhcbiAgICAgICAgICAgIENvb3JkaW5hdGVzIGluIHRoZSBzcGFjZSBvZiB0aGUgd29ybGQgKGdpdmVuIHdlIG1vdmVkKVxuICAgICAgICAgICAgICAgIGltYWdlIGRyYXcgc3RhcnQgLT4gLXcvMiwgLWgvMlxuICAgICAgICAgICAgICAgIGltYWdlIGRyYXcgc2l6ZSAgLT4gdywgaFxuICAgICAgICAqL1xuICAgICAgICB0aGlzLmN0eC5kcmF3SW1hZ2UoaW1hZ2UsXG4gICAgICAgICAgICBzcHJpdGUuaW1hZ2VPZmZzZXQueCArIGFuaW1hdGlvbk9mZnNldC54LCBzcHJpdGUuaW1hZ2VPZmZzZXQueSArIGFuaW1hdGlvbk9mZnNldC55LFxuICAgICAgICAgICAgc3ByaXRlLnNpemUueCwgc3ByaXRlLnNpemUueSxcbiAgICAgICAgICAgICgtc3ByaXRlLnNpemUueCpzcHJpdGUuc2NhbGUueC8yKSp0aGlzLnpvb20sICgtc3ByaXRlLnNpemUueSpzcHJpdGUuc2NhbGUueS8yKSp0aGlzLnpvb20sXG4gICAgICAgICAgICBzcHJpdGUuc2l6ZS54ICogc3ByaXRlLnNjYWxlLngqdGhpcy56b29tLCBzcHJpdGUuc2l6ZS55ICogc3ByaXRlLnNjYWxlLnkqdGhpcy56b29tKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVuZGVyR3JhcGhpYyhncmFwaGljOiBHcmFwaGljKTogdm9pZCB7XG4gICAgICAgIGlmKGdyYXBoaWMgaW5zdGFuY2VvZiBQb2ludCl7XG4gICAgICAgICAgICB0aGlzLmdyYXBoaWNSZW5kZXJlci5yZW5kZXJQb2ludCg8UG9pbnQ+Z3JhcGhpYywgdGhpcy56b29tKTtcbiAgICAgICAgfSBlbHNlIGlmKGdyYXBoaWMgaW5zdGFuY2VvZiBMaW5lKXtcbiAgICAgICAgICAgIHRoaXMuZ3JhcGhpY1JlbmRlcmVyLnJlbmRlckxpbmUoPExpbmU+Z3JhcGhpYywgdGhpcy5vcmlnaW4sIHRoaXMuem9vbSk7XG4gICAgICAgIH0gZWxzZSBpZihncmFwaGljIGluc3RhbmNlb2YgUmVjdCl7XG4gICAgICAgICAgICB0aGlzLmdyYXBoaWNSZW5kZXJlci5yZW5kZXJSZWN0KDxSZWN0PmdyYXBoaWMsIHRoaXMuem9vbSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVuZGVyVGlsZW1hcCh0aWxlbWFwOiBUaWxlbWFwKTogdm9pZCB7XG4gICAgICAgIGlmKHRpbGVtYXAgaW5zdGFuY2VvZiBPcnRob2dvbmFsVGlsZW1hcCl7XG4gICAgICAgICAgICB0aGlzLnRpbGVtYXBSZW5kZXJlci5yZW5kZXJPcnRob2dvbmFsVGlsZW1hcCg8T3J0aG9nb25hbFRpbGVtYXA+dGlsZW1hcCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVuZGVyVUlFbGVtZW50KHVpRWxlbWVudDogVUlFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGlmKHVpRWxlbWVudCBpbnN0YW5jZW9mIExhYmVsKXtcbiAgICAgICAgICAgIHRoaXMudWlFbGVtZW50UmVuZGVyZXIucmVuZGVyTGFiZWwodWlFbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmKHVpRWxlbWVudCBpbnN0YW5jZW9mIEJ1dHRvbil7XG4gICAgICAgICAgICB0aGlzLnVpRWxlbWVudFJlbmRlcmVyLnJlbmRlckJ1dHRvbih1aUVsZW1lbnQpO1xuICAgICAgICB9IGVsc2UgaWYodWlFbGVtZW50IGluc3RhbmNlb2YgU2xpZGVyKXtcbiAgICAgICAgICAgIHRoaXMudWlFbGVtZW50UmVuZGVyZXIucmVuZGVyU2xpZGVyKHVpRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSBpZih1aUVsZW1lbnQgaW5zdGFuY2VvZiBUZXh0SW5wdXQpe1xuICAgICAgICAgICAgdGhpcy51aUVsZW1lbnRSZW5kZXJlci5yZW5kZXJUZXh0SW5wdXQodWlFbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNsZWFyKGNsZWFyQ29sb3I6IENvbG9yKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLndvcmxkU2l6ZS54LCB0aGlzLndvcmxkU2l6ZS55KTtcbiAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gY2xlYXJDb2xvci50b1N0cmluZygpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUmVjdCgwLCAwLCB0aGlzLndvcmxkU2l6ZS54LCB0aGlzLndvcmxkU2l6ZS55KTtcbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgTGluZSBmcm9tIFwiLi4vLi4vTm9kZXMvR3JhcGhpY3MvTGluZVwiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9Qb2ludFwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vLi4vU2NlbmUvU2NlbmVcIjtcblxuLyoqXG4gKiBBIHV0aWxpdHkgY2xhc3MgdG8gaGVscCB0aGUgQHJlZmVyZW5jZVtDYW52YXNSZW5kZXJlcl0gcmVuZGVyIEByZWZlcmVuY2VbR3JhcGhpY11zXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdyYXBoaWNSZW5kZXJlciB7XG4gICAgLyoqIFRoZSByZXNvdXJjZSBtYW5hZ2VyIG9mIHRoZSBnYW1lIGVuZ2luZSAqL1xuICAgIHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcbiAgICAvKiogVGhlIGN1cnJlbnQgc2NlbmUgKi9cbiAgICBwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuICAgIC8qKiBUaGUgcmVuZGVyaW5nIGNvbnRleHQgKi9cbiAgICBwcm90ZWN0ZWQgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG5cbiAgICBjb25zdHJ1Y3RvcihjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCl7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuY3R4ID0gY3R4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIG9mIHRoaXMgR3JhcGhpY1JlbmRlcmVyXG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBjdXJyZW50IHNjZW5lXG4gICAgICovXG4gICAgc2V0U2NlbmUoc2NlbmU6IFNjZW5lKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgcG9pbnRcbiAgICAgKiBAcGFyYW0gcG9pbnQgVGhlIHBvaW50IHRvIHJlbmRlclxuICAgICAqIEBwYXJhbSB6b29tIFRoZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgcmVuZGVyUG9pbnQocG9pbnQ6IFBvaW50LCB6b29tOiBudW1iZXIpOiB2b2lkIHtcblx0XHR0aGlzLmN0eC5maWxsU3R5bGUgPSBwb2ludC5jb2xvci50b1N0cmluZ1JHQkEoKTtcbiAgICAgICAgdGhpcy5jdHguZmlsbFJlY3QoKC1wb2ludC5zaXplLngvMikqem9vbSwgKC1wb2ludC5zaXplLnkvMikqem9vbSxcbiAgICAgICAgcG9pbnQuc2l6ZS54Knpvb20sIHBvaW50LnNpemUueSp6b29tKTtcbiAgICB9XG5cbiAgICByZW5kZXJMaW5lKGxpbmU6IExpbmUsIG9yaWdpbjogVmVjMiwgem9vbTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gbGluZS5jb2xvci50b1N0cmluZ1JHQkEoKTtcbiAgICAgICAgdGhpcy5jdHgubGluZVdpZHRoID0gbGluZS50aGlja25lc3M7XG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5tb3ZlVG8oMCwgMCk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVUbygobGluZS5lbmQueCAtIGxpbmUuc3RhcnQueCkqem9vbSwgKGxpbmUuZW5kLnkgLSBsaW5lLnN0YXJ0LnkpKnpvb20pO1xuICAgICAgICB0aGlzLmN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIHJlY3RcbiAgICAgKiBAcGFyYW0gcmVjdCBUaGUgcmVjdCB0byByZW5kZXJcbiAgICAgKiBAcGFyYW0gem9vbSBUaGUgem9vbSBsZXZlbFxuICAgICAqL1xuICAgIHJlbmRlclJlY3QocmVjdDogUmVjdCwgem9vbTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIC8vIERyYXcgdGhlIGludGVyaW9yIG9mIHRoZSByZWN0XG4gICAgICAgIGlmKHJlY3QuY29sb3IuYSAhPT0gMCl7XG4gICAgICAgICAgICB0aGlzLmN0eC5maWxsU3R5bGUgPSByZWN0LmNvbG9yLnRvU3RyaW5nUkdCKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5maWxsUmVjdCgoLXJlY3Quc2l6ZS54LzIpKnpvb20sICgtcmVjdC5zaXplLnkvMikqem9vbSwgcmVjdC5zaXplLngqem9vbSwgcmVjdC5zaXplLnkqem9vbSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEcmF3IHRoZSBib3JkZXIgb2YgdGhlIHJlY3QgaWYgaXQgaXNuJ3QgdHJhbnNwYXJlbnRcbiAgICAgICAgaWYocmVjdC5ib3JkZXJDb2xvci5hICE9PSAwKXtcbiAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gcmVjdC5nZXRCb3JkZXJDb2xvcigpLnRvU3RyaW5nUkdCKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5saW5lV2lkdGggPSByZWN0LmdldEJvcmRlcldpZHRoKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VSZWN0KCgtcmVjdC5zaXplLngvMikqem9vbSwgKC1yZWN0LnNpemUueS8yKSp6b29tLCByZWN0LnNpemUueCp6b29tLCByZWN0LnNpemUueSp6b29tKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBUaWxlc2V0IGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZXNldFwiO1xuXG4vKipcbiAqIEEgdXRpbGl0eSBjbGFzcyBmb3IgdGhlIEByZWZlcmVuY2VbQ2FudmFzUmVuZGVyZXJdIHRvIHJlbmRlciBAcmVmZXJlbmNlW1RpbGVtYXBdc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUaWxlbWFwUmVuZGVyZXIge1xuICAgIHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuICAgIHByb3RlY3RlZCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblxuICAgIGNvbnN0cnVjdG9yKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKXtcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5jdHggPSBjdHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2NlbmUgb2YgdGhpcyBUaWxlbWFwUmVuZGVyZXJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGN1cnJlbnQgc2NlbmVcbiAgICAgKi9cbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYW4gb3J0aG9nb25hbCB0aWxlbWFwXG4gICAgICogQHBhcmFtIHRpbGVtYXAgVGhlIHRpbGVtYXAgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyT3J0aG9nb25hbFRpbGVtYXAodGlsZW1hcDogT3J0aG9nb25hbFRpbGVtYXApOiB2b2lkIHtcbiAgICAgICAgbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSB0aWxlbWFwLmdldExheWVyKCkuZ2V0QWxwaGEoKTtcbiAgICAgICAgXG4gICAgICAgIGxldCBvcmlnaW4gPSB0aGlzLnNjZW5lLmdldFZpZXdUcmFuc2xhdGlvbih0aWxlbWFwKTtcbiAgICAgICAgbGV0IHNpemUgPSB0aGlzLnNjZW5lLmdldFZpZXdwb3J0KCkuZ2V0SGFsZlNpemUoKTtcbiAgICAgICAgbGV0IHpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuICAgICAgICBsZXQgYm90dG9tUmlnaHQgPSBvcmlnaW4uY2xvbmUoKS5hZGQoc2l6ZS5zY2FsZWQoMip6b29tKSk7XG5cbiAgICAgICAgaWYodGlsZW1hcC52aXNpYmxlKXtcbiAgICAgICAgICAgIGxldCBtaW5Db2xSb3cgPSB0aWxlbWFwLmdldENvbFJvd0F0KG9yaWdpbik7XG4gICAgICAgICAgICBsZXQgbWF4Q29sUm93ID0gdGlsZW1hcC5nZXRDb2xSb3dBdChib3R0b21SaWdodCk7XG5cbiAgICAgICAgICAgIGZvcihsZXQgeCA9IG1pbkNvbFJvdy54OyB4IDw9IG1heENvbFJvdy54OyB4Kyspe1xuICAgICAgICAgICAgICAgIGZvcihsZXQgeSA9IG1pbkNvbFJvdy55OyB5IDw9IG1heENvbFJvdy55OyB5Kyspe1xuICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHRpbGUgYXQgdGhpcyBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBsZXQgdGlsZSA9IHRpbGVtYXAuZ2V0VGlsZUF0Um93Q29sKG5ldyBWZWMyKHgsIHkpKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IHRoZSByb3QvZmxpcCBwYXJhbWV0ZXJzIGlmIHRoZXJlIGFyZSBhbnlcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFzayA9ICgweEUgPDwgMjgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByb3RGbGlwID0gKChtYXNrICYgdGlsZSkgPj4gMjgpICYgMHhGO1xuICAgICAgICAgICAgICAgICAgICB0aWxlID0gdGlsZSAmIH5tYXNrO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpbmQgdGhlIHRpbGVzZXQgdGhhdCBvd25zIHRoaXMgdGlsZSBpbmRleCBhbmQgcmVuZGVyXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgdGlsZXNldCBvZiB0aWxlbWFwLmdldFRpbGVzZXRzKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGlsZXNldC5oYXNUaWxlKHRpbGUpKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclRpbGUodGlsZXNldCwgdGlsZSwgeCwgeSwgb3JpZ2luLCB0aWxlbWFwLnNjYWxlLCB6b29tLCByb3RGbGlwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gcHJldmlvdXNBbHBoYTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgdGlsZVxuICAgICAqIEBwYXJhbSB0aWxlc2V0IFRoZSB0aWxlc2V0IHRoaXMgdGlsZSBiZWxvbmdzIHRvIFxuICAgICAqIEBwYXJhbSB0aWxlSW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlXG4gICAgICogQHBhcmFtIHRpbGVtYXBSb3cgVGhlIHJvdyBvZiB0aGUgdGlsZSBpbiB0aGUgdGlsZW1hcFxuICAgICAqIEBwYXJhbSB0aWxlbWFwQ29sIFRoZSBjb2x1bW4gb2YgdGhlIHRpbGUgaW4gdGhlIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gb3JpZ2luIFRoZSBvcmlnaW4gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHNjYWxlIFRoZSBzY2FsZSBvZiB0aGUgdGlsZW1hcFxuICAgICAqIEBwYXJhbSB6b29tIFRoZSB6b29tIGxldmVsIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZW5kZXJUaWxlKHRpbGVzZXQ6IFRpbGVzZXQsIHRpbGVJbmRleDogbnVtYmVyLCB0aWxlbWFwUm93OiBudW1iZXIsIHRpbGVtYXBDb2w6IG51bWJlciwgb3JpZ2luOiBWZWMyLCBzY2FsZTogVmVjMiwgem9vbTogbnVtYmVyLCByb3RGbGlwOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGltYWdlID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0SW1hZ2UodGlsZXNldC5nZXRJbWFnZUtleSgpKTtcblxuICAgICAgICAvLyBHZXQgdGhlIHRydWUgaW5kZXhcbiAgICAgICAgbGV0IGluZGV4ID0gdGlsZUluZGV4IC0gdGlsZXNldC5nZXRTdGFydEluZGV4KCk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSByb3cgYW5kIGNvbCBvZiB0aGUgdGlsZSBpbiBpbWFnZSBzcGFjZVxuICAgICAgICBsZXQgcm93ID0gTWF0aC5mbG9vcihpbmRleCAvIHRpbGVzZXQuZ2V0TnVtQ29scygpKTtcbiAgICAgICAgbGV0IGNvbCA9IGluZGV4ICUgdGlsZXNldC5nZXROdW1Db2xzKCk7XG4gICAgICAgIGxldCB3aWR0aCA9IHRpbGVzZXQuZ2V0VGlsZVNpemUoKS54O1xuICAgICAgICBsZXQgaGVpZ2h0ID0gdGlsZXNldC5nZXRUaWxlU2l6ZSgpLnk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBwb3NpdGlvbiB0byBzdGFydCBhIGNyb3AgaW4gdGhlIHRpbGVzZXQgaW1hZ2VcbiAgICAgICAgbGV0IGxlZnQgPSBjb2wgKiB3aWR0aDtcbiAgICAgICAgbGV0IHRvcCA9IHJvdyAqIGhlaWdodDtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHBvc2l0aW9uIGluIHRoZSB3b3JsZCB0byByZW5kZXIgdGhlIHRpbGVcbiAgICAgICAgbGV0IHggPSBNYXRoLmZsb29yKHRpbGVtYXBSb3cgKiB3aWR0aCAqIHNjYWxlLngpO1xuICAgICAgICBsZXQgeSA9IE1hdGguZmxvb3IodGlsZW1hcENvbCAqIGhlaWdodCAqIHNjYWxlLnkpO1xuXG4gICAgICAgIGxldCB3b3JsZFggPSBNYXRoLmZsb29yKCh4IC0gb3JpZ2luLngpKnpvb20pO1xuICAgICAgICBsZXQgd29ybGRZID0gTWF0aC5mbG9vcigoeSAtIG9yaWdpbi55KSp6b29tKTtcbiAgICAgICAgbGV0IHdvcmxkV2lkdGggPSBNYXRoLmNlaWwod2lkdGggKiBzY2FsZS54ICogem9vbSk7XG4gICAgICAgIGxldCB3b3JsZEhlaWdodCA9IE1hdGguY2VpbChoZWlnaHQgKiBzY2FsZS55ICogem9vbSk7XG5cbiAgICAgICAgaWYocm90RmxpcCAhPT0gMCl7XG4gICAgICAgICAgICBsZXQgc2NhbGVYID0gMTtcbiAgICAgICAgICAgIGxldCBzY2FsZVkgPSAxO1xuICAgICAgICAgICAgbGV0IHNoZWFyWCA9IDA7XG4gICAgICAgICAgICBsZXQgc2hlYXJZID0gMDtcblxuICAgICAgICAgICAgLy8gRmxpcCBvbiB0aGUgeC1heGlzXG4gICAgICAgICAgICBpZihyb3RGbGlwICYgOCl7XG4gICAgICAgICAgICAgICAgc2NhbGVYID0gLTE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZsaXAgb24gdGhlIHktYXhpc1xuICAgICAgICAgICAgaWYocm90RmxpcCAmIDQpe1xuICAgICAgICAgICAgICAgIHNjYWxlWSA9IC0xO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGbGlwIG92ZXIgdGhlIGxpbmUgeT14XG4gICAgICAgICAgICBpZihyb3RGbGlwICYgMil7XG4gICAgICAgICAgICAgICAgc2hlYXJYID0gc2NhbGVZO1xuICAgICAgICAgICAgICAgIHNoZWFyWSA9IHNjYWxlWDtcbiAgICAgICAgICAgICAgICBzY2FsZVggPSAwO1xuICAgICAgICAgICAgICAgIHNjYWxlWSA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybShzY2FsZVgsIHNoZWFyWCwgc2hlYXJZLCBzY2FsZVksIHdvcmxkWCArIHdvcmxkV2lkdGgvMiwgd29ybGRZICsgd29ybGRIZWlnaHQvMik7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gUmVuZGVyIHRoZSB0aWxlXG4gICAgICAgICAgICB0aGlzLmN0eC5kcmF3SW1hZ2UoaW1hZ2UsXG4gICAgICAgICAgICAgICAgbGVmdCwgdG9wLFxuICAgICAgICAgICAgICAgIHdpZHRoLCBoZWlnaHQsXG4gICAgICAgICAgICAgICAgLXdvcmxkV2lkdGgvMiwgLXdvcmxkSGVpZ2h0LzIsXG4gICAgICAgICAgICAgICAgd29ybGRXaWR0aCwgd29ybGRIZWlnaHQpO1xuXG4gICAgICAgICAgICBpZihyb3RGbGlwICE9PSAwKXtcbiAgICAgICAgICAgICAgICB0aGlzLmN0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBObyByb3RhdGlvbnMsIGRvbid0IGRvIHRoZSBjYWxjdWxhdGlvbnMsIGp1c3QgcmVuZGVyIHRoZSB0aWxlXG4gICAgICAgICAgICAvLyBSZW5kZXIgdGhlIHRpbGVcbiAgICAgICAgICAgIHRoaXMuY3R4LmRyYXdJbWFnZShpbWFnZSxcbiAgICAgICAgICAgICAgICBsZWZ0LCB0b3AsXG4gICAgICAgICAgICAgICAgd2lkdGgsIGhlaWdodCxcbiAgICAgICAgICAgICAgICB3b3JsZFgsIHdvcmxkWSxcbiAgICAgICAgICAgICAgICB3b3JsZFdpZHRoLCB3b3JsZEhlaWdodCk7XG4gICAgICAgIH1cblxuXG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEJ1dHRvbiBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9CdXR0b25cIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IFNsaWRlciBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9TbGlkZXJcIjtcbmltcG9ydCBUZXh0SW5wdXQgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvVGV4dElucHV0XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi9VdGlscy9NYXRoVXRpbHNcIjtcblxuLyoqXG4gKiBBIHV0aWxpdHkgY2xhc3MgdG8gaGVscCB0aGUgQHJlZmVyZW5jZVtDYW52YXNSZW5kZXJlcl0gcmVuZGVyIEByZWZlcmVuY2VbVUlFbGVtZW50XXNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVUlFbGVtZW50UmVuZGVyZXIge1xuICAgIHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuICAgIHByb3RlY3RlZCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblxuICAgIGNvbnN0cnVjdG9yKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKSB7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuY3R4ID0gY3R4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIG9mIHRoaXMgVUlFbGVtZW50UmVuZGVyZXJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGN1cnJlbnQgc2NlbmVcbiAgICAgKi9cbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBsYWJlbFxuICAgICAqIEBwYXJhbSBsYWJlbCBUaGUgbGFiZWwgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyTGFiZWwobGFiZWw6IExhYmVsKTogdm9pZCB7XG4gICAgICAgIC8vIC8vIElmIHRoZSBzaXplIGlzIHVuYXNzaWduZWQgKGJ5IHRoZSB1c2VyIG9yIGF1dG9tYXRpY2FsbHkpIGFzc2lnbiBpdFxuICAgICAgICAvLyBsYWJlbC5oYW5kbGVJbml0aWFsU2l6aW5nKHRoaXMuY3R4KTtcblxuICAgICAgICAvLyAvLyBHcmFiIHRoZSBnbG9iYWwgYWxwaGEgc28gd2UgY2FuIGFkanVzdCBpdCBmb3IgdGhpcyByZW5kZXJcbiAgICAgICAgLy8gbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcblxuICAgICAgICAvLyAvLyBHZXQgdGhlIGZvbnQgYW5kIHRleHQgcG9zaXRpb24gaW4gbGFiZWxcbiAgICAgICAgLy8gdGhpcy5jdHguZm9udCA9IGxhYmVsLmdldEZvbnRTdHJpbmcoKTtcbiAgICAgICAgLy8gbGV0IG9mZnNldCA9IGxhYmVsLmNhbGN1bGF0ZVRleHRPZmZzZXQodGhpcy5jdHgpO1xuXG4gICAgICAgIC8vIC8vIFN0cm9rZSBhbmQgZmlsbCBhIHJvdW5kZWQgcmVjdCBhbmQgZ2l2ZSBpdCB0ZXh0XG4gICAgICAgIC8vIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwuYmFja2dyb3VuZENvbG9yLmE7XG4gICAgICAgIC8vIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGxhYmVsLmNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICAvLyB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoLWxhYmVsLnNpemUueC8yLCAtbGFiZWwuc2l6ZS55LzIsXG4gICAgICAgIC8vIFx0bGFiZWwuc2l6ZS54LCBsYWJlbC5zaXplLnksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgLy8gdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVCb3JkZXJDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICAvLyB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLmJvcmRlckNvbG9yLmE7XG4gICAgICAgIC8vIHRoaXMuY3R4LmxpbmVXaWR0aCA9IGxhYmVsLmJvcmRlcldpZHRoO1xuICAgICAgICAvLyB0aGlzLmN0eC5zdHJva2VSb3VuZGVkUmVjdCgtbGFiZWwuc2l6ZS54LzIsIC1sYWJlbC5zaXplLnkvMixcbiAgICAgICAgLy8gXHRsYWJlbC5zaXplLngsIGxhYmVsLnNpemUueSwgbGFiZWwuYm9yZGVyUmFkaXVzKTtcblxuICAgICAgICAvLyB0aGlzLmN0eC5maWxsU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVUZXh0Q29sb3IoKTtcbiAgICAgICAgLy8gdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBsYWJlbC50ZXh0Q29sb3IuYTtcbiAgICAgICAgLy8gdGhpcy5jdHguZmlsbFRleHQobGFiZWwudGV4dCwgb2Zmc2V0LnggLSBsYWJlbC5zaXplLngvMiwgb2Zmc2V0LnkgLSBsYWJlbC5zaXplLnkvMik7XG5cbiAgICAgICAgLy8gdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBwcmV2aW91c0FscGhhO1xuICAgICAgICAvLyBJZiB0aGUgc2l6ZSBpcyB1bmFzc2lnbmVkIChieSB0aGUgdXNlciBvciBhdXRvbWF0aWNhbGx5KSBhc3NpZ24gaXRcbiAgICAgICAgbGV0IGxpbmVzID0gbGFiZWwudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgIGxldCB0ZW1wVGV4dCA9IGxhYmVsLnRleHQ7XG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBsZXQgbWF4ID0gMDtcbiAgICAgICAgICAgIGxldCBtYXhMZW5ndGhJbmRleCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxpbmVzW2ldLmxlbmd0aCA+IG1heCkge1xuICAgICAgICAgICAgICAgICAgICBtYXggPSBsaW5lc1tpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIG1heExlbmd0aEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYWJlbC50ZXh0ID0gbGluZXNbbWF4TGVuZ3RoSW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIGxhYmVsLmhhbmRsZUluaXRpYWxTaXppbmcodGhpcy5jdHgpO1xuICAgICAgICAvLyBHcmFiIHRoZSBnbG9iYWwgYWxwaGEgc28gd2UgY2FuIGFkanVzdCBpdCBmb3IgdGhpcyByZW5kZXJcbiAgICAgICAgbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcblxuICAgICAgICAvLyBHZXQgdGhlIGZvbnQgYW5kIHRleHQgcG9zaXRpb24gaW4gbGFiZWxcbiAgICAgICAgdGhpcy5jdHguZm9udCA9IGxhYmVsLmdldEZvbnRTdHJpbmcoKTtcbiAgICAgICAgbGV0IG9mZnNldCA9IGxhYmVsLmNhbGN1bGF0ZVRleHRPZmZzZXQodGhpcy5jdHgpO1xuXG4gICAgICAgIC8vIFN0cm9rZSBhbmQgZmlsbCBhIHJvdW5kZWQgcmVjdCBhbmQgZ2l2ZSBpdCB0ZXh0XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwuYmFja2dyb3VuZENvbG9yLmE7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGxhYmVsLmNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoLWxhYmVsLnNpemUueCAvIDIsIC1sYWJlbC5zaXplLnkgLyAyLFxuICAgICAgICAgICAgbGFiZWwuc2l6ZS54LCBsYWJlbC5zaXplLnksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVCb3JkZXJDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLmJvcmRlckNvbG9yLmE7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVXaWR0aCA9IGxhYmVsLmJvcmRlcldpZHRoO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2VSb3VuZGVkUmVjdCgtbGFiZWwuc2l6ZS54IC8gMiwgLWxhYmVsLnNpemUueSAvIDIsXG4gICAgICAgICAgICBsYWJlbC5zaXplLngsIGxhYmVsLnNpemUueSArICgobGluZXMubGVuZ3RoIC0gMSkgKiBsYWJlbC5mb250U2l6ZSksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gbGFiZWwuY2FsY3VsYXRlVGV4dENvbG9yKCk7XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwudGV4dENvbG9yLmE7XG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxUZXh0KGxhYmVsLnRleHQsIG9mZnNldC54IC0gbGFiZWwuc2l6ZS54IC8gMiwgKG9mZnNldC55IC0gbGFiZWwuc2l6ZS55IC8gMikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBhZGRpdGlvbmFsWSA9IGkgKiAobGFiZWwuc2l6ZS55IC8gMiArIChsYWJlbC5mb250U2l6ZSA9PT0gNDAgPyAyMCA6IDEwKSk7XG4gICAgICAgICAgICAgICAgbGFiZWwudGV4dCA9IGxpbmVzW2ldO1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGxhYmVsLmNhbGN1bGF0ZVRleHRPZmZzZXQodGhpcy5jdHgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxUZXh0KGxpbmVzW2ldLCAob2Zmc2V0LnggLSBsYWJlbC5zaXplLnggLyAyKSwgKG9mZnNldC55IC0gbGFiZWwuc2l6ZS55IC8gMiArIGFkZGl0aW9uYWxZKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBwcmV2aW91c0FscGhhO1xuICAgICAgICBsYWJlbC50ZXh0ID0gdGVtcFRleHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIGJ1dHRvblxuICAgICAqIEBwYXJhbSBidXR0b24gVGhlIGJ1dHRvbiB0byByZW5kZXJcbiAgICAgKi9cbiAgICByZW5kZXJCdXR0b24oYnV0dG9uOiBCdXR0b24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZW5kZXJMYWJlbChidXR0b24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBzbGlkZXJcbiAgICAgKiBAcGFyYW0gc2xpZGVyIFRoZSBzbGlkZXIgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyU2xpZGVyKHNsaWRlcjogU2xpZGVyKTogdm9pZCB7XG4gICAgICAgIC8vIEdyYWIgdGhlIGdsb2JhbCBhbHBoYSBzbyB3ZSBjYW4gYWRqdXN0IGl0IGZvciB0aGlzIHJlbmRlclxuICAgICAgICBsZXQgcHJldmlvdXNBbHBoYSA9IHRoaXMuY3R4Lmdsb2JhbEFscGhhO1xuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IHNsaWRlci5nZXRMYXllcigpLmdldEFscGhhKCk7XG5cbiAgICAgICAgLy8gQ2FsY3VhbGF0ZSB0aGUgc2xpZGVyIHNpemVcbiAgICAgICAgbGV0IHNsaWRlclNpemUgPSBuZXcgVmVjMihzbGlkZXIuc2l6ZS54LCAyKTtcblxuICAgICAgICAvLyBEcmF3IHRoZSBzbGlkZXJcbiAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gc2xpZGVyLnNsaWRlckNvbG9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxSb3VuZGVkUmVjdCgtc2xpZGVyU2l6ZS54IC8gMiwgLXNsaWRlclNpemUueSAvIDIsXG4gICAgICAgICAgICBzbGlkZXJTaXplLngsIHNsaWRlclNpemUueSwgc2xpZGVyLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuaWIgc2l6ZSBhbmQgcG9zaXRpb25cbiAgICAgICAgbGV0IHggPSBNYXRoVXRpbHMubGVycCgtc2xpZGVyLnNpemUueCAvIDIsIHNsaWRlci5zaXplLnggLyAyLCBzbGlkZXIuZ2V0VmFsdWUoKSk7XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgbmliXG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHNsaWRlci5uaWJDb2xvci50b1N0cmluZygpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoeCAtIHNsaWRlci5uaWJTaXplLnggLyAyLCAtc2xpZGVyLm5pYlNpemUueSAvIDIsXG4gICAgICAgICAgICBzbGlkZXIubmliU2l6ZS54LCBzbGlkZXIubmliU2l6ZS55LCBzbGlkZXIuYm9yZGVyUmFkaXVzKTtcblxuICAgICAgICAvLyBSZXNldCB0aGUgYWxwaGFcbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBwcmV2aW91c0FscGhhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSB0ZXh0SW5wdXRcbiAgICAgKiBAcGFyYW0gdGV4dElucHV0IFRoZSB0ZXh0SW5wdXQgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyVGV4dElucHV0KHRleHRJbnB1dDogVGV4dElucHV0KTogdm9pZCB7XG4gICAgICAgIC8vIFNob3cgYSBjdXJzb3Igc29tZXRpbWVzXG4gICAgICAgIGlmICh0ZXh0SW5wdXQuZm9jdXNlZCAmJiB0ZXh0SW5wdXQuY3Vyc29yQ291bnRlciAlIDYwID4gMzApIHtcbiAgICAgICAgICAgIHRleHRJbnB1dC50ZXh0ICs9IFwifFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZW5kZXJMYWJlbCh0ZXh0SW5wdXQpO1xuXG4gICAgICAgIGlmICh0ZXh0SW5wdXQuZm9jdXNlZCkge1xuICAgICAgICAgICAgaWYgKHRleHRJbnB1dC5jdXJzb3JDb3VudGVyICUgNjAgPiAzMCkge1xuICAgICAgICAgICAgICAgIHRleHRJbnB1dC50ZXh0ID0gdGV4dElucHV0LnRleHQuc3Vic3RyaW5nKDAsIHRleHRJbnB1dC50ZXh0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0ZXh0SW5wdXQuY3Vyc29yQ291bnRlciArPSAxO1xuICAgICAgICAgICAgaWYgKHRleHRJbnB1dC5jdXJzb3JDb3VudGVyID49IDYwKSB7XG4gICAgICAgICAgICAgICAgdGV4dElucHV0LmN1cnNvckNvdW50ZXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IFVJRWxlbWVudCBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcblxuLyoqXG4gKiBBbiBhYnN0cmFjdCBmcmFtZXdvcmsgdG8gcHV0IGFsbCByZW5kZXJpbmcgaW4gb25jZSBwbGFjZSBpbiB0aGUgYXBwbGljYXRpb25cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUmVuZGVyaW5nTWFuYWdlciB7XG4gICAgLyoqIFRoZSBSZXNvdXJjZU1hbmFnZXIgKi9cbiAgICBwcm90ZWN0ZWQgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvKiogVGhlIHNjZW5lIGN1cnJlbnRseSBiZWluZyByZW5kZXJlZCAqL1xuICAgIHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIGN1cnJlbnRseSBiZWluZyByZW5kZXJlZFxuICAgICAqIEBwYXJhbSBzY2VuZSBUaGUgY3VycmVudCBTY2VuZVxuICAgICAqL1xuICAgIHNldFNjZW5lKHNjZW5lOiBTY2VuZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgY2FudmFzIGZvciB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSBjYW52YXMgVGhlIGNhbnZhcyBlbGVtZW50XG4gICAgICogQHBhcmFtIHdpZHRoIFRoZSBkZXNpcmVkIHdpZHRoIG9mIHRoZSBjYW52YXNcbiAgICAgKiBAcGFyYW0gaGVpZ2h0IFRoZSBkZXNpcmVkIGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgICogQHJldHVybnMgVGhlIHJlbmRlcmluZyBjb250ZXh0IG9mIHRoZSBjYW52YXNcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBpbml0aWFsaXplQ2FudmFzKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogYW55O1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgdmlzaWJsZSBzZXQgb2YgQ2FudmFzTm9kZXMgYW5kIHZpc2libGUgcG9ydGlvbnMgb2YgdGlsZW1hcHMsIGFzIHdlbGwgYXMgYW55IFVJRWxlbWVudCBpbiBVSUxheWVyc1xuICAgICAqIEBwYXJhbSB2aXNpYmxlU2V0IFRoZSB2aXNpYmxlIHNldCBvZiBDYW52YXNOb2Rlc1xuICAgICAqIEBwYXJhbSB0aWxlbWFwcyBUaGUgdGlsZW1hcHMgdXNlZCBpbiB0aGUgYXBwbGljYXRpb25cbiAgICAgKiBAcGFyYW0gdWlMYXllcnMgVGhlIHVzZXIgaW50ZXJmYWNlIGxheWVyc1xuICAgICAqL1xuICAgIGFic3RyYWN0IHJlbmRlcih2aXNpYmxlU2V0OiBBcnJheTxDYW52YXNOb2RlPiwgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+LCB1aUxheWVyczogTWFwPFVJTGF5ZXI+KTogdm9pZDtcblxuICAgIC8qKiBDbGVhcnMgdGhlIGNhbnZhcyAqL1xuICAgIGFic3RyYWN0IGNsZWFyKGNvbG9yOiBDb2xvcik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgc3ByaXRlXG4gICAgICogQHBhcmFtIHNwcml0ZSBUaGUgc3ByaXRlIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCByZW5kZXJTcHJpdGUoc3ByaXRlOiBTcHJpdGUpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhbiBhbmltYXRlZCBzcHJpdGVcbiAgICAgKiBAcGFyYW0gc3ByaXRlIFRoZSBhbmltYXRlZCBzcHJpdGUgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlckFuaW1hdGVkU3ByaXRlKHNwcml0ZTogQW5pbWF0ZWRTcHJpdGUpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIGdyYXBoaWNcbiAgICAgKiBAcGFyYW0gZ3JhcGhpYyBUaGUgZ3JhcGhpYyB0byByZW5kZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVuZGVyR3JhcGhpYyhncmFwaGljOiBHcmFwaGljKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSB0aWxlbWFwXG4gICAgICogQHBhcmFtIHRpbGVtYXAgVGhlIHRpbGVtYXAgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQ7XG5cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBVSUVsZW1lbnRcbiAgICAgKiBAcGFyYW0gdWlFbGVtZW50IFRoZSBVSUVsZW1lbnQgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlclVJRWxlbWVudCh1aUVsZW1lbnQ6IFVJRWxlbWVudCk6IHZvaWQ7XG59IiwiaW1wb3J0IEdyYXBoIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgR3JhcGhpYyBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY1wiO1xuaW1wb3J0IHsgR3JhcGhpY1R5cGUgfSBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvR3JhcGhpY1R5cGVzXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgU2hhZGVyUmVnaXN0cnkgZnJvbSBcIi4uL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvU2hhZGVyUmVnaXN0cnlcIjtcbmltcG9ydCBSZWdpc3RyeU1hbmFnZXIgZnJvbSBcIi4uL1JlZ2lzdHJ5L1JlZ2lzdHJ5TWFuYWdlclwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9QYXJhbGxheExheWVyXCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBSZW5kZXJpbmdVdGlscyBmcm9tIFwiLi4vVXRpbHMvUmVuZGVyaW5nVXRpbHNcIjtcbmltcG9ydCBSZW5kZXJpbmdNYW5hZ2VyIGZyb20gXCIuL1JlbmRlcmluZ01hbmFnZXJcIjtcbmltcG9ydCBTaGFkZXJUeXBlIGZyb20gXCIuL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViR0xSZW5kZXJlciBleHRlbmRzIFJlbmRlcmluZ01hbmFnZXIge1xuXG5cdHByb3RlY3RlZCBvcmlnaW46IFZlYzI7XG5cdHByb3RlY3RlZCB6b29tOiBudW1iZXI7XG5cdHByb3RlY3RlZCB3b3JsZFNpemU6IFZlYzI7XG5cblx0cHJvdGVjdGVkIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cdHByb3RlY3RlZCB0ZXh0Q3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG5cblx0aW5pdGlhbGl6ZUNhbnZhcyhjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCB7XG5cdFx0Y2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cblx0XHR0aGlzLndvcmxkU2l6ZSA9IFZlYzIuWkVSTztcblx0XHR0aGlzLndvcmxkU2l6ZS54ID0gd2lkdGg7XG5cdFx0dGhpcy53b3JsZFNpemUueSA9IGhlaWdodDtcblxuXHRcdC8vIEdldCB0aGUgV2ViR0wgY29udGV4dFxuICAgICAgICB0aGlzLmdsID0gY2FudmFzLmdldENvbnRleHQoXCJ3ZWJnbFwiKTtcblxuXHRcdHRoaXMuZ2wudmlld3BvcnQoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuXHRcdHRoaXMuZ2wuZGlzYWJsZSh0aGlzLmdsLkRFUFRIX1RFU1QpO1xuICAgICAgICB0aGlzLmdsLmVuYWJsZSh0aGlzLmdsLkJMRU5EKTtcbiAgICAgICAgdGhpcy5nbC5ibGVuZEZ1bmModGhpcy5nbC5TUkNfQUxQSEEsIHRoaXMuZ2wuT05FX01JTlVTX1NSQ19BTFBIQSk7XG4gICAgICAgIHRoaXMuZ2wuZW5hYmxlKHRoaXMuZ2wuQ1VMTF9GQUNFKTtcblxuXHRcdC8vIFRlbGwgdGhlIHJlc291cmNlIG1hbmFnZXIgd2UncmUgdXNpbmcgV2ViR0xcblx0XHRSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS51c2VXZWJHTCh0cnVlLCB0aGlzLmdsKTtcblxuXHRcdC8vIFNob3cgdGhlIHRleHQgY2FudmFzIGFuZCBnZXQgaXRzIGNvbnRleHRcblx0XHRsZXQgdGV4dENhbnZhcyA9IDxIVE1MQ2FudmFzRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInRleHQtY2FudmFzXCIpO1xuXHRcdHRleHRDYW52YXMuaGlkZGVuID0gZmFsc2U7XG5cdFx0dGhpcy50ZXh0Q3R4ID0gdGV4dENhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cblx0XHQvLyBTaXplIHRoZSB0ZXh0IGNhbnZhcyB0byBiZSB0aGUgc2FtZSBhcyB0aGUgZ2FtZSBjYW52YXNcblx0XHR0ZXh0Q2FudmFzLmhlaWdodCA9IGhlaWdodDtcblx0XHR0ZXh0Q2FudmFzLndpZHRoID0gd2lkdGg7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2w7XG5cdH1cblxuXHRyZW5kZXIodmlzaWJsZVNldDogQ2FudmFzTm9kZVtdLCB0aWxlbWFwczogVGlsZW1hcFtdLCB1aUxheWVyczogTWFwPFVJTGF5ZXI+KTogdm9pZCB7XG5cdFx0Zm9yKGxldCBub2RlIG9mIHZpc2libGVTZXQpe1xuXHRcdFx0dGhpcy5yZW5kZXJOb2RlKG5vZGUpO1xuXHRcdH1cblxuXHRcdHVpTGF5ZXJzLmZvckVhY2goa2V5ID0+IHtcblx0XHRcdGlmKCF1aUxheWVycy5nZXQoa2V5KS5pc0hpZGRlbigpKVxuXHRcdFx0XHR1aUxheWVycy5nZXQoa2V5KS5nZXRJdGVtcygpLmZvckVhY2gobm9kZSA9PiB0aGlzLnJlbmRlck5vZGUoPENhbnZhc05vZGU+bm9kZSkpXG5cdFx0fSk7XG5cdH1cblxuXHRjbGVhcihjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHR0aGlzLmdsLmNsZWFyQ29sb3IoY29sb3IuciwgY29sb3IuZywgY29sb3IuYiwgY29sb3IuYSk7XG5cdFx0dGhpcy5nbC5jbGVhcih0aGlzLmdsLkNPTE9SX0JVRkZFUl9CSVQgfCB0aGlzLmdsLkRFUFRIX0JVRkZFUl9CSVQpO1xuXG5cdFx0dGhpcy50ZXh0Q3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLndvcmxkU2l6ZS54LCB0aGlzLndvcmxkU2l6ZS55KTtcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJOb2RlKG5vZGU6IENhbnZhc05vZGUpOiB2b2lkIHtcblx0XHQvLyBDYWxjdWxhdGUgdGhlIG9yaWdpbiBvZiB0aGUgdmlld3BvcnQgYWNjb3JkaW5nIHRvIHRoaXMgc3ByaXRlXG4gICAgICAgIHRoaXMub3JpZ2luID0gdGhpcy5zY2VuZS5nZXRWaWV3VHJhbnNsYXRpb24obm9kZSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB6b29tIGxldmVsIG9mIHRoZSBzY2VuZVxuICAgICAgICB0aGlzLnpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuXHRcdFxuXHRcdGlmKG5vZGUuaGFzQ3VzdG9tU2hhZGVyKXtcblx0XHRcdC8vIElmIHRoZSBub2RlIGhhcyBhIGN1c3RvbSBzaGFkZXIsIHJlbmRlciB1c2luZyB0aGF0XG5cdFx0XHR0aGlzLnJlbmRlckN1c3RvbShub2RlKTtcblx0XHR9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIEdyYXBoaWMpe1xuXHRcdFx0dGhpcy5yZW5kZXJHcmFwaGljKG5vZGUpO1xuXHRcdH0gZWxzZSBpZihub2RlIGluc3RhbmNlb2YgU3ByaXRlKXtcblx0XHRcdGlmKG5vZGUgaW5zdGFuY2VvZiBBbmltYXRlZFNwcml0ZSl7XG5cdFx0XHRcdHRoaXMucmVuZGVyQW5pbWF0ZWRTcHJpdGUobm9kZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbmRlclNwcml0ZShub2RlKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIFVJRWxlbWVudCl7XG5cdFx0XHR0aGlzLnJlbmRlclVJRWxlbWVudChub2RlKTtcblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyU3ByaXRlKHNwcml0ZTogU3ByaXRlKTogdm9pZCB7XG5cdFx0bGV0IHNoYWRlciA9IFJlZ2lzdHJ5TWFuYWdlci5zaGFkZXJzLmdldChTaGFkZXJSZWdpc3RyeS5TUFJJVEVfU0hBREVSKTtcblx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyhzcHJpdGUpLCBzcHJpdGUpO1xuXHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyQW5pbWF0ZWRTcHJpdGUoc3ByaXRlOiBBbmltYXRlZFNwcml0ZSk6IHZvaWQge1xuXHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQoU2hhZGVyUmVnaXN0cnkuU1BSSVRFX1NIQURFUik7XG5cdFx0bGV0IG9wdGlvbnMgPSB0aGlzLmFkZE9wdGlvbnMoc2hhZGVyLmdldE9wdGlvbnMoc3ByaXRlKSwgc3ByaXRlKTtcblx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHR9XG5cblx0cHJvdGVjdGVkIHJlbmRlckdyYXBoaWMoZ3JhcGhpYzogR3JhcGhpYyk6IHZvaWQge1xuXG5cdFx0aWYoZ3JhcGhpYyBpbnN0YW5jZW9mIFBvaW50KXtcblx0XHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQoU2hhZGVyUmVnaXN0cnkuUE9JTlRfU0hBREVSKTtcblx0XHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKGdyYXBoaWMpLCBncmFwaGljKTtcblx0XHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cdFx0fSBlbHNlIGlmKGdyYXBoaWMgaW5zdGFuY2VvZiBSZWN0KSB7XG5cdFx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KFNoYWRlclJlZ2lzdHJ5LlJFQ1RfU0hBREVSKTtcblx0XHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKGdyYXBoaWMpLCBncmFwaGljKTtcblx0XHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cdFx0fSBcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJNZXRob2Qgbm90IGltcGxlbWVudGVkLlwiKTtcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJVSUVsZW1lbnQodWlFbGVtZW50OiBVSUVsZW1lbnQpOiB2b2lkIHtcblx0XHRpZih1aUVsZW1lbnQgaW5zdGFuY2VvZiBMYWJlbCl7XG5cdFx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KFNoYWRlclJlZ2lzdHJ5LkxBQkVMX1NIQURFUik7XG5cdFx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyh1aUVsZW1lbnQpLCB1aUVsZW1lbnQpO1xuXHRcdFx0c2hhZGVyLnJlbmRlcih0aGlzLmdsLCBvcHRpb25zKTtcblxuXHRcdFx0dGhpcy50ZXh0Q3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAodWlFbGVtZW50LnBvc2l0aW9uLnggLSB0aGlzLm9yaWdpbi54KSp0aGlzLnpvb20sICh1aUVsZW1lbnQucG9zaXRpb24ueSAtIHRoaXMub3JpZ2luLnkpKnRoaXMuem9vbSk7XG5cdFx0XHR0aGlzLnRleHRDdHgucm90YXRlKC11aUVsZW1lbnQucm90YXRpb24pO1xuXHRcdFx0bGV0IGdsb2JhbEFscGhhID0gdGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhO1xuXHRcdFx0dGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhID0gdWlFbGVtZW50LmFscGhhO1xuXG5cdFx0XHQvLyBSZW5kZXIgdGV4dFxuXHRcdFx0dGhpcy50ZXh0Q3R4LmZvbnQgPSB1aUVsZW1lbnQuZ2V0Rm9udFN0cmluZygpO1xuXHRcdFx0bGV0IG9mZnNldCA9IHVpRWxlbWVudC5jYWxjdWxhdGVUZXh0T2Zmc2V0KHRoaXMudGV4dEN0eCk7XG5cdFx0XHR0aGlzLnRleHRDdHguZmlsbFN0eWxlID0gdWlFbGVtZW50LmNhbGN1bGF0ZVRleHRDb2xvcigpO1xuXHRcdFx0dGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhID0gdWlFbGVtZW50LnRleHRDb2xvci5hO1xuXHRcdFx0dGhpcy50ZXh0Q3R4LmZpbGxUZXh0KHVpRWxlbWVudC50ZXh0LCBvZmZzZXQueCAtIHVpRWxlbWVudC5zaXplLngvMiwgb2Zmc2V0LnkgLSB1aUVsZW1lbnQuc2l6ZS55LzIpO1xuXG5cdFx0XHR0aGlzLnRleHRDdHguZ2xvYmFsQWxwaGEgPSBnbG9iYWxBbHBoYTtcbiAgICAgICAgXHR0aGlzLnRleHRDdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApO1xuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJDdXN0b20obm9kZTogQ2FudmFzTm9kZSk6IHZvaWQge1xuXHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQobm9kZS5jdXN0b21TaGFkZXJLZXkpO1xuXHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKG5vZGUpLCBub2RlKTtcblx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHR9XG5cblx0cHJvdGVjdGVkIGFkZE9wdGlvbnMob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Piwgbm9kZTogQ2FudmFzTm9kZSk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdC8vIEdpdmUgdGhlIHNoYWRlciBhY2Nlc3MgdG8gdGhlIHdvcmxkIHNpemVcblx0XHRvcHRpb25zLndvcmxkU2l6ZSA9IHRoaXMud29ybGRTaXplO1xuXG5cdFx0Ly8gQWRqdXN0IHRoZSBvcmlnaW4gcG9zaXRpb24gdG8gdGhlIHBhcmFsbGF4XG5cdFx0bGV0IGxheWVyID0gbm9kZS5nZXRMYXllcigpO1xuXHRcdGxldCBwYXJhbGxheCA9IG5ldyBWZWMyKDEsIDEpO1xuXHRcdGlmKGxheWVyIGluc3RhbmNlb2YgUGFyYWxsYXhMYXllcil7XG5cdFx0XHRwYXJhbGxheCA9ICg8UGFyYWxsYXhMYXllcj5sYXllcikucGFyYWxsYXg7XG5cdFx0fVxuXG5cdFx0b3B0aW9ucy5vcmlnaW4gPSB0aGlzLm9yaWdpbi5jbG9uZSgpLm11bHQocGFyYWxsYXgpO1xuXG5cdFx0cmV0dXJuIG9wdGlvbnM7XG5cdH1cblxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi8uLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5cbi8qKlxuICogQSB3cmFwcGVyIGNsYXNzIGZvciBXZWJHTCBzaGFkZXJzLlxuICogVGhpcyBjbGFzcyBpcyBhIHNpbmdsZXRvbiwgYW5kIHRoZXJlIGlzIG9ubHkgb25lIGZvciBlYWNoIHNoYWRlciB0eXBlLlxuICogQWxsIG9iamVjdHMgdGhhdCB1c2UgdGhpcyBzaGFkZXIgdHlwZSB3aWxsIHJlZmVyIHRvIGFuZCBtb2RpZnkgdGhpcyBzYW1lIHR5cGUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFNoYWRlclR5cGUge1xuXHQvKiogVGhlIG5hbWUgb2YgdGhpcyBzaGFkZXIgKi9cblx0cHJvdGVjdGVkIG5hbWU6IHN0cmluZztcblxuXHQvKiogVGhlIGtleSB0byB0aGUgV2ViR0xQcm9ncmFtIGluIHRoZSBSZXNvdXJjZU1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHByb2dyYW1LZXk6IHN0cmluZztcblxuXHQvKiogQSByZWZlcmVuY2UgdG8gdGhlIHJlc291cmNlIG1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG5cdGNvbnN0cnVjdG9yKHByb2dyYW1LZXk6IHN0cmluZyl7XG5cdFx0dGhpcy5wcm9ncmFtS2V5ID0gcHJvZ3JhbUtleTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRpYWxpemVzIGFueSBidWZmZXIgb2JqZWN0cyBhc3NvY2lhdGVkIHdpdGggdGhpcyBzaGFkZXIgdHlwZS5cblx0ICogQHBhcmFtIGdsIFRoZSBXZWJHTCByZW5kZXJpbmcgY29udGV4dFxuXHQgKi9cblx0YWJzdHJhY3QgaW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBMb2FkcyBhbnkgdW5pZm9ybXNcblx0ICogQHBhcmFtIGdsIFRoZSBXZWJHTCByZW5kZXJpbmcgY29udGV4dFxuXHQgKiBAcGFyYW0gb3B0aW9ucyBJbmZvcm1hdGlvbiBhYm91dCB0aGUgb2JqZWN0IHdlJ3JlIGN1cnJlbnRseSByZW5kZXJpbmdcblx0ICovXG5cdGFic3RyYWN0IHJlbmRlcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZDtcblxuXHQvKipcblx0ICogRXh0cmFjdHMgdGhlIG9wdGlvbnMgZnJvbSB0aGUgQ2FudmFzTm9kZSBhbmQgZ2l2ZXMgdGhlbSB0byB0aGUgcmVuZGVyIGZ1bmN0aW9uXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIGdldCBvcHRpb25zIGZyb21cblx0ICogQHJldHVybnMgQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG9wdGlvbnMgdGhhdCBzaG91bGQgYmUgcGFzc2VkIHRvIHRoZSByZW5kZXIgZnVuY3Rpb25cblx0ICovXG5cdGdldE9wdGlvbnMobm9kZTogQ2FudmFzTm9kZSk6IFJlY29yZDxzdHJpbmcsIGFueT4ge3JldHVybiB7fTt9XG59IiwiaW1wb3J0IE1hdDR4NCBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL01hdDR4NFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uLy4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUXVhZFNoYWRlclR5cGUgZnJvbSBcIi4vUXVhZFNoYWRlclR5cGVcIjtcblxuLyoqICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMYWJlbFNoYWRlclR5cGUgZXh0ZW5kcyBRdWFkU2hhZGVyVHlwZSB7XG5cblx0Y29uc3RydWN0b3IocHJvZ3JhbUtleTogc3RyaW5nKXtcblx0XHRzdXBlcihwcm9ncmFtS2V5KTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHR9XG5cblx0aW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkIHtcblx0XHR0aGlzLmJ1ZmZlck9iamVjdEtleSA9IFwibGFiZWxcIjtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5jcmVhdGVCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXHR9XG5cblx0cmVuZGVyKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRjb25zdCBiYWNrZ3JvdW5kQ29sb3IgPSBvcHRpb25zLmJhY2tncm91bmRDb2xvci50b1dlYkdMKCk7XG5cdFx0Y29uc3QgYm9yZGVyQ29sb3IgPSBvcHRpb25zLmJvcmRlckNvbG9yLnRvV2ViR0woKTtcblxuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gdGhpcy5nZXRWZXJ0aWNlcyhvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG5cdFx0Y29uc3QgRlNJWkUgPSB2ZXJ0ZXhEYXRhLkJZVEVTX1BFUl9FTEVNRU5UO1xuXG5cdFx0Ly8gQmluZCB0aGUgYnVmZmVyXG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG5cdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHZlcnRleERhdGEsIGdsLlNUQVRJQ19EUkFXKTtcblxuXHRcdC8vIEF0dHJpYnV0ZXNcblx0XHRjb25zdCBhX1Bvc2l0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1Bvc2l0aW9uXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9Qb3NpdGlvbiwgMiwgZ2wuRkxPQVQsIGZhbHNlLCAyICogRlNJWkUsIDAgKiBGU0laRSk7XG5cdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYV9Qb3NpdGlvbik7XG5cblx0XHQvLyBVbmlmb3Jtc1xuXHRcdGNvbnN0IHVfQmFja2dyb3VuZENvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9CYWNrZ3JvdW5kQ29sb3JcIik7XG5cdFx0Z2wudW5pZm9ybTRmdih1X0JhY2tncm91bmRDb2xvciwgYmFja2dyb3VuZENvbG9yKTtcblxuICAgICAgICBjb25zdCB1X0JvcmRlckNvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Cb3JkZXJDb2xvclwiKTtcblx0XHRnbC51bmlmb3JtNGZ2KHVfQm9yZGVyQ29sb3IsIGJvcmRlckNvbG9yKTtcblxuICAgICAgICBjb25zdCB1X01heFNpemUgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X01heFNpemVcIik7XG4gICAgICAgIGdsLnVuaWZvcm0yZih1X01heFNpemUsIC12ZXJ0ZXhEYXRhWzBdLCB2ZXJ0ZXhEYXRhWzFdKTtcblxuXHRcdC8vIEdldCB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHQvLyBXZSB3YW50IGEgc3F1YXJlIGZvciBvdXIgcmVuZGVyaW5nIHNwYWNlLCBzbyBnZXQgdGhlIG1heGltdW0gZGltZW5zaW9uIG9mIG91ciBxdWFkXG5cdFx0bGV0IG1heERpbWVuc2lvbiA9IE1hdGgubWF4KG9wdGlvbnMuc2l6ZS54LCBvcHRpb25zLnNpemUueSk7XG5cbiAgICAgICAgY29uc3QgdV9Cb3JkZXJXaWR0aCA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQm9yZGVyV2lkdGhcIik7XG5cdFx0Z2wudW5pZm9ybTFmKHVfQm9yZGVyV2lkdGgsIG9wdGlvbnMuYm9yZGVyV2lkdGgvbWF4RGltZW5zaW9uKTtcblxuICAgICAgICBjb25zdCB1X0JvcmRlclJhZGl1cyA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQm9yZGVyUmFkaXVzXCIpO1xuXHRcdGdsLnVuaWZvcm0xZih1X0JvcmRlclJhZGl1cywgb3B0aW9ucy5ib3JkZXJSYWRpdXMvbWF4RGltZW5zaW9uKTtcblxuXHRcdC8vIFRoZSBzaXplIG9mIHRoZSByZW5kZXJpbmcgc3BhY2Ugd2lsbCBiZSBhIHNxdWFyZSB3aXRoIHRoaXMgbWF4aW11bSBkaW1lbnNpb25cblx0XHRsZXQgc2l6ZSA9IG5ldyBWZWMyKG1heERpbWVuc2lvbiwgbWF4RGltZW5zaW9uKS5zY2FsZSgyL29wdGlvbnMud29ybGRTaXplLngsIDIvb3B0aW9ucy53b3JsZFNpemUueSk7XG5cblx0XHQvLyBDZW50ZXIgb3VyIHRyYW5zbGF0aW9ucyBhcm91bmQgKDAsIDApXG5cdFx0Y29uc3QgdHJhbnNsYXRlWCA9IChvcHRpb25zLnBvc2l0aW9uLnggLSBvcHRpb25zLm9yaWdpbi54IC0gb3B0aW9ucy53b3JsZFNpemUueC8yKS9tYXhEaW1lbnNpb247XG5cdFx0Y29uc3QgdHJhbnNsYXRlWSA9IC0ob3B0aW9ucy5wb3NpdGlvbi55IC0gb3B0aW9ucy5vcmlnaW4ueSAtIG9wdGlvbnMud29ybGRTaXplLnkvMikvbWF4RGltZW5zaW9uO1xuXG5cdFx0Ly8gQ3JlYXRlIG91ciB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHR0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShuZXcgRmxvYXQzMkFycmF5KFt0cmFuc2xhdGVYLCB0cmFuc2xhdGVZXSkpO1xuXHRcdHRoaXMuc2NhbGUuc2NhbGUoc2l6ZSk7XG5cdFx0dGhpcy5yb3RhdGlvbi5yb3RhdGUob3B0aW9ucy5yb3RhdGlvbik7XG5cdFx0bGV0IHRyYW5zZm9ybWF0aW9uID0gTWF0NHg0Lk1VTFQodGhpcy50cmFuc2xhdGlvbiwgdGhpcy5zY2FsZSwgdGhpcy5yb3RhdGlvbik7XG5cblx0XHQvLyBQYXNzIHRoZSB0cmFuc2xhdGlvbiBtYXRyaXggdG8gb3VyIHNoYWRlclxuXHRcdGNvbnN0IHVfVHJhbnNmb3JtID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9UcmFuc2Zvcm1cIik7XG5cdFx0Z2wudW5pZm9ybU1hdHJpeDRmdih1X1RyYW5zZm9ybSwgZmFsc2UsIHRyYW5zZm9ybWF0aW9uLnRvQXJyYXkoKSk7XG5cblx0XHQvLyBEcmF3IHRoZSBxdWFkXG5cdFx0Z2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHJlbmRlcmluZyBzcGFjZSBhbHdheXMgaGFzIHRvIGJlIGEgc3F1YXJlLCBzbyBtYWtlIHN1cmUgaXRzIHNxdWFyZSB3LnIudCB0byB0aGUgbGFyZ2VzdCBkaW1lbnNpb25cblx0ICogQHBhcmFtIHcgVGhlIHdpZHRoIG9mIHRoZSBxdWFkIGluIHBpeGVsc1xuXHQgKiBAcGFyYW0gaCBUaGUgaGVpZ2h0IG9mIHRoZSBxdWFkIGluIHBpeGVsc1xuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB0aGUgdmVydGljZXMgb2YgdGhlIHF1YWRcblx0ICovXG5cdGdldFZlcnRpY2VzKHc6IG51bWJlciwgaDogbnVtYmVyKTogRmxvYXQzMkFycmF5IHtcblx0XHRsZXQgeCwgeTtcblxuXHRcdGlmKGggPiB3KXtcblx0XHRcdHkgPSAwLjU7XG5cdFx0XHR4ID0gdy8oMipoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0eCA9IDAuNTtcblx0XHRcdHkgPSBoLygyKncpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdC14LCAgeSxcblx0XHRcdC14LCAteSxcblx0XHRcdCB4LCAgeSxcblx0XHRcdCB4LCAteVxuXHRcdF0pO1xuXHR9XG5cblx0Z2V0T3B0aW9ucyhyZWN0OiBMYWJlbCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHJlY3QucG9zaXRpb24sXG5cdFx0XHRiYWNrZ3JvdW5kQ29sb3I6IHJlY3QuY2FsY3VsYXRlQmFja2dyb3VuZENvbG9yKCksXG4gICAgICAgICAgICBib3JkZXJDb2xvcjogcmVjdC5jYWxjdWxhdGVCb3JkZXJDb2xvcigpLFxuICAgICAgICAgICAgYm9yZGVyV2lkdGg6IHJlY3QuYm9yZGVyV2lkdGgsXG4gICAgICAgICAgICBib3JkZXJSYWRpdXM6IHJlY3QuYm9yZGVyUmFkaXVzLFxuXHRcdFx0c2l6ZTogcmVjdC5zaXplLFxuXHRcdFx0cm90YXRpb246IHJlY3Qucm90YXRpb25cblx0XHR9XG5cblx0XHRyZXR1cm4gb3B0aW9ucztcblx0fVxufSIsImltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvR3JhcGhpY3MvUG9pbnRcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBSZW5kZXJpbmdVdGlscyBmcm9tIFwiLi4vLi4vLi4vVXRpbHMvUmVuZGVyaW5nVXRpbHNcIjtcbmltcG9ydCBTaGFkZXJUeXBlIGZyb20gXCIuLi9TaGFkZXJUeXBlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvaW50U2hhZGVyVHlwZSBleHRlbmRzIFNoYWRlclR5cGUge1xuXG5cdHByb3RlY3RlZCBidWZmZXJPYmplY3RLZXk6IHN0cmluZztcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXHR9XG5cblx0aW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkIHtcblx0XHR0aGlzLmJ1ZmZlck9iamVjdEtleSA9IFwicG9pbnRcIjtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5jcmVhdGVCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXHR9XG5cblx0cmVuZGVyKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRsZXQgcG9zaXRpb24gPSBSZW5kZXJpbmdVdGlscy50b1dlYkdMQ29vcmRzKG9wdGlvbnMucG9zaXRpb24sIG9wdGlvbnMub3JpZ2luLCBvcHRpb25zLndvcmxkU2l6ZSk7XG5cdFx0bGV0IGNvbG9yID0gUmVuZGVyaW5nVXRpbHMudG9XZWJHTENvbG9yKG9wdGlvbnMuY29sb3IpO1xuXG5cdFx0Y29uc3QgcHJvZ3JhbSA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldFNoYWRlclByb2dyYW0odGhpcy5wcm9ncmFtS2V5KTtcblx0XHRjb25zdCBidWZmZXIgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXG5cdFx0Z2wudXNlUHJvZ3JhbShwcm9ncmFtKTtcblxuXHRcdGNvbnN0IHZlcnRleERhdGEgPSBwb3NpdGlvbjtcblxuXHRcdGNvbnN0IEZTSVpFID0gdmVydGV4RGF0YS5CWVRFU19QRVJfRUxFTUVOVDtcblxuXHRcdC8vIEJpbmQgdGhlIGJ1ZmZlclxuXHRcdGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBidWZmZXIpO1xuXHRcdGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCB2ZXJ0ZXhEYXRhLCBnbC5TVEFUSUNfRFJBVyk7XG5cblx0XHQvLyBBdHRyaWJ1dGVzXG5cdFx0Y29uc3QgYV9Qb3NpdGlvbiA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIFwiYV9Qb3NpdGlvblwiKTtcblx0XHRnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGFfUG9zaXRpb24sIDIsIGdsLkZMT0FULCBmYWxzZSwgMiAqIEZTSVpFLCAwICogRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfUG9zaXRpb24pO1xuXG5cdFx0Ly8gVW5pZm9ybXNcblx0XHRjb25zdCB1X0NvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Db2xvclwiKTtcblx0XHRnbC51bmlmb3JtNGZ2KHVfQ29sb3IsIGNvbG9yKTtcblxuXHRcdGNvbnN0IHVfUG9pbnRTaXplID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Qb2ludFNpemVcIik7XG5cdFx0Z2wudW5pZm9ybTFmKHVfUG9pbnRTaXplLCBvcHRpb25zLnBvaW50U2l6ZSk7XG5cblx0XHRnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgMCwgMSk7XG5cdH1cblxuXHRnZXRPcHRpb25zKHBvaW50OiBQb2ludCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHBvaW50LnBvc2l0aW9uLFxuXHRcdFx0Y29sb3I6IHBvaW50LmNvbG9yLFxuXHRcdFx0cG9pbnRTaXplOiBwb2ludC5zaXplLFxuXHRcdH1cblxuXHRcdHJldHVybiBvcHRpb25zO1xuXHR9XG59IiwiaW1wb3J0IE1hdDR4NCBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL01hdDR4NFwiO1xuaW1wb3J0IFNoYWRlclR5cGUgZnJvbSBcIi4uL1NoYWRlclR5cGVcIjtcblxuLyoqIFJlcHJlc2VudHMgYW55IFdlYkdMIG9iamVjdHMgdGhhdCBoYXZlIGEgcXVhZCBtZXNoIChpLmUuIGEgcmVjdGFuZ3VsYXIgZ2FtZSBvYmplY3QgY29tcG9zZWQgb2Ygb25seSB0d28gdHJpYW5nbGVzKSAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUXVhZFNoYWRlclR5cGUgZXh0ZW5kcyBTaGFkZXJUeXBlIHtcblx0LyoqIFRoZSBrZXkgdG8gdGhlIGJ1ZmZlciBvYmplY3QgZm9yIHRoaXMgc2hhZGVyICovXG5cdHByb3RlY3RlZCBidWZmZXJPYmplY3RLZXk6IHN0cmluZztcblxuXHQvKiogVGhlIHNjYWxlIG1hdHJpYyAqL1xuXHRwcm90ZWN0ZWQgc2NhbGU6IE1hdDR4NDtcblxuXHQvKiogVGhlIHJvdGF0aW9uIG1hdHJpeCAqL1xuXHRwcm90ZWN0ZWQgcm90YXRpb246IE1hdDR4NDtcblxuXHQvKiogVGhlIHRyYW5zbGF0aW9uIG1hdHJpeCAqL1xuXHRwcm90ZWN0ZWQgdHJhbnNsYXRpb246IE1hdDR4NDtcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXG5cdFx0dGhpcy5zY2FsZSA9IE1hdDR4NC5JREVOVElUWTtcblx0XHR0aGlzLnJvdGF0aW9uID0gTWF0NHg0LklERU5USVRZO1xuXHRcdHRoaXMudHJhbnNsYXRpb24gPSBNYXQ0eDQuSURFTlRJVFk7XG5cdH1cbn0iLCJpbXBvcnQgTWF0NHg0IGZyb20gXCIuLi8uLi8uLi9EYXRhVHlwZXMvTWF0NHg0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi8uLi9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUXVhZFNoYWRlclR5cGUgZnJvbSBcIi4vUXVhZFNoYWRlclR5cGVcIjtcblxuLyoqICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWN0U2hhZGVyVHlwZSBleHRlbmRzIFF1YWRTaGFkZXJUeXBlIHtcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdH1cblxuXHRpbml0QnVmZmVyT2JqZWN0KCk6IHZvaWQge1xuXHRcdHRoaXMuYnVmZmVyT2JqZWN0S2V5ID0gXCJyZWN0XCI7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIuY3JlYXRlQnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblx0fVxuXG5cdHJlbmRlcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0Y29uc3QgY29sb3IgPSBvcHRpb25zLmNvbG9yLnRvV2ViR0woKTtcblxuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gdGhpcy5nZXRWZXJ0aWNlcyhvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG5cdFx0Y29uc3QgRlNJWkUgPSB2ZXJ0ZXhEYXRhLkJZVEVTX1BFUl9FTEVNRU5UO1xuXG5cdFx0Ly8gQmluZCB0aGUgYnVmZmVyXG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG5cdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHZlcnRleERhdGEsIGdsLlNUQVRJQ19EUkFXKTtcblxuXHRcdC8vIEF0dHJpYnV0ZXNcblx0XHRjb25zdCBhX1Bvc2l0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1Bvc2l0aW9uXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9Qb3NpdGlvbiwgMiwgZ2wuRkxPQVQsIGZhbHNlLCAyICogRlNJWkUsIDAgKiBGU0laRSk7XG5cdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYV9Qb3NpdGlvbik7XG5cblx0XHQvLyBVbmlmb3Jtc1xuXHRcdGNvbnN0IHVfQ29sb3IgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X0NvbG9yXCIpO1xuXHRcdGdsLnVuaWZvcm00ZnYodV9Db2xvciwgY29sb3IpO1xuXG5cdFx0Ly8gR2V0IHRyYW5zZm9ybWF0aW9uIG1hdHJpeFxuXHRcdC8vIFdlIHdhbnQgYSBzcXVhcmUgZm9yIG91ciByZW5kZXJpbmcgc3BhY2UsIHNvIGdldCB0aGUgbWF4aW11bSBkaW1lbnNpb24gb2Ygb3VyIHF1YWRcblx0XHRsZXQgbWF4RGltZW5zaW9uID0gTWF0aC5tYXgob3B0aW9ucy5zaXplLngsIG9wdGlvbnMuc2l6ZS55KTtcblxuXHRcdC8vIFRoZSBzaXplIG9mIHRoZSByZW5kZXJpbmcgc3BhY2Ugd2lsbCBiZSBhIHNxdWFyZSB3aXRoIHRoaXMgbWF4aW11bSBkaW1lbnNpb25cblx0XHRsZXQgc2l6ZSA9IG5ldyBWZWMyKG1heERpbWVuc2lvbiwgbWF4RGltZW5zaW9uKS5zY2FsZSgyL29wdGlvbnMud29ybGRTaXplLngsIDIvb3B0aW9ucy53b3JsZFNpemUueSk7XG5cblx0XHQvLyBDZW50ZXIgb3VyIHRyYW5zbGF0aW9ucyBhcm91bmQgKDAsIDApXG5cdFx0Y29uc3QgdHJhbnNsYXRlWCA9IChvcHRpb25zLnBvc2l0aW9uLnggLSBvcHRpb25zLm9yaWdpbi54IC0gb3B0aW9ucy53b3JsZFNpemUueC8yKS9tYXhEaW1lbnNpb247XG5cdFx0Y29uc3QgdHJhbnNsYXRlWSA9IC0ob3B0aW9ucy5wb3NpdGlvbi55IC0gb3B0aW9ucy5vcmlnaW4ueSAtIG9wdGlvbnMud29ybGRTaXplLnkvMikvbWF4RGltZW5zaW9uO1xuXG5cdFx0Ly8gQ3JlYXRlIG91ciB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHR0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShuZXcgRmxvYXQzMkFycmF5KFt0cmFuc2xhdGVYLCB0cmFuc2xhdGVZXSkpO1xuXHRcdHRoaXMuc2NhbGUuc2NhbGUoc2l6ZSk7XG5cdFx0dGhpcy5yb3RhdGlvbi5yb3RhdGUob3B0aW9ucy5yb3RhdGlvbik7XG5cdFx0bGV0IHRyYW5zZm9ybWF0aW9uID0gTWF0NHg0Lk1VTFQodGhpcy50cmFuc2xhdGlvbiwgdGhpcy5zY2FsZSwgdGhpcy5yb3RhdGlvbik7XG5cblx0XHQvLyBQYXNzIHRoZSB0cmFuc2xhdGlvbiBtYXRyaXggdG8gb3VyIHNoYWRlclxuXHRcdGNvbnN0IHVfVHJhbnNmb3JtID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9UcmFuc2Zvcm1cIik7XG5cdFx0Z2wudW5pZm9ybU1hdHJpeDRmdih1X1RyYW5zZm9ybSwgZmFsc2UsIHRyYW5zZm9ybWF0aW9uLnRvQXJyYXkoKSk7XG5cblx0XHQvLyBEcmF3IHRoZSBxdWFkXG5cdFx0Z2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cdH1cblxuXG5cdC8qXG5cdFx0U28gYXMgaXQgdHVybnMgb3V0LCBXZWJHTCBoYXMgYW4gaXNzdWUgd2l0aCBub24tc3F1YXJlIHF1YWRzLlxuXHRcdEl0IGRvZXNuJ3QgbGlrZSB3aGVuIHlvdSBkb24ndCBoYXZlIGEgMS0xIHNjYWxlLCBhbmQgcm90YXRpb25zIGFyZSBlbnRpcmVseSBtZXNzZWQgdXAgaWYgdGhpcyBpcyBub3QgdGhlIGNhc2UuXG5cdFx0VG8gc29sdmUgdGhpcywgSSB1c2VkIHRoZSBzY2FsZSBvZiB0aGUgTEFSR0VTVCBkaW1lbnNpb24gb2YgdGhlIHF1YWQgdG8gbWFrZSBhIHNxdWFyZSwgdGhlbiBhZGp1c3RlZCB0aGUgdmVydGV4IGNvb3JkaW5hdGVzIGluc2lkZSBvZiB0aGF0LlxuXHRcdEEgZGlhZ3JhbSBvZiB0aGUgc29sdXRpb24gZm9sbG93cy5cblxuXHRcdFRoZXJlIGlzIGEgYm91bmRpbmcgc3F1YXJlIGZvciB0aGUgcXVhZCB3aXRoIGRpbWVuc2lvbnMgaHhoIChpbiB0aGlzIGNhc2UsIHNpbmNlIGhlaWdodCBpcyB0aGUgbGFyZ2VzdCBkaW1lbnNpb24pLlxuXHRcdFRoZSBvZmZzZXQgaW4gdGhlIHZlcnRpY2FsIGRpcmVjdGlvbiBpcyB0aGVyZWZvcmUgMC41LCBhcyBpdCBpcyBub3JtYWxseS5cblx0XHRIb3dldmVyLCB0aGUgb2Zmc2V0IGluIHRoZSBob3Jpem9udGFsIGRpcmVjdGlvbiBpcyBub3Qgc28gc3RyYWlnaHRmb3J3YXJkLCBidXQgaXNuJ3QgY29uY2VwdHVhbGx5IGhhcmQuXG5cdFx0QWxsIHdlIHJlYWxseSBoYXZlIHRvIGRvIGlzIGEgcmFuZ2UgY2hhbmdlIGZyb20gWzAsIGhlaWdodC8yXSB0byBbMCwgMC41XSwgd2hlcmUgb3VyIHZhbHVlIGlzIHQgPSB3aWR0aC8yLCBhbmQgMCA8PSB0IDw9IGhlaWdodC8yLlxuXG5cdFx0U28gbm93IHdlIGhhdmUgb3VyIHJlY3QsIGluIGEgc3BhY2Ugc2NhbGVkIHdpdGggcmVzcGVjdCB0byB0aGUgbGFyZ2VzdCBkaW1lbnNpb24uXG5cdFx0Um90YXRpb25zIHdvcmsgYXMgeW91IHdvdWxkIGV4cGVjdCwgZXZlbiBmb3IgbG9uZyByZWN0YW5nbGVzLlxuXG5cdFx0XHRcdFx0MC41XG5cdFx0XHRfXyBfXyBfXyBfXyBfXyBfXyBfX1xuXHRcdFx0fFx0fDg4ODg4ODg4ODg4fFx0fFxuXHRcdFx0fFx0fDg4ODg4ODg4ODg4fFx0fFxuXHRcdFx0fFx0fDg4ODg4ODg4ODg4fFx0fFxuXHRcdC0wLjV8XyBffDg4ODg4ODg4ODg4fF8gX3wwLjVcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0ICBcdFx0fF9fX3w4ODg4ODg4ODg4OHxfX198XG5cdFx0XHQgIFx0XHQtMC41XG5cblx0XHRUaGUgZ2V0VmVydGljZXMgZnVuY3Rpb24gYmVsb3cgZG9lcyBhcyBkZXNjcmliZWQsIGFuZCBjb252ZXJ0cyB0aGUgcmFuZ2Vcblx0Ki9cblx0LyoqXG5cdCAqIFRoZSByZW5kZXJpbmcgc3BhY2UgYWx3YXlzIGhhcyB0byBiZSBhIHNxdWFyZSwgc28gbWFrZSBzdXJlIGl0cyBzcXVhcmUgdy5yLnQgdG8gdGhlIGxhcmdlc3QgZGltZW5zaW9uXG5cdCAqIEBwYXJhbSB3IFRoZSB3aWR0aCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHBhcmFtIGggVGhlIGhlaWdodCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2YgdGhlIHZlcnRpY2VzIG9mIHRoZSBxdWFkXG5cdCAqL1xuXHRnZXRWZXJ0aWNlcyh3OiBudW1iZXIsIGg6IG51bWJlcik6IEZsb2F0MzJBcnJheSB7XG5cdFx0bGV0IHgsIHk7XG5cblx0XHRpZihoID4gdyl7XG5cdFx0XHR5ID0gMC41O1xuXHRcdFx0eCA9IHcvKDIqaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHggPSAwLjU7XG5cdFx0XHR5ID0gaC8oMip3KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEZsb2F0MzJBcnJheShbXG5cdFx0XHQteCwgIHksXG5cdFx0XHQteCwgLXksXG5cdFx0XHQgeCwgIHksXG5cdFx0XHQgeCwgLXlcblx0XHRdKTtcblx0fVxuXG5cdGdldE9wdGlvbnMocmVjdDogUmVjdCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHJlY3QucG9zaXRpb24sXG5cdFx0XHRjb2xvcjogcmVjdC5jb2xvcixcblx0XHRcdHNpemU6IHJlY3Quc2l6ZSxcblx0XHRcdHJvdGF0aW9uOiByZWN0LnJvdGF0aW9uXG5cdFx0fVxuXG5cdFx0cmV0dXJuIG9wdGlvbnM7XG5cdH1cbn0iLCJpbXBvcnQgTWF0NHg0IGZyb20gXCIuLi8uLi8uLi9EYXRhVHlwZXMvTWF0NHg0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBRdWFkU2hhZGVyVHlwZSBmcm9tIFwiLi9RdWFkU2hhZGVyVHlwZVwiO1xuXG4vKiogQSBzaGFkZXIgZm9yIHNwcml0ZXMgYW5kIGFuaW1hdGVkIHNwcml0ZXMgKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwcml0ZVNoYWRlclR5cGUgZXh0ZW5kcyBRdWFkU2hhZGVyVHlwZSB7XG5cdGNvbnN0cnVjdG9yKHByb2dyYW1LZXk6IHN0cmluZyl7XG5cdFx0c3VwZXIocHJvZ3JhbUtleSk7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcblx0fVxuXG5cdGluaXRCdWZmZXJPYmplY3QoKTogdm9pZCB7XG5cdFx0dGhpcy5idWZmZXJPYmplY3RLZXkgPSBcInNwcml0ZVwiO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyLmNyZWF0ZUJ1ZmZlcih0aGlzLmJ1ZmZlck9iamVjdEtleSk7XG5cdH1cblxuXHRyZW5kZXIoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblx0XHRjb25zdCB0ZXh0dXJlID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0VGV4dHVyZShvcHRpb25zLmltYWdlS2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gdGhpcy5nZXRWZXJ0aWNlcyhvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnksIG9wdGlvbnMuc2NhbGUpO1xuXG5cdFx0Y29uc3QgRlNJWkUgPSB2ZXJ0ZXhEYXRhLkJZVEVTX1BFUl9FTEVNRU5UO1xuXG5cdFx0Ly8gQmluZCB0aGUgYnVmZmVyXG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG5cdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHZlcnRleERhdGEsIGdsLlNUQVRJQ19EUkFXKTtcblxuXHRcdC8vIEF0dHJpYnV0ZXNcblx0XHRjb25zdCBhX1Bvc2l0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1Bvc2l0aW9uXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9Qb3NpdGlvbiwgMiwgZ2wuRkxPQVQsIGZhbHNlLCA0ICogRlNJWkUsIDAgKiBGU0laRSk7XG5cdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYV9Qb3NpdGlvbik7XG5cblx0XHRjb25zdCBhX1RleENvb3JkID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1RleENvb3JkXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9UZXhDb29yZCwgMiwgZ2wuRkxPQVQsIGZhbHNlLCA0ICogRlNJWkUsIDIqRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfVGV4Q29vcmQpO1xuXG5cdFx0Ly8gVW5pZm9ybXNcblx0XHQvLyBHZXQgdHJhbnNmb3JtYXRpb24gbWF0cml4XG5cdFx0Ly8gV2Ugd2FudCBhIHNxdWFyZSBmb3Igb3VyIHJlbmRlcmluZyBzcGFjZSwgc28gZ2V0IHRoZSBtYXhpbXVtIGRpbWVuc2lvbiBvZiBvdXIgcXVhZFxuXHRcdGxldCBtYXhEaW1lbnNpb24gPSBNYXRoLm1heChvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG5cdFx0Ly8gVGhlIHNpemUgb2YgdGhlIHJlbmRlcmluZyBzcGFjZSB3aWxsIGJlIGEgc3F1YXJlIHdpdGggdGhpcyBtYXhpbXVtIGRpbWVuc2lvblxuXHRcdGxldCBzaXplID0gbmV3IFZlYzIobWF4RGltZW5zaW9uLCBtYXhEaW1lbnNpb24pLnNjYWxlKDIvb3B0aW9ucy53b3JsZFNpemUueCwgMi9vcHRpb25zLndvcmxkU2l6ZS55KTtcblxuXHRcdC8vIENlbnRlciBvdXIgdHJhbnNsYXRpb25zIGFyb3VuZCAoMCwgMClcblx0XHRjb25zdCB0cmFuc2xhdGVYID0gKG9wdGlvbnMucG9zaXRpb24ueCAtIG9wdGlvbnMub3JpZ2luLnggLSBvcHRpb25zLndvcmxkU2l6ZS54LzIpL21heERpbWVuc2lvbjtcblx0XHRjb25zdCB0cmFuc2xhdGVZID0gLShvcHRpb25zLnBvc2l0aW9uLnkgLSBvcHRpb25zLm9yaWdpbi55IC0gb3B0aW9ucy53b3JsZFNpemUueS8yKS9tYXhEaW1lbnNpb247XG5cblx0XHQvLyBDcmVhdGUgb3VyIHRyYW5zZm9ybWF0aW9uIG1hdHJpeFxuXHRcdHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKG5ldyBGbG9hdDMyQXJyYXkoW3RyYW5zbGF0ZVgsIHRyYW5zbGF0ZVldKSk7XG5cdFx0dGhpcy5zY2FsZS5zY2FsZShzaXplKTtcblx0XHR0aGlzLnJvdGF0aW9uLnJvdGF0ZShvcHRpb25zLnJvdGF0aW9uKTtcblx0XHRsZXQgdHJhbnNmb3JtYXRpb24gPSBNYXQ0eDQuTVVMVCh0aGlzLnRyYW5zbGF0aW9uLCB0aGlzLnNjYWxlLCB0aGlzLnJvdGF0aW9uKTtcblxuXHRcdC8vIFBhc3MgdGhlIHRyYW5zbGF0aW9uIG1hdHJpeCB0byBvdXIgc2hhZGVyXG5cdFx0Y29uc3QgdV9UcmFuc2Zvcm0gPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X1RyYW5zZm9ybVwiKTtcblx0XHRnbC51bmlmb3JtTWF0cml4NGZ2KHVfVHJhbnNmb3JtLCBmYWxzZSwgdHJhbnNmb3JtYXRpb24udG9BcnJheSgpKTtcblxuXHRcdC8vIFNldCB1cCBvdXIgc2FtcGxlciB3aXRoIG91ciBhc3NpZ25lZCB0ZXh0dXJlIHVuaXRcblx0XHRjb25zdCB1X1NhbXBsZXIgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X1NhbXBsZXJcIik7XG5cdFx0Z2wudW5pZm9ybTFpKHVfU2FtcGxlciwgdGV4dHVyZSk7XG5cblx0XHQvLyBQYXNzIGluIHRleFNoaWZ0XG5cdFx0Y29uc3QgdV90ZXhTaGlmdCA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfdGV4U2hpZnRcIik7XG5cdFx0Z2wudW5pZm9ybTJmdih1X3RleFNoaWZ0LCBvcHRpb25zLnRleFNoaWZ0KTtcblxuXHRcdC8vIFBhc3MgaW4gdGV4U2NhbGVcblx0XHRjb25zdCB1X3RleFNjYWxlID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV90ZXhTY2FsZVwiKTtcblx0XHRnbC51bmlmb3JtMmZ2KHVfdGV4U2NhbGUsIG9wdGlvbnMudGV4U2NhbGUpO1xuXG5cdFx0Ly8gRHJhdyB0aGUgcXVhZFxuXHRcdGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSByZW5kZXJpbmcgc3BhY2UgYWx3YXlzIGhhcyB0byBiZSBhIHNxdWFyZSwgc28gbWFrZSBzdXJlIGl0cyBzcXVhcmUgdy5yLnQgdG8gdGhlIGxhcmdlc3QgZGltZW5zaW9uXG5cdCAqIEBwYXJhbSB3IFRoZSB3aWR0aCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHBhcmFtIGggVGhlIGhlaWdodCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2YgdGhlIHZlcnRpY2VzIG9mIHRoZSBxdWFkXG5cdCAqL1xuXHRnZXRWZXJ0aWNlcyh3OiBudW1iZXIsIGg6IG51bWJlciwgc2NhbGU6IEZsb2F0MzJBcnJheSk6IEZsb2F0MzJBcnJheSB7XG5cdFx0bGV0IHgsIHk7XG5cblx0XHRpZihoID4gdyl7XG5cdFx0XHR5ID0gMC41O1xuXHRcdFx0eCA9IHcvKDIqaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHggPSAwLjU7XG5cdFx0XHR5ID0gaC8oMip3KTtcblx0XHR9XG5cblx0XHQvLyBTY2FsZSB0aGUgcmVuZGVyaW5nIHNwYWNlIGlmIG5lZWRlZFxuXHRcdHggKj0gc2NhbGVbMF07XG5cdFx0eSAqPSBzY2FsZVsxXTtcblxuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdC14LCAgeSwgMC4wLCAwLjAsXG5cdFx0XHQteCwgLXksIDAuMCwgMS4wLFxuXHRcdFx0IHgsICB5LCAxLjAsIDAuMCxcblx0XHRcdCB4LCAteSwgMS4wLCAxLjBcblx0XHRdKTtcblx0fVxuXG5cdGdldE9wdGlvbnMoc3ByaXRlOiBTcHJpdGUpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRsZXQgdGV4U2hpZnQ7XG5cdFx0bGV0IHRleFNjYWxlO1xuXG5cdFx0aWYoc3ByaXRlIGluc3RhbmNlb2YgQW5pbWF0ZWRTcHJpdGUpe1xuXHRcdFx0bGV0IGFuaW1hdGlvbkluZGV4ID0gc3ByaXRlLmFuaW1hdGlvbi5nZXRJbmRleEFuZEFkdmFuY2VBbmltYXRpb24oKTtcblx0XHRcdGxldCBvZmZzZXQgPSBzcHJpdGUuZ2V0QW5pbWF0aW9uT2Zmc2V0KGFuaW1hdGlvbkluZGV4KTtcblx0XHRcdHRleFNoaWZ0ID0gbmV3IEZsb2F0MzJBcnJheShbb2Zmc2V0LnggLyAoc3ByaXRlLmNvbHMgKiBzcHJpdGUuc2l6ZS54KSwgb2Zmc2V0LnkgLyAoc3ByaXRlLnJvd3MgKiBzcHJpdGUuc2l6ZS55KV0pO1xuXHRcdFx0dGV4U2NhbGUgPSBuZXcgRmxvYXQzMkFycmF5KFsxLyhzcHJpdGUuY29scyksIDEvKHNwcml0ZS5yb3dzKV0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0ZXhTaGlmdCA9IG5ldyBGbG9hdDMyQXJyYXkoWzAsIDBdKTtcblx0XHRcdHRleFNjYWxlID0gbmV3IEZsb2F0MzJBcnJheShbMSwgMV0pO1xuXHRcdH1cblxuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHNwcml0ZS5wb3NpdGlvbixcblx0XHRcdHJvdGF0aW9uOiBzcHJpdGUucm90YXRpb24sXG5cdFx0XHRzaXplOiBzcHJpdGUuc2l6ZSxcblx0XHRcdHNjYWxlOiBzcHJpdGUuc2NhbGUudG9BcnJheSgpLFxuXHRcdFx0aW1hZ2VLZXk6IHNwcml0ZS5pbWFnZUlkLFxuXHRcdFx0dGV4U2hpZnQsXG5cdFx0XHR0ZXhTY2FsZVxuXHRcdH1cblxuXHRcdHJldHVybiBvcHRpb25zO1xuXHR9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFF1ZXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvUXVldWVcIjtcbmltcG9ydCB7IFRpbGVkVGlsZW1hcERhdGEgfSBmcm9tIFwiLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiO1xuaW1wb3J0IFN0cmluZ1V0aWxzIGZyb20gXCIuLi9VdGlscy9TdHJpbmdVdGlsc1wiO1xuaW1wb3J0IEF1ZGlvTWFuYWdlciBmcm9tIFwiLi4vU291bmQvQXVkaW9NYW5hZ2VyXCI7XG5pbXBvcnQgU3ByaXRlc2hlZXQgZnJvbSBcIi4uL0RhdGFUeXBlcy9TcHJpdGVzaGVldFwiO1xuaW1wb3J0IFdlYkdMUHJvZ3JhbVR5cGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9SZW5kZXJpbmcvV2ViR0xQcm9ncmFtVHlwZVwiO1xuXG4vKipcbiAqIFRoZSByZXNvdXJjZSBtYW5hZ2VyIGZvciB0aGUgZ2FtZSBlbmdpbmUuXG4gKiBUaGUgcmVzb3VyY2UgbWFuYWdlciBpbnRlcmZhY2VzIHdpdGggdGhlIGxvYWRhYmxlIGFzc2V0cyBvZiBhIGdhbWUgc3VjaCBhcyBpbWFnZXMsIGRhdGEgZmlsZXMsXG4gKiBhbmQgc291bmRzLCB3aGljaCBhcmUgYWxsIGZvdW5kIGluIHRoZSBkaXN0IGZvbGRlci5cbiAqIFRoaXMgY2xhc3MgY29udHJvbHMgbG9hZGluZyBhbmQgdXBkYXRlcyB0aGUgQHJlZmVyZW5jZVtTY2VuZV0gd2l0aCB0aGUgbG9hZGluZyBwcm9ncmVzcywgc28gdGhhdCB0aGUgc2NlbmUgZG9lcyBcbiAqIG5vdCBzdGFydCBiZWZvcmUgYWxsIG5lY2Vzc2FyeSBhc3NldHMgYXJlIGxvYWRlZC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVzb3VyY2VNYW5hZ2VyIHtcbiAgICAvLyBJbnN0YW5jZSBmb3IgdGhlIHNpbmdsZXRvbiBjbGFzc1xuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvLyBCb29sZWFucyB0byBrZWVwIHRyYWNrIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBSZXNvdXJjZU1hbmFnZXIgaXMgY3VycmVudGx5IGxvYWRpbmcgc29tZXRoaW5nXG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IGFueSByZXNvdXJjZXMgYXJlIGxvYWRpbmcgKi9cbiAgICBwcml2YXRlIGxvYWRpbmc6IGJvb2xlYW47XG4gICAgLyoqIEEgYm9vbGVhbiB0byBpbmRpY2F0ZSB0aGF0IHRoZSBhc3NldHMganVzdCBmaW5pc2hlZCBsb2FkaW5nICovXG4gICAgcHJpdmF0ZSBqdXN0TG9hZGVkOiBib29sZWFuO1xuXG4gICAgLy8gRnVuY3Rpb25zIHRvIGRvIHNvbWV0aGluZyB3aGVuIGxvYWRpbmcgcHJvZ3Jlc3NlcyBvciBpcyBjb21wbGV0ZWQgc3VjaCBhcyByZW5kZXIgYSBsb2FkaW5nIHNjcmVlblxuICAgIC8qKiBBIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gbG9hZGluZyBwcm9ncmVzc2VzICovXG4gICAgcHVibGljIG9uTG9hZFByb2dyZXNzOiBGdW5jdGlvbjtcbiAgICAvKiogQSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIGxvYWRpbmcgY29tcGxldGVzICovXG4gICAgcHVibGljIG9uTG9hZENvbXBsZXRlOiBGdW5jdGlvbjtcblxuXG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IGltYWdlcyBuZWVkIHRvIGJlIGxvYWRlZCovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9pbWFnZXNMb2FkZWQ6IG51bWJlcjtcbiAgICAvKiogTnVtYmVyIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgaW1hZ2VzIGFyZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X2ltYWdlc1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2YgaW1hZ2VzIHdlIG11c3QgbG9hZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIGltYWdlcyB0aGF0IGFyZSBjdXJyZW50bHkgbG9hZGVkIGFuZCBiZWluZyB1c2VkIGJ5IHRoZSBzY2VuZS4gVGhlIHJlZmVyZW5jZSB0byB0aGVzZSBpbWFnZXMgb25seSBleGlzdCBoZXJlIGZvciBlYXN5IGNsZWFudXAuICovXG4gICAgcHJpdmF0ZSBpbWFnZXM6IE1hcDxIVE1MSW1hZ2VFbGVtZW50PjtcblxuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSB0aWxlbWFwcyBuZWVkIHRvIGJlIGxvYWRlZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRpbGVtYXBzIGFyZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2YgdGlsZW1hcHMgd2UgbXVzdCBsb2FkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9zcHJpdGVzaGVldExvYWRpbmdRdWV1ZTogUXVldWU8S2V5UGF0aFBhaXI+O1xuICAgIC8qKiBBIG1hcCBvZiB0aGUgdGlsZW1hcHMgdGhhdCBhcmUgY3VycmVudGx5IGxvYWRlZCBhbmQgKHByZXN1bWFibHkpIGJlaW5nIHVzZWQgYnkgdGhlIHNjZW5lICovXG4gICAgcHJpdmF0ZSBzcHJpdGVzaGVldHM6IE1hcDxTcHJpdGVzaGVldD47XG5cbiAgICAvKiogTnVtYmVyIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgdGlsZW1hcHMgbmVlZCB0byBiZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBzTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRpbGVtYXBzIGFyZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkOiBudW1iZXI7XG4gICAgLyoqIFRoZSBxdWV1ZSBvZiB0aWxlbWFwcyB3ZSBtdXN0IGxvYWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIHRpbGVtYXBzIHRoYXQgYXJlIGN1cnJlbnRseSBsb2FkZWQgYW5kIChwcmVzdW1hYmx5KSBiZWluZyB1c2VkIGJ5IHRoZSBzY2VuZSAqL1xuICAgIHByaXZhdGUgdGlsZW1hcHM6IE1hcDxUaWxlZFRpbGVtYXBEYXRhPjtcblxuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSBzb3VuZHMgbmVlZCB0byBiZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X2F1ZGlvTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHNvdW5kcyBhcmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9hdWRpb1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2Ygc291bmRzIHdlIG11c3QgbG9hZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIHNvdW5kcyB0aGF0IGFyZSBjdXJyZW50bHkgbG9hZGVkIGFuZCAocHJlc3VtYWJseSkgYmVpbmcgdXNlZCBieSB0aGUgc2NlbmUgKi9cbiAgICBwcml2YXRlIGF1ZGlvQnVmZmVyczogTWFwPEF1ZGlvQnVmZmVyPjtcblxuICAgIC8qKiBUaGUgdG90YWwgbnVtYmVyIG9mIFwidHlwZXNcIiBvZiB0aGluZ3MgdGhhdCBuZWVkIHRvIGJlIGxvYWRlZCAoaS5lLiBpbWFnZXMgYW5kIHRpbGVtYXBzKSAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfdHlwZXNUb0xvYWQ6IG51bWJlcjtcblxuICAgIHByaXZhdGUgbG9hZG9ubHlfanNvbkxvYWRlZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfanNvblRvTG9hZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfanNvbkxvYWRpbmdRdWV1ZTogUXVldWU8S2V5UGF0aFBhaXI+O1xuICAgIHByaXZhdGUganNvbk9iamVjdHM6IE1hcDxSZWNvcmQ8c3RyaW5nLCBhbnk+PjtcblxuICAgIC8qICMjIyMjIyMjIyMgSU5GT1JNQVRJT04gU1BFQ0lBTCBUTyBXRUJHTCAjIyMjIyMjIyMjICovXG4gICAgcHJpdmF0ZSBnbF9XZWJHTEFjdGl2ZTogYm9vbGVhbjtcblxuICAgIHByaXZhdGUgbG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zVG9Mb2FkOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBsb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhfU2hhZGVyPjtcblxuICAgIHByaXZhdGUgbG9hZG9ubHlfdGlsZW1hcE9iamVjdFRvTG9hZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRlZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZTogUXVldWU8S2V5TWFwUGFpcj47XG5cbiAgICBwcml2YXRlIGdsX1NoYWRlclByb2dyYW1zOiBNYXA8V2ViR0xQcm9ncmFtVHlwZT47XG5cbiAgICBwcml2YXRlIGdsX1RleHR1cmVzOiBNYXA8bnVtYmVyPjtcbiAgICBwcml2YXRlIGdsX05leHRUZXh0dXJlSUQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGdsX0J1ZmZlcnM6IE1hcDxXZWJHTEJ1ZmZlcj47XG5cbiAgICBwcml2YXRlIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cbiAgICAvKiAjIyMjIyMjIyMjIFVOTE9BRElORyBBTkQgRVhDTFVTSU9OIExJU1QgIyMjIyMjIyMjIyAqL1xuICAgIC8qKiBBIGxpc3Qgb2YgcmVzb3VyY2VzIHRoYXQgd2lsbCBiZSB1bmxvYWRlZCBhdCB0aGUgZW5kIG9mIHRoZSBjdXJyZW50IHNjZW5lICovXG4gICAgcHJpdmF0ZSByZXNvdXJjZXNUb1VubG9hZDogQXJyYXk8UmVzb3VyY2VSZWZlcmVuY2U+O1xuXG4gICAgLyoqIEEgbGlzdCBvZiByZXNvdXJjZXMgdG8ga2VlcCB1bnRpbCBmdXJ0aGVyIG5vdGljZSAqL1xuICAgIHByaXZhdGUgcmVzb3VyY2VzVG9LZWVwOiBBcnJheTxSZXNvdXJjZVJlZmVyZW5jZT47XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5qdXN0TG9hZGVkID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZXNMb2FkZWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc1RvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5pbWFnZXMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5zcHJpdGVzaGVldHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwc0xvYWRlZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy50aWxlbWFwcyA9IG5ldyBNYXAoKTtcblxuICAgICAgICB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5hdWRpb0J1ZmZlcnMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGVkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uVG9Mb2FkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgICAgIHRoaXMuanNvbk9iamVjdHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc0xvYWRlZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZSA9IG5ldyBRdWV1ZSgpO1xuXG4gICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5nbF9UZXh0dXJlcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5nbF9OZXh0VGV4dHVyZUlEID0gMDtcbiAgICAgICAgdGhpcy5nbF9CdWZmZXJzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5yZXNvdXJjZXNUb0tlZXAgPSBuZXcgQXJyYXkoKTtcblxuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICB9O1xuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBTSU5HTEVUT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzIG9yIGEgbmV3IGluc3RhbmNlIGlmIG5vbmUgZXhpc3RcbiAgICAgKiBAcmV0dXJucyBUaGUgcmVzb3VyY2UgbWFuYWdlclxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBSZXNvdXJjZU1hbmFnZXIge1xuICAgICAgICBpZiAoIXRoaXMuaW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuaW5zdGFuY2UgPSBuZXcgUmVzb3VyY2VNYW5hZ2VyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICAvKiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIFBVQkxJQyBGVU5DVElPTiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjKi9cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZXMgb3IgZGVhY3RpdmF0ZXMgdGhlIHVzZSBvZiBXZWJHTFxuICAgICAqIEBwYXJhbSBmbGFnIFRydWUgaWYgV2ViR0wgc2hvdWxkIGJlIHVzZWQsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqIEBwYXJhbSBnbCBUaGUgaW5zdGFuY2Ugb2YgdGhlIGdyYXBoaWNzIGNvbnRleHQsIGlmIGFwcGxpY2FibGVcbiAgICAgKi9cbiAgICBwdWJsaWMgdXNlV2ViR0woZmxhZzogYm9vbGVhbiwgZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IHZvaWQge1xuICAgICAgICB0aGlzLmdsX1dlYkdMQWN0aXZlID0gZmxhZztcblxuICAgICAgICBpZiAodGhpcy5nbF9XZWJHTEFjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5nbCA9IGdsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYW4gaW1hZ2UgZnJvbSBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIGFzc29jaWF0ZSB0aGUgbG9hZGVkIGltYWdlIHdpdGhcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgaW1hZ2UgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBpbWFnZShrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcEltYWdlKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2VlcFJlc291cmNlKGtleSwgUmVzb3VyY2VUeXBlLklNQUdFKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBsb2FkZWQgaW1hZ2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCBpbWFnZVxuICAgICAqIEByZXR1cm5zIFRoZSBpbWFnZSBlbGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGlzIGtleVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRJbWFnZShrZXk6IHN0cmluZyk6IEhUTUxJbWFnZUVsZW1lbnQge1xuICAgICAgICBsZXQgaW1hZ2UgPSB0aGlzLmltYWdlcy5nZXQoa2V5KTtcbiAgICAgICAgLy8gaWYgKGltYWdlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gICAgIHRocm93IGBUaGVyZSBpcyBubyBpbWFnZSBhc3NvY2lhdGVkIHdpdGgga2V5IFwiJHtrZXl9XCJgXG4gICAgICAgIC8vIH1cbiAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGEgc3ByaXRlc2hlZXQgZnJvbSBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIGFzc29jaWF0ZSB0aGUgbG9hZGVkIHNwcml0ZXNoZWV0IHdpdGhcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgc3ByaXRlc2hlZXQgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBzcHJpdGVzaGVldChrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcFNwcml0ZXNoZWV0KGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2VlcFJlc291cmNlKGtleSwgUmVzb3VyY2VUeXBlLlNQUklURVNIRUVUKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBsb2FkZWQgc3ByaXRlc2hlZXRcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHNwcml0ZXNoZWV0IHRvIGxvYWRcbiAgICAgKiBAcmV0dXJucyBUaGUgbG9hZGVkIFNwcml0ZXNoZWV0XG4gICAgICovXG4gICAgcHVibGljIGdldFNwcml0ZXNoZWV0KGtleTogc3RyaW5nKTogU3ByaXRlc2hlZXQge1xuICAgICAgICByZXR1cm4gdGhpcy5zcHJpdGVzaGVldHMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYW4gYXVkaW8gZmlsZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgbG9hZGVkIGF1ZGlvIGZpbGVcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICovXG4gICAgcHVibGljIGF1ZGlvKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIHBhdGg6IHBhdGggfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGVsbHMgdGhlIHJlc291cmNlIG1hbmFnZXIgdG8ga2VlcCB0aGlzIHJlc291cmNlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSByZXNvdXJjZVxuICAgICAqL1xuICAgIHB1YmxpYyBrZWVwQXVkaW8oa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwUmVzb3VyY2Uoa2V5LCBSZXNvdXJjZVR5cGUuQVVESU8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhIGxvYWRlZCBhdWRpbyBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBhdWRpbyBmaWxlIHRvIGxvYWRcbiAgICAgKiBAcmV0dXJucyBUaGUgQXVkaW9CdWZmZXIgY3JlYXRlZCBmcm9tIHRoZSBsb2FkZWQgYXVkaW8gZmxlXG4gICAgICovXG4gICAgcHVibGljIGdldEF1ZGlvKGtleTogc3RyaW5nKTogQXVkaW9CdWZmZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5hdWRpb0J1ZmZlcnMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIHRpbGVtYXAgZnJvbSBhIGpzb24gZmlsZS4gQXV0b21hdGljYWxseSBsb2FkcyByZWxhdGVkIGltYWdlc1xuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgbG9hZGVkIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgdGlsZW1hcCB0byBsb2FkXG4gICAgICovXG4gICAgcHVibGljIHRpbGVtYXAoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcFRpbGVtYXAoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwUmVzb3VyY2Uoa2V5LCBSZXNvdXJjZVR5cGUuVElMRU1BUCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmVpdmVzIGEgbG9hZGVkIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCB0aWxlbWFwXG4gICAgICogQHJldHVybnMgVGhlIHRpbGVtYXAgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlIGtleVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRUaWxlbWFwKGtleTogc3RyaW5nKTogVGlsZWRUaWxlbWFwRGF0YSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbGVtYXBzLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFuIG9iamVjdCBmcm9tIGEganNvbiBmaWxlLlxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgbG9hZGVkIG9iamVjdFxuICAgICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBqc29uIGZpbGUgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBvYmplY3Qoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZykge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcE9iamVjdChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmtlZXBSZXNvdXJjZShrZXksIFJlc291cmNlVHlwZS5KU09OKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgYSBsb2FkZWQgb2JqZWN0XG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBsb2FkZWQgb2JqZWN0XG4gICAgICogQHJldHVybnMgVGhlIG9iamVjdCBkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUga2V5XG4gICAgICovXG4gICAgcHVibGljIGdldE9iamVjdChrZXk6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gdGhpcy5qc29uT2JqZWN0cy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICAvKiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIExPQUQgRlVOQ1RJT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIHJlc291cmNlcyBjdXJyZW50bHkgaW4gdGhlIHF1ZXVlXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWwgd2hlbiB0aGUgcmVzb3VyY2VzIGFyZSBmaW5pc2hlZCBsb2FkaW5nXG4gICAgICovXG4gICAgbG9hZFJlc291cmNlc0Zyb21RdWV1ZShjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90eXBlc1RvTG9hZCA9IDU7XG5cbiAgICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcblxuICAgICAgICAvLyBMb2FkIGV2ZXJ5dGhpbmcgaW4gdGhlIHF1ZXVlcy4gVGlsZW1hcHMgaGF2ZSB0byBjb21lIGJlZm9yZSBpbWFnZXMgYmVjYXVzZSB0aGV5IHdpbGwgYWRkIG5ldyBpbWFnZXMgdG8gdGhlIHF1ZXVlXG5cbiAgICAgICAgdGhpcy5sb2FkVGlsZW1hcE9iamVjdEZyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBUaWxlbWFwT2JqZWN0c1wiKTtcbiAgICAgICAgICAgIHRoaXMubG9hZFRpbGVtYXBzRnJvbVF1ZXVlKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBUaWxlbWFwc1wiKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRTcHJpdGVzaGVldHNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBTcHJpdGVzaGVldHNcIik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZEltYWdlc0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBJbWFnZXNcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRBdWRpb0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgQXVkaW9cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkT2JqZWN0c0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGVkIE9iamVjdHNcIik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ2xfV2ViR0xBY3RpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2xfTG9hZFNoYWRlcnNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGVkIFNoYWRlcnNcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nKGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nKGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICAvLyBEb25lIGxvYWRpbmdcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuanVzdExvYWRlZCA9IHRydWU7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBVTkxPQUQgRlVOQ1RJT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG5cbiAgICBwcml2YXRlIGtlZXBSZXNvdXJjZShrZXk6IHN0cmluZywgdHlwZTogUmVzb3VyY2VUeXBlKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiS2VlcCByZXNvdXJjZS4uLlwiKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnJlc291cmNlc1RvVW5sb2FkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgcmVzb3VyY2UgPSB0aGlzLnJlc291cmNlc1RvVW5sb2FkW2ldO1xuICAgICAgICAgICAgaWYgKHJlc291cmNlLmtleSA9PT0ga2V5ICYmIHJlc291cmNlLnJlc291cmNlVHlwZSA9PT0gdHlwZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRm91bmQgcmVzb3VyY2UgXCIgKyBrZXkgKyBcIiBvZiB0eXBlIFwiICsgdHlwZSArIFwiLiBLZWVwaW5nLlwiKTtcbiAgICAgICAgICAgICAgICBsZXQgcmVzb3VyY2VUb01vdmUgPSB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvS2VlcC5wdXNoKC4uLnJlc291cmNlVG9Nb3ZlKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWxldGVzIHJlZmVyZW5jZXMgdG8gYWxsIHJlc291cmNlcyBpbiB0aGUgcmVzb3VyY2UgbWFuYWdlclxuICAgICAqL1xuICAgIHVubG9hZEFsbFJlc291cmNlcygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuanVzdExvYWRlZCA9IGZhbHNlO1xuXG4gICAgICAgIGZvciAobGV0IHJlc291cmNlIG9mIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQpIHtcbiAgICAgICAgICAgIC8vIFVubG9hZCB0aGUgcmVzb3VyY2VcbiAgICAgICAgICAgIHRoaXMudW5sb2FkUmVzb3VyY2UocmVzb3VyY2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1bmxvYWRSZXNvdXJjZShyZXNvdXJjZTogUmVzb3VyY2VSZWZlcmVuY2UpOiB2b2lkIHtcbiAgICAgICAgLy8gRGVsZXRlIHRoZSByZXNvdXJjZSBpdHNlbGZcbiAgICAgICAgc3dpdGNoIChyZXNvdXJjZS5yZXNvdXJjZVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgUmVzb3VyY2VUeXBlLklNQUdFOlxuICAgICAgICAgICAgICAgIHRoaXMuaW1hZ2VzLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2xfVGV4dHVyZXMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSZXNvdXJjZVR5cGUuVElMRU1BUDpcbiAgICAgICAgICAgICAgICB0aGlzLnRpbGVtYXBzLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSZXNvdXJjZVR5cGUuU1BSSVRFU0hFRVQ6XG4gICAgICAgICAgICAgICAgdGhpcy5zcHJpdGVzaGVldHMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFJlc291cmNlVHlwZS5BVURJTzpcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQnVmZmVycy5kZWxldGUocmVzb3VyY2Uua2V5KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUmVzb3VyY2VUeXBlLkpTT046XG4gICAgICAgICAgICAgICAgdGhpcy5qc29uT2JqZWN0cy5kZWxldGUocmVzb3VyY2Uua2V5KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIC8qY2FzZSBSZXNvdXJjZVR5cGUuU0hBREVSOlxuICAgICAgICAgICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMuZ2V0KHJlc291cmNlLmtleSkuZGVsZXRlKHRoaXMuZ2wpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7Ki9cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlbGV0ZSBhbnkgZGVwZW5kZW5jaWVzXG4gICAgICAgIGZvciAobGV0IGRlcGVuZGVuY3kgb2YgcmVzb3VyY2UuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICB0aGlzLnVubG9hZFJlc291cmNlKGRlcGVuZGVuY3kpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBXT1JLIEZVTkNUSU9OUyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjKi9cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgdGlsZW1hcHMgY3VycmVudGx5IGluIHRoZSB0aWxlbWFwIGxvYWRpbmcgcXVldWVcbiAgICAgKiBAcGFyYW0gb25GaW5pc2hMb2FkaW5nIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gbG9hZGluZyBpcyBjb21wbGV0ZVxuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZFRpbGVtYXBzRnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwc1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfdGlsZW1hcExvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNMb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IHRpbGVtYXAgPSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5sb2FkVGlsZW1hcCh0aWxlbWFwLmtleSwgdGlsZW1hcC5wYXRoLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYSBzaW5ndWxhciB0aWxlbWFwIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgdGlsZW1hcFxuICAgICAqIEBwYXJhbSBwYXRoVG9UaWxlbWFwSlNPTiBUaGUgcGF0aCB0byB0aGUgdGlsZW1hcCBKU09OIGZpbGVcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tJZkxhc3QgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRUaWxlbWFwKGtleTogc3RyaW5nLCBwYXRoVG9UaWxlbWFwSlNPTjogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUocGF0aFRvVGlsZW1hcEpTT04sIChmaWxlVGV4dDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBsZXQgdGlsZW1hcE9iamVjdCA9IDxUaWxlZFRpbGVtYXBEYXRhPkpTT04ucGFyc2UoZmlsZVRleHQpO1xuXG4gICAgICAgICAgICAvLyBXZSBjYW4gcGFyc2UgdGhlIG9iamVjdCBsYXRlciAtIGl0J3MgbXVjaCBmYXN0ZXIgdGhhbiBsb2FkaW5nXG4gICAgICAgICAgICB0aGlzLnRpbGVtYXBzLmFkZChrZXksIHRpbGVtYXBPYmplY3QpO1xuICAgICAgICAgICAgbGV0IHJlc291cmNlID0gbmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLlRJTEVNQVApO1xuXG4gICAgICAgICAgICAvLyBHcmFiIHRoZSB0aWxlc2V0IGltYWdlcyB3ZSBuZWVkIHRvIGxvYWQgYW5kIGFkZCB0aGVtIHRvIHRoZSBpbWFnZWxvYWRpbmcgcXVldWVcbiAgICAgICAgICAgIGZvciAobGV0IHRpbGVzZXQgb2YgdGlsZW1hcE9iamVjdC50aWxlc2V0cykge1xuICAgICAgICAgICAgICAgIGlmICh0aWxlc2V0LmltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBrZXkgPSB0aWxlc2V0LmltYWdlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgcGF0aCA9IFN0cmluZ1V0aWxzLmdldFBhdGhGcm9tRmlsZVBhdGgocGF0aFRvVGlsZW1hcEpTT04pICsga2V5O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCwgaXNEZXBlbmRlbmN5OiB0cnVlIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGltYWdlIGFzIGEgZGVwZW5kZW5jeSB0byB0aGUgdGlsZW1hcFxuICAgICAgICAgICAgICAgICAgICByZXNvdXJjZS5hZGREZXBlbmRlbmN5KG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGlsZXNldC50aWxlcykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB0aWxlIG9mIHRpbGVzZXQudGlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrZXkgPSB0aWxlLmltYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhdGggPSBTdHJpbmdVdGlscy5nZXRQYXRoRnJvbUZpbGVQYXRoKHBhdGhUb1RpbGVtYXBKU09OKSArIGtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoLCBpc0RlcGVuZGVuY3k6IHRydWUgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGltYWdlIGFzIGEgZGVwZW5kZW5jeSB0byB0aGUgdGlsZW1hcFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2UuYWRkRGVwZW5kZW5jeShuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWRkIHRoZSByZXNvdXJjZSByZWZlcmVuY2UgdG8gdGhlIGxpc3Qgb2YgcmVzb3VyY2UgdG8gdW5sb2FkXG4gICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnB1c2gocmVzb3VyY2UpO1xuXG4gICAgICAgICAgICAvLyBGaW5pc2ggbG9hZGluZ1xuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nVGlsZW1hcChjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGEgdGlsZW1hcC4gQ2FsbHMgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlmIHRoaXMgaXMgdGhlIGxhc3QgdGlsZW1hcCBiZWluZyBsb2FkZWRcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdUaWxlbWFwKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBzTG9hZGVkICs9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfdGlsZW1hcHNMb2FkZWQgPT09IHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyB0aWxlbWFwc1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFsbCBzcHJpdGVzaGVldHMgY3VycmVudGx5IGluIHRoZSBzcHJpdGVzaGVldCBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZSBzcHJpdGVzaGVldHMgYXJlIGRvbmUgbG9hZGluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZFNwcml0ZXNoZWV0c0Zyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzVG9Mb2FkID0gdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldExvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNUb0xvYWQgPT09IDApIHtcbiAgICAgICAgICAgIG9uRmluaXNoTG9hZGluZygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IHNwcml0ZXNoZWV0ID0gdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldExvYWRpbmdRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRTcHJpdGVzaGVldChzcHJpdGVzaGVldC5rZXksIHNwcml0ZXNoZWV0LnBhdGgsIG9uRmluaXNoTG9hZGluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHNpbmd1bGFyIHNwcml0ZXNoZWV0IFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgc3ByaXRlc2hlZXQgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBwYXRoVG9TcHJpdGVzaGVldEpTT04gVGhlIHBhdGggdG8gdGhlIHNwcml0ZXNoZWV0IEpTT04gZmlsZVxuICAgICAqIEBwYXJhbSBjYWxsYmFja0lmTGFzdCBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IHNwcml0ZXNoZWV0XG4gICAgICovXG4gICAgcHJpdmF0ZSBsb2FkU3ByaXRlc2hlZXQoa2V5OiBzdHJpbmcsIHBhdGhUb1Nwcml0ZXNoZWV0SlNPTjogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUocGF0aFRvU3ByaXRlc2hlZXRKU09OLCAoZmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHNwcml0ZXNoZWV0ID0gPFNwcml0ZXNoZWV0PkpTT04ucGFyc2UoZmlsZVRleHQpO1xuXG4gICAgICAgICAgICAvLyBXZSBjYW4gcGFyc2UgdGhlIG9iamVjdCBsYXRlciAtIGl0J3MgbXVjaCBmYXN0ZXIgdGhhbiBsb2FkaW5nXG4gICAgICAgICAgICB0aGlzLnNwcml0ZXNoZWV0cy5hZGQoa2V5LCBzcHJpdGVzaGVldCk7XG5cbiAgICAgICAgICAgIGxldCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5TUFJJVEVTSEVFVCk7XG5cbiAgICAgICAgICAgIC8vIEdyYWIgdGhlIGltYWdlIHdlIG5lZWQgdG8gbG9hZCBhbmQgYWRkIGl0IHRvIHRoZSBpbWFnZWxvYWRpbmcgcXVldWVcbiAgICAgICAgICAgIGxldCBwYXRoID0gU3RyaW5nVXRpbHMuZ2V0UGF0aEZyb21GaWxlUGF0aChwYXRoVG9TcHJpdGVzaGVldEpTT04pICsgc3ByaXRlc2hlZXQuc3ByaXRlU2hlZXRJbWFnZTtcbiAgICAgICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleTogc3ByaXRlc2hlZXQubmFtZSwgcGF0aDogcGF0aCwgaXNEZXBlbmRlbmN5OiB0cnVlIH0pO1xuXG4gICAgICAgICAgICByZXNvdXJjZS5hZGREZXBlbmRlbmN5KG5ldyBSZXNvdXJjZVJlZmVyZW5jZShzcHJpdGVzaGVldC5uYW1lLCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChyZXNvdXJjZSk7XG5cbiAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nXG4gICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdTcHJpdGVzaGVldChjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGEgc3ByaXRlc2hlZXQuIENhbGxzIHRoZSBjYWxsYmFjayBmdW5jdGlvbiBpZiB0aGlzIGlzIHRoZSBsYXN0IHNwcml0ZXNoZWV0IGJlaW5nIGxvYWRlZFxuICAgICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IHNwcml0ZXNoZWV0IHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdTcHJpdGVzaGVldChjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgPT09IHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgc3ByaXRlc2hlZXRzXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIGltYWdlcyBjdXJyZW50bHkgaW4gdGhlIGltYWdlIGxvYWRpbmcgcXVldWVcbiAgICAgKiBAcGFyYW0gb25GaW5pc2hMb2FkaW5nIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gdGhlcmUgYXJlIG5vIG1vcmUgaW1hZ2VzIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRJbWFnZXNGcm9tUXVldWUob25GaW5pc2hMb2FkaW5nOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCA9IDA7XG5cbiAgICAgICAgLy8gSWYgbm8gaXRlbXMgdG8gbG9hZCwgd2UncmUgZmluaXNoZWRcbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfaW1hZ2VzVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmhhc0l0ZW1zKCkpIHtcbiAgICAgICAgICAgIGxldCBpbWFnZSA9IHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5sb2FkSW1hZ2UoaW1hZ2Uua2V5LCBpbWFnZS5wYXRoLCBpbWFnZS5pc0RlcGVuZGVuY3ksIG9uRmluaXNoTG9hZGluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHNpbmd1bGFyIGltYWdlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBpbWFnZSB0byBsb2FkXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIGltYWdlIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tJZkxhc3QgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBpbWFnZVxuICAgICAqL1xuICAgIHB1YmxpYyBsb2FkSW1hZ2Uoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZywgaXNEZXBlbmRlbmN5OiBib29sZWFuLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQWRkIHRvIGxvYWRlZCBpbWFnZXNcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VzLmFkZChrZXksIGltYWdlKTtcblxuICAgICAgICAgICAgLy8gSWYgbm90IGEgZGVwZW5kZW5jeSwgcHVzaCBpdCB0byB0aGUgdW5sb2FkIGxpc3QuIE90aGVyd2lzZSBpdCdzIG1hbmFnZWQgYnkgc29tZXRoaW5nIGVsc2VcbiAgICAgICAgICAgIGlmICghaXNEZXBlbmRlbmN5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiBXZWJHTCBpcyBhY3RpdmUsIGNyZWF0ZSBhIHRleHR1cmVcbiAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVXZWJHTFRleHR1cmUoa2V5LCBpbWFnZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZpbmlzaCBpbWFnZSBsb2FkXG4gICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdJbWFnZShjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpbWFnZS5zcmMgPSBwYXRoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGFuIGltYWdlLiBJZiB0aGlzIGlzIHRoZSBsYXN0IGltYWdlLCBpdCBjYWxscyB0aGUgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBpbWFnZVxuICAgICAqL1xuICAgIHByaXZhdGUgZmluaXNoTG9hZGluZ0ltYWdlKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCArPSAxO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV9pbWFnZXNUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyBpbWFnZXNcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgYXVkaW8gY3VycmVudGx5IGluIHRoZSB0aWxlbWFwIGxvYWRpbmcgcXVldWVcbiAgICAgKiBAcGFyYW0gb25GaW5pc2hMb2FkaW5nIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gdGlsZW1hcHMgYXJlIGRvbmUgbG9hZGluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZEF1ZGlvRnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCA9PT0gMCkge1xuICAgICAgICAgICAgb25GaW5pc2hMb2FkaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAodGhpcy5sb2Fkb25seV9hdWRpb0xvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgYXVkaW8gPSB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZEF1ZGlvKGF1ZGlvLmtleSwgYXVkaW8ucGF0aCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBzaW5ndWxhciBhdWRpbyBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHRoZSBhdWRpbyBmaWxlIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICogQHBhcmFtIGNhbGxiYWNrSWZMYXN0IFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBsb2FkQXVkaW8oa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZywgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIGxldCBhdWRpb0N0eCA9IEF1ZGlvTWFuYWdlci5nZXRJbnN0YW5jZSgpLmdldEF1ZGlvQ29udGV4dCgpO1xuXG4gICAgICAgIGxldCByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgIHJlcXVlc3Qub3BlbignR0VUJywgcGF0aCwgdHJ1ZSk7XG4gICAgICAgIHJlcXVlc3QucmVzcG9uc2VUeXBlID0gJ2FycmF5YnVmZmVyJztcblxuICAgICAgICByZXF1ZXN0Lm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICAgIGF1ZGlvQ3R4LmRlY29kZUF1ZGlvRGF0YShyZXF1ZXN0LnJlc3BvbnNlLCAoYnVmZmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIHRvIGxpc3Qgb2YgYXVkaW8gYnVmZmVyc1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9CdWZmZXJzLmFkZChrZXksIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5BVURJTykpO1xuXG4gICAgICAgICAgICAgICAgLy8gRmluaXNoIGxvYWRpbmcgc291bmRcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdBdWRpbyhjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIkVycm9yIGxvYWRpbmcgc291bmRcIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJlcXVlc3Quc2VuZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGFuIGF1ZGlvIGZpbGUuIENhbGxzIHRoZSBjYWxsYmFjayBmdW5jdG9uIGlmIHRoaXMgaXMgdGhlIGxhc3QgYXVkaW8gc2FtcGxlIGJlaW5nIGxvYWRlZC5cbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBhdWRpbyBmaWxlIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdBdWRpbyhjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRlZCArPSAxO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X2F1ZGlvVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgYXVkaW9cbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgb2JqZWN0cyBjdXJyZW50bHkgaW4gdGhlIG9iamVjdCBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZXJlIGFyZSBubyBtb3JlIG9iamVjdHMgdG8gbG9hZFxuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZE9iamVjdHNGcm9tUXVldWUob25GaW5pc2hMb2FkaW5nOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Ub0xvYWQgPSB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2pzb25Ub0xvYWQgPT09IDApIHtcbiAgICAgICAgICAgIG9uRmluaXNoTG9hZGluZygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKHRoaXMubG9hZG9ubHlfanNvbkxvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgb2JqID0gdGhpcy5sb2Fkb25seV9qc29uTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZE9iamVjdChvYmoua2V5LCBvYmoucGF0aCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGEgc2luZ3VsYXIgb2JqZWN0XG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBvYmplY3QgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBvYmplY3QgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBjYWxsYmFja0lmTGFzdCBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IG9iamVjdFxuICAgICAqL1xuICAgIHB1YmxpYyBsb2FkT2JqZWN0KGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGNhbGxiYWNrSWZMYXN0OiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRUZXh0RmlsZShwYXRoLCAoZmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IG9iaiA9IEpTT04ucGFyc2UoZmlsZVRleHQpO1xuICAgICAgICAgICAgdGhpcy5qc29uT2JqZWN0cy5hZGQoa2V5LCBvYmopO1xuXG4gICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnB1c2gobmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLkpTT04pKTtcblxuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmluaXNoIGxvYWRpbmcgYW4gb2JqZWN0LiBJZiB0aGlzIGlzIHRoZSBsYXN0IG9iamVjdCwgaXQgY2FsbHMgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3Qgb2JqZWN0XG4gICAgICovXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nT2JqZWN0KGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9qc29uTG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X2pzb25Ub0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyBvYmplY3RzXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyBXRUJHTCBTUEVDSUZJQyBGVU5DVElPTlMgIyMjIyMjIyMjIyAqL1xuXG4gICAgcHVibGljIGdldFRleHR1cmUoa2V5OiBzdHJpbmcpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5nbF9UZXh0dXJlcy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2hhZGVyUHJvZ3JhbShrZXk6IHN0cmluZyk6IFdlYkdMUHJvZ3JhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdsX1NoYWRlclByb2dyYW1zLmdldChrZXkpLnByb2dyYW07XG4gICAgfVxuXG4gICAgcHVibGljIGdldEJ1ZmZlcihrZXk6IHN0cmluZyk6IFdlYkdMQnVmZmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2xfQnVmZmVycy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVdlYkdMVGV4dHVyZShpbWFnZUtleTogc3RyaW5nLCBpbWFnZTogSFRNTEltYWdlRWxlbWVudCk6IHZvaWQge1xuICAgICAgICAvLyBHZXQgdGhlIHRleHR1cmUgSURcbiAgICAgICAgY29uc3QgdGV4dHVyZUlEID0gdGhpcy5nZXRUZXh0dXJlSUQodGhpcy5nbF9OZXh0VGV4dHVyZUlEKTtcblxuICAgICAgICAvLyBDcmVhdGUgdGhlIHRleHR1cmVcbiAgICAgICAgY29uc3QgdGV4dHVyZSA9IHRoaXMuZ2wuY3JlYXRlVGV4dHVyZSgpO1xuXG4gICAgICAgIC8vIFNldCB1cCB0aGUgdGV4dHVyZVxuICAgICAgICAvLyBFbmFibGUgdGV4dHVyZTBcbiAgICAgICAgdGhpcy5nbC5hY3RpdmVUZXh0dXJlKHRleHR1cmVJRCk7XG5cbiAgICAgICAgLy8gQmluZCBvdXIgdGV4dHVyZSB0byB0ZXh0dXJlIDBcbiAgICAgICAgdGhpcy5nbC5iaW5kVGV4dHVyZSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRleHR1cmUpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgdGV4dHVyZSBwYXJhbWV0ZXJzXG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCB0aGlzLmdsLkxJTkVBUik7XG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9XUkFQX1MsIHRoaXMuZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9XUkFQX1QsIHRoaXMuZ2wuQ0xBTVBfVE9fRURHRSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSB0ZXh0dXJlIGltYWdlXG4gICAgICAgIHRoaXMuZ2wudGV4SW1hZ2UyRCh0aGlzLmdsLlRFWFRVUkVfMkQsIDAsIHRoaXMuZ2wuUkdCQSwgdGhpcy5nbC5SR0JBLCB0aGlzLmdsLlVOU0lHTkVEX0JZVEUsIGltYWdlKTtcblxuICAgICAgICAvLyBBZGQgdGhlIHRleHR1cmUgdG8gb3VyIG1hcCB3aXRoIHRoZSBzYW1lIGtleSBhcyB0aGUgaW1hZ2VcbiAgICAgICAgdGhpcy5nbF9UZXh0dXJlcy5hZGQoaW1hZ2VLZXksIHRoaXMuZ2xfTmV4dFRleHR1cmVJRCk7XG5cbiAgICAgICAgLy8gSW5jcmVtZW50IHRoZSBrZXlcbiAgICAgICAgdGhpcy5nbF9OZXh0VGV4dHVyZUlEICs9IDE7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRUZXh0dXJlSUQoaWQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIC8vIFN0YXJ0IHdpdGggOSBjYXNlcyAtIHRoaXMgY2FuIGJlIGV4cGFuZGVkIGlmIG5lZWRlZCwgYnV0IGZvciB0aGUgYmVzdCBwZXJmb3JtYW5jZSxcbiAgICAgICAgLy8gVGV4dHVyZXMgc2hvdWxkIGJlIHN0aXRjaGVkIGludG8gYW4gYXRsYXNcbiAgICAgICAgc3dpdGNoIChpZCkge1xuICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gdGhpcy5nbC5URVhUVVJFMDtcbiAgICAgICAgICAgIGNhc2UgMTogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTE7XG4gICAgICAgICAgICBjYXNlIDI6IHJldHVybiB0aGlzLmdsLlRFWFRVUkUyO1xuICAgICAgICAgICAgY2FzZSAzOiByZXR1cm4gdGhpcy5nbC5URVhUVVJFMztcbiAgICAgICAgICAgIGNhc2UgNDogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTQ7XG4gICAgICAgICAgICBjYXNlIDU6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU1O1xuICAgICAgICAgICAgY2FzZSA2OiByZXR1cm4gdGhpcy5nbC5URVhUVVJFNjtcbiAgICAgICAgICAgIGNhc2UgNzogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTc7XG4gICAgICAgICAgICBjYXNlIDg6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU4O1xuICAgICAgICAgICAgZGVmYXVsdDogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlQnVmZmVyKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICBsZXQgYnVmZmVyID0gdGhpcy5nbC5jcmVhdGVCdWZmZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5nbF9CdWZmZXJzLmFkZChrZXksIGJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbnF1ZXVlcyBsb2FkaW5nIG9mIGEgbmV3IHNoYWRlciBwcm9ncmFtXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBzaGFkZXIgcHJvZ3JhbVxuICAgICAqIEBwYXJhbSB2U2hhZGVyRmlsZXBhdGggXG4gICAgICogQHBhcmFtIGZTaGFkZXJGaWxlcGF0aCBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2hhZGVyKGtleTogc3RyaW5nLCB2U2hhZGVyRmlsZXBhdGg6IHN0cmluZywgZlNoYWRlckZpbGVwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgbGV0IHNwbGl0UGF0aCA9IHZTaGFkZXJGaWxlcGF0aC5zcGxpdChcIi5cIik7XG4gICAgICAgIGxldCBlbmQgPSBzcGxpdFBhdGhbc3BsaXRQYXRoLmxlbmd0aCAtIDFdO1xuXG4gICAgICAgIGlmIChlbmQgIT09IFwidnNoYWRlclwiKSB7XG4gICAgICAgICAgICB0aHJvdyBgJHt2U2hhZGVyRmlsZXBhdGh9IGlzIG5vdCBhIHZhbGlkIHZlcnRleCBzaGFkZXIgLSBtdXN0IGVuZCBpbiBcIi52c2hhZGVyYDtcbiAgICAgICAgfVxuXG4gICAgICAgIHNwbGl0UGF0aCA9IGZTaGFkZXJGaWxlcGF0aC5zcGxpdChcIi5cIik7XG4gICAgICAgIGVuZCA9IHNwbGl0UGF0aFtzcGxpdFBhdGgubGVuZ3RoIC0gMV07XG5cbiAgICAgICAgaWYgKGVuZCAhPT0gXCJmc2hhZGVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IGAke2ZTaGFkZXJGaWxlcGF0aH0gaXMgbm90IGEgdmFsaWQgdmVydGV4IHNoYWRlciAtIG11c3QgZW5kIGluIFwiLmZzaGFkZXJgO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHBhdGhzID0gbmV3IEtleVBhdGhfU2hhZGVyKCk7XG4gICAgICAgIHBhdGhzLmtleSA9IGtleTtcbiAgICAgICAgcGF0aHMudnBhdGggPSB2U2hhZGVyRmlsZXBhdGg7XG4gICAgICAgIHBhdGhzLmZwYXRoID0gZlNoYWRlckZpbGVwYXRoO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyTG9hZGluZ1F1ZXVlLmVucXVldWUocGF0aHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcFNoYWRlcihrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmtlZXBSZXNvdXJjZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnbF9Mb2FkU2hhZGVyc0Zyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNUb0xvYWQgPSB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIHdlYkdMIGlzbidhY3RpdmUgb3IgdGhlcmUgYXJlIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICghdGhpcy5nbF9XZWJHTEFjdGl2ZSB8fCB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgc2hhZGVyID0gdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5nbF9Mb2FkU2hhZGVyKHNoYWRlci5rZXksIHNoYWRlci52cGF0aCwgc2hhZGVyLmZwYXRoLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnbF9Mb2FkU2hhZGVyKGtleTogc3RyaW5nLCB2cGF0aDogc3RyaW5nLCBmcGF0aDogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUodnBhdGgsICh2RmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3QgdlNoYWRlciA9IHZGaWxlVGV4dDtcblxuICAgICAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUoZnBhdGgsIChmRmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZTaGFkZXIgPSBmRmlsZVRleHRcblxuICAgICAgICAgICAgICAgIC8vIEV4dHJhY3QgdGhlIHByb2dyYW0gYW5kIHNoYWRlcnNcbiAgICAgICAgICAgICAgICBjb25zdCBbc2hhZGVyUHJvZ3JhbSwgdmVydGV4U2hhZGVyLCBmcmFnbWVudFNoYWRlcl0gPSB0aGlzLmNyZWF0ZVNoYWRlclByb2dyYW0odlNoYWRlciwgZlNoYWRlcik7XG5cbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSB3cmFwcGVyIHR5cGVcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9ncmFtV3JhcHBlciA9IG5ldyBXZWJHTFByb2dyYW1UeXBlKCk7XG4gICAgICAgICAgICAgICAgcHJvZ3JhbVdyYXBwZXIucHJvZ3JhbSA9IHNoYWRlclByb2dyYW07XG4gICAgICAgICAgICAgICAgcHJvZ3JhbVdyYXBwZXIudmVydGV4U2hhZGVyID0gdmVydGV4U2hhZGVyO1xuICAgICAgICAgICAgICAgIHByb2dyYW1XcmFwcGVyLmZyYWdtZW50U2hhZGVyID0gZnJhZ21lbnRTaGFkZXI7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgdG8gb3VyIG1hcFxuICAgICAgICAgICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMuYWRkKGtleSwgcHJvZ3JhbVdyYXBwZXIpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5TSEFERVIpKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nXG4gICAgICAgICAgICAgICAgdGhpcy5nbF9GaW5pc2hMb2FkaW5nU2hhZGVyKGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdsX0ZpbmlzaExvYWRpbmdTaGFkZXIoY2FsbGJhY2s6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc0xvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc1RvTG9hZCkge1xuICAgICAgICAgICAgLy8gV2UncmUgZG9uZSBsb2FkaW5nIHNoYWRlcnNcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVNoYWRlclByb2dyYW0odlNoYWRlclNvdXJjZTogc3RyaW5nLCBmU2hhZGVyU291cmNlOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgdmVydGV4U2hhZGVyID0gdGhpcy5sb2FkVmVydGV4U2hhZGVyKHZTaGFkZXJTb3VyY2UpO1xuICAgICAgICBjb25zdCBmcmFnbWVudFNoYWRlciA9IHRoaXMubG9hZEZyYWdtZW50U2hhZGVyKGZTaGFkZXJTb3VyY2UpO1xuXG4gICAgICAgIGlmICh2ZXJ0ZXhTaGFkZXIgPT09IG51bGwgfHwgZnJhZ21lbnRTaGFkZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFdlIGhhZCBhIHByb2JsZW0gaW50aWFsaXppbmcgLSBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgYSBzaGFkZXIgcHJvZ3JhbVxuICAgICAgICBjb25zdCBwcm9ncmFtID0gdGhpcy5nbC5jcmVhdGVQcm9ncmFtKCk7XG4gICAgICAgIGlmICghcHJvZ3JhbSkge1xuICAgICAgICAgICAgLy8gRXJyb3IgY3JlYXRpbmdcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkZhaWxlZCB0byBjcmVhdGUgcHJvZ3JhbVwiKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXR0YWNoIG91ciB2ZXJ0ZXggYW5kIGZyYWdtZW50IHNoYWRlclxuICAgICAgICB0aGlzLmdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCB2ZXJ0ZXhTaGFkZXIpO1xuICAgICAgICB0aGlzLmdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCBmcmFnbWVudFNoYWRlcik7XG5cbiAgICAgICAgLy8gTGlua1xuICAgICAgICB0aGlzLmdsLmxpbmtQcm9ncmFtKHByb2dyYW0pO1xuICAgICAgICBpZiAoIXRoaXMuZ2wuZ2V0UHJvZ3JhbVBhcmFtZXRlcihwcm9ncmFtLCB0aGlzLmdsLkxJTktfU1RBVFVTKSkge1xuICAgICAgICAgICAgLy8gRXJyb3IgbGlua2luZ1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmdsLmdldFByb2dyYW1JbmZvTG9nKHByb2dyYW0pO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiRmFpbGVkIHRvIGxpbmsgcHJvZ3JhbTogXCIgKyBlcnJvcik7XG5cbiAgICAgICAgICAgIC8vIENsZWFuIHVwXG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbSk7XG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVNoYWRlcih2ZXJ0ZXhTaGFkZXIpO1xuICAgICAgICAgICAgdGhpcy5nbC5kZWxldGVTaGFkZXIoZnJhZ21lbnRTaGFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXZSBzdWNjZXNzZnVsbHkgY3JlYXRlIGEgcHJvZ3JhbVxuICAgICAgICByZXR1cm4gW3Byb2dyYW0sIHZlcnRleFNoYWRlciwgZnJhZ21lbnRTaGFkZXJdO1xuICAgIH1cblxuICAgIHByaXZhdGUgbG9hZFZlcnRleFNoYWRlcihzaGFkZXJTb3VyY2U6IHN0cmluZyk6IFdlYkdMU2hhZGVyIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHZlcnRleCBzaGFkZXJcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZFNoYWRlcih0aGlzLmdsLlZFUlRFWF9TSEFERVIsIHNoYWRlclNvdXJjZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkRnJhZ21lbnRTaGFkZXIoc2hhZGVyU291cmNlOiBzdHJpbmcpOiBXZWJHTFNoYWRlciB7XG4gICAgICAgIC8vIENyZWF0ZSBhIG5ldyBmcmFnbWVudCBzaGFkZXJcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZFNoYWRlcih0aGlzLmdsLkZSQUdNRU5UX1NIQURFUiwgc2hhZGVyU291cmNlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRTaGFkZXIodHlwZTogbnVtYmVyLCBzaGFkZXJTb3VyY2U6IHN0cmluZyk6IFdlYkdMU2hhZGVyIHtcbiAgICAgICAgY29uc3Qgc2hhZGVyID0gdGhpcy5nbC5jcmVhdGVTaGFkZXIodHlwZSk7XG5cbiAgICAgICAgLy8gSWYgd2UgY291bGRuJ3QgY3JlYXRlIHRoZSBzaGFkZXIsIGVycm9yXG4gICAgICAgIGlmIChzaGFkZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlVuYWJsZSB0byBjcmVhdGUgc2hhZGVyXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIHNvdXJjZSB0byB0aGUgc2hhZGVyIGFuZCBjb21waWxlXG4gICAgICAgIHRoaXMuZ2wuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyU291cmNlKTtcbiAgICAgICAgdGhpcy5nbC5jb21waWxlU2hhZGVyKHNoYWRlcik7XG5cbiAgICAgICAgLy8gTWFrZSBzdXJlIHRoZXJlIHdlcmUgbm8gZXJyb3JzIGR1cmluZyB0aGlzIHByb2Nlc3NcbiAgICAgICAgaWYgKCF0aGlzLmdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIHRoaXMuZ2wuQ09NUElMRV9TVEFUVVMpKSB7XG4gICAgICAgICAgICAvLyBOb3QgY29tcGlsZWQgLSBlcnJvclxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmdsLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkZhaWxlZCB0byBjb21waWxlIHNoYWRlcjogXCIgKyBlcnJvcik7XG5cbiAgICAgICAgICAgIC8vIENsZWFuIHVwXG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdWNlc3MsIHNvIHJldHVybiB0aGUgc2hhZGVyXG4gICAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyBHRU5FUkFMIExPQURJTkcgRlVOQ1RJT05TICMjIyMjIyMjIyMgKi9cblxuICAgIHByaXZhdGUgbG9hZFRleHRGaWxlKHRleHRGaWxlUGF0aDogc3RyaW5nLCBjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgbGV0IHhvYmo6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgIHhvYmoub3ZlcnJpZGVNaW1lVHlwZShcImFwcGxpY2F0aW9uL2pzb25cIik7XG4gICAgICAgIHhvYmoub3BlbignR0VUJywgdGV4dEZpbGVQYXRoLCB0cnVlKTtcbiAgICAgICAgeG9iai5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoKHhvYmoucmVhZHlTdGF0ZSA9PSA0KSAmJiAoeG9iai5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHhvYmoucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgeG9iai5zZW5kKG51bGwpO1xuICAgIH1cblxuICAgIC8qICMjIyMjIyMjIyMgTE9BRElORyBCQVIgSU5GTyAjIyMjIyMjIyMjICovXG5cbiAgICBwcml2YXRlIGdldExvYWRQZXJjZW50KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiAodGhpcy5sb2Fkb25seV90aWxlbWFwc0xvYWRlZCAvIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWRcbiAgICAgICAgICAgICsgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgLyB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZFxuICAgICAgICAgICAgKyB0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCAvIHRoaXMubG9hZG9ubHlfaW1hZ2VzVG9Mb2FkXG4gICAgICAgICAgICArIHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkZWQgLyB0aGlzLmxvYWRvbmx5X2F1ZGlvVG9Mb2FkKVxuICAgICAgICAgICAgLyB0aGlzLmxvYWRvbmx5X3R5cGVzVG9Mb2FkO1xuICAgIH1cblxuICAgIC8vIEN1c3RvbWl6ZWQgZnVudGlvbnMgYmVsb3dcbiAgICAvLyBUaGVzZSBmdW50aW9ucyBhcmUgTk9UIHdlbGwgdGVzdGVkISEhXG4gICAgLy8gT25seSB1c2VkIGZvciBzaGF0dGVyZWQgc3dvcmQgc3BlY2lmaWMgcHVycG9zZSEhIVxuICAgIC8vIFVzZSB0aGVtIGNhcmVmdWxseSEhIVxuXG4gICAgcHVibGljIHRpbGVtYXBGcm9tT2JqZWN0KGtleTogc3RyaW5nLCB0aWxlbWFwOiBUaWxlZFRpbGVtYXBEYXRhKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIG1hcDogdGlsZW1hcCB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRUaWxlbWFwT2JqZWN0RnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkID0gdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGluZ1F1ZXVlLmdldFNpemUoKTtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IG1hcCA9IHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRUaWxlbWFwRnJvbU9iamVjdChtYXAua2V5LCBtYXAubWFwLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkVGlsZW1hcEZyb21PYmplY3Qoa2V5OiBzdHJpbmcsIHRpbGVkTWFwOiBUaWxlZFRpbGVtYXBEYXRhLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgLy8gV2UgY2FuIHBhcnNlIHRoZSBvYmplY3QgbGF0ZXIgLSBpdCdzIG11Y2ggZmFzdGVyIHRoYW4gbG9hZGluZ1xuXG4gICAgICAgIHRoaXMudGlsZW1hcHMuYWRkKGtleSwgdGlsZWRNYXApO1xuICAgICAgICBsZXQgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuVElMRU1BUCk7XG5cbiAgICAgICAgLy8gR3JhYiB0aGUgdGlsZXNldCBpbWFnZXMgd2UgbmVlZCB0byBsb2FkIGFuZCBhZGQgdGhlbSB0byB0aGUgaW1hZ2Vsb2FkaW5nIHF1ZXVlXG4gICAgICAgIGZvciAobGV0IHRpbGVzZXQgb2YgdGlsZWRNYXAudGlsZXNldHMpIHtcbiAgICAgICAgICAgIGlmICh0aWxlc2V0LmltYWdlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGtleSA9IHRpbGVzZXQuaW1hZ2U7XG4gICAgICAgICAgICAgICAgbGV0IHBhdGggPSBrZXk7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZUxvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIHBhdGg6IHBhdGgsIGlzRGVwZW5kZW5jeTogdHJ1ZSB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGltYWdlIGFzIGEgZGVwZW5kZW5jeSB0byB0aGUgdGlsZW1hcFxuICAgICAgICAgICAgICAgIHJlc291cmNlLmFkZERlcGVuZGVuY3kobmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLklNQUdFKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIHJlc291cmNlIHJlZmVyZW5jZSB0byB0aGUgbGlzdCBvZiByZXNvdXJjZSB0byB1bmxvYWRcbiAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKHJlc291cmNlKTtcblxuICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdUaWxlbWFwT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdUaWxlbWFwT2JqZWN0KGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyB0aWxlbWFwc1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzaW5nbGVJbWFnZShrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQWRkIHRvIGxvYWRlZCBpbWFnZXNcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VzLmFkZChrZXksIGltYWdlKTtcblxuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuXG4gICAgICAgICAgICAvLyBJZiBXZWJHTCBpcyBhY3RpdmUsIGNyZWF0ZSBhIHRleHR1cmVcbiAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVXZWJHTFRleHR1cmUoa2V5LCBpbWFnZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZpbmlzaCBpbWFnZSBsb2FkXG4gICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdTaW5nbGVPYmplY3QoY2FsbGJhY2tJZkxhc3QpO1xuICAgICAgICB9XG4gICAgICAgIGltYWdlLnNyYyA9IHBhdGg7XG4gICAgfVxuXG4gICAgcHVibGljIHNpbmdsZUF1ZGlvKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGNhbGxiYWNrSWZMYXN0OiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICBsZXQgYXVkaW9DdHggPSBBdWRpb01hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRBdWRpb0NvbnRleHQoKTtcblxuICAgICAgICBsZXQgcmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICByZXF1ZXN0Lm9wZW4oJ0dFVCcsIHBhdGgsIHRydWUpO1xuICAgICAgICByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7XG5cbiAgICAgICAgcmVxdWVzdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICBhdWRpb0N0eC5kZWNvZGVBdWRpb0RhdGEocmVxdWVzdC5yZXNwb25zZSwgKGJ1ZmZlcikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEFkZCB0byBsaXN0IG9mIGF1ZGlvIGJ1ZmZlcnNcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQnVmZmVycy5hZGQoa2V5LCBidWZmZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuQVVESU8pKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nIHNvdW5kXG4gICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nU2luZ2xlT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRocm93IFwiRXJyb3IgbG9hZGluZyBzb3VuZFwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVxdWVzdC5zZW5kKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nU2luZ2xlT2JqZWN0KGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5sb2FkaW5nKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vbkxvYWRQcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIHRoaXMub25Mb2FkUHJvZ3Jlc3ModGhpcy5nZXRMb2FkUGVyY2VudCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmp1c3RMb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuanVzdExvYWRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMub25Mb2FkQ29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uTG9hZENvbXBsZXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQSBjbGFzcyByZXByZXNlbnRpbmcgYSByZWZlcmVuY2UgdG8gYSByZXNvdXJjZS5cbiAqIFRoaXMgaXMgdXNlZCBmb3IgdGhlIGV4ZW1wdGlvbiBsaXN0IHRvIGFzc3VyZSBhc3NldHMgYW5kIHRoZWlyIGRlcGVuZGVuY2llcyBkb24ndCBnZXRcbiAqIGRlc3Ryb3llZCBpZiB0aGV5IGFyZSBzdGlsbCBuZWVkZWQuXG4gKi9cbmNsYXNzIFJlc291cmNlUmVmZXJlbmNlIHtcbiAgICBrZXk6IHN0cmluZztcbiAgICByZXNvdXJjZVR5cGU6IFJlc291cmNlVHlwZTtcbiAgICBkZXBlbmRlbmNpZXM6IEFycmF5PFJlc291cmNlUmVmZXJlbmNlPjtcblxuICAgIGNvbnN0cnVjdG9yKGtleTogc3RyaW5nLCByZXNvdXJjZVR5cGU6IFJlc291cmNlVHlwZSkge1xuICAgICAgICB0aGlzLmtleSA9IGtleTtcbiAgICAgICAgdGhpcy5yZXNvdXJjZVR5cGUgPSByZXNvdXJjZVR5cGU7XG4gICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgYWRkRGVwZW5kZW5jeShyZXNvdXJjZTogUmVzb3VyY2VSZWZlcmVuY2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMucHVzaChyZXNvdXJjZSk7XG4gICAgfVxufVxuXG5cbmVudW0gUmVzb3VyY2VUeXBlIHtcbiAgICBJTUFHRSA9IFwiSU1BR0VcIixcbiAgICBUSUxFTUFQID0gXCJUSUxFTUFQXCIsXG4gICAgU1BSSVRFU0hFRVQgPSBcIlNQUklURVNIRUVUXCIsXG4gICAgQVVESU8gPSBcIkFVRElPXCIsXG4gICAgSlNPTiA9IFwiSlNPTlwiLFxuICAgIFNIQURFUiA9IFwiU0hBREVSXCJcbn1cblxuLyoqXG4gKiBBIHBhaXIgcmVwcmVzZW50aW5nIGEga2V5IGFuZCB0aGUgcGF0aCBvZiB0aGUgcmVzb3VyY2UgdG8gbG9hZFxuICovXG5jbGFzcyBLZXlQYXRoUGFpciB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIGlzRGVwZW5kZW5jeT86IGJvb2xlYW4gPSBmYWxzZTtcbn1cblxuY2xhc3MgS2V5TWFwUGFpciB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgbWFwOiBUaWxlZFRpbGVtYXBEYXRhO1xufVxuXG5jbGFzcyBLZXlQYXRoX1NoYWRlciB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgdnBhdGg6IHN0cmluZztcbiAgICBmcGF0aDogc3RyaW5nO1xufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCB7IEdyYXBoaWNUeXBlIH0gZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlc1wiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBTbGlkZXIgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvU2xpZGVyXCI7XG5pbXBvcnQgVGV4dElucHV0IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1RleHRJbnB1dFwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBMaW5lIGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9MaW5lXCI7XG5pbXBvcnQgUGFydGljbGUgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1BhcnRpY2xlXCI7XG5cbi8vIEBpZ25vcmVQYWdlXG5cbi8qKlxuICogQSBmYWN0b3J5IHRoYXQgYWJzdHJhY3RzIGFkZGluZyBAcmVmZXJlbmNlW0NhbnZhc05vZGVdcyB0byB0aGUgQHJlZmVyZW5jZVtTY2VuZV0uXG4gKiBBY2Nlc3MgbWV0aG9kcyBpbiB0aGlzIGZhY3RvcnkgdGhyb3VnaCBTY2VuZS5hZGQuW21ldGhvZE5hbWVdKCkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhbnZhc05vZGVGYWN0b3J5IHtcblx0cHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcblx0cHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG5cdGluaXQoc2NlbmU6IFNjZW5lKTogdm9pZCB7XG5cdFx0dGhpcy5zY2VuZSA9IHNjZW5lO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhbiBpbnN0YW5jZSBvZiBhIFVJRWxlbWVudCB0byB0aGUgY3VycmVudCBzY2VuZSAtIGkuZS4gYW55IGNsYXNzIHRoYXQgZXh0ZW5kcyBVSUVsZW1lbnRcblx0ICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgb2YgVUlFbGVtZW50IHRvIGFkZFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciB0byBhZGQgdGhlIFVJRWxlbWVudCB0b1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gZmVlZCB0byB0aGUgY29uc3RydWN0b3Jcblx0ICogQHJldHVybnMgQSBuZXcgVUlFbGVtZW50XG5cdCAqL1xuXHRhZGRVSUVsZW1lbnQgPSAodHlwZTogc3RyaW5nIHwgVUlFbGVtZW50VHlwZSwgbGF5ZXJOYW1lOiBzdHJpbmcsIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogVUlFbGVtZW50ID0+IHtcblx0XHQvLyBHZXQgdGhlIGxheWVyXG5cdFx0bGV0IGxheWVyID0gdGhpcy5zY2VuZS5nZXRMYXllcihsYXllck5hbWUpO1xuXG5cdFx0bGV0IGluc3RhbmNlOiBVSUVsZW1lbnQ7XG5cblx0XHRzd2l0Y2godHlwZSl7XG5cdFx0XHRjYXNlIFVJRWxlbWVudFR5cGUuQlVUVE9OOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRCdXR0b24ob3B0aW9ucyk7XG5cdFx0XHRicmVhaztcblx0XHRcdGNhc2UgVUlFbGVtZW50VHlwZS5MQUJFTDpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkTGFiZWwob3B0aW9ucyk7XG5cdFx0XHRicmVhaztcblx0XHRcdGNhc2UgVUlFbGVtZW50VHlwZS5TTElERVI6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZFNsaWRlcihvcHRpb25zKTtcblx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBVSUVsZW1lbnRUeXBlLlRFWFRfSU5QVVQ6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZFRleHRJbnB1dChvcHRpb25zKTtcblx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0dGhyb3cgYFVJRWxlbWVudFR5cGUgJyR7dHlwZX0nIGRvZXMgbm90IGV4aXN0LCBvciBpcyByZWdpc3RlcmVkIGluY29ycmVjdGx5LmBcblx0XHR9XG5cblx0XHRpbnN0YW5jZS5zZXRTY2VuZSh0aGlzLnNjZW5lKTtcblx0XHRpbnN0YW5jZS5pZCA9IHRoaXMuc2NlbmUuZ2VuZXJhdGVJZCgpO1xuXHRcdHRoaXMuc2NlbmUuZ2V0U2NlbmVHcmFwaCgpLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0Ly8gQWRkIGluc3RhbmNlIHRvIGxheWVyXG5cdFx0bGF5ZXIuYWRkTm9kZShpbnN0YW5jZSlcblxuXHRcdHJldHVybiBpbnN0YW5jZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgc3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBTcHJpdGVcblx0ICovXG5cdGFkZFNwcml0ZSA9IChrZXk6IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcpOiBTcHJpdGUgPT4ge1xuXHRcdGxldCBsYXllciA9IHRoaXMuc2NlbmUuZ2V0TGF5ZXIobGF5ZXJOYW1lKTtcblxuXHRcdGxldCBpbnN0YW5jZSA9IG5ldyBTcHJpdGUoa2V5KTtcblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBzY2VuZVxuXHRcdGluc3RhbmNlLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuXHRcdGluc3RhbmNlLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG5cblx0XHRpZighKHRoaXMuc2NlbmUuaXNQYXJhbGxheExheWVyKGxheWVyTmFtZSkgfHwgdGhpcy5zY2VuZS5pc1VJTGF5ZXIobGF5ZXJOYW1lKSkpe1xuXHRcdFx0dGhpcy5zY2VuZS5nZXRTY2VuZUdyYXBoKCkuYWRkTm9kZShpbnN0YW5jZSk7XG5cdFx0fVxuXHRcdFxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBsYXllclxuXHRcdGxheWVyLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0cmV0dXJuIGluc3RhbmNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYW4gQW5pbWF0ZWRTcHJpdGUgdG8gdGhlIGN1cnJlbnQgc2NlbmVcblx0ICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBpbWFnZSB0aGUgc3ByaXRlIHdpbGwgcmVwcmVzZW50XG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIG9uIHdoaWNoIHRvIGFkZCB0aGUgc3ByaXRlXG5cdCAqIEByZXR1cm5zIEEgbmV3IEFuaW1hdGVkU3ByaXRlXG5cdCAqL1xuXHRhZGRBbmltYXRlZFNwcml0ZSA9IChrZXk6IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcpOiBBbmltYXRlZFNwcml0ZSA9PiB7XG5cdFx0bGV0IGxheWVyID0gdGhpcy5zY2VuZS5nZXRMYXllcihsYXllck5hbWUpO1xuXHRcdGxldCBzcHJpdGVzaGVldCA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldFNwcml0ZXNoZWV0KGtleSk7XG5cdFx0bGV0IGluc3RhbmNlID0gbmV3IEFuaW1hdGVkU3ByaXRlKHNwcml0ZXNoZWV0KTtcblxuXHRcdC8vIEFkZCBpbnN0YW5jZSBmbyBzY2VuZVxuXHRcdGluc3RhbmNlLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuXHRcdGluc3RhbmNlLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG5cdFx0XG5cdFx0aWYoISh0aGlzLnNjZW5lLmlzUGFyYWxsYXhMYXllcihsYXllck5hbWUpIHx8IHRoaXMuc2NlbmUuaXNVSUxheWVyKGxheWVyTmFtZSkpKXtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0U2NlbmVHcmFwaCgpLmFkZE5vZGUoaW5zdGFuY2UpO1xuXHRcdH1cblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBsYXllclxuXHRcdGxheWVyLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0cmV0dXJuIGluc3RhbmNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBuZXcgZ3JhcGhpYyBlbGVtZW50IHRvIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9mIGdyYXBoaWMgdG8gYWRkXG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIG9uIHdoaWNoIHRvIGFkZCB0aGUgZ3JhcGhpY1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgZ3JhcGhpYyBjb25zdHJ1Y3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBHcmFwaGljXG5cdCAqL1xuXHRhZGRHcmFwaGljID0gKHR5cGU6IEdyYXBoaWNUeXBlIHwgc3RyaW5nLCBsYXllck5hbWU6IHN0cmluZywgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBHcmFwaGljID0+IHtcblx0XHQvLyBHZXQgdGhlIGxheWVyXG5cdFx0bGV0IGxheWVyID0gdGhpcy5zY2VuZS5nZXRMYXllcihsYXllck5hbWUpO1xuXG5cdFx0bGV0IGluc3RhbmNlOiBHcmFwaGljO1xuXG5cdFx0c3dpdGNoKHR5cGUpe1xuXHRcdFx0Y2FzZSBHcmFwaGljVHlwZS5QT0lOVDpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkUG9pbnQob3B0aW9ucyk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBHcmFwaGljVHlwZS5MSU5FOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRMaW5lKG9wdGlvbnMpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgR3JhcGhpY1R5cGUuUkVDVDpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkUmVjdChvcHRpb25zKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIEdyYXBoaWNUeXBlLlBBUlRJQ0xFOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRQYXJ0aWNsZShvcHRpb25zKTtcblx0XHRcdFx0YnJlYWs7XHRcdFx0XHRcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHRocm93IGBHcmFwaGljVHlwZSAnJHt0eXBlfScgZG9lcyBub3QgZXhpc3QsIG9yIGlzIHJlZ2lzdGVyZWQgaW5jb3JyZWN0bHkuYFxuXHRcdH1cblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBzY2VuZVxuXHRcdGluc3RhbmNlLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuXHRcdGluc3RhbmNlLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG5cblx0XHRpZighKHRoaXMuc2NlbmUuaXNQYXJhbGxheExheWVyKGxheWVyTmFtZSkgfHwgdGhpcy5zY2VuZS5pc1VJTGF5ZXIobGF5ZXJOYW1lKSkpe1xuXHRcdFx0dGhpcy5zY2VuZS5nZXRTY2VuZUdyYXBoKCkuYWRkTm9kZShpbnN0YW5jZSk7XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIGluc3RhbmNlIHRvIGxheWVyXG5cdFx0bGF5ZXIuYWRkTm9kZShpbnN0YW5jZSk7XG5cblx0XHRyZXR1cm4gaW5zdGFuY2U7XG5cdH1cblxuXHQvKiAtLS0tLS0tLS0tIEJVSUxERVJTIC0tLS0tLS0tLS0gKi9cblxuXHRidWlsZEJ1dHRvbihvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IEJ1dHRvbiB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIkJ1dHRvblwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiQnV0dG9uXCIsIG9wdGlvbnMsIFwidGV4dFwiLCBcInN0cmluZ1wiKTtcblxuXHRcdHJldHVybiBuZXcgQnV0dG9uKG9wdGlvbnMucG9zaXRpb24sIG9wdGlvbnMudGV4dCk7XG5cdH1cblxuXHRidWlsZExhYmVsKG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogTGFiZWwge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJMYWJlbFwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGFiZWxcIiwgb3B0aW9ucywgXCJ0ZXh0XCIsIFwic3RyaW5nXCIpO1xuXG5cdFx0cmV0dXJuIG5ldyBMYWJlbChvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLnRleHQpXG5cdH1cblxuXHRidWlsZFNsaWRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogU2xpZGVyIHtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiU2xpZGVyXCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXG5cdFx0bGV0IGluaXRWYWx1ZSA9IDA7XG5cdFx0aWYob3B0aW9ucy52YWx1ZSAhPT0gdW5kZWZpbmVkKXtcblx0XHRcdGluaXRWYWx1ZSA9IG9wdGlvbnMudmFsdWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBTbGlkZXIob3B0aW9ucy5wb3NpdGlvbiwgaW5pdFZhbHVlKTtcblx0fVxuXG5cdGJ1aWxkVGV4dElucHV0KG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBUZXh0SW5wdXQge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJUZXh0SW5wdXRcIiwgb3B0aW9ucywgXCJwb3NpdGlvblwiLCBWZWMyLCBcIlZlYzJcIik7XG5cblx0XHRyZXR1cm4gbmV3IFRleHRJbnB1dChvcHRpb25zLnBvc2l0aW9uKTtcblx0fVxuXG5cdGJ1aWxkUG9pbnQob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQb2ludCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlBvaW50XCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXG5cdFx0cmV0dXJuIG5ldyBQb2ludChvcHRpb25zLnBvc2l0aW9uKTtcblx0fVxuXG5cdGJ1aWxkUGFydGljbGUob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQb2ludCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlBhcnRpY2xlXCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJQYXJ0aWNsZVwiLCBvcHRpb25zLCBcInNpemVcIiwgVmVjMiwgXCJWZWMyXCIpO1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJQYXJ0aWNsZVwiLCBvcHRpb25zLCBcIm1hc3NcIiwgXCJudW1iZXJcIiwgXCJudW1iZXJcIik7XG5cblx0XHQvL0NoYW5nZWQgZm9yIHRlc3Rpbmdcblx0XHRyZXR1cm4gbmV3IFBhcnRpY2xlKG9wdGlvbnMucG9zaXRpb24sIG9wdGlvbnMuc2l6ZSwgb3B0aW9ucy5tYXNzKTtcblx0fVxuXG5cdGJ1aWxkTGluZShvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IFBvaW50IHtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGluZVwiLCBvcHRpb25zLCBcInN0YXJ0XCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGluZVwiLCBvcHRpb25zLCBcImVuZFwiLCBWZWMyLCBcIlZlYzJcIik7XG5cblx0XHRyZXR1cm4gbmV3IExpbmUob3B0aW9ucy5zdGFydCwgb3B0aW9ucy5lbmQpO1xuXHR9XG5cblx0YnVpbGRSZWN0KG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogUmVjdCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlJlY3RcIiwgb3B0aW9ucywgXCJwb3NpdGlvblwiLCBWZWMyLCBcIlZlYzJcIik7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlJlY3RcIiwgb3B0aW9ucywgXCJzaXplXCIsIFZlYzIsIFwiVmVjMlwiKTtcblxuXHRcdHJldHVybiBuZXcgUmVjdChvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLnNpemUpO1xuXHR9XG5cblx0LyogLS0tLS0tLS0tLSBFUlJPUiBIQU5ETElORyAtLS0tLS0tLS0tICovXG5cblx0Y2hlY2tJZlByb3BFeGlzdHM8VD4ob2JqZWN0TmFtZTogc3RyaW5nLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBwcm9wOiBzdHJpbmcsIHR5cGU6IChuZXcgKC4uLmFyZ3M6IGFueSkgPT4gVCkgfCBzdHJpbmcsIHR5cGVOYW1lPzogc3RyaW5nKXtcblx0XHRpZighb3B0aW9ucyB8fCBvcHRpb25zW3Byb3BdID09PSB1bmRlZmluZWQpe1xuXHRcdFx0Ly8gQ2hlY2sgdGhhdCB0aGUgb3B0aW9ucyBvYmplY3QgaGFzIHRoZSBwcm9wZXJ0eVxuXHRcdFx0dGhyb3cgYCR7b2JqZWN0TmFtZX0gb2JqZWN0IHJlcXVpcmVzIGFyZ3VtZW50ICR7cHJvcH0gb2YgdHlwZSAke3R5cGVOYW1lfSwgYnV0IG5vbmUgd2FzIHByb3ZpZGVkLmA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIENoZWNrIHRoYXQgdGhlIHByb3BlcnR5IGhhcyB0aGUgY29ycmVjdCB0eXBlXG5cdFx0XHRpZigodHlwZW9mIHR5cGUpID09PSBcInN0cmluZ1wiKXtcblx0XHRcdFx0aWYoISh0eXBlb2Ygb3B0aW9uc1twcm9wXSA9PT0gdHlwZSkpe1xuXHRcdFx0XHRcdHRocm93IGAke29iamVjdE5hbWV9IG9iamVjdCByZXF1aXJlcyBhcmd1bWVudCAke3Byb3B9IG9mIHR5cGUgJHt0eXBlfSwgYnV0IHByb3ZpZGVkICR7cHJvcH0gd2FzIG5vdCBvZiB0eXBlICR7dHlwZX0uYDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmKHR5cGUgaW5zdGFuY2VvZiBGdW5jdGlvbil7XG5cdFx0XHRcdC8vIElmIHR5cGUgaXMgYSBjb25zdHJ1Y3RvciwgY2hlY2sgYWdhaW5zdCB0aGF0XG5cdFx0XHRcdGlmKCEob3B0aW9uc1twcm9wXSBpbnN0YW5jZW9mIHR5cGUpKXtcblx0XHRcdFx0XHR0aHJvdyBgJHtvYmplY3ROYW1lfSBvYmplY3QgcmVxdWlyZXMgYXJndW1lbnQgJHtwcm9wfSBvZiB0eXBlICR7dHlwZU5hbWV9LCBidXQgcHJvdmlkZWQgJHtwcm9wfSB3YXMgbm90IG9mIHR5cGUgJHt0eXBlTmFtZX0uYDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhyb3cgYCR7b2JqZWN0TmFtZX0gb2JqZWN0IHJlcXVpcmVzIGFyZ3VtZW50ICR7cHJvcH0gb2YgdHlwZSAke3R5cGVOYW1lfSwgYnV0IHByb3ZpZGVkICR7cHJvcH0gd2FzIG5vdCBvZiB0eXBlICR7dHlwZU5hbWV9LmA7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZVwiO1xuaW1wb3J0IENhbnZhc05vZGVGYWN0b3J5IGZyb20gXCIuL0NhbnZhc05vZGVGYWN0b3J5XCI7XG5pbXBvcnQgVGlsZW1hcEZhY3RvcnkgZnJvbSBcIi4vVGlsZW1hcEZhY3RvcnlcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi8uLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCB7IEdyYXBoaWNUeXBlIH0gZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlc1wiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL0xheWVyXCI7XG5cbi8qKlxuICogVGhlIG1hbmFnZXIgb2YgYWxsIGZhY3RvcmllcyB1c2VkIGZvciBhZGRpbmcgQHJlZmVyZW5jZVtHYW1lTm9kZV1zIHRvIHRoZSBAcmVmZXJlbmNlW1NjZW5lXS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFjdG9yeU1hbmFnZXIge1xuXG4gICAgLy8gQ29uc3RydWN0b3JzIGFyZSBjYWxsZWQgaGVyZSB0byBhbGxvdyBhc3NpZ25tZW50IG9mIHRoZWlyIGZ1bmN0aW9ucyB0byBmdW5jdGlvbnMgaW4gdGhpcyBjbGFzc1xuICAgIHByaXZhdGUgY2FudmFzTm9kZUZhY3Rvcnk6IENhbnZhc05vZGVGYWN0b3J5ID0gbmV3IENhbnZhc05vZGVGYWN0b3J5KCk7XG4gICAgcHJpdmF0ZSB0aWxlbWFwRmFjdG9yeTogVGlsZW1hcEZhY3RvcnkgPSBuZXcgVGlsZW1hcEZhY3RvcnkoKTtcblxuICAgIGNvbnN0cnVjdG9yKHNjZW5lOiBTY2VuZSwgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+KXtcbiAgICAgICAgdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5pbml0KHNjZW5lKTtcbiAgICAgICAgdGhpcy50aWxlbWFwRmFjdG9yeS5pbml0KHNjZW5lLCB0aWxlbWFwcyk7XG4gICAgfVxuXG4gICAgLy8gRXhwb3NlIGFsbCBvZiB0aGUgZmFjdG9yaWVzIHRocm91Z2ggdGhlIGZhY3RvcnkgbWFuYWdlclxuICAgIC8qKlxuXHQgKiBBZGRzIGFuIGluc3RhbmNlIG9mIGEgVUlFbGVtZW50IHRvIHRoZSBjdXJyZW50IHNjZW5lIC0gaS5lLiBhbnkgY2xhc3MgdGhhdCBleHRlbmRzIFVJRWxlbWVudFxuXHQgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiBVSUVsZW1lbnQgdG8gYWRkXG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIHRvIGFkZCB0aGUgVUlFbGVtZW50IHRvXG5cdCAqIEBwYXJhbSBvcHRpb25zIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBmZWVkIHRvIHRoZSBjb25zdHJ1Y3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBVSUVsZW1lbnRcblx0ICovXG4gICAgdWlFbGVtZW50KHR5cGU6IHN0cmluZyB8IFVJRWxlbWVudFR5cGUsIGxheWVyTmFtZTogc3RyaW5nLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IFVJRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhc05vZGVGYWN0b3J5LmFkZFVJRWxlbWVudCh0eXBlLCBsYXllck5hbWUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBBZGRzIGEgc3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBTcHJpdGVcblx0ICovXG5cdHNwcml0ZShrZXk6IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcpOiBTcHJpdGUge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5hZGRTcHJpdGUoa2V5LCBsYXllck5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBBZGRzIGFuIEFuaW1hdGVkU3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBBbmltYXRlZFNwcml0ZVxuXHQgKi9cblx0YW5pbWF0ZWRTcHJpdGUoa2V5OiBzdHJpbmcsIGxheWVyTmFtZTogc3RyaW5nKTogQW5pbWF0ZWRTcHJpdGUge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5hZGRBbmltYXRlZFNwcml0ZShrZXksIGxheWVyTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG5cdCAqIEFkZHMgYSBuZXcgZ3JhcGhpYyBlbGVtZW50IHRvIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9mIGdyYXBoaWMgdG8gYWRkXG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIG9uIHdoaWNoIHRvIGFkZCB0aGUgZ3JhcGhpY1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgZ3JhcGhpYyBjb25zdHJ1Y3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBHcmFwaGljXG5cdCAqL1xuXHRncmFwaGljKHR5cGU6IEdyYXBoaWNUeXBlIHwgc3RyaW5nLCBsYXllck5hbWU6IHN0cmluZywgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBHcmFwaGljIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FudmFzTm9kZUZhY3RvcnkuYWRkR3JhcGhpYyh0eXBlLCBsYXllck5hbWUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSB0aWxlbWFwIHRvIHRoZSBzY2VuZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgbG9hZGVkIHRpbGVtYXAgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBjb25zdHIgVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBkZXNpcmVkIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gYXJncyBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBzZW5kIHRvIHRoZSB0aWxlbWFwIGNvbnN0cnVjdG9yXG4gICAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgTGF5ZXJzLCBlYWNoIG9mIHdoaWNoIGNvbnRhaW5zIGEgbGF5ZXIgb2YgdGhlIHRpbGVtYXAgYXMgaXRzIG93biBUaWxlbWFwIGluc3RhbmNlLlxuICAgICAqL1xuXHR0aWxlbWFwKGtleTogc3RyaW5nLCBzY2FsZT86IFZlYzIpOiBBcnJheTxMYXllcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy50aWxlbWFwRmFjdG9yeS5hZGQoa2V5LCBzY2FsZSk7XG4gICAgfVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi8uLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL0xheWVyXCI7XG5pbXBvcnQgVGlsZXNldCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVzZXRcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgVGlsZWRDb2xsZWN0aW9uVGlsZSB9IGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFBvc2l0aW9uR3JhcGggZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9HcmFwaHMvUG9zaXRpb25HcmFwaFwiO1xuaW1wb3J0IE5hdm1lc2ggZnJvbSBcIi4uLy4uL1BhdGhmaW5kaW5nL05hdm1lc2hcIjtcblxuLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBBIGZhY3RvcnkgdGhhdCBhYnN0cmFjdHMgYWRkaW5nIEByZWZlcmVuY2VbVGlsZW1hcF1zIHRvIHRoZSBAcmVmZXJlbmNlW1NjZW5lXS5cbiAqIEFjY2VzcyBtZXRob2RzIGluIHRoaXMgZmFjdG9yeSB0aHJvdWdoIFNjZW5lLmFkZC5bbWV0aG9kTmFtZV0oKS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGlsZW1hcEZhY3Rvcnkge1xuICAgIHByaXZhdGUgc2NlbmU6IFNjZW5lO1xuICAgIHByaXZhdGUgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+O1xuICAgIHByaXZhdGUgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG4gICAgXG4gICAgaW5pdChzY2VuZTogU2NlbmUsIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPik6IHZvaWQge1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgICAgIHRoaXMudGlsZW1hcHMgPSB0aWxlbWFwcztcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPIC0gVGhpcyBpcyBzcGVjaWZpY2FsbHkgY2F0ZXJlZCB0byBUaWxlZCB0aWxlbWFwcyByaWdodCBub3cuIEluIHRoZSBmdXR1cmUsXG4gICAgLy8gaXQgd291bGQgYmUgZ29vZCB0byBoYXZlIGEgXCJwYXJzZVRpbGVtYXBcIiBmdW5jdGlvbiB0aGF0IHdvdWxkIGNvbnZlcnQgdGhlIHRpbGVtYXBcbiAgICAvLyBkYXRhIGludG8gYSBzdGFuZGFyZCBmb3JtYXQuIFRoaXMgY291bGQgYWxsb3cgZm9yIHN1cHBvcnQgZnJvbSBvdGhlciBwcm9ncmFtc1xuICAgIC8vIG9yIHRoZSBkZXZlbG9wbWVudCBvZiBhbiBpbnRlcm5hbCBsZXZlbCBidWlsZGVyIHRvb2xcbiAgICAvKipcbiAgICAgKiBBZGRzIGEgdGlsZW1hcCB0byB0aGUgc2NlbmVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBvZiB0aGUgZGVzaXJlZCB0aWxlbWFwXG4gICAgICogQHBhcmFtIGFyZ3MgQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgdGlsZW1hcCBjb25zdHJ1Y3RvclxuICAgICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIExheWVycywgZWFjaCBvZiB3aGljaCBjb250YWlucyBhIGxheWVyIG9mIHRoZSB0aWxlbWFwIGFzIGl0cyBvd24gVGlsZW1hcCBpbnN0YW5jZS5cbiAgICAgKi9cblx0YWRkID0gKGtleTogc3RyaW5nLCBzY2FsZTogVmVjMiA9IG5ldyBWZWMyKDEsIDEpKTogQXJyYXk8TGF5ZXI+ID0+IHtcbiAgICAgICAgLy8gR2V0IFRpbGVtYXAgRGF0YVxuICAgICAgICBsZXQgdGlsZW1hcERhdGEgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRUaWxlbWFwKGtleSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBjb25zdHJ1Y3RvciBmb3IgdGhpcyB0aWxlbWFwIHRvIGVpdGhlciBiZSBvcnRob2dyYXBoaWMgb3IgaXNvbWV0cmljXG4gICAgICAgIGxldCBjb25zdHI6IG5ldyguLi5hcmdzOiBhbnkpID0+IFRpbGVtYXA7XG4gICAgICAgIGlmKHRpbGVtYXBEYXRhLm9yaWVudGF0aW9uID09PSBcIm9ydGhvZ3JhcGhpY1wiKXtcbiAgICAgICAgICAgIGNvbnN0ciA9IE9ydGhvZ29uYWxUaWxlbWFwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm8gaXNvbWV0cmljIHRpbGVtYXAgc3VwcG9ydCByaWdodCBub3csIHNvIE9ydGhvZ3JhcGhpYyB0aWxlbWFwXG4gICAgICAgICAgICBjb25zdHIgPSBPcnRob2dvbmFsVGlsZW1hcDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHJldHVybiB2YWx1ZSBhcnJheVxuICAgICAgICBsZXQgc2NlbmVMYXllcnMgPSBuZXcgQXJyYXk8TGF5ZXI+KCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFsbCBvZiB0aGUgdGlsZXNldHMgZm9yIHRoaXMgdGlsZW1hcFxuICAgICAgICBsZXQgdGlsZXNldHMgPSBuZXcgQXJyYXk8VGlsZXNldD4oKTtcblxuICAgICAgICBsZXQgY29sbGVjdGlvblRpbGVzID0gbmV3IEFycmF5PFRpbGVkQ29sbGVjdGlvblRpbGU+KCk7XG5cbiAgICAgICAgZm9yKGxldCB0aWxlc2V0IG9mIHRpbGVtYXBEYXRhLnRpbGVzZXRzKXtcbiAgICAgICAgICAgIGlmKHRpbGVzZXQuaW1hZ2Upe1xuICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgYSBzdGFuZGFyZCB0aWxlc2V0IGFuZCBub3QgYSBjb2xsZWN0aW9uLCBjcmVhdGUgYSB0aWxlc2V0IGZvciBpdC5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIC0gV2UgYXJlIGlnbm9yaW5nIGNvbGxlY3Rpb24gdGlsZXNldHMgZm9yIG5vdy4gVGhpcyBpcyBsaWtlbHkgbm90IGEgZ3JlYXQgaWRlYSBpbiBwcmFjdGljZSxcbiAgICAgICAgICAgICAgICAvLyBhcyB0aGVvcmV0aWNhbGx5IHNvbWVvbmUgY291bGQgd2FudCB0byB1c2Ugb25lIGZvciBhIHN0YW5kYXJkIHRpbGVtYXAuIFdlIGFyZSBhc3N1bWluZyBmb3Igbm93XG4gICAgICAgICAgICAgICAgLy8gdGhhdCB3ZSBvbmx5IHdhbnQgdG8gdXNlIHRoZW0gZm9yIG9iamVjdCBsYXllcnNcbiAgICAgICAgICAgICAgICB0aWxlc2V0cy5wdXNoKG5ldyBUaWxlc2V0KHRpbGVzZXQpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGlsZXNldC50aWxlcy5mb3JFYWNoKHRpbGUgPT4gdGlsZS5pZCArPSB0aWxlc2V0LmZpcnN0Z2lkKTtcbiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uVGlsZXMucHVzaCguLi50aWxlc2V0LnRpbGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExvb3Agb3ZlciB0aGUgbGF5ZXJzIG9mIHRoZSB0aWxlbWFwIGFuZCBjcmVhdGUgdGlsZWRsYXllcnMgb3Igb2JqZWN0IGxheWVyc1xuICAgICAgICBmb3IobGV0IGxheWVyIG9mIHRpbGVtYXBEYXRhLmxheWVycyl7XG5cbiAgICAgICAgICAgIGxldCBzY2VuZUxheWVyO1xuICAgICAgICAgICAgbGV0IGlzUGFyYWxsYXhMYXllciA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGRlcHRoID0gMDtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYobGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgZm9yKGxldCBwcm9wIG9mIGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICBpZihwcm9wLm5hbWUgPT09IFwiUGFyYWxsYXhcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1BhcmFsbGF4TGF5ZXIgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIkRlcHRoXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaXNQYXJhbGxheExheWVyKXtcbiAgICAgICAgICAgICAgICBzY2VuZUxheWVyID0gdGhpcy5zY2VuZS5hZGRQYXJhbGxheExheWVyKGxheWVyLm5hbWUsIG5ldyBWZWMyKDEsIDEpLCBkZXB0aCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNjZW5lTGF5ZXIgPSB0aGlzLnNjZW5lLmFkZExheWVyKGxheWVyLm5hbWUsIGRlcHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYobGF5ZXIudHlwZSA9PT0gXCJ0aWxlbGF5ZXJcIil7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHRpbGVtYXAgb2JqZWN0IGZvciB0aGUgbGF5ZXJcbiAgICAgICAgICAgICAgICBsZXQgdGlsZW1hcCA9IG5ldyBjb25zdHIodGlsZW1hcERhdGEsIGxheWVyLCB0aWxlc2V0cywgc2NhbGUpO1xuICAgICAgICAgICAgICAgIHRpbGVtYXAuaWQgPSB0aGlzLnNjZW5lLmdlbmVyYXRlSWQoKTtcbiAgICAgICAgICAgICAgICB0aWxlbWFwLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuICAgIFxuICAgICAgICAgICAgICAgIC8vIEFkZCB0aWxlbWFwIHRvIHNjZW5lXG4gICAgICAgICAgICAgICAgdGhpcy50aWxlbWFwcy5wdXNoKHRpbGVtYXApO1xuICAgIFxuICAgICAgICAgICAgICAgIHNjZW5lTGF5ZXIuYWRkTm9kZSh0aWxlbWFwKTtcbiAgICBcbiAgICAgICAgICAgICAgICAvLyBSZWdpc3RlciB0aWxlbWFwIHdpdGggcGh5c2ljcyBpZiBpdCdzIGNvbGxpZGFibGVcbiAgICAgICAgICAgICAgICBpZih0aWxlbWFwLmlzQ29sbGlkYWJsZSl7XG4gICAgICAgICAgICAgICAgICAgIHRpbGVtYXAuYWRkUGh5c2ljcygpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpdGVtIG9mIGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGl0ZW0ubmFtZSA9PT0gXCJHcm91cFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcC5zZXRHcm91cChpdGVtLnZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgbGV0IGlzTmF2bWVzaFBvaW50cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxldCBuYXZtZXNoTmFtZTtcbiAgICAgICAgICAgICAgICBsZXQgZWRnZXM7XG4gICAgICAgICAgICAgICAgaWYobGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgcHJvcCBvZiBsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHByb3AubmFtZSA9PT0gXCJOYXZtZXNoUG9pbnRzXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzTmF2bWVzaFBvaW50cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIm5hbWVcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2bWVzaE5hbWUgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJlZGdlc1wiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlcyA9IHByb3AudmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZihpc05hdm1lc2hQb2ludHMpe1xuICAgICAgICAgICAgICAgICAgICBsZXQgZyA9IG5ldyBQb3NpdGlvbkdyYXBoKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBvYmogb2YgbGF5ZXIub2JqZWN0cyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBnLmFkZFBvc2l0aW9uZWROb2RlKG5ldyBWZWMyKG9iai54LCBvYmoueSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBlZGdlIG9mIGVkZ2VzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGcuYWRkRWRnZShlZGdlLmZyb20sIGVkZ2UudG8pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zY2VuZS5nZXROYXZpZ2F0aW9uTWFuYWdlcigpLmFkZE5hdmlnYWJsZUVudGl0eShuYXZtZXNoTmFtZSwgbmV3IE5hdm1lc2goZykpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIExheWVyIGlzIGFuIG9iamVjdCBsYXllciwgc28gYWRkIGVhY2ggb2JqZWN0IGFzIGEgc3ByaXRlIHRvIGEgbmV3IGxheWVyXG4gICAgICAgICAgICAgICAgZm9yKGxldCBvYmogb2YgbGF5ZXIub2JqZWN0cyl7XG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIG9iaiBpcyBjb2xsaWRhYmxlXG4gICAgICAgICAgICAgICAgICAgIGxldCBoYXNQaHlzaWNzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpc0NvbGxpZGFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGlzVHJpZ2dlciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb25FbnRlciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvbkV4aXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBsZXQgdHJpZ2dlckdyb3VwID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGdyb3VwID0gXCJcIjtcblxuICAgICAgICAgICAgICAgICAgICBpZihvYmoucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHByb3Agb2Ygb2JqLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHByb3AubmFtZSA9PT0gXCJIYXNQaHlzaWNzXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNQaHlzaWNzID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIkNvbGxpZGFibGVcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQ29sbGlkYWJsZSA9IHByb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJHcm91cFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiSXNUcmlnZ2VyXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RyaWdnZXIgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiVHJpZ2dlckdyb3VwXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyR3JvdXAgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiVHJpZ2dlck9uRW50ZXJcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uRW50ZXIgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiVHJpZ2dlck9uRXhpdFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25FeGl0ID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBsZXQgc3ByaXRlOiBTcHJpdGU7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgb2JqIGlzIGEgdGlsZSBmcm9tIGEgdGlsZXNldFxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHRpbGVzZXQgb2YgdGlsZXNldHMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGlsZXNldC5oYXNUaWxlKG9iai5naWQpKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgb2JqZWN0IGlzIGEgdGlsZSBmcm9tIHRoaXMgc2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGltYWdlS2V5ID0gdGlsZXNldC5nZXRJbWFnZUtleSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSB0aWxlc2V0LmdldEltYWdlT2Zmc2V0Rm9yVGlsZShvYmouZ2lkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUgPSB0aGlzLnNjZW5lLmFkZC5zcHJpdGUoaW1hZ2VLZXksIGxheWVyLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzaXplID0gdGlsZXNldC5nZXRUaWxlU2l6ZSgpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnBvc2l0aW9uLnNldCgob2JqLnggKyBzaXplLngvMikqc2NhbGUueCwgKG9iai55IC0gc2l6ZS55LzIpKnNjYWxlLnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zZXRJbWFnZU9mZnNldChvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zaXplLmNvcHkoc2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNjYWxlLnNldChzY2FsZS54LCBzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdCBpbiBhIHRpbGVzZXQsIG11c3QgY29ycmVzcG9uZCB0byBhIGNvbGxlY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgaWYoIXNwcml0ZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHRpbGUgb2YgY29sbGVjdGlvblRpbGVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihvYmouZ2lkID09PSB0aWxlLmlkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGltYWdlS2V5ID0gdGlsZS5pbWFnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlID0gdGhpcy5zY2VuZS5hZGQuc3ByaXRlKGltYWdlS2V5LCBsYXllci5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnBvc2l0aW9uLnNldCgob2JqLnggKyB0aWxlLmltYWdld2lkdGgvMikqc2NhbGUueCwgKG9iai55IC0gdGlsZS5pbWFnZWhlaWdodC8yKSpzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNjYWxlLnNldChzY2FsZS54LCBzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBOb3cgd2UgaGF2ZSBzcHJpdGUuIEFzc29jaWF0ZSBpdCB3aXRoIG91ciBwaHlzaWNzIG9iamVjdCBpZiB0aGVyZSBpcyBvbmVcbiAgICAgICAgICAgICAgICAgICAgaWYoaGFzUGh5c2ljcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIHRoZSBzcHJpdGUgYSBzdGF0aWMgcGh5c2ljcyBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5hZGRQaHlzaWNzKHNwcml0ZS5ib3VuZGFyeS5jbG9uZSgpLCBWZWMyLlpFUk8sIGlzQ29sbGlkYWJsZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUuc2V0R3JvdXAoZ3JvdXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaXNUcmlnZ2VyICYmIHRyaWdnZXJHcm91cCAhPT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNldFRyaWdnZXIodHJpZ2dlckdyb3VwLCBvbkVudGVyLCBvbkV4aXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgc2NlbmVMYXllcnMucHVzaChzY2VuZUxheWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzY2VuZUxheWVycztcblx0fVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi9TY2VuZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5cblxuLyoqXG4gKiBBIGxheWVyIGluIHRoZSBzY2VuZS4gTGF5ZXJzIGFyZSB1c2VkIGZvciBzb3J0aW5nIEByZWZlcmVuY2VbR2FtZU5vZGVdcyBieSBkZXB0aC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGF5ZXIge1xuICAgIC8qKiBUaGUgc2NlbmUgdGhpcyBsYXllciBiZWxvbmdzIHRvICovXG4gICAgcHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcblxuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGlzIGxheWVyICovXG4gICAgcHJvdGVjdGVkIG5hbWU6IHN0cmluZztcblxuICAgIC8qKiBXaGV0aGVyIHRoaXMgbGF5ZXIgaXMgcGF1c2VkIG9yIG5vdCAqL1xuICAgIHByb3RlY3RlZCBwYXVzZWQ6IGJvb2xlYW47XG5cbiAgICAvKiogV2hldGhlciB0aGlzIGxheWVyIGlzIGhpZGRlbiBmcm9tIGJlaW5nIHJlbmRlcmVkIG9yIG5vdCAqL1xuICAgIHByb3RlY3RlZCBoaWRkZW46IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIGdsb2JhbCBhbHBoYSBsZXZlbCBvZiB0aGlzIGxheWVyICovXG4gICAgcHJvdGVjdGVkIGFscGhhOiBudW1iZXI7XG5cbiAgICAvKiogQW4gYXJyYXkgb2YgdGhlIEdhbWVOb2RlcyB0aGF0IGJlbG9uZyB0byB0aGlzIGxheWVyICovXG4gICAgcHJvdGVjdGVkIGl0ZW1zOiBBcnJheTxHYW1lTm9kZT47XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyBsYXllciBzaG91bGQgYmUgeXNvcnRlZCAqL1xuICAgIHByb3RlY3RlZCB5U29ydDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgZGVwdGggb2YgdGhpcyBsYXllciBjb21wYXJlZCB0byBvdGhlciBsYXllcnMgKi9cbiAgICBwcm90ZWN0ZWQgZGVwdGg6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgbGF5ZXIuIFRvIGRvIHRoaXMgaW4gYSBnYW1lLCB1c2UgdGhlIGFkZExheWVyKCkgbWV0aG9kIGluIEByZWZyZW5jZVtTY2VuZV1cbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRvIGFkZCB0aGUgbGF5ZXIgdG9cbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzY2VuZTogU2NlbmUsIG5hbWU6IHN0cmluZyl7XG4gICAgICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5oaWRkZW4gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hbHBoYSA9IDE7XG4gICAgICAgIHRoaXMuaXRlbXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy55U29ydCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRlcHRoID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgdGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICovXG4gICAgZ2V0TmFtZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcy9VbnBhdXNlcyB0aGUgbGF5ZXIuIEFmZmVjdHMgYWxsIGVsZW1lbnRzIGluIHRoaXMgbGF5ZXJcbiAgICAgKiBAcGFyYW0gcGF1c2VWYWx1ZSBUcnVlIGlmIHRoZSBsYXllciBzaG91bGQgYmUgcGF1c2VkLCBmYWxzZSBpZiBub3RcbiAgICAgKi9cbiAgICBzZXRQYXVzZWQocGF1c2VWYWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IHBhdXNlVmFsdWU7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIGxheWVyIGlzIHBhdXNlZFxuICAgICAqL1xuICAgIGlzUGF1c2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXVzZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgb3BhY2l0eSBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcGFyYW0gYWxwaGEgVGhlIG5ldyBvcGFjaXR5IHZhbHVlIGluIHRoZSByYW5nZSBbMCwgMV1cbiAgICAgKi9cbiAgICBzZXRBbHBoYShhbHBoYTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWxwaGEgPSBNYXRoVXRpbHMuY2xhbXAoYWxwaGEsIDAsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG9wYWNpdHkgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG9wYWNpdHlcbiAgICAgKi9cbiAgICBnZXRBbHBoYSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5hbHBoYTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBsYXllcidzIGhpZGRlbiB2YWx1ZS4gSWYgaGlkZGVuLCBhIGxheWVyIHdpbGwgbm90IGJlIHJlbmRlcmVkLCBidXQgd2lsbCBzdGlsbCB1cGRhdGVcbiAgICAgKiBAcGFyYW0gaGlkZGVuIFRoZSBoaWRkZW4gdmFsdWUgb2YgdGhlIGxheWVyXG4gICAgICovXG4gICAgc2V0SGlkZGVuKGhpZGRlbjogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmhpZGRlbiA9IGhpZGRlbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBoaWRlZW4gdmFsdWUgb2YgdGhlIGx5YWVyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgc2NlbmUgaXMgaGlkZGVuLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpc0hpZGRlbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGlkZGVuO1xuICAgIH1cblxuICAgIC8qKiBQYXVzZXMgdGhpcyBzY2VuZSBhbmQgaGlkZXMgaXQgKi9cbiAgICBkaXNhYmxlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuaGlkZGVuID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKiogVW5wYXVzZXMgdGhpcyBsYXllciBhbmQgbWFrZXMgaXQgdmlzaWJsZSAqL1xuICAgIGVuYWJsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5oaWRkZW4gPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHdoZXRoZXIgb3Igbm90IHRoZSBzY2VuZSB3aWxsIHlTb3J0IGF1dG9tYXRpY2FsbHkuXG4gICAgICogeVNvcnRpbmcgbWVhbnMgdGhhdCBDYW52YXNOb2RlcyBvbiB0aGlzIGxheWVyIHdpbGwgaGF2ZSB0aGVpciBkZXB0aCBzb3J0ZWQgZGVwZW5kaW5nIG9uIHRoZWlyIHktdmFsdWUuXG4gICAgICogVGhpcyBtZWFucyB0aGF0IGlmIGFuIG9iamVjdCBpcyBcImhpZ2hlclwiIGluIHRoZSBzY2VuZSwgaXQgd2lsbCBzb3J0IGJlaGluZCBvYmplY3RzIHRoYXQgYXJlIFwibG93ZXJcIi5cbiAgICAgKiBUaGlzIGlzIHVzZWZ1bCBmb3IgMy80IHZpZXcgZ2FtZXMsIG9yIHNpbWlsYXIgc2l0dWF0aW9ucywgd2hlcmUgeW91IHNvbWV0aW1lcyB3YW50IHRvIGJlIGluIGZyb250IG9mIG9iamVjdHMsXG4gICAgICogYW5kIG90aGVyIHRpbWVzIHdhbnQgdG8gYmUgYmVoaW5kIHRoZSBzYW1lIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHlTb3J0IFRydWUgaWYgeVNvcnRpbmcgc2hvdWxkIGJlIGFjdGl2ZSwgZmFsc2UgaWYgbm90XG4gICAgICovXG4gICAgc2V0WVNvcnQoeVNvcnQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy55U29ydCA9IHlTb3J0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHlTb3J0IHN0YXR1cyBvZiB0aGUgc2NlbmVcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHlTb3J0aW5nIGlzIG9jY3VycmluZywgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgZ2V0WVNvcnQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnlTb3J0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGRlcHRoIG9mIHRoZSBsYXllciBjb21wYXJlZCB0byBvdGhlciBsYXllcnMuIEEgbGFyZ2VyIG51bWJlciBtZWFucyB0aGUgbGF5ZXIgd2lsbCBiZSBjbG9zZXIgdG8gdGhlIHNjcmVlbi5cbiAgICAgKiBAcGFyYW0gZGVwdGggVGhlIGRlcHRoIG9mIHRoZSBsYXllci5cbiAgICAgKi9cbiAgICBzZXREZXB0aChkZXB0aDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGVwdGggPSBkZXB0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIGRlcHRoIG9mIHRoZSBsYXllci5cbiAgICAgKiBAcmV0dXJucyBUaGUgZGVwdGhcbiAgICAgKi9cbiAgICBnZXREZXB0aCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5kZXB0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbm9kZSB0byB0aGlzIGxheWVyXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gYWRkIHRvIHRoaXMgbGF5ZXIuXG4gICAgICovXG4gICAgYWRkTm9kZShub2RlOiBHYW1lTm9kZSk6IHZvaWQge1xuICAgICAgICB0aGlzLml0ZW1zLnB1c2gobm9kZSk7XG4gICAgICAgIG5vZGUuc2V0TGF5ZXIodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIG5vZGUgZnJvbSB0aGlzIGxheWVyXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG4gICAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgbm9kZSB3YXMgcmVtb3ZlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgcmVtb3ZlTm9kZShub2RlOiBHYW1lTm9kZSk6IHZvaWQge1xuICAgICAgICAvLyBGaW5kIGFuZCByZW1vdmUgdGhlIG5vZGVcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5pdGVtcy5pbmRleE9mKG5vZGUpO1xuXG4gICAgICAgIGlmKGluZGV4ICE9PSAtMSl7XG4gICAgICAgICAgICB0aGlzLml0ZW1zLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICBub2RlLnNldExheWVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgYWxsIEdhbWVOb2RlcyBmcm9tIHRoaXMgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBhbiBBcnJheSB0aGF0IGNvbnRhaW5zIGFsbCBvZiB0aGUgR2FtZU5vZGVzIGluIHRoaXMgbGF5ZXIuXG4gICAgICovXG4gICAgZ2V0SXRlbXMoKTogQXJyYXk8R2FtZU5vZGU+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXM7XG4gICAgfVxufSIsImltcG9ydCBMYXllciBmcm9tIFwiLi4vTGF5ZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZVwiO1xuXG4vKipcbiAqIEFuIGV4dGVuc2lvbiBvZiBhIExheWVyIHRoYXQgaGFzIGEgcGFyYWxsYXggdmFsdWUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBhcmFsbGF4TGF5ZXIgZXh0ZW5kcyBMYXllciB7XG5cdC8qKiBUaGUgdmFsdWUgb2YgdGhlIHBhcmFsbGF4IG9mIHRoZSBMYXllciAqL1xuXHRwYXJhbGxheDogVmVjMjtcblx0XG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IFBhcmFsbGF4TGF5ZXIuXG5cdCAqIFVzZSBhZGRQYXJhbGxheExheWVyKCkgaW4gQHJlZmVyZW5jZVtTY2VuZV0gdG8gYWRkIGEgbGF5ZXIgb2YgdGhpcyB0eXBlIHRvIHlvdXIgZ2FtZS5cblx0ICogQHBhcmFtIHNjZW5lIFRoZSBTY2VuZSB0byBhZGQgdGhpcyBQYXJhbGxheExheWVyIHRvXG5cdCAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBQYXJhbGxheExheWVyXG5cdCAqIEBwYXJhbSBwYXJhbGxheCBUaGUgcGFyYWxsYXggbGV2ZWxcblx0ICovXG5cdGNvbnN0cnVjdG9yKHNjZW5lOiBTY2VuZSwgbmFtZTogc3RyaW5nLCBwYXJhbGxheDogVmVjMil7XG5cdFx0c3VwZXIoc2NlbmUsIG5hbWUpO1xuXHRcdHRoaXMucGFyYWxsYXggPSBwYXJhbGxheDtcblx0fVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZVwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4vUGFyYWxsYXhMYXllclwiO1xuXG4vKipcbiAqIEEgTGF5ZXIgc3RyaWN0bHkgdG8gYmUgdXNlZCBmb3IgbWFuYWdpbmcgVUlFbGVtZW50cy5cbiAqIFRoaXMgaXMgaW50ZW5kZWQgdG8gYmUgYSBMYXllciB0aGF0IGFsd2F5cyBzdGF5cyBpbiB0aGUgc2FtZSBwbGFjZSxcbiAqIGFuZCB0aHVzIHJlbmRlcnMgdGhpbmdzIGxpa2UgYSBIVUQgb3IgYW4gaW52ZW50b3J5IHdpdGhvdXQgdGFraW5nIGludG8gY29uc2lkZXJhdGlvbiB0aGUgXFxyZWZlcmVuY2VbVmlld3BvcnRdIHNjcm9sbC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVUlMYXllciBleHRlbmRzIFBhcmFsbGF4TGF5ZXIge1xuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBVSUxheWVyLlxuXHQgKiBVc2UgYWRkVUlMYXllcigpIGluIEByZWZlcmVuY2VbU2NlbmVdIHRvIGFkZCBhIGxheWVyIG9mIHRoaXMgdHlwZSB0byB5b3VyIGdhbWUuXG5cdCAqIEBwYXJhbSBzY2VuZSBUaGUgU2NlbmUgdG8gYWRkIHRoaXMgVUlMYXllciB0b1xuXHQgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgVUlMYXllclxuXHQgKi9cblx0Y29uc3RydWN0b3Ioc2NlbmU6IFNjZW5lLCBuYW1lOiBzdHJpbmcpe1xuXHRcdHN1cGVyKHNjZW5lLCBuYW1lLCBWZWMyLlpFUk8pO1xuXHR9XG59IiwiaW1wb3J0IExheWVyIGZyb20gXCIuL0xheWVyXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lR3JhcGggZnJvbSBcIi4uL1NjZW5lR3JhcGgvU2NlbmVHcmFwaFwiO1xuaW1wb3J0IFBoeXNpY3NNYW5hZ2VyIGZyb20gXCIuLi9QaHlzaWNzL1BoeXNpY3NNYW5hZ2VyXCI7XG5pbXBvcnQgQmFzaWNQaHlzaWNzTWFuYWdlciBmcm9tIFwiLi4vUGh5c2ljcy9CYXNpY1BoeXNpY3NNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmVHcmFwaEFycmF5IGZyb20gXCIuLi9TY2VuZUdyYXBoL1NjZW5lR3JhcGhBcnJheVwiO1xuaW1wb3J0IEZhY3RvcnlNYW5hZ2VyIGZyb20gXCIuL0ZhY3Rvcmllcy9GYWN0b3J5TWFuYWdlclwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBHYW1lIGZyb20gXCIuLi9Mb29wL0dhbWVcIjtcbmltcG9ydCBTY2VuZU1hbmFnZXIgZnJvbSBcIi4vU2NlbmVNYW5hZ2VyXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uL0V2ZW50cy9SZWNlaXZlclwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IE5hdmlnYXRpb25NYW5hZ2VyIGZyb20gXCIuLi9QYXRoZmluZGluZy9OYXZpZ2F0aW9uTWFuYWdlclwiO1xuaW1wb3J0IEFJTWFuYWdlciBmcm9tIFwiLi4vQUkvQUlNYW5hZ2VyXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgUGFyYWxsYXhMYXllciBmcm9tIFwiLi9MYXllcnMvUGFyYWxsYXhMYXllclwiO1xuaW1wb3J0IFVJTGF5ZXIgZnJvbSBcIi4vTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU2NlbmVPcHRpb25zIGZyb20gXCIuL1NjZW5lT3B0aW9uc1wiO1xuaW1wb3J0IFJlbmRlcmluZ01hbmFnZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9SZW5kZXJpbmdNYW5hZ2VyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgVGltZXJNYW5hZ2VyIGZyb20gXCIuLi9UaW1pbmcvVGltZXJNYW5hZ2VyXCI7XG5pbXBvcnQgVHdlZW5NYW5hZ2VyIGZyb20gXCIuLi9SZW5kZXJpbmcvQW5pbWF0aW9ucy9Ud2Vlbk1hbmFnZXJcIjtcbmltcG9ydCBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9BbmltYXRpb25zL1BhcnRpY2xlU3lzdGVtTWFuYWdlclwiO1xuXG4vKipcbiAqIFNjZW5lcyBhcmUgdGhlIG1haW4gY29udGFpbmVyIGluIHRoZSBnYW1lIGVuZ2luZS5cbiAqIFlvdXIgbWFpbiBzY2VuZSBpcyB0aGUgY3VycmVudCBsZXZlbCBvciBtZW51IG9mIHRoZSBnYW1lLCBhbmQgd2lsbCBjb250YWluIGFsbCBvZiB0aGUgR2FtZU5vZGVzIG5lZWRlZC5cbiAqIFNjZW5lcyBwcm92aWRlIGFuIGVhc3kgd2F5IHRvIGxvYWQgYXNzZXRzLCBhZGQgYXNzZXRzIHRvIHRoZSBnYW1lIHdvcmxkLCBhbmQgdW5sb2FkIGFzc2V0cyxcbiAqIGFuZCBoYXZlIGxpZmVjeWNsZSBtZXRob2RzIGV4cG9zZWQgZm9yIHRoZXNlIGZ1bmN0aW9ucy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NlbmUgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIGdhbWUgd29ybGQuICovXG4gICAgcHJvdGVjdGVkIHdvcmxkU2l6ZTogVmVjMjtcblxuICAgIC8qKiBUaGUgdmlld3BvcnQuICovXG4gICAgcHJvdGVjdGVkIHZpZXdwb3J0OiBWaWV3cG9ydDtcblxuICAgIC8qKiBBIGZsYWcgdGhhdCByZXByZXNlbnRzIHdoZXRoZXIgdGhpcyBzY2VuZSBpcyBydW5uaW5nIG9yIG5vdC4gKi9cbiAgICBwcm90ZWN0ZWQgcnVubmluZzogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgbWFuYWdlciBvZiB0aGlzIHNjZW5lLiAqL1xuICAgIHByb3RlY3RlZCBzY2VuZU1hbmFnZXI6IFNjZW5lTWFuYWdlcjtcblxuICAgIC8qKiBUaGUgcmVjZWl2ZXIgZm9yIHRoaXMgc2NlbmUuICovXG4gICAgcHJvdGVjdGVkIHJlY2VpdmVyOiBSZWNlaXZlcjtcblxuICAgIC8qKiBUaGUgZW1pdHRlciBmb3IgdGhpcyBzY2VuZS4gKi9cbiAgICBwcm90ZWN0ZWQgZW1pdHRlcjogRW1pdHRlcjtcblxuICAgIC8qKiBUaGlzIGxpc3Qgb2YgdGlsZW1hcHMgaW4gdGhpcyBzY2VuZS4gKi9cbiAgICBwcm90ZWN0ZWQgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+O1xuXG4gICAgLyoqIEEgbWFwIGZyb20gbGF5ZXIgbmFtZXMgdG8gdGhlIGxheWVycyB0aGVtc2VsdmVzICovXG4gICAgcHJvdGVjdGVkIGxheWVyczogTWFwPExheWVyPjtcblxuICAgIC8qKiBBIG1hcCBmcm9tIHBhcmFsbGF4IGxheWVyIG5hbWVzIHRvIHRoZSBwYXJhbGxheCBsYXllcnMgdGhlbXNlbHZlcyAqL1xuICAgIHByb3RlY3RlZCBwYXJhbGxheExheWVyczogTWFwPFBhcmFsbGF4TGF5ZXI+O1xuXG4gICAgLyoqIEEgbWFwIGZyb20gdWlMYXllciBuYW1lcyB0byB0aGUgdWlMYXllcnMgdGhlbXNlbHZlcyAqL1xuICAgIHByb3RlY3RlZCB1aUxheWVyczogTWFwPFVJTGF5ZXI+O1xuXG4gICAgLyoqIFRoZSBzY2VuZSBncmFwaCBvZiB0aGUgU2NlbmUqL1xuICAgIHByb3RlY3RlZCBzY2VuZUdyYXBoOiBTY2VuZUdyYXBoO1xuXG4gICAgLyoqIFRoZSBwaHlzaWNzIG1hbmFnZXIgb2YgdGhlIFNjZW5lICovXG4gICAgcHJvdGVjdGVkIHBoeXNpY3NNYW5hZ2VyOiBQaHlzaWNzTWFuYWdlcjtcbiAgICBcbiAgICAvKiogVGhlIG5hdmlnYXRpb24gbWFuYWdlciBvZiB0aGUgU2NlbmUgKi9cbiAgICBwcm90ZWN0ZWQgbmF2TWFuYWdlcjogTmF2aWdhdGlvbk1hbmFnZXI7XG5cbiAgICAvKiogVGhlIEFJIG1hbmFnZXIgb2YgdGhlIFNjZW5lICovXG4gICAgcHJvdGVjdGVkIGFpTWFuYWdlcjogQUlNYW5hZ2VyO1xuXG4gICAgLyoqIFRoZSByZW5kZXJpbmdNYW5hZ2VyIG9mIHRoZSBzY2VuZSAqL1xuICAgIHByb3RlY3RlZCByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyO1xuXG4gICAgLyoqIEFuIGludGVyZmFjZSB0aGF0IGFsbG93cyB0aGUgYWRkaW5nIG9mIGRpZmZlcmVudCBub2RlcyB0byB0aGUgc2NlbmUgKi9cbiAgICBwdWJsaWMgYWRkOiBGYWN0b3J5TWFuYWdlcjtcblxuICAgIC8qKiBBbiBpbnRlcmZhY2UgdGhhdCBhbGxvd3MgdGhlIGxvYWRpbmcgb2YgZGlmZmVyZW50IGZpbGVzIGZvciB1c2UgaW4gdGhlIHNjZW5lLiBBbiBhbGlhcyBmb3IgcmVzb3VyY2VNYW5hZ2VyICovXG4gICAgcHVibGljIGxvYWQ6IFJlc291cmNlTWFuYWdlcjtcblxuICAgIC8qKiBBbiBpbnRlcmZhY2UgdGhhdCBhbGxvd3MgdGhlIGxvYWRpbmcgYW5kIHVubG9hZGluZyBvZiBkaWZmZXJlbnQgZmlsZXMgZm9yIHVzZSBpbiB0aGUgc2NlbmUgKi9cbiAgICBwdWJsaWMgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvKiogVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhpcyBzY2VuZSAqL1xuICAgIHB1YmxpYyBzY2VuZU9wdGlvbnM6IFNjZW5lT3B0aW9ucztcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgU2NlbmUuIFRvIGFkZCBhIG5ldyBTY2VuZSBpbiB5b3VyIGdhbWUsIHVzZSBjaGFuZ2VUb1NjZW5lKCkgaW4gQHJlZmVyZW5jZVtTY2VuZU1hbmFnZXJdXG4gICAgICogQHBhcmFtIHZpZXdwb3J0IFRoZSB2aWV3cG9ydCBvZiB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSBzY2VuZU1hbmFnZXIgVGhlIFNjZW5lTWFuYWdlciB0aGF0IG93bnMgdGhpcyBTY2VuZVxuICAgICAqIEBwYXJhbSByZW5kZXJpbmdNYW5hZ2VyIFRoZSBSZW5kZXJpbmdNYW5hZ2VyIHRoYXQgd2lsbCBoYW5kbGUgdGhpcyBTY2VuZSdzIHJlbmRlcmluZ1xuICAgICAqIEBwYXJhbSBnYW1lIFRoZSBpbnN0YW5jZSBvZiB0aGUgR2FtZVxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBvcHRpb25zIGZvciBTY2VuZSBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHZpZXdwb3J0OiBWaWV3cG9ydCwgc2NlbmVNYW5hZ2VyOiBTY2VuZU1hbmFnZXIsIHJlbmRlcmluZ01hbmFnZXI6IFJlbmRlcmluZ01hbmFnZXIsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pe1xuICAgICAgICB0aGlzLnNjZW5lT3B0aW9ucyA9IFNjZW5lT3B0aW9ucy5wYXJzZShvcHRpb25zID09PSB1bmRlZmluZWQgPyB7fSA6IG9wdGlvbnMpO1xuXG4gICAgICAgIHRoaXMud29ybGRTaXplID0gbmV3IFZlYzIoNTAwLCA1MDApO1xuICAgICAgICB0aGlzLnZpZXdwb3J0ID0gdmlld3BvcnQ7XG4gICAgICAgIHRoaXMudmlld3BvcnQuc2V0Qm91bmRzKDAsIDAsIDI1NjAsIDEyODApO1xuICAgICAgICB0aGlzLnJ1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIgPSBzY2VuZU1hbmFnZXI7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIgPSBuZXcgUmVjZWl2ZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcblxuICAgICAgICB0aGlzLnRpbGVtYXBzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuc2NlbmVHcmFwaCA9IG5ldyBTY2VuZUdyYXBoQXJyYXkodGhpcy52aWV3cG9ydCwgdGhpcyk7XG5cbiAgICAgICAgdGhpcy5sYXllcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMudWlMYXllcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMucGFyYWxsYXhMYXllcnMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5waHlzaWNzTWFuYWdlciA9IG5ldyBCYXNpY1BoeXNpY3NNYW5hZ2VyKHRoaXMuc2NlbmVPcHRpb25zLnBoeXNpY3MpO1xuICAgICAgICB0aGlzLm5hdk1hbmFnZXIgPSBuZXcgTmF2aWdhdGlvbk1hbmFnZXIoKTtcbiAgICAgICAgdGhpcy5haU1hbmFnZXIgPSBuZXcgQUlNYW5hZ2VyKCk7XG4gICAgICAgIHRoaXMucmVuZGVyaW5nTWFuYWdlciA9IHJlbmRlcmluZ01hbmFnZXI7XG5cbiAgICAgICAgdGhpcy5hZGQgPSBuZXcgRmFjdG9yeU1hbmFnZXIodGhpcywgdGhpcy50aWxlbWFwcyk7XG5cbiAgICAgICAgdGhpcy5sb2FkID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKClcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSB0aGlzLmxvYWQ7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB0aW1lciBtYW5hZ2VyIGFuZCBjbGVhciBhbnkgZXhpc3RpbmcgdGltZXJzXG4gICAgICAgIFRpbWVyTWFuYWdlci5nZXRJbnN0YW5jZSgpLmNsZWFyVGltZXJzKCk7XG4gICAgfVxuXG4gICAgLyoqIEEgbGlmZWN5Y2xlIG1ldGhvZCB0aGF0IGdldHMgY2FsbGVkIGltbWVkaWF0ZWx5IGFmdGVyIGEgbmV3IHNjZW5lIGlzIGNyZWF0ZWQsIGJlZm9yZSBhbnl0aGluZyBlbHNlLiAqL1xuICAgIGluaXRTY2VuZShpbml0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxuXG4gICAgLyoqIEEgbGlmZWN5Y2xlIG1ldGhvZCB0aGF0IGdldHMgY2FsbGVkIHdoZW4gYSBuZXcgc2NlbmUgaXMgY3JlYXRlZC4gTG9hZCBhbGwgZmlsZXMgeW91IHdpc2ggdG8gYWNjZXNzIGluIHRoZSBzY2VuZSBoZXJlLiAqL1xuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHt9XG5cbiAgICAvKiogQSBsaWZlY3ljbGUgbWV0aG9kIGNhbGxlZCBzdHJpY3RseSBhZnRlciBsb2FkU2NlbmUoKS4gQ3JlYXRlIGFueSBnYW1lIG9iamVjdHMgeW91IHdpc2ggdG8gdXNlIGluIHRoZSBzY2VuZSBoZXJlLiAqL1xuICAgIHN0YXJ0U2NlbmUoKTogdm9pZCB7fVxuXG4gICAgLyoqXG4gICAgICogQSBsaWZlY3ljbGUgbWV0aG9kIGNhbGxlZCBldmVyeSBmcmFtZSBvZiB0aGUgZ2FtZS4gVGhpcyBpcyB3aGVyZSB5b3UgY2FuIGR5bmFtaWNhbGx5IGRvIHRoaW5ncyBsaWtlIGFkZCBpbiBuZXcgZW5lbWllc1xuICAgICAqIEBwYXJhbSBkZWx0YSBUaGUgdGltZSB0aGlzIGZyYW1lIHJlcHJlc2VudHNcbiAgICAgKi9cbiAgICB1cGRhdGVTY2VuZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge31cblxuICAgIC8qKiBBIGxpZmVjeWNsZSBtZXRob2QgdGhhdCBnZXRzIGNhbGxlZCBvbiBzY2VuZSBkZXN0cnVjdGlvbi4gU3BlY2lmeSB3aGljaCBmaWxlcyB5b3Ugbm8gbG9uZ2VyIG5lZWQgZm9yIGdhcmJhZ2UgY29sbGVjdGlvbi4gKi9cbiAgICB1bmxvYWRTY2VuZSgpOiB2b2lkIHt9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51cGRhdGVTY2VuZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIERvIHRpbWUgdXBkYXRlc1xuICAgICAgICBUaW1lck1hbmFnZXIuZ2V0SW5zdGFuY2UoKS51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBEbyBhbGwgQUkgdXBkYXRlc1xuICAgICAgICB0aGlzLmFpTWFuYWdlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBVcGRhdGUgYWxsIHBoeXNpY3Mgb2JqZWN0c1xuICAgICAgICB0aGlzLnBoeXNpY3NNYW5hZ2VyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBhbGwgY2FudmFzIG9iamVjdHNcbiAgICAgICAgdGhpcy5zY2VuZUdyYXBoLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBhbGwgdGlsZW1hcHNcbiAgICAgICAgdGhpcy50aWxlbWFwcy5mb3JFYWNoKHRpbGVtYXAgPT4ge1xuICAgICAgICAgICAgaWYoIXRpbGVtYXAuZ2V0TGF5ZXIoKS5pc1BhdXNlZCgpKXtcbiAgICAgICAgICAgICAgICB0aWxlbWFwLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICAgICAgfSBcbiAgICAgICAgfSk7XG4gICAgICAgIFxuICAgICAgICAvLyBVcGRhdGUgYWxsIHR3ZWVuc1xuICAgICAgICBUd2Vlbk1hbmFnZXIuZ2V0SW5zdGFuY2UoKS51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBVcGRhdGUgYWxsIHBhcnRpY2xlIHN5c3RlbXNcbiAgICAgICAgUGFydGljbGVTeXN0ZW1NYW5hZ2VyLmdldEluc3RhbmNlKCkudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHZpZXdwb3J0XG4gICAgICAgIHRoaXMudmlld3BvcnQudXBkYXRlKGRlbHRhVCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdHMgcmVuZGVyYWJsZSBzZXRzIGFuZCBjb29yZGluYXRlcyB3aXRoIHRoZSBSZW5kZXJpbmdNYW5hZ2VyIHRvIGRyYXcgdGhlIFNjZW5lXG4gICAgICovXG4gICAgcmVuZGVyKCk6IHZvaWQge1xuICAgICAgICAvLyBHZXQgdGhlIHZpc2libGUgc2V0IG9mIG5vZGVzXG4gICAgICAgIGxldCB2aXNpYmxlU2V0ID0gdGhpcy5zY2VuZUdyYXBoLmdldFZpc2libGVTZXQoKTtcblxuICAgICAgICAvLyBBZGQgcGFyYWxsYXggbGF5ZXIgaXRlbXMgdG8gdGhlIHZpc2libGUgc2V0ICh3ZSdyZSByZW5kZXJpbmcgdGhlbSBhbGwgZm9yIG5vdylcbiAgICAgICAgdGhpcy5wYXJhbGxheExheWVycy5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICBsZXQgcExheWVyID0gdGhpcy5wYXJhbGxheExheWVycy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGZvcihsZXQgbm9kZSBvZiBwTGF5ZXIuZ2V0SXRlbXMoKSl7XG4gICAgICAgICAgICAgICAgaWYobm9kZSBpbnN0YW5jZW9mIENhbnZhc05vZGUpe1xuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlU2V0LnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTZW5kIHRoZSB2aXNpYmxlIHNldCwgdGlsZW1hcHMsIGFuZCB1aUxheWVycyB0byB0aGUgcmVuZGVyZXJcbiAgICAgICAgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyLnJlbmRlcih2aXNpYmxlU2V0LCB0aGlzLnRpbGVtYXBzLCB0aGlzLnVpTGF5ZXJzKTtcblxuICAgICAgICBsZXQgbm9kZXMgPSB0aGlzLnNjZW5lR3JhcGguZ2V0QWxsTm9kZXMoKTtcbiAgICAgICAgdGhpcy50aWxlbWFwcy5mb3JFYWNoKHRpbGVtYXAgPT4gdGlsZW1hcC52aXNpYmxlID8gbm9kZXMucHVzaCh0aWxlbWFwKSA6IDApO1xuICAgICAgICBEZWJ1Zy5zZXROb2Rlcyhub2Rlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2NlbmUgYXMgcnVubmluZyBvciBub3RcbiAgICAgKiBAcGFyYW0gcnVubmluZyBUcnVlIGlmIHRoZSBTY2VuZSBzaG91bGQgYmUgcnVubmluZywgZmFsc2UgaWYgbm90XG4gICAgICovXG4gICAgc2V0UnVubmluZyhydW5uaW5nOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMucnVubmluZyA9IHJ1bm5pbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgU2NlbmUgaXMgcnVubmluZ1xuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHNjZW5lIGlzIHJ1bm5pbmcsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGlzUnVubmluZygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucnVubmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbm9kZSBmcm9tIHRoaXMgU2NlbmVcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byByZW1vdmVcbiAgICAgKi9cbiAgICByZW1vdmUobm9kZTogR2FtZU5vZGUpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIGZyb20gdGhlIHNjZW5lIGdyYXBoXG4gICAgICAgIGlmKG5vZGUgaW5zdGFuY2VvZiBDYW52YXNOb2RlKXtcbiAgICAgICAgICAgIHRoaXMuc2NlbmVHcmFwaC5yZW1vdmVOb2RlKG5vZGUpO1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICAvKiogRGVzdHJveXMgdGhpcyBzY2VuZSBhbmQgYWxsIG5vZGVzIGluIGl0ICovXG4gICAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMuc2NlbmVHcmFwaC5nZXRBbGxOb2RlcygpKXtcbiAgICAgICAgICAgIG5vZGUuZGVzdHJveSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGxldCB0aWxlbWFwIG9mIHRoaXMudGlsZW1hcHMpe1xuICAgICAgICAgICAgdGlsZW1hcC5kZXN0cm95KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlY2VpdmVyLmRlc3Ryb3koKTtcblxuICAgICAgICBkZWxldGUgdGhpcy5zY2VuZUdyYXBoO1xuICAgICAgICBkZWxldGUgdGhpcy5waHlzaWNzTWFuYWdlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMubmF2TWFuYWdlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMuYWlNYW5hZ2VyO1xuICAgICAgICBkZWxldGUgdGhpcy5yZWNlaXZlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbmV3IGxheWVyIHRvIHRoZSBzY2VuZSBhbmQgcmV0dXJucyBpdFxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBuZXcgbGF5ZXJcbiAgICAgKiBAcGFyYW0gZGVwdGggVGhlIGRlcHRoIG9mIHRoZSBsYXllclxuICAgICAqIEByZXR1cm5zIFRoZSBuZXdseSBjcmVhdGVkIExheWVyXG4gICAgICovXG4gICAgYWRkTGF5ZXIobmFtZTogc3RyaW5nLCBkZXB0aD86IG51bWJlcik6IExheWVyIHtcbiAgICAgICAgaWYodGhpcy5sYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMucGFyYWxsYXhMYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMudWlMYXllcnMuaGFzKG5hbWUpKXtcbiAgICAgICAgICAgIHRocm93IGBMYXllciB3aXRoIG5hbWUgJHtuYW1lfSBhbHJlYWR5IGV4aXN0c2A7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbGF5ZXIgPSBuZXcgTGF5ZXIodGhpcywgbmFtZSk7XG5cbiAgICAgICAgdGhpcy5sYXllcnMuYWRkKG5hbWUsIGxheWVyKTtcblxuICAgICAgICBpZihkZXB0aCl7XG4gICAgICAgICAgICBsYXllci5zZXREZXB0aChkZXB0aCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIG5ldyBwYXJhbGxheCBsYXllciB0byB0aGlzIHNjZW5lIGFuZCByZXR1cm5zIGl0XG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIHBhcmFsbGF4IGxheWVyXG4gICAgICogQHBhcmFtIHBhcmFsbGF4IFRoZSBwYXJhbGxheCBsZXZlbFxuICAgICAqIEBwYXJhbSBkZXB0aCBUaGUgZGVwdGggb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgUGFyYWxsYXhMYXllclxuICAgICAqL1xuICAgIGFkZFBhcmFsbGF4TGF5ZXIobmFtZTogc3RyaW5nLCBwYXJhbGxheDogVmVjMiwgZGVwdGg/OiBudW1iZXIpOiBQYXJhbGxheExheWVyIHtcbiAgICAgICAgaWYodGhpcy5sYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMucGFyYWxsYXhMYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMudWlMYXllcnMuaGFzKG5hbWUpKXtcbiAgICAgICAgICAgIHRocm93IGBMYXllciB3aXRoIG5hbWUgJHtuYW1lfSBhbHJlYWR5IGV4aXN0c2A7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbGF5ZXIgPSBuZXcgUGFyYWxsYXhMYXllcih0aGlzLCBuYW1lLCBwYXJhbGxheCk7XG5cbiAgICAgICAgdGhpcy5wYXJhbGxheExheWVycy5hZGQobmFtZSwgbGF5ZXIpO1xuXG4gICAgICAgIGlmKGRlcHRoKXtcbiAgICAgICAgICAgIGxheWVyLnNldERlcHRoKGRlcHRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsYXllcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbmV3IFVJTGF5ZXIgdG8gdGhlIHNjZW5lXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIG5ldyBVSWxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgVUlMYXllclxuICAgICAqL1xuICAgIGFkZFVJTGF5ZXIobmFtZTogc3RyaW5nKTogVUlMYXllciB7XG4gICAgICAgIGlmKHRoaXMubGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnBhcmFsbGF4TGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnVpTGF5ZXJzLmhhcyhuYW1lKSl7XG4gICAgICAgICAgICB0aHJvdyBgTGF5ZXIgd2l0aCBuYW1lICR7bmFtZX0gYWxyZWFkeSBleGlzdHNgO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxheWVyID0gbmV3IFVJTGF5ZXIodGhpcywgbmFtZSk7XG5cbiAgICAgICAgdGhpcy51aUxheWVycy5hZGQobmFtZSwgbGF5ZXIpO1xuXG4gICAgICAgIHJldHVybiBsYXllcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgbGF5ZXIgZnJvbSB0aGUgc2NlbmUgYnkgbmFtZSBpZiBpdCBleGlzdHMuXG4gICAgICogVGhpcyBjYW4gYmUgYSBMYXllciBvciBhbnkgb2YgaXRzIHN1YmNsYXNzZXNcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBUaGUgTGF5ZXIgZm91bmQgd2l0aCB0aGF0IG5hbWVcbiAgICAgKi9cbiAgICBnZXRMYXllcihuYW1lOiBzdHJpbmcpOiBMYXllciB7XG4gICAgICAgIGlmKHRoaXMubGF5ZXJzLmhhcyhuYW1lKSl7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sYXllcnMuZ2V0KG5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYodGhpcy5wYXJhbGxheExheWVycy5oYXMobmFtZSkpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyYWxsYXhMYXllcnMuZ2V0KG5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYodGhpcy51aUxheWVycy5oYXMobmFtZSkpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudWlMYXllcnMuZ2V0KG5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgYFJlcXVlc3RlZCBsYXllciAke25hbWV9IGRvZXMgbm90IGV4aXN0LmA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBsYXllciBpcyBhIFBhcmFsbGF4TGF5ZXJcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoaXMgbGF5ZXIgaXMgYSBQYXJhbGxheExheWVyXG4gICAgICovXG4gICAgaXNQYXJhbGxheExheWVyKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJhbGxheExheWVycy5oYXMobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoaXMgbGF5ZXIgaXMgYSBVSUxheWVyXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIGxheWVyIGlzIFBhcmFsbGF4TGF5ZXJcbiAgICAgKi9cbiAgICBpc1VJTGF5ZXIobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnVpTGF5ZXJzLmhhcyhuYW1lKTtcbiAgICB9ICAgIFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdHJhbnNsYXRpb24gb2YgdGhpcyBub2RlIHdpdGggcmVzcGVjdCB0byBjYW1lcmEgc3BhY2UgKGR1ZSB0byB0aGUgdmlld3BvcnQgbW92aW5nKS5cbiAgICAgKiBUaGlzIHZhbHVlIGlzIGFmZmVjdGVkIGJ5IHRoZSBwYXJhbGxheCBsZXZlbCBvZiB0aGUgQHJlZmVyZW5jZVtMYXllcl0gdGhlIG5vZGUgaXMgb24uXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gY2hlY2sgdGhlIHZpZXdwb3J0IHdpdGggcmVzcGVjdCB0b1xuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSB0cmFuc2xhdGlvbiBvZiB2aWV3cG9ydCB3aXRoIHJlc3BlY3QgdG8gdGhpcyBub2RlLlxuICAgICAqL1xuICAgIGdldFZpZXdUcmFuc2xhdGlvbihub2RlOiBHYW1lTm9kZSk6IFZlYzIge1xuICAgICAgICBsZXQgbGF5ZXIgPSBub2RlLmdldExheWVyKCk7XG5cbiAgICAgICAgaWYobGF5ZXIgaW5zdGFuY2VvZiBQYXJhbGxheExheWVyIHx8IGxheWVyIGluc3RhbmNlb2YgVUlMYXllcil7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52aWV3cG9ydC5nZXRPcmlnaW4oKS5tdWx0KGxheWVyLnBhcmFsbGF4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZpZXdwb3J0LmdldE9yaWdpbigpO1xuICAgICAgICB9XG5cdH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNjYWxlIGxldmVsIG9mIHRoZSB2aWV3XG4gICAgICogQHJldHVybnMgVGhlIHpvb20gbGV2ZWwgb2YgdGhlIHZpZXdwb3J0XG4gICAgKi9cblx0Z2V0Vmlld1NjYWxlKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMudmlld3BvcnQuZ2V0Wm9vbUxldmVsKCk7XG5cdH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIFZpZXdwb3J0IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNjZW5lXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgVmlld3BvcnRcbiAgICAgKi9cbiAgICBnZXRWaWV3cG9ydCgpOiBWaWV3cG9ydCB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdwb3J0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHdvcmxkIHNpemUgb2YgdGhpcyBTY2VuZVxuICAgICAqIEByZXR1cm5zIFRoZSB3b3JsZCBzaXplIGluIGEgVmVjMlxuICAgICAqL1xuICAgIGdldFdvcmxkU2l6ZSgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud29ybGRTaXplO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIFNjZW5lR3JhcGggYXNzb2NpYXRlZCB3aXRoIHRoaXMgU2NlbmVcbiAgICAgKiBAcmV0dXJucyBUaGUgU2NlbmVHcmFwaFxuICAgICAqL1xuICAgIGdldFNjZW5lR3JhcGgoKTogU2NlbmVHcmFwaCB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjZW5lR3JhcGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgUGh5c2ljc01hbmFnZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgU2NlbmVcbiAgICAgKiBAcmV0dXJucyBUaGUgUGh5c2ljc01hbmFnZXJcbiAgICAgKi9cbiAgICBnZXRQaHlzaWNzTWFuYWdlcigpOiBQaHlzaWNzTWFuYWdlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnBoeXNpY3NNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIE5hdmlnYXRpb25NYW5hZ2VyIGFzc29jaWF0ZWQgd2l0aCB0aGlzIFNjZW5lXG4gICAgICogQHJldHVybnMgVGhlIE5hdmlnYXRpb25NYW5hZ2VyXG4gICAgICovXG4gICAgZ2V0TmF2aWdhdGlvbk1hbmFnZXIoKTogTmF2aWdhdGlvbk1hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5uYXZNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIEFJTWFuYWdlciBhc3NvY2lhdGVkIHdpdGggdGhpcyBTY2VuZVxuICAgICAqIEByZXR1cm5zIFRoZSBBSU1hbmFnZXJcbiAgICAgKi9cbiAgICBnZXRBSU1hbmFnZXIoKTogQUlNYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWlNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyBhbiBJRCBmb3IgYSBHYW1lTm9kZVxuICAgICAqIEByZXR1cm5zIFRoZSBuZXcgSURcbiAgICAgKi9cbiAgICBnZW5lcmF0ZUlkKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjZW5lTWFuYWdlci5nZW5lcmF0ZUlkKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGEgVGlsZW1hcCBpbiB0aGlzIFNjZW5lXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIFRpbGVtYXBcbiAgICAgKiBAcmV0dXJucyBUaGUgVGlsZW1hcCwgaWYgb25lIHRoaXMgbmFtZSBleGlzdHMsIG90aGVyd2lzZSBudWxsXG4gICAgICovXG4gICAgZ2V0VGlsZW1hcChuYW1lOiBzdHJpbmcpOiBUaWxlbWFwIHtcbiAgICAgICAgZm9yKGxldCB0aWxlbWFwIG9mIHRoaXMgLnRpbGVtYXBzKXtcbiAgICAgICAgICAgIGlmKHRpbGVtYXAubmFtZSA9PT0gbmFtZSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbGVtYXA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59IiwiaW1wb3J0IFNjZW5lIGZyb20gXCIuL1NjZW5lXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBSZW5kZXJpbmdNYW5hZ2VyIGZyb20gXCIuLi9SZW5kZXJpbmcvUmVuZGVyaW5nTWFuYWdlclwiO1xuaW1wb3J0IE1lbW9yeVV0aWxzIGZyb20gXCIuLi9VdGlscy9NZW1vcnlVdGlsc1wiO1xuXG4vKipcbiAqIFRoZSBTY2VuZU1hbmFnZXIgYWN0cyBhcyBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIFNjZW5lcywgYW5kIGhhbmRsZXMgdGhlIGxpZmVjeWNsZSBtZXRob2RzIG9mIFNjZW5lcy5cbiAqIEl0IGdpdmVzIFNjZW5lcyBhY2Nlc3MgdG8gaW5mb3JtYXRpb24gdGhleSBuZWVkIGZyb20gdGhlIEByZWZlcmVuY2VbR2FtZV0gY2xhc3Mgd2hpbGUga2VlcGluZyBhIGxheWVyIG9mIHNlcGFyYXRpb24uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lTWFuYWdlciB7XG5cdC8qKiBUaGUgY3VycmVudCBTY2VuZSBvZiB0aGUgZ2FtZSAqL1xuXHRwcm90ZWN0ZWQgY3VycmVudFNjZW5lOiBTY2VuZTtcblxuXHQvKiogVGhlIFZpZXdwb3J0IG9mIHRoZSBnYW1lICovXG5cdHByb3RlY3RlZCB2aWV3cG9ydDogVmlld3BvcnQ7XG5cblx0LyoqIEEgcmVmZXJlbmNlIHRvIHRoZSBSZXNvdXJjZU1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG5cdC8qKiBBIGNvdW50ZXIgdG8ga2VlcCB0cmFjayBvZiBnYW1lIGlkcyAqL1xuXHRwcm90ZWN0ZWQgaWRDb3VudGVyOiBudW1iZXI7XG5cblx0LyoqIFRoZSBSZW5kZXJpbmdNYW5hZ2VyIG9mIHRoZSBnYW1lICovXG5cdHByb3RlY3RlZCByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyO1xuXG5cdC8qKiBGb3IgY29uc2lzdGVuY3ksIG9ubHkgY2hhbmdlIHNjZW5lcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB1cGRhdGUgY3ljbGUgKi9cblx0cHJvdGVjdGVkIHBlbmRpbmdTY2VuZTogU2NlbmU7XG5cdHByb3RlY3RlZCBwZW5kaW5nU2NlbmVJbml0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IFNjZW5lTWFuYWdlclxuXHQgKiBAcGFyYW0gdmlld3BvcnQgVGhlIFZpZXdwb3J0IG9mIHRoZSBnYW1lXG5cdCAqIEBwYXJhbSBnYW1lIFRoZSBHYW1lIGluc3RhbmNlXG5cdCAqIEBwYXJhbSByZW5kZXJpbmdNYW5hZ2VyIFRoZSBSZW5kZXJpbmdNYW5hZ2VyIG9mIHRoZSBnYW1lXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcih2aWV3cG9ydDogVmlld3BvcnQsIHJlbmRlcmluZ01hbmFnZXI6IFJlbmRlcmluZ01hbmFnZXIpe1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdFx0dGhpcy52aWV3cG9ydCA9IHZpZXdwb3J0O1xuXHRcdHRoaXMucmVuZGVyaW5nTWFuYWdlciA9IHJlbmRlcmluZ01hbmFnZXI7XG5cdFx0dGhpcy5pZENvdW50ZXIgPSAwO1xuXHRcdHRoaXMucGVuZGluZ1NjZW5lID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGQgYSBzY2VuZSBhcyB0aGUgbWFpbiBzY2VuZS5cblx0ICogVXNlIHRoaXMgbWV0aG9kIGlmIHlvdSd2ZSBjcmVhdGVkIGEgc3ViY2xhc3Mgb2YgU2NlbmUsIGFuZCB5b3Ugd2FudCB0byBhZGQgaXQgYXMgdGhlIG1haW4gU2NlbmUuXG5cdCAqIEBwYXJhbSBjb25zdHIgVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBzY2VuZSB0byBhZGRcblx0ICogQHBhcmFtIGluaXQgQW4gb2JqZWN0IHRvIHBhc3MgdG8gdGhlIGluaXQgZnVuY3Rpb24gb2YgdGhlIG5ldyBzY2VuZVxuXHQgKi9cblx0cHVibGljIGNoYW5nZVRvU2NlbmU8VCBleHRlbmRzIFNjZW5lPihjb25zdHI6IG5ldyAoLi4uYXJnczogYW55KSA9PiBULCBpbml0PzogUmVjb3JkPHN0cmluZywgYW55Piwgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRjb25zb2xlLmxvZyhcIkNyZWF0aW5nIHRoZSBuZXcgc2NlbmUgLSBjaGFuZ2UgaXMgcGVuZGluZyB1bnRpbCBuZXh0IHVwZGF0ZVwiKTtcblx0XHR0aGlzLnBlbmRpbmdTY2VuZSA9IG5ldyBjb25zdHIodGhpcy52aWV3cG9ydCwgdGhpcywgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyLCBvcHRpb25zKTtcblx0XHR0aGlzLnBlbmRpbmdTY2VuZUluaXQgPSBpbml0O1xuXHR9XG5cblx0cHJvdGVjdGVkIGRvU2NlbmVDaGFuZ2UoKXtcblx0XHRjb25zb2xlLmxvZyhcIlBlcmZvcm1pbmcgc2NlbmUgY2hhbmdlXCIpO1xuXHRcdHRoaXMudmlld3BvcnQuc2V0Q2VudGVyKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54LCB0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSk7XG5cdFx0XG5cdFx0aWYodGhpcy5jdXJyZW50U2NlbmUpe1xuXHRcdFx0Y29uc29sZS5sb2coXCJVbmxvYWRpbmcgb2xkIHNjZW5lXCIpXG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS51bmxvYWRTY2VuZSgpO1xuXG5cdFx0XHRjb25zb2xlLmxvZyhcIkRlc3Ryb3lpbmcgb2xkIHNjZW5lXCIpO1xuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUuZGVzdHJveSgpO1xuXHRcdH1cblxuXHRcdGNvbnNvbGUubG9nKFwiVW5sb2FkaW5nIG9sZCByZXNvdXJjZXMuLi5cIik7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIudW5sb2FkQWxsUmVzb3VyY2VzKCk7XG5cblx0XHQvLyBNYWtlIHRoZSBwZW5kaW5nIHNjZW5lIHRoZSBjdXJyZW50IG9uZVxuXHRcdHRoaXMuY3VycmVudFNjZW5lID0gdGhpcy5wZW5kaW5nU2NlbmU7XG5cblx0XHQvLyBNYWtlIHRoZSBwZW5kaW5nIHNjZW5lIG51bGxcblx0XHR0aGlzLnBlbmRpbmdTY2VuZSA9IG51bGw7XG5cblx0XHQvLyBJbml0IHRoZSBzY2VuZVxuXHRcdHRoaXMuY3VycmVudFNjZW5lLmluaXRTY2VuZSh0aGlzLnBlbmRpbmdTY2VuZUluaXQpO1xuXG5cdFx0Ly8gRW5xdWV1ZSBhbGwgc2NlbmUgYXNzZXQgbG9hZHNcblx0XHR0aGlzLmN1cnJlbnRTY2VuZS5sb2FkU2NlbmUoKTtcblxuXHRcdC8vIExvYWQgYWxsIGFzc2V0c1xuXHRcdGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgU2NlbmUgTG9hZFwiKTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5sb2FkUmVzb3VyY2VzRnJvbVF1ZXVlKCgpID0+IHtcblx0XHRcdGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgU2NlbmVcIik7XG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS5zdGFydFNjZW5lKCk7XG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS5zZXRSdW5uaW5nKHRydWUpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5yZW5kZXJpbmdNYW5hZ2VyLnNldFNjZW5lKHRoaXMuY3VycmVudFNjZW5lKTtcblx0fVxuXHRcblx0LyoqXG5cdCAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBJRFxuXHQgKiBAcmV0dXJucyBBIG5ldyBJRFxuXHQgKi9cblx0cHVibGljIGdlbmVyYXRlSWQoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5pZENvdW50ZXIrKztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW5kZXJzIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqL1xuXHRwdWJsaWMgcmVuZGVyKCk6IHZvaWQge1xuXHRcdGlmKHRoaXMuY3VycmVudFNjZW5lKXtcblx0XHRcdHRoaXMuY3VycmVudFNjZW5lLnJlbmRlcigpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqIEBwYXJhbSBkZWx0YVQgVGhlIHRpbWVzdGVwIG9mIHRoZSBTY2VuZVxuXHQgKi9cblx0cHVibGljIHVwZGF0ZShkZWx0YVQ6IG51bWJlcil7XG5cdFx0aWYodGhpcy5wZW5kaW5nU2NlbmUgIT09IG51bGwpe1xuXHRcdFx0dGhpcy5kb1NjZW5lQ2hhbmdlKCk7XG5cdFx0fVxuXG5cdFx0aWYodGhpcy5jdXJyZW50U2NlbmUgJiYgdGhpcy5jdXJyZW50U2NlbmUuaXNSdW5uaW5nKCkpe1xuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUudXBkYXRlKGRlbHRhVCk7XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IEFycmF5VXRpbHMgZnJvbSBcIi4uL1V0aWxzL0FycmF5VXRpbHNcIjtcblxuLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBUaGUgb3B0aW9ucyB0byBnaXZlIGEgQHJlZmVyZW5jZVtTY2VuZV0gZm9yIGluaXRpYWxpemF0aW9uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lT3B0aW9ucyB7XG4gICAgcGh5c2ljczoge1xuICAgICAgICBncm91cHM6IEFycmF5PHN0cmluZz4sXG4gICAgICAgIGNvbGxpc2lvbnM6IEFycmF5PEFycmF5PG51bWJlcj4+O1xuICAgIH1cblxuICAgIHN0YXRpYyBwYXJzZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogU2NlbmVPcHRpb25ze1xuICAgICAgICBsZXQgc09wdCA9IG5ldyBTY2VuZU9wdGlvbnMoKTtcblxuICAgICAgICBpZihvcHRpb25zLnBoeXNpY3MgPT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICBzT3B0LnBoeXNpY3MgPSB7Z3JvdXBzOiB1bmRlZmluZWQsIGNvbGxpc2lvbnM6IHVuZGVmaW5lZH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzT3B0LnBoeXNpY3MgPSBvcHRpb25zLnBoeXNpY3M7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc09wdDtcbiAgICB9XG59IiwiaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuL1ZpZXdwb3J0XCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgaW50ZXJmYWNlIG9mIGEgU2NlbmVHcmFwaC5cbiAqIEV4cG9zZXMgbWV0aG9kcyBmb3IgdXNlIGJ5IG90aGVyIGNvZGUsIGJ1dCBsZWF2ZXMgdGhlIGltcGxlbWVudGF0aW9uIHVwIHRvIHRoZSBzdWJjbGFzc2VzLlxuICogVGhlIFNjZW5lR3JhcGggbWFuYWdlcyB0aGUgcG9zaXRpb25zIG9mIGFsbCBHYW1lTm9kZXMsIGFuZCBjYW4gZWFzaWx5IHBydW5lIGEgdmlzaWJsZSBzZXQgZm9yIHJlbmRlcmluZy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgU2NlbmVHcmFwaCB7XG5cdC8qKlx0QSByZWZlcmVuY2UgdG8gdGhlIHZpZXdwb3J0ICovXG5cdHByb3RlY3RlZCB2aWV3cG9ydDogVmlld3BvcnQ7XG5cdC8qKlx0QSBtYXAgb2YgQ2FudmFzTm9kZXMgaW4gdGhpcyBTY2VuZUdyYXBoICovXG5cdHByb3RlY3RlZCBub2RlTWFwOiBBcnJheTxDYW52YXNOb2RlPjtcblx0LyoqIEEgY291bnRlciBvZiBJRHMgZm9yIG5vZGVzIGluIHRoaXMgU2NlbmVHcmFwaCAqL1xuXHRwcm90ZWN0ZWQgaWRDb3VudGVyOiBudW1iZXI7XG5cdC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgU2NlbmUgdGhpcyBTY2VuZUdyYXBoIGJlbG9uZ3MgdG8gKi9cblx0cHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBTY2VuZUdyYXBoXG5cdCAqIEBwYXJhbSB2aWV3cG9ydCBUaGUgdmlld3BvcnRcblx0ICogQHBhcmFtIHNjZW5lIFRoZSBTY2VuZSB0aGlzIFNjZW5lR3JhcGggYmVsb25ncyB0b1xuXHQgKi9cbiAgICBjb25zdHJ1Y3Rvcih2aWV3cG9ydDogVmlld3BvcnQsIHNjZW5lOiBTY2VuZSl7XG5cdFx0dGhpcy52aWV3cG9ydCA9IHZpZXdwb3J0O1xuXHRcdHRoaXMuc2NlbmUgPSBzY2VuZTtcblx0XHR0aGlzLm5vZGVNYXAgPSBuZXcgQXJyYXkoKTtcblx0XHR0aGlzLmlkQ291bnRlciA9IDA7XG4gICAgfVxuXG5cdC8qKlxuXHQgKiBBZGQgYSBub2RlIHRvIHRoZSBTY2VuZUdyYXBoXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBDYW52YXNOb2RlIHRvIGFkZCB0byB0aGUgU2NlbmVHcmFwaFxuXHQgKiBAcmV0dXJucyBUaGUgU2NlbmVHcmFwaCBJRCBvZiB0aGlzIG5ld2x5IGFkZGVkIENhbnZhc05vZGVcblx0ICovXG4gICAgYWRkTm9kZShub2RlOiBDYW52YXNOb2RlKTogbnVtYmVyIHtcblx0XHR0aGlzLm5vZGVNYXBbbm9kZS5pZF0gPSBub2RlO1xuXHRcdHRoaXMuYWRkTm9kZVNwZWNpZmljKG5vZGUsIHRoaXMuaWRDb3VudGVyKTtcblx0XHR0aGlzLmlkQ291bnRlciArPSAxO1xuXHRcdHJldHVybiB0aGlzLmlkQ291bnRlciAtIDE7XG5cdH07XG5cblx0LyoqXG5cdCAqIEFuIG92ZXJyaWRhYmxlIG1ldGhvZCB0byBhZGQgYSBDYW52YXNOb2RlIHRvIHRoZSBzcGVjaWZpYyBkYXRhIHN0cnVjdHVyZSBvZiB0aGUgU2NlbmVHcmFwaFxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byBhZGQgdG8gdGhlIGRhdGEgc3RydWN0dXJlXG5cdCAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIENhbnZhc05vZGVcblx0ICovXG5cdHByb3RlY3RlZCBhYnN0cmFjdCBhZGROb2RlU3BlY2lmaWMobm9kZTogQ2FudmFzTm9kZSwgaWQ6IG51bWJlcik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYSBub2RlIGZyb20gdGhlIFNjZW5lR3JhcGhcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG5cdCAqL1xuICAgIHJlbW92ZU5vZGUobm9kZTogQ2FudmFzTm9kZSk6IHZvaWQge1xuXHRcdC8vIEZpbmQgYW5kIHJlbW92ZSBub2RlIGluIE8obilcblx0XHR0aGlzLm5vZGVNYXBbbm9kZS5pZF0gPSB1bmRlZmluZWQ7XG5cdFx0dGhpcy5yZW1vdmVOb2RlU3BlY2lmaWMobm9kZSwgbm9kZS5pZCk7XG5cdH07XG5cblx0LyoqXG5cdCAqIFRoZSBzcGVjaWZpYyBpbXBsZW1lbnRhdGlvbiBvZiByZW1vdmluZyBhIG5vZGVcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG5cdCAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIG5vZGUgdG8gcmVtb3ZlXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgcmVtb3ZlTm9kZVNwZWNpZmljKG5vZGU6IENhbnZhc05vZGUsIGlkOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBHZXQgYSBzcGVjaWZpYyBub2RlIHVzaW5nIGl0cyBpZFxuXHQgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBDYW52YXNOb2RlIHRvIHJldHJpZXZlXG5cdCAqIEByZXR1cm5zIFRoZSBub2RlIHdpdGggdGhpcyBJRFxuXHQgKi9cblx0Z2V0Tm9kZShpZDogbnVtYmVyKTogQ2FudmFzTm9kZSB7XG5cdFx0cmV0dXJuIHRoaXMubm9kZU1hcFtpZF07XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgbm9kZXMgYXQgc3BlY2lmaWMgY29vcmRpbmF0ZXNcblx0ICogQHBhcmFtIHZlY09yWCBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSBwb3NpdGlvbiwgb3IgdGhlIGNvb3JkaW5hdGVzIGluIGEgVmVjMlxuXHQgKiBAcGFyYW0geSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBwb3NpdGlvblxuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBub2RlcyBmb3VuZCBhdCB0aGUgcG9zaXRpb24gcHJvdmlkZWRcblx0ICovXG4gICAgZ2V0Tm9kZXNBdCh2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiBBcnJheTxDYW52YXNOb2RlPiB7XG5cdFx0aWYodmVjT3JYIGluc3RhbmNlb2YgVmVjMil7XG5cdFx0XHRyZXR1cm4gdGhpcy5nZXROb2Rlc0F0Q29vcmRzKHZlY09yWC54LCB2ZWNPclgueSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB0aGlzLmdldE5vZGVzQXRDb29yZHModmVjT3JYLCB5KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgbm9kZXMgdGhhdCBvdmVybGFwIGEgc3BlY2lmaWMgYm91bmRhcnlcblx0ICogQHBhcmFtIGJvdW5kYXJ5IFRoZSByZWdpb24gdG8gY2hlY2tcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2Ygbm9kZXMgZm91bmQgb3ZlcmxhcHBpbmcgdGhlIHByb3ZpZGVkIGJvdW5kYXJ5XG5cdCAqL1xuXHRhYnN0cmFjdCBnZXROb2Rlc0luUmVnaW9uKGJvdW5kYXJ5OiBBQUJCKTogQXJyYXk8Q2FudmFzTm9kZT47XG5cdFxuXHQvKipcblx0ICogUmV0dXJucyBhbGwgbm9kZXMgaW4gdGhlIFNjZW5lR3JhcGhcblx0ICogQHJldHVybnMgQW4gQXJyYXkgY29udGFpbmluZyBhbGwgbm9kZXMgaW4gdGhlIFNjZW5lR3JhcGhcblx0ICovXG5cdGdldEFsbE5vZGVzKCk6IEFycmF5PENhbnZhc05vZGU+IHtcblx0XHRsZXQgYXJyID0gbmV3IEFycmF5PENhbnZhc05vZGU+KCk7XG5cdFx0Zm9yKGxldCBpID0gMDsgaSA8IHRoaXMubm9kZU1hcC5sZW5ndGg7IGkrKyl7XG5cdFx0XHRpZih0aGlzLm5vZGVNYXBbaV0gIT09IHVuZGVmaW5lZCl7XG5cdFx0XHRcdGFyci5wdXNoKHRoaXMubm9kZU1hcFtpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBhcnI7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHNwZWNpZmljIGltcGxlbWVudGF0aW9uIG9mIGdldHRpbmcgYSBub2RlIGF0IGNlcnRhaW4gY29vcmRpbmF0ZXNcblx0ICogQHBhcmFtIHggVGhlIHgtY29vcmRpbmF0ZXMgb2YgdGhlIG5vZGVcblx0ICogQHBhcmFtIHkgVGhlIHktY29vcmRpbmF0ZXMgb2YgdGhlIG5vZGVcblx0ICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGdldE5vZGVzQXRDb29yZHMoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBBcnJheTxDYW52YXNOb2RlPjtcblxuXHRhYnN0cmFjdCB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkO1xuXHRcblx0YWJzdHJhY3QgcmVuZGVyKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZDtcblxuXHQvKipcblx0ICogR2V0cyB0aGUgdmlzaWJsZSBzZXQgb2YgQ2FudmFzTm9kZXMgYmFzZWQgb24gdGhlIEByZWZlcmVuY2VbVmlld3BvcnRdXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHZpc2libGUgbm9kZXMgaW4gdGhlIFNjZW5lR3JhcGhcblx0ICovXG4gICAgYWJzdHJhY3QgZ2V0VmlzaWJsZVNldCgpOiBBcnJheTxDYW52YXNOb2RlPjtcbn0iLCJpbXBvcnQgU2NlbmVHcmFwaCBmcm9tIFwiLi9TY2VuZUdyYXBoXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuL1ZpZXdwb3J0XCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgU3RhdHMgZnJvbSBcIi4uL0RlYnVnL1N0YXRzXCI7XG5cbi8qKlxuICogQW4gaW1wbGVtZW50YXRpb24gb2YgYSBTY2VuZUdyYXBoIHRoYXQgc2ltcGx5IHN0b3JlZCBDYW52YXNOb2RlcyBpbiBhbiBhcnJheS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NlbmVHcmFwaEFycmF5IGV4dGVuZHMgU2NlbmVHcmFwaCB7XG4gICAgLyoqIFRoZSBsaXN0IG9mIENhbnZhc05vZGVzIGluIHRoaXMgU2NlbmVHcmFwaCAqL1xuICAgIHByaXZhdGUgbm9kZUxpc3Q6IEFycmF5PENhbnZhc05vZGU+O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBTY2VuZUdyYXBoQXJyYXlcbiAgICAgKiBAcGFyYW0gdmlld3BvcnQgVGhlIFZpZXdwb3J0XG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBTY2VuZSB0aGlzIFNjZW5lR3JhcGggYmVsb25ncyB0b1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHZpZXdwb3J0OiBWaWV3cG9ydCwgc2NlbmU6IFNjZW5lKXtcbiAgICAgICAgc3VwZXIodmlld3BvcnQsIHNjZW5lKTtcblxuICAgICAgICB0aGlzLm5vZGVMaXN0ID0gbmV3IEFycmF5PENhbnZhc05vZGU+KCk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIGFkZE5vZGVTcGVjaWZpYyhub2RlOiBDYW52YXNOb2RlLCBpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMubm9kZUxpc3QucHVzaChub2RlKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVtb3ZlTm9kZVNwZWNpZmljKG5vZGU6IENhbnZhc05vZGUsIGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5ub2RlTGlzdC5pbmRleE9mKG5vZGUpO1xuICAgICAgICBpZihpbmRleCA+IC0xKXtcbiAgICAgICAgICAgIHRoaXMubm9kZUxpc3Quc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGdldE5vZGVzQXRDb29yZHMoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBBcnJheTxDYW52YXNOb2RlPiB7XG4gICAgICAgIGxldCByZXN1bHRzID0gW107XG5cbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMubm9kZUxpc3Qpe1xuICAgICAgICAgICAgaWYobm9kZS5jb250YWlucyh4LCB5KSl7XG4gICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgZ2V0Tm9kZXNJblJlZ2lvbihib3VuZGFyeTogQUFCQik6IEFycmF5PENhbnZhc05vZGU+IHtcbiAgICAgICAgbGV0IHQwID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIGxldCByZXN1bHRzID0gW107XG5cbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMubm9kZUxpc3Qpe1xuICAgICAgICAgICAgaWYoYm91bmRhcnkub3ZlcmxhcHMobm9kZS5ib3VuZGFyeSkpe1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgdDEgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgU3RhdHMubG9nKFwic2dxdWVyeVwiLCAodDEtdDApKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IHQwID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIGZvcihsZXQgbm9kZSBvZiB0aGlzLm5vZGVMaXN0KXtcbiAgICAgICAgICAgIGlmKCFub2RlLmdldExheWVyKCkuaXNQYXVzZWQoKSl7XG4gICAgICAgICAgICAgICAgbm9kZS51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgdDEgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgU3RhdHMubG9nKFwic2d1cGRhdGVcIiwgKHQxLXQwKSk7XG4gICAgfVxuXG4gICAgcmVuZGVyKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZCB7fVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgZ2V0VmlzaWJsZVNldCgpOiBBcnJheTxDYW52YXNOb2RlPiB7XG4gICAgICAgIGxldCB2aXNpYmxlU2V0ID0gbmV3IEFycmF5PENhbnZhc05vZGU+KCk7XG5cbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMubm9kZUxpc3Qpe1xuICAgICAgICAgICAgaWYoIW5vZGUuZ2V0TGF5ZXIoKS5pc0hpZGRlbigpICYmIG5vZGUudmlzaWJsZSAmJiB0aGlzLnZpZXdwb3J0LmluY2x1ZGVzKG5vZGUpKXtcbiAgICAgICAgICAgICAgICB2aXNpYmxlU2V0LnB1c2gobm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmlzaWJsZVNldDtcbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgUXVldWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9RdWV1ZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9QYXJhbGxheExheWVyXCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcblxuLyoqXG4gKiBUaGUgdmlld3BvcnQgb2YgdGhlIGdhbWUuIENvcnJlc3BvbmRzIHRvIHRoZSB2aXNpYmxlIHdpbmRvdyBkaXNwbGF5ZWQgaW4gdGhlIGJyb3dzZXIuXG4gKiBUaGUgdmlld3BvcnQga2VlcHMgdHJhY2sgb2YgaXRzIHBvc2l0aW9uIGluIHRoZSBnYW1lIHdvcmxkLCBhbmQgY2FuIGFjdCBhcyBhIGNhbWVyYSB0byBmb2xsb3cgb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmlld3BvcnQge1xuICAgIC8qKiBUaGUgQUFCQiB0aGF0IGNvbnRhaW5zIHRoZSBwb3NpdGlvbiBhbmQgc2l6ZSBvZiB0aGUgdmlld3BvcnQgdmlldyAqL1xuICAgIHByaXZhdGUgdmlldzogQUFCQjtcbiAgICAvKiogVGhlIGJvdW5kYXJ5IGZvciB0aGUgdmlld3BvcnQuIFRoaXMgcmVwcmVzZW50cyB0aGUgbGltaXRzIHRvIHdoZXJlIHRoZSB2aWV3cG9ydCBjYW4gZ28gKi9cbiAgICBwcml2YXRlIGJvdW5kYXJ5OiBBQUJCO1xuICAgIC8qKiBUaGUgR2FtZU5vZGUgdGhlIFZpZXdwb3J0IGlzIGZvbGxvd2luZyAqL1xuICAgIHByaXZhdGUgZm9sbG93aW5nOiBHYW1lTm9kZTtcbiAgICAvKiogVGhlIHBvc2l0aW9uIHRoZSBHYW1lTm9kZSBpcyBmb2N1c2luZyBvbi4gVGhpcyBpcyBvdmVycmlkZGVuIGlmIFwiZm9sbG93aW5nXCIgaXMgc2V0LiAqL1xuICAgIHByaXZhdGUgZm9jdXM6IFZlYzI7XG5cbiAgICAvKiogQSBxdWV1ZSBvZiBwcmV2aW91cyBwb3NpdGlvbnMgb2Ygd2hhdCB0aGlzIHZpZXdwb3J0IGlzIGZvbGxvd2luZy4gVXNlZCBmb3Igc21vb3RoaW5nIHZpZXdwb3J0IG1vdmVtZW50ICovXG4gICAgcHJpdmF0ZSBsYXN0UG9zaXRpb25zOiBRdWV1ZTxWZWMyPjtcblxuICAgIC8qKiBUaGUgbnVtYmVyIG9mIHByZXZpb3VzIHBvc2l0aW9ucyB0aGlzIHZpZXdwb3J0IHRyYWNrcyAqL1xuICAgIHByaXZhdGUgc21vb3RoaW5nRmFjdG9yOiBudW1iZXI7XG5cbiAgICAvKiogQSBib29sZWFuIHRoYSByZXByZXNlbnRzIHdoZXRoZXIgdGhlIHBsYXllciBjYW4gem9vbSBieSBzY3JvbGxpbmcgd2l0aCB0aGUgbW91c2Ugd2hlZWwgKi9cbiAgICBwcml2YXRlIHNjcm9sbFpvb21FbmFibGVkOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBhbW91bnQgdGhhdCBpcyB6b29tZWQgaW4gb3Igb3V0LiAqL1xuICAgIHByaXZhdGUgWk9PTV9GQUNUT1I6IG51bWJlciA9IDEuMjtcblxuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgY2FudmFzICovXG4gICAgcHJpdmF0ZSBjYW52YXNTaXplOiBWZWMyO1xuXG4gICAgY29uc3RydWN0b3IoY2FudmFzU2l6ZTogVmVjMiwgem9vbUxldmVsOiBudW1iZXIpe1xuICAgICAgICB0aGlzLnZpZXcgPSBuZXcgQUFCQihWZWMyLlpFUk8sIFZlYzIuWkVSTyk7XG4gICAgICAgIHRoaXMuYm91bmRhcnkgPSBuZXcgQUFCQihWZWMyLlpFUk8sIFZlYzIuWkVSTyk7XG4gICAgICAgIHRoaXMubGFzdFBvc2l0aW9ucyA9IG5ldyBRdWV1ZSgpO1xuICAgICAgICB0aGlzLnNtb290aGluZ0ZhY3RvciA9IDEwO1xuICAgICAgICB0aGlzLnNjcm9sbFpvb21FbmFibGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2FudmFzU2l6ZSA9IFZlYzIuWkVSTztcbiAgICAgICAgdGhpcy5mb2N1cyA9IFZlYzIuWkVSTztcblxuICAgICAgICAvLyBTZXQgdGhlIHNpemUgb2YgdGhlIGNhbnZhc1xuICAgICAgICB0aGlzLnNldENhbnZhc1NpemUoY2FudmFzU2l6ZSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydFxuICAgICAgICB0aGlzLnNldFNpemUoY2FudmFzU2l6ZSk7XG4gICAgICAgIHRoaXMuc2V0Wm9vbUxldmVsKHpvb21MZXZlbCk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBjZW50ZXIgKGFuZCBtYWtlIHRoZSB2aWV3cG9ydCBzdGF5IHRoZXJlKVxuICAgICAgICB0aGlzLnNldENlbnRlcih0aGlzLnZpZXcuaGFsZlNpemUuY2xvbmUoKSk7XG4gICAgICAgIHRoaXMuc2V0Rm9jdXModGhpcy52aWV3LmhhbGZTaXplLmNsb25lKCkpO1xuICAgIH1cblxuICAgIC8qKiBFbmFibGVzIHRoZSB2aWV3cG9ydCB0byB6b29tIGluIGFuZCBvdXQgKi9cbiAgICBlbmFibGVab29tKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjcm9sbFpvb21FbmFibGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcmV0dXJucyBUaGUgY2VudGVyIG9mIHRoZSB2aWV3cG9ydCBhcyBhIFZlYzJcbiAgICAgKi9cbiAgICBnZXRDZW50ZXIoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXcuY2VudGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgVmVjMiB3aXRoIHRoZSBvcmlnaW4gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHJldHVybnMgVGhlIHRvcCBsZWZ0IGNvcm5kZXIgb2YgdGhlIFZpZXBvcnQgYXMgYSBWZWMyXG4gICAgICovXG4gICAgZ2V0T3JpZ2luKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy52aWV3LmxlZnQsIHRoaXMudmlldy50b3ApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHJlZ2lvbiB2aXNpYmxlIHRvIHRoaXMgdmlld3BvcnRcbiAgICAgKiBAcmV0dXJucyBUaGUgQUFCQiBjb250YWluaW5nIHRoZSByZWdpb24gdmlzaWJsZSB0byB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBnZXRWaWV3KCk6IEFBQkIge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgcG9zaXRpb24gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZlY09yWCBUaGUgbmV3IHBvc2l0aW9uIG9yIHRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIG5ldyBwb3NpdGlvblxuICAgICAqIEBwYXJhbSB5IFRoZSB5LWNvb3JkaW5hdGUgb2YgdGhlIG5ldyBwb3NpdGlvblxuICAgICAqL1xuICAgIHNldENlbnRlcih2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiB2b2lkIHtcbiAgICAgICAgbGV0IHBvczogVmVjMjtcblx0XHRpZih2ZWNPclggaW5zdGFuY2VvZiBWZWMyKXtcbiAgICAgICAgICAgIHBvcyA9IHZlY09yWDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBvcyA9IG5ldyBWZWMyKHZlY09yWCwgeSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZXcuY2VudGVyID0gcG9zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0IGFzIGEgVmVjMlxuICAgICAqIEByZXR1cm5zIFRoZSBoYWxmLXNpemUgb2YgdGhlIHZpZXdwb3J0IGFzIGEgVmVjMlxuICAgICAqL1xuICAgIGdldEhhbGZTaXplKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3LmdldEhhbGZTaXplKCk7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZlY09yWCBUaGUgbmV3IHdpZHRoIG9mIHRoZSB2aWV3cG9ydCBvciB0aGUgbmV3IHNpemUgYXMgYSBWZWMyXG4gICAgICogQHBhcmFtIHkgVGhlIG5ldyBoZWlnaHQgb2YgdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgc2V0U2l6ZSh2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiB2b2lkIHtcblx0XHRpZih2ZWNPclggaW5zdGFuY2VvZiBWZWMyKXtcblx0XHRcdHRoaXMudmlldy5zZXRIYWxmU2l6ZSh2ZWNPclguc2NhbGVkKDEvMikpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnZpZXcuc2V0SGFsZlNpemUobmV3IFZlYzIodmVjT3JYLzIsIHkvMikpO1xuXHRcdH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBoYWxmLXNpemUgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZlY09yWCBUaGUgbmV3IGhhbGYtd2lkdGggb2YgdGhlIHZpZXdwb3J0IG9yIHRoZSBuZXcgaGFsZi1zaXplIGFzIGEgVmVjMlxuICAgICAqIEBwYXJhbSB5IFRoZSBuZXcgaGVpZ2h0IG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHNldEhhbGZTaXplKHZlY09yWDogVmVjMiB8IG51bWJlciwgeTogbnVtYmVyID0gbnVsbCk6IHZvaWQge1xuXHRcdGlmKHZlY09yWCBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0dGhpcy52aWV3LnNldEhhbGZTaXplKHZlY09yWC5jbG9uZSgpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy52aWV3LnNldEhhbGZTaXplKG5ldyBWZWMyKHZlY09yWCwgeSkpO1xuXHRcdH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSB2aWV3cG9ydCB3aXRoIHRoZSBzaXplIG9mIHRoZSBjdXJyZW50IENhbnZhc1xuICAgICAqIEBwYXJhbSB2ZWNPclggVGhlIHdpZHRoIG9mIHRoZSBjYW52YXMsIG9yIHRoZSBjYW52YXMgc2l6ZSBhcyBhIFZlYzJcbiAgICAgKiBAcGFyYW0geSBUaGUgaGVpZ2h0IG9mIHRoZSBjYW52YXNcbiAgICAgKi9cbiAgICBzZXRDYW52YXNTaXplKHZlY09yWDogVmVjMiB8IG51bWJlciwgeTogbnVtYmVyID0gbnVsbCk6IHZvaWQge1xuXHRcdGlmKHZlY09yWCBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0dGhpcy5jYW52YXNTaXplID0gdmVjT3JYLmNsb25lKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuY2FudmFzU2l6ZSA9IG5ldyBWZWMyKHZlY09yWCwgeSk7XG5cdFx0fVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHpvb20gVGhlIHpvb20gbGV2ZWxcbiAgICAgKi9cbiAgICBzZXRab29tTGV2ZWwoem9vbTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMudmlldy5oYWxmU2l6ZS5jb3B5KHRoaXMuY2FudmFzU2l6ZS5zY2FsZWQoMS96b29tLzIpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEByZXR1cm5zIFRoZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgZ2V0Wm9vbUxldmVsKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhc1NpemUueC90aGlzLnZpZXcuaHcvMlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNtb290aGluZyBmYWN0b3IgZm9yIHRoZSB2aWV3cG9ydCBtb3ZlbWVudC5cbiAgICAgKiBAcGFyYW0gc21vb3RoaW5nRmFjdG9yIFRoZSBzbW9vdGhpbmcgZmFjdG9yIGZvciB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBzZXRTbW9vdGhpbmdGYWN0b3Ioc21vb3RoaW5nRmFjdG9yOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYoc21vb3RoaW5nRmFjdG9yIDwgMSkgc21vb3RoaW5nRmFjdG9yID0gMTtcbiAgICAgICAgdGhpcy5zbW9vdGhpbmdGYWN0b3IgPSBzbW9vdGhpbmdGYWN0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGVsbHMgdGhlIHZpZXdwb3J0IHRvIGZvY3VzIG9uIGEgcG9pbnQuIE92ZXJpZGRlbiBieSBcImZvbGxvd2luZ1wiLlxuICAgICAqIEBwYXJhbSBmb2N1cyBUaGUgcG9pbnQgdGhlICB2aWV3cG9ydCBzaG91bGQgZm9jdXMgb25cbiAgICAgKi9cbiAgICBzZXRGb2N1cyhmb2N1czogVmVjMik6IHZvaWQge1xuICAgICAgICB0aGlzLmZvY3VzLmNvcHkoZm9jdXMpO1xuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIENhbnZhc05vZGUgaXMgaW5zaWRlIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbm9kZSBpcyBjdXJyZW50bHkgdmlzaWJsZSBpbiB0aGUgdmlld3BvcnQsIGZhbHNlIGlmIG5vdFxuICAgICAqL1xuICAgIGluY2x1ZGVzKG5vZGU6IENhbnZhc05vZGUpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IHBhcmFsbGF4ID0gbm9kZS5nZXRMYXllcigpIGluc3RhbmNlb2YgUGFyYWxsYXhMYXllciB8fCBub2RlLmdldExheWVyKCkgaW5zdGFuY2VvZiBVSUxheWVyID8gKDxQYXJhbGxheExheWVyPm5vZGUuZ2V0TGF5ZXIoKSkucGFyYWxsYXggOiBuZXcgVmVjMigxLCAxKTtcbiAgICAgICAgbGV0IGNlbnRlciA9IHRoaXMudmlldy5jZW50ZXIuY2xvbmUoKTtcbiAgICAgICAgdGhpcy52aWV3LmNlbnRlci5tdWx0KHBhcmFsbGF4KTtcbiAgICAgICAgbGV0IG92ZXJsYXBzID0gdGhpcy52aWV3Lm92ZXJsYXBzKG5vZGUuYm91bmRhcnkpO1xuICAgICAgICB0aGlzLnZpZXcuY2VudGVyID0gY2VudGVyXG4gICAgICAgIHJldHVybiBvdmVybGFwcztcbiAgICB9XG5cblx0Ly8gVE9ETzogUHV0IHNvbWUgZXJyb3IgaGFuZGxpbmcgb24gdGhpcyBmb3IgdHJ5aW5nIHRvIG1ha2UgdGhlIGJvdW5kcyB0b28gc21hbGwgZm9yIHRoZSB2aWV3cG9ydFxuICAgIC8vIFRPRE86IFRoaXMgc2hvdWxkIHByb2JhYmx5IGJlIGRvbmUgYXV0b21hdGljYWxseSwgb3Igc2hvdWxkIGNvbnNpZGVyIHRoZSBhc3BlY3QgcmF0aW8gb3Igc29tZXRoaW5nXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYm91bmRzIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSBsb3dlclggVGhlIGxlZnQgZWRnZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gbG93ZXJZIFRoZSB0b3AgZWRnZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gdXBwZXJYIFRoZSByaWdodCBlZGdlIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB1cHBlclkgVGhlIGJvdHRvbSBlZGdlIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHNldEJvdW5kcyhsb3dlclg6IG51bWJlciwgbG93ZXJZOiBudW1iZXIsIHVwcGVyWDogbnVtYmVyLCB1cHBlclk6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBsZXQgaHdpZHRoID0gKHVwcGVyWCAtIGxvd2VyWCkvMjtcbiAgICAgICAgbGV0IGhoZWlnaHQgPSAodXBwZXJZIC0gbG93ZXJZKS8yO1xuICAgICAgICBsZXQgeCA9IGxvd2VyWCArIGh3aWR0aDtcbiAgICAgICAgbGV0IHkgPSBsb3dlclkgKyBoaGVpZ2h0O1xuICAgICAgICB0aGlzLmJvdW5kYXJ5LmNlbnRlci5zZXQoeCwgeSk7XG4gICAgICAgIHRoaXMuYm91bmRhcnkuaGFsZlNpemUuc2V0KGh3aWR0aCwgaGhlaWdodCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZSB0aGUgdmlld3BvcnQgZm9sbG93IHRoZSBzcGVjaWZpZWQgR2FtZU5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgR2FtZU5vZGUgdG8gZm9sbG93XG4gICAgICovXG4gICAgZm9sbG93KG5vZGU6IEdhbWVOb2RlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9sbG93aW5nID0gbm9kZTtcbiAgICB9XG5cbiAgICB1cGRhdGVWaWV3KCk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLmxhc3RQb3NpdGlvbnMuZ2V0U2l6ZSgpID4gdGhpcy5zbW9vdGhpbmdGYWN0b3Ipe1xuICAgICAgICAgICAgdGhpcy5sYXN0UG9zaXRpb25zLmRlcXVldWUoKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gR2V0IHRoZSBhdmVyYWdlIG9mIHRoZSBsYXN0IDEwIHBvc2l0aW9uc1xuICAgICAgICBsZXQgcG9zID0gVmVjMi5aRVJPO1xuICAgICAgICB0aGlzLmxhc3RQb3NpdGlvbnMuZm9yRWFjaChwb3NpdGlvbiA9PiBwb3MuYWRkKHBvc2l0aW9uKSk7XG4gICAgICAgIHBvcy5zY2FsZSgxL3RoaXMubGFzdFBvc2l0aW9ucy5nZXRTaXplKCkpO1xuXG4gICAgICAgIC8vIFNldCB0aGlzIHBvc2l0aW9uIGVpdGhlciB0byB0aGUgb2JqZWN0IG9yIHRvIGl0cyBib3VuZHNcbiAgICAgICAgcG9zLnggPSBNYXRoVXRpbHMuY2xhbXAocG9zLngsIHRoaXMuYm91bmRhcnkubGVmdCArIHRoaXMudmlldy5odywgdGhpcy5ib3VuZGFyeS5yaWdodCAtIHRoaXMudmlldy5odyk7XG4gICAgICAgIHBvcy55ID0gTWF0aFV0aWxzLmNsYW1wKHBvcy55LCB0aGlzLmJvdW5kYXJ5LnRvcCArIHRoaXMudmlldy5oaCwgdGhpcy5ib3VuZGFyeS5ib3R0b20gLSB0aGlzLnZpZXcuaGgpO1xuXG4gICAgICAgIC8vIEFzc3VyZSB0aGVyZSBhcmUgbm8gbGluZXMgaW4gdGhlIHRpbGVtYXBcbiAgICAgICAgcG9zLnggPSBNYXRoLmZsb29yKHBvcy54KTtcbiAgICAgICAgcG9zLnkgPSBNYXRoLmZsb29yKHBvcy55KTtcbiAgICAgICAgXG4gICAgICAgIHRoaXMudmlldy5jZW50ZXIuY29weShwb3MpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBJZiB6b29tIGlzIGVuYWJsZWRcbiAgICAgICAgaWYodGhpcy5zY3JvbGxab29tRW5hYmxlZCl7XG4gICAgICAgICAgICBpZihJbnB1dC5kaWRKdXN0U2Nyb2xsKCkpe1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50U2l6ZSA9IHRoaXMudmlldy5nZXRIYWxmU2l6ZSgpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgaWYoSW5wdXQuZ2V0U2Nyb2xsRGlyZWN0aW9uKCkgPCAwKXtcbiAgICAgICAgICAgICAgICAgICAgLy8gWm9vbSBpblxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2l6ZS5zY2FsZSgxL3RoaXMuWk9PTV9GQUNUT1IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFpvb20gb3V0XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnNjYWxlKHRoaXMuWk9PTV9GQUNUT1IpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGN1cnJlbnRTaXplLnggPiB0aGlzLmJvdW5kYXJ5Lmh3KXtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZhY3RvciA9IHRoaXMuYm91bmRhcnkuaHcvY3VycmVudFNpemUueDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNpemUueCA9IHRoaXMuYm91bmRhcnkuaHc7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnkgKj0gZmFjdG9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGN1cnJlbnRTaXplLnkgPiB0aGlzLmJvdW5kYXJ5LmhoKXtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZhY3RvciA9IHRoaXMuYm91bmRhcnkuaGgvY3VycmVudFNpemUueTtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNpemUueSA9IHRoaXMuYm91bmRhcnkuaGg7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnggKj0gZmFjdG9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmlldy5zZXRIYWxmU2l6ZShjdXJyZW50U2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB2aWV3cG9ydCBpcyBmb2xsb3dpbmcgYW4gb2JqZWN0XG4gICAgICAgIGlmKHRoaXMuZm9sbG93aW5nKXtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBvdXIgbGlzdCBvZiBwcmV2aW91cyBwb3NpdGlvbnNcbiAgICAgICAgICAgIHRoaXMubGFzdFBvc2l0aW9ucy5lbnF1ZXVlKHRoaXMuZm9sbG93aW5nLnBvc2l0aW9uLmNsb25lKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sYXN0UG9zaXRpb25zLmVucXVldWUodGhpcy5mb2N1cyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnVwZGF0ZVZpZXcoKTtcbiAgICB9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuLyoqXG4gKiBNYW5hZ2VzIGFueSBzb3VuZHMgb3IgbXVzaWMgbmVlZGVkIGZvciB0aGUgZ2FtZS5cbiAqIFRocm91Z2ggdGhlIEV2ZW50UXVldWUsIGV4cG9zZXMgaW50ZXJmYWNlIHRvIHBsYXkgc291bmRzIHNvIEdhbWVOb2RlcyBjYW4gYWN0aXZhdGUgc291bmRzIHdpdGhvdXRcbiAqIG5lZWRpbmcgZGlyZWN0IHJlZmVyZW5jZXMgdG8gdGhlIGF1ZGlvIHN5c3RlbVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBdWRpb01hbmFnZXIge1xuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBBdWRpb01hbmFnZXI7XG5cbiAgICAvKiogVGhlIGV2ZW50IHJlY2VpdmVyIG9mIHRoaXMgQXVkaW9NYW5hZ2VyICovXG4gICAgcHJpdmF0ZSByZWNlaXZlcjogUmVjZWl2ZXI7XG5cbiAgICAvKiogQSBNYXAgb2YgdGhlIG5hbWVzIG9mIGN1cnJlbnRseSBwbGF5aW5nIChvciBwYXVzZWQpIHNvdW5kcyB0byB0aGVpciBBdWRpb0J1ZmZlcnMgKi9cbiAgICBwcml2YXRlIGN1cnJlbnRTb3VuZHM6IE1hcDxBdWRpb0J1ZmZlclNvdXJjZU5vZGU+O1xuXG4gICAgcHJpdmF0ZSBhdWRpb0N0eDogQXVkaW9Db250ZXh0O1xuXG4gICAgcHJpdmF0ZSBnYWluTm9kZXM6IEFycmF5PEdhaW5Ob2RlPjtcblxuICAgIHByaXZhdGUgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy5pbml0QXVkaW8oKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShbXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlNUT1BfU09VTkQsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlBMQVlfTVVTSUMsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlBMQVlfU0ZYLFxuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5NVVRFX0NIQU5ORUwsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlVOTVVURV9DSEFOTkVMXG4gICAgICAgIF0pO1xuICAgICAgICB0aGlzLmN1cnJlbnRTb3VuZHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5nYWluTm9kZXMgPSBuZXcgQXJyYXk8R2Fpbk5vZGU+KE1BWF9BVURJT19DSEFOTkVMUyk7XG4gICAgICAgIHRoaXMuaW5pdEdhaW5Ob2RlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgaW5zdGFuY2Ugb2YgdGhlIEF1ZGlvTWFuYWdlciBjbGFzcyBvciBjcmVhdGUgYSBuZXcgb25lIGlmIG5vbmUgZXhpc3RzXG4gICAgICogQHJldHVybnMgVGhlIEF1ZGlvTWFuYWdlclxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogQXVkaW9NYW5hZ2VyIHtcbiAgICAgICAgaWYoIXRoaXMuaW5zdGFuY2Upe1xuICAgICAgICAgICAgdGhpcy5pbnN0YW5jZSA9IG5ldyBBdWRpb01hbmFnZXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgd2ViQXVkaW8gY29udGV4dFxuICAgICAqL1xuICAgIHByaXZhdGUgaW5pdEF1ZGlvKCk6IHZvaWQge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgd2luZG93LkF1ZGlvQ29udGV4dCA9IHdpbmRvdy5BdWRpb0NvbnRleHQ7Ly8gfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDsgXG4gICAgICAgICAgICB0aGlzLmF1ZGlvQ3R4ID0gbmV3IEF1ZGlvQ29udGV4dCgpOyBcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWIgQXVkaW8gQVBJIHN1Y2Nlc3NmdWxseSBsb2FkZWQnKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYiBBdWRpbyBBUEkgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKTsgXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRHYWluTm9kZXMoKTogdm9pZCB7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBNQVhfQVVESU9fQ0hBTk5FTFM7IGkrKyl7XG4gICAgICAgICAgICB0aGlzLmdhaW5Ob2Rlc1tpXSA9IHRoaXMuYXVkaW9DdHguY3JlYXRlR2FpbigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCBhdWRpbyBjb250ZXh0XG4gICAgICogQHJldHVybnMgVGhlIEF1ZGlvQ29udGV4dFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRBdWRpb0NvbnRleHQoKTogQXVkaW9Db250ZXh0IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXVkaW9DdHg7XG4gICAgfVxuXG4gICAgLypcbiAgICAgICAgQWNjb3JkaW5nIHRvIHRoZSBNRE4sIGNyZWF0ZSBhIG5ldyBzb3VuZCBmb3IgZXZlcnkgY2FsbDpcblxuICAgICAgICBBbiBBdWRpb0J1ZmZlclNvdXJjZU5vZGUgY2FuIG9ubHkgYmUgcGxheWVkIG9uY2U7IGFmdGVyIGVhY2ggY2FsbCB0byBzdGFydCgpLCB5b3UgaGF2ZSB0byBjcmVhdGUgYSBuZXcgbm9kZVxuICAgICAgICBpZiB5b3Ugd2FudCB0byBwbGF5IHRoZSBzYW1lIHNvdW5kIGFnYWluLiBGb3J0dW5hdGVseSwgdGhlc2Ugbm9kZXMgYXJlIHZlcnkgaW5leHBlbnNpdmUgdG8gY3JlYXRlLCBhbmQgdGhlXG4gICAgICAgIGFjdHVhbCBBdWRpb0J1ZmZlcnMgY2FuIGJlIHJldXNlZCBmb3IgbXVsdGlwbGUgcGxheXMgb2YgdGhlIHNvdW5kLiBJbmRlZWQsIHlvdSBjYW4gdXNlIHRoZXNlIG5vZGVzIGluIGFcbiAgICAgICAgXCJmaXJlIGFuZCBmb3JnZXRcIiBtYW5uZXI6IGNyZWF0ZSB0aGUgbm9kZSwgY2FsbCBzdGFydCgpIHRvIGJlZ2luIHBsYXlpbmcgdGhlIHNvdW5kLCBhbmQgZG9uJ3QgZXZlbiBib3RoZXIgdG9cbiAgICAgICAgaG9sZCBhIHJlZmVyZW5jZSB0byBpdC4gSXQgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIGdhcmJhZ2UtY29sbGVjdGVkIGF0IGFuIGFwcHJvcHJpYXRlIHRpbWUsIHdoaWNoIHdvbid0IGJlXG4gICAgICAgIHVudGlsIHNvbWV0aW1lIGFmdGVyIHRoZSBzb3VuZCBoYXMgZmluaXNoZWQgcGxheWluZy5cbiAgICAqL1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgc291bmQgZnJvbSB0aGUga2V5IG9mIGEgbG9hZGVkIGF1ZGlvIGZpbGVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCBhdWRpbyBmaWxlIHRvIGNyZWF0ZSBhIG5ldyBzb3VuZCBmb3JcbiAgICAgKiBAcmV0dXJucyBUaGUgbmV3bHkgY3JlYXRlZCBBdWRpb0J1ZmZlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVTb3VuZChrZXk6IHN0cmluZywgaG9sZFJlZmVyZW5jZTogYm9vbGVhbiwgY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSwgb3B0aW9uczogTWFwPGFueT4pOiBBdWRpb0J1ZmZlclNvdXJjZU5vZGUge1xuICAgICAgICAvLyBHZXQgYXVkaW8gYnVmZmVyXG4gICAgICAgIGxldCBidWZmZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRBdWRpbyhrZXkpO1xuXG4gICAgICAgIC8vIENyZWF0ZSBhIHNvdW5kIHNvdXJjZVxuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5hdWRpb0N0eC5jcmVhdGVCdWZmZXJTb3VyY2UoKTsgXG4gICAgICBcbiAgICAgICAgLy8gVGVsbCB0aGUgc291cmNlIHdoaWNoIHNvdW5kIHRvIHBsYXlcbiAgICAgICAgc291cmNlLmJ1ZmZlciA9IGJ1ZmZlcjsgICAgICAgICAgICAgICBcbiAgICAgIFxuICAgICAgICAvLyBBZGQgYW55IGFkZGl0aW9uYWwgbm9kZXNcbiAgICAgICAgY29uc3Qgbm9kZXM6IEFycmF5PEF1ZGlvTm9kZT4gPSBbc291cmNlXTtcblxuICAgICAgICAvLyBEbyBhbnkgYWRkaXRpb25hbCBub2RlcyBoZXJlP1xuICAgICAgICAvLyBPZiBjb3Vyc2UsIHRoZXJlIGFyZW4ndCBhbnkgc3VwcG9ydGVkIHlldC4uLlxuXG4gICAgICAgIC8vIEFkZCB0aGUgZ2FpbiBub2RlIGZvciB0aGlzIGNoYW5uZWxcbiAgICAgICAgbm9kZXMucHVzaCh0aGlzLmdhaW5Ob2Rlc1tjaGFubmVsXSk7XG5cbiAgICAgICAgLy8gQ29ubmVjdCBhbnkgbm9kZXMgYWxvbmcgdGhlIHBhdGhcbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIG5vZGVzW2ktMV0uY29ubmVjdChub2Rlc1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb25uZWN0IHRoZSBzb3VyY2UgdG8gdGhlIGNvbnRleHQncyBkZXN0aW5hdGlvblxuICAgICAgICBub2Rlc1tub2Rlcy5sZW5ndGggLSAxXS5jb25uZWN0KHRoaXMuYXVkaW9DdHguZGVzdGluYXRpb24pO1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQbGF5IHRoZSBzb3VuZCBzcGVjaWZpZWQgYnkgdGhlIGtleVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgc291bmQgdG8gcGxheVxuICAgICAqIEBwYXJhbSBsb29wIEEgYm9vbGVhbiBmb3Igd2hldGhlciBvciBub3QgdG8gbG9vcCB0aGUgc291bmRcbiAgICAgKiBAcGFyYW0gaG9sZFJlZmVyZW5jZSBBIGJvb2xlYW4gZm9yIHdoZXRoZXIgb3Igbm90IHdlIHdhbnQgdG8gaG9sZCBvbiB0byBhIHJlZmVyZW5jZSBvZiB0aGUgYXVkaW8gbm9kZS4gVGhpcyBpcyBnb29kIGZvciBwbGF5aW5nIG11c2ljIG9uIGEgbG9vcCB0aGF0IHdpbGwgZXZlbnR1YWxseSBuZWVkIHRvIGJlIHN0b3BwZWQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHBsYXlTb3VuZChrZXk6IHN0cmluZywgbG9vcDogYm9vbGVhbiwgaG9sZFJlZmVyZW5jZTogYm9vbGVhbiwgY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSwgb3B0aW9uczogTWFwPGFueT4pOiB2b2lkIHtcbiAgICAgICAgbGV0IHNvdW5kID0gdGhpcy5jcmVhdGVTb3VuZChrZXksIGhvbGRSZWZlcmVuY2UsIGNoYW5uZWwsIG9wdGlvbnMpO1xuXG4gICAgICAgIGlmKGxvb3Ape1xuICAgICAgICAgICAgc291bmQubG9vcCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYSByZWZlcmVuY2Ugb2YgdGhlIG5ldyBzb3VuZCB0byBhIG1hcC4gVGhpcyB3aWxsIGFsbG93IHVzIHRvIHN0b3AgYSBsb29waW5nIG9yIGxvbmcgc291bmQgYXQgYSBsYXRlciB0aW1lXG4gICAgICAgIGlmKGhvbGRSZWZlcmVuY2Upe1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50U291bmRzLmFkZChrZXksIHNvdW5kKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgc291bmQuc3RhcnQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdG9wIHRoZSBzb3VuZCBzcGVjaWZpZWQgYnkgdGhlIGtleVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzdG9wU291bmQoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgbGV0IHNvdW5kID0gdGhpcy5jdXJyZW50U291bmRzLmdldChrZXkpO1xuICAgICAgICBpZihzb3VuZCl7XG4gICAgICAgICAgICBzb3VuZC5zdG9wKCk7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRTb3VuZHMuZGVsZXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbXV0ZUNoYW5uZWwoY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSl7XG4gICAgICAgIHRoaXMuZ2Fpbk5vZGVzW2NoYW5uZWxdLmdhaW4uc2V0VmFsdWVBdFRpbWUoMCwgdGhpcy5hdWRpb0N0eC5jdXJyZW50VGltZSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHVubXV0ZUNoYW5uZWwoY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSl7XG4gICAgICAgIHRoaXMuZ2Fpbk5vZGVzW2NoYW5uZWxdLmdhaW4uc2V0VmFsdWVBdFRpbWUoMSwgdGhpcy5hdWRpb0N0eC5jdXJyZW50VGltZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdm9sdW1lIG9mIGEgY2hhbm5lbCB1c2luZyB0aGUgR2Fpbk5vZGUgZm9yIHRoYXQgY2hhbm5lbC4gRm9yIG1vcmVcbiAgICAgKiBpbmZvcm1hdGlvbiBvbiBHYWluTm9kZXMsIHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvR2Fpbk5vZGVcbiAgICAgKiBAcGFyYW0gY2hhbm5lbCBUaGUgYXVkaW8gY2hhbm5lbCB0byBzZXQgdGhlIHZvbHVtZSBmb3JcbiAgICAgKiBAcGFyYW0gdm9sdW1lIFRoZSB2b2x1bWUgb2YgdGhlIGNoYW5uZWwuIDAgaXMgbXV0ZWQuIFZhbHVlcyBiZWxvdyB6ZXJvIHdpbGwgYmUgc2V0IHRvIHplcm8uXG4gICAgICovXG4gICAgc3RhdGljIHNldFZvbHVtZShjaGFubmVsOiBBdWRpb0NoYW5uZWxUeXBlLCB2b2x1bWU6IG51bWJlcil7XG4gICAgICAgIGlmKHZvbHVtZSA8IDApe1xuICAgICAgICAgICAgdm9sdW1lID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFtID0gQXVkaW9NYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIGFtLmdhaW5Ob2Rlc1tjaGFubmVsXS5nYWluLnNldFZhbHVlQXRUaW1lKHZvbHVtZSwgYW0uYXVkaW9DdHguY3VycmVudFRpbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIEdhaW5Ob2RlIGZvciB0aGlzIGNoYW5uZWwuXG4gICAgICogTGVhcm4gbW9yZSBhYm91dCBHYWluTm9kZXMgaGVyZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvR2Fpbk5vZGVcbiAgICAgKiBET04nVCBVU0UgVEhJUyBVTkxFU1MgWU9VIEtOT1cgV0hBVCBZT1UnUkUgRE9JTkdcbiAgICAgKiBAcGFyYW0gY2hhbm5lbCBUaGUgY2hhbm5lbFxuICAgICAqIEByZXR1cm5zIFRoZSBHYWluTm9kZSBmb3IgdGhlIHNwZWNpZmllZCBjaGFubmVsXG4gICAgICovXG4gICAgZ2V0Q2hhbm5lbEdhaW5Ob2RlKGNoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGUpe1xuICAgICAgICByZXR1cm4gdGhpcy5nYWluTm9kZXNbY2hhbm5lbF07XG4gICAgfVxuICAgIFxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBQbGF5IGVhY2ggYXVkaW8gY2xpcCByZXF1ZXN0ZWRcbiAgICAgICAgLy8gVE9ETyAtIEFkZCBsb2dpYyB0byBtZXJnZSBzb3VuZHMgaWYgdGhlcmUgYXJlIG11bHRpcGxlIG9mIHRoZSBzYW1lIGtleVxuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQgfHwgZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5QTEFZX01VU0lDIHx8IGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuUExBWV9TRlgpe1xuICAgICAgICAgICAgICAgIGxldCBzb3VuZEtleSA9IGV2ZW50LmRhdGEuZ2V0KFwia2V5XCIpO1xuICAgICAgICAgICAgICAgIGxldCBsb29wID0gZXZlbnQuZGF0YS5nZXQoXCJsb29wXCIpO1xuICAgICAgICAgICAgICAgIGxldCBob2xkUmVmZXJlbmNlID0gZXZlbnQuZGF0YS5nZXQoXCJob2xkUmVmZXJlbmNlXCIpO1xuXG4gICAgICAgICAgICAgICAgbGV0IGNoYW5uZWwgPSBBdWRpb0NoYW5uZWxUeXBlLkRFRkFVTFQ7XG5cbiAgICAgICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlBMQVlfTVVTSUMpe1xuICAgICAgICAgICAgICAgICAgICBjaGFubmVsID0gQXVkaW9DaGFubmVsVHlwZS5NVVNJQztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoR2FtZUV2ZW50VHlwZS5QTEFZX1NGWCl7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5uZWwgPSBBdWRpb0NoYW5uZWxUeXBlLlNGWDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZXZlbnQuZGF0YS5oYXMoXCJjaGFubmVsXCIpKXtcbiAgICAgICAgICAgICAgICAgICAgY2hhbm5lbCA9IGV2ZW50LmRhdGEuZ2V0KFwiY2hhbm5lbFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBsYXlTb3VuZChzb3VuZEtleSwgbG9vcCwgaG9sZFJlZmVyZW5jZSwgY2hhbm5lbCwgZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuU1RPUF9TT1VORCl7XG4gICAgICAgICAgICAgICAgbGV0IHNvdW5kS2V5ID0gZXZlbnQuZGF0YS5nZXQoXCJrZXlcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9wU291bmQoc291bmRLZXkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLk1VVEVfQ0hBTk5FTCl7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRlQ2hhbm5lbChldmVudC5kYXRhLmdldChcImNoYW5uZWxcIikpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlVOTVVURV9DSEFOTkVMKXtcbiAgICAgICAgICAgICAgICB0aGlzLnVubXV0ZUNoYW5uZWwoZXZlbnQuZGF0YS5nZXQoXCJjaGFubmVsXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGVudW0gQXVkaW9DaGFubmVsVHlwZSB7XG4gICAgREVGQVVMVCA9IDAsXG4gICAgU0ZYID0gMSxcbiAgICBNVVNJQyA9IDIsXG4gICAgQ1VTVE9NXzEgPSAzLFxuICAgIENVU1RPTV8yID0gNCxcbiAgICBDVVNUT01fMyA9IDUsXG4gICAgQ1VTVE9NXzQgPSA2LFxuICAgIENVU1RPTV81ID0gNyxcbiAgICBDVVNUT01fNiA9IDgsXG4gICAgQ1VTVE9NXzcgPSA5LFxuICAgIENVU1RPTV84ID0gMTAsXG4gICAgQ1VTVE9NXzkgPSAxMSxcbn1cblxuZXhwb3J0IGNvbnN0IE1BWF9BVURJT19DSEFOTkVMUyA9IDEyOyIsImltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCBUaW1lck1hbmFnZXIgZnJvbSBcIi4vVGltZXJNYW5hZ2VyXCI7XG5cbi8qKiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGltZXIgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcblxuICAgIC8qKiBUaGUgY3VycmVudCBzdGF0ZSBvZiB0aGlzIHRpbWVyICovXG4gICAgcHJvdGVjdGVkIHN0YXRlOiBUaW1lclN0YXRlO1xuICAgIFxuICAgIC8qKiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoaXMgdGltZXIgZW5kcyAqL1xuICAgIHByb3RlY3RlZCBvbkVuZDogRnVuY3Rpb247XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyB0aW1lciBzaG91bGQgbG9vcCAqL1xuICAgIHByb3RlY3RlZCBsb29wOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSB0b3RhbCBhbW91bnQgb2YgdGltZSB0aGlzIHRpbWVyIHJ1bnMgZm9yICovXG4gICAgcHJvdGVjdGVkIHRvdGFsVGltZTogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBhbW91bnQgb2YgdGltZSBsZWZ0IG9uIHRoZSBjdXJyZW50IHJ1biAqL1xuICAgIHByb3RlY3RlZCB0aW1lTGVmdDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBudW1iZXIgb2YgdGltZXMgdGhpcyB0aW1lciBoYXMgYmVlbiBydW4gKi9cbiAgICBwcm90ZWN0ZWQgbnVtUnVuczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IodGltZTogbnVtYmVyLCBvbkVuZD86IEZ1bmN0aW9uLCBsb29wOiBib29sZWFuID0gZmFsc2Upe1xuICAgICAgICAvLyBSZWdpc3RlciB0aGlzIHRpbWVyXG4gICAgICAgIFRpbWVyTWFuYWdlci5nZXRJbnN0YW5jZSgpLmFkZFRpbWVyKHRoaXMpO1xuICAgICAgICBcbiAgICAgICAgdGhpcy50b3RhbFRpbWUgPSB0aW1lO1xuICAgICAgICB0aGlzLnRpbWVMZWZ0ID0gMDtcbiAgICAgICAgdGhpcy5vbkVuZCA9IG9uRW5kO1xuICAgICAgICB0aGlzLmxvb3AgPSBsb29wO1xuICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5TVE9QUEVEO1xuICAgICAgICB0aGlzLm51bVJ1bnMgPSAwO1xuICAgIH1cblxuICAgIGlzU3RvcHBlZCgpe1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZSA9PT0gVGltZXJTdGF0ZS5TVE9QUEVEO1xuICAgIH1cblxuICAgIGlzUGF1c2VkKCl7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlID09PSBUaW1lclN0YXRlLlBBVVNFRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoaXMgdGltZXIgaGFzIGJlZW4gcnVuIGJlZm9yZVxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgaXQgaGFzIGJlZW4gcnVuIGF0IGxlYXN0IG9uY2UgKGFmdGVyIHRoZSBsYXRlc3QgcmVzZXQpLCBhbmQgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaGFzUnVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5udW1SdW5zID4gMDtcbiAgICB9XG5cbiAgICBzdGFydCh0aW1lPzogbnVtYmVyKXtcbiAgICAgICAgaWYodGltZSAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHRoaXMudG90YWxUaW1lID0gdGltZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5BQ1RJVkU7XG4gICAgICAgIHRoaXMudGltZUxlZnQgPSB0aGlzLnRvdGFsVGltZTtcbiAgICB9XG5cbiAgICAvKiogUmVzZXRzIHRoaXMgdGltZXIuIFNldHMgdGhlIHByb2dyZXNzIGJhY2sgdG8gemVybywgYW5kIHNldHMgdGhlIG51bWJlciBvZiBydW5zIGJhY2sgdG8gemVybyAqL1xuICAgIHJlc2V0KCl7XG4gICAgICAgIHRoaXMudGltZUxlZnQgPSB0aGlzLnRvdGFsVGltZTtcbiAgICAgICAgdGhpcy5udW1SdW5zID0gMDtcbiAgICB9XG5cbiAgICBwYXVzZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IFRpbWVyU3RhdGUuUEFVU0VEO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcil7XG4gICAgICAgIGlmKHRoaXMuc3RhdGUgPT09IFRpbWVyU3RhdGUuQUNUSVZFKXtcbiAgICAgICAgICAgIHRoaXMudGltZUxlZnQgLT0gZGVsdGFUKjEwMDA7XG5cbiAgICAgICAgICAgIGlmKHRoaXMudGltZUxlZnQgPD0gMCl7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lTGVmdCA9IE1hdGhVdGlscy5jbGFtcExvdzAodGhpcy50aW1lTGVmdCk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBlbmQoKXtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBzdGF0ZVxuICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5TVE9QUEVEO1xuICAgICAgICB0aGlzLm51bVJ1bnMgKz0gMTtcblxuICAgICAgICAvLyBDYWxsIHRoZSBlbmQgZnVuY3Rpb24gaWYgdGhlcmUgaXMgb25lXG4gICAgICAgIGlmKHRoaXMub25FbmQpe1xuICAgICAgICAgICAgdGhpcy5vbkVuZCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTG9vcCBpZiB3ZSB3YW50IHRvXG4gICAgICAgIGlmKHRoaXMubG9vcCl7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5BQ1RJVkU7XG4gICAgICAgICAgICB0aGlzLnRpbWVMZWZ0ID0gdGhpcy50b3RhbFRpbWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0b1N0cmluZygpOiBzdHJpbmd7XG4gICAgICAgIHJldHVybiBcIlRpbWVyOiBcIiArIHRoaXMuc3RhdGUgKyBcIiAtIFRpbWUgTGVmdDogXCIgKyB0aGlzLnRpbWVMZWZ0ICsgXCJtcyBvZiBcIiArIHRoaXMudG90YWxUaW1lICsgXCJtc1wiO1xuICAgIH1cbn1cblxuZXhwb3J0IGVudW0gVGltZXJTdGF0ZSB7XG4gICAgQUNUSVZFID0gXCJBQ1RJVkVcIixcbiAgICBQQVVTRUQgPSBcIlBBVVNFRFwiLFxuICAgIFNUT1BQRUQgPSBcIlNUT1BQRURcIlxufSIsImltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4vVGltZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGltZXJNYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cbiAgICBwcm90ZWN0ZWQgdGltZXJzOiBBcnJheTxUaW1lcj47XG5cbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnRpbWVycyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzdGF0aWMgaW5zdGFuY2U6IFRpbWVyTWFuYWdlcjtcblxuICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBUaW1lck1hbmFnZXIge1xuICAgICAgICBpZighdGhpcy5pbnN0YW5jZSl7XG4gICAgICAgICAgICB0aGlzLmluc3RhbmNlID0gbmV3IFRpbWVyTWFuYWdlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgYWRkVGltZXIodGltZXI6IFRpbWVyKXtcbiAgICAgICAgdGhpcy50aW1lcnMucHVzaCh0aW1lcik7XG4gICAgfVxuXG4gICAgY2xlYXJUaW1lcnMoKXtcbiAgICAgICAgdGhpcy50aW1lcnMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50aW1lcnMuZm9yRWFjaCh0aW1lciA9PiB0aW1lci51cGRhdGUoZGVsdGFUKSk7XG4gICAgfVxufSIsImltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4vTWF0aFV0aWxzXCI7XG5cbi8vIFRPRE86IFRoaXMgc2hvdWxkIGJlIG1vdmVkIHRvIHRoZSBkYXRhdHlwZXMgZm9sZGVyXG4vKipcbiAqIEEgQ29sb3IgdXRpbCBjbGFzcyB0aGF0IGtlZXBzIHRyYWNrIG9mIGNvbG9ycyBsaWtlIGEgdmVjdG9yLCBidXQgY2FuIGJlIGNvbnZlcnRlZCBpbnRvIGEgc3RyaW5nIGZvcm1hdFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2xvciB7XG5cdC8qKiBUaGUgcmVkIHZhbHVlICovXG5cdHB1YmxpYyByOiBudW1iZXI7XG5cdC8qKiBUaGUgZ3JlZW4gdmFsdWUgKi9cblx0cHVibGljIGc6IG51bWJlcjtcblx0LyoqIFRoZSBibHVlIHZhbHVlICovXG5cdHB1YmxpYyBiOiBudW1iZXI7XG5cdC8qKiBUaGUgYWxwaGEgdmFsdWUgKi9cblx0cHVibGljIGE6IG51bWJlcjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBjb2xvclxuXHQgKiBAcGFyYW0gciBSZWRcblx0ICogQHBhcmFtIGcgR3JlZW5cblx0ICogQHBhcmFtIGIgQmx1ZVxuXHQgKiBAcGFyYW0gYSBBbHBoYVxuXHQgKi9cblx0Y29uc3RydWN0b3IocjogbnVtYmVyID0gMCwgZzogbnVtYmVyID0gMCwgYjogbnVtYmVyID0gMCwgYTogbnVtYmVyID0gMSl7XG4gICAgICAgIHRoaXMuciA9IHI7XG4gICAgICAgIHRoaXMuZyA9IGc7XG4gICAgICAgIHRoaXMuYiA9IGI7XG4gICAgICAgIHRoaXMuYSA9IGE7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBUcmFuc3BhcmVudCBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2JhKDAsIDAsIDAsIDApXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IFRSQU5TUEFSRU5UKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDAsIDAsIDAsIDApO1xuXHR9XG5cdFxuXHQvKipcdFxuXHQgKiBSZWQgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMCwgMClcblx0ICovXG5cdHN0YXRpYyBnZXQgUkVEKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDI1NSwgMCwgMCwgMSk7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBHcmVlbiBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMjU1LCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBHUkVFTigpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigwLCAyNTUsIDAsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogQmx1ZSBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMCwgMjU1KVxuXHQgKi9cblx0c3RhdGljIGdldCBCTFVFKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDAsIDAsIDI1NSwgMSk7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBZZWxsb3cgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMjU1LCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBZRUxMT1coKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMjU1LCAyNTUsIDAsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogTWFnZW50YSBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMjU1LCAwLCAyNTUpXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IE1BR0VOVEEoKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMjU1LCAwLCAyNTUsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogQ3lhbiBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMjU1LCAyNTUpXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IENZQU4oKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMCwgMjU1LCAyNTUsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogV2hpdGUgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMjU1LCAyNTUpXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IFdISVRFKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDI1NSwgMjU1LCAyNTUsIDEpO1xuXHR9IFxuXG5cdC8qKlx0XG5cdCAqIEJsYWNrIGNvbG9yXG5cdCAqIEByZXR1cm5zIHJnYigwLCAwLCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBCTEFDSygpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigwLCAwLCAwLCAxKTtcblx0fVxuXG5cdC8qKlx0XG5cdCAqIE9yYW5nZSBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMjU1LCAxMDAsIDApXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IE9SQU5HRSgpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigyNTUsIDEwMCwgMCwgMSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgY29sb3IgdG8gdGhlIHZhbHVlcyBwcm92aWRlZFxuXHQgKiBAcGFyYW0gciBSZWRcblx0ICogQHBhcmFtIGcgR3JlZW5cblx0ICogQHBhcmFtIGIgQmx1ZVxuXHQgKiBAcGFyYW0gYSBBbHBoYVxuXHQgKi9cblx0c2V0KHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIsIGE6IG51bWJlciA9IDEpOiB2b2lkIHtcblx0XHR0aGlzLnIgPSByO1xuXHRcdHRoaXMuZyA9IGc7XG5cdFx0dGhpcy5iID0gYjtcblx0XHR0aGlzLmEgPSBhO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBuZXcgY29sb3Igc2xpZ2h0bHkgbGlnaHRlciB0aGFuIHRoZSBjdXJyZW50IGNvbG9yXG5cdCAqIEByZXR1cm5zIEEgbmV3IGxpZ2h0ZXIgQ29sb3Jcblx0ICovXG5cdGxpZ2h0ZW4oKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoTWF0aFV0aWxzLmNsYW1wKHRoaXMuciArIDQwLCAwLCAyNTUpLCBNYXRoVXRpbHMuY2xhbXAodGhpcy5nICsgNDAsIDAsIDI1NSksIE1hdGhVdGlscy5jbGFtcCh0aGlzLmIgKyA0MCwgMCwgMjU1KSwgTWF0aFV0aWxzLmNsYW1wKHRoaXMuYSArIDEwLCAwLCAyNTUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IGNvbG9yIHNsaWdodGx5IGRhcmtlciB0aGFuIHRoZSBjdXJyZW50IGNvbG9yXG5cdCAqIEByZXR1cm5zIEEgbmV3IGRhcmtlciBDb2xvclxuXHQgKi9cblx0ZGFya2VuKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKE1hdGhVdGlscy5jbGFtcCh0aGlzLnIgLSA0MCwgMCwgMjU1KSwgTWF0aFV0aWxzLmNsYW1wKHRoaXMuZyAtIDQwLCAwLCAyNTUpLCBNYXRoVXRpbHMuY2xhbXAodGhpcy5iIC0gNDAsIDAsIDI1NSksIE1hdGhVdGlscy5jbGFtcCh0aGlzLmEgKyAxMCwgMCwgMjU1KSk7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoaXMgY29sb3IgYXMgYW4gYXJyYXlcblx0ICogQHJldHVybnMgW3IsIGcsIGIsIGFdXG5cdCAqL1xuXHR0b0FycmF5KCk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdIHtcblx0XHRyZXR1cm4gW3RoaXMuciwgdGhpcy5nLCB0aGlzLmIsIHRoaXMuYV07XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBjb2xvciBhcyBhIHN0cmluZyBvZiB0aGUgZm9ybSAjUlJHR0JCXG5cdCAqIEByZXR1cm5zICNSUkdHQkJcblx0ICovXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiI1wiICsgTWF0aFV0aWxzLnRvSGV4KHRoaXMuciwgMikgKyBNYXRoVXRpbHMudG9IZXgodGhpcy5nLCAyKSArIE1hdGhVdGlscy50b0hleCh0aGlzLmIsIDIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGNvbG9yIGFzIGEgc3RyaW5nIG9mIHRoZSBmb3JtIHJnYihyLCBnLCBiKVxuXHQgKiBAcmV0dXJucyByZ2IociwgZywgYilcblx0ICovXG5cdHRvU3RyaW5nUkdCKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwicmdiKFwiICsgdGhpcy5yLnRvU3RyaW5nKCkgKyBcIiwgXCIgKyB0aGlzLmcudG9TdHJpbmcoKSArIFwiLCBcIiArIHRoaXMuYi50b1N0cmluZygpICsgXCIpXCI7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY29sb3IgYXMgYSBzdHJpbmcgb2YgdGhlIGZvcm0gcmdiYShyLCBnLCBiLCBhKVxuXHQgKiBAcmV0dXJucyByZ2JhKHIsIGcsIGIsIGEpXG5cdCAqL1xuXHR0b1N0cmluZ1JHQkEoKTogc3RyaW5nIHtcblx0XHRpZih0aGlzLmEgPT09IDApe1xuXHRcdFx0cmV0dXJuIHRoaXMudG9TdHJpbmdSR0IoKTtcblx0XHR9XG5cdFx0cmV0dXJuIFwicmdiYShcIiArIHRoaXMuci50b1N0cmluZygpICsgXCIsIFwiICsgdGhpcy5nLnRvU3RyaW5nKCkgKyBcIiwgXCIgKyB0aGlzLmIudG9TdHJpbmcoKSArIFwiLCBcIiArIHRoaXMuYS50b1N0cmluZygpICtcIilcIlxuXHR9XG5cblx0LyoqXG5cdCAqIFR1cm5zIHRoaXMgY29sb3IgaW50byBhIGZsb2F0MzJBcnJheSBhbmQgY2hhbmdlcyBjb2xvciByYW5nZSB0byBbMC4wLCAxLjBdXG5cdCAqIEByZXR1cm5zIGEgRmxvYXQzMkFycmF5IGNvbnRhaW5pbmcgdGhlIGNvbG9yXG5cdCAqL1xuXHR0b1dlYkdMKCk6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0dGhpcy5yLzI1NSxcblx0XHRcdHRoaXMuZy8yNTUsXG5cdFx0XHR0aGlzLmIvMjU1LFxuXHRcdFx0dGhpcy5hXG5cdFx0XSk7XG5cdH1cblxuXHRzdGF0aWMgZnJvbVN0cmluZ0hleChzdHI6IHN0cmluZyk6IENvbG9yIHtcblx0XHRsZXQgaSA9IDA7XG5cdFx0aWYoc3RyLmNoYXJBdCgwKSA9PSBcIiNcIikgaSs9IDE7XG5cdFx0bGV0IHIgPSBNYXRoVXRpbHMuZnJvbUhleChzdHIuc3Vic3RyaW5nKGksIGkrMikpO1xuXHRcdGxldCBnID0gTWF0aFV0aWxzLmZyb21IZXgoc3RyLnN1YnN0cmluZyhpKzIsIGkrNCkpO1xuXHRcdGxldCBiID0gTWF0aFV0aWxzLmZyb21IZXgoc3RyLnN1YnN0cmluZyhpKzQsIGkrNikpO1xuXHRcdHJldHVybiBuZXcgQ29sb3IociwgZywgYik7XG5cdH1cbn0iLCIvLyBAaWdub3JlUGFnZVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFYXNlRnVuY3Rpb25zIHtcblxuICAgIHN0YXRpYyBlYXNlSW5PdXRTaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiAtKE1hdGguY29zKE1hdGguUEkgKiB4KSAtIDEpIC8gMjtcbiAgICB9XG5cbiAgICBzdGF0aWMgZWFzZU91dEluU2luZSh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4geCA8IDAuNSA/IC1NYXRoLmNvcyhNYXRoLlBJKih4ICsgMC41KSkvMiA6IC1NYXRoLmNvcyhNYXRoLlBJKih4IC0gMC41KSkvMiArIDE7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VPdXRTaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBNYXRoLnNpbigoeCAqIE1hdGguUEkpIC8gMik7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VJblNpbmUoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIDEgLSBNYXRoLmNvcygoeCAqIE1hdGguUEkpIC8gMik7IFxuICAgIH1cblxuICAgIHN0YXRpYyBlYXNlSW5PdXRRdWludCh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4geCA8IDAuNSA/IDE2ICogeCAqIHggKiB4ICogeCAqIHggOiAxIC0gTWF0aC5wb3coLTIgKiB4ICsgMiwgNSkgLyAyOyAgICBcbiAgICB9XG5cbiAgICBzdGF0aWMgZWFzZUluT3V0UXVhZCh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4geCA8IDAuNSA/IDIgKiB4ICogeCA6IDEgLSBNYXRoLnBvdygtMiAqIHggKyAyLCAyKSAvIDI7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VPdXRJblF1YWQoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwLjUgPyB0aGlzLmVhc2VPdXRJbl9PdXRQb3coeCwgMikgOiB0aGlzLmVhc2VPdXRJbl9JblBvdyh4LCAyKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBlYXNlT3V0SW5fT3V0UG93KHg6IG51bWJlciwgcG93OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gMC41IC0gTWF0aC5wb3coLTIgKiB4ICsgMSwgcG93KSAvIDI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZWFzZU91dEluX0luUG93KHg6IG51bWJlciwgcG93OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gMC41ICsgTWF0aC5wb3coMiAqIHggLSAxLCBwb3cpIC8gMjtcbiAgICB9XG59XG5cbmV4cG9ydCBlbnVtIEVhc2VGdW5jdGlvblR5cGUge1xuICAgIC8vIFNJTkVcbiAgICBJTl9PVVRfU0lORSA9IFwiZWFzZUluT3V0U2luZVwiLFxuICAgIE9VVF9JTl9TSU5FID0gXCJlYXNlT3V0SW5TaW5lXCIsXG4gICAgSU5fU0lORSA9IFwiZWFzZUluU2luZVwiLFxuICAgIE9VVF9TSU5FID0gXCJlYXNlT3V0U2luZVwiLFxuXG4gICAgLy8gUVVBRFxuICAgIElOX09VVF9RVUFEID0gXCJlYXNlSW5PdXRRdWFkXCIsXG4gICAgT1VUX0lOX1FVQUQgPSBcImVhc2VPdXRJblF1YWRcIixcblxuICAgIC8vIFFVSU5UXG4gICAgSU5fT1VUX1FVSU5UID0gXCJlYXNlSW5PdXRRdWludFwiXG59IiwiaW1wb3J0IEdyYXBoIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoXCI7XG5pbXBvcnQgRWRnZU5vZGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9HcmFwaHMvRWRnZU5vZGVcIjtcblxuLyoqIEEgY2xhc3MgdG8gcHJvdmlkZXMgc29tZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgZ3JhcGhzICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHcmFwaFV0aWxzIHtcblxuXHQvKipcblx0ICogQW4gaW1wbGVtZW50YXRpb24gb2YgRGppa3N0cmEncyBzaG9ydGVzdCBwYXRoIGFsZ29yaXRobSBiYXNlZCBvbiB0aGUgb25lIGRlc2NyaWJlZCBpbiBUaGUgQWxnb3JpdGhtIERlc2lnbiBNYW51YWwuXG5cdCAqIEBwYXJhbSBnIFRoZSBncmFwaFxuXHQgKiBAcGFyYW0gc3RhcnQgVGhlIG51bWJlciB0byBzdGFydCB0aGUgc2hvcnRlc3QgcGF0aCBmcm9tXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHBhcmVudCBvZiBlYWNoIG5vZGUgb2YgdGhlIEdyYXBoIGluIHRoZSBzaG9ydGVzdCBwYXRoLlxuXHQgKi9cblx0c3RhdGljIGRqaWtzdHJhKGc6IEdyYXBoLCBzdGFydDogbnVtYmVyKTogQXJyYXk8bnVtYmVyPiB7XG5cdFx0bGV0IGk6IG51bWJlcjtcdFx0Ly8gQ291bnRlclxuXHRcdGxldCBwOiBFZGdlTm9kZTtcdC8vIFBvaW50ZXIgdG8gZWRnZW5vZGVcblx0XHRsZXQgaW5UcmVlOiBBcnJheTxib29sZWFuPiA9IG5ldyBBcnJheShnLm51bVZlcnRpY2VzKTtcblx0XHRsZXQgZGlzdGFuY2U6IEFycmF5PG51bWJlcj4gPSBuZXcgQXJyYXkoZy5udW1WZXJ0aWNlcyk7XG5cdFx0bGV0IHBhcmVudDogQXJyYXk8bnVtYmVyPiA9IG5ldyBBcnJheShnLm51bVZlcnRpY2VzKTtcblx0XHRsZXQgdjogbnVtYmVyO1x0XHQvLyBDdXJyZW50IHZlcnRleCB0byBwcm9jZXNzXG5cdFx0bGV0IHc6IG51bWJlcjsgXHRcdC8vIENhbmRpZGF0ZSBmb3IgbmV4dCB2ZXJ0ZXhcblx0XHRsZXQgd2VpZ2h0OiBudW1iZXI7XHQvLyBFZGdlIHdlaWdodFxuXHRcdGxldCBkaXN0O1x0XHRcdC8vIEJlc3QgY3VycmVudCBkaXN0YW5jZSBmcm9tIHN0YXJ0XG5cblx0XHRmb3IoaSA9IDA7IGkgPCBnLm51bVZlcnRpY2VzOyBpKyspe1xuXHRcdFx0aW5UcmVlW2ldID0gZmFsc2U7XG5cdFx0XHRkaXN0YW5jZVtpXSA9IEluZmluaXR5O1xuXHRcdFx0cGFyZW50W2ldID0gLTE7XG5cdFx0fVxuXG5cdFx0ZGlzdGFuY2Vbc3RhcnRdID0gMDtcblx0XHR2ID0gc3RhcnQ7XG5cblx0XHR3aGlsZSghaW5UcmVlW3ZdKXtcblx0XHRcdGluVHJlZVt2XSA9IHRydWU7XG5cdFx0XHRwID0gZy5lZGdlc1t2XTtcblxuXHRcdFx0d2hpbGUocCAhPT0gbnVsbCl7XG5cdFx0XHRcdHcgPSBwLnk7XG5cdFx0XHRcdHdlaWdodCA9IHAud2VpZ2h0O1xuXG5cdFx0XHRcdGlmKGRpc3RhbmNlW3ddID4gZGlzdGFuY2Vbdl0gKyB3ZWlnaHQpe1xuXHRcdFx0XHRcdGRpc3RhbmNlW3ddID0gZGlzdGFuY2Vbdl0gKyB3ZWlnaHQ7XG5cdFx0XHRcdFx0cGFyZW50W3ddID0gdjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHAgPSBwLm5leHQ7XG5cdFx0XHR9XG5cblx0XHRcdHYgPSAwO1xuXG5cdFx0XHRkaXN0ID0gSW5maW5pdHk7XG5cblx0XHRcdGZvcihpID0gMDsgaSA8PSBnLm51bVZlcnRpY2VzOyBpKyspe1xuXHRcdFx0XHRpZighaW5UcmVlW2ldICYmIGRpc3QgPiBkaXN0YW5jZVtpXSl7XG5cdFx0XHRcdFx0ZGlzdCA9IGRpc3RhbmNlO1xuXHRcdFx0XHRcdHYgPSBpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHBhcmVudDtcblxuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5cbi8qKiBBIGNsYXNzIGNvbnRhaW5pbmcgc29tZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgbWF0aCBvcGVyYXRpb25zICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNYXRoVXRpbHMge1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpZ24gb2YgdGhlIHZhbHVlIHByb3ZpZGVkXG4gICAgICogQHBhcmFtIHggVGhlIHZhbHVlIHRvIGV4dHJhY3QgdGhlIHNpZ24gZnJvbVxuICAgICAqIEByZXR1cm5zIC0xIGlmIHRoZSBudW1iZXIgaXMgbGVzcyB0aGFuIDAsIDEgb3RoZXJ3aXNlXG4gICAgICovXG4gICAgc3RhdGljIHNpZ24oeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwID8gLTEgOiAxO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBvciBub3QgeCBpcyBiZXR3ZWVuIGEgYW5kIGJcbiAgICAgKiBAcGFyYW0gYSBUaGUgbWluIGJvdW5kXG4gICAgICogQHBhcmFtIGIgVGhlIG1heCBib3VuZFxuICAgICAqIEBwYXJhbSB4IFRoZSB2YWx1ZSB0byBjaGVja1xuICAgICAqIEBwYXJhbSBleGNsdXNpdmUgV2hldGhlciBvciBub3QgYSBhbmQgYiBhcmUgZXhjbHVzaXZlIGJvdW5kc1xuICAgICAqIEByZXR1cm5zIFRydWUgaWYgeCBpcyBiZXR3ZWVuIGEgYW5kIGIsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHN0YXRpYyBiZXR3ZWVuKGE6IG51bWJlciwgYjogbnVtYmVyLCB4OiBudW1iZXIsIGV4Y2x1c2l2ZT86IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICAgICAgaWYoZXhjbHVzaXZlKXtcbiAgICAgICAgICAgIHJldHVybiAoYSA8IHgpICYmICh4IDwgYik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gKGEgPD0geCkgJiYgKHggPD0gYik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgdGhlIHZhbHVlIHggdG8gdGhlIHJhbmdlIFttaW4sIG1heF0sIHJvdW5kaW5nIHVwIG9yIGRvd24gaWYgbmVlZGVkXG4gICAgICogQHBhcmFtIHggVGhlIHZhbHVlIHRvIGJlIGNsYW1wZWRcbiAgICAgKiBAcGFyYW0gbWluIFRoZSBtaW4gb2YgdGhlIHJhbmdlXG4gICAgICogQHBhcmFtIG1heCBUaGUgbWF4IG9mIHRoZSByYW5nZVxuICAgICAqIEByZXR1cm5zIHgsIGlmIGl0IGlzIGJldHdlZW4gbWluIGFuZCBtYXgsIG9yIG1pbi9tYXggaWYgaXQgZXhjZWVkcyB0aGVpciBib3VuZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXAoeDogbnVtYmVyLCBtaW46IG51bWJlciwgbWF4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZih4IDwgbWluKSByZXR1cm4gbWluO1xuICAgICAgICBpZih4ID4gbWF4KSByZXR1cm4gbWF4O1xuICAgICAgICByZXR1cm4geDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgdGhlIHZhbHVlIHggdG8gdGhlIHJhbmdlIGJldHdlZW4gMCBhbmQgMVxuICAgICAqIEBwYXJhbSB4IFRoZSB2YWx1ZSB0byBiZSBjbGFtcGVkXG4gICAgICogQHJldHVybnMgeCwgaWYgaXQgaXMgYmV0d2VlbiAwIGFuZCAxLCBvciAwLzEgaWYgaXQgZXhjZWVkcyB0aGVpciBib3VuZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXAwMSh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTWF0aFV0aWxzLmNsYW1wKHgsIDAsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyB0aGUgbG93ZXIgZW5kIG9mIHRoZSB2YWx1ZSBvZiB4IHRvIHRoZSByYW5nZSB0byBtaW5cbiAgICAgKiBAcGFyYW0geCBUaGUgdmFsdWUgdG8gYmUgY2xhbXBlZFxuICAgICAqIEBwYXJhbSBtaW4gVGhlIG1pbmltdW0gYWxsb3dlZCB2YWx1ZSBvZiB4XG4gICAgICogQHJldHVybnMgeCwgaWYgaXQgaXMgZ3JlYXRlciB0aGFuIG1pbiwgb3RoZXJ3aXNlIG1pblxuICAgICAqL1xuICAgIHN0YXRpYyBjbGFtcExvdyh4OiBudW1iZXIsIG1pbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCBtaW4gPyBtaW4gOiB4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyB0aGUgbG93ZXIgZW5kIG9mIHRoZSB2YWx1ZSBvZiB4IHRvIHplcm9cbiAgICAgKiBAcGFyYW0geCBUaGUgdmFsdWUgdG8gYmUgY2xhbXBlZFxuICAgICAqIEByZXR1cm5zIHgsIGlmIGl0IGlzIGdyZWF0ZXIgdGhhbiAwLCBvdGhlcndpc2UgMFxuICAgICAqL1xuICAgIHN0YXRpYyBjbGFtcExvdzAoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5jbGFtcExvdyh4LCAwKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2xhbXBNYWduaXR1ZGUodjogVmVjMiwgbTogbnVtYmVyKTogVmVjMiB7XG4gICAgICAgIGlmKHYubWFnU3EoKSA+IG0qbSl7XG4gICAgICAgICAgICByZXR1cm4gdi5zY2FsZVRvKG0pO1xuICAgICAgICB9IGVsc2V7XG4gICAgICAgICAgICByZXR1cm4gdjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBjaGFuZ2VSYW5nZSh4OiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlciwgbmV3TWluOiBudW1iZXIsIG5ld01heDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGVycChuZXdNaW4sIG5ld01heCwgdGhpcy5pbnZMZXJwKG1pbiwgbWF4LCB4KSk7XG4gICAgfVxuXG4gICAgLyoqXG5cdCAqIExpbmVhciBJbnRlcnBvbGF0aW9uXG5cdCAqIEBwYXJhbSBhIFRoZSBmaXJzdCB2YWx1ZSBmb3IgdGhlIGludGVycG9sYXRpb24gYm91bmRcblx0ICogQHBhcmFtIGIgVGhlIHNlY29uZCB2YWx1ZSBmb3IgdGhlIGludGVycG9sYXRpb24gYm91bmRcblx0ICogQHBhcmFtIHQgVGhlIHRpbWUgd2UgYXJlIGludGVycG9sYXRpbmcgdG9cbiAgICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgYmV0d2VlbiBhIGFuZCBiIGF0IHRpbWUgdFxuXHQgKi9cblx0c3RhdGljIGxlcnAoYTogbnVtYmVyLCBiOiBudW1iZXIsIHQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBhICsgdCAqIChiIC0gYSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW52ZXJzZSBMaW5lYXIgSW50ZXJwb2xhdGlvbi4gRmluZHMgdGhlIHRpbWUgYXQgd2hpY2ggYSB2YWx1ZSBiZXR3ZWVuIGEgYW5kIGIgd291bGQgb2NjdXJcbiAgICAgKiBAcGFyYW0gYSBUaGUgZmlyc3QgdmFsdWUgZm9yIHRoZSBpbnRlcnBvbGF0aW9uIGJvdW5kXG4gICAgICogQHBhcmFtIGIgVGhlIHNlY29uZCB2YWx1ZSBmb3IgdGhlIGludGVycG9sYXRpb24gYm91bmRcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGN1cnJlbnQgdmFsdWVcbiAgICAgKiBAcmV0dXJucyBUaGUgdGltZSBhdCB3aGljaCB0aGUgY3VycmVudCB2YWx1ZSBvY2N1cnMgYmV0d2VlbiBhIGFuZCBiXG4gICAgICovXG4gICAgc3RhdGljIGludkxlcnAoYTogbnVtYmVyLCBiOiBudW1iZXIsIHZhbHVlOiBudW1iZXIpe1xuICAgICAgICByZXR1cm4gKHZhbHVlIC0gYSkvKGIgLSBhKTtcbiAgICB9XG4gICAgXG4gICAgLyoqXG4gICAgICogQ3V0cyBvZmYgZGVjaW1hbCBwb2ludHMgb2YgYSBudW1iZXIgYWZ0ZXIgYSBzcGVjaWZpZWQgcGxhY2VcbiAgICAgKiBAcGFyYW0gbnVtIFRoZSBudW1iZXIgdG8gZmxvb3JcbiAgICAgKiBAcGFyYW0gcGxhY2UgVGhlIGxhc3QgZGVjaW1hbCBwbGFjZSBvZiB0aGUgbmV3IG51bWJlclxuICAgICAqIEByZXR1cm5zIFRoZSBmbG9vcmVkIG51bWJlclxuICAgICAqL1xuICAgIHN0YXRpYyBmbG9vclRvUGxhY2UobnVtOiBudW1iZXIsIHBsYWNlOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZihwbGFjZSA9PT0gMCl7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihudW0pO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGZhY3RvciA9IDEwO1xuICAgICAgICB3aGlsZShwbGFjZSA+IDEpe1xuICAgICAgICAgICAgZmFjdG9yICE9IDEwO1xuICAgICAgICAgICAgcGxhY2UtLTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bSpmYWN0b3IpL2ZhY3RvcjtcblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBudW1iZXIgZnJvbSBhIGhleCBzdHJpbmdcbiAgICAgKiBAcGFyYW0gc3RyIHRoZSBzdHJpbmcgY29udGFpbmluZyB0aGUgaGV4IG51bWJlclxuICAgICAqIEByZXR1cm5zIHRoZSBudW1iZXIgaW4gZGVjaW1hbCByZXByZXNlbnRlZCBieSB0aGUgaGV4IHN0cmluZ1xuICAgICAqL1xuICAgIHN0YXRpYyBmcm9tSGV4KHN0cjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHN0ciwgMTYpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG51bWJlciBhcyBhIGhleGFkZWNpbWFsXG4gICAgICogQHBhcmFtIG51bSBUaGUgbnVtYmVyIHRvIGNvbnZlcnQgdG8gaGV4XG4gICAgICogQHBhcmFtIG1pbkxlbmd0aCBUaGUgbGVuZ3RoIG9mIHRoZSByZXR1cm5lZCBoZXggc3RyaW5nIChhZGRzIHplcm8gcGFkZGluZyBpZiBuZWVkZWQpXG4gICAgICogQHJldHVybnMgVGhlIGhleCByZXByZXNlbnRhdGlvbiBvZiB0aGUgbnVtYmVyIGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgc3RhdGljIHRvSGV4KG51bTogbnVtYmVyLCBtaW5MZW5ndGg6IG51bWJlciA9IG51bGwpOiBzdHJpbmcge1xuICAgICAgICBsZXQgZmFjdG9yID0gMTtcbiAgICAgICAgd2hpbGUoZmFjdG9yKjE2IDwgbnVtKXtcbiAgICAgICAgICAgIGZhY3RvciAqPSAxNjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaGV4U3RyID0gXCJcIjtcbiAgICAgICAgd2hpbGUoZmFjdG9yID49IDEpe1xuICAgICAgICAgICAgbGV0IGRpZ2l0ID0gTWF0aC5mbG9vcihudW0vZmFjdG9yKTtcbiAgICAgICAgICAgIGhleFN0ciArPSBNYXRoVXRpbHMudG9IZXhEaWdpdChkaWdpdCk7XG4gICAgICAgICAgICBudW0gLT0gZGlnaXQgKiBmYWN0b3I7XG4gICAgICAgICAgICBmYWN0b3IgLz0gMTY7XG5cdFx0fVxuXHRcdFxuXHRcdGlmKG1pbkxlbmd0aCAhPT0gbnVsbCl7XG5cdFx0XHR3aGlsZShoZXhTdHIubGVuZ3RoIDwgbWluTGVuZ3RoKXtcblx0XHRcdFx0aGV4U3RyID0gXCIwXCIgKyBoZXhTdHI7XG5cdFx0XHR9XG5cdFx0fVxuXG4gICAgICAgIHJldHVybiBoZXhTdHI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYSBkaWdpdCB0byBoZXhhZGVjaW1hbC4gSW4gdGhpcyBjYXNlLCBhIGRpZ2l0IGlzIGJldHdlZW4gMCBhbmQgMTUgaW5jbHVzaXZlXG4gICAgICogQHBhcmFtIG51bSBUaGUgZGlnaXQgdG8gY29udmVydCB0byBoZXhhZGVjaW1hbFxuICAgICAqIEByZXR1cm5zIFRoZSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGRpZ2l0IGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgc3RhdGljIHRvSGV4RGlnaXQobnVtOiBudW1iZXIpOiBzdHJpbmcge1xuICAgICAgICBpZihudW0gPCAxMCl7XG4gICAgICAgICAgICByZXR1cm4gXCJcIiArIG51bTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKDY1ICsgbnVtIC0gMTApO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuL0NvbG9yXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuL01hdGhVdGlsc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZW5kZXJpbmdVdGlscyB7XG5cdHN0YXRpYyB0b1dlYkdMQ29vcmRzKHBvaW50OiBWZWMyLCBvcmlnaW46IFZlYzIsIHdvcmxkU2l6ZTogVmVjMik6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0TWF0aFV0aWxzLmNoYW5nZVJhbmdlKHBvaW50LngsIG9yaWdpbi54LCBvcmlnaW4ueCArIHdvcmxkU2l6ZS54LCAtMSwgMSksXG5cdFx0XHRNYXRoVXRpbHMuY2hhbmdlUmFuZ2UocG9pbnQueSwgb3JpZ2luLnksIG9yaWdpbi55ICsgd29ybGRTaXplLnksIDEsIC0xKVxuXHRcdF0pO1xuXHR9XG5cblx0c3RhdGljIHRvV2ViR0xTY2FsZShzaXplOiBWZWMyLCB3b3JsZFNpemU6IFZlYzIpOiBGbG9hdDMyQXJyYXkge1xuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdDIqc2l6ZS54L3dvcmxkU2l6ZS54LFxuXHRcdFx0MipzaXplLnkvd29ybGRTaXplLnksXG5cdFx0XSk7XG5cdH1cblxuXHRzdGF0aWMgdG9XZWJHTENvbG9yKGNvbG9yOiBDb2xvcik6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0TWF0aFV0aWxzLmNoYW5nZVJhbmdlKGNvbG9yLnIsIDAsIDI1NSwgMCwgMSksXG5cdFx0XHRNYXRoVXRpbHMuY2hhbmdlUmFuZ2UoY29sb3IuZywgMCwgMjU1LCAwLCAxKSxcblx0XHRcdE1hdGhVdGlscy5jaGFuZ2VSYW5nZShjb2xvci5iLCAwLCAyNTUsIDAsIDEpLFxuXHRcdFx0Y29sb3IuYVxuXHRcdF0pO1xuXHR9XG59IiwiLyoqIFNvbWUgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIGRlYWxpbmcgd2l0aCBzdHJpbmdzICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTdHJpbmdVdGlscyB7XG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgdGhlIHBhdGggZnJvbSBhIGZpbGVwYXRoIHRoYXQgaW5jbHVkZXMgdGhlIGZpbGVcbiAgICAgKiBAcGFyYW0gZmlsZVBhdGggdGhlIGZpbGVwYXRoIHRvIGV4dHJhY3QgdGhlIHBhdGggZnJvbVxuICAgICAqIEByZXR1cm5zIFRoZSBwYXRoIHBvcnRpb24gb2YgdGhlIGZpbGVwYXRoIHByb3ZpZGVkXG4gICAgICovXG4gICAgc3RhdGljIGdldFBhdGhGcm9tRmlsZVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGxldCBzcGxpdFBhdGggPSBmaWxlUGF0aC5zcGxpdChcIi9cIik7XG4gICAgICAgIHNwbGl0UGF0aC5wb3AoKTtcbiAgICAgICAgc3BsaXRQYXRoLnB1c2goXCJcIik7XG4gICAgICAgIHJldHVybiBzcGxpdFBhdGguam9pbihcIi9cIik7XG4gICAgfVxufSIsIlxuaW1wb3J0IEdhbWUgZnJvbSBcIi4vV29sZmllMkQvTG9vcC9HYW1lXCI7XG5pbXBvcnQgTWFpbk1lbnUgZnJvbSBcIi4vc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9NYWluTWVudVwiO1xuaW1wb3J0IFJlZ2lzdHJ5TWFuYWdlciBmcm9tIFwiLi9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXJcIjtcbmltcG9ydCBXZWFwb25UZW1wbGF0ZVJlZ2lzdHJ5IGZyb20gXCIuL3NoYXR0ZXJlZF9zd29yZC9SZWdpc3RyeS9XZWFwb25SZWdpc3RyeVwiO1xuaW1wb3J0IFdlYXBvblR5cGVSZWdpc3RyeSBmcm9tIFwiLi9zaGF0dGVyZWRfc3dvcmQvUmVnaXN0cnkvV2VhcG9uVHlwZVJlZ2lzdHJ5XCI7XG5cbi8vIFRoZSBtYWluIGZ1bmN0aW9uIGlzIHlvdXIgZW50cnlwb2ludCBpbnRvIFdvbGZpZTJELiBTcGVjaWZ5IHlvdXIgZmlyc3Qgc2NlbmUgYW5kIGFueSBvcHRpb25zIGhlcmUuXG4oZnVuY3Rpb24gbWFpbigpe1xuICAgIC8vIFJ1biBhbnkgdGVzdHNcbiAgICBydW5UZXN0cygpO1xuXG4gICAgLy8gU2V0IHVwIG9wdGlvbnMgZm9yIG91ciBnYW1lXG4gICAgbGV0IG9wdGlvbnMgPSB7XG4gICAgICAgIGNhbnZhc1NpemU6IHt4OiB3aW5kb3cuaW5uZXJXaWR0aCwgeTogd2luZG93LmlubmVySGVpZ2h0fSwgICAgICAgICAgLy8gVGhlIHNpemUgb2YgdGhlIGdhbWVcbiAgICAgICAgY2xlYXJDb2xvcjoge3I6IDAsIGc6IDAsIGI6IDB9LCAgIC8vIFRoZSBjb2xvciB0aGUgZ2FtZSBjbGVhcnMgdG9cbiAgICAgICAgaW5wdXRzOiBbXG4gICAgICAgICAgICB7bmFtZTogXCJsZWZ0XCIsIGtleXM6IFtcImFcIiwgXCJhcnJvd2xlZnRcIl19LCAgICAvL1RPRE8gLSBhZGQgYXJyb3cga2V5c1xuICAgICAgICAgICAge25hbWU6IFwicmlnaHRcIiwga2V5czogW1wiZFwiLCBcImFycm93cmlnaHRcIl19LFxuICAgICAgICAgICAge25hbWU6IFwidXBcIiwga2V5czogW1wid1wiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJkb3duXCIsIGtleXM6IFtcInNcIl19LFxuICAgICAgICAgICAge25hbWU6IFwianVtcFwiLCBrZXlzOiBbXCJ4XCIsXCJzcGFjZVwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJhdHRhY2tcIiwga2V5czogW1wialwiLFwielwiLFwiZW50ZXJcIl19LCAgXG4gICAgICAgICAgICB7bmFtZTogXCJkYXNoXCIsIGtleXM6IFtcImtcIixcInpcIl19LFxuICAgICAgICAgICAge25hbWU6IFwic2tpbGxcIiwga2V5czogW1wibFwiLFwidlwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJpbnZlbnRvcnlcIiwga2V5czogW1wiaVwiLFwiYlwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJwYXVzZVwiLCBrZXlzOiBbXCJlc2NhcGVcIl19LCAgICBcbiAgICAgICAgICAgIHtuYW1lOiBcInRhYlwiLCBrZXlzOiBbXCJ0YWJcIl19ICAgLFxuICAgICAgICAgICAge25hbWU6IFwic3Bhd25cIiwga2V5czogW1wicVwiXX0gICAgICAgIC8vZGVidWcgZmVhdHVyZSB0byB0ZXN0IGVuZW15IHNwYXduaW5nLCBwcmVzcyBxIHRvIHNwYXduIGVuZW15IGF0IGN1cnJlbnQgbG9jYXRpb24gXG4gICAgICAgIF0sXG4gICAgICAgIHVzZVdlYkdMOiBmYWxzZSwgICAgICAgICAgICAgICAgICAgICAgICAvLyBUZWxsIHRoZSBnYW1lIHdlIHdhbnQgdG8gdXNlIHdlYmdsXG4gICAgICAgIHNob3dEZWJ1ZzogdHJ1ZSAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hldGhlciB0byBzaG93IGRlYnVnIG1lc3NhZ2VzLiBZb3UgY2FuIGNoYW5nZSB0aGlzIHRvIHRydWUgaWYgeW91IHdhbnRcbiAgICB9XG5cblxuICAgIC8vIFNldCB1cCBjdXN0b20gcmVnaXN0cmllc1xuICAgIGxldCB3ZWFwb25UZW1wbGF0ZVJlZ2lzdHJ5ID0gbmV3IFdlYXBvblRlbXBsYXRlUmVnaXN0cnkoKTtcbiAgICBSZWdpc3RyeU1hbmFnZXIuYWRkQ3VzdG9tUmVnaXN0cnkoXCJ3ZWFwb25UZW1wbGF0ZXNcIiwgd2VhcG9uVGVtcGxhdGVSZWdpc3RyeSk7XG4gICAgXG4gICAgbGV0IHdlYXBvblR5cGVSZWdpc3RyeSA9IG5ldyBXZWFwb25UeXBlUmVnaXN0cnkoKTtcbiAgICBSZWdpc3RyeU1hbmFnZXIuYWRkQ3VzdG9tUmVnaXN0cnkoXCJ3ZWFwb25UeXBlc1wiLCB3ZWFwb25UeXBlUmVnaXN0cnkpO1xuXG4gICAgLy8gQ3JlYXRlIGEgZ2FtZSB3aXRoIHRoZSBvcHRpb25zIHNwZWNpZmllZFxuICAgIGNvbnN0IGdhbWUgPSBuZXcgR2FtZShvcHRpb25zKTtcblxuICAgIC8vIFN0YXJ0IG91ciBnYW1lXG4gICAgZ2FtZS5zdGFydChNYWluTWVudSwge30pOyAgIFxuICAgIC8vVE9ETyAtIGNoYW5nZSB0byBzcGxhc2ggc2NyZWVuIG9uY2UgYXZhaWxhYmxlXG4gICAgLy9nYW1lLnN0YXJ0KFNwbGFzaFNjcmVlbix7fSk7XG59KSgpO1xuXG5mdW5jdGlvbiBydW5UZXN0cygpe307IiwiaW1wb3J0IEdvYXBBY3Rpb25QbGFubmVyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9BSS9Hb2FwQWN0aW9uUGxhbm5lclwiO1xuaW1wb3J0IFN0YXRlTWFjaGluZUFJIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9BSS9TdGF0ZU1hY2hpbmVBSVwiO1xuaW1wb3J0IFN0YXRlTWFjaGluZUdvYXBBSSBmcm9tIFwiLi4vLi4vV29sZmllMkQvQUkvU3RhdGVNYWNoaW5lR29hcEFJXCI7XG5pbXBvcnQgR29hcEFjdGlvbiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL0ludGVyZmFjZXMvR29hcEFjdGlvblwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IFN0YWNrIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvU3RhY2tcIjtcbmltcG9ydCBTdGF0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1N0YXRlL1N0YXRlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IE9ydGhvZ29uYWxUaWxlbWFwIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9UaWxlbWFwcy9PcnRob2dvbmFsVGlsZW1hcFwiO1xuaW1wb3J0IE5hdmlnYXRpb25QYXRoIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZpZ2F0aW9uUGF0aFwiO1xuaW1wb3J0IFdlYXBvbiBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uXCI7XG5pbXBvcnQgQmF0dGxlckFJIGZyb20gXCIuL0JhdHRsZXJBSVwiO1xuXG5pbXBvcnQgUGF0cm9sIGZyb20gXCIuL0VuZW15U3RhdGVzL1BhdHJvbFwiO1xuaW1wb3J0IHsgU3RhdHVzZXMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcblxuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcblxuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvTWF0aFV0aWxzXCI7XG5cbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEVuZW15QUkgZXh0ZW5kcyBTdGF0ZU1hY2hpbmVHb2FwQUkgaW1wbGVtZW50cyBCYXR0bGVyQUkge1xuICAgIC8qKiBUaGUgb3duZXIgb2YgdGhpcyBBSSAqL1xuICAgIG93bmVyOiBBbmltYXRlZFNwcml0ZTtcblxuICAgIC8qKiBUaGUgdG90YWwgcG9zc2libGUgYW1vdW50IG9mIGhlYWx0aCB0aGlzIGVudGl0eSBoYXMgKi9cbiAgICBtYXhIZWFsdGg6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgY3VycmVudCBhbW91bnQgb2YgaGVhbHRoIHRoaXMgZW50aXR5IGhhcyAqL1xuICAgIENVUlJFTlRfSFA6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgZGVmYXVsdCBtb3ZlbWVudCBzcGVlZCBvZiB0aGlzIEFJICovXG4gICAgc3BlZWQ6IG51bWJlciA9IDIwO1xuXG4gICAgLyoqIFRoZSB3ZWFwb24gdGhpcyBBSSBoYXMgKi9cbiAgICB3ZWFwb246IFdlYXBvbjtcblxuICAgIC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgcGxheWVyIG9iamVjdCAqL1xuICAgIHBsYXllcjogR2FtZU5vZGU7XG5cbiAgICAvLyBUaGUgY3VycmVudCBrbm93biBwb3NpdGlvbiBvZiB0aGUgcGxheWVyXG4gICAgcGxheWVyUG9zOiBWZWMyO1xuXG4gICAgLy8gVGhlIGxhc3Qga25vd24gcG9zaXRpb24gb2YgdGhlIHBsYXllclxuICAgIGxhc3RQbGF5ZXJQb3M6IFZlYzI7XG5cbiAgICAvLyBBdHRhY2sgcmFuZ2VcbiAgICBpblJhbmdlOiBudW1iZXI7XG5cbiAgICAvLyBQYXRoIHRvIHBsYXllclxuICAgIC8vcGF0aDogTmF2aWdhdGlvblBhdGg7XG5cbiAgICAvLyBQYXRoIGF3YXkgZnJvbSBwbGF5ZXJcbiAgICByZXRyZWF0UGF0aDogTmF2aWdhdGlvblBhdGg7XG5cbiAgICB0aWxlbWFwOiBPcnRob2dvbmFsVGlsZW1hcDtcblxuICAgIHZlbG9jaXR5OiBWZWMyID0gVmVjMi5aRVJPO1xuXG4gICAgZGlyZWN0aW9uOiBudW1iZXI7IC8vMSBmb3IgcmlnaHQsIC0xIGZvciBsZWZ0XG5cbiAgICBpbml0aWFsaXplQUkob3duZXI6IEFuaW1hdGVkU3ByaXRlLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG4gICAgICAgIHRoaXMub3duZXIgPSBvd25lcjtcblxuICAgICAgICAvL2FkZCBzdGF0ZXNcbiAgICAgICAgIC8vIFBhdHJvbCBtb2RlXG4gICAgICAgIHRoaXMuYWRkU3RhdGUoRW5lbXlTdGF0ZXMuREVGQVVMVCwgbmV3IFBhdHJvbCh0aGlzLCBvd25lcikpO1xuICAgICAgICBcbiAgICAgICAgdGhpcy5tYXhIZWFsdGggPSBvcHRpb25zLmhlYWx0aDtcblxuICAgICAgICB0aGlzLkNVUlJFTlRfSFAgPSBvcHRpb25zLmhlYWx0aDtcblxuICAgICAgICB0aGlzLndlYXBvbiA9IG9wdGlvbnMud2VhcG9uO1xuXG4gICAgICAgIHRoaXMucGxheWVyID0gb3B0aW9ucy5wbGF5ZXI7XG5cbiAgICAgICAgdGhpcy5pblJhbmdlID0gb3B0aW9ucy5pblJhbmdlO1xuXG4gICAgICAgIHRoaXMuZ29hbCA9IG9wdGlvbnMuZ29hbDtcblxuICAgICAgICB0aGlzLmN1cnJlbnRTdGF0dXMgPSBvcHRpb25zLnN0YXR1cztcblxuICAgICAgICB0aGlzLnBvc3NpYmxlQWN0aW9ucyA9IG9wdGlvbnMuYWN0aW9ucztcblxuICAgICAgICB0aGlzLnBsYW4gPSBuZXcgU3RhY2s8R29hcEFjdGlvbj4oKTtcblxuICAgICAgICB0aGlzLnBsYW5uZXIgPSBuZXcgR29hcEFjdGlvblBsYW5uZXIoKTtcblxuICAgICAgICAvL1RPRE8gLSBnZXQgY29ycmVjdCB0aWxlbWFwXG4gICAgICAgIC8vdGhpcy50aWxlbWFwID0gdGhpcy5vd25lci5nZXRTY2VuZSgpLmdldFRpbGVtYXAob3B0aW9ucy50aWxlbWFwKSBhcyBPcnRob2dvbmFsVGlsZW1hcDtcbiAgICAgICAgdGhpcy50aWxlbWFwID0gPE9ydGhvZ29uYWxUaWxlbWFwPnRoaXMub3duZXIuZ2V0U2NlbmUoKS5nZXRMYXllcihcIldhbGxcIikuZ2V0SXRlbXMoKVswXTtcbiAgICAgICAgLy90aGlzLnRpbGVtYXAgPSA8T3J0aG9nb25hbFRpbGVtYXA+dGhpcy5vd25lci5nZXRTY2VuZSgpLmdldFRpbGVtYXAoXCJNYWluXCIpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdG8gdGhlIGRlZmF1bHQgc3RhdGVcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKEVuZW15U3RhdGVzLkRFRkFVTFQpO1xuXG4gICAgICAgIC8vdGhpcy5nZXRQbGF5ZXJQb3NpdGlvbigpO1xuXG4gICAgICAgIHRoaXMuZGlyZWN0aW9uID0gMTsgLy9kZWZhdWx0IG1vdmluZyB0byB0aGUgcmlnaHRcbiAgICAgICAgXG4gICAgfVxuXG4gICAgYWN0aXZhdGUob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQgeyB9XG5cbiAgICBkYW1hZ2UoZGFtYWdlOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5DVVJSRU5UX0hQIC09IGRhbWFnZTtcbiAgICAgICAgLy9UT0RPIC1cbiAgICAgICAgdGhpcy5vd25lci5hbmltYXRpb24ucGxheShcIkhVUlRcIik7XG4gICAgICAgIGNvbnNvbGUubG9nKGRhbWFnZSArXCIgZGFtYWdlIHRha2VuLCBcIit0aGlzLkNVUlJFTlRfSFArXCIgaHAgbGVmdFwiKTtcblxuICAgICAgICAvLyBJZiB3ZSdyZSBsb3cgZW5vdWdoLCBhZGQgTG93IEhlYWx0aCBzdGF0dXMgdG8gZW5lbXlcbiAgICAgICAgaWYgKHRoaXMuQ1VSUkVOVF9IUCA8PSBNYXRoLmZsb29yKHRoaXMubWF4SGVhbHRoLzIpKSB7XG4gICAgICAgICAgICBcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIGhlYWx0aCBnb2VzIGJlbG93IDAsIGRpc2FibGUgQUkgYW5kIGZpcmUgZW5lbXlEaWVkIGV2ZW50XG4gICAgICAgIGlmICh0aGlzLkNVUlJFTlRfSFAgPD0gMCkge1xuICAgICAgICAgICAgdGhpcy5vd25lci5zZXRBSUFjdGl2ZShmYWxzZSwge30pO1xuICAgICAgICAgICAgdGhpcy5vd25lci5pc0NvbGxpZGFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMub3duZXIudmlzaWJsZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuRU5FTVlfS0lMTEVELCB7b3duZXI6IHRoaXMub3duZXIuaWQsIGFpOnRoaXN9KTtcblxuXG4gICAgICAgICAgICBpZiAoTWF0aC5yYW5kb20oKSA8IDAuMDUpIHtcbiAgICAgICAgICAgICAgICAvLyBnaXZlIGJ1ZmYgbWF5YmVcbiAgICAgICAgICAgICAgICAvL3RoaXMuZW1pdHRlci5maXJlRXZlbnQoXCJnaXZlQnVmZlwiLCB7IHBvc2l0aW9uOiB0aGlzLm93bmVyLnBvc2l0aW9uIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy9UT0RPIC0gbmVlZCB0byBtb2RpZnkgZm9yIHNpZGUgdmlld1xuICAgIC8qXG4gICAgaXNQbGF5ZXJWaXNpYmxlKHBvczogVmVjMik6IFZlYzJ7XG4gICAgICAgIC8vQ2hlY2sgaWYgb25lIHBsYXllciBpcyB2aXNpYmxlLCB0YWtpbmcgaW50byBhY2NvdW50IHdhbGxzXG5cbiAgICAgICAgLy8gR2V0IHRoZSBuZXcgcGxheWVyIGxvY2F0aW9uXG4gICAgICAgIGxldCBzdGFydCA9IHRoaXMub3duZXIucG9zaXRpb24uY2xvbmUoKTtcbiAgICAgICAgbGV0IGRlbHRhID0gcG9zLmNsb25lKCkuc3ViKHN0YXJ0KTtcblxuICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggdGhlIHRpbGVtYXAgcmVnaW9uIHVudGlsIHdlIGZpbmQgYSBjb2xsaXNpb25cbiAgICAgICAgbGV0IG1pblggPSBNYXRoLm1pbihzdGFydC54LCBwb3MueCk7XG4gICAgICAgIGxldCBtYXhYID0gTWF0aC5tYXgoc3RhcnQueCwgcG9zLngpO1xuICAgICAgICBsZXQgbWluWSA9IE1hdGgubWluKHN0YXJ0LnksIHBvcy55KTtcbiAgICAgICAgbGV0IG1heFkgPSBNYXRoLm1heChzdGFydC55LCBwb3MueSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB3YWxsIHRpbGVtYXBcbiAgICAgICAgbGV0IHdhbGxzID0gPE9ydGhvZ29uYWxUaWxlbWFwPnRoaXMub3duZXIuZ2V0U2NlbmUoKS5nZXRMYXllcihcIldhbGxcIikuZ2V0SXRlbXMoKVswXTtcblxuICAgICAgICBsZXQgbWluSW5kZXggPSB3YWxscy5nZXRDb2xSb3dBdChuZXcgVmVjMihtaW5YLCBtaW5ZKSk7XG4gICAgICAgIGxldCBtYXhJbmRleCA9IHdhbGxzLmdldENvbFJvd0F0KG5ldyBWZWMyKG1heFgsIG1heFkpKTtcblxuICAgICAgICBsZXQgdGlsZVNpemUgPSB3YWxscy5nZXRUaWxlU2l6ZSgpO1xuXG4gICAgICAgIGZvciAobGV0IGNvbCA9IG1pbkluZGV4Lng7IGNvbCA8PSBtYXhJbmRleC54OyBjb2wrKykge1xuICAgICAgICAgICAgZm9yIChsZXQgcm93ID0gbWluSW5kZXgueTsgcm93IDw9IG1heEluZGV4Lnk7IHJvdysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdhbGxzLmlzVGlsZUNvbGxpZGFibGUoY29sLCByb3cpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgcG9zaXRpb24gb2YgdGhpcyB0aWxlXG4gICAgICAgICAgICAgICAgICAgIGxldCB0aWxlUG9zID0gbmV3IFZlYzIoY29sICogdGlsZVNpemUueCArIHRpbGVTaXplLnggLyAyLCByb3cgKiB0aWxlU2l6ZS55ICsgdGlsZVNpemUueSAvIDIpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIGNvbGxpZGVyIGZvciB0aGlzIHRpbGVcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbGxpZGVyID0gbmV3IEFBQkIodGlsZVBvcywgdGlsZVNpemUuc2NhbGVkKDEgLyAyKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGhpdCA9IGNvbGxpZGVyLmludGVyc2VjdFNlZ21lbnQoc3RhcnQsIGRlbHRhLCBWZWMyLlpFUk8pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChoaXQgIT09IG51bGwgJiYgc3RhcnQuZGlzdGFuY2VTcVRvKGhpdC5wb3MpIDwgc3RhcnQuZGlzdGFuY2VTcVRvKHBvcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGhpdCBhIHdhbGwsIHdlIGNhbid0IHNlZSB0aGUgcGxheWVyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb3M7XG4gICAgfVxuICAgICovXG5cbiAgICBcblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcil7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFRoaXMgaXMgdGhlIHBsYW4gdGhhdCBpcyBleGVjdXRlZCBpbiB0aGUgQWN0aXZlIHN0YXRlLCBzbyB3aGVuZXZlciB3ZSBkb24ndCBoYXZlIGEgcGxhbiwgYWNxdWlyZSBhIG5ldyBvbmUgZ2l2ZW4gdGhlIGN1cnJlbnQgc3RhdHVzZXMgdGhlIGVuZW15IGhhc1xuICAgICAgICAvKlxuICAgICAgICBpZiAodGhpcy5wbGFuLmlzRW1wdHkoKSkge1xuICAgICAgICAgICAgLy9nZXQgYSBuZXcgcGxhblxuICAgICAgICAgICAgdGhpcy5wbGFuID0gdGhpcy5wbGFubmVyLnBsYW4oU3RhdHVzZXMuUkVBQ0hFRF9HT0FMLCB0aGlzLnBvc3NpYmxlQWN0aW9ucywgdGhpcy5jdXJyZW50U3RhdHVzLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgICAqL1xuICAgICAgICBcbiAgICB9XG59XG5cbmV4cG9ydCBlbnVtIEVuZW15U3RhdGVzIHtcbiAgICBERUZBVUxUID0gXCJkZWZhdWx0XCIsXG4gICAgQUxFUlQgPSBcImFsZXJ0XCIsXG4gICAgUFJFVklPVVMgPSBcInByZXZpb3VzXCJcbn0iLCJpbXBvcnQgU3RhdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZVwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IEVuZW15QUkgZnJvbSBcIi4uL0VuZW15QUlcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgRW5lbXlTdGF0ZSBleHRlbmRzIFN0YXRlIHtcbiAgICBwcm90ZWN0ZWQgcGFyZW50OiBFbmVteUFJO1xuICAgIHByb3RlY3RlZCBvd25lcjogR2FtZU5vZGU7XG4gICAgZ3Jhdml0eTogbnVtYmVyID0gMTUwMDsgLy9UT0RPIC0gY2FuIGNoYW5nZSBsYXRlclxuXG4gICAgY29uc3RydWN0b3IocGFyZW50OiBFbmVteUFJLCBvd25lcjogR2FtZU5vZGUpe1xuICAgICAgc3VwZXIocGFyZW50KTtcbiAgICAgIHRoaXMub3duZXIgPSBvd25lcjtcbiAgICB9XG5cblxuICAgIFxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHQvLyBEbyBncmF2aXR5XG5cdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueSArPSB0aGlzLmdyYXZpdHkqZGVsdGFUO1xuXHR9XG4gICAgXG59XG5cbiIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IE5hdmlnYXRpb25QYXRoIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZpZ2F0aW9uUGF0aFwiO1xuXG5pbXBvcnQgRW5lbXlBSSwgeyBFbmVteVN0YXRlcyB9IGZyb20gXCIuLi9FbmVteUFJXCI7XG5pbXBvcnQgRW5lbXlTdGF0ZSBmcm9tIFwiLi9FbmVteVN0YXRlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgT25Hcm91bmQgZnJvbSBcIi4vT25Hcm91bmRcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYXRyb2wgZXh0ZW5kcyBFbmVteVN0YXRlIHtcblxuICAgIFxuXG4gICAgLy8gQSByZXR1cm4gb2JqZWN0IGZvciBleGl0aW5nIHRoaXMgc3RhdGVcbiAgICBwcm90ZWN0ZWQgcmV0T2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG4gICAgY29uc3RydWN0b3IocGFyZW50OiBFbmVteUFJLCBvd25lcjogR2FtZU5vZGUpe1xuICAgICAgICBzdXBlcihwYXJlbnQsIG93bmVyKTtcbiAgICAgIFxuICAgIH1cblxuICAgIG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICAvL3RoaXMuY3VycmVudFBhdGggPSB0aGlzLmdldE5leHRQYXRoKCk7XG4gICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnBsYXkoXCJJRExFXCIsIHRydWUpO1xuICAgIH1cblxuICAgIGhhbmRsZUlucHV0KGV2ZW50OiBHYW1lRXZlbnQpOiB2b2lkIHsgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICBcbiAgICAgICAgLy9ubyBnb2FwIHJuLCBqdXN0IGFkZGluZyBzb21lIG1vdmluZ1xuICAgICAgICBsZXQgY29scm93ID0gdGhpcy5wYXJlbnQudGlsZW1hcC5nZXRDb2xSb3dBdCh0aGlzLm93bmVyLnBvc2l0aW9uLmNsb25lKCkpO1xuICAgICAgICBcbiAgICAgICAgLy9jaGVjayBpZiBuZXh0IHRpbGUgb24gd2Fsa2luZyBwYXRoIGlzIGNvbGxpZGFibGVcbiAgICAgICAgaWYodGhpcy5wYXJlbnQudGlsZW1hcC5pc1RpbGVDb2xsaWRhYmxlKGNvbHJvdy54K3RoaXMucGFyZW50LmRpcmVjdGlvbixjb2xyb3cueSkpe1xuICAgICAgICAgICAgLy90dXJuIGFyb3VuZFxuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyh0aGlzLnBhcmVudC50aWxlbWFwLmdldFRpbGVBdFJvd0NvbChjb2xyb3cpKTtcbiAgICAgICAgICAgIHRoaXMucGFyZW50LmRpcmVjdGlvbiAqPSAtMTtcbiAgICAgICAgICAgICg8U3ByaXRlPnRoaXMub3duZXIpLmludmVydFggPSBNYXRoVXRpbHMuc2lnbigxKSA8IDA7XG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwidHVybiBhcm91bmQgY3VzIHdhbGwgaW4gZnJvbnRcIik7XG4gICAgICAgIH1cbiAgICAgICAgLy9jaGVjayBpZiBuZXh0IGdyb3VuZCB0aWxlIGlzIGNvbGxpZGFibGUgXG4gICAgICAgIGVsc2UgaWYodGhpcy5wYXJlbnQudGlsZW1hcC5pc1RpbGVDb2xsaWRhYmxlKGNvbHJvdy54K3RoaXMucGFyZW50LmRpcmVjdGlvbixjb2xyb3cueSsxKSl7XG4gICAgICAgICAgICAvL2tlZXAgbW92aW5nXG4gICAgICAgICAgICAvL3RoaXMudmVsb2NpdHkueCA9ICB0aGlzLnNwZWVkO1xuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcInRoZXJlIGlzIGZsb29yIGFoZWFkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2V7XG4gICAgICAgICAgICAvL3R1cm4gYXJvdW5kIFxuICAgICAgICAgICAgdGhpcy5wYXJlbnQuZGlyZWN0aW9uICo9LTE7XG4gICAgICAgICAgICAoPFNwcml0ZT50aGlzLm93bmVyKS5pbnZlcnRYID0gTWF0aFV0aWxzLnNpZ24oMSkgPCAwO1xuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcInR1cm4gYXJvdW5kIGN1cyBubyBmbG9vciBpbiBmcm9udFwiKTtcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgICAgIC8vbW92ZVxuICAgICAgICB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gdGhpcy5wYXJlbnQuZGlyZWN0aW9uICogdGhpcy5wYXJlbnQuc3BlZWQ7XG5cbiAgICAgICAgLy9tb3ZlIHRoaXMgZWxzZXdoZXJlIGxhdGVyXG4gICAgICAgIHRoaXMub3duZXIubW92ZSh0aGlzLnBhcmVudC52ZWxvY2l0eS5zY2FsZWQoZGVsdGFUKSk7XG4gICAgICAgIC8vY29uc29sZS5sb2coXCJlbmVteSBtb3ZpbmdcIik7XG4gICAgfVxuXG4gICAgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXRPYmo7XG4gICAgfVxuXG4gICAgXG5cbn0iLCJcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBCYXR0bGVyQUkgZnJvbSBcIi4uL0FJL0JhdHRsZXJBSVwiO1xuaW1wb3J0IFdlYXBvbiBmcm9tIFwiLi9pdGVtcy9XZWFwb25cIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmF0dGxlTWFuYWdlciB7XG4gICAgcGxheWVyczogQXJyYXk8QmF0dGxlckFJPjtcblxuICAgIGVuZW1pZXM6IEFycmF5PEJhdHRsZXJBST47XG5cbiAgICBoYW5kbGVJbnRlcmFjdGlvbihhdHRhY2tlclR5cGU6IHN0cmluZywgd2VhcG9uOiBXZWFwb24pIHtcbiAgICAgICAgLy9tYXkgYmUgdW5uZWVkZWQgc2luY2Ugd2UgYXJlIGNvbnRyb2xsaW5nIHRoZSBwbGF5ZXIgLSBcbiAgICAgICAgLy93ZSBkZXRlcm1pbmUgZW5lbXkgY29sbGlzaW9uIHRoZXJlXG4gICAgICAgIFxuICAgICAgICBpZiAoYXR0YWNrZXJUeXBlID09PSBcInBsYXllclwiKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgY29sbGlzaW9ucyB3aXRoIGVuZW1pZXNcbiAgICAgICAgICAgIGlmKHRoaXMuZW5lbWllcy5sZW5ndGggIT0gMCl7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZW5lbXkgb2YgdGhpcy5lbmVtaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3ZWFwb24uaGl0cyhlbmVteS5vd25lcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZW15LmRhbWFnZSh3ZWFwb24udHlwZS5kYW1hZ2UgKyB3ZWFwb24uRVhUUkFfREFNQUdFKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJlbmVteSB0b29rIGRtZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGZvciBjb2xsaXNpb24gd2l0aCBwbGF5ZXJcbiAgICAgICAgICAgIGZvciAobGV0IHBsYXllciBvZiB0aGlzLnBsYXllcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAod2VhcG9uLmhpdHMocGxheWVyLm93bmVyKSkge1xuICAgICAgICAgICAgICAgICAgICBwbGF5ZXIuZGFtYWdlKHdlYXBvbi50eXBlLmRhbWFnZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuXG4gICAgfVxuXG4gICAgc2V0UGxheWVycyhwbGF5ZXI6IEFycmF5PEJhdHRsZXJBST4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wbGF5ZXJzID0gcGxheWVyO1xuICAgIH1cblxuICAgIHNldEVuZW1pZXMoZW5lbWllczogQXJyYXk8QmF0dGxlckFJPik6IHZvaWQge1xuICAgICAgICB0aGlzLmVuZW1pZXMgPSBlbmVtaWVzO1xuICAgIH1cblxuICAgIGFkZEVuZW15KGVuZW15IDogQmF0dGxlckFJKXtcbiAgICAgICAgdGhpcy5lbmVtaWVzLnB1c2goZW5lbXkpO1xuICAgIH1cblxuICAgIHJlbW92ZUVuZW15KGVuZW15IDogQmF0dGxlckFJKXtcbiAgICAgICBcbiAgICAgICAgXG4gICAgICAgIHRoaXMuZW5lbWllcyA9IHRoaXMuZW5lbWllcy5maWx0ZXIoaXRlbSA9PiBpdGVtICE9PSBlbmVteSlcbiAgICAgICAgaWYodGhpcy5lbmVtaWVzLmxlbmd0aCA9PSAwKXtcbiAgICAgICAgICAgIHRoaXMuZW5lbWllcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmVuZW1pZXM7XG4gICAgICAgICAgXG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgR3JhcGhpY1R5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvR3JhcGhpY1R5cGVzXCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBJdGVtIGZyb20gXCIuL2l0ZW1zL0l0ZW1cIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW52ZW50b3J5TWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHBvc2l0aW9uOiBWZWMyO1xuICAgIHByaXZhdGUgaXRlbXM6IEFycmF5PEl0ZW0+O1xuICAgIHByaXZhdGUgaW52ZW50b3J5U2xvdHM6IEFycmF5PFNwcml0ZT47XG4gICAgcHJpdmF0ZSBzbG90U2l6ZTogVmVjMjtcbiAgICBwcml2YXRlIHBhZGRpbmc6IG51bWJlcjtcbiAgICBwcml2YXRlIGN1cnJlbnRTbG90OiBudW1iZXI7XG4gICAgcHJpdmF0ZSBzbG90TGF5ZXI6IHN0cmluZztcbiAgICBwcml2YXRlIGl0ZW1MYXllcjogc3RyaW5nO1xuICAgIHByaXZhdGUgc2VsZWN0ZWRTbG90OiBSZWN0O1xuXG4gICAgY29uc3RydWN0b3Ioc2NlbmU6IFNjZW5lLCBzaXplOiBudW1iZXIsIGludmVudG9yeVNsb3Q6IHN0cmluZywgcG9zaXRpb246IFZlYzIsIHBhZGRpbmc6IG51bWJlciwgc2xvdExheWVyOiBzdHJpbmcsIGl0ZW1MYXllcjogc3RyaW5nKXtcbiAgICAgICAgdGhpcy5pdGVtcyA9IG5ldyBBcnJheShzaXplKTtcbiAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90cyA9IG5ldyBBcnJheShzaXplKTtcbiAgICAgICAgdGhpcy5wYWRkaW5nID0gcGFkZGluZztcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuICAgICAgICB0aGlzLmN1cnJlbnRTbG90ID0gMDtcblxuICAgICAgICAvLyBBZGQgbGF5ZXJzXG4gICAgICAgIHRoaXMuc2xvdExheWVyID0gc2xvdExheWVyO1xuICAgICAgICBzY2VuZS5hZGRVSUxheWVyKHRoaXMuc2xvdExheWVyKS5zZXREZXB0aCgxMDApO1xuICAgICAgICB0aGlzLml0ZW1MYXllciA9IGl0ZW1MYXllcjtcbiAgICAgICAgc2NlbmUuYWRkVUlMYXllcih0aGlzLml0ZW1MYXllcikuc2V0RGVwdGgoMTAxKTtcblxuICAgICAgICAvLyBDcmVhdGUgdGhlIGludmVudG9yeSBzbG90c1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKXtcbiAgICAgICAgICAgIHRoaXMuaW52ZW50b3J5U2xvdHNbaV0gPSBzY2VuZS5hZGQuc3ByaXRlKGludmVudG9yeVNsb3QsIHRoaXMuc2xvdExheWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2xvdFNpemUgPSB0aGlzLmludmVudG9yeVNsb3RzWzBdLnNpemUuY2xvbmUoKTtcblxuICAgICAgICAvLyBQb3NpdGlvbiB0aGUgaW52ZW50b3J5IHNsb3RzXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspe1xuICAgICAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90c1tpXS5wb3NpdGlvbi5zZXQocG9zaXRpb24ueCArIGkqKHRoaXMuc2xvdFNpemUueCArIHRoaXMucGFkZGluZyksIHBvc2l0aW9uLnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIGEgcmVjdCBmb3IgdGhlIHNlbGVjdGVkIHNsb3RcbiAgICAgICAgdGhpcy5zZWxlY3RlZFNsb3QgPSA8UmVjdD5zY2VuZS5hZGQuZ3JhcGhpYyhHcmFwaGljVHlwZS5SRUNULCBzbG90TGF5ZXIsIHtwb3NpdGlvbjogdGhpcy5wb3NpdGlvbi5jbG9uZSgpLCBzaXplOiB0aGlzLnNsb3RTaXplLmNsb25lKCkuaW5jKC0yKX0pO1xuICAgICAgICB0aGlzLnNlbGVjdGVkU2xvdC5jb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0aGlzLnNlbGVjdGVkU2xvdC5jb2xvci5hID0gMC4yO1xuICAgIH1cblxuICAgIGdldEl0ZW0oKTogSXRlbSB7XG4gICAgICAgIHJldHVybiB0aGlzLml0ZW1zW3RoaXMuY3VycmVudFNsb3RdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoYW5nZXMgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzbG90XG4gICAgICovXG4gICAgY2hhbmdlU2xvdChzbG90OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdXJyZW50U2xvdCA9IHNsb3Q7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTbG90LnBvc2l0aW9uLmNvcHkodGhpcy5pbnZlbnRvcnlTbG90c1tzbG90XS5wb3NpdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNsb3RcbiAgICAgKi9cbiAgICBnZXRTbG90KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRTbG90O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYW4gaXRlbSB0byB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNsb3RcbiAgICAgKi9cbiAgICBhZGRJdGVtKGl0ZW06IEl0ZW0pOiBib29sZWFuIHtcbiAgICAgICAgaWYoIXRoaXMuaXRlbXNbdGhpcy5jdXJyZW50U2xvdF0pe1xuICAgICAgICAgICAgLy8gQWRkIHRoZSBpdGVtIHRvIHRoZSBpbnZlbnRvcnlcbiAgICAgICAgICAgIHRoaXMuaXRlbXNbdGhpcy5jdXJyZW50U2xvdF0gPSBpdGVtO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGd1aVxuICAgICAgICAgICAgaXRlbS5tb3ZlU3ByaXRlKG5ldyBWZWMyKHRoaXMucG9zaXRpb24ueCArIHRoaXMuY3VycmVudFNsb3QqKHRoaXMuc2xvdFNpemUueCArIHRoaXMucGFkZGluZyksIHRoaXMucG9zaXRpb24ueSksIHRoaXMuaXRlbUxheWVyKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIEZhaWxlZCB0byBhZGQgaXRlbSwgc29tZXRoaW5nIHdhcyBhbHJlYWR5IGluIHRoZSBzbG90XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFuZCByZXR1cm5zIGFuIGl0ZW0gZnJvbSB0aGUgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBzbG90LCBpZiBwb3NzaWJsZVxuICAgICAqL1xuICAgIHJlbW92ZUl0ZW0oKTogSXRlbSB7XG4gICAgICAgIGxldCBpdGVtID0gdGhpcy5pdGVtc1t0aGlzLmN1cnJlbnRTbG90XTtcblxuICAgICAgICB0aGlzLml0ZW1zW3RoaXMuY3VycmVudFNsb3RdID0gbnVsbDtcblxuICAgICAgICBpZihpdGVtKXtcbiAgICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRBY3RpdmUoYWN0aXZlOiBib29sZWFuKSB7XG4gICAgICAgIGlmIChhY3RpdmUpe1xuICAgICAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90cy5mb3JFYWNoKHNsb3QgPT4gc2xvdC5hbHBoYSA9IDEuMCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZXtcbiAgICAgICAgICAgIHRoaXMuaW52ZW50b3J5U2xvdHMuZm9yRWFjaChzbG90ID0+IHNsb3QuYWxwaGEgPSAwLjUpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgSXRlbSB7XG4gICAgLyoqIFRoZSBzcHJpdGUgdGhhdCByZXByZXNlbnRzIHRoaXMgd2VhcG9uIGluIHRoZSB3b3JsZCBvciBpbiBhbiBpbnZlbnRvcnkgKi9cbiAgICBzcHJpdGU6IFNwcml0ZTtcblxuICAgIGNvbnN0cnVjdG9yKHNwcml0ZTogU3ByaXRlKXtcbiAgICAgICAgdGhpcy5zcHJpdGUgPSBzcHJpdGU7XG4gICAgfVxuXG4gICAgbW92ZVNwcml0ZShwb3NpdGlvbjogVmVjMiwgbGF5ZXI/OiBzdHJpbmcpe1xuICAgICAgICAvLyBDaGFuZ2UgdGhlIGxheWVyIGlmIG5lZWRlZFxuICAgICAgICBpZihsYXllcil7XG4gICAgICAgICAgICBsZXQgY3VycmVudExheWVyID0gdGhpcy5zcHJpdGUuZ2V0TGF5ZXIoKTtcbiAgICAgICAgICAgIGN1cnJlbnRMYXllci5yZW1vdmVOb2RlKHRoaXMuc3ByaXRlKTtcbiAgICAgICAgICAgIGxldCBuZXdMYXllciA9IHRoaXMuc3ByaXRlLmdldFNjZW5lKCkuZ2V0TGF5ZXIobGF5ZXIpO1xuICAgICAgICAgICAgbmV3TGF5ZXIuYWRkTm9kZSh0aGlzLnNwcml0ZSk7XG4gICAgICAgICAgICB0aGlzLnNwcml0ZS5zZXRMYXllcihuZXdMYXllcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb3ZlIHRoZSBzcHJpdGVcbiAgICAgICAgdGhpcy5zcHJpdGUucG9zaXRpb24uY29weShwb3NpdGlvbik7XG4gICAgfVxuXG4gICAgYWJzdHJhY3QgdXNlKHVzZXI6IEdhbWVOb2RlLCAuLi5hcmdzOiBhbnkpOiB2b2lkO1xufSIsIi8vVE9ETyBpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvRW1pdHRlclwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBUaW1lciBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvVGltaW5nL1RpbWVyXCI7XG5pbXBvcnQgQmF0dGxlTWFuYWdlciBmcm9tIFwiLi4vQmF0dGxlTWFuYWdlclwiO1xuaW1wb3J0IEl0ZW0gZnJvbSBcIi4vSXRlbVwiO1xuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4vV2VhcG9uVHlwZXMvV2VhcG9uVHlwZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2VhcG9uIGV4dGVuZHMgSXRlbSB7XG4gICAgLyoqIFRoZSB0eXBlIG9mIHRoaXMgd2VhcG9uICovXG4gICAgdHlwZTogV2VhcG9uVHlwZTtcblxuICAgIC8qKiBBIGxpc3Qgb2YgYXNzZXRzIHRoaXMgd2VhcG9uIG5lZWRzIHRvIGJlIGFuaW1hdGVkICovXG4gICAgYXNzZXRzOiBBcnJheTxhbnk+O1xuXG4gICAgLyoqIEFuIGV2ZW50IGVtaXR0ZXIgdG8gaG9vayBpbnRvIHRoZSBFdmVudFF1ZXVlICovXG4gICAgZW1pdHRlcjogRW1pdHRlclxuXG4gICAgLyoqIFRoZSBiYXR0bGUgbWFuYWdlciAqL1xuICAgIGJhdHRsZU1hbmFnZXI6IEJhdHRsZU1hbmFnZXI7XG5cbiAgICAvKiogVGhlIGNvb2xkb3duIHRpbWVyIGZvciB0aGlzIHdlYXBvbidzIHVzZSAqL1xuICAgIGNvb2xkb3duVGltZXI6IFRpbWVyO1xuXG4gICAgRVhUUkFfREFNQUdFIDogbnVtYmVyOyAgLy9mbGF0IGV4dHJhIGRhbWFnZSB2YWx1ZVxuXG4gICAgRVhUUkFfUkFOR0U6IG51bWJlciA7ICAgLy9wZXJjZW50YWdlIHZhbHVlIC0+IC4xID0gMTAlIGV4dHJhIHJhbmdlXG5cbiAgICBjb25zdHJ1Y3RvcihzcHJpdGU6IFNwcml0ZSwgdHlwZTogV2VhcG9uVHlwZSwgYmF0dGxlTWFuYWdlcjogQmF0dGxlTWFuYWdlcil7XG4gICAgICAgIHN1cGVyKHNwcml0ZSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlLmNsb25lKCk7XG5cbiAgICAgICAgLy8gS2VlcCBhIHJlZmVyZW5jZSB0byB0aGUgc3ByaXRlIG9mIHRoaXMgd2VhcG9uXG4gICAgICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xuXG4gICAgICAgIC8vIENyZWF0ZSBhbiBldmVudCBlbWl0dGVyXG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG5cbiAgICAgICAgLy8gU2F2ZSBhIHJlZmVyZW5jZSB0byB0aGUgYmF0dGxlciBtYW5hZ2VyXG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlciA9IGJhdHRsZU1hbmFnZXI7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBjb29sZG93biB0aW1lclxuICAgICAgICB0aGlzLmNvb2xkb3duVGltZXIgPSBuZXcgVGltZXIodHlwZS5jb29sZG93bik7ICBcbiAgICAgICAgdGhpcy5FWFRSQV9EQU1BR0UgPSAwO1xuICAgICAgICB0aGlzLkVYVFJBX1JBTkdFPTA7IFxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIC8qKlxuICAgICAqIFVzZXMgdGhpcyB3ZWFwb24gaW4gdGhlIHNwZWNpZmllZCBkaXJlY3Rpb24uXG4gICAgICogVGhpcyBvbmx5IHdvcmtzIGlmIHRoZSBjb29sZG93biB0aW1lciBoYXMgZW5kZWRcbiAgICAgKi9cbiAgICB1c2UodXNlcjogR2FtZU5vZGUsIHVzZXJUeXBlOiBzdHJpbmcsIGRpcmVjdGlvbjogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICAvLyBJZiB0aGUgY29vbGRvd24gdGltZXIgaXMgc3RpbGwgcnVubmluZywgd2UgY2FuJ3QgdXNlIHRoZSB3ZWFwb25cbiAgICAgICAgaWYoIXRoaXMuY29vbGRvd25UaW1lci5pc1N0b3BwZWQoKSl7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVseSBvbiB0aGUgd2VhcG9uIHR5cGUgdG8gY3JlYXRlIGFueSBuZWNlc3NhcnkgYXNzZXRzXG4gICAgICAgIHRoaXMuYXNzZXRzID0gdGhpcy50eXBlLmNyZWF0ZVJlcXVpcmVkQXNzZXRzKHRoaXMuc3ByaXRlLmdldFNjZW5lKCkpO1xuXG4gICAgICAgIC8vIERvIGEgdHlwZSBzcGVjaWZpYyB3ZWFwb24gYW5pbWF0aW9uXG4gICAgICAgIHRoaXMudHlwZS5kb0FuaW1hdGlvbih1c2VyLCBkaXJlY3Rpb24sIHRoaXMuRVhUUkFfUkFOR0UsIC4uLnRoaXMuYXNzZXRzKTtcblxuICAgICAgICAvLyBBcHBseSBkYW1hZ2VcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyLmhhbmRsZUludGVyYWN0aW9uKHVzZXJUeXBlLCB0aGlzKTtcbiAgICBcbiAgICAgICAgLy8gUmVzZXQgdGhlIGNvb2xkb3duIHRpbWVyXG4gICAgICAgIHRoaXMuY29vbGRvd25UaW1lci5zdGFydCgpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgY2hlY2sgZm9yIHdoZXRoZXIgb3Igbm90IHRoaXMgd2VhcG9uIGhpdCBhIG5vZGVcbiAgICAgKi9cbiAgICBoaXRzKG5vZGU6IEdhbWVOb2RlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnR5cGUuaGl0cyhub2RlLCAuLi50aGlzLmFzc2V0cyk7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uLy4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4vV2VhcG9uVHlwZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTbGljZSBleHRlbmRzIFdlYXBvblR5cGUge1xuXG4gICAgaW5pdGlhbGl6ZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGFtYWdlID0gb3B0aW9ucy5kYW1hZ2U7XG4gICAgICAgIHRoaXMuY29vbGRvd24gPSBvcHRpb25zLmNvb2xkb3duO1xuICAgICAgICB0aGlzLmRpc3BsYXlOYW1lID0gb3B0aW9ucy5kaXNwbGF5TmFtZTtcbiAgICAgICAgdGhpcy5zcHJpdGVLZXkgPSBvcHRpb25zLnNwcml0ZUtleTtcbiAgICAgICAgdGhpcy51c2VWb2x1bWUgPSBvcHRpb25zLnVzZVZvbHVtZTtcbiAgICB9XG5cbiAgICBkb0FuaW1hdGlvbihhdHRhY2tlcjogR2FtZU5vZGUsIGRpcmVjdGlvbjogVmVjMiwgZXh0cmFSYW5nZTpudW1iZXIsc2xpY2VTcHJpdGU6IEFuaW1hdGVkU3ByaXRlKTogdm9pZCB7XG4gICAgICAgIC8vVE9ETy0gXG4gICAgICAgIC8vNCB0byBzY2FsZSB1cCB0aGUgZGVmYXVsdCBzcHJpdGUgLSBtYXkgYmUgZGlmZmVyZW50IGxhdGVyIGRlcGVuZGluZyBvbiBhdGsgYW5pbVxuICAgICAgICBzbGljZVNwcml0ZS5zY2FsZVggPSAyKigxK2V4dHJhUmFuZ2UpOyAvL21pZ2h0IGhhdmUgdG8gYWRkIGV4dHJhIHJhbmdlIHRvIHkgYXMgd2VsbFxuICAgICAgICBzbGljZVNwcml0ZS5zY2FsZVkgPSAyO1xuXG4gICAgICAgIC8vIFJvdGF0ZSB0aGlzIHdpdGggdGhlIGdhbWUgbm9kZVxuICAgICAgICAvLyBUT0RPIC0gbmVlZCB0byByb3RhdGUgdGhlIGFuaW0gcHJvcGVybHlcbiAgICAgICAgc2xpY2VTcHJpdGUucm90YXRpb24gPSBhdHRhY2tlci5yb3RhdGlvbjtcbiAgICAgICAgc2xpY2VTcHJpdGUucm90YXRpb24gPSAoPFNwcml0ZT5hdHRhY2tlcikuaW52ZXJ0WD8gLjUqIE1hdGguUEkgOiAxLjUgKiBNYXRoLlBJO1xuICAgICAgICAvLyBNb3ZlIHRoZSBzbGljZSBvdXQgZnJvbSB0aGUgcGxheWVyXG4gICAgICAgIC8vc2NhbGUgPSBudW0gb2YgcGl4ZWxzIGJldHdlZW4gY2VudGVyIG9mIHNwcml0ZSBhbmQgYXRrIGFuaW1cbiAgICAgICAgc2xpY2VTcHJpdGUucG9zaXRpb24gPSBhdHRhY2tlci5wb3NpdGlvbi5jbG9uZSgpLmFkZChkaXJlY3Rpb24uc2NhbGVkKDMyKSk7IFxuICAgICAgICBzbGljZVNwcml0ZS5wb3NpdGlvbiA9ICBzbGljZVNwcml0ZS5wb3NpdGlvbi5hZGQobmV3IFZlYzIoMCwxNikpOyAgICAvL21ha2UgaXQgZ28gZG93biBhIGJpdFxuICAgICAgICBcbiAgICAgICAgLy8gUGxheSB0aGUgc2xpY2UgYW5pbWF0aW9uIHcvbyBsb29wLCBidXQgcXVldWUgdGhlIG5vcm1hbCBhbmltYXRpb25cbiAgICAgICAgc2xpY2VTcHJpdGUuYW5pbWF0aW9uLnBsYXkoXCJTTElDRVwiKTtcbiAgICAgICAgc2xpY2VTcHJpdGUuYW5pbWF0aW9uLnF1ZXVlKFwiTk9STUFMXCIsIHRydWUpO1xuICAgIH1cblxuICAgIGNyZWF0ZVJlcXVpcmVkQXNzZXRzKHNjZW5lOiBTY2VuZSk6IFtBbmltYXRlZFNwcml0ZV0ge1xuICAgICAgICBsZXQgc2xpY2UgPSBzY2VuZS5hZGQuYW5pbWF0ZWRTcHJpdGUoXCJzbGljZVwiLCBcInByaW1hcnlcIik7XG4gICAgICAgIHNsaWNlLmFuaW1hdGlvbi5wbGF5KFwiTk9STUFMXCIsIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBbc2xpY2VdO1xuICAgIH1cblxuICAgIGhpdHMobm9kZTogR2FtZU5vZGUsIHNsaWNlU3ByaXRlOiBBbmltYXRlZFNwcml0ZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gc2xpY2VTcHJpdGUuYm91bmRhcnkub3ZlcmxhcHMobm9kZS5jb2xsaXNpb25TaGFwZSk7XG4gICAgfVxuXG4gICAgY2xvbmUoKTogV2VhcG9uVHlwZSB7XG4gICAgICAgIGxldCBuZXdUeXBlID0gbmV3IFNsaWNlKCk7XG4gICAgICAgIG5ld1R5cGUuaW5pdGlhbGl6ZSh7ZGFtYWdlOiB0aGlzLmRhbWFnZSwgY29vbGRvd246IHRoaXMuY29vbGRvd24sIGRpc3BsYXlOYW1lOiB0aGlzLmRpc3BsYXlOYW1lLCBzcHJpdGVLZXk6IHRoaXMuc3ByaXRlS2V5LCB1c2VWb2x1bWU6IHRoaXMudXNlVm9sdW1lfSk7XG4gICAgICAgIHJldHVybiBuZXdUeXBlO1xuICAgIH1cbn0iLCJpbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uLy4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFdlYXBvblR5cGUge1xuICAgIC8qKiBUaGUga2V5IGZvciB0aGlzIHNwcml0ZSBpbWFnZSAqL1xuICAgIHNwcml0ZUtleTogc3RyaW5nO1xuXG4gICAgLyoqIEhvdyBtdWNoIGRhbWFnZSB0aGlzIHdlYXBvbiBkb2VzICovXG4gICAgZGFtYWdlOiBudW1iZXI7XG5cbiAgICAvKiogRGlzcGxheSBuYW1lICovXG4gICAgZGlzcGxheU5hbWU6IHN0cmluZztcblxuICAgIC8qKiBUaGUgdXNlIGNvb2xkb3duIG9mIHRoZSB3ZWFwb24gKi9cbiAgICBjb29sZG93bjogbnVtYmVyO1xuXG4gICAgLyoqIEhvdyBsb3VkIGl0IGlzIHRvIHVzZSB0aGlzIHdlYXBvbiAqL1xuICAgIHVzZVZvbHVtZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhpcyB3ZWFwb24gdHlwZSB3aXRoIGRhdGFcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBpbml0aWFsaXplKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFuaW1hdGlvbiB0byBkbyB3aGVuIHRoaXMgd2VhcG9uIGlzIHVzZWRcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBkb0FuaW1hdGlvbiguLi5hcmdzOiBhbnkpOiB2b2lkO1xuXG4gICAgYWJzdHJhY3QgY3JlYXRlUmVxdWlyZWRBc3NldHMoc2NlbmU6IFNjZW5lKTogQXJyYXk8YW55PjtcblxuICAgIGFic3RyYWN0IGhpdHMobm9kZTogR2FtZU5vZGUsIC4uLmFyZ3M6IGFueSk6IGJvb2xlYW47XG5cbiAgICBhYnN0cmFjdCBjbG9uZSgpOiBXZWFwb25UeXBlO1xufSIsImltcG9ydCBTdGF0ZU1hY2hpbmVBSSBmcm9tIFwiLi4vLi4vV29sZmllMkQvQUkvU3RhdGVNYWNoaW5lQUlcIjtcbmltcG9ydCBHYW1lTm9kZSwgeyBUd2VlbmFibGVQcm9wZXJ0aWVzIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgeyBQbGF5ZXJfRXZlbnRzIH0gZnJvbSBcIi4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgRmFsbCBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvRmFsbFwiO1xuaW1wb3J0IElkbGUgZnJvbSBcIi4vUGxheWVyU3RhdGVzL0lkbGVcIjtcbmltcG9ydCBJbkFpciBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvSW5BaXJcIjtcbmltcG9ydCBKdW1wIGZyb20gXCIuL1BsYXllclN0YXRlcy9KdW1wXCI7XG5pbXBvcnQgV2FsayBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvV2Fsa1wiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IEl0ZW0gZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL0l0ZW1cIjtcbmltcG9ydCBJbnZlbnRvcnlNYW5hZ2VyIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9JbnZlbnRvcnlNYW5hZ2VyXCI7XG5pbXBvcnQgSW5wdXQgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0lucHV0L0lucHV0XCI7XG5pbXBvcnQgQmF0dGxlckFJIGZyb20gXCIuLi9BSS9CYXR0bGVyQUlcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IFdlYXBvbiBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcblxuXG5leHBvcnQgZW51bSBQbGF5ZXJUeXBlIHtcbiAgICBQTEFURk9STUVSID0gXCJwbGF0Zm9ybWVyXCIsXG4gICAgVE9QRE9XTiA9IFwidG9wZG93blwiXG59XG5cbmV4cG9ydCBlbnVtIFBsYXllclN0YXRlcyB7XG4gICAgSURMRSA9IFwiaWRsZVwiLFxuICAgIFdBTEsgPSBcIndhbGtcIixcblx0SlVNUCA9IFwianVtcFwiLFxuICAgIEZBTEwgPSBcImZhbGxcIixcblx0UFJFVklPVVMgPSBcInByZXZpb3VzXCJcbn1cblxuZXhwb3J0IGVudW0gQnVmZlR5cGUge1xuICAgIEFUSyA9IFwiYXR0YWNrXCIsXG4gICAgREVGID0gXCJkZWZlbmNlXCIsXG4gICAgSEVBTFRIID0gXCJoZWFsdGhcIixcbiAgICBTUEVFRCA9IFwic3BlZWRcIixcbiAgICBSQU5HRSA9IFwicmFuZ2VcIlxufVxuXG5cbnR5cGUgQnVmZiA9IHtcbiAgICBcInR5cGVcIjogQnVmZlR5cGUsXG4gICAgXCJ2YWx1ZVwiOiBudW1iZXIsXG4gICAgXCJib251c1wiOiBib29sZWFuLFxufVxuXG50eXBlIEJ1ZmZzID0gW1xuICAgIEJ1ZmYsIEJ1ZmYsIEJ1ZmZcbl1cblxuLy9UT0RPIC0gZGlzY3VzcyBtYXggc3RhdHMgZHVyaW5nIHJlZmluZW1lbnQsIHVudXNlZCBmb3Igbm93XG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQbGF5ZXJDb250cm9sbGVyIGV4dGVuZHMgU3RhdGVNYWNoaW5lQUkgaW1wbGVtZW50cyBCYXR0bGVyQUl7XG4gICAgb3duZXI6IEdhbWVOb2RlO1xuICAgIHZlbG9jaXR5OiBWZWMyID0gVmVjMi5aRVJPO1xuICAgIC8vd2lsbCBuZWVkIHRvIGRpc2N1c3MgcmVkdW5kYW50IHN0YXRzXG5cdHNwZWVkOiBudW1iZXIgPSAyMDA7XG5cdE1JTl9TUEVFRDogbnVtYmVyID0gMjAwO1xuICAgIE1BWF9TUEVFRDogbnVtYmVyID0gMzAwO1xuICAgIEJBU0VfSFA6IG51bWJlciA9IDEwMDtcbiAgICBNQVhfSFA6IG51bWJlciA9IDEwMDtcbiAgICBDVVJSRU5UX0hQOiBudW1iZXIgPSAxMDA7XG4gICAgQkFTRV9BVEs6IG51bWJlciA9IDEwMDtcbiAgICBNQVhfQVRLOiBudW1iZXIgPSAxMDA7XG4gICAgQ1VSUkVOVF9BVEs6IG51bWJlciA9IDEwMDtcbiAgICBCQVNFX0RFRjogbnVtYmVyID0gMTAwO1xuICAgIE1BWF9ERUY6IG51bWJlciA9IDEwMDtcbiAgICBDVVJSRU5UX0RFRjogbnVtYmVyID0gMTAwO1xuICAgIHRpbGVtYXA6IE9ydGhvZ29uYWxUaWxlbWFwO1xuXG4gICAgLy8gVE9ETyAtIFxuICAgIGRhbWFnZShkYW1hZ2U6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLkNVUlJFTlRfSFAgLT0gZGFtYWdlO1xuICAgIH1cblxuICAgIHByaXZhdGUgbG9va0RpcmVjdGlvbjogVmVjMjtcblxuXG4gICAgLyoqIEEgbGlzdCBvZiBpdGVtcyBpbiB0aGUgZ2FtZSB3b3JsZCAqL1xuICAgIHByaXZhdGUgaXRlbXM6IEFycmF5PEl0ZW0+O1xuXG4gICAgLy8gVGhlIGludmVudG9yeSBvZiB0aGUgcGxheWVyXG4gICAgaW52ZW50b3J5OiBJbnZlbnRvcnlNYW5hZ2VyO1xuXG4gICAgQ1VSUkVOVF9CVUZGUzoge1xuICAgICAgICBhdGs6IG51bWJlcjsgICAgLy9mbGF0IHZhbHVlIHRvIGFkZCB0byB3ZWFwb25cbiAgICAgICAgaHA6IG51bWJlcjsgICAgIC8vZmxhdCB2YWx1ZSBcbiAgICAgICAgZGVmOiBudW1iZXI7ICAgIC8vZmxhdCB2YWx1ZVxuICAgICAgICBzcGVlZDogbnVtYmVyOyAgLy9mbGF0IHZhbHVlXG4gICAgICAgIHJhbmdlOm51bWJlcjsgICAvL3JhbmdlIHdpbGwgYmUgYSBtdWx0aXBsaWVyIHZhbHVlOiAxLjUgPSAxNTAlIHJhbmdlXG4gICAgfVxuICAgIFxuICAgIFxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRocmVlIGxlZ2FsIHJhbmRvbSBnZW5lcmF0ZSBidWZmcyBiYXNlZCBvbiBjdXJyZW50IHN0YXRlXG5cdCAqIEByZXR1cm5zIFRocmVlIGJ1ZmZzXG5cdCAqL1xuICAgIHN0YXRpYyBnZXRCdWZmcygpOiBCdWZmcyB7XG4gICAgICAgIC8vIFRPRE9cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcblx0ICogQWRkIGdpdmVuIGJ1ZmYgdG8gdGhlIHBsYXllclxuXHQgKiBAcGFyYW0gYnVmZiBHaXZlbiBidWZmXG5cdCAqL1xuICAgIGFkZEJ1ZmYoYnVmZjogQnVmZik6IHZvaWQge1xuICAgICAgICAvLyBUT0RPXG4gICAgICAgIGxldCBpdGVtID0gdGhpcy5pbnZlbnRvcnkuZ2V0SXRlbSgpO1xuICAgICAgICAgICAgXG4gICAgICAgIHN3aXRjaChidWZmLnR5cGUpe1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5IRUFMVEg6XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0JVRkZTLmhwICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0hQICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkFUSzpcbiAgICAgICAgICAgICAgICAvL1RPRE8gLSBkZWNpZGUgd2hhdCB0byBkbyB3aXRoIGF0ayBzdGF0XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0JVRkZTLmF0ayArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICg8V2VhcG9uPml0ZW0pLkVYVFJBX0RBTUFHRSArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuU1BFRUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0JVRkZTLnNwZWVkICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkRFRjpcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfQlVGRlMuZGVmICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlJBTkdFOlxuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9CVUZGUy5yYW5nZSArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICg8V2VhcG9uPml0ZW0pLkVYVFJBX1JBTkdFICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgXG5cbiAgICAvL1RPRE8gLSBnZXQgdGhlIGNvcnJlY3QgdGlsZW1hcFxuICAgIGluaXRpYWxpemVBSShvd25lcjogR2FtZU5vZGUsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pe1xuICAgICAgICB0aGlzLm93bmVyID0gb3duZXI7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXplUGxhdGZvcm1lcigpO1xuXG4gICAgICAgIHRoaXMudGlsZW1hcCA9IHRoaXMub3duZXIuZ2V0U2NlbmUoKS5nZXRUaWxlbWFwKG9wdGlvbnMudGlsZW1hcCkgYXMgT3J0aG9nb25hbFRpbGVtYXA7XG4gICAgICBcbiAgICAgICAgdGhpcy5pbnZlbnRvcnkgID0gb3B0aW9ucy5pbnZlbnRvcnk7XG5cbiAgICAgICAgdGhpcy5sb29rRGlyZWN0aW9uID0gbmV3IFZlYzIoKTtcblxuICAgICAgICB0aGlzLkNVUlJFTlRfQlVGRlMgPSB7aHA6MCwgYXRrOjAsIGRlZjowLCBzcGVlZDowLCByYW5nZTowfTtcbiAgICAgICBcbiAgICAgICAgLy90byB0ZXN0IHRoZSBidWZmc1xuICAgICAgICAvL3RoaXMuYWRkQnVmZigge3R5cGU6QnVmZlR5cGUuSEVBTFRILCB2YWx1ZToxLCBib251czpmYWxzZX0gKTtcbiAgICAgICAgLy90aGlzLmFkZEJ1ZmYoIHt0eXBlOkJ1ZmZUeXBlLlJBTkdFLCB2YWx1ZToxLCBib251czpmYWxzZX0gKTtcbiAgICB9XG5cbiAgICBpbml0aWFsaXplUGxhdGZvcm1lcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlZCA9IDQwMDtcblxuICAgICAgICBsZXQgaWRsZSA9IG5ldyBJZGxlKHRoaXMsIHRoaXMub3duZXIpO1xuXHRcdHRoaXMuYWRkU3RhdGUoUGxheWVyU3RhdGVzLklETEUsIGlkbGUpO1xuXHRcdGxldCB3YWxrID0gbmV3IFdhbGsodGhpcywgdGhpcy5vd25lcik7XG5cdFx0dGhpcy5hZGRTdGF0ZShQbGF5ZXJTdGF0ZXMuV0FMSywgd2Fsayk7XG5cdFx0bGV0IGp1bXAgPSBuZXcgSnVtcCh0aGlzLCB0aGlzLm93bmVyKTtcbiAgICAgICAgdGhpcy5hZGRTdGF0ZShQbGF5ZXJTdGF0ZXMuSlVNUCwganVtcCk7XG4gICAgICAgIGxldCBmYWxsID0gbmV3IEZhbGwodGhpcywgdGhpcy5vd25lcik7XG4gICAgICAgIHRoaXMuYWRkU3RhdGUoUGxheWVyU3RhdGVzLkZBTEwsIGZhbGwpO1xuICAgICAgICBcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKFBsYXllclN0YXRlcy5JRExFKTtcbiAgICB9XG5cbiAgICBjaGFuZ2VTdGF0ZShzdGF0ZU5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICAvLyBJZiB3ZSBqdW1wIG9yIGZhbGwsIHB1c2ggdGhlIHN0YXRlIHNvIHdlIGNhbiBnbyBiYWNrIHRvIG91ciBjdXJyZW50IHN0YXRlIGxhdGVyXG4gICAgICAgIC8vIHVubGVzcyB3ZSdyZSBnb2luZyBmcm9tIGp1bXAgdG8gZmFsbCBvciBzb21ldGhpbmdcbiAgICAgICAgaWYoKHN0YXRlTmFtZSA9PT0gUGxheWVyU3RhdGVzLkpVTVAgfHwgc3RhdGVOYW1lID09PSBQbGF5ZXJTdGF0ZXMuRkFMTCkgJiYgISh0aGlzLnN0YWNrLnBlZWsoKSBpbnN0YW5jZW9mIEluQWlyKSl7XG4gICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5zdGF0ZU1hcC5nZXQoc3RhdGVOYW1lKSk7XG4gICAgICAgIH1cblxuICAgICAgICBzdXBlci5jaGFuZ2VTdGF0ZShzdGF0ZU5hbWUpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG5cdFx0aWYodGhpcy5jdXJyZW50U3RhdGUgaW5zdGFuY2VvZiBKdW1wKXtcblx0XHRcdERlYnVnLmxvZyhcInBsYXllcnN0YXRlXCIsIFwiUGxheWVyIFN0YXRlOiBKdW1wXCIpO1xuXHRcdH0gZWxzZSBpZiAodGhpcy5jdXJyZW50U3RhdGUgaW5zdGFuY2VvZiBXYWxrKXtcblx0XHRcdERlYnVnLmxvZyhcInBsYXllcnN0YXRlXCIsIFwiUGxheWVyIFN0YXRlOiBXYWxrXCIpO1xuXHRcdH0gZWxzZSBpZiAodGhpcy5jdXJyZW50U3RhdGUgaW5zdGFuY2VvZiBJZGxlKXtcblx0XHRcdERlYnVnLmxvZyhcInBsYXllcnN0YXRlXCIsIFwiUGxheWVyIFN0YXRlOiBJZGxlXCIpO1xuXHRcdH0gZWxzZSBpZih0aGlzLmN1cnJlbnRTdGF0ZSBpbnN0YW5jZW9mIEZhbGwpe1xuICAgICAgICAgICAgRGVidWcubG9nKFwicGxheWVyc3RhdGVcIiwgXCJQbGF5ZXIgU3RhdGU6IEZhbGxcIik7XG4gICAgICAgIH1cbiAgICAgICAgRGVidWcubG9nKFwicGxheWVyc3BlZWRcIiwgXCJ4OiBcIiArIHRoaXMudmVsb2NpdHkueCArIFwiLCB5OlwiICsgdGhpcy52ZWxvY2l0eS55KTtcblxuXG4gICAgICAgIC8vdGVzdGluZyB0aGUgYXR0YWNrcyBoZXJlLCBtYXkgYmUgbW92ZWQgdG8gYW5vdGhlciBwbGFjZSBsYXRlcmFcbiAgICAgICAgaWYoSW5wdXQuaXNKdXN0UHJlc3NlZChcImF0dGFja1wiKSl7XG4gICAgICAgICAgICBsZXQgaXRlbSA9IHRoaXMuaW52ZW50b3J5LmdldEl0ZW0oKTtcbiAgICAgICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJBVFRBQ0tcIiwgdHJ1ZSk7XG4gICAgICAgICAgICAvL1RPRE8gLSBnZXQgcHJvcGVyIGxvb2sgZGlyZWN0aW9uIFxuICAgICAgICAgICAgdGhpcy5sb29rRGlyZWN0aW9uLnggPSAoPFNwcml0ZT50aGlzLm93bmVyKS5pbnZlcnRYID8gLTEgOiAxO1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgaXMgYW4gaXRlbSBpbiB0aGUgY3VycmVudCBzbG90LCB1c2UgaXRcbiAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgaXRlbS51c2UodGhpcy5vd25lciwgXCJwbGF5ZXJcIiwgdGhpcy5sb29rRGlyZWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgXG5cdH1cblxuICAgIFxufSIsImltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEluQWlyIGZyb20gXCIuL0luQWlyXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZhbGwgZXh0ZW5kcyBJbkFpciB7XG4gICAgb3duZXI6IEFuaW1hdGVkU3ByaXRlO1xuXG5cdG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXkoXCJGQUxMXCIsIHRydWUpO1xuXHR9XG5cbiAgICBvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG5cdFx0dGhpcy5vd25lci5hbmltYXRpb24uc3RvcCgpO1xuICAgICAgICByZXR1cm4ge307XG4gICAgfVxufSIsImltcG9ydCBJbnB1dCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvSW5wdXQvSW5wdXRcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IHsgUGxheWVyU3RhdGVzIH0gZnJvbSBcIi4uL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBPbkdyb3VuZCBmcm9tIFwiLi9Pbkdyb3VuZFwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJZGxlIGV4dGVuZHMgT25Hcm91bmQge1xuXHRvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0dGhpcy5wYXJlbnQuc3BlZWQgPSB0aGlzLnBhcmVudC5NSU5fU1BFRUQ7XG5cdH1cblxuXHRcblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0c3VwZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgICAgIFxuICAgICAgICB0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSURMRVwiLCB0cnVlKTtcblxuXHRcdGxldCBkaXIgPSB0aGlzLmdldElucHV0RGlyZWN0aW9uKCk7XG5cblx0XHRpZighZGlyLmlzWmVybygpICYmIGRpci55ID09PSAwKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoUGxheWVyU3RhdGVzLldBTEspO1xuXHRcdH1cblx0XHRcblx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gMDtcblxuXHRcdHRoaXMub3duZXIubW92ZSh0aGlzLnBhcmVudC52ZWxvY2l0eS5zY2FsZWQoZGVsdGFUKSk7XG5cdH1cblxuXHRvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG5cdFx0dGhpcy5vd25lci5hbmltYXRpb24uc3RvcCgpO1xuXHRcdHJldHVybiB7fTtcblx0fVxufSIsImltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCB7IFBsYXllclN0YXRlcyB9IGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgUGxheWVyU3RhdGUgZnJvbSBcIi4vUGxheWVyU3RhdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgSW5BaXIgZXh0ZW5kcyBQbGF5ZXJTdGF0ZSB7XG4gICAgXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIGxldCBkaXIgPSB0aGlzLmdldElucHV0RGlyZWN0aW9uKCk7XG5cbiAgICAgICAgaWYoZGlyLnggIT09IDApe1xuXHRcdFx0KDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IE1hdGhVdGlscy5zaWduKGRpci54KSA8IDA7XG5cdFx0fVxuICAgICAgICBcblx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS54ICs9IGRpci54ICogdGhpcy5wYXJlbnQuc3BlZWQvMy41IC0gMC4zKnRoaXMucGFyZW50LnZlbG9jaXR5Lng7XG5cblx0XHR0aGlzLm93bmVyLm1vdmUodGhpcy5wYXJlbnQudmVsb2NpdHkuc2NhbGVkKGRlbHRhVCkpO1xuXG4gICAgICAgIGlmKHRoaXMub3duZXIub25Hcm91bmQpe1xuXHRcdFx0dGhpcy5maW5pc2hlZChQbGF5ZXJTdGF0ZXMuUFJFVklPVVMpO1xuXHRcdH1cbiAgICB9XG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgeyBFYXNlRnVuY3Rpb25UeXBlIH0gZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL0Vhc2VGdW5jdGlvbnNcIjtcbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCB7IFBsYXllclN0YXRlcyB9IGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgSW5BaXIgZnJvbSBcIi4vSW5BaXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSnVtcCBleHRlbmRzIEluQWlyIHtcblx0b3duZXI6IEFuaW1hdGVkU3ByaXRlO1xuXG5cdG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7a2V5OiBcImp1bXBcIiwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IGZhbHNlfSk7XG5cdH1cblxuXHRcblxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICB0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5KFwiSlVNUFwiLCB0cnVlKTtcblxuXHRcdGlmKHRoaXMub3duZXIub25DZWlsaW5nKXtcblx0XHRcdHRoaXMucGFyZW50LnZlbG9jaXR5LnkgPSAwO1xuXHRcdH1cblxuXHRcdC8vIElmIHdlJ3JlIGZhbGxpbmcsIGdvIHRvIHRoZSBmYWxsIHN0YXRlXG5cdFx0aWYodGhpcy5wYXJlbnQudmVsb2NpdHkueSA+PSAwKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoUGxheWVyU3RhdGVzLkZBTEwpO1xuXHRcdH1cblx0fVxuXG5cdG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5zdG9wKCk7XG5cdFx0cmV0dXJuIHt9O1xuXHR9XG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IFBsYXllclN0YXRlIGZyb20gXCIuL1BsYXllclN0YXRlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE9uR3JvdW5kIGV4dGVuZHMgUGxheWVyU3RhdGUge1xuXHRvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHt9XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYodGhpcy5wYXJlbnQudmVsb2NpdHkueSA+IDApe1xuXHRcdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueSA9IDA7XG5cdFx0fVxuXHRcdHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG5cdFx0bGV0IGRpcmVjdGlvbiA9IHRoaXMuZ2V0SW5wdXREaXJlY3Rpb24oKTtcblxuXHRcdGlmKGRpcmVjdGlvbi54ICE9PSAwKXtcblx0XHRcdCg8U3ByaXRlPnRoaXMub3duZXIpLmludmVydFggPSBNYXRoVXRpbHMuc2lnbihkaXJlY3Rpb24ueCkgPCAwO1xuXHRcdH1cblxuXHRcdC8vIElmIHdlIGp1bXAsIG1vdmUgdG8gdGhlIEp1bXAgc3RhdGUsIGdpdmUgYSBidXJzdCBvZiB1cHdhcmRzIHZlbG9jaXR5XG5cdFx0aWYoSW5wdXQuaXNKdXN0UHJlc3NlZChcImp1bXBcIikpe1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdFx0XG5cdFx0fSBlbHNlIGlmKCF0aGlzLm93bmVyLm9uR3JvdW5kKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoXCJmYWxsXCIpO1xuXHRcdH1cblxuXHRcdFxuXHR9XG5cblx0b25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdHJldHVybiB7fTtcblx0fVxufSIsImltcG9ydCBTdGF0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1N0YXRlL1N0YXRlXCI7XG5pbXBvcnQgU3RhdGVNYWNoaW5lIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvU3RhdGUvU3RhdGVNYWNoaW5lXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvSW5wdXQvSW5wdXRcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBUaW1lciBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvVGltaW5nL1RpbWVyXCI7XG5pbXBvcnQgeyBQbGF5ZXJfRXZlbnRzIH0gZnJvbSBcIi4uLy4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgUGxheWVyQ29udHJvbGxlciBmcm9tIFwiLi4vUGxheWVyQ29udHJvbGxlclwiO1xuXG5cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFBsYXllclN0YXRlIGV4dGVuZHMgU3RhdGUge1xuXHRvd25lcjogR2FtZU5vZGU7XG5cdGdyYXZpdHk6IG51bWJlciA9IDE1MDA7IC8vVE9ETyAtIGNhbiBjaGFuZ2UgbGF0ZXJcblx0cGFyZW50OiBQbGF5ZXJDb250cm9sbGVyO1xuXHRwb3NpdGlvblRpbWVyOiBUaW1lcjtcblxuXHRjb25zdHJ1Y3RvcihwYXJlbnQ6IFN0YXRlTWFjaGluZSwgb3duZXI6IEdhbWVOb2RlKXtcblx0XHRzdXBlcihwYXJlbnQpO1xuXHRcdHRoaXMub3duZXIgPSBvd25lcjtcblx0XHR0aGlzLnBvc2l0aW9uVGltZXIgPSBuZXcgVGltZXIoMjUwKTtcblx0XHR0aGlzLnBvc2l0aW9uVGltZXIuc3RhcnQoKTtcblx0fVxuXG5cdFxuXHRoYW5kbGVJbnB1dChldmVudDogR2FtZUV2ZW50KTogdm9pZCB7XG5cdFx0XG5cdH1cblxuXHQvKiogXG5cdCAqIEdldCB0aGUgaW5wdXRzIGZyb20gdGhlIGtleWJvYXJkLCBvciBWZWMyLlplcm8gaWYgbm90aGluZyBpcyBiZWluZyBwcmVzc2VkXG5cdCAqL1xuXHRnZXRJbnB1dERpcmVjdGlvbigpOiBWZWMyIHtcblx0XHRsZXQgZGlyZWN0aW9uID0gVmVjMi5aRVJPO1xuXHRcdGRpcmVjdGlvbi54ID0gKElucHV0LmlzUHJlc3NlZChcImxlZnRcIikgPyAtMSA6IDApICsgKElucHV0LmlzUHJlc3NlZChcInJpZ2h0XCIpID8gMSA6IDApO1xuXHRcdGRpcmVjdGlvbi55ID0gKElucHV0LmlzSnVzdFByZXNzZWQoXCJqdW1wXCIpID8gLTEgOiAwKTtcblx0XHRyZXR1cm4gZGlyZWN0aW9uO1xuXHR9XG5cblx0XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Ly8gRG8gZ3Jhdml0eVxuXHRcdFxuXHRcdGlmICh0aGlzLnBvc2l0aW9uVGltZXIuaXNTdG9wcGVkKCkpe1xuXHRcdFx0dGhpcy5lbWl0dGVyLmZpcmVFdmVudChQbGF5ZXJfRXZlbnRzLlBMQVlFUl9NT1ZFLCB7cG9zaXRpb246IHRoaXMub3duZXIucG9zaXRpb24uY2xvbmUoKX0pO1xuXHRcdFx0dGhpcy5wb3NpdGlvblRpbWVyLnN0YXJ0KCk7XG5cdFx0fVxuXHRcdHRoaXMucGFyZW50LnZlbG9jaXR5LnkgKz0gdGhpcy5ncmF2aXR5KmRlbHRhVDtcblx0fVxufSIsImltcG9ydCBJbnB1dCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvSW5wdXQvSW5wdXRcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IHsgUGxheWVyX0V2ZW50cyB9IGZyb20gXCIuLi8uLi9zd29yZF9lbnVtc1wiO1xuaW1wb3J0IHsgUGxheWVyU3RhdGVzIH0gZnJvbSBcIi4uL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBPbkdyb3VuZCBmcm9tIFwiLi9Pbkdyb3VuZFwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXYWxrIGV4dGVuZHMgT25Hcm91bmQge1xuXHRvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0dGhpcy5wYXJlbnQuc3BlZWQgPSB0aGlzLnBhcmVudC5NSU5fU1BFRUQ7XG5cdH1cblxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXHRcdC8vY29uc29sZS5sb2coXCJ3YWxraW5nIGFuaW1cIik7XG4gICAgICAgIHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJXQUxLXCIsIHRydWUpO1xuXG5cdFx0bGV0IGRpciA9IHRoaXMuZ2V0SW5wdXREaXJlY3Rpb24oKTtcblxuXHRcdGlmKGRpci5pc1plcm8oKSl7XG5cdFx0XHR0aGlzLmZpbmlzaGVkKFBsYXllclN0YXRlcy5JRExFKTtcblx0XHR9IFxuXHRcdHRoaXMucGFyZW50LnZlbG9jaXR5LnggPSBkaXIueCAqIHRoaXMucGFyZW50LnNwZWVkXG5cblx0XHR0aGlzLm93bmVyLm1vdmUodGhpcy5wYXJlbnQudmVsb2NpdHkuc2NhbGVkKGRlbHRhVCkpO1xuXHR9XG5cblx0b25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnN0b3AoKTtcblx0XHRyZXR1cm4ge307XG5cdH1cbn0iLCJpbXBvcnQgUmVnaXN0cnkgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvUmVnaXN0cnlcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcblxuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblR5cGVzL1dlYXBvblR5cGVcIjtcbmltcG9ydCBTbGljZSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvU2xpY2VcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2VhcG9uVGVtcGxhdGVSZWdpc3RyeSBleHRlbmRzIFJlZ2lzdHJ5PFdlYXBvbkNvbnN0cnVjdG9yPiB7XG4gICAgXG4gICAgcHVibGljIHByZWxvYWQoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJtID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cbiAgICAgICAgLy9UT0RPIC0gXG4gICAgICAgIC8vIExvYWQgc3ByaXRlcyBmb3IgZWFjaCB3ZWFwb24gXG4gICAgICAgIC8vcm0uaW1hZ2UoXCJzb21ldGhpbmdcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXMvc29tZXRoaW5nLnBuZ1wiKTtcbiAgICAgICAgcm0uaW1hZ2UoXCJrbmlmZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlcy9rbmlmZS5wbmdcIik7XG5cbiAgICAgICAgLy8gTG9hZCBzcHJpdGVzaGVldHNcbiAgICAgICAgLy9ybS5zcHJpdGVzaGVldChcIndlYXBvbiBhbmltXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvd2VhcG9uIGFuaW0uanNvblwiKTtcbiAgICAgICAgcm0uc3ByaXRlc2hlZXQoXCJzbGljZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL3NsaWNlLmpzb25cIik7XG5cbiAgICAgICAgLy8gUmVnaXN0ZXIgZGVmYXVsdCB0eXBlc1xuICAgICAgICAvL3RoaXMucmVnaXN0ZXJJdGVtKFwiaXRlbXR5cGVcIiwgaXRlbVR5cGVmaWxlKTtcbiAgICAgICAgdGhpcy5yZWdpc3Rlckl0ZW0oXCJzbGljZVwiLCBTbGljZSk7XG4gICAgICAgIFxuICAgIH1cblxuICAgIFxuICAgIHB1YmxpYyByZWdpc3RlckFuZFByZWxvYWRJdGVtKGtleTogc3RyaW5nKTogdm9pZCB7fVxuXG4gICAgcHVibGljIHJlZ2lzdGVySXRlbShrZXk6IHN0cmluZywgY29uc3RyOiBXZWFwb25Db25zdHJ1Y3Rvcik6IHZvaWQge1xuICAgICAgICB0aGlzLmFkZChrZXksIGNvbnN0cik7XG4gICAgfVxufVxuXG50eXBlIFdlYXBvbkNvbnN0cnVjdG9yID0gbmV3ICguLi5hcmdzOiBhbnkpID0+IFdlYXBvblR5cGU7IiwiaW1wb3J0IFJlZ2lzdHJ5IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyaWVzL1JlZ2lzdHJ5XCI7XG5pbXBvcnQgV2VhcG9uVHlwZSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvV2VhcG9uVHlwZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWFwb25UeXBlUmVnaXN0cnkgZXh0ZW5kcyBSZWdpc3RyeTxXZWFwb25UeXBlPiB7XG4gICAgXG4gICAgcHVibGljIHByZWxvYWQoKTogdm9pZCB7fVxuXG4gICAgLy8gV2UgZG9uJ3QgbmVlZCB0aGlzIGZvciB0aGlzIGFzc2lnbm1lbnRcbiAgICBwdWJsaWMgcmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShrZXk6IHN0cmluZyk6IHZvaWQge31cblxuICAgIHB1YmxpYyByZWdpc3Rlckl0ZW0oa2V5OiBzdHJpbmcsIHR5cGU6IFdlYXBvblR5cGUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hZGQoa2V5LCB0eXBlKTtcbiAgICB9XG59IiwiaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgSW5wdXQgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0lucHV0L0lucHV0XCI7XG5pbXBvcnQgeyBUd2VlbmFibGVQcm9wZXJ0aWVzIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgeyBHcmFwaGljVHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9HcmFwaGljVHlwZXNcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUG9pbnRcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1RpbWluZy9UaW1lclwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IHsgRWFzZUZ1bmN0aW9uVHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9FYXNlRnVuY3Rpb25zXCI7XG5pbXBvcnQgUGxheWVyQ29udHJvbGxlciBmcm9tIFwiLi4vUGxheWVyL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBNYWluTWVudSBmcm9tIFwiLi9NYWluTWVudVwiO1xuaW1wb3J0IHsgUGxheWVyX0V2ZW50cywgU3RhdHVzZXMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBSZWdpc3RyeU1hbmFnZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJ5TWFuYWdlclwiO1xuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblR5cGVzL1dlYXBvblR5cGVcIjtcbmltcG9ydCBXZWFwb24gZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblwiO1xuaW1wb3J0IEJhdHRsZU1hbmFnZXIgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL0JhdHRsZU1hbmFnZXJcIjtcbmltcG9ydCBFbmVteUFJIGZyb20gXCIuLi9BSS9FbmVteUFJXCI7XG5pbXBvcnQgQmF0dGxlckFJIGZyb20gXCIuLi9BSS9CYXR0bGVyQUlcIjtcbmltcG9ydCBJbnZlbnRvcnlNYW5hZ2VyIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9JbnZlbnRvcnlNYW5hZ2VyXCI7XG5pbXBvcnQgSXRlbSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvSXRlbVwiO1xuXG5cblxuXG5cbi8vICBUT0RPXG4vKipcbiAqIEFkZCBpbiBzb21lIGxldmVsIG11c2ljLlxuICogVGhpcyBjYW4gYmUgZG9uZSBoZXJlIGluIHRoZSBiYXNlIEdhbWVMZXZlbCBjbGFzcyBvciBpbmRpdmlkdWFsIGxldmVsIGZpbGVzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdhbWVMZXZlbCBleHRlbmRzIFNjZW5lIHtcbiAgICAvLyBFdmVyeSBsZXZlbCB3aWxsIGhhdmUgYSBwbGF5ZXIsIHdoaWNoIHdpbGwgYmUgYW4gYW5pbWF0ZWQgc3ByaXRlXG4gICAgcHJvdGVjdGVkIHBsYXllclNwYXduOiBWZWMyO1xuICAgIHByb3RlY3RlZCBwbGF5ZXI6IEFuaW1hdGVkU3ByaXRlO1xuICAgIHByb3RlY3RlZCByZXNwYXduVGltZXI6IFRpbWVyO1xuXG4gICAgLy8gTGFiZWxzIGZvciB0aGUgVUlcbiAgICBwcm90ZWN0ZWQgc3RhdGljIGxpdmVzQ291bnQ6IG51bWJlciA9IDM7XG4gICAgcHJvdGVjdGVkIGxpdmVzQ291bnRMYWJlbDogTGFiZWw7XG5cbiAgICAvLyBTdHVmZiB0byBlbmQgdGhlIGxldmVsIGFuZCBnbyB0byB0aGUgbmV4dCBsZXZlbFxuICAgIHByb3RlY3RlZCBsZXZlbEVuZEFyZWE6IFJlY3Q7XG4gICAgcHJvdGVjdGVkIG5leHRMZXZlbDogbmV3ICguLi5hcmdzOiBhbnkpID0+IEdhbWVMZXZlbDtcbiAgICBwcm90ZWN0ZWQgbGV2ZWxFbmRUaW1lcjogVGltZXI7XG4gICAgcHJvdGVjdGVkIGxldmVsRW5kTGFiZWw6IExhYmVsO1xuICAgIFxuICAgIC8vIFNjcmVlbiBmYWRlIGluL291dCBmb3IgbGV2ZWwgc3RhcnQgYW5kIGVuZFxuICAgIHByb3RlY3RlZCBsZXZlbFRyYW5zaXRpb25UaW1lcjogVGltZXI7XG4gICAgcHJvdGVjdGVkIGxldmVsVHJhbnNpdGlvblNjcmVlbjogUmVjdDtcblxuICAgIC8vIFRoZSBiYXR0bGUgbWFuYWdlciBmb3IgdGhlIHNjZW5lXG4gICAgcHJpdmF0ZSBiYXR0bGVNYW5hZ2VyOiBCYXR0bGVNYW5hZ2VyO1xuXG4gICAgLy8gSGVhbHRoIFVJXG4gICAgcHJvdGVjdGVkIGhlYWx0aExhYmVsOiBMYWJlbDtcblxuICAgIC8vc2VlZCBVSVxuICAgIHByb3RlY3RlZCBzZWVkTGFiZWw6IExhYmVsOyAgIFxuXG4gICAgLy8gQSBsaXN0IG9mIGl0ZW1zIGluIHRoZSBzY2VuZVxuICAgIHByaXZhdGUgaXRlbXM6IEFycmF5PEl0ZW0+O1xuXG4gICAgIC8vIEEgbGlzdCBvZiBlbmVtaWVzXG4gICAgcHJpdmF0ZSBlbmVtaWVzOiBBcnJheTxBbmltYXRlZFNwcml0ZT47XG4gICAgXG4gICAgcmFuZG9tU2VlZDogbnVtYmVyO1xuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy9jYW4gbG9hZCBwbGF5ZXIgc3ByaXRlIGhlcmVcblxuICAgICAgICAvL2NhbiBsb2FkIGVuZW15IHNwcml0ZSBoZXJlXG5cbiAgICAgICAgLy8gTG9hZCB0aGUgc2NlbmUgaW5mb1xuICAgICAgICB0aGlzLmxvYWQub2JqZWN0KFwid2VhcG9uRGF0YVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvZGF0YS93ZWFwb25EYXRhLmpzb25cIik7XG5cbiAgICAgICAgLy8gTG9hZCBpbiB0aGUgZW5lbXkgaW5mb1xuICAgICAgICAvL3RoaXMubG9hZC5vYmplY3QoXCJlbmVteURhdGFcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2RhdGEvZW5lbXkuanNvblwiKTtcblxuICAgICAgICAvLyBMb2FkIGluIGl0ZW0gaW5mb1xuICAgICAgICAvL3RoaXMubG9hZC5vYmplY3QoXCJpdGVtRGF0YVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvZGF0YS9pdGVtcy5qc29uXCIpO1xuXG5cbiAgICAgICAgdGhpcy5sb2FkLmltYWdlKFwia25pZmVcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXMva25pZmUucG5nXCIpO1xuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJzbGljZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL3NsaWNlLmpzb25cIik7XG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcImludmVudG9yeVNsb3RcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXMvaW52ZW50b3J5LnBuZ1wiKTtcblxuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJ0ZXN0X2R1bW15XCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy90ZXN0X2R1bW15Lmpzb25cIilcbiAgICB9XG5cbiAgICBzdGFydFNjZW5lKCk6IHZvaWQge1xuXG4gICAgICAgXG5cbiAgICAgICAgLy8gRG8gdGhlIGdhbWUgbGV2ZWwgc3RhbmRhcmQgaW5pdGlhbGl6YXRpb25zXG4gICAgICAgIHRoaXMuaW5pdExheWVycygpO1xuICAgICAgICB0aGlzLmluaXRWaWV3cG9ydCgpO1xuXG4gICAgICAgIC8vIENyZWF0ZSB0aGUgYmF0dGxlIG1hbmFnZXJcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyID0gbmV3IEJhdHRsZU1hbmFnZXIoKTtcblxuICAgICAgICAvLyBUT0RPXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZVdlYXBvbnMoKTtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgaXRlbXMgYXJyYXkgLSB0aGlzIHJlcHJlc2VudHMgaXRlbXMgdGhhdCBhcmUgaW4gdGhlIGdhbWUgd29ybGRcbiAgICAgICAgdGhpcy5pdGVtcyA9IG5ldyBBcnJheSgpO1xuXG4gICAgICAgICAvLyBDcmVhdGUgYW4gZW5lbWllcyBhcnJheVxuICAgICAgICB0aGlzLmVuZW1pZXMgPSBuZXcgQXJyYXkoKTtcblxuICAgICAgICB0aGlzLmluaXRQbGF5ZXIoKTtcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVUb0V2ZW50cygpO1xuICAgICAgICB0aGlzLmFkZFVJKCk7XG5cbiAgICAgICAgXG4gICAgICAgIC8vIFNlbmQgdGhlIHBsYXllciBhbmQgZW5lbWllcyB0byB0aGUgYmF0dGxlIG1hbmFnZXJcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyLnNldFBsYXllcnMoWzxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haV0pO1xuICAgICAgICAvLyBJbml0aWFsaXplIGFsbCBlbmVtaWVzXG4gICAgICAgIC8vdGhpcy5pbml0aWFsaXplRW5lbWllcygpO1xuICAgICAgICB0aGlzLmJhdHRsZU1hbmFnZXIuc2V0RW5lbWllcyh0aGlzLmVuZW1pZXMubWFwKGVuZW15ID0+IDxCYXR0bGVyQUk+ZW5lbXkuX2FpKSk7XG5cbiAgICAgICAgLy8gU3Vic2NyaWJlIHRvIHJlbGV2YW50IGV2ZW50c1xuICAgICAgICAvL3RoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiXCIpO1xuICAgICAgXG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgdGltZXJzXG4gICAgICAgIHRoaXMucmVzcGF3blRpbWVyID0gbmV3IFRpbWVyKDEwMDAsICgpID0+IHtcbiAgICAgICAgICAgIGlmKEdhbWVMZXZlbC5saXZlc0NvdW50ID09PSAwKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwYXduUGxheWVyKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5wbGF5ZXIuZW5hYmxlUGh5c2ljcygpO1xuICAgICAgICAgICAgICAgIHRoaXMucGxheWVyLnVuZnJlZXplKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmxldmVsVHJhbnNpdGlvblRpbWVyID0gbmV3IFRpbWVyKDUwMCk7XG4gICAgICAgIHRoaXMubGV2ZWxFbmRUaW1lciA9IG5ldyBUaW1lcigzMDAwLCAoKSA9PiB7XG4gICAgICAgICAgICAvLyBBZnRlciB0aGUgbGV2ZWwgZW5kIHRpbWVyIGVuZHMsIGZhZGUgdG8gYmxhY2sgYW5kIHRoZW4gZ28gdG8gdGhlIG5leHQgc2NlbmVcbiAgICAgICAgICAgIHRoaXMubGV2ZWxUcmFuc2l0aW9uU2NyZWVuLnR3ZWVucy5wbGF5KFwiZmFkZUluXCIpO1xuICAgICAgICB9KTtcblxuXG4gICAgICAgIFxuICAgICAgICAvLyBTdGFydCB0aGUgYmxhY2sgc2NyZWVuIGZhZGUgb3V0XG4gICAgICAgIHRoaXMubGV2ZWxUcmFuc2l0aW9uU2NyZWVuLnR3ZWVucy5wbGF5KFwiZmFkZU91dFwiKTtcblxuICAgICAgICAvL1RPRE8gLSB1bmNvbW1lbnQgd2hlbiBkb25lIHRlc3RpbmdcbiAgICAgICAgLy8gSW5pdGlhbGx5IGRpc2FibGUgcGxheWVyIG1vdmVtZW50XG4gICAgICAgIC8vSW5wdXQuZGlzYWJsZUlucHV0KCk7XG4gICAgICAgIElucHV0LmVuYWJsZUlucHV0KCk7XG4gICAgfVxuXG5cbiAgICB1cGRhdGVTY2VuZShkZWx0YVQ6IG51bWJlcil7XG4gICAgICAgIC8vIEhhbmRsZSBldmVudHMgYW5kIHVwZGF0ZSB0aGUgVUkgaWYgbmVlZGVkXG4gICAgICAgIHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuICAgICAgICAgICAgbGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgc3dpdGNoKGV2ZW50LnR5cGUpe1xuICAgICAgICAgICAgICAgIGNhc2UgUGxheWVyX0V2ZW50cy5FTkVNWV9LSUxMRUQ6XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBsZXQgbm9kZSA9IHRoaXMuc2NlbmVHcmFwaC5nZXROb2RlKGV2ZW50LmRhdGEuZ2V0KFwib3duZXJcIikpOy8vZ2V0IGVuZW15IGlkIFxuICAgICAgICAgICAgICAgICAgICAvL3JlbW92ZSBlbmVteSBmcm9tIGVuZW1pZXNcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmVtaWVzID0gdGhpcy5lbmVtaWVzLmZpbHRlcihpdGVtID0+IGl0ZW0gIT09IGV2ZW50LmRhdGEuZ2V0KFwiYWlcIikpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJhdHRsZU1hbmFnZXIucmVtb3ZlRW5lbXkoZXZlbnQuZGF0YS5nZXQoXCJhaVwiKSk7XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcImVuZW15IGRlc3Ryb3llZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL3VwZGF0ZSBoZWFsdGggVUkgXG4gICAgICAgIGxldCBwbGF5ZXJBSSA9ICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5haSk7XG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwudGV4dCA9IFwiUGxheWVyIEhlYWx0aDogXCIrIHBsYXllckFJLkNVUlJFTlRfSFAgKycvJyArIChwbGF5ZXJBSS5NQVhfSFAgK3BsYXllckFJLkNVUlJFTlRfQlVGRlMuaHAgKTtcblxuICAgICAgICAvL2hhbmRsZSBjb2xsaXNpb25zIC0gbWF5IGJlIGluIGJhdHRsZSBtYW5hZ2VyIGluc3RlYWRcblxuICAgICAgICAvL21vdmUgYmFja2dyb3VuZFxuXG4gICAgICAgIC8vIEdldCB0aGUgdmlld3BvcnQgY2VudGVyIGFuZCBwYWRkZWQgc2l6ZVxuXHRcdGNvbnN0IHZpZXdwb3J0Q2VudGVyID0gdGhpcy52aWV3cG9ydC5nZXRDZW50ZXIoKS5jbG9uZSgpO1xuXHRcdGNvbnN0IGJhc2VWaWV3cG9ydFNpemUgPSB0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkuc2NhbGVkKDIpO1xuICAgICAgICAvL2NoZWNrIHBvc2l0aW9uIG9mIHBsYXllclxuICAgICAgICB0aGlzLnBsYXllckZhbGxvZmYodmlld3BvcnRDZW50ZXIsIGJhc2VWaWV3cG9ydFNpemUpO1xuXG4gICAgICAgIC8vVE9ETyAtIHRoaXMgaXMgZm9yIHRlc3RpbmdcbiAgICAgICAgaWYoSW5wdXQuaXNKdXN0UHJlc3NlZChcInNwYXduXCIpKXtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidHJ5aW5nIHRvIHNwYXduIGVuZW15XCIpO1xuICAgICAgICAgICAgdGhpcy5hZGRFbmVteShcInRlc3RfZHVtbXlcIix0aGlzLnBsYXllci5wb3NpdGlvbix7cGxheWVyOiB0aGlzLnBsYXllciwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWx0aCA6MTAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlbWFwOiBcIk1haW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9hY3Rpb25zOmFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdvYWw6IFN0YXR1c2VzLlJFQUNIRURfR09BTCxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIFxuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbHplcyB0aGUgbGF5ZXJzXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGluaXRMYXllcnMoKTogdm9pZCB7XG4gICAgICAgIC8vIEFkZCBhIGxheWVyIGZvciBVSVxuICAgICAgICB0aGlzLmFkZFVJTGF5ZXIoXCJVSVwiKTtcblxuICAgICAgICAvLyBBZGQgYSBsYXllciBmb3IgcGxheWVycyBhbmQgZW5lbWllc1xuICAgICAgICB0aGlzLmFkZExheWVyKFwicHJpbWFyeVwiLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdFZpZXdwb3J0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnZpZXdwb3J0LnNldFpvb21MZXZlbCgyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGFsbCBzdWJzY3JpcHRpb25zIHRvIGV2ZW50c1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBzdWJzY3JpYmVUb0V2ZW50cygpe1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShbXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLlBMQVlFUl9ISVRfRU5FTVksXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLkVORU1ZX0tJTExFRCxcbiAgICAgICAgICAgIFBsYXllcl9FdmVudHMuTEVWRUxfU1RBUlQsXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLkxFVkVMX0VORCxcbiAgICAgICAgICAgIFBsYXllcl9FdmVudHMuUExBWUVSX0tJTExFRFxuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPIC0gXG4gICAgLyoqXG4gICAgICogQWRkcyBpbiBhbnkgbmVjZXNzYXJ5IFVJIHRvIHRoZSBnYW1lXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFkZFVJKCl7XG4gICAgICAgIC8vIEluLWdhbWUgbGFiZWxzXG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwgPSA8TGFiZWw+IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIse3Bvc2l0aW9uOiBuZXcgVmVjMigxMjAsIDMwKSwgdGV4dDogXCJQbGF5ZXIgSGVhbHRoOiBcIisgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLmFpKS5DVVJSRU5UX0hQIH0pO1xuICAgICAgICB0aGlzLmhlYWx0aExhYmVsLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0aGlzLmhlYWx0aExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG5cbiAgICAgICAgLy9zZWVkIGxhYmVsXG4gICAgICAgIFxuICAgICAgICAvL3RoaXMuc2VlZExhYmVsID0gPExhYmVsPiB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJVSVwiLHtwb3NpdGlvbjogbmV3IFZlYzIoNDAwLCAzMCksIHRleHQ6IFwiU2VlZDogXCIrIHRoaXMucmFuZG9tU2VlZCB9KTtcbiAgICAgICAgdGhpcy5zZWVkTGFiZWwgPSA8TGFiZWw+IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIse3Bvc2l0aW9uOiBuZXcgVmVjMih0aGlzLndvcmxkU2l6ZS54IC0gNTAsIDMwKSwgdGV4dDogXCJTZWVkOiBcIisgdGhpcy5yYW5kb21TZWVkIH0pO1xuICAgICAgICB0aGlzLnNlZWRMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5zZWVkTGFiZWwuZm9udCA9IFwiUGl4ZWxTaW1wbGVcIjtcbiAgICAgIFxuXG4gICAgICAgIC8vIEVuZCBvZiBsZXZlbCBsYWJlbCAoc3RhcnQgb2ZmIHNjcmVlbilcbiAgICAgICAgdGhpcy5sZXZlbEVuZExhYmVsID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoLTMwMCwgMjAwKSwgdGV4dDogXCJMZXZlbCBDb21wbGV0ZVwifSk7XG4gICAgICAgIHRoaXMubGV2ZWxFbmRMYWJlbC5zaXplLnNldCgxMjAwLCA2MCk7XG4gICAgICAgIHRoaXMubGV2ZWxFbmRMYWJlbC5ib3JkZXJSYWRpdXMgPSAwO1xuICAgICAgICB0aGlzLmxldmVsRW5kTGFiZWwuYmFja2dyb3VuZENvbG9yID0gbmV3IENvbG9yKDM0LCAzMiwgNTIpO1xuICAgICAgICB0aGlzLmxldmVsRW5kTGFiZWwudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMubGV2ZWxFbmRMYWJlbC5mb250U2l6ZSA9IDQ4O1xuICAgICAgICB0aGlzLmxldmVsRW5kTGFiZWwuZm9udCA9IFwiUGl4ZWxTaW1wbGVcIjtcblxuICAgICAgICAvLyBBZGQgYSB0d2VlbiB0byBtb3ZlIHRoZSBsYWJlbCBvbiBzY3JlZW5cbiAgICAgICAgdGhpcy5sZXZlbEVuZExhYmVsLnR3ZWVucy5hZGQoXCJzbGlkZUluXCIsIHtcbiAgICAgICAgICAgIHN0YXJ0RGVsYXk6IDAsXG4gICAgICAgICAgICBkdXJhdGlvbjogMTAwMCxcbiAgICAgICAgICAgIGVmZmVjdHM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiBUd2VlbmFibGVQcm9wZXJ0aWVzLnBvc1gsXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiAtMzAwLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IDMwMCxcbiAgICAgICAgICAgICAgICAgICAgZWFzZTogRWFzZUZ1bmN0aW9uVHlwZS5PVVRfU0lORVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5sZXZlbFRyYW5zaXRpb25TY3JlZW4gPSA8UmVjdD50aGlzLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIFwiVUlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMigzMDAsIDIwMCksIHNpemU6IG5ldyBWZWMyKDYwMCwgNDAwKX0pO1xuICAgICAgICB0aGlzLmxldmVsVHJhbnNpdGlvblNjcmVlbi5jb2xvciA9IG5ldyBDb2xvcigzNCwgMzIsIDUyKTtcbiAgICAgICAgdGhpcy5sZXZlbFRyYW5zaXRpb25TY3JlZW4uYWxwaGEgPSAxO1xuXG4gICAgICAgIHRoaXMubGV2ZWxUcmFuc2l0aW9uU2NyZWVuLnR3ZWVucy5hZGQoXCJmYWRlSW5cIiwge1xuICAgICAgICAgICAgc3RhcnREZWxheTogMCxcbiAgICAgICAgICAgIGR1cmF0aW9uOiAxMDAwLFxuICAgICAgICAgICAgZWZmZWN0czogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydHk6IFR3ZWVuYWJsZVByb3BlcnRpZXMuYWxwaGEsXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiAwLFxuICAgICAgICAgICAgICAgICAgICBlbmQ6IDEsXG4gICAgICAgICAgICAgICAgICAgIGVhc2U6IEVhc2VGdW5jdGlvblR5cGUuSU5fT1VUX1FVQURcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgb25FbmQ6IFBsYXllcl9FdmVudHMuTEVWRUxfRU5EXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMubGV2ZWxUcmFuc2l0aW9uU2NyZWVuLnR3ZWVucy5hZGQoXCJmYWRlT3V0XCIsIHtcbiAgICAgICAgICAgIHN0YXJ0RGVsYXk6IDAsXG4gICAgICAgICAgICBkdXJhdGlvbjogMTAwMCxcbiAgICAgICAgICAgIGVmZmVjdHM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnR5OiBUd2VlbmFibGVQcm9wZXJ0aWVzLmFscGhhLFxuICAgICAgICAgICAgICAgICAgICBzdGFydDogMSxcbiAgICAgICAgICAgICAgICAgICAgZW5kOiAwLFxuICAgICAgICAgICAgICAgICAgICBlYXNlOiBFYXNlRnVuY3Rpb25UeXBlLklOX09VVF9RVUFEXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIG9uRW5kOiBQbGF5ZXJfRXZlbnRzLkxFVkVMX1NUQVJUXG4gICAgICAgIH0pO1xuXG5cbiAgICB9XG5cbiAgICAvL1RPRE8gLSBkZXRlcm1pbmUgd2hldGhlciB3ZSB3aWxsIGhhdmUgd2VhcG9uIGRhdGF0eXBlXG4gICAgLyoqXG4gICAgICogXG4gICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIG5ldyB3ZWFwb25cbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgd2VhcG9uVHlwZSBvZiB0aGUgd2VhcG9uLCBhcyBhIHN0cmluZ1xuICAgICAqL1xuICAgICBjcmVhdGVXZWFwb24odHlwZTogc3RyaW5nKTogV2VhcG9uIHtcbiAgICAgICAgbGV0IHdlYXBvblR5cGUgPSA8V2VhcG9uVHlwZT5SZWdpc3RyeU1hbmFnZXIuZ2V0UmVnaXN0cnkoXCJ3ZWFwb25UeXBlc1wiKS5nZXQodHlwZSk7XG5cbiAgICAgICAgbGV0IHNwcml0ZSA9IHRoaXMuYWRkLnNwcml0ZSh3ZWFwb25UeXBlLnNwcml0ZUtleSwgXCJwcmltYXJ5XCIpO1xuXG4gICAgICAgIHJldHVybiBuZXcgV2VhcG9uKHNwcml0ZSwgd2VhcG9uVHlwZSwgdGhpcy5iYXR0bGVNYW5hZ2VyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0YWxpemVzIGFsbCB3ZWFwb24gdHlwZXMgYmFzZWQgb2YgZGF0YSBmcm9tIHdlYXBvbkRhdGEuanNvblxuICAgICAqL1xuICAgICBpbml0aWFsaXplV2VhcG9ucygpOiB2b2lke1xuICAgICAgICBsZXQgd2VhcG9uRGF0YSA9IHRoaXMubG9hZC5nZXRPYmplY3QoXCJ3ZWFwb25EYXRhXCIpO1xuXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB3ZWFwb25EYXRhLm51bVdlYXBvbnM7IGkrKyl7XG4gICAgICAgICAgICBsZXQgd2VhcG9uID0gd2VhcG9uRGF0YS53ZWFwb25zW2ldO1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBwcm90b3R5cGVcbiAgICAgICAgICAgIGxldCBjb25zdHIgPSBSZWdpc3RyeU1hbmFnZXIuZ2V0UmVnaXN0cnkoXCJ3ZWFwb25UZW1wbGF0ZXNcIikuZ2V0KHdlYXBvbi53ZWFwb25UeXBlKTtcblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgd2VhcG9uIHR5cGVcbiAgICAgICAgICAgIGxldCB3ZWFwb25UeXBlID0gbmV3IGNvbnN0cigpO1xuXG4gICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICAgICAgd2VhcG9uVHlwZS5pbml0aWFsaXplKHdlYXBvbik7XG5cbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICAgICAgUmVnaXN0cnlNYW5hZ2VyLmdldFJlZ2lzdHJ5KFwid2VhcG9uVHlwZXNcIikucmVnaXN0ZXJJdGVtKHdlYXBvbi5uYW1lLCB3ZWFwb25UeXBlKVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBwbGF5ZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdFBsYXllcigpOiB2b2lkIHtcbiAgICAgICAgXG5cbiAgICAgICAgLy9jcmVhdGUgdGhlIGludmVudG9yeVxuICAgICAgICBsZXQgaW52ZW50b3J5ID0gbmV3IEludmVudG9yeU1hbmFnZXIodGhpcywgMSwgXCJpbnZlbnRvcnlTbG90XCIsIG5ldyBWZWMyKDE2LCAxNiksIDQsIFwic2xvdHMxXCIsIFwiaXRlbXMxXCIpO1xuICAgICAgICBcblxuICAgICAgICAvL2FkZCBzdGFydGluZyB3ZWFwb24gdG8gaW52ZW50b3J5XG4gICAgICAgIGxldCBzdGFydGluZ1dlYXBvbiA9IHRoaXMuY3JlYXRlV2VhcG9uKFwia25pZmVcIik7XG4gICAgICAgIGludmVudG9yeS5hZGRJdGVtKHN0YXJ0aW5nV2VhcG9uKTsgICAgICAgICAgICAgIC8vdXNpbmcgc2xpY2UgdG8gdGVzdCByaWdodCBub3dcblxuXG4gICAgICAgIC8vIEFkZCB0aGUgcGxheWVyXG4gICAgICAgIHRoaXMucGxheWVyID0gdGhpcy5hZGQuYW5pbWF0ZWRTcHJpdGUoXCJwbGF5ZXJcIiwgXCJwcmltYXJ5XCIpO1xuICAgICAgICB0aGlzLnBsYXllci5zY2FsZS5zZXQoMSwgMSk7XG4gICAgICAgIGlmKCF0aGlzLnBsYXllclNwYXduKXtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlBsYXllciBzcGF3biB3YXMgbmV2ZXIgc2V0IC0gc2V0dGluZyBzcGF3biB0byAoMCwgMClcIik7XG4gICAgICAgICAgICB0aGlzLnBsYXllclNwYXduID0gVmVjMi5aRVJPO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucGxheWVyLnBvc2l0aW9uLmNvcHkodGhpcy5wbGF5ZXJTcGF3bik7XG4gICAgICAgIHRoaXMucGxheWVyLmFkZFBoeXNpY3MobmV3IEFBQkIoVmVjMi5aRVJPLCBuZXcgVmVjMigxNCwgMTYpKSk7ICAvL3NldHMgdGhlIGNvbGxpc2lvbiBzaGFwZVxuICAgICAgICB0aGlzLnBsYXllci5jb2xsaWRlck9mZnNldC5zZXQoMCwgMTYpO1xuICAgICAgICB0aGlzLnBsYXllci5hZGRBSShQbGF5ZXJDb250cm9sbGVyLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwbGF5ZXJUeXBlOiBcInBsYXRmb3JtZXJcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICB0aWxlbWFwOiBcIk1haW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwZWVkOiAxMDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDEwLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW52ZW50b3J5OiBpbnZlbnRvcnksXG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtczogdGhpcy5pdGVtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0RW5hYmxlZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICByYW5nZTogMTAwXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucGxheWVyLnNldEdyb3VwKFwicGxheWVyXCIpO1xuXG4gICAgICAgIHRoaXMudmlld3BvcnQuZm9sbG93KHRoaXMucGxheWVyKTtcbiAgICB9XG5cbiAgICBcbiAgICAvL1RPRE8gLSBcbiAgICAvKipcbiAgICAgKiBBZGRzIGFuIEVuZW15IGludG8gdGhlIGdhbWVcbiAgICAgKiBAcGFyYW0gc3ByaXRlS2V5IFRoZSBrZXkgb2YgdGhlIEVuZW15IHNwcml0ZVxuICAgICAqIEBwYXJhbSB0aWxlUG9zIFRoZSB0aWxlbWFwIHBvc2l0aW9uIHRvIGFkZCB0aGUgRW5lbXkgdG9cbiAgICAgKiBAcGFyYW0gYWlPcHRpb25zIFRoZSBvcHRpb25zIGZvciB0aGUgRW5lbXkgQUlcbiAgICAgKi9cbiAgICBcbiAgICBwcm90ZWN0ZWQgYWRkRW5lbXkoc3ByaXRlS2V5OiBzdHJpbmcsIHRpbGVQb3M6IFZlYzIsIGFpT3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICBsZXQgZW5lbXkgPSB0aGlzLmFkZC5hbmltYXRlZFNwcml0ZShzcHJpdGVLZXksIFwicHJpbWFyeVwiKTtcbiAgICAgICAgLy9lbmVteS5wb3NpdGlvbi5zZXQodGlsZVBvcy54KjMyLCB0aWxlUG9zLnkqMzIpO1xuICAgICAgICBlbmVteS5wb3NpdGlvbi5jb3B5KHRpbGVQb3MpO1xuICAgICAgICBlbmVteS5zY2FsZS5zZXQoMiwgMik7XG4gICAgICAgIGVuZW15LmFkZFBoeXNpY3MobmV3IEFBQkIoVmVjMi5aRVJPLCBuZXcgVmVjMigxNiwgMjUpKSk7XG4gICAgICAgIGVuZW15LmNvbGxpZGVyT2Zmc2V0LnNldCgwLCA2KTtcbiAgICAgICAgZW5lbXkuYWRkQUkoRW5lbXlBSSwgYWlPcHRpb25zKTsgLy9UT0RPIC0gYWRkIGluZGl2aWR1YWwgZW5lbXkgQUlcbiAgICAgICAgZW5lbXkuc2V0R3JvdXAoXCJFbmVteVwiKTtcbiAgICAgICAgXG4gICAgICAgIC8vYWRkIGVuZW15IHRvIHRoZSBlbmVteSBhcnJheVxuICAgICAgICB0aGlzLmVuZW1pZXMucHVzaChlbmVteSk7XG4gICAgICAgIC8vdGhpcy5iYXR0bGVNYW5hZ2VyLnNldEVuZW1pZXModGhpcy5lbmVtaWVzLm1hcChlbmVteSA9PiA8QmF0dGxlckFJPmVuZW15Ll9haSkpO1xuICAgICAgICB0aGlzLmJhdHRsZU1hbmFnZXIuYWRkRW5lbXkoPEJhdHRsZXJBST5lbmVteS5fYWkpO1xuICAgIH1cbiAgICBcblxuICAgXG4gICAgcHJvdGVjdGVkIGhhbmRsZVBsYXllckVuZW15Q29sbGlzaW9uKHBsYXllcjogQW5pbWF0ZWRTcHJpdGUsIGVuZW15OiBBbmltYXRlZFNwcml0ZSkge1xuICAgICAgICAvL2NvbGxpc2lvbnMgYXJlIGhhbmRsZWQgYnkgdGhlIGJhdHRsZU1hbmFnZXIgLSBubyBuZWVkIGZvciB0aGlzIGluIGdhbWVsZXZlbCBmb3Igbm93IFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluY3JlbWVudHMgdGhlIGFtb3VudCBvZiBsaWZlIHRoZSBwbGF5ZXIgaGFzXG4gICAgICogQHBhcmFtIGFtdCBUaGUgYW1vdW50IHRvIGFkZCB0byB0aGUgcGxheWVyIGxpZmVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5jUGxheWVyTGlmZShhbXQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBHYW1lTGV2ZWwubGl2ZXNDb3VudCArPSBhbXQ7XG4gICAgICAgIHRoaXMubGl2ZXNDb3VudExhYmVsLnRleHQgPSBcIkxpdmVzOiBcIiArIEdhbWVMZXZlbC5saXZlc0NvdW50O1xuICAgICAgICBpZiAoR2FtZUxldmVsLmxpdmVzQ291bnQgPT0gMCl7XG4gICAgICAgICAgICBJbnB1dC5kaXNhYmxlSW5wdXQoKTtcbiAgICAgICAgICAgIHRoaXMucGxheWVyLmRpc2FibGVQaHlzaWNzKCk7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJwbGF5ZXJfZGVhdGhcIiwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IGZhbHNlfSk7XG4gICAgICAgICAgICB0aGlzLnBsYXllci50d2VlbnMucGxheShcImRlYXRoXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcGxheWVyIHRvIHNwYXduXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlc3Bhd25QbGF5ZXIoKTogdm9pZCB7XG4gICAgICAgIEdhbWVMZXZlbC5saXZlc0NvdW50ID0gMztcbiAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlNUT1BfU09VTkQsIHtrZXk6IFwibGV2ZWxfbXVzaWNcIn0pO1xuICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51LCB7fSk7XG4gICAgICAgIElucHV0LmVuYWJsZUlucHV0KCk7XG4gICAgfVxuXG5cblxuICAgIC8qKlxuICAgICAqIFxuICAgICAqIGhhbmRsZXMgdGhlIHBsYXllciBmYWxsaW5nIG9mZiB0aGUgbWFwXG4gICAgICogXG4gICAgICogQHBhcmFtIHZpZXdwb3J0Q2VudGVyIFRoZSBjZW50ZXIgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZpZXdwb3J0U2l6ZSBUaGUgc2l6ZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBwbGF5ZXJGYWxsb2ZmKHZpZXdwb3J0Q2VudGVyOiBWZWMyLCB2aWV3cG9ydFNpemU6IFZlYzIpOnZvaWR7XG4gICAgICAgICBpZih0aGlzLnBsYXllci5wb3NpdGlvbi55ID49IHZpZXdwb3J0Q2VudGVyLnkgK3ZpZXdwb3J0U2l6ZS55LzIuMCl7XG5cdFx0XHRcblx0XHRcdHRoaXMucGxheWVyLnBvc2l0aW9uLnNldCh0aGlzLnBsYXllclNwYXduLngsdGhpcy5wbGF5ZXJTcGF3bi55KTtcblx0XHR9XG4gICAgfVxuXG4gICAgXG59IiwiXG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQ29uZmlnTWFuYWdlciBmcm9tIFwiLi4vVG9vbHMvQ29uZmlnTWFuYWdlclwiO1xuaW1wb3J0IFNhdmVNYW5hZ2VyIGZyb20gXCIuLi9Ub29scy9TYXZlTWFuYWdlclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBMYXllciBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvTGF5ZXJcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IE1haW5NZW51IGZyb20gXCIuL01haW5NZW51XCI7XG5pbXBvcnQgU2NlbmVXaXRoU3RvcnkgZnJvbSBcIi4vU2NlbmVXaXRoU3RvcnlcIjtcbmltcG9ydCBUdXRvcmlhbCBmcm9tIFwiLi9UdXRvcmlhbFwiO1xuXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExldmVscyBleHRlbmRzIFNjZW5lIHtcbiAgICBwcml2YXRlIHByaW1hcnk6IExheWVyO1xuICAgIC8vIFRPRE9cbiAgICBsb2FkU2NlbmUoKXt9XG4gICAgc3RhcnRTY2VuZSgpe1xuICAgICAgICBjb25zdCBjZW50ZXIgPSB0aGlzLnZpZXdwb3J0LmdldENlbnRlcigpO1xuXG4gICAgICAgIC8vIFRoZSBtYWluIG1lbnVcbiAgICAgICAgdGhpcy5wcmltYXJ5ID0gdGhpcy5hZGRVSUxheWVyKFwicHJpbWFyeVwiKTtcblxuICAgICAgICBcbiAgICAgICAgY29uc3QgdHV0b3JpYWwgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDIwMCksIHRleHQ6IFwidHV0b3JpYWwgXCJ9KTtcbiAgICAgICAgdHV0b3JpYWwuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIHR1dG9yaWFsLmJvcmRlcldpZHRoID0gMjtcbiAgICAgICAgdHV0b3JpYWwuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdHV0b3JpYWwuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHR1dG9yaWFsLm9uQ2xpY2tFdmVudElkID0gXCJ0dXRvcmlhbFwiO1xuXG4gICAgICAgIGNvbnN0IGxldmVsMSA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMTUwKSwgdGV4dDogXCJsZXZlbCAxXCJ9KTtcbiAgICAgICAgbGV2ZWwxLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBsZXZlbDEuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBsZXZlbDEuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbGV2ZWwxLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBsZXZlbDEub25DbGlja0V2ZW50SWQgPSBcImxldmVsMVwiO1xuXG4gICAgICAgIGNvbnN0IGxldmVsMiA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMTAwKSwgdGV4dDogXCJsZXZlbCAyXCJ9KTtcbiAgICAgICAgbGV2ZWwyLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBsZXZlbDIuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBsZXZlbDIuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbGV2ZWwyLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBsZXZlbDIub25DbGlja0V2ZW50SWQgPSBcImxldmVsMlwiO1xuXG4gICAgICAgIGNvbnN0IGxldmVsMyA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gNTApLCB0ZXh0OiBcImxldmVsIDNcIn0pO1xuICAgICAgICBsZXZlbDMuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGxldmVsMy5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGxldmVsMy5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBsZXZlbDMuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGxldmVsMy5vbkNsaWNrRXZlbnRJZCA9IFwibGV2ZWwzXCI7XG5cbiAgICAgICAgY29uc3QgbGV2ZWw0ID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInByaW1hcnlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKSwgdGV4dDogXCJsZXZlbCA0XCJ9KTtcbiAgICAgICAgbGV2ZWw0LnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBsZXZlbDQuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBsZXZlbDQuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbGV2ZWw0LmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBsZXZlbDQub25DbGlja0V2ZW50SWQgPSBcImxldmVsNFwiO1xuXG4gICAgICAgIGNvbnN0IGxldmVsNSA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgNTApLCB0ZXh0OiBcImxldmVsIDVcIn0pO1xuICAgICAgICBsZXZlbDUuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGxldmVsNS5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGxldmVsNS5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBsZXZlbDUuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGxldmVsNS5vbkNsaWNrRXZlbnRJZCA9IFwibGV2ZWw1XCI7XG5cbiAgICAgICAgY29uc3QgU3RvcnlTY2VuZVRlc3RlciA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMTAwKSwgdGV4dDogXCJTdG9yeVNjZW5lVGVzdGVyXCJ9KTtcbiAgICAgICAgU3RvcnlTY2VuZVRlc3Rlci5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgU3RvcnlTY2VuZVRlc3Rlci5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIFN0b3J5U2NlbmVUZXN0ZXIuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgU3RvcnlTY2VuZVRlc3Rlci5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgU3RvcnlTY2VuZVRlc3Rlci5vbkNsaWNrRXZlbnRJZCA9IFwiU3RvcnlTY2VuZVRlc3RlclwiO1xuXG4gICAgICAgIGNvbnN0IGJhY2sgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDI1MCksIHRleHQ6IFwiQmFja1wifSk7XG4gICAgICAgIGJhY2suc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGJhY2suYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBiYWNrLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGJhY2suYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGJhY2sub25DbGlja0V2ZW50SWQgPSBcImJhY2tcIjtcbiAgICAgICAgXG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwidHV0b3JpYWxcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwibGV2ZWwxXCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImxldmVsMlwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJsZXZlbDNcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwibGV2ZWw0XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImxldmVsNVwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJTdG9yeVNjZW5lVGVzdGVyXCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImJhY2tcIik7XG4gICAgfVxuXG4gICAgdXBkYXRlU2NlbmUoKXtcbiAgICAgICAgd2hpbGUodGhpcy5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSl7XG4gICAgICAgICAgICBsZXQgZXZlbnQgPSB0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpO1xuXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhldmVudCk7XG5cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJ0dXRvcmlhbFwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKFR1dG9yaWFsLCB7fSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwibGV2ZWwxXCIpe1xuICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoTWFpbk1lbnUsIHt9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJsZXZlbDJcIil7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShNYWluTWVudSwge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcImxldmVsM1wiKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51LCB7fSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwibGV2ZWw0XCIpe1xuICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoTWFpbk1lbnUsIHt9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJsZXZlbDVcIil7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShNYWluTWVudSwge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcIlN0b3J5U2NlbmVUZXN0ZXJcIil7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShTY2VuZVdpdGhTdG9yeSwge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcImJhY2tcIil7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShNYWluTWVudSwge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIFxuICAgICAgICB9XG4gICAgfVxuXG59IiwiaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IENvbmZpZ01hbmFnZXIgZnJvbSBcIi4uL1Rvb2xzL0NvbmZpZ01hbmFnZXJcIjtcbmltcG9ydCBTYXZlTWFuYWdlciBmcm9tIFwiLi4vVG9vbHMvU2F2ZU1hbmFnZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgQnV0dG9uIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvblwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL0xheWVyXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBMZXZlbHMgZnJvbSBcIi4vTGV2ZWxzXCI7XG5pbXBvcnQgUmFuZG9tTWFwR2VuZXJhdG9yIGZyb20gXCIuLi9Ub29scy9SYW5kb21NYXBHZW5lcmF0b3JcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWFpbk1lbnUgZXh0ZW5kcyBTY2VuZSB7XG4gICAgcHJvdGVjdGVkIGNvbmZpZzogQ29uZmlnTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgc2F2ZTogU2F2ZU1hbmFnZXI7XG5cbiAgICAvLyBMYXllcnMsIGZvciBtdWx0aXBsZSBtYWluIG1lbnUgc2NyZWVuc1xuICAgIHByaXZhdGUgbWFpbk1lbnU6IExheWVyO1xuICAgIHByaXZhdGUgYWJvdXQ6IExheWVyO1xuICAgIHByaXZhdGUgY29udHJvbDogTGF5ZXI7XG4gICAgLy8gcHJpdmF0ZSBybWc6IFJhbmRvbU1hcEdlbmVyYXRvcjtcbiAgICBcblxuICAgIGFuaW1hdGVkU3ByaXRlOiBBbmltYXRlZFNwcml0ZTtcblxuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy8gTG9hZCB0aGUgbWVudSBzb25nXG4gICAgICAgIC8vdGhpcy5sb2FkLmF1ZGlvKFwibWVudVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvbXVzaWMvbWVudS5tcDNcIik7XG4gICAgfVxuXG4gICAgLy9UT0RPIFxuICAgIFxuICAgIHN0YXJ0U2NlbmUoKTogdm9pZHtcbiAgICAgICAgLy8gdGhpcy5jb25maWcgPSBuZXcgQ29uZmlnTWFuYWdlcigpO1xuICAgICAgICAvLyB0aGlzLnNhdmUgPSBuZXcgU2F2ZU1hbmFnZXIoKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5jb25maWcuZ2V0Vm9sdW1lKCkpO1xuICAgICAgICAvLyB0aGlzLmNvbmZpZy5zZXRWb2x1bWUoMTAwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5jb25maWcuZ2V0Vm9sdW1lKCkpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh0aGlzLnNhdmUuZ2V0TGV2ZWwoKSk7XG4gICAgICAgIC8vIHRoaXMuc2F2ZS5zZXRMZXZlbCgxMCk7XG5cbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5zYXZlLmdldExldmVsKCkpO1xuICAgICAgICBcbiAgICAgICAgLy8gdGhpcy5ybWcgPSBuZXcgUmFuZG9tTWFwR2VuZXJhdG9yKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9mb3Jlc3RfdGVtcGxhdGUuanNvblwiLCAxMTQ1MTQpO1xuICAgICAgICAvLyB0aGlzLnJtZy5nZXRNYXAoKTtcblxuXG5cbiAgICAgICAgLy8gU2NlbmUgaGFzIHN0YXJ0ZWQsIHNvIHN0YXJ0IHBsYXlpbmcgbXVzaWNcbiAgICAgICAgLy90aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJtZW51XCIsIGxvb3A6IHRydWUsIGhvbGRSZWZlcmVuY2U6IHRydWV9KTtcblxuICAgICAgICBjb25zdCBjZW50ZXIgPSB0aGlzLnZpZXdwb3J0LmdldENlbnRlcigpO1xuXG4gICAgICAgIC8vIFRoZSBtYWluIG1lbnVcbiAgICAgICAgdGhpcy5tYWluTWVudSA9IHRoaXMuYWRkVUlMYXllcihcIm1haW5NZW51XCIpO1xuXG4gICAgICAgIC8vIEFkZCBtYXAgYnV0dG9uLCBhbmQgZ2l2ZSBpdCBhbiBldmVudCB0byBlbWl0IG9uIHByZXNzXG4gICAgICAgIGNvbnN0IG1hcCA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJtYWluTWVudVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDEwMCksIHRleHQ6IFwiTWFwXCJ9KTtcbiAgICAgICAgbWFwLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBtYXAuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBtYXAuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbWFwLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBtYXAub25DbGlja0V2ZW50SWQgPSBcIm1hcFwiO1xuXG5cbiAgICAgICAgLy8gQWRkIGFib3V0IGJ1dHRvblxuICAgICAgICBjb25zdCBhYm91dCA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJtYWluTWVudVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDEwMCksIHRleHQ6IFwiQWJvdXRcIn0pO1xuICAgICAgICBhYm91dC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgYWJvdXQuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBhYm91dC5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBhYm91dC5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgYWJvdXQub25DbGlja0V2ZW50SWQgPSBcImFib3V0XCI7XG5cbiAgICAgICAgXG4gICAgICAgIC8vIEFkZCBjb250cm9sIGJ1dHRvbiwgYW5kIGdpdmUgaXQgYW4gZXZlbnQgdG8gZW1pdCBvbiBwcmVzc1xuICAgICAgICBjb25zdCBjb250cm9sID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcIm1haW5NZW51XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogXCJDb250cm9sc1wifSk7XG4gICAgICAgIGNvbnRyb2wuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGNvbnRyb2wuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBjb250cm9sLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnRyb2wuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGNvbnRyb2wub25DbGlja0V2ZW50SWQgPSBcImNvbnRyb2xcIjtcblxuICAgICAgICAvKiAjIyMjIyMjIyMjIEFCT1VUIFNDUkVFTiAjIyMjIyMjIyMjICovXG4gICAgICAgIHRoaXMuYWJvdXQgPSB0aGlzLmFkZFVJTGF5ZXIoXCJhYm91dFwiKTtcbiAgICAgICAgdGhpcy5hYm91dC5zZXRIaWRkZW4odHJ1ZSk7XG5cbiAgICAgICAgY29uc3QgYWJvdXRIZWFkZXIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAyNTApLCB0ZXh0OiBcIkFib3V0XCJ9KTtcbiAgICAgICAgYWJvdXRIZWFkZXIudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG5cbiAgICAgICAgXG4gICAgICAgIGNvbnN0IHRleHQxID0gXCJUaGlzIGdhbWUgd2FzIGNyZWF0ZWQgYnkgSGVucnkgQ2hlbiwgS2VsbHkgUGVuZywgYW5kIFJlbmdlXCI7XG4gICAgICAgIGNvbnN0IHRleHQyID0gXCJ1c2luZyB0aGUgV29sZmllMkQgZ2FtZSBlbmdpbmUsIGEgVHlwZVNjcmlwdCBnYW1lIGVuZ2luZSBjcmVhdGVkIGJ5XCI7XG4gICAgICAgIGNvbnN0IHRleHQzID0gXCJKb2UgV2VhdmVyIGFuZCBSaWNoYXJkIE1jS2VubmEuXCI7XG5cbiAgICAgICAgY29uc3QgbGluZTEgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSA1MCksIHRleHQ6IHRleHQxfSk7XG4gICAgICAgIGNvbnN0IGxpbmUyID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImFib3V0XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogdGV4dDJ9KTtcbiAgICAgICAgY29uc3QgbGluZTMgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyA1MCksIHRleHQ6IHRleHQzfSk7XG5cbiAgICAgICAgbGluZTEudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGxpbmUyLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBsaW5lMy50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcblxuICAgICAgICBjb25zdCBhYm91dEJhY2sgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAyNTApLCB0ZXh0OiBcIkJhY2tcIn0pO1xuICAgICAgICBhYm91dEJhY2suc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGFib3V0QmFjay5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGFib3V0QmFjay5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBhYm91dEJhY2suYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGFib3V0QmFjay5vbkNsaWNrRXZlbnRJZCA9IFwibWVudVwiO1xuXG4gICAgICAgIC8vIFN1YnNjcmliZSB0byB0aGUgYnV0dG9uIGV2ZW50c1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcIm1hcFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJhYm91dFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJtZW51XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImNvbnRyb2xcIik7XG5cbiAgICAgICBcbiAgICAgICAgLy9Db250cm9sIHNjcmVlblxuICAgICAgICB0aGlzLmNvbnRyb2wgPSB0aGlzLmFkZFVJTGF5ZXIoXCJjb250cm9sXCIpO1xuICAgICAgICB0aGlzLmNvbnRyb2wuc2V0SGlkZGVuKHRydWUpO1xuXG4gICAgXG4gICAgICAgIFxuICAgICAgICBjb25zdCBoZWFkZXIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDI1MCksIHRleHQ6IFwiQ29udHJvbHNcIn0pO1xuICAgICAgICBoZWFkZXIudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IGxjID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAxNTApLCB0ZXh0OiBcIkEvRCAtIE1vdmUgTGVmdC9SaWdodFwifSk7XG4gICAgICAgIGxjLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCByYyA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMTAwKSwgdGV4dDogXCJXL1MgLSBMb29rIFVwL0Rvd25cIn0pO1xuICAgICAgICByYy50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgY29uc3Qgd2FzZCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gNTApLCB0ZXh0OiBcIkovWi9FbnRlciAtIENvbmZpcm0gQXR0YWNrXCJ9KTtcbiAgICAgICAgd2FzZC50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGUgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSksIHRleHQ6IFwiU1BBQ0UvWCAtIEp1bXBcIn0pO1xuICAgICAgICBlLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCBxID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyA1MCksIHRleHQ6IFwiSy9DIC0gRGFzaFwifSk7XG4gICAgICAgIHEudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IG9uZVR3byA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMTAwKSwgdGV4dDogXCJML1YgLSBVc2UgU2tpbGxcIn0pO1xuICAgICAgICBvbmVUd28udGV4dENvbG9yID0gQ29sb3IuV0hJVEVcbiAgICAgICAgY29uc3QgenggPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDE1MCksIHRleHQ6IFwiSS9CIC0gb3BlbiBCYWNrcGFja1wifSk7XG4gICAgICAgIHp4LnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCB0YiA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMjAwKSwgdGV4dDogXCJFU0MgLSBQYXVzZVwifSk7XG4gICAgICAgIHRiLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuXG4gICAgICAgIGNvbnN0IGJhY2sgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDI1MCksIHRleHQ6IFwiQmFja1wifSk7XG4gICAgICAgIGJhY2suc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGJhY2suYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBiYWNrLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGJhY2suYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGJhY2sub25DbGlja0V2ZW50SWQgPSBcIm1lbnVcIjtcbiAgICAgICAgXG5cbiAgICB9XG5cbiAgICB1bmxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy8gVGhlIHNjZW5lIGlzIGJlaW5nIGRlc3Ryb3llZCwgc28gd2UgY2FuIHN0b3AgcGxheWluZyB0aGUgc29uZ1xuICAgICAgICAvL3RoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELCB7a2V5OiBcIm1lbnVcIn0pO1xuICAgIH1cblxuICAgIFxuICAgIHVwZGF0ZVNjZW5lKCl7XG4gICAgICAgIHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuICAgICAgICAgICAgbGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcblxuICAgICAgICAgICAgY29uc29sZS5sb2coZXZlbnQpO1xuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcIm1hcFwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKExldmVscywge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcImFib3V0XCIpe1xuICAgICAgICAgICAgICAgIHRoaXMuYWJvdXQuc2V0SGlkZGVuKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW5NZW51LnNldEhpZGRlbih0cnVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJtZW51XCIpe1xuICAgICAgICAgICAgICAgIHRoaXMubWFpbk1lbnUuc2V0SGlkZGVuKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmFib3V0LnNldEhpZGRlbih0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2wuc2V0SGlkZGVuKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJjb250cm9sXCIpe1xuICAgICAgICAgICAgICAgIHRoaXMubWFpbk1lbnUuc2V0SGlkZGVuKHRydWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbC5zZXRIaWRkZW4oZmFsc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJpbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgTGFiZWwsIHsgSEFsaWduIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBTdG9yeSBmcm9tIFwiLi4vVG9vbHMvRGF0YVR5cGVzL1N0b3J5XCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IExheWVyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9MYXllclwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vLi4vV29sZmllMkQvSW5wdXQvSW5wdXRcIjtcblxuZW51bSBNb2RlIHtcbiAgICBHQU1FX01PREUgPSBcIkdhbWVNb2RlXCIsXG4gICAgU1RPUllfTU9ERSA9IFwiU3RvcnlNb2RlXCIsXG4gICAgUEFVU0VfTU9ERSA9IFwiUGF1c2VNb2RlXCIsXG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lV2l0aFN0b3J5IGV4dGVuZHMgU2NlbmUge1xuICAgIHByaXZhdGUgY3VycmVudE1vZGU6IE1vZGUgPSBNb2RlLkdBTUVfTU9ERTtcbiAgICBwcml2YXRlIHN0b3J5dGV4dExhYmVsOiBMYWJlbDtcbiAgICBwcml2YXRlIHN0b3J5TGF5ZXI6IExheWVyO1xuICAgIHByaXZhdGUgcHJpbWFyeTogTGF5ZXI7XG4gICAgcHJpdmF0ZSBzdG9yeTogU3Rvcnk7XG4gICAgcHJpdmF0ZSBzdG9yeVByb2dyZXNzOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBzdG9yeVNwcml0ZXM6IEFycmF5PFNwcml0ZT47XG4gICAgcHJpdmF0ZSBzdG9yeUJHTXM6IEFycmF5PHN0cmluZz47XG4gICAgcHJpdmF0ZSBjdXJyZW50U3BlYWtlcjogc3RyaW5nO1xuICAgIHByaXZhdGUgY3VycmVudENvbnRlbnQ6IHN0cmluZztcblxuICAgIHN0YXJ0U2NlbmUoKTogdm9pZCB7XG5cblxuXG4gICAgICAgIC8vIFRoZSBjb2RlIGJlbG93IGFyZSBmb3IgdGVzdGluZyBvbmx5LiBQbGVhc2UgY29tbWVudCB0aGVtIHdoZW4gc3VibWl0XG5cbiAgICAgICAgdGhpcy5wcmltYXJ5ID0gdGhpcy5hZGRVSUxheWVyKFwicHJpbWFyeVwiKTtcbiAgICAgICAgY29uc3QgY2VudGVyID0gdGhpcy52aWV3cG9ydC5nZXRDZW50ZXIoKTtcbiAgICAgICAgY29uc3QgbG9hZFN0b3J5ID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInByaW1hcnlcIiwgeyBwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogXCJMb2FkU3RvcnlcIiB9KTtcbiAgICAgICAgbG9hZFN0b3J5LnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBsb2FkU3RvcnkuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBsb2FkU3RvcnkuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbG9hZFN0b3J5LmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBsb2FkU3Rvcnkub25DbGlja0V2ZW50SWQgPSBcImxvYWRTdG9yeVwiO1xuICAgICAgICB0aGlzLnN0b3J5TGF5ZXIgPSB0aGlzLmFkZFVJTGF5ZXIoXCJzdG9yeVwiKTtcbiAgICAgICAgdGhpcy5zdG9yeUxheWVyLmRpc2FibGUoKTtcblxuXG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwibG9hZFN0b3J5XCIpO1xuXG5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGxvYWQgYSBzdG9yeSBKU09OIGZyb20gc3RvcnlQYXRoIGFuZCBhdXRvIGRpc3BsYXkgaXQgdG8gc3RvcnlMYXllclxuICAgICAqIEBwYXJhbSBzdG9yeVBhdGggVGhlIHBhdGggdG8gdGhlIHN0b3J5IEpTT05cbiAgICAgKi9cbiAgICBhc3luYyBzdG9yeUxvYWRlcihzdG9yeVBhdGg6IHN0cmluZykge1xuICAgICAgICAvLyBJIG1heSB3YW50IHRvIGxvYWQgbXVsdGlwbGUgc3RvcmllcyBpbiBhIHNpbmdsZSBzY2VuZSwgYnV0IHRoaXMgXG4gICAgICAgIC8vIExheWVyIHdpdGggbmFtZSBzdG9yeSBhbHJlYWR5IGV4aXN0c1xuICAgICAgICAvLyBzbyBjYW4gaSBkZXRlY3Qgd2hldGhlciB0aGlzIGxheWVyIGV4aXN0cz9cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCAoYXdhaXQgZmV0Y2goc3RvcnlQYXRoKSkuanNvbigpO1xuICAgICAgICB0aGlzLnN0b3J5ID0gPFN0b3J5PnJlc3BvbnNlO1xuICAgICAgICBjb25zb2xlLmxvZyhcInN0b3J5OlwiLCB0aGlzLnN0b3J5KTtcbiAgICAgICAgaWYgKHRoaXMuc3RvcnkuYmdtKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3J5QkdNcyA9IG5ldyBBcnJheTtcbiAgICAgICAgICAgIHRoaXMuc3RvcnkuYmdtLmZvckVhY2goKGJnbSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIHRoaXMubG9hZC5hdWRpbyhiZ20ua2V5LCBiZ20ucGF0aCk7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJhdWRpbzpcIiwgYmdtLmtleSwgXCJwYXRoOlwiLCBiZ20ucGF0aCk7XG4gICAgICAgICAgICAgICAgLy8gdGhpcy5sb2FkLmxvYWRSZXNvdXJjZXNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vICAgICBjb25zb2xlLmxvZyhcImZpbmlzaGVkIGxvYWRpbmcgYXVkaW9cIik7XG4gICAgICAgICAgICAgICAgLy8gICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7IGtleTogYmdtLmtleSwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgLy8gfSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5sb2FkLmdldEF1ZGlvKGJnbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7IGtleTogYmdtLmtleSwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWQuc2luZ2xlQXVkaW8oYmdtLmtleSwgYmdtLnBhdGgsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5QTEFZX1NPVU5ELCB7IGtleTogYmdtLmtleSwgbG9vcDogZmFsc2UsIGhvbGRSZWZlcmVuY2U6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnlCR01zLnB1c2goYmdtLmtleSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3VycmVudFNwZWFrZXIgPSB0aGlzLnN0b3J5LnRleHRzWzBdLnNwZWFrZXI7XG4gICAgICAgIHRoaXMuY3VycmVudENvbnRlbnQgPSB0aGlzLnN0b3J5LnRleHRzWzBdLmNvbnRlbnQ7XG4gICAgICAgIHRoaXMuc3RvcnlMYXllci5lbmFibGUoKTtcbiAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJzdG9yeVwiLCB7IHBvc2l0aW9uOiBuZXcgVmVjMih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCwgdGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkgKyAyNDApLCB0ZXh0OiBcIlwiIH0pO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG4gICAgICAgIHRoaXMuc3Rvcnl0ZXh0TGFiZWwuZm9udFNpemUgPSAyMDtcbiAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLnN0b3J5UHJvZ3Jlc3MgPSAtMTtcbiAgICAgICAgdGhpcy5zdG9yeVNwcml0ZXMgPSBuZXcgQXJyYXk7XG4gICAgICAgIHRoaXMuY3VycmVudE1vZGUgPSBNb2RlLlNUT1JZX01PREU7XG4gICAgICAgIHRoaXMudXBkYXRlU3RvcnkoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBzdG9yeSBoYXMgbmV4dCBzZW50ZW5jZSBGYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBoYXNOZXh0U3RvcnkoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRNb2RlID09PSBNb2RlLlNUT1JZX01PREUgJiYgdGhpcy5zdG9yeVByb2dyZXNzICsgMSA8IHRoaXMuc3RvcnkudGV4dHMubGVuZ3RoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdvIHRvIHRoZSBuZXh0IHNlbnRlbmNlIG9mIGN1cnJlbnQgc3RvcnkgaWYgdGhlcmUgaXMgb25lIG9yIGNsZWFyIHRoZSBzdG9yeUxheWVyIGFuZCBleGl0IHN0b3J5TW9kZVxuICAgICAqL1xuICAgIHVwZGF0ZVN0b3J5KCkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50TW9kZSA9PT0gTW9kZS5TVE9SWV9NT0RFICYmIHRoaXMuaGFzTmV4dFN0b3J5KCkpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcnlQcm9ncmVzcysrO1xuICAgICAgICAgICAgbGV0IHRtcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3J5LnRleHRzW3RoaXMuc3RvcnlQcm9ncmVzc10uYWN0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5hY3Rpb25zLmZvckVhY2goYWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImxvYWRTcHJpdGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzLmxvYWQuaW1hZ2UoYWN0aW9uLmtleSwgYWN0aW9uLnBhdGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMubG9hZC5sb2FkUmVzb3VyY2VzRnJvbVF1ZXVlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgdG1wID0gdGhpcy5hZGQuc3ByaXRlKGFjdGlvbi5rZXksIFwic3RvcnlcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIHRtcC5wb3NpdGlvbi5zZXQoYWN0aW9uLnBvc2l0b25bMF0sIGFjdGlvbi5wb3NpdG9uWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgdG1wLnNjYWxlLnNldChhY3Rpb24uc2NhbGVbMF0sIGFjdGlvbi5zY2FsZVsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIHRoaXMuc3RvcnlTcHJpdGVzLnB1c2godG1wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sb2FkLmdldEltYWdlKGFjdGlvbi5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuYWRkLnNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAucG9zaXRpb24uc2V0KGFjdGlvbi5wb3NpdG9uWzBdLCBhY3Rpb24ucG9zaXRvblsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC5zY2FsZS5zZXQoYWN0aW9uLnNjYWxlWzBdLCBhY3Rpb24uc2NhbGVbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWQuc2luZ2xlSW1hZ2UoYWN0aW9uLmtleSwgYWN0aW9uLnBhdGgsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuYWRkLnNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnBvc2l0aW9uLnNldChhY3Rpb24ucG9zaXRvblswXSwgYWN0aW9uLnBvc2l0b25bMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnNjYWxlLnNldChhY3Rpb24uc2NhbGVbMF0sIGFjdGlvbi5zY2FsZVsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FzZSBcImxvYWRBbmltYXRlZFNwcml0ZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChhY3Rpb24ua2V5LCBhY3Rpb24ucGF0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgdGhpcy5sb2FkLmxvYWRSZXNvdXJjZXNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICB0bXAgPSB0aGlzLmFkZC5hbmltYXRlZFNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICB0bXAucG9zaXRpb24uc2V0KGFjdGlvbi5wb3NpdG9uWzBdLCBhY3Rpb24ucG9zaXRvblsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgICAgIHRtcC5zY2FsZS5zZXQoYWN0aW9uLnNjYWxlWzBdLCBhY3Rpb24uc2NhbGVbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwibW92ZVNwcml0ZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuc3RvcnlTcHJpdGVzLmZpbmQoZnVuY3Rpb24gKHNwcml0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ByaXRlLmltYWdlSWQgPT09IGFjdGlvbi5rZXk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnBvc2l0aW9uLnNldChhY3Rpb24ucG9zaXRvblswXSwgYWN0aW9uLnBvc2l0b25bMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC5zY2FsZS5zZXQoYWN0aW9uLnNjYWxlWzBdLCBhY3Rpb24uc2NhbGVbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInNob3dTcHJpdGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAgPSB0aGlzLnN0b3J5U3ByaXRlcy5maW5kKGZ1bmN0aW9uIChzcHJpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNwcml0ZS5pbWFnZUlkID09PSBhY3Rpb24ua2V5O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC52aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJoaWRlU3ByaXRlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gdGhpcy5zdG9yeVNwcml0ZXMuZmluZChmdW5jdGlvbiAoc3ByaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzcHJpdGUuaW1hZ2VJZCA9PT0gYWN0aW9uLmtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRTcGVha2VyID0gdGhpcy5zdG9yeS50ZXh0c1t0aGlzLnN0b3J5UHJvZ3Jlc3NdLnNwZWFrZXI7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRDb250ZW50ID0gdGhpcy5zdG9yeS50ZXh0c1t0aGlzLnN0b3J5UHJvZ3Jlc3NdLmNvbnRlbnQ7XG4gICAgICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLnRleHQgPSAodGhpcy5jdXJyZW50U3BlYWtlcj8odGhpcy5jdXJyZW50U3BlYWtlcitcIjpcIik6KFwiXCIpKSArICdcXG4nICsgdGhpcy5jdXJyZW50Q29udGVudDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudE1vZGUgPSBNb2RlLkdBTUVfTU9ERTtcbiAgICAgICAgICAgIHRoaXMuc3RvcnlQcm9ncmVzcyA9IEluZmluaXR5O1xuICAgICAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC5kZXN0cm95KCk7XG4gICAgICAgICAgICBpZiAodGhpcy5zdG9yeVNwcml0ZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5mb3JFYWNoKChzcHJpdGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgc3ByaXRlLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3J5QkdNcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnlCR01zLmZvckVhY2goKGJnbSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuU1RPUF9TT1VORCwgeyBrZXk6IGJnbSB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJzb3VuZCBzdG9wcGVkOlwiLCBiZ20pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zdG9yeUxheWVyLmRpc2FibGUoKTtcbiAgICAgICAgICAgIHRoaXMuc3RvcnlCR01zID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5zdG9yeVNwcml0ZXMgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0b3J5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIC8vIHRoaXMuc3RvcnlMYXllciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHVwZGF0ZVNjZW5lKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHdoaWxlICh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKSB7XG4gICAgICAgICAgICBsZXQgZXZlbnQgPSB0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpO1xuICAgICAgICAgICAgLy8gVGVzdGluZyBjb2RlICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJsb2FkU3RvcnlcIiAmJiB0aGlzLmN1cnJlbnRNb2RlID09PSBNb2RlLkdBTUVfTU9ERSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnlMb2FkZXIoXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2pzb25zL3N0b3J5Lmpzb25cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGVzdGluZyBjb2RlXG4gICAgICAgIGlmIChJbnB1dC5pc01vdXNlSnVzdFByZXNzZWQoKSAmJiB0aGlzLmN1cnJlbnRNb2RlID09PSBNb2RlLlNUT1JZX01PREUpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlU3RvcnkoKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IFJhbmRvbU1hcEdlbmVyYXRvciBmcm9tIFwiLi4vVG9vbHMvUmFuZG9tTWFwR2VuZXJhdG9yXCI7XG5pbXBvcnQgR2FtZUxldmVsIGZyb20gXCIuL0dhbWVMZXZlbFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVHV0b3JpYWwgZXh0ZW5kcyBHYW1lTGV2ZWx7XG4gICAgcHJpdmF0ZSBtYXA6IFRpbGVkVGlsZW1hcERhdGE7XG4gICAgXG5cbiAgICBsb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLmxvYWRTY2VuZSgpO1xuICAgICAgICAvLyBMb2FkIHJlc291cmNlc1xuICAgICAgICAvLyB0aGlzLmxvYWQudGlsZW1hcChcImZvcmVzdDFcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3RpbGVtYXBzL1R1dG9yaWFsLmpzb25cIik7XG4gICAgICAgIC8vIGxldCBtYXAgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcIm1hcFwiKTtcbiAgICAgICAgdGhpcy5yYW5kb21TZWVkID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKjEwMDAwMDAwMDAwKTtcbiAgICAgICAgbGV0IHJtZyA9IG5ldyBSYW5kb21NYXBHZW5lcmF0b3IoXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2pzb25zL2ZvcmVzdF90ZW1wbGF0ZS5qc29uXCIsIHRoaXMucmFuZG9tU2VlZCk7XG4gICAgICAgIHRoaXMubWFwID0gcm1nLmdldE1hcCgpO1xuICAgICAgICB0aGlzLmxvYWQudGlsZW1hcEZyb21PYmplY3QoXCJmb3Jlc3QxXCIsIHRoaXMubWFwKTtcbiAgICAgICAgXG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcInBsYXllclwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL0hpcm8uanNvblwiKVxuXG4gICAgICAgIC8vIFRPRE8gLSBjaGFuZ2Ugd2hlbiBkb25lIHRlc3RpbmdcbiAgICAgICAgdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwic2xpY2VcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9zbGljZS5qc29uXCIpO1xuICAgICAgICBcbiAgICAgICAgXG5cbiAgICAgICAgLy9sb2FkIG11c2ljIGhlcmVcbiAgICB9XG5cbiAgICBzdGFydFNjZW5lKCk6IHZvaWQge1xuICAgICAgICAvLyBBZGQgdGhlIGxldmVsIDEgdGlsZW1hcFxuICAgICAgICB0aGlzLmFkZC50aWxlbWFwKFwiZm9yZXN0MVwiLCBuZXcgVmVjMigyLCAyKSk7XG4gICAgICAgIHRoaXMudmlld3BvcnQuc2V0Qm91bmRzKDAsIDAsIHRoaXMubWFwLndpZHRoKjMyLCB0aGlzLm1hcC5oZWlnaHQqMzIpO1xuICAgICAgICB0aGlzLnZpZXdwb3J0LmZvbGxvdyh0aGlzLnBsYXllcik7XG5cbiAgICAgICAgdGhpcy5wbGF5ZXJTcGF3biA9IG5ldyBWZWMyKDUqMzIsIDkqMzIpO1xuXG4gICAgICAgIC8vIERvIGdlbmVyaWMgc2V0dXAgZm9yIGEgR2FtZUxldmVsXG4gICAgICAgIHN1cGVyLnN0YXJ0U2NlbmUoKTtcblxuICAgIH1cblxuICAgIHVwZGF0ZVNjZW5lKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZVNjZW5lKGRlbHRhVCk7XG4gICAgfVxuXG59IiwiaW1wb3J0IHsgVGlsZWRMYXllckRhdGEsIFRpbGVkVGlsZW1hcERhdGEgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgTWFwVGVtcGxhdGUsIHsgRW50cmFuY2UsIFJvb21UZW1wbGF0ZSB9IGZyb20gXCIuL0RhdGFUeXBlcy9NYXBUZW1wbGF0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSYW5kb21NYXBHZW5lcmF0b3Ige1xuICAgIHByaXZhdGUgdGVtcGxhdGU6IE1hcFRlbXBsYXRlO1xuICAgIHByaXZhdGUgbWluWDogbnVtYmVyO1xuICAgIHByaXZhdGUgbWF4WDogbnVtYmVyO1xuICAgIHByaXZhdGUgbWluWTogbnVtYmVyO1xuICAgIHByaXZhdGUgbWF4WTogbnVtYmVyO1xuICAgIHByaXZhdGUgbWFwOiBUaWxlZFRpbGVtYXBEYXRhO1xuICAgIHByaXZhdGUgcm9vbVdpdGhMZWZ0RW50cmFuY2U6IEFycmF5PFJvb21UZW1wbGF0ZT47XG4gICAgcHJpdmF0ZSByb29tV2l0aExlZnRFbnRyYW5jZVdlaWdodDogbnVtYmVyO1xuICAgIHByaXZhdGUgcm9vbVdpdGhSaWdodEVudHJhbmNlOiBBcnJheTxSb29tVGVtcGxhdGU+O1xuICAgIHByaXZhdGUgcm9vbVdpdGhSaWdodEVudHJhbmNlV2VpZ2h0OiBudW1iZXI7XG4gICAgcHJpdmF0ZSByb29tV2l0aFVwRW50cmFuY2U6IEFycmF5PFJvb21UZW1wbGF0ZT47XG4gICAgcHJpdmF0ZSByb29tV2l0aFVwRW50cmFuY2VXZWlnaHQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHJvb21XaXRoRG93bkVudHJhbmNlOiBBcnJheTxSb29tVGVtcGxhdGU+O1xuICAgIHByaXZhdGUgcm9vbVdpdGhEb3duRW50cmFuY2VXZWlnaHQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHJvb21zOiBBcnJheTxSb29tPlxuICAgIHByaXZhdGUgZ2VuOiBhbnk7XG4gICAgcHJpdmF0ZSBoYXNFeGl0OiBib29sZWFuO1xuICAgIHByaXZhdGUgbWluUm9vbTogbnVtYmVyO1xuICAgIHByaXZhdGUgcm9vbVBsYWNlZDogbnVtYmVyO1xuICAgIHByaXZhdGUgZXhpdEZhY2luZzogRmFjaW5nO1xuICAgIHByaXZhdGUgZW5lbWllczogQXJyYXk8RW5lbXk+O1xuICAgIHByaXZhdGUgcGxheWVyOiBWZWMyO1xuXG4gICAgY29uc3RydWN0b3IoSlNPTkZpbGVQYXRoOiBzdHJpbmcsIHNlZWQ6IGFueSkge1xuICAgICAgICBsZXQgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgIHhoci5vdmVycmlkZU1pbWVUeXBlKFwiYXBwbGljYXRpb24vanNvblwiKTtcbiAgICAgICAgeGhyLm9wZW4oJ0dFVCcsIEpTT05GaWxlUGF0aCwgZmFsc2UpO1xuICAgICAgICB4aHIuc2VuZChudWxsKTtcbiAgICAgICAgdGhpcy50ZW1wbGF0ZSA9IEpTT04ucGFyc2UoeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgIHRoaXMucm9vbVdpdGhMZWZ0RW50cmFuY2UgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5yb29tV2l0aFJpZ2h0RW50cmFuY2UgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5yb29tV2l0aFVwRW50cmFuY2UgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5yb29tV2l0aERvd25FbnRyYW5jZSA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLm1pblggPSB0aGlzLm1pblkgPSB0aGlzLm1heFggPSB0aGlzLm1heFkgPVxuICAgICAgICAgICAgdGhpcy5yb29tV2l0aExlZnRFbnRyYW5jZVdlaWdodCA9IHRoaXMucm9vbVdpdGhSaWdodEVudHJhbmNlV2VpZ2h0ID1cbiAgICAgICAgICAgIHRoaXMucm9vbVdpdGhVcEVudHJhbmNlV2VpZ2h0ID0gdGhpcy5yb29tV2l0aERvd25FbnRyYW5jZVdlaWdodCA9IDA7XG5cbiAgICAgICAgdGhpcy5tYXAgPSBuZXcgVGlsZWRUaWxlbWFwRGF0YSgpO1xuICAgICAgICB0aGlzLnJvb21zID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuZW5lbWllcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLnBsYXllciA9IG5ldyBWZWMyKCk7XG4gICAgICAgIGxldCBnZW4gPSByZXF1aXJlKCdyYW5kb20tc2VlZCcpO1xuICAgICAgICB0aGlzLmdlbiA9IG5ldyBnZW4oc2VlZCk7XG4gICAgICAgIHRoaXMuaGFzRXhpdCA9IGZhbHNlO1xuICAgICAgICB0aGlzLm1pblJvb20gPSB0aGlzLnRlbXBsYXRlLm1pbnJvb207XG4gICAgICAgIHRoaXMucm9vbVBsYWNlZCA9IDA7XG4gICAgICAgIHRoaXMuZXhpdEZhY2luZyA9IHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcodGhpcy50ZW1wbGF0ZS5leGl0LmVudHJhbmNlc1swXSwgdGhpcy50ZW1wbGF0ZS5leGl0LndpZHRoKTtcblxuXG4gICAgICAgIGZvciAobGV0IHJvb20gb2YgdGhpcy50ZW1wbGF0ZS5yb29tcykge1xuICAgICAgICAgICAgbGV0IGxlZnQgPSBmYWxzZSwgcmlnaHQgPSBmYWxzZSwgdXAgPSBmYWxzZSwgZG93biA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChsZXQgZW50cmFuY2Ugb2Ygcm9vbS5lbnRyYW5jZXMpIHtcbiAgICAgICAgICAgICAgICBsZXQgZmFjaW5nID0gdGhpcy5nZXRFbnRyYW5jZUZhY2luZyhlbnRyYW5jZSwgcm9vbS53aWR0aCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChmYWNpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBGYWNpbmcuTEVGVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRmFjaW5nLlJJR0hUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmlnaHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRmFjaW5nLlVQOlxuICAgICAgICAgICAgICAgICAgICAgICAgdXAgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRmFjaW5nLkRPV046XG4gICAgICAgICAgICAgICAgICAgICAgICBkb3duID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxlZnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoTGVmdEVudHJhbmNlLnB1c2gocm9vbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aExlZnRFbnRyYW5jZVdlaWdodCArPSByb29tLndlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhSaWdodEVudHJhbmNlLnB1c2gocm9vbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aFJpZ2h0RW50cmFuY2VXZWlnaHQgKz0gcm9vbS53ZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodXApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoVXBFbnRyYW5jZS5wdXNoKHJvb20pO1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhVcEVudHJhbmNlV2VpZ2h0ICs9IHJvb20ud2VpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRvd24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoRG93bkVudHJhbmNlLnB1c2gocm9vbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aERvd25FbnRyYW5jZVdlaWdodCArPSByb29tLndlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldE1hcCgpOiBUaWxlZFRpbGVtYXBEYXRhIHtcbiAgICAgICAgbGV0IHJvb20gPSB0aGlzLmNvcHlSb29tKHRoaXMudGVtcGxhdGUuZW50cmFuY2UsIDAsIDApO1xuICAgICAgICB0aGlzLnJvb21zLnB1c2gocm9vbSk7XG5cbiAgICAgICAgbGV0IGZhY2luZyA9IHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcodGhpcy50ZW1wbGF0ZS5lbnRyYW5jZS5lbnRyYW5jZXNbMF0sIHRoaXMudGVtcGxhdGUuZW50cmFuY2Uud2lkdGgpO1xuICAgICAgICBsZXQgcG9zaXRpb24gPSBuZXcgVmVjMih0aGlzLnRlbXBsYXRlLmVudHJhbmNlLmVudHJhbmNlc1swXS54LCB0aGlzLnRlbXBsYXRlLmVudHJhbmNlLmVudHJhbmNlc1swXS55KTtcblxuICAgICAgICB0aGlzLnB1dE5leHRSb29tKHBvc2l0aW9uLCB0aGlzLmdldE9wcG9zaXRlRmFjaW5nKGZhY2luZykpO1xuXG4gICAgICAgIGlmICghdGhpcy5oYXNFeGl0KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbCB0byBnZW5lcmF0ZSBhIG1hcCB3aXRoIGV4aXQhXCIpO1xuXG4gICAgICAgIHRoaXMuZmlsbERhdGEoKTtcbiAgICAgICAgY29uc29sZS5sb2coXCJHZW5lcmF0ZWQgbWFwOlwiLCB0aGlzLm1hcCk7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcDtcbiAgICB9XG5cbiAgICBnZXRQbGF5ZXIoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLnBsYXllcjtcbiAgICB9XG5cbiAgICBnZXRFbmVtaWVzKCk6IEFycmF5PEVuZW15PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmVuZW1pZXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwdXROZXh0Um9vbShwb3NpdGlvbjogVmVjMiwgZmFjaW5nOiBGYWNpbmcpOiBib29sZWFuIHtcbiAgICAgICAgc3dpdGNoIChmYWNpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkxFRlQ6XG4gICAgICAgICAgICAgICAgcG9zaXRpb24ueCArPSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuUklHSFQ6XG4gICAgICAgICAgICAgICAgcG9zaXRpb24ueCAtPSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuVVA6XG4gICAgICAgICAgICAgICAgcG9zaXRpb24ueSArPSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuRE9XTjpcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi55IC09IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnJvb21QbGFjZWQgPj0gdGhpcy5taW5Sb29tICYmIGZhY2luZyA9PSB0aGlzLmV4aXRGYWNpbmcpIHtcbiAgICAgICAgICAgIHRoaXMucHV0RXhpdFJvb20ocG9zaXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbmV4dFJvb20gPSB0aGlzLmdldFJhbmRvbVJvb20oZmFjaW5nKTtcbiAgICAgICAgbGV0IG5leHRQb3NpdGlvbjogVmVjMiA9IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHRoaXNFbnRyYW5jZTogRW50cmFuY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZvciAobGV0IGVudHJhbmNlIG9mIG5leHRSb29tLmVudHJhbmNlcykge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcoZW50cmFuY2UsIG5leHRSb29tLndlaWdodCkgPT0gZmFjaW5nKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRtcFBvc2l0aW9uID0gbmV3IFZlYzIocG9zaXRpb24ueCAtIGVudHJhbmNlLngsIHBvc2l0aW9uLnkgLSBlbnRyYW5jZS55KTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkUm9vbSh0bXBQb3NpdGlvbiwgbmV3IFZlYzIodG1wUG9zaXRpb24ueCArIG5leHRSb29tLndpZHRoIC0gMSwgdG1wUG9zaXRpb24ueSArIG5leHRSb29tLmhlaWdodCAtIDEpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzRW50cmFuY2UgPSBlbnRyYW5jZTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dFBvc2l0aW9uID0gdG1wUG9zaXRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpc0VudHJhbmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJvb20gPSB0aGlzLmNvcHlSb29tKG5leHRSb29tLCBuZXh0UG9zaXRpb24ueCwgbmV4dFBvc2l0aW9uLnkpO1xuICAgICAgICB0aGlzLnJvb21zLnB1c2gocm9vbSk7XG4gICAgICAgIHRoaXMucm9vbVBsYWNlZCArPSAxO1xuICAgICAgICBpZiAodGhpcy5oYXNFeGl0ICYmIHRoaXMuZ2VuLnJhbmdlKCkgPD0gMC4xKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgZW50cmFuY2Ugb2YgbmV4dFJvb20uZW50cmFuY2VzKSB7XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UgIT0gdGhpc0VudHJhbmNlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGZhY2luZyA9IHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcoZW50cmFuY2UsIG5leHRSb29tLndpZHRoKTtcbiAgICAgICAgICAgICAgICBsZXQgcG9zaXRpb24gPSBuZXcgVmVjMihuZXh0UG9zaXRpb24ueCArIGVudHJhbmNlLngsIG5leHRQb3NpdGlvbi55ICsgZW50cmFuY2UueSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wdXROZXh0Um9vbShwb3NpdGlvbiwgdGhpcy5nZXRPcHBvc2l0ZUZhY2luZyhmYWNpbmcpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUVudHJhbmNlKHJvb20sIGVudHJhbmNlLCBmYWNpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1dEV4aXRSb29tKHBvc2l0aW9uOiBWZWMyKTogdm9pZCB7XG4gICAgICAgIHBvc2l0aW9uID0gbmV3IFZlYzIocG9zaXRpb24ueCAtIHRoaXMudGVtcGxhdGUuZXhpdC5lbnRyYW5jZXNbMF0ueCwgcG9zaXRpb24ueSAtIHRoaXMudGVtcGxhdGUuZXhpdC5lbnRyYW5jZXNbMF0ueSk7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkUm9vbShwb3NpdGlvbiwgbmV3IFZlYzIocG9zaXRpb24ueCArIHRoaXMudGVtcGxhdGUuZXhpdC53aWR0aCAtIDEsIHBvc2l0aW9uLnkgKyB0aGlzLnRlbXBsYXRlLmV4aXQuaGVpZ2h0IC0gMSkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgcHV0IGV4aXQgcm9vbSEhISBQb3NpdGlvbiBpcyBpbnZhbGlkISEhIFBsZWFzZSBjaGVjayBvcmRlciBvZiBlbnRyYW5jZXMgaW4gbWFwIHRlbXBsYXRlLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcm9vbSA9IHRoaXMuY29weVJvb20odGhpcy50ZW1wbGF0ZS5leGl0LCBwb3NpdGlvbi54LCBwb3NpdGlvbi55KTtcbiAgICAgICAgdGhpcy5yb29tcy5wdXNoKHJvb20pO1xuICAgICAgICB0aGlzLmhhc0V4aXQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3ZlRW50cmFuY2Uocm9vbTogUm9vbSwgZW50cmFuY2U6IEVudHJhbmNlLCBmYWNpbmc6IEZhY2luZyk6IHZvaWQge1xuICAgICAgICBsZXQgd2lkdGggPSByb29tLmJvdHRvbVJpZ2h0LnggLSByb29tLnRvcExlZnQueCArIDE7XG4gICAgICAgIGlmIChmYWNpbmcgPT0gRmFjaW5nLkxFRlQgfHwgZmFjaW5nID09IEZhY2luZy5SSUdIVCkge1xuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGVudHJhbmNlLndpZHRoOyBpbmRleCsrKVxuICAgICAgICAgICAgICAgIHJvb20udG9wTGF5ZXJbKGVudHJhbmNlLnkgKyBpbmRleCkgKiB3aWR0aCArIGVudHJhbmNlLnhdID0gMDtcbiAgICAgICAgICAgIGlmIChlbnRyYW5jZS55ID4gMClcbiAgICAgICAgICAgICAgICByb29tLnRvcExheWVyWyhlbnRyYW5jZS55IC0gMSkgKiB3aWR0aCArIGVudHJhbmNlLnhdID0gZW50cmFuY2UuYWx0X3RpbGVbMF07XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UueSArIGVudHJhbmNlLndpZHRoIDw9IChyb29tLmJvdHRvbVJpZ2h0LnkgLSByb29tLnRvcExlZnQueSkpXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMYXllclsoZW50cmFuY2UueSArIGVudHJhbmNlLndpZHRoKSAqIHdpZHRoICsgZW50cmFuY2UueF0gPSBlbnRyYW5jZS5hbHRfdGlsZVsxXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBlbnRyYW5jZS53aWR0aDsgaW5kZXgrKylcbiAgICAgICAgICAgICAgICByb29tLnRvcExheWVyWyhlbnRyYW5jZS55KSAqIHdpZHRoICsgZW50cmFuY2UueCArIGluZGV4XSA9IDA7XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UueCA+IDApXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMYXllclsoZW50cmFuY2UueSkgKiB3aWR0aCArIGVudHJhbmNlLnggLSAxXSA9IGVudHJhbmNlLmFsdF90aWxlWzBdO1xuICAgICAgICAgICAgaWYgKGVudHJhbmNlLnggKyBlbnRyYW5jZS53aWR0aCA8PSAocm9vbS5ib3R0b21SaWdodC54IC0gcm9vbS50b3BMZWZ0LngpKVxuICAgICAgICAgICAgICAgIHJvb20udG9wTGF5ZXJbKGVudHJhbmNlLnkpICogd2lkdGggKyBlbnRyYW5jZS54ICsgZW50cmFuY2Uud2lkdGhdID0gZW50cmFuY2UuYWx0X3RpbGVbMV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbGxEYXRhKCkge1xuICAgICAgICBsZXQgd2lkdGggPSB0aGlzLm1heFggLSB0aGlzLm1pblggKyAxO1xuICAgICAgICBsZXQgaGVpZ2h0ID0gdGhpcy5tYXhZIC0gdGhpcy5taW5ZICsgMTtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzID0gbmV3IEFycmF5KDIpO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0gPSBuZXcgVGlsZWRMYXllckRhdGE7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1sxXSA9IG5ldyBUaWxlZExheWVyRGF0YTtcbiAgICAgICAgdGhpcy5tYXAud2lkdGggPSB0aGlzLm1hcC5sYXllcnNbMF0ud2lkdGggPSB0aGlzLm1hcC5sYXllcnNbMV0ud2lkdGggPSB3aWR0aDtcbiAgICAgICAgdGhpcy5tYXAuaGVpZ2h0ID0gdGhpcy5tYXAubGF5ZXJzWzBdLmhlaWdodCA9IHRoaXMubWFwLmxheWVyc1sxXS5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIHRoaXMubWFwLnRpbGVoZWlnaHQgPSB0aGlzLnRlbXBsYXRlLnRpbGVoZWlnaHQ7XG4gICAgICAgIHRoaXMubWFwLnRpbGV3aWR0aCA9IHRoaXMudGVtcGxhdGUudGlsZXdpZHRoO1xuICAgICAgICB0aGlzLm1hcC5vcmllbnRhdGlvbiA9IFwib3J0aG9nb25hbFwiO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0ueCA9IHRoaXMubWFwLmxheWVyc1swXS55ID0gdGhpcy5tYXAubGF5ZXJzWzFdLnggPSB0aGlzLm1hcC5sYXllcnNbMV0ueSA9IDA7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5vcGFjaXR5ID0gdGhpcy5tYXAubGF5ZXJzWzFdLm9wYWNpdHkgPSAxO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0udmlzaWJsZSA9IHRoaXMubWFwLmxheWVyc1sxXS52aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzBdLnR5cGUgPSB0aGlzLm1hcC5sYXllcnNbMV0udHlwZSA9IFwidGlsZWxheWVyXCI7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5uYW1lID0gXCJGbG9vclwiO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMV0ubmFtZSA9IFwiV2FsbFwiO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0ucHJvcGVydGllcyA9IFt7XG4gICAgICAgICAgICBuYW1lOiBcIkNvbGxpZGFibGVcIixcbiAgICAgICAgICAgIHR5cGU6IFwiYm9vbFwiLFxuICAgICAgICAgICAgdmFsdWU6IGZhbHNlXG4gICAgICAgIH1dXG4gICAgICAgIHRoaXMubWFwLmxheWVyc1sxXS5wcm9wZXJ0aWVzID0gW3tcbiAgICAgICAgICAgIG5hbWU6IFwiQ29sbGlkYWJsZVwiLFxuICAgICAgICAgICAgdHlwZTogXCJib29sXCIsXG4gICAgICAgICAgICB2YWx1ZTogdHJ1ZVxuICAgICAgICB9XVxuICAgICAgICB0aGlzLm1hcC50aWxlc2V0cyA9IFt7XG4gICAgICAgICAgICBjb2x1bW5zOiB0aGlzLnRlbXBsYXRlLmNvbHVtbnMsXG4gICAgICAgICAgICB0aWxld2lkdGg6IHRoaXMudGVtcGxhdGUudGlsZXdpZHRoLFxuICAgICAgICAgICAgdGlsZWhlaWdodDogdGhpcy50ZW1wbGF0ZS50aWxlaGVpZ2h0LFxuICAgICAgICAgICAgdGlsZWNvdW50OiB0aGlzLnRlbXBsYXRlLnRpbGVjb3VudCxcbiAgICAgICAgICAgIGZpcnN0Z2lkOiB0aGlzLnRlbXBsYXRlLmZpcnN0Z2lkLFxuICAgICAgICAgICAgaW1hZ2VoZWlnaHQ6IHRoaXMudGVtcGxhdGUuaW1hZ2VoZWlnaHQsXG4gICAgICAgICAgICBpbWFnZXdpZHRoOiB0aGlzLnRlbXBsYXRlLmltYWdld2lkdGgsXG4gICAgICAgICAgICBtYXJnaW46IHRoaXMudGVtcGxhdGUubWFyZ2luLFxuICAgICAgICAgICAgc3BhY2luZzogdGhpcy50ZW1wbGF0ZS5zcGFjaW5nLFxuICAgICAgICAgICAgbmFtZTogdGhpcy50ZW1wbGF0ZS5uYW1lLFxuICAgICAgICAgICAgaW1hZ2U6IHRoaXMudGVtcGxhdGUuaW1hZ2VcbiAgICAgICAgfV1cblxuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0uZGF0YSA9IG5ldyBBcnJheSh3aWR0aCAqIGhlaWdodCkuZmlsbCh0aGlzLnRlbXBsYXRlLmJhY2tncm91bmQpO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMV0uZGF0YSA9IG5ldyBBcnJheSh3aWR0aCAqIGhlaWdodCk7XG5cbiAgICAgICAgZm9yIChsZXQgcm9vbSBvZiB0aGlzLnJvb21zKSB7XG4gICAgICAgICAgICBsZXQgcm9vbVdpZHRoID0gcm9vbS5ib3R0b21SaWdodC54IC0gcm9vbS50b3BMZWZ0LnggKyAxO1xuICAgICAgICAgICAgbGV0IHJvb21IZWlnaHQgPSByb29tLmJvdHRvbVJpZ2h0LnkgLSByb29tLnRvcExlZnQueSArIDE7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvb21IZWlnaHQ7IGkrKylcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJvb21XaWR0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5kYXRhWyhyb29tLnRvcExlZnQueSArIGkpICogd2lkdGggKyByb29tLnRvcExlZnQueCArIGpdID0gcm9vbS5ib3R0b21MYXllcltpICogcm9vbVdpZHRoICsgal07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWFwLmxheWVyc1sxXS5kYXRhWyhyb29tLnRvcExlZnQueSArIGkpICogd2lkdGggKyByb29tLnRvcExlZnQueCArIGpdID0gcm9vbS50b3BMYXllcltpICogcm9vbVdpZHRoICsgal07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJvb20uZW5lbWllcylcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBlbmVteSBvZiB0aGlzLmVuZW1pZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZW5lbXkucG9zaXRpb24ueCAtPSB0aGlzLm1pblg7XG4gICAgICAgICAgICAgICAgICAgIGVuZW15LnBvc2l0aW9uLnkgLT0gdGhpcy5taW5ZO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZW1pZXMucHVzaChlbmVteSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMucGxheWVyLnggLT0gdGhpcy5taW5YO1xuICAgICAgICB0aGlzLnBsYXllci55IC09IHRoaXMubWluWTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGlzVmFsaWRSb29tKHRvcExlZnQ6IFZlYzIsIGJvdHRvbVJpZ2h0OiBWZWMyKTogYm9vbGVhbiB7XG4gICAgICAgIGZvciAobGV0IHJvb20gb2YgdGhpcy5yb29tcykge1xuICAgICAgICAgICAgaWYgKHJvb20udG9wTGVmdC54IDw9IGJvdHRvbVJpZ2h0LnggJiZcbiAgICAgICAgICAgICAgICByb29tLmJvdHRvbVJpZ2h0LnggPj0gdG9wTGVmdC54ICYmXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMZWZ0LnkgPD0gYm90dG9tUmlnaHQueSAmJlxuICAgICAgICAgICAgICAgIHJvb20uYm90dG9tUmlnaHQueSA+PSB0b3BMZWZ0LnkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXCJGb3VuZCBhbiBpbnZhbGlkIHJvb20hIFRvcExlZnQ6XCIsIHRvcExlZnQudG9TdHJpbmcoKSwgXCJCb3R0b21SaWdodDpcIiwgYm90dG9tUmlnaHQudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0RW50cmFuY2VGYWNpbmcoZW50cmFuY2U6IEVudHJhbmNlLCB3aWR0aDogbnVtYmVyKTogRmFjaW5nIHtcbiAgICAgICAgaWYgKGVudHJhbmNlLnggPT09IDApXG4gICAgICAgICAgICByZXR1cm4gRmFjaW5nLkxFRlQ7XG4gICAgICAgIGVsc2UgaWYgKGVudHJhbmNlLnggPT09IHdpZHRoIC0gMSlcbiAgICAgICAgICAgIHJldHVybiBGYWNpbmcuUklHSFRcbiAgICAgICAgZWxzZSBpZiAoZW50cmFuY2UueSA9PT0gMClcbiAgICAgICAgICAgIHJldHVybiBGYWNpbmcuVVA7XG4gICAgICAgIHJldHVybiBGYWNpbmcuRE9XTjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldE9wcG9zaXRlRmFjaW5nKGZhY2luZzogRmFjaW5nKTogRmFjaW5nIHtcbiAgICAgICAgc3dpdGNoIChmYWNpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkxFRlQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5SSUdIVDtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlJJR0hUOlxuICAgICAgICAgICAgICAgIHJldHVybiBGYWNpbmcuTEVGVDtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlVQOlxuICAgICAgICAgICAgICAgIHJldHVybiBGYWNpbmcuRE9XTjtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkRPV046XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5VUDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0UmFuZG9tUm9vbShmYWNpbmc6IEZhY2luZyk6IFJvb21UZW1wbGF0ZSB7XG4gICAgICAgIGxldCBhcnJheSA9IHRoaXMuZ2V0Um9vbUFycmF5KGZhY2luZyksIHdlaWdodCA9IHRoaXMuZ2V0Um9vbVdlaWdodChmYWNpbmcpO1xuICAgICAgICBsZXQgdmFsdWUgPSB0aGlzLmdlbih3ZWlnaHQpO1xuXG4gICAgICAgIGlmICh2YWx1ZSA+PSB3ZWlnaHQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSYW5kb20gbnVtYmVyIFwiICsgdmFsdWUgKyBcIiBpcyBsYXJnZXIgdGhhbiB0b3RhbCB3ZWlnaHQgXCIgKyB3ZWlnaHQpO1xuXG4gICAgICAgIGZvciAobGV0IHJvb20gb2YgYXJyYXkpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA8IHJvb20ud2VpZ2h0KVxuICAgICAgICAgICAgICAgIHJldHVybiByb29tO1xuICAgICAgICAgICAgdmFsdWUgLT0gcm9vbS53ZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgUm9vbSEgXFxuVmFsdWU6IFwiICsgdmFsdWUgKyBcIlxcblJvb21zOiBcIiArIEpTT04uc3RyaW5naWZ5KGFycmF5KSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSb29tQXJyYXkoZmFjaW5nOiBGYWNpbmcpOiBBcnJheTxSb29tVGVtcGxhdGU+IHtcbiAgICAgICAgc3dpdGNoIChmYWNpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkxFRlQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhMZWZ0RW50cmFuY2U7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5SSUdIVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aFJpZ2h0RW50cmFuY2U7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5VUDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aFVwRW50cmFuY2U7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5ET1dOOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoRG93bkVudHJhbmNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSb29tV2VpZ2h0KGZhY2luZzogRmFjaW5nKTogbnVtYmVyIHtcbiAgICAgICAgc3dpdGNoIChmYWNpbmcpIHtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkxFRlQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhMZWZ0RW50cmFuY2VXZWlnaHQ7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5SSUdIVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aFJpZ2h0RW50cmFuY2VXZWlnaHQ7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5VUDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aFVwRW50cmFuY2VXZWlnaHQ7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5ET1dOOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoRG93bkVudHJhbmNlV2VpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb3B5Um9vbShvbGQ6IFJvb21UZW1wbGF0ZSwgcG9zWDogbnVtYmVyLCBwb3NZOiBudW1iZXIpOiBSb29tIHtcbiAgICAgICAgbGV0IHJvb20gPSBuZXcgUm9vbSgpO1xuICAgICAgICByb29tLnRvcExlZnQgPSBuZXcgVmVjMihwb3NYLCBwb3NZKTtcbiAgICAgICAgcm9vbS5ib3R0b21SaWdodCA9IG5ldyBWZWMyKHBvc1ggKyBvbGQud2lkdGggLSAxLCBwb3NZICsgb2xkLmhlaWdodCAtIDEpO1xuICAgICAgICByb29tLnRvcExheWVyID0gWy4uLm9sZC50b3BMYXllcl07XG4gICAgICAgIHJvb20uYm90dG9tTGF5ZXIgPSBbLi4ub2xkLmJvdHRvbUxheWVyXTtcbiAgICAgICAgcm9vbS5lbmVtaWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIGlmIChvbGQuc3ByaXRlcykge1xuICAgICAgICAgICAgZm9yIChsZXQgc3ByaXRlIG9mIG9sZC5zcHJpdGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNwcml0ZS50eXBlID09PSAncGxheWVyJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsYXllci54ID0gc3ByaXRlLng7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGxheWVyLnkgPSBzcHJpdGUueTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmdlbi5yYW5kb20oKSA8PSBzcHJpdGUucG9zc2liaWxpdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0bXAgPSBuZXcgRW5lbXkoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRtcC50eXBlID0gc3ByaXRlLnR5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB0bXAucG9zaXRpb24gPSBuZXcgVmVjMihwb3NYICsgc3ByaXRlLngsIHBvc1kgKyBzcHJpdGUueSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByb29tLmVuZW1pZXMucHVzaCh0bXApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChwb3NYIDwgdGhpcy5taW5YKVxuICAgICAgICAgICAgdGhpcy5taW5YID0gcG9zWDtcbiAgICAgICAgaWYgKHBvc1kgPCB0aGlzLm1pblkpXG4gICAgICAgICAgICB0aGlzLm1pblkgPSBwb3NZO1xuICAgICAgICBpZiAocG9zWCArIG9sZC53aWR0aCAtIDEgPiB0aGlzLm1heFgpXG4gICAgICAgICAgICB0aGlzLm1heFggPSBwb3NYICsgb2xkLndpZHRoIC0gMTtcbiAgICAgICAgaWYgKHBvc1kgKyBvbGQuaGVpZ2h0IC0gMSA+IHRoaXMubWF4WSlcbiAgICAgICAgICAgIHRoaXMubWF4WSA9IHBvc1kgKyBvbGQuaGVpZ2h0IC0gMTtcbiAgICAgICAgcmV0dXJuIHJvb207XG4gICAgfVxufVxuXG5jbGFzcyBSb29tIHtcbiAgICB0b3BMZWZ0OiBWZWMyO1xuICAgIGJvdHRvbVJpZ2h0OiBWZWMyO1xuICAgIHRvcExheWVyOiBBcnJheTxudW1iZXI+O1xuICAgIGJvdHRvbUxheWVyOiBBcnJheTxudW1iZXI+O1xuICAgIGVuZW1pZXM6IEFycmF5PEVuZW15PlxufVxuXG5leHBvcnQgY2xhc3MgRW5lbXkge1xuICAgIHR5cGU6IFN0cmluZztcbiAgICBwb3NpdGlvbjogVmVjMjtcbn1cblxuZW51bSBGYWNpbmcge1xuICAgIExFRlQgPSBcImxlZnRcIixcbiAgICBSSUdIVCA9IFwicmlnaHRcIixcbiAgICBVUCA9IFwidXBcIixcbiAgICBET1dOID0gXCJkb3duXCJcbn0iLCJleHBvcnQgZW51bSBQbGF5ZXJfRXZlbnRzIHtcbiAgICBQTEFZRVJfTU9WRSA9IFwiUGxheWVyTW92ZVwiLFxuICAgIFBMQVlFUl9KVU1QID0gXCJQbGF5ZXJKdW1wXCIsXG4gICAgUExBWUVSX0FUVEFDSyA9IFwiUGxheWVyQXR0YWNrXCIsXG4gICAgUExBWUVSX0RBU0ggPSBcIlBsYXllckRhc2hcIixcbiAgICBQTEFZRVJfSEVBTCA9IFwiUGxheWVySGVhbFwiLFxuICAgIExFVkVMX1NUQVJUID0gXCJMZXZlbFN0YXJ0XCIsXG4gICAgTEVWRUxfRU5EID0gXCJMZXZlbEVuZFwiLFxuICAgIFBMQVlFUl9LSUxMRUQgPSBcIlBsYXllcktpbGxlZFwiLFxuICAgIEVORU1ZX0tJTExFRCA9IFwiRW5lbXlLaWxsZWRcIixcbiAgICBQTEFZRVJfSElUX0VORU1ZID0gXCJQbGF5ZXJIaXRFbmVteVwiLFxuICAgIEJPU1NfS0lMTEVEID0gXCJCb3NzS2lsbGVkXCIsXG59XG5leHBvcnQgZW51bSBEYW1hZ2VfVHlwZSB7XG4gICAgTk9STUFMX0RBTUFHRSA9IFwiTm9ybWFsRGFtYWdlXCIsXG4gICAgRU5WSVJPTk1FTlRfREFNQUdFID0gXCJFbnZpcm9ubWVudERhbWFnZVwiLFxuICAgIERPVF9EQU1BR0UgPSBcIkRPVERhbWFnZVwiLFxufVxuXG5leHBvcnQgZW51bSBTdGF0dXNlcyB7XG4gICAgSU5fUkFOR0UgPSBcIklOX1JBTkdFXCIsXG4gICAgTE9XX0hFQUxUSCA9IFwiTE9XX0hFQUxUSFwiLFxuICAgIENBTl9SRVRSRUFUID0gXCJDQU5fUkVUUkVBVFwiLFxuICAgIFJFQUNIRURfR09BTCA9IFwiR09BTFwiXG59Il19
|