@firestitch/report 18.9.0 → 18.10.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/anchor-at-point.d.ts +14 -0
- package/app/reports/canvas-landing-page.d.ts +2 -0
- package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
- package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
- package/app/reports/components/report-component/report-component.component.d.ts +35 -1
- package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
- package/app/reports/data/report.data.d.ts +17 -2
- package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
- package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
- package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
- package/app/reports/drill-crumbs.d.ts +12 -0
- package/app/reports/export/report-export-collector.service.d.ts +13 -4
- package/app/reports/export/report-filter-lines.d.ts +18 -0
- package/app/reports/filter-settings-rules.d.ts +33 -0
- package/app/reports/format.d.ts +0 -1
- package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
- package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
- package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
- package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
- package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
- package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
- package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
- package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
- package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
- package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
- package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
- package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
- package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
- package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
- package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
- package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
- package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
- package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
- package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
- package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
- package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
- package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
- package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
- package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
- package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
- package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
- package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
- package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
- package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
- package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
- package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
- package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
- package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
- package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
- package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
- package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
- package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
- package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
- package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
- package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
- package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
- package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
- package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
- package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
- package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
- package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
- package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
- package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
- package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
- package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
- package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
- package/app/reports/interfaces/report-view.interface.d.ts +7 -0
- package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
- package/app/reports/interfaces/report-views.interface.d.ts +7 -0
- package/app/reports/interfaces/report.interface.d.ts +27 -3
- package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
- package/app/reports/mark-click.d.ts +20 -0
- package/app/reports/option-builder.d.ts +12 -1
- package/app/reports/report-chat-viewer-state.d.ts +8 -0
- package/app/reports/report-date-presets.d.ts +2 -0
- package/app/reports/report-filter-items.d.ts +27 -22
- package/app/reports/report-tile.d.ts +2 -0
- package/app/reports/report-url-state.d.ts +27 -10
- package/app/reports/report-view-config.d.ts +36 -0
- package/app/reports/report-view-menu.d.ts +15 -0
- package/app/reports/report-viewer-features.d.ts +5 -0
- package/app/reports/services/report-filter-options.service.d.ts +26 -0
- package/app/reports/services/report-filter-state.service.d.ts +64 -1
- package/app/reports/services/report-view.service.d.ts +51 -0
- package/app/reports/tile-data-state.d.ts +7 -0
- package/app/reports/tile-loads.d.ts +4 -0
- package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
- package/app/reports/views/report/report.component.d.ts +6 -0
- package/esm2022/app/reports/anchor-at-point.mjs +49 -0
- package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
- package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
- package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
- package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +47 -32
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +257 -61
- package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
- package/esm2022/app/reports/data/report.data.mjs +87 -10
- package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
- package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
- package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
- package/esm2022/app/reports/drill-crumbs.mjs +73 -0
- package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
- package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
- package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
- package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
- package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
- package/esm2022/app/reports/format.mjs +2 -22
- package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
- package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
- package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
- package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
- package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
- package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
- package/esm2022/app/reports/mark-click.mjs +193 -0
- package/esm2022/app/reports/option-builder.mjs +159 -15
- package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
- package/esm2022/app/reports/report-date-presets.mjs +18 -0
- package/esm2022/app/reports/report-filter-items.mjs +343 -72
- package/esm2022/app/reports/report-tile.mjs +12 -0
- package/esm2022/app/reports/report-url-state.mjs +596 -108
- package/esm2022/app/reports/report-view-config.mjs +697 -0
- package/esm2022/app/reports/report-view-menu.mjs +119 -0
- package/esm2022/app/reports/report-viewer-features.mjs +42 -0
- package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
- package/esm2022/app/reports/services/report-filter-state.service.mjs +697 -62
- package/esm2022/app/reports/services/report-view.service.mjs +358 -0
- package/esm2022/app/reports/tile-data-state.mjs +127 -0
- package/esm2022/app/reports/tile-loads.mjs +38 -0
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +177 -46
- package/esm2022/app/reports/views/report/report.component.mjs +103 -23
- package/esm2022/public_api.mjs +23 -1
- package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
- package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
- package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +9063 -4272
- package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +22 -0
- package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
|
@@ -1,22 +1,31 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, EventEmitter, HostBinding, Input, NgZone, Output, ViewChild, inject, input, output, signal, viewChild, } from '@angular/core';
|
|
1
|
+
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, EventEmitter, HostBinding, Input, NgZone, Output, ViewChild, computed, inject, input, output, signal, viewChild, } from '@angular/core';
|
|
2
2
|
import { MatIconButton } from '@angular/material/button';
|
|
3
3
|
import { MatDialog } from '@angular/material/dialog';
|
|
4
4
|
import { MatIcon } from '@angular/material/icon';
|
|
5
|
+
import { MatProgressBar } from '@angular/material/progress-bar';
|
|
5
6
|
import { MatTooltip } from '@angular/material/tooltip';
|
|
6
7
|
import { FsFilterModule } from '@firestitch/filter';
|
|
7
|
-
import { FsMenuModule } from '@firestitch/menu';
|
|
8
|
+
import { FsMenuComponent, FsMenuModule } from '@firestitch/menu';
|
|
8
9
|
import { FsMessage } from '@firestitch/message';
|
|
9
10
|
import { FsProcess } from '@firestitch/process';
|
|
10
11
|
import { FsPrompt } from '@firestitch/prompt';
|
|
11
|
-
import { Subject,
|
|
12
|
+
import { Subject, filter as rxFilter, map, switchMap, tap } from 'rxjs';
|
|
12
13
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
14
|
+
import { openAtPoint } from '../../anchor-at-point';
|
|
13
15
|
import { ReportData } from '../../data/report.data';
|
|
14
16
|
import { ListColumnsComponent } from '../../dialogs/list-columns/list-columns.component';
|
|
17
|
+
import { DRILL_CRUMB_SEPARATOR, DRILL_RESET_MESSAGE, adoptedDrillPath, drillCrumbLabels, drillOutsideMessage, drillResetNoted, } from '../../drill-crumbs';
|
|
15
18
|
import { kpiCardSettings, sameKpiCardSettings } from '../../kpi-card';
|
|
16
19
|
import { componentPaddingCss } from '../../layout';
|
|
17
20
|
import { listHideableColumns } from '../../list-config';
|
|
21
|
+
import { MARK_ACTION_LABELS, decideMarkClick, drillDownPath, markActions, tileMarkActions, } from '../../mark-click';
|
|
18
22
|
import { LIST_SEARCH_ITEM, filterItemForGroup, groupValuesFromQuery, listSearchItem, } from '../../report-filter-items';
|
|
23
|
+
import { groupValueSignature } from '../../report-filter-items';
|
|
24
|
+
import { offeredViewerFeatures } from '../../report-viewer-features';
|
|
25
|
+
import { ReportFilterOptionsService } from '../../services/report-filter-options.service';
|
|
19
26
|
import { movedGroupValues, ReportFilterStateService } from '../../services/report-filter-state.service';
|
|
27
|
+
import { isTimeSeriesChart } from '../../tile-data-state';
|
|
28
|
+
import { tileLoads } from '../../tile-loads';
|
|
20
29
|
import { ComponentChartComponent } from '../component-chart/component-chart.component';
|
|
21
30
|
import { ComponentKpiComponent } from '../component-kpi/component-kpi.component';
|
|
22
31
|
import { ComponentListComponent } from '../component-list/component-list.component';
|
|
@@ -97,12 +106,53 @@ export class ReportComponentComponent {
|
|
|
97
106
|
// repaints the header and body.
|
|
98
107
|
filterConfig = signal(null);
|
|
99
108
|
data = signal(null);
|
|
109
|
+
// The shimmer: only while the tile has no data to show yet. A refetch keeps
|
|
110
|
+
// the data on screen and sets `refreshing`, a thin bar over the body.
|
|
100
111
|
loading = signal(false);
|
|
112
|
+
refreshing = signal(false);
|
|
101
113
|
error = signal(null);
|
|
114
|
+
// Which of a chart's legend entries are on, by series name. Held here and
|
|
115
|
+
// handed to each option the chart builds: ngx-echarts sets an option with
|
|
116
|
+
// notMerge, which would otherwise turn every entry back on at each refetch.
|
|
117
|
+
legendSelected = signal({});
|
|
118
|
+
// A list is drawn again when a reset moves its sort: FsList reads its sort
|
|
119
|
+
// only when it is created. Every other reset reloads it in place.
|
|
120
|
+
listResetKey = computed(() => this._filterState.listSortResets().get(this.component?.id) ?? 0);
|
|
121
|
+
// What a click on this tile's marks may do on its last answer: the chart
|
|
122
|
+
// shows a hand and a tooltip hint for them. (While the layout is edited a
|
|
123
|
+
// veil covers the body, so no mark is hovered or clicked.)
|
|
124
|
+
tileActions = computed(() => tileMarkActions({
|
|
125
|
+
data: this.data(),
|
|
126
|
+
features: this._offeredFeatures(),
|
|
127
|
+
}));
|
|
128
|
+
// The actions the mark menu lists for the click it was opened on.
|
|
129
|
+
markMenuActions = signal([]);
|
|
130
|
+
markActionLabels = MARK_ACTION_LABELS;
|
|
131
|
+
// The breadcrumb after the title while the chart is drilled ('2026', 'Q3'),
|
|
132
|
+
// one label per step of its path, in the report's locale. Empty at the top
|
|
133
|
+
// and while the viewer is not offered drill: a path an older server never
|
|
134
|
+
// applies is kept for the link, but not shown.
|
|
135
|
+
drillCrumbs = computed(() => (this._offeredFeatures().includes('drill')
|
|
136
|
+
? drillCrumbLabels(this._filterState.drill(this.component?.id), this._filterState.formatContext())
|
|
137
|
+
: []));
|
|
138
|
+
drillSeparator = DRILL_CRUMB_SEPARATOR;
|
|
139
|
+
// What an empty tile says: the drilled period it reads no day of, else
|
|
140
|
+
// 'No data'.
|
|
141
|
+
emptyMessage = computed(() => drillOutsideMessage(this.data()?.drill, this._filterState.formatContext()) ?? 'No data');
|
|
142
|
+
markMenu;
|
|
143
|
+
markAnchor;
|
|
102
144
|
_text = viewChild(ComponentTextComponent);
|
|
103
145
|
_refresh$ = new Subject();
|
|
146
|
+
// The state version the header was last built for (filterKey).
|
|
147
|
+
_headerVersion = signal(0);
|
|
148
|
+
// The header groups' values as the header last showed them: as it was
|
|
149
|
+
// built, then as its own bar reported each change. filterKey carries their
|
|
150
|
+
// signature as built.
|
|
151
|
+
_shown = new Map();
|
|
152
|
+
_headerValues = signal('');
|
|
104
153
|
_reportData = inject(ReportData);
|
|
105
154
|
_filterState = inject(ReportFilterStateService);
|
|
155
|
+
_filterOptions = inject(ReportFilterOptionsService);
|
|
106
156
|
_process = inject(FsProcess);
|
|
107
157
|
_message = inject(FsMessage);
|
|
108
158
|
_prompt = inject(FsPrompt);
|
|
@@ -111,15 +161,30 @@ export class ReportComponentComponent {
|
|
|
111
161
|
_destroyRef = inject(DestroyRef);
|
|
112
162
|
_zone = inject(NgZone);
|
|
113
163
|
_host = inject(ElementRef);
|
|
164
|
+
// The features a mark action needs: served by the report's server and
|
|
165
|
+
// implemented by this viewer.
|
|
166
|
+
_offeredFeatures = computed(() => offeredViewerFeatures(this._filterState.viewerFeatures()));
|
|
167
|
+
// The mark a first tap previewed (decideMarkClick), and the click the mark
|
|
168
|
+
// menu is open for.
|
|
169
|
+
_touchedMark = null;
|
|
170
|
+
_menuClick = null;
|
|
171
|
+
// The group-by moved since the last answer: a path the server then drops
|
|
172
|
+
// because it no longer starts at the chart's top is not news to the viewer.
|
|
173
|
+
_grainMoved = false;
|
|
114
174
|
ngOnInit() {
|
|
115
175
|
this._buildFilterConfig();
|
|
176
|
+
if (!this.isText) {
|
|
177
|
+
this._rebuildHeaderOnNewState();
|
|
178
|
+
}
|
|
116
179
|
// Lists fetch through FsList; text has nothing to fetch, and a value is
|
|
117
180
|
// never drawn (it reads inside text).
|
|
118
181
|
if (this.component.type !== 'list' && !this.isText && isDrawn(this.component)) {
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
182
|
+
// One load stream (tileLoads): the first load at once, then one per
|
|
183
|
+
// settled sweep of changes, each cancelling the one in flight, and an
|
|
184
|
+
// answer sent before a view was applied is dropped.
|
|
185
|
+
tileLoads(this._refresh$, () => this._load(), () => this._filterState.stateVersion())
|
|
186
|
+
.pipe(tap((result) => this._loaded(result)), takeUntilDestroyed(this._destroyRef))
|
|
187
|
+
.subscribe();
|
|
123
188
|
this._filterState.changesFor(this.component)
|
|
124
189
|
.pipe(takeUntilDestroyed(this._destroyRef))
|
|
125
190
|
.subscribe(() => this._refresh$.next());
|
|
@@ -128,9 +193,15 @@ export class ReportComponentComponent {
|
|
|
128
193
|
if (this._isTimeSeries) {
|
|
129
194
|
this._filterState.frequencyChanges()
|
|
130
195
|
.pipe(takeUntilDestroyed(this._destroyRef))
|
|
131
|
-
.subscribe(() =>
|
|
196
|
+
.subscribe(() => {
|
|
197
|
+
this._grainMoved = true;
|
|
198
|
+
this._refresh$.next();
|
|
199
|
+
});
|
|
132
200
|
}
|
|
133
|
-
this.
|
|
201
|
+
// A drill moves this chart alone.
|
|
202
|
+
this._filterState.drillChanges(this.component.id)
|
|
203
|
+
.pipe(takeUntilDestroyed(this._destroyRef))
|
|
204
|
+
.subscribe(() => this._refresh$.next());
|
|
134
205
|
}
|
|
135
206
|
}
|
|
136
207
|
// The report reloads (e.g. after the settings dialog adds/moves a filter)
|
|
@@ -158,11 +229,18 @@ export class ReportComponentComponent {
|
|
|
158
229
|
// it renders: the set of component-level filter groups AND the title, which
|
|
159
230
|
// lives in fs-filter's heading template. fs-filter is OnPush and the heading is
|
|
160
231
|
// rendered inside ITS view, so marking this component does not repaint the
|
|
161
|
-
// title — recreating the block does.
|
|
232
|
+
// title — recreating the block does. The key also carries the state version
|
|
233
|
+
// the header was built for, so an applied view, which replaces every value
|
|
234
|
+
// at once, recreates it with the new values. And it carries the values the
|
|
235
|
+
// header was built with: a group shown here and in the report bar (level
|
|
236
|
+
// 'both') that the report bar changes is built again here, so the header
|
|
237
|
+
// never shows 'West' while the data leaves West out.
|
|
162
238
|
get filterKey() {
|
|
163
239
|
return [
|
|
240
|
+
this._headerVersion(),
|
|
164
241
|
this.component.title,
|
|
165
242
|
...this.componentFilterGroups.map((group) => `${group.id}:${group.level}`),
|
|
243
|
+
this._headerValues(),
|
|
166
244
|
].join('|');
|
|
167
245
|
}
|
|
168
246
|
get isText() {
|
|
@@ -288,37 +366,63 @@ export class ReportComponentComponent {
|
|
|
288
366
|
this._refresh$.next();
|
|
289
367
|
}
|
|
290
368
|
}
|
|
291
|
-
// The CSV is what the screen shows, so it carries the
|
|
292
|
-
//
|
|
293
|
-
// viewer's header sort, search and hidden columns
|
|
294
|
-
//
|
|
295
|
-
//
|
|
369
|
+
// The CSV is what the screen shows, so it carries the tile's interaction
|
|
370
|
+
// state (tileDataState): the group-by grain for a time-series chart, a
|
|
371
|
+
// chart's drill path, the viewer's header sort, search and hidden columns
|
|
372
|
+
// for a list (a searched list exports only the rows the search leaves, and
|
|
373
|
+
// the hidden columns stay out of the file), and the groups that match
|
|
374
|
+
// 'any'. A note the server returns (the file was cut) is shown before the
|
|
375
|
+
// download starts, so a short file never passes for the whole result.
|
|
296
376
|
exportCsv() {
|
|
297
377
|
const filters = this._filterState.resolveForComponent(this.component);
|
|
298
|
-
const state =
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
378
|
+
const state = this._filterState.tileState(this.component);
|
|
379
|
+
this._process.download(`Exporting ${this.component.title ?? 'component'}`, this._reportData.exportComponent(this.reportId, this.component.id, filters, state)
|
|
380
|
+
.pipe(tap(({ notes }) => notes?.length && this._message.warning(notes.join(' '))), map(({ url }) => url)));
|
|
381
|
+
}
|
|
382
|
+
// The one click handler (B10.2): every click on a mark of this tile, a
|
|
383
|
+
// chart's or a KPI's value, comes here, so its actions never compete. The
|
|
384
|
+
// rule (decideMarkClick) does nothing without an action, lets a first tap
|
|
385
|
+
// show the tooltip, runs a lone action at once, and opens the mark menu at
|
|
386
|
+
// the click for two or more. Not while the layout is edited.
|
|
387
|
+
onMarkClick(click) {
|
|
388
|
+
if (this.editMode) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const actions = markActions(click, { data: this.data(), features: this._offeredFeatures() });
|
|
392
|
+
const decision = decideMarkClick(click, actions, this._touchedMark);
|
|
393
|
+
this._touchedMark = decision.touched;
|
|
394
|
+
if (decision.outcome === 'run') {
|
|
395
|
+
this._runMarkAction(decision.actions[0], click);
|
|
304
396
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (sort) {
|
|
308
|
-
state.sort = sort;
|
|
397
|
+
else if (decision.outcome === 'menu') {
|
|
398
|
+
this._openMarkMenu(decision.actions, click);
|
|
309
399
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
400
|
+
}
|
|
401
|
+
// A click or a tap on the chart that hit no mark: a tap held for its
|
|
402
|
+
// second tap is let go, so tapping that mark again shows its tooltip first.
|
|
403
|
+
onMarkMiss() {
|
|
404
|
+
this._touchedMark = null;
|
|
405
|
+
}
|
|
406
|
+
// A row of the mark menu: runs its action for the click the menu opened on.
|
|
407
|
+
runMarkAction(action) {
|
|
408
|
+
const click = this._menuClick;
|
|
409
|
+
this._menuClick = null;
|
|
410
|
+
if (click) {
|
|
411
|
+
this._runMarkAction(action, click);
|
|
314
412
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
413
|
+
}
|
|
414
|
+
// Back up the drill path to its first `depth` steps: 0 is the chart's top
|
|
415
|
+
// (the title's crumb and Back to top), and a crumb goes back to the period
|
|
416
|
+
// it names. The chart reads again (drillChanges).
|
|
417
|
+
drillTo(depth) {
|
|
418
|
+
if (this.editMode) {
|
|
419
|
+
return;
|
|
319
420
|
}
|
|
320
|
-
this.
|
|
321
|
-
|
|
421
|
+
this._filterState.setDrill(this.component.id, this._filterState.drill(this.component.id).slice(0, depth));
|
|
422
|
+
}
|
|
423
|
+
// One level up: the period the chart is drilled into is left.
|
|
424
|
+
drillUp() {
|
|
425
|
+
this.drillTo(Math.max(0, this._filterState.drill(this.component.id).length - 1));
|
|
322
426
|
}
|
|
323
427
|
// Any interaction inside a component must never start a canvas pan (the
|
|
324
428
|
// zoom-pan host listens for mousedown/touchstart at the container level).
|
|
@@ -417,6 +521,11 @@ export class ReportComponentComponent {
|
|
|
417
521
|
const groups = this.componentFilterGroups;
|
|
418
522
|
const listSearch = this._filterState.listSearchable(this.component);
|
|
419
523
|
const reported = new Map(groups.map((group) => [group.id, this._filterState.value(group.id) ?? null]));
|
|
524
|
+
const features = this._filterState.viewerFeatures();
|
|
525
|
+
const report = this._filterState.report();
|
|
526
|
+
this._shown = reported;
|
|
527
|
+
this._headerValues.set([...reported.values()].map(groupValueSignature).join('|'));
|
|
528
|
+
this._headerVersion.set(this._filterState.stateVersion());
|
|
420
529
|
this.filterConfig.set({
|
|
421
530
|
// fs-filter never touches the URL or persists filter state. The values
|
|
422
531
|
// are owned by ReportFilterStateService, which feeds the report view's
|
|
@@ -424,14 +533,14 @@ export class ReportComponentComponent {
|
|
|
424
533
|
queryParam: false,
|
|
425
534
|
persist: false,
|
|
426
535
|
items: [
|
|
427
|
-
...groups.map((group) => filterItemForGroup(group, this.
|
|
536
|
+
...groups.map((group) => filterItemForGroup(group, this._filterOptions, report, this._filterState.value(group.id), features)),
|
|
428
537
|
...(listSearch ? [listSearchItem(this._filterState.listSearch(this.component.id))] : []),
|
|
429
538
|
],
|
|
430
539
|
// Typing in the search box must not refetch through the groups, nor set
|
|
431
540
|
// a stale group value back, and a group change must not refetch through
|
|
432
541
|
// the search.
|
|
433
542
|
change: (query) => {
|
|
434
|
-
const values = groupValuesFromQuery(query ?? {}, this.componentFilterGroups);
|
|
543
|
+
const values = groupValuesFromQuery(query ?? {}, this.componentFilterGroups, report);
|
|
435
544
|
for (const { groupId, value } of movedGroupValues(reported, values)) {
|
|
436
545
|
this._filterState.setValue(groupId, value);
|
|
437
546
|
}
|
|
@@ -439,8 +548,42 @@ export class ReportComponentComponent {
|
|
|
439
548
|
this._filterState.setListSearch(this.component.id, String(query?.[LIST_SEARCH_ITEM] ?? ''));
|
|
440
549
|
}
|
|
441
550
|
},
|
|
551
|
+
// 'Clear filters' puts this header's own groups back on the open view,
|
|
552
|
+
// else on their authored defaults. fs-filter reports its own cleared
|
|
553
|
+
// items (change) just before this, so the reset wins. A server without
|
|
554
|
+
// saved views keeps the clear it always had: the header's items only.
|
|
555
|
+
clear: features.includes('views')
|
|
556
|
+
? () => this._filterState.resetGroupsToBase(groups.map((group) => group.id))
|
|
557
|
+
: undefined,
|
|
558
|
+
// The chip shows exactly while one of those groups differs from what
|
|
559
|
+
// that clear puts back (groupsDifferFromBase). fs-filter's own rule
|
|
560
|
+
// compares the items with the values this header was built with, so it
|
|
561
|
+
// would miss a value the open view holds and offer a clear that changes
|
|
562
|
+
// nothing. A server without saved views keeps fs-filter's own rule.
|
|
563
|
+
clearVisible: features.includes('views')
|
|
564
|
+
? () => this._filterState.groupsDifferFromBase(groups.map((group) => group.id))
|
|
565
|
+
: undefined,
|
|
442
566
|
});
|
|
443
567
|
}
|
|
568
|
+
// apply() and resetToBase() move the state version and announce a full
|
|
569
|
+
// change (null). The header is built again for the new version, and
|
|
570
|
+
// filterKey, which carries it, recreates the block: fs-filter reads its
|
|
571
|
+
// config once. Any other full change (a reload, the match) leaves it be.
|
|
572
|
+
// A change to one group the header shows with another value (another bar
|
|
573
|
+
// set it) builds it again too.
|
|
574
|
+
_rebuildHeaderOnNewState() {
|
|
575
|
+
this._filterState.changesFor(this.component)
|
|
576
|
+
.pipe(rxFilter((groupId) => (groupId === null
|
|
577
|
+
? this._filterState.stateVersion() !== this._headerVersion()
|
|
578
|
+
: this._showsOtherValue(groupId))), tap(() => this._buildFilterConfig()), takeUntilDestroyed(this._destroyRef))
|
|
579
|
+
.subscribe();
|
|
580
|
+
}
|
|
581
|
+
// Whether the header shows a group with a value other than the one stored
|
|
582
|
+
// for it. A change the header's own bar made is what it shows already.
|
|
583
|
+
_showsOtherValue(groupId) {
|
|
584
|
+
return this._shown.has(groupId)
|
|
585
|
+
&& groupValueSignature(this._shown.get(groupId)) !== groupValueSignature(this._filterState.value(groupId));
|
|
586
|
+
}
|
|
444
587
|
_origin = { x: 0, y: 0, w: 0, h: 0 };
|
|
445
588
|
// Pointer-capture gesture loop: runs outside Angular, repaints imperatively,
|
|
446
589
|
// and finishes back inside Angular (selection/persistence).
|
|
@@ -490,10 +633,9 @@ export class ReportComponentComponent {
|
|
|
490
633
|
});
|
|
491
634
|
}
|
|
492
635
|
// A chart on a time x-axis — the only component the report's group-by control
|
|
493
|
-
// applies to
|
|
494
|
-
// this is its documented browser-side mirror, for products on an older framework.
|
|
636
|
+
// applies to (isTimeSeriesChart, the browser-side mirror of the server's rule).
|
|
495
637
|
get _isTimeSeries() {
|
|
496
|
-
return this.component
|
|
638
|
+
return isTimeSeriesChart(this.component);
|
|
497
639
|
}
|
|
498
640
|
// Auto height (box fits its content) vs fixed (use `h` exactly). Derived from
|
|
499
641
|
// type, server-side: KPI tiles are auto; charts and lists are fixed — charts
|
|
@@ -532,36 +674,84 @@ export class ReportComponentComponent {
|
|
|
532
674
|
}
|
|
533
675
|
}
|
|
534
676
|
// ----- data ----------------------------------------------------------------
|
|
677
|
+
// One request of the load stream (tileLoads), built from the state now. The
|
|
678
|
+
// shimmer shows only while the tile has nothing on screen; otherwise the
|
|
679
|
+
// data stays and the thin bar shows.
|
|
535
680
|
_load() {
|
|
536
|
-
this.
|
|
681
|
+
const first = !this.data();
|
|
682
|
+
this.loading.set(first);
|
|
683
|
+
this.refreshing.set(!first);
|
|
537
684
|
this.error.set(null);
|
|
538
685
|
const filters = this._filterState.resolveForComponent(this.component);
|
|
539
|
-
//
|
|
540
|
-
//
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
this._reportData.componentData(this.reportId, this.component.id, filters, state)
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
686
|
+
// The tile's interaction state, the one its CSV and every export carry
|
|
687
|
+
// (tileDataState): a time-series chart's grain (when the viewer picked
|
|
688
|
+
// one) so the backend re-buckets, a chart's drill path, and the groups
|
|
689
|
+
// that match 'any'.
|
|
690
|
+
const state = this._filterState.tileState(this.component);
|
|
691
|
+
return this._reportData.componentData(this.reportId, this.component.id, filters, state);
|
|
692
|
+
}
|
|
693
|
+
// A failed load clears the data with its message, so the next load starts
|
|
694
|
+
// from the shimmer and never shows the data the failure replaced. A
|
|
695
|
+
// chart's answer gives its drill path.
|
|
696
|
+
_loaded(result) {
|
|
697
|
+
this.data.set(result.data);
|
|
698
|
+
this.error.set(result.error);
|
|
699
|
+
this.loading.set(false);
|
|
700
|
+
this.refreshing.set(false);
|
|
701
|
+
if (result.error === null && result.data) {
|
|
702
|
+
this._adoptDrill(result.data);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
// A chart takes the drill path its answer applied (adoptedDrillPath) while
|
|
706
|
+
// the viewer is offered drill; an older server applies none, and the path
|
|
707
|
+
// stays for the link. When the path it sent was cut, the viewer is told
|
|
708
|
+
// once (drillResetNoted): the shorter path is what the chart reads from
|
|
709
|
+
// now on, so the server cuts nothing again.
|
|
710
|
+
_adoptDrill(data) {
|
|
711
|
+
const grainMoved = this._grainMoved;
|
|
712
|
+
this._grainMoved = false;
|
|
713
|
+
if (this.component.type !== 'chart' || !this._offeredFeatures().includes('drill')) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
if (this._filterState.adoptDrill(this.component.id, adoptedDrillPath(data.drill))
|
|
717
|
+
&& drillResetNoted(data.drill, grainMoved)) {
|
|
718
|
+
this._message.warning(DRILL_RESET_MESSAGE);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
// ----- mark clicks ---------------------------------------------------------
|
|
722
|
+
_runMarkAction(action, click) {
|
|
723
|
+
if (action === 'drill') {
|
|
724
|
+
this._drillDown(click);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
// Drill down: the chart's path goes one level below the period clicked,
|
|
728
|
+
// and the chart reads again (drillChanges).
|
|
729
|
+
_drillDown(click) {
|
|
730
|
+
const path = drillDownPath(this.data()?.drill, click);
|
|
731
|
+
if (path) {
|
|
732
|
+
this._filterState.setDrill(this.component.id, path);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
// Lists the click's actions in the mark menu and opens it at the click,
|
|
736
|
+
// through the zero-size anchor (openAtPoint).
|
|
737
|
+
_openMarkMenu(actions, click) {
|
|
738
|
+
const anchor = this.markAnchor?.nativeElement;
|
|
739
|
+
if (!anchor) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
this._menuClick = click;
|
|
743
|
+
this.markMenuActions.set(actions);
|
|
744
|
+
openAtPoint(anchor, click.pointer, this.zoom, () => this.markMenu?.openMenu(null));
|
|
556
745
|
}
|
|
557
746
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportComponentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
558
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ReportComponentComponent, isStandalone: true, selector: "app-report-component", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: false, isRequired: false, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: false, isRequired: false, transformFunction: null }, groups: { classPropertyName: "groups", publicName: "groups", isSignal: false, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: false, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: false, isRequired: false, transformFunction: null }, snapper: { classPropertyName: "snapper", publicName: "snapper", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: null }, tokens: { classPropertyName: "tokens", publicName: "tokens", isSignal: true, isRequired: false, transformFunction: null }, valueKeysElsewhere: { classPropertyName: "valueKeysElsewhere", publicName: "valueKeysElsewhere", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectComponent: "selectComponent", positionChanged: "positionChanged", openSettings: "openSettings", removed: "removed", valueSettings: "valueSettings", textSaved: "textSaved", valuesRemoved: "valuesRemoved" }, host: { properties: { "class.height-auto": "this.heightAuto" } }, viewQueries: [{ propertyName: "_text", first: true, predicate: ComponentTextComponent, descendants: true, isSignal: true }, { propertyName: "chartComponent", first: true, predicate: ComponentChartComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"component-box\"\n [class.editing]=\"editMode\"\n [class.text]=\"isText\"\n [class.selected]=\"selected\"\n [style.padding]=\"bodyPadding\"\n (pointerdown)=\"onComponentPointerDown($event)\"\n (mousedown)=\"stopCanvasPan($event)\"\n (touchstart)=\"stopCanvasPan($event)\">\n <!-- The header is an fs-filter: heading template = title (and the edit-mode\n drag handle), actions = the menu, items = component-level filter groups,\n the same strip for every type (lists included). fs-filter reads its\n config once, so the block is keyed on the component-filter set to be\n recreated when it changes. -->\n <!-- A text block has no title bar \u2014 it IS its words, like a text box on a\n slide \u2014 so it gets neither the header nor the data actions. -->\n @for (key of isText ? [] : [filterKey]; track key) {\n <fs-filter\n class=\"component-filter\"\n [config]=\"filterConfig()\">\n <ng-template fsFilterHeading>\n <div\n class=\"component-title\"\n (pointerdown)=\"onDragStart($event)\">\n {{ component.title }}\n @if (truncated) {\n <mat-icon\n class=\"truncated-icon\"\n matTooltip=\"Showing a truncated result \u2014 refine the filters to see everything.\">\n warning_amber\n </mat-icon>\n }\n </div>\n </ng-template>\n </fs-filter>\n }\n <!-- The actions menu is floated top-right (absolute) rather than living in\n fs-filter's actions slot, so its ~40px button height no longer drives the\n header row's height. It overlays the box corner; the heading reserves\n right padding so a long title ellipsises before it. -->\n @if (!isText || (editMode && !textEditing())) {\n <button\n mat-icon-button\n class=\"component-menu\"\n [fsMenuTriggerFor]=\"menu\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"stopCanvasPan($event)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <!-- Beside its trigger, inside the same block: an fs-menu that finds no\n trigger of its own draws one. -->\n <fs-menu #menu>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"editText()\">\n <mat-icon>edit</mat-icon>\n <span>Edit text</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"deleteText()\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"settings()\">\n <mat-icon>tune</mat-icon>\n <span>Settings</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"exportCsv()\">\n <mat-icon>download</mat-icon>\n <span>Export CSV</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!hidesColumns\"\n (click)=\"chooseColumns()\">\n <mat-icon>view_column</mat-icon>\n <span>Columns</span>\n </ng-template>\n </fs-menu>\n }\n <div class=\"component-body\">\n @if (isText) {\n <app-report-component-text\n [html]=\"textHtml() ?? component.config?.html ?? ''\"\n [tokens]=\"tokens()\"\n [editing]=\"textEditing()\"\n [shownElsewhere]=\"shownElsewhere\"\n (saved)=\"onTextSaved($event)\"\n (editEnded)=\"textEditing.set(false)\"\n (valueSettings)=\"valueSettings.emit($event)\">\n </app-report-component-text>\n } @else if (component.type === 'list') {\n <app-report-component-list\n [reportId]=\"reportId\"\n [component]=\"component\">\n </app-report-component-list>\n } @else if (loading()) {\n <div class=\"component-state\">\n <div class=\"loading-shimmer\"></div>\n </div>\n } @else if (error()) {\n <div class=\"component-state error\">\n {{ error() }}\n </div>\n } @else if (!data()?.rows?.length) {\n <div class=\"component-state\">\n No data\n </div>\n } @else if (component.type === 'kpi') {\n <app-report-component-kpi\n [component]=\"component\"\n [data]=\"data()\">\n </app-report-component-kpi>\n } @else {\n <app-report-component-chart\n [component]=\"component\"\n [data]=\"data()\">\n </app-report-component-chart>\n }\n <!-- In edit mode a transparent veil over the body makes the WHOLE\n component draggable (industry standard: you grab the object, not just\n its title bar) and keeps inner widgets from swallowing the gesture. -->\n @if (editMode && !textEditing()) {\n <div\n class=\"drag-veil\"\n (pointerdown)=\"onDragStart($event)\">\n </div>\n }\n </div>\n</div>\n<!-- Handles live OUTSIDE the clipped box so they straddle its edges. -->\n@if (editMode && selected) {\n @for (handle of resizeHandles; track handle) {\n <div\n class=\"handle handle-{{ handle }}\"\n (mousedown)=\"stopCanvasPan($event)\"\n (pointerdown)=\"onResizeStart($event, handle)\">\n </div>\n }\n}", styles: [":host{position:absolute;display:flex;flex-direction:column;font-size:10px;--mdc-outlined-button-container-height: 30px;--mdc-outlined-button-label-text-size: 10px;--mat-outlined-button-horizontal-padding: 15px;--mdc-text-button-container-height: 30px;--mdc-text-button-label-text-size: 10px;--mat-text-button-horizontal-padding: 15px;--mat-button-outlined-container-height: 30px;--mat-button-outlined-label-text-size: 10px;--mat-button-outlined-horizontal-padding: 15px;--mat-button-text-container-height: 30px;--mat-button-text-label-text-size: 10px;--mat-button-text-horizontal-padding: 15px}.component-box{position:relative;width:100%;flex:1 1 auto;min-height:0;box-sizing:border-box;display:flex;flex-direction:column;background:#fff;border:1px solid #e4e7eb;border-radius:6px;overflow:hidden;transition:box-shadow .12s ease,border-color .12s ease;cursor:default}.component-box.editing .component-title{cursor:grab}.component-box.editing .component-title:active{cursor:grabbing}.component-box.editing:hover{border-color:#9db3c8;box-shadow:0 2px 8px #0f172a14}.component-box.selected{border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color),0 4px 14px #2196f32e}.component-box.text{background:transparent;border-color:transparent;border-radius:0;overflow:visible}.component-box.text.editing{border-style:dashed;border-color:#cbd2d9}.component-box.text.editing:hover{box-shadow:none}.component-box.text.selected{border-style:solid;border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color)}:host ::ng-deep .component-filter .filter-bar-container{align-items:center!important}.component-filter{flex:0 0 auto;display:block;padding:0 0 4px}.component-filter .component-title{display:flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;padding-right:40px;font-size:var(--report-heading-size);font-weight:600;color:#1f2933;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.component-filter .component-title .truncated-icon{font-size:16px;width:16px;height:16px;color:#f59e0b}.component-menu{position:absolute;top:2px;right:2px;z-index:30}.component-body{flex:1 1 auto;min-height:0;position:relative}:host(.height-auto) .component-state{min-height:120px}.drag-veil{position:absolute;inset:0;cursor:grab;touch-action:none}.drag-veil:active{cursor:grabbing}.component-state{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:12px;color:#7b8794;padding:8px;text-align:center}.component-state.error{color:#e15759}.loading-shimmer{width:70%;height:60%;border-radius:6px;background:linear-gradient(100deg,#f0f4f8 40%,#e4ebf2,#f0f4f8 60%);background-size:200% 100%;animation:shimmer 1.2s infinite linear}@keyframes shimmer{to{background-position-x:-200%}}.handle{position:absolute;width:14px;height:14px;display:flex;align-items:center;justify-content:center;touch-action:none;z-index:20;transform:scale(calc(1 / var(--canvas-zoom, 1)))}.handle:before{content:\"\";width:8px;height:8px;background:#fff;border:1.5px solid var(--brand-primary-color);border-radius:2px;box-shadow:0 1px 2px #0f172a33}.handle-nw{left:-7px;top:-7px;cursor:nwse-resize}.handle-n{left:calc(50% - 7px);top:-7px;cursor:ns-resize}.handle-ne{right:-7px;top:-7px;cursor:nesw-resize}.handle-e{right:-7px;top:calc(50% - 7px);cursor:ew-resize}.handle-se{right:-7px;bottom:-7px;cursor:nwse-resize}.handle-s{left:calc(50% - 7px);bottom:-7px;cursor:ns-resize}.handle-sw{left:-7px;bottom:-7px;cursor:nesw-resize}.handle-w{left:-7px;top:calc(50% - 7px);cursor:ew-resize}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: FsFilterModule }, { kind: "component", type: i1.FilterComponent, selector: "fs-filter", inputs: ["config"], outputs: ["closed", "opened", "ready"] }, { kind: "directive", type: i1.FilterHeadingDirective, selector: "[fsFilterHeading]" }, { kind: "ngmodule", type: FsMenuModule }, { kind: "component", type: i2.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { kind: "directive", type: i2.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { kind: "directive", type: i2.FsMenuTriggerDirective, selector: "[fsMenuTriggerFor]", inputs: ["fsMenuTriggerFor"] }, { kind: "component", type: ComponentChartComponent, selector: "app-report-component-chart", inputs: ["component", "data"] }, { kind: "component", type: ComponentKpiComponent, selector: "app-report-component-kpi", inputs: ["component", "data"] }, { kind: "component", type: ComponentListComponent, selector: "app-report-component-list", inputs: ["reportId", "component"] }, { kind: "component", type: ComponentTextComponent, selector: "app-report-component-text", inputs: ["html", "tokens", "editing", "shownElsewhere"], outputs: ["saved", "editEnded", "valueSettings"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
747
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ReportComponentComponent, isStandalone: true, selector: "app-report-component", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: false, isRequired: false, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: false, isRequired: false, transformFunction: null }, groups: { classPropertyName: "groups", publicName: "groups", isSignal: false, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: false, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: false, isRequired: false, transformFunction: null }, snapper: { classPropertyName: "snapper", publicName: "snapper", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: null }, tokens: { classPropertyName: "tokens", publicName: "tokens", isSignal: true, isRequired: false, transformFunction: null }, valueKeysElsewhere: { classPropertyName: "valueKeysElsewhere", publicName: "valueKeysElsewhere", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectComponent: "selectComponent", positionChanged: "positionChanged", openSettings: "openSettings", removed: "removed", valueSettings: "valueSettings", textSaved: "textSaved", valuesRemoved: "valuesRemoved" }, host: { properties: { "class.height-auto": "this.heightAuto" } }, viewQueries: [{ propertyName: "_text", first: true, predicate: ComponentTextComponent, descendants: true, isSignal: true }, { propertyName: "chartComponent", first: true, predicate: ComponentChartComponent, descendants: true }, { propertyName: "markMenu", first: true, predicate: ["markMenu"], descendants: true }, { propertyName: "markAnchor", first: true, predicate: ["markAnchor"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"component-box\"\n [class.editing]=\"editMode\"\n [class.text]=\"isText\"\n [class.selected]=\"selected\"\n [style.padding]=\"bodyPadding\"\n (pointerdown)=\"onComponentPointerDown($event)\"\n (mousedown)=\"stopCanvasPan($event)\"\n (touchstart)=\"stopCanvasPan($event)\">\n <!-- The header is an fs-filter: heading template = title (and the edit-mode\n drag handle), actions = the menu, items = component-level filter groups,\n the same strip for every type (lists included). fs-filter reads its\n config once, so the block is keyed on the component-filter set to be\n recreated when it changes. -->\n <!-- A text block has no title bar \u2014 it IS its words, like a text box on a\n slide \u2014 so it gets neither the header nor the data actions. -->\n @for (key of isText ? [] : [filterKey]; track key) {\n <fs-filter\n class=\"component-filter\"\n [config]=\"filterConfig()\">\n <ng-template fsFilterHeading>\n <div\n class=\"component-title\"\n (pointerdown)=\"onDragStart($event)\">\n <!-- While the chart is drilled the title leads its breadcrumb:\n 'Title \u203A 2026 \u203A Q3'. The title goes back to the top and each\n crumb to the period it names; the last is where the chart is.\n A long path is cut at its left end, so the crumbs nearest the\n chart stay in view. While the layout is edited the crumbs are\n plain text (the stylesheet; drillTo does nothing then). -->\n @if (drillCrumbs().length) {\n <span class=\"drill-path\">\n <span dir=\"ltr\">\n <a\n class=\"drill-crumb\"\n tabindex=\"0\"\n (click)=\"drillTo(0)\"\n (keydown.enter)=\"drillTo(0)\">\n {{ component.title }}\n </a>\n @for (label of drillCrumbs(); track $index; let last = $last) {\n <span class=\"drill-separator\">{{ drillSeparator }}</span>\n @if (last) {\n <span>{{ label }}</span>\n } @else {\n <a\n class=\"drill-crumb\"\n tabindex=\"0\"\n (click)=\"drillTo($index + 1)\"\n (keydown.enter)=\"drillTo($index + 1)\">\n {{ label }}\n </a>\n }\n }\n </span>\n </span>\n } @else {\n {{ component.title }}\n }\n @if (truncated) {\n <mat-icon\n class=\"truncated-icon\"\n matTooltip=\"Showing a truncated result \u2014 refine the filters to see everything.\">\n warning_amber\n </mat-icon>\n }\n </div>\n </ng-template>\n </fs-filter>\n }\n <!-- The actions menu is floated top-right (absolute) rather than living in\n fs-filter's actions slot, so its ~40px button height no longer drives the\n header row's height. It overlays the box corner; the heading reserves\n right padding so a long title ellipsises before it. -->\n @if (!isText || (editMode && !textEditing())) {\n <button\n mat-icon-button\n class=\"component-menu\"\n [fsMenuTriggerFor]=\"menu\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"stopCanvasPan($event)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <!-- Beside its trigger, inside the same block: an fs-menu that finds no\n trigger of its own draws one. -->\n <fs-menu #menu>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"editText()\">\n <mat-icon>edit</mat-icon>\n <span>Edit text</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"deleteText()\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!drillCrumbs().length || editMode\"\n (click)=\"drillUp()\">\n <mat-icon>arrow_upward</mat-icon>\n <span>Drill up</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!drillCrumbs().length || editMode\"\n (click)=\"drillTo(0)\">\n <mat-icon>vertical_align_top</mat-icon>\n <span>Back to top</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"settings()\">\n <mat-icon>tune</mat-icon>\n <span>Settings</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"exportCsv()\">\n <mat-icon>download</mat-icon>\n <span>Export CSV</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!hidesColumns\"\n (click)=\"chooseColumns()\">\n <mat-icon>view_column</mat-icon>\n <span>Columns</span>\n </ng-template>\n </fs-menu>\n }\n <div class=\"component-body\">\n <!-- A refetch keeps the data on screen under a thin bar; the shimmer\n below is for the first load only. -->\n @if (refreshing()) {\n <mat-progress-bar\n class=\"refresh-bar\"\n aria-label=\"Refreshing data\"\n [mode]=\"'indeterminate'\">\n </mat-progress-bar>\n }\n @if (isText) {\n <app-report-component-text\n [html]=\"textHtml() ?? component.config?.html ?? ''\"\n [tokens]=\"tokens()\"\n [editing]=\"textEditing()\"\n [shownElsewhere]=\"shownElsewhere\"\n (saved)=\"onTextSaved($event)\"\n (editEnded)=\"textEditing.set(false)\"\n (valueSettings)=\"valueSettings.emit($event)\">\n </app-report-component-text>\n } @else if (component.type === 'list') {\n @for (key of [listResetKey()]; track key) {\n <app-report-component-list\n [reportId]=\"reportId\"\n [component]=\"component\">\n </app-report-component-list>\n }\n } @else if (loading()) {\n <div class=\"component-state\">\n <div class=\"loading-shimmer\"></div>\n </div>\n } @else if (error()) {\n <div class=\"component-state error\">\n {{ error() }}\n </div>\n } @else if (!data()?.rows?.length) {\n <div class=\"component-state\">\n {{ emptyMessage() }}\n </div>\n } @else if (component.type === 'kpi') {\n <app-report-component-kpi\n [component]=\"component\"\n [data]=\"data()\"\n (markClick)=\"onMarkClick($event)\">\n </app-report-component-kpi>\n } @else {\n <app-report-component-chart\n [component]=\"component\"\n [data]=\"data()\"\n [actions]=\"tileActions()\"\n [(legendSelected)]=\"legendSelected\"\n (markClick)=\"onMarkClick($event)\"\n (markMiss)=\"onMarkMiss()\">\n </app-report-component-chart>\n }\n <!-- In edit mode a transparent veil over the body makes the WHOLE\n component draggable (industry standard: you grab the object, not just\n its title bar) and keeps inner widgets from swallowing the gesture. -->\n @if (editMode && !textEditing()) {\n <div\n class=\"drag-veil\"\n (pointerdown)=\"onDragStart($event)\">\n </div>\n }\n </div>\n</div>\n<!-- The mark menu, for a click whose mark offers two or more actions. It\n opens at the click: its trigger is a zero-size anchor that\n anchor-at-point.ts moves there first. -->\n@if (!isText && !editMode) {\n <span\n #markAnchor\n [style.position]=\"'absolute'\"\n [fsMenuTriggerFor]=\"markMenu\">\n </span>\n <fs-menu #markMenu>\n @for (action of markMenuActions(); track action) {\n <ng-template\n fs-menu-item\n (click)=\"runMarkAction(action)\">\n {{ markActionLabels[action] }}\n </ng-template>\n }\n </fs-menu>\n}\n<!-- Handles live OUTSIDE the clipped box so they straddle its edges. -->\n@if (editMode && selected) {\n @for (handle of resizeHandles; track handle) {\n <div\n class=\"handle handle-{{ handle }}\"\n (mousedown)=\"stopCanvasPan($event)\"\n (pointerdown)=\"onResizeStart($event, handle)\">\n </div>\n }\n}", styles: [":host{position:absolute;display:flex;flex-direction:column;font-size:10px;--mdc-outlined-button-container-height: 30px;--mdc-outlined-button-label-text-size: 10px;--mat-outlined-button-horizontal-padding: 15px;--mdc-text-button-container-height: 30px;--mdc-text-button-label-text-size: 10px;--mat-text-button-horizontal-padding: 15px;--mat-button-outlined-container-height: 30px;--mat-button-outlined-label-text-size: 10px;--mat-button-outlined-horizontal-padding: 15px;--mat-button-text-container-height: 30px;--mat-button-text-label-text-size: 10px;--mat-button-text-horizontal-padding: 15px}.component-box{position:relative;width:100%;flex:1 1 auto;min-height:0;box-sizing:border-box;display:flex;flex-direction:column;background:#fff;border:1px solid #e4e7eb;border-radius:6px;overflow:hidden;transition:box-shadow .12s ease,border-color .12s ease;cursor:default}.component-box.editing .component-title{cursor:grab}.component-box.editing .component-title:active{cursor:grabbing}.component-box.editing .drill-crumb{pointer-events:none}.component-box.editing:hover{border-color:#9db3c8;box-shadow:0 2px 8px #0f172a14}.component-box.selected{border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color),0 4px 14px #2196f32e}.component-box.text{background:transparent;border-color:transparent;border-radius:0;overflow:visible}.component-box.text.editing{border-style:dashed;border-color:#cbd2d9}.component-box.text.editing:hover{box-shadow:none}.component-box.text.selected{border-style:solid;border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color)}:host ::ng-deep .component-filter .filter-bar-container{align-items:center!important}.component-filter{flex:0 0 auto;display:block;padding:0 0 4px}.component-filter .component-title{display:flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;padding-right:40px;font-size:var(--report-heading-size);font-weight:600;color:#1f2933;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.component-filter .component-title .truncated-icon{font-size:16px;width:16px;height:16px;color:#f59e0b}.component-filter .component-title .drill-path{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left}.component-filter .component-title .drill-crumb{color:inherit;cursor:pointer;text-decoration:none}.component-filter .component-title .drill-crumb:hover,.component-filter .component-title .drill-crumb:focus-visible{text-decoration:underline}.component-filter .component-title .drill-separator{opacity:.6}.component-menu{position:absolute;top:2px;right:2px;z-index:30}.component-body{flex:1 1 auto;min-height:0;position:relative}.refresh-bar{position:absolute;top:0;left:0;right:0;z-index:1;pointer-events:none;--mdc-linear-progress-track-height: 2px;--mdc-linear-progress-active-indicator-height: 2px;--mat-progress-bar-track-height: 2px;--mat-progress-bar-active-indicator-height: 2px}:host(.height-auto) .component-state{min-height:120px}.drag-veil{position:absolute;inset:0;cursor:grab;touch-action:none}.drag-veil:active{cursor:grabbing}.component-state{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:12px;color:#7b8794;padding:8px;text-align:center}.component-state.error{color:#e15759}.loading-shimmer{width:70%;height:60%;border-radius:6px;background:linear-gradient(100deg,#f0f4f8 40%,#e4ebf2,#f0f4f8 60%);background-size:200% 100%;animation:shimmer 1.2s infinite linear}@keyframes shimmer{to{background-position-x:-200%}}.handle{position:absolute;width:14px;height:14px;display:flex;align-items:center;justify-content:center;touch-action:none;z-index:20;transform:scale(calc(1 / var(--canvas-zoom, 1)))}.handle:before{content:\"\";width:8px;height:8px;background:#fff;border:1.5px solid var(--brand-primary-color);border-radius:2px;box-shadow:0 1px 2px #0f172a33}.handle-nw{left:-7px;top:-7px;cursor:nwse-resize}.handle-n{left:calc(50% - 7px);top:-7px;cursor:ns-resize}.handle-ne{right:-7px;top:-7px;cursor:nesw-resize}.handle-e{right:-7px;top:calc(50% - 7px);cursor:ew-resize}.handle-se{right:-7px;bottom:-7px;cursor:nwse-resize}.handle-s{left:calc(50% - 7px);bottom:-7px;cursor:ns-resize}.handle-sw{left:-7px;bottom:-7px;cursor:nesw-resize}.handle-w{left:-7px;top:calc(50% - 7px);cursor:ew-resize}\n"], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: FsFilterModule }, { kind: "component", type: i1.FilterComponent, selector: "fs-filter", inputs: ["config"], outputs: ["closed", "opened", "ready"] }, { kind: "directive", type: i1.FilterHeadingDirective, selector: "[fsFilterHeading]" }, { kind: "ngmodule", type: FsMenuModule }, { kind: "component", type: i2.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { kind: "directive", type: i2.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { kind: "directive", type: i2.FsMenuTriggerDirective, selector: "[fsMenuTriggerFor]", inputs: ["fsMenuTriggerFor"] }, { kind: "component", type: ComponentChartComponent, selector: "app-report-component-chart", inputs: ["component", "data", "legendSelected", "actions"], outputs: ["legendSelectedChange", "markClick", "markMiss"] }, { kind: "component", type: ComponentKpiComponent, selector: "app-report-component-kpi", inputs: ["component", "data"], outputs: ["markClick"] }, { kind: "component", type: ComponentListComponent, selector: "app-report-component-list", inputs: ["reportId", "component"] }, { kind: "component", type: ComponentTextComponent, selector: "app-report-component-text", inputs: ["html", "tokens", "editing", "shownElsewhere"], outputs: ["saved", "editEnded", "valueSettings"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
559
748
|
}
|
|
560
749
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportComponentComponent, decorators: [{
|
|
561
750
|
type: Component,
|
|
562
751
|
args: [{ selector: 'app-report-component', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
563
752
|
MatIcon,
|
|
564
753
|
MatIconButton,
|
|
754
|
+
MatProgressBar,
|
|
565
755
|
MatTooltip,
|
|
566
756
|
FsFilterModule,
|
|
567
757
|
FsMenuModule,
|
|
@@ -569,7 +759,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
569
759
|
ComponentKpiComponent,
|
|
570
760
|
ComponentListComponent,
|
|
571
761
|
ComponentTextComponent,
|
|
572
|
-
], template: "<div\n class=\"component-box\"\n [class.editing]=\"editMode\"\n [class.text]=\"isText\"\n [class.selected]=\"selected\"\n [style.padding]=\"bodyPadding\"\n (pointerdown)=\"onComponentPointerDown($event)\"\n (mousedown)=\"stopCanvasPan($event)\"\n (touchstart)=\"stopCanvasPan($event)\">\n <!-- The header is an fs-filter: heading template = title (and the edit-mode\n drag handle), actions = the menu, items = component-level filter groups,\n the same strip for every type (lists included). fs-filter reads its\n config once, so the block is keyed on the component-filter set to be\n recreated when it changes. -->\n <!-- A text block has no title bar \u2014 it IS its words, like a text box on a\n slide \u2014 so it gets neither the header nor the data actions. -->\n @for (key of isText ? [] : [filterKey]; track key) {\n <fs-filter\n class=\"component-filter\"\n [config]=\"filterConfig()\">\n <ng-template fsFilterHeading>\n <div\n class=\"component-title\"\n (pointerdown)=\"onDragStart($event)\">\n {{ component.title }}\n @if (truncated) {\n <mat-icon\n class=\"truncated-icon\"\n matTooltip=\"Showing a truncated result \u2014 refine the filters to see everything.\">\n warning_amber\n </mat-icon>\n }\n </div>\n </ng-template>\n </fs-filter>\n }\n <!-- The actions menu is floated top-right (absolute) rather than living in\n fs-filter's actions slot, so its ~40px button height no longer drives the\n header row's height. It overlays the box corner; the heading reserves\n right padding so a long title ellipsises before it. -->\n @if (!isText || (editMode && !textEditing())) {\n <button\n mat-icon-button\n class=\"component-menu\"\n [fsMenuTriggerFor]=\"menu\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"stopCanvasPan($event)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <!-- Beside its trigger, inside the same block: an fs-menu that finds no\n trigger of its own draws one. -->\n <fs-menu #menu>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"editText()\">\n <mat-icon>edit</mat-icon>\n <span>Edit text</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"deleteText()\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"settings()\">\n <mat-icon>tune</mat-icon>\n <span>Settings</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"exportCsv()\">\n <mat-icon>download</mat-icon>\n <span>Export CSV</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!hidesColumns\"\n (click)=\"chooseColumns()\">\n <mat-icon>view_column</mat-icon>\n <span>Columns</span>\n </ng-template>\n </fs-menu>\n }\n <div class=\"component-body\">\n @if (isText) {\n <app-report-component-text\n [html]=\"textHtml() ?? component.config?.html ?? ''\"\n [tokens]=\"tokens()\"\n [editing]=\"textEditing()\"\n [shownElsewhere]=\"shownElsewhere\"\n (saved)=\"onTextSaved($event)\"\n (editEnded)=\"textEditing.set(false)\"\n (valueSettings)=\"valueSettings.emit($event)\">\n </app-report-component-text>\n } @else if (component.type === 'list') {\n <app-report-component-list\n [reportId]=\"reportId\"\n [component]=\"component\">\n </app-report-component-list>\n } @else if (loading()) {\n <div class=\"component-state\">\n <div class=\"loading-shimmer\"></div>\n </div>\n } @else if (error()) {\n <div class=\"component-state error\">\n {{ error() }}\n </div>\n } @else if (!data()?.rows?.length) {\n <div class=\"component-state\">\n No data\n </div>\n } @else if (component.type === 'kpi') {\n <app-report-component-kpi\n [component]=\"component\"\n [data]=\"data()\">\n </app-report-component-kpi>\n } @else {\n <app-report-component-chart\n [component]=\"component\"\n [data]=\"data()\">\n </app-report-component-chart>\n }\n <!-- In edit mode a transparent veil over the body makes the WHOLE\n component draggable (industry standard: you grab the object, not just\n its title bar) and keeps inner widgets from swallowing the gesture. -->\n @if (editMode && !textEditing()) {\n <div\n class=\"drag-veil\"\n (pointerdown)=\"onDragStart($event)\">\n </div>\n }\n </div>\n</div>\n<!-- Handles live OUTSIDE the clipped box so they straddle its edges. -->\n@if (editMode && selected) {\n @for (handle of resizeHandles; track handle) {\n <div\n class=\"handle handle-{{ handle }}\"\n (mousedown)=\"stopCanvasPan($event)\"\n (pointerdown)=\"onResizeStart($event, handle)\">\n </div>\n }\n}", styles: [":host{position:absolute;display:flex;flex-direction:column;font-size:10px;--mdc-outlined-button-container-height: 30px;--mdc-outlined-button-label-text-size: 10px;--mat-outlined-button-horizontal-padding: 15px;--mdc-text-button-container-height: 30px;--mdc-text-button-label-text-size: 10px;--mat-text-button-horizontal-padding: 15px;--mat-button-outlined-container-height: 30px;--mat-button-outlined-label-text-size: 10px;--mat-button-outlined-horizontal-padding: 15px;--mat-button-text-container-height: 30px;--mat-button-text-label-text-size: 10px;--mat-button-text-horizontal-padding: 15px}.component-box{position:relative;width:100%;flex:1 1 auto;min-height:0;box-sizing:border-box;display:flex;flex-direction:column;background:#fff;border:1px solid #e4e7eb;border-radius:6px;overflow:hidden;transition:box-shadow .12s ease,border-color .12s ease;cursor:default}.component-box.editing .component-title{cursor:grab}.component-box.editing .component-title:active{cursor:grabbing}.component-box.editing:hover{border-color:#9db3c8;box-shadow:0 2px 8px #0f172a14}.component-box.selected{border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color),0 4px 14px #2196f32e}.component-box.text{background:transparent;border-color:transparent;border-radius:0;overflow:visible}.component-box.text.editing{border-style:dashed;border-color:#cbd2d9}.component-box.text.editing:hover{box-shadow:none}.component-box.text.selected{border-style:solid;border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color)}:host ::ng-deep .component-filter .filter-bar-container{align-items:center!important}.component-filter{flex:0 0 auto;display:block;padding:0 0 4px}.component-filter .component-title{display:flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;padding-right:40px;font-size:var(--report-heading-size);font-weight:600;color:#1f2933;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.component-filter .component-title .truncated-icon{font-size:16px;width:16px;height:16px;color:#f59e0b}.component-menu{position:absolute;top:2px;right:2px;z-index:30}.component-body{flex:1 1 auto;min-height:0;position:relative}:host(.height-auto) .component-state{min-height:120px}.drag-veil{position:absolute;inset:0;cursor:grab;touch-action:none}.drag-veil:active{cursor:grabbing}.component-state{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:12px;color:#7b8794;padding:8px;text-align:center}.component-state.error{color:#e15759}.loading-shimmer{width:70%;height:60%;border-radius:6px;background:linear-gradient(100deg,#f0f4f8 40%,#e4ebf2,#f0f4f8 60%);background-size:200% 100%;animation:shimmer 1.2s infinite linear}@keyframes shimmer{to{background-position-x:-200%}}.handle{position:absolute;width:14px;height:14px;display:flex;align-items:center;justify-content:center;touch-action:none;z-index:20;transform:scale(calc(1 / var(--canvas-zoom, 1)))}.handle:before{content:\"\";width:8px;height:8px;background:#fff;border:1.5px solid var(--brand-primary-color);border-radius:2px;box-shadow:0 1px 2px #0f172a33}.handle-nw{left:-7px;top:-7px;cursor:nwse-resize}.handle-n{left:calc(50% - 7px);top:-7px;cursor:ns-resize}.handle-ne{right:-7px;top:-7px;cursor:nesw-resize}.handle-e{right:-7px;top:calc(50% - 7px);cursor:ew-resize}.handle-se{right:-7px;bottom:-7px;cursor:nwse-resize}.handle-s{left:calc(50% - 7px);bottom:-7px;cursor:ns-resize}.handle-sw{left:-7px;bottom:-7px;cursor:nesw-resize}.handle-w{left:-7px;top:calc(50% - 7px);cursor:ew-resize}\n"] }]
|
|
762
|
+
], template: "<div\n class=\"component-box\"\n [class.editing]=\"editMode\"\n [class.text]=\"isText\"\n [class.selected]=\"selected\"\n [style.padding]=\"bodyPadding\"\n (pointerdown)=\"onComponentPointerDown($event)\"\n (mousedown)=\"stopCanvasPan($event)\"\n (touchstart)=\"stopCanvasPan($event)\">\n <!-- The header is an fs-filter: heading template = title (and the edit-mode\n drag handle), actions = the menu, items = component-level filter groups,\n the same strip for every type (lists included). fs-filter reads its\n config once, so the block is keyed on the component-filter set to be\n recreated when it changes. -->\n <!-- A text block has no title bar \u2014 it IS its words, like a text box on a\n slide \u2014 so it gets neither the header nor the data actions. -->\n @for (key of isText ? [] : [filterKey]; track key) {\n <fs-filter\n class=\"component-filter\"\n [config]=\"filterConfig()\">\n <ng-template fsFilterHeading>\n <div\n class=\"component-title\"\n (pointerdown)=\"onDragStart($event)\">\n <!-- While the chart is drilled the title leads its breadcrumb:\n 'Title \u203A 2026 \u203A Q3'. The title goes back to the top and each\n crumb to the period it names; the last is where the chart is.\n A long path is cut at its left end, so the crumbs nearest the\n chart stay in view. While the layout is edited the crumbs are\n plain text (the stylesheet; drillTo does nothing then). -->\n @if (drillCrumbs().length) {\n <span class=\"drill-path\">\n <span dir=\"ltr\">\n <a\n class=\"drill-crumb\"\n tabindex=\"0\"\n (click)=\"drillTo(0)\"\n (keydown.enter)=\"drillTo(0)\">\n {{ component.title }}\n </a>\n @for (label of drillCrumbs(); track $index; let last = $last) {\n <span class=\"drill-separator\">{{ drillSeparator }}</span>\n @if (last) {\n <span>{{ label }}</span>\n } @else {\n <a\n class=\"drill-crumb\"\n tabindex=\"0\"\n (click)=\"drillTo($index + 1)\"\n (keydown.enter)=\"drillTo($index + 1)\">\n {{ label }}\n </a>\n }\n }\n </span>\n </span>\n } @else {\n {{ component.title }}\n }\n @if (truncated) {\n <mat-icon\n class=\"truncated-icon\"\n matTooltip=\"Showing a truncated result \u2014 refine the filters to see everything.\">\n warning_amber\n </mat-icon>\n }\n </div>\n </ng-template>\n </fs-filter>\n }\n <!-- The actions menu is floated top-right (absolute) rather than living in\n fs-filter's actions slot, so its ~40px button height no longer drives the\n header row's height. It overlays the box corner; the heading reserves\n right padding so a long title ellipsises before it. -->\n @if (!isText || (editMode && !textEditing())) {\n <button\n mat-icon-button\n class=\"component-menu\"\n [fsMenuTriggerFor]=\"menu\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"stopCanvasPan($event)\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <!-- Beside its trigger, inside the same block: an fs-menu that finds no\n trigger of its own draws one. -->\n <fs-menu #menu>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"editText()\">\n <mat-icon>edit</mat-icon>\n <span>Edit text</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!isText\"\n (click)=\"deleteText()\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!drillCrumbs().length || editMode\"\n (click)=\"drillUp()\">\n <mat-icon>arrow_upward</mat-icon>\n <span>Drill up</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!drillCrumbs().length || editMode\"\n (click)=\"drillTo(0)\">\n <mat-icon>vertical_align_top</mat-icon>\n <span>Back to top</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"settings()\">\n <mat-icon>tune</mat-icon>\n <span>Settings</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"isText\"\n (click)=\"exportCsv()\">\n <mat-icon>download</mat-icon>\n <span>Export CSV</span>\n </ng-template>\n <ng-template\n fs-menu-item\n [hidden]=\"!hidesColumns\"\n (click)=\"chooseColumns()\">\n <mat-icon>view_column</mat-icon>\n <span>Columns</span>\n </ng-template>\n </fs-menu>\n }\n <div class=\"component-body\">\n <!-- A refetch keeps the data on screen under a thin bar; the shimmer\n below is for the first load only. -->\n @if (refreshing()) {\n <mat-progress-bar\n class=\"refresh-bar\"\n aria-label=\"Refreshing data\"\n [mode]=\"'indeterminate'\">\n </mat-progress-bar>\n }\n @if (isText) {\n <app-report-component-text\n [html]=\"textHtml() ?? component.config?.html ?? ''\"\n [tokens]=\"tokens()\"\n [editing]=\"textEditing()\"\n [shownElsewhere]=\"shownElsewhere\"\n (saved)=\"onTextSaved($event)\"\n (editEnded)=\"textEditing.set(false)\"\n (valueSettings)=\"valueSettings.emit($event)\">\n </app-report-component-text>\n } @else if (component.type === 'list') {\n @for (key of [listResetKey()]; track key) {\n <app-report-component-list\n [reportId]=\"reportId\"\n [component]=\"component\">\n </app-report-component-list>\n }\n } @else if (loading()) {\n <div class=\"component-state\">\n <div class=\"loading-shimmer\"></div>\n </div>\n } @else if (error()) {\n <div class=\"component-state error\">\n {{ error() }}\n </div>\n } @else if (!data()?.rows?.length) {\n <div class=\"component-state\">\n {{ emptyMessage() }}\n </div>\n } @else if (component.type === 'kpi') {\n <app-report-component-kpi\n [component]=\"component\"\n [data]=\"data()\"\n (markClick)=\"onMarkClick($event)\">\n </app-report-component-kpi>\n } @else {\n <app-report-component-chart\n [component]=\"component\"\n [data]=\"data()\"\n [actions]=\"tileActions()\"\n [(legendSelected)]=\"legendSelected\"\n (markClick)=\"onMarkClick($event)\"\n (markMiss)=\"onMarkMiss()\">\n </app-report-component-chart>\n }\n <!-- In edit mode a transparent veil over the body makes the WHOLE\n component draggable (industry standard: you grab the object, not just\n its title bar) and keeps inner widgets from swallowing the gesture. -->\n @if (editMode && !textEditing()) {\n <div\n class=\"drag-veil\"\n (pointerdown)=\"onDragStart($event)\">\n </div>\n }\n </div>\n</div>\n<!-- The mark menu, for a click whose mark offers two or more actions. It\n opens at the click: its trigger is a zero-size anchor that\n anchor-at-point.ts moves there first. -->\n@if (!isText && !editMode) {\n <span\n #markAnchor\n [style.position]=\"'absolute'\"\n [fsMenuTriggerFor]=\"markMenu\">\n </span>\n <fs-menu #markMenu>\n @for (action of markMenuActions(); track action) {\n <ng-template\n fs-menu-item\n (click)=\"runMarkAction(action)\">\n {{ markActionLabels[action] }}\n </ng-template>\n }\n </fs-menu>\n}\n<!-- Handles live OUTSIDE the clipped box so they straddle its edges. -->\n@if (editMode && selected) {\n @for (handle of resizeHandles; track handle) {\n <div\n class=\"handle handle-{{ handle }}\"\n (mousedown)=\"stopCanvasPan($event)\"\n (pointerdown)=\"onResizeStart($event, handle)\">\n </div>\n }\n}", styles: [":host{position:absolute;display:flex;flex-direction:column;font-size:10px;--mdc-outlined-button-container-height: 30px;--mdc-outlined-button-label-text-size: 10px;--mat-outlined-button-horizontal-padding: 15px;--mdc-text-button-container-height: 30px;--mdc-text-button-label-text-size: 10px;--mat-text-button-horizontal-padding: 15px;--mat-button-outlined-container-height: 30px;--mat-button-outlined-label-text-size: 10px;--mat-button-outlined-horizontal-padding: 15px;--mat-button-text-container-height: 30px;--mat-button-text-label-text-size: 10px;--mat-button-text-horizontal-padding: 15px}.component-box{position:relative;width:100%;flex:1 1 auto;min-height:0;box-sizing:border-box;display:flex;flex-direction:column;background:#fff;border:1px solid #e4e7eb;border-radius:6px;overflow:hidden;transition:box-shadow .12s ease,border-color .12s ease;cursor:default}.component-box.editing .component-title{cursor:grab}.component-box.editing .component-title:active{cursor:grabbing}.component-box.editing .drill-crumb{pointer-events:none}.component-box.editing:hover{border-color:#9db3c8;box-shadow:0 2px 8px #0f172a14}.component-box.selected{border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color),0 4px 14px #2196f32e}.component-box.text{background:transparent;border-color:transparent;border-radius:0;overflow:visible}.component-box.text.editing{border-style:dashed;border-color:#cbd2d9}.component-box.text.editing:hover{box-shadow:none}.component-box.text.selected{border-style:solid;border-color:var(--brand-primary-color);box-shadow:0 0 0 1px var(--brand-primary-color)}:host ::ng-deep .component-filter .filter-bar-container{align-items:center!important}.component-filter{flex:0 0 auto;display:block;padding:0 0 4px}.component-filter .component-title{display:flex;align-items:center;gap:4px;-webkit-user-select:none;user-select:none;padding-right:40px;font-size:var(--report-heading-size);font-weight:600;color:#1f2933;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.component-filter .component-title .truncated-icon{font-size:16px;width:16px;height:16px;color:#f59e0b}.component-filter .component-title .drill-path{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left}.component-filter .component-title .drill-crumb{color:inherit;cursor:pointer;text-decoration:none}.component-filter .component-title .drill-crumb:hover,.component-filter .component-title .drill-crumb:focus-visible{text-decoration:underline}.component-filter .component-title .drill-separator{opacity:.6}.component-menu{position:absolute;top:2px;right:2px;z-index:30}.component-body{flex:1 1 auto;min-height:0;position:relative}.refresh-bar{position:absolute;top:0;left:0;right:0;z-index:1;pointer-events:none;--mdc-linear-progress-track-height: 2px;--mdc-linear-progress-active-indicator-height: 2px;--mat-progress-bar-track-height: 2px;--mat-progress-bar-active-indicator-height: 2px}:host(.height-auto) .component-state{min-height:120px}.drag-veil{position:absolute;inset:0;cursor:grab;touch-action:none}.drag-veil:active{cursor:grabbing}.component-state{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:12px;color:#7b8794;padding:8px;text-align:center}.component-state.error{color:#e15759}.loading-shimmer{width:70%;height:60%;border-radius:6px;background:linear-gradient(100deg,#f0f4f8 40%,#e4ebf2,#f0f4f8 60%);background-size:200% 100%;animation:shimmer 1.2s infinite linear}@keyframes shimmer{to{background-position-x:-200%}}.handle{position:absolute;width:14px;height:14px;display:flex;align-items:center;justify-content:center;touch-action:none;z-index:20;transform:scale(calc(1 / var(--canvas-zoom, 1)))}.handle:before{content:\"\";width:8px;height:8px;background:#fff;border:1.5px solid var(--brand-primary-color);border-radius:2px;box-shadow:0 1px 2px #0f172a33}.handle-nw{left:-7px;top:-7px;cursor:nwse-resize}.handle-n{left:calc(50% - 7px);top:-7px;cursor:ns-resize}.handle-ne{right:-7px;top:-7px;cursor:nesw-resize}.handle-e{right:-7px;top:calc(50% - 7px);cursor:ew-resize}.handle-se{right:-7px;bottom:-7px;cursor:nwse-resize}.handle-s{left:calc(50% - 7px);bottom:-7px;cursor:ns-resize}.handle-sw{left:-7px;bottom:-7px;cursor:nesw-resize}.handle-w{left:-7px;top:calc(50% - 7px);cursor:ew-resize}\n"] }]
|
|
573
763
|
}], propDecorators: { reportId: [{
|
|
574
764
|
type: Input
|
|
575
765
|
}], component: [{
|
|
@@ -593,8 +783,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
593
783
|
}], chartComponent: [{
|
|
594
784
|
type: ViewChild,
|
|
595
785
|
args: [ComponentChartComponent]
|
|
786
|
+
}], markMenu: [{
|
|
787
|
+
type: ViewChild,
|
|
788
|
+
args: ['markMenu']
|
|
789
|
+
}], markAnchor: [{
|
|
790
|
+
type: ViewChild,
|
|
791
|
+
args: ['markAnchor']
|
|
596
792
|
}], heightAuto: [{
|
|
597
793
|
type: HostBinding,
|
|
598
794
|
args: ['class.height-auto']
|
|
599
795
|
}] } });
|
|
600
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWNvbXBvbmVudC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvY29tcG9uZW50cy9yZXBvcnQtY29tcG9uZW50L3JlcG9ydC1jb21wb25lbnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvcmVwb3J0LWNvbXBvbmVudC9yZXBvcnQtY29tcG9uZW50LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFDMUQsWUFBWSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFxQixNQUFNLEVBQWlCLFNBQVMsRUFBRSxNQUFNLEVBQ3JHLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFNBQVMsR0FDakMsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRXZELE9BQU8sRUFBZ0IsY0FBYyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRTlDLE9BQU8sRUFBRSxPQUFPLEVBQUUsWUFBWSxF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RUcsT0FBTywySUFDUCxhQUFhLDZGQUNiLFVBQVUsZ1JBQ1YsY0FBYyx5UEFDZCxZQUFZLHdaQUNaLHVCQUF1QixzR0FDdkIscUJBQXFCLG9HQUNyQixzQkFBc0IseUdBQ3RCLHNCQUFzQjs7NEZBR2Isd0JBQXdCO2tCQWxCcEMsU0FBUzsrQkFDRSxzQkFBc0IsbUJBR2YsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJLFdBQ1A7d0JBQ1AsT0FBTzt3QkFDUCxhQUFhO3dCQUNiLFVBQVU7d0JBQ1YsY0FBYzt3QkFDZCxZQUFZO3dCQUNaLHVCQUF1Qjt3QkFDdkIscUJBQXFCO3dCQUNyQixzQkFBc0I7d0JBQ3RCLHNCQUFzQjtxQkFDdkI7OEJBSWUsUUFBUTtzQkFBdkIsS0FBSztnQkFDVSxTQUFTO3NCQUF4QixLQUFLO2dCQUNVLE1BQU07c0JBQXJCLEtBQUs7Z0JBQ1UsUUFBUTtzQkFBdkIsS0FBSztnQkFFVSxJQUFJO3NCQUFuQixLQUFLO2dCQUNVLE9BQU87c0JBQXRCLEtBQUs7Z0JBQ1UsUUFBUTtzQkFBdkIsS0FBSztnQkFFVyxlQUFlO3NCQUEvQixNQUFNO2dCQUNVLGVBQWU7c0JBQS9CLE1BQU07Z0JBQ1UsWUFBWTtzQkFBNUIsTUFBTTtnQkF1Q0EsY0FBYztzQkFEcEIsU0FBUzt1QkFBQyx1QkFBdUI7Z0JBdWdCdkIsVUFBVTtzQkFEcEIsV0FBVzt1QkFBQyxtQkFBbUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsIEhvc3RCaW5kaW5nLCBJbnB1dCwgTmdab25lLCBPbkNoYW5nZXMsIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQsIGluamVjdCxcbiAgaW5wdXQsIG91dHB1dCwgc2lnbmFsLCB2aWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5cbmltcG9ydCB7IE1hdEljb25CdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTWF0RGlhbG9nIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IE1hdEljb24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcbmltcG9ydCB7IE1hdFRvb2x0aXAgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90b29sdGlwJztcblxuaW1wb3J0IHsgRmlsdGVyQ29uZmlnLCBGc0ZpbHRlck1vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL2ZpbHRlcic7XG5pbXBvcnQgeyBGc01lbnVNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9tZW51JztcbmltcG9ydCB7IEZzTWVzc2FnZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9jZXNzIH0gZnJvbSAnQGZpcmVzdGl0Y2gvcHJvY2Vzcyc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5cbmltcG9ydCB7IFN1YmplY3QsIGRlYm91bmNlVGltZSwgbWFwLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7IExpc3RDb2x1bW5zQ29tcG9uZW50LCBMaXN0Q29sdW1uc0RpYWxvZ0RhdGEgfSBmcm9tICcuLi8uLi9kaWFsb2dzL2xpc3QtY29sdW1ucy9saXN0LWNvbHVtbnMuY29tcG9uZW50JztcbmltcG9ydCB7XG4gIENvbXBvbmVudERhdGEsXG4gIENvbXBvbmVudERhdGFTdGF0ZSxcbiAgQ29tcG9uZW50U2V0dGluZ3MsXG4gIEtwaUNvbmZpZyxcbiAgUmVwb3J0Q29tcG9uZW50IGFzIFJlcG9ydENvbXBvbmVudE1vZGVsLFxuICBSZXBvcnRGaWx0ZXJHcm91cCxcbn0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGtwaUNhcmRTZXR0aW5ncywgc2FtZUtwaUNhcmRTZXR0aW5ncyB9IGZyb20gJy4uLy4uL2twaS1jYXJkJztcbmltcG9ydCB7IGNvbXBvbmVudFBhZGRpbmdDc3MgfSBmcm9tICcuLi8uLi9sYXlvdXQnO1xuaW1wb3J0IHsgbGlzdEhpZGVhYmxlQ29sdW1ucyB9IGZyb20gJy4uLy4uL2xpc3QtY29uZmlnJztcbmltcG9ydCB7XG4gIExJU1RfU0VBUkNIX0lURU0sIGZpbHRlckl0ZW1Gb3JHcm91cCwgZ3JvdXBWYWx1ZXNGcm9tUXVlcnksIGxpc3RTZWFyY2hJdGVtLFxufSBmcm9tICcuLi8uLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcbmltcG9ydCB7IG1vdmVkR3JvdXBWYWx1ZXMsIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3JlcG9ydC1maWx0ZXItc3RhdGUuc2VydmljZSc7XG5pbXBvcnQgeyBDb21wb25lbnRDaGFydENvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudC1jaGFydC9jb21wb25lbnQtY2hhcnQuY29tcG9uZW50JztcbmltcG9ydCB7IENvbXBvbmVudEtwaUNvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudC1rcGkvY29tcG9uZW50LWtwaS5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ29tcG9uZW50TGlzdENvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudC1saXN0L2NvbXBvbmVudC1saXN0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb21wb25lbnRUZXh0Q29tcG9uZW50IH0gZnJvbSAnLi4vY29tcG9uZW50LXRleHQvY29tcG9uZW50LXRleHQuY29tcG9uZW50JztcbmltcG9ydCB7IFRleHRUb2tlbkNvbnRleHQgfSBmcm9tICcuLi8uLi90ZXh0JztcbmltcG9ydCB7IE5PX1ZBTFVFX0tFWVMsIGlzRHJhd24sIHZhbHVlS2V5cyB9IGZyb20gJy4uLy4uL3ZhbHVlcyc7XG5pbXBvcnQgeyBDYW52YXNTbmFwcGVyLCBQWF9QRVJfSU5DSCB9IGZyb20gJy4uL3JlcG9ydC1jYW52YXMvcmVwb3J0LWNhbnZhcy5jb21wb25lbnQnO1xuXG5cbi8vIFJlc2l6ZSBoYW5kbGVzLCBuYW1lZCBieSBjb21wYXNzIGRpcmVjdGlvbi5cbmNvbnN0IEhBTkRMRVMgPSBbJ253JywgJ24nLCAnbmUnLCAnZScsICdzZScsICdzJywgJ3N3JywgJ3cnXSBhcyBjb25zdDtcbnR5cGUgSGFuZGxlID0gdHlwZW9mIEhBTkRMRVNbbnVtYmVyXTtcblxuY29uc3QgTUlOX1cgPSAwLjY7IC8vIGluY2hlc1xuY29uc3QgTUlOX0ggPSAwLjQ7IC8vIGluY2hlc1xuXG4vLyBUd28gcHJlc3NlcyBvbiBhIHRleHQgYmxvY2sgdGhpcyBjbG9zZSB0b2dldGhlciBvcGVuIGl0cyBlZGl0b3IuIERldGVjdGVkXG4vLyBoZXJlIHJhdGhlciB0aGFuIHdpdGggYSBkYmxjbGljayBsaXN0ZW5lciBiZWNhdXNlIHRoZSBkcmFnIGxvb3AgY2xhaW1zIHRoZVxuLy8gcG9pbnRlciBvbiBldmVyeSBwcmVzcywgYW5kIGEgYnJvd3NlciBpcyBub3Qgb2JsaWdlZCB0byBkZWxpdmVyIGRibGNsaWNrXG4vLyB0aHJvdWdoIGEgY2FwdHVyZWQsIGRlZmF1bHQtcHJldmVudGVkIHBvaW50ZXIuXG5jb25zdCBET1VCTEVfUFJFU1NfTVMgPSA0MDA7XG5cbi8vIE9uZSBjb21wb25lbnQgb24gdGhlIHBhZ2U6IHRpdGxlIGJhciwgdGhlIHR5cGUtc3BlY2lmaWMgYm9keSAoY2hhcnQgfCBsaXN0XG4vLyB8IGtwaSksIGEgbWVudSAoc2V0dGluZ3MsIGZpbHRlciB0b2dnbGVzLCBleHBvcnQpIOKAlCBhbmQgdGhlIGVkaXRpbmdcbi8vIGludGVyYWN0aW9uczogY2xpY2sgc2VsZWN0czsgdGhlIHNlbGVjdGlvbiBmcmFtZSBzaG93cyA4IHJlc2l6ZSBoYW5kbGVzO1xuLy8gZHJhZ2dpbmcgdGhlIGJvZHkgbW92ZXMgd2l0aCBzbWFydCBhbGlnbm1lbnQgZ3VpZGVzICh2aWEgdGhlIGNhbnZhc1xuLy8gc25hcHBlcik7IGV2ZXJ5dGhpbmcgd29ya3MgYXQgYW55IHpvb20gKHBpeGVsIGRlbHRhcyDDtyB6b29twrc5NiDihpIgaW5jaGVzKS5cbi8vXG4vLyBDaGFydHMgYW5kIEtQSXMgZmV0Y2ggdGhlaXIgb3duIGRhdGEgaGVyZTsgbGlzdHMgZmV0Y2ggaW5zaWRlXG4vLyBDb21wb25lbnRMaXN0Q29tcG9uZW50IHRocm91Z2ggRnNMaXN0IHBhZ2luZy5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1yZXBvcnQtY29tcG9uZW50JyxcbiAgdGVtcGxhdGVVcmw6ICcuL3JlcG9ydC1jb21wb25lbnQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9yZXBvcnQtY29tcG9uZW50LmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgTWF0SWNvbixcbiAgICBNYXRJY29uQnV0dG9uLFxuICAgIE1hdFRvb2x0aXAsXG4gICAgRnNGaWx0ZXJNb2R1bGUsXG4gICAgRnNNZW51TW9kdWxlLFxuICAgIENvbXBvbmVudENoYXJ0Q29tcG9uZW50LFxuICAgIENvbXBvbmVudEtwaUNvbXBvbmVudCxcbiAgICBDb21wb25lbnRMaXN0Q29tcG9uZW50LFxuICAgIENvbXBvbmVudFRleHRDb21wb25lbnQsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIFJlcG9ydENvbXBvbmVudENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBASW5wdXQoKSBwdWJsaWMgcmVwb3J0SWQ6IG51bWJlcjtcbiAgQElucHV0KCkgcHVibGljIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50TW9kZWw7XG4gIEBJbnB1dCgpIHB1YmxpYyBncm91cHM6IE1hcDxudW1iZXIsIFJlcG9ydEZpbHRlckdyb3VwPjtcbiAgQElucHV0KCkgcHVibGljIGVkaXRNb2RlID0gZmFsc2U7XG4gIC8vIFRoZSBjYW52YXMgem9vbSDigJQgY29udmVydHMgb24tc2NyZWVuIHBpeGVsIGRlbHRhcyBiYWNrIHRvIGluY2hlcy5cbiAgQElucHV0KCkgcHVibGljIHpvb20gPSAxO1xuICBASW5wdXQoKSBwdWJsaWMgc25hcHBlcjogQ2FudmFzU25hcHBlciB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBwdWJsaWMgc2VsZWN0ZWQgPSBmYWxzZTtcblxuICBAT3V0cHV0KCkgcHVibGljIHNlbGVjdENvbXBvbmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuICBAT3V0cHV0KCkgcHVibGljIHBvc2l0aW9uQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBjb21wb25lbnRJZDogbnVtYmVyIH0gJiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+PigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9wZW5TZXR0aW5ncyA9IG5ldyBFdmVudEVtaXR0ZXI8UmVwb3J0Q29tcG9uZW50TW9kZWw+KCk7XG5cbiAgLy8gV2hhdCBhIHRleHQgYmxvY2sncyB7e3Rva2Vuc319IGZpbGwgd2l0aCBvbiB0aGUgcGFnZSBpdCBpcyBkcmF3biBvbi5cbiAgcHVibGljIHJlYWRvbmx5IHRva2VucyA9IGlucHV0PFRleHRUb2tlbkNvbnRleHQ+KHsgcGFnZU51bWJlcjogMSwgcGFnZU5hbWU6ICcnLCByZXBvcnROYW1lOiAnJyB9KTtcblxuICAvLyBUaGUgdmFsdWUga2V5cyB0aGUgb3RoZXIgdGV4dCBibG9ja3Mgb2YgYSB0ZXh0J3MgbGF5ZXIgc2hvdywgcmVhZCBieSB0aGVcbiAgLy8gY2FudmFzIHdoZW4gdGhlIHRleHQncyBlZGl0b3IgYXNrcy5cbiAgcHVibGljIHJlYWRvbmx5IHZhbHVlS2V5c0Vsc2V3aGVyZSA9IGlucHV0PCgodGV4dDogUmVwb3J0Q29tcG9uZW50TW9kZWwpID0+IFJlYWRvbmx5U2V0PHN0cmluZz4pIHwgbnVsbD4obnVsbCk7XG5cbiAgLy8gQSB0ZXh0IGJsb2NrIHdhcyBkZWxldGVkIGZyb20gaXRzIG1lbnUg4oCUIHRoZSBjYW52YXMgZHJvcHMgaXQuXG4gIHB1YmxpYyByZWFkb25seSByZW1vdmVkID0gb3V0cHV0PG51bWJlcj4oKTtcblxuICAvLyBBIHZhbHVlJ3Mgc2V0dGluZ3Mgd2VyZSBhc2tlZCBmb3IgZnJvbSBpdHMgY2hpcCBpbiB0aGUgdGV4dCwgYnkgdGhlXG4gIC8vIHZhbHVlJ3Mga2V5LiBUaGUgY2FudmFzIG9wZW5zIHRoZW0uXG4gIHB1YmxpYyByZWFkb25seSB2YWx1ZVNldHRpbmdzID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICAvLyBUaGUgdGV4dCdzIGh0bWwgd2FzIHNhdmVkLiBFbWl0dGVkIG9uIHRoZSByZXNwb25zZSwgc28gdGhlIHNlcnZlciBhbHJlYWR5XG4gIC8vIGhvbGRzIHRoZSBodG1sIHdoZW4gdGhlIGNhbnZhcyByZWFkcyB0aGUgdmFsdWVzIGl0IHNob3dzLlxuICBwdWJsaWMgcmVhZG9ubHkgdGV4dFNhdmVkID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICAvLyBEZWxldGluZyB0aGUgdGV4dCBhbHNvIGRlbGV0ZWQgdGhlIHZhbHVlcyBubyBvdGhlciB0ZXh0IG9uIGl0cyBwYWdlIHJlYWRzLFxuICAvLyBieSBpZC4gVGhlIGNhbnZhcyBoYXMgdGhlIHJlcG9ydCByZWxvYWRlZC5cbiAgcHVibGljIHJlYWRvbmx5IHZhbHVlc1JlbW92ZWQgPSBvdXRwdXQ8bnVtYmVyW10+KCk7XG5cbiAgLy8gVGhlIHRleHQgYmxvY2sncyBlZGl0b3IgaXMgb3BlbiAoZG91YmxlLXByZXNzIGluIGVkaXQgbW9kZSkuIENsb3NlZCBieSBmb2N1c1xuICAvLyBsZWF2aW5nIHRoZSBibG9jaywgYnkgZGVzZWxlY3RpbmcgaXQsIG9yIGJ5IGxlYXZpbmcgZWRpdCBtb2RlIOKAlCBlYWNoIG9mXG4gIC8vIHdoaWNoIHNhdmVzLlxuICBwdWJsaWMgcmVhZG9ubHkgdGV4dEVkaXRpbmcgPSBzaWduYWwoZmFsc2UpO1xuICAvLyBBIHRleHQgYmxvY2sncyBodG1sIGFzIGxhc3Qgc2F2ZWQgaGVyZTsgbnVsbCB1bnRpbCB0aGVuLCBzbyB0aGUgYmxvY2tcbiAgLy8gc2hvd3MgaXRzIHN0b3JlZCBodG1sLlxuICBwdWJsaWMgcmVhZG9ubHkgdGV4dEh0bWwgPSBzaWduYWw8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG5cbiAgLy8gV2hhdCB0aGUgb3RoZXIgdGV4dCBibG9ja3Mgb2YgdGhpcyB0ZXh0J3MgbGF5ZXIgc2hvdywgZm9yIGl0cyBlZGl0b3Inc1xuICAvLyBub3RpY2UuIFN0YWJsZSwgc28gdGhlIHRleHQgYmxvY2sncyBpbnB1dCBuZXZlciBjaGFuZ2VzOyBpdCBhc2tzIHdoZW4gYW5cbiAgLy8gZWRpdCB0YWtlcyBhIHZhbHVlJ3MgbGFzdCBjaGlwIG91dC5cbiAgcHVibGljIHJlYWRvbmx5IHNob3duRWxzZXdoZXJlID0gKCk6IFJlYWRvbmx5U2V0PHN0cmluZz4gPT5cbiAgICB0aGlzLnZhbHVlS2V5c0Vsc2V3aGVyZSgpPy4odGhpcy5jb21wb25lbnQpID8/IE5PX1ZBTFVFX0tFWVM7XG5cbiAgQFZpZXdDaGlsZChDb21wb25lbnRDaGFydENvbXBvbmVudClcbiAgcHVibGljIGNoYXJ0Q29tcG9uZW50OiBDb21wb25lbnRDaGFydENvbXBvbmVudDtcblxuICAvLyBSZXNpemUgaGFuZGxlcyBieSB0eXBlOiBhIGZpeGVkLWhlaWdodCBjb21wb25lbnQgKGNoYXJ0L2xpc3QpXG4gIC8vIGdldHMgYWxsIGVpZ2h0IChyZXNpemUgd2lkdGggQU5EIGhlaWdodCk7IGFuIGF1dG8taGVpZ2h0IG9uZSAoa3BpKSBnZXRzXG4gIC8vIG9ubHkgdGhlIHNpZGUgaGFuZGxlcyBzaW5jZSBpdHMgaGVpZ2h0IGZpdHMgaXRzIGNvbnRlbnQgYW5kIGNhbid0IGJlIHNldC5cbiAgcHVibGljIGdldCByZXNpemVIYW5kbGVzKCk6IHJlYWRvbmx5IEhhbmRsZVtdIHtcbiAgICByZXR1cm4gdGhpcy5faGVpZ2h0QXV0byA/IFsnZScsICd3J10gOiBIQU5ETEVTO1xuICB9XG5cbiAgLy8gVGhlIGNvbXBvbmVudCdzIGhlYWRlciBJUyBhbiBmcy1maWx0ZXI6IGhlYWRpbmcgdGVtcGxhdGUgPSBpdHMgdGl0bGUgKGFuZFxuICAvLyB0aGUgZHJhZyBoYW5kbGUpLCBhY3Rpb25zID0gdGhlIFNldHRpbmdzIC8gZmlsdGVyLXRvZ2dsZXMgLyBFeHBvcnQgbWVudSxcbiAgLy8gaXRlbXMgPSBpdHMgY29tcG9uZW50LWxldmVsIGZpbHRlciBncm91cHMsIGZvciBldmVyeSBjb21wb25lbnQgdHlwZSwgbGlzdHNcbiAgLy8gaW5jbHVkZWQsIHBsdXMgYSBsaXN0J3Mgc2VhcmNoIGJveC4gUmVidWlsdCB3aGVuIGEgZmlsdGVyIHRvZ2dsZSBjaGFuZ2VzIHdoaWNoIGdyb3VwcyBzaG93LFxuICAvLyBhbmQgd2hlbiB0aGUgc2V0dGluZ3MgZGlhbG9nIGNoYW5nZXMgdGhlIHRpdGxlIG9yIHBhZGRpbmc6IHNldHRpbmcgaXRcbiAgLy8gcmVwYWludHMgdGhlIGhlYWRlciBhbmQgYm9keS5cbiAgcHVibGljIHJlYWRvbmx5IGZpbHRlckNvbmZpZyA9IHNpZ25hbDxGaWx0ZXJDb25maWcgfCBudWxsPihudWxsKTtcblxuICBwdWJsaWMgcmVhZG9ubHkgZGF0YSA9IHNpZ25hbDxDb21wb25lbnREYXRhIHwgbnVsbD4obnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSBsb2FkaW5nID0gc2lnbmFsKGZhbHNlKTtcbiAgcHVibGljIHJlYWRvbmx5IGVycm9yID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3RleHQgPSB2aWV3Q2hpbGQoQ29tcG9uZW50VGV4dENvbXBvbmVudCk7XG4gIHByaXZhdGUgX3JlZnJlc2gkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSBfZmlsdGVyU3RhdGUgPSBpbmplY3QoUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBfcHJvY2VzcyA9IGluamVjdChGc1Byb2Nlc3MpO1xuICBwcml2YXRlIF9tZXNzYWdlID0gaW5qZWN0KEZzTWVzc2FnZSk7XG4gIHByaXZhdGUgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgX2RpYWxvZyA9IGluamVjdChNYXREaWFsb2cpO1xuICBwcml2YXRlIF9sYXN0UHJlc3MgPSAwO1xuICBwcml2YXRlIF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuICBwcml2YXRlIF96b25lID0gaW5qZWN0KE5nWm9uZSk7XG4gIHByaXZhdGUgX2hvc3Q6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+ID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLl9idWlsZEZpbHRlckNvbmZpZygpO1xuXG4gICAgLy8gTGlzdHMgZmV0Y2ggdGhyb3VnaCBGc0xpc3Q7IHRleHQgaGFzIG5vdGhpbmcgdG8gZmV0Y2gsIGFuZCBhIHZhbHVlIGlzXG4gICAgLy8gbmV2ZXIgZHJhd24gKGl0IHJlYWRzIGluc2lkZSB0ZXh0KS5cbiAgICBpZiAodGhpcy5jb21wb25lbnQudHlwZSAhPT0gJ2xpc3QnICYmICF0aGlzLmlzVGV4dCAmJiBpc0RyYXduKHRoaXMuY29tcG9uZW50KSkge1xuICAgICAgLy8gRGVib3VuY2VkIHNvIGEgcmFwaWQgZmlsdGVyIHN3ZWVwIGZpcmVzIG9uZSBxdWVyeSwgbm90IG9uZSBwZXIgY2hhbmdlLlxuICAgICAgdGhpcy5fcmVmcmVzaCRcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgZGVib3VuY2VUaW1lKDMwMCksXG4gICAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpLFxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fbG9hZCgpKTtcblxuICAgICAgdGhpcy5fZmlsdGVyU3RhdGUuY2hhbmdlc0Zvcih0aGlzLmNvbXBvbmVudClcbiAgICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuX3JlZnJlc2gkLm5leHQoKSk7XG5cbiAgICAgIC8vIEEgZ3JvdXAtYnkgY2hhbmdlIHJlLWJ1Y2tldHMgZXZlcnkgdGltZS1zZXJpZXMgY2hhcnQ7IGl0IGlzbid0IHNjb3BlZFxuICAgICAgLy8gdG8gYSBmaWx0ZXIgZ3JvdXAsIHNvIGl0IHJpZGVzIGl0cyBvd24gc3RyZWFtLlxuICAgICAgaWYgKHRoaXMuX2lzVGltZVNlcmllcykge1xuICAgICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5mcmVxdWVuY3lDaGFuZ2VzKClcbiAgICAgICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9yZWZyZXNoJC5uZXh0KCkpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9sb2FkKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gVGhlIHJlcG9ydCByZWxvYWRzIChlLmcuIGFmdGVyIHRoZSBzZXR0aW5ncyBkaWFsb2cgYWRkcy9tb3ZlcyBhIGZpbHRlcilcbiAgLy8gaGFuZCB0aGlzIGluc3RhbmNlIGZyZXNoIGBjb21wb25lbnRgL2Bncm91cHNgIGlucHV0cyB3aXRob3V0IHJlLXJ1bm5pbmdcbiAgLy8gbmdPbkluaXQuIFJlYnVpbGQgdGhlIGhlYWRlciBjb25maWcgc28gdGhlIGlubGluZSBjb21wb25lbnQtZmlsdGVyIHN0cmlwXG4gIC8vIHJlZmxlY3RzIHRoZSBuZXcgZmlsdGVyczsgdGhlIHRlbXBsYXRlIHJlY3JlYXRlcyB0aGUgZnMtZmlsdGVyIHZpYVxuICAvLyBgZmlsdGVyS2V5YCBzbyBpdCBhY3R1YWxseSByZS1yZWFkcyB0aGlzIGNvbmZpZy5cbiAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAvLyBDbGlja2luZyBhd2F5IChkZXNlbGVjdCkgb3IgbGVhdmluZyBlZGl0IG1vZGUgY2xvc2VzIGFuIG9wZW4gdGV4dCBlZGl0b3IsXG4gICAgLy8gd2hpY2ggaXMgd2hhdCBzYXZlcyBpdC5cbiAgICBpZiAoKGNoYW5nZXMuc2VsZWN0ZWQgJiYgIXRoaXMuc2VsZWN0ZWQpIHx8IChjaGFuZ2VzLmVkaXRNb2RlICYmICF0aGlzLmVkaXRNb2RlKSkge1xuICAgICAgdGhpcy50ZXh0RWRpdGluZy5zZXQoZmFsc2UpO1xuICAgIH1cblxuICAgIC8vIEEgbmV3IGNvbXBvbmVudCBvYmplY3QgY2FycmllcyBpdHMgb3duIHN0b3JlZCBodG1sLlxuICAgIGlmIChjaGFuZ2VzLmNvbXBvbmVudCAmJiAhY2hhbmdlcy5jb21wb25lbnQuZmlyc3RDaGFuZ2UpIHtcbiAgICAgIHRoaXMudGV4dEh0bWwuc2V0KG51bGwpO1xuICAgIH1cblxuICAgIGNvbnN0IGZpbHRlcnNDaGFuZ2VkID0gKGNoYW5nZXMuY29tcG9uZW50ICYmICFjaGFuZ2VzLmNvbXBvbmVudC5maXJzdENoYW5nZSlcbiAgICAgIHx8IChjaGFuZ2VzLmdyb3VwcyAmJiAhY2hhbmdlcy5ncm91cHMuZmlyc3RDaGFuZ2UpO1xuXG4gICAgaWYgKGZpbHRlcnNDaGFuZ2VkKSB7XG4gICAgICB0aGlzLl9idWlsZEZpbHRlckNvbmZpZygpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGZzLWZpbHRlciByZWFkcyBpdHMgY29uZmlnIG9ubHkgb25jZSBhdCBpbml0LCBzbyB0aGUgaGVhZGVyIGlzIGtleWVkIG9uIHdoYXRcbiAgLy8gaXQgcmVuZGVyczogdGhlIHNldCBvZiBjb21wb25lbnQtbGV2ZWwgZmlsdGVyIGdyb3VwcyBBTkQgdGhlIHRpdGxlLCB3aGljaFxuICAvLyBsaXZlcyBpbiBmcy1maWx0ZXIncyBoZWFkaW5nIHRlbXBsYXRlLiBmcy1maWx0ZXIgaXMgT25QdXNoIGFuZCB0aGUgaGVhZGluZyBpc1xuICAvLyByZW5kZXJlZCBpbnNpZGUgSVRTIHZpZXcsIHNvIG1hcmtpbmcgdGhpcyBjb21wb25lbnQgZG9lcyBub3QgcmVwYWludCB0aGVcbiAgLy8gdGl0bGUg4oCUIHJlY3JlYXRpbmcgdGhlIGJsb2NrIGRvZXMuXG4gIHB1YmxpYyBnZXQgZmlsdGVyS2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFtcbiAgICAgIHRoaXMuY29tcG9uZW50LnRpdGxlLFxuICAgICAgLi4udGhpcy5jb21wb25lbnRGaWx0ZXJHcm91cHMubWFwKChncm91cCkgPT4gYCR7Z3JvdXAuaWR9OiR7Z3JvdXAubGV2ZWx9YCksXG4gICAgXS5qb2luKCd8Jyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGlzVGV4dCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnQudHlwZSA9PT0gJ3RleHQnO1xuICB9XG5cbiAgLy8gT3BlbiB0aGUgdGV4dCBlZGl0b3IgaW4gcGxhY2UuXG4gIHB1YmxpYyBlZGl0VGV4dCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZWRpdE1vZGUgfHwgIXRoaXMuaXNUZXh0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zZWxlY3RDb21wb25lbnQuZW1pdCh0aGlzLmNvbXBvbmVudC5pZCk7XG4gICAgdGhpcy50ZXh0RWRpdGluZy5zZXQodHJ1ZSk7XG4gIH1cblxuICAvLyBUYWtlIGEgZGVsZXRlZCB2YWx1ZSdzIGNoaXBzIG91dCBvZiB0aGUgdGV4dCdzIG9wZW4gZWRpdG9yLlxuICBwdWJsaWMgcmVtb3ZlVmFsdWUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl90ZXh0KCk/LnJlbW92ZVZhbHVlKGtleSk7XG4gIH1cblxuICAvLyBUaGUgZWRpdG9yIGNsb3NlZCB3aXRoIGNoYW5nZWQgaHRtbC4gS2VwdCBsb2NhbGx5IGF0IG9uY2Ugc28gdGhlIGJsb2NrXG4gIC8vIHJlLXJlbmRlcnMgd2hhdCB3YXMgdHlwZWQsIHRoZW4gcmVwbGFjZWQgYnkgd2hhdCB0aGUgc2VydmVyIHN0b3JlZDogaXRcbiAgLy8gcmVidWlsZHMgdGhlIGh0bWwgZnJvbSBpdHMgYWxsb3dsaXN0IGFuZCBkcm9wcyBhbnkgdmFsdWUgdG9rZW4gaXRzIHBhZ2UgaGFzXG4gIC8vIG5vIHZhbHVlIGZvciwgc28gdGhlIGJsb2NrIG5ldmVyIGhvbGRzIGEgdG9rZW4gdGhlIHNlcnZlciBkb2Vzbid0LlxuICBwdWJsaWMgb25UZXh0U2F2ZWQoaHRtbDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5fc2V0VGV4dEh0bWwoaHRtbCk7XG4gICAgdGhpcy5fcmVwb3J0RGF0YS51cGRhdGVDb21wb25lbnQodGhpcy5yZXBvcnRJZCwgdGhpcy5jb21wb25lbnQuaWQsIHsgaHRtbCB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcCgocmVzcG9uc2UpID0+ICh0eXBlb2YgcmVzcG9uc2U/LmNvbmZpZz8uaHRtbCA9PT0gJ3N0cmluZycgPyByZXNwb25zZS5jb25maWcuaHRtbCBhcyBzdHJpbmcgOiBodG1sKSksXG4gICAgICAgIHRhcCgoc3RvcmVkKSA9PiB7XG4gICAgICAgICAgdGhpcy5fc2V0VGV4dEh0bWwoc3RvcmVkKTtcbiAgICAgICAgICB0aGlzLnRleHRTYXZlZC5lbWl0KHN0b3JlZCk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvLyBUaGUgc2VydmVyIGRlbGV0ZXMgdGhlIHRleHQgYW5kIHRoZW4gZXZlcnkgdmFsdWUgb24gaXRzIHBhZ2UgdGhhdCBubyBvdGhlclxuICAvLyB0ZXh0IHNob3dzLCBhbmQgYW5zd2VycyB3aXRoIHRoZWlyIGlkcy5cbiAgcHVibGljIGRlbGV0ZVRleHQoKTogdm9pZCB7XG4gICAgY29uc3QgdmFsdWVzTm90ZSA9IHZhbHVlS2V5cyh0aGlzLmNvbXBvbmVudC5jb25maWc/Lmh0bWwpLmxlbmd0aFxuICAgICAgPyAnIFZhbHVlcyBubyBvdGhlciB0ZXh0IG9uIHRoaXMgcGFnZSB1c2VzIGFyZSBkZWxldGVkIHdpdGggaXQuJ1xuICAgICAgOiAnJztcblxuICAgIHRoaXMuX3Byb21wdC5jb25maXJtKHtcbiAgICAgIHRpdGxlOiAnQ29uZmlybScsXG4gICAgICB0ZW1wbGF0ZTogYEFyZSB5b3Ugc3VyZSB5b3Ugd291bGQgbGlrZSB0byBkZWxldGUgdGhpcyB0ZXh0PyR7dmFsdWVzTm90ZX1gLFxuICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlQ29tcG9uZW50KHRoaXMucmVwb3J0SWQsIHRoaXMuY29tcG9uZW50LmlkKSksXG4gICAgICAgIHRhcCgocmVzcG9uc2U6IHsgcmVtb3ZlZFZhbHVlcz86IG51bWJlcltdIH0pID0+IHtcbiAgICAgICAgICBpZiAocmVzcG9uc2U/LnJlbW92ZWRWYWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXNSZW1vdmVkLmVtaXQocmVzcG9uc2UucmVtb3ZlZFZhbHVlcyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMucmVtb3ZlZC5lbWl0KHRoaXMuY29tcG9uZW50LmlkKTtcbiAgICAgICAgfSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdHJ1bmNhdGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMuZGF0YSgpPy50cnVuY2F0ZWQ7XG4gIH1cblxuICAvLyBDb250ZW50IHBhZGRpbmcgKHRoZSBjYW52YXMgem9vbSBzY2FsZXMgdGhlIHBhZ2UgYXMgYSB3aG9sZSkuIEVhY2ggZWRnZVxuICAvLyBkZWZhdWx0cyB0byAxLzhcIi5cbiAgcHVibGljIGdldCBib2R5UGFkZGluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiBjb21wb25lbnRQYWRkaW5nQ3NzKHRoaXMuY29tcG9uZW50KTtcbiAgfVxuXG4gIC8vIFRoZSBjb21wb25lbnQtbGV2ZWwgZmlsdGVyIGdyb3VwcyB0aGF0IHNob3VsZCByZW5kZXIgYXMgYW4gaW5saW5lIGNvbnRyb2xcbiAgLy8gc3RyaXAgb24gVEhJUyBjb21wb25lbnQ6IGEgZ3JvdXAgaXMgaW5jbHVkZWQgd2hlbiBpdCdzIGxldmVsPWNvbXBvbmVudCBhbmRcbiAgLy8gaGFzIGFuIGVuYWJsZWQsIHNlc3Npb24tb24gZmlsdGVyIGhlcmUuIFJlcG9ydC1sZXZlbCBncm91cHMgbGl2ZSBpbiB0aGVcbiAgLy8gdG9wIGJhciBpbnN0ZWFkLiBMaXN0cyB1c2UgdGhpcyBzdHJpcCBsaWtlIGNoYXJ0cyBkbzogYSB2YWx1ZSBzZXQgaGVyZSBpc1xuICAvLyB0aGUgZ3JvdXAncyB2YWx1ZSwgc28gaXQgcmVhY2hlcyBldmVyeSBjb21wb25lbnQgaW4gdGhlIGdyb3VwLlxuICBwdWJsaWMgZ2V0IGNvbXBvbmVudEZpbHRlckdyb3VwcygpOiBSZXBvcnRGaWx0ZXJHcm91cFtdIHtcbiAgICBpZiAoIXRoaXMuZ3JvdXBzKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgZ3JvdXBJZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiB0aGlzLmNvbXBvbmVudC5maWx0ZXJzID8/IFtdKSB7XG4gICAgICBpZiAoIWZpbHRlci5lbmFibGVkIHx8IHRoaXMuX2ZpbHRlclN0YXRlLmlzRmlsdGVyRGlzYWJsZWQoZmlsdGVyLmlkKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5ncm91cHMuZ2V0KGZpbHRlci5maWx0ZXJHcm91cElkKTtcbiAgICAgIGlmIChncm91cCAmJiAoZ3JvdXAubGV2ZWwgPT09ICdjb21wb25lbnQnIHx8IGdyb3VwLmxldmVsID09PSAnYm90aCcpKSB7XG4gICAgICAgIGdyb3VwSWRzLmFkZChncm91cC5pZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFsuLi5ncm91cElkc10ubWFwKChpZCkgPT4gdGhpcy5ncm91cHMuZ2V0KGlkKSkuZmlsdGVyKEJvb2xlYW4pO1xuICB9XG5cbiAgcHVibGljIHNldHRpbmdzKCk6IHZvaWQge1xuICAgIHRoaXMub3BlblNldHRpbmdzLmVtaXQodGhpcy5jb21wb25lbnQpO1xuICB9XG5cbiAgLy8gV2hldGhlciB0aGUgbWVudSBvZmZlcnMgQ29sdW1uczogYSBwbGFpbiBsaXN0IHdpdGggbW9yZSB0aGFuIG9uZVxuICAvLyBjb25maWd1cmVkIGNvbHVtbi4gQSBjcm9zcy10YWIncyBjb2x1bW5zIGNvbWUgYW5kIGdvIHdpdGggdGhlIGRhdGEuXG4gIHB1YmxpYyBnZXQgaGlkZXNDb2x1bW5zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudC50eXBlID09PSAnbGlzdCcgJiYgbGlzdEhpZGVhYmxlQ29sdW1ucyh0aGlzLmNvbXBvbmVudC5jb25maWcpLmxlbmd0aCA+IDE7XG4gIH1cblxuICAvLyBXaGljaCBvZiBhIHBsYWluIGxpc3QncyBjb2x1bW5zIHNob3cuIFRoZSBjaG9pY2UgaXMgdGhlIHZpZXdlcidzIChrZXB0IGluXG4gIC8vIHRoZSBVUkwsIG5ldmVyIHNhdmVkIHRvIHRoZSByZXBvcnQpLCBhbmQgdGhlIGxpc3QgaGlkZXMgdGhlIGNvbHVtbnMgaW5cbiAgLy8gcGxhY2UsIHdpdGggbm8gcmVmZXRjaC5cbiAgcHVibGljIGNob29zZUNvbHVtbnMoKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1ucyA9ICh0aGlzLmNvbXBvbmVudC5jb25maWc/LmNvbHVtbnMgPz8gW10pXG4gICAgICAubWFwKChjb2x1bW4pID0+ICh7IGNvbHVtbjogY29sdW1uLmNvbHVtbiwgbGFiZWw6IGNvbHVtbi5sYWJlbCB8fCBjb2x1bW4uY29sdW1uIH0pKTtcblxuICAgIHRoaXMuX2RpYWxvZy5vcGVuPExpc3RDb2x1bW5zQ29tcG9uZW50LCBMaXN0Q29sdW1uc0RpYWxvZ0RhdGEsIHN0cmluZ1tdPihMaXN0Q29sdW1uc0NvbXBvbmVudCwge1xuICAgICAgZGF0YTogeyBjb2x1bW5zLCBoaWRkZW46IFsuLi50aGlzLl9maWx0ZXJTdGF0ZS5oaWRkZW5Db2x1bW5zKHRoaXMuY29tcG9uZW50LmlkKV0gfSxcbiAgICAgIHdpZHRoOiAnNDAwcHgnLFxuICAgICAgbWF4V2lkdGg6ICc5NXZ3JyxcbiAgICAgIGF1dG9Gb2N1czogZmFsc2UsXG4gICAgfSlcbiAgICAgIC5hZnRlckNsb3NlZCgpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKChoaWRkZW4pID0+IHtcbiAgICAgICAgLy8gQ2FuY2VsIGNsb3NlcyB3aXRoIG5vdGhpbmcsIHdoaWNoIGNoYW5nZXMgbm90aGluZy5cbiAgICAgICAgaWYgKGhpZGRlbikge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLnNldEhpZGRlbkNvbHVtbnModGhpcy5jb21wb25lbnQuaWQsIGhpZGRlbik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gUHJlc2VudGF0aW9uIHNldHRpbmdzIHNhdmVkIGZyb20gdGhlIHNldHRpbmdzIGRpYWxvZy4gVGl0bGUgYW5kIHBhZGRpbmcgYXJlXG4gIC8vIG5vdCBwYXJ0IG9mIHRoZSBxdWVyeSwgc28gdGhlIGRhdGEgYWxyZWFkeSBmZXRjaGVkIHN0aWxsIHN0YW5kcyDigJQgdGhpcyBvbmx5XG4gIC8vIHJlcGFpbnRzLiBUaGUgaGVhZGVyIGNvbmZpZyBpcyByZWJ1aWx0IGJlY2F1c2UgYGZpbHRlcktleWAgY2hhbmdlcyB3aXRoIHRoZVxuICAvLyB0aXRsZSBhbmQgcmVjcmVhdGVzIHRoZSBmcy1maWx0ZXIgYmxvY2sgYXJvdW5kIGl0OyBzZXR0aW5nIHRoZSBjb25maWcgc2lnbmFsXG4gIC8vIGlzIGFsc28gd2hhdCByZXBhaW50cyB0aGUgbmV3IHBhZGRpbmcuIFRoZSBjaGFydCBmb2xsb3dzIGl0cyBib3ggb24gaXRzIG93blxuICAvLyAobmd4LWVjaGFydHMgb2JzZXJ2ZXMgdGhlIGhvc3QpLCBzbyBub3RoaW5nIGlzIHRvbGQgdG8gcmVzaXplLiBBIEtQSSdzIGNhcmRcbiAgLy8ga2V5cyBhcmUgZGlmZmVyZW50OiBzZXR0aW5ncy5rcGkgY2FycmllcyB0aGUga2V5cyB0aGUgc2VydmVyIHNhdmVkIChuZXZlclxuICAvLyB0aGUgb25lcyB0aGUgZGlhbG9nIHNlbnQpLCBhbmQgdGhlIHNlcnZlciBzZW5kcyB0aGUgdGFyZ2V0J3MgcHJvZ3Jlc3MgYW5kXG4gIC8vIHRoZSBzcGFya2xpbmUncyBwb2ludHMgd2l0aCB0aGUgZGF0YSwgc28gYSBjaGFuZ2UgdG8gdGhlbSByZWxvYWRzIGl0LlxuICBwdWJsaWMgYXBwbHlTZXR0aW5ncyhzZXR0aW5nczogQ29tcG9uZW50U2V0dGluZ3MpOiB2b2lkIHtcbiAgICBjb25zdCBjYXJkQ2hhbmdlZCA9ICEhc2V0dGluZ3Mua3BpXG4gICAgICAmJiAhc2FtZUtwaUNhcmRTZXR0aW5ncyhzZXR0aW5ncy5rcGksIGtwaUNhcmRTZXR0aW5ncyh0aGlzLmNvbXBvbmVudC5jb25maWcgYXMgS3BpQ29uZmlnKSk7XG5cbiAgICB0aGlzLmNvbXBvbmVudC50aXRsZSA9IHNldHRpbmdzLnRpdGxlO1xuICAgIHRoaXMuY29tcG9uZW50LmNvbmZpZyA9IHsgLi4udGhpcy5jb21wb25lbnQuY29uZmlnLCBwYWRkaW5nOiBzZXR0aW5ncy5wYWRkaW5nLCAuLi4oc2V0dGluZ3Mua3BpID8/IHt9KSB9O1xuXG4gICAgdGhpcy5fYnVpbGRGaWx0ZXJDb25maWcoKTtcblxuICAgIGlmIChjYXJkQ2hhbmdlZCkge1xuICAgICAgdGhpcy5fcmVmcmVzaCQubmV4dCgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRoZSBDU1YgaXMgd2hhdCB0aGUgc2NyZWVuIHNob3dzLCBzbyBpdCBjYXJyaWVzIHRoZSBzYW1lIGludGVyYWN0aW9uIHN0YXRlXG4gIC8vIHRoZSBzY3JlZW4gZmV0Y2hlZCB3aXRoOiB0aGUgZ3JvdXAtYnkgZ3JhaW4gZm9yIGEgdGltZS1zZXJpZXMgY2hhcnQsIGFuZCB0aGVcbiAgLy8gdmlld2VyJ3MgaGVhZGVyIHNvcnQsIHNlYXJjaCBhbmQgaGlkZGVuIGNvbHVtbnMgZm9yIGEgbGlzdC4gQSBub3RlIHRoZVxuICAvLyBzZXJ2ZXIgcmV0dXJucyAodGhlIGZpbGUgd2FzIGN1dCkgaXMgc2hvd24gYmVmb3JlIHRoZSBkb3dubG9hZCBzdGFydHMsIHNvIGFcbiAgLy8gc2hvcnQgZmlsZSBuZXZlciBwYXNzZXMgZm9yIHRoZSB3aG9sZSByZXN1bHQuXG4gIHB1YmxpYyBleHBvcnRDc3YoKTogdm9pZCB7XG4gICAgY29uc3QgZmlsdGVycyA9IHRoaXMuX2ZpbHRlclN0YXRlLnJlc29sdmVGb3JDb21wb25lbnQodGhpcy5jb21wb25lbnQpO1xuICAgIGNvbnN0IHN0YXRlOiBDb21wb25lbnREYXRhU3RhdGUgPSB7fTtcblxuICAgIC8vIEEgZGVsaWJlcmF0ZSBtaXJyb3Igb2YgdGhlIHNlcnZlcidzIFJlcG9ydFF1ZXJ5UnVubmVyOjpfaXNUaW1lU2VyaWVzQ2hhcnQsXG4gICAgLy8gd2hpY2ggaXMgY2Fub25pY2FsIGFuZCBkcm9wcyB0aGUgZ3JhaW4gZm9yIGV2ZXJ5IG90aGVyIGNvbXBvbmVudC4gS2VwdCBzb1xuICAgIC8vIGEgcHJvZHVjdCBwaW5uZWQgdG8gYW4gb2xkZXIgZnJhbWV3b3JrIGRvZXMgbm90IHJlLWJ1Y2tldCBhIG5vbi10aW1lIGNoYXJ0LlxuICAgIGlmICh0aGlzLl9pc1RpbWVTZXJpZXMgJiYgdGhpcy5fZmlsdGVyU3RhdGUuZnJlcXVlbmN5KCkpIHtcbiAgICAgIHN0YXRlLmZyZXF1ZW5jeSA9IHRoaXMuX2ZpbHRlclN0YXRlLmZyZXF1ZW5jeSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGlzTGlzdCA9IHRoaXMuY29tcG9uZW50LnR5cGUgPT09ICdsaXN0JztcbiAgICBjb25zdCBzb3J0ID0gaXNMaXN0ID8gdGhpcy5fZmlsdGVyU3RhdGUubGlzdFNvcnQodGhpcy5jb21wb25lbnQuaWQpIDogbnVsbDtcbiAgICBpZiAoc29ydCkge1xuICAgICAgc3RhdGUuc29ydCA9IHNvcnQ7XG4gICAgfVxuXG4gICAgLy8gQSBzZWFyY2hlZCBsaXN0IGV4cG9ydHMgb25seSB0aGUgcm93cyB0aGUgc2VhcmNoIGxlYXZlcywgYXMgb24gc2NyZWVuLlxuICAgIGNvbnN0IHNlYXJjaCA9IGlzTGlzdCA/IHRoaXMuX2ZpbHRlclN0YXRlLmxpc3RTZWFyY2godGhpcy5jb21wb25lbnQuaWQpIDogbnVsbDtcbiAgICBpZiAoc2VhcmNoKSB7XG4gICAgICBzdGF0ZS5zZWFyY2ggPSBzZWFyY2g7XG4gICAgfVxuXG4gICAgLy8gVGhlIGNvbHVtbnMgdGhlIHZpZXdlciBoaWQgc3RheSBvdXQgb2YgdGhlIGZpbGUsIGFzIG9mZiB0aGUgc2NyZWVuLlxuICAgIGNvbnN0IGhpZGRlbkNvbHVtbnMgPSBpc0xpc3QgPyB0aGlzLl9maWx0ZXJTdGF0ZS5oaWRkZW5Db2x1bW5zKHRoaXMuY29tcG9uZW50LmlkKSA6IFtdO1xuICAgIGlmIChoaWRkZW5Db2x1bW5zLmxlbmd0aCkge1xuICAgICAgc3RhdGUuaGlkZGVuQ29sdW1ucyA9IFsuLi5oaWRkZW5Db2x1bW5zXTtcbiAgICB9XG5cbiAgICB0aGlzLl9wcm9jZXNzLmRvd25sb2FkKFxuICAgICAgYEV4cG9ydGluZyAke3RoaXMuY29tcG9uZW50LnRpdGxlID8/ICdjb21wb25lbnQnfWAsXG4gICAgICB0aGlzLl9yZXBvcnREYXRhLmV4cG9ydENvbXBvbmVudCh0aGlzLnJlcG9ydElkLCB0aGlzLmNvbXBvbmVudC5pZCwgZmlsdGVycywgc3RhdGUpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHRhcCgoeyBub3RlcyB9KSA9PiBub3Rlcz8ubGVuZ3RoICYmIHRoaXMuX21lc3NhZ2Uud2FybmluZyhub3Rlcy5qb2luKCcgJykpKSxcbiAgICAgICAgICBtYXAoKHsgdXJsIH0pID0+IHVybCksXG4gICAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIC8vIEFueSBpbnRlcmFjdGlvbiBpbnNpZGUgYSBjb21wb25lbnQgbXVzdCBuZXZlciBzdGFydCBhIGNhbnZhcyBwYW4gKHRoZVxuICAvLyB6b29tLXBhbiBob3N0IGxpc3RlbnMgZm9yIG1vdXNlZG93bi90b3VjaHN0YXJ0IGF0IHRoZSBjb250YWluZXIgbGV2ZWwpLlxuICBwdWJsaWMgc3RvcENhbnZhc1BhbihldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIHB1YmxpYyBvbkNvbXBvbmVudFBvaW50ZXJEb3duKGV2ZW50OiBQb2ludGVyRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBpZiAodGhpcy5lZGl0TW9kZSAmJiAhdGhpcy5zZWxlY3RlZCkge1xuICAgICAgdGhpcy5zZWxlY3RDb21wb25lbnQuZW1pdCh0aGlzLmNvbXBvbmVudC5pZCk7XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0gZWRpdC1tb2RlIGdlc3R1cmVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHB1YmxpYyBvbkRyYWdTdGFydChldmVudDogUG9pbnRlckV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVkaXRNb2RlIHx8IHRoaXMudGV4dEVkaXRpbmcoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEEgc2Vjb25kIHByZXNzIG9uIGEgdGV4dCBibG9jayBvcGVucyBpdHMgZWRpdG9yIGluc3RlYWQgb2YgZHJhZ2dpbmcuXG4gICAgaWYgKHRoaXMuaXNUZXh0KSB7XG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3QgaXNEb3VibGVQcmVzcyA9IG5vdyAtIHRoaXMuX2xhc3RQcmVzcyA8IERPVUJMRV9QUkVTU19NUztcbiAgICAgIHRoaXMuX2xhc3RQcmVzcyA9IG5vdztcblxuICAgICAgaWYgKGlzRG91YmxlUHJlc3MpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMuZWRpdFRleHQoKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zZWxlY3RDb21wb25lbnQuZW1pdCh0aGlzLmNvbXBvbmVudC5pZCk7XG5cbiAgICB0aGlzLl90cmFjayhldmVudCwgKGRlbHRhWCwgZGVsdGFZKSA9PiB7XG4gICAgICBsZXQgeCA9IE1hdGgubWF4KDAsIHRoaXMuX29yaWdpbi54ICsgdGhpcy5faW5jaGVzKGRlbHRhWCkpO1xuICAgICAgbGV0IHkgPSBNYXRoLm1heCgwLCB0aGlzLl9vcmlnaW4ueSArIHRoaXMuX2luY2hlcyhkZWx0YVkpKTtcblxuICAgICAgaWYgKHRoaXMuc25hcHBlcikge1xuICAgICAgICAoeyB4LCB5IH0gPSB0aGlzLnNuYXBwZXIuc25hcE1vdmUodGhpcy5jb21wb25lbnQsIHgsIHkpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb21wb25lbnQueCA9IHg7XG4gICAgICB0aGlzLmNvbXBvbmVudC55ID0geTtcbiAgICAgIHRoaXMuX2FwcGx5R2VvbWV0cnkoKTtcbiAgICB9LCAoKSA9PiB0aGlzLl9lbWl0R2VvbWV0cnkoKSk7XG4gIH1cblxuICBwdWJsaWMgb25SZXNpemVTdGFydChldmVudDogUG9pbnRlckV2ZW50LCBoYW5kbGU6IEhhbmRsZSk6IHZvaWQge1xuICAgIGlmICghdGhpcy5lZGl0TW9kZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2VsZWN0Q29tcG9uZW50LmVtaXQodGhpcy5jb21wb25lbnQuaWQpO1xuXG4gICAgdGhpcy5fdHJhY2soZXZlbnQsIChkZWx0YVgsIGRlbHRhWSkgPT4ge1xuICAgICAgY29uc3QgZHggPSB0aGlzLl9pbmNoZXMoZGVsdGFYKTtcbiAgICAgIGNvbnN0IGR5ID0gdGhpcy5faW5jaGVzKGRlbHRhWSk7XG4gICAgICBsZXQgeyB4LCB5LCB3LCBoIH0gPSB0aGlzLl9vcmlnaW47XG5cbiAgICAgIGlmIChoYW5kbGUuaW5jbHVkZXMoJ2UnKSkge1xuICAgICAgICB3ID0gTWF0aC5tYXgoTUlOX1csIHRoaXMuX29yaWdpbi53ICsgZHgpO1xuICAgICAgfVxuICAgICAgaWYgKGhhbmRsZS5pbmNsdWRlcygncycpKSB7XG4gICAgICAgIGggPSBNYXRoLm1heChNSU5fSCwgdGhpcy5fb3JpZ2luLmggKyBkeSk7XG4gICAgICB9XG4gICAgICBpZiAoaGFuZGxlLmluY2x1ZGVzKCd3JykpIHtcbiAgICAgICAgY29uc3QgY2xhbXBlZCA9IE1hdGgubWluKGR4LCB0aGlzLl9vcmlnaW4udyAtIE1JTl9XKTtcbiAgICAgICAgeCA9IHRoaXMuX29yaWdpbi54ICsgY2xhbXBlZDtcbiAgICAgICAgdyA9IHRoaXMuX29yaWdpbi53IC0gY2xhbXBlZDtcbiAgICAgIH1cbiAgICAgIGlmIChoYW5kbGUuaW5jbHVkZXMoJ24nKSkge1xuICAgICAgICBjb25zdCBjbGFtcGVkID0gTWF0aC5taW4oZHksIHRoaXMuX29yaWdpbi5oIC0gTUlOX0gpO1xuICAgICAgICB5ID0gdGhpcy5fb3JpZ2luLnkgKyBjbGFtcGVkO1xuICAgICAgICBoID0gdGhpcy5fb3JpZ2luLmggLSBjbGFtcGVkO1xuICAgICAgfVxuXG4gICAgICBsZXQgZ2VvbWV0cnkgPSB7IHgsIHksIHcsIGggfTtcbiAgICAgIGlmICh0aGlzLnNuYXBwZXIpIHtcbiAgICAgICAgZ2VvbWV0cnkgPSB0aGlzLnNuYXBwZXIuc25hcFJlc2l6ZSh0aGlzLmNvbXBvbmVudCwgZ2VvbWV0cnksIGhhbmRsZSk7XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5jb21wb25lbnQsIGdlb21ldHJ5KTtcbiAgICAgIHRoaXMuX2FwcGx5R2VvbWV0cnkoKTtcbiAgICAgIHRoaXMuY2hhcnRDb21wb25lbnQ/LnJlc2l6ZSgpO1xuICAgIH0sICgpID0+IHRoaXMuX2VtaXRHZW9tZXRyeSgpKTtcbiAgfVxuXG4gIC8vIChSZSlidWlsZCB0aGUgaGVhZGVyIGZzLWZpbHRlciBjb25maWc6IGhlYWRpbmcgdGVtcGxhdGUgcmVuZGVycyB0aGUgdGl0bGVcbiAgLy8gYW5kIGl0ZW1zIGFyZSB0aGlzIGNvbXBvbmVudCdzIGNvbXBvbmVudC1sZXZlbCBmaWx0ZXIgZ3JvdXBzLiBUaGUgYWN0aW9uc1xuICAvLyBtZW51IChTZXR0aW5ncyAvIEV4cG9ydCBDU1YpIGlzIE5PVCBoZXJlIOKAlCBpdCdzIGEgc3RhbmRhbG9uZSBrZWJhYiBmbG9hdGVkXG4gIC8vIHRvcC1yaWdodCBpbiB0aGUgdGVtcGxhdGUsIHNvIGl0cyBidXR0b24gaGVpZ2h0IG5vIGxvbmdlciBkcml2ZXMgdGhlIGhlYWRlclxuICAvLyByb3cncyBoZWlnaHQgKHdoaWNoIHdvdWxkIG90aGVyd2lzZSBpbmZsYXRlIHRoZSBoZWFkaW5nIGJ5IH40MHB4KS5cbiAgLy9cbiAgLy8gQSBsaXN0IGFsc28gZ2V0cyBhIHNlYXJjaCBib3ggb3ZlciBpdHMgdGV4dCBjb2x1bW5zLCB1bmxlc3MgaXRzIGhlYWRlclxuICAvLyBzaG93cyBhIGtleXdvcmQgZ3JvdXAgKFJlcG9ydEZpbHRlclN0YXRlU2VydmljZS5saXN0U2VhcmNoYWJsZSwgd2hpY2ggYWxzb1xuICAvLyBkcm9wcyBhIHNlYXJjaCBrZXB0IGZyb20gYmVmb3JlIHN1Y2ggYSBncm91cCBhcHBlYXJlZCkuXG4gIC8vXG4gIC8vIGByZXBvcnRlZGAgaXMgd2hhdCB0aGlzIGhlYWRlciBsYXN0IHJlcG9ydGVkIGZvciBlYWNoIG9mIGl0cyBncm91cHMsXG4gIC8vIHN0YXJ0aW5nIGZyb20gdGhlIHZhbHVlcyBpdCBpcyBidWlsdCB3aXRoLiBBIGNoYW5nZSBzZXRzIG9ubHkgdGhlIGdyb3Vwc1xuICAvLyB3aG9zZSBoZWFkZXIgdmFsdWUgbW92ZWQgKG1vdmVkR3JvdXBWYWx1ZXMpOiBmcy1maWx0ZXIgcmVwb3J0cyBldmVyeSBpdGVtXG4gIC8vIG9uIGFueSBjaGFuZ2UsIGFuZCBhIGdyb3VwIHNob3duIGluIHRoZSByZXBvcnQgYmFyIHRvbyBtYXkgaGF2ZSBjaGFuZ2VkXG4gIC8vIHRoZXJlIHNpbmNlLCB3aXRob3V0IHRoaXMgaGVhZGVyIGJlaW5nIHJlcGFpbnRlZC5cbiAgcHJpdmF0ZSBfc2V0VGV4dEh0bWwoaHRtbDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb21wb25lbnQuY29uZmlnID0geyAuLi50aGlzLmNvbXBvbmVudC5jb25maWcsIGh0bWwgfTtcbiAgICB0aGlzLnRleHRIdG1sLnNldChodG1sKTtcbiAgfVxuXG4gIHByaXZhdGUgX2J1aWxkRmlsdGVyQ29uZmlnKCk6IHZvaWQge1xuICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuY29tcG9uZW50RmlsdGVyR3JvdXBzO1xuICAgIGNvbnN0IGxpc3RTZWFyY2ggPSB0aGlzLl9maWx0ZXJTdGF0ZS5saXN0U2VhcmNoYWJsZSh0aGlzLmNvbXBvbmVudCk7XG4gICAgY29uc3QgcmVwb3J0ZWQgPSBuZXcgTWFwKGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiBbZ3JvdXAuaWQsIHRoaXMuX2ZpbHRlclN0YXRlLnZhbHVlKGdyb3VwLmlkKSA/PyBudWxsXSkpO1xuXG4gICAgdGhpcy5maWx0ZXJDb25maWcuc2V0KHtcbiAgICAgIC8vIGZzLWZpbHRlciBuZXZlciB0b3VjaGVzIHRoZSBVUkwgb3IgcGVyc2lzdHMgZmlsdGVyIHN0YXRlLiBUaGUgdmFsdWVzXG4gICAgICAvLyBhcmUgb3duZWQgYnkgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlLCB3aGljaCBmZWVkcyB0aGUgcmVwb3J0IHZpZXcnc1xuICAgICAgLy8gb25lIFVSTCB3cml0ZXIgKHJlcG9ydC11cmwtc3RhdGUudHMpLlxuICAgICAgcXVlcnlQYXJhbTogZmFsc2UsXG4gICAgICBwZXJzaXN0OiBmYWxzZSxcbiAgICAgIGl0ZW1zOiBbXG4gICAgICAgIC4uLmdyb3Vwcy5tYXAoKGdyb3VwKSA9PlxuICAgICAgICAgIGZpbHRlckl0ZW1Gb3JHcm91cChncm91cCwgdGhpcy5fcmVwb3J0RGF0YSwgdGhpcy5yZXBvcnRJZCwgdGhpcy5fZmlsdGVyU3RhdGUudmFsdWUoZ3JvdXAuaWQpKSksXG4gICAgICAgIC4uLihsaXN0U2VhcmNoID8gW2xpc3RTZWFyY2hJdGVtKHRoaXMuX2ZpbHRlclN0YXRlLmxpc3RTZWFyY2godGhpcy5jb21wb25lbnQuaWQpKV0gOiBbXSksXG4gICAgICBdLFxuICAgICAgLy8gVHlwaW5nIGluIHRoZSBzZWFyY2ggYm94IG11c3Qgbm90IHJlZmV0Y2ggdGhyb3VnaCB0aGUgZ3JvdXBzLCBub3Igc2V0XG4gICAgICAvLyBhIHN0YWxlIGdyb3VwIHZhbHVlIGJhY2ssIGFuZCBhIGdyb3VwIGNoYW5nZSBtdXN0IG5vdCByZWZldGNoIHRocm91Z2hcbiAgICAgIC8vIHRoZSBzZWFyY2guXG4gICAgICBjaGFuZ2U6IChxdWVyeSkgPT4ge1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBncm91cFZhbHVlc0Zyb21RdWVyeShxdWVyeSA/PyB7fSwgdGhpcy5jb21wb25lbnRGaWx0ZXJHcm91cHMpO1xuXG4gICAgICAgIGZvciAoY29uc3QgeyBncm91cElkLCB2YWx1ZSB9IG9mIG1vdmVkR3JvdXBWYWx1ZXMocmVwb3J0ZWQsIHZhbHVlcykpIHtcbiAgICAgICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5zZXRWYWx1ZShncm91cElkLCB2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGlzdFNlYXJjaCkge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLnNldExpc3RTZWFyY2godGhpcy5jb21wb25lbnQuaWQsIFN0cmluZyhxdWVyeT8uW0xJU1RfU0VBUkNIX0lURU1dID8/ICcnKSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9vcmlnaW4gPSB7IHg6IDAsIHk6IDAsIHc6IDAsIGg6IDAgfTtcblxuICAvLyBQb2ludGVyLWNhcHR1cmUgZ2VzdHVyZSBsb29wOiBydW5zIG91dHNpZGUgQW5ndWxhciwgcmVwYWludHMgaW1wZXJhdGl2ZWx5LFxuICAvLyBhbmQgZmluaXNoZXMgYmFjayBpbnNpZGUgQW5ndWxhciAoc2VsZWN0aW9uL3BlcnNpc3RlbmNlKS5cbiAgcHJpdmF0ZSBfdHJhY2soXG4gICAgZXZlbnQ6IFBvaW50ZXJFdmVudCxcbiAgICBvbk1vdmU6IChkZWx0YVg6IG51bWJlciwgZGVsdGFZOiBudW1iZXIpID0+IHZvaWQsXG4gICAgb25FbmQ6ICgpID0+IHZvaWQsXG4gICk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBjb25zdCBoYW5kbGUgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgaGFuZGxlLnNldFBvaW50ZXJDYXB0dXJlKGV2ZW50LnBvaW50ZXJJZCk7XG5cbiAgICB0aGlzLl9vcmlnaW4gPSB7XG4gICAgICB4OiB0aGlzLmNvbXBvbmVudC54LFxuICAgICAgeTogdGhpcy5jb21wb25lbnQueSxcbiAgICAgIHc6IHRoaXMuY29tcG9uZW50LncsXG4gICAgICBoOiB0aGlzLmNvbXBvbmVudC5oLFxuICAgIH07XG4gICAgY29uc3Qgc3RhcnRYID0gZXZlbnQuY2xpZW50WDtcbiAgICBjb25zdCBzdGFydFkgPSBldmVudC5jbGllbnRZO1xuXG4gICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBjb25zdCBtb3ZlID0gKGU6IFBvaW50ZXJFdmVudCkgPT4gb25Nb3ZlKGUuY2xpZW50WCAtIHN0YXJ0WCwgZS5jbGllbnRZIC0gc3RhcnRZKTtcbiAgICAgIGNvbnN0IGVuZCA9ICgpID0+IHtcbiAgICAgICAgaGFuZGxlLnJlbGVhc2VQb2ludGVyQ2FwdHVyZShldmVudC5wb2ludGVySWQpO1xuICAgICAgICBoYW5kbGUucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcm1vdmUnLCBtb3ZlKTtcbiAgICAgICAgaGFuZGxlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIGVuZCk7XG4gICAgICAgIGhhbmRsZS5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVyY2FuY2VsJywgZW5kKTtcblxuICAgICAgICB0aGlzLl96b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5zbmFwcGVyPy5jbGVhcigpO1xuICAgICAgICAgIG9uRW5kKCk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgaGFuZGxlLmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJtb3ZlJywgbW92ZSk7XG4gICAgICBoYW5kbGUuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcnVwJywgZW5kKTtcbiAgICAgIGhhbmRsZS5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyY2FuY2VsJywgZW5kKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2VtaXRHZW9tZXRyeSgpOiB2b2lkIHtcbiAgICB0aGlzLmNvbXBvbmVudC54ID0gdGhpcy5fcm91bmQodGhpcy5jb21wb25lbnQueCk7XG4gICAgdGhpcy5jb21wb25lbnQueSA9IHRoaXMuX3JvdW5kKHRoaXMuY29tcG9uZW50LnkpO1xuICAgIHRoaXMuY29tcG9uZW50LncgPSB0aGlzLl9yb3VuZChNYXRoLm1heChNSU5fVywgdGhpcy5jb21wb25lbnQudykpO1xuICAgIHRoaXMuY29tcG9uZW50LmggPSB0aGlzLl9yb3VuZChNYXRoLm1heChNSU5fSCwgdGhpcy5jb21wb25lbnQuaCkpO1xuICAgIHRoaXMuX2FwcGx5R2VvbWV0cnkoKTtcbiAgICB0aGlzLmNoYXJ0Q29tcG9uZW50Py5yZXNpemUoKTtcblxuICAgIHRoaXMucG9zaXRpb25DaGFuZ2VkLmVtaXQoe1xuICAgICAgY29tcG9uZW50SWQ6IHRoaXMuY29tcG9uZW50LmlkLFxuICAgICAgeDogdGhpcy5jb21wb25lbnQueCxcbiAgICAgIHk6IHRoaXMuY29tcG9uZW50LnksXG4gICAgICB3OiB0aGlzLmNvbXBvbmVudC53LFxuICAgICAgaDogdGhpcy5jb21wb25lbnQuaCxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIEEgY2hhcnQgb24gYSB0aW1lIHgtYXhpcyDigJQgdGhlIG9ubHkgY29tcG9uZW50IHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sXG4gIC8vIGFwcGxpZXMgdG8uIFRoZSBzZXJ2ZXIgb3ducyB0aGlzIHJ1bGUgKFJlcG9ydFF1ZXJ5UnVubmVyOjpfaXNUaW1lU2VyaWVzQ2hhcnQpO1xuICAvLyB0aGlzIGlzIGl0cyBkb2N1bWVudGVkIGJyb3dzZXItc2lkZSBtaXJyb3IsIGZvciBwcm9kdWN0cyBvbiBhbiBvbGRlciBmcmFtZXdvcmsuXG4gIHByaXZhdGUgZ2V0IF9pc1RpbWVTZXJpZXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY29tcG9uZW50LnR5cGUgPT09ICdjaGFydCcgJiYgdGhpcy5jb21wb25lbnQuY29uZmlnPy54QXhpcz8ua2luZCA9PT0gJ3RpbWUnO1xuICB9XG5cbiAgLy8gQXV0byBoZWlnaHQgKGJveCBmaXRzIGl0cyBjb250ZW50KSB2cyBmaXhlZCAodXNlIGBoYCBleGFjdGx5KS4gRGVyaXZlZCBmcm9tXG4gIC8vIHR5cGUsIHNlcnZlci1zaWRlOiBLUEkgdGlsZXMgYXJlIGF1dG87IGNoYXJ0cyBhbmQgbGlzdHMgYXJlIGZpeGVkIOKAlCBjaGFydHNcbiAgLy8gZml0IHRoZSBib3ggYW5kIG5ldmVyIG92ZXJmbG93LCBsaXN0cyBzY3JvbGwgaW5zaWRlIGl0LlxuICBwcml2YXRlIGdldCBfaGVpZ2h0QXV0bygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnQuYXV0b0hlaWdodCAhPT0gZmFsc2U7XG4gIH1cblxuICAvLyBEcml2ZXMgdGhlIGF1dG8tb25seSBDU1MgZGVmYXVsdCAoZW1wdHktc3RhdGUgYmFzZWxpbmUpIHNvIGl0IG5ldmVyIGFwcGxpZXNcbiAgLy8gdG8gYSBmaXhlZC1oZWlnaHQgY29tcG9uZW50LlxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmhlaWdodC1hdXRvJylcbiAgcHVibGljIGdldCBoZWlnaHRBdXRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9oZWlnaHRBdXRvO1xuICB9XG5cbiAgLy8gU2NyZWVuIHBpeGVscyDihpIgaW5jaGVzIGF0IHRoZSBjdXJyZW50IHpvb20uXG4gIHByaXZhdGUgX2luY2hlcyhwaXhlbHM6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHBpeGVscyAvICh0aGlzLnpvb20gKiBQWF9QRVJfSU5DSCk7XG4gIH1cblxuICAvLyBDbGVhbiBwZXJzaXN0ZWQgdmFsdWVzOiBodW5kcmVkdGhzIG9mIGFuIGluY2guXG4gIHByaXZhdGUgX3JvdW5kKHZhbHVlOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbHVlICogMTAwKSAvIDEwMDtcbiAgfVxuXG4gIC8vIFRoZSBjYW52YXMgcG9zaXRpb25zIHRoZSBob3N0IHZpYSBbc3R5bGVdOyBtaWQtZ2VzdHVyZSB3ZSBzZXQgaXQgZGlyZWN0bHlcbiAgLy8gc28gT25QdXNoIG5ldmVyIHJlLXJlbmRlcnMgaW4gdGhlIG1vdmUgbG9vcC5cbiAgcHJpdmF0ZSBfYXBwbHlHZW9tZXRyeSgpOiB2b2lkIHtcbiAgICBjb25zdCBzdHlsZSA9IHRoaXMuX2hvc3QubmF0aXZlRWxlbWVudC5zdHlsZTtcbiAgICBzdHlsZS5sZWZ0ID0gYCR7dGhpcy5jb21wb25lbnQueCAqIFBYX1BFUl9JTkNIfXB4YDtcbiAgICBzdHlsZS50b3AgPSBgJHt0aGlzLmNvbXBvbmVudC55ICogUFhfUEVSX0lOQ0h9cHhgO1xuICAgIHN0eWxlLndpZHRoID0gYCR7dGhpcy5jb21wb25lbnQudyAqIFBYX1BFUl9JTkNIfXB4YDtcblxuICAgIC8vIEF1dG8gKGtwaSk6IG5vIGZpeGVkIGhlaWdodCDigJQgdGhlIGJveCBzaXplcyB0byBpdHMgY29udGVudC4gRml4ZWRcbiAgICAvLyAoY2hhcnQvbGlzdCk6IGBoYCBpcyB0aGUgZXhhY3QgaGVpZ2h0LiBNaXJyb3JzIHRoZSBjYW52YXMgW3N0eWxlXSBiaW5kaW5nXG4gICAgLy8gc28gdGhlIG1pZC1nZXN0dXJlIHBhaW50IG1hdGNoZXMgdGhlIHBvc3QtZ2VzdHVyZSByZS1yZW5kZXIuXG4gICAgaWYgKHRoaXMuX2hlaWdodEF1dG8pIHtcbiAgICAgIHN0eWxlLmhlaWdodCA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZS5oZWlnaHQgPSBgJHt0aGlzLmNvbXBvbmVudC5oICogUFhfUEVSX0lOQ0h9cHhgO1xuICAgIH1cbiAgfVxuXG4gIC8vIC0tLS0tIGRhdGEgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHByaXZhdGUgX2xvYWQoKTogdm9pZCB7XG4gICAgdGhpcy5sb2FkaW5nLnNldCh0cnVlKTtcbiAgICB0aGlzLmVycm9yLnNldChudWxsKTtcblxuICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLl9maWx0ZXJTdGF0ZS5yZXNvbHZlRm9yQ29tcG9uZW50KHRoaXMuY29tcG9uZW50KTtcbiAgICAvLyBUaW1lLXNlcmllcyBjaGFydHMgY2FycnkgdGhlIGdyb3VwLWJ5IGdyYWluIChpZiB0aGUgdmlld2VyIHBpY2tlZCBvbmUpIHNvXG4gICAgLy8gdGhlIGJhY2tlbmQgcmUtYnVja2V0czsgZXZlcnl0aGluZyBlbHNlIHNlbmRzIG5vIGludGVyYWN0aW9uIHN0YXRlIGhlcmUuXG4gICAgY29uc3Qgc3RhdGUgPSB0aGlzLl9pc1RpbWVTZXJpZXMgJiYgdGhpcy5fZmlsdGVyU3RhdGUuZnJlcXVlbmN5KClcbiAgICAgID8geyBmcmVxdWVuY3k6IHRoaXMuX2ZpbHRlclN0YXRlLmZyZXF1ZW5jeSgpIH1cbiAgICAgIDoge307XG5cbiAgICB0aGlzLl9yZXBvcnREYXRhLmNvbXBvbmVudERhdGEodGhpcy5yZXBvcnRJZCwgdGhpcy5jb21wb25lbnQuaWQsIGZpbHRlcnMsIHN0YXRlKVxuICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChkYXRhOiBDb21wb25lbnREYXRhKSA9PiB7XG4gICAgICAgICAgdGhpcy5kYXRhLnNldChkYXRhKTtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIHRoaXMubG9hZGluZy5zZXQoZmFsc2UpO1xuICAgICAgICAgIHRoaXMuZXJyb3Iuc2V0KGVycm9yPy5lcnJvcj8ubWVzc2FnZSA/PyBlcnJvcj8ubWVzc2FnZSA/PyAnRmFpbGVkIHRvIGxvYWQgZGF0YScpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cbn1cbiIsIjxkaXZcbiAgICBjbGFzcz1cImNvbXBvbmVudC1ib3hcIlxuICAgIFtjbGFzcy5lZGl0aW5nXT1cImVkaXRNb2RlXCJcbiAgICBbY2xhc3MudGV4dF09XCJpc1RleHRcIlxuICAgIFtjbGFzcy5zZWxlY3RlZF09XCJzZWxlY3RlZFwiXG4gICAgW3N0eWxlLnBhZGRpbmddPVwiYm9keVBhZGRpbmdcIlxuICAgIChwb2ludGVyZG93bik9XCJvbkNvbXBvbmVudFBvaW50ZXJEb3duKCRldmVudClcIlxuICAgIChtb3VzZWRvd24pPVwic3RvcENhbnZhc1BhbigkZXZlbnQpXCJcbiAgICAodG91Y2hzdGFydCk9XCJzdG9wQ2FudmFzUGFuKCRldmVudClcIj5cbiAgPCEtLSBUaGUgaGVhZGVyIGlzIGFuIGZzLWZpbHRlcjogaGVhZGluZyB0ZW1wbGF0ZSA9IHRpdGxlIChhbmQgdGhlIGVkaXQtbW9kZVxuICAgICAgIGRyYWcgaGFuZGxlKSwgYWN0aW9ucyA9IHRoZSBtZW51LCBpdGVtcyA9IGNvbXBvbmVudC1sZXZlbCBmaWx0ZXIgZ3JvdXBzLFxuICAgICAgIHRoZSBzYW1lIHN0cmlwIGZvciBldmVyeSB0eXBlIChsaXN0cyBpbmNsdWRlZCkuIGZzLWZpbHRlciByZWFkcyBpdHNcbiAgICAgICBjb25maWcgb25jZSwgc28gdGhlIGJsb2NrIGlzIGtleWVkIG9uIHRoZSBjb21wb25lbnQtZmlsdGVyIHNldCB0byBiZVxuICAgICAgIHJlY3JlYXRlZCB3aGVuIGl0IGNoYW5nZXMuIC0tPlxuICA8IS0tIEEgdGV4dCBibG9jayBoYXMgbm8gdGl0bGUgYmFyIOKAlCBpdCBJUyBpdHMgd29yZHMsIGxpa2UgYSB0ZXh0IGJveCBvbiBhXG4gICAgICAgc2xpZGUg4oCUIHNvIGl0IGdldHMgbmVpdGhlciB0aGUgaGVhZGVyIG5vciB0aGUgZGF0YSBhY3Rpb25zLiAtLT5cbiAgQGZvciAoa2V5IG9mIGlzVGV4dCA/IFtdIDogW2ZpbHRlcktleV07IHRyYWNrIGtleSkge1xuICAgIDxmcy1maWx0ZXJcbiAgICAgICAgY2xhc3M9XCJjb21wb25lbnQtZmlsdGVyXCJcbiAgICAgICAgW2NvbmZpZ109XCJmaWx0ZXJDb25maWcoKVwiPlxuICAgICAgPG5nLXRlbXBsYXRlIGZzRmlsdGVySGVhZGluZz5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJjb21wb25lbnQtdGl0bGVcIlxuICAgICAgICAgICAgKHBvaW50ZXJkb3duKT1cIm9uRHJhZ1N0YXJ0KCRldmVudClcIj5cbiAgICAgICAgICB7eyBjb21wb25lbnQudGl0bGUgfX1cbiAgICAgICAgICBAaWYgKHRydW5jYXRlZCkge1xuICAgICAgICAgICAgPG1hdC1pY29uXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ0cnVuY2F0ZWQtaWNvblwiXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlNob3dpbmcgYSB0cnVuY2F0ZWQgcmVzdWx0IOKAlCByZWZpbmUgdGhlIGZpbHRlcnMgdG8gc2VlIGV2ZXJ5dGhpbmcuXCI+XG4gICAgICAgICAgICAgIHdhcm5pbmdfYW1iZXJcbiAgICAgICAgICAgIDwvbWF0LWljb24+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9mcy1maWx0ZXI+XG4gIH1cbiAgPCEtLSBUaGUgYWN0aW9ucyBtZW51IGlzIGZsb2F0ZWQgdG9wLXJpZ2h0IChhYnNvbHV0ZSkgcmF0aGVyIHRoYW4gbGl2aW5nIGluXG4gICAgICAgZnMtZmlsdGVyJ3MgYWN0aW9ucyBzbG90LCBzbyBpdHMgfjQwcHggYnV0dG9uIGhlaWdodCBubyBsb25nZXIgZHJpdmVzIHRoZVxuICAgICAgIGhlYWRlciByb3cncyBoZWlnaHQuIEl0IG92ZXJsYXlzIHRoZSBib3ggY29ybmVyOyB0aGUgaGVhZGluZyByZXNlcnZlc1xuICAgICAgIHJpZ2h0IHBhZGRpbmcgc28gYSBsb25nIHRpdGxlIGVsbGlwc2lzZXMgYmVmb3JlIGl0LiAtLT5cbiAgQGlmICghaXNUZXh0IHx8IChlZGl0TW9kZSAmJiAhdGV4dEVkaXRpbmcoKSkpIHtcbiAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICBjbGFzcz1cImNvbXBvbmVudC1tZW51XCJcbiAgICAgICAgW2ZzTWVudVRyaWdnZXJGb3JdPVwibWVudVwiXG4gICAgICAgIChwb2ludGVyZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAobW91c2Vkb3duKT1cInN0b3BDYW52YXNQYW4oJGV2ZW50KVwiPlxuICAgICAgPG1hdC1pY29uPm1vcmVfdmVydDwvbWF0LWljb24+XG4gICAgPC9idXR0b24+XG4gICAgPCEtLSBCZXNpZGUgaXRzIHRyaWdnZXIsIGluc2lkZSB0aGUgc2FtZSBibG9jazogYW4gZnMtbWVudSB0aGF0IGZpbmRzIG5vXG4gICAgICAgICB0cmlnZ2VyIG9mIGl0cyBvd24gZHJhd3Mgb25lLiAtLT5cbiAgICA8ZnMtbWVudSAjbWVudT5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgIGZzLW1lbnUtaXRlbVxuICAgICAgICAgIFtoaWRkZW5dPVwiIWlzVGV4dFwiXG4gICAgICAgICAgKGNsaWNrKT1cImVkaXRUZXh0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmVkaXQ8L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5FZGl0IHRleHQ8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCIhaXNUZXh0XCJcbiAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlVGV4dCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5EZWxldGU8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCJpc1RleHRcIlxuICAgICAgICAgIChjbGljayk9XCJzZXR0aW5ncygpXCI+XG4gICAgICAgIDxtYXQtaWNvbj50dW5lPC9tYXQtaWNvbj5cbiAgICAgICAgPHNwYW4+U2V0dGluZ3M8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCJpc1RleHRcIlxuICAgICAgICAgIChjbGljayk9XCJleHBvcnRDc3YoKVwiPlxuICAgICAgICA8bWF0LWljb24+ZG93bmxvYWQ8L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5FeHBvcnQgQ1NWPC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgIGZzLW1lbnUtaXRlbVxuICAgICAgICAgIFtoaWRkZW5dPVwiIWhpZGVzQ29sdW1uc1wiXG4gICAgICAgICAgKGNsaWNrKT1cImNob29zZUNvbHVtbnMoKVwiPlxuICAgICAgICA8bWF0LWljb24+dmlld19jb2x1bW48L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5Db2x1bW5zPC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2ZzLW1lbnU+XG4gIH1cbiAgPGRpdiBjbGFzcz1cImNvbXBvbmVudC1ib2R5XCI+XG4gICAgQGlmIChpc1RleHQpIHtcbiAgICAgIDxhcHAtcmVwb3J0LWNvbXBvbmVudC10ZXh0XG4gICAgICAgIFtodG1sXT1cInRleHRIdG1sKCkgPz8gY29tcG9uZW50LmNvbmZpZz8uaHRtbCA/PyAnJ1wiXG4gICAgICAgIFt0b2tlbnNdPVwidG9rZW5zKClcIlxuICAgICAgICBbZWRpdGluZ109XCJ0ZXh0RWRpdGluZygpXCJcbiAgICAgICAgW3Nob3duRWxzZXdoZXJlXT1cInNob3duRWxzZXdoZXJlXCJcbiAgICAgICAgKHNhdmVkKT1cIm9uVGV4dFNhdmVkKCRldmVudClcIlxuICAgICAgICAoZWRpdEVuZGVkKT1cInRleHRFZGl0aW5nLnNldChmYWxzZSlcIlxuICAgICAgICAodmFsdWVTZXR0aW5ncyk9XCJ2YWx1ZVNldHRpbmdzLmVtaXQoJGV2ZW50KVwiPlxuICAgICAgPC9hcHAtcmVwb3J0LWNvbXBvbmVudC10ZXh0PlxuICAgIH0gQGVsc2UgaWYgKGNvbXBvbmVudC50eXBlID09PSAnbGlzdCcpIHtcbiAgICAgIDxhcHAtcmVwb3J0LWNvbXBvbmVudC1saXN0XG4gICAgICAgIFtyZXBvcnRJZF09XCJyZXBvcnRJZFwiXG4gICAgICAgIFtjb21wb25lbnRdPVwiY29tcG9uZW50XCI+XG4gICAgICA8L2FwcC1yZXBvcnQtY29tcG9uZW50LWxpc3Q+XG4gICAgfSBAZWxzZSBpZiAobG9hZGluZygpKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwiY29tcG9uZW50LXN0YXRlXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLXNoaW1tZXJcIj48L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIH0gQGVsc2UgaWYgKGVycm9yKCkpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJjb21wb25lbnQtc3RhdGUgZXJyb3JcIj5cbiAgICAgICAge3sgZXJyb3IoKSB9fVxuICAgICAgPC9kaXY+XG4gICAgfSBAZWxzZSBpZiAoIWRhdGEoKT8ucm93cz8ubGVuZ3RoKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwiY29tcG9uZW50LXN0YXRlXCI+XG4gICAgICAgIE5vIGRhdGFcbiAgICAgIDwvZGl2PlxuICAgIH0gQGVsc2UgaWYgKGNvbXBvbmVudC50eXBlID09PSAna3BpJykge1xuICAgICAgPGFwcC1yZXBvcnQtY29tcG9uZW50LWtwaVxuICAgICAgICBbY29tcG9uZW50XT1cImNvbXBvbmVudFwiXG4gICAgICAgIFtkYXRhXT1cImRhdGEoKVwiPlxuICAgICAgPC9hcHAtcmVwb3J0LWNvbXBvbmVudC1rcGk+XG4gICAgfSBAZWxzZSB7XG4gICAgICA8YXBwLXJlcG9ydC1jb21wb25lbnQtY2hhcnRcbiAgICAgICAgW2NvbXBvbmVudF09XCJjb21wb25lbnRcIlxuICAgICAgICBbZGF0YV09XCJkYXRhKClcIj5cbiAgICAgIDwvYXBwLXJlcG9ydC1jb21wb25lbnQtY2hhcnQ+XG4gICAgfVxuICAgIDwhLS0gSW4gZWRpdCBtb2RlIGEgdHJhbnNwYXJlbnQgdmVpbCBvdmVyIHRoZSBib2R5IG1ha2VzIHRoZSBXSE9MRVxuICAgICAgICAgY29tcG9uZW50IGRyYWdnYWJsZSAoaW5kdXN0cnkgc3RhbmRhcmQ6IHlvdSBncmFiIHRoZSBvYmplY3QsIG5vdCBqdXN0XG4gICAgICAgICBpdHMgdGl0bGUgYmFyKSBhbmQga2VlcHMgaW5uZXIgd2lkZ2V0cyBmcm9tIHN3YWxsb3dpbmcgdGhlIGdlc3R1cmUuIC0tPlxuICAgIEBpZiAoZWRpdE1vZGUgJiYgIXRleHRFZGl0aW5nKCkpIHtcbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJkcmFnLXZlaWxcIlxuICAgICAgICAocG9pbnRlcmRvd24pPVwib25EcmFnU3RhcnQoJGV2ZW50KVwiPlxuICAgICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbjwvZGl2PlxuPCEtLSBIYW5kbGVzIGxpdmUgT1VUU0lERSB0aGUgY2xpcHBlZCBib3ggc28gdGhleSBzdHJhZGRsZSBpdHMgZWRnZXMuIC0tPlxuQGlmIChlZGl0TW9kZSAmJiBzZWxlY3RlZCkge1xuICBAZm9yIChoYW5kbGUgb2YgcmVzaXplSGFuZGxlczsgdHJhY2sgaGFuZGxlKSB7XG4gICAgPGRpdlxuICAgICAgY2xhc3M9XCJoYW5kbGUgaGFuZGxlLXt7IGhhbmRsZSB9fVwiXG4gICAgICAobW91c2Vkb3duKT1cInN0b3BDYW52YXNQYW4oJGV2ZW50KVwiXG4gICAgICAocG9pbnRlcmRvd24pPVwib25SZXNpemVTdGFydCgkZXZlbnQsIGhhbmRsZSlcIj5cbiAgICA8L2Rpdj5cbiAgfVxufSJdfQ==
|
|
796
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWNvbXBvbmVudC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvY29tcG9uZW50cy9yZXBvcnQtY29tcG9uZW50L3JlcG9ydC1jb21wb25lbnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvcmVwb3J0LWNvbXBvbmVudC9yZXBvcnQtY29tcG9uZW50LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFDMUQsWUFBWSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFxQixNQUFNLEVBQWlCLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUMvRyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEdBQ2pDLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNoRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFdkQsT0FBTyxFQUFnQixjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDaEQsT0FBTyxF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QXVCLCtMQUN2QixxQkFBcUIsNEhBQ3JCLHNCQUFzQix5R0FDdEIsc0JBQXNCOzs0RkFHYix3QkFBd0I7a0JBbkJwQyxTQUFTOytCQUNFLHNCQUFzQixtQkFHZix1QkFBdUIsQ0FBQyxNQUFNLGNBQ25DLElBQUksV0FDUDt3QkFDUCxPQUFPO3dCQUNQLGFBQWE7d0JBQ2IsY0FBYzt3QkFDZCxVQUFVO3dCQUNWLGNBQWM7d0JBQ2QsWUFBWTt3QkFDWix1QkFBdUI7d0JBQ3ZCLHFCQUFxQjt3QkFDckIsc0JBQXNCO3dCQUN0QixzQkFBc0I7cUJBQ3ZCOzhCQUllLFFBQVE7c0JBQXZCLEtBQUs7Z0JBQ1UsU0FBUztzQkFBeEIsS0FBSztnQkFDVSxNQUFNO3NCQUFyQixLQUFLO2dCQUNVLFFBQVE7c0JBQXZCLEtBQUs7Z0JBRVUsSUFBSTtzQkFBbkIsS0FBSztnQkFDVSxPQUFPO3NCQUF0QixLQUFLO2dCQUNVLFFBQVE7c0JBQXZCLEtBQUs7Z0JBRVcsZUFBZTtzQkFBL0IsTUFBTTtnQkFDVSxlQUFlO3NCQUEvQixNQUFNO2dCQUNVLFlBQVk7c0JBQTVCLE1BQU07Z0JBdUNBLGNBQWM7c0JBRHBCLFNBQVM7dUJBQUMsdUJBQXVCO2dCQStEM0IsUUFBUTtzQkFEZCxTQUFTO3VCQUFDLFVBQVU7Z0JBSWQsVUFBVTtzQkFEaEIsU0FBUzt1QkFBQyxZQUFZO2dCQW1tQlosVUFBVTtzQkFEcEIsV0FBVzt1QkFBQyxtQkFBbUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsIEhvc3RCaW5kaW5nLCBJbnB1dCwgTmdab25lLCBPbkNoYW5nZXMsIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQsIGNvbXB1dGVkLCBpbmplY3QsXG4gIGlucHV0LCBvdXRwdXQsIHNpZ25hbCwgdmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuXG5pbXBvcnQgeyBNYXRJY29uQnV0dG9uIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJztcbmltcG9ydCB7IE1hdERpYWxvZyB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XG5pbXBvcnQgeyBNYXRJY29uIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XG5pbXBvcnQgeyBNYXRQcm9ncmVzc0JhciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Byb2dyZXNzLWJhcic7XG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XG5cbmltcG9ydCB7IEZpbHRlckNvbmZpZywgRnNGaWx0ZXJNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9maWx0ZXInO1xuaW1wb3J0IHsgRnNNZW51Q29tcG9uZW50LCBGc01lbnVNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9tZW51JztcbmltcG9ydCB7IEZzTWVzc2FnZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgRnNQcm9jZXNzIH0gZnJvbSAnQGZpcmVzdGl0Y2gvcHJvY2Vzcyc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QsIGZpbHRlciBhcyByeEZpbHRlciwgbWFwLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5cbmltcG9ydCB7IG9wZW5BdFBvaW50IH0gZnJvbSAnLi4vLi4vYW5jaG9yLWF0LXBvaW50JztcbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7IExpc3RDb2x1bW5zQ29tcG9uZW50LCBMaXN0Q29sdW1uc0RpYWxvZ0RhdGEgfSBmcm9tICcuLi8uLi9kaWFsb2dzL2xpc3QtY29sdW1ucy9saXN0LWNvbHVtbnMuY29tcG9uZW50JztcbmltcG9ydCB7XG4gIERSSUxMX0NSVU1CX1NFUEFSQVRPUiwgRFJJTExfUkVTRVRfTUVTU0FHRSwgYWRvcHRlZERyaWxsUGF0aCwgZHJpbGxDcnVtYkxhYmVscywgZHJpbGxPdXRzaWRlTWVzc2FnZSxcbiAgZHJpbGxSZXNldE5vdGVkLFxufSBmcm9tICcuLi8uLi9kcmlsbC1jcnVtYnMnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50RGF0YSxcbiAgQ29tcG9uZW50U2V0dGluZ3MsXG4gIEZpbHRlckdyb3VwVmFsdWUsXG4gIEtwaUNvbmZpZyxcbiAgUmVwb3J0Q29tcG9uZW50IGFzIFJlcG9ydENvbXBvbmVudE1vZGVsLFxuICBSZXBvcnRGaWx0ZXJHcm91cCxcbn0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydE1hcmtBY3Rpb24gfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC1tYXJrLWFjdGlvbi50eXBlJztcbmltcG9ydCB7IFJlcG9ydE1hcmtDbGljayB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvcmVwb3J0LW1hcmstY2xpY2suaW50ZXJmYWNlJztcbmltcG9ydCB7IFRpbGVMb2FkUmVzdWx0IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy90aWxlLWxvYWQtcmVzdWx0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBrcGlDYXJkU2V0dGluZ3MsIHNhbWVLcGlDYXJkU2V0dGluZ3MgfSBmcm9tICcuLi8uLi9rcGktY2FyZCc7XG5pbXBvcnQgeyBjb21wb25lbnRQYWRkaW5nQ3NzIH0gZnJvbSAnLi4vLi4vbGF5b3V0JztcbmltcG9ydCB7IGxpc3RIaWRlYWJsZUNvbHVtbnMgfSBmcm9tICcuLi8uLi9saXN0LWNvbmZpZyc7XG5pbXBvcnQge1xuICBNQVJLX0FDVElPTl9MQUJFTFMsIGRlY2lkZU1hcmtDbGljaywgZHJpbGxEb3duUGF0aCwgbWFya0FjdGlvbnMsIHRpbGVNYXJrQWN0aW9ucyxcbn0gZnJvbSAnLi4vLi4vbWFyay1jbGljayc7XG5pbXBvcnQge1xuICBMSVNUX1NFQVJDSF9JVEVNLCBmaWx0ZXJJdGVtRm9yR3JvdXAsIGdyb3VwVmFsdWVzRnJvbVF1ZXJ5LCBsaXN0U2VhcmNoSXRlbSxcbn0gZnJvbSAnLi4vLi4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5pbXBvcnQgeyBncm91cFZhbHVlU2lnbmF0dXJlIH0gZnJvbSAnLi4vLi4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5pbXBvcnQgeyBvZmZlcmVkVmlld2VyRmVhdHVyZXMgfSBmcm9tICcuLi8uLi9yZXBvcnQtdmlld2VyLWZlYXR1cmVzJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlck9wdGlvbnNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLnNlcnZpY2UnO1xuaW1wb3J0IHsgbW92ZWRHcm91cFZhbHVlcywgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcbmltcG9ydCB7IGlzVGltZVNlcmllc0NoYXJ0IH0gZnJvbSAnLi4vLi4vdGlsZS1kYXRhLXN0YXRlJztcbmltcG9ydCB7IHRpbGVMb2FkcyB9IGZyb20gJy4uLy4uL3RpbGUtbG9hZHMnO1xuaW1wb3J0IHsgQ29tcG9uZW50Q2hhcnRDb21wb25lbnQgfSBmcm9tICcuLi9jb21wb25lbnQtY2hhcnQvY29tcG9uZW50LWNoYXJ0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb21wb25lbnRLcGlDb21wb25lbnQgfSBmcm9tICcuLi9jb21wb25lbnQta3BpL2NvbXBvbmVudC1rcGkuY29tcG9uZW50JztcbmltcG9ydCB7IENvbXBvbmVudExpc3RDb21wb25lbnQgfSBmcm9tICcuLi9jb21wb25lbnQtbGlzdC9jb21wb25lbnQtbGlzdC5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ29tcG9uZW50VGV4dENvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudC10ZXh0L2NvbXBvbmVudC10ZXh0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUZXh0VG9rZW5Db250ZXh0IH0gZnJvbSAnLi4vLi4vdGV4dCc7XG5pbXBvcnQgeyBOT19WQUxVRV9LRVlTLCBpc0RyYXduLCB2YWx1ZUtleXMgfSBmcm9tICcuLi8uLi92YWx1ZXMnO1xuaW1wb3J0IHsgQ2FudmFzU25hcHBlciwgUFhfUEVSX0lOQ0ggfSBmcm9tICcuLi9yZXBvcnQtY2FudmFzL3JlcG9ydC1jYW52YXMuY29tcG9uZW50JztcblxuXG4vLyBSZXNpemUgaGFuZGxlcywgbmFtZWQgYnkgY29tcGFzcyBkaXJlY3Rpb24uXG5jb25zdCBIQU5ETEVTID0gWydudycsICduJywgJ25lJywgJ2UnLCAnc2UnLCAncycsICdzdycsICd3J10gYXMgY29uc3Q7XG50eXBlIEhhbmRsZSA9IHR5cGVvZiBIQU5ETEVTW251bWJlcl07XG5cbmNvbnN0IE1JTl9XID0gMC42OyAvLyBpbmNoZXNcbmNvbnN0IE1JTl9IID0gMC40OyAvLyBpbmNoZXNcblxuLy8gVHdvIHByZXNzZXMgb24gYSB0ZXh0IGJsb2NrIHRoaXMgY2xvc2UgdG9nZXRoZXIgb3BlbiBpdHMgZWRpdG9yLiBEZXRlY3RlZFxuLy8gaGVyZSByYXRoZXIgdGhhbiB3aXRoIGEgZGJsY2xpY2sgbGlzdGVuZXIgYmVjYXVzZSB0aGUgZHJhZyBsb29wIGNsYWltcyB0aGVcbi8vIHBvaW50ZXIgb24gZXZlcnkgcHJlc3MsIGFuZCBhIGJyb3dzZXIgaXMgbm90IG9ibGlnZWQgdG8gZGVsaXZlciBkYmxjbGlja1xuLy8gdGhyb3VnaCBhIGNhcHR1cmVkLCBkZWZhdWx0LXByZXZlbnRlZCBwb2ludGVyLlxuY29uc3QgRE9VQkxFX1BSRVNTX01TID0gNDAwO1xuXG4vLyBPbmUgY29tcG9uZW50IG9uIHRoZSBwYWdlOiB0aXRsZSBiYXIsIHRoZSB0eXBlLXNwZWNpZmljIGJvZHkgKGNoYXJ0IHwgbGlzdFxuLy8gfCBrcGkpLCBhIG1lbnUgKHNldHRpbmdzLCBmaWx0ZXIgdG9nZ2xlcywgZXhwb3J0KSDigJQgYW5kIHRoZSBlZGl0aW5nXG4vLyBpbnRlcmFjdGlvbnM6IGNsaWNrIHNlbGVjdHM7IHRoZSBzZWxlY3Rpb24gZnJhbWUgc2hvd3MgOCByZXNpemUgaGFuZGxlcztcbi8vIGRyYWdnaW5nIHRoZSBib2R5IG1vdmVzIHdpdGggc21hcnQgYWxpZ25tZW50IGd1aWRlcyAodmlhIHRoZSBjYW52YXNcbi8vIHNuYXBwZXIpOyBldmVyeXRoaW5nIHdvcmtzIGF0IGFueSB6b29tIChwaXhlbCBkZWx0YXMgw7cgem9vbcK3OTYg4oaSIGluY2hlcykuXG4vL1xuLy8gQ2hhcnRzIGFuZCBLUElzIGZldGNoIHRoZWlyIG93biBkYXRhIGhlcmU7IGxpc3RzIGZldGNoIGluc2lkZVxuLy8gQ29tcG9uZW50TGlzdENvbXBvbmVudCB0aHJvdWdoIEZzTGlzdCBwYWdpbmcuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtcmVwb3J0LWNvbXBvbmVudCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9yZXBvcnQtY29tcG9uZW50LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vcmVwb3J0LWNvbXBvbmVudC5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIE1hdEljb24sXG4gICAgTWF0SWNvbkJ1dHRvbixcbiAgICBNYXRQcm9ncmVzc0JhcixcbiAgICBNYXRUb29sdGlwLFxuICAgIEZzRmlsdGVyTW9kdWxlLFxuICAgIEZzTWVudU1vZHVsZSxcbiAgICBDb21wb25lbnRDaGFydENvbXBvbmVudCxcbiAgICBDb21wb25lbnRLcGlDb21wb25lbnQsXG4gICAgQ29tcG9uZW50TGlzdENvbXBvbmVudCxcbiAgICBDb21wb25lbnRUZXh0Q29tcG9uZW50LFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBSZXBvcnRDb21wb25lbnRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcyB7XG5cbiAgQElucHV0KCkgcHVibGljIHJlcG9ydElkOiBudW1iZXI7XG4gIEBJbnB1dCgpIHB1YmxpYyBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudE1vZGVsO1xuICBASW5wdXQoKSBwdWJsaWMgZ3JvdXBzOiBNYXA8bnVtYmVyLCBSZXBvcnRGaWx0ZXJHcm91cD47XG4gIEBJbnB1dCgpIHB1YmxpYyBlZGl0TW9kZSA9IGZhbHNlO1xuICAvLyBUaGUgY2FudmFzIHpvb20g4oCUIGNvbnZlcnRzIG9uLXNjcmVlbiBwaXhlbCBkZWx0YXMgYmFjayB0byBpbmNoZXMuXG4gIEBJbnB1dCgpIHB1YmxpYyB6b29tID0gMTtcbiAgQElucHV0KCkgcHVibGljIHNuYXBwZXI6IENhbnZhc1NuYXBwZXIgfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgcHVibGljIHNlbGVjdGVkID0gZmFsc2U7XG5cbiAgQE91dHB1dCgpIHB1YmxpYyBzZWxlY3RDb21wb25lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBwb3NpdGlvbkNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHsgY29tcG9uZW50SWQ6IG51bWJlciB9ICYgUmVjb3JkPHN0cmluZywgbnVtYmVyPj4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvcGVuU2V0dGluZ3MgPSBuZXcgRXZlbnRFbWl0dGVyPFJlcG9ydENvbXBvbmVudE1vZGVsPigpO1xuXG4gIC8vIFdoYXQgYSB0ZXh0IGJsb2NrJ3Mge3t0b2tlbnN9fSBmaWxsIHdpdGggb24gdGhlIHBhZ2UgaXQgaXMgZHJhd24gb24uXG4gIHB1YmxpYyByZWFkb25seSB0b2tlbnMgPSBpbnB1dDxUZXh0VG9rZW5Db250ZXh0Pih7IHBhZ2VOdW1iZXI6IDEsIHBhZ2VOYW1lOiAnJywgcmVwb3J0TmFtZTogJycgfSk7XG5cbiAgLy8gVGhlIHZhbHVlIGtleXMgdGhlIG90aGVyIHRleHQgYmxvY2tzIG9mIGEgdGV4dCdzIGxheWVyIHNob3csIHJlYWQgYnkgdGhlXG4gIC8vIGNhbnZhcyB3aGVuIHRoZSB0ZXh0J3MgZWRpdG9yIGFza3MuXG4gIHB1YmxpYyByZWFkb25seSB2YWx1ZUtleXNFbHNld2hlcmUgPSBpbnB1dDwoKHRleHQ6IFJlcG9ydENvbXBvbmVudE1vZGVsKSA9PiBSZWFkb25seVNldDxzdHJpbmc+KSB8IG51bGw+KG51bGwpO1xuXG4gIC8vIEEgdGV4dCBibG9jayB3YXMgZGVsZXRlZCBmcm9tIGl0cyBtZW51IOKAlCB0aGUgY2FudmFzIGRyb3BzIGl0LlxuICBwdWJsaWMgcmVhZG9ubHkgcmVtb3ZlZCA9IG91dHB1dDxudW1iZXI+KCk7XG5cbiAgLy8gQSB2YWx1ZSdzIHNldHRpbmdzIHdlcmUgYXNrZWQgZm9yIGZyb20gaXRzIGNoaXAgaW4gdGhlIHRleHQsIGJ5IHRoZVxuICAvLyB2YWx1ZSdzIGtleS4gVGhlIGNhbnZhcyBvcGVucyB0aGVtLlxuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVTZXR0aW5ncyA9IG91dHB1dDxzdHJpbmc+KCk7XG5cbiAgLy8gVGhlIHRleHQncyBodG1sIHdhcyBzYXZlZC4gRW1pdHRlZCBvbiB0aGUgcmVzcG9uc2UsIHNvIHRoZSBzZXJ2ZXIgYWxyZWFkeVxuICAvLyBob2xkcyB0aGUgaHRtbCB3aGVuIHRoZSBjYW52YXMgcmVhZHMgdGhlIHZhbHVlcyBpdCBzaG93cy5cbiAgcHVibGljIHJlYWRvbmx5IHRleHRTYXZlZCA9IG91dHB1dDxzdHJpbmc+KCk7XG5cbiAgLy8gRGVsZXRpbmcgdGhlIHRleHQgYWxzbyBkZWxldGVkIHRoZSB2YWx1ZXMgbm8gb3RoZXIgdGV4dCBvbiBpdHMgcGFnZSByZWFkcyxcbiAgLy8gYnkgaWQuIFRoZSBjYW52YXMgaGFzIHRoZSByZXBvcnQgcmVsb2FkZWQuXG4gIHB1YmxpYyByZWFkb25seSB2YWx1ZXNSZW1vdmVkID0gb3V0cHV0PG51bWJlcltdPigpO1xuXG4gIC8vIFRoZSB0ZXh0IGJsb2NrJ3MgZWRpdG9yIGlzIG9wZW4gKGRvdWJsZS1wcmVzcyBpbiBlZGl0IG1vZGUpLiBDbG9zZWQgYnkgZm9jdXNcbiAgLy8gbGVhdmluZyB0aGUgYmxvY2ssIGJ5IGRlc2VsZWN0aW5nIGl0LCBvciBieSBsZWF2aW5nIGVkaXQgbW9kZSDigJQgZWFjaCBvZlxuICAvLyB3aGljaCBzYXZlcy5cbiAgcHVibGljIHJlYWRvbmx5IHRleHRFZGl0aW5nID0gc2lnbmFsKGZhbHNlKTtcbiAgLy8gQSB0ZXh0IGJsb2NrJ3MgaHRtbCBhcyBsYXN0IHNhdmVkIGhlcmU7IG51bGwgdW50aWwgdGhlbiwgc28gdGhlIGJsb2NrXG4gIC8vIHNob3dzIGl0cyBzdG9yZWQgaHRtbC5cbiAgcHVibGljIHJlYWRvbmx5IHRleHRIdG1sID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuXG4gIC8vIFdoYXQgdGhlIG90aGVyIHRleHQgYmxvY2tzIG9mIHRoaXMgdGV4dCdzIGxheWVyIHNob3csIGZvciBpdHMgZWRpdG9yJ3NcbiAgLy8gbm90aWNlLiBTdGFibGUsIHNvIHRoZSB0ZXh0IGJsb2NrJ3MgaW5wdXQgbmV2ZXIgY2hhbmdlczsgaXQgYXNrcyB3aGVuIGFuXG4gIC8vIGVkaXQgdGFrZXMgYSB2YWx1ZSdzIGxhc3QgY2hpcCBvdXQuXG4gIHB1YmxpYyByZWFkb25seSBzaG93bkVsc2V3aGVyZSA9ICgpOiBSZWFkb25seVNldDxzdHJpbmc+ID0+XG4gICAgdGhpcy52YWx1ZUtleXNFbHNld2hlcmUoKT8uKHRoaXMuY29tcG9uZW50KSA/PyBOT19WQUxVRV9LRVlTO1xuXG4gIEBWaWV3Q2hpbGQoQ29tcG9uZW50Q2hhcnRDb21wb25lbnQpXG4gIHB1YmxpYyBjaGFydENvbXBvbmVudDogQ29tcG9uZW50Q2hhcnRDb21wb25lbnQ7XG5cbiAgLy8gUmVzaXplIGhhbmRsZXMgYnkgdHlwZTogYSBmaXhlZC1oZWlnaHQgY29tcG9uZW50IChjaGFydC9saXN0KVxuICAvLyBnZXRzIGFsbCBlaWdodCAocmVzaXplIHdpZHRoIEFORCBoZWlnaHQpOyBhbiBhdXRvLWhlaWdodCBvbmUgKGtwaSkgZ2V0c1xuICAvLyBvbmx5IHRoZSBzaWRlIGhhbmRsZXMgc2luY2UgaXRzIGhlaWdodCBmaXRzIGl0cyBjb250ZW50IGFuZCBjYW4ndCBiZSBzZXQuXG4gIHB1YmxpYyBnZXQgcmVzaXplSGFuZGxlcygpOiByZWFkb25seSBIYW5kbGVbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2hlaWdodEF1dG8gPyBbJ2UnLCAndyddIDogSEFORExFUztcbiAgfVxuXG4gIC8vIFRoZSBjb21wb25lbnQncyBoZWFkZXIgSVMgYW4gZnMtZmlsdGVyOiBoZWFkaW5nIHRlbXBsYXRlID0gaXRzIHRpdGxlIChhbmRcbiAgLy8gdGhlIGRyYWcgaGFuZGxlKSwgYWN0aW9ucyA9IHRoZSBTZXR0aW5ncyAvIGZpbHRlci10b2dnbGVzIC8gRXhwb3J0IG1lbnUsXG4gIC8vIGl0ZW1zID0gaXRzIGNvbXBvbmVudC1sZXZlbCBmaWx0ZXIgZ3JvdXBzLCBmb3IgZXZlcnkgY29tcG9uZW50IHR5cGUsIGxpc3RzXG4gIC8vIGluY2x1ZGVkLCBwbHVzIGEgbGlzdCdzIHNlYXJjaCBib3guIFJlYnVpbHQgd2hlbiBhIGZpbHRlciB0b2dnbGUgY2hhbmdlcyB3aGljaCBncm91cHMgc2hvdyxcbiAgLy8gYW5kIHdoZW4gdGhlIHNldHRpbmdzIGRpYWxvZyBjaGFuZ2VzIHRoZSB0aXRsZSBvciBwYWRkaW5nOiBzZXR0aW5nIGl0XG4gIC8vIHJlcGFpbnRzIHRoZSBoZWFkZXIgYW5kIGJvZHkuXG4gIHB1YmxpYyByZWFkb25seSBmaWx0ZXJDb25maWcgPSBzaWduYWw8RmlsdGVyQ29uZmlnIHwgbnVsbD4obnVsbCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGRhdGEgPSBzaWduYWw8Q29tcG9uZW50RGF0YSB8IG51bGw+KG51bGwpO1xuICAvLyBUaGUgc2hpbW1lcjogb25seSB3aGlsZSB0aGUgdGlsZSBoYXMgbm8gZGF0YSB0byBzaG93IHlldC4gQSByZWZldGNoIGtlZXBzXG4gIC8vIHRoZSBkYXRhIG9uIHNjcmVlbiBhbmQgc2V0cyBgcmVmcmVzaGluZ2AsIGEgdGhpbiBiYXIgb3ZlciB0aGUgYm9keS5cbiAgcHVibGljIHJlYWRvbmx5IGxvYWRpbmcgPSBzaWduYWwoZmFsc2UpO1xuICBwdWJsaWMgcmVhZG9ubHkgcmVmcmVzaGluZyA9IHNpZ25hbChmYWxzZSk7XG4gIHB1YmxpYyByZWFkb25seSBlcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyBXaGljaCBvZiBhIGNoYXJ0J3MgbGVnZW5kIGVudHJpZXMgYXJlIG9uLCBieSBzZXJpZXMgbmFtZS4gSGVsZCBoZXJlIGFuZFxuICAvLyBoYW5kZWQgdG8gZWFjaCBvcHRpb24gdGhlIGNoYXJ0IGJ1aWxkczogbmd4LWVjaGFydHMgc2V0cyBhbiBvcHRpb24gd2l0aFxuICAvLyBub3RNZXJnZSwgd2hpY2ggd291bGQgb3RoZXJ3aXNlIHR1cm4gZXZlcnkgZW50cnkgYmFjayBvbiBhdCBlYWNoIHJlZmV0Y2guXG4gIHB1YmxpYyByZWFkb25seSBsZWdlbmRTZWxlY3RlZCA9IHNpZ25hbDxSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuPj4+KHt9KTtcblxuICAvLyBBIGxpc3QgaXMgZHJhd24gYWdhaW4gd2hlbiBhIHJlc2V0IG1vdmVzIGl0cyBzb3J0OiBGc0xpc3QgcmVhZHMgaXRzIHNvcnRcbiAgLy8gb25seSB3aGVuIGl0IGlzIGNyZWF0ZWQuIEV2ZXJ5IG90aGVyIHJlc2V0IHJlbG9hZHMgaXQgaW4gcGxhY2UuXG4gIHB1YmxpYyByZWFkb25seSBsaXN0UmVzZXRLZXkgPSBjb21wdXRlZCgoKSA9PiB0aGlzLl9maWx0ZXJTdGF0ZS5saXN0U29ydFJlc2V0cygpLmdldCh0aGlzLmNvbXBvbmVudD8uaWQpID8/IDApO1xuXG4gIC8vIFdoYXQgYSBjbGljayBvbiB0aGlzIHRpbGUncyBtYXJrcyBtYXkgZG8gb24gaXRzIGxhc3QgYW5zd2VyOiB0aGUgY2hhcnRcbiAgLy8gc2hvd3MgYSBoYW5kIGFuZCBhIHRvb2x0aXAgaGludCBmb3IgdGhlbS4gKFdoaWxlIHRoZSBsYXlvdXQgaXMgZWRpdGVkIGFcbiAgLy8gdmVpbCBjb3ZlcnMgdGhlIGJvZHksIHNvIG5vIG1hcmsgaXMgaG92ZXJlZCBvciBjbGlja2VkLilcbiAgcHVibGljIHJlYWRvbmx5IHRpbGVBY3Rpb25zID0gY29tcHV0ZWQ8UmVwb3J0TWFya0FjdGlvbltdPigoKSA9PiB0aWxlTWFya0FjdGlvbnMoe1xuICAgIGRhdGE6IHRoaXMuZGF0YSgpLFxuICAgIGZlYXR1cmVzOiB0aGlzLl9vZmZlcmVkRmVhdHVyZXMoKSxcbiAgfSkpO1xuXG4gIC8vIFRoZSBhY3Rpb25zIHRoZSBtYXJrIG1lbnUgbGlzdHMgZm9yIHRoZSBjbGljayBpdCB3YXMgb3BlbmVkIG9uLlxuICBwdWJsaWMgcmVhZG9ubHkgbWFya01lbnVBY3Rpb25zID0gc2lnbmFsPFJlcG9ydE1hcmtBY3Rpb25bXT4oW10pO1xuICBwdWJsaWMgcmVhZG9ubHkgbWFya0FjdGlvbkxhYmVscyA9IE1BUktfQUNUSU9OX0xBQkVMUztcblxuICAvLyBUaGUgYnJlYWRjcnVtYiBhZnRlciB0aGUgdGl0bGUgd2hpbGUgdGhlIGNoYXJ0IGlzIGRyaWxsZWQgKCcyMDI2JywgJ1EzJyksXG4gIC8vIG9uZSBsYWJlbCBwZXIgc3RlcCBvZiBpdHMgcGF0aCwgaW4gdGhlIHJlcG9ydCdzIGxvY2FsZS4gRW1wdHkgYXQgdGhlIHRvcFxuICAvLyBhbmQgd2hpbGUgdGhlIHZpZXdlciBpcyBub3Qgb2ZmZXJlZCBkcmlsbDogYSBwYXRoIGFuIG9sZGVyIHNlcnZlciBuZXZlclxuICAvLyBhcHBsaWVzIGlzIGtlcHQgZm9yIHRoZSBsaW5rLCBidXQgbm90IHNob3duLlxuICBwdWJsaWMgcmVhZG9ubHkgZHJpbGxDcnVtYnMgPSBjb21wdXRlZDxzdHJpbmdbXT4oKCkgPT4gKHRoaXMuX29mZmVyZWRGZWF0dXJlcygpLmluY2x1ZGVzKCdkcmlsbCcpXG4gICAgPyBkcmlsbENydW1iTGFiZWxzKHRoaXMuX2ZpbHRlclN0YXRlLmRyaWxsKHRoaXMuY29tcG9uZW50Py5pZCksIHRoaXMuX2ZpbHRlclN0YXRlLmZvcm1hdENvbnRleHQoKSlcbiAgICA6IFtdKSk7XG4gIHB1YmxpYyByZWFkb25seSBkcmlsbFNlcGFyYXRvciA9IERSSUxMX0NSVU1CX1NFUEFSQVRPUjtcblxuICAvLyBXaGF0IGFuIGVtcHR5IHRpbGUgc2F5czogdGhlIGRyaWxsZWQgcGVyaW9kIGl0IHJlYWRzIG5vIGRheSBvZiwgZWxzZVxuICAvLyAnTm8gZGF0YScuXG4gIHB1YmxpYyByZWFkb25seSBlbXB0eU1lc3NhZ2UgPSBjb21wdXRlZCgoKSA9PiBkcmlsbE91dHNpZGVNZXNzYWdlKFxuICAgIHRoaXMuZGF0YSgpPy5kcmlsbCxcbiAgICB0aGlzLl9maWx0ZXJTdGF0ZS5mb3JtYXRDb250ZXh0KCksXG4gICkgPz8gJ05vIGRhdGEnKTtcblxuICBAVmlld0NoaWxkKCdtYXJrTWVudScpXG4gIHB1YmxpYyBtYXJrTWVudTogRnNNZW51Q29tcG9uZW50O1xuXG4gIEBWaWV3Q2hpbGQoJ21hcmtBbmNob3InKVxuICBwdWJsaWMgbWFya0FuY2hvcjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfdGV4dCA9IHZpZXdDaGlsZChDb21wb25lbnRUZXh0Q29tcG9uZW50KTtcbiAgcHJpdmF0ZSBfcmVmcmVzaCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAvLyBUaGUgc3RhdGUgdmVyc2lvbiB0aGUgaGVhZGVyIHdhcyBsYXN0IGJ1aWx0IGZvciAoZmlsdGVyS2V5KS5cbiAgcHJpdmF0ZSByZWFkb25seSBfaGVhZGVyVmVyc2lvbiA9IHNpZ25hbCgwKTtcbiAgLy8gVGhlIGhlYWRlciBncm91cHMnIHZhbHVlcyBhcyB0aGUgaGVhZGVyIGxhc3Qgc2hvd2VkIHRoZW06IGFzIGl0IHdhc1xuICAvLyBidWlsdCwgdGhlbiBhcyBpdHMgb3duIGJhciByZXBvcnRlZCBlYWNoIGNoYW5nZS4gZmlsdGVyS2V5IGNhcnJpZXMgdGhlaXJcbiAgLy8gc2lnbmF0dXJlIGFzIGJ1aWx0LlxuICBwcml2YXRlIF9zaG93biA9IG5ldyBNYXA8bnVtYmVyLCBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfaGVhZGVyVmFsdWVzID0gc2lnbmFsKCcnKTtcbiAgcHJpdmF0ZSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSBfZmlsdGVyU3RhdGUgPSBpbmplY3QoUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBfZmlsdGVyT3B0aW9ucyA9IGluamVjdChSZXBvcnRGaWx0ZXJPcHRpb25zU2VydmljZSk7XG4gIHByaXZhdGUgX3Byb2Nlc3MgPSBpbmplY3QoRnNQcm9jZXNzKTtcbiAgcHJpdmF0ZSBfbWVzc2FnZSA9IGluamVjdChGc01lc3NhZ2UpO1xuICBwcml2YXRlIF9wcm9tcHQgPSBpbmplY3QoRnNQcm9tcHQpO1xuICBwcml2YXRlIF9kaWFsb2cgPSBpbmplY3QoTWF0RGlhbG9nKTtcbiAgcHJpdmF0ZSBfbGFzdFByZXNzID0gMDtcbiAgcHJpdmF0ZSBfZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcbiAgcHJpdmF0ZSBfem9uZSA9IGluamVjdChOZ1pvbmUpO1xuICBwcml2YXRlIF9ob3N0OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgLy8gVGhlIGZlYXR1cmVzIGEgbWFyayBhY3Rpb24gbmVlZHM6IHNlcnZlZCBieSB0aGUgcmVwb3J0J3Mgc2VydmVyIGFuZFxuICAvLyBpbXBsZW1lbnRlZCBieSB0aGlzIHZpZXdlci5cbiAgcHJpdmF0ZSByZWFkb25seSBfb2ZmZXJlZEZlYXR1cmVzID0gY29tcHV0ZWQoKCkgPT4gb2ZmZXJlZFZpZXdlckZlYXR1cmVzKHRoaXMuX2ZpbHRlclN0YXRlLnZpZXdlckZlYXR1cmVzKCkpKTtcbiAgLy8gVGhlIG1hcmsgYSBmaXJzdCB0YXAgcHJldmlld2VkIChkZWNpZGVNYXJrQ2xpY2spLCBhbmQgdGhlIGNsaWNrIHRoZSBtYXJrXG4gIC8vIG1lbnUgaXMgb3BlbiBmb3IuXG4gIHByaXZhdGUgX3RvdWNoZWRNYXJrOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfbWVudUNsaWNrOiBSZXBvcnRNYXJrQ2xpY2sgfCBudWxsID0gbnVsbDtcbiAgLy8gVGhlIGdyb3VwLWJ5IG1vdmVkIHNpbmNlIHRoZSBsYXN0IGFuc3dlcjogYSBwYXRoIHRoZSBzZXJ2ZXIgdGhlbiBkcm9wc1xuICAvLyBiZWNhdXNlIGl0IG5vIGxvbmdlciBzdGFydHMgYXQgdGhlIGNoYXJ0J3MgdG9wIGlzIG5vdCBuZXdzIHRvIHRoZSB2aWV3ZXIuXG4gIHByaXZhdGUgX2dyYWluTW92ZWQgPSBmYWxzZTtcblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5fYnVpbGRGaWx0ZXJDb25maWcoKTtcblxuICAgIGlmICghdGhpcy5pc1RleHQpIHtcbiAgICAgIHRoaXMuX3JlYnVpbGRIZWFkZXJPbk5ld1N0YXRlKCk7XG4gICAgfVxuXG4gICAgLy8gTGlzdHMgZmV0Y2ggdGhyb3VnaCBGc0xpc3Q7IHRleHQgaGFzIG5vdGhpbmcgdG8gZmV0Y2gsIGFuZCBhIHZhbHVlIGlzXG4gICAgLy8gbmV2ZXIgZHJhd24gKGl0IHJlYWRzIGluc2lkZSB0ZXh0KS5cbiAgICBpZiAodGhpcy5jb21wb25lbnQudHlwZSAhPT0gJ2xpc3QnICYmICF0aGlzLmlzVGV4dCAmJiBpc0RyYXduKHRoaXMuY29tcG9uZW50KSkge1xuICAgICAgLy8gT25lIGxvYWQgc3RyZWFtICh0aWxlTG9hZHMpOiB0aGUgZmlyc3QgbG9hZCBhdCBvbmNlLCB0aGVuIG9uZSBwZXJcbiAgICAgIC8vIHNldHRsZWQgc3dlZXAgb2YgY2hhbmdlcywgZWFjaCBjYW5jZWxsaW5nIHRoZSBvbmUgaW4gZmxpZ2h0LCBhbmQgYW5cbiAgICAgIC8vIGFuc3dlciBzZW50IGJlZm9yZSBhIHZpZXcgd2FzIGFwcGxpZWQgaXMgZHJvcHBlZC5cbiAgICAgIHRpbGVMb2Fkcyh0aGlzLl9yZWZyZXNoJCwgKCkgPT4gdGhpcy5fbG9hZCgpLCAoKSA9PiB0aGlzLl9maWx0ZXJTdGF0ZS5zdGF0ZVZlcnNpb24oKSlcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFwKChyZXN1bHQpID0+IHRoaXMuX2xvYWRlZChyZXN1bHQpKSxcbiAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgpO1xuXG4gICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5jaGFuZ2VzRm9yKHRoaXMuY29tcG9uZW50KVxuICAgICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fcmVmcmVzaCQubmV4dCgpKTtcblxuICAgICAgLy8gQSBncm91cC1ieSBjaGFuZ2UgcmUtYnVja2V0cyBldmVyeSB0aW1lLXNlcmllcyBjaGFydDsgaXQgaXNuJ3Qgc2NvcGVkXG4gICAgICAvLyB0byBhIGZpbHRlciBncm91cCwgc28gaXQgcmlkZXMgaXRzIG93biBzdHJlYW0uXG4gICAgICBpZiAodGhpcy5faXNUaW1lU2VyaWVzKSB7XG4gICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLmZyZXF1ZW5jeUNoYW5nZXMoKVxuICAgICAgICAgIC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX2dyYWluTW92ZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5fcmVmcmVzaCQubmV4dCgpO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBBIGRyaWxsIG1vdmVzIHRoaXMgY2hhcnQgYWxvbmUuXG4gICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5kcmlsbENoYW5nZXModGhpcy5jb21wb25lbnQuaWQpXG4gICAgICAgIC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9yZWZyZXNoJC5uZXh0KCkpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRoZSByZXBvcnQgcmVsb2FkcyAoZS5nLiBhZnRlciB0aGUgc2V0dGluZ3MgZGlhbG9nIGFkZHMvbW92ZXMgYSBmaWx0ZXIpXG4gIC8vIGhhbmQgdGhpcyBpbnN0YW5jZSBmcmVzaCBgY29tcG9uZW50YC9gZ3JvdXBzYCBpbnB1dHMgd2l0aG91dCByZS1ydW5uaW5nXG4gIC8vIG5nT25Jbml0LiBSZWJ1aWxkIHRoZSBoZWFkZXIgY29uZmlnIHNvIHRoZSBpbmxpbmUgY29tcG9uZW50LWZpbHRlciBzdHJpcFxuICAvLyByZWZsZWN0cyB0aGUgbmV3IGZpbHRlcnM7IHRoZSB0ZW1wbGF0ZSByZWNyZWF0ZXMgdGhlIGZzLWZpbHRlciB2aWFcbiAgLy8gYGZpbHRlcktleWAgc28gaXQgYWN0dWFsbHkgcmUtcmVhZHMgdGhpcyBjb25maWcuXG4gIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgLy8gQ2xpY2tpbmcgYXdheSAoZGVzZWxlY3QpIG9yIGxlYXZpbmcgZWRpdCBtb2RlIGNsb3NlcyBhbiBvcGVuIHRleHQgZWRpdG9yLFxuICAgIC8vIHdoaWNoIGlzIHdoYXQgc2F2ZXMgaXQuXG4gICAgaWYgKChjaGFuZ2VzLnNlbGVjdGVkICYmICF0aGlzLnNlbGVjdGVkKSB8fCAoY2hhbmdlcy5lZGl0TW9kZSAmJiAhdGhpcy5lZGl0TW9kZSkpIHtcbiAgICAgIHRoaXMudGV4dEVkaXRpbmcuc2V0KGZhbHNlKTtcbiAgICB9XG5cbiAgICAvLyBBIG5ldyBjb21wb25lbnQgb2JqZWN0IGNhcnJpZXMgaXRzIG93biBzdG9yZWQgaHRtbC5cbiAgICBpZiAoY2hhbmdlcy5jb21wb25lbnQgJiYgIWNoYW5nZXMuY29tcG9uZW50LmZpcnN0Q2hhbmdlKSB7XG4gICAgICB0aGlzLnRleHRIdG1sLnNldChudWxsKTtcbiAgICB9XG5cbiAgICBjb25zdCBmaWx0ZXJzQ2hhbmdlZCA9IChjaGFuZ2VzLmNvbXBvbmVudCAmJiAhY2hhbmdlcy5jb21wb25lbnQuZmlyc3RDaGFuZ2UpXG4gICAgICB8fCAoY2hhbmdlcy5ncm91cHMgJiYgIWNoYW5nZXMuZ3JvdXBzLmZpcnN0Q2hhbmdlKTtcblxuICAgIGlmIChmaWx0ZXJzQ2hhbmdlZCkge1xuICAgICAgdGhpcy5fYnVpbGRGaWx0ZXJDb25maWcoKTtcbiAgICB9XG4gIH1cblxuICAvLyBmcy1maWx0ZXIgcmVhZHMgaXRzIGNvbmZpZyBvbmx5IG9uY2UgYXQgaW5pdCwgc28gdGhlIGhlYWRlciBpcyBrZXllZCBvbiB3aGF0XG4gIC8vIGl0IHJlbmRlcnM6IHRoZSBzZXQgb2YgY29tcG9uZW50LWxldmVsIGZpbHRlciBncm91cHMgQU5EIHRoZSB0aXRsZSwgd2hpY2hcbiAgLy8gbGl2ZXMgaW4gZnMtZmlsdGVyJ3MgaGVhZGluZyB0ZW1wbGF0ZS4gZnMtZmlsdGVyIGlzIE9uUHVzaCBhbmQgdGhlIGhlYWRpbmcgaXNcbiAgLy8gcmVuZGVyZWQgaW5zaWRlIElUUyB2aWV3LCBzbyBtYXJraW5nIHRoaXMgY29tcG9uZW50IGRvZXMgbm90IHJlcGFpbnQgdGhlXG4gIC8vIHRpdGxlIOKAlCByZWNyZWF0aW5nIHRoZSBibG9jayBkb2VzLiBUaGUga2V5IGFsc28gY2FycmllcyB0aGUgc3RhdGUgdmVyc2lvblxuICAvLyB0aGUgaGVhZGVyIHdhcyBidWlsdCBmb3IsIHNvIGFuIGFwcGxpZWQgdmlldywgd2hpY2ggcmVwbGFjZXMgZXZlcnkgdmFsdWVcbiAgLy8gYXQgb25jZSwgcmVjcmVhdGVzIGl0IHdpdGggdGhlIG5ldyB2YWx1ZXMuIEFuZCBpdCBjYXJyaWVzIHRoZSB2YWx1ZXMgdGhlXG4gIC8vIGhlYWRlciB3YXMgYnVpbHQgd2l0aDogYSBncm91cCBzaG93biBoZXJlIGFuZCBpbiB0aGUgcmVwb3J0IGJhciAobGV2ZWxcbiAgLy8gJ2JvdGgnKSB0aGF0IHRoZSByZXBvcnQgYmFyIGNoYW5nZXMgaXMgYnVpbHQgYWdhaW4gaGVyZSwgc28gdGhlIGhlYWRlclxuICAvLyBuZXZlciBzaG93cyAnV2VzdCcgd2hpbGUgdGhlIGRhdGEgbGVhdmVzIFdlc3Qgb3V0LlxuICBwdWJsaWMgZ2V0IGZpbHRlcktleSgpOiBzdHJpbmcge1xuICAgIHJldHVybiBbXG4gICAgICB0aGlzLl9oZWFkZXJWZXJzaW9uKCksXG4gICAgICB0aGlzLmNvbXBvbmVudC50aXRsZSxcbiAgICAgIC4uLnRoaXMuY29tcG9uZW50RmlsdGVyR3JvdXBzLm1hcCgoZ3JvdXApID0+IGAke2dyb3VwLmlkfToke2dyb3VwLmxldmVsfWApLFxuICAgICAgdGhpcy5faGVhZGVyVmFsdWVzKCksXG4gICAgXS5qb2luKCd8Jyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGlzVGV4dCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnQudHlwZSA9PT0gJ3RleHQnO1xuICB9XG5cbiAgLy8gT3BlbiB0aGUgdGV4dCBlZGl0b3IgaW4gcGxhY2UuXG4gIHB1YmxpYyBlZGl0VGV4dCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZWRpdE1vZGUgfHwgIXRoaXMuaXNUZXh0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zZWxlY3RDb21wb25lbnQuZW1pdCh0aGlzLmNvbXBvbmVudC5pZCk7XG4gICAgdGhpcy50ZXh0RWRpdGluZy5zZXQodHJ1ZSk7XG4gIH1cblxuICAvLyBUYWtlIGEgZGVsZXRlZCB2YWx1ZSdzIGNoaXBzIG91dCBvZiB0aGUgdGV4dCdzIG9wZW4gZWRpdG9yLlxuICBwdWJsaWMgcmVtb3ZlVmFsdWUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl90ZXh0KCk/LnJlbW92ZVZhbHVlKGtleSk7XG4gIH1cblxuICAvLyBUaGUgZWRpdG9yIGNsb3NlZCB3aXRoIGNoYW5nZWQgaHRtbC4gS2VwdCBsb2NhbGx5IGF0IG9uY2Ugc28gdGhlIGJsb2NrXG4gIC8vIHJlLXJlbmRlcnMgd2hhdCB3YXMgdHlwZWQsIHRoZW4gcmVwbGFjZWQgYnkgd2hhdCB0aGUgc2VydmVyIHN0b3JlZDogaXRcbiAgLy8gcmVidWlsZHMgdGhlIGh0bWwgZnJvbSBpdHMgYWxsb3dsaXN0IGFuZCBkcm9wcyBhbnkgdmFsdWUgdG9rZW4gaXRzIHBhZ2UgaGFzXG4gIC8vIG5vIHZhbHVlIGZvciwgc28gdGhlIGJsb2NrIG5ldmVyIGhvbGRzIGEgdG9rZW4gdGhlIHNlcnZlciBkb2Vzbid0LlxuICBwdWJsaWMgb25UZXh0U2F2ZWQoaHRtbDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5fc2V0VGV4dEh0bWwoaHRtbCk7XG4gICAgdGhpcy5fcmVwb3J0RGF0YS51cGRhdGVDb21wb25lbnQodGhpcy5yZXBvcnRJZCwgdGhpcy5jb21wb25lbnQuaWQsIHsgaHRtbCB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcCgocmVzcG9uc2UpID0+ICh0eXBlb2YgcmVzcG9uc2U/LmNvbmZpZz8uaHRtbCA9PT0gJ3N0cmluZycgPyByZXNwb25zZS5jb25maWcuaHRtbCBhcyBzdHJpbmcgOiBodG1sKSksXG4gICAgICAgIHRhcCgoc3RvcmVkKSA9PiB7XG4gICAgICAgICAgdGhpcy5fc2V0VGV4dEh0bWwoc3RvcmVkKTtcbiAgICAgICAgICB0aGlzLnRleHRTYXZlZC5lbWl0KHN0b3JlZCk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvLyBUaGUgc2VydmVyIGRlbGV0ZXMgdGhlIHRleHQgYW5kIHRoZW4gZXZlcnkgdmFsdWUgb24gaXRzIHBhZ2UgdGhhdCBubyBvdGhlclxuICAvLyB0ZXh0IHNob3dzLCBhbmQgYW5zd2VycyB3aXRoIHRoZWlyIGlkcy5cbiAgcHVibGljIGRlbGV0ZVRleHQoKTogdm9pZCB7XG4gICAgY29uc3QgdmFsdWVzTm90ZSA9IHZhbHVlS2V5cyh0aGlzLmNvbXBvbmVudC5jb25maWc/Lmh0bWwpLmxlbmd0aFxuICAgICAgPyAnIFZhbHVlcyBubyBvdGhlciB0ZXh0IG9uIHRoaXMgcGFnZSB1c2VzIGFyZSBkZWxldGVkIHdpdGggaXQuJ1xuICAgICAgOiAnJztcblxuICAgIHRoaXMuX3Byb21wdC5jb25maXJtKHtcbiAgICAgIHRpdGxlOiAnQ29uZmlybScsXG4gICAgICB0ZW1wbGF0ZTogYEFyZSB5b3Ugc3VyZSB5b3Ugd291bGQgbGlrZSB0byBkZWxldGUgdGhpcyB0ZXh0PyR7dmFsdWVzTm90ZX1gLFxuICAgIH0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX3JlcG9ydERhdGEuZGVsZXRlQ29tcG9uZW50KHRoaXMucmVwb3J0SWQsIHRoaXMuY29tcG9uZW50LmlkKSksXG4gICAgICAgIHRhcCgocmVzcG9uc2U6IHsgcmVtb3ZlZFZhbHVlcz86IG51bWJlcltdIH0pID0+IHtcbiAgICAgICAgICBpZiAocmVzcG9uc2U/LnJlbW92ZWRWYWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXNSZW1vdmVkLmVtaXQocmVzcG9uc2UucmVtb3ZlZFZhbHVlcyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMucmVtb3ZlZC5lbWl0KHRoaXMuY29tcG9uZW50LmlkKTtcbiAgICAgICAgfSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdHJ1bmNhdGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMuZGF0YSgpPy50cnVuY2F0ZWQ7XG4gIH1cblxuICAvLyBDb250ZW50IHBhZGRpbmcgKHRoZSBjYW52YXMgem9vbSBzY2FsZXMgdGhlIHBhZ2UgYXMgYSB3aG9sZSkuIEVhY2ggZWRnZVxuICAvLyBkZWZhdWx0cyB0byAxLzhcIi5cbiAgcHVibGljIGdldCBib2R5UGFkZGluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiBjb21wb25lbnRQYWRkaW5nQ3NzKHRoaXMuY29tcG9uZW50KTtcbiAgfVxuXG4gIC8vIFRoZSBjb21wb25lbnQtbGV2ZWwgZmlsdGVyIGdyb3VwcyB0aGF0IHNob3VsZCByZW5kZXIgYXMgYW4gaW5saW5lIGNvbnRyb2xcbiAgLy8gc3RyaXAgb24gVEhJUyBjb21wb25lbnQ6IGEgZ3JvdXAgaXMgaW5jbHVkZWQgd2hlbiBpdCdzIGxldmVsPWNvbXBvbmVudCBhbmRcbiAgLy8gaGFzIGFuIGVuYWJsZWQsIHNlc3Npb24tb24gZmlsdGVyIGhlcmUuIFJlcG9ydC1sZXZlbCBncm91cHMgbGl2ZSBpbiB0aGVcbiAgLy8gdG9wIGJhciBpbnN0ZWFkLiBMaXN0cyB1c2UgdGhpcyBzdHJpcCBsaWtlIGNoYXJ0cyBkbzogYSB2YWx1ZSBzZXQgaGVyZSBpc1xuICAvLyB0aGUgZ3JvdXAncyB2YWx1ZSwgc28gaXQgcmVhY2hlcyBldmVyeSBjb21wb25lbnQgaW4gdGhlIGdyb3VwLlxuICBwdWJsaWMgZ2V0IGNvbXBvbmVudEZpbHRlckdyb3VwcygpOiBSZXBvcnRGaWx0ZXJHcm91cFtdIHtcbiAgICBpZiAoIXRoaXMuZ3JvdXBzKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgZ3JvdXBJZHMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiB0aGlzLmNvbXBvbmVudC5maWx0ZXJzID8/IFtdKSB7XG4gICAgICBpZiAoIWZpbHRlci5lbmFibGVkIHx8IHRoaXMuX2ZpbHRlclN0YXRlLmlzRmlsdGVyRGlzYWJsZWQoZmlsdGVyLmlkKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5ncm91cHMuZ2V0KGZpbHRlci5maWx0ZXJHcm91cElkKTtcbiAgICAgIGlmIChncm91cCAmJiAoZ3JvdXAubGV2ZWwgPT09ICdjb21wb25lbnQnIHx8IGdyb3VwLmxldmVsID09PSAnYm90aCcpKSB7XG4gICAgICAgIGdyb3VwSWRzLmFkZChncm91cC5pZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFsuLi5ncm91cElkc10ubWFwKChpZCkgPT4gdGhpcy5ncm91cHMuZ2V0KGlkKSkuZmlsdGVyKEJvb2xlYW4pO1xuICB9XG5cbiAgcHVibGljIHNldHRpbmdzKCk6IHZvaWQge1xuICAgIHRoaXMub3BlblNldHRpbmdzLmVtaXQodGhpcy5jb21wb25lbnQpO1xuICB9XG5cbiAgLy8gV2hldGhlciB0aGUgbWVudSBvZmZlcnMgQ29sdW1uczogYSBwbGFpbiBsaXN0IHdpdGggbW9yZSB0aGFuIG9uZVxuICAvLyBjb25maWd1cmVkIGNvbHVtbi4gQSBjcm9zcy10YWIncyBjb2x1bW5zIGNvbWUgYW5kIGdvIHdpdGggdGhlIGRhdGEuXG4gIHB1YmxpYyBnZXQgaGlkZXNDb2x1bW5zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudC50eXBlID09PSAnbGlzdCcgJiYgbGlzdEhpZGVhYmxlQ29sdW1ucyh0aGlzLmNvbXBvbmVudC5jb25maWcpLmxlbmd0aCA+IDE7XG4gIH1cblxuICAvLyBXaGljaCBvZiBhIHBsYWluIGxpc3QncyBjb2x1bW5zIHNob3cuIFRoZSBjaG9pY2UgaXMgdGhlIHZpZXdlcidzIChrZXB0IGluXG4gIC8vIHRoZSBVUkwsIG5ldmVyIHNhdmVkIHRvIHRoZSByZXBvcnQpLCBhbmQgdGhlIGxpc3QgaGlkZXMgdGhlIGNvbHVtbnMgaW5cbiAgLy8gcGxhY2UsIHdpdGggbm8gcmVmZXRjaC5cbiAgcHVibGljIGNob29zZUNvbHVtbnMoKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1ucyA9ICh0aGlzLmNvbXBvbmVudC5jb25maWc/LmNvbHVtbnMgPz8gW10pXG4gICAgICAubWFwKChjb2x1bW4pID0+ICh7IGNvbHVtbjogY29sdW1uLmNvbHVtbiwgbGFiZWw6IGNvbHVtbi5sYWJlbCB8fCBjb2x1bW4uY29sdW1uIH0pKTtcblxuICAgIHRoaXMuX2RpYWxvZy5vcGVuPExpc3RDb2x1bW5zQ29tcG9uZW50LCBMaXN0Q29sdW1uc0RpYWxvZ0RhdGEsIHN0cmluZ1tdPihMaXN0Q29sdW1uc0NvbXBvbmVudCwge1xuICAgICAgZGF0YTogeyBjb2x1bW5zLCBoaWRkZW46IFsuLi50aGlzLl9maWx0ZXJTdGF0ZS5oaWRkZW5Db2x1bW5zKHRoaXMuY29tcG9uZW50LmlkKV0gfSxcbiAgICAgIHdpZHRoOiAnNDAwcHgnLFxuICAgICAgbWF4V2lkdGg6ICc5NXZ3JyxcbiAgICAgIGF1dG9Gb2N1czogZmFsc2UsXG4gICAgfSlcbiAgICAgIC5hZnRlckNsb3NlZCgpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKChoaWRkZW4pID0+IHtcbiAgICAgICAgLy8gQ2FuY2VsIGNsb3NlcyB3aXRoIG5vdGhpbmcsIHdoaWNoIGNoYW5nZXMgbm90aGluZy5cbiAgICAgICAgaWYgKGhpZGRlbikge1xuICAgICAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLnNldEhpZGRlbkNvbHVtbnModGhpcy5jb21wb25lbnQuaWQsIGhpZGRlbik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gUHJlc2VudGF0aW9uIHNldHRpbmdzIHNhdmVkIGZyb20gdGhlIHNldHRpbmdzIGRpYWxvZy4gVGl0bGUgYW5kIHBhZGRpbmcgYXJlXG4gIC8vIG5vdCBwYXJ0IG9mIHRoZSBxdWVyeSwgc28gdGhlIGRhdGEgYWxyZWFkeSBmZXRjaGVkIHN0aWxsIHN0YW5kcyDigJQgdGhpcyBvbmx5XG4gIC8vIHJlcGFpbnRzLiBUaGUgaGVhZGVyIGNvbmZpZyBpcyByZWJ1aWx0IGJlY2F1c2UgYGZpbHRlcktleWAgY2hhbmdlcyB3aXRoIHRoZVxuICAvLyB0aXRsZSBhbmQgcmVjcmVhdGVzIHRoZSBmcy1maWx0ZXIgYmxvY2sgYXJvdW5kIGl0OyBzZXR0aW5nIHRoZSBjb25maWcgc2lnbmFsXG4gIC8vIGlzIGFsc28gd2hhdCByZXBhaW50cyB0aGUgbmV3IHBhZGRpbmcuIFRoZSBjaGFydCBmb2xsb3dzIGl0cyBib3ggb24gaXRzIG93blxuICAvLyAobmd4LWVjaGFydHMgb2JzZXJ2ZXMgdGhlIGhvc3QpLCBzbyBub3RoaW5nIGlzIHRvbGQgdG8gcmVzaXplLiBBIEtQSSdzIGNhcmRcbiAgLy8ga2V5cyBhcmUgZGlmZmVyZW50OiBzZXR0aW5ncy5rcGkgY2FycmllcyB0aGUga2V5cyB0aGUgc2VydmVyIHNhdmVkIChuZXZlclxuICAvLyB0aGUgb25lcyB0aGUgZGlhbG9nIHNlbnQpLCBhbmQgdGhlIHNlcnZlciBzZW5kcyB0aGUgdGFyZ2V0J3MgcHJvZ3Jlc3MgYW5kXG4gIC8vIHRoZSBzcGFya2xpbmUncyBwb2ludHMgd2l0aCB0aGUgZGF0YSwgc28gYSBjaGFuZ2UgdG8gdGhlbSByZWxvYWRzIGl0LlxuICBwdWJsaWMgYXBwbHlTZXR0aW5ncyhzZXR0aW5nczogQ29tcG9uZW50U2V0dGluZ3MpOiB2b2lkIHtcbiAgICBjb25zdCBjYXJkQ2hhbmdlZCA9ICEhc2V0dGluZ3Mua3BpXG4gICAgICAmJiAhc2FtZUtwaUNhcmRTZXR0aW5ncyhzZXR0aW5ncy5rcGksIGtwaUNhcmRTZXR0aW5ncyh0aGlzLmNvbXBvbmVudC5jb25maWcgYXMgS3BpQ29uZmlnKSk7XG5cbiAgICB0aGlzLmNvbXBvbmVudC50aXRsZSA9IHNldHRpbmdzLnRpdGxlO1xuICAgIHRoaXMuY29tcG9uZW50LmNvbmZpZyA9IHsgLi4udGhpcy5jb21wb25lbnQuY29uZmlnLCBwYWRkaW5nOiBzZXR0aW5ncy5wYWRkaW5nLCAuLi4oc2V0dGluZ3Mua3BpID8/IHt9KSB9O1xuXG4gICAgdGhpcy5fYnVpbGRGaWx0ZXJDb25maWcoKTtcblxuICAgIGlmIChjYXJkQ2hhbmdlZCkge1xuICAgICAgdGhpcy5fcmVmcmVzaCQubmV4dCgpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRoZSBDU1YgaXMgd2hhdCB0aGUgc2NyZWVuIHNob3dzLCBzbyBpdCBjYXJyaWVzIHRoZSB0aWxlJ3MgaW50ZXJhY3Rpb25cbiAgLy8gc3RhdGUgKHRpbGVEYXRhU3RhdGUpOiB0aGUgZ3JvdXAtYnkgZ3JhaW4gZm9yIGEgdGltZS1zZXJpZXMgY2hhcnQsIGFcbiAgLy8gY2hhcnQncyBkcmlsbCBwYXRoLCB0aGUgdmlld2VyJ3MgaGVhZGVyIHNvcnQsIHNlYXJjaCBhbmQgaGlkZGVuIGNvbHVtbnNcbiAgLy8gZm9yIGEgbGlzdCAoYSBzZWFyY2hlZCBsaXN0IGV4cG9ydHMgb25seSB0aGUgcm93cyB0aGUgc2VhcmNoIGxlYXZlcywgYW5kXG4gIC8vIHRoZSBoaWRkZW4gY29sdW1ucyBzdGF5IG91dCBvZiB0aGUgZmlsZSksIGFuZCB0aGUgZ3JvdXBzIHRoYXQgbWF0Y2hcbiAgLy8gJ2FueScuIEEgbm90ZSB0aGUgc2VydmVyIHJldHVybnMgKHRoZSBmaWxlIHdhcyBjdXQpIGlzIHNob3duIGJlZm9yZSB0aGVcbiAgLy8gZG93bmxvYWQgc3RhcnRzLCBzbyBhIHNob3J0IGZpbGUgbmV2ZXIgcGFzc2VzIGZvciB0aGUgd2hvbGUgcmVzdWx0LlxuICBwdWJsaWMgZXhwb3J0Q3N2KCk6IHZvaWQge1xuICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLl9maWx0ZXJTdGF0ZS5yZXNvbHZlRm9yQ29tcG9uZW50KHRoaXMuY29tcG9uZW50KTtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuX2ZpbHRlclN0YXRlLnRpbGVTdGF0ZSh0aGlzLmNvbXBvbmVudCk7XG5cbiAgICB0aGlzLl9wcm9jZXNzLmRvd25sb2FkKFxuICAgICAgYEV4cG9ydGluZyAke3RoaXMuY29tcG9uZW50LnRpdGxlID8/ICdjb21wb25lbnQnfWAsXG4gICAgICB0aGlzLl9yZXBvcnREYXRhLmV4cG9ydENvbXBvbmVudCh0aGlzLnJlcG9ydElkLCB0aGlzLmNvbXBvbmVudC5pZCwgZmlsdGVycywgc3RhdGUpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHRhcCgoeyBub3RlcyB9KSA9PiBub3Rlcz8ubGVuZ3RoICYmIHRoaXMuX21lc3NhZ2Uud2FybmluZyhub3Rlcy5qb2luKCcgJykpKSxcbiAgICAgICAgICBtYXAoKHsgdXJsIH0pID0+IHVybCksXG4gICAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIC8vIFRoZSBvbmUgY2xpY2sgaGFuZGxlciAoQjEwLjIpOiBldmVyeSBjbGljayBvbiBhIG1hcmsgb2YgdGhpcyB0aWxlLCBhXG4gIC8vIGNoYXJ0J3Mgb3IgYSBLUEkncyB2YWx1ZSwgY29tZXMgaGVyZSwgc28gaXRzIGFjdGlvbnMgbmV2ZXIgY29tcGV0ZS4gVGhlXG4gIC8vIHJ1bGUgKGRlY2lkZU1hcmtDbGljaykgZG9lcyBub3RoaW5nIHdpdGhvdXQgYW4gYWN0aW9uLCBsZXRzIGEgZmlyc3QgdGFwXG4gIC8vIHNob3cgdGhlIHRvb2x0aXAsIHJ1bnMgYSBsb25lIGFjdGlvbiBhdCBvbmNlLCBhbmQgb3BlbnMgdGhlIG1hcmsgbWVudSBhdFxuICAvLyB0aGUgY2xpY2sgZm9yIHR3byBvciBtb3JlLiBOb3Qgd2hpbGUgdGhlIGxheW91dCBpcyBlZGl0ZWQuXG4gIHB1YmxpYyBvbk1hcmtDbGljayhjbGljazogUmVwb3J0TWFya0NsaWNrKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZWRpdE1vZGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBhY3Rpb25zID0gbWFya0FjdGlvbnMoY2xpY2ssIHsgZGF0YTogdGhpcy5kYXRhKCksIGZlYXR1cmVzOiB0aGlzLl9vZmZlcmVkRmVhdHVyZXMoKSB9KTtcbiAgICBjb25zdCBkZWNpc2lvbiA9IGRlY2lkZU1hcmtDbGljayhjbGljaywgYWN0aW9ucywgdGhpcy5fdG91Y2hlZE1hcmspO1xuICAgIHRoaXMuX3RvdWNoZWRNYXJrID0gZGVjaXNpb24udG91Y2hlZDtcblxuICAgIGlmIChkZWNpc2lvbi5vdXRjb21lID09PSAncnVuJykge1xuICAgICAgdGhpcy5fcnVuTWFya0FjdGlvbihkZWNpc2lvbi5hY3Rpb25zWzBdLCBjbGljayk7XG4gICAgfSBlbHNlIGlmIChkZWNpc2lvbi5vdXRjb21lID09PSAnbWVudScpIHtcbiAgICAgIHRoaXMuX29wZW5NYXJrTWVudShkZWNpc2lvbi5hY3Rpb25zLCBjbGljayk7XG4gICAgfVxuICB9XG5cbiAgLy8gQSBjbGljayBvciBhIHRhcCBvbiB0aGUgY2hhcnQgdGhhdCBoaXQgbm8gbWFyazogYSB0YXAgaGVsZCBmb3IgaXRzXG4gIC8vIHNlY29uZCB0YXAgaXMgbGV0IGdvLCBzbyB0YXBwaW5nIHRoYXQgbWFyayBhZ2FpbiBzaG93cyBpdHMgdG9vbHRpcCBmaXJzdC5cbiAgcHVibGljIG9uTWFya01pc3MoKTogdm9pZCB7XG4gICAgdGhpcy5fdG91Y2hlZE1hcmsgPSBudWxsO1xuICB9XG5cbiAgLy8gQSByb3cgb2YgdGhlIG1hcmsgbWVudTogcnVucyBpdHMgYWN0aW9uIGZvciB0aGUgY2xpY2sgdGhlIG1lbnUgb3BlbmVkIG9uLlxuICBwdWJsaWMgcnVuTWFya0FjdGlvbihhY3Rpb246IFJlcG9ydE1hcmtBY3Rpb24pOiB2b2lkIHtcbiAgICBjb25zdCBjbGljayA9IHRoaXMuX21lbnVDbGljaztcbiAgICB0aGlzLl9tZW51Q2xpY2sgPSBudWxsO1xuXG4gICAgaWYgKGNsaWNrKSB7XG4gICAgICB0aGlzLl9ydW5NYXJrQWN0aW9uKGFjdGlvbiwgY2xpY2spO1xuICAgIH1cbiAgfVxuXG4gIC8vIEJhY2sgdXAgdGhlIGRyaWxsIHBhdGggdG8gaXRzIGZpcnN0IGBkZXB0aGAgc3RlcHM6IDAgaXMgdGhlIGNoYXJ0J3MgdG9wXG4gIC8vICh0aGUgdGl0bGUncyBjcnVtYiBhbmQgQmFjayB0byB0b3ApLCBhbmQgYSBjcnVtYiBnb2VzIGJhY2sgdG8gdGhlIHBlcmlvZFxuICAvLyBpdCBuYW1lcy4gVGhlIGNoYXJ0IHJlYWRzIGFnYWluIChkcmlsbENoYW5nZXMpLlxuICBwdWJsaWMgZHJpbGxUbyhkZXB0aDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZWRpdE1vZGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9maWx0ZXJTdGF0ZS5zZXREcmlsbCh0aGlzLmNvbXBvbmVudC5pZCwgdGhpcy5fZmlsdGVyU3RhdGUuZHJpbGwodGhpcy5jb21wb25lbnQuaWQpLnNsaWNlKDAsIGRlcHRoKSk7XG4gIH1cblxuICAvLyBPbmUgbGV2ZWwgdXA6IHRoZSBwZXJpb2QgdGhlIGNoYXJ0IGlzIGRyaWxsZWQgaW50byBpcyBsZWZ0LlxuICBwdWJsaWMgZHJpbGxVcCgpOiB2b2lkIHtcbiAgICB0aGlzLmRyaWxsVG8oTWF0aC5tYXgoMCwgdGhpcy5fZmlsdGVyU3RhdGUuZHJpbGwodGhpcy5jb21wb25lbnQuaWQpLmxlbmd0aCAtIDEpKTtcbiAgfVxuXG4gIC8vIEFueSBpbnRlcmFjdGlvbiBpbnNpZGUgYSBjb21wb25lbnQgbXVzdCBuZXZlciBzdGFydCBhIGNhbnZhcyBwYW4gKHRoZVxuICAvLyB6b29tLXBhbiBob3N0IGxpc3RlbnMgZm9yIG1vdXNlZG93bi90b3VjaHN0YXJ0IGF0IHRoZSBjb250YWluZXIgbGV2ZWwpLlxuICBwdWJsaWMgc3RvcENhbnZhc1BhbihldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIHB1YmxpYyBvbkNvbXBvbmVudFBvaW50ZXJEb3duKGV2ZW50OiBQb2ludGVyRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBpZiAodGhpcy5lZGl0TW9kZSAmJiAhdGhpcy5zZWxlY3RlZCkge1xuICAgICAgdGhpcy5zZWxlY3RDb21wb25lbnQuZW1pdCh0aGlzLmNvbXBvbmVudC5pZCk7XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0gZWRpdC1tb2RlIGdlc3R1cmVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHB1YmxpYyBvbkRyYWdTdGFydChldmVudDogUG9pbnRlckV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVkaXRNb2RlIHx8IHRoaXMudGV4dEVkaXRpbmcoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEEgc2Vjb25kIHByZXNzIG9uIGEgdGV4dCBibG9jayBvcGVucyBpdHMgZWRpdG9yIGluc3RlYWQgb2YgZHJhZ2dpbmcuXG4gICAgaWYgKHRoaXMuaXNUZXh0KSB7XG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3QgaXNEb3VibGVQcmVzcyA9IG5vdyAtIHRoaXMuX2xhc3RQcmVzcyA8IERPVUJMRV9QUkVTU19NUztcbiAgICAgIHRoaXMuX2xhc3RQcmVzcyA9IG5vdztcblxuICAgICAgaWYgKGlzRG91YmxlUHJlc3MpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMuZWRpdFRleHQoKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zZWxlY3RDb21wb25lbnQuZW1pdCh0aGlzLmNvbXBvbmVudC5pZCk7XG5cbiAgICB0aGlzLl90cmFjayhldmVudCwgKGRlbHRhWCwgZGVsdGFZKSA9PiB7XG4gICAgICBsZXQgeCA9IE1hdGgubWF4KDAsIHRoaXMuX29yaWdpbi54ICsgdGhpcy5faW5jaGVzKGRlbHRhWCkpO1xuICAgICAgbGV0IHkgPSBNYXRoLm1heCgwLCB0aGlzLl9vcmlnaW4ueSArIHRoaXMuX2luY2hlcyhkZWx0YVkpKTtcblxuICAgICAgaWYgKHRoaXMuc25hcHBlcikge1xuICAgICAgICAoeyB4LCB5IH0gPSB0aGlzLnNuYXBwZXIuc25hcE1vdmUodGhpcy5jb21wb25lbnQsIHgsIHkpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb21wb25lbnQueCA9IHg7XG4gICAgICB0aGlzLmNvbXBvbmVudC55ID0geTtcbiAgICAgIHRoaXMuX2FwcGx5R2VvbWV0cnkoKTtcbiAgICB9LCAoKSA9PiB0aGlzLl9lbWl0R2VvbWV0cnkoKSk7XG4gIH1cblxuICBwdWJsaWMgb25SZXNpemVTdGFydChldmVudDogUG9pbnRlckV2ZW50LCBoYW5kbGU6IEhhbmRsZSk6IHZvaWQge1xuICAgIGlmICghdGhpcy5lZGl0TW9kZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2VsZWN0Q29tcG9uZW50LmVtaXQodGhpcy5jb21wb25lbnQuaWQpO1xuXG4gICAgdGhpcy5fdHJhY2soZXZlbnQsIChkZWx0YVgsIGRlbHRhWSkgPT4ge1xuICAgICAgY29uc3QgZHggPSB0aGlzLl9pbmNoZXMoZGVsdGFYKTtcbiAgICAgIGNvbnN0IGR5ID0gdGhpcy5faW5jaGVzKGRlbHRhWSk7XG4gICAgICBsZXQgeyB4LCB5LCB3LCBoIH0gPSB0aGlzLl9vcmlnaW47XG5cbiAgICAgIGlmIChoYW5kbGUuaW5jbHVkZXMoJ2UnKSkge1xuICAgICAgICB3ID0gTWF0aC5tYXgoTUlOX1csIHRoaXMuX29yaWdpbi53ICsgZHgpO1xuICAgICAgfVxuICAgICAgaWYgKGhhbmRsZS5pbmNsdWRlcygncycpKSB7XG4gICAgICAgIGggPSBNYXRoLm1heChNSU5fSCwgdGhpcy5fb3JpZ2luLmggKyBkeSk7XG4gICAgICB9XG4gICAgICBpZiAoaGFuZGxlLmluY2x1ZGVzKCd3JykpIHtcbiAgICAgICAgY29uc3QgY2xhbXBlZCA9IE1hdGgubWluKGR4LCB0aGlzLl9vcmlnaW4udyAtIE1JTl9XKTtcbiAgICAgICAgeCA9IHRoaXMuX29yaWdpbi54ICsgY2xhbXBlZDtcbiAgICAgICAgdyA9IHRoaXMuX29yaWdpbi53IC0gY2xhbXBlZDtcbiAgICAgIH1cbiAgICAgIGlmIChoYW5kbGUuaW5jbHVkZXMoJ24nKSkge1xuICAgICAgICBjb25zdCBjbGFtcGVkID0gTWF0aC5taW4oZHksIHRoaXMuX29yaWdpbi5oIC0gTUlOX0gpO1xuICAgICAgICB5ID0gdGhpcy5fb3JpZ2luLnkgKyBjbGFtcGVkO1xuICAgICAgICBoID0gdGhpcy5fb3JpZ2luLmggLSBjbGFtcGVkO1xuICAgICAgfVxuXG4gICAgICBsZXQgZ2VvbWV0cnkgPSB7IHgsIHksIHcsIGggfTtcbiAgICAgIGlmICh0aGlzLnNuYXBwZXIpIHtcbiAgICAgICAgZ2VvbWV0cnkgPSB0aGlzLnNuYXBwZXIuc25hcFJlc2l6ZSh0aGlzLmNvbXBvbmVudCwgZ2VvbWV0cnksIGhhbmRsZSk7XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5jb21wb25lbnQsIGdlb21ldHJ5KTtcbiAgICAgIHRoaXMuX2FwcGx5R2VvbWV0cnkoKTtcbiAgICAgIHRoaXMuY2hhcnRDb21wb25lbnQ/LnJlc2l6ZSgpO1xuICAgIH0sICgpID0+IHRoaXMuX2VtaXRHZW9tZXRyeSgpKTtcbiAgfVxuXG4gIC8vIChSZSlidWlsZCB0aGUgaGVhZGVyIGZzLWZpbHRlciBjb25maWc6IGhlYWRpbmcgdGVtcGxhdGUgcmVuZGVycyB0aGUgdGl0bGVcbiAgLy8gYW5kIGl0ZW1zIGFyZSB0aGlzIGNvbXBvbmVudCdzIGNvbXBvbmVudC1sZXZlbCBmaWx0ZXIgZ3JvdXBzLiBUaGUgYWN0aW9uc1xuICAvLyBtZW51IChTZXR0aW5ncyAvIEV4cG9ydCBDU1YpIGlzIE5PVCBoZXJlIOKAlCBpdCdzIGEgc3RhbmRhbG9uZSBrZWJhYiBmbG9hdGVkXG4gIC8vIHRvcC1yaWdodCBpbiB0aGUgdGVtcGxhdGUsIHNvIGl0cyBidXR0b24gaGVpZ2h0IG5vIGxvbmdlciBkcml2ZXMgdGhlIGhlYWRlclxuICAvLyByb3cncyBoZWlnaHQgKHdoaWNoIHdvdWxkIG90aGVyd2lzZSBpbmZsYXRlIHRoZSBoZWFkaW5nIGJ5IH40MHB4KS5cbiAgLy9cbiAgLy8gQSBsaXN0IGFsc28gZ2V0cyBhIHNlYXJjaCBib3ggb3ZlciBpdHMgdGV4dCBjb2x1bW5zLCB1bmxlc3MgaXRzIGhlYWRlclxuICAvLyBzaG93cyBhIGtleXdvcmQgZ3JvdXAgKFJlcG9ydEZpbHRlclN0YXRlU2VydmljZS5saXN0U2VhcmNoYWJsZSwgd2hpY2ggYWxzb1xuICAvLyBkcm9wcyBhIHNlYXJjaCBrZXB0IGZyb20gYmVmb3JlIHN1Y2ggYSBncm91cCBhcHBlYXJlZCkuXG4gIC8vXG4gIC8vIGByZXBvcnRlZGAgaXMgd2hhdCB0aGlzIGhlYWRlciBsYXN0IHJlcG9ydGVkIGZvciBlYWNoIG9mIGl0cyBncm91cHMsXG4gIC8vIHN0YXJ0aW5nIGZyb20gdGhlIHZhbHVlcyBpdCBpcyBidWlsdCB3aXRoLiBBIGNoYW5nZSBzZXRzIG9ubHkgdGhlIGdyb3Vwc1xuICAvLyB3aG9zZSBoZWFkZXIgdmFsdWUgbW92ZWQgKG1vdmVkR3JvdXBWYWx1ZXMpOiBmcy1maWx0ZXIgcmVwb3J0cyBldmVyeSBpdGVtXG4gIC8vIG9uIGFueSBjaGFuZ2UsIGFuZCBhIGdyb3VwIHNob3duIGluIHRoZSByZXBvcnQgYmFyIHRvbyBtYXkgaGF2ZSBjaGFuZ2VkXG4gIC8vIHRoZXJlIHNpbmNlLCB3aXRob3V0IHRoaXMgaGVhZGVyIGJlaW5nIHJlcGFpbnRlZC5cbiAgcHJpdmF0ZSBfc2V0VGV4dEh0bWwoaHRtbDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb21wb25lbnQuY29uZmlnID0geyAuLi50aGlzLmNvbXBvbmVudC5jb25maWcsIGh0bWwgfTtcbiAgICB0aGlzLnRleHRIdG1sLnNldChodG1sKTtcbiAgfVxuXG4gIHByaXZhdGUgX2J1aWxkRmlsdGVyQ29uZmlnKCk6IHZvaWQge1xuICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuY29tcG9uZW50RmlsdGVyR3JvdXBzO1xuICAgIGNvbnN0IGxpc3RTZWFyY2ggPSB0aGlzLl9maWx0ZXJTdGF0ZS5saXN0U2VhcmNoYWJsZSh0aGlzLmNvbXBvbmVudCk7XG4gICAgY29uc3QgcmVwb3J0ZWQgPSBuZXcgTWFwKGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiBbZ3JvdXAuaWQsIHRoaXMuX2ZpbHRlclN0YXRlLnZhbHVlKGdyb3VwLmlkKSA/PyBudWxsXSkpO1xuICAgIGNvbnN0IGZlYXR1cmVzID0gdGhpcy5fZmlsdGVyU3RhdGUudmlld2VyRmVhdHVyZXMoKTtcbiAgICBjb25zdCByZXBvcnQgPSB0aGlzLl9maWx0ZXJTdGF0ZS5yZXBvcnQoKTtcblxuICAgIHRoaXMuX3Nob3duID0gcmVwb3J0ZWQ7XG4gICAgdGhpcy5faGVhZGVyVmFsdWVzLnNldChbLi4ucmVwb3J0ZWQudmFsdWVzKCldLm1hcChncm91cFZhbHVlU2lnbmF0dXJlKS5qb2luKCd8JykpO1xuICAgIHRoaXMuX2hlYWRlclZlcnNpb24uc2V0KHRoaXMuX2ZpbHRlclN0YXRlLnN0YXRlVmVyc2lvbigpKTtcbiAgICB0aGlzLmZpbHRlckNvbmZpZy5zZXQoe1xuICAgICAgLy8gZnMtZmlsdGVyIG5ldmVyIHRvdWNoZXMgdGhlIFVSTCBvciBwZXJzaXN0cyBmaWx0ZXIgc3RhdGUuIFRoZSB2YWx1ZXNcbiAgICAgIC8vIGFyZSBvd25lZCBieSBSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UsIHdoaWNoIGZlZWRzIHRoZSByZXBvcnQgdmlldydzXG4gICAgICAvLyBvbmUgVVJMIHdyaXRlciAocmVwb3J0LXVybC1zdGF0ZS50cykuXG4gICAgICBxdWVyeVBhcmFtOiBmYWxzZSxcbiAgICAgIHBlcnNpc3Q6IGZhbHNlLFxuICAgICAgaXRlbXM6IFtcbiAgICAgICAgLi4uZ3JvdXBzLm1hcCgoZ3JvdXApID0+XG4gICAgICAgICAgZmlsdGVySXRlbUZvckdyb3VwKGdyb3VwLCB0aGlzLl9maWx0ZXJPcHRpb25zLCByZXBvcnQsIHRoaXMuX2ZpbHRlclN0YXRlLnZhbHVlKGdyb3VwLmlkKSwgZmVhdHVyZXMpKSxcbiAgICAgICAgLi4uKGxpc3RTZWFyY2ggPyBbbGlzdFNlYXJjaEl0ZW0odGhpcy5fZmlsdGVyU3RhdGUubGlzdFNlYXJjaCh0aGlzLmNvbXBvbmVudC5pZCkpXSA6IFtdKSxcbiAgICAgIF0sXG4gICAgICAvLyBUeXBpbmcgaW4gdGhlIHNlYXJjaCBib3ggbXVzdCBub3QgcmVmZXRjaCB0aHJvdWdoIHRoZSBncm91cHMsIG5vciBzZXRcbiAgICAgIC8vIGEgc3RhbGUgZ3JvdXAgdmFsdWUgYmFjaywgYW5kIGEgZ3JvdXAgY2hhbmdlIG11c3Qgbm90IHJlZmV0Y2ggdGhyb3VnaFxuICAgICAgLy8gdGhlIHNlYXJjaC5cbiAgICAgIGNoYW5nZTogKHF1ZXJ5KSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbHVlcyA9IGdyb3VwVmFsdWVzRnJvbVF1ZXJ5KHF1ZXJ5ID8/IHt9LCB0aGlzLmNvbXBvbmVudEZpbHRlckdyb3VwcywgcmVwb3J0KTtcblxuICAgICAgICBmb3IgKGNvbnN0IHsgZ3JvdXBJZCwgdmFsdWUgfSBvZiBtb3ZlZEdyb3VwVmFsdWVzKHJlcG9ydGVkLCB2YWx1ZXMpKSB7XG4gICAgICAgICAgdGhpcy5fZmlsdGVyU3RhdGUuc2V0VmFsdWUoZ3JvdXBJZCwgdmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxpc3RTZWFyY2gpIHtcbiAgICAgICAgICB0aGlzLl9maWx0ZXJTdGF0ZS5zZXRMaXN0U2VhcmNoKHRoaXMuY29tcG9uZW50LmlkLCBTdHJpbmcocXVlcnk/LltMSVNUX1NFQVJDSF9JVEVNXSA/PyAnJykpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgLy8gJ0NsZWFyIGZpbHRlcnMnIHB1dHMgdGhpcyBoZWFkZXIncyBvd24gZ3JvdXBzIGJhY2sgb24gdGhlIG9wZW4gdmlldyxcbiAgICAgIC8vIGVsc2Ugb24gdGhlaXIgYXV0aG9yZWQgZGVmYXVsdHMuIGZzLWZpbHRlciByZXBvcnRzIGl0cyBvd24gY2xlYXJlZFxuICAgICAgLy8gaXRlbXMgKGNoYW5nZSkganVzdCBiZWZvcmUgdGhpcywgc28gdGhlIHJlc2V0IHdpbnMuIEEgc2VydmVyIHdpdGhvdXRcbiAgICAgIC8vIHNhdmVkIHZpZXdzIGtlZXBzIHRoZSBjbGVhciBpdCBhbHdheXMgaGFkOiB0aGUgaGVhZGVyJ3MgaXRlbXMgb25seS5cbiAgICAgIGNsZWFyOiBmZWF0dXJlcy5pbmNsdWRlcygndmlld3MnKVxuICAgICAgICA/ICgpID0+IHRoaXMuX2ZpbHRlclN0YXRlLnJlc2V0R3JvdXBzVG9CYXNlKGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiBncm91cC5pZCkpXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgLy8gVGhlIGNoaXAgc2hvd3MgZXhhY3RseSB3aGlsZSBvbmUgb2YgdGhvc2UgZ3JvdXBzIGRpZmZlcnMgZnJvbSB3aGF0XG4gICAgICAvLyB0aGF0IGNsZWFyIHB1dHMgYmFjayAoZ3JvdXBzRGlmZmVyRnJvbUJhc2UpLiBmcy1maWx0ZXIncyBvd24gcnVsZVxuICAgICAgLy8gY29tcGFyZXMgdGhlIGl0ZW1zIHdpdGggdGhlIHZhbHVlcyB0aGlzIGhlYWRlciB3YXMgYnVpbHQgd2l0aCwgc28gaXRcbiAgICAgIC8vIHdvdWxkIG1pc3MgYSB2YWx1ZSB0aGUgb3BlbiB2aWV3IGhvbGRzIGFuZCBvZmZlciBhIGNsZWFyIHRoYXQgY2hhbmdlc1xuICAgICAgLy8gbm90aGluZy4gQSBzZXJ2ZXIgd2l0aG91dCBzYXZlZCB2aWV3cyBrZWVwcyBmcy1maWx0ZXIncyBvd24gcnVsZS5cbiAgICAgIGNsZWFyVmlzaWJsZTogZmVhdHVyZXMuaW5jbHVkZXMoJ3ZpZXdzJylcbiAgICAgICAgPyAoKSA9PiB0aGlzLl9maWx0ZXJTdGF0ZS5ncm91cHNEaWZmZXJGcm9tQmFzZShncm91cHMubWFwKChncm91cCkgPT4gZ3JvdXAuaWQpKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGFwcGx5KCkgYW5kIHJlc2V0VG9CYXNlKCkgbW92ZSB0aGUgc3RhdGUgdmVyc2lvbiBhbmQgYW5ub3VuY2UgYSBmdWxsXG4gIC8vIGNoYW5nZSAobnVsbCkuIFRoZSBoZWFkZXIgaXMgYnVpbHQgYWdhaW4gZm9yIHRoZSBuZXcgdmVyc2lvbiwgYW5kXG4gIC8vIGZpbHRlcktleSwgd2hpY2ggY2FycmllcyBpdCwgcmVjcmVhdGVzIHRoZSBibG9jazogZnMtZmlsdGVyIHJlYWRzIGl0c1xuICAvLyBjb25maWcgb25jZS4gQW55IG90aGVyIGZ1bGwgY2hhbmdlIChhIHJlbG9hZCwgdGhlIG1hdGNoKSBsZWF2ZXMgaXQgYmUuXG4gIC8vIEEgY2hhbmdlIHRvIG9uZSBncm91cCB0aGUgaGVhZGVyIHNob3dzIHdpdGggYW5vdGhlciB2YWx1ZSAoYW5vdGhlciBiYXJcbiAgLy8gc2V0IGl0KSBidWlsZHMgaXQgYWdhaW4gdG9vLlxuICBwcml2YXRlIF9yZWJ1aWxkSGVhZGVyT25OZXdTdGF0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9maWx0ZXJTdGF0ZS5jaGFuZ2VzRm9yKHRoaXMuY29tcG9uZW50KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHJ4RmlsdGVyKChncm91cElkKSA9PiAoZ3JvdXBJZCA9PT0gbnVsbFxuICAgICAgICAgID8gdGhpcy5fZmlsdGVyU3RhdGUuc3RhdGVWZXJzaW9uKCkgIT09IHRoaXMuX2hlYWRlclZlcnNpb24oKVxuICAgICAgICAgIDogdGhpcy5fc2hvd3NPdGhlclZhbHVlKGdyb3VwSWQpKSksXG4gICAgICAgIHRhcCgoKSA9PiB0aGlzLl9idWlsZEZpbHRlckNvbmZpZygpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgLy8gV2hldGhlciB0aGUgaGVhZGVyIHNob3dzIGEgZ3JvdXAgd2l0aCBhIHZhbHVlIG90aGVyIHRoYW4gdGhlIG9uZSBzdG9yZWRcbiAgLy8gZm9yIGl0LiBBIGNoYW5nZSB0aGUgaGVhZGVyJ3Mgb3duIGJhciBtYWRlIGlzIHdoYXQgaXQgc2hvd3MgYWxyZWFkeS5cbiAgcHJpdmF0ZSBfc2hvd3NPdGhlclZhbHVlKGdyb3VwSWQ6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9zaG93bi5oYXMoZ3JvdXBJZClcbiAgICAgICYmIGdyb3VwVmFsdWVTaWduYXR1cmUodGhpcy5fc2hvd24uZ2V0KGdyb3VwSWQpKSAhPT0gZ3JvdXBWYWx1ZVNpZ25hdHVyZSh0aGlzLl9maWx0ZXJTdGF0ZS52YWx1ZShncm91cElkKSk7XG4gIH1cblxuICBwcml2YXRlIF9vcmlnaW4gPSB7IHg6IDAsIHk6IDAsIHc6IDAsIGg6IDAgfTtcblxuICAvLyBQb2ludGVyLWNhcHR1cmUgZ2VzdHVyZSBsb29wOiBydW5zIG91dHNpZGUgQW5ndWxhciwgcmVwYWludHMgaW1wZXJhdGl2ZWx5LFxuICAvLyBhbmQgZmluaXNoZXMgYmFjayBpbnNpZGUgQW5ndWxhciAoc2VsZWN0aW9uL3BlcnNpc3RlbmNlKS5cbiAgcHJpdmF0ZSBfdHJhY2soXG4gICAgZXZlbnQ6IFBvaW50ZXJFdmVudCxcbiAgICBvbk1vdmU6IChkZWx0YVg6IG51bWJlciwgZGVsdGFZOiBudW1iZXIpID0+IHZvaWQsXG4gICAgb25FbmQ6ICgpID0+IHZvaWQsXG4gICk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBjb25zdCBoYW5kbGUgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgaGFuZGxlLnNldFBvaW50ZXJDYXB0dXJlKGV2ZW50LnBvaW50ZXJJZCk7XG5cbiAgICB0aGlzLl9vcmlnaW4gPSB7XG4gICAgICB4OiB0aGlzLmNvbXBvbmVudC54LFxuICAgICAgeTogdGhpcy5jb21wb25lbnQueSxcbiAgICAgIHc6IHRoaXMuY29tcG9uZW50LncsXG4gICAgICBoOiB0aGlzLmNvbXBvbmVudC5oLFxuICAgIH07XG4gICAgY29uc3Qgc3RhcnRYID0gZXZlbnQuY2xpZW50WDtcbiAgICBjb25zdCBzdGFydFkgPSBldmVudC5jbGllbnRZO1xuXG4gICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBjb25zdCBtb3ZlID0gKGU6IFBvaW50ZXJFdmVudCkgPT4gb25Nb3ZlKGUuY2xpZW50WCAtIHN0YXJ0WCwgZS5jbGllbnRZIC0gc3RhcnRZKTtcbiAgICAgIGNvbnN0IGVuZCA9ICgpID0+IHtcbiAgICAgICAgaGFuZGxlLnJlbGVhc2VQb2ludGVyQ2FwdHVyZShldmVudC5wb2ludGVySWQpO1xuICAgICAgICBoYW5kbGUucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcm1vdmUnLCBtb3ZlKTtcbiAgICAgICAgaGFuZGxlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIGVuZCk7XG4gICAgICAgIGhhbmRsZS5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVyY2FuY2VsJywgZW5kKTtcblxuICAgICAgICB0aGlzLl96b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5zbmFwcGVyPy5jbGVhcigpO1xuICAgICAgICAgIG9uRW5kKCk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgaGFuZGxlLmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJtb3ZlJywgbW92ZSk7XG4gICAgICBoYW5kbGUuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcnVwJywgZW5kKTtcbiAgICAgIGhhbmRsZS5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyY2FuY2VsJywgZW5kKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2VtaXRHZW9tZXRyeSgpOiB2b2lkIHtcbiAgICB0aGlzLmNvbXBvbmVudC54ID0gdGhpcy5fcm91bmQodGhpcy5jb21wb25lbnQueCk7XG4gICAgdGhpcy5jb21wb25lbnQueSA9IHRoaXMuX3JvdW5kKHRoaXMuY29tcG9uZW50LnkpO1xuICAgIHRoaXMuY29tcG9uZW50LncgPSB0aGlzLl9yb3VuZChNYXRoLm1heChNSU5fVywgdGhpcy5jb21wb25lbnQudykpO1xuICAgIHRoaXMuY29tcG9uZW50LmggPSB0aGlzLl9yb3VuZChNYXRoLm1heChNSU5fSCwgdGhpcy5jb21wb25lbnQuaCkpO1xuICAgIHRoaXMuX2FwcGx5R2VvbWV0cnkoKTtcbiAgICB0aGlzLmNoYXJ0Q29tcG9uZW50Py5yZXNpemUoKTtcblxuICAgIHRoaXMucG9zaXRpb25DaGFuZ2VkLmVtaXQoe1xuICAgICAgY29tcG9uZW50SWQ6IHRoaXMuY29tcG9uZW50LmlkLFxuICAgICAgeDogdGhpcy5jb21wb25lbnQueCxcbiAgICAgIHk6IHRoaXMuY29tcG9uZW50LnksXG4gICAgICB3OiB0aGlzLmNvbXBvbmVudC53LFxuICAgICAgaDogdGhpcy5jb21wb25lbnQuaCxcbiAgICB9KTtcbiAgfVxuXG4gIC8vIEEgY2hhcnQgb24gYSB0aW1lIHgtYXhpcyDigJQgdGhlIG9ubHkgY29tcG9uZW50IHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sXG4gIC8vIGFwcGxpZXMgdG8gKGlzVGltZVNlcmllc0NoYXJ0LCB0aGUgYnJvd3Nlci1zaWRlIG1pcnJvciBvZiB0aGUgc2VydmVyJ3MgcnVsZSkuXG4gIHByaXZhdGUgZ2V0IF9pc1RpbWVTZXJpZXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGlzVGltZVNlcmllc0NoYXJ0KHRoaXMuY29tcG9uZW50KTtcbiAgfVxuXG4gIC8vIEF1dG8gaGVpZ2h0IChib3ggZml0cyBpdHMgY29udGVudCkgdnMgZml4ZWQgKHVzZSBgaGAgZXhhY3RseSkuIERlcml2ZWQgZnJvbVxuICAvLyB0eXBlLCBzZXJ2ZXItc2lkZTogS1BJIHRpbGVzIGFyZSBhdXRvOyBjaGFydHMgYW5kIGxpc3RzIGFyZSBmaXhlZCDigJQgY2hhcnRzXG4gIC8vIGZpdCB0aGUgYm94IGFuZCBuZXZlciBvdmVyZmxvdywgbGlzdHMgc2Nyb2xsIGluc2lkZSBpdC5cbiAgcHJpdmF0ZSBnZXQgX2hlaWdodEF1dG8oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY29tcG9uZW50LmF1dG9IZWlnaHQgIT09IGZhbHNlO1xuICB9XG5cbiAgLy8gRHJpdmVzIHRoZSBhdXRvLW9ubHkgQ1NTIGRlZmF1bHQgKGVtcHR5LXN0YXRlIGJhc2VsaW5lKSBzbyBpdCBuZXZlciBhcHBsaWVzXG4gIC8vIHRvIGEgZml4ZWQtaGVpZ2h0IGNvbXBvbmVudC5cbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5oZWlnaHQtYXV0bycpXG4gIHB1YmxpYyBnZXQgaGVpZ2h0QXV0bygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faGVpZ2h0QXV0bztcbiAgfVxuXG4gIC8vIFNjcmVlbiBwaXhlbHMg4oaSIGluY2hlcyBhdCB0aGUgY3VycmVudCB6b29tLlxuICBwcml2YXRlIF9pbmNoZXMocGl4ZWxzOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiBwaXhlbHMgLyAodGhpcy56b29tICogUFhfUEVSX0lOQ0gpO1xuICB9XG5cbiAgLy8gQ2xlYW4gcGVyc2lzdGVkIHZhbHVlczogaHVuZHJlZHRocyBvZiBhbiBpbmNoLlxuICBwcml2YXRlIF9yb3VuZCh2YWx1ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCkgLyAxMDA7XG4gIH1cblxuICAvLyBUaGUgY2FudmFzIHBvc2l0aW9ucyB0aGUgaG9zdCB2aWEgW3N0eWxlXTsgbWlkLWdlc3R1cmUgd2Ugc2V0IGl0IGRpcmVjdGx5XG4gIC8vIHNvIE9uUHVzaCBuZXZlciByZS1yZW5kZXJzIGluIHRoZSBtb3ZlIGxvb3AuXG4gIHByaXZhdGUgX2FwcGx5R2VvbWV0cnkoKTogdm9pZCB7XG4gICAgY29uc3Qgc3R5bGUgPSB0aGlzLl9ob3N0Lm5hdGl2ZUVsZW1lbnQuc3R5bGU7XG4gICAgc3R5bGUubGVmdCA9IGAke3RoaXMuY29tcG9uZW50LnggKiBQWF9QRVJfSU5DSH1weGA7XG4gICAgc3R5bGUudG9wID0gYCR7dGhpcy5jb21wb25lbnQueSAqIFBYX1BFUl9JTkNIfXB4YDtcbiAgICBzdHlsZS53aWR0aCA9IGAke3RoaXMuY29tcG9uZW50LncgKiBQWF9QRVJfSU5DSH1weGA7XG5cbiAgICAvLyBBdXRvIChrcGkpOiBubyBmaXhlZCBoZWlnaHQg4oCUIHRoZSBib3ggc2l6ZXMgdG8gaXRzIGNvbnRlbnQuIEZpeGVkXG4gICAgLy8gKGNoYXJ0L2xpc3QpOiBgaGAgaXMgdGhlIGV4YWN0IGhlaWdodC4gTWlycm9ycyB0aGUgY2FudmFzIFtzdHlsZV0gYmluZGluZ1xuICAgIC8vIHNvIHRoZSBtaWQtZ2VzdHVyZSBwYWludCBtYXRjaGVzIHRoZSBwb3N0LWdlc3R1cmUgcmUtcmVuZGVyLlxuICAgIGlmICh0aGlzLl9oZWlnaHRBdXRvKSB7XG4gICAgICBzdHlsZS5oZWlnaHQgPSAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgc3R5bGUuaGVpZ2h0ID0gYCR7dGhpcy5jb21wb25lbnQuaCAqIFBYX1BFUl9JTkNIfXB4YDtcbiAgICB9XG4gIH1cblxuICAvLyAtLS0tLSBkYXRhIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBPbmUgcmVxdWVzdCBvZiB0aGUgbG9hZCBzdHJlYW0gKHRpbGVMb2FkcyksIGJ1aWx0IGZyb20gdGhlIHN0YXRlIG5vdy4gVGhlXG4gIC8vIHNoaW1tZXIgc2hvd3Mgb25seSB3aGlsZSB0aGUgdGlsZSBoYXMgbm90aGluZyBvbiBzY3JlZW47IG90aGVyd2lzZSB0aGVcbiAgLy8gZGF0YSBzdGF5cyBhbmQgdGhlIHRoaW4gYmFyIHNob3dzLlxuICBwcml2YXRlIF9sb2FkKCk6IE9ic2VydmFibGU8Q29tcG9uZW50RGF0YT4ge1xuICAgIGNvbnN0IGZpcnN0ID0gIXRoaXMuZGF0YSgpO1xuXG4gICAgdGhpcy5sb2FkaW5nLnNldChmaXJzdCk7XG4gICAgdGhpcy5yZWZyZXNoaW5nLnNldCghZmlyc3QpO1xuICAgIHRoaXMuZXJyb3Iuc2V0KG51bGwpO1xuXG4gICAgY29uc3QgZmlsdGVycyA9IHRoaXMuX2ZpbHRlclN0YXRlLnJlc29sdmVGb3JDb21wb25lbnQodGhpcy5jb21wb25lbnQpO1xuICAgIC8vIFRoZSB0aWxlJ3MgaW50ZXJhY3Rpb24gc3RhdGUsIHRoZSBvbmUgaXRzIENTViBhbmQgZXZlcnkgZXhwb3J0IGNhcnJ5XG4gICAgLy8gKHRpbGVEYXRhU3RhdGUpOiBhIHRpbWUtc2VyaWVzIGNoYXJ0J3MgZ3JhaW4gKHdoZW4gdGhlIHZpZXdlciBwaWNrZWRcbiAgICAvLyBvbmUpIHNvIHRoZSBiYWNrZW5kIHJlLWJ1Y2tldHMsIGEgY2hhcnQncyBkcmlsbCBwYXRoLCBhbmQgdGhlIGdyb3Vwc1xuICAgIC8vIHRoYXQgbWF0Y2ggJ2FueScuXG4gICAgY29uc3Qgc3RhdGUgPSB0aGlzLl9maWx0ZXJTdGF0ZS50aWxlU3RhdGUodGhpcy5jb21wb25lbnQpO1xuXG4gICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEuY29tcG9uZW50RGF0YSh0aGlzLnJlcG9ydElkLCB0aGlzLmNvbXBvbmVudC5pZCwgZmlsdGVycywgc3RhdGUpO1xuICB9XG5cbiAgLy8gQSBmYWlsZWQgbG9hZCBjbGVhcnMgdGhlIGRhdGEgd2l0aCBpdHMgbWVzc2FnZSwgc28gdGhlIG5leHQgbG9hZCBzdGFydHNcbiAgLy8gZnJvbSB0aGUgc2hpbW1lciBhbmQgbmV2ZXIgc2hvd3MgdGhlIGRhdGEgdGhlIGZhaWx1cmUgcmVwbGFjZWQuIEFcbiAgLy8gY2hhcnQncyBhbnN3ZXIgZ2l2ZXMgaXRzIGRyaWxsIHBhdGguXG4gIHByaXZhdGUgX2xvYWRlZChyZXN1bHQ6IFRpbGVMb2FkUmVzdWx0PENvbXBvbmVudERhdGE+KTogdm9pZCB7XG4gICAgdGhpcy5kYXRhLnNldChyZXN1bHQuZGF0YSk7XG4gICAgdGhpcy5lcnJvci5zZXQocmVzdWx0LmVycm9yKTtcbiAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICB0aGlzLnJlZnJlc2hpbmcuc2V0KGZhbHNlKTtcblxuICAgIGlmIChyZXN1bHQuZXJyb3IgPT09IG51bGwgJiYgcmVzdWx0LmRhdGEpIHtcbiAgICAgIHRoaXMuX2Fkb3B0RHJpbGwocmVzdWx0LmRhdGEpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgY2hhcnQgdGFrZXMgdGhlIGRyaWxsIHBhdGggaXRzIGFuc3dlciBhcHBsaWVkIChhZG9wdGVkRHJpbGxQYXRoKSB3aGlsZVxuICAvLyB0aGUgdmlld2VyIGlzIG9mZmVyZWQgZHJpbGw7IGFuIG9sZGVyIHNlcnZlciBhcHBsaWVzIG5vbmUsIGFuZCB0aGUgcGF0aFxuICAvLyBzdGF5cyBmb3IgdGhlIGxpbmsuIFdoZW4gdGhlIHBhdGggaXQgc2VudCB3YXMgY3V0LCB0aGUgdmlld2VyIGlzIHRvbGRcbiAgLy8gb25jZSAoZHJpbGxSZXNldE5vdGVkKTogdGhlIHNob3J0ZXIgcGF0aCBpcyB3aGF0IHRoZSBjaGFydCByZWFkcyBmcm9tXG4gIC8vIG5vdyBvbiwgc28gdGhlIHNlcnZlciBjdXRzIG5vdGhpbmcgYWdhaW4uXG4gIHByaXZhdGUgX2Fkb3B0RHJpbGwoZGF0YTogQ29tcG9uZW50RGF0YSk6IHZvaWQge1xuICAgIGNvbnN0IGdyYWluTW92ZWQgPSB0aGlzLl9ncmFpbk1vdmVkO1xuICAgIHRoaXMuX2dyYWluTW92ZWQgPSBmYWxzZTtcblxuICAgIGlmICh0aGlzLmNvbXBvbmVudC50eXBlICE9PSAnY2hhcnQnIHx8ICF0aGlzLl9vZmZlcmVkRmVhdHVyZXMoKS5pbmNsdWRlcygnZHJpbGwnKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9maWx0ZXJTdGF0ZS5hZG9wdERyaWxsKHRoaXMuY29tcG9uZW50LmlkLCBhZG9wdGVkRHJpbGxQYXRoKGRhdGEuZHJpbGwpKVxuICAgICAgJiYgZHJpbGxSZXNldE5vdGVkKGRhdGEuZHJpbGwsIGdyYWluTW92ZWQpKSB7XG4gICAgICB0aGlzLl9tZXNzYWdlLndhcm5pbmcoRFJJTExfUkVTRVRfTUVTU0FHRSk7XG4gICAgfVxuICB9XG5cbiAgLy8gLS0tLS0gbWFyayBjbGlja3MgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgcHJpdmF0ZSBfcnVuTWFya0FjdGlvbihhY3Rpb246IFJlcG9ydE1hcmtBY3Rpb24sIGNsaWNrOiBSZXBvcnRNYXJrQ2xpY2spOiB2b2lkIHtcbiAgICBpZiAoYWN0aW9uID09PSAnZHJpbGwnKSB7XG4gICAgICB0aGlzLl9kcmlsbERvd24oY2xpY2spO1xuICAgIH1cbiAgfVxuXG4gIC8vIERyaWxsIGRvd246IHRoZSBjaGFydCdzIHBhdGggZ29lcyBvbmUgbGV2ZWwgYmVsb3cgdGhlIHBlcmlvZCBjbGlja2VkLFxuICAvLyBhbmQgdGhlIGNoYXJ0IHJlYWRzIGFnYWluIChkcmlsbENoYW5nZXMpLlxuICBwcml2YXRlIF9kcmlsbERvd24oY2xpY2s6IFJlcG9ydE1hcmtDbGljayk6IHZvaWQge1xuICAgIGNvbnN0IHBhdGggPSBkcmlsbERvd25QYXRoKHRoaXMuZGF0YSgpPy5kcmlsbCwgY2xpY2spO1xuXG4gICAgaWYgKHBhdGgpIHtcbiAgICAgIHRoaXMuX2ZpbHRlclN0YXRlLnNldERyaWxsKHRoaXMuY29tcG9uZW50LmlkLCBwYXRoKTtcbiAgICB9XG4gIH1cblxuICAvLyBMaXN0cyB0aGUgY2xpY2sncyBhY3Rpb25zIGluIHRoZSBtYXJrIG1lbnUgYW5kIG9wZW5zIGl0IGF0IHRoZSBjbGljayxcbiAgLy8gdGhyb3VnaCB0aGUgemVyby1zaXplIGFuY2hvciAob3BlbkF0UG9pbnQpLlxuICBwcml2YXRlIF9vcGVuTWFya01lbnUoYWN0aW9uczogUmVwb3J0TWFya0FjdGlvbltdLCBjbGljazogUmVwb3J0TWFya0NsaWNrKTogdm9pZCB7XG4gICAgY29uc3QgYW5jaG9yID0gdGhpcy5tYXJrQW5jaG9yPy5uYXRpdmVFbGVtZW50O1xuXG4gICAgaWYgKCFhbmNob3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9tZW51Q2xpY2sgPSBjbGljaztcbiAgICB0aGlzLm1hcmtNZW51QWN0aW9ucy5zZXQoYWN0aW9ucyk7XG4gICAgb3BlbkF0UG9pbnQoYW5jaG9yLCBjbGljay5wb2ludGVyLCB0aGlzLnpvb20sICgpID0+IHRoaXMubWFya01lbnU/Lm9wZW5NZW51KG51bGwpKTtcbiAgfVxufVxuIiwiPGRpdlxuICAgIGNsYXNzPVwiY29tcG9uZW50LWJveFwiXG4gICAgW2NsYXNzLmVkaXRpbmddPVwiZWRpdE1vZGVcIlxuICAgIFtjbGFzcy50ZXh0XT1cImlzVGV4dFwiXG4gICAgW2NsYXNzLnNlbGVjdGVkXT1cInNlbGVjdGVkXCJcbiAgICBbc3R5bGUucGFkZGluZ109XCJib2R5UGFkZGluZ1wiXG4gICAgKHBvaW50ZXJkb3duKT1cIm9uQ29tcG9uZW50UG9pbnRlckRvd24oJGV2ZW50KVwiXG4gICAgKG1vdXNlZG93bik9XCJzdG9wQ2FudmFzUGFuKCRldmVudClcIlxuICAgICh0b3VjaHN0YXJ0KT1cInN0b3BDYW52YXNQYW4oJGV2ZW50KVwiPlxuICA8IS0tIFRoZSBoZWFkZXIgaXMgYW4gZnMtZmlsdGVyOiBoZWFkaW5nIHRlbXBsYXRlID0gdGl0bGUgKGFuZCB0aGUgZWRpdC1tb2RlXG4gICAgICAgZHJhZyBoYW5kbGUpLCBhY3Rpb25zID0gdGhlIG1lbnUsIGl0ZW1zID0gY29tcG9uZW50LWxldmVsIGZpbHRlciBncm91cHMsXG4gICAgICAgdGhlIHNhbWUgc3RyaXAgZm9yIGV2ZXJ5IHR5cGUgKGxpc3RzIGluY2x1ZGVkKS4gZnMtZmlsdGVyIHJlYWRzIGl0c1xuICAgICAgIGNvbmZpZyBvbmNlLCBzbyB0aGUgYmxvY2sgaXMga2V5ZWQgb24gdGhlIGNvbXBvbmVudC1maWx0ZXIgc2V0IHRvIGJlXG4gICAgICAgcmVjcmVhdGVkIHdoZW4gaXQgY2hhbmdlcy4gLS0+XG4gIDwhLS0gQSB0ZXh0IGJsb2NrIGhhcyBubyB0aXRsZSBiYXIg4oCUIGl0IElTIGl0cyB3b3JkcywgbGlrZSBhIHRleHQgYm94IG9uIGFcbiAgICAgICBzbGlkZSDigJQgc28gaXQgZ2V0cyBuZWl0aGVyIHRoZSBoZWFkZXIgbm9yIHRoZSBkYXRhIGFjdGlvbnMuIC0tPlxuICBAZm9yIChrZXkgb2YgaXNUZXh0ID8gW10gOiBbZmlsdGVyS2V5XTsgdHJhY2sga2V5KSB7XG4gICAgPGZzLWZpbHRlclxuICAgICAgICBjbGFzcz1cImNvbXBvbmVudC1maWx0ZXJcIlxuICAgICAgICBbY29uZmlnXT1cImZpbHRlckNvbmZpZygpXCI+XG4gICAgICA8bmctdGVtcGxhdGUgZnNGaWx0ZXJIZWFkaW5nPlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cImNvbXBvbmVudC10aXRsZVwiXG4gICAgICAgICAgICAocG9pbnRlcmRvd24pPVwib25EcmFnU3RhcnQoJGV2ZW50KVwiPlxuICAgICAgICAgIDwhLS0gV2hpbGUgdGhlIGNoYXJ0IGlzIGRyaWxsZWQgdGhlIHRpdGxlIGxlYWRzIGl0cyBicmVhZGNydW1iOlxuICAgICAgICAgICAgICAgJ1RpdGxlIOKAuiAyMDI2IOKAuiBRMycuIFRoZSB0aXRsZSBnb2VzIGJhY2sgdG8gdGhlIHRvcCBhbmQgZWFjaFxuICAgICAgICAgICAgICAgY3J1bWIgdG8gdGhlIHBlcmlvZCBpdCBuYW1lczsgdGhlIGxhc3QgaXMgd2hlcmUgdGhlIGNoYXJ0IGlzLlxuICAgICAgICAgICAgICAgQSBsb25nIHBhdGggaXMgY3V0IGF0IGl0cyBsZWZ0IGVuZCwgc28gdGhlIGNydW1icyBuZWFyZXN0IHRoZVxuICAgICAgICAgICAgICAgY2hhcnQgc3RheSBpbiB2aWV3LiBXaGlsZSB0aGUgbGF5b3V0IGlzIGVkaXRlZCB0aGUgY3J1bWJzIGFyZVxuICAgICAgICAgICAgICAgcGxhaW4gdGV4dCAodGhlIHN0eWxlc2hlZXQ7IGRyaWxsVG8gZG9lcyBub3RoaW5nIHRoZW4pLiAtLT5cbiAgICAgICAgICBAaWYgKGRyaWxsQ3J1bWJzKCkubGVuZ3RoKSB7XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImRyaWxsLXBhdGhcIj5cbiAgICAgICAgICAgICAgPHNwYW4gZGlyPVwibHRyXCI+XG4gICAgICAgICAgICAgICAgPGFcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkcmlsbC1jcnVtYlwiXG4gICAgICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJkcmlsbFRvKDApXCJcbiAgICAgICAgICAgICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiZHJpbGxUbygwKVwiPlxuICAgICAgICAgICAgICAgICAge3sgY29tcG9uZW50LnRpdGxlIH19XG4gICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgIEBmb3IgKGxhYmVsIG9mIGRyaWxsQ3J1bWJzKCk7IHRyYWNrICRpbmRleDsgbGV0IGxhc3QgPSAkbGFzdCkge1xuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkcmlsbC1zZXBhcmF0b3JcIj57eyBkcmlsbFNlcGFyYXRvciB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIEBpZiAobGFzdCkge1xuICAgICAgICAgICAgICAgICAgICA8c3Bhbj57eyBsYWJlbCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkcmlsbC1jcnVtYlwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0YWJpbmRleD1cIjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImRyaWxsVG8oJGluZGV4ICsgMSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiZHJpbGxUbygkaW5kZXggKyAxKVwiPlxuICAgICAgICAgICAgICAgICAgICAgIHt7IGxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgIHt7IGNvbXBvbmVudC50aXRsZSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgICBAaWYgKHRydW5jYXRlZCkge1xuICAgICAgICAgICAgPG1hdC1pY29uXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ0cnVuY2F0ZWQtaWNvblwiXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlNob3dpbmcgYSB0cnVuY2F0ZWQgcmVzdWx0IOKAlCByZWZpbmUgdGhlIGZpbHRlcnMgdG8gc2VlIGV2ZXJ5dGhpbmcuXCI+XG4gICAgICAgICAgICAgIHdhcm5pbmdfYW1iZXJcbiAgICAgICAgICAgIDwvbWF0LWljb24+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9mcy1maWx0ZXI+XG4gIH1cbiAgPCEtLSBUaGUgYWN0aW9ucyBtZW51IGlzIGZsb2F0ZWQgdG9wLXJpZ2h0IChhYnNvbHV0ZSkgcmF0aGVyIHRoYW4gbGl2aW5nIGluXG4gICAgICAgZnMtZmlsdGVyJ3MgYWN0aW9ucyBzbG90LCBzbyBpdHMgfjQwcHggYnV0dG9uIGhlaWdodCBubyBsb25nZXIgZHJpdmVzIHRoZVxuICAgICAgIGhlYWRlciByb3cncyBoZWlnaHQuIEl0IG92ZXJsYXlzIHRoZSBib3ggY29ybmVyOyB0aGUgaGVhZGluZyByZXNlcnZlc1xuICAgICAgIHJpZ2h0IHBhZGRpbmcgc28gYSBsb25nIHRpdGxlIGVsbGlwc2lzZXMgYmVmb3JlIGl0LiAtLT5cbiAgQGlmICghaXNUZXh0IHx8IChlZGl0TW9kZSAmJiAhdGV4dEVkaXRpbmcoKSkpIHtcbiAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICBjbGFzcz1cImNvbXBvbmVudC1tZW51XCJcbiAgICAgICAgW2ZzTWVudVRyaWdnZXJGb3JdPVwibWVudVwiXG4gICAgICAgIChwb2ludGVyZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAobW91c2Vkb3duKT1cInN0b3BDYW52YXNQYW4oJGV2ZW50KVwiPlxuICAgICAgPG1hdC1pY29uPm1vcmVfdmVydDwvbWF0LWljb24+XG4gICAgPC9idXR0b24+XG4gICAgPCEtLSBCZXNpZGUgaXRzIHRyaWdnZXIsIGluc2lkZSB0aGUgc2FtZSBibG9jazogYW4gZnMtbWVudSB0aGF0IGZpbmRzIG5vXG4gICAgICAgICB0cmlnZ2VyIG9mIGl0cyBvd24gZHJhd3Mgb25lLiAtLT5cbiAgICA8ZnMtbWVudSAjbWVudT5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgIGZzLW1lbnUtaXRlbVxuICAgICAgICAgIFtoaWRkZW5dPVwiIWlzVGV4dFwiXG4gICAgICAgICAgKGNsaWNrKT1cImVkaXRUZXh0KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmVkaXQ8L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5FZGl0IHRleHQ8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCIhaXNUZXh0XCJcbiAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlVGV4dCgpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5EZWxldGU8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCIhZHJpbGxDcnVtYnMoKS5sZW5ndGggfHwgZWRpdE1vZGVcIlxuICAgICAgICAgIChjbGljayk9XCJkcmlsbFVwKClcIj5cbiAgICAgICAgPG1hdC1pY29uPmFycm93X3Vwd2FyZDwvbWF0LWljb24+XG4gICAgICAgIDxzcGFuPkRyaWxsIHVwPC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgIGZzLW1lbnUtaXRlbVxuICAgICAgICAgIFtoaWRkZW5dPVwiIWRyaWxsQ3J1bWJzKCkubGVuZ3RoIHx8IGVkaXRNb2RlXCJcbiAgICAgICAgICAoY2xpY2spPVwiZHJpbGxUbygwKVwiPlxuICAgICAgICA8bWF0LWljb24+dmVydGljYWxfYWxpZ25fdG9wPC9tYXQtaWNvbj5cbiAgICAgICAgPHNwYW4+QmFjayB0byB0b3A8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCJpc1RleHRcIlxuICAgICAgICAgIChjbGljayk9XCJzZXR0aW5ncygpXCI+XG4gICAgICAgIDxtYXQtaWNvbj50dW5lPC9tYXQtaWNvbj5cbiAgICAgICAgPHNwYW4+U2V0dGluZ3M8L3NwYW4+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgW2hpZGRlbl09XCJpc1RleHRcIlxuICAgICAgICAgIChjbGljayk9XCJleHBvcnRDc3YoKVwiPlxuICAgICAgICA8bWF0LWljb24+ZG93bmxvYWQ8L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5FeHBvcnQgQ1NWPC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgIGZzLW1lbnUtaXRlbVxuICAgICAgICAgIFtoaWRkZW5dPVwiIWhpZGVzQ29sdW1uc1wiXG4gICAgICAgICAgKGNsaWNrKT1cImNob29zZUNvbHVtbnMoKVwiPlxuICAgICAgICA8bWF0LWljb24+dmlld19jb2x1bW48L21hdC1pY29uPlxuICAgICAgICA8c3Bhbj5Db2x1bW5zPC9zcGFuPlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2ZzLW1lbnU+XG4gIH1cbiAgPGRpdiBjbGFzcz1cImNvbXBvbmVudC1ib2R5XCI+XG4gICAgPCEtLSBBIHJlZmV0Y2gga2VlcHMgdGhlIGRhdGEgb24gc2NyZWVuIHVuZGVyIGEgdGhpbiBiYXI7IHRoZSBzaGltbWVyXG4gICAgICAgICBiZWxvdyBpcyBmb3IgdGhlIGZpcnN0IGxvYWQgb25seS4gLS0+XG4gICAgQGlmIChyZWZyZXNoaW5nKCkpIHtcbiAgICAgIDxtYXQtcHJvZ3Jlc3MtYmFyXG4gICAgICAgIGNsYXNzPVwicmVmcmVzaC1iYXJcIlxuICAgICAgICBhcmlhLWxhYmVsPVwiUmVmcmVzaGluZyBkYXRhXCJcbiAgICAgICAgW21vZGVdPVwiJ2luZGV0ZXJtaW5hdGUnXCI+XG4gICAgICA8L21hdC1wcm9ncmVzcy1iYXI+XG4gICAgfVxuICAgIEBpZiAoaXNUZXh0KSB7XG4gICAgICA8YXBwLXJlcG9ydC1jb21wb25lbnQtdGV4dFxuICAgICAgICBbaHRtbF09XCJ0ZXh0SHRtbCgpID8/IGNvbXBvbmVudC5jb25maWc/Lmh0bWwgPz8gJydcIlxuICAgICAgICBbdG9rZW5zXT1cInRva2VucygpXCJcbiAgICAgICAgW2VkaXRpbmddPVwidGV4dEVkaXRpbmcoKVwiXG4gICAgICAgIFtzaG93bkVsc2V3aGVyZV09XCJzaG93bkVsc2V3aGVyZVwiXG4gICAgICAgIChzYXZlZCk9XCJvblRleHRTYXZlZCgkZXZlbnQpXCJcbiAgICAgICAgKGVkaXRFbmRlZCk9XCJ0ZXh0RWRpdGluZy5zZXQoZmFsc2UpXCJcbiAgICAgICAgKHZhbHVlU2V0dGluZ3MpPVwidmFsdWVTZXR0aW5ncy5lbWl0KCRldmVudClcIj5cbiAgICAgIDwvYXBwLXJlcG9ydC1jb21wb25lbnQtdGV4dD5cbiAgICB9IEBlbHNlIGlmIChjb21wb25lbnQudHlwZSA9PT0gJ2xpc3QnKSB7XG4gICAgICBAZm9yIChrZXkgb2YgW2xpc3RSZXNldEtleSgpXTsgdHJhY2sga2V5KSB7XG4gICAgICAgIDxhcHAtcmVwb3J0LWNvbXBvbmVudC1saXN0XG4gICAgICAgICAgW3JlcG9ydElkXT1cInJlcG9ydElkXCJcbiAgICAgICAgICBbY29tcG9uZW50XT1cImNvbXBvbmVudFwiPlxuICAgICAgICA8L2FwcC1yZXBvcnQtY29tcG9uZW50LWxpc3Q+XG4gICAgICB9XG4gICAgfSBAZWxzZSBpZiAobG9hZGluZygpKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwiY29tcG9uZW50LXN0YXRlXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLXNoaW1tZXJcIj48L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIH0gQGVsc2UgaWYgKGVycm9yKCkpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJjb21wb25lbnQtc3RhdGUgZXJyb3JcIj5cbiAgICAgICAge3sgZXJyb3IoKSB9fVxuICAgICAgPC9kaXY+XG4gICAgfSBAZWxzZSBpZiAoIWRhdGEoKT8ucm93cz8ubGVuZ3RoKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwiY29tcG9uZW50LXN0YXRlXCI+XG4gICAgICAgIHt7IGVtcHR5TWVzc2FnZSgpIH19XG4gICAgICA8L2Rpdj5cbiAgICB9IEBlbHNlIGlmIChjb21wb25lbnQudHlwZSA9PT0gJ2twaScpIHtcbiAgICAgIDxhcHAtcmVwb3J0LWNvbXBvbmVudC1rcGlcbiAgICAgICAgW2NvbXBvbmVudF09XCJjb21wb25lbnRcIlxuICAgICAgICBbZGF0YV09XCJkYXRhKClcIlxuICAgICAgICAobWFya0NsaWNrKT1cIm9uTWFya0NsaWNrKCRldmVudClcIj5cbiAgICAgIDwvYXBwLXJlcG9ydC1jb21wb25lbnQta3BpPlxuICAgIH0gQGVsc2Uge1xuICAgICAgPGFwcC1yZXBvcnQtY29tcG9uZW50LWNoYXJ0XG4gICAgICAgIFtjb21wb25lbnRdPVwiY29tcG9uZW50XCJcbiAgICAgICAgW2RhdGFdPVwiZGF0YSgpXCJcbiAgICAgICAgW2FjdGlvbnNdPVwidGlsZUFjdGlvbnMoKVwiXG4gICAgICAgIFsobGVnZW5kU2VsZWN0ZWQpXT1cImxlZ2VuZFNlbGVjdGVkXCJcbiAgICAgICAgKG1hcmtDbGljayk9XCJvbk1hcmtDbGljaygkZXZlbnQpXCJcbiAgICAgICAgKG1hcmtNaXNzKT1cIm9uTWFya01pc3MoKVwiPlxuICAgICAgPC9hcHAtcmVwb3J0LWNvbXBvbmVudC1jaGFydD5cbiAgICB9XG4gICAgPCEtLSBJbiBlZGl0IG1vZGUgYSB0cmFuc3BhcmVudCB2ZWlsIG92ZXIgdGhlIGJvZHkgbWFrZXMgdGhlIFdIT0xFXG4gICAgICAgICBjb21wb25lbnQgZHJhZ2dhYmxlIChpbmR1c3RyeSBzdGFuZGFyZDogeW91IGdyYWIgdGhlIG9iamVjdCwgbm90IGp1c3RcbiAgICAgICAgIGl0cyB0aXRsZSBiYXIpIGFuZCBrZWVwcyBpbm5lciB3aWRnZXRzIGZyb20gc3dhbGxvd2luZyB0aGUgZ2VzdHVyZS4gLS0+XG4gICAgQGlmIChlZGl0TW9kZSAmJiAhdGV4dEVkaXRpbmcoKSkge1xuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cImRyYWctdmVpbFwiXG4gICAgICAgIChwb2ludGVyZG93bik9XCJvbkRyYWdTdGFydCgkZXZlbnQpXCI+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIDwvZGl2PlxuPC9kaXY+XG48IS0tIFRoZSBtYXJrIG1lbnUsIGZvciBhIGNsaWNrIHdob3NlIG1hcmsgb2ZmZXJzIHR3byBvciBtb3JlIGFjdGlvbnMuIEl0XG4gICAgIG9wZW5zIGF0IHRoZSBjbGljazogaXRzIHRyaWdnZXIgaXMgYSB6ZXJvLXNpemUgYW5jaG9yIHRoYXRcbiAgICAgYW5jaG9yLWF0LXBvaW50LnRzIG1vdmVzIHRoZXJlIGZpcnN0LiAtLT5cbkBpZiAoIWlzVGV4dCAmJiAhZWRpdE1vZGUpIHtcbiAgPHNwYW5cbiAgICAjbWFya0FuY2hvclxuICAgIFtzdHlsZS5wb3NpdGlvbl09XCInYWJzb2x1dGUnXCJcbiAgICBbZnNNZW51VHJpZ2dlckZvcl09XCJtYXJrTWVudVwiPlxuICA8L3NwYW4+XG4gIDxmcy1tZW51ICNtYXJrTWVudT5cbiAgICBAZm9yIChhY3Rpb24gb2YgbWFya01lbnVBY3Rpb25zKCk7IHRyYWNrIGFjdGlvbikge1xuICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbWVudS1pdGVtXG4gICAgICAgICAgKGNsaWNrKT1cInJ1bk1hcmtBY3Rpb24oYWN0aW9uKVwiPlxuICAgICAgICB7eyBtYXJrQWN0aW9uTGFiZWxzW2FjdGlvbl0gfX1cbiAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgfVxuICA8L2ZzLW1lbnU+XG59XG48IS0tIEhhbmRsZXMgbGl2ZSBPVVRTSURFIHRoZSBjbGlwcGVkIGJveCBzbyB0aGV5IHN0cmFkZGxlIGl0cyBlZGdlcy4gLS0+XG5AaWYgKGVkaXRNb2RlICYmIHNlbGVjdGVkKSB7XG4gIEBmb3IgKGhhbmRsZSBvZiByZXNpemVIYW5kbGVzOyB0cmFjayBoYW5kbGUpIHtcbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cImhhbmRsZSBoYW5kbGUte3sgaGFuZGxlIH19XCJcbiAgICAgIChtb3VzZWRvd24pPVwic3RvcENhbnZhc1BhbigkZXZlbnQpXCJcbiAgICAgIChwb2ludGVyZG93bik9XCJvblJlc2l6ZVN0YXJ0KCRldmVudCwgaGFuZGxlKVwiPlxuICAgIDwvZGl2PlxuICB9XG59Il19
|