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.
Files changed (117) hide show
  1. package/README.md +24 -0
  2. package/esm2020/lib/breadcrumbs/zendu-breadcrumbs.component.mjs +37 -0
  3. package/esm2020/lib/card-block/zendu-card-block.component.mjs +21 -0
  4. package/esm2020/lib/checkbox/zendu-checkbox.component.mjs +44 -0
  5. package/esm2020/lib/colorpicker/zendu-colorpicker.component.mjs +106 -0
  6. package/esm2020/lib/column-configuration/columnState.mjs +2 -0
  7. package/esm2020/lib/column-configuration/zendu-column-configuration.component.mjs +118 -0
  8. package/esm2020/lib/datepicker/date-picker-day.mjs +2 -0
  9. package/esm2020/lib/datepicker/date-picker-hint.mjs +2 -0
  10. package/esm2020/lib/datepicker/datepicker.mjs +9 -0
  11. package/esm2020/lib/datepicker/zendu-datepicker.component.mjs +434 -0
  12. package/esm2020/lib/doc-scanner/zendu-doc-scanner.component.mjs +628 -0
  13. package/esm2020/lib/file-upload/zendu-file-upload.component.mjs +107 -0
  14. package/esm2020/lib/filter/dateRange.mjs +2 -0
  15. package/esm2020/lib/filter/filtersConfig.mjs +2 -0
  16. package/esm2020/lib/filter/numberRange.mjs +2 -0
  17. package/esm2020/lib/filter/zendu-filter.component.mjs +461 -0
  18. package/esm2020/lib/icon/zendu-icon.component.mjs +24 -0
  19. package/esm2020/lib/local.lock.mjs +33 -0
  20. package/esm2020/lib/location-search/location.address.mjs +2 -0
  21. package/esm2020/lib/location-search/zendu-location-search.component.mjs +129 -0
  22. package/esm2020/lib/map/map.types.mjs +2 -0
  23. package/esm2020/lib/map/zendu-map.component.mjs +129 -0
  24. package/esm2020/lib/map-preview/zendu-map-preview.component.mjs +30 -0
  25. package/esm2020/lib/ng-zenduit.module.mjs +158 -0
  26. package/esm2020/lib/pagination-bar/pageItem.mjs +2 -0
  27. package/esm2020/lib/pagination-bar/zendu-pagination-bar.component.mjs +71 -0
  28. package/esm2020/lib/phone-input/zendu-phone-input.component.mjs +141 -0
  29. package/esm2020/lib/progress/zendu-progress.component.mjs +29 -0
  30. package/esm2020/lib/radio-button/radio-button.component.mjs +48 -0
  31. package/esm2020/lib/search-box/zendu-search-box.component.mjs +124 -0
  32. package/esm2020/lib/select/templates/zendu-select-option.directive.mjs +16 -0
  33. package/esm2020/lib/select/templates/zendu-select-value.directive.mjs +16 -0
  34. package/esm2020/lib/select/zendu-select.component.mjs +303 -0
  35. package/esm2020/lib/services/geoconding.service.mjs +61 -0
  36. package/esm2020/lib/services/map.service.mjs +181 -0
  37. package/esm2020/lib/services/opencv.service.mjs +109 -0
  38. package/esm2020/lib/services/zendu-notify.service.mjs +92 -0
  39. package/esm2020/lib/sort-header/zendu-sort-header.component.mjs +36 -0
  40. package/esm2020/lib/spinner/zendu-spinner.component.mjs +11 -0
  41. package/esm2020/lib/toggle/zendu-toggle.component.mjs +32 -0
  42. package/esm2020/lib/toggle-slide/zendu-toggle-slide.component.mjs +27 -0
  43. package/esm2020/lib/util.mjs +93 -0
  44. package/esm2020/ng-zenduit.mjs +5 -0
  45. package/esm2020/public-api.mjs +42 -0
  46. package/fesm2015/ng-zenduit.mjs +3768 -0
  47. package/fesm2015/ng-zenduit.mjs.map +1 -0
  48. package/fesm2020/ng-zenduit.mjs +3735 -0
  49. package/fesm2020/ng-zenduit.mjs.map +1 -0
  50. package/icons/arrow-down-small.svg +3 -0
  51. package/icons/arrow-up-small.svg +3 -0
  52. package/icons/calendar.svg +6 -0
  53. package/icons/cross.svg +3 -0
  54. package/icons/date.svg +3 -0
  55. package/icons/expand.svg +3 -0
  56. package/icons/filter.svg +3 -0
  57. package/icons/play.svg +10 -0
  58. package/icons/redo.svg +3 -0
  59. package/icons/rotate.svg +3 -0
  60. package/icons/time.svg +4 -0
  61. package/icons/undo.svg +3 -0
  62. package/index.d.ts +5 -0
  63. package/lib/breadcrumbs/zendu-breadcrumbs.component.d.ts +22 -0
  64. package/lib/card-block/zendu-card-block.component.d.ts +9 -0
  65. package/lib/checkbox/zendu-checkbox.component.d.ts +17 -0
  66. package/lib/colorpicker/zendu-colorpicker.component.d.ts +28 -0
  67. package/lib/column-configuration/columnState.d.ts +7 -0
  68. package/lib/column-configuration/zendu-column-configuration.component.d.ts +43 -0
  69. package/lib/datepicker/date-picker-day.d.ts +8 -0
  70. package/lib/datepicker/date-picker-hint.d.ts +5 -0
  71. package/lib/datepicker/datepicker.d.ts +7 -0
  72. package/lib/datepicker/zendu-datepicker.component.d.ts +94 -0
  73. package/lib/doc-scanner/zendu-doc-scanner.component.d.ts +82 -0
  74. package/lib/file-upload/zendu-file-upload.component.d.ts +28 -0
  75. package/lib/filter/dateRange.d.ts +4 -0
  76. package/lib/filter/filtersConfig.d.ts +88 -0
  77. package/lib/filter/numberRange.d.ts +4 -0
  78. package/lib/filter/zendu-filter.component.d.ts +59 -0
  79. package/lib/icon/zendu-icon.component.d.ts +10 -0
  80. package/lib/local.lock.d.ts +8 -0
  81. package/lib/location-search/location.address.d.ts +12 -0
  82. package/lib/location-search/zendu-location-search.component.d.ts +32 -0
  83. package/lib/map/map.types.d.ts +33 -0
  84. package/lib/map/zendu-map.component.d.ts +23 -0
  85. package/lib/map-preview/zendu-map-preview.component.d.ts +11 -0
  86. package/lib/ng-zenduit.module.d.ts +34 -0
  87. package/lib/pagination-bar/pageItem.d.ts +4 -0
  88. package/lib/pagination-bar/zendu-pagination-bar.component.d.ts +25 -0
  89. package/lib/phone-input/zendu-phone-input.component.d.ts +39 -0
  90. package/lib/progress/zendu-progress.component.d.ts +14 -0
  91. package/lib/radio-button/radio-button.component.d.ts +18 -0
  92. package/lib/search-box/zendu-search-box.component.d.ts +26 -0
  93. package/lib/select/templates/zendu-select-option.directive.d.ts +8 -0
  94. package/lib/select/templates/zendu-select-value.directive.d.ts +8 -0
  95. package/lib/select/zendu-select.component.d.ts +107 -0
  96. package/lib/services/geoconding.service.d.ts +23 -0
  97. package/lib/services/map.service.d.ts +22 -0
  98. package/lib/services/opencv.service.d.ts +46 -0
  99. package/lib/services/zendu-notify.service.d.ts +10 -0
  100. package/lib/sort-header/zendu-sort-header.component.d.ts +10 -0
  101. package/lib/spinner/zendu-spinner.component.d.ts +5 -0
  102. package/lib/toggle/zendu-toggle.component.d.ts +14 -0
  103. package/lib/toggle-slide/zendu-toggle-slide.component.d.ts +13 -0
  104. package/lib/util.d.ts +11 -0
  105. package/package.json +36 -0
  106. package/public-api.d.ts +38 -0
  107. package/styles/action-menu.scss +127 -0
  108. package/styles/all.scss +11 -0
  109. package/styles/button.scss +188 -0
  110. package/styles/colors.scss +125 -0
  111. package/styles/common-form.scss +159 -0
  112. package/styles/extenal.scss +2 -0
  113. package/styles/ghost.scss +38 -0
  114. package/styles/global-restyle.scss +25 -0
  115. package/styles/page-layout.scss +82 -0
  116. package/styles/snackbar.scss +91 -0
  117. 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=