tango-app-ui-store-builder 1.2.4 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/esm2022/lib/components/collection-update-ai/collection-update-ai.component.mjs +3 -2
  2. package/esm2022/lib/components/collection-update-ai/find-replace-layout/prepare-template/prepare-template.component.mjs +3 -2
  3. package/esm2022/lib/components/collection-update-ai/find-replace-layout/review-replace/review-replace.component.mjs +3 -2
  4. package/esm2022/lib/components/create-fixture/create-fixture.component.mjs +41 -4
  5. package/esm2022/lib/components/custom-select/custom-select.component.mjs +14 -5
  6. package/esm2022/lib/components/fixture-template/template-assign-stores/preview-modal/preview-modal.component.mjs +3 -2
  7. package/esm2022/lib/components/fixture-template/template-assign-stores/template-assign-stores.component.mjs +3 -2
  8. package/esm2022/lib/components/fixture-template-table/find-and-replace/find-and-replace.component.mjs +3 -2
  9. package/esm2022/lib/components/fixture-template-table/fixture-template-table.component.mjs +2 -3
  10. package/esm2022/lib/components/fixture-template-tree/fixture-template-tree.component.mjs +3 -2
  11. package/esm2022/lib/components/manage-plano/verification-table/verification-table.component.mjs +2 -3
  12. package/esm2022/lib/components/manage-store-plano/manage-store-plano.component.mjs +87 -13
  13. package/esm2022/lib/components/manage-store-plano/plano-rollout/plano-rollout.component.mjs +4 -3
  14. package/esm2022/lib/components/manage-store-plano/template-basic-details/template-basic-details.component.mjs +114 -4
  15. package/esm2022/lib/components/manage-store-plano/zone-verification-feedback/zone-verification-feedback.component.mjs +7 -2
  16. package/esm2022/lib/components/onboard-store-plano/onboard-fixture/onboard-fixture.component.mjs +3 -3
  17. package/esm2022/lib/components/onboard-store-plano/onboard-store-plano.component.mjs +255 -25
  18. package/esm2022/lib/components/plano-configurations/plano-configurations.component.mjs +162 -3
  19. package/esm2022/lib/components/plano-library/fixture-library/fixture-library.component.mjs +3 -4
  20. package/esm2022/lib/components/plano-library/vm-library/vm-library.component.mjs +3 -4
  21. package/esm2022/lib/components/plano-tools/cad-files/cad-files.component.mjs +88 -0
  22. package/esm2022/lib/components/plano-tools/cad-render/cad-render.component.mjs +4 -5
  23. package/esm2022/lib/components/plano-tools/move-bucket/move-bucket.component.mjs +239 -0
  24. package/esm2022/lib/components/plano-tools/plano-data-export/plano-data-export.component.mjs +98 -3
  25. package/esm2022/lib/components/plano-tools/plano-migrate/plano-migrate.component.mjs +5 -4
  26. package/esm2022/lib/components/plano-tools/store-exports/store-exports.component.mjs +135 -33
  27. package/esm2022/lib/components/plano-tools/swap-template/swap-template.component.mjs +325 -0
  28. package/esm2022/lib/components/plano-tools/tools-parent/tools-parent.component.mjs +3 -3
  29. package/esm2022/lib/components/planogram/merch-compliance/merch-compliance.component.mjs +3 -2
  30. package/esm2022/lib/components/planogram/merch-compliance/product-locator/product-locator.component.mjs +3 -2
  31. package/esm2022/lib/components/planogram/plano-analytics/plano-analytics.component.mjs +3 -2
  32. package/esm2022/lib/components/planogram/plano-details-parent/plano-details-parent.component.mjs +1 -1
  33. package/esm2022/lib/components/planogram/plano-overview/plano-comparison/plano-comparison.component.mjs +3 -2
  34. package/esm2022/lib/components/planogram/plano-overview/plano-overview.component.mjs +3 -2
  35. package/esm2022/lib/components/planogram/plano-table/plano-table.component.mjs +2 -3
  36. package/esm2022/lib/components/popups/delete-confirmation/delete-confirmation.component.mjs +10 -3
  37. package/esm2022/lib/components/store-plano/store-plano-tree-view/store-plano-tree-view.component.mjs +3 -4
  38. package/esm2022/lib/components/store-plano/store-plano.component.mjs +4 -3
  39. package/esm2022/lib/data/fixture-template.data.mjs +12 -1
  40. package/esm2022/lib/functions/plano.function.mjs +13 -1
  41. package/esm2022/lib/services/store-builder.service.mjs +35 -1
  42. package/esm2022/lib/tango-store-builder-routing.module.mjs +16 -1
  43. package/esm2022/lib/tango-store-builder.module.mjs +10 -1
  44. package/fesm2022/tango-app-ui-store-builder.mjs +1914 -401
  45. package/fesm2022/tango-app-ui-store-builder.mjs.map +1 -1
  46. package/lib/components/create-fixture/create-fixture.component.d.ts +3 -0
  47. package/lib/components/custom-select/custom-select.component.d.ts +5 -2
  48. package/lib/components/manage-plano/rollout-table/rollout-table.component.d.ts +4 -4
  49. package/lib/components/manage-plano/verification-table/verification-table.component.d.ts +5 -5
  50. package/lib/components/manage-store-plano/manage-store-plano.component.d.ts +7 -1
  51. package/lib/components/manage-store-plano/template-basic-details/template-basic-details.component.d.ts +14 -1
  52. package/lib/components/onboard-store-plano/onboard-store-plano.component.d.ts +19 -2
  53. package/lib/components/plano-configurations/plano-configurations.component.d.ts +19 -1
  54. package/lib/components/plano-tools/cad-files/cad-files.component.d.ts +30 -0
  55. package/lib/components/plano-tools/move-bucket/move-bucket.component.d.ts +64 -0
  56. package/lib/components/plano-tools/plano-data-export/plano-data-export.component.d.ts +26 -0
  57. package/lib/components/plano-tools/store-exports/store-exports.component.d.ts +28 -3
  58. package/lib/components/plano-tools/swap-template/swap-template.component.d.ts +83 -0
  59. package/lib/components/popups/delete-confirmation/delete-confirmation.component.d.ts +3 -1
  60. package/lib/data/fixture-template.data.d.ts +8 -0
  61. package/lib/functions/plano.function.d.ts +1 -0
  62. package/lib/services/store-builder.service.d.ts +26 -0
  63. package/lib/tango-store-builder.module.d.ts +56 -53
  64. package/package.json +1 -1
@@ -49,6 +49,17 @@ export class PlanoDataExportComponent {
49
49
  paginationSizes = [25, 50, 100, 200];
50
50
  pageSize = 50;
51
51
  currentPage = 1;
52
+ // VM Placement Export by VM Name
53
+ vmSelectedStores = [];
54
+ vmInitialStores = [];
55
+ vmNameRegex = '';
56
+ isVmRunning = false;
57
+ vmResult = null;
58
+ vmResultColumns = [];
59
+ vmPageSize = 50;
60
+ vmCurrentPage = 1;
61
+ vmMessage = '';
62
+ vmMessageType = 'success';
52
63
  destroy$ = new Subject();
53
64
  constructor(sbs, gs) {
54
65
  this.sbs = sbs;
@@ -269,15 +280,99 @@ export class PlanoDataExportComponent {
269
280
  this.messageType = type;
270
281
  setTimeout(() => (this.message = ''), 5000);
271
282
  }
283
+ // ---------- VM Placement Export ----------
284
+ onVmStoresSelected(stores) {
285
+ this.vmSelectedStores = stores;
286
+ }
287
+ get vmTotalRows() {
288
+ return this.vmResult?.rows.length || 0;
289
+ }
290
+ get vmPagedRows() {
291
+ if (!this.vmResult)
292
+ return [];
293
+ let start = (this.vmCurrentPage - 1) * this.vmPageSize;
294
+ return this.vmResult.rows.slice(start, start + this.vmPageSize);
295
+ }
296
+ get vmPageStart() {
297
+ if (!this.vmTotalRows)
298
+ return 0;
299
+ return (this.vmCurrentPage - 1) * this.vmPageSize + 1;
300
+ }
301
+ get vmPageEnd() {
302
+ return Math.min(this.vmCurrentPage * this.vmPageSize, this.vmTotalRows);
303
+ }
304
+ onVmPageChange(page) {
305
+ this.vmCurrentPage = Number(page) || 1;
306
+ }
307
+ onVmPageSizeChange(size) {
308
+ this.vmPageSize = Number(size) || 50;
309
+ this.vmCurrentPage = 1;
310
+ }
311
+ onVmRun() {
312
+ if (this.vmSelectedStores.length === 0) {
313
+ this.showVmMessage('Please select at least one store.', 'error');
314
+ return;
315
+ }
316
+ if (!this.vmNameRegex || !this.vmNameRegex.trim()) {
317
+ this.showVmMessage('Please enter a VM name (regex).', 'error');
318
+ return;
319
+ }
320
+ let payload = {
321
+ clientId: this.clientId,
322
+ storeNames: this.vmSelectedStores.map((s) => s.label),
323
+ vmName: this.vmNameRegex.trim(),
324
+ };
325
+ this.isVmRunning = true;
326
+ this.vmResult = null;
327
+ this.vmCurrentPage = 1;
328
+ this.sbs.runVmPlacementQuery(payload).subscribe({
329
+ next: (res) => {
330
+ this.vmResult = res?.data || null;
331
+ this.vmResultColumns = this.vmResult?.columns || [];
332
+ this.isVmRunning = false;
333
+ this.vmCurrentPage = 1;
334
+ if (this.vmResult) {
335
+ this.showVmMessage(`Matched ${this.vmResult.matchedVmCount} VM(s); found ${this.vmResult.totalRows} placement row(s).`, 'success');
336
+ }
337
+ },
338
+ error: (err) => {
339
+ this.showVmMessage(err?.error?.message || 'Failed to run VM placement query.', 'error');
340
+ this.isVmRunning = false;
341
+ },
342
+ });
343
+ }
344
+ onVmExport() {
345
+ if (!this.vmResult || !this.vmResult.rows.length) {
346
+ this.showVmMessage('No data to export. Run the query first.', 'error');
347
+ return;
348
+ }
349
+ let cleaned = this.vmResult.rows.map((r) => {
350
+ let copy = {};
351
+ for (let col of this.vmResultColumns)
352
+ copy[col] = r[col] ?? '';
353
+ return copy;
354
+ });
355
+ let safeName = (this.vmNameRegex || 'vm')
356
+ .trim()
357
+ .replace(/[^a-z0-9]+/gi, '_')
358
+ .toLowerCase();
359
+ let fileName = `vm_placement_${safeName}_${Date.now()}`;
360
+ this.sbs.exportAsExcelFile(cleaned, fileName);
361
+ }
362
+ showVmMessage(msg, type) {
363
+ this.vmMessage = msg;
364
+ this.vmMessageType = type;
365
+ setTimeout(() => (this.vmMessage = ''), 5000);
366
+ }
272
367
  ngOnDestroy() {
273
368
  this.destroy$.next();
274
369
  this.destroy$.complete();
275
370
  }
276
371
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlanoDataExportComponent, deps: [{ token: i1.StoreBuilderService }, { token: i2.GlobalStateService }], target: i0.ɵɵFactoryTarget.Component });
277
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: PlanoDataExportComponent, selector: "lib-plano-data-export", ngImport: i0, template: "<section class=\"plano-data-export p-3\">\r\n <div class=\"card p-4 mb-3\">\r\n <h5 class=\"mb-1\">Plano Data Export</h5>\r\n <p class=\"text-muted small mb-3\">\r\n Build a query against planogram fixtures, preview results, and export as Excel.\r\n </p>\r\n\r\n @if (isLoadingSchema) {\r\n <div class=\"text-muted small\">Loading query schema...</div>\r\n }\r\n\r\n <!-- Stores -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Stores</div>\r\n <lib-store-select\r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"initialStores\"\r\n (selectedChange)=\"onStoresSelected($event)\">\r\n </lib-store-select>\r\n </div>\r\n\r\n <!-- Match Criteria -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Match Criteria</div>\r\n <div class=\"d-flex align-items-center gap-3\">\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combAnd\"\r\n name=\"combinator\" value=\"AND\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combAnd\">Match all (AND)</label>\r\n </div>\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combOr\"\r\n name=\"combinator\" value=\"OR\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combOr\">Match any (OR)</label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n @if (!filters.length) {\r\n <div class=\"text-muted small mb-2\">\r\n No criteria \u2014 query will return every fixture for the selected stores.\r\n </div>\r\n }\r\n\r\n @for (row of filters; track $index) {\r\n <div class=\"filter-row d-flex gap-2 mb-2 align-items-center\">\r\n <select class=\"form-select form-select-sm filter-field\"\r\n [(ngModel)]=\"row.field\"\r\n (change)=\"onFilterFieldChange($index)\">\r\n @for (f of filterableFields; track f.key) {\r\n <option [value]=\"f.key\">{{ f.label }}</option>\r\n }\r\n </select>\r\n\r\n <select class=\"form-select form-select-sm filter-op\"\r\n [(ngModel)]=\"row.operator\">\r\n @for (op of operatorsForField(row.field); track op.key) {\r\n <option [value]=\"op.key\">{{ op.label }}</option>\r\n }\r\n </select>\r\n\r\n <input\r\n class=\"form-control form-control-sm filter-value\"\r\n [placeholder]=\"isValueDisabledFor(row.operator) ? '\u2014' : 'value'\"\r\n [disabled]=\"isValueDisabledFor(row.operator)\"\r\n [(ngModel)]=\"row.value\">\r\n\r\n <button class=\"btn btn-sm btn-outline-danger\" (click)=\"removeFilter($index)\"\r\n title=\"Remove\">\u00D7</button>\r\n </div>\r\n }\r\n\r\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"addFilter()\"\r\n [disabled]=\"!filterableFields.length\">\r\n + Add Criterion\r\n </button>\r\n </div>\r\n\r\n <!-- Selection Mode -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Fixture Selection</div>\r\n <div class=\"d-flex flex-wrap align-items-center gap-3\">\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selAll\"\r\n name=\"selectionMode\" value=\"all\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selAll\">All matching fixtures</label>\r\n </div>\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selFirstN\"\r\n name=\"selectionMode\" value=\"firstN\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selFirstN\">First</label>\r\n </div>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n class=\"form-control form-control-sm count-input\"\r\n [(ngModel)]=\"limitPerStore\"\r\n [disabled]=\"selectionMode !== 'firstN'\">\r\n <span class=\"text-muted small\">matching from entrance, per store</span>\r\n </div>\r\n\r\n <div class=\"form-check mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" id=\"incNotFound\"\r\n [(ngModel)]=\"includeNotFoundRows\">\r\n <label class=\"form-check-label\" for=\"incNotFound\">\r\n Include empty rows for stores with no matches\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <!-- Output Columns -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Output Columns</div>\r\n <div class=\"d-flex gap-2\">\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"selectAllColumns()\">\r\n Select all\r\n </button>\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"clearAllColumns()\">\r\n Clear\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"column-grid\">\r\n @for (col of outputColumns; track col.key) {\r\n <label class=\"column-item\">\r\n <input type=\"checkbox\" class=\"form-check-input me-2\"\r\n [(ngModel)]=\"col.selected\">\r\n {{ col.label }}\r\n </label>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"onRun()\"\r\n [disabled]=\"isRunning || isLoadingSchema || selectedStores.length === 0\">\r\n {{ isRunning ? 'Running...' : 'Run Query' }}\r\n </button>\r\n <button\r\n class=\"btn btn-success\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"!result || !result.rows.length\">\r\n Export to Excel\r\n </button>\r\n </div>\r\n\r\n @if (message) {\r\n <div\r\n class=\"mt-3 alert\"\r\n [class.alert-success]=\"messageType === 'success'\"\r\n [class.alert-danger]=\"messageType === 'error'\">\r\n {{ message }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Result Preview -->\r\n @if (result) {\r\n <div class=\"card p-4\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-3\">\r\n <div>\r\n <h6 class=\"mb-0\">Results</h6>\r\n <small class=\"text-muted\">\r\n {{ totalRows }} row(s)\r\n @if (totalRows) {\r\n \u00B7 showing {{ pageStart }}\u2013{{ pageEnd }}\r\n }\r\n </small>\r\n </div>\r\n </div>\r\n\r\n @if (!result.rows.length) {\r\n <div class=\"text-muted\">No data found for the given query.</div>\r\n } @else {\r\n <div class=\"table-responsive\">\r\n <table class=\"table table-sm table-bordered\">\r\n <thead>\r\n <tr>\r\n @for (col of resultColumns; track col.key) {\r\n <th>{{ col.label }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of pagedRows; track $index) {\r\n <tr [class.row-not-found]=\"row['__notFound']\">\r\n @for (col of resultColumns; track col.key) {\r\n <td\r\n [ngbTooltip]=\"row[col.label]?.toString() ? row[col.label] : null\"\r\n container=\"body\"\r\n placement=\"top\"\r\n [openDelay]=\"300\">\r\n {{ row[col.label] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <lib-pagination\r\n [itemsPerPage]=\"pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [totalItems]=\"totalRows\"\r\n [pageSize]=\"pageSize\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [directionLinks]=\"true\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (pageSizeChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n }\r\n </div>\r\n }\r\n</section>\r\n", styles: [".plano-data-export .card{border:1px solid #e0e0e0}.plano-data-export .block{border:1px solid #e9ecef;border-radius:6px;padding:12px 14px;background:#fafbfc}.plano-data-export .block-title{font-weight:600;font-size:.95rem;color:#344054}.plano-data-export .filter-row .filter-field{flex:0 0 220px}.plano-data-export .filter-row .filter-op{flex:0 0 200px}.plano-data-export .filter-row .filter-value{flex:1 1 auto;min-width:120px}.plano-data-export .count-input{width:80px}.plano-data-export .column-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:6px 14px}.plano-data-export .column-item{display:flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:.92rem;margin-bottom:0}.plano-data-export .table th{white-space:nowrap;background:#f8f9fa;position:sticky;top:0;z-index:1}.plano-data-export .table td{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:default}.plano-data-export .row-not-found td{color:#98a2b3;font-style:italic}.plano-data-export .table-responsive{max-height:480px;overflow:auto}\n"], dependencies: [{ kind: "directive", type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.PaginationComponent, selector: "lib-pagination", inputs: ["collection", "itemsPerPage", "currentPage", "totalItems", "directionLinks", "pageSize", "paginationSizes"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "directive", type: i5.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: i6.StoreSelectComponent, selector: "lib-store-select", inputs: ["options", "initialSelected", "singleSelect"], outputs: ["selectedChange"] }] });
372
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: PlanoDataExportComponent, selector: "lib-plano-data-export", ngImport: i0, template: "<section class=\"plano-data-export p-3\">\r\n <div class=\"card p-4 mb-3\">\r\n <h5 class=\"mb-1\">Plano Data Export</h5>\r\n <p class=\"text-muted small mb-3\">\r\n Build a query against planogram fixtures, preview results, and export as Excel.\r\n </p>\r\n\r\n @if (isLoadingSchema) {\r\n <div class=\"text-muted small\">Loading query schema...</div>\r\n }\r\n\r\n <!-- Stores -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Stores</div>\r\n <lib-store-select\r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"initialStores\"\r\n (selectedChange)=\"onStoresSelected($event)\">\r\n </lib-store-select>\r\n </div>\r\n\r\n <!-- Match Criteria -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Match Criteria</div>\r\n <div class=\"d-flex align-items-center gap-3\">\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combAnd\"\r\n name=\"combinator\" value=\"AND\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combAnd\">Match all (AND)</label>\r\n </div>\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combOr\"\r\n name=\"combinator\" value=\"OR\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combOr\">Match any (OR)</label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n @if (!filters.length) {\r\n <div class=\"text-muted small mb-2\">\r\n No criteria \u2014 query will return every fixture for the selected stores.\r\n </div>\r\n }\r\n\r\n @for (row of filters; track $index) {\r\n <div class=\"filter-row d-flex gap-2 mb-2 align-items-center\">\r\n <select class=\"form-select form-select-sm filter-field\"\r\n [(ngModel)]=\"row.field\"\r\n (change)=\"onFilterFieldChange($index)\">\r\n @for (f of filterableFields; track f.key) {\r\n <option [value]=\"f.key\">{{ f.label }}</option>\r\n }\r\n </select>\r\n\r\n <select class=\"form-select form-select-sm filter-op\"\r\n [(ngModel)]=\"row.operator\">\r\n @for (op of operatorsForField(row.field); track op.key) {\r\n <option [value]=\"op.key\">{{ op.label }}</option>\r\n }\r\n </select>\r\n\r\n <input\r\n class=\"form-control form-control-sm filter-value\"\r\n [placeholder]=\"isValueDisabledFor(row.operator) ? '\u2014' : 'value'\"\r\n [disabled]=\"isValueDisabledFor(row.operator)\"\r\n [(ngModel)]=\"row.value\">\r\n\r\n <button class=\"btn btn-sm btn-outline-danger\" (click)=\"removeFilter($index)\"\r\n title=\"Remove\">\u00D7</button>\r\n </div>\r\n }\r\n\r\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"addFilter()\"\r\n [disabled]=\"!filterableFields.length\">\r\n + Add Criterion\r\n </button>\r\n </div>\r\n\r\n <!-- Selection Mode -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Fixture Selection</div>\r\n <div class=\"d-flex flex-wrap align-items-center gap-3\">\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selAll\"\r\n name=\"selectionMode\" value=\"all\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selAll\">All matching fixtures</label>\r\n </div>\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selFirstN\"\r\n name=\"selectionMode\" value=\"firstN\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selFirstN\">First</label>\r\n </div>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n class=\"form-control form-control-sm count-input\"\r\n [(ngModel)]=\"limitPerStore\"\r\n [disabled]=\"selectionMode !== 'firstN'\">\r\n <span class=\"text-muted small\">matching from entrance, per store</span>\r\n </div>\r\n\r\n <div class=\"form-check mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" id=\"incNotFound\"\r\n [(ngModel)]=\"includeNotFoundRows\">\r\n <label class=\"form-check-label\" for=\"incNotFound\">\r\n Include empty rows for stores with no matches\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <!-- Output Columns -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Output Columns</div>\r\n <div class=\"d-flex gap-2\">\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"selectAllColumns()\">\r\n Select all\r\n </button>\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"clearAllColumns()\">\r\n Clear\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"column-grid\">\r\n @for (col of outputColumns; track col.key) {\r\n <label class=\"column-item\">\r\n <input type=\"checkbox\" class=\"form-check-input me-2\"\r\n [(ngModel)]=\"col.selected\">\r\n {{ col.label }}\r\n </label>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"onRun()\"\r\n [disabled]=\"isRunning || isLoadingSchema || selectedStores.length === 0\">\r\n {{ isRunning ? 'Running...' : 'Run Query' }}\r\n </button>\r\n <button\r\n class=\"btn btn-success\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"!result || !result.rows.length\">\r\n Export to Excel\r\n </button>\r\n </div>\r\n\r\n @if (message) {\r\n <div\r\n class=\"mt-3 alert\"\r\n [class.alert-success]=\"messageType === 'success'\"\r\n [class.alert-danger]=\"messageType === 'error'\">\r\n {{ message }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- VM Placement Export by VM Name -->\r\n <div class=\"card p-4 mb-3\">\r\n <h5 class=\"mb-1\">VM Placement Export by VM Name</h5>\r\n <p class=\"text-muted small mb-3\">\r\n Find every fixture (in the selected stores) that contains any VM whose\r\n <code>vmName</code> matches the regex, and export one row per VM placement\r\n with fixture details and shelf/zone coordinates.\r\n </p>\r\n\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Stores</div>\r\n <lib-store-select\r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"vmInitialStores\"\r\n (selectedChange)=\"onVmStoresSelected($event)\">\r\n </lib-store-select>\r\n </div>\r\n\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">VM Name (regex)</div>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"e.g. Zodiac, ^Hiphop, Leatherite\"\r\n [(ngModel)]=\"vmNameRegex\">\r\n <small class=\"text-muted\">Case-insensitive. Matched against the <code>planoVmDetails.vmName</code> field.</small>\r\n </div>\r\n\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"onVmRun()\"\r\n [disabled]=\"isVmRunning || vmSelectedStores.length === 0 || !vmNameRegex.trim()\">\r\n {{ isVmRunning ? 'Running...' : 'Run Query' }}\r\n </button>\r\n <button\r\n class=\"btn btn-success\"\r\n (click)=\"onVmExport()\"\r\n [disabled]=\"!vmResult || !vmResult.rows.length\">\r\n Export to Excel\r\n </button>\r\n </div>\r\n\r\n @if (vmMessage) {\r\n <div\r\n class=\"mt-3 alert\"\r\n [class.alert-success]=\"vmMessageType === 'success'\"\r\n [class.alert-danger]=\"vmMessageType === 'error'\">\r\n {{ vmMessage }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (vmResult) {\r\n <div class=\"card p-4 mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-3\">\r\n <div>\r\n <h6 class=\"mb-0\">VM Placement Results</h6>\r\n <small class=\"text-muted\">\r\n {{ vmTotalRows }} row(s)\r\n @if (vmTotalRows) {\r\n \u00B7 showing {{ vmPageStart }}\u2013{{ vmPageEnd }}\r\n }\r\n </small>\r\n </div>\r\n </div>\r\n\r\n @if (!vmResult.rows.length) {\r\n <div class=\"text-muted\">No VM placements found for the given stores and vmName.</div>\r\n } @else {\r\n <div class=\"table-responsive\">\r\n <table class=\"table table-sm table-bordered\">\r\n <thead>\r\n <tr>\r\n @for (col of vmResultColumns; track col) {\r\n <th>{{ col }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of vmPagedRows; track $index) {\r\n <tr>\r\n @for (col of vmResultColumns; track col) {\r\n <td\r\n [ngbTooltip]=\"row[col]?.toString() ? row[col] : null\"\r\n container=\"body\"\r\n placement=\"top\"\r\n [openDelay]=\"300\">\r\n {{ row[col] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <lib-pagination\r\n [itemsPerPage]=\"vmPageSize\"\r\n [currentPage]=\"vmCurrentPage\"\r\n [totalItems]=\"vmTotalRows\"\r\n [pageSize]=\"vmPageSize\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [directionLinks]=\"true\"\r\n (pageChange)=\"onVmPageChange($event)\"\r\n (pageSizeChange)=\"onVmPageSizeChange($event)\">\r\n </lib-pagination>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Result Preview -->\r\n @if (result) {\r\n <div class=\"card p-4\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-3\">\r\n <div>\r\n <h6 class=\"mb-0\">Results</h6>\r\n <small class=\"text-muted\">\r\n {{ totalRows }} row(s)\r\n @if (totalRows) {\r\n \u00B7 showing {{ pageStart }}\u2013{{ pageEnd }}\r\n }\r\n </small>\r\n </div>\r\n </div>\r\n\r\n @if (!result.rows.length) {\r\n <div class=\"text-muted\">No data found for the given query.</div>\r\n } @else {\r\n <div class=\"table-responsive\">\r\n <table class=\"table table-sm table-bordered\">\r\n <thead>\r\n <tr>\r\n @for (col of resultColumns; track col.key) {\r\n <th>{{ col.label }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of pagedRows; track $index) {\r\n <tr [class.row-not-found]=\"row['__notFound']\">\r\n @for (col of resultColumns; track col.key) {\r\n <td\r\n [ngbTooltip]=\"row[col.label]?.toString() ? row[col.label] : null\"\r\n container=\"body\"\r\n placement=\"top\"\r\n [openDelay]=\"300\">\r\n {{ row[col.label] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <lib-pagination\r\n [itemsPerPage]=\"pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [totalItems]=\"totalRows\"\r\n [pageSize]=\"pageSize\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [directionLinks]=\"true\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (pageSizeChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n }\r\n </div>\r\n }\r\n</section>\r\n", styles: [".plano-data-export .card{border:1px solid #e0e0e0}.plano-data-export .block{border:1px solid #e9ecef;border-radius:6px;padding:12px 14px;background:#fafbfc}.plano-data-export .block-title{font-weight:600;font-size:.95rem;color:#344054}.plano-data-export .filter-row .filter-field{flex:0 0 220px}.plano-data-export .filter-row .filter-op{flex:0 0 200px}.plano-data-export .filter-row .filter-value{flex:1 1 auto;min-width:120px}.plano-data-export .count-input{width:80px}.plano-data-export .column-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:6px 14px}.plano-data-export .column-item{display:flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:.92rem;margin-bottom:0}.plano-data-export .table th{white-space:nowrap;background:#f8f9fa;position:sticky;top:0;z-index:1}.plano-data-export .table td{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:default}.plano-data-export .row-not-found td{color:#98a2b3;font-style:italic}.plano-data-export .table-responsive{max-height:480px;overflow:auto}\n"], dependencies: [{ kind: "directive", type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.PaginationComponent, selector: "lib-pagination", inputs: ["collection", "itemsPerPage", "currentPage", "totalItems", "directionLinks", "pageSize", "paginationSizes"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "directive", type: i5.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: i6.StoreSelectComponent, selector: "lib-store-select", inputs: ["options", "initialSelected", "singleSelect"], outputs: ["selectedChange"] }] });
278
373
  }
279
374
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PlanoDataExportComponent, decorators: [{
280
375
  type: Component,
281
- args: [{ selector: 'lib-plano-data-export', template: "<section class=\"plano-data-export p-3\">\r\n <div class=\"card p-4 mb-3\">\r\n <h5 class=\"mb-1\">Plano Data Export</h5>\r\n <p class=\"text-muted small mb-3\">\r\n Build a query against planogram fixtures, preview results, and export as Excel.\r\n </p>\r\n\r\n @if (isLoadingSchema) {\r\n <div class=\"text-muted small\">Loading query schema...</div>\r\n }\r\n\r\n <!-- Stores -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Stores</div>\r\n <lib-store-select\r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"initialStores\"\r\n (selectedChange)=\"onStoresSelected($event)\">\r\n </lib-store-select>\r\n </div>\r\n\r\n <!-- Match Criteria -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Match Criteria</div>\r\n <div class=\"d-flex align-items-center gap-3\">\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combAnd\"\r\n name=\"combinator\" value=\"AND\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combAnd\">Match all (AND)</label>\r\n </div>\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combOr\"\r\n name=\"combinator\" value=\"OR\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combOr\">Match any (OR)</label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n @if (!filters.length) {\r\n <div class=\"text-muted small mb-2\">\r\n No criteria \u2014 query will return every fixture for the selected stores.\r\n </div>\r\n }\r\n\r\n @for (row of filters; track $index) {\r\n <div class=\"filter-row d-flex gap-2 mb-2 align-items-center\">\r\n <select class=\"form-select form-select-sm filter-field\"\r\n [(ngModel)]=\"row.field\"\r\n (change)=\"onFilterFieldChange($index)\">\r\n @for (f of filterableFields; track f.key) {\r\n <option [value]=\"f.key\">{{ f.label }}</option>\r\n }\r\n </select>\r\n\r\n <select class=\"form-select form-select-sm filter-op\"\r\n [(ngModel)]=\"row.operator\">\r\n @for (op of operatorsForField(row.field); track op.key) {\r\n <option [value]=\"op.key\">{{ op.label }}</option>\r\n }\r\n </select>\r\n\r\n <input\r\n class=\"form-control form-control-sm filter-value\"\r\n [placeholder]=\"isValueDisabledFor(row.operator) ? '\u2014' : 'value'\"\r\n [disabled]=\"isValueDisabledFor(row.operator)\"\r\n [(ngModel)]=\"row.value\">\r\n\r\n <button class=\"btn btn-sm btn-outline-danger\" (click)=\"removeFilter($index)\"\r\n title=\"Remove\">\u00D7</button>\r\n </div>\r\n }\r\n\r\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"addFilter()\"\r\n [disabled]=\"!filterableFields.length\">\r\n + Add Criterion\r\n </button>\r\n </div>\r\n\r\n <!-- Selection Mode -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Fixture Selection</div>\r\n <div class=\"d-flex flex-wrap align-items-center gap-3\">\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selAll\"\r\n name=\"selectionMode\" value=\"all\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selAll\">All matching fixtures</label>\r\n </div>\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selFirstN\"\r\n name=\"selectionMode\" value=\"firstN\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selFirstN\">First</label>\r\n </div>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n class=\"form-control form-control-sm count-input\"\r\n [(ngModel)]=\"limitPerStore\"\r\n [disabled]=\"selectionMode !== 'firstN'\">\r\n <span class=\"text-muted small\">matching from entrance, per store</span>\r\n </div>\r\n\r\n <div class=\"form-check mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" id=\"incNotFound\"\r\n [(ngModel)]=\"includeNotFoundRows\">\r\n <label class=\"form-check-label\" for=\"incNotFound\">\r\n Include empty rows for stores with no matches\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <!-- Output Columns -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Output Columns</div>\r\n <div class=\"d-flex gap-2\">\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"selectAllColumns()\">\r\n Select all\r\n </button>\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"clearAllColumns()\">\r\n Clear\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"column-grid\">\r\n @for (col of outputColumns; track col.key) {\r\n <label class=\"column-item\">\r\n <input type=\"checkbox\" class=\"form-check-input me-2\"\r\n [(ngModel)]=\"col.selected\">\r\n {{ col.label }}\r\n </label>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"onRun()\"\r\n [disabled]=\"isRunning || isLoadingSchema || selectedStores.length === 0\">\r\n {{ isRunning ? 'Running...' : 'Run Query' }}\r\n </button>\r\n <button\r\n class=\"btn btn-success\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"!result || !result.rows.length\">\r\n Export to Excel\r\n </button>\r\n </div>\r\n\r\n @if (message) {\r\n <div\r\n class=\"mt-3 alert\"\r\n [class.alert-success]=\"messageType === 'success'\"\r\n [class.alert-danger]=\"messageType === 'error'\">\r\n {{ message }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Result Preview -->\r\n @if (result) {\r\n <div class=\"card p-4\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-3\">\r\n <div>\r\n <h6 class=\"mb-0\">Results</h6>\r\n <small class=\"text-muted\">\r\n {{ totalRows }} row(s)\r\n @if (totalRows) {\r\n \u00B7 showing {{ pageStart }}\u2013{{ pageEnd }}\r\n }\r\n </small>\r\n </div>\r\n </div>\r\n\r\n @if (!result.rows.length) {\r\n <div class=\"text-muted\">No data found for the given query.</div>\r\n } @else {\r\n <div class=\"table-responsive\">\r\n <table class=\"table table-sm table-bordered\">\r\n <thead>\r\n <tr>\r\n @for (col of resultColumns; track col.key) {\r\n <th>{{ col.label }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of pagedRows; track $index) {\r\n <tr [class.row-not-found]=\"row['__notFound']\">\r\n @for (col of resultColumns; track col.key) {\r\n <td\r\n [ngbTooltip]=\"row[col.label]?.toString() ? row[col.label] : null\"\r\n container=\"body\"\r\n placement=\"top\"\r\n [openDelay]=\"300\">\r\n {{ row[col.label] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <lib-pagination\r\n [itemsPerPage]=\"pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [totalItems]=\"totalRows\"\r\n [pageSize]=\"pageSize\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [directionLinks]=\"true\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (pageSizeChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n }\r\n </div>\r\n }\r\n</section>\r\n", styles: [".plano-data-export .card{border:1px solid #e0e0e0}.plano-data-export .block{border:1px solid #e9ecef;border-radius:6px;padding:12px 14px;background:#fafbfc}.plano-data-export .block-title{font-weight:600;font-size:.95rem;color:#344054}.plano-data-export .filter-row .filter-field{flex:0 0 220px}.plano-data-export .filter-row .filter-op{flex:0 0 200px}.plano-data-export .filter-row .filter-value{flex:1 1 auto;min-width:120px}.plano-data-export .count-input{width:80px}.plano-data-export .column-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:6px 14px}.plano-data-export .column-item{display:flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:.92rem;margin-bottom:0}.plano-data-export .table th{white-space:nowrap;background:#f8f9fa;position:sticky;top:0;z-index:1}.plano-data-export .table td{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:default}.plano-data-export .row-not-found td{color:#98a2b3;font-style:italic}.plano-data-export .table-responsive{max-height:480px;overflow:auto}\n"] }]
376
+ args: [{ selector: 'lib-plano-data-export', template: "<section class=\"plano-data-export p-3\">\r\n <div class=\"card p-4 mb-3\">\r\n <h5 class=\"mb-1\">Plano Data Export</h5>\r\n <p class=\"text-muted small mb-3\">\r\n Build a query against planogram fixtures, preview results, and export as Excel.\r\n </p>\r\n\r\n @if (isLoadingSchema) {\r\n <div class=\"text-muted small\">Loading query schema...</div>\r\n }\r\n\r\n <!-- Stores -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Stores</div>\r\n <lib-store-select\r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"initialStores\"\r\n (selectedChange)=\"onStoresSelected($event)\">\r\n </lib-store-select>\r\n </div>\r\n\r\n <!-- Match Criteria -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Match Criteria</div>\r\n <div class=\"d-flex align-items-center gap-3\">\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combAnd\"\r\n name=\"combinator\" value=\"AND\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combAnd\">Match all (AND)</label>\r\n </div>\r\n <div class=\"form-check form-check-inline mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"combOr\"\r\n name=\"combinator\" value=\"OR\" [(ngModel)]=\"filterCombinator\">\r\n <label class=\"form-check-label\" for=\"combOr\">Match any (OR)</label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n @if (!filters.length) {\r\n <div class=\"text-muted small mb-2\">\r\n No criteria \u2014 query will return every fixture for the selected stores.\r\n </div>\r\n }\r\n\r\n @for (row of filters; track $index) {\r\n <div class=\"filter-row d-flex gap-2 mb-2 align-items-center\">\r\n <select class=\"form-select form-select-sm filter-field\"\r\n [(ngModel)]=\"row.field\"\r\n (change)=\"onFilterFieldChange($index)\">\r\n @for (f of filterableFields; track f.key) {\r\n <option [value]=\"f.key\">{{ f.label }}</option>\r\n }\r\n </select>\r\n\r\n <select class=\"form-select form-select-sm filter-op\"\r\n [(ngModel)]=\"row.operator\">\r\n @for (op of operatorsForField(row.field); track op.key) {\r\n <option [value]=\"op.key\">{{ op.label }}</option>\r\n }\r\n </select>\r\n\r\n <input\r\n class=\"form-control form-control-sm filter-value\"\r\n [placeholder]=\"isValueDisabledFor(row.operator) ? '\u2014' : 'value'\"\r\n [disabled]=\"isValueDisabledFor(row.operator)\"\r\n [(ngModel)]=\"row.value\">\r\n\r\n <button class=\"btn btn-sm btn-outline-danger\" (click)=\"removeFilter($index)\"\r\n title=\"Remove\">\u00D7</button>\r\n </div>\r\n }\r\n\r\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"addFilter()\"\r\n [disabled]=\"!filterableFields.length\">\r\n + Add Criterion\r\n </button>\r\n </div>\r\n\r\n <!-- Selection Mode -->\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Fixture Selection</div>\r\n <div class=\"d-flex flex-wrap align-items-center gap-3\">\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selAll\"\r\n name=\"selectionMode\" value=\"all\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selAll\">All matching fixtures</label>\r\n </div>\r\n <div class=\"form-check mb-0\">\r\n <input class=\"form-check-input\" type=\"radio\" id=\"selFirstN\"\r\n name=\"selectionMode\" value=\"firstN\" [(ngModel)]=\"selectionMode\">\r\n <label class=\"form-check-label\" for=\"selFirstN\">First</label>\r\n </div>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n class=\"form-control form-control-sm count-input\"\r\n [(ngModel)]=\"limitPerStore\"\r\n [disabled]=\"selectionMode !== 'firstN'\">\r\n <span class=\"text-muted small\">matching from entrance, per store</span>\r\n </div>\r\n\r\n <div class=\"form-check mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" id=\"incNotFound\"\r\n [(ngModel)]=\"includeNotFoundRows\">\r\n <label class=\"form-check-label\" for=\"incNotFound\">\r\n Include empty rows for stores with no matches\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <!-- Output Columns -->\r\n <div class=\"block mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\r\n <div class=\"block-title mb-0\">Output Columns</div>\r\n <div class=\"d-flex gap-2\">\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"selectAllColumns()\">\r\n Select all\r\n </button>\r\n <button class=\"btn btn-sm btn-link p-0\" (click)=\"clearAllColumns()\">\r\n Clear\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"column-grid\">\r\n @for (col of outputColumns; track col.key) {\r\n <label class=\"column-item\">\r\n <input type=\"checkbox\" class=\"form-check-input me-2\"\r\n [(ngModel)]=\"col.selected\">\r\n {{ col.label }}\r\n </label>\r\n }\r\n </div>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"onRun()\"\r\n [disabled]=\"isRunning || isLoadingSchema || selectedStores.length === 0\">\r\n {{ isRunning ? 'Running...' : 'Run Query' }}\r\n </button>\r\n <button\r\n class=\"btn btn-success\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"!result || !result.rows.length\">\r\n Export to Excel\r\n </button>\r\n </div>\r\n\r\n @if (message) {\r\n <div\r\n class=\"mt-3 alert\"\r\n [class.alert-success]=\"messageType === 'success'\"\r\n [class.alert-danger]=\"messageType === 'error'\">\r\n {{ message }}\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- VM Placement Export by VM Name -->\r\n <div class=\"card p-4 mb-3\">\r\n <h5 class=\"mb-1\">VM Placement Export by VM Name</h5>\r\n <p class=\"text-muted small mb-3\">\r\n Find every fixture (in the selected stores) that contains any VM whose\r\n <code>vmName</code> matches the regex, and export one row per VM placement\r\n with fixture details and shelf/zone coordinates.\r\n </p>\r\n\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">Stores</div>\r\n <lib-store-select\r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"vmInitialStores\"\r\n (selectedChange)=\"onVmStoresSelected($event)\">\r\n </lib-store-select>\r\n </div>\r\n\r\n <div class=\"block mb-3\">\r\n <div class=\"block-title\">VM Name (regex)</div>\r\n <input\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"e.g. Zodiac, ^Hiphop, Leatherite\"\r\n [(ngModel)]=\"vmNameRegex\">\r\n <small class=\"text-muted\">Case-insensitive. Matched against the <code>planoVmDetails.vmName</code> field.</small>\r\n </div>\r\n\r\n <div class=\"d-flex gap-2\">\r\n <button\r\n class=\"btn btn-primary\"\r\n (click)=\"onVmRun()\"\r\n [disabled]=\"isVmRunning || vmSelectedStores.length === 0 || !vmNameRegex.trim()\">\r\n {{ isVmRunning ? 'Running...' : 'Run Query' }}\r\n </button>\r\n <button\r\n class=\"btn btn-success\"\r\n (click)=\"onVmExport()\"\r\n [disabled]=\"!vmResult || !vmResult.rows.length\">\r\n Export to Excel\r\n </button>\r\n </div>\r\n\r\n @if (vmMessage) {\r\n <div\r\n class=\"mt-3 alert\"\r\n [class.alert-success]=\"vmMessageType === 'success'\"\r\n [class.alert-danger]=\"vmMessageType === 'error'\">\r\n {{ vmMessage }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (vmResult) {\r\n <div class=\"card p-4 mb-3\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-3\">\r\n <div>\r\n <h6 class=\"mb-0\">VM Placement Results</h6>\r\n <small class=\"text-muted\">\r\n {{ vmTotalRows }} row(s)\r\n @if (vmTotalRows) {\r\n \u00B7 showing {{ vmPageStart }}\u2013{{ vmPageEnd }}\r\n }\r\n </small>\r\n </div>\r\n </div>\r\n\r\n @if (!vmResult.rows.length) {\r\n <div class=\"text-muted\">No VM placements found for the given stores and vmName.</div>\r\n } @else {\r\n <div class=\"table-responsive\">\r\n <table class=\"table table-sm table-bordered\">\r\n <thead>\r\n <tr>\r\n @for (col of vmResultColumns; track col) {\r\n <th>{{ col }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of vmPagedRows; track $index) {\r\n <tr>\r\n @for (col of vmResultColumns; track col) {\r\n <td\r\n [ngbTooltip]=\"row[col]?.toString() ? row[col] : null\"\r\n container=\"body\"\r\n placement=\"top\"\r\n [openDelay]=\"300\">\r\n {{ row[col] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <lib-pagination\r\n [itemsPerPage]=\"vmPageSize\"\r\n [currentPage]=\"vmCurrentPage\"\r\n [totalItems]=\"vmTotalRows\"\r\n [pageSize]=\"vmPageSize\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [directionLinks]=\"true\"\r\n (pageChange)=\"onVmPageChange($event)\"\r\n (pageSizeChange)=\"onVmPageSizeChange($event)\">\r\n </lib-pagination>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Result Preview -->\r\n @if (result) {\r\n <div class=\"card p-4\">\r\n <div class=\"d-flex align-items-center justify-content-between mb-3\">\r\n <div>\r\n <h6 class=\"mb-0\">Results</h6>\r\n <small class=\"text-muted\">\r\n {{ totalRows }} row(s)\r\n @if (totalRows) {\r\n \u00B7 showing {{ pageStart }}\u2013{{ pageEnd }}\r\n }\r\n </small>\r\n </div>\r\n </div>\r\n\r\n @if (!result.rows.length) {\r\n <div class=\"text-muted\">No data found for the given query.</div>\r\n } @else {\r\n <div class=\"table-responsive\">\r\n <table class=\"table table-sm table-bordered\">\r\n <thead>\r\n <tr>\r\n @for (col of resultColumns; track col.key) {\r\n <th>{{ col.label }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of pagedRows; track $index) {\r\n <tr [class.row-not-found]=\"row['__notFound']\">\r\n @for (col of resultColumns; track col.key) {\r\n <td\r\n [ngbTooltip]=\"row[col.label]?.toString() ? row[col.label] : null\"\r\n container=\"body\"\r\n placement=\"top\"\r\n [openDelay]=\"300\">\r\n {{ row[col.label] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <lib-pagination\r\n [itemsPerPage]=\"pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [totalItems]=\"totalRows\"\r\n [pageSize]=\"pageSize\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [directionLinks]=\"true\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (pageSizeChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n }\r\n </div>\r\n }\r\n</section>\r\n", styles: [".plano-data-export .card{border:1px solid #e0e0e0}.plano-data-export .block{border:1px solid #e9ecef;border-radius:6px;padding:12px 14px;background:#fafbfc}.plano-data-export .block-title{font-weight:600;font-size:.95rem;color:#344054}.plano-data-export .filter-row .filter-field{flex:0 0 220px}.plano-data-export .filter-row .filter-op{flex:0 0 200px}.plano-data-export .filter-row .filter-value{flex:1 1 auto;min-width:120px}.plano-data-export .count-input{width:80px}.plano-data-export .column-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:6px 14px}.plano-data-export .column-item{display:flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:.92rem;margin-bottom:0}.plano-data-export .table th{white-space:nowrap;background:#f8f9fa;position:sticky;top:0;z-index:1}.plano-data-export .table td{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:default}.plano-data-export .row-not-found td{color:#98a2b3;font-style:italic}.plano-data-export .table-responsive{max-height:480px;overflow:auto}\n"] }]
282
377
  }], ctorParameters: () => [{ type: i1.StoreBuilderService }, { type: i2.GlobalStateService }] });
283
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbm8tZGF0YS1leHBvcnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvcGxhbm8tZGF0YS1leHBvcnQvcGxhbm8tZGF0YS1leHBvcnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvcGxhbm8tZGF0YS1leHBvcnQvcGxhbm8tZGF0YS1leHBvcnQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFHN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7Ozs7QUFrQ3RGLE1BQU0sbUJBQW1CLEdBQXFDO0lBQzVELEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFO0lBQ3pDLEVBQUUsR0FBRyxFQUFFLGlCQUFpQixFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRTtJQUNyRCxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRTtJQUMvQyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLGdCQUFnQixFQUFFO0lBQ2pELEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdDLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdDLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdDLEVBQUUs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R0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDO3dHQXJTVSx3QkFBd0I7NEZBQXhCLHdCQUF3Qiw2REM3RHJDLGs0UUE0TkE7OzRGRC9KYSx3QkFBd0I7a0JBTHBDLFNBQVM7K0JBQ0UsdUJBQXVCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBTdG9yZUJ1aWxkZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvc3RvcmUtYnVpbGRlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgR2xvYmFsU3RhdGVTZXJ2aWNlIH0gZnJvbSAndGFuZ28tYXBwLXVpLWdsb2JhbCc7XHJcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCwgZGVib3VuY2VUaW1lLCBmaWx0ZXIsIGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFN0b3JlT3B0aW9uIH0gZnJvbSAnLi4vLi4vY29sbGVjdGlvbi11cGRhdGUtYWkvY29tcG9uZW50cy9zdG9yZS1zZWxlY3Qvc3RvcmUtc2VsZWN0LmNvbXBvbmVudCc7XHJcblxyXG5pbnRlcmZhY2UgRmllbGREZWYge1xyXG4gIGtleTogc3RyaW5nO1xyXG4gIGxhYmVsOiBzdHJpbmc7XHJcbiAgdHlwZTogJ3N0cmluZycgfCAnbnVtYmVyJyB8ICdhcnJheU9mU3RyaW5ncyc7XHJcbiAgZmlsdGVyYWJsZTogYm9vbGVhbjtcclxuICBvdXRwdXQ6IGJvb2xlYW47XHJcbn1cclxuXHJcbmludGVyZmFjZSBPcGVyYXRvckRlZiB7XHJcbiAga2V5OiBzdHJpbmc7XHJcbiAgbGFiZWw6IHN0cmluZztcclxufVxyXG5cclxuaW50ZXJmYWNlIEZpbHRlclJvdyB7XHJcbiAgZmllbGQ6IHN0cmluZztcclxuICBvcGVyYXRvcjogc3RyaW5nO1xyXG4gIHZhbHVlOiBzdHJpbmc7XHJcbn1cclxuXHJcbmludGVyZmFjZSBDb2x1bW5TZWxlY3Rpb24ge1xyXG4gIGtleTogc3RyaW5nO1xyXG4gIGxhYmVsOiBzdHJpbmc7XHJcbiAgc2VsZWN0ZWQ6IGJvb2xlYW47XHJcbn1cclxuXHJcbmludGVyZmFjZSBRdWVyeVJlc3VsdCB7XHJcbiAgY29sdW1uczogc3RyaW5nW107XHJcbiAgcm93czogUmVjb3JkPHN0cmluZywgYW55PltdO1xyXG4gIHRvdGFsUm93czogbnVtYmVyO1xyXG59XHJcblxyXG5jb25zdCBPVVRQVVRfQ09MVU1OX09SREVSOiB7IGtleTogc3RyaW5nOyBsYWJlbDogc3RyaW5nIH1bXSA9IFtcclxuICB7IGtleTogJ3N0b3JlTmFtZScsIGxhYmVsOiAnU3RvcmUgTmFtZScgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVDYXRlZ29yeScsIGxhYmVsOiAnRml4dHVyZSBDYXRlZ29yeScgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVXaWR0aCcsIGxhYmVsOiAnRml4dHVyZSBXaWR0aCcgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVOdW1iZXInLCBsYWJlbDogJ0ZpeHR1cmUgTnVtYmVyJyB9LFxyXG4gIHsga2V5OiAnZml4dHVyZU5hbWUnLCBsYWJlbDogJ0ZpeHR1cmUgTmFtZScgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVUeXBlJywgbGFiZWw6ICdGaXh0dXJlIFR5cGUnIH0sXHJcbiAgeyBrZXk6ICdoZWFkZXJMYWJlbCcsIGxhYmVsOiAnSGVhZGVyIExhYmVsJyB9LFxyXG4gIHsga2V5OiAndGVtcGxhdGVHcm91cE5hbWUnLCBsYWJlbDogJ1RlbXBsYXRlIEdyb3VwIE5hbWUnIH0sXHJcbiAgeyBrZXk6ICd3YWxsTnVtYmVyJywgbGFiZWw6ICdXYWxsIE51bWJlcicgfSxcclxuICB7IGtleTogJ3dhbGxGaXh0dXJlTnVtYmVyJywgbGFiZWw6ICdXYWxsIEZpeHR1cmUgTnVtYmVyJyB9LFxyXG4gIHsga2V5OiAndm1OYW1lcycsIGxhYmVsOiAnVk0gTmFtZXMnIH0sXHJcbiAgeyBrZXk6ICd2bUNvdW50JywgbGFiZWw6ICdWTSBDb3VudCcgfSxcclxuICB7IGtleTogJ3Byb2R1Y3RQaWRzJywgbGFiZWw6ICdQcm9kdWN0IFBJRHMnIH0sXHJcbiAgeyBrZXk6ICdwb3NpdGlvbicsIGxhYmVsOiAnUG9zaXRpb24nIH0sXHJcbiAgeyBrZXk6ICdwb3NpdGlvbkxhYmVsJywgbGFiZWw6ICdQb3NpdGlvbiBMYWJlbCcgfSxcclxuICB7IGtleTogJ3N0YW5kYXJkQ2FwYWNpdHknLCBsYWJlbDogJ1N0YW5kYXJkIENhcGFjaXR5JyB9LFxyXG5dO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdsaWItcGxhbm8tZGF0YS1leHBvcnQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9wbGFuby1kYXRhLWV4cG9ydC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3BsYW5vLWRhdGEtZXhwb3J0LmNvbXBvbmVudC5zY3NzJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIFBsYW5vRGF0YUV4cG9ydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICBjbGllbnRJZDogc3RyaW5nO1xyXG4gIHN0b3JlT3B0aW9uczogU3RvcmVPcHRpb25bXSA9IFtdO1xyXG4gIGluaXRpYWxTdG9yZXM6IFN0b3JlT3B0aW9uW10gPSBbXTtcclxuICBzZWxlY3RlZFN0b3JlczogU3RvcmVPcHRpb25bXSA9IFtdO1xyXG5cclxuICBmaWVsZHM6IEZpZWxkRGVmW10gPSBbXTtcclxuICBvcGVyYXRvcnNCeVR5cGU6IFJlY29yZDxzdHJpbmcsIE9wZXJhdG9yRGVmW10+ID0ge307XHJcbiAgaXNMb2FkaW5nU2NoZW1hOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIGZpbHRlcnM6IEZpbHRlclJvd1tdID0gW107XHJcbiAgZmlsdGVyQ29tYmluYXRvcjogJ0FORCcgfCAnT1InID0gJ0FORCc7XHJcblxyXG4gIHNlbGVjdGlvbk1vZGU6ICdhbGwnIHwgJ2ZpcnN0TicgPSAnZmlyc3ROJztcclxuICBsaW1pdFBlclN0b3JlOiBudW1iZXIgPSAxO1xyXG5cclxuICBvdXRwdXRDb2x1bW5zOiBDb2x1bW5TZWxlY3Rpb25bXSA9IFtdO1xyXG5cclxuICBpbmNsdWRlTm90Rm91bmRSb3dzOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgaXNSdW5uaW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgcmVzdWx0OiBRdWVyeVJlc3VsdCB8IG51bGwgPSBudWxsO1xyXG4gIHJlc3VsdENvbHVtbnM6IHsga2V5OiBzdHJpbmc7IGxhYmVsOiBzdHJpbmcgfVtdID0gW107XHJcblxyXG4gIG1lc3NhZ2U6IHN0cmluZyA9ICcnO1xyXG4gIG1lc3NhZ2VUeXBlOiAnc3VjY2VzcycgfCAnZXJyb3InID0gJ3N1Y2Nlc3MnO1xyXG5cclxuICBwYWdpbmF0aW9uU2l6ZXM6IG51bWJlcltdID0gWzI1LCA1MCwgMTAwLCAyMDBdO1xyXG4gIHBhZ2VTaXplOiBudW1iZXIgPSA1MDtcclxuICBjdXJyZW50UGFnZTogbnVtYmVyID0gMTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBzYnM6IFN0b3JlQnVpbGRlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGdzOiBHbG9iYWxTdGF0ZVNlcnZpY2UsXHJcbiAgKSB7fVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuZ3MuZGF0YVJhbmdlVmFsdWVcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpLFxyXG4gICAgICAgIGRlYm91bmNlVGltZSgyMDApLFxyXG4gICAgICAgIGZpbHRlcigoZGF0YSkgPT4gISFkYXRhKSxcclxuICAgICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKGRhdGE6IGFueSkgPT4ge1xyXG4gICAgICAgIGlmIChkYXRhPy5jbGllbnQpIHtcclxuICAgICAgICAgIHRoaXMuY2xpZW50SWQgPSBkYXRhLmNsaWVudDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgbGV0IGhlYWRlckRhdGEgPSBKU09OLnBhcnNlKFxyXG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnaGVhZGVyLWZpbHRlcnMnKSBhcyBzdHJpbmcsXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgdGhpcy5jbGllbnRJZCA9IGhlYWRlckRhdGE/LmNsaWVudDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5sb2FkU3RvcmVzKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIHRoaXMubG9hZFNjaGVtYSgpO1xyXG4gIH1cclxuXHJcbiAgbG9hZFN0b3JlcygpIHtcclxuICAgIHRoaXMuc2JzLmdldFN0b3JlT3JDbHVzdGVyTGlzdCh7IHNlYXJjaE1vZGU6ICdzdG9yZScgfSkuc3Vic2NyaWJlKChyZXM6IGFueSkgPT4ge1xyXG4gICAgICBpZiAocmVzPy5kYXRhKSB7XHJcbiAgICAgICAgdGhpcy5zdG9yZU9wdGlvbnMgPSByZXMuZGF0YTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBsb2FkU2NoZW1hKCkge1xyXG4gICAgdGhpcy5pc0xvYWRpbmdTY2hlbWEgPSB0cnVlO1xyXG4gICAgdGhpcy5zYnMuZ2V0UGxhbm9EYXRhU2NoZW1hKCkuc3Vic2NyaWJlKHtcclxuICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5maWVsZHMgPSByZXM/LmRhdGE/LmZpZWxkcyB8fCBbXTtcclxuICAgICAgICB0aGlzLm9wZXJhdG9yc0J5VHlwZSA9IHJlcz8uZGF0YT8ub3BlcmF0b3JzQnlUeXBlIHx8IHt9O1xyXG5cclxuICAgICAgICBsZXQgb3V0cHV0RmllbGRzID0gdGhpcy5maWVsZHMuZmlsdGVyKChmKSA9PiBmLm91dHB1dCk7XHJcbiAgICAgICAgbGV0IGJ5S2V5ID0gbmV3IE1hcChvdXRwdXRGaWVsZHMubWFwKChmKSA9PiBbZi5rZXksIGZdKSk7XHJcblxyXG4gICAgICAgIGxldCBvcmRlcmVkOiB7IGtleTogc3RyaW5nOyBsYWJlbDogc3RyaW5nIH1bXSA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIE9VVFBVVF9DT0xVTU5fT1JERVIpIHtcclxuICAgICAgICAgIGxldCBmID0gYnlLZXkuZ2V0KGVudHJ5LmtleSk7XHJcbiAgICAgICAgICBvcmRlcmVkLnB1c2goe1xyXG4gICAgICAgICAgICBrZXk6IGVudHJ5LmtleSxcclxuICAgICAgICAgICAgbGFiZWw6IGY/LmxhYmVsIHx8IGVudHJ5LmxhYmVsLFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBieUtleS5kZWxldGUoZW50cnkua2V5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yIChsZXQgZiBvZiBieUtleS52YWx1ZXMoKSkgb3JkZXJlZC5wdXNoKHsga2V5OiBmLmtleSwgbGFiZWw6IGYubGFiZWwgfSk7XHJcblxyXG4gICAgICAgIHRoaXMub3V0cHV0Q29sdW1ucyA9IG9yZGVyZWQubWFwKChmKSA9PiAoe1xyXG4gICAgICAgICAga2V5OiBmLmtleSxcclxuICAgICAgICAgIGxhYmVsOiBmLmxhYmVsLFxyXG4gICAgICAgICAgc2VsZWN0ZWQ6IHRoaXMuZGVmYXVsdFNlbGVjdGVkKGYua2V5KSxcclxuICAgICAgICB9KSk7XHJcbiAgICAgICAgdGhpcy5pc0xvYWRpbmdTY2hlbWEgPSBmYWxzZTtcclxuICAgICAgfSxcclxuICAgICAgZXJyb3I6ICgpID0+IHtcclxuICAgICAgICB0aGlzLmZpZWxkcyA9IFtdO1xyXG4gICAgICAgIHRoaXMub3BlcmF0b3JzQnlUeXBlID0ge307XHJcbiAgICAgICAgdGhpcy5vdXRwdXRDb2x1bW5zID0gW107XHJcbiAgICAgICAgdGhpcy5pc0xvYWRpbmdTY2hlbWEgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnNob3dNZXNzYWdlKCdGYWlsZWQgdG8gbG9hZCBxdWVyeSBzY2hlbWEuJywgJ2Vycm9yJyk7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZGVmYXVsdFNlbGVjdGVkKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gW1xyXG4gICAgICAnc3RvcmVOYW1lJyxcclxuICAgICAgJ2ZpeHR1cmVDYXRlZ29yeScsXHJcbiAgICAgICdmaXh0dXJlV2lkdGgnLFxyXG4gICAgICAnZml4dHVyZU51bWJlcicsXHJcbiAgICAgICdmaXh0dXJlVHlwZScsXHJcbiAgICAgICdoZWFkZXJMYWJlbCcsXHJcbiAgICAgICd3YWxsTnVtYmVyJyxcclxuICAgICAgJ3dhbGxGaXh0dXJlTnVtYmVyJyxcclxuICAgICAgJ3ZtTmFtZXMnLFxyXG4gICAgICAncG9zaXRpb25MYWJlbCcsXHJcbiAgICAgICdzdGFuZGFyZENhcGFjaXR5JyxcclxuICAgIF0uaW5jbHVkZXMoa2V5KTtcclxuICB9XHJcblxyXG4gIGdldCBmaWx0ZXJhYmxlRmllbGRzKCk6IEZpZWxkRGVmW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuZmllbGRzLmZpbHRlcigoZikgPT4gZi5maWx0ZXJhYmxlKTtcclxuICB9XHJcblxyXG4gIG9wZXJhdG9yc0ZvckZpZWxkKGZpZWxkS2V5OiBzdHJpbmcpOiBPcGVyYXRvckRlZltdIHtcclxuICAgIGxldCBmID0gdGhpcy5maWVsZHMuZmluZCgoeCkgPT4geC5rZXkgPT09IGZpZWxkS2V5KTtcclxuICAgIGlmICghZikgcmV0dXJuIFtdO1xyXG4gICAgcmV0dXJuIHRoaXMub3BlcmF0b3JzQnlUeXBlW2YudHlwZV0gfHwgW107XHJcbiAgfVxyXG5cclxuICBpc1ZhbHVlRGlzYWJsZWRGb3Iob3BlcmF0b3I6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIG9wZXJhdG9yID09PSAnZXhpc3RzJyB8fCBvcGVyYXRvciA9PT0gJ25vdEV4aXN0cyc7XHJcbiAgfVxyXG5cclxuICBvblN0b3Jlc1NlbGVjdGVkKHN0b3JlczogU3RvcmVPcHRpb25bXSkge1xyXG4gICAgdGhpcy5zZWxlY3RlZFN0b3JlcyA9IHN0b3JlcztcclxuICB9XHJcblxyXG4gIGFkZEZpbHRlcigpIHtcclxuICAgIGxldCBmaXJzdEZpZWxkID0gdGhpcy5maWx0ZXJhYmxlRmllbGRzWzBdO1xyXG4gICAgaWYgKCFmaXJzdEZpZWxkKSByZXR1cm47XHJcbiAgICBsZXQgZmlyc3RPcCA9IHRoaXMub3BlcmF0b3JzQnlUeXBlW2ZpcnN0RmllbGQudHlwZV0/LlswXTtcclxuICAgIHRoaXMuZmlsdGVycy5wdXNoKHtcclxuICAgICAgZmllbGQ6IGZpcnN0RmllbGQua2V5LFxyXG4gICAgICBvcGVyYXRvcjogZmlyc3RPcD8ua2V5IHx8ICdlcXVhbHMnLFxyXG4gICAgICB2YWx1ZTogJycsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHJlbW92ZUZpbHRlcihpZHg6IG51bWJlcikge1xyXG4gICAgdGhpcy5maWx0ZXJzLnNwbGljZShpZHgsIDEpO1xyXG4gIH1cclxuXHJcbiAgb25GaWx0ZXJGaWVsZENoYW5nZShpZHg6IG51bWJlcikge1xyXG4gICAgbGV0IHJvdyA9IHRoaXMuZmlsdGVyc1tpZHhdO1xyXG4gICAgbGV0IGFsbG93ZWQgPSB0aGlzLm9wZXJhdG9yc0ZvckZpZWxkKHJvdy5maWVsZCk7XHJcbiAgICBpZiAoIWFsbG93ZWQuZmluZCgob3ApID0+IG9wLmtleSA9PT0gcm93Lm9wZXJhdG9yKSkge1xyXG4gICAgICByb3cub3BlcmF0b3IgPSBhbGxvd2VkWzBdPy5rZXkgfHwgJ2VxdWFscyc7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZWxlY3RBbGxDb2x1bW5zKCkge1xyXG4gICAgdGhpcy5vdXRwdXRDb2x1bW5zLmZvckVhY2goKGMpID0+IChjLnNlbGVjdGVkID0gdHJ1ZSkpO1xyXG4gIH1cclxuXHJcbiAgY2xlYXJBbGxDb2x1bW5zKCkge1xyXG4gICAgdGhpcy5vdXRwdXRDb2x1bW5zLmZvckVhY2goKGMpID0+IChjLnNlbGVjdGVkID0gZmFsc2UpKTtcclxuICB9XHJcblxyXG4gIGdldCBzZWxlY3RlZENvbHVtbnMoKTogQ29sdW1uU2VsZWN0aW9uW10ge1xyXG4gICAgcmV0dXJuIHRoaXMub3V0cHV0Q29sdW1ucy5maWx0ZXIoKGMpID0+IGMuc2VsZWN0ZWQpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHRvdGFsUm93cygpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMucmVzdWx0Py5yb3dzLmxlbmd0aCB8fCAwO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHBhZ2VkUm93cygpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10ge1xyXG4gICAgaWYgKCF0aGlzLnJlc3VsdCkgcmV0dXJuIFtdO1xyXG4gICAgbGV0IHN0YXJ0ID0gKHRoaXMuY3VycmVudFBhZ2UgLSAxKSAqIHRoaXMucGFnZVNpemU7XHJcbiAgICByZXR1cm4gdGhpcy5yZXN1bHQucm93cy5zbGljZShzdGFydCwgc3RhcnQgKyB0aGlzLnBhZ2VTaXplKTtcclxuICB9XHJcblxyXG4gIGdldCBwYWdlU3RhcnQoKTogbnVtYmVyIHtcclxuICAgIGlmICghdGhpcy50b3RhbFJvd3MpIHJldHVybiAwO1xyXG4gICAgcmV0dXJuICh0aGlzLmN1cnJlbnRQYWdlIC0gMSkgKiB0aGlzLnBhZ2VTaXplICsgMTtcclxuICB9XHJcblxyXG4gIGdldCBwYWdlRW5kKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gTWF0aC5taW4odGhpcy5jdXJyZW50UGFnZSAqIHRoaXMucGFnZVNpemUsIHRoaXMudG90YWxSb3dzKTtcclxuICB9XHJcblxyXG4gIG9uUGFnZUNoYW5nZShwYWdlOiBudW1iZXIpIHtcclxuICAgIHRoaXMuY3VycmVudFBhZ2UgPSBOdW1iZXIocGFnZSkgfHwgMTtcclxuICB9XHJcblxyXG4gIG9uUGFnZVNpemVDaGFuZ2Uoc2l6ZTogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnBhZ2VTaXplID0gTnVtYmVyKHNpemUpIHx8IDUwO1xyXG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IDE7XHJcbiAgfVxyXG5cclxuICBvblJ1bigpIHtcclxuICAgIGlmICh0aGlzLnNlbGVjdGVkU3RvcmVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKCdQbGVhc2Ugc2VsZWN0IGF0IGxlYXN0IG9uZSBzdG9yZS4nLCAnZXJyb3InKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRDb2x1bW5zLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKCdQbGVhc2Ugc2VsZWN0IGF0IGxlYXN0IG9uZSBvdXRwdXQgY29sdW1uLicsICdlcnJvcicpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5zZWxlY3Rpb25Nb2RlID09PSAnZmlyc3ROJykge1xyXG4gICAgICBsZXQgbiA9IE51bWJlcih0aGlzLmxpbWl0UGVyU3RvcmUpO1xyXG4gICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShuKSB8fCBuIDwgMSkge1xyXG4gICAgICAgIHRoaXMuc2hvd01lc3NhZ2UoXHJcbiAgICAgICAgICAnTnVtYmVyIG9mIGZpeHR1cmVzIHBlciBzdG9yZSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlci4nLFxyXG4gICAgICAgICAgJ2Vycm9yJyxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBjb2x1bW5zU25hcHNob3QgPSB0aGlzLnNlbGVjdGVkQ29sdW1ucy5tYXAoKGMpID0+ICh7XHJcbiAgICAgIGtleTogYy5rZXksXHJcbiAgICAgIGxhYmVsOiBjLmxhYmVsLFxyXG4gICAgfSkpO1xyXG5cclxuICAgIGxldCBwYXlsb2FkID0ge1xyXG4gICAgICBjbGllbnRJZDogdGhpcy5jbGllbnRJZCxcclxuICAgICAgc3RvcmVOYW1lczogdGhpcy5zZWxlY3RlZFN0b3Jlcy5tYXAoKHMpID0+IHMubGFiZWwpLFxyXG4gICAgICBmaWx0ZXJzOiB0aGlzLmZpbHRlcnNcclxuICAgICAgICAuZmlsdGVyKChmKSA9PiBmLmZpZWxkICYmIGYub3BlcmF0b3IpXHJcbiAgICAgICAgLm1hcCgoZikgPT4gKHtcclxuICAgICAgICAgIGZpZWxkOiBmLmZpZWxkLFxyXG4gICAgICAgICAgb3BlcmF0b3I6IGYub3BlcmF0b3IsXHJcbiAgICAgICAgICB2YWx1ZTogdGhpcy5pc1ZhbHVlRGlzYWJsZWRGb3IoZi5vcGVyYXRvcikgPyAnJyA6IGYudmFsdWUsXHJcbiAgICAgICAgfSkpLFxyXG4gICAgICBmaWx0ZXJDb21iaW5hdG9yOiB0aGlzLmZpbHRlckNvbWJpbmF0b3IsXHJcbiAgICAgIHNlbGVjdGlvbk1vZGU6IHRoaXMuc2VsZWN0aW9uTW9kZSxcclxuICAgICAgbGltaXRQZXJTdG9yZTpcclxuICAgICAgICB0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICdmaXJzdE4nID8gTnVtYmVyKHRoaXMubGltaXRQZXJTdG9yZSkgOiB1bmRlZmluZWQsXHJcbiAgICAgIGNvbHVtbnM6IGNvbHVtbnNTbmFwc2hvdCxcclxuICAgICAgaW5jbHVkZU5vdEZvdW5kUm93czogdGhpcy5pbmNsdWRlTm90Rm91bmRSb3dzLFxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLmlzUnVubmluZyA9IHRydWU7XHJcbiAgICB0aGlzLnJlc3VsdCA9IG51bGw7XHJcbiAgICB0aGlzLnJlc3VsdENvbHVtbnMgPSBjb2x1bW5zU25hcHNob3Q7XHJcbiAgICB0aGlzLmN1cnJlbnRQYWdlID0gMTtcclxuICAgIHRoaXMuc2JzLnJ1blBsYW5vRGF0YVF1ZXJ5KHBheWxvYWQpLnN1YnNjcmliZSh7XHJcbiAgICAgIG5leHQ6IChyZXM6IGFueSkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVzdWx0ID0gcmVzPy5kYXRhIHx8IG51bGw7XHJcbiAgICAgICAgdGhpcy5pc1J1bm5pbmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmN1cnJlbnRQYWdlID0gMTtcclxuICAgICAgICBpZiAodGhpcy5yZXN1bHQpIHtcclxuICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2UoYEZvdW5kICR7dGhpcy5yZXN1bHQudG90YWxSb3dzfSByb3cocykuYCwgJ3N1Y2Nlc3MnKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0sXHJcbiAgICAgIGVycm9yOiAoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICB0aGlzLnNob3dNZXNzYWdlKFxyXG4gICAgICAgICAgZXJyPy5lcnJvcj8ubWVzc2FnZSB8fCAnRmFpbGVkIHRvIHJ1biBxdWVyeS4nLFxyXG4gICAgICAgICAgJ2Vycm9yJyxcclxuICAgICAgICApO1xyXG4gICAgICAgIHRoaXMuaXNSdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uRXhwb3J0KCkge1xyXG4gICAgaWYgKCF0aGlzLnJlc3VsdCB8fCAhdGhpcy5yZXN1bHQucm93cy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5zaG93TWVzc2FnZSgnTm8gZGF0YSB0byBleHBvcnQuIFJ1biB0aGUgcXVlcnkgZmlyc3QuJywgJ2Vycm9yJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGxldCBjbGVhbmVkID0gdGhpcy5yZXN1bHQucm93cy5tYXAoKHIpID0+IHtcclxuICAgICAgbGV0IGNvcHk6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuICAgICAgZm9yIChsZXQgY29sIG9mIHRoaXMucmVzdWx0Q29sdW1ucykgY29weVtjb2wubGFiZWxdID0gcltjb2wubGFiZWxdID8/ICcnO1xyXG4gICAgICByZXR1cm4gY29weTtcclxuICAgIH0pO1xyXG4gICAgbGV0IGZpbGVOYW1lID0gYHBsYW5vX2RhdGFfZXhwb3J0XyR7RGF0ZS5ub3coKX1gO1xyXG4gICAgdGhpcy5zYnMuZXhwb3J0QXNFeGNlbEZpbGUoY2xlYW5lZCwgZmlsZU5hbWUpO1xyXG4gIH1cclxuXHJcbiAgc2hvd01lc3NhZ2UobXNnOiBzdHJpbmcsIHR5cGU6ICdzdWNjZXNzJyB8ICdlcnJvcicpIHtcclxuICAgIHRoaXMubWVzc2FnZSA9IG1zZztcclxuICAgIHRoaXMubWVzc2FnZVR5cGUgPSB0eXBlO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiAodGhpcy5tZXNzYWdlID0gJycpLCA1MDAwKTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XHJcbiAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XHJcbiAgfVxyXG59XHJcbiIsIjxzZWN0aW9uIGNsYXNzPVwicGxhbm8tZGF0YS1leHBvcnQgcC0zXCI+XHJcbiAgPGRpdiBjbGFzcz1cImNhcmQgcC00IG1iLTNcIj5cclxuICAgIDxoNSBjbGFzcz1cIm1iLTFcIj5QbGFubyBEYXRhIEV4cG9ydDwvaDU+XHJcbiAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGwgbWItM1wiPlxyXG4gICAgICBCdWlsZCBhIHF1ZXJ5IGFnYWluc3QgcGxhbm9ncmFtIGZpeHR1cmVzLCBwcmV2aWV3IHJlc3VsdHMsIGFuZCBleHBvcnQgYXMgRXhjZWwuXHJcbiAgICA8L3A+XHJcblxyXG4gICAgQGlmIChpc0xvYWRpbmdTY2hlbWEpIHtcclxuICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj5Mb2FkaW5nIHF1ZXJ5IHNjaGVtYS4uLjwvZGl2PlxyXG4gICAgfVxyXG5cclxuICAgIDwhLS0gU3RvcmVzIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJsb2NrIG1iLTNcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImJsb2NrLXRpdGxlXCI+U3RvcmVzPC9kaXY+XHJcbiAgICAgIDxsaWItc3RvcmUtc2VsZWN0XHJcbiAgICAgICAgW29wdGlvbnNdPVwic3RvcmVPcHRpb25zXCJcclxuICAgICAgICBbaW5pdGlhbFNlbGVjdGVkXT1cImluaXRpYWxTdG9yZXNcIlxyXG4gICAgICAgIChzZWxlY3RlZENoYW5nZSk9XCJvblN0b3Jlc1NlbGVjdGVkKCRldmVudClcIj5cclxuICAgICAgPC9saWItc3RvcmUtc2VsZWN0PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBNYXRjaCBDcml0ZXJpYSAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJibG9jayBtYi0zXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGp1c3RpZnktY29udGVudC1iZXR3ZWVuIG1iLTJcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiYmxvY2stdGl0bGUgbWItMFwiPk1hdGNoIENyaXRlcmlhPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZ2FwLTNcIj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIGZvcm0tY2hlY2staW5saW5lIG1iLTBcIj5cclxuICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiIHR5cGU9XCJyYWRpb1wiIGlkPVwiY29tYkFuZFwiXHJcbiAgICAgICAgICAgICAgbmFtZT1cImNvbWJpbmF0b3JcIiB2YWx1ZT1cIkFORFwiIFsobmdNb2RlbCldPVwiZmlsdGVyQ29tYmluYXRvclwiPlxyXG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgZm9yPVwiY29tYkFuZFwiPk1hdGNoIGFsbCAoQU5EKTwvbGFiZWw+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIGZvcm0tY2hlY2staW5saW5lIG1iLTBcIj5cclxuICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiIHR5cGU9XCJyYWRpb1wiIGlkPVwiY29tYk9yXCJcclxuICAgICAgICAgICAgICBuYW1lPVwiY29tYmluYXRvclwiIHZhbHVlPVwiT1JcIiBbKG5nTW9kZWwpXT1cImZpbHRlckNvbWJpbmF0b3JcIj5cclxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cImNvbWJPclwiPk1hdGNoIGFueSAoT1IpPC9sYWJlbD5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIEBpZiAoIWZpbHRlcnMubGVuZ3RoKSB7XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGwgbWItMlwiPlxyXG4gICAgICAgICAgTm8gY3JpdGVyaWEg4oCUIHF1ZXJ5IHdpbGwgcmV0dXJuIGV2ZXJ5IGZpeHR1cmUgZm9yIHRoZSBzZWxlY3RlZCBzdG9yZXMuXHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIEBmb3IgKHJvdyBvZiBmaWx0ZXJzOyB0cmFjayAkaW5kZXgpIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmlsdGVyLXJvdyBkLWZsZXggZ2FwLTIgbWItMiBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdCBmb3JtLXNlbGVjdC1zbSBmaWx0ZXItZmllbGRcIlxyXG4gICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy5maWVsZFwiXHJcbiAgICAgICAgICAgIChjaGFuZ2UpPVwib25GaWx0ZXJGaWVsZENoYW5nZSgkaW5kZXgpXCI+XHJcbiAgICAgICAgICAgIEBmb3IgKGYgb2YgZmlsdGVyYWJsZUZpZWxkczsgdHJhY2sgZi5rZXkpIHtcclxuICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJmLmtleVwiPnt7IGYubGFiZWwgfX08L29wdGlvbj5cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgPC9zZWxlY3Q+XHJcblxyXG4gICAgICAgICAgPHNlbGVjdCBjbGFzcz1cImZvcm0tc2VsZWN0IGZvcm0tc2VsZWN0LXNtIGZpbHRlci1vcFwiXHJcbiAgICAgICAgICAgIFsobmdNb2RlbCldPVwicm93Lm9wZXJhdG9yXCI+XHJcbiAgICAgICAgICAgIEBmb3IgKG9wIG9mIG9wZXJhdG9yc0ZvckZpZWxkKHJvdy5maWVsZCk7IHRyYWNrIG9wLmtleSkge1xyXG4gICAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIm9wLmtleVwiPnt7IG9wLmxhYmVsIH19PC9vcHRpb24+XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIDwvc2VsZWN0PlxyXG5cclxuICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBmb3JtLWNvbnRyb2wtc20gZmlsdGVyLXZhbHVlXCJcclxuICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImlzVmFsdWVEaXNhYmxlZEZvcihyb3cub3BlcmF0b3IpID8gJ+KAlCcgOiAndmFsdWUnXCJcclxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImlzVmFsdWVEaXNhYmxlZEZvcihyb3cub3BlcmF0b3IpXCJcclxuICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cudmFsdWVcIj5cclxuXHJcbiAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tb3V0bGluZS1kYW5nZXJcIiAoY2xpY2spPVwicmVtb3ZlRmlsdGVyKCRpbmRleClcIlxyXG4gICAgICAgICAgICB0aXRsZT1cIlJlbW92ZVwiPsOXPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnlcIiAoY2xpY2spPVwiYWRkRmlsdGVyKClcIlxyXG4gICAgICAgIFtkaXNhYmxlZF09XCIhZmlsdGVyYWJsZUZpZWxkcy5sZW5ndGhcIj5cclxuICAgICAgICArIEFkZCBDcml0ZXJpb25cclxuICAgICAgPC9idXR0b24+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIFNlbGVjdGlvbiBNb2RlIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJsb2NrIG1iLTNcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImJsb2NrLXRpdGxlXCI+Rml4dHVyZSBTZWxlY3Rpb248L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBmbGV4LXdyYXAgYWxpZ24taXRlbXMtY2VudGVyIGdhcC0zXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2sgbWItMFwiPlxyXG4gICAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiIHR5cGU9XCJyYWRpb1wiIGlkPVwic2VsQWxsXCJcclxuICAgICAgICAgICAgbmFtZT1cInNlbGVjdGlvbk1vZGVcIiB2YWx1ZT1cImFsbFwiIFsobmdNb2RlbCldPVwic2VsZWN0aW9uTW9kZVwiPlxyXG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cInNlbEFsbFwiPkFsbCBtYXRjaGluZyBmaXh0dXJlczwvbGFiZWw+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2sgbWItMFwiPlxyXG4gICAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiIHR5cGU9XCJyYWRpb1wiIGlkPVwic2VsRmlyc3ROXCJcclxuICAgICAgICAgICAgbmFtZT1cInNlbGVjdGlvbk1vZGVcIiB2YWx1ZT1cImZpcnN0TlwiIFsobmdNb2RlbCldPVwic2VsZWN0aW9uTW9kZVwiPlxyXG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cInNlbEZpcnN0TlwiPkZpcnN0PC9sYWJlbD5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8aW5wdXRcclxuICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBmb3JtLWNvbnRyb2wtc20gY291bnQtaW5wdXRcIlxyXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJsaW1pdFBlclN0b3JlXCJcclxuICAgICAgICAgIFtkaXNhYmxlZF09XCJzZWxlY3Rpb25Nb2RlICE9PSAnZmlyc3ROJ1wiPlxyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbFwiPm1hdGNoaW5nIGZyb20gZW50cmFuY2UsIHBlciBzdG9yZTwvc3Bhbj5cclxuICAgICAgPC9kaXY+XHJcblxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVjayBtdC0yXCI+XHJcbiAgICAgICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiIHR5cGU9XCJjaGVja2JveFwiIGlkPVwiaW5jTm90Rm91bmRcIlxyXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJpbmNsdWRlTm90Rm91bmRSb3dzXCI+XHJcbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cImluY05vdEZvdW5kXCI+XHJcbiAgICAgICAgICBJbmNsdWRlIGVtcHR5IHJvd3MgZm9yIHN0b3JlcyB3aXRoIG5vIG1hdGNoZXNcclxuICAgICAgICA8L2xhYmVsPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gT3V0cHV0IENvbHVtbnMgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYmxvY2sgbWItM1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBtYi0yXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImJsb2NrLXRpdGxlIG1iLTBcIj5PdXRwdXQgQ29sdW1uczwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZ2FwLTJcIj5cclxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1saW5rIHAtMFwiIChjbGljayk9XCJzZWxlY3RBbGxDb2x1bW5zKClcIj5cclxuICAgICAgICAgICAgU2VsZWN0IGFsbFxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tbGluayBwLTBcIiAoY2xpY2spPVwiY2xlYXJBbGxDb2x1bW5zKClcIj5cclxuICAgICAgICAgICAgQ2xlYXJcclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNvbHVtbi1ncmlkXCI+XHJcbiAgICAgICAgQGZvciAoY29sIG9mIG91dHB1dENvbHVtbnM7IHRyYWNrIGNvbC5rZXkpIHtcclxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbHVtbi1pdGVtXCI+XHJcbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBjbGFzcz1cImZvcm0tY2hlY2staW5wdXQgbWUtMlwiXHJcbiAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjb2wuc2VsZWN0ZWRcIj5cclxuICAgICAgICAgICAge3sgY29sLmxhYmVsIH19XHJcbiAgICAgICAgICA8L2xhYmVsPlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIEFjdGlvbiBCdXR0b25zIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBnYXAtMlwiPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxyXG4gICAgICAgIChjbGljayk9XCJvblJ1bigpXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNSdW5uaW5nIHx8IGlzTG9hZGluZ1NjaGVtYSB8fCBzZWxlY3RlZFN0b3Jlcy5sZW5ndGggPT09IDBcIj5cclxuICAgICAgICB7eyBpc1J1bm5pbmcgPyAnUnVubmluZy4uLicgOiAnUnVuIFF1ZXJ5JyB9fVxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzXCJcclxuICAgICAgICAoY2xpY2spPVwib25FeHBvcnQoKVwiXHJcbiAgICAgICAgW2Rpc2FibGVkXT1cIiFyZXN1bHQgfHwgIXJlc3VsdC5yb3dzLmxlbmd0aFwiPlxyXG4gICAgICAgIEV4cG9ydCB0byBFeGNlbFxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIEBpZiAobWVzc2FnZSkge1xyXG4gICAgICA8ZGl2XHJcbiAgICAgICAgY2xhc3M9XCJtdC0zIGFsZXJ0XCJcclxuICAgICAgICBbY2xhc3MuYWxlcnQtc3VjY2Vzc109XCJtZXNzYWdlVHlwZSA9PT0gJ3N1Y2Nlc3MnXCJcclxuICAgICAgICBbY2xhc3MuYWxlcnQtZGFuZ2VyXT1cIm1lc3NhZ2VUeXBlID09PSAnZXJyb3InXCI+XHJcbiAgICAgICAge3sgbWVzc2FnZSB9fVxyXG4gICAgICA8L2Rpdj5cclxuICAgIH1cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBSZXN1bHQgUHJldmlldyAtLT5cclxuICBAaWYgKHJlc3VsdCkge1xyXG4gICAgPGRpdiBjbGFzcz1cImNhcmQgcC00XCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGp1c3RpZnktY29udGVudC1iZXR3ZWVuIG1iLTNcIj5cclxuICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgPGg2IGNsYXNzPVwibWItMFwiPlJlc3VsdHM8L2g2PlxyXG4gICAgICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPlxyXG4gICAgICAgICAgICB7eyB0b3RhbFJvd3MgfX0gcm93KHMpXHJcbiAgICAgICAgICAgIEBpZiAodG90YWxSb3dzKSB7XHJcbiAgICAgICAgICAgICAgwrcgc2hvd2luZyB7eyBwYWdlU3RhcnQgfX3igJN7eyBwYWdlRW5kIH19XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIDwvc21hbGw+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgQGlmICghcmVzdWx0LnJvd3MubGVuZ3RoKSB7XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWRcIj5ObyBkYXRhIGZvdW5kIGZvciB0aGUgZ2l2ZW4gcXVlcnkuPC9kaXY+XHJcbiAgICAgIH0gQGVsc2Uge1xyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1yZXNwb25zaXZlXCI+XHJcbiAgICAgICAgICA8dGFibGUgY2xhc3M9XCJ0YWJsZSB0YWJsZS1zbSB0YWJsZS1ib3JkZXJlZFwiPlxyXG4gICAgICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgQGZvciAoY29sIG9mIHJlc3VsdENvbHVtbnM7IHRyYWNrIGNvbC5rZXkpIHtcclxuICAgICAgICAgICAgICAgICAgPHRoPnt7IGNvbC5sYWJlbCB9fTwvdGg+XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgPC90aGVhZD5cclxuICAgICAgICAgICAgPHRib2R5PlxyXG4gICAgICAgICAgICAgIEBmb3IgKHJvdyBvZiBwYWdlZFJvd3M7IHRyYWNrICRpbmRleCkge1xyXG4gICAgICAgICAgICAgICAgPHRyIFtjbGFzcy5yb3ctbm90LWZvdW5kXT1cInJvd1snX19ub3RGb3VuZCddXCI+XHJcbiAgICAgICAgICAgICAgICAgIEBmb3IgKGNvbCBvZiByZXN1bHRDb2x1bW5zOyB0cmFjayBjb2wua2V5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgPHRkXHJcbiAgICAgICAgICAgICAgICAgICAgICBbbmdiVG9vbHRpcF09XCJyb3dbY29sLmxhYmVsXT8udG9TdHJpbmcoKSA/IHJvd1tjb2wubGFiZWxdIDogbnVsbFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXI9XCJib2R5XCJcclxuICAgICAgICAgICAgICAgICAgICAgIHBsYWNlbWVudD1cInRvcFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBbb3BlbkRlbGF5XT1cIjMwMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAge3sgcm93W2NvbC5sYWJlbF0gfX1cclxuICAgICAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgPC90Ym9keT5cclxuICAgICAgICAgIDwvdGFibGU+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDxsaWItcGFnaW5hdGlvblxyXG4gICAgICAgICAgW2l0ZW1zUGVyUGFnZV09XCJwYWdlU2l6ZVwiXHJcbiAgICAgICAgICBbY3VycmVudFBhZ2VdPVwiY3VycmVudFBhZ2VcIlxyXG4gICAgICAgICAgW3RvdGFsSXRlbXNdPVwidG90YWxSb3dzXCJcclxuICAgICAgICAgIFtwYWdlU2l6ZV09XCJwYWdlU2l6ZVwiXHJcbiAgICAgICAgICBbcGFnaW5hdGlvblNpemVzXT1cInBhZ2luYXRpb25TaXplc1wiXHJcbiAgICAgICAgICBbZGlyZWN0aW9uTGlua3NdPVwidHJ1ZVwiXHJcbiAgICAgICAgICAocGFnZUNoYW5nZSk9XCJvblBhZ2VDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgICAocGFnZVNpemVDaGFuZ2UpPVwib25QYWdlU2l6ZUNoYW5nZSgkZXZlbnQpXCI+XHJcbiAgICAgICAgPC9saWItcGFnaW5hdGlvbj5cclxuICAgICAgfVxyXG4gICAgPC9kaXY+XHJcbiAgfVxyXG48L3NlY3Rpb24+XHJcbiJdfQ==
378
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhbm8tZGF0YS1leHBvcnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvcGxhbm8tZGF0YS1leHBvcnQvcGxhbm8tZGF0YS1leHBvcnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvcGxhbm8tZGF0YS1leHBvcnQvcGxhbm8tZGF0YS1leHBvcnQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFHN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7Ozs7QUF5Q3RGLE1BQU0sbUJBQW1CLEdBQXFDO0lBQzVELEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFO0lBQ3pDLEVBQUUsR0FBRyxFQUFFLGlCQUFpQixFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRTtJQUNyRCxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRTtJQUMvQyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLGdCQUFnQixFQUFFO0lBQ2pELEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdDLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdDLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO0lBQzdDLEVBQUUs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LCBPbkluaXQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBTdG9yZUJ1aWxkZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvc3RvcmUtYnVpbGRlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgR2xvYmFsU3RhdGVTZXJ2aWNlIH0gZnJvbSAndGFuZ28tYXBwLXVpLWdsb2JhbCc7XHJcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCwgZGVib3VuY2VUaW1lLCBmaWx0ZXIsIGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IFN0b3JlT3B0aW9uIH0gZnJvbSAnLi4vLi4vY29sbGVjdGlvbi11cGRhdGUtYWkvY29tcG9uZW50cy9zdG9yZS1zZWxlY3Qvc3RvcmUtc2VsZWN0LmNvbXBvbmVudCc7XHJcblxyXG5pbnRlcmZhY2UgRmllbGREZWYge1xyXG4gIGtleTogc3RyaW5nO1xyXG4gIGxhYmVsOiBzdHJpbmc7XHJcbiAgdHlwZTogJ3N0cmluZycgfCAnbnVtYmVyJyB8ICdhcnJheU9mU3RyaW5ncyc7XHJcbiAgZmlsdGVyYWJsZTogYm9vbGVhbjtcclxuICBvdXRwdXQ6IGJvb2xlYW47XHJcbn1cclxuXHJcbmludGVyZmFjZSBPcGVyYXRvckRlZiB7XHJcbiAga2V5OiBzdHJpbmc7XHJcbiAgbGFiZWw6IHN0cmluZztcclxufVxyXG5cclxuaW50ZXJmYWNlIEZpbHRlclJvdyB7XHJcbiAgZmllbGQ6IHN0cmluZztcclxuICBvcGVyYXRvcjogc3RyaW5nO1xyXG4gIHZhbHVlOiBzdHJpbmc7XHJcbn1cclxuXHJcbmludGVyZmFjZSBDb2x1bW5TZWxlY3Rpb24ge1xyXG4gIGtleTogc3RyaW5nO1xyXG4gIGxhYmVsOiBzdHJpbmc7XHJcbiAgc2VsZWN0ZWQ6IGJvb2xlYW47XHJcbn1cclxuXHJcbmludGVyZmFjZSBRdWVyeVJlc3VsdCB7XHJcbiAgY29sdW1uczogc3RyaW5nW107XHJcbiAgcm93czogUmVjb3JkPHN0cmluZywgYW55PltdO1xyXG4gIHRvdGFsUm93czogbnVtYmVyO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgVm1QbGFjZW1lbnRSZXN1bHQge1xyXG4gIGNvbHVtbnM6IHN0cmluZ1tdO1xyXG4gIHJvd3M6IFJlY29yZDxzdHJpbmcsIGFueT5bXTtcclxuICB0b3RhbFJvd3M6IG51bWJlcjtcclxuICBtYXRjaGVkVm1Db3VudDogbnVtYmVyO1xyXG59XHJcblxyXG5jb25zdCBPVVRQVVRfQ09MVU1OX09SREVSOiB7IGtleTogc3RyaW5nOyBsYWJlbDogc3RyaW5nIH1bXSA9IFtcclxuICB7IGtleTogJ3N0b3JlTmFtZScsIGxhYmVsOiAnU3RvcmUgTmFtZScgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVDYXRlZ29yeScsIGxhYmVsOiAnRml4dHVyZSBDYXRlZ29yeScgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVXaWR0aCcsIGxhYmVsOiAnRml4dHVyZSBXaWR0aCcgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVOdW1iZXInLCBsYWJlbDogJ0ZpeHR1cmUgTnVtYmVyJyB9LFxyXG4gIHsga2V5OiAnZml4dHVyZU5hbWUnLCBsYWJlbDogJ0ZpeHR1cmUgTmFtZScgfSxcclxuICB7IGtleTogJ2ZpeHR1cmVUeXBlJywgbGFiZWw6ICdGaXh0dXJlIFR5cGUnIH0sXHJcbiAgeyBrZXk6ICdoZWFkZXJMYWJlbCcsIGxhYmVsOiAnSGVhZGVyIExhYmVsJyB9LFxyXG4gIHsga2V5OiAndGVtcGxhdGVHcm91cE5hbWUnLCBsYWJlbDogJ1RlbXBsYXRlIEdyb3VwIE5hbWUnIH0sXHJcbiAgeyBrZXk6ICd3YWxsTnVtYmVyJywgbGFiZWw6ICdXYWxsIE51bWJlcicgfSxcclxuICB7IGtleTogJ3dhbGxGaXh0dXJlTnVtYmVyJywgbGFiZWw6ICdXYWxsIEZpeHR1cmUgTnVtYmVyJyB9LFxyXG4gIHsga2V5OiAndm1OYW1lcycsIGxhYmVsOiAnVk0gTmFtZXMnIH0sXHJcbiAgeyBrZXk6ICd2bUNvdW50JywgbGFiZWw6ICdWTSBDb3VudCcgfSxcclxuICB7IGtleTogJ3Byb2R1Y3RQaWRzJywgbGFiZWw6ICdQcm9kdWN0IFBJRHMnIH0sXHJcbiAgeyBrZXk6ICdwb3NpdGlvbicsIGxhYmVsOiAnUG9zaXRpb24nIH0sXHJcbiAgeyBrZXk6ICdwb3NpdGlvbkxhYmVsJywgbGFiZWw6ICdQb3NpdGlvbiBMYWJlbCcgfSxcclxuICB7IGtleTogJ3N0YW5kYXJkQ2FwYWNpdHknLCBsYWJlbDogJ1N0YW5kYXJkIENhcGFjaXR5JyB9LFxyXG5dO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdsaWItcGxhbm8tZGF0YS1leHBvcnQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9wbGFuby1kYXRhLWV4cG9ydC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3BsYW5vLWRhdGEtZXhwb3J0LmNvbXBvbmVudC5zY3NzJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIFBsYW5vRGF0YUV4cG9ydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICBjbGllbnRJZDogc3RyaW5nO1xyXG4gIHN0b3JlT3B0aW9uczogU3RvcmVPcHRpb25bXSA9IFtdO1xyXG4gIGluaXRpYWxTdG9yZXM6IFN0b3JlT3B0aW9uW10gPSBbXTtcclxuICBzZWxlY3RlZFN0b3JlczogU3RvcmVPcHRpb25bXSA9IFtdO1xyXG5cclxuICBmaWVsZHM6IEZpZWxkRGVmW10gPSBbXTtcclxuICBvcGVyYXRvcnNCeVR5cGU6IFJlY29yZDxzdHJpbmcsIE9wZXJhdG9yRGVmW10+ID0ge307XHJcbiAgaXNMb2FkaW5nU2NoZW1hOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIGZpbHRlcnM6IEZpbHRlclJvd1tdID0gW107XHJcbiAgZmlsdGVyQ29tYmluYXRvcjogJ0FORCcgfCAnT1InID0gJ0FORCc7XHJcblxyXG4gIHNlbGVjdGlvbk1vZGU6ICdhbGwnIHwgJ2ZpcnN0TicgPSAnZmlyc3ROJztcclxuICBsaW1pdFBlclN0b3JlOiBudW1iZXIgPSAxO1xyXG5cclxuICBvdXRwdXRDb2x1bW5zOiBDb2x1bW5TZWxlY3Rpb25bXSA9IFtdO1xyXG5cclxuICBpbmNsdWRlTm90Rm91bmRSb3dzOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgaXNSdW5uaW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgcmVzdWx0OiBRdWVyeVJlc3VsdCB8IG51bGwgPSBudWxsO1xyXG4gIHJlc3VsdENvbHVtbnM6IHsga2V5OiBzdHJpbmc7IGxhYmVsOiBzdHJpbmcgfVtdID0gW107XHJcblxyXG4gIG1lc3NhZ2U6IHN0cmluZyA9ICcnO1xyXG4gIG1lc3NhZ2VUeXBlOiAnc3VjY2VzcycgfCAnZXJyb3InID0gJ3N1Y2Nlc3MnO1xyXG5cclxuICBwYWdpbmF0aW9uU2l6ZXM6IG51bWJlcltdID0gWzI1LCA1MCwgMTAwLCAyMDBdO1xyXG4gIHBhZ2VTaXplOiBudW1iZXIgPSA1MDtcclxuICBjdXJyZW50UGFnZTogbnVtYmVyID0gMTtcclxuXHJcbiAgLy8gVk0gUGxhY2VtZW50IEV4cG9ydCBieSBWTSBOYW1lXHJcbiAgdm1TZWxlY3RlZFN0b3JlczogU3RvcmVPcHRpb25bXSA9IFtdO1xyXG4gIHZtSW5pdGlhbFN0b3JlczogU3RvcmVPcHRpb25bXSA9IFtdO1xyXG4gIHZtTmFtZVJlZ2V4OiBzdHJpbmcgPSAnJztcclxuICBpc1ZtUnVubmluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHZtUmVzdWx0OiBWbVBsYWNlbWVudFJlc3VsdCB8IG51bGwgPSBudWxsO1xyXG4gIHZtUmVzdWx0Q29sdW1uczogc3RyaW5nW10gPSBbXTtcclxuICB2bVBhZ2VTaXplOiBudW1iZXIgPSA1MDtcclxuICB2bUN1cnJlbnRQYWdlOiBudW1iZXIgPSAxO1xyXG4gIHZtTWVzc2FnZTogc3RyaW5nID0gJyc7XHJcbiAgdm1NZXNzYWdlVHlwZTogJ3N1Y2Nlc3MnIHwgJ2Vycm9yJyA9ICdzdWNjZXNzJztcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBzYnM6IFN0b3JlQnVpbGRlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGdzOiBHbG9iYWxTdGF0ZVNlcnZpY2UsXHJcbiAgKSB7fVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuZ3MuZGF0YVJhbmdlVmFsdWVcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpLFxyXG4gICAgICAgIGRlYm91bmNlVGltZSgyMDApLFxyXG4gICAgICAgIGZpbHRlcigoZGF0YSkgPT4gISFkYXRhKSxcclxuICAgICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKGRhdGE6IGFueSkgPT4ge1xyXG4gICAgICAgIGlmIChkYXRhPy5jbGllbnQpIHtcclxuICAgICAgICAgIHRoaXMuY2xpZW50SWQgPSBkYXRhLmNsaWVudDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgbGV0IGhlYWRlckRhdGEgPSBKU09OLnBhcnNlKFxyXG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnaGVhZGVyLWZpbHRlcnMnKSBhcyBzdHJpbmcsXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgdGhpcy5jbGllbnRJZCA9IGhlYWRlckRhdGE/LmNsaWVudDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5sb2FkU3RvcmVzKCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIHRoaXMubG9hZFNjaGVtYSgpO1xyXG4gIH1cclxuXHJcbiAgbG9hZFN0b3JlcygpIHtcclxuICAgIHRoaXMuc2JzLmdldFN0b3JlT3JDbHVzdGVyTGlzdCh7IHNlYXJjaE1vZGU6ICdzdG9yZScgfSkuc3Vic2NyaWJlKChyZXM6IGFueSkgPT4ge1xyXG4gICAgICBpZiAocmVzPy5kYXRhKSB7XHJcbiAgICAgICAgdGhpcy5zdG9yZU9wdGlvbnMgPSByZXMuZGF0YTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBsb2FkU2NoZW1hKCkge1xyXG4gICAgdGhpcy5pc0xvYWRpbmdTY2hlbWEgPSB0cnVlO1xyXG4gICAgdGhpcy5zYnMuZ2V0UGxhbm9EYXRhU2NoZW1hKCkuc3Vic2NyaWJlKHtcclxuICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5maWVsZHMgPSByZXM/LmRhdGE/LmZpZWxkcyB8fCBbXTtcclxuICAgICAgICB0aGlzLm9wZXJhdG9yc0J5VHlwZSA9IHJlcz8uZGF0YT8ub3BlcmF0b3JzQnlUeXBlIHx8IHt9O1xyXG5cclxuICAgICAgICBsZXQgb3V0cHV0RmllbGRzID0gdGhpcy5maWVsZHMuZmlsdGVyKChmKSA9PiBmLm91dHB1dCk7XHJcbiAgICAgICAgbGV0IGJ5S2V5ID0gbmV3IE1hcChvdXRwdXRGaWVsZHMubWFwKChmKSA9PiBbZi5rZXksIGZdKSk7XHJcblxyXG4gICAgICAgIGxldCBvcmRlcmVkOiB7IGtleTogc3RyaW5nOyBsYWJlbDogc3RyaW5nIH1bXSA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIE9VVFBVVF9DT0xVTU5fT1JERVIpIHtcclxuICAgICAgICAgIGxldCBmID0gYnlLZXkuZ2V0KGVudHJ5LmtleSk7XHJcbiAgICAgICAgICBvcmRlcmVkLnB1c2goe1xyXG4gICAgICAgICAgICBrZXk6IGVudHJ5LmtleSxcclxuICAgICAgICAgICAgbGFiZWw6IGY/LmxhYmVsIHx8IGVudHJ5LmxhYmVsLFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBieUtleS5kZWxldGUoZW50cnkua2V5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZm9yIChsZXQgZiBvZiBieUtleS52YWx1ZXMoKSkgb3JkZXJlZC5wdXNoKHsga2V5OiBmLmtleSwgbGFiZWw6IGYubGFiZWwgfSk7XHJcblxyXG4gICAgICAgIHRoaXMub3V0cHV0Q29sdW1ucyA9IG9yZGVyZWQubWFwKChmKSA9PiAoe1xyXG4gICAgICAgICAga2V5OiBmLmtleSxcclxuICAgICAgICAgIGxhYmVsOiBmLmxhYmVsLFxyXG4gICAgICAgICAgc2VsZWN0ZWQ6IHRoaXMuZGVmYXVsdFNlbGVjdGVkKGYua2V5KSxcclxuICAgICAgICB9KSk7XHJcbiAgICAgICAgdGhpcy5pc0xvYWRpbmdTY2hlbWEgPSBmYWxzZTtcclxuICAgICAgfSxcclxuICAgICAgZXJyb3I6ICgpID0+IHtcclxuICAgICAgICB0aGlzLmZpZWxkcyA9IFtdO1xyXG4gICAgICAgIHRoaXMub3BlcmF0b3JzQnlUeXBlID0ge307XHJcbiAgICAgICAgdGhpcy5vdXRwdXRDb2x1bW5zID0gW107XHJcbiAgICAgICAgdGhpcy5pc0xvYWRpbmdTY2hlbWEgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnNob3dNZXNzYWdlKCdGYWlsZWQgdG8gbG9hZCBxdWVyeSBzY2hlbWEuJywgJ2Vycm9yJyk7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZGVmYXVsdFNlbGVjdGVkKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gW1xyXG4gICAgICAnc3RvcmVOYW1lJyxcclxuICAgICAgJ2ZpeHR1cmVDYXRlZ29yeScsXHJcbiAgICAgICdmaXh0dXJlV2lkdGgnLFxyXG4gICAgICAnZml4dHVyZU51bWJlcicsXHJcbiAgICAgICdmaXh0dXJlVHlwZScsXHJcbiAgICAgICdoZWFkZXJMYWJlbCcsXHJcbiAgICAgICd3YWxsTnVtYmVyJyxcclxuICAgICAgJ3dhbGxGaXh0dXJlTnVtYmVyJyxcclxuICAgICAgJ3ZtTmFtZXMnLFxyXG4gICAgICAncG9zaXRpb25MYWJlbCcsXHJcbiAgICAgICdzdGFuZGFyZENhcGFjaXR5JyxcclxuICAgIF0uaW5jbHVkZXMoa2V5KTtcclxuICB9XHJcblxyXG4gIGdldCBmaWx0ZXJhYmxlRmllbGRzKCk6IEZpZWxkRGVmW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuZmllbGRzLmZpbHRlcigoZikgPT4gZi5maWx0ZXJhYmxlKTtcclxuICB9XHJcblxyXG4gIG9wZXJhdG9yc0ZvckZpZWxkKGZpZWxkS2V5OiBzdHJpbmcpOiBPcGVyYXRvckRlZltdIHtcclxuICAgIGxldCBmID0gdGhpcy5maWVsZHMuZmluZCgoeCkgPT4geC5rZXkgPT09IGZpZWxkS2V5KTtcclxuICAgIGlmICghZikgcmV0dXJuIFtdO1xyXG4gICAgcmV0dXJuIHRoaXMub3BlcmF0b3JzQnlUeXBlW2YudHlwZV0gfHwgW107XHJcbiAgfVxyXG5cclxuICBpc1ZhbHVlRGlzYWJsZWRGb3Iob3BlcmF0b3I6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIG9wZXJhdG9yID09PSAnZXhpc3RzJyB8fCBvcGVyYXRvciA9PT0gJ25vdEV4aXN0cyc7XHJcbiAgfVxyXG5cclxuICBvblN0b3Jlc1NlbGVjdGVkKHN0b3JlczogU3RvcmVPcHRpb25bXSkge1xyXG4gICAgdGhpcy5zZWxlY3RlZFN0b3JlcyA9IHN0b3JlcztcclxuICB9XHJcblxyXG4gIGFkZEZpbHRlcigpIHtcclxuICAgIGxldCBmaXJzdEZpZWxkID0gdGhpcy5maWx0ZXJhYmxlRmllbGRzWzBdO1xyXG4gICAgaWYgKCFmaXJzdEZpZWxkKSByZXR1cm47XHJcbiAgICBsZXQgZmlyc3RPcCA9IHRoaXMub3BlcmF0b3JzQnlUeXBlW2ZpcnN0RmllbGQudHlwZV0/LlswXTtcclxuICAgIHRoaXMuZmlsdGVycy5wdXNoKHtcclxuICAgICAgZmllbGQ6IGZpcnN0RmllbGQua2V5LFxyXG4gICAgICBvcGVyYXRvcjogZmlyc3RPcD8ua2V5IHx8ICdlcXVhbHMnLFxyXG4gICAgICB2YWx1ZTogJycsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHJlbW92ZUZpbHRlcihpZHg6IG51bWJlcikge1xyXG4gICAgdGhpcy5maWx0ZXJzLnNwbGljZShpZHgsIDEpO1xyXG4gIH1cclxuXHJcbiAgb25GaWx0ZXJGaWVsZENoYW5nZShpZHg6IG51bWJlcikge1xyXG4gICAgbGV0IHJvdyA9IHRoaXMuZmlsdGVyc1tpZHhdO1xyXG4gICAgbGV0IGFsbG93ZWQgPSB0aGlzLm9wZXJhdG9yc0ZvckZpZWxkKHJvdy5maWVsZCk7XHJcbiAgICBpZiAoIWFsbG93ZWQuZmluZCgob3ApID0+IG9wLmtleSA9PT0gcm93Lm9wZXJhdG9yKSkge1xyXG4gICAgICByb3cub3BlcmF0b3IgPSBhbGxvd2VkWzBdPy5rZXkgfHwgJ2VxdWFscyc7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZWxlY3RBbGxDb2x1bW5zKCkge1xyXG4gICAgdGhpcy5vdXRwdXRDb2x1bW5zLmZvckVhY2goKGMpID0+IChjLnNlbGVjdGVkID0gdHJ1ZSkpO1xyXG4gIH1cclxuXHJcbiAgY2xlYXJBbGxDb2x1bW5zKCkge1xyXG4gICAgdGhpcy5vdXRwdXRDb2x1bW5zLmZvckVhY2goKGMpID0+IChjLnNlbGVjdGVkID0gZmFsc2UpKTtcclxuICB9XHJcblxyXG4gIGdldCBzZWxlY3RlZENvbHVtbnMoKTogQ29sdW1uU2VsZWN0aW9uW10ge1xyXG4gICAgcmV0dXJuIHRoaXMub3V0cHV0Q29sdW1ucy5maWx0ZXIoKGMpID0+IGMuc2VsZWN0ZWQpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHRvdGFsUm93cygpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMucmVzdWx0Py5yb3dzLmxlbmd0aCB8fCAwO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHBhZ2VkUm93cygpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10ge1xyXG4gICAgaWYgKCF0aGlzLnJlc3VsdCkgcmV0dXJuIFtdO1xyXG4gICAgbGV0IHN0YXJ0ID0gKHRoaXMuY3VycmVudFBhZ2UgLSAxKSAqIHRoaXMucGFnZVNpemU7XHJcbiAgICByZXR1cm4gdGhpcy5yZXN1bHQucm93cy5zbGljZShzdGFydCwgc3RhcnQgKyB0aGlzLnBhZ2VTaXplKTtcclxuICB9XHJcblxyXG4gIGdldCBwYWdlU3RhcnQoKTogbnVtYmVyIHtcclxuICAgIGlmICghdGhpcy50b3RhbFJvd3MpIHJldHVybiAwO1xyXG4gICAgcmV0dXJuICh0aGlzLmN1cnJlbnRQYWdlIC0gMSkgKiB0aGlzLnBhZ2VTaXplICsgMTtcclxuICB9XHJcblxyXG4gIGdldCBwYWdlRW5kKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gTWF0aC5taW4odGhpcy5jdXJyZW50UGFnZSAqIHRoaXMucGFnZVNpemUsIHRoaXMudG90YWxSb3dzKTtcclxuICB9XHJcblxyXG4gIG9uUGFnZUNoYW5nZShwYWdlOiBudW1iZXIpIHtcclxuICAgIHRoaXMuY3VycmVudFBhZ2UgPSBOdW1iZXIocGFnZSkgfHwgMTtcclxuICB9XHJcblxyXG4gIG9uUGFnZVNpemVDaGFuZ2Uoc2l6ZTogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnBhZ2VTaXplID0gTnVtYmVyKHNpemUpIHx8IDUwO1xyXG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IDE7XHJcbiAgfVxyXG5cclxuICBvblJ1bigpIHtcclxuICAgIGlmICh0aGlzLnNlbGVjdGVkU3RvcmVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKCdQbGVhc2Ugc2VsZWN0IGF0IGxlYXN0IG9uZSBzdG9yZS4nLCAnZXJyb3InKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRDb2x1bW5zLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKCdQbGVhc2Ugc2VsZWN0IGF0IGxlYXN0IG9uZSBvdXRwdXQgY29sdW1uLicsICdlcnJvcicpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5zZWxlY3Rpb25Nb2RlID09PSAnZmlyc3ROJykge1xyXG4gICAgICBsZXQgbiA9IE51bWJlcih0aGlzLmxpbWl0UGVyU3RvcmUpO1xyXG4gICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShuKSB8fCBuIDwgMSkge1xyXG4gICAgICAgIHRoaXMuc2hvd01lc3NhZ2UoXHJcbiAgICAgICAgICAnTnVtYmVyIG9mIGZpeHR1cmVzIHBlciBzdG9yZSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlci4nLFxyXG4gICAgICAgICAgJ2Vycm9yJyxcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBjb2x1bW5zU25hcHNob3QgPSB0aGlzLnNlbGVjdGVkQ29sdW1ucy5tYXAoKGMpID0+ICh7XHJcbiAgICAgIGtleTogYy5rZXksXHJcbiAgICAgIGxhYmVsOiBjLmxhYmVsLFxyXG4gICAgfSkpO1xyXG5cclxuICAgIGxldCBwYXlsb2FkID0ge1xyXG4gICAgICBjbGllbnRJZDogdGhpcy5jbGllbnRJZCxcclxuICAgICAgc3RvcmVOYW1lczogdGhpcy5zZWxlY3RlZFN0b3Jlcy5tYXAoKHMpID0+IHMubGFiZWwpLFxyXG4gICAgICBmaWx0ZXJzOiB0aGlzLmZpbHRlcnNcclxuICAgICAgICAuZmlsdGVyKChmKSA9PiBmLmZpZWxkICYmIGYub3BlcmF0b3IpXHJcbiAgICAgICAgLm1hcCgoZikgPT4gKHtcclxuICAgICAgICAgIGZpZWxkOiBmLmZpZWxkLFxyXG4gICAgICAgICAgb3BlcmF0b3I6IGYub3BlcmF0b3IsXHJcbiAgICAgICAgICB2YWx1ZTogdGhpcy5pc1ZhbHVlRGlzYWJsZWRGb3IoZi5vcGVyYXRvcikgPyAnJyA6IGYudmFsdWUsXHJcbiAgICAgICAgfSkpLFxyXG4gICAgICBmaWx0ZXJDb21iaW5hdG9yOiB0aGlzLmZpbHRlckNvbWJpbmF0b3IsXHJcbiAgICAgIHNlbGVjdGlvbk1vZGU6IHRoaXMuc2VsZWN0aW9uTW9kZSxcclxuICAgICAgbGltaXRQZXJTdG9yZTpcclxuICAgICAgICB0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICdmaXJzdE4nID8gTnVtYmVyKHRoaXMubGltaXRQZXJTdG9yZSkgOiB1bmRlZmluZWQsXHJcbiAgICAgIGNvbHVtbnM6IGNvbHVtbnNTbmFwc2hvdCxcclxuICAgICAgaW5jbHVkZU5vdEZvdW5kUm93czogdGhpcy5pbmNsdWRlTm90Rm91bmRSb3dzLFxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLmlzUnVubmluZyA9IHRydWU7XHJcbiAgICB0aGlzLnJlc3VsdCA9IG51bGw7XHJcbiAgICB0aGlzLnJlc3VsdENvbHVtbnMgPSBjb2x1bW5zU25hcHNob3Q7XHJcbiAgICB0aGlzLmN1cnJlbnRQYWdlID0gMTtcclxuICAgIHRoaXMuc2JzLnJ1blBsYW5vRGF0YVF1ZXJ5KHBheWxvYWQpLnN1YnNjcmliZSh7XHJcbiAgICAgIG5leHQ6IChyZXM6IGFueSkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVzdWx0ID0gcmVzPy5kYXRhIHx8IG51bGw7XHJcbiAgICAgICAgdGhpcy5pc1J1bm5pbmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmN1cnJlbnRQYWdlID0gMTtcclxuICAgICAgICBpZiAodGhpcy5yZXN1bHQpIHtcclxuICAgICAgICAgIHRoaXMuc2hvd01lc3NhZ2UoYEZvdW5kICR7dGhpcy5yZXN1bHQudG90YWxSb3dzfSByb3cocykuYCwgJ3N1Y2Nlc3MnKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0sXHJcbiAgICAgIGVycm9yOiAoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICB0aGlzLnNob3dNZXNzYWdlKFxyXG4gICAgICAgICAgZXJyPy5lcnJvcj8ubWVzc2FnZSB8fCAnRmFpbGVkIHRvIHJ1biBxdWVyeS4nLFxyXG4gICAgICAgICAgJ2Vycm9yJyxcclxuICAgICAgICApO1xyXG4gICAgICAgIHRoaXMuaXNSdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uRXhwb3J0KCkge1xyXG4gICAgaWYgKCF0aGlzLnJlc3VsdCB8fCAhdGhpcy5yZXN1bHQucm93cy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5zaG93TWVzc2FnZSgnTm8gZGF0YSB0byBleHBvcnQuIFJ1biB0aGUgcXVlcnkgZmlyc3QuJywgJ2Vycm9yJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGxldCBjbGVhbmVkID0gdGhpcy5yZXN1bHQucm93cy5tYXAoKHIpID0+IHtcclxuICAgICAgbGV0IGNvcHk6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuICAgICAgZm9yIChsZXQgY29sIG9mIHRoaXMucmVzdWx0Q29sdW1ucykgY29weVtjb2wubGFiZWxdID0gcltjb2wubGFiZWxdID8/ICcnO1xyXG4gICAgICByZXR1cm4gY29weTtcclxuICAgIH0pO1xyXG4gICAgbGV0IGZpbGVOYW1lID0gYHBsYW5vX2RhdGFfZXhwb3J0XyR7RGF0ZS5ub3coKX1gO1xyXG4gICAgdGhpcy5zYnMuZXhwb3J0QXNFeGNlbEZpbGUoY2xlYW5lZCwgZmlsZU5hbWUpO1xyXG4gIH1cclxuXHJcbiAgc2hvd01lc3NhZ2UobXNnOiBzdHJpbmcsIHR5cGU6ICdzdWNjZXNzJyB8ICdlcnJvcicpIHtcclxuICAgIHRoaXMubWVzc2FnZSA9IG1zZztcclxuICAgIHRoaXMubWVzc2FnZVR5cGUgPSB0eXBlO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiAodGhpcy5tZXNzYWdlID0gJycpLCA1MDAwKTtcclxuICB9XHJcblxyXG4gIC8vIC0tLS0tLS0tLS0gVk0gUGxhY2VtZW50IEV4cG9ydCAtLS0tLS0tLS0tXHJcblxyXG4gIG9uVm1TdG9yZXNTZWxlY3RlZChzdG9yZXM6IFN0b3JlT3B0aW9uW10pIHtcclxuICAgIHRoaXMudm1TZWxlY3RlZFN0b3JlcyA9IHN0b3JlcztcclxuICB9XHJcblxyXG4gIGdldCB2bVRvdGFsUm93cygpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMudm1SZXN1bHQ/LnJvd3MubGVuZ3RoIHx8IDA7XHJcbiAgfVxyXG5cclxuICBnZXQgdm1QYWdlZFJvd3MoKTogUmVjb3JkPHN0cmluZywgYW55PltdIHtcclxuICAgIGlmICghdGhpcy52bVJlc3VsdCkgcmV0dXJuIFtdO1xyXG4gICAgbGV0IHN0YXJ0ID0gKHRoaXMudm1DdXJyZW50UGFnZSAtIDEpICogdGhpcy52bVBhZ2VTaXplO1xyXG4gICAgcmV0dXJuIHRoaXMudm1SZXN1bHQucm93cy5zbGljZShzdGFydCwgc3RhcnQgKyB0aGlzLnZtUGFnZVNpemUpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHZtUGFnZVN0YXJ0KCk6IG51bWJlciB7XHJcbiAgICBpZiAoIXRoaXMudm1Ub3RhbFJvd3MpIHJldHVybiAwO1xyXG4gICAgcmV0dXJuICh0aGlzLnZtQ3VycmVudFBhZ2UgLSAxKSAqIHRoaXMudm1QYWdlU2l6ZSArIDE7XHJcbiAgfVxyXG5cclxuICBnZXQgdm1QYWdlRW5kKCk6IG51bWJlciB7XHJcbiAgICByZXR1cm4gTWF0aC5taW4odGhpcy52bUN1cnJlbnRQYWdlICogdGhpcy52bVBhZ2VTaXplLCB0aGlzLnZtVG90YWxSb3dzKTtcclxuICB9XHJcblxyXG4gIG9uVm1QYWdlQ2hhbmdlKHBhZ2U6IG51bWJlcikge1xyXG4gICAgdGhpcy52bUN1cnJlbnRQYWdlID0gTnVtYmVyKHBhZ2UpIHx8IDE7XHJcbiAgfVxyXG5cclxuICBvblZtUGFnZVNpemVDaGFuZ2Uoc2l6ZTogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnZtUGFnZVNpemUgPSBOdW1iZXIoc2l6ZSkgfHwgNTA7XHJcbiAgICB0aGlzLnZtQ3VycmVudFBhZ2UgPSAxO1xyXG4gIH1cclxuXHJcbiAgb25WbVJ1bigpIHtcclxuICAgIGlmICh0aGlzLnZtU2VsZWN0ZWRTdG9yZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHRoaXMuc2hvd1ZtTWVzc2FnZSgnUGxlYXNlIHNlbGVjdCBhdCBsZWFzdCBvbmUgc3RvcmUuJywgJ2Vycm9yJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICghdGhpcy52bU5hbWVSZWdleCB8fCAhdGhpcy52bU5hbWVSZWdleC50cmltKCkpIHtcclxuICAgICAgdGhpcy5zaG93Vm1NZXNzYWdlKCdQbGVhc2UgZW50ZXIgYSBWTSBuYW1lIChyZWdleCkuJywgJ2Vycm9yJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcGF5bG9hZCA9IHtcclxuICAgICAgY2xpZW50SWQ6IHRoaXMuY2xpZW50SWQsXHJcbiAgICAgIHN0b3JlTmFtZXM6IHRoaXMudm1TZWxlY3RlZFN0b3Jlcy5tYXAoKHMpID0+IHMubGFiZWwpLFxyXG4gICAgICB2bU5hbWU6IHRoaXMudm1OYW1lUmVnZXgudHJpbSgpLFxyXG4gICAgfTtcclxuXHJcbiAgICB0aGlzLmlzVm1SdW5uaW5nID0gdHJ1ZTtcclxuICAgIHRoaXMudm1SZXN1bHQgPSBudWxsO1xyXG4gICAgdGhpcy52bUN1cnJlbnRQYWdlID0gMTtcclxuICAgIHRoaXMuc2JzLnJ1blZtUGxhY2VtZW50UXVlcnkocGF5bG9hZCkuc3Vic2NyaWJlKHtcclxuICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy52bVJlc3VsdCA9IHJlcz8uZGF0YSB8fCBudWxsO1xyXG4gICAgICAgIHRoaXMudm1SZXN1bHRDb2x1bW5zID0gdGhpcy52bVJlc3VsdD8uY29sdW1ucyB8fCBbXTtcclxuICAgICAgICB0aGlzLmlzVm1SdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy52bUN1cnJlbnRQYWdlID0gMTtcclxuICAgICAgICBpZiAodGhpcy52bVJlc3VsdCkge1xyXG4gICAgICAgICAgdGhpcy5zaG93Vm1NZXNzYWdlKFxyXG4gICAgICAgICAgICBgTWF0Y2hlZCAke3RoaXMudm1SZXN1bHQubWF0Y2hlZFZtQ291bnR9IFZNKHMpOyBmb3VuZCAke3RoaXMudm1SZXN1bHQudG90YWxSb3dzfSBwbGFjZW1lbnQgcm93KHMpLmAsXHJcbiAgICAgICAgICAgICdzdWNjZXNzJyxcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9LFxyXG4gICAgICBlcnJvcjogKGVycjogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5zaG93Vm1NZXNzYWdlKFxyXG4gICAgICAgICAgZXJyPy5lcnJvcj8ubWVzc2FnZSB8fCAnRmFpbGVkIHRvIHJ1biBWTSBwbGFjZW1lbnQgcXVlcnkuJyxcclxuICAgICAgICAgICdlcnJvcicsXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0aGlzLmlzVm1SdW5uaW5nID0gZmFsc2U7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uVm1FeHBvcnQoKSB7XHJcbiAgICBpZiAoIXRoaXMudm1SZXN1bHQgfHwgIXRoaXMudm1SZXN1bHQucm93cy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5zaG93Vm1NZXNzYWdlKCdObyBkYXRhIHRvIGV4cG9ydC4gUnVuIHRoZSBxdWVyeSBmaXJzdC4nLCAnZXJyb3InKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgbGV0IGNsZWFuZWQgPSB0aGlzLnZtUmVzdWx0LnJvd3MubWFwKChyKSA9PiB7XHJcbiAgICAgIGxldCBjb3B5OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XHJcbiAgICAgIGZvciAobGV0IGNvbCBvZiB0aGlzLnZtUmVzdWx0Q29sdW1ucykgY29weVtjb2xdID0gcltjb2xdID8/ICcnO1xyXG4gICAgICByZXR1cm4gY29weTtcclxuICAgIH0pO1xyXG4gICAgbGV0IHNhZmVOYW1lID0gKHRoaXMudm1OYW1lUmVnZXggfHwgJ3ZtJylcclxuICAgICAgLnRyaW0oKVxyXG4gICAgICAucmVwbGFjZSgvW15hLXowLTldKy9naSwgJ18nKVxyXG4gICAgICAudG9Mb3dlckNhc2UoKTtcclxuICAgIGxldCBmaWxlTmFtZSA9IGB2bV9wbGFjZW1lbnRfJHtzYWZlTmFtZX1fJHtEYXRlLm5vdygpfWA7XHJcbiAgICB0aGlzLnNicy5leHBvcnRBc0V4Y2VsRmlsZShjbGVhbmVkLCBmaWxlTmFtZSk7XHJcbiAgfVxyXG5cclxuICBzaG93Vm1NZXNzYWdlKG1zZzogc3RyaW5nLCB0eXBlOiAnc3VjY2VzcycgfCAnZXJyb3InKSB7XHJcbiAgICB0aGlzLnZtTWVzc2FnZSA9IG1zZztcclxuICAgIHRoaXMudm1NZXNzYWdlVHlwZSA9IHR5cGU7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+ICh0aGlzLnZtTWVzc2FnZSA9ICcnKSwgNTAwMCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xyXG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xyXG4gIH1cclxufVxyXG4iLCI8c2VjdGlvbiBjbGFzcz1cInBsYW5vLWRhdGEtZXhwb3J0IHAtM1wiPlxyXG4gIDxkaXYgY2xhc3M9XCJjYXJkIHAtNCBtYi0zXCI+XHJcbiAgICA8aDUgY2xhc3M9XCJtYi0xXCI+UGxhbm8gRGF0YSBFeHBvcnQ8L2g1PlxyXG4gICAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkIHNtYWxsIG1iLTNcIj5cclxuICAgICAgQnVpbGQgYSBxdWVyeSBhZ2FpbnN0IHBsYW5vZ3JhbSBmaXh0dXJlcywgcHJldmlldyByZXN1bHRzLCBhbmQgZXhwb3J0IGFzIEV4Y2VsLlxyXG4gICAgPC9wPlxyXG5cclxuICAgIEBpZiAoaXNMb2FkaW5nU2NoZW1hKSB7XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkIHNtYWxsXCI+TG9hZGluZyBxdWVyeSBzY2hlbWEuLi48L2Rpdj5cclxuICAgIH1cclxuXHJcbiAgICA8IS0tIFN0b3JlcyAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJibG9jayBtYi0zXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9jay10aXRsZVwiPlN0b3JlczwvZGl2PlxyXG4gICAgICA8bGliLXN0b3JlLXNlbGVjdFxyXG4gICAgICAgIFtvcHRpb25zXT1cInN0b3JlT3B0aW9uc1wiXHJcbiAgICAgICAgW2luaXRpYWxTZWxlY3RlZF09XCJpbml0aWFsU3RvcmVzXCJcclxuICAgICAgICAoc2VsZWN0ZWRDaGFuZ2UpPVwib25TdG9yZXNTZWxlY3RlZCgkZXZlbnQpXCI+XHJcbiAgICAgIDwvbGliLXN0b3JlLXNlbGVjdD5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gTWF0Y2ggQ3JpdGVyaWEgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYmxvY2sgbWItM1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBtYi0yXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImJsb2NrLXRpdGxlIG1iLTBcIj5NYXRjaCBDcml0ZXJpYTwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGdhcC0zXCI+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVjayBmb3JtLWNoZWNrLWlubGluZSBtYi0wXCI+XHJcbiAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwicmFkaW9cIiBpZD1cImNvbWJBbmRcIlxyXG4gICAgICAgICAgICAgIG5hbWU9XCJjb21iaW5hdG9yXCIgdmFsdWU9XCJBTkRcIiBbKG5nTW9kZWwpXT1cImZpbHRlckNvbWJpbmF0b3JcIj5cclxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cImNvbWJBbmRcIj5NYXRjaCBhbGwgKEFORCk8L2xhYmVsPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVjayBmb3JtLWNoZWNrLWlubGluZSBtYi0wXCI+XHJcbiAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwicmFkaW9cIiBpZD1cImNvbWJPclwiXHJcbiAgICAgICAgICAgICAgbmFtZT1cImNvbWJpbmF0b3JcIiB2YWx1ZT1cIk9SXCIgWyhuZ01vZGVsKV09XCJmaWx0ZXJDb21iaW5hdG9yXCI+XHJcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBmb3I9XCJjb21iT3JcIj5NYXRjaCBhbnkgKE9SKTwvbGFiZWw+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcblxyXG4gICAgICBAaWYgKCFmaWx0ZXJzLmxlbmd0aCkge1xyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkIHNtYWxsIG1iLTJcIj5cclxuICAgICAgICAgIE5vIGNyaXRlcmlhIOKAlCBxdWVyeSB3aWxsIHJldHVybiBldmVyeSBmaXh0dXJlIGZvciB0aGUgc2VsZWN0ZWQgc3RvcmVzLlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICB9XHJcblxyXG4gICAgICBAZm9yIChyb3cgb2YgZmlsdGVyczsgdHJhY2sgJGluZGV4KSB7XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlci1yb3cgZC1mbGV4IGdhcC0yIG1iLTIgYWxpZ24taXRlbXMtY2VudGVyXCI+XHJcbiAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwiZm9ybS1zZWxlY3QgZm9ybS1zZWxlY3Qtc20gZmlsdGVyLWZpZWxkXCJcclxuICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cuZmllbGRcIlxyXG4gICAgICAgICAgICAoY2hhbmdlKT1cIm9uRmlsdGVyRmllbGRDaGFuZ2UoJGluZGV4KVwiPlxyXG4gICAgICAgICAgICBAZm9yIChmIG9mIGZpbHRlcmFibGVGaWVsZHM7IHRyYWNrIGYua2V5KSB7XHJcbiAgICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiZi5rZXlcIj57eyBmLmxhYmVsIH19PC9vcHRpb24+XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIDwvc2VsZWN0PlxyXG5cclxuICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdCBmb3JtLXNlbGVjdC1zbSBmaWx0ZXItb3BcIlxyXG4gICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy5vcGVyYXRvclwiPlxyXG4gICAgICAgICAgICBAZm9yIChvcCBvZiBvcGVyYXRvcnNGb3JGaWVsZChyb3cuZmllbGQpOyB0cmFjayBvcC5rZXkpIHtcclxuICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJvcC5rZXlcIj57eyBvcC5sYWJlbCB9fTwvb3B0aW9uPlxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICA8L3NlbGVjdD5cclxuXHJcbiAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtIGZpbHRlci12YWx1ZVwiXHJcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJpc1ZhbHVlRGlzYWJsZWRGb3Iocm93Lm9wZXJhdG9yKSA/ICfigJQnIDogJ3ZhbHVlJ1wiXHJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJpc1ZhbHVlRGlzYWJsZWRGb3Iocm93Lm9wZXJhdG9yKVwiXHJcbiAgICAgICAgICAgIFsobmdNb2RlbCldPVwicm93LnZhbHVlXCI+XHJcblxyXG4gICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tc20gYnRuLW91dGxpbmUtZGFuZ2VyXCIgKGNsaWNrKT1cInJlbW92ZUZpbHRlcigkaW5kZXgpXCJcclxuICAgICAgICAgICAgdGl0bGU9XCJSZW1vdmVcIj7DlzwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICB9XHJcblxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tb3V0bGluZS1wcmltYXJ5XCIgKGNsaWNrKT1cImFkZEZpbHRlcigpXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwiIWZpbHRlcmFibGVGaWVsZHMubGVuZ3RoXCI+XHJcbiAgICAgICAgKyBBZGQgQ3JpdGVyaW9uXHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBTZWxlY3Rpb24gTW9kZSAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJibG9jayBtYi0zXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9jay10aXRsZVwiPkZpeHR1cmUgU2VsZWN0aW9uPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZmxleC13cmFwIGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtM1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIG1iLTBcIj5cclxuICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwicmFkaW9cIiBpZD1cInNlbEFsbFwiXHJcbiAgICAgICAgICAgIG5hbWU9XCJzZWxlY3Rpb25Nb2RlXCIgdmFsdWU9XCJhbGxcIiBbKG5nTW9kZWwpXT1cInNlbGVjdGlvbk1vZGVcIj5cclxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBmb3I9XCJzZWxBbGxcIj5BbGwgbWF0Y2hpbmcgZml4dHVyZXM8L2xhYmVsPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrIG1iLTBcIj5cclxuICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwicmFkaW9cIiBpZD1cInNlbEZpcnN0TlwiXHJcbiAgICAgICAgICAgIG5hbWU9XCJzZWxlY3Rpb25Nb2RlXCIgdmFsdWU9XCJmaXJzdE5cIiBbKG5nTW9kZWwpXT1cInNlbGVjdGlvbk1vZGVcIj5cclxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBmb3I9XCJzZWxGaXJzdE5cIj5GaXJzdDwvbGFiZWw+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgIG1pbj1cIjFcIlxyXG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtIGNvdW50LWlucHV0XCJcclxuICAgICAgICAgIFsobmdNb2RlbCldPVwibGltaXRQZXJTdG9yZVwiXHJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwic2VsZWN0aW9uTW9kZSAhPT0gJ2ZpcnN0TidcIj5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj5tYXRjaGluZyBmcm9tIGVudHJhbmNlLCBwZXIgc3RvcmU8L3NwYW4+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2sgbXQtMlwiPlxyXG4gICAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwiY2hlY2tib3hcIiBpZD1cImluY05vdEZvdW5kXCJcclxuICAgICAgICAgIFsobmdNb2RlbCldPVwiaW5jbHVkZU5vdEZvdW5kUm93c1wiPlxyXG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBmb3I9XCJpbmNOb3RGb3VuZFwiPlxyXG4gICAgICAgICAgSW5jbHVkZSBlbXB0eSByb3dzIGZvciBzdG9yZXMgd2l0aCBubyBtYXRjaGVzXHJcbiAgICAgICAgPC9sYWJlbD5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIE91dHB1dCBDb2x1bW5zIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImJsb2NrIG1iLTNcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIganVzdGlmeS1jb250ZW50LWJldHdlZW4gbWItMlwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJibG9jay10aXRsZSBtYi0wXCI+T3V0cHV0IENvbHVtbnM8L2Rpdj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGdhcC0yXCI+XHJcbiAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tbGluayBwLTBcIiAoY2xpY2spPVwic2VsZWN0QWxsQ29sdW1ucygpXCI+XHJcbiAgICAgICAgICAgIFNlbGVjdCBhbGxcclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpbmsgcC0wXCIgKGNsaWNrKT1cImNsZWFyQWxsQ29sdW1ucygpXCI+XHJcbiAgICAgICAgICAgIENsZWFyXHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjb2x1bW4tZ3JpZFwiPlxyXG4gICAgICAgIEBmb3IgKGNvbCBvZiBvdXRwdXRDb2x1bW5zOyB0cmFjayBjb2wua2V5KSB7XHJcbiAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb2x1bW4taXRlbVwiPlxyXG4gICAgICAgICAgICA8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0IG1lLTJcIlxyXG4gICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiY29sLnNlbGVjdGVkXCI+XHJcbiAgICAgICAgICAgIHt7IGNvbC5sYWJlbCB9fVxyXG4gICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICB9XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBBY3Rpb24gQnV0dG9ucyAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZ2FwLTJcIj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCJcclxuICAgICAgICAoY2xpY2spPVwib25SdW4oKVwiXHJcbiAgICAgICAgW2Rpc2FibGVkXT1cImlzUnVubmluZyB8fCBpc0xvYWRpbmdTY2hlbWEgfHwgc2VsZWN0ZWRTdG9yZXMubGVuZ3RoID09PSAwXCI+XHJcbiAgICAgICAge3sgaXNSdW5uaW5nID8gJ1J1bm5pbmcuLi4nIDogJ1J1biBRdWVyeScgfX1cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2Vzc1wiXHJcbiAgICAgICAgKGNsaWNrKT1cIm9uRXhwb3J0KClcIlxyXG4gICAgICAgIFtkaXNhYmxlZF09XCIhcmVzdWx0IHx8ICFyZXN1bHQucm93cy5sZW5ndGhcIj5cclxuICAgICAgICBFeHBvcnQgdG8gRXhjZWxcclxuICAgICAgPC9idXR0b24+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICBAaWYgKG1lc3NhZ2UpIHtcclxuICAgICAgPGRpdlxyXG4gICAgICAgIGNsYXNzPVwibXQtMyBhbGVydFwiXHJcbiAgICAgICAgW2NsYXNzLmFsZXJ0LXN1Y2Nlc3NdPVwibWVzc2FnZVR5cGUgPT09ICdzdWNjZXNzJ1wiXHJcbiAgICAgICAgW2NsYXNzLmFsZXJ0LWRhbmdlcl09XCJtZXNzYWdlVHlwZSA9PT0gJ2Vycm9yJ1wiPlxyXG4gICAgICAgIHt7IG1lc3NhZ2UgfX1cclxuICAgICAgPC9kaXY+XHJcbiAgICB9XHJcbiAgPC9kaXY+XHJcblxyXG4gIDwhLS0gVk0gUGxhY2VtZW50IEV4cG9ydCBieSBWTSBOYW1lIC0tPlxyXG4gIDxkaXYgY2xhc3M9XCJjYXJkIHAtNCBtYi0zXCI+XHJcbiAgICA8aDUgY2xhc3M9XCJtYi0xXCI+Vk0gUGxhY2VtZW50IEV4cG9ydCBieSBWTSBOYW1lPC9oNT5cclxuICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbCBtYi0zXCI+XHJcbiAgICAgIEZpbmQgZXZlcnkgZml4dHVyZSAoaW4gdGhlIHNlbGVjdGVkIHN0b3JlcykgdGhhdCBjb250YWlucyBhbnkgVk0gd2hvc2VcclxuICAgICAgPGNvZGU+dm1OYW1lPC9jb2RlPiBtYXRjaGVzIHRoZSByZWdleCwgYW5kIGV4cG9ydCBvbmUgcm93IHBlciBWTSBwbGFjZW1lbnRcclxuICAgICAgd2l0aCBmaXh0dXJlIGRldGFpbHMgYW5kIHNoZWxmL3pvbmUgY29vcmRpbmF0ZXMuXHJcbiAgICA8L3A+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cImJsb2NrIG1iLTNcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImJsb2NrLXRpdGxlXCI+U3RvcmVzPC9kaXY+XHJcbiAgICAgIDxsaWItc3RvcmUtc2VsZWN0XHJcbiAgICAgICAgW29wdGlvbnNdPVwic3RvcmVPcHRpb25zXCJcclxuICAgICAgICBbaW5pdGlhbFNlbGVjdGVkXT1cInZtSW5pdGlhbFN0b3Jlc1wiXHJcbiAgICAgICAgKHNlbGVjdGVkQ2hhbmdlKT1cIm9uVm1TdG9yZXNTZWxlY3RlZCgkZXZlbnQpXCI+XHJcbiAgICAgIDwvbGliLXN0b3JlLXNlbGVjdD5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxkaXYgY2xhc3M9XCJibG9jayBtYi0zXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9jay10aXRsZVwiPlZNIE5hbWUgKHJlZ2V4KTwvZGl2PlxyXG4gICAgICA8aW5wdXRcclxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBmb3JtLWNvbnRyb2wtc21cIlxyXG4gICAgICAgIHBsYWNlaG9sZGVyPVwiZS5nLiBab2RpYWMsIF5IaXBob3AsIExlYXRoZXJpdGVcIlxyXG4gICAgICAgIFsobmdNb2RlbCldPVwidm1OYW1lUmVnZXhcIj5cclxuICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPkNhc2UtaW5zZW5zaXRpdmUuIE1hdGNoZWQgYWdhaW5zdCB0aGUgPGNvZGU+cGxhbm9WbURldGFpbHMudm1OYW1lPC9jb2RlPiBmaWVsZC48L3NtYWxsPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBnYXAtMlwiPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxyXG4gICAgICAgIChjbGljayk9XCJvblZtUnVuKClcIlxyXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc1ZtUnVubmluZyB8fCB2bVNlbGVjdGVkU3RvcmVzLmxlbmd0aCA9PT0gMCB8fCAhdm1OYW1lUmVnZXgudHJpbSgpXCI+XHJcbiAgICAgICAge3sgaXNWbVJ1bm5pbmcgPyAnUnVubmluZy4uLicgOiAnUnVuIFF1ZXJ5JyB9fVxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzXCJcclxuICAgICAgICAoY2xpY2spPVwib25WbUV4cG9ydCgpXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwiIXZtUmVzdWx0IHx8ICF2bVJlc3VsdC5yb3dzLmxlbmd0aFwiPlxyXG4gICAgICAgIEV4cG9ydCB0byBFeGNlbFxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIEBpZiAodm1NZXNzYWdlKSB7XHJcbiAgICAgIDxkaXZcclxuICAgICAgICBjbGFzcz1cIm10LTMgYWxlcnRcIlxyXG4gICAgICAgIFtjbGFzcy5hbGVydC1zdWNjZXNzXT1cInZtTWVzc2FnZVR5cGUgPT09ICdzdWNjZXNzJ1wiXHJcbiAgICAgICAgW2NsYXNzLmFsZXJ0LWRhbmdlcl09XCJ2bU1lc3NhZ2VUeXBlID09PSAnZXJyb3InXCI+XHJcbiAgICAgICAge3sgdm1NZXNzYWdlIH19XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgfVxyXG4gIDwvZGl2PlxyXG5cclxuICBAaWYgKHZtUmVzdWx0KSB7XHJcbiAgICA8ZGl2IGNsYXNzPVwiY2FyZCBwLTQgbWItM1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBtYi0zXCI+XHJcbiAgICAgICAgPGRpdj5cclxuICAgICAgICAgIDxoNiBjbGFzcz1cIm1iLTBcIj5WTSBQbGFjZW1lbnQgUmVzdWx0czwvaDY+XHJcbiAgICAgICAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XHJcbiAgICAgICAgICAgIHt7IHZtVG90YWxSb3dzIH19IHJvdyhzKVxyXG4gICAgICAgICAgICBAaWYgKHZtVG90YWxSb3dzKSB7XHJcbiAgICAgICAgICAgICAgwrcgc2hvd2luZyB7eyB2bVBhZ2VTdGFydCB9feKAk3t7IHZtUGFnZUVuZCB9fVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICA8L3NtYWxsPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIEBpZiAoIXZtUmVzdWx0LnJvd3MubGVuZ3RoKSB7XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWRcIj5ObyBWTSBwbGFjZW1lbnRzIGZvdW5kIGZvciB0aGUgZ2l2ZW4gc3RvcmVzIGFuZCB2bU5hbWUuPC9kaXY+XHJcbiAgICAgIH0gQGVsc2Uge1xyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1yZXNwb25zaXZlXCI+XHJcbiAgICAgICAgICA8dGFibGUgY2xhc3M9XCJ0YWJsZSB0YWJsZS1zbSB0YWJsZS1ib3JkZXJlZFwiPlxyXG4gICAgICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgQGZvciAoY29sIG9mIHZtUmVzdWx0Q29sdW1uczsgdHJhY2sgY29sKSB7XHJcbiAgICAgICAgICAgICAgICAgIDx0aD57eyBjb2wgfX08L3RoPlxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDwvdGhlYWQ+XHJcbiAgICAgICAgICAgIDx0Ym9keT5cclxuICAgICAgICAgICAgICBAZm9yIChyb3cgb2Ygdm1QYWdlZFJvd3M7IHRyYWNrICRpbmRleCkge1xyXG4gICAgICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgICBAZm9yIChjb2wgb2Ygdm1SZXN1bHRDb2x1bW5zOyB0cmFjayBjb2wpIHtcclxuICAgICAgICAgICAgICAgICAgICA8dGRcclxuICAgICAgICAgICAgICAgICAgICAgIFtuZ2JUb29sdGlwXT1cInJvd1tjb2xdPy50b1N0cmluZygpID8gcm93W2NvbF0gOiBudWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lcj1cImJvZHlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgcGxhY2VtZW50PVwidG9wXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtvcGVuRGVsYXldPVwiMzAwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICB7eyByb3dbY29sXSB9fVxyXG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICA8L3Rib2R5PlxyXG4gICAgICAgICAgPC90YWJsZT5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPGxpYi1wYWdpbmF0aW9uXHJcbiAgICAgICAgICBbaXRlbXNQZXJQYWdlXT1cInZtUGFnZVNpemVcIlxyXG4gICAgICAgICAgW2N1cnJlbnRQYWdlXT1cInZtQ3VycmVudFBhZ2VcIlxyXG4gICAgICAgICAgW3RvdGFsSXRlbXNdPVwidm1Ub3RhbFJvd3NcIlxyXG4gICAgICAgICAgW3BhZ2VTaXplXT1cInZtUGFnZVNpemVcIlxyXG4gICAgICAgICAgW3BhZ2luYXRpb25TaXplc109XCJwYWdpbmF0aW9uU2l6ZXNcIlxyXG4gICAgICAgICAgW2RpcmVjdGlvbkxpbmtzXT1cInRydWVcIlxyXG4gICAgICAgICAgKHBhZ2VDaGFuZ2UpPVwib25WbVBhZ2VDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgICAocGFnZVNpemVDaGFuZ2UpPVwib25WbVBhZ2VTaXplQ2hhbmdlKCRldmVudClcIj5cclxuICAgICAgICA8L2xpYi1wYWdpbmF0aW9uPlxyXG4gICAgICB9XHJcbiAgICA8L2Rpdj5cclxuICB9XHJcblxyXG4gIDwhLS0gUmVzdWx0IFByZXZpZXcgLS0+XHJcbiAgQGlmIChyZXN1bHQpIHtcclxuICAgIDxkaXYgY2xhc3M9XCJjYXJkIHAtNFwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBtYi0zXCI+XHJcbiAgICAgICAgPGRpdj5cclxuICAgICAgICAgIDxoNiBjbGFzcz1cIm1iLTBcIj5SZXN1bHRzPC9oNj5cclxuICAgICAgICAgIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cclxuICAgICAgICAgICAge3sgdG90YWxSb3dzIH19IHJvdyhzKVxyXG4gICAgICAgICAgICBAaWYgKHRvdGFsUm93cykge1xyXG4gICAgICAgICAgICAgIMK3IHNob3dpbmcge3sgcGFnZVN0YXJ0IH194oCTe3sgcGFnZUVuZCB9fVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICA8L3NtYWxsPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIEBpZiAoIXJlc3VsdC5yb3dzLmxlbmd0aCkge1xyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+Tm8gZGF0YSBmb3VuZCBmb3IgdGhlIGdpdmVuIHF1ZXJ5LjwvZGl2PlxyXG4gICAgICB9IEBlbHNlIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwidGFibGUtcmVzcG9uc2l2ZVwiPlxyXG4gICAgICAgICAgPHRhYmxlIGNsYXNzPVwidGFibGUgdGFibGUtc20gdGFibGUtYm9yZGVyZWRcIj5cclxuICAgICAgICAgICAgPHRoZWFkPlxyXG4gICAgICAgICAgICAgIDx0cj5cclxuICAgICAgICAgICAgICAgIEBmb3IgKGNvbCBvZiByZXN1bHRDb2x1bW5zOyB0cmFjayBjb2wua2V5KSB7XHJcbiAgICAgICAgICAgICAgICAgIDx0aD57eyBjb2wubGFiZWwgfX08L3RoPlxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDwvdGhlYWQ+XHJcbiAgICAgICAgICAgIDx0Ym9keT5cclxuICAgICAgICAgICAgICBAZm9yIChyb3cgb2YgcGFnZWRSb3dzOyB0cmFjayAkaW5kZXgpIHtcclxuICAgICAgICAgICAgICAgIDx0ciBbY2xhc3Mucm93LW5vdC1mb3VuZF09XCJyb3dbJ19fbm90Rm91bmQnXVwiPlxyXG4gICAgICAgICAgICAgICAgICBAZm9yIChjb2wgb2YgcmVzdWx0Q29sdW1uczsgdHJhY2sgY29sLmtleSkge1xyXG4gICAgICAgICAgICAgICAgICAgIDx0ZFxyXG4gICAgICAgICAgICAgICAgICAgICAgW25nYlRvb2x0aXBdPVwicm93W2NvbC5sYWJlbF0/LnRvU3RyaW5nKCkgPyByb3dbY29sLmxhYmVsXSA6IG51bGxcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyPVwiYm9keVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBwbGFjZW1lbnQ9XCJ0b3BcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgW29wZW5EZWxheV09XCIzMDBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgIHt7IHJvd1tjb2wubGFiZWxdIH19XHJcbiAgICAgICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIDwvdGJvZHk+XHJcbiAgICAgICAgICA8L3RhYmxlPlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8bGliLXBhZ2luYXRpb25cclxuICAgICAgICAgIFtpdGVtc1BlclBhZ2VdPVwicGFnZVNpemVcIlxyXG4gICAgICAgICAgW2N1cnJlbnRQYWdlXT1cImN1cnJlbnRQYWdlXCJcclxuICAgICAgICAgIFt0b3RhbEl0ZW1zXT1cInRvdGFsUm93c1wiXHJcbiAgICAgICAgICBbcGFnZVNpemVdPVwicGFnZVNpemVcIlxyXG4gICAgICAgICAgW3BhZ2luYXRpb25TaXplc109XCJwYWdpbmF0aW9uU2l6ZXNcIlxyXG4gICAgICAgICAgW2RpcmVjdGlvbkxpbmtzXT1cInRydWVcIlxyXG4gICAgICAgICAgKHBhZ2VDaGFuZ2UpPVwib25QYWdlQ2hhbmdlKCRldmVudClcIlxyXG4gICAgICAgICAgKHBhZ2VTaXplQ2hhbmdlKT1cIm9uUGFnZVNpemVDaGFuZ2UoJGV2ZW50KVwiPlxyXG4gICAgICAgIDwvbGliLXBhZ2luYXRpb24+XHJcbiAgICAgIH1cclxuICAgIDwvZGl2PlxyXG4gIH1cclxuPC9zZWN0aW9uPlxyXG4iXX0=