angular-responsive-carousel-ng16
Version:
Carousel for Angular. A simple solution for horizontal scrolling images with lazy loading.
343 lines • 43.4 kB
JavaScript
export class Touches {
get touchListeners() {
return this.properties.touchListeners ? this.properties.touchListeners : this._touchListeners;
}
get mouseListeners() {
return this.properties.mouseListeners ? this.properties.mouseListeners : this._mouseListeners;
}
get otherListeners() {
return this.properties.otherListeners ? this.properties.otherListeners : this._otherListeners;
}
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], { passive: 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);
}
}
}
}
addEventListeners(listener) {
const handler = this._mouseListeners[listener];
window.addEventListener(listener, this[handler], false);
}
removeEventListeners(listener) {
const handler = this._mouseListeners[listener];
window.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;
return undefined;
}
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);
}
}
return undefined;
}
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG91Y2hlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItcmVzcG9uc2l2ZS1jYXJvdXNlbC1uZzE2L3NyYy9saWIvdG91Y2hlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFhQSxNQUFNLE9BQU8sT0FBTztJQStCaEIsSUFBSSxjQUFjO1FBQ2QsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDbEcsQ0FBQztJQUVELElBQUksY0FBYztRQUNkLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO0lBQ2xHLENBQUM7SUFFRCxJQUFJLGNBQWM7UUFDZCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUNsRyxDQUFDO0lBRUQsWUFBWSxVQUFzQjtRQXZDbEMsY0FBUyxHQUFjLFNBQVMsQ0FBQztRQUNqQyxhQUFRLEdBQVEsRUFBRSxDQUFDO1FBQ25CLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFDWCxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsWUFBTyxHQUFHLENBQUMsQ0FBQztRQUVaLHdCQUFtQixHQUFHLEdBQUcsQ0FBQztRQUMxQixrQkFBYSxHQUFHLEdBQUcsQ0FBQztRQUNwQixtQkFBYyxHQUFHLENBQUMsQ0FBQztRQUNuQixNQUFDLEdBQVcsQ0FBQyxDQUFDO1FBQ2QsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFFcEIsb0JBQWUsR0FBUTtZQUNuQixZQUFZLEVBQUUs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SyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQztTQUNuRDtJQUNMLENBQUM7SUFFRCxpQkFBaUI7UUFDYixJQUFJLFFBQVEsR0FBRywyQkFBMkIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEQsSUFBSSxFQUFFLEdBQUcsVUFBUyxLQUFVO1lBQ3hCLE9BQU8sTUFBTSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDNUMsQ0FBQyxDQUFBO1FBRUQsSUFBSSxDQUFDLGNBQWMsSUFBSSxNQUFNLENBQUMsRUFBRTtZQUM1QixPQUFPLElBQUksQ0FBQztTQUNmO1FBRUQscUZBQXFGO1FBQ3JGLHVCQUF1QjtRQUN2QixJQUFJLEtBQUssR0FBRyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3RSxPQUFPLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNyQixDQUFDO0lBR0QsbUNBQW1DO0lBQ25DLEVBQUUsQ0FBQyxLQUFnQixFQUFFLE9BQWlCO1FBQ2xDLElBQUksS0FBSyxFQUFFO1lBQ1AsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUM7U0FDbEM7SUFDTCxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgaW50ZXJmYWNlIFByb3BlcnRpZXMge1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIGxpc3RlbmVycz86ICdhdXRvJyB8ICdtb3VzZSBhbmQgdG91Y2gnO1xuICAgIHRvdWNoTGlzdGVuZXJzPzogYW55O1xuICAgIG1vdXNlTGlzdGVuZXJzPzogYW55O1xuICAgIG90aGVyTGlzdGVuZXJzPzogYW55O1xuICAgIHJlc2l6ZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCB0eXBlIEV2ZW50VHlwZSA9IHVuZGVmaW5lZCB8ICd0b3VjaGVuZCcgfCAncGFuJyB8ICdwaW5jaCcgfCAnaG9yaXpvbnRhbC1zd2lwZScgfCAndmVydGljYWwtc3dpcGUnIHwgJ3RhcCcgfCAnbG9uZ3RhcCc7XG5leHBvcnQgdHlwZSBUb3VjaEhhbmRsZXIgPSAnaGFuZGxlVG91Y2hzdGFydCcgfCAnaGFuZGxlVG91Y2htb3ZlJyB8ICdoYW5kbGVUb3VjaGVuZCc7XG5leHBvcnQgdHlwZSBNb3VzZUhhbmRsZXIgPSAnaGFuZGxlTW91c2Vkb3duJyB8ICdoYW5kbGVNb3VzZW1vdmUnIHwgJ2hhbmRsZU1vdXNldXAnO1xuXG5leHBvcnQgY2xhc3MgVG91Y2hlcyB7XG4gICAgcHJvcGVydGllczogUHJvcGVydGllcztcbiAgICBlbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgICBlbGVtZW50UG9zaXRpb246IENsaWVudFJlY3Q7XG4gICAgZXZlbnRUeXBlOiBFdmVudFR5cGUgPSB1bmRlZmluZWQ7XG4gICAgaGFuZGxlcnM6IGFueSA9IHt9O1xuICAgIHN0YXJ0WCA9IDA7XG4gICAgc3RhcnRZID0gMDtcbiAgICBsYXN0VGFwID0gMDtcbiAgICBkb3VibGVUYXBUaW1lb3V0OiBhbnk7XG4gICAgZG91YmxlVGFwTWluVGltZW91dCA9IDMwMDtcbiAgICB0YXBNaW5UaW1lb3V0ID0gMjAwO1xuICAgIHRvdWNoc3RhcnRUaW1lID0gMDtcbiAgICBpOiBudW1iZXIgPSAwO1xuICAgIGlzTW91c2Vkb3duID0gZmFsc2U7XG5cbiAgICBfdG91Y2hMaXN0ZW5lcnM6IGFueSA9IHtcbiAgICAgICAgXCJ0b3VjaHN0YXJ0XCI6IFwiaGFuZGxlVG91Y2hzdGFydFwiLFxuICAgICAgICBcInRvdWNobW92ZVwiOiBcImhhbmRsZVRvdWNobW92ZVwiLFxuICAgICAgICBcInRvdWNoZW5kXCI6IFwiaGFuZGxlVG91Y2hlbmRcIlxuICAgIH1cbiAgICBfbW91c2VMaXN0ZW5lcnM6IGFueSA9IHtcbiAgICAgICAgXCJtb3VzZWRvd25cIjogXCJoYW5kbGVNb3VzZWRvd25cIixcbiAgICAgICAgXCJtb3VzZW1vdmVcIjogXCJoYW5kbGVNb3VzZW1vdmVcIixcbiAgICAgICAgXCJtb3VzZXVwXCI6IFwiaGFuZGxlTW91c2V1cFwiLFxuICAgICAgICBcIndoZWVsXCI6IFwiaGFuZGxlV2hlZWxcIlxuICAgIH1cbiAgICBfb3RoZXJMaXN0ZW5lcnM6IGFueSA9IHtcbiAgICAgICAgXCJyZXNpemVcIjogXCJoYW5kbGVSZXNpemVcIlxuICAgIH1cblxuICAgIGdldCB0b3VjaExpc3RlbmVycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydGllcy50b3VjaExpc3RlbmVycyA/IHRoaXMucHJvcGVydGllcy50b3VjaExpc3RlbmVycyA6IHRoaXMuX3RvdWNoTGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGdldCBtb3VzZUxpc3RlbmVycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydGllcy5tb3VzZUxpc3RlbmVycyA/IHRoaXMucHJvcGVydGllcy5tb3VzZUxpc3RlbmVycyA6IHRoaXMuX21vdXNlTGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGdldCBvdGhlckxpc3RlbmVycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcGVydGllcy5vdGhlckxpc3RlbmVycyA/IHRoaXMucHJvcGVydGllcy5vdGhlckxpc3RlbmVycyA6IHRoaXMuX290aGVyTGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKHByb3BlcnRpZXM6IFByb3BlcnRpZXMpIHtcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcbiAgICAgICAgdGhpcy5lbGVtZW50ID0gdGhpcy5wcm9wZXJ0aWVzLmVsZW1lbnQ7XG4gICAgICAgIHRoaXMuZWxlbWVudFBvc2l0aW9uID0gdGhpcy5nZXRFbGVtZW50UG9zaXRpb24oKTtcblxuICAgICAgICB0aGlzLnRvZ2dsZUV2ZW50TGlzdGVuZXJzKCdhZGRFdmVudExpc3RlbmVyJyk7XG4gICAgfVxuXG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy50b2dnbGVFdmVudExpc3RlbmVycygncmVtb3ZlRXZlbnRMaXN0ZW5lcicpO1xuICAgIH1cblxuICAgIHRvZ2dsZUV2ZW50TGlzdGVuZXJzKGFjdGlvbjogJ2FkZEV2ZW50TGlzdGVuZXInIHwgJ3JlbW92ZUV2ZW50TGlzdGVuZXInKSB7XG4gICAgICAgIGxldCBsaXN0ZW5lcnM7XG5cbiAgICAgICAgaWYgKHRoaXMucHJvcGVydGllcy5saXN0ZW5lcnMgPT09ICdtb3VzZSBhbmQgdG91Y2gnKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBPYmplY3QuYXNzaWduKHRoaXMudG91Y2hMaXN0ZW5lcnMsIHRoaXMubW91c2VMaXN0ZW5lcnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGlzdGVuZXJzID0gdGhpcy5kZXRlY3RUb3VjaFNjcmVlbigpID8gdGhpcy50b3VjaExpc3RlbmVycyA6IHRoaXMubW91c2VMaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5wcm9wZXJ0aWVzLnJlc2l6ZSkge1xuICAgICAgICAgICAgbGlzdGVuZXJzID0gT2JqZWN0LmFzc2lnbihsaXN0ZW5lcnMsIHRoaXMub3RoZXJMaXN0ZW5lcnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgbGlzdGVuZXIgaW4gbGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVyOiBNb3VzZUhhbmRsZXIgPSBsaXN0ZW5lcnNbbGlzdGVuZXJdO1xuXG4gICAgICAgICAgICAvLyBXaW5kb3dcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lciA9PT0gXCJyZXNpemVcIikge1xuICAgICAgICAgICAgICAgIGlmIChhY3Rpb24gPT09ICdhZGRFdmVudExpc3RlbmVyJykge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uID09PSAncmVtb3ZlRXZlbnRMaXN0ZW5lcicpIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIobGlzdGVuZXIsIHRoaXNbaGFuZGxlcl0sIGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEb2N1bWVudFxuICAgICAgICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lciA9PT0gJ21vdXNldXAnIHx8IGxpc3RlbmVyID09PSBcIm1vdXNlbW92ZVwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ2FkZEV2ZW50TGlzdGVuZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIobGlzdGVuZXIsIHRoaXNbaGFuZGxlcl0sIHtwYXNzaXZlOiBmYWxzZX0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uID09PSAncmVtb3ZlRXZlbnRMaXN0ZW5lcicpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEVsZW1lbnRcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbiA9PT0gJ2FkZEV2ZW50TGlzdGVuZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGxpc3RlbmVyLCB0aGlzW2hhbmRsZXJdLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhY3Rpb24gPT09ICdyZW1vdmVFdmVudExpc3RlbmVyJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFkZEV2ZW50TGlzdGVuZXJzKGxpc3RlbmVyOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgaGFuZGxlcjogTW91c2VIYW5kbGVyID0gdGhpcy5fbW91c2VMaXN0ZW5lcnNbbGlzdGVuZXJdO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xuICAgIH1cblxuICAgIHJlbW92ZUV2ZW50TGlzdGVuZXJzKGxpc3RlbmVyOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgaGFuZGxlcjogTW91c2VIYW5kbGVyID0gdGhpcy5fbW91c2VMaXN0ZW5lcnNbbGlzdGVuZXJdO1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihsaXN0ZW5lciwgdGhpc1toYW5kbGVyXSwgZmFsc2UpO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogTGlzdGVuZXJzXG4gICAgICovXG5cbiAgICAvKiBUb3VjaHN0YXJ0ICovXG5cbiAgICBoYW5kbGVUb3VjaHN0YXJ0ID0gKGV2ZW50OiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbigpO1xuICAgICAgICB0aGlzLnRvdWNoc3RhcnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuZXZlbnRUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0VG91Y2hzdGFydFBvc2l0aW9uKGV2ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucnVuSGFuZGxlcihcInRvdWNoc3RhcnRcIiwgZXZlbnQpO1xuICAgIH1cblxuXG4gICAgLyogVG91Y2htb3ZlICovXG5cbiAgICBoYW5kbGVUb3VjaG1vdmUgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCB0b3VjaGVzID0gZXZlbnQudG91Y2hlcztcblxuICAgICAgICAvLyBQYW5cbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0UGFuKHRvdWNoZXMpKSB7XG4gICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJwYW5cIiwgZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGluY2hcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0UGluY2goZXZlbnQpKSB7XG4gICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJwaW5jaFwiLCBldmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMaW5lYXIgc3dpcGVcbiAgICAgICAgc3dpdGNoICh0aGlzLmRldGVjdExpbmVhclN3aXBlKGV2ZW50KSkge1xuICAgICAgICAgICAgY2FzZSBcImhvcml6b250YWwtc3dpcGVcIjpcbiAgICAgICAgICAgICAgICBldmVudC5zd2lwZVR5cGUgPSBcImhvcml6b250YWwtc3dpcGVcIjtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJob3Jpem9udGFsLXN3aXBlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJ2ZXJ0aWNhbC1zd2lwZVwiOlxuICAgICAgICAgICAgICAgIGV2ZW50LnN3aXBlVHlwZSA9IFwidmVydGljYWwtc3dpcGVcIjtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJ2ZXJ0aWNhbC1zd2lwZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMaW5lYXIgc3dpcGVcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQpIHx8XG4gICAgICAgICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8XG4gICAgICAgICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJykge1xuXG4gICAgICAgICAgICB0aGlzLmhhbmRsZUxpbmVhclN3aXBlKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhhbmRsZUxpbmVhclN3aXBlKGV2ZW50OiBhbnkpIHtcbiAgICAgICAgLy9ldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHRoaXMuaSsrO1xuXG4gICAgICAgIGlmICh0aGlzLmkgPiAzKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50VHlwZSA9IHRoaXMuZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnKSB7XG4gICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoJ2hvcml6b250YWwtc3dpcGUnLCBldmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5ldmVudFR5cGUgPT09ICd2ZXJ0aWNhbC1zd2lwZScpIHtcbiAgICAgICAgICAgIHRoaXMucnVuSGFuZGxlcigndmVydGljYWwtc3dpcGUnLCBldmVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qIFRvdWNoZW5kICovXG5cbiAgICBoYW5kbGVUb3VjaGVuZCA9IChldmVudDogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IHRvdWNoZXMgPSBldmVudC50b3VjaGVzO1xuXG4gICAgICAgIC8vIERvdWJsZSBUYXBcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0RG91YmxlVGFwKCkpIHtcbiAgICAgICAgICAgIHRoaXMucnVuSGFuZGxlcihcImRvdWJsZS10YXBcIiwgZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGFwXG4gICAgICAgIHRoaXMuZGV0ZWN0VGFwKCk7XG5cbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwidG91Y2hlbmRcIiwgZXZlbnQpO1xuICAgICAgICB0aGlzLmV2ZW50VHlwZSA9ICd0b3VjaGVuZCc7XG5cbiAgICAgICAgaWYgKHRvdWNoZXMgJiYgdG91Y2hlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRUeXBlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5pID0gMDtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogTW91c2Vkb3duICovXG5cbiAgICBoYW5kbGVNb3VzZWRvd24gPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgICB0aGlzLmlzTW91c2Vkb3duID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5lbGVtZW50UG9zaXRpb24gPSB0aGlzLmdldEVsZW1lbnRQb3NpdGlvbigpO1xuICAgICAgICB0aGlzLnRvdWNoc3RhcnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuZXZlbnRUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0TW91c2Vkb3duUG9zaXRpb24oZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwibW91c2Vkb3duXCIsIGV2ZW50KTtcbiAgICB9XG5cblxuICAgIC8qIE1vdXNlbW92ZSAqL1xuXG4gICAgaGFuZGxlTW91c2Vtb3ZlID0gKGV2ZW50OiBhbnkpID0+IHtcbiAgICAgICAgLy9ldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBcbiAgICAgICAgaWYgKCF0aGlzLmlzTW91c2Vkb3duKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQYW5cbiAgICAgICAgdGhpcy5ydW5IYW5kbGVyKFwicGFuXCIsIGV2ZW50KTtcblxuICAgICAgICAvLyBMaW5lYXIgc3dpcGVcbiAgICAgICAgc3dpdGNoICh0aGlzLmRldGVjdExpbmVhclN3aXBlKGV2ZW50KSkge1xuICAgICAgICAgICAgY2FzZSBcImhvcml6b250YWwtc3dpcGVcIjpcbiAgICAgICAgICAgICAgICBldmVudC5zd2lwZVR5cGUgPSBcImhvcml6b250YWwtc3dpcGVcIjtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJob3Jpem9udGFsLXN3aXBlXCIsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJ2ZXJ0aWNhbC1zd2lwZVwiOlxuICAgICAgICAgICAgICAgIGV2ZW50LnN3aXBlVHlwZSA9IFwidmVydGljYWwtc3dpcGVcIjtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJ2ZXJ0aWNhbC1zd2lwZVwiLCBldmVudCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMaW5lYXIgc3dpcGVcbiAgICAgICAgaWYgKHRoaXMuZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQpIHx8XG4gICAgICAgICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8XG4gICAgICAgICAgICB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJykge1xuXG4gICAgICAgICAgICB0aGlzLmhhbmRsZUxpbmVhclN3aXBlKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyogTW91c2V1cCAqL1xuXG4gICAgaGFuZGxlTW91c2V1cCA9IChldmVudDogYW55KSA9PiB7XG5cbiAgICAgICAgLy8gVGFwXG4gICAgICAgIHRoaXMuZGV0ZWN0VGFwKCk7XG5cbiAgICAgICAgdGhpcy5pc01vdXNlZG93biA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJtb3VzZXVwXCIsIGV2ZW50KTtcbiAgICAgICAgdGhpcy5ldmVudFR5cGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaSA9IDA7XG4gICAgfVxuXG5cbiAgICAvKiBXaGVlbCAqL1xuXG4gICAgaGFuZGxlV2hlZWwgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJ3aGVlbFwiLCBldmVudCk7XG4gICAgfVxuXG4gICAgLyogUmVzaXplICovXG5cbiAgICBoYW5kbGVSZXNpemUgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJyZXNpemVcIiwgZXZlbnQpO1xuICAgIH1cblxuICAgIHJ1bkhhbmRsZXIoZXZlbnROYW1lOiBhbnksIHJlc3BvbnNlOiBhbnkpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFuZGxlcnNbZXZlbnROYW1lXSkge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVyc1tldmVudE5hbWVdKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLypcbiAgICAgKiBEZXRlY3Rpb25cbiAgICAgKi9cblxuICAgIGRldGVjdFBhbih0b3VjaGVzOiBhbnkpIHtcbiAgICAgICAgcmV0dXJuIHRvdWNoZXMubGVuZ3RoID09PSAxICYmICF0aGlzLmV2ZW50VHlwZSB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ3Bhbic7XG4gICAgfVxuXG4gICAgZGV0ZWN0RG91YmxlVGFwKCkge1xuICAgICAgICBpZiAodGhpcy5ldmVudFR5cGUgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjdXJyZW50VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICBjb25zdCB0YXBMZW5ndGggPSBjdXJyZW50VGltZSAtIHRoaXMubGFzdFRhcDtcblxuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5kb3VibGVUYXBUaW1lb3V0KTtcblxuICAgICAgICBpZiAodGFwTGVuZ3RoIDwgdGhpcy5kb3VibGVUYXBNaW5UaW1lb3V0ICYmIHRhcExlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kb3VibGVUYXBUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuZG91YmxlVGFwVGltZW91dCk7XG4gICAgICAgICAgICB9LCB0aGlzLmRvdWJsZVRhcE1pblRpbWVvdXQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFzdFRhcCA9IGN1cnJlbnRUaW1lO1xuXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgZGV0ZWN0VGFwKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5ldmVudFR5cGUgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjdXJyZW50VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICBjb25zdCB0YXBMZW5ndGggPSBjdXJyZW50VGltZSAtIHRoaXMudG91Y2hzdGFydFRpbWU7XG5cbiAgICAgICAgaWYgKHRhcExlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlmICh0YXBMZW5ndGggPCB0aGlzLnRhcE1pblRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJ0YXBcIiwgZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJ1bkhhbmRsZXIoXCJsb25ndGFwXCIsIGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRldGVjdFBpbmNoKGV2ZW50OiBhbnkpIHtcbiAgICAgICAgY29uc3QgdG91Y2hlcyA9IGV2ZW50LnRvdWNoZXM7XG4gICAgICAgIHJldHVybiAodG91Y2hlcy5sZW5ndGggPT09IDIgJiYgdGhpcy5ldmVudFR5cGUgPT09IHVuZGVmaW5lZCkgfHwgdGhpcy5ldmVudFR5cGUgPT09ICdwaW5jaCc7XG4gICAgfVxuXG4gICAgZGV0ZWN0TGluZWFyU3dpcGUoZXZlbnQ6IGFueSkge1xuICAgICAgICBjb25zdCB0b3VjaGVzID0gZXZlbnQudG91Y2hlcztcblxuICAgICAgICBpZiAodG91Y2hlcykge1xuICAgICAgICAgICAgaWYgKHRvdWNoZXMubGVuZ3RoID09PSAxICYmICF0aGlzLmV2ZW50VHlwZSB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ2hvcml6b250YWwtc3dpcGUnIHx8IHRoaXMuZXZlbnRUeXBlID09PSAndmVydGljYWwtc3dpcGUnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGluZWFyU3dpcGVUeXBlKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5ldmVudFR5cGUgfHwgdGhpcy5ldmVudFR5cGUgPT09ICdob3Jpem9udGFsLXN3aXBlJyB8fCB0aGlzLmV2ZW50VHlwZSA9PT0gJ3ZlcnRpY2FsLXN3aXBlJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldExpbmVhclN3aXBlVHlwZShldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGdldExpbmVhclN3aXBlVHlwZShldmVudDogYW55KSB7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50VHlwZSAhPT0gJ2hvcml6b250YWwtc3dpcGUnICYmIHRoaXMuZXZlbnRUeXBlICE9PSAndmVydGljYWwtc3dpcGUnKSB7XG4gICAgICAgICAgICBjb25zdCBtb3ZlbWVudFggPSBNYXRoLmFicyh0aGlzLm1vdmVMZWZ0KDAsIGV2ZW50KSAtIHRoaXMuc3RhcnRYKTtcbiAgICAgICAgICAgIGNvbnN0IG1vdmVtZW50WSA9IE1hdGguYWJzKHRoaXMubW92ZVRvcCgwLCBldmVudCkgLSB0aGlzLnN0YXJ0WSk7XG5cbiAgICAgICAgICAgIGlmICgobW92ZW1lbnRZICogMykgPiBtb3ZlbWVudFgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3ZlcnRpY2FsLXN3aXBlJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdob3Jpem9udGFsLXN3aXBlJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV2ZW50VHlwZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldEVsZW1lbnRQb3NpdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9XG5cbiAgICBnZXRUb3VjaHN0YXJ0UG9zaXRpb24oZXZlbnQ6IGFueSkge1xuICAgICAgICB0aGlzLnN0YXJ0WCA9IGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WCAtIHRoaXMuZWxlbWVudFBvc2l0aW9uLmxlZnQ7XG4gICAgICAgIHRoaXMuc3RhcnRZID0gZXZlbnQudG91Y2hlc1swXS5jbGllbnRZIC0gdGhpcy5lbGVtZW50UG9zaXRpb24udG9wO1xuICAgIH1cblxuICAgIGdldE1vdXNlZG93blBvc2l0aW9uKGV2ZW50OiBhbnkpIHtcbiAgICAgICAgdGhpcy5zdGFydFggPSBldmVudC5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcbiAgICAgICAgdGhpcy5zdGFydFkgPSBldmVudC5jbGllbnRZIC0gdGhpcy5lbGVtZW50UG9zaXRpb24udG9wO1xuICAgIH1cblxuICAgIG1vdmVMZWZ0KGluZGV4OiBhbnksIGV2ZW50OiBhbnkpIHtcbiAgICAgICAgY29uc3QgdG91Y2hlcyA9IGV2ZW50LnRvdWNoZXM7XG5cbiAgICAgICAgaWYgKHRvdWNoZXMpIHtcbiAgICAgICAgICAgIHJldHVybiB0b3VjaGVzW2luZGV4XS5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBldmVudC5jbGllbnRYIC0gdGhpcy5lbGVtZW50UG9zaXRpb24ubGVmdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG1vdmVUb3AoaW5kZXg6IGFueSwgZXZlbnQ6IGFueSkge1xuICAgICAgICBjb25zdCB0b3VjaGVzID0gZXZlbnQudG91Y2hlcztcblxuICAgICAgICBpZiAodG91Y2hlcykge1xuICAgICAgICAgICAgcmV0dXJuIHRvdWNoZXNbaW5kZXhdLmNsaWVudFkgLSB0aGlzLmVsZW1lbnRQb3NpdGlvbi50b3A7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZXZlbnQuY2xpZW50WSAtIHRoaXMuZWxlbWVudFBvc2l0aW9uLnRvcDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRldGVjdFRvdWNoU2NyZWVuKCkge1xuICAgICAgICB2YXIgcHJlZml4ZXMgPSAnIC13ZWJraXQtIC1tb3otIC1vLSAtbXMtICcuc3BsaXQoJyAnKTtcbiAgICAgICAgdmFyIG1xID0gZnVuY3Rpb24ocXVlcnk6IGFueSkge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5tYXRjaE1lZGlhKHF1ZXJ5KS5tYXRjaGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCgnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGluY2x1ZGUgdGhlICdoZWFydHonIGFzIGEgd2F5IHRvIGhhdmUgYSBub24gbWF0Y2hpbmcgTVEgdG8gaGVscCB0ZXJtaW5hdGUgdGhlIGpvaW5cbiAgICAgICAgLy8gaHR0cHM6Ly9naXQuaW8vdnpuRkhcbiAgICAgICAgdmFyIHF1ZXJ5ID0gWycoJywgcHJlZml4ZXMuam9pbigndG91Y2gtZW5hYmxlZCksKCcpLCAnaGVhcnR6JywgJyknXS5qb2luKCcnKTtcbiAgICAgICAgcmV0dXJuIG1xKHF1ZXJ5KTtcbiAgICB9XG5cblxuICAgIC8qIFB1YmxpYyBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzICovXG4gICAgb24oZXZlbnQ6IEV2ZW50VHlwZSwgaGFuZGxlcjogRnVuY3Rpb24pIHtcbiAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZXJzW2V2ZW50XSA9IGhhbmRsZXI7XG4gICAgICAgIH1cbiAgICB9XG59Il19