UNPKG

@ng-bootstrap/ng-bootstrap

Version:
356 lines 54.1 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, Directive, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, TemplateRef, ViewEncapsulation } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; import { NgbCarouselConfig } from './carousel-config'; import { BehaviorSubject, combineLatest, NEVER, Subject, timer, zip } from 'rxjs'; import { distinctUntilChanged, map, startWith, switchMap, take, takeUntil } from 'rxjs/operators'; import { ngbCompleteTransition, ngbRunTransition } from '../util/transition/ngbTransition'; import { ngbCarouselTransitionIn, ngbCarouselTransitionOut, NgbSlideEventDirection } from './carousel-transition'; let nextId = 0; /** * A directive that wraps the individual carousel slide. */ export class NgbSlide { constructor(tplRef) { this.tplRef = tplRef; /** * Slide id that must be unique for the entire document. * * If not provided, will be generated in the `ngb-slide-xx` format. */ this.id = `ngb-slide-${nextId++}`; /** * An event emitted when the slide transition is finished * * @since 8.0.0 */ this.slid = new EventEmitter(); } } NgbSlide.decorators = [ { type: Directive, args: [{ selector: 'ng-template[ngbSlide]' },] } ]; NgbSlide.ctorParameters = () => [ { type: TemplateRef } ]; NgbSlide.propDecorators = { id: [{ type: Input }], slid: [{ type: Output }] }; /** * Carousel is a component to easily create and control slideshows. * * Allows to set intervals, change the way user interacts with the slides and provides a programmatic API. */ export class NgbCarousel { constructor(config, _platformId, _ngZone, _cd, _container) { this._platformId = _platformId; this._ngZone = _ngZone; this._cd = _cd; this._container = _container; this.NgbSlideEventSource = NgbSlideEventSource; this._destroy$ = new Subject(); this._interval$ = new BehaviorSubject(0); this._mouseHover$ = new BehaviorSubject(false); this._focused$ = new BehaviorSubject(false); this._pauseOnHover$ = new BehaviorSubject(false); this._pauseOnFocus$ = new BehaviorSubject(false); this._pause$ = new BehaviorSubject(false); this._wrap$ = new BehaviorSubject(false); /** * An event emitted just before the slide transition starts. * * See [`NgbSlideEvent`](#/components/carousel/api#NgbSlideEvent) for payload details. */ this.slide = new EventEmitter(); /** * An event emitted right after the slide transition is completed. * * See [`NgbSlideEvent`](#/components/carousel/api#NgbSlideEvent) for payload details. * * @since 8.0.0 */ this.slid = new EventEmitter(); /* * Keep the ids of the panels currently transitionning * in order to allow only the transition revertion */ this._transitionIds = null; this.animation = config.animation; this.interval = config.interval; this.wrap = config.wrap; this.keyboard = config.keyboard; this.pauseOnHover = config.pauseOnHover; this.pauseOnFocus = config.pauseOnFocus; this.showNavigationArrows = config.showNavigationArrows; this.showNavigationIndicators = config.showNavigationIndicators; } /** * Time in milliseconds before the next slide is shown. */ set interval(value) { this._interval$.next(value); } get interval() { return this._interval$.value; } /** * If `true`, will 'wrap' the carousel by switching from the last slide back to the first. */ set wrap(value) { this._wrap$.next(value); } get wrap() { return this._wrap$.value; } /** * If `true`, will pause slide switching when mouse cursor hovers the slide. * * @since 2.2.0 */ set pauseOnHover(value) { this._pauseOnHover$.next(value); } get pauseOnHover() { return this._pauseOnHover$.value; } /** * If `true`, will pause slide switching when the focus is inside the carousel. */ set pauseOnFocus(value) { this._pauseOnFocus$.next(value); } get pauseOnFocus() { return this._pauseOnFocus$.value; } set mouseHover(value) { this._mouseHover$.next(value); } get mouseHover() { return this._mouseHover$.value; } set focused(value) { this._focused$.next(value); } get focused() { return this._focused$.value; } arrowLeft() { this.focus(); this.prev(NgbSlideEventSource.ARROW_LEFT); } arrowRight() { this.focus(); this.next(NgbSlideEventSource.ARROW_RIGHT); } ngAfterContentInit() { // setInterval() doesn't play well with SSR and protractor, // so we should run it in the browser and outside Angular if (isPlatformBrowser(this._platformId)) { this._ngZone.runOutsideAngular(() => { const hasNextSlide$ = combineLatest([ this.slide.pipe(map(slideEvent => slideEvent.current), startWith(this.activeId)), this._wrap$, this.slides.changes.pipe(startWith(null)) ]) .pipe(map(([currentSlideId, wrap]) => { const slideArr = this.slides.toArray(); const currentSlideIdx = this._getSlideIdxById(currentSlideId); return wrap ? slideArr.length > 1 : currentSlideIdx < slideArr.length - 1; }), distinctUntilChanged()); combineLatest([ this._pause$, this._pauseOnHover$, this._mouseHover$, this._pauseOnFocus$, this._focused$, this._interval$, hasNextSlide$ ]) .pipe(map(([pause, pauseOnHover, mouseHover, pauseOnFocus, focused, interval, hasNextSlide]) => ((pause || (pauseOnHover && mouseHover) || (pauseOnFocus && focused) || !hasNextSlide) ? 0 : interval)), distinctUntilChanged(), switchMap(interval => interval > 0 ? timer(interval, interval) : NEVER), takeUntil(this._destroy$)) .subscribe(() => this._ngZone.run(() => this.next(NgbSlideEventSource.TIMER))); }); } this.slides.changes.pipe(takeUntil(this._destroy$)).subscribe(() => { var _a; (_a = this._transitionIds) === null || _a === void 0 ? void 0 : _a.forEach(id => ngbCompleteTransition(this._getSlideElement(id))); this._transitionIds = null; this._cd.markForCheck(); // The following code need to be done asynchronously, after the dom becomes stable, // otherwise all changes will be undone. this._ngZone.onStable.pipe(take(1)).subscribe(() => { for (const { id } of this.slides) { const element = this._getSlideElement(id); if (id === this.activeId) { element.classList.add('active'); } else { element.classList.remove('active'); } } }); }); } ngAfterContentChecked() { let activeSlide = this._getSlideById(this.activeId); this.activeId = activeSlide ? activeSlide.id : (this.slides.length ? this.slides.first.id : ''); } ngAfterViewInit() { // Initialize the 'active' class (not managed by the template) if (this.activeId) { const element = this._getSlideElement(this.activeId); if (element) { element.classList.add('active'); } } } ngOnDestroy() { this._destroy$.next(); } /** * Navigates to a slide with the specified identifier. */ select(slideId, source) { this._cycleToSelected(slideId, this._getSlideEventDirection(this.activeId, slideId), source); } /** * Navigates to the previous slide. */ prev(source) { this._cycleToSelected(this._getPrevSlide(this.activeId), NgbSlideEventDirection.RIGHT, source); } /** * Navigates to the next slide. */ next(source) { this._cycleToSelected(this._getNextSlide(this.activeId), NgbSlideEventDirection.LEFT, source); } /** * Pauses cycling through the slides. */ pause() { this._pause$.next(true); } /** * Restarts cycling through the slides from left to right. */ cycle() { this._pause$.next(false); } /** * Set the focus on the carousel. */ focus() { this._container.nativeElement.focus(); } _cycleToSelected(slideIdx, direction, source) { const transitionIds = this._transitionIds; if (transitionIds && (transitionIds[0] !== slideIdx || transitionIds[1] !== this.activeId)) { // Revert prevented return; } let selectedSlide = this._getSlideById(slideIdx); if (selectedSlide && selectedSlide.id !== this.activeId) { this._transitionIds = [this.activeId, slideIdx]; this.slide.emit({ prev: this.activeId, current: selectedSlide.id, direction: direction, paused: this._pause$.value, source }); const options = { animation: this.animation, runningTransition: 'stop', context: { direction }, }; const transitions = []; const activeSlide = this._getSlideById(this.activeId); if (activeSlide) { const activeSlideTransition = ngbRunTransition(this._ngZone, this._getSlideElement(activeSlide.id), ngbCarouselTransitionOut, options); activeSlideTransition.subscribe(() => { activeSlide.slid.emit({ isShown: false, direction, source }); }); transitions.push(activeSlideTransition); } const previousId = this.activeId; this.activeId = selectedSlide.id; const nextSlide = this._getSlideById(this.activeId); const transition = ngbRunTransition(this._ngZone, this._getSlideElement(selectedSlide.id), ngbCarouselTransitionIn, options); transition.subscribe(() => { nextSlide === null || nextSlide === void 0 ? void 0 : nextSlide.slid.emit({ isShown: true, direction, source }); }); transitions.push(transition); zip(...transitions).pipe(take(1)).subscribe(() => { this._transitionIds = null; this.slid.emit({ prev: previousId, current: selectedSlide.id, direction: direction, paused: this._pause$.value, source }); }); } // we get here after the interval fires or any external API call like next(), prev() or select() this._cd.markForCheck(); } _getSlideEventDirection(currentActiveSlideId, nextActiveSlideId) { const currentActiveSlideIdx = this._getSlideIdxById(currentActiveSlideId); const nextActiveSlideIdx = this._getSlideIdxById(nextActiveSlideId); return currentActiveSlideIdx > nextActiveSlideIdx ? NgbSlideEventDirection.RIGHT : NgbSlideEventDirection.LEFT; } _getSlideById(slideId) { return this.slides.find(slide => slide.id === slideId) || null; } _getSlideIdxById(slideId) { const slide = this._getSlideById(slideId); return slide != null ? this.slides.toArray().indexOf(slide) : -1; } _getNextSlide(currentSlideId) { const slideArr = this.slides.toArray(); const currentSlideIdx = this._getSlideIdxById(currentSlideId); const isLastSlide = currentSlideIdx === slideArr.length - 1; return isLastSlide ? (this.wrap ? slideArr[0].id : slideArr[slideArr.length - 1].id) : slideArr[currentSlideIdx + 1].id; } _getPrevSlide(currentSlideId) { const slideArr = this.slides.toArray(); const currentSlideIdx = this._getSlideIdxById(currentSlideId); const isFirstSlide = currentSlideIdx === 0; return isFirstSlide ? (this.wrap ? slideArr[slideArr.length - 1].id : slideArr[0].id) : slideArr[currentSlideIdx - 1].id; } _getSlideElement(slideId) { return this._container.nativeElement.querySelector(`#slide-${slideId}`); } } NgbCarousel.decorators = [ { type: Component, args: [{ selector: 'ngb-carousel', exportAs: 'ngbCarousel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { 'class': 'carousel slide', '[style.display]': '"block"', 'tabIndex': '0', '(keydown.arrowLeft)': 'keyboard && arrowLeft()', '(keydown.arrowRight)': 'keyboard && arrowRight()', '(mouseenter)': 'mouseHover = true', '(mouseleave)': 'mouseHover = false', '(focusin)': 'focused = true', '(focusout)': 'focused = false', '[attr.aria-activedescendant]': `'slide-' + activeId` }, template: ` <ol class="carousel-indicators" [class.sr-only]="!showNavigationIndicators" role="tablist"> <li *ngFor="let slide of slides" [class.active]="slide.id === activeId" role="tab" [attr.aria-labelledby]="'slide-' + slide.id" [attr.aria-controls]="'slide-' + slide.id" [attr.aria-selected]="slide.id === activeId" (click)="focus();select(slide.id, NgbSlideEventSource.INDICATOR);"></li> </ol> <div class="carousel-inner"> <div *ngFor="let slide of slides; index as i; count as c" class="carousel-item" [id]="'slide-' + slide.id" role="tabpanel"> <span class="sr-only" i18n="Currently selected slide number read by screen reader@@ngb.carousel.slide-number"> Slide {{i + 1}} of {{c}} </span> <ng-template [ngTemplateOutlet]="slide.tplRef"></ng-template> </div> </div> <a class="carousel-control-prev" role="button" (click)="arrowLeft()" *ngIf="showNavigationArrows"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="sr-only" i18n="@@ngb.carousel.previous">Previous</span> </a> <a class="carousel-control-next" role="button" (click)="arrowRight()" *ngIf="showNavigationArrows"> <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="sr-only" i18n="@@ngb.carousel.next">Next</span> </a> ` },] } ]; NgbCarousel.ctorParameters = () => [ { type: NgbCarouselConfig }, { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }, { type: NgZone }, { type: ChangeDetectorRef }, { type: ElementRef } ]; NgbCarousel.propDecorators = { slides: [{ type: ContentChildren, args: [NgbSlide,] }], animation: [{ type: Input }], activeId: [{ type: Input }], interval: [{ type: Input }], wrap: [{ type: Input }], keyboard: [{ type: Input }], pauseOnHover: [{ type: Input }], pauseOnFocus: [{ type: Input }], showNavigationArrows: [{ type: Input }], showNavigationIndicators: [{ type: Input }], slide: [{ type: Output }], slid: [{ type: Output }] }; export var NgbSlideEventSource; (function (NgbSlideEventSource) { NgbSlideEventSource["TIMER"] = "timer"; NgbSlideEventSource["ARROW_LEFT"] = "arrowLeft"; NgbSlideEventSource["ARROW_RIGHT"] = "arrowRight"; NgbSlideEventSource["INDICATOR"] = "indicator"; })(NgbSlideEventSource || (NgbSlideEventSource = {})); export const NGB_CAROUSEL_DIRECTIVES = [NgbCarousel, NgbSlide]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuanMiLCJzb3VyY2VSb290IjoiLi4vLi4vLi4vc3JjLyIsInNvdXJjZXMiOlsiY2Fyb3VzZWwvY2Fyb3VzZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULGVBQWUsRUFDZixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sRUFFTixNQUFNLEVBQ04sV0FBVyxFQUVYLFdBQVcsRUFDWCxpQkFBaUIsRUFFbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFbEQsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFFcEQsT0FBTyxFQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFjLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzVGLE9BQU8sRUFBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEcsT0FBTyxFQUFDLHFCQUFxQixFQUFFLGdCQUFnQixFQUF1QixNQUFNLGtDQUFrQyxDQUFDO0FBQy9HLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsd0JBQXdCLEVBQ3hCLHNCQUFzQixFQUV2QixNQUFNLHVCQUF1QixDQUFDO0FBRS9CLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztBQUVmOztHQUVHO0FBRUgsTUFBTSxPQUFPLFFBQVE7SUFlbkIsWUFBbUIsTUFBd0I7UUFBeEIsV0FBTSxHQUFOLE1BQU0sQ0FBa0I7UUFkM0M7Ozs7V0FJRztRQUNNLE9BQUUsR0FBRyxhQUFhLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFFdEM7Ozs7V0FJRztRQUNPLFNBQUksR0FBRyxJQUFJ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LGlCQUFpQjtvQkFDL0IsOEJBQThCLEVBQUUscUJBQXFCO2lCQUN0RDtnQkFDRCxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJUO2FBQ0Y7OztZQWxGTyxpQkFBaUI7NENBNE1TLE1BQU0sU0FBQyxXQUFXO1lBdk5sRCxNQUFNO1lBUk4saUJBQWlCO1lBSWpCLFVBQVU7OztxQkFvR1QsZUFBZSxTQUFDLFFBQVE7d0JBa0J4QixLQUFLO3VCQU9MLEtBQUs7dUJBS0wsS0FBSzttQkFVTCxLQUFLO3VCQVVMLEtBQUs7MkJBT0wsS0FBSzsyQkFVTCxLQUFLO21DQVlMLEtBQUs7dUNBT0wsS0FBSztvQkFPTCxNQUFNO21CQVNOLE1BQU07O0FBeVNULE1BQU0sQ0FBTixJQUFZLG1CQUtYO0FBTEQsV0FBWSxtQkFBbUI7SUFDN0Isc0NBQWUsQ0FBQTtJQUNmLCtDQUF3QixDQUFBO0lBQ3hCLGlEQUEwQixDQUFBO0lBQzFCLDhDQUF1QixDQUFBO0FBQ3pCLENBQUMsRUFMVyxtQkFBbUIsS0FBbkIsbUJBQW1CLFFBSzlCO0FBRUQsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlckNvbnRlbnRDaGVja2VkLFxuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkcmVuLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgUExBVEZPUk1fSUQsXG4gIFF1ZXJ5TGlzdCxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxuICBBZnRlclZpZXdJbml0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtpc1BsYXRmb3JtQnJvd3Nlcn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0IHtOZ2JDYXJvdXNlbENvbmZpZ30gZnJvbSAnLi9jYXJvdXNlbC1jb25maWcnO1xuXG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgTkVWRVIsIE9ic2VydmFibGUsIFN1YmplY3QsIHRpbWVyLCB6aXB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtkaXN0aW5jdFVudGlsQ2hhbmdlZCwgbWFwLCBzdGFydFdpdGgsIHN3aXRjaE1hcCwgdGFrZSwgdGFrZVVudGlsfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge25nYkNvbXBsZXRlVHJhbnNpdGlvbiwgbmdiUnVuVHJhbnNpdGlvbiwgTmdiVHJhbnNpdGlvbk9wdGlvbnN9IGZyb20gJy4uL3V0aWwvdHJhbnNpdGlvbi9uZ2JUcmFuc2l0aW9uJztcbmltcG9ydCB7XG4gIG5nYkNhcm91c2VsVHJhbnNpdGlvbkluLFxuICBuZ2JDYXJvdXNlbFRyYW5zaXRpb25PdXQsXG4gIE5nYlNsaWRlRXZlbnREaXJlY3Rpb24sXG4gIE5nYkNhcm91c2VsQ3R4XG59IGZyb20gJy4vY2Fyb3VzZWwtdHJhbnNpdGlvbic7XG5cbmxldCBuZXh0SWQgPSAwO1xuXG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgd3JhcHMgdGhlIGluZGl2aWR1YWwgY2Fyb3VzZWwgc2xpZGUuXG4gKi9cbkBEaXJlY3RpdmUoe3NlbGVjdG9yOiAnbmctdGVtcGxhdGVbbmdiU2xpZGVdJ30pXG5leHBvcnQgY2xhc3MgTmdiU2xpZGUge1xuICAvKipcbiAgICogU2xpZGUgaWQgdGhhdCBtdXN0IGJlIHVuaXF1ZSBmb3IgdGhlIGVudGlyZSBkb2N1bWVudC5cbiAgICpcbiAgICogSWYgbm90IHByb3ZpZGVkLCB3aWxsIGJlIGdlbmVyYXRlZCBpbiB0aGUgYG5nYi1zbGlkZS14eGAgZm9ybWF0LlxuICAgKi9cbiAgQElucHV0KCkgaWQgPSBgbmdiLXNsaWRlLSR7bmV4dElkKyt9YDtcblxuICAvKipcbiAgICogQW4gZXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBzbGlkZSB0cmFuc2l0aW9uIGlzIGZpbmlzaGVkXG4gICAqXG4gICAqIEBzaW5jZSA4LjAuMFxuICAgKi9cbiAgQE91dHB1dCgpIHNsaWQgPSBuZXcgRXZlbnRFbWl0dGVyPE5nYlNpbmdsZVNsaWRlRXZlbnQ+KCk7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHRwbFJlZjogVGVtcGxhdGVSZWY8YW55Pikge31cbn1cblxuLyoqXG4gKiBDYXJvdXNlbCBpcyBhIGNvbXBvbmVudCB0byBlYXNpbHkgY3JlYXRlIGFuZCBjb250cm9sIHNsaWRlc2hvd3MuXG4gKlxuICogQWxsb3dzIHRvIHNldCBpbnRlcnZhbHMsIGNoYW5nZSB0aGUgd2F5IHVzZXIgaW50ZXJhY3RzIHdpdGggdGhlIHNsaWRlcyBhbmQgcHJvdmlkZXMgYSBwcm9ncmFtbWF0aWMgQVBJLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ2ItY2Fyb3VzZWwnLFxuICBleHBvcnRBczogJ25nYkNhcm91c2VsJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGhvc3Q6IHtcbiAgICAnY2xhc3MnOiAnY2Fyb3VzZWwgc2xpZGUnLFxuICAgICdbc3R5bGUuZGlzcGxheV0nOiAnXCJibG9ja1wiJyxcbiAgICAndGFiSW5kZXgnOiAnMCcsXG4gICAgJyhrZXlkb3duLmFycm93TGVmdCknOiAna2V5Ym9hcmQgJiYgYXJyb3dMZWZ0KCknLFxuICAgICcoa2V5ZG93bi5hcnJvd1JpZ2h0KSc6ICdrZXlib2FyZCAmJiBhcnJvd1JpZ2h0KCknLFxuICAgICcobW91c2VlbnRlciknOiAnbW91c2VIb3ZlciA9IHRydWUnLFxuICAgICcobW91c2VsZWF2ZSknOiAnbW91c2VIb3ZlciA9IGZhbHNlJyxcbiAgICAnKGZvY3VzaW4pJzogJ2ZvY3VzZWQgPSB0cnVlJyxcbiAgICAnKGZvY3Vzb3V0KSc6ICdmb2N1c2VkID0gZmFsc2UnLFxuICAgICdbYXR0ci5hcmlhLWFjdGl2ZWRlc2NlbmRhbnRdJzogYCdzbGlkZS0nICsgYWN0aXZlSWRgXG4gIH0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPG9sIGNsYXNzPVwiY2Fyb3VzZWwtaW5kaWNhdG9yc1wiIFtjbGFzcy5zci1vbmx5XT1cIiFzaG93TmF2aWdhdGlvbkluZGljYXRvcnNcIiByb2xlPVwidGFibGlzdFwiPlxuICAgICAgPGxpICpuZ0Zvcj1cImxldCBzbGlkZSBvZiBzbGlkZXNcIiBbY2xhc3MuYWN0aXZlXT1cInNsaWRlLmlkID09PSBhY3RpdmVJZFwiXG4gICAgICAgICAgcm9sZT1cInRhYlwiIFthdHRyLmFyaWEtbGFiZWxsZWRieV09XCInc2xpZGUtJyArIHNsaWRlLmlkXCIgW2F0dHIuYXJpYS1jb250cm9sc109XCInc2xpZGUtJyArIHNsaWRlLmlkXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cInNsaWRlLmlkID09PSBhY3RpdmVJZFwiXG4gICAgICAgICAgKGNsaWNrKT1cImZvY3VzKCk7c2VsZWN0KHNsaWRlLmlkLCBOZ2JTbGlkZUV2ZW50U291cmNlLklORElDQVRPUik7XCI+PC9saT5cbiAgICA8L29sPlxuICAgIDxkaXYgY2xhc3M9XCJjYXJvdXNlbC1pbm5lclwiPlxuICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgc2xpZGUgb2Ygc2xpZGVzOyBpbmRleCBhcyBpOyBjb3VudCBhcyBjXCIgY2xhc3M9XCJjYXJvdXNlbC1pdGVtXCIgW2lkXT1cIidzbGlkZS0nICsgc2xpZGUuaWRcIiByb2xlPVwidGFicGFuZWxcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJzci1vbmx5XCIgaTE4bj1cIkN1cnJlbnRseSBzZWxlY3RlZCBzbGlkZSBudW1iZXIgcmVhZCBieSBzY3JlZW4gcmVhZGVyQEBuZ2IuY2Fyb3VzZWwuc2xpZGUtbnVtYmVyXCI+XG4gICAgICAgICAgU2xpZGUge3tpICsgMX19IG9mIHt7Y319XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInNsaWRlLnRwbFJlZlwiPjwvbmctdGVtcGxhdGU+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8YSBjbGFzcz1cImNhcm91c2VsLWNvbnRyb2wtcHJldlwiIHJvbGU9XCJidXR0b25cIiAoY2xpY2spPVwiYXJyb3dMZWZ0KClcIiAqbmdJZj1cInNob3dOYXZpZ2F0aW9uQXJyb3dzXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cImNhcm91c2VsLWNvbnRyb2wtcHJldi1pY29uXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJzci1vbmx5XCIgaTE4bj1cIkBAbmdiLmNhcm91c2VsLnByZXZpb3VzXCI+UHJldmlvdXM8L3NwYW4+XG4gICAgPC9hPlxuICAgIDxhIGNsYXNzPVwiY2Fyb3VzZWwtY29udHJvbC1uZXh0XCIgcm9sZT1cImJ1dHRvblwiIChjbGljayk9XCJhcnJvd1JpZ2h0KClcIiAqbmdJZj1cInNob3dOYXZpZ2F0aW9uQXJyb3dzXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cImNhcm91c2VsLWNvbnRyb2wtbmV4dC1pY29uXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJzci1vbmx5XCIgaTE4bj1cIkBAbmdiLmNhcm91c2VsLm5leHRcIj5OZXh0PC9zcGFuPlxuICAgIDwvYT5cbiAgYFxufSlcbmV4cG9ydCBjbGFzcyBOZ2JDYXJvdXNlbCBpbXBsZW1lbnRzIEFmdGVyQ29udGVudENoZWNrZWQsXG4gICAgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgQENvbnRlbnRDaGlsZHJlbihOZ2JTbGlkZSkgc2xpZGVzOiBRdWVyeUxpc3Q8TmdiU2xpZGU+O1xuXG4gIHB1YmxpYyBOZ2JTbGlkZUV2ZW50U291cmNlID0gTmdiU2xpZGVFdmVudFNvdXJjZTtcblxuICBwcml2YXRlIF9kZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgX2ludGVydmFsJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoMCk7XG4gIHByaXZhdGUgX21vdXNlSG92ZXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdChmYWxzZSk7XG4gIHByaXZhdGUgX2ZvY3VzZWQkID0gbmV3IEJlaGF2aW9yU3ViamVjdChmYWxzZSk7XG4gIHByaXZhdGUgX3BhdXNlT25Ib3ZlciQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcbiAgcHJpdmF0ZSBfcGF1c2VPbkZvY3VzJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpO1xuICBwcml2YXRlIF9wYXVzZSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcbiAgcHJpdmF0ZSBfd3JhcCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcblxuICAvKipcbiAgICogQSBmbGFnIHRvIGVuYWJsZS9kaXNhYmxlIHRoZSBhbmltYXRpb25zLlxuICAgKlxuICAgKiBAc2luY2UgOC4wLjBcbiAgICovXG4gIEBJbnB1dCgpIGFuaW1hdGlvbjogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHNsaWRlIGlkIHRoYXQgc2hvdWxkIGJlIGRpc3BsYXllZCAqKmluaXRpYWxseSoqLlxuICAgKlxuICAgKiBGb3Igc3Vic2VxdWVudCBpbnRlcmFjdGlvbnMgdXNlIG1ldGhvZHMgYHNlbGVjdCgpYCwgYG5leHQoKWAsIGV0Yy4gYW5kIHRoZSBgKHNsaWRlKWAgb3V0cHV0LlxuICAgKi9cbiAgQElucHV0KCkgYWN0aXZlSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVGltZSBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHRoZSBuZXh0IHNsaWRlIGlzIHNob3duLlxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IGludGVydmFsKHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLl9pbnRlcnZhbCQubmV4dCh2YWx1ZSk7XG4gIH1cblxuICBnZXQgaW50ZXJ2YWwoKSB7IHJldHVybiB0aGlzLl9pbnRlcnZhbCQudmFsdWU7IH1cblxuICAvKipcbiAgICogSWYgYHRydWVgLCB3aWxsICd3cmFwJyB0aGUgY2Fyb3VzZWwgYnkgc3dpdGNoaW5nIGZyb20gdGhlIGxhc3Qgc2xpZGUgYmFjayB0byB0aGUgZmlyc3QuXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgd3JhcCh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuX3dyYXAkLm5leHQodmFsdWUpO1xuICB9XG5cbiAgZ2V0IHdyYXAoKSB7IHJldHVybiB0aGlzLl93cmFwJC52YWx1ZTsgfVxuXG4gIC8qKlxuICAgKiBJZiBgdHJ1ZWAsIGFsbG93cyB0byBpbnRlcmFjdCB3aXRoIGNhcm91c2VsIHVzaW5nIGtleWJvYXJkICdhcnJvdyBsZWZ0JyBhbmQgJ2Fycm93IHJpZ2h0Jy5cbiAgICovXG4gIEBJbnB1dCgpIGtleWJvYXJkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJZiBgdHJ1ZWAsIHdpbGwgcGF1c2Ugc2xpZGUgc3dpdGNoaW5nIHdoZW4gbW91c2UgY3Vyc29yIGhvdmVycyB0aGUgc2xpZGUuXG4gICAqXG4gICAqIEBzaW5jZSAyLjIuMFxuICAgKi9cbiAgQElucHV0KClcbiAgc2V0IHBhdXNlT25Ib3Zlcih2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuX3BhdXNlT25Ib3ZlciQubmV4dCh2YWx1ZSk7XG4gIH1cblxuICBnZXQgcGF1c2VPbkhvdmVyKCkgeyByZXR1cm4gdGhpcy5fcGF1c2VPbkhvdmVyJC52YWx1ZTsgfVxuXG4gIC8qKlxuICAgKiBJZiBgdHJ1ZWAsIHdpbGwgcGF1c2Ugc2xpZGUgc3dpdGNoaW5nIHdoZW4gdGhlIGZvY3VzIGlzIGluc2lkZSB0aGUgY2Fyb3VzZWwuXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgcGF1c2VPbkZvY3VzKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fcGF1c2VPbkZvY3VzJC5uZXh0KHZhbHVlKTtcbiAgfVxuXG4gIGdldCBwYXVzZU9uRm9jdXMoKSB7IHJldHVybiB0aGlzLl9wYXVzZU9uRm9jdXMkLnZhbHVlOyB9XG5cbiAgLyoqXG4gICAqIElmIGB0cnVlYCwgJ3ByZXZpb3VzJyBhbmQgJ25leHQnIG5hdmlnYXRpb24gYXJyb3dzIHdpbGwgYmUgdmlzaWJsZSBvbiB0aGUgc2xpZGUuXG4gICAqXG4gICAqIEBzaW5jZSAyLjIuMFxuICAgKi9cbiAgQElucHV0KCkgc2hvd05hdmlnYXRpb25BcnJvd3M6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIElmIGB0cnVlYCwgbmF2aWdhdGlvbiBpbmRpY2F0b3JzIGF0IHRoZSBib3R0b20gb2YgdGhlIHNsaWRlIHdpbGwgYmUgdmlzaWJsZS5cbiAgICpcbiAgICogQHNpbmNlIDIuMi4wXG4gICAqL1xuICBASW5wdXQoKSBzaG93TmF2aWdhdGlvbkluZGljYXRvcnM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEFuIGV2ZW50IGVtaXR0ZWQganVzdCBiZWZvcmUgdGhlIHNsaWRlIHRyYW5zaXRpb24gc3RhcnRzLlxuICAgKlxuICAgKiBTZWUgW2BOZ2JTbGlkZUV2ZW50YF0oIy9jb21wb25lbnRzL2Nhcm91c2VsL2FwaSNOZ2JTbGlkZUV2ZW50KSBmb3IgcGF5bG9hZCBkZXRhaWxzLlxuICAgKi9cbiAgQE91dHB1dCgpIHNsaWRlID0gbmV3IEV2ZW50RW1pdHRlcjxOZ2JTbGlkZUV2ZW50PigpO1xuXG4gIC8qKlxuICAgKiBBbiBldmVudCBlbWl0dGVkIHJpZ2h0IGFmdGVyIHRoZSBzbGlkZSB0cmFuc2l0aW9uIGlzIGNvbXBsZXRlZC5cbiAgICpcbiAgICogU2VlIFtgTmdiU2xpZGVFdmVudGBdKCMvY29tcG9uZW50cy9jYXJvdXNlbC9hcGkjTmdiU2xpZGVFdmVudCkgZm9yIHBheWxvYWQgZGV0YWlscy5cbiAgICpcbiAgICogQHNpbmNlIDguMC4wXG4gICAqL1xuICBAT3V0cHV0KCkgc2xpZCA9IG5ldyBFdmVudEVtaXR0ZXI8TmdiU2xpZGVFdmVudD4oKTtcblxuICAvKlxuICAgKiBLZWVwIHRoZSBpZHMgb2YgdGhlIHBhbmVscyBjdXJyZW50bHkgdHJhbnNpdGlvbm5pbmdcbiAgICogaW4gb3JkZXIgdG8gYWxsb3cgb25seSB0aGUgdHJhbnNpdGlvbiByZXZlcnRpb25cbiAgICovXG4gIHByaXZhdGUgX3RyYW5zaXRpb25JZHM6IFtzdHJpbmcsIHN0cmluZ10gfCBudWxsID0gbnVsbDtcblxuICBzZXQgbW91c2VIb3Zlcih2YWx1ZTogYm9vbGVhbikgeyB0aGlzLl9tb3VzZUhvdmVyJC5uZXh0KHZhbHVlKTsgfVxuXG4gIGdldCBtb3VzZUhvdmVyKCkgeyByZXR1cm4gdGhpcy5fbW91c2VIb3ZlciQudmFsdWU7IH1cblxuICBzZXQgZm9jdXNlZCh2YWx1ZTogYm9vbGVhbikgeyB0aGlzLl9mb2N1c2VkJC5uZXh0KHZhbHVlKTsgfVxuXG4gIGdldCBmb2N1c2VkKCkgeyByZXR1cm4gdGhpcy5fZm9jdXNlZCQudmFsdWU7IH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIGNvbmZpZzogTmdiQ2Fyb3VzZWxDb25maWcsIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgX3BsYXRmb3JtSWQsIHByaXZhdGUgX25nWm9uZTogTmdab25lLFxuICAgICAgcHJpdmF0ZSBfY2Q6IENoYW5nZURldGVjdG9yUmVmLCBwcml2YXRlIF9jb250YWluZXI6IEVsZW1lbnRSZWYpIHtcbiAgICB0aGlzLmFuaW1hdGlvbiA9IGNvbmZpZy5hbmltYXRpb247XG4gICAgdGhpcy5pbnRlcnZhbCA9IGNvbmZpZy5pbnRlcnZhbDtcbiAgICB0aGlzLndyYXAgPSBjb25maWcud3JhcDtcbiAgICB0aGlzLmtleWJvYXJkID0gY29uZmlnLmtleWJvYXJkO1xuICAgIHRoaXMucGF1c2VPbkhvdmVyID0gY29uZmlnLnBhdXNlT25Ib3ZlcjtcbiAgICB0aGlzLnBhdXNlT25Gb2N1cyA9IGNvbmZpZy5wYXVzZU9uRm9jdXM7XG4gICAgdGhpcy5zaG93TmF2aWdhdGlvbkFycm93cyA9IGNvbmZpZy5zaG93TmF2aWdhdGlvbkFycm93cztcbiAgICB0aGlzLnNob3dOYXZpZ2F0aW9uSW5kaWNhdG9ycyA9IGNvbmZpZy5zaG93TmF2aWdhdGlvbkluZGljYXRvcnM7XG4gIH1cblxuICBhcnJvd0xlZnQoKSB7XG4gICAgdGhpcy5mb2N1cygpO1xuICAgIHRoaXMucHJldihOZ2JTbGlkZUV2ZW50U291cmNlLkFSUk9XX0xFRlQpO1xuICB9XG5cbiAgYXJyb3dSaWdodCgpIHtcbiAgICB0aGlzLmZvY3VzKCk7XG4gICAgdGhpcy5uZXh0KE5nYlNsaWRlRXZlbnRTb3VyY2UuQVJST1dfUklHSFQpO1xuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgIC8vIHNldEludGVydmFsKCkgZG9lc24ndCBwbGF5IHdlbGwgd2l0aCBTU1IgYW5kIHByb3RyYWN0b3IsXG4gICAgLy8gc28gd2Ugc2hvdWxkIHJ1biBpdCBpbiB0aGUgYnJvd3NlciBhbmQgb3V0c2lkZSBBbmd1bGFyXG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMuX3BsYXRmb3JtSWQpKSB7XG4gICAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICBjb25zdCBoYXNOZXh0U2xpZGUkID0gY29tYmluZUxhdGVzdChbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2xpZGUucGlwZShtYXAoc2xpZGVFdmVudCA9PiBzbGlkZUV2ZW50LmN1cnJlbnQpLCBzdGFydFdpdGgodGhpcy5hY3RpdmVJZCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93cmFwJCwgdGhpcy5zbGlkZXMuY2hhbmdlcy5waXBlKHN0YXJ0V2l0aChudWxsKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgoW2N1cnJlbnRTbGlkZUlkLCB3cmFwXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNsaWRlQXJyID0gdGhpcy5zbGlkZXMudG9BcnJheSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTbGlkZUlkeCA9IHRoaXMuX2dldFNsaWRlSWR4QnlJZChjdXJyZW50U2xpZGVJZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdyYXAgPyBzbGlkZUFyci5sZW5ndGggPiAxIDogY3VycmVudFNsaWRlSWR4IDwgc2xpZGVBcnIubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpO1xuICAgICAgICBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgICB0aGlzLl9wYXVzZSQsIHRoaXMuX3BhdXNlT25Ib3ZlciQsIHRoaXMuX21vdXNlSG92ZXIkLCB0aGlzLl9wYXVzZU9uRm9jdXMkLCB0aGlzLl9mb2N1c2VkJCwgdGhpcy5faW50ZXJ2YWwkLFxuICAgICAgICAgIGhhc05leHRTbGlkZSRcbiAgICAgICAgXSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIG1hcCgoW3BhdXNlLCBwYXVzZU9uSG92ZXIsIG1vdXNlSG92ZXIsIHBhdXNlT25Gb2N1cywgZm9jdXNlZCwgaW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgICAgaGFzTmV4dFNsaWRlXTogW2Jvb2xlYW4sIGJvb2xlYW4sIGJvb2xlYW4sIGJvb2xlYW4sIGJvb2xlYW4sIG51bWJlciwgYm9vbGVhbl0pID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAoKHBhdXNlIHx8IChwYXVzZU9uSG92ZXIgJiYgbW91c2VIb3ZlcikgfHwgKHBhdXNlT25Gb2N1cyAmJiBmb2N1c2VkKSB8fCAhaGFzTmV4dFNsaWRlKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnZhbCkpLFxuXG4gICAgICAgICAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSwgc3dpdGNoTWFwKGludGVydmFsID0+IGludGVydmFsID4gMCA/IHRpbWVyKGludGVydmFsLCBpbnRlcnZhbCkgOiBORVZFUiksXG4gICAgICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fbmdab25lLnJ1bigoKSA9PiB0aGlzLm5leHQoTmdiU2xpZGVFdmVudFNvdXJjZS5USU1FUikpKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuc2xpZGVzLmNoYW5nZXMucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5fdHJhbnNpdGlvbklkcyA/LmZvckVhY2goaWQgPT4gbmdiQ29tcGxldGVUcmFuc2l0aW9uKHRoaXMuX2dldFNsaWRlRWxlbWVudChpZCkpKTtcbiAgICAgIHRoaXMuX3RyYW5zaXRpb25JZHMgPSBudWxsO1xuXG4gICAgICB0aGlzLl9jZC5tYXJrRm9yQ2hlY2soKTtcblxuICAgICAgLy8gVGhlIGZvbGxvd2luZyBjb2RlIG5lZWQgdG8gYmUgZG9uZSBhc3luY2hyb25vdXNseSwgYWZ0ZXIgdGhlIGRvbSBiZWNvbWVzIHN0YWJsZSxcbiAgICAgIC8vIG90aGVyd2lzZSBhbGwgY2hhbmdlcyB3aWxsIGJlIHVuZG9uZS5cbiAgICAgIHRoaXMuX25nWm9uZS5vblN0YWJsZS5waXBlKHRha2UoMSkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgeyBpZCB9IG9mIHRoaXMuc2xpZGVzKSB7XG4gICAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuX2dldFNsaWRlRWxlbWVudChpZCk7XG4gICAgICAgICAgaWYgKGlkID09PSB0aGlzLmFjdGl2ZUlkKSB7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudENoZWNrZWQoKSB7XG4gICAgbGV0IGFjdGl2ZVNsaWRlID0gdGhpcy5fZ2V0U2xpZGVCeUlkKHRoaXMuYWN0aXZlSWQpO1xuICAgIHRoaXMuYWN0aXZlSWQgPSBhY3RpdmVTbGlkZSA/IGFjdGl2ZVNsaWRlLmlkIDogKHRoaXMuc2xpZGVzLmxlbmd0aCA/IHRoaXMuc2xpZGVzLmZpcnN0LmlkIDogJycpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIC8vIEluaXRpYWxpemUgdGhlICdhY3RpdmUnIGNsYXNzIChub3QgbWFuYWdlZCBieSB0aGUgdGVtcGxhdGUpXG4gICAgaWYgKHRoaXMuYWN0aXZlSWQpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLl9nZXRTbGlkZUVsZW1lbnQodGhpcy5hY3RpdmVJZCk7XG4gICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2FjdGl2ZScpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkgeyB0aGlzLl9kZXN0cm95JC5uZXh0KCk7IH1cblxuICAvKipcbiAgICogTmF2aWdhdGVzIHRvIGEgc2xpZGUgd2l0aCB0aGUgc3BlY2lmaWVkIGlkZW50aWZpZXIuXG4gICAqL1xuICBzZWxlY3Qoc2xpZGVJZDogc3RyaW5nLCBzb3VyY2U/OiBOZ2JTbGlkZUV2ZW50U291cmNlKSB7XG4gICAgdGhpcy5fY3ljbGVUb1NlbGVjdGVkKHNsaWRlSWQsIHRoaXMuX2dldFNsaWRlRXZlbnREaXJlY3Rpb24odGhpcy5hY3RpdmVJZCwgc2xpZGVJZCksIHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogTmF2aWdhdGVzIHRvIHRoZSBwcmV2aW91cyBzbGlkZS5cbiAgICovXG4gIHByZXYoc291cmNlPzogTmdiU2xpZGVFdmVudFNvdXJjZSkge1xuICAgIHRoaXMuX2N5Y2xlVG9TZWxlY3RlZCh0aGlzLl9nZXRQcmV2U2xpZGUodGhpcy5hY3RpdmVJZCksIE5nYlNsaWRlRXZlbnREaXJlY3Rpb24uUklHSFQsIHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogTmF2aWdhdGVzIHRvIHRoZSBuZXh0IHNsaWRlLlxuICAgKi9cbiAgbmV4dChzb3VyY2U/OiBOZ2JTbGlkZUV2ZW50U291cmNlKSB7XG4gICAgdGhpcy5fY3ljbGVUb1NlbGVjdGVkKHRoaXMuX2dldE5leHRTbGlkZSh0aGlzLmFjdGl2ZUlkKSwgTmdiU2xpZGVFdmVudERpcmVjdGlvbi5MRUZULCBzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhdXNlcyBjeWNsaW5nIHRocm91Z2ggdGhlIHNsaWRlcy5cbiAgICovXG4gIHBhdXNlKCkgeyB0aGlzLl9wYXVzZSQubmV4dCh0cnVlKTsgfVxuXG4gIC8qKlxuICAgKiBSZXN0YXJ0cyBjeWNsaW5nIHRocm91Z2ggdGhlIHNsaWRlcyBmcm9tIGxlZnQgdG8gcmlnaHQuXG4gICAqL1xuICBjeWNsZSgpIHsgdGhpcy5fcGF1c2UkLm5leHQoZmFsc2UpOyB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZm9jdXMgb24gdGhlIGNhcm91c2VsLlxuICAgKi9cbiAgZm9jdXMoKSB7IHRoaXMuX2NvbnRhaW5lci5uYXRpdmVFbGVtZW50LmZvY3VzKCk7IH1cblxuICBwcml2YXRlIF9jeWNsZVRvU2VsZWN0ZWQoc2xpZGVJZHg6IHN0cmluZywgZGlyZWN0aW9uOiBOZ2JTbGlkZUV2ZW50RGlyZWN0aW9uLCBzb3VyY2U/OiBOZ2JTbGlkZUV2ZW50U291cmNlKSB7XG4gICAgY29uc3QgdHJhbnNpdGlvbklkcyA9IHRoaXMuX3RyYW5zaXRpb25JZHM7XG4gICAgaWYgKHRyYW5zaXRpb25JZHMgJiYgKHRyYW5zaXRpb25JZHNbMF0gIT09IHNsaWRlSWR4IHx8IHRyYW5zaXRpb25JZHNbMV0gIT09IHRoaXMuYWN0aXZlSWQpKSB7XG4gICAgICAvLyBSZXZlcnQgcHJldmVudGVkXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNlbGVjdGVkU2xpZGUgPSB0aGlzLl9nZXRTbGlkZUJ5SWQoc2xpZGVJZHgpO1xuICAgIGlmIChzZWxlY3RlZFNsaWRlICYmIHNlbGVjdGVkU2xpZGUuaWQgIT09IHRoaXMuYWN0aXZlSWQpIHtcbiAgICAgIHRoaXMuX3RyYW5zaXRpb25JZHMgPSBbdGhpcy5hY3RpdmVJZCwgc2xpZGVJZHhdO1xuICAgICAgdGhpcy5zbGlkZS5lbWl0KFxuICAgICAgICAgIHtwcmV2OiB0aGlzLmFjdGl2ZUlkLCBjdXJyZW50OiBzZWxlY3RlZFNsaWRlLmlkLCBkaXJlY3Rpb246IGRpcmVjdGlvbiwgcGF1c2VkOiB0aGlzLl9wYXVzZSQudmFsdWUsIHNvdXJjZX0pO1xuXG4gICAgICBjb25zdCBvcHRpb25zOiBOZ2JUcmFuc2l0aW9uT3B0aW9uczxOZ2JDYXJvdXNlbEN0eD4gPSB7XG4gICAgICAgIGFuaW1hdGlvbjogdGhpcy5hbmltYXRpb24sXG4gICAgICAgIHJ1bm5pbmdUcmFuc2l0aW9uOiAnc3RvcCcsXG4gICAgICAgIGNvbnRleHQ6IHtkaXJlY3Rpb259LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHJhbnNpdGlvbnM6IEFycmF5PE9ic2VydmFibGU8YW55Pj4gPSBbXTtcbiAgICAgIGNvbnN0IGFjdGl2ZVNsaWRlID0gdGhpcy5fZ2V0U2xpZGVCeUlkKHRoaXMuYWN0aXZlSWQpO1xuICAgICAgaWYgKGFjdGl2ZVNsaWRlKSB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZVNsaWRlVHJhbnNpdGlvbiA9XG4gICAgICAgICAgICBuZ2JSdW5UcmFuc2l0aW9uKHRoaXMuX25nWm9uZSwgdGhpcy5fZ2V0U2xpZGVFbGVtZW50KGFjdGl2ZVNsaWRlLmlkKSwgbmdiQ2Fyb3VzZWxUcmFuc2l0aW9uT3V0LCBvcHRpb25zKTtcbiAgICAgICAgYWN0aXZlU2xpZGVUcmFuc2l0aW9uLnN1YnNjcmliZSgoKSA9PiB7IGFjdGl2ZVNsaWRlLnNsaWQuZW1pdCh7aXNTaG93bjogZmFsc2UsIGRpcmVjdGlvbiwgc291cmNlfSk7IH0pO1xuICAgICAgICB0cmFuc2l0aW9ucy5wdXNoKGFjdGl2ZVNsaWRlVHJhbnNpdGlvbik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHByZXZpb3VzSWQgPSB0aGlzLmFjdGl2ZUlkO1xuICAgICAgdGhpcy5hY3RpdmVJZCA9IHNlbGVjdGVkU2xpZGUuaWQ7XG4gICAgICBjb25zdCBuZXh0U2xpZGUgPSB0aGlzLl9nZXRTbGlkZUJ5SWQodGhpcy5hY3RpdmVJZCk7XG4gICAgICBjb25zdCB0cmFuc2l0aW9uID1cbiAgICAgICAgICBuZ2JSdW5UcmFuc2l0aW9uKHRoaXMuX25nWm9uZSwgdGhpcy5fZ2V0U2xpZGVFbGVtZW50KHNlbGVjdGVkU2xpZGUuaWQpLCBuZ2JDYXJvdXNlbFRyYW5zaXRpb25Jbiwgb3B0aW9ucyk7XG4gICAgICB0cmFuc2l0aW9uLnN1YnNjcmliZSgoKSA9PiB7IG5leHRTbGlkZSA/LnNsaWQuZW1pdCh7aXNTaG93bjogdHJ1ZSwgZGlyZWN0aW9uLCBzb3VyY2V9KTsgfSk7XG4gICAgICB0cmFuc2l0aW9ucy5wdXNoKHRyYW5zaXRpb24pO1xuXG4gICAgICB6aXAoLi4udHJhbnNpdGlvbnMpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fdHJhbnNpdGlvbklkcyA9IG51bGw7XG4gICAgICAgIHRoaXMuc2xpZC5lbWl0KFxuICAgICAgICAgICAge3ByZXY6IHByZXZpb3VzSWQsIGN1cnJlbnQ6IHNlbGVjdGVkU2xpZGUgIS5pZCwgZGlyZWN0aW9uOiBkaXJlY3Rpb24sIHBhdXNlZDogdGhpcy5fcGF1c2UkLnZhbHVlLCBzb3VyY2V9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIHdlIGdldCBoZXJlIGFmdGVyIHRoZSBpbnRlcnZhbCBmaXJlcyBvciBhbnkgZXh0ZXJuYWwgQVBJIGNhbGwgbGlrZSBuZXh0KCksIHByZXYoKSBvciBzZWxlY3QoKVxuICAgIHRoaXMuX2NkLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0U2xpZGVFdmVudERpcmVjdGlvbihjdXJyZW50QWN0aXZlU2xpZGVJZDogc3RyaW5nLCBuZXh0QWN0aXZlU2xpZGVJZDogc3RyaW5nKTogTmdiU2xpZGVFdmVudERpcmVjdGlvbiB7XG4gICAgY29uc3QgY3VycmVudE