555 lines
71 KiB
JavaScript
555 lines
71 KiB
JavaScript
const nope = (x) => { };
|
|
const getSize = (value, options) => value * options.pixelSize;
|
|
const drawBorderedRect = (position, context, options) => {
|
|
const borderWidth = options.borderWidth;
|
|
if (!borderWidth) {
|
|
return;
|
|
}
|
|
const actualLineWidth = getSize(borderWidth, options);
|
|
context.lineWidth = actualLineWidth;
|
|
context.strokeStyle = 'white';
|
|
context.strokeRect(getSize(position.x, options) - Math.round(actualLineWidth / 2), getSize(position.y, options) - Math.round(actualLineWidth / 2), getSize(position.width, options) + actualLineWidth, getSize(position.height, options) + actualLineWidth);
|
|
};
|
|
class TetrissimoLevel {
|
|
constructor(order, speed) {
|
|
this.order = order;
|
|
this.movementsPerSecond = speed;
|
|
}
|
|
}
|
|
TetrissimoLevel.level1 = new TetrissimoLevel(1, 0.5);
|
|
TetrissimoLevel.level2 = new TetrissimoLevel(2, 0.75);
|
|
TetrissimoLevel.level3 = new TetrissimoLevel(2, 1);
|
|
TetrissimoLevel.level4 = new TetrissimoLevel(2, 1.5);
|
|
TetrissimoLevel.level5 = new TetrissimoLevel(2, 2);
|
|
TetrissimoLevel.level6 = new TetrissimoLevel(2, 3);
|
|
TetrissimoLevel.level7 = new TetrissimoLevel(2, 4);
|
|
TetrissimoLevel.level8 = new TetrissimoLevel(2, 6);
|
|
TetrissimoLevel.level9 = new TetrissimoLevel(2, 8);
|
|
TetrissimoLevel.level10 = new TetrissimoLevel(2, 10);
|
|
class TetrissimoGame {
|
|
constructor(ui) {
|
|
this.startedAt = null;
|
|
this.pausedAt = null;
|
|
this.finishedAt = null;
|
|
this.state = 'not-started';
|
|
this.fps = 60;
|
|
this.lastFrameTimes = [];
|
|
this.pieces = [];
|
|
this.currentLevel = TetrissimoLevel.level1;
|
|
this.msUntilNextTick = 0;
|
|
this.lastTick = new Date();
|
|
this.lastUpdate = new Date();
|
|
this.ui = ui;
|
|
}
|
|
getState() {
|
|
return this.state;
|
|
}
|
|
setTargetFps(fps) {
|
|
this.fps = fps;
|
|
}
|
|
setLevel(level) {
|
|
this.currentLevel = level;
|
|
}
|
|
getCurrentFps() {
|
|
switch (this.state) {
|
|
case 'running':
|
|
if (this.lastFrameTimes.length <= 1) {
|
|
return 0;
|
|
}
|
|
const firstFrame = this.lastFrameTimes[0];
|
|
const lastFrame = this.lastFrameTimes[this.lastFrameTimes.length - 1];
|
|
const elapsedMs = lastFrame - firstFrame;
|
|
const avgMsPerFrame = (elapsedMs / this.lastFrameTimes.length);
|
|
return 1000 / avgMsPerFrame;
|
|
case 'paused':
|
|
case 'not-started':
|
|
case 'finished':
|
|
return 0;
|
|
default:
|
|
nope(this.state);
|
|
throw new Error(`Invalid game state "${this.state}"`);
|
|
}
|
|
}
|
|
performPieceAction(action) {
|
|
if (this.state !== 'running') {
|
|
return;
|
|
}
|
|
const piece = this.pieces.filter(piece => piece.state === 'in-play')[0];
|
|
if (!piece) {
|
|
// nothing to do, no pieces in play
|
|
return;
|
|
}
|
|
const movementIncrement = 1;
|
|
switch (action.type) {
|
|
case 'moveLeft':
|
|
this.moveIfValid(piece, -movementIncrement, 0);
|
|
break;
|
|
case 'moveRight':
|
|
this.moveIfValid(piece, movementIncrement, 0);
|
|
break;
|
|
case 'moveDown':
|
|
if (!this.moveIfValid(piece, 0, movementIncrement)) {
|
|
// make fixed to bottom of play area
|
|
piece.setFixed();
|
|
}
|
|
break;
|
|
case 'rotateLeft':
|
|
// TODO ensure it's a valid move
|
|
piece.rotateLeft();
|
|
break;
|
|
case 'rotateRight':
|
|
piece.rotateRight();
|
|
break;
|
|
default:
|
|
nope(action.type);
|
|
throw new Error(`invalid action "${action.type}"`);
|
|
}
|
|
}
|
|
start() {
|
|
this.pausedAt = null;
|
|
switch (this.state) {
|
|
case 'running':
|
|
// no-op
|
|
break;
|
|
case 'paused':
|
|
case 'not-started':
|
|
this.lastTick = new Date();
|
|
this.lastUpdate = new Date();
|
|
this.startedAt = new Date();
|
|
this.state = 'running';
|
|
this.update();
|
|
break;
|
|
case 'finished':
|
|
throw new Error('Cannot start a finished game');
|
|
default:
|
|
nope(this.state);
|
|
throw new Error(`Invalid game state "${this.state}"`);
|
|
}
|
|
}
|
|
pause() {
|
|
switch (this.state) {
|
|
case 'running':
|
|
case 'paused':
|
|
this.pausedAt = new Date();
|
|
this.state = 'paused';
|
|
this.lastFrameTimes = [];
|
|
break;
|
|
case 'not-started':
|
|
case 'finished':
|
|
throw new Error(`Cannot pause game while it's in state "${this.state}"`);
|
|
default:
|
|
nope(this.state);
|
|
throw new Error(`Invalid game state "${this.state}"`);
|
|
}
|
|
}
|
|
update() {
|
|
const tickStart = Date.now();
|
|
this.lastFrameTimes.push(tickStart);
|
|
if (this.lastFrameTimes.length > 20) {
|
|
this.lastFrameTimes.shift();
|
|
}
|
|
switch (this.state) {
|
|
case 'running':
|
|
this.performUpdate();
|
|
break;
|
|
case 'paused':
|
|
case 'not-started':
|
|
case 'finished':
|
|
throw new Error(`Cannot advance game while in state "${this.state}"`);
|
|
default:
|
|
nope(this.state);
|
|
throw new Error(`Invalid game state "${this.state}"`);
|
|
}
|
|
const elapsed = Date.now() - tickStart;
|
|
const nextTickTimeout = Math.max(0, (1000 / this.fps) - elapsed);
|
|
setTimeout(() => {
|
|
switch (this.state) {
|
|
case 'running':
|
|
this.update();
|
|
break;
|
|
case 'paused':
|
|
case 'not-started':
|
|
case 'finished':
|
|
break;
|
|
default:
|
|
nope(this.state);
|
|
throw new Error(`Invalid game state "${this.state}"`);
|
|
}
|
|
}, nextTickTimeout);
|
|
}
|
|
performUpdate() {
|
|
const sinceLastUpdate = Date.now() - this.lastUpdate.getTime();
|
|
this.msUntilNextTick -= sinceLastUpdate;
|
|
this.lastUpdate = new Date();
|
|
if (this.msUntilNextTick <= 0) {
|
|
this.tick();
|
|
}
|
|
// detect collision
|
|
// is every column filled? remove column
|
|
// is every row filled? end game
|
|
ui.update();
|
|
}
|
|
moveIfValid(piece, xDelta, yDelta) {
|
|
const translation = {
|
|
xDelta,
|
|
yDelta,
|
|
};
|
|
if (this.ui.canMovePiece(piece, translation)) {
|
|
piece.move(translation);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
;
|
|
tick() {
|
|
const inPlayPieces = this.pieces.filter(piece => piece.state === 'in-play');
|
|
if (!inPlayPieces.length) {
|
|
const newPiece = TetrissimoPiece.T.clone();
|
|
newPiece.state = 'in-play';
|
|
this.pieces.push(newPiece);
|
|
this.ui.addPiece(newPiece);
|
|
}
|
|
else {
|
|
inPlayPieces.forEach((piece) => {
|
|
if (!this.moveIfValid(piece, 0, 1)) {
|
|
piece.setFixed();
|
|
}
|
|
});
|
|
}
|
|
this.msUntilNextTick = Math.round(1000 / this.currentLevel.movementsPerSecond);
|
|
this.lastTick = new Date();
|
|
}
|
|
}
|
|
class TetrissimoUI {
|
|
constructor(canvas, playArea,
|
|
// nextBox: TetrissimoNextBox,
|
|
hud) {
|
|
this.pieces = [];
|
|
this.playArea = playArea;
|
|
// this.nextBox = nextBox;
|
|
this.hud = hud;
|
|
const context = canvas.getContext('2d');
|
|
if (!context) {
|
|
throw new Error('failed to get 2d context');
|
|
}
|
|
this.options = {
|
|
borderWidth: 1,
|
|
canvas: canvas,
|
|
context,
|
|
gridLines: 4,
|
|
hud: {
|
|
width: 32,
|
|
height: 12,
|
|
},
|
|
playArea: {
|
|
width: 68,
|
|
height: 128,
|
|
},
|
|
padding: 2,
|
|
pixelSize: 4,
|
|
};
|
|
}
|
|
setOptions(options) {
|
|
Object.keys(options).forEach((key) => {
|
|
this.options[key] = options[key];
|
|
});
|
|
}
|
|
addPiece(piece) {
|
|
this.pieces.push(piece);
|
|
}
|
|
getPiecePosition(piece) {
|
|
const origin = this.getPieceOrigin(piece);
|
|
const offset = piece.getOffset();
|
|
return {
|
|
x: origin.x + offset.x,
|
|
y: origin.y + offset.y,
|
|
};
|
|
}
|
|
canMovePiece(piece, delta) {
|
|
// check each block in layout's edge to see if it's in a valid area?s
|
|
const layout = piece.getLayout();
|
|
const position = this.getPiecePosition(piece);
|
|
for (let i = 0; i < layout.length; i++) {
|
|
const blockTopEdge = position.y + (i * TetrissimoPiece.blockLength) + (delta.yDelta * TetrissimoPiece.blockLength);
|
|
for (let j = 0; j < layout[i].length; j++) {
|
|
if (layout[i][j] === 0) {
|
|
continue;
|
|
}
|
|
const blockLeftEdge = position.x + (j * TetrissimoPiece.blockLength) + (delta.xDelta * TetrissimoPiece.blockLength);
|
|
const isCollision = this.hasCollision({
|
|
x: blockLeftEdge,
|
|
y: blockTopEdge,
|
|
width: TetrissimoPiece.blockLength,
|
|
height: TetrissimoPiece.blockLength,
|
|
});
|
|
if (isCollision) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
hasCollision(rect) {
|
|
const playAreaLeftEdge = this.options.padding;
|
|
const playAreaRightEdge = playAreaLeftEdge + this.options.playArea.width;
|
|
const playAreaTopEdge = this.options.padding;
|
|
const playAreaBottomEdge = playAreaTopEdge + this.options.playArea.height;
|
|
const leftEdge = rect.x;
|
|
const rightEdge = rect.x + rect.width;
|
|
const topEdge = rect.y;
|
|
const bottomEdge = rect.y + rect.height;
|
|
const isInPlayArea = leftEdge >= playAreaLeftEdge &&
|
|
rightEdge <= playAreaRightEdge &&
|
|
bottomEdge <= playAreaBottomEdge &&
|
|
topEdge >= playAreaTopEdge;
|
|
if (!isInPlayArea) {
|
|
return true;
|
|
}
|
|
const fixedPieces = this.pieces.filter(piece => piece.state === 'fixed');
|
|
for (const piece of fixedPieces) {
|
|
const position = this.getPiecePosition(piece);
|
|
const layout = piece.getLayout();
|
|
for (let i = 0; i < layout.length; i++) {
|
|
const blockTopEdge = position.y + (i * TetrissimoPiece.blockLength);
|
|
const blockBottomEdge = blockTopEdge + TetrissimoPiece.blockLength;
|
|
for (let j = 0; j < layout[i].length; j++) {
|
|
if (layout[i][j] === 0) {
|
|
continue;
|
|
}
|
|
const blockLeftEdge = position.x + (j * TetrissimoPiece.blockLength);
|
|
const blockRightEdge = blockLeftEdge + TetrissimoPiece.blockLength;
|
|
const isCollision = leftEdge >= blockLeftEdge &&
|
|
rightEdge <= blockRightEdge &&
|
|
bottomEdge <= blockBottomEdge &&
|
|
topEdge >= blockTopEdge;
|
|
if (isCollision) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
update() {
|
|
const options = this.options;
|
|
const context = this.options.context;
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
// fill background
|
|
context.fillStyle = 'rgb(224,158,107)';
|
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
// draw some grid lines
|
|
if (typeof (options.gridLines) === 'number') {
|
|
context.strokeStyle = 'rgba(255, 255, 255, 0.25)';
|
|
context.lineWidth = 1;
|
|
const increment = options.pixelSize * options.gridLines;
|
|
for (let i = 0; i < options.canvas.width; i += increment) {
|
|
// draw vertical line
|
|
context.beginPath();
|
|
context.moveTo(i, 0);
|
|
context.lineTo(i, options.canvas.height);
|
|
context.stroke();
|
|
}
|
|
for (let i = 0; i < options.canvas.height; i += increment) {
|
|
// draw horizontal lines
|
|
context.beginPath();
|
|
context.moveTo(0, i);
|
|
context.lineTo(options.canvas.width, i);
|
|
context.stroke();
|
|
}
|
|
}
|
|
const totalWidth = Math.floor(canvas.width / options.pixelSize);
|
|
const padding = options.padding;
|
|
// draw HUD in top right corner
|
|
this.hud.render(context, Object.assign(Object.assign({}, options), { x: totalWidth - padding - options.hud.width, y: padding }));
|
|
// draw play area
|
|
this.playArea.render(context, Object.assign(Object.assign({}, options), { x: padding, y: padding }));
|
|
this.pieces.forEach((piece, i) => {
|
|
piece.render(context, Object.assign(Object.assign({}, options), this.getPieceOrigin(piece)));
|
|
});
|
|
}
|
|
getPieceOrigin(piece) {
|
|
const length = TetrissimoPiece.blockLength;
|
|
// TODO rotation will cause problems, need a "PieceDefinition" or something with a static layout
|
|
let translateX = Math.floor((piece.getBlockWidth() * length) / 2);
|
|
// we can only perform movements in multiples of the blockLength, so we must clamp it
|
|
// to ensure it's not offset
|
|
translateX -= (translateX % length);
|
|
const padding = this.options.padding;
|
|
return {
|
|
x: padding + Math.round(this.options.playArea.width / 2) - translateX,
|
|
y: padding,
|
|
};
|
|
}
|
|
}
|
|
class TetrissimoNextBox {
|
|
render(context, options) {
|
|
}
|
|
}
|
|
class TetrissimoHUD {
|
|
render(context, options) {
|
|
const position = {
|
|
x: options.x,
|
|
y: options.y,
|
|
width: options.hud.width,
|
|
height: options.hud.height,
|
|
};
|
|
drawBorderedRect(position, context, options);
|
|
}
|
|
}
|
|
class TetrissimoPlayArea {
|
|
render(context, options) {
|
|
const position = {
|
|
x: options.x,
|
|
y: options.y,
|
|
width: options.playArea.width,
|
|
height: options.playArea.height,
|
|
};
|
|
drawBorderedRect(position, context, options);
|
|
}
|
|
}
|
|
class TetrissimoPiece {
|
|
constructor(name, layout, color) {
|
|
this.offset = { x: 0, y: 0 };
|
|
this.state = 'in-play';
|
|
this.name = name;
|
|
this.originalLayout = layout.map(row => row.concat([]));
|
|
this.layout = layout.concat([]);
|
|
this.color = color;
|
|
}
|
|
getOffset() {
|
|
return this.offset;
|
|
}
|
|
getLayout() {
|
|
return this.layout;
|
|
}
|
|
move(translation) {
|
|
if (this.state !== 'in-play') {
|
|
return;
|
|
}
|
|
this.offset.x += (translation.xDelta * TetrissimoPiece.blockLength);
|
|
this.offset.y += (translation.yDelta * TetrissimoPiece.blockLength);
|
|
}
|
|
rotateLeft() {
|
|
if (this.state !== 'in-play') {
|
|
return;
|
|
}
|
|
// clockwise turn
|
|
const newLayout = [];
|
|
for (let i = 0; i < this.layout.length; i++) {
|
|
const col = this.layout.length - 1 - i;
|
|
for (let j = 0; j < this.layout[i].length; j++) {
|
|
const row = j;
|
|
if (!newLayout[row]) {
|
|
newLayout[row] = [];
|
|
}
|
|
newLayout[row][col] = this.layout[i][j];
|
|
}
|
|
}
|
|
this.layout = newLayout;
|
|
}
|
|
rotateRight() {
|
|
if (this.state !== 'in-play') {
|
|
return;
|
|
}
|
|
const newLayout = [];
|
|
for (let i = 0; i < this.layout.length; i++) {
|
|
const col = i;
|
|
for (let j = 0; j < this.layout[i].length; j++) {
|
|
const row = this.layout[i].length - 1 - j;
|
|
if (!newLayout[row]) {
|
|
newLayout[row] = [];
|
|
}
|
|
newLayout[row][col] = this.layout[i][j];
|
|
}
|
|
}
|
|
this.layout = newLayout;
|
|
}
|
|
setFixed() {
|
|
this.state = 'fixed';
|
|
}
|
|
getBlockWidth() {
|
|
return this.layout
|
|
.map(arr => arr.filter(value => value === 1).length)
|
|
.reduce((max, len) => Math.max(max, len), 0);
|
|
}
|
|
getBlockHeight() {
|
|
const cols = [];
|
|
for (let i = 0; i < this.layout.length; i++) {
|
|
for (let j = 0; j < this.layout[i].length; j++) {
|
|
if (!cols[j]) {
|
|
cols[j] = [];
|
|
}
|
|
cols[j].push(this.layout[i][j]);
|
|
}
|
|
}
|
|
return cols
|
|
.map(arr => arr.filter(value => value === 1).length)
|
|
.reduce((max, len) => Math.max(max, len), 0);
|
|
}
|
|
clone() {
|
|
return new TetrissimoPiece(this.name, this.layout, this.color);
|
|
}
|
|
render(context, options) {
|
|
this.layout.forEach((columns, rowNum) => {
|
|
columns.forEach((value, colNum) => {
|
|
switch (value) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
context.fillStyle = this.color;
|
|
const length = TetrissimoPiece.blockLength;
|
|
const offsetX = this.offset.x;
|
|
const offsetY = this.offset.y;
|
|
const x = options.x + offsetX + (colNum * length);
|
|
const y = options.y + offsetY + (rowNum * length);
|
|
const actualLength = getSize(length, options);
|
|
context.fillRect(getSize(x, options), getSize(y, options), actualLength, actualLength);
|
|
break;
|
|
default:
|
|
nope(value);
|
|
throw new Error(`Invalid piece cell value "${value}"`);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
TetrissimoPiece.blockLength = 4;
|
|
TetrissimoPiece.J = new TetrissimoPiece('J', [
|
|
[0, 1],
|
|
[0, 1],
|
|
[1, 1],
|
|
], 'black');
|
|
TetrissimoPiece.S = new TetrissimoPiece('S', [
|
|
[0, 1, 1],
|
|
[1, 1, 0],
|
|
], 'green');
|
|
TetrissimoPiece.T = new TetrissimoPiece('T', [
|
|
[1, 1, 1],
|
|
[0, 1, 0],
|
|
], 'blue');
|
|
TetrissimoPiece.Z = new TetrissimoPiece('Z', [
|
|
[1, 1, 0,],
|
|
[0, 1, 1,],
|
|
], 'yellow');
|
|
TetrissimoPiece.I = new TetrissimoPiece('I', [
|
|
[1, 1, 1, 1],
|
|
], 'magenta');
|
|
TetrissimoPiece.L = new TetrissimoPiece('L', [
|
|
[1],
|
|
[1],
|
|
[1, 1],
|
|
], 'cyan');
|
|
TetrissimoPiece.O = new TetrissimoPiece('O', [
|
|
[1, 1],
|
|
[1, 1],
|
|
], 'red');
|
|
// ---------------------------------------------
|
|
const hud = new TetrissimoHUD();
|
|
const playArea = new TetrissimoPlayArea();
|
|
const canvas = document.getElementsByTagName('canvas')[0];
|
|
if (!canvas) {
|
|
throw new Error('no canvas');
|
|
}
|
|
const ui = new TetrissimoUI(canvas, playArea, hud);
|
|
const game = new TetrissimoGame(ui);
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV0cmlzc2ltby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRldHJpc3NpbW8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFRLEVBQVEsRUFBRSxHQUFFLENBQUMsQ0FBQztBQXFEcEMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxLQUFhLEVBQUUsT0FBMkMsRUFBVSxFQUFFLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7QUFFbEgsTUFBTSxnQkFBZ0IsR0FBRyxDQUN4QixRQUE0QyxFQUM1QyxPQUFpQyxFQUNqQyxPQUErQixFQUN4QixFQUFFO0lBQ1QsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQztJQUN4QyxJQUFJLENBQUMsV0FBVyxFQUFFO1FBQ2pCLE9BQU87S0FDUDtJQUVELE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEQsT0FBTyxDQUFDLFNBQVMsR0FBRyxlQUFlLENBQUM7SUFDcEMsT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUM7SUFDOUIsT0FBTyxDQUFDLFVBQVUsQ0FDakIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDLEVBQzlELE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxFQUM5RCxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRyxlQUFlLEVBQ2xELE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxHQUFHLGVBQWUsQ0FDbkQsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sZUFBZTtJQWVwQixZQUFtQixLQUFhLEVB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LEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzVDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUMvQyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUM7Z0JBQ2QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRTtvQkFDcEIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztpQkFDcEI7Z0JBQ0QsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDeEM7U0FDRDtRQUVELElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO0lBQ3pCLENBQUM7SUFFTSxXQUFXO1FBQ2pCLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFDN0IsT0FBTztTQUNQO1FBRUQsTUFBTSxTQUFTLEdBQWdCLEVBQUUsQ0FBQztRQUNsQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDNUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUMvQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0s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QU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDbkQsTUFBTSxJQUFJLEdBQUcsSUFBSSxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJ0eXBlIEdhbWVTdGF0ZSA9ICdydW5uaW5nJyB8ICdwYXVzZWQnIHwgJ25vdC1zdGFydGVkJyB8ICdmaW5pc2hlZCc7XG5cbmNvbnN0IG5vcGUgPSAoeDogbmV2ZXIpOiB2b2lkID0+IHt9O1xuXG50eXBlIFBpZWNlQ2VsbCA9IDAgfCAxO1xudHlwZSBQaWVjZUxheW91dCA9IFBpZWNlQ2VsbFtdW107XG5cbmludGVyZmFjZSBVSUVsZW1lbnQge1xuXHRyZW5kZXIoY29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELCBvcHRpb25zOiBVSUVsZW1lbnRSZW5kZXJPcHRpb25zKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIERpbWVuc2lvbnMge1xuXHR3aWR0aDogbnVtYmVyO1xuXHRoZWlnaHQ6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIEdsb2JhbFVJT3B0aW9ucyB7XG5cdHBpeGVsU2l6ZTogbnVtYmVyO1xuXHRwYWRkaW5nOiBudW1iZXI7XG5cdGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQ7XG5cdGNvbnRleHQ6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblx0Z3JpZExpbmVzOiBmYWxzZSB8IG51bWJlcjtcblx0Ym9yZGVyV2lkdGg6IG51bWJlcjtcblx0aHVkOiBEaW1lbnNpb25zO1xuXHRwbGF5QXJlYTogRGltZW5zaW9ucztcbn1cblxuaW50ZXJmYWNlIFVJRWxlbWVudFJlbmRlck9wdGlvbnMgZXh0ZW5kcyBHbG9iYWxVSU9wdGlvbnMge1xuXHR4OiBudW1iZXI7XG5cdHk6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFBpZWNlVHJhbnNsYXRpb24ge1xuXHR4RGVsdGE6IG51bWJlcjtcblx0eURlbHRhOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBUZXRyaXNzaW1vQ29vcmRpbmF0ZXMge1xuXHR4OiBudW1iZXI7XG5cdHk6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFJlY3RhbmdsZUNvb3JkaW5hdGVzIGV4dGVuZHMgVGV0cmlzc2ltb0Nvb3JkaW5hdGVzLCBEaW1lbnNpb25zIHt9XG5cbnR5cGUgUGllY2VBY3Rpb25UeXBlID1cblx0J21vdmVMZWZ0JyB8XG5cdCdtb3ZlUmlnaHQnIHxcblx0J21vdmVEb3duJyB8XG5cdCdyb3RhdGVMZWZ0JyB8XG5cdCdyb3RhdGVSaWdodCc7XG5cbmludGVyZmFjZSBQaWVjZUFjdGlvbiB7XG5cdHR5cGU6IFBpZWNlQWN0aW9uVHlwZTtcbn1cblxuY29uc3QgZ2V0U2l6ZSA9ICh2YWx1ZTogbnVtYmVyLCBvcHRpb25zOiBQaWNrPEdsb2JhbFVJT3B0aW9ucywgJ3BpeGVsU2l6ZSc+KTogbnVtYmVyID0+IHZhbHVlICogb3B0aW9ucy5waXhlbFNpemU7XG5cbmNvbnN0IGRyYXdCb3JkZXJlZFJlY3QgPSAoXG5cdHBvc2l0aW9uOiBEaW1lbnNpb25zICYgVGV0cmlzc2ltb0Nvb3JkaW5hdGVzLFxuXHRjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQsXG5cdG9wdGlvbnM6IFVJRWxlbWVudFJlbmRlck9wdGlvbnMsXG4pOiB2b2lkID0+IHtcblx0Y29uc3QgYm9yZGVyV2lkdGggPSBvcHRpb25zLmJvcmRlcldpZHRoO1xuXHRpZiAoIWJvcmRlcldpZHRoKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Y29uc3QgYWN0dWFsTGluZVdpZHRoID0gZ2V0U2l6ZShib3JkZXJXaWR0aCwgb3B0aW9ucyk7XG5cdGNvbnRleHQubGluZVdpZHRoID0gYWN0dWFsTGluZVdpZHRoO1xuXHRjb250ZXh0LnN0cm9rZVN0eWxlID0gJ3doaXRlJztcblx0Y29udGV4dC5zdHJva2VSZWN0KFxuXHRcdGdldFNpemUocG9zaXRpb24ueCwgb3B0aW9ucykgLSBNYXRoLnJvdW5kKGFjdHVhbExpbmVXaWR0aCAvIDIpLFxuXHRcdGdldFNpemUocG9zaXRpb24ueSwgb3B0aW9ucykgLSBNYXRoLnJvdW5kKGFjdHVhbExpbmVXaWR0aCAvIDIpLFxuXHRcdGdldFNpemUocG9zaXRpb24ud2lkdGgsIG9wdGlvbnMpICsgYWN0dWFsTGluZVdpZHRoLFxuXHRcdGdldFNpemUocG9zaXRpb24uaGVpZ2h0LCBvcHRpb25zKSArIGFjdHVhbExpbmVXaWR0aCxcblx0KTtcbn07XG5cbmNsYXNzIFRldHJpc3NpbW9MZXZlbCB7XG5cdHB1YmxpYyByZWFkb25seSBvcmRlcjogbnVtYmVyO1xuXHRwdWJsaWMgcmVhZG9ubHkgbW92ZW1lbnRzUGVyU2Vjb25kOiBudW1iZXI7XG5cblx0cHVibGljIHN0YXRpYyByZWFkb25seSBsZXZlbDEgPSBuZXcgVGV0cmlzc2ltb0xldmVsKDEsIDAuNSk7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgbGV2ZWwyID0gbmV3IFRldHJpc3NpbW9MZXZlbCgyLCAwLjc1KTtcblx0cHVibGljIHN0YXRpYyByZWFkb25seSBsZXZlbDMgPSBuZXcgVGV0cmlzc2ltb0xldmVsKDIsIDEpO1xuXHRwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGxldmVsNCA9IG5ldyBUZXRyaXNzaW1vTGV2ZWwoMiwgMS41KTtcblx0cHVibGljIHN0YXRpYyByZWFkb25seSBsZXZlbDUgPSBuZXcgVGV0cmlzc2ltb0xldmVsKDIsIDIpO1xuXHRwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGxldmVsNiA9IG5ldyBUZXRyaXNzaW1vTGV2ZWwoMiwgMyk7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgbGV2ZWw3ID0gbmV3IFRldHJpc3NpbW9MZXZlbCgyLCA0KTtcblx0cHVibGljIHN0YXRpYyByZWFkb25seSBsZXZlbDggPSBuZXcgVGV0cmlzc2ltb0xldmVsKDIsIDYpO1xuXHRwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGxldmVsOSA9IG5ldyBUZXRyaXNzaW1vTGV2ZWwoMiwgOCk7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgbGV2ZWwxMCA9IG5ldyBUZXRyaXNzaW1vTGV2ZWwoMiwgMTApO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihvcmRlcjogbnVtYmVyLCBzcGVlZDogbnVtYmVyKSB7XG5cdFx0dGhpcy5vcmRlciA9IG9yZGVyO1xuXHRcdHRoaXMubW92ZW1lbnRzUGVyU2Vjb25kID0gc3BlZWQ7XG5cdH1cbn1cblxuY2xhc3MgVGV0cmlzc2ltb0dhbWUge1xuXHRwcml2YXRlIHN0YXJ0ZWRBdDogRGF0ZSB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHBhdXNlZEF0OiBEYXRlIHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgZmluaXNoZWRBdDogRGF0ZSB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHN0YXRlOiBHYW1lU3RhdGUgPSAnbm90LXN0YXJ0ZWQnO1xuXHRwcml2YXRlIGZwcyA9IDYwO1xuXHRwcml2YXRlIHJlYWRvbmx5IHVpOiBUZXRyaXNzaW1vVUk7XG5cdHByaXZhdGUgbGFzdEZyYW1lVGltZXM6IG51bWJlcltdID0gW107XG5cdHByaXZhdGUgcmVhZG9ubHkgcGllY2VzOiBUZXRyaXNzaW1vUGllY2VbXSA9IFtdO1xuXHRwdWJsaWMgY3VycmVudExldmVsOiBUZXRyaXNzaW1vTGV2ZWwgPSBUZXRyaXNzaW1vTGV2ZWwubGV2ZWwxO1xuXHRwcml2YXRlIG1zVW50aWxOZXh0VGljayA9IDA7XG5cdHByaXZhdGUgbGFzdFRpY2sgPSBuZXcgRGF0ZSgpO1xuXHRwcml2YXRlIGxhc3RVcGRhdGUgPSBuZXcgRGF0ZSgpO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcih1aTogVGV0cmlzc2ltb1VJKSB7XG5cdFx0dGhpcy51aSA9IHVpO1xuXHR9XG5cblx0cHVibGljIGdldFN0YXRlKCk6IEdhbWVTdGF0ZSB7XG5cdFx0cmV0dXJuIHRoaXMuc3RhdGU7XG5cdH1cblxuXHRwdWJsaWMgc2V0VGFyZ2V0RnBzKGZwczogbnVtYmVyKSB7XG5cdFx0dGhpcy5mcHMgPSBmcHM7XG5cdH1cblxuXHRwdWJsaWMgc2V0TGV2ZWwobGV2ZWw6IFRldHJpc3NpbW9MZXZlbCkge1xuXHRcdHRoaXMuY3VycmVudExldmVsID0gbGV2ZWw7XG5cdH1cblxuXHRwdWJsaWMgZ2V0Q3VycmVudEZwcygpOiBudW1iZXIge1xuXHRcdHN3aXRjaCAodGhpcy5zdGF0ZSkge1xuXHRcdFx0Y2FzZSAncnVubmluZyc6XG5cdFx0XHRcdGlmICh0aGlzLmxhc3RGcmFtZVRpbWVzLmxlbmd0aCA8PSAxKSB7XG5cdFx0XHRcdFx0cmV0dXJuIDA7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBmaXJzdEZyYW1lID0gdGhpcy5sYXN0RnJhbWVUaW1lc1swXTtcblx0XHRcdFx0Y29uc3QgbGFzdEZyYW1lID0gdGhpcy5sYXN0RnJhbWVUaW1lc1t0aGlzLmxhc3RGcmFtZVRpbWVzLmxlbmd0aCAtIDFdO1xuXHRcdFx0XHRjb25zdCBlbGFwc2VkTXMgPSBsYXN0RnJhbWUgLSBmaXJzdEZyYW1lO1xuXHRcdFx0XHRjb25zdCBhdmdNc1BlckZyYW1lID0gKGVsYXBzZWRNcyAvIHRoaXMubGFzdEZyYW1lVGltZXMubGVuZ3RoKTtcblx0XHRcdFx0cmV0dXJuIDEwMDAgLyBhdmdNc1BlckZyYW1lO1xuXHRcdFx0Y2FzZSAncGF1c2VkJzpcblx0XHRcdGNhc2UgJ25vdC1zdGFydGVkJzpcblx0XHRcdGNhc2UgJ2ZpbmlzaGVkJzpcblx0XHRcdFx0cmV0dXJuIDA7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRub3BlKHRoaXMuc3RhdGUpO1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZ2FtZSBzdGF0ZSBcIiR7dGhpcy5zdGF0ZX1cImApO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBwZXJmb3JtUGllY2VBY3Rpb24oYWN0aW9uOiBQaWVjZUFjdGlvbikge1xuXHRcdGlmICh0aGlzLnN0YXRlICE9PSAncnVubmluZycpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBwaWVjZSA9IHRoaXMucGllY2VzLmZpbHRlcihwaWVjZSA9PiBwaWVjZS5zdGF0ZSA9PT0gJ2luLXBsYXknKVswXTtcblx0XHRpZiAoIXBpZWNlKSB7XG5cdFx0XHQvLyBub3RoaW5nIHRvIGRvLCBubyBwaWVjZXMgaW4gcGxheVxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IG1vdmVtZW50SW5jcmVtZW50ID0gMTtcblxuXHRcdHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcblx0XHRcdGNhc2UgJ21vdmVMZWZ0Jzpcblx0XHRcdFx0dGhpcy5tb3ZlSWZWYWxpZChwaWVjZSwgLW1vdmVtZW50SW5jcmVtZW50LCAwKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdtb3ZlUmlnaHQnOlxuXHRcdFx0XHR0aGlzLm1vdmVJZlZhbGlkKHBpZWNlLCBtb3ZlbWVudEluY3JlbWVudCwgMCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnbW92ZURvd24nOlxuXHRcdFx0XHRpZiAoIXRoaXMubW92ZUlmVmFsaWQocGllY2UsIDAsIG1vdmVtZW50SW5jcmVtZW50KSkge1xuXHRcdFx0XHRcdC8vIG1ha2UgZml4ZWQgdG8gYm90dG9tIG9mIHBsYXkgYXJlYVxuXHRcdFx0XHRcdHBpZWNlLnNldEZpeGVkKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdyb3RhdGVMZWZ0Jzpcblx0XHRcdFx0Ly8gVE9ETyBlbnN1cmUgaXQncyBhIHZhbGlkIG1vdmVcblx0XHRcdFx0cGllY2Uucm90YXRlTGVmdCgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3JvdGF0ZVJpZ2h0Jzpcblx0XHRcdFx0cGllY2Uucm90YXRlUmlnaHQoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRub3BlKGFjdGlvbi50eXBlKTtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGFjdGlvbiBcIiR7YWN0aW9uLnR5cGV9XCJgKTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgc3RhcnQoKSB7XG5cdFx0dGhpcy5wYXVzZWRBdCA9IG51bGw7XG5cblx0XHRzd2l0Y2ggKHRoaXMuc3RhdGUpIHtcblx0XHRcdGNhc2UgJ3J1bm5pbmcnOlxuXHRcdFx0XHQvLyBuby1vcFxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3BhdXNlZCc6XG5cdFx0XHRjYXNlICdub3Qtc3RhcnRlZCc6XG5cdFx0XHRcdHRoaXMubGFzdFRpY2sgPSBuZXcgRGF0ZSgpO1xuXHRcdFx0XHR0aGlzLmxhc3RVcGRhdGUgPSBuZXcgRGF0ZSgpO1xuXHRcdFx0XHR0aGlzLnN0YXJ0ZWRBdCA9IG5ldyBEYXRlKCk7XG5cdFx0XHRcdHRoaXMuc3RhdGUgPSAncnVubmluZyc7XG5cdFx0XHRcdHRoaXMudXBkYXRlKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnZmluaXNoZWQnOlxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzdGFydCBhIGZpbmlzaGVkIGdhbWUnKTtcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdG5vcGUodGhpcy5zdGF0ZSk7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBnYW1lIHN0YXRlIFwiJHt0aGlzLnN0YXRlfVwiYCk7XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHBhdXNlKCkge1xuXHRcdHN3aXRjaCAodGhpcy5zdGF0ZSkge1xuXHRcdFx0Y2FzZSAncnVubmluZyc6XG5cdFx0XHRjYXNlICdwYXVzZWQnOlxuXHRcdFx0XHR0aGlzLnBhdXNlZEF0ID0gbmV3IERhdGUoKTtcblx0XHRcdFx0dGhpcy5zdGF0ZSA9ICdwYXVzZWQnO1xuXHRcdFx0XHR0aGlzLmxhc3RGcmFtZVRpbWVzID0gW107XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnbm90LXN0YXJ0ZWQnOlxuXHRcdFx0Y2FzZSAnZmluaXNoZWQnOlxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBwYXVzZSBnYW1lIHdoaWxlIGl0J3MgaW4gc3RhdGUgXCIke3RoaXMuc3RhdGV9XCJgKTtcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdG5vcGUodGhpcy5zdGF0ZSk7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBnYW1lIHN0YXRlIFwiJHt0aGlzLnN0YXRlfVwiYCk7XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHVwZGF0ZSgpOiB2b2lkIHtcblx0XHRjb25zdCB0aWNrU3RhcnQgPSBEYXRlLm5vdygpO1xuXHRcdHRoaXMubGFzdEZyYW1lVGltZXMucHVzaCh0aWNrU3RhcnQpO1xuXHRcdGlmICh0aGlzLmxhc3RGcmFtZVRpbWVzLmxlbmd0aCA+IDIwKSB7XG5cdFx0XHR0aGlzLmxhc3RGcmFtZVRpbWVzLnNoaWZ0KCk7XG5cdFx0fVxuXG5cdFx0c3dpdGNoICh0aGlzLnN0YXRlKSB7XG5cdFx0XHRjYXNlICdydW5uaW5nJzpcblx0XHRcdFx0dGhpcy5wZXJmb3JtVXBkYXRlKCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAncGF1c2VkJzpcblx0XHRcdGNhc2UgJ25vdC1zdGFydGVkJzpcblx0XHRcdGNhc2UgJ2ZpbmlzaGVkJzpcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgYWR2YW5jZSBnYW1lIHdoaWxlIGluIHN0YXRlIFwiJHt0aGlzLnN0YXRlfVwiYCk7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRub3BlKHRoaXMuc3RhdGUpO1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZ2FtZSBzdGF0ZSBcIiR7dGhpcy5zdGF0ZX1cImApO1xuXHRcdH1cblxuXHRcdGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gdGlja1N0YXJ0O1xuXHRcdGNvbnN0IG5leHRUaWNrVGltZW91dCA9IE1hdGgubWF4KDAsICgxMDAwIC8gdGhpcy5mcHMpIC0gZWxhcHNlZCk7XG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRzd2l0Y2ggKHRoaXMuc3RhdGUpIHtcblx0XHRcdFx0Y2FzZSAncnVubmluZyc6XG5cdFx0XHRcdFx0dGhpcy51cGRhdGUoKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAncGF1c2VkJzpcblx0XHRcdFx0Y2FzZSAnbm90LXN0YXJ0ZWQnOlxuXHRcdFx0XHRjYXNlICdmaW5pc2hlZCc6XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0bm9wZSh0aGlzLnN0YXRlKTtcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZ2FtZSBzdGF0ZSBcIiR7dGhpcy5zdGF0ZX1cImApO1xuXHRcdFx0fVxuXHRcdH0sIG5leHRUaWNrVGltZW91dCk7XG5cdH1cblxuXHRwcml2YXRlIHBlcmZvcm1VcGRhdGUoKTogdm9pZCB7XG5cdFx0Y29uc3Qgc2luY2VMYXN0VXBkYXRlID0gRGF0ZS5ub3coKSAtIHRoaXMubGFzdFVwZGF0ZS5nZXRUaW1lKCk7XG5cdFx0dGhpcy5tc1VudGlsTmV4dFRpY2sgLT0gc2luY2VMYXN0VXBkYXRlO1xuXHRcdHRoaXMubGFzdFVwZGF0ZSA9IG5ldyBEYXRlKCk7XG5cblx0XHRpZiAodGhpcy5tc1VudGlsTmV4dFRpY2sgPD0gMCkge1xuXHRcdFx0dGhpcy50aWNrKCk7XG5cdFx0fVxuXG5cdFx0Ly8gZGV0ZWN0IGNvbGxpc2lvblxuXHRcdC8vIGlzIGV2ZXJ5IGNvbHVtbiBmaWxsZWQ/IHJlbW92ZSBjb2x1bW5cblx0XHQvLyBpcyBldmVyeSByb3cgZmlsbGVkPyBlbmQgZ2FtZVxuXG5cdFx0dWkudXBkYXRlKCk7XG5cdH1cblxuXHRwcml2YXRlIG1vdmVJZlZhbGlkKHBpZWNlOiBUZXRyaXNzaW1vUGllY2UsIHhEZWx0YTogbnVtYmVyLCB5RGVsdGE6IG51bWJlcik6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IHRyYW5zbGF0aW9uOiBQaWVjZVRyYW5zbGF0aW9uID0ge1xuXHRcdFx0eERlbHRhLFxuXHRcdFx0eURlbHRhLFxuXHRcdH07XG5cdFx0aWYgKHRoaXMudWkuY2FuTW92ZVBpZWNlKHBpZWNlLCB0cmFuc2xhdGlvbikpIHtcblx0XHRcdHBpZWNlLm1vdmUodHJhbnNsYXRpb24pO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xuXG5cdHByaXZhdGUgdGljaygpOiB2b2lkIHtcblx0XHRjb25zdCBpblBsYXlQaWVjZXMgPSB0aGlzLnBpZWNlcy5maWx0ZXIocGllY2UgPT4gcGllY2Uuc3RhdGUgPT09ICdpbi1wbGF5Jyk7XG5cdFx0aWYgKCFpblBsYXlQaWVjZXMubGVuZ3RoKSB7XG5cdFx0XHRjb25zdCBuZXdQaWVjZSA9IFRldHJpc3NpbW9QaWVjZS5ULmNsb25lKCk7XG5cdFx0XHRuZXdQaWVjZS5zdGF0ZSA9ICdpbi1wbGF5Jztcblx0XHRcdHRoaXMucGllY2VzLnB1c2gobmV3UGllY2UpO1xuXHRcdFx0dGhpcy51aS5hZGRQaWVjZShuZXdQaWVjZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGluUGxheVBpZWNlcy5mb3JFYWNoKChwaWVjZSkgPT4ge1xuXHRcdFx0XHRpZiAoIXRoaXMubW92ZUlmVmFsaWQocGllY2UsIDAsIDEpKSB7XG5cdFx0XHRcdFx0cGllY2Uuc2V0Rml4ZWQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5tc1VudGlsTmV4dFRpY2sgPSBNYXRoLnJvdW5kKDEwMDAgLyB0aGlzLmN1cnJlbnRMZXZlbC5tb3ZlbWVudHNQZXJTZWNvbmQpO1xuXHRcdHRoaXMubGFzdFRpY2sgPSBuZXcgRGF0ZSgpO1xuXHR9XG59XG5cbmNsYXNzIFRldHJpc3NpbW9VSSB7XG5cdHB1YmxpYyByZWFkb25seSBwbGF5QXJlYTogVGV0cmlzc2ltb1BsYXlBcmVhO1xuXHRwcml2YXRlIHJlYWRvbmx5IHBpZWNlczogQXJyYXk8UmVhZG9ubHk8VGV0cmlzc2ltb1BpZWNlPj4gPSBbXTtcblx0cHVibGljIHJlYWRvbmx5IG5leHRCb3g6IFRldHJpc3NpbW9OZXh0Qm94O1xuXHRwdWJsaWMgcmVhZG9ubHkgaHVkOiBUZXRyaXNzaW1vSFVEO1xuXHRwdWJsaWMgcmVhZG9ubHkgb3B0aW9uczogR2xvYmFsVUlPcHRpb25zO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LFxuXHRcdHBsYXlBcmVhOiBUZXRyaXNzaW1vUGxheUFyZWEsXG5cdFx0Ly8gbmV4dEJveDogVGV0cmlzc2ltb05leHRCb3gsXG5cdFx0aHVkOiBUZXRyaXNzaW1vSFVELFxuXHQpIHtcblx0XHR0aGlzLnBsYXlBcmVhID0gcGxheUFyZWE7XG5cdFx0Ly8gdGhpcy5uZXh0Qm94ID0gbmV4dEJveDtcblx0XHR0aGlzLmh1ZCA9IGh1ZDtcblxuXHRcdGNvbnN0IGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblx0XHRpZiAoIWNvbnRleHQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignZmFpbGVkIHRvIGdldCAyZCBjb250ZXh0Jyk7XG5cdFx0fVxuXHRcdHRoaXMub3B0aW9ucyA9IHtcblx0XHRcdGJvcmRlcldpZHRoOiAxLFxuXHRcdFx0Y2FudmFzOiBjYW52YXMsXG5cdFx0XHRjb250ZXh0LFxuXHRcdFx0Z3JpZExpbmVzOiA0LFxuXHRcdFx0aHVkOiB7XG5cdFx0XHRcdHdpZHRoOiAzMixcblx0XHRcdFx0aGVpZ2h0OiAxMixcblx0XHRcdH0sXG5cdFx0XHRwbGF5QXJlYToge1xuXHRcdFx0XHR3aWR0aDogNjgsXG5cdFx0XHRcdGhlaWdodDogMTI4LFxuXHRcdFx0fSxcblx0XHRcdHBhZGRpbmc6IDIsXG5cdFx0XHRwaXhlbFNpemU6IDQsXG5cdFx0fTtcblx0fVxuXG5cdHB1YmxpYyBzZXRPcHRpb25zKG9wdGlvbnM6IE9taXQ8R2xvYmFsVUlPcHRpb25zLCAnY2FudmFzJyB8ICdjb250ZXh0Jz4pIHtcblx0XHRPYmplY3Qua2V5cyhvcHRpb25zKS5mb3JFYWNoKChrZXkpID0+IHtcblx0XHRcdHRoaXMub3B0aW9uc1trZXldID0gb3B0aW9uc1trZXldO1xuXHRcdH0pO1xuXHR9XG5cblx0cHVibGljIGFkZFBpZWNlKHBpZWNlOiBUZXRyaXNzaW1vUGllY2UpIHtcblx0XHR0aGlzLnBpZWNlcy5wdXNoKHBpZWNlKTtcblx0fVxuXG5cdHByaXZhdGUgZ2V0UGllY2VQb3NpdGlvbihwaWVjZTogUmVhZG9ubHk8VGV0cmlzc2ltb1BpZWNlPik6IFRldHJpc3NpbW9Db29yZGluYXRlcyB7XG5cdFx0Y29uc3Qgb3JpZ2luID0gdGhpcy5nZXRQaWVjZU9yaWdpbihwaWVjZSk7XG5cdFx0Y29uc3Qgb2Zmc2V0ID0gcGllY2UuZ2V0T2Zmc2V0KCk7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0eDogb3JpZ2luLnggKyBvZmZzZXQueCxcblx0XHRcdHk6IG9yaWdpbi55ICsgb2Zmc2V0LnksXG5cdFx0fTtcblx0fVxuXG5cdHB1YmxpYyBjYW5Nb3ZlUGllY2UocGllY2U6IFJlYWRvbmx5PFRldHJpc3NpbW9QaWVjZT4sIGRlbHRhOiBQaWVjZVRyYW5zbGF0aW9uKTogYm9vbGVhbiB7XG5cdFx0Ly8gY2hlY2sgZWFjaCBibG9jayBpbiBsYXlvdXQncyBlZGdlIHRvIHNlZSBpZiBpdCdzIGluIGEgdmFsaWQgYXJlYT9zXG5cblx0XHRjb25zdCBsYXlvdXQgPSBwaWVjZS5nZXRMYXlvdXQoKTtcblx0XHRjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0UGllY2VQb3NpdGlvbihwaWVjZSk7XG5cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxheW91dC5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgYmxvY2tUb3BFZGdlID0gcG9zaXRpb24ueSArIChpICogVGV0cmlzc2ltb1BpZWNlLmJsb2NrTGVuZ3RoKSArIChkZWx0YS55RGVsdGEgKiBUZXRyaXNzaW1vUGllY2UuYmxvY2tMZW5ndGgpO1xuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCBsYXlvdXRbaV0ubGVuZ3RoOyBqKyspIHtcblx0XHRcdFx0aWYgKGxheW91dFtpXVtqXSA9PT0gMCkge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uc3QgYmxvY2tMZWZ0RWRnZSA9IHBvc2l0aW9uLnggKyAoaiAqIFRldHJpc3NpbW9QaWVjZS5ibG9ja0xlbmd0aCkgKyAoZGVsdGEueERlbHRhICogVGV0cmlzc2ltb1BpZWNlLmJsb2NrTGVuZ3RoKTtcblxuXHRcdFx0XHRjb25zdCBpc0NvbGxpc2lvbiA9IHRoaXMuaGFzQ29sbGlzaW9uKHtcblx0XHRcdFx0XHR4OiBibG9ja0xlZnRFZGdlLFxuXHRcdFx0XHRcdHk6IGJsb2NrVG9wRWRnZSxcblx0XHRcdFx0XHR3aWR0aDogVGV0cmlzc2ltb1BpZWNlLmJsb2NrTGVuZ3RoLFxuXHRcdFx0XHRcdGhlaWdodDogVGV0cmlzc2ltb1BpZWNlLmJsb2NrTGVuZ3RoLFxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRpZiAoaXNDb2xsaXNpb24pIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHByaXZhdGUgaGFzQ29sbGlzaW9uKHJlY3Q6IFJlY3RhbmdsZUNvb3JkaW5hdGVzKTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgcGxheUFyZWFMZWZ0RWRnZSA9IHRoaXMub3B0aW9ucy5wYWRkaW5nO1xuXHRcdGNvbnN0IHBsYXlBcmVhUmlnaHRFZGdlID0gcGxheUFyZWFMZWZ0RWRnZSArIHRoaXMub3B0aW9ucy5wbGF5QXJlYS53aWR0aDtcblx0XHRjb25zdCBwbGF5QXJlYVRvcEVkZ2UgPSB0aGlzLm9wdGlvbnMucGFkZGluZztcblx0XHRjb25zdCBwbGF5QXJlYUJvdHRvbUVkZ2UgPSBwbGF5QXJlYVRvcEVkZ2UgKyB0aGlzLm9wdGlvbnMucGxheUFyZWEuaGVpZ2h0O1xuXG5cdFx0Y29uc3QgbGVmdEVkZ2UgPSByZWN0Lng7XG5cdFx0Y29uc3QgcmlnaHRFZGdlID0gcmVjdC54ICsgcmVjdC53aWR0aDtcblx0XHRjb25zdCB0b3BFZGdlID0gcmVjdC55O1xuXHRcdGNvbnN0IGJvdHRvbUVkZ2UgPSByZWN0LnkgKyByZWN0LmhlaWdodDtcblxuXHRcdGNvbnN0IGlzSW5QbGF5QXJlYSA9XG5cdFx0XHRsZWZ0RWRnZSA+PSBwbGF5QXJlYUxlZnRFZGdlICYmXG5cdFx0XHRyaWdodEVkZ2UgPD0gcGxheUFyZWFSaWdodEVkZ2UgJiZcblx0XHRcdGJvdHRvbUVkZ2UgPD0gcGxheUFyZWFCb3R0b21FZGdlICYmXG5cdFx0XHR0b3BFZGdlID49IHBsYXlBcmVhVG9wRWRnZTtcblxuXHRcdGlmICghaXNJblBsYXlBcmVhKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRjb25zdCBmaXhlZFBpZWNlcyA9IHRoaXMucGllY2VzLmZpbHRlcihwaWVjZSA9PiBwaWVjZS5zdGF0ZSA9PT0gJ2ZpeGVkJyk7XG5cdFx0Zm9yIChjb25zdCBwaWVjZSBvZiBmaXhlZFBpZWNlcykge1xuXHRcdFx0Y29uc3QgcG9zaXRpb24gPSB0aGlzLmdldFBpZWNlUG9zaXRpb24ocGllY2UpO1xuXHRcdFx0Y29uc3QgbGF5b3V0ID0gcGllY2UuZ2V0TGF5b3V0KCk7XG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxheW91dC5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRjb25zdCBibG9ja1RvcEVkZ2UgPSBwb3NpdGlvbi55ICsgKGkgKiBUZXRyaXNzaW1vUGllY2UuYmxvY2tMZW5ndGgpO1xuXHRcdFx0XHRjb25zdCBibG9ja0JvdHRvbUVkZ2UgPSBibG9ja1RvcEVkZ2UgKyBUZXRyaXNzaW1vUGllY2UuYmxvY2tMZW5ndGg7XG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgbGF5b3V0W2ldLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0aWYgKGxheW91dFtpXVtqXSA9PT0gMCkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Y29uc3QgYmxvY2tMZWZ0RWRnZSA9IHBvc2l0aW9uLnggKyAoaiAqIFRldHJpc3NpbW9QaWVjZS5ibG9ja0xlbmd0aCk7XG5cdFx0XHRcdFx0Y29uc3QgYmxvY2tSaWdodEVkZ2UgPSBibG9ja0xlZnRFZGdlICsgVGV0cmlzc2ltb1BpZWNlLmJsb2NrTGVuZ3RoO1xuXG5cdFx0XHRcdFx0Y29uc3QgaXNDb2xsaXNpb24gPVxuXHRcdFx0XHRcdFx0bGVmdEVkZ2UgPj0gYmxvY2tMZWZ0RWRnZSAmJlxuXHRcdFx0XHRcdFx0cmlnaHRFZGdlIDw9IGJsb2NrUmlnaHRFZGdlICYmXG5cdFx0XHRcdFx0XHRib3R0b21FZGdlIDw9IGJsb2NrQm90dG9tRWRnZSAmJlxuXHRcdFx0XHRcdFx0dG9wRWRnZSA+PSBibG9ja1RvcEVkZ2U7XG5cblx0XHRcdFx0XHRpZiAoaXNDb2xsaXNpb24pIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHB1YmxpYyB1cGRhdGUoKSB7XG5cdFx0Y29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblx0XHRjb25zdCBjb250ZXh0ID0gdGhpcy5vcHRpb25zLmNvbnRleHQ7XG5cblx0XHRjb250ZXh0LmNsZWFyUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG5cdFx0Ly8gZmlsbCBiYWNrZ3JvdW5kXG5cdFx0Y29udGV4dC5maWxsU3R5bGUgPSAncmdiKDIyNCwxNTgsMTA3KSc7XG5cdFx0Y29udGV4dC5maWxsUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xuXG5cdFx0Ly8gZHJhdyBzb21lIGdyaWQgbGluZXNcblx0XHRpZiAodHlwZW9mKG9wdGlvbnMuZ3JpZExpbmVzKSA9PT0gJ251bWJlcicpIHtcblx0XHRcdGNvbnRleHQuc3Ryb2tlU3R5bGUgPSAncmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KSc7XG5cdFx0XHRjb250ZXh0LmxpbmVXaWR0aCA9IDE7XG5cdFx0XHRjb25zdCBpbmNyZW1lbnQgPSBvcHRpb25zLnBpeGVsU2l6ZSAqIG9wdGlvbnMuZ3JpZExpbmVzO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBvcHRpb25zLmNhbnZhcy53aWR0aDsgaSArPSBpbmNyZW1lbnQpIHtcblx0XHRcdFx0Ly8gZHJhdyB2ZXJ0aWNhbCBsaW5lXG5cdFx0XHRcdGNvbnRleHQuYmVnaW5QYXRoKCk7XG5cdFx0XHRcdGNvbnRleHQubW92ZVRvKGksIDApO1xuXHRcdFx0XHRjb250ZXh0LmxpbmVUbyhpLCBvcHRpb25zLmNhbnZhcy5oZWlnaHQpO1xuXHRcdFx0XHRjb250ZXh0LnN0cm9rZSgpO1xuXHRcdFx0fVxuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBvcHRpb25zLmNhbnZhcy5oZWlnaHQ7IGkgKz0gaW5jcmVtZW50KSB7XG5cdFx0XHRcdC8vIGRyYXcgaG9yaXpvbnRhbCBsaW5lc1xuXHRcdFx0XHRjb250ZXh0LmJlZ2luUGF0aCgpO1xuXHRcdFx0XHRjb250ZXh0Lm1vdmVUbygwLCBpKTtcblx0XHRcdFx0Y29udGV4dC5saW5lVG8ob3B0aW9ucy5jYW52YXMud2lkdGgsIGkpO1xuXHRcdFx0XHRjb250ZXh0LnN0cm9rZSgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGNvbnN0IHRvdGFsV2lkdGggPSBNYXRoLmZsb29yKGNhbnZhcy53aWR0aCAvIG9wdGlvbnMucGl4ZWxTaXplKTtcblx0XHRjb25zdCBwYWRkaW5nID0gb3B0aW9ucy5wYWRkaW5nO1xuXG5cdFx0Ly8gZHJhdyBIVUQgaW4gdG9wIHJpZ2h0IGNvcm5lclxuXHRcdHRoaXMuaHVkLnJlbmRlcihjb250ZXh0LCB7XG5cdFx0XHQuLi5vcHRpb25zLFxuXHRcdFx0eDogdG90YWxXaWR0aCAtIHBhZGRpbmcgLSBvcHRpb25zLmh1ZC53aWR0aCxcblx0XHRcdHk6IHBhZGRpbmcsXG5cdFx0fSk7XG5cblx0XHQvLyBkcmF3IHBsYXkgYXJlYVxuXHRcdHRoaXMucGxheUFyZWEucmVuZGVyKGNvbnRleHQsIHtcblx0XHRcdC4uLm9wdGlvbnMsXG5cdFx0XHR4OiBwYWRkaW5nLFxuXHRcdFx0eTogcGFkZGluZyxcblx0XHR9KTtcblxuXHRcdHRoaXMucGllY2VzLmZvckVhY2goKHBpZWNlLCBpKSA9PiB7XG5cdFx0XHRwaWVjZS5yZW5kZXIoY29udGV4dCwge1xuXHRcdFx0XHQuLi5vcHRpb25zLFxuXHRcdFx0XHQuLi50aGlzLmdldFBpZWNlT3JpZ2luKHBpZWNlKSxcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBnZXRQaWVjZU9yaWdpbihwaWVjZTogUmVhZG9ubHk8VGV0cmlzc2ltb1BpZWNlPik6IFRldHJpc3NpbW9Db29yZGluYXRlcyB7XG5cdFx0Y29uc3QgbGVuZ3RoID0gVGV0cmlzc2ltb1BpZWNlLmJsb2NrTGVuZ3RoO1xuXHRcdC8vIFRPRE8gcm90YXRpb24gd2lsbCBjYXVzZSBwcm9ibGVtcywgbmVlZCBhIFwiUGllY2VEZWZpbml0aW9uXCIgb3Igc29tZXRoaW5nIHdpdGggYSBzdGF0aWMgbGF5b3V0XG5cdFx0bGV0IHRyYW5zbGF0ZVggPSBNYXRoLmZsb29yKChwaWVjZS5nZXRCbG9ja1dpZHRoKCkgKiBsZW5ndGgpIC8gMik7XG5cblx0XHQvLyB3ZSBjYW4gb25seSBwZXJmb3JtIG1vdmVtZW50cyBpbiBtdWx0aXBsZXMgb2YgdGhlIGJsb2NrTGVuZ3RoLCBzbyB3ZSBtdXN0IGNsYW1wIGl0XG5cdFx0Ly8gdG8gZW5zdXJlIGl0J3Mgbm90IG9mZnNldFxuXHRcdHRyYW5zbGF0ZVggLT0gKHRyYW5zbGF0ZVggJSBsZW5ndGgpO1xuXHRcdGNvbnN0IHBhZGRpbmcgPSB0aGlzLm9wdGlvbnMucGFkZGluZztcblx0XHRyZXR1cm4ge1xuXHRcdFx0eDogcGFkZGluZyArIE1hdGgucm91bmQodGhpcy5vcHRpb25zLnBsYXlBcmVhLndpZHRoIC8gMikgLSB0cmFuc2xhdGVYLFxuXHRcdFx0eTogcGFkZGluZyxcblx0XHR9O1xuXHR9XG59XG5cbmNsYXNzIFRldHJpc3NpbW9OZXh0Qm94IGltcGxlbWVudHMgVUlFbGVtZW50IHtcblx0cHVibGljIHJlbmRlcihjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQsIG9wdGlvbnM6IFVJRWxlbWVudFJlbmRlck9wdGlvbnMpIHtcblxuXHR9XG59XG5cbmNsYXNzIFRldHJpc3NpbW9IVUQgaW1wbGVtZW50cyBVSUVsZW1lbnQge1xuXHRwdWJsaWMgcmVuZGVyKGNvbnRleHQ6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCwgb3B0aW9uczogVUlFbGVtZW50UmVuZGVyT3B0aW9ucykge1xuXHRcdGNvbnN0IHBvc2l0aW9uID0ge1xuXHRcdFx0eDogb3B0aW9ucy54LFxuXHRcdFx0eTogb3B0aW9ucy55LFxuXHRcdFx0d2lkdGg6IG9wdGlvbnMuaHVkLndpZHRoLFxuXHRcdFx0aGVpZ2h0OiBvcHRpb25zLmh1ZC5oZWlnaHQsXG5cdFx0fTtcblx0XHRkcmF3Qm9yZGVyZWRSZWN0KHBvc2l0aW9uLCBjb250ZXh0LCBvcHRpb25zKTtcblx0fVxufVxuXG5jbGFzcyBUZXRyaXNzaW1vUGxheUFyZWEgaW1wbGVtZW50cyBVSUVsZW1lbnQge1xuXHRwdWJsaWMgcmVuZGVyKGNvbnRleHQ6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCwgb3B0aW9uczogVUlFbGVtZW50UmVuZGVyT3B0aW9ucykge1xuXHRcdGNvbnN0IHBvc2l0aW9uID0ge1xuXHRcdFx0eDogb3B0aW9ucy54LFxuXHRcdFx0eTogb3B0aW9ucy55LFxuXHRcdFx0d2lkdGg6IG9wdGlvbnMucGxheUFyZWEud2lkdGgsXG5cdFx0XHRoZWlnaHQ6IG9wdGlvbnMucGxheUFyZWEuaGVpZ2h0LFxuXHRcdH07XG5cdFx0ZHJhd0JvcmRlcmVkUmVjdChwb3NpdGlvbiwgY29udGV4dCwgb3B0aW9ucyk7XG5cdH1cbn1cblxudHlwZSBQaWVjZVN0YXRlID0gJ2luLXBsYXknIHwgJ2ZpeGVkJztcblxuY2xhc3MgVGV0cmlzc2ltb1BpZWNlIGltcGxlbWVudHMgVUlFbGVtZW50IHtcblx0cHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblx0cHJpdmF0ZSByZWFkb25seSBvcmlnaW5hbExheW91dDogUmVhZG9ubHk8UGllY2VMYXlvdXQ+O1xuXHRwcml2YXRlIGxheW91dDogUGllY2VMYXlvdXQ7XG5cdHByaXZhdGUgb2Zmc2V0OiBUZXRyaXNzaW1vQ29vcmRpbmF0ZXMgPSB7IHg6IDAsIHk6IDAgfTtcblx0cHJpdmF0ZSByZWFkb25seSBjb2xvcjogc3RyaW5nO1xuXHRwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGJsb2NrTGVuZ3RoID0gNDtcblx0cHVibGljIHN0YXRlOiBQaWVjZVN0YXRlID0gJ2luLXBsYXknO1xuXG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgSiA9IG5ldyBUZXRyaXNzaW1vUGllY2UoXG5cdFx0J0onLFxuXHRcdFtcblx0XHRcdFswLCAxXSxcblx0XHRcdFswLCAxXSxcblx0XHRcdFsxLCAxXSxcblx0XHRdLFxuXHRcdCdibGFjaycsXG5cdCk7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUzogVGV0cmlzc2ltb1BpZWNlID0gbmV3IFRldHJpc3NpbW9QaWVjZShcblx0XHQnUycsXG5cdFx0W1xuXHRcdFx0WzAsIDEsIDFdLFxuXHRcdFx0WzEsIDEsIDBdLFxuXHRcdF0sXG5cdFx0J2dyZWVuJyxcblx0KTtcblx0cHVibGljIHN0YXRpYyByZWFkb25seSBUOiBUZXRyaXNzaW1vUGllY2UgPSBuZXcgVGV0cmlzc2ltb1BpZWNlKFxuXHRcdCdUJyxcblx0XHRbXG5cdFx0XHRbMSwgMSwgMV0sXG5cdFx0XHRbMCwgMSwgMF0sXG5cdFx0XSxcblx0XHQnYmx1ZScsXG5cdCk7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgWjogVGV0cmlzc2ltb1BpZWNlID0gbmV3IFRldHJpc3NpbW9QaWVjZShcblx0XHQnWicsXG5cdFx0W1xuXHRcdFx0WzEsIDEsIDAsXSxcblx0XHRcdFswLCAxLCAxLF0sXG5cdFx0XSxcblx0XHQneWVsbG93Jyxcblx0KTtcblx0cHVibGljIHN0YXRpYyByZWFkb25seSBJOiBUZXRyaXNzaW1vUGllY2UgPSBuZXcgVGV0cmlzc2ltb1BpZWNlKFxuXHRcdCdJJyxcblx0XHRbXG5cdFx0XHRbMSwgMSwgMSwgMV0sXG5cdFx0XSxcblx0XHQnbWFnZW50YScsXG5cdCk7XG5cdHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTDogVGV0cmlzc2ltb1BpZWNlID0gbmV3IFRldHJpc3NpbW9QaWVjZShcblx0XHQnTCcsXG5cdFx0W1xuXHRcdFx0WzFdLFxuXHRcdFx0WzFdLFxuXHRcdFx0WzEsIDFdLFxuXHRcdF0sXG5cdFx0J2N5YW4nLFxuXHQpO1xuXHRwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE86IFRldHJpc3NpbW9QaWVjZSA9IG5ldyBUZXRyaXNzaW1vUGllY2UoXG5cdFx0J08nLFxuXHRcdFtcblx0XHRcdFsxLCAxXSxcblx0XHRcdFsxLCAxXSxcblx0XHRdLFxuXHRcdCdyZWQnLFxuXHQpO1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihuYW1lOiBzdHJpbmcsIGxheW91dDogUGllY2VMYXlvdXQsIGNvbG9yOiBzdHJpbmcpIHtcblx0XHR0aGlzLm5hbWUgPSBuYW1lO1xuXHRcdHRoaXMub3JpZ2luYWxMYXlvdXQgPSBsYXlvdXQubWFwKHJvdyA9PiByb3cuY29uY2F0KFtdKSk7XG5cdFx0dGhpcy5sYXlvdXQgPSBsYXlvdXQuY29uY2F0KFtdKTtcblx0XHR0aGlzLmNvbG9yID0gY29sb3I7XG5cdH1cblxuXHRwdWJsaWMgZ2V0T2Zmc2V0KCk6IFJlYWRvbmx5PFRldHJpc3NpbW9Db29yZGluYXRlcz4ge1xuXHRcdHJldHVybiB0aGlzLm9mZnNldDtcblx0fVxuXG5cdHB1YmxpYyBnZXRMYXlvdXQoKTogUmVhZG9ubHk8UGllY2VMYXlvdXQ+IHtcblx0XHRyZXR1cm4gdGhpcy5sYXlvdXQ7XG5cdH1cblxuXHRwdWJsaWMgbW92ZSh0cmFuc2xhdGlvbjogUGllY2VUcmFuc2xhdGlvbikge1xuXHRcdGlmICh0aGlzLnN0YXRlICE9PSAnaW4tcGxheScpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLm9mZnNldC54ICs9ICh0cmFuc2xhdGlvbi54RGVsdGEgKiBUZXRyaXNzaW1vUGllY2UuYmxvY2tMZW5ndGgpO1xuXHRcdHRoaXMub2Zmc2V0LnkgKz0gKHRyYW5zbGF0aW9uLnlEZWx0YSAqIFRldHJpc3NpbW9QaWVjZS5ibG9ja0xlbmd0aCk7XG5cdH1cblxuXHRwdWJsaWMgcm90YXRlTGVmdCgpIHtcblx0XHRpZiAodGhpcy5zdGF0ZSAhPT0gJ2luLXBsYXknKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gY2xvY2t3aXNlIHR1cm5cblx0XHRjb25zdCBuZXdMYXlvdXQ6IFBpZWNlTGF5b3V0ID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxheW91dC5sZW5ndGg7IGkrKykge1xuXHRcdFx0Y29uc3QgY29sID0gdGhpcy5sYXlvdXQubGVuZ3RoIC0gMSAtIGk7XG5cdFx0XHRmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMubGF5b3V0W2ldLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdGNvbnN0IHJvdyA9IGo7XG5cdFx0XHRcdGlmICghbmV3TGF5b3V0W3Jvd10pIHtcblx0XHRcdFx0XHRuZXdMYXlvdXRbcm93XSA9IFtdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdG5ld0xheW91dFtyb3ddW2NvbF0gPSB0aGlzLmxheW91dFtpXVtqXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmxheW91dCA9IG5ld0xheW91dDtcblx0fVxuXG5cdHB1YmxpYyByb3RhdGVSaWdodCgpIHtcblx0XHRpZiAodGhpcy5zdGF0ZSAhPT0gJ2luLXBsYXknKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgbmV3TGF5b3V0OiBQaWVjZUxheW91dCA9IFtdO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5sYXlvdXQubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNvbnN0IGNvbCA9IGk7XG5cdFx0XHRmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMubGF5b3V0W2ldLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdGNvbnN0IHJvdyA9IHRoaXMubGF5b3V0W2ldLmxlbmd0aCAtIDEgLSBqO1xuXHRcdFx0XHRpZiAoIW5ld0xheW91dFtyb3ddKSB7XG5cdFx0XHRcdFx0bmV3TGF5b3V0W3Jvd10gPSBbXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRuZXdMYXlvdXRbcm93XVtjb2xdID0gdGhpcy5sYXlvdXRbaV1bal07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5sYXlvdXQgPSBuZXdMYXlvdXQ7XG5cdH1cblxuXHRwdWJsaWMgc2V0Rml4ZWQoKSB7XG5cdFx0dGhpcy5zdGF0ZSA9ICdmaXhlZCc7XG5cdH1cblxuXHRwdWJsaWMgZ2V0QmxvY2tXaWR0aCgpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLmxheW91dFxuXHRcdFx0Lm1hcChhcnIgPT4gYXJyLmZpbHRlcih2YWx1ZSA9PiB2YWx1ZSA9PT0gMSkubGVuZ3RoKVxuXHRcdFx0LnJlZHVjZSgobWF4LCBsZW4pID0+IE1hdGgubWF4KG1heCwgbGVuKSwgMCk7XG5cdH1cblxuXHRwdWJsaWMgZ2V0QmxvY2tIZWlnaHQoKTogbnVtYmVyIHtcblx0XHRjb25zdCBjb2xzOiBQaWVjZUNlbGxbXVtdID0gW107XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmxheW91dC5sZW5ndGg7IGkrKykge1xuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmxheW91dFtpXS5sZW5ndGg7IGorKykge1xuXHRcdFx0XHRpZiAoIWNvbHNbal0pIHtcblx0XHRcdFx0XHRjb2xzW2pdID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0Y29sc1tqXS5wdXNoKHRoaXMubGF5b3V0W2ldW2pdKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gY29sc1xuXHRcdFx0Lm1hcChhcnIgPT4gYXJyLmZpbHRlcih2YWx1ZSA9PiB2YWx1ZSA9PT0gMSkubGVuZ3RoKVxuXHRcdFx0LnJlZHVjZSgobWF4LCBsZW4pID0+IE1hdGgubWF4KG1heCwgbGVuKSwgMCk7XG5cdH1cblxuXHRwdWJsaWMgY2xvbmUoKTogVGV0cmlzc2ltb1BpZWNlIHtcblx0XHRyZXR1cm4gbmV3IFRldHJpc3NpbW9QaWVjZSh0aGlzLm5hbWUsIHRoaXMubGF5b3V0LCB0aGlzLmNvbG9yKTtcblx0fVxuXG5cdHB1YmxpYyByZW5kZXIoY29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELCBvcHRpb25zOiBVSUVsZW1lbnRSZW5kZXJPcHRpb25zKSB7XG5cdFx0dGhpcy5sYXlvdXQuZm9yRWFjaCgoY29sdW1ucywgcm93TnVtKSA9PiB7XG5cdFx0XHRjb2x1bW5zLmZvckVhY2goKHZhbHVlLCBjb2xOdW0pID0+IHtcblx0XHRcdFx0c3dpdGNoICh2YWx1ZSkge1xuXHRcdFx0XHRcdGNhc2UgMDpcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdGNhc2UgMTpcblx0XHRcdFx0XHRcdGNvbnRleHQuZmlsbFN0eWxlID0gdGhpcy5jb2xvcjtcblx0XHRcdFx0XHRcdGNvbnN0IGxlbmd0aCA9IFRldHJpc3NpbW9QaWVjZS5ibG9ja0xlbmd0aDtcblx0XHRcdFx0XHRcdGNvbnN0IG9mZnNldFggPSB0aGlzLm9mZnNldC54O1xuXHRcdFx0XHRcdFx0Y29uc3Qgb2Zmc2V0WSA9IHRoaXMub2Zmc2V0Lnk7XG5cblx0XHRcdFx0XHRcdGNvbnN0IHggPSBvcHRpb25zLnggKyBvZmZzZXRYICsgKGNvbE51bSAqIGxlbmd0aCk7XG5cdFx0XHRcdFx0XHRjb25zdCB5ID0gb3B0aW9ucy55ICsgb2Zmc2V0WSArIChyb3dOdW0gKiBsZW5ndGgpO1xuXHRcdFx0XHRcdFx0Y29uc3QgYWN0dWFsTGVuZ3RoID0gZ2V0U2l6ZShsZW5ndGgsIG9wdGlvbnMpO1xuXHRcdFx0XHRcdFx0Y29udGV4dC5maWxsUmVjdChnZXRTaXplKHgsIG9wdGlvbnMpLCBnZXRTaXplKHksIG9wdGlvbnMpLCBhY3R1YWxMZW5ndGgsIGFjdHVhbExlbmd0aCk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0bm9wZSh2YWx1ZSk7XG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcGllY2UgY2VsbCB2YWx1ZSBcIiR7dmFsdWV9XCJgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmNvbnN0IGh1ZCA9IG5ldyBUZXRyaXNzaW1vSFVEKCk7XG5jb25zdCBwbGF5QXJlYSA9IG5ldyBUZXRyaXNzaW1vUGxheUFyZWEoKTtcblxuY29uc3QgY2FudmFzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2NhbnZhcycpWzBdO1xuaWYgKCFjYW52YXMpIHtcblx0dGhyb3cgbmV3IEVycm9yKCdubyBjYW52YXMnKTtcbn1cblxuY29uc3QgdWkgPSBuZXcgVGV0cmlzc2ltb1VJKGNhbnZhcywgcGxheUFyZWEsIGh1ZCk7XG5jb25zdCBnYW1lID0gbmV3IFRldHJpc3NpbW9HYW1lKHVpKTtcblxuIl19
|