UNPKG

116 kBJavaScriptView Raw
1import { __values } from 'tslib';
2import { Injectable, Component, Input, HostListener, Output, EventEmitter, NgModule } from '@angular/core';
3import { fabric } from 'fabric';
4import { CommonModule } from '@angular/common';
5import { MatToolbarModule } from '@angular/material/toolbar';
6import { ColorPickerModule } from 'ngx-color-picker';
7import { MatButtonModule } from '@angular/material';
8
9/**
10 * @fileoverview added by tsickle
11 * @suppress {checkTypes} checked by tsc
12 */
13/** @enum {number} */
14var AvailableGeometricShape = {
15 "Rectangle": 0,
16 "Circle": 1,
17 "Triangle": 2,
18 "Line": 3,
19 "Cross": 4,
20};
21AvailableGeometricShape[AvailableGeometricShape["Rectangle"]] = "Rectangle";
22AvailableGeometricShape[AvailableGeometricShape["Circle"]] = "Circle";
23AvailableGeometricShape[AvailableGeometricShape["Triangle"]] = "Triangle";
24AvailableGeometricShape[AvailableGeometricShape["Line"]] = "Line";
25AvailableGeometricShape[AvailableGeometricShape["Cross"]] = "Cross";
26
27/**
28 * @fileoverview added by tsickle
29 * @suppress {checkTypes} checked by tsc
30 */
31var /** @type {?} */ SHAPE_DATA = {
32 width: 200,
33 height: 200,
34 left: 50,
35 top: 50,
36 radius: 100,
37 stroke: 10,
38 freeDrawingBrushWidth: 10,
39 cornerSize: 20
40};
41
42/**
43 * @fileoverview added by tsickle
44 * @suppress {checkTypes} checked by tsc
45 */
46var CanvasManagerService = /** @class */ (function () {
47 function CanvasManagerService() {
48 this.emptyCanvas();
49 this.mousePosition = { x: 0, y: 0 };
50 this.cropStartingPosition = { x: 0, y: 0 };
51 }
52 Object.defineProperty(CanvasManagerService.prototype, "canvasObjects", {
53 get: /**
54 * @return {?}
55 */
56 function () {
57 return this.canvas.getObjects();
58 },
59 enumerable: true,
60 configurable: true
61 });
62 Object.defineProperty(CanvasManagerService.prototype, "canvasBackgroundImage", {
63 get: /**
64 * @return {?}
65 */
66 function () {
67 return this.canvas.backgroundImage;
68 },
69 enumerable: true,
70 configurable: true
71 });
72 Object.defineProperty(CanvasManagerService.prototype, "activeObject", {
73 get: /**
74 * @return {?}
75 */
76 function () {
77 return this.canvas.getActiveObject();
78 },
79 enumerable: true,
80 configurable: true
81 });
82 Object.defineProperty(CanvasManagerService.prototype, "activeGroup", {
83 get: /**
84 * @return {?}
85 */
86 function () {
87 return this.canvas.getActiveObjects();
88 },
89 enumerable: true,
90 configurable: true
91 });
92 Object.defineProperty(CanvasManagerService.prototype, "divCanvasContainer", {
93 get: /**
94 * @return {?}
95 */
96 function () {
97 return document.getElementsByClassName('div-canvas-container')[0];
98 },
99 enumerable: true,
100 configurable: true
101 });
102 /**
103 * @return {?}
104 */
105 CanvasManagerService.prototype.emptyCanvas = /**
106 * @return {?}
107 */
108 function () {
109 if (this.canvas) {
110 this.canvas.dispose();
111 }
112 this.canvas = new fabric.Canvas('canvas');
113 this.canvas.clear();
114 this.canvas.remove(this.canvas.getObjects());
115 };
116 /**
117 * @param {?=} backgroundImageURL
118 * @return {?}
119 */
120 CanvasManagerService.prototype.loadNewImage = /**
121 * @param {?=} backgroundImageURL
122 * @return {?}
123 */
124 function (backgroundImageURL) {
125 this.emptyCanvas();
126 if (backgroundImageURL) {
127 this.setBackgroundFromURL(backgroundImageURL);
128 }
129 };
130 /**
131 * @return {?}
132 */
133 CanvasManagerService.prototype.renderCanvas = /**
134 * @return {?}
135 */
136 function () {
137 this.markSelectedObjectsDirty();
138 this.canvas.renderAll();
139 };
140 /**
141 * @param {?} strokeColor
142 * @param {?} fillColor
143 * @param {?} shape
144 * @return {?}
145 */
146 CanvasManagerService.prototype.addGeometricShape = /**
147 * @param {?} strokeColor
148 * @param {?} fillColor
149 * @param {?} shape
150 * @return {?}
151 */
152 function (strokeColor, fillColor, shape) {
153 switch (shape) {
154 case AvailableGeometricShape.Rectangle:
155 this.addRectangle(strokeColor, fillColor);
156 break;
157 case AvailableGeometricShape.Circle:
158 this.addCircle(strokeColor, fillColor);
159 break;
160 case AvailableGeometricShape.Triangle:
161 this.addTriangle(strokeColor, fillColor);
162 break;
163 case AvailableGeometricShape.Line:
164 this.addHorizontalLine(strokeColor, fillColor);
165 break;
166 case AvailableGeometricShape.Cross:
167 this.addCross(strokeColor, fillColor);
168 break;
169 }
170 };
171 /**
172 * @param {?} strokeColor
173 * @param {?} fillColor
174 * @return {?}
175 */
176 CanvasManagerService.prototype.addRectangle = /**
177 * @param {?} strokeColor
178 * @param {?} fillColor
179 * @return {?}
180 */
181 function (strokeColor, fillColor) {
182 this.canvas.add(new fabric.Rect({
183 width: SHAPE_DATA.width,
184 height: SHAPE_DATA.height,
185 left: SHAPE_DATA.left,
186 top: SHAPE_DATA.top,
187 fill: fillColor,
188 stroke: strokeColor,
189 strokeWidth: SHAPE_DATA.stroke,
190 cornerSize: SHAPE_DATA.cornerSize
191 }));
192 };
193 /**
194 * @param {?} strokeColor
195 * @param {?} fillColor
196 * @return {?}
197 */
198 CanvasManagerService.prototype.addCircle = /**
199 * @param {?} strokeColor
200 * @param {?} fillColor
201 * @return {?}
202 */
203 function (strokeColor, fillColor) {
204 this.canvas.add(new fabric.Circle({
205 left: SHAPE_DATA.left,
206 top: SHAPE_DATA.top,
207 radius: SHAPE_DATA.radius,
208 stroke: strokeColor,
209 strokeWidth: SHAPE_DATA.stroke,
210 fill: fillColor,
211 cornerSize: SHAPE_DATA.cornerSize
212 }));
213 };
214 /**
215 * @param {?} strokeColor
216 * @param {?} fillColor
217 * @return {?}
218 */
219 CanvasManagerService.prototype.addTriangle = /**
220 * @param {?} strokeColor
221 * @param {?} fillColor
222 * @return {?}
223 */
224 function (strokeColor, fillColor) {
225 this.canvas.add(new fabric.Triangle({
226 width: SHAPE_DATA.width,
227 height: SHAPE_DATA.height,
228 left: SHAPE_DATA.left,
229 top: SHAPE_DATA.top,
230 fill: fillColor,
231 stroke: strokeColor,
232 strokeWidth: SHAPE_DATA.stroke,
233 cornerSize: SHAPE_DATA.cornerSize
234 }));
235 };
236 /**
237 * @param {?} strokeColor
238 * @param {?} fillColor
239 * @return {?}
240 */
241 CanvasManagerService.prototype.addHorizontalLine = /**
242 * @param {?} strokeColor
243 * @param {?} fillColor
244 * @return {?}
245 */
246 function (strokeColor, fillColor) {
247 this.canvas.add(this.createHorizontalLine(strokeColor));
248 };
249 /**
250 * @param {?} strokeColor
251 * @return {?}
252 */
253 CanvasManagerService.prototype.createHorizontalLine = /**
254 * @param {?} strokeColor
255 * @return {?}
256 */
257 function (strokeColor) {
258 var /** @type {?} */ line = new fabric.Line([100, 150, 200, 150], {
259 left: 50,
260 top: 100,
261 stroke: strokeColor,
262 strokeWidth: 5,
263 cornerSize: SHAPE_DATA.cornerSize
264 });
265 line.setControlsVisibility({
266 bl: false,
267 br: false,
268 tl: false,
269 tr: false,
270 mt: false,
271 mb: false
272 });
273 return line;
274 };
275 /**
276 * @param {?} strokeColor
277 * @return {?}
278 */
279 CanvasManagerService.prototype.createVerticalLine = /**
280 * @param {?} strokeColor
281 * @return {?}
282 */
283 function (strokeColor) {
284 var /** @type {?} */ line = new fabric.Line([150, 100, 150, 200], {
285 left: 100,
286 top: 50,
287 stroke: strokeColor,
288 strokeWidth: 5,
289 cornerSize: SHAPE_DATA.cornerSize
290 });
291 line.setControlsVisibility({
292 bl: false,
293 br: false,
294 tl: false,
295 tr: false,
296 ml: false,
297 mr: false
298 });
299 return line;
300 };
301 /**
302 * @param {?} strokeColor
303 * @param {?} fillColor
304 * @return {?}
305 */
306 CanvasManagerService.prototype.addCross = /**
307 * @param {?} strokeColor
308 * @param {?} fillColor
309 * @return {?}
310 */
311 function (strokeColor, fillColor) {
312 var /** @type {?} */ horizontalLine = this.createHorizontalLine(strokeColor);
313 var /** @type {?} */ verticalLine = this.createVerticalLine(strokeColor);
314 this.canvas.add(horizontalLine);
315 this.canvas.add(verticalLine);
316 };
317 /**
318 * @return {?}
319 */
320 CanvasManagerService.prototype.toggleFreeDrawing = /**
321 * @return {?}
322 */
323 function () {
324 this.canvas.isDrawingMode = !this.canvas.isDrawingMode;
325 };
326 /**
327 * @param {?} color
328 * @return {?}
329 */
330 CanvasManagerService.prototype.setFreeDrawingBrushColor = /**
331 * @param {?} color
332 * @return {?}
333 */
334 function (color) {
335 this.canvas.freeDrawingBrush.color = color;
336 this.setFreeDrawingBrushWidthFromZoom(this.canvas.getZoom());
337 };
338 /**
339 * @param {?} zoom
340 * @return {?}
341 */
342 CanvasManagerService.prototype.setFreeDrawingBrushWidthFromZoom = /**
343 * @param {?} zoom
344 * @return {?}
345 */
346 function (zoom) {
347 this.canvas.freeDrawingBrush.width = SHAPE_DATA.freeDrawingBrushWidth * (1 / zoom);
348 };
349 /**
350 * @param {?} color
351 * @param {?} inputText
352 * @return {?}
353 */
354 CanvasManagerService.prototype.addText = /**
355 * @param {?} color
356 * @param {?} inputText
357 * @return {?}
358 */
359 function (color, inputText) {
360 var /** @type {?} */ text = new fabric.IText('text', {
361 fontFamily: 'arial black',
362 fontStyle: 'bold',
363 left: SHAPE_DATA.left,
364 top: SHAPE_DATA.top,
365 cornerSize: SHAPE_DATA.cornerSize
366 });
367 text.setColor(color);
368 this.canvas.add(text);
369 };
370 /**
371 * @param {?} imageURL
372 * @return {?}
373 */
374 CanvasManagerService.prototype.addImage = /**
375 * @param {?} imageURL
376 * @return {?}
377 */
378 function (imageURL) {
379 var _this = this;
380 return new Promise(function (resolve, reject) {
381 var /** @type {?} */ canvas = _this.canvas;
382 var /** @type {?} */ image = new Image();
383 image.onload = function (img) {
384 var /** @type {?} */ fabricImage = new fabric.Image(image, {
385 angle: 0,
386 width: image.width,
387 height: image.height,
388 left: SHAPE_DATA.left,
389 top: SHAPE_DATA.top,
390 scaleX: 1,
391 scaleY: 1,
392 cornerSize: SHAPE_DATA.cornerSize
393 });
394 canvas.add(fabricImage);
395 resolve();
396 };
397 image.src = imageURL;
398 });
399 };
400 /**
401 * @param {?} backgroundImageURL
402 * @return {?}
403 */
404 CanvasManagerService.prototype.setBackgroundFromURL = /**
405 * @param {?} backgroundImageURL
406 * @return {?}
407 */
408 function (backgroundImageURL) {
409 var /** @type {?} */ canvas = this.canvas;
410 var /** @type {?} */ resize = this.resizeCanvasAndComputeScaleFactor;
411 return new Promise(function (resolve, reject) {
412 if (backgroundImageURL == null) {
413 return reject();
414 }
415 var /** @type {?} */ image = new Image();
416 image.onload = function () {
417 var /** @type {?} */ f_img = new fabric.Image(image, {});
418 var /** @type {?} */ scaleData = resize(f_img, canvas);
419 canvas.setBackgroundImage(f_img, canvas.renderAll.bind(canvas), {
420 scaleX: scaleData.scaleFactor,
421 scaleY: scaleData.scaleFactor
422 });
423 canvas.setWidth(f_img.width * scaleData.scaleFactor);
424 canvas.setHeight(f_img.height * scaleData.scaleFactor);
425 canvas.renderAll();
426 resolve();
427 };
428 image.src = backgroundImageURL;
429 });
430 };
431 /**
432 * @param {?} f_img
433 * @param {?} canvas
434 * @return {?}
435 */
436 CanvasManagerService.prototype.resizeCanvasAndComputeScaleFactor = /**
437 * @param {?} f_img
438 * @param {?} canvas
439 * @return {?}
440 */
441 function (f_img, canvas) {
442 var /** @type {?} */ container = document.getElementsByClassName('div-canvas-container')[0];
443 canvas.setWidth(container.clientWidth);
444 canvas.setHeight(container.clientHeight);
445 var /** @type {?} */ canvasAspect = container.clientWidth / container.clientHeight;
446 var /** @type {?} */ imgAspect = f_img.width / f_img.height;
447 var /** @type {?} */ left, /** @type {?} */ top, /** @type {?} */ scaleFactor;
448 if (canvasAspect <= imgAspect) {
449 scaleFactor = container.clientWidth / f_img.width;
450 left = 0;
451 top = -(f_img.height * scaleFactor - container.clientHeight) / 2;
452 }
453 else {
454 scaleFactor = container.clientHeight / f_img.height;
455 top = 0;
456 left = -(f_img.width * scaleFactor - container.clientWidth) / 2;
457 }
458 return { scaleFactor: scaleFactor, left: left, top: top };
459 };
460 /**
461 * @return {?}
462 */
463 CanvasManagerService.prototype.onOrientationChange = /**
464 * @return {?}
465 */
466 function () {
467 this.mousePosition = { x: this.canvas.getWidth, y: this.canvas.getHeight };
468 this.cropImage();
469 };
470 /**
471 * @param {?} color
472 * @return {?}
473 */
474 CanvasManagerService.prototype.changeSelectedObjectsFillColor = /**
475 * @param {?} color
476 * @return {?}
477 */
478 function (color) {
479 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
480 if (activeObjects) {
481 try {
482 for (var activeObjects_1 = __values(activeObjects), activeObjects_1_1 = activeObjects_1.next(); !activeObjects_1_1.done; activeObjects_1_1 = activeObjects_1.next()) {
483 var object = activeObjects_1_1.value;
484 object.setColor(color);
485 this.canvas.renderAll();
486 }
487 }
488 catch (e_1_1) { e_1 = { error: e_1_1 }; }
489 finally {
490 try {
491 if (activeObjects_1_1 && !activeObjects_1_1.done && (_a = activeObjects_1.return)) _a.call(activeObjects_1);
492 }
493 finally { if (e_1) throw e_1.error; }
494 }
495 }
496 var e_1, _a;
497 };
498 /**
499 * @param {?} color
500 * @return {?}
501 */
502 CanvasManagerService.prototype.changeSelectedObjectsStrokeColor = /**
503 * @param {?} color
504 * @return {?}
505 */
506 function (color) {
507 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
508 if (activeObjects) {
509 try {
510 for (var activeObjects_2 = __values(activeObjects), activeObjects_2_1 = activeObjects_2.next(); !activeObjects_2_1.done; activeObjects_2_1 = activeObjects_2.next()) {
511 var object = activeObjects_2_1.value;
512 if (object.type === 'i-text') {
513 object.setColor(color);
514 }
515 else {
516 object.stroke = color;
517 object.set('dirty', true);
518 }
519 }
520 }
521 catch (e_2_1) { e_2 = { error: e_2_1 }; }
522 finally {
523 try {
524 if (activeObjects_2_1 && !activeObjects_2_1.done && (_a = activeObjects_2.return)) _a.call(activeObjects_2);
525 }
526 finally { if (e_2) throw e_2.error; }
527 }
528 this.canvas.renderAll();
529 }
530 var e_2, _a;
531 };
532 /**
533 * @return {?}
534 */
535 CanvasManagerService.prototype.deleteSelectedObjects = /**
536 * @return {?}
537 */
538 function () {
539 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
540 if (activeObjects) {
541 try {
542 for (var activeObjects_3 = __values(activeObjects), activeObjects_3_1 = activeObjects_3.next(); !activeObjects_3_1.done; activeObjects_3_1 = activeObjects_3.next()) {
543 var object = activeObjects_3_1.value;
544 this.canvas.remove(object);
545 }
546 }
547 catch (e_3_1) { e_3 = { error: e_3_1 }; }
548 finally {
549 try {
550 if (activeObjects_3_1 && !activeObjects_3_1.done && (_a = activeObjects_3.return)) _a.call(activeObjects_3);
551 }
552 finally { if (e_3) throw e_3.error; }
553 }
554 this.canvas.discardActiveObject();
555 this.canvas.renderAll();
556 }
557 var e_3, _a;
558 };
559 /**
560 * @return {?}
561 */
562 CanvasManagerService.prototype.bringSelectedObjectsToFront = /**
563 * @return {?}
564 */
565 function () {
566 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
567 if (activeObjects) {
568 try {
569 for (var activeObjects_4 = __values(activeObjects), activeObjects_4_1 = activeObjects_4.next(); !activeObjects_4_1.done; activeObjects_4_1 = activeObjects_4.next()) {
570 var object = activeObjects_4_1.value;
571 this.canvas.bringToFront(object);
572 }
573 }
574 catch (e_4_1) { e_4 = { error: e_4_1 }; }
575 finally {
576 try {
577 if (activeObjects_4_1 && !activeObjects_4_1.done && (_a = activeObjects_4.return)) _a.call(activeObjects_4);
578 }
579 finally { if (e_4) throw e_4.error; }
580 }
581 }
582 var e_4, _a;
583 };
584 /**
585 * @return {?}
586 */
587 CanvasManagerService.prototype.sendSelectedObjectsToBack = /**
588 * @return {?}
589 */
590 function () {
591 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
592 if (activeObjects) {
593 try {
594 for (var activeObjects_5 = __values(activeObjects), activeObjects_5_1 = activeObjects_5.next(); !activeObjects_5_1.done; activeObjects_5_1 = activeObjects_5.next()) {
595 var object = activeObjects_5_1.value;
596 this.canvas.sendToBack(object);
597 }
598 }
599 catch (e_5_1) { e_5 = { error: e_5_1 }; }
600 finally {
601 try {
602 if (activeObjects_5_1 && !activeObjects_5_1.done && (_a = activeObjects_5.return)) _a.call(activeObjects_5);
603 }
604 finally { if (e_5) throw e_5.error; }
605 }
606 }
607 var e_5, _a;
608 };
609 /**
610 * @return {?}
611 */
612 CanvasManagerService.prototype.jsonFromCanvas = /**
613 * @return {?}
614 */
615 function () {
616 return this.canvas.toJSON();
617 };
618 /**
619 * @param {?} json
620 * @return {?}
621 */
622 CanvasManagerService.prototype.loadfromJson = /**
623 * @param {?} json
624 * @return {?}
625 */
626 function (json) {
627 var _this = this;
628 var /** @type {?} */ container = this.divCanvasContainer;
629 this.setCanvasSize(container.clientWidth, container.clientHeight);
630 return new Promise(function (resolve, reject) {
631 _this.adjustCanvas(json);
632 _this.canvas.loadFromJSON(json, _this.canvas.renderAll.bind(_this.canvas));
633 resolve();
634 });
635 };
636 /**
637 * @param {?} json
638 * @return {?}
639 */
640 CanvasManagerService.prototype.adjustCanvas = /**
641 * @param {?} json
642 * @return {?}
643 */
644 function (json) {
645 var /** @type {?} */ backgroundImage = json['backgroundImage'];
646 var /** @type {?} */ container = this.divCanvasContainer;
647 var /** @type {?} */ width = backgroundImage['width'];
648 var /** @type {?} */ height = backgroundImage['height'];
649 var /** @type {?} */ canvasWidth = container.clientWidth;
650 var /** @type {?} */ canvasHeight = container.clientHeight;
651 var /** @type {?} */ canvasAspect = canvasWidth / canvasHeight;
652 var /** @type {?} */ imgAspect = width / height;
653 var /** @type {?} */ scaleFactor;
654 if (canvasAspect <= imgAspect) {
655 scaleFactor = canvasWidth / width;
656 }
657 else {
658 scaleFactor = canvasHeight / height;
659 }
660 var /** @type {?} */ objectScale = scaleFactor / backgroundImage['scaleX'];
661 backgroundImage['scaleX'] = scaleFactor;
662 backgroundImage['scaleY'] = scaleFactor;
663 this.setCanvasSize(width * scaleFactor, height * scaleFactor);
664 var /** @type {?} */ objects = json['objects'];
665 for (var /** @type {?} */ i = 0; i < objects.length; i++) {
666 objects[i]['left'] *= objectScale;
667 objects[i]['top'] *= objectScale;
668 objects[i]['scaleX'] *= objectScale;
669 objects[i]['scaleY'] *= objectScale;
670 }
671 this.canvas.selectable = true;
672 this.canvas.selection = true;
673 this.canvas.renderAll();
674 };
675 /**
676 * @return {?}
677 */
678 CanvasManagerService.prototype.exportImageAsDataURL = /**
679 * @return {?}
680 */
681 function () {
682 return this.canvas.toDataURL('image/png');
683 };
684 /**
685 * @param {?} itemNumber
686 * @return {?}
687 */
688 CanvasManagerService.prototype.selectItem = /**
689 * @param {?} itemNumber
690 * @return {?}
691 */
692 function (itemNumber) {
693 this.canvas.setActiveObject(this.canvas.item(itemNumber));
694 };
695 /**
696 * @param {?} activeObject
697 * @return {?}
698 */
699 CanvasManagerService.prototype.getIndexOf = /**
700 * @param {?} activeObject
701 * @return {?}
702 */
703 function (activeObject) {
704 return this.canvas.getObjects().indexOf(activeObject);
705 };
706 /**
707 * @return {?}
708 */
709 CanvasManagerService.prototype.selectLastObject = /**
710 * @return {?}
711 */
712 function () {
713 var /** @type {?} */ itemNumber = this.canvas.getObjects().length - 1;
714 var /** @type {?} */ object = this.canvas.item(itemNumber);
715 this.canvas.setActiveObject(object);
716 object.enterEditing();
717 };
718 /**
719 * @return {?}
720 */
721 CanvasManagerService.prototype.markSelectedObjectsDirty = /**
722 * @return {?}
723 */
724 function () {
725 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
726 if (activeObjects) {
727 try {
728 for (var activeObjects_6 = __values(activeObjects), activeObjects_6_1 = activeObjects_6.next(); !activeObjects_6_1.done; activeObjects_6_1 = activeObjects_6.next()) {
729 var object = activeObjects_6_1.value;
730 object.set('dirty', true);
731 }
732 }
733 catch (e_6_1) { e_6 = { error: e_6_1 }; }
734 finally {
735 try {
736 if (activeObjects_6_1 && !activeObjects_6_1.done && (_a = activeObjects_6.return)) _a.call(activeObjects_6);
737 }
738 finally { if (e_6) throw e_6.error; }
739 }
740 }
741 var e_6, _a;
742 };
743 /**
744 * @return {?}
745 */
746 CanvasManagerService.prototype.addSelectionRectangle = /**
747 * @return {?}
748 */
749 function () {
750 this.cropRectangle = new fabric.Rect({
751 fill: 'transparent',
752 originX: 'left',
753 originY: 'top',
754 stroke: '#ccc',
755 strokeDashArray: [2, 2],
756 opacity: 1,
757 width: 1,
758 height: 1
759 });
760 this.cropRectangle.visible = false;
761 this.canvas.add(this.cropRectangle);
762 };
763 /**
764 * @param {?} event
765 * @return {?}
766 */
767 CanvasManagerService.prototype.ajustCropRectangleFromMouse = /**
768 * @param {?} event
769 * @return {?}
770 */
771 function (event) {
772 var /** @type {?} */ x = Math.min(event.layerX, this.mousePosition.x), /** @type {?} */
773 y = Math.min(event.layerY, this.mousePosition.y), /** @type {?} */
774 w = Math.abs(event.layerX - this.mousePosition.x), /** @type {?} */
775 h = Math.abs(event.layerY - this.mousePosition.y);
776 if (!w || !h) {
777 return false;
778 }
779 this.cropRectangle
780 .set('top', y)
781 .set('left', x)
782 .set('width', w)
783 .set('height', h);
784 this.canvas.renderAll();
785 return true;
786 };
787 /**
788 * @param {?} event
789 * @return {?}
790 */
791 CanvasManagerService.prototype.startSelectingCropRectangleFromMouse = /**
792 * @param {?} event
793 * @return {?}
794 */
795 function (event) {
796 this.cropStartingPosition = { x: this.canvas.left, y: this.canvas.top };
797 this.cropRectangle.left = event.layerX;
798 this.cropRectangle.top = event.layerY;
799 this.cropRectangle.setCoords();
800 this.mousePosition = { x: event.layerX, y: event.layerY };
801 this.canvas.renderAll();
802 this.cropRectangle.visible = true;
803 this.canvas.bringToFront(this.cropRectangle);
804 };
805 /**
806 * @return {?}
807 */
808 CanvasManagerService.prototype.cropImage = /**
809 * @return {?}
810 */
811 function () {
812 var /** @type {?} */ left = this.cropRectangle.left;
813 var /** @type {?} */ top = this.cropRectangle.top;
814 var /** @type {?} */ width = this.cropRectangle.width;
815 var /** @type {?} */ height = this.cropRectangle.height;
816 var /** @type {?} */ container = this.divCanvasContainer;
817 var /** @type {?} */ canvasWidth = container.clientWidth;
818 var /** @type {?} */ canvasHeight = container.clientHeight;
819 var /** @type {?} */ canvasAspect = canvasWidth / canvasHeight;
820 var /** @type {?} */ imgAspect = width / height;
821 var /** @type {?} */ scaleFactor;
822 if (canvasAspect <= imgAspect) {
823 scaleFactor = canvasWidth / width;
824 }
825 else {
826 scaleFactor = canvasHeight / height;
827 }
828 this.setCanvasSize(width * scaleFactor, height * scaleFactor);
829 this.canvas.backgroundImage.scaleX *= scaleFactor;
830 this.canvas.backgroundImage.scaleY *= scaleFactor;
831 this.canvas.backgroundImage.left -= left;
832 this.canvas.backgroundImage.left *= scaleFactor;
833 this.canvas.backgroundImage.top -= top - scaleFactor;
834 this.canvas.backgroundImage.top *= scaleFactor;
835 this.moveAllObjectsInCanvas(-1 * left, -1 * top, scaleFactor);
836 this.enableSlection();
837 this.cropRectangle.visible = false;
838 this.canvas.remove(this.cropRectangle);
839 this.canvas.renderAll();
840 };
841 /**
842 * @return {?}
843 */
844 CanvasManagerService.prototype.enableSlection = /**
845 * @return {?}
846 */
847 function () {
848 this.canvas.selectable = true;
849 this.canvas.selection = true;
850 };
851 /**
852 * @param {?} event
853 * @return {?}
854 */
855 CanvasManagerService.prototype.ajustCropRectangle = /**
856 * @param {?} event
857 * @return {?}
858 */
859 function (event) {
860 var /** @type {?} */ touch = event.touches[0];
861 var /** @type {?} */ rect = event.target.getBoundingClientRect();
862 var /** @type {?} */ x = Math.min(touch.clientX - rect.left, this.mousePosition.x), /** @type {?} */
863 y = Math.min(touch.clientY - rect.top, this.mousePosition.y), /** @type {?} */
864 w = Math.abs(touch.clientX - rect.left - this.mousePosition.x), /** @type {?} */
865 h = Math.abs(touch.clientY - rect.top - this.mousePosition.y);
866 if (!w || !h) {
867 return false;
868 }
869 this.cropRectangle
870 .set('left', x)
871 .set('top', y)
872 .set('width', w)
873 .set('height', h);
874 this.canvas.renderAll();
875 return true;
876 };
877 /**
878 * @param {?} event
879 * @return {?}
880 */
881 CanvasManagerService.prototype.startSelectingCropRectangle = /**
882 * @param {?} event
883 * @return {?}
884 */
885 function (event) {
886 this.cropStartingPosition = { x: this.canvas.left, y: this.canvas.top };
887 var /** @type {?} */ touch = event.touches[0];
888 var /** @type {?} */ rect = event.target.getBoundingClientRect();
889 this.cropRectangle.left = touch.clientX - rect.left;
890 this.cropRectangle.top = touch.clientY - rect.top;
891 this.cropRectangle.setCoords();
892 this.mousePosition = { x: touch.clientX - rect.left, y: touch.clientY - rect.top };
893 this.canvas.renderAll();
894 this.cropRectangle.visible = true;
895 this.canvas.bringToFront(this.cropRectangle);
896 };
897 /**
898 * @return {?}
899 */
900 CanvasManagerService.prototype.disableSelection = /**
901 * @return {?}
902 */
903 function () {
904 this.canvas.selection = false;
905 };
906 /**
907 * @param {?} x
908 * @param {?} y
909 * @param {?} scaleFactor
910 * @return {?}
911 */
912 CanvasManagerService.prototype.moveAllObjectsInCanvas = /**
913 * @param {?} x
914 * @param {?} y
915 * @param {?} scaleFactor
916 * @return {?}
917 */
918 function (x, y, scaleFactor) {
919 var /** @type {?} */ objects = this.canvas.getObjects();
920 try {
921 for (var objects_1 = __values(objects), objects_1_1 = objects_1.next(); !objects_1_1.done; objects_1_1 = objects_1.next()) {
922 var obj = objects_1_1.value;
923 obj.left += x;
924 obj.left *= scaleFactor;
925 obj.scaleX *= scaleFactor;
926 obj.top += y;
927 obj.scaleY *= scaleFactor;
928 obj.top *= scaleFactor;
929 obj.setCoords();
930 }
931 }
932 catch (e_7_1) { e_7 = { error: e_7_1 }; }
933 finally {
934 try {
935 if (objects_1_1 && !objects_1_1.done && (_a = objects_1.return)) _a.call(objects_1);
936 }
937 finally { if (e_7) throw e_7.error; }
938 }
939 var e_7, _a;
940 };
941 /**
942 * @return {?}
943 */
944 CanvasManagerService.prototype.groupSelectedObjects = /**
945 * @return {?}
946 */
947 function () {
948 var /** @type {?} */ activeObjects = this.canvas.getActiveObjects();
949 if (activeObjects) {
950 var /** @type {?} */ objects = [];
951 try {
952 for (var activeObjects_7 = __values(activeObjects), activeObjects_7_1 = activeObjects_7.next(); !activeObjects_7_1.done; activeObjects_7_1 = activeObjects_7.next()) {
953 var object = activeObjects_7_1.value;
954 objects.push(object);
955 }
956 }
957 catch (e_8_1) { e_8 = { error: e_8_1 }; }
958 finally {
959 try {
960 if (activeObjects_7_1 && !activeObjects_7_1.done && (_a = activeObjects_7.return)) _a.call(activeObjects_7);
961 }
962 finally { if (e_8) throw e_8.error; }
963 }
964 this.deleteSelectedObjects();
965 var /** @type {?} */ group = new fabric.Group(objects);
966 this.canvas.add(group);
967 group.setCoords();
968 this.canvas.setActiveObject(group);
969 this.canvas.renderAll();
970 }
971 var e_8, _a;
972 };
973 /**
974 * @param {?} event
975 * @return {?}
976 */
977 CanvasManagerService.prototype.setLastPanPosition = /**
978 * @param {?} event
979 * @return {?}
980 */
981 function (event) {
982 this.lastPanPosition = new fabric.Point(event.touches[0].clientX, event.touches[0].clientY);
983 };
984 /**
985 * @param {?} event
986 * @return {?}
987 */
988 CanvasManagerService.prototype.panCanvas = /**
989 * @param {?} event
990 * @return {?}
991 */
992 function (event) {
993 var /** @type {?} */ delta = new fabric.Point(event.touches[0].clientX - this.lastPanPosition.x, event.touches[0].clientY - this.lastPanPosition.y);
994 this.canvas.relativePan(delta);
995 this.preventPanOutsideCanvas();
996 this.canvas.renderAll();
997 this.setLastPanPosition(event);
998 };
999 /**
1000 * @return {?}
1001 */
1002 CanvasManagerService.prototype.preventPanOutsideCanvas = /**
1003 * @return {?}
1004 */
1005 function () {
1006 var /** @type {?} */ canvasViewPort = this.canvas.viewportTransform;
1007 var /** @type {?} */ bottomEndPoint = this.canvas.height * (canvasViewPort[0] - 1);
1008 if (canvasViewPort[5] >= 0 || -bottomEndPoint > canvasViewPort[5]) {
1009 canvasViewPort[5] = (canvasViewPort[5] >= 0) ? 0 : -bottomEndPoint;
1010 }
1011 var /** @type {?} */ rightEndPoint = this.canvas.width * (canvasViewPort[0] - 1);
1012 if (canvasViewPort[4] >= 0 || -rightEndPoint > canvasViewPort[4]) {
1013 canvasViewPort[4] = (canvasViewPort[4] >= 0) ? 0 : -rightEndPoint;
1014 }
1015 };
1016 /**
1017 * @param {?} event
1018 * @return {?}
1019 */
1020 CanvasManagerService.prototype.zoom = /**
1021 * @param {?} event
1022 * @return {?}
1023 */
1024 function (event) {
1025 if (Math.abs(event.overallVelocity) > 0.005) {
1026 var /** @type {?} */ point = new fabric.Point(event.center.x, event.center.y);
1027 var /** @type {?} */ zoom = this.canvas.getZoom();
1028 zoom = zoom + (event.scale - zoom) / 20;
1029 if (zoom < 1) {
1030 zoom = 1;
1031 this.canvas.zoomToPoint(new fabric.Point(0, 0), zoom);
1032 this.canvas.absolutePan(new fabric.Point(0, 0));
1033 }
1034 else {
1035 if (zoom > 10) {
1036 zoom = 10;
1037 }
1038 this.canvas.zoomToPoint(point, zoom);
1039 }
1040 this.setFreeDrawingBrushWidthFromZoom(zoom);
1041 this.canvas.renderAll();
1042 }
1043 };
1044 /**
1045 * @param {?} width
1046 * @param {?} height
1047 * @return {?}
1048 */
1049 CanvasManagerService.prototype.setCanvasSize = /**
1050 * @param {?} width
1051 * @param {?} height
1052 * @return {?}
1053 */
1054 function (width, height) {
1055 this.canvas.setWidth(width);
1056 this.canvas.setHeight(height);
1057 };
1058 /**
1059 * @return {?}
1060 */
1061 CanvasManagerService.prototype.resetZoom = /**
1062 * @return {?}
1063 */
1064 function () {
1065 this.canvas.zoomToPoint(new fabric.Point(0, 0), 1);
1066 this.canvas.absolutePan(new fabric.Point(0, 0));
1067 };
1068 CanvasManagerService.decorators = [
1069 { type: Injectable },
1070 ];
1071 /** @nocollapse */
1072 CanvasManagerService.ctorParameters = function () { return []; };
1073 return CanvasManagerService;
1074}());
1075
1076/**
1077 * @fileoverview added by tsickle
1078 * @suppress {checkTypes} checked by tsc
1079 */
1080/** @enum {number} */
1081var KEY_CODE = {
1082 DELETE: 46,
1083 BACKSPACE: 8,
1084};
1085KEY_CODE[KEY_CODE.DELETE] = "DELETE";
1086KEY_CODE[KEY_CODE.BACKSPACE] = "BACKSPACE";
1087
1088/**
1089 * @fileoverview added by tsickle
1090 * @suppress {checkTypes} checked by tsc
1091 */
1092var /** @type {?} */ Black = '#000000';
1093var /** @type {?} */ Transparent = 'transparent';
1094var WebSketchToolComponent = /** @class */ (function () {
1095 function WebSketchToolComponent(canvasManagerService) {
1096 this.canvasManagerService = canvasManagerService;
1097 this.availableGeometricShapes = AvailableGeometricShape;
1098 this.canvas = new EventEmitter();
1099 this.strokeColor = Black;
1100 this.fillColor = Transparent;
1101 this.isCropping = false;
1102 this.isLoaded = false;
1103 }
1104 /**
1105 * @return {?}
1106 */
1107 WebSketchToolComponent.prototype.ngOnInit = /**
1108 * @return {?}
1109 */
1110 function () {
1111 this.setCanvas();
1112 };
1113 /**
1114 * @return {?}
1115 */
1116 WebSketchToolComponent.prototype.ngOnChanges = /**
1117 * @return {?}
1118 */
1119 function () {
1120 this.setCanvas();
1121 };
1122 /**
1123 * @return {?}
1124 */
1125 WebSketchToolComponent.prototype.setCanvas = /**
1126 * @return {?}
1127 */
1128 function () {
1129 if (this.imageData) {
1130 this.canvasManagerService.emptyCanvas();
1131 this.canvasManagerService.resetZoom();
1132 if (this.loadedJson == null || this.loadedJson.length < 10) {
1133 this.canvasManagerService.setBackgroundFromURL(this.imageData);
1134 }
1135 else {
1136 this.canvasManagerService.loadfromJson(JSON.parse(this.loadedJson));
1137 }
1138 this.isLoaded = true;
1139 this.previousImageData = this.imageData;
1140 this.emitCanvas();
1141 }
1142 };
1143 /**
1144 * @return {?}
1145 */
1146 WebSketchToolComponent.prototype.addText = /**
1147 * @return {?}
1148 */
1149 function () {
1150 this.canvasManagerService.addText(this.strokeColor, ' ');
1151 this.emitCanvas();
1152 };
1153 /**
1154 * @param {?} shape
1155 * @return {?}
1156 */
1157 WebSketchToolComponent.prototype.addShape = /**
1158 * @param {?} shape
1159 * @return {?}
1160 */
1161 function (shape) {
1162 this.canvasManagerService.addGeometricShape(this.strokeColor, this.fillColor, AvailableGeometricShape[shape]);
1163 this.emitCanvas();
1164 };
1165 /**
1166 * @return {?}
1167 */
1168 WebSketchToolComponent.prototype.changeStrokeColor = /**
1169 * @return {?}
1170 */
1171 function () {
1172 this.canvasManagerService.changeSelectedObjectsStrokeColor(this.strokeColor);
1173 this.canvasManagerService.setFreeDrawingBrushColor(this.strokeColor);
1174 this.emitCanvas();
1175 };
1176 /**
1177 * @return {?}
1178 */
1179 WebSketchToolComponent.prototype.bringFoward = /**
1180 * @return {?}
1181 */
1182 function () {
1183 this.canvasManagerService.bringSelectedObjectsToFront();
1184 this.emitCanvas();
1185 };
1186 /**
1187 * @return {?}
1188 */
1189 WebSketchToolComponent.prototype.sendToBack = /**
1190 * @return {?}
1191 */
1192 function () {
1193 this.canvasManagerService.sendSelectedObjectsToBack();
1194 this.emitCanvas();
1195 };
1196 /**
1197 * @return {?}
1198 */
1199 WebSketchToolComponent.prototype.draw = /**
1200 * @return {?}
1201 */
1202 function () {
1203 this.isDrawing = !this.isDrawing;
1204 this.canvasManagerService.toggleFreeDrawing();
1205 this.canvasManagerService.setFreeDrawingBrushColor(this.strokeColor);
1206 };
1207 /**
1208 * @return {?}
1209 */
1210 WebSketchToolComponent.prototype.saveImage = /**
1211 * @return {?}
1212 */
1213 function () {
1214 var /** @type {?} */ dataURL = this.canvasManagerService.exportImageAsDataURL();
1215 var /** @type {?} */ link = document.createElement('a');
1216 link.download = 'image';
1217 link.href = dataURL;
1218 document.body.appendChild(link);
1219 link.click();
1220 document.body.removeChild(link);
1221 };
1222 /**
1223 * @return {?}
1224 */
1225 WebSketchToolComponent.prototype.crop = /**
1226 * @return {?}
1227 */
1228 function () {
1229 this.isCropping = true;
1230 this.canvasManagerService.disableSelection();
1231 this.canvasManagerService.addSelectionRectangle();
1232 };
1233 /**
1234 * @param {?} event
1235 * @return {?}
1236 */
1237 WebSketchToolComponent.prototype.keyEvent = /**
1238 * @param {?} event
1239 * @return {?}
1240 */
1241 function (event) {
1242 if (event.keyCode === KEY_CODE.DELETE) {
1243 this.deleteSelection();
1244 }
1245 this.emitCanvas();
1246 };
1247 /**
1248 * @return {?}
1249 */
1250 WebSketchToolComponent.prototype.deleteSelection = /**
1251 * @return {?}
1252 */
1253 function () {
1254 this.canvasManagerService.deleteSelectedObjects();
1255 this.emitCanvas();
1256 };
1257 /**
1258 * @param {?} event
1259 * @return {?}
1260 */
1261 WebSketchToolComponent.prototype.mouseUp = /**
1262 * @param {?} event
1263 * @return {?}
1264 */
1265 function (event) {
1266 if (this.isCropping) {
1267 this.canvasManagerService.cropImage();
1268 this.isCropping = false;
1269 }
1270 this.emitCanvas();
1271 };
1272 /**
1273 * @param {?} event
1274 * @return {?}
1275 */
1276 WebSketchToolComponent.prototype.mouseMove = /**
1277 * @param {?} event
1278 * @return {?}
1279 */
1280 function (event) {
1281 if (this.isCropping) {
1282 this.canvasManagerService.ajustCropRectangleFromMouse(event);
1283 }
1284 };
1285 /**
1286 * @param {?} event
1287 * @return {?}
1288 */
1289 WebSketchToolComponent.prototype.mouseDown = /**
1290 * @param {?} event
1291 * @return {?}
1292 */
1293 function (event) {
1294 if (this.isCropping) {
1295 this.canvasManagerService.startSelectingCropRectangleFromMouse(event);
1296 }
1297 };
1298 /**
1299 * @return {?}
1300 */
1301 WebSketchToolComponent.prototype.group = /**
1302 * @return {?}
1303 */
1304 function () {
1305 this.canvasManagerService.groupSelectedObjects();
1306 this.emitCanvas();
1307 };
1308 /**
1309 * @return {?}
1310 */
1311 WebSketchToolComponent.prototype.emitCanvas = /**
1312 * @return {?}
1313 */
1314 function () {
1315 this.canvas.emit(this.canvasManagerService.canvas);
1316 };
1317 WebSketchToolComponent.decorators = [
1318 { type: Component, args: [{
1319 selector: 'lib-web-sketch-tool',
1320 template: "<div\n class=\"div-canvas-container\"\n (mousedown)=\"mouseDown($event)\"\n (mousemove)=\"mouseMove($event)\"\n (mouseup)=\"mouseUp($event)\"\n>\n <canvas id=\"canvas\"></canvas>\n</div>\n\n<mat-toolbar class=\"edit-toolbar\">\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"addShape('Rectangle')\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-square\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"addShape('Circle')\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-circle\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"addShape('Triangle')\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-caret-up\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"addShape('Line')\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-minus\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"addText()\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-font\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n color=\"accent\"\n (click)=\"crop()\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-crop\"></i>\n </button>\n\n <button\n mat-button\n (click)=\"draw()\"\n class=\"tool-button\"\n >\n <i class=\"fas fa-pencil-alt\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"group()\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-object-group\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n color=\"accent\"\n (click)=\"bringFoward()\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-angle-up\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n color=\"accent\"\n (click)=\"sendToBack()\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-angle-down\"></i>\n </button>\n\n <button\n mat-button\n class=\"tool-button\"\n (click)=\"deleteSelection()\"\n [disabled]=\"isDrawing\"\n >\n <i class=\"fas fa-trash\"></i>\n </button>\n\n <button\n mat-button\n (click)=\"saveImage()\"\n class=\"tool-button\"\n >\n <i class=\"fas fa-download\"></i>\n </button>\n\n <input\n mat-button\n class=\"colorPicker\"\n [(colorPicker)]=\"strokeColor\"\n [style.background]=\"strokeColor\"\n (colorPickerChange)=\"changeStrokeColor()\"\n >\n</mat-toolbar>\n",
1321 styles: [".div-canvas-container{text-align:center;margin:0 auto;padding:0;height:90%!important;width:100%!important;-o-object-fit:contain;object-fit:contain}.edit-toolbar{height:7%;justify-content:center}.toolbar-button{font-family:FontAwesome;display:inline-block;width:1.5em;min-width:0}.mat-button.tool-button{min-width:40px!important;width:50px;min-height:40px!important;height:40px;margin-right:10px}.colorPicker{width:40px;height:36px;margin-top:3px;color:transparent}i{font-size:1.5em;color:#000}"],
1322 providers: [CanvasManagerService]
1323 },] },
1324 ];
1325 /** @nocollapse */
1326 WebSketchToolComponent.ctorParameters = function () { return [
1327 { type: CanvasManagerService, },
1328 ]; };
1329 WebSketchToolComponent.propDecorators = {
1330 "imageData": [{ type: Input },],
1331 "loadedJson": [{ type: Input },],
1332 "canvas": [{ type: Output },],
1333 "keyEvent": [{ type: HostListener, args: ['window:keyup', ['$event'],] },],
1334 };
1335 return WebSketchToolComponent;
1336}());
1337
1338/**
1339 * @fileoverview added by tsickle
1340 * @suppress {checkTypes} checked by tsc
1341 */
1342var WebSketchToolModule = /** @class */ (function () {
1343 function WebSketchToolModule() {
1344 }
1345 WebSketchToolModule.decorators = [
1346 { type: NgModule, args: [{
1347 imports: [CommonModule, ColorPickerModule, MatButtonModule, MatToolbarModule],
1348 declarations: [WebSketchToolComponent],
1349 exports: [WebSketchToolComponent]
1350 },] },
1351 ];
1352 return WebSketchToolModule;
1353}());
1354
1355/**
1356 * @fileoverview added by tsickle
1357 * @suppress {checkTypes} checked by tsc
1358 */
1359
1360/**
1361 * @fileoverview added by tsickle
1362 * @suppress {checkTypes} checked by tsc
1363 */
1364
1365export { WebSketchToolComponent, CanvasManagerService, WebSketchToolModule };
1366
1367//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliLXNrZXRjaC10b29sLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9saWItc2tldGNoLXRvb2wvYXBwL2xpYi1za2V0Y2gtdG9vbC9jb25zdGFudHMvc2hhcGUtZGF0YS50cyIsIm5nOi8vbGliLXNrZXRjaC10b29sL2FwcC9saWItc2tldGNoLXRvb2wvc2VydmljZXMvY2FudmFzLW1hbmFnZXIuc2VydmljZS50cyIsIm5nOi8vbGliLXNrZXRjaC10b29sL2FwcC9saWItc2tldGNoLXRvb2wvd2ViLWNvbXBvbmVudC93ZWItc2tldGNoLXRvb2wuY29tcG9uZW50LnRzIiwibmc6Ly9saWItc2tldGNoLXRvb2wvYXBwL2xpYi1za2V0Y2gtdG9vbC93ZWItc2tldGNoLXRvb2wubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBTSEFQRV9EQVRBID0ge1xuICB3aWR0aDogMjAwLFxuICBoZWlnaHQ6IDIwMCxcbiAgbGVmdDogNTAsXG4gIHRvcDogNTAsXG4gIHJhZGl1czogMTAwLFxuICBzdHJva2U6IDEwLFxuICBmcmVlRHJhd2luZ0JydXNoV2lkdGg6IDEwLFxuICBjb3JuZXJTaXplOiAyMFxufTtcbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGZhYnJpYyB9IGZyb20gJ2ZhYnJpYyc7XG5cbmltcG9ydCB7IEF2YWlsYWJsZUdlb21ldHJpY1NoYXBlIH0gZnJvbSAnLi8uLi9jb25zdGFudHMvYXZhaWxhYmxlLWdlb21ldHJpYy1zaGFwZXMnO1xuaW1wb3J0IHsgU0hBUEVfREFUQSB9IGZyb20gJy4vLi4vY29uc3RhbnRzL3NoYXBlLWRhdGEnO1xuXG5pbnRlcmZhY2UgU2NhbGVEYXRhIHtcbiAgc2NhbGVGYWN0b3I6IG51bWJlcjtcbiAgbGVmdDogbnVtYmVyO1xuICB0b3A6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFBvc2l0aW9uIHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBDYW52YXNNYW5hZ2VyU2VydmljZSB7XG4gIHB1YmxpYyBjYW52YXM7XG5cbiAgcHJpdmF0ZSBjcm9wUmVjdGFuZ2xlOiBmYWJyaWMuUmVjdDtcbiAgcHJpdmF0ZSBtb3VzZVBvc2l0aW9uOiBQb3NpdGlvbjtcbiAgcHJpdmF0ZSBjcm9wU3RhcnRpbmdQb3NpdGlvbjogUG9zaXRpb247XG4gIHByaXZhdGUgbGFzdFBhblBvc2l0aW9uOiBmYWJyaWMuUG9pbnQ7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5lbXB0eUNhbnZhcygpO1xuICAgIHRoaXMubW91c2VQb3NpdGlvbiA9IHt4OiAwLCB5OiAwfTtcbiAgICB0aGlzLmNyb3BTdGFydGluZ1Bvc2l0aW9uID0ge3g6IDAsIHk6IDB9O1xuICB9XG5cbiAgZ2V0IGNhbnZhc09iamVjdHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldE9iamVjdHMoKTtcbiAgfVxuXG4gIGdldCBjYW52YXNCYWNrZ3JvdW5kSW1hZ2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmJhY2tncm91bmRJbWFnZTtcbiAgfVxuXG4gIGdldCBhY3RpdmVPYmplY3QoKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLmdldEFjdGl2ZU9iamVjdCgpO1xuICB9XG5cbiAgZ2V0IGFjdGl2ZUdyb3VwKCkge1xuICAgIHJldHVybiB0aGlzLmNhbnZhcy5nZXRBY3RpdmVPYmplY3RzKCk7XG4gIH1cblxuICBnZXQgZGl2Q2FudmFzQ29udGFpbmVyKCkge1xuICAgIHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdkaXYtY2FudmFzLWNvbnRhaW5lcicpWzBdO1xuICB9XG5cbiAgcHVibGljIGVtcHR5Q2FudmFzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmNhbnZhcykge1xuICAgICAgdGhpcy5jYW52YXMuZGlzcG9zZSgpO1xuICAgIH1cbiAgICB0aGlzLmNhbnZhcyA9IG5ldyBmYWJyaWMuQ2FudmFzKCdjYW52YXMnKTtcbiAgICB0aGlzLmNhbnZhcy5jbGVhcigpO1xuICAgIHRoaXMuY2FudmFzLnJlbW92ZSh0aGlzLmNhbnZhcy5nZXRPYmplY3RzKCkpO1xuICB9XG5cbiAgcHVibGljIGxvYWROZXdJbWFnZShiYWNrZ3JvdW5kSW1hZ2VVUkw/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmVtcHR5Q2FudmFzKCk7XG4gICAgaWYgKGJhY2tncm91bmRJbWFnZVVSTCkge1xuICAgICAgdGhpcy5zZXRCYWNrZ3JvdW5kRnJvbVVSTChiYWNrZ3JvdW5kSW1hZ2VVUkwpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyByZW5kZXJDYW52YXMoKTogdm9pZCB7XG4gICAgdGhpcy5tYXJrU2VsZWN0ZWRPYmplY3RzRGlydHkoKTtcbiAgICB0aGlzLmNhbnZhcy5yZW5kZXJBbGwoKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRHZW9tZXRyaWNTaGFwZShzdHJva2VDb2xvcjogc3RyaW5nLCBmaWxsQ29sb3I6IHN0cmluZywgc2hhcGU6IEF2YWlsYWJsZUdlb21ldHJpY1NoYXBlKTogdm9pZCB7XG4gICAgc3dpdGNoIChzaGFwZSkge1xuICAgICAgY2FzZSBBdmFpbGFibGVHZW9tZXRyaWNTaGFwZS5SZWN0YW5nbGU6XG4gICAgICAgIHRoaXMuYWRkUmVjdGFuZ2xlKHN0cm9rZUNvbG9yLCBmaWxsQ29sb3IpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQXZhaWxhYmxlR2VvbWV0cmljU2hhcGUuQ2lyY2xlOlxuICAgICAgICB0aGlzLmFkZENpcmNsZShzdHJva2VDb2xvciwgZmlsbENvbG9yKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEF2YWlsYWJsZUdlb21ldHJpY1NoYXBlLlRyaWFuZ2xlOlxuICAgICAgICB0aGlzLmFkZFRyaWFuZ2xlKHN0cm9rZUNvbG9yLCBmaWxsQ29sb3IpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQXZhaWxhYmxlR2VvbWV0cmljU2hhcGUuTGluZTpcbiAgICAgICAgdGhpcy5hZGRIb3Jpem9udGFsTGluZShzdHJva2VDb2xvciwgZmlsbENvbG9yKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEF2YWlsYWJsZUdlb21ldHJpY1NoYXBlLkNyb3NzOlxuICAgICAgICB0aGlzLmFkZENyb3NzKHN0cm9rZUNvbG9yLCBmaWxsQ29sb3IpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFkZFJlY3RhbmdsZShzdHJva2VDb2xvcjogc3RyaW5nLCBmaWxsQ29sb3I6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY2FudmFzLmFkZChcbiAgICAgIG5ldyBmYWJyaWMuUmVjdCh7XG4gICAgICAgIHdpZHRoOiBTSEFQRV9EQVRBLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IFNIQVBFX0RBVEEuaGVpZ2h0LFxuICAgICAgICBsZWZ0OiBTSEFQRV9EQVRBLmxlZnQsXG4gICAgICAgIHRvcDogU0hBUEVfREFUQS50b3AsXG4gICAgICAgIGZpbGw6IGZpbGxDb2xvcixcbiAgICAgICAgc3Ryb2tlOiBzdHJva2VDb2xvcixcbiAgICAgICAgc3Ryb2tlV2lkdGg6IFNIQVBFX0RBVEEuc3Ryb2tlLFxuICAgICAgICBjb3JuZXJTaXplOiBTSEFQRV9EQVRBLmNvcm5lclNpemVcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQ2lyY2xlKHN0cm9rZUNvbG9yOiBzdHJpbmcsIGZpbGxDb2xvcjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jYW52YXMuYWRkKFxuICAgICAgbmV3IGZhYnJpYy5DaXJjbGUoe1xuICAgICAgICBsZWZ0OiBTSEFQRV9EQVRBLmxlZnQsXG4gICAgICAgIHRvcDogU0hBUEVfREFUQS50b3AsXG4gICAgICAgIHJhZGl1czogU0hBUEVfREFUQS5yYWRpdXMsXG4gICAgICAgIHN0cm9rZTogc3Ryb2tlQ29sb3IsXG4gICAgICAgIHN0cm9rZVdpZHRoOiBTSEFQRV9EQVRBLnN0cm9rZSxcbiAgICAgICAgZmlsbDogZmlsbENvbG9yLFxuICAgICAgICBjb3JuZXJTaXplOiBTSEFQRV9EQVRBLmNvcm5lclNpemVcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkVHJpYW5nbGUoc3Ryb2tlQ29sb3I6IHN0cmluZywgZmlsbENvbG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmNhbnZhcy5hZGQoXG4gICAgICBuZXcgZmFicmljLlRyaWFuZ2xlKHtcbiAgICAgICAgd2lkdGg6IFNIQVBFX0RBVEEud2lkdGgsXG4gICAgICAgIGhlaWdodDogU0hBUEVfREFUQS5oZWlnaHQsXG4gICAgICAgIGxlZnQ6IFNIQVBFX0RBVEEubGVmdCxcbiAgICAgICAgdG9wOiBTSEFQRV9EQVRBLnRvcCxcbiAgICAgICAgZmlsbDogZmlsbENvbG9yLFxuICAgICAgICBzdHJva2U6IHN0cm9rZUNvbG9yLFxuICAgICAgICBzdHJva2VXaWR0aDogU0hBUEVfREFUQS5zdHJva2UsXG4gICAgICAgIGNvcm5lclNpemU6IFNIQVBFX0RBVEEuY29ybmVyU2l6ZVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRIb3Jpem9udGFsTGluZShzdHJva2VDb2xvcjogc3RyaW5nLCBmaWxsQ29sb3I6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY2FudmFzLmFkZCh0aGlzLmNyZWF0ZUhvcml6b250YWxMaW5lKHN0cm9rZUNvbG9yKSk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUhvcml6b250YWxMaW5lKHN0cm9rZUNvbG9yOiBzdHJpbmcpOiBmYWJyaWMuTGluZSB7XG4gICAgY29uc3QgbGluZSA9IG5ldyBmYWJyaWMuTGluZShbMTAwLCAxNTAsIDIwMCwgMTUwXSwge1xuICAgICAgbGVmdDogNTAsXG4gICAgICB0b3A6IDEwMCxcbiAgICAgIHN0cm9rZTogc3Ryb2tlQ29sb3IsXG4gICAgICBzdHJva2VXaWR0aDogNSxcbiAgICAgIGNvcm5lclNpemU6IFNIQVBFX0RBVEEuY29ybmVyU2l6ZVxuICAgIH0pO1xuXG4gICAgbGluZS5zZXRDb250cm9sc1Zpc2liaWxpdHkoe1xuICAgICAgYmw6IGZhbHNlLFxuICAgICAgYnI6IGZhbHNlLFxuICAgICAgdGw6IGZhbHNlLFxuICAgICAgdHI6IGZhbHNlLFxuICAgICAgbXQ6IGZhbHNlLFxuICAgICAgbWI6IGZhbHNlXG4gICAgfSk7XG5cbiAgICByZXR1cm4gbGluZTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVmVydGljYWxMaW5lKHN0cm9rZUNvbG9yOiBzdHJpbmcpOiBmYWJyaWMuTGluZSB7XG4gICAgY29uc3QgbGluZSA9IG5ldyBmYWJyaWMuTGluZShbMTUwLCAxMDAsIDE1MCwgMjAwXSwge1xuICAgICAgbGVmdDogMTAwLFxuICAgICAgdG9wOiA1MCxcbiAgICAgIHN0cm9rZTogc3Ryb2tlQ29sb3IsXG4gICAgICBzdHJva2VXaWR0aDogNSxcbiAgICAgIGNvcm5lclNpemU6IFNIQVBFX0RBVEEuY29ybmVyU2l6ZVxuICAgIH0pO1xuXG4gICAgbGluZS5zZXRDb250cm9sc1Zpc2liaWxpdHkoe1xuICAgICAgYmw6IGZhbHNlLFxuICAgICAgYnI6IGZhbHNlLFxuICAgICAgdGw6IGZhbHNlLFxuICAgICAgdHI6IGZhbHNlLFxuICAgICAgbWw6IGZhbHNlLFxuICAgICAgbXI6IGZhbHNlXG4gICAgfSk7XG5cbiAgICByZXR1cm4gbGluZTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQ3Jvc3Moc3Ryb2tlQ29sb3I6IHN0cmluZywgZmlsbENvbG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBob3Jpem9udGFsTGluZSA9IHRoaXMuY3JlYXRlSG9yaXpvbnRhbExpbmUoc3Ryb2tlQ29sb3IpO1xuICAgIGNvbnN0IHZlcnRpY2FsTGluZSA9IHRoaXMuY3JlYXRlVmVydGljYWxMaW5lKHN0cm9rZUNvbG9yKTtcbiAgICB0aGlzLmNhbnZhcy5hZGQoaG9yaXpvbnRhbExpbmUpO1xuICAgIHRoaXMuY2FudmFzLmFkZCh2ZXJ0aWNhbExpbmUpO1xuICB9XG5cbiAgcHVibGljIHRvZ2dsZUZyZWVEcmF3aW5nKCk6IHZvaWQge1xuICAgIHRoaXMuY2FudmFzLmlzRHJhd2luZ01vZGUgPSAhdGhpcy5jYW52YXMuaXNEcmF3aW5nTW9kZTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRGcmVlRHJhd2luZ0JydXNoQ29sb3IoY29sb3I6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY2FudmFzLmZyZWVEcmF3aW5nQnJ1c2guY29sb3IgPSBjb2xvcjtcbiAgICB0aGlzLnNldEZyZWVEcmF3aW5nQnJ1c2hXaWR0aEZyb21ab29tKHRoaXMuY2FudmFzLmdldFpvb20oKSk7XG4gIH1cblxuICBwcml2YXRlIHNldEZyZWVEcmF3aW5nQnJ1c2hXaWR0aEZyb21ab29tKHpvb206IG51bWJlcikge1xuICAgIHRoaXMuY2FudmFzLmZyZWVEcmF3aW5nQnJ1c2gud2lkdGggPSBTSEFQRV9EQVRBLmZyZWVEcmF3aW5nQnJ1c2hXaWR0aCAqICgxIC8gem9vbSk7XG4gIH1cblxuICBwdWJsaWMgYWRkVGV4dChjb2xvcjogc3RyaW5nLCBpbnB1dFRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHRleHQgPSBuZXcgZmFicmljLklUZXh0KCd0ZXh0Jywge1xuICAgICAgZm9udEZhbWlseTogJ2FyaWFsIGJsYWNrJyxcbiAgICAgIGZvbnRTdHlsZTogJ2JvbGQnLFxuICAgICAgbGVmdDogU0hBUEVfREFUQS5sZWZ0LFxuICAgICAgdG9wOiBTSEFQRV9EQVRBLnRvcCxcbiAgICAgIGNvcm5lclNpemU6IFNIQVBFX0RBVEEuY29ybmVyU2l6ZVxuICAgIH0pO1xuXG4gICAgdGV4dC5zZXRDb2xvcihjb2xvcik7XG5cbiAgICB0aGlzLmNhbnZhcy5hZGQodGV4dCk7XG4gIH1cblxuICBwdWJsaWMgYWRkSW1hZ2UoaW1hZ2VVUkw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShcbiAgICAgIChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgY2FudmFzID0gdGhpcy5jYW52YXM7XG5cbiAgICAgICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24oaW1nKSB7XG4gICAgICAgICAgY29uc3QgZmFicmljSW1hZ2UgPSBuZXcgZmFicmljLkltYWdlKGltYWdlLCB7XG4gICAgICAgICAgICBhbmdsZTogMCxcbiAgICAgICAgICAgIHdpZHRoOiBpbWFnZS53aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogaW1hZ2UuaGVpZ2h0LFxuICAgICAgICAgICAgbGVmdDogU0hBUEVfREFUQS5sZWZ0LFxuICAgICAgICAgICAgdG9wOiBTSEFQRV9EQVRBLnRvcCxcbiAgICAgICAgICAgIHNjYWxlWDogMSxcbiAgICAgICAgICAgIHNjYWxlWTogMSxcbiAgICAgICAgICAgIGNvcm5lclNpemU6IFNIQVBFX0RBVEEuY29ybmVyU2l6ZVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhbnZhcy5hZGQoZmFicmljSW1hZ2UpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgaW1hZ2Uuc3JjID0gaW1hZ2VVUkw7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRCYWNrZ3JvdW5kRnJvbVVSTChiYWNrZ3JvdW5kSW1hZ2VVUkw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMuY2FudmFzO1xuICAgIGNvbnN0IHJlc2l6ZSA9IHRoaXMucmVzaXplQ2FudmFzQW5kQ29tcHV0ZVNjYWxlRmFjdG9yO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKFxuICAgICAgKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoYmFja2dyb3VuZEltYWdlVVJMID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgY29uc3QgZl9pbWcgPSBuZXcgZmFicmljLkltYWdlKGltYWdlLCB7fSk7XG5cbiAgICAgICAgICBjb25zdCBzY2FsZURhdGEgPSByZXNpemUoZl9pbWcsIGNhbnZhcyk7XG5cbiAgICAgICAgICBjYW52YXMuc2V0QmFja2dyb3VuZEltYWdlKGZfaW1nLCBjYW52YXMucmVuZGVyQWxsLmJpbmQoY2FudmFzKSwge1xuICAgICAgICAgICAgc2NhbGVYOiBzY2FsZURhdGEuc2NhbGVGYWN0b3IsXG4gICAgICAgICAgICBzY2FsZVk6IHNjYWxlRGF0YS5zY2FsZUZhY3RvclxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY2FudmFzLnNldFdpZHRoKGZfaW1nLndpZHRoICogc2NhbGVEYXRhLnNjYWxlRmFjdG9yKTtcbiAgICAgICAgICBjYW52YXMuc2V0SGVpZ2h0KGZfaW1nLmhlaWdodCAqIHNjYWxlRGF0YS5zY2FsZUZhY3Rvcik7XG5cbiAgICAgICAgICBjYW52YXMucmVuZGVyQWxsKCk7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBpbWFnZS5zcmMgPSBiYWNrZ3JvdW5kSW1hZ2VVUkw7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzaXplQ2FudmFzQW5kQ29tcHV0ZVNjYWxlRmFjdG9yKGZfaW1nOiBmYWJyaWMuSW1hZ2UsIGNhbnZhczogZmFicmljLkNhbnZhcyk6IFNjYWxlRGF0YSB7XG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcbiAgICAgICdkaXYtY2FudmFzLWNvbnRhaW5lcidcbiAgICApWzBdO1xuXG4gICAgY2FudmFzLnNldFdpZHRoKGNvbnRhaW5lci5jbGllbnRXaWR0aCk7XG4gICAgY2FudmFzLnNldEhlaWdodChjb250YWluZXIuY2xpZW50SGVpZ2h0KTtcblxuICAgIGNvbnN0IGNhbnZhc0FzcGVjdCA9IGNvbnRhaW5lci5jbGllbnRXaWR0aCAvIGNvbnRhaW5lci5jbGllbnRIZWlnaHQ7XG4gICAgY29uc3QgaW1nQXNwZWN0ID0gZl9pbWcud2lkdGggLyBmX2ltZy5oZWlnaHQ7XG4gICAgbGV0IGxlZnQsIHRvcCwgc2NhbGVGYWN0b3I7XG5cbiAgICBpZiAoY2FudmFzQXNwZWN0IDw9IGltZ0FzcGVjdCkge1xuICAgICAgc2NhbGVGYWN0b3IgPSBjb250YWluZXIuY2xpZW50V2lkdGggLyBmX2ltZy53aWR0aDtcbiAgICAgIGxlZnQgPSAwO1xuICAgICAgdG9wID0gLShmX2ltZy5oZWlnaHQgKiBzY2FsZUZhY3RvciAtIGNvbnRhaW5lci5jbGllbnRIZWlnaHQpIC8gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgc2NhbGVGYWN0b3IgPSBjb250YWluZXIuY2xpZW50SGVpZ2h0IC8gZl9pbWcuaGVpZ2h0O1xuICAgICAgdG9wID0gMDtcbiAgICAgIGxlZnQgPSAtKGZfaW1nLndpZHRoICogc2NhbGVGYWN0b3IgLSBjb250YWluZXIuY2xpZW50V2lkdGgpIC8gMjtcbiAgICB9XG5cbiAgICByZXR1cm4geyBzY2FsZUZhY3Rvcjogc2NhbGVGYWN0b3IsIGxlZnQ6IGxlZnQsIHRvcDogdG9wIH07XG4gIH1cblxuICBwdWJsaWMgb25PcmllbnRhdGlvbkNoYW5nZSgpIHtcbiAgICB0aGlzLm1vdXNlUG9zaXRpb24gPSB7eDogdGhpcy5jYW52YXMuZ2V0V2lkdGgsIHk6IHRoaXMuY2FudmFzLmdldEhlaWdodCB9O1xuICAgIHRoaXMuY3JvcEltYWdlKCk7XG4gIH1cblxuICBwdWJsaWMgY2hhbmdlU2VsZWN0ZWRPYmplY3RzRmlsbENvbG9yKGNvbG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBhY3RpdmVPYmplY3RzID0gdGhpcy5jYW52YXMuZ2V0QWN0aXZlT2JqZWN0cygpO1xuXG4gICAgaWYgKGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgIGZvciAoY29uc3Qgb2JqZWN0IG9mIGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgICAgb2JqZWN0LnNldENvbG9yKGNvbG9yKTtcbiAgICAgICAgdGhpcy5jYW52YXMucmVuZGVyQWxsKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGNoYW5nZVNlbGVjdGVkT2JqZWN0c1N0cm9rZUNvbG9yKGNvbG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBhY3RpdmVPYmplY3RzID0gdGhpcy5jYW52YXMuZ2V0QWN0aXZlT2JqZWN0cygpO1xuXG4gICAgaWYgKGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgIGZvciAoY29uc3Qgb2JqZWN0IG9mIGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgICAgaWYgKG9iamVjdC50eXBlID09PSAnaS10ZXh0Jykge1xuICAgICAgICAgIG9iamVjdC5zZXRDb2xvcihjb2xvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb2JqZWN0LnN0cm9rZSA9IGNvbG9yO1xuICAgICAgICAgIG9iamVjdC5zZXQoJ2RpcnR5JywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuY2FudmFzLnJlbmRlckFsbCgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBkZWxldGVTZWxlY3RlZE9iamVjdHMoKTogdm9pZCB7XG4gICAgY29uc3QgYWN0aXZlT2JqZWN0cyA9IHRoaXMuY2FudmFzLmdldEFjdGl2ZU9iamVjdHMoKTtcblxuICAgIGlmIChhY3RpdmVPYmplY3RzKSB7XG4gICAgICBmb3IgKGNvbnN0IG9iamVjdCBvZiBhY3RpdmVPYmplY3RzKSB7XG4gICAgICAgIHRoaXMuY2FudmFzLnJlbW92ZShvYmplY3QpO1xuICAgICAgfVxuICAgICAgdGhpcy5jYW52YXMuZGlzY2FyZEFjdGl2ZU9iamVjdCgpO1xuICAgICAgdGhpcy5jYW52YXMucmVuZGVyQWxsKCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGJyaW5nU2VsZWN0ZWRPYmplY3RzVG9Gcm9udCgpOiB2b2lkIHtcbiAgICBjb25zdCBhY3RpdmVPYmplY3RzID0gdGhpcy5jYW52YXMuZ2V0QWN0aXZlT2JqZWN0cygpO1xuXG4gICAgaWYgKGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgIGZvciAoY29uc3Qgb2JqZWN0IG9mIGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgICAgdGhpcy5jYW52YXMuYnJpbmdUb0Zyb250KG9iamVjdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHNlbmRTZWxlY3RlZE9iamVjdHNUb0JhY2soKTogdm9pZCB7XG4gICAgY29uc3QgYWN0aXZlT2JqZWN0cyA9IHRoaXMuY2FudmFzLmdldEFjdGl2ZU9iamVjdHMoKTtcblxuICAgIGlmIChhY3RpdmVPYmplY3RzKSB7XG4gICAgICBmb3IgKGNvbnN0IG9iamVjdCBvZiBhY3RpdmVPYmplY3RzKSB7XG4gICAgICAgIHRoaXMuY2FudmFzLnNlbmRUb0JhY2sob2JqZWN0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwdWJsaWMganNvbkZyb21DYW52YXMoKTogSlNPTiB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLnRvSlNPTigpO1xuICB9XG5cbiAgcHVibGljIGxvYWRmcm9tSnNvbihqc29uOiBKU09OKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5kaXZDYW52YXNDb250YWluZXI7XG5cbiAgICB0aGlzLnNldENhbnZhc1NpemUoY29udGFpbmVyLmNsaWVudFdpZHRoLCBjb250YWluZXIuY2xpZW50SGVpZ2h0KTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShcbiAgICAgIChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5hZGp1c3RDYW52YXMoanNvbik7XG4gICAgICAgIHRoaXMuY2FudmFzLmxvYWRGcm9tSlNPTihqc29uLCB0aGlzLmNhbnZhcy5yZW5kZXJBbGwuYmluZCh0aGlzLmNhbnZhcykpO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGp1c3RDYW52YXMoanNvbjogSlNPTik6IHZvaWQge1xuICAgIGNvbnN0IGJhY2tncm91bmRJbWFnZSA9IGpzb25bJ2JhY2tncm91bmRJbWFnZSddO1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5kaXZDYW52YXNDb250YWluZXI7XG5cbiAgICBjb25zdCB3aWR0aCA9IGJhY2tncm91bmRJbWFnZVsnd2lkdGgnXTtcbiAgICBjb25zdCBoZWlnaHQgPSBiYWNrZ3JvdW5kSW1hZ2VbJ2hlaWdodCddO1xuXG4gICAgY29uc3QgY2FudmFzV2lkdGggPSBjb250YWluZXIuY2xpZW50V2lkdGg7XG4gICAgY29uc3QgY2FudmFzSGVpZ2h0ID0gY29udGFpbmVyLmNsaWVudEhlaWdodDtcblxuICAgIGNvbnN0IGNhbnZhc0FzcGVjdCA9IGNhbnZhc1dpZHRoIC8gY2FudmFzSGVpZ2h0O1xuICAgIGNvbnN0IGltZ0FzcGVjdCA9IHdpZHRoIC8gaGVpZ2h0O1xuICAgIGxldCBzY2FsZUZhY3RvcjtcblxuICAgIGlmIChjYW52YXNBc3BlY3QgPD0gaW1nQXNwZWN0KSB7XG4gICAgICBzY2FsZUZhY3RvciA9IGNhbnZhc1dpZHRoIC8gd2lkdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjYWxlRmFjdG9yID0gY2FudmFzSGVpZ2h0IC8gaGVpZ2h0O1xuICAgIH1cblxuICAgIGNvbnN0IG9iamVjdFNjYWxlID0gc2NhbGVGYWN0b3IgLyBiYWNrZ3JvdW5kSW1hZ2VbJ3NjYWxlWCddO1xuXG4gICAgYmFja2dyb3VuZEltYWdlWydzY2FsZVgnXSA9IHNjYWxlRmFjdG9yO1xuICAgIGJhY2tncm91bmRJbWFnZVsnc2NhbGVZJ10gPSBzY2FsZUZhY3RvcjtcblxuICAgIHRoaXMuc2V0Q2FudmFzU2l6ZSh3aWR0aCAqIHNjYWxlRmFjdG9yLCBoZWlnaHQgKiBzY2FsZUZhY3Rvcik7XG5cbiAgICBjb25zdCBvYmplY3RzID0ganNvblsnb2JqZWN0cyddO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYmplY3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBvYmplY3RzW2ldWydsZWZ0J10gKj0gb2JqZWN0U2NhbGU7XG4gICAgICBvYmplY3RzW2ldWyd0b3AnXSAqPSBvYmplY3RTY2FsZTtcbiAgICAgIG9iamVjdHNbaV1bJ3NjYWxlWCddICo9IG9iamVjdFNjYWxlO1xuICAgICAgb2JqZWN0c1tpXVsnc2NhbGVZJ10gKj0gb2JqZWN0U2NhbGU7XG4gICAgfVxuXG4gICAgdGhpcy5jYW52YXMuc2VsZWN0YWJsZSA9IHRydWU7XG4gICAgdGhpcy5jYW52YXMuc2VsZWN0aW9uID0gdHJ1ZTtcblxuICAgIHRoaXMuY2FudmFzLnJlbmRlckFsbCgpO1xuICB9XG5cbiAgcHVibGljIGV4cG9ydEltYWdlQXNEYXRhVVJMKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG4gIH1cblxuICBwdWJsaWMgc2VsZWN0SXRlbShpdGVtTnVtYmVyOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmNhbnZhcy5zZXRBY3RpdmVPYmplY3QodGhpcy5jYW52YXMuaXRlbShpdGVtTnVtYmVyKSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0SW5kZXhPZihhY3RpdmVPYmplY3QpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmNhbnZhcy5nZXRPYmplY3RzKCkuaW5kZXhPZihhY3RpdmVPYmplY3QpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZWxlY3RMYXN0T2JqZWN0KCk6IHZvaWQge1xuICAgIGNvbnN0IGl0ZW1OdW1iZXIgPSB0aGlzLmNhbnZhcy5nZXRPYmplY3RzKCkubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBvYmplY3QgPSB0aGlzLmNhbnZhcy5pdGVtKGl0ZW1OdW1iZXIpO1xuICAgIHRoaXMuY2FudmFzLnNldEFjdGl2ZU9iamVjdChvYmplY3QpO1xuICAgIG9iamVjdC5lbnRlckVkaXRpbmcoKTtcbiAgfVxuXG4gIHByaXZhdGUgbWFya1NlbGVjdGVkT2JqZWN0c0RpcnR5KCk6IHZvaWQge1xuICAgIGNvbnN0IGFjdGl2ZU9iamVjdHMgPSB0aGlzLmNhbnZhcy5nZXRBY3RpdmVPYmplY3RzKCk7XG5cbiAgICBpZiAoYWN0aXZlT2JqZWN0cykge1xuICAgICAgZm9yIChjb25zdCBvYmplY3Qgb2YgYWN0aXZlT2JqZWN0cykge1xuICAgICAgICBvYmplY3Quc2V0KCdkaXJ0eScsIHRydWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhZGRTZWxlY3Rpb25SZWN0YW5nbGUoKTogdm9pZCB7XG4gICAgdGhpcy5jcm9wUmVjdGFuZ2xlID0gbmV3IGZhYnJpYy5SZWN0KHtcbiAgICAgIGZpbGw6ICd0cmFuc3BhcmVudCcsXG4gICAgICBvcmlnaW5YOiAnbGVmdCcsXG4gICAgICBvcmlnaW5ZOiAndG9wJyxcbiAgICAgIHN0cm9rZTogJyNjY2MnLFxuICAgICAgc3Ryb2tlRGFzaEFycmF5OiBbMiwgMl0sXG4gICAgICBvcGFjaXR5OiAxLFxuICAgICAgd2lkdGg6IDEsXG4gICAgICBoZWlnaHQ6IDFcbiAgICB9KTtcblxuICAgIHRoaXMuY3JvcFJlY3RhbmdsZS52aXNpYmxlID0gZmFsc2U7XG4gICAgdGhpcy5jYW52YXMuYWRkKHRoaXMuY3JvcFJlY3RhbmdsZSk7XG4gIH1cblxuICBwdWJsaWMgYWp1c3RDcm9wUmVjdGFuZ2xlRnJvbU1vdXNlKGV2ZW50OiBNb3VzZUV2ZW50KTogYm9vbGVhbiB7XG4gICAgY29uc3QgeCA9IE1hdGgubWluKGV2ZW50LmxheWVyWCwgdGhpcy5tb3VzZVBvc2l0aW9uLngpLFxuICAgICAgeSA9IE1hdGgubWluKGV2ZW50LmxheWVyWSwgdGhpcy5tb3VzZVBvc2l0aW9uLnkpLFxuICAgICAgdyA9IE1hdGguYWJzKGV2ZW50LmxheWVyWCAtIHRoaXMubW91c2VQb3NpdGlvbi54KSxcbiAgICAgIGggPSBNYXRoLmFicyhldmVudC5sYXllclkgLSB0aGlzLm1vdXNlUG9zaXRpb24ueSk7XG5cbiAgICBpZiAoIXcgfHwgIWgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLmNyb3BSZWN0YW5nbGVcbiAgICAgIC5zZXQoJ3RvcCcsIHkpXG4gICAgICAuc2V0KCdsZWZ0JywgeClcbiAgICAgIC5zZXQoJ3dpZHRoJywgdylcbiAgICAgIC5zZXQoJ2hlaWdodCcsIGgpO1xuXG4gICAgdGhpcy5jYW52YXMucmVuZGVyQWxsKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHB1YmxpYyBzdGFydFNlbGVjdGluZ0Nyb3BSZWN0YW5nbGVGcm9tTW91c2UoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmNyb3BTdGFydGluZ1Bvc2l0aW9uID0geyB4OiB0aGlzLmNhbnZhcy5sZWZ0LCB5OiB0aGlzLmNhbnZhcy50b3AgfTtcblxuICAgIHRoaXMuY3JvcFJlY3RhbmdsZS5sZWZ0ID0gZXZlbnQubGF5ZXJYO1xuICAgIHRoaXMuY3JvcFJlY3RhbmdsZS50b3AgPSBldmVudC5sYXllclk7XG4gICAgdGhpcy5jcm9wUmVjdGFuZ2xlLnNldENvb3JkcygpO1xuXG4gICAgdGhpcy5tb3VzZVBvc2l0aW9uID0ge3g6IGV2ZW50LmxheWVyWCwgeTogZXZlbnQubGF5ZXJZIH07XG5cbiAgICB0aGlzLmNhbnZhcy5yZW5kZXJBbGwoKTtcbiAgICB0aGlzLmNyb3BSZWN0YW5nbGUudmlzaWJsZSA9IHRydWU7XG4gICAgdGhpcy5jYW52YXMuYnJpbmdUb0Zyb250KHRoaXMuY3JvcFJlY3RhbmdsZSk7XG4gIH1cblxuICBwdWJsaWMgY3JvcEltYWdlKCk6IHZvaWQge1xuICAgIGNvbnN0IGxlZnQgPSB0aGlzLmNyb3BSZWN0YW5nbGUubGVmdDtcbiAgICBjb25zdCB0b3AgPSB0aGlzLmNyb3BSZWN0YW5nbGUudG9wO1xuXG4gICAgY29uc3Qgd2lkdGggPSB0aGlzLmNyb3BSZWN0YW5nbGUud2lkdGg7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5jcm9wUmVjdGFuZ2xlLmhlaWdodDtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuZGl2Q2FudmFzQ29udGFpbmVyO1xuXG4gICAgY29uc3QgY2FudmFzV2lkdGggPSBjb250YWluZXIuY2xpZW50V2lkdGg7XG4gICAgY29uc3QgY2FudmFzSGVpZ2h0ID0gY29udGFpbmVyLmNsaWVudEhlaWdodDtcblxuICAgIGNvbnN0IGNhbnZhc0FzcGVjdCA9IGNhbnZhc1dpZHRoIC8gY2FudmFzSGVpZ2h0O1xuICAgIGNvbnN0IGltZ0FzcGVjdCA9IHdpZHRoIC8gaGVpZ2h0O1xuICAgIGxldCBzY2FsZUZhY3RvcjtcblxuICAgIGlmIChjYW52YXNBc3BlY3QgPD0gaW1nQXNwZWN0KSB7XG4gICAgICBzY2FsZUZhY3RvciA9IGNhbnZhc1dpZHRoIC8gd2lkdGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjYWxlRmFjdG9yID0gY2FudmFzSGVpZ2h0IC8gaGVpZ2h0O1xuICAgIH1cblxuICAgIHRoaXMuc2V0Q2FudmFzU2l6ZSh3aWR0aCAqIHNjYWxlRmFjdG9yLCBoZWlnaHQgKiBzY2FsZUZhY3Rvcik7XG5cbiAgICB0aGlzLmNhbnZhcy5iYWNrZ3JvdW5kSW1hZ2Uuc2NhbGVYICo9IHNjYWxlRmFjdG9yO1xuICAgIHRoaXMuY2FudmFzLmJhY2tncm91bmRJbWFnZS5zY2FsZVkgKj0gc2NhbGVGYWN0b3I7XG5cbiAgICB0aGlzLmNhbnZhcy5iYWNrZ3JvdW5kSW1hZ2UubGVmdCAtPSBsZWZ0O1xuICAgIHRoaXMuY2FudmFzLmJhY2tncm91bmRJbWFnZS5sZWZ0ICo9IHNjYWxlRmFjdG9yO1xuICAgIHRoaXMuY2FudmFzLmJhY2tncm91bmRJbWFnZS50b3AgLT0gdG9wIC0gc2NhbGVGYWN0b3I7XG4gICAgdGhpcy5jYW52YXMuYmFja2dyb3VuZEltYWdlLnRvcCAqPSBzY2FsZUZhY3RvcjtcblxuICAgIHRoaXMubW92ZUFsbE9iamVjdHNJbkNhbnZhcygtMSAqIGxlZnQsIC0xICogdG9wLCBzY2FsZUZhY3Rvcik7XG5cbiAgICB0aGlzLmVuYWJsZVNsZWN0aW9uKCk7XG4gICAgdGhpcy5jcm9wUmVjdGFuZ2xlLnZpc2libGUgPSBmYWxzZTtcblxuICAgIHRoaXMuY2FudmFzLnJlbW92ZSh0aGlzLmNyb3BSZWN0YW5nbGUpO1xuXG4gICAgdGhpcy5jYW52YXMucmVuZGVyQWxsKCk7XG4gIH1cblxuICBwdWJsaWMgZW5hYmxlU2xlY3Rpb24oKSB7XG4gICAgdGhpcy5jYW52YXMuc2VsZWN0YWJsZSA9IHRydWU7XG4gICAgdGhpcy5jYW52YXMuc2VsZWN0aW9uID0gdHJ1ZTtcbiAgfVxuXG4gIHB1YmxpYyBhanVzdENyb3BSZWN0YW5nbGUoZXZlbnQpOiBib29sZWFuIHtcbiAgICBjb25zdCB0b3VjaCA9IGV2ZW50LnRvdWNoZXNbMF07XG5cbiAgICBjb25zdCByZWN0ID0gZXZlbnQudGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgY29uc3QgeCA9IE1hdGgubWluKHRvdWNoLmNsaWVudFggLSByZWN0LmxlZnQsIHRoaXMubW91c2VQb3NpdGlvbi54KSxcbiAgICAgIHkgPSBNYXRoLm1pbih0b3VjaC5jbGllbnRZIC0gcmVjdC50b3AsIHRoaXMubW91c2VQb3NpdGlvbi55KSxcbiAgICAgIHcgPSBNYXRoLmFicyh0b3VjaC5jbGllbnRYIC0gcmVjdC5sZWZ0IC0gdGhpcy5tb3VzZVBvc2l0aW9uLngpLFxuICAgICAgaCA9IE1hdGguYWJzKHRvdWNoLmNsaWVudFkgLSByZWN0LnRvcCAtIHRoaXMubW91c2VQb3NpdGlvbi55KTtcblxuICAgIGlmICghdyB8fCAhaCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMuY3JvcFJlY3RhbmdsZVxuICAgICAgLnNldCgnbGVmdCcsIHgpXG4gICAgICAuc2V0KCd0b3AnLCB5KVxuICAgICAgLnNldCgnd2lkdGgnLCB3KVxuICAgICAgLnNldCgnaGVpZ2h0JywgaCk7XG5cbiAgICB0aGlzLmNhbnZhcy5yZW5kZXJBbGwoKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHVibGljIHN0YXJ0U2VsZWN0aW5nQ3JvcFJlY3RhbmdsZShldmVudCk6IHZvaWQge1xuICAgIHRoaXMuY3JvcFN0YXJ0aW5nUG9zaXRpb24gPSB7IHg6IHRoaXMuY2FudmFzLmxlZnQsIHk6IHRoaXMuY2FudmFzLnRvcCB9O1xuXG4gICAgY29uc3QgdG91Y2ggPSBldmVudC50b3VjaGVzWzBdO1xuICAgIGNvbnN0IHJlY3QgPSBldmVudC50YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICB0aGlzLmNyb3BSZWN0YW5nbGUubGVmdCA9IHRvdWNoLmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgdGhpcy5jcm9wUmVjdGFuZ2xlLnRvcCA9IHRvdWNoLmNsaWVudFkgLSByZWN0LnRvcDtcbiAgICB0aGlzLmNyb3BSZWN0YW5nbGUuc2V0Q29vcmRzKCk7XG5cbiAgICB0aGlzLm1vdXNlUG9zaXRpb24gPSB7IHg6IHRvdWNoLmNsaWVudFggLSByZWN0LmxlZnQsIHk6IHRvdWNoLmNsaWVudFkgLSByZWN0LnRvcCB9O1xuXG4gICAgdGhpcy5jYW52YXMucmVuZGVyQWxsKCk7XG4gICAgdGhpcy5jcm9wUmVjdGFuZ2xlLnZpc2libGUgPSB0cnVlO1xuICAgIHRoaXMuY2FudmFzLmJyaW5nVG9Gcm9udCh0aGlzLmNyb3BSZWN0YW5nbGUpO1xuICB9XG5cbiAgcHVibGljIGRpc2FibGVTZWxlY3Rpb24oKSB7XG4gICAgdGhpcy5jYW52YXMuc2VsZWN0aW9uID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIG1vdmVBbGxPYmplY3RzSW5DYW52YXMoeDogbnVtYmVyLCB5OiBudW1iZXIsIHNjYWxlRmFjdG9yOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBvYmplY3RzID0gdGhpcy5jYW52YXMuZ2V0T2JqZWN0cygpO1xuICAgIGZvciAoY29uc3Qgb2JqIG9mIG9iamVjdHMpIHtcbiAgICAgIG9iai5sZWZ0ICs9IHg7XG4gICAgICBvYmoubGVmdCAqPSBzY2FsZUZhY3RvcjtcbiAgICAgIG9iai5zY2FsZVggKj0gc2NhbGVGYWN0b3I7XG4gICAgICBvYmoudG9wICs9IHk7XG4gICAgICBvYmouc2NhbGVZICo9IHNjYWxlRmFjdG9yO1xuICAgICAgb2JqLnRvcCAqPSBzY2FsZUZhY3RvcjtcbiAgICAgIG9iai5zZXRDb29yZHMoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ3JvdXBTZWxlY3RlZE9iamVjdHMoKTogdm9pZCB7XG4gICAgY29uc3QgYWN0aXZlT2JqZWN0cyA9IHRoaXMuY2FudmFzLmdldEFjdGl2ZU9iamVjdHMoKTtcblxuICAgIGlmIChhY3RpdmVPYmplY3RzKSB7XG4gICAgICBjb25zdCBvYmplY3RzID0gW107XG5cbiAgICAgIGZvciAoY29uc3Qgb2JqZWN0IG9mIGFjdGl2ZU9iamVjdHMpIHtcbiAgICAgICAgb2JqZWN0cy5wdXNoKG9iamVjdCk7XG4gICAgICB9XG4gICAgICB0aGlzLmRlbGV0ZVNlbGVjdGVkT2JqZWN0cygpO1xuXG4gICAgICBjb25zdCBncm91cCA9IG5ldyBmYWJyaWMuR3JvdXAob2JqZWN0cyk7XG4gICAgICB0aGlzLmNhbnZhcy5hZGQoZ3JvdXApO1xuICAgICAgZ3JvdXAuc2V0Q29vcmRzKCk7XG5cbiAgICAgIHRoaXMuY2FudmFzLnNldEFjdGl2ZU9iamVjdChncm91cCk7XG5cbiAgICAgIHRoaXMuY2FudmFzLnJlbmRlckFsbCgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBzZXRMYXN0UGFuUG9zaXRpb24oZXZlbnQpIHtcbiAgICB0aGlzLmxhc3RQYW5Qb3NpdGlvbiA9IG5ldyBmYWJyaWMuUG9pbnQoZXZlbnQudG91Y2hlc1swXS5jbGllbnRYLCBldmVudC50b3VjaGVzWzBdLmNsaWVudFkpO1xuICB9XG5cbiAgcHVibGljIHBhbkNhbnZhcyhldmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGRlbHRhID0gbmV3IGZhYnJpYy5Qb2ludChcbiAgICAgIGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WCAtIHRoaXMubGFzdFBhblBvc2l0aW9uLngsXG4gICAgICBldmVudC50b3VjaGVzWzBdLmNsaWVudFkgLSB0aGlzLmxhc3RQYW5Qb3NpdGlvbi55XG4gICAgKTtcblxuICAgIHRoaXMuY2FudmFzLnJlbGF0aXZlUGFuKGRlbHRhKTtcbiAgICB0aGlzLnByZXZlbnRQYW5PdXRzaWRlQ2FudmFzKCk7XG5cbiAgICB0aGlzLmNhbnZhcy5yZW5kZXJBbGwoKTtcbiAgICB0aGlzLnNldExhc3RQYW5Qb3NpdGlvbihldmVudCk7XG4gIH1cblxuICBwcml2YXRlIHByZXZlbnRQYW5PdXRzaWRlQ2FudmFzKCkge1xuICAgIGNvbnN0IGNhbnZhc1ZpZXdQb3J0ID0gdGhpcy5jYW52YXMudmlld3BvcnRUcmFuc2Zvcm07XG5cbiAgICBjb25zdCBib3R0b21FbmRQb2ludCA9IHRoaXMuY2FudmFzLmhlaWdodCAqIChjYW52YXNWaWV3UG9ydFswXSAtIDEpO1xuICAgIGlmIChjYW52YXNWaWV3UG9ydFs1XSA+PSAwIHx8IC1ib3R0b21FbmRQb2ludCA+IGNhbnZhc1ZpZXdQb3J0WzVdKSB7XG4gICAgICAgIGNhbnZhc1ZpZXdQb3J0WzVdID0gKGNhbnZhc1ZpZXdQb3J0WzVdID49IDApID8gMCA6IC1ib3R0b21FbmRQb2ludDtcbiAgICB9XG5cbiAgICBjb25zdCByaWdodEVuZFBvaW50ID0gdGhpcy5jYW52YXMud2lkdGggKiAoY2FudmFzVmlld1BvcnRbMF0gLSAxKTtcbiAgICBpZiAoY2FudmFzVmlld1BvcnRbNF0gPj0gMCB8fCAtcmlnaHRFbmRQb2ludCA+IGNhbnZhc1ZpZXdQb3J0WzRdKSB7XG4gICAgICAgIGNhbnZhc1ZpZXdQb3J0WzRdID0gKGNhbnZhc1ZpZXdQb3J0WzRdID49IDApID8gMCA6IC1yaWdodEVuZFBvaW50O1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyB6b29tKGV2ZW50KTogdm9pZCB7XG4gICAgaWYgKE1hdGguYWJzKGV2ZW50Lm92ZXJhbGxWZWxvY2l0eSkgPiAwLjAwNSkge1xuICAgICAgY29uc3QgcG9pbnQgPSBuZXcgZmFicmljLlBvaW50KGV2ZW50LmNlbnRlci54LCBldmVudC5jZW50ZXIueSk7XG5cbiAgICAgIGxldCB6b29tID0gdGhpcy5jYW52YXMuZ2V0Wm9vbSgpO1xuICAgICAgem9vbSA9IHpvb20gKyAoZXZlbnQuc2NhbGUgLSB6b29tKSAvIDIwO1xuXG5cbiAgICAgIGlmICh6b29tIDwgMSkge1xuICAgICAgICB6b29tID0gMTtcbiAgICAgICAgdGhpcy5jYW52YXMuem9vbVRvUG9pbnQobmV3IGZhYnJpYy5Qb2ludCgwLCAwKSwgem9vbSk7XG4gICAgICAgIHRoaXMuY2FudmFzLmFic29sdXRlUGFuKG5ldyBmYWJyaWMuUG9pbnQoMCwgMCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHpvb20gPiAxMCkge1xuICAgICAgICAgIHpvb20gPSAxMDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbnZhcy56b29tVG9Qb2ludChwb2ludCwgem9vbSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2V0RnJlZURyYXdpbmdCcnVzaFdpZHRoRnJvbVpvb20oem9vbSk7XG4gICAgICB0aGlzLmNhbnZhcy5yZW5kZXJBbGwoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldENhbnZhc1NpemUod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICB0aGlzLmNhbnZhcy5zZXRXaWR0aCh3aWR0aCk7XG4gICAgdGhpcy5jYW52YXMuc2V0SGVpZ2h0KGhlaWdodCk7XG4gIH1cblxuICBwdWJsaWMgcmVzZXRab29tKCkge1xuICAgIHRoaXMuY2FudmFzLnpvb21Ub1BvaW50KG5ldyBmYWJyaWMuUG9pbnQoMCwgMCksIDEpO1xuICAgIHRoaXMuY2FudmFzLmFic29sdXRlUGFuKG5ldyBmYWJyaWMuUG9pbnQoMCwgMCkpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIEhvc3RMaXN0ZW5lciwgT3V0cHV0LCBPbkNoYW5nZXMsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZm9yRWFjaCB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlci9zcmMvdXRpbHMvY29sbGVjdGlvbic7XG5pbXBvcnQgeyBDYW52YXNNYW5hZ2VyU2VydmljZSB9IGZyb20gJy4vLi4vc2VydmljZXMvY2FudmFzLW1hbmFnZXIuc2VydmljZSc7XG5pbXBvcnQgeyBBdmFpbGFibGVHZW9tZXRyaWNTaGFwZSB9IGZyb20gJy4vLi4vY29uc3RhbnRzL2F2YWlsYWJsZS1nZW9tZXRyaWMtc2hhcGVzJztcbmltcG9ydCB7IEtFWV9DT0RFIH0gZnJvbSAnLi8uLi9jb25zdGFudHMva2V5LWNvZGUnO1xuaW1wb3J0IHsgZmFicmljIH0gZnJvbSAnZmFicmljJztcblxuY29uc3QgQmxhY2sgPSAnIzAwMDAwMCc7XG5jb25zdCBUcmFuc3BhcmVudCA9ICd0cmFuc3BhcmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi13ZWItc2tldGNoLXRvb2wnLFxuICB0ZW1wbGF0ZTogYDxkaXZcbiAgICBjbGFzcz1cImRpdi1jYW52YXMtY29udGFpbmVyXCJcbiAgICAobW91c2Vkb3duKT1cIm1vdXNlRG93bigkZXZlbnQpXCJcbiAgICAobW91c2Vtb3ZlKT1cIm1vdXNlTW92ZSgkZXZlbnQpXCJcbiAgICAobW91c2V1cCk9XCJtb3VzZVVwKCRldmVudClcIlxuPlxuICAgIDxjYW52YXMgaWQ9XCJjYW52YXNcIj48L2NhbnZhcz5cbjwvZGl2PlxuXG48bWF0LXRvb2xiYXIgY2xhc3M9XCJlZGl0LXRvb2xiYXJcIj5cbiAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgY2xhc3M9XCJ0b29sLWJ1dHRvblwiXG4gICAgICAgIChjbGljayk9XCJhZGRTaGFwZSgnUmVjdGFuZ2xlJylcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNEcmF3aW5nXCJcbiAgICA+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNxdWFyZVwiPjwvaT5cbiAgICA8L2J1dHRvbj5cblxuICAgIDxidXR0b25cbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICBjbGFzcz1cInRvb2wtYnV0dG9uXCJcbiAgICAgICAgKGNsaWNrKT1cImFkZFNoYXBlKCdDaXJjbGUnKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0RyYXdpbmdcIlxuICAgID5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2lyY2xlXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgPGJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIGNsYXNzPVwidG9vbC1idXR0b25cIlxuICAgICAgICAoY2xpY2spPVwiYWRkU2hhcGUoJ1RyaWFuZ2xlJylcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNEcmF3aW5nXCJcbiAgICA+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNhcmV0LXVwXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgPGJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIGNsYXNzPVwidG9vbC1idXR0b25cIlxuICAgICAgICAoY2xpY2spPVwiYWRkU2hhcGUoJ0xpbmUnKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0RyYXdpbmdcIlxuICAgID5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbWludXNcIj48L2k+XG4gICAgPC9idXR0b24+XG5cbiAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgY2xhc3M9XCJ0b29sLWJ1dHRvblwiXG4gICAgICAgIChjbGljayk9XCJhZGRUZXh0KClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNEcmF3aW5nXCJcbiAgICA+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWZvbnRcIj48L2k+XG4gICAgPC9idXR0b24+XG5cbiAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgY2xhc3M9XCJ0b29sLWJ1dHRvblwiXG4gICAgICAgIGNvbG9yPVwiYWNjZW50XCJcbiAgICAgICAgKGNsaWNrKT1cImNyb3AoKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0RyYXdpbmdcIlxuICAgID5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY3JvcFwiPjwvaT5cbiAgICA8L2J1dHRvbj5cblxuICAgIDxidXR0b25cbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAoY2xpY2spPVwiZHJhdygpXCJcbiAgICAgICAgY2xhc3M9XCJ0b29sLWJ1dHRvblwiXG4gICAgPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1wZW5jaWwtYWx0XCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgPGJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIGNsYXNzPVwidG9vbC1idXR0b25cIlxuICAgICAgICAoY2xpY2spPVwiZ3JvdXAoKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0RyYXdpbmdcIlxuICAgID5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtb2JqZWN0LWdyb3VwXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgPGJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIGNsYXNzPVwidG9vbC1idXR0b25cIlxuICAgICAgICBjb2xvcj1cImFjY2VudFwiXG4gICAgICAgIChjbGljayk9XCJicmluZ0Zvd2FyZCgpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImlzRHJhd2luZ1wiXG4gICAgPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1hbmdsZS11cFwiPjwvaT5cbiAgICA8L2J1dHRvbj5cblxuICAgIDxidXR0b25cbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICBjbGFzcz1cInRvb2wtYnV0dG9uXCJcbiAgICAgICAgY29sb3I9XCJhY2NlbnRcIlxuICAgICAgICAoY2xpY2spPVwic2VuZFRvQmFjaygpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImlzRHJhd2luZ1wiXG4gICAgPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1hbmdsZS1kb3duXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgPGJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIGNsYXNzPVwidG9vbC1idXR0b25cIlxuICAgICAgICAoY2xpY2spPVwiZGVsZXRlU2VsZWN0aW9uKClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiaXNEcmF3aW5nXCJcbiAgICA+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXRyYXNoXCI+PC9pPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgPGJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIChjbGljayk9XCJzYXZlSW1hZ2UoKVwiXG4gICAgICAgIGNsYXNzPVwidG9vbC1idXR0b25cIlxuICAgID5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZG93bmxvYWRcIj48L2k+XG4gICAgPC9idXR0b24+XG5cbiAgICA8aW5wdXRcbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICBjbGFzcz1cImNvbG9yUGlja2VyXCJcbiAgICAgICAgWyhjb2xvclBpY2tlcildPVwic3Ryb2tlQ29sb3JcIlxuICAgICAgICBbc3R5bGUuYmFja2dyb3VuZF09XCJzdHJva2VDb2xvclwiXG4gICAgICAgIChjb2xvclBpY2tlckNoYW5nZSk9XCJjaGFuZ2VTdHJva2VDb2xvcigpXCJcbiAgICA+XG48L21hdC10b29sYmFyPlxuYCxcbiAgc3R5bGVzOiBbYC5kaXYtY2FudmFzLWNvbnRhaW5lcnt0ZXh0LWFsaWduOmNlbnRlcjttYXJnaW46MCBhdXRvO3BhZGRpbmc6MDtoZWlnaHQ6OTAlIWltcG9ydGFudDt3aWR0aDoxMDAlIWltcG9ydGFudDstby1vYmplY3QtZml0OmNvbnRhaW47b2JqZWN0LWZpdDpjb250YWlufS5lZGl0LXRvb2xiYXJ7aGVpZ2h0OjclO2p1c3RpZnktY29udGVudDpjZW50ZXJ9LnRvb2xiYXItYnV0dG9ue2ZvbnQtZmFtaWx5OkZvbnRBd2Vzb21lO2Rpc3BsYXk6aW5saW5lLWJsb2NrO3dpZHRoOjEuNWVtO21pbi13aWR0aDowfS5tYXQtYnV0dG9uLnRvb2wtYnV0dG9ue21pbi13aWR0aDo0MHB4IWltcG9ydGFudDt3aWR0aDo1MHB4O21pbi1oZWlnaHQ6NDBweCFpbXBvcnRhbnQ7aGVpZ2h0OjQwcHg7bWFyZ2luLXJpZ2h0OjEwcHh9LmNvbG9yUGlja2Vye3dpZHRoOjQwcHg7aGVpZ2h0OjM2cHg7bWFyZ2luLXRvcDozcHg7Y29sb3I6dHJhbnNwYXJlbnR9aXtmb250LXNpemU6MS41ZW07Y29sb3I6IzAwMH1gXSxcbiAgcHJvdmlkZXJzOiBbQ2FudmFzTWFuYWdlclNlcnZpY2VdXG59KVxuXG5leHBvcnQgY2xhc3MgV2ViU2tldGNoVG9vbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgcHVibGljIGZpbGxDb2xvcjogc3RyaW5nO1xuICBwdWJsaWMgc3Ryb2tlQ29sb3I6IHN0cmluZztcblxuICBwdWJsaWMgYXZhaWxhYmxlR2VvbWV0cmljU2hhcGVzID0gQXZhaWxhYmxlR2VvbWV0cmljU2hhcGU7XG4gIHB1YmxpYyBpc0RyYXdpbmc6IGJvb2xlYW47XG4gIHB1YmxpYyBpc0Nyb3BwaW5nOiBib29sZWFuO1xuICBwdWJsaWMgaXNMYXN0SW1hZ2U6IGJvb2xlYW47XG5cbiAgcHJpdmF0ZSBpc0xvYWRlZDogYm9vbGVhbjtcbiAgcHJpdmF0ZSBwcmV2aW91c0ltYWdlRGF0YTogc3RyaW5nO1xuXG4gIEBJbnB1dCgpIHB1YmxpYyBpbWFnZURhdGE6IHN0cmluZztcbiAgQElucHV0KCkgcHVibGljIGxvYWRlZEpzb246IHN0cmluZztcblxuICBAT3V0cHV0KCkgcHVibGljIGNhbnZhcyA9IG5ldyBFdmVudEVtaXR0ZXI8ZmFicmljLkNhbnZhcz4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNhbnZhc01hbmFnZXJTZXJ2aWNlOiBDYW52YXNNYW5hZ2VyU2VydmljZSkge1xuICAgIHRoaXMuc3Ryb2tlQ29sb3IgPSBCbGFjaztcbiAgICB0aGlzLmZpbGxDb2xvciA9IFRyYW5zcGFyZW50O1xuICAgIHRoaXMuaXNDcm9wcGluZyA9IGZhbHNlO1xuICAgIHRoaXMuaXNMb2FkZWQgPSBmYWxzZTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuc2V0Q2FudmFzKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcygpIHtcbiAgICAgIHRoaXMuc2V0Q2FudmFzKCk7XG4gIH1cblxuICBwcml2YXRlIHNldENhbnZhcygpIHtcbiAgICBpZiAodGhpcy5pbWFnZURhdGEpIHtcbiAgICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuZW1wdHlDYW52YXMoKTtcbiAgICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UucmVzZXRab29tKCk7XG4gICAgICBpZiAodGhpcy5sb2FkZWRKc29uID09IG51bGwgfHwgdGhpcy5sb2FkZWRKc29uLmxlbmd0aCA8IDEwKSB7XG4gICAgICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2Uuc2V0QmFja2dyb3VuZEZyb21VUkwodGhpcy5pbWFnZURhdGEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLmxvYWRmcm9tSnNvbihKU09OLnBhcnNlKHRoaXMubG9hZGVkSnNvbikpO1xuICAgICAgfVxuICAgICAgdGhpcy5pc0xvYWRlZCA9IHRydWU7XG4gICAgICB0aGlzLnByZXZpb3VzSW1hZ2VEYXRhID0gdGhpcy5pbWFnZURhdGE7XG4gICAgICB0aGlzLmVtaXRDYW52YXMoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYWRkVGV4dCgpIHtcbiAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLmFkZFRleHQodGhpcy5zdHJva2VDb2xvciwgJyAnKTtcbiAgICB0aGlzLmVtaXRDYW52YXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRTaGFwZShzaGFwZTogc3RyaW5nKSB7XG4gICAgdGhpcy5jYW52YXNNYW5hZ2VyU2VydmljZS5hZGRHZW9tZXRyaWNTaGFwZShcbiAgICAgIHRoaXMuc3Ryb2tlQ29sb3IsXG4gICAgICB0aGlzLmZpbGxDb2xvcixcbiAgICAgIEF2YWlsYWJsZUdlb21ldHJpY1NoYXBlW3NoYXBlXVxuICAgICk7XG4gICAgdGhpcy5lbWl0Q2FudmFzKCk7XG4gIH1cblxuICBwdWJsaWMgY2hhbmdlU3Ryb2tlQ29sb3IoKSB7XG4gICAgdGhpcy5jYW52YXNNYW5hZ2VyU2VydmljZS5jaGFuZ2VTZWxlY3RlZE9iamVjdHNTdHJva2VDb2xvcihcbiAgICAgIHRoaXMuc3Ryb2tlQ29sb3JcbiAgICApO1xuICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2Uuc2V0RnJlZURyYXdpbmdCcnVzaENvbG9yKHRoaXMuc3Ryb2tlQ29sb3IpO1xuICAgIHRoaXMuZW1pdENhbnZhcygpO1xuICB9XG5cbiAgcHVibGljIGJyaW5nRm93YXJkKCkge1xuICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuYnJpbmdTZWxlY3RlZE9iamVjdHNUb0Zyb250KCk7XG4gICAgdGhpcy5lbWl0Q2FudmFzKCk7XG4gIH1cblxuICBwdWJsaWMgc2VuZFRvQmFjaygpIHtcbiAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLnNlbmRTZWxlY3RlZE9iamVjdHNUb0JhY2soKTtcbiAgICB0aGlzLmVtaXRDYW52YXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBkcmF3KCkge1xuICAgIHRoaXMuaXNEcmF3aW5nID0gIXRoaXMuaXNEcmF3aW5nO1xuICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UudG9nZ2xlRnJlZURyYXdpbmcoKTtcbiAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLnNldEZyZWVEcmF3aW5nQnJ1c2hDb2xvcih0aGlzLnN0cm9rZUNvbG9yKTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlSW1hZ2UoKSB7XG4gICAgY29uc3QgZGF0YVVSTCA9IHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuZXhwb3J0SW1hZ2VBc0RhdGFVUkwoKTtcblxuICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgbGluay5kb3dubG9hZCA9ICdpbWFnZSc7XG5cbiAgICBsaW5rLmhyZWYgPSBkYXRhVVJMO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobGluayk7XG4gICAgbGluay5jbGljaygpO1xuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQobGluayk7XG4gIH1cblxuICBwdWJsaWMgY3JvcCgpIHtcbiAgICB0aGlzLmlzQ3JvcHBpbmcgPSB0cnVlO1xuICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuZGlzYWJsZVNlbGVjdGlvbigpO1xuICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuYWRkU2VsZWN0aW9uUmVjdGFuZ2xlKCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6a2V5dXAnLCBbJyRldmVudCddKVxuICBrZXlFdmVudChldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIGlmIChldmVudC5rZXlDb2RlID09PSBLRVlfQ09ERS5ERUxFVEUpIHtcbiAgICAgIHRoaXMuZGVsZXRlU2VsZWN0aW9uKCk7XG4gICAgfVxuICAgIHRoaXMuZW1pdENhbnZhcygpO1xuICB9XG5cbiAgcHVibGljIGRlbGV0ZVNlbGVjdGlvbigpIHtcbiAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLmRlbGV0ZVNlbGVjdGVkT2JqZWN0cygpO1xuICAgIHRoaXMuZW1pdENhbnZhcygpO1xuICB9XG5cbiAgcHVibGljIG1vdXNlVXAoZXZlbnQpIHtcbiAgICBpZiAodGhpcy5pc0Nyb3BwaW5nKSB7XG4gICAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLmNyb3BJbWFnZSgpO1xuICAgICAgdGhpcy5pc0Nyb3BwaW5nID0gZmFsc2U7XG4gICAgfVxuICAgIHRoaXMuZW1pdENhbnZhcygpO1xuICB9XG5cbiAgcHVibGljIG1vdXNlTW92ZShldmVudDogTW91c2VFdmVudCkge1xuICAgIGlmICh0aGlzLmlzQ3JvcHBpbmcpIHtcbiAgICAgIHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuYWp1c3RDcm9wUmVjdGFuZ2xlRnJvbU1vdXNlKGV2ZW50KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgbW91c2VEb3duKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgaWYgKHRoaXMuaXNDcm9wcGluZykge1xuICAgICAgdGhpcy5jYW52YXNNYW5hZ2VyU2VydmljZS5zdGFydFNlbGVjdGluZ0Nyb3BSZWN0YW5nbGVGcm9tTW91c2UoZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBncm91cCgpIHtcbiAgICB0aGlzLmNhbnZhc01hbmFnZXJTZXJ2aWNlLmdyb3VwU2VsZWN0ZWRPYmplY3RzKCk7XG4gICAgdGhpcy5lbWl0Q2FudmFzKCk7XG4gIH1cblxuICBwdWJsaWMgZW1pdENhbnZhcygpIHtcbiAgICB0aGlzLmNhbnZhcy5lbWl0KHRoaXMuY2FudmFzTWFuYWdlclNlcnZpY2UuY2FudmFzKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBNYXRUb29sYmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbGJhcic7XG5pbXBvcnQgeyBDb2xvclBpY2tlck1vZHVsZSB9IGZyb20gJ25neC1jb2xvci1waWNrZXInO1xuaW1wb3J0IHsgTWF0QnV0dG9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwnO1xuXG5pbXBvcnQgeyBXZWJTa2V0Y2hUb29sQ29tcG9uZW50IH0gZnJvbSAnLi93ZWItY29tcG9uZW50L3dlYi1za2V0Y2gtdG9vbC5jb21wb25lbnQnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBDb2xvclBpY2tlck1vZHVsZSwgTWF0QnV0dG9uTW9kdWxlLCBNYXRUb29sYmFyTW9kdWxlXSxcbiAgZGVjbGFyYXRpb25zOiBbV2ViU2tldGNoVG9vbENvbXBvbmVudF0sXG4gIGV4cG9ydHM6IFtXZWJTa2V0Y2hUb29sQ29tcG9uZW50XVxufSlcbmV4cG9ydCBjbGFzcyBXZWJTa2V0Y2hUb29sTW9kdWxlIHt9XG4iXSwibmFtZXMiOlsidHNsaWJfMS5fX3ZhbHVlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsQUFBTyxxQkFBTSxVQUFVLEdBQUc7SUFDeEIsS0FBSyxFQUFFLEdBQUc7SUFDVixNQUFNLEVBQUUsR0FBRztJQUNYLElBQUksRUFBRSxFQUFFO0lBQ1IsR0FBRyxFQUFFLEVBQUU7SUFDUCxNQUFNLEVBQUUsR0FBRztJQUNYLE1BQU0sRUFBRSxFQUFFO0lBQ1YscUJBQXFCLEVBQUUsRUFBRTtJQUN6QixVQUFVLEVBQUUsRUFBRTtDQUNmLENBQUM7Ozs7Ozs7SUNpQkE7UUFDRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxFQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxDQUFDO0tBQzFDO0lBRUQsc0JBQUksK0NBQWE7Ozs7UUFBakI7WUFDRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDakM7OztPQUFBO0lBRUQsc0JBQUksdURBQXFCOzs7O1FBQXpCO1lBQ0UsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQztTQUNwQzs7O09BQUE7SUFFRCxzQkFBSSw4Q0FBWTs7OztRQUFoQjtZQUNFLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsQ0FBQztTQUN0Qzs7O09BQUE7SUFF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
\No newline at end of file