@firestitch/report 18.6.1 → 18.7.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 +8 -9
- package/app/reports/components/component-list/component-list.component.d.ts +33 -10
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +0 -1
- package/app/reports/components/report-component/report-component.component.d.ts +4 -2
- package/app/reports/data/report.data.d.ts +2 -1
- 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 -1
- 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-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 +12 -9
- package/app/reports/export/report-pdf.service.d.ts +1 -0
- package/app/reports/export/report-pptx.service.d.ts +17 -0
- package/app/reports/format.d.ts +38 -3
- package/app/reports/interfaces/report.interface.d.ts +81 -10
- package/app/reports/list-config.d.ts +9 -0
- package/app/reports/option-builder.d.ts +69 -9
- 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/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 +26 -2
- package/app/reports/theme/palette.d.ts +3 -0
- package/app/reports/theme/typography.d.ts +1 -0
- package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +19 -20
- package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +23 -29
- package/esm2022/app/reports/components/component-list/component-list.component.mjs +158 -32
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +3 -8
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +81 -21
- package/esm2022/app/reports/data/report.data.mjs +17 -4
- 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 +137 -15
- 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-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 +95 -40
- package/esm2022/app/reports/export/report-pdf.service.mjs +92 -36
- package/esm2022/app/reports/export/report-pptx.service.mjs +482 -86
- package/esm2022/app/reports/format.mjs +497 -58
- package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
- package/esm2022/app/reports/list-config.mjs +74 -0
- package/esm2022/app/reports/option-builder.mjs +868 -98
- 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/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 +235 -20
- package/esm2022/app/reports/theme/echarts.mjs +8 -2
- package/esm2022/app/reports/theme/palette.mjs +19 -1
- package/esm2022/app/reports/theme/typography.mjs +4 -1
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +1 -1
- package/esm2022/public_api.mjs +9 -1
- package/fesm2022/{firestitch-report-echarts-Djtmaxj1.mjs → firestitch-report-echarts-u5ImuZT5.mjs} +9 -3
- package/fesm2022/firestitch-report-echarts-u5ImuZT5.mjs.map +1 -0
- package/fesm2022/{firestitch-report-firestitch-report-D3zseBZc.mjs → firestitch-report-firestitch-report-Cz-kA_id.mjs} +3221 -660
- package/fesm2022/firestitch-report-firestitch-report-Cz-kA_id.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +8 -0
- package/fesm2022/firestitch-report-echarts-Djtmaxj1.mjs.map +0 -1
- package/fesm2022/firestitch-report-firestitch-report-D3zseBZc.mjs.map +0 -1
|
@@ -1,56 +1,434 @@
|
|
|
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
|
+
const NUMERIC_PATTERN = /^\s*[-+]?(\d+\.?\d*|\.\d+)([eE][-+]?\d+)?\s*$/;
|
|
123
|
+
// The formatToParts types that carry a number's digits and separators.
|
|
124
|
+
const NUMBER_PARTS = new Set(['integer', 'group', 'decimal', 'fraction']);
|
|
125
|
+
const DIGIT_PARTS = new Set(['integer', 'fraction']);
|
|
126
|
+
const UNIT_SCALES = new Map([
|
|
127
|
+
[ReportNumberUnits.Thousands, { divisor: 1e3, suffix: 'K', commas: ',' }],
|
|
128
|
+
[ReportNumberUnits.Millions, { divisor: 1e6, suffix: 'M', commas: ',,' }],
|
|
129
|
+
]);
|
|
130
|
+
// The value as a finite number when it is one or plainly spells one, else
|
|
131
|
+
// null.
|
|
132
|
+
export function toFiniteNumber(value) {
|
|
133
|
+
if (typeof value === 'number') {
|
|
134
|
+
return Number.isFinite(value) ? value : null;
|
|
135
|
+
}
|
|
136
|
+
if (typeof value !== 'string' || !NUMERIC_PATTERN.test(value)) {
|
|
137
|
+
return null;
|
|
25
138
|
}
|
|
26
139
|
const numeric = Number(value);
|
|
27
|
-
|
|
140
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
141
|
+
}
|
|
142
|
+
// Whether a slot asks to be formatted at all. A slot without these keys, or a
|
|
143
|
+
// list column whose format is date, keeps its own rendering. Units none is the
|
|
144
|
+
// same as no units key, as it is on the server.
|
|
145
|
+
export function hasNumberFormat(spec) {
|
|
146
|
+
if (!spec || spec.format === ReportListColumnFormat.Date) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return valueFormat(spec) !== null
|
|
150
|
+
|| (spec.precision ?? null) !== null
|
|
151
|
+
|| ((spec.units ?? ReportNumberUnits.None) !== ReportNumberUnits.None);
|
|
152
|
+
}
|
|
153
|
+
// The units a value is written in. auto decides by the magnitude: a million
|
|
154
|
+
// and up reads M, a thousand and up K, unless the value would then round to
|
|
155
|
+
// 1000K at these decimals, which reads 1M instead.
|
|
156
|
+
export function resolveUnits(units, magnitude, decimals) {
|
|
157
|
+
switch (units) {
|
|
158
|
+
case ReportNumberUnits.Thousands:
|
|
159
|
+
case ReportNumberUnits.Millions:
|
|
160
|
+
return units;
|
|
161
|
+
case ReportNumberUnits.Auto:
|
|
162
|
+
return autoUnits(Math.abs(magnitude), decimals);
|
|
163
|
+
default:
|
|
164
|
+
return ReportNumberUnits.None;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function autoUnits(magnitude, decimals) {
|
|
168
|
+
if (magnitude >= 1e6) {
|
|
169
|
+
return ReportNumberUnits.Millions;
|
|
170
|
+
}
|
|
171
|
+
if (magnitude < 1e3) {
|
|
172
|
+
return ReportNumberUnits.None;
|
|
173
|
+
}
|
|
174
|
+
return roundTo(magnitude / 1e3, decimals) >= 1000
|
|
175
|
+
? ReportNumberUnits.Millions
|
|
176
|
+
: ReportNumberUnits.Thousands;
|
|
177
|
+
}
|
|
178
|
+
// The value rounded as Intl rounds it for display, so the K-to-M promotion
|
|
179
|
+
// agrees with the digits actually shown.
|
|
180
|
+
function roundTo(value, decimals) {
|
|
181
|
+
const digits = clampDecimals(decimals) ?? 0;
|
|
182
|
+
// A fixed locale only so Number() can parse the rounded digits back.
|
|
183
|
+
return Number(numberFormat(REPORT_FALLBACK_LOCALE, {
|
|
184
|
+
useGrouping: false,
|
|
185
|
+
minimumFractionDigits: 0,
|
|
186
|
+
maximumFractionDigits: digits,
|
|
187
|
+
}).format(value));
|
|
188
|
+
}
|
|
189
|
+
// One value, written by the rules above.
|
|
190
|
+
export function formatNumber(value, spec, context, options = {}) {
|
|
191
|
+
if (isEmptyValue(value)) {
|
|
192
|
+
return options.empty ?? EMPTY_VALUE;
|
|
193
|
+
}
|
|
194
|
+
const numeric = toFiniteNumber(value);
|
|
195
|
+
if (numeric === null) {
|
|
28
196
|
return String(value);
|
|
29
197
|
}
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
198
|
+
const style = resolveStyle(spec);
|
|
199
|
+
const precision = clampDecimals(spec?.precision);
|
|
200
|
+
const units = style === ReportValueFormat.Percent
|
|
201
|
+
? ReportNumberUnits.None
|
|
202
|
+
: options.units ?? resolveUnits(spec?.units, numeric, precision ?? SCALED_DECIMALS);
|
|
203
|
+
const scale = UNIT_SCALES.get(units);
|
|
204
|
+
const decimals = clampDecimals(options.decimals) ?? precision;
|
|
205
|
+
const formatter = numberFormat(context.locale, styleOptions(style, context, decimals, !!scale));
|
|
206
|
+
const text = writeNumber(formatter, (numeric === 0 ? 0 : numeric) / (scale?.divisor ?? 1), scale?.suffix);
|
|
207
|
+
return style === ReportValueFormat.Percent && !context.ratioPercent ? `${text}%` : text;
|
|
208
|
+
}
|
|
209
|
+
function isEmptyValue(value) {
|
|
210
|
+
return value === null
|
|
211
|
+
|| value === undefined
|
|
212
|
+
|| value === ''
|
|
213
|
+
|| value === '-'
|
|
214
|
+
|| (typeof value === 'number' && !Number.isFinite(value));
|
|
215
|
+
}
|
|
216
|
+
// The value format a slot names, or null when it names none (or only date).
|
|
217
|
+
function valueFormat(spec) {
|
|
218
|
+
return Object.values(ReportValueFormat).find((format) => format === spec?.format) ?? null;
|
|
219
|
+
}
|
|
220
|
+
function resolveStyle(spec) {
|
|
221
|
+
return valueFormat(spec) ?? ReportValueFormat.Number;
|
|
222
|
+
}
|
|
223
|
+
// A usable decimal count, or null. A stored value outside the schema's bounds
|
|
224
|
+
// is brought inside them rather than thrown on by Intl.
|
|
225
|
+
function clampDecimals(decimals) {
|
|
226
|
+
return typeof decimals === 'number' && Number.isFinite(decimals)
|
|
227
|
+
? Math.min(MAX_PRECISION, Math.max(0, Math.round(decimals)))
|
|
228
|
+
: null;
|
|
229
|
+
}
|
|
230
|
+
function styleOptions(style, context, decimals, scaled) {
|
|
231
|
+
const fractionDigits = fractionDigitOptions(decimals, defaultDecimals(style, scaled));
|
|
232
|
+
switch (style) {
|
|
233
|
+
case ReportValueFormat.Currency:
|
|
234
|
+
return { ...currencyOptions(context.currency), ...fractionDigits };
|
|
235
|
+
case ReportValueFormat.Percent:
|
|
236
|
+
return context.ratioPercent ? { style: 'percent', ...fractionDigits } : fractionDigits;
|
|
50
237
|
default:
|
|
51
|
-
return
|
|
238
|
+
return fractionDigits;
|
|
52
239
|
}
|
|
53
240
|
}
|
|
241
|
+
function currencyOptions(currency) {
|
|
242
|
+
return { style: 'currency', currency, currencyDisplay: 'symbol' };
|
|
243
|
+
}
|
|
244
|
+
// The most decimals a style shows when nothing pins them; null leaves Intl's
|
|
245
|
+
// own default.
|
|
246
|
+
function defaultDecimals(style, scaled) {
|
|
247
|
+
if (scaled) {
|
|
248
|
+
return SCALED_DECIMALS;
|
|
249
|
+
}
|
|
250
|
+
switch (style) {
|
|
251
|
+
case ReportValueFormat.Percent:
|
|
252
|
+
return PERCENT_DECIMALS;
|
|
253
|
+
case ReportValueFormat.Currency:
|
|
254
|
+
return CURRENCY_DECIMALS;
|
|
255
|
+
default:
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// Pinned decimals set both bounds. Otherwise a maximum also sets the minimum
|
|
260
|
+
// to zero, so no engine throws on a maximum below a currency's own minimum.
|
|
261
|
+
function fractionDigitOptions(pinned, maximum) {
|
|
262
|
+
if (pinned !== null) {
|
|
263
|
+
return { minimumFractionDigits: pinned, maximumFractionDigits: pinned };
|
|
264
|
+
}
|
|
265
|
+
return maximum === null ? {} : { minimumFractionDigits: 0, maximumFractionDigits: maximum };
|
|
266
|
+
}
|
|
267
|
+
// The formatted value, with the units letter after its digits. A negative
|
|
268
|
+
// whose shown digits are all zero is written as zero, so no '-0' appears.
|
|
269
|
+
function writeNumber(formatter, value, suffix) {
|
|
270
|
+
if (value >= 0 && !suffix) {
|
|
271
|
+
return formatter.format(value);
|
|
272
|
+
}
|
|
273
|
+
const parts = formatter.formatToParts(value);
|
|
274
|
+
if (value < 0 && !hasNonZeroDigit(formatter, parts)) {
|
|
275
|
+
return writeNumber(formatter, 0, suffix);
|
|
276
|
+
}
|
|
277
|
+
if (!suffix) {
|
|
278
|
+
return parts.map((part) => part.value).join('');
|
|
279
|
+
}
|
|
280
|
+
const last = parts.reduce((found, part, index) => NUMBER_PARTS.has(part.type) ? index : found, -1);
|
|
281
|
+
return [
|
|
282
|
+
...parts.slice(0, last + 1).map((part) => part.value),
|
|
283
|
+
suffix,
|
|
284
|
+
...parts.slice(last + 1).map((part) => part.value),
|
|
285
|
+
].join('');
|
|
286
|
+
}
|
|
287
|
+
// Compared with the locale's own zero, so a numbering system other than
|
|
288
|
+
// 0-9 is read correctly.
|
|
289
|
+
function hasNonZeroDigit(formatter, parts) {
|
|
290
|
+
const zero = formatter.formatToParts(0).find((part) => part.type === 'integer')?.value ?? '0';
|
|
291
|
+
return parts.some((part) => DIGIT_PARTS.has(part.type)
|
|
292
|
+
&& Array.from(part.value).some((character) => character !== zero));
|
|
293
|
+
}
|
|
294
|
+
// A chart's value axis takes a format only when every measure on it agrees on
|
|
295
|
+
// the style (each measure's format, number when it names none) and at least
|
|
296
|
+
// one of them names a format. The first measure that does gives the axis its
|
|
297
|
+
// precision and units. Otherwise null: the axis keeps its default ticks on
|
|
298
|
+
// screen and in PowerPoint, and each series still formats its own tooltips.
|
|
299
|
+
export function axisNumberFormat(measures) {
|
|
300
|
+
const style = measures.length ? resolveStyle(measures[0]) : null;
|
|
301
|
+
if (style === null || measures.some((measure) => resolveStyle(measure) !== style)) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
const formatted = measures.find((measure) => hasNumberFormat(measure));
|
|
305
|
+
return formatted ? numberFormatSpec(formatted) : null;
|
|
306
|
+
}
|
|
307
|
+
function numberFormatSpec(spec) {
|
|
308
|
+
return {
|
|
309
|
+
...(spec.format !== undefined ? { format: spec.format } : {}),
|
|
310
|
+
...(spec.precision !== undefined ? { precision: spec.precision } : {}),
|
|
311
|
+
...(spec.units !== undefined ? { units: spec.units } : {}),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
// How a chart's value axis writes its ticks: the units decided once from the
|
|
315
|
+
// axis peak, and the decimals the precision pins, else as many as the axis's
|
|
316
|
+
// tick step needs (a percent axis up to 0.12% steps by 0.02%, two decimals).
|
|
317
|
+
// Pinned decimals keep the ticks distinct, and PowerPoint can only pin them.
|
|
318
|
+
export function resolveChartNumberFormat(spec, peak, context) {
|
|
319
|
+
const style = resolveStyle(spec);
|
|
320
|
+
const precision = clampDecimals(spec.precision);
|
|
321
|
+
const units = style === ReportValueFormat.Percent
|
|
322
|
+
? ReportNumberUnits.None
|
|
323
|
+
: resolveUnits(spec.units, peak, precision ?? SCALED_DECIMALS);
|
|
324
|
+
return { units, decimals: precision ?? axisDecimals(style, units, peak, context) };
|
|
325
|
+
}
|
|
326
|
+
// The decimals the axis's nice tick step needs. A plain, unabbreviated number
|
|
327
|
+
// pins none (null): its ticks keep their own decimals. An unscaled currency
|
|
328
|
+
// axis that needs decimals shows cents, and a K/M axis keeps its step's
|
|
329
|
+
// decimals ('$0.5M', not '$0.50M').
|
|
330
|
+
function axisDecimals(style, units, peak, context) {
|
|
331
|
+
const scale = UNIT_SCALES.get(units);
|
|
332
|
+
if (style === ReportValueFormat.Number && !scale) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
const shownPeak = style === ReportValueFormat.Percent && context.ratioPercent
|
|
336
|
+
? Math.abs(peak) * 100
|
|
337
|
+
: Math.abs(peak) / (scale?.divisor ?? 1);
|
|
338
|
+
const step = niceStep(shownPeak / AXIS_TICKS);
|
|
339
|
+
const decimals = step > 0 ? clampDecimals(-Math.floor(Math.log10(step))) ?? 0 : 0;
|
|
340
|
+
return style === ReportValueFormat.Currency && decimals > 0 && !scale ? CURRENCY_AXIS_DECIMALS : decimals;
|
|
341
|
+
}
|
|
342
|
+
// ECharts' nice(): the round number (1, 2, 3, 5 or 10 times a power of ten) a
|
|
343
|
+
// rough tick step snaps to.
|
|
344
|
+
function niceStep(rough) {
|
|
345
|
+
if (!(rough > 0) || !Number.isFinite(rough)) {
|
|
346
|
+
return 0;
|
|
347
|
+
}
|
|
348
|
+
const exponent = Math.floor(Math.log10(rough));
|
|
349
|
+
const power = Math.pow(10, exponent);
|
|
350
|
+
const fraction = rough / power;
|
|
351
|
+
let nice = 10;
|
|
352
|
+
if (fraction < 1.5) {
|
|
353
|
+
nice = 1;
|
|
354
|
+
}
|
|
355
|
+
else if (fraction < 2.5) {
|
|
356
|
+
nice = 2;
|
|
357
|
+
}
|
|
358
|
+
else if (fraction < 4) {
|
|
359
|
+
nice = 3;
|
|
360
|
+
}
|
|
361
|
+
else if (fraction < 7) {
|
|
362
|
+
nice = 5;
|
|
363
|
+
}
|
|
364
|
+
return nice * power;
|
|
365
|
+
}
|
|
366
|
+
// PowerPoint's number format code for a formatted value axis, matching the
|
|
367
|
+
// screen's ticks: '#,##0.0%' (percent), '"$"#,##0' (currency),
|
|
368
|
+
// '#,##0.0,"K"' (thousands), '#,##0" $"' (fr-CA currency). A plain number
|
|
369
|
+
// whose decimals are not pinned keeps chartAxisFormatCode's code. The code's
|
|
370
|
+
// separators follow the opening machine's locale; the currency symbol and its
|
|
371
|
+
// side follow the report's.
|
|
372
|
+
export function numberFormatCode(spec, context, chart, series, stacked) {
|
|
373
|
+
const style = resolveStyle(spec);
|
|
374
|
+
const scale = style === ReportValueFormat.Percent ? undefined : UNIT_SCALES.get(chart.units);
|
|
375
|
+
if (style === ReportValueFormat.Number && !scale && chart.decimals === null) {
|
|
376
|
+
return chartAxisFormatCode(series, stacked);
|
|
377
|
+
}
|
|
378
|
+
const decimals = chart.decimals ?? 0;
|
|
379
|
+
const digits = `#,##0${decimals > 0 ? `.${'0'.repeat(decimals)}` : ''}`;
|
|
380
|
+
if (style === ReportValueFormat.Percent) {
|
|
381
|
+
return `${digits}${context.ratioPercent ? '%' : '"%"'}`;
|
|
382
|
+
}
|
|
383
|
+
const scaled = `${digits}${scale?.commas ?? ''}`;
|
|
384
|
+
const unit = scale?.suffix ?? '';
|
|
385
|
+
if (style !== ReportValueFormat.Currency) {
|
|
386
|
+
return unit ? `${scaled}"${unit}"` : scaled;
|
|
387
|
+
}
|
|
388
|
+
const symbol = currencySymbol(context);
|
|
389
|
+
return symbol.prefix
|
|
390
|
+
? `"${symbol.text}"${scaled}${unit ? `"${unit}"` : ''}`
|
|
391
|
+
: `${scaled}"${unit}${symbol.text}"`;
|
|
392
|
+
}
|
|
393
|
+
const CURRENCY_SYMBOLS = new Map();
|
|
394
|
+
function currencySymbol(context) {
|
|
395
|
+
const key = `${context.locale}|${context.currency}`;
|
|
396
|
+
let symbol = CURRENCY_SYMBOLS.get(key);
|
|
397
|
+
if (!symbol) {
|
|
398
|
+
const parts = numberFormat(context.locale, currencyOptions(context.currency)).formatToParts(1);
|
|
399
|
+
const currency = parts.findIndex((part) => part.type === 'currency');
|
|
400
|
+
const first = parts.findIndex((part) => NUMBER_PARTS.has(part.type));
|
|
401
|
+
const last = parts.reduce((found, part, index) => NUMBER_PARTS.has(part.type) ? index : found, -1);
|
|
402
|
+
const prefix = currency < first;
|
|
403
|
+
const text = (prefix ? parts.slice(Math.max(currency, 0), first) : parts.slice(last + 1))
|
|
404
|
+
.map((part) => part.value)
|
|
405
|
+
.join('')
|
|
406
|
+
.replace(/"/g, '');
|
|
407
|
+
symbol = { prefix, text };
|
|
408
|
+
CURRENCY_SYMBOLS.set(key, symbol);
|
|
409
|
+
}
|
|
410
|
+
return symbol;
|
|
411
|
+
}
|
|
412
|
+
// Every decimal a number has, grouped, in the locale: what ECharts prints by
|
|
413
|
+
// default (its addCommas), but in the report's locale, so a chart's axis and
|
|
414
|
+
// tooltip read like the rest of the report. 1234.5 reads 1,234.5 in en-US and
|
|
415
|
+
// 1 234,5 in fr-CA. A non-numeric string is shown as it came, and anything
|
|
416
|
+
// else non-numeric as '-', as ECharts shows it. As there, an infinite value
|
|
417
|
+
// reads 'Infinity' and negative zero (a tick a float error leaves just below
|
|
418
|
+
// zero) reads '0'.
|
|
419
|
+
const PLAIN_NUMBER = { maximumFractionDigits: 20 };
|
|
420
|
+
export function formatPlainNumber(value, locale) {
|
|
421
|
+
const numeric = typeof value === 'number'
|
|
422
|
+
? value
|
|
423
|
+
: typeof value === 'string' && value.trim() !== '' ? Number(value) : NaN;
|
|
424
|
+
if (Number.isNaN(numeric)) {
|
|
425
|
+
return typeof value === 'string' ? value : '-';
|
|
426
|
+
}
|
|
427
|
+
if (!Number.isFinite(numeric)) {
|
|
428
|
+
return String(numeric);
|
|
429
|
+
}
|
|
430
|
+
return numberFormat(locale, PLAIN_NUMBER).format(numeric === 0 ? 0 : numeric);
|
|
431
|
+
}
|
|
54
432
|
// The axis peak at which a native chart's value axis gains thousands
|
|
55
433
|
// separators. From here up the ticks are whole numbers in practice; below it
|
|
56
434
|
// neither the screen nor PowerPoint's 'General' shows a separator.
|
|
@@ -61,15 +439,19 @@ export const AXIS_SEPARATOR_THRESHOLD = 1000;
|
|
|
61
439
|
// (where ticks are whole numbers) gets '#,##0', and a smaller range keeps
|
|
62
440
|
// 'General' so fractional ticks (0.25, 0.5) are not rounded away.
|
|
63
441
|
//
|
|
64
|
-
// The peak
|
|
65
|
-
// stack: the largest sum, per category, of every series' absolute value.
|
|
442
|
+
// The peak is chartValuePeak's.
|
|
66
443
|
export function chartAxisFormatCode(series, stacked) {
|
|
444
|
+
return chartValuePeak(series, stacked) >= AXIS_SEPARATOR_THRESHOLD ? '#,##0' : 'General';
|
|
445
|
+
}
|
|
446
|
+
// The largest magnitude a chart's value axis has to reach. A missing value
|
|
447
|
+
// counts as 0. A stacked chart's peak is its tallest stack: the largest sum,
|
|
448
|
+
// per category, of every series' absolute value.
|
|
449
|
+
export function chartValuePeak(series, stacked) {
|
|
67
450
|
const magnitudes = series.map((values) => values.map((value) => Math.abs(value ?? 0)));
|
|
68
|
-
|
|
451
|
+
return stacked
|
|
69
452
|
? Math.max(0, ...(magnitudes[0] ?? []).map((_, index) => magnitudes
|
|
70
453
|
.reduce((sum, values) => sum + (values[index] ?? 0), 0)))
|
|
71
454
|
: Math.max(0, ...magnitudes.flat());
|
|
72
|
-
return peak >= AXIS_SEPARATOR_THRESHOLD ? '#,##0' : 'General';
|
|
73
455
|
}
|
|
74
456
|
// The zone every date in a report is read in. The server resolves it (the
|
|
75
457
|
// report's own zone, else the application's default reporting zone) and sends
|
|
@@ -80,6 +462,52 @@ export function chartAxisFormatCode(series, stacked) {
|
|
|
80
462
|
export function resolveReportTimezone(report) {
|
|
81
463
|
return report.effectiveTimezone ?? report.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
82
464
|
}
|
|
465
|
+
// The date shapes a report writes, each in the report's locale.
|
|
466
|
+
// 'Jan 5, 2026' / '5 janv. 2026': a date cell, a filter bound.
|
|
467
|
+
export const DAY_SHORT = { year: 'numeric', month: 'short', day: 'numeric' };
|
|
468
|
+
// 'January 5, 2026' / '5 janvier 2026': an export cover's date line.
|
|
469
|
+
export const DAY_LONG = { year: 'numeric', month: 'long', day: 'numeric' };
|
|
470
|
+
// 'January' / 'janvier': a monthly period label (its year is added apart).
|
|
471
|
+
export const MONTH_LONG = { month: 'long' };
|
|
472
|
+
// 'January 2026' / 'janvier 2026': a monthly period label written in full.
|
|
473
|
+
export const MONTH_YEAR = { year: 'numeric', month: 'long' };
|
|
474
|
+
// 'Jan 5' / '5 janv.': a daily or weekly period label.
|
|
475
|
+
export const MONTH_DAY = { month: 'short', day: 'numeric' };
|
|
476
|
+
// A date in the locale. With a zone, the day it falls on there; without one,
|
|
477
|
+
// the browser's zone, which keeps a calendar day parsed as local midnight
|
|
478
|
+
// unshifted. It never throws, since a pipe or an export calls it per cell: an
|
|
479
|
+
// invalid Date reads '', a malformed locale ('en_CA') reads the fallback
|
|
480
|
+
// locale, and an unknown zone reads UTC, which still names a real day.
|
|
481
|
+
export function formatLocalDate(date, locale, options, timeZone) {
|
|
482
|
+
if (Number.isNaN(date.getTime())) {
|
|
483
|
+
return '';
|
|
484
|
+
}
|
|
485
|
+
try {
|
|
486
|
+
return writeDate(dateFormat(locale, options, timeZone), date);
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
return formatFallbackDate(date, resolveReportLocale(locale), options, timeZone);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
function formatFallbackDate(date, locale, options, timeZone) {
|
|
493
|
+
try {
|
|
494
|
+
return writeDate(dateFormat(locale, options, timeZone), date);
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
return writeDate(dateFormat(locale, options, 'UTC'), date);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
// Intl writes a year below 1000 with only the digits it has ('Jan 1, 1'); a
|
|
501
|
+
// date's year is always written with four ('Jan 1, 0001'), so a sentinel day
|
|
502
|
+
// still reads as a date. Only such a year pays for formatToParts.
|
|
503
|
+
function writeDate(formatter, date) {
|
|
504
|
+
if (date.getUTCFullYear() > 1000) {
|
|
505
|
+
return formatter.format(date);
|
|
506
|
+
}
|
|
507
|
+
return formatter.formatToParts(date)
|
|
508
|
+
.map((part) => part.type === 'year' ? part.value.padStart(4, '0') : part.value)
|
|
509
|
+
.join('');
|
|
510
|
+
}
|
|
83
511
|
const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
84
512
|
const DATE_TIME_PATTERN = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(\.\d+)?$/;
|
|
85
513
|
// A report row's date cell as a calendar day in the report's zone.
|
|
@@ -95,29 +523,40 @@ const DATE_TIME_PATTERN = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(\.\d+)?$/
|
|
|
95
523
|
// - Anything else is shown as it came, and so is a value that has the shape
|
|
96
524
|
// but names no real day (a zero date '0000-00-00', or '2026-02-30'): one
|
|
97
525
|
// bad cell must not throw out of a pipe or abort an export.
|
|
98
|
-
|
|
526
|
+
// The day is written in the report's locale: 'Jan 5, 2026' in en-US, '5 janv.
|
|
527
|
+
// 2026' in fr-CA.
|
|
528
|
+
export function formatReportDate(value, timezone, locale) {
|
|
99
529
|
if (value === null || value === undefined || value === '') {
|
|
100
530
|
return '';
|
|
101
531
|
}
|
|
102
532
|
const text = String(value);
|
|
103
533
|
if (DATE_ONLY_PATTERN.test(text)) {
|
|
104
534
|
const day = parseISO(text);
|
|
105
|
-
return isValid(day) ?
|
|
535
|
+
return isValid(day) ? formatLocalDate(day, locale, DAY_SHORT) : text;
|
|
106
536
|
}
|
|
107
537
|
const dateTime = DATE_TIME_PATTERN.exec(text);
|
|
108
538
|
if (!dateTime) {
|
|
109
539
|
return text;
|
|
110
540
|
}
|
|
111
541
|
const instant = parseISO(`${dateTime[1]}T${dateTime[2]}Z`);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
542
|
+
return isValid(instant) ? formatLocalDate(instant, locale, DAY_SHORT, timezone) : text;
|
|
543
|
+
}
|
|
544
|
+
// English names for a locale and a currency, for the settings selects. The
|
|
545
|
+
// interface stays English whatever the report's locale: 'fr-CA' reads
|
|
546
|
+
// 'Canadian French', 'CAD' reads 'Canadian Dollar'. A runtime without the
|
|
547
|
+
// names shows the code.
|
|
548
|
+
export function localeName(tag) {
|
|
549
|
+
return displayName('language', tag);
|
|
550
|
+
}
|
|
551
|
+
export function currencyName(code) {
|
|
552
|
+
return displayName('currency', code);
|
|
553
|
+
}
|
|
554
|
+
function displayName(type, code) {
|
|
116
555
|
try {
|
|
117
|
-
return
|
|
556
|
+
return new Intl.DisplayNames(['en'], { type }).of(code) ?? code;
|
|
118
557
|
}
|
|
119
558
|
catch {
|
|
120
|
-
return
|
|
559
|
+
return code;
|
|
121
560
|
}
|
|
122
561
|
}
|
|
123
562
|
// A short, human label for a zone: its city plus the current abbreviation,
|
|
@@ -154,4 +593,4 @@ export function getZonedNow(timezone) {
|
|
|
154
593
|
return now;
|
|
155
594
|
}
|
|
156
595
|
}
|
|
157
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2Zvcm1hdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDckQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUs1RCw0RUFBNEU7QUFDNUUsZ0ZBQWdGO0FBQ2hGLDZDQUE2QztBQUU3Qyw4RUFBOEU7QUFDOUUsd0VBQXdFO0FBQ3hFLHdFQUF3RTtBQUN4RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSxFQUFFO0FBQ0YsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0UsU0FBUztBQUNULFNBQVMsaUJBQWlCLENBQUMsU0FBa0I7SUFDM0MsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztRQUMvQixDQUFDLENBQUMsRUFBRSxxQkFBcUIsRUFBRSxTQUFTLEVBQUUscUJBQXFCLEVBQUUsU0FBUyxFQUFFO1FBQ3hFLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDVCxDQUFDO0FBRUQsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxLQUFjLEVBQ2QsTUFBZSxFQUNmLFNBQWtCLEVBQ2xCLFlBQVksR0FBRyxJQUFJO0lBRW5CLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUMxRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDOUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM5QixPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FB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TUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUV2QixJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRXpDLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDckQsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmb3JtYXQsIGlzVmFsaWQsIHBhcnNlSVNPIH0gZnJvbSAnZGF0ZS1mbnMnO1xuaW1wb3J0IHsgZm9ybWF0SW5UaW1lWm9uZSwgdG9ab25lZFRpbWUgfSBmcm9tICdkYXRlLWZucy10eic7XG5cbmltcG9ydCB7IFJlcG9ydCB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcblxuXG4vLyBNZWFzdXJlLXZhbHVlIGZvcm1hdHRpbmcgc2hhcmVkIGJ5IHRoZSBLUEkgcmVuZGVyZXIgYW5kIHRoZSBleHBvcnRzIOKAlCB0aGVcbi8vIGNvbmZpZydzIGBmb3JtYXRgIChudW1iZXIgfCBwZXJjZW50IHwgY3VycmVuY3kpIGFuZCBgcHJlY2lzaW9uYCBtZWFuIHRoZSBzYW1lXG4vLyB0aGluZyBvbiBzY3JlZW4sIGluIFBvd2VyUG9pbnQgYW5kIGluIFBERi5cblxuLy8gcGVyY2VudCB0YWtlcyBhIDAtMSByYXRpbyBhbmQgc2hvd3MgaXQgYXMgYSBwZXJjZW50YWdlOiAwLjMgcmVhZHMgMzAlLiBXaXRoXG4vLyBubyBwcmVjaXNpb24gaXQgc2hvd3MgYXQgbW9zdCBvbmUgZGVjaW1hbCAoMC4wMzcgcmVhZHMgMy43JSk7IGEgbmFtZWRcbi8vIHByZWNpc2lvbiBjb3VudHMgdGhlIGRlY2ltYWxzIG9mIHRoZSBwZXJjZW50YWdlLCBub3Qgb2YgdGhlIHJhdGlvLCBzb1xuLy8gcHJlY2lzaW9uIDEgc2hvd3MgMC4zIGFzIDMwLjAlLiBBbiBvbGRlciBzZXJ2ZXIgc2VuZHMgcGVyY2VudCB2YWx1ZXMgYWxyZWFkeVxuLy8geDEwMCAoMzguNSBmb3IgMzguNSUpOyBpdHMgcmVwb3J0cyBjYXJyeSBubyBgcGVyY2VudEZvcm1hdGAsIGFuZCB0aGUgY2FsbGVyXG4vLyBwYXNzZXMgcmF0aW9QZXJjZW50IGZhbHNlIHNvIHRoZSB2YWx1ZSBpcyBwcmludGVkIGFzIGl0IGNhbWUsIHdpdGggYSAlIHNpZ24uXG4vL1xuLy8gV2hlbiB0aGUgbWVhc3VyZSBuYW1lcyBhIHByZWNpc2lvbiBpdCBpcyBwaW5uZWQgYXMgQk9USCB0aGUgbWluaW11bSBhbmQgdGhlXG4vLyBtYXhpbXVtLCBzbyBhIGNvbHVtbiBvZiByYXRlcyBsaW5lcyB1cCBpbnN0ZWFkIG9mIGVhY2ggdmFsdWUgc2hvd2luZyBob3dldmVyXG4vLyBtYW55IGRlY2ltYWxzIGl0IGhhcHBlbnMgdG8gbmVlZC4gVW5kZWZpbmVkIGxlYXZlcyBlYWNoIGZvcm1hdCdzIG93biBkZWZhdWx0XG4vLyBhbG9uZS5cbmZ1bmN0aW9uIGdldEZyYWN0aW9uRGlnaXRzKHByZWNpc2lvbj86IG51bWJlcik6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyB7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUocHJlY2lzaW9uKVxuICAgID8geyBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IHByZWNpc2lvbiwgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiBwcmVjaXNpb24gfVxuICAgIDoge307XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRNZWFzdXJlVmFsdWUoXG4gIHZhbHVlOiB1bmtub3duLFxuICBmb3JtYXQ/OiBzdHJpbmcsXG4gIHByZWNpc2lvbj86IG51bWJlcixcbiAgcmF0aW9QZXJjZW50ID0gdHJ1ZSxcbik6IHN0cmluZyB7XG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykge1xuICAgIHJldHVybiAn4oCUJztcbiAgfVxuXG4gIGNvbnN0IG51bWVyaWMgPSBOdW1iZXIodmFsdWUpO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShudW1lcmljKSkge1xuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgY29uc3QgZnJhY3Rpb25EaWdpdHMgPSBnZXRGcmFjdGlvbkRpZ2l0cyhwcmVjaXNpb24pO1xuXG4gIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgY2FzZSAncGVyY2VudCc6XG4gICAgICBpZiAoIXJhdGlvUGVyY2VudCkge1xuICAgICAgICByZXR1cm4gYCR7bmV3IEludGwuTnVtYmVyRm9ybWF0KHVuZGVmaW5lZCwgeyBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDEsIC4uLmZyYWN0aW9uRGlnaXRzIH0pLmZvcm1hdChudW1lcmljKX0lYDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBJbnRsLk51bWJlckZvcm1hdCh1bmRlZmluZWQsIHtcbiAgICAgICAgc3R5bGU6ICdwZXJjZW50JyxcbiAgICAgICAgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiAxLFxuICAgICAgICAuLi5mcmFjdGlvbkRpZ2l0cyxcbiAgICAgIH0pLmZvcm1hdChudW1lcmljKTtcbiAgICBjYXNlICdjdXJyZW5jeSc6XG4gICAgICByZXR1cm4gbmV3IEludGwuTnVtYmVyRm9ybWF0KHVuZGVmaW5lZCwge1xuICAgICAgICBzdHlsZTogJ2N1cnJlbmN5JyxcbiAgICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgICAvLyBXaG9sZSBkb2xsYXJzIHVubGVzcyB0aGUgbWVhc3VyZSBhc2tzIGZvciBkZWNpbWFscyDigJQgY2VudHMgd2VyZVxuICAgICAgICAvLyB1bnJlcHJlc2VudGFibGUgYmVmb3JlLCBiZWNhdXNlIHRoaXMgd2FzIGhhcmRjb2RlZCB0byAwLlxuICAgICAgICBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDAsXG4gICAgICAgIC4uLmZyYWN0aW9uRGlnaXRzLFxuICAgICAgfSkuZm9ybWF0KG51bWVyaWMpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IEludGwuTnVtYmVyRm9ybWF0KHVuZGVmaW5lZCwgZnJhY3Rpb25EaWdpdHMpLmZvcm1hdChudW1lcmljKTtcbiAgfVxufVxuXG5cbi8vIFRoZSBheGlzIHBlYWsgYXQgd2hpY2ggYSBuYXRpdmUgY2hhcnQncyB2YWx1ZSBheGlzIGdhaW5zIHRob3VzYW5kc1xuLy8gc2VwYXJhdG9ycy4gRnJvbSBoZXJlIHVwIHRoZSB0aWNrcyBhcmUgd2hvbGUgbnVtYmVycyBpbiBwcmFjdGljZTsgYmVsb3cgaXRcbi8vIG5laXRoZXIgdGhlIHNjcmVlbiBub3IgUG93ZXJQb2ludCdzICdHZW5lcmFsJyBzaG93cyBhIHNlcGFyYXRvci5cbmV4cG9ydCBjb25zdCBBWElTX1NFUEFSQVRPUl9USFJFU0hPTEQgPSAxMDAwO1xuXG4vLyBQb3dlclBvaW50J3MgbnVtYmVyIGZvcm1hdCBmb3IgYSBuYXRpdmUgY2hhcnQncyB2YWx1ZSBheGlzLCBtYXRjaGluZyB3aGF0IHRoZVxuLy8gb24tc2NyZWVuIGF4aXMgcHJpbnRzIGJ5IGRlZmF1bHQ6IHRob3VzYW5kcyBzZXBhcmF0b3JzIHdpdGggZWFjaCB0aWNrJ3Mgb3duXG4vLyBkZWNpbWFscy4gRXhjZWwgaGFzIG5vIFwiR2VuZXJhbCB3aXRoIHNlcGFyYXRvcnNcIiwgc28gYW4gYXhpcyByZWFjaGluZyAxLDAwMFxuLy8gKHdoZXJlIHRpY2tzIGFyZSB3aG9sZSBudW1iZXJzKSBnZXRzICcjLCMjMCcsIGFuZCBhIHNtYWxsZXIgcmFuZ2Uga2VlcHNcbi8vICdHZW5lcmFsJyBzbyBmcmFjdGlvbmFsIHRpY2tzICgwLjI1LCAwLjUpIGFyZSBub3Qgcm91bmRlZCBhd2F5LlxuLy9cbi8vIFRoZSBwZWFrIGNvdW50cyBhIG1pc3NpbmcgdmFsdWUgYXMgMC4gQSBzdGFja2VkIGNoYXJ0J3MgcGVhayBpcyBpdHMgdGFsbGVzdFxuLy8gc3RhY2s6IHRoZSBsYXJnZXN0IHN1bSwgcGVyIGNhdGVnb3J5LCBvZiBldmVyeSBzZXJpZXMnIGFic29sdXRlIHZhbHVlLlxuZXhwb3J0IGZ1bmN0aW9uIGNoYXJ0QXhpc0Zvcm1hdENvZGUoc2VyaWVzOiAobnVtYmVyIHwgbnVsbClbXVtdLCBzdGFja2VkOiBib29sZWFuKTogc3RyaW5nIHtcbiAgY29uc3QgbWFnbml0dWRlcyA9IHNlcmllcy5tYXAoKHZhbHVlcykgPT4gdmFsdWVzLm1hcCgodmFsdWUpID0+IE1hdGguYWJzKHZhbHVlID8/IDApKSk7XG5cbiAgY29uc3QgcGVhayA9IHN0YWNrZWRcbiAgICA/IE1hdGgubWF4KDAsIC4uLihtYWduaXR1ZGVzWzBdID8/IFtdKS5tYXAoKF8sIGluZGV4KSA9PiBtYWduaXR1ZGVzXG4gICAgICAucmVkdWNlKChzdW0sIHZhbHVlcykgPT4gc3VtICsgKHZhbHVlc1tpbmRleF0gPz8gMCksIDApKSlcbiAgICA6IE1hdGgubWF4KDAsIC4uLm1hZ25pdHVkZXMuZmxhdCgpKTtcblxuICByZXR1cm4gcGVhayA+PSBBWElTX1NFUEFSQVRPUl9USFJFU0hPTEQgPyAnIywjIzAnIDogJ0dlbmVyYWwnO1xufVxuXG5cbi8vIFRoZSB6b25lIGV2ZXJ5IGRhdGUgaW4gYSByZXBvcnQgaXMgcmVhZCBpbi4gVGhlIHNlcnZlciByZXNvbHZlcyBpdCAodGhlXG4vLyByZXBvcnQncyBvd24gem9uZSwgZWxzZSB0aGUgYXBwbGljYXRpb24ncyBkZWZhdWx0IHJlcG9ydGluZyB6b25lKSBhbmQgc2VuZHNcbi8vIGl0IGFzIGBlZmZlY3RpdmVUaW1lem9uZWAuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCB0aGUgZmllbGQgc3RpbGwgdXNlZCBhXG4vLyByZXBvcnQncyBwaW5uZWQgYHRpbWV6b25lYCwgc28gdGhhdCBjb21lcyBuZXh0OyB0aGUgYnJvd3NlcidzIHpvbmUgaXMgdGhlIGxhc3Rcbi8vIGZhbGxiYWNrLiBUaGlzIGlzIHRoZSBvbmUgcGxhY2UgdGhhdCBjaGFpbiBsaXZlcywgc28gZXZlcnkgZGF0ZSB0aGUgdmlld2VyXG4vLyByZW5kZXJzIG9yIHJlc29sdmVzIGFncmVlcyB3aXRoIGV2ZXJ5IG90aGVyLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZXBvcnRUaW1lem9uZShyZXBvcnQ6IFBpY2s8UmVwb3J0LCAnZWZmZWN0aXZlVGltZXpvbmUnIHwgJ3RpbWV6b25lJz4pOiBzdHJpbmcge1xuICByZXR1cm4gcmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lID8/IHJlcG9ydC50aW1lem9uZSA/PyBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG59XG5cblxuY29uc3QgREFURV9PTkxZX1BBVFRFUk4gPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9JC87XG5jb25zdCBEQVRFX1RJTUVfUEFUVEVSTiA9IC9eKFxcZHs0fS1cXGR7Mn0tXFxkezJ9KVsgVF0oXFxkezJ9OlxcZHsyfTpcXGR7Mn0pKFxcLlxcZCspPyQvO1xuXG4vLyBBIHJlcG9ydCByb3cncyBkYXRlIGNlbGwgYXMgYSBjYWxlbmRhciBkYXkgaW4gdGhlIHJlcG9ydCdzIHpvbmUuXG4vL1xuLy8gUmVwb3J0IHJvd3MgYXJlIHJhdyBkYXRhYmFzZSBzdHJpbmdzLCBub3Qgc2VyaWFsaXplZCBtb2RlbHMsIHNvIHRoZWlyIHNoYXBlXG4vLyBpcyB0aGUgd2lyZSBjb250cmFjdDogYSBEQVRFIGNvbHVtbiBhcnJpdmVzIGFzICdZWVlZLU1NLUREJyBhbmQgYVxuLy8gZGF0ZS1hbmQtdGltZSBjb2x1bW4gYXMgJ1lZWVktTU0tREQgSEg6TU06U1MnIGluIFVUQy4gUmVhZGluZyB0aGF0IHNoYXBlXG4vLyBoZXJlIGRvZXMgbm90IHJlLWRlcml2ZSBhIHNlcnZlciBydWxlOyBpdCBvbmx5IHN0b3BzIHRoZSBicm93c2VyIGd1ZXNzaW5nLlxuLy8gLSBBIGNhbGVuZGFyIGRheSBpcyBuZXZlciBzaGlmdGVkOiBwYXJzZUlTTyByZWFkcyBpdCBhcyBsb2NhbCBtaWRuaWdodCwgc29cbi8vICAgdGhlIGRheSBwcmludGVkIGlzIHRoZSBkYXkgc3RvcmVkLCB3aGF0ZXZlciB0aGUgem9uZS5cbi8vIC0gQW4gaW5zdGFudCBpcyBwaW5uZWQgdG8gVVRDIHdpdGggYW4gZXhwbGljaXQgJ1onLCB0aGVuIHNob3duIGFzIHRoZSBkYXkgaXRcbi8vICAgZmVsbCBvbiBpbiB0aGUgcmVwb3J0J3Mgem9uZSwgdGhlIHNhbWUgZGF5IHRoZSBmaWx0ZXJzIGFuZCB0aW1lIGJ1Y2tldHMgdXNlLlxuLy8gLSBBbnl0aGluZyBlbHNlIGlzIHNob3duIGFzIGl0IGNhbWUsIGFuZCBzbyBpcyBhIHZhbHVlIHRoYXQgaGFzIHRoZSBzaGFwZVxuLy8gICBidXQgbmFtZXMgbm8gcmVhbCBkYXkgKGEgemVybyBkYXRlICcwMDAwLTAwLTAwJywgb3IgJzIwMjYtMDItMzAnKTogb25lXG4vLyAgIGJhZCBjZWxsIG11c3Qgbm90IHRocm93IG91dCBvZiBhIHBpcGUgb3IgYWJvcnQgYW4gZXhwb3J0LlxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJlcG9ydERhdGUodmFsdWU6IHVua25vd24sIHRpbWV6b25lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBjb25zdCB0ZXh0ID0gU3RyaW5nKHZhbHVlKTtcblxuICBpZiAoREFURV9PTkxZX1BBVFRFUk4udGVzdCh0ZXh0KSkge1xuICAgIGNvbnN0IGRheSA9IHBhcnNlSVNPKHRleHQpO1xuXG4gICAgcmV0dXJuIGlzVmFsaWQoZGF5KSA/IGZvcm1hdChkYXksICdNTU0gZCwgeXl5eScpIDogdGV4dDtcbiAgfVxuXG4gIGNvbnN0IGRhdGVUaW1lID0gREFURV9USU1FX1BBVFRFUk4uZXhlYyh0ZXh0KTtcbiAgaWYgKCFkYXRlVGltZSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgY29uc3QgaW5zdGFudCA9IHBhcnNlSVNPKGAke2RhdGVUaW1lWzFdfVQke2RhdGVUaW1lWzJdfVpgKTtcbiAgaWYgKCFpc1ZhbGlkKGluc3RhbnQpKSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cblxuICAvLyBBbiB1bmtub3duIHpvbmUgbWFrZXMgZGF0ZS1mbnMtdHogdGhyb3c7IFVUQyBzdGlsbCBuYW1lcyBhIHJlYWwgZGF5LlxuICB0cnkge1xuICAgIHJldHVybiBmb3JtYXRJblRpbWVab25lKGluc3RhbnQsIHRpbWV6b25lLCAnTU1NIGQsIHl5eXknKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZvcm1hdEluVGltZVpvbmUoaW5zdGFudCwgJ1VUQycsICdNTU0gZCwgeXl5eScpO1xuICB9XG59XG5cblxuLy8gQSBzaG9ydCwgaHVtYW4gbGFiZWwgZm9yIGEgem9uZTogaXRzIGNpdHkgcGx1cyB0aGUgY3VycmVudCBhYmJyZXZpYXRpb24sXG4vLyBlLmcuICdBbWVyaWNhL05ld19Zb3JrJyByZWFkcyAnTmV3IFlvcmsgKEVEVCknLiBVVEMgc3RheXMgJ1VUQycsIGFuZCBhblxuLy8gdW5rbm93biB6b25lIGlzIHNob3duIGFzIGl0cyBpZC4gQW4gJ0V0Yy8nIHpvbmUgbmFtZXMgbm8gY2l0eSwgYW5kIGl0cyBQT1NJWFxuLy8gc2lnbiBpcyB0aGUgcmV2ZXJzZSBvZiB0aGUgb2Zmc2V0ICgnRXRjL0dNVCs1JyBpcyBHTVQtNSksIHNvIGl0IHJlYWRzIGFzIHRoZVxuLy8gYWJicmV2aWF0aW9uIGFsb25lOiAnRXRjL1VUQycgaXMgJ1VUQycsICdFdGMvR01UKzUnIGlzICdHTVQtNScuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGltZXpvbmVMYWJlbCh0aW1lem9uZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHRpbWV6b25lID09PSAnVVRDJykge1xuICAgIHJldHVybiB0aW1lem9uZTtcbiAgfVxuXG4gIGNvbnN0IHNlZ21lbnRzID0gdGltZXpvbmUuc3BsaXQoJy8nKTtcblxuICB0cnkge1xuICAgIGNvbnN0IGFiYnJldmlhdGlvbiA9IGZvcm1hdEluVGltZVpvbmUobmV3IERhdGUoKSwgdGltZXpvbmUsICd6enonKTtcblxuICAgIHJldHVybiBzZWdtZW50c1swXSA9PT0gJ0V0YydcbiAgICAgID8gYWJicmV2aWF0aW9uXG4gICAgICA6IGAke3NlZ21lbnRzW3NlZ21lbnRzLmxlbmd0aCAtIDFdLnJlcGxhY2UoL18vZywgJyAnKX0gKCR7YWJicmV2aWF0aW9ufSlgO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdGltZXpvbmU7XG4gIH1cbn1cblxuXG4vLyBcIk5vd1wiIGFzIGEgRGF0ZSB3aG9zZSBsb2NhbCBmaWVsZHMgcmVhZCB0aGUgd2FsbCBjbG9jayBpbiB0aGUgZ2l2ZW4gem9uZSwgc29cbi8vIGRhdGUtZm5zIGNhbGVuZGFyIGFyaXRobWV0aWMgKHN0YXJ0T2ZXZWVrLCBzdGFydE9mTW9udGgsIC4uLikgYW5kXG4vLyBkYXRlQm91bmRTdHJpbmcoKSBsYW5kIG9uIHRoZSB6b25lJ3MgY2FsZW5kYXIgZGF5IHJhdGhlciB0aGFuIHRoZSBicm93c2VyJ3MuXG4vLyBBbiB1bmtub3duIHpvbmUgZmFsbHMgYmFjayB0byB0aGUgYnJvd3NlcidzIGNsb2NrLlxuZXhwb3J0IGZ1bmN0aW9uIGdldFpvbmVkTm93KHRpbWV6b25lOiBzdHJpbmcpOiBEYXRlIHtcbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHpvbmVkID0gdG9ab25lZFRpbWUobm93LCB0aW1lem9uZSk7XG5cbiAgICByZXR1cm4gTnVtYmVyLmlzTmFOKHpvbmVkLmdldFRpbWUoKSkgPyBub3cgOiB6b25lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG5vdztcbiAgfVxufVxuIl19
|
|
596
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2Zvcm1hdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTVELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBV3JFLDZFQUE2RTtBQUM3RSw4RUFBOEU7QUFDOUUsa0ZBQWtGO0FBQ2xGLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFvQixPQUFPLENBQUM7QUFDL0QsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQXVCLEtBQUssQ0FBQztBQUVsRSxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBa0MsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUNqRixNQUFNLEVBQUUsc0JBQXNCO0lBQzlCLFFBQVEsRUFBRSx3QkFBd0I7SUFDbEMsWUFBWSxFQUFFLElBQUk7Q0FDbkIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxnQkFBZ0IsR0FBRyxZQUFZLENBQUM7QUFHdEMsOEVBQThFO0FBQzlFLDZFQUE2RTtBQUM3RSxzREFBc0Q7QUFDdEQsTUFBTSxVQUFVLG1CQUFtQixDQUFDLEdBQThCO0lBQ2hFLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNULE9BQU8sc0JBQXNCLENBQUM7SUFDaEMsQ0FBQztJQUVELElBQUksQ0FBQztRQUNILE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksc0JBQXNCLENBQUM7SUFDbEYsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sc0JBQXNCLENBQUM7SUFDaEMsQ0FBQztBQUNILENBQUM7QUFFRCwyRUFBMkU7QUFDM0UsOEVBQThFO0FBQzlFLDBFQUEwRTtBQUMxRSw4RUFBOEU7QUFDOUUsd0RBQXdEO0FBQ3hELE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxJQUErQjtJQUNuRSxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDMUMsT0FBTyx3QkFBd0IsQ0FBQztJQUNsQyxDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsWUFBWSxDQUFDLHNCQUFzQixFQUFFLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUU1RSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLHdCQUF3QixDQUFDO0lBQ2xDLENBQUM7QUFDSCxDQUFDO0FBRUQsMkVBQTJFO0FBQzNFLDhFQUE4RTtBQUM5RSx5REFBeUQ7QUFDekQsTUFBTSxVQUFVLG9CQUFvQixDQUNsQyxNQUErRTtJQUUvRSxPQUFPO1FBQ0wsTUFBTSxFQUFFLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUM7UUFDbkQsUUFBUSxFQUFFLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUN6RCxZQUFZLEVBQUUsTUFBTSxDQUFDLGFBQWEsS0FBSyxPQUFPO0tBQy9DLENBQUM7QUFDSixDQUFDO0FBR0QsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSx5QkFBeUI7QUFDekIsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQTZCLENBQUM7QUFDNUQsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQStCLENBQUM7QUFFNUQsTUFBTSxVQUFVLFlBQVksQ0FBQyxNQUFjLEVBQUUsT0FBaUM7SUFDNUUsTUFBTSxHQUFHLEdBQUcsR0FBRyxNQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO0lBQ25ELElBQUksU0FBUyxHQUFHLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFeEMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2YsU0FBUyxHQUFHLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbkQsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsK0RBQStEO0FBQy9ELE1BQU0sVUFBVSxVQUFVLENBQ3hCLE1BQWMsRUFDZCxPQUFtQyxFQUNuQyxRQUFpQjtJQUVqQixNQUFNLEdBQUcsR0FBRyxHQUFHLE1BQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLFFBQVEsSUFBSSxFQUFFLEVBQUUsQ0FBQztJQUNyRSxJQUFJLFNBQVMsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRXRDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNmLFNBQVMsR0FBRyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLEVBQUUsR0FBRyxPQUFPLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUN0RSxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUdELHVFQUF1RTtBQUN2RSwyRUFBMkU7QUFDM0UsK0VBQStFO0FBQy9FLDhDQUE4QztBQUM5QywrRUFBK0U7QUFDL0UsMkNBQTJDO0FBQzNDLDhFQUE4RTtBQUM5RSw0RUFBNEU7QUFDNUUsNERBQTREO0FBQzVELHlFQUF5RTtBQUN6RSwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsaUJBQWlCO0FBQ2pCLDZFQUE2RTtBQUM3RSx5RUFBeUU7QUFDekUsNkVBQTZFO0FBQzdFLGtCQUFrQjtBQUNsQiwyRUFBMkU7QUFDM0UsOEVBQThFO0FBQzlFLDZEQUE2RDtBQUM3RCw4RUFBOEU7QUFDOUUsZ0NBQWdDO0FBQ2hDLDJFQUEyRTtBQUMzRSwyQ0FBMkM7QUFFM0MsaUVBQWlFO0FBQ2pFLE1BQU0sYUFBYSxHQUFHLENBQUMsQ0FBQztBQUN4QiwwRUFBMEU7QUFDMUUsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLENBQUM7QUFDM0IsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBQzFCLGdFQUFnRTtBQUNoRSxNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1QixxRUFBcUU7QUFDckUsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLENBQUM7QUFDakMsK0RBQStEO0FBQy9ELE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQztBQUN4Qix5RUFBeUU7QUFDekUsTUFBTSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBRXJCLE1BQU0sZUFBZSxHQUFHLCtDQUErQyxDQUFDO0FBQ3hFLHVFQUF1RTtBQUN2RSxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBNkIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0FBQ3RHLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxDQUE2QixDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0FBWWpGLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxDQUEyQjtJQUNwRCxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDekUsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDO0NBQzFFLENBQUMsQ0FBQztBQW1CSCwwRUFBMEU7QUFDMUUsUUFBUTtBQUNSLE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBYztJQUMzQyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlCLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDL0MsQ0FBQztJQUVELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzlELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUU5QixPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0FBQ25ELENBQUM7QUFFRCw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLGdEQUFnRDtBQUNoRCxNQUFNLFVBQVUsZUFBZSxDQUFDLElBQThCO0lBQzVELElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxzQkFBc0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6RCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJO1dBQzVCLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJO1dBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzNFLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsNEVBQTRFO0FBQzVFLG1EQUFtRDtBQUNuRCxNQUFNLFVBQVUsWUFBWSxDQUMxQixLQUEyQyxFQUMzQyxTQUFpQixFQUNqQixRQUFnQjtJQUVoQixRQUFRLEtBQUssRUFBRSxDQUFDO1FBQ2QsS0FBSyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7UUFDakMsS0FBSyxpQkFBaUIsQ0FBQyxRQUFRO1lBQzdCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsS0FBSyxpQkFBaUIsQ0FBQyxJQUFJO1lBQ3pCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDbEQ7WUFDRSxPQUFPLGlCQUFpQixDQUFDLElBQUksQ0FBQztJQUNsQyxDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsU0FBUyxDQUFDLFNBQWlCLEVBQUUsUUFBZ0I7SUFDcEQsSUFBSSxTQUFTLElBQUksR0FBRyxFQUFFLENBQUM7UUFDckIsT0FBTyxpQkFBaUIsQ0FBQyxRQUFRLENBQUM7SUFDcEMsQ0FBQztJQUVELElBQUksU0FBUyxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLE9BQU8saUJBQWlCLENBQUMsSUFBSSxDQUFDO0lBQ2hDLENBQUM7SUFFRCxPQUFPLE9BQU8sQ0FBQyxTQUFTLEdBQUcsR0FBRyxFQUFFLFFBQVEsQ0FBQyxJQUFJLElBQUk7UUFDL0MsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLFFBQVE7UUFDNUIsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLFNBQVMsQ0FBQztBQUNsQyxDQUFDO0FBRUQsMkVBQTJFO0FBQzNFLHlDQUF5QztBQUN6QyxTQUFTLE9BQU8sQ0FBQyxLQUFhLEVBQUUsUUFBZ0I7SUFDOUMsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU1QyxxRUFBcUU7SUFDckUsT0FBTyxNQUFNLENBQUMsWUFBWSxDQUFDLHNCQUFzQixFQUFFO1FBQ2pELFdBQVcsRUFBRSxLQUFLO1FBQ2xCLHFCQUFxQixFQUFFLENBQUM7UUFDeEIscUJBQXFCLEVBQUUsTUFBTTtLQUM5QixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDcEIsQ0FBQztBQUVELHlDQUF5QztBQUN6QyxNQUFNLFVBQVUsWUFBWSxDQUMxQixLQUFjLEVBQ2QsSUFBeUMsRUFDekMsT0FBNEIsRUFDNUIsVUFBK0IsRUFBRTtJQUVqQyxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3hCLE9BQU8sT0FBTyxDQUFDLEtBQUssSUFBSSxXQUFXLENBQUM7SUFDdEMsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QyxJQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNyQixPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sU0FBUyxHQUFHLGFBQWEsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDakQsTUFBTSxLQUFLLEdBQUcsS0FBSyxLQUFLLGlCQUFpQixDQUFDLE9BQU87UUFDL0MsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLElBQUk7UUFDeEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksWUFBWSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsSUFBSSxlQUFlLENBQUMsQ0FBQztJQUN0RixNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksU0FBUyxDQUFDO0lBQzlELE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNoRyxNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsU0FBUyxFQUFFLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBRTFHLE9BQU8sS0FBSyxLQUFLLGlCQUFpQixDQUFDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUMxRixDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsS0FBYztJQUNsQyxPQUFPLEtBQUssS0FBSyxJQUFJO1dBQ2hCLEtBQUssS0FBSyxTQUFTO1dBQ25CLEtBQUssS0FBSyxFQUFFO1dBQ1osS0FBSyxLQUFLLEdBQUc7V0FDYixDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUM5RCxDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLFNBQVMsV0FBVyxDQUFDLElBQXlDO0lBQzVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUM7QUFDNUYsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLElBQXlDO0lBQzdELE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLGlCQUFpQixDQUFDLE1BQU0sQ0FBQztBQUN2RCxDQUFDO0FBRUQsOEVBQThFO0FBQzlFLHdEQUF3RDtBQUN4RCxTQUFTLGFBQWEsQ0FBQyxRQUFtQztJQUN4RCxPQUFPLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUM5RCxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQzVELENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDWCxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQ25CLEtBQXdCLEVBQ3hCLE9BQTRCLEVBQzVCLFFBQXVCLEVBQ3ZCLE1BQWU7SUFFZixNQUFNLGNBQWMsR0FBRyxvQkFBb0IsQ0FBQyxRQUFRLEVBQUUsZUFBZSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBRXRGLFFBQVEsS0FBSyxFQUFFLENBQUM7UUFDZCxLQUFLLGlCQUFpQixDQUFDLFFBQVE7WUFDN0IsT0FBTyxFQUFFLEdBQUcsZUFBZSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxHQUFHLGNBQWMsRUFBRSxDQUFDO1FBQ3JFLEtBQUssaUJBQWlCLENBQUMsT0FBTztZQUM1QixPQUFPLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUM7UUFDekY7WUFDRSxPQUFPLGNBQWMsQ0FBQztJQUMxQixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLFFBQTRCO0lBQ25ELE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLENBQUM7QUFDcEUsQ0FBQztBQUVELDZFQUE2RTtBQUM3RSxlQUFlO0FBQ2YsU0FBUyxlQUFlLENBQUMsS0FBd0IsRUFBRSxNQUFlO0lBQ2hFLElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDO0lBRUQsUUFBUSxLQUFLLEVBQUUsQ0FBQztRQUNkLEtBQUssaUJBQWlCLENBQUMsT0FBTztZQUM1QixPQUFPLGdCQUFnQixDQUFDO1FBQzFCLEtBQUssaUJBQWlCLENBQUMsUUFBUTtZQUM3QixPQUFPLGlCQUFpQixDQUFDO1FBQzNCO1lBQ0UsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztBQUNILENBQUM7QUFFRCw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLFNBQVMsb0JBQW9CLENBQUMsTUFBcUIsRUFBRSxPQUFzQjtJQUN6RSxJQUFJLE1BQU0sS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNwQixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxFQUFFLHFCQUFxQixFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQzFFLENBQUM7SUFFRCxPQUFPLE9BQU8sS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxxQkFBcUIsRUFBRSxDQUFDLEVBQUUscUJBQXFCLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFDOUYsQ0FBQztBQUVELDBFQUEwRTtBQUMxRSwwRUFBMEU7QUFDMUUsU0FBUyxXQUFXLENBQUMsU0FBNEIsRUFBRSxLQUFhLEVBQUUsTUFBZTtJQUMvRSxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMxQixPQUFPLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFN0MsSUFBSSxLQUFLLEdBQUcsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3BELE9BQU8sV0FBVyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNaLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVuRyxPQUFPO1FBQ0wsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3JELE1BQU07UUFDTixHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztLQUNuRCxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNiLENBQUM7QUFFRCx3RUFBd0U7QUFDeEUseUJBQXlCO0FBQ3pCLFNBQVMsZUFBZSxDQUFDLFNBQTRCLEVBQUUsS0FBOEI7SUFDbkYsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDLEVBQUUsS0FBSyxJQUFJLEdBQUcsQ0FBQztJQUU5RixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztXQUNqRCxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3ZFLENBQUM7QUFHRCw4RUFBOEU7QUFDOUUsNEVBQTRFO0FBQzVFLDZFQUE2RTtBQUM3RSwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxRQUF3QjtJQUN2RCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUVqRSxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDbEYsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFFdkUsT0FBTyxTQUFTLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDeEQsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQUMsSUFBc0I7SUFDOUMsT0FBTztRQUNMLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDN0QsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN0RSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQzNELENBQUM7QUFDSixDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLDZFQUE2RTtBQUM3RSw2RUFBNkU7QUFDN0UsNkVBQTZFO0FBQzdFLE1BQU0sVUFBVSx3QkFBd0IsQ0FDdEMsSUFBc0IsRUFDdEIsSUFBWSxFQUNaLE9BQTRCO0lBRTVCLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxNQUFNLFNBQVMsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hELE1BQU0sS0FBSyxHQUFHLEtBQUssS0FBSyxpQkFBaUIsQ0FBQyxPQUFPO1FBQy9DLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJO1FBQ3hCLENBQUMsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsU0FBUyxJQUFJLGVBQWUsQ0FBQyxDQUFDO0lBRWpFLE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFNBQVMsSUFBSSxZQUFZLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQztBQUNyRixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLDRFQUE0RTtBQUM1RSx3RUFBd0U7QUFDeEUsb0NBQW9DO0FBQ3BDLFNBQVMsWUFBWSxDQUNuQixLQUF3QixFQUN4QixLQUFvQixFQUNwQixJQUFZLEVBQ1osT0FBNEI7SUFFNUIsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVyQyxJQUFJLEtBQUssS0FBSyxpQkFBaUIsQ0FBQyxNQUFNLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNqRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxLQUFLLEtBQUssaUJBQWlCLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxZQUFZO1FBQzNFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUc7UUFDdEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzNDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxTQUFTLEdBQUcsVUFBVSxDQUFDLENBQUM7SUFDOUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVsRixPQUFPLEtBQUssS0FBSyxpQkFBaUIsQ0FBQyxRQUFRLElBQUksUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztBQUM1RyxDQUFDO0FBRUQsOEVBQThFO0FBQzlFLDRCQUE0QjtBQUM1QixTQUFTLFFBQVEsQ0FBQyxLQUFhO0lBQzdCLElBQUksQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM1QyxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMvQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBRyxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQy9CLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNkLElBQUksUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ25CLElBQUksR0FBRyxDQUFDLENBQUM7SUFDWCxDQUFDO1NBQU0sSUFBSSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFDMUIsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNYLENBQUM7U0FBTSxJQUFJLFFBQVEsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN4QixJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ1gsQ0FBQztTQUFNLElBQUksUUFBUSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3hCLElBQUksR0FBRyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRUQsT0FBTyxJQUFJLEdBQUcsS0FBSyxDQUFDO0FBQ3RCLENBQUM7QUFFRCwyRUFBMkU7QUFDM0UsK0RBQStEO0FBQy9ELDBFQUEwRTtBQUMxRSw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLDRCQUE0QjtBQUM1QixNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLElBQXNCLEVBQ3RCLE9BQTRCLEVBQzVCLEtBQXdCLEVBQ3hCLE1BQTJCLEVBQzNCLE9BQWdCO0lBRWhCLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxNQUFNLEtBQUssR0FBRyxLQUFLLEtBQUssaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTdGLElBQUksS0FBSyxLQUFLLGlCQUFpQixDQUFDLE1BQU0sSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsUUFBUSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQzVFLE9BQU8sbUJBQW1CLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQztJQUNyQyxNQUFNLE1BQU0sR0FBRyxRQUFRLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUV4RSxJQUFJLEtBQUssS0FBSyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN4QyxPQUFPLEdBQUcsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDMUQsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLEdBQUcsTUFBTSxHQUFHLEtBQUssRUFBRSxNQUFNLElBQUksRUFBRSxFQUFFLENBQUM7SUFDakQsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFFakMsSUFBSSxLQUFLLEtBQUssaUJBQWlCLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDOUMsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUV2QyxPQUFPLE1BQU0sQ0FBQyxNQUFNO1FBQ2xCLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3ZELENBQUMsQ0FBQyxHQUFHLE1BQU0sSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDO0FBQ3pDLENBQUM7QUFVRCxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUEwQixDQUFDO0FBRTNELFNBQVMsY0FBYyxDQUFDLE9BQTRCO0lBQ2xELE1BQU0sR0FBRyxHQUFHLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEQsSUFBSSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRXZDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNaLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLGVBQWUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDL0YsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQztRQUNyRSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkcsTUFBTSxNQUFNLEdBQUcsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUNoQyxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUM7YUFDdEYsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO2FBQ3pCLElBQUksQ0FBQyxFQUFFLENBQUM7YUFDUixPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRXJCLE1BQU0sR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUMxQixnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBR0QsNkVBQTZFO0FBQzdFLDZFQUE2RTtBQUM3RSw4RUFBOEU7QUFDOUUsMkVBQTJFO0FBQzNFLDRFQUE0RTtBQUM1RSw2RUFBNkU7QUFDN0UsbUJBQW1CO0FBQ25CLE1BQU0sWUFBWSxHQUE2QixFQUFFLHFCQUFxQixFQUFFLEVBQUUsRUFBRSxDQUFDO0FBRTdFLE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxLQUFjLEVBQUUsTUFBdUI7SUFDdkUsTUFBTSxPQUFPLEdBQUcsT0FBTyxLQUFLLEtBQUssUUFBUTtRQUN2QyxDQUFDLENBQUMsS0FBSztRQUNQLENBQUMsQ0FBQyxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFFM0UsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDMUIsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0lBQ2pELENBQUM7SUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQzlCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pCLENBQUM7SUFFRCxPQUFPLFlBQVksQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDaEYsQ0FBQztBQUdELHFFQUFxRTtBQUNyRSw2RUFBNkU7QUFDN0UsbUVBQW1FO0FBQ25FLE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLElBQUksQ0FBQztBQUU3QyxnRkFBZ0Y7QUFDaEYsOEVBQThFO0FBQzlFLDhFQUE4RTtBQUM5RSwwRUFBMEU7QUFDMUUsa0VBQWtFO0FBQ2xFLEVBQUU7QUFDRixnQ0FBZ0M7QUFDaEMsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE1BQTJCLEVBQUUsT0FBZ0I7SUFDL0UsT0FBTyxjQUFjLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxJQUFJLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUMzRixDQUFDO0FBRUQsMkVBQTJFO0FBQzNFLDZFQUE2RTtBQUM3RSxpREFBaUQ7QUFDakQsTUFBTSxVQUFVLGNBQWMsQ0FBQyxNQUEyQixFQUFFLE9BQWdCO0lBQzFFLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV2RixPQUFPLE9BQU87UUFDWixDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxVQUFVO2FBQ2hFLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNELENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFHRCwwRUFBMEU7QUFDMUUsOEVBQThFO0FBQzlFLDZFQUE2RTtBQUM3RSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLCtDQUErQztBQUMvQyxNQUFNLFVBQVUscUJBQXFCLENBQUMsTUFBc0Q7SUFDMUYsT0FBTyxNQUFNLENBQUMsaUJBQWlCLElBQUksTUFBTSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUMsUUFBUSxDQUFDO0FBQ3pHLENBQUM7QUFHRCxnRUFBZ0U7QUFDaEUsK0RBQStEO0FBQy9ELE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBK0IsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQ3pHLHFFQUFxRTtBQUNyRSxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQStCLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUN2RywyRUFBMkU7QUFDM0UsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUErQixFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUN4RSwyRUFBMkU7QUFDM0UsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUErQixFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ3pGLHVEQUF1RDtBQUN2RCxNQUFNLENBQUMsTUFBTSxTQUFTLEdBQStCLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLENBQUM7QUFFeEYsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSw4RUFBOEU7QUFDOUUseUVBQXlFO0FBQ3pFLHVFQUF1RTtBQUN2RSxNQUFNLFVBQVUsZUFBZSxDQUM3QixJQUFVLEVBQ1YsTUFBdUIsRUFDdkIsT0FBbUMsRUFDbkMsUUFBaUI7SUFFakIsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDakMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsT0FBTyxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sa0JBQWtCLENBQUMsSUFBSSxFQUFFLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNsRixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQ3pCLElBQVUsRUFDVixNQUF1QixFQUN2QixPQUFtQyxFQUNuQyxRQUFpQjtJQUVqQixJQUFJLENBQUM7UUFDSCxPQUFPLFNBQVMsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDN0QsQ0FBQztBQUNILENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsNkVBQTZFO0FBQzdFLGtFQUFrRTtBQUNsRSxTQUFTLFNBQVMsQ0FBQyxTQUE4QixFQUFFLElBQVU7SUFDM0QsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLEdBQUcsSUFBSSxFQUFFLENBQUM7UUFDakMsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRCxPQUFPLFNBQVMsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDO1NBQ2pDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztTQUM5RSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDZCxDQUFDO0FBR0QsTUFBTSxpQkFBaUIsR0FBRyxxQkFBcUIsQ0FBQztBQUNoRCxNQUFNLGlCQUFpQixHQUFHLHNEQUFzRCxDQUFDO0FBRWpGLG1FQUFtRTtBQUNuRSxFQUFFO0FBQ0YsOEVBQThFO0FBQzlFLG9FQUFvRTtBQUNwRSwyRUFBMkU7QUFDM0UsNkVBQTZFO0FBQzdFLDZFQUE2RTtBQUM3RSwwREFBMEQ7QUFDMUQsK0VBQStFO0FBQy9FLGlGQUFpRjtBQUNqRiw0RUFBNEU7QUFDNUUsMkVBQTJFO0FBQzNFLDhEQUE4RDtBQUM5RCw4RUFBOEU7QUFDOUUsa0JBQWtCO0FBQ2xCLE1BQU0sVUFBVSxnQkFBZ0IsQ0FDOUIsS0FBYyxFQUNkLFFBQWdCLEVBQ2hCLE1BQXVCO0lBRXZCLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUMxRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFM0IsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNqQyxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFM0IsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDdkUsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDZCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUUzRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDekYsQ0FBQztBQUdELDJFQUEyRTtBQUMzRSxzRUFBc0U7QUFDdEUsMEVBQTBFO0FBQzFFLHdCQUF3QjtBQUN4QixNQUFNLFVBQVUsVUFBVSxDQUFDLEdBQW9CO0lBQzdDLE9BQU8sV0FBVyxDQUFDLFVBQVUsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUN0QyxDQUFDO0FBRUQsTUFBTSxVQUFVLFlBQVksQ0FBQyxJQUF3QjtJQUNuRCxPQUFPLFdBQVcsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDdkMsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLElBQTZCLEVBQUUsSUFBWTtJQUM5RCxJQUFJLENBQUM7UUFDSCxPQUFPLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDO0lBQ2xFLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDO0FBR0QsMkVBQTJFO0FBQzNFLDBFQUEwRTtBQUMxRSwrRUFBK0U7QUFDL0UsK0VBQStFO0FBQy9FLGtFQUFrRTtBQUNsRSxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsUUFBZ0I7SUFDL0MsSUFBSSxRQUFRLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDdkIsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFckMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxJQUFJLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbkUsT0FBTyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSztZQUMxQixDQUFDLENBQUMsWUFBWTtZQUNkLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEtBQUssWUFBWSxHQUFHLENBQUM7SUFDOUUsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7QUFDSCxDQUFDO0FBR0QsK0VBQStFO0FBQy9FLG9FQUFvRTtBQUNwRSwrRUFBK0U7QUFDL0UscURBQXFEO0FBQ3JELE1BQU0sVUFBVSxXQUFXLENBQUMsUUFBZ0I7SUFDMUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUV2QixJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBRXpDLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7SUFDckQsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1ZhbGlkLCBwYXJzZUlTTyB9IGZyb20gJ2RhdGUtZm5zJztcbmltcG9ydCB7IGZvcm1hdEluVGltZVpvbmUsIHRvWm9uZWRUaW1lIH0gZnJvbSAnZGF0ZS1mbnMtdHonO1xuXG5pbXBvcnQgeyBSZXBvcnRMaXN0Q29sdW1uRm9ybWF0IH0gZnJvbSAnLi9lbnVtcy9yZXBvcnQtbGlzdC1jb2x1bW4tZm9ybWF0LmVudW0nO1xuaW1wb3J0IHsgUmVwb3J0TnVtYmVyVW5pdHMgfSBmcm9tICcuL2VudW1zL3JlcG9ydC1udW1iZXItdW5pdHMuZW51bSc7XG5pbXBvcnQgeyBSZXBvcnRWYWx1ZUZvcm1hdCB9IGZyb20gJy4vZW51bXMvcmVwb3J0LXZhbHVlLWZvcm1hdC5lbnVtJztcbmltcG9ydCB7XG4gIENoYXJ0TWVhc3VyZSxcbiAgTnVtYmVyRm9ybWF0U3BlYyxcbiAgUmVwb3J0LFxuICBSZXBvcnRDdXJyZW5jeUNvZGUsXG4gIFJlcG9ydEZvcm1hdENvbnRleHQsXG4gIFJlcG9ydExvY2FsZVRhZyxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuXG5cbi8vIFdoYXQgYSByZXBvcnQgcmVhZHMgd2hlbiB0aGUgc2VydmVyIG5hbWVzIG5vIHVzYWJsZSBsb2NhbGUgb3IgY3VycmVuY3k6IGFuXG4vLyBvbGRlciBzZXJ2ZXIgdGhhdCBzZW5kcyBuZWl0aGVyLCBvciBhIHZhbHVlIHRoaXMgYnJvd3NlcidzIEludGwgY2Fubm90IHVzZS5cbi8vIE5ldmVyIHRoZSBicm93c2VyJ3Mgb3duIGxvY2FsZSwgc28gZXZlcnkgdmlld2VyIG9mIGEgcmVwb3J0IHNlZXMgdGhlIHNhbWUgdGV4dC5cbmV4cG9ydCBjb25zdCBSRVBPUlRfRkFMTEJBQ0tfTE9DQUxFOiBSZXBvcnRMb2NhbGVUYWcgPSAnZW4tVVMnO1xuZXhwb3J0IGNvbnN0IFJFUE9SVF9GQUxMQkFDS19DVVJSRU5DWTogUmVwb3J0Q3VycmVuY3lDb2RlID0gJ1VTRCc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0ZPUk1BVF9DT05URVhUOiBSZWFkb25seTxSZXBvcnRGb3JtYXRDb250ZXh0PiA9IE9iamVjdC5mcmVlemUoe1xuICBsb2NhbGU6IFJFUE9SVF9GQUxMQkFDS19MT0NBTEUsXG4gIGN1cnJlbmN5OiBSRVBPUlRfRkFMTEJBQ0tfQ1VSUkVOQ1ksXG4gIHJhdGlvUGVyY2VudDogdHJ1ZSxcbn0pO1xuXG5jb25zdCBDVVJSRU5DWV9QQVRURVJOID0gL15bQS1aXXszfSQvO1xuXG5cbi8vIFRoZSBzZXJ2ZXIncyByZXNvbHZlZCBsb2NhbGUgYXMgb25lIHRoaXMgYnJvd3NlciBjYW4gZm9ybWF0IGluLiBBIG1hbGZvcm1lZFxuLy8gdGFnICgnZW5fQ0EnKSBtYWtlcyBzdXBwb3J0ZWRMb2NhbGVzT2YgdGhyb3csIGFuZCBvbmUgSW50bCBoYXMgbm8gZGF0YSBmb3Jcbi8vICgneHgtWVknKSBjb21lcyBiYWNrIGVtcHR5OyBib3RoIHJlYWQgdGhlIGZhbGxiYWNrLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZXBvcnRMb2NhbGUodGFnOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogUmVwb3J0TG9jYWxlVGFnIHtcbiAgaWYgKCF0YWcpIHtcbiAgICByZXR1cm4gUkVQT1JUX0ZBTExCQUNLX0xPQ0FMRTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIEludGwuTnVtYmVyRm9ybWF0LnN1cHBvcnRlZExvY2FsZXNPZihbdGFnXSlbMF0gPz8gUkVQT1JUX0ZBTExCQUNLX0xPQ0FMRTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIFJFUE9SVF9GQUxMQkFDS19MT0NBTEU7XG4gIH1cbn1cblxuLy8gVGhlIHNlcnZlcidzIHJlc29sdmVkIGN1cnJlbmN5IGFzIG9uZSBJbnRsIGNhbiBsYWJlbC4gVGhlIHNlcnZlciBkZWNpZGVzXG4vLyB3aGljaCBjb2RlcyBuYW1lIG1vbmV5OyB0aGlzIG9ubHkgZ3VhcmRzIGFnYWluc3QgYSBjb2RlIEludGwgY2Fubm90IHRha2UgYXRcbi8vIGFsbC4gSXQgaXMgbmV2ZXIgY2hlY2tlZCBhZ2FpbnN0IHRoZSBydW50aW1lJ3Mgb3duIGN1cnJlbmN5IGxpc3QsIHdoaWNoXG4vLyBkaWZmZXJzIGJldHdlZW4gYnJvd3NlcnMgYW5kIGxlYXZlcyBvdXQgY29kZXMgdGhlIHNlcnZlciBvZmZlcnMgKFZFRiwgTVJPKSxcbi8vIHNvIGV2ZXJ5IHZpZXdlciBsYWJlbHMgYSByZXBvcnQncyBtb25leSB0aGUgc2FtZSB3YXkuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVJlcG9ydEN1cnJlbmN5KGNvZGU6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBSZXBvcnRDdXJyZW5jeUNvZGUge1xuICBpZiAoIWNvZGUgfHwgIUNVUlJFTkNZX1BBVFRFUk4udGVzdChjb2RlKSkge1xuICAgIHJldHVybiBSRVBPUlRfRkFMTEJBQ0tfQ1VSUkVOQ1k7XG4gIH1cblxuICB0cnkge1xuICAgIG51bWJlckZvcm1hdChSRVBPUlRfRkFMTEJBQ0tfTE9DQUxFLCB7IHN0eWxlOiAnY3VycmVuY3knLCBjdXJyZW5jeTogY29kZSB9KTtcblxuICAgIHJldHVybiBjb2RlO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gUkVQT1JUX0ZBTExCQUNLX0NVUlJFTkNZO1xuICB9XG59XG5cbi8vIFRoZSBvbmUgcGxhY2UgYSByZXBvcnQncyBmb3JtYXQgY29udGV4dCBpcyBidWlsdDogdGhlIHNlcnZlcidzIGVmZmVjdGl2ZVxuLy8gbG9jYWxlIGFuZCBjdXJyZW5jeSAoYWJzZW50IG9uIGFuIG9sZGVyIHNlcnZlciwgd2hpY2ggdGhlbiByZWFkcyBlbi1VUy9VU0QpXG4vLyBhbmQgd2hldGhlciBpdHMgcGVyY2VudCBtZWFzdXJlcyBhcnJpdmUgYXMgMC0xIHJhdGlvcy5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlRm9ybWF0Q29udGV4dChcbiAgcmVwb3J0OiBQaWNrPFJlcG9ydCwgJ2VmZmVjdGl2ZUxvY2FsZScgfCAnZWZmZWN0aXZlQ3VycmVuY3knIHwgJ3BlcmNlbnRGb3JtYXQnPixcbik6IFJlcG9ydEZvcm1hdENvbnRleHQge1xuICByZXR1cm4ge1xuICAgIGxvY2FsZTogcmVzb2x2ZVJlcG9ydExvY2FsZShyZXBvcnQuZWZmZWN0aXZlTG9jYWxlKSxcbiAgICBjdXJyZW5jeTogcmVzb2x2ZVJlcG9ydEN1cnJlbmN5KHJlcG9ydC5lZmZlY3RpdmVDdXJyZW5jeSksXG4gICAgcmF0aW9QZXJjZW50OiByZXBvcnQucGVyY2VudEZvcm1hdCA9PT0gJ3JhdGlvJyxcbiAgfTtcbn1cblxuXG4vLyBCdWlsZGluZyBhbiBJbnRsIGZvcm1hdHRlciBpcyBmYXIgc2xvd2VyIHRoYW4gdXNpbmcgb25lLCBhbmQgYSBjaGFydCBmb3JtYXRzXG4vLyBldmVyeSB0aWNrIGFuZCB0b29sdGlwIHZhbHVlLCBzbyBlYWNoIGRpc3RpbmN0IGxvY2FsZSArIG9wdGlvbnMgKCsgem9uZSkgaXNcbi8vIGJ1aWx0IG9uY2UgYW5kIHJldXNlZC5cbmNvbnN0IE5VTUJFUl9GT1JNQVRTID0gbmV3IE1hcDxzdHJpbmcsIEludGwuTnVtYmVyRm9ybWF0PigpO1xuY29uc3QgREFURV9GT1JNQVRTID0gbmV3IE1hcDxzdHJpbmcsIEludGwuRGF0ZVRpbWVGb3JtYXQ+KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJGb3JtYXQobG9jYWxlOiBzdHJpbmcsIG9wdGlvbnM6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyk6IEludGwuTnVtYmVyRm9ybWF0IHtcbiAgY29uc3Qga2V5ID0gYCR7bG9jYWxlfXwke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMpfWA7XG4gIGxldCBmb3JtYXR0ZXIgPSBOVU1CRVJfRk9STUFUUy5nZXQoa2V5KTtcblxuICBpZiAoIWZvcm1hdHRlcikge1xuICAgIGZvcm1hdHRlciA9IG5ldyBJbnRsLk51bWJlckZvcm1hdChsb2NhbGUsIG9wdGlvbnMpO1xuICAgIE5VTUJFUl9GT1JNQVRTLnNldChrZXksIGZvcm1hdHRlcik7XG4gIH1cblxuICByZXR1cm4gZm9ybWF0dGVyO1xufVxuXG4vLyBObyB6b25lIGZvcm1hdHMgaW4gdGhlIGJyb3dzZXIncyBvd24gem9uZSwgd2hpY2ggaXMgcmlnaHQgZm9yIGEgY2FsZW5kYXIgZGF5XG4vLyBwYXJzZWQgYXMgbG9jYWwgbWlkbmlnaHQ6IHRoZSBkYXkgcHJpbnRlZCBpcyB0aGUgZGF5IHN0b3JlZC5cbmV4cG9ydCBmdW5jdGlvbiBkYXRlRm9ybWF0KFxuICBsb2NhbGU6IHN0cmluZyxcbiAgb3B0aW9uczogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMsXG4gIHRpbWVab25lPzogc3RyaW5nLFxuKTogSW50bC5EYXRlVGltZUZvcm1hdCB7XG4gIGNvbnN0IGtleSA9IGAke2xvY2FsZX18JHtKU09OLnN0cmluZ2lmeShvcHRpb25zKX18JHt0aW1lWm9uZSA/PyAnJ31gO1xuICBsZXQgZm9ybWF0dGVyID0gREFURV9GT1JNQVRTLmdldChrZXkpO1xuXG4gIGlmICghZm9ybWF0dGVyKSB7XG4gICAgZm9ybWF0dGVyID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQobG9jYWxlLCB7IC4uLm9wdGlvbnMsIHRpbWVab25lIH0pO1xuICAgIERBVEVfRk9STUFUUy5zZXQoa2V5LCBmb3JtYXR0ZXIpO1xuICB9XG5cbiAgcmV0dXJuIGZvcm1hdHRlcjtcbn1cblxuXG4vLyBOdW1iZXIgZm9ybWF0dGluZzogdGhlIG9uZSBlbmdpbmUgYmVoaW5kIGV2ZXJ5IG51bWVyaWMgc2xvdCAoYSBjaGFydFxuLy8gbWVhc3VyZSwgYSBLUEkgbWVhc3VyZSwgYSBsaXN0IGNvbHVtbiwgYSBjcm9zcy10YWIncyBjZWxscyksIHNvIGEgZm9ybWF0XG4vLyBtZWFucyB0aGUgc2FtZSB0aGluZyBvbiBzY3JlZW4sIGluIHRoZSBQREYgYW5kIGluIFBvd2VyUG9pbnQuIFRoZSBkYXRhIHN0YXlzXG4vLyByYXc7IG9ubHkgd2hhdCBpcyBzaG93biBjaGFuZ2VzLiBUaGUgcnVsZXM6XG4vLyAtIEVtcHR5OiBudWxsLCB1bmRlZmluZWQsICcnLCAnLScgYW5kIGEgbm9uLWZpbml0ZSBudW1iZXIgcHJpbnQgdGhlIGNhbGxlcidzXG4vLyAgIGBlbXB0eWAgKCfigJQnIHVubGVzcyBpdCBuYW1lcyBhbm90aGVyKS5cbi8vIC0gTnVtZXJpYzogYSBmaW5pdGUgbnVtYmVyLCBvciBhIHN0cmluZyB0aGF0IHNwZWxscyBvbmUgcGxhaW5seSAoJzEyMzQuNTAnLFxuLy8gICAnLTNlMicpLiBBbnl0aGluZyBlbHNlICgnJDEsMjM0JywgYW4gaWQgd2l0aCBsZXR0ZXJzLCAnICcpIHByaW50cyBhcyBpdFxuLy8gICBjYW1lLCBzaW5jZSBhIGNvbHVtbiB0aGUgU1FMIGFscmVhZHkgZm9ybWF0dGVkIGlzIHRleHQuXG4vLyAtIFN0eWxlczogbnVtYmVyIGlzIGEgcGxhaW4gZGVjaW1hbDsgY3VycmVuY3kgaXMgdGhlIHJlcG9ydCdzIGN1cnJlbmN5XG4vLyAgIHdyaXR0ZW4gaW4gaXRzIGxvY2FsZSB3aXRoIGl0cyBzeW1ib2wgKFVTRCByZWFkcyAnJDEsMjM1JyBpbiBlbi1VUyBhbmRcbi8vICAgJ1VTJDEsMjM1JyBpbiBlbi1DQTsgRVVSIHJlYWRzICcxIDIzNSDigqwnIGluIGZyLUZSKTsgcGVyY2VudCB0YWtlcyBhIDAtMVxuLy8gICByYXRpbyAoMC4zIHJlYWRzIDMwJSksIG9yLCBmcm9tIGFuIG9sZGVyIHNlcnZlciB0aGF0IHNlbmRzIHBlcmNlbnQgdmFsdWVzXG4vLyAgIGFscmVhZHkgeDEwMCwgYSBkZWNpbWFsIHdpdGggYSAlIHNpZ24uIFByZWNpc2lvbiBvciB1bml0cyB3aXRob3V0IGEgZm9ybWF0XG4vLyAgIG1lYW4gbnVtYmVyLlxuLy8gLSBEZWNpbWFsczogYSBwcmVjaXNpb24gcGlucyBib3RoIHRoZSBtaW5pbXVtIGFuZCB0aGUgbWF4aW11bSwgc28gYSBjb2x1bW5cbi8vICAgb2YgcmF0ZXMgbGluZXMgdXAuIFdpdGhvdXQgb25lOiBhdCBtb3N0IG9uZSBmb3IgYSBwZXJjZW50IGFuZCBmb3IgYW5cbi8vICAgYWJicmV2aWF0ZWQgdmFsdWUgKDEuMkspLCB3aG9sZSB1bml0cyBmb3IgY3VycmVuY3ksIHRoZSBsb2NhbGUncyBkZWZhdWx0XG4vLyAgIGZvciBhIG51bWJlci5cbi8vIC0gVW5pdHM6IHRob3VzYW5kcyBhbmQgbWlsbGlvbnMgZGl2aWRlIGFuZCBhZGQgYSBLIG9yIE0gYWZ0ZXIgdGhlIGRpZ2l0c1xuLy8gICAoJyQxLjJLJywgJzEsMksgJCcpOyBhdXRvIHBpY2tzIHBlciB2YWx1ZSBieSBzaXplLCBhbmQgYSB2YWx1ZSB0aGF0IHdvdWxkXG4vLyAgIHJvdW5kIHRvIDEwMDBLIHJlYWRzIDFNLiBVbml0cyBuZXZlciBhcHBseSB0byBhIHBlcmNlbnQuXG4vLyAtIE5lZ2F0aXZlcyBrZWVwIHRoZSBsb2NhbGUncyBsZWFkaW5nIG1pbnVzLiBBIG5lZ2F0aXZlIHRoYXQgcm91bmRzIHRvIHplcm9cbi8vICAgcHJpbnRzIGFzIHplcm8sIG5ldmVyICctMCcuXG4vLyAtIFJvdW5kaW5nIGlzIEludGwncywgb24gdGhlIGRpZ2l0cyBzaG93bi4gRXZlcnkgdmFsdWUgaXMgd3JpdHRlbiBpbiB0aGVcbi8vICAgY29udGV4dCdzIGxvY2FsZSwgbmV2ZXIgdGhlIGJyb3dzZXIncy5cblxuLy8gVGhlIG1vc3QgZGVjaW1hbHMgYSBwcmVjaXNpb24gcGluczogdGhlIHNlcnZlcidzIHNjaGVtYSBib3VuZC5cbmNvbnN0IE1BWF9QUkVDSVNJT04gPSA2O1xuLy8gQXQgbW9zdCBvbmUgZGVjaW1hbCBmb3IgYSBwZXJjZW50LCBhbmQgZm9yIGFuIGFiYnJldmlhdGVkIHZhbHVlICgxLjJLKS5cbmNvbnN0IFBFUkNFTlRfREVDSU1BTFMgPSAxO1xuY29uc3QgU0NBTEVEX0RFQ0lNQUxTID0gMTtcbi8vIE1vbmV5IHNob3dzIHdob2xlIHVuaXRzIHVubGVzcyBhIHByZWNpc2lvbiBhc2tzIGZvciBkZWNpbWFscy5cbmNvbnN0IENVUlJFTkNZX0RFQ0lNQUxTID0gMDtcbi8vIEEgY3VycmVuY3kgYXhpcyB3aG9zZSB0aWNrcyBuZWVkIGRlY2ltYWxzIHNob3dzIGNlbnRzLCBub3QgdGVudGhzLlxuY29uc3QgQ1VSUkVOQ1lfQVhJU19ERUNJTUFMUyA9IDI7XG4vLyBXaGF0IGEgbWlzc2luZyB2YWx1ZSBwcmludHMgdW5sZXNzIHRoZSBjYWxsZXIgbmFtZXMgaXRzIG93bi5cbmNvbnN0IEVNUFRZX1ZBTFVFID0gJ+KAlCc7XG4vLyBUaGUgdGljayBjb3VudCBhIHZhbHVlIGF4aXMgYWltcyBmb3IsIGFzIEVDaGFydHMnIHNwbGl0TnVtYmVyIGRlZmF1bHQuXG5jb25zdCBBWElTX1RJQ0tTID0gNTtcblxuY29uc3QgTlVNRVJJQ19QQVRURVJOID0gL15cXHMqWy0rXT8oXFxkK1xcLj9cXGQqfFxcLlxcZCspKFtlRV1bLStdP1xcZCspP1xccyokLztcbi8vIFRoZSBmb3JtYXRUb1BhcnRzIHR5cGVzIHRoYXQgY2FycnkgYSBudW1iZXIncyBkaWdpdHMgYW5kIHNlcGFyYXRvcnMuXG5jb25zdCBOVU1CRVJfUEFSVFMgPSBuZXcgU2V0PEludGwuTnVtYmVyRm9ybWF0UGFydFR5cGVzPihbJ2ludGVnZXInLCAnZ3JvdXAnLCAnZGVjaW1hbCcsICdmcmFjdGlvbiddKTtcbmNvbnN0IERJR0lUX1BBUlRTID0gbmV3IFNldDxJbnRsLk51bWJlckZvcm1hdFBhcnRUeXBlcz4oWydpbnRlZ2VyJywgJ2ZyYWN0aW9uJ10pO1xuXG4vLyBBIG51bWVyaWMgZm9ybWF0J3MgdW5pdHMgb25jZSBkZWNpZGVkOiBhdXRvIGlzIHJlc29sdmVkIHRvIG9uZSBvZiB0aGVzZS5cbmV4cG9ydCB0eXBlIFJlc29sdmVkVW5pdHMgPSBSZXBvcnROdW1iZXJVbml0cy5Ob25lIHwgUmVwb3J0TnVtYmVyVW5pdHMuVGhvdXNhbmRzIHwgUmVwb3J0TnVtYmVyVW5pdHMuTWlsbGlvbnM7XG5cbmludGVyZmFjZSBVbml0U2NhbGUge1xuICBkaXZpc29yOiBudW1iZXI7XG4gIHN1ZmZpeDogc3RyaW5nO1xuICAvLyBUaGUgUG93ZXJQb2ludC9FeGNlbCBzY2FsaW5nIGNvbW1hczogZWFjaCBvbmUgZGl2aWRlcyBieSAxLDAwMC5cbiAgY29tbWFzOiBzdHJpbmc7XG59XG5cbmNvbnN0IFVOSVRfU0NBTEVTID0gbmV3IE1hcDxSZXNvbHZlZFVuaXRzLCBVbml0U2NhbGU+KFtcbiAgW1JlcG9ydE51bWJlclVuaXRzLlRob3VzYW5kcywgeyBkaXZpc29yOiAxZTMsIHN1ZmZpeDogJ0snLCBjb21tYXM6ICcsJyB9XSxcbiAgW1JlcG9ydE51bWJlclVuaXRzLk1pbGxpb25zLCB7IGRpdmlzb3I6IDFlNiwgc3VmZml4OiAnTScsIGNvbW1hczogJywsJyB9XSxcbl0pO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZvcm1hdE51bWJlck9wdGlvbnMge1xuICAvLyBXaGF0IGFuIGVtcHR5IHZhbHVlIHByaW50czogJ+KAlCcgZm9yIGEgS1BJIG9yIGEgdG9vbHRpcCwgJycgZm9yIGEgY2VsbC5cbiAgZW1wdHk/OiBzdHJpbmc7XG4gIC8vIFVuaXRzIGFscmVhZHkgZGVjaWRlZCBmb3IgdGhlIHdob2xlIGNoYXJ0LCBpbiBwbGFjZSBvZiB0aGUgc3BlYydzIG93bi5cbiAgdW5pdHM/OiBSZXNvbHZlZFVuaXRzO1xuICAvLyBEZWNpbWFscyBhbHJlYWR5IGRlY2lkZWQgZm9yIHRoZSB3aG9sZSBjaGFydCwgcGlubmVkIGFzIG1pbiBhbmQgbWF4LiBudWxsXG4gIC8vIGxlYXZlcyB0aGUgc3BlYydzIG93bi5cbiAgZGVjaW1hbHM/OiBudW1iZXIgfCBudWxsO1xufVxuXG4vLyBIb3cgYSBjaGFydCdzIHZhbHVlIGF4aXMgd3JpdGVzIGl0cyB0aWNrcywgZGVjaWRlZCBvbmNlIHBlciBjaGFydC5cbmV4cG9ydCBpbnRlcmZhY2UgQ2hhcnROdW1iZXJGb3JtYXQge1xuICB1bml0czogUmVzb2x2ZWRVbml0cztcbiAgLy8gUGlubmVkIGRlY2ltYWxzLCBvciBudWxsIGZvciBhIHBsYWluIG51bWJlciB3aG9zZSB0aWNrcyBrZWVwIHRoZWlyIG93bi5cbiAgZGVjaW1hbHM6IG51bWJlciB8IG51bGw7XG59XG5cbi8vIFRoZSB2YWx1ZSBhcyBhIGZpbml0ZSBudW1iZXIgd2hlbiBpdCBpcyBvbmUgb3IgcGxhaW5seSBzcGVsbHMgb25lLCBlbHNlXG4vLyBudWxsLlxuZXhwb3J0IGZ1bmN0aW9uIHRvRmluaXRlTnVtYmVyKHZhbHVlOiB1bmtub3duKTogbnVtYmVyIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZSh2YWx1ZSkgPyB2YWx1ZSA6IG51bGw7XG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCAhTlVNRVJJQ19QQVRURVJOLnRlc3QodmFsdWUpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBudW1lcmljID0gTnVtYmVyKHZhbHVlKTtcblxuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKG51bWVyaWMpID8gbnVtZXJpYyA6IG51bGw7XG59XG5cbi8vIFdoZXRoZXIgYSBzbG90IGFza3MgdG8gYmUgZm9ybWF0dGVkIGF0IGFsbC4gQSBzbG90IHdpdGhvdXQgdGhlc2Uga2V5cywgb3IgYVxuLy8gbGlzdCBjb2x1bW4gd2hvc2UgZm9ybWF0IGlzIGRhdGUsIGtlZXBzIGl0cyBvd24gcmVuZGVyaW5nLiBVbml0cyBub25lIGlzIHRoZVxuLy8gc2FtZSBhcyBubyB1bml0cyBrZXksIGFzIGl0IGlzIG9uIHRoZSBzZXJ2ZXIuXG5leHBvcnQgZnVuY3Rpb24gaGFzTnVtYmVyRm9ybWF0KHNwZWM/OiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCk6IGJvb2xlYW4ge1xuICBpZiAoIXNwZWMgfHwgc3BlYy5mb3JtYXQgPT09IFJlcG9ydExpc3RDb2x1bW5Gb3JtYXQuRGF0ZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB2YWx1ZUZvcm1hdChzcGVjKSAhPT0gbnVsbFxuICAgIHx8IChzcGVjLnByZWNpc2lvbiA/PyBudWxsKSAhPT0gbnVsbFxuICAgIHx8ICgoc3BlYy51bml0cyA/PyBSZXBvcnROdW1iZXJVbml0cy5Ob25lKSAhPT0gUmVwb3J0TnVtYmVyVW5pdHMuTm9uZSk7XG59XG5cbi8vIFRoZSB1bml0cyBhIHZhbHVlIGlzIHdyaXR0ZW4gaW4uIGF1dG8gZGVjaWRlcyBieSB0aGUgbWFnbml0dWRlOiBhIG1pbGxpb25cbi8vIGFuZCB1cCByZWFkcyBNLCBhIHRob3VzYW5kIGFuZCB1cCBLLCB1bmxlc3MgdGhlIHZhbHVlIHdvdWxkIHRoZW4gcm91bmQgdG9cbi8vIDEwMDBLIGF0IHRoZXNlIGRlY2ltYWxzLCB3aGljaCByZWFkcyAxTSBpbnN0ZWFkLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVVbml0cyhcbiAgdW5pdHM6IFJlcG9ydE51bWJlclVuaXRzIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgbWFnbml0dWRlOiBudW1iZXIsXG4gIGRlY2ltYWxzOiBudW1iZXIsXG4pOiBSZXNvbHZlZFVuaXRzIHtcbiAgc3dpdGNoICh1bml0cykge1xuICAgIGNhc2UgUmVwb3J0TnVtYmVyVW5pdHMuVGhvdXNhbmRzOlxuICAgIGNhc2UgUmVwb3J0TnVtYmVyVW5pdHMuTWlsbGlvbnM6XG4gICAgICByZXR1cm4gdW5pdHM7XG4gICAgY2FzZSBSZXBvcnROdW1iZXJVbml0cy5BdXRvOlxuICAgICAgcmV0dXJuIGF1dG9Vbml0cyhNYXRoLmFicyhtYWduaXR1ZGUpLCBkZWNpbWFscyk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBSZXBvcnROdW1iZXJVbml0cy5Ob25lO1xuICB9XG59XG5cbmZ1bmN0aW9uIGF1dG9Vbml0cyhtYWduaXR1ZGU6IG51bWJlciwgZGVjaW1hbHM6IG51bWJlcik6IFJlc29sdmVkVW5pdHMge1xuICBpZiAobWFnbml0dWRlID49IDFlNikge1xuICAgIHJldHVybiBSZXBvcnROdW1iZXJVbml0cy5NaWxsaW9ucztcbiAgfVxuXG4gIGlmIChtYWduaXR1ZGUgPCAxZTMpIHtcbiAgICByZXR1cm4gUmVwb3J0TnVtYmVyVW5pdHMuTm9uZTtcbiAgfVxuXG4gIHJldHVybiByb3VuZFRvKG1hZ25pdHVkZSAvIDFlMywgZGVjaW1hbHMpID49IDEwMDBcbiAgICA/IFJlcG9ydE51bWJlclVuaXRzLk1pbGxpb25zXG4gICAgOiBSZXBvcnROdW1iZXJVbml0cy5UaG91c2FuZHM7XG59XG5cbi8vIFRoZSB2YWx1ZSByb3VuZGVkIGFzIEludGwgcm91bmRzIGl0IGZvciBkaXNwbGF5LCBzbyB0aGUgSy10by1NIHByb21vdGlvblxuLy8gYWdyZWVzIHdpdGggdGhlIGRpZ2l0cyBhY3R1YWxseSBzaG93bi5cbmZ1bmN0aW9uIHJvdW5kVG8odmFsdWU6IG51bWJlciwgZGVjaW1hbHM6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IGRpZ2l0cyA9IGNsYW1wRGVjaW1hbHMoZGVjaW1hbHMpID8/IDA7XG5cbiAgLy8gQSBmaXhlZCBsb2NhbGUgb25seSBzbyBOdW1iZXIoKSBjYW4gcGFyc2UgdGhlIHJvdW5kZWQgZGlnaXRzIGJhY2suXG4gIHJldHVybiBOdW1iZXIobnVtYmVyRm9ybWF0KFJFUE9SVF9GQUxMQkFDS19MT0NBTEUsIHtcbiAgICB1c2VHcm91cGluZzogZmFsc2UsXG4gICAgbWluaW11bUZyYWN0aW9uRGlnaXRzOiAwLFxuICAgIG1heGltdW1GcmFjdGlvbkRpZ2l0czogZGlnaXRzLFxuICB9KS5mb3JtYXQodmFsdWUpKTtcbn1cblxuLy8gT25lIHZhbHVlLCB3cml0dGVuIGJ5IHRoZSBydWxlcyBhYm92ZS5cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXROdW1iZXIoXG4gIHZhbHVlOiB1bmtub3duLFxuICBzcGVjOiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgY29udGV4dDogUmVwb3J0Rm9ybWF0Q29udGV4dCxcbiAgb3B0aW9uczogRm9ybWF0TnVtYmVyT3B0aW9ucyA9IHt9LFxuKTogc3RyaW5nIHtcbiAgaWYgKGlzRW1wdHlWYWx1ZSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gb3B0aW9ucy5lbXB0eSA/PyBFTVBUWV9WQUxVRTtcbiAgfVxuXG4gIGNvbnN0IG51bWVyaWMgPSB0b0Zpbml0ZU51bWJlcih2YWx1ZSk7XG4gIGlmIChudW1lcmljID09PSBudWxsKSB7XG4gICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBjb25zdCBzdHlsZSA9IHJlc29sdmVTdHlsZShzcGVjKTtcbiAgY29uc3QgcHJlY2lzaW9uID0gY2xhbXBEZWNpbWFscyhzcGVjPy5wcmVjaXNpb24pO1xuICBjb25zdCB1bml0cyA9IHN0eWxlID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5QZXJjZW50XG4gICAgPyBSZXBvcnROdW1iZXJVbml0cy5Ob25lXG4gICAgOiBvcHRpb25zLnVuaXRzID8/IHJlc29sdmVVbml0cyhzcGVjPy51bml0cywgbnVtZXJpYywgcHJlY2lzaW9uID8/IFNDQUxFRF9ERUNJTUFMUyk7XG4gIGNvbnN0IHNjYWxlID0gVU5JVF9TQ0FMRVMuZ2V0KHVuaXRzKTtcbiAgY29uc3QgZGVjaW1hbHMgPSBjbGFtcERlY2ltYWxzKG9wdGlvbnMuZGVjaW1hbHMpID8/IHByZWNpc2lvbjtcbiAgY29uc3QgZm9ybWF0dGVyID0gbnVtYmVyRm9ybWF0KGNvbnRleHQubG9jYWxlLCBzdHlsZU9wdGlvbnMoc3R5bGUsIGNvbnRleHQsIGRlY2ltYWxzLCAhIXNjYWxlKSk7XG4gIGNvbnN0IHRleHQgPSB3cml0ZU51bWJlcihmb3JtYXR0ZXIsIChudW1lcmljID09PSAwID8gMCA6IG51bWVyaWMpIC8gKHNjYWxlPy5kaXZpc29yID8/IDEpLCBzY2FsZT8uc3VmZml4KTtcblxuICByZXR1cm4gc3R5bGUgPT09IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgJiYgIWNvbnRleHQucmF0aW9QZXJjZW50ID8gYCR7dGV4dH0lYCA6IHRleHQ7XG59XG5cbmZ1bmN0aW9uIGlzRW1wdHlWYWx1ZSh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGxcbiAgICB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkXG4gICAgfHwgdmFsdWUgPT09ICcnXG4gICAgfHwgdmFsdWUgPT09ICctJ1xuICAgIHx8ICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmICFOdW1iZXIuaXNGaW5pdGUodmFsdWUpKTtcbn1cblxuLy8gVGhlIHZhbHVlIGZvcm1hdCBhIHNsb3QgbmFtZXMsIG9yIG51bGwgd2hlbiBpdCBuYW1lcyBub25lIChvciBvbmx5IGRhdGUpLlxuZnVuY3Rpb24gdmFsdWVGb3JtYXQoc3BlYzogTnVtYmVyRm9ybWF0U3BlYyB8IG51bGwgfCB1bmRlZmluZWQpOiBSZXBvcnRWYWx1ZUZvcm1hdCB8IG51bGwge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhSZXBvcnRWYWx1ZUZvcm1hdCkuZmluZCgoZm9ybWF0KSA9PiBmb3JtYXQgPT09IHNwZWM/LmZvcm1hdCkgPz8gbnVsbDtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0eWxlKHNwZWM6IE51bWJlckZvcm1hdFNwZWMgfCBudWxsIHwgdW5kZWZpbmVkKTogUmVwb3J0VmFsdWVGb3JtYXQge1xuICByZXR1cm4gdmFsdWVGb3JtYXQoc3BlYykgPz8gUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyO1xufVxuXG4vLyBBIHVzYWJsZSBkZWNpbWFsIGNvdW50LCBvciBudWxsLiBBIHN0b3JlZCB2YWx1ZSBvdXRzaWRlIHRoZSBzY2hlbWEncyBib3VuZHNcbi8vIGlzIGJyb3VnaHQgaW5zaWRlIHRoZW0gcmF0aGVyIHRoYW4gdGhyb3duIG9uIGJ5IEludGwuXG5mdW5jdGlvbiBjbGFtcERlY2ltYWxzKGRlY2ltYWxzOiBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHwgbnVsbCB7XG4gIHJldHVybiB0eXBlb2YgZGVjaW1hbHMgPT09ICdudW1iZXInICYmIE51bWJlci5pc0Zpbml0ZShkZWNpbWFscylcbiAgICA/IE1hdGgubWluKE1BWF9QUkVDSVNJT04sIE1hdGgubWF4KDAsIE1hdGgucm91bmQoZGVjaW1hbHMpKSlcbiAgICA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT3B0aW9ucyhcbiAgc3R5bGU6IFJlcG9ydFZhbHVlRm9ybWF0LFxuICBjb250ZXh0OiBSZXBvcnRGb3JtYXRDb250ZXh0LFxuICBkZWNpbWFsczogbnVtYmVyIHwgbnVsbCxcbiAgc2NhbGVkOiBib29sZWFuLFxuKTogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zIHtcbiAgY29uc3QgZnJhY3Rpb25EaWdpdHMgPSBmcmFjdGlvbkRpZ2l0T3B0aW9ucyhkZWNpbWFscywgZGVmYXVsdERlY2ltYWxzKHN0eWxlLCBzY2FsZWQpKTtcblxuICBzd2l0Y2ggKHN0eWxlKSB7XG4gICAgY2FzZSBSZXBvcnRWYWx1ZUZvcm1hdC5DdXJyZW5jeTpcbiAgICAgIHJldHVybiB7IC4uLmN1cnJlbmN5T3B0aW9ucyhjb250ZXh0LmN1cnJlbmN5KSwgLi4uZnJhY3Rpb25EaWdpdHMgfTtcbiAgICBjYXNlIFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQ6XG4gICAgICByZXR1cm4gY29udGV4dC5yYXRpb1BlcmNlbnQgPyB7IHN0eWxlOiAncGVyY2VudCcsIC4uLmZyYWN0aW9uRGlnaXRzIH0gOiBmcmFjdGlvbkRpZ2l0cztcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZyYWN0aW9uRGlnaXRzO1xuICB9XG59XG5cbmZ1bmN0aW9uIGN1cnJlbmN5T3B0aW9ucyhjdXJyZW5jeTogUmVwb3J0Q3VycmVuY3lDb2RlKTogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zIHtcbiAgcmV0dXJuIHsgc3R5bGU6ICdjdXJyZW5jeScsIGN1cnJlbmN5LCBjdXJyZW5jeURpc3BsYXk6ICdzeW1ib2wnIH07XG59XG5cbi8vIFRoZSBtb3N0IGRlY2ltYWxzIGEgc3R5bGUgc2hvd3Mgd2hlbiBub3RoaW5nIHBpbnMgdGhlbTsgbnVsbCBsZWF2ZXMgSW50bCdzXG4vLyBvd24gZGVmYXVsdC5cbmZ1bmN0aW9uIGRlZmF1bHREZWNpbWFscyhzdHlsZTogUmVwb3J0VmFsdWVGb3JtYXQsIHNjYWxlZDogYm9vbGVhbik6IG51bWJlciB8IG51bGwge1xuICBpZiAoc2NhbGVkKSB7XG4gICAgcmV0dXJuIFNDQUxFRF9ERUNJTUFMUztcbiAgfVxuXG4gIHN3aXRjaCAoc3R5bGUpIHtcbiAgICBjYXNlIFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQ6XG4gICAgICByZXR1cm4gUEVSQ0VOVF9ERUNJTUFMUztcbiAgICBjYXNlIFJlcG9ydFZhbHVlRm9ybWF0LkN1cnJlbmN5OlxuICAgICAgcmV0dXJuIENVUlJFTkNZX0RFQ0lNQUxTO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vLyBQaW5uZWQgZGVjaW1hbHMgc2V0IGJvdGggYm91bmRzLiBPdGhlcndpc2UgYSBtYXhpbXVtIGFsc28gc2V0cyB0aGUgbWluaW11bVxuLy8gdG8gemVybywgc28gbm8gZW5naW5lIHRocm93cyBvbiBhIG1heGltdW0gYmVsb3cgYSBjdXJyZW5jeSdzIG93biBtaW5pbXVtLlxuZnVuY3Rpb24gZnJhY3Rpb25EaWdpdE9wdGlvbnMocGlubmVkOiBudW1iZXIgfCBudWxsLCBtYXhpbXVtOiBudW1iZXIgfCBudWxsKTogSW50bC5OdW1iZXJGb3JtYXRPcHRpb25zIHtcbiAgaWYgKHBpbm5lZCAhPT0gbnVsbCkge1xuICAgIHJldHVybiB7IG1pbmltdW1GcmFjdGlvbkRpZ2l0czogcGlubmVkLCBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IHBpbm5lZCB9O1xuICB9XG5cbiAgcmV0dXJuIG1heGltdW0gPT09IG51bGwgPyB7fSA6IHsgbWluaW11bUZyYWN0aW9uRGlnaXRzOiAwLCBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IG1heGltdW0gfTtcbn1cblxuLy8gVGhlIGZvcm1hdHRlZCB2YWx1ZSwgd2l0aCB0aGUgdW5pdHMgbGV0dGVyIGFmdGVyIGl0cyBkaWdpdHMuIEEgbmVnYXRpdmVcbi8vIHdob3NlIHNob3duIGRpZ2l0cyBhcmUgYWxsIHplcm8gaXMgd3JpdHRlbiBhcyB6ZXJvLCBzbyBubyAnLTAnIGFwcGVhcnMuXG5mdW5jdGlvbiB3cml0ZU51bWJlcihmb3JtYXR0ZXI6IEludGwuTnVtYmVyRm9ybWF0LCB2YWx1ZTogbnVtYmVyLCBzdWZmaXg/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodmFsdWUgPj0gMCAmJiAhc3VmZml4KSB7XG4gICAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXQodmFsdWUpO1xuICB9XG5cbiAgY29uc3QgcGFydHMgPSBmb3JtYXR0ZXIuZm9ybWF0VG9QYXJ0cyh2YWx1ZSk7XG5cbiAgaWYgKHZhbHVlIDwgMCAmJiAhaGFzTm9uWmVyb0RpZ2l0KGZvcm1hdHRlciwgcGFydHMpKSB7XG4gICAgcmV0dXJuIHdyaXRlTnVtYmVyKGZvcm1hdHRlciwgMCwgc3VmZml4KTtcbiAgfVxuXG4gIGlmICghc3VmZml4KSB7XG4gICAgcmV0dXJuIHBhcnRzLm1hcCgocGFydCkgPT4gcGFydC52YWx1ZSkuam9pbignJyk7XG4gIH1cblxuICBjb25zdCBsYXN0ID0gcGFydHMucmVkdWNlKChmb3VuZCwgcGFydCwgaW5kZXgpID0+IE5VTUJFUl9QQVJUUy5oYXMocGFydC50eXBlKSA/IGluZGV4IDogZm91bmQsIC0xKTtcblxuICByZXR1cm4gW1xuICAgIC4uLnBhcnRzLnNsaWNlKDAsIGxhc3QgKyAxKS5tYXAoKHBhcnQpID0+IHBhcnQudmFsdWUpLFxuICAgIHN1ZmZpeCxcbiAgICAuLi5wYXJ0cy5zbGljZShsYXN0ICsgMSkubWFwKChwYXJ0KSA9PiBwYXJ0LnZhbHVlKSxcbiAgXS5qb2luKCcnKTtcbn1cblxuLy8gQ29tcGFyZWQgd2l0aCB0aGUgbG9jYWxlJ3Mgb3duIHplcm8sIHNvIGEgbnVtYmVyaW5nIHN5c3RlbSBvdGhlciB0aGFuXG4vLyAwLTkgaXMgcmVhZCBjb3JyZWN0bHkuXG5mdW5jdGlvbiBoYXNOb25aZXJvRGlnaXQoZm9ybWF0dGVyOiBJbnRsLk51bWJlckZvcm1hdCwgcGFydHM6IEludGwuTnVtYmVyRm9ybWF0UGFydFtdKTogYm9vbGVhbiB7XG4gIGNvbnN0IHplcm8gPSBmb3JtYXR0ZXIuZm9ybWF0VG9QYXJ0cygwKS5maW5kKChwYXJ0KSA9PiBwYXJ0LnR5cGUgPT09ICdpbnRlZ2VyJyk/LnZhbHVlID8/ICcwJztcblxuICByZXR1cm4gcGFydHMuc29tZSgocGFydCkgPT4gRElHSVRfUEFSVFMuaGFzKHBhcnQudHlwZSlcbiAgICAmJiBBcnJheS5mcm9tKHBhcnQudmFsdWUpLnNvbWUoKGNoYXJhY3RlcikgPT4gY2hhcmFjdGVyICE9PSB6ZXJvKSk7XG59XG5cblxuLy8gQSBjaGFydCdzIHZhbHVlIGF4aXMgdGFrZXMgYSBmb3JtYXQgb25seSB3aGVuIGV2ZXJ5IG1lYXN1cmUgb24gaXQgYWdyZWVzIG9uXG4vLyB0aGUgc3R5bGUgKGVhY2ggbWVhc3VyZSdzIGZvcm1hdCwgbnVtYmVyIHdoZW4gaXQgbmFtZXMgbm9uZSkgYW5kIGF0IGxlYXN0XG4vLyBvbmUgb2YgdGhlbSBuYW1lcyBhIGZvcm1hdC4gVGhlIGZpcnN0IG1lYXN1cmUgdGhhdCBkb2VzIGdpdmVzIHRoZSBheGlzIGl0c1xuLy8gcHJlY2lzaW9uIGFuZCB1bml0cy4gT3RoZXJ3aXNlIG51bGw6IHRoZSBheGlzIGtlZXBzIGl0cyBkZWZhdWx0IHRpY2tzIG9uXG4vLyBzY3JlZW4gYW5kIGluIFBvd2VyUG9pbnQsIGFuZCBlYWNoIHNlcmllcyBzdGlsbCBmb3JtYXRzIGl0cyBvd24gdG9vbHRpcHMuXG5leHBvcnQgZnVuY3Rpb24gYXhpc051bWJlckZvcm1hdChtZWFzdXJlczogQ2hhcnRNZWFzdXJlW10pOiBOdW1iZXJGb3JtYXRTcGVjIHwgbnVsbCB7XG4gIGNvbnN0IHN0eWxlID0gbWVhc3VyZXMubGVuZ3RoID8gcmVzb2x2ZVN0eWxlKG1lYXN1cmVzWzBdKSA6IG51bGw7XG5cbiAgaWYgKHN0eWxlID09PSBudWxsIHx8IG1lYXN1cmVzLnNvbWUoKG1lYXN1cmUpID0+IHJlc29sdmVTdHlsZShtZWFzdXJlKSAhPT0gc3R5bGUpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBmb3JtYXR0ZWQgPSBtZWFzdXJlcy5maW5kKChtZWFzdXJlKSA9PiBoYXNOdW1iZXJGb3JtYXQobWVhc3VyZSkpO1xuXG4gIHJldHVybiBmb3JtYXR0ZWQgPyBudW1iZXJGb3JtYXRTcGVjKGZvcm1hdHRlZCkgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBudW1iZXJGb3JtYXRTcGVjKHNwZWM6IE51bWJlckZvcm1hdFNwZWMpOiBOdW1iZXJGb3JtYXRTcGVjIHtcbiAgcmV0dXJuIHtcbiAgICAuLi4oc3BlYy5mb3JtYXQgIT09IHVuZGVmaW5lZCA/IHsgZm9ybWF0OiBzcGVjLmZvcm1hdCB9IDoge30pLFxuICAgIC4uLihzcGVjLnByZWNpc2lvbiAhPT0gdW5kZWZpbmVkID8geyBwcmVjaXNpb246IHNwZWMucHJlY2lzaW9uIH0gOiB7fSksXG4gICAgLi4uKHNwZWMudW5pdHMgIT09IHVuZGVmaW5lZCA/IHsgdW5pdHM6IHNwZWMudW5pdHMgfSA6IHt9KSxcbiAgfTtcbn1cblxuLy8gSG93IGEgY2hhcnQncyB2YWx1ZSBheGlzIHdyaXRlcyBpdHMgdGlja3M6IHRoZSB1bml0cyBkZWNpZGVkIG9uY2UgZnJvbSB0aGVcbi8vIGF4aXMgcGVhaywgYW5kIHRoZSBkZWNpbWFscyB0aGUgcHJlY2lzaW9uIHBpbnMsIGVsc2UgYXMgbWFueSBhcyB0aGUgYXhpcydzXG4vLyB0aWNrIHN0ZXAgbmVlZHMgKGEgcGVyY2VudCBheGlzIHVwIHRvIDAuMTIlIHN0ZXBzIGJ5IDAuMDIlLCB0d28gZGVjaW1hbHMpLlxuLy8gUGlubmVkIGRlY2ltYWxzIGtlZXAgdGhlIHRpY2tzIGRpc3RpbmN0LCBhbmQgUG93ZXJQb2ludCBjYW4gb25seSBwaW4gdGhlbS5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQ2hhcnROdW1iZXJGb3JtYXQoXG4gIHNwZWM6IE51bWJlckZvcm1hdFNwZWMsXG4gIHBlYWs6IG51bWJlcixcbiAgY29udGV4dDogUmVwb3J0Rm9ybWF0Q29udGV4dCxcbik6IENoYXJ0TnVtYmVyRm9ybWF0IHtcbiAgY29uc3Qgc3R5bGUgPSByZXNvbHZlU3R5bGUoc3BlYyk7XG4gIGNvbnN0IHByZWNpc2lvbiA9IGNsYW1wRGVjaW1hbHMoc3BlYy5wcmVjaXNpb24pO1xuICBjb25zdCB1bml0cyA9IHN0eWxlID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5QZXJjZW50XG4gICAgPyBSZXBvcnROdW1iZXJVbml0cy5Ob25lXG4gICAgOiByZXNvbHZlVW5pdHMoc3BlYy51bml0cywgcGVhaywgcHJlY2lzaW9uID8/IFNDQUxFRF9ERUNJTUFMUyk7XG5cbiAgcmV0dXJuIHsgdW5pdHMsIGRlY2ltYWxzOiBwcmVjaXNpb24gPz8gYXhpc0RlY2ltYWxzKHN0eWxlLCB1bml0cywgcGVhaywgY29udGV4dCkgfTtcbn1cblxuLy8gVGhlIGRlY2ltYWxzIHRoZSBheGlzJ3MgbmljZSB0aWNrIHN0ZXAgbmVlZHMuIEEgcGxhaW4sIHVuYWJicmV2aWF0ZWQgbnVtYmVyXG4vLyBwaW5zIG5vbmUgKG51bGwpOiBpdHMgdGlja3Mga2VlcCB0aGVpciBvd24gZGVjaW1hbHMuIEFuIHVuc2NhbGVkIGN1cnJlbmN5XG4vLyBheGlzIHRoYXQgbmVlZHMgZGVjaW1hbHMgc2hvd3MgY2VudHMsIGFuZCBhIEsvTSBheGlzIGtlZXBzIGl0cyBzdGVwJ3Ncbi8vIGRlY2ltYWxzICgnJDAuNU0nLCBub3QgJyQwLjUwTScpLlxuZnVuY3Rpb24gYXhpc0RlY2ltYWxzKFxuICBzdHlsZTogUmVwb3J0VmFsdWVGb3JtYXQsXG4gIHVuaXRzOiBSZXNvbHZlZFVuaXRzLFxuICBwZWFrOiBudW1iZXIsXG4gIGNvbnRleHQ6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4pOiBudW1iZXIgfCBudWxsIHtcbiAgY29uc3Qgc2NhbGUgPSBVTklUX1NDQUxFUy5nZXQodW5pdHMpO1xuXG4gIGlmIChzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyICYmICFzY2FsZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3Qgc2hvd25QZWFrID0gc3R5bGUgPT09IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgJiYgY29udGV4dC5yYXRpb1BlcmNlbnRcbiAgICA/IE1hdGguYWJzKHBlYWspICogMTAwXG4gICAgOiBNYXRoLmFicyhwZWFrKSAvIChzY2FsZT8uZGl2aXNvciA/PyAxKTtcbiAgY29uc3Qgc3RlcCA9IG5pY2VTdGVwKHNob3duUGVhayAvIEFYSVNfVElDS1MpO1xuICBjb25zdCBkZWNpbWFscyA9IHN0ZXAgPiAwID8gY2xhbXBEZWNpbWFscygtTWF0aC5mbG9vcihNYXRoLmxvZzEwKHN0ZXApKSkgPz8gMCA6IDA7XG5cbiAgcmV0dXJuIHN0eWxlID09PSBSZXBvcnRWYWx1ZUZvcm1hdC5DdXJyZW5jeSAmJiBkZWNpbWFscyA+IDAgJiYgIXNjYWxlID8gQ1VSUkVOQ1lfQVhJU19ERUNJTUFMUyA6IGRlY2ltYWxzO1xufVxuXG4vLyBFQ2hhcnRzJyBuaWNlKCk6IHRoZSByb3VuZCBudW1iZXIgKDEsIDIsIDMsIDUgb3IgMTAgdGltZXMgYSBwb3dlciBvZiB0ZW4pIGFcbi8vIHJvdWdoIHRpY2sgc3RlcCBzbmFwcyB0by5cbmZ1bmN0aW9uIG5pY2VTdGVwKHJvdWdoOiBudW1iZXIpOiBudW1iZXIge1xuICBpZiAoIShyb3VnaCA+IDApIHx8ICFOdW1iZXIuaXNGaW5pdGUocm91Z2gpKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICBjb25zdCBleHBvbmVudCA9IE1hdGguZmxvb3IoTWF0aC5sb2cxMChyb3VnaCkpO1xuICBjb25zdCBwb3dlciA9IE1hdGgucG93KDEwLCBleHBvbmVudCk7XG4gIGNvbnN0IGZyYWN0aW9uID0gcm91Z2ggLyBwb3dlcjtcbiAgbGV0IG5pY2UgPSAxMDtcbiAgaWYgKGZyYWN0aW9uIDwgMS41KSB7XG4gICAgbmljZSA9IDE7XG4gIH0gZWxzZSBpZiAoZnJhY3Rpb24gPCAyLjUpIHtcbiAgICBuaWNlID0gMjtcbiAgfSBlbHNlIGlmIChmcmFjdGlvbiA8IDQpIHtcbiAgICBuaWNlID0gMztcbiAgfSBlbHNlIGlmIChmcmFjdGlvbiA8IDcpIHtcbiAgICBuaWNlID0gNTtcbiAgfVxuXG4gIHJldHVybiBuaWNlICogcG93ZXI7XG59XG5cbi8vIFBvd2VyUG9pbnQncyBudW1iZXIgZm9ybWF0IGNvZGUgZm9yIGEgZm9ybWF0dGVkIHZhbHVlIGF4aXMsIG1hdGNoaW5nIHRoZVxuLy8gc2NyZWVuJ3MgdGlja3M6ICcjLCMjMC4wJScgKHBlcmNlbnQpLCAnXCIkXCIjLCMjMCcgKGN1cnJlbmN5KSxcbi8vICcjLCMjMC4wLFwiS1wiJyAodGhvdXNhbmRzKSwgJyMsIyMwXCIgJFwiJyAoZnItQ0EgY3VycmVuY3kpLiBBIHBsYWluIG51bWJlclxuLy8gd2hvc2UgZGVjaW1hbHMgYXJlIG5vdCBwaW5uZWQga2VlcHMgY2hhcnRBeGlzRm9ybWF0Q29kZSdzIGNvZGUuIFRoZSBjb2RlJ3Ncbi8vIHNlcGFyYXRvcnMgZm9sbG93IHRoZSBvcGVuaW5nIG1hY2hpbmUncyBsb2NhbGU7IHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIGl0c1xuLy8gc2lkZSBmb2xsb3cgdGhlIHJlcG9ydCdzLlxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlckZvcm1hdENvZGUoXG4gIHNwZWM6IE51bWJlckZvcm1hdFNwZWMsXG4gIGNvbnRleHQ6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4gIGNoYXJ0OiBDaGFydE51bWJlckZvcm1hdCxcbiAgc2VyaWVzOiAobnVtYmVyIHwgbnVsbClbXVtdLFxuICBzdGFja2VkOiBib29sZWFuLFxuKTogc3RyaW5nIHtcbiAgY29uc3Qgc3R5bGUgPSByZXNvbHZlU3R5bGUoc3BlYyk7XG4gIGNvbnN0IHNjYWxlID0gc3R5bGUgPT09IFJlcG9ydFZhbHVlRm9ybWF0LlBlcmNlbnQgPyB1bmRlZmluZWQgOiBVTklUX1NDQUxFUy5nZXQoY2hhcnQudW5pdHMpO1xuXG4gIGlmIChzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuTnVtYmVyICYmICFzY2FsZSAmJiBjaGFydC5kZWNpbWFscyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBjaGFydEF4aXNGb3JtYXRDb2RlKHNlcmllcywgc3RhY2tlZCk7XG4gIH1cblxuICBjb25zdCBkZWNpbWFscyA9IGNoYXJ0LmRlY2ltYWxzID8/IDA7XG4gIGNvbnN0IGRpZ2l0cyA9IGAjLCMjMCR7ZGVjaW1hbHMgPiAwID8gYC4keycwJy5yZXBlYXQoZGVjaW1hbHMpfWAgOiAnJ31gO1xuXG4gIGlmIChzdHlsZSA9PT0gUmVwb3J0VmFsdWVGb3JtYXQuUGVyY2VudCkge1xuICAgIHJldHVybiBgJHtkaWdpdHN9JHtjb250ZXh0LnJhdGlvUGVyY2VudCA/ICclJyA6ICdcIiVcIid9YDtcbiAgfVxuXG4gIGNvbnN0IHNjYWxlZCA9IGAke2RpZ2l0c30ke3NjYWxlPy5jb21tYXMgPz8gJyd9YDtcbiAgY29uc3QgdW5pdCA9IHNjYWxlPy5zdWZmaXggPz8gJyc7XG5cbiAgaWYgKHN0eWxlICE9PSBSZXBvcnRWYWx1ZUZvcm1hdC5DdXJyZW5jeSkge1xuICAgIHJldHVybiB1bml0ID8gYCR7c2NhbGVkfVwiJHt1bml0fVwiYCA6IHNjYWxlZDtcbiAgfVxuXG4gIGNvbnN0IHN5bWJvbCA9IGN1cnJlbmN5U3ltYm9sKGNvbnRleHQpO1xuXG4gIHJldHVybiBzeW1ib2wucHJlZml4XG4gICAgPyBgXCIke3N5bWJvbC50ZXh0fVwiJHtzY2FsZWR9JHt1bml0ID8gYFwiJHt1bml0fVwiYCA6ICcnfWBcbiAgICA6IGAke3NjYWxlZH1cIiR7dW5pdH0ke3N5bWJvbC50ZXh0fVwiYDtcbn1cblxuLy8gVGhlIGN1cnJlbmN5IHN5bWJvbCBhcyB0aGUgbG9jYWxlIHdyaXRlcyBpdCBiZXNpZGUgYSBudW1iZXIsIHdpdGggdGhlIHNwYWNlXG4vLyBiZXR3ZWVuIHRoZW0sIGFuZCB3aGljaCBzaWRlIGl0IHNpdHMgb246ICckJyBiZWZvcmUgaW4gZW4tVVMsICcgJCcgYWZ0ZXIgaW5cbi8vIGZyLUNBLiBRdW90ZXMgYXJlIGRyb3BwZWQsIGFzIGEgZm9ybWF0IGNvZGUgY2Fubm90IGhvbGQgdGhlbS5cbmludGVyZmFjZSBDdXJyZW5jeVN5bWJvbCB7XG4gIHByZWZpeDogYm9vbGVhbjtcbiAgdGV4dDogc3RyaW5nO1xufVxuXG5jb25zdCBDVVJSRU5DWV9TWU1CT0xTID0gbmV3IE1hcDxzdHJpbmcsIEN1cnJlbmN5U3ltYm9sPigpO1xuXG5mdW5jdGlvbiBjdXJyZW5jeVN5bWJvbChjb250ZXh0OiBSZXBvcnRGb3JtYXRDb250ZXh0KTogQ3VycmVuY3lTeW1ib2wge1xuICBjb25zdCBrZXkgPSBgJHtjb250ZXh0LmxvY2FsZX18JHtjb250ZXh0LmN1cnJlbmN5fWA7XG4gIGxldCBzeW1ib2wgPSBDVVJSRU5DWV9TWU1CT0xTLmdldChrZXkpO1xuXG4gIGlmICghc3ltYm9sKSB7XG4gICAgY29uc3QgcGFydHMgPSBudW1iZXJGb3JtYXQoY29udGV4dC5sb2NhbGUsIGN1cnJlbmN5T3B0aW9ucyhjb250ZXh0LmN1cnJlbmN5KSkuZm9ybWF0VG9QYXJ0cygxKTtcbiAgICBjb25zdCBjdXJyZW5jeSA9IHBhcnRzLmZpbmRJbmRleCgocGFydCkgPT4gcGFydC50eXBlID09PSAnY3VycmVuY3knKTtcbiAgICBjb25zdCBmaXJzdCA9IHBhcnRzLmZpbmRJbmRleCgocGFydCkgPT4gTlVNQkVSX1BBUlRTLmhhcyhwYXJ0LnR5cGUpKTtcbiAgICBjb25zdCBsYXN0ID0gcGFydHMucmVkdWNlKChmb3VuZCwgcGFydCwgaW5kZXgpID0+IE5VTUJFUl9QQVJUUy5oYXMocGFydC50eXBlKSA/IGluZGV4IDogZm91bmQsIC0xKTtcbiAgICBjb25zdCBwcmVmaXggPSBjdXJyZW5jeSA8IGZpcnN0O1xuICAgIGNvbnN0IHRleHQgPSAocHJlZml4ID8gcGFydHMuc2xpY2UoTWF0aC5tYXgoY3VycmVuY3ksIDApLCBmaXJzdCkgOiBwYXJ0cy5zbGljZShsYXN0ICsgMSkpXG4gICAgICAubWFwKChwYXJ0KSA9PiBwYXJ0LnZhbHVlKVxuICAgICAgLmpvaW4oJycpXG4gICAgICAucmVwbGFjZSgvXCIvZywgJycpO1xuXG4gICAgc3ltYm9sID0geyBwcmVmaXgsIHRleHQgfTtcbiAgICBDVVJSRU5DWV9TWU1CT0xTLnNldChrZXksIHN5bWJvbCk7XG4gIH1cblxuICByZXR1cm4gc3ltYm9sO1xufVxuXG5cbi8vIEV2ZXJ5IGRlY2ltYWwgYSBudW1iZXIgaGFzLCBncm91cGVkLCBpbiB0aGUgbG9jYWxlOiB3aGF0IEVDaGFydHMgcHJpbnRzIGJ5XG4vLyBkZWZhdWx0IChpdHMgYWRkQ29tbWFzKSwgYnV0IGluIHRoZSByZXBvcnQncyBsb2NhbGUsIHNvIGEgY2hhcnQncyBheGlzIGFuZFxuLy8gdG9vbHRpcCByZWFkIGxpa2UgdGhlIHJlc3Qgb2YgdGhlIHJlcG9ydC4gMTIzNC41IHJlYWRzIDEsMjM0LjUgaW4gZW4tVVMgYW5kXG4vLyAxIDIzNCw1IGluIGZyLUNBLiBBIG5vbi1udW1lcmljIHN0cmluZyBpcyBzaG93biBhcyBpdCBjYW1lLCBhbmQgYW55dGhpbmdcbi8vIGVsc2Ugbm9uLW51bWVyaWMgYXMgJy0nLCBhcyBFQ2hhcnRzIHNob3dzIGl0LiBBcyB0aGVyZSwgYW4gaW5maW5pdGUgdmFsdWVcbi8vIHJlYWRzICdJbmZpbml0eScgYW5kIG5lZ2F0aXZlIHplcm8gKGEgdGljayBhIGZsb2F0IGVycm9yIGxlYXZlcyBqdXN0IGJlbG93XG4vLyB6ZXJvKSByZWFkcyAnMCcuXG5jb25zdCBQTEFJTl9OVU1CRVI6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyA9IHsgbWF4aW11bUZyYWN0aW9uRGlnaXRzOiAyMCB9O1xuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0UGxhaW5OdW1iZXIodmFsdWU6IHVua25vd24sIGxvY2FsZTogUmVwb3J0TG9jYWxlVGFnKTogc3RyaW5nIHtcbiAgY29uc3QgbnVtZXJpYyA9IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcidcbiAgICA/IHZhbHVlXG4gICAgOiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLnRyaW0oKSAhPT0gJycgPyBOdW1iZXIodmFsdWUpIDogTmFOO1xuXG4gIGlmIChOdW1iZXIuaXNOYU4obnVtZXJpYykpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlIDogJy0nO1xuICB9XG5cbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUobnVtZXJpYykpIHtcbiAgICByZXR1cm4gU3RyaW5nKG51bWVyaWMpO1xuICB9XG5cbiAgcmV0dXJuIG51bWJlckZvcm1hdChsb2NhbGUsIFBMQUlOX05VTUJFUikuZm9ybWF0KG51bWVyaWMgPT09IDAgPyAwIDogbnVtZXJpYyk7XG59XG5cblxuLy8gVGhlIGF4aXMgcGVhayBhdCB3aGljaCBhIG5hdGl2ZSBjaGFydCdzIHZhbHVlIGF4aXMgZ2FpbnMgdGhvdXNhbmRzXG4vLyBzZXBhcmF0b3JzLiBGcm9tIGhlcmUgdXAgdGhlIHRpY2tzIGFyZSB3aG9sZSBudW1iZXJzIGluIHByYWN0aWNlOyBiZWxvdyBpdFxuLy8gbmVpdGhlciB0aGUgc2NyZWVuIG5vciBQb3dlclBvaW50J3MgJ0dlbmVyYWwnIHNob3dzIGEgc2VwYXJhdG9yLlxuZXhwb3J0IGNvbnN0IEFYSVNfU0VQQVJBVE9SX1RIUkVTSE9MRCA9IDEwMDA7XG5cbi8vIFBvd2VyUG9pbnQncyBudW1iZXIgZm9ybWF0IGZvciBhIG5hdGl2ZSBjaGFydCdzIHZhbHVlIGF4aXMsIG1hdGNoaW5nIHdoYXQgdGhlXG4vLyBvbi1zY3JlZW4gYXhpcyBwcmludHMgYnkgZGVmYXVsdDogdGhvdXNhbmRzIHNlcGFyYXRvcnMgd2l0aCBlYWNoIHRpY2sncyBvd25cbi8vIGRlY2ltYWxzLiBFeGNlbCBoYXMgbm8gXCJHZW5lcmFsIHdpdGggc2VwYXJhdG9yc1wiLCBzbyBhbiBheGlzIHJlYWNoaW5nIDEsMDAwXG4vLyAod2hlcmUgdGlja3MgYXJlIHdob2xlIG51bWJlcnMpIGdldHMgJyMsIyMwJywgYW5kIGEgc21hbGxlciByYW5nZSBrZWVwc1xuLy8gJ0dlbmVyYWwnIHNvIGZyYWN0aW9uYWwgdGlja3MgKDAuMjUsIDAuNSkgYXJlIG5vdCByb3VuZGVkIGF3YXkuXG4vL1xuLy8gVGhlIHBlYWsgaXMgY2hhcnRWYWx1ZVBlYWsncy5cbmV4cG9ydCBmdW5jdGlvbiBjaGFydEF4aXNGb3JtYXRDb2RlKHNlcmllczogKG51bWJlciB8IG51bGwpW11bXSwgc3RhY2tlZDogYm9vbGVhbik6IHN0cmluZyB7XG4gIHJldHVybiBjaGFydFZhbHVlUGVhayhzZXJpZXMsIHN0YWNrZWQpID49IEFYSVNfU0VQQVJBVE9SX1RIUkVTSE9MRCA/ICcjLCMjMCcgOiAnR2VuZXJhbCc7XG59XG5cbi8vIFRoZSBsYXJnZXN0IG1hZ25pdHVkZSBhIGNoYXJ0J3MgdmFsdWUgYXhpcyBoYXMgdG8gcmVhY2guIEEgbWlzc2luZyB2YWx1ZVxuLy8gY291bnRzIGFzIDAuIEEgc3RhY2tlZCBjaGFydCdzIHBlYWsgaXMgaXRzIHRhbGxlc3Qgc3RhY2s6IHRoZSBsYXJnZXN0IHN1bSxcbi8vIHBlciBjYXRlZ29yeSwgb2YgZXZlcnkgc2VyaWVzJyBhYnNvbHV0ZSB2YWx1ZS5cbmV4cG9ydCBmdW5jdGlvbiBjaGFydFZhbHVlUGVhayhzZXJpZXM6IChudW1iZXIgfCBudWxsKVtdW10sIHN0YWNrZWQ6IGJvb2xlYW4pOiBudW1iZXIge1xuICBjb25zdCBtYWduaXR1ZGVzID0gc2VyaWVzLm1hcCgodmFsdWVzKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4gTWF0aC5hYnModmFsdWUgPz8gMCkpKTtcblxuICByZXR1cm4gc3RhY2tlZFxuICAgID8gTWF0aC5tYXgoMCwgLi4uKG1hZ25pdHVkZXNbMF0gPz8gW10pLm1hcCgoXywgaW5kZXgpID0+IG1hZ25pdHVkZXNcbiAgICAgIC5yZWR1Y2UoKHN1bSwgdmFsdWVzKSA9PiBzdW0gKyAodmFsdWVzW2luZGV4XSA/PyAwKSwgMCkpKVxuICAgIDogTWF0aC5tYXgoMCwgLi4ubWFnbml0dWRlcy5mbGF0KCkpO1xufVxuXG5cbi8vIFRoZSB6b25lIGV2ZXJ5IGRhdGUgaW4gYSByZXBvcnQgaXMgcmVhZCBpbi4gVGhlIHNlcnZlciByZXNvbHZlcyBpdCAodGhlXG4vLyByZXBvcnQncyBvd24gem9uZSwgZWxzZSB0aGUgYXBwbGljYXRpb24ncyBkZWZhdWx0IHJlcG9ydGluZyB6b25lKSBhbmQgc2VuZHNcbi8vIGl0IGFzIGBlZmZlY3RpdmVUaW1lem9uZWAuIEEgc2VydmVyIHRvbyBvbGQgdG8gc2VuZCB0aGUgZmllbGQgc3RpbGwgdXNlZCBhXG4vLyByZXBvcnQncyBwaW5uZWQgYHRpbWV6b25lYCwgc28gdGhhdCBjb21lcyBuZXh0OyB0aGUgYnJvd3NlcidzIHpvbmUgaXMgdGhlIGxhc3Rcbi8vIGZhbGxiYWNrLiBUaGlzIGlzIHRoZSBvbmUgcGxhY2UgdGhhdCBjaGFpbiBsaXZlcywgc28gZXZlcnkgZGF0ZSB0aGUgdmlld2VyXG4vLyByZW5kZXJzIG9yIHJlc29sdmVzIGFncmVlcyB3aXRoIGV2ZXJ5IG90aGVyLlxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZXBvcnRUaW1lem9uZShyZXBvcnQ6IFBpY2s8UmVwb3J0LCAnZWZmZWN0aXZlVGltZXpvbmUnIHwgJ3RpbWV6b25lJz4pOiBzdHJpbmcge1xuICByZXR1cm4gcmVwb3J0LmVmZmVjdGl2ZVRpbWV6b25lID8/IHJlcG9ydC50aW1lem9uZSA/PyBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG59XG5cblxuLy8gVGhlIGRhdGUgc2hhcGVzIGEgcmVwb3J0IHdyaXRlcywgZWFjaCBpbiB0aGUgcmVwb3J0J3MgbG9jYWxlLlxuLy8gJ0phbiA1LCAyMDI2JyAvICc1IGphbnYuIDIwMjYnOiBhIGRhdGUgY2VsbCwgYSBmaWx0ZXIgYm91bmQuXG5leHBvcnQgY29uc3QgREFZX1NIT1JUOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ3Nob3J0JywgZGF5OiAnbnVtZXJpYycgfTtcbi8vICdKYW51YXJ5IDUsIDIwMjYnIC8gJzUgamFudmllciAyMDI2JzogYW4gZXhwb3J0IGNvdmVyJ3MgZGF0ZSBsaW5lLlxuZXhwb3J0IGNvbnN0IERBWV9MT05HOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnLCBkYXk6ICdudW1lcmljJyB9O1xuLy8gJ0phbnVhcnknIC8gJ2phbnZpZXInOiBhIG1vbnRobHkgcGVyaW9kIGxhYmVsIChpdHMgeWVhciBpcyBhZGRlZCBhcGFydCkuXG5leHBvcnQgY29uc3QgTU9OVEhfTE9ORzogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMgPSB7IG1vbnRoOiAnbG9uZycgfTtcbi8vICdKYW51YXJ5IDIwMjYnIC8gJ2phbnZpZXIgMjAyNic6IGEgbW9udGhseSBwZXJpb2QgbGFiZWwgd3JpdHRlbiBpbiBmdWxsLlxuZXhwb3J0IGNvbnN0IE1PTlRIX1lFQVI6IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zID0geyB5ZWFyOiAnbnVtZXJpYycsIG1vbnRoOiAnbG9uZycgfTtcbi8vICdKYW4gNScgLyAnNSBqYW52Lic6IGEgZGFpbHkgb3Igd2Vla2x5IHBlcmlvZCBsYWJlbC5cbmV4cG9ydCBjb25zdCBNT05USF9EQVk6IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zID0geyBtb250aDogJ3Nob3J0JywgZGF5OiAnbnVtZXJpYycgfTtcblxuLy8gQSBkYXRlIGluIHRoZSBsb2NhbGUuIFdpdGggYSB6b25lLCB0aGUgZGF5IGl0IGZhbGxzIG9uIHRoZXJlOyB3aXRob3V0IG9uZSxcbi8vIHRoZSBicm93c2VyJ3Mgem9uZSwgd2hpY2gga2VlcHMgYSBjYWxlbmRhciBkYXkgcGFyc2VkIGFzIGxvY2FsIG1pZG5pZ2h0XG4vLyB1bnNoaWZ0ZWQuIEl0IG5ldmVyIHRocm93cywgc2luY2UgYSBwaXBlIG9yIGFuIGV4cG9ydCBjYWxscyBpdCBwZXIgY2VsbDogYW5cbi8vIGludmFsaWQgRGF0ZSByZWFkcyAnJywgYSBtYWxmb3JtZWQgbG9jYWxlICgnZW5fQ0EnKSByZWFkcyB0aGUgZmFsbGJhY2tcbi8vIGxvY2FsZSwgYW5kIGFuIHVua25vd24gem9uZSByZWFkcyBVVEMsIHdoaWNoIHN0aWxsIG5hbWVzIGEgcmVhbCBkYXkuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0TG9jYWxEYXRlKFxuICBkYXRlOiBEYXRlLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbiAgb3B0aW9uczogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMsXG4gIHRpbWVab25lPzogc3RyaW5nLFxuKTogc3RyaW5nIHtcbiAgaWYgKE51bWJlci5pc05hTihkYXRlLmdldFRpbWUoKSkpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICB0cnkge1xuICAgIHJldHVybiB3cml0ZURhdGUoZGF0ZUZvcm1hdChsb2NhbGUsIG9wdGlvbnMsIHRpbWVab25lKSwgZGF0ZSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmb3JtYXRGYWxsYmFja0RhdGUoZGF0ZSwgcmVzb2x2ZVJlcG9ydExvY2FsZShsb2NhbGUpLCBvcHRpb25zLCB0aW1lWm9uZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZm9ybWF0RmFsbGJhY2tEYXRlKFxuICBkYXRlOiBEYXRlLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbiAgb3B0aW9uczogSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMsXG4gIHRpbWVab25lPzogc3RyaW5nLFxuKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gd3JpdGVEYXRlKGRhdGVGb3JtYXQobG9jYWxlLCBvcHRpb25zLCB0aW1lWm9uZSksIGRhdGUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gd3JpdGVEYXRlKGRhdGVGb3JtYXQobG9jYWxlLCBvcHRpb25zLCAnVVRDJyksIGRhdGUpO1xuICB9XG59XG5cbi8vIEludGwgd3JpdGVzIGEgeWVhciBiZWxvdyAxMDAwIHdpdGggb25seSB0aGUgZGlnaXRzIGl0IGhhcyAoJ0phbiAxLCAxJyk7IGFcbi8vIGRhdGUncyB5ZWFyIGlzIGFsd2F5cyB3cml0dGVuIHdpdGggZm91ciAoJ0phbiAxLCAwMDAxJyksIHNvIGEgc2VudGluZWwgZGF5XG4vLyBzdGlsbCByZWFkcyBhcyBhIGRhdGUuIE9ubHkgc3VjaCBhIHllYXIgcGF5cyBmb3IgZm9ybWF0VG9QYXJ0cy5cbmZ1bmN0aW9uIHdyaXRlRGF0ZShmb3JtYXR0ZXI6IEludGwuRGF0ZVRpbWVGb3JtYXQsIGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICBpZiAoZGF0ZS5nZXRVVENGdWxsWWVhcigpID4gMTAwMCkge1xuICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0KGRhdGUpO1xuICB9XG5cbiAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXRUb1BhcnRzKGRhdGUpXG4gICAgLm1hcCgocGFydCkgPT4gcGFydC50eXBlID09PSAneWVhcicgPyBwYXJ0LnZhbHVlLnBhZFN0YXJ0KDQsICcwJykgOiBwYXJ0LnZhbHVlKVxuICAgIC5qb2luKCcnKTtcbn1cblxuXG5jb25zdCBEQVRFX09OTFlfUEFUVEVSTiA9IC9eXFxkezR9LVxcZHsyfS1cXGR7Mn0kLztcbmNvbnN0IERBVEVfVElNRV9QQVRURVJOID0gL14oXFxkezR9LVxcZHsyfS1cXGR7Mn0pWyBUXShcXGR7Mn06XFxkezJ9OlxcZHsyfSkoXFwuXFxkKyk/JC87XG5cbi8vIEEgcmVwb3J0IHJvdydzIGRhdGUgY2VsbCBhcyBhIGNhbGVuZGFyIGRheSBpbiB0aGUgcmVwb3J0J3Mgem9uZS5cbi8vXG4vLyBSZXBvcnQgcm93cyBhcmUgcmF3IGRhdGFiYXNlIHN0cmluZ3MsIG5vdCBzZXJpYWxpemVkIG1vZGVscywgc28gdGhlaXIgc2hhcGVcbi8vIGlzIHRoZSB3aXJlIGNvbnRyYWN0OiBhIERBVEUgY29sdW1uIGFycml2ZXMgYXMgJ1lZWVktTU0tREQnIGFuZCBhXG4vLyBkYXRlLWFuZC10aW1lIGNvbHVtbiBhcyAnWVlZWS1NTS1ERCBISDpNTTpTUycgaW4gVVRDLiBSZWFkaW5nIHRoYXQgc2hhcGVcbi8vIGhlcmUgZG9lcyBub3QgcmUtZGVyaXZlIGEgc2VydmVyIHJ1bGU7IGl0IG9ubHkgc3RvcHMgdGhlIGJyb3dzZXIgZ3Vlc3NpbmcuXG4vLyAtIEEgY2FsZW5kYXIgZGF5IGlzIG5ldmVyIHNoaWZ0ZWQ6IHBhcnNlSVNPIHJlYWRzIGl0IGFzIGxvY2FsIG1pZG5pZ2h0LCBzb1xuLy8gICB0aGUgZGF5IHByaW50ZWQgaXMgdGhlIGRheSBzdG9yZWQsIHdoYXRldmVyIHRoZSB6b25lLlxuLy8gLSBBbiBpbnN0YW50IGlzIHBpbm5lZCB0byBVVEMgd2l0aCBhbiBleHBsaWNpdCAnWicsIHRoZW4gc2hvd24gYXMgdGhlIGRheSBpdFxuLy8gICBmZWxsIG9uIGluIHRoZSByZXBvcnQncyB6b25lLCB0aGUgc2FtZSBkYXkgdGhlIGZpbHRlcnMgYW5kIHRpbWUgYnVja2V0cyB1c2UuXG4vLyAtIEFueXRoaW5nIGVsc2UgaXMgc2hvd24gYXMgaXQgY2FtZSwgYW5kIHNvIGlzIGEgdmFsdWUgdGhhdCBoYXMgdGhlIHNoYXBlXG4vLyAgIGJ1dCBuYW1lcyBubyByZWFsIGRheSAoYSB6ZXJvIGRhdGUgJzAwMDAtMDAtMDAnLCBvciAnMjAyNi0wMi0zMCcpOiBvbmVcbi8vICAgYmFkIGNlbGwgbXVzdCBub3QgdGhyb3cgb3V0IG9mIGEgcGlwZSBvciBhYm9ydCBhbiBleHBvcnQuXG4vLyBUaGUgZGF5IGlzIHdyaXR0ZW4gaW4gdGhlIHJlcG9ydCdzIGxvY2FsZTogJ0phbiA1LCAyMDI2JyBpbiBlbi1VUywgJzUgamFudi5cbi8vIDIwMjYnIGluIGZyLUNBLlxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFJlcG9ydERhdGUoXG4gIHZhbHVlOiB1bmtub3duLFxuICB0aW1lem9uZTogc3RyaW5nLFxuICBsb2NhbGU6IFJlcG9ydExvY2FsZVRhZyxcbik6IHN0cmluZyB7XG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIGNvbnN0IHRleHQgPSBTdHJpbmcodmFsdWUpO1xuXG4gIGlmIChEQVRFX09OTFlfUEFUVEVSTi50ZXN0KHRleHQpKSB7XG4gICAgY29uc3QgZGF5ID0gcGFyc2VJU08odGV4dCk7XG5cbiAgICByZXR1cm4gaXNWYWxpZChkYXkpID8gZm9ybWF0TG9jYWxEYXRlKGRheSwgbG9jYWxlLCBEQVlfU0hPUlQpIDogdGV4dDtcbiAgfVxuXG4gIGNvbnN0IGRhdGVUaW1lID0gREFURV9USU1FX1BBVFRFUk4uZXhlYyh0ZXh0KTtcbiAgaWYgKCFkYXRlVGltZSkge1xuICAgIHJldHVybiB0ZXh0O1xuICB9XG5cbiAgY29uc3QgaW5zdGFudCA9IHBhcnNlSVNPKGAke2RhdGVUaW1lWzFdfVQke2RhdGVUaW1lWzJdfVpgKTtcblxuICByZXR1cm4gaXNWYWxpZChpbnN0YW50KSA/IGZvcm1hdExvY2FsRGF0ZShpbnN0YW50LCBsb2NhbGUsIERBWV9TSE9SVCwgdGltZXpvbmUpIDogdGV4dDtcbn1cblxuXG4vLyBFbmdsaXNoIG5hbWVzIGZvciBhIGxvY2FsZSBhbmQgYSBjdXJyZW5jeSwgZm9yIHRoZSBzZXR0aW5ncyBzZWxlY3RzLiBUaGVcbi8vIGludGVyZmFjZSBzdGF5cyBFbmdsaXNoIHdoYXRldmVyIHRoZSByZXBvcnQncyBsb2NhbGU6ICdmci1DQScgcmVhZHNcbi8vICdDYW5hZGlhbiBGcmVuY2gnLCAnQ0FEJyByZWFkcyAnQ2FuYWRpYW4gRG9sbGFyJy4gQSBydW50aW1lIHdpdGhvdXQgdGhlXG4vLyBuYW1lcyBzaG93cyB0aGUgY29kZS5cbmV4cG9ydCBmdW5jdGlvbiBsb2NhbGVOYW1lKHRhZzogUmVwb3J0TG9jYWxlVGFnKTogc3RyaW5nIHtcbiAgcmV0dXJuIGRpc3BsYXlOYW1lKCdsYW5ndWFnZScsIHRhZyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjdXJyZW5jeU5hbWUoY29kZTogUmVwb3J0Q3VycmVuY3lDb2RlKTogc3RyaW5nIHtcbiAgcmV0dXJuIGRpc3BsYXlOYW1lKCdjdXJyZW5jeScsIGNvZGUpO1xufVxuXG5mdW5jdGlvbiBkaXNwbGF5TmFtZSh0eXBlOiAnbGFuZ3VhZ2UnIHwgJ2N1cnJlbmN5JywgY29kZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbmV3IEludGwuRGlzcGxheU5hbWVzKFsnZW4nXSwgeyB0eXBlIH0pLm9mKGNvZGUpID8/IGNvZGU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBjb2RlO1xuICB9XG59XG5cblxuLy8gQSBzaG9ydCwgaHVtYW4gbGFiZWwgZm9yIGEgem9uZTogaXRzIGNpdHkgcGx1cyB0aGUgY3VycmVudCBhYmJyZXZpYXRpb24sXG4vLyBlLmcuICdBbWVyaWNhL05ld19Zb3JrJyByZWFkcyAnTmV3IFlvcmsgKEVEVCknLiBVVEMgc3RheXMgJ1VUQycsIGFuZCBhblxuLy8gdW5rbm93biB6b25lIGlzIHNob3duIGFzIGl0cyBpZC4gQW4gJ0V0Yy8nIHpvbmUgbmFtZXMgbm8gY2l0eSwgYW5kIGl0cyBQT1NJWFxuLy8gc2lnbiBpcyB0aGUgcmV2ZXJzZSBvZiB0aGUgb2Zmc2V0ICgnRXRjL0dNVCs1JyBpcyBHTVQtNSksIHNvIGl0IHJlYWRzIGFzIHRoZVxuLy8gYWJicmV2aWF0aW9uIGFsb25lOiAnRXRjL1VUQycgaXMgJ1VUQycsICdFdGMvR01UKzUnIGlzICdHTVQtNScuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGltZXpvbmVMYWJlbCh0aW1lem9uZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHRpbWV6b25lID09PSAnVVRDJykge1xuICAgIHJldHVybiB0aW1lem9uZTtcbiAgfVxuXG4gIGNvbnN0IHNlZ21lbnRzID0gdGltZXpvbmUuc3BsaXQoJy8nKTtcblxuICB0cnkge1xuICAgIGNvbnN0IGFiYnJldmlhdGlvbiA9IGZvcm1hdEluVGltZVpvbmUobmV3IERhdGUoKSwgdGltZXpvbmUsICd6enonKTtcblxuICAgIHJldHVybiBzZWdtZW50c1swXSA9PT0gJ0V0YydcbiAgICAgID8gYWJicmV2aWF0aW9uXG4gICAgICA6IGAke3NlZ21lbnRzW3NlZ21lbnRzLmxlbmd0aCAtIDFdLnJlcGxhY2UoL18vZywgJyAnKX0gKCR7YWJicmV2aWF0aW9ufSlgO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdGltZXpvbmU7XG4gIH1cbn1cblxuXG4vLyBcIk5vd1wiIGFzIGEgRGF0ZSB3aG9zZSBsb2NhbCBmaWVsZHMgcmVhZCB0aGUgd2FsbCBjbG9jayBpbiB0aGUgZ2l2ZW4gem9uZSwgc29cbi8vIGRhdGUtZm5zIGNhbGVuZGFyIGFyaXRobWV0aWMgKHN0YXJ0T2ZXZWVrLCBzdGFydE9mTW9udGgsIC4uLikgYW5kXG4vLyBkYXRlQm91bmRTdHJpbmcoKSBsYW5kIG9uIHRoZSB6b25lJ3MgY2FsZW5kYXIgZGF5IHJhdGhlciB0aGFuIHRoZSBicm93c2VyJ3MuXG4vLyBBbiB1bmtub3duIHpvbmUgZmFsbHMgYmFjayB0byB0aGUgYnJvd3NlcidzIGNsb2NrLlxuZXhwb3J0IGZ1bmN0aW9uIGdldFpvbmVkTm93KHRpbWV6b25lOiBzdHJpbmcpOiBEYXRlIHtcbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHpvbmVkID0gdG9ab25lZFRpbWUobm93LCB0aW1lem9uZSk7XG5cbiAgICByZXR1cm4gTnVtYmVyLmlzTmFOKHpvbmVkLmdldFRpbWUoKSkgPyBub3cgOiB6b25lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG5vdztcbiAgfVxufVxuIl19
|