@firestitch/report 18.0.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 +16 -0
- package/app/reports/components/component-kpi/component-kpi.component.d.ts +12 -0
- package/app/reports/components/component-list/component-list.component.d.ts +27 -0
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +84 -0
- package/app/reports/components/report-component/report-component.component.d.ts +71 -0
- package/app/reports/components/timezone-select/timezone-select.component.d.ts +18 -0
- package/app/reports/data/report.data.d.ts +48 -0
- package/app/reports/dialogs/component-settings/component-settings.component.d.ts +49 -0
- package/app/reports/dialogs/report-settings/report-settings.component.d.ts +25 -0
- package/app/reports/export/offscreen-chart.d.ts +2 -0
- package/app/reports/export/report-export-collector.service.d.ts +26 -0
- package/app/reports/export/report-pdf.service.d.ts +13 -0
- package/app/reports/export/report-pptx.service.d.ts +14 -0
- package/app/reports/format.d.ts +1 -0
- package/app/reports/interfaces/report.interface.d.ts +174 -0
- package/app/reports/layout.d.ts +11 -0
- package/app/reports/option-builder.d.ts +15 -0
- package/app/reports/report-filter-items.d.ts +9 -0
- package/app/reports/services/report-filter-state.service.d.ts +25 -0
- package/app/reports/services/report.service.d.ts +15 -0
- package/app/reports/theme/echarts.d.ts +2 -0
- package/app/reports/theme/palette.d.ts +2 -0
- package/app/reports/views/report/report.component.d.ts +50 -0
- package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +47 -0
- package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +33 -0
- package/esm2022/app/reports/components/component-list/component-list.component.mjs +178 -0
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +347 -0
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +453 -0
- package/esm2022/app/reports/components/timezone-select/timezone-select.component.mjs +70 -0
- package/esm2022/app/reports/data/report.data.mjs +152 -0
- package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +221 -0
- package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +109 -0
- package/esm2022/app/reports/export/offscreen-chart.mjs +33 -0
- package/esm2022/app/reports/export/report-export-collector.service.mjs +94 -0
- package/esm2022/app/reports/export/report-pdf.service.mjs +155 -0
- package/esm2022/app/reports/export/report-pptx.service.mjs +224 -0
- package/esm2022/app/reports/format.mjs +25 -0
- package/esm2022/app/reports/interfaces/report.interface.mjs +16 -0
- package/esm2022/app/reports/layout.mjs +50 -0
- package/esm2022/app/reports/option-builder.mjs +293 -0
- package/esm2022/app/reports/report-filter-items.mjs +125 -0
- package/esm2022/app/reports/services/report-filter-state.service.mjs +177 -0
- package/esm2022/app/reports/services/report.service.mjs +56 -0
- package/esm2022/app/reports/theme/echarts.mjs +59 -0
- package/esm2022/app/reports/theme/palette.mjs +10 -0
- package/esm2022/app/reports/views/report/report.component.mjs +354 -0
- package/esm2022/firestitch-report.mjs +5 -0
- package/esm2022/public_api.mjs +13 -0
- package/fesm2022/firestitch-report-echarts-BxYnpz7n.mjs +60 -0
- package/fesm2022/firestitch-report-echarts-BxYnpz7n.mjs.map +1 -0
- package/fesm2022/firestitch-report-firestitch-report-Cnotycly.mjs +3107 -0
- package/fesm2022/firestitch-report-firestitch-report-Cnotycly.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +2 -0
- package/fesm2022/firestitch-report.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/package.json +39 -0
- package/public_api.d.ts +5 -0
- package/styles.scss +1 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { format } from 'date-fns';
|
|
3
|
+
import { formatMeasureValue } from '../format';
|
|
4
|
+
import { pageGeometry } from '../layout';
|
|
5
|
+
import { extractChartSeries, formatPeriodLabel, isColorBy, resolveLegendPosition, spansMultipleYears } from '../option-builder';
|
|
6
|
+
import { REPORT_CHART_COLORS } from '../theme/palette';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
// Component title strip height on the slide, inches.
|
|
9
|
+
const TITLE_H = 0.28;
|
|
10
|
+
// Approximate table row height, inches — drives the rows-that-fit cap.
|
|
11
|
+
const TABLE_ROW_H = 0.26;
|
|
12
|
+
// Our legend positions mapped to pptxgenjs's single-letter legendPos codes.
|
|
13
|
+
// 'hidden' has no slot — showLegend is turned off instead — so it falls back
|
|
14
|
+
// to top.
|
|
15
|
+
const PPTX_LEGEND_POS = {
|
|
16
|
+
top: 't',
|
|
17
|
+
bottom: 'b',
|
|
18
|
+
left: 'l',
|
|
19
|
+
right: 'r',
|
|
20
|
+
hidden: 't',
|
|
21
|
+
};
|
|
22
|
+
// Builds the PowerPoint deck client-side with pptxgenjs. Charts are NATIVE
|
|
23
|
+
// editable PowerPoint charts (slide.addChart writes real chart XML with an
|
|
24
|
+
// embedded data workbook — "Edit Data" works), never images. The page IS the
|
|
25
|
+
// slide: the report's unit is inches — exactly PowerPoint's unit — so the
|
|
26
|
+
// layout and every component position transfer with no conversion at all.
|
|
27
|
+
// pptxgenjs is loaded lazily so it lives in its own webpack chunk.
|
|
28
|
+
export class ReportPptxService {
|
|
29
|
+
async export(collected) {
|
|
30
|
+
const PptxGenJS = (await import('pptxgenjs')).default;
|
|
31
|
+
const report = collected.report;
|
|
32
|
+
const pageW = report.pageWidth;
|
|
33
|
+
const pageH = report.pageHeight;
|
|
34
|
+
const pptx = new PptxGenJS();
|
|
35
|
+
pptx.defineLayout({ name: 'REPORT', width: pageW, height: pageH });
|
|
36
|
+
pptx.layout = 'REPORT';
|
|
37
|
+
pptx.title = report.name;
|
|
38
|
+
this._titleSlide(pptx, collected, pageW, pageH);
|
|
39
|
+
for (const collectedPage of collected.pages) {
|
|
40
|
+
const slide = pptx.addSlide();
|
|
41
|
+
const geometry = pageGeometry(report, collectedPage.page);
|
|
42
|
+
for (const item of collectedPage.components) {
|
|
43
|
+
this._renderComponent(pptx, slide, item, geometry.get(item.component.id));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
await pptx.writeFile({ fileName: `${this._slug(report.name)}.pptx` });
|
|
47
|
+
}
|
|
48
|
+
_titleSlide(pptx, collected, pageW, pageH) {
|
|
49
|
+
const slide = pptx.addSlide();
|
|
50
|
+
slide.addText(collected.report.name, {
|
|
51
|
+
x: 0.5, y: pageH * 0.3, w: pageW - 1, h: 0.8,
|
|
52
|
+
fontSize: 30, bold: true, color: '1F2933',
|
|
53
|
+
});
|
|
54
|
+
const lines = [
|
|
55
|
+
format(new Date(), 'MMMM d, yyyy'),
|
|
56
|
+
...collected.filterSummary,
|
|
57
|
+
];
|
|
58
|
+
slide.addText(lines.join('\n'), {
|
|
59
|
+
x: 0.5, y: pageH * 0.3 + 0.9, w: pageW - 1, h: Math.max(0.4, lines.length * 0.25),
|
|
60
|
+
fontSize: 12, color: '52606D',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
_renderComponent(pptx, slide, item, geometry) {
|
|
64
|
+
const component = item.component;
|
|
65
|
+
// Geometry is in inches — PowerPoint's native unit (flow layout arrives
|
|
66
|
+
// pre-resolved into rows by pageGeometry).
|
|
67
|
+
const { x, y, w, h } = geometry ?? component;
|
|
68
|
+
if (component.title) {
|
|
69
|
+
slide.addText(component.title, {
|
|
70
|
+
x, y, w, h: TITLE_H,
|
|
71
|
+
fontSize: 10, bold: true, color: '1F2933', valign: 'top',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const bodyY = y + TITLE_H;
|
|
75
|
+
const bodyH = Math.max(0.3, h - TITLE_H);
|
|
76
|
+
if (!item.data || !item.data.rows?.length) {
|
|
77
|
+
slide.addText(item.data ? 'No data' : 'Data unavailable', {
|
|
78
|
+
x, y: bodyY, w, h: bodyH,
|
|
79
|
+
fontSize: 10, italic: true, color: '7B8794', align: 'center', valign: 'middle',
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
switch (component.type) {
|
|
84
|
+
case 'chart':
|
|
85
|
+
this._renderChart(pptx, slide, component, item.data, x, bodyY, w, bodyH);
|
|
86
|
+
break;
|
|
87
|
+
case 'list':
|
|
88
|
+
this._renderTable(slide, component, item.data, x, bodyY, w, bodyH);
|
|
89
|
+
break;
|
|
90
|
+
case 'kpi':
|
|
91
|
+
this._renderKpi(slide, component, item.data, x, bodyY, w, bodyH);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
_renderChart(pptx, slide, component, data, x, y, w, h) {
|
|
96
|
+
const config = component.config;
|
|
97
|
+
const chartType = config.chartType ?? 'bar';
|
|
98
|
+
const extracted = extractChartSeries(component, data);
|
|
99
|
+
const typeMap = {
|
|
100
|
+
bar: pptx.ChartType.bar,
|
|
101
|
+
line: pptx.ChartType.line,
|
|
102
|
+
area: pptx.ChartType.area,
|
|
103
|
+
pie: pptx.ChartType.pie,
|
|
104
|
+
donut: pptx.ChartType.doughnut,
|
|
105
|
+
};
|
|
106
|
+
const pie = chartType === 'pie' || chartType === 'donut';
|
|
107
|
+
const colorBy = isColorBy(config);
|
|
108
|
+
// Compact period labels match the on-screen axis (year only when the data
|
|
109
|
+
// spans years); PowerPoint can't do a styled second line, so it's inline.
|
|
110
|
+
const granularity = data.granularity;
|
|
111
|
+
const labels = granularity
|
|
112
|
+
? extracted.categories.map((category) => formatPeriodLabel(category, granularity, spansMultipleYears(extracted.categories)))
|
|
113
|
+
: extracted.categories;
|
|
114
|
+
// Native chart data: one entry per series (pie charts take exactly one).
|
|
115
|
+
// colorBy emits one series per category for the on-screen overlap; PowerPoint
|
|
116
|
+
// has no equivalent overlap, so collapse them back into a single series (each
|
|
117
|
+
// category's value sits at its own slot) — one full-width bar per category —
|
|
118
|
+
// rather than letting PowerPoint cluster them into slivers.
|
|
119
|
+
const chartData = colorBy
|
|
120
|
+
? [{
|
|
121
|
+
name: config.measures?.[0]?.label ?? config.colorBy?.label ?? '',
|
|
122
|
+
labels,
|
|
123
|
+
values: extracted.categories.map((_, index) => extracted.series[index]?.values[index] ?? 0),
|
|
124
|
+
}]
|
|
125
|
+
: (pie ? extracted.series.slice(0, 1) : extracted.series)
|
|
126
|
+
.map((series) => ({
|
|
127
|
+
name: series.name,
|
|
128
|
+
labels,
|
|
129
|
+
values: series.values.map((value) => value ?? 0),
|
|
130
|
+
}));
|
|
131
|
+
// A single-series colorBy chart can't carry a per-category legend in a native
|
|
132
|
+
// PowerPoint bar chart; the category axis labels identify each bar instead.
|
|
133
|
+
const legendPosition = colorBy
|
|
134
|
+
? 'hidden'
|
|
135
|
+
: resolveLegendPosition(config, extracted.series.length);
|
|
136
|
+
slide.addChart(typeMap[chartType], chartData, {
|
|
137
|
+
x, y, w, h,
|
|
138
|
+
chartColors: REPORT_CHART_COLORS,
|
|
139
|
+
showLegend: legendPosition !== 'hidden',
|
|
140
|
+
legendPos: PPTX_LEGEND_POS[legendPosition],
|
|
141
|
+
legendFontSize: 9,
|
|
142
|
+
barDir: config.orientation === 'horizontal' ? 'bar' : 'col',
|
|
143
|
+
barGrouping: config.stacked ? 'stacked' : 'clustered',
|
|
144
|
+
holeSize: chartType === 'donut' ? 55 : undefined,
|
|
145
|
+
catAxisLabelFontSize: 9,
|
|
146
|
+
valAxisLabelFontSize: 9,
|
|
147
|
+
showCatAxisTitle: !!config.xAxis?.label,
|
|
148
|
+
catAxisTitle: config.xAxis?.label,
|
|
149
|
+
catAxisTitleFontSize: 10,
|
|
150
|
+
showValAxisTitle: !!config.measures?.[0]?.label && !pie,
|
|
151
|
+
valAxisTitle: config.measures?.[0]?.label,
|
|
152
|
+
valAxisTitleFontSize: 10,
|
|
153
|
+
dataBorder: { pt: 0, color: 'FFFFFF' },
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
_renderTable(slide, component, data, x, y, w, h) {
|
|
157
|
+
const config = component.config;
|
|
158
|
+
const columns = config.columns?.length
|
|
159
|
+
? config.columns
|
|
160
|
+
: data.columns.map((column) => ({ column, label: column }));
|
|
161
|
+
const cap = Math.max(2, Math.floor(h / TABLE_ROW_H) - 1);
|
|
162
|
+
const rows = data.rows.slice(0, cap);
|
|
163
|
+
const remaining = (data.paging?.total ?? data.rows.length) - rows.length;
|
|
164
|
+
const header = columns.map((column) => ({
|
|
165
|
+
text: column.label || column.column,
|
|
166
|
+
options: { bold: true, color: 'FFFFFF', fill: { color: '4E79A7' } },
|
|
167
|
+
}));
|
|
168
|
+
const body = rows.map((row) => columns.map((column) => ({
|
|
169
|
+
text: this._cell(row[column.column], column.format),
|
|
170
|
+
options: {},
|
|
171
|
+
})));
|
|
172
|
+
if (remaining > 0) {
|
|
173
|
+
body.push([{
|
|
174
|
+
text: `… ${remaining} more row(s) — use the component's CSV export for the full dataset`,
|
|
175
|
+
options: { colspan: columns.length, italic: true, color: '7B8794' },
|
|
176
|
+
}]);
|
|
177
|
+
}
|
|
178
|
+
slide.addTable([header, ...body], {
|
|
179
|
+
x, y, w,
|
|
180
|
+
fontSize: 9,
|
|
181
|
+
color: '1F2933',
|
|
182
|
+
border: { type: 'solid', pt: 0.5, color: 'E4E7EB' },
|
|
183
|
+
autoPage: false,
|
|
184
|
+
rowH: TABLE_ROW_H,
|
|
185
|
+
valign: 'middle',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
_renderKpi(slide, component, data, x, y, w, h) {
|
|
189
|
+
const config = component.config;
|
|
190
|
+
const row = data.rows[0] ?? {};
|
|
191
|
+
const column = config.measure?.column ?? Object.keys(row)[0];
|
|
192
|
+
const value = formatMeasureValue(row[column], config.measure?.format);
|
|
193
|
+
slide.addText([
|
|
194
|
+
{ text: value, options: { fontSize: 28, bold: true, color: '1F2933', breakLine: true } },
|
|
195
|
+
{ text: config.measure?.label ?? '', options: { fontSize: 10, color: '7B8794' } },
|
|
196
|
+
], {
|
|
197
|
+
x, y, w, h,
|
|
198
|
+
align: 'center',
|
|
199
|
+
valign: 'middle',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
_cell(value, columnFormat) {
|
|
203
|
+
if (value === null || value === undefined) {
|
|
204
|
+
return '';
|
|
205
|
+
}
|
|
206
|
+
if (columnFormat === 'date') {
|
|
207
|
+
const date = new Date(String(value));
|
|
208
|
+
return Number.isNaN(date.getTime()) ? String(value) : format(date, 'MMM d, yyyy');
|
|
209
|
+
}
|
|
210
|
+
if (columnFormat === 'number') {
|
|
211
|
+
return formatMeasureValue(value, 'number');
|
|
212
|
+
}
|
|
213
|
+
return String(value);
|
|
214
|
+
}
|
|
215
|
+
_slug(name) {
|
|
216
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'report';
|
|
217
|
+
}
|
|
218
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportPptxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
219
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportPptxService });
|
|
220
|
+
}
|
|
221
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportPptxService, decorators: [{
|
|
222
|
+
type: Injectable
|
|
223
|
+
}] });
|
|
224
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXBwdHguc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9leHBvcnQvcmVwb3J0LXBwdHguc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFbEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBUy9DLE9BQU8sRUFBcUIsWUFBWSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzVELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUscUJBQXFCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNoSSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7QUFJdkQscURBQXFEO0FBQ3JELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQztBQUNyQix1RUFBdUU7QUFDdkUsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDO0FBRXpCLDRFQUE0RTtBQUM1RSw2RUFBNkU7QUFDN0UsVUFBVTtBQUNWLE1BQU0sZUFBZSxHQUFrRDtJQUNyRSxHQUFHLEVBQUUsR0FBRztJQUNSLE1BQU0sRUFBRSxHQUFHO0lBQ1gsSUFBSSxFQUFFLEdBQUc7SUFDVCxLQUFLLEVBQUUsR0FBRztJQUNWLE1BQU0sRUFBRSxHQUFHO0NBQ1osQ0FBQztBQUVGLDJFQUEyRTtBQUMzRSwyRUFBMkU7QUFDM0UsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSwwRUFBMEU7QUFDMUUsbUVBQW1FO0FBRW5FLE1BQU0sT0FBTyxpQkFBaUI7SUFFckIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUEwQjtRQUM1QyxNQUFNLFNBQVMsR0FBRyxDQUFDLE1BQU0sTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBRXRELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7UUFDaEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQztRQUMvQixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDO1FBRWhDLE1BQU0sSUFBSSxHQUFHLElBQUksU0FBUyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNuRSxJQUFJLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQztRQUN2QixJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFFekIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUVoRCxLQUFLLE1BQU0sYUFBYSxJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM1QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDOUIsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFMUQsS0FBSyxNQUFNLElBQUksSUFBSSxhQUFhLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQzVDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM1RSxDQUFDO1FBQ0gsQ0FBQztRQUVELE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFTyxXQUFXLENBQUMsSUFBUyxFQUFFLFNBQTBCLEVBQUUsS0FBYSxFQUFFLEtBQWE7UUFDckYsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRTlCLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7WUFDbkMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsS0FBSyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRztZQUM1QyxRQUFRLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVE7U0FDMUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxLQUFLLEdBQUc7WUFDWixNQUFNLENBQUMsSUFBSSxJQUFJLEVBQUUsRUFBRSxjQUFjLENBQUM7WUFDbEMsR0FBRyxTQUFTLENBQUMsYUFBYTtTQUMzQixDQUFDO1FBRUYsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQzlCLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEtBQUssR0FBRyxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNqRixRQUFRLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRO1NBQzlCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxJQUFTLEVBQUUsS0FBVSxFQUFFLElBQXdCLEVBQUUsUUFBNEI7UUFDcEcsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNqQyx3RUFBd0U7UUFDeEUsMkNBQTJDO1FBQzNDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRyxRQUFRLElBQUksU0FBUyxDQUFDO1FBRTdDLElBQUksU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRTtnQkFDN0IsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE9BQU87Z0JBQ25CLFFBQVEsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxLQUFLO2FBQ3pELENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsT0FBTyxDQUFDO1FBQzFCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQztRQUV6QyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQzFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsRUFBRTtnQkFDeEQsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLO2dCQUN4QixRQUFRLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxRQUFRO2FBQy9FLENBQUMsQ0FBQztZQUVILE9BQU87UUFDVCxDQUFDO1FBRUQsUUFBUSxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdkIsS0FBSyxPQUFPO2dCQUNWLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDekUsTUFBTTtZQUNSLEtBQUssTUFBTTtnQkFDVCxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDbkUsTUFBTTtZQUNSLEtBQUssS0FBSztnQkFDUixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDakUsTUFBTTtRQUNWLENBQUM7SUFDSCxDQUFDO0lBRU8sWUFBWSxDQUNsQixJQUFTLEVBQ1QsS0FBVSxFQUNWLFNBQTBCLEVBQzFCLElBQW1CLEVBQ25CLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVM7UUFFMUMsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQXFCLENBQUM7UUFDL0MsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUM7UUFDNUMsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXRELE1BQU0sT0FBTyxHQUF3QjtZQUNuQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHO1lBQ3ZCLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUk7WUFDekIsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSTtZQUN6QixHQUFHLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHO1lBQ3ZCLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVE7U0FDL0IsQ0FBQztRQUVGLE1BQU0sR0FBRyxHQUFHLFNBQVMsS0FBSyxLQUFLLElBQUksU0FBUyxLQUFLLE9BQU8sQ0FBQztRQUN6RCxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbEMsMEVBQTBFO1FBQzFFLDBFQUEwRTtRQUMxRSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQ3JDLE1BQU0sTUFBTSxHQUFHLFdBQVc7WUFDeEIsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FDdEMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUNyRixDQUFDLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQztRQUV6Qix5RUFBeUU7UUFDekUsOEVBQThFO1FBQzlFLDhFQUE4RTtRQUM5RSw2RUFBNkU7UUFDN0UsNERBQTREO1FBQzVELE1BQU0sU0FBUyxHQUFHLE9BQU87WUFDdkIsQ0FBQyxDQUFDLENBQUM7b0JBQ0QsSUFBSSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRTtvQkFDaEUsTUFBTTtvQkFDTixNQUFNLEVBQUUsU0FBUyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQzVGLENBQUM7WUFDRixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztpQkFDdEQsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7Z0JBQ2pCLE1BQU07Z0JBQ04sTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO2FBQ2pELENBQUMsQ0FBQyxDQUFDO1FBRVIsOEVBQThFO1FBQzlFLDRFQUE0RTtRQUM1RSxNQUFNLGNBQWMsR0FBRyxPQUFPO1lBQzVCLENBQUMsQ0FBQyxRQUFRO1lBQ1YsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTNELEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLFNBQVMsRUFBRTtZQUM1QyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ1YsV0FBVyxFQUFFLG1CQUFtQjtZQUNoQyxVQUFVLEVBQUUsY0FBYyxLQUFLLFFBQVE7WUFDdkMsU0FBUyxFQUFFLGVBQWUsQ0FBQyxjQUFjLENBQUM7WUFDMUMsY0FBYyxFQUFFLENBQUM7WUFDakIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxXQUFXLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUs7WUFDM0QsV0FBVyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsV0FBVztZQUNyRCxRQUFRLEVBQUUsU0FBUyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ2hELG9CQUFvQixFQUFFLENBQUM7WUFDdkIsb0JBQW9CLEVBQUUsQ0FBQztZQUN2QixnQkFBZ0IsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLO1lBQ3ZDLFlBQVksRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFLEtBQUs7WUFDakMsb0JBQW9CLEVBQUUsRUFBRTtZQUN4QixnQkFBZ0IsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLEdBQUc7WUFDdkQsWUFBWSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLO1lBQ3pDLG9CQUFvQixFQUFFLEVBQUU7WUFDeEIsVUFBVSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1NBQ3ZDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxZQUFZLENBQ2xCLEtBQVUsRUFDVixTQUEwQixFQUMxQixJQUFtQixFQUNuQixDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO1FBRTFDLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFvQixDQUFDO1FBQzlDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTTtZQUNwQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU87WUFDaEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFOUQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDekQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBRXpFLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdEMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxLQUFLLElBQUksTUFBTSxDQUFDLE1BQU07WUFDbkMsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTtTQUNwRSxDQUFDLENBQUMsQ0FBQztRQUVKLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdEQsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ25ELE9BQU8sRUFBRSxFQUFFO1NBQ1osQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVMLElBQUksU0FBUyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDVCxJQUFJLEVBQUUsS0FBSyxTQUFTLG9FQUFvRTtvQkFDeEYsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFTO2lCQUMzRSxDQUFDLENBQUMsQ0FBQztRQUNOLENBQUM7UUFFRCxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUU7WUFDaEMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ1AsUUFBUSxFQUFFLENBQUM7WUFDWCxLQUFLLEVBQUUsUUFBUTtZQUNmLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO1lBQ25ELFFBQVEsRUFBRSxLQUFLO1lBQ2YsSUFBSSxFQUFFLFdBQVc7WUFDakIsTUFBTSxFQUFFLFFBQVE7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLFVBQVUsQ0FDaEIsS0FBVSxFQUNWLFNBQTBCLEVBQzFCLElBQW1CLEVBQ25CLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVM7UUFFMUMsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQW1CLENBQUM7UUFDN0MsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDL0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RCxNQUFNLEtBQUssR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUV0RSxLQUFLLENBQUMsT0FBTyxDQUFDO1lBQ1osRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUN4RixFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEVBQUU7U0FDbEYsRUFBRTtZQUNELENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDVixLQUFLLEVBQUUsUUFBUTtZQUNmLE1BQU0sRUFBRSxRQUFRO1NBQ2pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxLQUFLLENBQUMsS0FBYyxFQUFFLFlBQXFCO1FBQ2pELElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDMUMsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsSUFBSSxZQUFZLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDNUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFckMsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDcEYsQ0FBQztRQUVELElBQUksWUFBWSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzlCLE9BQU8sa0JBQWtCLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRU8sS0FBSyxDQUFDLElBQVk7UUFDeEIsT0FBTyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxJQUFJLFFBQVEsQ0FBQztJQUM1RixDQUFDO3dHQXBQVSxpQkFBaUI7NEdBQWpCLGlCQUFpQjs7NEZBQWpCLGlCQUFpQjtrQkFEN0IsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgZm9ybWF0IH0gZnJvbSAnZGF0ZS1mbnMnO1xuXG5pbXBvcnQgeyBmb3JtYXRNZWFzdXJlVmFsdWUgfSBmcm9tICcuLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgQ2hhcnRDb25maWcsXG4gIENvbXBvbmVudERhdGEsXG4gIExlZ2VuZFBvc2l0aW9uLFxuICBMaXN0Q29uZmlnLFxuICBLcGlDb25maWcsXG4gIFJlcG9ydENvbXBvbmVudCxcbn0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IENvbXBvbmVudEdlb21ldHJ5LCBwYWdlR2VvbWV0cnkgfSBmcm9tICcuLi9sYXlvdXQnO1xuaW1wb3J0IHsgZXh0cmFjdENoYXJ0U2VyaWVzLCBmb3JtYXRQZXJpb2RMYWJlbCwgaXNDb2xvckJ5LCByZXNvbHZlTGVnZW5kUG9zaXRpb24sIHNwYW5zTXVsdGlwbGVZZWFycyB9IGZyb20gJy4uL29wdGlvbi1idWlsZGVyJztcbmltcG9ydCB7IFJFUE9SVF9DSEFSVF9DT0xPUlMgfSBmcm9tICcuLi90aGVtZS9wYWxldHRlJztcbmltcG9ydCB7IENvbGxlY3RlZENvbXBvbmVudCwgQ29sbGVjdGVkUmVwb3J0IH0gZnJvbSAnLi9yZXBvcnQtZXhwb3J0LWNvbGxlY3Rvci5zZXJ2aWNlJztcblxuXG4vLyBDb21wb25lbnQgdGl0bGUgc3RyaXAgaGVpZ2h0IG9uIHRoZSBzbGlkZSwgaW5jaGVzLlxuY29uc3QgVElUTEVfSCA9IDAuMjg7XG4vLyBBcHByb3hpbWF0ZSB0YWJsZSByb3cgaGVpZ2h0LCBpbmNoZXMg4oCUIGRyaXZlcyB0aGUgcm93cy10aGF0LWZpdCBjYXAuXG5jb25zdCBUQUJMRV9ST1dfSCA9IDAuMjY7XG5cbi8vIE91ciBsZWdlbmQgcG9zaXRpb25zIG1hcHBlZCB0byBwcHR4Z2VuanMncyBzaW5nbGUtbGV0dGVyIGxlZ2VuZFBvcyBjb2Rlcy5cbi8vICdoaWRkZW4nIGhhcyBubyBzbG90IOKAlCBzaG93TGVnZW5kIGlzIHR1cm5lZCBvZmYgaW5zdGVhZCDigJQgc28gaXQgZmFsbHMgYmFja1xuLy8gdG8gdG9wLlxuY29uc3QgUFBUWF9MRUdFTkRfUE9TOiBSZWNvcmQ8TGVnZW5kUG9zaXRpb24sICd0JyB8ICdiJyB8ICdsJyB8ICdyJz4gPSB7XG4gIHRvcDogJ3QnLFxuICBib3R0b206ICdiJyxcbiAgbGVmdDogJ2wnLFxuICByaWdodDogJ3InLFxuICBoaWRkZW46ICd0Jyxcbn07XG5cbi8vIEJ1aWxkcyB0aGUgUG93ZXJQb2ludCBkZWNrIGNsaWVudC1zaWRlIHdpdGggcHB0eGdlbmpzLiBDaGFydHMgYXJlIE5BVElWRVxuLy8gZWRpdGFibGUgUG93ZXJQb2ludCBjaGFydHMgKHNsaWRlLmFkZENoYXJ0IHdyaXRlcyByZWFsIGNoYXJ0IFhNTCB3aXRoIGFuXG4vLyBlbWJlZGRlZCBkYXRhIHdvcmtib29rIOKAlCBcIkVkaXQgRGF0YVwiIHdvcmtzKSwgbmV2ZXIgaW1hZ2VzLiBUaGUgcGFnZSBJUyB0aGVcbi8vIHNsaWRlOiB0aGUgcmVwb3J0J3MgdW5pdCBpcyBpbmNoZXMg4oCUIGV4YWN0bHkgUG93ZXJQb2ludCdzIHVuaXQg4oCUIHNvIHRoZVxuLy8gbGF5b3V0IGFuZCBldmVyeSBjb21wb25lbnQgcG9zaXRpb24gdHJhbnNmZXIgd2l0aCBubyBjb252ZXJzaW9uIGF0IGFsbC5cbi8vIHBwdHhnZW5qcyBpcyBsb2FkZWQgbGF6aWx5IHNvIGl0IGxpdmVzIGluIGl0cyBvd24gd2VicGFjayBjaHVuay5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSZXBvcnRQcHR4U2VydmljZSB7XG5cbiAgcHVibGljIGFzeW5jIGV4cG9ydChjb2xsZWN0ZWQ6IENvbGxlY3RlZFJlcG9ydCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IFBwdHhHZW5KUyA9IChhd2FpdCBpbXBvcnQoJ3BwdHhnZW5qcycpKS5kZWZhdWx0O1xuXG4gICAgY29uc3QgcmVwb3J0ID0gY29sbGVjdGVkLnJlcG9ydDtcbiAgICBjb25zdCBwYWdlVyA9IHJlcG9ydC5wYWdlV2lkdGg7XG4gICAgY29uc3QgcGFnZUggPSByZXBvcnQucGFnZUhlaWdodDtcblxuICAgIGNvbnN0IHBwdHggPSBuZXcgUHB0eEdlbkpTKCk7XG4gICAgcHB0eC5kZWZpbmVMYXlvdXQoeyBuYW1lOiAnUkVQT1JUJywgd2lkdGg6IHBhZ2VXLCBoZWlnaHQ6IHBhZ2VIIH0pO1xuICAgIHBwdHgubGF5b3V0ID0gJ1JFUE9SVCc7XG4gICAgcHB0eC50aXRsZSA9IHJlcG9ydC5uYW1lO1xuXG4gICAgdGhpcy5fdGl0bGVTbGlkZShwcHR4LCBjb2xsZWN0ZWQsIHBhZ2VXLCBwYWdlSCk7XG5cbiAgICBmb3IgKGNvbnN0IGNvbGxlY3RlZFBhZ2Ugb2YgY29sbGVjdGVkLnBhZ2VzKSB7XG4gICAgICBjb25zdCBzbGlkZSA9IHBwdHguYWRkU2xpZGUoKTtcbiAgICAgIGNvbnN0IGdlb21ldHJ5ID0gcGFnZUdlb21ldHJ5KHJlcG9ydCwgY29sbGVjdGVkUGFnZS5wYWdlKTtcblxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGNvbGxlY3RlZFBhZ2UuY29tcG9uZW50cykge1xuICAgICAgICB0aGlzLl9yZW5kZXJDb21wb25lbnQocHB0eCwgc2xpZGUsIGl0ZW0sIGdlb21ldHJ5LmdldChpdGVtLmNvbXBvbmVudC5pZCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGF3YWl0IHBwdHgud3JpdGVGaWxlKHsgZmlsZU5hbWU6IGAke3RoaXMuX3NsdWcocmVwb3J0Lm5hbWUpfS5wcHR4YCB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3RpdGxlU2xpZGUocHB0eDogYW55LCBjb2xsZWN0ZWQ6IENvbGxlY3RlZFJlcG9ydCwgcGFnZVc6IG51bWJlciwgcGFnZUg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHNsaWRlID0gcHB0eC5hZGRTbGlkZSgpO1xuXG4gICAgc2xpZGUuYWRkVGV4dChjb2xsZWN0ZWQucmVwb3J0Lm5hbWUsIHtcbiAgICAgIHg6IDAuNSwgeTogcGFnZUggKiAwLjMsIHc6IHBhZ2VXIC0gMSwgaDogMC44LFxuICAgICAgZm9udFNpemU6IDMwLCBib2xkOiB0cnVlLCBjb2xvcjogJzFGMjkzMycsXG4gICAgfSk7XG5cbiAgICBjb25zdCBsaW5lcyA9IFtcbiAgICAgIGZvcm1hdChuZXcgRGF0ZSgpLCAnTU1NTSBkLCB5eXl5JyksXG4gICAgICAuLi5jb2xsZWN0ZWQuZmlsdGVyU3VtbWFyeSxcbiAgICBdO1xuXG4gICAgc2xpZGUuYWRkVGV4dChsaW5lcy5qb2luKCdcXG4nKSwge1xuICAgICAgeDogMC41LCB5OiBwYWdlSCAqIDAuMyArIDAuOSwgdzogcGFnZVcgLSAxLCBoOiBNYXRoLm1heCgwLjQsIGxpbmVzLmxlbmd0aCAqIDAuMjUpLFxuICAgICAgZm9udFNpemU6IDEyLCBjb2xvcjogJzUyNjA2RCcsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9yZW5kZXJDb21wb25lbnQocHB0eDogYW55LCBzbGlkZTogYW55LCBpdGVtOiBDb2xsZWN0ZWRDb21wb25lbnQsIGdlb21ldHJ5PzogQ29tcG9uZW50R2VvbWV0cnkpOiB2b2lkIHtcbiAgICBjb25zdCBjb21wb25lbnQgPSBpdGVtLmNvbXBvbmVudDtcbiAgICAvLyBHZW9tZXRyeSBpcyBpbiBpbmNoZXMg4oCUIFBvd2VyUG9pbnQncyBuYXRpdmUgdW5pdCAoZmxvdyBsYXlvdXQgYXJyaXZlc1xuICAgIC8vIHByZS1yZXNvbHZlZCBpbnRvIHJvd3MgYnkgcGFnZUdlb21ldHJ5KS5cbiAgICBjb25zdCB7IHgsIHksIHcsIGggfSA9IGdlb21ldHJ5ID8/IGNvbXBvbmVudDtcblxuICAgIGlmIChjb21wb25lbnQudGl0bGUpIHtcbiAgICAgIHNsaWRlLmFkZFRleHQoY29tcG9uZW50LnRpdGxlLCB7XG4gICAgICAgIHgsIHksIHcsIGg6IFRJVExFX0gsXG4gICAgICAgIGZvbnRTaXplOiAxMCwgYm9sZDogdHJ1ZSwgY29sb3I6ICcxRjI5MzMnLCB2YWxpZ246ICd0b3AnLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgYm9keVkgPSB5ICsgVElUTEVfSDtcbiAgICBjb25zdCBib2R5SCA9IE1hdGgubWF4KDAuMywgaCAtIFRJVExFX0gpO1xuXG4gICAgaWYgKCFpdGVtLmRhdGEgfHwgIWl0ZW0uZGF0YS5yb3dzPy5sZW5ndGgpIHtcbiAgICAgIHNsaWRlLmFkZFRleHQoaXRlbS5kYXRhID8gJ05vIGRhdGEnIDogJ0RhdGEgdW5hdmFpbGFibGUnLCB7XG4gICAgICAgIHgsIHk6IGJvZHlZLCB3LCBoOiBib2R5SCxcbiAgICAgICAgZm9udFNpemU6IDEwLCBpdGFsaWM6IHRydWUsIGNvbG9yOiAnN0I4Nzk0JywgYWxpZ246ICdjZW50ZXInLCB2YWxpZ246ICdtaWRkbGUnLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGNvbXBvbmVudC50eXBlKSB7XG4gICAgICBjYXNlICdjaGFydCc6XG4gICAgICAgIHRoaXMuX3JlbmRlckNoYXJ0KHBwdHgsIHNsaWRlLCBjb21wb25lbnQsIGl0ZW0uZGF0YSwgeCwgYm9keVksIHcsIGJvZHlIKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdsaXN0JzpcbiAgICAgICAgdGhpcy5fcmVuZGVyVGFibGUoc2xpZGUsIGNvbXBvbmVudCwgaXRlbS5kYXRhLCB4LCBib2R5WSwgdywgYm9keUgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2twaSc6XG4gICAgICAgIHRoaXMuX3JlbmRlcktwaShzbGlkZSwgY29tcG9uZW50LCBpdGVtLmRhdGEsIHgsIGJvZHlZLCB3LCBib2R5SCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3JlbmRlckNoYXJ0KFxuICAgIHBwdHg6IGFueSxcbiAgICBzbGlkZTogYW55LFxuICAgIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50LFxuICAgIGRhdGE6IENvbXBvbmVudERhdGEsXG4gICAgeDogbnVtYmVyLCB5OiBudW1iZXIsIHc6IG51bWJlciwgaDogbnVtYmVyLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSBjb21wb25lbnQuY29uZmlnIGFzIENoYXJ0Q29uZmlnO1xuICAgIGNvbnN0IGNoYXJ0VHlwZSA9IGNvbmZpZy5jaGFydFR5cGUgPz8gJ2Jhcic7XG4gICAgY29uc3QgZXh0cmFjdGVkID0gZXh0cmFjdENoYXJ0U2VyaWVzKGNvbXBvbmVudCwgZGF0YSk7XG5cbiAgICBjb25zdCB0eXBlTWFwOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuICAgICAgYmFyOiBwcHR4LkNoYXJ0VHlwZS5iYXIsXG4gICAgICBsaW5lOiBwcHR4LkNoYXJ0VHlwZS5saW5lLFxuICAgICAgYXJlYTogcHB0eC5DaGFydFR5cGUuYXJlYSxcbiAgICAgIHBpZTogcHB0eC5DaGFydFR5cGUucGllLFxuICAgICAgZG9udXQ6IHBwdHguQ2hhcnRUeXBlLmRvdWdobnV0LFxuICAgIH07XG5cbiAgICBjb25zdCBwaWUgPSBjaGFydFR5cGUgPT09ICdwaWUnIHx8IGNoYXJ0VHlwZSA9PT0gJ2RvbnV0JztcbiAgICBjb25zdCBjb2xvckJ5ID0gaXNDb2xvckJ5KGNvbmZpZyk7XG5cbiAgICAvLyBDb21wYWN0IHBlcmlvZCBsYWJlbHMgbWF0Y2ggdGhlIG9uLXNjcmVlbiBheGlzICh5ZWFyIG9ubHkgd2hlbiB0aGUgZGF0YVxuICAgIC8vIHNwYW5zIHllYXJzKTsgUG93ZXJQb2ludCBjYW4ndCBkbyBhIHN0eWxlZCBzZWNvbmQgbGluZSwgc28gaXQncyBpbmxpbmUuXG4gICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBkYXRhLmdyYW51bGFyaXR5O1xuICAgIGNvbnN0IGxhYmVscyA9IGdyYW51bGFyaXR5XG4gICAgICA/IGV4dHJhY3RlZC5jYXRlZ29yaWVzLm1hcCgoY2F0ZWdvcnkpID0+XG4gICAgICAgIGZvcm1hdFBlcmlvZExhYmVsKGNhdGVnb3J5LCBncmFudWxhcml0eSwgc3BhbnNNdWx0aXBsZVllYXJzKGV4dHJhY3RlZC5jYXRlZ29yaWVzKSkpXG4gICAgICA6IGV4dHJhY3RlZC5jYXRlZ29yaWVzO1xuXG4gICAgLy8gTmF0aXZlIGNoYXJ0IGRhdGE6IG9uZSBlbnRyeSBwZXIgc2VyaWVzIChwaWUgY2hhcnRzIHRha2UgZXhhY3RseSBvbmUpLlxuICAgIC8vIGNvbG9yQnkgZW1pdHMgb25lIHNlcmllcyBwZXIgY2F0ZWdvcnkgZm9yIHRoZSBvbi1zY3JlZW4gb3ZlcmxhcDsgUG93ZXJQb2ludFxuICAgIC8vIGhhcyBubyBlcXVpdmFsZW50IG92ZXJsYXAsIHNvIGNvbGxhcHNlIHRoZW0gYmFjayBpbnRvIGEgc2luZ2xlIHNlcmllcyAoZWFjaFxuICAgIC8vIGNhdGVnb3J5J3MgdmFsdWUgc2l0cyBhdCBpdHMgb3duIHNsb3QpIOKAlCBvbmUgZnVsbC13aWR0aCBiYXIgcGVyIGNhdGVnb3J5IOKAlFxuICAgIC8vIHJhdGhlciB0aGFuIGxldHRpbmcgUG93ZXJQb2ludCBjbHVzdGVyIHRoZW0gaW50byBzbGl2ZXJzLlxuICAgIGNvbnN0IGNoYXJ0RGF0YSA9IGNvbG9yQnlcbiAgICAgID8gW3tcbiAgICAgICAgbmFtZTogY29uZmlnLm1lYXN1cmVzPy5bMF0/LmxhYmVsID8/IGNvbmZpZy5jb2xvckJ5Py5sYWJlbCA/PyAnJyxcbiAgICAgICAgbGFiZWxzLFxuICAgICAgICB2YWx1ZXM6IGV4dHJhY3RlZC5jYXRlZ29yaWVzLm1hcCgoXywgaW5kZXgpID0+IGV4dHJhY3RlZC5zZXJpZXNbaW5kZXhdPy52YWx1ZXNbaW5kZXhdID8/IDApLFxuICAgICAgfV1cbiAgICAgIDogKHBpZSA/IGV4dHJhY3RlZC5zZXJpZXMuc2xpY2UoMCwgMSkgOiBleHRyYWN0ZWQuc2VyaWVzKVxuICAgICAgICAubWFwKChzZXJpZXMpID0+ICh7XG4gICAgICAgICAgbmFtZTogc2VyaWVzLm5hbWUsXG4gICAgICAgICAgbGFiZWxzLFxuICAgICAgICAgIHZhbHVlczogc2VyaWVzLnZhbHVlcy5tYXAoKHZhbHVlKSA9PiB2YWx1ZSA/PyAwKSxcbiAgICAgICAgfSkpO1xuXG4gICAgLy8gQSBzaW5nbGUtc2VyaWVzIGNvbG9yQnkgY2hhcnQgY2FuJ3QgY2FycnkgYSBwZXItY2F0ZWdvcnkgbGVnZW5kIGluIGEgbmF0aXZlXG4gICAgLy8gUG93ZXJQb2ludCBiYXIgY2hhcnQ7IHRoZSBjYXRlZ29yeSBheGlzIGxhYmVscyBpZGVudGlmeSBlYWNoIGJhciBpbnN0ZWFkLlxuICAgIGNvbnN0IGxlZ2VuZFBvc2l0aW9uID0gY29sb3JCeVxuICAgICAgPyAnaGlkZGVuJ1xuICAgICAgOiByZXNvbHZlTGVnZW5kUG9zaXRpb24oY29uZmlnLCBleHRyYWN0ZWQuc2VyaWVzLmxlbmd0aCk7XG5cbiAgICBzbGlkZS5hZGRDaGFydCh0eXBlTWFwW2NoYXJ0VHlwZV0sIGNoYXJ0RGF0YSwge1xuICAgICAgeCwgeSwgdywgaCxcbiAgICAgIGNoYXJ0Q29sb3JzOiBSRVBPUlRfQ0hBUlRfQ09MT1JTLFxuICAgICAgc2hvd0xlZ2VuZDogbGVnZW5kUG9zaXRpb24gIT09ICdoaWRkZW4nLFxuICAgICAgbGVnZW5kUG9zOiBQUFRYX0xFR0VORF9QT1NbbGVnZW5kUG9zaXRpb25dLFxuICAgICAgbGVnZW5kRm9udFNpemU6IDksXG4gICAgICBiYXJEaXI6IGNvbmZpZy5vcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnID8gJ2JhcicgOiAnY29sJyxcbiAgICAgIGJhckdyb3VwaW5nOiBjb25maWcuc3RhY2tlZCA/ICdzdGFja2VkJyA6ICdjbHVzdGVyZWQnLFxuICAgICAgaG9sZVNpemU6IGNoYXJ0VHlwZSA9PT0gJ2RvbnV0JyA/IDU1IDogdW5kZWZpbmVkLFxuICAgICAgY2F0QXhpc0xhYmVsRm9udFNpemU6IDksXG4gICAgICB2YWxBeGlzTGFiZWxGb250U2l6ZTogOSxcbiAgICAgIHNob3dDYXRBeGlzVGl0bGU6ICEhY29uZmlnLnhBeGlzPy5sYWJlbCxcbiAgICAgIGNhdEF4aXNUaXRsZTogY29uZmlnLnhBeGlzPy5sYWJlbCxcbiAgICAgIGNhdEF4aXNUaXRsZUZvbnRTaXplOiAxMCxcbiAgICAgIHNob3dWYWxBeGlzVGl0bGU6ICEhY29uZmlnLm1lYXN1cmVzPy5bMF0/LmxhYmVsICYmICFwaWUsXG4gICAgICB2YWxBeGlzVGl0bGU6IGNvbmZpZy5tZWFzdXJlcz8uWzBdPy5sYWJlbCxcbiAgICAgIHZhbEF4aXNUaXRsZUZvbnRTaXplOiAxMCxcbiAgICAgIGRhdGFCb3JkZXI6IHsgcHQ6IDAsIGNvbG9yOiAnRkZGRkZGJyB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVuZGVyVGFibGUoXG4gICAgc2xpZGU6IGFueSxcbiAgICBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudCxcbiAgICBkYXRhOiBDb21wb25lbnREYXRhLFxuICAgIHg6IG51bWJlciwgeTogbnVtYmVyLCB3OiBudW1iZXIsIGg6IG51bWJlcixcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gY29tcG9uZW50LmNvbmZpZyBhcyBMaXN0Q29uZmlnO1xuICAgIGNvbnN0IGNvbHVtbnMgPSBjb25maWcuY29sdW1ucz8ubGVuZ3RoXG4gICAgICA/IGNvbmZpZy5jb2x1bW5zXG4gICAgICA6IGRhdGEuY29sdW1ucy5tYXAoKGNvbHVtbikgPT4gKHsgY29sdW1uLCBsYWJlbDogY29sdW1uIH0pKTtcblxuICAgIGNvbnN0IGNhcCA9IE1hdGgubWF4KDIsIE1hdGguZmxvb3IoaCAvIFRBQkxFX1JPV19IKSAtIDEpO1xuICAgIGNvbnN0IHJvd3MgPSBkYXRhLnJvd3Muc2xpY2UoMCwgY2FwKTtcbiAgICBjb25zdCByZW1haW5pbmcgPSAoZGF0YS5wYWdpbmc/LnRvdGFsID8/IGRhdGEucm93cy5sZW5ndGgpIC0gcm93cy5sZW5ndGg7XG5cbiAgICBjb25zdCBoZWFkZXIgPSBjb2x1bW5zLm1hcCgoY29sdW1uKSA9PiAoe1xuICAgICAgdGV4dDogY29sdW1uLmxhYmVsIHx8IGNvbHVtbi5jb2x1bW4sXG4gICAgICBvcHRpb25zOiB7IGJvbGQ6IHRydWUsIGNvbG9yOiAnRkZGRkZGJywgZmlsbDogeyBjb2xvcjogJzRFNzlBNycgfSB9LFxuICAgIH0pKTtcblxuICAgIGNvbnN0IGJvZHkgPSByb3dzLm1hcCgocm93KSA9PiBjb2x1bW5zLm1hcCgoY29sdW1uKSA9PiAoe1xuICAgICAgdGV4dDogdGhpcy5fY2VsbChyb3dbY29sdW1uLmNvbHVtbl0sIGNvbHVtbi5mb3JtYXQpLFxuICAgICAgb3B0aW9uczoge30sXG4gICAgfSkpKTtcblxuICAgIGlmIChyZW1haW5pbmcgPiAwKSB7XG4gICAgICBib2R5LnB1c2goW3tcbiAgICAgICAgdGV4dDogYOKApiAke3JlbWFpbmluZ30gbW9yZSByb3cocykg4oCUIHVzZSB0aGUgY29tcG9uZW50J3MgQ1NWIGV4cG9ydCBmb3IgdGhlIGZ1bGwgZGF0YXNldGAsXG4gICAgICAgIG9wdGlvbnM6IHsgY29sc3BhbjogY29sdW1ucy5sZW5ndGgsIGl0YWxpYzogdHJ1ZSwgY29sb3I6ICc3Qjg3OTQnIH0gYXMgYW55LFxuICAgICAgfV0pO1xuICAgIH1cblxuICAgIHNsaWRlLmFkZFRhYmxlKFtoZWFkZXIsIC4uLmJvZHldLCB7XG4gICAgICB4LCB5LCB3LFxuICAgICAgZm9udFNpemU6IDksXG4gICAgICBjb2xvcjogJzFGMjkzMycsXG4gICAgICBib3JkZXI6IHsgdHlwZTogJ3NvbGlkJywgcHQ6IDAuNSwgY29sb3I6ICdFNEU3RUInIH0sXG4gICAgICBhdXRvUGFnZTogZmFsc2UsXG4gICAgICByb3dIOiBUQUJMRV9ST1dfSCxcbiAgICAgIHZhbGlnbjogJ21pZGRsZScsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9yZW5kZXJLcGkoXG4gICAgc2xpZGU6IGFueSxcbiAgICBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudCxcbiAgICBkYXRhOiBDb21wb25lbnREYXRhLFxuICAgIHg6IG51bWJlciwgeTogbnVtYmVyLCB3OiBudW1iZXIsIGg6IG51bWJlcixcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gY29tcG9uZW50LmNvbmZpZyBhcyBLcGlDb25maWc7XG4gICAgY29uc3Qgcm93ID0gZGF0YS5yb3dzWzBdID8/IHt9O1xuICAgIGNvbnN0IGNvbHVtbiA9IGNvbmZpZy5tZWFzdXJlPy5jb2x1bW4gPz8gT2JqZWN0LmtleXMocm93KVswXTtcbiAgICBjb25zdCB2YWx1ZSA9IGZvcm1hdE1lYXN1cmVWYWx1ZShyb3dbY29sdW1uXSwgY29uZmlnLm1lYXN1cmU/LmZvcm1hdCk7XG5cbiAgICBzbGlkZS5hZGRUZXh0KFtcbiAgICAgIHsgdGV4dDogdmFsdWUsIG9wdGlvbnM6IHsgZm9udFNpemU6IDI4LCBib2xkOiB0cnVlLCBjb2xvcjogJzFGMjkzMycsIGJyZWFrTGluZTogdHJ1ZSB9IH0sXG4gICAgICB7IHRleHQ6IGNvbmZpZy5tZWFzdXJlPy5sYWJlbCA/PyAnJywgb3B0aW9uczogeyBmb250U2l6ZTogMTAsIGNvbG9yOiAnN0I4Nzk0JyB9IH0sXG4gICAgXSwge1xuICAgICAgeCwgeSwgdywgaCxcbiAgICAgIGFsaWduOiAnY2VudGVyJyxcbiAgICAgIHZhbGlnbjogJ21pZGRsZScsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9jZWxsKHZhbHVlOiB1bmtub3duLCBjb2x1bW5Gb3JtYXQ/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgaWYgKGNvbHVtbkZvcm1hdCA9PT0gJ2RhdGUnKSB7XG4gICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoU3RyaW5nKHZhbHVlKSk7XG5cbiAgICAgIHJldHVybiBOdW1iZXIuaXNOYU4oZGF0ZS5nZXRUaW1lKCkpID8gU3RyaW5nKHZhbHVlKSA6IGZvcm1hdChkYXRlLCAnTU1NIGQsIHl5eXknKTtcbiAgICB9XG5cbiAgICBpZiAoY29sdW1uRm9ybWF0ID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIGZvcm1hdE1lYXN1cmVWYWx1ZSh2YWx1ZSwgJ251bWJlcicpO1xuICAgIH1cblxuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2x1ZyhuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuYW1lLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvW15hLXowLTldKy9nLCAnLScpLnJlcGxhY2UoL14tK3wtKyQvZywgJycpIHx8ICdyZXBvcnQnO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Measure-value formatting shared by the KPI renderer and the exports — the
|
|
2
|
+
// config's `format` (number | percent | currency) means the same thing on
|
|
3
|
+
// screen, in PowerPoint and in PDF.
|
|
4
|
+
export function formatMeasureValue(value, format) {
|
|
5
|
+
if (value === null || value === undefined || value === '') {
|
|
6
|
+
return '—';
|
|
7
|
+
}
|
|
8
|
+
const numeric = Number(value);
|
|
9
|
+
if (!Number.isFinite(numeric)) {
|
|
10
|
+
return String(value);
|
|
11
|
+
}
|
|
12
|
+
switch (format) {
|
|
13
|
+
case 'percent':
|
|
14
|
+
return `${new Intl.NumberFormat().format(numeric)}%`;
|
|
15
|
+
case 'currency':
|
|
16
|
+
return new Intl.NumberFormat(undefined, {
|
|
17
|
+
style: 'currency',
|
|
18
|
+
currency: 'USD',
|
|
19
|
+
maximumFractionDigits: 0,
|
|
20
|
+
}).format(numeric);
|
|
21
|
+
default:
|
|
22
|
+
return new Intl.NumberFormat().format(numeric);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2Zvcm1hdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw0RUFBNEU7QUFDNUUsMEVBQTBFO0FBQzFFLG9DQUFvQztBQUNwQyxNQUFNLFVBQVUsa0JBQWtCLENBQUMsS0FBYyxFQUFFLE1BQWU7SUFDaEUsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQzFELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQzlCLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxRQUFRLE1BQU0sRUFBRSxDQUFDO1FBQ2YsS0FBSyxTQUFTO1lBQ1osT0FBTyxHQUFHLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ3ZELEtBQUssVUFBVTtZQUNiLE9BQU8sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRTtnQkFDdEMsS0FBSyxFQUFFLFVBQVU7Z0JBQ2pCLFFBQVEsRUFBRSxLQUFLO2dCQUNmLHFCQUFxQixFQUFFLENBQUM7YUFDekIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNyQjtZQUNFLE9BQU8sSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ25ELENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVhc3VyZS12YWx1ZSBmb3JtYXR0aW5nIHNoYXJlZCBieSB0aGUgS1BJIHJlbmRlcmVyIGFuZCB0aGUgZXhwb3J0cyDigJQgdGhlXG4vLyBjb25maWcncyBgZm9ybWF0YCAobnVtYmVyIHwgcGVyY2VudCB8IGN1cnJlbmN5KSBtZWFucyB0aGUgc2FtZSB0aGluZyBvblxuLy8gc2NyZWVuLCBpbiBQb3dlclBvaW50IGFuZCBpbiBQREYuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0TWVhc3VyZVZhbHVlKHZhbHVlOiB1bmtub3duLCBmb3JtYXQ/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICByZXR1cm4gJ+KAlCc7XG4gIH1cblxuICBjb25zdCBudW1lcmljID0gTnVtYmVyKHZhbHVlKTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUobnVtZXJpYykpIHtcbiAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgY2FzZSAncGVyY2VudCc6XG4gICAgICByZXR1cm4gYCR7bmV3IEludGwuTnVtYmVyRm9ybWF0KCkuZm9ybWF0KG51bWVyaWMpfSVgO1xuICAgIGNhc2UgJ2N1cnJlbmN5JzpcbiAgICAgIHJldHVybiBuZXcgSW50bC5OdW1iZXJGb3JtYXQodW5kZWZpbmVkLCB7XG4gICAgICAgIHN0eWxlOiAnY3VycmVuY3knLFxuICAgICAgICBjdXJyZW5jeTogJ1VTRCcsXG4gICAgICAgIG1heGltdW1GcmFjdGlvbkRpZ2l0czogMCxcbiAgICAgIH0pLmZvcm1hdChudW1lcmljKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIG5ldyBJbnRsLk51bWJlckZvcm1hdCgpLmZvcm1hdChudW1lcmljKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// The assembled report structure returned by GET /api/reports/:id — composed
|
|
2
|
+
// server-side from the normalized tables (reports → report_pages →
|
|
3
|
+
// report_components + report_filters, plus report_filter_groups). All keys are
|
|
4
|
+
// camelCase; component `config` is the standard format the renderer maps to
|
|
5
|
+
// ECharts options / FsList config.
|
|
6
|
+
// The runtime Frequency control's choices — re-buckets every time-series chart
|
|
7
|
+
// at view time, overriding each chart's authored granularity. 'year' reads as
|
|
8
|
+
// "Annually" in the control.
|
|
9
|
+
export const FREQUENCY_OPTIONS = [
|
|
10
|
+
{ value: 'day', name: 'Day' },
|
|
11
|
+
{ value: 'week', name: 'Week' },
|
|
12
|
+
{ value: 'month', name: 'Month' },
|
|
13
|
+
{ value: 'quarter', name: 'Quarter' },
|
|
14
|
+
{ value: 'year', name: 'Annually' },
|
|
15
|
+
];
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LmludGVyZmFjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNkVBQTZFO0FBQzdFLG1FQUFtRTtBQUNuRSwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLG1DQUFtQztBQXdGbkMsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw2QkFBNkI7QUFDN0IsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQWdEO0lBQzVFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFO0lBQzdCLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFO0lBQy9CLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0lBQ2pDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO0lBQ3JDLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO0NBQ3BDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgYXNzZW1ibGVkIHJlcG9ydCBzdHJ1Y3R1cmUgcmV0dXJuZWQgYnkgR0VUIC9hcGkvcmVwb3J0cy86aWQg4oCUIGNvbXBvc2VkXG4vLyBzZXJ2ZXItc2lkZSBmcm9tIHRoZSBub3JtYWxpemVkIHRhYmxlcyAocmVwb3J0cyDihpIgcmVwb3J0X3BhZ2VzIOKGklxuLy8gcmVwb3J0X2NvbXBvbmVudHMgKyByZXBvcnRfZmlsdGVycywgcGx1cyByZXBvcnRfZmlsdGVyX2dyb3VwcykuIEFsbCBrZXlzIGFyZVxuLy8gY2FtZWxDYXNlOyBjb21wb25lbnQgYGNvbmZpZ2AgaXMgdGhlIHN0YW5kYXJkIGZvcm1hdCB0aGUgcmVuZGVyZXIgbWFwcyB0b1xuLy8gRUNoYXJ0cyBvcHRpb25zIC8gRnNMaXN0IGNvbmZpZy5cblxuLy8gTGF5b3V0IG1vZGVzOiBGcmVlZm9ybSA9IGFic29sdXRlbHkgcG9zaXRpb25lZCBjb21wb25lbnRzIChkcmFnIGFueXdoZXJlKTtcbi8vIEZsb3cgPSBjb21wb25lbnRzIGZsb3cgbGlrZSByb3dzLCBlYWNoIHRha2luZyBmbG93V2lkdGggJSBvZiB0aGUgcGFnZSB3aWR0aC5cbmV4cG9ydCB0eXBlIFJlcG9ydExheW91dCA9ICdmcmVlZm9ybScgfCAnZmxvdyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0IHtcbiAgaWQ6IG51bWJlcjtcbiAgbmFtZTogc3RyaW5nO1xuICBwYWdlU2l6ZTogJ3dpZGVzY3JlZW4nIHwgJ2xldHRlcic7XG4gIHBhZ2VPcmllbnRhdGlvbjogJ2xhbmRzY2FwZScgfCAncG9ydHJhaXQnO1xuICBsYXlvdXQ6IFJlcG9ydExheW91dDtcbiAgLy8gSUFOQSB0aW1lem9uZSAoZS5nLiBBbWVyaWNhL05ld19Zb3JrKSBhbmNob3JpbmcgZGF0ZSBmaWx0ZXJpbmcgKyBjaGFydCBkYXRlXG4gIC8vIGJ1Y2tldGluZy4gbnVsbCBmYWxscyBiYWNrIHRvIHRoZSBhY2NvdW50IHpvbmUgdGhlbiBVVEMgKHJlc29sdmVkIHNlcnZlci1zaWRlKS5cbiAgdGltZXpvbmU6IHN0cmluZyB8IG51bGw7XG4gIC8vIFJlcG9ydC1sZXZlbCBjb25maWc6IHR5cG9ncmFwaGljIHN0eWxlcywgZXRjLiAoY2FtZWxDYXNlIEpTT04gY29sdW1uKS5cbiAgY29uZmlnOiBSZXBvcnRDb25maWc7XG4gIC8vIENhbnZhcyBkaW1lbnNpb25zIGluIElOQ0hFUyAodGhlIHJlcG9ydCdzIG5hdGl2ZSB1bml0IOKAlCBQREZzIGFuZFxuICAvLyBQb3dlclBvaW50IGFyZSBpbmNoLWJhc2VkLCBzbyBleHBvcnRzIGFyZSBkaW1lbnNpb25hbGx5IGV4YWN0KS5cbiAgcGFnZVdpZHRoOiBudW1iZXI7XG4gIHBhZ2VIZWlnaHQ6IG51bWJlcjtcbiAgcGFnZXM6IFJlcG9ydFBhZ2VbXTtcbiAgZmlsdGVyR3JvdXBzOiBSZXBvcnRGaWx0ZXJHcm91cFtdO1xufVxuXG4vLyBSZXBvcnQtbGV2ZWwgc3R5bGluZy4gU2l6ZXMgYXJlIGluIFBPSU5UUyAoMS83MlwiKSDigJQgdGhlIHJlcG9ydCdzIHR5cG9ncmFwaHlcbi8vIG1hcHMgMToxIHRvIFBERiAoNzJwdC9pbikgYW5kIFBvd2VyUG9pbnQgKHBvaW50IGZvbnQgc2l6ZXMpLCBzbyBhIHBvaW50XG4vLyB2YWx1ZSBpcyBkaW1lbnNpb25hbGx5IGV4YWN0IG9uIHNjcmVlbiBhbmQgaW4gZXZlcnkgZXhwb3J0LlxuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRDb25maWcge1xuICBzdHlsZXM/OiBSZXBvcnRTdHlsZXM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0U3R5bGVzIHtcbiAgaGVhZGluZz86IHsgc2l6ZT86IG51bWJlciB9O1xufVxuXG4vLyBDb250ZW50IHBhZGRpbmcgYXJvdW5kIGEgY29tcG9uZW50J3MgYm9keSwgaW4gSU5DSEVTICh0aGUgZ2VvbWV0cnkgdW5pdCkuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudFBhZGRpbmcge1xuICB0b3A/OiBudW1iZXI7XG4gIHJpZ2h0PzogbnVtYmVyO1xuICBib3R0b20/OiBudW1iZXI7XG4gIGxlZnQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0UGFnZSB7XG4gIGlkOiBudW1iZXI7XG4gIG5hbWU6IHN0cmluZyB8IG51bGw7XG4gIG9yZGVyOiBudW1iZXI7XG4gIGNvbXBvbmVudHM6IFJlcG9ydENvbXBvbmVudFtdO1xufVxuXG5leHBvcnQgdHlwZSBSZXBvcnRDb21wb25lbnRUeXBlID0gJ2NoYXJ0JyB8ICdsaXN0JyB8ICdrcGknO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydENvbXBvbmVudCB7XG4gIGlkOiBudW1iZXI7XG4gIHR5cGU6IFJlcG9ydENvbXBvbmVudFR5cGU7XG4gIHRpdGxlOiBzdHJpbmcgfCBudWxsO1xuICAvLyBHZW9tZXRyeSBpbiBJTkNIRVMuIEZyZWVmb3JtOiBhYnNvbHV0ZSBwb3NpdGlvbiBvbiB0aGUgcGFnZSBjYW52YXMuXG4gIC8vIEZsb3c6IG9ubHkgZmxvd1dpZHRoL29yZGVyIGFwcGx5OyB4L3kgYXJlIHJlbWVtYmVyZWQgZm9yIGEgc3dpdGNoIGJhY2sgdG9cbiAgLy8gZnJlZWZvcm0uXG4gIHg6IG51bWJlcjtcbiAgeTogbnVtYmVyO1xuICB3OiBudW1iZXI7XG4gIGg6IG51bWJlcjtcbiAgLy8gSGVpZ2h0IG1vZGUsIERFUklWRUQgZnJvbSB0eXBlIHNlcnZlci1zaWRlIChub3Qgc3RvcmVkLCByZWFkLW9ubHkpOiBsaXN0c1xuICAvLyBhbmQgS1BJIHRpbGVzIGFyZSBhdXRvICh0aGUgYm94IHNpemVzIHRvIGl0cyBjb250ZW50LCBgaGAgaWdub3JlZCk7IGNoYXJ0c1xuICAvLyBhcmUgYWx3YXlzIGZpeGVkICh1c2UgYGhgKSBzbyB0aGV5IGZpdCB0aGUgYm94IGFuZCBuZXZlciBvdmVyZmxvdy5cbiAgYXV0b0hlaWdodDogYm9vbGVhbjtcbiAgLy8gRmxvdyBsYXlvdXQ6ICUgb2YgdGhlIHBhZ2UgY29udGVudCB3aWR0aCB0aGlzIGNvbXBvbmVudCB0YWtlcy5cbiAgZmxvd1dpZHRoOiBudW1iZXI7XG4gIC8vIEZsb3cgbGF5b3V0IG9yZGVyaW5nLlxuICBvcmRlcjogbnVtYmVyO1xuICBzcWw6IHN0cmluZyB8IG51bGw7XG4gIGNvbmZpZzogQ2hhcnRDb25maWcgJiBMaXN0Q29uZmlnICYgS3BpQ29uZmlnICYgQ29tcG9uZW50TGF5b3V0Q29uZmlnICYgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGZpbHRlcnM6IFJlcG9ydEZpbHRlcltdO1xufVxuXG4vLyBDcm9zcy10eXBlIGxheW91dC9zdHlsZSBrZXlzIGNhcnJpZWQgaW4gYSBjb21wb25lbnQncyBjb25maWcgKGFsb25nc2lkZSB0aGVcbi8vIHR5cGUtc3BlY2lmaWMgY2hhcnQvbGlzdC9rcGkga2V5cykuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudExheW91dENvbmZpZyB7XG4gIHBhZGRpbmc/OiBDb21wb25lbnRQYWRkaW5nO1xufVxuXG4vLyBXaGVyZSBhIGNoYXJ0J3MgbGVnZW5kIHNpdHMgcmVsYXRpdmUgdG8gdGhlIHBsb3QsIG9yICdoaWRkZW4nIHRvIGRyb3AgaXQuXG5leHBvcnQgdHlwZSBMZWdlbmRQb3NpdGlvbiA9ICd0b3AnIHwgJ2JvdHRvbScgfCAnbGVmdCcgfCAncmlnaHQnIHwgJ2hpZGRlbic7XG5cbmV4cG9ydCB0eXBlIENoYXJ0R3JhbnVsYXJpdHkgPSAnZGF5JyB8ICd3ZWVrJyB8ICdtb250aCcgfCAncXVhcnRlcicgfCAneWVhcic7XG5cbi8vIFRoZSBydW50aW1lIEZyZXF1ZW5jeSBjb250cm9sJ3MgY2hvaWNlcyDigJQgcmUtYnVja2V0cyBldmVyeSB0aW1lLXNlcmllcyBjaGFydFxuLy8gYXQgdmlldyB0aW1lLCBvdmVycmlkaW5nIGVhY2ggY2hhcnQncyBhdXRob3JlZCBncmFudWxhcml0eS4gJ3llYXInIHJlYWRzIGFzXG4vLyBcIkFubnVhbGx5XCIgaW4gdGhlIGNvbnRyb2wuXG5leHBvcnQgY29uc3QgRlJFUVVFTkNZX09QVElPTlM6IHsgdmFsdWU6IENoYXJ0R3JhbnVsYXJpdHk7IG5hbWU6IHN0cmluZyB9W10gPSBbXG4gIHsgdmFsdWU6ICdkYXknLCBuYW1lOiAnRGF5JyB9LFxuICB7IHZhbHVlOiAnd2VlaycsIG5hbWU6ICdXZWVrJyB9LFxuICB7IHZhbHVlOiAnbW9udGgnLCBuYW1lOiAnTW9udGgnIH0sXG4gIHsgdmFsdWU6ICdxdWFydGVyJywgbmFtZTogJ1F1YXJ0ZXInIH0sXG4gIHsgdmFsdWU6ICd5ZWFyJywgbmFtZTogJ0FubnVhbGx5JyB9LFxuXTtcblxuZXhwb3J0IGludGVyZmFjZSBDaGFydENvbmZpZyB7XG4gIGNoYXJ0VHlwZT86ICdiYXInIHwgJ2xpbmUnIHwgJ2FyZWEnIHwgJ3BpZScgfCAnZG9udXQnO1xuICAvLyBGb3Iga2luZCAndGltZScsIHRoZSBzZXJ2ZXIgYnVja2V0cyB0aGUgcmF3IGRhdGV0aW1lIGNvbHVtbiB0byBgZ3JhbnVsYXJpdHlgXG4gIC8vIGluIHRoZSByZXBvcnQncyB0aW1lem9uZSAodGhlIFNRTCBleHBvc2VzIHRoZSByYXcgY29sdW1uLCB1bmJ1Y2tldGVkKS5cbiAgeEF4aXM/OiB7IGNvbHVtbjogc3RyaW5nOyBraW5kPzogJ2NhdGVnb3J5JyB8ICd0aW1lJzsgZ3JhbnVsYXJpdHk/OiBDaGFydEdyYW51bGFyaXR5OyBsYWJlbD86IHN0cmluZyB9O1xuICBtZWFzdXJlcz86IENoYXJ0TWVhc3VyZVtdO1xuICBzcGxpdEJ5PzogeyBjb2x1bW46IHN0cmluZzsgbGFiZWw/OiBzdHJpbmcgfTtcbiAgLy8gU2luZ2xlLWRpbWVuc2lvbiBiYXIgY2hhcnRzIG9ubHk6IGNvbG9yIGVhY2ggYmFyIGJ5IGl0cyBvd24gY2F0ZWdvcnkgYW5kXG4gIC8vIHNob3cgYSBsZWdlbmQsIFdJVEhPVVQgc3BsaXR0aW5nIGludG8gbXVsdGlwbGUgc2VyaWVzICh3aGljaCBzbGl2ZXJzIHRoZVxuICAvLyBiYXJzKS4gdjEgZXhwZWN0cyBjb2xvckJ5LmNvbHVtbiA9PT0geEF4aXMuY29sdW1uLiBJZ25vcmVkIHdoZW4gc3BsaXRCeSBpc1xuICAvLyBzZXQgb3IgdGhlIGNoYXJ0IGlzbid0IGEgYmFyIGNoYXJ0LlxuICBjb2xvckJ5PzogeyBjb2x1bW46IHN0cmluZzsgbGFiZWw/OiBzdHJpbmcgfTtcbiAgb3JpZW50YXRpb24/OiAndmVydGljYWwnIHwgJ2hvcml6b250YWwnO1xuICBzdGFja2VkPzogYm9vbGVhbjtcbiAgbGVnZW5kPzogTGVnZW5kUG9zaXRpb247XG4gIHNvcnQ/OiBSZXBvcnRTb3J0O1xuICBsaW1pdD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDaGFydE1lYXN1cmUge1xuICBjb2x1bW46IHN0cmluZztcbiAgYWdncmVnYXRpb24/OiAnc3VtJyB8ICdjb3VudCcgfCAnYXZnJyB8ICdtaW4nIHwgJ21heCc7XG4gIGxhYmVsPzogc3RyaW5nO1xuICBmb3JtYXQ/OiAnbnVtYmVyJyB8ICdwZXJjZW50JyB8ICdjdXJyZW5jeSc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlzdENvbmZpZyB7XG4gIGNvbHVtbnM/OiB7IGNvbHVtbjogc3RyaW5nOyBsYWJlbD86IHN0cmluZzsgZm9ybWF0PzogJ2RhdGUnIHwgJ251bWJlcicgfVtdO1xuICBzb3J0PzogUmVwb3J0U29ydDtcbiAgcGFnZVNpemU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgS3BpQ29uZmlnIHtcbiAgbWVhc3VyZT86IENoYXJ0TWVhc3VyZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRTb3J0IHtcbiAgY29sdW1uOiBzdHJpbmc7XG4gIGRpcmVjdGlvbj86ICdhc2MnIHwgJ2Rlc2MnO1xufVxuXG5leHBvcnQgdHlwZSBSZXBvcnRGaWx0ZXJUeXBlID0gJ2RhdGVSYW5nZScgfCAnc2VsZWN0JyB8ICdrZXl3b3JkJztcblxuLy8gV2hlcmUgYSBmaWx0ZXIgZ3JvdXAncyBjb250cm9sIGlzIGV4cG9zZWQuIEEgZ3JvdXAgY2FuIGJlIHNob3duIG9uIGl0c1xuLy8gY29tcG9uZW50cywgaW4gdGhlIHJlcG9ydCBiYXIsIG9yIEJPVEggYXQgb25jZSAodGhlIHR3byBhcmUgaW5kZXBlbmRlbnRcbi8vIHRvZ2dsZXMgaW4gdGhlIFVJKTsgYSBjb2x1bW4gd2l0aCBuZWl0aGVyIGV4cG9zZWQgc2ltcGx5IGhhcyBubyBmaWx0ZXIuXG5leHBvcnQgdHlwZSBSZXBvcnRGaWx0ZXJMZXZlbCA9ICdjb21wb25lbnQnIHwgJ3JlcG9ydCcgfCAnYm90aCc7XG5cbi8vIE9uZSBmaWx0ZXJhYmxlIG91dHB1dCBjb2x1bW4gb2YgYSBjb21wb25lbnQncyBTUUwsIHdpdGggdGhlIGZpbHRlciBpbnRlcmZhY2Vcbi8vIElORkVSUkVEIGZyb20gaXRzIGRhdGEgKHRoZSBodW1hbiBuZXZlciBwaWNrcyB0aGUgaW50ZXJmYWNlIOKAlCBpdCBmb2xsb3dzIHRoZVxuLy8gY29sdW1uJ3MgdHlwZSkuIERyaXZlcyB0aGUgRmlsdGVycyB0YWIgbGlzdGluZy5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0RmlsdGVyYWJsZUNvbHVtbiB7XG4gIGNvbHVtbjogc3RyaW5nO1xuICB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlO1xufVxuXG4vLyBHcm91bmQgdHJ1dGg6IG9uZSBmaWx0ZXJhYmxlIG91dHB1dCBjb2x1bW4gT04gb25lIGNvbXBvbmVudCdzIFNRTC4gQWx3YXlzIGFcbi8vIG1lbWJlciBvZiBhIGZpbHRlciBncm91cCDigJQgdGhlIHVuaXQgdGhhdCBsaW5rcyBlcXVpdmFsZW50IGZpbHRlcnMgYWNyb3NzXG4vLyBjb21wb25lbnRzIGFuZCBkZWNpZGVzIHdoZXJlIHRoZSBjb250cm9sIHJlbmRlcnMgKGNvbXBvbmVudCB2cyByZXBvcnQgYmFyKS5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0RmlsdGVyIHtcbiAgaWQ6IG51bWJlcjtcbiAgY29tcG9uZW50SWQ6IG51bWJlcjtcbiAgZmlsdGVyR3JvdXBJZDogbnVtYmVyO1xuICBmaWx0ZXJDb2x1bW46IHN0cmluZztcbiAgbGFiZWw6IHN0cmluZyB8IG51bGw7XG4gIGVuYWJsZWQ6IGJvb2xlYW47XG4gIGhhc09wdGlvbnM6IGJvb2xlYW47XG4gIGNvbmZpZzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0RmlsdGVyR3JvdXAge1xuICBpZDogbnVtYmVyO1xuICBsYWJlbDogc3RyaW5nIHwgbnVsbDtcbiAgdHlwZTogUmVwb3J0RmlsdGVyVHlwZTtcbiAgbGV2ZWw6IFJlcG9ydEZpbHRlckxldmVsO1xuICBvcmRlcjogbnVtYmVyO1xuICBjb25maWc6IHsgZGVmYXVsdD86IEZpbHRlckdyb3VwRGVmYXVsdCB9ICYgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGZpbHRlcnM6IFJlcG9ydEZpbHRlcltdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbHRlckdyb3VwRGVmYXVsdCB7XG4gIHJlbGF0aXZlPzogc3RyaW5nOyAvLyBlLmcuIGxhc3QxMk1vbnRocywgbGFzdDMwRGF5cywgeWVhclRvRGF0ZVxuICBzdGFydD86IHN0cmluZztcbiAgZW5kPzogc3RyaW5nO1xufVxuXG4vLyBUaGUgc2Vzc2lvbiB2YWx1ZSBvZiBhIGZpbHRlciBncm91cCAobmV2ZXIgcGVyc2lzdGVkKTogc2hhcGUgZGVwZW5kcyBvbiB0aGVcbi8vIGdyb3VwJ3MgdHlwZS5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsdGVyR3JvdXBWYWx1ZSB7XG4gIHN0YXJ0PzogRGF0ZSB8IHN0cmluZyB8IG51bGw7IC8vIGRhdGVSYW5nZVxuICBlbmQ/OiBEYXRlIHwgc3RyaW5nIHwgbnVsbDsgLy8gZGF0ZVJhbmdlXG4gIHZhbHVlcz86IHVua25vd25bXTsgLy8gc2VsZWN0XG4gIHZhbHVlPzogc3RyaW5nOyAvLyBrZXl3b3JkXG59XG5cbi8vIE9uZSByZXNvbHZlZCBmaWx0ZXIgc2VudCB3aXRoIGEgY29tcG9uZW50J3MgZGF0YSByZXF1ZXN0LlxuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZEZpbHRlclZhbHVlIHtcbiAgZmlsdGVySWQ6IG51bWJlcjtcbiAgc3RhcnQ/OiBzdHJpbmc7XG4gIGVuZD86IHN0cmluZztcbiAgdmFsdWVzPzogdW5rbm93bltdO1xuICB2YWx1ZT86IHN0cmluZztcbn1cblxuLy8gUGVyLWNvbXBvbmVudCBpbnRlcmFjdGlvbiBzdGF0ZSBzZW50IHdpdGggdGhlIGRhdGEgcmVxdWVzdDogbGlzdHMgc2VuZFxuLy8gc29ydC9wYWdpbmc7IHRpbWUtc2VyaWVzIGNoYXJ0cyBzZW5kIHRoZSB2aWV3ZXIncyBjaG9zZW4gRnJlcXVlbmN5LCB3aGljaFxuLy8gb3ZlcnJpZGVzIHRoZSBhdXRob3JlZCBncmFudWxhcml0eSBmb3IgdGhhdCByZXF1ZXN0IG9ubHkuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudERhdGFTdGF0ZSB7XG4gIHNvcnQ/OiBSZXBvcnRTb3J0O1xuICBwYWdlPzogbnVtYmVyO1xuICBwYWdlU2l6ZT86IG51bWJlcjtcbiAgZnJlcXVlbmN5PzogQ2hhcnRHcmFudWxhcml0eTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21wb25lbnREYXRhIHtcbiAgY29sdW1uczogc3RyaW5nW107XG4gIHJvd3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG4gIHBhZ2luZz86IHsgdG90YWw6IG51bWJlcjsgcGFnZTogbnVtYmVyOyBwYWdlU2l6ZTogbnVtYmVyIH07XG4gIHRydW5jYXRlZDogYm9vbGVhbjtcbiAgLy8gVGhlIGVmZmVjdGl2ZSB0aW1lIGJ1Y2tldCB0aGUgcm93cyB3ZXJlIGdyb3VwZWQgaW50byAoYWZ0ZXIgYW55IEZyZXF1ZW5jeVxuICAvLyBvdmVycmlkZSksIG9yIG51bGwgZm9yIGEgbm9uLXRpbWUgYXhpcy4gRHJpdmVzIHRoZSBjb21wYWN0IHgtYXhpcyBsYWJlbHMuXG4gIGdyYW51bGFyaXR5PzogQ2hhcnRHcmFudWxhcml0eSB8IG51bGw7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0TGlzdEl0ZW0ge1xuICBpZDogbnVtYmVyO1xuICBuYW1lOiBzdHJpbmc7XG59XG5cbi8vIFRoZSBjaGF0IHR1cm4gZmxhZ3MgdGhpcyBjb250ZXh0J3MgYmFja2VuZCBhZGRzIChSZXBvcnRzXFxBaVZpZXcpLlxuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRDaGF0UmVzcG9uc2Uge1xuICByZXBvcnRDaGFuZ2VkPzogYm9vbGVhbjtcbiAgcmVwb3J0UmVuYW1lZD86IGJvb2xlYW47XG59XG4iXX0=
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Page padding for flow layout, inches — mirrored by the canvas CSS.
|
|
2
|
+
export const FLOW_PADDING = 0.25;
|
|
3
|
+
// Default content padding around a component's body, inches (1/8").
|
|
4
|
+
export const DEFAULT_COMPONENT_PADDING = 0.125;
|
|
5
|
+
// Default report heading size, points (1/72"). Applies to component titles.
|
|
6
|
+
export const DEFAULT_HEADING_SIZE = 16;
|
|
7
|
+
// Resolved geometry (inches) for every component on a page, in BOTH layout
|
|
8
|
+
// modes — the single definition the PPT and PDF exports lay out from:
|
|
9
|
+
//
|
|
10
|
+
// Freeform: the stored x/y/w/h verbatim.
|
|
11
|
+
// Flow: components in `order`, each flowWidth% of the content width,
|
|
12
|
+
// wrapping into rows (a row breaks when the next component would
|
|
13
|
+
// exceed 100%); row height = the tallest component in the row.
|
|
14
|
+
// Matches the canvas's flex-wrap rendering.
|
|
15
|
+
export function pageGeometry(report, page) {
|
|
16
|
+
const geometry = new Map();
|
|
17
|
+
if (report.layout !== 'flow') {
|
|
18
|
+
for (const component of page.components) {
|
|
19
|
+
geometry.set(component.id, {
|
|
20
|
+
x: component.x, y: component.y, w: component.w, h: component.h,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return geometry;
|
|
24
|
+
}
|
|
25
|
+
const contentW = report.pageWidth - FLOW_PADDING * 2;
|
|
26
|
+
const sorted = [...page.components].sort((a, b) => (a.order - b.order) || (a.y - b.y) || (a.x - b.x));
|
|
27
|
+
let cursorX = 0; // fraction of contentW consumed in the current row
|
|
28
|
+
let rowTop = FLOW_PADDING;
|
|
29
|
+
let rowHeight = 0;
|
|
30
|
+
for (const component of sorted) {
|
|
31
|
+
const fraction = Math.min(100, Math.max(10, component.flowWidth ?? 50)) / 100;
|
|
32
|
+
// Wrap when this component doesn't fit the remainder (small tolerance for
|
|
33
|
+
// 33.33+33.33+33.33 style splits).
|
|
34
|
+
if (cursorX + fraction > 1.001) {
|
|
35
|
+
rowTop += rowHeight;
|
|
36
|
+
cursorX = 0;
|
|
37
|
+
rowHeight = 0;
|
|
38
|
+
}
|
|
39
|
+
geometry.set(component.id, {
|
|
40
|
+
x: FLOW_PADDING + cursorX * contentW,
|
|
41
|
+
y: rowTop,
|
|
42
|
+
w: fraction * contentW,
|
|
43
|
+
h: component.h,
|
|
44
|
+
});
|
|
45
|
+
cursorX += fraction;
|
|
46
|
+
rowHeight = Math.max(rowHeight, component.h);
|
|
47
|
+
}
|
|
48
|
+
return geometry;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2xheW91dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxxRUFBcUU7QUFDckUsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQztBQUVqQyxvRUFBb0U7QUFDcEUsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsS0FBSyxDQUFDO0FBRS9DLDRFQUE0RTtBQUM1RSxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUM7QUFTdkMsMkVBQTJFO0FBQzNFLHNFQUFzRTtBQUN0RSxFQUFFO0FBQ0YsMkNBQTJDO0FBQzNDLDJFQUEyRTtBQUMzRSw2RUFBNkU7QUFDN0UsMkVBQTJFO0FBQzNFLHdEQUF3RDtBQUN4RCxNQUFNLFVBQVUsWUFBWSxDQUFDLE1BQWMsRUFBRSxJQUFnQjtJQUMzRCxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBNkIsQ0FBQztJQUV0RCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssTUFBTSxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDeEMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFO2dCQUN6QixDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUM7YUFDL0QsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsU0FBUyxHQUFHLFlBQVksR0FBRyxDQUFDLENBQUM7SUFDckQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXRHLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLG1EQUFtRDtJQUNwRSxJQUFJLE1BQU0sR0FBRyxZQUFZLENBQUM7SUFDMUIsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBRWxCLEtBQUssTUFBTSxTQUFTLElBQUksTUFBTSxFQUFFLENBQUM7UUFDL0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsU0FBUyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztRQUU5RSwwRUFBMEU7UUFDMUUsbUNBQW1DO1FBQ25DLElBQUksT0FBTyxHQUFHLFFBQVEsR0FBRyxLQUFLLEVBQUUsQ0FBQztZQUMvQixNQUFNLElBQUksU0FBUyxDQUFDO1lBQ3BCLE9BQU8sR0FBRyxDQUFDLENBQUM7WUFDWixTQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLENBQUM7UUFFRCxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUU7WUFDekIsQ0FBQyxFQUFFLFlBQVksR0FBRyxPQUFPLEdBQUcsUUFBUTtZQUNwQyxDQUFDLEVBQUUsTUFBTTtZQUNULENBQUMsRUFBRSxRQUFRLEdBQUcsUUFBUTtZQUN0QixDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUM7U0FDZixDQUFDLENBQUM7UUFFSCxPQUFPLElBQUksUUFBUSxDQUFDO1FBQ3BCLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSZXBvcnQsIFJlcG9ydENvbXBvbmVudCwgUmVwb3J0UGFnZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcblxuXG4vLyBQYWdlIHBhZGRpbmcgZm9yIGZsb3cgbGF5b3V0LCBpbmNoZXMg4oCUIG1pcnJvcmVkIGJ5IHRoZSBjYW52YXMgQ1NTLlxuZXhwb3J0IGNvbnN0IEZMT1dfUEFERElORyA9IDAuMjU7XG5cbi8vIERlZmF1bHQgY29udGVudCBwYWRkaW5nIGFyb3VuZCBhIGNvbXBvbmVudCdzIGJvZHksIGluY2hlcyAoMS84XCIpLlxuZXhwb3J0IGNvbnN0IERFRkFVTFRfQ09NUE9ORU5UX1BBRERJTkcgPSAwLjEyNTtcblxuLy8gRGVmYXVsdCByZXBvcnQgaGVhZGluZyBzaXplLCBwb2ludHMgKDEvNzJcIikuIEFwcGxpZXMgdG8gY29tcG9uZW50IHRpdGxlcy5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0hFQURJTkdfU0laRSA9IDE2O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvbmVudEdlb21ldHJ5IHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG4gIHc6IG51bWJlcjtcbiAgaDogbnVtYmVyO1xufVxuXG4vLyBSZXNvbHZlZCBnZW9tZXRyeSAoaW5jaGVzKSBmb3IgZXZlcnkgY29tcG9uZW50IG9uIGEgcGFnZSwgaW4gQk9USCBsYXlvdXRcbi8vIG1vZGVzIOKAlCB0aGUgc2luZ2xlIGRlZmluaXRpb24gdGhlIFBQVCBhbmQgUERGIGV4cG9ydHMgbGF5IG91dCBmcm9tOlxuLy9cbi8vICAgRnJlZWZvcm06IHRoZSBzdG9yZWQgeC95L3cvaCB2ZXJiYXRpbS5cbi8vICAgRmxvdzogICAgIGNvbXBvbmVudHMgaW4gYG9yZGVyYCwgZWFjaCBmbG93V2lkdGglIG9mIHRoZSBjb250ZW50IHdpZHRoLFxuLy8gICAgICAgICAgICAgd3JhcHBpbmcgaW50byByb3dzIChhIHJvdyBicmVha3Mgd2hlbiB0aGUgbmV4dCBjb21wb25lbnQgd291bGRcbi8vICAgICAgICAgICAgIGV4Y2VlZCAxMDAlKTsgcm93IGhlaWdodCA9IHRoZSB0YWxsZXN0IGNvbXBvbmVudCBpbiB0aGUgcm93LlxuLy8gICAgICAgICAgICAgTWF0Y2hlcyB0aGUgY2FudmFzJ3MgZmxleC13cmFwIHJlbmRlcmluZy5cbmV4cG9ydCBmdW5jdGlvbiBwYWdlR2VvbWV0cnkocmVwb3J0OiBSZXBvcnQsIHBhZ2U6IFJlcG9ydFBhZ2UpOiBNYXA8bnVtYmVyLCBDb21wb25lbnRHZW9tZXRyeT4ge1xuICBjb25zdCBnZW9tZXRyeSA9IG5ldyBNYXA8bnVtYmVyLCBDb21wb25lbnRHZW9tZXRyeT4oKTtcblxuICBpZiAocmVwb3J0LmxheW91dCAhPT0gJ2Zsb3cnKSB7XG4gICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGFnZS5jb21wb25lbnRzKSB7XG4gICAgICBnZW9tZXRyeS5zZXQoY29tcG9uZW50LmlkLCB7XG4gICAgICAgIHg6IGNvbXBvbmVudC54LCB5OiBjb21wb25lbnQueSwgdzogY29tcG9uZW50LncsIGg6IGNvbXBvbmVudC5oLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdlb21ldHJ5O1xuICB9XG5cbiAgY29uc3QgY29udGVudFcgPSByZXBvcnQucGFnZVdpZHRoIC0gRkxPV19QQURESU5HICogMjtcbiAgY29uc3Qgc29ydGVkID0gWy4uLnBhZ2UuY29tcG9uZW50c10uc29ydCgoYSwgYikgPT4gKGEub3JkZXIgLSBiLm9yZGVyKSB8fCAoYS55IC0gYi55KSB8fCAoYS54IC0gYi54KSk7XG5cbiAgbGV0IGN1cnNvclggPSAwOyAvLyBmcmFjdGlvbiBvZiBjb250ZW50VyBjb25zdW1lZCBpbiB0aGUgY3VycmVudCByb3dcbiAgbGV0IHJvd1RvcCA9IEZMT1dfUEFERElORztcbiAgbGV0IHJvd0hlaWdodCA9IDA7XG5cbiAgZm9yIChjb25zdCBjb21wb25lbnQgb2Ygc29ydGVkKSB7XG4gICAgY29uc3QgZnJhY3Rpb24gPSBNYXRoLm1pbigxMDAsIE1hdGgubWF4KDEwLCBjb21wb25lbnQuZmxvd1dpZHRoID8/IDUwKSkgLyAxMDA7XG5cbiAgICAvLyBXcmFwIHdoZW4gdGhpcyBjb21wb25lbnQgZG9lc24ndCBmaXQgdGhlIHJlbWFpbmRlciAoc21hbGwgdG9sZXJhbmNlIGZvclxuICAgIC8vIDMzLjMzKzMzLjMzKzMzLjMzIHN0eWxlIHNwbGl0cykuXG4gICAgaWYgKGN1cnNvclggKyBmcmFjdGlvbiA+IDEuMDAxKSB7XG4gICAgICByb3dUb3AgKz0gcm93SGVpZ2h0O1xuICAgICAgY3Vyc29yWCA9IDA7XG4gICAgICByb3dIZWlnaHQgPSAwO1xuICAgIH1cblxuICAgIGdlb21ldHJ5LnNldChjb21wb25lbnQuaWQsIHtcbiAgICAgIHg6IEZMT1dfUEFERElORyArIGN1cnNvclggKiBjb250ZW50VyxcbiAgICAgIHk6IHJvd1RvcCxcbiAgICAgIHc6IGZyYWN0aW9uICogY29udGVudFcsXG4gICAgICBoOiBjb21wb25lbnQuaCxcbiAgICB9KTtcblxuICAgIGN1cnNvclggKz0gZnJhY3Rpb247XG4gICAgcm93SGVpZ2h0ID0gTWF0aC5tYXgocm93SGVpZ2h0LCBjb21wb25lbnQuaCk7XG4gIH1cblxuICByZXR1cm4gZ2VvbWV0cnk7XG59XG4iXX0=
|