UNPKG

ngx-carousel-ease

Version:

ngx-carousel-ease is a versatile Angular library providing a feature-rich, simple, and performant carousel component. This library supports infinite and responsive mode, mouse and touch event. Attention has been put to accessibility, performance, and frie

345 lines 46.9 kB
import { CommunSlider } from './communSlider'; export class InfiniteSlider extends CommunSlider { constructor(carousel, responsive, slideToScroll, LIMIT_AUTO_SLIDE, strechingLimit, autoSlide, animationTimingFn, animationTimingMs, MAX_DOM_SIZE, enableMouseDrag, enableTouch, autoPlay, autoPlayInterval, autoPlayAtStart, playDirection, autoplaySlideToScroll, carouselService, cd) { super(carousel, responsive, slideToScroll, LIMIT_AUTO_SLIDE, strechingLimit, autoSlide, animationTimingFn, animationTimingMs, enableMouseDrag, enableTouch, autoPlay, autoPlayInterval, autoPlayAtStart, playDirection, autoplaySlideToScroll, carouselService, cd); this.MAX_DOM_SIZE = MAX_DOM_SIZE; this.initProperties(); this.updateProperties(); this.addSlidesToRightAtStart(); } initProperties() { this.defineAutoPlayDirection(); super.initProperties(); } /** * next and prev are defined separatively */ defineAutoPlayDirection() { if (this.playDirection === 'ltr') { this.directionAutoPlay = this.next.bind(this); } else { this.directionAutoPlay = this.prev.bind(this); } } /** * Add slides to the right at start * If only one window (number of dots === 1) and not responsive mode, there is possibly space at start for slides to the right (even though this configuration does not make a lot of sense) * TODO: ajouter des slides si slidesToShow > total slides */ addSlidesToRightAtStart() { if (this.carousel.numberDots() > 1 || this.responsive) { return; } this.addSlidesToTheRight(); } /** * Fired at drag start * Instantiate property of the starting drag point on the X axis. Used to compute the translation. * Disabling the transition while applying the transformation because of the attached animation. */ dragStart(event) { if (super.currentEventIsDisabled(event)) return; super.dragStart(event); } /** * Relaunch autoPlay if not disabled or infinite mode (never disabled by limits) * Restart only if started (playActive). */ relaunchAutoPlay() { if (this.playActive()) { clearInterval(this.autoInterval); this.launchAutoPlay(); } } /** * Fired at drag end */ dragStop(event) { if (this.currentEventIsDisabled(event)) return; this.dragging.set(false); this.previousTranslation = this.currentTranslation(); this.autoSlider(); } autoSlider() { if (!this.autoSlide) return; const referenceWidth = Math.min(this.carousel.slideWidth, this.carousel.slideMaxWidth || Infinity); const currentLimit = this.prevLimit + this.carousel.slideWidthWithGap; // previousTranslation always a negative number, currentLimit always positive const currentPositionChange = this.previousTranslation + currentLimit; const moveComparedToSlide = (currentPositionChange / referenceWidth) * 100; if (moveComparedToSlide < -this.LIMIT_AUTO_SLIDE || moveComparedToSlide > this.LIMIT_AUTO_SLIDE) { if (moveComparedToSlide > this.LIMIT_AUTO_SLIDE) { this.changeSlideNumber(-1); this.decreaseLimits(); } else { this.changeSlideNumber(1); this.increaseLimits(); } } if (-this.currentTranslation() > this.lastWindowTranslation) { this.addSlidesToTheRight(); } this.computeTransformation(this.accumulatedSlide); } /** * Fired at dragging * Compute the translation, change the slide number, update the direction. */ dragMove(event) { if (this.currentEventIsDisabled(event)) return; if (!this.dragging()) return; this.currentX = event instanceof MouseEvent ? event.pageX : event.changedTouches[0].pageX; this.setDirection(); this.previousX = this.currentX; this.positionChange = this.currentX - this.startX; this.currentTranslation.set(this.positionChange + this.previousTranslation); this.applyTranslation(this.currentTranslation()); this.modifyCurrentSlide(); } /** * Responsible for changing slide number and updating the limits. * If createSlidesInfiniteModeIfLimitsReached() doesn't take action, slide change according to previous computed limits. */ modifyCurrentSlide() { if (this.createSlidesInfiniteModeIfLimits()) return; if (-this.currentTranslation() < this.prevLimit) { this.changeSlideNumber(-1); this.decreaseLimits(); } else if (-this.currentTranslation() >= this.nextLimit) { this.changeSlideNumber(1); this.increaseLimits(); } } /** * Handle slide creation in infinite mode if limits reached * Mouse or touch drag. */ createSlidesInfiniteModeIfLimits() { if (this.currentTranslation() > 0) { this.addSlidesToTheLeft(); this.decreaseLimits(true); // not enabled at start if (this.currentSlide() > 0) { this.changeSlideNumber(-1); } return true; } else if (-this.currentTranslation() > this.lastWindowTranslation) { this.addSlidesToTheRight(); if (this.DOMLimitReached) { this.changePrevAndNextLimits(this.accumulatedSlide); return true; } } return false; } /** * Append or prepend new slides according to the direction * If new slides prepended, update the translation to the correct place (appending new slides do not change the translation). * Limit DOM growth or update last window translation if applicable. */ appendOrPrependNElements() { if (this.direction === 'left') { for (let i = this.arrayOfSlides.length - 1; i >= 0; i--) { const clonedElement = this.arrayOfSlides[i].cloneNode(true); this.slidesContainer.prepend(clonedElement); } this.accumulatedSlide += this.totalSlides; this.resetViewLeftDirection(); } else { for (let i = 0; i < this.arrayOfSlides.length; i++) { const clonedElement = this.arrayOfSlides[i].cloneNode(true); this.slidesContainer.append(clonedElement); } } if (this.totalAmountOfSlides >= this.MAX_DOM_SIZE * this.totalSlides) { // Limit DOM growth, max X times original DOM // console.log('dom limit reached'); this.limitDOMGrowth(); this.DOMLimitReached = true; } else { this.totalAmountOfSlides += this.totalSlides; this.DOMLimitReached = false; this.updateLastWindowTranslation(); } } /** * Limit DOM growth * Reset the view accordingly. */ limitDOMGrowth() { const slides = this.carousel.selectSlides(); if (this.direction === 'right') { for (let i = 0; i < this.totalSlides; i++) { slides[i].remove(); } this.resetViewRightDirection(); this.accumulatedSlide -= this.totalSlides; } else { for (let i = slides.length - 1; i > slides.length - this.totalSlides - 1; i--) { slides[i].remove(); } } } /** * Reset the view in a movement to the left * New slides added to the left, so the view has to be updated accordingly. * If the carousel is moved with the mouse | touch event (dragging is true), the offset should be equal to a full carousel width. Otherwise (with the buttons), the computed translation should be taken into account. * Side comment: the view does not have to be updated for slides added to the right, since relative order does not change. * getBoundingClientRect triggers reflow of the element. */ resetViewLeftDirection() { const translation = Math.abs(this.previousTranslation) + this.fullWidthInf; this.previousTranslation = -translation; this.slidesContainer.style.transition = 'none'; const transformation = this.dragging() ? -this.fullWidthInf : -translation; this.applyTranslation(transformation); this.slidesContainer.getBoundingClientRect(); } /** * Reset the view in a movement to the right * First set of slides have been deleted, so the translation has to be updated accordingly. * currentTranslation is a negative number so it will be decreased by a set of slides. * getBoundingClientRect triggers reflow of the element. */ resetViewRightDirection() { const translation = this.currentTranslation() + this.fullWidthInf; this.slidesContainer.style.transition = 'none'; this.applyTranslation(translation); this.previousTranslation = translation - this.positionChange; this.slidesContainer.getBoundingClientRect(); } addSlidesToTheLeft() { this.appendOrPrependNElements(); } addSlidesToTheRight() { this.appendOrPrependNElements(); } /** * Increase limit on basis of previous computed limits (movement to the right) * Schema: || previous | current || next */ increaseLimits() { this.nextLimit += Math.floor(this.carousel.slideWidthWithGap); this.prevLimit = Math.floor(this.nextLimit - this.carousel.slideWidthWithGap * 2); } /** * Previous button navigation */ prev(slides = this.slideToScroll) { this.direction = 'left'; this.handleBtnInfinite(-slides); this.changeSlideNumber(-slides); this.changePrevAndNextLimits(this.accumulatedSlide); this.computeTransformation(this.accumulatedSlide); this.relaunchAutoPlay(); } /** * Next button navigation */ next(slides = this.slideToScroll) { this.direction = 'right'; this.handleBtnInfinite(slides); this.changeSlideNumber(slides); this.changePrevAndNextLimits(this.accumulatedSlide); this.computeTransformation(this.accumulatedSlide); this.relaunchAutoPlay(); } /** * Buttons navigation in infinite mode * Create new slide if limits reached (start or end). Update slide, limits and apply transformation accordingly. */ handleBtnInfinite(step) { let cardOffset = 0; const goingTo = this.accumulatedSlide + step; // there is (possibly) a card offset if not responsive if (!this.responsive) cardOffset = 1; if (goingTo < 0) { this.addSlidesToTheLeft(); } else if (goingTo + this.carousel.slideToShow + cardOffset > this.totalAmountOfSlides) { this.addSlidesToTheRight(); } } /** * Navigation with bullet points * Update values accordingly. */ goTo(bullet) { const slideHasChanged = this.currentSlide() !== bullet; this.direction = this.currentSlide() < bullet ? 'right' : 'left'; this.currentSlide.set(bullet); this.fireSlideChangeEvent(slideHasChanged, this.currentSlide()); this.relaunchAutoPlay(); this.navInfiniteBullets(bullet); } /** * Bullets navigation * Create new slides if exceeding end of carousel. */ navInfiniteBullets(bullet) { let cardOffset = 0; const positionOfCurrentSlide = this.accumulatedSlide % this.totalSlides; const difference = bullet - positionOfCurrentSlide; this.accumulatedSlide += difference; // there is (possibly) a card offset if not responsive if (!this.responsive) cardOffset = 1; if (this.accumulatedSlide + this.carousel.slideToShow + cardOffset > this.totalAmountOfSlides) { this.addSlidesToTheRight(); } this.computeTransformation(this.accumulatedSlide); this.changePrevAndNextLimits(this.accumulatedSlide); } /** * Exception: if only one window (numberDots === 1), update the accumulatedSlide to let the transformation occurs, but currentSlide should stay at 0. */ changeSlideNumber(step) { const slideNumberBeforeChange = this.currentSlide(); this.infiniteChangeSlideNumber(step); if (this.carousel.numberDots() === 1) { this.currentSlide.set(0); } const current = this.carousel.numberDots() > 1 ? this.currentSlide() : this.accumulatedSlide; const slideHasChanged = slideNumberBeforeChange !== this.currentSlide(); this.fireSlideChangeEvent(slideHasChanged, current); } infiniteChangeSlideNumber(step) { this.accumulatedSlide += step; this.currentSlide.update((slide) => slide + step); const lastSlide = this.totalSlides - 1; if (this.currentSlide() > lastSlide) { this.currentSlide.update((slide) => slide % this.totalSlides); } else if (this.currentSlide() < 0) { this.currentSlide.update((slide) => slide + this.totalSlides); } } /** * Compute transformation that will be applied on basis of the provided slide number */ computeTransformation(slide) { const transformation = slide * this.carousel.slideWidthWithGap; this.applyTransformation(transformation); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5maW5pdGVTbGlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jYXJvdXNlbC9zcmMvbGliL2luZmluaXRlU2xpZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU5QyxNQUFNLE9BQU8sY0FBZSxTQUFRLFlBQVk7SUFHOUMsWUFDRSxRQUFrQixFQUNsQixVQUFtQixFQUNuQixhQUFxQixFQUNyQixnQkFBd0IsRUFDeEIsY0FBc0IsRUFDdEIsU0FBa0IsRUFDbEIsaUJBQXlCLEVBQ3pCLGlCQUF5QixFQUN6QixZQUFvQixFQUNwQixlQUF3QixFQUN4QixXQUFvQixFQUNwQixRQUFpQixFQUNqQixnQkFBd0IsRUFDeEIsZUFBd0IsRUFDeEIsYUFBcUIsRUFDckIscUJBQTZCLEVBQzdCLGVBQWdDLEVBQ2hDLEVBQXFCO1FBRXJCLEtBQUssQ0FDSCxRQUFRLEVBQ1IsVUFBVSxFQUNWLGFBQWEsRUFDYixnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLFNBQVMsRUFDVCxpQkFBaUIsRUFDakIsaUJBQWlCLEVBQ2pCLGVBQWUsRUFDZixXQUFXLEVBQ1gsUUFBUSxFQUNSLGdCQUFnQixFQUNoQixlQUFlLEVBQ2YsYUFBYSxFQUNiLHFCQUFxQixFQUNyQixlQUFlLEVBQ2YsRUFBRSxDQUNILENBQUM7UUFDRixJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7SUFDakMsQ0FBQztJQUVRLGNBQWM7UUFDckIsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7UUFDL0IsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNILHVCQUF1QjtRQUNyQixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILHVCQUF1QjtRQUNyQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN0RCxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRDs7OztPQUlHO0lBQ00sU0FBUyxDQUFDLEtBQThCO1FBQy9DLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU87UUFFaEQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN6QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsZ0JBQWdCO1FBQ2QsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQztZQUN0QixhQUFhLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN4QixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUSxDQUFDLEtBQThCO1FBQ3JDLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU87UUFDL0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBRXJELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQsVUFBVTtRQUNSLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFFNUIsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDN0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxJQUFJLFFBQVEsQ0FDeEMsQ0FBQztRQUNGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQztRQUV0RSw2RUFBNkU7UUFDN0UsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsWUFBWSxDQUFDO1FBQ3RFLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxxQkFBcUIsR0FBRyxjQUFjLENBQUMsR0FBRyxHQUFHLENBQUM7UUFFM0UsSUFDRSxtQkFBbUIsR0FBRyxDQUFDLElBQUksQ0FBQyxnQkFBZ0I7WUFDNUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixFQUMzQyxDQUFDO1lBQ0QsSUFBSSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDaEQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN4QixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMxQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDeEIsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDNUQsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDN0IsQ0FBQztRQUVELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsUUFBUSxDQUFDLEtBQThCO1FBQ3JDLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU87UUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFBRSxPQUFPO1FBRTdCLElBQUksQ0FBQyxRQUFRO1lBQ1gsS0FBSyxZQUFZLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7UUFFNUUsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUUvQixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNsRCxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFFNUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILGtCQUFrQjtRQUNoQixJQUFJLElBQUksQ0FBQyxnQ0FBZ0MsRUFBRTtZQUFFLE9BQU87UUFFcEQsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDeEIsQ0FBQzthQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDeEQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN4QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILGdDQUFnQztRQUM5QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFMUIsdUJBQXVCO1lBQ3ZCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUM1QixJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM3QixDQUFDO1lBQ0QsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO2FBQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ25FLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRTNCLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUN6QixJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7Z0JBQ3BELE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsd0JBQXdCO1FBQ3RCLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUM5QixLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3hELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUM1RCxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM5QyxDQUFDO1lBRUQsSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUM7WUFDMUMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDaEMsQ0FBQzthQUFNLENBQUM7WUFDTixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDbkQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzVELElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQzdDLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsbUJBQW1CLElBQUksSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckUsNkNBQTZDO1lBQzdDLG9DQUFvQztZQUNwQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdEIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUM7UUFDOUIsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsbUJBQW1CLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQztZQUM3QyxJQUFJLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQztZQUM3QixJQUFJLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztRQUNyQyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILGNBQWM7UUFDWixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBRTVDLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUMvQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUMxQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDckIsQ0FBQztZQUVELElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQzVDLENBQUM7YUFBTSxDQUFDO1lBQ04sS0FDRSxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFDekIsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLEVBQ3hDLENBQUMsRUFBRSxFQUNILENBQUM7Z0JBQ0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILHNCQUFzQjtRQUNwQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDM0UsSUFBSSxDQUFDLG1CQUFtQixHQUFHLENBQUMsV0FBVyxDQUFDO1FBRXhDLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUM7UUFDL0MsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1FBQzNFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV0QyxJQUFJLENBQUMsZUFBZSxDQUFDLHFCQUFxQixFQUFFLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsdUJBQXVCO1FBQ3JCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFFbEUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztRQUMvQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBRTdELElBQUksQ0FBQyxlQUFlLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUMvQyxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRCxtQkFBbUI7UUFDakIsSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7SUFDbEMsQ0FBQztJQUVEOzs7T0FHRztJQUNNLGNBQWM7UUFDckIsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQ3JELENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhO1FBQzlCLElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDO1FBRXhCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYTtRQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQztRQUV6QixJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILGlCQUFpQixDQUFDLElBQVk7UUFDNUIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFFN0Msc0RBQXNEO1FBQ3RELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVTtZQUFFLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFFckMsSUFBSSxPQUFPLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDaEIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDNUIsQ0FBQzthQUFNLElBQ0wsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxHQUFHLFVBQVU7WUFDaEQsSUFBSSxDQUFDLG1CQUFtQixFQUN4QixDQUFDO1lBQ0QsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJLENBQUMsTUFBYztRQUNqQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFLEtBQUssTUFBTSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFFakUsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUVoRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILGtCQUFrQixDQUFDLE1BQWM7UUFDL0IsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDeEUsTUFBTSxVQUFVLEdBQUcsTUFBTSxHQUFHLHNCQUFzQixDQUFDO1FBQ25ELElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxVQUFVLENBQUM7UUFFcEMsc0RBQXNEO1FBQ3RELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVTtZQUFFLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFFckMsSUFDRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEdBQUcsVUFBVTtZQUM5RCxJQUFJLENBQUMsbUJBQW1CLEVBQ3hCLENBQUM7WUFDRCxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUM3QixDQUFDO1FBRUQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxpQkFBaUIsQ0FBQyxJQUFZO1FBQzVCLE1BQU0sdUJBQXVCLEdBQVcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzVELElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0IsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUNYLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLEdBQUcsQ0FBQztZQUM1QixDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDO1FBRTVCLE1BQU0sZUFBZSxHQUNuQix1QkFBdUIsS0FBSyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbEQsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQseUJBQXlCLENBQUMsSUFBWTtRQUNwQyxJQUFJLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDO1FBQzlCLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFFbEQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLEdBQUcsU0FBUyxFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDaEUsQ0FBQzthQUFNLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ25DLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxxQkFBcUIsQ0FBQyxLQUFhO1FBQ2pDLE1BQU0sY0FBYyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDO1FBRS9ELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUMzQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3RvclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDYXJvdXNlbCB9IGZyb20gJy4vY2Fyb3VzZWwnO1xyXG5pbXBvcnQgeyBDYXJvdXNlbFNlcnZpY2UgfSBmcm9tICcuL2Nhcm91c2VsLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDb21tdW5TbGlkZXIgfSBmcm9tICcuL2NvbW11blNsaWRlcic7XHJcblxyXG5leHBvcnQgY2xhc3MgSW5maW5pdGVTbGlkZXIgZXh0ZW5kcyBDb21tdW5TbGlkZXIge1xyXG4gIHJlYWRvbmx5IE1BWF9ET01fU0laRTogbnVtYmVyO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIGNhcm91c2VsOiBDYXJvdXNlbCxcclxuICAgIHJlc3BvbnNpdmU6IGJvb2xlYW4sXHJcbiAgICBzbGlkZVRvU2Nyb2xsOiBudW1iZXIsXHJcbiAgICBMSU1JVF9BVVRPX1NMSURFOiBudW1iZXIsXHJcbiAgICBzdHJlY2hpbmdMaW1pdDogbnVtYmVyLFxyXG4gICAgYXV0b1NsaWRlOiBib29sZWFuLFxyXG4gICAgYW5pbWF0aW9uVGltaW5nRm46IHN0cmluZyxcclxuICAgIGFuaW1hdGlvblRpbWluZ01zOiBudW1iZXIsXHJcbiAgICBNQVhfRE9NX1NJWkU6IG51bWJlcixcclxuICAgIGVuYWJsZU1vdXNlRHJhZzogYm9vbGVhbixcclxuICAgIGVuYWJsZVRvdWNoOiBib29sZWFuLFxyXG4gICAgYXV0b1BsYXk6IGJvb2xlYW4sXHJcbiAgICBhdXRvUGxheUludGVydmFsOiBudW1iZXIsXHJcbiAgICBhdXRvUGxheUF0U3RhcnQ6IGJvb2xlYW4sXHJcbiAgICBwbGF5RGlyZWN0aW9uOiBzdHJpbmcsXHJcbiAgICBhdXRvcGxheVNsaWRlVG9TY3JvbGw6IG51bWJlcixcclxuICAgIGNhcm91c2VsU2VydmljZTogQ2Fyb3VzZWxTZXJ2aWNlLFxyXG4gICAgY2Q6IENoYW5nZURldGVjdG9yUmVmXHJcbiAgKSB7XHJcbiAgICBzdXBlcihcclxuICAgICAgY2Fyb3VzZWwsXHJcbiAgICAgIHJlc3BvbnNpdmUsXHJcbiAgICAgIHNsaWRlVG9TY3JvbGwsXHJcbiAgICAgIExJTUlUX0FVVE9fU0xJREUsXHJcbiAgICAgIHN0cmVjaGluZ0xpbWl0LFxyXG4gICAgICBhdXRvU2xpZGUsXHJcbiAgICAgIGFuaW1hdGlvblRpbWluZ0ZuLFxyXG4gICAgICBhbmltYXRpb25UaW1pbmdNcyxcclxuICAgICAgZW5hYmxlTW91c2VEcmFnLFxyXG4gICAgICBlbmFibGVUb3VjaCxcclxuICAgICAgYXV0b1BsYXksXHJcbiAgICAgIGF1dG9QbGF5SW50ZXJ2YWwsXHJcbiAgICAgIGF1dG9QbGF5QXRTdGFydCxcclxuICAgICAgcGxheURpcmVjdGlvbixcclxuICAgICAgYXV0b3BsYXlTbGlkZVRvU2Nyb2xsLFxyXG4gICAgICBjYXJvdXNlbFNlcnZpY2UsXHJcbiAgICAgIGNkXHJcbiAgICApO1xyXG4gICAgdGhpcy5NQVhfRE9NX1NJWkUgPSBNQVhfRE9NX1NJWkU7XHJcbiAgICB0aGlzLmluaXRQcm9wZXJ0aWVzKCk7XHJcbiAgICB0aGlzLnVwZGF0ZVByb3BlcnRpZXMoKTtcclxuICAgIHRoaXMuYWRkU2xpZGVzVG9SaWdodEF0U3RhcnQoKTtcclxuICB9XHJcblxyXG4gIG92ZXJyaWRlIGluaXRQcm9wZXJ0aWVzKCkge1xyXG4gICAgdGhpcy5kZWZpbmVBdXRvUGxheURpcmVjdGlvbigpO1xyXG4gICAgc3VwZXIuaW5pdFByb3BlcnRpZXMoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIG5leHQgYW5kIHByZXYgYXJlIGRlZmluZWQgc2VwYXJhdGl2ZWx5XHJcbiAgICovXHJcbiAgZGVmaW5lQXV0b1BsYXlEaXJlY3Rpb24oKSB7XHJcbiAgICBpZiAodGhpcy5wbGF5RGlyZWN0aW9uID09PSAnbHRyJykge1xyXG4gICAgICB0aGlzLmRpcmVjdGlvbkF1dG9QbGF5ID0gdGhpcy5uZXh0LmJpbmQodGhpcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmRpcmVjdGlvbkF1dG9QbGF5ID0gdGhpcy5wcmV2LmJpbmQodGhpcyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGQgc2xpZGVzIHRvIHRoZSByaWdodCBhdCBzdGFydFxyXG4gICAqIElmIG9ubHkgb25lIHdpbmRvdyAobnVtYmVyIG9mIGRvdHMgPT09IDEpIGFuZCBub3QgcmVzcG9uc2l2ZSBtb2RlLCB0aGVyZSBpcyBwb3NzaWJseSBzcGFjZSBhdCBzdGFydCBmb3Igc2xpZGVzIHRvIHRoZSByaWdodCAoZXZlbiB0aG91Z2ggdGhpcyBjb25maWd1cmF0aW9uIGRvZXMgbm90IG1ha2UgYSBsb3Qgb2Ygc2Vuc2UpXHJcbiAgICogVE9ETzogYWpvdXRlciBkZXMgc2xpZGVzIHNpIHNsaWRlc1RvU2hvdyA+IHRvdGFsIHNsaWRlc1xyXG4gICAqL1xyXG4gIGFkZFNsaWRlc1RvUmlnaHRBdFN0YXJ0KCkge1xyXG4gICAgaWYgKHRoaXMuY2Fyb3VzZWwubnVtYmVyRG90cygpID4gMSB8fCB0aGlzLnJlc3BvbnNpdmUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuYWRkU2xpZGVzVG9UaGVSaWdodCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRmlyZWQgYXQgZHJhZyBzdGFydFxyXG4gICAqIEluc3RhbnRpYXRlIHByb3BlcnR5IG9mIHRoZSBzdGFydGluZyBkcmFnIHBvaW50IG9uIHRoZSBYIGF4aXMuIFVzZWQgdG8gY29tcHV0ZSB0aGUgdHJhbnNsYXRpb24uXHJcbiAgICogRGlzYWJsaW5nIHRoZSB0cmFuc2l0aW9uIHdoaWxlIGFwcGx5aW5nIHRoZSB0cmFuc2Zvcm1hdGlvbiBiZWNhdXNlIG9mIHRoZSBhdHRhY2hlZCBhbmltYXRpb24uXHJcbiAgICovXHJcbiAgb3ZlcnJpZGUgZHJhZ1N0YXJ0KGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkge1xyXG4gICAgaWYgKHN1cGVyLmN1cnJlbnRFdmVudElzRGlzYWJsZWQoZXZlbnQpKSByZXR1cm47XHJcblxyXG4gICAgc3VwZXIuZHJhZ1N0YXJ0KGV2ZW50KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbGF1bmNoIGF1dG9QbGF5IGlmIG5vdCBkaXNhYmxlZCBvciBpbmZpbml0ZSBtb2RlIChuZXZlciBkaXNhYmxlZCBieSBsaW1pdHMpXHJcbiAgICogUmVzdGFydCBvbmx5IGlmIHN0YXJ0ZWQgKHBsYXlBY3RpdmUpLlxyXG4gICAqL1xyXG4gIHJlbGF1bmNoQXV0b1BsYXkoKSB7XHJcbiAgICBpZiAodGhpcy5wbGF5QWN0aXZlKCkpIHtcclxuICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmF1dG9JbnRlcnZhbCk7XHJcbiAgICAgIHRoaXMubGF1bmNoQXV0b1BsYXkoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZpcmVkIGF0IGRyYWcgZW5kXHJcbiAgICovXHJcbiAgZHJhZ1N0b3AoZXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KSB7XHJcbiAgICBpZiAodGhpcy5jdXJyZW50RXZlbnRJc0Rpc2FibGVkKGV2ZW50KSkgcmV0dXJuO1xyXG4gICAgdGhpcy5kcmFnZ2luZy5zZXQoZmFsc2UpO1xyXG4gICAgdGhpcy5wcmV2aW91c1RyYW5zbGF0aW9uID0gdGhpcy5jdXJyZW50VHJhbnNsYXRpb24oKTtcclxuXHJcbiAgICB0aGlzLmF1dG9TbGlkZXIoKTtcclxuICB9XHJcblxyXG4gIGF1dG9TbGlkZXIoKSB7XHJcbiAgICBpZiAoIXRoaXMuYXV0b1NsaWRlKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgcmVmZXJlbmNlV2lkdGggPSBNYXRoLm1pbihcclxuICAgICAgdGhpcy5jYXJvdXNlbC5zbGlkZVdpZHRoLFxyXG4gICAgICB0aGlzLmNhcm91c2VsLnNsaWRlTWF4V2lkdGggfHwgSW5maW5pdHlcclxuICAgICk7XHJcbiAgICBjb25zdCBjdXJyZW50TGltaXQgPSB0aGlzLnByZXZMaW1pdCArIHRoaXMuY2Fyb3VzZWwuc2xpZGVXaWR0aFdpdGhHYXA7XHJcblxyXG4gICAgLy8gcHJldmlvdXNUcmFuc2xhdGlvbiBhbHdheXMgYSBuZWdhdGl2ZSBudW1iZXIsIGN1cnJlbnRMaW1pdCBhbHdheXMgcG9zaXRpdmVcclxuICAgIGNvbnN0IGN1cnJlbnRQb3NpdGlvbkNoYW5nZSA9IHRoaXMucHJldmlvdXNUcmFuc2xhdGlvbiArIGN1cnJlbnRMaW1pdDtcclxuICAgIGNvbnN0IG1vdmVDb21wYXJlZFRvU2xpZGUgPSAoY3VycmVudFBvc2l0aW9uQ2hhbmdlIC8gcmVmZXJlbmNlV2lkdGgpICogMTAwO1xyXG5cclxuICAgIGlmIChcclxuICAgICAgbW92ZUNvbXBhcmVkVG9TbGlkZSA8IC10aGlzLkxJTUlUX0FVVE9fU0xJREUgfHxcclxuICAgICAgbW92ZUNvbXBhcmVkVG9TbGlkZSA+IHRoaXMuTElNSVRfQVVUT19TTElERVxyXG4gICAgKSB7XHJcbiAgICAgIGlmIChtb3ZlQ29tcGFyZWRUb1NsaWRlID4gdGhpcy5MSU1JVF9BVVRPX1NMSURFKSB7XHJcbiAgICAgICAgdGhpcy5jaGFuZ2VTbGlkZU51bWJlcigtMSk7XHJcbiAgICAgICAgdGhpcy5kZWNyZWFzZUxpbWl0cygpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuY2hhbmdlU2xpZGVOdW1iZXIoMSk7XHJcbiAgICAgICAgdGhpcy5pbmNyZWFzZUxpbWl0cygpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKC10aGlzLmN1cnJlbnRUcmFuc2xhdGlvbigpID4gdGhpcy5sYXN0V2luZG93VHJhbnNsYXRpb24pIHtcclxuICAgICAgdGhpcy5hZGRTbGlkZXNUb1RoZVJpZ2h0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5jb21wdXRlVHJhbnNmb3JtYXRpb24odGhpcy5hY2N1bXVsYXRlZFNsaWRlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZpcmVkIGF0IGRyYWdnaW5nXHJcbiAgICogQ29tcHV0ZSB0aGUgdHJhbnNsYXRpb24sIGNoYW5nZSB0aGUgc2xpZGUgbnVtYmVyLCB1cGRhdGUgdGhlIGRpcmVjdGlvbi5cclxuICAgKi9cclxuICBkcmFnTW92ZShldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpIHtcclxuICAgIGlmICh0aGlzLmN1cnJlbnRFdmVudElzRGlzYWJsZWQoZXZlbnQpKSByZXR1cm47XHJcbiAgICBpZiAoIXRoaXMuZHJhZ2dpbmcoKSkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMuY3VycmVudFggPVxyXG4gICAgICBldmVudCBpbnN0YW5jZW9mIE1vdXNlRXZlbnQgPyBldmVudC5wYWdlWCA6IGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYO1xyXG5cclxuICAgIHRoaXMuc2V0RGlyZWN0aW9uKCk7XHJcbiAgICB0aGlzLnByZXZpb3VzWCA9IHRoaXMuY3VycmVudFg7XHJcblxyXG4gICAgdGhpcy5wb3NpdGlvbkNoYW5nZSA9IHRoaXMuY3VycmVudFggLSB0aGlzLnN0YXJ0WDtcclxuICAgIHRoaXMuY3VycmVudFRyYW5zbGF0aW9uLnNldCh0aGlzLnBvc2l0aW9uQ2hhbmdlICsgdGhpcy5wcmV2aW91c1RyYW5zbGF0aW9uKTtcclxuXHJcbiAgICB0aGlzLmFwcGx5VHJhbnNsYXRpb24odGhpcy5jdXJyZW50VHJhbnNsYXRpb24oKSk7XHJcbiAgICB0aGlzLm1vZGlmeUN1cnJlbnRTbGlkZSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVzcG9uc2libGUgZm9yIGNoYW5naW5nIHNsaWRlIG51bWJlciBhbmQgdXBkYXRpbmcgdGhlIGxpbWl0cy5cclxuICAgKiBJZiBjcmVhdGVTbGlkZXNJbmZpbml0ZU1vZGVJZkxpbWl0c1JlYWNoZWQoKSBkb2Vzbid0IHRha2UgYWN0aW9uLCBzbGlkZSBjaGFuZ2UgYWNjb3JkaW5nIHRvIHByZXZpb3VzIGNvbXB1dGVkIGxpbWl0cy5cclxuICAgKi9cclxuICBtb2RpZnlDdXJyZW50U2xpZGUoKSB7XHJcbiAgICBpZiAodGhpcy5jcmVhdGVTbGlkZXNJbmZpbml0ZU1vZGVJZkxpbWl0cygpKSByZXR1cm47XHJcblxyXG4gICAgaWYgKC10aGlzLmN1cnJlbnRUcmFuc2xhdGlvbigpIDwgdGhpcy5wcmV2TGltaXQpIHtcclxuICAgICAgdGhpcy5jaGFuZ2VTbGlkZU51bWJlcigtMSk7XHJcbiAgICAgIHRoaXMuZGVjcmVhc2VMaW1pdHMoKTtcclxuICAgIH0gZWxzZSBpZiAoLXRoaXMuY3VycmVudFRyYW5zbGF0aW9uKCkgPj0gdGhpcy5uZXh0TGltaXQpIHtcclxuICAgICAgdGhpcy5jaGFuZ2VTbGlkZU51bWJlcigxKTtcclxuICAgICAgdGhpcy5pbmNyZWFzZUxpbWl0cygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlIHNsaWRlIGNyZWF0aW9uIGluIGluZmluaXRlIG1vZGUgaWYgbGltaXRzIHJlYWNoZWRcclxuICAgKiBNb3VzZSBvciB0b3VjaCBkcmFnLlxyXG4gICAqL1xyXG4gIGNyZWF0ZVNsaWRlc0luZmluaXRlTW9kZUlmTGltaXRzKCkge1xyXG4gICAgaWYgKHRoaXMuY3VycmVudFRyYW5zbGF0aW9uKCkgPiAwKSB7XHJcbiAgICAgIHRoaXMuYWRkU2xpZGVzVG9UaGVMZWZ0KCk7XHJcbiAgICAgIHRoaXMuZGVjcmVhc2VMaW1pdHModHJ1ZSk7XHJcblxyXG4gICAgICAvLyBub3QgZW5hYmxlZCBhdCBzdGFydFxyXG4gICAgICBpZiAodGhpcy5jdXJyZW50U2xpZGUoKSA+IDApIHtcclxuICAgICAgICB0aGlzLmNoYW5nZVNsaWRlTnVtYmVyKC0xKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH0gZWxzZSBpZiAoLXRoaXMuY3VycmVudFRyYW5zbGF0aW9uKCkgPiB0aGlzLmxhc3RXaW5kb3dUcmFuc2xhdGlvbikge1xyXG4gICAgICB0aGlzLmFkZFNsaWRlc1RvVGhlUmlnaHQoKTtcclxuXHJcbiAgICAgIGlmICh0aGlzLkRPTUxpbWl0UmVhY2hlZCkge1xyXG4gICAgICAgIHRoaXMuY2hhbmdlUHJldkFuZE5leHRMaW1pdHModGhpcy5hY2N1bXVsYXRlZFNsaWRlKTtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFwcGVuZCBvciBwcmVwZW5kIG5ldyBzbGlkZXMgYWNjb3JkaW5nIHRvIHRoZSBkaXJlY3Rpb25cclxuICAgKiBJZiBuZXcgc2xpZGVzIHByZXBlbmRlZCwgdXBkYXRlIHRoZSB0cmFuc2xhdGlvbiB0byB0aGUgY29ycmVjdCBwbGFjZSAoYXBwZW5kaW5nIG5ldyBzbGlkZXMgZG8gbm90IGNoYW5nZSB0aGUgdHJhbnNsYXRpb24pLlxyXG4gICAqIExpbWl0IERPTSBncm93dGggb3IgdXBkYXRlIGxhc3Qgd2luZG93IHRyYW5zbGF0aW9uIGlmIGFwcGxpY2FibGUuXHJcbiAgICovXHJcbiAgYXBwZW5kT3JQcmVwZW5kTkVsZW1lbnRzKCkge1xyXG4gICAgaWYgKHRoaXMuZGlyZWN0aW9uID09PSAnbGVmdCcpIHtcclxuICAgICAgZm9yIChsZXQgaSA9IHRoaXMuYXJyYXlPZlNsaWRlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIGNvbnN0IGNsb25lZEVsZW1lbnQgPSB0aGlzLmFycmF5T2ZTbGlkZXNbaV0uY2xvbmVOb2RlKHRydWUpO1xyXG4gICAgICAgIHRoaXMuc2xpZGVzQ29udGFpbmVyLnByZXBlbmQoY2xvbmVkRWxlbWVudCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuYWNjdW11bGF0ZWRTbGlkZSArPSB0aGlzLnRvdGFsU2xpZGVzO1xyXG4gICAgICB0aGlzLnJlc2V0Vmlld0xlZnREaXJlY3Rpb24oKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5hcnJheU9mU2xpZGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgY29uc3QgY2xvbmVkRWxlbWVudCA9IHRoaXMuYXJyYXlPZlNsaWRlc1tpXS5jbG9uZU5vZGUodHJ1ZSk7XHJcbiAgICAgICAgdGhpcy5zbGlkZXNDb250YWluZXIuYXBwZW5kKGNsb25lZEVsZW1lbnQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMudG90YWxBbW91bnRPZlNsaWRlcyA+PSB0aGlzLk1BWF9ET01fU0laRSAqIHRoaXMudG90YWxTbGlkZXMpIHtcclxuICAgICAgLy8gTGltaXQgRE9NIGdyb3d0aCwgbWF4IFggdGltZXMgb3JpZ2luYWwgRE9NXHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdkb20gbGltaXQgcmVhY2hlZCcpO1xyXG4gICAgICB0aGlzLmxpbWl0RE9NR3Jvd3RoKCk7XHJcbiAgICAgIHRoaXMuRE9NTGltaXRSZWFjaGVkID0gdHJ1ZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMudG90YWxBbW91bnRPZlNsaWRlcyArPSB0aGlzLnRvdGFsU2xpZGVzO1xyXG4gICAgICB0aGlzLkRPTUxpbWl0UmVhY2hlZCA9IGZhbHNlO1xyXG4gICAgICB0aGlzLnVwZGF0ZUxhc3RXaW5kb3dUcmFuc2xhdGlvbigpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTGltaXQgRE9NIGdyb3d0aFxyXG4gICAqIFJlc2V0IHRoZSB2aWV3IGFjY29yZGluZ2x5LlxyXG4gICAqL1xyXG4gIGxpbWl0RE9NR3Jvd3RoKCkge1xyXG4gICAgY29uc3Qgc2xpZGVzID0gdGhpcy5jYXJvdXNlbC5zZWxlY3RTbGlkZXMoKTtcclxuXHJcbiAgICBpZiAodGhpcy5kaXJlY3Rpb24gPT09ICdyaWdodCcpIHtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnRvdGFsU2xpZGVzOyBpKyspIHtcclxuICAgICAgICBzbGlkZXNbaV0ucmVtb3ZlKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMucmVzZXRWaWV3UmlnaHREaXJlY3Rpb24oKTtcclxuICAgICAgdGhpcy5hY2N1bXVsYXRlZFNsaWRlIC09IHRoaXMudG90YWxTbGlkZXM7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBmb3IgKFxyXG4gICAgICAgIGxldCBpID0gc2xpZGVzLmxlbmd0aCAtIDE7XHJcbiAgICAgICAgaSA+IHNsaWRlcy5sZW5ndGggLSB0aGlzLnRvdGFsU2xpZGVzIC0gMTtcclxuICAgICAgICBpLS1cclxuICAgICAgKSB7XHJcbiAgICAgICAgc2xpZGVzW2ldLnJlbW92ZSgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXNldCB0aGUgdmlldyBpbiBhIG1vdmVtZW50IHRvIHRoZSBsZWZ0XHJcbiAgICogTmV3IHNsaWRlcyBhZGRlZCB0byB0aGUgbGVmdCwgc28gdGhlIHZpZXcgaGFzIHRvIGJlIHVwZGF0ZWQgYWNjb3JkaW5nbHkuXHJcbiAgICogSWYgdGhlIGNhcm91c2VsIGlzIG1vdmVkIHdpdGggdGhlIG1vdXNlIHwgdG91Y2ggZXZlbnQgKGRyYWdnaW5nIGlzIHRydWUpLCB0aGUgb2Zmc2V0IHNob3VsZCBiZSBlcXVhbCB0byBhIGZ1bGwgY2Fyb3VzZWwgd2lkdGguIE90aGVyd2lzZSAod2l0aCB0aGUgYnV0dG9ucyksIHRoZSBjb21wdXRlZCB0cmFuc2xhdGlvbiBzaG91bGQgYmUgdGFrZW4gaW50byBhY2NvdW50LlxyXG4gICAqIFNpZGUgY29tbWVudDogdGhlIHZpZXcgZG9lcyBub3QgaGF2ZSB0byBiZSB1cGRhdGVkIGZvciBzbGlkZXMgYWRkZWQgdG8gdGhlIHJpZ2h0LCBzaW5jZSByZWxhdGl2ZSBvcmRlciBkb2VzIG5vdCBjaGFuZ2UuXHJcbiAgICogZ2V0Qm91bmRpbmdDbGllbnRSZWN0IHRyaWdnZXJzIHJlZmxvdyBvZiB0aGUgZWxlbWVudC5cclxuICAgKi9cclxuICByZXNldFZpZXdMZWZ0RGlyZWN0aW9uKCkge1xyXG4gICAgY29uc3QgdHJhbnNsYXRpb24gPSBNYXRoLmFicyh0aGlzLnByZXZpb3VzVHJhbnNsYXRpb24pICsgdGhpcy5mdWxsV2lkdGhJbmY7XHJcbiAgICB0aGlzLnByZXZpb3VzVHJhbnNsYXRpb24gPSAtdHJhbnNsYXRpb247XHJcblxyXG4gICAgdGhpcy5zbGlkZXNDb250YWluZXIuc3R5bGUudHJhbnNpdGlvbiA9ICdub25lJztcclxuICAgIGNvbnN0IHRyYW5zZm9ybWF0aW9uID0gdGhpcy5kcmFnZ2luZygpID8gLXRoaXMuZnVsbFdpZHRoSW5mIDogLXRyYW5zbGF0aW9uO1xyXG4gICAgdGhpcy5hcHBseVRyYW5zbGF0aW9uKHRyYW5zZm9ybWF0aW9uKTtcclxuXHJcbiAgICB0aGlzLnNsaWRlc0NvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlc2V0IHRoZSB2aWV3IGluIGEgbW92ZW1lbnQgdG8gdGhlIHJpZ2h0XHJcbiAgICogRmlyc3Qgc2V0IG9mIHNsaWRlcyBoYXZlIGJlZW4gZGVsZXRlZCwgc28gdGhlIHRyYW5zbGF0aW9uIGhhcyB0byBiZSB1cGRhdGVkIGFjY29yZGluZ2x5LlxyXG4gICAqIGN1cnJlbnRUcmFuc2xhdGlvbiBpcyBhIG5lZ2F0aXZlIG51bWJlciBzbyBpdCB3aWxsIGJlIGRlY3JlYXNlZCBieSBhIHNldCBvZiBzbGlkZXMuXHJcbiAgICogZ2V0Qm91bmRpbmdDbGllbnRSZWN0IHRyaWdnZXJzIHJlZmxvdyBvZiB0aGUgZWxlbWVudC5cclxuICAgKi9cclxuICByZXNldFZpZXdSaWdodERpcmVjdGlvbigpIHtcclxuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gdGhpcy5jdXJyZW50VHJhbnNsYXRpb24oKSArIHRoaXMuZnVsbFdpZHRoSW5mO1xyXG5cclxuICAgIHRoaXMuc2xpZGVzQ29udGFpbmVyLnN0eWxlLnRyYW5zaXRpb24gPSAnbm9uZSc7XHJcbiAgICB0aGlzLmFwcGx5VHJhbnNsYXRpb24odHJhbnNsYXRpb24pO1xyXG4gICAgdGhpcy5wcmV2aW91c1RyYW5zbGF0aW9uID0gdHJhbnNsYXRpb24gLSB0aGlzLnBvc2l0aW9uQ2hhbmdlO1xyXG5cclxuICAgIHRoaXMuc2xpZGVzQ29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gIH1cclxuXHJcbiAgYWRkU2xpZGVzVG9UaGVMZWZ0KCkge1xyXG4gICAgdGhpcy5hcHBlbmRPclByZXBlbmRORWxlbWVudHMoKTtcclxuICB9XHJcblxyXG4gIGFkZFNsaWRlc1RvVGhlUmlnaHQoKSB7XHJcbiAgICB0aGlzLmFwcGVuZE9yUHJlcGVuZE5FbGVtZW50cygpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5jcmVhc2UgbGltaXQgb24gYmFzaXMgb2YgcHJldmlvdXMgY29tcHV0ZWQgbGltaXRzIChtb3ZlbWVudCB0byB0aGUgcmlnaHQpXHJcbiAgICogU2NoZW1hOiB8fCBwcmV2aW91cyB8IGN1cnJlbnQgfHwgbmV4dFxyXG4gICAqL1xyXG4gIG92ZXJyaWRlIGluY3JlYXNlTGltaXRzKCkge1xyXG4gICAgdGhpcy5uZXh0TGltaXQgKz0gTWF0aC5mbG9vcih0aGlzLmNhcm91c2VsLnNsaWRlV2lkdGhXaXRoR2FwKTtcclxuICAgIHRoaXMucHJldkxpbWl0ID0gTWF0aC5mbG9vcihcclxuICAgICAgdGhpcy5uZXh0TGltaXQgLSB0aGlzLmNhcm91c2VsLnNsaWRlV2lkdGhXaXRoR2FwICogMlxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFByZXZpb3VzIGJ1dHRvbiBuYXZpZ2F0aW9uXHJcbiAgICovXHJcbiAgcHJldihzbGlkZXMgPSB0aGlzLnNsaWRlVG9TY3JvbGwpIHtcclxuICAgIHRoaXMuZGlyZWN0aW9uID0gJ2xlZnQnO1xyXG5cclxuICAgIHRoaXMuaGFuZGxlQnRuSW5maW5pdGUoLXNsaWRlcyk7XHJcbiAgICB0aGlzLmNoYW5nZVNsaWRlTnVtYmVyKC1zbGlkZXMpO1xyXG4gICAgdGhpcy5jaGFuZ2VQcmV2QW5kTmV4dExpbWl0cyh0aGlzLmFjY3VtdWxhdGVkU2xpZGUpO1xyXG4gICAgdGhpcy5jb21wdXRlVHJhbnNmb3JtYXRpb24odGhpcy5hY2N1bXVsYXRlZFNsaWRlKTtcclxuICAgIHRoaXMucmVsYXVuY2hBdXRvUGxheSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTmV4dCBidXR0b24gbmF2aWdhdGlvblxyXG4gICAqL1xyXG4gIG5leHQoc2xpZGVzID0gdGhpcy5zbGlkZVRvU2Nyb2xsKSB7XHJcbiAgICB0aGlzLmRpcmVjdGlvbiA9ICdyaWdodCc7XHJcblxyXG4gICAgdGhpcy5oYW5kbGVCdG5JbmZpbml0ZShzbGlkZXMpO1xyXG4gICAgdGhpcy5jaGFuZ2VTbGlkZU51bWJlcihzbGlkZXMpO1xyXG4gICAgdGhpcy5jaGFuZ2VQcmV2QW5kTmV4dExpbWl0cyh0aGlzLmFjY3VtdWxhdGVkU2xpZGUpO1xyXG4gICAgdGhpcy5jb21wdXRlVHJhbnNmb3JtYXRpb24odGhpcy5hY2N1bXVsYXRlZFNsaWRlKTtcclxuICAgIHRoaXMucmVsYXVuY2hBdXRvUGxheSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQnV0dG9ucyBuYXZpZ2F0aW9uIGluIGluZmluaXRlIG1vZGVcclxuICAgKiBDcmVhdGUgbmV3IHNsaWRlIGlmIGxpbWl0cyByZWFjaGVkIChzdGFydCBvciBlbmQpLiBVcGRhdGUgc2xpZGUsIGxpbWl0cyBhbmQgYXBwbHkgdHJhbnNmb3JtYXRpb24gYWNjb3JkaW5nbHkuXHJcbiAgICovXHJcbiAgaGFuZGxlQnRuSW5maW5pdGUoc3RlcDogbnVtYmVyKSB7XHJcbiAgICBsZXQgY2FyZE9mZnNldCA9IDA7XHJcbiAgICBjb25zdCBnb2luZ1RvID0gdGhpcy5hY2N1bXVsYXRlZFNsaWRlICsgc3RlcDtcclxuXHJcbiAgICAvLyB0aGVyZSBpcyAocG9zc2libHkpIGEgY2FyZCBvZmZzZXQgaWYgbm90IHJlc3BvbnNpdmVcclxuICAgIGlmICghdGhpcy5yZXNwb25zaXZlKSBjYXJkT2Zmc2V0ID0gMTtcclxuXHJcbiAgICBpZiAoZ29pbmdUbyA8IDApIHtcclxuICAgICAgdGhpcy5hZGRTbGlkZXNUb1RoZUxlZnQoKTtcclxuICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgIGdvaW5nVG8gKyB0aGlzLmNhcm91c2VsLnNsaWRlVG9TaG93ICsgY2FyZE9mZnNldCA+XHJcbiAgICAgIHRoaXMudG90YWxBbW91bnRPZlNsaWRlc1xyXG4gICAgKSB7XHJcbiAgICAgIHRoaXMuYWRkU2xpZGVzVG9UaGVSaWdodCgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTmF2aWdhdGlvbiB3aXRoIGJ1bGxldCBwb2ludHNcclxuICAgKiBVcGRhdGUgdmFsdWVzIGFjY29yZGluZ2x5LlxyXG4gICAqL1xyXG4gIGdvVG8oYnVsbGV0OiBudW1iZXIpIHtcclxuICAgIGNvbnN0IHNsaWRlSGFzQ2hhbmdlZCA9IHRoaXMuY3VycmVudFNsaWRlKCkgIT09IGJ1bGxldDtcclxuICAgIHRoaXMuZGlyZWN0aW9uID0gdGhpcy5jdXJyZW50U2xpZGUoKSA8IGJ1bGxldCA/ICdyaWdodCcgOiAnbGVmdCc7XHJcblxyXG4gICAgdGhpcy5jdXJyZW50U2xpZGUuc2V0KGJ1bGxldCk7XHJcbiAgICB0aGlzLmZpcmVTbGlkZUNoYW5nZUV2ZW50KHNsaWRlSGFzQ2hhbmdlZCwgdGhpcy5jdXJyZW50U2xpZGUoKSk7XHJcblxyXG4gICAgdGhpcy5yZWxhdW5jaEF1dG9QbGF5KCk7XHJcbiAgICB0aGlzLm5hdkluZmluaXRlQnVsbGV0cyhidWxsZXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQnVsbGV0cyBuYXZpZ2F0aW9uXHJcbiAgICogQ3JlYXRlIG5ldyBzbGlkZXMgaWYgZXhjZWVkaW5nIGVuZCBvZiBjYXJvdXNlbC5cclxuICAgKi9cclxuICBuYXZJbmZpbml0ZUJ1bGxldHMoYnVsbGV0OiBudW1iZXIpIHtcclxuICAgIGxldCBjYXJkT2Zmc2V0ID0gMDtcclxuICAgIGNvbnN0IHBvc2l0aW9uT2ZDdXJyZW50U2xpZGUgPSB0aGlzLmFjY3VtdWxhdGVkU2xpZGUgJSB0aGlzLnRvdGFsU2xpZGVzO1xyXG4gICAgY29uc3QgZGlmZmVyZW5jZSA9IGJ1bGxldCAtIHBvc2l0aW9uT2ZDdXJyZW50U2xpZGU7XHJcbiAgICB0aGlzLmFjY3VtdWxhdGVkU2xpZGUgKz0gZGlmZmVyZW5jZTtcclxuXHJcbiAgICAvLyB0aGVyZSBpcyAocG9zc2libHkpIGEgY2FyZCBvZmZzZXQgaWYgbm90IHJlc3BvbnNpdmVcclxuICAgIGlmICghdGhpcy5yZXNwb25zaXZlKSBjYXJkT2Zmc2V0ID0gMTtcclxuXHJcbiAgICBpZiAoXHJcbiAgICAgIHRoaXMuYWNjdW11bGF0ZWRTbGlkZSArIHRoaXMuY2Fyb3VzZWwuc2xpZGVUb1Nob3cgKyBjYXJkT2Zmc2V0ID5cclxuICAgICAgdGhpcy50b3RhbEFtb3VudE9mU2xpZGVzXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5hZGRTbGlkZXNUb1RoZVJpZ2h0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5jb21wdXRlVHJhbnNmb3JtYXRpb24odGhpcy5hY2N1bXVsYXRlZFNsaWRlKTtcclxuICAgIHRoaXMuY2hhbmdlUHJldkFuZE5leHRMaW1pdHModGhpcy5hY2N1bXVsYXRlZFNsaWRlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEV4Y2VwdGlvbjogaWYgb25seSBvbmUgd2luZG93IChudW1iZXJEb3RzID09PSAxKSwgdXBkYXRlIHRoZSBhY2N1bXVsYXRlZFNsaWRlIHRvIGxldCB0aGUgdHJhbnNmb3JtYXRpb24gb2NjdXJzLCBidXQgY3VycmVudFNsaWRlIHNob3VsZCBzdGF5IGF0IDAuXHJcbiAgICovXHJcbiAgY2hhbmdlU2xpZGVOdW1iZXIoc3RlcDogbnVtYmVyKSB7XHJcbiAgICBjb25zdCBzbGlkZU51bWJlckJlZm9yZUNoYW5nZTogbnVtYmVyID0gdGhpcy5jdXJyZW50U2xpZGUoKTtcclxuICAgIHRoaXMuaW5maW5pdGVDaGFuZ2VTbGlkZU51bWJlcihzdGVwKTtcclxuXHJcbiAgICBpZiAodGhpcy5jYXJvdXNlbC5udW1iZXJEb3RzKCkgPT09IDEpIHtcclxuICAgICAgdGhpcy5jdXJyZW50U2xpZGUuc2V0KDApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGN1cnJlbnQ6IG51bWJlciA9XHJcbiAgICAgIHRoaXMuY2Fyb3VzZWwubnVtYmVyRG90cygpID4gMVxyXG4gICAgICAgID8gdGhpcy5jdXJyZW50U2xpZGUoKVxyXG4gICAgICAgIDogdGhpcy5hY2N1bXVsYXRlZFNsaWRlO1xyXG5cclxuICAgIGNvbnN0IHNsaWRlSGFzQ2hhbmdlZDogYm9vbGVhbiA9XHJcbiAgICAgIHNsaWRlTnVtYmVyQmVmb3JlQ2hhbmdlICE9PSB0aGlzLmN1cnJlbnRTbGlkZSgpO1xyXG4gICAgdGhpcy5maXJlU2xpZGVDaGFuZ2VFdmVudChzbGlkZUhhc0NoYW5nZWQsIGN1cnJlbnQpO1xyXG4gIH1cclxuXHJcbiAgaW5maW5pdGVDaGFuZ2VTbGlkZU51bWJlcihzdGVwOiBudW1iZXIpIHtcclxuICAgIHRoaXMuYWNjdW11bGF0ZWRTbGlkZSArPSBzdGVwO1xyXG4gICAgdGhpcy5jdXJyZW50U2xpZGUudXBkYXRlKChzbGlkZSkgPT4gc2xpZGUgKyBzdGVwKTtcclxuXHJcbiAgICBjb25zdCBsYXN0U2xpZGUgPSB0aGlzLnRvdGFsU2xpZGVzIC0gMTtcclxuICAgIGlmICh0aGlzLmN1cnJlbnRTbGlkZSgpID4gbGFzdFNsaWRlKSB7XHJcbiAgICAgIHRoaXMuY3VycmVudFNsaWRlLnVwZGF0ZSgoc2xpZGUpID0+IHNsaWRlICUgdGhpcy50b3RhbFNsaWRlcyk7XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMuY3VycmVudFNsaWRlKCkgPCAwKSB7XHJcbiAgICAgIHRoaXMuY3VycmVudFNsaWRlLnVwZGF0ZSgoc2xpZGUpID0+IHNsaWRlICsgdGhpcy50b3RhbFNsaWRlcyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb21wdXRlIHRyYW5zZm9ybWF0aW9uIHRoYXQgd2lsbCBiZSBhcHBsaWVkIG9uIGJhc2lzIG9mIHRoZSBwcm92aWRlZCBzbGlkZSBudW1iZXJcclxuICAgKi9cclxuICBjb21wdXRlVHJhbnNmb3JtYXRpb24oc2xpZGU6IG51bWJlcikge1xyXG4gICAgY29uc3QgdHJhbnNmb3JtYXRpb24gPSBzbGlkZSAqIHRoaXMuY2Fyb3VzZWwuc2xpZGVXaWR0aFdpdGhHYXA7XHJcblxyXG4gICAgdGhpcy5hcHBseVRyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uKTtcclxuICB9XHJcbn1cclxuIl19