@hxui/angular
Version:
* * *
563 lines (538 loc) • 57.9 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { ITabularConfig } from './tabular-config.interface';
import { ActionConfigRouteType } from './actions-config.interface';
import { TabularSortByService, SortByDirection } from './tabular-sort-by.service';
import { TabularConfig } from './tabular.config';
import { TabularSize } from './tabular-size.enum';
import { TabularColumnTypes } from './tabular-column.interface';
import { Context } from '../enums';
import * as _ from 'lodash';
export class TabularComponent {
/**
* @param {?} conf
* @param {?} sortByService
*/
constructor(conf, sortByService) {
this.conf = conf;
this.sortByService = sortByService;
/**
* Event fired when refresh is called.
* Host should refresh data of input.
*/
this.refresh = new EventEmitter();
/**
* Event fired when a row is clicked.
*/
this.rowClick = new EventEmitter();
/**
* Event fired when a column is sorted
*/
this.onSort = new EventEmitter();
this.oldRows = [];
this.pagedItems = [];
this.TabularColumnTypes = TabularColumnTypes;
this.TabularSize = TabularSize;
this.ActionConfigRouteType = ActionConfigRouteType;
this.selectAll = false;
this.Context = Context;
this.SortByDirection = SortByDirection;
this.toggleSelectAll = ($event) => {
for (let i = 0; i < this.rows.length; i++) {
this.rows[i].checked = this.selectAll;
}
};
this.toggleIndividualSelect = ($event) => {
/** @type {?} */
let count = 0;
for (let i = 0; i < this.rows.length; i++) {
if (this.rows[i].checked) {
count++;
}
}
this.selectAll = (this.rows.length === count);
};
Object.assign(this, conf);
}
/**
* Tabular configuration
* IPaginationInstance, ISearchConfig
* @return {?}
*/
get config() {
return this._config;
}
/**
* @param {?} c
* @return {?}
*/
set config(c) {
if (!c.sortBy) {
c.sortBy = [];
}
this._config = c;
}
/**
* The function to call when a action item is clicked *
* @return {?}
*/
get callback() {
return this._callback;
}
/**
* @param {?} Fn
* @return {?}
*/
set callback(Fn) {
this._callback = Fn;
}
/**
* Search term is used in the simple search pipe
* Array of objects: *ngFor="#row of rows | simpleSearch : 'the search term'"
* @return {?}
*/
get searchTerm() {
return this._searchTerm;
}
/**
* @param {?} term
* @return {?}
*/
set searchTerm(term) {
this._searchTerm = term;
}
/**
* @return {?}
*/
ngOnInit() {
}
/**
* @return {?}
*/
ngDoCheck() {
if (!_.isEqual(this.rows, this.oldRows)) {
this.oldRows = _.cloneDeep(this.rows);
this.orderByData(false);
}
}
/**
* Calls the parsed callback with optional arguments
* @param {?} event
* @param {?} cb
* @return {?}
*/
executeCallback(event, cb) {
if (cb.length) {
if (cb.length === 1) { // if callback has no arguments
cb[0]();
}
else { // if callback has 1 or more arguments
// if callback has 1 or more arguments
/** @type {?} */
const args = [];
for (let i = 1; i < cb.length; i++) {
args.push(cb[i]);
}
cb[0].apply(this, args);
}
}
}
/**
* @param {?=} $event
* @return {?}
*/
setPage($event = {
page: this.config.pagination.currentPage,
itemsPerPage: this.config.pagination.itemsPerPage
}) {
this.config.pagination.currentPage = $event.page;
// calculate start and end page item indexes
/** @type {?} */
const startIndex = (this.config.pagination.currentPage - 1) * this.config.pagination.itemsPerPage;
/** @type {?} */
const endIndex = Math.min(startIndex + this.config.pagination.itemsPerPage - 1, this.totalItemCount - 1);
this.pagedItems = this.rows.slice(startIndex, endIndex + 1);
}
/**
* Get the action tooltip if it exists
* @param {?} action
* @return {?}
*/
getActionTooltip(action) {
return (action && action.disabledConfig) ? action.disabledConfig.tooltip : '';
}
/**
* @param {?} action
* @return {?}
*/
getActionDisabledState(action) {
return (action && action.disabledConfig) ? action.disabledConfig.disabled : false;
}
/**
* Handles the column header click event for sorting.
* Sort order is Descending, Ascending followed by None.
* @param {?} key
* @param {?} type
* @return {?}
*/
onSortClickHandler(key, type) {
/** @type {?} */
const findPropInSortList = this.config.sortBy.filter((prop) => { return (prop.property === key); });
if (findPropInSortList.length) {
/** @type {?} */
const prop = findPropInSortList[0];
/** @type {?} */
const index = this.config.sortBy.findIndex(x => x === prop);
if (prop.direction === SortByDirection.None) {
prop.direction = SortByDirection.Descending;
}
else if (prop.direction === SortByDirection.Descending) {
prop.direction = SortByDirection.Ascending;
}
else if (prop.direction === SortByDirection.Ascending) {
if (index > -1) {
this.config.sortBy.splice(index, 1);
}
}
}
else {
if (!this.config.multiSorting) {
this.config.sortBy = [];
}
this.config.sortBy.push({ property: key, direction: SortByDirection.Descending, type: type });
}
this.orderByData(true);
return false;
}
/**
* @param {?} key
* @param {?} direction
* @return {?}
*/
isColumnSorted(key, direction) {
/** @type {?} */
const findPropInSortList = this.config.sortBy.filter((prop) => { return (prop.property === key && prop.direction === direction); });
return (findPropInSortList.length > 0);
}
/**
* Handles the row click event.
* @param {?} $event
* @param {?} data
* @return {?}
*/
onRowClickHandler($event, data) {
/** @type {?} */
const el = $event.target;
if (this.config.clickableRows) {
if (el.parentElement.tagName === 'BUTTON' ||
el.tagName === 'BUTTON' ||
el.parentElement.classList.contains('hx-checkbox-control')) {
return;
}
this.rowClick.emit(data);
}
}
/**
* @param {?} emitSortEvent
* @return {?}
*/
orderByData(emitSortEvent) {
if (this.config.sortBy.length > 0) {
if (!this.config.remoteSorting) {
this.rows = [...this.rows]; // Required as array-sort-by mutates the original array
this.sortByService.sortBy(this.rows, this.config.sortBy);
}
}
if (emitSortEvent) {
this.onSort.emit(this.config.sortBy);
}
this.setPage();
}
/**
* @return {?}
*/
get totalItemCount() {
return this.rows.length;
}
/**
* Helper to determine if tabular instance is in small mode
* @return {?}
*/
isSmall() {
return (this.config.size === TabularSize.Small);
}
/**
* @param {?} colData
* @return {?}
*/
hasValidBadgeTypeParams(colData) {
if (colData) {
if (typeof colData.label !== 'undefined') {
return true;
}
else {
console.error('Record for column type badge is invalid, make sure you have the right type. ITabularColumnTypeBadge', { columnValue: colData });
}
}
return false;
}
/**
* @param {?} colData
* @return {?}
*/
hasValidIconTypeParams(colData) {
/** @type {?} */
let hasError = false;
if (colData) {
if (typeof colData.icon !== 'undefined') {
if (typeof colData.tooltip.config !== 'undefined' && typeof colData.tooltip.content !== 'undefined') {
if (typeof colData.tooltip.config.context !== 'undefined' || typeof colData.tooltip.config.placement !== 'undefined') {
return true;
}
else {
hasError = true;
}
}
else {
hasError = true;
}
}
else {
hasError = true;
}
}
if (hasError) {
console.error('Record for column type icon is invalid, make sure you have the right type. ITabularColumnTypeIcon', { columnValue: colData });
}
return false;
}
/**
* @param {?} colData
* @return {?}
*/
getTooltipContext(colData) {
return (!this.hasValidIconTypeParams(colData)) ? colData.tooltip.config.context : Context.None;
}
/**
* @param {?} action
* @return {?}
*/
hasChildren(action) {
return (action.children && action.children.length > 0);
}
/**
* @param {?} index
* @param {?} action
* @return {?}
*/
trackByFn(index, action) {
return index; // or action.id
}
}
TabularComponent.decorators = [
{ type: Component, args: [{
selector: 'hxa-tabular',
template: `<table class="tabular hx-table is-striped {{config.cssClass}}"
[class.is-hover]="config.clickableRows"
[class.is-narrow]="config.size === TabularSize.Small"
[class.has-sticky-header]="config.stickyHeader">
<thead>
<tr>
<th *ngFor="let col of columns" class="{{col.cssClass}} tabular__{{col.label}}" [ngClass]="{'tabular__checkboxes': col.dataType === TabularColumnTypes.Checkbox, 'tabular__sortable': col.sortable}">
<!-- sortable column -->
<a class="tabular__sorter" href="#" *ngIf="col.sortable && col.dataType != TabularColumnTypes.Checkbox" (click)="onSortClickHandler(col.id, col.dataType)">{{col.label}} <i class="hx-icon icon-arrow-up is-small" [class.icon-arrow-up]="isColumnSorted(col.id, SortByDirection.Ascending)" [class.icon-arrow-down]="isColumnSorted(col.id, SortByDirection.Descending)" *ngIf="isColumnSorted(col.id, SortByDirection.Descending) || isColumnSorted(col.id, SortByDirection.Ascending)"></i></a>
<!-- non sortable column -->
<span *ngIf="!col.sortable && col.dataType !== TabularColumnTypes.Checkbox">{{col.label}}</span>
<!-- checkbox column -->
<div *ngIf="col.dataType === TabularColumnTypes.Checkbox" class="hx-checkbox-control">
<input id="selectAll" name="selectAll" type="checkbox" class="hx-checkbox" (change)="toggleSelectAll($event)" title="Select All" [(ngModel)]="selectAll" />
<label for="selectAll" class="hx-label"></label>
</div>
</th>
</tr>
</thead>
<tbody>
<!--<tr *ngFor="let row of rows | paginate: config.pagination | simpleSearch: searchTerm">-->
<tr *ngFor="let row of pagedItems"
(click)="onRowClickHandler($event, row)"
[class.is-selected]="row.selected"
[class.is-danger]="row.context && row.context === Context.Danger"
[class.is-warning]="row.context && row.context === Context.Warning"
[class.is-info]="row.context && row.context === Context.Info"
[class.is-success]="row.context && row.context === Context.Success"
[class.has-stripe-danger]="row.stripeContext && row.stripeContext === Context.Danger"
[class.has-stripe-warning]="row.stripeContext && row.stripeContext === Context.Warning"
[class.has-stripe-info]="row.stripeContext && row.stripeContext === Context.Info"
[class.has-stripe-success]="row.stripeContext && row.stripeContext === Context.Success"
[ngClass]="[row.cssClass? row.cssClass : '']"
[attr.title]="row.title ? row.title : ''">
<td *ngFor="let col of columns" class="{{col.cssClass}} tabular__{{col.label}}" [ngClass]="{'tabular__checkboxes': col.dataType === TabularColumnTypes.Checkbox}">
<!-- checkbox type -->
<div *ngIf="col.dataType === TabularColumnTypes.Checkbox" class="hx-checkbox-control">
<input id="checkbox-{{row.id}}" name="{{col.label}}-checkbox" type="checkbox" class="hx-checkbox" title="{{col.label}}" (change)="toggleIndividualSelect($event)" [(ngModel)]="row.checked" />
<label for="checkbox-{{row.id}}" class="hx-label"></label>
</div>
<!-- string type | number type -->
<span *ngIf="col.dataType === TabularColumnTypes.String || col.dataType === TabularColumnTypes.Number" title="{{row[col.id]}}">{{row[col.id]}}</span>
<!-- html type -->
<div *ngIf="col.dataType === TabularColumnTypes.Html" [innerHTML]="row[col.id]"></div>
<!-- icon type -->
<i *ngIf="col.dataType === TabularColumnTypes.Icon && hasValidIconTypeParams(row[col.id])" title="" class="hx-icon {{row[col.id].icon}}" [hxTooltip]="row[col.id].tooltip.content" placement="{{row[col.id].tooltip.config.placement}}" [context]="row[col.id].tooltip.config.context"></i>
<!-- date type -->
<span *ngIf="col.dataType === TabularColumnTypes.Date">{{row[col.id] | date:'d/M/yy'}}</span>
<!-- status type -->
<span *ngIf="col.dataType === TabularColumnTypes.Status" class="hx-icon" [ngClass]="{'is-primary':row[col.id],'is-danger':!row[col.id], 'icon-check-empty': row[col.id], 'icon-close-empty':!row[col.id]}" ></span>
<!-- badge type -->
<span *ngIf="col.dataType === TabularColumnTypes.Badge && hasValidBadgeTypeParams(row[col.id])" class="hx-badge is-small {{row[col.id].cssClass}}"><span class="hx-badge-content">{{row[col.id].label}}</span></span>
<!-- date time type -->
<span *ngIf="col.dataType === TabularColumnTypes.DateTime">{{row[col.id] | date:'d/M/yy h:mm a'}}</span>
<!-- actions type -->
<div *ngIf="col.dataType === TabularColumnTypes.Actions" class="hx-dropdown tabularActions">
<div class="tabularActions__action">
<ng-container *ngFor="let action of row[col.id];trackBy: trackByFn">
<!-- single action -->
<span [hxTooltip]="action.tooltip?.content"
placement="{{action.tooltip?.config.placement}}"
[context]="action.tooltip?.config.context"
[disabled]="action.tooltip?.config.disabled">
<button type="button" class="hx-button is-flat" [class.is-small]="config.size === TabularSize.Small"
*ngIf="!getActionDisabledState(action) && action.routeType === ActionConfigRouteType.Route && !hasChildren(action)"
[routerLink]="action.route"
class="hx-button is-flat {{action.css}}"
title="{{action.label}}"
><span class="hx-icon {{action.icon}}"></span></button>
</span>
<span [hxTooltip]="action.tooltip?.content"
placement="{{action.tooltip?.config.placement}}"
[context]="action.tooltip?.config.context"
[disabled]="action.tooltip?.config.disabled">
<button type="button" class="hx-button is-flat" [class.is-small]="config.size === TabularSize.Small"
*ngIf="!getActionDisabledState(action) && action.routeType === ActionConfigRouteType.Callback && !hasChildren(action)"
(click)='executeCallback($event,action.callback)'
class="hx-button is-flat {{action.css}}"
[hxTooltip]="action.tooltip?.content"
placement="{{action.tooltip?.config.placement}}"
[context]="action.tooltip?.config.context"><span class="hx-icon {{action.icon}}"></span></button>
</span>
<!-- action with children -->
<div class="hx-dropdown" hxaDropdown *ngIf="hasChildren(action)" [isDisabled]="!!row.actionDisabled">
<span [hxTooltip]="action.tooltip?.content"
placement="{{action.tooltip?.config.placement}}"
[context]="action.tooltip?.config.context"
[disabled]="action.tooltip?.config.disabled">
<button class="hx-button is-flat hx-button-dropdown" [class.is-small]="config.size === TabularSize.Small" hxaDropdownToggle type="button">
<i class="icon {{action.icon}}"></i>
</button>
</span>
<div class="hx-dropdown-menu" *hxaDropdownMenu>
<ng-container *ngFor="let childAction of action.children;trackBy: trackByFn">
<a *ngIf="!getActionDisabledState(childAction) && childAction.routeType === ActionConfigRouteType.Route"
[routerLink]="childAction.route"
hxaDropdownItem
class="hx-dropdown-item {{childAction.css}}" [id]="childAction.id">{{childAction.label}}</a>
<a *ngIf="!getActionDisabledState(childAction) && childAction.routeType === ActionConfigRouteType.Callback"
(click)='executeCallback($event,childAction.callback)'
hxaDropdownItem
class="hx-dropdown-item {{childAction.css}}" [id]="childAction.id" >{{childAction.label}}</a>
</ng-container>
</div>
</div>
</ng-container>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<hx-pagination [directionLinks]="true" [boundaryLinks]="true" [rotate]="false" [maxSize]="10"
[totalItems]="totalItemCount" [itemsPerPage]="config.pagination.itemsPerPage"
[(ngModel)]="config.pagination.currentPage" (pageChanged)="setPage($event)" *ngIf="totalItemCount > config.pagination.itemsPerPage"></hx-pagination>
`,
styles: [
'.tabular__sortable {}',
'.tabular__sorter {cursor:pointer; display:flex; align-items: center;}',
'.tabular__sorter .hx-icon {margin-left:.1rem;}',
'.tabular__checkboxes{width:2%;}',
'.tabular__checkboxes .hx-checkbox-control{display:flex;}',
'.tabularActions__action button.hx-button{ width: 1rem;}',
'.tabularActions__action {display:flex;}'
]
},] },
];
/** @nocollapse */
TabularComponent.ctorParameters = () => [
{ type: TabularConfig },
{ type: TabularSortByService }
];
TabularComponent.propDecorators = {
columns: [{ type: Input }],
rows: [{ type: Input }],
config: [{ type: Input }],
callback: [{ type: Input }],
searchTerm: [{ type: Input }],
refresh: [{ type: Output }],
rowClick: [{ type: Output }],
onSort: [{ type: Output }]
};
if (false) {
/**
* Collection of column models
* @type {?}
*/
TabularComponent.prototype.columns;
/**
* Collection of data rows
* @type {?}
*/
TabularComponent.prototype.rows;
/**
* Event fired when refresh is called.
* Host should refresh data of input.
* @type {?}
*/
TabularComponent.prototype.refresh;
/**
* Event fired when a row is clicked.
* @type {?}
*/
TabularComponent.prototype.rowClick;
/**
* Event fired when a column is sorted
* @type {?}
*/
TabularComponent.prototype.onSort;
/** @type {?} */
TabularComponent.prototype.oldRows;
/** @type {?} */
TabularComponent.prototype.pagedItems;
/** @type {?} */
TabularComponent.prototype.TabularColumnTypes;
/** @type {?} */
TabularComponent.prototype.TabularSize;
/** @type {?} */
TabularComponent.prototype.ActionConfigRouteType;
/** @type {?} */
TabularComponent.prototype.selectAll;
/** @type {?} */
TabularComponent.prototype.Context;
/** @type {?} */
TabularComponent.prototype.SortByDirection;
/** @type {?} */
TabularComponent.prototype._callback;
/** @type {?} */
TabularComponent.prototype._config;
/** @type {?} */
TabularComponent.prototype._searchTerm;
/** @type {?} */
TabularComponent.prototype.toggleSelectAll;
/** @type {?} */
TabularComponent.prototype.toggleIndividualSelect;
/** @type {?} */
TabularComponent.prototype.conf;
/** @type {?} */
TabularComponent.prototype.sortByService;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFidWxhci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AaHh1aS9hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL3RhYnVsYXIvdGFidWxhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQ3ZDLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRCxPQUFPLEVBQUMscUJBQXFCLEVBQWlCLE1BQU0sNEJBQTRCLENBQUM7QUFDakYsT0FBTyxFQUFDLG9CQUFvQixFQUFFLGVBQWUsRUFBa0IsTUFBTSwyQkFBMkIsQ0FBQztBQUNqRyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDL0MsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBQ2hELE9BQU8sRUFBa0Qsa0JBQWtCLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUUvRyxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBNko1QixNQUFNLE9BQU8sZ0JBQWdCOzs7OztJQWdGMUIsWUFDUyxJQUFtQixFQUNuQixhQUFtQztRQURuQyxTQUFJLEdBQUosSUFBSSxDQUFlO1FBQ25CLGtCQUFhLEdBQWIsYUFBYSxDQUFzQjs7Ozs7UUE1Qm5DLFlBQU8sR0FBMEIsSUFBSSxZQUFZLEVBQVcsQ0FBQzs7OztRQUs3RCxhQUFRLEdBQXNCLElBQUksWUFBWSxFQUFPLENBQUM7Ozs7UUFNdEQsV0FBTSxHQUFvQyxJQUFJLFlBQVksRUFBcUIsQ0FBQztRQUVuRixZQUFPLEdBQWtCLEVBQUUsQ0FBQztRQUM1QixlQUFVLEdBQVUsRUFBRSxDQUFDO1FBQ3ZCLHVCQUFrQixHQUFHLGtCQUFrQixDQUFDO1FBQ3hD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RUFBRSxhQUFhO2dCQUN2QixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBNElYO2dCQUNDLE1BQU0sRUFBRTtvQkFDTix1QkFBdUI7b0JBQ3ZCLHVFQUF1RTtvQkFDdkUsZ0RBQWdEO29CQUNoRCxpQ0FBaUM7b0JBQ2pDLDBEQUEwRDtvQkFDMUQseURBQXlEO29CQUN6RCx5Q0FBeUM7aUJBQzFDO2FBQ0Y7Ozs7WUEvSk8sYUFBYTtZQURiLG9CQUFvQjs7O3NCQXdLekIsS0FBSzttQkFNSixLQUFLO3FCQU1OLEtBQUs7dUJBWUwsS0FBSzt5QkFhTCxLQUFLO3NCQVlMLE1BQU07dUJBS04sTUFBTTtxQkFNTixNQUFNOzs7Ozs7O0lBNURQLG1DQUFrQzs7Ozs7SUFNakMsZ0NBQTZCOzs7Ozs7SUEyQzlCLG1DQUF1RTs7Ozs7SUFLdkUsb0NBQWdFOzs7OztJQU1oRSxrQ0FBMEY7O0lBRTFGLG1DQUFtQzs7SUFDbkMsc0NBQThCOztJQUM5Qiw4Q0FBK0M7O0lBQy9DLHVDQUFpQzs7SUFDakMsaURBQXFEOztJQUNyRCxxQ0FBeUI7O0lBQ3pCLG1DQUF5Qjs7SUFDekIsMkNBQXlDOztJQUN6QyxxQ0FBOEI7O0lBQzlCLG1DQUFrQzs7SUFDbEMsdUNBQThCOztJQXNDN0IsMkNBSUE7O0lBR0Esa0RBUUE7O0lBakRDLGdDQUEyQjs7SUFDM0IseUNBQTJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBEb0NoZWNrLCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXNcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtUYWJ1bGFyQ29sdW1ufSBmcm9tICcuL3RhYnVsYXInO1xyXG5pbXBvcnQge0lUYWJ1bGFyQ29uZmlnfSBmcm9tICcuL3RhYnVsYXItY29uZmlnLmludGVyZmFjZSc7XHJcbmltcG9ydCB7QWN0aW9uQ29uZmlnUm91dGVUeXBlLCBJQWN0aW9uc0NvbmZpZ30gZnJvbSAnLi9hY3Rpb25zLWNvbmZpZy5pbnRlcmZhY2UnO1xyXG5pbXBvcnQge1RhYnVsYXJTb3J0QnlTZXJ2aWNlLCBTb3J0QnlEaXJlY3Rpb24sIElTb3J0QnlQcm9wZXJ0eX0gZnJvbSAnLi90YWJ1bGFyLXNvcnQtYnkuc2VydmljZSc7XHJcbmltcG9ydCB7VGFidWxhckNvbmZpZ30gZnJvbSAnLi90YWJ1bGFyLmNvbmZpZyc7XHJcbmltcG9ydCB7VGFidWxhclNpemV9IGZyb20gJy4vdGFidWxhci1zaXplLmVudW0nO1xyXG5pbXBvcnQge0lUYWJ1bGFyQ29sdW1uQmFkZ2VUeXBlLCBJVGFidWxhckNvbHVtbkljb25UeXBlLCBUYWJ1bGFyQ29sdW1uVHlwZXN9IGZyb20gJy4vdGFidWxhci1jb2x1bW4uaW50ZXJmYWNlJztcclxuaW1wb3J0IHtJVGFidWxhclJvd30gZnJvbSAnLi90YWJ1bGFyLXJvdy5pbnRlcmZhY2UnO1xyXG5pbXBvcnQge0NvbnRleHR9IGZyb20gJy4uL2VudW1zJztcclxuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdoeGEtdGFidWxhcicsXHJcbiAgdGVtcGxhdGU6IGA8dGFibGUgY2xhc3M9XCJ0YWJ1bGFyIGh4LXRhYmxlIGlzLXN0cmlwZWQge3tjb25maWcuY3NzQ2xhc3N9fVwiXHJcbiAgICAgICBbY2xhc3MuaXMtaG92ZXJdPVwiY29uZmlnLmNsaWNrYWJsZVJvd3NcIlxyXG4gICAgICAgW2NsYXNzLmlzLW5hcnJvd109XCJjb25maWcuc2l6ZSA9PT0gVGFidWxhclNpemUuU21hbGxcIlxyXG4gICAgICAgW2NsYXNzLmhhcy1zdGlja3ktaGVhZGVyXT1cImNvbmZpZy5zdGlja3lIZWFkZXJcIj5cclxuICA8dGhlYWQ+XHJcbiAgPHRyPlxyXG4gICAgPHRoICpuZ0Zvcj1cImxldCBjb2wgb2YgY29sdW1uc1wiIGNsYXNzPVwie3tjb2wuY3NzQ2xhc3N9fSB0YWJ1bGFyX197e2NvbC5sYWJlbH19XCIgW25nQ2xhc3NdPVwieyd0YWJ1bGFyX19jaGVja2JveGVzJzogY29sLmRhdGFUeXBlID09PSBUYWJ1bGFyQ29sdW1uVHlwZXMuQ2hlY2tib3gsICd0YWJ1bGFyX19zb3J0YWJsZSc6IGNvbC5zb3J0YWJsZX1cIj5cclxuXHJcbiAgICAgIDwhLS0gc29ydGFibGUgY29sdW1uIC0tPlxyXG4gICAgICA8YSBjbGFzcz1cInRhYnVsYXJfX3NvcnRlclwiIGhyZWY9XCIjXCIgKm5nSWY9XCJjb2wuc29ydGFibGUgJiYgY29sLmRhdGFUeXBlICE9IFRhYnVsYXJDb2x1bW5UeXBlcy5DaGVja2JveFwiIChjbGljayk9XCJvblNvcnRDbGlja0hhbmRsZXIoY29sLmlkLCBjb2wuZGF0YVR5cGUpXCI+e3tjb2wubGFiZWx9fSA8aSBjbGFzcz1cImh4LWljb24gaWNvbi1hcnJvdy11cCBpcy1zbWFsbFwiIFtjbGFzcy5pY29uLWFycm93LXVwXT1cImlzQ29sdW1uU29ydGVkKGNvbC5pZCwgU29ydEJ5RGlyZWN0aW9uLkFzY2VuZGluZylcIiBbY2xhc3MuaWNvbi1hcnJvdy1kb3duXT1cImlzQ29sdW1uU29ydGVkKGNvbC5pZCwgU29ydEJ5RGlyZWN0aW9uLkRlc2NlbmRpbmcpXCIgKm5nSWY9XCJpc0NvbHVtblNvcnRlZChjb2wuaWQsIFNvcnRCeURpcmVjdGlvbi5EZXNjZW5kaW5nKSB8fCBpc0NvbHVtblNvcnRlZChjb2wuaWQsIFNvcnRCeURpcmVjdGlvbi5Bc2NlbmRpbmcpXCI+PC9pPjwvYT5cclxuXHJcbiAgICAgIDwhLS0gbm9uIHNvcnRhYmxlIGNvbHVtbiAtLT5cclxuICAgICAgPHNwYW4gKm5nSWY9XCIhY29sLnNvcnRhYmxlICYmIGNvbC5kYXRhVHlwZSAhPT0gVGFidWxhckNvbHVtblR5cGVzLkNoZWNrYm94XCI+e3tjb2wubGFiZWx9fTwvc3Bhbj5cclxuXHJcbiAgICAgIDwhLS0gY2hlY2tib3ggY29sdW1uIC0tPlxyXG4gICAgICA8ZGl2ICpuZ0lmPVwiY29sLmRhdGFUeXBlID09PSBUYWJ1bGFyQ29sdW1uVHlwZXMuQ2hlY2tib3hcIiBjbGFzcz1cImh4LWNoZWNrYm94LWNvbnRyb2xcIj5cclxuICAgICAgICA8aW5wdXQgaWQ9XCJzZWxlY3RBbGxcIiBuYW1lPVwic2VsZWN0QWxsXCIgdHlwZT1cImNoZWNrYm94XCIgY2xhc3M9XCJoeC1jaGVja2JveFwiIChjaGFuZ2UpPVwidG9nZ2xlU2VsZWN0QWxsKCRldmVudClcIiB0aXRsZT1cIlNlbGVjdCBBbGxcIiBbKG5nTW9kZWwpXT1cInNlbGVjdEFsbFwiIC8+XHJcbiAgICAgICAgPGxhYmVsIGZvcj1cInNlbGVjdEFsbFwiIGNsYXNzPVwiaHgtbGFiZWxcIj48L2xhYmVsPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvdGg+XHJcbiAgPC90cj5cclxuICA8L3RoZWFkPlxyXG5cclxuICA8dGJvZHk+XHJcbiAgPCEtLTx0ciAqbmdGb3I9XCJsZXQgcm93IG9mIHJvd3MgfCBwYWdpbmF0ZTogY29uZmlnLnBhZ2luYXRpb24gfCBzaW1wbGVTZWFyY2g6IHNlYXJjaFRlcm1cIj4tLT5cclxuICA8dHIgKm5nRm9yPVwibGV0IHJvdyBvZiBwYWdlZEl0ZW1zXCJcclxuICAgICAgKGNsaWNrKT1cIm9uUm93Q2xpY2tIYW5kbGVyKCRldmVudCwgcm93KVwiXHJcbiAgICAgIFtjbGFzcy5pcy1zZWxlY3RlZF09XCJyb3cuc2VsZWN0ZWRcIlxyXG4gICAgICBbY2xhc3MuaXMtZGFuZ2VyXT1cInJvdy5jb250ZXh0ICYmIHJvdy5jb250ZXh0ID09PSBDb250ZXh0LkRhbmdlclwiXHJcbiAgICAgIFtjbGFzcy5pcy13YXJuaW5nXT1cInJvdy5jb250ZXh0ICYmIHJvdy5jb250ZXh0ID09PSBDb250ZXh0Lldhcm5pbmdcIlxyXG4gICAgICBbY2xhc3MuaXMtaW5mb109XCJyb3cuY29udGV4dCAmJiByb3cuY29udGV4dCA9PT0gQ29udGV4dC5JbmZvXCJcclxuICAgICAgW2NsYXNzLmlzLXN1Y2Nlc3NdPVwicm93LmNvbnRleHQgJiYgcm93LmNvbnRleHQgPT09IENvbnRleHQuU3VjY2Vzc1wiXHJcbiAgICAgIFtjbGFzcy5oYXMtc3RyaXBlLWRhbmdlcl09XCJyb3cuc3RyaXBlQ29udGV4dCAmJiByb3cuc3RyaXBlQ29udGV4dCA9PT0gQ29udGV4dC5EYW5nZXJcIlxyXG4gICAgICBbY2xhc3MuaGFzLXN0cmlwZS13YXJuaW5nXT1cInJvdy5zdHJpcGVDb250ZXh0ICYmIHJvdy5zdHJpcGVDb250ZXh0ID09PSBDb250ZXh0Lldhcm5pbmdcIlxyXG4gICAgICBbY2xhc3MuaGFzLXN0cmlwZS1pbmZvXT1cInJvdy5zdHJpcGVDb250ZXh0ICYmIHJvdy5zdHJpcGVDb250ZXh0ID09PSBDb250ZXh0LkluZm9cIlxyXG4gICAgICBbY2xhc3MuaGFzLXN0cmlwZS1zdWNjZXNzXT1cInJvdy5zdHJpcGVDb250ZXh0ICYmIHJvdy5zdHJpcGVDb250ZXh0ID09PSBDb250ZXh0LlN1Y2Nlc3NcIlxyXG4gICAgICBbbmdDbGFzc109XCJbcm93LmNzc0NsYXNzPyByb3cuY3NzQ2xhc3MgOiAnJ11cIlxyXG4gICAgICBbYXR0ci50aXRsZV09XCJyb3cudGl0bGUgPyByb3cudGl0bGUgOiAnJ1wiPlxyXG4gICAgPHRkICpuZ0Zvcj1cImxldCBjb2wgb2YgY29sdW1uc1wiIGNsYXNzPVwie3tjb2wuY3NzQ2xhc3N9fSB0YWJ1bGFyX197e2NvbC5sYWJlbH19XCIgW25nQ2xhc3NdPVwieyd0YWJ1bGFyX19jaGVja2JveGVzJzogY29sLmRhdGFUeXBlID09PSBUYWJ1bGFyQ29sdW1uVHlwZXMuQ2hlY2tib3h9XCI+XHJcblxyXG4gICAgICA8IS0tIGNoZWNrYm94IHR5cGUgLS0+XHJcbiAgICAgIDxkaXYgKm5nSWY9XCJjb2wuZGF0YVR5cGUgPT09IFRhYnVsYXJDb2x1bW5UeXBlcy5DaGVja2JveFwiIGNsYXNzPVwiaHgtY2hlY2tib3gtY29udHJvbFwiPlxyXG4gICAgICAgIDxpbnB1dCBpZD1cImNoZWNrYm94LXt7cm93LmlkfX1cIiBuYW1lPVwie3tjb2wubGFiZWx9fS1jaGVja2JveFwiIHR5cGU9XCJjaGVja2JveFwiIGNsYXNzPVwiaHgtY2hlY2tib3hcIiB0aXRsZT1cInt7Y29sLmxhYmVsfX1cIiAoY2hhbmdlKT1cInRvZ2dsZUluZGl2aWR1YWxTZWxlY3QoJGV2ZW50KVwiIFsobmdNb2RlbCldPVwicm93LmNoZWNrZWRcIiAvPlxyXG4gICAgICAgIDxsYWJlbCBmb3I9XCJjaGVja2JveC17e3Jvdy5pZH19XCIgY2xhc3M9XCJoeC1sYWJlbFwiPjwvbGFiZWw+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBzdHJpbmcgdHlwZSB8IG51bWJlciB0eXBlIC0tPlxyXG4gICAgICA8c3BhbiAqbmdJZj1cImNvbC5kYXRhVHlwZSA9PT0gVGFidWxhckNvbHVtblR5cGVzLlN0cmluZyB8fCBjb2wuZGF0YVR5cGUgPT09IFRhYnVsYXJDb2x1bW5UeXBlcy5OdW1iZXJcIiB0aXRsZT1cInt7cm93W2NvbC5pZF19fVwiPnt7cm93W2NvbC5pZF19fTwvc3Bhbj5cclxuXHJcbiAgICAgIDwhLS0gaHRtbCB0eXBlIC0tPlxyXG4gICAgICA8ZGl2ICpuZ0lmPVwiY29sLmRhdGFUeXBlID09PSBUYWJ1bGFyQ29sdW1uVHlwZXMuSHRtbFwiIFtpbm5lckhUTUxdPVwicm93W2NvbC5pZF1cIj48L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gaWNvbiB0eXBlIC0tPlxyXG4gICAgICA8aSAqbmdJZj1cImNvbC5kYXRhVHlwZSA9PT0gVGFidWxhckNvbHVtblR5cGVzLkljb24gJiYgaGFzVmFsaWRJY29uVHlwZVBhcmFtcyhyb3dbY29sLmlkXSlcIiB0aXRsZT1cIlwiIGNsYXNzPVwiaHgtaWNvbiB7e3Jvd1tjb2wuaWRdLmljb259fVwiIFtoeFRvb2x0aXBdPVwicm93W2NvbC5pZF0udG9vbHRpcC5jb250ZW50XCIgcGxhY2VtZW50PVwie3tyb3dbY29sLmlkXS50b29sdGlwLmNvbmZpZy5wbGFjZW1lbnR9fVwiIFtjb250ZXh0XT1cInJvd1tjb2wuaWRdLnRvb2x0aXAuY29uZmlnLmNvbnRleHRcIj48L2k+XHJcblxyXG4gICAgICA8IS0tIGRhdGUgdHlwZSAtLT5cclxuICAgICAgPHNwYW4gKm5nSWY9XCJjb2wuZGF0YVR5cGUgPT09IFRhYnVsYXJDb2x1bW5UeXBlcy5EYXRlXCI+e3tyb3dbY29sLmlkXSB8IGRhdGU6J2QvTS95eSd9fTwvc3Bhbj5cclxuXHJcbiAgICAgIDwhLS0gc3RhdHVzIHR5cGUgLS0+XHJcbiAgICAgIDxzcGFuICpuZ0lmPVwiY29sLmRhdGFUeXBlID09PSBUYWJ1bGFyQ29sdW1uVHlwZXMuU3RhdHVzXCIgY2xhc3M9XCJoeC1pY29uXCIgW25nQ2xhc3NdPVwieydpcy1wcmltYXJ5Jzpyb3dbY29sLmlkXSwnaXMtZGFuZ2VyJzohcm93W2NvbC5pZF0sICdpY29uLWNoZWNrLWVtcHR5Jzogcm93W2NvbC5pZF0sICdpY29uLWNsb3NlLWVtcHR5Jzohcm93W2NvbC5pZF19XCIgPjwvc3Bhbj5cclxuXHJcbiAgICAgIDwhLS0gYmFkZ2UgdHlwZSAtLT5cclxuICAgICAgPHNwYW4gKm5nSWY9XCJjb2wuZGF0YVR5cGUgPT09IFRhYnVsYXJDb2x1bW5UeXBlcy5CYWRnZSAmJiBoYXNWYWxpZEJhZGdlVHlwZVBhcmFtcyhyb3dbY29sLmlkXSlcIiBjbGFzcz1cImh4LWJhZGdlIGlzLXNtYWxsIHt7cm93W2NvbC5pZF0uY3NzQ2xhc3N9fVwiPjxzcGFuIGNsYXNzPVwiaHgtYmFkZ2UtY29udGVudFwiPnt7cm93W2NvbC5pZF0ubGFiZWx9fTwvc3Bhbj48L3NwYW4+XHJcblxyXG4gICAgICA8IS0tIGRhdGUgdGltZSB0eXBlIC0tPlxyXG4gICAgICA8c3BhbiAqbmdJZj1cImNvbC5kYXRhVHlwZSA9PT0gVGFidWxhckNvbHVtblR5cGVzLkRhdGVUaW1lXCI+e3tyb3dbY29sLmlkXSB8IGRhdGU6J2QvTS95eSBoOm1tIGEnfX08L3NwYW4+XHJcblxyXG4gICAgICA8IS0tIGFjdGlvbnMgdHlwZSAtLT5cclxuICAgICAgPGRpdiAqbmdJZj1cImNvbC5kYXRhVHlwZSA9PT0gVGFidWxhckNvbHVtblR5cGVzLkFjdGlvbnNcIiBjbGFzcz1cImh4LWRyb3Bkb3duIHRhYnVsYXJBY3Rpb25zXCI+XHJcblxyXG5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwidGFidWxhckFjdGlvbnNfX2FjdGlvblwiPlxyXG5cclxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGFjdGlvbiBvZiByb3dbY29sLmlkXTt0cmFja0J5OiB0cmFja0J5Rm5cIj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gc2luZ2xlIGFjdGlvbiAtLT5cclxuICAgICAgICAgICAgPHNwYW4gIFtoeFRvb2x0aXBdPVwiYWN0aW9uLnRvb2x0aXA/LmNvbnRlbnRcIlxyXG4gICAgICAgICAgICAgICAgICAgcGxhY2VtZW50PVwie3thY3Rpb24udG9vbHRpcD8uY29uZmlnLnBsYWNlbWVudH19XCJcclxuICAgICAgICAgICAgICAgICAgIFtjb250ZXh0XT1cImFjdGlvbi50b29sdGlwPy5jb25maWcuY29udGV4dFwiXHJcbiAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYWN0aW9uLnRvb2x0aXA/LmNvbmZpZy5kaXNhYmxlZFwiPlxyXG4gICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiaHgtYnV0dG9uIGlzLWZsYXRcIiBbY2xhc3MuaXMtc21hbGxdPVwiY29uZmlnLnNpemUgPT09IFRhYnVsYXJTaXplLlNtYWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiIWdldEFjdGlvbkRpc2FibGVkU3RhdGUoYWN0aW9uKSAmJiBhY3Rpb24ucm91dGVUeXBlID09PSBBY3Rpb25Db25maWdSb3V0ZVR5cGUuUm91dGUgJiYgIWhhc0NoaWxkcmVuKGFjdGlvbilcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgW3JvdXRlckxpbmtdPVwiYWN0aW9uLnJvdXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaHgtYnV0dG9uIGlzLWZsYXQge3thY3Rpb24uY3NzfX1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgdGl0bGU9XCJ7e2FjdGlvbi5sYWJlbH19XCJcclxuICAgICAgICAgICAgICAgICAgICAgPjxzcGFuIGNsYXNzPVwiaHgtaWNvbiB7e2FjdGlvbi5pY29ufX1cIj48L3NwYW4+PC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgICAgPHNwYW4gIFtoeFRvb2x0aXBdPVwiYWN0aW9uLnRvb2x0aXA/LmNvbnRlbnRcIlxyXG4gICAgICAgICAgICAgICAgICAgcGxhY2VtZW50PVwie3thY3Rpb24udG9vbHRpcD8uY29uZmlnLnBsYWNlbWVudH19XCJcclxuICAgICAgICAgICAgICAgICAgIFtjb250ZXh0XT1cImFjdGlvbi50b29sdGlwPy5jb25maWcuY29udGV4dFwiXHJcbiAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiYWN0aW9uLnRvb2x0aXA/LmNvbmZpZy5kaXNhYmxlZFwiPlxyXG4gICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiaHgtYnV0dG9uIGlzLWZsYXRcIiBbY2xhc3MuaXMtc21hbGxdPVwiY29uZmlnLnNpemUgPT09IFRhYnVsYXJTaXplLlNtYWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiIWdldEFjdGlvbkRpc2FibGVkU3RhdGUoYWN0aW9uKSAmJiBhY3Rpb24ucm91dGVUeXBlID09PSBBY3Rpb25Db25maWdSb3V0ZVR5cGUuQ2FsbGJhY2sgJiYgIWhhc0NoaWxkcmVuKGFjdGlvbilcIlxyXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9J2V4ZWN1dGVDYWxsYmFjaygkZXZlbnQsYWN0aW9uLmNhbGxiYWNrKSdcclxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImh4LWJ1dHRvbiBpcy1mbGF0IHt7YWN0aW9uLmNzc319XCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtoeFRvb2x0aXBdPVwiYWN0aW9uLnRvb2x0aXA/LmNvbnRlbnRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgcGxhY2VtZW50PVwie3thY3Rpb24udG9vbHRpcD8uY29uZmlnLnBsYWNlbWVudH19XCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtjb250ZXh0XT1cImFjdGlvbi50b29sdGlwPy5jb25maWcuY29udGV4dFwiPjxzcGFuIGNsYXNzPVwiaHgtaWNvbiB7e2FjdGlvbi5pY29ufX1cIj48L3NwYW4+PC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvc3Bhbj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gYWN0aW9uIHdpdGggY2hpbGRyZW4gLS0+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoeC1kcm9wZG93blwiIGh4YURyb3Bkb3duICAqbmdJZj1cImhhc0NoaWxkcmVuKGFjdGlvbilcIiBbaXNEaXNhYmxlZF09XCIhIXJvdy5hY3Rpb25EaXNhYmxlZFwiPlxyXG4gICAgICAgICAgICA8c3BhbiBbaHhUb29sdGlwXT1cImFjdGlvbi50b29sdGlwPy5jb250ZW50XCJcclxuICAgICAgICAgICAgICAgICAgcGxhY2VtZW50PVwie3thY3Rpb24udG9vbHRpcD8uY29uZmlnLnBsYWNlbWVudH19XCJcclxuICAgICAgICAgICAgICAgICAgW2NvbnRleHRdPVwiYWN0aW9uLnRvb2x0aXA/LmNvbmZpZy5jb250ZXh0XCJcclxuICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImFjdGlvbi50b29sdGlwPy5jb25maWcuZGlzYWJsZWRcIj5cclxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJoeC1idXR0b24gaXMtZmxhdCBoeC1idXR0b24tZHJvcGRvd25cIiBbY2xhc3MuaXMtc21hbGxdPVwiY29uZmlnLnNpemUgPT09IFRhYnVsYXJTaXplLlNtYWxsXCIgaHhhRHJvcGRvd25Ub2dnbGUgdHlwZT1cImJ1dHRvblwiPlxyXG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJpY29uIHt7YWN0aW9uLmljb259fVwiPjwvaT5cclxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3NwYW4+XHJcblxyXG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoeC1kcm9wZG93bi1tZW51XCIgKmh4YURyb3Bkb3duTWVudT5cclxuXHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjaGlsZEFjdGlvbiBvZiBhY3Rpb24uY2hpbGRyZW47dHJhY2tCeTogdHJhY2tCeUZuXCI+XHJcbiAgICAgICAgICAgICAgICAgIDxhICpuZ0lmPVwiIWdldEFjdGlvbkRpc2FibGVkU3RhdGUoY2hpbGRBY3Rpb24pICYmIGNoaWxkQWN0aW9uLnJvdXRlVHlwZSA9PT0gQWN0aW9uQ29uZmlnUm91dGVUeXBlLlJvdXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtyb3V0ZXJMaW5rXT1cImNoaWxkQWN0aW9uLnJvdXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgIGh4YURyb3Bkb3duSXRlbVxyXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoeC1kcm9wZG93bi1pdGVtIHt7Y2hpbGRBY3Rpb24uY3NzfX1cIiBbaWRdPVwiY2hpbGRBY3Rpb24uaWRcIj57e2NoaWxkQWN0aW9uLmxhYmVsfX08L2E+XHJcbiAgICAgICAgICAgICAgICAgIDxhICpuZ0lmPVwiIWdldEFjdGlvbkRpc2FibGVkU3RhdGUoY2hpbGRBY3Rpb24pICYmIGNoaWxkQWN0aW9uLnJvdXRlVHlwZSA9PT0gQWN0aW9uQ29uZmlnUm91dGVUeXBlLkNhbGxiYWNrXCJcclxuICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9J2V4ZWN1dGVDYWxsYmFjaygkZXZlbnQsY2hpbGRBY3Rpb24uY2FsbGJhY2spJ1xyXG4gICAgICAgICAgICAgICAgICAgICAgIGh4YURyb3Bkb3duSXRlbVxyXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJoeC1kcm9wZG93bi1pdGVtIHt7Y2hpbGRBY3Rpb24uY3NzfX1cIiBbaWRdPVwiY2hpbGRBY3Rpb24uaWRcIiA+e3tjaGlsZEFjdGlvbi5sYWJlbH19PC9hPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgIDwvdGQ+XHJcbiAgPC90cj5cclxuICA8L3Rib2R5PlxyXG48L3RhYmxlPlxyXG5cclxuPGh4LXBhZ2luYXRpb24gW2RpcmVjdGlvbkxpbmtzXT1cInRydWVcIiBbYm91bmRhcnlMaW5rc109XCJ0cnVlXCIgW3JvdGF0ZV09XCJmYWxzZVwiIFttYXhTaXplXT1cIjEwXCJcclxuICAgICAgICAgICAgICAgW3RvdGFsSXRlbXNdPVwidG90YWxJdGVtQ291bnRcIiBbaXRlbXNQZXJQYWdlXT1cImNvbmZpZy5wYWdpbmF0aW9uLml0ZW1zUGVyUGFnZVwiXHJcbiAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiY29uZmlnLnBhZ2luYXRpb24uY3VycmVudFBhZ2VcIiAocGFnZUNoYW5nZWQpPVwic2V0UGFnZSgkZXZlbnQpXCIgKm5nSWY9XCJ0b3RhbEl0ZW1Db3VudCA+IGNvbmZpZy5wYWdpbmF0aW9uLml0ZW1zUGVyUGFnZVwiPjwvaHgtcGFnaW5hdGlvbj5cclxuYCxcclxuICBzdHlsZXM6IFtcclxuICAgICcudGFidWxhcl9fc29ydGFibGUge30nLFxyXG4gICAgJy50YWJ1bGFyX19zb3J0ZXIge2N1cnNvcjpwb2ludGVyOyBkaXNwbGF5OmZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7fScsXHJcbiAgICAnLnRhYnVsYXJfX3NvcnRlciAuaHgtaWNvbiB7bWFyZ2luLWxlZnQ6LjFyZW07fScsXHJcbiAgICAnLnRhYnVsYXJfX2NoZWNrYm94ZXN7d2lkdGg6MiU7fScsXHJcbiAgICAnLnRhYnVsYXJfX2NoZWNrYm94ZXMgLmh4LWNoZWNrYm94LWNvbnRyb2x7ZGlzcGxheTpmbGV4O30nLFxyXG4gICAgJy50YWJ1bGFyQWN0aW9uc19fYWN0aW9uIGJ1dHRvbi5oeC1idXR0b257IHdpZHRoOiAxcmVtO30nLFxyXG4gICAgJy50YWJ1bGFyQWN0aW9uc19fYWN0aW9uIHtkaXNwbGF5OmZsZXg7fSdcclxuICBdXHJcbn0pXHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIFRhYnVsYXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIERvQ2hlY2sge1xyXG5cclxuICAvKipcclxuICAgKiBDb2xsZWN0aW9uIG9mIGNvbHVtbiBtb2RlbHNcclxuICAgKi9cclxuICBASW5wdXQoKSBjb2x1bW5zOiBUYWJ1bGFyQ29sdW1uW107XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbGxlY3Rpb24gb2YgZGF0YSByb3dzXHJcbiAgICovXHJcbiAgLy8gdG9kbyAtIHRoaXMgaXMgbm90IHN0cmljdC4gc2hvdWxkIGl0IGJlIHdoZW4gaXQncyBkeW5hbWljPy5cclxuICAgQElucHV0KCkgcm93czogSVRhYnVsYXJSb3dbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogVGFidWxhciBjb25maWd1cmF0aW9uXHJcbiAgICogSVBhZ2luYXRpb25JbnN0YW5jZSwgSVNlYXJjaENvbmZpZ1xyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGdldCBjb25maWcoKTogSVRhYnVsYXJDb25maWcgIHtcclxuICAgIHJldHVybiB0aGlzLl9jb25maWc7XHJcbiAgfVxyXG4gIHB1YmxpYyBzZXQgY29uZmlnKGM6IElUYWJ1bGFyQ29uZmlnKSAge1xyXG4gICAgaWYgKCFjLnNvcnRCeSkge1xyXG4gICAgICBjLnNvcnRCeSA9IFtdO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fY29uZmlnID0gYztcclxuICB9XHJcblxyXG4gIC8qKiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIGEgYWN0aW9uIGl0ZW0gaXMgY2xpY2tlZCAqKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBnZXQgY2FsbGJhY2soKTogRnVuY3Rpb257XHJcbiAgICByZXR1cm4gdGhpcy5fY2FsbGJhY2s7XHJcbiAgfVxyXG4gIHB1YmxpYyBzZXQgY2FsbGJhY2soRm46IEZ1bmN0aW9uKXtcclxuICAgIHRoaXMuX2NhbGxiYWNrID0gRm47XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogU2VhcmNoIHRlcm0gaXMgdXNlZCBpbiB0aGUgc2ltcGxlIHNlYXJjaCBwaXBlXHJcbiAgICogQXJyYXkgb2Ygb2JqZWN0czogKm5nRm9yPVwiI3JvdyBvZiByb3dzIHwgc2ltcGxlU2VhcmNoIDogJ3RoZSBzZWFyY2ggdGVybSdcIlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGdldCBzZWFyY2hUZXJtKCk6IHN0cmluZ3tcclxuICAgIHJldHVybiB0aGlzLl9zZWFyY2hUZXJtO1xyXG4gIH1cclxuICBwdWJsaWMgc2V0IHNlYXJjaFRlcm0odGVybTogc3RyaW5nKXtcclxuICAgIHRoaXMuX3NlYXJjaFRlcm0gPSB0ZXJtO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnQgZmlyZWQgd2hlbiByZWZyZXNoIGlzIGNhbGxlZC5cclxuICAgKiBIb3N0IHNob3VsZCByZWZyZXNoIGRhdGEgb2YgaW5wdXQuXHJcbiAgICovXHJcbiAgQE91dHB1dCgpIHJlZnJlc2g6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnQgZmlyZWQgd2hlbiBhIHJvdyBpcyBjbGlja2VkLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSByb3dDbGljazogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuXHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50IGZpcmVkIHdoZW4gYSBjb2x1bW4gaXMgc29ydGVkXHJcbiAgICovXHJcbiAgQE91dHB1dCgpIG9uU29ydDogRXZlbnRFbWl0dGVyPElTb3J0QnlQcm9wZXJ0eVtdPiA9IG5ldyBFdmVudEVtaXR0ZXI8SVNvcnRCeVByb3BlcnR5W10+KCk7XHJcblxyXG4gIHB1YmxpYyBvbGRSb3dzOiBJVGFidWxhclJvd1tdID0gW107XHJcbiAgcHVibGljIHBhZ2VkSXRlbXM6IGFueVtdID0gW107XHJcbiAgcHVibGljIFRhYnVsYXJDb2x1bW5UeXBlcyA9IFRhYnVsYXJDb2x1bW5UeXBlcztcclxuICBwdWJsaWMgVGFidWxhclNpemUgPSBUYWJ1bGFyU2l6ZTtcclxuICBwdWJsaWMgQWN0aW9uQ29uZmlnUm91dGVUeXBlID0gQWN0aW9uQ29uZmlnUm91dGVUeXBlO1xyXG4gIHB1YmxpYyBzZWxlY3RBbGwgPSBmYWxzZTtcclxuICBwdWJsaWMgQ29udGV4dCA9IENvbnRleHQ7XHJcbiAgcHVibGljIFNvcnRCeURpcmVjdGlvbiA9IFNvcnRCeURpcmVjdGlvbjtcclxuICBwcm90ZWN0ZWQgX2NhbGxiYWNrOiBGdW5jdGlvbjtcclxuICBwcm90ZWN0ZWQgX2NvbmZpZzogSVRhYnVsYXJDb25maWc7XHJcbiAgcHJvdGVjdGVkIF9zZWFyY2hUZXJtOiBzdHJpbmc7XHJcblxyXG5cclxuICAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIGNvbmY6IFRhYnVsYXJDb25maWcsXHJcbiAgICBwcml2YXRlIHNvcnRCeVNlcnZpY2U6IFRhYnVsYXJTb3J0QnlTZXJ2aWNlXHJcbiAgKSB7XHJcbiAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNvbmYpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcblxyXG4gIH1cclxuXHJcbiAgbmdEb0NoZWNrKCkge1xyXG4gICAgaWYgKCFfLmlzRXF1YWwodGhpcy5yb3dzLCB0aGlzLm9sZFJvd3MpKSB7XHJcbiAgICAgIHRoaXMub2xkUm93cyA9IF8uY2xvbmVEZWVwKHRoaXMucm93cyk7XHJcbiAgICAgIHRoaXMub3JkZXJCeURhdGEoZmFsc2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsbHMgdGhlIHBhcnNlZCBjYWxsYmFjayB3aXRoIG9wdGlvbmFsIGFyZ3VtZW50c1xyXG4gICAqL1xyXG4gICBleGVjdXRlQ2FsbGJhY2soZXZlbnQ6IEV2ZW50LCBjYjogYW55W10pIHtcclxuICAgIGlmIChjYi5sZW5ndGgpIHtcclxuICAgICAgaWYgKGNiLmxlbmd0aCA9PT0gMSkgeyAvLyBpZiBjYWxsYmFjayBoYXMgbm8gYXJndW1lbnRzXHJcbiAgICAgICAgY2JbMF0oKTtcclxuICAgICAgfSBlbHNlIHsgLy8gaWYgY2FsbGJhY2sgaGF