@firestitch/report 18.10.0 → 18.10.2

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 (66) hide show
  1. package/app/reports/components/component-text/component-text.component.d.ts +1 -0
  2. package/app/reports/components/component-text/value-embed.plugin.d.ts +25 -1
  3. package/app/reports/components/report-canvas/report-canvas.component.d.ts +12 -0
  4. package/app/reports/components/report-component/report-component.component.d.ts +1 -0
  5. package/app/reports/data/report.data.d.ts +5 -7
  6. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +13 -1
  7. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +30 -2
  8. package/app/reports/export/report-export-collector.service.d.ts +13 -5
  9. package/app/reports/export/report-filter-lines.d.ts +3 -0
  10. package/app/reports/filter-settings-rules.d.ts +4 -0
  11. package/app/reports/filter-text.d.ts +8 -0
  12. package/app/reports/format.d.ts +1 -0
  13. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +1 -0
  14. package/app/reports/interfaces/report-filter-group-changes.interface.d.ts +7 -0
  15. package/app/reports/interfaces/report.interface.d.ts +1 -14
  16. package/app/reports/report-filter-items.d.ts +11 -8
  17. package/app/reports/report-view-config.d.ts +1 -3
  18. package/app/reports/services/report-filter-state.service.d.ts +5 -14
  19. package/app/reports/services/report-view.service.d.ts +1 -13
  20. package/app/reports/text.d.ts +16 -0
  21. package/app/reports/views/report/fs-ai-report.component.d.ts +2 -8
  22. package/esm2022/app/reports/canvas-landing-page.mjs +7 -6
  23. package/esm2022/app/reports/components/component-list/component-list.component.mjs +5 -5
  24. package/esm2022/app/reports/components/component-text/component-text.component.mjs +34 -22
  25. package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +254 -42
  26. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +130 -24
  27. package/esm2022/app/reports/components/report-component/report-component.component.mjs +38 -19
  28. package/esm2022/app/reports/data/report.data.mjs +19 -11
  29. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +57 -14
  30. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +169 -21
  31. package/esm2022/app/reports/export/report-export-collector.service.mjs +84 -33
  32. package/esm2022/app/reports/export/report-filter-lines.mjs +25 -8
  33. package/esm2022/app/reports/export/report-pdf.service.mjs +31 -21
  34. package/esm2022/app/reports/export/report-pptx.service.mjs +21 -11
  35. package/esm2022/app/reports/filter-settings-rules.mjs +8 -1
  36. package/esm2022/app/reports/filter-text.mjs +154 -0
  37. package/esm2022/app/reports/format.mjs +3 -2
  38. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +1 -1
  39. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +1 -1
  40. package/esm2022/app/reports/interfaces/report-filter-group-changes.interface.mjs +2 -0
  41. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +1 -1
  42. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +1 -1
  43. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  44. package/esm2022/app/reports/report-date-presets.mjs +2 -2
  45. package/esm2022/app/reports/report-filter-items.mjs +48 -106
  46. package/esm2022/app/reports/report-view-config.mjs +6 -116
  47. package/esm2022/app/reports/services/report-filter-state.service.mjs +92 -269
  48. package/esm2022/app/reports/services/report-view.service.mjs +25 -165
  49. package/esm2022/app/reports/text.mjs +59 -13
  50. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +69 -130
  51. package/esm2022/app/reports/views/report/report.component.mjs +25 -19
  52. package/fesm2022/{firestitch-report-echarts-UBg8Wlhd.mjs → firestitch-report-echarts-CyHkFToO.mjs} +2 -2
  53. package/fesm2022/{firestitch-report-echarts-UBg8Wlhd.mjs.map → firestitch-report-echarts-CyHkFToO.mjs.map} +1 -1
  54. package/fesm2022/{firestitch-report-firestitch-report-B1keNrcK.mjs → firestitch-report-firestitch-report-DftB7M1o.mjs} +2936 -3254
  55. package/fesm2022/firestitch-report-firestitch-report-DftB7M1o.mjs.map +1 -0
  56. package/fesm2022/firestitch-report.mjs +1 -1
  57. package/package.json +1 -1
  58. package/app/reports/interfaces/report-url-link.interface.d.ts +0 -4
  59. package/app/reports/interfaces/report-url-value-name.type.d.ts +0 -1
  60. package/app/reports/interfaces/report-url-write.interface.d.ts +0 -4
  61. package/app/reports/report-url-state.d.ts +0 -36
  62. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +0 -2
  63. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +0 -2
  64. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +0 -2
  65. package/esm2022/app/reports/report-url-state.mjs +0 -677
  66. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +0 -1
@@ -1,4 +1,6 @@
1
- import { ChangeDetectionStrategy, Component, DestroyRef, computed, inject, signal } from '@angular/core';
1
+ import { DOCUMENT } from '@angular/common';
2
+ import { HttpContext } from '@angular/common/http';
3
+ import { ChangeDetectionStrategy, Component, DestroyRef, Injector, afterNextRender, computed, inject, signal, } from '@angular/core';
2
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
5
  import { FormsModule } from '@angular/forms';
4
6
  import { MatButton } from '@angular/material/button';
@@ -8,6 +10,7 @@ import { MatInput } from '@angular/material/input';
8
10
  import { MatOption, MatSelect } from '@angular/material/select';
9
11
  import { MatSlideToggle } from '@angular/material/slide-toggle';
10
12
  import { MatTabsModule } from '@angular/material/tabs';
13
+ import { DisplayApiError } from '@firestitch/api';
11
14
  import { FsAutocompleteChipsModule } from '@firestitch/autocomplete-chips';
12
15
  import { FsDatePickerModule } from '@firestitch/datepicker';
13
16
  import { FsDialogModule } from '@firestitch/dialog';
@@ -19,14 +22,14 @@ import { FsPrompt } from '@firestitch/prompt';
19
22
  import { FsSkeletonModule } from '@firestitch/skeleton';
20
23
  import { FsTabsModule } from '@firestitch/tabs';
21
24
  import { TimezoneSelectComponent } from '../../components/timezone-select/timezone-select.component';
22
- import { forkJoin, of } from 'rxjs';
23
- import { catchError, finalize, switchMap, tap } from 'rxjs/operators';
25
+ import { forkJoin, from, of, throwError } from 'rxjs';
26
+ import { catchError, concatMap, finalize, switchMap, tap, toArray } from 'rxjs/operators';
24
27
  import { ReportData } from '../../data/report.data';
25
28
  import { ReportValueFormat } from '../../enums/report-value-format.enum';
26
29
  import { DAY_SHORT, REPORT_FALLBACK_CURRENCY, currencyName, formatLocalDate, formatNumber, localeName, resolveReportCurrency, resolveReportLocale, } from '../../format';
27
30
  import { DEFAULT_HEADING_SIZE, HEADER_FOOTER_MAX, PAGE_DIMENSION_MAX, PAGE_DIMENSION_MIN } from '../../layout';
28
31
  import { dateFromBound, dateToBound, loadGroupOptions, matchOptions, relativeLabel, resolveOptionValues, } from '../../report-filter-items';
29
- import { DEFAULT_BOUND_SCALE, FIXED_DATES_PERIOD, boundsError, dateRangeDefault, defaultChanged, defaultPeriod, defaultPeriodOptions, defaultRowGroups, defaultRowLabel, numberRangeDefault, parseDefaultBound, selectDefault, showExcludeToggle, } from '../../filter-settings-rules';
32
+ import { DEFAULT_BOUND_SCALE, FILTER_LABEL_MAX_LENGTH, FILTER_NAME_MAX_LENGTH, FILTER_NAME_PATTERN, FILTER_NAME_PATTERN_MESSAGE, FIXED_DATES_PERIOD, boundsError, dateRangeDefault, defaultChanged, defaultPeriod, defaultPeriodOptions, defaultRowGroups, defaultRowLabel, numberRangeDefault, parseDefaultBound, selectDefault, showExcludeToggle, } from '../../filter-settings-rules';
30
33
  import { reportLocalePatch } from './report-locale-patch';
31
34
  import * as i0 from "@angular/core";
32
35
  import * as i1 from "@angular/forms";
@@ -63,7 +66,11 @@ function currencyLabel(code) {
63
66
  // default month + organization scopes the landing page from the first load.
64
67
  // The rules of the rows live in filter-settings-rules.ts.
65
68
  export class ReportSettingsComponent {
66
- selectedTab = 'settings';
69
+ // A signal, so a refused Label or Name can bring the Filters tab forward.
70
+ selectedTab = signal('settings');
71
+ // True once any save request has been stored, even when the save as a
72
+ // whole then failed: the page reloads after a dismissed dialog too.
73
+ wrote = signal(false);
67
74
  name = '';
68
75
  // The page in inches. No initializer: every report carries a size, and
69
76
  // ngOnInit seeds both before the tab renders, so a placeholder here could only
@@ -145,6 +152,12 @@ export class ReportSettingsComponent {
145
152
  filterRows = signal([]);
146
153
  fixedDatesPeriod = FIXED_DATES_PERIOD;
147
154
  boundScale = DEFAULT_BOUND_SCALE;
155
+ namePattern = FILTER_NAME_PATTERN;
156
+ namePatternMessage = FILTER_NAME_PATTERN_MESSAGE;
157
+ nameMaxLength = FILTER_NAME_MAX_LENGTH;
158
+ labelMaxLength = FILTER_LABEL_MAX_LENGTH;
159
+ labelInputId = labelInputId;
160
+ nameInputId = nameInputId;
148
161
  // The Default minimum and Default maximum checks, through fsForm. Each field
149
162
  // gets the other end as its validateData, so typing in one checks the pair
150
163
  // again; boundsError words the refusal as the server does.
@@ -154,12 +167,27 @@ export class ReportSettingsComponent {
154
167
  maxBoundValidator = (control, min) => {
155
168
  this._throwBoundsError(min, control.value);
156
169
  };
170
+ // The server's refusal of a Label or Name, through fsForm. The shape and
171
+ // length are checked on the field (fsFormPattern, fsFormMaxLength), but only
172
+ // the server knows the report's other names, so the field shows the
173
+ // server's own words while it still holds the refused value. A new refusal
174
+ // arrives as the field's validateData, which checks the field again.
175
+ refusalValidator = (control, refusal) => {
176
+ if (refusal && String(control.value ?? '').trim() === refusal.value) {
177
+ throw new Error(refusal.message);
178
+ }
179
+ };
157
180
  _data = inject(MAT_DIALOG_DATA);
158
181
  _dialogRef = inject(MatDialogRef);
159
182
  _reportData = inject(ReportData);
160
183
  _message = inject(FsMessage);
161
184
  _prompt = inject(FsPrompt);
162
185
  _destroyRef = inject(DestroyRef);
186
+ _injector = inject(Injector);
187
+ _document = inject(DOCUMENT);
188
+ // The id of the Label or Name input the server last refused, focused once
189
+ // it is on screen (see focusRefusal).
190
+ _refusedInputId = null;
163
191
  // Only a server that resolves a report's locale offers the locale list.
164
192
  _serverHasLocale = this._data.report.effectiveLocale !== undefined;
165
193
  // True once the locale request has answered, with the list or an error.
@@ -208,13 +236,23 @@ export class ReportSettingsComponent {
208
236
  .subscribe();
209
237
  }
210
238
  }
211
- // A change to a row's Default period, exclude toggle or range ends. A new
239
+ // A change to a row's Label, Name, Default period, exclude toggle or range ends. A new
212
240
  // row object rather than a mutation, so the signal sees the change; the
213
241
  // @for tracks group.id, so the row's controls survive the swap.
214
242
  patchRow(row, patch) {
215
243
  this.filterRows.update((rows) => rows
216
244
  .map((item) => (item.group.id === row.group.id ? { ...item, ...patch } : item)));
217
245
  }
246
+ // Focuses the Label or Name input the server refused, once it is on
247
+ // screen: straight after the refusal when the Filters tab is showing, else
248
+ // when the tab group has brought it forward.
249
+ focusRefusal() {
250
+ const input = this._refusedInputId ? this._document.getElementById(this._refusedInputId) : null;
251
+ if (input) {
252
+ input.focus();
253
+ this._refusedInputId = null;
254
+ }
255
+ }
218
256
  // Confirm and delete here, while the dialog is still open, then close with
219
257
  // a `deleted` result. The page reacts to the result; it no longer owns the
220
258
  // prompt or the API call.
@@ -231,10 +269,9 @@ export class ReportSettingsComponent {
231
269
  }
232
270
  save = () => {
233
271
  const reportId = this._data.report.id;
234
- // Persist the report settings and each changed filter default together, so
235
- // the single Save covers all three tabs. The report reloads on the `saved`
272
+ // One Save covers all three tabs. The report reloads on the `saved`
236
273
  // result, re-seeding the bar from the new defaults.
237
- const settings$ = this._reportData.update(reportId, {
274
+ const settings = {
238
275
  name: this.name,
239
276
  pageWidth: this._pageDimension(this.pageWidth),
240
277
  pageHeight: this._pageDimension(this.pageHeight),
@@ -245,14 +282,27 @@ export class ReportSettingsComponent {
245
282
  headerHeight: this._pageDimension(this.headerHeight) || 0,
246
283
  footerHeight: this._pageDimension(this.footerHeight) || 0,
247
284
  },
248
- });
249
- const defaults$ = this.filterRows()
250
- .filter((row) => defaultChanged(row.group.config?.default, this._rowDefault(row)))
251
- .map((row) => this._reportData.updateFilterGroup(reportId, row.group.id, {
252
- default: this._rowDefault(row),
253
- }));
254
- return forkJoin([settings$, ...defaults$])
255
- .pipe(tap(() => {
285
+ };
286
+ // One group update per changed filter, carrying only what changed: its
287
+ // label, name and default all live in the group's config, so two requests
288
+ // for one group would each write the config over the other.
289
+ const saves = this.filterRows()
290
+ .map((row) => ({ row, changes: this._groupChanges(row) }))
291
+ .filter((save) => Object.keys(save.changes).length > 0);
292
+ // A label or name can be refused, so those updates go first, one after
293
+ // another, and a refusal stops the save before anything else is written:
294
+ // the report settings and the other defaults wait until every name is
295
+ // taken. In sequence, two renames in one save are checked against each
296
+ // other, and a rename onto a name another filter is giving up goes after
297
+ // it. The server applies name before default, so a refused name leaves
298
+ // that filter's default unwritten too.
299
+ const named = this._renameOrder(saves.filter((save) => this._namesOrLabels(save.changes)));
300
+ const defaults = saves.filter((save) => !this._namesOrLabels(save.changes));
301
+ return from(named)
302
+ .pipe(concatMap((save) => this._saveNamed(reportId, save)), toArray(), switchMap(() => forkJoin([
303
+ this._reportData.update(reportId, settings),
304
+ ...defaults.map((save) => this._reportData.updateFilterGroup(reportId, save.row.group.id, save.changes)),
305
+ ].map((request$) => request$.pipe(tap(() => this.wrote.set(true)))))), tap(() => {
256
306
  this._message.success('Report settings saved');
257
307
  this._dialogRef.close({ action: 'saved' });
258
308
  }));
@@ -282,6 +332,72 @@ export class ReportSettingsComponent {
282
332
  _storedOption(stored, offered, label) {
283
333
  return stored && !offered.includes(stored) ? [{ value: stored, label: label(stored) }] : [];
284
334
  }
335
+ // What a save changes on a row's group: the label, name and default, each
336
+ // only when the operator changed it. Label and name are sent only to a
337
+ // server that sent a name, and never one from the other.
338
+ _groupChanges(row) {
339
+ const changes = {};
340
+ if (row.showName) {
341
+ const label = row.label.trim();
342
+ if (label !== (row.group.label ?? '')) {
343
+ changes.label = label;
344
+ }
345
+ const name = row.name.trim();
346
+ if (name !== row.group.name) {
347
+ changes.name = name;
348
+ }
349
+ }
350
+ const rowDefault = this._rowDefault(row);
351
+ if (defaultChanged(row.group.config?.default, rowDefault)) {
352
+ changes.default = rowDefault;
353
+ }
354
+ return changes;
355
+ }
356
+ _namesOrLabels(changes) {
357
+ return changes.name !== undefined || changes.label !== undefined;
358
+ }
359
+ // The updates in the order they are sent: a rename onto a name another
360
+ // filter holds goes after the others, so a filter giving that name up in
361
+ // the same save has done so first.
362
+ _renameOrder(saves) {
363
+ const held = (save) => {
364
+ const name = save.changes.name?.toLowerCase();
365
+ return name !== undefined && this.filterRows()
366
+ .some((row) => row.group.id !== save.row.group.id && row.group.name?.toLowerCase() === name);
367
+ };
368
+ return [...saves].sort((a, b) => Number(held(a)) - Number(held(b)));
369
+ }
370
+ // Saves a filter's update that carries a label or name. A refusal is the
371
+ // server's to word ('Name "region" is already used by the filter
372
+ // "Area".'), so it shows on the field rather than in a dialog, and the save
373
+ // fails. What was saved becomes the row's stored group, so a later save
374
+ // does not send it again.
375
+ _saveNamed(reportId, save) {
376
+ const { row, changes } = save;
377
+ return this._reportData.updateFilterGroup(reportId, row.group.id, changes, { context: new HttpContext().set(DisplayApiError, false) })
378
+ .pipe(tap(() => {
379
+ this.wrote.set(true);
380
+ this.patchRow(row, { group: storedGroup(row.group, changes) });
381
+ }), catchError((error) => {
382
+ this._showRefusal(row, changes, refusalMessage(error));
383
+ return throwError(() => error);
384
+ }));
385
+ }
386
+ // Shows a refusal on the field it is about (the name, which the server
387
+ // checks first, else the label), brings the Filters tab forward and
388
+ // focuses the field, so a save made from another tab says why it failed.
389
+ _showRefusal(row, changes, message) {
390
+ if (changes.name !== undefined) {
391
+ this.patchRow(row, { nameRefusal: { value: changes.name, message } });
392
+ this._refusedInputId = nameInputId(row.group.id);
393
+ }
394
+ else {
395
+ this.patchRow(row, { labelRefusal: { value: changes.label ?? '', message } });
396
+ this._refusedInputId = labelInputId(row.group.id);
397
+ }
398
+ this.selectedTab.set('filters');
399
+ afterNextRender(() => this.focusRefusal(), { injector: this._injector });
400
+ }
285
401
  _throwBoundsError(min, max) {
286
402
  const error = boundsError(parseDefaultBound(min), parseDefaultBound(max));
287
403
  if (error) {
@@ -327,7 +443,12 @@ export class ReportSettingsComponent {
327
443
  const groupDefault = group.config?.default;
328
444
  return {
329
445
  group,
330
- label: defaultRowLabel(group, report.pages),
446
+ heading: defaultRowLabel(group, report.pages),
447
+ label: group.label ?? '',
448
+ name: group.name ?? '',
449
+ showName: typeof group.name === 'string',
450
+ labelRefusal: null,
451
+ nameRefusal: null,
331
452
  period: defaultPeriod(groupDefault),
332
453
  periodOptions: defaultPeriodOptions(relativeLabel, groupDefault?.relative ?? null),
333
454
  start: dateFromBound(groupDefault?.start),
@@ -367,7 +488,7 @@ export class ReportSettingsComponent {
367
488
  }
368
489
  }
369
490
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
370
- 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 <!-- One section per report bar filter: its heading, then its\n default, one field per row. -->\n @for (row of filterRows(); track row.group.id) {\n <h3>\n {{ row.label }}\n </h3>\n @switch (row.group.type) {\n @case ('dateRange') {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default period\n </mat-label>\n <mat-select\n [ngModel]=\"row.period\"\n (ngModelChange)=\"patchRow(row, { period: $event })\"\n [name]=\"'period' + row.group.id\">\n @for (option of row.periodOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (row.period === fixedDatesPeriod) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default from\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=\"full-width\">\n <mat-label>\n Default to\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n }\n }\n @case ('select') {\n <fs-label-field class=\"full-width\">\n <fs-autocomplete-chips\n class=\"full-width\"\n label=\"Default values\"\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 </fs-label-field>\n @if (row.showExclude) {\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"row.exclude\"\n (ngModelChange)=\"patchRow(row, { exclude: $event })\"\n [name]=\"'exclude' + row.group.id\">\n Exclude these values\n </mat-slide-toggle>\n </fs-label-field>\n }\n }\n @case ('numberRange') {\n <!-- fsMaskNumber hands back text; the check and the save\n read it through parseDefaultBound, so 0 is kept. -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default minimum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.min\"\n (ngModelChange)=\"patchRow(row, { min: $event })\"\n [name]=\"'min' + row.group.id\"\n [validate]=\"minBoundValidator\"\n [validateData]=\"row.max\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default maximum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.max\"\n (ngModelChange)=\"patchRow(row, { max: $event })\"\n [name]=\"'max' + row.group.id\"\n [validate]=\"maxBoundValidator\"\n [validateData]=\"row.min\">\n </mat-form-field>\n }\n @default {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default text\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 bar 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: "directive", type: i2.FsFormValidateDirective, selector: "[validate]", inputs: ["validate", "validateData", "validateOnSubmit"] }, { 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: FsLabelModule }, { kind: "component", type: i3.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "ngmodule", type: FsMaskModule }, { kind: "directive", type: i4.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsMessageModule }, { kind: "component", type: i6.FsMessageInfoComponent, selector: "fs-message-info" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i7.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i7.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i8.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i9.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes", "width"], outputs: ["change"] }, { kind: "ngmodule", type: FsAutocompleteChipsModule }, { kind: "component", type: i10.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: i10.FsAutocompleteObjectDirective, selector: "[fsAutocompleteObject],[fsAutocompleteChipsTemplate]" }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i11.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i11.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: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: TimezoneSelectComponent, selector: "fs-ai-report-timezone-select", inputs: ["placeholder", "required", "disabled", "timezone"], outputs: ["timezoneChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
491
+ 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 <!-- animationDone: a refused Label or Name is focused once the\n Filters tab is on screen. -->\n <mat-tab-group\n [(selected)]=\"selectedTab\"\n (animationDone)=\"focusRefusal()\">\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 <!-- One section per report bar filter: its heading, its label\n and name, then its default, one field per row. -->\n @for (row of filterRows(); track row.group.id) {\n <h3>\n {{ row.heading }}\n </h3>\n <!-- The label and the name are independent: a new label\n never changes the name, and the name is edited on its\n own. The server checks both, and its refusal shows on\n the field (refusalValidator). -->\n @if (row.showName) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Label\n </mat-label>\n <input\n matInput\n [id]=\"labelInputId(row.group.id)\"\n [ngModel]=\"row.label\"\n (ngModelChange)=\"patchRow(row, { label: $event })\"\n [name]=\"'label' + row.group.id\"\n [fsFormRequired]=\"true\"\n [fsFormMaxLength]=\"labelMaxLength\"\n [validate]=\"refusalValidator\"\n [validateData]=\"row.labelRefusal\">\n <mat-hint>\n What the filter shows. Changing it never changes the name.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [id]=\"nameInputId(row.group.id)\"\n [ngModel]=\"row.name\"\n (ngModelChange)=\"patchRow(row, { name: $event })\"\n [name]=\"'name' + row.group.id\"\n [fsFormRequired]=\"true\"\n [fsFormPattern]=\"namePattern\"\n [fsFormPatternMessage]=\"namePatternMessage\"\n [fsFormMaxLength]=\"nameMaxLength\"\n [validate]=\"refusalValidator\"\n [validateData]=\"row.nameRefusal\">\n <mat-hint>\n How the AI refers to this filter: a letter, then letters and digits.\n </mat-hint>\n </mat-form-field>\n }\n @switch (row.group.type) {\n @case ('dateRange') {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default period\n </mat-label>\n <mat-select\n [ngModel]=\"row.period\"\n (ngModelChange)=\"patchRow(row, { period: $event })\"\n [name]=\"'period' + row.group.id\">\n @for (option of row.periodOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (row.period === fixedDatesPeriod) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default from\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=\"full-width\">\n <mat-label>\n Default to\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n }\n }\n @case ('select') {\n <fs-label-field class=\"full-width\">\n <fs-autocomplete-chips\n class=\"full-width\"\n label=\"Default values\"\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 </fs-label-field>\n @if (row.showExclude) {\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"row.exclude\"\n (ngModelChange)=\"patchRow(row, { exclude: $event })\"\n [name]=\"'exclude' + row.group.id\">\n Exclude these values\n </mat-slide-toggle>\n </fs-label-field>\n }\n }\n @case ('numberRange') {\n <!-- fsMaskNumber hands back text; the check and the save\n read it through parseDefaultBound, so 0 is kept. -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default minimum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.min\"\n (ngModelChange)=\"patchRow(row, { min: $event })\"\n [name]=\"'min' + row.group.id\"\n [validate]=\"minBoundValidator\"\n [validateData]=\"row.max\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default maximum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.max\"\n (ngModelChange)=\"patchRow(row, { max: $event })\"\n [name]=\"'max' + row.group.id\"\n [validate]=\"maxBoundValidator\"\n [validateData]=\"row.min\">\n </mat-form-field>\n }\n @default {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default text\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 bar 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: "directive", type: i2.FsFormMaxLengthDirective, selector: "[fsFormMaxLength]", inputs: ["fsFormMaxLength", "fsFormMaxLengthMessage"] }, { kind: "directive", type: i2.FsFormPatternDirective, selector: "[fsFormPattern]", inputs: ["fsFormPattern", "fsFormPatternMessage"] }, { kind: "directive", type: i2.FsFormValidateDirective, selector: "[validate]", inputs: ["validate", "validateData", "validateOnSubmit"] }, { 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: FsLabelModule }, { kind: "component", type: i3.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "ngmodule", type: FsMaskModule }, { kind: "directive", type: i4.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsMessageModule }, { kind: "component", type: i6.FsMessageInfoComponent, selector: "fs-message-info" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i7.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i7.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i8.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i9.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes", "width"], outputs: ["change"] }, { kind: "ngmodule", type: FsAutocompleteChipsModule }, { kind: "component", type: i10.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: i10.FsAutocompleteObjectDirective, selector: "[fsAutocompleteObject],[fsAutocompleteChipsTemplate]" }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i11.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i11.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: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: TimezoneSelectComponent, selector: "fs-ai-report-timezone-select", inputs: ["placeholder", "required", "disabled", "timezone"], outputs: ["timezoneChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
371
492
  }
372
493
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportSettingsComponent, decorators: [{
373
494
  type: Component,
@@ -396,6 +517,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
396
517
  MatOption,
397
518
  MatSlideToggle,
398
519
  TimezoneSelectComponent,
399
- ], 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 <!-- One section per report bar filter: its heading, then its\n default, one field per row. -->\n @for (row of filterRows(); track row.group.id) {\n <h3>\n {{ row.label }}\n </h3>\n @switch (row.group.type) {\n @case ('dateRange') {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default period\n </mat-label>\n <mat-select\n [ngModel]=\"row.period\"\n (ngModelChange)=\"patchRow(row, { period: $event })\"\n [name]=\"'period' + row.group.id\">\n @for (option of row.periodOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (row.period === fixedDatesPeriod) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default from\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=\"full-width\">\n <mat-label>\n Default to\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n }\n }\n @case ('select') {\n <fs-label-field class=\"full-width\">\n <fs-autocomplete-chips\n class=\"full-width\"\n label=\"Default values\"\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 </fs-label-field>\n @if (row.showExclude) {\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"row.exclude\"\n (ngModelChange)=\"patchRow(row, { exclude: $event })\"\n [name]=\"'exclude' + row.group.id\">\n Exclude these values\n </mat-slide-toggle>\n </fs-label-field>\n }\n }\n @case ('numberRange') {\n <!-- fsMaskNumber hands back text; the check and the save\n read it through parseDefaultBound, so 0 is kept. -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default minimum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.min\"\n (ngModelChange)=\"patchRow(row, { min: $event })\"\n [name]=\"'min' + row.group.id\"\n [validate]=\"minBoundValidator\"\n [validateData]=\"row.max\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default maximum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.max\"\n (ngModelChange)=\"patchRow(row, { max: $event })\"\n [name]=\"'max' + row.group.id\"\n [validate]=\"maxBoundValidator\"\n [validateData]=\"row.min\">\n </mat-form-field>\n }\n @default {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default text\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 bar 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"] }]
520
+ ], 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 <!-- animationDone: a refused Label or Name is focused once the\n Filters tab is on screen. -->\n <mat-tab-group\n [(selected)]=\"selectedTab\"\n (animationDone)=\"focusRefusal()\">\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 <!-- One section per report bar filter: its heading, its label\n and name, then its default, one field per row. -->\n @for (row of filterRows(); track row.group.id) {\n <h3>\n {{ row.heading }}\n </h3>\n <!-- The label and the name are independent: a new label\n never changes the name, and the name is edited on its\n own. The server checks both, and its refusal shows on\n the field (refusalValidator). -->\n @if (row.showName) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Label\n </mat-label>\n <input\n matInput\n [id]=\"labelInputId(row.group.id)\"\n [ngModel]=\"row.label\"\n (ngModelChange)=\"patchRow(row, { label: $event })\"\n [name]=\"'label' + row.group.id\"\n [fsFormRequired]=\"true\"\n [fsFormMaxLength]=\"labelMaxLength\"\n [validate]=\"refusalValidator\"\n [validateData]=\"row.labelRefusal\">\n <mat-hint>\n What the filter shows. Changing it never changes the name.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [id]=\"nameInputId(row.group.id)\"\n [ngModel]=\"row.name\"\n (ngModelChange)=\"patchRow(row, { name: $event })\"\n [name]=\"'name' + row.group.id\"\n [fsFormRequired]=\"true\"\n [fsFormPattern]=\"namePattern\"\n [fsFormPatternMessage]=\"namePatternMessage\"\n [fsFormMaxLength]=\"nameMaxLength\"\n [validate]=\"refusalValidator\"\n [validateData]=\"row.nameRefusal\">\n <mat-hint>\n How the AI refers to this filter: a letter, then letters and digits.\n </mat-hint>\n </mat-form-field>\n }\n @switch (row.group.type) {\n @case ('dateRange') {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default period\n </mat-label>\n <mat-select\n [ngModel]=\"row.period\"\n (ngModelChange)=\"patchRow(row, { period: $event })\"\n [name]=\"'period' + row.group.id\">\n @for (option of row.periodOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (row.period === fixedDatesPeriod) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default from\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=\"full-width\">\n <mat-label>\n Default to\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"row.end\"\n [name]=\"'end' + row.group.id\">\n </mat-form-field>\n }\n }\n @case ('select') {\n <fs-label-field class=\"full-width\">\n <fs-autocomplete-chips\n class=\"full-width\"\n label=\"Default values\"\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 </fs-label-field>\n @if (row.showExclude) {\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"row.exclude\"\n (ngModelChange)=\"patchRow(row, { exclude: $event })\"\n [name]=\"'exclude' + row.group.id\">\n Exclude these values\n </mat-slide-toggle>\n </fs-label-field>\n }\n }\n @case ('numberRange') {\n <!-- fsMaskNumber hands back text; the check and the save\n read it through parseDefaultBound, so 0 is kept. -->\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default minimum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.min\"\n (ngModelChange)=\"patchRow(row, { min: $event })\"\n [name]=\"'min' + row.group.id\"\n [validate]=\"minBoundValidator\"\n [validateData]=\"row.max\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default maximum\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [signed]=\"true\"\n [scale]=\"boundScale\"\n [ngModel]=\"row.max\"\n (ngModelChange)=\"patchRow(row, { max: $event })\"\n [name]=\"'max' + row.group.id\"\n [validate]=\"maxBoundValidator\"\n [validateData]=\"row.min\">\n </mat-form-field>\n }\n @default {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Default text\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 bar 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"] }]
400
521
  }] });
401
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL3JlcG9ydC1zZXR0aW5ncy9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvcmVwb3J0LXNldHRpbmdzL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBVSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNoRSxPQUFPLEVBQW1CLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3SCxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDMUYsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUMzRSxP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QUFRLGlVQUNSLFNBQVMsd2VBQ1QsU0FBUyxxSkFDVCxjQUFjLDBVQUNkLHVCQUF1Qjs7NEZBR2QsdUJBQXVCO2tCQWhDbkMsU0FBUztzQ0FHUyx1QkFBdUIsQ0FBQyxNQUFNLGNBQ25DLElBQUksV0FDUDt3QkFDUCxXQUFXO3dCQUNYLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixZQUFZO3dCQUNaLGNBQWM7d0JBQ2QsZUFBZTt3QkFDZixZQUFZO3dCQUNaLGdCQUFnQjt3QkFDaEIsa0JBQWtCO3dCQUNsQix5QkFBeUI7d0JBQ3pCLGFBQWE7d0JBQ2IsU0FBUzt3QkFDVCxjQUFjO3dCQUNkLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixZQUFZO3dCQUNaLFFBQVE7d0JBQ1IsT0FBTzt3QkFDUCxTQUFTO3dCQUNULFFBQVE7d0JBQ1IsU0FBUzt3QkFDVCxTQUFTO3dCQUNULGNBQWM7d0JBQ2QsdUJBQXVCO3FCQUN4QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIERlc3Ryb3lSZWYsIE9uSW5pdCwgY29tcHV0ZWQsIGluamVjdCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBNYXRCdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTUFUX0RJQUxPR19EQVRBLCBNYXREaWFsb2dBY3Rpb25zLCBNYXREaWFsb2dDb250ZW50LCBNYXREaWFsb2dSZWYsIE1hdERpYWxvZ1RpdGxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IE1hdEZvcm1GaWVsZCwgTWF0TGFiZWwsIE1hdEhpbnQsIE1hdFN1ZmZpeCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgTWF0SW5wdXQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XG5pbXBvcnQgeyBNYXRPcHRpb24sIE1hdFNlbGVjdCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XG5pbXBvcnQgeyBNYXRTbGlkZVRvZ2dsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NsaWRlLXRvZ2dsZSc7XG5pbXBvcnQgeyBNYXRUYWJzTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFicyc7XG5cbmltcG9ydCB7IEZzQXV0b2NvbXBsZXRlQ2hpcHNNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9hdXRvY29tcGxldGUtY2hpcHMnO1xuaW1wb3J0IHsgRnNEYXRlUGlja2VyTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGF0ZXBpY2tlcic7XG5pbXBvcnQgeyBGc0RpYWxvZ01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2RpYWxvZyc7XG5pbXBvcnQgeyBGc0Zvcm1Nb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9mb3JtJztcbmltcG9ydCB7IEZzTGFiZWxNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9sYWJlbCc7XG5pbXBvcnQgeyBGc01hc2tNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9tYXNrJztcbmltcG9ydCB7IEZzTWVzc2FnZSwgRnNNZXNzYWdlTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWVzc2FnZSc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5pbXBvcnQgeyBGc1NrZWxldG9uTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvc2tlbGV0b24nO1xuaW1wb3J0IHsgRnNUYWJzTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvdGFicyc7XG5cbmltcG9ydCB7IFRpbWV6b25lU2VsZWN0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy90aW1lem9uZS1zZWxlY3QvdGltZXpvbmUtc2VsZWN0LmNvbXBvbmVudCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIGZvcmtKb2luLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgZmluYWxpemUsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm1hdCB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtYXQuZW51bSc7XG5pbXBvcnQge1xuICBEQVlfU0hPUlQsXG4gIFJFUE9SVF9GQUxMQkFDS19DVVJSRU5DWSxcbiAgY3VycmVuY3lOYW1lLFxuICBmb3JtYXRMb2NhbERhdGUsXG4gIGZvcm1hdE51bWJlcixcbiAgbG9jYWxlTmFtZSxcbiAgcmVzb2x2ZVJlcG9ydEN1cnJlbmN5LFxuICByZXNvbHZlUmVwb3J0TG9jYWxlLFxufSBmcm9tICcuLi8uLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LFxuICBSZXBvcnQsXG4gIFJlcG9ydEZpbHRlckdyb3VwLFxuICBSZXBvcnRMb2NhbGVzLFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgREVGQVVMVF9IRUFESU5HX1NJWkUsIEhFQURFUl9GT09URVJfTUFYLCBQQUdFX0RJTUVOU0lPTl9NQVgsIFBBR0VfRElNRU5TSU9OX01JTiB9IGZyb20gJy4uLy4uL2xheW91dCc7XG5pbXBvcnQge1xuICBkYXRlRnJvbUJvdW5kLCBkYXRlVG9Cb3VuZCwgbG9hZEdyb3VwT3B0aW9ucywgbWF0Y2hPcHRpb25zLCByZWxhdGl2ZUxhYmVsLCByZXNvbHZlT3B0aW9uVmFsdWVzLFxufSBmcm9tICcuLi8uLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcbmltcG9ydCB7XG4gIERFRkFVTFRfQk9VTkRfU0NBTEUsXG4gIEZJWEVEX0RBVEVTX1BFUklPRCxcbiAgYm91bmRzRXJyb3IsXG4gIGRhdGVSYW5nZURlZmF1bHQsXG4gIGRlZmF1bHRDaGFuZ2VkLFxuICBkZWZhdWx0UGVyaW9kLFxuICBkZWZhdWx0UGVyaW9kT3B0aW9ucyxcbiAgZGVmYXVsdFJvd0dyb3VwcyxcbiAgZGVmYXVsdFJvd0xhYmVsLFxuICBudW1iZXJSYW5nZURlZmF1bHQsXG4gIHBhcnNlRGVmYXVsdEJvdW5kLFxuICBzZWxlY3REZWZhdWx0LFxuICBzaG93RXhjbHVkZVRvZ2dsZSxcbn0gZnJvbSAnLi4vLi4vZmlsdGVyLXNldHRpbmdzLXJ1bGVzJztcbmltcG9ydCB7IEZpbHRlclNldHRpbmdzT3B0aW9uIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9maWx0ZXItc2V0dGluZ3Mtb3B0aW9uLmludGVyZmFjZSc7XG5cbmltcG9ydCB7IHJlcG9ydExvY2FsZVBhdGNoIH0gZnJvbSAnLi9yZXBvcnQtbG9jYWxlLXBhdGNoJztcblxuXG4vLyBXaGF0IHRoZSBkaWFsb2cgaGFuZHMgYmFjayB3aGVuIGl0IGNsb3Nlcywgc28gdGhlIHBhZ2Uga25vd3Mgd2hhdCBoYXBwZW5lZFxuLy8gd2l0aG91dCBzbmlmZmluZyBtYWdpYyBzdHJpbmdzLiBBIGRpc21pc3NlZCBkaWFsb2cgY2xvc2VzIHdpdGggYHVuZGVmaW5lZGAuXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydFNldHRpbmdzUmVzdWx0IHtcbiAgYWN0aW9uOiAnc2F2ZWQnIHwgJ2RlbGV0ZWQnO1xufVxuXG5cbi8vIE9uZSByZXBvcnQgYmFyIGZpbHRlciBpbiB0aGUgRmlsdGVycyB0YWI6IGl0cyBncm91cCwgYW5kIGFuIGVkaXRhYmxlIGRyYWZ0XG4vLyBkZWZhdWx0LiBUaGUgZHJhZnQgZmllbGRzIHVzZWQgZGVwZW5kIG9uIHRoZSB0eXBlIChkYXRlUmFuZ2Ug4oaSIGEgRGVmYXVsdFxuLy8gcGVyaW9kLCB3aGljaCBpcyBhIHJlbGF0aXZlIHJhbmdlIG9yIEZpeGVkIGRhdGVzIHdpdGggc3RhcnQvZW5kIERhdGVzO1xuLy8gc2VsZWN0IOKGkiB2YWx1ZXMsIGtlcHQgb3IgbGVmdCBvdXQ7IGtleXdvcmQg4oaSIHRleHQ7IG51bWJlclJhbmdlIOKGkiBtaW4gYW5kXG4vLyBtYXgpLiBgZmV0Y2hgIGxvYWRzIHRoZSBzZWxlY3Qgb3B0aW9ucyB0aGUgc2FtZSB3YXkgdGhlIHJlcG9ydCBiYXIgZG9lcy5cbmludGVyZmFjZSBGaWx0ZXJEZWZhdWx0Um93IHtcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwO1xuICBsYWJlbDogc3RyaW5nO1xuICAvLyBBIHJlbGF0aXZlIHJhbmdlIG5hbWUsIG9yIEZJWEVEX0RBVEVTX1BFUklPRCBmb3Igc3RhcnQgYW5kIGVuZC5cbiAgcGVyaW9kOiBzdHJpbmc7XG4gIHBlcmlvZE9wdGlvbnM6IEZpbHRlclNldHRpbmdzT3B0aW9uW107XG4gIHN0YXJ0OiBEYXRlIHwgbnVsbDtcbiAgZW5kOiBEYXRlIHwgbnVsbDtcbiAgdmFsdWVzOiB7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdO1xuICAvLyBUaGUgdmFsdWVzIGFyZSBsZWZ0IG91dCByYXRoZXIgdGhhbiBrZXB0LlxuICBleGNsdWRlOiBib29sZWFuO1xuICBzaG93RXhjbHVkZTogYm9vbGVhbjtcbiAgdmFsdWU6IHN0cmluZztcbiAgLy8gVGhlIHJhbmdlIGVuZHMgYXMgdHlwZWQ6IGZzTWFza051bWJlciBoYW5kcyBiYWNrIHRleHQuIFJlYWQgdGhyb3VnaFxuICAvLyBwYXJzZURlZmF1bHRCb3VuZC5cbiAgbWluOiBudW1iZXIgfCBzdHJpbmcgfCBudWxsO1xuICBtYXg6IG51bWJlciB8IHN0cmluZyB8IG51bGw7XG4gIGZldGNoOiAoa2V5d29yZD86IHN0cmluZykgPT4gT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPjtcbn1cblxuLy8gT25lIGVudHJ5IG9mIHRoZSBMb2NhbGUgb3IgQ3VycmVuY3kgc2VsZWN0LiAnJyBpcyB0aGUgZXhwbGljaXQgRGVmYXVsdC5cbmludGVyZmFjZSBMb2NhbGVTZWxlY3RPcHRpb24ge1xuICB2YWx1ZTogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xufVxuXG4vLyBUaGUgZGF5IHRoZSBMb2NhbGUgaGludCB3cml0ZXMsIGEgZml4ZWQgY2FsZW5kYXIgZGF5IHNvIHRoZSBleGFtcGxlIG5ldmVyXG4vLyBjaGFuZ2VzIHVuZGVyIHRoZSBvcGVyYXRvci5cbmNvbnN0IEVYQU1QTEVfREFZID0gbmV3IERhdGUoMjAyNiwgMCwgNSk7XG5jb25zdCBFWEFNUExFX0FNT1VOVCA9IDEyMzQuNTtcblxuLy8gJ0NhbmFkaWFuIEZyZW5jaCAoZnItQ0EpJywgJ0NhbmFkaWFuIERvbGxhciAoQ0FEKSc6IEVuZ2xpc2ggbmFtZXMgd2hhdGV2ZXJcbi8vIHRoZSByZXBvcnQncyBsb2NhbGUsIHdpdGggdGhlIGNvZGUgdGhhdCBpcyBzdG9yZWQuXG5mdW5jdGlvbiBsb2NhbGVMYWJlbCh0YWc6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtsb2NhbGVOYW1lKHRhZyl9ICgke3RhZ30pYDtcbn1cblxuZnVuY3Rpb24gY3VycmVuY3lMYWJlbChjb2RlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7Y3VycmVuY3lOYW1lKGNvZGUpfSAoJHtjb2RlfSlgO1xufVxuXG5cbi8vIFJlcG9ydCBzZXR0aW5ncywgaW4gdGhyZWUgdGFiczpcbi8vICAgU2V0dGluZ3Mg4oCUIG5hbWUgKyBwYWdlIHNldHVwIChzaXplIGluIGluY2hlcywgaGVhZGVyL2Zvb3RlciBiYW5kIGRlcHRocykuXG4vLyAgIFN0eWxlcyAgIOKAlCB0aGUgcmVwb3J0J3MgdHlwb2dyYXBoaWMgc3R5bGVzIChzaXplcyBpbiBQT0lOVFMsIDE6MSB3aXRoXG4vLyAgIFBERi9Qb3dlclBvaW50KTsgdGhlIEhlYWRpbmcgc2l6ZSB0byBzdGFydC5cbi8vICAgRmlsdGVycyAg4oCUIHRoZSByZXBvcnQgYmFyIGZpbHRlcnMgKGV2ZXJ5IHBhZ2Ugb3Igb25lIHBhZ2UpIGFuZCB0aGVpclxuLy8gICBERUZBVUxUIHZhbHVlcy4gQSBkZWZhdWx0IHNlZWRzIHRoZSByZXBvcnQgYmFyIG9uIGV2ZXJ5IG9wZW4gKGZvciBldmVyeVxuLy8gICB2aWV3ZXIpIGJ1dCBzdGF5cyB1c2VyLWNoYW5nZWFibGUg4oCUIGl0IHByZS1maWxscyB0aGUgY29udHJvbCwgaXQgZG9lc24ndFxuLy8gICBsb2NrIGl0LiBUaGlzIGlzIHRoZSBmaXggZm9yIGhlYXZ5IHJlcG9ydHMgb3BlbmluZyBibGFuayBhbmQgdGltaW5nIG91dDogYVxuLy8gICBkZWZhdWx0IG1vbnRoICsgb3JnYW5pemF0aW9uIHNjb3BlcyB0aGUgbGFuZGluZyBwYWdlIGZyb20gdGhlIGZpcnN0IGxvYWQuXG4vLyAgIFRoZSBydWxlcyBvZiB0aGUgcm93cyBsaXZlIGluIGZpbHRlci1zZXR0aW5ncy1ydWxlcy50cy5cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZVVybDogJy4vcmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vcmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgRm9ybXNNb2R1bGUsXG4gICAgRnNGb3JtTW9kdWxlLFxuICAgIEZzTGFiZWxNb2R1bGUsXG4gICAgRnNNYXNrTW9kdWxlLFxuICAgIEZzRGlhbG9nTW9kdWxlLFxuICAgIEZzTWVzc2FnZU1vZHVsZSxcbiAgICBGc1RhYnNNb2R1bGUsXG4gICAgRnNTa2VsZXRvbk1vZHVsZSxcbiAgICBGc0RhdGVQaWNrZXJNb2R1bGUsXG4gICAgRnNBdXRvY29tcGxldGVDaGlwc01vZHVsZSxcbiAgICBNYXRUYWJzTW9kdWxlLFxuICAgIE1hdEJ1dHRvbixcbiAgICBNYXREaWFsb2dUaXRsZSxcbiAgICBNYXREaWFsb2dDb250ZW50LFxuICAgIE1hdERpYWxvZ0FjdGlvbnMsXG4gICAgTWF0Rm9ybUZpZWxkLFxuICAgIE1hdExhYmVsLFxuICAgIE1hdEhpbnQsXG4gICAgTWF0U3VmZml4LFxuICAgIE1hdElucHV0LFxuICAgIE1hdFNlbGVjdCxcbiAgICBNYXRPcHRpb24sXG4gICAgTWF0U2xpZGVUb2dnbGUsXG4gICAgVGltZXpvbmVTZWxlY3RDb21wb25lbnQsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIFJlcG9ydFNldHRpbmdzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBwdWJsaWMgc2VsZWN0ZWRUYWIgPSAnc2V0dGluZ3MnO1xuXG4gIHB1YmxpYyBuYW1lID0gJyc7XG4gIC8vIFRoZSBwYWdlIGluIGluY2hlcy4gTm8gaW5pdGlhbGl6ZXI6IGV2ZXJ5IHJlcG9ydCBjYXJyaWVzIGEgc2l6ZSwgYW5kXG4gIC8vIG5nT25Jbml0IHNlZWRzIGJvdGggYmVmb3JlIHRoZSB0YWIgcmVuZGVycywgc28gYSBwbGFjZWhvbGRlciBoZXJlIGNvdWxkIG9ubHlcbiAgLy8gZXZlciBiZSBhIHdyb25nIG51bWJlciBicmllZmx5IHNob3dpbmcgYXMgdGhlIG9wZXJhdG9yJ3Mgb3duLlxuICAvL1xuICAvLyBUeXBlZCBgbnVtYmVyIHwgc3RyaW5nYCBiZWNhdXNlIGZzTWFza051bWJlciBpcyB0aGUgY29udHJvbDogaXQgaXMgc2VlZGVkXG4gIC8vIHdpdGggdGhlIHJlcG9ydCdzIG51bWJlciBidXQgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgU1RSSU5HIHRoZSBvcGVyYXRvclxuICAvLyB0eXBlZC4gU2F2ZSBjYXN0cyBpdCBvbmNlLCBvbiB0aGUgd2F5IG91dCDigJQgc2VlIGBfcGFnZURpbWVuc2lvbigpYC5cbiAgcHVibGljIHBhZ2VXaWR0aDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcGFnZUhlaWdodDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcGFnZURpbWVuc2lvbk1pbiA9IFBBR0VfRElNRU5TSU9OX01JTjtcbiAgcHVibGljIHJlYWRvbmx5IHBhZ2VEaW1lbnNpb25NYXggPSBQQUdFX0RJTUVOU0lPTl9NQVg7XG4gIC8vIFRoZSBoZWFkZXIgYW5kIGZvb3RlciBiYW5kIGRlcHRocywgaW5jaGVzIOKAlCB0eXBlZCBsaWtlIHRoZSBwYWdlIHNpemVcbiAgLy8gYmVjYXVzZSBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayBhIHN0cmluZy5cbiAgcHVibGljIGhlYWRlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIGZvb3RlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIHJlYWRvbmx5IGhlYWRlckZvb3Rlck1heCA9IEhFQURFUl9GT09URVJfTUFYO1xuICAvLyBTZWVkZWQgd2l0aCB0aGUgem9uZSB0aGUgcmVwb3J0IGFjdHVhbGx5IHVzZXM6IGl0cyBvd24gc3RvcmVkIHpvbmUsIGVsc2VcbiAgLy8gdGhlIGFwcGxpY2F0aW9uIGRlZmF1bHQgdGhlIHNlcnZlciByZXNvbHZlZCAoZWZmZWN0aXZlVGltZXpvbmUpLiBTYXZlIHNlbmRzXG4gIC8vIGl0IG9ubHkgd2hlbiBpdCBkaWZmZXJzIGZyb20gdGhhdCBlZmZlY3RpdmUgem9uZSwgc28gb3BlbmluZyBhbmQgc2F2aW5nIGFcbiAgLy8gcmVwb3J0IHRoYXQgZm9sbG93cyB0aGUgZGVmYXVsdCBuZXZlciBwaW5zIGl0IHRvIGEgem9uZS5cbiAgcHVibGljIHRpbWV6b25lID0gJyc7XG4gIHB1YmxpYyBoZWFkaW5nU2l6ZSA9IERFRkFVTFRfSEVBRElOR19TSVpFO1xuXG4gIC8vIFRoZSBsb2NhbGVzIGFuZCBjdXJyZW5jaWVzIHRoZSBzZXJ2ZXIgb2ZmZXJzLiBudWxsIHVudGlsIGxvYWRlZCwgYW5kXG4gIC8vIG5ldmVyIGxvYWRlZCBmcm9tIGEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCBlZmZlY3RpdmVMb2NhbGU6IHRoZXJlIHRoZVxuICAvLyBzZWxlY3RzIHN0YXkgaGlkZGVuIGFuZCB0aGUgcmVwb3J0IHJlYWRzIGVuLVVTL1VTRC5cbiAgcHVibGljIHJlYWRvbmx5IGxvY2FsZXMgPSBzaWduYWw8UmVwb3J0TG9jYWxlcyB8IG51bGw+KG51bGwpO1xuICAvLyBUaGUgcmVwb3J0J3Mgb3duIGxvY2FsZSBhbmQgY3VycmVuY3ksICcnIHdoZW4gaXQgZm9sbG93cyB0aGUgZGVmYXVsdC4gU2F2ZVxuICAvLyBzZW5kcyBlYWNoIG9ubHkgd2hlbiBpdCBkaWZmZXJzIGZyb20gdGhlIHN0b3JlZCB2YWx1ZS5cbiAgcHVibGljIHJlYWRvbmx5IGxvY2FsZSA9IHNpZ25hbCgnJyk7XG4gIHB1YmxpYyByZWFkb25seSBjdXJyZW5jeSA9IHNpZ25hbCgnJyk7XG4gIC8vIFRoZSB3aG9sZSBmb3JtIHdhaXRzIGJlaGluZCBvbmUgc2tlbGV0b24gdW50aWwgdGhlIGZpbHRlciByb3dzIGFyZSBidWlsdFxuICAvLyBhbmQgdGhlIGxvY2FsZSByZXF1ZXN0IGhhcyBzZXR0bGVkLCBzbyB0aGUgU2V0dGluZ3MgdGFiIG5ldmVyIHNob3dzXG4gIC8vIHdpdGhvdXQgaXRzIExvY2FsZSBhbmQgQ3VycmVuY3kgc2VsZWN0cy4gQSBmYWlsZWQgbG9jYWxlIHJlcXVlc3Qgc2V0dGxlc1xuICAvLyB0b286IHRoZSB0d28gc2VsZWN0cyBzdGF5IGhpZGRlbiAobG9jYWxlcygpIGlzIHN0aWxsIG51bGwpIGFuZCBldmVyeSBvdGhlclxuICAvLyBzZXR0aW5nIHN0YXlzIGVkaXRhYmxlLlxuICBwdWJsaWMgcmVhZG9ubHkgcmVhZHkgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9maWx0ZXJzUmVhZHkoKSAmJiAoIXRoaXMuX3NlcnZlckhhc0xvY2FsZSB8fCB0aGlzLl9sb2NhbGVzU2V0dGxlZCgpKSk7XG5cbiAgLy8gQW4gZXhwbGljaXQgRGVmYXVsdCAoJycpIG5hbWluZyB0aGUgbG9jYWxlIGl0IHN0YW5kcyBmb3IsIHRoZW4gZWFjaCBvZmZlcmVkXG4gIC8vIGxvY2FsZS4gQSBzdG9yZWQgbG9jYWxlIHRoZSBzZXJ2ZXIgbm8gbG9uZ2VyIG9mZmVycyBpcyBsaXN0ZWQgZmlyc3QsIHNvXG4gIC8vIHRoZSBzZWxlY3Qgc3RpbGwgc2hvd3Mgd2hhdCB0aGUgcmVwb3J0IGhvbGRzLlxuICBwdWJsaWMgcmVhZG9ubHkgbG9jYWxlT3B0aW9ucyA9IGNvbXB1dGVkPExvY2FsZVNlbGVjdE9wdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGlmICghbG9jYWxlcykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IG9mZmVyZWQgPSBsb2NhbGVzLm9wdGlvbnMubWFwKChvcHRpb24pID0+IG9wdGlvbi5sb2NhbGUpO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIC4uLnRoaXMuX3N0b3JlZE9wdGlvbih0aGlzLl9kYXRhLnJlcG9ydC5sb2NhbGUsIG9mZmVyZWQsIGxvY2FsZUxhYmVsKSxcbiAgICAgIHsgdmFsdWU6ICcnLCBsYWJlbDogYERlZmF1bHQg4oCUICR7bG9jYWxlTmFtZShsb2NhbGVzLmRlZmF1bHRMb2NhbGUpfWAgfSxcbiAgICAgIC4uLm9mZmVyZWQubWFwKCh0YWcpID0+ICh7IHZhbHVlOiB0YWcsIGxhYmVsOiBsb2NhbGVMYWJlbCh0YWcpIH0pKSxcbiAgICBdO1xuICB9KTtcblxuICAvLyBBbiBleHBsaWNpdCBEZWZhdWx0ICgnJykgbmFtaW5nIHRoZSBjdXJyZW5jeSB0aGUgc2VsZWN0ZWQgbG9jYWxlIHVzZXMgd2hlblxuICAvLyB0aGUgcmVwb3J0IG5hbWVzIG5vbmUsIHRoZW4gZXZlcnkgY3VycmVuY3kuIEEgc3RvcmVkIGNvZGUgdGhlIHNlcnZlciBub1xuICAvLyBsb25nZXIgb2ZmZXJzIGlzIGxpc3RlZCBmaXJzdC5cbiAgcHVibGljIHJlYWRvbmx5IGN1cnJlbmN5T3B0aW9ucyA9IGNvbXB1dGVkPExvY2FsZVNlbGVjdE9wdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGlmICghbG9jYWxlcykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiBbXG4gICAgICAuLi50aGlzLl9zdG9yZWRPcHRpb24odGhpcy5fZGF0YS5yZXBvcnQuY3VycmVuY3ksIGxvY2FsZXMuY3VycmVuY2llcywgY3VycmVuY3lMYWJlbCksXG4gICAgICB7IHZhbHVlOiAnJywgbGFiZWw6IGBEZWZhdWx0IOKAlCAke2N1cnJlbmN5TGFiZWwodGhpcy5fZGVmYXVsdEN1cnJlbmN5KCkpfWAgfSxcbiAgICAgIC4uLmxvY2FsZXMuY3VycmVuY2llcy5tYXAoKGNvZGUpID0+ICh7IHZhbHVlOiBjb2RlLCBsYWJlbDogY3VycmVuY3lMYWJlbChjb2RlKSB9KSksXG4gICAgXTtcbiAgfSk7XG5cbiAgLy8gSG93IHRoZSByZXBvcnQgd2lsbCB3cml0ZSBhbiBhbW91bnQgYW5kIGEgZGF5IG9uY2Ugc2F2ZWQ6IHRoZSBzZWxlY3RlZFxuICAvLyBsb2NhbGUgYW5kIGN1cnJlbmN5LCBvciB0aGUgZGVmYXVsdHMgdGhleSBmYWxsIGJhY2sgdG8sIGUuZy5cbiAgLy8gJzEgMjM0LDUwICQgwrcgNSBqYW52LiAyMDI2JyBpbiBmci1DQS5cbiAgcHVibGljIHJlYWRvbmx5IGZvcm1hdEV4YW1wbGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlID0gcmVzb2x2ZVJlcG9ydExvY2FsZSh0aGlzLl9hcHBsaWVkTG9jYWxlKCkpO1xuICAgIGNvbnN0IGN1cnJlbmN5ID0gcmVzb2x2ZVJlcG9ydEN1cnJlbmN5KHRoaXMuX2FwcGxpZWRDdXJyZW5jeSgpKTtcblxuICAgIHJldHVybiBbXG4gICAgICBmb3JtYXROdW1iZXIoXG4gICAgICAgIEVYQU1QTEVfQU1PVU5ULFxuICAgICAgICB7IGZvcm1hdDogUmVwb3J0VmFsdWVGb3JtYXQuQ3VycmVuY3ksIHByZWNpc2lvbjogMiB9LFxuICAgICAgICB7IGxvY2FsZSwgY3VycmVuY3ksIHJhdGlvUGVyY2VudDogdHJ1ZSB9LFxuICAgICAgKSxcbiAgICAgIGZvcm1hdExvY2FsRGF0ZShFWEFNUExFX0RBWSwgbG9jYWxlLCBEQVlfU0hPUlQpLFxuICAgIF0uam9pbignIMK3ICcpO1xuICB9KTtcblxuICAvLyBUaGUgcmVwb3J0IGJhciBmaWx0ZXJzIGFuZCB0aGVpciBlZGl0YWJsZSBkZWZhdWx0IHZhbHVlcyAoRmlsdGVycyB0YWIpLlxuICBwdWJsaWMgcmVhZG9ubHkgZmlsdGVyUm93cyA9IHNpZ25hbDxGaWx0ZXJEZWZhdWx0Um93W10+KFtdKTtcbiAgcHVibGljIHJlYWRvbmx5IGZpeGVkRGF0ZXNQZXJpb2QgPSBGSVhFRF9EQVRFU19QRVJJT0Q7XG4gIHB1YmxpYyByZWFkb25seSBib3VuZFNjYWxlID0gREVGQVVMVF9CT1VORF9TQ0FMRTtcblxuICAvLyBUaGUgRGVmYXVsdCBtaW5pbXVtIGFuZCBEZWZhdWx0IG1heGltdW0gY2hlY2tzLCB0aHJvdWdoIGZzRm9ybS4gRWFjaCBmaWVsZFxuICAvLyBnZXRzIHRoZSBvdGhlciBlbmQgYXMgaXRzIHZhbGlkYXRlRGF0YSwgc28gdHlwaW5nIGluIG9uZSBjaGVja3MgdGhlIHBhaXJcbiAgLy8gYWdhaW47IGJvdW5kc0Vycm9yIHdvcmRzIHRoZSByZWZ1c2FsIGFzIHRoZSBzZXJ2ZXIgZG9lcy5cbiAgcHVibGljIHJlYWRvbmx5IG1pbkJvdW5kVmFsaWRhdG9yID0gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgbWF4OiB1bmtub3duKTogdm9pZCA9PiB7XG4gICAgdGhpcy5fdGhyb3dCb3VuZHNFcnJvcihjb250cm9sLnZhbHVlLCBtYXgpO1xuICB9O1xuXG4gIHB1YmxpYyByZWFkb25seSBtYXhCb3VuZFZhbGlkYXRvciA9IChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIG1pbjogdW5rbm93bik6IHZvaWQgPT4ge1xuICAgIHRoaXMuX3Rocm93Qm91bmRzRXJyb3IobWluLCBjb250cm9sLnZhbHVlKTtcbiAgfTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9kYXRhOiB7IHJlcG9ydDogUmVwb3J0IH0gPSBpbmplY3QoTUFUX0RJQUxPR19EQVRBKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZGlhbG9nUmVmID0gaW5qZWN0PE1hdERpYWxvZ1JlZjxSZXBvcnRTZXR0aW5nc0NvbXBvbmVudCwgUmVwb3J0U2V0dGluZ3NSZXN1bHQ+PihNYXREaWFsb2dSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlID0gaW5qZWN0KEZzTWVzc2FnZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG4gIC8vIE9ubHkgYSBzZXJ2ZXIgdGhhdCByZXNvbHZlcyBhIHJlcG9ydCdzIGxvY2FsZSBvZmZlcnMgdGhlIGxvY2FsZSBsaXN0LlxuICBwcml2YXRlIHJlYWRvbmx5IF9zZXJ2ZXJIYXNMb2NhbGUgPSB0aGlzLl9kYXRhLnJlcG9ydC5lZmZlY3RpdmVMb2NhbGUgIT09IHVuZGVmaW5lZDtcbiAgLy8gVHJ1ZSBvbmNlIHRoZSBsb2NhbGUgcmVxdWVzdCBoYXMgYW5zd2VyZWQsIHdpdGggdGhlIGxpc3Qgb3IgYW4gZXJyb3IuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2xvY2FsZXNTZXR0bGVkID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gVHJ1ZSBvbmNlIHRoZSBmaWx0ZXIgcm93cyBhcmUgcHVibGlzaGVkIChzZWUgX2J1aWxkRmlsdGVyUm93cykuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2ZpbHRlcnNSZWFkeSA9IHNpZ25hbChmYWxzZSk7XG5cbiAgLy8gVGhlIGxvY2FsZSB0aGUgcmVwb3J0IHdvdWxkIGJlIHdyaXR0ZW4gaW46IHRoZSBzZWxlY3RlZCBvbmUgd2hlbiB0aGVcbiAgLy8gc2VydmVyIG9mZmVycyBpdCwgZWxzZSB0aGUgZGVmYXVsdCAoYSBzdG9yZWQgbG9jYWxlIGl0IG5vIGxvbmdlciBvZmZlcnNcbiAgLy8gZmFsbHMgYmFjayB0byB0aGUgZGVmYXVsdCwgYXMgaXQgZG9lcyBvbiB0aGUgc2VydmVyKS5cbiAgcHJpdmF0ZSByZWFkb25seSBfYXBwbGllZExvY2FsZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBsb2NhbGVzID0gdGhpcy5sb2NhbGVzKCk7XG4gICAgY29uc3QgbG9jYWxlID0gdGhpcy5sb2NhbGUoKTtcblxuICAgIHJldHVybiBsb2NhbGVzPy5vcHRpb25zLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLmxvY2FsZSA9PT0gbG9jYWxlKVxuICAgICAgPyBsb2NhbGVcbiAgICAgIDogbG9jYWxlcz8uZGVmYXVsdExvY2FsZSA/PyAnJztcbiAgfSk7XG5cbiAgLy8gVGhlIGN1cnJlbmN5IGEgcmVwb3J0IGluIHRoZSBhcHBsaWVkIGxvY2FsZSB1c2VzIHdoZW4gaXQgbmFtZXMgbm9uZS5cbiAgcHJpdmF0ZSByZWFkb25seSBfZGVmYXVsdEN1cnJlbmN5ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGxvY2FsZSA9IHRoaXMuX2FwcGxpZWRMb2NhbGUoKTtcblxuICAgIHJldHVybiB0aGlzLmxvY2FsZXMoKT8ub3B0aW9ucy5maW5kKChvcHRpb24pID0+IG9wdGlvbi5sb2NhbGUgPT09IGxvY2FsZSk/LmRlZmF1bHRDdXJyZW5jeVxuICAgICAgPz8gUkVQT1JUX0ZBTExCQUNLX0NVUlJFTkNZO1xuICB9KTtcblxuICAvLyBUaGUgY3VycmVuY3kgdGhlIHJlcG9ydCB3b3VsZCBsYWJlbCBtb25leSBpbjogdGhlIHNlbGVjdGVkIG9uZSB3aGVuIHRoZVxuICAvLyBzZXJ2ZXIgb2ZmZXJzIGl0LCBlbHNlIHRoZSBkZWZhdWx0LlxuICBwcml2YXRlIHJlYWRvbmx5IF9hcHBsaWVkQ3VycmVuY3kgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY3VycmVuY3kgPSB0aGlzLmN1cnJlbmN5KCk7XG5cbiAgICByZXR1cm4gdGhpcy5sb2NhbGVzKCk/LmN1cnJlbmNpZXMuaW5jbHVkZXMoY3VycmVuY3kpXG4gICAgICA/IGN1cnJlbmN5XG4gICAgICA6IHRoaXMuX2RlZmF1bHRDdXJyZW5jeSgpO1xuICB9KTtcblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgY29uc3QgcmVwb3J0ID0gdGhpcy5fZGF0YS5yZXBvcnQ7XG4gICAgdGhpcy5uYW1lID0gcmVwb3J0Lm5hbWU7XG4gICAgdGhpcy5wYWdlV2lkdGggPSByZXBvcnQucGFnZVdpZHRoO1xuICAgIHRoaXMucGFnZUhlaWdodCA9IHJlcG9ydC5wYWdlSGVpZ2h0O1xuICAgIHRoaXMuaGVhZGVySGVpZ2h0ID0gcmVwb3J0LmNvbmZpZz8uaGVhZGVyRm9vdGVyPy5oZWFkZXJIZWlnaHQgPz8gMDtcbiAgICB0aGlzLmZvb3RlckhlaWdodCA9IHJlcG9ydC5jb25maWc/LmhlYWRlckZvb3Rlcj8uZm9vdGVySGVpZ2h0ID8/IDA7XG4gICAgdGhpcy50aW1lem9uZSA9IHJlcG9ydC50aW1lem9uZSA/PyByZXBvcnQuZWZmZWN0aXZlVGltZXpvbmUgPz8gJyc7XG4gICAgdGhpcy5oZWFkaW5nU2l6ZSA9IHJlcG9ydC5jb25maWc/LnN0eWxlcz8uaGVhZGluZz8uc2l6ZSA/PyBERUZBVUxUX0hFQURJTkdfU0laRTtcbiAgICB0aGlzLmxvY2FsZS5zZXQocmVwb3J0LmxvY2FsZSA/PyAnJyk7XG4gICAgdGhpcy5jdXJyZW5jeS5zZXQocmVwb3J0LmN1cnJlbmN5ID8/ICcnKTtcblxuICAgIHRoaXMuX2J1aWxkRmlsdGVyUm93cyhyZXBvcnQpO1xuXG4gICAgaWYgKHRoaXMuX3NlcnZlckhhc0xvY2FsZSkge1xuICAgICAgdGhpcy5fcmVwb3J0RGF0YS5sb2NhbGVzKClcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFwKChsb2NhbGVzKSA9PiB0aGlzLmxvY2FsZXMuc2V0KGxvY2FsZXMpKSxcbiAgICAgICAgICBjYXRjaEVycm9yKCgpID0+IG9mKG51bGwpKSxcbiAgICAgICAgICBmaW5hbGl6ZSgoKSA9PiB0aGlzLl9sb2NhbGVzU2V0dGxlZC5zZXQodHJ1ZSkpLFxuICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQSBjaGFuZ2UgdG8gYSByb3cncyBEZWZhdWx0IHBlcmlvZCwgZXhjbHVkZSB0b2dnbGUgb3IgcmFuZ2UgZW5kcy4gQSBuZXdcbiAgLy8gcm93IG9iamVjdCByYXRoZXIgdGhhbiBhIG11dGF0aW9uLCBzbyB0aGUgc2lnbmFsIHNlZXMgdGhlIGNoYW5nZTsgdGhlXG4gIC8vIEBmb3IgdHJhY2tzIGdyb3VwLmlkLCBzbyB0aGUgcm93J3MgY29udHJvbHMgc3Vydml2ZSB0aGUgc3dhcC5cbiAgcHVibGljIHBhdGNoUm93KHJvdzogRmlsdGVyRGVmYXVsdFJvdywgcGF0Y2g6IFBhcnRpYWw8RmlsdGVyRGVmYXVsdFJvdz4pOiB2b2lkIHtcbiAgICB0aGlzLmZpbHRlclJvd3MudXBkYXRlKChyb3dzKSA9PiByb3dzXG4gICAgICAubWFwKChpdGVtKSA9PiAoaXRlbS5ncm91cC5pZCA9PT0gcm93Lmdyb3VwLmlkID8geyAuLi5pdGVtLCAuLi5wYXRjaCB9IDogaXRlbSkpKTtcbiAgfVxuXG4gIC8vIENvbmZpcm0gYW5kIGRlbGV0ZSBoZXJlLCB3aGlsZSB0aGUgZGlhbG9nIGlzIHN0aWxsIG9wZW4sIHRoZW4gY2xvc2Ugd2l0aFxuICAvLyBhIGBkZWxldGVkYCByZXN1bHQuIFRoZSBwYWdlIHJlYWN0cyB0byB0aGUgcmVzdWx0OyBpdCBubyBsb25nZXIgb3ducyB0aGVcbiAgLy8gcHJvbXB0IG9yIHRoZSBBUEkgY2FsbC5cbiAgcHVibGljIGRlbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9wcm9tcHQuY29uZmlybSh7XG4gICAgICB0aXRsZTogJ0RlbGV0ZSBSZXBvcnQnLFxuICAgICAgdGVtcGxhdGU6IGBEZWxldGUgXCIke3RoaXMuX2RhdGEucmVwb3J0Lm5hbWV9XCI/IFRoaXMgY2Fubm90IGJlIHVuZG9uZS5gLFxuICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlKHRoaXMuX2RhdGEucmVwb3J0LmlkKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3MoJ1JlcG9ydCBkZWxldGVkJyk7XG4gICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZSh7IGFjdGlvbjogJ2RlbGV0ZWQnIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc2F2ZSA9ICgpID0+IHtcbiAgICBjb25zdCByZXBvcnRJZCA9IHRoaXMuX2RhdGEucmVwb3J0LmlkO1xuXG4gICAgLy8gUGVyc2lzdCB0aGUgcmVwb3J0IHNldHRpbmdzIGFuZCBlYWNoIGNoYW5nZWQgZmlsdGVyIGRlZmF1bHQgdG9nZXRoZXIsIHNvXG4gICAgLy8gdGhlIHNpbmdsZSBTYXZlIGNvdmVycyBhbGwgdGhyZWUgdGFicy4gVGhlIHJlcG9ydCByZWxvYWRzIG9uIHRoZSBgc2F2ZWRgXG4gICAgLy8gcmVzdWx0LCByZS1zZWVkaW5nIHRoZSBiYXIgZnJvbSB0aGUgbmV3IGRlZmF1bHRzLlxuICAgIGNvbnN0IHNldHRpbmdzJCA9IHRoaXMuX3JlcG9ydERhdGEudXBkYXRlKHJlcG9ydElkLCB7XG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBwYWdlV2lkdGg6IHRoaXMuX3BhZ2VEaW1lbnNpb24odGhpcy5wYWdlV2lkdGgpLFxuICAgICAgcGFnZUhlaWdodDogdGhpcy5fcGFnZURpbWVuc2lvbih0aGlzLnBhZ2VIZWlnaHQpLFxuICAgICAgLi4udGhpcy5fdGltZXpvbmVTZXR0aW5nKCksXG4gICAgICAuLi5yZXBvcnRMb2NhbGVQYXRjaCh0aGlzLl9kYXRhLnJlcG9ydCwgdGhpcy5sb2NhbGUoKSwgdGhpcy5jdXJyZW5jeSgpKSxcbiAgICAgIHN0eWxlczogeyBoZWFkaW5nOiB7IHNpemU6IHRoaXMuaGVhZGluZ1NpemUgfSB9LFxuICAgICAgaGVhZGVyRm9vdGVyOiB7XG4gICAgICAgIGhlYWRlckhlaWdodDogdGhpcy5fcGFnZURpbWVuc2lvbih0aGlzLmhlYWRlckhlaWdodCkgfHwgMCxcbiAgICAgICAgZm9vdGVySGVpZ2h0OiB0aGlzLl9wYWdlRGltZW5zaW9uKHRoaXMuZm9vdGVySGVpZ2h0KSB8fCAwLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlZmF1bHRzJCA9IHRoaXMuZmlsdGVyUm93cygpXG4gICAgICAuZmlsdGVyKChyb3cpID0+IGRlZmF1bHRDaGFuZ2VkKHJvdy5ncm91cC5jb25maWc/LmRlZmF1bHQsIHRoaXMuX3Jvd0RlZmF1bHQocm93KSkpXG4gICAgICAubWFwKChyb3cpID0+IHRoaXMuX3JlcG9ydERhdGEudXBkYXRlRmlsdGVyR3JvdXAocmVwb3J0SWQsIHJvdy5ncm91cC5pZCwge1xuICAgICAgICBkZWZhdWx0OiB0aGlzLl9yb3dEZWZhdWx0KHJvdyksXG4gICAgICB9KSk7XG5cbiAgICByZXR1cm4gZm9ya0pvaW4oW3NldHRpbmdzJCwgLi4uZGVmYXVsdHMkXSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnUmVwb3J0IHNldHRpbmdzIHNhdmVkJyk7XG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgYWN0aW9uOiAnc2F2ZWQnIH0pO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH07XG5cbiAgLy8gVGhlIHBhZ2UgZGltZW5zaW9uIGFzIGEgcmVhbCBudW1iZXIgZm9yIHRoZSB3aXJlLiBmc01hc2tOdW1iZXIgaGFuZHMgYmFja1xuICAvLyB0aGUgdW5tYXNrZWQgc3RyaW5nIGl0IGJ1aWx0IHdpdGggYSBmaXhlZCAnLicgcmFkaXggKHdoaWNoIGlzIHRoZSB3aG9sZVxuICAvLyBwb2ludCBvZiB0aGUgbWFzayAtIGEgbmF0aXZlIG51bWJlciBpbnB1dCBwYWludHMgdGhlIHZpZXdlcidzIGxvY2FsZVxuICAvLyBzZXBhcmF0b3IgaW5zdGVhZCksIHNvIHRoZSBjYXN0IGhlcmUgaXMgYSBzdHJhaWdodCBwYXJzZSBhbmQgbmV2ZXIgc2VlcyBhXG4gIC8vIGNvbW1hLiBUaGUgYmFja2VuZCByZWplY3RzIGFueXRoaW5nIG5vbi1udW1lcmljIHJhdGhlciB0aGFuIGNvZXJjaW5nLCBzbyBhXG4gIC8vIE5hTiBmYWlscyBsb3VkbHkgaW5zdGVhZCBvZiBzaWxlbnRseSBzdG9yaW5nIGEgd3JvbmcgcGFnZSBzaXplLlxuICBwcml2YXRlIF9wYWdlRGltZW5zaW9uKHZhbHVlOiBudW1iZXIgfCBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID8gdmFsdWUgOiBwYXJzZUZsb2F0KHZhbHVlKTtcbiAgfVxuXG4gIC8vIFRoZSB6b25lIGZvciB0aGUgc2V0dGluZ3MgUFVULCBzZW50IG9ubHkgd2hlbiBpdCBtb3ZlcyB0aGUgcmVwb3J0IG9mZiB0aGVcbiAgLy8gem9uZSBpdCBhbHJlYWR5IHVzZXMsIHNvIGFuIHVudG91Y2hlZCBkaWFsb2cgbmV2ZXIgcGlucyBhIHJlcG9ydCB0aGF0XG4gIC8vIGZvbGxvd3MgdGhlIGFwcGxpY2F0aW9uIGRlZmF1bHQuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZFxuICAvLyBlZmZlY3RpdmVUaW1lem9uZSBnZXRzIHRoZSB6b25lIGV2ZXJ5IHRpbWUsIGFzIGl0IGFsd2F5cyBkaWQuXG4gIHByaXZhdGUgX3RpbWV6b25lU2V0dGluZygpOiB7IHRpbWV6b25lPzogc3RyaW5nIH0ge1xuICAgIGNvbnN0IGVmZmVjdGl2ZVRpbWV6b25lID0gdGhpcy5fZGF0YS5yZXBvcnQuZWZmZWN0aXZlVGltZXpvbmU7XG5cbiAgICByZXR1cm4gZWZmZWN0aXZlVGltZXpvbmUgPT09IHVuZGVmaW5lZCB8fCB0aGlzLnRpbWV6b25lICE9PSBlZmZlY3RpdmVUaW1lem9uZVxuICAgICAgPyB7IHRpbWV6b25lOiB0aGlzLnRpbWV6b25lIH1cbiAgICAgIDoge307XG4gIH1cblxuICAvLyBUaGUgc3RvcmVkIHZhbHVlIGFzIGl0cyBvd24gb3B0aW9uIHdoZW4gdGhlIHNlcnZlciBubyBsb25nZXIgb2ZmZXJzIGl0LCBzb1xuICAvLyB0aGUgc2VsZWN0IG5hbWVzIGl0IGluc3RlYWQgb2Ygc2hvd2luZyBibGFuay4gTGVmdCBhcyBpdCBpcywgaXQgaXMgbmV2ZXJcbiAgLy8gc2VudCAoc2VlIHJlcG9ydExvY2FsZVBhdGNoKSwgYW5kIHRoZSByZXBvcnQgcmVhZHMgdGhlIGRlZmF1bHQgbWVhbndoaWxlLlxuICBwcml2YXRlIF9zdG9yZWRPcHRpb24oXG4gICAgc3RvcmVkOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuICAgIG9mZmVyZWQ6IHN0cmluZ1tdLFxuICAgIGxhYmVsOiAodmFsdWU6IHN0cmluZykgPT4gc3RyaW5nLFxuICApOiBMb2NhbGVTZWxlY3RPcHRpb25bXSB7XG4gICAgcmV0dXJuIHN0b3JlZCAmJiAhb2ZmZXJlZC5pbmNsdWRlcyhzdG9yZWQpID8gW3sgdmFsdWU6IHN0b3JlZCwgbGFiZWw6IGxhYmVsKHN0b3JlZCkgfV0gOiBbXTtcbiAgfVxuXG4gIHByaXZhdGUgX3Rocm93Qm91bmRzRXJyb3IobWluOiB1bmtub3duLCBtYXg6IHVua25vd24pOiB2b2lkIHtcbiAgICBjb25zdCBlcnJvciA9IGJvdW5kc0Vycm9yKHBhcnNlRGVmYXVsdEJvdW5kKG1pbiksIHBhcnNlRGVmYXVsdEJvdW5kKG1heCkpO1xuXG4gICAgaWYgKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEJ1aWxkIG9uZSBlZGl0YWJsZSByb3cgcGVyIHJlcG9ydCBiYXIgZmlsdGVyIGdyb3VwIChldmVyeSBwYWdlIG9yIG9uZVxuICAvLyBwYWdlKSwgaW4gYmFyIG9yZGVyLCBzZWVkaW5nIGVhY2ggZHJhZnQgZnJvbSB0aGUgZ3JvdXAncyBzdG9yZWQgZGVmYXVsdC5cbiAgcHJpdmF0ZSBfYnVpbGRGaWx0ZXJSb3dzKHJlcG9ydDogUmVwb3J0KTogdm9pZCB7XG4gICAgY29uc3QgYnVpbHQgPSBkZWZhdWx0Um93R3JvdXBzKHJlcG9ydC5maWx0ZXJHcm91cHMpXG4gICAgICAubWFwKChncm91cCkgPT4ge1xuICAgICAgICBjb25zdCBncm91cERlZmF1bHQgPSBncm91cC5jb25maWc/LmRlZmF1bHQ7XG4gICAgICAgIC8vIE9uZSBzaGFyZWQsIHJlcGxheWVkIG9wdGlvbiBzdHJlYW0gcGVyIGdyb3VwOiB0aGUgY2hpcHMgZmV0Y2ggYW5kIHRoZVxuICAgICAgICAvLyBzdG9yZWQgZGVmYXVsdCdzIGxhYmVscyByZWFkIHRoZSBzYW1lIGxpc3QsIHNvIGl0IGlzIGZldGNoZWQgb25jZS5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyQgPSBsb2FkR3JvdXBPcHRpb25zKGdyb3VwLCB0aGlzLl9yZXBvcnREYXRhLCByZXBvcnQuaWQpO1xuICAgICAgICBjb25zdCByb3cgPSB0aGlzLl9maWx0ZXJSb3cocmVwb3J0LCBncm91cCwgb3B0aW9ucyQpO1xuXG4gICAgICAgIHJldHVybiB7IHJvdywgb3B0aW9ucyQsIHZhbHVlczogZ3JvdXBEZWZhdWx0Py52YWx1ZXMgPz8gZ3JvdXBEZWZhdWx0Py5leGNsdWRlVmFsdWVzID8/IFtdIH07XG4gICAgICB9KTtcblxuICAgIGNvbnN0IHJvd3MgPSBidWlsdC5tYXAoKGVudHJ5KSA9PiBlbnRyeS5yb3cpO1xuICAgIGNvbnN0IHNlZWRlZCA9IGJ1aWx0LmZpbHRlcigoZW50cnkpID0+IGVudHJ5LnZhbHVlcy5sZW5ndGgpO1xuXG4gICAgLy8gTm90aGluZyB0byBuYW1lIOKAlCBwdWJsaXNoIGltbWVkaWF0ZWx5IHJhdGhlciB0aGFuIHdhaXRpbmcgb24gYSByZXF1ZXN0XG4gICAgLy8gbm8gcm93IG5lZWRzLlxuICAgIGlmICghc2VlZGVkLmxlbmd0aCkge1xuICAgICAgdGhpcy5fcHVibGlzaEZpbHRlclJvd3Mocm93cyk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBBIHN0b3JlZCBzZWxlY3QgZGVmYXVsdCBob2xkcyBpZHMsIHNvIGl0cyBjaGlwcyBjYW4gb25seSBiZSBuYW1lZCBvbmNlIHRoZVxuICAgIC8vIG9wdGlvbiBsaXN0IGlzIGluLiBSZXNvbHZlIGV2ZXJ5IHNlZWRlZCByb3cgZmlyc3QgYW5kIHB1Ymxpc2ggdGhlIHJvd3MgaW5cbiAgICAvLyBvbmUgZ28sIHNvIHRoZSB0YWIgbmV2ZXIgcmVuZGVycyBhIGNoaXAgc2hvd2luZyBhIHJhdyBpZC4gV2hlbiBhbiBvcHRpb25cbiAgICAvLyBsaXN0IGZhaWxzIHRvIGxvYWQsIHRoZSByb3dzIHB1Ymxpc2ggdW5yZXNvbHZlZDogZWFjaCBjaGlwIG5hbWVzIGl0cyBpZCxcbiAgICAvLyBhbmQgYW4gdW50b3VjaGVkIHJvdyBzdGlsbCBzYXZlcyB0aGUgc3RvcmVkIGRlZmF1bHQgdW5jaGFuZ2VkLlxuICAgIGZvcmtKb2luKHNlZWRlZC5tYXAoKGVudHJ5KSA9PiByZXNvbHZlT3B0aW9uVmFsdWVzKGVudHJ5Lm9wdGlvbnMkLCBlbnRyeS52YWx1ZXMpKSlcbiAgICAgIC5waXBlKFxuICAgICAgICBjYXRjaEVycm9yKCgpID0+IG9mKHNlZWRlZC5tYXAoKGVudHJ5KSA9PiBlbnRyeS52YWx1ZXMubWFwKCh2YWx1ZSkgPT4gKHsgbmFtZTogU3RyaW5nKHZhbHVlKSwgdmFsdWUgfSkpKSkpLFxuICAgICAgICB0YXAoKHJlc29sdmVkKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZWQuZm9yRWFjaCgodmFsdWVzLCBpbmRleCkgPT4gc2VlZGVkW2luZGV4XS5yb3cudmFsdWVzID0gdmFsdWVzKTtcbiAgICAgICAgICB0aGlzLl9wdWJsaXNoRmlsdGVyUm93cyhyb3dzKTtcbiAgICAgICAgfSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8vIE9uZSByb3cncyBkcmFmdCwgc2VlZGVkIGZyb20gaXRzIGdyb3VwJ3Mgc3RvcmVkIGRlZmF1bHQuIEEgc3RvcmVkIHNlbGVjdFxuICAvLyBkZWZhdWx0J3MgdmFsdWVzIGFyZSBuYW1lZCBsYXRlciwgb25jZSB0aGUgb3B0aW9uIGxpc3QgY2FycnlpbmcgdGhlaXJcbiAgLy8gbGFiZWxzIGlzIGluIChzZWUgX2J1aWxkRmlsdGVyUm93cykuXG4gIHByaXZhdGUgX2ZpbHRlclJvdyhcbiAgICByZXBvcnQ6IFJlcG9ydCxcbiAgICBncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsXG4gICAgb3B0aW9ucyQ6IE9ic2VydmFibGU8eyBuYW1lOiBzdHJpbmc7IHZhbHVlOiB1bmtub3duIH1bXT4sXG4gICk6IEZpbHRlckRlZmF1bHRSb3cge1xuICAgIGNvbnN0IGdyb3VwRGVmYXVsdCA9IGdyb3VwLmNvbmZpZz8uZGVmYXVsdDtcblxuICAgIHJldHVybiB7XG4gICAgICBncm91cCxcbiAgICAgIGxhYmVsOiBkZWZhdWx0Um93TGFiZWwoZ3JvdXAsIHJlcG9ydC5wYWdlcyksXG4gICAgICBwZXJpb2Q6IGRlZmF1bHRQZXJpb2QoZ3JvdXBEZWZhdWx0KSxcbiAgICAgIHBlcmlvZE9wdGlvbnM6IGRlZmF1bHRQZXJpb2RPcHRpb25zKHJlbGF0aXZlTGFiZWwsIGdyb3VwRGVmYXVsdD8ucmVsYXRpdmUgPz8gbnVsbCksXG4gICAgICBzdGFydDogZGF0ZUZyb21Cb3VuZChncm91cERlZmF1bHQ/LnN0YXJ0KSxcbiAgICAgIGVuZDogZGF0ZUZyb21Cb3VuZChncm91cERlZmF1bHQ/LmVuZCksXG4gICAgICB2YWx1ZXM6IFtdLFxuICAgICAgZXhjbHVkZTogISFncm91cERlZmF1bHQ/LmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aCxcbiAgICAgIC8vIEFuIG9sZGVyIHNlcnZlciBsaXN0cyBubyBmZWF0dXJlcywgYW5kIGxlYXZlcyBubyB2YWx1ZXMgb3V0LlxuICAgICAgc2hvd0V4Y2x1ZGU6IHNob3dFeGNsdWRlVG9nZ2xlKGdyb3VwLCByZXBvcnQudmlld2VyRmVhdHVyZXMpLFxuICAgICAgdmFsdWU6IGdyb3VwRGVmYXVsdD8udmFsdWUgPz8gJycsXG4gICAgICBtaW46IGdyb3VwRGVmYXVsdD8ubWluID8/IG51bGwsXG4gICAgICBtYXg6IGdyb3VwRGVmYXVsdD8ubWF4ID8/IG51bGwsXG4gICAgICAvLyBmcy1hdXRvY29tcGxldGUtY2hpcHMgZmV0Y2g6IHRoZSBncm91cCdzIGRpc3RpbmN0IG9wdGlvbnMsIG5hbWUtZmlsdGVyZWQuXG4gICAgICAvLyBTYW1lIGxvYWRlciB0aGUgcmVwb3J0IGJhciB1c2VzLCBzbyB0aGUgdHdvIG5ldmVyIGRyaWZ0LlxuICAgICAgZmV0Y2g6IChrZXl3b3JkPzogc3RyaW5nKSA9PiBtYXRjaE9wdGlvbnMob3B0aW9ucyQsIGtleXdvcmQpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF9wdWJsaXNoRmlsdGVyUm93cyhyb3dzOiBGaWx0ZXJEZWZhdWx0Um93W10pOiB2b2lkIHtcbiAgICB0aGlzLmZpbHRlclJvd3Muc2V0KHJvd3MpO1xuICAgIHRoaXMuX2ZpbHRlcnNSZWFkeS5zZXQodHJ1ZSk7XG4gIH1cblxuICAvLyBUaGUgZHJhZnQgZGVmYXVsdCBub3JtYWxpemVkIHRvIHRoZSB3aXJlIHNoYXBlIGZvciB0aGlzIHJvdydzIHR5cGUsIG9yIG51bGxcbiAgLy8gd2hlbiBlbXB0eSAod2hpY2ggY2xlYXJzIHRoZSBzdG9yZWQgZGVmYXVsdCkuXG4gIHByaXZhdGUgX3Jvd0RlZmF1bHQocm93OiBGaWx0ZXJEZWZhdWx0Um93KTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB7XG4gICAgc3dpdGNoIChyb3cuZ3JvdXAudHlwZSkge1xuICAgICAgY2FzZSAnZGF0ZVJhbmdlJzpcbiAgICAgICAgcmV0dXJuIGRhdGVSYW5nZURlZmF1bHQocm93LnBlcmlvZCwgZGF0ZVRvQm91bmQocm93LnN0YXJ0KSwgZGF0ZVRvQm91bmQocm93LmVuZCkpO1xuXG4gICAgICBjYXNlICdzZWxlY3QnOlxuICAgICAgICAvLyBBIGhpZGRlbiB0b2dnbGUgbGVhdmVzIG5vdGhpbmcgb3V0LlxuICAgICAgICByZXR1cm4gc2VsZWN0RGVmYXVsdChyb3cudmFsdWVzLm1hcCgob3B0aW9uKSA9PiBvcHRpb24udmFsdWUpLCByb3cuc2hvd0V4Y2x1ZGUgJiYgcm93LmV4Y2x1ZGUpO1xuXG4gICAgICBjYXNlICdudW1iZXJSYW5nZSc6XG4gICAgICAgIHJldHVybiBudW1iZXJSYW5nZURlZmF1bHQocm93Lm1pbiwgcm93Lm1heCk7XG5cbiAgICAgIGNhc2UgJ2tleXdvcmQnOlxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHJvdy52YWx1ZS50cmltKCk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlID8geyB2YWx1ZSB9IDogbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxufVxuIiwiPGZvcm1cbiAgICBmc0Zvcm1cbiAgICBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8aDEgbWF0LWRpYWxvZy10aXRsZT5cbiAgICAgIFJlcG9ydCBTZXR0aW5nc1xuICAgIDwvaDE+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+XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgQXBwbGllcyB0byBjb21wb25lbnQgdGl0bGVzLiBQb2ludHMgbWFwIDE6MSB0byBQREYgYW5kIFBvd2VyUG9pbnQuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgICBsYWJlbD1cIkZpbHRlcnNcIlxuICAgICAgICAgICAgICBuYW1lPVwiZmlsdGVyc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtbiB0YWItYm9keVwiPlxuICAgICAgICAgICAgICBAaWYgKGZpbHRlclJvd3MoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICA8IS0tIE9uZSBzZWN0aW9uIHBlciByZXBvcnQgYmFyIGZpbHRlcjogaXRzIGhlYWRpbmcsIHRoZW4gaXRzXG4gICAgICAgICAgICAgICAgICAgICBkZWZhdWx0LCBvbmUgZmllbGQgcGVyIHJvdy4gLS0+XG4gICAgICAgICAgICAgICAgQGZvciAocm93IG9mIGZpbHRlclJvd3MoKTsgdHJhY2sgcm93Lmdyb3VwLmlkKSB7XG4gICAgICAgICAgICAgICAgICA8aDM+XG4gICAgICAgICAgICAgICAgICAgIHt7IHJvdy5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgPC9oMz5cbiAgICAgICAgICAgICAgICAgIEBzd2l0Y2ggKHJvdy5ncm91cC50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIEBjYXNlICgnZGF0ZVJhbmdlJykge1xuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQgcGVyaW9kXG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwicm93LnBlcmlvZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwicGF0Y2hSb3cocm93LCB7IHBlcmlvZDogJGV2ZW50IH0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCIncGVyaW9kJyArIHJvdy5ncm91cC5pZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2Ygcm93LnBlcmlvZE9wdGlvbnM7IHRyYWNrIG9wdGlvbi52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKHJvdy5wZXJpb2QgPT09IGZpeGVkRGF0ZXNQZXJpb2QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0IGZyb21cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnNEYXRlUGlja2VyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cuc3RhcnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidzdGFydCcgKyByb3cuZ3JvdXAuaWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCB0b1xuICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmc0RhdGVQaWNrZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy5lbmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidlbmQnICsgcm93Lmdyb3VwLmlkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBAY2FzZSAoJ3NlbGVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZnMtYXV0b2NvbXBsZXRlLWNoaXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmdWxsLXdpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD1cIkRlZmF1bHQgdmFsdWVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZmV0Y2hdPVwicm93LmZldGNoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy52YWx1ZXNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIid2YWx1ZXMnICsgcm93Lmdyb3VwLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbXVsdGlwbGVdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ZldGNoT25Gb2N1c109XCJ0cnVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnNBdXRvY29tcGxldGVDaGlwc1RlbXBsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQtb2JqZWN0PVwib2JqZWN0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgb2JqZWN0Lm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZnMtYXV0b2NvbXBsZXRlLWNoaXBzPlxuICAgICAgICAgICAgICAgICAgICAgIDwvZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgQGlmIChyb3cuc2hvd0V4Y2x1ZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxmcy1sYWJlbC1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zbGlkZS10b2dnbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5leGNsdWRlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInBhdGNoUm93KHJvdywgeyBleGNsdWRlOiAkZXZlbnQgfSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ2V4Y2x1ZGUnICsgcm93Lmdyb3VwLmlkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXhjbHVkZSB0aGVzZSB2YWx1ZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9mcy1sYWJlbC1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGNhc2UgKCdudW1iZXJSYW5nZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8IS0tIGZzTWFza051bWJlciBoYW5kcyBiYWNrIHRleHQ7IHRoZSBjaGVjayBhbmQgdGhlIHNhdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWQgaXQgdGhyb3VnaCBwYXJzZURlZmF1bHRCb3VuZCwgc28gMCBpcyBrZXB0LiAtLT5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0IG1pbmltdW1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2lnbmVkXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCJib3VuZFNjYWxlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cubWluXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJwYXRjaFJvdyhyb3csIHsgbWluOiAkZXZlbnQgfSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidtaW4nICsgcm93Lmdyb3VwLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsaWRhdGVdPVwibWluQm91bmRWYWxpZGF0b3JcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt2YWxpZGF0ZURhdGFdPVwicm93Lm1heFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCBtYXhpbXVtXG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3NpZ25lZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiYm91bmRTY2FsZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwicm93Lm1heFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwicGF0Y2hSb3cocm93LCB7IG1heDogJGV2ZW50IH0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCInbWF4JyArIHJvdy5ncm91cC5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbGlkYXRlXT1cIm1heEJvdW5kVmFsaWRhdG9yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsaWRhdGVEYXRhXT1cInJvdy5taW5cIj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBkZWZhdWx0IHtcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0IHRleHRcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicm93LnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ3ZhbHVlJyArIHJvdy5ncm91cC5pZFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgIDxmcy1tZXNzYWdlLWluZm8+XG4gICAgICAgICAgICAgICAgICBUaGlzIHJlcG9ydCBoYXMgbm8gcmVwb3J0IGJhciBmaWx0ZXJzIHlldC4gQWRkIGEgZmlsdGVyIHRvIGFcbiAgICAgICAgICAgICAgICAgIGNvbXBvbmVudCAoaXRzIHNldHRpbmdzIOKGkiBGaWx0ZXJzKSBhbmQgc2hvdyBpdCBpbiB0aGUgcmVwb3J0IGJhcixcbiAgICAgICAgICAgICAgICAgIHRoZW4gc2V0IGl0cyBkZWZhdWx0IGhlcmUuXG4gICAgICAgICAgICAgICAgPC9mcy1tZXNzYWdlLWluZm8+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgPC9tYXQtdGFiLWdyb3VwPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgIDxmcy1mb3JtLWRpYWxvZy1hY3Rpb25zPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKClcIj5cbiAgICAgICAgICBEZWxldGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2ZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPiJdfQ==
522
+ // What a refused request says: the server's message, else the error's own,
523
+ // else a plain fallback.
524
+ function refusalMessage(error) {
525
+ const failure = error;
526
+ const message = failure?.error?.message ?? failure?.message;
527
+ return typeof message === 'string' && message ? message : 'The filter could not be saved.';
528
+ }
529
+ // The group as the server now stores it, once an update carrying `changes`
530
+ // is taken.
531
+ function storedGroup(group, changes) {
532
+ return {
533
+ ...group,
534
+ ...(changes.name !== undefined ? { name: changes.name } : {}),
535
+ ...(changes.label !== undefined ? { label: changes.label } : {}),
536
+ config: changes.default !== undefined
537
+ ? { ...group.config, default: changes.default ?? undefined }
538
+ : group.config,
539
+ };
540
+ }
541
+ // The ids of a filter's Label and Name inputs, so a refused one can be
542
+ // focused.
543
+ function labelInputId(groupId) {
544
+ return `filterLabel${groupId}`;
545
+ }
546
+ function nameInputId(groupId) {
547
+ return `filterName${groupId}`;
548
+ }
549
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL3JlcG9ydC1zZXR0aW5ncy9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvcmVwb3J0LXNldHRpbmdzL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFDTCx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBVSxlQUFlLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQzVHLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBbUIsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxlQUFlLEVBQUUsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdILE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0s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b24nO1xuaW1wb3J0IHsgSHR0cENvbnRleHQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBJbmplY3RvciwgT25Jbml0LCBhZnRlck5leHRSZW5kZXIsIGNvbXB1dGVkLCBpbmplY3QsIHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBNYXRCdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTUFUX0RJQUxPR19EQVRBLCBNYXREaWFsb2dBY3Rpb25zLCBNYXREaWFsb2dDb250ZW50LCBNYXREaWFsb2dSZWYsIE1hdERpYWxvZ1RpdGxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IE1hdEZvcm1GaWVsZCwgTWF0TGFiZWwsIE1hdEhpbnQsIE1hdFN1ZmZpeCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgTWF0SW5wdXQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XG5pbXBvcnQgeyBNYXRPcHRpb24sIE1hdFNlbGVjdCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XG5pbXBvcnQgeyBNYXRTbGlkZVRvZ2dsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NsaWRlLXRvZ2dsZSc7XG5pbXBvcnQgeyBNYXRUYWJzTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFicyc7XG5cbmltcG9ydCB7IERpc3BsYXlBcGlFcnJvciB9IGZyb20gJ0BmaXJlc3RpdGNoL2FwaSc7XG5pbXBvcnQgeyBGc0F1dG9jb21wbGV0ZUNoaXBzTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvYXV0b2NvbXBsZXRlLWNoaXBzJztcbmltcG9ydCB7IEZzRGF0ZVBpY2tlck1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2RhdGVwaWNrZXInO1xuaW1wb3J0IHsgRnNEaWFsb2dNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9kaWFsb2cnO1xuaW1wb3J0IHsgRnNGb3JtTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZm9ybSc7XG5pbXBvcnQgeyBGc0xhYmVsTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbGFiZWwnO1xuaW1wb3J0IHsgRnNNYXNrTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWFzayc7XG5pbXBvcnQgeyBGc01lc3NhZ2UsIEZzTWVzc2FnZU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9tcHQgfSBmcm9tICdAZmlyZXN0aXRjaC9wcm9tcHQnO1xuaW1wb3J0IHsgRnNTa2VsZXRvbk1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3NrZWxldG9uJztcbmltcG9ydCB7IEZzVGFic01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3RhYnMnO1xuXG5pbXBvcnQgeyBUaW1lem9uZVNlbGVjdENvbXBvbmVudCB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvdGltZXpvbmUtc2VsZWN0L3RpbWV6b25lLXNlbGVjdC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBmb3JrSm9pbiwgZnJvbSwgb2YsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIGNvbmNhdE1hcCwgZmluYWxpemUsIHN3aXRjaE1hcCwgdGFwLCB0b0FycmF5IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm1hdCB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtYXQuZW51bSc7XG5pbXBvcnQge1xuICBEQVlfU0hPUlQsXG4gIFJFUE9SVF9GQUxMQkFDS19DVVJSRU5DWSxcbiAgY3VycmVuY3lOYW1lLFxuICBmb3JtYXRMb2NhbERhdGUsXG4gIGZvcm1hdE51bWJlcixcbiAgbG9jYWxlTmFtZSxcbiAgcmVzb2x2ZVJlcG9ydEN1cnJlbmN5LFxuICByZXNvbHZlUmVwb3J0TG9jYWxlLFxufSBmcm9tICcuLi8uLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LFxuICBSZXBvcnQsXG4gIFJlcG9ydEZpbHRlckdyb3VwLFxuICBSZXBvcnRMb2NhbGVzLFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyR3JvdXBDaGFuZ2VzIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLWdyb3VwLWNoYW5nZXMuaW50ZXJmYWNlJztcbmltcG9ydCB7IERFRkFVTFRfSEVBRElOR19TSVpFLCBIRUFERVJfRk9PVEVSX01BWCwgUEFHRV9ESU1FTlNJT05fTUFYLCBQQUdFX0RJTUVOU0lPTl9NSU4gfSBmcm9tICcuLi8uLi9sYXlvdXQnO1xuaW1wb3J0IHtcbiAgZGF0ZUZyb21Cb3VuZCwgZGF0ZVRvQm91bmQsIGxvYWRHcm91cE9wdGlvbnMsIG1hdGNoT3B0aW9ucywgcmVsYXRpdmVMYWJlbCwgcmVzb2x2ZU9wdGlvblZhbHVlcyxcbn0gZnJvbSAnLi4vLi4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5pbXBvcnQge1xuICBERUZBVUxUX0JPVU5EX1NDQUxFLFxuICBGSUxURVJfTEFCRUxfTUFYX0xFTkdUSCxcbiAgRklMVEVSX05BTUVfTUFYX0xFTkdUSCxcbiAgRklMVEVSX05BTUVfUEFUVEVSTixcbiAgRklMVEVSX05BTUVfUEFUVEVSTl9NRVNTQUdFLFxuICBGSVhFRF9EQVRFU19QRVJJT0QsXG4gIGJvdW5kc0Vycm9yLFxuICBkYXRlUmFuZ2VEZWZhdWx0LFxuICBkZWZhdWx0Q2hhbmdlZCxcbiAgZGVmYXVsdFBlcmlvZCxcbiAgZGVmYXVsdFBlcmlvZE9wdGlvbnMsXG4gIGRlZmF1bHRSb3dHcm91cHMsXG4gIGRlZmF1bHRSb3dMYWJlbCxcbiAgbnVtYmVyUmFuZ2VEZWZhdWx0LFxuICBwYXJzZURlZmF1bHRCb3VuZCxcbiAgc2VsZWN0RGVmYXVsdCxcbiAgc2hvd0V4Y2x1ZGVUb2dnbGUsXG59IGZyb20gJy4uLy4uL2ZpbHRlci1zZXR0aW5ncy1ydWxlcyc7XG5pbXBvcnQgeyBGaWx0ZXJTZXR0aW5nc09wdGlvbiB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvZmlsdGVyLXNldHRpbmdzLW9wdGlvbi5pbnRlcmZhY2UnO1xuXG5pbXBvcnQgeyByZXBvcnRMb2NhbGVQYXRjaCB9IGZyb20gJy4vcmVwb3J0LWxvY2FsZS1wYXRjaCc7XG5cblxuLy8gV2hhdCB0aGUgZGlhbG9nIGhhbmRzIGJhY2sgd2hlbiBpdCBjbG9zZXMsIHNvIHRoZSBwYWdlIGtub3dzIHdoYXQgaGFwcGVuZWRcbi8vIHdpdGhvdXQgc25pZmZpbmcgbWFnaWMgc3RyaW5ncy4gQSBkaXNtaXNzZWQgZGlhbG9nIGNsb3NlcyB3aXRoIGB1bmRlZmluZWRgLlxuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRTZXR0aW5nc1Jlc3VsdCB7XG4gIGFjdGlvbjogJ3NhdmVkJyB8ICdkZWxldGVkJztcbn1cblxuXG4vLyBBIE5hbWUgb3IgTGFiZWwgdGhlIHNlcnZlciByZWZ1c2VkIGZvciBhIGZpbHRlciBncm91cCwgd2l0aCB0aGUgbWVzc2FnZSBpdFxuLy8gZ2F2ZS5cbmludGVyZmFjZSBGaWx0ZXJGaWVsZFJlZnVzYWwge1xuICB2YWx1ZTogc3RyaW5nO1xuICBtZXNzYWdlOiBzdHJpbmc7XG59XG5cbi8vIE9uZSByZXBvcnQgYmFyIGZpbHRlciBpbiB0aGUgRmlsdGVycyB0YWI6IGl0cyBncm91cCwgaXRzIGxhYmVsIGFuZCBuYW1lLFxuLy8gYW5kIGFuIGVkaXRhYmxlIGRyYWZ0IGRlZmF1bHQuIFRoZSBkcmFmdCBmaWVsZHMgdXNlZCBkZXBlbmQgb24gdGhlIHR5cGVcbi8vIChkYXRlUmFuZ2Ug4oaSIGEgRGVmYXVsdCBwZXJpb2QsIHdoaWNoIGlzIGEgcmVsYXRpdmUgcmFuZ2Ugb3IgRml4ZWQgZGF0ZXNcbi8vIHdpdGggc3RhcnQvZW5kIERhdGVzOyBzZWxlY3Qg4oaSIHZhbHVlcywga2VwdCBvciBsZWZ0IG91dDsga2V5d29yZCDihpIgdGV4dDtcbi8vIG51bWJlclJhbmdlIOKGkiBtaW4gYW5kIG1heCkuIGBmZXRjaGAgbG9hZHMgdGhlIHNlbGVjdCBvcHRpb25zIHRoZSBzYW1lIHdheVxuLy8gdGhlIHJlcG9ydCBiYXIgZG9lcy5cbmludGVyZmFjZSBGaWx0ZXJEZWZhdWx0Um93IHtcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwO1xuICAvLyBUaGUgc2VjdGlvbiBoZWFkaW5nOiB0aGUgbGFiZWwsIHdpdGggdGhlIHBhZ2UgZm9yIGEgcGFnZSBmaWx0ZXIuXG4gIGhlYWRpbmc6IHN0cmluZztcbiAgLy8gVGhlIGdyb3VwJ3MgbGFiZWwgYW5kIG5hbWUgYXMgdHlwZWQsIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIuIEVhY2ggaXNcbiAgLy8gc2F2ZWQgb25seSB3aGVuIGl0IGRpZmZlcnMgZnJvbSB0aGUgc3RvcmVkIG9uZTsgdGhlIG5hbWUgaXMgbmV2ZXJcbiAgLy8gZGVyaXZlZCBmcm9tIHRoZSBsYWJlbCBoZXJlLlxuICBsYWJlbDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIC8vIFRoZSBzZXJ2ZXIgc2VudCBhIG5hbWUsIHNvIGl0IGFsc28gdGFrZXMgYSBsYWJlbCBhbmQgYSBuYW1lIG9uIHRoZSBncm91cFxuICAvLyB1cGRhdGUgKGFuIG9sZGVyIHNlcnZlciBzZW5kcyBub25lLCBhbmQgdGhlIHR3byBmaWVsZHMgYXJlIGhpZGRlbikuXG4gIHNob3dOYW1lOiBib29sZWFuO1xuICAvLyBUaGUgbGFzdCBsYWJlbCBhbmQgbmFtZSB0aGUgc2VydmVyIHJlZnVzZWQsIGVhY2ggc2hvd24gb24gaXRzIGZpZWxkXG4gIC8vIHdoaWxlIHRoZSBmaWVsZCBzdGlsbCBob2xkcyBpdC5cbiAgbGFiZWxSZWZ1c2FsOiBGaWx0ZXJGaWVsZFJlZnVzYWwgfCBudWxsO1xuICBuYW1lUmVmdXNhbDogRmlsdGVyRmllbGRSZWZ1c2FsIHwgbnVsbDtcbiAgLy8gQSByZWxhdGl2ZSByYW5nZSBuYW1lLCBvciBGSVhFRF9EQVRFU19QRVJJT0QgZm9yIHN0YXJ0IGFuZCBlbmQuXG4gIHBlcmlvZDogc3RyaW5nO1xuICBwZXJpb2RPcHRpb25zOiBGaWx0ZXJTZXR0aW5nc09wdGlvbltdO1xuICBzdGFydDogRGF0ZSB8IG51bGw7XG4gIGVuZDogRGF0ZSB8IG51bGw7XG4gIHZhbHVlczogeyBuYW1lOiBzdHJpbmc7IHZhbHVlOiB1bmtub3duIH1bXTtcbiAgLy8gVGhlIHZhbHVlcyBhcmUgbGVmdCBvdXQgcmF0aGVyIHRoYW4ga2VwdC5cbiAgZXhjbHVkZTogYm9vbGVhbjtcbiAgc2hvd0V4Y2x1ZGU6IGJvb2xlYW47XG4gIHZhbHVlOiBzdHJpbmc7XG4gIC8vIFRoZSByYW5nZSBlbmRzIGFzIHR5cGVkOiBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0ZXh0LiBSZWFkIHRocm91Z2hcbiAgLy8gcGFyc2VEZWZhdWx0Qm91bmQuXG4gIG1pbjogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbDtcbiAgbWF4OiBudW1iZXIgfCBzdHJpbmcgfCBudWxsO1xuICBmZXRjaDogKGtleXdvcmQ/OiBzdHJpbmcpID0+IE9ic2VydmFibGU8eyBuYW1lOiBzdHJpbmc7IHZhbHVlOiB1bmtub3duIH1bXT47XG59XG5cbi8vIE9uZSBmaWx0ZXIncyBncm91cCB1cGRhdGUgaW4gYSBzYXZlOiBvbmx5IHRoZSBrZXlzIHRoZSBvcGVyYXRvciBjaGFuZ2VkLlxuaW50ZXJmYWNlIEZpbHRlckdyb3VwU2F2ZSB7XG4gIHJvdzogRmlsdGVyRGVmYXVsdFJvdztcbiAgY2hhbmdlczogUmVwb3J0RmlsdGVyR3JvdXBDaGFuZ2VzO1xufVxuXG4vLyBPbmUgZW50cnkgb2YgdGhlIExvY2FsZSBvciBDdXJyZW5jeSBzZWxlY3QuICcnIGlzIHRoZSBleHBsaWNpdCBEZWZhdWx0LlxuaW50ZXJmYWNlIExvY2FsZVNlbGVjdE9wdGlvbiB7XG4gIHZhbHVlOiBzdHJpbmc7XG4gIGxhYmVsOiBzdHJpbmc7XG59XG5cbi8vIFRoZSBkYXkgdGhlIExvY2FsZSBoaW50IHdyaXRlcywgYSBmaXhlZCBjYWxlbmRhciBkYXkgc28gdGhlIGV4YW1wbGUgbmV2ZXJcbi8vIGNoYW5nZXMgdW5kZXIgdGhlIG9wZXJhdG9yLlxuY29uc3QgRVhBTVBMRV9EQVkgPSBuZXcgRGF0ZSgyMDI2LCAwLCA1KTtcbmNvbnN0IEVYQU1QTEVfQU1PVU5UID0gMTIzNC41O1xuXG4vLyAnQ2FuYWRpYW4gRnJlbmNoIChmci1DQSknLCAnQ2FuYWRpYW4gRG9sbGFyIChDQUQpJzogRW5nbGlzaCBuYW1lcyB3aGF0ZXZlclxuLy8gdGhlIHJlcG9ydCdzIGxvY2FsZSwgd2l0aCB0aGUgY29kZSB0aGF0IGlzIHN0b3JlZC5cbmZ1bmN0aW9uIGxvY2FsZUxhYmVsKHRhZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2xvY2FsZU5hbWUodGFnKX0gKCR7dGFnfSlgO1xufVxuXG5mdW5jdGlvbiBjdXJyZW5jeUxhYmVsKGNvZGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtjdXJyZW5jeU5hbWUoY29kZSl9ICgke2NvZGV9KWA7XG59XG5cblxuLy8gUmVwb3J0IHNldHRpbmdzLCBpbiB0aHJlZSB0YWJzOlxuLy8gICBTZXR0aW5ncyDigJQgbmFtZSArIHBhZ2Ugc2V0dXAgKHNpemUgaW4gaW5jaGVzLCBoZWFkZXIvZm9vdGVyIGJhbmQgZGVwdGhzKS5cbi8vICAgU3R5bGVzICAg4oCUIHRoZSByZXBvcnQncyB0eXBvZ3JhcGhpYyBzdHlsZXMgKHNpemVzIGluIFBPSU5UUywgMToxIHdpdGhcbi8vICAgUERGL1Bvd2VyUG9pbnQpOyB0aGUgSGVhZGluZyBzaXplIHRvIHN0YXJ0LlxuLy8gICBGaWx0ZXJzICDigJQgdGhlIHJlcG9ydCBiYXIgZmlsdGVycyAoZXZlcnkgcGFnZSBvciBvbmUgcGFnZSkgYW5kIHRoZWlyXG4vLyAgIERFRkFVTFQgdmFsdWVzLiBBIGRlZmF1bHQgc2VlZHMgdGhlIHJlcG9ydCBiYXIgb24gZXZlcnkgb3BlbiAoZm9yIGV2ZXJ5XG4vLyAgIHZpZXdlcikgYnV0IHN0YXlzIHVzZXItY2hhbmdlYWJsZSDigJQgaXQgcHJlLWZpbGxzIHRoZSBjb250cm9sLCBpdCBkb2Vzbid0XG4vLyAgIGxvY2sgaXQuIFRoaXMgaXMgdGhlIGZpeCBmb3IgaGVhdnkgcmVwb3J0cyBvcGVuaW5nIGJsYW5rIGFuZCB0aW1pbmcgb3V0OiBhXG4vLyAgIGRlZmF1bHQgbW9udGggKyBvcmdhbml6YXRpb24gc2NvcGVzIHRoZSBsYW5kaW5nIHBhZ2UgZnJvbSB0aGUgZmlyc3QgbG9hZC5cbi8vICAgVGhlIHJ1bGVzIG9mIHRoZSByb3dzIGxpdmUgaW4gZmlsdGVyLXNldHRpbmdzLXJ1bGVzLnRzLlxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0Zvcm1Nb2R1bGUsXG4gICAgRnNMYWJlbE1vZHVsZSxcbiAgICBGc01hc2tNb2R1bGUsXG4gICAgRnNEaWFsb2dNb2R1bGUsXG4gICAgRnNNZXNzYWdlTW9kdWxlLFxuICAgIEZzVGFic01vZHVsZSxcbiAgICBGc1NrZWxldG9uTW9kdWxlLFxuICAgIEZzRGF0ZVBpY2tlck1vZHVsZSxcbiAgICBGc0F1dG9jb21wbGV0ZUNoaXBzTW9kdWxlLFxuICAgIE1hdFRhYnNNb2R1bGUsXG4gICAgTWF0QnV0dG9uLFxuICAgIE1hdERpYWxvZ1RpdGxlLFxuICAgIE1hdERpYWxvZ0NvbnRlbnQsXG4gICAgTWF0RGlhbG9nQWN0aW9ucyxcbiAgICBNYXRGb3JtRmllbGQsXG4gICAgTWF0TGFiZWwsXG4gICAgTWF0SGludCxcbiAgICBNYXRTdWZmaXgsXG4gICAgTWF0SW5wdXQsXG4gICAgTWF0U2VsZWN0LFxuICAgIE1hdE9wdGlvbixcbiAgICBNYXRTbGlkZVRvZ2dsZSxcbiAgICBUaW1lem9uZVNlbGVjdENvbXBvbmVudCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgUmVwb3J0U2V0dGluZ3NDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIC8vIEEgc2lnbmFsLCBzbyBhIHJlZnVzZWQgTGFiZWwgb3IgTmFtZSBjYW4gYnJpbmcgdGhlIEZpbHRlcnMgdGFiIGZvcndhcmQuXG4gIHB1YmxpYyByZWFkb25seSBzZWxlY3RlZFRhYiA9IHNpZ25hbCgnc2V0dGluZ3MnKTtcbiAgLy8gVHJ1ZSBvbmNlIGFueSBzYXZlIHJlcXVlc3QgaGFzIGJlZW4gc3RvcmVkLCBldmVuIHdoZW4gdGhlIHNhdmUgYXMgYVxuICAvLyB3aG9sZSB0aGVuIGZhaWxlZDogdGhlIHBhZ2UgcmVsb2FkcyBhZnRlciBhIGRpc21pc3NlZCBkaWFsb2cgdG9vLlxuICBwdWJsaWMgcmVhZG9ubHkgd3JvdGUgPSBzaWduYWwoZmFsc2UpO1xuXG4gIHB1YmxpYyBuYW1lID0gJyc7XG4gIC8vIFRoZSBwYWdlIGluIGluY2hlcy4gTm8gaW5pdGlhbGl6ZXI6IGV2ZXJ5IHJlcG9ydCBjYXJyaWVzIGEgc2l6ZSwgYW5kXG4gIC8vIG5nT25Jbml0IHNlZWRzIGJvdGggYmVmb3JlIHRoZSB0YWIgcmVuZGVycywgc28gYSBwbGFjZWhvbGRlciBoZXJlIGNvdWxkIG9ubHlcbiAgLy8gZXZlciBiZSBhIHdyb25nIG51bWJlciBicmllZmx5IHNob3dpbmcgYXMgdGhlIG9wZXJhdG9yJ3Mgb3duLlxuICAvL1xuICAvLyBUeXBlZCBgbnVtYmVyIHwgc3RyaW5nYCBiZWNhdXNlIGZzTWFza051bWJlciBpcyB0aGUgY29udHJvbDogaXQgaXMgc2VlZGVkXG4gIC8vIHdpdGggdGhlIHJlcG9ydCdzIG51bWJlciBidXQgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgU1RSSU5HIHRoZSBvcGVyYXRvclxuICAvLyB0eXBlZC4gU2F2ZSBjYXN0cyBpdCBvbmNlLCBvbiB0aGUgd2F5IG91dCDigJQgc2VlIGBfcGFnZURpbWVuc2lvbigpYC5cbiAgcHVibGljIHBhZ2VXaWR0aDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcGFnZUhlaWdodDogbnVtYmVyIHwgc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcGFnZURpbWVuc2lvbk1pbiA9IFBBR0VfRElNRU5TSU9OX01JTjtcbiAgcHVibGljIHJlYWRvbmx5IHBhZ2VEaW1lbnNpb25NYXggPSBQQUdFX0RJTUVOU0lPTl9NQVg7XG4gIC8vIFRoZSBoZWFkZXIgYW5kIGZvb3RlciBiYW5kIGRlcHRocywgaW5jaGVzIOKAlCB0eXBlZCBsaWtlIHRoZSBwYWdlIHNpemVcbiAgLy8gYmVjYXVzZSBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayBhIHN0cmluZy5cbiAgcHVibGljIGhlYWRlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIGZvb3RlckhlaWdodDogbnVtYmVyIHwgc3RyaW5nID0gMDtcbiAgcHVibGljIHJlYWRvbmx5IGhlYWRlckZvb3Rlck1heCA9IEhFQURFUl9GT09URVJfTUFYO1xuICAvLyBTZWVkZWQgd2l0aCB0aGUgem9uZSB0aGUgcmVwb3J0IGFjdHVhbGx5IHVzZXM6IGl0cyBvd24gc3RvcmVkIHpvbmUsIGVsc2VcbiAgLy8gdGhlIGFwcGxpY2F0aW9uIGRlZmF1bHQgdGhlIHNlcnZlciByZXNvbHZlZCAoZWZmZWN0aXZlVGltZXpvbmUpLiBTYXZlIHNlbmRzXG4gIC8vIGl0IG9ubHkgd2hlbiBpdCBkaWZmZXJzIGZyb20gdGhhdCBlZmZlY3RpdmUgem9uZSwgc28gb3BlbmluZyBhbmQgc2F2aW5nIGFcbiAgLy8gcmVwb3J0IHRoYXQgZm9sbG93cyB0aGUgZGVmYXVsdCBuZXZlciBwaW5zIGl0IHRvIGEgem9uZS5cbiAgcHVibGljIHRpbWV6b25lID0gJyc7XG4gIHB1YmxpYyBoZWFkaW5nU2l6ZSA9IERFRkFVTFRfSEVBRElOR19TSVpFO1xuXG4gIC8vIFRoZSBsb2NhbGVzIGFuZCBjdXJyZW5jaWVzIHRoZSBzZXJ2ZXIgb2ZmZXJzLiBudWxsIHVudGlsIGxvYWRlZCwgYW5kXG4gIC8vIG5ldmVyIGxvYWRlZCBmcm9tIGEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCBlZmZlY3RpdmVMb2NhbGU6IHRoZXJlIHRoZVxuICAvLyBzZWxlY3RzIHN0YXkgaGlkZGVuIGFuZCB0aGUgcmVwb3J0IHJlYWRzIGVuLVVTL1VTRC5cbiAgcHVibGljIHJlYWRvbmx5IGxvY2FsZXMgPSBzaWduYWw8UmVwb3J0TG9jYWxlcyB8IG51bGw+KG51bGwpO1xuICAvLyBUaGUgcmVwb3J0J3Mgb3duIGxvY2FsZSBhbmQgY3VycmVuY3ksICcnIHdoZW4gaXQgZm9sbG93cyB0aGUgZGVmYXVsdC4gU2F2ZVxuICAvLyBzZW5kcyBlYWNoIG9ubHkgd2hlbiBpdCBkaWZmZXJzIGZyb20gdGhlIHN0b3JlZCB2YWx1ZS5cbiAgcHVibGljIHJlYWRvbmx5IGxvY2FsZSA9IHNpZ25hbCgnJyk7XG4gIHB1YmxpYyByZWFkb25seSBjdXJyZW5jeSA9IHNpZ25hbCgnJyk7XG4gIC8vIFRoZSB3aG9sZSBmb3JtIHdhaXRzIGJlaGluZCBvbmUgc2tlbGV0b24gdW50aWwgdGhlIGZpbHRlciByb3dzIGFyZSBidWlsdFxuICAvLyBhbmQgdGhlIGxvY2FsZSByZXF1ZXN0IGhhcyBzZXR0bGVkLCBzbyB0aGUgU2V0dGluZ3MgdGFiIG5ldmVyIHNob3dzXG4gIC8vIHdpdGhvdXQgaXRzIExvY2FsZSBhbmQgQ3VycmVuY3kgc2VsZWN0cy4gQSBmYWlsZWQgbG9jYWxlIHJlcXVlc3Qgc2V0dGxlc1xuICAvLyB0b286IHRoZSB0d28gc2VsZWN0cyBzdGF5IGhpZGRlbiAobG9jYWxlcygpIGlzIHN0aWxsIG51bGwpIGFuZCBldmVyeSBvdGhlclxuICAvLyBzZXR0aW5nIHN0YXlzIGVkaXRhYmxlLlxuICBwdWJsaWMgcmVhZG9ubHkgcmVhZHkgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9maWx0ZXJzUmVhZHkoKSAmJiAoIXRoaXMuX3NlcnZlckhhc0xvY2FsZSB8fCB0aGlzLl9sb2NhbGVzU2V0dGxlZCgpKSk7XG5cbiAgLy8gQW4gZXhwbGljaXQgRGVmYXVsdCAoJycpIG5hbWluZyB0aGUgbG9jYWxlIGl0IHN0YW5kcyBmb3IsIHRoZW4gZWFjaCBvZmZlcmVkXG4gIC8vIGxvY2FsZS4gQSBzdG9yZWQgbG9jYWxlIHRoZSBzZXJ2ZXIgbm8gbG9uZ2VyIG9mZmVycyBpcyBsaXN0ZWQgZmlyc3QsIHNvXG4gIC8vIHRoZSBzZWxlY3Qgc3RpbGwgc2hvd3Mgd2hhdCB0aGUgcmVwb3J0IGhvbGRzLlxuICBwdWJsaWMgcmVhZG9ubHkgbG9jYWxlT3B0aW9ucyA9IGNvbXB1dGVkPExvY2FsZVNlbGVjdE9wdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGlmICghbG9jYWxlcykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IG9mZmVyZWQgPSBsb2NhbGVzLm9wdGlvbnMubWFwKChvcHRpb24pID0+IG9wdGlvbi5sb2NhbGUpO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIC4uLnRoaXMuX3N0b3JlZE9wdGlvbih0aGlzLl9kYXRhLnJlcG9ydC5sb2NhbGUsIG9mZmVyZWQsIGxvY2FsZUxhYmVsKSxcbiAgICAgIHsgdmFsdWU6ICcnLCBsYWJlbDogYERlZmF1bHQg4oCUICR7bG9jYWxlTmFtZShsb2NhbGVzLmRlZmF1bHRMb2NhbGUpfWAgfSxcbiAgICAgIC4uLm9mZmVyZWQubWFwKCh0YWcpID0+ICh7IHZhbHVlOiB0YWcsIGxhYmVsOiBsb2NhbGVMYWJlbCh0YWcpIH0pKSxcbiAgICBdO1xuICB9KTtcblxuICAvLyBBbiBleHBsaWNpdCBEZWZhdWx0ICgnJykgbmFtaW5nIHRoZSBjdXJyZW5jeSB0aGUgc2VsZWN0ZWQgbG9jYWxlIHVzZXMgd2hlblxuICAvLyB0aGUgcmVwb3J0IG5hbWVzIG5vbmUsIHRoZW4gZXZlcnkgY3VycmVuY3kuIEEgc3RvcmVkIGNvZGUgdGhlIHNlcnZlciBub1xuICAvLyBsb25nZXIgb2ZmZXJzIGlzIGxpc3RlZCBmaXJzdC5cbiAgcHVibGljIHJlYWRvbmx5IGN1cnJlbmN5T3B0aW9ucyA9IGNvbXB1dGVkPExvY2FsZVNlbGVjdE9wdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMubG9jYWxlcygpO1xuICAgIGlmICghbG9jYWxlcykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiBbXG4gICAgICAuLi50aGlzLl9zdG9yZWRPcHRpb24odGhpcy5fZGF0YS5yZXBvcnQuY3VycmVuY3ksIGxvY2FsZXMuY3VycmVuY2llcywgY3VycmVuY3lMYWJlbCksXG4gICAgICB7IHZhbHVlOiAnJywgbGFiZWw6IGBEZWZhdWx0IOKAlCAke2N1cnJlbmN5TGFiZWwodGhpcy5fZGVmYXVsdEN1cnJlbmN5KCkpfWAgfSxcbiAgICAgIC4uLmxvY2FsZXMuY3VycmVuY2llcy5tYXAoKGNvZGUpID0+ICh7IHZhbHVlOiBjb2RlLCBsYWJlbDogY3VycmVuY3lMYWJlbChjb2RlKSB9KSksXG4gICAgXTtcbiAgfSk7XG5cbiAgLy8gSG93IHRoZSByZXBvcnQgd2lsbCB3cml0ZSBhbiBhbW91bnQgYW5kIGEgZGF5IG9uY2Ugc2F2ZWQ6IHRoZSBzZWxlY3RlZFxuICAvLyBsb2NhbGUgYW5kIGN1cnJlbmN5LCBvciB0aGUgZGVmYXVsdHMgdGhleSBmYWxsIGJhY2sgdG8sIGUuZy5cbiAgLy8gJzEgMjM0LDUwICQgwrcgNSBqYW52LiAyMDI2JyBpbiBmci1DQS5cbiAgcHVibGljIHJlYWRvbmx5IGZvcm1hdEV4YW1wbGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbG9jYWxlID0gcmVzb2x2ZVJlcG9ydExvY2FsZSh0aGlzLl9hcHBsaWVkTG9jYWxlKCkpO1xuICAgIGNvbnN0IGN1cnJlbmN5ID0gcmVzb2x2ZVJlcG9ydEN1cnJlbmN5KHRoaXMuX2FwcGxpZWRDdXJyZW5jeSgpKTtcblxuICAgIHJldHVybiBbXG4gICAgICBmb3JtYXROdW1iZXIoXG4gICAgICAgIEVYQU1QTEVfQU1PVU5ULFxuICAgICAgICB7IGZvcm1hdDogUmVwb3J0VmFsdWVGb3JtYXQuQ3VycmVuY3ksIHByZWNpc2lvbjogMiB9LFxuICAgICAgICB7IGxvY2FsZSwgY3VycmVuY3ksIHJhdGlvUGVyY2VudDogdHJ1ZSB9LFxuICAgICAgKSxcbiAgICAgIGZvcm1hdExvY2FsRGF0ZShFWEFNUExFX0RBWSwgbG9jYWxlLCBEQVlfU0hPUlQpLFxuICAgIF0uam9pbignIMK3ICcpO1xuICB9KTtcblxuICAvLyBUaGUgcmVwb3J0IGJhciBmaWx0ZXJzIGFuZCB0aGVpciBlZGl0YWJsZSBkZWZhdWx0IHZhbHVlcyAoRmlsdGVycyB0YWIpLlxuICBwdWJsaWMgcmVhZG9ubHkgZmlsdGVyUm93cyA9IHNpZ25hbDxGaWx0ZXJEZWZhdWx0Um93W10+KFtdKTtcbiAgcHVibGljIHJlYWRvbmx5IGZpeGVkRGF0ZXNQZXJpb2QgPSBGSVhFRF9EQVRFU19QRVJJT0Q7XG4gIHB1YmxpYyByZWFkb25seSBib3VuZFNjYWxlID0gREVGQVVMVF9CT1VORF9TQ0FMRTtcbiAgcHVibGljIHJlYWRvbmx5IG5hbWVQYXR0ZXJuID0gRklMVEVSX05BTUVfUEFUVEVSTjtcbiAgcHVibGljIHJlYWRvbmx5IG5hbWVQYXR0ZXJuTWVzc2FnZSA9IEZJTFRFUl9OQU1FX1BBVFRFUk5fTUVTU0FHRTtcbiAgcHVibGljIHJlYWRvbmx5IG5hbWVNYXhMZW5ndGggPSBGSUxURVJfTkFNRV9NQVhfTEVOR1RIO1xuICBwdWJsaWMgcmVhZG9ubHkgbGFiZWxNYXhMZW5ndGggPSBGSUxURVJfTEFCRUxfTUFYX0xFTkdUSDtcbiAgcHVibGljIHJlYWRvbmx5IGxhYmVsSW5wdXRJZCA9IGxhYmVsSW5wdXRJZDtcbiAgcHVibGljIHJlYWRvbmx5IG5hbWVJbnB1dElkID0gbmFtZUlucHV0SWQ7XG5cbiAgLy8gVGhlIERlZmF1bHQgbWluaW11bSBhbmQgRGVmYXVsdCBtYXhpbXVtIGNoZWNrcywgdGhyb3VnaCBmc0Zvcm0uIEVhY2ggZmllbGRcbiAgLy8gZ2V0cyB0aGUgb3RoZXIgZW5kIGFzIGl0cyB2YWxpZGF0ZURhdGEsIHNvIHR5cGluZyBpbiBvbmUgY2hlY2tzIHRoZSBwYWlyXG4gIC8vIGFnYWluOyBib3VuZHNFcnJvciB3b3JkcyB0aGUgcmVmdXNhbCBhcyB0aGUgc2VydmVyIGRvZXMuXG4gIHB1YmxpYyByZWFkb25seSBtaW5Cb3VuZFZhbGlkYXRvciA9IChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIG1heDogdW5rbm93bik6IHZvaWQgPT4ge1xuICAgIHRoaXMuX3Rocm93Qm91bmRzRXJyb3IoY29udHJvbC52YWx1ZSwgbWF4KTtcbiAgfTtcblxuICBwdWJsaWMgcmVhZG9ubHkgbWF4Qm91bmRWYWxpZGF0b3IgPSAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBtaW46IHVua25vd24pOiB2b2lkID0+IHtcbiAgICB0aGlzLl90aHJvd0JvdW5kc0Vycm9yKG1pbiwgY29udHJvbC52YWx1ZSk7XG4gIH07XG5cbiAgLy8gVGhlIHNlcnZlcidzIHJlZnVzYWwgb2YgYSBMYWJlbCBvciBOYW1lLCB0aHJvdWdoIGZzRm9ybS4gVGhlIHNoYXBlIGFuZFxuICAvLyBsZW5ndGggYXJlIGNoZWNrZWQgb24gdGhlIGZpZWxkIChmc0Zvcm1QYXR0ZXJuLCBmc0Zvcm1NYXhMZW5ndGgpLCBidXQgb25seVxuICAvLyB0aGUgc2VydmVyIGtub3dzIHRoZSByZXBvcnQncyBvdGhlciBuYW1lcywgc28gdGhlIGZpZWxkIHNob3dzIHRoZVxuICAvLyBzZXJ2ZXIncyBvd24gd29yZHMgd2hpbGUgaXQgc3RpbGwgaG9sZHMgdGhlIHJlZnVzZWQgdmFsdWUuIEEgbmV3IHJlZnVzYWxcbiAgLy8gYXJyaXZlcyBhcyB0aGUgZmllbGQncyB2YWxpZGF0ZURhdGEsIHdoaWNoIGNoZWNrcyB0aGUgZmllbGQgYWdhaW4uXG4gIHB1YmxpYyByZWFkb25seSByZWZ1c2FsVmFsaWRhdG9yID0gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgcmVmdXNhbDogRmlsdGVyRmllbGRSZWZ1c2FsIHwgbnVsbCk6IHZvaWQgPT4ge1xuICAgIGlmIChyZWZ1c2FsICYmIFN0cmluZyhjb250cm9sLnZhbHVlID8/ICcnKS50cmltKCkgPT09IHJlZnVzYWwudmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihyZWZ1c2FsLm1lc3NhZ2UpO1xuICAgIH1cbiAgfTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9kYXRhOiB7IHJlcG9ydDogUmVwb3J0IH0gPSBpbmplY3QoTUFUX0RJQUxPR19EQVRBKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZGlhbG9nUmVmID0gaW5qZWN0PE1hdERpYWxvZ1JlZjxSZXBvcnRTZXR0aW5nc0NvbXBvbmVudCwgUmVwb3J0U2V0dGluZ3NSZXN1bHQ+PihNYXREaWFsb2dSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlID0gaW5qZWN0KEZzTWVzc2FnZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2luamVjdG9yID0gaW5qZWN0KEluamVjdG9yKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZG9jdW1lbnQgPSBpbmplY3QoRE9DVU1FTlQpO1xuICAvLyBUaGUgaWQgb2YgdGhlIExhYmVsIG9yIE5hbWUgaW5wdXQgdGhlIHNlcnZlciBsYXN0IHJlZnVzZWQsIGZvY3VzZWQgb25jZVxuICAvLyBpdCBpcyBvbiBzY3JlZW4gKHNlZSBmb2N1c1JlZnVzYWwpLlxuICBwcml2YXRlIF9yZWZ1c2VkSW5wdXRJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8vIE9ubHkgYSBzZXJ2ZXIgdGhhdCByZXNvbHZlcyBhIHJlcG9ydCdzIGxvY2FsZSBvZmZlcnMgdGhlIGxvY2FsZSBsaXN0LlxuICBwcml2YXRlIHJlYWRvbmx5IF9zZXJ2ZXJIYXNMb2NhbGUgPSB0aGlzLl9kYXRhLnJlcG9ydC5lZmZlY3RpdmVMb2NhbGUgIT09IHVuZGVmaW5lZDtcbiAgLy8gVHJ1ZSBvbmNlIHRoZSBsb2NhbGUgcmVxdWVzdCBoYXMgYW5zd2VyZWQsIHdpdGggdGhlIGxpc3Qgb3IgYW4gZXJyb3IuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2xvY2FsZXNTZXR0bGVkID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gVHJ1ZSBvbmNlIHRoZSBmaWx0ZXIgcm93cyBhcmUgcHVibGlzaGVkIChzZWUgX2J1aWxkRmlsdGVyUm93cykuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2ZpbHRlcnNSZWFkeSA9IHNpZ25hbChmYWxzZSk7XG5cbiAgLy8gVGhlIGxvY2FsZSB0aGUgcmVwb3J0IHdvdWxkIGJlIHdyaXR0ZW4gaW46IHRoZSBzZWxlY3RlZCBvbmUgd2hlbiB0aGVcbiAgLy8gc2VydmVyIG9mZmVycyBpdCwgZWxzZSB0aGUgZGVmYXVsdCAoYSBzdG9yZWQgbG9jYWxlIGl0IG5vIGxvbmdlciBvZmZlcnNcbiAgLy8gZmFsbHMgYmFjayB0byB0aGUgZGVmYXVsdCwgYXMgaXQgZG9lcyBvbiB0aGUgc2VydmVyKS5cbiAgcHJpdmF0ZSByZWFkb25seSBfYXBwbGllZExvY2FsZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBsb2NhbGVzID0gdGhpcy5sb2NhbGVzKCk7XG4gICAgY29uc3QgbG9jYWxlID0gdGhpcy5sb2NhbGUoKTtcblxuICAgIHJldHVybiBsb2NhbGVzPy5vcHRpb25zLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLmxvY2FsZSA9PT0gbG9jYWxlKVxuICAgICAgPyBsb2NhbGVcbiAgICAgIDogbG9jYWxlcz8uZGVmYXVsdExvY2FsZSA/PyAnJztcbiAgfSk7XG5cbiAgLy8gVGhlIGN1cnJlbmN5IGEgcmVwb3J0IGluIHRoZSBhcHBsaWVkIGxvY2FsZSB1c2VzIHdoZW4gaXQgbmFtZXMgbm9uZS5cbiAgcHJpdmF0ZSByZWFkb25seSBfZGVmYXVsdEN1cnJlbmN5ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGxvY2FsZSA9IHRoaXMuX2FwcGxpZWRMb2NhbGUoKTtcblxuICAgIHJldHVybiB0aGlzLmxvY2FsZXMoKT8ub3B0aW9ucy5maW5kKChvcHRpb24pID0+IG9wdGlvbi5sb2NhbGUgPT09IGxvY2FsZSk/LmRlZmF1bHRDdXJyZW5jeVxuICAgICAgPz8gUkVQT1JUX0ZBTExCQUNLX0NVUlJFTkNZO1xuICB9KTtcblxuICAvLyBUaGUgY3VycmVuY3kgdGhlIHJlcG9ydCB3b3VsZCBsYWJlbCBtb25leSBpbjogdGhlIHNlbGVjdGVkIG9uZSB3aGVuIHRoZVxuICAvLyBzZXJ2ZXIgb2ZmZXJzIGl0LCBlbHNlIHRoZSBkZWZhdWx0LlxuICBwcml2YXRlIHJlYWRvbmx5IF9hcHBsaWVkQ3VycmVuY3kgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY3VycmVuY3kgPSB0aGlzLmN1cnJlbmN5KCk7XG5cbiAgICByZXR1cm4gdGhpcy5sb2NhbGVzKCk/LmN1cnJlbmNpZXMuaW5jbHVkZXMoY3VycmVuY3kpXG4gICAgICA/IGN1cnJlbmN5XG4gICAgICA6IHRoaXMuX2RlZmF1bHRDdXJyZW5jeSgpO1xuICB9KTtcblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgY29uc3QgcmVwb3J0ID0gdGhpcy5fZGF0YS5yZXBvcnQ7XG4gICAgdGhpcy5uYW1lID0gcmVwb3J0Lm5hbWU7XG4gICAgdGhpcy5wYWdlV2lkdGggPSByZXBvcnQucGFnZVdpZHRoO1xuICAgIHRoaXMucGFnZUhlaWdodCA9IHJlcG9ydC5wYWdlSGVpZ2h0O1xuICAgIHRoaXMuaGVhZGVySGVpZ2h0ID0gcmVwb3J0LmNvbmZpZz8uaGVhZGVyRm9vdGVyPy5oZWFkZXJIZWlnaHQgPz8gMDtcbiAgICB0aGlzLmZvb3RlckhlaWdodCA9IHJlcG9ydC5jb25maWc/LmhlYWRlckZvb3Rlcj8uZm9vdGVySGVpZ2h0ID8/IDA7XG4gICAgdGhpcy50aW1lem9uZSA9IHJlcG9ydC50aW1lem9uZSA/PyByZXBvcnQuZWZmZWN0aXZlVGltZXpvbmUgPz8gJyc7XG4gICAgdGhpcy5oZWFkaW5nU2l6ZSA9IHJlcG9ydC5jb25maWc/LnN0eWxlcz8uaGVhZGluZz8uc2l6ZSA/PyBERUZBVUxUX0hFQURJTkdfU0laRTtcbiAgICB0aGlzLmxvY2FsZS5zZXQocmVwb3J0LmxvY2FsZSA/PyAnJyk7XG4gICAgdGhpcy5jdXJyZW5jeS5zZXQocmVwb3J0LmN1cnJlbmN5ID8/ICcnKTtcblxuICAgIHRoaXMuX2J1aWxkRmlsdGVyUm93cyhyZXBvcnQpO1xuXG4gICAgaWYgKHRoaXMuX3NlcnZlckhhc0xvY2FsZSkge1xuICAgICAgdGhpcy5fcmVwb3J0RGF0YS5sb2NhbGVzKClcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFwKChsb2NhbGVzKSA9PiB0aGlzLmxvY2FsZXMuc2V0KGxvY2FsZXMpKSxcbiAgICAgICAgICBjYXRjaEVycm9yKCgpID0+IG9mKG51bGwpKSxcbiAgICAgICAgICBmaW5hbGl6ZSgoKSA9PiB0aGlzLl9sb2NhbGVzU2V0dGxlZC5zZXQodHJ1ZSkpLFxuICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQSBjaGFuZ2UgdG8gYSByb3cncyBMYWJlbCwgTmFtZSwgRGVmYXVsdCBwZXJpb2QsIGV4Y2x1ZGUgdG9nZ2xlIG9yIHJhbmdlIGVuZHMuIEEgbmV3XG4gIC8vIHJvdyBvYmplY3QgcmF0aGVyIHRoYW4gYSBtdXRhdGlvbiwgc28gdGhlIHNpZ25hbCBzZWVzIHRoZSBjaGFuZ2U7IHRoZVxuICAvLyBAZm9yIHRyYWNrcyBncm91cC5pZCwgc28gdGhlIHJvdydzIGNvbnRyb2xzIHN1cnZpdmUgdGhlIHN3YXAuXG4gIHB1YmxpYyBwYXRjaFJvdyhyb3c6IEZpbHRlckRlZmF1bHRSb3csIHBhdGNoOiBQYXJ0aWFsPEZpbHRlckRlZmF1bHRSb3c+KTogdm9pZCB7XG4gICAgdGhpcy5maWx0ZXJSb3dzLnVwZGF0ZSgocm93cykgPT4gcm93c1xuICAgICAgLm1hcCgoaXRlbSkgPT4gKGl0ZW0uZ3JvdXAuaWQgPT09IHJvdy5ncm91cC5pZCA/IHsgLi4uaXRlbSwgLi4ucGF0Y2ggfSA6IGl0ZW0pKSk7XG4gIH1cblxuICAvLyBGb2N1c2VzIHRoZSBMYWJlbCBvciBOYW1lIGlucHV0IHRoZSBzZXJ2ZXIgcmVmdXNlZCwgb25jZSBpdCBpcyBvblxuICAvLyBzY3JlZW46IHN0cmFpZ2h0IGFmdGVyIHRoZSByZWZ1c2FsIHdoZW4gdGhlIEZpbHRlcnMgdGFiIGlzIHNob3dpbmcsIGVsc2VcbiAgLy8gd2hlbiB0aGUgdGFiIGdyb3VwIGhhcyBicm91Z2h0IGl0IGZvcndhcmQuXG4gIHB1YmxpYyBmb2N1c1JlZnVzYWwoKTogdm9pZCB7XG4gICAgY29uc3QgaW5wdXQgPSB0aGlzLl9yZWZ1c2VkSW5wdXRJZCA/IHRoaXMuX2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuX3JlZnVzZWRJbnB1dElkKSA6IG51bGw7XG5cbiAgICBpZiAoaW5wdXQpIHtcbiAgICAgIGlucHV0LmZvY3VzKCk7XG4gICAgICB0aGlzLl9yZWZ1c2VkSW5wdXRJZCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gQ29uZmlybSBhbmQgZGVsZXRlIGhlcmUsIHdoaWxlIHRoZSBkaWFsb2cgaXMgc3RpbGwgb3BlbiwgdGhlbiBjbG9zZSB3aXRoXG4gIC8vIGEgYGRlbGV0ZWRgIHJlc3VsdC4gVGhlIHBhZ2UgcmVhY3RzIHRvIHRoZSByZXN1bHQ7IGl0IG5vIGxvbmdlciBvd25zIHRoZVxuICAvLyBwcm9tcHQgb3IgdGhlIEFQSSBjYWxsLlxuICBwdWJsaWMgZGVsZXRlKCk6IHZvaWQge1xuICAgIHRoaXMuX3Byb21wdC5jb25maXJtKHtcbiAgICAgIHRpdGxlOiAnRGVsZXRlIFJlcG9ydCcsXG4gICAgICB0ZW1wbGF0ZTogYERlbGV0ZSBcIiR7dGhpcy5fZGF0YS5yZXBvcnQubmFtZX1cIj8gVGhpcyBjYW5ub3QgYmUgdW5kb25lLmAsXG4gICAgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5fcmVwb3J0RGF0YS5kZWxldGUodGhpcy5fZGF0YS5yZXBvcnQuaWQpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnUmVwb3J0IGRlbGV0ZWQnKTtcbiAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgYWN0aW9uOiAnZGVsZXRlZCcgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlID0gKCkgPT4ge1xuICAgIGNvbnN0IHJlcG9ydElkID0gdGhpcy5fZGF0YS5yZXBvcnQuaWQ7XG5cbiAgICAvLyBPbmUgU2F2ZSBjb3ZlcnMgYWxsIHRocmVlIHRhYnMuIFRoZSByZXBvcnQgcmVsb2FkcyBvbiB0aGUgYHNhdmVkYFxuICAgIC8vIHJlc3VsdCwgcmUtc2VlZGluZyB0aGUgYmFyIGZyb20gdGhlIG5ldyBkZWZhdWx0cy5cbiAgICBjb25zdCBzZXR0aW5ncyA9IHtcbiAgICAgIG5hbWU6IHRoaXMubmFtZSxcbiAgICAgIHBhZ2VXaWR0aDogdGhpcy5fcGFnZURpbWVuc2lvbih0aGlzLnBhZ2VXaWR0aCksXG4gICAgICBwYWdlSGVpZ2h0OiB0aGlzLl9wYWdlRGltZW5zaW9uKHRoaXMucGFnZUhlaWdodCksXG4gICAgICAuLi50aGlzLl90aW1lem9uZVNldHRpbmcoKSxcbiAgICAgIC4uLnJlcG9ydExvY2FsZVBhdGNoKHRoaXMuX2RhdGEucmVwb3J0LCB0aGlzLmxvY2FsZSgpLCB0aGlzLmN1cnJlbmN5KCkpLFxuICAgICAgc3R5bGVzOiB7IGhlYWRpbmc6IHsgc2l6ZTogdGhpcy5oZWFkaW5nU2l6ZSB9IH0sXG4gICAgICBoZWFkZXJGb290ZXI6IHtcbiAgICAgICAgaGVhZGVySGVpZ2h0OiB0aGlzLl9wYWdlRGltZW5zaW9uKHRoaXMuaGVhZGVySGVpZ2h0KSB8fCAwLFxuICAgICAgICBmb290ZXJIZWlnaHQ6IHRoaXMuX3BhZ2VEaW1lbnNpb24odGhpcy5mb290ZXJIZWlnaHQpIHx8IDAsXG4gICAgICB9LFxuICAgIH07XG5cbiAgICAvLyBPbmUgZ3JvdXAgdXBkYXRlIHBlciBjaGFuZ2VkIGZpbHRlciwgY2Fycnlpbmcgb25seSB3aGF0IGNoYW5nZWQ6IGl0c1xuICAgIC8vIGxhYmVsLCBuYW1lIGFuZCBkZWZhdWx0IGFsbCBsaXZlIGluIHRoZSBncm91cCdzIGNvbmZpZywgc28gdHdvIHJlcXVlc3RzXG4gICAgLy8gZm9yIG9uZSBncm91cCB3b3VsZCBlYWNoIHdyaXRlIHRoZSBjb25maWcgb3ZlciB0aGUgb3RoZXIuXG4gICAgY29uc3Qgc2F2ZXMgPSB0aGlzLmZpbHRlclJvd3MoKVxuICAgICAgLm1hcCgocm93KSA9PiAoeyByb3csIGNoYW5nZXM6IHRoaXMuX2dyb3VwQ2hhbmdlcyhyb3cpIH0pKVxuICAgICAgLmZpbHRlcigoc2F2ZSkgPT4gT2JqZWN0LmtleXMoc2F2ZS5jaGFuZ2VzKS5sZW5ndGggPiAwKTtcblxuICAgIC8vIEEgbGFiZWwgb3IgbmFtZSBjYW4gYmUgcmVmdXNlZCwgc28gdGhvc2UgdXBkYXRlcyBnbyBmaXJzdCwgb25lIGFmdGVyXG4gICAgLy8gYW5vdGhlciwgYW5kIGEgcmVmdXNhbCBzdG9wcyB0aGUgc2F2ZSBiZWZvcmUgYW55dGhpbmcgZWxzZSBpcyB3cml0dGVuOlxuICAgIC8vIHRoZSByZXBvcnQgc2V0dGluZ3MgYW5kIHRoZSBvdGhlciBkZWZhdWx0cyB3YWl0IHVudGlsIGV2ZXJ5IG5hbWUgaXNcbiAgICAvLyB0YWtlbi4gSW4gc2VxdWVuY2UsIHR3byByZW5hbWVzIGluIG9uZSBzYXZlIGFyZSBjaGVja2VkIGFnYWluc3QgZWFjaFxuICAgIC8vIG90aGVyLCBhbmQgYSByZW5hbWUgb250byBhIG5hbWUgYW5vdGhlciBmaWx0ZXIgaXMgZ2l2aW5nIHVwIGdvZXMgYWZ0ZXJcbiAgICAvLyBpdC4gVGhlIHNlcnZlciBhcHBsaWVzIG5hbWUgYmVmb3JlIGRlZmF1bHQsIHNvIGEgcmVmdXNlZCBuYW1lIGxlYXZlc1xuICAgIC8vIHRoYXQgZmlsdGVyJ3MgZGVmYXVsdCB1bndyaXR0ZW4gdG9vLlxuICAgIGNvbnN0IG5hbWVkID0gdGhpcy5fcmVuYW1lT3JkZXIoc2F2ZXMuZmlsdGVyKChzYXZlKSA9PiB0aGlzLl9uYW1lc09yTGFiZWxzKHNhdmUuY2hhbmdlcykpKTtcbiAgICBjb25zdCBkZWZhdWx0cyA9IHNhdmVzLmZpbHRlcigoc2F2ZSkgPT4gIXRoaXMuX25hbWVzT3JMYWJlbHMoc2F2ZS5jaGFuZ2VzKSk7XG5cbiAgICByZXR1cm4gZnJvbShuYW1lZClcbiAgICAgIC5waXBlKFxuICAgICAgICBjb25jYXRNYXAoKHNhdmUpID0+IHRoaXMuX3NhdmVOYW1lZChyZXBvcnRJZCwgc2F2ZSkpLFxuICAgICAgICB0b0FycmF5KCksXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiBmb3JrSm9pbihbXG4gICAgICAgICAgdGhpcy5fcmVwb3J0RGF0YS51cGRhdGUocmVwb3J0SWQsIHNldHRpbmdzKSxcbiAgICAgICAgICAuLi5kZWZhdWx0cy5tYXAoKHNhdmUpID0+IHRoaXMuX3JlcG9ydERhdGEudXBkYXRlRmlsdGVyR3JvdXAocmVwb3J0SWQsIHNhdmUucm93Lmdyb3VwLmlkLCBzYXZlLmNoYW5nZXMpKSxcbiAgICAgICAgXS5tYXAoKHJlcXVlc3QkKSA9PiByZXF1ZXN0JC5waXBlKHRhcCgoKSA9PiB0aGlzLndyb3RlLnNldCh0cnVlKSkpKSkpLFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnUmVwb3J0IHNldHRpbmdzIHNhdmVkJyk7XG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgYWN0aW9uOiAnc2F2ZWQnIH0pO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH07XG5cbiAgLy8gVGhlIHBhZ2UgZGltZW5zaW9uIGFzIGEgcmVhbCBudW1iZXIgZm9yIHRoZSB3aXJlLiBmc01hc2tOdW1iZXIgaGFuZHMgYmFja1xuICAvLyB0aGUgdW5tYXNrZWQgc3RyaW5nIGl0IGJ1aWx0IHdpdGggYSBmaXhlZCAnLicgcmFkaXggKHdoaWNoIGlzIHRoZSB3aG9sZVxuICAvLyBwb2ludCBvZiB0aGUgbWFzayAtIGEgbmF0aXZlIG51bWJlciBpbnB1dCBwYWludHMgdGhlIHZpZXdlcidzIGxvY2FsZVxuICAvLyBzZXBhcmF0b3IgaW5zdGVhZCksIHNvIHRoZSBjYXN0IGhlcmUgaXMgYSBzdHJhaWdodCBwYXJzZSBhbmQgbmV2ZXIgc2VlcyBhXG4gIC8vIGNvbW1hLiBUaGUgYmFja2VuZCByZWplY3RzIGFueXRoaW5nIG5vbi1udW1lcmljIHJhdGhlciB0aGFuIGNvZXJjaW5nLCBzbyBhXG4gIC8vIE5hTiBmYWlscyBsb3VkbHkgaW5zdGVhZCBvZiBzaWxlbnRseSBzdG9yaW5nIGEgd3JvbmcgcGFnZSBzaXplLlxuICBwcml2YXRlIF9wYWdlRGltZW5zaW9uKHZhbHVlOiBudW1iZXIgfCBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID8gdmFsdWUgOiBwYXJzZUZsb2F0KHZhbHVlKTtcbiAgfVxuXG4gIC8vIFRoZSB6b25lIGZvciB0aGUgc2V0dGluZ3MgUFVULCBzZW50IG9ubHkgd2hlbiBpdCBtb3ZlcyB0aGUgcmVwb3J0IG9mZiB0aGVcbiAgLy8gem9uZSBpdCBhbHJlYWR5IHVzZXMsIHNvIGFuIHVudG91Y2hlZCBkaWFsb2cgbmV2ZXIgcGlucyBhIHJlcG9ydCB0aGF0XG4gIC8vIGZvbGxvd3MgdGhlIGFwcGxpY2F0aW9uIGRlZmF1bHQuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZFxuICAvLyBlZmZlY3RpdmVUaW1lem9uZSBnZXRzIHRoZSB6b25lIGV2ZXJ5IHRpbWUsIGFzIGl0IGFsd2F5cyBkaWQuXG4gIHByaXZhdGUgX3RpbWV6b25lU2V0dGluZygpOiB7IHRpbWV6b25lPzogc3RyaW5nIH0ge1xuICAgIGNvbnN0IGVmZmVjdGl2ZVRpbWV6b25lID0gdGhpcy5fZGF0YS5yZXBvcnQuZWZmZWN0aXZlVGltZXpvbmU7XG5cbiAgICByZXR1cm4gZWZmZWN0aXZlVGltZXpvbmUgPT09IHVuZGVmaW5lZCB8fCB0aGlzLnRpbWV6b25lICE9PSBlZmZlY3RpdmVUaW1lem9uZVxuICAgICAgPyB7IHRpbWV6b25lOiB0aGlzLnRpbWV6b25lIH1cbiAgICAgIDoge307XG4gIH1cblxuICAvLyBUaGUgc3RvcmVkIHZhbHVlIGFzIGl0cyBvd24gb3B0aW9uIHdoZW4gdGhlIHNlcnZlciBubyBsb25nZXIgb2ZmZXJzIGl0LCBzb1xuICAvLyB0aGUgc2VsZWN0IG5hbWVzIGl0IGluc3RlYWQgb2Ygc2hvd2luZyBibGFuay4gTGVmdCBhcyBpdCBpcywgaXQgaXMgbmV2ZXJcbiAgLy8gc2VudCAoc2VlIHJlcG9ydExvY2FsZVBhdGNoKSwgYW5kIHRoZSByZXBvcnQgcmVhZHMgdGhlIGRlZmF1bHQgbWVhbndoaWxlLlxuICBwcml2YXRlIF9zdG9yZWRPcHRpb24oXG4gICAgc3RvcmVkOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuICAgIG9mZmVyZWQ6IHN0cmluZ1tdLFxuICAgIGxhYmVsOiAodmFsdWU6IHN0cmluZykgPT4gc3RyaW5nLFxuICApOiBMb2NhbGVTZWxlY3RPcHRpb25bXSB7XG4gICAgcmV0dXJuIHN0b3JlZCAmJiAhb2ZmZXJlZC5pbmNsdWRlcyhzdG9yZWQpID8gW3sgdmFsdWU6IHN0b3JlZCwgbGFiZWw6IGxhYmVsKHN0b3JlZCkgfV0gOiBbXTtcbiAgfVxuXG4gIC8vIFdoYXQgYSBzYXZlIGNoYW5nZXMgb24gYSByb3cncyBncm91cDogdGhlIGxhYmVsLCBuYW1lIGFuZCBkZWZhdWx0LCBlYWNoXG4gIC8vIG9ubHkgd2hlbiB0aGUgb3BlcmF0b3IgY2hhbmdlZCBpdC4gTGFiZWwgYW5kIG5hbWUgYXJlIHNlbnQgb25seSB0byBhXG4gIC8vIHNlcnZlciB0aGF0IHNlbnQgYSBuYW1lLCBhbmQgbmV2ZXIgb25lIGZyb20gdGhlIG90aGVyLlxuICBwcml2YXRlIF9ncm91cENoYW5nZXMocm93OiBGaWx0ZXJEZWZhdWx0Um93KTogUmVwb3J0RmlsdGVyR3JvdXBDaGFuZ2VzIHtcbiAgICBjb25zdCBjaGFuZ2VzOiBSZXBvcnRGaWx0ZXJHcm91cENoYW5nZXMgPSB7fTtcblxuICAgIGlmIChyb3cuc2hvd05hbWUpIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gcm93LmxhYmVsLnRyaW0oKTtcbiAgICAgIGlmIChsYWJlbCAhPT0gKHJvdy5ncm91cC5sYWJlbCA/PyAnJykpIHtcbiAgICAgICAgY2hhbmdlcy5sYWJlbCA9IGxhYmVsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBuYW1lID0gcm93Lm5hbWUudHJpbSgpO1xuICAgICAgaWYgKG5hbWUgIT09IHJvdy5ncm91cC5uYW1lKSB7XG4gICAgICAgIGNoYW5nZXMubmFtZSA9IG5hbWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgcm93RGVmYXVsdCA9IHRoaXMuX3Jvd0RlZmF1bHQocm93KTtcbiAgICBpZiAoZGVmYXVsdENoYW5nZWQocm93Lmdyb3VwLmNvbmZpZz8uZGVmYXVsdCwgcm93RGVmYXVsdCkpIHtcbiAgICAgIGNoYW5nZXMuZGVmYXVsdCA9IHJvd0RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNoYW5nZXM7XG4gIH1cblxuICBwcml2YXRlIF9uYW1lc09yTGFiZWxzKGNoYW5nZXM6IFJlcG9ydEZpbHRlckdyb3VwQ2hhbmdlcyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjaGFuZ2VzLm5hbWUgIT09IHVuZGVmaW5lZCB8fCBjaGFuZ2VzLmxhYmVsICE9PSB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBUaGUgdXBkYXRlcyBpbiB0aGUgb3JkZXIgdGhleSBhcmUgc2VudDogYSByZW5hbWUgb250byBhIG5hbWUgYW5vdGhlclxuICAvLyBmaWx0ZXIgaG9sZHMgZ29lcyBhZnRlciB0aGUgb3RoZXJzLCBzbyBhIGZpbHRlciBnaXZpbmcgdGhhdCBuYW1lIHVwIGluXG4gIC8vIHRoZSBzYW1lIHNhdmUgaGFzIGRvbmUgc28gZmlyc3QuXG4gIHByaXZhdGUgX3JlbmFtZU9yZGVyKHNhdmVzOiBGaWx0ZXJHcm91cFNhdmVbXSk6IEZpbHRlckdyb3VwU2F2ZVtdIHtcbiAgICBjb25zdCBoZWxkID0gKHNhdmU6IEZpbHRlckdyb3VwU2F2ZSk6IGJvb2xlYW4gPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IHNhdmUuY2hhbmdlcy5uYW1lPy50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICByZXR1cm4gbmFtZSAhPT0gdW5kZWZpbmVkICYmIHRoaXMuZmlsdGVyUm93cygpXG4gICAgICAgIC5zb21lKChyb3cpID0+IHJvdy5ncm91cC5pZCAhPT0gc2F2ZS5yb3cuZ3JvdXAuaWQgJiYgcm93Lmdyb3VwLm5hbWU/LnRvTG93ZXJDYXNlKCkgPT09IG5hbWUpO1xuICAgIH07XG5cbiAgICByZXR1cm4gWy4uLnNhdmVzXS5zb3J0KChhLCBiKSA9PiBOdW1iZXIoaGVsZChhKSkgLSBOdW1iZXIoaGVsZChiKSkpO1xuICB9XG5cbiAgLy8gU2F2ZXMgYSBmaWx0ZXIncyB1cGRhdGUgdGhhdCBjYXJyaWVzIGEgbGFiZWwgb3IgbmFtZS4gQSByZWZ1c2FsIGlzIHRoZVxuICAvLyBzZXJ2ZXIncyB0byB3b3JkICgnTmFtZSBcInJlZ2lvblwiIGlzIGFscmVhZHkgdXNlZCBieSB0aGUgZmlsdGVyXG4gIC8vIFwiQXJlYVwiLicpLCBzbyBpdCBzaG93cyBvbiB0aGUgZmllbGQgcmF0aGVyIHRoYW4gaW4gYSBkaWFsb2csIGFuZCB0aGUgc2F2ZVxuICAvLyBmYWlscy4gV2hhdCB3YXMgc2F2ZWQgYmVjb21lcyB0aGUgcm93J3Mgc3RvcmVkIGdyb3VwLCBzbyBhIGxhdGVyIHNhdmVcbiAgLy8gZG9lcyBub3Qgc2VuZCBpdCBhZ2Fpbi5cbiAgcHJpdmF0ZSBfc2F2ZU5hbWVkKHJlcG9ydElkOiBudW1iZXIsIHNhdmU6IEZpbHRlckdyb3VwU2F2ZSk6IE9ic2VydmFibGU8dW5rbm93bj4ge1xuICAgIGNvbnN0IHsgcm93LCBjaGFuZ2VzIH0gPSBzYXZlO1xuXG4gICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEudXBkYXRlRmlsdGVyR3JvdXAoXG4gICAgICByZXBvcnRJZCxcbiAgICAgIHJvdy5ncm91cC5pZCxcbiAgICAgIGNoYW5nZXMsXG4gICAgICB7IGNvbnRleHQ6IG5ldyBIdHRwQ29udGV4dCgpLnNldChEaXNwbGF5QXBpRXJyb3IsIGZhbHNlKSB9LFxuICAgIClcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMud3JvdGUuc2V0KHRydWUpO1xuICAgICAgICAgIHRoaXMucGF0Y2hSb3cocm93LCB7IGdyb3VwOiBzdG9yZWRHcm91cChyb3cuZ3JvdXAsIGNoYW5nZXMpIH0pO1xuICAgICAgICB9KSxcbiAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgICAgICB0aGlzLl9zaG93UmVmdXNhbChyb3csIGNoYW5nZXMsIHJlZnVzYWxNZXNzYWdlKGVycm9yKSk7XG5cbiAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIC8vIFNob3dzIGEgcmVmdXNhbCBvbiB0aGUgZmllbGQgaXQgaXMgYWJvdXQgKHRoZSBuYW1lLCB3aGljaCB0aGUgc2VydmVyXG4gIC8vIGNoZWNrcyBmaXJzdCwgZWxzZSB0aGUgbGFiZWwpLCBicmluZ3MgdGhlIEZpbHRlcnMgdGFiIGZvcndhcmQgYW5kXG4gIC8vIGZvY3VzZXMgdGhlIGZpZWxkLCBzbyBhIHNhdmUgbWFkZSBmcm9tIGFub3RoZXIgdGFiIHNheXMgd2h5IGl0IGZhaWxlZC5cbiAgcHJpdmF0ZSBfc2hvd1JlZnVzYWwocm93OiBGaWx0ZXJEZWZhdWx0Um93LCBjaGFuZ2VzOiBSZXBvcnRGaWx0ZXJHcm91cENoYW5nZXMsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLm5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5wYXRjaFJvdyhyb3csIHsgbmFtZVJlZnVzYWw6IHsgdmFsdWU6IGNoYW5nZXMubmFtZSwgbWVzc2FnZSB9IH0pO1xuICAgICAgdGhpcy5fcmVmdXNlZElucHV0SWQgPSBuYW1lSW5wdXRJZChyb3cuZ3JvdXAuaWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnBhdGNoUm93KHJvdywgeyBsYWJlbFJlZnVzYWw6IHsgdmFsdWU6IGNoYW5nZXMubGFiZWwgPz8gJycsIG1lc3NhZ2UgfSB9KTtcbiAgICAgIHRoaXMuX3JlZnVzZWRJbnB1dElkID0gbGFiZWxJbnB1dElkKHJvdy5ncm91cC5pZCk7XG4gICAgfVxuXG4gICAgdGhpcy5zZWxlY3RlZFRhYi5zZXQoJ2ZpbHRlcnMnKTtcbiAgICBhZnRlck5leHRSZW5kZXIoKCkgPT4gdGhpcy5mb2N1c1JlZnVzYWwoKSwgeyBpbmplY3RvcjogdGhpcy5faW5qZWN0b3IgfSk7XG4gIH1cblxuICBwcml2YXRlIF90aHJvd0JvdW5kc0Vycm9yKG1pbjogdW5rbm93biwgbWF4OiB1bmtub3duKTogdm9pZCB7XG4gICAgY29uc3QgZXJyb3IgPSBib3VuZHNFcnJvcihwYXJzZURlZmF1bHRCb3VuZChtaW4pLCBwYXJzZURlZmF1bHRCb3VuZChtYXgpKTtcblxuICAgIGlmIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvLyBCdWlsZCBvbmUgZWRpdGFibGUgcm93IHBlciByZXBvcnQgYmFyIGZpbHRlciBncm91cCAoZXZlcnkgcGFnZSBvciBvbmVcbiAgLy8gcGFnZSksIGluIGJhciBvcmRlciwgc2VlZGluZyBlYWNoIGRyYWZ0IGZyb20gdGhlIGdyb3VwJ3Mgc3RvcmVkIGRlZmF1bHQuXG4gIHByaXZhdGUgX2J1aWxkRmlsdGVyUm93cyhyZXBvcnQ6IFJlcG9ydCk6IHZvaWQge1xuICAgIGNvbnN0IGJ1aWx0ID0gZGVmYXVsdFJvd0dyb3VwcyhyZXBvcnQuZmlsdGVyR3JvdXBzKVxuICAgICAgLm1hcCgoZ3JvdXApID0+IHtcbiAgICAgICAgY29uc3QgZ3JvdXBEZWZhdWx0ID0gZ3JvdXAuY29uZmlnPy5kZWZhdWx0O1xuICAgICAgICAvLyBPbmUgc2hhcmVkLCByZXBsYXllZCBvcHRpb24gc3RyZWFtIHBlciBncm91cDogdGhlIGNoaXBzIGZldGNoIGFuZCB0aGVcbiAgICAgICAgLy8gc3RvcmVkIGRlZmF1bHQncyBsYWJlbHMgcmVhZCB0aGUgc2FtZSBsaXN0LCBzbyBpdCBpcyBmZXRjaGVkIG9uY2UuXG4gICAgICAgIGNvbnN0IG9wdGlvbnMkID0gbG9hZEdyb3VwT3B0aW9ucyhncm91cCwgdGhpcy5fcmVwb3J0RGF0YSwgcmVwb3J0LmlkKTtcbiAgICAgICAgY29uc3Qgcm93ID0gdGhpcy5fZmlsdGVyUm93KHJlcG9ydCwgZ3JvdXAsIG9wdGlvbnMkKTtcblxuICAgICAgICByZXR1cm4geyByb3csIG9wdGlvbnMkLCB2YWx1ZXM6IGdyb3VwRGVmYXVsdD8udmFsdWVzID8/IGdyb3VwRGVmYXVsdD8uZXhjbHVkZVZhbHVlcyA/PyBbXSB9O1xuICAgICAgfSk7XG5cbiAgICBjb25zdCByb3dzID0gYnVpbHQubWFwKChlbnRyeSkgPT4gZW50cnkucm93KTtcbiAgICBjb25zdCBzZWVkZWQgPSBidWlsdC5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS52YWx1ZXMubGVuZ3RoKTtcblxuICAgIC8vIE5vdGhpbmcgdG8gbmFtZSDigJQgcHVibGlzaCBpbW1lZGlhdGVseSByYXRoZXIgdGhhbiB3YWl0aW5nIG9uIGEgcmVxdWVzdFxuICAgIC8vIG5vIHJvdyBuZWVkcy5cbiAgICBpZiAoIXNlZWRlZC5sZW5ndGgpIHtcbiAgICAgIHRoaXMuX3B1Ymxpc2hGaWx0ZXJSb3dzKHJvd3MpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQSBzdG9yZWQgc2VsZWN0IGRlZmF1bHQgaG9sZHMgaWRzLCBzbyBpdHMgY2hpcHMgY2FuIG9ubHkgYmUgbmFtZWQgb25jZSB0aGVcbiAgICAvLyBvcHRpb24gbGlzdCBpcyBpbi4gUmVzb2x2ZSBldmVyeSBzZWVkZWQgcm93IGZpcnN0IGFuZCBwdWJsaXNoIHRoZSByb3dzIGluXG4gICAgLy8gb25lIGdvLCBzbyB0aGUgdGFiIG5ldmVyIHJlbmRlcnMgYSBjaGlwIHNob3dpbmcgYSByYXcgaWQuIFdoZW4gYW4gb3B0aW9uXG4gICAgLy8gbGlzdCBmYWlscyB0byBsb2FkLCB0aGUgcm93cyBwdWJsaXNoIHVucmVzb2x2ZWQ6IGVhY2ggY2hpcCBuYW1lcyBpdHMgaWQsXG4gICAgLy8gYW5kIGFuIHVudG91Y2hlZCByb3cgc3RpbGwgc2F2ZXMgdGhlIHN0b3JlZCBkZWZhdWx0IHVuY2hhbmdlZC5cbiAgICBmb3JrSm9pbihzZWVkZWQubWFwKChlbnRyeSkgPT4gcmVzb2x2ZU9wdGlvblZhbHVlcyhlbnRyeS5vcHRpb25zJCwgZW50cnkudmFsdWVzKSkpXG4gICAgICAucGlwZShcbiAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBvZihzZWVkZWQubWFwKChlbnRyeSkgPT4gZW50cnkudmFsdWVzLm1hcCgodmFsdWUpID0+ICh7IG5hbWU6IFN0cmluZyh2YWx1ZSksIHZhbHVlIH0pKSkpKSxcbiAgICAgICAgdGFwKChyZXNvbHZlZCkgPT4ge1xuICAgICAgICAgIHJlc29sdmVkLmZvckVhY2goKHZhbHVlcywgaW5kZXgpID0+IHNlZWRlZFtpbmRleF0ucm93LnZhbHVlcyA9IHZhbHVlcyk7XG4gICAgICAgICAgdGhpcy5fcHVibGlzaEZpbHRlclJvd3Mocm93cyk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvLyBPbmUgcm93J3MgZHJhZnQsIHNlZWRlZCBmcm9tIGl0cyBncm91cCdzIHN0b3JlZCBkZWZhdWx0LiBBIHN0b3JlZCBzZWxlY3RcbiAgLy8gZGVmYXVsdCdzIHZhbHVlcyBhcmUgbmFtZWQgbGF0ZXIsIG9uY2UgdGhlIG9wdGlvbiBsaXN0IGNhcnJ5aW5nIHRoZWlyXG4gIC8vIGxhYmVscyBpcyBpbiAoc2VlIF9idWlsZEZpbHRlclJvd3MpLlxuICBwcml2YXRlIF9maWx0ZXJSb3coXG4gICAgcmVwb3J0OiBSZXBvcnQsXG4gICAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLFxuICAgIG9wdGlvbnMkOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+LFxuICApOiBGaWx0ZXJEZWZhdWx0Um93IHtcbiAgICBjb25zdCBncm91cERlZmF1bHQgPSBncm91cC5jb25maWc/LmRlZmF1bHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZ3JvdXAsXG4gICAgICBoZWFkaW5nOiBkZWZhdWx0Um93TGFiZWwoZ3JvdXAsIHJlcG9ydC5wYWdlcyksXG4gICAgICBsYWJlbDogZ3JvdXAubGFiZWwgPz8gJycsXG4gICAgICBuYW1lOiBncm91cC5uYW1lID8/ICcnLFxuICAgICAgc2hvd05hbWU6IHR5cGVvZiBncm91cC5uYW1lID09PSAnc3RyaW5nJyxcbiAgICAgIGxhYmVsUmVmdXNhbDogbnVsbCxcbiAgICAgIG5hbWVSZWZ1c2FsOiBudWxsLFxuICAgICAgcGVyaW9kOiBkZWZhdWx0UGVyaW9kKGdyb3VwRGVmYXVsdCksXG4gICAgICBwZXJpb2RPcHRpb25zOiBkZWZhdWx0UGVyaW9kT3B0aW9ucyhyZWxhdGl2ZUxhYmVsLCBncm91cERlZmF1bHQ/LnJlbGF0aXZlID8/IG51bGwpLFxuICAgICAgc3RhcnQ6IGRhdGVGcm9tQm91bmQoZ3JvdXBEZWZhdWx0Py5zdGFydCksXG4gICAgICBlbmQ6IGRhdGVGcm9tQm91bmQoZ3JvdXBEZWZhdWx0Py5lbmQpLFxuICAgICAgdmFsdWVzOiBbXSxcbiAgICAgIGV4Y2x1ZGU6ICEhZ3JvdXBEZWZhdWx0Py5leGNsdWRlVmFsdWVzPy5sZW5ndGgsXG4gICAgICAvLyBBbiBvbGRlciBzZXJ2ZXIgbGlzdHMgbm8gZmVhdHVyZXMsIGFuZCBsZWF2ZXMgbm8gdmFsdWVzIG91dC5cbiAgICAgIHNob3dFeGNsdWRlOiBzaG93RXhjbHVkZVRvZ2dsZShncm91cCwgcmVwb3J0LnZpZXdlckZlYXR1cmVzKSxcbiAgICAgIHZhbHVlOiBncm91cERlZmF1bHQ/LnZhbHVlID8/ICcnLFxuICAgICAgbWluOiBncm91cERlZmF1bHQ/Lm1pbiA/PyBudWxsLFxuICAgICAgbWF4OiBncm91cERlZmF1bHQ/Lm1heCA/PyBudWxsLFxuICAgICAgLy8gZnMtYXV0b2NvbXBsZXRlLWNoaXBzIGZldGNoOiB0aGUgZ3JvdXAncyBkaXN0aW5jdCBvcHRpb25zLCBuYW1lLWZpbHRlcmVkLlxuICAgICAgLy8gU2FtZSBsb2FkZXIgdGhlIHJlcG9ydCBiYXIgdXNlcywgc28gdGhlIHR3byBuZXZlciBkcmlmdC5cbiAgICAgIGZldGNoOiAoa2V5d29yZD86IHN0cmluZykgPT4gbWF0Y2hPcHRpb25zKG9wdGlvbnMkLCBrZXl3b3JkKSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBfcHVibGlzaEZpbHRlclJvd3Mocm93czogRmlsdGVyRGVmYXVsdFJvd1tdKTogdm9pZCB7XG4gICAgdGhpcy5maWx0ZXJSb3dzLnNldChyb3dzKTtcbiAgICB0aGlzLl9maWx0ZXJzUmVhZHkuc2V0KHRydWUpO1xuICB9XG5cbiAgLy8gVGhlIGRyYWZ0IGRlZmF1bHQgbm9ybWFsaXplZCB0byB0aGUgd2lyZSBzaGFwZSBmb3IgdGhpcyByb3cncyB0eXBlLCBvciBudWxsXG4gIC8vIHdoZW4gZW1wdHkgKHdoaWNoIGNsZWFycyB0aGUgc3RvcmVkIGRlZmF1bHQpLlxuICBwcml2YXRlIF9yb3dEZWZhdWx0KHJvdzogRmlsdGVyRGVmYXVsdFJvdyk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwge1xuICAgIHN3aXRjaCAocm93Lmdyb3VwLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICAgIHJldHVybiBkYXRlUmFuZ2VEZWZhdWx0KHJvdy5wZXJpb2QsIGRhdGVUb0JvdW5kKHJvdy5zdGFydCksIGRhdGVUb0JvdW5kKHJvdy5lbmQpKTtcblxuICAgICAgY2FzZSAnc2VsZWN0JzpcbiAgICAgICAgLy8gQSBoaWRkZW4gdG9nZ2xlIGxlYXZlcyBub3RoaW5nIG91dC5cbiAgICAgICAgcmV0dXJuIHNlbGVjdERlZmF1bHQocm93LnZhbHVlcy5tYXAoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlKSwgcm93LnNob3dFeGNsdWRlICYmIHJvdy5leGNsdWRlKTtcblxuICAgICAgY2FzZSAnbnVtYmVyUmFuZ2UnOlxuICAgICAgICByZXR1cm4gbnVtYmVyUmFuZ2VEZWZhdWx0KHJvdy5taW4sIHJvdy5tYXgpO1xuXG4gICAgICBjYXNlICdrZXl3b3JkJzpcbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSByb3cudmFsdWUudHJpbSgpO1xuXG4gICAgICAgIHJldHVybiB2YWx1ZSA/IHsgdmFsdWUgfSA6IG51bGw7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbn1cblxuXG4vLyBXaGF0IGEgcmVmdXNlZCByZXF1ZXN0IHNheXM6IHRoZSBzZXJ2ZXIncyBtZXNzYWdlLCBlbHNlIHRoZSBlcnJvcidzIG93bixcbi8vIGVsc2UgYSBwbGFpbiBmYWxsYmFjay5cbmZ1bmN0aW9uIHJlZnVzYWxNZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgY29uc3QgZmFpbHVyZSA9IGVycm9yIGFzIHsgZXJyb3I/OiB7IG1lc3NhZ2U/OiB1bmtub3duIH07IG1lc3NhZ2U/OiB1bmtub3duIH0gfCBudWxsO1xuICBjb25zdCBtZXNzYWdlID0gZmFpbHVyZT8uZXJyb3I/Lm1lc3NhZ2UgPz8gZmFpbHVyZT8ubWVzc2FnZTtcblxuICByZXR1cm4gdHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnICYmIG1lc3NhZ2UgPyBtZXNzYWdlIDogJ1RoZSBmaWx0ZXIgY291bGQgbm90IGJlIHNhdmVkLic7XG59XG5cbi8vIFRoZSBncm91cCBhcyB0aGUgc2VydmVyIG5vdyBzdG9yZXMgaXQsIG9uY2UgYW4gdXBkYXRlIGNhcnJ5aW5nIGBjaGFuZ2VzYFxuLy8gaXMgdGFrZW4uXG5mdW5jdGlvbiBzdG9yZWRHcm91cChncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsIGNoYW5nZXM6IFJlcG9ydEZpbHRlckdyb3VwQ2hhbmdlcyk6IFJlcG9ydEZpbHRlckdyb3VwIHtcbiAgcmV0dXJuIHtcbiAgICAuLi5ncm91cCxcbiAgICAuLi4oY2hhbmdlcy5uYW1lICE9PSB1bmRlZmluZWQgPyB7IG5hbWU6IGNoYW5nZXMubmFtZSB9IDoge30pLFxuICAgIC4uLihjaGFuZ2VzLmxhYmVsICE9PSB1bmRlZmluZWQgPyB7IGxhYmVsOiBjaGFuZ2VzLmxhYmVsIH0gOiB7fSksXG4gICAgY29uZmlnOiBjaGFuZ2VzLmRlZmF1bHQgIT09IHVuZGVmaW5lZFxuICAgICAgPyB7IC4uLmdyb3VwLmNvbmZpZywgZGVmYXVsdDogY2hhbmdlcy5kZWZhdWx0ID8/IHVuZGVmaW5lZCB9XG4gICAgICA6IGdyb3VwLmNvbmZpZyxcbiAgfTtcbn1cblxuLy8gVGhlIGlkcyBvZiBhIGZpbHRlcidzIExhYmVsIGFuZCBOYW1lIGlucHV0cywgc28gYSByZWZ1c2VkIG9uZSBjYW4gYmVcbi8vIGZvY3VzZWQuXG5mdW5jdGlvbiBsYWJlbElucHV0SWQoZ3JvdXBJZDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBmaWx0ZXJMYWJlbCR7Z3JvdXBJZH1gO1xufVxuXG5mdW5jdGlvbiBuYW1lSW5wdXRJZChncm91cElkOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gYGZpbHRlck5hbWUke2dyb3VwSWR9YDtcbn1cbiIsIjxmb3JtXG4gICAgZnNGb3JtXG4gICAgW3N1Ym1pdF09XCJzYXZlXCI+XG4gIDxmcy1kaWFsb2c+XG4gICAgPGgxIG1hdC1kaWFsb2ctdGl0bGU+XG4gICAgICBSZXBvcnQgU2V0dGluZ3NcbiAgICA8L2gxPlxuICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICA8IS0tIE9uZSBza2VsZXRvbiBvdmVyIHRoZSB3aG9sZSBib2R5IHVudGlsIHRoZSBsb2NhbGUgbGlzdCBpcyBpbi4gLS0+XG4gICAgICA8bmctY29udGFpbmVyICpmc1NrZWxldG9uRm9ybT1cInJlYWR5KCkgfHwgbnVsbFwiPlxuICAgICAgICA8IS0tIGFuaW1hdGlvbkRvbmU6IGEgcmVmdXNlZCBMYWJlbCBvciBOYW1lIGlzIGZvY3VzZWQgb25jZSB0aGVcbiAgICAgICAgICAgICBGaWx0ZXJzIHRhYiBpcyBvbiBzY3JlZW4uIC0tPlxuICAgICAgICA8bWF0LXRhYi1ncm91cFxuICAgICAgICAgICAgWyhzZWxlY3RlZCldPVwic2VsZWN0ZWRUYWJcIlxuICAgICAgICAgICAgKGFuaW1hdGlvbkRvbmUpPVwiZm9jdXNSZWZ1c2FsKClcIj5cbiAgICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAgICAgICAgICAgICAgbmFtZT1cInNldHRpbmdzXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uIHRhYi1ib2R5XCI+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgTmFtZVxuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwibmFtZVwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwibmFtZVwiXG4gICAgICAgICAgICAgICAgICBbZnNGb3JtUmVxdWlyZWRdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICA8IS0tXG4gICAgICAgICAgICAgICAgVGhlIHBhZ2UsIHR5cGVkIGluIGluY2hlcy4gT3JpZW50YXRpb24gaXMgbm90IGFza2VkIGZvciBiZWNhdXNlIGl0XG4gICAgICAgICAgICAgICAgaXMgbm90IGFuIGluZGVwZW5kZW50IGNob2ljZSAtIGEgcGFnZSB3aWRlciB0aGFuIGl0IGlzIHRhbGwgSVNcbiAgICAgICAgICAgICAgICBsYW5kc2NhcGUgLSBzbyB0aGUgdHdvIG51bWJlcnMgc2F5IGV2ZXJ5dGhpbmcgdGhlcmUgaXMgdG8gc2F5LlxuICAgICAgICAgICAgICAtLT5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZzLXJvdy5nYXAtc20uYWxpZ24tc3RhcnRcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmcy1mbGV4XCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBXaWR0aFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIxXCJcbiAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhZ2VXaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZ2VXaWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwicGFnZURpbWVuc2lvbk1pblwiXG4gICAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCJwYWdlRGltZW5zaW9uTWF4XCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICAgIGluY2hlc1xuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmcy1mbGV4XCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBIZWlnaHRcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiMVwiXG4gICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWdlSGVpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFnZUhlaWdodFwiXG4gICAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwicGFnZURpbWVuc2lvbk1pblwiXG4gICAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCJwYWdlRGltZW5zaW9uTWF4XCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICAgIGluY2hlc1xuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwhLS1cbiAgICAgICAgICAgICAgICBIb3cgZGVlcCB0aGUgaGVhZGVyIGFuZCBmb290ZXIgYmFuZHMgYXJlLiBUaGVpciBjb250ZW50IGlzIGVkaXRlZFxuICAgICAgICAgICAgICAgIG9uIHRoZSBjYW52YXMgKEVkaXQgbGF5b3V0IOKGkiBIZWFkZXIgJiBmb290ZXIpOyB0aGVzZSByZXNlcnZlIHRoZVxuICAgICAgICAgICAgICAgIHNwYWNlIGZvciBpdCwgYW5kIDAgbWVhbnMgbm8gYmFuZC5cbiAgICAgICAgICAgICAgLS0+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgSGVhZGVyIGhlaWdodFxuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjJcIlxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImhlYWRlckhlaWdodFwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJoZWFkZXJIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjBcIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWF4XT1cImhlYWRlckZvb3Rlck1heFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgIGluY2hlc1xuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIEZvb3RlciBoZWlnaHRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIyXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJmb290ZXJIZWlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwiZm9vdGVySGVpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCJoZWFkZXJGb290ZXJNYXhcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICBpbmNoZXNcbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPGZzLWFpLXJlcG9ydC10aW1lem9uZS1zZWxlY3QgWyh0aW1lem9uZSldPVwidGltZXpvbmVcIj48L2ZzLWFpLXJlcG9ydC10aW1lem9uZS1zZWxlY3Q+XG4gICAgICAgICAgICAgIDwhLS1cbiAgICAgICAgICAgICAgICBIb3cgbnVtYmVycyBhbmQgZGF0ZXMgYXJlIHdyaXR0ZW4gKGZvcm1hdHRpbmcgb25seTogbm8gdGV4dCBpc1xuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZWQpIGFuZCB3aGljaCBjdXJyZW5jeSBtb25leSBpcyBsYWJlbGVkIGluLiBIaWRkZW4gb24gYVxuICAgICAgICAgICAgICAgIHNlcnZlciB0b28gb2xkIHRvIHJlc29sdmUgYSByZXBvcnQncyBsb2NhbGUuXG4gICAgICAgICAgICAgIC0tPlxuICAgICAgICAgICAgICBAaWYgKGxvY2FsZXMoKSkge1xuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIExvY2FsZVxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImxvY2FsZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJsb2NhbGUuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJsb2NhbGVcIj5cbiAgICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIGxvY2FsZU9wdGlvbnMoKTsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm9wdGlvbi52YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgb3B0aW9uLmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgIHt7IGZvcm1hdEV4YW1wbGUoKSB9fVxuICAgICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIEN1cnJlbmN5XG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwiY3VycmVuY3koKVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiY3VycmVuY3kuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJjdXJyZW5jeVwiPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2YgY3VycmVuY3lPcHRpb25zKCk7IHRyYWNrIG9wdGlvbi52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5sYWJlbCB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBOYW1lcyB0aGUgY3VycmVuY3kgYW1vdW50cyBhcmUgaW47IGl0IGRvZXMgbm90IGNvbnZlcnQgdGhlbS5cbiAgICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9tYXQtdGFiPlxuICAgICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICAgIGxhYmVsPVwiU3R5bGVzXCJcbiAgICAgICAgICAgICAgbmFtZT1cInN0eWxlc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtbiB0YWItYm9keVwiPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIEhlYWRpbmcgU2l6ZVxuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgc3RlcD1cIjFcIlxuICAgICAgICAgICAgICAgICAgbWluPVwiNlwiXG4gICAgICAgICAgICAgICAgICBtYXg9XCI5NlwiXG4gICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImhlYWRpbmdTaXplXCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJoZWFkaW5nU2l6ZVwiXG4gICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjZcIlxuICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCI5NlwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICBwdFxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICBBcHBsaWVzIHRvIGNvbXBvbmVudCB0aXRsZXMuIFBvaW50cyBtYXAgMToxIHRvIFBERiBhbmQgUG93ZXJQb2ludC5cbiAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9tYXQtdGFiPlxuICAgICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICAgIGxhYmVsPVwiRmlsdGVyc1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJmaWx0ZXJzXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uIHRhYi1ib2R5XCI+XG4gICAgICAgICAgICAgIEBpZiAoZmlsdGVyUm93cygpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIDwhLS0gT25lIHNlY3Rpb24gcGVyIHJlcG9ydCBiYXIgZmlsdGVyOiBpdHMgaGVhZGluZywgaXRzIGxhYmVsXG4gICAgICAgICAgICAgICAgICAgICBhbmQgbmFtZSwgdGhlbiBpdHMgZGVmYXVsdCwgb25lIGZpZWxkIHBlciByb3cuIC0tPlxuICAgICAgICAgICAgICAgIEBmb3IgKHJvdyBvZiBmaWx0ZXJSb3dzKCk7IHRyYWNrIHJvdy5ncm91cC5pZCkge1xuICAgICAgICAgICAgICAgICAgPGgzPlxuICAgICAgICAgICAgICAgICAgICB7eyByb3cuaGVhZGluZyB9fVxuICAgICAgICAgICAgICAgICAgPC9oMz5cbiAgICAgICAgICAgICAgICAgIDwhLS0gVGhlIGxhYmVsIGFuZCB0aGUgbmFtZSBhcmUgaW5kZXBlbmRlbnQ6IGEgbmV3IGxhYmVsXG4gICAgICAgICAgICAgICAgICAgICAgIG5ldmVyIGNoYW5nZXMgdGhlIG5hbWUsIGFuZCB0aGUgbmFtZSBpcyBlZGl0ZWQgb24gaXRzXG4gICAgICAgICAgICAgICAgICAgICAgIG93bi4gVGhlIHNlcnZlciBjaGVja3MgYm90aCwgYW5kIGl0cyByZWZ1c2FsIHNob3dzIG9uXG4gICAgICAgICAgICAgICAgICAgICAgIHRoZSBmaWVsZCAocmVmdXNhbFZhbGlkYXRvcikuIC0tPlxuICAgICAgICAgICAgICAgICAgQGlmIChyb3cuc2hvd05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICBMYWJlbFxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBbaWRdPVwibGFiZWxJbnB1dElkKHJvdy5ncm91cC5pZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cubGFiZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJwYXRjaFJvdyhyb3csIHsgbGFiZWw6ICRldmVudCB9KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidsYWJlbCcgKyByb3cuZ3JvdXAuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbZnNGb3JtUmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhMZW5ndGhdPVwibGFiZWxNYXhMZW5ndGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsaWRhdGVdPVwicmVmdXNhbFZhbGlkYXRvclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFt2YWxpZGF0ZURhdGFdPVwicm93LmxhYmVsUmVmdXNhbFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgICAgICAgIFdoYXQgdGhlIGZpbHRlciBzaG93cy4gQ2hhbmdpbmcgaXQgbmV2ZXIgY2hhbmdlcyB0aGUgbmFtZS5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIE5hbWVcbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cIm5hbWVJbnB1dElkKHJvdy5ncm91cC5pZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cubmFtZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInBhdGNoUm93KHJvdywgeyBuYW1lOiAkZXZlbnQgfSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCInbmFtZScgKyByb3cuZ3JvdXAuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbZnNGb3JtUmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1QYXR0ZXJuXT1cIm5hbWVQYXR0ZXJuXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybVBhdHRlcm5NZXNzYWdlXT1cIm5hbWVQYXR0ZXJuTWVzc2FnZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhMZW5ndGhdPVwibmFtZU1heExlbmd0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFt2YWxpZGF0ZV09XCJyZWZ1c2FsVmFsaWRhdG9yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbGlkYXRlRGF0YV09XCJyb3cubmFtZVJlZnVzYWxcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgICAgICBIb3cgdGhlIEFJIHJlZmVycyB0byB0aGlzIGZpbHRlcjogYSBsZXR0ZXIsIHRoZW4gbGV0dGVycyBhbmQgZGlnaXRzLlxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBAc3dpdGNoIChyb3cuZ3JvdXAudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBAY2FzZSAoJ2RhdGVSYW5nZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBEZWZhdWx0IHBlcmlvZFxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5wZXJpb2RcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInBhdGNoUm93KHJvdywgeyBwZXJpb2Q6ICRldmVudCB9KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ3BlcmlvZCcgKyByb3cuZ3JvdXAuaWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIHJvdy5wZXJpb2RPcHRpb25zOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgQGlmIChyb3cucGVyaW9kID09PSBmaXhlZERhdGVzUGVyaW9kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCBmcm9tXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzRGF0ZVBpY2tlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicm93LnN0YXJ0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCInc3RhcnQnICsgcm93Lmdyb3VwLmlkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQgdG9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnNEYXRlUGlja2VyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cuZW5kXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCInZW5kJyArIHJvdy5ncm91cC5pZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGNhc2UgKCdzZWxlY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGZzLWxhYmVsLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGZzLWF1dG9jb21wbGV0ZS1jaGlwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZnVsbC13aWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9XCJEZWZhdWx0IHZhbHVlc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ZldGNoXT1cInJvdy5mZXRjaFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3cudmFsdWVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCIndmFsdWVzJyArIHJvdy5ncm91cC5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW211bHRpcGxlXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmZXRjaE9uRm9jdXNdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzQXV0b2NvbXBsZXRlQ2hpcHNUZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0LW9iamVjdD1cIm9iamVjdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9iamVjdC5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2ZzLWF1dG9jb21wbGV0ZS1jaGlwcz5cbiAgICAgICAgICAgICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIEBpZiAocm93LnNob3dFeGNsdWRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cuZXhjbHVkZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJwYXRjaFJvdyhyb3csIHsgZXhjbHVkZTogJGV2ZW50IH0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIidleGNsdWRlJyArIHJvdy5ncm91cC5pZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV4Y2x1ZGUgdGhlc2UgdmFsdWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNsaWRlLXRvZ2dsZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBjYXNlICgnbnVtYmVyUmFuZ2UnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPCEtLSBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0ZXh0OyB0aGUgY2hlY2sgYW5kIHRoZSBzYXZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkIGl0IHRocm91Z2ggcGFyc2VEZWZhdWx0Qm91bmQsIHNvIDAgaXMga2VwdC4gLS0+XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCBtaW5pbXVtXG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3NpZ25lZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiYm91bmRTY2FsZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwicm93Lm1pblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwicGF0Y2hSb3cocm93LCB7IG1pbjogJGV2ZW50IH0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCInbWluJyArIHJvdy5ncm91cC5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbGlkYXRlXT1cIm1pbkJvdW5kVmFsaWRhdG9yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsaWRhdGVEYXRhXT1cInJvdy5tYXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQgbWF4aW11bVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaWduZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cImJvdW5kU2NhbGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5tYXhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInBhdGNoUm93KHJvdywgeyBtYXg6ICRldmVudCB9KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ21heCcgKyByb3cuZ3JvdXAuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt2YWxpZGF0ZV09XCJtYXhCb3VuZFZhbGlkYXRvclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbGlkYXRlRGF0YV09XCJyb3cubWluXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBAZGVmYXVsdCB7XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVmYXVsdCB0ZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvdy52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cIid2YWx1ZScgKyByb3cuZ3JvdXAuaWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8ZnMtbWVzc2FnZS1pbmZvPlxuICAgICAgICAgICAgICAgICAgVGhpcyByZXBvcnQgaGFzIG5vIHJlcG9ydCBiYXIgZmlsdGVycyB5ZXQuIEFkZCBhIGZpbHRlciB0byBhXG4gICAgICAgICAgICAgICAgICBjb21wb25lbnQgKGl0cyBzZXR0aW5ncyDihpIgRmlsdGVycykgYW5kIHNob3cgaXQgaW4gdGhlIHJlcG9ydCBiYXIsXG4gICAgICAgICAgICAgICAgICB0aGVuIHNldCBpdHMgZGVmYXVsdCBoZXJlLlxuICAgICAgICAgICAgICAgIDwvZnMtbWVzc2FnZS1pbmZvPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIDwvbWF0LXRhYi1ncm91cD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvbWF0LWRpYWxvZy1jb250ZW50PlxuICAgIDxtYXQtZGlhbG9nLWFjdGlvbnM+XG4gICAgICA8ZnMtZm9ybS1kaWFsb2ctYWN0aW9ucz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgKGNsaWNrKT1cImRlbGV0ZSgpXCI+XG4gICAgICAgICAgRGVsZXRlXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9mcy1mb3JtLWRpYWxvZy1hY3Rpb25zPlxuICAgIDwvbWF0LWRpYWxvZy1hY3Rpb25zPlxuICA8L2ZzLWRpYWxvZz5cbjwvZm9ybT4iXX0=