@firestitch/report 18.8.1 → 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/component-text/component-text.component.d.ts +47 -2
- package/app/reports/components/component-text/value-embed.plugin.d.ts +67 -0
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +37 -9
- package/app/reports/components/report-component/report-component.component.d.ts +45 -2
- package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
- package/app/reports/data/report.data.d.ts +18 -2
- package/app/reports/dialogs/component-settings/component-settings.component.d.ts +25 -2
- 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/enums/report-value-formula.enum.d.ts +6 -0
- package/app/reports/export/report-export-collector.service.d.ts +35 -4
- package/app/reports/export/report-export.service.d.ts +3 -1
- package/app/reports/export/report-filter-lines.d.ts +18 -0
- package/app/reports/export/report-pdf.service.d.ts +18 -2
- package/app/reports/export/report-pptx.service.d.ts +15 -2
- package/app/reports/export/report-text-layout.service.d.ts +35 -0
- package/app/reports/filter-settings-rules.d.ts +33 -0
- package/app/reports/format.d.ts +2 -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 +48 -5
- package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
- package/app/reports/layout.d.ts +2 -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 +65 -2
- package/app/reports/services/report-view.service.d.ts +51 -0
- package/app/reports/text.d.ts +50 -0
- package/app/reports/tile-data-state.d.ts +7 -0
- package/app/reports/tile-loads.d.ts +4 -0
- package/app/reports/values.d.ts +17 -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/component-text/component-text.component.mjs +213 -16
- package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +484 -0
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +296 -55
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +318 -76
- package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
- package/esm2022/app/reports/data/report.data.mjs +103 -8
- package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +210 -44
- 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/enums/report-value-formula.enum.mjs +14 -0
- package/esm2022/app/reports/export/report-export-collector.service.mjs +299 -125
- package/esm2022/app/reports/export/report-export.service.mjs +57 -19
- package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
- package/esm2022/app/reports/export/report-pdf.service.mjs +315 -71
- package/esm2022/app/reports/export/report-pptx.service.mjs +293 -71
- package/esm2022/app/reports/export/report-text-layout.service.mjs +241 -0
- package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
- package/esm2022/app/reports/format.mjs +13 -30
- 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/layout.mjs +11 -1
- 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 +715 -71
- package/esm2022/app/reports/services/report-view.service.mjs +358 -0
- package/esm2022/app/reports/text.mjs +293 -85
- package/esm2022/app/reports/tile-data-state.mjs +127 -0
- package/esm2022/app/reports/tile-loads.mjs +38 -0
- package/esm2022/app/reports/values.mjs +183 -0
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +180 -46
- package/esm2022/app/reports/views/report/report.component.mjs +106 -23
- package/esm2022/public_api.mjs +24 -1
- package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
- package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
- package/fesm2022/{firestitch-report-firestitch-report-CSylkyko.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +11315 -4201
- 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 +23 -0
- package/fesm2022/firestitch-report-firestitch-report-CSylkyko.mjs.map +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { ItemType } from '@firestitch/filter';
|
|
1
|
+
import { ItemType, getExcludeName } from '@firestitch/filter';
|
|
2
2
|
import { format, parseISO } from 'date-fns';
|
|
3
3
|
import { of } from 'rxjs';
|
|
4
4
|
import { map, shareReplay } from 'rxjs/operators';
|
|
5
|
-
import {
|
|
5
|
+
import { filterLineText, matchLineText } from './export/report-filter-lines';
|
|
6
|
+
import { DAY_SHORT, formatLocalDate, resolveFormatContext } from './format';
|
|
6
7
|
import { GRANULARITY_OPTIONS, } from './interfaces/report.interface';
|
|
8
|
+
import { offersExclude } from './report-viewer-features';
|
|
7
9
|
// A date-range boundary as the picked LOCAL calendar day (no time, no tz).
|
|
8
10
|
// Date-range filters are calendar-day semantics, so the boundary must carry
|
|
9
11
|
// only Y-M-D — never a timezone-bearing instant the backend would shift.
|
|
@@ -67,14 +69,8 @@ export function relativeLabel(relative) {
|
|
|
67
69
|
// query values back into per-group FilterGroupValues. Shared by the report-bar
|
|
68
70
|
// fs-filter and the per-component fs-filter so both render through the same
|
|
69
71
|
// library and write into ReportFilterStateService identically. Items are named
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
export const GROUP_PARAM_PREFIX = 'g';
|
|
73
|
-
// The query key fs-filter uses for a group's item(s), and the report URL's key
|
|
74
|
-
// for the group's value (report-url-state.ts). One naming for both.
|
|
75
|
-
export function groupItemName(group) {
|
|
76
|
-
return `${GROUP_PARAM_PREFIX}${group.id}`;
|
|
77
|
-
}
|
|
72
|
+
// by the group's key (groupParamKeys), so the query keys map straight back to
|
|
73
|
+
// the group, and the report link uses the same query keys (report-url-state.ts).
|
|
78
74
|
// The query key for the report's group-by control. Fixed rather than derived
|
|
79
75
|
// from an id because a report has exactly one — and it is NOT a filter group,
|
|
80
76
|
// so it is read straight off the change query instead of through
|
|
@@ -82,15 +78,115 @@ export function groupItemName(group) {
|
|
|
82
78
|
// (report-url-state.ts). The grain travels to the server as the data
|
|
83
79
|
// request's `state.frequency`.
|
|
84
80
|
export const GROUP_BY_ITEM = 'groupBy';
|
|
81
|
+
// The keys of the report URL that are not filter groups (report-url-state.ts
|
|
82
|
+
// reads and writes them). They are declared here because a group key must
|
|
83
|
+
// not take one, and report-url-state.ts imports this file.
|
|
84
|
+
// The shared view the state is a diff from, and the open personal view.
|
|
85
|
+
export const VIEW_PARAM = 'rv';
|
|
86
|
+
export const PERSONAL_VIEW_PARAM = 'rpv';
|
|
87
|
+
// The link's format.
|
|
88
|
+
export const FORMAT_PARAM = 'rf';
|
|
89
|
+
// The host's page key (FsAiReportComponent.pageQueryParam), as most hosts
|
|
90
|
+
// name it.
|
|
91
|
+
export const PAGE_PARAM = 'page';
|
|
92
|
+
// The word before a group's id in the key of a group whose label gives no
|
|
93
|
+
// key it can use (filter12).
|
|
94
|
+
const FALLBACK_KEY_WORD = 'filter';
|
|
95
|
+
// The query key of one end of an fs-filter range item: the item's name and
|
|
96
|
+
// the end with its first letter upper-cased (fs-filter's getRangeName), so
|
|
97
|
+
// units gives unitsMin and date gives dateFrom.
|
|
98
|
+
export function itemRangeName(name, end) {
|
|
99
|
+
return `${name}${end.charAt(0).toUpperCase()}${end.slice(1)}`;
|
|
100
|
+
}
|
|
101
|
+
// Each group's key in the report URL, by group id, which is also the name of
|
|
102
|
+
// its fs-filter item: the camelCase of the label the bar shows ('Region' ->
|
|
103
|
+
// region, 'Report Period' -> reportPeriod). The link writes a group under
|
|
104
|
+
// the item's own query keys (region=, excludeRegion=, unitsMin=, dateFrom=).
|
|
105
|
+
// A key the report cannot give a group as it is (another group with a lower
|
|
106
|
+
// id has it or one of its forms, another link key or bar item uses it, or it
|
|
107
|
+
// is shaped like a tile's id key, such as q4) is the key and the group's id
|
|
108
|
+
// (region12). A label with no letter or digit, or a clash even then, keys on
|
|
109
|
+
// filter<id>. `groups` is every group of the report, so every bar and the
|
|
110
|
+
// link name a group alike.
|
|
111
|
+
export function groupParamKeys(groups) {
|
|
112
|
+
// The URL's other keys and the bar's other items.
|
|
113
|
+
const taken = new Set([
|
|
114
|
+
PAGE_PARAM, GROUP_BY_ITEM, MATCH_ITEM, LIST_SEARCH_ITEM, VIEW_PARAM, PERSONAL_VIEW_PARAM, FORMAT_PARAM,
|
|
115
|
+
]);
|
|
116
|
+
const free = (candidate) => !!candidate
|
|
117
|
+
&& keyForms(candidate).every((form) => !taken.has(form) && !ID_KEY.test(form));
|
|
118
|
+
const keys = new Map();
|
|
119
|
+
[...groups]
|
|
120
|
+
.sort((a, b) => a.id - b.id)
|
|
121
|
+
.forEach((group) => {
|
|
122
|
+
const wanted = labelKey(groupLabel(group));
|
|
123
|
+
const key = [wanted, wanted && `${wanted}${group.id}`].find(free) ?? fallbackKey(group.id, free);
|
|
124
|
+
keyForms(key).forEach((form) => taken.add(form));
|
|
125
|
+
keys.set(group.id, key);
|
|
126
|
+
});
|
|
127
|
+
return keys;
|
|
128
|
+
}
|
|
129
|
+
// filter<id>, or, in the rare report where another group's label already
|
|
130
|
+
// gives that, filter<id> and a count.
|
|
131
|
+
function fallbackKey(groupId, free) {
|
|
132
|
+
const base = `${FALLBACK_KEY_WORD}${groupId}`;
|
|
133
|
+
let key = base;
|
|
134
|
+
for (let count = 2; !free(key); count++) {
|
|
135
|
+
key = `${base}N${count}`;
|
|
136
|
+
}
|
|
137
|
+
return key;
|
|
138
|
+
}
|
|
139
|
+
// A group's key among `groups` (every group of the report). A group that is
|
|
140
|
+
// not among them is keyed as one more of them.
|
|
141
|
+
export function groupParamKey(group, groups) {
|
|
142
|
+
return groupParamKeys(groups.some((candidate) => candidate.id === group.id) ? groups : [...groups, group])
|
|
143
|
+
.get(group.id);
|
|
144
|
+
}
|
|
145
|
+
// The name of a group's fs-filter item: its key among the report's groups.
|
|
146
|
+
export function groupItemName(group, report) {
|
|
147
|
+
return groupParamKey(group, report?.filterGroups ?? []);
|
|
148
|
+
}
|
|
149
|
+
// The label a group's chip shows: its own, else its first member's column.
|
|
150
|
+
function groupLabel(group) {
|
|
151
|
+
return group.label || group.filters?.[0]?.filterColumn || '';
|
|
152
|
+
}
|
|
153
|
+
// A letter and then digits: the shape of the URL's tile keys (s31, q31,
|
|
154
|
+
// h31, d44), kept off the groups so a group key never reads as one.
|
|
155
|
+
const ID_KEY = /^[a-z]\d+$/;
|
|
156
|
+
const RANGE_ENDS = ['min', 'max', 'from', 'to'];
|
|
157
|
+
// Every key a group's item or link may write under `key`: the key, its
|
|
158
|
+
// exclude key (excludeRegion) and an fs-filter range's own keys.
|
|
159
|
+
function keyForms(key) {
|
|
160
|
+
return [key, getExcludeName(key), ...RANGE_ENDS.map((end) => itemRangeName(key, end))];
|
|
161
|
+
}
|
|
162
|
+
// A label as a camelCase key: accents dropped, words split on anything that
|
|
163
|
+
// is not a letter or digit (and where a lower-case letter meets an upper-case
|
|
164
|
+
// one), the first word lower-case, every later one capitalized.
|
|
165
|
+
function labelKey(label) {
|
|
166
|
+
return label
|
|
167
|
+
.normalize('NFD')
|
|
168
|
+
.replace(/\p{M}/gu, '')
|
|
169
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
170
|
+
.split(/[^A-Za-z0-9]+/)
|
|
171
|
+
.filter((word) => word !== '')
|
|
172
|
+
.map((word, index) => {
|
|
173
|
+
const lower = word.toLowerCase();
|
|
174
|
+
return index ? lower.charAt(0).toUpperCase() + lower.slice(1) : lower;
|
|
175
|
+
})
|
|
176
|
+
.join('');
|
|
177
|
+
}
|
|
85
178
|
// A select group's distinct options, as { name, value } pairs. The server sends
|
|
86
179
|
// { value, label }: the value is what the filter matches on (an entity's stable
|
|
87
180
|
// id) and the label is what the viewer reads — so a renamed entity keeps its id
|
|
88
181
|
// and simply shows its new name here. Options come from the first member filter
|
|
89
182
|
// that declares them — members are the same data point, so any member's list
|
|
90
183
|
// serves the group. The list is fetched once (the server caps it) and replayed
|
|
91
|
-
// (shareReplay), so repeated reads never refetch.
|
|
92
|
-
//
|
|
93
|
-
//
|
|
184
|
+
// (shareReplay), so repeated reads never refetch. This is the full list, never
|
|
185
|
+
// narrowed by other filters: the report-settings default picker reads it (an
|
|
186
|
+
// author sets a default against the whole list), and so does the export's
|
|
187
|
+
// filter wording for a pick the bar has not named. The bars read
|
|
188
|
+
// ReportFilterOptionsService instead. Returns an empty list when no member
|
|
189
|
+
// provides options.
|
|
94
190
|
export function loadGroupOptions(group, reportData, reportId) {
|
|
95
191
|
const optionFilter = (group.filters ?? []).find((member) => member.hasOptions);
|
|
96
192
|
if (!optionFilter) {
|
|
@@ -102,15 +198,21 @@ export function loadGroupOptions(group, reportData, reportId) {
|
|
|
102
198
|
}
|
|
103
199
|
// Stored filter values (ids) paired back with the labels to show for them.
|
|
104
200
|
// A saved default holds only values, so the names have to be read back off the
|
|
105
|
-
// option list — that indirection is exactly what survives a rename.
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
201
|
+
// option list — that indirection is exactly what survives a rename. `label`
|
|
202
|
+
// names a value first: a name already learned (ReportFilterOptionsService.label)
|
|
203
|
+
// holds for a pick a narrowed list leaves out, and when it names every value
|
|
204
|
+
// the list is not read at all. A value with no name and no matching option
|
|
205
|
+
// (its entity was deleted, so it is no longer listed) falls back to showing
|
|
206
|
+
// the raw value rather than dropping the chip, which would silently widen the
|
|
207
|
+
// filter.
|
|
208
|
+
export function resolveOptionValues(options$, values, label = () => null) {
|
|
209
|
+
const named = (options) => values.map((value) => {
|
|
111
210
|
const option = options.find((candidate) => String(candidate.value) === String(value));
|
|
112
|
-
return { name: option?.name ?? String(value), value };
|
|
113
|
-
})
|
|
211
|
+
return { name: label(value) ?? option?.name ?? String(value), value };
|
|
212
|
+
});
|
|
213
|
+
return values.every((value) => label(value) !== null)
|
|
214
|
+
? of(named([]))
|
|
215
|
+
: options$.pipe(map(named));
|
|
114
216
|
}
|
|
115
217
|
// Case-insensitive name filter applied to a loaded option list — the typed
|
|
116
218
|
// keyword has to be matched here because fs-autocomplete renders what we return
|
|
@@ -121,47 +223,161 @@ export function matchOptions(options$, keyword) {
|
|
|
121
223
|
? options.filter((option) => option.name.toLowerCase().includes(term))
|
|
122
224
|
: options));
|
|
123
225
|
}
|
|
226
|
+
// The panel row of a select whose list the server cut at 500.
|
|
227
|
+
export const OPTIONS_TRUNCATED_NOTE = 'Showing the first 500. Type to narrow.';
|
|
228
|
+
// The panel row of a select whose list could not be read. The next focus or
|
|
229
|
+
// keystroke asks again.
|
|
230
|
+
export const OPTIONS_FAILED_NOTE = 'Could not load the list.';
|
|
124
231
|
// Build the fs-filter config item for a group, seeding its default from the
|
|
125
232
|
// current session value so authored/relative defaults show selected on open.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
233
|
+
// A select lists what `options` offers for it in `report`. `features` is the
|
|
234
|
+
// report's viewerFeatures: a select offers 'Exclude these' by the rule of
|
|
235
|
+
// offersExclude (the server lists excludeValues and no member binds several
|
|
236
|
+
// columns), and a number range is a min/max control only when it lists
|
|
237
|
+
// numberRange.
|
|
238
|
+
export function filterItemForGroup(group, options, report, initial, features = []) {
|
|
239
|
+
const name = groupItemName(group, report);
|
|
240
|
+
const label = groupLabel(group);
|
|
129
241
|
switch (group.type) {
|
|
130
242
|
case 'dateRange':
|
|
131
|
-
return
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
case 'select': {
|
|
140
|
-
// One shared, replayed option stream so typing never refetches.
|
|
141
|
-
const options$ = loadGroupOptions(group, reportData, reportId);
|
|
142
|
-
const values = initial?.values;
|
|
143
|
-
return {
|
|
144
|
-
name,
|
|
145
|
-
type: ItemType.AutoCompleteChips,
|
|
146
|
-
label,
|
|
147
|
-
fetchOnFocus: true,
|
|
148
|
-
values: (keyword) => matchOptions(options$, keyword),
|
|
149
|
-
// Stored values are ids, so the chips can only be named once the option
|
|
150
|
-
// list has loaded — hence the observable form of `default`.
|
|
151
|
-
default: values?.length
|
|
152
|
-
? () => resolveOptionValues(options$, values)
|
|
153
|
-
: undefined,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
243
|
+
return dateRangeFilterItem(name, label, initial);
|
|
244
|
+
case 'select':
|
|
245
|
+
return selectFilterItem(group, label, options, report, initial, offersExclude(group, features));
|
|
246
|
+
case 'numberRange':
|
|
247
|
+
return features.includes('numberRange')
|
|
248
|
+
? numberRangeFilterItem(group, label, report, initial)
|
|
249
|
+
: keywordFilterItem(name, label, initial);
|
|
156
250
|
case 'keyword':
|
|
157
251
|
default:
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
252
|
+
return keywordFilterItem(name, label, initial);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// A date range opens on its days, and its chip shows them. A preset picked in
|
|
256
|
+
// the date picker only sets the days.
|
|
257
|
+
function dateRangeFilterItem(name, label, initial) {
|
|
258
|
+
const hasDays = !!(initial?.start || initial?.end);
|
|
259
|
+
return {
|
|
260
|
+
name,
|
|
261
|
+
type: ItemType.DateRange,
|
|
262
|
+
label: { from: `${label} From`, to: `${label} To` },
|
|
263
|
+
default: hasDays
|
|
264
|
+
? { from: initial.start ?? undefined, to: initial.end ?? undefined }
|
|
265
|
+
: undefined,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// A select's picks, kept or left out. With `exclude` the list has the
|
|
269
|
+
// 'Exclude these' row, and a value that leaves out opens with it on. Its list
|
|
270
|
+
// is read on focus and on each keystroke: the options service fetches it when
|
|
271
|
+
// the other filters changed since and replays it otherwise, and typing
|
|
272
|
+
// filters it here. A list the server cut, or one that could not be read,
|
|
273
|
+
// says so in a panel row.
|
|
274
|
+
function selectFilterItem(group, label, options, report, initial, exclude) {
|
|
275
|
+
const excluding = exclude && !initial?.values?.length && !!initial?.excludeValues?.length;
|
|
276
|
+
const picks = excluding ? initial.excludeValues : initial?.values;
|
|
277
|
+
const options$ = options.options(group, report);
|
|
278
|
+
return {
|
|
279
|
+
name: groupItemName(group, report),
|
|
280
|
+
type: ItemType.AutoCompleteChips,
|
|
281
|
+
label,
|
|
282
|
+
fetchOnFocus: true,
|
|
283
|
+
exclude: exclude ? {} : undefined,
|
|
284
|
+
values: (keyword) => matchOptions(options$, keyword),
|
|
285
|
+
panelNote: () => optionsNote(options, group.id),
|
|
286
|
+
// Stored values are ids, so a chip is named by a name already learned or
|
|
287
|
+
// once the option list has loaded — hence the observable form of `default`.
|
|
288
|
+
default: picks?.length
|
|
289
|
+
? () => resolveOptionValues(options$, picks, (value) => options.label(group.id, value))
|
|
290
|
+
.pipe(map((selected) => (excluding ? { exclude: true, selected } : selected)))
|
|
291
|
+
: undefined,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
// The panel row of a select's latest list: a failure first, then a cut list.
|
|
295
|
+
function optionsNote(options, groupId) {
|
|
296
|
+
if (options.failed(groupId)) {
|
|
297
|
+
return OPTIONS_FAILED_NOTE;
|
|
164
298
|
}
|
|
299
|
+
return options.truncated(groupId) ? OPTIONS_TRUNCATED_NOTE : null;
|
|
300
|
+
}
|
|
301
|
+
// A number range's low and high ends, either one open. 0 is an end like any
|
|
302
|
+
// other. Its chip reads as the export lines do ('Amount: 0 or more',
|
|
303
|
+
// 'Amount: 0 to 10'): the ends are read off the item's query the way the
|
|
304
|
+
// bar's change reads them, and worded in the report's locale.
|
|
305
|
+
function numberRangeFilterItem(group, label, report, initial) {
|
|
306
|
+
const name = groupItemName(group, report);
|
|
307
|
+
const min = initial?.min ?? undefined;
|
|
308
|
+
const max = initial?.max ?? undefined;
|
|
309
|
+
const locale = resolveFormatContext(report ?? {}).locale;
|
|
310
|
+
return {
|
|
311
|
+
name,
|
|
312
|
+
type: ItemType.Range,
|
|
313
|
+
label,
|
|
314
|
+
default: min !== undefined || max !== undefined ? { min, max } : undefined,
|
|
315
|
+
chipText: (item) => filterLineText({ label, level: group.level }, numberRangeFromQuery(item.query, name), { locale }, 'chip'),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function keywordFilterItem(name, label, initial) {
|
|
319
|
+
return {
|
|
320
|
+
name,
|
|
321
|
+
type: ItemType.Keyword,
|
|
322
|
+
label,
|
|
323
|
+
default: initial?.value,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
// The groups a match of 'any' combines: report bar groups (a page group on
|
|
327
|
+
// its own page only) that a viewer picks values, text or a number range in.
|
|
328
|
+
// Dates, tile-only groups and the cross-filter always narrow on their own.
|
|
329
|
+
// The server holds the same rule and checks every id it is sent.
|
|
330
|
+
const MATCH_ANY_LEVELS = ['report', 'both', 'page'];
|
|
331
|
+
const MATCH_ANY_TYPES = ['select', 'keyword', 'numberRange'];
|
|
332
|
+
// Whether a group joins a match of 'any' on page `pageId`.
|
|
333
|
+
export function isMatchAnyGroup(group, pageId) {
|
|
334
|
+
return MATCH_ANY_LEVELS.includes(group.level)
|
|
335
|
+
&& MATCH_ANY_TYPES.includes(group.type)
|
|
336
|
+
&& (group.level !== 'page' || (!!pageId && group.pageId === pageId));
|
|
337
|
+
}
|
|
338
|
+
// The report bar's groups in their saved order: the report and both groups,
|
|
339
|
+
// and the page groups of the page on screen (`pageId`).
|
|
340
|
+
export function reportBarGroups(report, pageId) {
|
|
341
|
+
return (report?.filterGroups ?? [])
|
|
342
|
+
.filter((group) => group.level === 'report' || group.level === 'both'
|
|
343
|
+
|| (group.level === 'page' && !!pageId && group.pageId === pageId))
|
|
344
|
+
.sort((a, b) => a.order - b.order);
|
|
345
|
+
}
|
|
346
|
+
// Whether the report has a group shown on one page only, so its report bar
|
|
347
|
+
// changes with the page on screen.
|
|
348
|
+
export function hasPageGroup(report) {
|
|
349
|
+
return (report?.filterGroups ?? []).some((group) => group.level === 'page');
|
|
350
|
+
}
|
|
351
|
+
// The query key of the report bar's Match control. Not a filter group: it
|
|
352
|
+
// says how the groups combine, so it is read straight off the change query.
|
|
353
|
+
// It is also the report URL's key for the match (match=any).
|
|
354
|
+
export const MATCH_ITEM = 'match';
|
|
355
|
+
const MATCH_OPTIONS = [
|
|
356
|
+
{ name: 'All filters', value: 'all' },
|
|
357
|
+
{ name: 'Any filter', value: 'any' },
|
|
358
|
+
];
|
|
359
|
+
// The report bar's Match control, last in the bar, or null when it would do
|
|
360
|
+
// nothing: the server must serve matchAny, and the bar must hold two or more
|
|
361
|
+
// groups that combine (an 'any' over one group is that group).
|
|
362
|
+
export function matchFilterItem(report, groups, pageId, match) {
|
|
363
|
+
const eligible = groups.filter((group) => isMatchAnyGroup(group, pageId));
|
|
364
|
+
if (!report?.viewerFeatures?.includes('matchAny') || eligible.length < 2) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
name: MATCH_ITEM,
|
|
369
|
+
type: ItemType.Select,
|
|
370
|
+
label: 'Match',
|
|
371
|
+
multiple: false,
|
|
372
|
+
values: () => MATCH_OPTIONS,
|
|
373
|
+
default: match,
|
|
374
|
+
// 'Match: any filter' or 'Match: all filters', in the export lines' words.
|
|
375
|
+
chipText: (item) => matchLineText(matchFromQuery(item.query), 'chip'),
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
// The match a change query of a bar with the Match control asks for.
|
|
379
|
+
export function matchFromQuery(query) {
|
|
380
|
+
return query?.[MATCH_ITEM] === 'any' ? 'any' : 'all';
|
|
165
381
|
}
|
|
166
382
|
// The query key of a list's search box in its component header. Fixed rather
|
|
167
383
|
// than derived from an id because a header holds at most one, and it is NOT a
|
|
@@ -245,26 +461,81 @@ export function groupBySignature(report) {
|
|
|
245
461
|
}
|
|
246
462
|
// Read an fs-filter change query into per-group values. Returns one entry per
|
|
247
463
|
// group with the value to store (or null to clear) — callers feed these to
|
|
248
|
-
// ReportFilterStateService.setValue.
|
|
249
|
-
export function groupValuesFromQuery(query, groups) {
|
|
464
|
+
// ReportFilterStateService.setValue. `report` names the groups' items.
|
|
465
|
+
export function groupValuesFromQuery(query, groups, report) {
|
|
250
466
|
return groups.map((group) => {
|
|
251
|
-
const name = groupItemName(group);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
groupId: group.id,
|
|
257
|
-
|
|
258
|
-
|
|
467
|
+
const name = groupItemName(group, report);
|
|
468
|
+
switch (group.type) {
|
|
469
|
+
case 'dateRange':
|
|
470
|
+
return { groupId: group.id, value: dateRangeFromQuery(query, name) };
|
|
471
|
+
case 'select':
|
|
472
|
+
return { groupId: group.id, value: selectFromQuery(query, name) };
|
|
473
|
+
case 'numberRange':
|
|
474
|
+
return { groupId: group.id, value: numberRangeFromQuery(query, name) };
|
|
475
|
+
default: {
|
|
476
|
+
const keyword = String(query[name] ?? '').trim();
|
|
477
|
+
return { groupId: group.id, value: keyword ? { value: keyword } : null };
|
|
478
|
+
}
|
|
259
479
|
}
|
|
260
|
-
if (group.type === 'select') {
|
|
261
|
-
const values = selectQueryValues(query[name]);
|
|
262
|
-
return { groupId: group.id, value: values.length ? { values } : null };
|
|
263
|
-
}
|
|
264
|
-
const keyword = String(query[name] ?? '').trim();
|
|
265
|
-
return { groupId: group.id, value: keyword ? { value: keyword } : null };
|
|
266
480
|
});
|
|
267
481
|
}
|
|
482
|
+
// A date range's days (<key>From, <key>To).
|
|
483
|
+
function dateRangeFromQuery(query, name) {
|
|
484
|
+
const start = query[itemRangeName(name, 'from')];
|
|
485
|
+
const end = query[itemRangeName(name, 'to')];
|
|
486
|
+
if (!start && !end) {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
return { start: start || null, end: end || null };
|
|
490
|
+
}
|
|
491
|
+
// A select's picks: kept (<key>), or left out while its exclude row is on
|
|
492
|
+
// (exclude<Key>).
|
|
493
|
+
function selectFromQuery(query, name) {
|
|
494
|
+
const excludeValues = selectQueryValues(query[getExcludeName(name)]);
|
|
495
|
+
if (excludeValues.length) {
|
|
496
|
+
return { excludeValues };
|
|
497
|
+
}
|
|
498
|
+
const values = selectQueryValues(query[name]);
|
|
499
|
+
return values.length ? { values } : null;
|
|
500
|
+
}
|
|
501
|
+
// A number range's ends (<key>Min, <key>Max). An end left empty is open.
|
|
502
|
+
function numberRangeFromQuery(query, name) {
|
|
503
|
+
const min = rangeBound(query[itemRangeName(name, 'min')]);
|
|
504
|
+
const max = rangeBound(query[itemRangeName(name, 'max')]);
|
|
505
|
+
if (min === null && max === null) {
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
...(min !== null ? { min } : {}),
|
|
510
|
+
...(max !== null ? { max } : {}),
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
// One end of a number range as fs-filter's Range sends it: the text typed in
|
|
514
|
+
// its input. Number() reads any non-empty text, so '0' is the end 0; empty or
|
|
515
|
+
// unreadable text is an open end.
|
|
516
|
+
function rangeBound(raw) {
|
|
517
|
+
const text = typeof raw === 'number' ? String(raw) : String(raw ?? '').trim();
|
|
518
|
+
const number = text === '' ? NaN : Number(text);
|
|
519
|
+
return Number.isFinite(number) ? number : null;
|
|
520
|
+
}
|
|
521
|
+
// A group value as text, the same for the same value whatever its source:
|
|
522
|
+
// days as calendar days, picks and ends as text, keyword text trimmed. The
|
|
523
|
+
// value a tile header was built with is keyed on it, so a header is created
|
|
524
|
+
// again when another bar changes a group it shows.
|
|
525
|
+
export function groupValueSignature(value) {
|
|
526
|
+
if (!value) {
|
|
527
|
+
return '';
|
|
528
|
+
}
|
|
529
|
+
return JSON.stringify([
|
|
530
|
+
dateBoundString(value.start) ?? '',
|
|
531
|
+
dateBoundString(value.end) ?? '',
|
|
532
|
+
(value.values ?? []).map(String),
|
|
533
|
+
(value.excludeValues ?? []).map(String),
|
|
534
|
+
(value.value ?? '').trim(),
|
|
535
|
+
value.min ?? '',
|
|
536
|
+
value.max ?? '',
|
|
537
|
+
]);
|
|
538
|
+
}
|
|
268
539
|
// fs-filter's AutoCompleteChips serialises a multi-select into ONE query value:
|
|
269
540
|
// the selected values joined by "," (its `query` getter does `.map(value).join(',')`).
|
|
270
541
|
// So a 2+ selection arrives as the string "a,b", not an array — splitting on ","
|
|
@@ -279,4 +550,4 @@ function selectQueryValues(raw) {
|
|
|
279
550
|
}
|
|
280
551
|
return String(raw).split(',');
|
|
281
552
|
}
|
|
282
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWZpbHRlci1pdGVtcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtZmlsdGVyLWl0ZW1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBcUIsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFakUsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFNUMsT0FBTyxFQUFjLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0QyxPQUFPLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBR2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3RELE9BQU8sRUFDK0IsbUJBQW1CLEdBRXhELE1BQU0sK0JBQStCLENBQUM7QUFHdkMsMkVBQTJFO0FBQzNFLDRFQUE0RTtBQUM1RSx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLGVBQWUsQ0FBQyxLQUF1QztJQUNyRSxJQUFJLEtBQUssWUFBWSxJQUFJLEVBQUUsQ0FBQztRQUMxQixPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELHNFQUFzRTtJQUN0RSw4QkFBOEI7SUFDOUIsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDeEQsQ0FBQztBQUdELDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLGlFQUFpRTtBQUNqRSxFQUFFO0FBQ0YsZ0ZBQWdGO0FBQ2hGLGdGQUFnRjtBQUNoRiw2REFBNkQ7QUFDN0QsRUFBRTtBQUNGLDRFQUE0RTtBQUM1RSwyQ0FBMkM7QUFDM0MsTUFBTSxVQUFVLGNB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QUVELE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNoQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUZpbHRlckNvbmZpZ0l0ZW0sIEl0ZW1UeXBlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZmlsdGVyJztcblxuaW1wb3J0IHsgZm9ybWF0LCBwYXJzZUlTTyB9IGZyb20gJ2RhdGUtZm5zJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgc2hhcmVSZXBsYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuL2RhdGEvcmVwb3J0LmRhdGEnO1xuaW1wb3J0IHsgREFZX1NIT1JULCBmb3JtYXRMb2NhbERhdGUgfSBmcm9tICcuL2Zvcm1hdCc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LCBGaWx0ZXJHcm91cFZhbHVlLCBHUkFOVUxBUklUWV9PUFRJT05TLCBSZXBvcnQsIFJlcG9ydEZpbHRlckdyb3VwLCBSZXBvcnRGaWx0ZXJPcHRpb24sXG4gIFJlcG9ydExvY2FsZVRhZyxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuXG5cbi8vIEEgZGF0ZS1yYW5nZSBib3VuZGFyeSBhcyB0aGUgcGlja2VkIExPQ0FMIGNhbGVuZGFyIGRheSAobm8gdGltZSwgbm8gdHopLlxuLy8gRGF0ZS1yYW5nZSBmaWx0ZXJzIGFyZSBjYWxlbmRhci1kYXkgc2VtYW50aWNzLCBzbyB0aGUgYm91bmRhcnkgbXVzdCBjYXJyeVxuLy8gb25seSBZLU0tRCDigJQgbmV2ZXIgYSB0aW1lem9uZS1iZWFyaW5nIGluc3RhbnQgdGhlIGJhY2tlbmQgd291bGQgc2hpZnQuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZUJvdW5kU3RyaW5nKHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICByZXR1cm4gZm9ybWF0KHZhbHVlLCAneXl5eS1NTS1kZCcpO1xuICB9XG5cbiAgLy8gQXV0aG9yZWQvcmVsYXRpdmUgZGVmYXVsdHMgYXJyaXZlIGFzIHN0cmluZ3MgYWxyZWFkeSBpbiBZLU0tRCBmb3JtO1xuICAvLyBrZWVwIGp1c3QgdGhlIGRhdGUgcG9ydGlvbi5cbiAgcmV0dXJuIHZhbHVlID8gU3RyaW5nKHZhbHVlKS5zbGljZSgwLCAxMCkgOiB1bmRlZmluZWQ7XG59XG5cblxuLy8gQSBkYXRlLXJhbmdlIGJvdW5kYXJ5IGFzIGl0IHNob3VsZCBSRUFEIG9uIGEgY292ZXIgcGFnZSDigJQgdGhlIHNhbWUgY2FsZW5kYXJcbi8vIGRheSBkYXRlQm91bmRTdHJpbmcoKSBoYW5kcyB0aGUgc2VydmVyLCBzbyBhIHByaW50ZWQgcGVyaW9kIGNhbiBuZXZlciBuYW1lIGFcbi8vIGRpZmZlcmVudCBkYXkgdGhhbiB0aGUgbnVtYmVycyB1bmRlciBpdCB3ZXJlIGZpbHRlcmVkIGJ5LiBSZXR1cm5zIG51bGwgd2hlblxuLy8gdGhlcmUgaXMgbm8gYm91bmRhcnk7IHRoZSBjYWxsZXIgc3VwcGxpZXMgaXRzIG93biBwbGFjZWhvbGRlci5cbi8vXG4vLyBUaGUgcGFyc2UgaGFzIHRvIGJlIHBhcnNlSVNPLCBub3QgYG5ldyBEYXRlYDogYG5ldyBEYXRlKCcyMDI2LTA1LTAxJylgIGlzIFVUQ1xuLy8gbWlkbmlnaHQsIHNvIGZvcm1hdHRpbmcgaXQgYW55d2hlcmUgd2VzdCBvZiBVVEMgcHJpbnRzIEFwciAzMC4gcGFyc2VJU08gcmVhZHNcbi8vIGEgYmFyZSBZLU0tRCBhcyBMT0NBTCBtaWRuaWdodCwgd2hpY2ggbm8gb2Zmc2V0IGNhbiBzaGlmdC5cbi8vXG4vLyBUaGUgZGF5IGlzIHdyaXR0ZW4gaW4gdGhlIHJlcG9ydCdzIGxvY2FsZSwgYXMgaXRzIGRhdGUgY2VsbHMgYXJlOiAnSmFuIDUsXG4vLyAyMDI2JyBpbiBlbi1VUywgJzUgamFudi4gMjAyNicgaW4gZnItQ0EuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZUJvdW5kTGFiZWwodmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLCBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBib3VuZCA9IGRhdGVCb3VuZFN0cmluZyh2YWx1ZSk7XG5cbiAgaWYgKCFib3VuZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgZGF0ZSA9IHBhcnNlSVNPKGJvdW5kKTtcblxuICByZXR1cm4gTnVtYmVyLmlzTmFOKGRhdGUuZ2V0VGltZSgpKSA/IFN0cmluZyh2YWx1ZSkgOiBmb3JtYXRMb2NhbERhdGUoZGF0ZSwgbG9jYWxlLCBEQVlfU0hPUlQpO1xufVxuXG5cbi8vIEEgc3RvcmVkIHl5eXktTU0tZGQgYm91bmRhcnkgYXMgYSBsb2NhbCBEYXRlIGZvciBhIGRhdGUgcGlja2VyLCBvciBudWxsLlxuLy8gcGFyc2VJU08gcmVhZHMgYSBiYXJlIFktTS1EIGFzIExPQ0FMIG1pZG5pZ2h0LCBzbyB0aGUgcGlja2VyIHNob3dzIHRoZSBkYXlcbi8vIHRoYXQgd2FzIHN0b3JlZCwgd2hhdGV2ZXIgdGhlIGJyb3dzZXIncyB6b25lLlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVGcm9tQm91bmQodmFsdWU6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBEYXRlIHwgbnVsbCB7XG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRhdGUgPSBwYXJzZUlTTyh2YWx1ZS5zbGljZSgwLCAxMCkpO1xuXG4gIHJldHVybiBOdW1iZXIuaXNOYU4oZGF0ZS5nZXRUaW1lKCkpID8gbnVsbCA6IGRhdGU7XG59XG5cblxuLy8gQSBwaWNrZWQgRGF0ZSBhcyBhIHl5eXktTU0tZGQgYm91bmRhcnkgZm9yIHN0b3JhZ2UsIG9yIG51bGwuIFVzZXMgdGhlIGxvY2FsXG4vLyBjYWxlbmRhciBkYXkgKGZvcm1hdCwgbm90IHRvSVNPU3RyaW5nKSBzbyB0aGUgYm91bmRhcnkgaXMgdGhlIGRheSB0aGF0IHdhc1xuLy8gcGlja2VkLCByZWdhcmRsZXNzIG9mIHRoZSBicm93c2VyJ3Mgem9uZS5cbmV4cG9ydCBmdW5jdGlvbiBkYXRlVG9Cb3VuZCh2YWx1ZTogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCBudWxsIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgRGF0ZSAmJiAhTnVtYmVyLmlzTmFOKHZhbHVlLmdldFRpbWUoKSlcbiAgICA/IGZvcm1hdCh2YWx1ZSwgJ3l5eXktTU0tZGQnKVxuICAgIDogbnVsbDtcbn1cblxuXG4vLyBBIHJlbGF0aXZlIGRhdGUtcmFuZ2UgcHJlc2V0IGtleSBhcyBhIHNlbnRlbmNlLWNhc2UgbGFiZWwsIGRlcml2ZWQgZnJvbSB0aGVcbi8vIGNhbWVsQ2FzZSBrZXkgaXRzZWxmICgnbGFzdDEyTW9udGhzJyByZWFkcyAnTGFzdCAxMiBtb250aHMnLCAndGhpc1dlZWsnXG4vLyByZWFkcyAnVGhpcyB3ZWVrJyksIHNvIG5vIGxpc3Qgb2YgcHJlc2V0cyBpcyBtaXJyb3JlZCBoZXJlIGFuZCBhIGtleSB0aGVcbi8vIHNlcnZlciBhZGRzIGxhdGVyIHN0aWxsIHJlYWRzIHNlbnNpYmx5LlxuZXhwb3J0IGZ1bmN0aW9uIHJlbGF0aXZlTGFiZWwocmVsYXRpdmU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHdvcmRzID0gcmVsYXRpdmVcbiAgICAucmVwbGFjZSgvKFthLXpdKShbQS1aMC05XSkvZywgJyQxICQyJylcbiAgICAucmVwbGFjZSgvKFxcZCkoW0EtWl0pL2csICckMSAkMicpXG4gICAgLnRvTG93ZXJDYXNlKCk7XG5cbiAgcmV0dXJuIHdvcmRzLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZHMuc2xpY2UoMSk7XG59XG5cblxuLy8gTWFwcyBhIHJlcG9ydCBmaWx0ZXIgR1JPVVAgdG8gYW4gZnMtZmlsdGVyIGNvbmZpZyBpdGVtLCBhbmQgcmVhZHMgZnMtZmlsdGVyXG4vLyBxdWVyeSB2YWx1ZXMgYmFjayBpbnRvIHBlci1ncm91cCBGaWx0ZXJHcm91cFZhbHVlcy4gU2hhcmVkIGJ5IHRoZSByZXBvcnQtYmFyXG4vLyBmcy1maWx0ZXIgYW5kIHRoZSBwZXItY29tcG9uZW50IGZzLWZpbHRlciBzbyBib3RoIHJlbmRlciB0aHJvdWdoIHRoZSBzYW1lXG4vLyBsaWJyYXJ5IGFuZCB3cml0ZSBpbnRvIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSBpZGVudGljYWxseS4gSXRlbXMgYXJlIG5hbWVkXG4vLyBgZzxncm91cElkPmAgc28gdGhlIHF1ZXJ5IGtleXMgbWFwIHN0cmFpZ2h0IGJhY2sgdG8gdGhlIGdyb3VwLlxuXG4vLyBUaGUgcHJlZml4IG9mIGEgZ3JvdXAncyBpdGVtIG5hbWUsIGFuZCBvZiBpdHMga2V5IGluIHRoZSByZXBvcnQgVVJMLlxuZXhwb3J0IGNvbnN0IEdST1VQX1BBUkFNX1BSRUZJWCA9ICdnJztcblxuLy8gVGhlIHF1ZXJ5IGtleSBmcy1maWx0ZXIgdXNlcyBmb3IgYSBncm91cCdzIGl0ZW0ocyksIGFuZCB0aGUgcmVwb3J0IFVSTCdzIGtleVxuLy8gZm9yIHRoZSBncm91cCdzIHZhbHVlIChyZXBvcnQtdXJsLXN0YXRlLnRzKS4gT25lIG5hbWluZyBmb3IgYm90aC5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEl0ZW1OYW1lKGdyb3VwOiBQaWNrPFJlcG9ydEZpbHRlckdyb3VwLCAnaWQnPik6IHN0cmluZyB7XG4gIHJldHVybiBgJHtHUk9VUF9QQVJBTV9QUkVGSVh9JHtncm91cC5pZH1gO1xufVxuXG4vLyBUaGUgcXVlcnkga2V5IGZvciB0aGUgcmVwb3J0J3MgZ3JvdXAtYnkgY29udHJvbC4gRml4ZWQgcmF0aGVyIHRoYW4gZGVyaXZlZFxuLy8gZnJvbSBhbiBpZCBiZWNhdXNlIGEgcmVwb3J0IGhhcyBleGFjdGx5IG9uZSDigJQgYW5kIGl0IGlzIE5PVCBhIGZpbHRlciBncm91cCxcbi8vIHNvIGl0IGlzIHJlYWQgc3RyYWlnaHQgb2ZmIHRoZSBjaGFuZ2UgcXVlcnkgaW5zdGVhZCBvZiB0aHJvdWdoXG4vLyBncm91cFZhbHVlc0Zyb21RdWVyeS4gSXQgaXMgYWxzbyB0aGUgcmVwb3J0IFVSTCdzIGtleSBmb3IgdGhlIGdyYWluXG4vLyAocmVwb3J0LXVybC1zdGF0ZS50cykuIFRoZSBncmFpbiB0cmF2ZWxzIHRvIHRoZSBzZXJ2ZXIgYXMgdGhlIGRhdGFcbi8vIHJlcXVlc3QncyBgc3RhdGUuZnJlcXVlbmN5YC5cbmV4cG9ydCBjb25zdCBHUk9VUF9CWV9JVEVNID0gJ2dyb3VwQnknO1xuXG4vLyBBIHNlbGVjdCBncm91cCdzIGRpc3RpbmN0IG9wdGlvbnMsIGFzIHsgbmFtZSwgdmFsdWUgfSBwYWlycy4gVGhlIHNlcnZlciBzZW5kc1xuLy8geyB2YWx1ZSwgbGFiZWwgfTogdGhlIHZhbHVlIGlzIHdoYXQgdGhlIGZpbHRlciBtYXRjaGVzIG9uIChhbiBlbnRpdHkncyBzdGFibGVcbi8vIGlkKSBhbmQgdGhlIGxhYmVsIGlzIHdoYXQgdGhlIHZpZXdlciByZWFkcyDigJQgc28gYSByZW5hbWVkIGVudGl0eSBrZWVwcyBpdHMgaWRcbi8vIGFuZCBzaW1wbHkgc2hvd3MgaXRzIG5ldyBuYW1lIGhlcmUuIE9wdGlvbnMgY29tZSBmcm9tIHRoZSBmaXJzdCBtZW1iZXIgZmlsdGVyXG4vLyB0aGF0IGRlY2xhcmVzIHRoZW0g4oCUIG1lbWJlcnMgYXJlIHRoZSBzYW1lIGRhdGEgcG9pbnQsIHNvIGFueSBtZW1iZXIncyBsaXN0XG4vLyBzZXJ2ZXMgdGhlIGdyb3VwLiBUaGUgbGlzdCBpcyBmZXRjaGVkIG9uY2UgKHRoZSBzZXJ2ZXIgY2FwcyBpdCkgYW5kIHJlcGxheWVkXG4vLyAoc2hhcmVSZXBsYXkpLCBzbyByZXBlYXRlZCByZWFkcyBuZXZlciByZWZldGNoLiBTaGFyZWQgYnkgdGhlIHJlcG9ydC1iYXJcbi8vIHNlbGVjdCBjb250cm9sIGFuZCB0aGUgcmVwb3J0LXNldHRpbmdzIGRlZmF1bHQgcGlja2VyIHNvIHRoZSB0d28gbmV2ZXIgZHJpZnQuXG4vLyBSZXR1cm5zIGFuIGVtcHR5IGxpc3Qgd2hlbiBubyBtZW1iZXIgcHJvdmlkZXMgb3B0aW9ucy5cbmV4cG9ydCBmdW5jdGlvbiBsb2FkR3JvdXBPcHRpb25zKFxuICBncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsXG4gIHJlcG9ydERhdGE6IFJlcG9ydERhdGEsXG4gIHJlcG9ydElkOiBudW1iZXIsXG4pOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+IHtcbiAgY29uc3Qgb3B0aW9uRmlsdGVyID0gKGdyb3VwLmZpbHRlcnMgPz8gW10pLmZpbmQoKG1lbWJlcikgPT4gbWVtYmVyLmhhc09wdGlvbnMpO1xuICBpZiAoIW9wdGlvbkZpbHRlcikge1xuICAgIHJldHVybiBvZihbXSk7XG4gIH1cblxuICByZXR1cm4gcmVwb3J0RGF0YS5maWx0ZXJPcHRpb25zKHJlcG9ydElkLCBvcHRpb25GaWx0ZXIuaWQpXG4gICAgLnBpcGUoXG4gICAgICBtYXAoKG9wdGlvbnM6IFJlcG9ydEZpbHRlck9wdGlvbltdKSA9PiAob3B0aW9ucyA/PyBbXSlcbiAgICAgICAgLm1hcCgob3B0aW9uKSA9PiAoeyBuYW1lOiBvcHRpb24ubGFiZWwsIHZhbHVlOiBvcHRpb24udmFsdWUgfSkpKSxcbiAgICAgIHNoYXJlUmVwbGF5KHsgYnVmZmVyU2l6ZTogMSwgcmVmQ291bnQ6IGZhbHNlIH0pLFxuICAgICk7XG59XG5cbi8vIFN0b3JlZCBmaWx0ZXIgdmFsdWVzIChpZHMpIHBhaXJlZCBiYWNrIHdpdGggdGhlIGxhYmVscyB0byBzaG93IGZvciB0aGVtLlxuLy8gQSBzYXZlZCBkZWZhdWx0IGhvbGRzIG9ubHkgdmFsdWVzLCBzbyB0aGUgbmFtZXMgaGF2ZSB0byBiZSByZWFkIGJhY2sgb2ZmIHRoZVxuLy8gb3B0aW9uIGxpc3Qg4oCUIHRoYXQgaW5kaXJlY3Rpb24gaXMgZXhhY3RseSB3aGF0IHN1cnZpdmVzIGEgcmVuYW1lLiBBIHZhbHVlIHdpdGhcbi8vIG5vIG1hdGNoaW5nIG9wdGlvbiAoaXRzIGVudGl0eSB3YXMgZGVsZXRlZCwgc28gaXQgaXMgbm8gbG9uZ2VyIGxpc3RlZCkgZmFsbHNcbi8vIGJhY2sgdG8gc2hvd2luZyB0aGUgcmF3IHZhbHVlIHJhdGhlciB0aGFuIGRyb3BwaW5nIHRoZSBjaGlwLCB3aGljaCB3b3VsZFxuLy8gc2lsZW50bHkgd2lkZW4gdGhlIGZpbHRlci5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlT3B0aW9uVmFsdWVzKFxuICBvcHRpb25zJDogT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPixcbiAgdmFsdWVzOiB1bmtub3duW10sXG4pOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+IHtcbiAgcmV0dXJuIG9wdGlvbnMkLnBpcGUobWFwKChvcHRpb25zKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbiA9IG9wdGlvbnMuZmluZCgoY2FuZGlkYXRlKSA9PiBTdHJpbmcoY2FuZGlkYXRlLnZhbHVlKSA9PT0gU3RyaW5nKHZhbHVlKSk7XG5cbiAgICByZXR1cm4geyBuYW1lOiBvcHRpb24/Lm5hbWUgPz8gU3RyaW5nKHZhbHVlKSwgdmFsdWUgfTtcbiAgfSkpKTtcbn1cblxuLy8gQ2FzZS1pbnNlbnNpdGl2ZSBuYW1lIGZpbHRlciBhcHBsaWVkIHRvIGEgbG9hZGVkIG9wdGlvbiBsaXN0IOKAlCB0aGUgdHlwZWRcbi8vIGtleXdvcmQgaGFzIHRvIGJlIG1hdGNoZWQgaGVyZSBiZWNhdXNlIGZzLWF1dG9jb21wbGV0ZSByZW5kZXJzIHdoYXQgd2UgcmV0dXJuXG4vLyB2ZXJiYXRpbS5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaE9wdGlvbnMoXG4gIG9wdGlvbnMkOiBPYnNlcnZhYmxlPHsgbmFtZTogc3RyaW5nOyB2YWx1ZTogdW5rbm93biB9W10+LFxuICBrZXl3b3JkPzogc3RyaW5nLFxuKTogT2JzZXJ2YWJsZTx7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHVua25vd24gfVtdPiB7XG4gIGNvbnN0IHRlcm0gPSAoa2V5d29yZCA/PyAnJykudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgcmV0dXJuIG9wdGlvbnMkLnBpcGUobWFwKChvcHRpb25zKSA9PiB0ZXJtXG4gICAgPyBvcHRpb25zLmZpbHRlcigob3B0aW9uKSA9PiBvcHRpb24ubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pKVxuICAgIDogb3B0aW9ucykpO1xufVxuXG4vLyBCdWlsZCB0aGUgZnMtZmlsdGVyIGNvbmZpZyBpdGVtIGZvciBhIGdyb3VwLCBzZWVkaW5nIGl0cyBkZWZhdWx0IGZyb20gdGhlXG4vLyBjdXJyZW50IHNlc3Npb24gdmFsdWUgc28gYXV0aG9yZWQvcmVsYXRpdmUgZGVmYXVsdHMgc2hvdyBzZWxlY3RlZCBvbiBvcGVuLlxuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlckl0ZW1Gb3JHcm91cChcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLFxuICByZXBvcnREYXRhOiBSZXBvcnREYXRhLFxuICByZXBvcnRJZDogbnVtYmVyLFxuICBpbml0aWFsPzogRmlsdGVyR3JvdXBWYWx1ZSxcbik6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXApO1xuICBjb25zdCBsYWJlbCA9IGdyb3VwLmxhYmVsIHx8IGdyb3VwLmZpbHRlcnM/LlswXT8uZmlsdGVyQ29sdW1uIHx8ICcnO1xuXG4gIHN3aXRjaCAoZ3JvdXAudHlwZSkge1xuICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lLFxuICAgICAgICB0eXBlOiBJdGVtVHlwZS5EYXRlUmFuZ2UsXG4gICAgICAgIGxhYmVsOiB7IGZyb206IGAke2xhYmVsfSBGcm9tYCwgdG86IGAke2xhYmVsfSBUb2AgfSxcbiAgICAgICAgZGVmYXVsdDogKGluaXRpYWw/LnN0YXJ0IHx8IGluaXRpYWw/LmVuZClcbiAgICAgICAgICA/IHsgZnJvbTogaW5pdGlhbC5zdGFydCA/PyB1bmRlZmluZWQsIHRvOiBpbml0aWFsLmVuZCA/PyB1bmRlZmluZWQgfVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfTtcblxuICAgIGNhc2UgJ3NlbGVjdCc6IHtcbiAgICAgIC8vIE9uZSBzaGFyZWQsIHJlcGxheWVkIG9wdGlvbiBzdHJlYW0gc28gdHlwaW5nIG5ldmVyIHJlZmV0Y2hlcy5cbiAgICAgIGNvbnN0IG9wdGlvbnMkID0gbG9hZEdyb3VwT3B0aW9ucyhncm91cCwgcmVwb3J0RGF0YSwgcmVwb3J0SWQpO1xuICAgICAgY29uc3QgdmFsdWVzID0gaW5pdGlhbD8udmFsdWVzO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lLFxuICAgICAgICB0eXBlOiBJdGVtVHlwZS5BdXRvQ29tcGxldGVDaGlwcyxcbiAgICAgICAgbGFiZWwsXG4gICAgICAgIGZldGNoT25Gb2N1czogdHJ1ZSxcbiAgICAgICAgdmFsdWVzOiAoa2V5d29yZD86IHN0cmluZykgPT4gbWF0Y2hPcHRpb25zKG9wdGlvbnMkLCBrZXl3b3JkKSxcbiAgICAgICAgLy8gU3RvcmVkIHZhbHVlcyBhcmUgaWRzLCBzbyB0aGUgY2hpcHMgY2FuIG9ubHkgYmUgbmFtZWQgb25jZSB0aGUgb3B0aW9uXG4gICAgICAgIC8vIGxpc3QgaGFzIGxvYWRlZCDigJQgaGVuY2UgdGhlIG9ic2VydmFibGUgZm9ybSBvZiBgZGVmYXVsdGAuXG4gICAgICAgIGRlZmF1bHQ6IHZhbHVlcz8ubGVuZ3RoXG4gICAgICAgICAgPyAoKSA9PiByZXNvbHZlT3B0aW9uVmFsdWVzKG9wdGlvbnMkLCB2YWx1ZXMpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNhc2UgJ2tleXdvcmQnOlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lLFxuICAgICAgICB0eXBlOiBJdGVtVHlwZS5LZXl3b3JkLFxuICAgICAgICBsYWJlbCxcbiAgICAgICAgZGVmYXVsdDogaW5pdGlhbD8udmFsdWUsXG4gICAgICB9O1xuICB9XG59XG5cbi8vIFRoZSBxdWVyeSBrZXkgb2YgYSBsaXN0J3Mgc2VhcmNoIGJveCBpbiBpdHMgY29tcG9uZW50IGhlYWRlci4gRml4ZWQgcmF0aGVyXG4vLyB0aGFuIGRlcml2ZWQgZnJvbSBhbiBpZCBiZWNhdXNlIGEgaGVhZGVyIGhvbGRzIGF0IG1vc3Qgb25lLCBhbmQgaXQgaXMgTk9UIGFcbi8vIGZpbHRlciBncm91cDogaXRzIHRleHQgbmFycm93cyB0aGF0IGxpc3QgYWxvbmUsIHNvIGl0IGlzIHJlYWQgc3RyYWlnaHQgb2ZmXG4vLyB0aGUgY2hhbmdlIHF1ZXJ5IGFuZCB0cmF2ZWxzIGFzIHRoZSBsaXN0J3Mgb3duIGBzdGF0ZS5zZWFyY2hgLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX0lURU0gPSAnbGlzdFNlYXJjaCc7XG5cbi8vIFRoZSBsb25nZXN0IHNlYXJjaCB0aGUgc2VydmVyIGFwcGxpZXMgKFJlcG9ydFF1ZXJ5UnVubmVyOjpNQVhfU0VBUkNIX0xFTkdUSCkuXG4vLyBUaGUgdmlld2VyIGN1dHMgdGhlIHRleHQgdG8gaXQgdG9vLCBzbyB0aGUgVVJMLCB0aGUgcmVxdWVzdCBhbmQgdGhlIGV4cG9ydFxuLy8gdGl0bGUgYWxsIGNhcnJ5IHRoZSB0ZXh0IHRoYXQgd2FzIGFjdHVhbGx5IHNlYXJjaGVkLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX01BWF9MRU5HVEggPSAxMDA7XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIGEgbGlzdCdzIHNlYXJjaCBib3gsIHNlZWRlZCB3aXRoIHRoZSB0ZXh0IHRoZVxuLy8gdmlld2VyIGxhc3Qgc2VhcmNoZWQuIGZzLWZpbHRlciBzaG93cyBvbmUgc2VhcmNoIGJveCBwZXIgYmFyIChpdHMgbGFzdFxuLy8ga2V5d29yZCBpdGVtKSwgc28gdGhlIGNhbGxlciBhZGRzIHRoaXMgb25seSB0byBhIGhlYWRlciB3aXRoIG5vIGtleXdvcmRcbi8vIGdyb3VwIG9mIGl0cyBvd24uXG5leHBvcnQgZnVuY3Rpb24gbGlzdFNlYXJjaEl0ZW0odmFsdWU6IHN0cmluZyB8IG51bGwpOiBJRmlsdGVyQ29uZmlnSXRlbSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogSXRlbVR5cGUuS2V5d29yZCxcbiAgICBuYW1lOiBMSVNUX1NFQVJDSF9JVEVNLFxuICAgIGxhYmVsOiAnU2VhcmNoJyxcbiAgICBkZWZhdWx0OiB2YWx1ZSA/PyB1bmRlZmluZWQsXG4gIH07XG59XG5cbi8vIFdoZXRoZXIgdGhlIHJlcG9ydCBoYXMgYSBjaGFydCB0aGUgZ3JvdXAtYnkgY29udHJvbCBjYW4gcmUtYnVja2V0LiBBIHRpbWVcbi8vIHgtYXhpcyBpcyB0aGUgd2hvbGUgcXVhbGlmaWNhdGlvbjogdGhlIGNvbnRyb2wgY2hhbmdlcyB0aGUgZ3JhaW4gb2YgdGhhdFxuLy8gYXhpcywgYW5kIGEgY2F0ZWdvcnkgYXhpcyBoYXMgbm8gZ3JhaW4gdG8gY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGhhc1RpbWVTZXJpZXNDaGFydChyZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIChyZXBvcnQ/LnBhZ2VzID8/IFtdKS5zb21lKChwYWdlKSA9PiAocGFnZS5jb21wb25lbnRzID8/IFtdKS5zb21lKChjb21wb25lbnQpID0+XG4gICAgY29tcG9uZW50LnR5cGUgPT09ICdjaGFydCcgJiYgY29tcG9uZW50LmNvbmZpZz8ueEF4aXM/LmtpbmQgPT09ICd0aW1lJykpO1xufVxuXG4vLyBUaGUgZ3JhaW5zIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sIG9mZmVycywgbmFtZWQgZm9yIHRoZSB2aWV3ZXIuIFdISUNIXG4vLyBvZiB0aGVtIGNvbWVzIGZyb20gdGhlIHJlcG9ydDsgaG93IHRoZXkgcmVhZCBjb21lcyBmcm9tIEdSQU5VTEFSSVRZX09QVElPTlMuXG4vLyBBbiBlbXB0eSBzdG9yZWQgbGlzdCBtZWFucyBldmVyeSBncmFpbiDigJQgdGhlIHNhbWUgcnVsZSB0aGUgYmFja2VuZCBhcHBsaWVzLlxuZnVuY3Rpb24gZ3JvdXBCeU9wdGlvbnMocmVwb3J0OiBSZXBvcnQpOiB7IHZhbHVlOiBDaGFydEdyYW51bGFyaXR5OyBuYW1lOiBzdHJpbmcgfVtdIHtcbiAgY29uc3QgZ3JhbnVsYXJpdGllcyA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk/LmdyYW51bGFyaXRpZXMgPz8gW107XG5cbiAgcmV0dXJuIGdyYW51bGFyaXRpZXMubGVuZ3RoXG4gICAgPyBHUkFOVUxBUklUWV9PUFRJT05TLmZpbHRlcigob3B0aW9uKSA9PiBncmFudWxhcml0aWVzLmluY2x1ZGVzKG9wdGlvbi52YWx1ZSkpXG4gICAgOiBHUkFOVUxBUklUWV9PUFRJT05TO1xufVxuXG4vLyBXaGV0aGVyIGEgZ3JhaW4gaXMgb25lIHRoZSByZXBvcnQncyBjb250cm9sIHN0aWxsIG9mZmVycy4gQSBncmFpbiBpdCBkb2Vzbid0XG4vLyBjYW5ub3Qgc3RheSBpbiBlZmZlY3Q6IHRoZSBhZ2VudCBjYW4gbmFycm93IHRoZSBsaXN0IGF0IGFueSB0aW1lLCBhbmQgYSBjaGFydFxuLy8gbGVmdCBidWNrZXRpbmcgYXQgYSBkcm9wcGVkIGdyYWluIGlzIG9uZSB0aGUgdmlld2VyIGNhbiBuZWl0aGVyIHNlZSBub3IgY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGlzR3JhbnVsYXJpdHlPZmZlcmVkKHJlcG9ydDogUmVwb3J0LCBncmFudWxhcml0eTogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuICFncmFudWxhcml0eSB8fCBncm91cEJ5T3B0aW9ucyhyZXBvcnQpLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlID09PSBncmFudWxhcml0eSk7XG59XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sLCBvciBudWxsIHdoZW4gdGhlXG4vLyByZXBvcnQgaGFzIG5vbmUgdG8gc2hvdy5cbi8vXG4vLyBJdCBsZWFkcyB0aGUgc2FtZSBiYXIgdGhlIGZpbHRlcnMgcmVuZGVyIGluLCBidXQgaXQgaXMgTk9UIG9uZTogYSBmaWx0ZXJcbi8vIG5hcnJvd3MgV0hJQ0ggcm93cyBhcmUgY291bnRlZCwgdGhpcyBjaGFuZ2VzIGhvdyB0aGUgc3Vydml2aW5nIHJvd3MgYXJlXG4vLyBCVUNLRVRFRCDigJQgYW5kIGl0IGNvbWVzIGZpcnN0IGJlY2F1c2UgdGhlIGdyYWluIGlzIHdoYXQgYSB2aWV3ZXIgc2V0dGxlc1xuLy8gYmVmb3JlIGRlY2lkaW5nIHdoaWNoIHJvd3MgdGhleSB3YW50LlxuLy8gUGlja2luZyBhIGdyYWluIHNldHMgYSBzZXNzaW9uLXdpZGUgb3ZlcnJpZGUgdGhhdCByaWRlcyBhbG9uZyBpbiBlYWNoIGNoYXJ0J3Ncbi8vIGRhdGEgcmVxdWVzdCwgc28gdGhlIGNoYXJ0cyB0aGVtc2VsdmVzIGFyZSBuZXZlciByZXdyaXR0ZW4uXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBCeUZpbHRlckl0ZW0oXG4gIHJlcG9ydDogUmVwb3J0LFxuICBpbml0aWFsPzogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwsXG4pOiBJRmlsdGVyQ29uZmlnSXRlbSB8IG51bGwge1xuICBjb25zdCBncm91cEJ5ID0gcmVwb3J0LmNvbmZpZz8uZ3JvdXBCeTtcblxuICAvLyBPbmx5IGFuIEVYUExJQ0lUIGZhbHNlIGhpZGVzIHRoZSBjb250cm9sLiBBbiBhYnNlbnQgYmxvY2sgbWVhbnMgYSByZXBvcnRcbiAgLy8gc2VydmVkIGJ5IGEgYnVpbGQgdGhhdCBwcmVkYXRlcyB0aGUgY29udHJvbCBiZWluZyBzdG9yZWQsIGFuZCBldmVyeSBvbmUgb2ZcbiAgLy8gdGhvc2UgaGFkIG9uZSDigJQgdGhlIGJhY2tlbmQgcmVzb2x2ZXMgaXQgdGhlIHNhbWUgd2F5IChSZXBvcnRHcm91cEJ5KS5cbiAgaWYgKGdyb3VwQnk/LmVuYWJsZWQgPT09IGZhbHNlIHx8ICFoYXNUaW1lU2VyaWVzQ2hhcnQocmVwb3J0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdmFsdWVzID0gZ3JvdXBCeU9wdGlvbnMocmVwb3J0KTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6IEdST1VQX0JZX0lURU0sXG4gICAgdHlwZTogSXRlbVR5cGUuU2VsZWN0LFxuICAgIGxhYmVsOiBncm91cEJ5Py5sYWJlbCB8fCAnR3JvdXAgQnknLFxuICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICB2YWx1ZXM6ICgpID0+IHZhbHVlcyxcbiAgICBkZWZhdWx0OiBpc0dyYW51bGFyaXR5T2ZmZXJlZChyZXBvcnQsIGluaXRpYWwgPz8gbnVsbCkgPyAoaW5pdGlhbCA/PyB1bmRlZmluZWQpIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vLyBUaGUgZ3JvdXAtYnkgY29udHJvbCdzIGNvbnRyaWJ1dGlvbiB0byB0aGUgdG9vbGJhcidzIGZzLWZpbHRlciBrZXkuIGZzLWZpbHRlclxuLy8gcmVhZHMgaXRzIGNvbmZpZyBvbmNlIGF0IGluaXQsIGFuZCB0aGUgYWdlbnQgY2FuIGNoYW5nZSB0aGUgY29udHJvbCdzIGxhYmVsXG4vLyBvciB0aGUgZ3JhaW5zIGl0IG9mZmVycyDigJQgd2l0aG91dCB0aG9zZSBpbiB0aGUga2V5IHRoZSBiYXIga2VlcHMgcmVuZGVyaW5nXG4vLyB0aGUgY29udHJvbCBpdCB3YXMgY3JlYXRlZCB3aXRoIHVudGlsIGEgZnVsbCBwYWdlIHJlbG9hZC5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEJ5U2lnbmF0dXJlKHJlcG9ydDogUmVwb3J0IHwgbnVsbCk6IHN0cmluZyB7XG4gIGlmICghcmVwb3J0IHx8ICFncm91cEJ5RmlsdGVySXRlbShyZXBvcnQpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3QgZ3JvdXBCeSA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk7XG5cbiAgcmV0dXJuIFsnZ3JvdXBCeScsIGdyb3VwQnk/LmxhYmVsID8/ICcnLCAoZ3JvdXBCeT8uZ3JhbnVsYXJpdGllcyA/PyBbXSkuam9pbignLCcpXS5qb2luKCc6Jyk7XG59XG5cbi8vIFJlYWQgYW4gZnMtZmlsdGVyIGNoYW5nZSBxdWVyeSBpbnRvIHBlci1ncm91cCB2YWx1ZXMuIFJldHVybnMgb25lIGVudHJ5IHBlclxuLy8gZ3JvdXAgd2l0aCB0aGUgdmFsdWUgdG8gc3RvcmUgKG9yIG51bGwgdG8gY2xlYXIpIOKAlCBjYWxsZXJzIGZlZWQgdGhlc2UgdG9cbi8vIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZS5zZXRWYWx1ZS5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFZhbHVlc0Zyb21RdWVyeShcbiAgcXVlcnk6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gIGdyb3VwczogUmVwb3J0RmlsdGVyR3JvdXBbXSxcbik6IHsgZ3JvdXBJZDogbnVtYmVyOyB2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwgfVtdIHtcbiAgcmV0dXJuIGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXApO1xuXG4gICAgaWYgKGdyb3VwLnR5cGUgPT09ICdkYXRlUmFuZ2UnKSB7XG4gICAgICBjb25zdCBzdGFydCA9IHF1ZXJ5W2Ake25hbWV9RnJvbWBdO1xuICAgICAgY29uc3QgZW5kID0gcXVlcnlbYCR7bmFtZX1Ub2BdO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBncm91cElkOiBncm91cC5pZCxcbiAgICAgICAgdmFsdWU6IChzdGFydCB8fCBlbmQpID8geyBzdGFydDogc3RhcnQgfHwgbnVsbCwgZW5kOiBlbmQgfHwgbnVsbCB9IDogbnVsbCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGdyb3VwLnR5cGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBzZWxlY3RRdWVyeVZhbHVlcyhxdWVyeVtuYW1lXSk7XG5cbiAgICAgIHJldHVybiB7IGdyb3VwSWQ6IGdyb3VwLmlkLCB2YWx1ZTogdmFsdWVzLmxlbmd0aCA/IHsgdmFsdWVzIH0gOiBudWxsIH07XG4gICAgfVxuXG4gICAgY29uc3Qga2V5d29yZCA9IFN0cmluZyhxdWVyeVtuYW1lXSA/PyAnJykudHJpbSgpO1xuXG4gICAgcmV0dXJuIHsgZ3JvdXBJZDogZ3JvdXAuaWQsIHZhbHVlOiBrZXl3b3JkID8geyB2YWx1ZToga2V5d29yZCB9IDogbnVsbCB9O1xuICB9KTtcbn1cblxuLy8gZnMtZmlsdGVyJ3MgQXV0b0NvbXBsZXRlQ2hpcHMgc2VyaWFsaXNlcyBhIG11bHRpLXNlbGVjdCBpbnRvIE9ORSBxdWVyeSB2YWx1ZTpcbi8vIHRoZSBzZWxlY3RlZCB2YWx1ZXMgam9pbmVkIGJ5IFwiLFwiIChpdHMgYHF1ZXJ5YCBnZXR0ZXIgZG9lcyBgLm1hcCh2YWx1ZSkuam9pbignLCcpYCkuXG4vLyBTbyBhIDIrIHNlbGVjdGlvbiBhcnJpdmVzIGFzIHRoZSBzdHJpbmcgXCJhLGJcIiwgbm90IGFuIGFycmF5IOKAlCBzcGxpdHRpbmcgb24gXCIsXCJcbi8vIHJldmVyc2VzIHRoYXQgZmFpdGhmdWxseS4gV2l0aG91dCB0aGlzLCBhIG11bHRpLXNlbGVjdCB3YXMgc2VudCBhcyB0aGUgc2luZ2xlXG4vLyB2YWx1ZSBbXCJhLGJcIl0sIHByb2R1Y2luZyBgY29sIElOICgnYSxiJylgIHNlcnZlci1zaWRlLCB3aGljaCBtYXRjaGVzIG5vdGhpbmcuXG5mdW5jdGlvbiBzZWxlY3RRdWVyeVZhbHVlcyhyYXc6IHVua25vd24pOiB1bmtub3duW10ge1xuICBpZiAoQXJyYXkuaXNBcnJheShyYXcpKSB7XG4gICAgcmV0dXJuIHJhdztcbiAgfVxuXG4gIGlmIChyYXcgPT09IG51bGwgfHwgcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBTdHJpbmcocmF3KS5zcGxpdCgnLCcpO1xufVxuIl19
|
|
553
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWZpbHRlci1pdGVtcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtZmlsdGVyLWl0ZW1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBcUIsUUFBUSxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRWpGLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRTVDLE9BQU8sRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdsRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLG9CQUFvQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBSTVFLE9BQU8sRUFDK0IsbUJBQW1CLEdBRXhELE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBSXpELDJFQUEyRTtBQUMzRSw0RUFBNEU7QUFDNUUseUVBQXlFO0FBQ3pFLE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBdUM7SUFDckUsSUFBSSxLQUFLLFlBQVksSUFBSSxFQUFFLENBQUM7UUFDMUIsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxzRUFBc0U7SUFDdEUsOEJBQThCO0lBQzlCLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3hELENBQUM7QUFHRCw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4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O0FBQ2pGLGdGQUFnRjtBQUNoRixnRkFBZ0Y7QUFDaEYsU0FBUyxpQkFBaUIsQ0FBQyxHQUFZO0lBQ3JDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVELElBQUksR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNwRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDaEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElGaWx0ZXJDb25maWdJdGVtLCBJdGVtVHlwZSwgZ2V0RXhjbHVkZU5hbWUgfSBmcm9tICdAZmlyZXN0aXRjaC9maWx0ZXInO1xuXG5pbXBvcnQgeyBmb3JtYXQsIHBhcnNlSVNPIH0gZnJvbSAnZGF0ZS1mbnMnO1xuXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBzaGFyZVJlcGxheSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBmaWx0ZXJMaW5lVGV4dCwgbWF0Y2hMaW5lVGV4dCB9IGZyb20gJy4vZXhwb3J0L3JlcG9ydC1maWx0ZXItbGluZXMnO1xuaW1wb3J0IHsgREFZX1NIT1JULCBmb3JtYXRMb2NhbERhdGUsIHJlc29sdmVGb3JtYXRDb250ZXh0IH0gZnJvbSAnLi9mb3JtYXQnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyTWF0Y2ggfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1tYXRjaC50eXBlJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlck9wdGlvblBhaXIgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb24tcGFpci5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0Vmlld2VyRmVhdHVyZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdmlld2VyLWZlYXR1cmUudHlwZSc7XG5pbXBvcnQge1xuICBDaGFydEdyYW51bGFyaXR5LCBGaWx0ZXJHcm91cFZhbHVlLCBHUkFOVUxBUklUWV9PUFRJT05TLCBSZXBvcnQsIFJlcG9ydEZpbHRlckdyb3VwLCBSZXBvcnRGaWx0ZXJMZXZlbCxcbiAgUmVwb3J0RmlsdGVyT3B0aW9uLCBSZXBvcnRGaWx0ZXJUeXBlLCBSZXBvcnRMb2NhbGVUYWcsXG59IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IG9mZmVyc0V4Y2x1ZGUgfSBmcm9tICcuL3JlcG9ydC12aWV3ZXItZmVhdHVyZXMnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL3JlcG9ydC1maWx0ZXItb3B0aW9ucy5zZXJ2aWNlJztcblxuXG4vLyBBIGRhdGUtcmFuZ2UgYm91bmRhcnkgYXMgdGhlIHBpY2tlZCBMT0NBTCBjYWxlbmRhciBkYXkgKG5vIHRpbWUsIG5vIHR6KS5cbi8vIERhdGUtcmFuZ2UgZmlsdGVycyBhcmUgY2FsZW5kYXItZGF5IHNlbWFudGljcywgc28gdGhlIGJvdW5kYXJ5IG11c3QgY2Fycnlcbi8vIG9ubHkgWS1NLUQg4oCUIG5ldmVyIGEgdGltZXpvbmUtYmVhcmluZyBpbnN0YW50IHRoZSBiYWNrZW5kIHdvdWxkIHNoaWZ0LlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVCb3VuZFN0cmluZyh2YWx1ZTogRGF0ZSB8IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIGZvcm1hdCh2YWx1ZSwgJ3l5eXktTU0tZGQnKTtcbiAgfVxuXG4gIC8vIEF1dGhvcmVkL3JlbGF0aXZlIGRlZmF1bHRzIGFycml2ZSBhcyBzdHJpbmdzIGFscmVhZHkgaW4gWS1NLUQgZm9ybTtcbiAgLy8ga2VlcCBqdXN0IHRoZSBkYXRlIHBvcnRpb24uXG4gIHJldHVybiB2YWx1ZSA/IFN0cmluZyh2YWx1ZSkuc2xpY2UoMCwgMTApIDogdW5kZWZpbmVkO1xufVxuXG5cbi8vIEEgZGF0ZS1yYW5nZSBib3VuZGFyeSBhcyBpdCBzaG91bGQgUkVBRCBvbiBhIGNvdmVyIHBhZ2Ug4oCUIHRoZSBzYW1lIGNhbGVuZGFyXG4vLyBkYXkgZGF0ZUJvdW5kU3RyaW5nKCkgaGFuZHMgdGhlIHNlcnZlciwgc28gYSBwcmludGVkIHBlcmlvZCBjYW4gbmV2ZXIgbmFtZSBhXG4vLyBkaWZmZXJlbnQgZGF5IHRoYW4gdGhlIG51bWJlcnMgdW5kZXIgaXQgd2VyZSBmaWx0ZXJlZCBieS4gUmV0dXJucyBudWxsIHdoZW5cbi8vIHRoZXJlIGlzIG5vIGJvdW5kYXJ5OyB0aGUgY2FsbGVyIHN1cHBsaWVzIGl0cyBvd24gcGxhY2Vob2xkZXIuXG4vL1xuLy8gVGhlIHBhcnNlIGhhcyB0byBiZSBwYXJzZUlTTywgbm90IGBuZXcgRGF0ZWA6IGBuZXcgRGF0ZSgnMjAyNi0wNS0wMScpYCBpcyBVVENcbi8vIG1pZG5pZ2h0LCBzbyBmb3JtYXR0aW5nIGl0IGFueXdoZXJlIHdlc3Qgb2YgVVRDIHByaW50cyBBcHIgMzAuIHBhcnNlSVNPIHJlYWRzXG4vLyBhIGJhcmUgWS1NLUQgYXMgTE9DQUwgbWlkbmlnaHQsIHdoaWNoIG5vIG9mZnNldCBjYW4gc2hpZnQuXG4vL1xuLy8gVGhlIGRheSBpcyB3cml0dGVuIGluIHRoZSByZXBvcnQncyBsb2NhbGUsIGFzIGl0cyBkYXRlIGNlbGxzIGFyZTogJ0phbiA1LFxuLy8gMjAyNicgaW4gZW4tVVMsICc1IGphbnYuIDIwMjYnIGluIGZyLUNBLlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVCb3VuZExhYmVsKHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCwgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcpOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgYm91bmQgPSBkYXRlQm91bmRTdHJpbmcodmFsdWUpO1xuXG4gIGlmICghYm91bmQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRhdGUgPSBwYXJzZUlTTyhib3VuZCk7XG5cbiAgcmV0dXJuIE51bWJlci5pc05hTihkYXRlLmdldFRpbWUoKSkgPyBTdHJpbmcodmFsdWUpIDogZm9ybWF0TG9jYWxEYXRlKGRhdGUsIGxvY2FsZSwgREFZX1NIT1JUKTtcbn1cblxuXG4vLyBBIHN0b3JlZCB5eXl5LU1NLWRkIGJvdW5kYXJ5IGFzIGEgbG9jYWwgRGF0ZSBmb3IgYSBkYXRlIHBpY2tlciwgb3IgbnVsbC5cbi8vIHBhcnNlSVNPIHJlYWRzIGEgYmFyZSBZLU0tRCBhcyBMT0NBTCBtaWRuaWdodCwgc28gdGhlIHBpY2tlciBzaG93cyB0aGUgZGF5XG4vLyB0aGF0IHdhcyBzdG9yZWQsIHdoYXRldmVyIHRoZSBicm93c2VyJ3Mgem9uZS5cbmV4cG9ydCBmdW5jdGlvbiBkYXRlRnJvbUJvdW5kKHZhbHVlOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogRGF0ZSB8IG51bGwge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBkYXRlID0gcGFyc2VJU08odmFsdWUuc2xpY2UoMCwgMTApKTtcblxuICByZXR1cm4gTnVtYmVyLmlzTmFOKGRhdGUuZ2V0VGltZSgpKSA/IG51bGwgOiBkYXRlO1xufVxuXG5cbi8vIEEgcGlja2VkIERhdGUgYXMgYSB5eXl5LU1NLWRkIGJvdW5kYXJ5IGZvciBzdG9yYWdlLCBvciBudWxsLiBVc2VzIHRoZSBsb2NhbFxuLy8gY2FsZW5kYXIgZGF5IChmb3JtYXQsIG5vdCB0b0lTT1N0cmluZykgc28gdGhlIGJvdW5kYXJ5IGlzIHRoZSBkYXkgdGhhdCB3YXNcbi8vIHBpY2tlZCwgcmVnYXJkbGVzcyBvZiB0aGUgYnJvd3NlcidzIHpvbmUuXG5leHBvcnQgZnVuY3Rpb24gZGF0ZVRvQm91bmQodmFsdWU6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgbnVsbCB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgIU51bWJlci5pc05hTih2YWx1ZS5nZXRUaW1lKCkpXG4gICAgPyBmb3JtYXQodmFsdWUsICd5eXl5LU1NLWRkJylcbiAgICA6IG51bGw7XG59XG5cblxuLy8gQSByZWxhdGl2ZSBkYXRlLXJhbmdlIHByZXNldCBrZXkgYXMgYSBzZW50ZW5jZS1jYXNlIGxhYmVsLCBkZXJpdmVkIGZyb20gdGhlXG4vLyBjYW1lbENhc2Uga2V5IGl0c2VsZiAoJ2xhc3QxMk1vbnRocycgcmVhZHMgJ0xhc3QgMTIgbW9udGhzJywgJ3RoaXNXZWVrJ1xuLy8gcmVhZHMgJ1RoaXMgd2VlaycpLCBzbyBubyBsaXN0IG9mIHByZXNldHMgaXMgbWlycm9yZWQgaGVyZSBhbmQgYSBrZXkgdGhlXG4vLyBzZXJ2ZXIgYWRkcyBsYXRlciBzdGlsbCByZWFkcyBzZW5zaWJseS5cbmV4cG9ydCBmdW5jdGlvbiByZWxhdGl2ZUxhYmVsKHJlbGF0aXZlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB3b3JkcyA9IHJlbGF0aXZlXG4gICAgLnJlcGxhY2UoLyhbYS16XSkoW0EtWjAtOV0pL2csICckMSAkMicpXG4gICAgLnJlcGxhY2UoLyhcXGQpKFtBLVpdKS9nLCAnJDEgJDInKVxuICAgIC50b0xvd2VyQ2FzZSgpO1xuXG4gIHJldHVybiB3b3Jkcy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHdvcmRzLnNsaWNlKDEpO1xufVxuXG5cbi8vIE1hcHMgYSByZXBvcnQgZmlsdGVyIEdST1VQIHRvIGFuIGZzLWZpbHRlciBjb25maWcgaXRlbSwgYW5kIHJlYWRzIGZzLWZpbHRlclxuLy8gcXVlcnkgdmFsdWVzIGJhY2sgaW50byBwZXItZ3JvdXAgRmlsdGVyR3JvdXBWYWx1ZXMuIFNoYXJlZCBieSB0aGUgcmVwb3J0LWJhclxuLy8gZnMtZmlsdGVyIGFuZCB0aGUgcGVyLWNvbXBvbmVudCBmcy1maWx0ZXIgc28gYm90aCByZW5kZXIgdGhyb3VnaCB0aGUgc2FtZVxuLy8gbGlicmFyeSBhbmQgd3JpdGUgaW50byBSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UgaWRlbnRpY2FsbHkuIEl0ZW1zIGFyZSBuYW1lZFxuLy8gYnkgdGhlIGdyb3VwJ3Mga2V5IChncm91cFBhcmFtS2V5cyksIHNvIHRoZSBxdWVyeSBrZXlzIG1hcCBzdHJhaWdodCBiYWNrIHRvXG4vLyB0aGUgZ3JvdXAsIGFuZCB0aGUgcmVwb3J0IGxpbmsgdXNlcyB0aGUgc2FtZSBxdWVyeSBrZXlzIChyZXBvcnQtdXJsLXN0YXRlLnRzKS5cblxuLy8gVGhlIHF1ZXJ5IGtleSBmb3IgdGhlIHJlcG9ydCdzIGdyb3VwLWJ5IGNvbnRyb2wuIEZpeGVkIHJhdGhlciB0aGFuIGRlcml2ZWRcbi8vIGZyb20gYW4gaWQgYmVjYXVzZSBhIHJlcG9ydCBoYXMgZXhhY3RseSBvbmUg4oCUIGFuZCBpdCBpcyBOT1QgYSBmaWx0ZXIgZ3JvdXAsXG4vLyBzbyBpdCBpcyByZWFkIHN0cmFpZ2h0IG9mZiB0aGUgY2hhbmdlIHF1ZXJ5IGluc3RlYWQgb2YgdGhyb3VnaFxuLy8gZ3JvdXBWYWx1ZXNGcm9tUXVlcnkuIEl0IGlzIGFsc28gdGhlIHJlcG9ydCBVUkwncyBrZXkgZm9yIHRoZSBncmFpblxuLy8gKHJlcG9ydC11cmwtc3RhdGUudHMpLiBUaGUgZ3JhaW4gdHJhdmVscyB0byB0aGUgc2VydmVyIGFzIHRoZSBkYXRhXG4vLyByZXF1ZXN0J3MgYHN0YXRlLmZyZXF1ZW5jeWAuXG5leHBvcnQgY29uc3QgR1JPVVBfQllfSVRFTSA9ICdncm91cEJ5JztcblxuLy8gVGhlIGtleXMgb2YgdGhlIHJlcG9ydCBVUkwgdGhhdCBhcmUgbm90IGZpbHRlciBncm91cHMgKHJlcG9ydC11cmwtc3RhdGUudHNcbi8vIHJlYWRzIGFuZCB3cml0ZXMgdGhlbSkuIFRoZXkgYXJlIGRlY2xhcmVkIGhlcmUgYmVjYXVzZSBhIGdyb3VwIGtleSBtdXN0XG4vLyBub3QgdGFrZSBvbmUsIGFuZCByZXBvcnQtdXJsLXN0YXRlLnRzIGltcG9ydHMgdGhpcyBmaWxlLlxuLy8gVGhlIHNoYXJlZCB2aWV3IHRoZSBzdGF0ZSBpcyBhIGRpZmYgZnJvbSwgYW5kIHRoZSBvcGVuIHBlcnNvbmFsIHZpZXcuXG5leHBvcnQgY29uc3QgVklFV19QQVJBTSA9ICdydic7XG5leHBvcnQgY29uc3QgUEVSU09OQUxfVklFV19QQVJBTSA9ICdycHYnO1xuLy8gVGhlIGxpbmsncyBmb3JtYXQuXG5leHBvcnQgY29uc3QgRk9STUFUX1BBUkFNID0gJ3JmJztcbi8vIFRoZSBob3N0J3MgcGFnZSBrZXkgKEZzQWlSZXBvcnRDb21wb25lbnQucGFnZVF1ZXJ5UGFyYW0pLCBhcyBtb3N0IGhvc3RzXG4vLyBuYW1lIGl0LlxuZXhwb3J0IGNvbnN0IFBBR0VfUEFSQU0gPSAncGFnZSc7XG5cbi8vIFRoZSB3b3JkIGJlZm9yZSBhIGdyb3VwJ3MgaWQgaW4gdGhlIGtleSBvZiBhIGdyb3VwIHdob3NlIGxhYmVsIGdpdmVzIG5vXG4vLyBrZXkgaXQgY2FuIHVzZSAoZmlsdGVyMTIpLlxuY29uc3QgRkFMTEJBQ0tfS0VZX1dPUkQgPSAnZmlsdGVyJztcblxuLy8gVGhlIGVuZHMgb2YgYW4gZnMtZmlsdGVyIHJhbmdlIGl0ZW06IFJhbmdlIHdyaXRlcyA8a2V5Pk1pbiBhbmQgPGtleT5NYXgsXG4vLyBEYXRlUmFuZ2UgPGtleT5Gcm9tIGFuZCA8a2V5PlRvLlxuZXhwb3J0IHR5cGUgSXRlbVJhbmdlRW5kID0gJ21pbicgfCAnbWF4JyB8ICdmcm9tJyB8ICd0byc7XG5cbi8vIFRoZSBxdWVyeSBrZXkgb2Ygb25lIGVuZCBvZiBhbiBmcy1maWx0ZXIgcmFuZ2UgaXRlbTogdGhlIGl0ZW0ncyBuYW1lIGFuZFxuLy8gdGhlIGVuZCB3aXRoIGl0cyBmaXJzdCBsZXR0ZXIgdXBwZXItY2FzZWQgKGZzLWZpbHRlcidzIGdldFJhbmdlTmFtZSksIHNvXG4vLyB1bml0cyBnaXZlcyB1bml0c01pbiBhbmQgZGF0ZSBnaXZlcyBkYXRlRnJvbS5cbmV4cG9ydCBmdW5jdGlvbiBpdGVtUmFuZ2VOYW1lKG5hbWU6IHN0cmluZywgZW5kOiBJdGVtUmFuZ2VFbmQpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7bmFtZX0ke2VuZC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke2VuZC5zbGljZSgxKX1gO1xufVxuXG4vLyBFYWNoIGdyb3VwJ3Mga2V5IGluIHRoZSByZXBvcnQgVVJMLCBieSBncm91cCBpZCwgd2hpY2ggaXMgYWxzbyB0aGUgbmFtZSBvZlxuLy8gaXRzIGZzLWZpbHRlciBpdGVtOiB0aGUgY2FtZWxDYXNlIG9mIHRoZSBsYWJlbCB0aGUgYmFyIHNob3dzICgnUmVnaW9uJyAtPlxuLy8gcmVnaW9uLCAnUmVwb3J0IFBlcmlvZCcgLT4gcmVwb3J0UGVyaW9kKS4gVGhlIGxpbmsgd3JpdGVzIGEgZ3JvdXAgdW5kZXJcbi8vIHRoZSBpdGVtJ3Mgb3duIHF1ZXJ5IGtleXMgKHJlZ2lvbj0sIGV4Y2x1ZGVSZWdpb249LCB1bml0c01pbj0sIGRhdGVGcm9tPSkuXG4vLyBBIGtleSB0aGUgcmVwb3J0IGNhbm5vdCBnaXZlIGEgZ3JvdXAgYXMgaXQgaXMgKGFub3RoZXIgZ3JvdXAgd2l0aCBhIGxvd2VyXG4vLyBpZCBoYXMgaXQgb3Igb25lIG9mIGl0cyBmb3JtcywgYW5vdGhlciBsaW5rIGtleSBvciBiYXIgaXRlbSB1c2VzIGl0LCBvciBpdFxuLy8gaXMgc2hhcGVkIGxpa2UgYSB0aWxlJ3MgaWQga2V5LCBzdWNoIGFzIHE0KSBpcyB0aGUga2V5IGFuZCB0aGUgZ3JvdXAncyBpZFxuLy8gKHJlZ2lvbjEyKS4gQSBsYWJlbCB3aXRoIG5vIGxldHRlciBvciBkaWdpdCwgb3IgYSBjbGFzaCBldmVuIHRoZW4sIGtleXMgb25cbi8vIGZpbHRlcjxpZD4uIGBncm91cHNgIGlzIGV2ZXJ5IGdyb3VwIG9mIHRoZSByZXBvcnQsIHNvIGV2ZXJ5IGJhciBhbmQgdGhlXG4vLyBsaW5rIG5hbWUgYSBncm91cCBhbGlrZS5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFBhcmFtS2V5cyhncm91cHM6IHJlYWRvbmx5IFBpY2s8UmVwb3J0RmlsdGVyR3JvdXAsICdpZCcgfCAnbGFiZWwnIHwgJ2ZpbHRlcnMnPltdKTogTWFwPG51bWJlciwgc3RyaW5nPiB7XG4gIC8vIFRoZSBVUkwncyBvdGhlciBrZXlzIGFuZCB0aGUgYmFyJ3Mgb3RoZXIgaXRlbXMuXG4gIGNvbnN0IHRha2VuID0gbmV3IFNldChbXG4gICAgUEFHRV9QQVJBTSwgR1JPVVBfQllfSVRFTSwgTUFUQ0hfSVRFTSwgTElTVF9TRUFSQ0hfSVRFTSwgVklFV19QQVJBTSwgUEVSU09OQUxfVklFV19QQVJBTSwgRk9STUFUX1BBUkFNLFxuICBdKTtcbiAgY29uc3QgZnJlZSA9IChjYW5kaWRhdGU6IHN0cmluZykgPT4gISFjYW5kaWRhdGVcbiAgICAmJiBrZXlGb3JtcyhjYW5kaWRhdGUpLmV2ZXJ5KChmb3JtKSA9PiAhdGFrZW4uaGFzKGZvcm0pICYmICFJRF9LRVkudGVzdChmb3JtKSk7XG4gIGNvbnN0IGtleXMgPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuXG4gIFsuLi5ncm91cHNdXG4gICAgLnNvcnQoKGEsIGIpID0+IGEuaWQgLSBiLmlkKVxuICAgIC5mb3JFYWNoKChncm91cCkgPT4ge1xuICAgICAgY29uc3Qgd2FudGVkID0gbGFiZWxLZXkoZ3JvdXBMYWJlbChncm91cCkpO1xuICAgICAgY29uc3Qga2V5ID0gW3dhbnRlZCwgd2FudGVkICYmIGAke3dhbnRlZH0ke2dyb3VwLmlkfWBdLmZpbmQoZnJlZSkgPz8gZmFsbGJhY2tLZXkoZ3JvdXAuaWQsIGZyZWUpO1xuXG4gICAgICBrZXlGb3JtcyhrZXkpLmZvckVhY2goKGZvcm0pID0+IHRha2VuLmFkZChmb3JtKSk7XG4gICAgICBrZXlzLnNldChncm91cC5pZCwga2V5KTtcbiAgICB9KTtcblxuICByZXR1cm4ga2V5cztcbn1cblxuLy8gZmlsdGVyPGlkPiwgb3IsIGluIHRoZSByYXJlIHJlcG9ydCB3aGVyZSBhbm90aGVyIGdyb3VwJ3MgbGFiZWwgYWxyZWFkeVxuLy8gZ2l2ZXMgdGhhdCwgZmlsdGVyPGlkPiBhbmQgYSBjb3VudC5cbmZ1bmN0aW9uIGZhbGxiYWNrS2V5KGdyb3VwSWQ6IG51bWJlciwgZnJlZTogKGNhbmRpZGF0ZTogc3RyaW5nKSA9PiBib29sZWFuKTogc3RyaW5nIHtcbiAgY29uc3QgYmFzZSA9IGAke0ZBTExCQUNLX0tFWV9XT1JEfSR7Z3JvdXBJZH1gO1xuICBsZXQga2V5ID0gYmFzZTtcblxuICBmb3IgKGxldCBjb3VudCA9IDI7ICFmcmVlKGtleSk7IGNvdW50KyspIHtcbiAgICBrZXkgPSBgJHtiYXNlfU4ke2NvdW50fWA7XG4gIH1cblxuICByZXR1cm4ga2V5O1xufVxuXG4vLyBBIGdyb3VwJ3Mga2V5IGFtb25nIGBncm91cHNgIChldmVyeSBncm91cCBvZiB0aGUgcmVwb3J0KS4gQSBncm91cCB0aGF0IGlzXG4vLyBub3QgYW1vbmcgdGhlbSBpcyBrZXllZCBhcyBvbmUgbW9yZSBvZiB0aGVtLlxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwUGFyYW1LZXkoXG4gIGdyb3VwOiBQaWNrPFJlcG9ydEZpbHRlckdyb3VwLCAnaWQnIHwgJ2xhYmVsJyB8ICdmaWx0ZXJzJz4sXG4gIGdyb3VwczogcmVhZG9ubHkgUGljazxSZXBvcnRGaWx0ZXJHcm91cCwgJ2lkJyB8ICdsYWJlbCcgfCAnZmlsdGVycyc+W10sXG4pOiBzdHJpbmcge1xuICByZXR1cm4gZ3JvdXBQYXJhbUtleXMoZ3JvdXBzLnNvbWUoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLmlkID09PSBncm91cC5pZCkgPyBncm91cHMgOiBbLi4uZ3JvdXBzLCBncm91cF0pXG4gICAgLmdldChncm91cC5pZCk7XG59XG5cbi8vIFRoZSBuYW1lIG9mIGEgZ3JvdXAncyBmcy1maWx0ZXIgaXRlbTogaXRzIGtleSBhbW9uZyB0aGUgcmVwb3J0J3MgZ3JvdXBzLlxuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwSXRlbU5hbWUoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLCByZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBzdHJpbmcge1xuICByZXR1cm4gZ3JvdXBQYXJhbUtleShncm91cCwgcmVwb3J0Py5maWx0ZXJHcm91cHMgPz8gW10pO1xufVxuXG4vLyBUaGUgbGFiZWwgYSBncm91cCdzIGNoaXAgc2hvd3M6IGl0cyBvd24sIGVsc2UgaXRzIGZpcnN0IG1lbWJlcidzIGNvbHVtbi5cbmZ1bmN0aW9uIGdyb3VwTGFiZWwoZ3JvdXA6IFBpY2s8UmVwb3J0RmlsdGVyR3JvdXAsICdsYWJlbCcgfCAnZmlsdGVycyc+KTogc3RyaW5nIHtcbiAgcmV0dXJuIGdyb3VwLmxhYmVsIHx8IGdyb3VwLmZpbHRlcnM/LlswXT8uZmlsdGVyQ29sdW1uIHx8ICcnO1xufVxuXG4vLyBBIGxldHRlciBhbmQgdGhlbiBkaWdpdHM6IHRoZSBzaGFwZSBvZiB0aGUgVVJMJ3MgdGlsZSBrZXlzIChzMzEsIHEzMSxcbi8vIGgzMSwgZDQ0KSwga2VwdCBvZmYgdGhlIGdyb3VwcyBzbyBhIGdyb3VwIGtleSBuZXZlciByZWFkcyBhcyBvbmUuXG5jb25zdCBJRF9LRVkgPSAvXlthLXpdXFxkKyQvO1xuXG5jb25zdCBSQU5HRV9FTkRTOiByZWFkb25seSBJdGVtUmFuZ2VFbmRbXSA9IFsnbWluJywgJ21heCcsICdmcm9tJywgJ3RvJ107XG5cbi8vIEV2ZXJ5IGtleSBhIGdyb3VwJ3MgaXRlbSBvciBsaW5rIG1heSB3cml0ZSB1bmRlciBga2V5YDogdGhlIGtleSwgaXRzXG4vLyBleGNsdWRlIGtleSAoZXhjbHVkZVJlZ2lvbikgYW5kIGFuIGZzLWZpbHRlciByYW5nZSdzIG93biBrZXlzLlxuZnVuY3Rpb24ga2V5Rm9ybXMoa2V5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBba2V5LCBnZXRFeGNsdWRlTmFtZShrZXkpLCAuLi5SQU5HRV9FTkRTLm1hcCgoZW5kKSA9PiBpdGVtUmFuZ2VOYW1lKGtleSwgZW5kKSldO1xufVxuXG4vLyBBIGxhYmVsIGFzIGEgY2FtZWxDYXNlIGtleTogYWNjZW50cyBkcm9wcGVkLCB3b3JkcyBzcGxpdCBvbiBhbnl0aGluZyB0aGF0XG4vLyBpcyBub3QgYSBsZXR0ZXIgb3IgZGlnaXQgKGFuZCB3aGVyZSBhIGxvd2VyLWNhc2UgbGV0dGVyIG1lZXRzIGFuIHVwcGVyLWNhc2Vcbi8vIG9uZSksIHRoZSBmaXJzdCB3b3JkIGxvd2VyLWNhc2UsIGV2ZXJ5IGxhdGVyIG9uZSBjYXBpdGFsaXplZC5cbmZ1bmN0aW9uIGxhYmVsS2V5KGxhYmVsOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbGFiZWxcbiAgICAubm9ybWFsaXplKCdORkQnKVxuICAgIC5yZXBsYWNlKC9cXHB7TX0vZ3UsICcnKVxuICAgIC5yZXBsYWNlKC8oW2EtejAtOV0pKFtBLVpdKS9nLCAnJDEgJDInKVxuICAgIC5zcGxpdCgvW15BLVphLXowLTldKy8pXG4gICAgLmZpbHRlcigod29yZCkgPT4gd29yZCAhPT0gJycpXG4gICAgLm1hcCgod29yZCwgaW5kZXgpID0+IHtcbiAgICAgIGNvbnN0IGxvd2VyID0gd29yZC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICByZXR1cm4gaW5kZXggPyBsb3dlci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGxvd2VyLnNsaWNlKDEpIDogbG93ZXI7XG4gICAgfSlcbiAgICAuam9pbignJyk7XG59XG5cbi8vIEEgc2VsZWN0IGdyb3VwJ3MgZGlzdGluY3Qgb3B0aW9ucywgYXMgeyBuYW1lLCB2YWx1ZSB9IHBhaXJzLiBUaGUgc2VydmVyIHNlbmRzXG4vLyB7IHZhbHVlLCBsYWJlbCB9OiB0aGUgdmFsdWUgaXMgd2hhdCB0aGUgZmlsdGVyIG1hdGNoZXMgb24gKGFuIGVudGl0eSdzIHN0YWJsZVxuLy8gaWQpIGFuZCB0aGUgbGFiZWwgaXMgd2hhdCB0aGUgdmlld2VyIHJlYWRzIOKAlCBzbyBhIHJlbmFtZWQgZW50aXR5IGtlZXBzIGl0cyBpZFxuLy8gYW5kIHNpbXBseSBzaG93cyBpdHMgbmV3IG5hbWUgaGVyZS4gT3B0aW9ucyBjb21lIGZyb20gdGhlIGZpcnN0IG1lbWJlciBmaWx0ZXJcbi8vIHRoYXQgZGVjbGFyZXMgdGhlbSDigJQgbWVtYmVycyBhcmUgdGhlIHNhbWUgZGF0YSBwb2ludCwgc28gYW55IG1lbWJlcidzIGxpc3Rcbi8vIHNlcnZlcyB0aGUgZ3JvdXAuIFRoZSBsaXN0IGlzIGZldGNoZWQgb25jZSAodGhlIHNlcnZlciBjYXBzIGl0KSBhbmQgcmVwbGF5ZWRcbi8vIChzaGFyZVJlcGxheSksIHNvIHJlcGVhdGVkIHJlYWRzIG5ldmVyIHJlZmV0Y2guIFRoaXMgaXMgdGhlIGZ1bGwgbGlzdCwgbmV2ZXJcbi8vIG5hcnJvd2VkIGJ5IG90aGVyIGZpbHRlcnM6IHRoZSByZXBvcnQtc2V0dGluZ3MgZGVmYXVsdCBwaWNrZXIgcmVhZHMgaXQgKGFuXG4vLyBhdXRob3Igc2V0cyBhIGRlZmF1bHQgYWdhaW5zdCB0aGUgd2hvbGUgbGlzdCksIGFuZCBzbyBkb2VzIHRoZSBleHBvcnQnc1xuLy8gZmlsdGVyIHdvcmRpbmcgZm9yIGEgcGljayB0aGUgYmFyIGhhcyBub3QgbmFtZWQuIFRoZSBiYXJzIHJlYWRcbi8vIFJlcG9ydEZpbHRlck9wdGlvbnNTZXJ2aWNlIGluc3RlYWQuIFJldHVybnMgYW4gZW1wdHkgbGlzdCB3aGVuIG5vIG1lbWJlclxuLy8gcHJvdmlkZXMgb3B0aW9ucy5cbmV4cG9ydCBmdW5jdGlvbiBsb2FkR3JvdXBPcHRpb25zKFxuICBncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsXG4gIHJlcG9ydERhdGE6IFJlcG9ydERhdGEsXG4gIHJlcG9ydElkOiBudW1iZXIsXG4pOiBPYnNlcnZhYmxlPFJlcG9ydEZpbHRlck9wdGlvblBhaXJbXT4ge1xuICBjb25zdCBvcHRpb25GaWx0ZXIgPSAoZ3JvdXAuZmlsdGVycyA/PyBbXSkuZmluZCgobWVtYmVyKSA9PiBtZW1iZXIuaGFzT3B0aW9ucyk7XG4gIGlmICghb3B0aW9uRmlsdGVyKSB7XG4gICAgcmV0dXJuIG9mKFtdKTtcbiAgfVxuXG4gIHJldHVybiByZXBvcnREYXRhLmZpbHRlck9wdGlvbnMocmVwb3J0SWQsIG9wdGlvbkZpbHRlci5pZClcbiAgICAucGlwZShcbiAgICAgIG1hcCgob3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uW10pID0+IChvcHRpb25zID8/IFtdKVxuICAgICAgICAubWFwKChvcHRpb24pID0+ICh7IG5hbWU6IG9wdGlvbi5sYWJlbCwgdmFsdWU6IG9wdGlvbi52YWx1ZSB9KSkpLFxuICAgICAgc2hhcmVSZXBsYXkoeyBidWZmZXJTaXplOiAxLCByZWZDb3VudDogZmFsc2UgfSksXG4gICAgKTtcbn1cblxuLy8gU3RvcmVkIGZpbHRlciB2YWx1ZXMgKGlkcykgcGFpcmVkIGJhY2sgd2l0aCB0aGUgbGFiZWxzIHRvIHNob3cgZm9yIHRoZW0uXG4vLyBBIHNhdmVkIGRlZmF1bHQgaG9sZHMgb25seSB2YWx1ZXMsIHNvIHRoZSBuYW1lcyBoYXZlIHRvIGJlIHJlYWQgYmFjayBvZmYgdGhlXG4vLyBvcHRpb24gbGlzdCDigJQgdGhhdCBpbmRpcmVjdGlvbiBpcyBleGFjdGx5IHdoYXQgc3Vydml2ZXMgYSByZW5hbWUuIGBsYWJlbGBcbi8vIG5hbWVzIGEgdmFsdWUgZmlyc3Q6IGEgbmFtZSBhbHJlYWR5IGxlYXJuZWQgKFJlcG9ydEZpbHRlck9wdGlvbnNTZXJ2aWNlLmxhYmVsKVxuLy8gaG9sZHMgZm9yIGEgcGljayBhIG5hcnJvd2VkIGxpc3QgbGVhdmVzIG91dCwgYW5kIHdoZW4gaXQgbmFtZXMgZXZlcnkgdmFsdWVcbi8vIHRoZSBsaXN0IGlzIG5vdCByZWFkIGF0IGFsbC4gQSB2YWx1ZSB3aXRoIG5vIG5hbWUgYW5kIG5vIG1hdGNoaW5nIG9wdGlvblxuLy8gKGl0cyBlbnRpdHkgd2FzIGRlbGV0ZWQsIHNvIGl0IGlzIG5vIGxvbmdlciBsaXN0ZWQpIGZhbGxzIGJhY2sgdG8gc2hvd2luZ1xuLy8gdGhlIHJhdyB2YWx1ZSByYXRoZXIgdGhhbiBkcm9wcGluZyB0aGUgY2hpcCwgd2hpY2ggd291bGQgc2lsZW50bHkgd2lkZW4gdGhlXG4vLyBmaWx0ZXIuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9wdGlvblZhbHVlcyhcbiAgb3B0aW9ucyQ6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPixcbiAgdmFsdWVzOiB1bmtub3duW10sXG4gIGxhYmVsOiAodmFsdWU6IHVua25vd24pID0+IHN0cmluZyB8IG51bGwgPSAoKSA9PiBudWxsLFxuKTogT2JzZXJ2YWJsZTxSZXBvcnRGaWx0ZXJPcHRpb25QYWlyW10+IHtcbiAgY29uc3QgbmFtZWQgPSAob3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbiA9IG9wdGlvbnMuZmluZCgoY2FuZGlkYXRlKSA9PiBTdHJpbmcoY2FuZGlkYXRlLnZhbHVlKSA9PT0gU3RyaW5nKHZhbHVlKSk7XG5cbiAgICByZXR1cm4geyBuYW1lOiBsYWJlbCh2YWx1ZSkgPz8gb3B0aW9uPy5uYW1lID8/IFN0cmluZyh2YWx1ZSksIHZhbHVlIH07XG4gIH0pO1xuXG4gIHJldHVybiB2YWx1ZXMuZXZlcnkoKHZhbHVlKSA9PiBsYWJlbCh2YWx1ZSkgIT09IG51bGwpXG4gICAgPyBvZihuYW1lZChbXSkpXG4gICAgOiBvcHRpb25zJC5waXBlKG1hcChuYW1lZCkpO1xufVxuXG4vLyBDYXNlLWluc2Vuc2l0aXZlIG5hbWUgZmlsdGVyIGFwcGxpZWQgdG8gYSBsb2FkZWQgb3B0aW9uIGxpc3Qg4oCUIHRoZSB0eXBlZFxuLy8ga2V5d29yZCBoYXMgdG8gYmUgbWF0Y2hlZCBoZXJlIGJlY2F1c2UgZnMtYXV0b2NvbXBsZXRlIHJlbmRlcnMgd2hhdCB3ZSByZXR1cm5cbi8vIHZlcmJhdGltLlxuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoT3B0aW9ucyhcbiAgb3B0aW9ucyQ6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPixcbiAga2V5d29yZD86IHN0cmluZyxcbik6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPiB7XG4gIGNvbnN0IHRlcm0gPSAoa2V5d29yZCA/PyAnJykudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgcmV0dXJuIG9wdGlvbnMkLnBpcGUobWFwKChvcHRpb25zKSA9PiB0ZXJtXG4gICAgPyBvcHRpb25zLmZpbHRlcigob3B0aW9uKSA9PiBvcHRpb24ubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHRlcm0pKVxuICAgIDogb3B0aW9ucykpO1xufVxuXG4vLyBUaGUgcGFuZWwgcm93IG9mIGEgc2VsZWN0IHdob3NlIGxpc3QgdGhlIHNlcnZlciBjdXQgYXQgNTAwLlxuZXhwb3J0IGNvbnN0IE9QVElPTlNfVFJVTkNBVEVEX05PVEUgPSAnU2hvd2luZyB0aGUgZmlyc3QgNTAwLiBUeXBlIHRvIG5hcnJvdy4nO1xuXG4vLyBUaGUgcGFuZWwgcm93IG9mIGEgc2VsZWN0IHdob3NlIGxpc3QgY291bGQgbm90IGJlIHJlYWQuIFRoZSBuZXh0IGZvY3VzIG9yXG4vLyBrZXlzdHJva2UgYXNrcyBhZ2Fpbi5cbmV4cG9ydCBjb25zdCBPUFRJT05TX0ZBSUxFRF9OT1RFID0gJ0NvdWxkIG5vdCBsb2FkIHRoZSBsaXN0Lic7XG5cbi8vIEJ1aWxkIHRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIGEgZ3JvdXAsIHNlZWRpbmcgaXRzIGRlZmF1bHQgZnJvbSB0aGVcbi8vIGN1cnJlbnQgc2Vzc2lvbiB2YWx1ZSBzbyBhdXRob3JlZC9yZWxhdGl2ZSBkZWZhdWx0cyBzaG93IHNlbGVjdGVkIG9uIG9wZW4uXG4vLyBBIHNlbGVjdCBsaXN0cyB3aGF0IGBvcHRpb25zYCBvZmZlcnMgZm9yIGl0IGluIGByZXBvcnRgLiBgZmVhdHVyZXNgIGlzIHRoZVxuLy8gcmVwb3J0J3Mgdmlld2VyRmVhdHVyZXM6IGEgc2VsZWN0IG9mZmVycyAnRXhjbHVkZSB0aGVzZScgYnkgdGhlIHJ1bGUgb2Zcbi8vIG9mZmVyc0V4Y2x1ZGUgKHRoZSBzZXJ2ZXIgbGlzdHMgZXhjbHVkZVZhbHVlcyBhbmQgbm8gbWVtYmVyIGJpbmRzIHNldmVyYWxcbi8vIGNvbHVtbnMpLCBhbmQgYSBudW1iZXIgcmFuZ2UgaXMgYSBtaW4vbWF4IGNvbnRyb2wgb25seSB3aGVuIGl0IGxpc3RzXG4vLyBudW1iZXJSYW5nZS5cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJJdGVtRm9yR3JvdXAoXG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgb3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UsXG4gIHJlcG9ydDogUmVwb3J0IHwgbnVsbCxcbiAgaW5pdGlhbD86IEZpbHRlckdyb3VwVmFsdWUsXG4gIGZlYXR1cmVzOiByZWFkb25seSBSZXBvcnRWaWV3ZXJGZWF0dXJlW10gPSBbXSxcbik6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXAsIHJlcG9ydCk7XG4gIGNvbnN0IGxhYmVsID0gZ3JvdXBMYWJlbChncm91cCk7XG5cbiAgc3dpdGNoIChncm91cC50eXBlKSB7XG4gICAgY2FzZSAnZGF0ZVJhbmdlJzpcbiAgICAgIHJldHVybiBkYXRlUmFuZ2VGaWx0ZXJJdGVtKG5hbWUsIGxhYmVsLCBpbml0aWFsKTtcblxuICAgIGNhc2UgJ3NlbGVjdCc6XG4gICAgICByZXR1cm4gc2VsZWN0RmlsdGVySXRlbShncm91cCwgbGFiZWwsIG9wdGlvbnMsIHJlcG9ydCwgaW5pdGlhbCwgb2ZmZXJzRXhjbHVkZShncm91cCwgZmVhdHVyZXMpKTtcblxuICAgIGNhc2UgJ251bWJlclJhbmdlJzpcbiAgICAgIHJldHVybiBmZWF0dXJlcy5pbmNsdWRlcygnbnVtYmVyUmFuZ2UnKVxuICAgICAgICA/IG51bWJlclJhbmdlRmlsdGVySXRlbShncm91cCwgbGFiZWwsIHJlcG9ydCwgaW5pdGlhbClcbiAgICAgICAgOiBrZXl3b3JkRmlsdGVySXRlbShuYW1lLCBsYWJlbCwgaW5pdGlhbCk7XG5cbiAgICBjYXNlICdrZXl3b3JkJzpcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGtleXdvcmRGaWx0ZXJJdGVtKG5hbWUsIGxhYmVsLCBpbml0aWFsKTtcbiAgfVxufVxuXG4vLyBBIGRhdGUgcmFuZ2Ugb3BlbnMgb24gaXRzIGRheXMsIGFuZCBpdHMgY2hpcCBzaG93cyB0aGVtLiBBIHByZXNldCBwaWNrZWQgaW5cbi8vIHRoZSBkYXRlIHBpY2tlciBvbmx5IHNldHMgdGhlIGRheXMuXG5mdW5jdGlvbiBkYXRlUmFuZ2VGaWx0ZXJJdGVtKG5hbWU6IHN0cmluZywgbGFiZWw6IHN0cmluZywgaW5pdGlhbD86IEZpbHRlckdyb3VwVmFsdWUpOiBJRmlsdGVyQ29uZmlnSXRlbSB7XG4gIGNvbnN0IGhhc0RheXMgPSAhIShpbml0aWFsPy5zdGFydCB8fCBpbml0aWFsPy5lbmQpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICB0eXBlOiBJdGVtVHlwZS5EYXRlUmFuZ2UsXG4gICAgbGFiZWw6IHsgZnJvbTogYCR7bGFiZWx9IEZyb21gLCB0bzogYCR7bGFiZWx9IFRvYCB9LFxuICAgIGRlZmF1bHQ6IGhhc0RheXNcbiAgICAgID8geyBmcm9tOiBpbml0aWFsLnN0YXJ0ID8/IHVuZGVmaW5lZCwgdG86IGluaXRpYWwuZW5kID8/IHVuZGVmaW5lZCB9XG4gICAgICA6IHVuZGVmaW5lZCxcbiAgfTtcbn1cblxuLy8gQSBzZWxlY3QncyBwaWNrcywga2VwdCBvciBsZWZ0IG91dC4gV2l0aCBgZXhjbHVkZWAgdGhlIGxpc3QgaGFzIHRoZVxuLy8gJ0V4Y2x1ZGUgdGhlc2UnIHJvdywgYW5kIGEgdmFsdWUgdGhhdCBsZWF2ZXMgb3V0IG9wZW5zIHdpdGggaXQgb24uIEl0cyBsaXN0XG4vLyBpcyByZWFkIG9uIGZvY3VzIGFuZCBvbiBlYWNoIGtleXN0cm9rZTogdGhlIG9wdGlvbnMgc2VydmljZSBmZXRjaGVzIGl0IHdoZW5cbi8vIHRoZSBvdGhlciBmaWx0ZXJzIGNoYW5nZWQgc2luY2UgYW5kIHJlcGxheXMgaXQgb3RoZXJ3aXNlLCBhbmQgdHlwaW5nXG4vLyBmaWx0ZXJzIGl0IGhlcmUuIEEgbGlzdCB0aGUgc2VydmVyIGN1dCwgb3Igb25lIHRoYXQgY291bGQgbm90IGJlIHJlYWQsXG4vLyBzYXlzIHNvIGluIGEgcGFuZWwgcm93LlxuZnVuY3Rpb24gc2VsZWN0RmlsdGVySXRlbShcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLFxuICBsYWJlbDogc3RyaW5nLFxuICBvcHRpb25zOiBSZXBvcnRGaWx0ZXJPcHRpb25zU2VydmljZSxcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBpbml0aWFsOiBGaWx0ZXJHcm91cFZhbHVlIHwgdW5kZWZpbmVkLFxuICBleGNsdWRlOiBib29sZWFuLFxuKTogSUZpbHRlckNvbmZpZ0l0ZW0ge1xuICBjb25zdCBleGNsdWRpbmcgPSBleGNsdWRlICYmICFpbml0aWFsPy52YWx1ZXM/Lmxlbmd0aCAmJiAhIWluaXRpYWw/LmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aDtcbiAgY29uc3QgcGlja3MgPSBleGNsdWRpbmcgPyBpbml0aWFsLmV4Y2x1ZGVWYWx1ZXMgOiBpbml0aWFsPy52YWx1ZXM7XG4gIGNvbnN0IG9wdGlvbnMkID0gb3B0aW9ucy5vcHRpb25zKGdyb3VwLCByZXBvcnQpO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZTogZ3JvdXBJdGVtTmFtZShncm91cCwgcmVwb3J0KSxcbiAgICB0eXBlOiBJdGVtVHlwZS5BdXRvQ29tcGxldGVDaGlwcyxcbiAgICBsYWJlbCxcbiAgICBmZXRjaE9uRm9jdXM6IHRydWUsXG4gICAgZXhjbHVkZTogZXhjbHVkZSA/IHt9IDogdW5kZWZpbmVkLFxuICAgIHZhbHVlczogKGtleXdvcmQ/OiBzdHJpbmcpID0+IG1hdGNoT3B0aW9ucyhvcHRpb25zJCwga2V5d29yZCksXG4gICAgcGFuZWxOb3RlOiAoKSA9PiBvcHRpb25zTm90ZShvcHRpb25zLCBncm91cC5pZCksXG4gICAgLy8gU3RvcmVkIHZhbHVlcyBhcmUgaWRzLCBzbyBhIGNoaXAgaXMgbmFtZWQgYnkgYSBuYW1lIGFscmVhZHkgbGVhcm5lZCBvclxuICAgIC8vIG9uY2UgdGhlIG9wdGlvbiBsaXN0IGhhcyBsb2FkZWQg4oCUIGhlbmNlIHRoZSBvYnNlcnZhYmxlIGZvcm0gb2YgYGRlZmF1bHRgLlxuICAgIGRlZmF1bHQ6IHBpY2tzPy5sZW5ndGhcbiAgICAgID8gKCkgPT4gcmVzb2x2ZU9wdGlvblZhbHVlcyhvcHRpb25zJCwgcGlja3MsICh2YWx1ZSkgPT4gb3B0aW9ucy5sYWJlbChncm91cC5pZCwgdmFsdWUpKVxuICAgICAgICAucGlwZShtYXAoKHNlbGVjdGVkKSA9PiAoZXhjbHVkaW5nID8geyBleGNsdWRlOiB0cnVlLCBzZWxlY3RlZCB9IDogc2VsZWN0ZWQpKSlcbiAgICAgIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vLyBUaGUgcGFuZWwgcm93IG9mIGEgc2VsZWN0J3MgbGF0ZXN0IGxpc3Q6IGEgZmFpbHVyZSBmaXJzdCwgdGhlbiBhIGN1dCBsaXN0LlxuZnVuY3Rpb24gb3B0aW9uc05vdGUob3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UsIGdyb3VwSWQ6IG51bWJlcik6IHN0cmluZyB8IG51bGwge1xuICBpZiAob3B0aW9ucy5mYWlsZWQoZ3JvdXBJZCkpIHtcbiAgICByZXR1cm4gT1BUSU9OU19GQUlMRURfTk9URTtcbiAgfVxuXG4gIHJldHVybiBvcHRpb25zLnRydW5jYXRlZChncm91cElkKSA/IE9QVElPTlNfVFJVTkNBVEVEX05PVEUgOiBudWxsO1xufVxuXG4vLyBBIG51bWJlciByYW5nZSdzIGxvdyBhbmQgaGlnaCBlbmRzLCBlaXRoZXIgb25lIG9wZW4uIDAgaXMgYW4gZW5kIGxpa2UgYW55XG4vLyBvdGhlci4gSXRzIGNoaXAgcmVhZHMgYXMgdGhlIGV4cG9ydCBsaW5lcyBkbyAoJ0Ftb3VudDogMCBvciBtb3JlJyxcbi8vICdBbW91bnQ6IDAgdG8gMTAnKTogdGhlIGVuZHMgYXJlIHJlYWQgb2ZmIHRoZSBpdGVtJ3MgcXVlcnkgdGhlIHdheSB0aGVcbi8vIGJhcidzIGNoYW5nZSByZWFkcyB0aGVtLCBhbmQgd29yZGVkIGluIHRoZSByZXBvcnQncyBsb2NhbGUuXG5mdW5jdGlvbiBudW1iZXJSYW5nZUZpbHRlckl0ZW0oXG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgbGFiZWw6IHN0cmluZyxcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBpbml0aWFsPzogRmlsdGVyR3JvdXBWYWx1ZSxcbik6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXAsIHJlcG9ydCk7XG4gIGNvbnN0IG1pbiA9IGluaXRpYWw/Lm1pbiA/PyB1bmRlZmluZWQ7XG4gIGNvbnN0IG1heCA9IGluaXRpYWw/Lm1heCA/PyB1bmRlZmluZWQ7XG4gIGNvbnN0IGxvY2FsZSA9IHJlc29sdmVGb3JtYXRDb250ZXh0KHJlcG9ydCA/PyB7fSkubG9jYWxlO1xuXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICB0eXBlOiBJdGVtVHlwZS5SYW5nZSxcbiAgICBsYWJlbCxcbiAgICBkZWZhdWx0OiBtaW4gIT09IHVuZGVmaW5lZCB8fCBtYXggIT09IHVuZGVmaW5lZCA/IHsgbWluLCBtYXggfSA6IHVuZGVmaW5lZCxcbiAgICBjaGlwVGV4dDogKGl0ZW0pID0+IGZpbHRlckxpbmVUZXh0KFxuICAgICAgeyBsYWJlbCwgbGV2ZWw6IGdyb3VwLmxldmVsIH0sXG4gICAgICBudW1iZXJSYW5nZUZyb21RdWVyeShpdGVtLnF1ZXJ5LCBuYW1lKSxcbiAgICAgIHsgbG9jYWxlIH0sXG4gICAgICAnY2hpcCcsXG4gICAgKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24ga2V5d29yZEZpbHRlckl0ZW0obmFtZTogc3RyaW5nLCBsYWJlbDogc3RyaW5nLCBpbml0aWFsPzogRmlsdGVyR3JvdXBWYWx1ZSk6IElGaWx0ZXJDb25maWdJdGVtIHtcbiAgcmV0dXJuIHtcbiAgICBuYW1lLFxuICAgIHR5cGU6IEl0ZW1UeXBlLktleXdvcmQsXG4gICAgbGFiZWwsXG4gICAgZGVmYXVsdDogaW5pdGlhbD8udmFsdWUsXG4gIH07XG59XG5cbi8vIFRoZSBncm91cHMgYSBtYXRjaCBvZiAnYW55JyBjb21iaW5lczogcmVwb3J0IGJhciBncm91cHMgKGEgcGFnZSBncm91cCBvblxuLy8gaXRzIG93biBwYWdlIG9ubHkpIHRoYXQgYSB2aWV3ZXIgcGlja3MgdmFsdWVzLCB0ZXh0IG9yIGEgbnVtYmVyIHJhbmdlIGluLlxuLy8gRGF0ZXMsIHRpbGUtb25seSBncm91cHMgYW5kIHRoZSBjcm9zcy1maWx0ZXIgYWx3YXlzIG5hcnJvdyBvbiB0aGVpciBvd24uXG4vLyBUaGUgc2VydmVyIGhvbGRzIHRoZSBzYW1lIHJ1bGUgYW5kIGNoZWNrcyBldmVyeSBpZCBpdCBpcyBzZW50LlxuY29uc3QgTUFUQ0hfQU5ZX0xFVkVMUzogcmVhZG9ubHkgUmVwb3J0RmlsdGVyTGV2ZWxbXSA9IFsncmVwb3J0JywgJ2JvdGgnLCAncGFnZSddO1xuY29uc3QgTUFUQ0hfQU5ZX1RZUEVTOiByZWFkb25seSBSZXBvcnRGaWx0ZXJUeXBlW10gPSBbJ3NlbGVjdCcsICdrZXl3b3JkJywgJ251bWJlclJhbmdlJ107XG5cbi8vIFdoZXRoZXIgYSBncm91cCBqb2lucyBhIG1hdGNoIG9mICdhbnknIG9uIHBhZ2UgYHBhZ2VJZGAuXG5leHBvcnQgZnVuY3Rpb24gaXNNYXRjaEFueUdyb3VwKGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCwgcGFnZUlkOiBudW1iZXIgfCBudWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBNQVRDSF9BTllfTEVWRUxTLmluY2x1ZGVzKGdyb3VwLmxldmVsKVxuICAgICYmIE1BVENIX0FOWV9UWVBFUy5pbmNsdWRlcyhncm91cC50eXBlKVxuICAgICYmIChncm91cC5sZXZlbCAhPT0gJ3BhZ2UnIHx8ICghIXBhZ2VJZCAmJiBncm91cC5wYWdlSWQgPT09IHBhZ2VJZCkpO1xufVxuXG4vLyBUaGUgcmVwb3J0IGJhcidzIGdyb3VwcyBpbiB0aGVpciBzYXZlZCBvcmRlcjogdGhlIHJlcG9ydCBhbmQgYm90aCBncm91cHMsXG4vLyBhbmQgdGhlIHBhZ2UgZ3JvdXBzIG9mIHRoZSBwYWdlIG9uIHNjcmVlbiAoYHBhZ2VJZGApLlxuZXhwb3J0IGZ1bmN0aW9uIHJlcG9ydEJhckdyb3VwcyhyZXBvcnQ6IFJlcG9ydCB8IG51bGwsIHBhZ2VJZDogbnVtYmVyIHwgbnVsbCk6IFJlcG9ydEZpbHRlckdyb3VwW10ge1xuICByZXR1cm4gKHJlcG9ydD8uZmlsdGVyR3JvdXBzID8/IFtdKVxuICAgIC5maWx0ZXIoKGdyb3VwKSA9PiBncm91cC5sZXZlbCA9PT0gJ3JlcG9ydCcgfHwgZ3JvdXAubGV2ZWwgPT09ICdib3RoJ1xuICAgICAgfHwgKGdyb3VwLmxldmVsID09PSAncGFnZScgJiYgISFwYWdlSWQgJiYgZ3JvdXAucGFnZUlkID09PSBwYWdlSWQpKVxuICAgIC5zb3J0KChhLCBiKSA9PiBhLm9yZGVyIC0gYi5vcmRlcik7XG59XG5cbi8vIFdoZXRoZXIgdGhlIHJlcG9ydCBoYXMgYSBncm91cCBzaG93biBvbiBvbmUgcGFnZSBvbmx5LCBzbyBpdHMgcmVwb3J0IGJhclxuLy8gY2hhbmdlcyB3aXRoIHRoZSBwYWdlIG9uIHNjcmVlbi5cbmV4cG9ydCBmdW5jdGlvbiBoYXNQYWdlR3JvdXAocmVwb3J0OiBSZXBvcnQgfCBudWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiAocmVwb3J0Py5maWx0ZXJHcm91cHMgPz8gW10pLnNvbWUoKGdyb3VwKSA9PiBncm91cC5sZXZlbCA9PT0gJ3BhZ2UnKTtcbn1cblxuLy8gVGhlIHF1ZXJ5IGtleSBvZiB0aGUgcmVwb3J0IGJhcidzIE1hdGNoIGNvbnRyb2wuIE5vdCBhIGZpbHRlciBncm91cDogaXRcbi8vIHNheXMgaG93IHRoZSBncm91cHMgY29tYmluZSwgc28gaXQgaXMgcmVhZCBzdHJhaWdodCBvZmYgdGhlIGNoYW5nZSBxdWVyeS5cbi8vIEl0IGlzIGFsc28gdGhlIHJlcG9ydCBVUkwncyBrZXkgZm9yIHRoZSBtYXRjaCAobWF0Y2g9YW55KS5cbmV4cG9ydCBjb25zdCBNQVRDSF9JVEVNID0gJ21hdGNoJztcblxuY29uc3QgTUFUQ0hfT1BUSU9OUzogeyBuYW1lOiBzdHJpbmc7IHZhbHVlOiBSZXBvcnRGaWx0ZXJNYXRjaCB9W10gPSBbXG4gIHsgbmFtZTogJ0FsbCBmaWx0ZXJzJywgdmFsdWU6ICdhbGwnIH0sXG4gIHsgbmFtZTogJ0FueSBmaWx0ZXInLCB2YWx1ZTogJ2FueScgfSxcbl07XG5cbi8vIFRoZSByZXBvcnQgYmFyJ3MgTWF0Y2ggY29udHJvbCwgbGFzdCBpbiB0aGUgYmFyLCBvciBudWxsIHdoZW4gaXQgd291bGQgZG9cbi8vIG5vdGhpbmc6IHRoZSBzZXJ2ZXIgbXVzdCBzZXJ2ZSBtYXRjaEFueSwgYW5kIHRoZSBiYXIgbXVzdCBob2xkIHR3byBvciBtb3JlXG4vLyBncm91cHMgdGhhdCBjb21iaW5lIChhbiAnYW55JyBvdmVyIG9uZSBncm91cCBpcyB0aGF0IGdyb3VwKS5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaEZpbHRlckl0ZW0oXG4gIHJlcG9ydDogUmVwb3J0IHwgbnVsbCxcbiAgZ3JvdXBzOiBSZXBvcnRGaWx0ZXJHcm91cFtdLFxuICBwYWdlSWQ6IG51bWJlciB8IG51bGwsXG4gIG1hdGNoOiBSZXBvcnRGaWx0ZXJNYXRjaCxcbik6IElGaWx0ZXJDb25maWdJdGVtIHwgbnVsbCB7XG4gIGNvbnN0IGVsaWdpYmxlID0gZ3JvdXBzLmZpbHRlcigoZ3JvdXApID0+IGlzTWF0Y2hBbnlHcm91cChncm91cCwgcGFnZUlkKSk7XG5cbiAgaWYgKCFyZXBvcnQ/LnZpZXdlckZlYXR1cmVzPy5pbmNsdWRlcygnbWF0Y2hBbnknKSB8fCBlbGlnaWJsZS5sZW5ndGggPCAyKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6IE1BVENIX0lURU0sXG4gICAgdHlwZTogSXRlbVR5cGUuU2VsZWN0LFxuICAgIGxhYmVsOiAnTWF0Y2gnLFxuICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICB2YWx1ZXM6ICgpID0+IE1BVENIX09QVElPTlMsXG4gICAgZGVmYXVsdDogbWF0Y2gsXG4gICAgLy8gJ01hdGNoOiBhbnkgZmlsdGVyJyBvciAnTWF0Y2g6IGFsbCBmaWx0ZXJzJywgaW4gdGhlIGV4cG9ydCBsaW5lcycgd29yZHMuXG4gICAgY2hpcFRleHQ6IChpdGVtKSA9PiBtYXRjaExpbmVUZXh0KG1hdGNoRnJvbVF1ZXJ5KGl0ZW0ucXVlcnkpLCAnY2hpcCcpLFxuICB9O1xufVxuXG4vLyBUaGUgbWF0Y2ggYSBjaGFuZ2UgcXVlcnkgb2YgYSBiYXIgd2l0aCB0aGUgTWF0Y2ggY29udHJvbCBhc2tzIGZvci5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaEZyb21RdWVyeShxdWVyeTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBSZXBvcnRGaWx0ZXJNYXRjaCB7XG4gIHJldHVybiBxdWVyeT8uW01BVENIX0lURU1dID09PSAnYW55JyA/ICdhbnknIDogJ2FsbCc7XG59XG5cbi8vIFRoZSBxdWVyeSBrZXkgb2YgYSBsaXN0J3Mgc2VhcmNoIGJveCBpbiBpdHMgY29tcG9uZW50IGhlYWRlci4gRml4ZWQgcmF0aGVyXG4vLyB0aGFuIGRlcml2ZWQgZnJvbSBhbiBpZCBiZWNhdXNlIGEgaGVhZGVyIGhvbGRzIGF0IG1vc3Qgb25lLCBhbmQgaXQgaXMgTk9UIGFcbi8vIGZpbHRlciBncm91cDogaXRzIHRleHQgbmFycm93cyB0aGF0IGxpc3QgYWxvbmUsIHNvIGl0IGlzIHJlYWQgc3RyYWlnaHQgb2ZmXG4vLyB0aGUgY2hhbmdlIHF1ZXJ5IGFuZCB0cmF2ZWxzIGFzIHRoZSBsaXN0J3Mgb3duIGBzdGF0ZS5zZWFyY2hgLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX0lURU0gPSAnbGlzdFNlYXJjaCc7XG5cbi8vIFRoZSBsb25nZXN0IHNlYXJjaCB0aGUgc2VydmVyIGFwcGxpZXMgKFJlcG9ydFF1ZXJ5UnVubmVyOjpNQVhfU0VBUkNIX0xFTkdUSCkuXG4vLyBUaGUgdmlld2VyIGN1dHMgdGhlIHRleHQgdG8gaXQgdG9vLCBzbyB0aGUgVVJMLCB0aGUgcmVxdWVzdCBhbmQgdGhlIGV4cG9ydFxuLy8gdGl0bGUgYWxsIGNhcnJ5IHRoZSB0ZXh0IHRoYXQgd2FzIGFjdHVhbGx5IHNlYXJjaGVkLlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX01BWF9MRU5HVEggPSAxMDA7XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIGEgbGlzdCdzIHNlYXJjaCBib3gsIHNlZWRlZCB3aXRoIHRoZSB0ZXh0IHRoZVxuLy8gdmlld2VyIGxhc3Qgc2VhcmNoZWQuIGZzLWZpbHRlciBzaG93cyBvbmUgc2VhcmNoIGJveCBwZXIgYmFyIChpdHMgbGFzdFxuLy8ga2V5d29yZCBpdGVtKSwgc28gdGhlIGNhbGxlciBhZGRzIHRoaXMgb25seSB0byBhIGhlYWRlciB3aXRoIG5vIGtleXdvcmRcbi8vIGdyb3VwIG9mIGl0cyBvd24uXG5leHBvcnQgZnVuY3Rpb24gbGlzdFNlYXJjaEl0ZW0odmFsdWU6IHN0cmluZyB8IG51bGwpOiBJRmlsdGVyQ29uZmlnSXRlbSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogSXRlbVR5cGUuS2V5d29yZCxcbiAgICBuYW1lOiBMSVNUX1NFQVJDSF9JVEVNLFxuICAgIGxhYmVsOiAnU2VhcmNoJyxcbiAgICBkZWZhdWx0OiB2YWx1ZSA/PyB1bmRlZmluZWQsXG4gIH07XG59XG5cbi8vIFdoZXRoZXIgdGhlIHJlcG9ydCBoYXMgYSBjaGFydCB0aGUgZ3JvdXAtYnkgY29udHJvbCBjYW4gcmUtYnVja2V0LiBBIHRpbWVcbi8vIHgtYXhpcyBpcyB0aGUgd2hvbGUgcXVhbGlmaWNhdGlvbjogdGhlIGNvbnRyb2wgY2hhbmdlcyB0aGUgZ3JhaW4gb2YgdGhhdFxuLy8gYXhpcywgYW5kIGEgY2F0ZWdvcnkgYXhpcyBoYXMgbm8gZ3JhaW4gdG8gY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGhhc1RpbWVTZXJpZXNDaGFydChyZXBvcnQ6IFJlcG9ydCB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIChyZXBvcnQ/LnBhZ2VzID8/IFtdKS5zb21lKChwYWdlKSA9PiAocGFnZS5jb21wb25lbnRzID8/IFtdKS5zb21lKChjb21wb25lbnQpID0+XG4gICAgY29tcG9uZW50LnR5cGUgPT09ICdjaGFydCcgJiYgY29tcG9uZW50LmNvbmZpZz8ueEF4aXM/LmtpbmQgPT09ICd0aW1lJykpO1xufVxuXG4vLyBUaGUgZ3JhaW5zIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sIG9mZmVycywgbmFtZWQgZm9yIHRoZSB2aWV3ZXIuIFdISUNIXG4vLyBvZiB0aGVtIGNvbWVzIGZyb20gdGhlIHJlcG9ydDsgaG93IHRoZXkgcmVhZCBjb21lcyBmcm9tIEdSQU5VTEFSSVRZX09QVElPTlMuXG4vLyBBbiBlbXB0eSBzdG9yZWQgbGlzdCBtZWFucyBldmVyeSBncmFpbiDigJQgdGhlIHNhbWUgcnVsZSB0aGUgYmFja2VuZCBhcHBsaWVzLlxuZnVuY3Rpb24gZ3JvdXBCeU9wdGlvbnMocmVwb3J0OiBSZXBvcnQpOiB7IHZhbHVlOiBDaGFydEdyYW51bGFyaXR5OyBuYW1lOiBzdHJpbmcgfVtdIHtcbiAgY29uc3QgZ3JhbnVsYXJpdGllcyA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk/LmdyYW51bGFyaXRpZXMgPz8gW107XG5cbiAgcmV0dXJuIGdyYW51bGFyaXRpZXMubGVuZ3RoXG4gICAgPyBHUkFOVUxBUklUWV9PUFRJT05TLmZpbHRlcigob3B0aW9uKSA9PiBncmFudWxhcml0aWVzLmluY2x1ZGVzKG9wdGlvbi52YWx1ZSkpXG4gICAgOiBHUkFOVUxBUklUWV9PUFRJT05TO1xufVxuXG4vLyBXaGV0aGVyIGEgZ3JhaW4gaXMgb25lIHRoZSByZXBvcnQncyBjb250cm9sIHN0aWxsIG9mZmVycy4gQSBncmFpbiBpdCBkb2Vzbid0XG4vLyBjYW5ub3Qgc3RheSBpbiBlZmZlY3Q6IHRoZSBhZ2VudCBjYW4gbmFycm93IHRoZSBsaXN0IGF0IGFueSB0aW1lLCBhbmQgYSBjaGFydFxuLy8gbGVmdCBidWNrZXRpbmcgYXQgYSBkcm9wcGVkIGdyYWluIGlzIG9uZSB0aGUgdmlld2VyIGNhbiBuZWl0aGVyIHNlZSBub3IgY2hhbmdlLlxuZXhwb3J0IGZ1bmN0aW9uIGlzR3JhbnVsYXJpdHlPZmZlcmVkKHJlcG9ydDogUmVwb3J0LCBncmFudWxhcml0eTogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuICFncmFudWxhcml0eSB8fCBncm91cEJ5T3B0aW9ucyhyZXBvcnQpLnNvbWUoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlID09PSBncmFudWxhcml0eSk7XG59XG5cbi8vIFRoZSBmcy1maWx0ZXIgY29uZmlnIGl0ZW0gZm9yIHRoZSByZXBvcnQncyBncm91cC1ieSBjb250cm9sLCBvciBudWxsIHdoZW4gdGhlXG4vLyByZXBvcnQgaGFzIG5vbmUgdG8gc2hvdy5cbi8vXG4vLyBJdCBsZWFkcyB0aGUgc2FtZSBiYXIgdGhlIGZpbHRlcnMgcmVuZGVyIGluLCBidXQgaXQgaXMgTk9UIG9uZTogYSBmaWx0ZXJcbi8vIG5hcnJvd3MgV0hJQ0ggcm93cyBhcmUgY291bnRlZCwgdGhpcyBjaGFuZ2VzIGhvdyB0aGUgc3Vydml2aW5nIHJvd3MgYXJlXG4vLyBCVUNLRVRFRCDigJQgYW5kIGl0IGNvbWVzIGZpcnN0IGJlY2F1c2UgdGhlIGdyYWluIGlzIHdoYXQgYSB2aWV3ZXIgc2V0dGxlc1xuLy8gYmVmb3JlIGRlY2lkaW5nIHdoaWNoIHJvd3MgdGhleSB3YW50LlxuLy8gUGlja2luZyBhIGdyYWluIHNldHMgYSBzZXNzaW9uLXdpZGUgb3ZlcnJpZGUgdGhhdCByaWRlcyBhbG9uZyBpbiBlYWNoIGNoYXJ0J3Ncbi8vIGRhdGEgcmVxdWVzdCwgc28gdGhlIGNoYXJ0cyB0aGVtc2VsdmVzIGFyZSBuZXZlciByZXdyaXR0ZW4uXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBCeUZpbHRlckl0ZW0oXG4gIHJlcG9ydDogUmVwb3J0LFxuICBpbml0aWFsPzogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwsXG4pOiBJRmlsdGVyQ29uZmlnSXRlbSB8IG51bGwge1xuICBjb25zdCBncm91cEJ5ID0gcmVwb3J0LmNvbmZpZz8uZ3JvdXBCeTtcblxuICAvLyBPbmx5IGFuIEVYUExJQ0lUIGZhbHNlIGhpZGVzIHRoZSBjb250cm9sLiBBbiBhYnNlbnQgYmxvY2sgbWVhbnMgYSByZXBvcnRcbiAgLy8gc2VydmVkIGJ5IGEgYnVpbGQgdGhhdCBwcmVkYXRlcyB0aGUgY29udHJvbCBiZWluZyBzdG9yZWQsIGFuZCBldmVyeSBvbmUgb2ZcbiAgLy8gdGhvc2UgaGFkIG9uZSDigJQgdGhlIGJhY2tlbmQgcmVzb2x2ZXMgaXQgdGhlIHNhbWUgd2F5IChSZXBvcnRHcm91cEJ5KS5cbiAgaWYgKGdyb3VwQnk/LmVuYWJsZWQgPT09IGZhbHNlIHx8ICFoYXNUaW1lU2VyaWVzQ2hhcnQocmVwb3J0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdmFsdWVzID0gZ3JvdXBCeU9wdGlvbnMocmVwb3J0KTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6IEdST1VQX0JZX0lURU0sXG4gICAgdHlwZTogSXRlbVR5cGUuU2VsZWN0LFxuICAgIGxhYmVsOiBncm91cEJ5Py5sYWJlbCB8fCAnR3JvdXAgQnknLFxuICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICB2YWx1ZXM6ICgpID0+IHZhbHVlcyxcbiAgICBkZWZhdWx0OiBpc0dyYW51bGFyaXR5T2ZmZXJlZChyZXBvcnQsIGluaXRpYWwgPz8gbnVsbCkgPyAoaW5pdGlhbCA/PyB1bmRlZmluZWQpIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vLyBUaGUgZ3JvdXAtYnkgY29udHJvbCdzIGNvbnRyaWJ1dGlvbiB0byB0aGUgdG9vbGJhcidzIGZzLWZpbHRlciBrZXkuIGZzLWZpbHRlclxuLy8gcmVhZHMgaXRzIGNvbmZpZyBvbmNlIGF0IGluaXQsIGFuZCB0aGUgYWdlbnQgY2FuIGNoYW5nZSB0aGUgY29udHJvbCdzIGxhYmVsXG4vLyBvciB0aGUgZ3JhaW5zIGl0IG9mZmVycyDigJQgd2l0aG91dCB0aG9zZSBpbiB0aGUga2V5IHRoZSBiYXIga2VlcHMgcmVuZGVyaW5nXG4vLyB0aGUgY29udHJvbCBpdCB3YXMgY3JlYXRlZCB3aXRoIHVudGlsIGEgZnVsbCBwYWdlIHJlbG9hZC5cbmV4cG9ydCBmdW5jdGlvbiBncm91cEJ5U2lnbmF0dXJlKHJlcG9ydDogUmVwb3J0IHwgbnVsbCk6IHN0cmluZyB7XG4gIGlmICghcmVwb3J0IHx8ICFncm91cEJ5RmlsdGVySXRlbShyZXBvcnQpKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3QgZ3JvdXBCeSA9IHJlcG9ydC5jb25maWc/Lmdyb3VwQnk7XG5cbiAgcmV0dXJuIFsnZ3JvdXBCeScsIGdyb3VwQnk/LmxhYmVsID8/ICcnLCAoZ3JvdXBCeT8uZ3JhbnVsYXJpdGllcyA/PyBbXSkuam9pbignLCcpXS5qb2luKCc6Jyk7XG59XG5cbi8vIFJlYWQgYW4gZnMtZmlsdGVyIGNoYW5nZSBxdWVyeSBpbnRvIHBlci1ncm91cCB2YWx1ZXMuIFJldHVybnMgb25lIGVudHJ5IHBlclxuLy8gZ3JvdXAgd2l0aCB0aGUgdmFsdWUgdG8gc3RvcmUgKG9yIG51bGwgdG8gY2xlYXIpIOKAlCBjYWxsZXJzIGZlZWQgdGhlc2UgdG9cbi8vIFJlcG9ydEZpbHRlclN0YXRlU2VydmljZS5zZXRWYWx1ZS4gYHJlcG9ydGAgbmFtZXMgdGhlIGdyb3VwcycgaXRlbXMuXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBWYWx1ZXNGcm9tUXVlcnkoXG4gIHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBncm91cHM6IFJlcG9ydEZpbHRlckdyb3VwW10sXG4gIHJlcG9ydDogUmVwb3J0IHwgbnVsbCxcbik6IHsgZ3JvdXBJZDogbnVtYmVyOyB2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwgfVtdIHtcbiAgcmV0dXJuIGdyb3Vwcy5tYXAoKGdyb3VwKSA9PiB7XG4gICAgY29uc3QgbmFtZSA9IGdyb3VwSXRlbU5hbWUoZ3JvdXAsIHJlcG9ydCk7XG5cbiAgICBzd2l0Y2ggKGdyb3VwLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICAgIHJldHVybiB7IGdyb3VwSWQ6IGdyb3VwLmlkLCB2YWx1ZTogZGF0ZVJhbmdlRnJvbVF1ZXJ5KHF1ZXJ5LCBuYW1lKSB9O1xuXG4gICAgICBjYXNlICdzZWxlY3QnOlxuICAgICAgICByZXR1cm4geyBncm91cElkOiBncm91cC5pZCwgdmFsdWU6IHNlbGVjdEZyb21RdWVyeShxdWVyeSwgbmFtZSkgfTtcblxuICAgICAgY2FzZSAnbnVtYmVyUmFuZ2UnOlxuICAgICAgICByZXR1cm4geyBncm91cElkOiBncm91cC5pZCwgdmFsdWU6IG51bWJlclJhbmdlRnJvbVF1ZXJ5KHF1ZXJ5LCBuYW1lKSB9O1xuXG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIGNvbnN0IGtleXdvcmQgPSBTdHJpbmcocXVlcnlbbmFtZV0gPz8gJycpLnRyaW0oKTtcblxuICAgICAgICByZXR1cm4geyBncm91cElkOiBncm91cC5pZCwgdmFsdWU6IGtleXdvcmQgPyB7IHZhbHVlOiBrZXl3b3JkIH0gOiBudWxsIH07XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuLy8gQSBkYXRlIHJhbmdlJ3MgZGF5cyAoPGtleT5Gcm9tLCA8a2V5PlRvKS5cbmZ1bmN0aW9uIGRhdGVSYW5nZUZyb21RdWVyeShxdWVyeTogUmVjb3JkPHN0cmluZywgYW55PiwgbmFtZTogc3RyaW5nKTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwge1xuICBjb25zdCBzdGFydCA9IHF1ZXJ5W2l0ZW1SYW5nZU5hbWUobmFtZSwgJ2Zyb20nKV07XG4gIGNvbnN0IGVuZCA9IHF1ZXJ5W2l0ZW1SYW5nZU5hbWUobmFtZSwgJ3RvJyldO1xuXG4gIGlmICghc3RhcnQgJiYgIWVuZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHsgc3RhcnQ6IHN0YXJ0IHx8IG51bGwsIGVuZDogZW5kIHx8IG51bGwgfTtcbn1cblxuLy8gQSBzZWxlY3QncyBwaWNrczoga2VwdCAoPGtleT4pLCBvciBsZWZ0IG91dCB3aGlsZSBpdHMgZXhjbHVkZSByb3cgaXMgb25cbi8vIChleGNsdWRlPEtleT4pLlxuZnVuY3Rpb24gc2VsZWN0RnJvbVF1ZXJ5KHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBuYW1lOiBzdHJpbmcpOiBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbCB7XG4gIGNvbnN0IGV4Y2x1ZGVWYWx1ZXMgPSBzZWxlY3RRdWVyeVZhbHVlcyhxdWVyeVtnZXRFeGNsdWRlTmFtZShuYW1lKV0pO1xuICBpZiAoZXhjbHVkZVZhbHVlcy5sZW5ndGgpIHtcbiAgICByZXR1cm4geyBleGNsdWRlVmFsdWVzIH07XG4gIH1cblxuICBjb25zdCB2YWx1ZXMgPSBzZWxlY3RRdWVyeVZhbHVlcyhxdWVyeVtuYW1lXSk7XG5cbiAgcmV0dXJuIHZhbHVlcy5sZW5ndGggPyB7IHZhbHVlcyB9IDogbnVsbDtcbn1cblxuLy8gQSBudW1iZXIgcmFuZ2UncyBlbmRzICg8a2V5Pk1pbiwgPGtleT5NYXgpLiBBbiBlbmQgbGVmdCBlbXB0eSBpcyBvcGVuLlxuZnVuY3Rpb24gbnVtYmVyUmFuZ2VGcm9tUXVlcnkocXVlcnk6IFJlY29yZDxzdHJpbmcsIGFueT4sIG5hbWU6IHN0cmluZyk6IEZpbHRlckdyb3VwVmFsdWUgfCBudWxsIHtcbiAgY29uc3QgbWluID0gcmFuZ2VCb3VuZChxdWVyeVtpdGVtUmFuZ2VOYW1lKG5hbWUsICdtaW4nKV0pO1xuICBjb25zdCBtYXggPSByYW5nZUJvdW5kKHF1ZXJ5W2l0ZW1SYW5nZU5hbWUobmFtZSwgJ21heCcpXSk7XG5cbiAgaWYgKG1pbiA9PT0gbnVsbCAmJiBtYXggPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uKG1pbiAhPT0gbnVsbCA/IHsgbWluIH0gOiB7fSksXG4gICAgLi4uKG1heCAhPT0gbnVsbCA/IHsgbWF4IH0gOiB7fSksXG4gIH07XG59XG5cbi8vIE9uZSBlbmQgb2YgYSBudW1iZXIgcmFuZ2UgYXMgZnMtZmlsdGVyJ3MgUmFuZ2Ugc2VuZHMgaXQ6IHRoZSB0ZXh0IHR5cGVkIGluXG4vLyBpdHMgaW5wdXQuIE51bWJlcigpIHJlYWRzIGFueSBub24tZW1wdHkgdGV4dCwgc28gJzAnIGlzIHRoZSBlbmQgMDsgZW1wdHkgb3Jcbi8vIHVucmVhZGFibGUgdGV4dCBpcyBhbiBvcGVuIGVuZC5cbmZ1bmN0aW9uIHJhbmdlQm91bmQocmF3OiB1bmtub3duKTogbnVtYmVyIHwgbnVsbCB7XG4gIGNvbnN0IHRleHQgPSB0eXBlb2YgcmF3ID09PSAnbnVtYmVyJyA/IFN0cmluZyhyYXcpIDogU3RyaW5nKHJhdyA/PyAnJykudHJpbSgpO1xuICBjb25zdCBudW1iZXIgPSB0ZXh0ID09PSAnJyA/IE5hTiA6IE51bWJlcih0ZXh0KTtcblxuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKG51bWJlcikgPyBudW1iZXIgOiBudWxsO1xufVxuXG4vLyBBIGdyb3VwIHZhbHVlIGFzIHRleHQsIHRoZSBzYW1lIGZvciB0aGUgc2FtZSB2YWx1ZSB3aGF0ZXZlciBpdHMgc291cmNlOlxuLy8gZGF5cyBhcyBjYWxlbmRhciBkYXlzLCBwaWNrcyBhbmQgZW5kcyBhcyB0ZXh0LCBrZXl3b3JkIHRleHQgdHJpbW1lZC4gVGhlXG4vLyB2YWx1ZSBhIHRpbGUgaGVhZGVyIHdhcyBidWlsdCB3aXRoIGlzIGtleWVkIG9uIGl0LCBzbyBhIGhlYWRlciBpcyBjcmVhdGVkXG4vLyBhZ2FpbiB3aGVuIGFub3RoZXIgYmFyIGNoYW5nZXMgYSBncm91cCBpdCBzaG93cy5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFZhbHVlU2lnbmF0dXJlKHZhbHVlOiBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoW1xuICAgIGRhdGVCb3VuZFN0cmluZyh2YWx1ZS5zdGFydCkgPz8gJycsXG4gICAgZGF0ZUJvdW5kU3RyaW5nKHZhbHVlLmVuZCkgPz8gJycsXG4gICAgKHZhbHVlLnZhbHVlcyA/PyBbXSkubWFwKFN0cmluZyksXG4gICAgKHZhbHVlLmV4Y2x1ZGVWYWx1ZXMgPz8gW10pLm1hcChTdHJpbmcpLFxuICAgICh2YWx1ZS52YWx1ZSA/PyAnJykudHJpbSgpLFxuICAgIHZhbHVlLm1pbiA/PyAnJyxcbiAgICB2YWx1ZS5tYXggPz8gJycsXG4gIF0pO1xufVxuXG4vLyBmcy1maWx0ZXIncyBBdXRvQ29tcGxldGVDaGlwcyBzZXJpYWxpc2VzIGEgbXVsdGktc2VsZWN0IGludG8gT05FIHF1ZXJ5IHZhbHVlOlxuLy8gdGhlIHNlbGVjdGVkIHZhbHVlcyBqb2luZWQgYnkgXCIsXCIgKGl0cyBgcXVlcnlgIGdldHRlciBkb2VzIGAubWFwKHZhbHVlKS5qb2luKCcsJylgKS5cbi8vIFNvIGEgMisgc2VsZWN0aW9uIGFycml2ZXMgYXMgdGhlIHN0cmluZyBcImEsYlwiLCBub3QgYW4gYXJyYXkg4oCUIHNwbGl0dGluZyBvbiBcIixcIlxuLy8gcmV2ZXJzZXMgdGhhdCBmYWl0aGZ1bGx5LiBXaXRob3V0IHRoaXMsIGEgbXVsdGktc2VsZWN0IHdhcyBzZW50IGFzIHRoZSBzaW5nbGVcbi8vIHZhbHVlIFtcImEsYlwiXSwgcHJvZHVjaW5nIGBjb2wgSU4gKCdhLGInKWAgc2VydmVyLXNpZGUsIHdoaWNoIG1hdGNoZXMgbm90aGluZy5cbmZ1bmN0aW9uIHNlbGVjdFF1ZXJ5VmFsdWVzKHJhdzogdW5rbm93bik6IHVua25vd25bXSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHtcbiAgICByZXR1cm4gcmF3O1xuICB9XG5cbiAgaWYgKHJhdyA9PT0gbnVsbCB8fCByYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIFN0cmluZyhyYXcpLnNwbGl0KCcsJyk7XG59XG4iXX0=
|