@firestitch/report 18.6.1 → 18.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/reports/components/component-chart/component-chart.component.d.ts +6 -7
- package/app/reports/components/component-kpi/component-kpi.component.d.ts +17 -9
- package/app/reports/components/component-kpi/components/sparkline/sparkline.component.d.ts +8 -0
- package/app/reports/components/component-list/component-list.component.d.ts +39 -10
- package/app/reports/components/component-note/component-note.component.d.ts +12 -0
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +0 -10
- package/app/reports/components/report-component/report-component.component.d.ts +5 -12
- package/app/reports/data/report.data.d.ts +2 -3
- package/app/reports/dialogs/component-settings/component-settings.component.d.ts +34 -2
- package/app/reports/dialogs/list-columns/list-columns.component.d.ts +23 -0
- package/app/reports/dialogs/report-settings/report-locale-patch.d.ts +5 -0
- package/app/reports/dialogs/report-settings/report-settings.component.d.ts +20 -2
- package/app/reports/enums/report-change-polarity.enum.d.ts +5 -0
- package/app/reports/enums/report-chart-color.enum.d.ts +12 -0
- package/app/reports/enums/report-chart-data-labels.enum.d.ts +6 -0
- package/app/reports/enums/report-chart-date-label.enum.d.ts +5 -0
- package/app/reports/enums/report-chart-line-style.enum.d.ts +5 -0
- package/app/reports/enums/report-chart-mark-stat.enum.d.ts +6 -0
- package/app/reports/enums/report-kpi-trend.enum.d.ts +5 -0
- package/app/reports/enums/report-list-column-format.enum.d.ts +6 -0
- package/app/reports/enums/report-number-units.enum.d.ts +6 -0
- package/app/reports/enums/report-value-format.enum.d.ts +5 -0
- package/app/reports/export/offscreen-chart.d.ts +2 -2
- package/app/reports/export/report-export-collector.service.d.ts +37 -8
- package/app/reports/export/report-pdf.service.d.ts +6 -0
- package/app/reports/export/report-pptx.service.d.ts +24 -0
- package/app/reports/format.d.ts +64 -3
- package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +2 -0
- package/app/reports/interfaces/report.interface.d.ts +205 -14
- package/app/reports/kpi-card.d.ts +48 -0
- package/app/reports/layout.d.ts +0 -9
- package/app/reports/list-config.d.ts +16 -0
- package/app/reports/option-builder.d.ts +76 -9
- package/app/reports/output-notes.d.ts +14 -0
- package/app/reports/pipes/report-date.pipe.d.ts +2 -1
- package/app/reports/pipes/report-number.pipe.d.ts +8 -0
- package/app/reports/pipes/report-output.pipe.d.ts +10 -0
- package/app/reports/report-filter-items.d.ts +5 -2
- package/app/reports/report-url-state.d.ts +4 -0
- package/app/reports/services/report-filter-state.service.d.ts +27 -2
- package/app/reports/theme/palette.d.ts +6 -0
- package/app/reports/theme/typography.d.ts +2 -0
- package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +23 -20
- package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +56 -29
- package/esm2022/app/reports/components/component-kpi/components/sparkline/sparkline.component.mjs +19 -0
- package/esm2022/app/reports/components/component-list/component-list.component.mjs +218 -32
- package/esm2022/app/reports/components/component-note/component-note.component.mjs +30 -0
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +7 -61
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +99 -100
- package/esm2022/app/reports/data/report.data.mjs +20 -7
- package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +133 -13
- package/esm2022/app/reports/dialogs/list-columns/list-columns.component.mjs +56 -0
- package/esm2022/app/reports/dialogs/report-settings/report-locale-patch.mjs +13 -0
- package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +138 -20
- package/esm2022/app/reports/enums/report-change-polarity.enum.mjs +11 -0
- package/esm2022/app/reports/enums/report-chart-color.enum.mjs +19 -0
- package/esm2022/app/reports/enums/report-chart-data-labels.enum.mjs +13 -0
- package/esm2022/app/reports/enums/report-chart-date-label.enum.mjs +13 -0
- package/esm2022/app/reports/enums/report-chart-line-style.enum.mjs +12 -0
- package/esm2022/app/reports/enums/report-chart-mark-stat.enum.mjs +12 -0
- package/esm2022/app/reports/enums/report-kpi-trend.enum.mjs +10 -0
- package/esm2022/app/reports/enums/report-list-column-format.enum.mjs +14 -0
- package/esm2022/app/reports/enums/report-number-units.enum.mjs +14 -0
- package/esm2022/app/reports/enums/report-value-format.enum.mjs +13 -0
- package/esm2022/app/reports/export/offscreen-chart.mjs +5 -4
- package/esm2022/app/reports/export/report-export-collector.service.mjs +186 -40
- package/esm2022/app/reports/export/report-pdf.service.mjs +332 -67
- package/esm2022/app/reports/export/report-pptx.service.mjs +765 -106
- package/esm2022/app/reports/format.mjs +917 -57
- package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
- package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
- package/esm2022/app/reports/kpi-card.mjs +174 -0
- package/esm2022/app/reports/layout.mjs +1 -46
- package/esm2022/app/reports/list-config.mjs +106 -0
- package/esm2022/app/reports/option-builder.mjs +1457 -117
- package/esm2022/app/reports/output-notes.mjs +158 -0
- package/esm2022/app/reports/pipes/report-date.pipe.mjs +7 -6
- package/esm2022/app/reports/pipes/report-number.pipe.mjs +25 -0
- package/esm2022/app/reports/pipes/report-output.pipe.mjs +28 -0
- package/esm2022/app/reports/report-filter-items.mjs +28 -3
- package/esm2022/app/reports/report-url-state.mjs +56 -15
- package/esm2022/app/reports/services/report-filter-state.service.mjs +274 -22
- package/esm2022/app/reports/theme/echarts.mjs +8 -2
- package/esm2022/app/reports/theme/palette.mjs +35 -1
- package/esm2022/app/reports/theme/typography.mjs +8 -1
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +2 -2
- package/esm2022/app/reports/views/report/report.component.mjs +3 -4
- package/esm2022/public_api.mjs +10 -1
- package/fesm2022/{firestitch-report-echarts-Djtmaxj1.mjs → firestitch-report-echarts-qCBE3LqM.mjs} +9 -3
- package/fesm2022/firestitch-report-echarts-qCBE3LqM.mjs.map +1 -0
- package/fesm2022/{firestitch-report-firestitch-report-D3zseBZc.mjs → firestitch-report-firestitch-report-DbsWbE-j.mjs} +5523 -875
- package/fesm2022/firestitch-report-firestitch-report-DbsWbE-j.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +9 -0
- package/fesm2022/firestitch-report-echarts-Djtmaxj1.mjs.map +0 -1
- package/fesm2022/firestitch-report-firestitch-report-D3zseBZc.mjs.map +0 -1
|
@@ -1,55 +1,620 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isValid, parseISO } from 'date-fns';
|
|
2
2
|
import { formatInTimeZone, toZonedTime } from 'date-fns-tz';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
3
|
+
import { ReportListColumnFormat } from './enums/report-list-column-format.enum';
|
|
4
|
+
import { ReportNumberUnits } from './enums/report-number-units.enum';
|
|
5
|
+
import { ReportValueFormat } from './enums/report-value-format.enum';
|
|
6
|
+
// What a report reads when the server names no usable locale or currency: an
|
|
7
|
+
// older server that sends neither, or a value this browser's Intl cannot use.
|
|
8
|
+
// Never the browser's own locale, so every viewer of a report sees the same text.
|
|
9
|
+
export const REPORT_FALLBACK_LOCALE = 'en-US';
|
|
10
|
+
export const REPORT_FALLBACK_CURRENCY = 'USD';
|
|
11
|
+
export const DEFAULT_FORMAT_CONTEXT = Object.freeze({
|
|
12
|
+
locale: REPORT_FALLBACK_LOCALE,
|
|
13
|
+
currency: REPORT_FALLBACK_CURRENCY,
|
|
14
|
+
ratioPercent: true,
|
|
15
|
+
});
|
|
16
|
+
const CURRENCY_PATTERN = /^[A-Z]{3}$/;
|
|
17
|
+
// The server's resolved locale as one this browser can format in. A malformed
|
|
18
|
+
// tag ('en_CA') makes supportedLocalesOf throw, and one Intl has no data for
|
|
19
|
+
// ('xx-YY') comes back empty; both read the fallback.
|
|
20
|
+
export function resolveReportLocale(tag) {
|
|
21
|
+
if (!tag) {
|
|
22
|
+
return REPORT_FALLBACK_LOCALE;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
return Intl.NumberFormat.supportedLocalesOf([tag])[0] ?? REPORT_FALLBACK_LOCALE;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return REPORT_FALLBACK_LOCALE;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// The server's resolved currency as one Intl can label. The server decides
|
|
32
|
+
// which codes name money; this only guards against a code Intl cannot take at
|
|
33
|
+
// all. It is never checked against the runtime's own currency list, which
|
|
34
|
+
// differs between browsers and leaves out codes the server offers (VEF, MRO),
|
|
35
|
+
// so every viewer labels a report's money the same way.
|
|
36
|
+
export function resolveReportCurrency(code) {
|
|
37
|
+
if (!code || !CURRENCY_PATTERN.test(code)) {
|
|
38
|
+
return REPORT_FALLBACK_CURRENCY;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
numberFormat(REPORT_FALLBACK_LOCALE, { style: 'currency', currency: code });
|
|
42
|
+
return code;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return REPORT_FALLBACK_CURRENCY;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// The one place a report's format context is built: the server's effective
|
|
49
|
+
// locale and currency (absent on an older server, which then reads en-US/USD)
|
|
50
|
+
// and whether its percent measures arrive as 0-1 ratios.
|
|
51
|
+
export function resolveFormatContext(report) {
|
|
52
|
+
return {
|
|
53
|
+
locale: resolveReportLocale(report.effectiveLocale),
|
|
54
|
+
currency: resolveReportCurrency(report.effectiveCurrency),
|
|
55
|
+
ratioPercent: report.percentFormat === 'ratio',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Building an Intl formatter is far slower than using one, and a chart formats
|
|
59
|
+
// every tick and tooltip value, so each distinct locale + options (+ zone) is
|
|
60
|
+
// built once and reused.
|
|
61
|
+
const NUMBER_FORMATS = new Map();
|
|
62
|
+
const DATE_FORMATS = new Map();
|
|
63
|
+
export function numberFormat(locale, options) {
|
|
64
|
+
const key = `${locale}|${JSON.stringify(options)}`;
|
|
65
|
+
let formatter = NUMBER_FORMATS.get(key);
|
|
66
|
+
if (!formatter) {
|
|
67
|
+
formatter = new Intl.NumberFormat(locale, options);
|
|
68
|
+
NUMBER_FORMATS.set(key, formatter);
|
|
69
|
+
}
|
|
70
|
+
return formatter;
|
|
71
|
+
}
|
|
72
|
+
// No zone formats in the browser's own zone, which is right for a calendar day
|
|
73
|
+
// parsed as local midnight: the day printed is the day stored.
|
|
74
|
+
export function dateFormat(locale, options, timeZone) {
|
|
75
|
+
const key = `${locale}|${JSON.stringify(options)}|${timeZone ?? ''}`;
|
|
76
|
+
let formatter = DATE_FORMATS.get(key);
|
|
77
|
+
if (!formatter) {
|
|
78
|
+
formatter = new Intl.DateTimeFormat(locale, { ...options, timeZone });
|
|
79
|
+
DATE_FORMATS.set(key, formatter);
|
|
80
|
+
}
|
|
81
|
+
return formatter;
|
|
82
|
+
}
|
|
83
|
+
// Number formatting: the one engine behind every numeric slot (a chart
|
|
84
|
+
// measure, a KPI measure, a list column, a cross-tab's cells), so a format
|
|
85
|
+
// means the same thing on screen, in the PDF and in PowerPoint. The data stays
|
|
86
|
+
// raw; only what is shown changes. The rules:
|
|
87
|
+
// - Empty: null, undefined, '', '-' and a non-finite number print the caller's
|
|
88
|
+
// `empty` ('—' unless it names another).
|
|
89
|
+
// - Numeric: a finite number, or a string that spells one plainly ('1234.50',
|
|
90
|
+
// '-3e2'). Anything else ('$1,234', an id with letters, ' ') prints as it
|
|
91
|
+
// came, since a column the SQL already formatted is text.
|
|
92
|
+
// - Styles: number is a plain decimal; currency is the report's currency
|
|
93
|
+
// written in its locale with its symbol (USD reads '$1,235' in en-US and
|
|
94
|
+
// 'US$1,235' in en-CA; EUR reads '1 235 €' in fr-FR); percent takes a 0-1
|
|
95
|
+
// ratio (0.3 reads 30%), or, from an older server that sends percent values
|
|
96
|
+
// already x100, a decimal with a % sign. Precision or units without a format
|
|
97
|
+
// mean number.
|
|
98
|
+
// - Decimals: a precision pins both the minimum and the maximum, so a column
|
|
99
|
+
// of rates lines up. Without one: at most one for a percent and for an
|
|
100
|
+
// abbreviated value (1.2K), whole units for currency, the locale's default
|
|
101
|
+
// for a number.
|
|
102
|
+
// - Units: thousands and millions divide and add a K or M after the digits
|
|
103
|
+
// ('$1.2K', '1,2K $'); auto picks per value by size, and a value that would
|
|
104
|
+
// round to 1000K reads 1M. Units never apply to a percent.
|
|
105
|
+
// - Negatives keep the locale's leading minus. A negative that rounds to zero
|
|
106
|
+
// prints as zero, never '-0'.
|
|
107
|
+
// - Rounding is Intl's, on the digits shown. Every value is written in the
|
|
108
|
+
// context's locale, never the browser's.
|
|
109
|
+
// The most decimals a precision pins: the server's schema bound.
|
|
110
|
+
const MAX_PRECISION = 6;
|
|
111
|
+
// At most one decimal for a percent, and for an abbreviated value (1.2K).
|
|
112
|
+
const PERCENT_DECIMALS = 1;
|
|
113
|
+
const SCALED_DECIMALS = 1;
|
|
114
|
+
// Money shows whole units unless a precision asks for decimals.
|
|
115
|
+
const CURRENCY_DECIMALS = 0;
|
|
116
|
+
// A currency axis whose ticks need decimals shows cents, not tenths.
|
|
117
|
+
const CURRENCY_AXIS_DECIMALS = 2;
|
|
118
|
+
// What a missing value prints unless the caller names its own.
|
|
119
|
+
const EMPTY_VALUE = '—';
|
|
120
|
+
// The tick count a value axis aims for, as ECharts' splitNumber default.
|
|
121
|
+
const AXIS_TICKS = 5;
|
|
122
|
+
// A change's sign: a plus on a positive value, nothing on zero.
|
|
123
|
+
const SIGNED = { signDisplay: 'exceptZero' };
|
|
124
|
+
const NUMERIC_PATTERN = /^\s*[-+]?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?\s*$/;
|
|
125
|
+
// The formatToParts types that carry a number's digits and separators.
|
|
126
|
+
const NUMBER_PARTS = new Set(['integer', 'group', 'decimal', 'fraction']);
|
|
127
|
+
const DIGIT_PARTS = new Set(['integer', 'fraction']);
|
|
128
|
+
const UNIT_SCALES = new Map([
|
|
129
|
+
[ReportNumberUnits.Thousands, { divisor: 1e3, suffix: 'K', commas: ',' }],
|
|
130
|
+
[ReportNumberUnits.Millions, { divisor: 1e6, suffix: 'M', commas: ',,' }],
|
|
131
|
+
]);
|
|
132
|
+
// The value as a finite number when it is one or plainly spells one, else
|
|
133
|
+
// null.
|
|
134
|
+
export function toFiniteNumber(value) {
|
|
135
|
+
if (typeof value === 'number') {
|
|
136
|
+
return Number.isFinite(value) ? value : null;
|
|
137
|
+
}
|
|
138
|
+
if (typeof value !== 'string' || !NUMERIC_PATTERN.test(value)) {
|
|
139
|
+
return null;
|
|
25
140
|
}
|
|
26
141
|
const numeric = Number(value);
|
|
27
|
-
|
|
142
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
143
|
+
}
|
|
144
|
+
// Whether a slot asks to be formatted at all. A slot without these keys, or a
|
|
145
|
+
// list column whose format is date, keeps its own rendering. Units none is the
|
|
146
|
+
// same as no units key, as it is on the server.
|
|
147
|
+
export function hasNumberFormat(spec) {
|
|
148
|
+
if (!spec || spec.format === ReportListColumnFormat.Date) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return valueFormat(spec) !== null
|
|
152
|
+
|| (spec.precision ?? null) !== null
|
|
153
|
+
|| ((spec.units ?? ReportNumberUnits.None) !== ReportNumberUnits.None);
|
|
154
|
+
}
|
|
155
|
+
// The units a value is written in. auto decides by the magnitude: a million
|
|
156
|
+
// and up reads M, a thousand and up K, unless the value would then round to
|
|
157
|
+
// 1000K at these decimals, which reads 1M instead.
|
|
158
|
+
export function resolveUnits(units, magnitude, decimals) {
|
|
159
|
+
switch (units) {
|
|
160
|
+
case ReportNumberUnits.Thousands:
|
|
161
|
+
case ReportNumberUnits.Millions:
|
|
162
|
+
return units;
|
|
163
|
+
case ReportNumberUnits.Auto:
|
|
164
|
+
return autoUnits(Math.abs(magnitude), decimals);
|
|
165
|
+
default:
|
|
166
|
+
return ReportNumberUnits.None;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function autoUnits(magnitude, decimals) {
|
|
170
|
+
if (magnitude >= 1e6) {
|
|
171
|
+
return ReportNumberUnits.Millions;
|
|
172
|
+
}
|
|
173
|
+
if (magnitude < 1e3) {
|
|
174
|
+
return ReportNumberUnits.None;
|
|
175
|
+
}
|
|
176
|
+
return roundTo(magnitude / 1e3, decimals) >= 1000
|
|
177
|
+
? ReportNumberUnits.Millions
|
|
178
|
+
: ReportNumberUnits.Thousands;
|
|
179
|
+
}
|
|
180
|
+
// The value rounded as Intl rounds it for display, so the K-to-M promotion
|
|
181
|
+
// agrees with the digits actually shown.
|
|
182
|
+
function roundTo(value, decimals) {
|
|
183
|
+
const digits = clampDecimals(decimals) ?? 0;
|
|
184
|
+
// A fixed locale only so Number() can parse the rounded digits back.
|
|
185
|
+
return Number(numberFormat(REPORT_FALLBACK_LOCALE, {
|
|
186
|
+
useGrouping: false,
|
|
187
|
+
minimumFractionDigits: 0,
|
|
188
|
+
maximumFractionDigits: digits,
|
|
189
|
+
}).format(value));
|
|
190
|
+
}
|
|
191
|
+
// One value, written by the rules above.
|
|
192
|
+
export function formatNumber(value, spec, context, options = {}) {
|
|
193
|
+
if (isEmptyValue(value)) {
|
|
194
|
+
return options.empty ?? EMPTY_VALUE;
|
|
195
|
+
}
|
|
196
|
+
const numeric = toFiniteNumber(value);
|
|
197
|
+
if (numeric === null) {
|
|
28
198
|
return String(value);
|
|
29
199
|
}
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
200
|
+
const style = resolveStyle(spec);
|
|
201
|
+
const precision = clampDecimals(spec?.precision);
|
|
202
|
+
const units = style === ReportValueFormat.Percent
|
|
203
|
+
? ReportNumberUnits.None
|
|
204
|
+
: options.units ?? resolveUnits(spec?.units, numeric, precision ?? SCALED_DECIMALS);
|
|
205
|
+
const scale = UNIT_SCALES.get(units);
|
|
206
|
+
const decimals = clampDecimals(options.decimals) ?? precision;
|
|
207
|
+
const formatter = numberFormat(context.locale, {
|
|
208
|
+
...styleOptions(style, context, decimals, !!scale),
|
|
209
|
+
...(options.signed ? SIGNED : {}),
|
|
210
|
+
});
|
|
211
|
+
const text = writeNumber(formatter, (numeric === 0 ? 0 : numeric) / (scale?.divisor ?? 1), scale?.suffix);
|
|
212
|
+
return style === ReportValueFormat.Percent && !context.ratioPercent ? `${text}%` : text;
|
|
213
|
+
}
|
|
214
|
+
function isEmptyValue(value) {
|
|
215
|
+
return value === null
|
|
216
|
+
|| value === undefined
|
|
217
|
+
|| value === ''
|
|
218
|
+
|| value === '-'
|
|
219
|
+
|| (typeof value === 'number' && !Number.isFinite(value));
|
|
220
|
+
}
|
|
221
|
+
// The value format a slot names, or null when it names none (or only date).
|
|
222
|
+
function valueFormat(spec) {
|
|
223
|
+
return Object.values(ReportValueFormat).find((format) => format === spec?.format) ?? null;
|
|
224
|
+
}
|
|
225
|
+
function resolveStyle(spec) {
|
|
226
|
+
return valueFormat(spec) ?? ReportValueFormat.Number;
|
|
227
|
+
}
|
|
228
|
+
// A usable decimal count, or null. A stored value outside the schema's bounds
|
|
229
|
+
// is brought inside them rather than thrown on by Intl.
|
|
230
|
+
function clampDecimals(decimals) {
|
|
231
|
+
return typeof decimals === 'number' && Number.isFinite(decimals)
|
|
232
|
+
? Math.min(MAX_PRECISION, Math.max(0, Math.round(decimals)))
|
|
233
|
+
: null;
|
|
234
|
+
}
|
|
235
|
+
function styleOptions(style, context, decimals, scaled) {
|
|
236
|
+
const fractionDigits = fractionDigitOptions(decimals, defaultDecimals(style, scaled));
|
|
237
|
+
switch (style) {
|
|
238
|
+
case ReportValueFormat.Currency:
|
|
239
|
+
return { ...currencyOptions(context.currency), ...fractionDigits };
|
|
240
|
+
case ReportValueFormat.Percent:
|
|
241
|
+
return context.ratioPercent ? { style: 'percent', ...fractionDigits } : fractionDigits;
|
|
242
|
+
default:
|
|
243
|
+
return fractionDigits;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function currencyOptions(currency) {
|
|
247
|
+
return { style: 'currency', currency, currencyDisplay: 'symbol' };
|
|
248
|
+
}
|
|
249
|
+
// The most decimals a style shows when nothing pins them; null leaves Intl's
|
|
250
|
+
// own default.
|
|
251
|
+
function defaultDecimals(style, scaled) {
|
|
252
|
+
if (scaled) {
|
|
253
|
+
return SCALED_DECIMALS;
|
|
254
|
+
}
|
|
255
|
+
switch (style) {
|
|
256
|
+
case ReportValueFormat.Percent:
|
|
257
|
+
return PERCENT_DECIMALS;
|
|
258
|
+
case ReportValueFormat.Currency:
|
|
259
|
+
return CURRENCY_DECIMALS;
|
|
50
260
|
default:
|
|
51
|
-
return
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Pinned decimals set both bounds. Otherwise a maximum also sets the minimum
|
|
265
|
+
// to zero, so no engine throws on a maximum below a currency's own minimum.
|
|
266
|
+
function fractionDigitOptions(pinned, maximum) {
|
|
267
|
+
if (pinned !== null) {
|
|
268
|
+
return { minimumFractionDigits: pinned, maximumFractionDigits: pinned };
|
|
269
|
+
}
|
|
270
|
+
return maximum === null ? {} : { minimumFractionDigits: 0, maximumFractionDigits: maximum };
|
|
271
|
+
}
|
|
272
|
+
// The formatted value, with the units letter after its digits. A negative
|
|
273
|
+
// whose shown digits are all zero is written as zero, so no '-0' appears.
|
|
274
|
+
function writeNumber(formatter, value, suffix) {
|
|
275
|
+
if (value >= 0 && !suffix) {
|
|
276
|
+
return formatter.format(value);
|
|
277
|
+
}
|
|
278
|
+
const parts = formatter.formatToParts(value);
|
|
279
|
+
if (value < 0 && !hasNonZeroDigit(formatter, parts)) {
|
|
280
|
+
return writeNumber(formatter, 0, suffix);
|
|
281
|
+
}
|
|
282
|
+
if (!suffix) {
|
|
283
|
+
return parts.map((part) => part.value).join('');
|
|
284
|
+
}
|
|
285
|
+
const last = parts.reduce((found, part, index) => NUMBER_PARTS.has(part.type) ? index : found, -1);
|
|
286
|
+
return [
|
|
287
|
+
...parts.slice(0, last + 1).map((part) => part.value),
|
|
288
|
+
suffix,
|
|
289
|
+
...parts.slice(last + 1).map((part) => part.value),
|
|
290
|
+
].join('');
|
|
291
|
+
}
|
|
292
|
+
// Compared with the locale's own zero, so a numbering system other than
|
|
293
|
+
// 0-9 is read correctly.
|
|
294
|
+
function hasNonZeroDigit(formatter, parts) {
|
|
295
|
+
const zero = formatter.formatToParts(0).find((part) => part.type === 'integer')?.value ?? '0';
|
|
296
|
+
return parts.some((part) => DIGIT_PARTS.has(part.type)
|
|
297
|
+
&& Array.from(part.value).some((character) => character !== zero));
|
|
298
|
+
}
|
|
299
|
+
// Output values: a column the server marks in ComponentData.outputs (a
|
|
300
|
+
// compared value, a rank, a share) written by what it is. The data stays raw;
|
|
301
|
+
// every number still goes through formatNumber. The rules:
|
|
302
|
+
// - The format: a slot's own explicit format always wins. Otherwise a current,
|
|
303
|
+
// prior or change column takes its source measure's format; a percent change
|
|
304
|
+
// is a percent; a rank is a whole number; a share is a percent to 1 decimal.
|
|
305
|
+
// An own precision or units still applies over those defaults.
|
|
306
|
+
// - Signs: a change and a percent change are signed ('+579', '-31.1%').
|
|
307
|
+
// - Points: a change of a percent-format value, and any share change, is a
|
|
308
|
+
// difference of two rates, so it prints in percentage points, signed and to
|
|
309
|
+
// 1 decimal unless a precision pins others: 0.1 reads '+10.0 pp'.
|
|
310
|
+
// - Missing: a missing prior, or a change or percent change left empty by
|
|
311
|
+
// one, prints '—' titled with the floor ('No baseline: no data before
|
|
312
|
+
// Mar 3, 2026'), or for a rank or a share with the period the row was
|
|
313
|
+
// absent from ('No rank in the prior period'); a percent change over a prior of 0 prints 'n/a' titled
|
|
314
|
+
// 'Prior was 0'. Any other missing value prints '—' (or the caller's empty).
|
|
315
|
+
// - Rank change: prior minus current, so a rise is positive: '▲ 2', '▼ 1',
|
|
316
|
+
// '–' for none, and 'new' for an empty change whose prior rank is missing
|
|
317
|
+
// or not passed (a row always has a current rank, so only the prior lacks).
|
|
318
|
+
// A percent change and a share are 0-1 fractions whatever the report's
|
|
319
|
+
// percentFormat: the server computes them, never a stored value.
|
|
320
|
+
// A missing comparison value prints EMPTY_VALUE whatever the caller's empty.
|
|
321
|
+
const NOT_APPLICABLE_VALUE = 'n/a';
|
|
322
|
+
const NEW_RANK_VALUE = 'new';
|
|
323
|
+
const RANK_UNCHANGED_VALUE = '–';
|
|
324
|
+
const RANK_UP_MARK = '▲';
|
|
325
|
+
const RANK_DOWN_MARK = '▼';
|
|
326
|
+
const POINTS_SUFFIX = 'pp';
|
|
327
|
+
const NO_PRIOR_RANK_TITLE = 'No rank in the prior period';
|
|
328
|
+
const NO_PRIOR_SHARE_TITLE = 'No share in the prior period';
|
|
329
|
+
// Percentage points and a share are written to one decimal unless pinned.
|
|
330
|
+
const POINTS_DECIMALS = 1;
|
|
331
|
+
const SHARE_DECIMALS = 1;
|
|
332
|
+
const RANK_DEFAULT_SPEC = Object.freeze({ format: ReportValueFormat.Number, precision: 0 });
|
|
333
|
+
const SHARE_DEFAULT_SPEC = Object.freeze({
|
|
334
|
+
format: ReportValueFormat.Percent,
|
|
335
|
+
precision: SHARE_DECIMALS,
|
|
336
|
+
});
|
|
337
|
+
const PERCENT_CHANGE_DEFAULT_SPEC = Object.freeze({ format: ReportValueFormat.Percent });
|
|
338
|
+
// One output value, written by the rules above. Without output metadata (a
|
|
339
|
+
// plain measure column, an older server) it is formatNumber with the slot's
|
|
340
|
+
// own format.
|
|
341
|
+
export function formatOutputValue(value, output, spec, context, options = {}) {
|
|
342
|
+
if (!output) {
|
|
343
|
+
return plainOutput(formatNumber(value, spec, context, { empty: options.empty }));
|
|
344
|
+
}
|
|
345
|
+
if (output.kind === 'rank' && output.role === 'change') {
|
|
346
|
+
return formatRankChange(value, spec, context, options);
|
|
347
|
+
}
|
|
348
|
+
const role = output.role;
|
|
349
|
+
const effective = outputFormatSpec(output, spec, options.measureSpec);
|
|
350
|
+
if (isEmptyValue(value)) {
|
|
351
|
+
return missingOutput(output, context, options);
|
|
352
|
+
}
|
|
353
|
+
if (role === 'change' && isPointsChange(output, effective)) {
|
|
354
|
+
return plainOutput(formatPoints(value, output, effective, context));
|
|
355
|
+
}
|
|
356
|
+
const signed = role === 'change' || role === 'percent_change';
|
|
357
|
+
const ratioContext = role === 'percent_change' || output.kind === 'share'
|
|
358
|
+
? { ...context, ratioPercent: true }
|
|
359
|
+
: context;
|
|
360
|
+
return plainOutput(formatNumber(value, effective, ratioContext, { signed }));
|
|
361
|
+
}
|
|
362
|
+
// The alias of the output that plays `role` in the same lane as `alias`: the
|
|
363
|
+
// same measure and kind, and (for a prior, change or percent change) the same
|
|
364
|
+
// prior lane. A measure compares against one lane only (two compares on one
|
|
365
|
+
// value are two measures), so a current value's lane is whichever one its
|
|
366
|
+
// measure's prior columns carry, lane 2 as readily as lane 1. A change column
|
|
367
|
+
// finds its prior this way to pass as OutputValueOptions.prior. null when the
|
|
368
|
+
// server sends no such column.
|
|
369
|
+
export function laneOutputAlias(outputs, alias, role) {
|
|
370
|
+
const source = outputs?.[alias];
|
|
371
|
+
if (!source) {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
const anyLane = source.role === 'current' || source.offset === null;
|
|
375
|
+
const found = Object.entries(outputs ?? {}).find(([, meta]) => meta.measure === source.measure
|
|
376
|
+
&& meta.kind === source.kind
|
|
377
|
+
&& meta.role === role
|
|
378
|
+
&& (role === 'current' || (anyLane ? meta.offset !== null : meta.offset === source.offset)));
|
|
379
|
+
return found ? found[0] : null;
|
|
380
|
+
}
|
|
381
|
+
function plainOutput(text) {
|
|
382
|
+
return { text, title: null };
|
|
383
|
+
}
|
|
384
|
+
// The format an output is written in: the slot's own explicit format, else
|
|
385
|
+
// the default for what it holds, with any own precision or units over it.
|
|
386
|
+
function outputFormatSpec(output, own, measureSpec) {
|
|
387
|
+
if (valueFormat(own) !== null) {
|
|
388
|
+
return own;
|
|
389
|
+
}
|
|
390
|
+
if (output.kind === 'rank') {
|
|
391
|
+
return withOwnDigits(RANK_DEFAULT_SPEC, own);
|
|
392
|
+
}
|
|
393
|
+
if (output.kind === 'share') {
|
|
394
|
+
return withOwnDigits(SHARE_DEFAULT_SPEC, own);
|
|
395
|
+
}
|
|
396
|
+
if (output.role === 'percent_change') {
|
|
397
|
+
return withOwnDigits(PERCENT_CHANGE_DEFAULT_SPEC, own);
|
|
398
|
+
}
|
|
399
|
+
return measureSpec ? withOwnDigits(measureSpec, own) : own ?? null;
|
|
400
|
+
}
|
|
401
|
+
// The base format with the slot's own precision and units over it.
|
|
402
|
+
function withOwnDigits(base, own) {
|
|
403
|
+
return {
|
|
404
|
+
...base,
|
|
405
|
+
...((own?.precision ?? null) !== null ? { precision: own.precision } : {}),
|
|
406
|
+
...((own?.units ?? null) !== null ? { units: own.units } : {}),
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
// A change between two rates: a share's, or a percent-format value's.
|
|
410
|
+
function isPointsChange(output, spec) {
|
|
411
|
+
return output.kind === 'share' || resolveStyle(spec) === ReportValueFormat.Percent;
|
|
412
|
+
}
|
|
413
|
+
// A rate change in percentage points. A share and a 0-1 percent are scaled
|
|
414
|
+
// x100; an older server's percent values already are.
|
|
415
|
+
function formatPoints(value, output, spec, context) {
|
|
416
|
+
const numeric = toFiniteNumber(value);
|
|
417
|
+
if (numeric === null) {
|
|
418
|
+
return String(value);
|
|
52
419
|
}
|
|
420
|
+
const points = output.kind === 'share' || context.ratioPercent ? numeric * 100 : numeric;
|
|
421
|
+
const decimals = clampDecimals(spec?.precision) ?? POINTS_DECIMALS;
|
|
422
|
+
const text = formatNumber(points, { format: ReportValueFormat.Number }, context, { decimals, signed: true });
|
|
423
|
+
return `${text} ${POINTS_SUFFIX}`;
|
|
424
|
+
}
|
|
425
|
+
// A missing output value. A missing prior, or a delta a missing prior left
|
|
426
|
+
// empty, has no baseline; a percent change over a zero prior has none to
|
|
427
|
+
// divide by.
|
|
428
|
+
function missingOutput(output, context, options) {
|
|
429
|
+
const role = output.role;
|
|
430
|
+
if (role === 'prior') {
|
|
431
|
+
return { text: EMPTY_VALUE, title: missingPriorTitle(output, options.floor, context.locale) };
|
|
432
|
+
}
|
|
433
|
+
if (role === 'change' || role === 'percent_change') {
|
|
434
|
+
const prior = options.prior;
|
|
435
|
+
if (role === 'percent_change' && toFiniteNumber(prior) === 0) {
|
|
436
|
+
return { text: NOT_APPLICABLE_VALUE, title: 'Prior was 0' };
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
text: EMPTY_VALUE,
|
|
440
|
+
title: prior !== undefined && isEmptyValue(prior)
|
|
441
|
+
? missingPriorTitle(output, options.floor, context.locale)
|
|
442
|
+
: null,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
return plainOutput(options.empty ?? EMPTY_VALUE);
|
|
446
|
+
}
|
|
447
|
+
// Why a prior is missing. A value's prior is missing when its window ends
|
|
448
|
+
// before the data starts. A rank's or a share's is missing when the row had
|
|
449
|
+
// no rank or share in the prior period, whatever the floor.
|
|
450
|
+
function missingPriorTitle(output, floor, locale) {
|
|
451
|
+
if (output.kind === 'rank') {
|
|
452
|
+
return NO_PRIOR_RANK_TITLE;
|
|
453
|
+
}
|
|
454
|
+
if (output.kind === 'share') {
|
|
455
|
+
return NO_PRIOR_SHARE_TITLE;
|
|
456
|
+
}
|
|
457
|
+
return noBaselineTitle(floor, locale);
|
|
458
|
+
}
|
|
459
|
+
function noBaselineTitle(floor, locale) {
|
|
460
|
+
const day = floor ? formatDay(floor, locale) : '';
|
|
461
|
+
return day ? `No baseline: no data before ${day}` : 'No baseline';
|
|
462
|
+
}
|
|
463
|
+
// A rank change: prior rank minus current, so moving up is positive.
|
|
464
|
+
function formatRankChange(value, spec, context, options) {
|
|
465
|
+
if (isEmptyValue(value)) {
|
|
466
|
+
return isEmptyValue(options.prior)
|
|
467
|
+
? { text: NEW_RANK_VALUE, title: NO_PRIOR_RANK_TITLE }
|
|
468
|
+
: plainOutput(EMPTY_VALUE);
|
|
469
|
+
}
|
|
470
|
+
const numeric = toFiniteNumber(value);
|
|
471
|
+
if (numeric === null) {
|
|
472
|
+
return plainOutput(String(value));
|
|
473
|
+
}
|
|
474
|
+
const rankSpec = valueFormat(spec) !== null ? spec : withOwnDigits(RANK_DEFAULT_SPEC, spec);
|
|
475
|
+
const places = formatNumber(Math.abs(numeric), rankSpec, context);
|
|
476
|
+
if (places === formatNumber(0, rankSpec, context)) {
|
|
477
|
+
return plainOutput(RANK_UNCHANGED_VALUE);
|
|
478
|
+
}
|
|
479
|
+
return plainOutput(`${numeric > 0 ? RANK_UP_MARK : RANK_DOWN_MARK} ${places}`);
|
|
480
|
+
}
|
|
481
|
+
// A chart's value axis takes a format only when every measure on it agrees on
|
|
482
|
+
// the style (each measure's format, number when it names none) and at least
|
|
483
|
+
// one of them names a format. The first measure that does gives the axis its
|
|
484
|
+
// precision and units. Otherwise null: the axis keeps its default ticks on
|
|
485
|
+
// screen and in PowerPoint, and each series still formats its own tooltips.
|
|
486
|
+
export function axisNumberFormat(measures) {
|
|
487
|
+
const style = measures.length ? resolveStyle(measures[0]) : null;
|
|
488
|
+
if (style === null || measures.some((measure) => resolveStyle(measure) !== style)) {
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
const formatted = measures.find((measure) => hasNumberFormat(measure));
|
|
492
|
+
return formatted ? numberFormatSpec(formatted) : null;
|
|
493
|
+
}
|
|
494
|
+
function numberFormatSpec(spec) {
|
|
495
|
+
return {
|
|
496
|
+
...(spec.format !== undefined ? { format: spec.format } : {}),
|
|
497
|
+
...(spec.precision !== undefined ? { precision: spec.precision } : {}),
|
|
498
|
+
...(spec.units !== undefined ? { units: spec.units } : {}),
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
// How a chart's value axis writes its ticks: the units decided once from the
|
|
502
|
+
// axis peak, and the decimals the precision pins, else as many as the axis's
|
|
503
|
+
// tick step needs (a percent axis up to 0.12% steps by 0.02%, two decimals).
|
|
504
|
+
// Pinned decimals keep the ticks distinct, and PowerPoint can only pin them.
|
|
505
|
+
export function resolveChartNumberFormat(spec, peak, context) {
|
|
506
|
+
const style = resolveStyle(spec);
|
|
507
|
+
const precision = clampDecimals(spec.precision);
|
|
508
|
+
const units = style === ReportValueFormat.Percent
|
|
509
|
+
? ReportNumberUnits.None
|
|
510
|
+
: resolveUnits(spec.units, peak, precision ?? SCALED_DECIMALS);
|
|
511
|
+
return { units, decimals: precision ?? axisDecimals(style, units, peak, context) };
|
|
512
|
+
}
|
|
513
|
+
// The decimals the axis's nice tick step needs. A plain, unabbreviated number
|
|
514
|
+
// pins none (null): its ticks keep their own decimals. An unscaled currency
|
|
515
|
+
// axis that needs decimals shows cents, and a K/M axis keeps its step's
|
|
516
|
+
// decimals ('$0.5M', not '$0.50M').
|
|
517
|
+
function axisDecimals(style, units, peak, context) {
|
|
518
|
+
const scale = UNIT_SCALES.get(units);
|
|
519
|
+
if (style === ReportValueFormat.Number && !scale) {
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
const shownPeak = style === ReportValueFormat.Percent && context.ratioPercent
|
|
523
|
+
? Math.abs(peak) * 100
|
|
524
|
+
: Math.abs(peak) / (scale?.divisor ?? 1);
|
|
525
|
+
const step = niceStep(shownPeak / AXIS_TICKS);
|
|
526
|
+
const decimals = step > 0 ? clampDecimals(-Math.floor(Math.log10(step))) ?? 0 : 0;
|
|
527
|
+
return style === ReportValueFormat.Currency && decimals > 0 && !scale ? CURRENCY_AXIS_DECIMALS : decimals;
|
|
528
|
+
}
|
|
529
|
+
// ECharts' nice(): the round number (1, 2, 3, 5 or 10 times a power of ten) a
|
|
530
|
+
// rough tick step snaps to.
|
|
531
|
+
function niceStep(rough) {
|
|
532
|
+
if (!(rough > 0) || !Number.isFinite(rough)) {
|
|
533
|
+
return 0;
|
|
534
|
+
}
|
|
535
|
+
const exponent = Math.floor(Math.log10(rough));
|
|
536
|
+
const power = Math.pow(10, exponent);
|
|
537
|
+
const fraction = rough / power;
|
|
538
|
+
let nice = 10;
|
|
539
|
+
if (fraction < 1.5) {
|
|
540
|
+
nice = 1;
|
|
541
|
+
}
|
|
542
|
+
else if (fraction < 2.5) {
|
|
543
|
+
nice = 2;
|
|
544
|
+
}
|
|
545
|
+
else if (fraction < 4) {
|
|
546
|
+
nice = 3;
|
|
547
|
+
}
|
|
548
|
+
else if (fraction < 7) {
|
|
549
|
+
nice = 5;
|
|
550
|
+
}
|
|
551
|
+
return nice * power;
|
|
552
|
+
}
|
|
553
|
+
// PowerPoint's number format code for a formatted value axis, matching the
|
|
554
|
+
// screen's ticks: '#,##0.0%' (percent), '"$"#,##0' (currency),
|
|
555
|
+
// '#,##0.0,"K"' (thousands), '#,##0" $"' (fr-CA currency). A plain number
|
|
556
|
+
// whose decimals are not pinned keeps chartAxisFormatCode's code. The code's
|
|
557
|
+
// separators follow the opening machine's locale; the currency symbol and its
|
|
558
|
+
// side follow the report's.
|
|
559
|
+
export function numberFormatCode(spec, context, chart, series, stacked) {
|
|
560
|
+
const style = resolveStyle(spec);
|
|
561
|
+
const scale = style === ReportValueFormat.Percent ? undefined : UNIT_SCALES.get(chart.units);
|
|
562
|
+
if (style === ReportValueFormat.Number && !scale && chart.decimals === null) {
|
|
563
|
+
return chartAxisFormatCode(series, stacked);
|
|
564
|
+
}
|
|
565
|
+
const decimals = chart.decimals ?? 0;
|
|
566
|
+
const digits = `#,##0${decimals > 0 ? `.${'0'.repeat(decimals)}` : ''}`;
|
|
567
|
+
if (style === ReportValueFormat.Percent) {
|
|
568
|
+
return `${digits}${context.ratioPercent ? '%' : '"%"'}`;
|
|
569
|
+
}
|
|
570
|
+
const scaled = `${digits}${scale?.commas ?? ''}`;
|
|
571
|
+
const unit = scale?.suffix ?? '';
|
|
572
|
+
if (style !== ReportValueFormat.Currency) {
|
|
573
|
+
return unit ? `${scaled}"${unit}"` : scaled;
|
|
574
|
+
}
|
|
575
|
+
const symbol = currencySymbol(context);
|
|
576
|
+
return symbol.prefix
|
|
577
|
+
? `"${symbol.text}"${scaled}${unit ? `"${unit}"` : ''}`
|
|
578
|
+
: `${scaled}"${unit}${symbol.text}"`;
|
|
579
|
+
}
|
|
580
|
+
const CURRENCY_SYMBOLS = new Map();
|
|
581
|
+
function currencySymbol(context) {
|
|
582
|
+
const key = `${context.locale}|${context.currency}`;
|
|
583
|
+
let symbol = CURRENCY_SYMBOLS.get(key);
|
|
584
|
+
if (!symbol) {
|
|
585
|
+
const parts = numberFormat(context.locale, currencyOptions(context.currency)).formatToParts(1);
|
|
586
|
+
const currency = parts.findIndex((part) => part.type === 'currency');
|
|
587
|
+
const first = parts.findIndex((part) => NUMBER_PARTS.has(part.type));
|
|
588
|
+
const last = parts.reduce((found, part, index) => NUMBER_PARTS.has(part.type) ? index : found, -1);
|
|
589
|
+
const prefix = currency < first;
|
|
590
|
+
const text = (prefix ? parts.slice(Math.max(currency, 0), first) : parts.slice(last + 1))
|
|
591
|
+
.map((part) => part.value)
|
|
592
|
+
.join('')
|
|
593
|
+
.replace(/"/g, '');
|
|
594
|
+
symbol = { prefix, text };
|
|
595
|
+
CURRENCY_SYMBOLS.set(key, symbol);
|
|
596
|
+
}
|
|
597
|
+
return symbol;
|
|
598
|
+
}
|
|
599
|
+
// Every decimal a number has, grouped, in the locale: what ECharts prints by
|
|
600
|
+
// default (its addCommas), but in the report's locale, so a chart's axis and
|
|
601
|
+
// tooltip read like the rest of the report. 1234.5 reads 1,234.5 in en-US and
|
|
602
|
+
// 1 234,5 in fr-CA. A non-numeric string is shown as it came, and anything
|
|
603
|
+
// else non-numeric as '-', as ECharts shows it. As there, an infinite value
|
|
604
|
+
// reads 'Infinity' and negative zero (a tick a float error leaves just below
|
|
605
|
+
// zero) reads '0'.
|
|
606
|
+
const PLAIN_NUMBER = { maximumFractionDigits: 20 };
|
|
607
|
+
export function formatPlainNumber(value, locale) {
|
|
608
|
+
const numeric = typeof value === 'number'
|
|
609
|
+
? value
|
|
610
|
+
: typeof value === 'string' && value.trim() !== '' ? Number(value) : NaN;
|
|
611
|
+
if (Number.isNaN(numeric)) {
|
|
612
|
+
return typeof value === 'string' ? value : '-';
|
|
613
|
+
}
|
|
614
|
+
if (!Number.isFinite(numeric)) {
|
|
615
|
+
return String(numeric);
|
|
616
|
+
}
|
|
617
|
+
return numberFormat(locale, PLAIN_NUMBER).format(numeric === 0 ? 0 : numeric);
|
|
53
618
|
}
|
|
54
619
|
// The axis peak at which a native chart's value axis gains thousands
|
|
55
620
|
// separators. From here up the ticks are whole numbers in practice; below it
|
|
@@ -61,15 +626,19 @@ export const AXIS_SEPARATOR_THRESHOLD = 1000;
|
|
|
61
626
|
// (where ticks are whole numbers) gets '#,##0', and a smaller range keeps
|
|
62
627
|
// 'General' so fractional ticks (0.25, 0.5) are not rounded away.
|
|
63
628
|
//
|
|
64
|
-
// The peak
|
|
65
|
-
// stack: the largest sum, per category, of every series' absolute value.
|
|
629
|
+
// The peak is chartValuePeak's.
|
|
66
630
|
export function chartAxisFormatCode(series, stacked) {
|
|
631
|
+
return chartValuePeak(series, stacked) >= AXIS_SEPARATOR_THRESHOLD ? '#,##0' : 'General';
|
|
632
|
+
}
|
|
633
|
+
// The largest magnitude a chart's value axis has to reach. A missing value
|
|
634
|
+
// counts as 0. A stacked chart's peak is its tallest stack: the largest sum,
|
|
635
|
+
// per category, of every series' absolute value.
|
|
636
|
+
export function chartValuePeak(series, stacked) {
|
|
67
637
|
const magnitudes = series.map((values) => values.map((value) => Math.abs(value ?? 0)));
|
|
68
|
-
|
|
638
|
+
return stacked
|
|
69
639
|
? Math.max(0, ...(magnitudes[0] ?? []).map((_, index) => magnitudes
|
|
70
640
|
.reduce((sum, values) => sum + (values[index] ?? 0), 0)))
|
|
71
641
|
: Math.max(0, ...magnitudes.flat());
|
|
72
|
-
return peak >= AXIS_SEPARATOR_THRESHOLD ? '#,##0' : 'General';
|
|
73
642
|
}
|
|
74
643
|
// The zone every date in a report is read in. The server resolves it (the
|
|
75
644
|
// report's own zone, else the application's default reporting zone) and sends
|
|
@@ -80,6 +649,52 @@ export function chartAxisFormatCode(series, stacked) {
|
|
|
80
649
|
export function resolveReportTimezone(report) {
|
|
81
650
|
return report.effectiveTimezone ?? report.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
82
651
|
}
|
|
652
|
+
// The date shapes a report writes, each in the report's locale.
|
|
653
|
+
// 'Jan 5, 2026' / '5 janv. 2026': a date cell, a filter bound.
|
|
654
|
+
export const DAY_SHORT = { year: 'numeric', month: 'short', day: 'numeric' };
|
|
655
|
+
// 'January 5, 2026' / '5 janvier 2026': an export cover's date line.
|
|
656
|
+
export const DAY_LONG = { year: 'numeric', month: 'long', day: 'numeric' };
|
|
657
|
+
// 'January' / 'janvier': a monthly period label (its year is added apart).
|
|
658
|
+
export const MONTH_LONG = { month: 'long' };
|
|
659
|
+
// 'January 2026' / 'janvier 2026': a monthly period label written in full.
|
|
660
|
+
export const MONTH_YEAR = { year: 'numeric', month: 'long' };
|
|
661
|
+
// 'Jan 5' / '5 janv.': a daily or weekly period label.
|
|
662
|
+
export const MONTH_DAY = { month: 'short', day: 'numeric' };
|
|
663
|
+
// A date in the locale. With a zone, the day it falls on there; without one,
|
|
664
|
+
// the browser's zone, which keeps a calendar day parsed as local midnight
|
|
665
|
+
// unshifted. It never throws, since a pipe or an export calls it per cell: an
|
|
666
|
+
// invalid Date reads '', a malformed locale ('en_CA') reads the fallback
|
|
667
|
+
// locale, and an unknown zone reads UTC, which still names a real day.
|
|
668
|
+
export function formatLocalDate(date, locale, options, timeZone) {
|
|
669
|
+
if (Number.isNaN(date.getTime())) {
|
|
670
|
+
return '';
|
|
671
|
+
}
|
|
672
|
+
try {
|
|
673
|
+
return writeDate(dateFormat(locale, options, timeZone), date);
|
|
674
|
+
}
|
|
675
|
+
catch {
|
|
676
|
+
return formatFallbackDate(date, resolveReportLocale(locale), options, timeZone);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
function formatFallbackDate(date, locale, options, timeZone) {
|
|
680
|
+
try {
|
|
681
|
+
return writeDate(dateFormat(locale, options, timeZone), date);
|
|
682
|
+
}
|
|
683
|
+
catch {
|
|
684
|
+
return writeDate(dateFormat(locale, options, 'UTC'), date);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
// Intl writes a year below 1000 with only the digits it has ('Jan 1, 1'); a
|
|
688
|
+
// date's year is always written with four ('Jan 1, 0001'), so a sentinel day
|
|
689
|
+
// still reads as a date. Only such a year pays for formatToParts.
|
|
690
|
+
function writeDate(formatter, date) {
|
|
691
|
+
if (date.getUTCFullYear() > 1000) {
|
|
692
|
+
return formatter.format(date);
|
|
693
|
+
}
|
|
694
|
+
return formatter.formatToParts(date)
|
|
695
|
+
.map((part) => part.type === 'year' ? part.value.padStart(4, '0') : part.value)
|
|
696
|
+
.join('');
|
|
697
|
+
}
|
|
83
698
|
const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
84
699
|
const DATE_TIME_PATTERN = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(\.\d+)?$/;
|
|
85
700
|
// A report row's date cell as a calendar day in the report's zone.
|
|
@@ -95,31 +710,276 @@ const DATE_TIME_PATTERN = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(\.\d+)?$/
|
|
|
95
710
|
// - Anything else is shown as it came, and so is a value that has the shape
|
|
96
711
|
// but names no real day (a zero date '0000-00-00', or '2026-02-30'): one
|
|
97
712
|
// bad cell must not throw out of a pipe or abort an export.
|
|
98
|
-
|
|
713
|
+
// The day is written in the report's locale: 'Jan 5, 2026' in en-US, '5 janv.
|
|
714
|
+
// 2026' in fr-CA.
|
|
715
|
+
export function formatReportDate(value, timezone, locale) {
|
|
99
716
|
if (value === null || value === undefined || value === '') {
|
|
100
717
|
return '';
|
|
101
718
|
}
|
|
102
719
|
const text = String(value);
|
|
103
720
|
if (DATE_ONLY_PATTERN.test(text)) {
|
|
104
721
|
const day = parseISO(text);
|
|
105
|
-
return isValid(day) ?
|
|
722
|
+
return isValid(day) ? formatLocalDate(day, locale, DAY_SHORT) : text;
|
|
106
723
|
}
|
|
107
724
|
const dateTime = DATE_TIME_PATTERN.exec(text);
|
|
108
725
|
if (!dateTime) {
|
|
109
726
|
return text;
|
|
110
727
|
}
|
|
111
728
|
const instant = parseISO(`${dateTime[1]}T${dateTime[2]}Z`);
|
|
112
|
-
|
|
113
|
-
|
|
729
|
+
return isValid(instant) ? formatLocalDate(instant, locale, DAY_SHORT, timezone) : text;
|
|
730
|
+
}
|
|
731
|
+
// The time of day an instant falls at in the report's zone: '2:23 PM' in
|
|
732
|
+
// en-US, '14 h 23' in fr-CA.
|
|
733
|
+
export const TIME_SHORT = { hour: 'numeric', minute: '2-digit' };
|
|
734
|
+
// A window's inclusive days, as the server sends them: 'yyyy-MM-dd' calendar
|
|
735
|
+
// days already in the report's zone. Like a date cell they are read as local
|
|
736
|
+
// midnight and written with NO zone, so a viewer in any zone sees the days
|
|
737
|
+
// sent. Both days: Intl's range in the locale ('Sep 1 – 30, 2026' in en-US,
|
|
738
|
+
// '1–30 sept. 2026' in fr-CA, one date when they are the same day). One day:
|
|
739
|
+
// an open window ('Since Sep 1, 2026', 'Through Sep 30, 2026'). Neither, or
|
|
740
|
+
// days that are not real ones: ''.
|
|
741
|
+
export function formatDayRange(start, end, locale, options = DAY_SHORT) {
|
|
742
|
+
const first = parseDay(start);
|
|
743
|
+
const last = parseDay(end);
|
|
744
|
+
if (first && last) {
|
|
745
|
+
return writeDayRange(first, last, locale, options);
|
|
746
|
+
}
|
|
747
|
+
if (first) {
|
|
748
|
+
return `Since ${formatLocalDate(first, locale, options)}`;
|
|
749
|
+
}
|
|
750
|
+
return last ? `Through ${formatLocalDate(last, locale, options)}` : '';
|
|
751
|
+
}
|
|
752
|
+
// The time a window ending today is cut at: the server's UTC
|
|
753
|
+
// 'yyyy-MM-dd HH:mm:ss' instant, as a time of day in the report's zone. ''
|
|
754
|
+
// for none, or for a value of another shape.
|
|
755
|
+
export function formatThroughTime(through, timezone, locale) {
|
|
756
|
+
const dateTime = through ? DATE_TIME_PATTERN.exec(through) : null;
|
|
757
|
+
const instant = dateTime ? parseISO(`${dateTime[1]}T${dateTime[2]}Z`) : null;
|
|
758
|
+
return instant && isValid(instant) ? formatLocalDate(instant, locale, TIME_SHORT, timezone) : '';
|
|
759
|
+
}
|
|
760
|
+
// A comparison or timeframe window in one line: its days, and the time it is
|
|
761
|
+
// cut at when it ends today on a date-and-time column ('Oct 1 – 2, 2026,
|
|
762
|
+
// until 2:23 PM').
|
|
763
|
+
export function formatDayWindow(meta, timezone, locale) {
|
|
764
|
+
const days = formatDayRange(meta.start, meta.end, locale);
|
|
765
|
+
const time = formatThroughTime(meta.through, timezone, locale);
|
|
766
|
+
return days && time ? `${days}, until ${time}` : days;
|
|
767
|
+
}
|
|
768
|
+
// One 'yyyy-MM-dd' day in the locale, written with no zone: 'Sep 1, 2026'.
|
|
769
|
+
function formatDay(day, locale) {
|
|
770
|
+
const date = parseDay(day);
|
|
771
|
+
return date ? formatLocalDate(date, locale, DAY_SHORT) : '';
|
|
772
|
+
}
|
|
773
|
+
// A 'yyyy-MM-dd' day as local midnight, or null when it is not a real day.
|
|
774
|
+
function parseDay(day) {
|
|
775
|
+
if (!day || !DATE_ONLY_PATTERN.test(day)) {
|
|
776
|
+
return null;
|
|
114
777
|
}
|
|
115
|
-
|
|
778
|
+
const date = parseISO(day);
|
|
779
|
+
return isValid(date) ? date : null;
|
|
780
|
+
}
|
|
781
|
+
// Intl's range writes the shared month and year once. A malformed locale
|
|
782
|
+
// reads the fallback; a runtime that cannot write ranges joins two dates.
|
|
783
|
+
function writeDayRange(first, last, locale, options) {
|
|
784
|
+
const [from, to] = first <= last ? [first, last] : [last, first];
|
|
785
|
+
for (const tag of [locale, resolveReportLocale(locale)]) {
|
|
786
|
+
try {
|
|
787
|
+
return dateFormat(tag, options).formatRange(from, to);
|
|
788
|
+
}
|
|
789
|
+
catch {
|
|
790
|
+
// The next locale, then the joined dates.
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
return `${formatLocalDate(from, locale, options)} – ${formatLocalDate(to, locale, options)}`;
|
|
794
|
+
}
|
|
795
|
+
// English names for a locale and a currency, for the settings selects. The
|
|
796
|
+
// interface stays English whatever the report's locale: 'fr-CA' reads
|
|
797
|
+
// 'Canadian French', 'CAD' reads 'Canadian Dollar'. A runtime without the
|
|
798
|
+
// names shows the code.
|
|
799
|
+
export function localeName(tag) {
|
|
800
|
+
return displayName('language', tag);
|
|
801
|
+
}
|
|
802
|
+
export function currencyName(code) {
|
|
803
|
+
return displayName('currency', code);
|
|
804
|
+
}
|
|
805
|
+
function displayName(type, code) {
|
|
116
806
|
try {
|
|
117
|
-
return
|
|
807
|
+
return new Intl.DisplayNames(['en'], { type }).of(code) ?? code;
|
|
118
808
|
}
|
|
119
809
|
catch {
|
|
120
|
-
return
|
|
810
|
+
return code;
|
|
121
811
|
}
|
|
122
812
|
}
|
|
813
|
+
// Comparison, window and KPI wording. The server sends codes and fields,
|
|
814
|
+
// never sentences (a window's description is for the agent and the exports'
|
|
815
|
+
// notes, not the screen); the interface words them here, in English like
|
|
816
|
+
// every other label, with any day written in the report's locale.
|
|
817
|
+
const GRANULARITY_UNITS = {
|
|
818
|
+
day: { one: 'day', many: 'days' },
|
|
819
|
+
week: { one: 'week', many: 'weeks' },
|
|
820
|
+
month: { one: 'month', many: 'months' },
|
|
821
|
+
quarter: { one: 'quarter', many: 'quarters' },
|
|
822
|
+
year: { one: 'year', many: 'years' },
|
|
823
|
+
};
|
|
824
|
+
// What a prior lane is called: always so for a named period, and for the
|
|
825
|
+
// previous period when the server names no unit for it.
|
|
826
|
+
const AGAINST_PHRASES = {
|
|
827
|
+
previous_period: 'previous period',
|
|
828
|
+
previous_week: 'previous week',
|
|
829
|
+
previous_month: 'previous month',
|
|
830
|
+
previous_quarter: 'previous quarter',
|
|
831
|
+
previous_year: 'previous year',
|
|
832
|
+
range: 'custom range',
|
|
833
|
+
};
|
|
834
|
+
// A prior lane's label, from its offset rather than from the measure, so a
|
|
835
|
+
// chart regrouped by the viewer says what it now compares. A named period
|
|
836
|
+
// reads by its name whatever shift carries it ('vs previous quarter' for 3
|
|
837
|
+
// months, 'vs previous year' for 364 days or 52 weeks, 'vs custom range').
|
|
838
|
+
// Only the previous period is worded from its unit and count: 'vs previous
|
|
839
|
+
// week', 'vs previous 3 months', 'vs previous 8 days' (a day-length shift).
|
|
840
|
+
export function comparisonOffsetLabel(offset) {
|
|
841
|
+
return `vs ${offsetPhrase(offset)}`;
|
|
842
|
+
}
|
|
843
|
+
function offsetPhrase(offset) {
|
|
844
|
+
if (offset.against !== 'previous_period' || !offset.unit || !offset.count) {
|
|
845
|
+
return AGAINST_PHRASES[offset.against] ?? AGAINST_PHRASES.previous_period;
|
|
846
|
+
}
|
|
847
|
+
return offset.count === 1
|
|
848
|
+
? `previous ${GRANULARITY_UNITS[offset.unit].one}`
|
|
849
|
+
: `previous ${offset.count} ${GRANULARITY_UNITS[offset.unit].many}`;
|
|
850
|
+
}
|
|
851
|
+
// One comparison note as a sentence. The comparison, when given, names the
|
|
852
|
+
// period compared with (its first prior lane).
|
|
853
|
+
export function comparisonNoteText(code, comparison) {
|
|
854
|
+
const offset = comparison?.offsets?.[0] ?? null;
|
|
855
|
+
const compared = offset ? `Compared with the ${offsetPhrase(offset)}` : null;
|
|
856
|
+
switch (code) {
|
|
857
|
+
case 'no_window':
|
|
858
|
+
return 'Pick a date range to see the comparison.';
|
|
859
|
+
case 'unit_inferred':
|
|
860
|
+
return compared
|
|
861
|
+
? `${compared}, judged from the dates picked.`
|
|
862
|
+
: 'The period compared with was judged from the dates picked.';
|
|
863
|
+
case 'window_in_future':
|
|
864
|
+
return 'The date range starts after today, so there is nothing to compare yet.';
|
|
865
|
+
case 'other_date_filter':
|
|
866
|
+
return 'A date filter on another column also applies to both periods.';
|
|
867
|
+
case 'grain_followed':
|
|
868
|
+
return compared
|
|
869
|
+
? `${compared}, following the grouping picked.`
|
|
870
|
+
: 'The comparison follows the grouping picked.';
|
|
871
|
+
default:
|
|
872
|
+
return '';
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
// What a windowed value is: 'Rolling 3-month total', 'Month-to-date total',
|
|
876
|
+
// 'Running total since the start of the data', then its days when the server
|
|
877
|
+
// sends them ('Rolling 7-day average, Sep 24 – 30, 2026'). granularity is the
|
|
878
|
+
// grouping the rows are drawn at (ComponentData.granularity), which names a
|
|
879
|
+
// rolling window authored in periods of the axis.
|
|
880
|
+
export function windowText(meta, locale, granularity) {
|
|
881
|
+
const days = formatDayRange(meta.start, meta.end, locale);
|
|
882
|
+
const phrase = windowPhrase(meta, granularity ?? null);
|
|
883
|
+
return days ? `${phrase}, ${days}` : phrase;
|
|
884
|
+
}
|
|
885
|
+
function windowPhrase(meta, granularity) {
|
|
886
|
+
const value = meta.average ? 'average' : 'total';
|
|
887
|
+
switch (meta.kind) {
|
|
888
|
+
case 'running':
|
|
889
|
+
return meta.fromBeginning ? `Running ${value} since the start of the data` : `Running ${value}`;
|
|
890
|
+
case 'to_date': {
|
|
891
|
+
const reset = meta.resetEvery ? GRANULARITY_UNITS[meta.resetEvery].one : null;
|
|
892
|
+
return reset ? `${capitalize(reset)}-to-date ${value}` : `To-date ${value}`;
|
|
893
|
+
}
|
|
894
|
+
case 'rolling': {
|
|
895
|
+
const unit = meta.unit ?? granularity;
|
|
896
|
+
const span = meta.periods ? `${meta.periods}-${unit ? GRANULARITY_UNITS[unit].one : 'period'} ` : '';
|
|
897
|
+
return `Rolling ${span}${value}`;
|
|
898
|
+
}
|
|
899
|
+
default:
|
|
900
|
+
return capitalize(value);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
// One window note as a sentence.
|
|
904
|
+
export function windowNoteText(code, meta, locale, granularity) {
|
|
905
|
+
switch (code) {
|
|
906
|
+
case 'snapped_start': {
|
|
907
|
+
const start = meta.start ? formatDay(meta.start, locale) : '';
|
|
908
|
+
return start
|
|
909
|
+
? `The start was moved to ${start}, the start of its period, so the first period is whole.`
|
|
910
|
+
: 'The start was moved to the start of its period, so the first period is whole.';
|
|
911
|
+
}
|
|
912
|
+
case 'span_converted':
|
|
913
|
+
return spanConvertedText(meta, granularity ?? null);
|
|
914
|
+
case 'grain_too_coarse':
|
|
915
|
+
return 'The grouping is coarser than the window, so it has no values at this grouping.';
|
|
916
|
+
case 'equal_grain_plain':
|
|
917
|
+
return 'At this grouping each window is a single period, so the values are the plain ones.';
|
|
918
|
+
case 'own_filter_caps_lead_in':
|
|
919
|
+
return 'The query\'s own date condition starts the window, so earlier rows are not counted.';
|
|
920
|
+
case 'week_by_monday':
|
|
921
|
+
return 'A week that spans two periods counts toward the period its Monday falls in.';
|
|
922
|
+
case 'incomplete_head':
|
|
923
|
+
return 'The first periods are blank because there are not enough earlier rows to fill a whole window.';
|
|
924
|
+
default:
|
|
925
|
+
return '';
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
// '3 months are shown as 13 weeks at this grouping.'
|
|
929
|
+
function spanConvertedText(meta, granularity) {
|
|
930
|
+
if (!meta.periods || !meta.unit || !meta.drawnPeriods) {
|
|
931
|
+
return 'The window\'s span was converted to the grouping shown.';
|
|
932
|
+
}
|
|
933
|
+
const authored = unitCount(meta.periods, meta.unit);
|
|
934
|
+
const drawn = granularity
|
|
935
|
+
? unitCount(meta.drawnPeriods, granularity)
|
|
936
|
+
: `${meta.drawnPeriods} ${meta.drawnPeriods === 1 ? 'period' : 'periods'}`;
|
|
937
|
+
return `${authored} ${meta.periods === 1 ? 'is' : 'are'} shown as ${drawn} at this grouping.`;
|
|
938
|
+
}
|
|
939
|
+
function unitCount(count, unit) {
|
|
940
|
+
return `${count} ${count === 1 ? GRANULARITY_UNITS[unit].one : GRANULARITY_UNITS[unit].many}`;
|
|
941
|
+
}
|
|
942
|
+
// Why a KPI's delta reads as it does, as a sentence. The baseline is named
|
|
943
|
+
// by what the value is compared against: the same period last year for a
|
|
944
|
+
// year-on-year comparison, else the period before.
|
|
945
|
+
export function kpiNoteText(code, against) {
|
|
946
|
+
const baseline = kpiBaselineText(against);
|
|
947
|
+
switch (code) {
|
|
948
|
+
case 'no_prior_data':
|
|
949
|
+
return `No baseline: ${baseline} has no data.`;
|
|
950
|
+
case 'up_from_zero':
|
|
951
|
+
return `New: ${baseline} was 0.`;
|
|
952
|
+
case 'no_change':
|
|
953
|
+
return `No change from ${baseline}.`;
|
|
954
|
+
case 'no_data_either':
|
|
955
|
+
return 'No data in either period.';
|
|
956
|
+
case 'sign_change':
|
|
957
|
+
return 'The value crossed zero, so there is no percent change.';
|
|
958
|
+
default:
|
|
959
|
+
return '';
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
// The window a KPI's value is compared with, as a noun phrase. An unknown or
|
|
963
|
+
// missing comparison reads as neutral wording rather than a wrong period.
|
|
964
|
+
function kpiBaselineText(against) {
|
|
965
|
+
switch (against) {
|
|
966
|
+
case 'previous_period':
|
|
967
|
+
return 'the previous period';
|
|
968
|
+
case 'previous_week':
|
|
969
|
+
return 'the previous week';
|
|
970
|
+
case 'previous_month':
|
|
971
|
+
return 'the previous month';
|
|
972
|
+
case 'previous_quarter':
|
|
973
|
+
return 'the previous quarter';
|
|
974
|
+
case 'previous_year':
|
|
975
|
+
return 'the same period last year';
|
|
976
|
+
default:
|
|
977
|
+
return 'the comparison period';
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
function capitalize(text) {
|
|
981
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
982
|
+
}
|
|
123
983
|
// A short, human label for a zone: its city plus the current abbreviation,
|
|
124
984
|
// e.g. 'America/New_York' reads 'New York (EDT)'. UTC stays 'UTC', and an
|
|
125
985
|
// unknown zone is shown as its id. An 'Etc/' zone names no city, and its POSIX
|
|
@@ -154,4 +1014,4 @@ export function getZonedNow(timezone) {
|
|
|
154
1014
|
return now;
|
|
155
1015
|
}
|
|
156
1016
|
}
|
|
157
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2Zvcm1hdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDckQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUs1RCw0RUFBNEU7QUFDNUUsZ0ZBQWdGO0FBQ2hGLDZDQUE2QztBQUU3Qyw4RUFBOEU7QUFDOUUsd0VBQXdFO0FBQ3hFLHdFQUF3RTtBQUN4RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSxFQUFFO0FBQ0YsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0UsU0FBUztBQUNULFNBQVMsaUJBQWlCLENBQUMsU0FBa0I7SUFDM0MsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztRQUMvQixDQUFDLENBQUMsRUFBRSxxQkFBcUIsRUFBRSxTQUFTLEVBQUUscUJBQXFCLEVBQUUsU0FBUyxFQUFFO1FBQ3hFLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDVCxDQUFDO0FBRUQsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxLQUFjLEVBQ2QsTUFBZSxFQUNmLFNBQWtCLEVBQ2xCLFlBQVksR0FBRyxJQUFJO0lBRW5CLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUMxRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDOUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM5QixPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FB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TUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUV2QixJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRXpDLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDckQsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmb3JtYXQsIGlzVmFsaWQsIHBhcnNlSVNPIH0gZnJvbSAnZGF0ZS1mbnMnO1xuaW1wb3J0IHsgZm9ybWF0SW5UaW1lWm9uZSwgdG9ab25lZFRpbWUgfSBmcm9tICdkYXRlLWZucy10eic7XG5cbmltcG9ydCB7IFJlcG9ydCB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcblxuXG4vLyBNZWFzdXJlLXZhbHVlIGZvcm1hdHRpbmcgc2hhcmVkIGJ5IHRoZSBLUEkgcmVuZGVyZXIgYW5kIHRoZSBleHBvcnRzIOKAlCB0aGVcbi8vIGNvbmZpZydzIGBmb3JtYXRgIChudW1iZXIgfCBwZXJjZW50IHwgY3VycmVuY3kpIGFuZCBgcHJlY2lzaW9uYCBtZWFuIHRoZSBzYW1lXG4vLyB0aGluZyBvbiBzY3JlZW4sIGluIFBvd2VyUG9pbnQgYW5kIGluIFBERi5cblxuLy8gcGVyY2VudCB0YWtlcyBhIDAtMSByYXRpbyBhbmQgc2hvd3MgaXQgYXMgYSBwZXJjZW50YWdlOiAwLjMgcmVhZHMgMzAlLiBXaXRoXG4vLyBubyBwcmVjaXNpb24gaXQgc2hvd3MgYXQgbW9zdCBvbmUgZGVjaW1hbCAoMC4wMzcgcmVhZHMgMy43JSk7IGEgbmFtZWRcbi8vIHByZWNpc2lvbiBjb3VudHMgdGhlIGRlY2ltYWxzIG9mIHRoZSBwZXJjZW50YWdlLCBub3Qgb2YgdGhlIHJhdGlvLCBzb1xuLy8gcHJlY2lzaW9uIDEgc2hvd3MgMC4zIGFzIDMwLjAlLiBBbiBvbGRlciBzZXJ2ZXIgc2VuZHMgcGVyY2VudCB2YWx1ZXMgYWxyZWFkeVxuLy8geDEwMCAoMzguNSBmb3IgMzguNSUpOyBpdHMgcmVwb3J0cyBjYXJyeSBubyBgcGVyY2VudEZvcm1hdGAsIGFuZCB0aGUgY2FsbGVyXG4vLyBwYXNzZXMgcmF0aW9QZXJjZW50IGZhbHNlIHNvIHRoZSB2YWx1ZSBpcyBwcmludGVkIGFzIGl0IGNhbWUsIHdpdGggYSAlIHNpZ24uXG4vL1xuLy8gV2hlbiB0aGUgbWVhc3VyZSBuYW1lcyBhIHByZWNpc2lvbiBpdCBpcyBwaW5uZWQgYXMgQk9USCB0aGUgbWluaW11bSBhbmQgdGhlXG4vLyBtYXhpbXVtLCBzbyBhIGNvbHVtbiBvZiByYXRlcyBsaW5lcyB1cCBpbnN0ZWFkIG9mIGVhY2ggdmFsdWUgc2hvd2luZyBob3dldmVyXG4vLyBtYW55IGRlY2ltYWxzIGl0IGhhcHBlbnMgdG8gbmVlZC4gVW5kZWZpbmVkIGxlYXZlcyBlYWNoIGZvcm1hdCdzIG93biBkZWZhdWx0XG4vLyBhbG9uZS5cbmZ1bmN0aW9uIGdldEZyYWN0aW9uRGlnaXRzKHByZWNpc2lvbj86IG51bWJlcik6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyB7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUocHJlY2lzaW9uKVxuICAgID8geyBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IHByZWNpc2lvbiwgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiBwcmVjaXNpb24gfVxuICAgIDoge307XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRNZWFzdXJlVmFsdWUoXG4gIHZhbHVlOiB1bmtub3duLFxuICBmb3JtYXQ/OiBzdHJpbmcsXG4gIHByZWNpc2lvbj86IG51bWJlcixcbiAgcmF0aW9QZXJjZW50ID0gdHJ1ZSxcbik6IHN0cmluZyB7XG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykge1xuICAgIHJldHVybiAn4oCUJztcbiAgfVxuXG4gIGNvbnN0IG51bWVyaWMgPSBOdW1iZXIodmFsdWUpO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShudW1lcmljKSkge1xuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgY29uc3QgZnJhY3Rpb25EaWdpdHMgPSBnZXRGcmFjdGlvbkRpZ2l0cyhwcmVjaXNpb24pO1xuXG4gIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgY2FzZSAncGVyY2VudCc6XG4gICAgICBpZiAoIXJhdGlvUGVyY2VudCkge1xuICAgICAgICByZXR1cm4gYCR7bmV3IEludGwuTnVtYmVyRm9ybWF0KHVuZGVmaW5lZCwgeyBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDEsIC4uLmZyYWN0aW9uRGlnaXRzIH0pLmZvcm1hdChudW1lcmljKX0lYDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBJbnRsLk51bWJlckZvcm1hdCh1bmRlZmluZWQsIHtcbiAgICAgICAgc3R5bGU6ICdwZXJjZW50JyxcbiAgICAgICAgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiAxLFxuICAgICAgICAuLi5mcmFjdGlvbkRpZ2l0cyxcbiAgICAgIH0pLmZvcm1hdChudW1lcmljKTtcbiAgICBjYXNlICdjdXJyZW5jeSc6XG4gICAgICByZXR1cm4gbmV3IEludGwuTnVtYmVyRm9ybWF0KHVuZGVmaW5lZCwge1xuICAgICAgICBzdHlsZTogJ2N1cnJlbmN5JyxcbiAgICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgICAvLyBXaG9sZSBkb2xsYXJzIHVubGVzcyB0aGUgbWVhc3VyZSBhc2tzIGZvciBkZWNpbWFscyDigJQgY2VudHMgd2VyZVxuICAgICAgICAvLyB1bnJlcHJlc2VudGFibGUgYmVmb3JlLCBiZWNhdXNlIHRoaXMgd2FzIGhhcmRjb2RlZCB0byAwLlxuICAgICAgICBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDAsXG4gICAgICAgIC4uLmZyYWN0aW9uRGlnaXRzLFxuICAgICAgfSkuZm9ybWF0KG51bWVyaWMpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IEludGwuTnVtYmVyRm9ybWF0KHVuZGVmaW5lZCwgZnJhY3Rpb25EaWdpdHMpLmZvcm1hdChudW1lcmljKTtcbiAgfVxufVxuXG5cbi8vIFRoZSBheGlzIHBlYWsgYXQgd2hpY2ggYSBuYXRpdmUgY2hhcnQncyB2YWx1ZSBheGlzIGdhaW5zIHRob3VzYW5kc1xuLy8gc2VwYXJhdG9ycy4gRnJvbSBoZXJlIHVwIHRoZSB0aWNrcyBhcmUgd2hvbGUgbnVtYmVycyBpbiBwcmFjdGljZTsgYmVsb3cgaXRcbi8vIG5laXRoZXIgdGhlIHNjcmVlbiBub3IgUG93ZXJQb2ludCdzICdHZW5lcmFsJyBzaG93cyBhIHNlcGFyYXRvci5cbmV4cG9ydCBjb25zdCBBWElTX1NFUEFSQVRPUl9USFJFU0hPTEQgPSAxMDAwO1xuXG4vLyBQb3dlclBvaW50J3MgbnVtYmVyIGZvcm1hdCBmb3IgYSBuYXRpdmUgY2hhcnQncyB2YWx1ZSBheGlzLCBtYXRjaGluZyB3aGF0IHRoZVxuLy8gb24tc2NyZWVuIGF4aXMgcHJpbnRzIGJ5IGRlZmF1bHQ6IHRob3VzYW5kcyBzZXBhcmF0b3JzIHdpdGggZWFjaCB0aWNrJ3Mgb3duXG4vLyBkZWNpbWFscy4gRXhjZWwgaGFzIG5vIFwiR2VuZXJhbCB3aXRoIHNlcGFyYXRvcnNcIiwgc28gYW4gYXhpcyByZWFjaGluZyAxLDAwMFxuLy8gKHdoZXJlIHRpY2tzIGFyZSB3aG9sZSBudW1iZXJzKSBnZXRzICcjLCMjMCcsIGFuZCBhIHNtYWxsZXIgcmFuZ2Uga2VlcHNcbi8vICdHZW5lcmFsJyBzbyBmcmFjdGlvbmFsIHRpY2tzICgwLjI1LCAwLjUpIGFyZSBub3Qgcm91bmRlZCBhd2F5LlxuLy9cbi8vIFRoZSBwZWFrIGNvdW50cyBhIG1pc3NpbmcgdmFsdWUgYXMgMC4gQSBzdGFja2VkIGNoYXJ0J3MgcGVhayBpcyBpdHMgdGFsbGVzdFxuLy8gc3RhY2s6IHRoZSBsYXJnZXN0IHN1bSwgcGVyIGNhdGVnb3J5LCBvZiBldmVyeSBzZXJpZXMnIGFic29sdXRlIHZhbHVlLlxuZXhwb3J0IGZ1bmN0aW9uIGNoYXJ0QXhpc0Zvcm1hdENvZGUoc2VyaWVzOiAobnVtYmVyIHwgbnVsbClbXVtdLCBzdGFja2VkOiBib29sZWFuKTogc3RyaW5nIHtcbiAgY29uc3QgbWFnbml0dWRlcyA9IHNlcmllcy5tYXAoKHZhbHVlcykgPT4gdmFsdWVzLm1hcCgodmFsdWUpID0+IE1hdGguYWJzKHZhbHVlID8/IDApKSk7XG5cbiAgY29uc3QgcGVhayA9IHN0YWNrZWRcbiAgICA/IE1hdGgubWF4KDAsIC4uLihtYWduaXR1ZGVzWzBdID8/IFtdKS5tYXAoKF8sIGluZGV4KSA9PiBtYWduaXR1ZGVzXG4gICAgICAucmVkdWNlKChzdW0sIHZhbHVlcykgPT4gc3VtICsgKHZhbHVlc1tpbmRleF0gPz8gMCksIDApKSlcbiAgICA6IE1hdGgubWF4KDAsIC4uLm1hZ25pdHVkZXMuZmxhdCgpKTtcblxuICByZXR1cm4gcGVhayA+PSBBWElTX1NFUEFSQVRPUl9USFJFU0hPTEQgPyAnIywjIzAnIDogJ0dlbmVyYWwnO1xufVxuXG5cbi8vIFRoZSB6b25lIGV2ZXJ5IGRhdGUgaW4gYSByZXBvcnQgaXMgcmVhZCBpbi4gVGhlIHNlcnZlciByZXNvbHZlcyBpdCAodGhlXG4vLyByZXBvcnQncyBvd24gem9uZSwgZWxzZSB0aGUgYXBwbGljYXRpb24ncyBkZWZhdWx0IHJlcG9ydGluZyB6b25lKSBhbmQgc2VuZHNcbi8vIGl0IGFzIGBlZmZlY3RpdmVUaW1lem9uZWAuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCB0aGUgZmllbGQgc3RpbGwgdXNlZCBhXG4vLyByZXBvcnQncyBwaW5uZWQgYHRpbWV6b25lYCwgc28gdGhhdCBjb21lcyBuZXh0OyB0aGUgYnJvd3NlcidzIHpvbmUgaXMgdGhlIGxhc3Rcbi8vIGZhbGxiYWNrLiBUaGlzIGlzIHRoZSBvbmUgcGxhY2UgdGhhdCBjaGFpbiBsaXZlcywgc28gZXZlcnkgZGF0ZSB0aGUgdmlld2VyXG4vLyByZW5kZXJzIG9yIHJlc29sdmVzIGFncmVlcyB3aXRoIGV2ZXJ5IG90aGVyLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZXBvcnRUaW1lem9uZShyZXBvcnQ6IFBpY2s8UmVwb3J0LCAnZWZmZWN0aXZlVGltZXpvbmUnIHwgJ3RpbWV6b25lJz4pOiBzdHJpbmcge1xuICByZXR1cm4gcmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lID8/IHJlcG9ydC50aW1lem9uZSA/PyBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG59XG5cblxuY29uc3QgREFURV9PTkxZX1BBVFRFUk4gPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9JC87XG5jb25zdCBEQVRFX1RJTUVfUEFUVEVSTiA9IC9eKFxcZHs0fS1cXGR7Mn0tXFxkezJ9KVsgVF0oXFxkezJ9OlxcZHsyfTpcXGR7Mn0pKFxcLlxcZCspPyQvO1xuXG4vLyBBIHJlcG9ydCByb3cncyBkYXRlIGNlbGwgYXMgYSBjYWxlbmRhciBkYXkgaW4gdGhlIHJlcG9ydCdzIHpvbmUuXG4vL1xuLy8gUmVwb3J0IHJvd3MgYXJlIHJhdyBkYXRhYmFzZSBzdHJpbmdzLCBub3Qgc2VyaWFsaXplZCBtb2RlbHMsIHNvIHRoZWlyIHNoYXBlXG4vLyBpcyB0aGUgd2lyZSBjb250cmFjdDogYSBEQVRFIGNvbHVtbiBhcnJpdmVzIGFzICdZWVlZLU1NLUREJyBhbmQgYVxuLy8gZGF0ZS1hbmQtdGltZSBjb2x1bW4gYXMgJ1lZWVktTU0tREQgSEg6TU06U1MnIGluIFVUQy4gUmVhZGluZyB0aGF0IHNoYXBlXG4vLyBoZXJlIGRvZXMgbm90IHJlLWRlcml2ZSBhIHNlcnZlciBydWxlOyBpdCBvbmx5IHN0b3BzIHRoZSBicm93c2VyIGd1ZXNzaW5nLlxuLy8gLSBBIGNhbGVuZGFyIGRheSBpcyBuZXZlciBzaGlmdGVkOiBwYXJzZUlTTyByZWFkcyBpdCBhcyBsb2NhbCBtaWRuaWdodCwgc29cbi8vICAgdGhlIGRheSBwcmludGVkIGlzIHRoZSBkYXkgc3RvcmVkLCB3aGF0ZXZlciB0aGUgem9uZS5cbi8vIC0gQW4gaW5zdGFudCBpcyBwaW5uZWQgdG8gVVRDIHdpdGggYW4gZXhwbGljaXQgJ1onLCB0aGVuIHNob3duIGFzIHRoZSBkYXkgaXRcbi8vICAgZmVsbCBvbiBpbiB0aGUgcmVwb3J0J3Mgem9uZSwgdGhlIHNhbWUgZGF5IHRoZSBmaWx0ZXJzIGFuZCB0aW1lIGJ1Y2tldHMgdXNlLlxuLy8gLSBBbnl0aGluZyBlbHNlIGlzIHNob3duIGFzIGl0IGNhbWUsIGFuZCBzbyBpcyBhIHZhbHVlIHRoYXQgaGFzIHRoZSBzaGFwZVxuLy8gICBidXQgbmFtZXMgbm8gcmVhbCBkYXkgKGEgemVybyBkYXRlICcwMDAwLTAwLTAwJywgb3IgJzIwMjYtMDItMzAnKTogb25lXG4vLyAgIGJhZCBjZWxsIG11c3Qgbm90IHRocm93IG91dCBvZiBhIHBpcGUgb3IgYWJvcnQgYW4gZXhwb3J0LlxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJlcG9ydERhdGUodmFsdWU6IHVua25vd24sIHRpbWV6b25lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBjb25zdCB0ZXh0ID0gU3RyaW5nKHZhbHVlKTtcblxuICBpZiAoREFURV9PTkxZX1BBVFRFUk4udGVzdCh0ZXh0KSkge1xuICAgIGNvbnN0IGRheSA9IHBhcnNlSVNPKHRleHQpO1xuXG4gICAgcmV0dXJuIGlzVmFsaWQoZGF5KSA/IGZvcm1hdChkYXksICdNTU0gZCwgeXl5eScpIDogdGV4dDtcbiAgfVxuXG4gIGNvbnN0IGRhdGVUaW1lID0gREFURV9USU1FX1BBVFRFUk4uZXhlYyh0ZXh0KTtcbiAgaWYgKCFkYXRlVGltZSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgY29uc3QgaW5zdGFudCA9IHBhcnNlSVNPKGAke2RhdGVUaW1lWzFdfVQke2RhdGVUaW1lWzJdfVpgKTtcbiAgaWYgKCFpc1ZhbGlkKGluc3RhbnQpKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICAvLyBBbiB1bmtub3duIHpvbmUgbWFrZXMgZGF0ZS1mbnMtdHogdGhyb3c7IFVUQyBzdGlsbCBuYW1lcyBhIHJlYWwgZGF5LlxuICB0cnkge1xuICAgIHJldHVybiBmb3JtYXRJblRpbWVab25lKGluc3RhbnQsIHRpbWV6b25lLCAnTU1NIGQsIHl5eXknKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZvcm1hdEluVGltZVpvbmUoaW5zdGFudCwgJ1VUQycsICdNTU0gZCwgeXl5eScpO1xuICB9XG59XG5cblxuLy8gQSBzaG9ydCwgaHVtYW4gbGFiZWwgZm9yIGEgem9uZTogaXRzIGNpdHkgcGx1cyB0aGUgY3VycmVudCBhYmJyZXZpYXRpb24sXG4vLyBlLmcuICdBbWVyaWNhL05ld19Zb3JrJyByZWFkcyAnTmV3IFlvcmsgKEVEVCknLiBVVEMgc3RheXMgJ1VUQycsIGFuZCBhblxuLy8gdW5rbm93biB6b25lIGlzIHNob3duIGFzIGl0cyBpZC4gQW4gJ0V0Yy8nIHpvbmUgbmFtZXMgbm8gY2l0eSwgYW5kIGl0cyBQT1NJWFxuLy8gc2lnbiBpcyB0aGUgcmV2ZXJzZSBvZiB0aGUgb2Zmc2V0ICgnRXRjL0dNVCs1JyBpcyBHTVQtNSksIHNvIGl0IHJlYWRzIGFzIHRoZVxuLy8gYWJicmV2aWF0aW9uIGFsb25lOiAnRXRjL1VUQycgaXMgJ1VUQycsICdFdGMvR01UKzUnIGlzICdHTVQtNScuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGltZXpvbmVMYWJlbCh0aW1lem9uZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHRpbWV6b25lID09PSAnVVRDJykge1xuICAgIHJldHVybiB0aW1lem9uZTtcbiAgfVxuXG4gIGNvbnN0IHNlZ21lbnRzID0gdGltZXpvbmUuc3BsaXQoJy8nKTtcblxuICB0cnkge1xuICAgIGNvbnN0IGFiYnJldmlhdGlvbiA9IGZvcm1hdEluVGltZVpvbmUobmV3IERhdGUoKSwgdGltZXpvbmUsICd6enonKTtcblxuICAgIHJldHVybiBzZWdtZW50c1swXSA9PT0gJ0V0YydcbiAgICAgID8gYWJicmV2aWF0aW9uXG4gICAgICA6IGAke3NlZ21lbnRzW3NlZ21lbnRzLmxlbmd0aCAtIDFdLnJlcGxhY2UoL18vZywgJyAnKX0gKCR7YWJicmV2aWF0aW9ufSlgO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdGltZXpvbmU7XG4gIH1cbn1cblxuXG4vLyBcIk5vd1wiIGFzIGEgRGF0ZSB3aG9zZSBsb2NhbCBmaWVsZHMgcmVhZCB0aGUgd2FsbCBjbG9jayBpbiB0aGUgZ2l2ZW4gem9uZSwgc29cbi8vIGRhdGUtZm5zIGNhbGVuZGFyIGFyaXRobWV0aWMgKHN0YXJ0T2ZXZWVrLCBzdGFydE9mTW9udGgsIC4uLikgYW5kXG4vLyBkYXRlQm91bmRTdHJpbmcoKSBsYW5kIG9uIHRoZSB6b25lJ3MgY2FsZW5kYXIgZGF5IHJhdGhlciB0aGFuIHRoZSBicm93c2VyJ3MuXG4vLyBBbiB1bmtub3duIHpvbmUgZmFsbHMgYmFjayB0byB0aGUgYnJvd3NlcidzIGNsb2NrLlxuZXhwb3J0IGZ1bmN0aW9uIGdldFpvbmVkTm93KHRpbWV6b25lOiBzdHJpbmcpOiBEYXRlIHtcbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHpvbmVkID0gdG9ab25lZFRpbWUobm93LCB0aW1lem9uZSk7XG5cbiAgICByZXR1cm4gTnVtYmVyLmlzTmFOKHpvbmVkLmdldFRpbWUoKSkgPyBub3cgOiB6b25lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG5vdztcbiAgfVxufVxuIl19
|
|
1017
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2Zvcm1hdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTVELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBcUJyRSw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLGtGQUFrRjtBQUNsRixNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBb0IsT0FBTyxDQUFDO0FBQy9ELE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUF1QixLQUFLLENBQUM7QUFFbEUsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQWtDLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDakYsTUFBTSxFQUFFLHNCQUFzQjtJQUM5QixRQUFRLEVBQUUsd0JBQXdCO0lBQ2xDLFlBQVksRUFBRSxJQUFJO0NBQ25CLENBQUMsQ0FBQztBQUVILE1BQU0sZ0JBQWdCLEdBQUcsWUFBWSxDQUFDO0FBR3RDLDhFQUE4RTtBQUM5RSw2RUFBNkU7QUFDN0Usc0RBQXNEO0FBQ3RELE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxHQUE4QjtJQUNoRSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDVCxPQUFPLHNCQUFzQixDQUFDO0lBQ2hDLENBQUM7SUFFRCxJQUFJLENBQUM7UUFDSCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLHNCQUFzQixD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LEtBQUssWUFBWSxHQUFHLENBQUM7SUFDOUUsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7QUFDSCxDQUFDO0FBR0QsK0VBQStFO0FBQy9FLG9FQUFvRTtBQUNwRSwrRUFBK0U7QUFDL0UscURBQXFEO0FBQ3JELE1BQU0sVUFBVSxXQUFXLENBQUMsUUFBZ0I7SUFDMUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUV2QixJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRXpDLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDckQsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1ZhbGlkLCBwYXJzZUlTTyB9IGZyb20gJ2RhdGUtZm5zJztcbmltcG9ydCB7IGZvcm1hdEluVGltZVpvbmUsIHRvWm9uZWRUaW1lIH0gZnJvbSAnZGF0ZS1mbnMtdHonO1xuXG5pbXBvcnQgeyBSZXBvcnRMaXN0Q29sdW1uRm9ybWF0IH0gZnJvbSAnLi9lbnVtcy9yZXBvcnQtbGlzdC1jb2x1bW4tZm9ybWF0LmVudW0nO1xuaW1wb3J0IHsgUmVwb3J0TnVtYmVyVW5pdHMgfSBmcm9tICcuL2VudW1zL3JlcG9ydC1udW1iZXItdW5pdHMuZW51bSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm1hdCB9IGZyb20gJy4vZW51bXMvcmVwb3J0LXZhbHVlLWZvcm1hdC5lbnVtJztcbmltcG9ydCB7XG4gIENoYXJ0R3JhbnVsYXJpdHksXG4gIENoYXJ0TWVhc3VyZSxcbiAgQ29tcGFyaXNvbkFnYWluc3QsXG4gIENvbXBhcmlzb25Ob3RlQ29kZSxcbiAgQ29tcGFyaXNvbk9mZnNldCxcbiAgQ29tcG9uZW50Q29tcGFyaXNvbixcbiAgS3BpTm90ZUNvZGUsXG4gIE51bWJlckZvcm1hdFNwZWMsXG4gIE91dHB1dE1ldGEsXG4gIE91dHB1dFJvbGUsXG4gIFJlcG9ydCxcbiAgUmVwb3J0Q3VycmVuY3lDb2RlLFxuICBSZXBvcnRGb3JtYXRDb250ZXh0LFxuICBSZXBvcnRMb2NhbGVUYWcsXG4gIFdpbmRvd01ldGEsXG4gIFdpbmRvd05vdGVDb2RlLFxufSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5cblxuLy8gV2hhdCBhIHJlcG9ydCByZWFkcyB3aGVuIHRoZSBzZXJ2ZXIgbmFtZXMgbm8gdXNhYmxlIGxvY2FsZSBvciBjdXJyZW5jeTogYW5cbi8vIG9sZGVyIHNlcnZlciB0aGF0IHNlbmRzIG5laXRoZXIsIG9yIGEgdmFsdWUgdGhpcyBicm93c2VyJ3MgSW50bCBjYW5ub3QgdXNlLlxuLy8gTmV2ZXIgdGhlIGJyb3dzZXIncyBvd24gbG9jYWxlLCBzbyBldmVyeSB2aWV3ZXIgb2YgYSByZXBvcnQgc2VlcyB0aGUgc2FtZSB0ZXh0LlxuZXhwb3J0IGNvbnN0IFJFUE9SVF9GQUxMQkFDS19MT0NBTEU6IFJlcG9ydExvY2FsZVRhZyA9ICdlbi1VUyc7XG5leHBvcnQgY29uc3QgUkVQT1JUX0ZBTExCQUNLX0NVUlJFTkNZOiBSZXBvcnRDdXJyZW5jeUNvZGUgPSAnVVNEJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfRk9STUFUX0NPTlRFWFQ6IFJlYWRvbmx5PFJlcG9ydEZvcm1hdENvbnRleHQ+ID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGxvY2FsZTogUkVQT1JUX0ZBTExCQUNLX0xPQ0FMRSxcbiAgY3VycmVuY3k6IFJFUE9SVF9GQUxMQkFDS19DVVJSRU5DWSxcbiAgcmF0aW9QZXJjZW50OiB0cnVlLFxufSk7XG5cbmNvbnN0IENVUlJFTkNZX1BBVFRFUk4gPSAvXltBLVpdezN9JC87XG5cblxuLy8gVGhlIHNlcnZlcidzIHJlc29sdmVkIGxvY2FsZSBhcyBvbmUgdGhpcyBicm93c2VyIGNhbiBmb3JtYXQgaW4uIEEgbWFsZm9ybWVkXG4vLyB0YWcgKCdlbl9DQScpIG1ha2VzIHN1cHBvcnRlZExvY2FsZXNPZiB0aHJvdywgYW5kIG9uZSBJbnRsIGhhcyBubyBkYXRhIGZvclxuLy8gKCd4eC1ZWScpIGNvbWVzIGJhY2sgZW1wdHk7IGJvdGggcmVhZCB0aGUgZmFsbGJhY2suXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVJlcG9ydExvY2FsZSh0YWc6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBSZXBvcnRMb2NhbGVUYWcge1xuICBpZiAoIXRhZykge1xuICAgIHJldHVybiBSRVBPUlRfRkFMTEJBQ0tfTE9DQUxFO1xuICB9XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gSW50bC5OdW1iZXJGb3JtYXQuc3VwcG9ydGVkTG9jYWxlc09mKFt0YWddKVswXSA/PyBSRVBPUlRfRkFMTEJBQ0tfTE9DQUxFO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gUkVQT1JUX0ZBTExCQUNLX0xPQ0FMRTtcbiAgfVxufVxuXG4vLyBUaGUgc2VydmVyJ3MgcmVzb2x2ZWQgY3VycmVuY3kgYXMgb25lIEludGwgY2FuIGxhYmVsLiBUaGUgc2VydmVyIGRlY2lkZXNcbi8vIHdoaWNoIGNvZGVzIG5hbWUgbW9uZXk7IHRoaXMgb25seSBndWFyZHMgYWdhaW5zdCBhIGNvZGUgSW50bCBjYW5ub3QgdGFrZSBhdFxuLy8gYWxsLiBJdCBpcyBuZXZlciBjaGVja2VkIGFnYWluc3QgdGhlIHJ1bnRpbWUncyBvd24gY3VycmVuY3kgbGlzdCwgd2hpY2hcbi8vIGRpZmZlcnMgYmV0d2VlbiBicm93c2VycyBhbmQgbGVhdmVzIG91dCBjb2RlcyB0aGUgc2VydmVyIG9mZmVycyAoVkVGLCBNUk8pLFxuLy8gc28gZXZlcnkgdmlld2VyIGxhYmVscyBhIHJlcG9ydCdzIG1vbmV5IHRoZSBzYW1lIHdheS5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUmVwb3J0Q3VycmVuY3koY29kZTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IFJlcG9ydEN1cnJlbmN5Q29kZSB7XG4gIGlmICghY29kZSB8fCAhQ1VSUkVOQ1lfUEFUVEVSTi50ZXN0KGNvZGUpKSB7XG4gICAgcmV0dXJuIFJFUE9SVF9GQUxMQkFDS19DVVJSRU5DWTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgbnVtYmVyRm9ybWF0KFJFUE9SVF9GQUxMQkFDS19MT0NBTEUsIHsgc3R5bGU6ICdjdXJyZW5jeScsIGN1cnJlbmN5OiBjb2RlIH0pO1xuXG4gICAgcmV0dXJuIGNvZGU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBSRVBPUlRfRkFMTEJBQ0tfQ1VSUkVOQ1k7XG4gIH1cbn1cblxuLy8gVGhlIG9uZSBwbGFjZSBhIHJlcG9ydCdzIGZvcm1hdCBjb250ZXh0IGlzIGJ1aWx0OiB0aGUgc2VydmVyJ3MgZWZmZWN0aXZlXG4vLyBsb2NhbGUgYW5kIGN1cnJlbmN5IChhYnNlbnQgb24gYW4gb2xkZXIgc2VydmVyLCB3aGljaCB0aGVuIHJlYWRzIGVuLVVTL1VTRClcbi8vIGFuZCB3aGV0aGVyIGl0cyBwZXJjZW50IG1lYXN1cmVzIGFycml2ZSBhcyAwLTEgcmF0aW9zLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVGb3JtYXRDb250ZXh0KFxuICByZXBvcnQ6IFBpY2s8UmVwb3J0LCAnZWZmZWN0aXZlTG9jYWxlJyB8ICdlZmZlY3RpdmVDdXJyZW5jeScgfCAncGVyY2VudEZvcm1hdCc+LFxuKTogUmVwb3J0Rm9ybWF0Q29udGV4dCB7XG4gIHJldHVybiB7XG4gICAgbG9jYWxlOiByZXNvbHZlUmVwb3J0TG9jYWxlKHJlcG9ydC5lZmZlY3RpdmVMb2NhbGUpLFxuICAgIGN1cnJlbmN5OiByZXNvbHZlUmVwb3J0Q3VycmVuY3kocmVwb3J0LmVmZmVjdGl2ZUN1cnJlbmN5KSxcbiAgICByYXRpb1BlcmNlbnQ6IHJlcG9ydC5wZXJjZW50Rm9ybWF0ID09PSAncmF0aW8nLFxuICB9O1xufVxuXG5cbi8vIEJ1aWxkaW5nIGFuIEludGwgZm9ybWF0dGVyIGlzIGZhciBzbG93ZXIgdGhhbiB1c2luZyBvbmUsIGFuZCBhIGNoYXJ0IGZvcm1hdHNcbi8vIGV2ZXJ5IHRpY2sgYW5kIHRvb2x0aXAgdmFsdWUsIHNvIGVhY2ggZGlzdGluY3QgbG9jYWxlICsgb3B0aW9ucyAoKyB6b25lKSBpc1xuLy8gYnVpbHQgb25jZSBhbmQgcmV1c2VkLlxuY29uc3QgTlVNQkVSX0ZPUk1BVFMgPSBuZXcgTWFwPHN0cmluZywgSW50bC5OdW1iZXJGb3JtYXQ+KCk7XG5jb25zdCBEQVRFX0ZPUk1BVFMgPSBuZXcgTWFwPHN0cmluZywgSW50bC5EYXRlVGltZUZvcm1hdD4oKTtcblxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlckZvcm1hdChsb2NhbGU6IHN0cmluZywgb3B0aW9uczogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zKTogSW50bC5OdW1iZXJGb3JtYXQge1xuICBjb25zdCBrZXkgPSBgJHtsb2NhbGV9fCR7SlNPTi5zdHJpbmdpZnkob3B0aW9ucyl9YDtcbiAgbGV0IGZvcm1hdHRlciA9IE5VTUJFUl9GT1JNQVRTLmdldChrZXkpO1xuXG4gIGlmICghZm9ybWF0dGVyKSB7XG4gICAgZm9ybWF0dGVyID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KGxvY2FsZSwgb3B0aW9ucyk7XG4gICAgTlVNQkVSX0ZPUk1BVFMuc2V0KGtleSwgZm9ybWF0dGVyKTtcbiAgfVxuXG4gIHJldHVybiBmb3JtYXR0ZXI7XG59XG5cbi8vIE5vIHpvbmUgZm9ybWF0cyBpbiB0aGUgYnJvd3NlcidzIG93biB6b25lLCB3aGljaCBpcyByaWdodCBmb3IgYSBjYWxlbmRhciBkYXlcbi8vIHBhcnNlZCBhcyBsb2NhbCBtaWRuaWdodDogdGhlIGRheSBwcmludGVkIGlzIHRoZSBkYXkgc3RvcmVkLlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVGb3JtYXQoXG4gIGxvY2FsZTogc3RyaW5nLFxuICBvcHRpb25zOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyxcbiAgdGltZVpvbmU/OiBzdHJpbmcsXG4pOiBJbnRsLkRhdGVUaW1lRm9ybWF0IHtcbiAgY29uc3Qga2V5ID0gYCR7bG9jYWxlfXwke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMpfXwke3RpbWVab25lID8/ICcnfWA7XG4gIGxldCBmb3JtYXR0ZXIgPSBEQVRFX0ZPUk1BVFMuZ2V0KGtleSk7XG5cbiAgaWYgKCFmb3JtYXR0ZXIpIHtcbiAgICBmb3JtYXR0ZXIgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChsb2NhbGUsIHsgLi4ub3B0aW9ucywgdGltZVpvbmUgfSk7XG4gICAgREFURV9GT1JNQVRTLnNldChrZXksIGZvcm1hdHRlcik7XG4gIH1cblxuICByZXR1cm4gZm9ybWF0dGVyO1xufVxuXG5cbi8vIE51bWJlciBmb3JtYXR0aW5nOiB0aGUgb25lIGVuZ2luZSBiZWhpbmQgZXZlcnkgbnVtZXJpYyBzbG90IChhIGNoYXJ0XG4vLyBtZWFzdXJlLCBhIEtQSSBtZWFzdXJlLCBhIGxpc3QgY29sdW1uLCBhIGNyb3NzLXRhYidzIGNlbGxzKSwgc28gYSBmb3JtYXRcbi8vIG1lYW5zIHRoZSBzYW1lIHRoaW5nIG9uIHNjcmVlbiwgaW4gdGhlIFBERiBhbmQgaW4gUG93ZXJQb2ludC4gVGhlIGRhdGEgc3RheXNcbi8vIHJhdzsgb25seSB3aGF0IGlzIHNob3duIGNoYW5nZXMuIFRoZSBydWxlczpcbi8vIC0gRW1wdHk6IG51bGwsIHVuZGVmaW5lZCwgJycsICctJyBhbmQgYSBub24tZmluaXRlIG51bWJlciBwcmludCB0aGUgY2FsbGVyJ3Ncbi8vICAgYGVtcHR5YCAoJ+KAlCcgdW5sZXNzIGl0IG5hbWVzIGFub3RoZXIpLlxuLy8gLSBOdW1lcmljOiBhIGZpbml0ZSBudW1iZXIsIG9yIGEgc3RyaW5nIHRoYXQgc3BlbGxzIG9uZSBwbGFpbmx5ICgnMTIzNC41MCcsXG4vLyAgICctM2UyJykuIEFueXRoaW5nIGVsc2UgKCckMSwyMzQnLCBhbiBpZCB3aXRoIGxldHRlcnMsICcgJykgcHJpbnRzIGFzIGl0XG4vLyAgIGNhbWUsIHNpbmNlIGEgY29sdW1uIHRoZSBTUUwgYWxyZWFkeSBmb3JtYXR0ZWQgaXMgdGV4dC5cbi8vIC0gU3R5bGVzOiBudW1iZXIgaXMgYSBwbGFpbiBkZWNpbWFsOyBjdXJyZW5jeSBpcyB0aGUgcmVwb3J0J3MgY3VycmVuY3lcbi8vICAgd3JpdHRlbiBpbiBpdHMgbG9jYWxlIHdpdGggaXRzIHN5bWJvbCAoVVNEIHJlYWRzICckMSwyMzUnIGluIGVuLVVTIGFuZFxuLy8gICAnVVMkMSwyMzUnIGluIGVuLUNBOyBFVVIgcmVhZHMgJzEgMjM1IOKCrCcgaW4gZnItRlIpOyBwZXJjZW50IHRha2VzIGEgMC0xXG4vLyAgIHJhdGlvICgwLjMgcmVhZHMgMzAlKSwgb3IsIGZyb20gYW4gb2xkZXIgc2VydmVyIHRoYXQgc2VuZHMgcGVyY2VudCB2YWx1ZXNcbi8vICAgYWxyZWFkeSB4MTAwLCBhIGRlY2ltYWwgd2l0aCBhICUgc2lnbi4gUHJlY2lzaW9uIG9yIHVuaXRzIHdpdGhvdXQgYSBmb3JtYXRcbi8vICAgbWVhbiBudW1iZXIuXG4vLyAtIERlY2ltYWxzOiBhIHByZWNpc2lvbiBwaW5zIGJvdGggdGhlIG1pbmltdW0gYW5kIHRoZSBtYXhpbXVtLCBzbyBhIGNvbHVtblxuLy8gICBvZiByYXRlcyBsaW5lcyB1cC4gV2l0aG91dCBvbmU6IGF0IG1vc3Qgb25lIGZvciBhIHBlcmNlbnQgYW5kIGZvciBhblxuLy8gICBhYmJyZXZpYXRlZCB2YWx1ZSAoMS4ySyksIHdob2xlIHVuaXRzIGZvciBjdXJyZW5jeSwgdGhlIGxvY2FsZSdzIGRlZmF1bHRcbi8vICAgZm9yIGEgbnVtYmVyLlxuLy8gLSBVbml0czogdGhvdXNhbmRzIGFuZCBtaWxsaW9ucyBkaXZpZGUgYW5kIGFkZCBhIEsgb3IgTSBhZnRlciB0aGUgZGlnaXRzXG4vLyAgICgnJDEuMksnLCAnMSwySyAkJyk7IGF1dG8gcGlja3MgcGVyIHZhbHVlIGJ5IHNpemUsIGFuZCBhIHZhbHVlIHRoYXQgd291bGRcbi8vICAgcm91bmQgdG8gMTAwMEsgcmVhZHMgMU0uIFVuaXRzIG5ldmVyIGFwcGx5IHRvIGEgcGVyY2VudC5cbi8vIC0gTmVnYXRpdmVzIGtlZXAgdGhlIGxvY2FsZSdzIGxlYWRpbmcgbWludXMuIEEgbmVnYXRpdmUgdGhhdCByb3VuZHMgdG8gemVyb1xuLy8gICBwcmludHMgYXMgemVybywgbmV2ZXIgJy0wJy5cbi8vIC0gUm91bmRpbmcgaXMgSW50bCdzLCBvbiB0aGUgZGlnaXRzIHNob3duLiBFdmVyeSB2YWx1ZSBpcyB3cml0dGVuIGluIHRoZVxuLy8gICBjb250ZXh0J3MgbG9jYWxlLCBuZXZlciB0aGUgYnJvd3NlcidzLlxuXG4vLyBUaGUgbW9zdCBkZWNpbWFscyBhIHByZWNpc2lvbiBwaW5zOiB0aGUgc2VydmVyJ3Mgc2NoZW1hIGJvdW5kLlxuY29uc3QgTUFYX1BSRUNJU0lPTiA9IDY7XG4vLyBBdCBtb3N0IG9uZSBkZWNpbWFsIGZvciBhIHBlcmNlbnQsIGFuZCBmb3IgYW4gYWJicmV2aWF0ZWQgdmFsdWUgKDEuMkspLlxuY29uc3QgUEVSQ0VOVF9ERUNJTUFMUyA9IDE7XG5jb25zdCBTQ0FMRURfREVDSU1BTFMgPSAxO1xuLy8gTW9uZXkgc2hvd3Mgd2hvbGUgdW5pdHMgdW5sZXNzIGEgcHJlY2lzaW9uIGFza3MgZm9yIGRlY2ltYWxzLlxuY29uc3QgQ1VSUkVOQ1lfREVDSU1BTFMgPSAwO1xuLy8gQSBjdXJyZW5jeSBheGlzIHdob3NlIHRpY2tzIG5lZWQgZGVjaW1hbHMgc2hvd3MgY2VudHMsIG5vdCB0ZW50aHMuXG5jb25zdCBDVVJSRU5DWV9BWElTX0RFQ0lNQUxTID0gMjtcbi8vIFdoYXQgYSBtaXNzaW5nIHZhbHVlIHByaW50cyB1bmxlc3MgdGhlIGNhbGxlciBuYW1lcyBpdHMgb3duLlxuY29uc3QgRU1QVFlfVkFMVUUgPSAn4oCUJztcbi8vIFRoZSB0aWNrIGNvdW50IGEgdmFsdWUgYXhpcyBhaW1zIGZvciwgYXMgRUNoYXJ0cycgc3BsaXROdW1iZXIgZGVmYXVsdC5cbmNvbnN0IEFYSVNfVElDS1MgPSA1O1xuXG4vLyBBIGNoYW5nZSdzIHNpZ246IGEgcGx1cyBvbiBhIHBvc2l0aXZlIHZhbHVlLCBub3RoaW5nIG9uIHplcm8uXG5jb25zdCBTSUdORUQ6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyA9IHsgc2lnbkRpc3BsYXk6ICdleGNlcHRaZXJvJyB9O1xuXG5jb25zdCBOVU1FUklDX1BBVFRFUk4gPSAvXlxccypbLStdPyhcXGQrXFwuP1xcZCp8XFwuXFxkKykoW2VFXVstK10/XFxkKyk/XFxzKiQvO1xuLy8gVGhlIGZvcm1hdFRvUGFydHMgdHlwZXMgdGhhdCBjYXJyeSBhIG51bWJlcidzIGRpZ2l0cyBhbmQgc2VwYXJhdG9ycy5cbmNvbnN0IE5VTUJFUl9QQVJUUyA9IG5ldyBTZXQ8SW50bC5OdW1iZXJGb3JtYXRQYXJ0VHlwZXM+KFsnaW50ZWdlcicsICdncm91cCcsICdkZWNpbWFsJywgJ2ZyYWN0aW9uJ10pO1xuY29uc3QgRElHSVRfUEFSVFMgPSBuZXcgU2V0PEludGwuTnVtYmVyRm9ybWF0UGFydFR5cGVzPihbJ2ludGVnZXInLCAnZnJhY3Rpb24nXSk7XG5cbi8vIEEgbnVtZXJpYyBmb3JtYXQncyB1bml0cyBvbmNlIGRlY2lkZWQ6IGF1dG8gaXMgcmVzb2x2ZWQgdG8gb25lIG9mIHRoZXNlLlxuZXhwb3J0IHR5cGUgUmVzb2x2ZWRVbml0cyA9IFJlcG9ydE51bWJlclVuaXRzLk5vbmUgfCBSZXBvcnROdW1iZXJVbml0cy5UaG91c2FuZHMgfCBSZXBvcnROdW1iZXJVbml0cy5NaWxsaW9ucztcblxuaW50ZXJmYWNlIFVuaXRTY2FsZSB7XG4gIGRpdmlzb3I6IG51bWJlcjtcbiAgc3VmZml4OiBzdHJpbmc7XG4gIC8vIFRoZSBQb3dlclBvaW50L0V4Y2VsIHNjYWxpbmcgY29tbWFzOiBlYWNoIG9uZSBkaXZpZGVzIGJ5IDEsMDAwLlxuICBjb21tYXM6IHN0cmluZztcbn1cblxuY29uc3QgVU5JVF9TQ0FMRVMgPSBuZXcgTWFwPFJlc29sdmVkVW5pdHMsIFVuaXRTY2FsZT4oW1xuICBbUmVwb3J0TnVtYmVyVW5pdHMuVGhvdXNhbmRzLCB7IGRpdmlzb3I6IDFlMywgc3VmZml4OiAnSycsIGNvbW1hczogJywnIH1dLFxuICBbUmVwb3J0TnVtYmVyVW5pdHMuTWlsbGlvbnMsIHsgZGl2aXNvcjogMWU2LCBzdWZmaXg6ICdNJywgY29tbWFzOiAnLCwnIH1dLFxuXSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRm9ybWF0TnVtYmVyT3B0aW9ucyB7XG4gIC8vIFdoYXQgYW4gZW1wdHkgdmFsdWUgcHJpbnRzOiAn4oCUJyBmb3IgYSBLUEkgb3IgYSB0b29sdGlwLCAnJyBmb3IgYSBjZWxsLlxuICBlbXB0eT86IHN0cmluZztcbiAgLy8gVW5pdHMgYWxyZWFkeSBkZWNpZGVkIGZvciB0aGUgd2hvbGUgY2hhcnQsIGluIHBsYWNlIG9mIHRoZSBzcGVjJ3Mgb3duLlxuICB1bml0cz86IFJlc29sdmVkVW5pdHM7XG4gIC8vIERlY2ltYWxzIGFscmVhZHkgZGVjaWRlZCBmb3IgdGhlIHdob2xlIGNoYXJ0LCBwaW5uZWQgYXMgbWluIGFuZCBtYXguIG51bGxcbiAgLy8gbGVhdmVzIHRoZSBzcGVjJ3Mgb3duLlxuICBkZWNpbWFscz86IG51bWJlciB8IG51bGw7XG4gIC8vIFdyaXRlcyBhIHBsdXMgYmVmb3JlIGEgcG9zaXRpdmUgdmFsdWUsIGFzIGEgY2hhbmdlIHJlYWRzICgnKzEyJScpLiBaZXJvLFxuICAvLyBhbmQgYSB2YWx1ZSB3aG9zZSBzaG93biBkaWdpdHMgYXJlIGFsbCB6ZXJvLCBzdGF5cyB1bnNpZ25lZC5cbiAgc2lnbmVkPzogYm9vbGVhbjtcbn1cblxuLy8gSG93IGEgY2hhcnQncyB2YWx1ZSBheGlzIHdyaXRlcyBpdHMgdGlja3MsIGRlY2lkZWQgb25jZSBwZXIgY2hhcnQuXG5leHBvcnQgaW50ZXJmYWNlIENoYXJ0TnVtYmVyRm9ybWF0IHtcbiAgdW5pdHM6IFJlc29sdmVkVW5pdHM7XG4gIC8vIFBpbm5lZCBkZWNpbWFscywgb3IgbnVsbCBmb3IgYSBwbGFpbiBudW1iZXIgd2hvc2UgdGlja3Mga2VlcCB0aGVpciBvd24uXG4gIGRlY2ltYWxzOiBudW1iZXIgfCBudWxsO1xufVxuXG4vLyBUaGUgdmFsdWUgYXMgYSBmaW5pdGUgbnVtYmVyIHdoZW4gaXQgaXMgb25lIG9yIHBsYWlubHkgc3BlbGxzIG9uZSwgZWxzZVxuLy8gbnVsbC5cbmV4cG9ydCBmdW5jdGlvbiB0b0Zpbml0ZU51bWJlcih2YWx1ZTogdW5rbm93bik6IG51bWJlciB8IG51bGwge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpID8gdmFsdWUgOiBudWxsO1xuICB9XG5cbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgfHwgIU5VTUVSSUNfUEFUVEVSTi50ZXN0KHZhbHVlKSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgbnVtZXJpYyA9IE51bWJlcih2YWx1ZSk7XG5cbiAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShudW1lcmljKSA/IG51bWVyaWMgOiBudWxsO1xufVxuXG4vLyBXaGV0aGVyIGEgc2xvdCBhc2tzIHRvIGJlIGZvcm1hdHRlZCBhdCBhbGwuIEEgc2xvdCB3aXRob3V0IHRoZXNlIGtleXMsIG9yIGFcbi8vIGxpc3QgY29sdW1uIHdob3NlIGZvcm1hdCBpcyBkYXRlLCBrZWVwcyBpdHMgb3duIHJlbmRlcmluZy4gVW5pdHMgbm9uZSBpcyB0aGVcbi8vIHNhbWUgYXMgbm8gdW5pdHMga2V5LCBhcyBpdCBpcyBvbiB0aGUgc2VydmVyLlxuZXhwb3J0IGZ1bmN0aW9uIGhhc051bWJlckZvcm1hdChzcGVjPzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwpOiBib29sZWFuIHtcbiAgaWYgKCFzcGVjIHx8IHNwZWMuZm9ybWF0ID09PSBSZXBvcnRMaXN0Q29sdW1uRm9ybWF0LkRhdGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdmFsdWVGb3JtYXQoc3BlYykgIT09IG51bGxcbiAgICB8fCAoc3BlYy5wcmVjaXNpb24gPz8gbnVsbCkgIT09IG51bGxcbiAgICB8fCAoKHNwZWMudW5pdHMgPz8gUmVwb3J0TnVtYmVyVW5pdHMuTm9uZSkgIT09IFJlcG9ydE51bWJlclVuaXRzLk5vbmUpO1xufVxuXG4vLyBUaGUgdW5pdHMgYSB2YWx1ZSBpcyB3cml0dGVuIGluLiBhdXRvIGRlY2lkZXMgYnkgdGhlIG1hZ25pdHVkZTogYSBtaWxsaW9uXG4vLyBhbmQgdXAgcmVhZHMgTSwgYSB0aG91c2FuZCBhbmQgdXAgSywgdW5sZXNzIHRoZSB2YWx1ZSB3b3VsZCB0aGVuIHJvdW5kIHRvXG4vLyAxMDAwSyBhdCB0aGVzZSBkZWNpbWFscywgd2hpY2ggcmVhZHMgMU0gaW5zdGVhZC5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlVW5pdHMoXG4gIHVuaXRzOiBSZXBvcnROdW1iZXJVbml0cyB8IG51bGwgfCB1bmRlZmluZWQsXG4gIG1hZ25pdHVkZTogbnVtYmVyLFxuICBkZWNpbWFsczogbnVtYmVyLFxuKTogUmVzb2x2ZWRVbml0cyB7XG4gIHN3aXRjaCAodW5pdHMpIHtcbiAgICBjYXNlIFJlcG9ydE51bWJlclVuaXRzLlRob3VzYW5kczpcbiAgICBjYXNlIFJlcG9ydE51bWJlclVuaXRzLk1pbGxpb25zOlxuICAgICAgcmV0dXJuIHVuaXRzO1xuICAgIGNhc2UgUmVwb3J0TnVtYmVyVW5pdHMuQXV0bzpcbiAgICAgIHJldHVybiBhdXRvVW5pdHMoTWF0aC5hYnMobWFnbml0dWRlKSwgZGVjaW1hbHMpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gUmVwb3J0TnVtYmVyVW5pdHMuTm9uZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhdXRvVW5pdHMobWFnbml0dWRlOiBudW1iZXIsIGRlY2ltYWxzOiBudW1iZXIpOiBSZXNvbHZlZFVuaXRzIHtcbiAgaWYgKG1hZ25pdHVkZSA+PSAxZTYpIHtcbiAgICByZXR1cm4gUmVwb3J0TnVtYmVyVW5pdHMuTWlsbGlvbnM7XG4gIH1cblxuICBpZiAobWFnbml0dWRlIDwgMWUzKSB7XG4gICAgcmV0dXJuIFJlcG9ydE51bWJlclVuaXRzLk5vbmU7XG4gIH1cblxuICByZXR1cm4gcm91bmRUbyhtYWduaXR1ZGUgLyAxZTMsIGRlY2ltYWxzKSA+PSAxMDAwXG4gICAgPyBSZXBvcnROdW1iZXJVbml0cy5NaWxsaW9uc1xuICAgIDogUmVwb3J0TnVtYmVyVW5pdHMuVGhvdXNhbmRzO1xufVxuXG4vLyBUaGUgdmFsdWUgcm91bmRlZCBhcyBJbnRsIHJvdW5kcyBpdCBmb3IgZGlzcGxheSwgc28gdGhlIEstdG8tTSBwcm9tb3Rpb25cbi8vIGFncmVlcyB3aXRoIHRoZSBkaWdpdHMgYWN0dWFsbHkgc2hvd24uXG5mdW5jdGlvbiByb3VuZFRvKHZhbHVlOiBudW1iZXIsIGRlY2ltYWxzOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBkaWdpdHMgPSBjbGFtcERlY2ltYWxzKGRlY2ltYWxzKSA/PyAwO1xuXG4gIC8vIEEgZml4ZWQgbG9jYWxlIG9ubHkgc28gTnVtYmVyKCkgY2FuIHBhcnNlIHRoZSByb3VuZGVkIGRpZ2l0cyBiYWNrLlxuICByZXR1cm4gTnVtYmVyKG51bWJlckZvcm1hdChSRVBPUlRfRkFMTEJBQ0tfTE9DQUxFLCB7XG4gICAgdXNlR3JvdXBpbmc6IGZhbHNlLFxuICAgIG1pbmltdW1GcmFjdGlvbkRpZ2l0czogMCxcbiAgICBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IGRpZ2l0cyxcbiAgfSkuZm9ybWF0KHZhbHVlKSk7XG59XG5cbi8vIE9uZSB2YWx1ZSwgd3JpdHRlbiBieSB0aGUgcnVsZXMgYWJvdmUuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0TnVtYmVyKFxuICB2YWx1ZTogdW5rbm93bixcbiAgc3BlYzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwgfCB1bmRlZmluZWQsXG4gIGNvbnRleHQ6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4gIG9wdGlvbnM6IEZvcm1hdE51bWJlck9wdGlvbnMgPSB7fSxcbik6IHN0cmluZyB7XG4gIGlmIChpc0VtcHR5VmFsdWUodmFsdWUpKSB7XG4gICAgcmV0dXJuIG9wdGlvbnMuZW1wdHkgPz8gRU1QVFlfVkFMVUU7XG4gIH1cblxuICBjb25zdCBudW1lcmljID0gdG9GaW5pdGVOdW1iZXIodmFsdWUpO1xuICBpZiAobnVtZXJpYyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgY29uc3Qgc3R5bGUgPSByZXNvbHZlU3R5bGUoc3BlYyk7XG4gIGNvbnN0IHByZWNpc2lvbiA9IGNsYW1wRGVjaW1hbHMoc3BlYz8ucHJlY2lzaW9uKTtcbiAgY29uc3QgdW5pdHMgPSBzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudFxuICAgID8gUmVwb3J0TnVtYmVyVW5pdHMuTm9uZVxuICAgIDogb3B0aW9ucy51bml0cyA/PyByZXNvbHZlVW5pdHMoc3BlYz8udW5pdHMsIG51bWVyaWMsIHByZWNpc2lvbiA/PyBTQ0FMRURfREVDSU1BTFMpO1xuICBjb25zdCBzY2FsZSA9IFVOSVRfU0NBTEVTLmdldCh1bml0cyk7XG4gIGNvbnN0IGRlY2ltYWxzID0gY2xhbXBEZWNpbWFscyhvcHRpb25zLmRlY2ltYWxzKSA/PyBwcmVjaXNpb247XG4gIGNvbnN0IGZvcm1hdHRlciA9IG51bWJlckZvcm1hdChjb250ZXh0LmxvY2FsZSwge1xuICAgIC4uLnN0eWxlT3B0aW9ucyhzdHlsZSwgY29udGV4dCwgZGVjaW1hbHMsICEhc2NhbGUpLFxuICAgIC4uLihvcHRpb25zLnNpZ25lZCA/IFNJR05FRCA6IHt9KSxcbiAgfSk7XG4gIGNvbnN0IHRleHQgPSB3cml0ZU51bWJlcihmb3JtYXR0ZXIsIChudW1lcmljID09PSAwID8gMCA6IG51bWVyaWMpIC8gKHNjYWxlPy5kaXZpc29yID8/IDEpLCBzY2FsZT8uc3VmZml4KTtcblxuICByZXR1cm4gc3R5bGUgPT09IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgJiYgIWNvbnRleHQucmF0aW9QZXJjZW50ID8gYCR7dGV4dH0lYCA6IHRleHQ7XG59XG5cbmZ1bmN0aW9uIGlzRW1wdHlWYWx1ZSh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGxcbiAgICB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkXG4gICAgfHwgdmFsdWUgPT09ICcnXG4gICAgfHwgdmFsdWUgPT09ICctJ1xuICAgIHx8ICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmICFOdW1iZXIuaXNGaW5pdGUodmFsdWUpKTtcbn1cblxuLy8gVGhlIHZhbHVlIGZvcm1hdCBhIHNsb3QgbmFtZXMsIG9yIG51bGwgd2hlbiBpdCBuYW1lcyBub25lIChvciBvbmx5IGRhdGUpLlxuZnVuY3Rpb24gdmFsdWVGb3JtYXQoc3BlYzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwgfCB1bmRlZmluZWQpOiBSZXBvcnRWYWx1ZUZvcm1hdCB8IG51bGwge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhSZXBvcnRWYWx1ZUZvcm1hdCkuZmluZCgoZm9ybWF0KSA9PiBmb3JtYXQgPT09IHNwZWM/LmZvcm1hdCkgPz8gbnVsbDtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0eWxlKHNwZWM6IE51bWJlckZvcm1hdFNwZWMgfCBudWxsIHwgdW5kZWZpbmVkKTogUmVwb3J0VmFsdWVGb3JtYXQge1xuICByZXR1cm4gdmFsdWVGb3JtYXQoc3BlYykgPz8gUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyO1xufVxuXG4vLyBBIHVzYWJsZSBkZWNpbWFsIGNvdW50LCBvciBudWxsLiBBIHN0b3JlZCB2YWx1ZSBvdXRzaWRlIHRoZSBzY2hlbWEncyBib3VuZHNcbi8vIGlzIGJyb3VnaHQgaW5zaWRlIHRoZW0gcmF0aGVyIHRoYW4gdGhyb3duIG9uIGJ5IEludGwuXG5mdW5jdGlvbiBjbGFtcERlY2ltYWxzKGRlY2ltYWxzOiBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHwgbnVsbCB7XG4gIHJldHVybiB0eXBlb2YgZGVjaW1hbHMgPT09ICdudW1iZXInICYmIE51bWJlci5pc0Zpbml0ZShkZWNpbWFscylcbiAgICA/IE1hdGgubWluKE1BWF9QUkVDSVNJT04sIE1hdGgubWF4KDAsIE1hdGgucm91bmQoZGVjaW1hbHMpKSlcbiAgICA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT3B0aW9ucyhcbiAgc3R5bGU6IFJlcG9ydFZhbHVlRm9ybWF0LFxuICBjb250ZXh0OiBSZXBvcnRGb3JtYXRDb250ZXh0LFxuICBkZWNpbWFsczogbnVtYmVyIHwgbnVsbCxcbiAgc2NhbGVkOiBib29sZWFuLFxuKTogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zIHtcbiAgY29uc3QgZnJhY3Rpb25EaWdpdHMgPSBmcmFjdGlvbkRpZ2l0T3B0aW9ucyhkZWNpbWFscywgZGVmYXVsdERlY2ltYWxzKHN0eWxlLCBzY2FsZWQpKTtcblxuICBzd2l0Y2ggKHN0eWxlKSB7XG4gICAgY2FzZSBSZXBvcnRWYWx1ZUZvcm1hdC5DdXJyZW5jeTpcbiAgICAgIHJldHVybiB7IC4uLmN1cnJlbmN5T3B0aW9ucyhjb250ZXh0LmN1cnJlbmN5KSwgLi4uZnJhY3Rpb25EaWdpdHMgfTtcbiAgICBjYXNlIFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQ6XG4gICAgICByZXR1cm4gY29udGV4dC5yYXRpb1BlcmNlbnQgPyB7IHN0eWxlOiAncGVyY2VudCcsIC4uLmZyYWN0aW9uRGlnaXRzIH0gOiBmcmFjdGlvbkRpZ2l0cztcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZyYWN0aW9uRGlnaXRzO1xuICB9XG59XG5cbmZ1bmN0aW9uIGN1cnJlbmN5T3B0aW9ucyhjdXJyZW5jeTogUmVwb3J0Q3VycmVuY3lDb2RlKTogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zIHtcbiAgcmV0dXJuIHsgc3R5bGU6ICdjdXJyZW5jeScsIGN1cnJlbmN5LCBjdXJyZW5jeURpc3BsYXk6ICdzeW1ib2wnIH07XG59XG5cbi8vIFRoZSBtb3N0IGRlY2ltYWxzIGEgc3R5bGUgc2hvd3Mgd2hlbiBub3RoaW5nIHBpbnMgdGhlbTsgbnVsbCBsZWF2ZXMgSW50bCdzXG4vLyBvd24gZGVmYXVsdC5cbmZ1bmN0aW9uIGRlZmF1bHREZWNpbWFscyhzdHlsZTogUmVwb3J0VmFsdWVGb3JtYXQsIHNjYWxlZDogYm9vbGVhbik6IG51bWJlciB8IG51bGwge1xuICBpZiAoc2NhbGVkKSB7XG4gICAgcmV0dXJuIFNDQUxFRF9ERUNJTUFMUztcbiAgfVxuXG4gIHN3aXRjaCAoc3R5bGUpIHtcbiAgICBjYXNlIFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQ6XG4gICAgICByZXR1cm4gUEVSQ0VOVF9ERUNJTUFMUztcbiAgICBjYXNlIFJlcG9ydFZhbHVlRm9ybWF0LkN1cnJlbmN5OlxuICAgICAgcmV0dXJuIENVUlJFTkNZX0RFQ0lNQUxTO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vLyBQaW5uZWQgZGVjaW1hbHMgc2V0IGJvdGggYm91bmRzLiBPdGhlcndpc2UgYSBtYXhpbXVtIGFsc28gc2V0cyB0aGUgbWluaW11bVxuLy8gdG8gemVybywgc28gbm8gZW5naW5lIHRocm93cyBvbiBhIG1heGltdW0gYmVsb3cgYSBjdXJyZW5jeSdzIG93biBtaW5pbXVtLlxuZnVuY3Rpb24gZnJhY3Rpb25EaWdpdE9wdGlvbnMocGlubmVkOiBudW1iZXIgfCBudWxsLCBtYXhpbXVtOiBudW1iZXIgfCBudWxsKTogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zIHtcbiAgaWYgKHBpbm5lZCAhPT0gbnVsbCkge1xuICAgIHJldHVybiB7IG1pbmltdW1GcmFjdGlvbkRpZ2l0czogcGlubmVkLCBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IHBpbm5lZCB9O1xuICB9XG5cbiAgcmV0dXJuIG1heGltdW0gPT09IG51bGwgPyB7fSA6IHsgbWluaW11bUZyYWN0aW9uRGlnaXRzOiAwLCBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IG1heGltdW0gfTtcbn1cblxuLy8gVGhlIGZvcm1hdHRlZCB2YWx1ZSwgd2l0aCB0aGUgdW5pdHMgbGV0dGVyIGFmdGVyIGl0cyBkaWdpdHMuIEEgbmVnYXRpdmVcbi8vIHdob3NlIHNob3duIGRpZ2l0cyBhcmUgYWxsIHplcm8gaXMgd3JpdHRlbiBhcyB6ZXJvLCBzbyBubyAnLTAnIGFwcGVhcnMuXG5mdW5jdGlvbiB3cml0ZU51bWJlcihmb3JtYXR0ZXI6IEludGwuTnVtYmVyRm9ybWF0LCB2YWx1ZTogbnVtYmVyLCBzdWZmaXg/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodmFsdWUgPj0gMCAmJiAhc3VmZml4KSB7XG4gICAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXQodmFsdWUpO1xuICB9XG5cbiAgY29uc3QgcGFydHMgPSBmb3JtYXR0ZXIuZm9ybWF0VG9QYXJ0cyh2YWx1ZSk7XG5cbiAgaWYgKHZhbHVlIDwgMCAmJiAhaGFzTm9uWmVyb0RpZ2l0KGZvcm1hdHRlciwgcGFydHMpKSB7XG4gICAgcmV0dXJuIHdyaXRlTnVtYmVyKGZvcm1hdHRlciwgMCwgc3VmZml4KTtcbiAgfVxuXG4gIGlmICghc3VmZml4KSB7XG4gICAgcmV0dXJuIHBhcnRzLm1hcCgocGFydCkgPT4gcGFydC52YWx1ZSkuam9pbignJyk7XG4gIH1cblxuICBjb25zdCBsYXN0ID0gcGFydHMucmVkdWNlKChmb3VuZCwgcGFydCwgaW5kZXgpID0+IE5VTUJFUl9QQVJUUy5oYXMocGFydC50eXBlKSA/IGluZGV4IDogZm91bmQsIC0xKTtcblxuICByZXR1cm4gW1xuICAgIC4uLnBhcnRzLnNsaWNlKDAsIGxhc3QgKyAxKS5tYXAoKHBhcnQpID0+IHBhcnQudmFsdWUpLFxuICAgIHN1ZmZpeCxcbiAgICAuLi5wYXJ0cy5zbGljZShsYXN0ICsgMSkubWFwKChwYXJ0KSA9PiBwYXJ0LnZhbHVlKSxcbiAgXS5qb2luKCcnKTtcbn1cblxuLy8gQ29tcGFyZWQgd2l0aCB0aGUgbG9jYWxlJ3Mgb3duIHplcm8sIHNvIGEgbnVtYmVyaW5nIHN5c3RlbSBvdGhlciB0aGFuXG4vLyAwLTkgaXMgcmVhZCBjb3JyZWN0bHkuXG5mdW5jdGlvbiBoYXNOb25aZXJvRGlnaXQoZm9ybWF0dGVyOiBJbnRsLk51bWJlckZvcm1hdCwgcGFydHM6IEludGwuTnVtYmVyRm9ybWF0UGFydFtdKTogYm9vbGVhbiB7XG4gIGNvbnN0IHplcm8gPSBmb3JtYXR0ZXIuZm9ybWF0VG9QYXJ0cygwKS5maW5kKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICdpbnRlZ2VyJyk/LnZhbHVlID8/ICcwJztcblxuICByZXR1cm4gcGFydHMuc29tZSgocGFydCkgPT4gRElHSVRfUEFSVFMuaGFzKHBhcnQudHlwZSlcbiAgICAmJiBBcnJheS5mcm9tKHBhcnQudmFsdWUpLnNvbWUoKGNoYXJhY3RlcikgPT4gY2hhcmFjdGVyICE9PSB6ZXJvKSk7XG59XG5cblxuLy8gT3V0cHV0IHZhbHVlczogYSBjb2x1bW4gdGhlIHNlcnZlciBtYXJrcyBpbiBDb21wb25lbnREYXRhLm91dHB1dHMgKGFcbi8vIGNvbXBhcmVkIHZhbHVlLCBhIHJhbmssIGEgc2hhcmUpIHdyaXR0ZW4gYnkgd2hhdCBpdCBpcy4gVGhlIGRhdGEgc3RheXMgcmF3O1xuLy8gZXZlcnkgbnVtYmVyIHN0aWxsIGdvZXMgdGhyb3VnaCBmb3JtYXROdW1iZXIuIFRoZSBydWxlczpcbi8vIC0gVGhlIGZvcm1hdDogYSBzbG90J3Mgb3duIGV4cGxpY2l0IGZvcm1hdCBhbHdheXMgd2lucy4gT3RoZXJ3aXNlIGEgY3VycmVudCxcbi8vICAgcHJpb3Igb3IgY2hhbmdlIGNvbHVtbiB0YWtlcyBpdHMgc291cmNlIG1lYXN1cmUncyBmb3JtYXQ7IGEgcGVyY2VudCBjaGFuZ2Vcbi8vICAgaXMgYSBwZXJjZW50OyBhIHJhbmsgaXMgYSB3aG9sZSBudW1iZXI7IGEgc2hhcmUgaXMgYSBwZXJjZW50IHRvIDEgZGVjaW1hbC5cbi8vICAgQW4gb3duIHByZWNpc2lvbiBvciB1bml0cyBzdGlsbCBhcHBsaWVzIG92ZXIgdGhvc2UgZGVmYXVsdHMuXG4vLyAtIFNpZ25zOiBhIGNoYW5nZSBhbmQgYSBwZXJjZW50IGNoYW5nZSBhcmUgc2lnbmVkICgnKzU3OScsICctMzEuMSUnKS5cbi8vIC0gUG9pbnRzOiBhIGNoYW5nZSBvZiBhIHBlcmNlbnQtZm9ybWF0IHZhbHVlLCBhbmQgYW55IHNoYXJlIGNoYW5nZSwgaXMgYVxuLy8gICBkaWZmZXJlbmNlIG9mIHR3byByYXRlcywgc28gaXQgcHJpbnRzIGluIHBlcmNlbnRhZ2UgcG9pbnRzLCBzaWduZWQgYW5kIHRvXG4vLyAgIDEgZGVjaW1hbCB1bmxlc3MgYSBwcmVjaXNpb24gcGlucyBvdGhlcnM6IDAuMSByZWFkcyAnKzEwLjAgcHAnLlxuLy8gLSBNaXNzaW5nOiBhIG1pc3NpbmcgcHJpb3IsIG9yIGEgY2hhbmdlIG9yIHBlcmNlbnQgY2hhbmdlIGxlZnQgZW1wdHkgYnlcbi8vICAgb25lLCBwcmludHMgJ+KAlCcgdGl0bGVkIHdpdGggdGhlIGZsb29yICgnTm8gYmFzZWxpbmU6IG5vIGRhdGEgYmVmb3JlXG4vLyAgIE1hciAzLCAyMDI2JyksIG9yIGZvciBhIHJhbmsgb3IgYSBzaGFyZSB3aXRoIHRoZSBwZXJpb2QgdGhlIHJvdyB3YXNcbi8vICAgYWJzZW50IGZyb20gKCdObyByYW5rIGluIHRoZSBwcmlvciBwZXJpb2QnKTsgYSBwZXJjZW50IGNoYW5nZSBvdmVyIGEgcHJpb3Igb2YgMCBwcmludHMgJ24vYScgdGl0bGVkXG4vLyAgICdQcmlvciB3YXMgMCcuIEFueSBvdGhlciBtaXNzaW5nIHZhbHVlIHByaW50cyAn4oCUJyAob3IgdGhlIGNhbGxlcidzIGVtcHR5KS5cbi8vIC0gUmFuayBjaGFuZ2U6IHByaW9yIG1pbnVzIGN1cnJlbnQsIHNvIGEgcmlzZSBpcyBwb3NpdGl2ZTogJ+KWsiAyJywgJ+KWvCAxJyxcbi8vICAgJ+KAkycgZm9yIG5vbmUsIGFuZCAnbmV3JyBmb3IgYW4gZW1wdHkgY2hhbmdlIHdob3NlIHByaW9yIHJhbmsgaXMgbWlzc2luZ1xuLy8gICBvciBub3QgcGFzc2VkIChhIHJvdyBhbHdheXMgaGFzIGEgY3VycmVudCByYW5rLCBzbyBvbmx5IHRoZSBwcmlvciBsYWNrcykuXG4vLyBBIHBlcmNlbnQgY2hhbmdlIGFuZCBhIHNoYXJlIGFyZSAwLTEgZnJhY3Rpb25zIHdoYXRldmVyIHRoZSByZXBvcnQnc1xuLy8gcGVyY2VudEZvcm1hdDogdGhlIHNlcnZlciBjb21wdXRlcyB0aGVtLCBuZXZlciBhIHN0b3JlZCB2YWx1ZS5cblxuLy8gQSBtaXNzaW5nIGNvbXBhcmlzb24gdmFsdWUgcHJpbnRzIEVNUFRZX1ZBTFVFIHdoYXRldmVyIHRoZSBjYWxsZXIncyBlbXB0eS5cbmNvbnN0IE5PVF9BUFBMSUNBQkxFX1ZBTFVFID0gJ24vYSc7XG5jb25zdCBORVdfUkFOS19WQUxVRSA9ICduZXcnO1xuY29uc3QgUkFOS19VTkNIQU5HRURfVkFMVUUgPSAn4oCTJztcbmNvbnN0IFJBTktfVVBfTUFSSyA9ICfilrInO1xuY29uc3QgUkFOS19ET1dOX01BUksgPSAn4pa8JztcbmNvbnN0IFBPSU5UU19TVUZGSVggPSAncHAnO1xuY29uc3QgTk9fUFJJT1JfUkFOS19USVRMRSA9ICdObyByYW5rIGluIHRoZSBwcmlvciBwZXJpb2QnO1xuY29uc3QgTk9fUFJJT1JfU0hBUkVfVElUTEUgPSAnTm8gc2hhcmUgaW4gdGhlIHByaW9yIHBlcmlvZCc7XG4vLyBQZXJjZW50YWdlIHBvaW50cyBhbmQgYSBzaGFyZSBhcmUgd3JpdHRlbiB0byBvbmUgZGVjaW1hbCB1bmxlc3MgcGlubmVkLlxuY29uc3QgUE9JTlRTX0RFQ0lNQUxTID0gMTtcbmNvbnN0IFNIQVJFX0RFQ0lNQUxTID0gMTtcblxuY29uc3QgUkFOS19ERUZBVUxUX1NQRUM6IFJlYWRvbmx5PE51bWJlckZvcm1hdFNwZWM+ID0gT2JqZWN0LmZyZWV6ZSh7IGZvcm1hdDogUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyLCBwcmVjaXNpb246IDAgfSk7XG5jb25zdCBTSEFSRV9ERUZBVUxUX1NQRUM6IFJlYWRvbmx5PE51bWJlckZvcm1hdFNwZWM+ID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGZvcm1hdDogUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudCxcbiAgcHJlY2lzaW9uOiBTSEFSRV9ERUNJTUFMUyxcbn0pO1xuY29uc3QgUEVSQ0VOVF9DSEFOR0VfREVGQVVMVF9TUEVDOiBSZWFkb25seTxOdW1iZXJGb3JtYXRTcGVjPiA9IE9iamVjdC5mcmVlemUoeyBmb3JtYXQ6IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgfSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3V0cHV0VmFsdWVPcHRpb25zIHtcbiAgLy8gVGhlIHNvdXJjZSBtZWFzdXJlJ3MgZm9ybWF0IChPdXRwdXRNZXRhLm1lYXN1cmUncyBzbG90KSwgd2hpY2ggYSBjdXJyZW50LFxuICAvLyBwcmlvciBvciBjaGFuZ2UgY29sdW1uIHRha2VzIHdoZW4gaXRzIG93biBzbG90IG5hbWVzIG5vbmUuXG4gIG1lYXN1cmVTcGVjPzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGw7XG4gIC8vIFRoZSByb3cncyBwcmlvciB2YWx1ZSBpbiB0aGUgc2FtZSBsYW5lIChzZWUgbGFuZU91dHB1dEFsaWFzKSwgZm9yIGEgY2hhbmdlXG4gIC8vIG9yIGEgcGVyY2VudCBjaGFuZ2U6IGl0IHRlbGxzIGEgbWlzc2luZyBiYXNlbGluZSAoJ+KAlCcpIGZyb20gYSB6ZXJvIG9uZVxuICAvLyAoJ24vYScpLCBhbmQgYSBuZXcgcmFuayBmcm9tIGFuIHVucmFua2VkIHJvdy4gTGVhdmUgaXQgb3V0IHdoZW4gdW5rbm93bi5cbiAgcHJpb3I/OiB1bmtub3duO1xuICAvLyBDb21wb25lbnREYXRhLmNvbXBhcmlzb24uZmxvb3I6IHRoZSBmaXJzdCBkYXkgd2l0aCBkYXRhLCBuYW1lZCBpbiB0aGVcbiAgLy8gbm8tYmFzZWxpbmUgdGl0bGUuXG4gIGZsb29yPzogc3RyaW5nIHwgbnVsbDtcbiAgLy8gV2hhdCBhIG1pc3NpbmcgY3VycmVudCBvciBwbGFpbiB2YWx1ZSBwcmludHMgKCcnIGZvciBhIGNlbGwpLiBBIG1pc3NpbmdcbiAgLy8gY29tcGFyaXNvbiB2YWx1ZSBhbHdheXMgcHJpbnRzICfigJQnLlxuICBlbXB0eT86IHN0cmluZztcbn1cblxuLy8gQW4gb3V0cHV0IHZhbHVlIGFzIHNob3duLCBhbmQgd2h5IGl0IHJlYWRzIHNvIHdoZW4gdGhhdCBpcyBub3Qgb2J2aW91c1xuLy8gKG51bGwgb3RoZXJ3aXNlKTogZm9yIGEgdG9vbHRpcCBvciBhIHRpdGxlIGF0dHJpYnV0ZS5cbmV4cG9ydCBpbnRlcmZhY2UgRm9ybWF0dGVkT3V0cHV0VmFsdWUge1xuICB0ZXh0OiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmcgfCBudWxsO1xufVxuXG4vLyBPbmUgb3V0cHV0IHZhbHVlLCB3cml0dGVuIGJ5IHRoZSBydWxlcyBhYm92ZS4gV2l0aG91dCBvdXRwdXQgbWV0YWRhdGEgKGFcbi8vIHBsYWluIG1lYXN1cmUgY29sdW1uLCBhbiBvbGRlciBzZXJ2ZXIpIGl0IGlzIGZvcm1hdE51bWJlciB3aXRoIHRoZSBzbG90J3Ncbi8vIG93biBmb3JtYXQuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0T3V0cHV0VmFsdWUoXG4gIHZhbHVlOiB1bmtub3duLFxuICBvdXRwdXQ6IE91dHB1dE1ldGEgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBzcGVjOiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgY29udGV4dDogUmVwb3J0Rm9ybWF0Q29udGV4dCxcbiAgb3B0aW9uczogT3V0cHV0VmFsdWVPcHRpb25zID0ge30sXG4pOiBGb3JtYXR0ZWRPdXRwdXRWYWx1ZSB7XG4gIGlmICghb3V0cHV0KSB7XG4gICAgcmV0dXJuIHBsYWluT3V0cHV0KGZvcm1hdE51bWJlcih2YWx1ZSwgc3BlYywgY29udGV4dCwgeyBlbXB0eTogb3B0aW9ucy5lbXB0eSB9KSk7XG4gIH1cblxuICBpZiAob3V0cHV0LmtpbmQgPT09ICdyYW5rJyAmJiBvdXRwdXQucm9sZSA9PT0gJ2NoYW5nZScpIHtcbiAgICByZXR1cm4gZm9ybWF0UmFua0NoYW5nZSh2YWx1ZSwgc3BlYywgY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cblxuICBjb25zdCByb2xlID0gb3V0cHV0LnJvbGU7XG4gIGNvbnN0IGVmZmVjdGl2ZSA9IG91dHB1dEZvcm1hdFNwZWMob3V0cHV0LCBzcGVjLCBvcHRpb25zLm1lYXN1cmVTcGVjKTtcblxuICBpZiAoaXNFbXB0eVZhbHVlKHZhbHVlKSkge1xuICAgIHJldHVybiBtaXNzaW5nT3V0cHV0KG91dHB1dCwgY29udGV4dCwgb3B0aW9ucyk7XG4gIH1cblxuICBpZiAocm9sZSA9PT0gJ2NoYW5nZScgJiYgaXNQb2ludHNDaGFuZ2Uob3V0cHV0LCBlZmZlY3RpdmUpKSB7XG4gICAgcmV0dXJuIHBsYWluT3V0cHV0KGZvcm1hdFBvaW50cyh2YWx1ZSwgb3V0cHV0LCBlZmZlY3RpdmUsIGNvbnRleHQpKTtcbiAgfVxuXG4gIGNvbnN0IHNpZ25lZCA9IHJvbGUgPT09ICdjaGFuZ2UnIHx8IHJvbGUgPT09ICdwZXJjZW50X2NoYW5nZSc7XG4gIGNvbnN0IHJhdGlvQ29udGV4dCA9IHJvbGUgPT09ICdwZXJjZW50X2NoYW5nZScgfHwgb3V0cHV0LmtpbmQgPT09ICdzaGFyZSdcbiAgICA/IHsgLi4uY29udGV4dCwgcmF0aW9QZXJjZW50OiB0cnVlIH1cbiAgICA6IGNvbnRleHQ7XG5cbiAgcmV0dXJuIHBsYWluT3V0cHV0KGZvcm1hdE51bWJlcih2YWx1ZSwgZWZmZWN0aXZlLCByYXRpb0NvbnRleHQsIHsgc2lnbmVkIH0pKTtcbn1cblxuLy8gVGhlIGFsaWFzIG9mIHRoZSBvdXRwdXQgdGhhdCBwbGF5cyBgcm9sZWAgaW4gdGhlIHNhbWUgbGFuZSBhcyBgYWxpYXNgOiB0aGVcbi8vIHNhbWUgbWVhc3VyZSBhbmQga2luZCwgYW5kIChmb3IgYSBwcmlvciwgY2hhbmdlIG9yIHBlcmNlbnQgY2hhbmdlKSB0aGUgc2FtZVxuLy8gcHJpb3IgbGFuZS4gQSBtZWFzdXJlIGNvbXBhcmVzIGFnYWluc3Qgb25lIGxhbmUgb25seSAodHdvIGNvbXBhcmVzIG9uIG9uZVxuLy8gdmFsdWUgYXJlIHR3byBtZWFzdXJlcyksIHNvIGEgY3VycmVudCB2YWx1ZSdzIGxhbmUgaXMgd2hpY2hldmVyIG9uZSBpdHNcbi8vIG1lYXN1cmUncyBwcmlvciBjb2x1bW5zIGNhcnJ5LCBsYW5lIDIgYXMgcmVhZGlseSBhcyBsYW5lIDEuIEEgY2hhbmdlIGNvbHVtblxuLy8gZmluZHMgaXRzIHByaW9yIHRoaXMgd2F5IHRvIHBhc3MgYXMgT3V0cHV0VmFsdWVPcHRpb25zLnByaW9yLiBudWxsIHdoZW4gdGhlXG4vLyBzZXJ2ZXIgc2VuZHMgbm8gc3VjaCBjb2x1bW4uXG5leHBvcnQgZnVuY3Rpb24gbGFuZU91dHB1dEFsaWFzKFxuICBvdXRwdXRzOiBSZWNvcmQ8c3RyaW5nLCBPdXRwdXRNZXRhPiB8IG51bGwgfCB1bmRlZmluZWQsXG4gIGFsaWFzOiBzdHJpbmcsXG4gIHJvbGU6IE91dHB1dFJvbGUsXG4pOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3Qgc291cmNlID0gb3V0cHV0cz8uW2FsaWFzXTtcblxuICBpZiAoIXNvdXJjZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgYW55TGFuZSA9IHNvdXJjZS5yb2xlID09PSAnY3VycmVudCcgfHwgc291cmNlLm9mZnNldCA9PT0gbnVsbDtcbiAgY29uc3QgZm91bmQgPSBPYmplY3QuZW50cmllcyhvdXRwdXRzID8/IHt9KS5maW5kKChbLCBtZXRhXSkgPT4gbWV0YS5tZWFzdXJlID09PSBzb3VyY2UubWVhc3VyZVxuICAgICYmIG1ldGEua2luZCA9PT0gc291cmNlLmtpbmRcbiAgICAmJiBtZXRhLnJvbGUgPT09IHJvbGVcbiAgICAmJiAocm9sZSA9PT0gJ2N1cnJlbnQnIHx8IChhbnlMYW5lID8gbWV0YS5vZmZzZXQgIT09IG51bGwgOiBtZXRhLm9mZnNldCA9PT0gc291cmNlLm9mZnNldCkpKTtcblxuICByZXR1cm4gZm91bmQgPyBmb3VuZFswXSA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIHBsYWluT3V0cHV0KHRleHQ6IHN0cmluZyk6IEZvcm1hdHRlZE91dHB1dFZhbHVlIHtcbiAgcmV0dXJuIHsgdGV4dCwgdGl0bGU6IG51bGwgfTtcbn1cblxuLy8gVGhlIGZvcm1hdCBhbiBvdXRwdXQgaXMgd3JpdHRlbiBpbjogdGhlIHNsb3QncyBvd24gZXhwbGljaXQgZm9ybWF0LCBlbHNlXG4vLyB0aGUgZGVmYXVsdCBmb3Igd2hhdCBpdCBob2xkcywgd2l0aCBhbnkgb3duIHByZWNpc2lvbiBvciB1bml0cyBvdmVyIGl0LlxuZnVuY3Rpb24gb3V0cHV0Rm9ybWF0U3BlYyhcbiAgb3V0cHV0OiBPdXRwdXRNZXRhLFxuICBvd246IE51bWJlckZvcm1hdFNwZWMgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBtZWFzdXJlU3BlYzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwgfCB1bmRlZmluZWQsXG4pOiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCB7XG4gIGlmICh2YWx1ZUZvcm1hdChvd24pICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIG93bjtcbiAgfVxuXG4gIGlmIChvdXRwdXQua2luZCA9PT0gJ3JhbmsnKSB7XG4gICAgcmV0dXJuIHdpdGhPd25EaWdpdHMoUkFOS19ERUZBVUxUX1NQRUMsIG93bik7XG4gIH1cblxuICBpZiAob3V0cHV0LmtpbmQgPT09ICdzaGFyZScpIHtcbiAgICByZXR1cm4gd2l0aE93bkRpZ2l0cyhTSEFSRV9ERUZBVUxUX1NQRUMsIG93bik7XG4gIH1cblxuICBpZiAob3V0cHV0LnJvbGUgPT09ICdwZXJjZW50X2NoYW5nZScpIHtcbiAgICByZXR1cm4gd2l0aE93bkRpZ2l0cyhQRVJDRU5UX0NIQU5HRV9ERUZBVUxUX1NQRUMsIG93bik7XG4gIH1cblxuICByZXR1cm4gbWVhc3VyZVNwZWMgPyB3aXRoT3duRGlnaXRzKG1lYXN1cmVTcGVjLCBvd24pIDogb3duID8/IG51bGw7XG59XG5cbi8vIFRoZSBiYXNlIGZvcm1hdCB3aXRoIHRoZSBzbG90J3Mgb3duIHByZWNpc2lvbiBhbmQgdW5pdHMgb3ZlciBpdC5cbmZ1bmN0aW9uIHdpdGhPd25EaWdpdHMoYmFzZTogTnVtYmVyRm9ybWF0U3BlYywgb3duOiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCB8IHVuZGVmaW5lZCk6IE51bWJlckZvcm1hdFNwZWMge1xuICByZXR1cm4ge1xuICAgIC4uLmJhc2UsXG4gICAgLi4uKChvd24/LnByZWNpc2lvbiA/PyBudWxsKSAhPT0gbnVsbCA/IHsgcHJlY2lzaW9uOiBvd24ucHJlY2lzaW9uIH0gOiB7fSksXG4gICAgLi4uKChvd24/LnVuaXRzID8/IG51bGwpICE9PSBudWxsID8geyB1bml0czogb3duLnVuaXRzIH0gOiB7fSksXG4gIH07XG59XG5cbi8vIEEgY2hhbmdlIGJldHdlZW4gdHdvIHJhdGVzOiBhIHNoYXJlJ3MsIG9yIGEgcGVyY2VudC1mb3JtYXQgdmFsdWUncy5cbmZ1bmN0aW9uIGlzUG9pbnRzQ2hhbmdlKG91dHB1dDogT3V0cHV0TWV0YSwgc3BlYzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIG91dHB1dC5raW5kID09PSAnc2hhcmUnIHx8IHJlc29sdmVTdHlsZShzcGVjKSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudDtcbn1cblxuLy8gQSByYXRlIGNoYW5nZSBpbiBwZXJjZW50YWdlIHBvaW50cy4gQSBzaGFyZSBhbmQgYSAwLTEgcGVyY2VudCBhcmUgc2NhbGVkXG4vLyB4MTAwOyBhbiBvbGRlciBzZXJ2ZXIncyBwZXJjZW50IHZhbHVlcyBhbHJlYWR5IGFyZS5cbmZ1bmN0aW9uIGZvcm1hdFBvaW50cyhcbiAgdmFsdWU6IHVua25vd24sXG4gIG91dHB1dDogT3V0cHV0TWV0YSxcbiAgc3BlYzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwsXG4gIGNvbnRleHQ6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4pOiBzdHJpbmcge1xuICBjb25zdCBudW1lcmljID0gdG9GaW5pdGVOdW1iZXIodmFsdWUpO1xuICBpZiAobnVtZXJpYyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgY29uc3QgcG9pbnRzID0gb3V0cHV0LmtpbmQgPT09ICdzaGFyZScgfHwgY29udGV4dC5yYXRpb1BlcmNlbnQgPyBudW1lcmljICogMTAwIDogbnVtZXJpYztcbiAgY29uc3QgZGVjaW1hbHMgPSBjbGFtcERlY2ltYWxzKHNwZWM/LnByZWNpc2lvbikgPz8gUE9JTlRTX0RFQ0lNQUxTO1xuICBjb25zdCB0ZXh0ID0gZm9ybWF0TnVtYmVyKHBvaW50cywgeyBmb3JtYXQ6IFJlcG9ydFZhbHVlRm9ybWF0Lk51bWJlciB9LCBjb250ZXh0LCB7IGRlY2ltYWxzLCBzaWduZWQ6IHRydWUgfSk7XG5cbiAgcmV0dXJuIGAke3RleHR9ICR7UE9JTlRTX1NVRkZJWH1gO1xufVxuXG4vLyBBIG1pc3Npbmcgb3V0cHV0IHZhbHVlLiBBIG1pc3NpbmcgcHJpb3IsIG9yIGEgZGVsdGEgYSBtaXNzaW5nIHByaW9yIGxlZnRcbi8vIGVtcHR5LCBoYXMgbm8gYmFzZWxpbmU7IGEgcGVyY2VudCBjaGFuZ2Ugb3ZlciBhIHplcm8gcHJpb3IgaGFzIG5vbmUgdG9cbi8vIGRpdmlkZSBieS5cbmZ1bmN0aW9uIG1pc3NpbmdPdXRwdXQoXG4gIG91dHB1dDogT3V0cHV0TWV0YSxcbiAgY29udGV4dDogUmVwb3J0Rm9ybWF0Q29udGV4dCxcbiAgb3B0aW9uczogT3V0cHV0VmFsdWVPcHRpb25zLFxuKTogRm9ybWF0dGVkT3V0cHV0VmFsdWUge1xuICBjb25zdCByb2xlID0gb3V0cHV0LnJvbGU7XG5cbiAgaWYgKHJvbGUgPT09ICdwcmlvcicpIHtcbiAgICByZXR1cm4geyB0ZXh0OiBFTVBUWV9WQUxVRSwgdGl0bGU6IG1pc3NpbmdQcmlvclRpdGxlKG91dHB1dCwgb3B0aW9ucy5mbG9vciwgY29udGV4dC5sb2NhbGUpIH07XG4gIH1cblxuICBpZiAocm9sZSA9PT0gJ2NoYW5nZScgfHwgcm9sZSA9PT0gJ3BlcmNlbnRfY2hhbmdlJykge1xuICAgIGNvbnN0IHByaW9yID0gb3B0aW9ucy5wcmlvcjtcblxuICAgIGlmIChyb2xlID09PSAncGVyY2VudF9jaGFuZ2UnICYmIHRvRmluaXRlTnVtYmVyKHByaW9yKSA9PT0gMCkge1xuICAgICAgcmV0dXJuIHsgdGV4dDogTk9UX0FQUExJQ0FCTEVfVkFMVUUsIHRpdGxlOiAnUHJpb3Igd2FzIDAnIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRleHQ6IEVNUFRZX1ZBTFVFLFxuICAgICAgdGl0bGU6IHByaW9yICE9PSB1bmRlZmluZWQgJiYgaXNFbXB0eVZhbHVlKHByaW9yKVxuICAgICAgICA/IG1pc3NpbmdQcmlvclRpdGxlKG91dHB1dCwgb3B0aW9ucy5mbG9vciwgY29udGV4dC5sb2NhbGUpXG4gICAgICAgIDogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHBsYWluT3V0cHV0KG9wdGlvbnMuZW1wdHkgPz8gRU1QVFlfVkFMVUUpO1xufVxuXG4vLyBXaHkgYSBwcmlvciBpcyBtaXNzaW5nLiBBIHZhbHVlJ3MgcHJpb3IgaXMgbWlzc2luZyB3aGVuIGl0cyB3aW5kb3cgZW5kc1xuLy8gYmVmb3JlIHRoZSBkYXRhIHN0YXJ0cy4gQSByYW5rJ3Mgb3IgYSBzaGFyZSdzIGlzIG1pc3Npbmcgd2hlbiB0aGUgcm93IGhhZFxuLy8gbm8gcmFuayBvciBzaGFyZSBpbiB0aGUgcHJpb3IgcGVyaW9kLCB3aGF0ZXZlciB0aGUgZmxvb3IuXG5mdW5jdGlvbiBtaXNzaW5nUHJpb3JUaXRsZShcbiAgb3V0cHV0OiBPdXRwdXRNZXRhLFxuICBmbG9vcjogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcsXG4pOiBzdHJpbmcge1xuICBpZiAob3V0cHV0LmtpbmQgPT09ICdyYW5rJykge1xuICAgIHJldHVybiBOT19QUklPUl9SQU5LX1RJVExFO1xuICB9XG5cbiAgaWYgKG91dHB1dC5raW5kID09PSAnc2hhcmUnKSB7XG4gICAgcmV0dXJuIE5PX1BSSU9SX1NIQVJFX1RJVExFO1xuICB9XG5cbiAgcmV0dXJuIG5vQmFzZWxpbmVUaXRsZShmbG9vciwgbG9jYWxlKTtcbn1cblxuZnVuY3Rpb24gbm9CYXNlbGluZVRpdGxlKGZsb29yOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLCBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyk6IHN0cmluZyB7XG4gIGNvbnN0IGRheSA9IGZsb29yID8gZm9ybWF0RGF5KGZsb29yLCBsb2NhbGUpIDogJyc7XG5cbiAgcmV0dXJuIGRheSA/IGBObyBiYXNlbGluZTogbm8gZGF0YSBiZWZvcmUgJHtkYXl9YCA6ICdObyBiYXNlbGluZSc7XG59XG5cbi8vIEEgcmFuayBjaGFuZ2U6IHByaW9yIHJhbmsgbWludXMgY3VycmVudCwgc28gbW92aW5nIHVwIGlzIHBvc2l0aXZlLlxuZnVuY3Rpb24gZm9ybWF0UmFua0NoYW5nZShcbiAgdmFsdWU6IHVua25vd24sXG4gIHNwZWM6IE51bWJlckZvcm1hdFNwZWMgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBjb250ZXh0OiBSZXBvcnRGb3JtYXRDb250ZXh0LFxuICBvcHRpb25zOiBPdXRwdXRWYWx1ZU9wdGlvbnMsXG4pOiBGb3JtYXR0ZWRPdXRwdXRWYWx1ZSB7XG4gIGlmIChpc0VtcHR5VmFsdWUodmFsdWUpKSB7XG4gICAgcmV0dXJuIGlzRW1wdHlWYWx1ZShvcHRpb25zLnByaW9yKVxuICAgICAgPyB7IHRleHQ6IE5FV19SQU5LX1ZBTFVFLCB0aXRsZTogTk9fUFJJT1JfUkFOS19USVRMRSB9XG4gICAgICA6IHBsYWluT3V0cHV0KEVNUFRZX1ZBTFVFKTtcbiAgfVxuXG4gIGNvbnN0IG51bWVyaWMgPSB0b0Zpbml0ZU51bWJlcih2YWx1ZSk7XG4gIGlmIChudW1lcmljID09PSBudWxsKSB7XG4gICAgcmV0dXJuIHBsYWluT3V0cHV0KFN0cmluZyh2YWx1ZSkpO1xuICB9XG5cbiAgY29uc3QgcmFua1NwZWMgPSB2YWx1ZUZvcm1hdChzcGVjKSAhPT0gbnVsbCA/IHNwZWMgOiB3aXRoT3duRGlnaXRzKFJBTktfREVGQVVMVF9TUEVDLCBzcGVjKTtcbiAgY29uc3QgcGxhY2VzID0gZm9ybWF0TnVtYmVyKE1hdGguYWJzKG51bWVyaWMpLCByYW5rU3BlYywgY29udGV4dCk7XG5cbiAgaWYgKHBsYWNlcyA9PT0gZm9ybWF0TnVtYmVyKDAsIHJhbmtTcGVjLCBjb250ZXh0KSkge1xuICAgIHJldHVybiBwbGFpbk91dHB1dChSQU5LX1VOQ0hBTkdFRF9WQUxVRSk7XG4gIH1cblxuICByZXR1cm4gcGxhaW5PdXRwdXQoYCR7bnVtZXJpYyA+IDAgPyBSQU5LX1VQX01BUksgOiBSQU5LX0RPV05fTUFSS30gJHtwbGFjZXN9YCk7XG59XG5cblxuLy8gQSBjaGFydCdzIHZhbHVlIGF4aXMgdGFrZXMgYSBmb3JtYXQgb25seSB3aGVuIGV2ZXJ5IG1lYXN1cmUgb24gaXQgYWdyZWVzIG9uXG4vLyB0aGUgc3R5bGUgKGVhY2ggbWVhc3VyZSdzIGZvcm1hdCwgbnVtYmVyIHdoZW4gaXQgbmFtZXMgbm9uZSkgYW5kIGF0IGxlYXN0XG4vLyBvbmUgb2YgdGhlbSBuYW1lcyBhIGZvcm1hdC4gVGhlIGZpcnN0IG1lYXN1cmUgdGhhdCBkb2VzIGdpdmVzIHRoZSBheGlzIGl0c1xuLy8gcHJlY2lzaW9uIGFuZCB1bml0cy4gT3RoZXJ3aXNlIG51bGw6IHRoZSBheGlzIGtlZXBzIGl0cyBkZWZhdWx0IHRpY2tzIG9uXG4vLyBzY3JlZW4gYW5kIGluIFBvd2VyUG9pbnQsIGFuZCBlYWNoIHNlcmllcyBzdGlsbCBmb3JtYXRzIGl0cyBvd24gdG9vbHRpcHMuXG5leHBvcnQgZnVuY3Rpb24gYXhpc051bWJlckZvcm1hdChtZWFzdXJlczogQ2hhcnRNZWFzdXJlW10pOiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCB7XG4gIGNvbnN0IHN0eWxlID0gbWVhc3VyZXMubGVuZ3RoID8gcmVzb2x2ZVN0eWxlKG1lYXN1cmVzWzBdKSA6IG51bGw7XG5cbiAgaWYgKHN0eWxlID09PSBudWxsIHx8IG1lYXN1cmVzLnNvbWUoKG1lYXN1cmUpID0+IHJlc29sdmVTdHlsZShtZWFzdXJlKSAhPT0gc3R5bGUpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBmb3JtYXR0ZWQgPSBtZWFzdXJlcy5maW5kKChtZWFzdXJlKSA9PiBoYXNOdW1iZXJGb3JtYXQobWVhc3VyZSkpO1xuXG4gIHJldHVybiBmb3JtYXR0ZWQgPyBudW1iZXJGb3JtYXRTcGVjKGZvcm1hdHRlZCkgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBudW1iZXJGb3JtYXRTcGVjKHNwZWM6IE51bWJlckZvcm1hdFNwZWMpOiBOdW1iZXJGb3JtYXRTcGVjIHtcbiAgcmV0dXJuIHtcbiAgICAuLi4oc3BlYy5mb3JtYXQgIT09IHVuZGVmaW5lZCA/IHsgZm9ybWF0OiBzcGVjLmZvcm1hdCB9IDoge30pLFxuICAgIC4uLihzcGVjLnByZWNpc2lvbiAhPT0gdW5kZWZpbmVkID8geyBwcmVjaXNpb246IHNwZWMucHJlY2lzaW9uIH0gOiB7fSksXG4gICAgLi4uKHNwZWMudW5pdHMgIT09IHVuZGVmaW5lZCA/IHsgdW5pdHM6IHNwZWMudW5pdHMgfSA6IHt9KSxcbiAgfTtcbn1cblxuLy8gSG93IGEgY2hhcnQncyB2YWx1ZSBheGlzIHdyaXRlcyBpdHMgdGlja3M6IHRoZSB1bml0cyBkZWNpZGVkIG9uY2UgZnJvbSB0aGVcbi8vIGF4aXMgcGVhaywgYW5kIHRoZSBkZWNpbWFscyB0aGUgcHJlY2lzaW9uIHBpbnMsIGVsc2UgYXMgbWFueSBhcyB0aGUgYXhpcydzXG4vLyB0aWNrIHN0ZXAgbmVlZHMgKGEgcGVyY2VudCBheGlzIHVwIHRvIDAuMTIlIHN0ZXBzIGJ5IDAuMDIlLCB0d28gZGVjaW1hbHMpLlxuLy8gUGlubmVkIGRlY2ltYWxzIGtlZXAgdGhlIHRpY2tzIGRpc3RpbmN0LCBhbmQgUG93ZXJQb2ludCBjYW4gb25seSBwaW4gdGhlbS5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQ2hhcnROdW1iZXJGb3JtYXQoXG4gIHNwZWM6IE51bWJlckZvcm1hdFNwZWMsXG4gIHBlYWs6IG51bWJlcixcbiAgY29udGV4dDogUmVwb3J0Rm9ybWF0Q29udGV4dCxcbik6IENoYXJ0TnVtYmVyRm9ybWF0IHtcbiAgY29uc3Qgc3R5bGUgPSByZXNvbHZlU3R5bGUoc3BlYyk7XG4gIGNvbnN0IHByZWNpc2lvbiA9IGNsYW1wRGVjaW1hbHMoc3BlYy5wcmVjaXNpb24pO1xuICBjb25zdCB1bml0cyA9IHN0eWxlID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5QZXJjZW50XG4gICAgPyBSZXBvcnROdW1iZXJVbml0cy5Ob25lXG4gICAgOiByZXNvbHZlVW5pdHMoc3BlYy51bml0cywgcGVhaywgcHJlY2lzaW9uID8/IFNDQUxFRF9ERUNJTUFMUyk7XG5cbiAgcmV0dXJuIHsgdW5pdHMsIGRlY2ltYWxzOiBwcmVjaXNpb24gPz8gYXhpc0RlY2ltYWxzKHN0eWxlLCB1bml0cywgcGVhaywgY29udGV4dCkgfTtcbn1cblxuLy8gVGhlIGRlY2ltYWxzIHRoZSBheGlzJ3MgbmljZSB0aWNrIHN0ZXAgbmVlZHMuIEEgcGxhaW4sIHVuYWJicmV2aWF0ZWQgbnVtYmVyXG4vLyBwaW5zIG5vbmUgKG51bGwpOiBpdHMgdGlja3Mga2VlcCB0aGVpciBvd24gZGVjaW1hbHMuIEFuIHVuc2NhbGVkIGN1cnJlbmN5XG4vLyBheGlzIHRoYXQgbmVlZHMgZGVjaW1hbHMgc2hvd3MgY2VudHMsIGFuZCBhIEsvTSBheGlzIGtlZXBzIGl0cyBzdGVwJ3Ncbi8vIGRlY2ltYWxzICgnJDAuNU0nLCBub3QgJyQwLjUwTScpLlxuZnVuY3Rpb24gYXhpc0RlY2ltYWxzKFxuICBzdHlsZTogUmVwb3J0VmFsdWVGb3JtYXQsXG4gIHVuaXRzOiBSZXNvbHZlZFVuaXRzLFxuICBwZWFrOiBudW1iZXIsXG4gIGNvbnRleHQ6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4pOiBudW1iZXIgfCBudWxsIHtcbiAgY29uc3Qgc2NhbGUgPSBVTklUX1NDQUxFUy5nZXQodW5pdHMpO1xuXG4gIGlmIChzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyICYmICFzY2FsZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3Qgc2hvd25QZWFrID0gc3R5bGUgPT09IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgJiYgY29udGV4dC5yYXRpb1BlcmNlbnRcbiAgICA/IE1hdGguYWJzKHBlYWspICogMTAwXG4gICAgOiBNYXRoLmFicyhwZWFrKSAvIChzY2FsZT8uZGl2aXNvciA/PyAxKTtcbiAgY29uc3Qgc3RlcCA9IG5pY2VTdGVwKHNob3duUGVhayAvIEFYSVNfVElDS1MpO1xuICBjb25zdCBkZWNpbWFscyA9IHN0ZXAgPiAwID8gY2xhbXBEZWNpbWFscygtTWF0aC5mbG9vcihNYXRoLmxvZzEwKHN0ZXApKSkgPz8gMCA6IDA7XG5cbiAgcmV0dXJuIHN0eWxlID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5DdXJyZW5jeSAmJiBkZWNpbWFscyA+IDAgJiYgIXNjYWxlID8gQ1VSUkVOQ1lfQVhJU19ERUNJTUFMUyA6IGRlY2ltYWxzO1xufVxuXG4vLyBFQ2hhcnRzJyBuaWNlKCk6IHRoZSByb3VuZCBudW1iZXIgKDEsIDIsIDMsIDUgb3IgMTAgdGltZXMgYSBwb3dlciBvZiB0ZW4pIGFcbi8vIHJvdWdoIHRpY2sgc3RlcCBzbmFwcyB0by5cbmZ1bmN0aW9uIG5pY2VTdGVwKHJvdWdoOiBudW1iZXIpOiBudW1iZXIge1xuICBpZiAoIShyb3VnaCA+IDApIHx8ICFOdW1iZXIuaXNGaW5pdGUocm91Z2gpKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICBjb25zdCBleHBvbmVudCA9IE1hdGguZmxvb3IoTWF0aC5sb2cxMChyb3VnaCkpO1xuICBjb25zdCBwb3dlciA9IE1hdGgucG93KDEwLCBleHBvbmVudCk7XG4gIGNvbnN0IGZyYWN0aW9uID0gcm91Z2ggLyBwb3dlcjtcbiAgbGV0IG5pY2UgPSAxMDtcbiAgaWYgKGZyYWN0aW9uIDwgMS41KSB7XG4gICAgbmljZSA9IDE7XG4gIH0gZWxzZSBpZiAoZnJhY3Rpb24gPCAyLjUpIHtcbiAgICBuaWNlID0gMjtcbiAgfSBlbHNlIGlmIChmcmFjdGlvbiA8IDQpIHtcbiAgICBuaWNlID0gMztcbiAgfSBlbHNlIGlmIChmcmFjdGlvbiA8IDcpIHtcbiAgICBuaWNlID0gNTtcbiAgfVxuXG4gIHJldHVybiBuaWNlICogcG93ZXI7XG59XG5cbi8vIFBvd2VyUG9pbnQncyBudW1iZXIgZm9ybWF0IGNvZGUgZm9yIGEgZm9ybWF0dGVkIHZhbHVlIGF4aXMsIG1hdGNoaW5nIHRoZVxuLy8gc2NyZWVuJ3MgdGlja3M6ICcjLCMjMC4wJScgKHBlcmNlbnQpLCAnXCIkXCIjLCMjMCcgKGN1cnJlbmN5KSxcbi8vICcjLCMjMC4wLFwiS1wiJyAodGhvdXNhbmRzKSwgJyMsIyMwXCIgJFwiJyAoZnItQ0EgY3VycmVuY3kpLiBBIHBsYWluIG51bWJlclxuLy8gd2hvc2UgZGVjaW1hbHMgYXJlIG5vdCBwaW5uZWQga2VlcHMgY2hhcnRBeGlzRm9ybWF0Q29kZSdzIGNvZGUuIFRoZSBjb2RlJ3Ncbi8vIHNlcGFyYXRvcnMgZm9sbG93IHRoZSBvcGVuaW5nIG1hY2hpbmUncyBsb2NhbGU7IHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIGl0c1xuLy8gc2lkZSBmb2xsb3cgdGhlIHJlcG9ydCdzLlxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlckZvcm1hdENvZGUoXG4gIHNwZWM6IE51bWJlckZvcm1hdFNwZWMsXG4gIGNvbnRleHQ6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4gIGNoYXJ0OiBDaGFydE51bWJlckZvcm1hdCxcbiAgc2VyaWVzOiAobnVtYmVyIHwgbnVsbClbXVtdLFxuICBzdGFja2VkOiBib29sZWFuLFxuKTogc3RyaW5nIHtcbiAgY29uc3Qgc3R5bGUgPSByZXNvbHZlU3R5bGUoc3BlYyk7XG4gIGNvbnN0IHNjYWxlID0gc3R5bGUgPT09IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgPyB1bmRlZmluZWQgOiBVTklUX1NDQUxFUy5nZXQoY2hhcnQudW5pdHMpO1xuXG4gIGlmIChzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyICYmICFzY2FsZSAmJiBjaGFydC5kZWNpbWFscyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBjaGFydEF4aXNGb3JtYXRDb2RlKHNlcmllcywgc3RhY2tlZCk7XG4gIH1cblxuICBjb25zdCBkZWNpbWFscyA9IGNoYXJ0LmRlY2ltYWxzID8/IDA7XG4gIGNvbnN0IGRpZ2l0cyA9IGAjLCMjMCR7ZGVjaW1hbHMgPiAwID8gYC4keycwJy5yZXBlYXQoZGVjaW1hbHMpfWAgOiAnJ31gO1xuXG4gIGlmIChzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudCkge1xuICAgIHJldHVybiBgJHtkaWdpdHN9JHtjb250ZXh0LnJhdGlvUGVyY2VudCA/ICclJyA6ICdcIiVcIid9YDtcbiAgfVxuXG4gIGNvbnN0IHNjYWxlZCA9IGAke2RpZ2l0c30ke3NjYWxlPy5jb21tYXMgPz8gJyd9YDtcbiAgY29uc3QgdW5pdCA9IHNjYWxlPy5zdWZmaXggPz8gJyc7XG5cbiAgaWYgKHN0eWxlICE9PSBSZXBvcnRWYWx1ZUZvcm1hdC5DdXJyZW5jeSkge1xuICAgIHJldHVybiB1bml0ID8gYCR7c2NhbGVkfVwiJHt1bml0fVwiYCA6IHNjYWxlZDtcbiAgfVxuXG4gIGNvbnN0IHN5bWJvbCA9IGN1cnJlbmN5U3ltYm9sKGNvbnRleHQpO1xuXG4gIHJldHVybiBzeW1ib2wucHJlZml4XG4gICAgPyBgXCIke3N5bWJvbC50ZXh0fVwiJHtzY2FsZWR9JHt1bml0ID8gYFwiJHt1bml0fVwiYCA6ICcnfWBcbiAgICA6IGAke3NjYWxlZH1cIiR7dW5pdH0ke3N5bWJvbC50ZXh0fVwiYDtcbn1cblxuLy8gVGhlIGN1cnJlbmN5IHN5bWJvbCBhcyB0aGUgbG9jYWxlIHdyaXRlcyBpdCBiZXNpZGUgYSBudW1iZXIsIHdpdGggdGhlIHNwYWNlXG4vLyBiZXR3ZWVuIHRoZW0sIGFuZCB3aGljaCBzaWRlIGl0IHNpdHMgb246ICckJyBiZWZvcmUgaW4gZW4tVVMsICcgJCcgYWZ0ZXIgaW5cbi8vIGZyLUNBLiBRdW90ZXMgYXJlIGRyb3BwZWQsIGFzIGEgZm9ybWF0IGNvZGUgY2Fubm90IGhvbGQgdGhlbS5cbmludGVyZmFjZSBDdXJyZW5jeVN5bWJvbCB7XG4gIHByZWZpeDogYm9vbGVhbjtcbiAgdGV4dDogc3RyaW5nO1xufVxuXG5jb25zdCBDVVJSRU5DWV9TWU1CT0xTID0gbmV3IE1hcDxzdHJpbmcsIEN1cnJlbmN5U3ltYm9sPigpO1xuXG5mdW5jdGlvbiBjdXJyZW5jeVN5bWJvbChjb250ZXh0OiBSZXBvcnRGb3JtYXRDb250ZXh0KTogQ3VycmVuY3lTeW1ib2wge1xuICBjb25zdCBrZXkgPSBgJHtjb250ZXh0LmxvY2FsZX18JHtjb250ZXh0LmN1cnJlbmN5fWA7XG4gIGxldCBzeW1ib2wgPSBDVVJSRU5DWV9TWU1CT0xTLmdldChrZXkpO1xuXG4gIGlmICghc3ltYm9sKSB7XG4gICAgY29uc3QgcGFydHMgPSBudW1iZXJGb3JtYXQoY29udGV4dC5sb2NhbGUsIGN1cnJlbmN5T3B0aW9ucyhjb250ZXh0LmN1cnJlbmN5KSkuZm9ybWF0VG9QYXJ0cygxKTtcbiAgICBjb25zdCBjdXJyZW5jeSA9IHBhcnRzLmZpbmRJbmRleCgocGFydCkgPT4gcGFydC50eXBlID09PSAnY3VycmVuY3knKTtcbiAgICBjb25zdCBmaXJzdCA9IHBhcnRzLmZpbmRJbmRleCgocGFydCkgPT4gTlVNQkVSX1BBUlRTLmhhcyhwYXJ0LnR5cGUpKTtcbiAgICBjb25zdCBsYXN0ID0gcGFydHMucmVkdWNlKChmb3VuZCwgcGFydCwgaW5kZXgpID0+IE5VTUJFUl9QQVJUUy5oYXMocGFydC50eXBlKSA/IGluZGV4IDogZm91bmQsIC0xKTtcbiAgICBjb25zdCBwcmVmaXggPSBjdXJyZW5jeSA8IGZpcnN0O1xuICAgIGNvbnN0IHRleHQgPSAocHJlZml4ID8gcGFydHMuc2xpY2UoTWF0aC5tYXgoY3VycmVuY3ksIDApLCBmaXJzdCkgOiBwYXJ0cy5zbGljZShsYXN0ICsgMSkpXG4gICAgICAubWFwKChwYXJ0KSA9PiBwYXJ0LnZhbHVlKVxuICAgICAgLmpvaW4oJycpXG4gICAgICAucmVwbGFjZSgvXCIvZywgJycpO1xuXG4gICAgc3ltYm9sID0geyBwcmVmaXgsIHRleHQgfTtcbiAgICBDVVJSRU5DWV9TWU1CT0xTLnNldChrZXksIHN5bWJvbCk7XG4gIH1cblxuICByZXR1cm4gc3ltYm9sO1xufVxuXG5cbi8vIEV2ZXJ5IGRlY2ltYWwgYSBudW1iZXIgaGFzLCBncm91cGVkLCBpbiB0aGUgbG9jYWxlOiB3aGF0IEVDaGFydHMgcHJpbnRzIGJ5XG4vLyBkZWZhdWx0IChpdHMgYWRkQ29tbWFzKSwgYnV0IGluIHRoZSByZXBvcnQncyBsb2NhbGUsIHNvIGEgY2hhcnQncyBheGlzIGFuZFxuLy8gdG9vbHRpcCByZWFkIGxpa2UgdGhlIHJlc3Qgb2YgdGhlIHJlcG9ydC4gMTIzNC41IHJlYWRzIDEsMjM0LjUgaW4gZW4tVVMgYW5kXG4vLyAxIDIzNCw1IGluIGZyLUNBLiBBIG5vbi1udW1lcmljIHN0cmluZyBpcyBzaG93biBhcyBpdCBjYW1lLCBhbmQgYW55dGhpbmdcbi8vIGVsc2Ugbm9uLW51bWVyaWMgYXMgJy0nLCBhcyBFQ2hhcnRzIHNob3dzIGl0LiBBcyB0aGVyZSwgYW4gaW5maW5pdGUgdmFsdWVcbi8vIHJlYWRzICdJbmZpbml0eScgYW5kIG5lZ2F0aXZlIHplcm8gKGEgdGljayBhIGZsb2F0IGVycm9yIGxlYXZlcyBqdXN0IGJlbG93XG4vLyB6ZXJvKSByZWFkcyAnMCcuXG5jb25zdCBQTEFJTl9OVU1CRVI6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyA9IHsgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiAyMCB9O1xuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0UGxhaW5OdW1iZXIodmFsdWU6IHVua25vd24sIGxvY2FsZTogUmVwb3J0TG9jYWxlVGFnKTogc3RyaW5nIHtcbiAgY29uc3QgbnVtZXJpYyA9IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcidcbiAgICA/IHZhbHVlXG4gICAgOiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLnRyaW0oKSAhPT0gJycgPyBOdW1iZXIodmFsdWUpIDogTmFOO1xuXG4gIGlmIChOdW1iZXIuaXNOYU4obnVtZXJpYykpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlIDogJy0nO1xuICB9XG5cbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUobnVtZXJpYykpIHtcbiAgICByZXR1cm4gU3RyaW5nKG51bWVyaWMpO1xuICB9XG5cbiAgcmV0dXJuIG51bWJlckZvcm1hdChsb2NhbGUsIFBMQUlOX05VTUJFUikuZm9ybWF0KG51bWVyaWMgPT09IDAgPyAwIDogbnVtZXJpYyk7XG59XG5cblxuLy8gVGhlIGF4aXMgcGVhayBhdCB3aGljaCBhIG5hdGl2ZSBjaGFydCdzIHZhbHVlIGF4aXMgZ2FpbnMgdGhvdXNhbmRzXG4vLyBzZXBhcmF0b3JzLiBGcm9tIGhlcmUgdXAgdGhlIHRpY2tzIGFyZSB3aG9sZSBudW1iZXJzIGluIHByYWN0aWNlOyBiZWxvdyBpdFxuLy8gbmVpdGhlciB0aGUgc2NyZWVuIG5vciBQb3dlclBvaW50J3MgJ0dlbmVyYWwnIHNob3dzIGEgc2VwYXJhdG9yLlxuZXhwb3J0IGNvbnN0IEFYSVNfU0VQQVJBVE9SX1RIUkVTSE9MRCA9IDEwMDA7XG5cbi8vIFBvd2VyUG9pbnQncyBudW1iZXIgZm9ybWF0IGZvciBhIG5hdGl2ZSBjaGFydCdzIHZhbHVlIGF4aXMsIG1hdGNoaW5nIHdoYXQgdGhlXG4vLyBvbi1zY3JlZW4gYXhpcyBwcmludHMgYnkgZGVmYXVsdDogdGhvdXNhbmRzIHNlcGFyYXRvcnMgd2l0aCBlYWNoIHRpY2sncyBvd25cbi8vIGRlY2ltYWxzLiBFeGNlbCBoYXMgbm8gXCJHZW5lcmFsIHdpdGggc2VwYXJhdG9yc1wiLCBzbyBhbiBheGlzIHJlYWNoaW5nIDEsMDAwXG4vLyAod2hlcmUgdGlja3MgYXJlIHdob2xlIG51bWJlcnMpIGdldHMgJyMsIyMwJywgYW5kIGEgc21hbGxlciByYW5nZSBrZWVwc1xuLy8gJ0dlbmVyYWwnIHNvIGZyYWN0aW9uYWwgdGlja3MgKDAuMjUsIDAuNSkgYXJlIG5vdCByb3VuZGVkIGF3YXkuXG4vL1xuLy8gVGhlIHBlYWsgaXMgY2hhcnRWYWx1ZVBlYWsncy5cbmV4cG9ydCBmdW5jdGlvbiBjaGFydEF4aXNGb3JtYXRDb2RlKHNlcmllczogKG51bWJlciB8IG51bGwpW11bXSwgc3RhY2tlZDogYm9vbGVhbik6IHN0cmluZyB7XG4gIHJldHVybiBjaGFydFZhbHVlUGVhayhzZXJpZXMsIHN0YWNrZWQpID49IEFYSVNfU0VQQVJBVE9SX1RIUkVTSE9MRCA/ICcjLCMjMCcgOiAnR2VuZXJhbCc7XG59XG5cbi8vIFRoZSBsYXJnZXN0IG1hZ25pdHVkZSBhIGNoYXJ0J3MgdmFsdWUgYXhpcyBoYXMgdG8gcmVhY2guIEEgbWlzc2luZyB2YWx1ZVxuLy8gY291bnRzIGFzIDAuIEEgc3RhY2tlZCBjaGFydCdzIHBlYWsgaXMgaXRzIHRhbGxlc3Qgc3RhY2s6IHRoZSBsYXJnZXN0IHN1bSxcbi8vIHBlciBjYXRlZ29yeSwgb2YgZXZlcnkgc2VyaWVzJyBhYnNvbHV0ZSB2YWx1ZS5cbmV4cG9ydCBmdW5jdGlvbiBjaGFydFZhbHVlUGVhayhzZXJpZXM6IChudW1iZXIgfCBudWxsKVtdW10sIHN0YWNrZWQ6IGJvb2xlYW4pOiBudW1iZXIge1xuICBjb25zdCBtYWduaXR1ZGVzID0gc2VyaWVzLm1hcCgodmFsdWVzKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4gTWF0aC5hYnModmFsdWUgPz8gMCkpKTtcblxuICByZXR1cm4gc3RhY2tlZFxuICAgID8gTWF0aC5tYXgoMCwgLi4uKG1hZ25pdHVkZXNbMF0gPz8gW10pLm1hcCgoXywgaW5kZXgpID0+IG1hZ25pdHVkZXNcbiAgICAgIC5yZWR1Y2UoKHN1bSwgdmFsdWVzKSA9PiBzdW0gKyAodmFsdWVzW2luZGV4XSA/PyAwKSwgMCkpKVxuICAgIDogTWF0aC5tYXgoMCwgLi4ubWFnbml0dWRlcy5mbGF0KCkpO1xufVxuXG5cbi8vIFRoZSB6b25lIGV2ZXJ5IGRhdGUgaW4gYSByZXBvcnQgaXMgcmVhZCBpbi4gVGhlIHNlcnZlciByZXNvbHZlcyBpdCAodGhlXG4vLyByZXBvcnQncyBvd24gem9uZSwgZWxzZSB0aGUgYXBwbGljYXRpb24ncyBkZWZhdWx0IHJlcG9ydGluZyB6b25lKSBhbmQgc2VuZHNcbi8vIGl0IGFzIGBlZmZlY3RpdmVUaW1lem9uZWAuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCB0aGUgZmllbGQgc3RpbGwgdXNlZCBhXG4vLyByZXBvcnQncyBwaW5uZWQgYHRpbWV6b25lYCwgc28gdGhhdCBjb21lcyBuZXh0OyB0aGUgYnJvd3NlcidzIHpvbmUgaXMgdGhlIGxhc3Rcbi8vIGZhbGxiYWNrLiBUaGlzIGlzIHRoZSBvbmUgcGxhY2UgdGhhdCBjaGFpbiBsaXZlcywgc28gZXZlcnkgZGF0ZSB0aGUgdmlld2VyXG4vLyByZW5kZXJzIG9yIHJlc29sdmVzIGFncmVlcyB3aXRoIGV2ZXJ5IG90aGVyLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZXBvcnRUaW1lem9uZShyZXBvcnQ6IFBpY2s8UmVwb3J0LCAnZWZmZWN0aXZlVGltZXpvbmUnIHwgJ3RpbWV6b25lJz4pOiBzdHJpbmcge1xuICByZXR1cm4gcmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lID8/IHJlcG9ydC50aW1lem9uZSA/PyBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG59XG5cblxuLy8gVGhlIGRhdGUgc2hhcGVzIGEgcmVwb3J0IHdyaXRlcywgZWFjaCBpbiB0aGUgcmVwb3J0J3MgbG9jYWxlLlxuLy8gJ0phbiA1LCAyMDI2JyAvICc1IGphbnYuIDIwMjYnOiBhIGRhdGUgY2VsbCwgYSBmaWx0ZXIgYm91bmQuXG5leHBvcnQgY29uc3QgREFZX1NIT1JUOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ3Nob3J0JywgZGF5OiAnbnVtZXJpYycgfTtcbi8vICdKYW51YXJ5IDUsIDIwMjYnIC8gJzUgamFudmllciAyMDI2JzogYW4gZXhwb3J0IGNvdmVyJ3MgZGF0ZSBsaW5lLlxuZXhwb3J0IGNvbnN0IERBWV9MT05HOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJyB9O1xuLy8gJ0phbnVhcnknIC8gJ2phbnZpZXInOiBhIG1vbnRobHkgcGVyaW9kIGxhYmVsIChpdHMgeWVhciBpcyBhZGRlZCBhcGFydCkuXG5leHBvcnQgY29uc3QgTU9OVEhfTE9ORzogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMgPSB7IG1vbnRoOiAnbG9uZycgfTtcbi8vICdKYW51YXJ5IDIwMjYnIC8gJ2phbnZpZXIgMjAyNic6IGEgbW9udGhseSBwZXJpb2QgbGFiZWwgd3JpdHRlbiBpbiBmdWxsLlxuZXhwb3J0IGNvbnN0IE1PTlRIX1lFQVI6IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zID0geyB5ZWFyOiAnbnVtZXJpYycsIG1vbnRoOiAnbG9uZycgfTtcbi8vICdKYW4gNScgLyAnNSBqYW52Lic6IGEgZGFpbHkgb3Igd2Vla2x5IHBlcmlvZCBsYWJlbC5cbmV4cG9ydCBjb25zdCBNT05USF9EQVk6IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zID0geyBtb250aDogJ3Nob3J0JywgZGF5OiAnbnVtZXJpYycgfTtcblxuLy8gQSBkYXRlIGluIHRoZSBsb2NhbGUuIFdpdGggYSB6b25lLCB0aGUgZGF5IGl0IGZhbGxzIG9uIHRoZXJlOyB3aXRob3V0IG9uZSxcbi8vIHRoZSBicm93c2VyJ3Mgem9uZSwgd2hpY2gga2VlcHMgYSBjYWxlbmRhciBkYXkgcGFyc2VkIGFzIGxvY2FsIG1pZG5pZ2h0XG4vLyB1bnNoaWZ0ZWQuIEl0IG5ldmVyIHRocm93cywgc2luY2UgYSBwaXBlIG9yIGFuIGV4cG9ydCBjYWxscyBpdCBwZXIgY2VsbDogYW5cbi8vIGludmFsaWQgRGF0ZSByZWFkcyAnJywgYSBtYWxmb3JtZWQgbG9jYWxlICgnZW5fQ0EnKSByZWFkcyB0aGUgZmFsbGJhY2tcbi8vIGxvY2FsZSwgYW5kIGFuIHVua25vd24gem9uZSByZWFkcyBVVEMsIHdoaWNoIHN0aWxsIG5hbWVzIGEgcmVhbCBkYXkuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0TG9jYWxEYXRlKFxuICBkYXRlOiBEYXRlLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbiAgb3B0aW9uczogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMsXG4gIHRpbWVab25lPzogc3RyaW5nLFxuKTogc3RyaW5nIHtcbiAgaWYgKE51bWJlci5pc05hTihkYXRlLmdldFRpbWUoKSkpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICB0cnkge1xuICAgIHJldHVybiB3cml0ZURhdGUoZGF0ZUZvcm1hdChsb2NhbGUsIG9wdGlvbnMsIHRpbWVab25lKSwgZGF0ZSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmb3JtYXRGYWxsYmFja0RhdGUoZGF0ZSwgcmVzb2x2ZVJlcG9ydExvY2FsZShsb2NhbGUpLCBvcHRpb25zLCB0aW1lWm9uZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZm9ybWF0RmFsbGJhY2tEYXRlKFxuICBkYXRlOiBEYXRlLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbiAgb3B0aW9uczogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMsXG4gIHRpbWVab25lPzogc3RyaW5nLFxuKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gd3JpdGVEYXRlKGRhdGVGb3JtYXQobG9jYWxlLCBvcHRpb25zLCB0aW1lWm9uZSksIGRhdGUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gd3JpdGVEYXRlKGRhdGVGb3JtYXQobG9jYWxlLCBvcHRpb25zLCAnVVRDJyksIGRhdGUpO1xuICB9XG59XG5cbi8vIEludGwgd3JpdGVzIGEgeWVhciBiZWxvdyAxMDAwIHdpdGggb25seSB0aGUgZGlnaXRzIGl0IGhhcyAoJ0phbiAxLCAxJyk7IGFcbi8vIGRhdGUncyB5ZWFyIGlzIGFsd2F5cyB3cml0dGVuIHdpdGggZm91ciAoJ0phbiAxLCAwMDAxJyksIHNvIGEgc2VudGluZWwgZGF5XG4vLyBzdGlsbCByZWFkcyBhcyBhIGRhdGUuIE9ubHkgc3VjaCBhIHllYXIgcGF5cyBmb3IgZm9ybWF0VG9QYXJ0cy5cbmZ1bmN0aW9uIHdyaXRlRGF0ZShmb3JtYXR0ZXI6IEludGwuRGF0ZVRpbWVGb3JtYXQsIGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICBpZiAoZGF0ZS5nZXRVVENGdWxsWWVhcigpID4gMTAwMCkge1xuICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0KGRhdGUpO1xuICB9XG5cbiAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXRUb1BhcnRzKGRhdGUpXG4gICAgLm1hcCgocGFydCkgPT4gcGFydC50eXBlID09PSAneWVhcicgPyBwYXJ0LnZhbHVlLnBhZFN0YXJ0KDQsICcwJykgOiBwYXJ0LnZhbHVlKVxuICAgIC5qb2luKCcnKTtcbn1cblxuXG5jb25zdCBEQVRFX09OTFlfUEFUVEVSTiA9IC9eXFxkezR9LVxcZHsyfS1cXGR7Mn0kLztcbmNvbnN0IERBVEVfVElNRV9QQVRURVJOID0gL14oXFxkezR9LVxcZHsyfS1cXGR7Mn0pWyBUXShcXGR7Mn06XFxkezJ9OlxcZHsyfSkoXFwuXFxkKyk/JC87XG5cbi8vIEEgcmVwb3J0IHJvdydzIGRhdGUgY2VsbCBhcyBhIGNhbGVuZGFyIGRheSBpbiB0aGUgcmVwb3J0J3Mgem9uZS5cbi8vXG4vLyBSZXBvcnQgcm93cyBhcmUgcmF3IGRhdGFiYXNlIHN0cmluZ3MsIG5vdCBzZXJpYWxpemVkIG1vZGVscywgc28gdGhlaXIgc2hhcGVcbi8vIGlzIHRoZSB3aXJlIGNvbnRyYWN0OiBhIERBVEUgY29sdW1uIGFycml2ZXMgYXMgJ1lZWVktTU0tREQnIGFuZCBhXG4vLyBkYXRlLWFuZC10aW1lIGNvbHVtbiBhcyAnWVlZWS1NTS1ERCBISDpNTTpTUycgaW4gVVRDLiBSZWFkaW5nIHRoYXQgc2hhcGVcbi8vIGhlcmUgZG9lcyBub3QgcmUtZGVyaXZlIGEgc2VydmVyIHJ1bGU7IGl0IG9ubHkgc3RvcHMgdGhlIGJyb3dzZXIgZ3Vlc3NpbmcuXG4vLyAtIEEgY2FsZW5kYXIgZGF5IGlzIG5ldmVyIHNoaWZ0ZWQ6IHBhcnNlSVNPIHJlYWRzIGl0IGFzIGxvY2FsIG1pZG5pZ2h0LCBzb1xuLy8gICB0aGUgZGF5IHByaW50ZWQgaXMgdGhlIGRheSBzdG9yZWQsIHdoYXRldmVyIHRoZSB6b25lLlxuLy8gLSBBbiBpbnN0YW50IGlzIHBpbm5lZCB0byBVVEMgd2l0aCBhbiBleHBsaWNpdCAnWicsIHRoZW4gc2hvd24gYXMgdGhlIGRheSBpdFxuLy8gICBmZWxsIG9uIGluIHRoZSByZXBvcnQncyB6b25lLCB0aGUgc2FtZSBkYXkgdGhlIGZpbHRlcnMgYW5kIHRpbWUgYnVja2V0cyB1c2UuXG4vLyAtIEFueXRoaW5nIGVsc2UgaXMgc2hvd24gYXMgaXQgY2FtZSwgYW5kIHNvIGlzIGEgdmFsdWUgdGhhdCBoYXMgdGhlIHNoYXBlXG4vLyAgIGJ1dCBuYW1lcyBubyByZWFsIGRheSAoYSB6ZXJvIGRhdGUgJzAwMDAtMDAtMDAnLCBvciAnMjAyNi0wMi0zMCcpOiBvbmVcbi8vICAgYmFkIGNlbGwgbXVzdCBub3QgdGhyb3cgb3V0IG9mIGEgcGlwZSBvciBhYm9ydCBhbiBleHBvcnQuXG4vLyBUaGUgZGF5IGlzIHdyaXR0ZW4gaW4gdGhlIHJlcG9ydCdzIGxvY2FsZTogJ0phbiA1LCAyMDI2JyBpbiBlbi1VUywgJzUgamFudi5cbi8vIDIwMjYnIGluIGZyLUNBLlxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJlcG9ydERhdGUoXG4gIHZhbHVlOiB1bmtub3duLFxuICB0aW1lem9uZTogc3RyaW5nLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbik6IHN0cmluZyB7XG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIGNvbnN0IHRleHQgPSBTdHJpbmcodmFsdWUpO1xuXG4gIGlmIChEQVRFX09OTFlfUEFUVEVSTi50ZXN0KHRleHQpKSB7XG4gICAgY29uc3QgZGF5ID0gcGFyc2VJU08odGV4dCk7XG5cbiAgICByZXR1cm4gaXNWYWxpZChkYXkpID8gZm9ybWF0TG9jYWxEYXRlKGRheSwgbG9jYWxlLCBEQVlfU0hPUlQpIDogdGV4dDtcbiAgfVxuXG4gIGNvbnN0IGRhdGVUaW1lID0gREFURV9USU1FX1BBVFRFUk4uZXhlYyh0ZXh0KTtcbiAgaWYgKCFkYXRlVGltZSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgY29uc3QgaW5zdGFudCA9IHBhcnNlSVNPKGAke2RhdGVUaW1lWzFdfVQke2RhdGVUaW1lWzJdfVpgKTtcblxuICByZXR1cm4gaXNWYWxpZChpbnN0YW50KSA/IGZvcm1hdExvY2FsRGF0ZShpbnN0YW50LCBsb2NhbGUsIERBWV9TSE9SVCwgdGltZXpvbmUpIDogdGV4dDtcbn1cblxuXG4vLyBUaGUgdGltZSBvZiBkYXkgYW4gaW5zdGFudCBmYWxscyBhdCBpbiB0aGUgcmVwb3J0J3Mgem9uZTogJzI6MjMgUE0nIGluXG4vLyBlbi1VUywgJzE0IGggMjMnIGluIGZyLUNBLlxuZXhwb3J0IGNvbnN0IFRJTUVfU0hPUlQ6IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zID0geyBob3VyOiAnbnVtZXJpYycsIG1pbnV0ZTogJzItZGlnaXQnIH07XG5cbi8vIEEgd2luZG93J3MgaW5jbHVzaXZlIGRheXMsIGFzIHRoZSBzZXJ2ZXIgc2VuZHMgdGhlbTogJ3l5eXktTU0tZGQnIGNhbGVuZGFyXG4vLyBkYXlzIGFscmVhZHkgaW4gdGhlIHJlcG9ydCdzIHpvbmUuIExpa2UgYSBkYXRlIGNlbGwgdGhleSBhcmUgcmVhZCBhcyBsb2NhbFxuLy8gbWlkbmlnaHQgYW5kIHdyaXR0ZW4gd2l0aCBOTyB6b25lLCBzbyBhIHZpZXdlciBpbiBhbnkgem9uZSBzZWVzIHRoZSBkYXlzXG4vLyBzZW50LiBCb3RoIGRheXM6IEludGwncyByYW5nZSBpbiB0aGUgbG9jYWxlICgnU2VwIDEg4oCTIDMwLCAyMDI2JyBpbiBlbi1VUyxcbi8vICcx4oCTMzAgc2VwdC4gMjAyNicgaW4gZnItQ0EsIG9uZSBkYXRlIHdoZW4gdGhleSBhcmUgdGhlIHNhbWUgZGF5KS4gT25lIGRheTpcbi8vIGFuIG9wZW4gd2luZG93ICgnU2luY2UgU2VwIDEsIDIwMjYnLCAnVGhyb3VnaCBTZXAgMzAsIDIwMjYnKS4gTmVpdGhlciwgb3Jcbi8vIGRheXMgdGhhdCBhcmUgbm90IHJlYWwgb25lczogJycuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0RGF5UmFuZ2UoXG4gIHN0YXJ0OiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBlbmQ6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQsXG4gIGxvY2FsZTogUmVwb3J0TG9jYWxlVGFnLFxuICBvcHRpb25zOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IERBWV9TSE9SVCxcbik6IHN0cmluZyB7XG4gIGNvbnN0IGZpcnN0ID0gcGFyc2VEYXkoc3RhcnQpO1xuICBjb25zdCBsYXN0ID0gcGFyc2VEYXkoZW5kKTtcblxuICBpZiAoZmlyc3QgJiYgbGFzdCkge1xuICAgIHJldHVybiB3cml0ZURheVJhbmdlKGZpcnN0LCBsYXN0LCBsb2NhbGUsIG9wdGlvbnMpO1xuICB9XG5cbiAgaWYgKGZpcnN0KSB7XG4gICAgcmV0dXJuIGBTaW5jZSAke2Zvcm1hdExvY2FsRGF0ZShmaXJzdCwgbG9jYWxlLCBvcHRpb25zKX1gO1xuICB9XG5cbiAgcmV0dXJuIGxhc3QgPyBgVGhyb3VnaCAke2Zvcm1hdExvY2FsRGF0ZShsYXN0LCBsb2NhbGUsIG9wdGlvbnMpfWAgOiAnJztcbn1cblxuLy8gVGhlIHRpbWUgYSB3aW5kb3cgZW5kaW5nIHRvZGF5IGlzIGN1dCBhdDogdGhlIHNlcnZlcidzIFVUQ1xuLy8gJ3l5eXktTU0tZGQgSEg6bW06c3MnIGluc3RhbnQsIGFzIGEgdGltZSBvZiBkYXkgaW4gdGhlIHJlcG9ydCdzIHpvbmUuICcnXG4vLyBmb3Igbm9uZSwgb3IgZm9yIGEgdmFsdWUgb2YgYW5vdGhlciBzaGFwZS5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRUaHJvdWdoVGltZShcbiAgdGhyb3VnaDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgdGltZXpvbmU6IHN0cmluZyxcbiAgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcsXG4pOiBzdHJpbmcge1xuICBjb25zdCBkYXRlVGltZSA9IHRocm91Z2ggPyBEQVRFX1RJTUVfUEFUVEVSTi5leGVjKHRocm91Z2gpIDogbnVsbDtcbiAgY29uc3QgaW5zdGFudCA9IGRhdGVUaW1lID8gcGFyc2VJU08oYCR7ZGF0ZVRpbWVbMV19VCR7ZGF0ZVRpbWVbMl19WmApIDogbnVsbDtcblxuICByZXR1cm4gaW5zdGFudCAmJiBpc1ZhbGlkKGluc3RhbnQpID8gZm9ybWF0TG9jYWxEYXRlKGluc3RhbnQsIGxvY2FsZSwgVElNRV9TSE9SVCwgdGltZXpvbmUpIDogJyc7XG59XG5cbi8vIEEgY29tcGFyaXNvbiBvciB0aW1lZnJhbWUgd2luZG93IGluIG9uZSBsaW5lOiBpdHMgZGF5cywgYW5kIHRoZSB0aW1lIGl0IGlzXG4vLyBjdXQgYXQgd2hlbiBpdCBlbmRzIHRvZGF5IG9uIGEgZGF0ZS1hbmQtdGltZSBjb2x1bW4gKCdPY3QgMSDigJMgMiwgMjAyNixcbi8vIHVudGlsIDI6MjMgUE0nKS5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXREYXlXaW5kb3coXG4gIG1ldGE6IHsgc3RhcnQ6IHN0cmluZyB8IG51bGw7IGVuZDogc3RyaW5nIHwgbnVsbDsgdGhyb3VnaD86IHN0cmluZyB8IG51bGwgfSxcbiAgdGltZXpvbmU6IHN0cmluZyxcbiAgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcsXG4pOiBzdHJpbmcge1xuICBjb25zdCBkYXlzID0gZm9ybWF0RGF5UmFuZ2UobWV0YS5zdGFydCwgbWV0YS5lbmQsIGxvY2FsZSk7XG4gIGNvbnN0IHRpbWUgPSBmb3JtYXRUaHJvdWdoVGltZShtZXRhLnRocm91Z2gsIHRpbWV6b25lLCBsb2NhbGUpO1xuXG4gIHJldHVybiBkYXlzICYmIHRpbWUgPyBgJHtkYXlzfSwgdW50aWwgJHt0aW1lfWAgOiBkYXlzO1xufVxuXG4vLyBPbmUgJ3l5eXktTU0tZGQnIGRheSBpbiB0aGUgbG9jYWxlLCB3cml0dGVuIHdpdGggbm8gem9uZTogJ1NlcCAxLCAyMDI2Jy5cbmZ1bmN0aW9uIGZvcm1hdERheShkYXk6IHN0cmluZywgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcpOiBzdHJpbmcge1xuICBjb25zdCBkYXRlID0gcGFyc2VEYXkoZGF5KTtcblxuICByZXR1cm4gZGF0ZSA/IGZvcm1hdExvY2FsRGF0ZShkYXRlLCBsb2NhbGUsIERBWV9TSE9SVCkgOiAnJztcbn1cblxuLy8gQSAneXl5eS1NTS1kZCcgZGF5IGFzIGxvY2FsIG1pZG5pZ2h0LCBvciBudWxsIHdoZW4gaXQgaXMgbm90IGEgcmVhbCBkYXkuXG5mdW5jdGlvbiBwYXJzZURheShkYXk6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBEYXRlIHwgbnVsbCB7XG4gIGlmICghZGF5IHx8ICFEQVRFX09OTFlfUEFUVEVSTi50ZXN0KGRheSkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRhdGUgPSBwYXJzZUlTTyhkYXkpO1xuXG4gIHJldHVybiBpc1ZhbGlkKGRhdGUpID8gZGF0ZSA6IG51bGw7XG59XG5cbi8vIEludGwncyByYW5nZSB3cml0ZXMgdGhlIHNoYXJlZCBtb250aCBhbmQgeWVhciBvbmNlLiBBIG1hbGZvcm1lZCBsb2NhbGVcbi8vIHJlYWRzIHRoZSBmYWxsYmFjazsgYSBydW50aW1lIHRoYXQgY2Fubm90IHdyaXRlIHJhbmdlcyBqb2lucyB0d28gZGF0ZXMuXG5mdW5jdGlvbiB3cml0ZURheVJhbmdlKGZpcnN0OiBEYXRlLCBsYXN0OiBEYXRlLCBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZywgb3B0aW9uczogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMpOiBzdHJpbmcge1xuICBjb25zdCBbZnJvbSwgdG9dID0gZmlyc3QgPD0gbGFzdCA/IFtmaXJzdCwgbGFzdF0gOiBbbGFzdCwgZmlyc3RdO1xuXG4gIGZvciAoY29uc3QgdGFnIG9mIFtsb2NhbGUsIHJlc29sdmVSZXBvcnRMb2NhbGUobG9jYWxlKV0pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGRhdGVGb3JtYXQodGFnLCBvcHRpb25zKS5mb3JtYXRSYW5nZShmcm9tLCB0byk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBUaGUgbmV4dCBsb2NhbGUsIHRoZW4gdGhlIGpvaW5lZCBkYXRlcy5cbiAgICB9XG4gIH1cblxuICByZXR1cm4gYCR7Zm9ybWF0TG9jYWxEYXRlKGZyb20sIGxvY2FsZSwgb3B0aW9ucyl9IOKAkyAke2Zvcm1hdExvY2FsRGF0ZSh0bywgbG9jYWxlLCBvcHRpb25zKX1gO1xufVxuXG5cbi8vIEVuZ2xpc2ggbmFtZXMgZm9yIGEgbG9jYWxlIGFuZCBhIGN1cnJlbmN5LCBmb3IgdGhlIHNldHRpbmdzIHNlbGVjdHMuIFRoZVxuLy8gaW50ZXJmYWNlIHN0YXlzIEVuZ2xpc2ggd2hhdGV2ZXIgdGhlIHJlcG9ydCdzIGxvY2FsZTogJ2ZyLUNBJyByZWFkc1xuLy8gJ0NhbmFkaWFuIEZyZW5jaCcsICdDQUQnIHJlYWRzICdDYW5hZGlhbiBEb2xsYXInLiBBIHJ1bnRpbWUgd2l0aG91dCB0aGVcbi8vIG5hbWVzIHNob3dzIHRoZSBjb2RlLlxuZXhwb3J0IGZ1bmN0aW9uIGxvY2FsZU5hbWUodGFnOiBSZXBvcnRMb2NhbGVUYWcpOiBzdHJpbmcge1xuICByZXR1cm4gZGlzcGxheU5hbWUoJ2xhbmd1YWdlJywgdGFnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGN1cnJlbmN5TmFtZShjb2RlOiBSZXBvcnRDdXJyZW5jeUNvZGUpOiBzdHJpbmcge1xuICByZXR1cm4gZGlzcGxheU5hbWUoJ2N1cnJlbmN5JywgY29kZSk7XG59XG5cbmZ1bmN0aW9uIGRpc3BsYXlOYW1lKHR5cGU6ICdsYW5ndWFnZScgfCAnY3VycmVuY3knLCBjb2RlOiBzdHJpbmcpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIHJldHVybiBuZXcgSW50bC5EaXNwbGF5TmFtZXMoWydlbiddLCB7IHR5cGUgfSkub2YoY29kZSkgPz8gY29kZTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGNvZGU7XG4gIH1cbn1cblxuXG4vLyBDb21wYXJpc29uLCB3aW5kb3cgYW5kIEtQSSB3b3JkaW5nLiBUaGUgc2VydmVyIHNlbmRzIGNvZGVzIGFuZCBmaWVsZHMsXG4vLyBuZXZlciBzZW50ZW5jZXMgKGEgd2luZG93J3MgZGVzY3JpcHRpb24gaXMgZm9yIHRoZSBhZ2VudCBhbmQgdGhlIGV4cG9ydHMnXG4vLyBub3Rlcywgbm90IHRoZSBzY3JlZW4pOyB0aGUgaW50ZXJmYWNlIHdvcmRzIHRoZW0gaGVyZSwgaW4gRW5nbGlzaCBsaWtlXG4vLyBldmVyeSBvdGhlciBsYWJlbCwgd2l0aCBhbnkgZGF5IHdyaXR0ZW4gaW4gdGhlIHJlcG9ydCdzIGxvY2FsZS5cblxuY29uc3QgR1JBTlVMQVJJVFlfVU5JVFM6IFJlY29yZDxDaGFydEdyYW51bGFyaXR5LCB7IG9uZTogc3RyaW5nOyBtYW55OiBzdHJpbmcgfT4gPSB7XG4gIGRheTogeyBvbmU6ICdkYXknLCBtYW55OiAnZGF5cycgfSxcbiAgd2VlazogeyBvbmU6ICd3ZWVrJywgbWFueTogJ3dlZWtzJyB9LFxuICBtb250aDogeyBvbmU6ICdtb250aCcsIG1hbnk6ICdtb250aHMnIH0sXG4gIHF1YXJ0ZXI6IHsgb25lOiAncXVhcnRlcicsIG1hbnk6ICdxdWFydGVycycgfSxcbiAgeWVhcjogeyBvbmU6ICd5ZWFyJywgbWFueTogJ3llYXJzJyB9LFxufTtcblxuLy8gV2hhdCBhIHByaW9yIGxhbmUgaXMgY2FsbGVkOiBhbHdheXMgc28gZm9yIGEgbmFtZWQgcGVyaW9kLCBhbmQgZm9yIHRoZVxuLy8gcHJldmlvdXMgcGVyaW9kIHdoZW4gdGhlIHNlcnZlciBuYW1lcyBubyB1bml0IGZvciBpdC5cbmNvbnN0IEFHQUlOU1RfUEhSQVNFUzogUmVjb3JkPENvbXBhcmlzb25BZ2FpbnN0LCBzdHJpbmc+ID0ge1xuICBwcmV2aW91c19wZXJpb2Q6ICdwcmV2aW91cyBwZXJpb2QnLFxuICBwcmV2aW91c193ZWVrOiAncHJldmlvdXMgd2VlaycsXG4gIHByZXZpb3VzX21vbnRoOiAncHJldmlvdXMgbW9udGgnLFxuICBwcmV2aW91c19xdWFydGVyOiAncHJldmlvdXMgcXVhcnRlcicsXG4gIHByZXZpb3VzX3llYXI6ICdwcmV2aW91cyB5ZWFyJyxcbiAgcmFuZ2U6ICdjdXN0b20gcmFuZ2UnLFxufTtcblxuLy8gQSBwcmlvciBsYW5lJ3MgbGFiZWwsIGZyb20gaXRzIG9mZnNldCByYXRoZXIgdGhhbiBmcm9tIHRoZSBtZWFzdXJlLCBzbyBhXG4vLyBjaGFydCByZWdyb3VwZWQgYnkgdGhlIHZpZXdlciBzYXlzIHdoYXQgaXQgbm93IGNvbXBhcmVzLiBBIG5hbWVkIHBlcmlvZFxuLy8gcmVhZHMgYnkgaXRzIG5hbWUgd2hhdGV2ZXIgc2hpZnQgY2FycmllcyBpdCAoJ3ZzIHByZXZpb3VzIHF1YXJ0ZXInIGZvciAzXG4vLyBtb250aHMsICd2cyBwcmV2aW91cyB5ZWFyJyBmb3IgMzY0IGRheXMgb3IgNTIgd2Vla3MsICd2cyBjdXN0b20gcmFuZ2UnKS5cbi8vIE9ubHkgdGhlIHByZXZpb3VzIHBlcmlvZCBpcyB3b3JkZWQgZnJvbSBpdHMgdW5pdCBhbmQgY291bnQ6ICd2cyBwcmV2aW91c1xuLy8gd2VlaycsICd2cyBwcmV2aW91cyAzIG1vbnRocycsICd2cyBwcmV2aW91cyA4IGRheXMnIChhIGRheS1sZW5ndGggc2hpZnQpLlxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmlzb25PZmZzZXRMYWJlbChvZmZzZXQ6IENvbXBhcmlzb25PZmZzZXQpOiBzdHJpbmcge1xuICByZXR1cm4gYHZzICR7b2Zmc2V0UGhyYXNlKG9mZnNldCl9YDtcbn1cblxuZnVuY3Rpb24gb2Zmc2V0UGhyYXNlKG9mZnNldDogQ29tcGFyaXNvbk9mZnNldCk6IHN0cmluZyB7XG4gIGlmIChvZmZzZXQuYWdhaW5zdCAhPT0gJ3ByZXZpb3VzX3BlcmlvZCcgfHwgIW9mZnNldC51bml0IHx8ICFvZmZzZXQuY291bnQpIHtcbiAgICByZXR1cm4gQUdBSU5TVF9QSFJBU0VTW29mZnNldC5hZ2FpbnN0XSA/PyBBR0FJTlNUX1BIUkFTRVMucHJldmlvdXNfcGVyaW9kO1xuICB9XG5cbiAgcmV0dXJuIG9mZnNldC5jb3VudCA9PT0gMVxuICAgID8gYHByZXZpb3VzICR7R1JBTlVMQVJJVFlfVU5JVFNbb2Zmc2V0LnVuaXRdLm9uZX1gXG4gICAgOiBgcHJldmlvdXMgJHtvZmZzZXQuY291bnR9ICR7R1JBTlVMQVJJVFlfVU5JVFNbb2Zmc2V0LnVuaXRdLm1hbnl9YDtcbn1cblxuLy8gT25lIGNvbXBhcmlzb24gbm90ZSBhcyBhIHNlbnRlbmNlLiBUaGUgY29tcGFyaXNvbiwgd2hlbiBnaXZlbiwgbmFtZXMgdGhlXG4vLyBwZXJpb2QgY29tcGFyZWQgd2l0aCAoaXRzIGZpcnN0IHByaW9yIGxhbmUpLlxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmlzb25Ob3RlVGV4dChcbiAgY29kZTogQ29tcGFyaXNvbk5vdGVDb2RlLFxuICBjb21wYXJpc29uPzogQ29tcG9uZW50Q29tcGFyaXNvbiB8IG51bGwsXG4pOiBzdHJpbmcge1xuICBjb25zdCBvZmZzZXQgPSBjb21wYXJpc29uPy5vZmZzZXRzPy5bMF0gPz8gbnVsbDtcbiAgY29uc3QgY29tcGFyZWQgPSBvZmZzZXQgPyBgQ29tcGFyZWQgd2l0aCB0aGUgJHtvZmZzZXRQaHJhc2Uob2Zmc2V0KX1gIDogbnVsbDtcblxuICBzd2l0Y2ggKGNvZGUpIHtcbiAgICBjYXNlICdub193aW5kb3cnOlxuICAgICAgcmV0dXJuICdQaWNrIGEgZGF0ZSByYW5nZSB0byBzZWUgdGhlIGNvbXBhcmlzb24uJztcbiAgICBjYXNlICd1bml0X2luZmVycmVkJzpcbiAgICAgIHJldHVybiBjb21wYXJlZFxuICAgICAgICA/IGAke2NvbXBhcmVkfSwganVkZ2VkIGZyb20gdGhlIGRhdGVzIHBpY2tlZC5gXG4gICAgICAgIDogJ1RoZSBwZXJpb2QgY29tcGFyZWQgd2l0aCB3YXMganVkZ2VkIGZyb20gdGhlIGRhdGVzIHBpY2tlZC4nO1xuICAgIGNhc2UgJ3dpbmRvd19pbl9mdXR1cmUnOlxuICAgICAgcmV0dXJuICdUaGUgZGF0ZSByYW5nZSBzdGFydHMgYWZ0ZXIgdG9kYXksIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG8gY29tcGFyZSB5ZXQuJztcbiAgICBjYXNlICdvdGhlcl9kYXRlX2ZpbHRlcic6XG4gICAgICByZXR1cm4gJ0EgZGF0ZSBmaWx0ZXIgb24gYW5vdGhlciBjb2x1bW4gYWxzbyBhcHBsaWVzIHRvIGJvdGggcGVyaW9kcy4nO1xuICAgIGNhc2UgJ2dyYWluX2ZvbGxvd2VkJzpcbiAgICAgIHJldHVybiBjb21wYXJlZFxuICAgICAgICA/IGAke2NvbXBhcmVkfSwgZm9sbG93aW5nIHRoZSBncm91cGluZyBwaWNrZWQuYFxuICAgICAgICA6ICdUaGUgY29tcGFyaXNvbiBmb2xsb3dzIHRoZSBncm91cGluZyBwaWNrZWQuJztcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuICcnO1xuICB9XG59XG5cbi8vIFdoYXQgYSB3aW5kb3dlZCB2YWx1ZSBpczogJ1JvbGxpbmcgMy1tb250aCB0b3RhbCcsICdNb250aC10by1kYXRlIHRvdGFsJyxcbi8vICdSdW5uaW5nIHRvdGFsIHNpbmNlIHRoZSBzdGFydCBvZiB0aGUgZGF0YScsIHRoZW4gaXRzIGRheXMgd2hlbiB0aGUgc2VydmVyXG4vLyBzZW5kcyB0aGVtICgnUm9sbGluZyA3LWRheSBhdmVyYWdlLCBTZXAgMjQg4oCTIDMwLCAyMDI2JykuIGdyYW51bGFyaXR5IGlzIHRoZVxuLy8gZ3JvdXBpbmcgdGhlIHJvd3MgYXJlIGRyYXduIGF0IChDb21wb25lbnREYXRhLmdyYW51bGFyaXR5KSwgd2hpY2ggbmFtZXMgYVxuLy8gcm9sbGluZyB3aW5kb3cgYXV0aG9yZWQgaW4gcGVyaW9kcyBvZiB0aGUgYXhpcy5cbmV4cG9ydCBmdW5jdGlvbiB3aW5kb3dUZXh0KFxuICBtZXRhOiBXaW5kb3dNZXRhLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbiAgZ3JhbnVsYXJpdHk/OiBDaGFydEdyYW51bGFyaXR5IHwgbnVsbCxcbik6IHN0cmluZyB7XG4gIGNvbnN0IGRheXMgPSBmb3JtYXREYXlSYW5nZShtZXRhLnN0YXJ0LCBtZXRhLmVuZCwgbG9jYWxlKTtcbiAgY29uc3QgcGhyYXNlID0gd2luZG93UGhyYXNlKG1ldGEsIGdyYW51bGFyaXR5ID8/IG51bGwpO1xuXG4gIHJldHVybiBkYXlzID8gYCR7cGhyYXNlfSwgJHtkYXlzfWAgOiBwaHJhc2U7XG59XG5cbmZ1bmN0aW9uIHdpbmRvd1BocmFzZShtZXRhOiBXaW5kb3dNZXRhLCBncmFudWxhcml0eTogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwpOiBzdHJpbmcge1xuICBjb25zdCB2YWx1ZSA9IG1ldGEuYXZlcmFnZSA/ICdhdmVyYWdlJyA6ICd0b3RhbCc7XG5cbiAgc3dpdGNoIChtZXRhLmtpbmQpIHtcbiAgICBjYXNlICdydW5uaW5nJzpcbiAgICAgIHJldHVybiBtZXRhLmZyb21CZWdpbm5pbmcgPyBgUnVubmluZyAke3ZhbHVlfSBzaW5jZSB0aGUgc3RhcnQgb2YgdGhlIGRhdGFgIDogYFJ1bm5pbmcgJHt2YWx1ZX1gO1xuICAgIGNhc2UgJ3RvX2RhdGUnOiB7XG4gICAgICBjb25zdCByZXNldCA9IG1ldGEucmVzZXRFdmVyeSA/IEdSQU5VTEFSSVRZX1VOSVRTW21ldGEucmVzZXRFdmVyeV0ub25lIDogbnVsbDtcblxuICAgICAgcmV0dXJuIHJlc2V0ID8gYCR7Y2FwaXRhbGl6ZShyZXNldCl9LXRvLWRhdGUgJHt2YWx1ZX1gIDogYFRvLWRhdGUgJHt2YWx1ZX1gO1xuICAgIH1cbiAgICBjYXNlICdyb2xsaW5nJzoge1xuICAgICAgY29uc3QgdW5pdCA9IG1ldGEudW5pdCA/PyBncmFudWxhcml0eTtcbiAgICAgIGNvbnN0IHNwYW4gPSBtZXRhLnBlcmlvZHMgPyBgJHttZXRhLnBlcmlvZHN9LSR7dW5pdCA/IEdSQU5VTEFSSVRZX1VOSVRTW3VuaXRdLm9uZSA6ICdwZXJpb2QnfSBgIDogJyc7XG5cbiAgICAgIHJldHVybiBgUm9sbGluZyAke3NwYW59JHt2YWx1ZX1gO1xuICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGNhcGl0YWxpemUodmFsdWUpO1xuICB9XG59XG5cbi8vIE9uZSB3aW5kb3cgbm90ZSBhcyBhIHNlbnRlbmNlLlxuZXhwb3J0IGZ1bmN0aW9uIHdpbmRvd05vdGVUZXh0KFxuICBjb2RlOiBXaW5kb3dOb3RlQ29kZSxcbiAgbWV0YTogV2luZG93TWV0YSxcbiAgbG9jYWxlOiBSZXBvcnRMb2NhbGVUYWcsXG4gIGdyYW51bGFyaXR5PzogQ2hhcnRHcmFudWxhcml0eSB8IG51bGwsXG4pOiBzdHJpbmcge1xuICBzd2l0Y2ggKGNvZGUpIHtcbiAgICBjYXNlICdzbmFwcGVkX3N0YXJ0Jzoge1xuICAgICAgY29uc3Qgc3RhcnQgPSBtZXRhLnN0YXJ0ID8gZm9ybWF0RGF5KG1ldGEuc3RhcnQsIGxvY2FsZSkgOiAnJztcblxuICAgICAgcmV0dXJuIHN0YXJ0XG4gICAgICAgID8gYFRoZSBzdGFydCB3YXMgbW92ZWQgdG8gJHtzdGFydH0sIHRoZSBzdGFydCBvZiBpdHMgcGVyaW9kLCBzbyB0aGUgZmlyc3QgcGVyaW9kIGlzIHdob2xlLmBcbiAgICAgICAgOiAnVGhlIHN0YXJ0IHdhcyBtb3ZlZCB0byB0aGUgc3RhcnQgb2YgaXRzIHBlcmlvZCwgc28gdGhlIGZpcnN0IHBlcmlvZCBpcyB3aG9sZS4nO1xuICAgIH1cbiAgICBjYXNlICdzcGFuX2NvbnZlcnRlZCc6XG4gICAgICByZXR1cm4gc3BhbkNvbnZlcnRlZFRleHQobWV0YSwgZ3JhbnVsYXJpdHkgPz8gbnVsbCk7XG4gICAgY2FzZSAnZ3JhaW5fdG9vX2NvYXJzZSc6XG4gICAgICByZXR1cm4gJ1RoZSBncm91cGluZyBpcyBjb2Fyc2VyIHRoYW4gdGhlIHdpbmRvdywgc28gaXQgaGFzIG5vIHZhbHVlcyBhdCB0aGlzIGdyb3VwaW5nLic7XG4gICAgY2FzZSAnZXF1YWxfZ3JhaW5fcGxhaW4nOlxuICAgICAgcmV0dXJuICdBdCB0aGlzIGdyb3VwaW5nIGVhY2ggd2luZG93IGlzIGEgc2luZ2xlIHBlcmlvZCwgc28gdGhlIHZhbHVlcyBhcmUgdGhlIHBsYWluIG9uZXMuJztcbiAgICBjYXNlICdvd25fZmlsdGVyX2NhcHNfbGVhZF9pbic6XG4gICAgICByZXR1cm4gJ1RoZSBxdWVyeVxcJ3Mgb3duIGRhdGUgY29uZGl0aW9uIHN0YXJ0cyB0aGUgd2luZG93LCBzbyBlYXJsaWVyIHJvd3MgYXJlIG5vdCBjb3VudGVkLic7XG4gICAgY2FzZSAnd2Vla19ieV9tb25kYXknOlxuICAgICAgcmV0dXJuICdBIHdlZWsgdGhhdCBzcGFucyB0d28gcGVyaW9kcyBjb3VudHMgdG93YXJkIHRoZSBwZXJpb2QgaXRzIE1vbmRheSBmYWxscyBpbi4nO1xuICAgIGNhc2UgJ2luY29tcGxldGVfaGVhZCc6XG4gICAgICByZXR1cm4gJ1RoZSBmaXJzdCBwZXJpb2RzIGFyZSBibGFuayBiZWNhdXNlIHRoZXJlIGFyZSBub3QgZW5vdWdoIGVhcmxpZXIgcm93cyB0byBmaWxsIGEgd2hvbGUgd2luZG93Lic7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAnJztcbiAgfVxufVxuXG4vLyAnMyBtb250aHMgYXJlIHNob3duIGFzIDEzIHdlZWtzIGF0IHRoaXMgZ3JvdXBpbmcuJ1xuZnVuY3Rpb24gc3BhbkNvbnZlcnRlZFRleHQobWV0YTogV2luZG93TWV0YSwgZ3JhbnVsYXJpdHk6IENoYXJ0R3JhbnVsYXJpdHkgfCBudWxsKTogc3RyaW5nIHtcbiAgaWYgKCFtZXRhLnBlcmlvZHMgfHwgIW1ldGEudW5pdCB8fCAhbWV0YS5kcmF3blBlcmlvZHMpIHtcbiAgICByZXR1cm4gJ1RoZSB3aW5kb3dcXCdzIHNwYW4gd2FzIGNvbnZlcnRlZCB0byB0aGUgZ3JvdXBpbmcgc2hvd24uJztcbiAgfVxuXG4gIGNvbnN0IGF1dGhvcmVkID0gdW5pdENvdW50KG1ldGEucGVyaW9kcywgbWV0YS51bml0KTtcbiAgY29uc3QgZHJhd24gPSBncmFudWxhcml0eVxuICAgID8gdW5pdENvdW50KG1ldGEuZHJhd25QZXJpb2RzLCBncmFudWxhcml0eSlcbiAgICA6IGAke21ldGEuZHJhd25QZXJpb2RzfSAke21ldGEuZHJhd25QZXJpb2RzID09PSAxID8gJ3BlcmlvZCcgOiAncGVyaW9kcyd9YDtcblxuICByZXR1cm4gYCR7YXV0aG9yZWR9ICR7bWV0YS5wZXJpb2RzID09PSAxID8gJ2lzJyA6ICdhcmUnfSBzaG93biBhcyAke2RyYXdufSBhdCB0aGlzIGdyb3VwaW5nLmA7XG59XG5cbmZ1bmN0aW9uIHVuaXRDb3VudChjb3VudDogbnVtYmVyLCB1bml0OiBDaGFydEdyYW51bGFyaXR5KTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2NvdW50fSAke2NvdW50ID09PSAxID8gR1JBTlVMQVJJVFlfVU5JVFNbdW5pdF0ub25lIDogR1JBTlVMQVJJVFlfVU5JVFNbdW5pdF0ubWFueX1gO1xufVxuXG4vLyBXaHkgYSBLUEkncyBkZWx0YSByZWFkcyBhcyBpdCBkb2VzLCBhcyBhIHNlbnRlbmNlLiBUaGUgYmFzZWxpbmUgaXMgbmFtZWRcbi8vIGJ5IHdoYXQgdGhlIHZhbHVlIGlzIGNvbXBhcmVkIGFnYWluc3Q6IHRoZSBzYW1lIHBlcmlvZCBsYXN0IHllYXIgZm9yIGFcbi8vIHllYXItb24teWVhciBjb21wYXJpc29uLCBlbHNlIHRoZSBwZXJpb2QgYmVmb3JlLlxuZXhwb3J0IGZ1bmN0aW9uIGtwaU5vdGVUZXh0KGNvZGU6IEtwaU5vdGVDb2RlLCBhZ2FpbnN0PzogQ29tcGFyaXNvbkFnYWluc3QgfCBudWxsKTogc3RyaW5nIHtcbiAgY29uc3QgYmFzZWxpbmUgPSBrcGlCYXNlbGluZVRleHQoYWdhaW5zdCk7XG5cbiAgc3dpdGNoIChjb2RlKSB7XG4gICAgY2FzZSAnbm9fcHJpb3JfZGF0YSc6XG4gICAgICByZXR1cm4gYE5vIGJhc2VsaW5lOiAke2Jhc2VsaW5lfSBoYXMgbm8gZGF0YS5gO1xuICAgIGNhc2UgJ3VwX2Zyb21femVybyc6XG4gICAgICByZXR1cm4gYE5ldzogJHtiYXNlbGluZX0gd2FzIDAuYDtcbiAgICBjYXNlICdub19jaGFuZ2UnOlxuICAgICAgcmV0dXJuIGBObyBjaGFuZ2UgZnJvbSAke2Jhc2VsaW5lfS5gO1xuICAgIGNhc2UgJ25vX2RhdGFfZWl0aGVyJzpcbiAgICAgIHJldHVybiAnTm8gZGF0YSBpbiBlaXRoZXIgcGVyaW9kLic7XG4gICAgY2FzZSAnc2lnbl9jaGFuZ2UnOlxuICAgICAgcmV0dXJuICdUaGUgdmFsdWUgY3Jvc3NlZCB6ZXJvLCBzbyB0aGVyZSBpcyBubyBwZXJjZW50IGNoYW5nZS4nO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gJyc7XG4gIH1cbn1cblxuLy8gVGhlIHdpbmRvdyBhIEtQSSdzIHZhbHVlIGlzIGNvbXBhcmVkIHdpdGgsIGFzIGEgbm91biBwaHJhc2UuIEFuIHVua25vd24gb3Jcbi8vIG1pc3NpbmcgY29tcGFyaXNvbiByZWFkcyBhcyBuZXV0cmFsIHdvcmRpbmcgcmF0aGVyIHRoYW4gYSB3cm9uZyBwZXJpb2QuXG5mdW5jdGlvbiBrcGlCYXNlbGluZVRleHQoYWdhaW5zdDogQ29tcGFyaXNvbkFnYWluc3QgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgc3dpdGNoIChhZ2FpbnN0KSB7XG4gICAgY2FzZSAncHJldmlvdXNfcGVyaW9kJzpcbiAgICAgIHJldHVybiAndGhlIHByZXZpb3VzIHBlcmlvZCc7XG4gICAgY2FzZSAncHJldmlvdXNfd2Vlayc6XG4gICAgICByZXR1cm4gJ3RoZSBwcmV2aW91cyB3ZWVrJztcbiAgICBjYXNlICdwcmV2aW91c19tb250aCc6XG4gICAgICByZXR1cm4gJ3RoZSBwcmV2aW91cyBtb250aCc7XG4gICAgY2FzZSAncHJldmlvdXNfcXVhcnRlcic6XG4gICAgICByZXR1cm4gJ3RoZSBwcmV2aW91cyBxdWFydGVyJztcbiAgICBjYXNlICdwcmV2aW91c195ZWFyJzpcbiAgICAgIHJldHVybiAndGhlIHNhbWUgcGVyaW9kIGxhc3QgeWVhcic7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAndGhlIGNvbXBhcmlzb24gcGVyaW9kJztcbiAgfVxufVxuXG5mdW5jdGlvbiBjYXBpdGFsaXplKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB0ZXh0LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgdGV4dC5zbGljZSgxKTtcbn1cblxuXG4vLyBBIHNob3J0LCBodW1hbiBsYWJlbCBmb3IgYSB6b25lOiBpdHMgY2l0eSBwbHVzIHRoZSBjdXJyZW50IGFiYnJldmlhdGlvbixcbi8vIGUuZy4gJ0FtZXJpY2EvTmV3X1lvcmsnIHJlYWRzICdOZXcgWW9yayAoRURUKScuIFVUQyBzdGF5cyAnVVRDJywgYW5kIGFuXG4vLyB1bmtub3duIHpvbmUgaXMgc2hvd24gYXMgaXRzIGlkLiBBbiAnRXRjLycgem9uZSBuYW1lcyBubyBjaXR5LCBhbmQgaXRzIFBPU0lYXG4vLyBzaWduIGlzIHRoZSByZXZlcnNlIG9mIHRoZSBvZmZzZXQgKCdFdGMvR01UKzUnIGlzIEdNVC01KSwgc28gaXQgcmVhZHMgYXMgdGhlXG4vLyBhYmJyZXZpYXRpb24gYWxvbmU6ICdFdGMvVVRDJyBpcyAnVVRDJywgJ0V0Yy9HTVQrNScgaXMgJ0dNVC01Jy5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUaW1lem9uZUxhYmVsKHRpbWV6b25lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodGltZXpvbmUgPT09ICdVVEMnKSB7XG4gICAgcmV0dXJuIHRpbWV6b25lO1xuICB9XG5cbiAgY29uc3Qgc2VnbWVudHMgPSB0aW1lem9uZS5zcGxpdCgnLycpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgYWJicmV2aWF0aW9uID0gZm9ybWF0SW5UaW1lWm9uZShuZXcgRGF0ZSgpLCB0aW1lem9uZSwgJ3p6eicpO1xuXG4gICAgcmV0dXJuIHNlZ21lbnRzWzBdID09PSAnRXRjJ1xuICAgICAgPyBhYmJyZXZpYXRpb25cbiAgICAgIDogYCR7c2VnbWVudHNbc2VnbWVudHMubGVuZ3RoIC0gMV0ucmVwbGFjZSgvXy9nLCAnICcpfSAoJHthYmJyZXZpYXRpb259KWA7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB0aW1lem9uZTtcbiAgfVxufVxuXG5cbi8vIFwiTm93XCIgYXMgYSBEYXRlIHdob3NlIGxvY2FsIGZpZWxkcyByZWFkIHRoZSB3YWxsIGNsb2NrIGluIHRoZSBnaXZlbiB6b25lLCBzb1xuLy8gZGF0ZS1mbnMgY2FsZW5kYXIgYXJpdGhtZXRpYyAoc3RhcnRPZldlZWssIHN0YXJ0T2ZNb250aCwgLi4uKSBhbmRcbi8vIGRhdGVCb3VuZFN0cmluZygpIGxhbmQgb24gdGhlIHpvbmUncyBjYWxlbmRhciBkYXkgcmF0aGVyIHRoYW4gdGhlIGJyb3dzZXIncy5cbi8vIEFuIHVua25vd24gem9uZSBmYWxscyBiYWNrIHRvIHRoZSBicm93c2VyJ3MgY2xvY2suXG5leHBvcnQgZnVuY3Rpb24gZ2V0Wm9uZWROb3codGltZXpvbmU6IHN0cmluZyk6IERhdGUge1xuICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuXG4gIHRyeSB7XG4gICAgY29uc3Qgem9uZWQgPSB0b1pvbmVkVGltZShub3csIHRpbWV6b25lKTtcblxuICAgIHJldHVybiBOdW1iZXIuaXNOYU4oem9uZWQuZ2V0VGltZSgpKSA/IG5vdyA6IHpvbmVkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbm93O1xuICB9XG59XG4iXX0=
|