UNPKG

ng-devui

Version:

DevUI components based on Angular

326 lines 57.6 kB
import { DOCUMENT } from '@angular/common'; import { Directive, ElementRef, Inject, Input, NgZone } from '@angular/core'; import { fromEvent, merge as mergeStatic, Subscription } from 'rxjs'; import { tap, throttleTime } from 'rxjs/operators'; import { DragDropService } from '../services/drag-drop.service'; import { Utils } from '../shared/utils'; import { DropScrollEnhanceTimingFunctionGroup, DropScrollOrientation } from './drop-scroll-enhance.type'; import * as i0 from "@angular/core"; import * as i1 from "../services/drag-drop.service"; export class DropScrollEnhancedDirective { constructor(el, zone, dragDropService, doc) { this.el = el; this.zone = zone; this.dragDropService = dragDropService; this.doc = doc; this.minSpeed = 50; this.maxSpeed = 1000; this.responseEdgeWidth = '100px'; this.speedFn = DropScrollEnhanceTimingFunctionGroup.default; this.direction = 'v'; this.backSpaceDroppable = true; this.subscription = new Subscription(); this.document = this.doc; } ngAfterViewInit() { // 设置父元素 this.el.nativeElement.parentNode.style.position = 'relative'; this.el.nativeElement.parentNode.style.display = 'block'; // 创建后退前进区域和对应的滚动函数 this.forwardScrollArea = this.createScrollArea(this.direction, DropScrollOrientation.forward); this.backwardScrollArea = this.createScrollArea(this.direction, DropScrollOrientation.backward); this.forwardScrollFn = this.createScrollFn(this.direction, DropScrollOrientation.forward, this.speedFn); this.backwardScrollFn = this.createScrollFn(this.direction, DropScrollOrientation.backward, this.speedFn); this.zone.runOutsideAngular(() => { // 拖拽到其上触发滚动 this.subscription.add(fromEvent(this.forwardScrollArea, 'dragover') .pipe(tap(event => { event.preventDefault(); event.stopPropagation(); }), throttleTime(100, undefined, { leading: true, trailing: false })).subscribe(event => this.forwardScrollFn(event))); this.subscription.add(fromEvent(this.backwardScrollArea, 'dragover') .pipe(tap(event => { event.preventDefault(); event.stopPropagation(); }), throttleTime(100, undefined, { leading: true, trailing: false })) .subscribe(event => this.backwardScrollFn(event))); // 拖拽放置委托 this.subscription.add(mergeStatic(fromEvent(this.forwardScrollArea, 'drop'), fromEvent(this.backwardScrollArea, 'drop')).subscribe(event => this.delegateDropEvent(event))); // 拖拽离开清除参数 this.subscription.add(mergeStatic(fromEvent(this.forwardScrollArea, 'dragleave', { passive: true }), fromEvent(this.backwardScrollArea, 'dragleave', { passive: true })).subscribe(event => this.cleanLastScrollTime())); // 滚动过程计算区域有效性,滚动条贴到边缘的时候无效,无效的时候设置鼠标事件可用为none this.subscription.add(fromEvent(this.el.nativeElement, 'scroll', { passive: true }) .pipe(throttleTime(300, undefined, { leading: true, trailing: true })) .subscribe(event => { this.toggleScrollToOneEnd(this.el.nativeElement, this.forwardScrollArea, this.direction, DropScrollOrientation.forward); this.toggleScrollToOneEnd(this.el.nativeElement, this.backwardScrollArea, this.direction, DropScrollOrientation.backward); })); // 窗口缩放的时候重绘有效性区域 this.subscription.add(fromEvent(window, 'resize', { passive: true }) .pipe(throttleTime(300, undefined, { leading: true, trailing: true })) .subscribe(event => this.resizeArea())); // dragstart的时候显示拖拽滚动边缘面板 this.subscription.add(this.dragDropService.dragStartEvent.subscribe(() => { if (!this.allowScroll()) { return; } this.zone.runOutsideAngular(() => { setTimeout(() => { // 立马出现会打断边缘元素的拖拽 this.forwardScrollArea.style.display = 'block'; this.backwardScrollArea.style.display = 'block'; }); }); })); // dragEnd或drop的时候结束了拖拽,滚动区域影藏起来 this.subscription.add(mergeStatic(this.dragDropService.dragEndEvent, this.dragDropService.dropEvent) .subscribe(() => { this.forwardScrollArea.style.display = 'none'; this.backwardScrollArea.style.display = 'none'; this.lastScrollTime = undefined; })); }); setTimeout(() => { this.resizeArea(); }, 0); } ngOnDestroy() { this.subscription.unsubscribe(); } createScrollFn(direction, orientation, speedFn) { if (typeof window === 'undefined') { return; } const scrollAttr = (direction === 'v') ? 'scrollTop' : 'scrollLeft'; const eventAttr = (direction === 'v') ? 'clientY' : 'clientX'; const scrollWidthAttr = (direction === 'v') ? 'scrollHeight' : 'scrollWidth'; const offsetWidthAttr = (direction === 'v') ? 'offsetHeight' : 'offsetWidth'; const clientWidthAttr = (direction === 'v') ? 'clientHeight' : 'clientWidth'; const rectWidthAttr = (direction === 'v') ? 'height' : 'width'; const compareTarget = (orientation === DropScrollOrientation.forward) ? this.forwardScrollArea : this.backwardScrollArea; const targetAttr = this.getCriticalEdge(direction, orientation); const scrollElement = this.el.nativeElement; return (event) => { const compareTargetRect = compareTarget.getBoundingClientRect(); const distance = event[eventAttr] - compareTargetRect[targetAttr]; let speed = speedFn(Math.abs(distance / (compareTargetRect[rectWidthAttr] || 1))); if (speed < this.minSpeed) { speed = this.minSpeed; } if (speed > this.maxSpeed) { speed = this.maxSpeed; } if (distance < 0) { speed = -speed; } if (this.animationFrameId) { window.cancelAnimationFrame(this.animationFrameId); this.animationFrameId = undefined; } this.animationFrameId = requestAnimationFrame(() => { const time = new Date().getTime(); const moveDistance = Math.ceil(speed * (time - (this.lastScrollTime || time)) / 1000); scrollElement[scrollAttr] -= moveDistance; this.lastScrollTime = time; // 判断是不是到尽头 if ((scrollElement[scrollAttr] === 0 && orientation === DropScrollOrientation.backward) || ((scrollElement[scrollAttr] + (scrollElement.getBoundingClientRect())[rectWidthAttr] - scrollElement[offsetWidthAttr] + scrollElement[clientWidthAttr]) === scrollElement[scrollWidthAttr] && orientation === DropScrollOrientation.forward)) { compareTarget.style.pointerEvents = 'none'; this.toggleActiveClass(compareTarget, false); } this.animationFrameId = undefined; }); if (this.backSpaceDroppable) { Utils.dispatchEventToUnderElement(event); } }; } delegateDropEvent(event) { if (this.backSpaceDroppable) { const ev = Utils.dispatchEventToUnderElement(event); if (ev.defaultPrevented) { event.preventDefault(); event.stopPropagation(); } } } getCriticalEdge(direction, orientation) { return (direction === 'v' && orientation === DropScrollOrientation.forward && 'bottom') || (direction === 'v' && orientation === DropScrollOrientation.backward && 'top') || (direction !== 'v' && orientation === DropScrollOrientation.forward && 'right') || (direction !== 'v' && orientation === DropScrollOrientation.backward && 'left') || 'bottom'; } getSecondEdge(direction) { return (direction === 'v' && 'left') || (direction !== 'v' && 'top') || 'left'; } createScrollArea(direction, orientation) { const area = this.document.createElement('div'); area.className = `dropover-scroll-area dropover-scroll-area-${this.getCriticalEdge(direction, orientation)}`; // 处理大小 area.classList.add('active'); this.setAreaSize(area, direction, orientation); // 处理位置 area.style.position = 'absolute'; this.setAreaStyleLayout(area, direction, orientation); // 默认不展示 area.style.display = 'none'; // 附着元素 this.el.nativeElement.parentNode.appendChild(area, this.el.nativeElement); return area; } setAreaSize(area, direction, orientation) { const rect = this.el.nativeElement.getBoundingClientRect(); const containerAttr = direction === 'v' ? 'height' : 'width'; const responseEdgeWidth = (typeof this.responseEdgeWidth === 'string') ? this.responseEdgeWidth : this.responseEdgeWidth(rect[containerAttr]); const settingOffset = this.viewOffset && (orientation === DropScrollOrientation.forward ? this.viewOffset.forward : this.viewOffset.backward); let width = direction === 'v' ? (rect.width + 'px') : responseEdgeWidth; let height = direction === 'v' ? responseEdgeWidth : (rect.height + 'px'); if (settingOffset) { if (settingOffset.widthOffset) { width = 'calc(' + width + ' + ' + (settingOffset.widthOffset) + 'px)'; } if (settingOffset.heightOffset) { height = 'calc(' + height + ' + ' + (settingOffset.heightOffset) + 'px)'; } } area.style.width = width; area.style.height = height; } setAreaStyleLayout(area, direction, orientation) { const target = this.el.nativeElement; const relatedTarget = this.el.nativeElement.parentNode; const defaultOffset = { left: 0, right: 0, top: 0, bottom: 0 }; const settingOffset = this.viewOffset && (orientation === DropScrollOrientation.forward ? this.viewOffset.forward : this.viewOffset.backward) || defaultOffset; const criticalEdge = this.getCriticalEdge(direction, orientation); const secondEdge = this.getSecondEdge(direction); [criticalEdge, secondEdge].forEach(edge => { area.style[edge] = this.getRelatedPosition(target, relatedTarget, edge, settingOffset[edge]); }); } getRelatedPosition(target, relatedTarget, edge, offsetValue) { if (typeof window === 'undefined') { return '0px'; } const relatedComputedStyle = window.getComputedStyle(relatedTarget); const relatedRect = relatedTarget.getBoundingClientRect(); const selfRect = target.getBoundingClientRect(); const helper = { left: ['left', 'Left'], right: ['right', 'Right'], top: ['top', 'Top'], bottom: ['bottom', 'Bottom'], }; let factor = 1; if (edge === 'right' || edge === 'bottom') { factor = -1; } return (selfRect[helper[edge][0]] - relatedRect[helper[edge][0]] + parseInt(relatedComputedStyle['border' + helper[edge][1] + 'Width'], 10)) * factor + (offsetValue || 0) + 'px'; } resizeArea() { [{ area: this.forwardScrollArea, orientation: DropScrollOrientation.forward }, { area: this.backwardScrollArea, orientation: DropScrollOrientation.backward } ] .forEach(item => { this.setAreaSize(item.area, this.direction, item.orientation); this.setAreaStyleLayout(item.area, this.direction, item.orientation); }); } toggleScrollToOneEnd(scrollElement, toggleElement, direction, orientation) { const scrollAttr = (direction === 'v') ? 'scrollTop' : 'scrollLeft'; const scrollWidthAttr = (direction === 'v') ? 'scrollHeight' : 'scrollWidth'; const offsetWidthAttr = (direction === 'v') ? 'offsetHeight' : 'offsetWidth'; const clientWidthAttr = (direction === 'v') ? 'clientHeight' : 'clientWidth'; const rectWidthAttr = (direction === 'v') ? 'height' : 'width'; if ((scrollElement[scrollAttr] === 0 && orientation === DropScrollOrientation.backward) || (Math.abs(scrollElement[scrollAttr] + (scrollElement.getBoundingClientRect())[rectWidthAttr] - scrollElement[scrollWidthAttr] - scrollElement[offsetWidthAttr] + scrollElement[clientWidthAttr]) < 1 && orientation === DropScrollOrientation.forward)) { toggleElement.style.pointerEvents = 'none'; this.toggleActiveClass(toggleElement, false); } else { toggleElement.style.pointerEvents = 'auto'; this.toggleActiveClass(toggleElement, true); } } cleanLastScrollTime() { if (this.animationFrameId && typeof window !== 'undefined') { window.cancelAnimationFrame(this.animationFrameId); this.animationFrameId = undefined; } this.lastScrollTime = undefined; } toggleActiveClass(target, active) { if (active) { target.classList.remove('inactive'); target.classList.add('active'); } else { target.classList.remove('active'); target.classList.add('inactive'); } } allowScroll() { if (!this.dropScrollScope) { return true; } let allowed = false; if (typeof this.dropScrollScope === 'string') { if (typeof this.dragDropService.scope === 'string') { allowed = this.dragDropService.scope === this.dropScrollScope; } if (this.dragDropService.scope instanceof Array) { allowed = this.dragDropService.scope.indexOf(this.dropScrollScope) > -1; } } if (this.dropScrollScope instanceof Array) { if (typeof this.dragDropService.scope === 'string') { allowed = this.dropScrollScope.indexOf(this.dragDropService.scope) > -1; } if (this.dragDropService.scope instanceof Array) { allowed = this.dropScrollScope.filter((item) => { return this.dragDropService.scope.indexOf(item) !== -1; }).length > 0; } } return allowed; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DropScrollEnhancedDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1.DragDropService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DropScrollEnhancedDirective, selector: "[dDropScrollEnhanced]", inputs: { minSpeed: "minSpeed", maxSpeed: "maxSpeed", responseEdgeWidth: "responseEdgeWidth", speedFn: "speedFn", direction: "direction", viewOffset: "viewOffset", dropScrollScope: "dropScrollScope", backSpaceDroppable: "backSpaceDroppable" }, exportAs: ["dDropScrollEnhanced"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DropScrollEnhancedDirective, decorators: [{ type: Directive, args: [{ selector: '[dDropScrollEnhanced]', exportAs: 'dDropScrollEnhanced' }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1.DragDropService }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }], propDecorators: { minSpeed: [{ type: Input }], maxSpeed: [{ type: Input }], responseEdgeWidth: [{ type: Input }], speedFn: [{ type: Input }], direction: [{ type: Input }], viewOffset: [{ type: Input }], dropScrollScope: [{ type: Input }], backSpaceDroppable: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcC1zY3JvbGwtZW5oYW5jZS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9kZXZ1aS9kcmFnZHJvcC9kaXJlY3RpdmVzL2Ryb3Atc2Nyb2xsLWVuaGFuY2UuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQWlCLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDdkcsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLElBQUksV0FBVyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRSxPQUFPLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNoRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEMsT0FBTyxFQUNzQyxvQ0FBb0MsRUFBRSxxQkFBcUIsRUFFdkcsTUFBTSw0QkFBNEIsQ0FBQzs7O0FBTXBDLE1BQU0sT0FBTywyQkFBMkI7SUFzQnRDLFlBQW9CLEVBQWMsRUFBVSxJQUFZLEVBQVUsZUFBZ0MsRUFDNUQsR0FBUTtRQUQxQixPQUFFLEdBQUYsRUFBRSxDQUFZO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFVLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUM1RCxRQUFHLEdBQUgsR0FBRyxDQUFLO1FBdEJyQyxhQUFRLEdBQW9CLEVBQUUsQ0FBQztRQUMvQixhQUFRLEdBQW9CLElBQUksQ0FBQztRQUNqQyxzQkFBaUIsR0FBMEMsT0FBTyxDQUFDO1FBQ25FLFlBQU8sR0FBNEIsb0NBQW9DLENBQUMsT0FBTyxDQUFDO1FBQ2hGLGNBQVMsR0FBd0IsR0FBRyxDQUFD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QztJQUNqQixDQUFDOytHQXZVVSwyQkFBMkIsaUdBdUJsQixRQUFRO21HQXZCakIsMkJBQTJCOzs0RkFBM0IsMkJBQTJCO2tCQUp2QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSx1QkFBdUI7b0JBQ2pDLFFBQVEsRUFBRSxxQkFBcUI7aUJBQ2hDOzswQkF3QmMsTUFBTTsyQkFBQyxRQUFRO3lDQXRCbkIsUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUlHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBJbmplY3QsIElucHV0LCBOZ1pvbmUsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBtZXJnZSBhcyBtZXJnZVN0YXRpYywgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YXAsIHRocm90dGxlVGltZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IERyYWdEcm9wU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2RyYWctZHJvcC5zZXJ2aWNlJztcbmltcG9ydCB7IFV0aWxzIH0gZnJvbSAnLi4vc2hhcmVkL3V0aWxzJztcbmltcG9ydCB7XG4gIERyb3BTY3JvbGxBcmVhT2Zmc2V0LCBEcm9wU2Nyb2xsRGlyZWN0aW9uLCBEcm9wU2Nyb2xsRW5oYW5jZVRpbWluZ0Z1bmN0aW9uR3JvdXAsIERyb3BTY3JvbGxPcmllbnRhdGlvbixcbiAgRHJvcFNjcm9sbFNwZWVkLCBEcm9wU2Nyb2xsU3BlZWRGdW5jdGlvbiwgRHJvcFNjcm9sbFRyaWdnZXJFZGdlXG59IGZyb20gJy4vZHJvcC1zY3JvbGwtZW5oYW5jZS50eXBlJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2REcm9wU2Nyb2xsRW5oYW5jZWRdJyxcbiAgZXhwb3J0QXM6ICdkRHJvcFNjcm9sbEVuaGFuY2VkJ1xufSlcbmV4cG9ydCBjbGFzcyBEcm9wU2Nyb2xsRW5oYW5jZWREaXJlY3RpdmUgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKSBtaW5TcGVlZDogRHJvcFNjcm9sbFNwZWVkID0gNTA7XG4gIEBJbnB1dCgpIG1heFNwZWVkOiBEcm9wU2Nyb2xsU3BlZWQgPSAxMDAwO1xuICBASW5wdXQoKSByZXNwb25zZUVkZ2VXaWR0aDogc3RyaW5nIHwgKCh0b3RhbDogbnVtYmVyKSA9PiBzdHJpbmcpICA9ICcxMDBweCc7XG4gIEBJbnB1dCgpIHNwZWVkRm46IERyb3BTY3JvbGxTcGVlZEZ1bmN0aW9uID0gRHJvcFNjcm9sbEVuaGFuY2VUaW1pbmdGdW5jdGlvbkdyb3VwLmRlZmF1bHQ7XG4gIEBJbnB1dCgpIGRpcmVjdGlvbjogRHJvcFNjcm9sbERpcmVjdGlvbiA9ICd2JztcbiAgQElucHV0KCkgdmlld09mZnNldDoge1xuICAgIGZvcndhcmQ/OiBEcm9wU2Nyb2xsQXJlYU9mZnNldDsgLy8g5LuF6YeN6KaB6L655ZKM5qyh6KaB6L655pyJ5pWIXG4gICAgYmFja3dhcmQ/OiBEcm9wU2Nyb2xsQXJlYU9mZnNldDtcbiAgfTtcbiAgQElucHV0KCkgZHJvcFNjcm9sbFNjb3BlOiBzdHJpbmcgfCBBcnJheTxzdHJpbmc+O1xuICBASW5wdXQoKSBiYWNrU3BhY2VEcm9wcGFibGUgPSB0cnVlO1xuXG4gIHByaXZhdGUgZm9yd2FyZFNjcm9sbEFyZWE6IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIGJhY2t3YXJkU2Nyb2xsQXJlYTogSFRNTEVsZW1lbnQ7XG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIHByaXZhdGUgZm9yd2FyZFNjcm9sbEZuOiAoZXZlbnQ6IERyYWdFdmVudCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBiYWNrd2FyZFNjcm9sbEZuOiAoZXZlbnQ6IERyYWdFdmVudCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBsYXN0U2Nyb2xsVGltZTtcbiAgcHJpdmF0ZSBhbmltYXRpb25GcmFtZUlkOiBudW1iZXI7XG4gIGRvY3VtZW50OiBEb2N1bWVudDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsOiBFbGVtZW50UmVmLCBwcml2YXRlIHpvbmU6IE5nWm9uZSwgcHJpdmF0ZSBkcmFnRHJvcFNlcnZpY2U6IERyYWdEcm9wU2VydmljZSxcbiAgICAgICAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2M6IGFueSkge1xuICAgIHRoaXMuZG9jdW1lbnQgPSB0aGlzLmRvYztcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICAvLyDorr7nva7niLblhYPntKBcbiAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQucGFyZW50Tm9kZS5zdHlsZS5wb3NpdGlvbiA9ICdyZWxhdGl2ZSc7XG4gICAgdGhpcy5lbC5uYXRpdmVFbGVtZW50LnBhcmVudE5vZGUuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgLy8g5Yib5bu65ZCO6YCA5YmN6L+b5Yy65Z+f5ZKM5a+55bqU55qE5rua5Yqo5Ye95pWwXG4gICAgdGhpcy5mb3J3YXJkU2Nyb2xsQXJlYSA9IHRoaXMuY3JlYXRlU2Nyb2xsQXJlYSh0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQpO1xuICAgIHRoaXMuYmFja3dhcmRTY3JvbGxBcmVhID0gdGhpcy5jcmVhdGVTY3JvbGxBcmVhKHRoaXMuZGlyZWN0aW9uLCBEcm9wU2Nyb2xsT3JpZW50YXRpb24uYmFja3dhcmQpO1xuICAgIHRoaXMuZm9yd2FyZFNjcm9sbEZuID0gdGhpcy5jcmVhdGVTY3JvbGxGbih0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQsIHRoaXMuc3BlZWRGbik7XG4gICAgdGhpcy5iYWNrd2FyZFNjcm9sbEZuID0gdGhpcy5jcmVhdGVTY3JvbGxGbih0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmJhY2t3YXJkLCB0aGlzLnNwZWVkRm4pO1xuICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAvLyDmi5bmi73liLDlhbbkuIrop6blj5Hmu5rliqhcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZChmcm9tRXZlbnQ8RHJhZ0V2ZW50Pih0aGlzLmZvcndhcmRTY3JvbGxBcmVhLCAnZHJhZ292ZXInKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICB0YXAoZXZlbnQgPT4ge2V2ZW50LnByZXZlbnREZWZhdWx0KCk7IGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyB9KSxcbiAgICAgICAgICB0aHJvdHRsZVRpbWUoMTAwLCB1bmRlZmluZWQsIHtsZWFkaW5nOiB0cnVlLCB0cmFpbGluZzogZmFsc2V9KVxuICAgICAgICApLnN1YnNjcmliZShldmVudCA9PiB0aGlzLmZvcndhcmRTY3JvbGxGbihldmVudCkpKTtcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZChmcm9tRXZlbnQ8RHJhZ0V2ZW50Pih0aGlzLmJhY2t3YXJkU2Nyb2xsQXJlYSwgJ2RyYWdvdmVyJylcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFwKGV2ZW50ID0+IHtldmVudC5wcmV2ZW50RGVmYXVsdCgpOyBldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgfSksXG4gICAgICAgICAgdGhyb3R0bGVUaW1lKDEwMCwgdW5kZWZpbmVkLCB7bGVhZGluZzogdHJ1ZSwgdHJhaWxpbmc6IGZhbHNlfSkpXG4gICAgICAgIC5zdWJzY3JpYmUoZXZlbnQgPT4gdGhpcy5iYWNrd2FyZFNjcm9sbEZuKGV2ZW50KSkpO1xuICAgICAgLy8g5ouW5ou95pS+572u5aeU5omYXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQoXG4gICAgICAgIG1lcmdlU3RhdGljKFxuICAgICAgICAgIGZyb21FdmVudDxEcmFnRXZlbnQ+KHRoaXMuZm9yd2FyZFNjcm9sbEFyZWEsICdkcm9wJyksXG4gICAgICAgICAgZnJvbUV2ZW50PERyYWdFdmVudD4odGhpcy5iYWNrd2FyZFNjcm9sbEFyZWEsICdkcm9wJylcbiAgICAgICAgKS5zdWJzY3JpYmUoZXZlbnQgPT4gdGhpcy5kZWxlZ2F0ZURyb3BFdmVudChldmVudCkpKTtcbiAgICAgIC8vIOaLluaLveemu+W8gOa4hemZpOWPguaVsFxuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgICBtZXJnZVN0YXRpYyhcbiAgICAgICAgICBmcm9tRXZlbnQodGhpcy5mb3J3YXJkU2Nyb2xsQXJlYSwgJ2RyYWdsZWF2ZScsIHtwYXNzaXZlOiB0cnVlfSksXG4gICAgICAgICAgZnJvbUV2ZW50KHRoaXMuYmFja3dhcmRTY3JvbGxBcmVhLCAnZHJhZ2xlYXZlJywge3Bhc3NpdmU6IHRydWV9KVxuICAgICAgICApLnN1YnNjcmliZShldmVudCA9PiB0aGlzLmNsZWFuTGFzdFNjcm9sbFRpbWUoKSlcbiAgICAgICk7XG4gICAgICAvLyDmu5rliqjov4fnqIvorqHnrpfljLrln5/mnInmlYjmgKfvvIzmu5rliqjmnaHotLTliLDovrnnvJjnmoTml7blgJnml6DmlYjvvIzml6DmlYjnmoTml7blgJnorr7nva7pvKDmoIfkuovku7blj6/nlKjkuLpub25lXG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbi5hZGQoXG4gICAgICAgIGZyb21FdmVudCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsICdzY3JvbGwnLCB7cGFzc2l2ZTogdHJ1ZX0pXG4gICAgICAgICAgLnBpcGUodGhyb3R0bGVUaW1lKDMwMCwgdW5kZWZpbmVkLCB7bGVhZGluZzogdHJ1ZSwgdHJhaWxpbmc6IHRydWV9KSlcbiAgICAgICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHtcbiAgICAgICAgICAgIHRoaXMudG9nZ2xlU2Nyb2xsVG9PbmVFbmQodGhpcy5lbC5uYXRpdmVFbGVtZW50LCB0aGlzLmZvcndhcmRTY3JvbGxBcmVhLCB0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmZvcndhcmQpO1xuICAgICAgICAgICAgdGhpcy50b2dnbGVTY3JvbGxUb09uZUVuZCh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsIHRoaXMuYmFja3dhcmRTY3JvbGxBcmVhLCB0aGlzLmRpcmVjdGlvbiwgRHJvcFNjcm9sbE9yaWVudGF0aW9uLmJhY2t3YXJkKTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcbiAgICAgIC8vIOeql+WPo+e8qeaUvueahOaXtuWAmemHjee7mOacieaViOaAp+WMuuWfn1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgICBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJywge3Bhc3NpdmU6IHRydWV9KVxuICAgICAgICAgIC5waXBlKHRocm90dGxlVGltZSgzMDAsIHVuZGVmaW5lZCwge2xlYWRpbmc6IHRydWUsIHRyYWlsaW5nOiB0cnVlfSkpXG4gICAgICAgICAgLnN1YnNjcmliZShldmVudCA9PiB0aGlzLnJlc2l6ZUFyZWEoKSlcbiAgICAgICk7XG4gICAgICAvLyBkcmFnc3RhcnTnmoTml7blgJnmmL7npLrmi5bmi73mu5rliqjovrnnvJjpnaLmnb9cbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZChcbiAgICAgICAgdGhpcy5kcmFnRHJvcFNlcnZpY2UuZHJhZ1N0YXJ0RXZlbnQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICBpZiAoIXRoaXMuYWxsb3dTY3JvbGwoKSkge3JldHVybjsgfVxuICAgICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgLy8g56uL6ams5Ye6546w5Lya5omT5pat6L6557yY5YWD57Sg55qE5ouW5ou9XG4gICAgICAgICAgICAgIHRoaXMuZm9yd2FyZFNjcm9sbEFyZWEuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgICAgICAgIHRoaXMuYmFja3dhcmRTY3JvbGxBcmVhLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgICAgLy8gZHJhZ0VuZOaIlmRyb3DnmoTml7blgJnnu5PmnZ/kuobmi5bmi73vvIzmu5rliqjljLrln5/lvbHol4/otbfmnaVcbiAgICAgIHRoaXMuc3Vic2NyaXB0aW9uLmFkZChcbiAgICAgICAgbWVyZ2VTdGF0aWModGhpcy5kcmFnRHJvcFNlcnZpY2UuZHJhZ0VuZEV2ZW50LCB0aGlzLmRyYWdEcm9wU2VydmljZS5kcm9wRXZlbnQpXG4gICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmZvcndhcmRTY3JvbGxBcmVhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICB0aGlzLmJhY2t3YXJkU2Nyb2xsQXJlYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgdGhpcy5sYXN0U2Nyb2xsVGltZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMucmVzaXplQXJlYSgpO1xuICAgIH0sIDApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIGNyZWF0ZVNjcm9sbEZuKGRpcmVjdGlvbjogRHJvcFNjcm9sbERpcmVjdGlvbiwgb3JpZW50YXRpb246IERyb3BTY3JvbGxPcmllbnRhdGlvbixcbiAgICAgICAgICAgICAgICAgc3BlZWRGbjogRHJvcFNjcm9sbFNwZWVkRnVuY3Rpb24pIHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3Qgc2Nyb2xsQXR0ciA9IChkaXJlY3Rpb24gPT09ICd2JykgPyAnc2Nyb2xsVG9wJyA6ICdzY3JvbGxMZWZ0JztcbiAgICBjb25zdCBldmVudEF0dHIgPSAoZGlyZWN0aW9uID09PSAndicpID8gJ2NsaWVudFknIDogJ2NsaWVudFgnO1xuICAgIGNvbnN0IHNjcm9sbFdpZHRoQXR0ciA9IChkaXJlY3Rpb24gPT09ICd2JykgPyAnc2Nyb2xsSGVpZ2h0JyA6ICdzY3JvbGxXaWR0aCc7XG4gICAgY29uc3Qgb2Zmc2V0V2lkdGhBdHRyID0gKGRpcmVjdGlvbiA9PT0gJ3YnKSA/ICdvZmZzZXRIZWlnaHQnIDogJ29mZnNldFdpZHRoJztcbiAgICBjb25zdCBjbGllbnRXaWR0aEF0dHIgPSAoZGlyZWN0aW9uID09PSAndicpID8gJ2NsaWVudEhlaWdodCcgOiAnY2xpZW50V2lkdGgnO1xuICAgIGNvbnN0IHJlY3RXaWR0aEF0dHIgPSAoZGlyZWN0aW9uID09PSAndicpID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICAgIGNvbnN0IGNvbXBhcmVUYXJnZXQgPSAob3JpZW50YXRpb24gPT09IERyb3BTY3JvbGxPcmllbnRhdGlvbi5mb3J3YXJkKSA/IHRoaXMuZm9yd2FyZFNjcm9sbEFyZWEgOiB0aGlzLmJhY2t3YXJkU2Nyb2xsQXJlYTtcbiAgICBjb25zdCB0YXJnZXRBdHRyID0gdGhpcy5nZXRDcml0aWNhbEVkZ2UoZGlyZWN0aW9uLCBvcmllbnRhdGlvbik7XG4gICAgY29uc3Qgc2Nyb2xsRWxlbWVudCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudDtcblxuICAgIHJldHVybiAoZXZlbnQ6IERyYWdFdmVudCkgPT4ge1xuICAgICAgY29uc3QgY29tcGFyZVRhcmdldFJlY3QgPSBjb21wYXJlVGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3QgZGlzdGFuY2UgPSBldmVudFtldmVudEF0dHJdIC0gY29tcGFyZVRhcmdldFJlY3RbdGFyZ2V0QXR0cl07XG4gICAgICBsZXQgc3BlZWQgPSBzcGVlZEZuKE1hdGguYWJzKGRpc3RhbmNlIC8gKGNvbXBhcmVUYXJnZXRSZWN0W3JlY3RXaWR0aEF0dHJdIHx8IDEpKSk7XG4gICAgICBpZiAoc3BlZWQgPCB0aGlzLm1pblNwZWVkKSB7IHNwZWVkID0gdGhpcy5taW5TcGVlZDsgfVxuICAgICAgaWYgKHNwZWVkID4gdGhpcy5tYXhTcGVlZCkgeyBzcGVlZCA9IHRoaXMubWF4U3BlZWQ7IH1cbiAgICAgIGlmIChkaXN0YW5jZSA8IDApIHsgc3BlZWQgPSAtIHNwZWVkOyB9XG4gICAgICBpZiAodGhpcy5hbmltYXRpb25GcmFtZUlkKSB7XG4gICAgICAgIHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLmFuaW1hdGlvbkZyYW1lSWQpO1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lSWQgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICBjb25zdCB0aW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgIGNvbnN0IG1vdmVEaXN0YW5jZSA9IE1hdGguY2VpbChzcGVlZCAqICh0aW1lIC0gKHRoaXMubGFzdFNjcm9sbFRpbWUgfHwgdGltZSkpIC8gMTAwMCk7XG4gICAgICAgIHNjcm9sbEVsZW1lbnRbc2Nyb2xsQXR0cl0gLT0gbW92ZURpc3RhbmNlO1xuICAgICAgICB0aGlzLmxhc3RTY3JvbGxUaW1lID0gdGltZTtcbiAgICAgICAgLy8g5Yik5pat5piv5LiN5piv5Yiw5bC95aS0XG4gICAgICAgIGlmICgoc2Nyb2xsRWxlbWVudFtzY3JvbGxBdHRyXSA9PT0gMCAmJiBvcmllbnRhdGlvbiA9PT0gRHJvcFNjcm9sbE9yaWVudGF0aW9uLmJhY2t3YXJkKVxuICAgICAgICB8fCAoKHNjcm9sbEVsZW1lbnRbc2Nyb2xsQXR0cl1cbiAgICAgICAgICArIChzY3JvbGxFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpKVtyZWN0V2lkdGhBdHRyXVxuICAgICAgICAgIC0gc2Nyb2xsRWxlbWVudFtvZmZzZXRXaWR0aEF0dHJdXG4gICAgICAgICAgKyBzY3JvbGxFbGVtZW50W2NsaWVudFdpZHRoQXR0cl1cbiAgICAgICAgKSA9PT0gc2Nyb2xsRWxlbWVudFtzY3JvbGxXaWR0aEF0dHJdXG4gICAgICAgICAgJiYgb3JpZW50YXRpb24gPT09IERyb3BTY3JvbGxPcmllbnRhdGlvbi5mb3J3YXJkKVxuICAgICAgICApIHtcbiAgICAgICAgICBjb21wYXJlVGFyZ2V0LnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgICAgdGhpcy50b2dnbGVBY3RpdmVDbGFzcyhjb21wYXJlVGFyZ2V0LCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hbmltYXRpb25GcmFtZUlkID0gdW5kZWZpbmVkO1xuICAgICAgfSk7XG4gICAgICBpZiAodGhpcy5iYWNrU3BhY2VEcm9wcGFibGUpIHtcbiAgICAgICAgVXRpbHMuZGlzcGF0Y2hFdmVudFRvVW5kZXJFbGVtZW50KGV2ZW50KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGRlbGVnYXRlRHJvcEV2ZW50KGV2ZW50OiBEcmFnRXZlbnQpIHtcbiAgICBpZiAodGhpcy5iYWNrU3BhY2VEcm9wcGFibGUpIHtcbiAgICAgIGNvbnN0IGV2ID0gVXRpbHMuZGlzcGF0Y2hFdmVudFRvVW5kZXJFbGVtZW50KGV2ZW50KTtcbiAgICAgIGlmIChldi5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBnZXRDcml0aWNhbEVkZ2UoZGlyZWN0aW9uOiBEcm9wU2Nyb2xsRGlyZWN0aW9uLCBvcmllbnRhdGlvbjogRHJvcFNjcm9sbE9yaWVudGF0aW9uKTogRHJvcFNjcm9sbFRyaWdnZXJFZGdlIHtcbiAgICByZXR1cm4gKGRpcmVjdGlvbiA9PT0gJ3YnICYmIG9yaWVudGF0aW9uID09PSBEcm9wU2Nyb2xsT3JpZW50YXRpb24uZm9yd2FyZCAmJiAnYm90dG9tJylcbiAgICB8fCAoZGlyZWN0aW9uID09PSAndicgJiYgb3JpZW50YXRpb24gPT09IERyb3BTY3JvbGxPcmllbnRhdGlvbi5iYWNrd2FyZCAmJiAndG9wJylcbiAgICB8fCAoZGlyZWN0aW9uICE9PSAndicgJiYgb3JpZW50YXRpb24gPT09IERyb3BTY3JvbGxPcmllbnRhdGlvbi5mb3J3YXJkICYmICdyaWdodCcpXG4gICAgfHwgKGRpcmVjdGlvbiAhPT0gJ3YnICYmIG9yaWVudGF0aW9uID09PSBEcm9wU2Nyb2xsT3JpZW50YXRpb24uYmFja3dhcmQgJiYgJ2xlZnQnKSB8fCAnYm90dG9tJztcbiAgfVxuICBnZXRTZWNvbmRFZGdlKGRpcmVjdGlvbjogRHJvcFNjcm9sbERpcmVjdGlvbik6IERyb3BTY3JvbGxUcmlnZ2VyRWRnZSB7XG4gICAgcmV0dXJuIChkaXJlY3Rpb24gPT09ICd2JyAmJiAnbGVmdCcpXG4gICAgfHwgKGRpcmVjdGlvbiAhPT0gJ3YnICYmICAndG9wJykgfHwgJ2xlZnQnO1xuICB9XG5cbiAgY3JlYXRlU2Nyb2xsQXJlYShkaXJlY3Rpb246IERyb3BTY3JvbGxEaXJlY3Rpb24sIG9yaWVudGF0aW9uOiBEcm9wU2Nyb2xsT3JpZW50YXRpb24pIHtcbiAgICBjb25zdCBhcmVhID0gdGhpcy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBhcmVhLmNsYXNzTmFtZSA9IGBkcm9wb3Zlci1zY3JvbGwtYXJlYSBkcm9wb3Zlci1zY3JvbGwtYXJlYS0ke3RoaXMuZ2V0Q3JpdGljYWxFZGdlKGRpcmVjdGlvbiwgb3JpZW50YXRpb24pfWA7XG4gICAgLy8g5aSE55CG5aSn5bCPXG4gICAgYXJlYS5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKTtcbiAgICB0aGlzLnNldEFyZWFTaXplKGFyZWEsIGRpcmVjdGlvbiwgb3JpZW50YXRpb24pO1xuICAgIC8vIOWkhOeQhuS9jee9rlxuICAgIGFyZWEuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIHRoaXMuc2V0QXJlYVN0eWxlTGF5b3V0KGFyZWEsIGRpcmVjdGlvbiwgb3JpZW50YXRpb24pO1xuXG4gICAgLy8g6buY6K6k5LiN5bGV56S6XG4gICAgYXJlYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIC8vIOmZhOedgOWFg+e0oFxuICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5wYXJlbnROb2RlLmFwcGVuZENoaWxkKGFyZWEsIHRoaXMuZWwubmF0aXZlRWxlbWVudCk7XG4gICAgcmV0dXJuIGFyZWE7XG4gIH1cblxuICBzZXRBcmVhU2l6ZShhcmVhOiBIVE1MRWxlbWVudCwgZGlyZWN0aW9uOiBEcm9wU2Nyb2xsRGlyZWN0aW9uLCBvcmllbnRhdGlvbjogRHJvcFNjcm9sbE9yaWVudGF0aW9uKSB7XG4gICAgY29uc3QgcmVjdCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBjb250YWluZXJBdHRyID0gZGlyZWN0aW9uID09PSAndicgPyAnaGVpZ2h0JyA6ICd3aW