ng-zenduit 1.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/README.md +24 -0
- package/esm2020/lib/breadcrumbs/zendu-breadcrumbs.component.mjs +37 -0
- package/esm2020/lib/card-block/zendu-card-block.component.mjs +21 -0
- package/esm2020/lib/checkbox/zendu-checkbox.component.mjs +44 -0
- package/esm2020/lib/colorpicker/zendu-colorpicker.component.mjs +106 -0
- package/esm2020/lib/column-configuration/columnState.mjs +2 -0
- package/esm2020/lib/column-configuration/zendu-column-configuration.component.mjs +118 -0
- package/esm2020/lib/datepicker/date-picker-day.mjs +2 -0
- package/esm2020/lib/datepicker/date-picker-hint.mjs +2 -0
- package/esm2020/lib/datepicker/datepicker.mjs +9 -0
- package/esm2020/lib/datepicker/zendu-datepicker.component.mjs +434 -0
- package/esm2020/lib/doc-scanner/zendu-doc-scanner.component.mjs +628 -0
- package/esm2020/lib/file-upload/zendu-file-upload.component.mjs +107 -0
- package/esm2020/lib/filter/dateRange.mjs +2 -0
- package/esm2020/lib/filter/filtersConfig.mjs +2 -0
- package/esm2020/lib/filter/numberRange.mjs +2 -0
- package/esm2020/lib/filter/zendu-filter.component.mjs +461 -0
- package/esm2020/lib/icon/zendu-icon.component.mjs +24 -0
- package/esm2020/lib/local.lock.mjs +33 -0
- package/esm2020/lib/location-search/location.address.mjs +2 -0
- package/esm2020/lib/location-search/zendu-location-search.component.mjs +129 -0
- package/esm2020/lib/map/map.types.mjs +2 -0
- package/esm2020/lib/map/zendu-map.component.mjs +129 -0
- package/esm2020/lib/map-preview/zendu-map-preview.component.mjs +30 -0
- package/esm2020/lib/ng-zenduit.module.mjs +158 -0
- package/esm2020/lib/pagination-bar/pageItem.mjs +2 -0
- package/esm2020/lib/pagination-bar/zendu-pagination-bar.component.mjs +71 -0
- package/esm2020/lib/phone-input/zendu-phone-input.component.mjs +141 -0
- package/esm2020/lib/progress/zendu-progress.component.mjs +29 -0
- package/esm2020/lib/radio-button/radio-button.component.mjs +48 -0
- package/esm2020/lib/search-box/zendu-search-box.component.mjs +124 -0
- package/esm2020/lib/select/templates/zendu-select-option.directive.mjs +16 -0
- package/esm2020/lib/select/templates/zendu-select-value.directive.mjs +16 -0
- package/esm2020/lib/select/zendu-select.component.mjs +303 -0
- package/esm2020/lib/services/geoconding.service.mjs +61 -0
- package/esm2020/lib/services/map.service.mjs +181 -0
- package/esm2020/lib/services/opencv.service.mjs +109 -0
- package/esm2020/lib/services/zendu-notify.service.mjs +92 -0
- package/esm2020/lib/sort-header/zendu-sort-header.component.mjs +36 -0
- package/esm2020/lib/spinner/zendu-spinner.component.mjs +11 -0
- package/esm2020/lib/toggle/zendu-toggle.component.mjs +32 -0
- package/esm2020/lib/toggle-slide/zendu-toggle-slide.component.mjs +27 -0
- package/esm2020/lib/util.mjs +93 -0
- package/esm2020/ng-zenduit.mjs +5 -0
- package/esm2020/public-api.mjs +42 -0
- package/fesm2015/ng-zenduit.mjs +3768 -0
- package/fesm2015/ng-zenduit.mjs.map +1 -0
- package/fesm2020/ng-zenduit.mjs +3735 -0
- package/fesm2020/ng-zenduit.mjs.map +1 -0
- package/icons/arrow-down-small.svg +3 -0
- package/icons/arrow-up-small.svg +3 -0
- package/icons/calendar.svg +6 -0
- package/icons/cross.svg +3 -0
- package/icons/date.svg +3 -0
- package/icons/expand.svg +3 -0
- package/icons/filter.svg +3 -0
- package/icons/play.svg +10 -0
- package/icons/redo.svg +3 -0
- package/icons/rotate.svg +3 -0
- package/icons/time.svg +4 -0
- package/icons/undo.svg +3 -0
- package/index.d.ts +5 -0
- package/lib/breadcrumbs/zendu-breadcrumbs.component.d.ts +22 -0
- package/lib/card-block/zendu-card-block.component.d.ts +9 -0
- package/lib/checkbox/zendu-checkbox.component.d.ts +17 -0
- package/lib/colorpicker/zendu-colorpicker.component.d.ts +28 -0
- package/lib/column-configuration/columnState.d.ts +7 -0
- package/lib/column-configuration/zendu-column-configuration.component.d.ts +43 -0
- package/lib/datepicker/date-picker-day.d.ts +8 -0
- package/lib/datepicker/date-picker-hint.d.ts +5 -0
- package/lib/datepicker/datepicker.d.ts +7 -0
- package/lib/datepicker/zendu-datepicker.component.d.ts +94 -0
- package/lib/doc-scanner/zendu-doc-scanner.component.d.ts +82 -0
- package/lib/file-upload/zendu-file-upload.component.d.ts +28 -0
- package/lib/filter/dateRange.d.ts +4 -0
- package/lib/filter/filtersConfig.d.ts +88 -0
- package/lib/filter/numberRange.d.ts +4 -0
- package/lib/filter/zendu-filter.component.d.ts +59 -0
- package/lib/icon/zendu-icon.component.d.ts +10 -0
- package/lib/local.lock.d.ts +8 -0
- package/lib/location-search/location.address.d.ts +12 -0
- package/lib/location-search/zendu-location-search.component.d.ts +32 -0
- package/lib/map/map.types.d.ts +33 -0
- package/lib/map/zendu-map.component.d.ts +23 -0
- package/lib/map-preview/zendu-map-preview.component.d.ts +11 -0
- package/lib/ng-zenduit.module.d.ts +34 -0
- package/lib/pagination-bar/pageItem.d.ts +4 -0
- package/lib/pagination-bar/zendu-pagination-bar.component.d.ts +25 -0
- package/lib/phone-input/zendu-phone-input.component.d.ts +39 -0
- package/lib/progress/zendu-progress.component.d.ts +14 -0
- package/lib/radio-button/radio-button.component.d.ts +18 -0
- package/lib/search-box/zendu-search-box.component.d.ts +26 -0
- package/lib/select/templates/zendu-select-option.directive.d.ts +8 -0
- package/lib/select/templates/zendu-select-value.directive.d.ts +8 -0
- package/lib/select/zendu-select.component.d.ts +107 -0
- package/lib/services/geoconding.service.d.ts +23 -0
- package/lib/services/map.service.d.ts +22 -0
- package/lib/services/opencv.service.d.ts +46 -0
- package/lib/services/zendu-notify.service.d.ts +10 -0
- package/lib/sort-header/zendu-sort-header.component.d.ts +10 -0
- package/lib/spinner/zendu-spinner.component.d.ts +5 -0
- package/lib/toggle/zendu-toggle.component.d.ts +14 -0
- package/lib/toggle-slide/zendu-toggle-slide.component.d.ts +13 -0
- package/lib/util.d.ts +11 -0
- package/package.json +36 -0
- package/public-api.d.ts +38 -0
- package/styles/action-menu.scss +127 -0
- package/styles/all.scss +11 -0
- package/styles/button.scss +188 -0
- package/styles/colors.scss +125 -0
- package/styles/common-form.scss +159 -0
- package/styles/extenal.scss +2 -0
- package/styles/ghost.scss +38 -0
- package/styles/global-restyle.scss +25 -0
- package/styles/page-layout.scss +82 -0
- package/styles/snackbar.scss +91 -0
- package/styles/table.scss +107 -0
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import { fabric } from 'fabric';
|
|
2
|
+
import { Component, Input, ViewChild, Output, EventEmitter, } from '@angular/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "../services/opencv.service";
|
|
5
|
+
import * as i2 from "@angular/common";
|
|
6
|
+
export class ZenduDocScanner {
|
|
7
|
+
constructor(_opencv) {
|
|
8
|
+
this._opencv = _opencv;
|
|
9
|
+
this.src = '';
|
|
10
|
+
this.width = 0;
|
|
11
|
+
this.height = 0;
|
|
12
|
+
this.isScanStart = false;
|
|
13
|
+
this.canAddText = false;
|
|
14
|
+
this.canDoodle = false;
|
|
15
|
+
this.currentStateIndex = -1;
|
|
16
|
+
this.canvasStates = [];
|
|
17
|
+
this.isResize = false;
|
|
18
|
+
this.isRedoing = false;
|
|
19
|
+
this.isUndoing = false;
|
|
20
|
+
this.extracted = new EventEmitter();
|
|
21
|
+
this.cornersChanged = new EventEmitter();
|
|
22
|
+
this.canAddTextOrDoole = new EventEmitter();
|
|
23
|
+
this.canRedoOrUndo = new EventEmitter();
|
|
24
|
+
this.screenPoints = [];
|
|
25
|
+
this._scaleFactor = 1;
|
|
26
|
+
this._controls = [];
|
|
27
|
+
this.selectedColor = '#121212';
|
|
28
|
+
this.isScaned = false;
|
|
29
|
+
this.textAdded = false;
|
|
30
|
+
this.icons = {
|
|
31
|
+
cross: new Image(),
|
|
32
|
+
rotate: new Image(),
|
|
33
|
+
expand: new Image(),
|
|
34
|
+
};
|
|
35
|
+
this.Image = {
|
|
36
|
+
height: 0,
|
|
37
|
+
width: 0,
|
|
38
|
+
};
|
|
39
|
+
this.borderWidth = 5;
|
|
40
|
+
this.colors = [
|
|
41
|
+
{ hexCode: '#FFFFFF', selected: false },
|
|
42
|
+
{ hexCode: '#121212', selected: false },
|
|
43
|
+
{ hexCode: '#2188D9', selected: false },
|
|
44
|
+
{ hexCode: '#DC3E33', selected: false },
|
|
45
|
+
{ hexCode: '#219653', selected: false },
|
|
46
|
+
{ hexCode: '#F1B10B', selected: false },
|
|
47
|
+
{ hexCode: '#00F0FF', selected: false },
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
set done(completed) {
|
|
51
|
+
console.log('mark as completed', completed);
|
|
52
|
+
if (completed) {
|
|
53
|
+
this.completeScan(completed);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
ngAfterViewInit() {
|
|
57
|
+
this.icons.cross.src = 'assets/ng-zenduit/icons/cross.svg';
|
|
58
|
+
this.icons.rotate.src = 'assets/ng-zenduit/icons/rotate.svg';
|
|
59
|
+
this.icons.expand.src = 'assets/ng-zenduit/icons/expand.svg';
|
|
60
|
+
setTimeout(async () => {
|
|
61
|
+
await this.init();
|
|
62
|
+
// Add an event listener for canvas edits
|
|
63
|
+
}, 1);
|
|
64
|
+
}
|
|
65
|
+
onCanvasEdit() {
|
|
66
|
+
let objects = this._canvas.getObjects();
|
|
67
|
+
if (objects && objects.length)
|
|
68
|
+
this._canvas._activeObject = objects[objects.length - 1];
|
|
69
|
+
if (!this.isScanStart && !this.isRedoing && !this.isUndoing) {
|
|
70
|
+
this.canRedoOrUndo.emit({
|
|
71
|
+
canUndo: this.currentStateIndex >= 0 ? true : false,
|
|
72
|
+
canRedo: this.currentStateIndex < this.canvasStates.length - 1 ? true : false,
|
|
73
|
+
});
|
|
74
|
+
this.saveCanvasState();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
ngOnChanges(changes) {
|
|
78
|
+
// When src changes
|
|
79
|
+
if (changes['src'] && this._canvas) {
|
|
80
|
+
this.build();
|
|
81
|
+
}
|
|
82
|
+
//When user start scan
|
|
83
|
+
if (changes['isScanStart'] && changes['isScanStart'].currentValue) {
|
|
84
|
+
if (this.src && this._canvas && this.isScanStart) {
|
|
85
|
+
this.addPointsTodoc();
|
|
86
|
+
this.canDoodle = false;
|
|
87
|
+
this._canvas.isDrawingMode = false;
|
|
88
|
+
this.isScaned = true;
|
|
89
|
+
this._canvas.selection = false;
|
|
90
|
+
this.textAdded = false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// When user wants to draw
|
|
94
|
+
if (changes['canDoodle'] &&
|
|
95
|
+
changes['canDoodle'].currentValue &&
|
|
96
|
+
this._canvas) {
|
|
97
|
+
if (this.canDoodle) {
|
|
98
|
+
this._canvas.isDrawingMode = this.canDoodle;
|
|
99
|
+
this._canvas.freeDrawingBrush = this.canDoodle
|
|
100
|
+
? new fabric.PencilBrush(this._canvas)
|
|
101
|
+
: null;
|
|
102
|
+
this._canvas.freeDrawingBrush.width = 10;
|
|
103
|
+
this._canvas.freeDrawingBrush.color = this.selectedColor;
|
|
104
|
+
this._canvas.selection = false;
|
|
105
|
+
this.isScanStart = false;
|
|
106
|
+
this.textAdded = false;
|
|
107
|
+
this._canvas.renderAll();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// When user wants to add text
|
|
111
|
+
if (changes['canAddText'] &&
|
|
112
|
+
changes['canAddText'].currentValue &&
|
|
113
|
+
this.canAddText) {
|
|
114
|
+
this.canDoodle = false;
|
|
115
|
+
this._canvas.isDrawingMode = false;
|
|
116
|
+
this.isScanStart = false;
|
|
117
|
+
}
|
|
118
|
+
if (changes['isUndoing'] && changes['isUndoing'].currentValue)
|
|
119
|
+
this.undo();
|
|
120
|
+
if (changes['isRedoing'] && changes['isRedoing'].currentValue)
|
|
121
|
+
this.redo();
|
|
122
|
+
}
|
|
123
|
+
// To change the color of brush or text
|
|
124
|
+
chngClrTextOrBrush(color, changeFor) {
|
|
125
|
+
this.selectedColor = color;
|
|
126
|
+
this.colors.map((clr, index) => {
|
|
127
|
+
this.colors[index] = { ...this.colors[index], selected: false };
|
|
128
|
+
if (this.colors[index].hexCode === color) {
|
|
129
|
+
this.colors[index] = { ...this.colors[index], selected: true };
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
if (changeFor === 'text') {
|
|
133
|
+
const activeObject = this._canvas.getActiveObject();
|
|
134
|
+
if (activeObject && activeObject.type === 'i-text') {
|
|
135
|
+
// Check if an active text object is selected
|
|
136
|
+
activeObject.set('fill', this.selectedColor); // Update the fill color
|
|
137
|
+
this._canvas.renderAll(); // Render the canvas to see the changes
|
|
138
|
+
}
|
|
139
|
+
this._canvas.renderAll();
|
|
140
|
+
// this.onCanvasEdit();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
this._canvas.freeDrawingBrush.color = color;
|
|
144
|
+
}
|
|
145
|
+
this.selectedColor = color;
|
|
146
|
+
}
|
|
147
|
+
async addPointsTodoc() {
|
|
148
|
+
const corners = await this._opencv.getPaperCorners(this._canvas.toDataURL({
|
|
149
|
+
format: 'jpeg',
|
|
150
|
+
quality: 1,
|
|
151
|
+
}), this.Image.height, this.Image.width);
|
|
152
|
+
if (corners) {
|
|
153
|
+
this.screenPoints = [
|
|
154
|
+
corners.topLeftCorner,
|
|
155
|
+
corners.topRightCorner,
|
|
156
|
+
corners.bottomRightCorner,
|
|
157
|
+
corners.bottomLeftCorner,
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
console.error(`can't detect document corners`);
|
|
162
|
+
const width = this._canvas.getWidth() / this._scaleFactor;
|
|
163
|
+
const height = this._canvas.getHeight() / this._scaleFactor;
|
|
164
|
+
const offset = 20;
|
|
165
|
+
this.screenPoints = [
|
|
166
|
+
{ x: offset, y: 0 },
|
|
167
|
+
{ x: width - offset, y: 0 },
|
|
168
|
+
{ x: width - offset, y: height - offset },
|
|
169
|
+
{ x: offset, y: height - offset },
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
// add polygon
|
|
173
|
+
//
|
|
174
|
+
this._cornersPg = new fabric.Polygon(this.screenPoints, {
|
|
175
|
+
stroke: '#2188d9',
|
|
176
|
+
strokeWidth: 10,
|
|
177
|
+
selectable: false,
|
|
178
|
+
fill: 'rgba(33, 136, 217, 0.1)',
|
|
179
|
+
hasBorders: true,
|
|
180
|
+
objectCaching: false,
|
|
181
|
+
});
|
|
182
|
+
this._canvas.add(this._cornersPg);
|
|
183
|
+
this.createControls(this._cornersPg);
|
|
184
|
+
}
|
|
185
|
+
async init(src) {
|
|
186
|
+
// Create canvas with new changed src
|
|
187
|
+
if (src) {
|
|
188
|
+
this.createCanvas();
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
try {
|
|
192
|
+
if (!this._canvasElement || !this._canvasElement.nativeElement) {
|
|
193
|
+
// canvas is not ready
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (this._canvas) {
|
|
197
|
+
// canvas already initalized
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
this.createCanvas();
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
console.error(err);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async createCanvas() {
|
|
208
|
+
// documentation: http://fabricjs.com/docs/fabric.Canvas.html
|
|
209
|
+
let canvas = this._canvasElement.nativeElement;
|
|
210
|
+
this._canvas = new fabric.Canvas(canvas, {
|
|
211
|
+
backgroundColor: 'white',
|
|
212
|
+
selection: false,
|
|
213
|
+
});
|
|
214
|
+
const { width, height } = this.getCanvasSize();
|
|
215
|
+
this._canvas.setWidth(width);
|
|
216
|
+
this._canvas.setHeight(height);
|
|
217
|
+
this._canvas.on('object:added', this.onCanvasEdit.bind(this));
|
|
218
|
+
this._canvas.on('object:modified', this.onCanvasEdit.bind(this));
|
|
219
|
+
this._canvas.on('mouse:down', this.addTextOnClick.bind(this));
|
|
220
|
+
this._canvas.on('mouse:move', this.resizeText.bind(this));
|
|
221
|
+
this._canvas.on('mouse:up', this.stopResizeText.bind(this));
|
|
222
|
+
if (this.src) {
|
|
223
|
+
await this.build();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
renderIcon(ctx, left, top, styleOverride, fabricObject, iconName) {
|
|
227
|
+
var size = 42;
|
|
228
|
+
var iconBackgroundSize = 50; // Adjust the size as needed
|
|
229
|
+
ctx.save();
|
|
230
|
+
// Draw a background circle behind the icon
|
|
231
|
+
ctx.fillStyle = 'white'; // Set the background color
|
|
232
|
+
ctx.beginPath();
|
|
233
|
+
ctx.arc(left, top - 10, iconBackgroundSize / 2, 0, 2 * Math.PI);
|
|
234
|
+
ctx.fill();
|
|
235
|
+
var img = this.icons[iconName];
|
|
236
|
+
img.onload = function () { };
|
|
237
|
+
ctx.translate(left, top - 10);
|
|
238
|
+
ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
|
|
239
|
+
ctx.drawImage(img, -size / 2, -size / 2, size, size);
|
|
240
|
+
ctx.restore();
|
|
241
|
+
}
|
|
242
|
+
stopResizeText(event) {
|
|
243
|
+
if (this.isResize) {
|
|
244
|
+
this.saveCanvasState();
|
|
245
|
+
this.isResize = false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
resizeText(event) {
|
|
249
|
+
if (this.isResize) {
|
|
250
|
+
const target = event.target;
|
|
251
|
+
const deltaY = event.e.clientY - this.initialMouseY;
|
|
252
|
+
// Limit the scaling factor to prevent excessive resizing
|
|
253
|
+
const scalingFactor = Math.min(2, Math.max(0.5, 1 + deltaY / 100));
|
|
254
|
+
// Calculate the new font size based on the original size and scaling factor
|
|
255
|
+
const newFontSize = this.originalFontSize * scalingFactor;
|
|
256
|
+
// Set the font size of the text object
|
|
257
|
+
target.fontSize = newFontSize;
|
|
258
|
+
// Re-render the canvas to see the live change
|
|
259
|
+
event.target.canvas.renderAll();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
addTextOnClick(event) {
|
|
263
|
+
let _text = new fabric.IText('Type your text here', {
|
|
264
|
+
left: event.pointer.x,
|
|
265
|
+
top: event.pointer.y,
|
|
266
|
+
fill: this.selectedColor,
|
|
267
|
+
fontSize: 50,
|
|
268
|
+
fontFamily: 'Roboto',
|
|
269
|
+
selectable: true,
|
|
270
|
+
fontWeight: 400,
|
|
271
|
+
borderScaleFactor: 3,
|
|
272
|
+
borderColor: 'white',
|
|
273
|
+
backgroundColor: 'transparent',
|
|
274
|
+
cornerColor: 'white',
|
|
275
|
+
padding: 42,
|
|
276
|
+
width: 200, // Set the initial width of the text box
|
|
277
|
+
});
|
|
278
|
+
//Custom controls for add text box
|
|
279
|
+
let customControls = {
|
|
280
|
+
removeControl: new fabric.Control({
|
|
281
|
+
x: -0.5,
|
|
282
|
+
y: -0.5,
|
|
283
|
+
offsetY: 16,
|
|
284
|
+
cursorStyle: 'pointer',
|
|
285
|
+
render: (ctx, left, top, styleOverride, fabricObject) => {
|
|
286
|
+
return this.renderIcon(ctx, left, top, styleOverride, fabricObject, 'cross');
|
|
287
|
+
},
|
|
288
|
+
mouseUpHandler: (eventData, transform) => {
|
|
289
|
+
var target = transform.target;
|
|
290
|
+
var canvas = target.canvas;
|
|
291
|
+
canvas.remove(target);
|
|
292
|
+
canvas.requestRenderAll();
|
|
293
|
+
this.saveCanvasState();
|
|
294
|
+
return true;
|
|
295
|
+
},
|
|
296
|
+
}),
|
|
297
|
+
rotateControl: new fabric.Control({
|
|
298
|
+
x: 0.5,
|
|
299
|
+
y: -0.5,
|
|
300
|
+
offsetY: 16,
|
|
301
|
+
cursorStyle: 'pointer',
|
|
302
|
+
render: (ctx, left, top, styleOverride, fabricObject) => {
|
|
303
|
+
return this.renderIcon(ctx, left, top, styleOverride, fabricObject, 'rotate');
|
|
304
|
+
},
|
|
305
|
+
mouseUpHandler: (eventData, transform) => {
|
|
306
|
+
let fabricObject = transform.target;
|
|
307
|
+
const rotationIncrement = 30; // Rotation increment in degrees
|
|
308
|
+
fabricObject.set('angle', (fabricObject.angle + rotationIncrement) % 360);
|
|
309
|
+
fabricObject.setCoords(); // Update object's coordinates
|
|
310
|
+
this.saveCanvasState();
|
|
311
|
+
return true;
|
|
312
|
+
},
|
|
313
|
+
}),
|
|
314
|
+
expantControl: new fabric.Control({
|
|
315
|
+
x: 0.5,
|
|
316
|
+
y: 0.5,
|
|
317
|
+
offsetY: 16,
|
|
318
|
+
cursorStyle: 'grab',
|
|
319
|
+
render: (ctx, left, top, styleOverride, fabricObject) => {
|
|
320
|
+
return this.renderIcon(ctx, left, top, styleOverride, fabricObject, 'expand');
|
|
321
|
+
},
|
|
322
|
+
}),
|
|
323
|
+
};
|
|
324
|
+
if (event.transform && event.transform.action === 'scale') {
|
|
325
|
+
this.isResize = true;
|
|
326
|
+
this.initialMouseY = event.e.clientY;
|
|
327
|
+
this.originalFontSize = event.target.fontSize;
|
|
328
|
+
}
|
|
329
|
+
if (!this.textAdded &&
|
|
330
|
+
!this.canDoodle &&
|
|
331
|
+
!this.isScanStart &&
|
|
332
|
+
this.canAddText) {
|
|
333
|
+
_text.controls = customControls;
|
|
334
|
+
this._canvas.add(_text);
|
|
335
|
+
this._canvas.renderAll();
|
|
336
|
+
this.textAdded = true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Function to save the canvas state
|
|
340
|
+
saveCanvasState() {
|
|
341
|
+
const state = JSON.stringify(this._canvas.toJSON());
|
|
342
|
+
// const state = this._canvas.getObjects()[this._canvas.getObjects.length - 1]
|
|
343
|
+
if (this.currentStateIndex < this.canvasStates.length - 1) {
|
|
344
|
+
this.canvasStates.length = this.currentStateIndex + 1; // Remove future states
|
|
345
|
+
}
|
|
346
|
+
let activeObj = this._canvas.getActiveObject();
|
|
347
|
+
if (activeObj && activeObj.type === 'path') {
|
|
348
|
+
// set remove border and controls for drawing
|
|
349
|
+
activeObj.set({
|
|
350
|
+
hasControls: false,
|
|
351
|
+
selectable: false,
|
|
352
|
+
hasBorders: false,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
const customControl = activeObj && activeObj.controls ? activeObj.controls : null;
|
|
356
|
+
this.canvasStates.push({ state, customControl });
|
|
357
|
+
this.currentStateIndex++;
|
|
358
|
+
}
|
|
359
|
+
redo() {
|
|
360
|
+
this.isRedoing = true;
|
|
361
|
+
if (this.currentStateIndex < this.canvasStates.length - 1) {
|
|
362
|
+
this.currentStateIndex++;
|
|
363
|
+
const nextState = this.canvasStates[this.currentStateIndex];
|
|
364
|
+
this.canRedoOrUndo.emit({
|
|
365
|
+
canUndo: this.currentStateIndex > 0 ? true : false,
|
|
366
|
+
canRedo: this.currentStateIndex < this.canvasStates.length - 1 ? true : false,
|
|
367
|
+
});
|
|
368
|
+
this._canvas.loadFromJSON(nextState.state, () => {
|
|
369
|
+
let activeObject = this._canvas.getActiveObject();
|
|
370
|
+
this._canvas.getObjects().forEach((obj) => {
|
|
371
|
+
if (obj !== activeObject) {
|
|
372
|
+
obj.evented = false;
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
if (activeObject && activeObject.type !== 'path') {
|
|
376
|
+
activeObject.controls =
|
|
377
|
+
nextState && nextState.customControl
|
|
378
|
+
? nextState.customControl
|
|
379
|
+
: null;
|
|
380
|
+
activeObject.set({
|
|
381
|
+
padding: 42,
|
|
382
|
+
borderScaleFactor: 3,
|
|
383
|
+
borderColor: 'white',
|
|
384
|
+
});
|
|
385
|
+
this.textAdded = true;
|
|
386
|
+
this.canAddTextOrDoole.emit({ key: 'doodle', value: false });
|
|
387
|
+
this.canAddTextOrDoole.emit({ key: 'text', value: true });
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
activeObject.set({
|
|
391
|
+
hasControls: false,
|
|
392
|
+
selectable: false,
|
|
393
|
+
hasBorders: false,
|
|
394
|
+
});
|
|
395
|
+
this.canAddTextOrDoole.emit({ key: 'text', value: false });
|
|
396
|
+
this.canAddTextOrDoole.emit({ key: 'doodle', value: true });
|
|
397
|
+
this._canvas.selection = false;
|
|
398
|
+
}
|
|
399
|
+
this._canvas.renderAll();
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
undo() {
|
|
404
|
+
this.isUndoing = true;
|
|
405
|
+
if (this.currentStateIndex > 0) {
|
|
406
|
+
this.currentStateIndex--;
|
|
407
|
+
const previousState = this.canvasStates[this.currentStateIndex];
|
|
408
|
+
this.canRedoOrUndo.emit({
|
|
409
|
+
canUndo: this.currentStateIndex > 0 ? true : false,
|
|
410
|
+
canRedo: this.currentStateIndex < this.canvasStates.length - 1 ? true : false,
|
|
411
|
+
});
|
|
412
|
+
this._canvas.loadFromJSON(previousState.state, () => {
|
|
413
|
+
let activeObject = this._canvas.getActiveObject();
|
|
414
|
+
if (activeObject) {
|
|
415
|
+
if (activeObject.type !== 'path') {
|
|
416
|
+
activeObject.set({
|
|
417
|
+
padding: 42,
|
|
418
|
+
borderScaleFactor: 3,
|
|
419
|
+
borderColor: 'white',
|
|
420
|
+
});
|
|
421
|
+
this._canvas.isDrawingMode = false;
|
|
422
|
+
this._canvas.freeDrawingBrush = null;
|
|
423
|
+
this.textAdded = true;
|
|
424
|
+
this.canAddTextOrDoole.emit({ key: 'doodle', value: false });
|
|
425
|
+
this.canAddTextOrDoole.emit({ key: 'text', value: true });
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
activeObject.set({
|
|
429
|
+
hasControls: false,
|
|
430
|
+
hasBorders: false,
|
|
431
|
+
});
|
|
432
|
+
this._canvas.selection = false;
|
|
433
|
+
this.canAddTextOrDoole.emit({ key: 'text', value: false });
|
|
434
|
+
this.canAddTextOrDoole.emit({ key: 'doodle', value: true });
|
|
435
|
+
}
|
|
436
|
+
this._canvas.getActiveObject().controls =
|
|
437
|
+
previousState && previousState.customControl
|
|
438
|
+
? previousState.customControl
|
|
439
|
+
: null;
|
|
440
|
+
}
|
|
441
|
+
this._canvas.getObjects().forEach((obj) => {
|
|
442
|
+
if (obj !== activeObject) {
|
|
443
|
+
obj.evented = false;
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
this._canvas.renderAll();
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
getCanvasSize() {
|
|
451
|
+
const img = new Image();
|
|
452
|
+
img.src = this.src;
|
|
453
|
+
const box = this._component.nativeElement.getBoundingClientRect();
|
|
454
|
+
const width = this.width || box.width || 1;
|
|
455
|
+
const height = this.height || box.height || 1;
|
|
456
|
+
return { width, height };
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* recognize paper corners
|
|
460
|
+
*/
|
|
461
|
+
async build() {
|
|
462
|
+
if (!this.src || !this._canvas) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const bg = await this.loadBackgroundImage(this.src);
|
|
466
|
+
// Remove all the existing objects before add the new image to background
|
|
467
|
+
this._canvas.clear();
|
|
468
|
+
const imgSize = bg.getOriginalSize();
|
|
469
|
+
this.Image = {
|
|
470
|
+
height: imgSize.height * this._scaleFactor,
|
|
471
|
+
width: imgSize.width * this._scaleFactor,
|
|
472
|
+
};
|
|
473
|
+
const scaleX = this._canvas.width / imgSize.width;
|
|
474
|
+
const scaleY = this._canvas.height / imgSize.height;
|
|
475
|
+
this._scaleFactor = Math.min(scaleY, scaleX);
|
|
476
|
+
this._canvas.setDimensions({
|
|
477
|
+
width: imgSize.width,
|
|
478
|
+
height: imgSize.height,
|
|
479
|
+
}, {
|
|
480
|
+
backstoreOnly: true,
|
|
481
|
+
});
|
|
482
|
+
this._canvas.setBackgroundImage(bg, () => {
|
|
483
|
+
this._canvas.renderAll();
|
|
484
|
+
});
|
|
485
|
+
this.saveCanvasState();
|
|
486
|
+
this._canvas.renderAll();
|
|
487
|
+
}
|
|
488
|
+
createControls(polygon) {
|
|
489
|
+
// remove previous controls
|
|
490
|
+
if (this._controls.length) {
|
|
491
|
+
this._canvas.remove(...this._controls);
|
|
492
|
+
this._controls = [];
|
|
493
|
+
}
|
|
494
|
+
if (polygon) {
|
|
495
|
+
for (const [index, point] of polygon.points.entries()) {
|
|
496
|
+
const circle = this.createControl(index, polygon);
|
|
497
|
+
this._controls.push(circle);
|
|
498
|
+
this._canvas.add(circle);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
createControl(index, polygon) {
|
|
503
|
+
const point = polygon.points[index];
|
|
504
|
+
const circle = new fabric.Circle({
|
|
505
|
+
left: point.x,
|
|
506
|
+
top: point.y,
|
|
507
|
+
originX: 'center',
|
|
508
|
+
originY: 'center',
|
|
509
|
+
fill: '#2188d9',
|
|
510
|
+
radius: 20,
|
|
511
|
+
hasRotatingPoint: false,
|
|
512
|
+
hasBorders: false,
|
|
513
|
+
hasControls: false,
|
|
514
|
+
objectCaching: false,
|
|
515
|
+
});
|
|
516
|
+
circle.on('moving', (evt) => {
|
|
517
|
+
if (evt.pointer) {
|
|
518
|
+
polygon.points[index] = new fabric.Point(evt.pointer.x, evt.pointer.y);
|
|
519
|
+
polygon.dirty = true;
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
circle.on('mouseup', (evt) => {
|
|
523
|
+
this.cornersChanged.emit();
|
|
524
|
+
this.screenPoints[index] = polygon.points[index];
|
|
525
|
+
});
|
|
526
|
+
return circle;
|
|
527
|
+
}
|
|
528
|
+
loadBackgroundImage(src) {
|
|
529
|
+
return new Promise((resolve, reject) => {
|
|
530
|
+
const img = new Image();
|
|
531
|
+
img.onload = () => {
|
|
532
|
+
let fabImage = new fabric.Image(img);
|
|
533
|
+
resolve(fabImage);
|
|
534
|
+
};
|
|
535
|
+
img.src = src;
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
async completeScan(completed) {
|
|
539
|
+
if (!completed) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
console.log(`complete scan & extract paper`);
|
|
543
|
+
if (!this._cornersPg) {
|
|
544
|
+
console.error(`Corner line is not available`);
|
|
545
|
+
}
|
|
546
|
+
if (this._cornersPg) {
|
|
547
|
+
this._canvas.remove(this._cornersPg);
|
|
548
|
+
this._canvas.remove(...this._controls);
|
|
549
|
+
this._canvas.renderAll();
|
|
550
|
+
}
|
|
551
|
+
let output;
|
|
552
|
+
if (this.isScaned) {
|
|
553
|
+
output = await this._opencv.extractPaper({
|
|
554
|
+
src: this._canvas.toDataURL({ quality: 1 }),
|
|
555
|
+
corners: {
|
|
556
|
+
topLeftCorner: this.screenPoints[0],
|
|
557
|
+
topRightCorner: this.screenPoints[1],
|
|
558
|
+
bottomRightCorner: this.screenPoints[2],
|
|
559
|
+
bottomLeftCorner: this.screenPoints[3],
|
|
560
|
+
},
|
|
561
|
+
height: this._canvas.height,
|
|
562
|
+
width: this._canvas.width,
|
|
563
|
+
});
|
|
564
|
+
this._canvas.remove(...this._canvas.getObjects());
|
|
565
|
+
this.isScaned = false;
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
output = this._canvas.toCanvasElement();
|
|
569
|
+
}
|
|
570
|
+
this.currentStateIndex = null;
|
|
571
|
+
this.canvasStates = [];
|
|
572
|
+
this.canRedoOrUndo.emit({
|
|
573
|
+
canUndo: this.currentStateIndex > 0 ? true : false,
|
|
574
|
+
canRedo: this.currentStateIndex < this.canvasStates.length - 1 ? true : false,
|
|
575
|
+
});
|
|
576
|
+
this.extracted.emit(output);
|
|
577
|
+
this.cleanupCanvas();
|
|
578
|
+
}
|
|
579
|
+
cleanupCanvas() {
|
|
580
|
+
this._canvas.getObjects().forEach((obj) => (obj.evented = false));
|
|
581
|
+
this._canvas.selection = false;
|
|
582
|
+
this._canvas.isDrawingMode = false;
|
|
583
|
+
this.canDoodle = false;
|
|
584
|
+
this.isScanStart = false;
|
|
585
|
+
this.canAddText = false;
|
|
586
|
+
this.textAdded = false;
|
|
587
|
+
this._canvas.renderAll();
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
ZenduDocScanner.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ZenduDocScanner, deps: [{ token: i1.OpenCVService }], target: i0.ɵɵFactoryTarget.Component });
|
|
591
|
+
ZenduDocScanner.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: ZenduDocScanner, selector: "zen-doc-scanner", inputs: { src: "src", width: "width", height: "height", isScanStart: "isScanStart", canAddText: "canAddText", canDoodle: "canDoodle", isRedoing: "isRedoing", isUndoing: "isUndoing", done: "done" }, outputs: { extracted: "extracted", cornersChanged: "cornersChanged", canAddTextOrDoole: "canAddTextOrDoole", canRedoOrUndo: "canRedoOrUndo" }, viewQueries: [{ propertyName: "_canvasElement", first: true, predicate: ["drawCanas"], descendants: true }, { propertyName: "_component", first: true, predicate: ["componentWrapper"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #componentWrapper\n class=\"component\">\n <canvas #drawCanas></canvas>\n <div class=\"colors-container\" *ngIf=\"canDoodle || canAddText\">\n <div class=\"colors\" *ngFor=\"let color of colors\" [ngStyle]=\"{'background': color.hexCode, 'border':color.selected ? '1.6px solid white' : 'none'}\" (click)=\"chngClrTextOrBrush(color.hexCode, canAddText ? 'text': 'doodle')\"></div>\n </div>\n</div>\n", styles: [".component{width:100%;height:100%}.colors-container{display:flex;height:20px;gap:16px;padding:8px 62px;justify-content:space-between;background:#262626}.colors-container .colors{width:20px;height:20px;border-radius:50%}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
592
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ZenduDocScanner, decorators: [{
|
|
593
|
+
type: Component,
|
|
594
|
+
args: [{ selector: 'zen-doc-scanner', template: "<div #componentWrapper\n class=\"component\">\n <canvas #drawCanas></canvas>\n <div class=\"colors-container\" *ngIf=\"canDoodle || canAddText\">\n <div class=\"colors\" *ngFor=\"let color of colors\" [ngStyle]=\"{'background': color.hexCode, 'border':color.selected ? '1.6px solid white' : 'none'}\" (click)=\"chngClrTextOrBrush(color.hexCode, canAddText ? 'text': 'doodle')\"></div>\n </div>\n</div>\n", styles: [".component{width:100%;height:100%}.colors-container{display:flex;height:20px;gap:16px;padding:8px 62px;justify-content:space-between;background:#262626}.colors-container .colors{width:20px;height:20px;border-radius:50%}\n"] }]
|
|
595
|
+
}], ctorParameters: function () { return [{ type: i1.OpenCVService }]; }, propDecorators: { _canvasElement: [{
|
|
596
|
+
type: ViewChild,
|
|
597
|
+
args: ['drawCanas']
|
|
598
|
+
}], _component: [{
|
|
599
|
+
type: ViewChild,
|
|
600
|
+
args: ['componentWrapper']
|
|
601
|
+
}], src: [{
|
|
602
|
+
type: Input
|
|
603
|
+
}], width: [{
|
|
604
|
+
type: Input
|
|
605
|
+
}], height: [{
|
|
606
|
+
type: Input
|
|
607
|
+
}], isScanStart: [{
|
|
608
|
+
type: Input
|
|
609
|
+
}], canAddText: [{
|
|
610
|
+
type: Input
|
|
611
|
+
}], canDoodle: [{
|
|
612
|
+
type: Input
|
|
613
|
+
}], isRedoing: [{
|
|
614
|
+
type: Input
|
|
615
|
+
}], isUndoing: [{
|
|
616
|
+
type: Input
|
|
617
|
+
}], done: [{
|
|
618
|
+
type: Input
|
|
619
|
+
}], extracted: [{
|
|
620
|
+
type: Output
|
|
621
|
+
}], cornersChanged: [{
|
|
622
|
+
type: Output
|
|
623
|
+
}], canAddTextOrDoole: [{
|
|
624
|
+
type: Output
|
|
625
|
+
}], canRedoOrUndo: [{
|
|
626
|
+
type: Output
|
|
627
|
+
}] } });
|
|
628
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemVuZHUtZG9jLXNjYW5uZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctemVuZHVpdC9zcmMvbGliL2RvYy1zY2FubmVyL3plbmR1LWRvYy1zY2FubmVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLXplbmR1aXQvc3JjL2xpYi9kb2Mtc2Nhbm5lci96ZW5kdS1kb2Mtc2Nhbm5lci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2hDLE9BQU8sRUFDTCxTQUFTLEVBRVQsS0FBSyxFQUVMLFNBQVMsRUFFVCxNQUFNLEVBQ04sWUFBWSxHQUViLE1BQU0sZUFBZSxDQUFDOzs7O0FBU3ZCLE1BQU0sT0FBTyxlQUFlO0lBbUYxQixZQUFvQixPQUFzQjtRQUF0QixZQUFPLEdBQVAsT0FBTyxDQUFlO1FBOUVqQyxRQUFHLEdBQUcsRUFBRSxDQUFDO1FBRVQsVUFBSyxHQUFHLENBQUMsQ0FBQztRQUVWLFdBQU0sR0FBRyxDQUFDLENBQUM7UUFFWCxnQkFBVyxHQUFZLEtBQUssQ0FBQztRQUU3QixlQUFVLEdBQVksS0FBSyxDQUFDO1FBRTVCLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFFcEMsc0JBQWlCLEdBQVcsQ0FBQyxDQUFDLENBQUM7UUFFL0IsaUJBQVksR0FBNEMsRUFBRSxDQUFDO1FBRTNELGFBQVEsR0FBWSxLQUFLLENBQUM7UUFJakIsY0FBUyxHQUFZLEtBQUssQ0FBQztRQUMzQixjQUFTLEdBQVksS0FBSyxDQUFDO1FBUTFCLGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBcUIsQ0FBQztRQUVsRCxtQkFBYyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFMUMsc0JBQWlCLEdBQUcsSUFBSSxZQUFZLEVBQU0sQ0FBQztRQUUzQyxrQkFBYSxHQUFHLElBQUksWUFBWSxFQUd0QyxDQUFDO1FBRUcsaUJBQVksR0FBK0IsRUFBRSxDQUFDO1FBTTlDLGlCQUFZLEdBQUcsQ0FBQyxDQUFDO1FBRWpCLGNBQVMsR0FBb0IsRUFBRSxDQUFDO1FBRXhDLGtCQUFhLEdBQVcsU0FBUyxDQUFDO1FBRWxDLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFFMUIsY0FBUyxHQUFZLEtBQUssQ0FBQztRQUUxQixVQUFLLEdBQUc7WUFDUCxLQUFLLEVBQUUsSUFBSSxLQUFLLEVBQUU7WUFDbEIsTUFBTSxFQUFFLElBQUksS0FBSyxFQUFFO1lBQ25CLE1BQU0sRUFBRSxJQUFJLEtBQUssRUFBRTtTQUNwQixDQUFDO1FBQ00sVUFBSyxHQUFHO1lBQ2QsTUFBTSxFQUFFLENBQUM7WUFDVCxLQUFLLEVBQUUsQ0FBQztTQUNULENBQUM7UUFDRixnQkFBVyxHQUFXLENBQUMsQ0FBQztRQUN4QixXQUFNLEdBQUc7WUFDUCxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN2QyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN2QyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN2QyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN2QyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN2QyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN2QyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRTtTQUN4QyxDQUFDO0lBSTJDLENBQUM7SUF4RDlDLElBQWEsSUFBSSxDQUFDLFNBQWtCO1FBQ2xDLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUMsU0FBUyxDQUFDLENBQUM7UUFDM0MsSUFBSSxTQUFTLEVBQUU7WUFDYixJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQzlCO0lBQ0gsQ0FBQztJQXFETSxlQUFlO1FBQ3BCLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxtQ0FBbUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEdBQUcsb0NBQW9DLENBQUM7UUFDN0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxHQUFFLG9DQUFvQyxDQUFDO1FBQzVELFVBQVUsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUNwQixNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNsQix5Q0FBeUM7UUFDM0MsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQztJQUVNLFlBQVk7UUFDakIsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN4QyxJQUFJLE9BQU8sSUFBSSxPQUFPLENBQUMsTUFBTTtZQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQzNELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDO2dCQUN0QixPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUNuRCxPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO2FBQzlFLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztTQUN4QjtJQUNILENBQUM7SUFDTSxXQUFXLENBQUMsT0FBc0I7UUFFdkMsbUJBQW1CO1FBQ25CLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDbEMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2Q7UUFDRCxzQkFBc0I7UUFDdEIsSUFBSSxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLFlBQVksRUFBRTtZQUNqRSxJQUFJLElBQUksQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO2dCQUNoRCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7Z0JBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO2dCQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO2FBQ3hCO1NBQ0Y7UUFDRCwwQkFBMEI7UUFDMUIsSUFDRSxPQUFPLENBQUMsV0FBVyxDQUFDO1lBQ3BCLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxZQUFZO1lBQ2pDLElBQUksQ0FBQyxPQUFPLEVBQ1o7WUFDQSxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ2xCLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7Z0JBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFNBQVM7b0JBQzVDLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztvQkFDdEMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDVCxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7Z0JBQ3pELElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztnQkFDL0IsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO2FBQzFCO1NBQ0Y7UUFDRCw4QkFBOEI7UUFDOUIsSUFDRSxPQUFPLENBQUMsWUFBWSxDQUFDO1lBQ3JCLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxZQUFZO1lBQ2xDLElBQUksQ0FBQyxVQUFVLEVBQ2Y7WUFDQSxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7WUFDbkMsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7U0FDMUI7UUFDRCxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsSUFBSSxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsWUFBWTtZQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMzRSxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsSUFBSSxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsWUFBWTtZQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM3RSxDQUFDO0lBQ0QsdUNBQXVDO0lBQ3ZDLGtCQUFrQixDQUFDLEtBQWEsRUFBRSxTQUFpQjtRQUNqRCxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUM3QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNoRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxLQUFLLEtBQUssRUFBRTtnQkFDeEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7YUFDaEU7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksU0FBUyxLQUFLLE1BQU0sRUFBRTtZQUN4QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3BELElBQUksWUFBWSxJQUFJLFlBQVksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO2dCQUNsRCw2Q0FBNkM7Z0JBQzdDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLHdCQUF3QjtnQkFDdEUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLHVDQUF1QzthQUNsRTtZQUNELElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDekIsdUJBQXVCO1NBQ3hCO2FBQU07WUFDTCxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7U0FDN0M7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUM3QixDQUFDO0lBQ0QsS0FBSyxDQUFDLGNBQWM7UUFDbEIsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FDaEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDckIsTUFBTSxFQUFFLE1BQU07WUFDZCxPQUFPLEVBQUUsQ0FBQztTQUNYLENBQUMsRUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFDakIsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQ2pCLENBQUM7UUFDRixJQUFJLE9BQU8sRUFBRTtZQUNYLElBQUksQ0FBQyxZQUFZLEdBQUc7Z0JBQ2xCLE9BQU8sQ0FBQyxhQUFhO2dCQUNyQixPQUFPLENBQUMsY0FBYztnQkFDdEIsT0FBTyxDQUFDLGlCQUFpQjtnQkFDekIsT0FBTyxDQUFDLGdCQUFnQjthQUN6QixDQUFDO1NBQ0g7YUFBTTtZQUNMLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztZQUMvQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7WUFDMUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQzVELE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsWUFBWSxHQUFHO2dCQUNsQixFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDbkIsRUFBRSxDQUFDLEVBQUUsS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFO2dCQUMzQixFQUFFLENBQUMsRUFBRSxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUFFO2dCQUN6QyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQUU7YUFDbEMsQ0FBQztTQUNIO1FBRUQsY0FBYztRQUNkLEVBQUU7UUFDRixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ3RELE1BQU0sRUFBRSxTQUFTO1lBQ2pCLFdBQVcsRUFBRSxFQUFFO1lBQ2YsVUFBVSxFQUFFLEtBQUs7WUFDakIsSUFBSSxFQUFFLHlCQUF5QjtZQUMvQixVQUFVLEVBQUUsSUFBSTtZQUNoQixhQUFhLEVBQUUsS0FBSztTQUNyQixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBWTtRQUM3QixxQ0FBcUM7UUFDckMsSUFBSSxHQUFHLEVBQUU7WUFDUCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7U0FDckI7YUFBTTtZQUNMLElBQUk7Z0JBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRTtvQkFDOUQsc0JBQXNCO29CQUN0QixPQUFPO2lCQUNSO2dCQUVELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtvQkFDaEIsNEJBQTRCO29CQUM1QixPQUFPO2lCQUNSO2dCQUNELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQzthQUNyQjtZQUFDLE9BQU8sR0FBRyxFQUFFO2dCQUNaLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDcEI7U0FDRjtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsWUFBWTtRQUNoQiw2REFBNkQ7UUFDN0QsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLENBQUM7UUFDL0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1lBQ3ZDLGVBQWUsRUFBRSxPQUFPO1lBQ3hCLFNBQVMsRUFBRSxLQUFLO1NBQ2pCLENBQUMsQ0FBQztRQUNILE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQy9DLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDNUQsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ1osTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDcEI7SUFDSCxDQUFDO0lBRUQsVUFBVSxDQUNSLEdBQTZCLEVBQzdCLElBQVksRUFDWixHQUFXLEVBQ1gsYUFBYSxFQUNiLFlBQTJCLEVBQzNCLFFBQWdCO1FBRWhCLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNkLElBQUksa0JBQWtCLEdBQUcsRUFBRSxDQUFDLENBQUMsNEJBQTRCO1FBQ3pELEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUVYLDJDQUEyQztRQUMzQyxHQUFHLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxDQUFDLDJCQUEyQjtRQUNwRCxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDaEIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxrQkFBa0IsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEUsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRVgsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMvQixHQUFHLENBQUMsTUFBTSxHQUFHLGNBQVksQ0FBQyxDQUFBO1FBQzFCLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM5QixHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDN0QsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDckQsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxjQUFjLENBQUMsS0FBUztRQUN0QixJQUFHLElBQUksQ0FBQyxRQUFRLEVBQUM7WUFDZixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUE7WUFDdEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7U0FDdkI7SUFDSCxDQUFDO0lBQ0QsVUFBVSxDQUFDLEtBQVU7UUFDbkIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7WUFDNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUVwRCx5REFBeUQ7WUFDekQsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBRW5FLDRFQUE0RTtZQUM1RSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsYUFBYSxDQUFDO1lBRTFELHVDQUF1QztZQUN2QyxNQUFNLENBQUMsUUFBUSxHQUFHLFdBQVcsQ0FBQztZQUU5Qiw4Q0FBOEM7WUFDOUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7U0FDakM7SUFDSCxDQUFDO0lBQ0QsY0FBYyxDQUFDLEtBQVU7UUFDdkIsSUFBSSxLQUFLLEdBQVUsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixFQUFFO1lBQ3pELElBQUksRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDckIsR0FBRyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNwQixJQUFJLEVBQUUsSUFBSSxDQUFDLGFBQWE7WUFDeEIsUUFBUSxFQUFFLEVBQUU7WUFDWixVQUFVLEVBQUUsUUFBUTtZQUNwQixVQUFVLEVBQUUsSUFBSTtZQUNoQixVQUFVLEVBQUUsR0FBRztZQUNmLGlCQUFpQixFQUFFLENBQUM7WUFDcEIsV0FBVyxFQUFFLE9BQU87WUFDcEIsZUFBZSxFQUFFLGFBQWE7WUFDOUIsV0FBVyxFQUFFLE9BQU87WUFDcEIsT0FBTyxFQUFFLEVBQUU7WUFDWCxLQUFLLEVBQUUsR0FBRyxFQUFFLHdDQUF3QztTQUNyRCxDQUFDLENBQUM7UUFDRCxrQ0FBa0M7UUFDdEMsSUFBSSxjQUFjLEdBQUc7WUFDbkIsYUFBYSxFQUFFLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQztnQkFDaEMsQ0FBQyxFQUFFLENBQUMsR0FBRztnQkFDUCxDQUFDLEVBQUUsQ0FBQyxHQUFHO2dCQUNQLE9BQU8sRUFBRSxFQUFFO2dCQUNYLFdBQVcsRUFBRSxTQUFTO2dCQUN0QixNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLEVBQUU7b0JBQ3RELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FDcEIsR0FBRyxFQUNILElBQUksRUFDSixHQUFHLEVBQ0gsYUFBYSxFQUNiLFlBQVksRUFDWixPQUFPLENBQ1IsQ0FBQztnQkFDSixDQUFDO2dCQUNELGNBQWMsRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsRUFBRTtvQkFDdkMsSUFBSSxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztvQkFDOUIsSUFBSSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztvQkFDM0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDdEIsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7b0JBQzFCLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQkFDdkIsT0FBTyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQzthQUNGLENBQUM7WUFFRixhQUFhLEVBQUUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDO2dCQUNoQyxDQUFDLEVBQUUsR0FBRztnQkFDTixDQUFDLEVBQUUsQ0FBQyxHQUFHO2dCQUNQLE9BQU8sRUFBRSxFQUFFO2dCQUNYLFdBQVcsRUFBRSxTQUFTO2dCQUN0QixNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLEVBQUU7b0JBQ3RELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FDcEIsR0FBRyxFQUNILElBQUksRUFDSixHQUFHLEVBQ0gsYUFBYSxFQUNiLFlBQVksRUFDWixRQUFRLENBQ1QsQ0FBQztnQkFDSixDQUFDO2dCQUNELGNBQWMsRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsRUFBRTtvQkFDdkMsSUFBSSxZQUFZLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztvQkFDcEMsTUFBTSxpQkFBaUIsR0FBRyxFQUFFLENBQUMsQ0FBQyxnQ0FBZ0M7b0JBQzlELFlBQVksQ0FBQyxHQUFHLENBQ2QsT0FBTyxFQUNQLENBQUMsWUFBWSxDQUFDLEtBQUssR0FBRyxpQkFBaUIsQ0FBQyxHQUFHLEdBQUcsQ0FDL0MsQ0FBQztvQkFDRixZQUFZLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyw4QkFBOEI7b0JBQ3hELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQkFDdkIsT0FBTyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQzthQUNGLENBQUM7WUFFRixhQUFhLEVBQUUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDO2dCQUNoQyxDQUFDLEVBQUUsR0FBRztnQkFDTixDQUFDLEVBQUUsR0FBRztnQkFDTixPQUFPLEVBQUUsRUFBRTtnQkFDWCxXQUFXLEVBQUUsTUFBTTtnQkFDbkIsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxFQUFFO29CQUN0RCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQ3BCLEdBQUcsRUFDSCxJQUFJLEVBQ0osR0FBRyxFQUNILGFBQWEsRUFDYixZQUFZLEVBQ1osUUFBUSxDQUNULENBQUM7Z0JBQ0osQ0FBQzthQUNGLENBQUM7U0FDSCxDQUFDO1FBQ0EsSUFBSSxLQUFLLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxLQUFLLE9BQU8sRUFBRTtZQUN6RCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNyQixJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztTQUMvQztRQUNELElBQ0UsQ0FBQyxJQUFJLENBQUMsU0FBUztZQUNmLENBQUMsSUFBSSxDQUFDLFNBQVM7WUFDZixDQUFDLElBQUksQ0FBQyxXQUFXO1lBQ2pCLElBQUksQ0FBQyxVQUFVLEVBQ2Y7WUFDQSxLQUFLLENBQUMsUUFBUSxHQUFHLGNBQWMsQ0FBQztZQUNoQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1NBQ3ZCO0lBQ0gsQ0FBQztJQUVELG9DQUFvQztJQUNwQyxlQUFlO1FBQ2IsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDcEQsOEVBQThFO1FBQzlFLElBQUksSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN6RCxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDLENBQUMsdUJBQXVCO1NBQy9FO1FBQ0QsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUUvQyxJQUFJLFNBQVMsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBQztZQUV6Qyw2Q0FBNkM7WUFDN0MsU0FBUyxDQUFDLEdBQUcsQ0FBQztnQkFDWixXQUFXLEVBQUUsS0FBSztnQkFDbEIsVUFBVSxFQUFFLEtBQUs7Z0JBQ2pCLFVBQVUsRUFBRSxLQUFLO2FBQ2xCLENBQUMsQ0FBQztTQUNKO1FBQ0QsTUFBTSxhQUFhLEdBQ2pCLFNBQVMsSUFBSSxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDOUQsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBQ00sSUFBSTtRQUNULElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLElBQUksSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN6RCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUN6QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDO2dCQUN0QixPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO2dCQUNsRCxPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO2FBQzlFLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFO2dCQUM5QyxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUNsRCxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUN4QyxJQUFJLEdBQUcsS0FBSyxZQUFZLEVBQUU7d0JBQ3hCLEdBQUcsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO3FCQUNyQjtnQkFDSCxDQUFDLENBQUMsQ0FBQztnQkFDSCxJQUFJLFlBQVksSUFBSSxZQUFZLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRTtvQkFDaEQsWUFBWSxDQUFDLFFBQVE7d0JBQ25CLFNBQVMsSUFBSSxTQUFTLENBQUMsYUFBYTs0QkFDbEMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhOzRCQUN6QixDQUFDLENBQUMsSUFBSSxDQUFDO29CQUNYLFlBQVksQ0FBQyxHQUFHLENBQUM7d0JBQ2YsT0FBTyxFQUFFLEVBQUU7d0JBQ1gsaUJBQWlCLEVBQUUsQ0FBQzt3QkFDcEIsV0FBVyxFQUFFLE9BQU87cUJBQ3JCLENBQUMsQ0FBQztvQkFDSCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztvQkFDdEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7b0JBQzdELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2lCQUMzRDtxQkFBTTtvQkFDTCxZQUFZLENBQUMsR0FBRyxDQUFDO3dCQUNmLFdBQVcsRUFBRSxLQUFLO3dCQUNsQixVQUFVLEVBQUUsS0FBSzt3QkFDakIsVUFBVSxFQUFFLEtBQUs7cUJBQ2xCLENBQUMsQ0FBQztvQkFDSCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztvQkFDM0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQzVELElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztpQkFDaEM7Z0JBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMzQixDQUFDLENBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQztJQUNNLElBQUk7UUFDVCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLEVBQUU7WUFDOUIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDekIsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNoRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQztnQkFDdEIsT0FBTyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSztnQkFDbEQsT0FBTyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSzthQUM5RSxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTtnQkFDbEQsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDbEQsSUFBSSxZQUFZLEVBQUU7b0JBQ2hCLElBQUksWUFBWSxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7d0JBQ2hDLFlBQVksQ0FBQyxHQUFHLENBQUM7NEJBQ2YsT0FBTyxFQUFFLEVBQUU7NEJBQ1gsaUJBQWlCLEVBQUUsQ0FBQzs0QkFDcEIsV0FBVyxFQUFFLE9BQU87eUJBQ3JCLENBQUMsQ0FBQzt3QkFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7d0JBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO3dCQUNyQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQzt3QkFDdEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7d0JBQzdELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO3FCQUMzRDt5QkFBTTt3QkFDTCxZQUFZLENBQUMsR0FBRyxDQUFDOzRCQUNmLFdBQVcsRUFBRSxLQUFLOzRCQUNsQixVQUFVLEVBQUUsS0FBSzt5QkFDbEIsQ0FBQyxDQUFDO3dCQUNILElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQzt3QkFDL0IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7d0JBQzNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO3FCQUM3RDtvQkFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVE7d0JBQ3JDLGFBQWEsSUFBSSxhQUFhLENBQUMsYUFBYTs0QkFDMUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxhQUFhOzRCQUM3QixDQUFDLENBQUMsSUFBSSxDQUFDO2lCQUNaO2dCQUNELElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7b0JBQ3hDLElBQUksR0FBRyxLQUFLLFlBQVksRUFBRTt3QkFDeEIsR0FBRyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7cUJBQ3JCO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUNILElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDM0IsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFDTyxhQUFhO1FBQ25CLE1BQU0sR0FBRyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7UUFDeEIsR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQ25CLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQztRQUMzQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO1FBQzlDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLEtBQUs7UUFDakIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQzlCLE9BQU87U0FDUjtRQUNELE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVwRCx5RUFBeUU7UUFDekUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVyQixNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLEtBQUssR0FBRztZQUNYLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZO1lBQzFDLEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZO1NBQ3pDLENBQUM7UUFDRixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ2xELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDcEQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FDeEI7WUFDRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7WUFDcEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1NBQ3ZCLEVBQ0Q7WUFDRSxhQUFhLEVBQUUsSUFBSTtTQUNwQixDQUNGLENBQUM7UUFDRixJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUU7WUFDdkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUMzQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFTyxjQUFjLENBQUMsT0FBdUI7UUFDNUMsMkJBQTJCO1FBQzNCLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUU7WUFDekIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7U0FDckI7UUFDRCxJQUFJLE9BQU8sRUFBRTtZQUNYLEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNyRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDbEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzVCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQzFCO1NBQ0Y7SUFDSCxDQUFDO0lBRU8sYUFBYSxDQUFDLEtBQWEsRUFBRSxPQUF1QjtRQUMxRCxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQztZQUMvQixJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDYixHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDWixPQUFPLEVBQUUsUUFBUTtZQUNqQixPQUFPLEVBQUUsUUFBUTtZQUNqQixJQUFJLEVBQUUsU0FBUztZQUNmLE1BQU0sRUFBRSxFQUFFO1lBQ1YsZ0JBQWdCLEVBQUUsS0FBSztZQUN2QixVQUFVLEVBQUUsS0FBSztZQUNqQixXQUFXLEVBQUUsS0FBSztZQUNsQixhQUFhLEVBQUUsS0FBSztTQUNyQixDQUFDLENBQUM7UUFDSCxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQzFCLElBQUksR0FBRyxDQUFDLE9BQU8sRUFBRTtnQkFDZixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN2RSxPQUFPLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQzthQUN0QjtRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUMzQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxHQUFXO1FBQ3JDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsTUFBTSxHQUFHLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN4QixHQUFHLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRTtnQkFDaEIsSUFBSSxRQUFRLEdBQUcsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNyQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDcEIsQ0FBQyxDQUFDO1lBQ0YsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLFlBQVksQ0FBQyxTQUFrQjtRQUMxQyxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2QsT0FBTztTQUNSO1FBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1FBRTdDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3BCLE9BQU8sQ0FBQyxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztTQUMvQztRQUNELElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDckMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztTQUMxQjtRQUNELElBQUksTUFBeUIsQ0FBQztRQUM5QixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDakIsTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7Z0JBQ3ZDLEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDM0MsT0FBTyxFQUFFO29CQUNQLGFBQWEsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztvQkFDbkMsY0FBYyxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO29CQUNwQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztvQkFDdkMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7aUJBQ3ZDO2dCQUNELE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU07Z0JBQzNCLEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUs7YUFDMUIsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7U0FDdkI7YUFBTTtZQUNMLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDO1NBQ3pDO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztRQUM5QixJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQztZQUN0QixPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO1lBQ2xELE9BQU8sRUFBRSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUs7U0FDOUUsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFDTyxhQUFhO1FBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDL0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQ25DLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDM0IsQ0FBQzs7NkdBMXFCVSxlQUFlO2lHQUFmLGVBQWUsK21CQ3BCNUIsaWFBT0E7NEZEYWEsZUFBZTtrQkFMM0IsU0FBUzsrQkFDRSxpQkFBaUI7b0dBS0gsY0FBYztzQkFBckMsU0FBUzt1QkFBQyxXQUFXO2dCQUVTLFVBQVU7c0JBQXhDLFNBQVM7dUJBQUMsa0JBQWtCO2dCQUVwQixHQUFHO3NCQUFYLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUVHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFVRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ08sSUFBSTtzQkFBaEIsS0FBSztnQkFPSSxTQUFTO3NCQUFsQixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU07Z0JBRUcsaUJBQWlCO3NCQUExQixNQUFNO2dCQUVHLGFBQWE7c0JBQXRCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmYWJyaWMgfSBmcm9tICdmYWJyaWMnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBJbnB1dCxcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgVmlld0NoaWxkLFxuICBPbkNoYW5nZXMsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBTaW1wbGVDaGFuZ2VzLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9wZW5DVlNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9vcGVuY3Yuc2VydmljZSc7XG5pbXBvcnQgeyBJVGV4dCB9IGZyb20gJ2ZhYnJpYy9mYWJyaWMtaW1wbCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3plbi1kb2Mtc2Nhbm5lcicsXG4gIHRlbXBsYXRlVXJsOiAnLi96ZW5kdS1kb2Mtc2Nhbm5lci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3plbmR1LWRvYy1zY2FubmVyLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIFplbmR1RG9jU2Nhbm5lciBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcyB7XG4gIEBWaWV3Q2hpbGQoJ2RyYXdDYW5hcycpIF9jYW52YXNFbGVtZW50ITogRWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD47XG5cbiAgQFZpZXdDaGlsZCgnY29tcG9uZW50V3JhcHBlcicpIF9jb21wb25lbnQhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcblxuICBASW5wdXQoKSBzcmMgPSAnJztcblxuICBASW5wdXQoKSB3aWR0aCA9IDA7XG5cbiAgQElucHV0KCkgaGVpZ2h0ID0gMDtcblxuICBASW5wdXQoKSBpc1NjYW5TdGFydDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGNhbkFkZFRleHQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBASW5wdXQoKSBjYW5Eb29kbGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBjdXJyZW50U3RhdGVJbmRleDogbnVtYmVyID0gLTE7XG5cbiAgY2FudmFzU3RhdGVzOiB7IHN0YXRlOiBzdHJpbmc7IGN1c3RvbUNvbnRyb2w6IGFueSB9W10gPSBbXTtcblxuICBpc1Jlc2l6ZTogYm9vbGVhbiA9IGZhbHNlO1xuICBpbml0aWFsTW91c2VZOiBudW1iZXI7XG4gIG9yaWdpbmFsRm9udFNpemU6IG51bWJlcjtcblxuICBASW5wdXQoKSBpc1JlZG9pbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgaXNVbmRvaW5nOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIHNldCBkb25lKGNvbXBsZXRlZDogYm9vbGVhbikge1xuICAgIGNvbnNvbGUubG9nKCdtYXJrIGFzIGNvbXBsZXRlZCcsY29tcGxldGVkKTtcbiAgICBpZiAoY29tcGxldGVkKSB7XG4gICAgICB0aGlzLmNvbXBsZXRlU2Nhbihjb21wbGV0ZWQpO1xuICAgIH1cbiAgfVxuXG4gIEBPdXRwdXQoKSBleHRyYWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPEhUTUxDYW52YXNFbGVtZW50PigpO1xuXG4gIEBPdXRwdXQoKSBjb3JuZXJzQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBAT3V0cHV0KCkgY2FuQWRkVGV4dE9yRG9vbGUgPSBuZXcgRXZlbnRFbWl0dGVyPHt9PigpO1xuXG4gIEBPdXRwdXQoKSBjYW5SZWRvT3JVbmRvID0gbmV3IEV2ZW50RW1pdHRlcjx7XG4gICAgY2FuUmVkbzogYm9vbGVhbjtcbiAgICBjYW5VbmRvOiBib29sZWFuO1xuICB9PigpO1xuXG4gIHByaXZhdGUgc2NyZWVuUG9pbnRzOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH1bXSA9IFtdO1xuXG4gIHByaXZhdGUgX2NhbnZhcyE6IGZhYnJpYy5DYW52YXM7XG5cbiAgcHJpdmF0ZSBfY29ybmVyc1BnITogZmFicmljLlBvbHlnb247XG5cbiAgcHJpdmF0ZSBfc2NhbGVGYWN0b3IgPSAxO1xuXG4gIHByaXZhdGUgX2NvbnRyb2xzOiBmYWJyaWMuQ2lyY2xlW10gPSBbXTtcblxuICBzZWxlY3RlZENvbG9yOiBzdHJpbmcgPSAnIzEyMTIxMic7XG5cbiAgaXNTY2FuZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICB0ZXh0QWRkZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgaWNvbnMgPSB7XG4gICAgY3Jvc3M6IG5ldyBJbWFnZSgpLFxuICAgIHJvdGF0ZTogbmV3IEltYWdlKCksXG4gICAgZXhwYW5kOiBuZXcgSW1hZ2UoKSxcbiAgfTtcbiAgcHJpdmF0ZSBJbWFnZSA9IHtcbiAgICBoZWlnaHQ6IDAsXG4gICAgd2lkdGg6IDAsXG4gIH07XG4gIGJvcmRlcldpZHRoOiBudW1iZXIgPSA1O1xuICBjb2xvcnMgPSBbXG4gICAgeyBoZXhDb2RlOiAnI0ZGRkZGRicsIHNlbGVjdGVkOiBmYWxzZSB9LFxuICAgIHsgaGV4Q29kZTogJyMxMjEyMTInLCBzZWxlY3RlZDogZmFsc2UgfSxcbiAgICB7IGhleENvZGU6ICcjMjE4OEQ5Jywgc2VsZWN0ZWQ6IGZhbHNlIH0sXG4gICAgeyBoZXhDb2RlOiAnI0RDM0UzMycsIHNlbGVjdGVkOiBmYWxzZSB9LFxuICAgIHsgaGV4Q29kZTogJyMyMTk2NTMnLCBzZWxlY3RlZDogZmFsc2UgfSxcbiAgICB7IGhleENvZGU6ICcjRjFCMTBCJywgc2VsZWN0ZWQ6IGZhbHNlIH0sXG4gICAgeyBoZXhDb2RlOiAnIzAwRjBGRicsIHNlbGVjdGVkOiBmYWxzZSB9LFxuICBdO1xuICByZXNpemVJY29uOiBIVE1MRWxlbWVudDtcbiAgcm90YXRlSWNvbjogSFRNTEVsZW1lbnQ7XG4gIHJlbW92ZUljb246IEhUTUxFbGVtZW50O1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9vcGVuY3Y6IE9wZW5DVlNlcnZpY2UpIHt9XG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmljb25zLmNyb3NzLnNyYyA9ICdhc3NldHMvbmctemVuZHVpdC9pY29ucy9jcm9zcy5zdmcnO1xuICAgIHRoaXMuaWNvbnMucm90YXRlLnNyYyA9ICdhc3NldHMvbmctemVuZHVpdC9pY29ucy9yb3RhdGUuc3ZnJztcbiAgICB0aGlzLmljb25zLmV4cGFuZC5zcmM9ICdhc3NldHMvbmctemVuZHVpdC9pY29ucy9leHBhbmQuc3ZnJztcbiAgICBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMuaW5pdCgpO1xuICAgICAgLy8gQWRkIGFuIGV2ZW50IGxpc3RlbmVyIGZvciBjYW52YXMgZWRpdHNcbiAgICB9LCAxKTtcbiAgfVxuXG4gIHB1YmxpYyBvbkNhbnZhc0VkaXQoKSB7XG4gICAgbGV0IG9iamVjdHMgPSB0aGlzLl9jYW52YXMuZ2V0T2JqZWN0cygpO1xuICAgIGlmIChvYmplY3RzICYmIG9iamVjdHMubGVuZ3RoKVxuICAgICAgdGhpcy5fY2FudmFzLl9hY3RpdmVPYmplY3QgPSBvYmplY3RzW29iamVjdHMubGVuZ3RoIC0gMV07XG4gICAgaWYgKCF0aGlzLmlzU2NhblN0YXJ0ICYmICF0aGlzLmlzUmVkb2luZyAmJiAhdGhpcy5pc1VuZG9pbmcpIHtcbiAgICAgIHRoaXMuY2FuUmVkb09yVW5kby5lbWl0KHtcbiAgICAgICAgY2FuVW5kbzogdGhpcy5jdXJyZW50U3RhdGVJbmRleCA+PSAwID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgICBjYW5SZWRvOiB0aGlzLmN1cnJlbnRTdGF0ZUluZGV4IDwgdGhpcy5jYW52YXNTdGF0ZXMubGVuZ3RoIC0gMSA/IHRydWUgOiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zYXZlQ2FudmFzU3RhdGUoKTtcbiAgICB9XG4gIH1cbiAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcblxuICAgIC8vIFdoZW4gc3JjIGNoYW5nZXNcbiAgICBpZiAoY2hhbmdlc1snc3JjJ10gJiYgdGhpcy5fY2FudmFzKSB7XG4gICAgICB0aGlzLmJ1aWxkKCk7XG4gICAgfVxuICAgIC8vV2hlbiB1c2VyIHN0YXJ0IHNjYW5cbiAgICBpZiAoY2hhbmdlc1snaXNTY2FuU3RhcnQnXSAmJiBjaGFuZ2VzWydpc1NjYW5TdGFydCddLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgaWYgKHRoaXMuc3JjICYmIHRoaXMuX2NhbnZhcyAmJiB0aGlzLmlzU2NhblN0YXJ0KSB7XG4gICAgICAgIHRoaXMuYWRkUG9pbnRzVG9kb2MoKTtcbiAgICAgICAgdGhpcy5jYW5Eb29kbGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fY2FudmFzLmlzRHJhd2luZ01vZGUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1NjYW5lZCA9IHRydWU7XG4gICAgICAgIHRoaXMuX2NhbnZhcy5zZWxlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy50ZXh0QWRkZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gV2hlbiB1c2VyIHdhbnRzIHRvIGRyYXdcbiAgICBpZiAoXG4gICAgICBjaGFuZ2VzWydjYW5Eb29kbGUnXSAmJlxuICAgICAgY2hhbmdlc1snY2FuRG9vZGxlJ10uY3VycmVudFZhbHVlICYmXG4gICAgICB0aGlzLl9jYW52YXNcbiAgICApIHtcbiAgICAgIGlmICh0aGlzLmNhbkRvb2RsZSkge1xuICAgICAgICB0aGlzLl9jYW52YXMuaXNEcmF3aW5nTW9kZSA9IHRoaXMuY2FuRG9vZGxlO1xuICAgICAgICB0aGlzLl9jYW52YXMuZnJlZURyYXdpbmdCcnVzaCA9IHRoaXMuY2FuRG9vZGxlXG4gICAgICAgICAgPyBuZXcgZmFicmljLlBlbmNpbEJydXNoKHRoaXMuX2NhbnZhcylcbiAgICAgICAgICA6IG51bGw7XG4gICAgICAgIHRoaXMuX2NhbnZhcy5mcmVlRHJhd2luZ0JydXNoLndpZHRoID0gMTA7XG4gICAgICAgIHRoaXMuX2NhbnZhcy5mcmVlRHJhd2luZ0JydXNoLmNvbG9yID0gdGhpcy5zZWxlY3RlZENvbG9yO1xuICAgICAgICB0aGlzLl9jYW52YXMuc2VsZWN0aW9uID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNTY2FuU3RhcnQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy50ZXh0QWRkZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fY2FudmFzLnJlbmRlckFsbCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBXaGVuIHVzZXIgd2FudHMgdG8gYWRkIHRleHRcbiAgICBpZiAoXG4gICAgICBjaGFuZ2VzWydjYW5BZGRUZXh0J10gJiZcbiAgICAgIGNoYW5nZXNbJ2NhbkFkZFRleHQnXS5jdXJyZW50VmFsdWUgJiZcbiAgICAgIHRoaXMuY2FuQWRkVGV4dFxuICAgICkge1xuICAgICAgdGhpcy5jYW5Eb29kbGUgPSBmYWxzZTtcbiAgICAgIHRoaXMuX2NhbnZhcy5pc0RyYXdpbmdNb2RlID0gZmFsc2U7XG4gICAgICB0aGlzLmlzU2NhblN0YXJ0ID0gZmFsc2U7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWydpc1VuZG9pbmcnXSAmJiBjaGFuZ2VzWydpc1VuZG9pbmcnXS5jdXJyZW50VmFsdWUpIHRoaXMudW5kbygpO1xuICAgIGlmIChjaGFuZ2VzWydpc1JlZG9pbmcnXSAmJiBjaGFuZ2VzWydpc1JlZG9pbmcnXS5jdXJyZW50VmFsdWUpIHRoaXMucmVkbygpO1xuICB9XG4gIC8vIFRvIGNoYW5nZSB0aGUgY29sb3Igb2YgYnJ1c2ggb3IgdGV4dFxuICBjaG5nQ2xyVGV4dE9yQnJ1c2goY29sb3I6IHN0cmluZywgY2hhbmdlRm9yOiBzdHJpbmcpIHtcbiAgICB0aGlzLnNlbGVjdGVkQ29sb3IgPSBjb2xvcjtcbiAgICB0aGlzLmNvbG9ycy5tYXAoKGNsciwgaW5kZXgpID0+IHtcbiAgICAgIHRoaXMuY29sb3JzW2luZGV4XSA9IHsgLi4udGhpcy5jb2xvcnNbaW5kZXhdLCBzZWxlY3RlZDogZmFsc2UgfTtcbiAgICAgIGlmICh0aGlzLmNvbG9yc1tpbmRleF0uaGV4Q29kZSA9PT0gY29sb3IpIHtcbiAgICAgICAgdGhpcy5jb2xvcnNbaW5kZXhdID0geyAuLi50aGlzLmNvbG9yc1tpbmRleF0sIHNlbGVjdGVkOiB0cnVlIH07XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGNoYW5nZUZvciA9PT0gJ3RleHQnKSB7XG4gICAgICBjb25zdCBhY3RpdmVPYmplY3QgPSB0aGlzLl9jYW52YXMuZ2V0QWN0aXZlT2JqZWN0KCk7XG4gICAgICBpZiAoYWN0aXZlT2JqZWN0ICYmIGFjdGl2ZU9iamVjdC50eXBlID09PSAnaS10ZXh0Jykge1xuICAgICAgICAvLyBDaGVjayBpZiBhbiBhY3RpdmUgdGV4dCBvYmplY3QgaXMgc2VsZWN0ZWRcbiAgICAgICAgYWN0aXZlT2JqZWN0LnNldCgnZmlsbCcsIHRoaXMuc2VsZWN0ZWRDb2xvcik7IC8vIFVwZGF0ZSB0aGUgZmlsbCBjb2xvclxuICAgICAgICB0aGlzLl9jYW52YXMucmVuZGVyQWxsKCk7IC8vIFJlbmRlciB0aGUgY2FudmFzIHRvIHNlZSB0aGUgY2hhbmdlc1xuICAgICAgfVxuICAgICAgdGhpcy5fY2FudmFzLnJlbmRlckFsbCgpO1xuICAgICAgLy8gdGhpcy5vbkNhbnZhc0VkaXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fY2FudmFzLmZyZWVEcmF3aW5nQnJ1c2guY29sb3IgPSBjb2xvcjtcbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZENvbG9yID0gY29sb3I7XG4gIH1cbiAgYXN5bmMgYWRkUG9pbnRzVG9kb2MoKSB7XG4gICAgY29uc3QgY29ybmVycyA9IGF3YWl0IHRoaXMuX29wZW5jdi5nZXRQYXBlckNvcm5lcnMoXG4gICAgICB0aGlzLl9jYW52YXMudG9EYXRhVVJMKHtcbiAgICAgICAgZm9ybWF0OiAnanBlZycsXG4gICAgICAgIHF1YWxpdHk6IDEsXG4gICAgICB9KSxcbiAgICAgIHRoaXMuSW1hZ2UuaGVpZ2h0LFxuICAgICAgdGhpcy5JbWFnZS53aWR0aFxuICAgICk7XG4gICAgaWYgKGNvcm5lcnMpIHtcbiAgICAgIHRoaXMuc2NyZWVuUG9pbnRzID0gW1xuICAgICAgICBjb3JuZXJzLnRvcExlZnRDb3JuZXIsXG4gICAgICAgIGNvcm5lcnMudG9wUmlnaHRDb3JuZXIsXG4gICAgICAgIGNvcm5lcnMuYm90dG9tUmlnaHRDb3JuZXIsXG4gICAgICAgIGNvcm5lcnMuYm90dG9tTGVmdENvcm5lcixcbiAgICAgIF07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYGNhbid0IGRldGVjdCBkb2N1bWVudCBjb3JuZXJzYCk7XG4gICAgICBjb25zdCB3aWR0aCA9IHRoaXMuX2NhbnZhcy5nZXRXaWR0aCgpIC8gdGhpcy5fc2NhbGVGYWN0b3I7XG4gICAgICBjb25zdCBoZWlnaHQgPSB0aGlzLl9jYW52YXMuZ2V0SGVpZ2h0KCkgLyB0aGlzLl9zY2FsZUZhY3RvcjtcbiAgICAgIGNvbnN0IG9mZnNldCA9IDIwO1xuICAgICAgdGhpcy5zY3JlZW5Qb2ludHMgPSBbXG4gICAgICAgIHsgeDogb2Zmc2V0LCB5OiAwIH0sXG4gICAgICAgIHsgeDogd2lkdGggLSBvZmZzZXQsIHk6IDAgfSxcbiAgICAgICAgeyB4OiB3aWR0aCAtIG9mZnNldCwgeTogaGVpZ2h0IC0gb2Zmc2V0IH0sXG4gICAgICAgIHsgeDogb2Zmc2V0LCB5OiBoZWlnaHQgLSBvZmZzZXQgfSxcbiAgICAgIF07XG4gICAgfVxuXG4gICAgLy8gYWRkIHBvbHlnb25cbiAgICAvL1xuICAgIHRoaXMuX2Nvcm5lcnNQZyA9IG5ldyBmYWJyaWMuUG9seWdvbih0aGlzLnNjcmVlblBvaW50cywge1xuICAgICAgc3Ryb2tlOiAnIzIxODhkOScsXG4gICAgICBzdHJva2VXaWR0aDogMTAsXG4gICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcbiAgICAgIGZpbGw6ICdyZ2JhKDMzLCAxMzYsIDIxNywgMC4xKScsXG4gICAgICBoYXNCb3JkZXJzOiB0cnVlLFxuICAgICAgb2JqZWN0Q2FjaGluZzogZmFsc2UsXG4gICAgfSk7XG4gICAgdGhpcy5fY2FudmFzLmFkZCh0aGlzLl9jb3JuZXJzUGcpO1xuICAgIHRoaXMuY3JlYXRlQ29udHJvbHModGhpcy5fY29ybmVyc1BnKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5pdChzcmM/OiBzdHJpbmcpIHtcbiAgICAvLyBDcmVhdGUgY2FudmFzIHdpdGggbmV3IGNoYW5nZWQgc3JjXG4gICAgaWYgKHNyYykge1xuICAgICAgdGhpcy5jcmVhdGVDYW52YXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCF0aGlzLl9jYW52YXNFbGVtZW50IHx8ICF0aGlzLl9jYW52YXNFbGVtZW50Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAvLyBjYW52YXMgaXMgbm90IHJlYWR5XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2NhbnZhcykge1xuICAgICAgICAgIC8vIGNhbnZhcyBhbHJlYWR5IGluaXRhbGl6ZWRcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVDYW52YXMoKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgY3JlYXRlQ2FudmFzKCkge1xuICAgIC8vIGRvY3VtZW50YXRpb246IGh0dHA6Ly9mYWJyaWNqcy5jb20vZG9jcy9mYWJyaWMuQ2FudmFzLmh0bWxcbiAgICBsZXQgY2FudmFzID0gdGhpcy5fY2FudmFzRWxlbWVudC5uYXRpdmVFbGVtZW50O1xuICAgIHRoaXMuX2NhbnZhcyA9IG5ldyBmYWJyaWMuQ2FudmFzKGNhbnZhcywge1xuICAgICAgYmFja2dyb3VuZENvbG9yOiAnd2hpdGUnLFxuICAgICAgc2VsZWN0aW9uOiBmYWxzZSxcbiAgICB9KTtcbiAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IHRoaXMuZ2V0Q2FudmFzU2l6ZSgpO1xuICAgIHRoaXMuX2NhbnZhcy5zZXRXaWR0aCh3aWR0aCk7XG4gICAgdGhpcy5fY2FudmFzLnNldEhlaWdodChoZWlnaHQpO1xuICAgIHRoaXMuX2NhbnZhcy5vbignb2JqZWN0OmFkZGVkJywgdGhpcy5vbkNhbnZhc0VkaXQuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5fY2FudmFzLm9uKCdvYmplY3Q6bW9kaWZpZWQnLCB0aGlzLm9uQ2FudmFzRWRpdC5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLl9jYW52YXMub24oJ21vdXNlOmRvd24nLCB0aGlzLmFkZFRleHRPbkNsaWNrLmJpbmQodGhpcykpO1xuICAgIHRoaXMuX2NhbnZhcy5vbignbW91c2U6bW92ZScsIHRoaXMucmVzaXplVGV4dC5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLl9jYW52YXMub24oJ21vdXNlOnVwJywgdGhpcy5zdG9wUmVzaXplVGV4dC5iaW5kKHRoaXMpKTtcbiAgICBpZiAodGhpcy5zcmMpIHtcbiAgICAgIGF3YWl0IHRoaXMuYnVpbGQoKTtcbiAgICB9XG4gIH1cblxuICByZW5kZXJJY29uKFxuICAgIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELFxuICAgIGxlZnQ6IG51bWJlcixcbiAgICB0b3A6IG51bWJlcixcbiAgICBzdHlsZU92ZXJyaWRlLFxuICAgIGZhYnJpY09iamVjdDogZmFicmljLk9iamVjdCxcbiAgICBpY29uTmFtZTogc3RyaW5nXG4gICkge1xuICAgIHZhciBzaXplID0gNDI7XG4gICAgdmFyIGljb25CYWNrZ3JvdW5kU2l6ZSA9IDUwOyAvLyBBZGp1c3QgdGhlIHNpemUgYXMgbmVlZGVkXG4gICAgY3R4LnNhdmUoKTtcblxuICAgIC8vIERyYXcgYSBiYWNrZ3JvdW5kIGNpcmNsZSBiZWhpbmQgdGhlIGljb25cbiAgICBjdHguZmlsbFN0eWxlID0gJ3doaXRlJzsgLy8gU2V0IHRoZSBiYWNrZ3JvdW5kIGNvbG9yXG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGN0eC5hcmMobGVmdCwgdG9wIC0gMTAsIGljb25CYWNrZ3JvdW5kU2l6ZSAvIDIsIDAsIDIgKiBNYXRoLlBJKTtcbiAgICBjdHguZmlsbCgpO1xuXG4gICAgdmFyIGltZyA9IHRoaXMuaWNvbnNbaWNvbk5hbWVdO1xuICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbiAoKXt9XG4gICAgY3R4LnRyYW5zbGF0ZShsZWZ0LCB0b3AgLSAxMCk7XG4gICAgY3R4LnJvdGF0ZShmYWJyaWMudXRpbC5kZWdyZWVzVG9SYWRpYW5zKGZhYnJpY09iamVjdC5hbmdsZSkpO1xuICAgIGN0eC5kcmF3SW1hZ2UoaW1nLCAtc2l6ZSAvIDIsIC1zaXplIC8gMiwgc2l6ZSwgc2l6ZSk7XG4gICAgY3R4LnJlc3RvcmUoKTtcbiAgfVxuXG4gIHN0b3BSZXNpemVUZXh0KGV2ZW50OmFueSkge1xuICAgIGlmKHRoaXMuaXNSZXNpemUpe1xuICAgICAgdGhpcy5zYXZlQ2FudmFzU3RhdGUoKVxuICAgICAgdGhpcy5pc1Jlc2l6ZSA9IGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXNpemVUZXh0KGV2ZW50OiBhbnkpIHtcbiAgICBpZiAodGhpcy5pc1Jlc2l6ZSkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0O1xuICAgICAgY29uc3QgZGVsdGFZID0gZXZlbnQuZS5jbGllbnRZIC0gdGhpcy5pbml0aWFsTW91c2VZO1xuXG4gICAgICAvLyBMaW1pdCB0aGUgc2NhbGluZyBmYWN0b3IgdG8gcHJldmVudCBleGNlc3NpdmUgcmVzaXppbmdcbiAgICAgIGNvbnN0IHNjYWxpbmdGYWN0b3IgPSBNYXRoLm1pbigyLCBNYXRoLm1heCgwLjUsIDEgKyBkZWx0YVkgLyAxMDApKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuZXcgZm9udCBzaXplIGJhc2VkIG9uIHRoZSBvcmlnaW5hbCBzaXplIGFuZCBzY2FsaW5nIGZhY3RvclxuICAgICAgY29uc3QgbmV3Rm9udFNpemUgPSB0aGlzLm9yaWdpbmFsRm9udFNpemUgKiBzY2FsaW5nRmFjdG9yO1xuXG4gICAgICAvLyBTZXQgdGhlIGZvbnQgc2l6ZSBvZiB0aGUgdGV4dCBvYmplY3RcbiAgICAgIHRhcmdldC5mb250U2l6ZSA9IG5ld0ZvbnRTaXplO1xuXG4gICAgICAvLyBSZS1yZW5kZXIgdGhlIGNhbnZhcyB0byBzZWUgdGhlIGxpdmUgY2hhbmdlXG4gICAgICBldmVudC50YXJnZXQuY2FudmFzLnJlbmRlckFsbCgpO1xuICAgIH1cbiAgfVxuICBhZGRUZXh0T25DbGljayhldmVudDogYW55KSB7XG4gICAgbGV0IF90ZXh0OiBJVGV4dCA9IG5ldyBmYWJyaWMuSVRleHQoJ1R5cGUgeW91ciB0ZXh0IGhlcmUnLCB7XG4gICAgICBsZWZ0OiBldmVudC5wb2ludGVyLngsXG4gICAgICB0b3A6IGV2ZW50LnBvaW50ZXIueSxcbiAgICAgIGZpbGw6IHRoaXMuc2VsZWN0ZWRDb2xvcixcbiAgICAgIGZvbnRTaXplOiA1MCxcbiAgICAgIGZvbnRGYW1pbHk6ICdSb2JvdG8nLFxuICAgICAgc2VsZWN0YWJsZTogdHJ1ZSxcbiAgICAgIGZvbnRXZWlnaHQ6IDQwMCxcbiAgICAgIGJvcmRlclNjYWxlRmFjdG9yOiAzLFxuICAgICAgYm9yZGVyQ29sb3I6ICd3aGl0ZScsXG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6ICd0cmFuc3BhcmVudCcsIC8vIFNldCBiYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSB0ZXh0IGJveFxuICAgICAgY29ybmVyQ29sb3I6ICd3aGl0ZScsIC8vIFNldCBjb3JuZXIgKHJlc2l6ZSBoYW5kbGUpIGNvbG9yIG9mIHRoZSB0ZXh0IGJveFxuICAgICAgcGFkZGluZzogNDIsIC8vIFNldCBwYWRkaW5nIGluc2lkZSB0aGUgdGV4dCBib3hcbiAgICAgIHdpZHRoOiAyMDAsIC8vIFNldCB0aGUgaW5pdGlhbCB3aWR0aCBvZiB0aGUgdGV4dCBib3hcbiAgICB9KTtcbiAgICAgIC8vQ3VzdG9tIGNvbnRyb2xzIGZvciBhZGQgdGV4dCBib3hcbiAgbGV0IGN1c3RvbUNvbnRyb2xzID0ge1xuICAgIHJlbW92ZUNvbnRyb2w6IG5ldyBmYWJyaWMuQ29udHJvbCh7XG4gICAgICB4OiAtMC41LFxuICAgICAgeTogLTAuNSxcbiAgICAgIG9mZnNldFk6IDE2LFxuICAgICAgY3Vyc29yU3R5bGU6ICdwb2ludGVyJyxcbiAgICAgIHJlbmRlcjogKGN0eCwgbGVmdCwgdG9wLCBzdHlsZU92ZXJyaWRlLCBmYWJyaWNPYmplY3QpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVySWNvbihcbiAgICAgICAgICBjdHgsXG4gICAgICAgICAgbGVmdCxcbiAgICAgICAgICB0b3AsXG4gICAgICAgICAgc3R5bGVPdmVycmlkZSxcbiAgICAgICAgICBmYWJyaWNPYmplY3QsXG4gICAgICAgICAgJ2Nyb3NzJ1xuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIG1vdXNlVXBIYW5kbGVyOiAoZXZlbnREYXRhLCB0cmFuc2Zvcm0pID0+IHtcbiAgICAgICAgdmFyIHRhcmdldCA9IHRyYW5zZm9ybS50YXJnZXQ7XG4gICAgICAgIHZhciBjYW52YXMgPSB0YXJnZXQuY2FudmFzO1xuICAgICAgICBjYW52YXMucmVtb3ZlKHRhcmdldCk7XG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XG4gICAgICAgIHRoaXMuc2F2ZUNhbnZhc1N0YXRlKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICB9KSxcblxuICAgIHJvdGF0ZUNvbnRyb2w6IG5ldyBmYWJyaWMuQ29udHJvbCh7XG4gICAgICB4OiAwLjUsXG4gICAgICB5OiAtMC41LFxuICAgICAgb2Zmc2V0WTogMTYsXG4gICAgICBjdXJzb3JTdHlsZTogJ3BvaW50ZXInLFxuICAgICAgcmVuZGVyOiAoY3R4LCBsZWZ0LCB0b3AsIHN0eWxlT3ZlcnJpZGUsIGZhYnJpY09iamVjdCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJJY29uKFxuICAgICAgICAgIGN0eCxcbiAgICAgICAgICBsZWZ0LFxuICAgICAgICAgIHRvcCxcbiAgICAgICAgICBzdHlsZU92ZXJyaWRlLFxuICAgICAgICAgIGZhYnJpY09iamVjdCxcbiAgICAgICAgICAncm90YXRlJ1xuICAgICAgICApO1xuICAgICAgfSxcbiAgICAgIG1vdXNlVXBIYW5kbGVyOiAoZXZlbnREYXRhLCB0cmFuc2Zvcm0pID0+IHtcbiAgICAgICAgbGV0IGZhYnJpY09iamVjdCA9IHRyYW5zZm9ybS50YXJnZXQ7XG4gICAgICAgIGNvbnN0IHJvdGF0aW9uSW5jcmVtZW50ID0gMzA7IC8vIFJvdGF0aW9uIGluY3JlbWVudCBpbiBkZWdyZWVzXG4gICAgICAgIGZhYnJpY09iamVjdC5zZXQoXG4gICAgICAgICAgJ2FuZ2xlJyxcbiAgICAgICAgICAoZmFicmljT2JqZWN0LmFuZ2xlICsgcm90YXRpb25JbmNyZW1lbnQpICUgMzYwXG4gICAgICAgICk7XG4gICAgICAgIGZhYnJpY09iamVjdC5zZXRDb29yZHMoKTsgLy8gVXBkYXRlIG9iamVjdCdzIGNvb3JkaW5hdGVzXG4gICAgICAgIHRoaXMuc2F2ZUNhbnZhc1N0YXRlKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSxcbiAgICB9KSxcblxuICAgIGV4cGFudENvbnRyb2w6IG5ldyBmYWJyaWMuQ29udHJvbCh7XG4gICAgICB4OiAwLjUsXG4gICAgICB5OiAwLjUsXG4gICAgICBvZmZzZXRZOiAxNixcbiAgICAgIGN1cnNvclN0eWxlOiAnZ3JhYicsXG4gICAgICByZW5kZXI6IChjdHgsIGxlZnQsIHRvcCwgc3R5bGVPdmVycmlkZSwgZmFicmljT2JqZWN0KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlckljb24oXG4gICAgICAgICAgY3R4LFxuICAgICAgICAgIGxlZnQsXG4gICAgICAgICAgdG9wLFxuICAgICAgICAgIHN0eWxlT3ZlcnJpZGUsXG4gICAgICAgICAgZmFicmljT2JqZWN0LFxuICAgICAgICAgICdleHBhbmQnXG4gICAgICAgICk7XG4gICAgICB9LFxuICAgIH0pLFxuICB9O1xuICAgIGlmIChldmVudC50cmFuc2Zvcm0gJiYgZXZlbnQudHJhbnNmb3JtLmFjdGlvbiA9PT0gJ3NjYWxlJykge1xuICAgICAgdGhpcy5pc1Jlc2l6ZSA9IHRydWU7XG4gICAgICB0aGlzLmluaXRpYWxNb3VzZVkgPSBldmVudC5lLmNsaWVudFk7XG4gICAgICB0aGlzLm9yaWdpbmFsRm9udFNpemUgPSBldmVudC50YXJnZXQuZm9udFNpemU7XG4gICAgfVxuICAgIGlmIChcbiAgICAgICF0aGlzLnRleHRBZGRlZCAmJlxuICAgICAgIXRoaXMuY2FuRG9vZGxlICYmXG4gICAgICAhdGhpcy5pc1NjYW5TdGFydCAmJlxuICAgICAgdGhpcy5jYW5BZGRUZXh0XG4gICAgKSB7XG4gICAgICBfdGV4dC5jb250cm9scyA9IGN1c3RvbUNvbnRyb2xzO1xuICAgICAgdGhpcy5fY2FudmFzLmFkZChfdGV4dCk7XG4gICAgICB0aGlzLl9jYW52YXMucmVuZGVyQWxsKCk7XG4gICAgICB0aGlzLnRleHRBZGRlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gRnVuY3Rpb24gdG8gc2F2ZSB0aGUgY2FudmFzIHN0YXRlXG4gIHNhdmVDYW52YXNTdGF0ZSgpIHtcbiAgICBjb25zdCBzdGF0ZSA9IEpTT04uc3RyaW5naWZ5KHRoaXMuX2NhbnZhcy50b0pTT04oKSk7XG4gICAgLy8gY29uc3Qgc3RhdGUgPSB0aGlzLl9jYW52YXMuZ2V0T2JqZWN0cygpW3RoaXMuX2NhbnZhcy5nZXRPYmplY3RzLmxlbmd0aCAtIDFdXG4gICAgaWYgKHRoaXMuY3VycmVudFN0YXRlSW5kZXggPCB0aGlzLmNhbnZhc1N0YXRlcy5sZW5ndGggLSAxKSB7XG4gICAgICB0aGlzLmNhbnZhc1N0YXRlcy5sZW5ndGggPSB0aGlzLmN1cnJlbnRTdGF0ZUluZGV4ICsgMTsgLy8gUmVtb3ZlIGZ1dHVyZSBzdGF0ZXNcbiAgICB9XG4gICAgbGV0IGFjdGl2ZU9iaiA9IHRoaXMuX2NhbnZhcy5nZXRBY3RpdmVPYmplY3QoKTtcblxuICAgIGlmIChhY3RpdmVPYmogJiYgYWN0aXZlT2JqLnR5cGUgPT09ICdwYXRoJyl7XG5cbiAgICAgIC8vIHNldCByZW1vdmUgYm9yZGVyIGFuZCBjb250cm9scyBmb3IgZHJhd2luZ1xuICAgICAgYWN0aXZlT2JqLnNldCh7XG4gICAgICAgIGhhc0NvbnRyb2xzOiBmYWxzZSxcbiAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXG4gICAgICAgIGhhc0JvcmRlcnM6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IGN1c3RvbUNvbnRyb2wgPVxuICAgICAgYWN0aXZlT2JqICYmIGFjdGl2ZU9iai5jb250cm9scyA/IGFjdGl2ZU9iai5jb250cm9scyA6IG51bGw7XG4gICAgdGhpcy5jYW52YXNTdGF0ZXMucHVzaCh7IHN0YXRlLCBjdXN0b21Db250cm9sIH0pO1xuICAgIHRoaXMuY3VycmVudFN0YXRlSW5kZXgrKztcbiAgfVxuICBwdWJsaWMgcmVkbygpIHtcbiAgICB0aGlzLmlzUmVkb2luZyA9IHRydWU7XG4gICAgaWYgKHRoaXMuY3VycmVudFN0YXRlSW5kZXggPCB0aGlzLmNhbnZhc1N0YXRlcy5sZW5ndGggLSAxKSB7XG4gICAgICB0aGlzLmN1cnJlbnRTdGF0ZUluZGV4Kys7XG4gICAgICBjb25zdCBuZXh0U3RhdGUgPSB0aGlzLmNhbnZhc1N0YXRlc1t0aGlzLmN1cnJlbnRTdGF0ZUluZGV4XTtcbiAgICAgIHRoaXMuY2FuUmVkb09yVW5kby5lbWl0KHtcbiAgICAgICAgY2FuVW5kbzogdGhpcy5jdXJyZW50U3RhdGVJbmRleCA+IDAgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgIGNhblJlZG86IHRoaXMuY3VycmVudFN0YXRlSW5kZXggPCB0aGlzLmNhbnZhc1N0YXRlcy5sZW5ndGggLSAxID8gdHJ1ZSA6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgICB0aGlzLl9jYW52YXMubG9hZEZyb21KU09OKG5leHRTdGF0ZS5zdGF0ZSwgKCkgPT4ge1xuICAgICAgICBsZXQgYWN0aXZlT2JqZWN0ID0gdGhpcy5fY2FudmFzLmdldEFjdGl2ZU9iamVjdCgpO1xuICAgICAgICB0aGlzLl9jYW52YXMuZ2V0T2JqZWN0cygpLmZvckVhY2goKG9iaikgPT4ge1xuICAgICAgICAgIGlmIChvYmogIT09IGFjdGl2ZU9iamVjdCkge1xuICAgICAgICAgICAgb2JqLmV2ZW50ZWQgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWN0aXZlT2JqZWN0ICYmIGFjdGl2ZU9iamVjdC50eXBlICE9PSAncGF0aCcpIHtcbiAgICAgICAgICBhY3RpdmVPYmplY3QuY29udHJvbHMgPVxuICAgICAgICAgICAgbmV4dFN0YXRlICYmIG5leHRTdGF0ZS5jdXN0b21Db250cm9sXG4gICAgICAgICAgICAgID8gbmV4dFN0YXRlLmN1c3RvbUNvbnRyb2xcbiAgICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICAgIGFjdGl2ZU9iamVjdC5zZXQoe1xuICAgICAgICAgICAgcGFkZGluZzogNDIsXG4gICAgICAgICAgICBib3JkZXJTY2FsZUZhY3RvcjogMyxcbiAgICAgICAgICAgIGJvcmRlckNvbG9yOiAnd2hpdGUnLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMudGV4dEFkZGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmNhbkFkZFRleHRPckRvb2xlLmVtaXQoeyBrZXk6ICdkb29kbGUnLCB2YWx1ZTogZmFsc2UgfSk7XG4gICAgICAgICAgdGhpcy5jYW5BZGRUZXh0T3JEb29sZS5lbWl0KHsga2V5OiAndGV4dCcsIHZhbHVlOiB0cnVlIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFjdGl2ZU9iamVjdC5zZXQoe1xuICAgICAgICAgICAgaGFzQ29udHJvbHM6IGZhbHNlLFxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXG4gICAgICAgICAgICBoYXNCb3JkZXJzOiBmYWxzZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLmNhbkFkZFRleHRPckRvb2xlLmVtaXQoeyBrZXk6ICd0ZXh0JywgdmFsdWU6IGZhbHNlIH0pO1xuICAgICAgICAgIHRoaXMuY2FuQWRkVGV4dE9yRG9vbGUuZW1pdCh7IGtleTogJ2Rvb2RsZScsIHZhbHVlOiB0cnVlIH0pO1xuICAgICAgICAgIHRoaXMuX2NhbnZhcy5zZWxlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9jYW52YXMucmVuZGVyQWxsKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcHVibGljIHVuZG8oKSB7XG4gICAgdGhpcy5pc1VuZG9pbmcgPSB0cnVlO1xuICAgIGlmICh0aGlzLmN1cnJlbnRTdGF0ZUluZGV4ID4gMCkge1xuICAgICAgdGhpcy5jdXJyZW50U3RhdGVJbmRleC0tO1xuICAgICAgY29uc3QgcHJldmlvdXNTdGF0ZSA9IHRoaXMuY2FudmFzU3RhdGVzW3RoaXMuY3VycmVudFN0YXRlSW5kZXhdO1xuICAgICAgdGhpcy5jYW5SZWRvT3JVbmRvLmVtaXQoe1xuICAgICAgICBjYW5VbmRvOiB0aGlzLmN1cnJlbnRTdGF0ZUluZGV4ID4gMCA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgY2FuUmVkbzogdGhpcy5jdXJyZW50U3RhdGVJbmRleCA8IHRoaXMuY2FudmFzU3RhdGVzLmxlbmd0aCAtIDEgPyB0cnVlIDogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fY2FudmFzLmxvYWRGcm9tSlNPTihwcmV2aW91c1N0YXRlLnN0YXRlLCAoKSA9PiB7XG4gICAgICAgIGxldCBhY3RpdmVPYmplY3QgPSB0aGlzLl9jYW52YXMuZ2V0QWN0aXZlT2JqZWN0KCk7XG4gICAgICAgIGlmIChhY3RpdmVPYmplY3QpIHtcbiAgICAgICAgICBpZiAoYWN0aXZlT2JqZWN0LnR5cGUgIT09ICdwYXRoJykge1xuICAgICAgICAgICAgYWN0aXZlT2JqZWN0LnNldCh7XG4gICAgICAgICAgICAgIHBhZGRpbmc6IDQyLFxuICAgICAgICAgICAgICBib3JkZXJTY2FsZUZhY3RvcjogMyxcbiAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6ICd3aGl0ZScsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuX2NhbnZhcy5pc0RyYXdpbmdNb2RlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9jYW52YXMuZnJlZURyYXdpbmdCcnVzaCA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRleHRBZGRlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNhbkFkZFRleHRPckRvb2xlLmVtaXQoeyBrZXk6ICdkb29kbGUnLCB2YWx1ZTogZmFsc2UgfSk7XG4gICAgICAgICAgICB0aGlzLmNhbkFkZFRleHRPckRvb2xlLmVtaXQoeyBrZXk6ICd0ZXh0JywgdmFsdWU6IHRydWUgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFjdGl2ZU9iamVjdC5zZXQoe1xuICAgICAgICAgICAgICBoYXNDb250cm9sczogZmFsc2UsXG4gICAgICAgICAgICAgIGhhc0JvcmRlcnM6IGZhbHNlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLl9jYW52YXMuc2VsZWN0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmNhbkFkZFRleHRPckRvb2xlLmVtaXQoeyBrZXk6ICd0ZXh0JywgdmFsdWU6IGZhbHNlIH0pO1xuICAgICAgICAgICAgdGhpcy5jYW5BZGRUZXh0T3JEb29sZS5lbWl0KHsga2V5OiAnZG9vZGxlJywgdmFsdWU6IHRydWUgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuX2NhbnZhcy5nZXRBY3RpdmVPYmplY3QoKS5jb250cm9scyA9XG4gICAgICAgICAgICBwcmV2aW91c1N0YXRlICYmIHByZXZpb3VzU3RhdGUuY3VzdG9tQ29udHJvbFxuICAgICAgICAgICAgICA/IHByZXZpb3VzU3RhdGUuY3VzdG9tQ29udHJvbFxuICAgICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY2FudmFzLmdldE9iamVjdHMoKS5mb3JFYWNoKChvYmopID0+IHtcbiAgICAgICAgICBpZiAob2JqICE9PSBhY3RpdmVPYmplY3QpIHtcbiAgICAgICAgICAgIG9iai5ldmVudGVkID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fY2FudmFzLnJlbmRlckFsbCgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHByaXZhdGUgZ2V0Q2FudmFzU2l6ZSgpIHtcbiAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICBpbWcuc3JjID0gdGhpcy5zcmM7XG4gICAgY29uc3QgYm94ID0gdGhpcy5fY29tcG9uZW50Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGggfHwgYm94LndpZHRoIHx8IDE7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQgfHwgYm94LmhlaWdodCB8fCAxO1xuICAgIHJldHVybiB7IHdpZHRoLCBoZWlnaHQgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiByZWNvZ25pemUgcGFwZXIgY29ybmVyc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBidWlsZCgpIHtcbiAgICBpZiAoIXRoaXMuc3JjIHx8ICF0aGlzLl9jYW52YXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgYmcgPSBhd2FpdCB0aGlzLmxvYWRCYWNrZ3JvdW5kSW1hZ2UodGhpcy5zcmMpO1xuXG4gICAgLy8gUmVtb3ZlIGFsbCB0aGUgZXhpc3Rpbmcgb2JqZWN0cyBiZWZvcmUgYWRkIHRoZSBuZXcgaW1hZ2UgdG8gYmFja2dyb3VuZFxuICAgIHRoaXMuX2NhbnZhcy5jbGVhcigpO1xuXG4gICAgY29uc3QgaW1nU2l6ZSA9IGJnLmdldE9yaWdpbmFsU2l6ZSgpO1xuICAgIHRoaXMuSW1hZ2UgPSB7XG4gICAgICBoZWlnaHQ6IGltZ1NpemUuaGVpZ2h0ICogdGhpcy5fc2NhbGVGYWN0b3IsXG4gICAgICB3aWR0aDogaW1nU2l6ZS53aWR0aCAqIHRoaXMuX3NjYWxlRmFjdG9yLFxuICAgIH07XG4gICAgY29uc3Qgc2NhbGVYID0gdGhpcy5fY2FudmFzLndpZHRoIC8gaW1nU2l6ZS53aWR0aDtcbiAgICBjb25zdCBzY2FsZVkgPSB0aGlzLl9jYW52YXMuaGVpZ2h0IC8gaW1nU2l6ZS5oZWlnaHQ7XG4gICAgdGhpcy5fc2NhbGVGYWN0b3IgPSBNYXRoLm1pbihzY2FsZVksIHNjYWxlWCk7XG4gICAgdGhpcy5fY2FudmFzLnNldERpbWVuc2lvbnMoXG4gICAgICB7XG4gICAgICAgIHdpZHRoOiBpbWdTaXplLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IGltZ1NpemUuaGVpZ2h0LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgYmFja3N0b3JlT25seTogdHJ1ZSxcbiAgICAgIH1cbiAgICApO1xuICAgIHRoaXMuX2NhbnZhcy5zZXRCYWNrZ3JvdW5kSW1hZ2UoYmcsICgpID0+IHtcbiAgICAgIHRoaXMuX2NhbnZhcy5yZW5kZXJBbGwoKTtcbiAgICB9KTtcbiAgICB0aGlzLnNhdmVDYW52YXNTdGF0ZSgpO1xuICAgIHRoaXMuX2NhbnZhcy5yZW5kZXJBbGwoKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQ29udHJvbHMocG9seWdvbjogZmFicmljLlBvbHlnb24pIHtcbiAgICAvLyByZW1vdmUgcHJldmlvdXMgY29udHJvbHNcbiAgICBpZiAodGhpcy5fY29udHJvbHMubGVuZ3RoKSB7XG4gICAgICB0aGlzLl9jYW52YXMucmVtb3ZlKC4uLnRoaXMuX2NvbnRyb2xzKTtcbiAgICAgIHRoaXMuX2NvbnRyb2xzID0gW107XG4gICAgfVxuICAgIGlmIChwb2x5Z29uKSB7XG4gICAgICBmb3IgKGNvbnN0IFtpbmRleCwgcG9pbnRdIG9mIHBvbHlnb24ucG9pbnRzLmVudHJpZXMoKSkge1xuICAgICAgICBjb25zdCBjaXJjbGUgPSB0aGlzLmNyZWF0ZUNvbnRyb2woaW5kZXgsIHBvbHlnb24pO1xuICAgICAgICB0aGlzLl9jb250cm9scy5wdXNoKGNpcmNsZSk7XG4gICAgICAgIHRoaXMuX2NhbnZhcy5hZGQoY2lyY2xlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUNvbnRyb2woaW5kZXg6IG51bWJlciwgcG9seWdvbjogZmFicmljLlBvbHlnb24pIHtcbiAgICBjb25zdCBwb2ludCA9IHBvbHlnb24ucG9pbnRzW2luZGV4XTtcbiAgICBjb25zdCBjaXJjbGUgPSBuZXcgZmFicmljLkNpcmNsZSh7XG4gICAgICBsZWZ0OiBwb2ludC54LFxuICAgICAgdG9wOiBwb2ludC55LFxuICAgICAgb3JpZ2luWDogJ2NlbnRlcicsXG4gICAgICBvcmlnaW5ZOiAnY2VudGVyJyxcbiAgICAgIGZpbGw6ICcjMjE4OGQ5JyxcbiAgICAgIHJhZGl1czogMjAsXG4gICAgICBoYXNSb3RhdGluZ1BvaW50OiBmYWxzZSxcbiAgICAgIGhhc0JvcmRlcnM6IGZhbHNlLFxuICAgICAgaGFzQ29udHJvbHM6IGZhbHNlLFxuICAgICAgb2JqZWN0Q2FjaGluZzogZmFsc2UsXG4gICAgfSk7XG4gICAgY2lyY2xlLm9uKCdtb3ZpbmcnLCAoZXZ0KSA9PiB7XG4gICAgICBpZiAoZXZ0LnBvaW50ZXIpIHtcbiAgICAgICAgcG9seWdvbi5wb2ludHNbaW5kZXhdID0gbmV3IGZhYnJpYy5Qb2ludChldnQucG9pbnRlci54LCBldnQucG9pbnRlci55KTtcbiAgICAgICAgcG9seWdvbi5kaXJ0eSA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY2lyY2xlLm9uKCdtb3VzZXVwJywgKGV2dCkgPT4ge1xuICAgICAgdGhpcy5jb3JuZXJzQ2hhbmdlZC5lbWl0KCk7XG4gICAgICB0aGlzLnNjcmVlblBvaW50c1tpbmRleF0gPSBwb2x5Z29uLnBvaW50c1tpbmRleF07XG4gICAgfSk7XG4gICAgcmV0dXJuIGNpcmNsZTtcbiAgfVxuXG4gIHByaXZhdGUgbG9hZEJhY2tncm91bmRJbWFnZShzcmM6IHN0cmluZyk6IFByb21pc2U8ZmFicmljLkltYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgaW1nLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgbGV0IGZhYkltYWdlID0gbmV3IGZhYnJpYy5JbWFnZShpbWcpO1xuICAgICAgICByZXNvbHZlKGZhYkltYWdlKTtcbiAgICAgIH07XG4gICAgICBpbWcuc3JjID0gc3JjO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGNvbXBsZXRlU2Nhbihjb21wbGV0ZWQ6IGJvb2xlYW4pIHtcbiAgICBpZiAoIWNvbXBsZXRlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgY29tcGxldGUgc2NhbiAmIGV4dHJhY3QgcGFwZXJgKTtcblxuICAgIGlmICghdGhpcy5fY29ybmVyc1BnKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBDb3JuZXIgbGluZSBpcyBub3QgYXZhaWxhYmxlYCk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jb3JuZXJzUGcpIHtcbiAgICAgIHRoaXMuX2NhbnZhcy5yZW1vdmUodGhpcy5fY29ybmVyc1BnKTtcbiAgICAgIHRoaXMuX2NhbnZhcy5yZW1vdmUoLi4udGhpcy5fY29udHJvbHMpO1xuICAgICAgdGhpcy5fY2FudmFzLnJlbmRlckFsbCgpO1xuICAgIH1cbiAgICBsZXQgb3V0cHV0OiBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICBpZiAodGhpcy5pc1NjYW5lZCkge1xuICAgICAgb3V0cHV0ID0gYXdhaXQgdGhpcy5fb3BlbmN2LmV4dHJhY3RQYXBlcih7XG4gICAgICAgIHNyYzogdGhpcy5fY2FudmFzLnRvRGF0YVVSTCh7IHF1YWxpdHk6IDEgfSksXG4gICAgICAgIGNvcm5lcnM6IHtcbiAgICAgICAgICB0b3BMZWZ0Q29ybmVyOiB0aGlzLnNjcmVlblBvaW50c1swXSxcbiAgICAgICAgICB0b3BSaWdodENvcm5lcjogdGhpcy5zY3JlZW5Qb2ludHNbMV0sXG4gICAgICAgICAgYm90dG9tUmlnaHRDb3JuZXI6IHRoaXMuc2NyZWVuUG9pbnRzWzJdLFxuICAgICAgICAgIGJvdHRvbUxlZnRDb3JuZXI6IHRoaXMuc2NyZWVuUG9pbnRzWzNdLFxuICAgICAgICB9LFxuICAgICAgICBoZWlnaHQ6IHRoaXMuX2NhbnZhcy5oZWlnaHQsXG4gICAgICAgIHdpZHRoOiB0aGlzLl9jYW52YXMud2lkdGgsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuX2NhbnZhcy5yZW1vdmUoLi4udGhpcy5fY2FudmFzLmdldE9iamVjdHMoKSk7XG4gICAgICB0aGlzLmlzU2NhbmVkID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dCA9IHRoaXMuX2NhbnZhcy50b0NhbnZhc0VsZW1lbnQoKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50U3RhdGVJbmRleCA9IG51bGw7XG4gICAgdGhpcy5jYW52YXNTdGF0ZXMgPSBbXTtcbiAgICB0aGlzLmNhblJlZG9PclVuZG8uZW1pdCh7XG4gICAgICBjYW5VbmRvOiB0aGlzLmN1cnJlbnRTdGF0ZUluZGV4ID4gMCA/IHRydWUgOiBmYWxzZSxcbiAgICAgIGNhblJlZG86IHRoaXMuY3VycmVudFN0YXRlSW5kZXggPCB0aGlzLmNhbnZhc1N0YXRlcy5sZW5ndGggLSAxID8gdHJ1ZSA6IGZhbHNlLFxuICAgIH0pO1xuICAgIHRoaXMuZXh0cmFjdGVkLmVtaXQob3V0cHV0KTtcbiAgICB0aGlzLmNsZWFudXBDYW52YXMoKTtcbiAgfVxuICBwcml2YXRlIGNsZWFudXBDYW52YXMoKSB7XG4gICAgdGhpcy5fY2FudmFzLmdldE9iamVjdHMoKS5mb3JFYWNoKChvYmopID0+IChvYmouZXZlbnRlZCA9IGZhbHNlKSk7XG4gICAgdGhpcy5fY2FudmFzLnNlbGVjdGlvbiA9IGZhbHNlO1xuICAgIHRoaXMuX2NhbnZhcy5pc0RyYXdpbmdNb2RlID0gZmFsc2U7XG4gICAgdGhpcy5jYW5Eb29kbGUgPSBmYWxzZTtcbiAgICB0aGlzLmlzU2NhblN0YXJ0ID0gZmFsc2U7XG4gICAgdGhpcy5jYW5BZGRUZXh0ID0gZmFsc2U7XG4gICAgdGhpcy50ZXh0QWRkZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9jYW52YXMucmVuZGVyQWxsKCk7XG4gIH1cbn1cbiIsIjxkaXYgI2NvbXBvbmVudFdyYXBwZXJcbiAgICAgY2xhc3M9XCJjb21wb25lbnRcIj5cbiAgICA8Y2FudmFzICNkcmF3Q2FuYXM+PC9jYW52YXM+XG4gIDxkaXYgY2xhc3M9XCJjb2xvcnMtY29udGFpbmVyXCIgKm5nSWY9XCJjYW5Eb29kbGUgfHwgY2FuQWRkVGV4dFwiPlxuICAgIDxkaXYgY2xhc3M9XCJjb2xvcnNcIiAqbmdGb3I9XCJsZXQgY29sb3Igb2YgY29sb3JzXCIgW25nU3R5bGVdPVwieydiYWNrZ3JvdW5kJzogY29sb3IuaGV4Q29kZSwgJ2JvcmRlcic6Y29sb3Iuc2VsZWN0ZWQgPyAnMS42cHggc29saWQgd2hpdGUnIDogJ25vbmUnfVwiIChjbGljayk9XCJjaG5nQ2xyVGV4dE9yQnJ1c2goY29sb3IuaGV4Q29kZSwgY2FuQWRkVGV4dCA/ICd0ZXh0JzogJ2Rvb2RsZScpXCI+PC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=
|