@firestitch/report 18.5.0 → 18.6.0

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 (59) hide show
  1. package/app/reports/components/component-list/component-list.component.d.ts +3 -6
  2. package/app/reports/components/report-canvas/report-canvas.component.d.ts +4 -4
  3. package/app/reports/components/report-component/report-component.component.d.ts +5 -5
  4. package/app/reports/components/timezone-select/timezone-select.component.d.ts +4 -6
  5. package/app/reports/consts/report-week.const.d.ts +2 -0
  6. package/app/reports/data/report-ai-chat.data.d.ts +12 -0
  7. package/app/reports/data/report.data.d.ts +3 -3
  8. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +6 -6
  9. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +5 -0
  10. package/app/reports/export/report-export-collector.service.d.ts +14 -2
  11. package/app/reports/export/report-pdf.service.d.ts +14 -1
  12. package/app/reports/export/report-pptx.service.d.ts +2 -1
  13. package/app/reports/format.d.ts +7 -0
  14. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +7 -0
  15. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +7 -0
  16. package/app/reports/interfaces/report.interface.d.ts +17 -2
  17. package/app/reports/pipes/report-date.pipe.d.ts +7 -0
  18. package/app/reports/report-filter-items.d.ts +5 -0
  19. package/app/reports/report-url-state.d.ts +14 -0
  20. package/app/reports/services/report-filter-state.service.d.ts +24 -2
  21. package/app/reports/theme/typography.d.ts +2 -0
  22. package/app/reports/views/report/fs-ai-report.component.d.ts +16 -8
  23. package/app/reports/views/report/report.component.d.ts +6 -6
  24. package/esm2022/app/reports/components/component-list/component-list.component.mjs +29 -104
  25. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +52 -44
  26. package/esm2022/app/reports/components/report-component/report-component.component.mjs +55 -35
  27. package/esm2022/app/reports/components/timezone-select/timezone-select.component.mjs +23 -23
  28. package/esm2022/app/reports/consts/report-week.const.mjs +7 -0
  29. package/esm2022/app/reports/data/report-ai-chat.data.mjs +25 -0
  30. package/esm2022/app/reports/data/report.data.mjs +22 -9
  31. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +25 -26
  32. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +38 -13
  33. package/esm2022/app/reports/export/report-export-collector.service.mjs +92 -28
  34. package/esm2022/app/reports/export/report-export.service.mjs +11 -8
  35. package/esm2022/app/reports/export/report-pdf.service.mjs +241 -81
  36. package/esm2022/app/reports/export/report-pptx.service.mjs +60 -45
  37. package/esm2022/app/reports/format.mjs +119 -8
  38. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +2 -0
  39. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +2 -0
  40. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  41. package/esm2022/app/reports/option-builder.mjs +131 -15
  42. package/esm2022/app/reports/pipes/report-date.pipe.mjs +21 -0
  43. package/esm2022/app/reports/report-filter-items.mjs +42 -10
  44. package/esm2022/app/reports/report-url-state.mjs +144 -0
  45. package/esm2022/app/reports/services/report-filter-state.service.mjs +308 -64
  46. package/esm2022/app/reports/theme/echarts.mjs +6 -5
  47. package/esm2022/app/reports/theme/typography.mjs +6 -0
  48. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +191 -90
  49. package/esm2022/app/reports/views/report/report.component.mjs +64 -62
  50. package/fesm2022/{firestitch-report-echarts-CtKYuRcT.mjs → firestitch-report-echarts-B9nl9XKM.mjs} +6 -6
  51. package/fesm2022/firestitch-report-echarts-B9nl9XKM.mjs.map +1 -0
  52. package/fesm2022/{firestitch-report-firestitch-report-Df1IXrEs.mjs → firestitch-report-firestitch-report-Bb65HEYB.mjs} +1707 -703
  53. package/fesm2022/firestitch-report-firestitch-report-Bb65HEYB.mjs.map +1 -0
  54. package/fesm2022/firestitch-report.mjs +1 -1
  55. package/package.json +1 -1
  56. package/app/reports/dialogs/report-settings/report-settings-default.d.ts +0 -2
  57. package/esm2022/app/reports/dialogs/report-settings/report-settings-default.mjs +0 -22
  58. package/fesm2022/firestitch-report-echarts-CtKYuRcT.mjs.map +0 -1
  59. package/fesm2022/firestitch-report-firestitch-report-Df1IXrEs.mjs.map +0 -1
@@ -1,24 +1,22 @@
1
1
  import { ChangeDetectionStrategy, Component, DestroyRef, Input, ViewChild, inject, signal } from '@angular/core';
2
2
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
- import { DatePipe } from '@angular/common';
4
- import { ItemType } from '@firestitch/filter';
5
3
  import { FsListComponent, FsListModule, PaginationStrategy } from '@firestitch/list';
6
4
  import { map } from 'rxjs';
7
5
  import { ReportData } from '../../data/report.data';
8
6
  import { formatPeriodLabel } from '../../option-builder';
9
- import { dateBoundString } from '../../report-filter-items';
7
+ import { ReportDatePipe } from '../../pipes/report-date.pipe';
10
8
  import { ReportFilterStateService } from '../../services/report-filter-state.service';
11
9
  import * as i0 from "@angular/core";
12
10
  import * as i1 from "@firestitch/list";
13
- // A list component: FsList + FsFilter rendered from the component's config and
14
- // its report_filters rows. The component's own filter bar carries its filters
15
- // whose group renders at the component level; report-level groups apply
16
- // through the shared filter-state service and merge into every request.
11
+ // A list component: an FsList rendered from the component's config. It has no
12
+ // filter bar of its own: its filters are group-keyed like every other
13
+ // component's, so component-level groups render in the component header strip
14
+ // (ReportComponentComponent) and report-level groups in the report bar, and
15
+ // every request takes its values from the shared filter-state service.
17
16
  // Paging and sorting are pushed into the SQL wrap server-side.
18
17
  export class ComponentListComponent {
19
18
  reportId;
20
19
  component;
21
- groups;
22
20
  listComponent;
23
21
  listConfig;
24
22
  // A plain list's columns are authored and fixed at init. A cross-tab's are
@@ -37,6 +35,10 @@ export class ComponentListComponent {
37
35
  // (it only renders what _load() fetched, which lists skip), so the warning
38
36
  // belongs here.
39
37
  truncated = signal(false);
38
+ // The report's effective zone, which date cells render in. Injected right
39
+ // here rather than read off _filterState, which is declared further down and
40
+ // is still undefined while this initializer runs.
41
+ timezone = inject(ReportFilterStateService).timezone;
40
42
  _reportData = inject(ReportData);
41
43
  _filterState = inject(ReportFilterStateService);
42
44
  _destroyRef = inject(DestroyRef);
@@ -45,23 +47,28 @@ export class ComponentListComponent {
45
47
  this.pivoted.set(!!config.pivotBy?.column);
46
48
  this.columns.set(config.columns ?? []);
47
49
  this._initListConfig(config);
48
- // Report-level filter changes that scope this component re-run the list.
50
+ // A change to any group this list's filters belong to (from the report bar
51
+ // or the component header strip) re-runs the list.
49
52
  this._filterState.changesFor(this.component)
50
53
  .pipe(takeUntilDestroyed(this._destroyRef))
51
54
  .subscribe(() => this.listComponent?.reload());
52
55
  }
53
56
  _initListConfig(config) {
57
+ // The viewer's last sort wins over the authored one, so a list recreated
58
+ // in the same session (page switch, reload after an edit) keeps it.
59
+ const sort = this._filterState.listSort(this.component.id) ?? config.sort;
54
60
  this.listConfig = {
55
61
  // Inside a report component the list is a clean data pane — no status
56
62
  // bar, no reload button (filter changes already refetch).
57
63
  status: false,
58
64
  reload: false,
59
- // Never touch the URL or persist filter/paging state — report filtering
60
- // is session-only.
65
+ // FsList never touches the URL or persists sort/paging state. The sort
66
+ // reaches the URL through ReportFilterStateService (setListSort), and
67
+ // paging stays out of it.
61
68
  queryParam: false,
62
69
  persist: false,
63
- sort: config.sort
64
- ? { value: config.sort.column, direction: config.sort.direction ?? 'asc' }
70
+ sort: sort
71
+ ? { value: sort.column, direction: sort.direction ?? 'asc' }
65
72
  : undefined,
66
73
  // Load-more: the list keeps a fixed, scrollable height and appends the
67
74
  // next page in place instead of swapping pages. The button is pinned to
@@ -82,50 +89,9 @@ export class ComponentListComponent {
82
89
  label: 'Load more',
83
90
  buttonType: 'stroked',
84
91
  },
85
- filters: this._ownFilters().map((filter) => this._filterItem(filter)),
86
92
  fetch: (query) => this._fetch(query),
87
93
  };
88
94
  }
89
- // The filters this list renders in its own bar: its report_filters whose
90
- // group is component-level. Report-level groups render in the report bar.
91
- _ownFilters() {
92
- return (this.component.filters ?? [])
93
- .filter((filter) => {
94
- const group = this.groups?.get(filter.filterGroupId);
95
- return filter.enabled && (!group || group.level === 'component' || group.level === 'both');
96
- });
97
- }
98
- _filterItem(filter) {
99
- const group = this.groups?.get(filter.filterGroupId);
100
- const name = `f${filter.id}`;
101
- const label = filter.label || group?.label || filter.filterColumn;
102
- switch (group?.type) {
103
- case 'dateRange':
104
- return {
105
- name,
106
- type: ItemType.DateRange,
107
- label: [`${label} From`, `${label} To`],
108
- };
109
- case 'select':
110
- return {
111
- name,
112
- type: ItemType.AutoCompleteChips,
113
- label,
114
- // The server sends { value, label }: the filter matches on the value
115
- // (an entity's stable id) while the viewer reads the label.
116
- values: () => this._reportData.filterOptions(this.reportId, filter.id)
117
- .pipe(map((options) => (options ?? [])
118
- .map((option) => ({ name: option.label, value: option.value })))),
119
- };
120
- case 'keyword':
121
- default:
122
- return {
123
- name,
124
- type: ItemType.Keyword,
125
- label,
126
- };
127
- }
128
- }
129
95
  _fetch(query) {
130
96
  // Many/load-more sends `offset` + `limit` (not `page`); derive the page so
131
97
  // the server-side wrap keeps working unchanged. Page strategy still sends
@@ -142,17 +108,12 @@ export class ComponentListComponent {
142
108
  const [column, direction] = order.split(',');
143
109
  state.sort = { column, direction: direction === 'desc' ? 'desc' : 'asc' };
144
110
  }
145
- // Report-level values from the shared session state, merged with this
146
- // list's own filter-bar values (own values win per filter).
147
- const resolved = new Map();
148
- for (const value of this._filterState.resolveForComponent(this.component)) {
149
- resolved.set(value.filterId, value);
150
- }
151
- for (const value of this._barValues(query)) {
152
- resolved.set(value.filterId, value);
153
- }
111
+ this._filterState.setListSort(this.component.id, state.sort ?? null);
112
+ // One source for filter values, the same one charts, KPIs and the exports
113
+ // read, so the list is filtered exactly as its header strip shows.
114
+ const filters = this._filterState.resolveForComponent(this.component);
154
115
  return this._reportData
155
- .componentData(this.reportId, this.component.id, [...resolved.values()], state)
116
+ .componentData(this.reportId, this.component.id, filters, state)
156
117
  .pipe(map((data) => {
157
118
  // A cross-tab's headers come back with the rows: the row-key column
158
119
  // first, then one per pivot value. Re-read them on every fetch, since
@@ -200,57 +161,21 @@ export class ComponentListComponent {
200
161
  .map((match) => match[1]));
201
162
  return years.size > 1;
202
163
  }
203
- // The list's own FsFilter values, read back out of the fetch query by the
204
- // `f<filterId>` naming convention.
205
- _barValues(query) {
206
- const values = [];
207
- for (const filter of this._ownFilters()) {
208
- const group = this.groups?.get(filter.filterGroupId);
209
- const name = `f${filter.id}`;
210
- if (group?.type === 'dateRange') {
211
- const from = dateBoundString(query[`${name}From`]);
212
- const to = dateBoundString(query[`${name}To`]);
213
- if (from || to) {
214
- values.push({ filterId: filter.id, start: from, end: to });
215
- }
216
- }
217
- else if (group?.type === 'select') {
218
- // fs-filter joins a multi-select into one "a,b" string; split it back
219
- // so each value binds separately (else `col IN ('a,b')` matches nothing).
220
- const selected = query[name];
221
- const selectedValues = Array.isArray(selected)
222
- ? selected
223
- : (selected ? String(selected).split(',') : []);
224
- if (selectedValues.length) {
225
- values.push({ filterId: filter.id, values: selectedValues });
226
- }
227
- }
228
- else {
229
- const keyword = String(query[name] ?? '').trim();
230
- if (keyword) {
231
- values.push({ filterId: filter.id, value: keyword });
232
- }
233
- }
234
- }
235
- return values;
236
- }
237
164
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
238
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentListComponent, isStandalone: true, selector: "app-report-component-list", inputs: { reportId: "reportId", component: "component", groups: "groups" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<fs-list [config]=\"listConfig\">\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [sortable]=\"!pivoted() || $first\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (column.format === 'date') {\n {{ row[column.column] | date: 'mediumDate' }}\n } @else {\n {{ row[column.column] }}\n }\n </ng-template>\n </fs-list-column>\n }\n</fs-list>\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;height:100%;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"], dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }, { kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i1.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
165
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentListComponent, isStandalone: true, selector: "app-report-component-list", inputs: { reportId: "reportId", component: "component" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<fs-list [config]=\"listConfig\">\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [sortable]=\"!pivoted() || $first\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (column.format === 'date') {\n {{ row[column.column] | fsReportDate: timezone() }}\n } @else {\n {{ row[column.column] }}\n }\n </ng-template>\n </fs-list-column>\n }\n</fs-list>\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;height:100%;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i1.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "pipe", type: ReportDatePipe, name: "fsReportDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
239
166
  }
240
167
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentListComponent, decorators: [{
241
168
  type: Component,
242
169
  args: [{ selector: 'app-report-component-list', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
243
- DatePipe,
244
170
  FsListModule,
245
- ], template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<fs-list [config]=\"listConfig\">\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [sortable]=\"!pivoted() || $first\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (column.format === 'date') {\n {{ row[column.column] | date: 'mediumDate' }}\n } @else {\n {{ row[column.column] }}\n }\n </ng-template>\n </fs-list-column>\n }\n</fs-list>\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;height:100%;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"] }]
171
+ ReportDatePipe,
172
+ ], template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<fs-list [config]=\"listConfig\">\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [sortable]=\"!pivoted() || $first\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (column.format === 'date') {\n {{ row[column.column] | fsReportDate: timezone() }}\n } @else {\n {{ row[column.column] }}\n }\n </ng-template>\n </fs-list-column>\n }\n</fs-list>\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;height:100%;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"] }]
246
173
  }], propDecorators: { reportId: [{
247
174
  type: Input
248
175
  }], component: [{
249
176
  type: Input
250
- }], groups: [{
251
- type: Input
252
177
  }], listComponent: [{
253
178
  type: ViewChild,
254
179
  args: [FsListComponent]
255
180
  }] } });
256
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFVLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUzQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUMsT0FBTyxFQUFFLGVBQWUsRUFBZ0IsWUFBWSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFbkcsT0FBTyxFQUFjLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUV2QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFXcEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzVELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDOzs7QUFHdEYsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSx3RUFBd0U7QUFDeEUsd0VBQXdFO0FBQ3hFLCtEQUErRDtBQVkvRCxNQUFNLE9BQU8sc0JBQXNCO0lBRWpCLFFBQVEs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QUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7d0dBL1BVLHNCQUFzQjs0RkFBdEIsc0JBQXNCLGdOQU10QixlQUFlLGdEQy9DNUIsNnNCQXdCQSxvNkJEYUksUUFBUSw0Q0FDUixZQUFZOzs0RkFHSCxzQkFBc0I7a0JBWGxDLFNBQVM7K0JBQ0UsMkJBQTJCLG1CQUdwQix1QkFBdUIsQ0FBQyxNQUFNLGNBQ25DLElBQUksV0FDUDt3QkFDUCxRQUFRO3dCQUNSLFlBQVk7cUJBQ2I7OEJBSWUsUUFBUTtzQkFBdkIsS0FBSztnQkFDVSxTQUFTO3NCQUF4QixLQUFLO2dCQUNVLE1BQU07c0JBQXJCLEtBQUs7Z0JBR0MsYUFBYTtzQkFEbkIsU0FBUzt1QkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgSW5wdXQsIE9uSW5pdCwgVmlld0NoaWxkLCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgRGF0ZVBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5pbXBvcnQgeyBJdGVtVHlwZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2ZpbHRlcic7XG5pbXBvcnQgeyBGc0xpc3RDb21wb25lbnQsIEZzTGlzdENvbmZpZywgRnNMaXN0TW9kdWxlLCBQYWdpbmF0aW9uU3RyYXRlZ3kgfSBmcm9tICdAZmlyZXN0aXRjaC9saXN0JztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgbWFwIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7XG4gIENvbXBvbmVudERhdGEsXG4gIENvbXBvbmVudERhdGFTdGF0ZSxcbiAgTGlzdENvbmZpZyxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRGaWx0ZXIsXG4gIFJlcG9ydEZpbHRlckdyb3VwLFxuICBSZXBvcnRGaWx0ZXJPcHRpb24sXG4gIFJlc29sdmVkRmlsdGVyVmFsdWUsXG59IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBmb3JtYXRQZXJpb2RMYWJlbCB9IGZyb20gJy4uLy4uL29wdGlvbi1idWlsZGVyJztcbmltcG9ydCB7IGRhdGVCb3VuZFN0cmluZyB9IGZyb20gJy4uLy4uL3JlcG9ydC1maWx0ZXItaXRlbXMnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcblxuXG4vLyBBIGxpc3QgY29tcG9uZW50OiBGc0xpc3QgKyBGc0ZpbHRlciByZW5kZXJlZCBmcm9tIHRoZSBjb21wb25lbnQncyBjb25maWcgYW5kXG4vLyBpdHMgcmVwb3J0X2ZpbHRlcnMgcm93cy4gVGhlIGNvbXBvbmVudCdzIG93biBmaWx0ZXIgYmFyIGNhcnJpZXMgaXRzIGZpbHRlcnNcbi8vIHdob3NlIGdyb3VwIHJlbmRlcnMgYXQgdGhlIGNvbXBvbmVudCBsZXZlbDsgcmVwb3J0LWxldmVsIGdyb3VwcyBhcHBseVxuLy8gdGhyb3VnaCB0aGUgc2hhcmVkIGZpbHRlci1zdGF0ZSBzZXJ2aWNlIGFuZCBtZXJnZSBpbnRvIGV2ZXJ5IHJlcXVlc3QuXG4vLyBQYWdpbmcgYW5kIHNvcnRpbmcgYXJlIHB1c2hlZCBpbnRvIHRoZSBTUUwgd3JhcCBzZXJ2ZXItc2lkZS5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1yZXBvcnQtY29tcG9uZW50LWxpc3QnLFxuICB0ZW1wbGF0ZVVybDogJy4vY29tcG9uZW50LWxpc3QuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jb21wb25lbnQtbGlzdC5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIERhdGVQaXBlLFxuICAgIEZzTGlzdE1vZHVsZSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQ29tcG9uZW50TGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgcHVibGljIHJlcG9ydElkOiBudW1iZXI7XG4gIEBJbnB1dCgpIHB1YmxpYyBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudDtcbiAgQElucHV0KCkgcHVibGljIGdyb3VwczogTWFwPG51bWJlciwgUmVwb3J0RmlsdGVyR3JvdXA+O1xuXG4gIEBWaWV3Q2hpbGQoRnNMaXN0Q29tcG9uZW50KVxuICBwdWJsaWMgbGlzdENvbXBvbmVudDogRnNMaXN0Q29tcG9uZW50O1xuXG4gIHB1YmxpYyBsaXN0Q29uZmlnOiBGc0xpc3RDb25maWc7XG5cbiAgLy8gQSBwbGFpbiBsaXN0J3MgY29sdW1ucyBhcmUgYXV0aG9yZWQgYW5kIGZpeGVkIGF0IGluaXQuIEEgY3Jvc3MtdGFiJ3MgYXJlXG4gIC8vIHRoZSBwaXZvdCBkaW1lbnNpb24ncyBWQUxVRVMsIHNvIHRoZXkgYXJyaXZlIHdpdGggdGhlIHJvd3MgYW5kIGNoYW5nZVxuICAvLyB3aGVuZXZlciB0aGUgZmlsdGVycyBkbyDigJQgd2hpY2ggaXMgd2h5IHRoaXMgaXMgYSBzaWduYWwgcmF0aGVyIHRoYW4gdGhlXG4gIC8vIG9uZS1zaG90IHJlYWQgaXQgdXNlZCB0byBiZS5cbiAgcHVibGljIGNvbHVtbnMgPSBzaWduYWw8eyBjb2x1bW46IHN0cmluZzsgbGFiZWw/OiBzdHJpbmc7IGZvcm1hdD86IHN0cmluZyB9W10+KFtdKTtcblxuICAvLyBBIGNyb3NzLXRhYiBzb3J0cyBvbmx5IGJ5IGl0cyByb3cta2V5IGNvbHVtbjogZXZlcnkgb3RoZXIgaGVhZGVyIGlzIGFcbiAgLy8gcGl2b3QgdmFsdWUsIGFuZCB0aGUgc2VydmVyIG9yZGVycyB0aGUgbG9uZyByb3dzIGJlZm9yZSBwaXZvdGluZywgc28gYVxuICAvLyBjbGljayBvbiBcIk1hciAyMDI2XCIgaGFzIG5vdGhpbmcgdG8gb3JkZXIgYnkuXG4gIHB1YmxpYyBwaXZvdGVkID0gc2lnbmFsKGZhbHNlKTtcblxuICAvLyBBIGN1dCByZXN1bHQgaXMgd29yc2UgZm9yIGEgZ3JpZCB0aGFuIGZvciBhIGxpc3Q6IHRoZSBjdXQgbGFuZHMgb24gdGhlIExPTkdcbiAgLy8gcm93cyBiZWZvcmUgdGhlIHJlc2hhcGUsIHNvIGEgcGl2b3QgdmFsdWUgbGl2aW5nIG9ubHkgaW4gdGhlIHRhaWwgdmFuaXNoZXNcbiAgLy8gYXMgYSB3aG9sZSBDT0xVTU4gYW5kIHN0cmFkZGxlZCBjZWxscyBjb21lIGJhY2sgYmxhbmssIGluZGlzdGluZ3Vpc2hhYmxlXG4gIC8vIGZyb20gYSByZWFsIHplcm8uIFRoZSBwYXJlbnQncyB0cnVuY2F0aW9uIGJhbm5lciBuZXZlciBmaXJlcyBmb3IgYSBsaXN0XG4gIC8vIChpdCBvbmx5IHJlbmRlcnMgd2hhdCBfbG9hZCgpIGZldGNoZWQsIHdoaWNoIGxpc3RzIHNraXApLCBzbyB0aGUgd2FybmluZ1xuICAvLyBiZWxvbmdzIGhlcmUuXG4gIHB1YmxpYyB0cnVuY2F0ZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIHByaXZhdGUgX3JlcG9ydERhdGEgPSBpbmplY3QoUmVwb3J0RGF0YSk7XG4gIHByaXZhdGUgX2ZpbHRlclN0YXRlID0gaW5qZWN0KFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSk7XG4gIHByaXZhdGUgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9ICh0aGlzLmNvbXBvbmVudC5jb25maWcgPz8ge30pIGFzIExpc3RDb25maWc7XG4gICAgdGhpcy5waXZvdGVkLnNldCghIWNvbmZpZy5waXZvdEJ5Py5jb2x1bW4pO1xuICAgIHRoaXMuY29sdW1ucy5zZXQoY29uZmlnLmNvbHVtbnMgPz8gW10pO1xuXG4gICAgdGhpcy5faW5pdExpc3RDb25maWcoY29uZmlnKTtcblxuICAgIC8vIFJlcG9ydC1sZXZlbCBmaWx0ZXIgY2hhbmdlcyB0aGF0IHNjb3BlIHRoaXMgY29tcG9uZW50IHJlLXJ1biB0aGUgbGlzdC5cbiAgICB0aGlzLl9maWx0ZXJTdGF0ZS5jaGFuZ2VzRm9yKHRoaXMuY29tcG9uZW50KVxuICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmxpc3RDb21wb25lbnQ/LnJlbG9hZCgpKTtcbiAgfVxuXG4gIHByaXZhdGUgX2luaXRMaXN0Q29uZmlnKGNvbmZpZzogTGlzdENvbmZpZyk6IHZvaWQge1xuICAgIHRoaXMubGlzdENvbmZpZyA9IHtcbiAgICAgIC8vIEluc2lkZSBhIHJlcG9ydCBjb21wb25lbnQgdGhlIGxpc3QgaXMgYSBjbGVhbiBkYXRhIHBhbmUg4oCUIG5vIHN0YXR1c1xuICAgICAgLy8gYmFyLCBubyByZWxvYWQgYnV0dG9uIChmaWx0ZXIgY2hhbmdlcyBhbHJlYWR5IHJlZmV0Y2gpLlxuICAgICAgc3RhdHVzOiBmYWxzZSxcbiAgICAgIHJlbG9hZDogZmFsc2UsXG4gICAgICAvLyBOZXZlciB0b3VjaCB0aGUgVVJMIG9yIHBlcnNpc3QgZmlsdGVyL3BhZ2luZyBzdGF0ZSDigJQgcmVwb3J0IGZpbHRlcmluZ1xuICAgICAgLy8gaXMgc2Vzc2lvbi1vbmx5LlxuICAgICAgcXVlcnlQYXJhbTogZmFsc2UsXG4gICAgICBwZXJzaXN0OiBmYWxzZSxcbiAgICAgIHNvcnQ6IGNvbmZpZy5zb3J0XG4gICAgICAgID8geyB2YWx1ZTogY29uZmlnLnNvcnQuY29sdW1uLCBkaXJlY3Rpb246IGNvbmZpZy5zb3J0LmRpcmVjdGlvbiA/PyAnYXNjJyB9XG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgLy8gTG9hZC1tb3JlOiB0aGUgbGlzdCBrZWVwcyBhIGZpeGVkLCBzY3JvbGxhYmxlIGhlaWdodCBhbmQgYXBwZW5kcyB0aGVcbiAgICAgIC8vIG5leHQgcGFnZSBpbiBwbGFjZSBpbnN0ZWFkIG9mIHN3YXBwaW5nIHBhZ2VzLiBUaGUgYnV0dG9uIGlzIHBpbm5lZCB0b1xuICAgICAgLy8gdGhlIGJvdHRvbSBvZiB0aGUgc2Nyb2xsIHBhbmUgKHNlZSBjb21wb25lbnQgU0NTUykuXG4gICAgICAvL1xuICAgICAgLy8gVXNlcyB0aGUgT2Zmc2V0IHN0cmF0ZWd5IChvZmZzZXQgKyBsaW1pdCkgcmF0aGVyIHRoYW4gTWFueTogaW5cbiAgICAgIC8vIEBmaXJlc3RpdGNoL2xpc3QgdGhlIHBhZ2luYXRpb24gdGVtcGxhdGUgcmVzb2x2ZXMgYGhhc01hbnlTdHJhdGVneWBcbiAgICAgIC8vIEJFRk9SRSBgbG9hZE1vcmVFbmFibGVkYCwgYW5kIE1hbnkgcmVuZGVycyBhIGZvcndhcmQtb25seSBwYWdlIHBhZ2VyIOKAlFxuICAgICAgLy8gc28gTWFueSB3b3VsZCBzdXBwcmVzcyB0aGUgbG9hZC1tb3JlIGJ1dHRvbiBlbnRpcmVseS4gT2Zmc2V0ICsgbG9hZE1vcmVcbiAgICAgIC8vIGlzIHRoZSBjb21iaW5hdGlvbiB0aGF0IGFjdHVhbGx5IHJlbmRlcnMgYW5kIGFwcGVuZHMuIGBfZmV0Y2hgIGFscmVhZHlcbiAgICAgIC8vIGRlcml2ZXMgYHBhZ2VgIGZyb20gYG9mZnNldGAsIHNvIHRoZSBzZXJ2ZXItc2lkZSB3cmFwIGlzIHVuYWZmZWN0ZWQuXG4gICAgICBwYWdpbmc6IHtcbiAgICAgICAgbGltaXQ6IGNvbmZpZy5wYWdlU2l6ZSA/PyAyNSxcbiAgICAgICAgc3RyYXRlZ3k6IFBhZ2luYXRpb25TdHJhdGVneS5PZmZzZXQsXG4gICAgICB9LFxuICAgICAgbG9hZE1vcmU6IHtcbiAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgbGFiZWw6ICdMb2FkIG1vcmUnLFxuICAgICAgICBidXR0b25UeXBlOiAnc3Ryb2tlZCcsXG4gICAgICB9LFxuICAgICAgZmlsdGVyczogdGhpcy5fb3duRmlsdGVycygpLm1hcCgoZmlsdGVyKSA9PiB0aGlzLl9maWx0ZXJJdGVtKGZpbHRlcikpLFxuICAgICAgZmV0Y2g6IChxdWVyeTogYW55KSA9PiB0aGlzLl9mZXRjaChxdWVyeSksXG4gICAgfTtcbiAgfVxuXG4gIC8vIFRoZSBmaWx0ZXJzIHRoaXMgbGlzdCByZW5kZXJzIGluIGl0cyBvd24gYmFyOiBpdHMgcmVwb3J0X2ZpbHRlcnMgd2hvc2VcbiAgLy8gZ3JvdXAgaXMgY29tcG9uZW50LWxldmVsLiBSZXBvcnQtbGV2ZWwgZ3JvdXBzIHJlbmRlciBpbiB0aGUgcmVwb3J0IGJhci5cbiAgcHJpdmF0ZSBfb3duRmlsdGVycygpOiBSZXBvcnRGaWx0ZXJbXSB7XG4gICAgcmV0dXJuICh0aGlzLmNvbXBvbmVudC5maWx0ZXJzID8/IFtdKVxuICAgICAgLmZpbHRlcigoZmlsdGVyKSA9PiB7XG4gICAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5ncm91cHM/LmdldChmaWx0ZXIuZmlsdGVyR3JvdXBJZCk7XG5cbiAgICAgICAgcmV0dXJuIGZpbHRlci5lbmFibGVkICYmICghZ3JvdXAgfHwgZ3JvdXAubGV2ZWwgPT09ICdjb21wb25lbnQnIHx8IGdyb3VwLmxldmVsID09PSAnYm90aCcpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9maWx0ZXJJdGVtKGZpbHRlcjogUmVwb3J0RmlsdGVyKTogYW55IHtcbiAgICBjb25zdCBncm91cCA9IHRoaXMuZ3JvdXBzPy5nZXQoZmlsdGVyLmZpbHRlckdyb3VwSWQpO1xuICAgIGNvbnN0IG5hbWUgPSBgZiR7ZmlsdGVyLmlkfWA7XG4gICAgY29uc3QgbGFiZWwgPSBmaWx0ZXIubGFiZWwgfHwgZ3JvdXA/LmxhYmVsIHx8IGZpbHRlci5maWx0ZXJDb2x1bW47XG5cbiAgICBzd2l0Y2ggKGdyb3VwPy50eXBlKSB7XG4gICAgICBjYXNlICdkYXRlUmFuZ2UnOlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgdHlwZTogSXRlbVR5cGUuRGF0ZVJhbmdlLFxuICAgICAgICAgIGxhYmVsOiBbYCR7bGFiZWx9IEZyb21gLCBgJHtsYWJlbH0gVG9gXSxcbiAgICAgICAgfTtcblxuICAgICAgY2FzZSAnc2VsZWN0JzpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIHR5cGU6IEl0ZW1UeXBlLkF1dG9Db21wbGV0ZUNoaXBzLFxuICAgICAgICAgIGxhYmVsLFxuICAgICAgICAgIC8vIFRoZSBzZXJ2ZXIgc2VuZHMgeyB2YWx1ZSwgbGFiZWwgfTogdGhlIGZpbHRlciBtYXRjaGVzIG9uIHRoZSB2YWx1ZVxuICAgICAgICAgIC8vIChhbiBlbnRpdHkncyBzdGFibGUgaWQpIHdoaWxlIHRoZSB2aWV3ZXIgcmVhZHMgdGhlIGxhYmVsLlxuICAgICAgICAgIHZhbHVlczogKCkgPT4gdGhpcy5fcmVwb3J0RGF0YS5maWx0ZXJPcHRpb25zKHRoaXMucmVwb3J0SWQsIGZpbHRlci5pZClcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICBtYXAoKG9wdGlvbnM6IFJlcG9ydEZpbHRlck9wdGlvbltdKSA9PiAob3B0aW9ucyA/PyBbXSlcbiAgICAgICAgICAgICAgICAubWFwKChvcHRpb24pID0+ICh7IG5hbWU6IG9wdGlvbi5sYWJlbCwgdmFsdWU6IG9wdGlvbi52YWx1ZSB9KSkpLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgfTtcblxuICAgICAgY2FzZSAna2V5d29yZCc6XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgdHlwZTogSXRlbVR5cGUuS2V5d29yZCxcbiAgICAgICAgICBsYWJlbCxcbiAgICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9mZXRjaChxdWVyeTogYW55KTogT2JzZXJ2YWJsZTx7IGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107IHBhZ2luZzogYW55IH0+IHtcbiAgICAvLyBNYW55L2xvYWQtbW9yZSBzZW5kcyBgb2Zmc2V0YCArIGBsaW1pdGAgKG5vdCBgcGFnZWApOyBkZXJpdmUgdGhlIHBhZ2Ugc29cbiAgICAvLyB0aGUgc2VydmVyLXNpZGUgd3JhcCBrZWVwcyB3b3JraW5nIHVuY2hhbmdlZC4gUGFnZSBzdHJhdGVneSBzdGlsbCBzZW5kc1xuICAgIC8vIGBwYWdlYCBkaXJlY3RseS5cbiAgICBjb25zdCBwYWdlU2l6ZSA9IHF1ZXJ5LmxpbWl0ID8/IDI1O1xuICAgIGNvbnN0IHBhZ2UgPSBxdWVyeS5wYWdlXG4gICAgICA/PyAocXVlcnkub2Zmc2V0ICE9IG51bGwgPyBNYXRoLmZsb29yKHF1ZXJ5Lm9mZnNldCAvIHBhZ2VTaXplKSArIDEgOiAxKTtcblxuICAgIGNvbnN0IHN0YXRlOiBDb21wb25lbnREYXRhU3RhdGUgPSB7XG4gICAgICBwYWdlLFxuICAgICAgcGFnZVNpemUsXG4gICAgfTtcblxuICAgIGNvbnN0IG9yZGVyID0gU3RyaW5nKHF1ZXJ5Lm9yZGVyID8/ICcnKTtcbiAgICBpZiAob3JkZXIpIHtcbiAgICAgIGNvbnN0IFtjb2x1bW4sIGRpcmVjdGlvbl0gPSBvcmRlci5zcGxpdCgnLCcpO1xuICAgICAgc3RhdGUuc29ydCA9IHsgY29sdW1uLCBkaXJlY3Rpb246IGRpcmVjdGlvbiA9PT0gJ2Rlc2MnID8gJ2Rlc2MnIDogJ2FzYycgfTtcbiAgICB9XG5cbiAgICAvLyBSZXBvcnQtbGV2ZWwgdmFsdWVzIGZyb20gdGhlIHNoYXJlZCBzZXNzaW9uIHN0YXRlLCBtZXJnZWQgd2l0aCB0aGlzXG4gICAgLy8gbGlzdCdzIG93biBmaWx0ZXItYmFyIHZhbHVlcyAob3duIHZhbHVlcyB3aW4gcGVyIGZpbHRlcikuXG4gICAgY29uc3QgcmVzb2x2ZWQgPSBuZXcgTWFwPG51bWJlciwgUmVzb2x2ZWRGaWx0ZXJWYWx1ZT4oKTtcbiAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHRoaXMuX2ZpbHRlclN0YXRlLnJlc29sdmVGb3JDb21wb25lbnQodGhpcy5jb21wb25lbnQpKSB7XG4gICAgICByZXNvbHZlZC5zZXQodmFsdWUuZmlsdGVySWQsIHZhbHVlKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCB2YWx1ZSBvZiB0aGlzLl9iYXJWYWx1ZXMocXVlcnkpKSB7XG4gICAgICByZXNvbHZlZC5zZXQodmFsdWUuZmlsdGVySWQsIHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YVxuICAgICAgLmNvbXBvbmVudERhdGEodGhpcy5yZXBvcnRJZCwgdGhpcy5jb21wb25lbnQuaWQsIFsuLi5yZXNvbHZlZC52YWx1ZXMoKV0sIHN0YXRlKVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcCgoZGF0YTogQ29tcG9uZW50RGF0YSkgPT4ge1xuICAgICAgICAgIC8vIEEgY3Jvc3MtdGFiJ3MgaGVhZGVycyBjb21lIGJhY2sgd2l0aCB0aGUgcm93czogdGhlIHJvdy1rZXkgY29sdW1uXG4gICAgICAgICAgLy8gZmlyc3QsIHRoZW4gb25lIHBlciBwaXZvdCB2YWx1ZS4gUmUtcmVhZCB0aGVtIG9uIGV2ZXJ5IGZldGNoLCBzaW5jZVxuICAgICAgICAgIC8vIGEgZmlsdGVyIGNoYW5nZSBjYW4gYWRkIG9yIHJlbW92ZSBhIGNvbHVtbi5cbiAgICAgICAgICBpZiAodGhpcy5waXZvdGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY29sdW1ucy5zZXQodGhpcy5fcGl2b3RDb2x1bW5zKGRhdGEpKTtcbiAgICAgICAgICAgIHRoaXMudHJ1bmNhdGVkLnNldCghIWRhdGEudHJ1bmNhdGVkKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0YTogZGF0YS5yb3dzID8/IFtdLFxuICAgICAgICAgICAgcGFnaW5nOiB7XG4gICAgICAgICAgICAgIGxpbWl0OiBkYXRhLnBhZ2luZz8ucGFnZVNpemUgPz8gc3RhdGUucGFnZVNpemUsXG4gICAgICAgICAgICAgIHJlY29yZHM6IGRhdGEucGFnaW5nPy50b3RhbCA/PyAoZGF0YS5yb3dzPy5sZW5ndGggPz8gMCksXG4gICAgICAgICAgICAgIHBhZ2U6IGRhdGEucGFnaW5nPy5wYWdlID8/IHN0YXRlLnBhZ2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIC8vIEEgY3Jvc3MtdGFiJ3MgY29sdW1ucywgYnVpbHQgZnJvbSB0aGUgd2lyZS4gVGhlIGZpcnN0IGlzIHRoZSByb3cga2V5IGFuZFxuICAvLyBrZWVwcyBpdHMgYXV0aG9yZWQgbGFiZWw7IHRoZSByZXN0IGFyZSBwaXZvdCBWQUxVRVMgdXNlZCBhcyBoZWFkaW5ncy4gV2hlblxuICAvLyB0aGUgcGl2b3QgYXhpcyBpcyBhIHRpbWUgZGltZW5zaW9uIHRoZSBzZXJ2ZXIgc2VuZHMgdGhlIGdyYWluIGl0IGJ1Y2tldGVkXG4gIC8vIGF0LCBzbyBhIHBlcmlvZC1zdGFydCBsaWtlIFwiMjAyNi0wMS0wMVwiIGlzIHNob3duIGFzIFwiSmFuIDIwMjZcIiDigJQgdGhlIHNhbWVcbiAgLy8gZm9ybWF0dGVyIHRoZSBjaGFydCdzIHgtYXhpcyB1c2VzLCBzbyBhIGdyaWQgYW5kIGEgY2hhcnQgb2YgdGhlIHNhbWUgcXVlcnlcbiAgLy8gbGFiZWwgdGhlaXIgcGVyaW9kcyBpZGVudGljYWxseS5cbiAgcHJpdmF0ZSBfcGl2b3RDb2x1bW5zKGRhdGE6IENvbXBvbmVudERhdGEpOiB7IGNvbHVtbjogc3RyaW5nOyBsYWJlbD86IHN0cmluZzsgZm9ybWF0Pzogc3RyaW5nIH1bXSB7XG4gICAgY29uc3QgY29uZmlnID0gKHRoaXMuY29tcG9uZW50LmNvbmZpZyA/PyB7fSkgYXMgTGlzdENvbmZpZztcbiAgICBjb25zdCBncmFudWxhcml0eSA9IGRhdGEuZ3JhbnVsYXJpdHk7XG4gICAgY29uc3QgbXVsdGlZZWFyID0gdGhpcy5fc3BhbnNNdWx0aXBsZVllYXJzKGRhdGEuY29sdW1ucyA/PyBbXSk7XG5cbiAgICByZXR1cm4gKGRhdGEuY29sdW1ucyA/PyBbXSkubWFwKChjb2x1bW4sIGluZGV4KSA9PiB7XG4gICAgICBpZiAoaW5kZXggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHsgY29sdW1uLCBsYWJlbDogY29uZmlnLnJvd0J5Py5sYWJlbCB8fCBjb2x1bW4gfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29sdW1uLFxuICAgICAgICBsYWJlbDogZ3JhbnVsYXJpdHkgPyBmb3JtYXRQZXJpb2RMYWJlbChjb2x1bW4sIGdyYW51bGFyaXR5LCBtdWx0aVllYXIpIDogY29sdW1uLFxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFdoZXRoZXIgdGhlIHBlcmlvZCBjb2x1bW5zIGNyb3NzIGEgeWVhciBib3VuZGFyeSwgd2hpY2ggZGVjaWRlcyBpZiB0aGVcbiAgLy8gZm9ybWF0dGVyIGFwcGVuZHMgdGhlIHllYXIgdG8gZWFjaCBoZWFkaW5nLlxuICBwcml2YXRlIF9zcGFuc011bHRpcGxlWWVhcnMoY29sdW1uczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICBjb25zdCB5ZWFycyA9IG5ldyBTZXQoXG4gICAgICBjb2x1bW5zXG4gICAgICAgIC5tYXAoKGNvbHVtbikgPT4gL14oXFxkezR9KS1cXGR7Mn0tXFxkezJ9Ly5leGVjKGNvbHVtbikpXG4gICAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgICAgLm1hcCgobWF0Y2gpID0+IG1hdGNoWzFdKSxcbiAgICApO1xuXG4gICAgcmV0dXJuIHllYXJzLnNpemUgPiAxO1xuICB9XG5cbiAgLy8gVGhlIGxpc3QncyBvd24gRnNGaWx0ZXIgdmFsdWVzLCByZWFkIGJhY2sgb3V0IG9mIHRoZSBmZXRjaCBxdWVyeSBieSB0aGVcbiAgLy8gYGY8ZmlsdGVySWQ+YCBuYW1pbmcgY29udmVudGlvbi5cbiAgcHJpdmF0ZSBfYmFyVmFsdWVzKHF1ZXJ5OiBhbnkpOiBSZXNvbHZlZEZpbHRlclZhbHVlW10ge1xuICAgIGNvbnN0IHZhbHVlczogUmVzb2x2ZWRGaWx0ZXJWYWx1ZVtdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiB0aGlzLl9vd25GaWx0ZXJzKCkpIHtcbiAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5ncm91cHM/LmdldChmaWx0ZXIuZmlsdGVyR3JvdXBJZCk7XG4gICAgICBjb25zdCBuYW1lID0gYGYke2ZpbHRlci5pZH1gO1xuXG4gICAgICBpZiAoZ3JvdXA/LnR5cGUgPT09ICdkYXRlUmFuZ2UnKSB7XG4gICAgICAgIGNvbnN0IGZyb20gPSBkYXRlQm91bmRTdHJpbmcocXVlcnlbYCR7bmFtZX1Gcm9tYF0pO1xuICAgICAgICBjb25zdCB0byA9IGRhdGVCb3VuZFN0cmluZyhxdWVyeVtgJHtuYW1lfVRvYF0pO1xuICAgICAgICBpZiAoZnJvbSB8fCB0bykge1xuICAgICAgICAgIHZhbHVlcy5wdXNoKHsgZmlsdGVySWQ6IGZpbHRlci5pZCwgc3RhcnQ6IGZyb20sIGVuZDogdG8gfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoZ3JvdXA/LnR5cGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAgIC8vIGZzLWZpbHRlciBqb2lucyBhIG11bHRpLXNlbGVjdCBpbnRvIG9uZSBcImEsYlwiIHN0cmluZzsgc3BsaXQgaXQgYmFja1xuICAgICAgICAvLyBzbyBlYWNoIHZhbHVlIGJpbmRzIHNlcGFyYXRlbHkgKGVsc2UgYGNvbCBJTiAoJ2EsYicpYCBtYXRjaGVzIG5vdGhpbmcpLlxuICAgICAgICBjb25zdCBzZWxlY3RlZCA9IHF1ZXJ5W25hbWVdO1xuICAgICAgICBjb25zdCBzZWxlY3RlZFZhbHVlcyA9IEFycmF5LmlzQXJyYXkoc2VsZWN0ZWQpXG4gICAgICAgICAgPyBzZWxlY3RlZFxuICAgICAgICAgIDogKHNlbGVjdGVkID8gU3RyaW5nKHNlbGVjdGVkKS5zcGxpdCgnLCcpIDogW10pO1xuICAgICAgICBpZiAoc2VsZWN0ZWRWYWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goeyBmaWx0ZXJJZDogZmlsdGVyLmlkLCB2YWx1ZXM6IHNlbGVjdGVkVmFsdWVzIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBrZXl3b3JkID0gU3RyaW5nKHF1ZXJ5W25hbWVdID8/ICcnKS50cmltKCk7XG4gICAgICAgIGlmIChrZXl3b3JkKSB7XG4gICAgICAgICAgdmFsdWVzLnB1c2goeyBmaWx0ZXJJZDogZmlsdGVyLmlkLCB2YWx1ZToga2V5d29yZCB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cbn1cbiIsIkBpZiAodHJ1bmNhdGVkKCkpIHtcbiAgPGRpdiBjbGFzcz1cInBpdm90LXRydW5jYXRlZFwiPlxuICAgIFRoaXMgZ3JpZCB3YXMgYnVpbHQgZnJvbSBhIHBhcnRpYWwgcmVzdWx0LCBzbyBzb21lIGNvbHVtbnMgb3IgdmFsdWVzIG1heSBiZSBtaXNzaW5nLiBOYXJyb3cgaXQgd2l0aCBhIGZpbHRlci5cbiAgPC9kaXY+XG59XG5cbjxmcy1saXN0IFtjb25maWddPVwibGlzdENvbmZpZ1wiPlxuICBAZm9yIChjb2x1bW4gb2YgY29sdW1ucygpOyB0cmFjayBjb2x1bW4uY29sdW1uKSB7XG4gICAgPGZzLWxpc3QtY29sdW1uXG4gICAgICBbbmFtZV09XCJjb2x1bW4uY29sdW1uXCJcbiAgICAgIFt0aXRsZV09XCJjb2x1bW4ubGFiZWwgfHwgY29sdW1uLmNvbHVtblwiXG4gICAgICBbc29ydGFibGVdPVwiIXBpdm90ZWQoKSB8fCAkZmlyc3RcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICBmcy1saXN0LWNlbGxcbiAgICAgICAgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgICBAaWYgKGNvbHVtbi5mb3JtYXQgPT09ICdkYXRlJykge1xuICAgICAgICAgIHt7IHJvd1tjb2x1bW4uY29sdW1uXSB8IGRhdGU6ICdtZWRpdW1EYXRlJyB9fVxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICB7eyByb3dbY29sdW1uLmNvbHVtbl0gfX1cbiAgICAgICAgfVxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2ZzLWxpc3QtY29sdW1uPlxuICB9XG48L2ZzLWxpc3Q+XG4iXX0=
181
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFVLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRWhFLE9BQU8sRUFBRSxlQUFlLEVBQWdCLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRW5HLE9BQU8sRUFBYyxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFdkMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBUXBELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQzs7O0FBR3RGLDhFQUE4RTtBQUM5RSxzRUFBc0U7QUFDdEUsOEVBQThFO0FBQzlFLDRFQUE0RTtBQUM1RSx1RUFBdUU7QUFDdkUsK0RBQStEO0FBWS9ELE1BQU0sT0FBTyxzQkFBc0I7SUFFakIsUUFBUSxDQUFTO0lBQ2pCLFNBQVMsQ0FBa0I7SUFHcEMsYUFBYSxDQUFrQjtJQUUvQixVQUFVLENBQWU7SUFFaEMsMkVBQTJFO0lBQzNF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bEMsU0FBUzsrQkFDRSwyQkFBMkIsbUJBR3BCLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osY0FBYztxQkFDZjs4QkFJZSxRQUFRO3NCQUF2QixLQUFLO2dCQUNVLFNBQVM7c0JBQXhCLEtBQUs7Z0JBR0MsYUFBYTtzQkFEbkIsU0FBUzt1QkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgSW5wdXQsIE9uSW5pdCwgVmlld0NoaWxkLCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuXG5pbXBvcnQgeyBGc0xpc3RDb21wb25lbnQsIEZzTGlzdENvbmZpZywgRnNMaXN0TW9kdWxlLCBQYWdpbmF0aW9uU3RyYXRlZ3kgfSBmcm9tICdAZmlyZXN0aXRjaC9saXN0JztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgbWFwIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7XG4gIENvbXBvbmVudERhdGEsXG4gIENvbXBvbmVudERhdGFTdGF0ZSxcbiAgTGlzdENvbmZpZyxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRTb3J0LFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgZm9ybWF0UGVyaW9kTGFiZWwgfSBmcm9tICcuLi8uLi9vcHRpb24tYnVpbGRlcic7XG5pbXBvcnQgeyBSZXBvcnREYXRlUGlwZSB9IGZyb20gJy4uLy4uL3BpcGVzL3JlcG9ydC1kYXRlLnBpcGUnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcblxuXG4vLyBBIGxpc3QgY29tcG9uZW50OiBhbiBGc0xpc3QgcmVuZGVyZWQgZnJvbSB0aGUgY29tcG9uZW50J3MgY29uZmlnLiBJdCBoYXMgbm9cbi8vIGZpbHRlciBiYXIgb2YgaXRzIG93bjogaXRzIGZpbHRlcnMgYXJlIGdyb3VwLWtleWVkIGxpa2UgZXZlcnkgb3RoZXJcbi8vIGNvbXBvbmVudCdzLCBzbyBjb21wb25lbnQtbGV2ZWwgZ3JvdXBzIHJlbmRlciBpbiB0aGUgY29tcG9uZW50IGhlYWRlciBzdHJpcFxuLy8gKFJlcG9ydENvbXBvbmVudENvbXBvbmVudCkgYW5kIHJlcG9ydC1sZXZlbCBncm91cHMgaW4gdGhlIHJlcG9ydCBiYXIsIGFuZFxuLy8gZXZlcnkgcmVxdWVzdCB0YWtlcyBpdHMgdmFsdWVzIGZyb20gdGhlIHNoYXJlZCBmaWx0ZXItc3RhdGUgc2VydmljZS5cbi8vIFBhZ2luZyBhbmQgc29ydGluZyBhcmUgcHVzaGVkIGludG8gdGhlIFNRTCB3cmFwIHNlcnZlci1zaWRlLlxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXJlcG9ydC1jb21wb25lbnQtbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NvbXBvbmVudC1saXN0LmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgRnNMaXN0TW9kdWxlLFxuICAgIFJlcG9ydERhdGVQaXBlLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb21wb25lbnRMaXN0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBwdWJsaWMgcmVwb3J0SWQ6IG51bWJlcjtcbiAgQElucHV0KCkgcHVibGljIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50O1xuXG4gIEBWaWV3Q2hpbGQoRnNMaXN0Q29tcG9uZW50KVxuICBwdWJsaWMgbGlzdENvbXBvbmVudDogRnNMaXN0Q29tcG9uZW50O1xuXG4gIHB1YmxpYyBsaXN0Q29uZmlnOiBGc0xpc3RDb25maWc7XG5cbiAgLy8gQSBwbGFpbiBsaXN0J3MgY29sdW1ucyBhcmUgYXV0aG9yZWQgYW5kIGZpeGVkIGF0IGluaXQuIEEgY3Jvc3MtdGFiJ3MgYXJlXG4gIC8vIHRoZSBwaXZvdCBkaW1lbnNpb24ncyBWQUxVRVMsIHNvIHRoZXkgYXJyaXZlIHdpdGggdGhlIHJvd3MgYW5kIGNoYW5nZVxuICAvLyB3aGVuZXZlciB0aGUgZmlsdGVycyBkbyDigJQgd2hpY2ggaXMgd2h5IHRoaXMgaXMgYSBzaWduYWwgcmF0aGVyIHRoYW4gdGhlXG4gIC8vIG9uZS1zaG90IHJlYWQgaXQgdXNlZCB0byBiZS5cbiAgcHVibGljIGNvbHVtbnMgPSBzaWduYWw8eyBjb2x1bW46IHN0cmluZzsgbGFiZWw/OiBzdHJpbmc7IGZvcm1hdD86IHN0cmluZyB9W10+KFtdKTtcblxuICAvLyBBIGNyb3NzLXRhYiBzb3J0cyBvbmx5IGJ5IGl0cyByb3cta2V5IGNvbHVtbjogZXZlcnkgb3RoZXIgaGVhZGVyIGlzIGFcbiAgLy8gcGl2b3QgdmFsdWUsIGFuZCB0aGUgc2VydmVyIG9yZGVycyB0aGUgbG9uZyByb3dzIGJlZm9yZSBwaXZvdGluZywgc28gYVxuICAvLyBjbGljayBvbiBcIk1hciAyMDI2XCIgaGFzIG5vdGhpbmcgdG8gb3JkZXIgYnkuXG4gIHB1YmxpYyBwaXZvdGVkID0gc2lnbmFsKGZhbHNlKTtcblxuICAvLyBBIGN1dCByZXN1bHQgaXMgd29yc2UgZm9yIGEgZ3JpZCB0aGFuIGZvciBhIGxpc3Q6IHRoZSBjdXQgbGFuZHMgb24gdGhlIExPTkdcbiAgLy8gcm93cyBiZWZvcmUgdGhlIHJlc2hhcGUsIHNvIGEgcGl2b3QgdmFsdWUgbGl2aW5nIG9ubHkgaW4gdGhlIHRhaWwgdmFuaXNoZXNcbiAgLy8gYXMgYSB3aG9sZSBDT0xVTU4gYW5kIHN0cmFkZGxlZCBjZWxscyBjb21lIGJhY2sgYmxhbmssIGluZGlzdGluZ3Vpc2hhYmxlXG4gIC8vIGZyb20gYSByZWFsIHplcm8uIFRoZSBwYXJlbnQncyB0cnVuY2F0aW9uIGJhbm5lciBuZXZlciBmaXJlcyBmb3IgYSBsaXN0XG4gIC8vIChpdCBvbmx5IHJlbmRlcnMgd2hhdCBfbG9hZCgpIGZldGNoZWQsIHdoaWNoIGxpc3RzIHNraXApLCBzbyB0aGUgd2FybmluZ1xuICAvLyBiZWxvbmdzIGhlcmUuXG4gIHB1YmxpYyB0cnVuY2F0ZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8vIFRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZSwgd2hpY2ggZGF0ZSBjZWxscyByZW5kZXIgaW4uIEluamVjdGVkIHJpZ2h0XG4gIC8vIGhlcmUgcmF0aGVyIHRoYW4gcmVhZCBvZmYgX2ZpbHRlclN0YXRlLCB3aGljaCBpcyBkZWNsYXJlZCBmdXJ0aGVyIGRvd24gYW5kXG4gIC8vIGlzIHN0aWxsIHVuZGVmaW5lZCB3aGlsZSB0aGlzIGluaXRpYWxpemVyIHJ1bnMuXG4gIHB1YmxpYyByZWFkb25seSB0aW1lem9uZSA9IGluamVjdChSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UpLnRpbWV6b25lO1xuXG4gIHByaXZhdGUgX3JlcG9ydERhdGEgPSBpbmplY3QoUmVwb3J0RGF0YSk7XG4gIHByaXZhdGUgX2ZpbHRlclN0YXRlID0gaW5qZWN0KFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSk7XG4gIHByaXZhdGUgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9ICh0aGlzLmNvbXBvbmVudC5jb25maWcgPz8ge30pIGFzIExpc3RDb25maWc7XG4gICAgdGhpcy5waXZvdGVkLnNldCghIWNvbmZpZy5waXZvdEJ5Py5jb2x1bW4pO1xuICAgIHRoaXMuY29sdW1ucy5zZXQoY29uZmlnLmNvbHVtbnMgPz8gW10pO1xuXG4gICAgdGhpcy5faW5pdExpc3RDb25maWcoY29uZmlnKTtcblxuICAgIC8vIEEgY2hhbmdlIHRvIGFueSBncm91cCB0aGlzIGxpc3QncyBmaWx0ZXJzIGJlbG9uZyB0byAoZnJvbSB0aGUgcmVwb3J0IGJhclxuICAgIC8vIG9yIHRoZSBjb21wb25lbnQgaGVhZGVyIHN0cmlwKSByZS1ydW5zIHRoZSBsaXN0LlxuICAgIHRoaXMuX2ZpbHRlclN0YXRlLmNoYW5nZXNGb3IodGhpcy5jb21wb25lbnQpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMubGlzdENvbXBvbmVudD8ucmVsb2FkKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdExpc3RDb25maWcoY29uZmlnOiBMaXN0Q29uZmlnKTogdm9pZCB7XG4gICAgLy8gVGhlIHZpZXdlcidzIGxhc3Qgc29ydCB3aW5zIG92ZXIgdGhlIGF1dGhvcmVkIG9uZSwgc28gYSBsaXN0IHJlY3JlYXRlZFxuICAgIC8vIGluIHRoZSBzYW1lIHNlc3Npb24gKHBhZ2Ugc3dpdGNoLCByZWxvYWQgYWZ0ZXIgYW4gZWRpdCkga2VlcHMgaXQuXG4gICAgY29uc3Qgc29ydDogUmVwb3J0U29ydCB8IHVuZGVmaW5lZCA9IHRoaXMuX2ZpbHRlclN0YXRlLmxpc3RTb3J0KHRoaXMuY29tcG9uZW50LmlkKSA/PyBjb25maWcuc29ydDtcblxuICAgIHRoaXMubGlzdENvbmZpZyA9IHtcbiAgICAgIC8vIEluc2lkZSBhIHJlcG9ydCBjb21wb25lbnQgdGhlIGxpc3QgaXMgYSBjbGVhbiBkYXRhIHBhbmUg4oCUIG5vIHN0YXR1c1xuICAgICAgLy8gYmFyLCBubyByZWxvYWQgYnV0dG9uIChmaWx0ZXIgY2hhbmdlcyBhbHJlYWR5IHJlZmV0Y2gpLlxuICAgICAgc3RhdHVzOiBmYWxzZSxcbiAgICAgIHJlbG9hZDogZmFsc2UsXG4gICAgICAvLyBGc0xpc3QgbmV2ZXIgdG91Y2hlcyB0aGUgVVJMIG9yIHBlcnNpc3RzIHNvcnQvcGFnaW5nIHN0YXRlLiBUaGUgc29ydFxuICAgICAgLy8gcmVhY2hlcyB0aGUgVVJMIHRocm91Z2ggUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIChzZXRMaXN0U29ydCksIGFuZFxuICAgICAgLy8gcGFnaW5nIHN0YXlzIG91dCBvZiBpdC5cbiAgICAgIHF1ZXJ5UGFyYW06IGZhbHNlLFxuICAgICAgcGVyc2lzdDogZmFsc2UsXG4gICAgICBzb3J0OiBzb3J0XG4gICAgICAgID8geyB2YWx1ZTogc29ydC5jb2x1bW4sIGRpcmVjdGlvbjogc29ydC5kaXJlY3Rpb24gPz8gJ2FzYycgfVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIC8vIExvYWQtbW9yZTogdGhlIGxpc3Qga2VlcHMgYSBmaXhlZCwgc2Nyb2xsYWJsZSBoZWlnaHQgYW5kIGFwcGVuZHMgdGhlXG4gICAgICAvLyBuZXh0IHBhZ2UgaW4gcGxhY2UgaW5zdGVhZCBvZiBzd2FwcGluZyBwYWdlcy4gVGhlIGJ1dHRvbiBpcyBwaW5uZWQgdG9cbiAgICAgIC8vIHRoZSBib3R0b20gb2YgdGhlIHNjcm9sbCBwYW5lIChzZWUgY29tcG9uZW50IFNDU1MpLlxuICAgICAgLy9cbiAgICAgIC8vIFVzZXMgdGhlIE9mZnNldCBzdHJhdGVneSAob2Zmc2V0ICsgbGltaXQpIHJhdGhlciB0aGFuIE1hbnk6IGluXG4gICAgICAvLyBAZmlyZXN0aXRjaC9saXN0IHRoZSBwYWdpbmF0aW9uIHRlbXBsYXRlIHJlc29sdmVzIGBoYXNNYW55U3RyYXRlZ3lgXG4gICAgICAvLyBCRUZPUkUgYGxvYWRNb3JlRW5hYmxlZGAsIGFuZCBNYW55IHJlbmRlcnMgYSBmb3J3YXJkLW9ubHkgcGFnZSBwYWdlciDigJRcbiAgICAgIC8vIHNvIE1hbnkgd291bGQgc3VwcHJlc3MgdGhlIGxvYWQtbW9yZSBidXR0b24gZW50aXJlbHkuIE9mZnNldCArIGxvYWRNb3JlXG4gICAgICAvLyBpcyB0aGUgY29tYmluYXRpb24gdGhhdCBhY3R1YWxseSByZW5kZXJzIGFuZCBhcHBlbmRzLiBgX2ZldGNoYCBhbHJlYWR5XG4gICAgICAvLyBkZXJpdmVzIGBwYWdlYCBmcm9tIGBvZmZzZXRgLCBzbyB0aGUgc2VydmVyLXNpZGUgd3JhcCBpcyB1bmFmZmVjdGVkLlxuICAgICAgcGFnaW5nOiB7XG4gICAgICAgIGxpbWl0OiBjb25maWcucGFnZVNpemUgPz8gMjUsXG4gICAgICAgIHN0cmF0ZWd5OiBQYWdpbmF0aW9uU3RyYXRlZ3kuT2Zmc2V0LFxuICAgICAgfSxcbiAgICAgIGxvYWRNb3JlOiB7XG4gICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGxhYmVsOiAnTG9hZCBtb3JlJyxcbiAgICAgICAgYnV0dG9uVHlwZTogJ3N0cm9rZWQnLFxuICAgICAgfSxcbiAgICAgIGZldGNoOiAocXVlcnk6IGFueSkgPT4gdGhpcy5fZmV0Y2gocXVlcnkpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF9mZXRjaChxdWVyeTogYW55KTogT2JzZXJ2YWJsZTx7IGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107IHBhZ2luZzogYW55IH0+IHtcbiAgICAvLyBNYW55L2xvYWQtbW9yZSBzZW5kcyBgb2Zmc2V0YCArIGBsaW1pdGAgKG5vdCBgcGFnZWApOyBkZXJpdmUgdGhlIHBhZ2Ugc29cbiAgICAvLyB0aGUgc2VydmVyLXNpZGUgd3JhcCBrZWVwcyB3b3JraW5nIHVuY2hhbmdlZC4gUGFnZSBzdHJhdGVneSBzdGlsbCBzZW5kc1xuICAgIC8vIGBwYWdlYCBkaXJlY3RseS5cbiAgICBjb25zdCBwYWdlU2l6ZSA9IHF1ZXJ5LmxpbWl0ID8/IDI1O1xuICAgIGNvbnN0IHBhZ2UgPSBxdWVyeS5wYWdlXG4gICAgICA/PyAocXVlcnkub2Zmc2V0ICE9IG51bGwgPyBNYXRoLmZsb29yKHF1ZXJ5Lm9mZnNldCAvIHBhZ2VTaXplKSArIDEgOiAxKTtcblxuICAgIGNvbnN0IHN0YXRlOiBDb21wb25lbnREYXRhU3RhdGUgPSB7XG4gICAgICBwYWdlLFxuICAgICAgcGFnZVNpemUsXG4gICAgfTtcblxuICAgIGNvbnN0IG9yZGVyID0gU3RyaW5nKHF1ZXJ5Lm9yZGVyID8/ICcnKTtcbiAgICBpZiAob3JkZXIpIHtcbiAgICAgIGNvbnN0IFtjb2x1bW4sIGRpcmVjdGlvbl0gPSBvcmRlci5zcGxpdCgnLCcpO1xuICAgICAgc3RhdGUuc29ydCA9IHsgY29sdW1uLCBkaXJlY3Rpb246IGRpcmVjdGlvbiA9PT0gJ2Rlc2MnID8gJ2Rlc2MnIDogJ2FzYycgfTtcbiAgICB9XG5cbiAgICB0aGlzLl9maWx0ZXJTdGF0ZS5zZXRMaXN0U29ydCh0aGlzLmNvbXBvbmVudC5pZCwgc3RhdGUuc29ydCA/PyBudWxsKTtcblxuICAgIC8vIE9uZSBzb3VyY2UgZm9yIGZpbHRlciB2YWx1ZXMsIHRoZSBzYW1lIG9uZSBjaGFydHMsIEtQSXMgYW5kIHRoZSBleHBvcnRzXG4gICAgLy8gcmVhZCwgc28gdGhlIGxpc3QgaXMgZmlsdGVyZWQgZXhhY3RseSBhcyBpdHMgaGVhZGVyIHN0cmlwIHNob3dzLlxuICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLl9maWx0ZXJTdGF0ZS5yZXNvbHZlRm9yQ29tcG9uZW50KHRoaXMuY29tcG9uZW50KTtcblxuICAgIHJldHVybiB0aGlzLl9yZXBvcnREYXRhXG4gICAgICAuY29tcG9uZW50RGF0YSh0aGlzLnJlcG9ydElkLCB0aGlzLmNvbXBvbmVudC5pZCwgZmlsdGVycywgc3RhdGUpXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChkYXRhOiBDb21wb25lbnREYXRhKSA9PiB7XG4gICAgICAgICAgLy8gQSBjcm9zcy10YWIncyBoZWFkZXJzIGNvbWUgYmFjayB3aXRoIHRoZSByb3dzOiB0aGUgcm93LWtleSBjb2x1bW5cbiAgICAgICAgICAvLyBmaXJzdCwgdGhlbiBvbmUgcGVyIHBpdm90IHZhbHVlLiBSZS1yZWFkIHRoZW0gb24gZXZlcnkgZmV0Y2gsIHNpbmNlXG4gICAgICAgICAgLy8gYSBmaWx0ZXIgY2hhbmdlIGNhbiBhZGQgb3IgcmVtb3ZlIGEgY29sdW1uLlxuICAgICAgICAgIGlmICh0aGlzLnBpdm90ZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5zLnNldCh0aGlzLl9waXZvdENvbHVtbnMoZGF0YSkpO1xuICAgICAgICAgICAgdGhpcy50cnVuY2F0ZWQuc2V0KCEhZGF0YS50cnVuY2F0ZWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkYXRhOiBkYXRhLnJvd3MgPz8gW10sXG4gICAgICAgICAgICBwYWdpbmc6IHtcbiAgICAgICAgICAgICAgbGltaXQ6IGRhdGEucGFnaW5nPy5wYWdlU2l6ZSA/PyBzdGF0ZS5wYWdlU2l6ZSxcbiAgICAgICAgICAgICAgcmVjb3JkczogZGF0YS5wYWdpbmc/LnRvdGFsID8/IChkYXRhLnJvd3M/Lmxlbmd0aCA/PyAwKSxcbiAgICAgICAgICAgICAgcGFnZTogZGF0YS5wYWdpbmc/LnBhZ2UgPz8gc3RhdGUucGFnZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgLy8gQSBjcm9zcy10YWIncyBjb2x1bW5zLCBidWlsdCBmcm9tIHRoZSB3aXJlLiBUaGUgZmlyc3QgaXMgdGhlIHJvdyBrZXkgYW5kXG4gIC8vIGtlZXBzIGl0cyBhdXRob3JlZCBsYWJlbDsgdGhlIHJlc3QgYXJlIHBpdm90IFZBTFVFUyB1c2VkIGFzIGhlYWRpbmdzLiBXaGVuXG4gIC8vIHRoZSBwaXZvdCBheGlzIGlzIGEgdGltZSBkaW1lbnNpb24gdGhlIHNlcnZlciBzZW5kcyB0aGUgZ3JhaW4gaXQgYnVja2V0ZWRcbiAgLy8gYXQsIHNvIGEgcGVyaW9kLXN0YXJ0IGxpa2UgXCIyMDI2LTAxLTAxXCIgaXMgc2hvd24gYXMgXCJKYW4gMjAyNlwiIOKAlCB0aGUgc2FtZVxuICAvLyBmb3JtYXR0ZXIgdGhlIGNoYXJ0J3MgeC1heGlzIHVzZXMsIHNvIGEgZ3JpZCBhbmQgYSBjaGFydCBvZiB0aGUgc2FtZSBxdWVyeVxuICAvLyBsYWJlbCB0aGVpciBwZXJpb2RzIGlkZW50aWNhbGx5LlxuICBwcml2YXRlIF9waXZvdENvbHVtbnMoZGF0YTogQ29tcG9uZW50RGF0YSk6IHsgY29sdW1uOiBzdHJpbmc7IGxhYmVsPzogc3RyaW5nOyBmb3JtYXQ/OiBzdHJpbmcgfVtdIHtcbiAgICBjb25zdCBjb25maWcgPSAodGhpcy5jb21wb25lbnQuY29uZmlnID8/IHt9KSBhcyBMaXN0Q29uZmlnO1xuICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gZGF0YS5ncmFudWxhcml0eTtcbiAgICBjb25zdCBtdWx0aVllYXIgPSB0aGlzLl9zcGFuc011bHRpcGxlWWVhcnMoZGF0YS5jb2x1bW5zID8/IFtdKTtcblxuICAgIHJldHVybiAoZGF0YS5jb2x1bW5zID8/IFtdKS5tYXAoKGNvbHVtbiwgaW5kZXgpID0+IHtcbiAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICByZXR1cm4geyBjb2x1bW4sIGxhYmVsOiBjb25maWcucm93Qnk/LmxhYmVsIHx8IGNvbHVtbiB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2x1bW4sXG4gICAgICAgIGxhYmVsOiBncmFudWxhcml0eSA/IGZvcm1hdFBlcmlvZExhYmVsKGNvbHVtbiwgZ3JhbnVsYXJpdHksIG11bHRpWWVhcikgOiBjb2x1bW4sXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgLy8gV2hldGhlciB0aGUgcGVyaW9kIGNvbHVtbnMgY3Jvc3MgYSB5ZWFyIGJvdW5kYXJ5LCB3aGljaCBkZWNpZGVzIGlmIHRoZVxuICAvLyBmb3JtYXR0ZXIgYXBwZW5kcyB0aGUgeWVhciB0byBlYWNoIGhlYWRpbmcuXG4gIHByaXZhdGUgX3NwYW5zTXVsdGlwbGVZZWFycyhjb2x1bW5zOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHllYXJzID0gbmV3IFNldChcbiAgICAgIGNvbHVtbnNcbiAgICAgICAgLm1hcCgoY29sdW1uKSA9PiAvXihcXGR7NH0pLVxcZHsyfS1cXGR7Mn0vLmV4ZWMoY29sdW1uKSlcbiAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgICAubWFwKChtYXRjaCkgPT4gbWF0Y2hbMV0pLFxuICAgICk7XG5cbiAgICByZXR1cm4geWVhcnMuc2l6ZSA+IDE7XG4gIH1cbn1cbiIsIkBpZiAodHJ1bmNhdGVkKCkpIHtcbiAgPGRpdiBjbGFzcz1cInBpdm90LXRydW5jYXRlZFwiPlxuICAgIFRoaXMgZ3JpZCB3YXMgYnVpbHQgZnJvbSBhIHBhcnRpYWwgcmVzdWx0LCBzbyBzb21lIGNvbHVtbnMgb3IgdmFsdWVzIG1heSBiZSBtaXNzaW5nLiBOYXJyb3cgaXQgd2l0aCBhIGZpbHRlci5cbiAgPC9kaXY+XG59XG5cbjxmcy1saXN0IFtjb25maWddPVwibGlzdENvbmZpZ1wiPlxuICBAZm9yIChjb2x1bW4gb2YgY29sdW1ucygpOyB0cmFjayBjb2x1bW4uY29sdW1uKSB7XG4gICAgPGZzLWxpc3QtY29sdW1uXG4gICAgICBbbmFtZV09XCJjb2x1bW4uY29sdW1uXCJcbiAgICAgIFt0aXRsZV09XCJjb2x1bW4ubGFiZWwgfHwgY29sdW1uLmNvbHVtblwiXG4gICAgICBbc29ydGFibGVdPVwiIXBpdm90ZWQoKSB8fCAkZmlyc3RcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICBmcy1saXN0LWNlbGxcbiAgICAgICAgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgICBAaWYgKGNvbHVtbi5mb3JtYXQgPT09ICdkYXRlJykge1xuICAgICAgICAgIHt7IHJvd1tjb2x1bW4uY29sdW1uXSB8IGZzUmVwb3J0RGF0ZTogdGltZXpvbmUoKSB9fVxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICB7eyByb3dbY29sdW1uLmNvbHVtbl0gfX1cbiAgICAgICAgfVxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2ZzLWxpc3QtY29sdW1uPlxuICB9XG48L2ZzLWxpc3Q+XG4iXX0=