UNPKG

carousel-angular

Version:

A simple carousel component for Angular 14+ based on 'angular-responsive-carousel' by Ivy Laboratory http://ivylab.space

362 lines 50.2 kB
import { Component, EventEmitter, HostBinding, HostListener, Input, Output } from '@angular/core'; import { Touches } from './touches'; import { Carousel } from './carousel'; import { Container } from './container'; import { Cells } from './cells'; import { Slide } from './slide'; import { Utils } from './utils'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class CarouselComponent { constructor(elementRef, ref) { this.elementRef = elementRef; this.ref = ref; this._isCounter = false; this._cellWidth = 200; this.isMoving = false; this.isNgContent = false; this.events = new EventEmitter(); this.height = 450; this.autoplay = true; this.autoplayInterval = 5000; this.pauseOnHover = true; this.dots = false; this.margin = 10; this.objectFit = 'cover'; this.minSwipeDistance = 10; this.transitionDuration = 200; this.transitionTimingFunction = 'ease-out'; this.counterSeparator = ' / '; this.overflowCellsLimit = 3; this.listeners = 'mouse and touch'; this.cellsToShow = 1; this.cellsToScroll = 1; this.freeScroll = false; this.arrows = true; this.arrowsOutside = false; this.arrowsTheme = 'light'; this.hostClassCarousel = true; this.handleTouchstart = (event) => { this.touches.addEventListeners('mousemove', 'handleMousemove'); this.carousel.handleTouchstart(event); this.isMoving = true; }; this.handleHorizontalSwipe = (event) => { event.preventDefault(); this.carousel.handleHorizontalSwipe(event); }; this.handleTouchend = (event) => { const { touches } = event; this.carousel.handleTouchend(event); this.touches.removeEventListeners('mousemove', 'handleMousemove'); this.isMoving = false; }; this.handleTap = (event) => { const outboundEvent = { name: 'click' }; const nodes = Array.prototype.slice.call(this.cellsElement.children); const cellElement = event.srcElement.closest('.carousel-cell'); const i = nodes.indexOf(cellElement); const cellIndex = nodes.indexOf(cellElement); outboundEvent.cellIndex = cellIndex; }; } get slideCounter() { if (this.carousel) { return this.carousel.slideCounter; } } get lapCounter() { if (this.carousel) { return this.carousel.lapCounter; } } get isLandscape() { return window.innerWidth > window.innerHeight; } get isSafari() { const ua = navigator.userAgent.toLowerCase(); if (ua.indexOf('safari') !== -1) { return !(ua.indexOf('chrome') > -1); } } get counter() { const counter = this.slideCounter; return counter + 1 + this.counterSeparator + this.cellLength; } get cellsElement() { return this.elementRef.nativeElement.querySelector('.carousel-cells'); } get isArrows() { return this.arrows && !this.freeScroll; } get isCounter() { return this._isCounter && this.cellLength > 1; } get activeDotIndex() { return this.slideCounter % this.cellLength; } get cellLimit() { if (this.carousel) { return this.carousel.cellLimit; } } get carouselWidth() { return this.elementRef.nativeElement.clientWidth; } set cellWidth(value) { if (value) { this._cellWidth = value; } } set isCounter(value) { if (value) { this._isCounter = value; } } onWindowResize(event) { if (this.utils.visibleWidth !== this.savedCarouselWidth) { this.resize(); } } onMouseEnter() { if (this.autoplay && this.pauseOnHover) { this.carouselProperties.autoplayIsPossible = false; this.carousel.stopAutoplay(); } } onMouseLeave() { if (this.autoplay && this.pauseOnHover) { this.carouselProperties.autoplayIsPossible = true; this.carousel.autoplay(); } } onDragStart() { return false; } ngOnInit() { this.isNgContent = this.cellsElement.children.length > 0; this.touches = new Touches({ element: this.cellsElement, listeners: this.listeners, mouseListeners: { mousedown: 'handleMousedown', mouseup: 'handleMouseup' } }); this.touches.on('touchstart', this.handleTouchstart); this.touches.on('horizontal-swipe', this.handleHorizontalSwipe); this.touches.on('touchend', this.handleTouchend); this.touches.on('mousedown', this.handleTouchstart); this.touches.on('mouseup', this.handleTouchend); this.touches.on('tap', this.handleTap); this.setDimensions(); } ngAfterViewInit() { this.initCarousel(); this.cellLength = this.getCellLength(); this.dotsArr = Array(this.cellLength).fill(1); this.ref.detectChanges(); this.carousel.lineUpCells(); this.savedCarouselWidth = this.carouselWidth; /* Start detecting changes in the DOM tree */ this.detectDomChanges(); } ngOnChanges(changes) { const isFirstChange = Object.values(changes).some(change => change.isFirstChange()); if (!isFirstChange && (changes.width || changes.height)) { this.setDimensions(); this.initCarousel(); this.carousel.lineUpCells(); this.ref.detectChanges(); } } ngOnDestroy() { this.touches.destroy(); // this.carousel.destroy(); } initCarousel() { this.carouselProperties = { id: this.id, cellsElement: this.elementRef.nativeElement.querySelector('.carousel-cells'), hostElement: this.elementRef.nativeElement, cellWidth: this.getCellWidth(), autoplayInterval: this.autoplayInterval, autoplayIsPossible: true, overflowCellsLimit: this.overflowCellsLimit, visibleWidth: this.width, margin: this.margin, minSwipeDistance: this.minSwipeDistance, transitionDuration: this.transitionDuration, transitionTimingFunction: this.transitionTimingFunction, videoProperties: this.videoProperties, eventHandler: this.events, freeScroll: this.freeScroll }; this.utils = new Utils(this.carouselProperties); this.cells = new Cells(this.carouselProperties, this.utils); this.container = new Container(this.carouselProperties, this.utils, this.cells); this.slide = new Slide(this.carouselProperties, this.utils, this.cells, this.container); if (this.autoplay && this.carousel) { this.carousel.stopAutoplay(); } this.carousel = new Carousel(this.carouselProperties, this.utils, this.cells, this.container, this.slide); if (this.autoplay) { this.carousel.autoplay(); } } resize() { this.landscapeMode = this.isLandscape; this.savedCarouselWidth = this.carouselWidth; this.carouselProperties.cellWidth = this.getCellWidth(); this.cells.updateProperties(this.carouselProperties); this.carousel.updateProperties(this.carouselProperties); this.container.updateProperties(this.carouselProperties); this.slide.updateProperties(this.carouselProperties); this.utils.updateProperties(this.carouselProperties); this.carousel.lineUpCells(); this.slide.select(0); this.ref.detectChanges(); } detectDomChanges() { const observer = new MutationObserver((mutations) => { this.onDomChanges(); }); const config = { attributes: true, childList: true, characterData: true }; observer.observe(this.cellsElement, config); } onDomChanges() { this.cellLength = this.getCellLength(); this.carousel.lineUpCells(); this.ref.detectChanges(); } setDimensions() { this.hostStyleHeight = `${this.height}px`; this.hostStyleWidth = `${this.width}px`; } handleTransitionendCellContainer(event) { if (event.target.className === 'carousel-cells') { this.carousel.handleTransitionend(); } } getCellWidth() { const elementWidth = this.carouselWidth; if (this.cellsToShow) { const margin = this.cellsToShow > 1 ? this.margin : 0; const totalMargin = margin * (this.cellsToShow - 1); return (elementWidth - totalMargin) / this.cellsToShow; } if (this._cellWidth === '100%') { return elementWidth; } return this._cellWidth; } next() { this.carousel.next(this.cellsToScroll); this.carousel.stopAutoplay(); } prev() { this.carousel.prev(this.cellsToScroll); this.carousel.stopAutoplay(); } isNextArrowDisabled() { if (this.carousel) { return this.carousel.isNextArrowDisabled(); } } isPrevArrowDisabled() { if (this.carousel) { return this.carousel.isPrevArrowDisabled(); } } getCellLength() { return this.cellsElement.children.length; } } CarouselComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: CarouselComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); CarouselComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: CarouselComponent, selector: "carousel, [carousel]", inputs: { id: "id", height: "height", width: "width", autoplay: "autoplay", autoplayInterval: "autoplayInterval", pauseOnHover: "pauseOnHover", dots: "dots", borderRadius: "borderRadius", margin: "margin", objectFit: "objectFit", minSwipeDistance: "minSwipeDistance", transitionDuration: "transitionDuration", transitionTimingFunction: "transitionTimingFunction", videoProperties: "videoProperties", counterSeparator: "counterSeparator", overflowCellsLimit: "overflowCellsLimit", listeners: "listeners", cellsToShow: "cellsToShow", cellsToScroll: "cellsToScroll", freeScroll: "freeScroll", arrows: "arrows", arrowsOutside: "arrowsOutside", arrowsTheme: "arrowsTheme", cellWidth: "cellWidth", isCounter: ["counter", "isCounter"] }, outputs: { events: "events" }, host: { listeners: { "window:resize": "onWindowResize($event)", "mouseenter": "onMouseEnter($event)", "mouseleave": "onMouseLeave($event)", "dragstart": "onDragStart($event)" }, properties: { "class.carousel": "this.hostClassCarousel", "style.height": "this.hostStyleHeight", "style.width": "this.hostStyleWidth" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"carousel-counter\" *ngIf=\"isCounter\">{{counter}}</div>\r\n\r\n<div class=\"carousel-container\" [class.carousel-moving]=\"isMoving\">\r\n\t<div class=\"carousel-cells\" #cells (transitionend)=\"handleTransitionendCellContainer($event)\">\r\n\t\t<ng-content></ng-content>\r\n\t</div>\r\n\r\n\t<div class=\"carousel-dots\" *ngIf=\"dots\">\r\n\t\t<div class=\"carousel-dot\" [class.carousel-dot-active]=\"i === activeDotIndex\" *ngFor=\"let dot of dotsArr; index as i\"></div>\r\n\t</div>\r\n</div>\r\n\r\n<div class=\"carousel-arrows\"\r\n\t[class.carousel-arrows-outside]=\"arrowsOutside\"\r\n\t[class.carousel-dark-arrows]=\"arrowsTheme === 'dark'\"\r\n\t*ngIf=\"isArrows\">\r\n\r\n\t<div class=\"carousel-arrow carousel-arrow-prev\" [class.carousel-arrow-disabled]=\"isPrevArrowDisabled()\" (click)=\"prev()\"></div>\r\n\t<div class=\"carousel-arrow carousel-arrow-next\" [class.carousel-arrow-disabled]=\"isNextArrowDisabled()\" (click)=\"next()\"></div>\r\n</div>\r\n", styles: [":host{-webkit-user-select:none;user-select:none;position:relative;z-index:10000;top:0;left:0;transform-origin:top left;display:block;box-sizing:border-box;width:100%;height:100%}:host .carousel-container{cursor:grab;overflow:hidden;width:100%;height:100%}:host .carousel-container.carousel-moving{cursor:grabbing}:host .carousel-counter{position:absolute;z-index:30;top:8px;right:24px;padding:5px 7px;font-size:11px;line-height:initial;color:#fff;text-align:right;background-color:#1725444d;border-radius:13px;transition:opacity .2s}:host ::ng-deep .carousel-cells{will-change:transform;display:block;width:100%;height:100%;transition:transform .2s}:host ::ng-deep .carousel-cells .carousel-cell{position:absolute;overflow:hidden;width:100%;height:100%}:host ::ng-deep .carousel-cells .carousel-cell img,:host ::ng-deep .carousel-cells .carousel-cell video{position:relative;width:100%;height:100%;object-fit:contain}:host ::ng-deep .carousel-cells .carousel-cell img.swiper-hide{display:none}:host ::ng-deep .carousel-cells .carousel-cell .carousel-play{position:absolute;z-index:1;inset:0}:host .carousel-arrow{cursor:pointer;position:absolute;z-index:10;top:50%;display:inline-block;width:20px;height:20px;margin-top:-10px;opacity:0;border:solid rgba(255,255,255,.6);border-width:0 4px 4px 0;border-radius:2px;transition:opacity .1s ease-in-out}:host .carousel-arrow:before{content:\" \";position:absolute;top:-50px;left:-50px;display:inline-block;width:100px;height:100px;border:0}:host .carousel-arrow:hover{opacity:.5}:host .carousel-arrow-prev{left:35px;transform:rotate(135deg)}:host .carousel-arrow-next{right:35px;transform:rotate(-45deg)}:host .carousel-arrows-outside .carousel-arrow-prev{left:-60px}:host .carousel-arrows-outside .carousel-arrow-next{right:-60px}:host .carousel-dark-arrows .carousel-arrow{filter:invert(1)}:host .carousel-arrow-disabled{display:none}:host .carousel-dots{position:absolute;z-index:10;right:0;bottom:0;left:0;text-align:center}:host .carousel-dots .carousel-dot{display:inline-block;width:8px;height:8px;margin:4px;border:2px solid #fff;border-radius:100px}:host .carousel-dots .carousel-dot-active{background-color:#fff}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: CarouselComponent, decorators: [{ type: Component, args: [{ selector: 'carousel, [carousel]', template: "<div class=\"carousel-counter\" *ngIf=\"isCounter\">{{counter}}</div>\r\n\r\n<div class=\"carousel-container\" [class.carousel-moving]=\"isMoving\">\r\n\t<div class=\"carousel-cells\" #cells (transitionend)=\"handleTransitionendCellContainer($event)\">\r\n\t\t<ng-content></ng-content>\r\n\t</div>\r\n\r\n\t<div class=\"carousel-dots\" *ngIf=\"dots\">\r\n\t\t<div class=\"carousel-dot\" [class.carousel-dot-active]=\"i === activeDotIndex\" *ngFor=\"let dot of dotsArr; index as i\"></div>\r\n\t</div>\r\n</div>\r\n\r\n<div class=\"carousel-arrows\"\r\n\t[class.carousel-arrows-outside]=\"arrowsOutside\"\r\n\t[class.carousel-dark-arrows]=\"arrowsTheme === 'dark'\"\r\n\t*ngIf=\"isArrows\">\r\n\r\n\t<div class=\"carousel-arrow carousel-arrow-prev\" [class.carousel-arrow-disabled]=\"isPrevArrowDisabled()\" (click)=\"prev()\"></div>\r\n\t<div class=\"carousel-arrow carousel-arrow-next\" [class.carousel-arrow-disabled]=\"isNextArrowDisabled()\" (click)=\"next()\"></div>\r\n</div>\r\n", styles: [":host{-webkit-user-select:none;user-select:none;position:relative;z-index:10000;top:0;left:0;transform-origin:top left;display:block;box-sizing:border-box;width:100%;height:100%}:host .carousel-container{cursor:grab;overflow:hidden;width:100%;height:100%}:host .carousel-container.carousel-moving{cursor:grabbing}:host .carousel-counter{position:absolute;z-index:30;top:8px;right:24px;padding:5px 7px;font-size:11px;line-height:initial;color:#fff;text-align:right;background-color:#1725444d;border-radius:13px;transition:opacity .2s}:host ::ng-deep .carousel-cells{will-change:transform;display:block;width:100%;height:100%;transition:transform .2s}:host ::ng-deep .carousel-cells .carousel-cell{position:absolute;overflow:hidden;width:100%;height:100%}:host ::ng-deep .carousel-cells .carousel-cell img,:host ::ng-deep .carousel-cells .carousel-cell video{position:relative;width:100%;height:100%;object-fit:contain}:host ::ng-deep .carousel-cells .carousel-cell img.swiper-hide{display:none}:host ::ng-deep .carousel-cells .carousel-cell .carousel-play{position:absolute;z-index:1;inset:0}:host .carousel-arrow{cursor:pointer;position:absolute;z-index:10;top:50%;display:inline-block;width:20px;height:20px;margin-top:-10px;opacity:0;border:solid rgba(255,255,255,.6);border-width:0 4px 4px 0;border-radius:2px;transition:opacity .1s ease-in-out}:host .carousel-arrow:before{content:\" \";position:absolute;top:-50px;left:-50px;display:inline-block;width:100px;height:100px;border:0}:host .carousel-arrow:hover{opacity:.5}:host .carousel-arrow-prev{left:35px;transform:rotate(135deg)}:host .carousel-arrow-next{right:35px;transform:rotate(-45deg)}:host .carousel-arrows-outside .carousel-arrow-prev{left:-60px}:host .carousel-arrows-outside .carousel-arrow-next{right:-60px}:host .carousel-dark-arrows .carousel-arrow{filter:invert(1)}:host .carousel-arrow-disabled{display:none}:host .carousel-dots{position:absolute;z-index:10;right:0;bottom:0;left:0;text-align:center}:host .carousel-dots .carousel-dot{display:inline-block;width:8px;height:8px;margin:4px;border:2px solid #fff;border-radius:100px}:host .carousel-dots .carousel-dot-active{background-color:#fff}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { events: [{ type: Output }], id: [{ type: Input }], height: [{ type: Input }], width: [{ type: Input }], autoplay: [{ type: Input }], autoplayInterval: [{ type: Input }], pauseOnHover: [{ type: Input }], dots: [{ type: Input }], borderRadius: [{ type: Input }], margin: [{ type: Input }], objectFit: [{ type: Input }], minSwipeDistance: [{ type: Input }], transitionDuration: [{ type: Input }], transitionTimingFunction: [{ type: Input }], videoProperties: [{ type: Input }], counterSeparator: [{ type: Input }], overflowCellsLimit: [{ type: Input }], listeners: [{ type: Input }], cellsToShow: [{ type: Input }], cellsToScroll: [{ type: Input }], freeScroll: [{ type: Input }], arrows: [{ type: Input }], arrowsOutside: [{ type: Input }], arrowsTheme: [{ type: Input }], cellWidth: [{ type: Input, args: ['cellWidth'] }], isCounter: [{ type: Input, args: ['counter'] }], hostClassCarousel: [{ type: HostBinding, args: ['class.carousel'] }], hostStyleHeight: [{ type: HostBinding, args: ['style.height'] }], hostStyleWidth: [{ type: HostBinding, args: ['style.width'] }], onWindowResize: [{ type: HostListener, args: ['window:resize', ['$event']] }], onMouseEnter: [{ type: HostListener, args: ['mouseenter', ['$event']] }], onMouseLeave: [{ type: HostListener, args: ['mouseleave', ['$event']] }], onDragStart: [{ type: HostListener, args: ['dragstart', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvY2Fyb3VzZWwtYW5ndWxhci9zcmMvbGliL2Nhcm91c2VsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uL3Byb2plY3RzL2Nhcm91c2VsLWFuZ3VsYXIvc3JjL2xpYi9jYXJvdXNlbC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUVULFlBQVksRUFDWixXQUFXLEVBQ1gsWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEVBR1AsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7OztBQU9oQyxNQUFNLE9BQU8saUJBQWlCO0lBd0w1QixZQUFvQixVQUFzQixFQUFVLEdBQXNCO1FBQXRELGVBQVUsR0FBVixVQUFVLENBQVk7UUFBVSxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQXpLMUUsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUVuQixlQUFVLEdBQW9CLEdBQUcsQ0FBQztRQUVsQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBRWpCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBZ0VWLFdBQU0sR0FBc0IsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUlyRCxXQUFNLEdBQUcsR0FBRyxDQUFDO1FBSWIsYUFBUSxHQUFHLElBQUksQ0FBQztRQUVoQixxQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFFeEIsaUJBQVksR0FBRyxJQUFJLENBQUM7UUFFcEIsU0FBSSxHQUFHLEtBQUssQ0FBQztRQUliLFdBQU0sR0FBRyxFQUFFLENBQUM7UUFFWixjQUFTLEdBQWlDLE9BQU8sQ0FBQztRQUVsRCxxQkFBZ0IsR0FBRyxFQUFFLENBQUM7UUFFdEIsdUJBQWtCLEdBQUcsR0FBRyxDQUFDO1FBRXpCLDZCQUF3QixHQUtsQixVQUFVLENBQUM7UUFJakIscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBRXpCLHVCQUFrQixHQUFHLENBQUMsQ0FBQztRQUV2QixjQUFTLEdBQStCLGlCQUFpQixDQUFDO1FBRTFELGdCQUFXLEdBQUcsQ0FBQyxDQUFDO1FBRWhCLGtCQUFhLEdBQUcsQ0FBQyxDQUFDO1FBRWxCLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFFbkIsV0FBTSxHQUFHLElBQUksQ0FBQztRQUVkLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBRXRCLGdCQUFXLEdBQXFCLE9BQU8sQ0FBQztRQWNsQixzQkFBaUIsR0FBRyxJQUFJLENBQUM7UUE4S3hELHFCQUFnQixHQUFHLENBQUMsS0FBVSxFQUFFLEVBQUU7WUFDaEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUMvRCxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3ZCLENBQUMsQ0FBQztRQUVGLDBCQUFxQixHQUFHLENBQUMsS0FBVSxFQUFFLEVBQUU7WUFDckMsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxRQUFRLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0MsQ0FBQyxDQUFDO1FBRUYsbUJBQWMsR0FBRyxDQUFDLEtBQVUsRUFBRSxFQUFFO1lBQzlCLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUM7WUFDMUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUNsRSxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUN4QixDQUFDLENBQUM7UUFFRixjQUFTLEdBQUcsQ0FBQyxLQUFVLEVBQUUsRUFBRTtZQUN6QixNQUFNLGFBQWEsR0FBUTtnQkFDekIsSUFBSSxFQUFFLE9BQU87YUFDZCxDQUFDO1lBQ0YsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckUsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFN0MsYUFBYSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDdEMsQ0FBQyxDQUFDO0lBeEsyRSxDQUFDO0lBeko5RSxJQUFJLFlBQVk7UUFDZCxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztTQUNuQztJQUNILENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDWixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQztTQUNqQztJQUNILENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLE1BQU0sQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQztJQUNoRCxDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1YsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM3QyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFDL0IsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3JDO0lBQ0gsQ0FBQztJQUVELElBQUksT0FBTztRQUNULE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDbEMsT0FBTyxPQUFPLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQy9ELENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ3pDLENBQUM7SUFFRCxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVELElBQUksY0FBYztRQUNoQixPQUFPLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUM3QyxDQUFDO0lBRUQsSUFBSSxTQUFTO1FBQ1gsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7U0FDaEM7SUFDSCxDQUFDO0lBRUQsSUFBSSxhQUFhO1FBQ2YsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUM7SUFDbkQsQ0FBQztJQXVERCxJQUF3QixTQUFTLENBQUMsS0FBc0I7UUFDdEQsSUFBSSxLQUFLLEVBQUU7WUFDVCxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztTQUN6QjtJQUNILENBQUM7SUFFRCxJQUFzQixTQUFTLENBQUMsS0FBYztRQUM1QyxJQUFJLEtBQUssRUFBRTtZQUNULElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQVNELGNBQWMsQ0FBQyxLQUFVO1FBQ3ZCLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEtBQUssSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQ3ZELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUNmO0lBQ0gsQ0FBQztJQUdELFlBQVk7UUFDVixJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUN0QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsa0JBQWtCLEdBQUcsS0FBSyxDQUFDO1lBQ25ELElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLENBQUM7U0FDOUI7SUFDSCxDQUFDO0lBR0QsWUFBWTtRQUNWLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUM7WUFDbEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztTQUMxQjtJQUNILENBQUM7SUFHRCxXQUFXO1FBQ1QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBSUQsUUFBUTtRQUNOLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUV6RCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDO1lBQ3pCLE9BQU8sRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMxQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsY0FBYyxFQUFFO2dCQUNkLFNBQVMsRUFBRSxpQkFBaUI7Z0JBQzVCLE9BQU8sRUFBRSxlQUFlO2FBQ3pCO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUV2QyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7UUFFN0MsNkNBQTZDO1FBQzdDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDNUIsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQztRQUN4RixJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDdkQsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7U0FDMUI7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdkIsMkJBQTJCO0lBQzdCLENBQUM7SUFFRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLGtCQUFrQixHQUFHO1lBQ3hCLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtZQUNYLFlBQVksRUFDVixJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsaUJBQWlCLENBQUM7WUFDaEUsV0FBVyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYTtZQUMxQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUM5QixnQkFBZ0IsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO1lBQ3ZDLGtCQUFrQixFQUFFLElBQUk7WUFDeEIsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtZQUMzQyxZQUFZLEVBQUUsSUFBSSxDQUFDLEtBQUs7WUFDeEIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLGdCQUFnQixFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDdkMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtZQUMzQyx3QkFBd0IsRUFBRSxJQUFJLENBQUMsd0JBQXdCO1lBQ3ZELGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZTtZQUNyQyxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDekIsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQzVCLENBQUM7UUFFRixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1RCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksU0FBUyxDQUM1QixJQUFJLENBQUMsa0JBQWtCLEVBQ3ZCLElBQUksQ0FBQyxLQUFLLEVBQ1YsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO1FBQ0YsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FDcEIsSUFBSSxDQUFDLGtCQUFrQixFQUN2QixJQUFJLENBQUMsS0FBSyxFQUNWLElBQUksQ0FBQyxLQUFLLEVBQ1YsSUFBSSxDQUFDLFNBQVMsQ0FDZixDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDbEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztTQUM5QjtRQUNELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxRQUFRLENBQzFCLElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsSUFBSSxDQUFDLEtBQUssRUFDVixJQUFJLENBQUMsS0FBSyxFQUNWLElBQUksQ0FBQyxTQUFTLEVBQ2QsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDMUI7SUFDSCxDQUFDO0lBRUQsTUFBTTtRQUNKLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUN0QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUU3QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN4RCxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDeEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxnQkFBZ0I7UUFDZCxNQUFNLFFBQVEsR0FBRyxJQUFJLGdCQUFnQixDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDbEQsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxNQUFNLEdBQUc7WUFDYixVQUFVLEVBQUUsSUFBSTtZQUNoQixTQUFTLEVBQUUsSUFBSTtZQUNmLGFBQWEsRUFBRSxJQUFJO1NBQ3BCLENBQUM7UUFDRixRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVELFlBQVk7UUFDVixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVELGFBQWE7UUFDWCxJQUFJLENBQUMsZUFBZSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDO1FBQzFDLElBQUksQ0FBQyxjQUFjLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUM7SUFDMUMsQ0FBQztJQWdDRCxnQ0FBZ0MsQ0FBQyxLQUFVO1FBQ3pDLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEtBQUssZ0JBQWdCLEVBQUU7WUFDL0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1NBQ3JDO0lBQ0gsQ0FBQztJQUVELFlBQVk7UUFDVixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBRXhDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNwQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3RELE1BQU0sV0FBVyxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDcEQsT0FBTyxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1NBQ3hEO1FBRUQsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLE1BQU0sRUFBRTtZQUM5QixPQUFPLFlBQVksQ0FBQztTQUNyQjtRQUNELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUN6QixDQUFDO0lBRUQsSUFBSTtRQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxJQUFJO1FBQ0YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELG1CQUFtQjtRQUNqQixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLG1CQUFtQixFQUFFLENBQUM7U0FDNUM7SUFDSCxDQUFDO0lBRUQsbUJBQW1CO1FBQ2pCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNqQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztTQUM1QztJQUNILENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7SUFDM0MsQ0FBQzs7K0dBL1lVLGlCQUFpQjttR0FBakIsaUJBQWlCLHlvQ0MxQjlCLDI5QkFvQkE7NEZETWEsaUJBQWlCO2tCQUw3QixTQUFTOytCQUNFLHNCQUFzQjtpSUF5RnRCLE1BQU07c0JBQWYsTUFBTTtnQkFFRSxFQUFFO3NCQUFWLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUVHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBRUcsd0JBQXdCO3NCQUFoQyxLQUFLO2dCQU9HLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUVHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRWtCLFNBQVM7c0JBQWhDLEtBQUs7dUJBQUMsV0FBVztnQkFNSSxTQUFTO3NCQUE5QixLQUFLO3VCQUFDLFNBQVM7Z0JBTWUsaUJBQWlCO3NCQUEvQyxXQUFXO3VCQUFDLGdCQUFnQjtnQkFFQSxlQUFlO3NCQUEzQyxXQUFXO3VCQUFDLGNBQWM7Z0JBRUMsY0FBYztzQkFBekMsV0FBVzt1QkFBQyxhQUFhO2dCQUcxQixjQUFjO3NCQURiLFlBQVk7dUJBQUMsZUFBZSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVF6QyxZQUFZO3NCQURYLFlBQVk7dUJBQUMsWUFBWSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVN0QyxZQUFZO3NCQURYLFlBQVk7dUJBQUMsWUFBWSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVN0QyxXQUFXO3NCQURWLFlBQVk7dUJBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBPbkRlc3Ryb3ksXG4gIFNpbXBsZUNoYW5nZXNcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IFByb3BlcnRpZXMgYXMgQ2Fyb3VzZWxQcm9wZXJ0aWVzIH0gZnJvbSAnLi9pbnRlcmZhY2VzJztcbmltcG9ydCB7IFRvdWNoZXMgfSBmcm9tICcuL3RvdWNoZXMnO1xuaW1wb3J0IHsgQ2Fyb3VzZWwgfSBmcm9tICcuL2Nhcm91c2VsJztcbmltcG9ydCB7IENvbnRhaW5lciB9IGZyb20gJy4vY29udGFpbmVyJztcbmltcG9ydCB7IENlbGxzIH0gZnJvbSAnLi9jZWxscyc7XG5pbXBvcnQgeyBTbGlkZSB9IGZyb20gJy4vc2xpZGUnO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuL3V0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2Fyb3VzZWwsIFtjYXJvdXNlbF0nLFxuICB0ZW1wbGF0ZVVybDogJy4vY2Fyb3VzZWwuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jYXJvdXNlbC5jb21wb25lbnQuc2FzcyddXG59KVxuZXhwb3J0IGNsYXNzIENhcm91c2VsQ29tcG9uZW50IGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgY2Fyb3VzZWw6IGFueTtcblxuICBjb250YWluZXI6IGFueTtcblxuICB1dGlsczogYW55O1xuXG4gIGNlbGxzOiBhbnk7XG5cbiAgc2xpZGU6IGFueTtcblxuICB0b3VjaGVzOiBhbnk7XG5cbiAgbGFuZHNjYXBlTW9kZTogYW55O1xuXG4gIF9pc0NvdW50ZXIgPSBmYWxzZTtcblxuICBfY2VsbFdpZHRoOiBudW1iZXIgfCAnMTAwJScgPSAyMDA7XG5cbiAgaXNNb3ZpbmcgPSBmYWxzZTtcblxuICBpc05nQ29udGVudCA9IGZhbHNlO1xuXG4gIGNlbGxMZW5ndGghOiBudW1iZXI7XG5cbiAgZG90c0FycjogYW55O1xuXG4gIGNhcm91c2VsUHJvcGVydGllcyE6IENhcm91c2VsUHJvcGVydGllcztcblxuICBzYXZlZENhcm91c2VsV2lkdGghOiBudW1iZXI7XG5cbiAgZ2V0IHNsaWRlQ291bnRlcigpIHtcbiAgICBpZiAodGhpcy5jYXJvdXNlbCkge1xuICAgICAgcmV0dXJuIHRoaXMuY2Fyb3VzZWwuc2xpZGVDb3VudGVyO1xuICAgIH1cbiAgfVxuXG4gIGdldCBsYXBDb3VudGVyKCkge1xuICAgIGlmICh0aGlzLmNhcm91c2VsKSB7XG4gICAgICByZXR1cm4gdGhpcy5jYXJvdXNlbC5sYXBDb3VudGVyO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpc0xhbmRzY2FwZSgpIHtcbiAgICByZXR1cm4gd2luZG93LmlubmVyV2lkdGggPiB3aW5kb3cuaW5uZXJIZWlnaHQ7XG4gIH1cblxuICBnZXQgaXNTYWZhcmkoKTogYW55IHtcbiAgICBjb25zdCB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAodWEuaW5kZXhPZignc2FmYXJpJykgIT09IC0xKSB7XG4gICAgICByZXR1cm4gISh1YS5pbmRleE9mKCdjaHJvbWUnKSA+IC0xKTtcbiAgICB9XG4gIH1cblxuICBnZXQgY291bnRlcigpIHtcbiAgICBjb25zdCBjb3VudGVyID0gdGhpcy5zbGlkZUNvdW50ZXI7XG4gICAgcmV0dXJuIGNvdW50ZXIgKyAxICsgdGhpcy5jb3VudGVyU2VwYXJhdG9yICsgdGhpcy5jZWxsTGVuZ3RoO1xuICB9XG5cbiAgZ2V0IGNlbGxzRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignLmNhcm91c2VsLWNlbGxzJyk7XG4gIH1cblxuICBnZXQgaXNBcnJvd3MoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXJyb3dzICYmICF0aGlzLmZyZWVTY3JvbGw7XG4gIH1cblxuICBnZXQgaXNDb3VudGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9pc0NvdW50ZXIgJiYgdGhpcy5jZWxsTGVuZ3RoID4gMTtcbiAgfVxuXG4gIGdldCBhY3RpdmVEb3RJbmRleCgpIHtcbiAgICByZXR1cm4gdGhpcy5zbGlkZUNvdW50ZXIgJSB0aGlzLmNlbGxMZW5ndGg7XG4gIH1cblxuICBnZXQgY2VsbExpbWl0KCkge1xuICAgIGlmICh0aGlzLmNhcm91c2VsKSB7XG4gICAgICByZXR1cm4gdGhpcy5jYXJvdXNlbC5jZWxsTGltaXQ7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGNhcm91c2VsV2lkdGgoKSB7XG4gICAgcmV0dXJuIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoO1xuICB9XG5cbiAgQE91dHB1dCgpIGV2ZW50czogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBASW5wdXQoKSBpZCE6IG51bWJlcjtcblxuICBASW5wdXQoKSBoZWlnaHQgPSA0NTA7XG5cbiAgQElucHV0KCkgd2lkdGghOiBudW1iZXI7XG5cbiAgQElucHV0KCkgYXV0b3BsYXkgPSB0cnVlO1xuXG4gIEBJbnB1dCgpIGF1dG9wbGF5SW50ZXJ2YWwgPSA1MDAwO1xuXG4gIEBJbnB1dCgpIHBhdXNlT25Ib3ZlciA9IHRydWU7XG5cbiAgQElucHV0KCkgZG90cyA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGJvcmRlclJhZGl1cyE6IG51bWJlcjtcblxuICBASW5wdXQoKSBtYXJnaW4gPSAxMDtcblxuICBASW5wdXQoKSBvYmplY3RGaXQ6ICdjb250YWluJyB8ICdjb3ZlcicgfCAnbm9uZScgPSAnY292ZXInO1xuXG4gIEBJbnB1dCgpIG1pblN3aXBlRGlzdGFuY2UgPSAxMDtcblxuICBASW5wdXQoKSB0cmFuc2l0aW9uRHVyYXRpb24gPSAyMDA7XG5cbiAgQElucHV0KCkgdHJhbnNpdGlvblRpbWluZ0Z1bmN0aW9uOlxuICAgIHwgJ2Vhc2UnXG4gICAgfCAnZWFzZS1pbidcbiAgICB8ICdlYXNlLW91dCdcbiAgICB8ICdlYXNlLWluLW91dCdcbiAgICB8ICdsaW5lYXInID0gJ2Vhc2Utb3V0JztcblxuICBASW5wdXQoKSB2aWRlb1Byb3BlcnRpZXM6IGFueTtcblxuICBASW5wdXQoKSBjb3VudGVyU2VwYXJhdG9yID0gJyAvICc7XG5cbiAgQElucHV0KCkgb3ZlcmZsb3dDZWxsc0xpbWl0ID0gMztcblxuICBASW5wdXQoKSBsaXN0ZW5lcnM6ICdhdXRvJyB8ICdtb3VzZSBhbmQgdG91Y2gnID0gJ21vdXNlIGFuZCB0b3VjaCc7XG5cbiAgQElucHV0KCkgY2VsbHNUb1Nob3cgPSAxO1xuXG4gIEBJbnB1dCgpIGNlbGxzVG9TY3JvbGwgPSAxO1xuXG4gIEBJbnB1dCgpIGZyZWVTY3JvbGwgPSBmYWxzZTtcblxuICBASW5wdXQoKSBhcnJvd3MgPSB0cnVlO1xuXG4gIEBJbnB1dCgpIGFycm93c091dHNpZGUgPSBmYWxzZTtcblxuICBASW5wdXQoKSBhcnJvd3NUaGVtZTogJ2xpZ2h0JyB8ICdkYXJrJyA9ICdsaWdodCc7XG5cbiAgQElucHV0KCdjZWxsV2lkdGgnKSBzZXQgY2VsbFdpZHRoKHZhbHVlOiBudW1iZXIgfCAnMTAwJScpIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuX2NlbGxXaWR0aCA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIEBJbnB1dCgnY291bnRlcicpIHNldCBpc0NvdW50ZXIodmFsdWU6IGJvb2xlYW4pIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuX2lzQ291bnRlciA9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0QmluZGluZygnY2xhc3MuY2Fyb3VzZWwnKSBob3N0Q2xhc3NDYXJvdXNlbCA9IHRydWU7XG5cbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS5oZWlnaHQnKSBob3N0U3R5bGVIZWlnaHQhOiBzdHJpbmc7XG5cbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS53aWR0aCcpIGhvc3RTdHlsZVdpZHRoITogc3RyaW5nO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbJyRldmVudCddKVxuICBvbldpbmRvd1Jlc2l6ZShldmVudDogYW55KSB7XG4gICAgaWYgKHRoaXMudXRpbHMudmlzaWJsZVdpZHRoICE9PSB0aGlzLnNhdmVkQ2Fyb3VzZWxXaWR0aCkge1xuICAgICAgdGhpcy5yZXNpemUoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdtb3VzZWVudGVyJywgWyckZXZlbnQnXSlcbiAgb25Nb3VzZUVudGVyKCkge1xuICAgIGlmICh0aGlzLmF1dG9wbGF5ICYmIHRoaXMucGF1c2VPbkhvdmVyKSB7XG4gICAgICB0aGlzLmNhcm91c2VsUHJvcGVydGllcy5hdXRvcGxheUlzUG9zc2libGUgPSBmYWxzZTtcbiAgICAgIHRoaXMuY2Fyb3VzZWwuc3RvcEF1dG9wbGF5KCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScsIFsnJGV2ZW50J10pXG4gIG9uTW91c2VMZWF2ZSgpIHtcbiAgICBpZiAodGhpcy5hdXRvcGxheSAmJiB0aGlzLnBhdXNlT25Ib3Zlcikge1xuICAgICAgdGhpcy5jYXJvdXNlbFByb3BlcnRpZXMuYXV0b3BsYXlJc1Bvc3NpYmxlID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2Fyb3VzZWwuYXV0b3BsYXkoKTtcbiAgICB9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkcmFnc3RhcnQnLCBbJyRldmVudCddKVxuICBvbkRyYWdTdGFydCgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsIHByaXZhdGUgcmVmOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmlzTmdDb250ZW50ID0gdGhpcy5jZWxsc0VsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID4gMDtcblxuICAgIHRoaXMudG91Y2hlcyA9IG5ldyBUb3VjaGVzKHtcbiAgICAgIGVsZW1lbnQ6IHRoaXMuY2VsbHNFbGVtZW50LFxuICAgICAgbGlzdGVuZXJzOiB0aGlzLmxpc3RlbmVycyxcbiAgICAgIG1vdXNlTGlzdGVuZXJzOiB7XG4gICAgICAgIG1vdXNlZG93bjogJ2hhbmRsZU1vdXNlZG93bicsXG4gICAgICAgIG1vdXNldXA6ICdoYW5kbGVNb3VzZXVwJ1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy50b3VjaGVzLm9uKCd0b3VjaHN0YXJ0JywgdGhpcy5oYW5kbGVUb3VjaHN0YXJ0KTtcbiAgICB0aGlzLnRvdWNoZXMub24oJ2hvcml6b250YWwtc3dpcGUnLCB0aGlzLmhhbmRsZUhvcml6b250YWxTd2lwZSk7XG4gICAgdGhpcy50b3VjaGVzLm9uKCd0b3VjaGVuZCcsIHRoaXMuaGFuZGxlVG91Y2hlbmQpO1xuICAgIHRoaXMudG91Y2hlcy5vbignbW91c2Vkb3duJywgdGhpcy5oYW5kbGVUb3VjaHN0YXJ0KTtcbiAgICB0aGlzLnRvdWNoZXMub24oJ21vdXNldXAnLCB0aGlzLmhhbmRsZVRvdWNoZW5kKTtcbiAgICB0aGlzLnRvdWNoZXMub24oJ3RhcCcsIHRoaXMuaGFuZGxlVGFwKTtcblxuICAgIHRoaXMuc2V0RGltZW5zaW9ucygpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuaW5pdENhcm91c2VsKCk7XG4gICAgdGhpcy5jZWxsTGVuZ3RoID0gdGhpcy5nZXRDZWxsTGVuZ3RoKCk7XG4gICAgdGhpcy5kb3RzQXJyID0gQXJyYXkodGhpcy5jZWxsTGVuZ3RoKS5maWxsKDEpO1xuICAgIHRoaXMucmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICB0aGlzLmNhcm91c2VsLmxpbmVVcENlbGxzKCk7XG4gICAgdGhpcy5zYXZlZENhcm91c2VsV2lkdGggPSB0aGlzLmNhcm91c2VsV2lkdGg7XG5cbiAgICAvKiBTdGFydCBkZXRlY3RpbmcgY2hhbmdlcyBpbiB0aGUgRE9NIHRyZWUgKi9cbiAgICB0aGlzLmRldGVjdERvbUNoYW5nZXMoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICAgICAgY29uc3QgaXNGaXJzdENoYW5nZSA9IE9iamVjdC52YWx1ZXMoY2hhbmdlcykuc29tZShjaGFuZ2UgPT4gY2hhbmdlLmlzRmlyc3RDaGFuZ2UoKSk7XG4gICAgaWYgKCFpc0ZpcnN0Q2hhbmdlICYmIChjaGFuZ2VzLndpZHRoIHx8IGNoYW5nZXMuaGVpZ2h0KSkge1xuICAgICAgdGhpcy5zZXREaW1lbnNpb25zKCk7XG4gICAgICB0aGlzLmluaXRDYXJvdXNlbCgpO1xuICAgICAgdGhpcy5jYXJvdXNlbC5saW5lVXBDZWxscygpO1xuICAgICAgdGhpcy5yZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMudG91Y2hlcy5kZXN0cm95KCk7XG4gICAgLy8gdGhpcy5jYXJvdXNlbC5kZXN0cm95KCk7XG4gIH1cblxuICBpbml0Q2Fyb3VzZWwoKSB7XG4gICAgdGhpcy5jYXJvdXNlbFByb3BlcnRpZXMgPSB7XG4gICAgICBpZDogdGhpcy5pZCxcbiAgICAgIGNlbGxzRWxlbWVudDpcbiAgICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignLmNhcm91c2VsLWNlbGxzJyksXG4gICAgICBob3N0RWxlbWVudDogdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICBjZWxsV2lkdGg6IHRoaXMuZ2V0Q2VsbFdpZHRoKCksXG4gICAgICBhdXRvcGxheUludGVydmFsOiB0aGlzLmF1dG9wbGF5SW50ZXJ2YWwsXG4gICAgICBhdXRvcGxheUlzUG9zc2libGU6IHRydWUsXG4gICAgICBvdmVyZmxvd0NlbGxzTGltaXQ6IHRoaXMub3ZlcmZsb3dDZWxsc0xpbWl0LFxuICAgICAgdmlzaWJsZVdpZHRoOiB0aGlzLndpZHRoLFxuICAgICAgbWFyZ2luOiB0aGlzLm1hcmdpbixcbiAgICAgIG1pblN3aXBlRGlzdGFuY2U6IHRoaXMubWluU3dpcGVEaXN0YW5jZSxcbiAgICAgIHRyYW5zaXRpb25EdXJhdGlvbjogdGhpcy50cmFuc2l0aW9uRHVyYXRpb24sXG4gICAgICB0cmFuc2l0aW9uVGltaW5nRnVuY3Rpb246IHRoaXMudHJhbnNpdGlvblRpbWluZ0Z1bmN0aW9uLFxuICAgICAgdmlkZW9Qcm9wZXJ0aWVzOiB0aGlzLnZpZGVvUHJvcGVydGllcyxcbiAgICAgIGV2ZW50SGFuZGxlcjogdGhpcy5ldmVudHMsXG4gICAgICBmcmVlU2Nyb2xsOiB0aGlzLmZyZWVTY3JvbGxcbiAgICB9O1xuXG4gICAgdGhpcy51dGlscyA9IG5ldyBVdGlscyh0aGlzLmNhcm91c2VsUHJvcGVydGllcyk7XG4gICAgdGhpcy5jZWxscyA9IG5ldyBDZWxscyh0aGlzLmNhcm91c2VsUHJvcGVydGllcywgdGhpcy51dGlscyk7XG4gICAgdGhpcy5jb250YWluZXIgPSBuZXcgQ29udGFpbmVyKFxuICAgICAgdGhpcy5jYXJvdXNlbFByb3BlcnRpZXMsXG4gICAgICB0aGlzLnV0aWxzLFxuICAgICAgdGhpcy5jZWxsc1xuICAgICk7XG4gICAgdGhpcy5zbGlkZSA9IG5ldyBTbGlkZShcbiAgICAgIHRoaXMuY2Fyb3VzZWxQcm9wZXJ0aWVzLFxuICAgICAgdGhpcy51dGlscyxcbiAgICAgIHRoaXMuY2VsbHMsXG4gICAgICB0aGlzLmNvbnRhaW5lclxuICAgICk7XG5cbiAgICBpZiAodGhpcy5hdXRvcGxheSAmJiB0aGlzLmNhcm91c2VsKSB7XG4gICAgICB0aGlzLmNhcm91c2VsLnN0b3BBdXRvcGxheSgpO1xuICAgIH1cbiAgICB0aGlzLmNhcm91c2VsID0gbmV3IENhcm91c2VsKFxuICAgICAgdGhpcy5jYXJvdXNlbFByb3BlcnRpZXMsXG4gICAgICB0aGlzLnV0aWxzLFxuICAgICAgdGhpcy5jZWxscyxcbiAgICAgIHRoaXMuY29udGFpbmVyLFxuICAgICAgdGhpcy5zbGlkZVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5hdXRvcGxheSkge1xuICAgICAgdGhpcy5jYXJvdXNlbC5hdXRvcGxheSgpO1xuICAgIH1cbiAgfVxuXG4gIHJlc2l6ZSgpIHtcbiAgICB0aGlzLmxhbmRzY2FwZU1vZGUgPSB0aGlzLmlzTGFuZHNjYXBlO1xuICAgIHRoaXMuc2F2ZWRDYXJvdXNlbFdpZHRoID0gdGhpcy5jYXJvdXNlbFdpZHRoO1xuXG4gICAgdGhpcy5jYXJvdXNlbFByb3BlcnRpZXMuY2VsbFdpZHRoID0gdGhpcy5nZXRDZWxsV2lkdGgoKTtcbiAgICB0aGlzLmNlbGxzLnVwZGF0ZVByb3BlcnRpZXModGhpcy5jYXJvdXNlbFByb3BlcnRpZXMpO1xuICAgIHRoaXMuY2Fyb3VzZWwudXBkYXRlUHJvcGVydGllcyh0aGlzLmNhcm91c2VsUHJvcGVydGllcyk7XG4gICAgdGhpcy5jb250YWluZXIudXBkYXRlUHJvcGVydGllcyh0aGlzLmNhcm91c2VsUHJvcGVydGllcyk7XG4gICAgdGhpcy5zbGlkZS51cGRhdGVQcm9wZXJ0aWVzKHRoaXMuY2Fyb3VzZWxQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLnV0aWxzLnVwZGF0ZVByb3BlcnRpZXModGhpcy5jYXJvdXNlbFByb3BlcnRpZXMpO1xuICAgIHRoaXMuY2Fyb3VzZWwubGluZVVwQ2VsbHMoKTtcbiAgICB0aGlzLnNsaWRlLnNlbGVjdCgwKTtcbiAgICB0aGlzLnJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBkZXRlY3REb21DaGFuZ2VzKCkge1xuICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9ucykgPT4ge1xuICAgICAgdGhpcy5vbkRvbUNoYW5nZXMoKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGF0dHJpYnV0ZXM6IHRydWUsXG4gICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICBjaGFyYWN0ZXJEYXRhOiB0cnVlXG4gICAgfTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKHRoaXMuY2VsbHNFbGVtZW50LCBjb25maWcpO1xuICB9XG5cbiAgb25Eb21DaGFuZ2VzKCkge1xuICAgIHRoaXMuY2VsbExlbmd0aCA9IHRoaXMuZ2V0Q2VsbExlbmd0aCgpO1xuICAgIHRoaXMuY2Fyb3VzZWwubGluZVVwQ2VsbHMoKTtcbiAgICB0aGlzLnJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBzZXREaW1lbnNpb25zKCkge1xuICAgIHRoaXMuaG9zdFN0eWxlSGVpZ2h0ID0gYCR7dGhpcy5oZWlnaHR9cHhgO1xuICAgIHRoaXMuaG9zdFN0eWxlV2lkdGggPSBgJHt0aGlzLndpZHRofXB4YDtcbiAgfVxuXG4gIGhhbmRsZVRvdWNoc3RhcnQgPSAoZXZlbnQ6IGFueSkgPT4ge1xuICAgIHRoaXMudG91Y2hlcy5hZGRFdmVudExpc3RlbmVycygnbW91c2Vtb3ZlJywgJ2hhbmRsZU1vdXNlbW92ZScpO1xuICAgIHRoaXMuY2Fyb3VzZWwuaGFuZGxlVG91Y2hzdGFydChldmVudCk7XG4gICAgdGhpcy5pc01vdmluZyA9IHRydWU7XG4gIH07XG5cbiAgaGFuZGxlSG9yaXpvbnRhbFN3aXBlID0gKGV2ZW50OiBhbnkpID0+IHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMuY2Fyb3VzZWwuaGFuZGxlSG9yaXpvbnRhbFN3aXBlKGV2ZW50KTtcbiAgfTtcblxuICBoYW5kbGVUb3VjaGVuZCA9IChldmVudDogYW55KSA9PiB7XG4gICAgY29uc3QgeyB0b3VjaGVzIH0gPSBldmVudDtcbiAgICB0aGlzLmNhcm91c2VsLmhhbmRsZVRvdWNoZW5kKGV2ZW50KTtcbiAgICB0aGlzLnRvdWNoZXMucmVtb3ZlRXZlbnRMaXN0ZW5lcnMoJ21vdXNlbW92ZScsICdoYW5kbGVNb3VzZW1vdmUnKTtcbiAgICB0aGlzLmlzTW92aW5nID0gZmFsc2U7XG4gIH07XG5cbiAgaGFuZGxlVGFwID0gKGV2ZW50OiBhbnkpID0+IHtcbiAgICBjb25zdCBvdXRib3VuZEV2ZW50OiBhbnkgPSB7XG4gICAgICBuYW1lOiAnY2xpY2snXG4gICAgfTtcbiAgICBjb25zdCBub2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuY2VsbHNFbGVtZW50LmNoaWxkcmVuKTtcbiAgICBjb25zdCBjZWxsRWxlbWVudCA9IGV2ZW50LnNyY0VsZW1lbnQuY2xvc2VzdCgnLmNhcm91c2VsLWNlbGwnKTtcbiAgICBjb25zdCBpID0gbm9kZXMuaW5kZXhPZihjZWxsRWxlbWVudCk7XG4gICAgY29uc3QgY2VsbEluZGV4ID0gbm9kZXMuaW5kZXhPZihjZWxsRWxlbWVudCk7XG5cbiAgICBvdXRib3VuZEV2ZW50LmNlbGxJbmRleCA9IGNlbGxJbmRleDtcbiAgfTtcblxuICBoYW5kbGVUcmFuc2l0aW9uZW5kQ2VsbENvbnRhaW5lcihldmVudDogYW55KSB7XG4gICAgaWYgKGV2ZW50LnRhcmdldC5jbGFzc05hbWUgPT09ICdjYXJvdXNlbC1jZWxscycpIHtcbiAgICAgIHRoaXMuY2Fyb3VzZWwuaGFuZGxlVHJhbnNpdGlvbmVuZCgpO1xuICAgIH1cbiAgfVxuXG4gIGdldENlbGxXaWR0aCgpIHtcbiAgICBjb25zdCBlbGVtZW50V2lkdGggPSB0aGlzLmNhcm91c2VsV2lkdGg7XG5cbiAgICBpZiAodGhpcy5jZWxsc1RvU2hvdykge1xuICAgICAgY29uc3QgbWFyZ2luID0gdGhpcy5jZWxsc1RvU2hvdyA+IDEgPyB0aGlzLm1hcmdpbiA6IDA7XG4gICAgICBjb25zdCB0b3RhbE1hcmdpbiA9IG1hcmdpbiAqICh0aGlzLmNlbGxzVG9TaG93IC0gMSk7XG4gICAgICByZXR1cm4gKGVsZW1lbnRXaWR0aCAtIHRvdGFsTWFyZ2luKSAvIHRoaXMuY2VsbHNUb1Nob3c7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2NlbGxXaWR0aCA9PT0gJzEwMCUnKSB7XG4gICAgICByZXR1cm4gZWxlbWVudFdpZHRoO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY2VsbFdpZHRoO1xuICB9XG5cbiAgbmV4dCgpIHtcbiAgICB0aGlzLmNhcm91c2VsLm5leHQodGhpcy5jZWxsc1RvU2Nyb2xsKTtcbiAgICB0aGlzLmNhcm91c2VsLnN0b3BBdXRvcGxheSgpO1xuICB9XG5cbiAgcHJldigpIHtcbiAgICB0aGlzLmNhcm91c2VsLnByZXYodGhpcy5jZWxsc1RvU2Nyb2xsKTtcbiAgICB0aGlzLmNhcm91c2VsLnN0b3BBdXRvcGxheSgpO1xuICB9XG5cbiAgaXNOZXh0QXJyb3dEaXNhYmxlZCgpIHtcbiAgICBpZiAodGhpcy5jYXJvdXNlbCkge1xuICAgICAgcmV0dXJuIHRoaXMuY2Fyb3VzZWwuaXNOZXh0QXJyb3dEaXNhYmxlZCgpO1xuICAgIH1cbiAgfVxuXG4gIGlzUHJldkFycm93RGlzYWJsZWQoKSB7XG4gICAgaWYgKHRoaXMuY2Fyb3VzZWwpIHtcbiAgICAgIHJldHVybiB0aGlzLmNhcm91c2VsLmlzUHJldkFycm93RGlzYWJsZWQoKTtcbiAgICB9XG4gIH1cblxuICBnZXRDZWxsTGVuZ3RoKCkge1xuICAgIHJldHVybiB0aGlzLmNlbGxzRWxlbWVudC5jaGlsZHJlbi5sZW5ndGg7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjYXJvdXNlbC1jb3VudGVyXCIgKm5nSWY9XCJpc0NvdW50ZXJcIj57e2NvdW50ZXJ9fTwvZGl2PlxyXG5cclxuPGRpdiBjbGFzcz1cImNhcm91c2VsLWNvbnRhaW5lclwiIFtjbGFzcy5jYXJvdXNlbC1tb3ZpbmddPVwiaXNNb3ZpbmdcIj5cclxuXHQ8ZGl2IGNsYXNzPVwiY2Fyb3VzZWwtY2VsbHNcIiAjY2VsbHMgKHRyYW5zaXRpb25lbmQpPVwiaGFuZGxlVHJhbnNpdGlvbmVuZENlbGxDb250YWluZXIoJGV2ZW50KVwiPlxyXG5cdFx0PG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG5cdDwvZGl2PlxyXG5cclxuXHQ8ZGl2IGNsYXNzPVwiY2Fyb3VzZWwtZG90c1wiICpuZ0lmPVwiZG90c1wiPlxyXG5cdFx0PGRpdiBjbGFzcz1cImNhcm91c2VsLWRvdFwiIFtjbGFzcy5jYXJvdXNlbC1kb3QtYWN0aXZlXT1cImkgPT09IGFjdGl2ZURvdEluZGV4XCIgKm5nRm9yPVwibGV0IGRvdCBvZiBkb3RzQXJyOyBpbmRleCBhcyBpXCI+PC9kaXY+XHJcblx0PC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuPGRpdiBjbGFzcz1cImNhcm91c2VsLWFycm93c1wiXHJcblx0W2NsYXNzLmNhcm91c2VsLWFycm93cy1vdXRzaWRlXT1cImFycm93c091dHNpZGVcIlxyXG5cdFtjbGFzcy5jYXJvdXNlbC1kYXJrLWFycm93c109XCJhcnJvd3NUaGVtZSA9PT0gJ2RhcmsnXCJcclxuXHQqbmdJZj1cImlzQXJyb3dzXCI+XHJcblxyXG5cdDxkaXYgY2xhc3M9XCJjYXJvdXNlbC1hcnJvdyBjYXJvdXNlbC1hcnJvdy1wcmV2XCIgW2NsYXNzLmNhcm91c2VsLWFycm93LWRpc2FibGVkXT1cImlzUHJldkFycm93RGlzYWJsZWQoKVwiIChjbGljayk9XCJwcmV2KClcIj48L2Rpdj5ccl