ngx-drag-and-drop
Version:
Angular library that allow you to build drag and drop without the native HTML5 API
544 lines • 61.9 kB
JavaScript
import { __decorate } from "tslib";
import { Directive, ElementRef, Input, HostListener, EventEmitter, Output, OnInit, OnDestroy } from '@angular/core';
import { myDoc } from './ngx-drag-and-drop.utils';
/*
interface ShadowRoot extends DocumentFragment {
styleSheets : StyleSheetList;
innerHTML : string;
host : Element;
activeElement : Element;
elementFromPoint (x : number, y : number) : Element;
elementsFromPoint (x : number, y : number) : Element[];
caretPositionFromPoint (x : number, y : number); // => CaretPosition
};
interface ElementWithShadowRoot extends HTMLElement {
shadowRoot : ShadowRoot;
};*/
const dragPointerId = 'dragPointer';
class DragManager {
constructor() {
this.draggingPointer = new Map();
this.draggedStructures = new Map();
this.dropZones = new Map();
}
preStartDrag(idPointer, x, y, delay, dist) {
this.draggingPointer.set(idPointer, { x: x, y: y });
return new Promise((resolve, reject) => {
setTimeout(() => {
const ptr = this.draggingPointer.get(idPointer);
const gogo = ptr && (Math.abs(x - ptr.x) + Math.abs(y - ptr.y)) < dist;
this.draggingPointer.delete(idPointer);
gogo ? resolve() : reject();
}, Math.max(0, delay));
});
}
startDrag(idPointer, dragged) {
this.draggedStructures.set(idPointer, dragged);
const possibleDropZones = new Map();
this.dropZones.forEach(dz => {
if (dz.checkAccept(dragged)) {
dz.appendDropCandidatePointer(idPointer);
possibleDropZones.set(dz.root, dz);
}
});
return possibleDropZones;
}
isAssociatedToDropZone(element) {
return this.dropZones.has(element);
}
registerDropZone(dropzone) {
this.dropZones.set(dropzone.root, dropzone);
}
unregisterDropZone(dropzone) {
this.dropZones.delete(dropzone.root);
}
pointerMove(idPointer, x, y) {
const ptr = this.draggingPointer.get(idPointer);
if (ptr) {
ptr.x = x;
ptr.y = y;
}
const dragged = this.draggedStructures.get(idPointer);
if (dragged && dragged instanceof Draggable) {
dragged.move(x, y);
}
return dragged !== undefined;
}
pointerRelease(idPointer) {
const dragged = this.draggedStructures.get(idPointer);
if (dragged) {
if (dragged instanceof Draggable) {
dragged.stop();
}
}
this.draggedStructures.delete(idPointer);
this.draggingPointer.delete(idPointer);
return dragged !== undefined;
}
}
const DM = new DragManager();
let dragDropInit = false;
let DragDrop = class DragDrop {
constructor() {
this.nbDragEnter = 0;
if (dragDropInit) {
console.error('Do not create multiple instance of directive drag-and-drop-wrapper !');
}
else {
dragDropInit = true;
}
}
removeFeedbackForDragPointer() {
this.nbDragEnter = 0;
DM.dropZones.forEach(dz => {
dz.removePointerHover(dragPointerId);
dz.removeDropCandidatePointer(dragPointerId);
});
}
drop(e) {
e.preventDefault();
e.stopPropagation();
this.removeFeedbackForDragPointer();
}
dragover(e) {
e.preventDefault();
e.stopPropagation();
}
dragenter(e) {
this.nbDragEnter++;
if (this.nbDragEnter === 1) {
DM.startDrag(dragPointerId, e);
}
}
dragleave(e) {
this.nbDragEnter--;
if (this.nbDragEnter === 0) {
this.removeFeedbackForDragPointer();
DM.pointerRelease(dragPointerId);
}
}
dragend(e) {
DM.pointerRelease(dragPointerId);
this.removeFeedbackForDragPointer();
e.preventDefault();
}
mousemove(e) {
DM.pointerMove('mouse', e.clientX, e.clientY);
}
mouseup(e) {
DM.pointerRelease('mouse');
}
touchmove(e) {
for (let i = 0; i < e.changedTouches.length; i++) {
const touch = e.changedTouches.item(i);
if (DM.pointerMove(touch.identifier.toString(), touch.clientX, touch.clientY)) {
e.preventDefault();
e.stopPropagation();
}
}
}
touchend(e) {
for (let i = 0; i < e.changedTouches.length; i++) {
const touch = e.changedTouches.item(i);
if (DM.pointerRelease(touch.identifier.toString())) {
e.preventDefault();
e.stopPropagation();
}
}
}
};
__decorate([
HostListener('document: drop', ['$event'])
], DragDrop.prototype, "drop", null);
__decorate([
HostListener('document: dragover', ['$event'])
], DragDrop.prototype, "dragover", null);
__decorate([
HostListener('document: dragenter', ['$event'])
], DragDrop.prototype, "dragenter", null);
__decorate([
HostListener('document: dragleave', ['$event'])
], DragDrop.prototype, "dragleave", null);
__decorate([
HostListener('document: dragend', ['$event'])
], DragDrop.prototype, "dragend", null);
__decorate([
HostListener('document: mousemove', ['$event'])
], DragDrop.prototype, "mousemove", null);
__decorate([
HostListener('document: mouseup', ['$event'])
], DragDrop.prototype, "mouseup", null);
__decorate([
HostListener('document: touchmove', ['$event'])
], DragDrop.prototype, "touchmove", null);
__decorate([
HostListener('document: touchend', ['$event'])
], DragDrop.prototype, "touchend", null);
DragDrop = __decorate([
Directive({
selector: '*[drag-and-drop-wrapper]'
})
], DragDrop);
export { DragDrop };
const offsetElement = (element) => {
let left = 0, top = 0;
while (element) {
top += element.offsetTop - element.scrollTop + element.clientTop;
left += element.offsetLeft - element.scrollLeft + element.clientLeft;
element = element.offsetParent;
}
return { left: left, top: top };
};
const ɵ0 = offsetElement;
let Draggable = class Draggable {
constructor(el) {
this.disabled = false;
this.onDragStart = new EventEmitter();
this.onDragEnd = new EventEmitter();
this.isBeingDragged = false;
this.cloneNode = null;
this.possibleDropZones = new Map();
this.root = el.nativeElement;
if (!dragDropInit) {
console.error('You should add one dragdrop attribute to your code before using draggable');
}
}
ngOnInit() {
//
}
ngOnDestroy() {
// XXX No stop in case of unplug while dragging... : // this.stop();
}
onMouseDown(event) {
if (!this.disabled) {
event.preventDefault();
event.stopPropagation();
this.prestart('mouse', event.clientX, event.clientY);
}
}
onTouchStart(event) {
event.stopPropagation();
for (let i = 0; i < event.changedTouches.length; i++) {
const touch = event.changedTouches.item(i);
this.prestart(touch.identifier.toString(), touch.clientX, touch.clientY);
}
}
prestart(idPointer, x, y) {
DM.preStartDrag(idPointer, x, y, this.startDelay || 0, this.startDistance || 10).then(() => {
this.start(idPointer, x, y);
}, () => {
// console.error('skip the drag');
});
}
start(idPointer, x, y) {
if (!this.isBeingDragged) {
this.isBeingDragged = true;
this.idPointer = idPointer;
const offset = offsetElement(this.root);
this.ox = x;
this.oy = y;
this.dx = x - offset.left;
this.dy = y - offset.top;
this.tx = this.root.offsetWidth;
this.ty = this.root.offsetHeight;
this.getClone();
this.cloneNode.style.left = (x - this.dx) + 'px';
this.cloneNode.style.top = (y - this.dy) + 'px';
this.onDragStart.emit(this.draggedData);
this.possibleDropZones = DM.startDrag(idPointer, this);
}
}
stop() {
this.possibleDropZones.forEach(dz => {
dz.removePointerHover(this.idPointer);
dz.removeDropCandidatePointer(this.idPointer);
});
this.isBeingDragged = false;
this.possibleDropZones.clear();
this.idPointer = null;
if (this.currentDropZone) {
this.currentDropZone.drop(this.draggedData);
}
this.currentDropZone = null;
this.onDragEnd.emit(this.draggedData);
this.deleteClone();
}
move(x, y) {
let element = null;
if (this.cloneNode === null) {
this.getClone();
}
if (this.cloneNode) {
this.cloneNode.style.left = (x - this.dx) + 'px';
this.cloneNode.style.top = (y - this.dy) + 'px';
const visibility = this.cloneNode.style.visibility;
this.cloneNode.style.visibility = 'hidden';
const top = this.cloneNode.style.top;
this.cloneNode.style.top = '999999999px';
element = myDoc.elementFromPoint(x, y);
this.cloneNode.style.top = top;
this.cloneNode.style.visibility = visibility;
const prevDropZone = this.currentDropZone;
while (element) {
this.currentDropZone = this.possibleDropZones.get(element);
if (this.currentDropZone) {
break;
}
element = element.parentElement;
}
if (prevDropZone !== this.currentDropZone) {
if (prevDropZone) {
prevDropZone.removePointerHover(this.idPointer);
}
if (this.currentDropZone) {
this.currentDropZone.appendPointerHover(this.idPointer);
}
}
}
return this;
}
deepStyle(original, clone) {
if (original instanceof HTMLElement) {
const style = window.getComputedStyle(original);
for (let i = 0; i < style.length; i++) {
const att = style[i];
clone.style[att] = style[att];
}
for (let i = 0; i < original.children.length; i++) {
this.deepStyle(original.children.item(i), clone.children.item(i));
}
}
}
deleteClone() {
if (this.cloneNode) {
if (this.cloneNode.parentNode) {
this.cloneNode.parentNode.removeChild(this.cloneNode);
}
this.cloneNode = null;
}
}
getClone() {
if (this.cloneNode === null) {
this.cloneNode = this.root.cloneNode(true);
this.deepStyle(this.root, this.cloneNode);
document.body.appendChild(this.cloneNode);
this.cloneNode.style.position = 'absolute';
this.cloneNode.style.zIndex = '999';
this.cloneNode.style.marginLeft = '0';
this.cloneNode.style.marginTop = '0';
this.cloneNode.style.marginRight = '0';
this.cloneNode.style.marginBottom = '0';
this.cloneNode.style.opacity = '';
this.cloneNode.style.cursor = '';
this.cloneNode.style.transform = '';
this.cloneNode.style.transformOrigin = '';
this.cloneNode.style.animation = '';
this.cloneNode.style.transition = '';
this.cloneNode.classList.add('drag-and-drop-clone-node');
}
return this.cloneNode;
}
};
Draggable.ctorParameters = () => [
{ type: ElementRef }
];
__decorate([
Input('draggable')
], Draggable.prototype, "draggedData", void 0);
__decorate([
Input('drag-start-delay')
], Draggable.prototype, "startDelay", void 0);
__decorate([
Input('start-distance')
], Draggable.prototype, "startDistance", void 0);
__decorate([
Input('disabled')
], Draggable.prototype, "disabled", void 0);
__decorate([
Output('drag-start')
], Draggable.prototype, "onDragStart", void 0);
__decorate([
Output('drag-end')
], Draggable.prototype, "onDragEnd", void 0);
__decorate([
HostListener('mousedown', ['$event'])
], Draggable.prototype, "onMouseDown", null);
__decorate([
HostListener('touchstart', ['$event'])
], Draggable.prototype, "onTouchStart", null);
Draggable = __decorate([
Directive({
selector: '*[draggable]'
})
], Draggable);
export { Draggable };
let Dropzone = class Dropzone {
constructor(el) {
this.nbDragEnter = 0;
this.onDropEmitter = new EventEmitter();
this.onDragStart = new EventEmitter();
this.onDragEnd = new EventEmitter();
this.onDragEnter = new EventEmitter();
this.onDragLeave = new EventEmitter();
this.dropCandidateofPointers = [];
this.pointersHover = [];
if (!dragDropInit) {
console.error('You should add one dragdrop attribute to your code before using dropzone');
}
this.root = el.nativeElement;
DM.registerDropZone(this);
}
ngOnInit() {
//
}
ngOnDestroy() {
DM.unregisterDropZone(this);
}
BrowserDragEnter(event) {
this.nbDragEnter++;
if (this.nbDragEnter === 1) {
this.appendPointerHover(dragPointerId);
}
}
BrowserDragLeave(event) {
this.nbDragEnter--;
if (this.nbDragEnter === 0) {
this.removePointerHover(dragPointerId);
}
}
BrowserDrop(event) {
DM.pointerRelease(dragPointerId);
this.nbDragEnter = 0;
this.onDropEmitter.emit(event);
}
drop(obj) {
this.onDropEmitter.emit(obj);
}
checkAccept(drag) {
let res;
if (drag instanceof Draggable) {
res = this.acceptFunction ? this.acceptFunction(drag.draggedData) : true;
}
else {
res = this.acceptFunction ? this.acceptFunction(drag) : true;
}
return res;
}
hasPointerHover(idPointer) {
return this.pointersHover.indexOf(idPointer) >= 0;
}
appendPointerHover(idPointer) {
if (this.pointersHover.indexOf(idPointer) === -1) {
const dragged = DM.draggedStructures.get(idPointer);
this.pointersHover.push(idPointer);
if (dragged instanceof Draggable) {
if (this.dragOverCSS_pointer) {
dragged.getClone().classList.add(this.dragOverCSS_pointer);
}
this.onDragEnter.emit(dragged.draggedData);
}
else {
this.onDragEnter.emit(dragged);
}
if (this.dragOverCSS) {
this.root.classList.add(this.dragOverCSS);
}
}
}
removePointerHover(idPointer) {
const pos = this.pointersHover.indexOf(idPointer);
if (pos >= 0) {
const dragged = DM.draggedStructures.get(idPointer);
this.pointersHover.splice(pos, 1);
if (dragged instanceof Draggable) {
if (this.dragOverCSS_pointer) {
dragged.getClone().classList.remove(this.dragOverCSS_pointer);
}
this.onDragLeave.emit(dragged.draggedData);
}
else {
this.onDragLeave.emit(dragged);
}
if (this.pointersHover.length === 0 && this.dragOverCSS) {
this.root.classList.remove(this.dragOverCSS);
}
}
}
appendDropCandidatePointer(idPointer) {
if (this.dropCandidateofPointers.indexOf(idPointer) === -1) {
const dragged = DM.draggedStructures.get(idPointer);
if (dragged instanceof Draggable) {
this.onDragStart.emit(dragged.draggedData);
}
else {
this.onDragStart.emit(dragged);
}
this.dropCandidateofPointers.push(idPointer);
if (this.dragCSS) {
this.root.classList.add(this.dragCSS);
}
}
}
removeDropCandidatePointer(idPointer) {
const pos = this.dropCandidateofPointers.indexOf(idPointer);
if (pos >= 0) {
const dragged = DM.draggedStructures.get(idPointer);
if (dragged instanceof Draggable) {
this.onDragEnd.emit(dragged.draggedData);
}
else {
this.onDragEnd.emit(dragged);
}
this.dropCandidateofPointers.splice(pos, 1);
if (this.dropCandidateofPointers.length === 0 && this.dragCSS) {
this.root.classList.remove(this.dragCSS);
}
}
}
};
Dropzone.ctorParameters = () => [
{ type: ElementRef }
];
__decorate([
Input('drag-css')
], Dropzone.prototype, "dragCSS", void 0);
__decorate([
Input('drag-over-css')
], Dropzone.prototype, "dragOverCSS", void 0);
__decorate([
Input('drag-over-css-for-draggable')
], Dropzone.prototype, "dragOverCSS_pointer", void 0);
__decorate([
Input('accept-function')
], Dropzone.prototype, "acceptFunction", void 0);
__decorate([
Output('ondrop')
], Dropzone.prototype, "onDropEmitter", void 0);
__decorate([
Output('drag-start')
], Dropzone.prototype, "onDragStart", void 0);
__decorate([
Output('drag-end')
], Dropzone.prototype, "onDragEnd", void 0);
__decorate([
Output('drag-enter')
], Dropzone.prototype, "onDragEnter", void 0);
__decorate([
Output('drag-leave')
], Dropzone.prototype, "onDragLeave", void 0);
__decorate([
HostListener('dragenter', ['$event'])
], Dropzone.prototype, "BrowserDragEnter", null);
__decorate([
HostListener('dragleave', ['$event'])
], Dropzone.prototype, "BrowserDragLeave", null);
__decorate([
HostListener('drop', ['$event'])
], Dropzone.prototype, "BrowserDrop", null);
Dropzone = __decorate([
Directive({ selector: '*[dropzone]' })
], Dropzone);
export { Dropzone };
export { ɵ0 };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWRyYWctYW5kLWRyb3AuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWRyYWctYW5kLWRyb3AvIiwic291cmNlcyI6WyJzcmMvYXBwL25neC1kcmFnLWFuZC1kcm9wL25neC1kcmFnLWFuZC1kcm9wLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEgsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBSWxEOzs7Ozs7Ozs7Ozs7O0lBYUk7QUFDSixNQUFNLGFBQWEsR0FBRyxhQUFhLENBQUM7QUFFcEMsTUFBTSxXQUFXO0lBQWpCO1FBQ0Usb0JBQWUsR0FBTyxJQUFJLEdBQUcsRUFBbUIsQ0FBQztRQUNqRCxzQkFBaUIsR0FBSyxJQUFJLEdBQUcsRUFBaUMsQ0FBQztRQUMvRCxjQUFTLEdBQWEsSUFBSSxHQUFHLEVBQXNCLENBQUM7SUF5RXRELENBQUM7SUF2RVEsWUFBWSxDQUNqQixTQUFpQixFQUNqQixDQUFTLEVBQ1QsQ0FBUyxFQUNULEtBQWEsRUFDYixJQUFZO1FBRVosSUFBSSxDQUFDLGVBQWUsQ0FBRyxHQUFHLENBQUMsU0FBUyxFQUFFLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUNwRCxPQUFPLElBQUksT0FBTyxDQUFRLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzVDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsTUFBTSxHQUFHLEdBQUssSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2xELE1BQU0sSUFBSSxHQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxH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WSxDQUFDOzZDQUF1QztBQUN4QztJQUFuQixNQUFNLENBQUMsVUFBVSxDQUFDOzJDQUFxQztBQUNsQztJQUFyQixNQUFNLENBQUMsWUFBWSxDQUFDOzZDQUF1QztBQUN0QztJQUFyQixNQUFNLENBQUMsWUFBWSxDQUFDOzZDQUF1QztBQXFCckI7SUFBdEMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dEQUtyQztBQUVzQztJQUF0QyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUM7Z0RBS3JDO0FBRWlDO0lBQWpDLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQzsyQ0FJaEM7QUFsRFUsUUFBUTtJQURwQixTQUFTLENBQUMsRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLENBQUM7R0FDMUIsUUFBUSxDQXlJcEI7U0F6SVksUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgSW5wdXQsIEhvc3RMaXN0ZW5lciwgRXZlbnRFbWl0dGVyLCBPdXRwdXQsIE9uSW5pdCwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBteURvYyB9IGZyb20gJy4vbmd4LWRyYWctYW5kLWRyb3AudXRpbHMnO1xuXG4vKiBQb2x5ZmlsbCBUb3VjaEV2ZW50ICovXG5leHBvcnQgaW50ZXJmYWNlIE15VG91Y2hFdmVudCBleHRlbmRzIFRvdWNoRXZlbnQge31cbi8qXG5pbnRlcmZhY2UgU2hhZG93Um9vdCBleHRlbmRzIERvY3VtZW50RnJhZ21lbnQge1xuICAgIHN0eWxlU2hlZXRzICAgICA6IFN0eWxlU2hlZXRMaXN0O1xuICAgIGlubmVySFRNTCAgICAgICA6IHN0cmluZztcbiAgICBob3N0ICAgICAgICAgICAgOiBFbGVtZW50O1xuICAgIGFjdGl2ZUVsZW1lbnQgICA6IEVsZW1lbnQ7XG4gICAgZWxlbWVudEZyb21Qb2ludCAgICAgICAgKHggOiBudW1iZXIsIHkgOiBudW1iZXIpIDogRWxlbWVudDtcbiAgICBlbGVtZW50c0Zyb21Qb2ludCAgICAgICAoeCA6IG51bWJlciwgeSA6IG51bWJlcikgOiBFbGVtZW50W107XG4gICAgY2FyZXRQb3NpdGlvbkZyb21Qb2ludCAgKHggOiBudW1iZXIsIHkgOiBudW1iZXIpOyAvLyA9PiBDYXJldFBvc2l0aW9uXG59O1xuXG5pbnRlcmZhY2UgRWxlbWVudFdpdGhTaGFkb3dSb290IGV4dGVuZHMgSFRNTEVsZW1lbnQge1xuICAgIHNoYWRvd1Jvb3QgIDogU2hhZG93Um9vdDtcbn07Ki9cbmNvbnN0IGRyYWdQb2ludGVySWQgPSAnZHJhZ1BvaW50ZXInO1xudHlwZSBQb2ludGVyID0ge3g6IG51bWJlciwgeTogbnVtYmVyfTtcbmNsYXNzIERyYWdNYW5hZ2VyIHtcbiAgZHJhZ2dpbmdQb2ludGVyICAgICA9IG5ldyBNYXA8c3RyaW5nLCBQb2ludGVyPigpO1xuICBkcmFnZ2VkU3RydWN0dXJlcyAgID0gbmV3IE1hcDxzdHJpbmcsIERyYWdnYWJsZSB8IERyYWdFdmVudD4oKTtcbiAgZHJvcFpvbmVzICAgICAgICAgICA9IG5ldyBNYXA8RWxlbWVudCwgRHJvcHpvbmUgPigpO1xuXG4gIHB1YmxpYyBwcmVTdGFydERyYWcoXG4gICAgaWRQb2ludGVyOiBzdHJpbmcsXG4gICAgeDogbnVtYmVyLFxuICAgIHk6IG51bWJlcixcbiAgICBkZWxheTogbnVtYmVyLFxuICAgIGRpc3Q6IG51bWJlcixcbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0aGlzLmRyYWdnaW5nUG9pbnRlciAgLnNldChpZFBvaW50ZXIsIHt4OiB4LCB5OiB5fSk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KCAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29uc3QgcHRyICAgPSB0aGlzLmRyYWdnaW5nUG9pbnRlci5nZXQoaWRQb2ludGVyKTtcbiAgICAgICAgY29uc3QgZ29nbyAgPSBwdHIgJiYgKE1hdGguYWJzKHggLSBwdHIueCkgKyBNYXRoLmFicyh5IC0gcHRyLnkpKSA8IGRpc3Q7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmdQb2ludGVyLmRlbGV0ZShpZFBvaW50ZXIpO1xuXG4gICAgICAgIGdvZ28gPyByZXNvbHZlKCkgOiByZWplY3QoKTtcbiAgICAgIH0sIE1hdGgubWF4KDAsIGRlbGF5KSk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc3RhcnREcmFnKFxuICAgIGlkUG9pbnRlcjogc3RyaW5nLFxuICAgIGRyYWdnZWQ6IERyYWdnYWJsZSB8IERyYWdFdmVudCxcbiAgKTogTWFwPEVsZW1lbnQsIERyb3B6b25lPiB7XG4gICAgdGhpcy5kcmFnZ2VkU3RydWN0dXJlcy5zZXQoaWRQb2ludGVyLCBkcmFnZ2VkKTtcbiAgICBjb25zdCBwb3NzaWJsZURyb3Bab25lcyA9IG5ldyBNYXA8RWxlbWVudCwgRHJvcHpvbmU+KCk7XG4gICAgdGhpcy5kcm9wWm9uZXMuZm9yRWFjaChkeiA9PiB7XG4gICAgICAgIGlmIChkei5jaGVja0FjY2VwdChkcmFnZ2VkKSkge1xuICAgICAgICAgICAgZHouYXBwZW5kRHJvcENhbmRpZGF0ZVBvaW50ZXIoaWRQb2ludGVyKTtcbiAgICAgICAgICAgIHBvc3NpYmxlRHJvcFpvbmVzLnNldChkei5yb290LCBkeik7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcG9zc2libGVEcm9wWm9uZXM7XG4gIH1cblxuICBwdWJsaWMgaXNBc3NvY2lhdGVkVG9Ecm9wWm9uZShlbGVtZW50OiBFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZHJvcFpvbmVzLmhhcyhlbGVtZW50KTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlckRyb3Bab25lKGRyb3B6b25lOiBEcm9wem9uZSkge1xuICAgIHRoaXMuZHJvcFpvbmVzLnNldChkcm9wem9uZS5yb290LCBkcm9wem9uZSk7XG4gIH1cblxuICBwdWJsaWMgdW5yZWdpc3RlckRyb3Bab25lKGRyb3B6b25lOiBEcm9wem9uZSkge1xuICAgIHRoaXMuZHJvcFpvbmVzLmRlbGV0ZShkcm9wem9uZS5yb290KTtcbiAgfVxuXG4gIHB1YmxpYyBwb2ludGVyTW92ZShpZFBvaW50ZXI6IHN0cmluZywgeDogbnVtYmVyLCB5OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCBwdHIgPSB0aGlzLmRyYWdnaW5nUG9pbnRlci5nZXQoaWRQb2ludGVyKTtcbiAgICBpZiAocHRyKSB7XG4gICAgICBwdHIueCA9IHg7IHB0ci55ID0geTtcbiAgICB9XG5cbiAgICBjb25zdCBkcmFnZ2VkID0gdGhpcy5kcmFnZ2VkU3RydWN0dXJlcy5nZXQoaWRQb2ludGVyKTtcblxuICAgIGlmIChkcmFnZ2VkICYmIGRyYWdnZWQgaW5zdGFuY2VvZiBEcmFnZ2FibGUpIHtcbiAgICAgIGRyYWdnZWQubW92ZSh4LCB5KTtcbiAgICB9XG4gICAgcmV0dXJuIGRyYWdnZWQgIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyBwb2ludGVyUmVsZWFzZShpZFBvaW50ZXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGRyYWdnZWQgPSB0aGlzLmRyYWdnZWRTdHJ1Y3R1cmVzLmdldChpZFBvaW50ZXIpO1xuICAgIGlmIChkcmFnZ2VkKSB7XG4gICAgICBpZiAoZHJhZ2dlZCBpbnN0YW5jZW9mIERyYWdnYWJsZSkge1xuICAgICAgICBkcmFnZ2VkLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5kcmFnZ2VkU3RydWN0dXJlcy5kZWxldGUoaWRQb2ludGVyKTtcbiAgICB0aGlzLmRyYWdnaW5nUG9pbnRlci5kZWxldGUoaWRQb2ludGVyKTtcbiAgICByZXR1cm4gZHJhZ2dlZCAhPT0gdW5kZWZpbmVkO1xuICB9XG59XG5cbmNvbnN0IERNID0gbmV3IERyYWdNYW5hZ2VyKCk7XG5cbmxldCBkcmFnRHJvcEluaXQgPSBmYWxzZTtcblxuXG5ARGlyZWN0aXZlKHtcbiAgICBzZWxlY3RvcjogJypbZHJhZy1hbmQtZHJvcC13cmFwcGVyXSdcbn0pXG5leHBvcnQgY2xhc3MgRHJhZ0Ryb3Age1xuICBuYkRyYWdFbnRlciA9IDA7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGlmIChkcmFnRHJvcEluaXQpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0RvIG5vdCBjcmVhdGUgbXVsdGlwbGUgaW5zdGFuY2Ugb2YgZGlyZWN0aXZlIGRyYWctYW5kLWRyb3Atd3JhcHBlciAhJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRyYWdEcm9wSW5pdCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmVtb3ZlRmVlZGJhY2tGb3JEcmFnUG9pbnRlcigpIHtcbiAgICB0aGlzLm5iRHJhZ0VudGVyID0gMDtcbiAgICBETS5kcm9wWm9uZXMuZm9yRWFjaChkeiA9PiB7XG4gICAgICBkei5yZW1vdmVQb2ludGVySG92ZXIoZHJhZ1BvaW50ZXJJZCk7XG4gICAgICBkei5yZW1vdmVEcm9wQ2FuZGlkYXRlUG9pbnRlcihkcmFnUG9pbnRlcklkKTtcbiAgICB9KTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OiBkcm9wJywgWyckZXZlbnQnXSkgZHJvcChlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5yZW1vdmVGZWVkYmFja0ZvckRyYWdQb2ludGVyKCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDogZHJhZ292ZXInLCBbJyRldmVudCddKSBkcmFnb3ZlcihlKSB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDogZHJhZ2VudGVyJywgWyckZXZlbnQnXSkgZHJhZ2VudGVyKGUpIHtcbiAgICB0aGlzLm5iRHJhZ0VudGVyKys7XG4gICAgaWYgKHRoaXMubmJEcmFnRW50ZXIgPT09IDEpIHtcbiAgICAgIERNLnN0YXJ0RHJhZyhkcmFnUG9pbnRlcklkLCBlKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDogZHJhZ2xlYXZlJywgWyckZXZlbnQnXSkgZHJhZ2xlYXZlKGUpIHtcbiAgICB0aGlzLm5iRHJhZ0VudGVyLS07XG4gICAgaWYgKHRoaXMubmJEcmFnRW50ZXIgPT09IDApIHtcbiAgICAgIHRoaXMucmVtb3ZlRmVlZGJhY2tGb3JEcmFnUG9pbnRlcigpO1xuICAgICAgRE0ucG9pbnRlclJlbGVhc2UoZHJhZ1BvaW50ZXJJZCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6IGRyYWdlbmQnLCBbJyRldmVudCddKSBkcmFnZW5kKGUpIHtcbiAgICBETS5wb2ludGVyUmVsZWFzZShkcmFnUG9pbnRlcklkKTtcbiAgICB0aGlzLnJlbW92ZUZlZWRiYWNrRm9yRHJhZ1BvaW50ZXIoKTtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDogbW91c2Vtb3ZlJywgWyckZXZlbnQnXSkgbW91c2Vtb3ZlKGUpIHtcbiAgICBETS5wb2ludGVyTW92ZSgnbW91c2UnLCBlLmNsaWVudFgsIGUuY2xpZW50WSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDogbW91c2V1cCcsIFsnJGV2ZW50J10pIG1vdXNldXAoZSkge1xuICAgIERNLnBvaW50ZXJSZWxlYXNlKCdtb3VzZScpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6IHRvdWNobW92ZScsIFsnJGV2ZW50J10pIHRvdWNobW92ZShlKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlLmNoYW5nZWRUb3VjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB0b3VjaDogVG91Y2ggPSBlLmNoYW5nZWRUb3VjaGVzLml0ZW0oaSk7XG4gICAgICBpZiAoRE0ucG9pbnRlck1vdmUodG91Y2guaWRlbnRpZmllci50b1N0cmluZygpLCB0b3VjaC5jbGllbnRYLCB0b3VjaC5jbGllbnRZKSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6IHRvdWNoZW5kJywgWyckZXZlbnQnXSkgdG91Y2hlbmQoZSkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZS5jaGFuZ2VkVG91Y2hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdG91Y2g6IFRvdWNoID0gZS5jaGFuZ2VkVG91Y2hlcy5pdGVtKGkpO1xuICAgICAgaWYgKERNLnBvaW50ZXJSZWxlYXNlKHRvdWNoLmlkZW50aWZpZXIudG9TdHJpbmcoKSkpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5jb25zdCBvZmZzZXRFbGVtZW50ID0gKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogeyBsZWZ0OiBudW1iZXIsIHRvcDogbnVtYmVyIH0gPT4ge1xuICBsZXQgbGVmdCA9IDAsIHRvcCA9IDA7XG4gIHdoaWxlIChlbGVtZW50KSB7XG4gICAgdG9wICs9IGVsZW1lbnQub2Zmc2V0VG9wIC0gZWxlbWVudC5zY3JvbGxUb3AgKyBlbGVtZW50LmNsaWVudFRvcDtcbiAgICBsZWZ0ICs9IGVsZW1lbnQub2Zmc2V0TGVmdCAtIGVsZW1lbnQuc2Nyb2xsTGVmdCArIGVsZW1lbnQuY2xpZW50TGVmdDtcbiAgICBlbGVtZW50ID0gZWxlbWVudC5vZmZzZXRQYXJlbnQgYXMgSFRNTEVsZW1lbnQ7XG4gIH1cbiAgcmV0dXJuIHsgbGVmdDogbGVmdCwgdG9wOiB0b3AgfTtcbn07XG5cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnKltkcmFnZ2FibGVdJ1xufSlcbmV4cG9ydCBjbGFzcyBEcmFnZ2FibGUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgnZHJhZ2dhYmxlJykgZHJhZ2dlZERhdGE6IGFueTtcbiAgQElucHV0KCdkcmFnLXN0YXJ0LWRlbGF5Jykgc3RhcnREZWxheTogbnVtYmVyO1xuICBASW5wdXQoJ3N0YXJ0LWRpc3RhbmNlJykgc3RhcnREaXN0YW5jZTogbnVtYmVyO1xuICBASW5wdXQoJ2Rpc2FibGVkJykgZGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQE91dHB1dCgnZHJhZy1zdGFydCcpIG9uRHJhZ1N0YXJ0ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoJ2RyYWctZW5kJykgb25EcmFnRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIHByaXZhdGUgaXNCZWluZ0RyYWdnZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBjbG9uZU5vZGU6IEhUTUxFbGVtZW50ID0gbnVsbDtcbiAgcHJpdmF0ZSBjdXJyZW50RHJvcFpvbmU6IERyb3B6b25lO1xuICBwcml2YXRlIHBvc3NpYmxlRHJvcFpvbmVzID0gbmV3IE1hcDxFbGVtZW50LCBEcm9wem9uZT4oKTtcbiAgcHJpdmF0ZSBkeDogbnVtYmVyO1xuICBwcml2YXRlIGR5OiBudW1iZXI7XG4gIHB1YmxpYyBveDogbnVtYmVyO1xuICBwdWJsaWMgb3k6IG51bWJlcjtcbiAgcHVibGljIHR4OiBudW1iZXI7XG4gIHB1YmxpYyB0eTogbnVtYmVyO1xuICBwcml2YXRlIGlkUG9pbnRlcjogc3RyaW5nO1xuICBwcml2YXRlIHJvb3Q6IEhUTUxFbGVtZW50O1xuXG4gIGNvbnN0cnVjdG9yKGVsOiBFbGVtZW50UmVmKSB7XG4gICAgdGhpcy5yb290ID0gZWwubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoIWRyYWdEcm9wSW5pdCkge1xuICAgICAgY29uc29sZS5lcnJvcignWW91IHNob3VsZCBhZGQgb25lIGRyYWdkcm9wIGF0dHJpYnV0ZSB0byB5b3VyIGNvZGUgYmVmb3JlIHVzaW5nIGRyYWdnYWJsZScpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIC8vXG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICAvLyBYWFggTm8gc3RvcCBpbiBjYXNlIG9mIHVucGx1ZyB3aGlsZSBkcmFnZ2luZy4uLiA6IC8vIHRoaXMuc3RvcCgpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2Vkb3duJywgWyckZXZlbnQnXSkgb25Nb3VzZURvd24oZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIHRoaXMucHJlc3RhcnQoJ21vdXNlJywgZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcigndG91Y2hzdGFydCcsIFsnJGV2ZW50J10pIG9uVG91Y2hTdGFydChldmVudDogTXlUb3VjaEV2ZW50KSB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBldmVudC5jaGFuZ2VkVG91Y2hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdG91Y2g6IFRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXMuaXRlbShpKTtcbiAgICAgIHRoaXMucHJlc3RhcnQodG91Y2guaWRlbnRpZmllci50b1N0cmluZygpLCB0b3VjaC5jbGllbnRYLCB0b3VjaC5jbGllbnRZKTtcbiAgICB9XG4gIH1cblxuICBwcmVzdGFydChpZFBvaW50ZXI6IHN0cmluZywgeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICBETS5wcmVTdGFydERyYWcoaWRQb2ludGVyLCB4LCB5LCB0aGlzLnN0YXJ0RGVsYXkgfHwgMCwgdGhpcy5zdGFydERpc3RhbmNlIHx8IDEwKS50aGVuKFxuICAgICAgKCkgPT4ge1xuICAgICAgICB0aGlzLnN0YXJ0KGlkUG9pbnRlciwgeCwgeSk7XG4gICAgICB9LFxuICAgICAgKCkgPT4ge1xuICAgICAgICAvLyBjb25zb2xlLmVycm9yKCdza2lwIHRoZSBkcmFnJyk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHN0YXJ0KGlkUG9pbnRlcjogc3RyaW5nLCB4OiBudW1iZXIsIHk6IG51bWJlcikge1xuICAgIGlmICghdGhpcy5pc0JlaW5nRHJhZ2dlZCkge1xuICAgICAgdGhpcy5pc0JlaW5nRHJhZ2dlZCA9IHRydWU7XG4gICAgICB0aGlzLmlkUG9pbnRlciA9IGlkUG9pbnRlcjtcbiAgICAgIGNvbnN0IG9mZnNldCA9IG9mZnNldEVsZW1lbnQodGhpcy5yb290KTtcbiAgICAgIHRoaXMub3ggPSB4OyB0aGlzLm95ID0geTtcbiAgICAgIHRoaXMuZHggPSB4IC0gb2Zmc2V0LmxlZnQ7XG4gICAgICB0aGlzLmR5ID0geSAtIG9mZnNldC50b3A7XG4gICAgICB0aGlzLnR4ID0gdGhpcy5yb290Lm9mZnNldFdpZHRoO1xuICAgICAgdGhpcy50eSA9IHRoaXMucm9vdC5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgIHRoaXMuZ2V0Q2xvbmUoKTtcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLmxlZnQgPSAoeCAtIHRoaXMuZHgpICsgJ3B4JztcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLnRvcCA9ICh5IC0gdGhpcy5keSkgKyAncHgnO1xuICAgICAgdGhpcy5vbkRyYWdTdGFydC5lbWl0KHRoaXMuZHJhZ2dlZERhdGEpO1xuICAgICAgdGhpcy5wb3NzaWJsZURyb3Bab25lcyA9IERNLnN0YXJ0RHJhZyhpZFBvaW50ZXIsIHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHN0b3AoKSB7XG4gICAgdGhpcy5wb3NzaWJsZURyb3Bab25lcy5mb3JFYWNoKGR6ID0+IHtcbiAgICAgIGR6LnJlbW92ZVBvaW50ZXJIb3Zlcih0aGlzLmlkUG9pbnRlcik7XG4gICAgICBkei5yZW1vdmVEcm9wQ2FuZGlkYXRlUG9pbnRlcih0aGlzLmlkUG9pbnRlcik7XG4gICAgfSk7XG4gICAgdGhpcy5pc0JlaW5nRHJhZ2dlZCA9IGZhbHNlO1xuICAgIHRoaXMucG9zc2libGVEcm9wWm9uZXMuY2xlYXIoKTtcbiAgICB0aGlzLmlkUG9pbnRlciA9IG51bGw7XG4gICAgaWYgKHRoaXMuY3VycmVudERyb3Bab25lKSB7XG4gICAgICB0aGlzLmN1cnJlbnREcm9wWm9uZS5kcm9wKHRoaXMuZHJhZ2dlZERhdGEpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnREcm9wWm9uZSA9IG51bGw7XG4gICAgdGhpcy5vbkRyYWdFbmQuZW1pdCh0aGlzLmRyYWdnZWREYXRhKTtcbiAgICB0aGlzLmRlbGV0ZUNsb25lKCk7XG4gIH1cblxuICBtb3ZlKHg6IG51bWJlciwgeTogbnVtYmVyKTogdGhpcyB7XG4gICAgbGV0IGVsZW1lbnQ6IEVsZW1lbnQgPSBudWxsO1xuICAgIGlmICh0aGlzLmNsb25lTm9kZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5nZXRDbG9uZSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jbG9uZU5vZGUpIHtcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLmxlZnQgPSAoeCAtIHRoaXMuZHgpICsgJ3B4JztcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLnRvcCA9ICh5IC0gdGhpcy5keSkgKyAncHgnO1xuICAgICAgY29uc3QgdmlzaWJpbGl0eSA9IHRoaXMuY2xvbmVOb2RlLnN0eWxlLnZpc2liaWxpdHk7XG4gICAgICB0aGlzLmNsb25lTm9kZS5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgICBjb25zdCB0b3AgPSB0aGlzLmNsb25lTm9kZS5zdHlsZS50b3A7XG4gICAgICB0aGlzLmNsb25lTm9kZS5zdHlsZS50b3AgPSAnOTk5OTk5OTk5cHgnO1xuXG4gICAgICBlbGVtZW50ID0gbXlEb2MuZWxlbWVudEZyb21Qb2ludCh4LCB5KTtcblxuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUudG9wID0gdG9wO1xuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUudmlzaWJpbGl0eSA9IHZpc2liaWxpdHk7XG5cbiAgICAgIGNvbnN0IHByZXZEcm9wWm9uZSA9IHRoaXMuY3VycmVudERyb3Bab25lO1xuICAgICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50RHJvcFpvbmUgPSB0aGlzLnBvc3NpYmxlRHJvcFpvbmVzLmdldChlbGVtZW50KTtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudERyb3Bab25lKSB7IGJyZWFrOyB9XG4gICAgICAgIGVsZW1lbnQgPSA8RWxlbWVudD5lbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChwcmV2RHJvcFpvbmUgIT09IHRoaXMuY3VycmVudERyb3Bab25lKSB7XG4gICAgICAgIGlmIChwcmV2RHJvcFpvbmUpIHtcbiAgICAgICAgICBwcmV2RHJvcFpvbmUucmVtb3ZlUG9pbnRlckhvdmVyKHRoaXMuaWRQb2ludGVyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5jdXJyZW50RHJvcFpvbmUpIHtcbiAgICAgICAgICB0aGlzLmN1cnJlbnREcm9wWm9uZS5hcHBlbmRQb2ludGVySG92ZXIodGhpcy5pZFBvaW50ZXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgZGVlcFN0eWxlKG9yaWdpbmFsOiBFbGVtZW50LCBjbG9uZTogRWxlbWVudCkge1xuICAgIGlmIChvcmlnaW5hbCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICBjb25zdCBzdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKG9yaWdpbmFsKTtcblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHlsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBhdHQgPSBzdHlsZVtpXTtcbiAgICAgICAgKGNsb25lIGFzIEhUTUxFbGVtZW50KS5zdHlsZVthdHRdID0gc3R5bGVbYXR0XTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcmlnaW5hbC5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLmRlZXBTdHlsZShvcmlnaW5hbC5jaGlsZHJlbi5pdGVtKGkpLCAoY2xvbmUgYXMgSFRNTEVsZW1lbnQpLmNoaWxkcmVuLml0ZW0oaSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGRlbGV0ZUNsb25lKCkge1xuICAgIGlmICh0aGlzLmNsb25lTm9kZSkge1xuICAgICAgaWYgKHRoaXMuY2xvbmVOb2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgdGhpcy5jbG9uZU5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmNsb25lTm9kZSk7XG4gICAgICB9XG4gICAgICB0aGlzLmNsb25lTm9kZSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgZ2V0Q2xvbmUoKTogSFRNTEVsZW1lbnQge1xuICAgIGlmICh0aGlzLmNsb25lTm9kZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5jbG9uZU5vZGUgPSA8SFRNTEVsZW1lbnQ+dGhpcy5yb290LmNsb25lTm9kZSh0cnVlKTtcbiAgICAgIHRoaXMuZGVlcFN0eWxlKHRoaXMucm9vdCwgdGhpcy5jbG9uZU5vZGUpO1xuXG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuY2xvbmVOb2RlKTtcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLnpJbmRleCA9ICc5OTknO1xuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUubWFyZ2luTGVmdCA9ICcwJztcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLm1hcmdpblRvcCA9ICcwJztcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLm1hcmdpblJpZ2h0ID0gJzAnO1xuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUubWFyZ2luQm90dG9tID0gJzAnO1xuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUub3BhY2l0eSA9ICcnO1xuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUuY3Vyc29yID0gJyc7XG4gICAgICB0aGlzLmNsb25lTm9kZS5zdHlsZS50cmFuc2Zvcm0gPSAnJztcbiAgICAgIHRoaXMuY2xvbmVOb2RlLnN0eWxlLnRyYW5zZm9ybU9yaWdpbiA9ICcnO1xuICAgICAgdGhpcy5jbG9uZU5vZGUuc3R5bGUuYW5pbWF0aW9uID0gJyc7XG4gICAgICB0aGlzLmNsb25lTm9kZS5zdHlsZS50cmFuc2l0aW9uID0gJyc7XG4gICAgICB0aGlzLmNsb25lTm9kZS5jbGFzc0xpc3QuYWRkKCdkcmFnLWFuZC1kcm9wLWNsb25lLW5vZGUnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2xvbmVOb2RlO1xuICB9XG59XG5cbkBEaXJlY3RpdmUoeyBzZWxlY3RvcjogJypbZHJvcHpvbmVdJyB9KVxuZXhwb3J0IGNsYXNzIERyb3B6b25lIGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBuYkRyYWdFbnRlciA9IDA7XG4gIHB1YmxpYyByb290OiBIVE1MRWxlbWVudDtcbiAgQElucHV0KCdkcmFnLWNzcycpIGRyYWdDU1M6IHN0cmluZztcbiAgQElucHV0KCdkcmFnLW92ZXItY3NzJykgZHJhZ092ZXJDU1M6IHN0cmluZztcbiAgQElucHV0KCdkcmFnLW92ZXItY3NzLWZvci1kcmFnZ2FibGUnKSBkcmFnT3ZlckNTU19wb2ludGVyOiBzdHJpbmc7XG4gIEBJbnB1dCgnYWNjZXB0LWZ1bmN0aW9uJykgYWNjZXB0RnVuY3Rpb246IChkYXRhOiBhbnkpID0+IGJvb2xlYW47XG4gIEBPdXRwdXQoJ29uZHJvcCcpIG9uRHJvcEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgnZHJhZy1zdGFydCcpIG9uRHJhZ1N0YXJ0ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoJ2RyYWctZW5kJykgb25EcmFnRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoJ2RyYWctZW50ZXInKSBvbkRyYWdFbnRlciA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICBAT3V0cHV0KCdkcmFnLWxlYXZlJykgb25EcmFnTGVhdmUgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBwcml2YXRlIGRyb3BDYW5kaWRhdGVvZlBvaW50ZXJzOiBBcnJheTxzdHJpbmc+ID0gW107XG4gIHByaXZhdGUgcG9pbnRlcnNIb3ZlcjogQXJyYXk8c3RyaW5nPiA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKGVsOiBFbGVtZW50UmVmKSB7XG4gICAgaWYgKCFkcmFnRHJvcEluaXQpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1lvdSBzaG91bGQgYWRkIG9uZSBkcmFnZHJvcCBhdHRyaWJ1dGUgdG8geW91ciBjb2RlIGJlZm9yZSB1c2luZyBkcm9wem9uZScpO1xuICAgIH1cbiAgICB0aGlzLnJvb3QgPSBlbC5uYXRpdmVFbGVtZW50O1xuICAgIERNLnJlZ2lzdGVyRHJvcFpvbmUodGhpcyk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICAvL1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgRE0udW5yZWdpc3RlckRyb3Bab25lKHRoaXMpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ2VudGVyJywgWyckZXZlbnQnXSkgQnJvd3NlckRyYWdFbnRlcihldmVudDogTW91c2VFdmVudCkge1xuICAgIHRoaXMubmJEcmFnRW50ZXIrKztcbiAgICBpZiAodGhpcy5uYkRyYWdFbnRlciA9PT0gMSkge1xuICAgICAgdGhpcy5hcHBlbmRQb2ludGVySG92ZXIoZHJhZ1BvaW50ZXJJZCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ2xlYXZlJywgWyckZXZlbnQnXSkgQnJvd3NlckRyYWdMZWF2ZShldmVudDogTW91c2VFdmVudCkge1xuICAgIHRoaXMubmJEcmFnRW50ZXItLTtcbiAgICBpZiAodGhpcy5uYkRyYWdFbnRlciA9PT0gMCkge1xuICAgICAgdGhpcy5yZW1vdmVQb2ludGVySG92ZXIoZHJhZ1BvaW50ZXJJZCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJvcCcsIFsnJGV2ZW50J10pIEJyb3dzZXJEcm9wKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgRE0ucG9pbnRlclJlbGVhc2UoZHJhZ1BvaW50ZXJJZCk7XG4gICAgdGhpcy5uYkRyYWdFbnRlciA9IDA7XG4gICAgdGhpcy5vbkRyb3BFbWl0dGVyLmVtaXQoZXZlbnQpO1xuICB9XG5cbiAgZHJvcChvYmopIHtcbiAgICB0aGlzLm9uRHJvcEVtaXR0ZXIuZW1pdChvYmopO1xuICB9XG5cbiAgY2hlY2tBY2NlcHQoZHJhZzogRHJhZ2dhYmxlIHwgRHJhZ0V2ZW50KTogYm9vbGVhbiB7XG4gICAgbGV0IHJlczogYm9vbGVhbjtcbiAgICBpZiAoZHJhZyBpbnN0YW5jZW9mIERyYWdnYWJsZSkge1xuICAgICAgcmVzID0gdGhpcy5hY2NlcHRGdW5jdGlvbiA/IHRoaXMuYWNjZXB0RnVuY3Rpb24oZHJhZy5kcmFnZ2VkRGF0YSkgOiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXMgPSB0aGlzLmFjY2VwdEZ1bmN0aW9uID8gdGhpcy5hY2NlcHRGdW5jdGlvbihkcmFnKSA6IHRydWU7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICBoYXNQb2ludGVySG92ZXIoaWRQb2ludGVyOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5wb2ludGVyc0hvdmVyLmluZGV4T2YoaWRQb2ludGVyKSA+PSAwO1xuICB9XG5cbiAgYXBwZW5kUG9pbnRlckhvdmVyKGlkUG9pbnRlcjogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMucG9pbnRlcnNIb3Zlci5pbmRleE9mKGlkUG9pbnRlcikgPT09IC0xKSB7XG4gICAgICBjb25zdCBkcmFnZ2VkID0gRE0uZHJhZ2dlZFN0cnVjdHVyZXMuZ2V0KGlkUG9pbnRlcik7XG4gICAgICB0aGlzLnBvaW50ZXJzSG92ZXIucHVzaChpZFBvaW50ZXIpO1xuICAgICAgaWYgKGRyYWdnZWQgaW5zdGFuY2VvZiBEcmFnZ2FibGUpIHtcbiAgICAgICAgaWYgKHRoaXMuZHJhZ092ZXJDU1NfcG9pbnRlcikge1xuICAgICAgICAgIGRyYWdnZWQuZ2V0Q2xvbmUoKS5jbGFzc0xpc3QuYWRkKHRoaXMuZHJhZ092ZXJDU1NfcG9pbnRlcik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbkRyYWdFbnRlci5lbWl0KGRyYWdnZWQuZHJhZ2dlZERhdGEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5vbkRyYWdFbnRlci5lbWl0KGRyYWdnZWQpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuZHJhZ092ZXJDU1MpIHtcbiAgICAgICAgdGhpcy5yb290LmNsYXNzTGlzdC5hZGQodGhpcy5kcmFnT3ZlckNTUyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmVtb3ZlUG9pbnRlckhvdmVyKGlkUG9pbnRlcjogc3RyaW5nKSB7XG4gICAgY29uc3QgcG9zID0gdGhpcy5wb2ludGVyc0hvdmVyLmluZGV4T2YoaWRQb2ludGVyKTtcbiAgICBpZiAocG9zID49IDApIHtcbiAgICAgIGNvbnN0IGRyYWdnZWQgPSBETS5kcmFnZ2VkU3RydWN0dXJlcy5nZXQoaWRQb2ludGVyKTtcbiAgICAgIHRoaXMucG9pbnRlcnNIb3Zlci5zcGxpY2UocG9zLCAxKTtcbiAgICAgIGlmIChkcmFnZ2VkIGluc3RhbmNlb2YgRHJhZ2dhYmxlKSB7XG4gICAgICAgIGlmICh0aGlzLmRyYWdPdmVyQ1NTX3BvaW50ZXIpIHtcbiAgICAgICAgICBkcmFnZ2VkLmdldENsb25lKCkuY2xhc3NMaXN0LnJlbW92ZSh0aGlzLmRyYWdPdmVyQ1NTX3BvaW50ZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub25EcmFnTGVhdmUuZW1pdChkcmFnZ2VkLmRyYWdnZWREYXRhKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMub25EcmFnTGVhdmUuZW1pdChkcmFnZ2VkKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnBvaW50ZXJzSG92ZXIubGVuZ3RoID09PSAwICYmIHRoaXMuZHJhZ092ZXJDU1MpIHtcbiAgICAgICAgdGhpcy5yb290LmNsYXNzTGlzdC5yZW1vdmUodGhpcy5kcmFnT3ZlckNTUyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXBwZW5kRHJvcENhbmRpZGF0ZVBvaW50ZXIoaWRQb2ludGVyOiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5kcm9wQ2FuZGlkYXRlb2ZQb2ludGVycy5pbmRleE9mKGlkUG9pbnRlcikgPT09IC0xKSB7XG4gICAgICBjb25zdCBkcmFnZ2VkID0gRE0uZHJhZ2dlZFN0cnVjdHVyZXMuZ2V0KGlkUG9pbnRlcik7XG4gICAgICBpZiAoZHJhZ2dlZCBpbnN0YW5jZW9mIERyYWdnYWJsZSkge1xuICAgICAgICB0aGlzLm9uRHJhZ1N0YXJ0LmVtaXQoZHJhZ2dlZC5kcmFnZ2VkRGF0YSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9uRHJhZ1N0YXJ0LmVtaXQoZHJhZ2dlZCk7XG4gICAgICB9XG4gICAgICB0aGlzLmRyb3BDYW5kaWRhdGVvZlBvaW50ZXJzLnB1c2goaWRQb2ludGVyKTtcbiAgICAgIGlmICh0aGlzLmRyYWdDU1MpIHtcbiAgICAgICAgdGhpcy5yb290LmNsYXNzTGlzdC5hZGQodGhpcy5kcmFnQ1NTKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZW1vdmVEcm9wQ2FuZGlkYXRlUG9pbnRlcihpZFBvaW50ZXI6IHN0cmluZykge1xuICAgIGNvbnN0IHBvcyA9IHRoaXMuZHJvcENhbmRpZGF0ZW9mUG9pbnRlcnMuaW5kZXhPZihpZFBvaW50ZXIpO1xuICAgIGlmIChwb3MgPj0gMCkge1xuICAgICAgY29uc3QgZHJhZ2dlZCA9IERNLmRyYWdnZWRTdHJ1Y3R1cmVzLmdldChpZFBvaW50ZXIpO1xuICAgICAgaWYgKGRyYWdnZWQgaW5zdGFuY2VvZiBEcmFnZ2FibGUpIHtcbiAgICAgICAgdGhpcy5vbkRyYWdFbmQuZW1pdChkcmFnZ2VkLmRyYWdnZWREYXRhKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMub25EcmFnRW5kLmVtaXQoZHJhZ2dlZCk7XG4gICAgICB9XG4gICAgICB0aGlzLmRyb3BDYW5kaWRhdGVvZlBvaW50ZXJzLnNwbGljZShwb3MsIDEpO1xuICAgICAgaWYgKHRoaXMuZHJvcENhbmRpZGF0ZW9mUG9pbnRlcnMubGVuZ3RoID09PSAwICYmIHRoaXMuZHJhZ0NTUykge1xuICAgICAgICB0aGlzLnJvb3QuY2xhc3NMaXN0LnJlbW92ZSh0aGlzLmRyYWdDU1MpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19