UNPKG

@kushki/ng-suka

Version:

<p align="center"> <h1 align="center">Suka Components Angular</h1> <p align="center"> An Angular implementation of the Suka Design System </p> </p>

524 lines (522 loc) 39.9 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // tslint:disable: variable-name import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewEncapsulation, HostBinding, } from '@angular/core'; import buildPaginationArray from './pagination-utils'; import { Subject } from 'rxjs'; /** * The default page size if there is no page size and there are no provided page size options. * @type {?} */ const DEFAULT_PAGE_SIZE = 50; /** * Change event object that is emitted when the user selects a * different page size or navigates to another page. */ export class PageEvent { } if (false) { /** * The current page index. * @type {?} */ PageEvent.prototype.pageIndex; /** * Index of the page that was selected previously. * @type {?} */ PageEvent.prototype.previousPageIndex; /** * The current page size * @type {?} */ PageEvent.prototype.pageSize; /** * The current total number of items being paged * @type {?} */ PageEvent.prototype.length; } /** * Component to provide navigation between paged inforsukaion. Displays the size of the current * page, user-selectable options to change that size, what items are being shown, and * navigational button to go to the previous or next page. */ export class Pagination { /** * @param {?} _changeDetectorRef */ constructor(_changeDetectorRef) { this._changeDetectorRef = _changeDetectorRef; this.initialized = new Subject(); this.disabled = false; this.baseClass = true; this._pageIndex = 0; this._length = 0; this._pageSizeOptions = []; this._hidePageSize = false; this._showFirstLastButtons = false; /** * Event emitted when the pagination changes the page size or page index. */ this.page = new EventEmitter(); /** * Displayed pages array */ this._pagesArray = []; /** * Calculate the page range */ this.getRangeLabel = (/** * @param {?} page * @param {?} pageSize * @param {?} length * @return {?} */ (page, pageSize, length) => { if (length === 0 || pageSize === 0) { return `0 de ${length}`; } length = Math.max(length, 0); /** @type {?} */ const startIndex = page * pageSize; // If the start index exceeds the list length, do not try and fix the end index to the end. /** @type {?} */ const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize; return `${startIndex + 1}${endIndex} de ${length}`; }); } /** * The zero-based page index of the displayed list of items. Defaulted to 0. * @return {?} */ get pageIndex() { return this._pageIndex; } /** * @param {?} value * @return {?} */ set pageIndex(value) { this._pageIndex = Math.max(coerceNumberProperty(value), 0); this._changeDetectorRef.markForCheck(); } /** * The length of the total number of items that are being paginated. Defaulted to 0. * @return {?} */ get length() { return this._length; } /** * @param {?} value * @return {?} */ set length(value) { this._length = coerceNumberProperty(value); this._changeDetectorRef.markForCheck(); this._updateDisplayedPagesArray(); } /** * Number of items to display on a page. By default set to 20. * @return {?} */ get pageSize() { return this._pageSize; } /** * @param {?} value * @return {?} */ set pageSize(value) { this._pageSize = Math.max(coerceNumberProperty(value), 0); this._updateDisplayedPageSizeOptions(); this._updateDisplayedPagesArray(); } /** * The set of provided page size options to display to the user. * @return {?} */ get pageSizeOptions() { return this._pageSizeOptions; } /** * @param {?} value * @return {?} */ set pageSizeOptions(value) { this._pageSizeOptions = (value || []).map((/** * @param {?} p * @return {?} */ p => coerceNumberProperty(p))); this._updateDisplayedPageSizeOptions(); } /** * Whether to hide the page size selection UI from the user. * @return {?} */ get hidePageSize() { return this._hidePageSize; } /** * @param {?} value * @return {?} */ set hidePageSize(value) { this._hidePageSize = coerceBooleanProperty(value); } /** * Whether to show the first/last buttons UI to the user. * @return {?} */ get showFirstLastButtons() { return this._showFirstLastButtons; } /** * @param {?} value * @return {?} */ set showFirstLastButtons(value) { this._showFirstLastButtons = coerceBooleanProperty(value); } /** * @return {?} */ ngOnInit() { this._initialized = true; this.initialized.next(true); this._updateDisplayedPageSizeOptions(); } /** * Advances to the next page if it exists. * @return {?} */ nextPage() { if (!this.hasNextPage()) { return; } /** @type {?} */ const previousPageIndex = this.pageIndex; this.pageIndex++; this._updateDisplayedPagesArray(); this._emitPageEvent(previousPageIndex); } /** * Move back to the previous page if it exists. * @return {?} */ previousPage() { if (!this.hasPreviousPage()) { return; } /** @type {?} */ const previousPageIndex = this.pageIndex; this.pageIndex--; this._updateDisplayedPagesArray(); this._emitPageEvent(previousPageIndex); } /** * Move to the first page if not already there. * @return {?} */ firstPage() { // hasPreviousPage being false implies at the start if (!this.hasPreviousPage()) { return; } /** @type {?} */ const previousPageIndex = this.pageIndex; this.pageIndex = 0; this._updateDisplayedPagesArray(); this._emitPageEvent(previousPageIndex); } /** * Move to the last page if not already there. * @return {?} */ lastPage() { // hasNextPage being false implies at the end if (!this.hasNextPage()) { return; } /** @type {?} */ const previousPageIndex = this.pageIndex; this.pageIndex = this.getNumberOfPages() - 1; this._updateDisplayedPagesArray(); this._emitPageEvent(previousPageIndex); } /** * @param {?} page * @return {?} */ goToPage(page) { /** @type {?} */ const previousPageIndex = this.pageIndex; this.pageIndex = page - 1; this._updateDisplayedPagesArray(); this._emitPageEvent(previousPageIndex); } /** * Whether there is a previous page. * @return {?} */ hasPreviousPage() { return this.pageIndex >= 1 && this.pageSize !== 0; } /** * Whether there is a next page. * @return {?} */ hasNextPage() { /** @type {?} */ const maxPageIndex = this.getNumberOfPages() - 1; return this.pageIndex < maxPageIndex && this.pageSize !== 0; } /** * Calculate the number of pages * @return {?} */ getNumberOfPages() { if (!this.pageSize) { return 0; } return Math.ceil(this.length / this.pageSize); } /** * Changes the page size so that the first item displayed on the page will still be * displayed using the new page size. * * For example, if the page size is 10 and on the second page (items indexed 10-19) then * switching so that the page size is 5 will set the third page as the current page so * that the 10th item will still be displayed. * @param {?} pageSize * @return {?} */ _changePageSize(pageSize) { // Current page needs to be updated to reflect the new page size. Navigate to the page // containing the previous page's first item. /** @type {?} */ const startIndex = this.pageIndex * this.pageSize; /** @type {?} */ const previousPageIndex = this.pageIndex; this.pageIndex = Math.floor(startIndex / pageSize) || 0; this.pageSize = pageSize; this._emitPageEvent(previousPageIndex); } /** * Checks whether the buttons for going forwards should be disabled. * @return {?} */ _nextButtonsDisabled() { return this.disabled || !this.hasNextPage(); } /** * Checks whether the buttons for going backwards should be disabled. * @return {?} */ _previousButtonsDisabled() { return this.disabled || !this.hasPreviousPage(); } /** * Updates the list of page size options to display to the user. Includes making sure that * the page size is an option and that the list is sorted. * @private * @return {?} */ _updateDisplayedPageSizeOptions() { if (!this._initialized) { return; } // If no page size is provided, use the first page size option or the default page size. if (!this.pageSize) { this._pageSize = this.pageSizeOptions.length !== 0 ? this.pageSizeOptions[0] : DEFAULT_PAGE_SIZE; } this._displayedPageSizeOptions = this.pageSizeOptions.slice(); if (this._displayedPageSizeOptions.indexOf(this.pageSize) === -1) { this._displayedPageSizeOptions.push(this.pageSize); } // Sort the numbers using a number-specific sort function. this._displayedPageSizeOptions.sort((/** * @param {?} a * @param {?} b * @return {?} */ (a, b) => a - b)); this._changeDetectorRef.markForCheck(); } /** * @private * @return {?} */ _updateDisplayedPagesArray() { this._pagesArray = buildPaginationArray(this.getNumberOfPages(), this.pageIndex + 1, 3); } /** * Emits an event notifying that a change of the pagination's properties has been triggered. * @private * @param {?} previousPageIndex * @return {?} */ _emitPageEvent(previousPageIndex) { this.page.emit({ previousPageIndex, pageIndex: this.pageIndex, pageSize: this.pageSize, length: this.length }); } } Pagination.decorators = [ { type: Component, args: [{ selector: 'suka-pagination', exportAs: 'sukaPagination', template: ` <div class="suka-pagination-outer-container"> <div class="suka-pagination-container"> <div class="suka-pagination-results"> Mostrando <span class="suka-pagination-result">{{getRangeLabel(pageIndex, pageSize, length)}}</span> </div> <div class="suka-pagination-actions"> <button type="button" class="suka-pagination-navigation-first" (click)="firstPage()" [disabled]="_previousButtonsDisabled()" *ngIf="showFirstLastButtons" sukaButton="plain" size="sm" > <suka-icon icon="chevrons-left" class="suka-pagination-icon"></suka-icon> </button> <button type="button" class="suka-pagination-navigation-previous" (click)="previousPage()" [disabled]="_previousButtonsDisabled()" sukaButton="plain" size="sm" > <suka-icon icon="chevron-left" class="suka-pagination-icon"></suka-icon> Anterior </button> <button *ngFor="let pageNumber of _pagesArray" type="button" class="suka-pagination-navigation-page" (click)="goToPage(pageNumber)" [disabled]="pageNumber === '...'" sukaButton="plain" size="sm" [ngClass]="{ 'suka-pagination-navigation-page--selected': pageNumber === pageIndex + 1 }" > {{pageNumber}} </button> <button type="button" class="suka-pagination-navigation-next" (click)="nextPage()" [disabled]="_nextButtonsDisabled()" sukaButton="plain" size="sm" > Siguiente <suka-icon icon="chevron-right" class="suka-pagination-icon"></suka-icon> </button> <button type="button" class="suka-pagination-navigation-last" (click)="lastPage()" [disabled]="_nextButtonsDisabled()" *ngIf="showFirstLastButtons" sukaButton="plain" size="sm" > <suka-icon icon="chevrons-right" class="suka-pagination-icon"></suka-icon> </button> </div> </div> </div> `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None }] } ]; /** @nocollapse */ Pagination.ctorParameters = () => [ { type: ChangeDetectorRef } ]; Pagination.propDecorators = { disabled: [{ type: Input }], baseClass: [{ type: HostBinding, args: ['class.suka-pagination',] }], pageIndex: [{ type: Input }], length: [{ type: Input }], pageSize: [{ type: Input }], pageSizeOptions: [{ type: Input }], hidePageSize: [{ type: Input }], showFirstLastButtons: [{ type: Input }], page: [{ type: Output }] }; if (false) { /** * @type {?} * @private */ Pagination.prototype._initialized; /** @type {?} */ Pagination.prototype.initialized; /** @type {?} */ Pagination.prototype.disabled; /** @type {?} */ Pagination.prototype.baseClass; /** * @type {?} * @private */ Pagination.prototype._pageIndex; /** * @type {?} * @private */ Pagination.prototype._length; /** * @type {?} * @private */ Pagination.prototype._pageSize; /** * @type {?} * @private */ Pagination.prototype._pageSizeOptions; /** * @type {?} * @private */ Pagination.prototype._hidePageSize; /** * @type {?} * @private */ Pagination.prototype._showFirstLastButtons; /** * Event emitted when the pagination changes the page size or page index. * @type {?} */ Pagination.prototype.page; /** * Displayed set of page size options. Will be sorted and include current page size. * @type {?} */ Pagination.prototype._displayedPageSizeOptions; /** * Displayed pages array * @type {?} */ Pagination.prototype._pagesArray; /** * Calculate the page range * @type {?} */ Pagination.prototype.getRangeLabel; /** * @type {?} * @private */ Pagination.prototype._changeDetectorRef; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aa3VzaGtpL25nLXN1a2EvIiwic291cmNlcyI6WyJsaWIvcGFnaW5hdGlvbi9wYWdpbmF0aW9uLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BGLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixpQkFBaUIsRUFDakIsV0FBVyxHQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sb0JBQW9CLE1BQU0sb0JBQW9CLENBQUM7QUFDdEQsT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7TUFHckMsaUJBQWlCLEdBQUcsRUFBRTs7Ozs7QUFNNUIsTUFBTSxPQUFPLFNBQVM7Q0FjckI7Ozs7OztJQVpDLDhCQUFrQjs7Ozs7SUFLbEIsc0NBQTBCOzs7OztJQUcxQiw2QkFBaUI7Ozs7O0lBR2pCLDJCQUFlOzs7Ozs7O0FBbUZqQixNQUFNLE9BQU8sVUFBVTs7OztJQXdFckIsWUFBb0Isa0JBQXFDO1FBQXJDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7UUF0RXpELGdCQUFXLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUVuQixhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ1ksY0FBUyxHQUFHLElBQUksQ0FBQztRQVUvQyxlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBVWYsWUFBTyxHQUFHLENBQUMsQ0FBQztRQW1CWixxQkFBZ0IsR0FBYSxFQUFFLENBQUM7UUFRaEMsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFTdEIsMEJBQXFCLEdBQUcsS0FBSyxDQUFDOzs7O1FBR25CLFNBQUksR0FBNEIsSUFBSSxZQUFZLEVBQWEsQ0FBQzs7OztRQU1qRixnQkFB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QThCOzs7OztJQVM5QiwyQ0FBc0M7Ozs7O0lBR3RDLDBCQUFpRjs7Ozs7SUFHakYsK0NBQW9DOzs7OztJQUdwQyxpQ0FBaUI7Ozs7O0lBaUZqQixtQ0FhQzs7Ozs7SUE1Rlcsd0NBQTZDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdHNsaW50OmRpc2FibGU6IHZhcmlhYmxlLW5hbWVcblxuaW1wb3J0IHsgY29lcmNlTnVtYmVyUHJvcGVydHksIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxuICBIb3N0QmluZGluZyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgYnVpbGRQYWdpbmF0aW9uQXJyYXkgZnJvbSAnLi9wYWdpbmF0aW9uLXV0aWxzJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuLyoqIFRoZSBkZWZhdWx0IHBhZ2Ugc2l6ZSBpZiB0aGVyZSBpcyBubyBwYWdlIHNpemUgYW5kIHRoZXJlIGFyZSBubyBwcm92aWRlZCBwYWdlIHNpemUgb3B0aW9ucy4gKi9cbmNvbnN0IERFRkFVTFRfUEFHRV9TSVpFID0gNTA7XG5cbi8qKlxuICogQ2hhbmdlIGV2ZW50IG9iamVjdCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiB0aGUgdXNlciBzZWxlY3RzIGFcbiAqIGRpZmZlcmVudCBwYWdlIHNpemUgb3IgbmF2aWdhdGVzIHRvIGFub3RoZXIgcGFnZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFBhZ2VFdmVudCB7XG4gIC8qKiBUaGUgY3VycmVudCBwYWdlIGluZGV4LiAqL1xuICBwYWdlSW5kZXg6IG51bWJlcjtcblxuICAvKipcbiAgICogSW5kZXggb2YgdGhlIHBhZ2UgdGhhdCB3YXMgc2VsZWN0ZWQgcHJldmlvdXNseS5cbiAgICovXG4gIHByZXZpb3VzUGFnZUluZGV4OiBudW1iZXI7XG5cbiAgLyoqIFRoZSBjdXJyZW50IHBhZ2Ugc2l6ZSAqL1xuICBwYWdlU2l6ZTogbnVtYmVyO1xuXG4gIC8qKiBUaGUgY3VycmVudCB0b3RhbCBudW1iZXIgb2YgaXRlbXMgYmVpbmcgcGFnZWQgKi9cbiAgbGVuZ3RoOiBudW1iZXI7XG59XG5cblxuLyoqXG4gKiBDb21wb25lbnQgdG8gcHJvdmlkZSBuYXZpZ2F0aW9uIGJldHdlZW4gcGFnZWQgaW5mb3JzdWthaW9uLiBEaXNwbGF5cyB0aGUgc2l6ZSBvZiB0aGUgY3VycmVudFxuICogcGFnZSwgdXNlci1zZWxlY3RhYmxlIG9wdGlvbnMgdG8gY2hhbmdlIHRoYXQgc2l6ZSwgd2hhdCBpdGVtcyBhcmUgYmVpbmcgc2hvd24sIGFuZFxuICogbmF2aWdhdGlvbmFsIGJ1dHRvbiB0byBnbyB0byB0aGUgcHJldmlvdXMgb3IgbmV4dCBwYWdlLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdWthLXBhZ2luYXRpb24nLFxuICBleHBvcnRBczogJ3N1a2FQYWdpbmF0aW9uJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwic3VrYS1wYWdpbmF0aW9uLW91dGVyLWNvbnRhaW5lclwiPlxuICAgICAgPGRpdiBjbGFzcz1cInN1a2EtcGFnaW5hdGlvbi1jb250YWluZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInN1a2EtcGFnaW5hdGlvbi1yZXN1bHRzXCI+XG4gICAgICAgICAgTW9zdHJhbmRvIDxzcGFuIGNsYXNzPVwic3VrYS1wYWdpbmF0aW9uLXJlc3VsdFwiPnt7Z2V0UmFuZ2VMYWJlbChwYWdlSW5kZXgsIHBhZ2VTaXplLCBsZW5ndGgpfX08L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdWthLXBhZ2luYXRpb24tYWN0aW9uc1wiPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInN1a2EtcGFnaW5hdGlvbi1uYXZpZ2F0aW9uLWZpcnN0XCJcbiAgICAgICAgICAgIChjbGljayk9XCJmaXJzdFBhZ2UoKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiX3ByZXZpb3VzQnV0dG9uc0Rpc2FibGVkKClcIlxuICAgICAgICAgICAgKm5nSWY9XCJzaG93Rmlyc3RMYXN0QnV0dG9uc1wiXG4gICAgICAgICAgICBzdWthQnV0dG9uPVwicGxhaW5cIlxuICAgICAgICAgICAgc2l6ZT1cInNtXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8c3VrYS1pY29uIGljb249XCJjaGV2cm9ucy1sZWZ0XCIgY2xhc3M9XCJzdWthLXBhZ2luYXRpb24taWNvblwiPjwvc3VrYS1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInN1a2EtcGFnaW5hdGlvbi1uYXZpZ2F0aW9uLXByZXZpb3VzXCJcbiAgICAgICAgICAgIChjbGljayk9XCJwcmV2aW91c1BhZ2UoKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiX3ByZXZpb3VzQnV0dG9uc0Rpc2FibGVkKClcIlxuICAgICAgICAgICAgc3VrYUJ1dHRvbj1cInBsYWluXCJcbiAgICAgICAgICAgIHNpemU9XCJzbVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHN1a2EtaWNvbiBpY29uPVwiY2hldnJvbi1sZWZ0XCIgY2xhc3M9XCJzdWthLXBhZ2luYXRpb24taWNvblwiPjwvc3VrYS1pY29uPlxuICAgICAgICAgICAgQW50ZXJpb3JcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAqbmdGb3I9XCJsZXQgcGFnZU51bWJlciBvZiBfcGFnZXNBcnJheVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwic3VrYS1wYWdpbmF0aW9uLW5hdmlnYXRpb24tcGFnZVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZ29Ub1BhZ2UocGFnZU51bWJlcilcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cInBhZ2VOdW1iZXIgPT09ICcuLi4nXCJcbiAgICAgICAgICAgIHN1a2FCdXR0b249XCJwbGFpblwiXG4gICAgICAgICAgICBzaXplPVwic21cIlxuICAgICAgICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICAgICAgICAnc3VrYS1wYWdpbmF0aW9uLW5hdmlnYXRpb24tcGFnZS0tc2VsZWN0ZWQnOiBwYWdlTnVtYmVyID09PSBwYWdlSW5kZXggKyAxXG4gICAgICAgICAgICB9XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7e3BhZ2VOdW1iZXJ9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJzdWthLXBhZ2luYXRpb24tbmF2aWdhdGlvbi1uZXh0XCJcbiAgICAgICAgICAgIChjbGljayk9XCJuZXh0UGFnZSgpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJfbmV4dEJ1dHRvbnNEaXNhYmxlZCgpXCJcbiAgICAgICAgICAgIHN1a2FCdXR0b249XCJwbGFpblwiXG4gICAgICAgICAgICBzaXplPVwic21cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIFNpZ3VpZW50ZVxuICAgICAgICAgICAgPHN1a2EtaWNvbiBpY29uPVwiY2hldnJvbi1yaWdodFwiIGNsYXNzPVwic3VrYS1wYWdpbmF0aW9uLWljb25cIj48L3N1a2EtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJzdWthLXBhZ2luYXRpb24tbmF2aWdhdGlvbi1sYXN0XCJcbiAgICAgICAgICAgIChjbGljayk9XCJsYXN0UGFnZSgpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJfbmV4dEJ1dHRvbnNEaXNhYmxlZCgpXCJcbiAgICAgICAgICAgICpuZ0lmPVwic2hvd0ZpcnN0TGFzdEJ1dHRvbnNcIlxuICAgICAgICAgICAgc3VrYUJ1dHRvbj1cInBsYWluXCJcbiAgICAgICAgICAgIHNpemU9XCJzbVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHN1a2EtaWNvbiBpY29uPVwiY2hldnJvbnMtcmlnaHRcIiBjbGFzcz1cInN1a2EtcGFnaW5hdGlvbi1pY29uXCI+PC9zdWthLWljb24+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgYCxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG59KVxuZXhwb3J0IGNsYXNzIFBhZ2luYXRpb24gaW1wbGVtZW50cyBPbkluaXQge1xuICBwcml2YXRlIF9pbml0aWFsaXplZDogYm9vbGVhbjtcbiAgaW5pdGlhbGl6ZWQgPSBuZXcgU3ViamVjdCgpO1xuXG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG4gIEBIb3N0QmluZGluZygnY2xhc3Muc3VrYS1wYWdpbmF0aW9uJykgYmFzZUNsYXNzID0gdHJ1ZTtcblxuICAvKiogVGhlIHplcm8tYmFzZWQgcGFnZSBpbmRleCBvZiB0aGUgZGlzcGxheWVkIGxpc3Qgb2YgaXRlbXMuIERlZmF1bHRlZCB0byAwLiAqL1xuICBASW5wdXQoKVxuICBnZXQgcGFnZUluZGV4KCk6IG51bWJlciB7IHJldHVybiB0aGlzLl9wYWdlSW5kZXg7IH1cbiAgc2V0IHBhZ2VJbmRleCh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fcGFnZUluZGV4ID0gTWF0aC5tYXgoY29lcmNlTnVtYmVyUHJvcGVydHkodmFsdWUpLCAwKTtcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHByaXZhdGUgX3BhZ2VJbmRleCA9IDA7XG5cbiAgLyoqIFRoZSBsZW5ndGggb2YgdGhlIHRvdGFsIG51bWJlciBvZiBpdGVtcyB0aGF0IGFyZSBiZWluZyBwYWdpbmF0ZWQuIERlZmF1bHRlZCB0byAwLiAqL1xuICBASW5wdXQoKVxuICBnZXQgbGVuZ3RoKCk6IG51bWJlciB7IHJldHVybiB0aGlzLl9sZW5ndGg7IH1cbiAgc2V0IGxlbmd0aCh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fbGVuZ3RoID0gY29lcmNlTnVtYmVyUHJvcGVydHkodmFsdWUpO1xuICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VzQXJyYXkoKTtcbiAgfVxuICBwcml2YXRlIF9sZW5ndGggPSAwO1xuXG4gIC8qKiBOdW1iZXIgb2YgaXRlbXMgdG8gZGlzcGxheSBvbiBhIHBhZ2UuIEJ5IGRlZmF1bHQgc2V0IHRvIDIwLiAqL1xuICBASW5wdXQoKVxuICBnZXQgcGFnZVNpemUoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuX3BhZ2VTaXplOyB9XG4gIHNldCBwYWdlU2l6ZSh2YWx1ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fcGFnZVNpemUgPSBNYXRoLm1heChjb2VyY2VOdW1iZXJQcm9wZXJ0eSh2YWx1ZSksIDApO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VTaXplT3B0aW9ucygpO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VzQXJyYXkoKTtcbiAgfVxuICBwcml2YXRlIF9wYWdlU2l6ZTogbnVtYmVyO1xuXG4gIC8qKiBUaGUgc2V0IG9mIHByb3ZpZGVkIHBhZ2Ugc2l6ZSBvcHRpb25zIHRvIGRpc3BsYXkgdG8gdGhlIHVzZXIuICovXG4gIEBJbnB1dCgpXG4gIGdldCBwYWdlU2l6ZU9wdGlvbnMoKTogbnVtYmVyW10geyByZXR1cm4gdGhpcy5fcGFnZVNpemVPcHRpb25zOyB9XG4gIHNldCBwYWdlU2l6ZU9wdGlvbnModmFsdWU6IG51bWJlcltdKSB7XG4gICAgdGhpcy5fcGFnZVNpemVPcHRpb25zID0gKHZhbHVlIHx8IFtdKS5tYXAocCA9PiBjb2VyY2VOdW1iZXJQcm9wZXJ0eShwKSk7XG4gICAgdGhpcy5fdXBkYXRlRGlzcGxheWVkUGFnZVNpemVPcHRpb25zKCk7XG4gIH1cbiAgcHJpdmF0ZSBfcGFnZVNpemVPcHRpb25zOiBudW1iZXJbXSA9IFtdO1xuXG4gIC8qKiBXaGV0aGVyIHRvIGhpZGUgdGhlIHBhZ2Ugc2l6ZSBzZWxlY3Rpb24gVUkgZnJvbSB0aGUgdXNlci4gKi9cbiAgQElucHV0KClcbiAgZ2V0IGhpZGVQYWdlU2l6ZSgpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuX2hpZGVQYWdlU2l6ZTsgfVxuICBzZXQgaGlkZVBhZ2VTaXplKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5faGlkZVBhZ2VTaXplID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcbiAgfVxuICBwcml2YXRlIF9oaWRlUGFnZVNpemUgPSBmYWxzZTtcblxuXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgdGhlIGZpcnN0L2xhc3QgYnV0dG9ucyBVSSB0byB0aGUgdXNlci4gKi9cbiAgQElucHV0KClcbiAgZ2V0IHNob3dGaXJzdExhc3RCdXR0b25zKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5fc2hvd0ZpcnN0TGFzdEJ1dHRvbnM7IH1cbiAgc2V0IHNob3dGaXJzdExhc3RCdXR0b25zKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fc2hvd0ZpcnN0TGFzdEJ1dHRvbnMgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICB9XG4gIHByaXZhdGUgX3Nob3dGaXJzdExhc3RCdXR0b25zID0gZmFsc2U7XG5cbiAgLyoqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgcGFnaW5hdGlvbiBjaGFuZ2VzIHRoZSBwYWdlIHNpemUgb3IgcGFnZSBpbmRleC4gKi9cbiAgQE91dHB1dCgpIHJlYWRvbmx5IHBhZ2U6IEV2ZW50RW1pdHRlcjxQYWdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxQYWdlRXZlbnQ+KCk7XG5cbiAgLyoqIERpc3BsYXllZCBzZXQgb2YgcGFnZSBzaXplIG9wdGlvbnMuIFdpbGwgYmUgc29ydGVkIGFuZCBpbmNsdWRlIGN1cnJlbnQgcGFnZSBzaXplLiAqL1xuICBfZGlzcGxheWVkUGFnZVNpemVPcHRpb25zOiBudW1iZXJbXTtcblxuICAvKiogRGlzcGxheWVkIHBhZ2VzIGFycmF5ICovXG4gIF9wYWdlc0FycmF5ID0gW107XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7IH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLl9pbml0aWFsaXplZCA9IHRydWU7XG4gICAgdGhpcy5pbml0aWFsaXplZC5uZXh0KHRydWUpO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VTaXplT3B0aW9ucygpO1xuICB9XG5cbiAgLyoqIEFkdmFuY2VzIHRvIHRoZSBuZXh0IHBhZ2UgaWYgaXQgZXhpc3RzLiAqL1xuICBuZXh0UGFnZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaGFzTmV4dFBhZ2UoKSkgeyByZXR1cm47IH1cblxuICAgIGNvbnN0IHByZXZpb3VzUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXg7XG4gICAgdGhpcy5wYWdlSW5kZXgrKztcbiAgICB0aGlzLl91cGRhdGVEaXNwbGF5ZWRQYWdlc0FycmF5KCk7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogTW92ZSBiYWNrIHRvIHRoZSBwcmV2aW91cyBwYWdlIGlmIGl0IGV4aXN0cy4gKi9cbiAgcHJldmlvdXNQYWdlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5oYXNQcmV2aW91c1BhZ2UoKSkgeyByZXR1cm47IH1cblxuICAgIGNvbnN0IHByZXZpb3VzUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXg7XG4gICAgdGhpcy5wYWdlSW5kZXgtLTtcbiAgICB0aGlzLl91cGRhdGVEaXNwbGF5ZWRQYWdlc0FycmF5KCk7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogTW92ZSB0byB0aGUgZmlyc3QgcGFnZSBpZiBub3QgYWxyZWFkeSB0aGVyZS4gKi9cbiAgZmlyc3RQYWdlKCk6IHZvaWQge1xuICAgIC8vIGhhc1ByZXZpb3VzUGFnZSBiZWluZyBmYWxzZSBpbXBsaWVzIGF0IHRoZSBzdGFydFxuICAgIGlmICghdGhpcy5oYXNQcmV2aW91c1BhZ2UoKSkgeyByZXR1cm47IH1cblxuICAgIGNvbnN0IHByZXZpb3VzUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXg7XG4gICAgdGhpcy5wYWdlSW5kZXggPSAwO1xuICAgIHRoaXMuX3VwZGF0ZURpc3BsYXllZFBhZ2VzQXJyYXkoKTtcbiAgICB0aGlzLl9lbWl0UGFnZUV2ZW50KHByZXZpb3VzUGFnZUluZGV4KTtcbiAgfVxuXG4gIC8qKiBNb3ZlIHRvIHRoZSBsYXN0IHBhZ2UgaWYgbm90IGFscmVhZHkgdGhlcmUuICovXG4gIGxhc3RQYWdlKCk6IHZvaWQge1xuICAgIC8vIGhhc05leHRQYWdlIGJlaW5nIGZhbHNlIGltcGxpZXMgYXQgdGhlIGVuZFxuICAgIGlmICghdGhpcy5oYXNOZXh0UGFnZSgpKSB7IHJldHVybjsgfVxuXG4gICAgY29uc3QgcHJldmlvdXNQYWdlSW5kZXggPSB0aGlzLnBhZ2VJbmRleDtcbiAgICB0aGlzLnBhZ2VJbmRleCA9IHRoaXMuZ2V0TnVtYmVyT2ZQYWdlcygpIC0gMTtcbiAgICB0aGlzLl91cGRhdGVEaXNwbGF5ZWRQYWdlc0FycmF5KCk7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICBnb1RvUGFnZShwYWdlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBwcmV2aW91c1BhZ2VJbmRleCA9IHRoaXMucGFnZUluZGV4O1xuXG4gICAgdGhpcy5wYWdlSW5kZXggPSBwYWdlIC0gMTtcbiAgICB0aGlzLl91cGRhdGVEaXNwbGF5ZWRQYWdlc0FycmF5KCk7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogV2hldGhlciB0aGVyZSBpcyBhIHByZXZpb3VzIHBhZ2UuICovXG4gIGhhc1ByZXZpb3VzUGFnZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wYWdlSW5kZXggPj0gMSAmJiB0aGlzLnBhZ2VTaXplICE9PSAwO1xuICB9XG5cbiAgLyoqIFdoZXRoZXIgdGhlcmUgaXMgYSBuZXh0IHBhZ2UuICovXG4gIGhhc05leHRQYWdlKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG1heFBhZ2VJbmRleCA9IHRoaXMuZ2V0TnVtYmVyT2ZQYWdlcygpIC0gMTtcbiAgICByZXR1cm4gdGhpcy5wYWdlSW5kZXggPCBtYXhQYWdlSW5kZXggJiYgdGhpcy5wYWdlU2l6ZSAhPT0gMDtcbiAgfVxuXG4gIC8qKiBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiBwYWdlcyAqL1xuICBnZXROdW1iZXJPZlBhZ2VzKCk6IG51bWJlciB7XG4gICAgaWYgKCF0aGlzLnBhZ2VTaXplKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gTWF0aC5jZWlsKHRoaXMubGVuZ3RoIC8gdGhpcy5wYWdlU2l6ZSk7XG4gIH1cblxuICAvKiogQ2FsY3VsYXRlIHRoZSBwYWdlIHJhbmdlICovXG4gIGdldFJhbmdlTGFiZWwgPSAocGFnZTogbnVtYmVyLCBwYWdlU2l6ZTogbnVtYmVyLCBsZW5ndGg6IG51bWJlcikgPT4ge1xuICAgIGlmIChsZW5ndGggPT09IDAgfHwgcGFnZVNpemUgPT09IDApIHsgcmV0dXJuIGAwIGRlICR7bGVuZ3RofWA7IH1cblxuICAgIGxlbmd0aCA9IE1hdGgubWF4KGxlbmd0aCwgMCk7XG5cbiAgICBjb25zdCBzdGFydEluZGV4ID0gcGFnZSAqIHBhZ2VTaXplO1xuXG4gICAgLy8gSWYgdGhlIHN0YXJ0IGluZGV4IGV4Y2VlZHMgdGhlIGxpc3QgbGVuZ3RoLCBkbyBub3QgdHJ5IGFuZCBmaXggdGhlIGVuZCBpbmRleCB0byB0aGUgZW5kLlxuICAgIGNvbnN0IGVuZEluZGV4ID0gc3RhcnRJbmRleCA8IGxlbmd0aCA/XG4gICAgICBNYXRoLm1pbihzdGFydEluZGV4ICsgcGFnZVNpemUsIGxlbmd0aCkgOlxuICAgICAgc3RhcnRJbmRleCArIHBhZ2VTaXplO1xuXG4gICAgcmV0dXJuIGAke3N0YXJ0SW5kZXggKyAxfSDigJMgJHtlbmRJbmRleH0gZGUgJHtsZW5ndGh9YDtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENoYW5nZXMgdGhlIHBhZ2Ugc2l6ZSBzbyB0aGF0IHRoZSBmaXJzdCBpdGVtIGRpc3BsYXllZCBvbiB0aGUgcGFnZSB3aWxsIHN0aWxsIGJlXG4gICAqIGRpc3BsYXllZCB1c2luZyB0aGUgbmV3IHBhZ2Ugc2l6ZS5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIGlmIHRoZSBwYWdlIHNpemUgaXMgMTAgYW5kIG9uIHRoZSBzZWNvbmQgcGFnZSAoaXRlbXMgaW5kZXhlZCAxMC0xOSkgdGhlblxuICAgKiBzd2l0Y2hpbmcgc28gdGhhdCB0aGUgcGFnZSBzaXplIGlzIDUgd2lsbCBzZXQgdGhlIHRoaXJkIHBhZ2UgYXMgdGhlIGN1cnJlbnQgcGFnZSBzb1xuICAgKiB0aGF0IHRoZSAxMHRoIGl0ZW0gd2lsbCBzdGlsbCBiZSBkaXNwbGF5ZWQuXG4gICAqL1xuICBfY2hhbmdlUGFnZVNpemUocGFnZVNpemU6IG51bWJlcikge1xuICAgIC8vIEN1cnJlbnQgcGFnZSBuZWVkcyB0byBiZSB1cGRhdGVkIHRvIHJlZmxlY3QgdGhlIG5ldyBwYWdlIHNpemUuIE5hdmlnYXRlIHRvIHRoZSBwYWdlXG4gICAgLy8gY29udGFpbmluZyB0aGUgcHJldmlvdXMgcGFnZSdzIGZpcnN0IGl0ZW0uXG4gICAgY29uc3Qgc3RhcnRJbmRleCA9IHRoaXMucGFnZUluZGV4ICogdGhpcy5wYWdlU2l6ZTtcbiAgICBjb25zdCBwcmV2aW91c1BhZ2VJbmRleCA9IHRoaXMucGFnZUluZGV4O1xuXG4gICAgdGhpcy5wYWdlSW5kZXggPSBNYXRoLmZsb29yKHN0YXJ0SW5kZXggLyBwYWdlU2l6ZSkgfHwgMDtcbiAgICB0aGlzLnBhZ2VTaXplID0gcGFnZVNpemU7XG4gICAgdGhpcy5fZW1pdFBhZ2VFdmVudChwcmV2aW91c1BhZ2VJbmRleCk7XG4gIH1cblxuICAvKiogQ2hlY2tzIHdoZXRoZXIgdGhlIGJ1dHRvbnMgZm9yIGdvaW5nIGZvcndhcmRzIHNob3VsZCBiZSBkaXNhYmxlZC4gKi9cbiAgX25leHRCdXR0b25zRGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGlzYWJsZWQgfHwgIXRoaXMuaGFzTmV4dFBhZ2UoKTtcbiAgfVxuXG4gIC8qKiBDaGVja3Mgd2hldGhlciB0aGUgYnV0dG9ucyBmb3IgZ29pbmcgYmFja3dhcmRzIHNob3VsZCBiZSBkaXNhYmxlZC4gKi9cbiAgX3ByZXZpb3VzQnV0dG9uc0Rpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmRpc2FibGVkIHx8ICF0aGlzLmhhc1ByZXZpb3VzUGFnZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIGxpc3Qgb2YgcGFnZSBzaXplIG9wdGlvbnMgdG8gZGlzcGxheSB0byB0aGUgdXNlci4gSW5jbHVkZXMgbWFraW5nIHN1cmUgdGhhdFxuICAgKiB0aGUgcGFnZSBzaXplIGlzIGFuIG9wdGlvbiBhbmQgdGhhdCB0aGUgbGlzdCBpcyBzb3J0ZWQuXG4gICAqL1xuICBwcml2YXRlIF91cGRhdGVEaXNwbGF5ZWRQYWdlU2l6ZU9wdGlvbnMoKSB7XG4gICAgaWYgKCF0aGlzLl9pbml0aWFsaXplZCkgeyByZXR1cm47IH1cblxuICAgIC8vIElmIG5vIHBhZ2Ugc2l6ZSBpcyBwcm92aWRlZCwgdXNlIHRoZSBmaXJzdCBwYWdlIHNpemUgb3B0aW9uIG9yIHRoZSBkZWZhdWx0IHBhZ2Ugc2l6ZS5cbiAgICBpZiAoIXRoaXMucGFnZVNpemUpIHtcbiAgICAgIHRoaXMuX3BhZ2VTaXplID0gdGhpcy5wYWdlU2l6ZU9wdGlvbnMubGVuZ3RoICE9PSAwID9cbiAgICAgICAgdGhpcy5wYWdlU2l6ZU9wdGlvbnNbMF0gOlxuICAgICAgICBERUZBVUxUX1BBR0VfU0laRTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaXNwbGF5ZWRQYWdlU2l6ZU9wdGlvbnMgPSB0aGlzLnBhZ2VTaXplT3B0aW9ucy5zbGljZSgpO1xuXG4gICAgaWYgKHRoaXMuX2Rpc3BsYXllZFBhZ2VTaXplT3B0aW9ucy5pbmRleE9mKHRoaXMucGFnZVNpemUpID09PSAtMSkge1xuICAgICAgdGhpcy5fZGlzcGxheWVkUGFnZVNpemVPcHRpb25zLnB1c2godGhpcy5wYWdlU2l6ZSk7XG4gICAgfVxuXG4gICAgLy8gU29ydCB0aGUgbnVtYmVycyB1c2luZyBhIG51bWJlci1zcGVjaWZpYyBzb3J0IGZ1bmN0aW9uLlxuICAgIHRoaXMuX2Rpc3BsYXllZFBhZ2VTaXplT3B0aW9ucy5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVEaXNwbGF5ZWRQYWdlc0FycmF5KCkge1xuICAgIHRoaXMuX3BhZ2VzQXJyYXkgPSBidWlsZFBhZ2luYXRpb25BcnJheSh0aGlzLmdldE51bWJlck9mUGFnZXMoKSwgdGhpcy5wYWdlSW5kZXggKyAxLCAzKTtcbiAgfVxuXG4gIC8qKiBFbWl0cyBhbiBldmVudCBub3RpZnlpbmcgdGhhdCBhIGNoYW5nZSBvZiB0aGUgcGFnaW5hdGlvbidzIHByb3BlcnRpZXMgaGFzIGJlZW4gdHJpZ2dlcmVkLiAqL1xuICBwcml2YXRlIF9lbWl0UGFnZUV2ZW50KHByZXZpb3VzUGFnZUluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLnBhZ2UuZW1pdCh7XG4gICAgICBwcmV2aW91c1BhZ2VJbmRleCxcbiAgICAgIHBhZ2VJbmRleDogdGhpcy5wYWdlSW5kZXgsXG4gICAgICBwYWdlU2l6ZTogdGhpcy5wYWdlU2l6ZSxcbiAgICAgIGxlbmd0aDogdGhpcy5sZW5ndGhcbiAgICB9KTtcbiAgfVxufVxuIl19