UNPKG

ngx-paypal-with-intent

Version:

Paypal integration for Angular 6, 7 and beyond

447 lines 53.1 kB
import { ChangeDetectionStrategy, Component, Input, ViewChild, NgModule } from '@angular/core';
import { interval, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
/** @enum {number} */
const PayPalFunding = {
    Card: 0,
    Credit: 1,
    Elv: 2,
};
PayPalFunding[PayPalFunding.Card] = 'Card';
PayPalFunding[PayPalFunding.Credit] = 'Credit';
PayPalFunding[PayPalFunding.Elv] = 'Elv';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
/** @enum {number} */
const PayPalIntegrationType = {
    ClientSideREST: 0,
    ServerSideREST: 1,
};
PayPalIntegrationType[PayPalIntegrationType.ClientSideREST] = 'ClientSideREST';
PayPalIntegrationType[PayPalIntegrationType.ServerSideREST] = 'ServerSideREST';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class PayPalConfig {
    /**
     * @param {?} integrationType
     * @param {?} environment
     * @param {?} config
     */
    constructor(integrationType, environment, config) {
        this.integrationType = integrationType;
        this.environment = environment;
        /**
         * Show 'Pay Now' button config
         */
        this.commit = true;
        /**
         * Set the intent of the payment.
         */
        this.intent = 'sale';
        Object.assign(this, config);
    }
}

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxPaypalComponent {
    constructor() {
        /**
         * Indicates if global configuration (provided via 'forRoot') is used
         */
        this.useGlobalConfig = false;
        /**
         * Used for indicating delayed rendered if container is not yet ready in DOM
         */
        this.registerPayPalScriptWhenContainerIsReady = false;
        /**
         * Polling interval if paypal script is pending
         */
        this.defaultPollInterval = 50;
        /**
         * Polling will stop after polling reaches this number
         */
        this.maximumPollWaitTime = 5000;
        /**
         * Name of the global variable where paypal is stored
         */
        this.paypalWindowName = 'paypal';
        /**
         * Name of the global variable indicating that script was initiated (added to page)
         */
        this.paypalWindowScriptInitiated = 'ngx-paypal-script-initiated';
        /**
         * PayPal integration script url
         */
        this.paypalScriptUrl = 'https://www.paypalobjects.com/api/checkout.js';
        this.payPalButtonContainerIdPrefix = 'ngx-paypal-button-container-';
        this.ngUnsubscribe = new Subject();
    }
    /**
     * @param {?} content
     * @return {?}
     */
    set payPalButtonContainerElem(content) {
        if (content) {
            this._payPalButtonContainerElem = content;
        }
    }
    /**
     * @param {?} changes
     * @return {?}
     */
    ngOnChanges(changes) {
        // init when config once its available
        if (this.config) {
            this.initPayPal();
        }
    }
    /**
     * @return {?}
     */
    ngAfterViewInit() {
        // register script if element is ready in dom
        if (this.registerPayPalScriptWhenContainerIsReady && this._payPalButtonContainerElem) {
            this.setupScript();
            this.registerPayPalScriptWhenContainerIsReady = false;
        }
    }
    /**
     * @return {?}
     */
    ngOnDestroy() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }
    /**
     * @return {?}
     */
    initPayPal() {
        // set unique paypal container button id
        this.payPalButtonContainerId = `${this.payPalButtonContainerIdPrefix}${this.getPseudoUniqueNumber()}`;
        // check if paypal was already register and if so, don't add it to page again
        if (!window[this.paypalWindowName]) {
            // check if script is pending
            if (window[this.paypalWindowScriptInitiated] === true) {
                this.pollUntilScriptAvailable();
            }
            else {
                // register script and set global flag
                window[this.paypalWindowScriptInitiated] = true;
                this.addPayPalScriptToPage();
            }
        }
        else {
            // just register payment
            this.handleScriptRegistering();
        }
    }
    /**
     * @return {?}
     */
    getPseudoUniqueNumber() {
        return new Date().valueOf();
    }
    /**
     * Used when there are multiple paypal components on the same page beacuse only 1 of them
     * may register paypal script. The other has to be polling until paypal is available or component destroyed
     * @return {?}
     */
    pollUntilScriptAvailable() {
        /** @type {?} */
        const obs = interval(this.defaultPollInterval)
            .pipe(takeUntil(this.ngUnsubscribe), map((x) => {
            if (x >= this.maximumPollWaitTime) {
                console.warn(`PayPal script was not loaded after '${this.maximumPollWaitTime}' maximum polling time.`);
                obs.unsubscribe();
                return;
            }
            // check if paypal script exists
            if (window[this.paypalWindowName]) {
                // register script
                this.handleScriptRegistering();
                // stop execution
                obs.unsubscribe();
            }
        }))
            .subscribe();
    }
    /**
     * @return {?}
     */
    addPayPalScriptToPage() {
        /** @type {?} */
        const script = document.createElement('script');
        script.innerHTML = '';
        script.src = this.paypalScriptUrl;
        script.onload = () => this.handleScriptRegistering();
        script.async = true;
        script.defer = true;
        this.paypalScriptElem.nativeElement.appendChild(script);
    }
    /**
     * @return {?}
     */
    handleScriptRegistering() {
        // check if container with requested id exists
        // this is here because dynamically switching between components would cause PayPal to
        // throw an error if the container already existed before
        if (this._payPalButtonContainerElem && this._payPalButtonContainerElem.nativeElement &&
            this._payPalButtonContainerElem.nativeElement.id === this.payPalButtonContainerId) {
            // container is ready, setup script right away
            this.setupScript();
        }
        else {
            // container is not ready, delay registering until it is
            this.registerPayPalScriptWhenContainerIsReady = true;
        }
    }
    /**
     * @return {?}
     */
    setupScript() {
        // first clear container
        if (!this._payPalButtonContainerElem) {
            throw Error(`Cannot setup script because paypal button container with id '${this.payPalButtonContainerId}' is not yet ready`);
        }
        this._payPalButtonContainerElem.nativeElement.innerHTML = '';
        if (!window[this.paypalWindowName]) {
            throw Error('PayPal script is not available');
        }
        // render PayPal button as per their docs at
        // https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/add-paypal-button/
        window[this.paypalWindowName].Button.render({
            // set environment
            env: this.config.environment.toString(),
            // Show the buyer a 'Pay Now' button in the checkout flow
            commit: this.config.commit,
            // init client for client side integration
            client: this.getClient(),
            // set button config if available
            style: this.config.button,
            // set funding if available
            funding: this.getFunding(),
            // payment() is called when the button is clicked
            payment: (data, actions) => {
                if (this.config.integrationType === PayPalIntegrationType.ServerSideREST) {
                    // client needs to create payment on server side
                    if (!this.config.payment) {
                        throw Error(`You need set up a create payment method and return
                            PayPal's payment id when using server side integration`);
                    }
                    // Paypal expects promise with payment id (string) to be returned
                    return this.config.payment().toPromise()
                        .then(paymentId => {
                        return paymentId;
                    });
                }
                if (this.config.integrationType === PayPalIntegrationType.ClientSideREST) {
                    if (!this.config.transactions || !Array.isArray(this.config.transactions) || this.config.transactions.length <= 0) {
                        throw Error(`You need to provide at least 1 transaction for client side integration`);
                    }
                    /** @type {?} */
                    const experienceConfig = this.config.experience;
                    return actions.payment.create({
                        payment: {
                            // Allow user to specifify intent, else use default 'sale'.
                            intent: this.config.intent ? this.config.intent : 'sale',
                            transactions: this.config.transactions
                        },
                        experience: {
                            input_fields: {
                                no_shipping: (experienceConfig && experienceConfig.noShipping) ? 1 : 0
                            },
                            presentation: {
                                brand_name: (experienceConfig && experienceConfig.brandName) ? experienceConfig.brandName : null,
                                logo_image: (experienceConfig && experienceConfig.logoImage) ? experienceConfig.logoImage : null,
                                locale_code: (experienceConfig && experienceConfig.localeCode) ? experienceConfig.localeCode : null
                            }
                        }
                    });
                }
            },
            // onAuthorize() is called when the buyer approves the payment
            onAuthorize: (data, actions) => {
                if (this.config.integrationType === PayPalIntegrationType.ServerSideREST) {
                    // client needs to server to execute the payment
                    if (!this.config.onAuthorize) {
                        throw Error(`You need set up an execute method when using server side integration`);
                    }
                    // Paypal expects promise
                    return this.config.onAuthorize(data, actions).toPromise();
                }
                if (this.config.integrationType === PayPalIntegrationType.ClientSideREST) {
                    // Make a call to the REST api to execute the payment
                    return actions.payment.execute().then(() => {
                        if (!this.config.onPaymentComplete) {
                            throw Error(`You should provide some callback when payment is finished when using client side integration`);
                        }
                        this.config.onPaymentComplete(data, actions);
                    });
                }
            },
            onError: (err) => {
                if (this.config.onError) {
                    this.config.onError(err);
                }
            },
            onCancel: (data, actions) => {
                if (this.config.onCancel) {
                    this.config.onCancel(data, actions);
                }
            },
            onClick: () => {
                if (this.config.onClick) {
                    this.config.onClick();
                }
            },
            validate: (actions) => {
                if (this.config.validate) {
                    this.config.validate(actions);
                }
            }
        }, `#${this.payPalButtonContainerId}`);
    }
    /**
     * @return {?}
     */
    getClient() {
        if (this.config.integrationType === PayPalIntegrationType.ClientSideREST) {
            if (!this.config.client) {
                throw Error(`You need to setup client information when using client side integration`);
            }
            return {
                production: this.config.client.production,
                sandbox: this.config.client.sandbox
            };
        }
        return undefined;
    }
    /**
     * @return {?}
     */
    getFunding() {
        // resolve funding to use paypal's properties
        if (!this.config.funding) {
            // no funding provided
            return undefined;
        }
        /** @type {?} */
        const allowed = [];
        /** @type {?} */
        const disallowed = [];
        if (this.config.funding.allowed) {
            this.config.funding.allowed.forEach(type => {
                allowed.push(this.mapFundingType(type));
            });
        }
        if (this.config.funding.disallowed) {
            this.config.funding.disallowed.forEach(type => {
                disallowed.push(this.mapFundingType(type));
            });
        }
        return {
            allowed: allowed,
            disallowed: disallowed
        };
    }
    /**
     * @param {?} type
     * @return {?}
     */
    mapFundingType(type) {
        if (type === PayPalFunding.Card) {
            return paypal.FUNDING.CARD;
        }
        if (type === PayPalFunding.Credit) {
            return paypal.FUNDING.CREDIT;
        }
        if (type === PayPalFunding.Elv) {
            return paypal.FUNDING.ELV;
        }
        throw Error(`Unsupported funding type '${type}'`);
    }
}
NgxPaypalComponent.decorators = [
    { type: Component, args: [{
                changeDetection: ChangeDetectionStrategy.OnPush,
                selector: 'ngx-paypal',
                template: `
    <div #payPalScriptElem></div>
    <div #payPalButtonContainerElem [id]="payPalButtonContainerId"></div>
    `
            }] }
];
/** @nocollapse */
NgxPaypalComponent.ctorParameters = () => [];
NgxPaypalComponent.propDecorators = {
    config: [{ type: Input }],
    useGlobalConfig: [{ type: Input }],
    paypalScriptElem: [{ type: ViewChild, args: ['payPalScriptElem',] }],
    payPalButtonContainerElem: [{ type: ViewChild, args: ['payPalButtonContainerElem',] }]
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
class NgxPayPalModule {
}
NgxPayPalModule.decorators = [
    { type: NgModule, args: [{
                imports: [],
                declarations: [
                    NgxPaypalComponent,
                ],
                exports: [
                    NgxPaypalComponent,
                ]
            },] }
];

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
/** @enum {string} */
const PayPalEnvironment = {
    Sandbox: 'sandbox',
    Production: 'production',
};

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */

export { NgxPayPalModule, PayPalEnvironment, PayPalFunding, PayPalIntegrationType, PayPalConfig, NgxPaypalComponent, NgxPaypalComponent as ɵa };

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXBheXBhbC13aXRoLWludGVudC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmd4LXBheXBhbC13aXRoLWludGVudC9saWIvbW9kZWxzL3BheXBhbC1mdW5kaW5nLnRzIiwibmc6Ly9uZ3gtcGF5cGFsLXdpdGgtaW50ZW50L2xpYi9tb2RlbHMvcGF5cGFsLWludGVncmF0aW9uLnRzIiwibmc6Ly9uZ3gtcGF5cGFsLXdpdGgtaW50ZW50L2xpYi9tb2RlbHMvcGF5cGFsLW1vZGVscy50cyIsIm5nOi8vbmd4LXBheXBhbC13aXRoLWludGVudC9saWIvY29tcG9uZW50cy9wYXlwYWwtY29tcG9uZW50LnRzIiwibmc6Ly9uZ3gtcGF5cGFsLXdpdGgtaW50ZW50L2xpYi9uZ3gtcGF5cGFsLm1vZHVsZS50cyIsIm5nOi8vbmd4LXBheXBhbC13aXRoLWludGVudC9saWIvbW9kZWxzL3BheXBhbC1lbnZpcm9ubWVudC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZW51bSBQYXlQYWxGdW5kaW5nIHtcbiAgICBDYXJkLFxuICAgIENyZWRpdCxcbiAgICBFbHZcbn1cbiIsImV4cG9ydCBlbnVtIFBheVBhbEludGVncmF0aW9uVHlwZSB7XG4gICAgQ2xpZW50U2lkZVJFU1QsXG4gICAgU2VydmVyU2lkZVJFU1QsXG59XG4iLCJpbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFBheVBhbEZ1bmRpbmcgfSBmcm9tICcuL3BheXBhbC1mdW5kaW5nJztcbmltcG9ydCB7IFBheVBhbEVudmlyb25tZW50IH0gZnJvbSAnLi9wYXlwYWwtZW52aXJvbm1lbnQnO1xuaW1wb3J0IHsgUGF5UGFsSW50ZWdyYXRpb25UeXBlIH0gZnJvbSAnLi9wYXlwYWwtaW50ZWdyYXRpb24nO1xuXG5leHBvcnQgY2xhc3MgUGF5UGFsQ29uZmlnIHtcblxuICAgIC8qKlxuICAgICAqIFNob3cgJ1BheSBOb3cnIGJ1dHRvbiBjb25maWdcbiAgICAgKi9cbiAgICBwdWJsaWMgY29tbWl0ID0gdHJ1ZTtcblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgaW50ZW50IG9mIHRoZSBwYXltZW50LlxuICAgICAqL1xuICAgIHB1YmxpYyBpbnRlbnQgPSAnc2FsZSc7XG5cbiAgICAvKipcbiAgICAgKiBDYWxsZWQgdG8gY3JlYXRlIG5ldyBwYXltZW50IGZvciBzZXJ2ZXIgc2lkZSBpbnRlZ3JhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBwYXltZW50PzogKCkgPT4gT2JzZXJ2YWJsZTxzdHJpbmc+O1xuXG4gICAgLyoqXG4gICAgICogQ2FsbGVkIHRvIGV4ZWN1dGUgcGF5bWVudCBmb3Igc2VydmVyIHNpZGUgaW50ZWdyYXRpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgb25BdXRob3JpemU/OiAoZGF0YTogSVBheVBhbFBheW1lbnRDb21wbGV0ZURhdGEsIGFjdGlvbnM6IGFueSkgPT4gT2JzZXJ2YWJsZTx2b2lkPjtcblxuICAgIC8qKlxuICAgICAqIENsaWVudCB0b2tlbnMgZm9yIGNsaWVudCBzaWRlIGludGVncmF0aW9uXG4gICAgICovXG4gICAgcHVibGljIGNsaWVudD86IElQYXlwYWxDbGllbnQ7XG5cbiAgICAvKipcbiAgICAgKiBBcnJheSBvZiB0cmFuc2FjdGlvbiwgcmVxdWlyZWQgZm9yIGNsaWVudCBzaWRlIGludGVncmF0aW9uXG4gICAgICovXG4gICAgcHVibGljIHRyYW5zYWN0aW9ucz86IElQYXlQYWxUcmFuc2FjdGlvbltdO1xuXG4gICAgLyoqXG4gICAgICogUGF5bWVudCBFeHBlcmllbmNlIGNvbmZpZ3VyYXRpb25zXG4gICAgICovXG4gICAgcHVibGljIGV4cGVyaWVuY2U/OiBJUGF5UGFsRXhwZXJpZW5jZTtcblxuICAgIC8qKlxuICAgICAqIENhbGxlZCBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb24gd2hlbiBwYXltZW50IGlzIGV4ZWN1dGVkXG4gICAgICovXG4gICAgcHVibGljIG9uUGF5bWVudENvbXBsZXRlPzogKGRhdGE6IElQYXlQYWxQYXltZW50Q29tcGxldGVEYXRhLCBhY3Rpb25zOiBhbnkpID0+IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBCdXR0b24gY29uZmlndXJhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBidXR0b24/OiBJUGF5UGFsQnV0dG9uU3R5bGU7XG5cbiAgICAvKipcbiAgICAgKiBQYXlwYWwgZnVuZGluZyBjb25maWd1cmF0aW9uXG4gICAgICovXG4gICAgcHVibGljIGZ1bmRpbmc/OiBJUGF5UGFsRnVuZGluZztcblxuICAgIC8qKlxuICAgICAqIENhbGxlZCB3aGVuIFBheVBhbCBleHBlcmllbmNlcyBhbiBlcnJvclxuICAgICAqL1xuICAgIHB1YmxpYyBvbkVycm9yPzogKGVycjogYW55KSA9PiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBoYW5kbGVyIHdpbGwgYmUgY2FsbGVkIGZvciBldmVyeSBjbGljayBvbiB0aGUgUGF5UGFsIGJ1dHRvblxuICAgICAqL1xuICAgIHB1YmxpYyBvbkNsaWNrPzogKCkgPT4gdm9pZDtcblxuICAgIC8qKlxuICAgICAqIENhbGxlZCB3aGVuIHVzZXIgY2FuY2VscyBwYXltZW50XG4gICAgICovXG4gICAgcHVibGljIG9uQ2FuY2VsPzogKGRhdGE6IElQYXlQYWxDYW5jZWxQYXltZW50LCBhY3Rpb25zOiBhbnkpID0+IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBDYW4gYmUgdXNlZCB0byB2YWxpZGF0aW9uIGFzIGNhbiBiZSBzZWVuIGhlcmU6IGh0dHBzOi8vZGV2ZWxvcGVyLnBheXBhbC5jb20vZGVtby9jaGVja291dC8jL3BhdHRlcm4vdmFsaWRhdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyB2YWxpZGF0ZT86IChhY3Rpb25zOiBhbnkpID0+IHZvaWQ7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFR5cGUgb2YgdGhlIGludGVncmF0aW9uXG4gICAgICAgICAqL1xuICAgICAgICBwdWJsaWMgaW50ZWdyYXRpb25UeXBlOiBQYXlQYWxJbnRlZ3JhdGlvblR5cGUsXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbnZpcm9ubWVudFxuICAgICAgICAgKi9cbiAgICAgICAgcHVibGljIGVudmlyb25tZW50OiBQYXlQYWxFbnZpcm9ubWVudCxcbiAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgICBvbkVycm9yPzogKGVycjogYW55KSA9PiB2b2lkLFxuICAgICAgICAgICAgb25DbGljaz86ICgpID0+IHZvaWQsXG4gICAgICAgICAgICB2YWxpZGF0ZT86IChhY3Rpb25zOiBhbnkpID0+IHZvaWQ7XG4gICAgICAgICAgICBvbkNhbmNlbD86IChkYXRhOiBJUGF5UGFsQ2FuY2VsUGF5bWVudCwgYWN0aW9uczogYW55KSA9PiB2b2lkLFxuICAgICAgICAgICAgcGF5bWVudD86ICgpID0+IE9ic2VydmFibGU8c3RyaW5nPixcbiAgICAgICAgICAgIGludGVudD86IHN0cmluZyxcbiAgICAgICAgICAgIG9uQXV0aG9yaXplPzogKGRhdGE6IElQYXlQYWxQYXltZW50Q29tcGxldGVEYXRhLCBhY3Rpb25zOiBhbnkpID0+IE9ic2VydmFibGU8dm9pZD4sXG4gICAgICAgICAgICBjbGllbnQ/OiBJUGF5cGFsQ2xpZW50LFxuICAgICAgICAgICAgb25QYXltZW50Q29tcGxldGU/OiAoZGF0YTogSVBheVBhbFBheW1lbnRDb21wbGV0ZURhdGEsIGFjdGlvbnM6IGFueSkgPT4gdm9pZCxcbiAgICAgICAgICAgIHRyYW5zYWN0aW9ucz86IElQYXlQYWxUcmFuc2FjdGlvbltdLFxuICAgICAgICAgICAgbm90ZV90b19wYXllcj86IHN0cmluZztcbiAgICAgICAgICAgIGV4cGVyaWVuY2U/OiBJUGF5UGFsRXhwZXJpZW5jZSxcbiAgICAgICAgICAgIGNvbW1pdD86IGJvb2xlYW4sXG4gICAgICAgICAgICBidXR0b24/OiBJUGF5UGFsQnV0dG9uU3R5bGUsXG4gICAgICAgICAgICBmdW5kaW5nPzogSVBheVBhbEZ1bmRpbmdcbiAgICAgICAgfSkge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNvbmZpZyk7XG4gICAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXlQYWxQYXltZW50Q29tcGxldGVEYXRhIHtcbiAgICBpbnRlbnQ6IHN0cmluZztcbiAgICBvcmRlcklEOiBzdHJpbmc7XG4gICAgcGF5ZXJJRDogc3RyaW5nO1xuICAgIHBheW1lbnRJRDogc3RyaW5nO1xuICAgIHBheW1lbnRUb2tlbjogc3RyaW5nO1xuICAgIHJldHVyblVybDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXlQYWxDYW5jZWxQYXltZW50IHtcbiAgICBkYXRhOiBJUGF5UGFsQ2FuY2VsUGF5bWVudERhdGE7XG4gICAgYWN0aW9uczogYW55O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXlQYWxDYW5jZWxQYXltZW50RGF0YSB7XG4gICAgYmlsbGluZ0lEOiBzdHJpbmc7XG4gICAgY2FuY2VsVXJsOiBzdHJpbmc7XG4gICAgaW50ZW50OiBzdHJpbmc7XG4gICAgcGF5bWVudElEOiBzdHJpbmc7XG4gICAgcGF5bWVudFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVBheXBhbENsaWVudCB7XG4gICAgc2FuZGJveD86IHN0cmluZztcbiAgICBwcm9kdWN0aW9uPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXlQYWxUcmFuc2FjdGlvbiB7XG4gICAgYW1vdW50OiBJUGF5UGFsQW1vdW50O1xuICAgIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICAgIGN1c3RvbT86IHN0cmluZztcbiAgICBwYXltZW50X29wdGlvbnM/OiBJUGF5UGFsVHJhbnNhY3Rpb25QYXltZW50T3B0aW9ucztcbiAgICBpbnZvaWNlX251bWJlcj86IHN0cmluZztcbiAgICBzb2Z0X2Rlc2NyaXB0b3I/OiBzdHJpbmc7XG4gICAgaXRlbV9saXN0PzogSVBheVBhbFRyYW5zYWN0aW9uSXRlbUxpc3Q7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVBheVBhbFRyYW5zYWN0aW9uSXRlbUxpc3Qge1xuICAgIGl0ZW1zPzogSVBheVBhbFRyYW5zYWN0aW9uSXRlbVtdO1xuICAgIHNoaXBwaW5nX2FkZHJlc3M/OiBJUGF5UGFsVHJhbnNhY3Rpb25TaGlwcGluZ0FkZHJlc3M7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVBheVBhbFRyYW5zYWN0aW9uSXRlbSB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGN1cnJlbmN5OiBzdHJpbmc7XG4gICAgcHJpY2U6IG51bWJlcjtcbiAgICBxdWFudGl0eTogbnVtYmVyO1xuXG4gICAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gICAgdGF4PzogbnVtYmVyO1xuICAgIHNrdT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJUGF5UGFsQW1vdW50IHtcbiAgICB0b3RhbDogbnVtYmVyO1xuICAgIGN1cnJlbmN5OiBzdHJpbmc7XG4gICAgZGV0YWlscz86IElQYXlQYWxBbW91bnREZXRhaWxzO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElQYXlQYWxUcmFuc2FjdGlvblNoaXBwaW5nQWRkcmVzcyB7XG4gICAgcmVjaXBpZW50X25hbWU6IHN0cmluZztcbiAgICBsaW5lMTogc3RyaW5nO1xuICAgIGxpbmUyPzogc3RyaW5nO1xuICAgIGNpdHk6IHN0cmluZztcbiAgICBjb3VudHJ5X2NvZGU6IHN0cmluZztcbiAgICBwb3N0YWxfY29kZTogc3RyaW5nO1xuICAgIHBob25lOiBzdHJpbmc7XG4gICAgc3RhdGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJUGF5UGFsQW1vdW50RGV0YWlscyB7XG4gICAgc3VidG90YWw6IG51bWJlcjtcbiAgICB0YXg6IG51bWJlcjtcbiAgICBzaGlwcGluZzogbnVtYmVyO1xuICAgIGhhbmRsaW5nX2ZlZTogbnVtYmVyO1xuICAgIHNoaXBwaW5nX2Rpc2NvdW50OiBudW1iZXI7XG4gICAgaW5zdXJhbmNlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVBheVBhbFRyYW5zYWN0aW9uUGF5bWVudE9wdGlvbnMge1xuICAgIGFsbG93ZWRfcGF5bWVudF9tZXRob2Q/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVBheVBhbEV4cGVyaWVuY2Uge1xuICAgIC8qKiBJbmRpY2F0ZXMgd2hldGhlciBQYXlQYWwgZGlzcGxheXMgc2hpcHBpbmcgYWRkcmVzcyBmaWVsZHMgb24gdGhlIGV4cGVyaWVuY2UgcGFnZXMgKi9cbiAgICBub1NoaXBwaW5nPzogYm9vbGVhbjtcbiAgICAvKiogQSBsYWJlbCB0aGF0IG92ZXJyaWRlcyB0aGUgYnVzaW5lc3MgbmFtZSBpbiB0aGUgUGF5UGFsIGFjY291bnQgb24gdGhlIFBheVBhbCBwYWdlcy4gTWF4IGxlbmd0aDogMTI3IGNoYXJhY3RlcnMuICovXG4gICAgYnJhbmROYW1lPzogc3RyaW5nO1xuICAgIC8qKiBVUkwgdG8gdGhlIGxvZ28gaW1hZ2UgKGdpZiwganBnLCBvciBwbmcpLiBUaGUgaW1hZ2UncyBtYXhpbXVtIHdpZHRoIGlzIDE5MCBwaXhlbHMgYW5kIG1heGltdW0gaGVpZ2h0IGlzIDYwIHBpeGVscy4gKi9cbiAgICBsb2dvSW1hZ2U/OiBzdHJpbmc7XG4gICAgLyoqIExvY2FsZSBpbiB3aGljaCB0byBkaXNwbGF5IFBheVBhbCBwYWdlICovXG4gICAgbG9jYWxlQ29kZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJUGF5UGFsQnV0dG9uU3R5bGUge1xuICAgIGxhYmVsPzogJ2NoZWNrb3V0JyB8ICdwYXknIHwgJ2J1eW5vdycgfCAncGF5cGFsJztcbiAgICBzaXplPzogJ3NtYWxsJyB8ICdtZWRpdW0nIHwgJ2xhcmdlJyB8ICdyZXNwb25zaXZlJztcbiAgICBzaGFwZT86ICdwaWxsJyB8ICdyZWN0JztcbiAgICBjb2xvcj86ICdnb2xkJyB8ICdibHVlJyB8ICdzaWx2ZXInIHwgJ2JsYWNrJztcbiAgICBsYXlvdXQ/OiAnaG9yaXpvbnRhbCcgfCAndmVydGljYWwnO1xuICAgIHRhZ2xpbmU/OiBmYWxzZTtcbiAgICBmdW5kaW5naWNvbnM/OiBib29sZWFuO1xuICAgIGJyYW5kaW5nPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJUGF5UGFsRnVuZGluZyB7XG4gICAgYWxsb3dlZDogUGF5UGFsRnVuZGluZ1tdO1xuICAgIGRpc2FsbG93ZWQ6IFBheVBhbEZ1bmRpbmdbXTtcbn1cblxuIiwiaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkRlc3Ryb3ksXG4gICAgU2ltcGxlQ2hhbmdlcyxcbiAgICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaW50ZXJ2YWwsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBQYXlQYWxGdW5kaW5nIH0gZnJvbSAnLi4vbW9kZWxzL3BheXBhbC1mdW5kaW5nJztcbmltcG9ydCB7IFBheVBhbEludGVncmF0aW9uVHlwZSB9IGZyb20gJy4uL21vZGVscy9wYXlwYWwtaW50ZWdyYXRpb24nO1xuaW1wb3J0IHsgSVBheXBhbENsaWVudCwgSVBheVBhbFBheW1lbnRDb21wbGV0ZURhdGEsIFBheVBhbENvbmZpZyB9IGZyb20gJy4uL21vZGVscy9wYXlwYWwtbW9kZWxzJztcblxuLyoqXG4gKiBHbG9iYWwgdmFyaWFibGUgd2hlcmUgUGF5UGFsIGlzIGxvYWRlZCB0b1xuICovXG5kZWNsYXJlIHZhciBwYXlwYWw6IGFueTtcblxuQENvbXBvbmVudCh7XG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgc2VsZWN0b3I6ICduZ3gtcGF5cGFsJyxcbiAgICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgI3BheVBhbFNjcmlwdEVsZW0+PC9kaXY+XG4gICAgPGRpdiAjcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbSBbaWRdPVwicGF5UGFsQnV0dG9uQ29udGFpbmVySWRcIj48L2Rpdj5cbiAgICBgXG59KVxuZXhwb3J0IGNsYXNzIE5neFBheXBhbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyYXRpb24gZm9yIHBheXBhbC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBjb25maWc6IFBheVBhbENvbmZpZztcblxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyBpZiBnbG9iYWwgY29uZmlndXJhdGlvbiAocHJvdmlkZWQgdmlhICdmb3JSb290JykgaXMgdXNlZFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHVzZUdsb2JhbENvbmZpZyA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQ29udGFpbmVyIGZvciBwYXlwYWwgc2NyaXB0XG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgncGF5UGFsU2NyaXB0RWxlbScpIHBheXBhbFNjcmlwdEVsZW06IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGZvciBpbmRpY2F0aW5nIGRlbGF5ZWQgcmVuZGVyZWQgaWYgY29udGFpbmVyIGlzIG5vdCB5ZXQgcmVhZHkgaW4gRE9NXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWdpc3RlclBheVBhbFNjcmlwdFdoZW5Db250YWluZXJJc1JlYWR5ID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBIb2xkcyBjdXJyZW50IGNvbnRhaW5lciBlbGVtZW50XG4gICAgICovXG4gICAgcHJpdmF0ZSBfcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbT86IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgncGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbScpIHNldCBwYXlQYWxCdXR0b25Db250YWluZXJFbGVtKGNvbnRlbnQ6IEVsZW1lbnRSZWYpIHtcbiAgICAgICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0gPSBjb250ZW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9sbGluZyBpbnRlcnZhbCBpZiBwYXlwYWwgc2NyaXB0IGlzIHBlbmRpbmdcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRQb2xsSW50ZXJ2YWwgPSA1MDtcblxuICAgIC8qKlxuICAgICAqIFBvbGxpbmcgd2lsbCBzdG9wIGFmdGVyIHBvbGxpbmcgcmVhY2hlcyB0aGlzIG51bWJlclxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbWF4aW11bVBvbGxXYWl0VGltZSA9IDUwMDA7XG5cbiAgICAvKipcbiAgICAqIE5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSB3aGVyZSBwYXlwYWwgaXMgc3RvcmVkXG4gICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IHBheXBhbFdpbmRvd05hbWUgPSAncGF5cGFsJztcblxuICAgIC8qKlxuICAgICAqIE5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSBpbmRpY2F0aW5nIHRoYXQgc2NyaXB0IHdhcyBpbml0aWF0ZWQgKGFkZGVkIHRvIHBhZ2UpXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXlwYWxXaW5kb3dTY3JpcHRJbml0aWF0ZWQgPSAnbmd4LXBheXBhbC1zY3JpcHQtaW5pdGlhdGVkJztcblxuICAgIC8qKlxuICAgICAqIFBheVBhbCBpbnRlZ3JhdGlvbiBzY3JpcHQgdXJsXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXlwYWxTY3JpcHRVcmwgPSAnaHR0cHM6Ly93d3cucGF5cGFsb2JqZWN0cy5jb20vYXBpL2NoZWNrb3V0LmpzJztcblxuICAgIC8qKlxuICAgICAqIElkIG9mIHRoZSBlbGVtZW50IHdoZXJlIFBheVBhbCBidXR0b24gd2lsbCBiZSByZW5kZXJlZFxuICAgICAqL1xuICAgIHB1YmxpYyBwYXlQYWxCdXR0b25Db250YWluZXJJZD86IHN0cmluZztcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgcGF5UGFsQnV0dG9uQ29udGFpbmVySWRQcmVmaXggPSAnbmd4LXBheXBhbC1idXR0b24tY29udGFpbmVyLSc7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IG5nVW5zdWJzY3JpYmU6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgKSB7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICAvLyBpbml0IHdoZW4gY29uZmlnIG9uY2UgaXRzIGF2YWlsYWJsZVxuICAgICAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFBheVBhbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICAvLyByZWdpc3RlciBzY3JpcHQgaWYgZWxlbWVudCBpcyByZWFkeSBpbiBkb21cbiAgICAgICAgaWYgKHRoaXMucmVnaXN0ZXJQYXlQYWxTY3JpcHRXaGVuQ29udGFpbmVySXNSZWFkeSAmJiB0aGlzLl9wYXlQYWxCdXR0b25Db250YWluZXJFbGVtKSB7XG4gICAgICAgICAgICB0aGlzLnNldHVwU2NyaXB0KCk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyUGF5UGFsU2NyaXB0V2hlbkNvbnRhaW5lcklzUmVhZHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUubmV4dCgpO1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRQYXlQYWwoKTogdm9pZCB7XG4gICAgICAgIC8vIHNldCB1bmlxdWUgcGF5cGFsIGNvbnRhaW5lciBidXR0b24gaWRcbiAgICAgICAgdGhpcy5wYXlQYWxCdXR0b25Db250YWluZXJJZCA9IGAke3RoaXMucGF5UGFsQnV0dG9uQ29udGFpbmVySWRQcmVmaXh9JHt0aGlzLmdldFBzZXVkb1VuaXF1ZU51bWJlcigpfWA7XG4gICAgICAgIC8vIGNoZWNrIGlmIHBheXBhbCB3YXMgYWxyZWFkeSByZWdpc3RlciBhbmQgaWYgc28sIGRvbid0IGFkZCBpdCB0byBwYWdlIGFnYWluXG4gICAgICAgIGlmICghd2luZG93W3RoaXMucGF5cGFsV2luZG93TmFtZV0pIHtcbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHNjcmlwdCBpcyBwZW5kaW5nXG4gICAgICAgICAgICBpZiAod2luZG93W3RoaXMucGF5cGFsV2luZG93U2NyaXB0SW5pdGlhdGVkXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9sbFVudGlsU2NyaXB0QXZhaWxhYmxlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHJlZ2lzdGVyIHNjcmlwdCBhbmQgc2V0IGdsb2JhbCBmbGFnXG4gICAgICAgICAgICAgICAgd2luZG93W3RoaXMucGF5cGFsV2luZG93U2NyaXB0SW5pdGlhdGVkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRQYXlQYWxTY3JpcHRUb1BhZ2UoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8ganVzdCByZWdpc3RlciBwYXltZW50XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVNjcmlwdFJlZ2lzdGVyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFBzZXVkb1VuaXF1ZU51bWJlcigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUoKS52YWx1ZU9mKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCB3aGVuIHRoZXJlIGFyZSBtdWx0aXBsZSBwYXlwYWwgY29tcG9uZW50cyBvbiB0aGUgc2FtZSBwYWdlIGJlYWN1c2Ugb25seSAxIG9mIHRoZW1cbiAgICAgKiBtYXkgcmVnaXN0ZXIgcGF5cGFsIHNjcmlwdC4gVGhlIG90aGVyIGhhcyB0byBiZSBwb2xsaW5nIHVudGlsIHBheXBhbCBpcyBhdmFpbGFibGUgb3IgY29tcG9uZW50IGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHByaXZhdGUgcG9sbFVudGlsU2NyaXB0QXZhaWxhYmxlKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBvYnMgPSBpbnRlcnZhbCh0aGlzLmRlZmF1bHRQb2xsSW50ZXJ2YWwpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSxcbiAgICAgICAgICAgICAgICBtYXAoKHgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHggPj0gdGhpcy5tYXhpbXVtUG9sbFdhaXRUaW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFBheVBhbCBzY3JpcHQgd2FzIG5vdCBsb2FkZWQgYWZ0ZXIgJyR7dGhpcy5tYXhpbXVtUG9sbFdhaXRUaW1lfScgbWF4aW11bSBwb2xsaW5nIHRpbWUuYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIHBheXBhbCBzY3JpcHQgZXhpc3RzXG4gICAgICAgICAgICAgICAgICAgIGlmICh3aW5kb3dbdGhpcy5wYXlwYWxXaW5kb3dOYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVnaXN0ZXIgc2NyaXB0XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVNjcmlwdFJlZ2lzdGVyaW5nKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0b3AgZXhlY3V0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRQYXlQYWxTY3JpcHRUb1BhZ2UoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICBzY3JpcHQuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIHNjcmlwdC5zcmMgPSB0aGlzLnBheXBhbFNjcmlwdFVybDtcbiAgICAgICAgc2NyaXB0Lm9ubG9hZCA9ICgpID0+IHRoaXMuaGFuZGxlU2NyaXB0UmVnaXN0ZXJpbmcoKTtcbiAgICAgICAgc2NyaXB0LmFzeW5jID0gdHJ1ZTtcbiAgICAgICAgc2NyaXB0LmRlZmVyID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLnBheXBhbFNjcmlwdEVsZW0ubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlU2NyaXB0UmVnaXN0ZXJpbmcoKTogdm9pZCB7XG4gICAgICAgIC8vIGNoZWNrIGlmIGNvbnRhaW5lciB3aXRoIHJlcXVlc3RlZCBpZCBleGlzdHNcbiAgICAgICAgLy8gdGhpcyBpcyBoZXJlIGJlY2F1c2UgZHluYW1pY2FsbHkgc3dpdGNoaW5nIGJldHdlZW4gY29tcG9uZW50cyB3b3VsZCBjYXVzZSBQYXlQYWwgdG9cbiAgICAgICAgLy8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIGNvbnRhaW5lciBhbHJlYWR5IGV4aXN0ZWQgYmVmb3JlXG4gICAgICAgIGlmICh0aGlzLl9wYXlQYWxCdXR0b25Db250YWluZXJFbGVtICYmIHRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0ubmF0aXZlRWxlbWVudCAmJlxuICAgICAgICAgICAgdGhpcy5fcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbS5uYXRpdmVFbGVtZW50LmlkID09PSB0aGlzLnBheVBhbEJ1dHRvbkNvbnRhaW5lcklkKSB7XG4gICAgICAgICAgICAvLyBjb250YWluZXIgaXMgcmVhZHksIHNldHVwIHNjcmlwdCByaWdodCBhd2F5XG4gICAgICAgICAgICB0aGlzLnNldHVwU2NyaXB0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb250YWluZXIgaXMgbm90IHJlYWR5LCBkZWxheSByZWdpc3RlcmluZyB1bnRpbCBpdCBpc1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlclBheVBhbFNjcmlwdFdoZW5Db250YWluZXJJc1JlYWR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0dXBTY3JpcHQoKTogdm9pZCB7XG4gICAgICAgIC8vIGZpcnN0IGNsZWFyIGNvbnRhaW5lclxuICAgICAgICBpZiAoIXRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0pIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKGBDYW5ub3Qgc2V0dXAgc2NyaXB0IGJlY2F1c2UgcGF5cGFsIGJ1dHRvbiBjb250YWluZXIgd2l0aCBpZCAnJHt0aGlzLnBheVBhbEJ1dHRvbkNvbnRhaW5lcklkfScgaXMgbm90IHlldCByZWFkeWApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbS5uYXRpdmVFbGVtZW50LmlubmVySFRNTCA9ICcnO1xuXG4gICAgICAgIGlmICghd2luZG93W3RoaXMucGF5cGFsV2luZG93TmFtZV0pIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdQYXlQYWwgc2NyaXB0IGlzIG5vdCBhdmFpbGFibGUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbmRlciBQYXlQYWwgYnV0dG9uIGFzIHBlciB0aGVpciBkb2NzIGF0XG4gICAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLnBheXBhbC5jb20vZG9jcy9pbnRlZ3JhdGlvbi9kaXJlY3QvZXhwcmVzcy1jaGVja291dC9pbnRlZ3JhdGlvbi1qc3Y0L2FkZC1wYXlwYWwtYnV0dG9uL1xuICAgICAgICB3aW5kb3dbdGhpcy5wYXlwYWxXaW5kb3dOYW1lXS5CdXR0b24ucmVuZGVyKHtcbiAgICAgICAgICAgIC8vIHNldCBlbnZpcm9ubWVudFxuICAgICAgICAgICAgZW52OiB0aGlzLmNvbmZpZy5lbnZpcm9ubWVudC50b1N0cmluZygpLFxuXG4gICAgICAgICAgICAvLyBTaG93IHRoZSBidXllciBhICdQYXkgTm93JyBidXR0b24gaW4gdGhlIGNoZWNrb3V0IGZsb3dcbiAgICAgICAgICAgIGNvbW1pdDogdGhpcy5jb25maWcuY29tbWl0LFxuXG4gICAgICAgICAgICAvLyBpbml0IGNsaWVudCBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb25cbiAgICAgICAgICAgIGNsaWVudDogdGhpcy5nZXRDbGllbnQoKSxcblxuICAgICAgICAgICAgLy8gc2V0IGJ1dHRvbiBjb25maWcgaWYgYXZhaWxhYmxlXG4gICAgICAgICAgICBzdHlsZTogdGhpcy5jb25maWcuYnV0dG9uLFxuXG4gICAgICAgICAgICAvLyBzZXQgZnVuZGluZyBpZiBhdmFpbGFibGVcbiAgICAgICAgICAgIGZ1bmRpbmc6IHRoaXMuZ2V0RnVuZGluZygpLFxuXG4gICAgICAgICAgICAvLyBwYXltZW50KCkgaXMgY2FsbGVkIHdoZW4gdGhlIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgICAgICAgICBwYXltZW50OiAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pbnRlZ3JhdGlvblR5cGUgPT09IFBheVBhbEludGVncmF0aW9uVHlwZS5TZXJ2ZXJTaWRlUkVTVCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjbGllbnQgbmVlZHMgdG8gY3JlYXRlIHBheW1lbnQgb24gc2VydmVyIHNpZGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5wYXltZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcihgWW91IG5lZWQgc2V0IHVwIGEgY3JlYXRlIHBheW1lbnQgbWV0aG9kIGFuZCByZXR1cm5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXlQYWwncyBwYXltZW50IGlkIHdoZW4gdXNpbmcgc2VydmVyIHNpZGUgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFBheXBhbCBleHBlY3RzIHByb21pc2Ugd2l0aCBwYXltZW50IGlkIChzdHJpbmcpIHRvIGJlIHJldHVybmVkXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5wYXltZW50KCkudG9Qcm9taXNlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKHBheW1lbnRJZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBheW1lbnRJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pbnRlZ3JhdGlvblR5cGUgPT09IFBheVBhbEludGVncmF0aW9uVHlwZS5DbGllbnRTaWRlUkVTVCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnRyYW5zYWN0aW9ucyB8fCAhQXJyYXkuaXNBcnJheSh0aGlzLmNvbmZpZy50cmFuc2FjdGlvbnMpIHx8IHRoaXMuY29uZmlnLnRyYW5zYWN0aW9ucy5sZW5ndGggPD0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoYFlvdSBuZWVkIHRvIHByb3ZpZGUgYXQgbGVhc3QgMSB0cmFuc2FjdGlvbiBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVyaWVuY2VDb25maWcgPSB0aGlzLmNvbmZpZy5leHBlcmllbmNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWN0aW9ucy5wYXltZW50LmNyZWF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxsb3cgdXNlciB0byBzcGVjaWZpZnkgaW50ZW50LCBlbHNlIHVzZSBkZWZhdWx0ICdzYWxlJy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6IHRoaXMuY29uZmlnLmludGVudCA/IHRoaXMuY29uZmlnLmludGVudCA6ICdzYWxlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbnM6IHRoaXMuY29uZmlnLnRyYW5zYWN0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVyaWVuY2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9maWVsZHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9fc2hpcHBpbmc6IChleHBlcmllbmNlQ29uZmlnICYmIGV4cGVyaWVuY2VDb25maWcubm9TaGlwcGluZykgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlc2VudGF0aW9uOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyYW5kX25hbWU6IChleHBlcmllbmNlQ29uZmlnICYmIGV4cGVyaWVuY2VDb25maWcuYnJhbmROYW1lKSA/IGV4cGVyaWVuY2VDb25maWcuYnJhbmROYW1lIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nb19pbWFnZTogKGV4cGVyaWVuY2VDb25maWcgJiYgZXhwZXJpZW5jZUNvbmZpZy5sb2dvSW1hZ2UpID8gZXhwZXJpZW5jZUNvbmZpZy5sb2dvSW1hZ2UgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGVfY29kZTogKGV4cGVyaWVuY2VDb25maWcgJiYgZXhwZXJpZW5jZUNvbmZpZy5sb2NhbGVDb2RlKSA/IGV4cGVyaWVuY2VDb25maWcubG9jYWxlQ29kZSA6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8vIG9uQXV0aG9yaXplKCkgaXMgY2FsbGVkIHdoZW4gdGhlIGJ1eWVyIGFwcHJvdmVzIHRoZSBwYXltZW50XG4gICAgICAgICAgICBvbkF1dGhvcml6ZTogKGRhdGE6IElQYXlQYWxQYXltZW50Q29tcGxldGVEYXRhLCBhY3Rpb25zOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcuaW50ZWdyYXRpb25UeXBlID09PSBQYXlQYWxJbnRlZ3JhdGlvblR5cGUuU2VydmVyU2lkZVJFU1QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xpZW50IG5lZWRzIHRvIHNlcnZlciB0byBleGVjdXRlIHRoZSBwYXltZW50XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcub25BdXRob3JpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3UgbmVlZCBzZXQgdXAgYW4gZXhlY3V0ZSBtZXRob2Qgd2hlbiB1c2luZyBzZXJ2ZXIgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUGF5cGFsIGV4cGVjdHMgcHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcub25BdXRob3JpemUoZGF0YSwgYWN0aW9ucykudG9Qcm9taXNlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmludGVncmF0aW9uVHlwZSA9PT0gUGF5UGFsSW50ZWdyYXRpb25UeXBlLkNsaWVudFNpZGVSRVNUKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYSBjYWxsIHRvIHRoZSBSRVNUIGFwaSB0byBleGVjdXRlIHRoZSBwYXltZW50XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3Rpb25zLnBheW1lbnQuZXhlY3V0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5vblBheW1lbnRDb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3Ugc2hvdWxkIHByb3ZpZGUgc29tZSBjYWxsYmFjayB3aGVuIHBheW1lbnQgaXMgZmluaXNoZWQgd2hlbiB1c2luZyBjbGllbnQgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcub25QYXltZW50Q29tcGxldGUoZGF0YSwgYWN0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRXJyb3I6IChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcub25FcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5vbkVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25DYW5jZWw6IChkYXRhLCBhY3Rpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm9uQ2FuY2VsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm9uQ2FuY2VsKGRhdGEsIGFjdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm9uQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcub25DbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2YWxpZGF0ZTogKGFjdGlvbnMpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcudmFsaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcudmFsaWRhdGUoYWN0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCBgIyR7dGhpcy5wYXlQYWxCdXR0b25Db250YWluZXJJZH1gKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENsaWVudCgpOiBJUGF5cGFsQ2xpZW50IHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmludGVncmF0aW9uVHlwZSA9PT0gUGF5UGFsSW50ZWdyYXRpb25UeXBlLkNsaWVudFNpZGVSRVNUKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmNsaWVudCkge1xuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3UgbmVlZCB0byBzZXR1cCBjbGllbnQgaW5mb3JtYXRpb24gd2hlbiB1c2luZyBjbGllbnQgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHByb2R1Y3Rpb246IHRoaXMuY29uZmlnLmNsaWVudC5wcm9kdWN0aW9uLFxuICAgICAgICAgICAgICAgIHNhbmRib3g6IHRoaXMuY29uZmlnLmNsaWVudC5zYW5kYm94XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEZ1bmRpbmcoKToge1xuICAgICAgICBhbGxvd2VkOiBhbnlbXSxcbiAgICAgICAgZGlzYWxsb3dlZDogYW55W11cbiAgICB9IHwgdW5kZWZpbmVkIHtcbiAgICAgICAgLy8gcmVzb2x2ZSBmdW5kaW5nIHRvIHVzZSBwYXlwYWwncyBwcm9wZXJ0aWVzXG4gICAgICAgIGlmICghdGhpcy5jb25maWcuZnVuZGluZykge1xuICAgICAgICAgICAgLy8gbm8gZnVuZGluZyBwcm92aWRlZFxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFsbG93ZWQ6IGFueVtdID0gW107XG4gICAgICAgIGNvbnN0IGRpc2FsbG93ZWQ6IGFueVtdID0gW107XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmZ1bmRpbmcuYWxsb3dlZCkge1xuICAgICAgICAgICAgdGhpcy5jb25maWcuZnVuZGluZy5hbGxvd2VkLmZvckVhY2godHlwZSA9PiB7XG4gICAgICAgICAgICAgICAgYWxsb3dlZC5wdXNoKHRoaXMubWFwRnVuZGluZ1R5cGUodHlwZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jb25maWcuZnVuZGluZy5kaXNhbGxvd2VkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5mdW5kaW5nLmRpc2FsbG93ZWQuZm9yRWFjaCh0eXBlID0+IHtcbiAgICAgICAgICAgICAgICBkaXNhbGxvd2VkLnB1c2godGhpcy5tYXBGdW5kaW5nVHlwZSh0eXBlKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhbGxvd2VkOiBhbGxvd2VkLFxuICAgICAgICAgICAgZGlzYWxsb3dlZDogZGlzYWxsb3dlZFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFwRnVuZGluZ1R5cGUodHlwZTogUGF5UGFsRnVuZGluZyk6IGFueSB7XG4gICAgICAgIGlmICh0eXBlID09PSBQYXlQYWxGdW5kaW5nLkNhcmQpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXlwYWwuRlVORElORy5DQVJEO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSBQYXlQYWxGdW5kaW5nLkNyZWRpdCkge1xuICAgICAgICAgICAgcmV0dXJuIHBheXBhbC5GVU5ESU5HLkNSRURJVDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gUGF5UGFsRnVuZGluZy5FbHYpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXlwYWwuRlVORElORy5FTFY7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgRXJyb3IoYFVuc3VwcG9ydGVkIGZ1bmRpbmcgdHlwZSAnJHt0eXBlfSdgKTtcbiAgICB9XG59XG5cbiIsImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IE5neFBheXBhbENvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9wYXlwYWwtY29tcG9uZW50JztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtcbiAgICBOZ3hQYXlwYWxDb21wb25lbnQsXG4gIF0sXG4gIGV4cG9ydHM6IFtcbiAgICBOZ3hQYXlwYWxDb21wb25lbnQsXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4UGF5UGFsTW9kdWxlIHtcbn1cblxuXG4iLCJleHBvcnQgZW51bSBQYXlQYWxFbnZpcm9ubWVudCB7XG4gICAgU2FuZGJveCA9ICdzYW5kYm94JyxcbiAgICBQcm9kdWN0aW9uID0gJ3Byb2R1Y3Rpb24nXG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztJQUNJLE9BQUk7SUFDSixTQUFNO0lBQ04sTUFBRzs7Ozs7Ozs7Ozs7O0lDRkgsaUJBQWM7SUFDZCxpQkFBYzs7Ozs7Ozs7O0FDSWxCLE1BQWEsWUFBWTs7Ozs7O0lBd0VyQixZQUlXLGVBQXNDLEVBSXRDLFdBQThCLEVBQ3JDLE1BZ0JDO1FBckJNLG9CQUFlLEdBQWYsZUFBZSxDQUF1QjtRQUl0QyxnQkFBVyxHQUFYLFdBQVcsQ0FBbUI7Ozs7UUEzRWxDLFdBQU0sR0FBRyxJQUFJLENBQUM7Ozs7UUFLZCxXQUFNLEdBQUcsTUFBTSxDQUFDO1FBd0ZuQixNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztLQUMvQjtDQUNKOzs7Ozs7QUMxR0QsTUErQmEsa0JBQWtCO0lBa0UzQjs7OztRQXhEUyxvQkFBZSxHQUFHLEtBQUssQ0FBQzs7OztRQVV6Qiw2Q0FBd0MsR0FBRyxLQUFLLENBQUM7Ozs7UUFleEMsd0JBQW1CLEdBQUcsRUFBRSxDQUFDOzs7O1FBS3pCLHdCQUFtQixHQUFHLElBQUksQ0FBQzs7OztRQUszQixxQkFBZ0IsR0FBRyxRQUFRLENBQUM7Ozs7UUFLNUIsZ0NBQTJCLEdBQUcsNkJBQTZCLENBQUM7Ozs7UUFLNUQsb0JBQWUsR0FBRywrQ0FBK0MsQ0FBQztRQU9sRSxrQ0FBNkIsR0FBRyw4QkFBOEIsQ0FBQztRQUUvRCxrQkFBYSxHQUFrQixJQUFJLE9BQU8sRUFBUSxDQUFDO0tBSW5FOzs7OztJQTFDRCxJQUE0Qyx5QkFBeUIsQ0FBQyxPQUFtQjtRQUNyRixJQUFJLE9BQU8sRUFBRTtZQUNULElBQUksQ0FBQywwQkFBMEIsR0FBRyxPQUFPLENBQUM7U0FDN0M7S0FDSjs7Ozs7SUF3Q0QsV0FBVyxDQUFDLE9BQXNCOztRQUU5QixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDYixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDckI7S0FDSjs7OztJQUVELGVBQWU7O1FBRVgsSUFBSSxJQUFJLENBQUMsd0NBQXdDLElBQUksSUFBSSxDQUFDLDBCQUEwQixFQUFFO1lBQ2xGLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsd0NBQXdDLEdBQUcsS0FBSyxDQUFDO1NBQ3pEO0tBQ0o7Ozs7SUFFRCxXQUFXO1FBQ1AsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQ2pDOzs7O0lBRU8sVUFBVTs7UUFFZCxJQUFJLENBQUMsdUJBQXVCLEdBQUcsR0FBRyxJQUFJLENBQUMsNkJBQTZCLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLEVBQUUsQ0FBQzs7UUFFdEcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTs7WUFFaEMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUNuRCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQzthQUNuQztpQkFBTTs7Z0JBRUgsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLElBQUksQ0FBQztnQkFDaEQsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7YUFDaEM7U0FFSjthQUFNOztZQUVILElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1NBQ2xDO0tBQ0o7Ozs7SUFFTyxxQkFBcUI7UUFDekIsT0FBTyxJQUFJLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQy9COzs7Ozs7SUFNTyx3QkFBd0I7O2NBQ3RCLEdBQUcsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDO2FBQ3pDLElBQUksQ0FDRCxTQUFTLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUM3QixHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ0YsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFO2dCQUMvQixPQUFPLENBQUMsSUFBSSxDQUFDLHVDQUF1QyxJQUFJLENBQUMsbUJBQW1CLHlCQUF5QixDQUFDLENBQUM7Z0JBQ3ZHLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbEIsT0FBTzthQUNWOztZQUdELElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFOztnQkFFL0IsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7O2dCQUcvQixHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7YUFDckI7U0FDSixDQUFDLENBQ0w7YUFDQSxTQUFTLEVBQUU7S0FDbkI7Ozs7SUFFTyxxQkFBcUI7O2NBQ25CLE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQztRQUMvQyxNQUFNLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUN0QixNQUFNLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDbEMsTUFBTSxDQUFDLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ3JELE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBRXBCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzNEOzs7O0lBRU8sdUJBQXVCOzs7O1FBSTNCLElBQUksSUFBSSxDQUFDLDBCQUEwQixJQUFJLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxhQUFhO1lBQ2hGLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxhQUFhLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyx1QkFBdUIsRUFBRTs7WUFFbkYsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3RCO2FBQU07O1lBRUgsSUFBSSxDQUFDLHdDQUF3QyxHQUFHLElBQUksQ0FBQztTQUN4RDtLQUNKOzs7O0lBRU8sV0FBVzs7UUFFZixJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixFQUFFO1lBQ2xDLE1BQU0sS0FBSyxDQUFDLGdFQUFnRSxJQUFJLENBQUMsdUJBQXVCLG9CQUFvQixDQUFDLENBQUM7U0FDakk7UUFFRCxJQUFJLENBQUMsMEJBQTBCLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFFN0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtZQUNoQyxNQUFNLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1NBQ2pEOzs7UUFJRCxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQzs7WUFFeEMsR0FBRyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRTs7WUFHdkMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTs7WUFHMUIsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUU7O1lBR3hCLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU07O1lBR3pCLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFOztZQUcxQixPQUFPLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTztnQkFDbkIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsS0FBSyxxQkFBcUIsQ0FBQyxjQUFjLEVBQUU7O29CQUV0RSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7d0JBQ3RCLE1BQU0sS0FBSyxDQUFDO21GQUMrQyxDQUFDLENBQUM7cUJBQ2hFOztvQkFHRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsU0FBUyxFQUFFO3lCQUNuQyxJQUFJLENBQUMsU0FBUzt3QkFDWCxPQUFPLFNBQVMsQ0FBQztxQkFDcEIsQ0FBQyxDQUFDO2lCQUNWO2dCQUVELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEtBQUsscUJBQXFCLENBQUMsY0FBYyxFQUFFO29CQUN0RSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRTt3QkFDL0csTUFBTSxLQUFLLENBQUMsd0VBQXdFLENBQUMsQ0FBQztxQkFDekY7OzBCQUVLLGdCQUFnQixHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVTtvQkFDL0MsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQzt3QkFDMUIsT0FBTyxFQUFFOzs0QkFFTCxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTTs0QkFDeEQsWUFBWSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWTt5QkFDekM7d0JBQ0QsVUFBVSxFQUFFOzRCQUNSLFlBQVksRUFBRTtnQ0FDVixXQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxVQUFVLElBQUksQ0FBQyxHQUFHLENBQUM7NkJBQ3pFOzRCQUNELFlBQVksRUFBRTtnQ0FDVixVQUFVLEVBQUUsQ0FBQyxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxTQUFTLElBQUksZ0JBQWdCLENBQUMsU0FBUyxHQUFHLElBQUk7Z0NBQ2hHLFVBQVUsRUFBRSxDQUFDLGdCQUFnQixJQUFJLGdCQUFnQixDQUFDLFNBQVMsSUFBSSxnQkFBZ0IsQ0FBQyxTQUFTLEdBQUcsSUFBSTtnQ0FDaEcsV0FBVyxFQUFFLENBQUMsZ0JBQWdCLElBQUksZ0JBQWdCLENBQUMsVUFBVSxJQUFJLGdCQUFnQixDQUFDLFVBQVUsR0FBRyxJQUFJOzZCQUN0Rzt5QkFDSjtxQkFDSixDQUFDLENBQUM7aUJBQ047YUFDSjs7WUFHRCxXQUFXLEVBQUUsQ0FBQyxJQUFnQyxFQUFFLE9BQVk7Z0JBQ3hELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEtBQUsscUJBQXFCLENBQUMsY0FBYyxFQUFFOztvQkFFdEUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFO3dCQUMxQixNQUFNLEtBQUssQ0FBQyxzRUFBc0UsQ0FBQyxDQUFDO3FCQUN2Rjs7b0JBR0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7aUJBQzdEO2dCQUVELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEtBQUsscUJBQXFCLENBQUMsY0FBYyxFQUFFOztvQkFFdEUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQzt3QkFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUU7NEJBQ2hDLE1BQU0sS0FBSyxDQUFDLDhGQUE4RixDQUFDLENBQUM7eUJBQy9HO3dCQUNELElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO3FCQUNoRCxDQUFDLENBQUM7aUJBQ047YUFDSjtZQUVELE9BQU8sRUFBRSxDQUFDLEdBQUc7Z0JBQ1QsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtvQkFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7aUJBQzVCO2FBQ0o7WUFFRCxRQUFRLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTztnQkFDcEIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtvQkFDdEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO2lCQUN2QzthQUNKO1lBQ0QsT0FBTyxFQUFFO2dCQUNMLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7b0JBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7aUJBQ3pCO2FBQ0o7WUFDRCxRQUFRLEVBQUUsQ0FBQyxPQUFPO2dCQUNkLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7b0JBQ3RCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUNqQzthQUNKO1NBQ0osRUFBRSxJQUFJLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLENBQUM7S0FDMUM7Ozs7SUFFTyxTQUFTO1FBQ2IsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsS0FBSyxxQkFBcUIsQ0FBQyxjQUFjLEVBQUU7WUFDdEUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO2dCQUNyQixNQUFNLEtBQUssQ0FBQyx5RUFBeUUsQ0FBQyxDQUFDO2FBQzFGO1lBRUQsT0FBTztnQkFDSCxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVTtnQkFDekMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU87YUFDdEMsQ0FBQztTQUNMO1FBRUQsT0FBTyxTQUFTLENBQUM7S0FDcEI7Ozs7SUFFTyxVQUFVOztRQUtkLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTs7WUFFdEIsT0FBTyxTQUFTLENBQUM7U0FDcEI7O2NBRUssT0FBTyxHQUFVLEVBQUU7O2NBQ25CLFVBQVUsR0FBVSxFQUFFO1FBRTVCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFO1lBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSTtnQkFDcEMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7YUFDM0MsQ0FBQyxDQUFDO1NBQ047UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRTtZQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUk7Z0JBQ3ZDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO2FBQzlDLENBQUMsQ0FBQztTQUNOO1FBRUQsT0FBTztZQUNILE9BQU8sRUFBRSxPQUFPO1lBQ2hCLFVBQVUsRUFBRSxVQUFVO1NBQ3pCLENBQUM7S0FDTDs7Ozs7SUFFTyxjQUFjLENBQUMsSUFBbUI7UUFDdEMsSUFBSSxJQUFJLEtBQUssYUFBYSxDQUFDLElBQUksRUFBRTtZQUM3QixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO1NBQzlCO1FBQ0QsSUFBSSxJQUFJLEtBQUssYUFBYSxDQUFDLE1BQU0sRUFBRTtZQUMvQixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1NBQ2hDO1FBQ0QsSUFBSSxJQUFJLEtBQUssYUFBYSxDQUFDLEdBQUcsRUFBRTtZQUM1QixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDO1NBQzdCO1FBQ0QsTUFBTSxLQUFLLENBQUMsNkJBQTZCLElBQUksR0FBRyxDQUFDLENBQUM7S0FDckQ7OztZQS9WSixTQUFTLFNBQUM7Z0JBQ1AsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07Z0JBQy9DLFFBQVEsRUFBRSxZQUFZO2dCQUN0QixRQUFRLEVBQUU7OztLQUdUO2FBQ0o7Ozs7O3FCQU1JLEtBQUs7OEJBS0wsS0FBSzsrQkFLTCxTQUFTLFNBQUMsa0JBQWtCO3dDQVc1QixTQUFTLFNBQUMsMkJBQTJCOzs7Ozs7O0FDekQxQyxNQWNhLGVBQWU7OztZQVYzQixRQUFRLFNBQUM7Z0JBQ1IsT0FBTyxFQUFFLEVBQ1I7Z0JBQ0QsWUFBWSxFQUFFO29CQUNaLGtCQUFrQjtpQkFDbkI7Z0JBQ0QsT0FBTyxFQUFFO29CQUNQLGtCQUFrQjtpQkFDbkI7YUFDRjs7Ozs7Ozs7O0lDWkcsU0FBVSxTQUFTO0lBQ25CLFlBQWEsWUFBWTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==