angular-gallery
Version:
Responsive gallery for Angular with touch screen support.
324 lines • 41.6 kB
JavaScript
export class Touches {
constructor(properties) {
this.eventType = undefined;
this.handlers = {};
this.startX = 0;
this.startY = 0;
this.lastTap = 0;
this.doubleTapMinTimeout = 300;
this.tapMinTimeout = 200;
this.touchstartTime = 0;
this.i = 0;
this.isMousedown = false;
this.touchListeners = {
"touchstart": "handleTouchstart",
"touchmove": "handleTouchmove",
"touchend": "handleTouchend"
};
this.mouseListeners = {
"mousedown": "handleMousedown",
"mousemove": "handleMousemove",
"mouseup": "handleMouseup",
"wheel": "handleWheel"
};
this.otherListeners = {
"resize": "handleResize"
};
/*
* Listeners
*/
/* Touchstart */
this.handleTouchstart = (event) => {
this.elementPosition = this.getElementPosition();
this.touchstartTime = new Date().getTime();
if (this.eventType === undefined) {
this.getTouchstartPosition(event);
}
this.runHandler("touchstart", event);
};
/* Touchmove */
this.handleTouchmove = (event) => {
const touches = event.touches;
// Pan
if (this.detectPan(touches)) {
this.runHandler("pan", event);
}
// Pinch
if (this.detectPinch(event)) {
this.runHandler("pinch", event);
}
// Linear swipe
switch (this.detectLinearSwipe(event)) {
case "horizontal-swipe":
event.swipeType = "horizontal-swipe";
this.runHandler("horizontal-swipe", event);
break;
case "vertical-swipe":
event.swipeType = "vertical-swipe";
this.runHandler("vertical-swipe", event);
break;
}
// Linear swipe
if (this.detectLinearSwipe(event) ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
this.handleLinearSwipe(event);
}
};
/* Touchend */
this.handleTouchend = (event) => {
const touches = event.touches;
// Double Tap
if (this.detectDoubleTap()) {
this.runHandler("double-tap", event);
}
// Tap
this.detectTap();
this.runHandler("touchend", event);
this.eventType = 'touchend';
if (touches && touches.length === 0) {
this.eventType = undefined;
this.i = 0;
}
};
/* Mousedown */
this.handleMousedown = (event) => {
this.isMousedown = true;
this.elementPosition = this.getElementPosition();
this.touchstartTime = new Date().getTime();
if (this.eventType === undefined) {
this.getMousedownPosition(event);
}
this.runHandler("mousedown", event);
};
/* Mousemove */
this.handleMousemove = (event) => {
//event.preventDefault();
if (!this.isMousedown) {
return;
}
// Pan
this.runHandler("pan", event);
// Linear swipe
switch (this.detectLinearSwipe(event)) {
case "horizontal-swipe":
event.swipeType = "horizontal-swipe";
this.runHandler("horizontal-swipe", event);
break;
case "vertical-swipe":
event.swipeType = "vertical-swipe";
this.runHandler("vertical-swipe", event);
break;
}
// Linear swipe
if (this.detectLinearSwipe(event) ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
this.handleLinearSwipe(event);
}
};
/* Mouseup */
this.handleMouseup = (event) => {
// Tap
this.detectTap();
this.isMousedown = false;
this.runHandler("mouseup", event);
this.eventType = undefined;
this.i = 0;
};
/* Wheel */
this.handleWheel = (event) => {
this.runHandler("wheel", event);
};
/* Resize */
this.handleResize = (event) => {
this.runHandler("resize", event);
};
this.properties = properties;
this.element = this.properties.element;
this.elementPosition = this.getElementPosition();
this.toggleEventListeners('addEventListener');
}
destroy() {
this.toggleEventListeners('removeEventListener');
}
toggleEventListeners(action) {
let listeners;
if (this.properties.listeners === 'mouse and touch') {
listeners = Object.assign(this.touchListeners, this.mouseListeners);
}
else {
listeners = this.detectTouchScreen() ? this.touchListeners : this.mouseListeners;
}
if (this.properties.resize) {
listeners = Object.assign(listeners, this.otherListeners);
}
for (var listener in listeners) {
const handler = listeners[listener];
// Window
if (listener === "resize") {
if (action === 'addEventListener') {
window.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
window.removeEventListener(listener, this[handler], false);
}
// Document
}
else if (listener === 'mouseup' || listener === "mousemove") {
if (action === 'addEventListener') {
document.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
document.removeEventListener(listener, this[handler], false);
}
// Element
}
else {
if (action === 'addEventListener') {
this.element.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
this.element.removeEventListener(listener, this[handler], false);
}
}
}
}
handleLinearSwipe(event) {
//event.preventDefault();
this.i++;
if (this.i > 3) {
this.eventType = this.getLinearSwipeType(event);
}
if (this.eventType === 'horizontal-swipe') {
this.runHandler('horizontal-swipe', event);
}
if (this.eventType === 'vertical-swipe') {
this.runHandler('vertical-swipe', event);
}
}
runHandler(eventName, response) {
if (this.handlers[eventName]) {
this.handlers[eventName](response);
}
}
/*
* Detection
*/
detectPan(touches) {
return touches.length === 1 && !this.eventType || this.eventType === 'pan';
}
detectDoubleTap() {
if (this.eventType != undefined) {
return;
}
const currentTime = new Date().getTime();
const tapLength = currentTime - this.lastTap;
clearTimeout(this.doubleTapTimeout);
if (tapLength < this.doubleTapMinTimeout && tapLength > 0) {
return true;
}
else {
this.doubleTapTimeout = setTimeout(() => {
clearTimeout(this.doubleTapTimeout);
}, this.doubleTapMinTimeout);
}
this.lastTap = currentTime;
}
detectTap() {
if (this.eventType != undefined) {
return;
}
const currentTime = new Date().getTime();
const tapLength = currentTime - this.touchstartTime;
if (tapLength > 0) {
if (tapLength < this.tapMinTimeout) {
this.runHandler("tap", event);
}
else {
this.runHandler("longtap", event);
}
}
}
detectPinch(event) {
const touches = event.touches;
return (touches.length === 2 && this.eventType === undefined) || this.eventType === 'pinch';
}
detectLinearSwipe(event) {
const touches = event.touches;
if (touches) {
if (touches.length === 1 && !this.eventType || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
return this.getLinearSwipeType(event);
}
}
else {
if (!this.eventType || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
return this.getLinearSwipeType(event);
}
}
}
getLinearSwipeType(event) {
if (this.eventType !== 'horizontal-swipe' && this.eventType !== 'vertical-swipe') {
const movementX = Math.abs(this.moveLeft(0, event) - this.startX);
const movementY = Math.abs(this.moveTop(0, event) - this.startY);
if ((movementY * 3) > movementX) {
return 'vertical-swipe';
}
else {
return 'horizontal-swipe';
}
}
else {
return this.eventType;
}
}
getElementPosition() {
return this.element.getBoundingClientRect();
}
getTouchstartPosition(event) {
this.startX = event.touches[0].clientX - this.elementPosition.left;
this.startY = event.touches[0].clientY - this.elementPosition.top;
}
getMousedownPosition(event) {
this.startX = event.clientX - this.elementPosition.left;
this.startY = event.clientY - this.elementPosition.top;
}
moveLeft(index, event) {
const touches = event.touches;
if (touches) {
return touches[index].clientX - this.elementPosition.left;
}
else {
return event.clientX - this.elementPosition.left;
}
}
moveTop(index, event) {
const touches = event.touches;
if (touches) {
return touches[index].clientY - this.elementPosition.top;
}
else {
return event.clientY - this.elementPosition.top;
}
}
detectTouchScreen() {
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var mq = function (query) {
return window.matchMedia(query).matches;
};
if (('ontouchstart' in window)) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
return mq(query);
}
/* Public properties and methods */
on(event, handler) {
if (event) {
this.handlers[event] = handler;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG91Y2hlcy5qcyIsInNvdXJjZVJvb3QiOiJuZzovL2FuZ3VsYXItZ2FsbGVyeS8iLCJzb3VyY2VzIjpbImxpYi90b3VjaGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVVBLE1BQU0sT0FBTyxPQUFPO0lBK0JoQixZQUFZLFVBQXNCO1FBM0JsQyxjQUFTLEdBQWMsU0FBUyxDQUFDO1FBQ2pDLGFBQVEsR0FBUSxFQUFFLENBQUM7UUFDbkIsV0FBTSxHQUFHLENBQUMsQ0FBQztRQUNYLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFDWCxZQUFPLEdBQUcsQ0FBQyxDQUFDO1FBRVosd0JBQW1CLEdBQUcsR0FBRyxDQUFDO1FBQzFCLGtCQUFhLEdBQUcsR0FBRyxDQUFDO1FBQ3BCLG1CQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLE1BQUMsR0FBVyxDQUFDLENBQUM7UUFDZCxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUVwQixtQkFBYyxHQUFRO1lBQ2xCLFlBQVksRUFBRSxrQkFBa0I7WUFDaEMsV0FBVyxFQUFFLGlCQUFpQjtZQUM5QixVQUFVLEVBQUUsZ0JBQWdCO1NBQy9CLENBQUE7UUFDRCxtQkFBYyxHQUFRO1lBQ2xCLFdBQVcsRUFBRSxpQkFBaUI7WUFDOUIsV0FBVyxFQUFFLGlCQUFpQjtZQUM5QixTQUFTLEVBQUUsZUFBZTtZQUMxQixPQUFPLEVBQUUsYUFBYTtTQUN6QixDQUFBO1FBQ0QsbUJBQWMsR0FBUTtZQUNsQixRQUFRLEVBQUUsY0FBYztTQUMzQixDQUFBO1FBMEREOztXQUVHO1FBRUgsZ0JBQWdCO1FBRWhCLHFCQUFnQixHQUFHLENBQUMsS0FBVSxFQUFFLEVBQUU7WUFDOUIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUNqRCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7WUFFM0MsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsRUFBRTtn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LElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDO1NBQzVEO2FBQU07WUFDSCxPQUFPLEtBQUssQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUM7U0FDbkQ7SUFDTCxDQUFDO0lBRUQsaUJBQWlCO1FBQ2IsSUFBSSxRQUFRLEdBQUcsMkJBQTJCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3RELElBQUksRUFBRSxHQUFHLFVBQVMsS0FBVTtZQUN4QixPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzVDLENBQUMsQ0FBQTtRQUVELElBQUksQ0FBQyxjQUFjLElBQUksTUFBTSxDQUFDLEVBQUU7WUFDNUIsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELHFGQUFxRjtRQUNyRix1QkFBdUI7UUFDdkIsSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0UsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUdELG1DQUFtQztJQUNuQyxFQUFFLENBQUMsS0FBZ0IsRUFBRSxPQUFpQjtRQUNsQyxJQUFJLEtBQUssRUFBRTtZQUNQLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDO1NBQ2xDO0lBQ0wsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGludGVyZmFjZSBQcm9wZXJ0aWVzIHtcclxuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xyXG4gICAgbGlzdGVuZXJzPzogJ2F1dG8nIHwgJ21vdXNlIGFuZCB0b3VjaCc7XHJcbiAgICByZXNpemU/OiBib29sZWFuO1xyXG59XHJcblxyXG5leHBvcnQgdHlwZSBFdmVudFR5cGUgPSB1bmRlZmluZWQgfCAndG91Y2hlbmQnIHwgJ3BhbicgfCAncGluY2gnIHwgJ2hvcml6b250YWwtc3dpcGUnIHwgJ3ZlcnRpY2FsLXN3aXBlJyB8ICd0YXAnIHwgJ2xvbmd0YXAnO1xyXG5leHBvcnQgdHlwZSBUb3VjaEhhbmRsZXIgPSAnaGFuZGxlVG91Y2hzdGFydCcgfCAnaGFuZGxlVG91Y2htb3ZlJyB8ICdoYW5kbGVUb3VjaGVuZCc7XHJcbmV4cG9ydCB0eXBlIE1vdXNlSGFuZGxlciA9ICdoYW5kbGVNb3VzZWRvd24nIHwgJ2hhbmRsZU1vdXNlbW92ZScgfCAnaGFuZGxlTW91c2V1cCc7XHJcblxyXG5leHBvcnQgY2xhc3MgVG91Y2hlcyB7XHJcbiAgICBwcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzO1xyXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQ7XHJcbiAgICBlbGVtZW50UG9zaXRpb246IENsaWVudFJlY3Q7XHJcbiAgICBldmVudFR5cGU6IEV2ZW50VHlwZSA9IHVuZGVmaW5lZDtcclxuICAgIGhhbmRsZXJzOiBhbnkgPSB7fTtcclxuICAgIHN0YXJ0WCA9IDA7XHJcbiAgICBzdGFydFkgPSAwO1xyXG4gICAgbGFzdFRhcCA9IDA7XHJcbiAgICBkb3VibGVUYXBUaW1lb3V0OiBhbnk7XHJcbiAgICBkb3VibGVUYXBNaW5UaW1lb3V0ID0gMzAwO1xyXG4gICAgdGFwTWluVGltZW91dCA9IDIwMDtcclxuICAgIHRvdWNoc3RhcnRUaW1lID0gMDtcclxuICAgIGk6IG51bWJlciA9IDA7XHJcbiAgICBpc01vdXNlZG93biA9IGZhbHNlO1xyXG5cclxuICAgIHRvdWNoTGlzdGVuZXJzOiBhbnkgPSB7XHJcbiAgICAgICAgXCJ0b3VjaHN0YXJ0XCI6IFwiaGFuZGxlVG91Y2hzdGFydFwiLFxyXG4gICAgICAgIFwidG91Y2htb3ZlXCI6IFwiaGFuZGxlVG91Y2htb3ZlXCIsXHJcbiAgICAgICAgXCJ0b3VjaGVuZFwiOiBcImhhbmRsZVRvdWNoZW5kXCJcclxuICAgIH1cclxuICAgIG1vdXNlTGlzdGVuZXJzOiBhbnkgPSB7XHJcbiAgICAgICAgXCJtb3VzZWRvd25cIjogXCJoYW5kbGVNb3VzZWRvd25cIixcclxuICAgICAgICBcIm1vdXNlbW92ZVwiOiBcImhhbmRsZU1vdXNlbW92ZVwiLFxyXG4gICAgICAgIFwibW91c2V1cFwiOiBcImhhbmRsZU1vdXNldXBcIixcclxuICAgICAgICBcIndoZWVsXCI6IFwiaGFuZGxlV2hlZWxcIlxyXG4gICAgfVxyXG4gICAgb3RoZXJMaXN0ZW5lcnM6IGFueSA9IHtcclxuICAgICAgICBcInJlc2l6ZVwiOiBcImhhbmRsZVJlc2l6ZVwiXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJvcGVydGllczogUHJvcGVydGllcykge1xyXG4gICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7XHJcbiAgICAgICAgdGhpcy5lbGVtZW50ID0gdGhpcy5wcm9wZXJ0aWVzLmVsZW1lbnQ7XHJcbiAgICAgICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbigpO1xyXG5cclxuICAgICAgICB0aGlzLnRvZ2dsZUV2ZW50TGlzdGVuZXJzKCdhZGRFdmVudExpc3RlbmVyJyk7XHJcbiAgICB9XHJcblxyXG4gICAgZGVzdHJveSgpIHtcclxuICAgICAgICB0aGlzLnRvZ2dsZUV2ZW50TGlzdGVuZXJzKCdyZW1vdmVFdmVudExpc3RlbmVyJyk7XHJcbiAgICB9XHJcblxyXG4gICAgdG9nZ2xlRXZlbnRMaXN0ZW5lcnMoYWN0aW9uOiAnYWRkRXZlbnRMaXN0ZW5lcicgfCAncmVtb3ZlRXZlbnRMaXN0ZW5lcicpIHtcclxuICAgICAgICBsZXQgbGlzdGVuZXJzO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzLmxpc3RlbmVycyA9PT0gJ21vdXNlIGFuZCB0b3VjaCcpIHtcclxuICAgICAgICAgICAgbGlzdGVuZXJzID0gT2JqZWN0LmFzc2lnbih0aGlzLnRvdWNoTGlzdGVuZXJzLCB0aGlzLm1vdXNlTGlzdGVuZXJzKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSB0aGlzLmRldGVjdFRvdWNoU2NyZWVuKCkgPyB0aGlzLnRvdWNoTGlzdGVuZXJzIDogdGhpcy5tb3VzZUxpc3RlbmVycztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnByb3BlcnRpZXMucmVzaXplKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IE9iamVjdC5hc3NpZ24obGlzdGVuZXJzLCB0aGlzLm90aGVyTGlzdGVuZXJzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAodmFyIGxpc3RlbmVyIGluIGxpc3RlbmVycykge1xyXG4gICAgICAgICAgICBjb25zdCBoYW5kbGVyOiBNb3VzZUhhbmRsZXIgPSBsaXN0ZW5lcnNbbGlzdGVuZXJdO1xyXG5cclxuICAgICAgICAgICAgLy8gV2luZG93XHJcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lciA9PT0gXCJyZXNpemVcIikge1xyXG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ2FkZEV2ZW50TGlzdGVuZXInKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIobGlzdGVuZXIsIHRoaXNbaGFuZGxlcl0sIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChhY3Rpb24gPT09ICdyZW1vdmVFdmVudExpc3RlbmVyJykge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIERvY3VtZW50XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGlzdGVuZXIgPT09ICdtb3VzZXVwJyB8fCBsaXN0ZW5lciA9PT0gXCJtb3VzZW1vdmVcIikge1xyXG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ2FkZEV2ZW50TGlzdGVuZXInKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ3JlbW92ZUV2ZW50TGlzdGVuZXInKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBFbGVtZW50XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uID09PSAnYWRkRXZlbnRMaXN0ZW5lcicpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ3JlbW92ZUV2ZW50TGlzdGVuZXInKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIobGlzdGVuZXIsIHRoaXNbaGFuZGxlcl0sIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKlxyXG4gICAgICogTGlzdGVuZXJzXHJcbiAgICAgKi9cclxuXHJcbiAgICAvKiBUb3VjaHN0YXJ0ICovXHJcblxyXG4gICAgaGFuZGxlVG91Y2hzdGFydCA9IChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbigpO1xyXG4gICAgICAgIHRoaXMudG91Y2hzdGFydFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRUeXBlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5nZXRUb3VjaHN0YXJ0UG9zaXRpb24oZXZlbnQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwidG91Y2hzdGFydFwiLCBldmVudCk7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIC8qIFRvdWNobW92ZSAqL1xyXG5cclxuICAgIGhhbmRsZVRvdWNobW92ZSA9IChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgY29uc3QgdG91Y2hlcyA9IGV2ZW50LnRvdWNoZXM7XHJcblxyXG4gICAgICAgIC8vIFBhblxyXG4gICAgICAgIGlmICh0aGlzLmRldGVjdFBhbih0b3VjaGVzKSkge1xyXG4gICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJwYW5cIiwgZXZlbnQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUGluY2hcclxuICAgICAgICBpZiAodGhpcy5kZXRlY3RQaW5jaChldmVudCkpIHtcclxuICAgICAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwicGluY2hcIiwgZXZlbnQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gTGluZWFyIHN3aXBlXHJcbiAgICAgICAgc3dpdGNoICh0aGlzLmRldGVjdExpbmVhclN3aXBlKGV2ZW50KSkge1xyXG4gICAgICAgICAgICBjYXNlIFwiaG9yaXpvbnRhbC1zd2lwZVwiOlxyXG4gICAgICAgICAgICAgICAgZXZlbnQuc3dpcGVUeXBlID0gXCJob3Jpem9udGFsLXN3aXBlXCI7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJob3Jpem9udGFsLXN3aXBlXCIsIGV2ZW50KTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFwidmVydGljYWwtc3dpcGVcIjpcclxuICAgICAgICAgICAgICAgIGV2ZW50LnN3aXBlVHlwZSA9IFwidmVydGljYWwtc3dpcGVcIjtcclxuICAgICAgICAgICAgICAgIHRoaXMucnVuSGFuZGxlcihcInZlcnRpY2FsLXN3aXBlXCIsIGV2ZW50KTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gTGluZWFyIHN3aXBlXHJcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQpIHx8XHJcbiAgICAgICAgICAgIHRoaXMuZXZlbnRUeXBlID09PSAnaG9yaXpvbnRhbC1zd2lwZScgfHxcclxuICAgICAgICAgICAgdGhpcy5ldmVudFR5cGUgPT09ICd2ZXJ0aWNhbC1zd2lwZScpIHtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlTGluZWFyU3dpcGUoZXZlbnQpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBoYW5kbGVMaW5lYXJTd2lwZShldmVudDogYW55KSB7XHJcbiAgICAgICAgLy9ldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgICAgICB0aGlzLmkrKztcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuaSA+IDMpIHtcclxuICAgICAgICAgICAgdGhpcy5ldmVudFR5cGUgPSB0aGlzLmdldExpbmVhclN3aXBlVHlwZShldmVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5ldmVudFR5cGUgPT09ICdob3Jpem9udGFsLXN3aXBlJykge1xyXG4gICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoJ2hvcml6b250YWwtc3dpcGUnLCBldmVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5ldmVudFR5cGUgPT09ICd2ZXJ0aWNhbC1zd2lwZScpIHtcclxuICAgICAgICAgICAgdGhpcy5ydW5IYW5kbGVyKCd2ZXJ0aWNhbC1zd2lwZScsIGV2ZW50KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG5cclxuICAgIC8qIFRvdWNoZW5kICovXHJcblxyXG4gICAgaGFuZGxlVG91Y2hlbmQgPSAoZXZlbnQ6IGFueSkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHRvdWNoZXMgPSBldmVudC50b3VjaGVzO1xyXG5cclxuICAgICAgICAvLyBEb3VibGUgVGFwXHJcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0RG91YmxlVGFwKCkpIHtcclxuICAgICAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwiZG91YmxlLXRhcFwiLCBldmVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBUYXBcclxuICAgICAgICB0aGlzLmRldGVjdFRhcCgpO1xyXG5cclxuICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJ0b3VjaGVuZFwiLCBldmVudCk7XHJcbiAgICAgICAgdGhpcy5ldmVudFR5cGUgPSAndG91Y2hlbmQnO1xyXG5cclxuICAgICAgICBpZiAodG91Y2hlcyAmJiB0b3VjaGVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmV2ZW50VHlwZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgdGhpcy5pID0gMDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG5cclxuICAgIC8qIE1vdXNlZG93biAqL1xyXG5cclxuICAgIGhhbmRsZU1vdXNlZG93biA9IChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5pc01vdXNlZG93biA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbigpO1xyXG4gICAgICAgIHRoaXMudG91Y2hzdGFydFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRUeXBlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5nZXRNb3VzZWRvd25Qb3NpdGlvbihldmVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJtb3VzZWRvd25cIiwgZXZlbnQpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvKiBNb3VzZW1vdmUgKi9cclxuXHJcbiAgICBoYW5kbGVNb3VzZW1vdmUgPSAoZXZlbnQ6IGFueSkgPT4ge1xyXG4gICAgICAgIC8vZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBcclxuICAgICAgICBpZiAoIXRoaXMuaXNNb3VzZWRvd24pIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUGFuXHJcbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwicGFuXCIsIGV2ZW50KTtcclxuXHJcbiAgICAgICAgLy8gTGluZWFyIHN3aXBlXHJcbiAgICAgICAgc3dpdGNoICh0aGlzLmRldGVjdExpbmVhclN3aXBlKGV2ZW50KSkge1xyXG4gICAgICAgICAgICBjYXNlIFwiaG9yaXpvbnRhbC1zd2lwZVwiOlxyXG4gICAgICAgICAgICAgICAgZXZlbnQuc3dpcGVUeXBlID0gXCJob3Jpem9udGFsLXN3aXBlXCI7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJob3Jpem9udGFsLXN3aXBlXCIsIGV2ZW50KTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFwidmVydGljYWwtc3dpcGVcIjpcclxuICAgICAgICAgICAgICAgIGV2ZW50LnN3aXBlVHlwZSA9IFwidmVydGljYWwtc3dpcGVcIjtcclxuICAgICAgICAgICAgICAgIHRoaXMucnVuSGFuZGxlcihcInZlcnRpY2FsLXN3aXBlXCIsIGV2ZW50KTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gTGluZWFyIHN3aXBlXHJcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQpIHx8XHJcbiAgICAgICAgICAgIHRoaXMuZXZlbnRUeXBlID09PSAnaG9yaXpvbnRhbC1zd2lwZScgfHxcclxuICAgICAgICAgICAgdGhpcy5ldmVudFR5cGUgPT09ICd2ZXJ0aWNhbC1zd2lwZScpIHtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlTGluZWFyU3dpcGUoZXZlbnQpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcblxyXG4gICAgLyogTW91c2V1cCAqL1xyXG5cclxuICAgIGhhbmRsZU1vdXNldXAgPSAoZXZlbnQ6IGFueSkgPT4ge1xyXG5cclxuICAgICAgICAvLyBUYXBcclxuICAgICAgICB0aGlzLmRldGVjdFRhcCgpO1xyXG5cclxuICAgICAgICB0aGlzLmlzTW91c2Vkb3duID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwibW91c2V1cFwiLCBldmVudCk7XHJcbiAgICAgICAgdGhpcy5ldmVudFR5cGUgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgdGhpcy5pID0gMDtcclxuICAgIH1cclxuXHJcblxyXG4gICAgLyogV2hlZWwgKi9cclxuXHJcbiAgICBoYW5kbGVXaGVlbCA9IChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwid2hlZWxcIiwgZXZlbnQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qIFJlc2l6ZSAqL1xyXG5cclxuICAgIGhhbmRsZVJlc2l6ZSA9IChldmVudDogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwicmVzaXplXCIsIGV2ZW50KTtcclxuICAgIH1cclxuXHJcbiAgICBydW5IYW5kbGVyKGV2ZW50TmFtZTogYW55LCByZXNwb25zZTogYW55KSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaGFuZGxlcnNbZXZlbnROYW1lXSkge1xyXG4gICAgICAgICAgICB0aGlzLmhhbmRsZXJzW2V2ZW50TmFtZV0ocmVzcG9uc2UpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcblxyXG4gICAgLypcclxuICAgICAqIERldGVjdGlvblxyXG4gICAgICovXHJcblxyXG4gICAgZGV0ZWN0UGFuKHRvdWNoZXM6IGFueSkge1xyXG4gICAgICAgIHJldHVybiB0b3VjaGVzLmxlbmd0aCA9PT0gMSAmJiAhdGhpcy5ldmVudFR5cGUgfHwgdGhpcy5ldmVudFR5cGUgPT09ICdwYW4nO1xyXG4gICAgfVxyXG5cclxuICAgIGRldGVjdERvdWJsZVRhcCgpIHtcclxuICAgICAgICBpZiAodGhpcy5ldmVudFR5cGUgIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XHJcbiAgICAgICAgY29uc3QgdGFwTGVuZ3RoID0gY3VycmVudFRpbWUgLSB0aGlzLmxhc3RUYXA7XHJcblxyXG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLmRvdWJsZVRhcFRpbWVvdXQpO1xyXG5cclxuICAgICAgICBpZiAodGFwTGVuZ3RoIDwgdGhpcy5kb3VibGVUYXBNaW5UaW1lb3V0ICYmIHRhcExlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5kb3VibGVUYXBUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5kb3VibGVUYXBUaW1lb3V0KTtcclxuICAgICAgICAgICAgfSwgdGhpcy5kb3VibGVUYXBNaW5UaW1lb3V0KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5sYXN0VGFwID0gY3VycmVudFRpbWU7XHJcbiAgICB9XHJcblxyXG4gICAgZGV0ZWN0VGFwKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmV2ZW50VHlwZSAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY3VycmVudFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcclxuICAgICAgICBjb25zdCB0YXBMZW5ndGggPSBjdXJyZW50VGltZSAtIHRoaXMudG91Y2hzdGFydFRpbWU7XHJcblxyXG4gICAgICAgIGlmICh0YXBMZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGlmICh0YXBMZW5ndGggPCB0aGlzLnRhcE1pblRpbWVvdXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucnVuSGFuZGxlcihcInRhcFwiLCBldmVudCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJsb25ndGFwXCIsIGV2ZW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBkZXRlY3RQaW5jaChldmVudDogYW55KSB7XHJcbiAgICAgICAgY29uc3QgdG91Y2hlcyA9IGV2ZW50LnRvdWNoZXM7XHJcbiAgICAgICAgcmV0dXJuICh0b3VjaGVzLmxlbmd0aCA9PT0gMiAmJiB0aGlzLmV2ZW50VHlwZSA9PT0gdW5kZWZpbmVkKSB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ3BpbmNoJztcclxuICAgIH1cclxuXHJcbiAgICBkZXRlY3RMaW5lYXJTd2lwZShldmVudDogYW55KSB7XHJcbiAgICAgICAgY29uc3QgdG91Y2hlcyA9IGV2ZW50LnRvdWNoZXM7XHJcblxyXG4gICAgICAgIGlmICh0b3VjaGVzKSB7XHJcbiAgICAgICAgICAgIGlmICh0b3VjaGVzLmxlbmd0aCA9PT0gMSAmJiAhdGhpcy5ldmVudFR5cGUgfHwgdGhpcy5ldmVudFR5cGUgPT09ICdob3Jpem9udGFsLXN3aXBlJyB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJykge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5ldmVudFR5cGUgfHwgdGhpcy5ldmVudFR5cGUgPT09ICdob3Jpem9udGFsLXN3aXBlJyB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJykge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBnZXRMaW5lYXJTd2lwZVR5cGUoZXZlbnQ6IGFueSkge1xyXG4gICAgICAgIGlmICh0aGlzLmV2ZW50VHlwZSAhPT0gJ2hvcml6b250YWwtc3dpcGUnICYmIHRoaXMuZXZlbnRUeXBlICE9PSAndmVydGljYWwtc3dpcGUnKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG1vdmVtZW50WCA9IE1hdGguYWJzKHRoaXMubW92ZUxlZnQoMCwgZXZlbnQpIC0gdGhpcy5zdGFydFgpO1xyXG4gICAgICAgICAgICBjb25zdCBtb3ZlbWVudFkgPSBNYXRoLmFicyh0aGlzLm1vdmVUb3AoMCwgZXZlbnQpIC0gdGhpcy5zdGFydFkpO1xyXG5cclxuICAgICAgICAgICAgaWYgKChtb3ZlbWVudFkgKiAzKSA+IG1vdmVtZW50WCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuICd2ZXJ0aWNhbC1zd2lwZSc7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2hvcml6b250YWwtc3dpcGUnO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXZlbnRUeXBlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBnZXRFbGVtZW50UG9zaXRpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIH1cclxuXHJcbiAgICBnZXRUb3VjaHN0YXJ0UG9zaXRpb24oZXZlbnQ6IGFueSkge1xyXG4gICAgICAgIHRoaXMuc3RhcnRYID0gZXZlbnQudG91Y2hlc1swXS5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcclxuICAgICAgICB0aGlzLnN0YXJ0WSA9IGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WSAtIHRoaXMuZWxlbWVudFBvc2l0aW9uLnRvcDtcclxuICAgIH1cclxuXHJcbiAgICBnZXRNb3VzZWRvd25Qb3NpdGlvbihldmVudDogYW55KSB7XHJcbiAgICAgICAgdGhpcy5zdGFydFggPSBldmVudC5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcclxuICAgICAgICB0aGlzLnN0YXJ0WSA9IGV2ZW50LmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XHJcbiAgICB9XHJcblxyXG4gICAgbW92ZUxlZnQoaW5kZXg6IGFueSwgZXZlbnQ6IGFueSkge1xyXG4gICAgICAgIGNvbnN0IHRvdWNoZXMgPSBldmVudC50b3VjaGVzO1xyXG5cclxuICAgICAgICBpZiAodG91Y2hlcykge1xyXG4gICAgICAgICAgICByZXR1cm4gdG91Y2hlc1tpbmRleF0uY2xpZW50WCAtIHRoaXMuZWxlbWVudFBvc2l0aW9uLmxlZnQ7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50LmNsaWVudFggLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi5sZWZ0O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBtb3ZlVG9wKGluZGV4OiBhbnksIGV2ZW50OiBhbnkpIHtcclxuICAgICAgICBjb25zdCB0b3VjaGVzID0gZXZlbnQudG91Y2hlcztcclxuXHJcbiAgICAgICAgaWYgKHRvdWNoZXMpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRvdWNoZXNbaW5kZXhdLmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV2ZW50LmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGRldGVjdFRvdWNoU2NyZWVuKCkge1xyXG4gICAgICAgIHZhciBwcmVmaXhlcyA9ICcgLXdlYmtpdC0gLW1vei0gLW8tIC1tcy0gJy5zcGxpdCgnICcpO1xyXG4gICAgICAgIHZhciBtcSA9IGZ1bmN0aW9uKHF1ZXJ5OiBhbnkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5tYXRjaE1lZGlhKHF1ZXJ5KS5tYXRjaGVzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCgnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gaW5jbHVkZSB0aGUgJ2hlYXJ0eicgYXMgYSB3YXkgdG8gaGF2ZSBhIG5vbiBtYXRjaGluZyBNUSB0byBoZWxwIHRlcm1pbmF0ZSB0aGUgam9pblxyXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0LmlvL3Z6bkZIXHJcbiAgICAgICAgdmFyIHF1ZXJ5ID0gWycoJywgcHJlZml4ZXMuam9pbigndG91Y2gtZW5hYmxlZCksKCcpLCAnaGVhcnR6JywgJyknXS5qb2luKCcnKTtcclxuICAgICAgICByZXR1cm4gbXEocXVlcnkpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvKiBQdWJsaWMgcHJvcGVydGllcyBhbmQgbWV0aG9kcyAqL1xyXG4gICAgb24oZXZlbnQ6IEV2ZW50VHlwZSwgaGFuZGxlcjogRnVuY3Rpb24pIHtcclxuICAgICAgICBpZiAoZXZlbnQpIHtcclxuICAgICAgICAgICAgdGhpcy5oYW5kbGVyc1tldmVudF0gPSBoYW5kbGVyO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufSJdfQ==