@firestitch/report 18.8.0 → 18.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/reports/components/component-text/component-text.component.d.ts +47 -2
- package/app/reports/components/component-text/value-embed.plugin.d.ts +67 -0
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +34 -9
- package/app/reports/components/report-component/report-component.component.d.ts +10 -1
- package/app/reports/data/report.data.d.ts +2 -1
- package/app/reports/dialogs/component-settings/component-settings.component.d.ts +8 -0
- package/app/reports/enums/report-value-formula.enum.d.ts +6 -0
- package/app/reports/export/report-export-collector.service.d.ts +24 -0
- package/app/reports/export/report-export.service.d.ts +3 -1
- package/app/reports/export/report-pdf.service.d.ts +18 -2
- package/app/reports/export/report-pptx.service.d.ts +15 -2
- package/app/reports/export/report-text-layout.service.d.ts +35 -0
- package/app/reports/format.d.ts +5 -1
- package/app/reports/interfaces/report.interface.d.ts +22 -3
- package/app/reports/layout.d.ts +2 -0
- package/app/reports/services/report-filter-state.service.d.ts +1 -1
- package/app/reports/text.d.ts +50 -0
- package/app/reports/theme/palette.d.ts +2 -0
- package/app/reports/values.d.ts +17 -0
- package/esm2022/app/reports/components/component-text/component-text.component.mjs +213 -16
- package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +484 -0
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +260 -34
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +65 -19
- package/esm2022/app/reports/data/report.data.mjs +19 -1
- package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +134 -23
- package/esm2022/app/reports/enums/report-value-formula.enum.mjs +14 -0
- package/esm2022/app/reports/export/report-export-collector.service.mjs +170 -44
- package/esm2022/app/reports/export/report-export.service.mjs +57 -19
- package/esm2022/app/reports/export/report-pdf.service.mjs +339 -96
- package/esm2022/app/reports/export/report-pptx.service.mjs +316 -88
- package/esm2022/app/reports/export/report-text-layout.service.mjs +241 -0
- package/esm2022/app/reports/format.mjs +41 -10
- package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
- package/esm2022/app/reports/kpi-card.mjs +19 -6
- package/esm2022/app/reports/layout.mjs +11 -1
- package/esm2022/app/reports/option-builder.mjs +18 -5
- package/esm2022/app/reports/output-notes.mjs +57 -11
- package/esm2022/app/reports/services/report-filter-state.service.mjs +19 -10
- package/esm2022/app/reports/text.mjs +293 -85
- package/esm2022/app/reports/theme/palette.mjs +7 -2
- package/esm2022/app/reports/values.mjs +183 -0
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +4 -1
- package/esm2022/app/reports/views/report/report.component.mjs +4 -1
- package/esm2022/public_api.mjs +2 -1
- package/fesm2022/{firestitch-report-echarts-qCBE3LqM.mjs → firestitch-report-echarts-DBMOHmBF.mjs} +2 -2
- package/fesm2022/{firestitch-report-echarts-qCBE3LqM.mjs.map → firestitch-report-echarts-DBMOHmBF.mjs.map} +1 -1
- package/fesm2022/{firestitch-report-firestitch-report-DbsWbE-j.mjs → firestitch-report-firestitch-report-CqbXT1gh.mjs} +3492 -1028
- package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +1 -0
- package/fesm2022/firestitch-report-firestitch-report-DbsWbE-j.mjs.map +0 -1
|
@@ -20,10 +20,13 @@ import { switchMap, tap } from 'rxjs/operators';
|
|
|
20
20
|
import { ReportData } from '../../data/report.data';
|
|
21
21
|
import { ReportChangePolarity } from '../../enums/report-change-polarity.enum';
|
|
22
22
|
import { ReportValueFormat } from '../../enums/report-value-format.enum';
|
|
23
|
+
import { ReportValueFormula } from '../../enums/report-value-formula.enum';
|
|
23
24
|
import { resolveFormatContext } from '../../format';
|
|
24
25
|
import { KPI_SPARKLINE_DEFAULT_GRANULARITY, KPI_SPARKLINE_DEFAULT_PERIODS, kpiCardSettings, sameKpiCardSettings, } from '../../kpi-card';
|
|
25
26
|
import { GRANULARITY_OPTIONS, } from '../../interfaces/report.interface';
|
|
26
27
|
import { DEFAULT_COMPONENT_PADDING } from '../../layout';
|
|
28
|
+
import { escapeHtml } from '../../text';
|
|
29
|
+
import { operandKeys, reportComponents, valueKey } from '../../values';
|
|
27
30
|
import * as i0 from "@angular/core";
|
|
28
31
|
import * as i1 from "@angular/forms";
|
|
29
32
|
import * as i2 from "@firestitch/form";
|
|
@@ -45,8 +48,17 @@ const KPI_SPARKLINE_MAX_PERIODS = 60;
|
|
|
45
48
|
// stored as the 0-1 ratio its value arrives in; the server refuses a stored
|
|
46
49
|
// target above 100, which is 10,000% here.
|
|
47
50
|
const KPI_PERCENT_TARGET_MAX = 10000;
|
|
51
|
+
// How a formula value's Settings tab writes out what it works out, in its
|
|
52
|
+
// operands' names.
|
|
53
|
+
const FORMULA_LINES = {
|
|
54
|
+
[ReportValueFormula.Change]: (names) => names.join(' − '),
|
|
55
|
+
[ReportValueFormula.PercentChange]: ([a, b]) => `% change of ${a} over ${b}`,
|
|
56
|
+
[ReportValueFormula.Ratio]: (names) => names.join(' ÷ '),
|
|
57
|
+
[ReportValueFormula.Sum]: (names) => names.join(' + '),
|
|
58
|
+
};
|
|
48
59
|
// Component settings, in tabs:
|
|
49
|
-
// Settings — title and content padding
|
|
60
|
+
// Settings — title and content padding (a value: just its name, since it
|
|
61
|
+
// sits inside a text block's words and has no box), and on a derived KPI its card:
|
|
50
62
|
// what a rise means, a target and a sparkline (number formats stay with
|
|
51
63
|
// the AI). Position/size are tuned by dragging on the canvas; height
|
|
52
64
|
// behaviour follows from the component type.
|
|
@@ -54,8 +66,12 @@ const KPI_PERCENT_TARGET_MAX = 10000;
|
|
|
54
66
|
// row carries two toggles: show in the report bar and/or show on this
|
|
55
67
|
// component (both, either, or neither). The interface (date range vs value
|
|
56
68
|
// picker) is inferred from the data, never chosen. Each toggle persists
|
|
57
|
-
// immediately and refreshes the in-dialog list.
|
|
69
|
+
// immediately and refreshes the in-dialog list. A value has no component
|
|
70
|
+
// to show a filter on, so it gets the report bar toggle only.
|
|
58
71
|
// SQL / Config — read-only diagnostics.
|
|
72
|
+
// A formula value has no Filters or SQL tab: the server works it out of other
|
|
73
|
+
// values on its page, so it runs no statement and follows the filters of the
|
|
74
|
+
// values it reads. Its Settings tab says what it works out, under its name.
|
|
59
75
|
export class ComponentSettingsComponent {
|
|
60
76
|
// A filter was added, removed or re-levelled, so the report's filter groups
|
|
61
77
|
// changed. Those mutations persist the moment they are clicked and the dialog
|
|
@@ -80,6 +96,13 @@ export class ComponentSettingsComponent {
|
|
|
80
96
|
sparklineMinPeriods = KPI_SPARKLINE_MIN_PERIODS;
|
|
81
97
|
sparklineMaxPeriods = KPI_SPARKLINE_MAX_PERIODS;
|
|
82
98
|
kpiCard = signal(false);
|
|
99
|
+
// A value inside a text block: no box, so no padding.
|
|
100
|
+
isValue = signal(false);
|
|
101
|
+
// A formula value: no statement, columns or filters of its own.
|
|
102
|
+
isFormula = signal(false);
|
|
103
|
+
// What a formula works out, in its operands' names; empty for any other
|
|
104
|
+
// component.
|
|
105
|
+
formulaLine = computed(() => (this.isFormula() ? this._formulaLine() : ''));
|
|
83
106
|
increaseIs = signal(ReportChangePolarity.Good);
|
|
84
107
|
// The target as typed: fsMaskNumber hands back the unmasked string. Empty
|
|
85
108
|
// means no target. A percent KPI's is in percent (targetPercent).
|
|
@@ -128,6 +151,8 @@ export class ComponentSettingsComponent {
|
|
|
128
151
|
this.report = this._data.report;
|
|
129
152
|
this.component = this._data.component;
|
|
130
153
|
this.title = this.component.title ?? '';
|
|
154
|
+
this.isValue.set(this.component.type === 'value');
|
|
155
|
+
this.isFormula.set(!!this.component.config?.formula);
|
|
131
156
|
const padding = this.component.config?.padding;
|
|
132
157
|
this.paddingTop = padding?.top ?? DEFAULT_COMPONENT_PADDING;
|
|
133
158
|
this.paddingRight = padding?.right ?? DEFAULT_COMPONENT_PADDING;
|
|
@@ -136,8 +161,12 @@ export class ComponentSettingsComponent {
|
|
|
136
161
|
this.configJson = JSON.stringify(this.component.config ?? {}, null, 2);
|
|
137
162
|
this._seedKpiCard();
|
|
138
163
|
this._seedFilters(this.report, this.component.id);
|
|
139
|
-
|
|
140
|
-
|
|
164
|
+
// A formula has no statement to compile and no columns to filter on, and
|
|
165
|
+
// the server would refuse both requests.
|
|
166
|
+
if (!this.isFormula()) {
|
|
167
|
+
this._loadColumns();
|
|
168
|
+
this._loadSql();
|
|
169
|
+
}
|
|
141
170
|
}
|
|
142
171
|
// Human-friendly name for the inferred interface shown beside each column.
|
|
143
172
|
typeLabel(type) {
|
|
@@ -149,16 +178,26 @@ export class ComponentSettingsComponent {
|
|
|
149
178
|
//
|
|
150
179
|
// The confirm says it cannot be undone because, from the UI, it cannot: the
|
|
151
180
|
// row is soft-deleted server-side but nothing here restores a component.
|
|
181
|
+
// A value's confirm also says what goes with it: the server takes its
|
|
182
|
+
// tokens out of every text on its page, not just the one it was opened from,
|
|
183
|
+
// and deletes the formulas that read it (_dependentsNote).
|
|
184
|
+
//
|
|
185
|
+
// The prompt renders its template as html, so every name in it is escaped.
|
|
152
186
|
delete() {
|
|
153
|
-
this._prompt.confirm(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
187
|
+
this._prompt.confirm(this.isValue()
|
|
188
|
+
? {
|
|
189
|
+
title: 'Delete Value',
|
|
190
|
+
template: `Delete the value "${escapeHtml(this.component.title || valueKey(this.component))}"? It is also taken out of every text on this page. This cannot be undone.${this._dependentsNote()}`,
|
|
191
|
+
}
|
|
192
|
+
: {
|
|
193
|
+
title: 'Delete Component',
|
|
194
|
+
template: `Are you sure you would like to delete "${escapeHtml(this.component.title || 'this component')}"? This cannot be undone.`,
|
|
195
|
+
})
|
|
196
|
+
.pipe(switchMap(() => this._reportData.deleteComponent(this.report.id, this.component.id)), tap(() => {
|
|
197
|
+
this._message.success(this.isValue() ? 'Value deleted' : 'Component deleted');
|
|
160
198
|
this._dialogRef.close({ deleted: true });
|
|
161
|
-
})
|
|
199
|
+
}), takeUntilDestroyed(this._destroyRef))
|
|
200
|
+
.subscribe();
|
|
162
201
|
}
|
|
163
202
|
// A percent target's bound, in the percent it is typed in. It reads the
|
|
164
203
|
// control, which fsForm validates before ngModelChange updates the signal.
|
|
@@ -170,7 +209,9 @@ export class ComponentSettingsComponent {
|
|
|
170
209
|
};
|
|
171
210
|
save = () => {
|
|
172
211
|
const settings = {
|
|
173
|
-
title
|
|
212
|
+
// The server trims a title; a value's Name is what its chips show, so it
|
|
213
|
+
// goes as the server keeps it.
|
|
214
|
+
title: this.isValue() ? this.title.trim() : this.title,
|
|
174
215
|
padding: {
|
|
175
216
|
top: this._padding(this.paddingTop),
|
|
176
217
|
right: this._padding(this.paddingRight),
|
|
@@ -186,7 +227,7 @@ export class ComponentSettingsComponent {
|
|
|
186
227
|
&& !sameKpiCardSettings(kpi, kpiCardSettings(this.component.config));
|
|
187
228
|
return this._reportData.updateComponent(this.report.id, this.component.id, {
|
|
188
229
|
title: settings.title,
|
|
189
|
-
padding: settings.padding,
|
|
230
|
+
...(this.isValue() ? {} : { padding: settings.padding }),
|
|
190
231
|
...(kpiChanged ? kpi : {}),
|
|
191
232
|
})
|
|
192
233
|
.pipe(tap((response) => {
|
|
@@ -198,7 +239,7 @@ export class ComponentSettingsComponent {
|
|
|
198
239
|
this._message.warning('Component saved, but the server did not save the card settings');
|
|
199
240
|
}
|
|
200
241
|
else {
|
|
201
|
-
this._message.success('Component saved');
|
|
242
|
+
this._message.success(this.isValue() ? 'Value saved' : 'Component saved');
|
|
202
243
|
}
|
|
203
244
|
this._dialogRef.close({ settings: saved ? { ...settings, kpi: saved } : settings });
|
|
204
245
|
}));
|
|
@@ -207,8 +248,15 @@ export class ComponentSettingsComponent {
|
|
|
207
248
|
// row's boolean first — so the toggle stays put with no blink — then persist
|
|
208
249
|
// and reconcile on reload. Neither on → no filter (removed); either on → the
|
|
209
250
|
// filter exists at the combined level. The interface type is inferred
|
|
210
|
-
// server-side.
|
|
251
|
+
// server-side. A value has the report bar toggle only, with its own rules
|
|
252
|
+
// (_setValueExposure).
|
|
211
253
|
setExposure(row, target, on) {
|
|
254
|
+
if (this.isValue()) {
|
|
255
|
+
if (target === 'report') {
|
|
256
|
+
this._setValueExposure(row, on);
|
|
257
|
+
}
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
212
260
|
row[target] = on;
|
|
213
261
|
const existing = this._filters.find((filter) => filter.filterColumn === row.column);
|
|
214
262
|
if (!row.report && !row.component) {
|
|
@@ -231,6 +279,66 @@ export class ComponentSettingsComponent {
|
|
|
231
279
|
}));
|
|
232
280
|
}
|
|
233
281
|
}
|
|
282
|
+
// A value's report bar toggle, the only one it has. Its filter's group is
|
|
283
|
+
// report-wide and may be shared (the report's Period, say), and a value has
|
|
284
|
+
// no strip of its own, so this never lowers a group's level: off unlinks
|
|
285
|
+
// this value alone and the group keeps its other members, and on raises a
|
|
286
|
+
// strip-only group to both, keeping its strips, or adds the value to a new
|
|
287
|
+
// report-level group.
|
|
288
|
+
_setValueExposure(row, on) {
|
|
289
|
+
row.report = on;
|
|
290
|
+
const existing = this._filters.find((filter) => filter.filterColumn === row.column);
|
|
291
|
+
if (!on) {
|
|
292
|
+
if (existing) {
|
|
293
|
+
this._run(this._reportData.deleteFilter(this.report.id, existing.id));
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (!existing) {
|
|
298
|
+
this._run(this._reportData.addFilter(this.report.id, this.component.id, {
|
|
299
|
+
filterColumn: row.column,
|
|
300
|
+
label: row.label,
|
|
301
|
+
level: 'report',
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
else if (this._groupsById.get(existing.filterGroupId)?.level === 'component') {
|
|
305
|
+
this._run(this._reportData.updateFilterGroup(this.report.id, existing.filterGroupId, { level: 'both' }));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// What a formula works out, naming each operand as its chips do. An op this
|
|
309
|
+
// viewer does not know reads nothing.
|
|
310
|
+
_formulaLine() {
|
|
311
|
+
const formula = this.component.config?.formula;
|
|
312
|
+
const line = formula ? FORMULA_LINES[formula.op] : undefined;
|
|
313
|
+
const values = this._layerValues();
|
|
314
|
+
return line ? line(operandKeys(this.component).map((key) => this._valueName(values, key))) : '';
|
|
315
|
+
}
|
|
316
|
+
// The sentence a query value's delete confirm ends with when formulas on its
|
|
317
|
+
// layer read it: the server deletes those with it. Empty when none does, and
|
|
318
|
+
// for a formula, whose operands stay.
|
|
319
|
+
_dependentsNote() {
|
|
320
|
+
if (this.isFormula()) {
|
|
321
|
+
return '';
|
|
322
|
+
}
|
|
323
|
+
const key = valueKey(this.component);
|
|
324
|
+
const names = this._layerValues()
|
|
325
|
+
.filter((value) => operandKeys(value).includes(key))
|
|
326
|
+
.map((value) => escapeHtml(value.title || valueKey(value)));
|
|
327
|
+
return names.length ? ` The values worked out from it are deleted too: ${names.join(', ')}.` : '';
|
|
328
|
+
}
|
|
329
|
+
// The values of the layer this value belongs to: the page whose values hold
|
|
330
|
+
// it, else the master's (a header or footer value).
|
|
331
|
+
_layerValues() {
|
|
332
|
+
const page = (this.report.pages ?? [])
|
|
333
|
+
.find((candidate) => (candidate.values ?? []).some((value) => value.id === this.component.id));
|
|
334
|
+
return (page ?? this.report.master)?.values ?? [];
|
|
335
|
+
}
|
|
336
|
+
// What a value is called where its chips show it: its name, else its key.
|
|
337
|
+
// The newest value holds a key, as it does in the text's tokens.
|
|
338
|
+
_valueName(values, key) {
|
|
339
|
+
const value = values.filter((candidate) => valueKey(candidate) === key).pop();
|
|
340
|
+
return value?.title || key;
|
|
341
|
+
}
|
|
234
342
|
// A derived KPI's card keys, from its config. A sql-mode KPI cannot carry
|
|
235
343
|
// them, so it gets no card fields.
|
|
236
344
|
_seedKpiCard() {
|
|
@@ -297,7 +405,9 @@ export class ComponentSettingsComponent {
|
|
|
297
405
|
});
|
|
298
406
|
}
|
|
299
407
|
// Build the row view-model from the loaded columns + filters/groups. Each
|
|
300
|
-
// row's toggles reflect where its filter group is currently exposed.
|
|
408
|
+
// row's toggles reflect where its filter group is currently exposed. A
|
|
409
|
+
// value's rows never read as on a component: it has no strip, whatever
|
|
410
|
+
// level a group it shares is at.
|
|
301
411
|
_rebuildRows() {
|
|
302
412
|
this.rows.set(this._filterableColumns.map((column) => {
|
|
303
413
|
const filter = this._filters.find((candidate) => candidate.filterColumn === column.column);
|
|
@@ -309,7 +419,7 @@ export class ComponentSettingsComponent {
|
|
|
309
419
|
|| this._groupsById.get(filter?.filterGroupId ?? -1)?.label
|
|
310
420
|
|| this._humanize(column.column),
|
|
311
421
|
report: level === 'report' || level === 'both',
|
|
312
|
-
component: level === 'component' || level === 'both',
|
|
422
|
+
component: !this.isValue() && (level === 'component' || level === 'both'),
|
|
313
423
|
};
|
|
314
424
|
}));
|
|
315
425
|
}
|
|
@@ -328,10 +438,11 @@ export class ComponentSettingsComponent {
|
|
|
328
438
|
// Re-seed from the server so the optimistic toggle snaps back to truth.
|
|
329
439
|
this._afterMutation();
|
|
330
440
|
}
|
|
441
|
+
// The component's filters and the groups they sit in, from the report as
|
|
442
|
+
// last loaded. A value is listed in its page's values, not its components.
|
|
331
443
|
_seedFilters(report, componentId) {
|
|
332
444
|
this._groupsById = new Map((report.filterGroups ?? []).map((group) => [group.id, group]));
|
|
333
|
-
const component = report
|
|
334
|
-
.flatMap((page) => page.components)
|
|
445
|
+
const component = reportComponents(report)
|
|
335
446
|
.find((candidate) => candidate.id === componentId);
|
|
336
447
|
this._filters = component?.filters ?? [];
|
|
337
448
|
this._rebuildRows();
|
|
@@ -381,7 +492,7 @@ export class ComponentSettingsComponent {
|
|
|
381
492
|
.replace(/\b\w/g, (character) => character.toUpperCase());
|
|
382
493
|
}
|
|
383
494
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
384
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || 'Component' }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Title\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\">\n </mat-form-field>\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Toggle where its control shows: in\n the report bar, on this component, both, or neither. The\n interface (date range vs value picker) follows the data. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-toggle\">\n Report bar\n </th>\n <th class=\"filter-col-toggle\">\n This component\n </th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n {{ typeLabel(row.type) }}\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.report\"\n (ngModelChange)=\"setExposure(row, 'report', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show in the report bar\">\n </mat-slide-toggle>\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setExposure(row, 'component', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show on this component\">\n </mat-slide-toggle>\n </td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\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}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:120px}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:130px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { 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.FsFormIntegerDirective, selector: "[fsFormInteger]", inputs: ["fsFormInteger", "fsFormIntegerMessage"] }, { 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: FsMaskModule }, { kind: "directive", type: i3.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsLabelModule }, { kind: "component", type: i5.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i6.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i6.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i7.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: "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: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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: 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: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: 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: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
495
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || (isValue() ? 'Value' : 'Component') }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n {{ isValue() ? 'Name' : 'Title' }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\"\n [fsFormRequired]=\"isValue()\">\n </mat-form-field>\n <!-- A formula value is read-only beyond its name: what it works\n out is the AI's to change. A formula this viewer cannot\n read has no line, and no row. -->\n @if (formulaLine()) {\n <fs-label-field>\n <fs-label>\n Formula\n </fs-label>\n {{ formulaLine() }}\n <fs-label-message>\n Worked out on the server; it follows the filters of the values it reads.\n </fs-label-message>\n </fs-label-field>\n }\n <!-- A value sits inside a text block's words: no box, no padding. -->\n @if (!isValue()) {\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n }\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <!-- A formula runs no statement and follows the filters of the values\n it reads, so it has neither a Filters nor an SQL tab. -->\n @if (!isFormula()) {\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Toggle where its control shows: in\n the report bar, on this component, both, or neither. The\n interface (date range vs value picker) follows the data.\n A value sits inside text and has no component to show a\n control on, so it gets the report bar column only. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-toggle\">\n Report bar\n </th>\n @if (!isValue()) {\n <th class=\"filter-col-toggle\">\n This component\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n {{ typeLabel(row.type) }}\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.report\"\n (ngModelChange)=\"setExposure(row, 'report', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show in the report bar\">\n </mat-slide-toggle>\n </td>\n @if (!isValue()) {\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setExposure(row, 'component', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show on this component\">\n </mat-slide-toggle>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n }\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\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}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:120px}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:130px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { 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.FsFormIntegerDirective, selector: "[fsFormInteger]", inputs: ["fsFormInteger", "fsFormIntegerMessage"] }, { 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: FsMaskModule }, { kind: "directive", type: i3.FsMaskNumberDirective, selector: "[fsMaskNumber]" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsLabelModule }, { kind: "component", type: i5.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i5.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "component", type: i5.FsLabelMessageComponent, selector: "fs-label-message" }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i6.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i6.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i7.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: "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: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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: 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: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: 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: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
385
496
|
}
|
|
386
497
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentSettingsComponent, decorators: [{
|
|
387
498
|
type: Component,
|
|
@@ -407,6 +518,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
407
518
|
MatSelect,
|
|
408
519
|
MatSlideToggle,
|
|
409
520
|
MatTooltip,
|
|
410
|
-
], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || 'Component' }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Title\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\">\n </mat-form-field>\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Toggle where its control shows: in\n the report bar, on this component, both, or neither. The\n interface (date range vs value picker) follows the data. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-toggle\">\n Report bar\n </th>\n <th class=\"filter-col-toggle\">\n This component\n </th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n {{ typeLabel(row.type) }}\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.report\"\n (ngModelChange)=\"setExposure(row, 'report', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show in the report bar\">\n </mat-slide-toggle>\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setExposure(row, 'component', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show on this component\">\n </mat-slide-toggle>\n </td>\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\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}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:120px}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:130px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\n"] }]
|
|
521
|
+
], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n {{ component.title || (isValue() ? 'Value' : 'Component') }}\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n {{ isValue() ? 'Name' : 'Title' }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"title\"\n name=\"title\"\n [fsFormRequired]=\"isValue()\">\n </mat-form-field>\n <!-- A formula value is read-only beyond its name: what it works\n out is the AI's to change. A formula this viewer cannot\n read has no line, and no row. -->\n @if (formulaLine()) {\n <fs-label-field>\n <fs-label>\n Formula\n </fs-label>\n {{ formulaLine() }}\n <fs-label-message>\n Worked out on the server; it follows the filters of the values it reads.\n </fs-label-message>\n </fs-label-field>\n }\n <!-- A value sits inside a text block's words: no box, no padding. -->\n @if (!isValue()) {\n <div class=\"subheading-2\">\n Padding\n </div>\n <div class=\"geometry-row\">\n <mat-form-field>\n <mat-label>\n Top\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingTop\"\n name=\"paddingTop\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Right\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingRight\"\n name=\"paddingRight\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Bottom\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingBottom\"\n name=\"paddingBottom\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Left\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"3\"\n [(ngModel)]=\"paddingLeft\"\n name=\"paddingLeft\"\n [fsFormMin]=\"0\">\n <div matTextSuffix>\n in\n </div>\n </mat-form-field>\n </div>\n }\n <!-- A derived KPI's card: what a rise means, a target and a\n sparkline. The server computes the progress and the points. -->\n @if (kpiCard()) {\n <div class=\"subheading-2\">\n Card\n </div>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Increase is\n </mat-label>\n <mat-select\n [ngModel]=\"increaseIs()\"\n (ngModelChange)=\"increaseIs.set($event)\"\n name=\"increaseIs\">\n @for (option of kpiPolarityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n Colors the change and decides when the target is met.\n </mat-hint>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"6\"\n [signed]=\"true\"\n [ngModel]=\"targetValue()\"\n (ngModelChange)=\"targetValue.set($event)\"\n name=\"targetValue\"\n [validate]=\"validateTarget\">\n @if (targetPercent()) {\n <div matTextSuffix>\n %\n </div>\n }\n <mat-hint>\n The value to reach. Leave empty for no target.\n </mat-hint>\n </mat-form-field>\n @if (hasTarget()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Target label\n </mat-label>\n <input\n matInput\n [ngModel]=\"targetLabel()\"\n (ngModelChange)=\"targetLabel.set($event)\"\n name=\"targetLabel\">\n <mat-hint>\n Shown before the target, such as Goal. Empty reads Target.\n </mat-hint>\n </mat-form-field>\n }\n <fs-label-field>\n <mat-slide-toggle\n [ngModel]=\"sparkline()\"\n (ngModelChange)=\"sparkline.set($event)\"\n name=\"sparkline\">\n Sparkline\n </mat-slide-toggle>\n <mat-hint>\n A small trend line of the value over its last periods.\n </mat-hint>\n </fs-label-field>\n @if (sparkline()) {\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline period\n </mat-label>\n <mat-select\n [ngModel]=\"sparklineGranularity()\"\n (ngModelChange)=\"sparklineGranularity.set($event)\"\n name=\"sparklineGranularity\">\n @for (option of granularityOptions; track option.value) {\n <mat-option [value]=\"option.value\">\n {{ option.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>\n Sparkline periods\n </mat-label>\n <input\n matInput\n fsMaskNumber\n [scale]=\"0\"\n [ngModel]=\"sparklinePeriods()\"\n (ngModelChange)=\"sparklinePeriods.set($event)\"\n name=\"sparklinePeriods\"\n [fsFormRequired]=\"true\"\n [fsFormInteger]=\"true\"\n [fsFormMin]=\"sparklineMinPeriods\"\n [fsFormMax]=\"sparklineMaxPeriods\">\n <mat-hint>\n How many periods the line covers, {{ sparklineMinPeriods }} to {{ sparklineMaxPeriods }}.\n </mat-hint>\n </mat-form-field>\n }\n }\n </div>\n </mat-tab>\n <!-- A formula runs no statement and follows the filters of the values\n it reads, so it has neither a Filters nor an SQL tab. -->\n @if (!isFormula()) {\n <mat-tab\n label=\"Filters\"\n name=\"filters\">\n <div class=\"tab-body\">\n @if (columnsError()) {\n <div class=\"filters-empty error\">\n {{ columnsError() }}\n </div>\n } @else if (rows().length) {\n <!-- Every filterable column. Toggle where its control shows: in\n the report bar, on this component, both, or neither. The\n interface (date range vs value picker) follows the data.\n A value sits inside text and has no component to show a\n control on, so it gets the report bar column only. -->\n <table class=\"filter-table\">\n <thead>\n <tr>\n <th class=\"filter-col-name\">\n Filter\n </th>\n <th class=\"filter-col-type\">\n Type\n </th>\n <th class=\"filter-col-toggle\">\n Report bar\n </th>\n @if (!isValue()) {\n <th class=\"filter-col-toggle\">\n This component\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.column) {\n <tr>\n <td class=\"filter-col-name\">\n {{ row.label }}\n </td>\n <td class=\"filter-col-type\">\n {{ typeLabel(row.type) }}\n </td>\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.report\"\n (ngModelChange)=\"setExposure(row, 'report', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show in the report bar\">\n </mat-slide-toggle>\n </td>\n @if (!isValue()) {\n <td class=\"filter-col-toggle\">\n <mat-slide-toggle\n [ngModel]=\"row.component\"\n (ngModelChange)=\"setExposure(row, 'component', $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n matTooltip=\"Show on this component\">\n </mat-slide-toggle>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n <div class=\"filters-empty\">\n This component has no filterable columns yet \u2014 give it some SQL first.\n </div>\n }\n </div>\n </mat-tab>\n <mat-tab\n label=\"SQL\"\n name=\"sql\">\n <div class=\"tab-body\">\n @if (sqlError()) {\n <div class=\"filters-empty error\">\n {{ sqlError() }}\n </div>\n } @else if (sql()) {\n @if (sqlBaseline()) {\n <!-- A derived component's statement is compiled from its\n document with no viewer state, so it is not byte-for-byte\n what produced the numbers on screen. Said here rather than\n left for the reader to discover. -->\n <div class=\"filters-empty\">\n Compiled from this component's query \u2014 no filters applied, times in {{ sqlTimezone() }}.\n </div>\n }\n <pre class=\"code-block\">{{ sql() }}</pre>\n } @else {\n <div class=\"filters-empty\">\n This component has no SQL yet.\n </div>\n }\n </div>\n </mat-tab>\n }\n <mat-tab\n label=\"Config\"\n name=\"config\">\n <div class=\"tab-body\">\n <pre class=\"code-block\">\n {{ configJson }}\n </pre>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <!-- Save | Delete | Cancel, the standard order. fs-form-dialog-actions\n renders its own Save/Done BEFORE the projected content, which would\n put Delete after Cancel, so `[save]=\"false\"` foots the row here and\n all three buttons are projected in order. Save submits the Settings\n tab; the other tabs persist as you touch them, so they get Done. -->\n <fs-form-dialog-actions [save]=\"false\">\n @if (selectedTab === 'settings') {\n <button\n mat-button\n type=\"submit\"\n color=\"primary\">\n Save\n </button>\n } @else {\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"null\">\n Done\n </button>\n }\n <button\n mat-button\n type=\"button\"\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n <button\n mat-button\n type=\"button\"\n class=\"cancel-button\"\n [mat-dialog-close]=\"null\">\n Cancel\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}.geometry-row{display:flex;gap:8px}.geometry-row mat-form-field{flex:1}.filter-table{border-spacing:0;width:100%;border-collapse:collapse}.filter-table thead th{color:#8f8f8f;font-weight:400;font-size:85%;text-align:left;padding:8px 16px}.filter-table tbody tr{clip-path:xywh(0 3px 100% calc(100% - 6px) round 10px)}.filter-table tbody td{border:none;background-color:#fafafa;padding:8px 16px;vertical-align:middle;text-align:left}.filter-table .filter-col-name{font-weight:600;color:#1f2933}.filter-table .filter-col-type{color:#7b8794;width:120px}.filter-table .filter-col-toggle,.filter-table th.filter-col-toggle{width:130px;text-align:center}.filters-empty{font-size:13px;color:#7b8794;padding:8px 0 4px}.filters-empty.error{color:#e15759}.code-block{margin:0;padding:10px 12px;background:#1f2933;color:#e4e7eb;border-radius:6px;font-family:JetBrains Mono,Consolas,monospace;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow:auto}\n"] }]
|
|
411
522
|
}] });
|
|
412
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL2NvbXBvbmVudC1zZXR0aW5ncy9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvY29tcG9uZW50LXNldHRpbmdzL2NvbXBvbmVudC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQVUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQy9GLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBbUIsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdJLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUs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QUFVOzs0RkFHRCwwQkFBMEI7a0JBN0J0QyxTQUFTO3NDQUdTLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQO3dCQUNQLFdBQVc7d0JBQ1gsWUFBWTt3QkFDWixZQUFZO3dCQUNaLGNBQWM7d0JBQ2QsYUFBYTt3QkFDYixZQUFZO3dCQUNaLGFBQWE7d0JBQ2IsY0FBYzt3QkFDZCxnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIsY0FBYzt3QkFDZCxZQUFZO3dCQUNaLE9BQU87d0JBQ1AsUUFBUTt3QkFDUixTQUFTO3dCQUNULFNBQVM7d0JBQ1QsUUFBUTt3QkFDUixTQUFTO3dCQUNULFNBQVM7d0JBQ1QsY0FBYzt3QkFDZCxVQUFVO3FCQUNYIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgRXZlbnRFbWl0dGVyLCBPbkluaXQsIGNvbXB1dGVkLCBpbmplY3QsIHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZ0FjdGlvbnMsIE1hdERpYWxvZ0Nsb3NlLCBNYXREaWFsb2dDb250ZW50LCBNYXREaWFsb2dSZWYsIE1hdERpYWxvZ1RpdGxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IE1hdEZvcm1GaWVsZCwgTWF0SGludCwgTWF0TGFiZWwsIE1hdFN1ZmZpeCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgTWF0QnV0dG9uIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJztcbmltcG9ydCB7IE1hdElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xuaW1wb3J0IHsgTWF0T3B0aW9uLCBNYXRTZWxlY3QgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zZWxlY3QnO1xuaW1wb3J0IHsgTWF0U2xpZGVUb2dnbGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zbGlkZS10b2dnbGUnO1xuaW1wb3J0IHsgTWF0VGFic01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYnMnO1xuaW1wb3J0IHsgTWF0VG9vbHRpcCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnO1xuXG5pbXBvcnQgeyBGc0RpYWxvZ01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2RpYWxvZyc7XG5pbXBvcnQgeyBGc0Zvcm1Nb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9mb3JtJztcbmltcG9ydCB7IEZzTGFiZWxNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9sYWJlbCc7XG5pbXBvcnQgeyBGc01hc2tNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9tYXNrJztcbmltcG9ydCB7IEZzTWVzc2FnZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9tcHQgfSBmcm9tICdAZmlyZXN0aXRjaC9wcm9tcHQnO1xuaW1wb3J0IHsgRnNUYWJzTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvdGFicyc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBSZXBvcnRDaGFuZ2VQb2xhcml0eSB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC1jaGFuZ2UtcG9sYXJpdHkuZW51bSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm1hdCB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtYXQuZW51bSc7XG5pbXBvcnQgeyByZXNvbHZlRm9ybWF0Q29udGV4dCB9IGZyb20gJy4uLy4uL2Zvcm1hdCc7XG5pbXBvcnQge1xuICBLUElfU1BBUktMSU5FX0RFRkFVTFRfR1JBTlVMQVJJVFksXG4gIEtQSV9TUEFSS0xJTkVfREVGQVVMVF9QRVJJT0RTLFxuICBrcGlDYXJkU2V0dGluZ3MsXG4gIHNhbWVLcGlDYXJkU2V0dGluZ3MsXG59IGZyb20gJy4uLy4uL2twaS1jYXJkJztcbmltcG9ydCB7XG4gIENoYXJ0R3JhbnVsYXJpdHksXG4gIENvbXBvbmVudFNldHRpbmdzLFxuICBHUkFOVUxBUklUWV9PUFRJT05TLFxuICBLcGlDYXJkU2V0dGluZ3MsXG4gIEtwaUNvbmZpZyxcbiAgUmVwb3J0LFxuICBSZXBvcnRDb21wb25lbnQsXG4gIFJlcG9ydENvbXBvbmVudFNxbCxcbiAgUmVwb3J0RmlsdGVyLFxuICBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgUmVwb3J0RmlsdGVyTGV2ZWwsXG4gIFJlcG9ydEZpbHRlclR5cGUsXG4gIFJlcG9ydEZpbHRlcmFibGVDb2x1bW4sXG59IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HIH0gZnJvbSAnLi4vLi4vbGF5b3V0JztcblxuXG4vLyBXaGF0IHRoZSBkaWFsb2cgaGFuZHMgYmFjay4gVGhlIFNldHRpbmdzIHRhYidzIFNhdmUgY2FycmllcyB0aGUgbmV3XG4vLyBgc2V0dGluZ3NgOyBEZWxldGUgY2FycmllcyBgZGVsZXRlZGAgYW5kIG5vIHNldHRpbmdzLCBiZWNhdXNlIHRoZSBjb21wb25lbnRcbi8vIGl0IHdhcyBvcGVuZWQgZm9yIG5vIGxvbmdlciBleGlzdHMuIEV2ZXJ5IG90aGVyIGV4aXQgKENhbmNlbCwgRG9uZSwgRXNjYXBlLFxuLy8gYmFja2Ryb3ApIGNsb3NlcyB3aXRoIG5vIHJlc3VsdCDigJQgZmlsdGVyIHdvcmsgaXMgYW5ub3VuY2VkIGFzIGl0IGhhcHBlbnNcbi8vIGluc3RlYWQsIHRocm91Z2ggYGZpbHRlcnNDaGFuZ2VkYC5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcG9uZW50U2V0dGluZ3NSZXN1bHQge1xuICBzZXR0aW5ncz86IENvbXBvbmVudFNldHRpbmdzO1xuICBkZWxldGVkPzogYm9vbGVhbjtcbn1cblxuLy8gV2hhdCB0aGUgc2V0dGluZ3MgZW5kcG9pbnQgcmV0dXJucyBmb3IgdGhlIGNvbXBvbmVudDogaXRzIGlkIGFuZCwgZnJvbSBhXG4vLyBzZXJ2ZXIgdGhhdCBzYXZlcyBhIEtQSSdzIGNhcmQga2V5cywgdGhlIHdob2xlIGNvbmZpZyBhcyBzYXZlZC5cbmludGVyZmFjZSBDb21wb25lbnRTZXR0aW5nc1Jlc3BvbnNlIHtcbiAgaWQ6IG51bWJlcjtcbiAgY29uZmlnPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsO1xufVxuXG5cbi8vIFdoYXQgYSByaXNlIGluIGEgS1BJJ3MgdmFsdWUgbWVhbnMsIGZvciB0aGUgSW5jcmVhc2UgaXMgc2VsZWN0LlxuY29uc3QgS1BJX0NIQU5HRV9QT0xBUklUWV9PUFRJT05TOiB7IHZhbHVlOiBSZXBvcnRDaGFuZ2VQb2xhcml0eTsgbmFtZTogc3RyaW5nIH1bXSA9IFtcbiAgeyB2YWx1ZTogUmVwb3J0Q2hhbmdlUG9sYXJpdHkuR29vZCwgbmFtZTogJ0dvb2QgbmV3cyDigJQgYSByaXNlIHNob3dzIGdyZWVuJyB9LFxuICB7IHZhbHVlOiBSZXBvcnRDaGFuZ2VQb2xhcml0eS5CYWQsIG5hbWU6ICdCYWQgbmV3cyDigJQgYSByaXNlIHNob3dzIHJlZCcgfSxcbiAgeyB2YWx1ZTogUmVwb3J0Q2hhbmdlUG9sYXJpdHkuTmV1dHJhbCwgbmFtZTogJ05laXRoZXIg4oCUIG5vIGNvbG9yJyB9LFxuXTtcblxuLy8gQSBLUEkgc3BhcmtsaW5lJ3MgcGVyaW9kcyBzdGF5IHdpdGhpbiAyIHRvIDYwLlxuY29uc3QgS1BJX1NQQVJLTElORV9NSU5fUEVSSU9EUyA9IDI7XG5jb25zdCBLUElfU1BBUktMSU5FX01BWF9QRVJJT0RTID0gNjA7XG5cbi8vIEEgcGVyY2VudCBLUEkncyB0YXJnZXQgaXMgZW50ZXJlZCBhcyB0aGUgcGVyY2VudCBzaG93biAoMTUgZm9yIDE1JSkgYW5kXG4vLyBzdG9yZWQgYXMgdGhlIDAtMSByYXRpbyBpdHMgdmFsdWUgYXJyaXZlcyBpbjsgdGhlIHNlcnZlciByZWZ1c2VzIGEgc3RvcmVkXG4vLyB0YXJnZXQgYWJvdmUgMTAwLCB3aGljaCBpcyAxMCwwMDAlIGhlcmUuXG5jb25zdCBLUElfUEVSQ0VOVF9UQVJHRVRfTUFYID0gMTAwMDA7XG5cblxuLy8gT25lIHJvdyBvZiB0aGUgRmlsdGVycyB0YWIgbGlzdGluZzogYSBmaWx0ZXJhYmxlIGNvbHVtbiwgdGhlIGludGVyZmFjZVxuLy8gaW5mZXJyZWQgZnJvbSBpdHMgZGF0YSwgYW5kIHdoZXJlIGl0cyBmaWx0ZXIgaXMgZXhwb3NlZCAodGhlIHR3byB0b2dnbGVzKS5cbmludGVyZmFjZSBGaWx0ZXJSb3cge1xuICBjb2x1bW46IHN0cmluZztcbiAgdHlwZTogUmVwb3J0RmlsdGVyVHlwZTtcbiAgbGFiZWw6IHN0cmluZztcbiAgcmVwb3J0OiBib29sZWFuO1xuICBjb21wb25lbnQ6IGJvb2xlYW47XG59XG5cblxuLy8gQ29tcG9uZW50IHNldHRpbmdzLCBpbiB0YWJzOlxuLy8gICBTZXR0aW5ncyDigJQgdGl0bGUgYW5kIGNvbnRlbnQgcGFkZGluZywgYW5kIG9uIGEgZGVyaXZlZCBLUEkgaXRzIGNhcmQ6XG4vLyAgIHdoYXQgYSByaXNlIG1lYW5zLCBhIHRhcmdldCBhbmQgYSBzcGFya2xpbmUgKG51bWJlciBmb3JtYXRzIHN0YXkgd2l0aFxuLy8gICB0aGUgQUkpLiBQb3NpdGlvbi9zaXplIGFyZSB0dW5lZCBieSBkcmFnZ2luZyBvbiB0aGUgY2FudmFzOyBoZWlnaHRcbi8vICAgYmVoYXZpb3VyIGZvbGxvd3MgZnJvbSB0aGUgY29tcG9uZW50IHR5cGUuXG4vLyAgIEZpbHRlcnMgIOKAlCBPTkUgbGlzdGluZyBvZiBldmVyeSBmaWx0ZXJhYmxlIGNvbHVtbiBvbiB0aGlzIGNvbXBvbmVudC4gRWFjaFxuLy8gICByb3cgY2FycmllcyB0d28gdG9nZ2xlczogc2hvdyBpbiB0aGUgcmVwb3J0IGJhciBhbmQvb3Igc2hvdyBvbiB0aGlzXG4vLyAgIGNvbXBvbmVudCAoYm90aCwgZWl0aGVyLCBvciBuZWl0aGVyKS4gVGhlIGludGVyZmFjZSAoZGF0ZSByYW5nZSB2cyB2YWx1ZVxuLy8gICBwaWNrZXIpIGlzIGluZmVycmVkIGZyb20gdGhlIGRhdGEsIG5ldmVyIGNob3Nlbi4gRWFjaCB0b2dnbGUgcGVyc2lzdHNcbi8vICAgaW1tZWRpYXRlbHkgYW5kIHJlZnJlc2hlcyB0aGUgaW4tZGlhbG9nIGxpc3QuXG4vLyAgIFNRTCAvIENvbmZpZyDigJQgcmVhZC1vbmx5IGRpYWdub3N0aWNzLlxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0Zvcm1Nb2R1bGUsXG4gICAgRnNNYXNrTW9kdWxlLFxuICAgIEZzRGlhbG9nTW9kdWxlLFxuICAgIEZzTGFiZWxNb2R1bGUsXG4gICAgRnNUYWJzTW9kdWxlLFxuICAgIE1hdFRhYnNNb2R1bGUsXG4gICAgTWF0RGlhbG9nVGl0bGUsXG4gICAgTWF0RGlhbG9nQ29udGVudCxcbiAgICBNYXREaWFsb2dBY3Rpb25zLFxuICAgIE1hdERpYWxvZ0Nsb3NlLFxuICAgIE1hdEZvcm1GaWVsZCxcbiAgICBNYXRIaW50LFxuICAgIE1hdExhYmVsLFxuICAgIE1hdFN1ZmZpeCxcbiAgICBNYXRCdXR0b24sXG4gICAgTWF0SW5wdXQsXG4gICAgTWF0T3B0aW9uLFxuICAgIE1hdFNlbGVjdCxcbiAgICBNYXRTbGlkZVRvZ2dsZSxcbiAgICBNYXRUb29sdGlwLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb21wb25lbnRTZXR0aW5nc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgLy8gQSBmaWx0ZXIgd2FzIGFkZGVkLCByZW1vdmVkIG9yIHJlLWxldmVsbGVkLCBzbyB0aGUgcmVwb3J0J3MgZmlsdGVyIGdyb3Vwc1xuICAvLyBjaGFuZ2VkLiBUaG9zZSBtdXRhdGlvbnMgcGVyc2lzdCB0aGUgbW9tZW50IHRoZXkgYXJlIGNsaWNrZWQgYW5kIHRoZSBkaWFsb2dcbiAgLy8gY2FuIHRoZW4gYmUgZGlzbWlzc2VkIGJ5IGEgcm91dGUgdGhhdCBjYXJyaWVzIG5vIHJlc3VsdCAoRXNjYXBlLCBiYWNrZHJvcCksXG4gIC8vIHNvIHRoZSBwYWdlIGlzIHRvbGQgaGVyZSByYXRoZXIgdGhhbiB0aHJvdWdoIHRoZSBjbG9zZSByZXN1bHQuXG4gIHB1YmxpYyByZWFkb25seSBmaWx0ZXJzQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBwdWJsaWMgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQ7XG4gIHB1YmxpYyByZXBvcnQ6IFJlcG9ydDtcblxuICBwdWJsaWMgc2VsZWN0ZWRUYWIgPSAnc2V0dGluZ3MnO1xuXG4gIHB1YmxpYyB0aXRsZSA9ICcnO1xuXG4gIC8vIENvbXBvbmVudCBwYWRkaW5nIGluIGluY2hlcy4gYG51bWJlciB8IHN0cmluZ2AgZm9yIHRoZSBzYW1lIHJlYXNvbiBhcyB0aGVcbiAgLy8gcGFnZSBkaW1lbnNpb25zIGluIHJlcG9ydC1zZXR0aW5nczogZnNNYXNrTnVtYmVyIHNlZWRzIGZyb20gdGhlIG51bWJlciBidXRcbiAgLy8gaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgc3RyaW5nLCBhbmQgc2F2ZSBjYXN0cyBpdCBvbmNlIG9uIHRoZSB3YXkgb3V0LlxuICBwdWJsaWMgcGFkZGluZ1RvcDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdSaWdodDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdCb3R0b206IG51bWJlciB8IHN0cmluZyA9IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG4gIHB1YmxpYyBwYWRkaW5nTGVmdDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcblxuICBwdWJsaWMgY29uZmlnSnNvbiA9ICcnO1xuXG4gIC8vIC0tLS0gS1BJIGNhcmQgc3RhdGUgKGEgZGVyaXZlZCBLUEkgb25seSkgLS0tLVxuICBwdWJsaWMgcmVhZG9ubHkga3BpUG9sYXJpdHlPcHRpb25zID0gS1BJX0NIQU5HRV9QT0xBUklUWV9PUFRJT05TO1xuICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnVsYXJpdHlPcHRpb25zID0gR1JBTlVMQVJJVFlfT1BUSU9OUztcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZU1pblBlcmlvZHMgPSBLUElfU1BBUktMSU5FX01JTl9QRVJJT0RTO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lTWF4UGVyaW9kcyA9IEtQSV9TUEFSS0xJTkVfTUFYX1BFUklPRFM7XG4gIHB1YmxpYyByZWFkb25seSBrcGlDYXJkID0gc2lnbmFsKGZhbHNlKTtcbiAgcHVibGljIHJlYWRvbmx5IGluY3JlYXNlSXMgPSBzaWduYWw8UmVwb3J0Q2hhbmdlUG9sYXJpdHk+KFJlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2QpO1xuICAvLyBUaGUgdGFyZ2V0IGFzIHR5cGVkOiBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgc3RyaW5nLiBFbXB0eVxuICAvLyBtZWFucyBubyB0YXJnZXQuIEEgcGVyY2VudCBLUEkncyBpcyBpbiBwZXJjZW50ICh0YXJnZXRQZXJjZW50KS5cbiAgcHVibGljIHJlYWRvbmx5IHRhcmdldFZhbHVlID0gc2lnbmFsPG51bWJlciB8IHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0TGFiZWwgPSBzaWduYWwoJycpO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0UGVyY2VudCA9IHNpZ25hbChmYWxzZSk7XG4gIHB1YmxpYyByZWFkb25seSBoYXNUYXJnZXQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9udW1iZXIodGhpcy50YXJnZXRWYWx1ZSgpKSAhPT0gbnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSBzcGFya2xpbmUgPSBzaWduYWwoZmFsc2UpO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lR3JhbnVsYXJpdHkgPSBzaWduYWw8Q2hhcnRHcmFudWxhcml0eT4oS1BJX1NQQVJLTElORV9ERUZBVUxUX0dSQU5VTEFSSVRZKTtcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZVBlcmlvZHMgPSBzaWduYWw8bnVtYmVyIHwgc3RyaW5nPihLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyk7XG5cbiAgLy8gLS0tLSBTUUwgdGFiIHN0YXRlIC0tLS1cbiAgLy8gVGhlIHN0YXRlbWVudCwgb25jZSBmZXRjaGVkLiBOdWxsIHdoaWxlIGl0IGlzIGluIGZsaWdodCwgYW5kIG51bGwgd2hlbiB0aGVcbiAgLy8gY29tcG9uZW50J3MgZG9jdW1lbnQgY291bGQgbm90IGJlIGNvbXBpbGVkIChzcWxFcnJvciB0aGVuIHNheXMgd2h5KS5cbiAgcHVibGljIHJlYWRvbmx5IHNxbCA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgLy8gVHJ1ZSB3aGVuIHRoZSBzdGF0ZW1lbnQgaXMgYSBERVJJVkVEIGJhc2VsaW5lOiBubyBmaWx0ZXJzLCB0aGUgYXV0aG9yZWRcbiAgLy8gZ3JhaW4sIHRpbWVzIGluIHRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZS4gVGhlIHRhYiBzYXlzIHNvLCBiZWNhdXNlIHRoZVxuICAvLyBudW1iZXJzIG9uIHNjcmVlbiBjb21lIGZyb20gdGhpcyBzdGF0ZW1lbnQgcGx1cyB0aGUgdmlld2VyJ3Mgb3duIGNob2ljZXNcbiAgLy8gYW5kIHRoZSB0d28gY2FuIGRpZmZlci5cbiAgcHVibGljIHJlYWRvbmx5IHNxbEJhc2VsaW5lID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gVGhlIHpvbmUgdGhlIHN0YXRlbWVudCB3YXMgY29tcGlsZWQgaW46IHRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZSwgc2VudFxuICAvLyB3aXRoIHRoZSBTUUwuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCBpdCBjb21waWxlZCBpbiBVVEMuXG4gIHB1YmxpYyByZWFkb25seSBzcWxUaW1lem9uZSA9IHNpZ25hbCgnVVRDJyk7XG4gIHB1YmxpYyByZWFkb25seSBzcWxFcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyAtLS0tIGZpbHRlciBtYW5hZ2VtZW50IHN0YXRlIC0tLS1cbiAgLy8gT25lIHJvdyBwZXIgZmlsdGVyYWJsZSBjb2x1bW4uIFRoZSB0d28gYm9vbGVhbnMgZHJpdmUgdGhlIHRvZ2dsZXM7IHdlIGZsaXBcbiAgLy8gdGhlbSBvcHRpbWlzdGljYWxseSBvbiBjbGljayAoc28gdGhlIFVJIG5ldmVyIGJsaW5rcyB3aGlsZSB0aGUgcmVxdWVzdCBpc1xuICAvLyBpbiBmbGlnaHQpIGFuZCByZWNvbmNpbGUgZnJvbSB0aGUgc2VydmVyIG9uIHJlbG9hZC5cbiAgcHVibGljIHJlYWRvbmx5IHJvd3MgPSBzaWduYWw8RmlsdGVyUm93W10+KFtdKTtcbiAgcHVibGljIHJlYWRvbmx5IGNvbHVtbnNFcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyBUaGUgcmF3IGlucHV0cyB0aGUgcm93cyBhcmUgYnVpbHQgZnJvbS5cbiAgcHJpdmF0ZSBfZmlsdGVyYWJsZUNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSA9IFtdO1xuICBwcml2YXRlIF9maWx0ZXJzOiBSZXBvcnRGaWx0ZXJbXSA9IFtdO1xuICBwcml2YXRlIF9ncm91cHNCeUlkID0gbmV3IE1hcDxudW1iZXIsIFJlcG9ydEZpbHRlckdyb3VwPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3R5cGVMYWJlbHM6IFJlY29yZDxSZXBvcnRGaWx0ZXJUeXBlLCBzdHJpbmc+ID0ge1xuICAgIHNlbGVjdDogJ1BpY2sgdmFsdWVzJyxcbiAgICBkYXRlUmFuZ2U6ICdEYXRlIHJhbmdlJyxcbiAgICBrZXl3b3JkOiAnU2VhcmNoIHRleHQnLFxuICB9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2RhdGE6IHsgcmVwb3J0OiBSZXBvcnQ7IGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50IH0gPSBpbmplY3QoTUFUX0RJQUxPR19EQVRBKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZGlhbG9nUmVmID0gaW5qZWN0PE1hdERpYWxvZ1JlZjxDb21wb25lbnRTZXR0aW5nc0NvbXBvbmVudCwgQ29tcG9uZW50U2V0dGluZ3NSZXN1bHQ+PihNYXREaWFsb2dSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlID0gaW5qZWN0KEZzTWVzc2FnZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMucmVwb3J0ID0gdGhpcy5fZGF0YS5yZXBvcnQ7XG4gICAgdGhpcy5jb21wb25lbnQgPSB0aGlzLl9kYXRhLmNvbXBvbmVudDtcblxuICAgIHRoaXMudGl0bGUgPSB0aGlzLmNvbXBvbmVudC50aXRsZSA/PyAnJztcblxuICAgIGNvbnN0IHBhZGRpbmcgPSB0aGlzLmNvbXBvbmVudC5jb25maWc/LnBhZGRpbmc7XG4gICAgdGhpcy5wYWRkaW5nVG9wID0gcGFkZGluZz8udG9wID8/IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG4gICAgdGhpcy5wYWRkaW5nUmlnaHQgPSBwYWRkaW5nPy5yaWdodCA/PyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuICAgIHRoaXMucGFkZGluZ0JvdHRvbSA9IHBhZGRpbmc/LmJvdHRvbSA/PyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuICAgIHRoaXMucGFkZGluZ0xlZnQgPSBwYWRkaW5nPy5sZWZ0ID8/IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG5cbiAgICB0aGlzLmNvbmZpZ0pzb24gPSBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbXBvbmVudC5jb25maWcgPz8ge30sIG51bGwsIDIpO1xuXG4gICAgdGhpcy5fc2VlZEtwaUNhcmQoKTtcblxuICAgIHRoaXMuX3NlZWRGaWx0ZXJzKHRoaXMucmVwb3J0LCB0aGlzLmNvbXBvbmVudC5pZCk7XG4gICAgdGhpcy5fbG9hZENvbHVtbnMoKTtcbiAgICB0aGlzLl9sb2FkU3FsKCk7XG4gIH1cblxuICAvLyBIdW1hbi1mcmllbmRseSBuYW1lIGZvciB0aGUgaW5mZXJyZWQgaW50ZXJmYWNlIHNob3duIGJlc2lkZSBlYWNoIGNvbHVtbi5cbiAgcHVibGljIHR5cGVMYWJlbCh0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fdHlwZUxhYmVsc1t0eXBlXSA/PyB0eXBlO1xuICB9XG5cbiAgLy8gQ29uZmlybSBhbmQgZGVsZXRlIGhlcmUsIHdoaWxlIHRoZSBkaWFsb2cgaXMgc3RpbGwgb3BlbiwgdGhlbiBjbG9zZSB3aXRoIGFcbiAgLy8gYGRlbGV0ZWRgIHJlc3VsdCBmb3IgdGhlIHBhZ2UgdG8gYWN0IG9uIOKAlCB0aGUgc2FtZSBzaGFwZSB0aGUgcmVwb3J0XG4gIC8vIHNldHRpbmdzIGRpYWxvZyB1c2VzIGZvciBkZWxldGluZyBhIHJlcG9ydC5cbiAgLy9cbiAgLy8gVGhlIGNvbmZpcm0gc2F5cyBpdCBjYW5ub3QgYmUgdW5kb25lIGJlY2F1c2UsIGZyb20gdGhlIFVJLCBpdCBjYW5ub3Q6IHRoZVxuICAvLyByb3cgaXMgc29mdC1kZWxldGVkIHNlcnZlci1zaWRlIGJ1dCBub3RoaW5nIGhlcmUgcmVzdG9yZXMgYSBjb21wb25lbnQuXG4gIHB1YmxpYyBkZWxldGUoKTogdm9pZCB7XG4gICAgdGhpcy5fcHJvbXB0LmNvbmZpcm0oe1xuICAgICAgdGl0bGU6ICdEZWxldGUgQ29tcG9uZW50JyxcbiAgICAgIHRlbXBsYXRlOiBgQXJlIHlvdSBzdXJlIHlvdSB3b3VsZCBsaWtlIHRvIGRlbGV0ZSBcIiR7dGhpcy5jb21wb25lbnQudGl0bGUgfHwgJ3RoaXMgY29tcG9uZW50J31cIj8gVGhpcyBjYW5ub3QgYmUgdW5kb25lLmAsXG4gICAgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5fcmVwb3J0RGF0YS5kZWxldGVDb21wb25lbnQodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3MoJ0NvbXBvbmVudCBkZWxldGVkJyk7XG4gICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZSh7IGRlbGV0ZWQ6IHRydWUgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIEEgcGVyY2VudCB0YXJnZXQncyBib3VuZCwgaW4gdGhlIHBlcmNlbnQgaXQgaXMgdHlwZWQgaW4uIEl0IHJlYWRzIHRoZVxuICAvLyBjb250cm9sLCB3aGljaCBmc0Zvcm0gdmFsaWRhdGVzIGJlZm9yZSBuZ01vZGVsQ2hhbmdlIHVwZGF0ZXMgdGhlIHNpZ25hbC5cbiAgcHVibGljIHZhbGlkYXRlVGFyZ2V0ID0gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5fbnVtYmVyKGNvbnRyb2wudmFsdWUpO1xuXG4gICAgaWYgKHRoaXMudGFyZ2V0UGVyY2VudCgpICYmIHZhbHVlICE9PSBudWxsICYmIHZhbHVlID4gS1BJX1BFUkNFTlRfVEFSR0VUX01BWCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBIHBlcmNlbnQgdGFyZ2V0IGNhbiBiZSBhdCBtb3N0IDEwLDAwMCUnKTtcbiAgICB9XG4gIH07XG5cbiAgcHVibGljIHNhdmUgPSAoKSA9PiB7XG4gICAgY29uc3Qgc2V0dGluZ3M6IENvbXBvbmVudFNldHRpbmdzID0ge1xuICAgICAgdGl0bGU6IHRoaXMudGl0bGUsXG4gICAgICBwYWRkaW5nOiB7XG4gICAgICAgIHRvcDogdGhpcy5fcGFkZGluZyh0aGlzLnBhZGRpbmdUb3ApLFxuICAgICAgICByaWdodDogdGhpcy5fcGFkZGluZyh0aGlzLnBhZGRpbmdSaWdodCksXG4gICAgICAgIGJvdHRvbTogdGhpcy5fcGFkZGluZyh0aGlzLnBhZGRpbmdCb3R0b20pLFxuICAgICAgICBsZWZ0OiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ0xlZnQpLFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgLy8gVGhlIGNhcmQga2V5cyBnbyBhcyBjb25maWcga2V5cyBiZXNpZGUgdGhlIHBhZGRpbmcgKGluY3JlYXNlSXMsIHRhcmdldFxuICAgIC8vIGFuZCBzcGFya2xpbmUsIG51bGwgdG8gcmVtb3ZlIG9uZSksIGFuZCBvbmx5IHdoZW4gdGhleSBjaGFuZ2VkLCBzbyBhXG4gICAgLy8gdGl0bGUgZWRpdCBuZXZlciB0b3VjaGVzIHRoZW0uXG4gICAgY29uc3Qga3BpID0gdGhpcy5rcGlDYXJkKCkgPyB0aGlzLl9rcGlDYXJkU2V0dGluZ3MoKSA6IG51bGw7XG4gICAgY29uc3Qga3BpQ2hhbmdlZCA9ICEha3BpXG4gICAgICAmJiAhc2FtZUtwaUNhcmRTZXR0aW5ncyhrcGksIGtwaUNhcmRTZXR0aW5ncyh0aGlzLmNvbXBvbmVudC5jb25maWcgYXMgS3BpQ29uZmlnKSk7XG5cbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YS51cGRhdGVDb21wb25lbnQodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkLCB7XG4gICAgICB0aXRsZTogc2V0dGluZ3MudGl0bGUsXG4gICAgICBwYWRkaW5nOiBzZXR0aW5ncy5wYWRkaW5nLFxuICAgICAgLi4uKGtwaUNoYW5nZWQgPyBrcGkgOiB7fSksXG4gICAgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKHJlc3BvbnNlOiBDb21wb25lbnRTZXR0aW5nc1Jlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgLy8gVGhlIGNhcmQgaXMgZHJhd24gZnJvbSB0aGUga2V5cyB0aGUgc2VydmVyIHNhdmVkLCByZWFkIGJhY2sgZnJvbVxuICAgICAgICAgIC8vIHRoZSBjb25maWcgaXQgcmV0dXJucy4gQSBzZXJ2ZXIgdGhhdCByZXR1cm5zIG5vIGNvbmZpZyBkaWQgbm90XG4gICAgICAgICAgLy8gc2F2ZSB0aGVtLCBzbyB0aGUgY2FyZCBrZWVwcyB3aGF0IGl0IGhhZCBhbmQgdGhlIGRpYWxvZyBzYXlzIHNvLlxuICAgICAgICAgIGNvbnN0IHNhdmVkID0ga3BpQ2hhbmdlZCA/IHRoaXMuX3NhdmVkS3BpQ2FyZChyZXNwb25zZSkgOiBudWxsO1xuXG4gICAgICAgICAgaWYgKGtwaUNoYW5nZWQgJiYgIXNhdmVkKSB7XG4gICAgICAgICAgICB0aGlzLl9tZXNzYWdlLndhcm5pbmcoJ0NvbXBvbmVudCBzYXZlZCwgYnV0IHRoZSBzZXJ2ZXIgZGlkIG5vdCBzYXZlIHRoZSBjYXJkIHNldHRpbmdzJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2VzcygnQ29tcG9uZW50IHNhdmVkJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgc2V0dGluZ3M6IHNhdmVkID8geyAuLi5zZXR0aW5ncywga3BpOiBzYXZlZCB9IDogc2V0dGluZ3MgfSk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfTtcblxuICAvLyBGbGlwIG9uZSBleHBvc3VyZSAocmVwb3J0IGJhciBvciB0aGlzIGNvbXBvbmVudCkgZm9yIGEgcm93LiBXZSB1cGRhdGUgdGhlXG4gIC8vIHJvdydzIGJvb2xlYW4gZmlyc3Qg4oCUIHNvIHRoZSB0b2dnbGUgc3RheXMgcHV0IHdpdGggbm8gYmxpbmsg4oCUIHRoZW4gcGVyc2lzdFxuICAvLyBhbmQgcmVjb25jaWxlIG9uIHJlbG9hZC4gTmVpdGhlciBvbiDihpIgbm8gZmlsdGVyIChyZW1vdmVkKTsgZWl0aGVyIG9uIOKGkiB0aGVcbiAgLy8gZmlsdGVyIGV4aXN0cyBhdCB0aGUgY29tYmluZWQgbGV2ZWwuIFRoZSBpbnRlcmZhY2UgdHlwZSBpcyBpbmZlcnJlZFxuICAvLyBzZXJ2ZXItc2lkZS5cbiAgcHVibGljIHNldEV4cG9zdXJlKHJvdzogRmlsdGVyUm93LCB0YXJnZXQ6ICdyZXBvcnQnIHwgJ2NvbXBvbmVudCcsIG9uOiBib29sZWFuKTogdm9pZCB7XG4gICAgcm93W3RhcmdldF0gPSBvbjtcblxuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5fZmlsdGVycy5maW5kKChmaWx0ZXIpID0+IGZpbHRlci5maWx0ZXJDb2x1bW4gPT09IHJvdy5jb2x1bW4pO1xuXG4gICAgaWYgKCFyb3cucmVwb3J0ICYmICFyb3cuY29tcG9uZW50KSB7XG4gICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgdGhpcy5fcnVuKHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlRmlsdGVyKHRoaXMucmVwb3J0LmlkLCBleGlzdGluZy5pZCkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbGV2ZWw6IFJlcG9ydEZpbHRlckxldmVsID0gcm93LnJlcG9ydCAmJiByb3cuY29tcG9uZW50XG4gICAgICA/ICdib3RoJ1xuICAgICAgOiAocm93LnJlcG9ydCA/ICdyZXBvcnQnIDogJ2NvbXBvbmVudCcpO1xuXG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICB0aGlzLl9ydW4odGhpcy5fcmVwb3J0RGF0YS51cGRhdGVGaWx0ZXJHcm91cCh0aGlzLnJlcG9ydC5pZCwgZXhpc3RpbmcuZmlsdGVyR3JvdXBJZCwgeyBsZXZlbCB9KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLmFkZEZpbHRlcih0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQsIHtcbiAgICAgICAgZmlsdGVyQ29sdW1uOiByb3cuY29sdW1uLFxuICAgICAgICBsYWJlbDogcm93LmxhYmVsLFxuICAgICAgICBsZXZlbCxcbiAgICAgIH0pKTtcbiAgICB9XG4gIH1cblxuICAvLyBBIGRlcml2ZWQgS1BJJ3MgY2FyZCBrZXlzLCBmcm9tIGl0cyBjb25maWcuIEEgc3FsLW1vZGUgS1BJIGNhbm5vdCBjYXJyeVxuICAvLyB0aGVtLCBzbyBpdCBnZXRzIG5vIGNhcmQgZmllbGRzLlxuICBwcml2YXRlIF9zZWVkS3BpQ2FyZCgpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSAodGhpcy5jb21wb25lbnQuY29uZmlnID8/IHt9KSBhcyBLcGlDb25maWc7XG5cbiAgICB0aGlzLmtwaUNhcmQuc2V0KHRoaXMuY29tcG9uZW50LnR5cGUgPT09ICdrcGknICYmICF0aGlzLmNvbXBvbmVudC5zcWwpO1xuICAgIHRoaXMuaW5jcmVhc2VJcy5zZXQoY29uZmlnLmluY3JlYXNlSXMgPz8gUmVwb3J0Q2hhbmdlUG9sYXJpdHkuR29vZCk7XG4gICAgdGhpcy50YXJnZXRQZXJjZW50LnNldChjb25maWcubWVhc3VyZT8uZm9ybWF0ID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5QZXJjZW50XG4gICAgICAmJiByZXNvbHZlRm9ybWF0Q29udGV4dCh0aGlzLnJlcG9ydCkucmF0aW9QZXJjZW50KTtcbiAgICB0aGlzLnRhcmdldFZhbHVlLnNldCh0aGlzLl90YXJnZXRTaG93bihjb25maWcudGFyZ2V0Py52YWx1ZSA/PyBudWxsKSk7XG4gICAgdGhpcy50YXJnZXRMYWJlbC5zZXQoY29uZmlnLnRhcmdldD8ubGFiZWwgPz8gJycpO1xuICAgIHRoaXMuc3BhcmtsaW5lLnNldCghIWNvbmZpZy5zcGFya2xpbmUpO1xuICAgIHRoaXMuc3BhcmtsaW5lR3JhbnVsYXJpdHkuc2V0KGNvbmZpZy5zcGFya2xpbmU/LmdyYW51bGFyaXR5ID8/IEtQSV9TUEFSS0xJTkVfREVGQVVMVF9HUkFOVUxBUklUWSk7XG4gICAgdGhpcy5zcGFya2xpbmVQZXJpb2RzLnNldChjb25maWcuc3BhcmtsaW5lPy5wZXJpb2RzID8/IEtQSV9TUEFSS0xJTkVfREVGQVVMVF9QRVJJT0RTKTtcbiAgfVxuXG4gIC8vIFRoZSBjYXJkIGtleXMgdGhlIHNlcnZlciBzYXZlZCwgZnJvbSB0aGUgY29uZmlnIGl0cyByZXNwb25zZSBjYXJyaWVzO1xuICAvLyBudWxsIHdoZW4gaXQgY2FycmllcyBub25lIChhIHNlcnZlciB0aGF0IGRvZXMgbm90IHNhdmUgdGhlbSkuXG4gIHByaXZhdGUgX3NhdmVkS3BpQ2FyZChyZXNwb25zZTogQ29tcG9uZW50U2V0dGluZ3NSZXNwb25zZSB8IG51bGwgfCB1bmRlZmluZWQpOiBLcGlDYXJkU2V0dGluZ3MgfCBudWxsIHtcbiAgICBjb25zdCBjb25maWcgPSByZXNwb25zZT8uY29uZmlnO1xuXG4gICAgcmV0dXJuIGNvbmZpZyAmJiB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGtwaUNhcmRTZXR0aW5ncyhjb25maWcgYXMgS3BpQ29uZmlnKSA6IG51bGw7XG4gIH1cblxuICAvLyBHb29kIGlzIHdoYXQgYW4gYWJzZW50IGluY3JlYXNlSXMgcmVhZHMsIHNvIGl0IGlzIHNhdmVkIGFzIGFic2VudC5cbiAgcHJpdmF0ZSBfa3BpQ2FyZFNldHRpbmdzKCk6IEtwaUNhcmRTZXR0aW5ncyB7XG4gICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5fbnVtYmVyKHRoaXMudGFyZ2V0VmFsdWUoKSk7XG4gICAgY29uc3QgbGFiZWwgPSB0aGlzLnRhcmdldExhYmVsKCkudHJpbSgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGluY3JlYXNlSXM6IHRoaXMuaW5jcmVhc2VJcygpID09PSBSZXBvcnRDaGFuZ2VQb2xhcml0eS5Hb29kID8gbnVsbCA6IHRoaXMuaW5jcmVhc2VJcygpLFxuICAgICAgdGFyZ2V0OiB0YXJnZXQgPT09IG51bGwgPyBudWxsIDogeyB2YWx1ZTogdGhpcy5fdGFyZ2V0U3RvcmVkKHRhcmdldCksIGxhYmVsOiBsYWJlbCB8fCBudWxsIH0sXG4gICAgICBzcGFya2xpbmU6IHRoaXMuc3BhcmtsaW5lKClcbiAgICAgICAgPyB7IGdyYW51bGFyaXR5OiB0aGlzLnNwYXJrbGluZUdyYW51bGFyaXR5KCksIHBlcmlvZHM6IHRoaXMuX251bWJlcih0aGlzLnNwYXJrbGluZVBlcmlvZHMoKSkgfVxuICAgICAgICA6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8vIEEgc3RvcmVkIHJhdGlvIGFzIHRoZSBwZXJjZW50IHR5cGVkLCByb3VuZGVkIHNvIDAuMTUgcmVhZHMgMTUgYW5kIG5vdFxuICAvLyAxNS4wMDAwMDAwMDAwMDAwMDIuXG4gIHByaXZhdGUgX3RhcmdldFNob3duKHZhbHVlOiBudW1iZXIgfCBudWxsKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8ICF0aGlzLnRhcmdldFBlcmNlbnQoKSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbHVlICogMTAwICogMWU2KSAvIDFlNjtcbiAgfVxuXG4gIHByaXZhdGUgX3RhcmdldFN0b3JlZCh2YWx1ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy50YXJnZXRQZXJjZW50KCkgPyB2YWx1ZSAvIDEwMCA6IHZhbHVlO1xuICB9XG5cbiAgLy8gQSB0eXBlZCBudW1iZXIsIG9yIG51bGwgd2hlbiB0aGUgZmllbGQgaXMgZW1wdHkuXG4gIHByaXZhdGUgX251bWJlcih2YWx1ZTogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IG51bWJlciA9IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZSA6IHBhcnNlRmxvYXQodmFsdWUpO1xuXG4gICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShudW1iZXIpID8gbnVtYmVyIDogbnVsbDtcbiAgfVxuXG4gIC8vIFRoZSBwYWRkaW5nIGFzIGEgcmVhbCBudW1iZXIgZm9yIHRoZSB3aXJlLiBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0aGVcbiAgLy8gdW5tYXNrZWQgc3RyaW5nIGl0IGJ1aWx0IHdpdGggYSBmaXhlZCAnLicgcmFkaXgsIHNvIHRoaXMgaXMgYSBzdHJhaWdodFxuICAvLyBwYXJzZSAtIHRoZSB3aG9sZSByZWFzb24gZm9yIHRoZSBtYXNrIGlzIHRoYXQgYSBuYXRpdmUgbnVtYmVyIGlucHV0IHdvdWxkXG4gIC8vIHBhaW50IChhbmQgcmVhZCBiYWNrKSB0aGUgdmlld2VyJ3Mgb3duIGxvY2FsZSBzZXBhcmF0b3IgaW5zdGVhZC5cbiAgcHJpdmF0ZSBfcGFkZGluZyh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyA/IHZhbHVlIDogcGFyc2VGbG9hdCh2YWx1ZSk7XG4gIH1cblxuICAvLyBSdW4gYSBmaWx0ZXIgbXV0YXRpb24sIHRoZW4gcmVsb2FkIHRvIHJlY29uY2lsZSB0aGUgb3B0aW1pc3RpYyBzdGF0ZS5cbiAgcHJpdmF0ZSBfcnVuKHJlcXVlc3Q6IE9ic2VydmFibGU8dW5rbm93bj4pOiB2b2lkIHtcbiAgICByZXF1ZXN0LnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAoKSA9PiB0aGlzLl9hZnRlck11dGF0aW9uKCksXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB0aGlzLl9tdXRhdGlvbkVycm9yKGVycm9yKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIEJ1aWxkIHRoZSByb3cgdmlldy1tb2RlbCBmcm9tIHRoZSBsb2FkZWQgY29sdW1ucyArIGZpbHRlcnMvZ3JvdXBzLiBFYWNoXG4gIC8vIHJvdydzIHRvZ2dsZXMgcmVmbGVjdCB3aGVyZSBpdHMgZmlsdGVyIGdyb3VwIGlzIGN1cnJlbnRseSBleHBvc2VkLlxuICBwcml2YXRlIF9yZWJ1aWxkUm93cygpOiB2b2lkIHtcbiAgICB0aGlzLnJvd3Muc2V0KHRoaXMuX2ZpbHRlcmFibGVDb2x1bW5zLm1hcCgoY29sdW1uKSA9PiB7XG4gICAgICBjb25zdCBmaWx0ZXIgPSB0aGlzLl9maWx0ZXJzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLmZpbHRlckNvbHVtbiA9PT0gY29sdW1uLmNvbHVtbik7XG4gICAgICBjb25zdCBsZXZlbCA9IGZpbHRlciA/IHRoaXMuX2dyb3Vwc0J5SWQuZ2V0KGZpbHRlci5maWx0ZXJHcm91cElkKT8ubGV2ZWwgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbHVtbjogY29sdW1uLmNvbHVtbixcbiAgICAgICAgdHlwZTogY29sdW1uLnR5cGUsXG4gICAgICAgIGxhYmVsOiBmaWx0ZXI/LmxhYmVsXG4gICAgICAgICAgfHwgdGhpcy5fZ3JvdXBzQnlJZC5nZXQoZmlsdGVyPy5maWx0ZXJHcm91cElkID8/IC0xKT8ubGFiZWxcbiAgICAgICAgICB8fCB0aGlzLl9odW1hbml6ZShjb2x1bW4uY29sdW1uKSxcbiAgICAgICAgcmVwb3J0OiBsZXZlbCA9PT0gJ3JlcG9ydCcgfHwgbGV2ZWwgPT09ICdib3RoJyxcbiAgICAgICAgY29tcG9uZW50OiBsZXZlbCA9PT0gJ2NvbXBvbmVudCcgfHwgbGV2ZWwgPT09ICdib3RoJyxcbiAgICAgIH07XG4gICAgfSkpO1xuICB9XG5cbiAgLy8gQWZ0ZXIgYW55IGZpbHRlciBtdXRhdGlvbjogcmUtZmV0Y2ggdGhlIHJlcG9ydCBzbyB0aGUgZGlhbG9nJ3MgZmlsdGVyIGxpc3RcbiAgLy8gKGFuZCB0aGUgcGFyZW50IGNhbnZhcywgb24gY2xvc2UpIHJlZmxlY3QgdGhlIG5ldyBncm91cHMvbGV2ZWxzLlxuICBwcml2YXRlIF9hZnRlck11dGF0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuZmlsdGVyc0NoYW5nZWQuZW1pdCgpO1xuXG4gICAgdGhpcy5fcmVwb3J0RGF0YS5nZXQodGhpcy5yZXBvcnQuaWQpXG4gICAgICAuc3Vic2NyaWJlKChyZXBvcnQ6IFJlcG9ydCkgPT4ge1xuICAgICAgICB0aGlzLnJlcG9ydCA9IHJlcG9ydDtcbiAgICAgICAgdGhpcy5fc2VlZEZpbHRlcnMocmVwb3J0LCB0aGlzLmNvbXBvbmVudC5pZCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX211dGF0aW9uRXJyb3IoZXJyb3I6IGFueSk6IHZvaWQge1xuICAgIHRoaXMuX21lc3NhZ2UuZXJyb3IoZXJyb3I/LmVycm9yPy5tZXNzYWdlID8/IGVycm9yPy5tZXNzYWdlID8/ICdGaWx0ZXIgb3BlcmF0aW9uIGZhaWxlZCcpO1xuICAgIC8vIFJlLXNlZWQgZnJvbSB0aGUgc2VydmVyIHNvIHRoZSBvcHRpbWlzdGljIHRvZ2dsZSBzbmFwcyBiYWNrIHRvIHRydXRoLlxuICAgIHRoaXMuX2FmdGVyTXV0YXRpb24oKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NlZWRGaWx0ZXJzKHJlcG9ydDogUmVwb3J0LCBjb21wb25lbnRJZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5fZ3JvdXBzQnlJZCA9IG5ldyBNYXAoKHJlcG9ydC5maWx0ZXJHcm91cHMgPz8gW10pLm1hcCgoZ3JvdXApID0+IFtncm91cC5pZCwgZ3JvdXBdKSk7XG5cbiAgICBjb25zdCBjb21wb25lbnQgPSByZXBvcnQucGFnZXNcbiAgICAgIC5mbGF0TWFwKChwYWdlKSA9PiBwYWdlLmNvbXBvbmVudHMpXG4gICAgICAuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGNvbXBvbmVudElkKTtcblxuICAgIHRoaXMuX2ZpbHRlcnMgPSBjb21wb25lbnQ/LmZpbHRlcnMgPz8gW107XG4gICAgdGhpcy5fcmVidWlsZFJvd3MoKTtcbiAgfVxuXG4gIC8vIFRoZSBzdGF0ZW1lbnQgdGhlIFNRTCB0YWIgc2hvd3MuIEZldGNoZWQgcmF0aGVyIHRoYW4gcmVhZCBvZmYgdGhlXG4gIC8vIGNvbXBvbmVudDogYSBkZXJpdmVkIGNvbXBvbmVudCBzdG9yZXMgYSBkb2N1bWVudCwgbm90IFNRTCwgc28gaXRzXG4gIC8vIHN0YXRlbWVudCBvbmx5IGV4aXN0cyBvbmNlIHRoZSBiYWNrZW5kIGNvbXBpbGVzIGl0LlxuICAvL1xuICAvLyBMb2FkZWQgaW4gbmdPbkluaXQgYmVzaWRlIHRoZSBjb2x1bW5zLCBOT1Qgb24gdGFiIGFjdGl2YXRpb24uIFRoZSB0YWJzIGFyZVxuICAvLyBub3QgbGF6eSAobm8gbWF0VGFiQ29udGVudCksIGFuZCBzd2l0Y2hpbmcgdGhlIHRhYi1ncm91cCdzIGBbKHNlbGVjdGVkKV1gXG4gIC8vIGJhbmFuYS1ib3ggdG8gYSBvbmUtd2F5IGJpbmRpbmcgcGx1cyAoc2VsZWN0ZWRDaGFuZ2UpIHRvIGdldCBhIGhvb2sgd291bGRcbiAgLy8gYnJlYWsgaXQ6IEZzVGFic0hlYWRlclRhYkdyb3VwRGlyZWN0aXZlIHNlbGYtYXNzaWducyBgdGhpcy5zZWxlY3RlZGAgYmVmb3JlXG4gIC8vIGl0IGVtaXRzLCBzbyB0aGUgZXZlbnQgaXMgZmlsdGVyZWQgb3V0IGFuZCB0aGUgbG9hZCB3b3VsZCBuZXZlciBmaXJlLiBPbmVcbiAgLy8gc21hbGwgcmVxdWVzdCB3aGVuIGEgZGlhbG9nIG9wZW5zIGlzIG5vdCB3b3J0aCB0aGF0IHJpc2suXG4gIHByaXZhdGUgX2xvYWRTcWwoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVwb3J0RGF0YS5jb21wb25lbnRTcWwodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChwcmV2aWV3OiBSZXBvcnRDb21wb25lbnRTcWwpID0+IHtcbiAgICAgICAgICB0aGlzLnNxbC5zZXQocHJldmlldz8uc3FsID8/IG51bGwpO1xuICAgICAgICAgIHRoaXMuc3FsQmFzZWxpbmUuc2V0KCEhcHJldmlldz8uYmFzZWxpbmUpO1xuICAgICAgICAgIHRoaXMuc3FsVGltZXpvbmUuc2V0KHByZXZpZXc/LnRpbWV6b25lIHx8ICdVVEMnKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChwcmV2aWV3Py5lcnJvciA/PyBudWxsKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMuc3FsLnNldChudWxsKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChlcnJvcj8uZXJyb3I/Lm1lc3NhZ2UgPz8gJ0NvdWxkIG5vdCByZWFkIHRoZSBjb21wb25lbnQgU1FMJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRDb2x1bW5zKCk6IHZvaWQge1xuICAgIHRoaXMuX3JlcG9ydERhdGEuY29tcG9uZW50Q29sdW1ucyh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKGNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSkgPT4ge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlcmFibGVDb2x1bW5zID0gY29sdW1ucyA/PyBbXTtcbiAgICAgICAgICB0aGlzLl9yZWJ1aWxkUm93cygpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5jb2x1bW5zRXJyb3Iuc2V0KGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyAnQ291bGQgbm90IHJlYWQgdGhlIGNvbXBvbmVudCBjb2x1bW5zJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2h1bWFuaXplKGNvbHVtbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29sdW1uXG4gICAgICAucmVwbGFjZSgvW19cXC1dKy9nLCAnICcpXG4gICAgICAucmVwbGFjZSgvXFxzKy9nLCAnICcpXG4gICAgICAudHJpbSgpXG4gICAgICAucmVwbGFjZSgvXFxiXFx3L2csIChjaGFyYWN0ZXIpID0+IGNoYXJhY3Rlci50b1VwcGVyQ2FzZSgpKTtcbiAgfVxufVxuIiwiPGZvcm1cbiAgICBmc0Zvcm1cbiAgICBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8aDEgbWF0LWRpYWxvZy10aXRsZT5cbiAgICAgIHt7IGNvbXBvbmVudC50aXRsZSB8fCAnQ29tcG9uZW50JyB9fVxuICAgIDwvaDE+XG4gICAgPG1hdC1kaWFsb2ctY29udGVudD5cbiAgICAgIDxtYXQtdGFiLWdyb3VwIFsoc2VsZWN0ZWQpXT1cInNlbGVjdGVkVGFiXCI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAgICAgICAgICAgIG5hbWU9XCJzZXR0aW5nc1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1jb2x1bW4gdGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICBUaXRsZVxuICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInRpdGxlXCJcbiAgICAgICAgICAgICAgICBuYW1lPVwidGl0bGVcIj5cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViaGVhZGluZy0yXCI+XG4gICAgICAgICAgICAgIFBhZGRpbmdcbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImdlb21ldHJ5LXJvd1wiPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIFRvcFxuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjNcIlxuICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nVG9wXCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWRkaW5nVG9wXCJcbiAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgIGluXG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgUmlnaHRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicGFkZGluZ1JpZ2h0XCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWRkaW5nUmlnaHRcIlxuICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgaW5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBCb3R0b21cbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicGFkZGluZ0JvdHRvbVwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ0JvdHRvbVwiXG4gICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjBcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIExlZnRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicGFkZGluZ0xlZnRcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZGRpbmdMZWZ0XCJcbiAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgIGluXG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwhLS0gQSBkZXJpdmVkIEtQSSdzIGNhcmQ6IHdoYXQgYSByaXNlIG1lYW5zLCBhIHRhcmdldCBhbmQgYVxuICAgICAgICAgICAgICAgICBzcGFya2xpbmUuIFRoZSBzZXJ2ZXIgY29tcHV0ZXMgdGhlIHByb2dyZXNzIGFuZCB0aGUgcG9pbnRzLiAtLT5cbiAgICAgICAgICAgIEBpZiAoa3BpQ2FyZCgpKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWJoZWFkaW5nLTJcIj5cbiAgICAgICAgICAgICAgICBDYXJkXG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIEluY3JlYXNlIGlzXG4gICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwiaW5jcmVhc2VJcygpXCJcbiAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiaW5jcmVhc2VJcy5zZXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJpbmNyZWFzZUlzXCI+XG4gICAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2Yga3BpUG9sYXJpdHlPcHRpb25zOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm9wdGlvbi52YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgQ29sb3JzIHRoZSBjaGFuZ2UgYW5kIGRlY2lkZXMgd2hlbiB0aGUgdGFyZ2V0IGlzIG1ldC5cbiAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIFRhcmdldFxuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjZcIlxuICAgICAgICAgICAgICAgICAgW3NpZ25lZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInRhcmdldFZhbHVlKClcIlxuICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwidGFyZ2V0VmFsdWUuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cInRhcmdldFZhbHVlXCJcbiAgICAgICAgICAgICAgICAgIFt2YWxpZGF0ZV09XCJ2YWxpZGF0ZVRhcmdldFwiPlxuICAgICAgICAgICAgICAgIEBpZiAodGFyZ2V0UGVyY2VudCgpKSB7XG4gICAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICAgICVcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICBUaGUgdmFsdWUgdG8gcmVhY2guIExlYXZlIGVtcHR5IGZvciBubyB0YXJnZXQuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgQGlmIChoYXNUYXJnZXQoKSkge1xuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIFRhcmdldCBsYWJlbFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwidGFyZ2V0TGFiZWwoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInRhcmdldExhYmVsLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInRhcmdldExhYmVsXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgIFNob3duIGJlZm9yZSB0aGUgdGFyZ2V0LCBzdWNoIGFzIEdvYWwuIEVtcHR5IHJlYWRzIFRhcmdldC5cbiAgICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1zbGlkZS10b2dnbGVcbiAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwic3BhcmtsaW5lKClcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzcGFya2xpbmUuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwic3BhcmtsaW5lXCI+XG4gICAgICAgICAgICAgICAgICBTcGFya2xpbmVcbiAgICAgICAgICAgICAgICA8L21hdC1zbGlkZS10b2dnbGU+XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgQSBzbWFsbCB0cmVuZCBsaW5lIG9mIHRoZSB2YWx1ZSBvdmVyIGl0cyBsYXN0IHBlcmlvZHMuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9mcy1sYWJlbC1maWVsZD5cbiAgICAgICAgICAgICAgQGlmIChzcGFya2xpbmUoKSkge1xuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIFNwYXJrbGluZSBwZXJpb2RcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJzcGFya2xpbmVHcmFudWxhcml0eSgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzcGFya2xpbmVHcmFudWxhcml0eS5zZXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInNwYXJrbGluZUdyYW51bGFyaXR5XCI+XG4gICAgICAgICAgICAgICAgICAgIEBmb3IgKG9wdGlvbiBvZiBncmFudWxhcml0eU9wdGlvbnM7IHRyYWNrIG9wdGlvbi52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBTcGFya2xpbmUgcGVyaW9kc1xuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIwXCJcbiAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwic3BhcmtsaW5lUGVyaW9kcygpXCJcbiAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lUGVyaW9kcy5zZXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJzcGFya2xpbmVQZXJpb2RzXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtSW50ZWdlcl09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCJzcGFya2xpbmVNaW5QZXJpb2RzXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1heF09XCJzcGFya2xpbmVNYXhQZXJpb2RzXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgICAgIEhvdyBtYW55IHBlcmlvZHMgdGhlIGxpbmUgY292ZXJzLCB7eyBzcGFya2xpbmVNaW5QZXJpb2RzIH19IHRvIHt7IHNwYXJrbGluZU1heFBlcmlvZHMgfX0uXG4gICAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9tYXQtdGFiPlxuICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgbGFiZWw9XCJGaWx0ZXJzXCJcbiAgICAgICAgICAgIG5hbWU9XCJmaWx0ZXJzXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInRhYi1ib2R5XCI+XG4gICAgICAgICAgICBAaWYgKGNvbHVtbnNFcnJvcigpKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5IGVycm9yXCI+XG4gICAgICAgICAgICAgICAge3sgY29sdW1uc0Vycm9yKCkgfX1cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICB9IEBlbHNlIGlmIChyb3dzKCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIDwhLS0gRXZlcnkgZmlsdGVyYWJsZSBjb2x1bW4uIFRvZ2dsZSB3aGVyZSBpdHMgY29udHJvbCBzaG93czogaW5cbiAgICAgICAgICAgICAgICAgICB0aGUgcmVwb3J0IGJhciwgb24gdGhpcyBjb21wb25lbnQsIGJvdGgsIG9yIG5laXRoZXIuIFRoZVxuICAgICAgICAgICAgICAgICAgIGludGVyZmFjZSAoZGF0ZSByYW5nZSB2cyB2YWx1ZSBwaWNrZXIpIGZvbGxvd3MgdGhlIGRhdGEuIC0tPlxuICAgICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJmaWx0ZXItdGFibGVcIj5cbiAgICAgICAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtbmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgIEZpbHRlclxuICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLXR5cGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICBUeXBlXG4gICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgUmVwb3J0IGJhclxuICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLXRvZ2dsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgICAgICAgQGZvciAocm93IG9mIHJvd3MoKTsgdHJhY2sgcm93LmNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwiZmlsdGVyLWNvbC1uYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyByb3cubGFiZWwgfX1cbiAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cImZpbHRlci1jb2wtdHlwZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgdHlwZUxhYmVsKHJvdy50eXBlKSB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwiZmlsdGVyLWNvbC10b2dnbGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5yZXBvcnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzZXRFeHBvc3VyZShyb3csICdyZXBvcnQnLCAkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cInsgc3RhbmRhbG9uZTogdHJ1ZSB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlNob3cgaW4gdGhlIHJlcG9ydCBiYXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNsaWRlLXRvZ2dsZT5cbiAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cuY29tcG9uZW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic2V0RXhwb3N1cmUocm93LCAnY29tcG9uZW50JywgJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7IHN0YW5kYWxvbmU6IHRydWUgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJTaG93IG9uIHRoaXMgY29tcG9uZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1zbGlkZS10b2dnbGU+XG4gICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICAgICAgICA8L3RhYmxlPlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5XCI+XG4gICAgICAgICAgICAgICAgVGhpcyBjb21wb25lbnQgaGFzIG5vIGZpbHRlcmFibGUgY29sdW1ucyB5ZXQg4oCUIGdpdmUgaXQgc29tZSBTUUwgZmlyc3QuXG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIlNRTFwiXG4gICAgICAgICAgICBuYW1lPVwic3FsXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInRhYi1ib2R5XCI+XG4gICAgICAgICAgICBAaWYgKHNxbEVycm9yKCkpIHtcbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHkgZXJyb3JcIj5cbiAgICAgICAgICAgICAgICB7eyBzcWxFcnJvcigpIH19XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfSBAZWxzZSBpZiAoc3FsKCkpIHtcbiAgICAgICAgICAgICAgQGlmIChzcWxCYXNlbGluZSgpKSB7XG4gICAgICAgICAgICAgICAgPCEtLSBBIGRlcml2ZWQgY29tcG9uZW50J3Mgc3RhdGVtZW50IGlzIGNvbXBpbGVkIGZyb20gaXRzXG4gICAgICAgICAgICAgICAgICAgICBkb2N1bWVudCB3aXRoIG5vIHZpZXdlciBzdGF0ZSwgc28gaXQgaXMgbm90IGJ5dGUtZm9yLWJ5dGVcbiAgICAgICAgICAgICAgICAgICAgIHdoYXQgcHJvZHVjZWQgdGhlIG51bWJlcnMgb24gc2NyZWVuLiBTYWlkIGhlcmUgcmF0aGVyIHRoYW5cbiAgICAgICAgICAgICAgICAgICAgIGxlZnQgZm9yIHRoZSByZWFkZXIgdG8gZGlzY292ZXIuIC0tPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5XCI+XG4gICAgICAgICAgICAgICAgICBDb21waWxlZCBmcm9tIHRoaXMgY29tcG9uZW50J3MgcXVlcnkg4oCUIG5vIGZpbHRlcnMgYXBwbGllZCwgdGltZXMgaW4ge3sgc3FsVGltZXpvbmUoKSB9fS5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8cHJlIGNsYXNzPVwiY29kZS1ibG9ja1wiPnt7IHNxbCgpIH19PC9wcmU+XG4gICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICBUaGlzIGNvbXBvbmVudCBoYXMgbm8gU1FMIHlldC5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgIGxhYmVsPVwiQ29uZmlnXCJcbiAgICAgICAgICAgIG5hbWU9XCJjb25maWdcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+XG4gICAgICAgICAgICAgIHt7IGNvbmZpZ0pzb24gfX1cbiAgICAgICAgICAgIDwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICA8L21hdC10YWItZ3JvdXA+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgIDwhLS0gU2F2ZSB8IERlbGV0ZSB8IENhbmNlbCwgdGhlIHN0YW5kYXJkIG9yZGVyLiBmcy1mb3JtLWRpYWxvZy1hY3Rpb25zXG4gICAgICAgICAgIHJlbmRlcnMgaXRzIG93biBTYXZlL0RvbmUgQkVGT1JFIHRoZSBwcm9qZWN0ZWQgY29udGVudCwgd2hpY2ggd291bGRcbiAgICAgICAgICAgcHV0IERlbGV0ZSBhZnRlciBDYW5jZWwsIHNvIGBbc2F2ZV09XCJmYWxzZVwiYCBmb290cyB0aGUgcm93IGhlcmUgYW5kXG4gICAgICAgICAgIGFsbCB0aHJlZSBidXR0b25zIGFyZSBwcm9qZWN0ZWQgaW4gb3JkZXIuIFNhdmUgc3VibWl0cyB0aGUgU2V0dGluZ3NcbiAgICAgICAgICAgdGFiOyB0aGUgb3RoZXIgdGFicyBwZXJzaXN0IGFzIHlvdSB0b3VjaCB0aGVtLCBzbyB0aGV5IGdldCBEb25lLiAtLT5cbiAgICAgIDxmcy1mb3JtLWRpYWxvZy1hY3Rpb25zIFtzYXZlXT1cImZhbHNlXCI+XG4gICAgICAgIEBpZiAoc2VsZWN0ZWRUYWIgPT09ICdzZXR0aW5ncycpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiPlxuICAgICAgICAgICAgU2F2ZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICAgIERvbmVcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKClcIj5cbiAgICAgICAgICBEZWxldGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjYW5jZWwtYnV0dG9uXCJcbiAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICBDYW5jZWxcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2ZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPiJdfQ==
|
|
523
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL2NvbXBvbmVudC1zZXR0aW5ncy9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvY29tcG9uZW50LXNldHRpbmdzL2NvbXBvbmVudC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQVUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQy9GLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBbUIsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdJLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMxRixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUs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UyxpTEFDVCxRQUFRLGlVQUNSLFNBQVMscUpBQ1QsU0FBUyx3ZUFDVCxjQUFjLDBVQUNkLFVBQVU7OzRGQUdELDBCQUEwQjtrQkE3QnRDLFNBQVM7c0NBR1MsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJLFdBQ1A7d0JBQ1AsV0FBVzt3QkFDWCxZQUFZO3dCQUNaLFlBQVk7d0JBQ1osY0FBYzt3QkFDZCxhQUFhO3dCQUNiLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixjQUFjO3dCQUNkLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixjQUFjO3dCQUNkLFlBQVk7d0JBQ1osT0FBTzt3QkFDUCxRQUFRO3dCQUNSLFNBQVM7d0JBQ1QsU0FBUzt3QkFDVCxRQUFRO3dCQUNSLFNBQVM7d0JBQ1QsU0FBUzt3QkFDVCxjQUFjO3dCQUNkLFVBQVU7cUJBQ1giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgY29tcHV0ZWQsIGluamVjdCwgc2lnbmFsLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE1BVF9ESUFMT0dfREFUQSwgTWF0RGlhbG9nQWN0aW9ucywgTWF0RGlhbG9nQ2xvc2UsIE1hdERpYWxvZ0NvbnRlbnQsIE1hdERpYWxvZ1JlZiwgTWF0RGlhbG9nVGl0bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkLCBNYXRIaW50LCBNYXRMYWJlbCwgTWF0U3VmZml4IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRCdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTWF0SW5wdXQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XG5pbXBvcnQgeyBNYXRPcHRpb24sIE1hdFNlbGVjdCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XG5pbXBvcnQgeyBNYXRTbGlkZVRvZ2dsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NsaWRlLXRvZ2dsZSc7XG5pbXBvcnQgeyBNYXRUYWJzTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFicyc7XG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XG5cbmltcG9ydCB7IEZzRGlhbG9nTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGlhbG9nJztcbmltcG9ydCB7IEZzRm9ybU1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2Zvcm0nO1xuaW1wb3J0IHsgRnNMYWJlbE1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2xhYmVsJztcbmltcG9ydCB7IEZzTWFza01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21hc2snO1xuaW1wb3J0IHsgRnNNZXNzYWdlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWVzc2FnZSc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5pbXBvcnQgeyBGc1RhYnNNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC90YWJzJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7IFJlcG9ydENoYW5nZVBvbGFyaXR5IH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LWNoYW5nZS1wb2xhcml0eS5lbnVtJztcbmltcG9ydCB7IFJlcG9ydFZhbHVlRm9ybWF0IH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LXZhbHVlLWZvcm1hdC5lbnVtJztcbmltcG9ydCB7IFJlcG9ydFZhbHVlRm9ybXVsYSB9IGZyb20gJy4uLy4uL2VudW1zL3JlcG9ydC12YWx1ZS1mb3JtdWxhLmVudW0nO1xuaW1wb3J0IHsgcmVzb2x2ZUZvcm1hdENvbnRleHQgfSBmcm9tICcuLi8uLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgS1BJX1NQQVJLTElORV9ERUZBVUxUX0dSQU5VTEFSSVRZLFxuICBLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyxcbiAga3BpQ2FyZFNldHRpbmdzLFxuICBzYW1lS3BpQ2FyZFNldHRpbmdzLFxufSBmcm9tICcuLi8uLi9rcGktY2FyZCc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LFxuICBDb21wb25lbnRTZXR0aW5ncyxcbiAgR1JBTlVMQVJJVFlfT1BUSU9OUyxcbiAgS3BpQ2FyZFNldHRpbmdzLFxuICBLcGlDb25maWcsXG4gIFJlcG9ydCxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRDb21wb25lbnRTcWwsXG4gIFJlcG9ydEZpbHRlcixcbiAgUmVwb3J0RmlsdGVyR3JvdXAsXG4gIFJlcG9ydEZpbHRlckxldmVsLFxuICBSZXBvcnRGaWx0ZXJUeXBlLFxuICBSZXBvcnRGaWx0ZXJhYmxlQ29sdW1uLFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgREVGQVVMVF9DT01QT05FTlRfUEFERElORyB9IGZyb20gJy4uLy4uL2xheW91dCc7XG5pbXBvcnQgeyBlc2NhcGVIdG1sIH0gZnJvbSAnLi4vLi4vdGV4dCc7XG5pbXBvcnQgeyBvcGVyYW5kS2V5cywgcmVwb3J0Q29tcG9uZW50cywgdmFsdWVLZXkgfSBmcm9tICcuLi8uLi92YWx1ZXMnO1xuXG5cbi8vIFdoYXQgdGhlIGRpYWxvZyBoYW5kcyBiYWNrLiBUaGUgU2V0dGluZ3MgdGFiJ3MgU2F2ZSBjYXJyaWVzIHRoZSBuZXdcbi8vIGBzZXR0aW5nc2A7IERlbGV0ZSBjYXJyaWVzIGBkZWxldGVkYCBhbmQgbm8gc2V0dGluZ3MsIGJlY2F1c2UgdGhlIGNvbXBvbmVudFxuLy8gaXQgd2FzIG9wZW5lZCBmb3Igbm8gbG9uZ2VyIGV4aXN0cy4gRXZlcnkgb3RoZXIgZXhpdCAoQ2FuY2VsLCBEb25lLCBFc2NhcGUsXG4vLyBiYWNrZHJvcCkgY2xvc2VzIHdpdGggbm8gcmVzdWx0IOKAlCBmaWx0ZXIgd29yayBpcyBhbm5vdW5jZWQgYXMgaXQgaGFwcGVuc1xuLy8gaW5zdGVhZCwgdGhyb3VnaCBgZmlsdGVyc0NoYW5nZWRgLlxuZXhwb3J0IGludGVyZmFjZSBDb21wb25lbnRTZXR0aW5nc1Jlc3VsdCB7XG4gIHNldHRpbmdzPzogQ29tcG9uZW50U2V0dGluZ3M7XG4gIGRlbGV0ZWQ/OiBib29sZWFuO1xufVxuXG4vLyBXaGF0IHRoZSBzZXR0aW5ncyBlbmRwb2ludCByZXR1cm5zIGZvciB0aGUgY29tcG9uZW50OiBpdHMgaWQgYW5kLCBmcm9tIGFcbi8vIHNlcnZlciB0aGF0IHNhdmVzIGEgS1BJJ3MgY2FyZCBrZXlzLCB0aGUgd2hvbGUgY29uZmlnIGFzIHNhdmVkLlxuaW50ZXJmYWNlIENvbXBvbmVudFNldHRpbmdzUmVzcG9uc2Uge1xuICBpZDogbnVtYmVyO1xuICBjb25maWc/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGw7XG59XG5cblxuLy8gV2hhdCBhIHJpc2UgaW4gYSBLUEkncyB2YWx1ZSBtZWFucywgZm9yIHRoZSBJbmNyZWFzZSBpcyBzZWxlY3QuXG5jb25zdCBLUElfQ0hBTkdFX1BPTEFSSVRZX09QVElPTlM6IHsgdmFsdWU6IFJlcG9ydENoYW5nZVBvbGFyaXR5OyBuYW1lOiBzdHJpbmcgfVtdID0gW1xuICB7IHZhbHVlOiBSZXBvcnRDaGFuZ2VQb2xhcml0eS5Hb29kLCBuYW1lOiAnR29vZCBuZXdzIOKAlCBhIHJpc2Ugc2hvd3MgZ3JlZW4nIH0sXG4gIHsgdmFsdWU6IFJlcG9ydENoYW5nZVBvbGFyaXR5LkJhZCwgbmFtZTogJ0JhZCBuZXdzIOKAlCBhIHJpc2Ugc2hvd3MgcmVkJyB9LFxuICB7IHZhbHVlOiBSZXBvcnRDaGFuZ2VQb2xhcml0eS5OZXV0cmFsLCBuYW1lOiAnTmVpdGhlciDigJQgbm8gY29sb3InIH0sXG5dO1xuXG4vLyBBIEtQSSBzcGFya2xpbmUncyBwZXJpb2RzIHN0YXkgd2l0aGluIDIgdG8gNjAuXG5jb25zdCBLUElfU1BBUktMSU5FX01JTl9QRVJJT0RTID0gMjtcbmNvbnN0IEtQSV9TUEFSS0xJTkVfTUFYX1BFUklPRFMgPSA2MDtcblxuLy8gQSBwZXJjZW50IEtQSSdzIHRhcmdldCBpcyBlbnRlcmVkIGFzIHRoZSBwZXJjZW50IHNob3duICgxNSBmb3IgMTUlKSBhbmRcbi8vIHN0b3JlZCBhcyB0aGUgMC0xIHJhdGlvIGl0cyB2YWx1ZSBhcnJpdmVzIGluOyB0aGUgc2VydmVyIHJlZnVzZXMgYSBzdG9yZWRcbi8vIHRhcmdldCBhYm92ZSAxMDAsIHdoaWNoIGlzIDEwLDAwMCUgaGVyZS5cbmNvbnN0IEtQSV9QRVJDRU5UX1RBUkdFVF9NQVggPSAxMDAwMDtcblxuLy8gSG93IGEgZm9ybXVsYSB2YWx1ZSdzIFNldHRpbmdzIHRhYiB3cml0ZXMgb3V0IHdoYXQgaXQgd29ya3Mgb3V0LCBpbiBpdHNcbi8vIG9wZXJhbmRzJyBuYW1lcy5cbmNvbnN0IEZPUk1VTEFfTElORVM6IFJlY29yZDxSZXBvcnRWYWx1ZUZvcm11bGEsIChuYW1lczogc3RyaW5nW10pID0+IHN0cmluZz4gPSB7XG4gIFtSZXBvcnRWYWx1ZUZvcm11bGEuQ2hhbmdlXTogKG5hbWVzKSA9PiBuYW1lcy5qb2luKCcg4oiSICcpLFxuICBbUmVwb3J0VmFsdWVGb3JtdWxhLlBlcmNlbnRDaGFuZ2VdOiAoW2EsIGJdKSA9PiBgJSBjaGFuZ2Ugb2YgJHthfSBvdmVyICR7Yn1gLFxuICBbUmVwb3J0VmFsdWVGb3JtdWxhLlJhdGlvXTogKG5hbWVzKSA9PiBuYW1lcy5qb2luKCcgw7cgJyksXG4gIFtSZXBvcnRWYWx1ZUZvcm11bGEuU3VtXTogKG5hbWVzKSA9PiBuYW1lcy5qb2luKCcgKyAnKSxcbn07XG5cblxuLy8gT25lIHJvdyBvZiB0aGUgRmlsdGVycyB0YWIgbGlzdGluZzogYSBmaWx0ZXJhYmxlIGNvbHVtbiwgdGhlIGludGVyZmFjZVxuLy8gaW5mZXJyZWQgZnJvbSBpdHMgZGF0YSwgYW5kIHdoZXJlIGl0cyBmaWx0ZXIgaXMgZXhwb3NlZCAodGhlIHR3byB0b2dnbGVzKS5cbmludGVyZmFjZSBGaWx0ZXJSb3cge1xuICBjb2x1bW46IHN0cmluZztcbiAgdHlwZTogUmVwb3J0RmlsdGVyVHlwZTtcbiAgbGFiZWw6IHN0cmluZztcbiAgcmVwb3J0OiBib29sZWFuO1xuICBjb21wb25lbnQ6IGJvb2xlYW47XG59XG5cblxuLy8gQ29tcG9uZW50IHNldHRpbmdzLCBpbiB0YWJzOlxuLy8gICBTZXR0aW5ncyDigJQgdGl0bGUgYW5kIGNvbnRlbnQgcGFkZGluZyAoYSB2YWx1ZToganVzdCBpdHMgbmFtZSwgc2luY2UgaXRcbi8vICAgc2l0cyBpbnNpZGUgYSB0ZXh0IGJsb2NrJ3Mgd29yZHMgYW5kIGhhcyBubyBib3gpLCBhbmQgb24gYSBkZXJpdmVkIEtQSSBpdHMgY2FyZDpcbi8vICAgd2hhdCBhIHJpc2UgbWVhbnMsIGEgdGFyZ2V0IGFuZCBhIHNwYXJrbGluZSAobnVtYmVyIGZvcm1hdHMgc3RheSB3aXRoXG4vLyAgIHRoZSBBSSkuIFBvc2l0aW9uL3NpemUgYXJlIHR1bmVkIGJ5IGRyYWdnaW5nIG9uIHRoZSBjYW52YXM7IGhlaWdodFxuLy8gICBiZWhhdmlvdXIgZm9sbG93cyBmcm9tIHRoZSBjb21wb25lbnQgdHlwZS5cbi8vICAgRmlsdGVycyAg4oCUIE9ORSBsaXN0aW5nIG9mIGV2ZXJ5IGZpbHRlcmFibGUgY29sdW1uIG9uIHRoaXMgY29tcG9uZW50LiBFYWNoXG4vLyAgIHJvdyBjYXJyaWVzIHR3byB0b2dnbGVzOiBzaG93IGluIHRoZSByZXBvcnQgYmFyIGFuZC9vciBzaG93IG9uIHRoaXNcbi8vICAgY29tcG9uZW50IChib3RoLCBlaXRoZXIsIG9yIG5laXRoZXIpLiBUaGUgaW50ZXJmYWNlIChkYXRlIHJhbmdlIHZzIHZhbHVlXG4vLyAgIHBpY2tlcikgaXMgaW5mZXJyZWQgZnJvbSB0aGUgZGF0YSwgbmV2ZXIgY2hvc2VuLiBFYWNoIHRvZ2dsZSBwZXJzaXN0c1xuLy8gICBpbW1lZGlhdGVseSBhbmQgcmVmcmVzaGVzIHRoZSBpbi1kaWFsb2cgbGlzdC4gQSB2YWx1ZSBoYXMgbm8gY29tcG9uZW50XG4vLyAgIHRvIHNob3cgYSBmaWx0ZXIgb24sIHNvIGl0IGdldHMgdGhlIHJlcG9ydCBiYXIgdG9nZ2xlIG9ubHkuXG4vLyAgIFNRTCAvIENvbmZpZyDigJQgcmVhZC1vbmx5IGRpYWdub3N0aWNzLlxuLy8gQSBmb3JtdWxhIHZhbHVlIGhhcyBubyBGaWx0ZXJzIG9yIFNRTCB0YWI6IHRoZSBzZXJ2ZXIgd29ya3MgaXQgb3V0IG9mIG90aGVyXG4vLyB2YWx1ZXMgb24gaXRzIHBhZ2UsIHNvIGl0IHJ1bnMgbm8gc3RhdGVtZW50IGFuZCBmb2xsb3dzIHRoZSBmaWx0ZXJzIG9mIHRoZVxuLy8gdmFsdWVzIGl0IHJlYWRzLiBJdHMgU2V0dGluZ3MgdGFiIHNheXMgd2hhdCBpdCB3b3JrcyBvdXQsIHVuZGVyIGl0cyBuYW1lLlxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jb21wb25lbnQtc2V0dGluZ3MuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0Zvcm1Nb2R1bGUsXG4gICAgRnNNYXNrTW9kdWxlLFxuICAgIEZzRGlhbG9nTW9kdWxlLFxuICAgIEZzTGFiZWxNb2R1bGUsXG4gICAgRnNUYWJzTW9kdWxlLFxuICAgIE1hdFRhYnNNb2R1bGUsXG4gICAgTWF0RGlhbG9nVGl0bGUsXG4gICAgTWF0RGlhbG9nQ29udGVudCxcbiAgICBNYXREaWFsb2dBY3Rpb25zLFxuICAgIE1hdERpYWxvZ0Nsb3NlLFxuICAgIE1hdEZvcm1GaWVsZCxcbiAgICBNYXRIaW50LFxuICAgIE1hdExhYmVsLFxuICAgIE1hdFN1ZmZpeCxcbiAgICBNYXRCdXR0b24sXG4gICAgTWF0SW5wdXQsXG4gICAgTWF0T3B0aW9uLFxuICAgIE1hdFNlbGVjdCxcbiAgICBNYXRTbGlkZVRvZ2dsZSxcbiAgICBNYXRUb29sdGlwLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb21wb25lbnRTZXR0aW5nc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgLy8gQSBmaWx0ZXIgd2FzIGFkZGVkLCByZW1vdmVkIG9yIHJlLWxldmVsbGVkLCBzbyB0aGUgcmVwb3J0J3MgZmlsdGVyIGdyb3Vwc1xuICAvLyBjaGFuZ2VkLiBUaG9zZSBtdXRhdGlvbnMgcGVyc2lzdCB0aGUgbW9tZW50IHRoZXkgYXJlIGNsaWNrZWQgYW5kIHRoZSBkaWFsb2dcbiAgLy8gY2FuIHRoZW4gYmUgZGlzbWlzc2VkIGJ5IGEgcm91dGUgdGhhdCBjYXJyaWVzIG5vIHJlc3VsdCAoRXNjYXBlLCBiYWNrZHJvcCksXG4gIC8vIHNvIHRoZSBwYWdlIGlzIHRvbGQgaGVyZSByYXRoZXIgdGhhbiB0aHJvdWdoIHRoZSBjbG9zZSByZXN1bHQuXG4gIHB1YmxpYyByZWFkb25seSBmaWx0ZXJzQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBwdWJsaWMgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQ7XG4gIHB1YmxpYyByZXBvcnQ6IFJlcG9ydDtcblxuICBwdWJsaWMgc2VsZWN0ZWRUYWIgPSAnc2V0dGluZ3MnO1xuXG4gIHB1YmxpYyB0aXRsZSA9ICcnO1xuXG4gIC8vIENvbXBvbmVudCBwYWRkaW5nIGluIGluY2hlcy4gYG51bWJlciB8IHN0cmluZ2AgZm9yIHRoZSBzYW1lIHJlYXNvbiBhcyB0aGVcbiAgLy8gcGFnZSBkaW1lbnNpb25zIGluIHJlcG9ydC1zZXR0aW5nczogZnNNYXNrTnVtYmVyIHNlZWRzIGZyb20gdGhlIG51bWJlciBidXRcbiAgLy8gaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgc3RyaW5nLCBhbmQgc2F2ZSBjYXN0cyBpdCBvbmNlIG9uIHRoZSB3YXkgb3V0LlxuICBwdWJsaWMgcGFkZGluZ1RvcDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdSaWdodDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgcHVibGljIHBhZGRpbmdCb3R0b206IG51bWJlciB8IHN0cmluZyA9IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkc7XG4gIHB1YmxpYyBwYWRkaW5nTGVmdDogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcblxuICBwdWJsaWMgY29uZmlnSnNvbiA9ICcnO1xuXG4gIC8vIC0tLS0gS1BJIGNhcmQgc3RhdGUgKGEgZGVyaXZlZCBLUEkgb25seSkgLS0tLVxuICBwdWJsaWMgcmVhZG9ubHkga3BpUG9sYXJpdHlPcHRpb25zID0gS1BJX0NIQU5HRV9QT0xBUklUWV9PUFRJT05TO1xuICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnVsYXJpdHlPcHRpb25zID0gR1JBTlVMQVJJVFlfT1BUSU9OUztcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZU1pblBlcmlvZHMgPSBLUElfU1BBUktMSU5FX01JTl9QRVJJT0RTO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lTWF4UGVyaW9kcyA9IEtQSV9TUEFSS0xJTkVfTUFYX1BFUklPRFM7XG4gIHB1YmxpYyByZWFkb25seSBrcGlDYXJkID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gQSB2YWx1ZSBpbnNpZGUgYSB0ZXh0IGJsb2NrOiBubyBib3gsIHNvIG5vIHBhZGRpbmcuXG4gIHB1YmxpYyByZWFkb25seSBpc1ZhbHVlID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gQSBmb3JtdWxhIHZhbHVlOiBubyBzdGF0ZW1lbnQsIGNvbHVtbnMgb3IgZmlsdGVycyBvZiBpdHMgb3duLlxuICBwdWJsaWMgcmVhZG9ubHkgaXNGb3JtdWxhID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gV2hhdCBhIGZvcm11bGEgd29ya3Mgb3V0LCBpbiBpdHMgb3BlcmFuZHMnIG5hbWVzOyBlbXB0eSBmb3IgYW55IG90aGVyXG4gIC8vIGNvbXBvbmVudC5cbiAgcHVibGljIHJlYWRvbmx5IGZvcm11bGFMaW5lID0gY29tcHV0ZWQoKCkgPT4gKHRoaXMuaXNGb3JtdWxhKCkgPyB0aGlzLl9mb3JtdWxhTGluZSgpIDogJycpKTtcbiAgcHVibGljIHJlYWRvbmx5IGluY3JlYXNlSXMgPSBzaWduYWw8UmVwb3J0Q2hhbmdlUG9sYXJpdHk+KFJlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2QpO1xuICAvLyBUaGUgdGFyZ2V0IGFzIHR5cGVkOiBmc01hc2tOdW1iZXIgaGFuZHMgYmFjayB0aGUgdW5tYXNrZWQgc3RyaW5nLiBFbXB0eVxuICAvLyBtZWFucyBubyB0YXJnZXQuIEEgcGVyY2VudCBLUEkncyBpcyBpbiBwZXJjZW50ICh0YXJnZXRQZXJjZW50KS5cbiAgcHVibGljIHJlYWRvbmx5IHRhcmdldFZhbHVlID0gc2lnbmFsPG51bWJlciB8IHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0TGFiZWwgPSBzaWduYWwoJycpO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFyZ2V0UGVyY2VudCA9IHNpZ25hbChmYWxzZSk7XG4gIHB1YmxpYyByZWFkb25seSBoYXNUYXJnZXQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9udW1iZXIodGhpcy50YXJnZXRWYWx1ZSgpKSAhPT0gbnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSBzcGFya2xpbmUgPSBzaWduYWwoZmFsc2UpO1xuICBwdWJsaWMgcmVhZG9ubHkgc3BhcmtsaW5lR3JhbnVsYXJpdHkgPSBzaWduYWw8Q2hhcnRHcmFudWxhcml0eT4oS1BJX1NQQVJLTElORV9ERUZBVUxUX0dSQU5VTEFSSVRZKTtcbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrbGluZVBlcmlvZHMgPSBzaWduYWw8bnVtYmVyIHwgc3RyaW5nPihLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyk7XG5cbiAgLy8gLS0tLSBTUUwgdGFiIHN0YXRlIC0tLS1cbiAgLy8gVGhlIHN0YXRlbWVudCwgb25jZSBmZXRjaGVkLiBOdWxsIHdoaWxlIGl0IGlzIGluIGZsaWdodCwgYW5kIG51bGwgd2hlbiB0aGVcbiAgLy8gY29tcG9uZW50J3MgZG9jdW1lbnQgY291bGQgbm90IGJlIGNvbXBpbGVkIChzcWxFcnJvciB0aGVuIHNheXMgd2h5KS5cbiAgcHVibGljIHJlYWRvbmx5IHNxbCA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgLy8gVHJ1ZSB3aGVuIHRoZSBzdGF0ZW1lbnQgaXMgYSBERVJJVkVEIGJhc2VsaW5lOiBubyBmaWx0ZXJzLCB0aGUgYXV0aG9yZWRcbiAgLy8gZ3JhaW4sIHRpbWVzIGluIHRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZS4gVGhlIHRhYiBzYXlzIHNvLCBiZWNhdXNlIHRoZVxuICAvLyBudW1iZXJzIG9uIHNjcmVlbiBjb21lIGZyb20gdGhpcyBzdGF0ZW1lbnQgcGx1cyB0aGUgdmlld2VyJ3Mgb3duIGNob2ljZXNcbiAgLy8gYW5kIHRoZSB0d28gY2FuIGRpZmZlci5cbiAgcHVibGljIHJlYWRvbmx5IHNxbEJhc2VsaW5lID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gVGhlIHpvbmUgdGhlIHN0YXRlbWVudCB3YXMgY29tcGlsZWQgaW46IHRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZSwgc2VudFxuICAvLyB3aXRoIHRoZSBTUUwuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCBpdCBjb21waWxlZCBpbiBVVEMuXG4gIHB1YmxpYyByZWFkb25seSBzcWxUaW1lem9uZSA9IHNpZ25hbCgnVVRDJyk7XG4gIHB1YmxpYyByZWFkb25seSBzcWxFcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyAtLS0tIGZpbHRlciBtYW5hZ2VtZW50IHN0YXRlIC0tLS1cbiAgLy8gT25lIHJvdyBwZXIgZmlsdGVyYWJsZSBjb2x1bW4uIFRoZSB0d28gYm9vbGVhbnMgZHJpdmUgdGhlIHRvZ2dsZXM7IHdlIGZsaXBcbiAgLy8gdGhlbSBvcHRpbWlzdGljYWxseSBvbiBjbGljayAoc28gdGhlIFVJIG5ldmVyIGJsaW5rcyB3aGlsZSB0aGUgcmVxdWVzdCBpc1xuICAvLyBpbiBmbGlnaHQpIGFuZCByZWNvbmNpbGUgZnJvbSB0aGUgc2VydmVyIG9uIHJlbG9hZC5cbiAgcHVibGljIHJlYWRvbmx5IHJvd3MgPSBzaWduYWw8RmlsdGVyUm93W10+KFtdKTtcbiAgcHVibGljIHJlYWRvbmx5IGNvbHVtbnNFcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyBUaGUgcmF3IGlucHV0cyB0aGUgcm93cyBhcmUgYnVpbHQgZnJvbS5cbiAgcHJpdmF0ZSBfZmlsdGVyYWJsZUNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSA9IFtdO1xuICBwcml2YXRlIF9maWx0ZXJzOiBSZXBvcnRGaWx0ZXJbXSA9IFtdO1xuICBwcml2YXRlIF9ncm91cHNCeUlkID0gbmV3IE1hcDxudW1iZXIsIFJlcG9ydEZpbHRlckdyb3VwPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3R5cGVMYWJlbHM6IFJlY29yZDxSZXBvcnRGaWx0ZXJUeXBlLCBzdHJpbmc+ID0ge1xuICAgIHNlbGVjdDogJ1BpY2sgdmFsdWVzJyxcbiAgICBkYXRlUmFuZ2U6ICdEYXRlIHJhbmdlJyxcbiAgICBrZXl3b3JkOiAnU2VhcmNoIHRleHQnLFxuICB9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2RhdGE6IHsgcmVwb3J0OiBSZXBvcnQ7IGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50IH0gPSBpbmplY3QoTUFUX0RJQUxPR19EQVRBKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZGlhbG9nUmVmID0gaW5qZWN0PE1hdERpYWxvZ1JlZjxDb21wb25lbnRTZXR0aW5nc0NvbXBvbmVudCwgQ29tcG9uZW50U2V0dGluZ3NSZXN1bHQ+PihNYXREaWFsb2dSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlID0gaW5qZWN0KEZzTWVzc2FnZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMucmVwb3J0ID0gdGhpcy5fZGF0YS5yZXBvcnQ7XG4gICAgdGhpcy5jb21wb25lbnQgPSB0aGlzLl9kYXRhLmNvbXBvbmVudDtcblxuICAgIHRoaXMudGl0bGUgPSB0aGlzLmNvbXBvbmVudC50aXRsZSA/PyAnJztcbiAgICB0aGlzLmlzVmFsdWUuc2V0KHRoaXMuY29tcG9uZW50LnR5cGUgPT09ICd2YWx1ZScpO1xuICAgIHRoaXMuaXNGb3JtdWxhLnNldCghIXRoaXMuY29tcG9uZW50LmNvbmZpZz8uZm9ybXVsYSk7XG5cbiAgICBjb25zdCBwYWRkaW5nID0gdGhpcy5jb21wb25lbnQuY29uZmlnPy5wYWRkaW5nO1xuICAgIHRoaXMucGFkZGluZ1RvcCA9IHBhZGRpbmc/LnRvcCA/PyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuICAgIHRoaXMucGFkZGluZ1JpZ2h0ID0gcGFkZGluZz8ucmlnaHQgPz8gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgICB0aGlzLnBhZGRpbmdCb3R0b20gPSBwYWRkaW5nPy5ib3R0b20gPz8gREVGQVVMVF9DT01QT05FTlRfUEFERElORztcbiAgICB0aGlzLnBhZGRpbmdMZWZ0ID0gcGFkZGluZz8ubGVmdCA/PyBERUZBVUxUX0NPTVBPTkVOVF9QQURESU5HO1xuXG4gICAgdGhpcy5jb25maWdKc29uID0gSlNPTi5zdHJpbmdpZnkodGhpcy5jb21wb25lbnQuY29uZmlnID8/IHt9LCBudWxsLCAyKTtcblxuICAgIHRoaXMuX3NlZWRLcGlDYXJkKCk7XG5cbiAgICB0aGlzLl9zZWVkRmlsdGVycyh0aGlzLnJlcG9ydCwgdGhpcy5jb21wb25lbnQuaWQpO1xuXG4gICAgLy8gQSBmb3JtdWxhIGhhcyBubyBzdGF0ZW1lbnQgdG8gY29tcGlsZSBhbmQgbm8gY29sdW1ucyB0byBmaWx0ZXIgb24sIGFuZFxuICAgIC8vIHRoZSBzZXJ2ZXIgd291bGQgcmVmdXNlIGJvdGggcmVxdWVzdHMuXG4gICAgaWYgKCF0aGlzLmlzRm9ybXVsYSgpKSB7XG4gICAgICB0aGlzLl9sb2FkQ29sdW1ucygpO1xuICAgICAgdGhpcy5fbG9hZFNxbCgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEh1bWFuLWZyaWVuZGx5IG5hbWUgZm9yIHRoZSBpbmZlcnJlZCBpbnRlcmZhY2Ugc2hvd24gYmVzaWRlIGVhY2ggY29sdW1uLlxuICBwdWJsaWMgdHlwZUxhYmVsKHR5cGU6IFJlcG9ydEZpbHRlclR5cGUpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl90eXBlTGFiZWxzW3R5cGVdID8/IHR5cGU7XG4gIH1cblxuICAvLyBDb25maXJtIGFuZCBkZWxldGUgaGVyZSwgd2hpbGUgdGhlIGRpYWxvZyBpcyBzdGlsbCBvcGVuLCB0aGVuIGNsb3NlIHdpdGggYVxuICAvLyBgZGVsZXRlZGAgcmVzdWx0IGZvciB0aGUgcGFnZSB0byBhY3Qgb24g4oCUIHRoZSBzYW1lIHNoYXBlIHRoZSByZXBvcnRcbiAgLy8gc2V0dGluZ3MgZGlhbG9nIHVzZXMgZm9yIGRlbGV0aW5nIGEgcmVwb3J0LlxuICAvL1xuICAvLyBUaGUgY29uZmlybSBzYXlzIGl0IGNhbm5vdCBiZSB1bmRvbmUgYmVjYXVzZSwgZnJvbSB0aGUgVUksIGl0IGNhbm5vdDogdGhlXG4gIC8vIHJvdyBpcyBzb2Z0LWRlbGV0ZWQgc2VydmVyLXNpZGUgYnV0IG5vdGhpbmcgaGVyZSByZXN0b3JlcyBhIGNvbXBvbmVudC5cbiAgLy8gQSB2YWx1ZSdzIGNvbmZpcm0gYWxzbyBzYXlzIHdoYXQgZ29lcyB3aXRoIGl0OiB0aGUgc2VydmVyIHRha2VzIGl0c1xuICAvLyB0b2tlbnMgb3V0IG9mIGV2ZXJ5IHRleHQgb24gaXRzIHBhZ2UsIG5vdCBqdXN0IHRoZSBvbmUgaXQgd2FzIG9wZW5lZCBmcm9tLFxuICAvLyBhbmQgZGVsZXRlcyB0aGUgZm9ybXVsYXMgdGhhdCByZWFkIGl0IChfZGVwZW5kZW50c05vdGUpLlxuICAvL1xuICAvLyBUaGUgcHJvbXB0IHJlbmRlcnMgaXRzIHRlbXBsYXRlIGFzIGh0bWwsIHNvIGV2ZXJ5IG5hbWUgaW4gaXQgaXMgZXNjYXBlZC5cbiAgcHVibGljIGRlbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9wcm9tcHQuY29uZmlybSh0aGlzLmlzVmFsdWUoKVxuICAgICAgPyB7XG4gICAgICAgIHRpdGxlOiAnRGVsZXRlIFZhbHVlJyxcbiAgICAgICAgdGVtcGxhdGU6IGBEZWxldGUgdGhlIHZhbHVlIFwiJHtlc2NhcGVIdG1sKHRoaXMuY29tcG9uZW50LnRpdGxlIHx8IHZhbHVlS2V5KHRoaXMuY29tcG9uZW50KSl9XCI/IEl0IGlzIGFsc28gdGFrZW4gb3V0IG9mIGV2ZXJ5IHRleHQgb24gdGhpcyBwYWdlLiBUaGlzIGNhbm5vdCBiZSB1bmRvbmUuJHt0aGlzLl9kZXBlbmRlbnRzTm90ZSgpfWAsXG4gICAgICB9XG4gICAgICA6IHtcbiAgICAgICAgdGl0bGU6ICdEZWxldGUgQ29tcG9uZW50JyxcbiAgICAgICAgdGVtcGxhdGU6IGBBcmUgeW91IHN1cmUgeW91IHdvdWxkIGxpa2UgdG8gZGVsZXRlIFwiJHtlc2NhcGVIdG1sKHRoaXMuY29tcG9uZW50LnRpdGxlIHx8ICd0aGlzIGNvbXBvbmVudCcpfVwiPyBUaGlzIGNhbm5vdCBiZSB1bmRvbmUuYCxcbiAgICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlQ29tcG9uZW50KHRoaXMucmVwb3J0LmlkLCB0aGlzLmNvbXBvbmVudC5pZCkpLFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2Vzcyh0aGlzLmlzVmFsdWUoKSA/ICdWYWx1ZSBkZWxldGVkJyA6ICdDb21wb25lbnQgZGVsZXRlZCcpO1xuICAgICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZSh7IGRlbGV0ZWQ6IHRydWUgfSk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvLyBBIHBlcmNlbnQgdGFyZ2V0J3MgYm91bmQsIGluIHRoZSBwZXJjZW50IGl0IGlzIHR5cGVkIGluLiBJdCByZWFkcyB0aGVcbiAgLy8gY29udHJvbCwgd2hpY2ggZnNGb3JtIHZhbGlkYXRlcyBiZWZvcmUgbmdNb2RlbENoYW5nZSB1cGRhdGVzIHRoZSBzaWduYWwuXG4gIHB1YmxpYyB2YWxpZGF0ZVRhcmdldCA9IChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiB2b2lkID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuX251bWJlcihjb250cm9sLnZhbHVlKTtcblxuICAgIGlmICh0aGlzLnRhcmdldFBlcmNlbnQoKSAmJiB2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSA+IEtQSV9QRVJDRU5UX1RBUkdFVF9NQVgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQSBwZXJjZW50IHRhcmdldCBjYW4gYmUgYXQgbW9zdCAxMCwwMDAlJyk7XG4gICAgfVxuICB9O1xuXG4gIHB1YmxpYyBzYXZlID0gKCkgPT4ge1xuICAgIGNvbnN0IHNldHRpbmdzOiBDb21wb25lbnRTZXR0aW5ncyA9IHtcbiAgICAgIC8vIFRoZSBzZXJ2ZXIgdHJpbXMgYSB0aXRsZTsgYSB2YWx1ZSdzIE5hbWUgaXMgd2hhdCBpdHMgY2hpcHMgc2hvdywgc28gaXRcbiAgICAgIC8vIGdvZXMgYXMgdGhlIHNlcnZlciBrZWVwcyBpdC5cbiAgICAgIHRpdGxlOiB0aGlzLmlzVmFsdWUoKSA/IHRoaXMudGl0bGUudHJpbSgpIDogdGhpcy50aXRsZSxcbiAgICAgIHBhZGRpbmc6IHtcbiAgICAgICAgdG9wOiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ1RvcCksXG4gICAgICAgIHJpZ2h0OiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ1JpZ2h0KSxcbiAgICAgICAgYm90dG9tOiB0aGlzLl9wYWRkaW5nKHRoaXMucGFkZGluZ0JvdHRvbSksXG4gICAgICAgIGxlZnQ6IHRoaXMuX3BhZGRpbmcodGhpcy5wYWRkaW5nTGVmdCksXG4gICAgICB9LFxuICAgIH07XG5cbiAgICAvLyBUaGUgY2FyZCBrZXlzIGdvIGFzIGNvbmZpZyBrZXlzIGJlc2lkZSB0aGUgcGFkZGluZyAoaW5jcmVhc2VJcywgdGFyZ2V0XG4gICAgLy8gYW5kIHNwYXJrbGluZSwgbnVsbCB0byByZW1vdmUgb25lKSwgYW5kIG9ubHkgd2hlbiB0aGV5IGNoYW5nZWQsIHNvIGFcbiAgICAvLyB0aXRsZSBlZGl0IG5ldmVyIHRvdWNoZXMgdGhlbS5cbiAgICBjb25zdCBrcGkgPSB0aGlzLmtwaUNhcmQoKSA/IHRoaXMuX2twaUNhcmRTZXR0aW5ncygpIDogbnVsbDtcbiAgICBjb25zdCBrcGlDaGFuZ2VkID0gISFrcGlcbiAgICAgICYmICFzYW1lS3BpQ2FyZFNldHRpbmdzKGtwaSwga3BpQ2FyZFNldHRpbmdzKHRoaXMuY29tcG9uZW50LmNvbmZpZyBhcyBLcGlDb25maWcpKTtcblxuICAgIHJldHVybiB0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZUNvbXBvbmVudCh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQsIHtcbiAgICAgIHRpdGxlOiBzZXR0aW5ncy50aXRsZSxcbiAgICAgIC4uLih0aGlzLmlzVmFsdWUoKSA/IHt9IDogeyBwYWRkaW5nOiBzZXR0aW5ncy5wYWRkaW5nIH0pLFxuICAgICAgLi4uKGtwaUNoYW5nZWQgPyBrcGkgOiB7fSksXG4gICAgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKHJlc3BvbnNlOiBDb21wb25lbnRTZXR0aW5nc1Jlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgLy8gVGhlIGNhcmQgaXMgZHJhd24gZnJvbSB0aGUga2V5cyB0aGUgc2VydmVyIHNhdmVkLCByZWFkIGJhY2sgZnJvbVxuICAgICAgICAgIC8vIHRoZSBjb25maWcgaXQgcmV0dXJucy4gQSBzZXJ2ZXIgdGhhdCByZXR1cm5zIG5vIGNvbmZpZyBkaWQgbm90XG4gICAgICAgICAgLy8gc2F2ZSB0aGVtLCBzbyB0aGUgY2FyZCBrZWVwcyB3aGF0IGl0IGhhZCBhbmQgdGhlIGRpYWxvZyBzYXlzIHNvLlxuICAgICAgICAgIGNvbnN0IHNhdmVkID0ga3BpQ2hhbmdlZCA/IHRoaXMuX3NhdmVkS3BpQ2FyZChyZXNwb25zZSkgOiBudWxsO1xuXG4gICAgICAgICAgaWYgKGtwaUNoYW5nZWQgJiYgIXNhdmVkKSB7XG4gICAgICAgICAgICB0aGlzLl9tZXNzYWdlLndhcm5pbmcoJ0NvbXBvbmVudCBzYXZlZCwgYnV0IHRoZSBzZXJ2ZXIgZGlkIG5vdCBzYXZlIHRoZSBjYXJkIHNldHRpbmdzJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2Uuc3VjY2Vzcyh0aGlzLmlzVmFsdWUoKSA/ICdWYWx1ZSBzYXZlZCcgOiAnQ29tcG9uZW50IHNhdmVkJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKHsgc2V0dGluZ3M6IHNhdmVkID8geyAuLi5zZXR0aW5ncywga3BpOiBzYXZlZCB9IDogc2V0dGluZ3MgfSk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfTtcblxuICAvLyBGbGlwIG9uZSBleHBvc3VyZSAocmVwb3J0IGJhciBvciB0aGlzIGNvbXBvbmVudCkgZm9yIGEgcm93LiBXZSB1cGRhdGUgdGhlXG4gIC8vIHJvdydzIGJvb2xlYW4gZmlyc3Qg4oCUIHNvIHRoZSB0b2dnbGUgc3RheXMgcHV0IHdpdGggbm8gYmxpbmsg4oCUIHRoZW4gcGVyc2lzdFxuICAvLyBhbmQgcmVjb25jaWxlIG9uIHJlbG9hZC4gTmVpdGhlciBvbiDihpIgbm8gZmlsdGVyIChyZW1vdmVkKTsgZWl0aGVyIG9uIOKGkiB0aGVcbiAgLy8gZmlsdGVyIGV4aXN0cyBhdCB0aGUgY29tYmluZWQgbGV2ZWwuIFRoZSBpbnRlcmZhY2UgdHlwZSBpcyBpbmZlcnJlZFxuICAvLyBzZXJ2ZXItc2lkZS4gQSB2YWx1ZSBoYXMgdGhlIHJlcG9ydCBiYXIgdG9nZ2xlIG9ubHksIHdpdGggaXRzIG93biBydWxlc1xuICAvLyAoX3NldFZhbHVlRXhwb3N1cmUpLlxuICBwdWJsaWMgc2V0RXhwb3N1cmUocm93OiBGaWx0ZXJSb3csIHRhcmdldDogJ3JlcG9ydCcgfCAnY29tcG9uZW50Jywgb246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1ZhbHVlKCkpIHtcbiAgICAgIGlmICh0YXJnZXQgPT09ICdyZXBvcnQnKSB7XG4gICAgICAgIHRoaXMuX3NldFZhbHVlRXhwb3N1cmUocm93LCBvbik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByb3dbdGFyZ2V0XSA9IG9uO1xuXG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLl9maWx0ZXJzLmZpbmQoKGZpbHRlcikgPT4gZmlsdGVyLmZpbHRlckNvbHVtbiA9PT0gcm93LmNvbHVtbik7XG5cbiAgICBpZiAoIXJvdy5yZXBvcnQgJiYgIXJvdy5jb21wb25lbnQpIHtcbiAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICB0aGlzLl9ydW4odGhpcy5fcmVwb3J0RGF0YS5kZWxldGVGaWx0ZXIodGhpcy5yZXBvcnQuaWQsIGV4aXN0aW5nLmlkKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBsZXZlbDogUmVwb3J0RmlsdGVyTGV2ZWwgPSByb3cucmVwb3J0ICYmIHJvdy5jb21wb25lbnRcbiAgICAgID8gJ2JvdGgnXG4gICAgICA6IChyb3cucmVwb3J0ID8gJ3JlcG9ydCcgOiAnY29tcG9uZW50Jyk7XG5cbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLnVwZGF0ZUZpbHRlckdyb3VwKHRoaXMucmVwb3J0LmlkLCBleGlzdGluZy5maWx0ZXJHcm91cElkLCB7IGxldmVsIH0pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcnVuKHRoaXMuX3JlcG9ydERhdGEuYWRkRmlsdGVyKHRoaXMucmVwb3J0LmlkLCB0aGlzLmNvbXBvbmVudC5pZCwge1xuICAgICAgICBmaWx0ZXJDb2x1bW46IHJvdy5jb2x1bW4sXG4gICAgICAgIGxhYmVsOiByb3cubGFiZWwsXG4gICAgICAgIGxldmVsLFxuICAgICAgfSkpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgdmFsdWUncyByZXBvcnQgYmFyIHRvZ2dsZSwgdGhlIG9ubHkgb25lIGl0IGhhcy4gSXRzIGZpbHRlcidzIGdyb3VwIGlzXG4gIC8vIHJlcG9ydC13aWRlIGFuZCBtYXkgYmUgc2hhcmVkICh0aGUgcmVwb3J0J3MgUGVyaW9kLCBzYXkpLCBhbmQgYSB2YWx1ZSBoYXNcbiAgLy8gbm8gc3RyaXAgb2YgaXRzIG93biwgc28gdGhpcyBuZXZlciBsb3dlcnMgYSBncm91cCdzIGxldmVsOiBvZmYgdW5saW5rc1xuICAvLyB0aGlzIHZhbHVlIGFsb25lIGFuZCB0aGUgZ3JvdXAga2VlcHMgaXRzIG90aGVyIG1lbWJlcnMsIGFuZCBvbiByYWlzZXMgYVxuICAvLyBzdHJpcC1vbmx5IGdyb3VwIHRvIGJvdGgsIGtlZXBpbmcgaXRzIHN0cmlwcywgb3IgYWRkcyB0aGUgdmFsdWUgdG8gYSBuZXdcbiAgLy8gcmVwb3J0LWxldmVsIGdyb3VwLlxuICBwcml2YXRlIF9zZXRWYWx1ZUV4cG9zdXJlKHJvdzogRmlsdGVyUm93LCBvbjogYm9vbGVhbik6IHZvaWQge1xuICAgIHJvdy5yZXBvcnQgPSBvbjtcblxuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5fZmlsdGVycy5maW5kKChmaWx0ZXIpID0+IGZpbHRlci5maWx0ZXJDb2x1bW4gPT09IHJvdy5jb2x1bW4pO1xuXG4gICAgaWYgKCFvbikge1xuICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLmRlbGV0ZUZpbHRlcih0aGlzLnJlcG9ydC5pZCwgZXhpc3RpbmcuaWQpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuX3J1bih0aGlzLl9yZXBvcnREYXRhLmFkZEZpbHRlcih0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQsIHtcbiAgICAgICAgZmlsdGVyQ29sdW1uOiByb3cuY29sdW1uLFxuICAgICAgICBsYWJlbDogcm93LmxhYmVsLFxuICAgICAgICBsZXZlbDogJ3JlcG9ydCcsXG4gICAgICB9KSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLl9ncm91cHNCeUlkLmdldChleGlzdGluZy5maWx0ZXJHcm91cElkKT8ubGV2ZWwgPT09ICdjb21wb25lbnQnKSB7XG4gICAgICB0aGlzLl9ydW4odGhpcy5fcmVwb3J0RGF0YS51cGRhdGVGaWx0ZXJHcm91cCh0aGlzLnJlcG9ydC5pZCwgZXhpc3RpbmcuZmlsdGVyR3JvdXBJZCwgeyBsZXZlbDogJ2JvdGgnIH0pKTtcbiAgICB9XG4gIH1cblxuICAvLyBXaGF0IGEgZm9ybXVsYSB3b3JrcyBvdXQsIG5hbWluZyBlYWNoIG9wZXJhbmQgYXMgaXRzIGNoaXBzIGRvLiBBbiBvcCB0aGlzXG4gIC8vIHZpZXdlciBkb2VzIG5vdCBrbm93IHJlYWRzIG5vdGhpbmcuXG4gIHByaXZhdGUgX2Zvcm11bGFMaW5lKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZm9ybXVsYSA9IHRoaXMuY29tcG9uZW50LmNvbmZpZz8uZm9ybXVsYTtcbiAgICBjb25zdCBsaW5lID0gZm9ybXVsYSA/IEZPUk1VTEFfTElORVNbZm9ybXVsYS5vcF0gOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy5fbGF5ZXJWYWx1ZXMoKTtcblxuICAgIHJldHVybiBsaW5lID8gbGluZShvcGVyYW5kS2V5cyh0aGlzLmNvbXBvbmVudCkubWFwKChrZXkpID0+IHRoaXMuX3ZhbHVlTmFtZSh2YWx1ZXMsIGtleSkpKSA6ICcnO1xuICB9XG5cbiAgLy8gVGhlIHNlbnRlbmNlIGEgcXVlcnkgdmFsdWUncyBkZWxldGUgY29uZmlybSBlbmRzIHdpdGggd2hlbiBmb3JtdWxhcyBvbiBpdHNcbiAgLy8gbGF5ZXIgcmVhZCBpdDogdGhlIHNlcnZlciBkZWxldGVzIHRob3NlIHdpdGggaXQuIEVtcHR5IHdoZW4gbm9uZSBkb2VzLCBhbmRcbiAgLy8gZm9yIGEgZm9ybXVsYSwgd2hvc2Ugb3BlcmFuZHMgc3RheS5cbiAgcHJpdmF0ZSBfZGVwZW5kZW50c05vdGUoKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5pc0Zvcm11bGEoKSkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGNvbnN0IGtleSA9IHZhbHVlS2V5KHRoaXMuY29tcG9uZW50KTtcbiAgICBjb25zdCBuYW1lcyA9IHRoaXMuX2xheWVyVmFsdWVzKClcbiAgICAgIC5maWx0ZXIoKHZhbHVlKSA9PiBvcGVyYW5kS2V5cyh2YWx1ZSkuaW5jbHVkZXMoa2V5KSlcbiAgICAgIC5tYXAoKHZhbHVlKSA9PiBlc2NhcGVIdG1sKHZhbHVlLnRpdGxlIHx8IHZhbHVlS2V5KHZhbHVlKSkpO1xuXG4gICAgcmV0dXJuIG5hbWVzLmxlbmd0aCA/IGAgVGhlIHZhbHVlcyB3b3JrZWQgb3V0IGZyb20gaXQgYXJlIGRlbGV0ZWQgdG9vOiAke25hbWVzLmpvaW4oJywgJyl9LmAgOiAnJztcbiAgfVxuXG4gIC8vIFRoZSB2YWx1ZXMgb2YgdGhlIGxheWVyIHRoaXMgdmFsdWUgYmVsb25ncyB0bzogdGhlIHBhZ2Ugd2hvc2UgdmFsdWVzIGhvbGRcbiAgLy8gaXQsIGVsc2UgdGhlIG1hc3RlcidzIChhIGhlYWRlciBvciBmb290ZXIgdmFsdWUpLlxuICBwcml2YXRlIF9sYXllclZhbHVlcygpOiBSZXBvcnRDb21wb25lbnRbXSB7XG4gICAgY29uc3QgcGFnZSA9ICh0aGlzLnJlcG9ydC5wYWdlcyA/PyBbXSlcbiAgICAgIC5maW5kKChjYW5kaWRhdGUpID0+IChjYW5kaWRhdGUudmFsdWVzID8/IFtdKS5zb21lKCh2YWx1ZSkgPT4gdmFsdWUuaWQgPT09IHRoaXMuY29tcG9uZW50LmlkKSk7XG5cbiAgICByZXR1cm4gKHBhZ2UgPz8gdGhpcy5yZXBvcnQubWFzdGVyKT8udmFsdWVzID8/IFtdO1xuICB9XG5cbiAgLy8gV2hhdCBhIHZhbHVlIGlzIGNhbGxlZCB3aGVyZSBpdHMgY2hpcHMgc2hvdyBpdDogaXRzIG5hbWUsIGVsc2UgaXRzIGtleS5cbiAgLy8gVGhlIG5ld2VzdCB2YWx1ZSBob2xkcyBhIGtleSwgYXMgaXQgZG9lcyBpbiB0aGUgdGV4dCdzIHRva2Vucy5cbiAgcHJpdmF0ZSBfdmFsdWVOYW1lKHZhbHVlczogUmVwb3J0Q29tcG9uZW50W10sIGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCB2YWx1ZSA9IHZhbHVlcy5maWx0ZXIoKGNhbmRpZGF0ZSkgPT4gdmFsdWVLZXkoY2FuZGlkYXRlKSA9PT0ga2V5KS5wb3AoKTtcblxuICAgIHJldHVybiB2YWx1ZT8udGl0bGUgfHwga2V5O1xuICB9XG5cbiAgLy8gQSBkZXJpdmVkIEtQSSdzIGNhcmQga2V5cywgZnJvbSBpdHMgY29uZmlnLiBBIHNxbC1tb2RlIEtQSSBjYW5ub3QgY2FycnlcbiAgLy8gdGhlbSwgc28gaXQgZ2V0cyBubyBjYXJkIGZpZWxkcy5cbiAgcHJpdmF0ZSBfc2VlZEtwaUNhcmQoKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gKHRoaXMuY29tcG9uZW50LmNvbmZpZyA/PyB7fSkgYXMgS3BpQ29uZmlnO1xuXG4gICAgdGhpcy5rcGlDYXJkLnNldCh0aGlzLmNvbXBvbmVudC50eXBlID09PSAna3BpJyAmJiAhdGhpcy5jb21wb25lbnQuc3FsKTtcbiAgICB0aGlzLmluY3JlYXNlSXMuc2V0KGNvbmZpZy5pbmNyZWFzZUlzID8/IFJlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2QpO1xuICAgIHRoaXMudGFyZ2V0UGVyY2VudC5zZXQoY29uZmlnLm1lYXN1cmU/LmZvcm1hdCA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudFxuICAgICAgJiYgcmVzb2x2ZUZvcm1hdENvbnRleHQodGhpcy5yZXBvcnQpLnJhdGlvUGVyY2VudCk7XG4gICAgdGhpcy50YXJnZXRWYWx1ZS5zZXQodGhpcy5fdGFyZ2V0U2hvd24oY29uZmlnLnRhcmdldD8udmFsdWUgPz8gbnVsbCkpO1xuICAgIHRoaXMudGFyZ2V0TGFiZWwuc2V0KGNvbmZpZy50YXJnZXQ/LmxhYmVsID8/ICcnKTtcbiAgICB0aGlzLnNwYXJrbGluZS5zZXQoISFjb25maWcuc3BhcmtsaW5lKTtcbiAgICB0aGlzLnNwYXJrbGluZUdyYW51bGFyaXR5LnNldChjb25maWcuc3BhcmtsaW5lPy5ncmFudWxhcml0eSA/PyBLUElfU1BBUktMSU5FX0RFRkFVTFRfR1JBTlVMQVJJVFkpO1xuICAgIHRoaXMuc3BhcmtsaW5lUGVyaW9kcy5zZXQoY29uZmlnLnNwYXJrbGluZT8ucGVyaW9kcyA/PyBLUElfU1BBUktMSU5FX0RFRkFVTFRfUEVSSU9EUyk7XG4gIH1cblxuICAvLyBUaGUgY2FyZCBrZXlzIHRoZSBzZXJ2ZXIgc2F2ZWQsIGZyb20gdGhlIGNvbmZpZyBpdHMgcmVzcG9uc2UgY2FycmllcztcbiAgLy8gbnVsbCB3aGVuIGl0IGNhcnJpZXMgbm9uZSAoYSBzZXJ2ZXIgdGhhdCBkb2VzIG5vdCBzYXZlIHRoZW0pLlxuICBwcml2YXRlIF9zYXZlZEtwaUNhcmQocmVzcG9uc2U6IENvbXBvbmVudFNldHRpbmdzUmVzcG9uc2UgfCBudWxsIHwgdW5kZWZpbmVkKTogS3BpQ2FyZFNldHRpbmdzIHwgbnVsbCB7XG4gICAgY29uc3QgY29uZmlnID0gcmVzcG9uc2U/LmNvbmZpZztcblxuICAgIHJldHVybiBjb25maWcgJiYgdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgPyBrcGlDYXJkU2V0dGluZ3MoY29uZmlnIGFzIEtwaUNvbmZpZykgOiBudWxsO1xuICB9XG5cbiAgLy8gR29vZCBpcyB3aGF0IGFuIGFic2VudCBpbmNyZWFzZUlzIHJlYWRzLCBzbyBpdCBpcyBzYXZlZCBhcyBhYnNlbnQuXG4gIHByaXZhdGUgX2twaUNhcmRTZXR0aW5ncygpOiBLcGlDYXJkU2V0dGluZ3Mge1xuICAgIGNvbnN0IHRhcmdldCA9IHRoaXMuX251bWJlcih0aGlzLnRhcmdldFZhbHVlKCkpO1xuICAgIGNvbnN0IGxhYmVsID0gdGhpcy50YXJnZXRMYWJlbCgpLnRyaW0oKTtcblxuICAgIHJldHVybiB7XG4gICAgICBpbmNyZWFzZUlzOiB0aGlzLmluY3JlYXNlSXMoKSA9PT0gUmVwb3J0Q2hhbmdlUG9sYXJpdHkuR29vZCA/IG51bGwgOiB0aGlzLmluY3JlYXNlSXMoKSxcbiAgICAgIHRhcmdldDogdGFyZ2V0ID09PSBudWxsID8gbnVsbCA6IHsgdmFsdWU6IHRoaXMuX3RhcmdldFN0b3JlZCh0YXJnZXQpLCBsYWJlbDogbGFiZWwgfHwgbnVsbCB9LFxuICAgICAgc3BhcmtsaW5lOiB0aGlzLnNwYXJrbGluZSgpXG4gICAgICAgID8geyBncmFudWxhcml0eTogdGhpcy5zcGFya2xpbmVHcmFudWxhcml0eSgpLCBwZXJpb2RzOiB0aGlzLl9udW1iZXIodGhpcy5zcGFya2xpbmVQZXJpb2RzKCkpIH1cbiAgICAgICAgOiBudWxsLFxuICAgIH07XG4gIH1cblxuICAvLyBBIHN0b3JlZCByYXRpbyBhcyB0aGUgcGVyY2VudCB0eXBlZCwgcm91bmRlZCBzbyAwLjE1IHJlYWRzIDE1IGFuZCBub3RcbiAgLy8gMTUuMDAwMDAwMDAwMDAwMDAyLlxuICBwcml2YXRlIF90YXJnZXRTaG93bih2YWx1ZTogbnVtYmVyIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCAhdGhpcy50YXJnZXRQZXJjZW50KCkpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCAqIDFlNikgLyAxZTY7XG4gIH1cblxuICBwcml2YXRlIF90YXJnZXRTdG9yZWQodmFsdWU6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudGFyZ2V0UGVyY2VudCgpID8gdmFsdWUgLyAxMDAgOiB2YWx1ZTtcbiAgfVxuXG4gIC8vIEEgdHlwZWQgbnVtYmVyLCBvciBudWxsIHdoZW4gdGhlIGZpZWxkIGlzIGVtcHR5LlxuICBwcml2YXRlIF9udW1iZXIodmFsdWU6IG51bWJlciB8IHN0cmluZyB8IG51bGwpOiBudW1iZXIgfCBudWxsIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBudW1iZXIgPSB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInID8gdmFsdWUgOiBwYXJzZUZsb2F0KHZhbHVlKTtcblxuICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUobnVtYmVyKSA/IG51bWJlciA6IG51bGw7XG4gIH1cblxuICAvLyBUaGUgcGFkZGluZyBhcyBhIHJlYWwgbnVtYmVyIGZvciB0aGUgd2lyZS4gZnNNYXNrTnVtYmVyIGhhbmRzIGJhY2sgdGhlXG4gIC8vIHVubWFza2VkIHN0cmluZyBpdCBidWlsdCB3aXRoIGEgZml4ZWQgJy4nIHJhZGl4LCBzbyB0aGlzIGlzIGEgc3RyYWlnaHRcbiAgLy8gcGFyc2UgLSB0aGUgd2hvbGUgcmVhc29uIGZvciB0aGUgbWFzayBpcyB0aGF0IGEgbmF0aXZlIG51bWJlciBpbnB1dCB3b3VsZFxuICAvLyBwYWludCAoYW5kIHJlYWQgYmFjaykgdGhlIHZpZXdlcidzIG93biBsb2NhbGUgc2VwYXJhdG9yIGluc3RlYWQuXG4gIHByaXZhdGUgX3BhZGRpbmcodmFsdWU6IG51bWJlciB8IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZSA6IHBhcnNlRmxvYXQodmFsdWUpO1xuICB9XG5cbiAgLy8gUnVuIGEgZmlsdGVyIG11dGF0aW9uLCB0aGVuIHJlbG9hZCB0byByZWNvbmNpbGUgdGhlIG9wdGltaXN0aWMgc3RhdGUuXG4gIHByaXZhdGUgX3J1bihyZXF1ZXN0OiBPYnNlcnZhYmxlPHVua25vd24+KTogdm9pZCB7XG4gICAgcmVxdWVzdC5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKCkgPT4gdGhpcy5fYWZ0ZXJNdXRhdGlvbigpLFxuICAgICAgZXJyb3I6IChlcnJvcikgPT4gdGhpcy5fbXV0YXRpb25FcnJvcihlcnJvciksXG4gICAgfSk7XG4gIH1cblxuICAvLyBCdWlsZCB0aGUgcm93IHZpZXctbW9kZWwgZnJvbSB0aGUgbG9hZGVkIGNvbHVtbnMgKyBmaWx0ZXJzL2dyb3Vwcy4gRWFjaFxuICAvLyByb3cncyB0b2dnbGVzIHJlZmxlY3Qgd2hlcmUgaXRzIGZpbHRlciBncm91cCBpcyBjdXJyZW50bHkgZXhwb3NlZC4gQVxuICAvLyB2YWx1ZSdzIHJvd3MgbmV2ZXIgcmVhZCBhcyBvbiBhIGNvbXBvbmVudDogaXQgaGFzIG5vIHN0cmlwLCB3aGF0ZXZlclxuICAvLyBsZXZlbCBhIGdyb3VwIGl0IHNoYXJlcyBpcyBhdC5cbiAgcHJpdmF0ZSBfcmVidWlsZFJvd3MoKTogdm9pZCB7XG4gICAgdGhpcy5yb3dzLnNldCh0aGlzLl9maWx0ZXJhYmxlQ29sdW1ucy5tYXAoKGNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgZmlsdGVyID0gdGhpcy5fZmlsdGVycy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5maWx0ZXJDb2x1bW4gPT09IGNvbHVtbi5jb2x1bW4pO1xuICAgICAgY29uc3QgbGV2ZWwgPSBmaWx0ZXIgPyB0aGlzLl9ncm91cHNCeUlkLmdldChmaWx0ZXIuZmlsdGVyR3JvdXBJZCk/LmxldmVsIDogdW5kZWZpbmVkO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2x1bW46IGNvbHVtbi5jb2x1bW4sXG4gICAgICAgIHR5cGU6IGNvbHVtbi50eXBlLFxuICAgICAgICBsYWJlbDogZmlsdGVyPy5sYWJlbFxuICAgICAgICAgIHx8IHRoaXMuX2dyb3Vwc0J5SWQuZ2V0KGZpbHRlcj8uZmlsdGVyR3JvdXBJZCA/PyAtMSk/LmxhYmVsXG4gICAgICAgICAgfHwgdGhpcy5faHVtYW5pemUoY29sdW1uLmNvbHVtbiksXG4gICAgICAgIHJlcG9ydDogbGV2ZWwgPT09ICdyZXBvcnQnIHx8IGxldmVsID09PSAnYm90aCcsXG4gICAgICAgIGNvbXBvbmVudDogIXRoaXMuaXNWYWx1ZSgpICYmIChsZXZlbCA9PT0gJ2NvbXBvbmVudCcgfHwgbGV2ZWwgPT09ICdib3RoJyksXG4gICAgICB9O1xuICAgIH0pKTtcbiAgfVxuXG4gIC8vIEFmdGVyIGFueSBmaWx0ZXIgbXV0YXRpb246IHJlLWZldGNoIHRoZSByZXBvcnQgc28gdGhlIGRpYWxvZydzIGZpbHRlciBsaXN0XG4gIC8vIChhbmQgdGhlIHBhcmVudCBjYW52YXMsIG9uIGNsb3NlKSByZWZsZWN0IHRoZSBuZXcgZ3JvdXBzL2xldmVscy5cbiAgcHJpdmF0ZSBfYWZ0ZXJNdXRhdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLmZpbHRlcnNDaGFuZ2VkLmVtaXQoKTtcblxuICAgIHRoaXMuX3JlcG9ydERhdGEuZ2V0KHRoaXMucmVwb3J0LmlkKVxuICAgICAgLnN1YnNjcmliZSgocmVwb3J0OiBSZXBvcnQpID0+IHtcbiAgICAgICAgdGhpcy5yZXBvcnQgPSByZXBvcnQ7XG4gICAgICAgIHRoaXMuX3NlZWRGaWx0ZXJzKHJlcG9ydCwgdGhpcy5jb21wb25lbnQuaWQpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9tdXRhdGlvbkVycm9yKGVycm9yOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl9tZXNzYWdlLmVycm9yKGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyBlcnJvcj8ubWVzc2FnZSA/PyAnRmlsdGVyIG9wZXJhdGlvbiBmYWlsZWQnKTtcbiAgICAvLyBSZS1zZWVkIGZyb20gdGhlIHNlcnZlciBzbyB0aGUgb3B0aW1pc3RpYyB0b2dnbGUgc25hcHMgYmFjayB0byB0cnV0aC5cbiAgICB0aGlzLl9hZnRlck11dGF0aW9uKCk7XG4gIH1cblxuICAvLyBUaGUgY29tcG9uZW50J3MgZmlsdGVycyBhbmQgdGhlIGdyb3VwcyB0aGV5IHNpdCBpbiwgZnJvbSB0aGUgcmVwb3J0IGFzXG4gIC8vIGxhc3QgbG9hZGVkLiBBIHZhbHVlIGlzIGxpc3RlZCBpbiBpdHMgcGFnZSdzIHZhbHVlcywgbm90IGl0cyBjb21wb25lbnRzLlxuICBwcml2YXRlIF9zZWVkRmlsdGVycyhyZXBvcnQ6IFJlcG9ydCwgY29tcG9uZW50SWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuX2dyb3Vwc0J5SWQgPSBuZXcgTWFwKChyZXBvcnQuZmlsdGVyR3JvdXBzID8/IFtdKS5tYXAoKGdyb3VwKSA9PiBbZ3JvdXAuaWQsIGdyb3VwXSkpO1xuXG4gICAgY29uc3QgY29tcG9uZW50ID0gcmVwb3J0Q29tcG9uZW50cyhyZXBvcnQpXG4gICAgICAuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGNvbXBvbmVudElkKTtcblxuICAgIHRoaXMuX2ZpbHRlcnMgPSBjb21wb25lbnQ/LmZpbHRlcnMgPz8gW107XG4gICAgdGhpcy5fcmVidWlsZFJvd3MoKTtcbiAgfVxuXG4gIC8vIFRoZSBzdGF0ZW1lbnQgdGhlIFNRTCB0YWIgc2hvd3MuIEZldGNoZWQgcmF0aGVyIHRoYW4gcmVhZCBvZmYgdGhlXG4gIC8vIGNvbXBvbmVudDogYSBkZXJpdmVkIGNvbXBvbmVudCBzdG9yZXMgYSBkb2N1bWVudCwgbm90IFNRTCwgc28gaXRzXG4gIC8vIHN0YXRlbWVudCBvbmx5IGV4aXN0cyBvbmNlIHRoZSBiYWNrZW5kIGNvbXBpbGVzIGl0LlxuICAvL1xuICAvLyBMb2FkZWQgaW4gbmdPbkluaXQgYmVzaWRlIHRoZSBjb2x1bW5zLCBOT1Qgb24gdGFiIGFjdGl2YXRpb24uIFRoZSB0YWJzIGFyZVxuICAvLyBub3QgbGF6eSAobm8gbWF0VGFiQ29udGVudCksIGFuZCBzd2l0Y2hpbmcgdGhlIHRhYi1ncm91cCdzIGBbKHNlbGVjdGVkKV1gXG4gIC8vIGJhbmFuYS1ib3ggdG8gYSBvbmUtd2F5IGJpbmRpbmcgcGx1cyAoc2VsZWN0ZWRDaGFuZ2UpIHRvIGdldCBhIGhvb2sgd291bGRcbiAgLy8gYnJlYWsgaXQ6IEZzVGFic0hlYWRlclRhYkdyb3VwRGlyZWN0aXZlIHNlbGYtYXNzaWducyBgdGhpcy5zZWxlY3RlZGAgYmVmb3JlXG4gIC8vIGl0IGVtaXRzLCBzbyB0aGUgZXZlbnQgaXMgZmlsdGVyZWQgb3V0IGFuZCB0aGUgbG9hZCB3b3VsZCBuZXZlciBmaXJlLiBPbmVcbiAgLy8gc21hbGwgcmVxdWVzdCB3aGVuIGEgZGlhbG9nIG9wZW5zIGlzIG5vdCB3b3J0aCB0aGF0IHJpc2suXG4gIHByaXZhdGUgX2xvYWRTcWwoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVwb3J0RGF0YS5jb21wb25lbnRTcWwodGhpcy5yZXBvcnQuaWQsIHRoaXMuY29tcG9uZW50LmlkKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChwcmV2aWV3OiBSZXBvcnRDb21wb25lbnRTcWwpID0+IHtcbiAgICAgICAgICB0aGlzLnNxbC5zZXQocHJldmlldz8uc3FsID8/IG51bGwpO1xuICAgICAgICAgIHRoaXMuc3FsQmFzZWxpbmUuc2V0KCEhcHJldmlldz8uYmFzZWxpbmUpO1xuICAgICAgICAgIHRoaXMuc3FsVGltZXpvbmUuc2V0KHByZXZpZXc/LnRpbWV6b25lIHx8ICdVVEMnKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChwcmV2aWV3Py5lcnJvciA/PyBudWxsKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMuc3FsLnNldChudWxsKTtcbiAgICAgICAgICB0aGlzLnNxbEVycm9yLnNldChlcnJvcj8uZXJyb3I/Lm1lc3NhZ2UgPz8gJ0NvdWxkIG5vdCByZWFkIHRoZSBjb21wb25lbnQgU1FMJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xvYWRDb2x1bW5zKCk6IHZvaWQge1xuICAgIHRoaXMuX3JlcG9ydERhdGEuY29tcG9uZW50Q29sdW1ucyh0aGlzLnJlcG9ydC5pZCwgdGhpcy5jb21wb25lbnQuaWQpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKGNvbHVtbnM6IFJlcG9ydEZpbHRlcmFibGVDb2x1bW5bXSkgPT4ge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlcmFibGVDb2x1bW5zID0gY29sdW1ucyA/PyBbXTtcbiAgICAgICAgICB0aGlzLl9yZWJ1aWxkUm93cygpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5jb2x1bW5zRXJyb3Iuc2V0KGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyAnQ291bGQgbm90IHJlYWQgdGhlIGNvbXBvbmVudCBjb2x1bW5zJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2h1bWFuaXplKGNvbHVtbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29sdW1uXG4gICAgICAucmVwbGFjZSgvW19cXC1dKy9nLCAnICcpXG4gICAgICAucmVwbGFjZSgvXFxzKy9nLCAnICcpXG4gICAgICAudHJpbSgpXG4gICAgICAucmVwbGFjZSgvXFxiXFx3L2csIChjaGFyYWN0ZXIpID0+IGNoYXJhY3Rlci50b1VwcGVyQ2FzZSgpKTtcbiAgfVxufVxuIiwiPGZvcm1cbiAgICBmc0Zvcm1cbiAgICBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8aDEgbWF0LWRpYWxvZy10aXRsZT5cbiAgICAgIHt7IGNvbXBvbmVudC50aXRsZSB8fCAoaXNWYWx1ZSgpID8gJ1ZhbHVlJyA6ICdDb21wb25lbnQnKSB9fVxuICAgIDwvaDE+XG4gICAgPG1hdC1kaWFsb2ctY29udGVudD5cbiAgICAgIDxtYXQtdGFiLWdyb3VwIFsoc2VsZWN0ZWQpXT1cInNlbGVjdGVkVGFiXCI+XG4gICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAgICAgICAgICAgIG5hbWU9XCJzZXR0aW5nc1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1jb2x1bW4gdGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICB7eyBpc1ZhbHVlKCkgPyAnTmFtZScgOiAnVGl0bGUnIH19XG4gICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwidGl0bGVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJ0aXRsZVwiXG4gICAgICAgICAgICAgICAgW2ZzRm9ybVJlcXVpcmVkXT1cImlzVmFsdWUoKVwiPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwhLS0gQSBmb3JtdWxhIHZhbHVlIGlzIHJlYWQtb25seSBiZXlvbmQgaXRzIG5hbWU6IHdoYXQgaXQgd29ya3NcbiAgICAgICAgICAgICAgICAgb3V0IGlzIHRoZSBBSSdzIHRvIGNoYW5nZS4gQSBmb3JtdWxhIHRoaXMgdmlld2VyIGNhbm5vdFxuICAgICAgICAgICAgICAgICByZWFkIGhhcyBubyBsaW5lLCBhbmQgbm8gcm93LiAtLT5cbiAgICAgICAgICAgIEBpZiAoZm9ybXVsYUxpbmUoKSkge1xuICAgICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgICAgPGZzLWxhYmVsPlxuICAgICAgICAgICAgICAgICAgRm9ybXVsYVxuICAgICAgICAgICAgICAgIDwvZnMtbGFiZWw+XG4gICAgICAgICAgICAgICAge3sgZm9ybXVsYUxpbmUoKSB9fVxuICAgICAgICAgICAgICAgIDxmcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICAgICAgV29ya2VkIG91dCBvbiB0aGUgc2VydmVyOyBpdCBmb2xsb3dzIHRoZSBmaWx0ZXJzIG9mIHRoZSB2YWx1ZXMgaXQgcmVhZHMuXG4gICAgICAgICAgICAgICAgPC9mcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgPCEtLSBBIHZhbHVlIHNpdHMgaW5zaWRlIGEgdGV4dCBibG9jaydzIHdvcmRzOiBubyBib3gsIG5vIHBhZGRpbmcuIC0tPlxuICAgICAgICAgICAgQGlmICghaXNWYWx1ZSgpKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWJoZWFkaW5nLTJcIj5cbiAgICAgICAgICAgICAgICBQYWRkaW5nXG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ2VvbWV0cnktcm93XCI+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgVG9wXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgW3NjYWxlXT1cIjNcIlxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhZGRpbmdUb3BcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ1RvcFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBSaWdodFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nUmlnaHRcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFkZGluZ1JpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybU1pbl09XCIwXCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IG1hdFRleHRTdWZmaXg+XG4gICAgICAgICAgICAgICAgICAgIGluXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIEJvdHRvbVxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nQm90dG9tXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhZGRpbmdCb3R0b21cIlxuICAgICAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjBcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICAgICAgaW5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgTGVmdFxuICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgZnNNYXNrTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJwYWRkaW5nTGVmdFwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWRkaW5nTGVmdFwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwiMFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICBpblxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA8IS0tIEEgZGVyaXZlZCBLUEkncyBjYXJkOiB3aGF0IGEgcmlzZSBtZWFucywgYSB0YXJnZXQgYW5kIGFcbiAgICAgICAgICAgICAgICAgc3BhcmtsaW5lLiBUaGUgc2VydmVyIGNvbXB1dGVzIHRoZSBwcm9ncmVzcyBhbmQgdGhlIHBvaW50cy4gLS0+XG4gICAgICAgICAgICBAaWYgKGtwaUNhcmQoKSkge1xuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViaGVhZGluZy0yXCI+XG4gICAgICAgICAgICAgICAgQ2FyZFxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBJbmNyZWFzZSBpc1xuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImluY3JlYXNlSXMoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImluY3JlYXNlSXMuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwiaW5jcmVhc2VJc1wiPlxuICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIGtwaVBvbGFyaXR5T3B0aW9uczsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJvcHRpb24udmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgIENvbG9ycyB0aGUgY2hhbmdlIGFuZCBkZWNpZGVzIHdoZW4gdGhlIHRhcmdldCBpcyBtZXQuXG4gICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICBUYXJnZXRcbiAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICBmc01hc2tOdW1iZXJcbiAgICAgICAgICAgICAgICAgIFtzY2FsZV09XCI2XCJcbiAgICAgICAgICAgICAgICAgIFtzaWduZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ0YXJnZXRWYWx1ZSgpXCJcbiAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInRhcmdldFZhbHVlLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJ0YXJnZXRWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICBbdmFsaWRhdGVdPVwidmFsaWRhdGVUYXJnZXRcIj5cbiAgICAgICAgICAgICAgICBAaWYgKHRhcmdldFBlcmNlbnQoKSkge1xuICAgICAgICAgICAgICAgICAgPGRpdiBtYXRUZXh0U3VmZml4PlxuICAgICAgICAgICAgICAgICAgICAlXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgVGhlIHZhbHVlIHRvIHJlYWNoLiBMZWF2ZSBlbXB0eSBmb3Igbm8gdGFyZ2V0LlxuICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIEBpZiAoaGFzVGFyZ2V0KCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBUYXJnZXQgbGFiZWxcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInRhcmdldExhYmVsKClcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJ0YXJnZXRMYWJlbC5zZXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ0YXJnZXRMYWJlbFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBTaG93biBiZWZvcmUgdGhlIHRhcmdldCwgc3VjaCBhcyBHb2FsLiBFbXB0eSByZWFkcyBUYXJnZXQuXG4gICAgICAgICAgICAgICAgICA8L21hdC1oaW50PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPGZzLWxhYmVsLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInNwYXJrbGluZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lLnNldCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInNwYXJrbGluZVwiPlxuICAgICAgICAgICAgICAgICAgU3BhcmtsaW5lXG4gICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICAgIEEgc21hbGwgdHJlbmQgbGluZSBvZiB0aGUgdmFsdWUgb3ZlciBpdHMgbGFzdCBwZXJpb2RzLlxuICAgICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgIDwvZnMtbGFiZWwtZmllbGQ+XG4gICAgICAgICAgICAgIEBpZiAoc3BhcmtsaW5lKCkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICBTcGFya2xpbmUgcGVyaW9kXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwic3BhcmtsaW5lR3JhbnVsYXJpdHkoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3BhcmtsaW5lR3JhbnVsYXJpdHkuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJzcGFya2xpbmVHcmFudWxhcml0eVwiPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChvcHRpb24gb2YgZ3JhbnVsYXJpdHlPcHRpb25zOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBvcHRpb24ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgU3BhcmtsaW5lIHBlcmlvZHNcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIGZzTWFza051bWJlclxuICAgICAgICAgICAgICAgICAgICBbc2NhbGVdPVwiMFwiXG4gICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInNwYXJrbGluZVBlcmlvZHMoKVwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNwYXJrbGluZVBlcmlvZHMuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwic3BhcmtsaW5lUGVyaW9kc1wiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1SZXF1aXJlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZzRm9ybUludGVnZXJdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NaW5dPVwic3BhcmtsaW5lTWluUGVyaW9kc1wiXG4gICAgICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwic3BhcmtsaW5lTWF4UGVyaW9kc1wiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgICAgICBIb3cgbWFueSBwZXJpb2RzIHRoZSBsaW5lIGNvdmVycywge3sgc3BhcmtsaW5lTWluUGVyaW9kcyB9fSB0byB7eyBzcGFya2xpbmVNYXhQZXJpb2RzIH19LlxuICAgICAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgPCEtLSBBIGZvcm11bGEgcnVucyBubyBzdGF0ZW1lbnQgYW5kIGZvbGxvd3MgdGhlIGZpbHRlcnMgb2YgdGhlIHZhbHVlc1xuICAgICAgICAgICAgIGl0IHJlYWRzLCBzbyBpdCBoYXMgbmVpdGhlciBhIEZpbHRlcnMgbm9yIGFuIFNRTCB0YWIuIC0tPlxuICAgICAgICBAaWYgKCFpc0Zvcm11bGEoKSkge1xuICAgICAgICAgIDxtYXQtdGFiXG4gICAgICAgICAgICAgIGxhYmVsPVwiRmlsdGVyc1wiXG4gICAgICAgICAgICAgIG5hbWU9XCJmaWx0ZXJzXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgQGlmIChjb2x1bW5zRXJyb3IoKSkge1xuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5IGVycm9yXCI+XG4gICAgICAgICAgICAgICAgICB7eyBjb2x1bW5zRXJyb3IoKSB9fVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9IEBlbHNlIGlmIChyb3dzKCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgPCEtLSBFdmVyeSBmaWx0ZXJhYmxlIGNvbHVtbi4gVG9nZ2xlIHdoZXJlIGl0cyBjb250cm9sIHNob3dzOiBpblxuICAgICAgICAgICAgICAgICAgICAgdGhlIHJlcG9ydCBiYXIsIG9uIHRoaXMgY29tcG9uZW50LCBib3RoLCBvciBuZWl0aGVyLiBUaGVcbiAgICAgICAgICAgICAgICAgICAgIGludGVyZmFjZSAoZGF0ZSByYW5nZSB2cyB2YWx1ZSBwaWNrZXIpIGZvbGxvd3MgdGhlIGRhdGEuXG4gICAgICAgICAgICAgICAgICAgICBBIHZhbHVlIHNpdHMgaW5zaWRlIHRleHQgYW5kIGhhcyBubyBjb21wb25lbnQgdG8gc2hvdyBhXG4gICAgICAgICAgICAgICAgICAgICBjb250cm9sIG9uLCBzbyBpdCBnZXRzIHRoZSByZXBvcnQgYmFyIGNvbHVtbiBvbmx5LiAtLT5cbiAgICAgICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJmaWx0ZXItdGFibGVcIj5cbiAgICAgICAgICAgICAgICAgIDx0aGVhZD5cbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtbmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgRmlsdGVyXG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJmaWx0ZXItY29sLXR5cGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIFR5cGVcbiAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBSZXBvcnQgYmFyXG4gICAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKCFpc1ZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImZpbHRlci1jb2wtdG9nZ2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICAgICAgICAgIEBmb3IgKHJvdyBvZiByb3dzKCk7IHRyYWNrIHJvdy5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLW5hbWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAge3sgcm93LmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwiZmlsdGVyLWNvbC10eXBlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHR5cGVMYWJlbChyb3cudHlwZSkgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLXRvZ2dsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cInJvdy5yZXBvcnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldEV4cG9zdXJlKHJvdywgJ3JlcG9ydCcsICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7IHN0YW5kYWxvbmU6IHRydWUgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlNob3cgaW4gdGhlIHJlcG9ydCBiYXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoIWlzVmFsdWUoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJmaWx0ZXItY29sLXRvZ2dsZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2xpZGUtdG9nZ2xlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJyb3cuY29tcG9uZW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldEV4cG9zdXJlKHJvdywgJ2NvbXBvbmVudCcsICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cInsgc3RhbmRhbG9uZTogdHJ1ZSB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJTaG93IG9uIHRoaXMgY29tcG9uZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICAgICAgPC90YWJsZT5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50IGhhcyBubyBmaWx0ZXJhYmxlIGNvbHVtbnMgeWV0IOKAlCBnaXZlIGl0IHNvbWUgU1FMIGZpcnN0LlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgICAgbGFiZWw9XCJTUUxcIlxuICAgICAgICAgICAgICBuYW1lPVwic3FsXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgICAgQGlmIChzcWxFcnJvcigpKSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHkgZXJyb3JcIj5cbiAgICAgICAgICAgICAgICAgIHt7IHNxbEVycm9yKCkgfX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgfSBAZWxzZSBpZiAoc3FsKCkpIHtcbiAgICAgICAgICAgICAgICBAaWYgKHNxbEJhc2VsaW5lKCkpIHtcbiAgICAgICAgICAgICAgICAgIDwhLS0gQSBkZXJpdmVkIGNvbXBvbmVudCdzIHN0YXRlbWVudCBpcyBjb21waWxlZCBmcm9tIGl0c1xuICAgICAgICAgICAgICAgICAgICAgICBkb2N1bWVudCB3aXRoIG5vIHZpZXdlciBzdGF0ZSwgc28gaXQgaXMgbm90IGJ5dGUtZm9yLWJ5dGVcbiAgICAgICAgICAgICAgICAgICAgICAgd2hhdCBwcm9kdWNlZCB0aGUgbnVtYmVycyBvbiBzY3JlZW4uIFNhaWQgaGVyZSByYXRoZXIgdGhhblxuICAgICAgICAgICAgICAgICAgICAgICBsZWZ0IGZvciB0aGUgcmVhZGVyIHRvIGRpc2NvdmVyLiAtLT5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWVtcHR5XCI+XG4gICAgICAgICAgICAgICAgICAgIENvbXBpbGVkIGZyb20gdGhpcyBjb21wb25lbnQncyBxdWVyeSDigJQgbm8gZmlsdGVycyBhcHBsaWVkLCB0aW1lcyBpbiB7eyBzcWxUaW1lem9uZSgpIH19LlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+e3sgc3FsKCkgfX08L3ByZT5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlcnMtZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgIFRoaXMgY29tcG9uZW50IGhhcyBubyBTUUwgeWV0LlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L21hdC10YWI+XG4gICAgICAgIH1cbiAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgIGxhYmVsPVwiQ29uZmlnXCJcbiAgICAgICAgICAgIG5hbWU9XCJjb25maWdcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGFiLWJvZHlcIj5cbiAgICAgICAgICAgIDxwcmUgY2xhc3M9XCJjb2RlLWJsb2NrXCI+XG4gICAgICAgICAgICAgIHt7IGNvbmZpZ0pzb24gfX1cbiAgICAgICAgICAgIDwvcHJlPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC10YWI+XG4gICAgICA8L21hdC10YWItZ3JvdXA+XG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgIDwhLS0gU2F2ZSB8IERlbGV0ZSB8IENhbmNlbCwgdGhlIHN0YW5kYXJkIG9yZGVyLiBmcy1mb3JtLWRpYWxvZy1hY3Rpb25zXG4gICAgICAgICAgIHJlbmRlcnMgaXRzIG93biBTYXZlL0RvbmUgQkVGT1JFIHRoZSBwcm9qZWN0ZWQgY29udGVudCwgd2hpY2ggd291bGRcbiAgICAgICAgICAgcHV0IERlbGV0ZSBhZnRlciBDYW5jZWwsIHNvIGBbc2F2ZV09XCJmYWxzZVwiYCBmb290cyB0aGUgcm93IGhlcmUgYW5kXG4gICAgICAgICAgIGFsbCB0aHJlZSBidXR0b25zIGFyZSBwcm9qZWN0ZWQgaW4gb3JkZXIuIFNhdmUgc3VibWl0cyB0aGUgU2V0dGluZ3NcbiAgICAgICAgICAgdGFiOyB0aGUgb3RoZXIgdGFicyBwZXJzaXN0IGFzIHlvdSB0b3VjaCB0aGVtLCBzbyB0aGV5IGdldCBEb25lLiAtLT5cbiAgICAgIDxmcy1mb3JtLWRpYWxvZy1hY3Rpb25zIFtzYXZlXT1cImZhbHNlXCI+XG4gICAgICAgIEBpZiAoc2VsZWN0ZWRUYWIgPT09ICdzZXR0aW5ncycpIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiPlxuICAgICAgICAgICAgU2F2ZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICAgIERvbmVcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKClcIj5cbiAgICAgICAgICBEZWxldGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjYW5jZWwtYnV0dG9uXCJcbiAgICAgICAgICAgIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIj5cbiAgICAgICAgICBDYW5jZWxcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2ZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPiJdfQ==
|