@firestitch/report 18.6.1 → 18.8.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 (97) hide show
  1. package/app/reports/components/component-chart/component-chart.component.d.ts +6 -7
  2. package/app/reports/components/component-kpi/component-kpi.component.d.ts +17 -9
  3. package/app/reports/components/component-kpi/components/sparkline/sparkline.component.d.ts +8 -0
  4. package/app/reports/components/component-list/component-list.component.d.ts +39 -10
  5. package/app/reports/components/component-note/component-note.component.d.ts +12 -0
  6. package/app/reports/components/report-canvas/report-canvas.component.d.ts +0 -10
  7. package/app/reports/components/report-component/report-component.component.d.ts +5 -12
  8. package/app/reports/data/report.data.d.ts +2 -3
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +34 -2
  10. package/app/reports/dialogs/list-columns/list-columns.component.d.ts +23 -0
  11. package/app/reports/dialogs/report-settings/report-locale-patch.d.ts +5 -0
  12. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +20 -2
  13. package/app/reports/enums/report-change-polarity.enum.d.ts +5 -0
  14. package/app/reports/enums/report-chart-color.enum.d.ts +12 -0
  15. package/app/reports/enums/report-chart-data-labels.enum.d.ts +6 -0
  16. package/app/reports/enums/report-chart-date-label.enum.d.ts +5 -0
  17. package/app/reports/enums/report-chart-line-style.enum.d.ts +5 -0
  18. package/app/reports/enums/report-chart-mark-stat.enum.d.ts +6 -0
  19. package/app/reports/enums/report-kpi-trend.enum.d.ts +5 -0
  20. package/app/reports/enums/report-list-column-format.enum.d.ts +6 -0
  21. package/app/reports/enums/report-number-units.enum.d.ts +6 -0
  22. package/app/reports/enums/report-value-format.enum.d.ts +5 -0
  23. package/app/reports/export/offscreen-chart.d.ts +2 -2
  24. package/app/reports/export/report-export-collector.service.d.ts +37 -8
  25. package/app/reports/export/report-pdf.service.d.ts +6 -0
  26. package/app/reports/export/report-pptx.service.d.ts +24 -0
  27. package/app/reports/format.d.ts +64 -3
  28. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +2 -0
  29. package/app/reports/interfaces/report.interface.d.ts +205 -14
  30. package/app/reports/kpi-card.d.ts +48 -0
  31. package/app/reports/layout.d.ts +0 -9
  32. package/app/reports/list-config.d.ts +16 -0
  33. package/app/reports/option-builder.d.ts +76 -9
  34. package/app/reports/output-notes.d.ts +14 -0
  35. package/app/reports/pipes/report-date.pipe.d.ts +2 -1
  36. package/app/reports/pipes/report-number.pipe.d.ts +8 -0
  37. package/app/reports/pipes/report-output.pipe.d.ts +10 -0
  38. package/app/reports/report-filter-items.d.ts +5 -2
  39. package/app/reports/report-url-state.d.ts +4 -0
  40. package/app/reports/services/report-filter-state.service.d.ts +27 -2
  41. package/app/reports/theme/palette.d.ts +6 -0
  42. package/app/reports/theme/typography.d.ts +2 -0
  43. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +23 -20
  44. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +56 -29
  45. package/esm2022/app/reports/components/component-kpi/components/sparkline/sparkline.component.mjs +19 -0
  46. package/esm2022/app/reports/components/component-list/component-list.component.mjs +218 -32
  47. package/esm2022/app/reports/components/component-note/component-note.component.mjs +30 -0
  48. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +7 -61
  49. package/esm2022/app/reports/components/report-component/report-component.component.mjs +99 -100
  50. package/esm2022/app/reports/data/report.data.mjs +20 -7
  51. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +133 -13
  52. package/esm2022/app/reports/dialogs/list-columns/list-columns.component.mjs +56 -0
  53. package/esm2022/app/reports/dialogs/report-settings/report-locale-patch.mjs +13 -0
  54. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +138 -20
  55. package/esm2022/app/reports/enums/report-change-polarity.enum.mjs +11 -0
  56. package/esm2022/app/reports/enums/report-chart-color.enum.mjs +19 -0
  57. package/esm2022/app/reports/enums/report-chart-data-labels.enum.mjs +13 -0
  58. package/esm2022/app/reports/enums/report-chart-date-label.enum.mjs +13 -0
  59. package/esm2022/app/reports/enums/report-chart-line-style.enum.mjs +12 -0
  60. package/esm2022/app/reports/enums/report-chart-mark-stat.enum.mjs +12 -0
  61. package/esm2022/app/reports/enums/report-kpi-trend.enum.mjs +10 -0
  62. package/esm2022/app/reports/enums/report-list-column-format.enum.mjs +14 -0
  63. package/esm2022/app/reports/enums/report-number-units.enum.mjs +14 -0
  64. package/esm2022/app/reports/enums/report-value-format.enum.mjs +13 -0
  65. package/esm2022/app/reports/export/offscreen-chart.mjs +5 -4
  66. package/esm2022/app/reports/export/report-export-collector.service.mjs +186 -40
  67. package/esm2022/app/reports/export/report-pdf.service.mjs +332 -67
  68. package/esm2022/app/reports/export/report-pptx.service.mjs +765 -106
  69. package/esm2022/app/reports/format.mjs +917 -57
  70. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  71. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  72. package/esm2022/app/reports/kpi-card.mjs +174 -0
  73. package/esm2022/app/reports/layout.mjs +1 -46
  74. package/esm2022/app/reports/list-config.mjs +106 -0
  75. package/esm2022/app/reports/option-builder.mjs +1457 -117
  76. package/esm2022/app/reports/output-notes.mjs +158 -0
  77. package/esm2022/app/reports/pipes/report-date.pipe.mjs +7 -6
  78. package/esm2022/app/reports/pipes/report-number.pipe.mjs +25 -0
  79. package/esm2022/app/reports/pipes/report-output.pipe.mjs +28 -0
  80. package/esm2022/app/reports/report-filter-items.mjs +28 -3
  81. package/esm2022/app/reports/report-url-state.mjs +56 -15
  82. package/esm2022/app/reports/services/report-filter-state.service.mjs +274 -22
  83. package/esm2022/app/reports/theme/echarts.mjs +8 -2
  84. package/esm2022/app/reports/theme/palette.mjs +35 -1
  85. package/esm2022/app/reports/theme/typography.mjs +8 -1
  86. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +2 -2
  87. package/esm2022/app/reports/views/report/report.component.mjs +3 -4
  88. package/esm2022/public_api.mjs +10 -1
  89. package/fesm2022/{firestitch-report-echarts-Djtmaxj1.mjs → firestitch-report-echarts-qCBE3LqM.mjs} +9 -3
  90. package/fesm2022/firestitch-report-echarts-qCBE3LqM.mjs.map +1 -0
  91. package/fesm2022/{firestitch-report-firestitch-report-D3zseBZc.mjs → firestitch-report-firestitch-report-DbsWbE-j.mjs} +5523 -875
  92. package/fesm2022/firestitch-report-firestitch-report-DbsWbE-j.mjs.map +1 -0
  93. package/fesm2022/firestitch-report.mjs +1 -1
  94. package/package.json +1 -1
  95. package/public_api.d.ts +9 -0
  96. package/fesm2022/firestitch-report-echarts-Djtmaxj1.mjs.map +0 -1
  97. package/fesm2022/firestitch-report-firestitch-report-D3zseBZc.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { ChangeDetectionStrategy, Component, DestroyRef, inject, signal } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, DestroyRef, computed, inject, signal } from '@angular/core';
2
2
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
3
  import { FormsModule } from '@angular/forms';
4
4
  import { MatButton } from '@angular/material/button';
@@ -14,13 +14,17 @@ import { FsFormModule } from '@firestitch/form';
14
14
  import { FsMaskModule } from '@firestitch/mask';
15
15
  import { FsMessage, FsMessageModule } from '@firestitch/message';
16
16
  import { FsPrompt } from '@firestitch/prompt';
17
+ import { FsSkeletonModule } from '@firestitch/skeleton';
17
18
  import { FsTabsModule } from '@firestitch/tabs';
18
19
  import { TimezoneSelectComponent } from '../../components/timezone-select/timezone-select.component';
19
- import { forkJoin } from 'rxjs';
20
- import { switchMap, tap } from 'rxjs/operators';
20
+ import { forkJoin, of } from 'rxjs';
21
+ import { catchError, finalize, switchMap, tap } from 'rxjs/operators';
21
22
  import { ReportData } from '../../data/report.data';
23
+ import { ReportValueFormat } from '../../enums/report-value-format.enum';
24
+ import { DAY_SHORT, REPORT_FALLBACK_CURRENCY, currencyName, formatLocalDate, formatNumber, localeName, resolveReportCurrency, resolveReportLocale, } from '../../format';
22
25
  import { DEFAULT_HEADING_SIZE, HEADER_FOOTER_MAX, PAGE_DIMENSION_MAX, PAGE_DIMENSION_MIN } from '../../layout';
23
26
  import { dateFromBound, dateToBound, loadGroupOptions, matchOptions, relativeLabel, resolveOptionValues, } from '../../report-filter-items';
27
+ import { reportLocalePatch } from './report-locale-patch';
24
28
  import * as i0 from "@angular/core";
25
29
  import * as i1 from "@angular/forms";
26
30
  import * as i2 from "@firestitch/form";
@@ -28,12 +32,24 @@ import * as i3 from "@firestitch/mask";
28
32
  import * as i4 from "@firestitch/dialog";
29
33
  import * as i5 from "@firestitch/message";
30
34
  import * as i6 from "@firestitch/tabs";
31
- import * as i7 from "@firestitch/datepicker";
32
- import * as i8 from "@firestitch/autocomplete-chips";
33
- import * as i9 from "@angular/material/tabs";
35
+ import * as i7 from "@firestitch/skeleton";
36
+ import * as i8 from "@firestitch/datepicker";
37
+ import * as i9 from "@firestitch/autocomplete-chips";
38
+ import * as i10 from "@angular/material/tabs";
39
+ // The day the Locale hint writes, a fixed calendar day so the example never
40
+ // changes under the operator.
41
+ const EXAMPLE_DAY = new Date(2026, 0, 5);
42
+ const EXAMPLE_AMOUNT = 1234.5;
43
+ // 'Canadian French (fr-CA)', 'Canadian Dollar (CAD)': English names whatever
44
+ // the report's locale, with the code that is stored.
45
+ function localeLabel(tag) {
46
+ return `${localeName(tag)} (${tag})`;
47
+ }
48
+ function currencyLabel(code) {
49
+ return `${currencyName(code)} (${code})`;
50
+ }
34
51
  // Report settings, in three tabs:
35
- // Settings — name + page setup (size in inches, header/footer band depths,
36
- // layout mode).
52
+ // Settings — name + page setup (size in inches, header/footer band depths).
37
53
  // Styles — the report's typographic styles (sizes in POINTS, 1:1 with
38
54
  // PDF/PowerPoint); the Heading size to start.
39
55
  // Filters — the report-level filters and their DEFAULT values. A default
@@ -60,13 +76,66 @@ export class ReportSettingsComponent {
60
76
  headerHeight = 0;
61
77
  footerHeight = 0;
62
78
  headerFooterMax = HEADER_FOOTER_MAX;
63
- layout = 'freeform';
64
79
  // Seeded with the zone the report actually uses: its own stored zone, else
65
80
  // the application default the server resolved (effectiveTimezone). Save sends
66
81
  // it only when it differs from that effective zone, so opening and saving a
67
82
  // report that follows the default never pins it to a zone.
68
83
  timezone = '';
69
84
  headingSize = DEFAULT_HEADING_SIZE;
85
+ // The locales and currencies the server offers. null until loaded, and
86
+ // never loaded from a server too old to send effectiveLocale: there the
87
+ // selects stay hidden and the report reads en-US/USD.
88
+ locales = signal(null);
89
+ // The report's own locale and currency, '' when it follows the default. Save
90
+ // sends each only when it differs from the stored value.
91
+ locale = signal('');
92
+ currency = signal('');
93
+ // The whole form waits behind one skeleton until the filter rows are built
94
+ // and the locale request has settled, so the Settings tab never shows
95
+ // without its Locale and Currency selects. A failed locale request settles
96
+ // too: the two selects stay hidden (locales() is still null) and every other
97
+ // setting stays editable.
98
+ ready = computed(() => this._filtersReady() && (!this._serverHasLocale || this._localesSettled()));
99
+ // An explicit Default ('') naming the locale it stands for, then each offered
100
+ // locale. A stored locale the server no longer offers is listed first, so
101
+ // the select still shows what the report holds.
102
+ localeOptions = computed(() => {
103
+ const locales = this.locales();
104
+ if (!locales) {
105
+ return [];
106
+ }
107
+ const offered = locales.options.map((option) => option.locale);
108
+ return [
109
+ ...this._storedOption(this._data.report.locale, offered, localeLabel),
110
+ { value: '', label: `Default — ${localeName(locales.defaultLocale)}` },
111
+ ...offered.map((tag) => ({ value: tag, label: localeLabel(tag) })),
112
+ ];
113
+ });
114
+ // An explicit Default ('') naming the currency the selected locale uses when
115
+ // the report names none, then every currency. A stored code the server no
116
+ // longer offers is listed first.
117
+ currencyOptions = computed(() => {
118
+ const locales = this.locales();
119
+ if (!locales) {
120
+ return [];
121
+ }
122
+ return [
123
+ ...this._storedOption(this._data.report.currency, locales.currencies, currencyLabel),
124
+ { value: '', label: `Default — ${currencyLabel(this._defaultCurrency())}` },
125
+ ...locales.currencies.map((code) => ({ value: code, label: currencyLabel(code) })),
126
+ ];
127
+ });
128
+ // How the report will write an amount and a day once saved: the selected
129
+ // locale and currency, or the defaults they fall back to, e.g.
130
+ // '1 234,50 $ · 5 janv. 2026' in fr-CA.
131
+ formatExample = computed(() => {
132
+ const locale = resolveReportLocale(this._appliedLocale());
133
+ const currency = resolveReportCurrency(this._appliedCurrency());
134
+ return [
135
+ formatNumber(EXAMPLE_AMOUNT, { format: ReportValueFormat.Currency, precision: 2 }, { locale, currency, ratioPercent: true }),
136
+ formatLocalDate(EXAMPLE_DAY, locale, DAY_SHORT),
137
+ ].join(' · ');
138
+ });
70
139
  // The report-level filters and their editable default values (Filters tab).
71
140
  filterRows = signal([]);
72
141
  relativeLabel = relativeLabel;
@@ -76,6 +145,36 @@ export class ReportSettingsComponent {
76
145
  _message = inject(FsMessage);
77
146
  _prompt = inject(FsPrompt);
78
147
  _destroyRef = inject(DestroyRef);
148
+ // Only a server that resolves a report's locale offers the locale list.
149
+ _serverHasLocale = this._data.report.effectiveLocale !== undefined;
150
+ // True once the locale request has answered, with the list or an error.
151
+ _localesSettled = signal(false);
152
+ // True once the filter rows are published (see _buildFilterRows).
153
+ _filtersReady = signal(false);
154
+ // The locale the report would be written in: the selected one when the
155
+ // server offers it, else the default (a stored locale it no longer offers
156
+ // falls back to the default, as it does on the server).
157
+ _appliedLocale = computed(() => {
158
+ const locales = this.locales();
159
+ const locale = this.locale();
160
+ return locales?.options.some((option) => option.locale === locale)
161
+ ? locale
162
+ : locales?.defaultLocale ?? '';
163
+ });
164
+ // The currency a report in the applied locale uses when it names none.
165
+ _defaultCurrency = computed(() => {
166
+ const locale = this._appliedLocale();
167
+ return this.locales()?.options.find((option) => option.locale === locale)?.defaultCurrency
168
+ ?? REPORT_FALLBACK_CURRENCY;
169
+ });
170
+ // The currency the report would label money in: the selected one when the
171
+ // server offers it, else the default.
172
+ _appliedCurrency = computed(() => {
173
+ const currency = this.currency();
174
+ return this.locales()?.currencies.includes(currency)
175
+ ? currency
176
+ : this._defaultCurrency();
177
+ });
79
178
  ngOnInit() {
80
179
  const report = this._data.report;
81
180
  this.name = report.name;
@@ -83,10 +182,16 @@ export class ReportSettingsComponent {
83
182
  this.pageHeight = report.pageHeight;
84
183
  this.headerHeight = report.config?.headerFooter?.headerHeight ?? 0;
85
184
  this.footerHeight = report.config?.headerFooter?.footerHeight ?? 0;
86
- this.layout = report.layout ?? 'freeform';
87
185
  this.timezone = report.timezone ?? report.effectiveTimezone ?? '';
88
186
  this.headingSize = report.config?.styles?.heading?.size ?? DEFAULT_HEADING_SIZE;
187
+ this.locale.set(report.locale ?? '');
188
+ this.currency.set(report.currency ?? '');
89
189
  this._buildFilterRows(report);
190
+ if (this._serverHasLocale) {
191
+ this._reportData.locales()
192
+ .pipe(tap((locales) => this.locales.set(locales)), catchError(() => of(null)), finalize(() => this._localesSettled.set(true)), takeUntilDestroyed(this._destroyRef))
193
+ .subscribe();
194
+ }
90
195
  }
91
196
  // Confirm and delete here, while the dialog is still open, then close with
92
197
  // a `deleted` result. The page reacts to the result; it no longer owns the
@@ -111,8 +216,8 @@ export class ReportSettingsComponent {
111
216
  name: this.name,
112
217
  pageWidth: this._pageDimension(this.pageWidth),
113
218
  pageHeight: this._pageDimension(this.pageHeight),
114
- layout: this.layout,
115
219
  ...this._timezoneSetting(),
220
+ ...reportLocalePatch(this._data.report, this.locale(), this.currency()),
116
221
  styles: { heading: { size: this.headingSize } },
117
222
  headerFooter: {
118
223
  headerHeight: this._pageDimension(this.headerHeight) || 0,
@@ -155,6 +260,12 @@ export class ReportSettingsComponent {
155
260
  ? { timezone: this.timezone }
156
261
  : {};
157
262
  }
263
+ // The stored value as its own option when the server no longer offers it, so
264
+ // the select names it instead of showing blank. Left as it is, it is never
265
+ // sent (see reportLocalePatch), and the report reads the default meanwhile.
266
+ _storedOption(stored, offered, label) {
267
+ return stored && !offered.includes(stored) ? [{ value: stored, label: label(stored) }] : [];
268
+ }
158
269
  // Build one editable row per report-level filter group (level report or both),
159
270
  // in bar order, seeding each draft from the group's stored default.
160
271
  _buildFilterRows(report) {
@@ -187,18 +298,24 @@ export class ReportSettingsComponent {
187
298
  // Nothing to name — publish immediately rather than waiting on a request
188
299
  // no row needs.
189
300
  if (!seeded.length) {
190
- this.filterRows.set(rows);
301
+ this._publishFilterRows(rows);
191
302
  return;
192
303
  }
193
304
  // A stored select default holds ids, so its chips can only be named once the
194
305
  // option list is in. Resolve every seeded row first and publish the rows in
195
- // one go, so the tab never renders a chip showing a raw id.
306
+ // one go, so the tab never renders a chip showing a raw id. When an option
307
+ // list fails to load, the rows publish unresolved: each chip names its id,
308
+ // and an untouched row still saves the stored default unchanged.
196
309
  forkJoin(seeded.map((entry) => resolveOptionValues(entry.options$, entry.values)))
197
- .pipe(takeUntilDestroyed(this._destroyRef))
198
- .subscribe((resolved) => {
310
+ .pipe(catchError(() => of(seeded.map((entry) => entry.values.map((value) => ({ name: String(value), value }))))), tap((resolved) => {
199
311
  resolved.forEach((values, index) => seeded[index].row.values = values);
200
- this.filterRows.set(rows);
201
- });
312
+ this._publishFilterRows(rows);
313
+ }), takeUntilDestroyed(this._destroyRef))
314
+ .subscribe();
315
+ }
316
+ _publishFilterRows(rows) {
317
+ this.filterRows.set(rows);
318
+ this._filtersReady.set(true);
202
319
  }
203
320
  // The draft default normalized to the wire shape for this row's type, or null
204
321
  // when empty (which clears the stored default). A date range is the picked
@@ -256,7 +373,7 @@ export class ReportSettingsComponent {
256
373
  return Object.keys(normalized).length ? normalized : null;
257
374
  }
258
375
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
259
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ReportSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n Report Settings\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"name\"\n name=\"name\"\n [fsFormRequired]=\"true\">\n </mat-form-field>\n <!--\n The page, typed in inches. Orientation is not asked for because it\n is not an independent choice - a page wider than it is tall IS\n landscape - so the two numbers say everything there is to say.\n -->\n <div class=\"fs-row.gap-sm.align-start\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Width\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageWidth\"\n name=\"pageWidth\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageHeight\"\n name=\"pageHeight\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n </div>\n <!--\n How deep the header and footer bands are. Their content is edited\n on the canvas (Edit layout \u2192 Header & footer); these reserve the\n space for it, and 0 means no band.\n -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Header height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"headerHeight\"\n name=\"headerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Footer height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"footerHeight\"\n name=\"footerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Layout\n </mat-label>\n <mat-select\n [(ngModel)]=\"layout\"\n name=\"layout\">\n <mat-option value=\"freeform\">\n Freeform \u2014 position components anywhere on the page\n </mat-option>\n <mat-option value=\"flow\">\n Flow \u2014 components flow into rows by width %\n </mat-option>\n </mat-select>\n <mat-hint>\n Freeform is like PowerPoint; Flow is like a responsive dashboard.\n </mat-hint>\n </mat-form-field>\n <fs-ai-report-timezone-select [(timezone)]=\"timezone\"></fs-ai-report-timezone-select>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Styles\"\n name=\"styles\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Heading Size\n </mat-label>\n <input\n matInput\n type=\"number\"\n step=\"1\"\n min=\"6\"\n max=\"96\"\n [(ngModel)]=\"headingSize\"\n name=\"headingSize\"\n [fsFormMin]=\"6\"\n [fsFormMax]=\"96\">\n <span matTextSuffix>\n pt\n </span>\n <mat-hint>\n Applies to component titles. Points map 1:1 to PDF and PowerPoint.\n </mat-hint>\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"fs-column tab-body\">\n @if (filterRows().length) {\n @for (row of filterRows(); track row.group.id) {\n @switch (row.group.type) {\n @case ('dateRange') {\n <div class=\"fs-row.gap-sm.align-center fs-flex\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default From {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.start\"\n [name]=\"'start' + row.group.id\">\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default To {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n </div>\n <!-- A stored rolling preset cannot be authored here, only\n kept, replaced by picking dates, or cleared. type=\"button\"\n keeps Clear from submitting the form. -->\n @if (row.relative && !row.start && !row.end) {\n <div class=\"fs-row.gap-sm.align-center\">\n <mat-hint class=\"fs-flex\">\n Rolling default: {{ relativeLabel(row.relative) }}. Pick dates to replace it.\n </mat-hint>\n <button\n mat-button\n type=\"button\"\n (click)=\"clearRelative(row)\">\n Clear\n </button>\n </div>\n }\n }\n @case ('select') {\n <fs-autocomplete-chips\n class=\"fs-flex\"\n [label]=\"'Default ' + row.label\"\n [fetch]=\"row.fetch\"\n [(ngModel)]=\"row.values\"\n [name]=\"'values' + row.group.id\"\n [multiple]=\"true\"\n [fetchOnFocus]=\"true\">\n <ng-template\n fsAutocompleteChipsTemplate\n let-object=\"object\">\n {{ object.name }}\n </ng-template>\n </fs-autocomplete-chips>\n }\n @default {\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default {{ row.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"row.value\"\n [name]=\"'value' + row.group.id\">\n </mat-form-field>\n }\n }\n }\n } @else {\n <fs-message-info>\n This report has no report-level filters yet. Add a filter to a\n component (its settings \u2192 Filters) and show it in the report bar,\n then set its default here.\n </fs-message-info>\n }\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <fs-form-dialog-actions>\n <button\n type=\"button\"\n mat-button\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i2.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "directive", type: i2.FsFormMinDirective, selector: "[fsFormMin]", inputs: ["fsFormMin", "fsFormMinMessage"] }, { kind: "directive", type: i2.FsFormMaxDirective, selector: "[fsFormMax]", inputs: ["fsFormMax", "fsFormMaxMessage"] }, { kind: "component", type: i2.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i2.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "directive", type: i2.FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }, { kind: "ngmodule", type: FsMaskModule }, { kind: "directive", type: i3.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsMessageModule }, { kind: "component", type: i5.FsMessageInfoComponent, selector: "fs-message-info" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i6.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i6.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i7.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes", "width"], outputs: ["change"] }, { kind: "ngmodule", type: FsAutocompleteChipsModule }, { kind: "component", type: i8.FsAutocompleteChipsComponent, selector: "fs-autocomplete-chips", inputs: ["fetch", "appearance", "floatLabel", "readonly", "size", "label", "placeholder", "chipImage", "chipBackground", "chipColor", "chipIcon", "chipIconColor", "chipClass", "chipPadding", "shape", "hint", "allowText", "allowObject", "delay", "minPanelWidth", "maxPanelHeight", "validateText", "removable", "allowClear", "color", "background", "orderable", "padless", "initOnClick", "fetchOnFocus", "multiple", "multipleAdd", "confirm", "disabled", "groupBy", "panelWidth", "panelClass", "compareWith"], outputs: ["selected", "removed", "reordered", "clear", "panelOpened", "panelClosed"] }, { kind: "directive", type: i8.FsAutocompleteObjectDirective, selector: "[fsAutocompleteObject],[fsAutocompleteChipsTemplate]" }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i9.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i9.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: TimezoneSelectComponent, selector: "fs-ai-report-timezone-select", inputs: ["placeholder", "required", "disabled", "timezone"], outputs: ["timezoneChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
376
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ReportSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n Report Settings\n </h1>\n <mat-dialog-content>\n <!-- One skeleton over the whole body until the locale list is in. -->\n <ng-container *fsSkeletonForm=\"ready() || null\">\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"name\"\n name=\"name\"\n [fsFormRequired]=\"true\">\n </mat-form-field>\n <!--\n The page, typed in inches. Orientation is not asked for because it\n is not an independent choice - a page wider than it is tall IS\n landscape - so the two numbers say everything there is to say.\n -->\n <div class=\"fs-row.gap-sm.align-start\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Width\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageWidth\"\n name=\"pageWidth\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageHeight\"\n name=\"pageHeight\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n </div>\n <!--\n How deep the header and footer bands are. Their content is edited\n on the canvas (Edit layout \u2192 Header & footer); these reserve the\n space for it, and 0 means no band.\n -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Header height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"headerHeight\"\n name=\"headerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Footer height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"footerHeight\"\n name=\"footerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <fs-ai-report-timezone-select [(timezone)]=\"timezone\"></fs-ai-report-timezone-select>\n <!--\n How numbers and dates are written (formatting only: no text is\n translated) and which currency money is labeled in. Hidden on a\n server too old to resolve a report's locale.\n -->\n @if (locales()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Locale\n </mat-label>\n <mat-select\n [ngModel]=\"locale()\"\n (ngModelChange)=\"locale.set($event)\"\n name=\"locale\">\n @for (option of localeOptions(); track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n {{ formatExample() }}\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Currency\n </mat-label>\n <mat-select\n [ngModel]=\"currency()\"\n (ngModelChange)=\"currency.set($event)\"\n name=\"currency\">\n @for (option of currencyOptions(); track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Names the currency amounts are in; it does not convert them.\n </mat-hint>\n </mat-form-field>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"Styles\"\n name=\"styles\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Heading Size\n </mat-label>\n <input\n matInput\n type=\"number\"\n step=\"1\"\n min=\"6\"\n max=\"96\"\n [(ngModel)]=\"headingSize\"\n name=\"headingSize\"\n [fsFormMin]=\"6\"\n [fsFormMax]=\"96\">\n <span matTextSuffix>\n pt\n </span>\n <mat-hint>\n Applies to component titles. Points map 1:1 to PDF and PowerPoint.\n </mat-hint>\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"fs-column tab-body\">\n @if (filterRows().length) {\n @for (row of filterRows(); track row.group.id) {\n @switch (row.group.type) {\n @case ('dateRange') {\n <div class=\"fs-row.gap-sm.align-center fs-flex\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default From {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.start\"\n [name]=\"'start' + row.group.id\">\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default To {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n </div>\n <!-- A stored rolling preset cannot be authored here, only\n kept, replaced by picking dates, or cleared. type=\"button\"\n keeps Clear from submitting the form. -->\n @if (row.relative && !row.start && !row.end) {\n <div class=\"fs-row.gap-sm.align-center\">\n <mat-hint class=\"fs-flex\">\n Rolling default: {{ relativeLabel(row.relative) }}. Pick dates to replace it.\n </mat-hint>\n <button\n mat-button\n type=\"button\"\n (click)=\"clearRelative(row)\">\n Clear\n </button>\n </div>\n }\n }\n @case ('select') {\n <fs-autocomplete-chips\n class=\"fs-flex\"\n [label]=\"'Default ' + row.label\"\n [fetch]=\"row.fetch\"\n [(ngModel)]=\"row.values\"\n [name]=\"'values' + row.group.id\"\n [multiple]=\"true\"\n [fetchOnFocus]=\"true\">\n <ng-template\n fsAutocompleteChipsTemplate\n let-object=\"object\">\n {{ object.name }}\n </ng-template>\n </fs-autocomplete-chips>\n }\n @default {\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default {{ row.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"row.value\"\n [name]=\"'value' + row.group.id\">\n </mat-form-field>\n }\n }\n }\n } @else {\n <fs-message-info>\n This report has no report-level filters yet. Add a filter to a\n component (its settings \u2192 Filters) and show it in the report bar,\n then set its default here.\n </fs-message-info>\n }\n </div>\n </mat-tab>\n </mat-tab-group>\n </ng-container>\n </mat-dialog-content>\n <mat-dialog-actions>\n <fs-form-dialog-actions>\n <button\n type=\"button\"\n mat-button\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i2.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "directive", type: i2.FsFormMinDirective, selector: "[fsFormMin]", inputs: ["fsFormMin", "fsFormMinMessage"] }, { kind: "directive", type: i2.FsFormMaxDirective, selector: "[fsFormMax]", inputs: ["fsFormMax", "fsFormMaxMessage"] }, { kind: "component", type: i2.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i2.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "directive", type: i2.FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }, { kind: "ngmodule", type: FsMaskModule }, { kind: "directive", type: i3.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsMessageModule }, { kind: "component", type: i5.FsMessageInfoComponent, selector: "fs-message-info" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i6.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i6.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i7.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i8.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes", "width"], outputs: ["change"] }, { kind: "ngmodule", type: FsAutocompleteChipsModule }, { kind: "component", type: i9.FsAutocompleteChipsComponent, selector: "fs-autocomplete-chips", inputs: ["fetch", "appearance", "floatLabel", "readonly", "size", "label", "placeholder", "chipImage", "chipBackground", "chipColor", "chipIcon", "chipIconColor", "chipClass", "chipPadding", "shape", "hint", "allowText", "allowObject", "delay", "minPanelWidth", "maxPanelHeight", "validateText", "removable", "allowClear", "color", "background", "orderable", "padless", "initOnClick", "fetchOnFocus", "multiple", "multipleAdd", "confirm", "disabled", "groupBy", "panelWidth", "panelClass", "compareWith"], outputs: ["selected", "removed", "reordered", "clear", "panelOpened", "panelClosed"] }, { kind: "directive", type: i9.FsAutocompleteObjectDirective, selector: "[fsAutocompleteObject],[fsAutocompleteChipsTemplate]" }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i10.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i10.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: TimezoneSelectComponent, selector: "fs-ai-report-timezone-select", inputs: ["placeholder", "required", "disabled", "timezone"], outputs: ["timezoneChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
260
377
  }
261
378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportSettingsComponent, decorators: [{
262
379
  type: Component,
@@ -267,6 +384,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
267
384
  FsDialogModule,
268
385
  FsMessageModule,
269
386
  FsTabsModule,
387
+ FsSkeletonModule,
270
388
  FsDatePickerModule,
271
389
  FsAutocompleteChipsModule,
272
390
  MatTabsModule,
@@ -282,6 +400,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
282
400
  MatSelect,
283
401
  MatOption,
284
402
  TimezoneSelectComponent,
285
- ], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n Report Settings\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"name\"\n name=\"name\"\n [fsFormRequired]=\"true\">\n </mat-form-field>\n <!--\n The page, typed in inches. Orientation is not asked for because it\n is not an independent choice - a page wider than it is tall IS\n landscape - so the two numbers say everything there is to say.\n -->\n <div class=\"fs-row.gap-sm.align-start\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Width\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageWidth\"\n name=\"pageWidth\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageHeight\"\n name=\"pageHeight\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n </div>\n <!--\n How deep the header and footer bands are. Their content is edited\n on the canvas (Edit layout \u2192 Header & footer); these reserve the\n space for it, and 0 means no band.\n -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Header height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"headerHeight\"\n name=\"headerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Footer height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"footerHeight\"\n name=\"footerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Layout\n </mat-label>\n <mat-select\n [(ngModel)]=\"layout\"\n name=\"layout\">\n <mat-option value=\"freeform\">\n Freeform \u2014 position components anywhere on the page\n </mat-option>\n <mat-option value=\"flow\">\n Flow \u2014 components flow into rows by width %\n </mat-option>\n </mat-select>\n <mat-hint>\n Freeform is like PowerPoint; Flow is like a responsive dashboard.\n </mat-hint>\n </mat-form-field>\n <fs-ai-report-timezone-select [(timezone)]=\"timezone\"></fs-ai-report-timezone-select>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Styles\"\n name=\"styles\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Heading Size\n </mat-label>\n <input\n matInput\n type=\"number\"\n step=\"1\"\n min=\"6\"\n max=\"96\"\n [(ngModel)]=\"headingSize\"\n name=\"headingSize\"\n [fsFormMin]=\"6\"\n [fsFormMax]=\"96\">\n <span matTextSuffix>\n pt\n </span>\n <mat-hint>\n Applies to component titles. Points map 1:1 to PDF and PowerPoint.\n </mat-hint>\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"fs-column tab-body\">\n @if (filterRows().length) {\n @for (row of filterRows(); track row.group.id) {\n @switch (row.group.type) {\n @case ('dateRange') {\n <div class=\"fs-row.gap-sm.align-center fs-flex\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default From {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.start\"\n [name]=\"'start' + row.group.id\">\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default To {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n </div>\n <!-- A stored rolling preset cannot be authored here, only\n kept, replaced by picking dates, or cleared. type=\"button\"\n keeps Clear from submitting the form. -->\n @if (row.relative && !row.start && !row.end) {\n <div class=\"fs-row.gap-sm.align-center\">\n <mat-hint class=\"fs-flex\">\n Rolling default: {{ relativeLabel(row.relative) }}. Pick dates to replace it.\n </mat-hint>\n <button\n mat-button\n type=\"button\"\n (click)=\"clearRelative(row)\">\n Clear\n </button>\n </div>\n }\n }\n @case ('select') {\n <fs-autocomplete-chips\n class=\"fs-flex\"\n [label]=\"'Default ' + row.label\"\n [fetch]=\"row.fetch\"\n [(ngModel)]=\"row.values\"\n [name]=\"'values' + row.group.id\"\n [multiple]=\"true\"\n [fetchOnFocus]=\"true\">\n <ng-template\n fsAutocompleteChipsTemplate\n let-object=\"object\">\n {{ object.name }}\n </ng-template>\n </fs-autocomplete-chips>\n }\n @default {\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default {{ row.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"row.value\"\n [name]=\"'value' + row.group.id\">\n </mat-form-field>\n }\n }\n }\n } @else {\n <fs-message-info>\n This report has no report-level filters yet. Add a filter to a\n component (its settings \u2192 Filters) and show it in the report bar,\n then set its default here.\n </fs-message-info>\n }\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <fs-form-dialog-actions>\n <button\n type=\"button\"\n mat-button\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}\n"] }]
403
+ ], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n Report Settings\n </h1>\n <mat-dialog-content>\n <!-- One skeleton over the whole body until the locale list is in. -->\n <ng-container *fsSkeletonForm=\"ready() || null\">\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"name\"\n name=\"name\"\n [fsFormRequired]=\"true\">\n </mat-form-field>\n <!--\n The page, typed in inches. Orientation is not asked for because it\n is not an independent choice - a page wider than it is tall IS\n landscape - so the two numbers say everything there is to say.\n -->\n <div class=\"fs-row.gap-sm.align-start\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Width\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageWidth\"\n name=\"pageWidth\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"1\"\n [(ngModel)]=\"pageHeight\"\n name=\"pageHeight\"\n [fsFormRequired]=\"true\"\n [fsFormMin]=\"pageDimensionMin\"\n [fsFormMax]=\"pageDimensionMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n </div>\n <!--\n How deep the header and footer bands are. Their content is edited\n on the canvas (Edit layout \u2192 Header & footer); these reserve the\n space for it, and 0 means no band.\n -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Header height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"headerHeight\"\n name=\"headerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Footer height\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"2\"\n [(ngModel)]=\"footerHeight\"\n name=\"footerHeight\"\n [fsFormMin]=\"0\"\n [fsFormMax]=\"headerFooterMax\">\n <div matTextSuffix>\n inches\n </div>\n </mat-form-field>\n <fs-ai-report-timezone-select [(timezone)]=\"timezone\"></fs-ai-report-timezone-select>\n <!--\n How numbers and dates are written (formatting only: no text is\n translated) and which currency money is labeled in. Hidden on a\n server too old to resolve a report's locale.\n -->\n @if (locales()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Locale\n </mat-label>\n <mat-select\n [ngModel]=\"locale()\"\n (ngModelChange)=\"locale.set($event)\"\n name=\"locale\">\n @for (option of localeOptions(); track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n {{ formatExample() }}\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Currency\n </mat-label>\n <mat-select\n [ngModel]=\"currency()\"\n (ngModelChange)=\"currency.set($event)\"\n name=\"currency\">\n @for (option of currencyOptions(); track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Names the currency amounts are in; it does not convert them.\n </mat-hint>\n </mat-form-field>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"Styles\"\n name=\"styles\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Heading Size\n </mat-label>\n <input\n matInput\n type=\"number\"\n step=\"1\"\n min=\"6\"\n max=\"96\"\n [(ngModel)]=\"headingSize\"\n name=\"headingSize\"\n [fsFormMin]=\"6\"\n [fsFormMax]=\"96\">\n <span matTextSuffix>\n pt\n </span>\n <mat-hint>\n Applies to component titles. Points map 1:1 to PDF and PowerPoint.\n </mat-hint>\n </mat-form-field>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"fs-column tab-body\">\n @if (filterRows().length) {\n @for (row of filterRows(); track row.group.id) {\n @switch (row.group.type) {\n @case ('dateRange') {\n <div class=\"fs-row.gap-sm.align-center fs-flex\">\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default From {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.start\"\n [name]=\"'start' + row.group.id\">\n </mat-form-field>\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default To {{ row.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n </div>\n <!-- A stored rolling preset cannot be authored here, only\n kept, replaced by picking dates, or cleared. type=\"button\"\n keeps Clear from submitting the form. -->\n @if (row.relative && !row.start && !row.end) {\n <div class=\"fs-row.gap-sm.align-center\">\n <mat-hint class=\"fs-flex\">\n Rolling default: {{ relativeLabel(row.relative) }}. Pick dates to replace it.\n </mat-hint>\n <button\n mat-button\n type=\"button\"\n (click)=\"clearRelative(row)\">\n Clear\n </button>\n </div>\n }\n }\n @case ('select') {\n <fs-autocomplete-chips\n class=\"fs-flex\"\n [label]=\"'Default ' + row.label\"\n [fetch]=\"row.fetch\"\n [(ngModel)]=\"row.values\"\n [name]=\"'values' + row.group.id\"\n [multiple]=\"true\"\n [fetchOnFocus]=\"true\">\n <ng-template\n fsAutocompleteChipsTemplate\n let-object=\"object\">\n {{ object.name }}\n </ng-template>\n </fs-autocomplete-chips>\n }\n @default {\n <mat-form-field class=\"fs-flex\">\n <mat-label>\n Default {{ row.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"row.value\"\n [name]=\"'value' + row.group.id\">\n </mat-form-field>\n }\n }\n }\n } @else {\n <fs-message-info>\n This report has no report-level filters yet. Add a filter to a\n component (its settings \u2192 Filters) and show it in the report bar,\n then set its default here.\n </fs-message-info>\n }\n </div>\n </mat-tab>\n </mat-tab-group>\n </ng-container>\n </mat-dialog-content>\n <mat-dialog-actions>\n <fs-form-dialog-actions>\n <button\n type=\"button\"\n mat-button\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}\n"] }]
286
404
  }] });
287
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL3JlcG9ydC1zZXR0aW5ncy9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvcmVwb3J0LXNldHRpbmdzL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBVSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU3QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDN0gsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzFGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUMzRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQUUs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WUFBWTt3QkFDWixRQUFRO3dCQUNSLE9BQU87d0JBQ1AsU0FBUzt3QkFDVCxRQUFRO3dCQUNSLFNBQVM7d0JBQ1QsU0FBUzt3QkFDVCx1QkFBdUI7cUJBQ3hCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgT25Jbml0LCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE1hdEJ1dHRvbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XG5pbXBvcnQgeyBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZ0FjdGlvbnMsIE1hdERpYWxvZ0NvbnRlbnQsIE1hdERpYWxvZ1JlZiwgTWF0RGlhbG9nVGl0bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkLCBNYXRMYWJlbCwgTWF0SGludCwgTWF0U3VmZml4IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcbmltcG9ydCB7IE1hdE9wdGlvbiwgTWF0U2VsZWN0IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc2VsZWN0JztcbmltcG9ydCB7IE1hdFRhYnNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcblxuaW1wb3J0IHsgRnNBdXRvY29tcGxldGVDaGlwc01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2F1dG9jb21wbGV0ZS1jaGlwcyc7XG5pbXBvcnQgeyBGc0RhdGVQaWNrZXJNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9kYXRlcGlja2VyJztcbmltcG9ydCB7IEZzRGlhbG9nTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGlhbG9nJztcbmltcG9ydCB7IEZzRm9ybU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2Zvcm0nO1xuaW1wb3J0IHsgRnNNYXNrTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWFzayc7XG5pbXBvcnQgeyBGc01lc3NhZ2UsIEZzTWVzc2FnZU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9tcHQgfSBmcm9tICdAZmlyZXN0aXRjaC9wcm9tcHQnO1xuaW1wb3J0IHsgRnNUYWJzTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvdGFicyc7XG5cbmltcG9ydCB7IFRpbWV6b25lU2VsZWN0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy90aW1lem9uZS1zZWxlY3QvdGltZXpvbmUtc2VsZWN0LmNvbXBvbmVudCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIGZvcmtKb2luIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4uLy4uL2RhdGEvcmVwb3J0LmRhdGEnO1xuaW1wb3J0IHtcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LFxuICBSZXBvcnQsXG4gIFJlcG9ydEZpbHRlckdyb3VwLFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgREVGQVVMVF9IRUFESU5HX1NJWkUsIEhFQURFUl9GT09URVJfTUFYLCBQQUdFX0RJTUVOU0lPTl9NQVgsIFBBR0VfRElNRU5TSU9OX01JTiB9IGZyb20gJy4uLy4uL2xheW91dCc7XG5pbXBvcnQge1xuICBkYXRlRnJvbUJvdW5kLCBkYXRlVG9Cb3VuZCwgbG9hZEdyb3VwT3B0aW9ucywgbWF0Y2hPcHRpb25zLCByZWxhdGl2ZUxhYmVsLCByZXNvbHZlT3B0aW9uVmFsdWVzLFxufSBmcm9tICcuLi8uLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcblxuXG4vLyBXaGF0IHRoZSBkaWFsb2cgaGFuZHMgYmFjayB3aGVuIGl0IGNsb3Nlcywgc28gdGhlIHBhZ2Uga25vd3Mgd2hhdCBoYXBwZW5lZFxuLy8gd2l0aG91dCBzbmlmZmluZyBtYWdpYyBzdHJpbmdzLiBBIGRpc21pc3NlZCBkaWFsb2cgY2xvc2VzIHdpdGggYHVuZGVmaW5lZGAuXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydFNldHRpbmdzUmVzdWx0IHtcbiAgYWN0aW9uOiAnc2F2ZWQnIHwgJ2RlbGV0ZWQnO1xufVxuXG5cbi8vIE9uZSByZXBvcnQtbGV2ZWwgZmlsdGVyIGluIHRoZSBGaWx0ZXJzIHRhYjogaXRzIGdyb3VwLCB0aGUgaW5mZXJyZWQgaW50ZXJmYWNlLFxuLy8gYW5kIGFuIGVkaXRhYmxlIGRyYWZ0IGRlZmF1bHQuIFRoZSBkcmFmdCBmaWVsZHMgdXNlZCBkZXBlbmQgb24gdGhlIHR5cGVcbi8vIChkYXRlUmFuZ2Ug4oaSIHN0YXJ0L2VuZCBEYXRlcyBvciBhIHN0b3JlZCByb2xsaW5nIGByZWxhdGl2ZWAgcHJlc2V0OyBzZWxlY3Qg4oaSXG4vLyB2YWx1ZXM7IGtleXdvcmQg4oaSIHRleHQpLiBgZmV0Y2hgIGxvYWRzIHRoZSBzZWxlY3Qgb3B0aW9ucyB0aGUgc2FtZSB3YXkgdGhlXG4vLyByZXBvcnQgYmFyIGRvZXMuXG5pbnRlcmZhY2UgRmlsdGVyRGVmYXVsdFJvdyB7XG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cDtcbiAgbGFiZWw6IHN0cmluZztcbiAgc3RhcnQ6IERhdGUgfCBudWxsO1xuICBlbmQ6IERhdGUgfCBudWxsO1xuICAvLyBUaGUgc3RvcmVkIHJvbGxpbmcgcHJlc2V0IChlLmcuICdsYXN0MTJNb250aHMnKS4gTm90IGF1dGhvcmVkIGhlcmU6IGl0IGlzXG4gIC8vIGNhcnJpZWQgc28gYW4gdW50b3VjaGVkIG9uZSBpcyBzZW50IGJhY2sgYXMgaXQgd2FzLCBhbmQgcGlja2VkIGRhdGVzIG9yXG4gIC8vIENsZWFyIHJlcGxhY2UgaXQuXG4gIHJlbGF0aXZlOiBzdHJpbmcgfCBudWxsO1xuICB2YWx1ZXM6IHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W107XG4gIHZhbHVlOiBzdHJpbmc7XG4gIGZldGNoOiAoa2V5d29yZD86IHN0cmluZykgPT4gT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPjtcbn1cblxuXG4vLyBSZXBvcnQgc2V0dGluZ3MsIGluIHRocmVlIHRhYnM6XG4vLyAgIFNldHRpbmdzIOKAlCBuYW1lICsgcGFnZSBzZXR1cCAoc2l6ZSBpbiBpbmNoZXMsIGhlYWRlci9mb290ZXIgYmFuZCBkZXB0aHMsXG4vLyAgIGxheW91dCBtb2RlKS5cbi8vICAgU3R5bGVzICAg4oCUIHRoZSByZXBvcnQncyB0eXBvZ3JhcGhpYyBzdHlsZXMgKHNpemVzIGluIFBPSU5UUywgMToxIHdpdGhcbi8vICAgUERGL1Bvd2VyUG9pbnQpOyB0aGUgSGVhZGluZyBzaXplIHRvIHN0YXJ0LlxuLy8gICBGaWx0ZXJzICDigJQgdGhlIHJlcG9ydC1sZXZlbCBmaWx0ZXJzIGFuZCB0aGVpciBERUZBVUxUIHZhbHVlcy4gQSBkZWZhdWx0XG4vLyAgIHNlZWRzIHRoZSByZXBvcnQgYmFyIG9uIGV2ZXJ5IG9wZW4gKGZvciBldmVyeSB2aWV3ZXIpIGJ1dCBzdGF5c1xuLy8gICB1c2VyLWNoYW5nZWFibGUg4oCUIGl0IHByZS1maWxscyB0aGUgY29udHJvbCwgaXQgZG9lc24ndCBsb2NrIGl0LiBUaGlzIGlzIHRoZVxuLy8gICBmaXggZm9yIGhlYXZ5IHJlcG9ydHMgb3BlbmluZyBibGFuayBhbmQgdGltaW5nIG91dDogYSBkZWZhdWx0IG1vbnRoICtcbi8vICAgb3JnYW5pemF0aW9uIHNjb3BlcyB0aGUgbGFuZGluZyBwYWdlIGZyb20gdGhlIGZpcnN0IGxvYWQuXG5AQ29tcG9uZW50KHtcbiAgdGVtcGxhdGVVcmw6ICcuL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIEZvcm1zTW9kdWxlLFxuICAgIEZzRm9ybU1vZHVsZSxcbiAgICBGc01hc2tNb2R1bGUsXG4gICAgRnNEaWFsb2dNb2R1bGUsXG4gICAgRnNNZXNzYWdlTW9kdWxlLFxuICAgIEZzVGFic01vZHVsZSxcbiAgICBGc0RhdGVQaWNrZXJNb2R1bGUsXG4gICAgRnNBdXRvY29tcGxldGVDaGlwc01vZHVsZSxcbiAgICBNYXRUYWJzTW9kdWxlLFxuICAgIE1hdEJ1dHRvbixcbiAgICBNYXREaWFsb2dUaXRsZSxcbiAgICBNYXREaWFsb2dDb250ZW50LFxuICAgIE1hdERpYWxvZ0FjdGlvbnMsXG4gICAgTWF0Rm9ybUZpZWxkLFxuICAgIE1hdExhYmVsLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0U3VmZml4LFxuICAgIE1hdElucHV0LFxuICAgIE1hdFNlbGVjdCxcbiAgICBNYXRPcHRpb24sXG4gICAgVGltZXpvbmVTZWxlY3RDb21wb25lbnQsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIFJlcG9ydFNldHRpbmdzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBwdWJsaWMgc2VsZWN0ZWRUYWIgPSAnc2V0dGluZ3MnO1xuXG4gIHB1YmxpYyBuYW1lID0gJyc7XG4gIC8vIFRoZSBwYWdlIGluIGluY2hlcy4gTm8gaW5pdGlhbGl6ZXI6IGV2ZXJ5IHJlcG9ydCBjYXJyaWVzIGEgc2l6ZSwgYW5kXG4gIC8vIG5nT25Jbml0IHNlZWRzIGJvdGggYmVmb3JlIHRoZSB0YWIgcmVuZGVycywgc28gYSBwbGFjZWhvbGRlciBoZXJlIGNvdWxkIG9ubHlcbiAgLy8gZXZlciBiZSBhIHdyb25nIG51bWJlciBicmllZmx5IHNob3dpbmcgYXMgdGhlIG9wZXJhdG9yJ3Mgb3duLlxuICAvL1xuICAvLyBUeXBlZCBgbnVtYmVyIHwgc3RyaW5nYCBiZWNhdXNlIGZzTWFza051bWJlciBpcyB0aGUgY29udHJvbDogaXQgaXMgc2VlZGVkXG4gIC8vIHdpdGggdGhlIHJlcG9ydCdzIG51bWJlciBidXQgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgU1RSSU5HIHRoZSBvcGVyYXRvclxuICAvLyB0eXBlZC4gU2F2ZSBjYXN0cyBpdCBvbmNlLCBvbiB0aGUgd2F5IG91dCDigJQgc2VlIGBfcGFnZURpbWVuc2lvbigpYC5cbiAgcHVibGljIHBhZ2VXaWR0aDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcGFnZUhlaWdodDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcGFnZURpbWVuc2lvbk1pbiA9IFBBR0VfRElNRU5TSU9OX01JTjtcbiAgcHVibGljIHJlYWRvbmx5IHBhZ2VEaW1lbnNpb25NYXggPSBQQUdFX0RJTUVOU0lPTl9NQVg7XG4gIC8vIFRoZSBoZWFkZXIgYW5kIGZvb3RlciBiYW5kIGRlcHRocywgaW5jaGVzIOKAlCB0eXBlZCBsaWtlIHRoZSBwYWdlIHNpemVcbiAgLy8gYmVjYXVzZSBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayBhIHN0cmluZy5cbiAgcHVibGljIGhlYWRlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIGZvb3RlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIHJlYWRvbmx5IGhlYWRlckZvb3Rlck1heCA9IEhFQURFUl9GT09URVJfTUFYO1xuICBwdWJsaWMgbGF5b3V0OiAnZnJlZWZvcm0nIHwgJ2Zsb3cnID0gJ2ZyZWVmb3JtJztcbiAgLy8gU2VlZGVkIHdpdGggdGhlIHpvbmUgdGhlIHJlcG9ydCBhY3R1YWxseSB1c2VzOiBpdHMgb3duIHN0b3JlZCB6b25lLCBlbHNlXG4gIC8vIHRoZSBhcHBsaWNhdGlvbiBkZWZhdWx0IHRoZSBzZXJ2ZXIgcmVzb2x2ZWQgKGVmZmVjdGl2ZVRpbWV6b25lKS4gU2F2ZSBzZW5kc1xuICAvLyBpdCBvbmx5IHdoZW4gaXQgZGlmZmVycyBmcm9tIHRoYXQgZWZmZWN0aXZlIHpvbmUsIHNvIG9wZW5pbmcgYW5kIHNhdmluZyBhXG4gIC8vIHJlcG9ydCB0aGF0IGZvbGxvd3MgdGhlIGRlZmF1bHQgbmV2ZXIgcGlucyBpdCB0byBhIHpvbmUuXG4gIHB1YmxpYyB0aW1lem9uZSA9ICcnO1xuICBwdWJsaWMgaGVhZGluZ1NpemUgPSBERUZBVUxUX0hFQURJTkdfU0laRTtcblxuICAvLyBUaGUgcmVwb3J0LWxldmVsIGZpbHRlcnMgYW5kIHRoZWlyIGVkaXRhYmxlIGRlZmF1bHQgdmFsdWVzIChGaWx0ZXJzIHRhYikuXG4gIHB1YmxpYyByZWFkb25seSBmaWx0ZXJSb3dzID0gc2lnbmFsPEZpbHRlckRlZmF1bHRSb3dbXT4oW10pO1xuICBwdWJsaWMgcmVhZG9ubHkgcmVsYXRpdmVMYWJlbCA9IHJlbGF0aXZlTGFiZWw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfZGF0YTogeyByZXBvcnQ6IFJlcG9ydCB9ID0gaW5qZWN0KE1BVF9ESUFMT0dfREFUQSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RpYWxvZ1JlZiA9IGluamVjdDxNYXREaWFsb2dSZWY8UmVwb3J0U2V0dGluZ3NDb21wb25lbnQsIFJlcG9ydFNldHRpbmdzUmVzdWx0Pj4oTWF0RGlhbG9nUmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbWVzc2FnZSA9IGluamVjdChGc01lc3NhZ2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9wcm9tcHQgPSBpbmplY3QoRnNQcm9tcHQpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBjb25zdCByZXBvcnQgPSB0aGlzLl9kYXRhLnJlcG9ydDtcbiAgICB0aGlzLm5hbWUgPSByZXBvcnQubmFtZTtcbiAgICB0aGlzLnBhZ2VXaWR0aCA9IHJlcG9ydC5wYWdlV2lkdGg7XG4gICAgdGhpcy5wYWdlSGVpZ2h0ID0gcmVwb3J0LnBhZ2VIZWlnaHQ7XG4gICAgdGhpcy5oZWFkZXJIZWlnaHQgPSByZXBvcnQuY29uZmlnPy5oZWFkZXJGb290ZXI/LmhlYWRlckhlaWdodCA/PyAwO1xuICAgIHRoaXMuZm9vdGVySGVpZ2h0ID0gcmVwb3J0LmNvbmZpZz8uaGVhZGVyRm9vdGVyPy5mb290ZXJIZWlnaHQgPz8gMDtcbiAgICB0aGlzLmxheW91dCA9IHJlcG9ydC5sYXlvdXQgPz8gJ2ZyZWVmb3JtJztcbiAgICB0aGlzLnRpbWV6b25lID0gcmVwb3J0LnRpbWV6b25lID8/IHJlcG9ydC5lZmZlY3RpdmVUaW1lem9uZSA/PyAnJztcbiAgICB0aGlzLmhlYWRpbmdTaXplID0gcmVwb3J0LmNvbmZpZz8uc3R5bGVzPy5oZWFkaW5nPy5zaXplID8/IERFRkFVTFRfSEVBRElOR19TSVpFO1xuXG4gICAgdGhpcy5fYnVpbGRGaWx0ZXJSb3dzKHJlcG9ydCk7XG4gIH1cblxuICAvLyBDb25maXJtIGFuZCBkZWxldGUgaGVyZSwgd2hpbGUgdGhlIGRpYWxvZyBpcyBzdGlsbCBvcGVuLCB0aGVuIGNsb3NlIHdpdGhcbiAgLy8gYSBgZGVsZXRlZGAgcmVzdWx0LiBUaGUgcGFnZSByZWFjdHMgdG8gdGhlIHJlc3VsdDsgaXQgbm8gbG9uZ2VyIG93bnMgdGhlXG4gIC8vIHByb21wdCBvciB0aGUgQVBJIGNhbGwuXG4gIHB1YmxpYyBkZWxldGUoKTogdm9pZCB7XG4gICAgdGhpcy5fcHJvbXB0LmNvbmZpcm0oe1xuICAgICAgdGl0bGU6ICdEZWxldGUgUmVwb3J0JyxcbiAgICAgIHRlbXBsYXRlOiBgRGVsZXRlIFwiJHt0aGlzLl9kYXRhLnJlcG9ydC5uYW1lfVwiPyBUaGlzIGNhbm5vdCBiZSB1bmRvbmUuYCxcbiAgICB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLl9yZXBvcnREYXRhLmRlbGV0ZSh0aGlzLl9kYXRhLnJlcG9ydC5pZCkpLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fbWVzc2FnZS5zdWNjZXNzKCdSZXBvcnQgZGVsZXRlZCcpO1xuICAgICAgICB0aGlzLl9kaWFsb2dSZWYuY2xvc2UoeyBhY3Rpb246ICdkZWxldGVkJyB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHNhdmUgPSAoKSA9PiB7XG4gICAgY29uc3QgcmVwb3J0SWQgPSB0aGlzLl9kYXRhLnJlcG9ydC5pZDtcblxuICAgIC8vIFBlcnNpc3QgdGhlIHJlcG9ydCBzZXR0aW5ncyBhbmQgZWFjaCBjaGFuZ2VkIGZpbHRlciBkZWZhdWx0IHRvZ2V0aGVyLCBzb1xuICAgIC8vIHRoZSBzaW5nbGUgU2F2ZSBjb3ZlcnMgYWxsIHRocmVlIHRhYnMuIFRoZSByZXBvcnQgcmVsb2FkcyBvbiB0aGUgYHNhdmVkYFxuICAgIC8vIHJlc3VsdCwgcmUtc2VlZGluZyB0aGUgYmFyIGZyb20gdGhlIG5ldyBkZWZhdWx0cy5cbiAgICBjb25zdCBzZXR0aW5ncyQgPSB0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZShyZXBvcnRJZCwge1xuICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgcGFnZVdpZHRoOiB0aGlzLl9wYWdlRGltZW5zaW9uKHRoaXMucGFnZVdpZHRoKSxcbiAgICAgIHBhZ2VIZWlnaHQ6IHRoaXMuX3BhZ2VEaW1lbnNpb24odGhpcy5wYWdlSGVpZ2h0KSxcbiAgICAgIGxheW91dDogdGhpcy5sYXlvdXQsXG4gICAgICAuLi50aGlzLl90aW1lem9uZVNldHRpbmcoKSxcbiAgICAgIHN0eWxlczogeyBoZWFkaW5nOiB7IHNpemU6IHRoaXMuaGVhZGluZ1NpemUgfSB9LFxuICAgICAgaGVhZGVyRm9vdGVyOiB7XG4gICAgICAgIGhlYWRlckhlaWdodDogdGhpcy5fcGFnZURpbWVuc2lvbih0aGlzLmhlYWRlckhlaWdodCkgfHwgMCxcbiAgICAgICAgZm9vdGVySGVpZ2h0OiB0aGlzLl9wYWdlRGltZW5zaW9uKHRoaXMuZm9vdGVySGVpZ2h0KSB8fCAwLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRzJCA9IHRoaXMuZmlsdGVyUm93cygpXG4gICAgICAuZmlsdGVyKChyb3cpID0+IHRoaXMuX2RlZmF1bHRDaGFuZ2VkKHJvdykpXG4gICAgICAubWFwKChyb3cpID0+IHRoaXMuX3JlcG9ydERhdGEudXBkYXRlRmlsdGVyR3JvdXAocmVwb3J0SWQsIHJvdy5ncm91cC5pZCwge1xuICAgICAgICBkZWZhdWx0OiB0aGlzLl9yb3dEZWZhdWx0KHJvdyksXG4gICAgICB9KSk7XG5cbiAgICByZXR1cm4gZm9ya0pvaW4oW3NldHRpbmdzJCwgLi4uZGVmYXVsdHMkXSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnUmVwb3J0IHNldHRpbmdzIHNhdmVkJyk7XG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgYWN0aW9uOiAnc2F2ZWQnIH0pO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH07XG5cbiAgLy8gRHJvcCB0aGUgcm93J3Mgc3RvcmVkIHJvbGxpbmcgcHJlc2V0IChDbGVhcikuIEEgbmV3IHJvdyBvYmplY3QgcmF0aGVyIHRoYW5cbiAgLy8gYSBtdXRhdGlvbiwgc28gdGhlIHNpZ25hbCBzZWVzIHRoZSBjaGFuZ2U7IHRoZSBAZm9yIHRyYWNrcyBncm91cC5pZCwgc29cbiAgLy8gdGhlIHJvdydzIGJpbmRpbmdzIHN1cnZpdmUgdGhlIHN3YXAuXG4gIHB1YmxpYyBjbGVhclJlbGF0aXZlKHJvdzogRmlsdGVyRGVmYXVsdFJvdyk6IHZvaWQge1xuICAgIHRoaXMuZmlsdGVyUm93cy51cGRhdGUoKHJvd3MpID0+IHJvd3MubWFwKChpdGVtKSA9PiAoaXRlbSA9PT0gcm93ID8geyAuLi5pdGVtLCByZWxhdGl2ZTogbnVsbCB9IDogaXRlbSkpKTtcbiAgfVxuXG4gIC8vIFRoZSBwYWdlIGRpbWVuc2lvbiBhcyBhIHJlYWwgbnVtYmVyIGZvciB0aGUgd2lyZS4gZnNNYXNrTnVtYmVyIGhhbmRzIGJhY2tcbiAgLy8gdGhlIHVubWFza2VkIHN0cmluZyBpdCBidWlsdCB3aXRoIGEgZml4ZWQgJy4nIHJhZGl4ICh3aGljaCBpcyB0aGUgd2hvbGVcbiAgLy8gcG9pbnQgb2YgdGhlIG1hc2sgLSBhIG5hdGl2ZSBudW1iZXIgaW5wdXQgcGFpbnRzIHRoZSB2aWV3ZXIncyBsb2NhbGVcbiAgLy8gc2VwYXJhdG9yIGluc3RlYWQpLCBzbyB0aGUgY2FzdCBoZXJlIGlzIGEgc3RyYWlnaHQgcGFyc2UgYW5kIG5ldmVyIHNlZXMgYVxuICAvLyBjb21tYS4gVGhlIGJhY2tlbmQgcmVqZWN0cyBhbnl0aGluZyBub24tbnVtZXJpYyByYXRoZXIgdGhhbiBjb2VyY2luZywgc28gYVxuICAvLyBOYU4gZmFpbHMgbG91ZGx5IGluc3RlYWQgb2Ygc2lsZW50bHkgc3RvcmluZyBhIHdyb25nIHBhZ2Ugc2l6ZS5cbiAgcHJpdmF0ZSBfcGFnZURpbWVuc2lvbih2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyA/IHZhbHVlIDogcGFyc2VGbG9hdCh2YWx1ZSk7XG4gIH1cblxuICAvLyBUaGUgem9uZSBmb3IgdGhlIHNldHRpbmdzIFBVVCwgc2VudCBvbmx5IHdoZW4gaXQgbW92ZXMgdGhlIHJlcG9ydCBvZmYgdGhlXG4gIC8vIHpvbmUgaXQgYWxyZWFkeSB1c2VzLCBzbyBhbiB1bnRvdWNoZWQgZGlhbG9nIG5ldmVyIHBpbnMgYSByZXBvcnQgdGhhdFxuICAvLyBmb2xsb3dzIHRoZSBhcHBsaWNhdGlvbiBkZWZhdWx0LiBBIHNlcnZlciB0b28gb2xkIHRvIHNlbmRcbiAgLy8gZWZmZWN0aXZlVGltZXpvbmUgZ2V0cyB0aGUgem9uZSBldmVyeSB0aW1lLCBhcyBpdCBhbHdheXMgZGlkLlxuICBwcml2YXRlIF90aW1lem9uZVNldHRpbmcoKTogeyB0aW1lem9uZT86IHN0cmluZyB9IHtcbiAgICBjb25zdCBlZmZlY3RpdmVUaW1lem9uZSA9IHRoaXMuX2RhdGEucmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lO1xuXG4gICAgcmV0dXJuIGVmZmVjdGl2ZVRpbWV6b25lID09PSB1bmRlZmluZWQgfHwgdGhpcy50aW1lem9uZSAhPT0gZWZmZWN0aXZlVGltZXpvbmVcbiAgICAgID8geyB0aW1lem9uZTogdGhpcy50aW1lem9uZSB9XG4gICAgICA6IHt9O1xuICB9XG5cbiAgLy8gQnVpbGQgb25lIGVkaXRhYmxlIHJvdyBwZXIgcmVwb3J0LWxldmVsIGZpbHRlciBncm91cCAobGV2ZWwgcmVwb3J0IG9yIGJvdGgpLFxuICAvLyBpbiBiYXIgb3JkZXIsIHNlZWRpbmcgZWFjaCBkcmFmdCBmcm9tIHRoZSBncm91cCdzIHN0b3JlZCBkZWZhdWx0LlxuICBwcml2YXRlIF9idWlsZEZpbHRlclJvd3MocmVwb3J0OiBSZXBvcnQpOiB2b2lkIHtcbiAgICBjb25zdCByZXBvcnRJZCA9IHJlcG9ydC5pZDtcblxuICAgIGNvbnN0IGJ1aWx0ID0gKHJlcG9ydC5maWx0ZXJHcm91cHMgPz8gW10pXG4gICAgICAuZmlsdGVyKChncm91cCkgPT4gZ3JvdXAubGV2ZWwgPT09ICdyZXBvcnQnIHx8IGdyb3VwLmxldmVsID09PSAnYm90aCcpXG4gICAgICAuc29ydCgoYSwgYikgPT4gYS5vcmRlciAtIGIub3JkZXIpXG4gICAgICAubWFwKChncm91cCkgPT4ge1xuICAgICAgICBjb25zdCBncm91cERlZmF1bHQgPSBncm91cC5jb25maWc/LmRlZmF1bHQ7XG4gICAgICAgIC8vIE9uZSBzaGFyZWQsIHJlcGxheWVkIG9wdGlvbiBzdHJlYW0gcGVyIGdyb3VwOiB0aGUgY2hpcHMgZmV0Y2ggYW5kIHRoZVxuICAgICAgICAvLyBzdG9yZWQgZGVmYXVsdCdzIGxhYmVscyByZWFkIHRoZSBzYW1lIGxpc3QsIHNvIGl0IGlzIGZldGNoZWQgb25jZS5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyQgPSBsb2FkR3JvdXBPcHRpb25zKGdyb3VwLCB0aGlzLl9yZXBvcnREYXRhLCByZXBvcnRJZCk7XG5cbiAgICAgICAgY29uc3Qgcm93OiBGaWx0ZXJEZWZhdWx0Um93ID0ge1xuICAgICAgICAgIGdyb3VwLFxuICAgICAgICAgIGxhYmVsOiBncm91cC5sYWJlbCB8fCBncm91cC5maWx0ZXJzPy5bMF0/LmZpbHRlckNvbHVtbiB8fCAnRmlsdGVyJyxcbiAgICAgICAgICBzdGFydDogZGF0ZUZyb21Cb3VuZChncm91cERlZmF1bHQ/LnN0YXJ0KSxcbiAgICAgICAgICBlbmQ6IGRhdGVGcm9tQm91bmQoZ3JvdXBEZWZhdWx0Py5lbmQpLFxuICAgICAgICAgIHJlbGF0aXZlOiBncm91cERlZmF1bHQ/LnJlbGF0aXZlID8/IG51bGwsXG4gICAgICAgICAgLy8gTmFtZWQgYmVsb3csIG9uY2UgdGhlIG9wdGlvbiBsaXN0IGNhcnJ5aW5nIHRoZWlyIGxhYmVscyBpcyBpbi5cbiAgICAgICAgICB2YWx1ZXM6IFtdLFxuICAgICAgICAgIHZhbHVlOiBncm91cERlZmF1bHQ/LnZhbHVlID8/ICcnLFxuICAgICAgICAgIC8vIGZzLWF1dG9jb21wbGV0ZS1jaGlwcyBmZXRjaDogdGhlIGdyb3VwJ3MgZGlzdGluY3Qgb3B0aW9ucywgbmFtZS1maWx0ZXJlZC5cbiAgICAgICAgICAvLyBTYW1lIGxvYWRlciB0aGUgcmVwb3J0IGJhciB1c2VzLCBzbyB0aGUgdHdvIG5ldmVyIGRyaWZ0LlxuICAgICAgICAgIGZldGNoOiAoa2V5d29yZD86IHN0cmluZykgPT4gbWF0Y2hPcHRpb25zKG9wdGlvbnMkLCBrZXl3b3JkKSxcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4geyByb3csIG9wdGlvbnMkLCB2YWx1ZXM6IGdyb3VwRGVmYXVsdD8udmFsdWVzID8/IFtdIH07XG4gICAgICB9KTtcblxuICAgIGNvbnN0IHJvd3MgPSBidWlsdC5tYXAoKGVudHJ5KSA9PiBlbnRyeS5yb3cpO1xuICAgIGNvbnN0IHNlZWRlZCA9IGJ1aWx0LmZpbHRlcigoZW50cnkpID0+IGVudHJ5LnZhbHVlcy5sZW5ndGgpO1xuXG4gICAgLy8gTm90aGluZyB0byBuYW1lIOKAlCBwdWJsaXNoIGltbWVkaWF0ZWx5IHJhdGhlciB0aGFuIHdhaXRpbmcgb24gYSByZXF1ZXN0XG4gICAgLy8gbm8gcm93IG5lZWRzLlxuICAgIGlmICghc2VlZGVkLmxlbmd0aCkge1xuICAgICAgdGhpcy5maWx0ZXJSb3dzLnNldChyb3dzKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEEgc3RvcmVkIHNlbGVjdCBkZWZhdWx0IGhvbGRzIGlkcywgc28gaXRzIGNoaXBzIGNhbiBvbmx5IGJlIG5hbWVkIG9uY2UgdGhlXG4gICAgLy8gb3B0aW9uIGxpc3QgaXMgaW4uIFJlc29sdmUgZXZlcnkgc2VlZGVkIHJvdyBmaXJzdCBhbmQgcHVibGlzaCB0aGUgcm93cyBpblxuICAgIC8vIG9uZSBnbywgc28gdGhlIHRhYiBuZXZlciByZW5kZXJzIGEgY2hpcCBzaG93aW5nIGEgcmF3IGlkLlxuICAgIGZvcmtKb2luKHNlZWRlZC5tYXAoKGVudHJ5KSA9PiByZXNvbHZlT3B0aW9uVmFsdWVzKGVudHJ5Lm9wdGlvbnMkLCBlbnRyeS52YWx1ZXMpKSlcbiAgICAgIC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoKHJlc29sdmVkKSA9PiB7XG4gICAgICAgIHJlc29sdmVkLmZvckVhY2goKHZhbHVlcywgaW5kZXgpID0+IHNlZWRlZFtpbmRleF0ucm93LnZhbHVlcyA9IHZhbHVlcyk7XG4gICAgICAgIHRoaXMuZmlsdGVyUm93cy5zZXQocm93cyk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFRoZSBkcmFmdCBkZWZhdWx0IG5vcm1hbGl6ZWQgdG8gdGhlIHdpcmUgc2hhcGUgZm9yIHRoaXMgcm93J3MgdHlwZSwgb3IgbnVsbFxuICAvLyB3aGVuIGVtcHR5ICh3aGljaCBjbGVhcnMgdGhlIHN0b3JlZCBkZWZhdWx0KS4gQSBkYXRlIHJhbmdlIGlzIHRoZSBwaWNrZWRcbiAgLy8gZGF0ZXMgd2hlbiB0aGVyZSBhcmUgYW55LCBlbHNlIHRoZSBjYXJyaWVkIHJvbGxpbmcgcHJlc2V0LCBuZXZlciBib3RoOiB0aGVcbiAgLy8gc2VydmVyIHJlZnVzZXMgYSByZWxhdGl2ZSBwcmVzZXQgY29tYmluZWQgd2l0aCBkYXRlcy5cbiAgcHJpdmF0ZSBfcm93RGVmYXVsdChyb3c6IEZpbHRlckRlZmF1bHRSb3cpOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHtcbiAgICBzd2l0Y2ggKHJvdy5ncm91cC50eXBlKSB7XG4gICAgICBjYXNlICdkYXRlUmFuZ2UnOiB7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gZGF0ZVRvQm91bmQocm93LnN0YXJ0KTtcbiAgICAgICAgY29uc3QgZW5kID0gZGF0ZVRvQm91bmQocm93LmVuZCk7XG5cbiAgICAgICAgaWYgKHN0YXJ0IHx8IGVuZCkge1xuICAgICAgICAgIHJldHVybiB7IHN0YXJ0OiBzdGFydCA/PyB1bmRlZmluZWQsIGVuZDogZW5kID8/IHVuZGVmaW5lZCB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJvdy5yZWxhdGl2ZSA/IHsgcmVsYXRpdmU6IHJvdy5yZWxhdGl2ZSB9IDogbnVsbDtcbiAgICAgIH1cblxuICAgICAgY2FzZSAnc2VsZWN0JzpcbiAgICAgICAgcmV0dXJuIHJvdy52YWx1ZXMubGVuZ3RoID8geyB2YWx1ZXM6IHJvdy52YWx1ZXMubWFwKChvcHRpb24pID0+IG9wdGlvbi52YWx1ZSkgfSA6IG51bGw7XG5cbiAgICAgIGNhc2UgJ2tleXdvcmQnOlxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHJvdy52YWx1ZS50cmltKCk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlID8geyB2YWx1ZSB9IDogbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBXaGV0aGVyIHRoZSByb3cncyBkcmFmdCBkaWZmZXJzIGZyb20gdGhlIGdyb3VwJ3Mgc3RvcmVkIGRlZmF1bHQg4oCUIG9ubHlcbiAgLy8gY2hhbmdlZCByb3dzIGFyZSBwZXJzaXN0ZWQgb24gU2F2ZS5cbiAgcHJpdmF0ZSBfZGVmYXVsdENoYW5nZWQocm93OiBGaWx0ZXJEZWZhdWx0Um93KTogYm9vbGVhbiB7XG4gICAgY29uc3QgYmVmb3JlID0gSlNPTi5zdHJpbmdpZnkodGhpcy5fbm9ybWFsaXplKHJvdy5ncm91cC5jb25maWc/LmRlZmF1bHQgPz8gbnVsbCkpO1xuICAgIGNvbnN0IGFmdGVyID0gSlNPTi5zdHJpbmdpZnkodGhpcy5fbm9ybWFsaXplKHRoaXMuX3Jvd0RlZmF1bHQocm93KSkpO1xuXG4gICAgcmV0dXJuIGJlZm9yZSAhPT0gYWZ0ZXI7XG4gIH1cblxuICAvLyBBIHN0YWJsZSBjb21wYXJpc29uIGZvcm06IGVtcHR5IGFuZCB1bmRlZmluZWQga2V5cyBhcmUgZHJvcHBlZCBzbyBhIG5vLW9wXG4gIC8vIGVkaXQgZG9lc24ndCByZWFkIGFzIGEgY2hhbmdlLiByZWxhdGl2ZSBpcyBjb21wYXJlZCBsaWtlIHRoZSByZXN0OiB0aGUgcm93XG4gIC8vIGNhcnJpZXMgaXQsIHNvIGFuIHVudG91Y2hlZCByb2xsaW5nIGRlZmF1bHQgcmVhZHMgYXMgdW5jaGFuZ2VkLlxuICBwcml2YXRlIF9ub3JtYWxpemUodmFsdWU6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwpOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHtcbiAgICBpZiAoIXZhbHVlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBub3JtYWxpemVkOiBGaWx0ZXJHcm91cERlZmF1bHQgPSB7fTtcbiAgICBpZiAodmFsdWUuc3RhcnQpIHtcbiAgICAgIG5vcm1hbGl6ZWQuc3RhcnQgPSB2YWx1ZS5zdGFydDtcbiAgICB9XG4gICAgaWYgKHZhbHVlLmVuZCkge1xuICAgICAgbm9ybWFsaXplZC5lbmQgPSB2YWx1ZS5lbmQ7XG4gICAgfVxuICAgIGlmICh2YWx1ZS52YWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgbm9ybWFsaXplZC52YWx1ZXMgPSB2YWx1ZS52YWx1ZXM7XG4gICAgfVxuICAgIGlmICh2YWx1ZS52YWx1ZSkge1xuICAgICAgbm9ybWFsaXplZC52YWx1ZSA9IHZhbHVlLnZhbHVlO1xuICAgIH1cbiAgICBpZiAodmFsdWUucmVsYXRpdmUpIHtcbiAgICAgIG5vcm1hbGl6ZWQucmVsYXRpdmUgPSB2YWx1ZS5yZWxhdGl2ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMobm9ybWFsaXplZCkubGVuZ3RoID8gbm9ybWFsaXplZCA6IG51bGw7XG4gIH1cbn1cbiIsIjxmb3JtXG4gICAgZnNGb3JtXG4gICAgW3N1Ym1pdF09XCJzYXZlXCI+XG4gIDxmcy1kaWFsb2c+XG4gICAgPGgxIG1hdC1kaWFsb2ctdGl0bGU+XG4gICAgICBSZXBvcnQgU2V0dGluZ3NcbiAgICA8L2gxPlxuICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICA8bWF0LXRhYi1ncm91cCBbKHNlbGVjdGVkKV09XCJzZWxlY3RlZFRhYlwiPlxuICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgbGFiZWw9XCJTZXR0aW5nc1wiXG4gICAgICAgICAgICBuYW1lPVwic2V0dGluZ3NcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uIHRhYi1ib2R5XCI+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgTmFtZVxuICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm5hbWVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJuYW1lXCJcbiAgICAgICAgICAgICAgICBbZnNGb3JtUmVxdWlyZWRdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwhLS1cbiAgICAgICAgICAgICAgVGhlIHBhZ2UsIHR5cGVkIGluIGluY2hlcy4gT3JpZW50YXRpb24gaXMgbm90IGFza2VkIGZvciBiZWNhdXNlIGl0XG4gICAgICAgICAgICAgIGlzIG5vdCBhbiBpbmRlcGVuZGVudCBjaG9pY2UgLSBhIHBhZ2Ugd2lkZXIgdGhhbiBpdCBpcyB0YWxsIElTXG4gICAgICAgICAgICAgIGxhbmRzY2FwZSAtIHNvIHRoZSB0d28gbnVtYmVycyBzYXkgZXZlcnl0aGluZyB0aGVyZSBpcyB0byBzYXkuXG4gICAgICAgICAgICAtLT5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1yb3cuZ2FwLXNtLmFsaWduLXN0YXJ0XCI+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZzLWZsZXhcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgV2lkdGhcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIxXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWdlV2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFnZVdpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cInBhZ2VEaW1lbnNpb25NaW5cIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWF4XT1cInBhZ2VEaW1lbnNpb25NYXhcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICBpbmNoZXNcbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBIZWlnaHRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIxXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWdlSGVpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZ2VIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtUmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwicGFnZURpbWVuc2lvbk1pblwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwicGFnZURpbWVuc2lvbk1heFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgIGluY2hlc1xuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8IS0tXG4gICAgICAgICAgICAgIEhvdyBkZWVwIHRoZSBoZWFkZXIgYW5kIGZvb3RlciBiYW5kcyBhcmUuIFRoZWlyIGNvbnRlbnQgaXMgZWRpdGVkXG4gICAgICAgICAgICAgIG9uIHRoZSBjYW52YXMgKEVkaXQgbGF5b3V0IOKGkiBIZWFkZXIgJiBmb290ZXIpOyB0aGVzZSByZXNlcnZlIHRoZVxuICAgICAgICAgICAgICBzcGFjZSBmb3IgaXQsIGFuZCAwIG1lYW5zIG5vIGJhbmQuXG4gICAgICAgICAgICAtLT5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICBIZWFkZXIgaGVpZ2h0XG4gICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIyXCJcbiAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiaGVhZGVySGVpZ2h0XCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJoZWFkZXJIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCJcbiAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwiaGVhZGVyRm9vdGVyTWF4XCI+XG4gICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICBpbmNoZXNcbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIEZvb3RlciBoZWlnaHRcbiAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjJcIlxuICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJmb290ZXJIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cImZvb3RlckhlaWdodFwiXG4gICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjBcIlxuICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCJoZWFkZXJGb290ZXJNYXhcIj5cbiAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgIGluY2hlc1xuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgTGF5b3V0XG4gICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJsYXlvdXRcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cImxheW91dFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwiZnJlZWZvcm1cIj5cbiAgICAgICAgICAgICAgICAgIEZyZWVmb3JtIOKAlCBwb3NpdGlvbiBjb21wb25lbnRzIGFueXdoZXJlIG9uIHRoZSBwYWdlXG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwiZmxvd1wiPlxuICAgICAgICAgICAgICAgICAgRmxvdyDigJQgY29tcG9uZW50cyBmbG93IGludG8gcm93cyBieSB3aWR0aCAlXG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICBGcmVlZm9ybSBpcyBsaWtlIFBvd2VyUG9pbnQ7IEZsb3cgaXMgbGlrZSBhIHJlc3BvbnNpdmUgZGFzaGJvYXJkLlxuICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxmcy1haS1yZXBvcnQtdGltZXpvbmUtc2VsZWN0IFsodGltZXpvbmUpXT1cInRpbWV6b25lXCI+PC9mcy1haS1yZXBvcnQtdGltZXpvbmUtc2VsZWN0PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIlN0eWxlc1wiXG4gICAgICAgICAgICBuYW1lPVwic3R5bGVzXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtbiB0YWItYm9keVwiPlxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIEhlYWRpbmcgU2l6ZVxuICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICBzdGVwPVwiMVwiXG4gICAgICAgICAgICAgICAgbWluPVwiNlwiXG4gICAgICAgICAgICAgICAgbWF4PVwiOTZcIlxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiaGVhZGluZ1NpemVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJoZWFkaW5nU2l6ZVwiXG4gICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCI2XCJcbiAgICAgICAgICAgICAgICBbZnNGb3JtTWF4XT1cIjk2XCI+XG4gICAgICAgICAgICAgIDxzcGFuIG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgcHRcbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgQXBwbGllcyB0byBjb21wb25lbnQgdGl0bGVzLiBQb2ludHMgbWFwIDE6MSB0byBQREYgYW5kIFBvd2VyUG9pbnQuXG4gICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIkZpbHRlcnNcIlxuICAgICAgICAgICAgbmFtZT1cImZpbHRlcnNcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uIHRhYi1ib2R5XCI+XG4gICAgICAgICAgICBAaWYgKGZpbHRlclJvd3MoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgQGZvciAocm93IG9mIGZpbHRlclJvd3MoKTsgdHJhY2sgcm93Lmdyb3VwLmlkKSB7XG4gICAgICAgICAgICAgICAgQHN3aXRjaCAocm93Lmdyb3VwLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgIEBjYXNlICgnZGF0ZVJhbmdlJykge1xuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtcm93LmdhcC1zbS5hbGlnbi1jZW50ZXIgZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZzLWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQgRnJvbSB7eyByb3cubGFiZWwgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGZzRGF0ZVBpY2tlclxuICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy5zdGFydFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidzdGFydCcgKyByb3cuZ3JvdXAuaWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZzLWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQgVG8ge3sgcm93LmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBmc0RhdGVQaWNrZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cuZW5kXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ2VuZCcgKyByb3cuZ3JvdXAuaWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBBIHN0b3JlZCByb2xsaW5nIHByZXNldCBjYW5ub3QgYmUgYXV0aG9yZWQgaGVyZSwgb25seVxuICAgICAgICAgICAgICAgICAgICAgICAgIGtlcHQsIHJlcGxhY2VkIGJ5IHBpY2tpbmcgZGF0ZXMsIG9yIGNsZWFyZWQuIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBzIENsZWFyIGZyb20gc3VibWl0dGluZyB0aGUgZm9ybS4gLS0+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAocm93LnJlbGF0aXZlICYmICFyb3cuc3RhcnQgJiYgIXJvdy5lbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtcm93LmdhcC1zbS5hbGlnbi1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaGludCBjbGFzcz1cImZzLWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgUm9sbGluZyBkZWZhdWx0OiB7eyByZWxhdGl2ZUxhYmVsKHJvdy5yZWxhdGl2ZSkgfX0uIFBpY2sgZGF0ZXMgdG8gcmVwbGFjZSBpdC5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhclJlbGF0aXZlKHJvdylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgQ2xlYXJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBAY2FzZSAoJ3NlbGVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgPGZzLWF1dG9jb21wbGV0ZS1jaGlwc1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmcy1mbGV4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtsYWJlbF09XCInRGVmYXVsdCAnICsgcm93LmxhYmVsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtmZXRjaF09XCJyb3cuZmV0Y2hcIlxuICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cudmFsdWVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIid2YWx1ZXMnICsgcm93Lmdyb3VwLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFttdWx0aXBsZV09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtmZXRjaE9uRm9jdXNdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICBmc0F1dG9jb21wbGV0ZUNoaXBzVGVtcGxhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0LW9iamVjdD1cIm9iamVjdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgb2JqZWN0Lm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICA8L2ZzLWF1dG9jb21wbGV0ZS1jaGlwcz5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIEBkZWZhdWx0IHtcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0IHt7IHJvdy5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicm93LnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIid2YWx1ZScgKyByb3cuZ3JvdXAuaWRcIj5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8ZnMtbWVzc2FnZS1pbmZvPlxuICAgICAgICAgICAgICAgIFRoaXMgcmVwb3J0IGhhcyBubyByZXBvcnQtbGV2ZWwgZmlsdGVycyB5ZXQuIEFkZCBhIGZpbHRlciB0byBhXG4gICAgICAgICAgICAgICAgY29tcG9uZW50IChpdHMgc2V0dGluZ3Mg4oaSIEZpbHRlcnMpIGFuZCBzaG93IGl0IGluIHRoZSByZXBvcnQgYmFyLFxuICAgICAgICAgICAgICAgIHRoZW4gc2V0IGl0cyBkZWZhdWx0IGhlcmUuXG4gICAgICAgICAgICAgIDwvZnMtbWVzc2FnZS1pbmZvPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICA8L21hdC10YWItZ3JvdXA+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgIDxmcy1mb3JtLWRpYWxvZy1hY3Rpb25zPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKClcIj5cbiAgICAgICAgICBEZWxldGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2ZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPiJdfQ==
405
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL3JlcG9ydC1zZXR0aW5ncy9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvcmVwb3J0LXNldHRpbmdzL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBVSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxlQUFlLEVBQUUsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdILE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFdkQsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDM0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQs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LCtvQkFDYixTQUFTLGlMQUNULGNBQWMsK0hBQ2QsZ0JBQWdCLHlHQUNoQixnQkFBZ0IsNEhBQ2hCLFlBQVksNExBQ1osUUFBUSxzREFDUixPQUFPLDhFQUNQLFNBQVMscUhBQ1QsUUFBUSxpVUFDUixTQUFTLHdlQUNULFNBQVMscUpBQ1QsdUJBQXVCOzs0RkFHZCx1QkFBdUI7a0JBOUJuQyxTQUFTO3NDQUdTLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQO3dCQUNQLFdBQVc7d0JBQ1gsWUFBWTt3QkFDWixZQUFZO3dCQUNaLGNBQWM7d0JBQ2QsZUFBZTt3QkFDZixZQUFZO3dCQUNaLGdCQUFnQjt3QkFDaEIsa0JBQWtCO3dCQUNsQix5QkFBeUI7d0JBQ3pCLGFBQWE7d0JBQ2IsU0FBUzt3QkFDVCxjQUFjO3dCQUNkLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixZQUFZO3dCQUNaLFFBQVE7d0JBQ1IsT0FBTzt3QkFDUCxTQUFTO3dCQUNULFFBQVE7d0JBQ1IsU0FBUzt3QkFDVCxTQUFTO3dCQUNULHVCQUF1QjtxQkFDeEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBPbkluaXQsIGNvbXB1dGVkLCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE1hdEJ1dHRvbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XG5pbXBvcnQgeyBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZ0FjdGlvbnMsIE1hdERpYWxvZ0NvbnRlbnQsIE1hdERpYWxvZ1JlZiwgTWF0RGlhbG9nVGl0bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkLCBNYXRMYWJlbCwgTWF0SGludCwgTWF0U3VmZml4IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcbmltcG9ydCB7IE1hdE9wdGlvbiwgTWF0U2VsZWN0IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc2VsZWN0JztcbmltcG9ydCB7IE1hdFRhYnNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcblxuaW1wb3J0IHsgRnNBdXRvY29tcGxldGVDaGlwc01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2F1dG9jb21wbGV0ZS1jaGlwcyc7XG5pbXBvcnQgeyBGc0RhdGVQaWNrZXJNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9kYXRlcGlja2VyJztcbmltcG9ydCB7IEZzRGlhbG9nTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGlhbG9nJztcbmltcG9ydCB7IEZzRm9ybU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2Zvcm0nO1xuaW1wb3J0IHsgRnNNYXNrTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWFzayc7XG5pbXBvcnQgeyBGc01lc3NhZ2UsIEZzTWVzc2FnZU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9tcHQgfSBmcm9tICdAZmlyZXN0aXRjaC9wcm9tcHQnO1xuaW1wb3J0IHsgRnNTa2VsZXRvbk1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3NrZWxldG9uJztcbmltcG9ydCB7IEZzVGFic01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3RhYnMnO1xuXG5pbXBvcnQgeyBUaW1lem9uZVNlbGVjdENvbXBvbmVudCB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvdGltZXpvbmUtc2VsZWN0L3RpbWV6b25lLXNlbGVjdC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBmb3JrSm9pbiwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIGZpbmFsaXplLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4uLy4uL2RhdGEvcmVwb3J0LmRhdGEnO1xuaW1wb3J0IHsgUmVwb3J0VmFsdWVGb3JtYXQgfSBmcm9tICcuLi8uLi9lbnVtcy9yZXBvcnQtdmFsdWUtZm9ybWF0LmVudW0nO1xuaW1wb3J0IHtcbiAgREFZX1NIT1JULFxuICBSRVBPUlRfRkFMTEJBQ0tfQ1VSUkVOQ1ksXG4gIGN1cnJlbmN5TmFtZSxcbiAgZm9ybWF0TG9jYWxEYXRlLFxuICBmb3JtYXROdW1iZXIsXG4gIGxvY2FsZU5hbWUsXG4gIHJlc29sdmVSZXBvcnRDdXJyZW5jeSxcbiAgcmVzb2x2ZVJlcG9ydExvY2FsZSxcbn0gZnJvbSAnLi4vLi4vZm9ybWF0JztcbmltcG9ydCB7XG4gIEZpbHRlckdyb3VwRGVmYXVsdCxcbiAgUmVwb3J0LFxuICBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgUmVwb3J0TG9jYWxlcyxcbn0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IERFRkFVTFRfSEVBRElOR19TSVpFLCBIRUFERVJfRk9PVEVSX01BWCwgUEFHRV9ESU1FTlNJT05fTUFYLCBQQUdFX0RJTUVOU0lPTl9NSU4gfSBmcm9tICcuLi8uLi9sYXlvdXQnO1xuaW1wb3J0IHtcbiAgZGF0ZUZyb21Cb3VuZCwgZGF0ZVRvQm91bmQsIGxvYWRHcm91cE9wdGlvbnMsIG1hdGNoT3B0aW9ucywgcmVsYXRpdmVMYWJlbCwgcmVzb2x2ZU9wdGlvblZhbHVlcyxcbn0gZnJvbSAnLi4vLi4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5cbmltcG9ydCB7IHJlcG9ydExvY2FsZVBhdGNoIH0gZnJvbSAnLi9yZXBvcnQtbG9jYWxlLXBhdGNoJztcblxuXG4vLyBXaGF0IHRoZSBkaWFsb2cgaGFuZHMgYmFjayB3aGVuIGl0IGNsb3Nlcywgc28gdGhlIHBhZ2Uga25vd3Mgd2hhdCBoYXBwZW5lZFxuLy8gd2l0aG91dCBzbmlmZmluZyBtYWdpYyBzdHJpbmdzLiBBIGRpc21pc3NlZCBkaWFsb2cgY2xvc2VzIHdpdGggYHVuZGVmaW5lZGAuXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydFNldHRpbmdzUmVzdWx0IHtcbiAgYWN0aW9uOiAnc2F2ZWQnIHwgJ2RlbGV0ZWQnO1xufVxuXG5cbi8vIE9uZSByZXBvcnQtbGV2ZWwgZmlsdGVyIGluIHRoZSBGaWx0ZXJzIHRhYjogaXRzIGdyb3VwLCB0aGUgaW5mZXJyZWQgaW50ZXJmYWNlLFxuLy8gYW5kIGFuIGVkaXRhYmxlIGRyYWZ0IGRlZmF1bHQuIFRoZSBkcmFmdCBmaWVsZHMgdXNlZCBkZXBlbmQgb24gdGhlIHR5cGVcbi8vIChkYXRlUmFuZ2Ug4oaSIHN0YXJ0L2VuZCBEYXRlcyBvciBhIHN0b3JlZCByb2xsaW5nIGByZWxhdGl2ZWAgcHJlc2V0OyBzZWxlY3Qg4oaSXG4vLyB2YWx1ZXM7IGtleXdvcmQg4oaSIHRleHQpLiBgZmV0Y2hgIGxvYWRzIHRoZSBzZWxlY3Qgb3B0aW9ucyB0aGUgc2FtZSB3YXkgdGhlXG4vLyByZXBvcnQgYmFyIGRvZXMuXG5pbnRlcmZhY2UgRmlsdGVyRGVmYXVsdFJvdyB7XG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cDtcbiAgbGFiZWw6IHN0cmluZztcbiAgc3RhcnQ6IERhdGUgfCBudWxsO1xuICBlbmQ6IERhdGUgfCBudWxsO1xuICAvLyBUaGUgc3RvcmVkIHJvbGxpbmcgcHJlc2V0IChlLmcuICdsYXN0MTJNb250aHMnKS4gTm90IGF1dGhvcmVkIGhlcmU6IGl0IGlzXG4gIC8vIGNhcnJpZWQgc28gYW4gdW50b3VjaGVkIG9uZSBpcyBzZW50IGJhY2sgYXMgaXQgd2FzLCBhbmQgcGlja2VkIGRhdGVzIG9yXG4gIC8vIENsZWFyIHJlcGxhY2UgaXQuXG4gIHJlbGF0aXZlOiBzdHJpbmcgfCBudWxsO1xuICB2YWx1ZXM6IHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W107XG4gIHZhbHVlOiBzdHJpbmc7XG4gIGZldGNoOiAoa2V5d29yZD86IHN0cmluZykgPT4gT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPjtcbn1cblxuLy8gT25lIGVudHJ5IG9mIHRoZSBMb2NhbGUgb3IgQ3VycmVuY3kgc2VsZWN0LiAnJyBpcyB0aGUgZXhwbGljaXQgRGVmYXVsdC5cbmludGVyZmFjZSBMb2NhbGVTZWxlY3RPcHRpb24ge1xuICB2YWx1ZTogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xufVxuXG4vLyBUaGUgZGF5IHRoZSBMb2NhbGUgaGludCB3cml0ZXMsIGEgZml4ZWQgY2FsZW5kYXIgZGF5IHNvIHRoZSBleGFtcGxlIG5ldmVyXG4vLyBjaGFuZ2VzIHVuZGVyIHRoZSBvcGVyYXRvci5cbmNvbnN0IEVYQU1QTEVfREFZID0gbmV3IERhdGUoMjAyNiwgMCwgNSk7XG5jb25zdCBFWEFNUExFX0FNT1VOVCA9IDEyMzQuNTtcblxuLy8gJ0NhbmFkaWFuIEZyZW5jaCAoZnItQ0EpJywgJ0NhbmFkaWFuIERvbGxhciAoQ0FEKSc6IEVuZ2xpc2ggbmFtZXMgd2hhdGV2ZXJcbi8vIHRoZSByZXBvcnQncyBsb2NhbGUsIHdpdGggdGhlIGNvZGUgdGhhdCBpcyBzdG9yZWQuXG5mdW5jdGlvbiBsb2NhbGVMYWJlbCh0YWc6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtsb2NhbGVOYW1lKHRhZyl9ICgke3RhZ30pYDtcbn1cblxuZnVuY3Rpb24gY3VycmVuY3lMYWJlbChjb2RlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7Y3VycmVuY3lOYW1lKGNvZGUpfSAoJHtjb2RlfSlgO1xufVxuXG5cbi8vIFJlcG9ydCBzZXR0aW5ncywgaW4gdGhyZWUgdGFiczpcbi8vICAgU2V0dGluZ3Mg4oCUIG5hbWUgKyBwYWdlIHNldHVwIChzaXplIGluIGluY2hlcywgaGVhZGVyL2Zvb3RlciBiYW5kIGRlcHRocykuXG4vLyAgIFN0eWxlcyAgIOKAlCB0aGUgcmVwb3J0J3MgdHlwb2dyYXBoaWMgc3R5bGVzIChzaXplcyBpbiBQT0lOVFMsIDE6MSB3aXRoXG4vLyAgIFBERi9Qb3dlclBvaW50KTsgdGhlIEhlYWRpbmcgc2l6ZSB0byBzdGFydC5cbi8vICAgRmlsdGVycyAg4oCUIHRoZSByZXBvcnQtbGV2ZWwgZmlsdGVycyBhbmQgdGhlaXIgREVGQVVMVCB2YWx1ZXMuIEEgZGVmYXVsdFxuLy8gICBzZWVkcyB0aGUgcmVwb3J0IGJhciBvbiBldmVyeSBvcGVuIChmb3IgZXZlcnkgdmlld2VyKSBidXQgc3RheXNcbi8vICAgdXNlci1jaGFuZ2VhYmxlIOKAlCBpdCBwcmUtZmlsbHMgdGhlIGNvbnRyb2wsIGl0IGRvZXNuJ3QgbG9jayBpdC4gVGhpcyBpcyB0aGVcbi8vICAgZml4IGZvciBoZWF2eSByZXBvcnRzIG9wZW5pbmcgYmxhbmsgYW5kIHRpbWluZyBvdXQ6IGEgZGVmYXVsdCBtb250aCArXG4vLyAgIG9yZ2FuaXphdGlvbiBzY29wZXMgdGhlIGxhbmRpbmcgcGFnZSBmcm9tIHRoZSBmaXJzdCBsb2FkLlxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0Zvcm1Nb2R1bGUsXG4gICAgRnNNYXNrTW9kdWxlLFxuICAgIEZzRGlhbG9nTW9kdWxlLFxuICAgIEZzTWVzc2FnZU1vZHVsZSxcbiAgICBGc1RhYnNNb2R1bGUsXG4gICAgRnNTa2VsZXRvbk1vZHVsZSxcbiAgICBGc0RhdGVQaWNrZXJNb2R1bGUsXG4gICAgRnNBdXRvY29tcGxldGVDaGlwc01vZHVsZSxcbiAgICBNYXRUYWJzTW9kdWxlLFxuICAgIE1hdEJ1dHRvbixcbiAgICBNYXREaWFsb2dUaXRsZSxcbiAgICBNYXREaWFsb2dDb250ZW50LFxuICAgIE1hdERpYWxvZ0FjdGlvbnMsXG4gICAgTWF0Rm9ybUZpZWxkLFxuICAgIE1hdExhYmVsLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0U3VmZml4LFxuICAgIE1hdElucHV0LFxuICAgIE1hdFNlbGVjdCxcbiAgICBNYXRPcHRpb24sXG4gICAgVGltZXpvbmVTZWxlY3RDb21wb25lbnQsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIFJlcG9ydFNldHRpbmdzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBwdWJsaWMgc2VsZWN0ZWRUYWIgPSAnc2V0dGluZ3MnO1xuXG4gIHB1YmxpYyBuYW1lID0gJyc7XG4gIC8vIFRoZSBwYWdlIGluIGluY2hlcy4gTm8gaW5pdGlhbGl6ZXI6IGV2ZXJ5IHJlcG9ydCBjYXJyaWVzIGEgc2l6ZSwgYW5kXG4gIC8vIG5nT25Jbml0IHNlZWRzIGJvdGggYmVmb3JlIHRoZSB0YWIgcmVuZGVycywgc28gYSBwbGFjZWhvbGRlciBoZXJlIGNvdWxkIG9ubHlcbiAgLy8gZXZlciBiZSBhIHdyb25nIG51bWJlciBicmllZmx5IHNob3dpbmcgYXMgdGhlIG9wZXJhdG9yJ3Mgb3duLlxuICAvL1xuICAvLyBUeXBlZCBgbnVtYmVyIHwgc3RyaW5nYCBiZWNhdXNlIGZzTWFza051bWJlciBpcyB0aGUgY29udHJvbDogaXQgaXMgc2VlZGVkXG4gIC8vIHdpdGggdGhlIHJlcG9ydCdzIG51bWJlciBidXQgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgU1RSSU5HIHRoZSBvcGVyYXRvclxuICAvLyB0eXBlZC4gU2F2ZSBjYXN0cyBpdCBvbmNlLCBvbiB0aGUgd2F5IG91dCDigJQgc2VlIGBfcGFnZURpbWVuc2lvbigpYC5cbiAgcHVibGljIHBhZ2VXaWR0aDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcGFnZUhlaWdodDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcGFnZURpbWVuc2lvbk1pbiA9IFBBR0VfRElNRU5TSU9OX01JTjtcbiAgcHVibGljIHJlYWRvbmx5IHBhZ2VEaW1lbnNpb25NYXggPSBQQUdFX0RJTUVOU0lPTl9NQVg7XG4gIC8vIFRoZSBoZWFkZXIgYW5kIGZvb3RlciBiYW5kIGRlcHRocywgaW5jaGVzIOKAlCB0eXBlZCBsaWtlIHRoZSBwYWdlIHNpemVcbiAgLy8gYmVjYXVzZSBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayBhIHN0cmluZy5cbiAgcHVibGljIGhlYWRlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIGZvb3RlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIHJlYWRvbmx5IGhlYWRlckZvb3Rlck1heCA9IEhFQURFUl9GT09URVJfTUFYO1xuICAvLyBTZWVkZWQgd2l0aCB0aGUgem9uZSB0aGUgcmVwb3J0IGFjdHVhbGx5IHVzZXM6IGl0cyBvd24gc3RvcmVkIHpvbmUsIGVsc2VcbiAgLy8gdGhlIGFwcGxpY2F0aW9uIGRlZmF1bHQgdGhlIHNlcnZlciByZXNvbHZlZCAoZWZmZWN0aXZlVGltZXpvbmUpLiBTYXZlIHNlbmRzXG4gIC8vIGl0IG9ubHkgd2hlbiBpdCBkaWZmZXJzIGZyb20gdGhhdCBlZmZlY3RpdmUgem9uZSwgc28gb3BlbmluZyBhbmQgc2F2aW5nIGFcbiAgLy8gcmVwb3J0IHRoYXQgZm9sbG93cyB0aGUgZGVmYXVsdCBuZXZlciBwaW5zIGl0IHRvIGEgem9uZS5cbiAgcHVibGljIHRpbWV6b25lID0gJyc7XG4gIHB1YmxpYyBoZWFkaW5nU2l6ZSA9IERFRkFVTFRfSEVBRElOR19TSVpFO1xuXG4gIC8vIFRoZSBsb2NhbGVzIGFuZCBjdXJyZW5jaWVzIHRoZSBzZXJ2ZXIgb2ZmZXJzLiBudWxsIHVudGlsIGxvYWRlZCwgYW5kXG4gIC8vIG5ldmVyIGxvYWRlZCBmcm9tIGEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCBlZmZlY3RpdmVMb2NhbGU6IHRoZXJlIHRoZVxuICAvLyBzZWxlY3RzIHN0YXkgaGlkZGVuIGFuZCB0aGUgcmVwb3J0IHJlYWRzIGVuLVVTL1VTRC5cbiAgcHVibGljIHJlYWRvbmx5IGxvY2FsZXMgPSBzaWduYWw8UmVwb3J0TG9jYWxlcyB8IG51bGw+KG51bGwpO1xuICAvLyBUaGUgcmVwb3J0J3Mgb3duIGxvY2FsZSBhbmQgY3VycmVuY3ksICcnIHdoZW4gaXQgZm9sbG93cyB0aGUgZGVmYXVsdC4gU2F2ZVxuICAvLyBzZW5kcyBlYWNoIG9ubHkgd2hlbiBpdCBkaWZmZXJzIGZyb20gdGhlIHN0b3JlZCB2YWx1ZS5cbiAgcHVibGljIHJlYWRvbmx5IGxvY2FsZSA9IHNpZ25hbCgnJyk7XG4gIHB1YmxpYyByZWFkb25seSBjdXJyZW5jeSA9IHNpZ25hbCgnJyk7XG4gIC8vIFRoZSB3aG9sZSBmb3JtIHdhaXRzIGJlaGluZCBvbmUgc2tlbGV0b24gdW50aWwgdGhlIGZpbHRlciByb3dzIGFyZSBidWlsdFxuICAvLyBhbmQgdGhlIGxvY2FsZSByZXF1ZXN0IGhhcyBzZXR0bGVkLCBzbyB0aGUgU2V0dGluZ3MgdGFiIG5ldmVyIHNob3dzXG4gIC8vIHdpdGhvdXQgaXRzIExvY2FsZSBhbmQgQ3VycmVuY3kgc2VsZWN0cy4gQSBmYWlsZWQgbG9jYWxlIHJlcXVlc3Qgc2V0dGxlc1xuICAvLyB0b286IHRoZSB0d28gc2VsZWN0cyBzdGF5IGhpZGRlbiAobG9jYWxlcygpIGlzIHN0aWxsIG51bGwpIGFuZCBldmVyeSBvdGhlclxuICAvLyBzZXR0aW5nIHN0YXlzIGVkaXRhYmxlLlxuICBwdWJsaWMgcmVhZG9ubHkgcmVhZHkgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9maWx0ZXJzUmVhZHkoKSAmJiAoIXRoaXMuX3NlcnZlckhhc0xvY2FsZSB8fCB0aGlzLl9sb2NhbGVzU2V0dGxlZCgpKSk7XG5cbiAgLy8gQW4gZXhwbGljaXQgRGVmYXVsdCAoJycpIG5hbWluZyB0aGUgbG9jYWxlIGl0IHN0YW5kcyBmb3IsIHRoZW4gZWFjaCBvZmZlcmVkXG4gIC8vIGxvY2FsZS4gQSBzdG9yZWQgbG9jYWxlIHRoZSBzZXJ2ZXIgbm8gbG9uZ2VyIG9mZmVycyBpcyBsaXN0ZWQgZmlyc3QsIHNvXG4gIC8vIHRoZSBzZWxlY3Qgc3RpbGwgc2hvd3Mgd2hhdCB0aGUgcmVwb3J0IGhvbGRzLlxuICBwdWJsaWMgcmVhZG9ubHkgbG9jYWxlT3B0aW9ucyA9IGNvbXB1dGVkPExvY2FsZVNlbGVjdE9wdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGlmICghbG9jYWxlcykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IG9mZmVyZWQgPSBsb2NhbGVzLm9wdGlvbnMubWFwKChvcHRpb24pID0+IG9wdGlvbi5sb2NhbGUpO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIC4uLnRoaXMuX3N0b3JlZE9wdGlvbih0aGlzLl9kYXRhLnJlcG9ydC5sb2NhbGUsIG9mZmVyZWQsIGxvY2FsZUxhYmVsKSxcbiAgICAgIHsgdmFsdWU6ICcnLCBsYWJlbDogYERlZmF1bHQg4oCUICR7bG9jYWxlTmFtZShsb2NhbGVzLmRlZmF1bHRMb2NhbGUpfWAgfSxcbiAgICAgIC4uLm9mZmVyZWQubWFwKCh0YWcpID0+ICh7IHZhbHVlOiB0YWcsIGxhYmVsOiBsb2NhbGVMYWJlbCh0YWcpIH0pKSxcbiAgICBdO1xuICB9KTtcblxuICAvLyBBbiBleHBsaWNpdCBEZWZhdWx0ICgnJykgbmFtaW5nIHRoZSBjdXJyZW5jeSB0aGUgc2VsZWN0ZWQgbG9jYWxlIHVzZXMgd2hlblxuICAvLyB0aGUgcmVwb3J0IG5hbWVzIG5vbmUsIHRoZW4gZXZlcnkgY3VycmVuY3kuIEEgc3RvcmVkIGNvZGUgdGhlIHNlcnZlciBub1xuICAvLyBsb25nZXIgb2ZmZXJzIGlzIGxpc3RlZCBmaXJzdC5cbiAgcHVibGljIHJlYWRvbmx5IGN1cnJlbmN5T3B0aW9ucyA9IGNvbXB1dGVkPExvY2FsZVNlbGVjdE9wdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGlmICghbG9jYWxlcykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiBbXG4gICAgICAuLi50aGlzLl9zdG9yZWRPcHRpb24odGhpcy5fZGF0YS5yZXBvcnQuY3VycmVuY3ksIGxvY2FsZXMuY3VycmVuY2llcywgY3VycmVuY3lMYWJlbCksXG4gICAgICB7IHZhbHVlOiAnJywgbGFiZWw6IGBEZWZhdWx0IOKAlCAke2N1cnJlbmN5TGFiZWwodGhpcy5fZGVmYXVsdEN1cnJlbmN5KCkpfWAgfSxcbiAgICAgIC4uLmxvY2FsZXMuY3VycmVuY2llcy5tYXAoKGNvZGUpID0+ICh7IHZhbHVlOiBjb2RlLCBsYWJlbDogY3VycmVuY3lMYWJlbChjb2RlKSB9KSksXG4gICAgXTtcbiAgfSk7XG5cbiAgLy8gSG93IHRoZSByZXBvcnQgd2lsbCB3cml0ZSBhbiBhbW91bnQgYW5kIGEgZGF5IG9uY2Ugc2F2ZWQ6IHRoZSBzZWxlY3RlZFxuICAvLyBsb2NhbGUgYW5kIGN1cnJlbmN5LCBvciB0aGUgZGVmYXVsdHMgdGhleSBmYWxsIGJhY2sgdG8sIGUuZy5cbiAgLy8gJzEgMjM0LDUwICQgwrcgNSBqYW52LiAyMDI2JyBpbiBmci1DQS5cbiAgcHVibGljIHJlYWRvbmx5IGZvcm1hdEV4YW1wbGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlID0gcmVzb2x2ZVJlcG9ydExvY2FsZSh0aGlzLl9hcHBsaWVkTG9jYWxlKCkpO1xuICAgIGNvbnN0IGN1cnJlbmN5ID0gcmVzb2x2ZVJlcG9ydEN1cnJlbmN5KHRoaXMuX2FwcGxpZWRDdXJyZW5jeSgpKTtcblxuICAgIHJldHVybiBbXG4gICAgICBmb3JtYXROdW1iZXIoXG4gICAgICAgIEVYQU1QTEVfQU1PVU5ULFxuICAgICAgICB7IGZvcm1hdDogUmVwb3J0VmFsdWVGb3JtYXQuQ3VycmVuY3ksIHByZWNpc2lvbjogMiB9LFxuICAgICAgICB7IGxvY2FsZSwgY3VycmVuY3ksIHJhdGlvUGVyY2VudDogdHJ1ZSB9LFxuICAgICAgKSxcbiAgICAgIGZvcm1hdExvY2FsRGF0ZShFWEFNUExFX0RBWSwgbG9jYWxlLCBEQVlfU0hPUlQpLFxuICAgIF0uam9pbignIMK3ICcpO1xuICB9KTtcblxuICAvLyBUaGUgcmVwb3J0LWxldmVsIGZpbHRlcnMgYW5kIHRoZWlyIGVkaXRhYmxlIGRlZmF1bHQgdmFsdWVzIChGaWx0ZXJzIHRhYikuXG4gIHB1YmxpYyByZWFkb25seSBmaWx0ZXJSb3dzID0gc2lnbmFsPEZpbHRlckRlZmF1bHRSb3dbXT4oW10pO1xuICBwdWJsaWMgcmVhZG9ubHkgcmVsYXRpdmVMYWJlbCA9IHJlbGF0aXZlTGFiZWw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfZGF0YTogeyByZXBvcnQ6IFJlcG9ydCB9ID0gaW5qZWN0KE1BVF9ESUFMT0dfREFUQSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RpYWxvZ1JlZiA9IGluamVjdDxNYXREaWFsb2dSZWY8UmVwb3J0U2V0dGluZ3NDb21wb25lbnQsIFJlcG9ydFNldHRpbmdzUmVzdWx0Pj4oTWF0RGlhbG9nUmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbWVzc2FnZSA9IGluamVjdChGc01lc3NhZ2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9wcm9tcHQgPSBpbmplY3QoRnNQcm9tcHQpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuICAvLyBPbmx5IGEgc2VydmVyIHRoYXQgcmVzb2x2ZXMgYSByZXBvcnQncyBsb2NhbGUgb2ZmZXJzIHRoZSBsb2NhbGUgbGlzdC5cbiAgcHJpdmF0ZSByZWFkb25seSBfc2VydmVySGFzTG9jYWxlID0gdGhpcy5fZGF0YS5yZXBvcnQuZWZmZWN0aXZlTG9jYWxlICE9PSB1bmRlZmluZWQ7XG4gIC8vIFRydWUgb25jZSB0aGUgbG9jYWxlIHJlcXVlc3QgaGFzIGFuc3dlcmVkLCB3aXRoIHRoZSBsaXN0IG9yIGFuIGVycm9yLlxuICBwcml2YXRlIHJlYWRvbmx5IF9sb2NhbGVzU2V0dGxlZCA9IHNpZ25hbChmYWxzZSk7XG4gIC8vIFRydWUgb25jZSB0aGUgZmlsdGVyIHJvd3MgYXJlIHB1Ymxpc2hlZCAoc2VlIF9idWlsZEZpbHRlclJvd3MpLlxuICBwcml2YXRlIHJlYWRvbmx5IF9maWx0ZXJzUmVhZHkgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8vIFRoZSBsb2NhbGUgdGhlIHJlcG9ydCB3b3VsZCBiZSB3cml0dGVuIGluOiB0aGUgc2VsZWN0ZWQgb25lIHdoZW4gdGhlXG4gIC8vIHNlcnZlciBvZmZlcnMgaXQsIGVsc2UgdGhlIGRlZmF1bHQgKGEgc3RvcmVkIGxvY2FsZSBpdCBubyBsb25nZXIgb2ZmZXJzXG4gIC8vIGZhbGxzIGJhY2sgdG8gdGhlIGRlZmF1bHQsIGFzIGl0IGRvZXMgb24gdGhlIHNlcnZlcikuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2FwcGxpZWRMb2NhbGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGNvbnN0IGxvY2FsZSA9IHRoaXMubG9jYWxlKCk7XG5cbiAgICByZXR1cm4gbG9jYWxlcz8ub3B0aW9ucy5zb21lKChvcHRpb24pID0+IG9wdGlvbi5sb2NhbGUgPT09IGxvY2FsZSlcbiAgICAgID8gbG9jYWxlXG4gICAgICA6IGxvY2FsZXM/LmRlZmF1bHRMb2NhbGUgPz8gJyc7XG4gIH0pO1xuXG4gIC8vIFRoZSBjdXJyZW5jeSBhIHJlcG9ydCBpbiB0aGUgYXBwbGllZCBsb2NhbGUgdXNlcyB3aGVuIGl0IG5hbWVzIG5vbmUuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2RlZmF1bHRDdXJyZW5jeSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBsb2NhbGUgPSB0aGlzLl9hcHBsaWVkTG9jYWxlKCk7XG5cbiAgICByZXR1cm4gdGhpcy5sb2NhbGVzKCk/Lm9wdGlvbnMuZmluZCgob3B0aW9uKSA9PiBvcHRpb24ubG9jYWxlID09PSBsb2NhbGUpPy5kZWZhdWx0Q3VycmVuY3lcbiAgICAgID8/IFJFUE9SVF9GQUxMQkFDS19DVVJSRU5DWTtcbiAgfSk7XG5cbiAgLy8gVGhlIGN1cnJlbmN5IHRoZSByZXBvcnQgd291bGQgbGFiZWwgbW9uZXkgaW46IHRoZSBzZWxlY3RlZCBvbmUgd2hlbiB0aGVcbiAgLy8gc2VydmVyIG9mZmVycyBpdCwgZWxzZSB0aGUgZGVmYXVsdC5cbiAgcHJpdmF0ZSByZWFkb25seSBfYXBwbGllZEN1cnJlbmN5ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGN1cnJlbmN5ID0gdGhpcy5jdXJyZW5jeSgpO1xuXG4gICAgcmV0dXJuIHRoaXMubG9jYWxlcygpPy5jdXJyZW5jaWVzLmluY2x1ZGVzKGN1cnJlbmN5KVxuICAgICAgPyBjdXJyZW5jeVxuICAgICAgOiB0aGlzLl9kZWZhdWx0Q3VycmVuY3koKTtcbiAgfSk7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IHJlcG9ydCA9IHRoaXMuX2RhdGEucmVwb3J0O1xuICAgIHRoaXMubmFtZSA9IHJlcG9ydC5uYW1lO1xuICAgIHRoaXMucGFnZVdpZHRoID0gcmVwb3J0LnBhZ2VXaWR0aDtcbiAgICB0aGlzLnBhZ2VIZWlnaHQgPSByZXBvcnQucGFnZUhlaWdodDtcbiAgICB0aGlzLmhlYWRlckhlaWdodCA9IHJlcG9ydC5jb25maWc/LmhlYWRlckZvb3Rlcj8uaGVhZGVySGVpZ2h0ID8/IDA7XG4gICAgdGhpcy5mb290ZXJIZWlnaHQgPSByZXBvcnQuY29uZmlnPy5oZWFkZXJGb290ZXI/LmZvb3RlckhlaWdodCA/PyAwO1xuICAgIHRoaXMudGltZXpvbmUgPSByZXBvcnQudGltZXpvbmUgPz8gcmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lID8/ICcnO1xuICAgIHRoaXMuaGVhZGluZ1NpemUgPSByZXBvcnQuY29uZmlnPy5zdHlsZXM/LmhlYWRpbmc/LnNpemUgPz8gREVGQVVMVF9IRUFESU5HX1NJWkU7XG4gICAgdGhpcy5sb2NhbGUuc2V0KHJlcG9ydC5sb2NhbGUgPz8gJycpO1xuICAgIHRoaXMuY3VycmVuY3kuc2V0KHJlcG9ydC5jdXJyZW5jeSA/PyAnJyk7XG5cbiAgICB0aGlzLl9idWlsZEZpbHRlclJvd3MocmVwb3J0KTtcblxuICAgIGlmICh0aGlzLl9zZXJ2ZXJIYXNMb2NhbGUpIHtcbiAgICAgIHRoaXMuX3JlcG9ydERhdGEubG9jYWxlcygpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHRhcCgobG9jYWxlcykgPT4gdGhpcy5sb2NhbGVzLnNldChsb2NhbGVzKSksXG4gICAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBvZihudWxsKSksXG4gICAgICAgICAgZmluYWxpemUoKCkgPT4gdGhpcy5fbG9jYWxlc1NldHRsZWQuc2V0KHRydWUpKSxcbiAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIENvbmZpcm0gYW5kIGRlbGV0ZSBoZXJlLCB3aGlsZSB0aGUgZGlhbG9nIGlzIHN0aWxsIG9wZW4sIHRoZW4gY2xvc2Ugd2l0aFxuICAvLyBhIGBkZWxldGVkYCByZXN1bHQuIFRoZSBwYWdlIHJlYWN0cyB0byB0aGUgcmVzdWx0OyBpdCBubyBsb25nZXIgb3ducyB0aGVcbiAgLy8gcHJvbXB0IG9yIHRoZSBBUEkgY2FsbC5cbiAgcHVibGljIGRlbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9wcm9tcHQuY29uZmlybSh7XG4gICAgICB0aXRsZTogJ0RlbGV0ZSBSZXBvcnQnLFxuICAgICAgdGVtcGxhdGU6IGBEZWxldGUgXCIke3RoaXMuX2RhdGEucmVwb3J0Lm5hbWV9XCI/IFRoaXMgY2Fubm90IGJlIHVuZG9uZS5gLFxuICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlKHRoaXMuX2RhdGEucmVwb3J0LmlkKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3MoJ1JlcG9ydCBkZWxldGVkJyk7XG4gICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZSh7IGFjdGlvbjogJ2RlbGV0ZWQnIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc2F2ZSA9ICgpID0+IHtcbiAgICBjb25zdCByZXBvcnRJZCA9IHRoaXMuX2RhdGEucmVwb3J0LmlkO1xuXG4gICAgLy8gUGVyc2lzdCB0aGUgcmVwb3J0IHNldHRpbmdzIGFuZCBlYWNoIGNoYW5nZWQgZmlsdGVyIGRlZmF1bHQgdG9nZXRoZXIsIHNvXG4gICAgLy8gdGhlIHNpbmdsZSBTYXZlIGNvdmVycyBhbGwgdGhyZWUgdGFicy4gVGhlIHJlcG9ydCByZWxvYWRzIG9uIHRoZSBgc2F2ZWRgXG4gICAgLy8gcmVzdWx0LCByZS1zZWVkaW5nIHRoZSBiYXIgZnJvbSB0aGUgbmV3IGRlZmF1bHRzLlxuICAgIGNvbnN0IHNldHRpbmdzJCA9IHRoaXMuX3JlcG9ydERhdGEudXBkYXRlKHJlcG9ydElkLCB7XG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBwYWdlV2lkdGg6IHRoaXMuX3BhZ2VEaW1lbnNpb24odGhpcy5wYWdlV2lkdGgpLFxuICAgICAgcGFnZUhlaWdodDogdGhpcy5fcGFnZURpbWVuc2lvbih0aGlzLnBhZ2VIZWlnaHQpLFxuICAgICAgLi4udGhpcy5fdGltZXpvbmVTZXR0aW5nKCksXG4gICAgICAuLi5yZXBvcnRMb2NhbGVQYXRjaCh0aGlzLl9kYXRhLnJlcG9ydCwgdGhpcy5sb2NhbGUoKSwgdGhpcy5jdXJyZW5jeSgpKSxcbiAgICAgIHN0eWxlczogeyBoZWFkaW5nOiB7IHNpemU6IHRoaXMuaGVhZGluZ1NpemUgfSB9LFxuICAgICAgaGVhZGVyRm9vdGVyOiB7XG4gICAgICAgIGhlYWRlckhlaWdodDogdGhpcy5fcGFnZURpbWVuc2lvbih0aGlzLmhlYWRlckhlaWdodCkgfHwgMCxcbiAgICAgICAgZm9vdGVySGVpZ2h0OiB0aGlzLl9wYWdlRGltZW5zaW9uKHRoaXMuZm9vdGVySGVpZ2h0KSB8fCAwLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRzJCA9IHRoaXMuZmlsdGVyUm93cygpXG4gICAgICAuZmlsdGVyKChyb3cpID0+IHRoaXMuX2RlZmF1bHRDaGFuZ2VkKHJvdykpXG4gICAgICAubWFwKChyb3cpID0+IHRoaXMuX3JlcG9ydERhdGEudXBkYXRlRmlsdGVyR3JvdXAocmVwb3J0SWQsIHJvdy5ncm91cC5pZCwge1xuICAgICAgICBkZWZhdWx0OiB0aGlzLl9yb3dEZWZhdWx0KHJvdyksXG4gICAgICB9KSk7XG5cbiAgICByZXR1cm4gZm9ya0pvaW4oW3NldHRpbmdzJCwgLi4uZGVmYXVsdHMkXSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnUmVwb3J0IHNldHRpbmdzIHNhdmVkJyk7XG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgYWN0aW9uOiAnc2F2ZWQnIH0pO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH07XG5cbiAgLy8gRHJvcCB0aGUgcm93J3Mgc3RvcmVkIHJvbGxpbmcgcHJlc2V0IChDbGVhcikuIEEgbmV3IHJvdyBvYmplY3QgcmF0aGVyIHRoYW5cbiAgLy8gYSBtdXRhdGlvbiwgc28gdGhlIHNpZ25hbCBzZWVzIHRoZSBjaGFuZ2U7IHRoZSBAZm9yIHRyYWNrcyBncm91cC5pZCwgc29cbiAgLy8gdGhlIHJvdydzIGJpbmRpbmdzIHN1cnZpdmUgdGhlIHN3YXAuXG4gIHB1YmxpYyBjbGVhclJlbGF0aXZlKHJvdzogRmlsdGVyRGVmYXVsdFJvdyk6IHZvaWQge1xuICAgIHRoaXMuZmlsdGVyUm93cy51cGRhdGUoKHJvd3MpID0+IHJvd3MubWFwKChpdGVtKSA9PiAoaXRlbSA9PT0gcm93ID8geyAuLi5pdGVtLCByZWxhdGl2ZTogbnVsbCB9IDogaXRlbSkpKTtcbiAgfVxuXG4gIC8vIFRoZSBwYWdlIGRpbWVuc2lvbiBhcyBhIHJlYWwgbnVtYmVyIGZvciB0aGUgd2lyZS4gZnNNYXNrTnVtYmVyIGhhbmRzIGJhY2tcbiAgLy8gdGhlIHVubWFza2VkIHN0cmluZyBpdCBidWlsdCB3aXRoIGEgZml4ZWQgJy4nIHJhZGl4ICh3aGljaCBpcyB0aGUgd2hvbGVcbiAgLy8gcG9pbnQgb2YgdGhlIG1hc2sgLSBhIG5hdGl2ZSBudW1iZXIgaW5wdXQgcGFpbnRzIHRoZSB2aWV3ZXIncyBsb2NhbGVcbiAgLy8gc2VwYXJhdG9yIGluc3RlYWQpLCBzbyB0aGUgY2FzdCBoZXJlIGlzIGEgc3RyYWlnaHQgcGFyc2UgYW5kIG5ldmVyIHNlZXMgYVxuICAvLyBjb21tYS4gVGhlIGJhY2tlbmQgcmVqZWN0cyBhbnl0aGluZyBub24tbnVtZXJpYyByYXRoZXIgdGhhbiBjb2VyY2luZywgc28gYVxuICAvLyBOYU4gZmFpbHMgbG91ZGx5IGluc3RlYWQgb2Ygc2lsZW50bHkgc3RvcmluZyBhIHdyb25nIHBhZ2Ugc2l6ZS5cbiAgcHJpdmF0ZSBfcGFnZURpbWVuc2lvbih2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyA/IHZhbHVlIDogcGFyc2VGbG9hdCh2YWx1ZSk7XG4gIH1cblxuICAvLyBUaGUgem9uZSBmb3IgdGhlIHNldHRpbmdzIFBVVCwgc2VudCBvbmx5IHdoZW4gaXQgbW92ZXMgdGhlIHJlcG9ydCBvZmYgdGhlXG4gIC8vIHpvbmUgaXQgYWxyZWFkeSB1c2VzLCBzbyBhbiB1bnRvdWNoZWQgZGlhbG9nIG5ldmVyIHBpbnMgYSByZXBvcnQgdGhhdFxuICAvLyBmb2xsb3dzIHRoZSBhcHBsaWNhdGlvbiBkZWZhdWx0LiBBIHNlcnZlciB0b28gb2xkIHRvIHNlbmRcbiAgLy8gZWZmZWN0aXZlVGltZXpvbmUgZ2V0cyB0aGUgem9uZSBldmVyeSB0aW1lLCBhcyBpdCBhbHdheXMgZGlkLlxuICBwcml2YXRlIF90aW1lem9uZVNldHRpbmcoKTogeyB0aW1lem9uZT86IHN0cmluZyB9IHtcbiAgICBjb25zdCBlZmZlY3RpdmVUaW1lem9uZSA9IHRoaXMuX2RhdGEucmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lO1xuXG4gICAgcmV0dXJuIGVmZmVjdGl2ZVRpbWV6b25lID09PSB1bmRlZmluZWQgfHwgdGhpcy50aW1lem9uZSAhPT0gZWZmZWN0aXZlVGltZXpvbmVcbiAgICAgID8geyB0aW1lem9uZTogdGhpcy50aW1lem9uZSB9XG4gICAgICA6IHt9O1xuICB9XG5cbiAgLy8gVGhlIHN0b3JlZCB2YWx1ZSBhcyBpdHMgb3duIG9wdGlvbiB3aGVuIHRoZSBzZXJ2ZXIgbm8gbG9uZ2VyIG9mZmVycyBpdCwgc29cbiAgLy8gdGhlIHNlbGVjdCBuYW1lcyBpdCBpbnN0ZWFkIG9mIHNob3dpbmcgYmxhbmsuIExlZnQgYXMgaXQgaXMsIGl0IGlzIG5ldmVyXG4gIC8vIHNlbnQgKHNlZSByZXBvcnRMb2NhbGVQYXRjaCksIGFuZCB0aGUgcmVwb3J0IHJlYWRzIHRoZSBkZWZhdWx0IG1lYW53aGlsZS5cbiAgcHJpdmF0ZSBfc3RvcmVkT3B0aW9uKFxuICAgIHN0b3JlZDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgICBvZmZlcmVkOiBzdHJpbmdbXSxcbiAgICBsYWJlbDogKHZhbHVlOiBzdHJpbmcpID0+IHN0cmluZyxcbiAgKTogTG9jYWxlU2VsZWN0T3B0aW9uW10ge1xuICAgIHJldHVybiBzdG9yZWQgJiYgIW9mZmVyZWQuaW5jbHVkZXMoc3RvcmVkKSA/IFt7IHZhbHVlOiBzdG9yZWQsIGxhYmVsOiBsYWJlbChzdG9yZWQpIH1dIDogW107XG4gIH1cblxuICAvLyBCdWlsZCBvbmUgZWRpdGFibGUgcm93IHBlciByZXBvcnQtbGV2ZWwgZmlsdGVyIGdyb3VwIChsZXZlbCByZXBvcnQgb3IgYm90aCksXG4gIC8vIGluIGJhciBvcmRlciwgc2VlZGluZyBlYWNoIGRyYWZ0IGZyb20gdGhlIGdyb3VwJ3Mgc3RvcmVkIGRlZmF1bHQuXG4gIHByaXZhdGUgX2J1aWxkRmlsdGVyUm93cyhyZXBvcnQ6IFJlcG9ydCk6IHZvaWQge1xuICAgIGNvbnN0IHJlcG9ydElkID0gcmVwb3J0LmlkO1xuXG4gICAgY29uc3QgYnVpbHQgPSAocmVwb3J0LmZpbHRlckdyb3VwcyA/PyBbXSlcbiAgICAgIC5maWx0ZXIoKGdyb3VwKSA9PiBncm91cC5sZXZlbCA9PT0gJ3JlcG9ydCcgfHwgZ3JvdXAubGV2ZWwgPT09ICdib3RoJylcbiAgICAgIC5zb3J0KChhLCBiKSA9PiBhLm9yZGVyIC0gYi5vcmRlcilcbiAgICAgIC5tYXAoKGdyb3VwKSA9PiB7XG4gICAgICAgIGNvbnN0IGdyb3VwRGVmYXVsdCA9IGdyb3VwLmNvbmZpZz8uZGVmYXVsdDtcbiAgICAgICAgLy8gT25lIHNoYXJlZCwgcmVwbGF5ZWQgb3B0aW9uIHN0cmVhbSBwZXIgZ3JvdXA6IHRoZSBjaGlwcyBmZXRjaCBhbmQgdGhlXG4gICAgICAgIC8vIHN0b3JlZCBkZWZhdWx0J3MgbGFiZWxzIHJlYWQgdGhlIHNhbWUgbGlzdCwgc28gaXQgaXMgZmV0Y2hlZCBvbmNlLlxuICAgICAgICBjb25zdCBvcHRpb25zJCA9IGxvYWRHcm91cE9wdGlvbnMoZ3JvdXAsIHRoaXMuX3JlcG9ydERhdGEsIHJlcG9ydElkKTtcblxuICAgICAgICBjb25zdCByb3c6IEZpbHRlckRlZmF1bHRSb3cgPSB7XG4gICAgICAgICAgZ3JvdXAsXG4gICAgICAgICAgbGFiZWw6IGdyb3VwLmxhYmVsIHx8IGdyb3VwLmZpbHRlcnM/LlswXT8uZmlsdGVyQ29sdW1uIHx8ICdGaWx0ZXInLFxuICAgICAgICAgIHN0YXJ0OiBkYXRlRnJvbUJvdW5kKGdyb3VwRGVmYXVsdD8uc3RhcnQpLFxuICAgICAgICAgIGVuZDogZGF0ZUZyb21Cb3VuZChncm91cERlZmF1bHQ/LmVuZCksXG4gICAgICAgICAgcmVsYXRpdmU6IGdyb3VwRGVmYXVsdD8ucmVsYXRpdmUgPz8gbnVsbCxcbiAgICAgICAgICAvLyBOYW1lZCBiZWxvdywgb25jZSB0aGUgb3B0aW9uIGxpc3QgY2FycnlpbmcgdGhlaXIgbGFiZWxzIGlzIGluLlxuICAgICAgICAgIHZhbHVlczogW10sXG4gICAgICAgICAgdmFsdWU6IGdyb3VwRGVmYXVsdD8udmFsdWUgPz8gJycsXG4gICAgICAgICAgLy8gZnMtYXV0b2NvbXBsZXRlLWNoaXBzIGZldGNoOiB0aGUgZ3JvdXAncyBkaXN0aW5jdCBvcHRpb25zLCBuYW1lLWZpbHRlcmVkLlxuICAgICAgICAgIC8vIFNhbWUgbG9hZGVyIHRoZSByZXBvcnQgYmFyIHVzZXMsIHNvIHRoZSB0d28gbmV2ZXIgZHJpZnQuXG4gICAgICAgICAgZmV0Y2g6IChrZXl3b3JkPzogc3RyaW5nKSA9PiBtYXRjaE9wdGlvbnMob3B0aW9ucyQsIGtleXdvcmQpLFxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB7IHJvdywgb3B0aW9ucyQsIHZhbHVlczogZ3JvdXBEZWZhdWx0Py52YWx1ZXMgPz8gW10gfTtcbiAgICAgIH0pO1xuXG4gICAgY29uc3Qgcm93cyA9IGJ1aWx0Lm1hcCgoZW50cnkpID0+IGVudHJ5LnJvdyk7XG4gICAgY29uc3Qgc2VlZGVkID0gYnVpbHQuZmlsdGVyKChlbnRyeSkgPT4gZW50cnkudmFsdWVzLmxlbmd0aCk7XG5cbiAgICAvLyBOb3RoaW5nIHRvIG5hbWUg4oCUIHB1Ymxpc2ggaW1tZWRpYXRlbHkgcmF0aGVyIHRoYW4gd2FpdGluZyBvbiBhIHJlcXVlc3RcbiAgICAvLyBubyByb3cgbmVlZHMuXG4gICAgaWYgKCFzZWVkZWQubGVuZ3RoKSB7XG4gICAgICB0aGlzLl9wdWJsaXNoRmlsdGVyUm93cyhyb3dzKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEEgc3RvcmVkIHNlbGVjdCBkZWZhdWx0IGhvbGRzIGlkcywgc28gaXRzIGNoaXBzIGNhbiBvbmx5IGJlIG5hbWVkIG9uY2UgdGhlXG4gICAgLy8gb3B0aW9uIGxpc3QgaXMgaW4uIFJlc29sdmUgZXZlcnkgc2VlZGVkIHJvdyBmaXJzdCBhbmQgcHVibGlzaCB0aGUgcm93cyBpblxuICAgIC8vIG9uZSBnbywgc28gdGhlIHRhYiBuZXZlciByZW5kZXJzIGEgY2hpcCBzaG93aW5nIGEgcmF3IGlkLiBXaGVuIGFuIG9wdGlvblxuICAgIC8vIGxpc3QgZmFpbHMgdG8gbG9hZCwgdGhlIHJvd3MgcHVibGlzaCB1bnJlc29sdmVkOiBlYWNoIGNoaXAgbmFtZXMgaXRzIGlkLFxuICAgIC8vIGFuZCBhbiB1bnRvdWNoZWQgcm93IHN0aWxsIHNhdmVzIHRoZSBzdG9yZWQgZGVmYXVsdCB1bmNoYW5nZWQuXG4gICAgZm9ya0pvaW4oc2VlZGVkLm1hcCgoZW50cnkpID0+IHJlc29sdmVPcHRpb25WYWx1ZXMoZW50cnkub3B0aW9ucyQsIGVudHJ5LnZhbHVlcykpKVxuICAgICAgLnBpcGUoXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4gb2Yoc2VlZGVkLm1hcCgoZW50cnkpID0+IGVudHJ5LnZhbHVlcy5tYXAoKHZhbHVlKSA9PiAoeyBuYW1lOiBTdHJpbmcodmFsdWUpLCB2YWx1ZSB9KSkpKSksXG4gICAgICAgIHRhcCgocmVzb2x2ZWQpID0+IHtcbiAgICAgICAgICByZXNvbHZlZC5mb3JFYWNoKCh2YWx1ZXMsIGluZGV4KSA9PiBzZWVkZWRbaW5kZXhdLnJvdy52YWx1ZXMgPSB2YWx1ZXMpO1xuICAgICAgICAgIHRoaXMuX3B1Ymxpc2hGaWx0ZXJSb3dzKHJvd3MpO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcHVibGlzaEZpbHRlclJvd3Mocm93czogRmlsdGVyRGVmYXVsdFJvd1tdKTogdm9pZCB7XG4gICAgdGhpcy5maWx0ZXJSb3dzLnNldChyb3dzKTtcbiAgICB0aGlzLl9maWx0ZXJzUmVhZHkuc2V0KHRydWUpO1xuICB9XG5cbiAgLy8gVGhlIGRyYWZ0IGRlZmF1bHQgbm9ybWFsaXplZCB0byB0aGUgd2lyZSBzaGFwZSBmb3IgdGhpcyByb3cncyB0eXBlLCBvciBudWxsXG4gIC8vIHdoZW4gZW1wdHkgKHdoaWNoIGNsZWFycyB0aGUgc3RvcmVkIGRlZmF1bHQpLiBBIGRhdGUgcmFuZ2UgaXMgdGhlIHBpY2tlZFxuICAvLyBkYXRlcyB3aGVuIHRoZXJlIGFyZSBhbnksIGVsc2UgdGhlIGNhcnJpZWQgcm9sbGluZyBwcmVzZXQsIG5ldmVyIGJvdGg6IHRoZVxuICAvLyBzZXJ2ZXIgcmVmdXNlcyBhIHJlbGF0aXZlIHByZXNldCBjb21iaW5lZCB3aXRoIGRhdGVzLlxuICBwcml2YXRlIF9yb3dEZWZhdWx0KHJvdzogRmlsdGVyRGVmYXVsdFJvdyk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwge1xuICAgIHN3aXRjaCAocm93Lmdyb3VwLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2RhdGVSYW5nZSc6IHtcbiAgICAgICAgY29uc3Qgc3RhcnQgPSBkYXRlVG9Cb3VuZChyb3cuc3RhcnQpO1xuICAgICAgICBjb25zdCBlbmQgPSBkYXRlVG9Cb3VuZChyb3cuZW5kKTtcblxuICAgICAgICBpZiAoc3RhcnQgfHwgZW5kKSB7XG4gICAgICAgICAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0ID8/IHVuZGVmaW5lZCwgZW5kOiBlbmQgPz8gdW5kZWZpbmVkIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcm93LnJlbGF0aXZlID8geyByZWxhdGl2ZTogcm93LnJlbGF0aXZlIH0gOiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjYXNlICdzZWxlY3QnOlxuICAgICAgICByZXR1cm4gcm93LnZhbHVlcy5sZW5ndGggPyB7IHZhbHVlczogcm93LnZhbHVlcy5tYXAoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlKSB9IDogbnVsbDtcblxuICAgICAgY2FzZSAna2V5d29yZCc6XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gcm93LnZhbHVlLnRyaW0oKTtcblxuICAgICAgICByZXR1cm4gdmFsdWUgPyB7IHZhbHVlIH0gOiBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFdoZXRoZXIgdGhlIHJvdydzIGRyYWZ0IGRpZmZlcnMgZnJvbSB0aGUgZ3JvdXAncyBzdG9yZWQgZGVmYXVsdCDigJQgb25seVxuICAvLyBjaGFuZ2VkIHJvd3MgYXJlIHBlcnNpc3RlZCBvbiBTYXZlLlxuICBwcml2YXRlIF9kZWZhdWx0Q2hhbmdlZChyb3c6IEZpbHRlckRlZmF1bHRSb3cpOiBib29sZWFuIHtcbiAgICBjb25zdCBiZWZvcmUgPSBKU09OLnN0cmluZ2lmeSh0aGlzLl9ub3JtYWxpemUocm93Lmdyb3VwLmNvbmZpZz8uZGVmYXVsdCA/PyBudWxsKSk7XG4gICAgY29uc3QgYWZ0ZXIgPSBKU09OLnN0cmluZ2lmeSh0aGlzLl9ub3JtYWxpemUodGhpcy5fcm93RGVmYXVsdChyb3cpKSk7XG5cbiAgICByZXR1cm4gYmVmb3JlICE9PSBhZnRlcjtcbiAgfVxuXG4gIC8vIEEgc3RhYmxlIGNvbXBhcmlzb24gZm9ybTogZW1wdHkgYW5kIHVuZGVmaW5lZCBrZXlzIGFyZSBkcm9wcGVkIHNvIGEgbm8tb3BcbiAgLy8gZWRpdCBkb2Vzbid0IHJlYWQgYXMgYSBjaGFuZ2UuIHJlbGF0aXZlIGlzIGNvbXBhcmVkIGxpa2UgdGhlIHJlc3Q6IHRoZSByb3dcbiAgLy8gY2FycmllcyBpdCwgc28gYW4gdW50b3VjaGVkIHJvbGxpbmcgZGVmYXVsdCByZWFkcyBhcyB1bmNoYW5nZWQuXG4gIHByaXZhdGUgX25vcm1hbGl6ZSh2YWx1ZTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwge1xuICAgIGlmICghdmFsdWUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IG5vcm1hbGl6ZWQ6IEZpbHRlckdyb3VwRGVmYXVsdCA9IHt9O1xuICAgIGlmICh2YWx1ZS5zdGFydCkge1xuICAgICAgbm9ybWFsaXplZC5zdGFydCA9IHZhbHVlLnN0YXJ0O1xuICAgIH1cbiAgICBpZiAodmFsdWUuZW5kKSB7XG4gICAgICBub3JtYWxpemVkLmVuZCA9IHZhbHVlLmVuZDtcbiAgICB9XG4gICAgaWYgKHZhbHVlLnZhbHVlcz8ubGVuZ3RoKSB7XG4gICAgICBub3JtYWxpemVkLnZhbHVlcyA9IHZhbHVlLnZhbHVlcztcbiAgICB9XG4gICAgaWYgKHZhbHVlLnZhbHVlKSB7XG4gICAgICBub3JtYWxpemVkLnZhbHVlID0gdmFsdWUudmFsdWU7XG4gICAgfVxuICAgIGlmICh2YWx1ZS5yZWxhdGl2ZSkge1xuICAgICAgbm9ybWFsaXplZC5yZWxhdGl2ZSA9IHZhbHVlLnJlbGF0aXZlO1xuICAgIH1cblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhub3JtYWxpemVkKS5sZW5ndGggPyBub3JtYWxpemVkIDogbnVsbDtcbiAgfVxufVxuIiwiPGZvcm1cbiAgICBmc0Zvcm1cbiAgICBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8aDEgbWF0LWRpYWxvZy10aXRsZT5cbiAgICAgIFJlcG9ydCBTZXR0aW5nc1xuICAgIDwvaDE+XG4gICAgPG1hdC1kaWFsb2ctY29udGVudD5cbiAgICAgIDwhLS0gT25lIHNrZWxldG9uIG92ZXIgdGhlIHdob2xlIGJvZHkgdW50aWwgdGhlIGxvY2FsZSBsaXN0IGlzIGluLiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgKmZzU2tlbGV0b25Gb3JtPVwicmVhZHkoKSB8fCBudWxsXCI+XG4gICAgICAgIDxtYXQtdGFiLWdyb3VwIFsoc2VsZWN0ZWQpXT1cInNlbGVjdGVkVGFiXCI+XG4gICAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgICAgbGFiZWw9XCJTZXR0aW5nc1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJzZXR0aW5nc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtbiB0YWItYm9keVwiPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIE5hbWVcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm5hbWVcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cIm5hbWVcIlxuICAgICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cInRydWVcIj5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPCEtLVxuICAgICAgICAgICAgICAgIFRoZSBwYWdlLCB0eXBlZCBpbiBpbmNoZXMuIE9yaWVudGF0aW9uIGlzIG5vdCBhc2tlZCBmb3IgYmVjYXVzZSBpdFxuICAgICAgICAgICAgICAgIGlzIG5vdCBhbiBpbmRlcGVuZGVudCBjaG9pY2UgLSBhIHBhZ2Ugd2lkZXIgdGhhbiBpdCBpcyB0YWxsIElTXG4gICAgICAgICAgICAgICAgbGFuZHNjYXBlIC0gc28gdGhlIHR3byBudW1iZXJzIHNheSBldmVyeXRoaW5nIHRoZXJlIGlzIHRvIHNheS5cbiAgICAgICAgICAgICAgLS0+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1yb3cuZ2FwLXNtLmFsaWduLXN0YXJ0XCI+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgV2lkdGhcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiMVwiXG4gICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWdlV2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWdlV2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1SZXF1aXJlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cInBhZ2VEaW1lbnNpb25NaW5cIlxuICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwicGFnZURpbWVuc2lvbk1heFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpbmNoZXNcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgSGVpZ2h0XG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjFcIlxuICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicGFnZUhlaWdodFwiXG4gICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZ2VIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1SZXF1aXJlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cInBhZ2VEaW1lbnNpb25NaW5cIlxuICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwicGFnZURpbWVuc2lvbk1heFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpbmNoZXNcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8IS0tXG4gICAgICAgICAgICAgICAgSG93IGRlZXAgdGhlIGhlYWRlciBhbmQgZm9vdGVyIGJhbmRzIGFyZS4gVGhlaXIgY29udGVudCBpcyBlZGl0ZWRcbiAgICAgICAgICAgICAgICBvbiB0aGUgY2FudmFzIChFZGl0IGxheW91dCDihpIgSGVhZGVyICYgZm9vdGVyKTsgdGhlc2UgcmVzZXJ2ZSB0aGVcbiAgICAgICAgICAgICAgICBzcGFjZSBmb3IgaXQsIGFuZCAwIG1lYW5zIG5vIGJhbmQuXG4gICAgICAgICAgICAgIC0tPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIEhlYWRlciBoZWlnaHRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIyXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJoZWFkZXJIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwiaGVhZGVySGVpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCJoZWFkZXJGb290ZXJNYXhcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICBpbmNoZXNcbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBGb290ZXIgaGVpZ2h0XG4gICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiMlwiXG4gICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZm9vdGVySGVpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cImZvb3RlckhlaWdodFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwiaGVhZGVyRm9vdGVyTWF4XCI+XG4gICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgaW5jaGVzXG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxmcy1haS1yZXBvcnQtdGltZXpvbmUtc2VsZWN0IFsodGltZXpvbmUpXT1cInRpbWV6b25lXCI+PC9mcy1haS1yZXBvcnQtdGltZXpvbmUtc2VsZWN0PlxuICAgICAgICAgICAgICA8IS0tXG4gICAgICAgICAgICAgICAgSG93IG51bWJlcnMgYW5kIGRhdGVzIGFyZSB3cml0dGVuIChmb3JtYXR0aW5nIG9ubHk6IG5vIHRleHQgaXNcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGVkKSBhbmQgd2hpY2ggY3VycmVuY3kgbW9uZXkgaXMgbGFiZWxlZCBpbi4gSGlkZGVuIG9uIGFcbiAgICAgICAgICAgICAgICBzZXJ2ZXIgdG9vIG9sZCB0byByZXNvbHZlIGEgcmVwb3J0J3MgbG9jYWxlLlxuICAgICAgICAgICAgICAtLT5cbiAgICAgICAgICAgICAgQGlmIChsb2NhbGVzKCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBMb2NhbGVcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJsb2NhbGUoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwibG9jYWxlLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwibG9jYWxlXCI+XG4gICAgICAgICAgICAgICAgICAgIEBmb3IgKG9wdGlvbiBvZiBsb2NhbGVPcHRpb25zKCk7IHRyYWNrIG9wdGlvbi52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICB7eyBmb3JtYXRFeGFtcGxlKCkgfX1cbiAgICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBDdXJyZW5jeVxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImN1cnJlbmN5KClcIlxuICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImN1cnJlbmN5LnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwiY3VycmVuY3lcIj5cbiAgICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIGN1cnJlbmN5T3B0aW9ucygpOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubGFiZWwgfX1cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgICAgTmFtZXMgdGhlIGN1cnJlbmN5IGFtb3VudHMgYXJlIGluOyBpdCBkb2VzIG5vdCBjb252ZXJ0IHRoZW0uXG4gICAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgICBsYWJlbD1cIlN0eWxlc1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJzdHlsZXNcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1jb2x1bW4gdGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBIZWFkaW5nIFNpemVcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgIHN0ZXA9XCIxXCJcbiAgICAgICAgICAgICAgICAgIG1pbj1cIjZcIlxuICAgICAgICAgICAgICAgICAgbWF4PVwiOTZcIlxuICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJoZWFkaW5nU2l6ZVwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwiaGVhZGluZ1NpemVcIlxuICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCI2XCJcbiAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwiOTZcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgcHRcbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgQXBwbGllcyB0byBjb21wb25lbnQgdGl0bGVzLiBQb2ludHMgbWFwIDE6MSB0byBQREYgYW5kIFBvd2VyUG9pbnQuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgICBsYWJlbD1cIkZpbHRlcnNcIlxuICAgICAgICAgICAgICBuYW1lPVwiZmlsdGVyc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtbiB0YWItYm9keVwiPlxuICAgICAgICAgICAgICBAaWYgKGZpbHRlclJvd3MoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBAZm9yIChyb3cgb2YgZmlsdGVyUm93cygpOyB0cmFjayByb3cuZ3JvdXAuaWQpIHtcbiAgICAgICAgICAgICAgICAgIEBzd2l0Y2ggKHJvdy5ncm91cC50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIEBjYXNlICgnZGF0ZVJhbmdlJykge1xuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1yb3cuZ2FwLXNtLmFsaWduLWNlbnRlciBmcy1mbGV4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmcy1mbGV4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCBGcm9tIHt7IHJvdy5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmc0RhdGVQaWNrZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy5zdGFydFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ3N0YXJ0JyArIHJvdy5ncm91cC5pZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZzLWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0IFRvIHt7IHJvdy5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmc0RhdGVQaWNrZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy5lbmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidlbmQnICsgcm93Lmdyb3VwLmlkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwhLS0gQSBzdG9yZWQgcm9sbGluZyBwcmVzZXQgY2Fubm90IGJlIGF1dGhvcmVkIGhlcmUsIG9ubHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlcHQsIHJlcGxhY2VkIGJ5IHBpY2tpbmcgZGF0ZXMsIG9yIGNsZWFyZWQuIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcHMgQ2xlYXIgZnJvbSBzdWJtaXR0aW5nIHRoZSBmb3JtLiAtLT5cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKHJvdy5yZWxhdGl2ZSAmJiAhcm93LnN0YXJ0ICYmICFyb3cuZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtcm93LmdhcC1zbS5hbGlnbi1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1oaW50IGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvbGxpbmcgZGVmYXVsdDoge3sgcmVsYXRpdmVMYWJlbChyb3cucmVsYXRpdmUpIH19LiBQaWNrIGRhdGVzIHRvIHJlcGxhY2UgaXQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNsZWFyUmVsYXRpdmUocm93KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIENsZWFyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBjYXNlICgnc2VsZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgIDxmcy1hdXRvY29tcGxldGUtY2hpcHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmcy1mbGV4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW2xhYmVsXT1cIidEZWZhdWx0ICcgKyByb3cubGFiZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbZmV0Y2hdPVwicm93LmZldGNoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cudmFsdWVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ3ZhbHVlcycgKyByb3cuZ3JvdXAuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbbXVsdGlwbGVdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmZXRjaE9uRm9jdXNdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnNBdXRvY29tcGxldGVDaGlwc1RlbXBsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0LW9iamVjdD1cIm9iamVjdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBvYmplY3QubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICA8L2ZzLWF1dG9jb21wbGV0ZS1jaGlwcz5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBAZGVmYXVsdCB7XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCB7eyByb3cubGFiZWwgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicm93LnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ3ZhbHVlJyArIHJvdy5ncm91cC5pZFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgIDxmcy1tZXNzYWdlLWluZm8+XG4gICAgICAgICAgICAgICAgICBUaGlzIHJlcG9ydCBoYXMgbm8gcmVwb3J0LWxldmVsIGZpbHRlcnMgeWV0LiBBZGQgYSBmaWx0ZXIgdG8gYVxuICAgICAgICAgICAgICAgICAgY29tcG9uZW50IChpdHMgc2V0dGluZ3Mg4oaSIEZpbHRlcnMpIGFuZCBzaG93IGl0IGluIHRoZSByZXBvcnQgYmFyLFxuICAgICAgICAgICAgICAgICAgdGhlbiBzZXQgaXRzIGRlZmF1bHQgaGVyZS5cbiAgICAgICAgICAgICAgICA8L2ZzLW1lc3NhZ2UtaW5mbz5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9tYXQtdGFiPlxuICAgICAgICA8L21hdC10YWItZ3JvdXA+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L21hdC1kaWFsb2ctY29udGVudD5cbiAgICA8bWF0LWRpYWxvZy1hY3Rpb25zPlxuICAgICAgPGZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgY29sb3I9XCJ3YXJuXCJcbiAgICAgICAgICAgIChjbGljayk9XCJkZWxldGUoKVwiPlxuICAgICAgICAgIERlbGV0ZVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZnMtZm9ybS1kaWFsb2ctYWN0aW9ucz5cbiAgICA8L21hdC1kaWFsb2ctYWN0aW9ucz5cbiAgPC9mcy1kaWFsb2c+XG48L2Zvcm0+Il19