@sumaris-net/ngx-components 18.25.5 → 18.25.6

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.
@@ -1,7 +1,6 @@
1
1
  import { booleanAttribute, ChangeDetectionStrategy, Component, EventEmitter, inject, Inject, Input, Optional, Output, ViewChild, } from '@angular/core';
2
2
  import { BehaviorSubject, Subject, Subscription } from 'rxjs';
3
3
  import { ENVIRONMENT } from '../../../../environments/environment.class';
4
- import { IonicSlides } from '@ionic/angular';
5
4
  import { isMobile } from '../../platforms';
6
5
  import { fadeInAnimation, fadeInOutAnimation } from '../../material/material.animations';
7
6
  import { isEmptyArray, isNilOrBlank, toBoolean } from '../../functions';
@@ -25,8 +24,8 @@ import * as i10 from "@angular/cdk/a11y";
25
24
  import * as i11 from "@angular/material/tooltip";
26
25
  import * as i12 from "../../directives/autofocus.directive";
27
26
  import * as i13 from "@rx-angular/template/for";
28
- import * as i14 from "../../pipes/property.pipes";
29
- import * as i15 from "../../pipes/arrays.pipe";
27
+ import * as i14 from "./slideshow/image-gallery-slideshow.component";
28
+ import * as i15 from "../../pipes/property.pipes";
30
29
  import * as i16 from "../../pipes/string.pipes";
31
30
  import * as i17 from "../../pipes/url.pipes";
32
31
  import * as i18 from "../../../../environments/environment.class";
@@ -51,10 +50,13 @@ export class AppImageGalleryComponent {
51
50
  _titleForm;
52
51
  _titleAutofocus = false;
53
52
  _slidesSubscription;
54
- _swiper;
55
- swiperModules = [IonicSlides];
56
53
  zoomActive = false;
57
54
  zoomScale = 1;
55
+ _mouseZoomEnabled = false;
56
+ _rotationEnabled = false;
57
+ _cropEnabled = false;
58
+ /** Whether the inline slideshow overlay is currently shown (only relevant when zoomPresentation === 'inline'). */
59
+ _inlineSlideshowActive = false;
58
60
  viewChange;
59
61
  cardColor;
60
62
  debug = null;
@@ -79,6 +81,24 @@ export class AppImageGalleryComponent {
79
81
  modal: 'large',
80
82
  };
81
83
  imageSizeQueryParam = 'size';
84
+ /** Enable mouse-wheel zoom and mouse-drag pan in the slideshow (defaults to true on desktop). */
85
+ enableMouseZoom = null;
86
+ /** Zoom step applied on each mouse-wheel tick (default 0.3). */
87
+ wheelZoomStep = 0.3;
88
+ /** Maximum zoom ratio reachable via mouse wheel (default 3). */
89
+ maxZoomRatio = 3;
90
+ /** Enable 90° rotation buttons in the slideshow (defaults to true). */
91
+ enableRotation = null;
92
+ /** Enable the crop tool in the slideshow (defaults to true). */
93
+ enableCrop = null;
94
+ /** Image format used when emitting the edited (cropped/rotated) image. */
95
+ imageExportFormat = 'png';
96
+ /** Export quality, applied only when imageExportFormat is 'jpeg' (0 to 1). */
97
+ imageExportQuality = 0.92;
98
+ /** Where to show the slideshow: in a full-screen modal (default), or inline, as an overlay over the gallery itself (desktop only). */
99
+ zoomPresentation = 'inline';
100
+ /** Height of the inline slideshow overlay (CSS value, e.g. '60vh'). Only used when zoomPresentation is 'inline'. */
101
+ inlineZoomHeight = '60vh';
82
102
  set dataSource(dataSource) {
83
103
  if (this._dataSource !== dataSource) {
84
104
  this._switchDataSource(dataSource);
@@ -96,15 +116,12 @@ export class AppImageGalleryComponent {
96
116
  get rowCount() {
97
117
  return this.rows?.length || 0;
98
118
  }
99
- get activeIndex() {
100
- return this.getSwiper()?.activeIndex || 0;
101
- }
102
119
  zoomModal;
103
120
  titlePopover;
104
- swiperRef;
105
121
  onBeforeDeleteRows = createPromiseEventEmitter();
106
122
  onAfterAddRows = new EventEmitter();
107
123
  onAfterEditRow = new EventEmitter();
124
+ onAfterEditImage = new EventEmitter();
108
125
  click = new EventEmitter();
109
126
  showTooltip = inject(APP_SHOW_TOOLTIP, { optional: true });
110
127
  constructor(imageService, platform, alterCtrl, translate, cd, environment) {
@@ -126,6 +143,13 @@ export class AppImageGalleryComponent {
126
143
  this.showAddCardButton = toBoolean(this.showAddCardButton, this.mobile);
127
144
  this.showFabButton = toBoolean(this.showFabButton, this.mobile && !this.showAddCardButton);
128
145
  this.showAddToolbarButton = this.showAddToolbarButton ?? (this.showToolbar && !this.readOnly);
146
+ this._mouseZoomEnabled = toBoolean(this.enableMouseZoom, !this.mobile);
147
+ this._rotationEnabled = toBoolean(this.enableRotation, true);
148
+ this._cropEnabled = toBoolean(this.enableCrop, true);
149
+ // The inline presentation is only meaningful on desktop: there is no "rest of the page" worth
150
+ // preserving on a small mobile screen, and the fullscreen modal already works well there.
151
+ if (this.mobile)
152
+ this.zoomPresentation = 'modal';
129
153
  // Get modal presenting element (iOS only)
130
154
  this._presentingElement = this.mobile ? document.querySelector('.ion-page') : null;
131
155
  }
@@ -256,82 +280,38 @@ export class AppImageGalleryComponent {
256
280
  // Delegate click action
257
281
  if (this.click.observed) {
258
282
  this.click.emit(row.currentData);
283
+ return;
284
+ }
285
+ // By default, open the slideshow: either inline (overlay in the gallery itself), or in a full-screen modal
286
+ this._selectedRowIndex = index;
287
+ if (this.zoomPresentation === 'inline') {
288
+ this._inlineSlideshowActive = true;
289
+ this.markForCheck();
259
290
  }
260
- // By default, open a zoom modal
261
291
  else {
262
- this._selectedRowIndex = index;
263
292
  await this.zoomModal.present();
264
293
  await this.zoomModal.onDidDismiss();
265
294
  }
266
295
  }
267
- activeSlideIndex = 0;
268
- getSwiper(swiperElement) {
269
- this._swiper = (swiperElement || this.swiperRef?.nativeElement)?.swiper || this._swiper;
270
- return this._swiper;
271
- }
272
- onSlideChange(swiperElement) {
273
- const swiper = this.getSwiper(swiperElement);
274
- this.activeSlideIndex = swiper.activeIndex;
296
+ closeInlineSlideshow() {
297
+ this._inlineSlideshowActive = false;
275
298
  this.markForCheck();
276
299
  }
277
- initModalSlides(swiperElement) {
278
- if (this._selectedRowIndex > 0) {
279
- if (this.debug)
280
- console.debug(`[image-gallery] Initializing modal, selectedRowIndex=${this._selectedRowIndex}`);
281
- // Use a setTimeout otherwise the swiper cannot slide
282
- setTimeout(() => {
283
- const swiper = this.getSwiper(swiperElement);
284
- swiper.slideTo(this._selectedRowIndex, 0);
285
- });
286
- }
287
- }
288
- async zoom(swiperElement, zoomIn) {
289
- if (this.debug)
290
- console.debug('[image-gallery] zoom ' + (zoomIn ? 'in' : 'out'), swiperElement);
291
- const swiper = this.getSwiper(swiperElement);
292
- const zoom = swiper.zoom;
293
- if (zoomIn)
294
- zoom.in();
295
- else
296
- zoom.out();
297
- }
298
- async deleteFromModal(event, swiperElement) {
299
- const swiper = this.getSwiper(swiperElement);
300
- const currentRow = this.rows.find((row, index) => index === swiper.activeIndex);
301
- if (!currentRow)
302
- return false; // Row not found
303
- const deleted = await this.delete(event, currentRow);
304
- if (this.rows.length === 0) {
305
- await this.zoomModal.dismiss();
306
- }
307
- else {
308
- // Reset the zoom
309
- swiper.zoom.out();
310
- swiper.update();
311
- this.markForCheck();
312
- }
313
- return deleted;
314
- }
315
- async slidePrev(swiperElement) {
316
- const swiper = this.getSwiper(swiperElement);
317
- const activeIndex = swiper.activeIndex;
318
- if (activeIndex === 0) {
319
- // Loop to last
320
- await swiper.slideTo(this.rows.length - 1, 0 /*no transition, to avoid a "revert" effect*/);
321
- }
322
- else {
323
- await swiper.slidePrev();
324
- }
325
- }
326
- async slideNext(swiperElement) {
327
- const swiper = this.getSwiper(swiperElement);
328
- const activeIndex = swiper.activeIndex;
329
- if (activeIndex === this.rows.length - 1) {
330
- // Loop to first
331
- await swiper.slideTo(0, 0 /*no transition, to avoid a "revert" effect*/);
300
+ /**
301
+ * Handles a delete request coming from the slideshow component (either inline or in the modal):
302
+ * runs the same confirmation/deletion flow as a card's delete button, then resolves the promise
303
+ * so the slideshow knows whether to reset its zoom or close.
304
+ */
305
+ async onSlideshowDeleteRequested(promiseEvent) {
306
+ try {
307
+ const deleted = await this.delete(promiseEvent, promiseEvent.detail.row);
308
+ promiseEvent.detail.success(deleted);
309
+ if (deleted && this.rows.length === 0 && this.zoomPresentation === 'inline') {
310
+ this.closeInlineSlideshow();
311
+ }
332
312
  }
333
- else {
334
- await swiper.slideNext();
313
+ catch (err) {
314
+ promiseEvent.detail.error(err);
335
315
  }
336
316
  }
337
317
  async canDeleteRows(rows, opts) {
@@ -370,11 +350,11 @@ export class AppImageGalleryComponent {
370
350
  this.cd.markForCheck();
371
351
  }
372
352
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AppImageGalleryComponent, deps: [{ token: i1.ImageService }, { token: i2.Platform }, { token: i2.AlertController }, { token: i3.TranslateService }, { token: i0.ChangeDetectorRef }, { token: ENVIRONMENT, optional: true }], target: i0.ɵɵFactoryTarget.Component });
373
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: { cardColor: "cardColor", debug: ["debug", "debug", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], readOnly: ["readOnly", "readOnly", booleanAttribute], mobile: ["mobile", "mobile", booleanAttribute], mode: "mode", confirmBeforeDelete: "confirmBeforeDelete", showToolbar: ["showToolbar", "showToolbar", booleanAttribute], showFabButton: ["showFabButton", "showFabButton", booleanAttribute], showTitle: ["showTitle", "showTitle", booleanAttribute], showAddToolbarButton: ["showAddToolbarButton", "showAddToolbarButton", booleanAttribute], showAddTextButton: ["showAddTextButton", "showAddTextButton", booleanAttribute], showAddCardButton: ["showAddCardButton", "showAddCardButton", booleanAttribute], showCardToolbar: ["showCardToolbar", "showCardToolbar", booleanAttribute], addButtonColor: "addButtonColor", addButtonText: "addButtonText", cardTemplate: "cardTemplate", imageSizes: "imageSizes", imageSizeQueryParam: "imageSizeQueryParam", dataSource: "dataSource" }, outputs: { onBeforeDeleteRows: "onBeforeDeleteRows", onAfterAddRows: "onAfterAddRows", onAfterEditRow: "onAfterEditRow", click: "click" }, viewQueries: [{ propertyName: "zoomModal", first: true, predicate: ["zoomModal"], descendants: true }, { propertyName: "titlePopover", first: true, predicate: ["titlePopover"], descendants: true }, { propertyName: "swiperRef", first: true, predicate: ["modalSwiper"], descendants: true }], ngImport: i0, template: "<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <ng-content select=\"ion-buttons[slot=start]\"></ng-content>\n\n <!-- Add -->\n @if (!readOnly && showAddToolbarButton && enabled) {\n <button\n mat-icon-button\n [title]=\"!showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n }\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container ion-padding-bottom {{ this.mode }}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container\n *ngTemplateOutlet=\"cardTemplate; context: { $implicit: row, mode: mode, image: image }\"\n ></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n @if (showTitle && image.title) {\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n }\n\n <!-- action toolbar shown when hover image -->\n @if (!readOnly && !mobile && showCardToolbar) {\n <ion-toolbar #cardToolbar color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n @if (showTitle) {\n <button\n mat-button\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"focusCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n }\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"!showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n }\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? addButtonText : ''\"\n [matTooltip]=\"showTooltip ? addButtonText : ''\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\">\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ activeSlideIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #modalSwiper\n [modules]=\"swiperModules\"\n [zoom]=\"true\"\n (swiperslidechange)=\"onSlideChange(modalSwiper)\"\n (swiperinit)=\"initModalSlides(modalSwiper)\"\n >\n @for (row of rows; track row.id; let last = $last) {\n <swiper-slide>\n @let image = row | propertyGet: 'currentData';\n <div class=\"swiper-zoom-container\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams('modal')\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n </div>\n </swiper-slide>\n }\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button\n *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px;--image-margin-safe-area: var(--image-margin-inline, 0px) * 2 - 3px;--segment-max-width: 150px}ion-toolbar{position:sticky;top:0}ion-toolbar ion-segment{max-width:var(--segment-max-width)}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%;max-height:var(--img-max-height, calc(100% - var(--image-margin-safe-area, 0px)))}.image-card .card-thumbnail>ion-img{min-height:100%;height:100%;object-fit:cover;object-position:center;transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-safe-area, 0px));max-height:max(min(30vh,200px),var(--img-max-height, 0px));transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal swiper-container{height:100%;background:#000}.zoom-modal ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2.IonRow, selector: "ion-row" }, { kind: "component", type: i2.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i2.IonSegmentButton, selector: "ion-segment-button", inputs: ["disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: i2.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2.IonModal, selector: "ion-modal" }, { kind: "component", type: i2.IonPopover, selector: "ion-popover" }, { kind: "directive", type: i2.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i10.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i12.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i3.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i13.RxFor, selector: "[rxFor][rxForOf]", inputs: ["rxForOf", "rxForTemplate", "rxForStrategy", "rxForParent", "rxForPatchZone", "rxForTrackBy", "rxForRenderCallback"] }, { kind: "pipe", type: i14.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i15.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i16.IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }, { kind: "pipe", type: i17.AppendQueryParamsPipePipe, name: "appendQueryParams" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
353
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: { cardColor: "cardColor", debug: ["debug", "debug", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], readOnly: ["readOnly", "readOnly", booleanAttribute], mobile: ["mobile", "mobile", booleanAttribute], mode: "mode", confirmBeforeDelete: "confirmBeforeDelete", showToolbar: ["showToolbar", "showToolbar", booleanAttribute], showFabButton: ["showFabButton", "showFabButton", booleanAttribute], showTitle: ["showTitle", "showTitle", booleanAttribute], showAddToolbarButton: ["showAddToolbarButton", "showAddToolbarButton", booleanAttribute], showAddTextButton: ["showAddTextButton", "showAddTextButton", booleanAttribute], showAddCardButton: ["showAddCardButton", "showAddCardButton", booleanAttribute], showCardToolbar: ["showCardToolbar", "showCardToolbar", booleanAttribute], addButtonColor: "addButtonColor", addButtonText: "addButtonText", cardTemplate: "cardTemplate", imageSizes: "imageSizes", imageSizeQueryParam: "imageSizeQueryParam", enableMouseZoom: ["enableMouseZoom", "enableMouseZoom", booleanAttribute], wheelZoomStep: "wheelZoomStep", maxZoomRatio: "maxZoomRatio", enableRotation: ["enableRotation", "enableRotation", booleanAttribute], enableCrop: ["enableCrop", "enableCrop", booleanAttribute], imageExportFormat: "imageExportFormat", imageExportQuality: "imageExportQuality", zoomPresentation: "zoomPresentation", inlineZoomHeight: "inlineZoomHeight", dataSource: "dataSource" }, outputs: { onBeforeDeleteRows: "onBeforeDeleteRows", onAfterAddRows: "onAfterAddRows", onAfterEditRow: "onAfterEditRow", onAfterEditImage: "onAfterEditImage", click: "click" }, viewQueries: [{ propertyName: "zoomModal", first: true, predicate: ["zoomModal"], descendants: true }, { propertyName: "titlePopover", first: true, predicate: ["titlePopover"], descendants: true }], ngImport: i0, template: "<ion-toolbar color=\"light\" class=\"gallery-toolbar\" *ngIf=\"showToolbar && !_inlineSlideshowActive\">\n <ng-content select=\"ion-buttons[slot=start]\"></ng-content>\n\n <!-- Add -->\n @if (!readOnly && showAddToolbarButton && enabled) {\n <button\n mat-icon-button\n [title]=\"!showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n }\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div\n class=\"gallery-container ion-padding-bottom {{ mode }}\"\n [class.inline-zoom-active]=\"_inlineSlideshowActive\"\n [style.--inline-zoom-height]=\"inlineZoomHeight\"\n>\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\" [class.cdk-visually-hidden]=\"_inlineSlideshowActive\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container\n *ngTemplateOutlet=\"cardTemplate; context: { $implicit: row, mode: mode, image: image }\"\n ></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n @if (showTitle && image.title) {\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n }\n\n <!-- action toolbar shown when hover image -->\n @if (!readOnly && !mobile && showCardToolbar) {\n <ion-toolbar #cardToolbar color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n @if (showTitle) {\n <button\n mat-button\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"focusCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n }\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"!showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n }\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? addButtonText : ''\"\n [matTooltip]=\"showTooltip ? addButtonText : ''\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n\n <!-- Inline slideshow: shown as an overlay directly within the gallery, instead of a full-screen modal.\n The rest of the page (outside the gallery) stays fully visible and usable, unlike the modal's backdrop. -->\n @if (zoomPresentation === 'inline' && _inlineSlideshowActive) {\n <app-image-gallery-slideshow\n class=\"inline-overlay\"\n @fadeInOutAnimation\n [rows]=\"rows\"\n [selectedIndex]=\"_selectedRowIndex\"\n [mobile]=\"mobile\"\n [readOnly]=\"readOnly\"\n [disabled]=\"disabled\"\n [debug]=\"debug\"\n [mouseZoomEnabled]=\"_mouseZoomEnabled\"\n [wheelZoomStep]=\"wheelZoomStep\"\n [maxZoomRatio]=\"maxZoomRatio\"\n [rotationEnabled]=\"_rotationEnabled\"\n [cropEnabled]=\"_cropEnabled\"\n [imageExportFormat]=\"imageExportFormat\"\n [imageExportQuality]=\"imageExportQuality\"\n [imageSizeQueryParam]=\"imageSizeQueryParam\"\n [modalImageSize]=\"imageSizes?.modal\"\n (deleteRequested)=\"onSlideshowDeleteRequested($event)\"\n (closeRequested)=\"closeInlineSlideshow()\"\n (afterEditImage)=\"onAfterEditImage.emit($event)\"\n (afterEditRow)=\"onAfterEditRow.emit($event)\"\n ></app-image-gallery-slideshow>\n }\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n@if (zoomPresentation === 'modal') {\n <ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <app-image-gallery-slideshow\n [rows]=\"rows\"\n [selectedIndex]=\"_selectedRowIndex\"\n [mobile]=\"mobile\"\n [readOnly]=\"readOnly\"\n [disabled]=\"disabled\"\n [debug]=\"debug\"\n [mouseZoomEnabled]=\"_mouseZoomEnabled\"\n [wheelZoomStep]=\"wheelZoomStep\"\n [maxZoomRatio]=\"maxZoomRatio\"\n [rotationEnabled]=\"_rotationEnabled\"\n [cropEnabled]=\"_cropEnabled\"\n [imageExportFormat]=\"imageExportFormat\"\n [imageExportQuality]=\"imageExportQuality\"\n [imageSizeQueryParam]=\"imageSizeQueryParam\"\n [modalImageSize]=\"imageSizes?.modal\"\n (deleteRequested)=\"onSlideshowDeleteRequested($event)\"\n (closeRequested)=\"zoomModal.dismiss()\"\n (afterEditImage)=\"onAfterEditImage.emit($event)\"\n (afterEditRow)=\"onAfterEditRow.emit($event)\"\n ></app-image-gallery-slideshow>\n </ng-template>\n </ion-modal>\n}\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px;--image-margin-safe-area: var(--image-margin-inline, 0px) * 2 - 3px;--segment-max-width: 150px}ion-toolbar{position:sticky;top:0}ion-toolbar ion-segment{max-width:var(--segment-max-width)}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%;max-height:var(--img-max-height, calc(100% - var(--image-margin-safe-area, 0px)))}.image-card .card-thumbnail>ion-img{min-height:100%;height:100%;object-fit:cover;object-position:center;transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-safe-area, 0px));max-height:max(min(30vh,200px),var(--img-max-height, 0px));transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.gallery-container{position:relative}.gallery-container.inline-zoom-active{min-height:var(--inline-zoom-height, 60vh)}.inline-overlay{position:absolute;inset:0;z-index:20;background:#000}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2.IonRow, selector: "ion-row" }, { kind: "component", type: i2.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i2.IonSegmentButton, selector: "ion-segment-button", inputs: ["disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: i2.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2.IonModal, selector: "ion-modal" }, { kind: "component", type: i2.IonPopover, selector: "ion-popover" }, { kind: "directive", type: i2.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i10.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i12.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i3.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i13.RxFor, selector: "[rxFor][rxForOf]", inputs: ["rxForOf", "rxForTemplate", "rxForStrategy", "rxForParent", "rxForPatchZone", "rxForTrackBy", "rxForRenderCallback"] }, { kind: "component", type: i14.AppImageGallerySlideshowComponent, selector: "app-image-gallery-slideshow", inputs: ["rows", "selectedIndex", "mobile", "readOnly", "disabled", "debug", "mouseZoomEnabled", "wheelZoomStep", "maxZoomRatio", "rotationEnabled", "cropEnabled", "imageExportFormat", "imageExportQuality", "imageSizeQueryParam", "modalImageSize"], outputs: ["deleteRequested", "closeRequested", "afterEditImage", "afterEditRow"] }, { kind: "pipe", type: i15.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i16.IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }, { kind: "pipe", type: i17.AppendQueryParamsPipePipe, name: "appendQueryParams" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
374
354
  }
375
355
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AppImageGalleryComponent, decorators: [{
376
356
  type: Component,
377
- args: [{ selector: 'app-image-gallery', animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <ng-content select=\"ion-buttons[slot=start]\"></ng-content>\n\n <!-- Add -->\n @if (!readOnly && showAddToolbarButton && enabled) {\n <button\n mat-icon-button\n [title]=\"!showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n }\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container ion-padding-bottom {{ this.mode }}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container\n *ngTemplateOutlet=\"cardTemplate; context: { $implicit: row, mode: mode, image: image }\"\n ></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n @if (showTitle && image.title) {\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n }\n\n <!-- action toolbar shown when hover image -->\n @if (!readOnly && !mobile && showCardToolbar) {\n <ion-toolbar #cardToolbar color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n @if (showTitle) {\n <button\n mat-button\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"focusCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n }\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"!showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n }\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? addButtonText : ''\"\n [matTooltip]=\"showTooltip ? addButtonText : ''\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\">\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ activeSlideIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #modalSwiper\n [modules]=\"swiperModules\"\n [zoom]=\"true\"\n (swiperslidechange)=\"onSlideChange(modalSwiper)\"\n (swiperinit)=\"initModalSlides(modalSwiper)\"\n >\n @for (row of rows; track row.id; let last = $last) {\n <swiper-slide>\n @let image = row | propertyGet: 'currentData';\n <div class=\"swiper-zoom-container\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams('modal')\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n </div>\n </swiper-slide>\n }\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button\n *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px;--image-margin-safe-area: var(--image-margin-inline, 0px) * 2 - 3px;--segment-max-width: 150px}ion-toolbar{position:sticky;top:0}ion-toolbar ion-segment{max-width:var(--segment-max-width)}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%;max-height:var(--img-max-height, calc(100% - var(--image-margin-safe-area, 0px)))}.image-card .card-thumbnail>ion-img{min-height:100%;height:100%;object-fit:cover;object-position:center;transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-safe-area, 0px));max-height:max(min(30vh,200px),var(--img-max-height, 0px));transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal swiper-container{height:100%;background:#000}.zoom-modal ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}\n"] }]
357
+ args: [{ selector: 'app-image-gallery', animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-toolbar color=\"light\" class=\"gallery-toolbar\" *ngIf=\"showToolbar && !_inlineSlideshowActive\">\n <ng-content select=\"ion-buttons[slot=start]\"></ng-content>\n\n <!-- Add -->\n @if (!readOnly && showAddToolbarButton && enabled) {\n <button\n mat-icon-button\n [title]=\"!showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n }\n\n <ng-content select=\"ion-buttons[slot=end]\"></ng-content>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div\n class=\"gallery-container ion-padding-bottom {{ mode }}\"\n [class.inline-zoom-active]=\"_inlineSlideshowActive\"\n [style.--inline-zoom-height]=\"inlineZoomHeight\"\n>\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\" [class.cdk-visually-hidden]=\"_inlineSlideshowActive\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container\n *ngTemplateOutlet=\"cardTemplate; context: { $implicit: row, mode: mode, image: image }\"\n ></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n @if (showTitle && image.title) {\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n }\n\n <!-- action toolbar shown when hover image -->\n @if (!readOnly && !mobile && showCardToolbar) {\n <ion-toolbar #cardToolbar color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n @if (showTitle) {\n <button\n mat-button\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"focusCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n }\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"!showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n }\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? addButtonText : ''\"\n [matTooltip]=\"showTooltip ? addButtonText : ''\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n\n <!-- Inline slideshow: shown as an overlay directly within the gallery, instead of a full-screen modal.\n The rest of the page (outside the gallery) stays fully visible and usable, unlike the modal's backdrop. -->\n @if (zoomPresentation === 'inline' && _inlineSlideshowActive) {\n <app-image-gallery-slideshow\n class=\"inline-overlay\"\n @fadeInOutAnimation\n [rows]=\"rows\"\n [selectedIndex]=\"_selectedRowIndex\"\n [mobile]=\"mobile\"\n [readOnly]=\"readOnly\"\n [disabled]=\"disabled\"\n [debug]=\"debug\"\n [mouseZoomEnabled]=\"_mouseZoomEnabled\"\n [wheelZoomStep]=\"wheelZoomStep\"\n [maxZoomRatio]=\"maxZoomRatio\"\n [rotationEnabled]=\"_rotationEnabled\"\n [cropEnabled]=\"_cropEnabled\"\n [imageExportFormat]=\"imageExportFormat\"\n [imageExportQuality]=\"imageExportQuality\"\n [imageSizeQueryParam]=\"imageSizeQueryParam\"\n [modalImageSize]=\"imageSizes?.modal\"\n (deleteRequested)=\"onSlideshowDeleteRequested($event)\"\n (closeRequested)=\"closeInlineSlideshow()\"\n (afterEditImage)=\"onAfterEditImage.emit($event)\"\n (afterEditRow)=\"onAfterEditRow.emit($event)\"\n ></app-image-gallery-slideshow>\n }\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n@if (zoomPresentation === 'modal') {\n <ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <app-image-gallery-slideshow\n [rows]=\"rows\"\n [selectedIndex]=\"_selectedRowIndex\"\n [mobile]=\"mobile\"\n [readOnly]=\"readOnly\"\n [disabled]=\"disabled\"\n [debug]=\"debug\"\n [mouseZoomEnabled]=\"_mouseZoomEnabled\"\n [wheelZoomStep]=\"wheelZoomStep\"\n [maxZoomRatio]=\"maxZoomRatio\"\n [rotationEnabled]=\"_rotationEnabled\"\n [cropEnabled]=\"_cropEnabled\"\n [imageExportFormat]=\"imageExportFormat\"\n [imageExportQuality]=\"imageExportQuality\"\n [imageSizeQueryParam]=\"imageSizeQueryParam\"\n [modalImageSize]=\"imageSizes?.modal\"\n (deleteRequested)=\"onSlideshowDeleteRequested($event)\"\n (closeRequested)=\"zoomModal.dismiss()\"\n (afterEditImage)=\"onAfterEditImage.emit($event)\"\n (afterEditRow)=\"onAfterEditRow.emit($event)\"\n ></app-image-gallery-slideshow>\n </ng-template>\n </ion-modal>\n}\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"!showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate) : ''\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px;--image-margin-safe-area: var(--image-margin-inline, 0px) * 2 - 3px;--segment-max-width: 150px}ion-toolbar{position:sticky;top:0}ion-toolbar ion-segment{max-width:var(--segment-max-width)}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%;max-height:var(--img-max-height, calc(100% - var(--image-margin-safe-area, 0px)))}.image-card .card-thumbnail>ion-img{min-height:100%;height:100%;object-fit:cover;object-position:center;transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-safe-area, 0px));max-height:max(min(30vh,200px),var(--img-max-height, 0px));transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.gallery-container{position:relative}.gallery-container.inline-zoom-active{min-height:var(--inline-zoom-height, 60vh)}.inline-overlay{position:absolute;inset:0;z-index:20;background:#000}\n"] }]
378
358
  }], ctorParameters: () => [{ type: i1.ImageService }, { type: i2.Platform }, { type: i2.AlertController }, { type: i3.TranslateService }, { type: i0.ChangeDetectorRef }, { type: i18.Environment, decorators: [{
379
359
  type: Optional
380
360
  }, {
@@ -429,6 +409,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
429
409
  type: Input
430
410
  }], imageSizeQueryParam: [{
431
411
  type: Input
412
+ }], enableMouseZoom: [{
413
+ type: Input,
414
+ args: [{ transform: booleanAttribute }]
415
+ }], wheelZoomStep: [{
416
+ type: Input
417
+ }], maxZoomRatio: [{
418
+ type: Input
419
+ }], enableRotation: [{
420
+ type: Input,
421
+ args: [{ transform: booleanAttribute }]
422
+ }], enableCrop: [{
423
+ type: Input,
424
+ args: [{ transform: booleanAttribute }]
425
+ }], imageExportFormat: [{
426
+ type: Input
427
+ }], imageExportQuality: [{
428
+ type: Input
429
+ }], zoomPresentation: [{
430
+ type: Input
431
+ }], inlineZoomHeight: [{
432
+ type: Input
432
433
  }], dataSource: [{
433
434
  type: Input
434
435
  }], zoomModal: [{
@@ -437,16 +438,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
437
438
  }], titlePopover: [{
438
439
  type: ViewChild,
439
440
  args: ['titlePopover']
440
- }], swiperRef: [{
441
- type: ViewChild,
442
- args: ['modalSwiper']
443
441
  }], onBeforeDeleteRows: [{
444
442
  type: Output
445
443
  }], onAfterAddRows: [{
446
444
  type: Output
447
445
  }], onAfterEditRow: [{
448
446
  type: Output
447
+ }], onAfterEditImage: [{
448
+ type: Output
449
449
  }], click: [{
450
450
  type: Output
451
451
  }] } });
452
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtZ2FsbGVyeS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3NoYXJlZC9pbWFnZS9nYWxsZXJ5L2ltYWdlLWdhbGxlcnkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvaW1hZ2UvZ2FsbGVyeS9pbWFnZS1nYWxsZXJ5LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBRXZCLFNBQVMsRUFFVCxZQUFZLEVBQ1osTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBR0wsUUFBUSxFQUNSLE1BQU0sRUFFTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGVBQWUsRUFBYyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTFFLE9BQU8sRUFBRSxXQUFXLEVBQWUsTUFBTSw0Q0FBNEMsQ0FBQztBQUd0RixPQUFPLEVBQW1CLFdBQVcsRUFBa0MsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sRUFBb0IsWUFBWSxFQUFhLE1BQU0sMEJBQTBCLENBQUM7QUFDckYsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHdEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLGdCQUFnQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBSzNFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUluRCxNQUFNLGtCQUFrQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDdkMsTUFBTSxFQUFFLENBQUM7SUFDVCxJQUFJLEVBQUUsRUFBRTtDQUNULENBQUMsQ0FBQztBQW9CSCxNQUFNLE9BQU8sd0JBQXdCO0lBaUZ2QjtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBcEZGLGVBQWUsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0lBQ3RDLHlCQUF5QixDQUFlO0lBQ3hDLGFBQWEsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0lBQ25DLFdBQVcsQ0FBcUI7SUFDaEMsTUFBTSxHQUFHLElBQUksZUFBZSxDQUFxRCxJQUFJLENBQUMsQ0FBQztJQUV2RixRQUFRLENBQVM7SUFDakIsaUJBQWlCLENBQVM7SUFDMUIsa0JBQWtCLEdBQVksSUFBSSxDQUFDO0lBQ25DLFVBQVUsQ0FBWTtJQUN0QixlQUFlLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLG1CQUFtQixDQUFlO0lBQ2xDLE9BQU8sQ0FBUztJQUVoQixhQUFhLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUM5QixVQUFVLEdBQUcsS0FBSyxDQUFDO0lBQ25CLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFFeEIsVUFBVSxDQUE2QjtJQUU5QixTQUFTLENBQTRCO0lBQ04sS0FBSyxHQUFZLElBQUksQ0FBQztJQUN0QixRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDakIsTUFBTSxHQUFZLElBQUksQ0FBQztJQUN0RCxJQUFJLEdBQWdCLElBQUksQ0FBQztJQUN6QixtQkFBbUIsR0FBRyxJQUFJLENBQUM7SUFDSSxXQUFXLEdBQUcsSUFBSSxDQUFDO0lBQ25CLGFBQWEsQ0FBVTtJQUN2QixTQUFTLEdBQUcsSUFBSSxDQUFDO0lBQ2pCLG9CQUFvQixDQUFVO0lBQzlCLGlCQUFpQixHQUFHLEtBQUssQ0FBQztJQUMxQixpQkFBaUIsR0FBRyxJQUFJLENBQUM7SUFDekIsZUFBZSxHQUFHLElBQUksQ0FBQztJQUN0RCxjQUFjLEdBQWMsVUFBVSxDQUFDO0lBQ3ZDLGFBQWEsR0FBVyxnQkFBZ0IsQ0FBQztJQUN6QyxZQUFZLENBQTJFO0lBQ3ZGLFVBQVUsR0FBc0I7UUFDdkMsTUFBTSxFQUFhLE9BQU87UUFDMUIsSUFBSSxFQUFhLFFBQVE7UUFDekIsS0FBSyxFQUFhLE9BQU87S0FDMUIsQ0FBQztJQUNPLG1CQUFtQixHQUFHLE1BQU0sQ0FBQztJQUV0QyxJQUFhLFVBQVUsQ0FBQyxVQUE2QztRQUNuRSxJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDcEMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxVQUFVO1FBQ1osT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzFCLENBQUM7SUFDRCxJQUFJLE9BQU87UUFDVCxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN4QixDQUFDO0lBRUQsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztJQUMzQixDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLFdBQVcsSUFBSSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUV1QixTQUFTLENBQVc7SUFDakIsWUFBWSxDQUFhO0lBQzFCLFNBQVMsQ0FBYTtJQUV0QyxrQkFBa0IsR0FBRyx5QkFBeUIsRUFBd0MsQ0FBQztJQUN2RixjQUFjLEdBQUcsSUFBSSxZQUFZLEVBQXFCLENBQUM7SUFDdkQsY0FBYyxHQUFHLElBQUksWUFBWSxFQUFtQixDQUFDO0lBQ3JELEtBQUssR0FBRyxJQUFJLFlBQVksRUFBSyxDQUFDO0lBRXhDLFdBQVcsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUUzRCxZQUNZLFlBQTBCLEVBQzFCLFFBQWtCLEVBQ2xCLFNBQTBCLEVBQzFCLFNBQTJCLEVBQzNCLEVBQXFCLEVBQ0UsV0FBeUI7UUFMaEQsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNsQixjQUFTLEdBQVQsU0FBUyxDQUFpQjtRQUMxQixjQUFTLEdBQVQsU0FBUyxDQUFrQjtRQUMzQixPQUFFLEdBQUYsRUFBRSxDQUFtQjtRQUcvQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksZUFBZSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFFM0UsVUFBVTtRQUNWLElBQUksQ0FBQyxLQUFLLEdBQUcsV0FBVyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztJQUN0RCxDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsUUFBUSxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxlQUFlLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hFLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzNGLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRTlGLDBDQUEwQztRQUMxQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3JGLENBQUM7SUFFRCxxQkFBcUI7UUFDbkIsSUFBSSxJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7WUFDdkQsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDL0IsQ0FBQztJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRWhDLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDO1FBRXhDLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25DLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLEdBQUcsQ0FDUCxLQUFhLEVBQ2IsSUFHQztRQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXhELElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQztZQUFFLE9BQU87UUFFakMsT0FBTyxDQUFDLElBQUksQ0FBQyw4QkFBOEIsTUFBTSxDQUFDLE1BQU0sV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRTdFLE1BQU0sSUFBSSxHQUFzQixFQUFFLENBQUM7UUFDbkMsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUMzQixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDL0MsR0FBRyxDQUFDLFdBQVcsR0FBRyxLQUFxQixDQUFDO1lBQ3hDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDZixNQUFNLEtBQUssR0FBRyxNQUFNLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzVDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxPQUFPLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxDQUFDLENBQUM7Z0JBQzFELE1BQU07WUFDUixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQVksRUFBRSxHQUFvQixFQUFFLElBQWdDO1FBQy9FLElBQUksS0FBSyxFQUFFLGdCQUFnQixJQUFJLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDM0QsS0FBSyxFQUFFLGNBQWMsRUFBRSxDQUFDO1FBQ3hCLEtBQUssRUFBRSxlQUFlLEVBQUUsQ0FBQztRQUV6QixzQkFBc0I7UUFDdEIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRTdCLElBQUksT0FBZ0IsQ0FBQztRQUNyQixJQUFJLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNsQixPQUFPLENBQUMsSUFBSSxDQUFDLG9DQUFvQyxDQUFDLENBQUM7WUFDbkQsT0FBTyxHQUFHLE1BQU0sR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxzQ0FBc0MsR0FBRyxHQUFHLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQ3BFLE9BQU8sR0FBRyxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMvQixDQUFDO1FBRUQsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVELGNBQWMsQ0FBQyxDQUFTO1FBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELFdBQVcsQ0FBQyxJQUFpQjtRQUMzQixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7WUFDakIsSUFBSSxDQUFDLFFBQVEsR0FBRyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUM7SUFDSCxDQUFDO0lBRUQsU0FBUyxDQUFDLEtBQWEsRUFBRSxHQUFvQjtRQUMzQyxPQUFPLEdBQUcsQ0FBQyxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVELEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBaUIsRUFBRSxHQUFvQixFQUFFLFdBQWdCO1FBQ3ZFLElBQUksS0FBSyxFQUFFLGdCQUFnQjtZQUFFLE9BQU87UUFDcEMsS0FBSyxFQUFFLGNBQWMsRUFBRSxDQUFDO1FBQ3hCLEtBQUssRUFBRSxlQUFlLEVBQUUsQ0FBQztRQUN6QixLQUFLLEVBQUUsd0JBQXdCLEVBQUUsQ0FBQztRQUVsQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFbkMsTUFBTSxZQUFZLEdBQUcsSUFBSSxXQUFXLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsSSxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksU0FBUyxDQUFDLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3JFLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7UUFFeEIsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRWxDLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBRTlELElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0NBQWtDLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFDekQsR0FBRyxDQUFDLFdBQVcsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQzdCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBRUQsOEZBQThGO1FBQzlGLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFUyxnQkFBZ0IsQ0FBQyxXQUFnQjtRQUN6QyxNQUFNLEVBQUUsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFnQixDQUFDO1FBQzVDLEVBQUUsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFUyxlQUFlLENBQUMsV0FBZ0I7UUFDeEMsTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBZ0IsQ0FBQztRQUM1QyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRVMsaUJBQWlCLENBQUMsVUFBOEI7UUFDeEQsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEMsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDO0lBQ2hDLENBQUM7SUFFUyxxQkFBcUI7UUFDN0IsMkVBQTJFO1FBQzNFLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDckIsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLFVBQTBFLENBQUM7UUFDL0UsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDbEMsVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFDRCxJQUFJLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO1FBQzlDLENBQUM7UUFDRCxJQUFJLENBQUMseUJBQXlCLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLHlCQUF5QixHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ25HLE9BQU8sQ0FBQyxLQUFLLENBQUMsbUNBQW1DLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDekQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdkIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVTLDhCQUE4QjtRQUN0QyxPQUFPLEtBQUssQ0FBQyx3RUFBd0UsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFFUyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQW9CLEVBQUUsS0FBYTtRQUMxRCx3QkFBd0I7UUFDeEIsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3hCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuQyxDQUFDO1FBRUQsZ0NBQWdDO2FBQzNCLENBQUM7WUFDSixJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO1lBQy9CLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMvQixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDdEMsQ0FBQztJQUNILENBQUM7SUFFUyxnQkFBZ0IsR0FBRyxDQUFDLENBQUM7SUFFckIsU0FBUyxDQUFDLGFBQW1CO1FBQ3JDLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsRUFBRSxNQUFNLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUN4RixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVTLGFBQWEsQ0FBQyxhQUFrQjtRQUN4QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDO1FBQzNDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRVMsZUFBZSxDQUFDLGFBQWtCO1FBQzFDLElBQUksSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsRUFBRSxDQUFDO1lBQy9CLElBQUksSUFBSSxDQUFDLEtBQUs7Z0JBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyx3REFBd0QsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztZQUNoSCxxREFBcUQ7WUFDckQsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFDZCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUM3QyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM1QyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRVMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFrQixFQUFFLE1BQWU7UUFDdEQsSUFBSSxJQUFJLENBQUMsS0FBSztZQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDaEcsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUM3QyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQ3pCLElBQUksTUFBTTtZQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQzs7WUFDakIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFUyxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxhQUFrQjtRQUN2RCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxLQUFLLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNoRixJQUFJLENBQUMsVUFBVTtZQUFFLE9BQU8sS0FBSyxDQUFDLENBQUMsZ0JBQWdCO1FBRS9DLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFckQsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDakMsQ0FBQzthQUFNLENBQUM7WUFDTixpQkFBaUI7WUFDakIsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNsQixNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRVMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxhQUFrQjtRQUMxQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUM7UUFDdkMsSUFBSSxXQUFXLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdEIsZUFBZTtZQUNmLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7UUFDOUYsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUMzQixDQUFDO0lBQ0gsQ0FBQztJQUVTLEtBQUssQ0FBQyxTQUFTLENBQUMsYUFBa0I7UUFDMUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUM3QyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDO1FBQ3ZDLElBQUksV0FBVyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3pDLGdCQUFnQjtZQUNoQixNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQzNFLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDM0IsQ0FBQztJQUNILENBQUM7SUFFUyxLQUFLLENBQUMsYUFBYSxDQUFDLElBQXVCLEVBQUUsSUFBZ0M7UUFDckYsc0JBQXNCO1FBQ3RCLElBQUksSUFBSSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQztnQkFDSCxNQUFNLFNBQVMsR0FBRyxNQUFNLGdCQUFnQixDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxXQUFXLEVBQUU7b0JBQzdFLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRTtpQkFDakIsQ0FBQyxDQUFDO2dCQUNILElBQUksQ0FBQyxTQUFTO29CQUFFLE9BQU8sS0FBSyxDQUFDO1lBQy9CLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLElBQUksR0FBRyxLQUFLLFdBQVc7b0JBQUUsT0FBTyxLQUFLLENBQUMsQ0FBQyxjQUFjO2dCQUNyRCxPQUFPLENBQUMsS0FBSyxDQUFDLHlDQUF5QyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUM5RCxNQUFNLEdBQUcsQ0FBQztZQUNaLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM3QixNQUFNLFNBQVMsR0FBRyxNQUFNLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDNUYsSUFBSSxDQUFDLFNBQVM7Z0JBQUUsT0FBTyxLQUFLLENBQUMsQ0FBQyxZQUFZO1FBQzVDLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFUyx1QkFBdUIsQ0FBQyxJQUE0QjtRQUM1RCxJQUFJLEdBQUcsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQUUsT0FBTyxTQUFTLENBQUM7UUFDekYsT0FBTztZQUNMLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7U0FDbEQsQ0FBQztJQUNKLENBQUM7SUFFUyxZQUFZO1FBQ3BCLElBQUksQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDekIsQ0FBQzt3R0EzWFUsd0JBQXdCLHNLQXNGYixXQUFXOzRGQXRGdEIsd0JBQXdCLDZGQXNCZixnQkFBZ0Isc0NBQ2hCLGdCQUFnQixzQ0FDaEIsZ0JBQWdCLGdDQUNoQixnQkFBZ0IseUdBR2hCLGdCQUFnQixxREFDaEIsZ0JBQWdCLHlDQUNoQixnQkFBZ0IsMEVBQ2hCLGdCQUFnQixpRUFDaEIsZ0JBQWdCLGlFQUNoQixnQkFBZ0IsMkRBQ2hCLGdCQUFnQiwwb0JDbkd0QyxtOFZBa1NBLHl2VERwT2MsQ0FBQyxlQUFlLEVBQUUsa0JBQWtCLENBQUM7OzRGQUd0Qyx3QkFBd0I7a0JBUHBDLFNBQVM7K0JBQ0UsbUJBQW1CLGNBR2pCLENBQUMsZUFBZSxFQUFFLGtCQUFrQixDQUFDLG1CQUNoQyx1QkFBdUIsQ0FBQyxNQUFNOzswQkF3RjVDLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsV0FBVzt5Q0FqRXhCLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ2tDLEtBQUs7c0JBQTVDLEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsUUFBUTtzQkFBL0MsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDRSxRQUFRO3NCQUEvQyxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUNFLE1BQU07c0JBQTdDLEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQzdCLElBQUk7c0JBQVosS0FBSztnQkFDRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ2tDLFdBQVc7c0JBQWxELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsYUFBYTtzQkFBcEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDRSxTQUFTO3NCQUFoRCxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUNFLG9CQUFvQjtzQkFBM0QsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDRSxpQkFBaUI7c0JBQXhELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsaUJBQWlCO3NCQUF4RCxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUNFLGVBQWU7c0JBQXRELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQzdCLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBS0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQUVPLFVBQVU7c0JBQXRCLEtBQUs7Z0JBd0JrQixTQUFTO3NCQUFoQyxTQUFTO3VCQUFDLFdBQVc7Z0JBQ0ssWUFBWTtzQkFBdEMsU0FBUzt1QkFBQyxjQUFjO2dCQUNDLFNBQVM7c0JBQWxDLFNBQVM7dUJBQUMsYUFBYTtnQkFFZCxrQkFBa0I7c0JBQTNCLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTTtnQkFDRyxjQUFjO3NCQUF2QixNQUFNO2dCQUNHLEtBQUs7c0JBQWQsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudENoZWNrZWQsXG4gIGJvb2xlYW5BdHRyaWJ1dGUsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRhYmxlRGF0YVNvdXJjZSwgVGFibGVFbGVtZW50IH0gZnJvbSAnQGUtaXMvbmd4LW1hdGVyaWFsLXRhYmxlJztcbmltcG9ydCB7IEVOVklST05NRU5ULCBFbnZpcm9ubWVudCB9IGZyb20gJy4uLy4uLy4uLy4uL2Vudmlyb25tZW50cy9lbnZpcm9ubWVudC5jbGFzcyc7XG5pbXBvcnQgeyBJbWFnZVNlcnZpY2UgfSBmcm9tICcuLi9pbWFnZS5zZXJ2aWNlJztcbmltcG9ydCB7IEltYWdlLCBJbWFnZVNpemUgfSBmcm9tICcuLi9pbWFnZS5tb2RlbCc7XG5pbXBvcnQgeyBBbGVydENvbnRyb2xsZXIsIElvbmljU2xpZGVzLCBJb25Nb2RhbCwgSW9uUG9wb3ZlciwgUGxhdGZvcm0gfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBpc01vYmlsZSB9IGZyb20gJy4uLy4uL3BsYXRmb3Jtcyc7XG5pbXBvcnQgeyBmYWRlSW5BbmltYXRpb24sIGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL21hdGVyaWFsL21hdGVyaWFsLmFuaW1hdGlvbnMnO1xuaW1wb3J0IHsgaXNFbXB0eUFycmF5LCBpc05pbE9yQmxhbmssIHRvQm9vbGVhbiB9IGZyb20gJy4uLy4uL2Z1bmN0aW9ucyc7XG5pbXBvcnQgeyBDb2xsZWN0aW9uVmlld2VyLCBpc0RhdGFTb3VyY2UsIExpc3RSYW5nZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBBbGVydHMgfSBmcm9tICcuLi8uLi9hbGVydHMnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgQXBwQ29sb3JzIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IGNyZWF0ZVByb21pc2VFdmVudEVtaXR0ZXIsIGVtaXRQcm9taXNlRXZlbnQgfSBmcm9tICcuLi8uLi9ldmVudHMnO1xuaW1wb3J0IHsgUHJlZGVmaW5lZENvbG9ycyB9IGZyb20gJ0Bpb25pYy9jb3JlJztcbmltcG9ydCB7IFN3aXBlciB9IGZyb20gJ3N3aXBlci90eXBlcyc7XG5pbXBvcnQgeyBJbWFnZU9wdGlvbnMgfSBmcm9tICdAY2FwYWNpdG9yL2NhbWVyYSc7XG5cbmltcG9ydCB7IEFQUF9TSE9XX1RPT0xUSVAgfSBmcm9tICcuLi8uLi9jb25zdGFudHMnO1xuXG5leHBvcnQgdHlwZSBHYWxsZXJ5TW9kZSA9ICdtb3NhaWMnIHwgJ2xpc3QnO1xuXG5jb25zdCBHYWxsZXJ5TW9kZUNvbFNpemUgPSBPYmplY3QuZnJlZXplKHtcbiAgbW9zYWljOiA0LFxuICBsaXN0OiAxMixcbn0pO1xuXG5leHBvcnQgaW50ZXJmYWNlIElTd2lwZXIgZXh0ZW5kcyBTd2lwZXIge1xuICBhY3RpdmVJbmRleDogbnVtYmVyO1xuICBpbWFnZXNMb2FkZWQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbWFnZUdhbGxlcnlTaXplcyB7XG4gIG1vc2FpYzogSW1hZ2VTaXplIHwgc3RyaW5nO1xuICBsaXN0OiBJbWFnZVNpemUgfCBzdHJpbmc7XG4gIG1vZGFsOiBJbWFnZVNpemUgfCBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1pbWFnZS1nYWxsZXJ5JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2ltYWdlLWdhbGxlcnkuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9pbWFnZS1nYWxsZXJ5LmNvbXBvbmVudC5zY3NzJ10sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5BbmltYXRpb24sIGZhZGVJbk91dEFuaW1hdGlvbl0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBBcHBJbWFnZUdhbGxlcnlDb21wb25lbnQ8VCBleHRlbmRzIEltYWdlPiBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBDb2xsZWN0aW9uVmlld2VyLCBBZnRlckNvbnRlbnRDaGVja2VkIHtcbiAgcHJvdGVjdGVkIF9kZXN0cm95U3ViamVjdCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByb3RlY3RlZCBfcmVuZGVyQ2hhbmdlU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gIHByb3RlY3RlZCBfc3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICBwcm90ZWN0ZWQgX2RhdGFTb3VyY2U6IFRhYmxlRGF0YVNvdXJjZTxUPjtcbiAgcHJvdGVjdGVkIF9kYXRhJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8VGFibGVFbGVtZW50PFQ+W10gfCBSZWFkb25seUFycmF5PFRhYmxlRWxlbWVudDxUPj4+KG51bGwpO1xuXG4gIHByb3RlY3RlZCBfY29sU2l6ZTogbnVtYmVyO1xuICBwcm90ZWN0ZWQgX3NlbGVjdGVkUm93SW5kZXg6IG51bWJlcjtcbiAgcHJvdGVjdGVkIF9wcmVzZW50aW5nRWxlbWVudDogRWxlbWVudCA9IG51bGw7XG4gIHByb3RlY3RlZCBfdGl0bGVGb3JtOiBGb3JtR3JvdXA7XG4gIHByb3RlY3RlZCBfdGl0bGVBdXRvZm9jdXMgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIF9zbGlkZXNTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJvdGVjdGVkIF9zd2lwZXI6IFN3aXBlcjtcblxuICBwcm90ZWN0ZWQgc3dpcGVyTW9kdWxlcyA9IFtJb25pY1NsaWRlc107XG4gIHByb3RlY3RlZCB6b29tQWN0aXZlID0gZmFsc2U7XG4gIHByb3RlY3RlZCB6b29tU2NhbGUgPSAxO1xuXG4gIHZpZXdDaGFuZ2U6IEJlaGF2aW9yU3ViamVjdDxMaXN0UmFuZ2U+O1xuXG4gIEBJbnB1dCgpIGNhcmRDb2xvcjogc3RyaW5nIHwgUHJlZGVmaW5lZENvbG9ycztcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIGRlYnVnOiBib29sZWFuID0gbnVsbDtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIGRpc2FibGVkID0gZmFsc2U7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSByZWFkT25seSA9IGZhbHNlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgbW9iaWxlOiBib29sZWFuID0gbnVsbDtcbiAgQElucHV0KCkgbW9kZTogR2FsbGVyeU1vZGUgPSBudWxsO1xuICBASW5wdXQoKSBjb25maXJtQmVmb3JlRGVsZXRlID0gdHJ1ZTtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHNob3dUb29sYmFyID0gdHJ1ZTtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHNob3dGYWJCdXR0b246IGJvb2xlYW47XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzaG93VGl0bGUgPSB0cnVlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd0FkZFRvb2xiYXJCdXR0b246IGJvb2xlYW47XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzaG93QWRkVGV4dEJ1dHRvbiA9IGZhbHNlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd0FkZENhcmRCdXR0b24gPSB0cnVlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd0NhcmRUb29sYmFyID0gdHJ1ZTtcbiAgQElucHV0KCkgYWRkQnV0dG9uQ29sb3I6IEFwcENvbG9ycyA9ICd0ZXJ0aWFyeSc7XG4gIEBJbnB1dCgpIGFkZEJ1dHRvblRleHQ6IHN0cmluZyA9ICdDT01NT04uQlROX0FERCc7XG4gIEBJbnB1dCgpIGNhcmRUZW1wbGF0ZTogVGVtcGxhdGVSZWY8eyAkaW1wbGljaXQ6IFRhYmxlRWxlbWVudDxUPjsgaW1hZ2U6IFQ7IG1vZGU6IEdhbGxlcnlNb2RlIH0+O1xuICBASW5wdXQoKSBpbWFnZVNpemVzOiBJbWFnZUdhbGxlcnlTaXplcyA9IHtcbiAgICBtb3NhaWM6IDxJbWFnZVNpemU+J3NtYWxsJyxcbiAgICBsaXN0OiA8SW1hZ2VTaXplPidtZWRpdW0nLFxuICAgIG1vZGFsOiA8SW1hZ2VTaXplPidsYXJnZScsXG4gIH07XG4gIEBJbnB1dCgpIGltYWdlU2l6ZVF1ZXJ5UGFyYW0gPSAnc2l6ZSc7XG5cbiAgQElucHV0KCkgc2V0IGRhdGFTb3VyY2UoZGF0YVNvdXJjZTogVGFibGVEYXRhU291cmNlPFQsIGFueSwgYW55LCBhbnk+KSB7XG4gICAgaWYgKHRoaXMuX2RhdGFTb3VyY2UgIT09IGRhdGFTb3VyY2UpIHtcbiAgICAgIHRoaXMuX3N3aXRjaERhdGFTb3VyY2UoZGF0YVNvdXJjZSk7XG4gICAgfVxuICB9XG4gIGdldCBkYXRhU291cmNlKCk6IFRhYmxlRGF0YVNvdXJjZTxULCBhbnksIGFueSwgYW55PiB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGFTb3VyY2U7XG4gIH1cbiAgZ2V0IGVuYWJsZWQoKSB7XG4gICAgcmV0dXJuICF0aGlzLmRpc2FibGVkO1xuICB9XG5cbiAgZ2V0IHJvd3MoKTogVGFibGVFbGVtZW50PFQ+W10gfCBSZWFkb25seUFycmF5PFRhYmxlRWxlbWVudDxUPj4ge1xuICAgIHJldHVybiB0aGlzLl9kYXRhJC52YWx1ZTtcbiAgfVxuXG4gIGdldCByb3dDb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy5yb3dzPy5sZW5ndGggfHwgMDtcbiAgfVxuXG4gIGdldCBhY3RpdmVJbmRleCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmdldFN3aXBlcigpPy5hY3RpdmVJbmRleCB8fCAwO1xuICB9XG5cbiAgQFZpZXdDaGlsZCgnem9vbU1vZGFsJykgem9vbU1vZGFsOiBJb25Nb2RhbDtcbiAgQFZpZXdDaGlsZCgndGl0bGVQb3BvdmVyJykgdGl0bGVQb3BvdmVyOiBJb25Qb3BvdmVyO1xuICBAVmlld0NoaWxkKCdtb2RhbFN3aXBlcicpIHN3aXBlclJlZjogRWxlbWVudFJlZjtcblxuICBAT3V0cHV0KCkgb25CZWZvcmVEZWxldGVSb3dzID0gY3JlYXRlUHJvbWlzZUV2ZW50RW1pdHRlcjxib29sZWFuLCB7IHJvd3M6IFRhYmxlRWxlbWVudDxUPltdIH0+KCk7XG4gIEBPdXRwdXQoKSBvbkFmdGVyQWRkUm93cyA9IG5ldyBFdmVudEVtaXR0ZXI8VGFibGVFbGVtZW50PFQ+W10+KCk7XG4gIEBPdXRwdXQoKSBvbkFmdGVyRWRpdFJvdyA9IG5ldyBFdmVudEVtaXR0ZXI8VGFibGVFbGVtZW50PFQ+PigpO1xuICBAT3V0cHV0KCkgY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPFQ+KCk7XG5cbiAgc2hvd1Rvb2x0aXAgPSBpbmplY3QoQVBQX1NIT1dfVE9PTFRJUCwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgaW1hZ2VTZXJ2aWNlOiBJbWFnZVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIHBsYXRmb3JtOiBQbGF0Zm9ybSxcbiAgICBwcm90ZWN0ZWQgYWx0ZXJDdHJsOiBBbGVydENvbnRyb2xsZXIsXG4gICAgcHJvdGVjdGVkIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgY2Q6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoRU5WSVJPTk1FTlQpIGVudmlyb25tZW50PzogRW52aXJvbm1lbnRcbiAgKSB7XG4gICAgdGhpcy52aWV3Q2hhbmdlID0gbmV3IEJlaGF2aW9yU3ViamVjdCh7IHN0YXJ0OiAwLCBlbmQ6IE51bWJlci5NQVhfVkFMVUUgfSk7XG5cbiAgICAvLyBERVYgbG9nXG4gICAgdGhpcy5kZWJ1ZyA9IGVudmlyb25tZW50ICYmICFlbnZpcm9ubWVudC5wcm9kdWN0aW9uO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5tb2JpbGUgPSB0b0Jvb2xlYW4odGhpcy5tb2JpbGUsIGlzTW9iaWxlKHdpbmRvdykpO1xuICAgIHRoaXMubW9kZSA9IHRoaXMubW9kZSA/PyAodGhpcy5tb2JpbGUgPyAnbGlzdCcgOiAnbW9zYWljJyk7XG4gICAgdGhpcy5fY29sU2l6ZSA9IEdhbGxlcnlNb2RlQ29sU2l6ZVt0aGlzLm1vZGVdO1xuICAgIHRoaXMuc2hvd1Rvb2xiYXIgPSB0b0Jvb2xlYW4odGhpcy5zaG93VG9vbGJhciwgIXRoaXMubW9iaWxlKTtcbiAgICB0aGlzLnNob3dDYXJkVG9vbGJhciA9IHRvQm9vbGVhbih0aGlzLnNob3dDYXJkVG9vbGJhciwgIXRoaXMubW9iaWxlKTtcbiAgICB0aGlzLnNob3dBZGRDYXJkQnV0dG9uID0gdG9Cb29sZWFuKHRoaXMuc2hvd0FkZENhcmRCdXR0b24sIHRoaXMubW9iaWxlKTtcbiAgICB0aGlzLnNob3dGYWJCdXR0b24gPSB0b0Jvb2xlYW4odGhpcy5zaG93RmFiQnV0dG9uLCB0aGlzLm1vYmlsZSAmJiAhdGhpcy5zaG93QWRkQ2FyZEJ1dHRvbik7XG4gICAgdGhpcy5zaG93QWRkVG9vbGJhckJ1dHRvbiA9IHRoaXMuc2hvd0FkZFRvb2xiYXJCdXR0b24gPz8gKHRoaXMuc2hvd1Rvb2xiYXIgJiYgIXRoaXMucmVhZE9ubHkpO1xuXG4gICAgLy8gR2V0IG1vZGFsIHByZXNlbnRpbmcgZWxlbWVudCAoaU9TIG9ubHkpXG4gICAgdGhpcy5fcHJlc2VudGluZ0VsZW1lbnQgPSB0aGlzLm1vYmlsZSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5pb24tcGFnZScpIDogbnVsbDtcbiAgfVxuXG4gIG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpIHtcbiAgICBpZiAodGhpcy5kYXRhU291cmNlICYmICF0aGlzLl9yZW5kZXJDaGFuZ2VTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuX29ic2VydmVSZW5kZXJDaGFuZ2VzKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5fZGVzdHJveVN1YmplY3QubmV4dCgpO1xuICAgIHRoaXMuX2Rlc3Ryb3lTdWJqZWN0LmNvbXBsZXRlKCk7XG5cbiAgICB0aGlzLl9zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9zbGlkZXNTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG5cbiAgICBpZiAoaXNEYXRhU291cmNlKHRoaXMuZGF0YVNvdXJjZSkpIHtcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5kaXNjb25uZWN0KHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFkZChcbiAgICBldmVudD86IEV2ZW50LFxuICAgIG9wdHM/OiB7IG1heEhlaWdodD86IG51bWJlcjsgbWF3V2lkdGg/OiBudW1iZXI7IHF1YWxpdHk/OiBudW1iZXI7IG11bHRpcGxlPzogYm9vbGVhbjsgYXV0b0hpZGVEcm9wQXJlYT86IGJvb2xlYW4gfSAmIE9taXQ8XG4gICAgICBJbWFnZU9wdGlvbnMsXG4gICAgICAncmVzdWx0VHlwZSdcbiAgICA+XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGltYWdlcyA9IGF3YWl0IHRoaXMuaW1hZ2VTZXJ2aWNlLmFkZChldmVudCwgb3B0cyk7XG5cbiAgICBpZiAoaXNFbXB0eUFycmF5KGltYWdlcykpIHJldHVybjtcblxuICAgIGNvbnNvbGUuaW5mbyhgW2ltYWdlLWdhbGxlcnldIEFkZGluZyBuZXcgJHtpbWFnZXMubGVuZ3RofSBpbWFnZShzKWAsIGltYWdlcyk7XG5cbiAgICBjb25zdCByb3dzOiBUYWJsZUVsZW1lbnQ8VD5bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaW1hZ2Ugb2YgaW1hZ2VzKSB7XG4gICAgICBjb25zdCByb3cgPSBhd2FpdCB0aGlzLl9kYXRhU291cmNlLmNyZWF0ZU5ldygpO1xuICAgICAgcm93LmN1cnJlbnREYXRhID0gaW1hZ2UgYXMgdW5rbm93biBhcyBUO1xuICAgICAgcm93cy5wdXNoKHJvdyk7XG4gICAgICBjb25zdCBhZGRlZCA9IGF3YWl0IHJvdy5jb25maXJtRWRpdENyZWF0ZSgpO1xuICAgICAgaWYgKCFhZGRlZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1tpbWFnZS1nYWxsZXJ5XSBDYW5ub3QgY29uZmlybSBuZXcgaW1hZ2UhJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMub25BZnRlckFkZFJvd3MuZW1pdChyb3dzKTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZShldmVudDogRXZlbnQsIHJvdzogVGFibGVFbGVtZW50PFQ+LCBvcHRzPzogeyBpbnRlcmFjdGl2ZT86IGJvb2xlYW4gfSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmIChldmVudD8uZGVmYXVsdFByZXZlbnRlZCB8fCB0aGlzLnJlYWRPbmx5KSByZXR1cm4gZmFsc2U7XG4gICAgZXZlbnQ/LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQ/LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgLy8gQ2hlY2sgdXNpbmcgZW1pdHRlclxuICAgIGNvbnN0IGNvbmZpcm1lZCA9IGF3YWl0IHRoaXMuY2FuRGVsZXRlUm93cyhbcm93XSk7XG4gICAgaWYgKCFjb25maXJtZWQpIHJldHVybiBmYWxzZTtcblxuICAgIGxldCBkZWxldGVkOiBib29sZWFuO1xuICAgIGlmIChyb3cuaWQgPT09IC0xKSB7XG4gICAgICBjb25zb2xlLmluZm8oJ1tpbWFnZS1nYWxsZXJ5XSBSZW1vdmluZyBuZXcgaW1hZ2UnKTtcbiAgICAgIGRlbGV0ZWQgPSBhd2FpdCByb3cuY2FuY2VsT3JEZWxldGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5pbmZvKCdbaW1hZ2UtZ2FsbGVyeV0gUmVtb3ZpbmcgaW1hZ2UgKGF0ICMnICsgcm93LmlkICsgJyknKTtcbiAgICAgIGRlbGV0ZWQgPSBhd2FpdCByb3cuZGVsZXRlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlbGV0ZWQ7XG4gIH1cblxuICB0b2dnbGVWaWV3TW9kZShfPzogRXZlbnQpIHtcbiAgICB0aGlzLnNldFZpZXdNb2RlKHRoaXMubW9kZSA9PT0gJ2xpc3QnID8gJ21vc2FpYycgOiAnbGlzdCcpO1xuICB9XG5cbiAgc2V0Vmlld01vZGUobW9kZTogR2FsbGVyeU1vZGUpIHtcbiAgICBpZiAodGhpcy5tb2RlICE9PSBtb2RlKSB7XG4gICAgICB0aGlzLm1vZGUgPSBtb2RlO1xuICAgICAgdGhpcy5fY29sU2l6ZSA9IEdhbGxlcnlNb2RlQ29sU2l6ZVt0aGlzLm1vZGVdO1xuICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICB0cmFja0J5Rm4oaW5kZXg6IG51bWJlciwgcm93OiBUYWJsZUVsZW1lbnQ8VD4pIHtcbiAgICByZXR1cm4gcm93LmlkO1xuICB9XG5cbiAgYXN5bmMgZWRpdFRpdGxlKGV2ZW50OiBNb3VzZUV2ZW50LCByb3c6IFRhYmxlRWxlbWVudDxUPiwgY2FyZFRvb2xiYXI6IGFueSkge1xuICAgIGlmIChldmVudD8uZGVmYXVsdFByZXZlbnRlZCkgcmV0dXJuO1xuICAgIGV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBldmVudD8uc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cbiAgICB0aGlzLmZvY3VzQ2FyZFRvb2xiYXIoY2FyZFRvb2xiYXIpO1xuXG4gICAgY29uc3QgdGl0bGVDb250cm9sID0gbmV3IEZvcm1Db250cm9sKHJvdy5jdXJyZW50RGF0YS50aXRsZSwgVmFsaWRhdG9ycy5jb21wb3NlKFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLm1heExlbmd0aCgyNTUpXSkpO1xuICAgIHRoaXMuX3RpdGxlRm9ybSA9IG5ldyBGb3JtR3JvdXAoeyB0aXRsZTogdGl0bGVDb250cm9sIH0pO1xuICAgIHRoaXMuX3RpdGxlQXV0b2ZvY3VzID0gdGhpcy5tb2JpbGUgJiYgdGhpcy5lbmFibGVkICYmICF0aGlzLnJlYWRPbmx5O1xuICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgYXdhaXQgdGhpcy50aXRsZVBvcG92ZXIucHJlc2VudCgpO1xuXG4gICAgY29uc3QgeyBkYXRhLCByb2xlIH0gPSBhd2FpdCB0aGlzLnRpdGxlUG9wb3Zlci5vbkRpZERpc21pc3MoKTtcblxuICAgIGlmICghcm9sZSB8fCByb2xlICE9PSAnQ0FOQ0VMJykge1xuICAgICAgY29uc29sZS5kZWJ1ZygnW2ltYWdlLWdhbGxlcnldIFVzZXIgc2V0IHRpdGxlOiAnICsgZGF0YSk7XG4gICAgICByb3cuY3VycmVudERhdGEudGl0bGUgPSBkYXRhO1xuICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIHRoaXMub25BZnRlckVkaXRSb3cuZW1pdChyb3cpO1xuICAgIH1cblxuICAgIC8vIEhpZGUgdGhlIHRvb2xiYXIsIGJlY2F1c2UgdGhlIGZvY3VzIGhhdmUgYmVlbiBnaXZlbiB0byB0aGUgZXZlbnQncyBvcmlnaW4gKHRoZSBlZGl0IGJ1dHRvbilcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaGlkZUNhcmRUb29sYmFyKGNhcmRUb29sYmFyKSwgNzUwKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBmb2N1c0NhcmRUb29sYmFyKGNhcmRUb29sYmFyOiBhbnkpIHtcbiAgICBjb25zdCBlbCA9IGNhcmRUb29sYmFyWydlbCddIGFzIEhUTUxFbGVtZW50O1xuICAgIGVsLmNsYXNzTGlzdC5hZGQoJ2ZvY3VzZWQnKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBoaWRlQ2FyZFRvb2xiYXIoY2FyZFRvb2xiYXI6IGFueSkge1xuICAgIGNvbnN0IGVsID0gY2FyZFRvb2xiYXJbJ2VsJ10gYXMgSFRNTEVsZW1lbnQ7XG4gICAgZWwuY2xhc3NMaXN0LnJlbW92ZSgnZm9jdXNlZCcpO1xuICB9XG5cbiAgcHJvdGVjdGVkIF9zd2l0Y2hEYXRhU291cmNlKGRhdGFTb3VyY2U6IFRhYmxlRGF0YVNvdXJjZTxUPikge1xuICAgIGlmIChpc0RhdGFTb3VyY2UodGhpcy5fZGF0YVNvdXJjZSkpIHtcbiAgICAgIHRoaXMuX2RhdGFTb3VyY2UuZGlzY29ubmVjdCh0aGlzKTtcbiAgICB9XG4gICAgdGhpcy5fZGF0YVNvdXJjZSA9IGRhdGFTb3VyY2U7XG4gIH1cblxuICBwcm90ZWN0ZWQgX29ic2VydmVSZW5kZXJDaGFuZ2VzKCkge1xuICAgIC8vIElmIG5vIGRhdGEgc291cmNlIGhhcyBiZWVuIHNldCwgdGhlcmUgaXMgbm90aGluZyB0byBvYnNlcnZlIGZvciBjaGFuZ2VzLlxuICAgIGlmICghdGhpcy5kYXRhU291cmNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBkYXRhU3RyZWFtOiBPYnNlcnZhYmxlPFRhYmxlRWxlbWVudDxUPltdIHwgUmVhZG9ubHlBcnJheTxUYWJsZUVsZW1lbnQ8VD4+PjtcbiAgICBpZiAoaXNEYXRhU291cmNlKHRoaXMuZGF0YVNvdXJjZSkpIHtcbiAgICAgIGRhdGFTdHJlYW0gPSB0aGlzLmRhdGFTb3VyY2UuY29ubmVjdCh0aGlzKTtcbiAgICB9XG4gICAgaWYgKGRhdGFTdHJlYW0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgdGhpcy5nZXRUYWJsZVVua25vd25EYXRhU291cmNlRXJyb3IoKTtcbiAgICB9XG4gICAgdGhpcy5fcmVuZGVyQ2hhbmdlU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX3JlbmRlckNoYW5nZVN1YnNjcmlwdGlvbiA9IGRhdGFTdHJlYW0ucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveVN1YmplY3QpKS5zdWJzY3JpYmUoKGRhdGEpID0+IHtcbiAgICAgIGNvbnNvbGUuZGVidWcoJ1tpbWFnZS1nYWxsZXJ5XSBSZWNlaXZlZCBuZXcgcm93cycsIGRhdGEpO1xuICAgICAgdGhpcy5fZGF0YSQubmV4dChkYXRhKTtcbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VGFibGVVbmtub3duRGF0YVNvdXJjZUVycm9yKCkge1xuICAgIHJldHVybiBFcnJvcihgUHJvdmlkZWQgZGF0YSBzb3VyY2UgZGlkIG5vdCBtYXRjaCBhbiBhcnJheSwgT2JzZXJ2YWJsZSwgb3IgRGF0YVNvdXJjZWApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGNsaWNrUm93KHJvdzogVGFibGVFbGVtZW50PFQ+LCBpbmRleDogbnVtYmVyKSB7XG4gICAgLy8gRGVsZWdhdGUgY2xpY2sgYWN0aW9uXG4gICAgaWYgKHRoaXMuY2xpY2sub2JzZXJ2ZWQpIHtcbiAgICAgIHRoaXMuY2xpY2suZW1pdChyb3cuY3VycmVudERhdGEpO1xuICAgIH1cblxuICAgIC8vIEJ5IGRlZmF1bHQsIG9wZW4gYSB6b29tIG1vZGFsXG4gICAgZWxzZSB7XG4gICAgICB0aGlzLl9zZWxlY3RlZFJvd0luZGV4ID0gaW5kZXg7XG4gICAgICBhd2FpdCB0aGlzLnpvb21Nb2RhbC5wcmVzZW50KCk7XG4gICAgICBhd2FpdCB0aGlzLnpvb21Nb2RhbC5vbkRpZERpc21pc3MoKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYWN0aXZlU2xpZGVJbmRleCA9IDA7XG5cbiAgcHJvdGVjdGVkIGdldFN3aXBlcihzd2lwZXJFbGVtZW50PzogYW55KTogU3dpcGVyIHtcbiAgICB0aGlzLl9zd2lwZXIgPSAoc3dpcGVyRWxlbWVudCB8fCB0aGlzLnN3aXBlclJlZj8ubmF0aXZlRWxlbWVudCk/LnN3aXBlciB8fCB0aGlzLl9zd2lwZXI7XG4gICAgcmV0dXJuIHRoaXMuX3N3aXBlcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblNsaWRlQ2hhbmdlKHN3aXBlckVsZW1lbnQ6IGFueSkge1xuICAgIGNvbnN0IHN3aXBlciA9IHRoaXMuZ2V0U3dpcGVyKHN3aXBlckVsZW1lbnQpO1xuICAgIHRoaXMuYWN0aXZlU2xpZGVJbmRleCA9IHN3aXBlci5hY3RpdmVJbmRleDtcbiAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGluaXRNb2RhbFNsaWRlcyhzd2lwZXJFbGVtZW50OiBhbnkpIHtcbiAgICBpZiAodGhpcy5fc2VsZWN0ZWRSb3dJbmRleCA+IDApIHtcbiAgICAgIGlmICh0aGlzLmRlYnVnKSBjb25zb2xlLmRlYnVnKGBbaW1hZ2UtZ2FsbGVyeV0gSW5pdGlhbGl6aW5nIG1vZGFsLCBzZWxlY3RlZFJvd0luZGV4PSR7dGhpcy5fc2VsZWN0ZWRSb3dJbmRleH1gKTtcbiAgICAgIC8vIFVzZSBhIHNldFRpbWVvdXQgb3RoZXJ3aXNlIHRoZSBzd2lwZXIgY2Fubm90IHNsaWRlXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29uc3Qgc3dpcGVyID0gdGhpcy5nZXRTd2lwZXIoc3dpcGVyRWxlbWVudCk7XG4gICAgICAgIHN3aXBlci5zbGlkZVRvKHRoaXMuX3NlbGVjdGVkUm93SW5kZXgsIDApO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHpvb20oc3dpcGVyRWxlbWVudDogYW55LCB6b29tSW46IGJvb2xlYW4pIHtcbiAgICBpZiAodGhpcy5kZWJ1ZykgY29uc29sZS5kZWJ1ZygnW2ltYWdlLWdhbGxlcnldIHpvb20gJyArICh6b29tSW4gPyAnaW4nIDogJ291dCcpLCBzd2lwZXJFbGVtZW50KTtcbiAgICBjb25zdCBzd2lwZXIgPSB0aGlzLmdldFN3aXBlcihzd2lwZXJFbGVtZW50KTtcbiAgICBjb25zdCB6b29tID0gc3dpcGVyLnpvb207XG4gICAgaWYgKHpvb21Jbikgem9vbS5pbigpO1xuICAgIGVsc2Ugem9vbS5vdXQoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVGcm9tTW9kYWwoZXZlbnQsIHN3aXBlckVsZW1lbnQ6IGFueSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHN3aXBlciA9IHRoaXMuZ2V0U3dpcGVyKHN3aXBlckVsZW1lbnQpO1xuICAgIGNvbnN0IGN1cnJlbnRSb3cgPSB0aGlzLnJvd3MuZmluZCgocm93LCBpbmRleCkgPT4gaW5kZXggPT09IHN3aXBlci5hY3RpdmVJbmRleCk7XG4gICAgaWYgKCFjdXJyZW50Um93KSByZXR1cm4gZmFsc2U7IC8vIFJvdyBub3QgZm91bmRcblxuICAgIGNvbnN0IGRlbGV0ZWQgPSBhd2FpdCB0aGlzLmRlbGV0ZShldmVudCwgY3VycmVudFJvdyk7XG5cbiAgICBpZiAodGhpcy5yb3dzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXdhaXQgdGhpcy56b29tTW9kYWwuZGlzbWlzcygpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBSZXNldCB0aGUgem9vbVxuICAgICAgc3dpcGVyLnpvb20ub3V0KCk7XG4gICAgICBzd2lwZXIudXBkYXRlKCk7XG4gICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgICByZXR1cm4gZGVsZXRlZDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBzbGlkZVByZXYoc3dpcGVyRWxlbWVudDogYW55KSB7XG4gICAgY29uc3Qgc3dpcGVyID0gdGhpcy5nZXRTd2lwZXIoc3dpcGVyRWxlbWVudCk7XG4gICAgY29uc3QgYWN0aXZlSW5kZXggPSBzd2lwZXIuYWN0aXZlSW5kZXg7XG4gICAgaWYgKGFjdGl2ZUluZGV4ID09PSAwKSB7XG4gICAgICAvLyBMb29wIHRvIGxhc3RcbiAgICAgIGF3YWl0IHN3aXBlci5zbGlkZVRvKHRoaXMucm93cy5sZW5ndGggLSAxLCAwIC8qbm8gdHJhbnNpdGlvbiwgdG8gYXZvaWQgYSBcInJldmVydFwiIGVmZmVjdCovKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgc3dpcGVyLnNsaWRlUHJldigpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBzbGlkZU5leHQoc3dpcGVyRWxlbWVudDogYW55KSB7XG4gICAgY29uc3Qgc3dpcGVyID0gdGhpcy5nZXRTd2lwZXIoc3dpcGVyRWxlbWVudCk7XG4gICAgY29uc3QgYWN0aXZlSW5kZXggPSBzd2lwZXIuYWN0aXZlSW5kZXg7XG4gICAgaWYgKGFjdGl2ZUluZGV4ID09PSB0aGlzLnJvd3MubGVuZ3RoIC0gMSkge1xuICAgICAgLy8gTG9vcCB0byBmaXJzdFxuICAgICAgYXdhaXQgc3dpcGVyLnNsaWRlVG8oMCwgMCAvKm5vIHRyYW5zaXRpb24sIHRvIGF2b2lkIGEgXCJyZXZlcnRcIiBlZmZlY3QqLyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHN3aXBlci5zbGlkZU5leHQoKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY2FuRGVsZXRlUm93cyhyb3dzOiBUYWJsZUVsZW1lbnQ8VD5bXSwgb3B0cz86IHsgaW50ZXJhY3RpdmU/OiBib29sZWFuIH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBDaGVjayB1c2luZyBlbWl0dGVyXG4gICAgaWYgKHRoaXMub25CZWZvcmVEZWxldGVSb3dzLm9ic2VydmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjYW5EZWxldGUgPSBhd2FpdCBlbWl0UHJvbWlzZUV2ZW50KHRoaXMub25CZWZvcmVEZWxldGVSb3dzLCAnY2FuRGVsZXRlJywge1xuICAgICAgICAgIGRldGFpbDogeyByb3dzIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWNhbkRlbGV0ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmIChlcnIgPT09ICdDQU5DRUxMRUQnKSByZXR1cm4gZmFsc2U7IC8vIFVzZXIgY2FuY2VsXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHdoaWxlIGNoZWNraW5nIGlmIGNhbiBkZWxldGUgcm93cycsIGVycik7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maXJtQmVmb3JlRGVsZXRlKSB7XG4gICAgICBjb25zdCBjb25maXJtZWQgPSBhd2FpdCBBbGVydHMuYXNrRGVsZXRlQ29uZmlybWF0aW9uKHRoaXMuYWx0ZXJDdHJsLCB0aGlzLnRyYW5zbGF0ZSwgZXZlbnQpO1xuICAgICAgaWYgKCFjb25maXJtZWQpIHJldHVybiBmYWxzZTsgLy8gQ2FuY2VsbGVkXG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0SW1hZ2VTaXplUXVlcnlQYXJhbXMobW9kZT86IEdhbGxlcnlNb2RlIHwgJ21vZGFsJyk6IHsgW2tleTogc3RyaW5nXTogYW55IH0ge1xuICAgIG1vZGUgPSBtb2RlID8/IHRoaXMubW9kZTtcbiAgICBpZiAoIXRoaXMuaW1hZ2VTaXplUXVlcnlQYXJhbSB8fCBpc05pbE9yQmxhbmsodGhpcy5pbWFnZVNpemVzPy5bbW9kZV0pKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBbdGhpcy5pbWFnZVNpemVRdWVyeVBhcmFtXTogdGhpcy5pbWFnZVNpemVzW21vZGVdLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFya0ZvckNoZWNrKCkge1xuICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gIH1cbn1cbiIsIjxpb24tdG9vbGJhciBjb2xvcj1cImxpZ2h0XCIgKm5nSWY9XCJzaG93VG9vbGJhclwiPlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJpb24tYnV0dG9uc1tzbG90PXN0YXJ0XVwiPjwvbmctY29udGVudD5cblxuICA8IS0tIEFkZCAtLT5cbiAgQGlmICghcmVhZE9ubHkgJiYgc2hvd0FkZFRvb2xiYXJCdXR0b24gJiYgZW5hYmxlZCkge1xuICAgIDxidXR0b25cbiAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgW3RpdGxlXT1cIiFzaG93VG9vbHRpcCA/ICgnQ09NTU9OLkJUTl9BREQnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgIFttYXRUb29sdGlwXT1cInNob3dUb29sdGlwID8gKCdDT01NT04uQlROX0FERCcgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgKGNsaWNrKT1cImFkZCgpXCJcbiAgICA+XG4gICAgICA8bWF0LWljb24+YWRkPC9tYXQtaWNvbj5cbiAgICA8L2J1dHRvbj5cbiAgfVxuXG4gIDxuZy1jb250ZW50IHNlbGVjdD1cImlvbi1idXR0b25zW3Nsb3Q9ZW5kXVwiPjwvbmctY29udGVudD5cblxuICA8aW9uLWJ1dHRvbnMgc2xvdD1cImVuZFwiPlxuICAgIDwhLS0gVG9nZ2xlIHZpZXcgbW9kZSAtLT5cbiAgICA8aW9uLXNlZ21lbnQgKGlvbkNoYW5nZSk9XCJ0b2dnbGVWaWV3TW9kZSgkZXZlbnQpXCIgY29sb3I9XCJhY2NlbnRcIiBbdmFsdWVdPVwiX2NvbFNpemVcIj5cbiAgICAgIDxpb24tc2VnbWVudC1idXR0b24gW3ZhbHVlXT1cIjRcIj5cbiAgICAgICAgPG1hdC1pY29uPnZpZXdfbW9kdWxlPC9tYXQtaWNvbj5cbiAgICAgIDwvaW9uLXNlZ21lbnQtYnV0dG9uPlxuICAgICAgPGlvbi1zZWdtZW50LWJ1dHRvbiBbdmFsdWVdPVwiMTJcIj5cbiAgICAgICAgPG1hdC1pY29uPnZpZXdfbGlzdDwvbWF0LWljb24+XG4gICAgICA8L2lvbi1zZWdtZW50LWJ1dHRvbj5cbiAgICA8L2lvbi1zZWdtZW50PlxuICA8L2lvbi1idXR0b25zPlxuPC9pb24tdG9vbGJhcj5cblxuPGRpdiBjbGFzcz1cImdhbGxlcnktY29udGFpbmVyIGlvbi1wYWRkaW5nLWJvdHRvbSB7eyB0aGlzLm1vZGUgfX1cIj5cbiAgPGRpdiAqbmdJZj1cIm1vYmlsZSAmJiB6b29tQWN0aXZlXCIgY2xhc3M9XCJiYWNrZHJvcFwiIFtzdHlsZS5vcGFjaXR5XT1cInpvb21TY2FsZVwiPjwvZGl2PlxuXG4gIDxpb24tZ3JpZCBjbGFzcz1cImlvbi1uby1wYWRkaW5nXCI+XG4gICAgPGlvbi1yb3c+XG4gICAgICA8aW9uLWNvbCAqcnhGb3I9XCJsZXQgcm93IG9mIF9kYXRhJDsgaW5kZXggYXMgaW5kZXg7IHRyYWNrQnk6IHRyYWNrQnlGblwiIFtzaXplXT1cIl9jb2xTaXplXCI+XG4gICAgICAgIEBsZXQgaW1hZ2UgPSByb3cgfCBwcm9wZXJ0eUdldDogJ2N1cnJlbnREYXRhJztcbiAgICAgICAgQGlmIChjYXJkVGVtcGxhdGUpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cImNhcmRUZW1wbGF0ZTsgY29udGV4dDogeyAkaW1wbGljaXQ6IHJvdywgbW9kZTogbW9kZSwgaW1hZ2U6IGltYWdlIH1cIlxuICAgICAgICAgID48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPGlvbi1jYXJkXG4gICAgICAgICAgICAjY2FyZFxuICAgICAgICAgICAgY2xhc3M9XCJpbWFnZS1jYXJkXCJcbiAgICAgICAgICAgIFtjbGFzcy56b29tLWhvdmVyXT1cIiFtb2JpbGVcIlxuICAgICAgICAgICAgW2NvbG9yXT1cImNhcmRDb2xvclwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2xpY2tSb3cocm93LCBpbmRleClcIlxuICAgICAgICAgICAgdGFwcGFibGVcbiAgICAgICAgICAgIEBmYWRlSW5BbmltYXRpb25cbiAgICAgICAgICA+XG4gICAgICAgICAgICA8ZmlndXJlIGNsYXNzPVwiY2FyZC10aHVtYm5haWxcIj5cbiAgICAgICAgICAgICAgQGlmIChpbWFnZS51cmwpIHtcbiAgICAgICAgICAgICAgICA8aW9uLWltZyBbc3JjXT1cImltYWdlLnVybCB8IGFwcGVuZFF1ZXJ5UGFyYW1zOiBnZXRJbWFnZVNpemVRdWVyeVBhcmFtcygpXCIgLz5cbiAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgPGlvbi1pbWcgW3NyY109XCJpbWFnZS5kYXRhVXJsXCIgLz5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9maWd1cmU+XG5cbiAgICAgICAgICAgIDwhLS0gdG9vbGJhciBmb3IgdGl0bGUgKHdoZW4gbm90IGhvdmVyKSAtLT5cbiAgICAgICAgICAgIEBpZiAoc2hvd1RpdGxlICYmIGltYWdlLnRpdGxlKSB7XG4gICAgICAgICAgICAgIDxpb24tdG9vbGJhciBjb2xvcj1cInRyYW5zcGFyZW50XCIgY2xhc3M9XCJ0aXRsZVwiPlxuICAgICAgICAgICAgICAgIDxpb24tbGFiZWwgY2xhc3M9XCJjYXJkLXRpdGxlXCI+e3sgaW1hZ2UudGl0bGUgfX08L2lvbi1sYWJlbD5cbiAgICAgICAgICAgICAgPC9pb24tdG9vbGJhcj5cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgPCEtLSBhY3Rpb24gdG9vbGJhciBzaG93biB3aGVuIGhvdmVyIGltYWdlIC0tPlxuICAgICAgICAgICAgQGlmICghcmVhZE9ubHkgJiYgIW1vYmlsZSAmJiBzaG93Q2FyZFRvb2xiYXIpIHtcbiAgICAgICAgICAgICAgPGlvbi10b29sYmFyICNjYXJkVG9vbGJhciBjb2xvcj1cImxpZ2h0XCIgY2xhc3M9XCJidXR0b25zXCI+XG4gICAgICAgICAgICAgICAgPCEtLSBlZGl0IHRpdGxlIGJ1dHRvbiAtLT5cbiAgICAgICAgICAgICAgICBAaWYgKHNob3dUaXRsZSkge1xuICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIHNsb3Q9XCJzdGFydFwiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJlZGl0VGl0bGUoJGV2ZW50LCByb3csIGNhcmRUb29sYmFyKVwiXG4gICAgICAgICAgICAgICAgICAgIChmb2N1c2luKT1cImZvY3VzQ2FyZFRvb2xiYXIoY2FyZFRvb2xiYXIpXCJcbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmVkaXQ8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwicm93LmN1cnJlbnREYXRhLnRpdGxlIHwgaXNOb3ROaWxPckJsYW5rOyBlbHNlIGVkaXRMYWJlbFwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIElNQUdFLkdBTExFUlkuQlROX0VESVRfVElUTEVcbiAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNlZGl0TGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+SU1BR0UuR0FMTEVSWS5CVE5fQUREX1RJVExFPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgtc3BhY2VyXCI+PC9kaXY+XG5cbiAgICAgICAgICAgICAgICA8IS0tIGRlbGV0ZSBidXR0b24gLS0+XG4gICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgICBzbG90PVwiZW5kXCJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaW9uLWZsb2F0LWVuZFwiXG4gICAgICAgICAgICAgICAgICBbdGl0bGVdPVwiIXNob3dUb29sdGlwID8gKCdDT01NT04uQlROX0RFTEVURScgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgICAgICAgICAgICAgW21hdFRvb2x0aXBdPVwic2hvd1Rvb2x0aXAgPyAoJ0NPTU1PTi5CVE5fREVMRVRFJyB8IHRyYW5zbGF0ZSkgOiAnJ1wiXG4gICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImRlbGV0ZSgkZXZlbnQsIHJvdylcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICA8L2lvbi10b29sYmFyPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvaW9uLWNhcmQ+XG4gICAgICAgIH1cbiAgICAgIDwvaW9uLWNvbD5cblxuICAgICAgPCEtLSBhZGQgYnV0dG9uIC0tPlxuICAgICAgQGlmICgoc2hvd0FkZFRleHRCdXR0b24gfHwgc2hvd0FkZENhcmRCdXR0b24pICYmICFyZWFkT25seSkge1xuICAgICAgICA8aW9uLWNvbCBbc2l6ZV09XCJfY29sU2l6ZVwiIEBmYWRlSW5BbmltYXRpb24+XG4gICAgICAgICAgQGlmIChzaG93QWRkVGV4dEJ1dHRvbikge1xuICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImFkZCgkZXZlbnQpXCIgW2Rpc2FibGVkXT1cImRpc2FibGVkXCIgW2NvbG9yXT1cImFkZEJ1dHRvbkNvbG9yXCI+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWwgdHJhbnNsYXRlPnt7IGFkZEJ1dHRvblRleHQgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlvbi1pY29uIHNsb3Q9XCJlbmRcIiBuYW1lPVwiY2FtZXJhXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICB9IEBlbHNlIGlmIChzaG93QWRkQ2FyZEJ1dHRvbikge1xuICAgICAgICAgICAgPGlvbi1jYXJkXG4gICAgICAgICAgICAgIGNsYXNzPVwiaW1hZ2UtY2FyZC1idXR0b25cIlxuICAgICAgICAgICAgICBjb2xvcj1cImxpZ2h0XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImFkZCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgICAgW3RpdGxlXT1cIiFzaG93VG9vbHRpcCA/IGFkZEJ1dHRvblRleHQgOiAnJ1wiXG4gICAgICAgICAgICAgIFttYXRUb29sdGlwXT1cInNob3dUb29sdGlwID8gYWRkQnV0dG9uVGV4dCA6ICcnXCJcbiAgICAgICAgICAgICAgdGFwcGFibGVcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPGlvbi1jYXJkLWNvbnRlbnQ+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImljb24tY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImNhbWVyYVwiIFtjb2xvcl09XCJhZGRCdXR0b25Db2xvclwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImFkZFwiIFtjb2xvcl09XCJhZGRCdXR0b25Db2xvclwiIGNsYXNzPVwiaWNvbi1zZWNvbmRhcnlcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L2lvbi1jYXJkLWNvbnRlbnQ+XG4gICAgICAgICAgICA8L2lvbi1jYXJkPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9pb24tY29sPlxuICAgICAgfVxuICAgIDwvaW9uLXJvdz5cbiAgPC9pb24tZ3JpZD5cbjwvZGl2PlxuXG48IS0tIEZBQiBidXR0b246IGFkZCAtLT5cbjxpb24tZmFiXG4gIHNsb3Q9XCJmaXhlZFwiXG4gIHZlcnRpY2FsPVwiYm90dG9tXCJcbiAgaG9yaXpvbnRhbD1cImVuZFwiXG4gICpuZ0lmPVwic2hvd0ZhYkJ1dHRvbiAmJiAhcmVhZE9ubHlcIlxuICBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCJkaXNhYmxlZFwiXG4gIEBmYWRlSW5PdXRBbmltYXRpb25cbj5cbiAgPGlvbi1mYWItYnV0dG9uIGNvbG9yPVwidGVydGlhcnlcIiAoY2xpY2spPVwiYWRkKCRldmVudClcIj5cbiAgICA8aW9uLWljb24gbmFtZT1cImNhbWVyYVwiPjwvaW9uLWljb24+XG4gICAgPGlvbi1pY29uIG5hbWU9XCJhZGRcIiBjbGFzcz1cImljb24tc2Vjb25kYXJ5XCIgc3R5bGU9XCJsZWZ0OiAzM3B4OyB0b3A6IDlweDsgZm9udC1zaXplOiAyMHB4XCI+PC9pb24taWNvbj5cbiAgPC9pb24tZmFiLWJ1dHRvbj5cbjwvaW9uLWZhYj5cblxuPCEtLSBab29tIG1vZGFsIC0tPlxuPGlvbi1tb2RhbCAjem9vbU1vZGFsIGNsYXNzPVwic3RhY2stbW9kYWwgem9vbS1tb2RhbFwiIFtjbGFzcy5tb2RhbC1mdWxsc2NyZWVuXT1cIm1vYmlsZVwiIFtjbGFzcy5tb2RhbC1sYXJnZV09XCIhbW9iaWxlXCI+XG4gIDxuZy10ZW1wbGF0ZT5cbiAgICA8aW9uLWNvbnRlbnQgY2xhc3M9XCJpb24tbm8tcGFkZGluZyBpb24tbm8tbWFyZ2luXCI+XG4gICAgICBAbGV0IGNvdW50ID0gcm93cz8ubGVuZ3RoIHx8IDA7XG4gICAgICA8IS0tIENvdW50ZXIgIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInRvcC1sZWZ0XCI+XG4gICAgICAgIDxpb24tbGFiZWwgY29sb3I9XCJsaWdodFwiPnt7IGFjdGl2ZVNsaWRlSW5kZXggKyAxIH19IC8ge3sgY291bnQgfX08L2lvbi1sYWJlbD5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8IS0tIHpvb20gYnV0dG9uIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInRvcC1yaWdodFwiPlxuICAgICAgICBAaWYgKCFtb2JpbGUpIHtcbiAgICAgICAgICA8aW9uLWZhYi1idXR0b24gc2l6ZT1cInNtYWxsXCIgKGNsaWNrKT1cInpvb20obW9kYWxTd2lwZXIsIHRydWUpXCIgY29sb3I9XCJsaWdodFwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJzZWFyY2hcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPGlvbi1pY29uIGNsYXNzPVwiaWNvbi1zZWNvbmRhcnlcIiBuYW1lPVwiYWRkXCI+PC9pb24taWNvbj5cbiAgICAgICAgICA8L2lvbi1mYWItYnV0dG9uPlxuICAgICAgICAgIDxpb24tZmFiLWJ1dHRvbiBzaXplPVwic21hbGxcIiAoY2xpY2spPVwiem9vbShtb2RhbFN3aXBlciwgZmFsc2UpXCIgY29sb3I9XCJsaWdodFwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJzZWFyY2hcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPGlvbi1pY29uIGNsYXNzPVwiaWNvbi1zZWNvbmRhcnlcIiBuYW1lPVwicmVtb3ZlXCI+PC9pb24taWNvbj5cbiAgICAgICAgICA8L2lvbi1mYWItYnV0dG9uPlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBuYXZpZ2F0aW9uIHNpZGUgYnV0dG9ucyBuZXh0L2JhY2sgLS0+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIW1vYmlsZSAmJiAocm93cyB8IGlzQXJyYXlMZW5ndGg6IHsgZ3JlYXRlclRoYW46IDEgfSlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNpZGUtYnV0dG9ucyBwcmV2XCIgKGNsaWNrKT1cInNsaWRlUHJldihtb2RhbFN3aXBlcilcIj5cbiAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImNoZXZyb24tYmFja1wiPjwvaW9uLWljb24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwic2lkZS1idXR0b25zIG5leHRcIiAoY2xpY2spPVwic2xpZGVOZXh0KG1vZGFsU3dpcGVyKVwiPlxuICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwiY2hldnJvbi1mb3J3YXJkXCI+PC9pb24taWNvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBpbWFnZSBzbGlkZXMgLS0+XG4gICAgICA8c3dpcGVyLWNvbnRhaW5lclxuICAgICAgICAjbW9kYWxTd2lwZXJcbiAgICAgICAgW21vZHVsZXNdPVwic3dpcGVyTW9kdWxlc1wiXG4gICAgICAgIFt6b29tXT1cInRydWVcIlxuICAgICAgICAoc3dpcGVyc2xpZGVjaGFuZ2UpPVwib25TbGlkZUNoYW5nZShtb2RhbFN3aXBlcilcIlxuICAgICAgICAoc3dpcGVyaW5pdCk9XCJpbml0TW9kYWxTbGlkZXMobW9kYWxTd2lwZXIpXCJcbiAgICAgID5cbiAgICAgICAgQGZvciAocm93IG9mIHJvd3M7IHRyYWNrIHJvdy5pZDsgbGV0IGxhc3QgPSAkbGFzdCkge1xuICAgICAgICAgIDxzd2lwZXItc2xpZGU+XG4gICAgICAgICAgICBAbGV0IGltYWdlID0gcm93IHwgcHJvcGVydHlHZXQ6ICdjdXJyZW50RGF0YSc7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3dpcGVyLXpvb20tY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgIEBpZiAoaW1hZ2UudXJsKSB7XG4gICAgICAgICAgICAgICAgPGlvbi1pbWcgW3NyY109XCJpbWFnZS51cmwgfCBhcHBlbmRRdWVyeVBhcmFtczogZ2V0SW1hZ2VTaXplUXVlcnlQYXJhbXMoJ21vZGFsJylcIiAvPlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8aW1nIFtzcmNdPVwiaW1hZ2UuZGF0YVVybFwiIFthbHRdPVwiaW1hZ2UudGl0bGVcIiAvPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L3N3aXBlci1zbGlkZT5cbiAgICAgICAgfVxuICAgICAgPC9zd2lwZXItY29udGFpbmVyPlxuICAgIDwvaW9uLWNvbnRlbnQ+XG5cbiAgICA8aW9uLWZvb3Rlcj5cbiAgICAgIDxpb24tdG9vbGJhciBjb2xvcj1cImxpZ2h0XCI+XG4gICAgICAgIDxpb24tcm93PlxuICAgICAgICAgIDxpb24tY29sIHNpemU9XCI0XCIgY2xhc3M9XCJpb24tdGV4dC1zdGFydFwiPlxuICAgICAgICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgICAgICAgKm5nSWY9XCIhcmVhZE9ubHlcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlRnJvbU1vZGFsKCRldmVudCwgbW9kYWxTd2lwZXIpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgICAgZmlsbD1cImNsZWFyXCJcbiAgICAgICAgICAgICAgY29sb3I9XCJkYW5nZXJcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bWF0LWljb24gc2xvdD1cInN0YXJ0XCI+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAge3sgJ0NPTU1PTi5CVE5fREVMRVRFJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgICA8aW9uLWNvbCBzaXplPVwiNFwiPjwvaW9uLWNvbD5cbiAgICAgICAgICA8aW9uLWNvbCBzaXplPVwiNFwiIGNsYXNzPVwiaW9uLXRleHQtZW5kXCI+XG4gICAgICAgICAgICA8aW9uLWJ1dHRvbiAoY2xpY2spPVwiem9vbU1vZGFsLmRpc21pc3MoKVwiIGNvbG9yPVwidGVydGlhcnlcIiBmaWxsPVwiY2xlYXJcIiAqbmdJZj1cIm1vYmlsZTsgZWxzZSBkZXNrdG9wXCI+XG4gICAgICAgICAgICAgIDxpb24taWNvbiBzbG90PVwic3RhcnRcIiBuYW1lPVwiY2xvc2VcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgICB7eyAnQ09NTU9OLkJUTl9DTE9TRScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjZGVza3RvcD5cbiAgICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cInpvb21Nb2RhbC5kaXNtaXNzKClcIiBjb2xvcj1cInRlcnRpYXJ5XCI+XG4gICAgICAgICAgICAgICAge3sgJ0NPTU1PTi5CVE5fQ0xPU0UnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9pb24tY29sPlxuICAgICAgICA8L2lvbi1yb3c+XG4gICAgICA8L2lvbi10b29sYmFyPlxuICAgIDwvaW9uLWZvb3Rlcj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvaW9uLW1vZGFsPlxuXG48aW9uLXBvcG92ZXIgI3RpdGxlUG9wb3Zlcj5cbiAgPG5nLXRlbXBsYXRlPlxuICAgIDxpb24tY29udGVudCBjbGFzcz1cImlvbi1wYWRkaW5nXCIgY2RrVHJhcEZvY3VzIFtjZGtUcmFwRm9jdXNBdXRvQ2FwdHVyZV09XCJ0cnVlXCI+XG4gICAgICA8Zm9ybSBbZm9ybUdyb3VwXT1cIl90aXRsZUZvcm1cIj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGZsb2F0TGFiZWw9XCJhdXRvXCI+XG4gICAgICAgICAgPG1hdC1sYWJlbCB0cmFuc2xhdGU+SU1BR0UuR0FMTEVSWS5USVRMRTwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInRpdGxlXCJcbiAgICAgICAgICAgIFtyZWFkb25seV09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBbYXBwQXV0b2ZvY3VzXT1cIl90aXRsZUF1dG9mb2N1c1wiXG4gICAgICAgICAgICAoa2V5ZG93bi5jb250cm9sLmVudGVyKT1cInRpdGxlUG9wb3Zlci5kaXNtaXNzKF90aXRsZUZvcm0uY29udHJvbHMudGl0bGUudmFsdWUpXCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgPC9mb3JtPlxuICAgIDwvaW9uLWNvbnRlbnQ+XG5cbiAgICA8aW9uLWZvb3Rlcj5cbiAgICAgIDxpb24tdG9vbGJhcj5cbiAgICAgICAgPGlvbi1yb3cgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiIG5vd3JhcD5cbiAgICAgICAgICA8aW9uLWNvbD48L2lvbi1jb2w+XG5cbiAgICAgICAgICA8aW9uLWNvbCBzaXplPVwiYXV0b1wiPlxuICAgICAgICAgICAgPGlvbi1idXR0b24gZmlsbD1cImNsZWFyXCIgY29sb3I9XCJkYXJrXCIgKGNsaWNrKT1cInRpdGxlUG9wb3Zlci5kaXNtaXNzKG51bGwsICdDQU5DRUwnKVwiPlxuICAgICAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5DT01NT04uQlROX0NBTkNFTDwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgICAgICAgW2ZpbGxdPVwiZGlzYWJsZWQgPyAnY2xlYXInIDogJ3NvbGlkJ1wiXG4gICAgICAgICAgICAgIChjbGljayk9XCJ0aXRsZVBvcG92ZXIuZGlzbWlzcyhfdGl0bGVGb3JtLmNvbnRyb2xzLnRpdGxlLnZhbHVlKVwiXG4gICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJ0aXRsZVBvcG92ZXIuZGlzbWlzcyhfdGl0bGVGb3JtLmNvbnRyb2xzLnRpdGxlLnZhbHVlKVwiXG4gICAgICAgICAgICAgIGNvbG9yPVwidGVydGlhcnlcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICBbdGl0bGVdPVwiIXNob3dUb29sdGlwID8gKCdDT01NT04uQlROX1ZBTElEQVRFX1dJVEhfU0hPUlRDVVRfSEVMUCcgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJzaG93VG9vbHRpcCA/ICgnQ09NTU9OLkJUTl9WQUxJREFURV9XSVRIX1NIT1JUQ1VUX0hFTFAnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPGlvbi1sYWJlbCB0cmFuc2xhdGU+Q09NTU9OLkJUTl9WQUxJREFURTwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgPC9pb24tcm93PlxuICAgICAgPC9pb24tdG9vbGJhcj5cbiAgICA8L2lvbi1mb290ZXI+XG4gIDwvbmctdGVtcGxhdGU+XG48L2lvbi1wb3BvdmVyPlxuIl19
452
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2UtZ2FsbGVyeS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3NoYXJlZC9pbWFnZS9nYWxsZXJ5L2ltYWdlLWdhbGxlcnkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvaW1hZ2UvZ2FsbGVyeS9pbWFnZS1nYWxsZXJ5LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBR0wsUUFBUSxFQUNSLE1BQU0sRUFFTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLGVBQWUsRUFBYyxPQUFPLEVBQUUsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRXhFLE9BQU8sRUFBQyxXQUFXLEVBQWMsTUFBTSw0Q0FBNEMsQ0FBQztBQUlwRixPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDekMsT0FBTyxFQUFDLGVBQWUsRUFBRSxrQkFBa0IsRUFBQyxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZGLE9BQU8sRUFBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3RFLE9BQU8sRUFBbUIsWUFBWSxFQUFZLE1BQU0sMEJBQTBCLENBQUM7QUFDbkYsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3pDLE9BQU8sRUFBQyxNQUFNLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFHcEMsT0FBTyxFQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEUsT0FBTyxFQUFDLHlCQUF5QixFQUFFLGdCQUFnQixFQUFlLE1BQU0sY0FB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Z0JBQWdCLEVBQUU7Z0JBRUUsVUFBVTtzQkFBakQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFFN0IsaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFFRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUVPLFVBQVU7c0JBQXRCLEtBQUs7Z0JBb0JrQixTQUFTO3NCQUFoQyxTQUFTO3VCQUFDLFdBQVc7Z0JBQ0ssWUFBWTtzQkFBdEMsU0FBUzt1QkFBQyxjQUFjO2dCQUVmLGtCQUFrQjtzQkFBM0IsTUFBTTtnQkFDRyxjQUFjO3NCQUF2QixNQUFNO2dCQUNHLGNBQWM7c0JBQXZCLE1BQU07Z0JBQ0csZ0JBQWdCO3NCQUF6QixNQUFNO2dCQUNHLEtBQUs7c0JBQWQsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudENoZWNrZWQsXG4gIGJvb2xlYW5BdHRyaWJ1dGUsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIFN1YmplY3QsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1RhYmxlRGF0YVNvdXJjZSwgVGFibGVFbGVtZW50fSBmcm9tICdAZS1pcy9uZ3gtbWF0ZXJpYWwtdGFibGUnO1xuaW1wb3J0IHtFTlZJUk9OTUVOVCwgRW52aXJvbm1lbnR9IGZyb20gJy4uLy4uLy4uLy4uL2Vudmlyb25tZW50cy9lbnZpcm9ubWVudC5jbGFzcyc7XG5pbXBvcnQge0ltYWdlU2VydmljZX0gZnJvbSAnLi4vaW1hZ2Uuc2VydmljZSc7XG5pbXBvcnQge0ltYWdlLCBJbWFnZVNpemV9IGZyb20gJy4uL2ltYWdlLm1vZGVsJztcbmltcG9ydCB7QWxlcnRDb250cm9sbGVyLCBJb25Nb2RhbCwgSW9uUG9wb3ZlciwgUGxhdGZvcm19IGZyb20gJ0Bpb25pYy9hbmd1bGFyJztcbmltcG9ydCB7aXNNb2JpbGV9IGZyb20gJy4uLy4uL3BsYXRmb3Jtcyc7XG5pbXBvcnQge2ZhZGVJbkFuaW1hdGlvbiwgZmFkZUluT3V0QW5pbWF0aW9ufSBmcm9tICcuLi8uLi9tYXRlcmlhbC9tYXRlcmlhbC5hbmltYXRpb25zJztcbmltcG9ydCB7aXNFbXB0eUFycmF5LCBpc05pbE9yQmxhbmssIHRvQm9vbGVhbn0gZnJvbSAnLi4vLi4vZnVuY3Rpb25zJztcbmltcG9ydCB7Q29sbGVjdGlvblZpZXdlciwgaXNEYXRhU291cmNlLCBMaXN0UmFuZ2V9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQge3Rha2VVbnRpbH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtBbGVydHN9IGZyb20gJy4uLy4uL2FsZXJ0cyc7XG5pbXBvcnQge1RyYW5zbGF0ZVNlcnZpY2V9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHtBcHBDb2xvcnN9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7Rm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9yc30gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtjcmVhdGVQcm9taXNlRXZlbnRFbWl0dGVyLCBlbWl0UHJvbWlzZUV2ZW50LCBQcm9taXNlRXZlbnR9IGZyb20gJy4uLy4uL2V2ZW50cyc7XG5pbXBvcnQge1ByZWRlZmluZWRDb2xvcnN9IGZyb20gJ0Bpb25pYy9jb3JlJztcbmltcG9ydCB7SW1hZ2VPcHRpb25zfSBmcm9tICdAY2FwYWNpdG9yL2NhbWVyYSc7XG5cbmltcG9ydCB7QVBQX1NIT1dfVE9PTFRJUH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzJztcbmltcG9ydCB7R2FsbGVyeU1vZGUsIEltYWdlRWRpdEV2ZW50LCBJbWFnZUV4cG9ydEZvcm1hdH0gZnJvbSAnLi9pbWFnZS1nYWxsZXJ5Lm1vZGVsJztcblxuZXhwb3J0IHR5cGUgSW1hZ2VHYWxsZXJ5Wm9vbVByZXNlbnRhdGlvbiA9ICdtb2RhbCcgfCAnaW5saW5lJztcblxuY29uc3QgR2FsbGVyeU1vZGVDb2xTaXplID0gT2JqZWN0LmZyZWV6ZSh7XG4gIG1vc2FpYzogNCxcbiAgbGlzdDogMTIsXG59KTtcblxuZXhwb3J0IGludGVyZmFjZSBJbWFnZUdhbGxlcnlTaXplcyB7XG4gIG1vc2FpYzogSW1hZ2VTaXplIHwgc3RyaW5nO1xuICBsaXN0OiBJbWFnZVNpemUgfCBzdHJpbmc7XG4gIG1vZGFsOiBJbWFnZVNpemUgfCBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1pbWFnZS1nYWxsZXJ5JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2ltYWdlLWdhbGxlcnkuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9pbWFnZS1nYWxsZXJ5LmNvbXBvbmVudC5zY3NzJ10sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5BbmltYXRpb24sIGZhZGVJbk91dEFuaW1hdGlvbl0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBBcHBJbWFnZUdhbGxlcnlDb21wb25lbnQ8VCBleHRlbmRzIEltYWdlPiBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBDb2xsZWN0aW9uVmlld2VyLCBBZnRlckNvbnRlbnRDaGVja2VkIHtcbiAgcHJvdGVjdGVkIF9kZXN0cm95U3ViamVjdCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByb3RlY3RlZCBfcmVuZGVyQ2hhbmdlU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG4gIHByb3RlY3RlZCBfc3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICBwcm90ZWN0ZWQgX2RhdGFTb3VyY2U6IFRhYmxlRGF0YVNvdXJjZTxUPjtcbiAgcHJvdGVjdGVkIF9kYXRhJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8VGFibGVFbGVtZW50PFQ+W10gfCBSZWFkb25seUFycmF5PFRhYmxlRWxlbWVudDxUPj4+KG51bGwpO1xuXG4gIHByb3RlY3RlZCBfY29sU2l6ZTogbnVtYmVyO1xuICBwcm90ZWN0ZWQgX3NlbGVjdGVkUm93SW5kZXg6IG51bWJlcjtcbiAgcHJvdGVjdGVkIF9wcmVzZW50aW5nRWxlbWVudDogRWxlbWVudCA9IG51bGw7XG4gIHByb3RlY3RlZCBfdGl0bGVGb3JtOiBGb3JtR3JvdXA7XG4gIHByb3RlY3RlZCBfdGl0bGVBdXRvZm9jdXMgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIF9zbGlkZXNTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuICBwcm90ZWN0ZWQgem9vbUFjdGl2ZSA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgem9vbVNjYWxlID0gMTtcbiAgcHJvdGVjdGVkIF9tb3VzZVpvb21FbmFibGVkID0gZmFsc2U7XG4gIHByb3RlY3RlZCBfcm90YXRpb25FbmFibGVkID0gZmFsc2U7XG4gIHByb3RlY3RlZCBfY3JvcEVuYWJsZWQgPSBmYWxzZTtcbiAgLyoqIFdoZXRoZXIgdGhlIGlubGluZSBzbGlkZXNob3cgb3ZlcmxheSBpcyBjdXJyZW50bHkgc2hvd24gKG9ubHkgcmVsZXZhbnQgd2hlbiB6b29tUHJlc2VudGF0aW9uID09PSAnaW5saW5lJykuICovXG4gIHByb3RlY3RlZCBfaW5saW5lU2xpZGVzaG93QWN0aXZlID0gZmFsc2U7XG5cbiAgdmlld0NoYW5nZTogQmVoYXZpb3JTdWJqZWN0PExpc3RSYW5nZT47XG5cbiAgQElucHV0KCkgY2FyZENvbG9yOiBzdHJpbmcgfCBQcmVkZWZpbmVkQ29sb3JzO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgZGVidWc6IGJvb2xlYW4gPSBudWxsO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgZGlzYWJsZWQgPSBmYWxzZTtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHJlYWRPbmx5ID0gZmFsc2U7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBtb2JpbGU6IGJvb2xlYW4gPSBudWxsO1xuICBASW5wdXQoKSBtb2RlOiBHYWxsZXJ5TW9kZSA9IG51bGw7XG4gIEBJbnB1dCgpIGNvbmZpcm1CZWZvcmVEZWxldGUgPSB0cnVlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd1Rvb2xiYXIgPSB0cnVlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd0ZhYkJ1dHRvbjogYm9vbGVhbjtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHNob3dUaXRsZSA9IHRydWU7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzaG93QWRkVG9vbGJhckJ1dHRvbjogYm9vbGVhbjtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHNob3dBZGRUZXh0QnV0dG9uID0gZmFsc2U7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzaG93QWRkQ2FyZEJ1dHRvbiA9IHRydWU7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzaG93Q2FyZFRvb2xiYXIgPSB0cnVlO1xuICBASW5wdXQoKSBhZGRCdXR0b25Db2xvcjogQXBwQ29sb3JzID0gJ3RlcnRpYXJ5JztcbiAgQElucHV0KCkgYWRkQnV0dG9uVGV4dDogc3RyaW5nID0gJ0NPTU1PTi5CVE5fQUREJztcbiAgQElucHV0KCkgY2FyZFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjx7ICRpbXBsaWNpdDogVGFibGVFbGVtZW50PFQ+OyBpbWFnZTogVDsgbW9kZTogR2FsbGVyeU1vZGUgfT47XG4gIEBJbnB1dCgpIGltYWdlU2l6ZXM6IEltYWdlR2FsbGVyeVNpemVzID0ge1xuICAgIG1vc2FpYzogPEltYWdlU2l6ZT4nc21hbGwnLFxuICAgIGxpc3Q6IDxJbWFnZVNpemU+J21lZGl1bScsXG4gICAgbW9kYWw6IDxJbWFnZVNpemU+J2xhcmdlJyxcbiAgfTtcbiAgQElucHV0KCkgaW1hZ2VTaXplUXVlcnlQYXJhbSA9ICdzaXplJztcblxuICAvKiogRW5hYmxlIG1vdXNlLXdoZWVsIHpvb20gYW5kIG1vdXNlLWRyYWcgcGFuIGluIHRoZSBzbGlkZXNob3cgKGRlZmF1bHRzIHRvIHRydWUgb24gZGVza3RvcCkuICovXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBlbmFibGVNb3VzZVpvb206IGJvb2xlYW4gPSBudWxsO1xuICAvKiogWm9vbSBzdGVwIGFwcGxpZWQgb24gZWFjaCBtb3VzZS13aGVlbCB0aWNrIChkZWZhdWx0IDAuMykuICovXG4gIEBJbnB1dCgpIHdoZWVsWm9vbVN0ZXAgPSAwLjM7XG4gIC8qKiBNYXhpbXVtIHpvb20gcmF0aW8gcmVhY2hhYmxlIHZpYSBtb3VzZSB3aGVlbCAoZGVmYXVsdCAzKS4gKi9cbiAgQElucHV0KCkgbWF4Wm9vbVJhdGlvID0gMztcbiAgLyoqIEVuYWJsZSA5MMKwIHJvdGF0aW9uIGJ1dHRvbnMgaW4gdGhlIHNsaWRlc2hvdyAoZGVmYXVsdHMgdG8gdHJ1ZSkuICovXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBlbmFibGVSb3RhdGlvbjogYm9vbGVhbiA9IG51bGw7XG4gIC8qKiBFbmFibGUgdGhlIGNyb3AgdG9vbCBpbiB0aGUgc2xpZGVzaG93IChkZWZhdWx0cyB0byB0cnVlKS4gKi9cbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIGVuYWJsZUNyb3A6IGJvb2xlYW4gPSBudWxsO1xuICAvKiogSW1hZ2UgZm9ybWF0IHVzZWQgd2hlbiBlbWl0dGluZyB0aGUgZWRpdGVkIChjcm9wcGVkL3JvdGF0ZWQpIGltYWdlLiAqL1xuICBASW5wdXQoKSBpbWFnZUV4cG9ydEZvcm1hdDogSW1hZ2VFeHBvcnRGb3JtYXQgPSAncG5nJztcbiAgLyoqIEV4cG9ydCBxdWFsaXR5LCBhcHBsaWVkIG9ubHkgd2hlbiBpbWFnZUV4cG9ydEZvcm1hdCBpcyAnanBlZycgKDAgdG8gMSkuICovXG4gIEBJbnB1dCgpIGltYWdlRXhwb3J0UXVhbGl0eSA9IDAuOTI7XG4gIC8qKiBXaGVyZSB0byBzaG93IHRoZSBzbGlkZXNob3c6IGluIGEgZnVsbC1zY3JlZW4gbW9kYWwgKGRlZmF1bHQpLCBvciBpbmxpbmUsIGFzIGFuIG92ZXJsYXkgb3ZlciB0aGUgZ2FsbGVyeSBpdHNlbGYgKGRlc2t0b3Agb25seSkuICovXG4gIEBJbnB1dCgpIHpvb21QcmVzZW50YXRpb246IEltYWdlR2FsbGVyeVpvb21QcmVzZW50YXRpb24gPSAnaW5saW5lJztcbiAgLyoqIEhlaWdodCBvZiB0aGUgaW5saW5lIHNsaWRlc2hvdyBvdmVybGF5IChDU1MgdmFsdWUsIGUuZy4gJzYwdmgnKS4gT25seSB1c2VkIHdoZW4gem9vbVByZXNlbnRhdGlvbiBpcyAnaW5saW5lJy4gKi9cbiAgQElucHV0KCkgaW5saW5lWm9vbUhlaWdodCA9ICc2MHZoJztcblxuICBASW5wdXQoKSBzZXQgZGF0YVNvdXJjZShkYXRhU291cmNlOiBUYWJsZURhdGFTb3VyY2U8VCwgYW55LCBhbnksIGFueT4pIHtcbiAgICBpZiAodGhpcy5fZGF0YVNvdXJjZSAhPT0gZGF0YVNvdXJjZSkge1xuICAgICAgdGhpcy5fc3dpdGNoRGF0YVNvdXJjZShkYXRhU291cmNlKTtcbiAgICB9XG4gIH1cbiAgZ2V0IGRhdGFTb3VyY2UoKTogVGFibGVEYXRhU291cmNlPFQsIGFueSwgYW55LCBhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YVNvdXJjZTtcbiAgfVxuICBnZXQgZW5hYmxlZCgpIHtcbiAgICByZXR1cm4gIXRoaXMuZGlzYWJsZWQ7XG4gIH1cblxuICBnZXQgcm93cygpOiBUYWJsZUVsZW1lbnQ8VD5bXSB8IFJlYWRvbmx5QXJyYXk8VGFibGVFbGVtZW50PFQ+PiB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGEkLnZhbHVlO1xuICB9XG5cbiAgZ2V0IHJvd0NvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnJvd3M/Lmxlbmd0aCB8fCAwO1xuICB9XG5cbiAgQFZpZXdDaGlsZCgnem9vbU1vZGFsJykgem9vbU1vZGFsOiBJb25Nb2RhbDtcbiAgQFZpZXdDaGlsZCgndGl0bGVQb3BvdmVyJykgdGl0bGVQb3BvdmVyOiBJb25Qb3BvdmVyO1xuXG4gIEBPdXRwdXQoKSBvbkJlZm9yZURlbGV0ZVJvd3MgPSBjcmVhdGVQcm9taXNlRXZlbnRFbWl0dGVyPGJvb2xlYW4sIHsgcm93czogVGFibGVFbGVtZW50PFQ+W10gfT4oKTtcbiAgQE91dHB1dCgpIG9uQWZ0ZXJBZGRSb3dzID0gbmV3IEV2ZW50RW1pdHRlcjxUYWJsZUVsZW1lbnQ8VD5bXT4oKTtcbiAgQE91dHB1dCgpIG9uQWZ0ZXJFZGl0Um93ID0gbmV3IEV2ZW50RW1pdHRlcjxUYWJsZUVsZW1lbnQ8VD4+KCk7XG4gIEBPdXRwdXQoKSBvbkFmdGVyRWRpdEltYWdlID0gbmV3IEV2ZW50RW1pdHRlcjxJbWFnZUVkaXRFdmVudDxUPj4oKTtcbiAgQE91dHB1dCgpIGNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxUPigpO1xuXG4gIHNob3dUb29sdGlwID0gaW5qZWN0KEFQUF9TSE9XX1RPT0xUSVAsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIGltYWdlU2VydmljZTogSW1hZ2VTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBwbGF0Zm9ybTogUGxhdGZvcm0sXG4gICAgcHJvdGVjdGVkIGFsdGVyQ3RybDogQWxlcnRDb250cm9sbGVyLFxuICAgIHByb3RlY3RlZCB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KEVOVklST05NRU5UKSBlbnZpcm9ubWVudD86IEVudmlyb25tZW50XG4gICkge1xuICAgIHRoaXMudmlld0NoYW5nZSA9IG5ldyBCZWhhdmlvclN1YmplY3QoeyBzdGFydDogMCwgZW5kOiBOdW1iZXIuTUFYX1ZBTFVFIH0pO1xuXG4gICAgLy8gREVWIGxvZ1xuICAgIHRoaXMuZGVidWcgPSBlbnZpcm9ubWVudCAmJiAhZW52aXJvbm1lbnQucHJvZHVjdGlvbjtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMubW9iaWxlID0gdG9Cb29sZWFuKHRoaXMubW9iaWxlLCBpc01vYmlsZSh3aW5kb3cpKTtcbiAgICB0aGlzLm1vZGUgPSB0aGlzLm1vZGUgPz8gKHRoaXMubW9iaWxlID8gJ2xpc3QnIDogJ21vc2FpYycpO1xuICAgIHRoaXMuX2NvbFNpemUgPSBHYWxsZXJ5TW9kZUNvbFNpemVbdGhpcy5tb2RlXTtcbiAgICB0aGlzLnNob3dUb29sYmFyID0gdG9Cb29sZWFuKHRoaXMuc2hvd1Rvb2xiYXIsICF0aGlzLm1vYmlsZSk7XG4gICAgdGhpcy5zaG93Q2FyZFRvb2xiYXIgPSB0b0Jvb2xlYW4odGhpcy5zaG93Q2FyZFRvb2xiYXIsICF0aGlzLm1vYmlsZSk7XG4gICAgdGhpcy5zaG93QWRkQ2FyZEJ1dHRvbiA9IHRvQm9vbGVhbih0aGlzLnNob3dBZGRDYXJkQnV0dG9uLCB0aGlzLm1vYmlsZSk7XG4gICAgdGhpcy5zaG93RmFiQnV0dG9uID0gdG9Cb29sZWFuKHRoaXMuc2hvd0ZhYkJ1dHRvbiwgdGhpcy5tb2JpbGUgJiYgIXRoaXMuc2hvd0FkZENhcmRCdXR0b24pO1xuICAgIHRoaXMuc2hvd0FkZFRvb2xiYXJCdXR0b24gPSB0aGlzLnNob3dBZGRUb29sYmFyQnV0dG9uID8/ICh0aGlzLnNob3dUb29sYmFyICYmICF0aGlzLnJlYWRPbmx5KTtcbiAgICB0aGlzLl9tb3VzZVpvb21FbmFibGVkID0gdG9Cb29sZWFuKHRoaXMuZW5hYmxlTW91c2Vab29tLCAhdGhpcy5tb2JpbGUpO1xuICAgIHRoaXMuX3JvdGF0aW9uRW5hYmxlZCA9IHRvQm9vbGVhbih0aGlzLmVuYWJsZVJvdGF0aW9uLCB0cnVlKTtcbiAgICB0aGlzLl9jcm9wRW5hYmxlZCA9IHRvQm9vbGVhbih0aGlzLmVuYWJsZUNyb3AsIHRydWUpO1xuICAgIC8vIFRoZSBpbmxpbmUgcHJlc2VudGF0aW9uIGlzIG9ubHkgbWVhbmluZ2Z1bCBvbiBkZXNrdG9wOiB0aGVyZSBpcyBubyBcInJlc3Qgb2YgdGhlIHBhZ2VcIiB3b3J0aFxuICAgIC8vIHByZXNlcnZpbmcgb24gYSBzbWFsbCBtb2JpbGUgc2NyZWVuLCBhbmQgdGhlIGZ1bGxzY3JlZW4gbW9kYWwgYWxyZWFkeSB3b3JrcyB3ZWxsIHRoZXJlLlxuICAgIGlmICh0aGlzLm1vYmlsZSkgdGhpcy56b29tUHJlc2VudGF0aW9uID0gJ21vZGFsJztcblxuICAgIC8vIEdldCBtb2RhbCBwcmVzZW50aW5nIGVsZW1lbnQgKGlPUyBvbmx5KVxuICAgIHRoaXMuX3ByZXNlbnRpbmdFbGVtZW50ID0gdGhpcy5tb2JpbGUgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcuaW9uLXBhZ2UnKSA6IG51bGw7XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudENoZWNrZWQoKSB7XG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSAmJiAhdGhpcy5fcmVuZGVyQ2hhbmdlU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlUmVuZGVyQ2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuX2Rlc3Ryb3lTdWJqZWN0Lm5leHQoKTtcbiAgICB0aGlzLl9kZXN0cm95U3ViamVjdC5jb21wbGV0ZSgpO1xuXG4gICAgdGhpcy5fc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fc2xpZGVzU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuXG4gICAgaWYgKGlzRGF0YVNvdXJjZSh0aGlzLmRhdGFTb3VyY2UpKSB7XG4gICAgICB0aGlzLmRhdGFTb3VyY2UuZGlzY29ubmVjdCh0aGlzKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhZGQoXG4gICAgZXZlbnQ/OiBFdmVudCxcbiAgICBvcHRzPzogeyBtYXhIZWlnaHQ/OiBudW1iZXI7IG1hd1dpZHRoPzogbnVtYmVyOyBxdWFsaXR5PzogbnVtYmVyOyBtdWx0aXBsZT86IGJvb2xlYW47IGF1dG9IaWRlRHJvcEFyZWE/OiBib29sZWFuIH0gJiBPbWl0PFxuICAgICAgSW1hZ2VPcHRpb25zLFxuICAgICAgJ3Jlc3VsdFR5cGUnXG4gICAgPlxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBpbWFnZXMgPSBhd2FpdCB0aGlzLmltYWdlU2VydmljZS5hZGQoZXZlbnQsIG9wdHMpO1xuXG4gICAgaWYgKGlzRW1wdHlBcnJheShpbWFnZXMpKSByZXR1cm47XG5cbiAgICBjb25zb2xlLmluZm8oYFtpbWFnZS1nYWxsZXJ5XSBBZGRpbmcgbmV3ICR7aW1hZ2VzLmxlbmd0aH0gaW1hZ2UocylgLCBpbWFnZXMpO1xuXG4gICAgY29uc3Qgcm93czogVGFibGVFbGVtZW50PFQ+W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGltYWdlIG9mIGltYWdlcykge1xuICAgICAgY29uc3Qgcm93ID0gYXdhaXQgdGhpcy5fZGF0YVNvdXJjZS5jcmVhdGVOZXcoKTtcbiAgICAgIHJvdy5jdXJyZW50RGF0YSA9IGltYWdlIGFzIHVua25vd24gYXMgVDtcbiAgICAgIHJvd3MucHVzaChyb3cpO1xuICAgICAgY29uc3QgYWRkZWQgPSBhd2FpdCByb3cuY29uZmlybUVkaXRDcmVhdGUoKTtcbiAgICAgIGlmICghYWRkZWQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdbaW1hZ2UtZ2FsbGVyeV0gQ2Fubm90IGNvbmZpcm0gbmV3IGltYWdlIScpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLm9uQWZ0ZXJBZGRSb3dzLmVtaXQocm93cyk7XG4gIH1cblxuICBhc3luYyBkZWxldGUoZXZlbnQ6IEV2ZW50LCByb3c6IFRhYmxlRWxlbWVudDxUPiwgb3B0cz86IHsgaW50ZXJhY3RpdmU/OiBib29sZWFuIH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoZXZlbnQ/LmRlZmF1bHRQcmV2ZW50ZWQgfHwgdGhpcy5yZWFkT25seSkgcmV0dXJuIGZhbHNlO1xuICAgIGV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIENoZWNrIHVzaW5nIGVtaXR0ZXJcbiAgICBjb25zdCBjb25maXJtZWQgPSBhd2FpdCB0aGlzLmNhbkRlbGV0ZVJvd3MoW3Jvd10pO1xuICAgIGlmICghY29uZmlybWVkKSByZXR1cm4gZmFsc2U7XG5cbiAgICBsZXQgZGVsZXRlZDogYm9vbGVhbjtcbiAgICBpZiAocm93LmlkID09PSAtMSkge1xuICAgICAgY29uc29sZS5pbmZvKCdbaW1hZ2UtZ2FsbGVyeV0gUmVtb3ZpbmcgbmV3IGltYWdlJyk7XG4gICAgICBkZWxldGVkID0gYXdhaXQgcm93LmNhbmNlbE9yRGVsZXRlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuaW5mbygnW2ltYWdlLWdhbGxlcnldIFJlbW92aW5nIGltYWdlIChhdCAjJyArIHJvdy5pZCArICcpJyk7XG4gICAgICBkZWxldGVkID0gYXdhaXQgcm93LmRlbGV0ZSgpO1xuICAgIH1cblxuICAgIHJldHVybiBkZWxldGVkO1xuICB9XG5cbiAgdG9nZ2xlVmlld01vZGUoXz86IEV2ZW50KSB7XG4gICAgdGhpcy5zZXRWaWV3TW9kZSh0aGlzLm1vZGUgPT09ICdsaXN0JyA/ICdtb3NhaWMnIDogJ2xpc3QnKTtcbiAgfVxuXG4gIHNldFZpZXdNb2RlKG1vZGU6IEdhbGxlcnlNb2RlKSB7XG4gICAgaWYgKHRoaXMubW9kZSAhPT0gbW9kZSkge1xuICAgICAgdGhpcy5tb2RlID0gbW9kZTtcbiAgICAgIHRoaXMuX2NvbFNpemUgPSBHYWxsZXJ5TW9kZUNvbFNpemVbdGhpcy5tb2RlXTtcbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuICB9XG5cbiAgdHJhY2tCeUZuKGluZGV4OiBudW1iZXIsIHJvdzogVGFibGVFbGVtZW50PFQ+KSB7XG4gICAgcmV0dXJuIHJvdy5pZDtcbiAgfVxuXG4gIGFzeW5jIGVkaXRUaXRsZShldmVudDogTW91c2VFdmVudCwgcm93OiBUYWJsZUVsZW1lbnQ8VD4sIGNhcmRUb29sYmFyOiBhbnkpIHtcbiAgICBpZiAoZXZlbnQ/LmRlZmF1bHRQcmV2ZW50ZWQpIHJldHVybjtcbiAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudD8uc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgZXZlbnQ/LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXG4gICAgdGhpcy5mb2N1c0NhcmRUb29sYmFyKGNhcmRUb29sYmFyKTtcblxuICAgIGNvbnN0IHRpdGxlQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbChyb3cuY3VycmVudERhdGEudGl0bGUsIFZhbGlkYXRvcnMuY29tcG9zZShbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5tYXhMZW5ndGgoMjU1KV0pKTtcbiAgICB0aGlzLl90aXRsZUZvcm0gPSBuZXcgRm9ybUdyb3VwKHsgdGl0bGU6IHRpdGxlQ29udHJvbCB9KTtcbiAgICB0aGlzLl90aXRsZUF1dG9mb2N1cyA9IHRoaXMubW9iaWxlICYmIHRoaXMuZW5hYmxlZCAmJiAhdGhpcy5yZWFkT25seTtcbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcblxuICAgIGF3YWl0IHRoaXMudGl0bGVQb3BvdmVyLnByZXNlbnQoKTtcblxuICAgIGNvbnN0IHsgZGF0YSwgcm9sZSB9ID0gYXdhaXQgdGhpcy50aXRsZVBvcG92ZXIub25EaWREaXNtaXNzKCk7XG5cbiAgICBpZiAoIXJvbGUgfHwgcm9sZSAhPT0gJ0NBTkNFTCcpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoJ1tpbWFnZS1nYWxsZXJ5XSBVc2VyIHNldCB0aXRsZTogJyArIGRhdGEpO1xuICAgICAgcm93LmN1cnJlbnREYXRhLnRpdGxlID0gZGF0YTtcbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgICB0aGlzLm9uQWZ0ZXJFZGl0Um93LmVtaXQocm93KTtcbiAgICB9XG5cbiAgICAvLyBIaWRlIHRoZSB0b29sYmFyLCBiZWNhdXNlIHRoZSBmb2N1cyBoYXZlIGJlZW4gZ2l2ZW4gdG8gdGhlIGV2ZW50J3Mgb3JpZ2luICh0aGUgZWRpdCBidXR0b24pXG4gICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmhpZGVDYXJkVG9vbGJhcihjYXJkVG9vbGJhciksIDc1MCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZm9jdXNDYXJkVG9vbGJhcihjYXJkVG9vbGJhcjogYW55KSB7XG4gICAgY29uc3QgZWwgPSBjYXJkVG9vbGJhclsnZWwnXSBhcyBIVE1MRWxlbWVudDtcbiAgICBlbC5jbGFzc0xpc3QuYWRkKCdmb2N1c2VkJyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGlkZUNhcmRUb29sYmFyKGNhcmRUb29sYmFyOiBhbnkpIHtcbiAgICBjb25zdCBlbCA9IGNhcmRUb29sYmFyWydlbCddIGFzIEhUTUxFbGVtZW50O1xuICAgIGVsLmNsYXNzTGlzdC5yZW1vdmUoJ2ZvY3VzZWQnKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfc3dpdGNoRGF0YVNvdXJjZShkYXRhU291cmNlOiBUYWJsZURhdGFTb3VyY2U8VD4pIHtcbiAgICBpZiAoaXNEYXRhU291cmNlKHRoaXMuX2RhdGFTb3VyY2UpKSB7XG4gICAgICB0aGlzLl9kYXRhU291cmNlLmRpc2Nvbm5lY3QodGhpcyk7XG4gICAgfVxuICAgIHRoaXMuX2RhdGFTb3VyY2UgPSBkYXRhU291cmNlO1xuICB9XG5cbiAgcHJvdGVjdGVkIF9vYnNlcnZlUmVuZGVyQ2hhbmdlcygpIHtcbiAgICAvLyBJZiBubyBkYXRhIHNvdXJjZSBoYXMgYmVlbiBzZXQsIHRoZXJlIGlzIG5vdGhpbmcgdG8gb2JzZXJ2ZSBmb3IgY2hhbmdlcy5cbiAgICBpZiAoIXRoaXMuZGF0YVNvdXJjZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgZGF0YVN0cmVhbTogT2JzZXJ2YWJsZTxUYWJsZUVsZW1lbnQ8VD5bXSB8IFJlYWRvbmx5QXJyYXk8VGFibGVFbGVtZW50PFQ+Pj47XG4gICAgaWYgKGlzRGF0YVNvdXJjZSh0aGlzLmRhdGFTb3VyY2UpKSB7XG4gICAgICBkYXRhU3RyZWFtID0gdGhpcy5kYXRhU291cmNlLmNvbm5lY3QodGhpcyk7XG4gICAgfVxuICAgIGlmIChkYXRhU3RyZWFtID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IHRoaXMuZ2V0VGFibGVVbmtub3duRGF0YVNvdXJjZUVycm9yKCk7XG4gICAgfVxuICAgIHRoaXMuX3JlbmRlckNoYW5nZVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9yZW5kZXJDaGFuZ2VTdWJzY3JpcHRpb24gPSBkYXRhU3RyZWFtLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3lTdWJqZWN0KSkuc3Vic2NyaWJlKChkYXRhKSA9PiB7XG4gICAgICBjb25zb2xlLmRlYnVnKCdbaW1hZ2UtZ2FsbGVyeV0gUmVjZWl2ZWQgbmV3IHJvd3MnLCBkYXRhKTtcbiAgICAgIHRoaXMuX2RhdGEkLm5leHQoZGF0YSk7XG4gICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFRhYmxlVW5rbm93bkRhdGFTb3VyY2VFcnJvcigpIHtcbiAgICByZXR1cm4gRXJyb3IoYFByb3ZpZGVkIGRhdGEgc291cmNlIGRpZCBub3QgbWF0Y2ggYW4gYXJyYXksIE9ic2VydmFibGUsIG9yIERhdGFTb3VyY2VgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjbGlja1Jvdyhyb3c6IFRhYmxlRWxlbWVudDxUPiwgaW5kZXg6IG51bWJlcikge1xuICAgIC8vIERlbGVnYXRlIGNsaWNrIGFjdGlvblxuICAgIGlmICh0aGlzLmNsaWNrLm9ic2VydmVkKSB7XG4gICAgICB0aGlzLmNsaWNrLmVtaXQocm93LmN1cnJlbnREYXRhKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBCeSBkZWZhdWx0LCBvcGVuIHRoZSBzbGlkZXNob3c6IGVpdGhlciBpbmxpbmUgKG92ZXJsYXkgaW4gdGhlIGdhbGxlcnkgaXRzZWxmKSwgb3IgaW4gYSBmdWxsLXNjcmVlbiBtb2RhbFxuICAgIHRoaXMuX3NlbGVjdGVkUm93SW5kZXggPSBpbmRleDtcbiAgICBpZiAodGhpcy56b29tUHJlc2VudGF0aW9uID09PSAnaW5saW5lJykge1xuICAgICAgdGhpcy5faW5saW5lU2xpZGVzaG93QWN0aXZlID0gdHJ1ZTtcbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuem9vbU1vZGFsLnByZXNlbnQoKTtcbiAgICAgIGF3YWl0IHRoaXMuem9vbU1vZGFsLm9uRGlkRGlzbWlzcygpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBjbG9zZUlubGluZVNsaWRlc2hvdygpIHtcbiAgICB0aGlzLl9pbmxpbmVTbGlkZXNob3dBY3RpdmUgPSBmYWxzZTtcbiAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgYSBkZWxldGUgcmVxdWVzdCBjb21pbmcgZnJvbSB0aGUgc2xpZGVzaG93IGNvbXBvbmVudCAoZWl0aGVyIGlubGluZSBvciBpbiB0aGUgbW9kYWwpOlxuICAgKiBydW5zIHRoZSBzYW1lIGNvbmZpcm1hdGlvbi9kZWxldGlvbiBmbG93IGFzIGEgY2FyZCdzIGRlbGV0ZSBidXR0b24sIHRoZW4gcmVzb2x2ZXMgdGhlIHByb21pc2VcbiAgICogc28gdGhlIHNsaWRlc2hvdyBrbm93cyB3aGV0aGVyIHRvIHJlc2V0IGl0cyB6b29tIG9yIGNsb3NlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIG9uU2xpZGVzaG93RGVsZXRlUmVxdWVzdGVkKHByb21pc2VFdmVudDogUHJvbWlzZUV2ZW50PGJvb2xlYW4sIHsgcm93OiBUYWJsZUVsZW1lbnQ8VD4gfT4pIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVsZXRlZCA9IGF3YWl0IHRoaXMuZGVsZXRlKHByb21pc2VFdmVudCwgcHJvbWlzZUV2ZW50LmRldGFpbC5yb3cpO1xuICAgICAgcHJvbWlzZUV2ZW50LmRldGFpbC5zdWNjZXNzKGRlbGV0ZWQpO1xuICAgICAgaWYgKGRlbGV0ZWQgJiYgdGhpcy5yb3dzLmxlbmd0aCA9PT0gMCAmJiB0aGlzLnpvb21QcmVzZW50YXRpb24gPT09ICdpbmxpbmUnKSB7XG4gICAgICAgIHRoaXMuY2xvc2VJbmxpbmVTbGlkZXNob3coKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHByb21pc2VFdmVudC5kZXRhaWwuZXJyb3IoZXJyKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY2FuRGVsZXRlUm93cyhyb3dzOiBUYWJsZUVsZW1lbnQ8VD5bXSwgb3B0cz86IHsgaW50ZXJhY3RpdmU/OiBib29sZWFuIH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBDaGVjayB1c2luZyBlbWl0dGVyXG4gICAgaWYgKHRoaXMub25CZWZvcmVEZWxldGVSb3dzLm9ic2VydmVkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjYW5EZWxldGUgPSBhd2FpdCBlbWl0UHJvbWlzZUV2ZW50KHRoaXMub25CZWZvcmVEZWxldGVSb3dzLCAnY2FuRGVsZXRlJywge1xuICAgICAgICAgIGRldGFpbDogeyByb3dzIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWNhbkRlbGV0ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmIChlcnIgPT09ICdDQU5DRUxMRUQnKSByZXR1cm4gZmFsc2U7IC8vIFVzZXIgY2FuY2VsXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHdoaWxlIGNoZWNraW5nIGlmIGNhbiBkZWxldGUgcm93cycsIGVycik7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maXJtQmVmb3JlRGVsZXRlKSB7XG4gICAgICBjb25zdCBjb25maXJtZWQgPSBhd2FpdCBBbGVydHMuYXNrRGVsZXRlQ29uZmlybWF0aW9uKHRoaXMuYWx0ZXJDdHJsLCB0aGlzLnRyYW5zbGF0ZSwgZXZlbnQpO1xuICAgICAgaWYgKCFjb25maXJtZWQpIHJldHVybiBmYWxzZTsgLy8gQ2FuY2VsbGVkXG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0SW1hZ2VTaXplUXVlcnlQYXJhbXMobW9kZT86IEdhbGxlcnlNb2RlIHwgJ21vZGFsJyk6IHsgW2tleTogc3RyaW5nXTogYW55IH0ge1xuICAgIG1vZGUgPSBtb2RlID8/IHRoaXMubW9kZTtcbiAgICBpZiAoIXRoaXMuaW1hZ2VTaXplUXVlcnlQYXJhbSB8fCBpc05pbE9yQmxhbmsodGhpcy5pbWFnZVNpemVzPy5bbW9kZV0pKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICBbdGhpcy5pbWFnZVNpemVRdWVyeVBhcmFtXTogdGhpcy5pbWFnZVNpemVzW21vZGVdLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFya0ZvckNoZWNrKCkge1xuICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gIH1cbn1cbiIsIjxpb24tdG9vbGJhciBjb2xvcj1cImxpZ2h0XCIgY2xhc3M9XCJnYWxsZXJ5LXRvb2xiYXJcIiAqbmdJZj1cInNob3dUb29sYmFyICYmICFfaW5saW5lU2xpZGVzaG93QWN0aXZlXCI+XG4gIDxuZy1jb250ZW50IHNlbGVjdD1cImlvbi1idXR0b25zW3Nsb3Q9c3RhcnRdXCI+PC9uZy1jb250ZW50PlxuXG4gIDwhLS0gQWRkIC0tPlxuICBAaWYgKCFyZWFkT25seSAmJiBzaG93QWRkVG9vbGJhckJ1dHRvbiAmJiBlbmFibGVkKSB7XG4gICAgPGJ1dHRvblxuICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICBbdGl0bGVdPVwiIXNob3dUb29sdGlwID8gKCdDT01NT04uQlROX0FERCcgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgW21hdFRvb2x0aXBdPVwic2hvd1Rvb2x0aXAgPyAoJ0NPTU1PTi5CVE5fQUREJyB8IHRyYW5zbGF0ZSkgOiAnJ1wiXG4gICAgICAoY2xpY2spPVwiYWRkKClcIlxuICAgID5cbiAgICAgIDxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPlxuICAgIDwvYnV0dG9uPlxuICB9XG5cbiAgPG5nLWNvbnRlbnQgc2VsZWN0PVwiaW9uLWJ1dHRvbnNbc2xvdD1lbmRdXCI+PC9uZy1jb250ZW50PlxuXG4gIDxpb24tYnV0dG9ucyBzbG90PVwiZW5kXCI+XG4gICAgPCEtLSBUb2dnbGUgdmlldyBtb2RlIC0tPlxuICAgIDxpb24tc2VnbWVudCAoaW9uQ2hhbmdlKT1cInRvZ2dsZVZpZXdNb2RlKCRldmVudClcIiBjb2xvcj1cImFjY2VudFwiIFt2YWx1ZV09XCJfY29sU2l6ZVwiPlxuICAgICAgPGlvbi1zZWdtZW50LWJ1dHRvbiBbdmFsdWVdPVwiNFwiPlxuICAgICAgICA8bWF0LWljb24+dmlld19tb2R1bGU8L21hdC1pY29uPlxuICAgICAgPC9pb24tc2VnbWVudC1idXR0b24+XG4gICAgICA8aW9uLXNlZ21lbnQtYnV0dG9uIFt2YWx1ZV09XCIxMlwiPlxuICAgICAgICA8bWF0LWljb24+dmlld19saXN0PC9tYXQtaWNvbj5cbiAgICAgIDwvaW9uLXNlZ21lbnQtYnV0dG9uPlxuICAgIDwvaW9uLXNlZ21lbnQ+XG4gIDwvaW9uLWJ1dHRvbnM+XG48L2lvbi10b29sYmFyPlxuXG48ZGl2XG4gIGNsYXNzPVwiZ2FsbGVyeS1jb250YWluZXIgaW9uLXBhZGRpbmctYm90dG9tIHt7IG1vZGUgfX1cIlxuICBbY2xhc3MuaW5saW5lLXpvb20tYWN0aXZlXT1cIl9pbmxpbmVTbGlkZXNob3dBY3RpdmVcIlxuICBbc3R5bGUuLS1pbmxpbmUtem9vbS1oZWlnaHRdPVwiaW5saW5lWm9vbUhlaWdodFwiXG4+XG4gIDxkaXYgKm5nSWY9XCJtb2JpbGUgJiYgem9vbUFjdGl2ZVwiIGNsYXNzPVwiYmFja2Ryb3BcIiBbc3R5bGUub3BhY2l0eV09XCJ6b29tU2NhbGVcIj48L2Rpdj5cblxuICA8aW9uLWdyaWQgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiIFtjbGFzcy5jZGstdmlzdWFsbHktaGlkZGVuXT1cIl9pbmxpbmVTbGlkZXNob3dBY3RpdmVcIj5cbiAgICA8aW9uLXJvdz5cbiAgICAgIDxpb24tY29sICpyeEZvcj1cImxldCByb3cgb2YgX2RhdGEkOyBpbmRleCBhcyBpbmRleDsgdHJhY2tCeTogdHJhY2tCeUZuXCIgW3NpemVdPVwiX2NvbFNpemVcIj5cbiAgICAgICAgQGxldCBpbWFnZSA9IHJvdyB8IHByb3BlcnR5R2V0OiAnY3VycmVudERhdGEnO1xuICAgICAgICBAaWYgKGNhcmRUZW1wbGF0ZSkge1xuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2FyZFRlbXBsYXRlOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogcm93LCBtb2RlOiBtb2RlLCBpbWFnZTogaW1hZ2UgfVwiXG4gICAgICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICA8aW9uLWNhcmRcbiAgICAgICAgICAgICNjYXJkXG4gICAgICAgICAgICBjbGFzcz1cImltYWdlLWNhcmRcIlxuICAgICAgICAgICAgW2NsYXNzLnpvb20taG92ZXJdPVwiIW1vYmlsZVwiXG4gICAgICAgICAgICBbY29sb3JdPVwiY2FyZENvbG9yXCJcbiAgICAgICAgICAgIChjbGljayk9XCJjbGlja1Jvdyhyb3csIGluZGV4KVwiXG4gICAgICAgICAgICB0YXBwYWJsZVxuICAgICAgICAgICAgQGZhZGVJbkFuaW1hdGlvblxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxmaWd1cmUgY2xhc3M9XCJjYXJkLXRodW1ibmFpbFwiPlxuICAgICAgICAgICAgICBAaWYgKGltYWdlLnVybCkge1xuICAgICAgICAgICAgICAgIDxpb24taW1nIFtzcmNdPVwiaW1hZ2UudXJsIHwgYXBwZW5kUXVlcnlQYXJhbXM6IGdldEltYWdlU2l6ZVF1ZXJ5UGFyYW1zKClcIiAvPlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8aW9uLWltZyBbc3JjXT1cImltYWdlLmRhdGFVcmxcIiAvPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2ZpZ3VyZT5cblxuICAgICAgICAgICAgPCEtLSB0b29sYmFyIGZvciB0aXRsZSAod2hlbiBub3QgaG92ZXIpIC0tPlxuICAgICAgICAgICAgQGlmIChzaG93VGl0bGUgJiYgaW1hZ2UudGl0bGUpIHtcbiAgICAgICAgICAgICAgPGlvbi10b29sYmFyIGNvbG9yPVwidHJhbnNwYXJlbnRcIiBjbGFzcz1cInRpdGxlXCI+XG4gICAgICAgICAgICAgICAgPGlvbi1sYWJlbCBjbGFzcz1cImNhcmQtdGl0bGVcIj57eyBpbWFnZS50aXRsZSB9fTwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgICA8L2lvbi10b29sYmFyPlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICA8IS0tIGFjdGlvbiB0b29sYmFyIHNob3duIHdoZW4gaG92ZXIgaW1hZ2UgLS0+XG4gICAgICAgICAgICBAaWYgKCFyZWFkT25seSAmJiAhbW9iaWxlICYmIHNob3dDYXJkVG9vbGJhcikge1xuICAgICAgICAgICAgICA8aW9uLXRvb2xiYXIgI2NhcmRUb29sYmFyIGNvbG9yPVwibGlnaHRcIiBjbGFzcz1cImJ1dHRvbnNcIj5cbiAgICAgICAgICAgICAgICA8IS0tIGVkaXQgdGl0bGUgYnV0dG9uIC0tPlxuICAgICAgICAgICAgICAgIEBpZiAoc2hvd1RpdGxlKSB7XG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgc2xvdD1cInN0YXJ0XCJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImVkaXRUaXRsZSgkZXZlbnQsIHJvdywgY2FyZFRvb2xiYXIpXCJcbiAgICAgICAgICAgICAgICAgICAgKGZvY3VzaW4pPVwiZm9jdXNDYXJkVG9vbGJhcihjYXJkVG9vbGJhcilcIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+ZWRpdDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJyb3cuY3VycmVudERhdGEudGl0bGUgfCBpc05vdE5pbE9yQmxhbms7IGVsc2UgZWRpdExhYmVsXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgSU1BR0UuR0FMTEVSWS5CVE5fRURJVF9USVRMRVxuICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI2VkaXRMYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5JTUFHRS5HQUxMRVJZLkJUTl9BRERfVElUTEU8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleC1zcGFjZXJcIj48L2Rpdj5cblxuICAgICAgICAgICAgICAgIDwhLS0gZGVsZXRlIGJ1dHRvbiAtLT5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgIHNsb3Q9XCJlbmRcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJpb24tZmxvYXQtZW5kXCJcbiAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCIhc2hvd1Rvb2x0aXAgPyAoJ0NPTU1PTi5CVE5fREVMRVRFJyB8IHRyYW5zbGF0ZSkgOiAnJ1wiXG4gICAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJzaG93VG9vbHRpcCA/ICgnQ09NTU9OLkJUTl9ERUxFVEUnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlKCRldmVudCwgcm93KVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmRlbGV0ZTwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDwvaW9uLXRvb2xiYXI+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9pb24tY2FyZD5cbiAgICAgICAgfVxuICAgICAgPC9pb24tY29sPlxuXG4gICAgICA8IS0tIGFkZCBidXR0b24gLS0+XG4gICAgICBAaWYgKChzaG93QWRkVGV4dEJ1dHRvbiB8fCBzaG93QWRkQ2FyZEJ1dHRvbikgJiYgIXJlYWRPbmx5KSB7XG4gICAgICAgIDxpb24tY29sIFtzaXplXT1cIl9jb2xTaXplXCIgQGZhZGVJbkFuaW1hdGlvbj5cbiAgICAgICAgICBAaWYgKHNob3dBZGRUZXh0QnV0dG9uKSB7XG4gICAgICAgICAgICA8aW9uLWJ1dHRvbiAoY2xpY2spPVwiYWRkKCRldmVudClcIiBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIiBbY29sb3JdPVwiYWRkQnV0dG9uQ29sb3JcIj5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbCB0cmFuc2xhdGU+e3sgYWRkQnV0dG9uVGV4dCB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW9uLWljb24gc2xvdD1cImVuZFwiIG5hbWU9XCJjYW1lcmFcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgIH0gQGVsc2UgaWYgKHNob3dBZGRDYXJkQnV0dG9uKSB7XG4gICAgICAgICAgICA8aW9uLWNhcmRcbiAgICAgICAgICAgICAgY2xhc3M9XCJpbWFnZS1jYXJkLWJ1dHRvblwiXG4gICAgICAgICAgICAgIGNvbG9yPVwibGlnaHRcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiYWRkKCRldmVudClcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICBbdGl0bGVdPVwiIXNob3dUb29sdGlwID8gYWRkQnV0dG9uVGV4dCA6ICcnXCJcbiAgICAgICAgICAgICAgW21hdFRvb2x0aXBdPVwic2hvd1Rvb2x0aXAgPyBhZGRCdXR0b25UZXh0IDogJydcIlxuICAgICAgICAgICAgICB0YXBwYWJsZVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8aW9uLWNhcmQtY29udGVudD5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaWNvbi1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwiY2FtZXJhXCIgW2NvbG9yXT1cImFkZEJ1dHRvbkNvbG9yXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwiYWRkXCIgW2NvbG9yXT1cImFkZEJ1dHRvbkNvbG9yXCIgY2xhc3M9XCJpY29uLXNlY29uZGFyeVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvaW9uLWNhcmQtY29udGVudD5cbiAgICAgICAgICAgIDwvaW9uLWNhcmQ+XG4gICAgICAgICAgfVxuICAgICAgICA8L2lvbi1jb2w+XG4gICAgICB9XG4gICAgPC9pb24tcm93PlxuICA8L2lvbi1ncmlkPlxuXG4gIDwhLS0gSW5saW5lIHNsaWRlc2hvdzogc2hvd24gYXMgYW4gb3ZlcmxheSBkaXJlY3RseSB3aXRoaW4gdGhlIGdhbGxlcnksIGluc3RlYWQgb2YgYSBmdWxsLXNjcmVlbiBtb2RhbC5cbiAgICAgICBUaGUgcmVzdCBvZiB0aGUgcGFnZSAob3V0c2lkZSB0aGUgZ2FsbGVyeSkgc3RheXMgZnVsbHkgdmlzaWJsZSBhbmQgdXNhYmxlLCB1bmxpa2UgdGhlIG1vZGFsJ3MgYmFja2Ryb3AuIC0tPlxuICBAaWYgKHpvb21QcmVzZW50YXRpb24gPT09ICdpbmxpbmUnICYmIF9pbmxpbmVTbGlkZXNob3dBY3RpdmUpIHtcbiAgICA8YXBwLWltYWdlLWdhbGxlcnktc2xpZGVzaG93XG4gICAgICBjbGFzcz1cImlubGluZS1vdmVybGF5XCJcbiAgICAgIEBmYWRlSW5PdXRBbmltYXRpb25cbiAgICAgIFtyb3dzXT1cInJvd3NcIlxuICAgICAgW3NlbGVjdGVkSW5kZXhdPVwiX3NlbGVjdGVkUm93SW5kZXhcIlxuICAgICAgW21vYmlsZV09XCJtb2JpbGVcIlxuICAgICAgW3JlYWRPbmx5XT1cInJlYWRPbmx5XCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICBbZGVidWddPVwiZGVidWdcIlxuICAgICAgW21vdXNlWm9vbUVuYWJsZWRdPVwiX21vdXNlWm9vbUVuYWJsZWRcIlxuICAgICAgW3doZWVsWm9vbVN0ZXBdPVwid2hlZWxab29tU3RlcFwiXG4gICAgICBbbWF4Wm9vbVJhdGlvXT1cIm1heFpvb21SYXRpb1wiXG4gICAgICBbcm90YXRpb25FbmFibGVkXT1cIl9yb3RhdGlvbkVuYWJsZWRcIlxuICAgICAgW2Nyb3BFbmFibGVkXT1cIl9jcm9wRW5hYmxlZFwiXG4gICAgICBbaW1hZ2VFeHBvcnRGb3JtYXRdPVwiaW1hZ2VFeHBvcnRGb3JtYXRcIlxuICAgICAgW2ltYWdlRXhwb3J0UXVhbGl0eV09XCJpbWFnZUV4cG9ydFF1YWxpdHlcIlxuICAgICAgW2ltYWdlU2l6ZVF1ZXJ5UGFyYW1dPVwiaW1hZ2VTaXplUXVlcnlQYXJhbVwiXG4gICAgICBbbW9kYWxJbWFnZVNpemVdPVwiaW1hZ2VTaXplcz8ubW9kYWxcIlxuICAgICAgKGRlbGV0ZVJlcXVlc3RlZCk9XCJvblNsaWRlc2hvd0RlbGV0ZVJlcXVlc3RlZCgkZXZlbnQpXCJcbiAgICAgIChjbG9zZVJlcXVlc3RlZCk9XCJjbG9zZUlubGluZVNsaWRlc2hvdygpXCJcbiAgICAgIChhZnRlckVkaXRJbWFnZSk9XCJvbkFmdGVyRWRpdEltYWdlLmVtaXQoJGV2ZW50KVwiXG4gICAgICAoYWZ0ZXJFZGl0Um93KT1cIm9uQWZ0ZXJFZGl0Um93LmVtaXQoJGV2ZW50KVwiXG4gICAgPjwvYXBwLWltYWdlLWdhbGxlcnktc2xpZGVzaG93PlxuICB9XG48L2Rpdj5cblxuPCEtLSBGQUIgYnV0dG9uOiBhZGQgLS0+XG48aW9uLWZhYlxuICBzbG90PVwiZml4ZWRcIlxuICB2ZXJ0aWNhbD1cImJvdHRvbVwiXG4gIGhvcml6b250YWw9XCJlbmRcIlxuICAqbmdJZj1cInNob3dGYWJCdXR0b24gJiYgIXJlYWRPbmx5XCJcbiAgW2NsYXNzLmNkay12aXN1YWxseS1oaWRkZW5dPVwiZGlzYWJsZWRcIlxuICBAZmFkZUluT3V0QW5pbWF0aW9uXG4+XG4gIDxpb24tZmFiLWJ1dHRvbiBjb2xvcj1cInRlcnRpYXJ5XCIgKGNsaWNrKT1cImFkZCgkZXZlbnQpXCI+XG4gICAgPGlvbi1pY29uIG5hbWU9XCJjYW1lcmFcIj48L2lvbi1pY29uPlxuICAgIDxpb24taWNvbiBuYW1lPVwiYWRkXCIgY2xhc3M9XCJpY29uLXNlY29uZGFyeVwiIHN0eWxlPVwibGVmdDogMzNweDsgdG9wOiA5cHg7IGZvbnQtc2l6ZTogMjBweFwiPjwvaW9uLWljb24+XG4gIDwvaW9uLWZhYi1idXR0b24+XG48L2lvbi1mYWI+XG5cbjwhLS0gWm9vbSBtb2RhbCAtLT5cbkBpZiAoem9vbVByZXNlbnRhdGlvbiA9PT0gJ21vZGFsJykge1xuICA8aW9uLW1vZGFsICN6b29tTW9kYWwgY2xhc3M9XCJzdGFjay1tb2RhbCB6b29tLW1vZGFsXCIgW2NsYXNzLm1vZGFsLWZ1bGxzY3JlZW5dPVwibW9iaWxlXCIgW2NsYXNzLm1vZGFsLWxhcmdlXT1cIiFtb2JpbGVcIj5cbiAgICA8bmctdGVtcGxhdGU+XG4gICAgICA8YXBwLWltYWdlLWdhbGxlcnktc2xpZGVzaG93XG4gICAgICAgIFtyb3dzXT1cInJvd3NcIlxuICAgICAgICBbc2VsZWN0ZWRJbmRleF09XCJfc2VsZWN0ZWRSb3dJbmRleFwiXG4gICAgICAgIFttb2JpbGVdPVwibW9iaWxlXCJcbiAgICAgICAgW3JlYWRPbmx5XT1cInJlYWRPbmx5XCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgW2RlYnVnXT1cImRlYnVnXCJcbiAgICAgICAgW21vdXNlWm9vbUVuYWJsZWRdPVwiX21vdXNlWm9vbUVuYWJsZWRcIlxuICAgICAgICBbd2hlZWxab29tU3RlcF09XCJ3aGVlbFpvb21TdGVwXCJcbiAgICAgICAgW21heFpvb21SYXRpb109XCJtYXhab29tUmF0aW9cIlxuICAgICAgICBbcm90YXRpb25FbmFibGVkXT1cIl9yb3RhdGlvbkVuYWJsZWRcIlxuICAgICAgICBbY3JvcEVuYWJsZWRdPVwiX2Nyb3BFbmFibGVkXCJcbiAgICAgICAgW2ltYWdlRXhwb3J0Rm9ybWF0XT1cImltYWdlRXhwb3J0Rm9ybWF0XCJcbiAgICAgICAgW2ltYWdlRXhwb3J0UXVhbGl0eV09XCJpbWFnZUV4cG9ydFF1YWxpdHlcIlxuICAgICAgICBbaW1hZ2VTaXplUXVlcnlQYXJhbV09XCJpbWFnZVNpemVRdWVyeVBhcmFtXCJcbiAgICAgICAgW21vZGFsSW1hZ2VTaXplXT1cImltYWdlU2l6ZXM/Lm1vZGFsXCJcbiAgICAgICAgKGRlbGV0ZVJlcXVlc3RlZCk9XCJvblNsaWRlc2hvd0RlbGV0ZVJlcXVlc3RlZCgkZXZlbnQpXCJcbiAgICAgICAgKGNsb3NlUmVxdWVzdGVkKT1cInpvb21Nb2RhbC5kaXNtaXNzKClcIlxuICAgICAgICAoYWZ0ZXJFZGl0SW1hZ2UpPVwib25BZnRlckVkaXRJbWFnZS5lbWl0KCRldmVudClcIlxuICAgICAgICAoYWZ0ZXJFZGl0Um93KT1cIm9uQWZ0ZXJFZGl0Um93LmVtaXQoJGV2ZW50KVwiXG4gICAgICA+PC9hcHAtaW1hZ2UtZ2FsbGVyeS1zbGlkZXNob3c+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9pb24tbW9kYWw+XG59XG5cbjxpb24tcG9wb3ZlciAjdGl0bGVQb3BvdmVyPlxuICA8bmctdGVtcGxhdGU+XG4gICAgPGlvbi1jb250ZW50IGNsYXNzPVwiaW9uLXBhZGRpbmdcIiBjZGtUcmFwRm9jdXMgW2Nka1RyYXBGb2N1c0F1dG9DYXB0dXJlXT1cInRydWVcIj5cbiAgICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiX3RpdGxlRm9ybVwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQgZmxvYXRMYWJlbD1cImF1dG9cIj5cbiAgICAgICAgICA8bWF0LWxhYmVsIHRyYW5zbGF0ZT5JTUFHRS5HQUxMRVJZLlRJVExFPC9tYXQtbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidGl0bGVcIlxuICAgICAgICAgICAgW3JlYWRvbmx5XT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwiX3RpdGxlQXV0b2ZvY3VzXCJcbiAgICAgICAgICAgIChrZXlkb3duLmNvbnRyb2wuZW50ZXIpPVwidGl0bGVQb3BvdmVyLmRpc21pc3MoX3RpdGxlRm9ybS5jb250cm9scy50aXRsZS52YWx1ZSlcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICA8L2Zvcm0+XG4gICAgPC9pb24tY29udGVudD5cblxuICAgIDxpb24tZm9vdGVyPlxuICAgICAgPGlvbi10b29sYmFyPlxuICAgICAgICA8aW9uLXJvdyBjbGFzcz1cImlvbi1uby1wYWRkaW5nXCIgbm93cmFwPlxuICAgICAgICAgIDxpb24tY29sPjwvaW9uLWNvbD5cblxuICAgICAgICAgIDxpb24tY29sIHNpemU9XCJhdXRvXCI+XG4gICAgICAgICAgICA8aW9uLWJ1dHRvbiBmaWxsPVwiY2xlYXJcIiBjb2xvcj1cImRhcmtcIiAoY2xpY2spPVwidGl0bGVQb3BvdmVyLmRpc21pc3MobnVsbCwgJ0NBTkNFTCcpXCI+XG4gICAgICAgICAgICAgIDxpb24tbGFiZWwgdHJhbnNsYXRlPkNPTU1PTi5CVE5fQ0FOQ0VMPC9pb24tbGFiZWw+XG4gICAgICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgICAgICA8aW9uLWJ1dHRvblxuICAgICAgICAgICAgICBbZmlsbF09XCJkaXNhYmxlZCA/ICdjbGVhcicgOiAnc29saWQnXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInRpdGxlUG9wb3Zlci5kaXNtaXNzKF90aXRsZUZvcm0uY29udHJvbHMudGl0bGUudmFsdWUpXCJcbiAgICAgICAgICAgICAgKGtleXVwLmVudGVyKT1cInRpdGxlUG9wb3Zlci5kaXNtaXNzKF90aXRsZUZvcm0uY29udHJvbHMudGl0bGUudmFsdWUpXCJcbiAgICAgICAgICAgICAgY29sb3I9XCJ0ZXJ0aWFyeVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgIFt0aXRsZV09XCIhc2hvd1Rvb2x0aXAgPyAoJ0NPTU1PTi5CVE5fVkFMSURBVEVfV0lUSF9TSE9SVENVVF9IRUxQJyB8IHRyYW5zbGF0ZSkgOiAnJ1wiXG4gICAgICAgICAgICAgIFttYXRUb29sdGlwXT1cInNob3dUb29sdGlwID8gKCdDT01NT04uQlROX1ZBTElEQVRFX1dJVEhfU0hPUlRDVVRfSEVMUCcgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5DT01NT04uQlROX1ZBTElEQVRFPC9pb24tbGFiZWw+XG4gICAgICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgICAgPC9pb24tY29sPlxuICAgICAgICA8L2lvbi1yb3c+XG4gICAgICA8L2lvbi10b29sYmFyPlxuICAgIDwvaW9uLWZvb3Rlcj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvaW9uLXBvcG92ZXI+XG4iXX0=