@eqproject/eqp-attachments 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/{esm2020 → esm2022}/eqproject-eqp-attachments.mjs +4 -4
  2. package/esm2022/lib/eqp-attachments.component.mjs +1096 -0
  3. package/{esm2020 → esm2022}/lib/eqp-attachments.module.mjs +43 -43
  4. package/esm2022/lib/helpers/attachment.helper.mjs +66 -0
  5. package/{esm2020 → esm2022}/lib/interfaces/IAttachment.mjs +11 -11
  6. package/{esm2020 → esm2022}/lib/interfaces/IOptions.mjs +1 -1
  7. package/{esm2020 → esm2022}/lib/modules/material.module.mjs +231 -231
  8. package/{esm2020 → esm2022}/lib/services/eqp-attachment-dialog.service.mjs +103 -103
  9. package/{esm2020 → esm2022}/lib/services/eqp-attachment.service.mjs +23 -23
  10. package/{esm2020 → esm2022}/public-api.mjs +9 -9
  11. package/fesm2022/eqproject-eqp-attachments.mjs +1565 -0
  12. package/fesm2022/eqproject-eqp-attachments.mjs.map +1 -0
  13. package/index.d.ts +5 -5
  14. package/lib/eqp-attachments.component.d.ts +319 -318
  15. package/lib/eqp-attachments.module.d.ts +13 -13
  16. package/lib/helpers/attachment.helper.d.ts +20 -20
  17. package/lib/interfaces/IAttachment.d.ts +21 -21
  18. package/lib/interfaces/IOptions.d.ts +11 -11
  19. package/lib/modules/material.module.d.ts +37 -37
  20. package/lib/services/eqp-attachment-dialog.service.d.ts +31 -31
  21. package/lib/services/eqp-attachment.service.d.ts +7 -7
  22. package/package.json +7 -12
  23. package/public-api.d.ts +6 -6
  24. package/esm2020/lib/eqp-attachments.component.mjs +0 -1064
  25. package/esm2020/lib/helpers/attachment.helper.mjs +0 -66
  26. package/fesm2015/eqproject-eqp-attachments.mjs +0 -1535
  27. package/fesm2015/eqproject-eqp-attachments.mjs.map +0 -1
  28. package/fesm2020/eqproject-eqp-attachments.mjs +0 -1532
  29. package/fesm2020/eqproject-eqp-attachments.mjs.map +0 -1
@@ -0,0 +1,1096 @@
1
+ import { Component, EventEmitter, Input, Output, ViewChild } from "@angular/core";
2
+ import { Validators } from "@angular/forms";
3
+ import { TooltipPositionType, TypeColumn } from "@eqproject/eqp-common";
4
+ import imageCompression from "browser-image-compression";
5
+ import { base64ToFile, ImageCropperComponent } from "ngx-image-cropper";
6
+ import { AttachmentHelperService } from "./helpers/attachment.helper";
7
+ import { AttachmentType } from "./interfaces/IAttachment";
8
+ import { EqpAttachmentDialogService } from "./services/eqp-attachment-dialog.service";
9
+ import { concatMap, from, Observable } from "rxjs";
10
+ import * as i0 from "@angular/core";
11
+ import * as i1 from "@angular/material/dialog";
12
+ import * as i2 from "@angular/forms";
13
+ import * as i3 from "@angular/platform-browser";
14
+ import * as i4 from "@angular/common/http";
15
+ import * as i5 from "./services/eqp-attachment.service";
16
+ import * as i6 from "@angular/material/button";
17
+ import * as i7 from "@angular/material/input";
18
+ import * as i8 from "@angular/material/form-field";
19
+ import * as i9 from "@angular/material/menu";
20
+ import * as i10 from "@angular/material/card";
21
+ import * as i11 from "@angular/material/icon";
22
+ import * as i12 from "@angular/material/tooltip";
23
+ import * as i13 from "@angular/common";
24
+ import * as i14 from "ngx-image-cropper";
25
+ import * as i15 from "@eqproject/eqp-table";
26
+ import * as i16 from "ngx-file-drop";
27
+ const toBase64 = (file) => new Promise((resolve, reject) => {
28
+ const reader = new FileReader();
29
+ reader.readAsDataURL(file);
30
+ reader.onload = () => resolve(reader.result.toString());
31
+ reader.onerror = (error) => reject(error);
32
+ });
33
+ export class EqpAttachmentsComponent {
34
+ dialog;
35
+ formBuilder;
36
+ sanitizer;
37
+ http;
38
+ cd;
39
+ eqpAttachmentService;
40
+ //#region @Input del componente
41
+ /**
42
+ * Se TRUE allora nasconde la colonna per le azioni sull'allegato (nel caso "multipleAttachment" è TRUE).
43
+ */
44
+ disableAction = false;
45
+ /**
46
+ * Se TRUE mostra il titolo nell'header nel caso in cui "multipleAttachment" è TRUE ("Elenco allegati" di default).
47
+ */
48
+ showHeader = true;
49
+ /**
50
+ * Titolo da visualizzare se il parametro "showHeader" è TRUE. Di devault viene visualizzato "Elenco allegati".
51
+ */
52
+ headerTitle = "Elenco allegati";
53
+ /**
54
+ * Sorgente dati da visualizzare. Nel caso si vuole gestire un singolo allegato va passato in ogni caso come Array.
55
+ */
56
+ attachmentsList = null;
57
+ /**
58
+ * Se TRUE non mostra la MatCard (nel caso in cui "multipleAttachment" è TRUE).
59
+ */
60
+ showMatCard = true;
61
+ /**
62
+ * Se FALSE allora il componente mostra solo il pulsante di caricamento di un singolo file, una volta caricato il file invoca l'evento di output "localEditedAttachments".
63
+ * Se TRUE allora il componente mostra l'elenco di tutti gli allegati ricevuto nel parametro "attachmentsList".
64
+ */
65
+ multipleAttachment = true;
66
+ /**
67
+ * Se assume il valore TRUE allora sarà possibile caricare più file per volta. Questa funzionalità è attiva
68
+ * SOLO se si gestiscono allegati multipli, quindi se l'input 'multipleAttachment' assume il valore TRUE, altrimenti è sempre disabilitata.
69
+ */
70
+ loadMultipleFiles = false;
71
+ /**
72
+ * Configurazione delle colonne della eqp-table per la visualizzazione degli allegati (caso "multipleAttachment" è TRUE).
73
+ */
74
+ attachmentsColumns = null;
75
+ /**
76
+ * Imposta il messaggio da visualizzare nel caso in cui la tabella degli allegati (nel caso in cui "multipleAttachment" è TRUE) è vuota.
77
+ */
78
+ emptyTableMessage = "Nessun dato trovato";
79
+ /**
80
+ * Se TRUE allora permette di selezionare soltanto file di tipo immagine, avente uno dei mimetype
81
+ * specificati dentro AttachmentHelperService.
82
+ * Se FALSE permette di selezionare qualsiasi tipo di file
83
+ */
84
+ allowOnlyImages = false;
85
+ /**
86
+ * Specifica i tipi di file che è possibile caricare
87
+ */
88
+ acceptedFileTypes;
89
+ /**
90
+ * Se TRUE disabilita il pulsante di Aggiunta allegato (a prescindere dal valore del parametro "multipleAttachment").
91
+ */
92
+ isDisabled = false;
93
+ /**
94
+ * Mostra/nasconde la colonna per visualizzare l'anteprima dei file nella tabella (caso multipleAtatchments = true).
95
+ */
96
+ showInlinePreview = false;
97
+ /**
98
+ * Endpoint da chiamare per recueprare l'IAttachmentDTO completo da vedere nell'anteprima. La chiamata sarà in POST e nel body
99
+ * conterrà l'IAttachmentDTO selezionato dall'utente.
100
+ * La chiamata viene eseguita solo per l'anteprima delle immagini essendo necessario il base64 completo dell'immagine a dimensione reale.
101
+ * Per documenti/link basta che sia popolata la proprietà FilePath di IAttachmentDTO.
102
+ */
103
+ getAttachmentEndpoint = null;
104
+ /**
105
+ * Hostname dell'ambiente di produzione dell'applicativo. Necessario per visualizzare l'anteprima dei documenti
106
+ * tramite il viewer di google.
107
+ * NOTA: Per visualizzare l'anteprima è necessario che la prorietà FilePath dell'IAttachmentDTO sia popolata e che
108
+ * sia abilitato l'accesso alla cartella sul server tramite hostname.
109
+ */
110
+ productionBaseUrl = null;
111
+ /**
112
+ * Opzioni per la compressione delle immagini caricate.
113
+ */
114
+ compressionOptions = {
115
+ maxSizeMB: 0.5,
116
+ maxWidthOrHeight: 1920,
117
+ useWebWorker: true
118
+ };
119
+ /**
120
+ * Array di AttachmentType che si possono aggiungere
121
+ */
122
+ allowedTypes = [AttachmentType.FILE, AttachmentType.LINK];
123
+ /**
124
+ * Permette di stabilire se la eqp-table contenente l'elenco degli allegati utilizza
125
+ * il multilingua oppure no
126
+ */
127
+ isEqpTableMultiLanguage = false;
128
+ /**
129
+ * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
130
+ * degli allegati deve essere paginata oppure no
131
+ */
132
+ tablePaginatorVisible = true;
133
+ /**
134
+ * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
135
+ * degli allegati deve contenere il campo di ricerca oppure no
136
+ */
137
+ isTableSearcheable = true;
138
+ /**
139
+ * In caso di gestione allegati multipli, permette di stabilire la dimensione pagina di default
140
+ * per la tabella contenente l'elenco degli allegati
141
+ */
142
+ tablePaginatorSize = null;
143
+ /**
144
+ * Permette di scegliere il modo in cui i file devono essere caricati
145
+ */
146
+ // @Input("uploadType") uploadType: UploadTypeEnum = UploadTypeEnum.FILE_AND_LINK;
147
+ /**
148
+ * Permette di stabilire se i pulsanti per il caricamento dei file sono separati o in un menù a tendina
149
+ */
150
+ separatedUploadButtons = false;
151
+ /**
152
+ * Permette di scegliere se dare la possibilità di vedere o no l'anteprima
153
+ */
154
+ showPreview = true;
155
+ /**
156
+ * In caso di allegato singolo, permette di scegliere se aggiungere file tramite drag and drop
157
+ */
158
+ singleAttachmentDragAndDrop = false;
159
+ /**
160
+ * Array di opzioni che si possono utilizzare per il crop
161
+ */
162
+ cropOptions = [];
163
+ /**
164
+ * Classe custom da assegnare al dialog del crop immagini
165
+ */
166
+ cropDialogClass;
167
+ /**
168
+ * Input per definire le label da usare nel componente
169
+ */
170
+ downloadTooltipPosition = TooltipPositionType.Below;
171
+ openLinkLabel = "Apri link";
172
+ addButtonLabel = "Aggiungi";
173
+ downloadLabel = "Download";
174
+ deleteLabel = "Elimina";
175
+ fileNameLabel = "Nome file";
176
+ previewLabel = "Anteprima";
177
+ uploadFileLabel = "Carica file";
178
+ confirmLabel = "Conferma";
179
+ abortLabel = "Annulla";
180
+ saveLabel = "Salva";
181
+ exitLabel = "Esci";
182
+ uploadWithDropboxLabel = "Carica con Dropbox";
183
+ cropLabel = "Scegli le dimensioni dell'immagine";
184
+ eqpTableSearchText = "Cerca";
185
+ deleteDialogTitle = null;
186
+ deleteDialogMessage = "Sei sicuro di voler cancellare quest'allegato?";
187
+ noImageSelectedErrorMessage = "Non è possibile selezionare un file che non sia un'immagine.";
188
+ wrongTypeSelectedErrorMessage = "Non è possibile caricare il file selezionato.";
189
+ videoPreviewErrorMessage = "Impossibile aprire l'anteprima di un file video.";
190
+ audioPreviewErrorMessage = "Impossibile aprire l'anteprima di un file audio.";
191
+ flipHorinzontalLabel = "Capovolgi orizzontalmente";
192
+ flipVerticalLabel = "Capovolgi verticalmente";
193
+ rotateRightLabel = "Ruota a destra";
194
+ rotateLeftLabel = "Ruota a sinistra";
195
+ //#endregion
196
+ //#region @Output del componente
197
+ /**
198
+ * Restituisce la lista aggiornata degli allegati.
199
+ */
200
+ localEditedAttachments = new EventEmitter();
201
+ /**
202
+ * Evento scatenato alla pressione del pulsante ESCI della modale di caricamento file.
203
+ */
204
+ abortAddAttachment = new EventEmitter();
205
+ /**
206
+ * Evento di output che restituisce l'IAttachmentDTO selezionato per il download nel caso FileDataBase64, FileContentType o FileName non fossero specificati.
207
+ */
208
+ downloadAttachment = new EventEmitter();
209
+ /**
210
+ * Evento di output che restituisce l'elemento eliminato prima che questo venga effettivamente rismosso dalla lista.
211
+ */
212
+ onDeleteAttachment = new EventEmitter();
213
+ //#endregion
214
+ //#region Proprietà per gestione caricamento nuovo allegato
215
+ newAttachment = {};
216
+ newMultipleAttachments = [];
217
+ attachmentType = AttachmentType;
218
+ // uploadTypeEnum = UploadTypeEnum;
219
+ newAttachmentForm;
220
+ selectedFile = null;
221
+ selectedFiles = null;
222
+ showCropImage = false;
223
+ dialogAddAttachment;
224
+ dialogRefAddAttachment;
225
+ dialogAddMultipleAttachment;
226
+ dialogRefCropImage;
227
+ dialogCropImage;
228
+ //#endregion
229
+ //#region Proprietà per gestione ridimensionamento file di tipo image
230
+ imageChangedEvent = "";
231
+ croppedImage = "";
232
+ transform = {};
233
+ canvasRotation = 0;
234
+ imageCropper;
235
+ imageInput;
236
+ //#endregion
237
+ AttachmentType = AttachmentType;
238
+ selectedAttachment;
239
+ originalWidth;
240
+ originalHeight;
241
+ customWidth;
242
+ customHeight;
243
+ attachmentTable;
244
+ inlinePreviewTemplate;
245
+ dialogPreview;
246
+ imageFile;
247
+ addingLinkMode = false;
248
+ constructor(dialog, formBuilder, sanitizer, http, cd, eqpAttachmentService) {
249
+ this.dialog = dialog;
250
+ this.formBuilder = formBuilder;
251
+ this.sanitizer = sanitizer;
252
+ this.http = http;
253
+ this.cd = cd;
254
+ this.eqpAttachmentService = eqpAttachmentService;
255
+ }
256
+ async ngOnInit() {
257
+ //Se è stata richiesta la gestione delle sole immagini allora imposta il filtro per le estensioni possibili da caricare
258
+ if (!this.acceptedFileTypes)
259
+ if (this.allowOnlyImages == true)
260
+ this.acceptedFileTypes = "image/*";
261
+ else
262
+ this.acceptedFileTypes = "*";
263
+ // Se non sono stati specificati i tipi da gestire ma è stato passato null o un array vuoto imposto i tipi di default.
264
+ if (!this.allowedTypes || this.allowedTypes.length == 0)
265
+ this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK, AttachmentType.DROPBOX];
266
+ else if (this.allowedTypes.find((t) => t != AttachmentType.FILE && t != AttachmentType.LINK && t != AttachmentType.DROPBOX)) {
267
+ EqpAttachmentDialogService.Warning('Almeno uno degli AttachmentType selezionati nel parametro "allowedTypes" non esiste.');
268
+ this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK, AttachmentType.DROPBOX];
269
+ }
270
+ //Se è stata richiesta la gestione multipla degli allegati allora configura l'eqp-table
271
+ if (this.multipleAttachment == true && (!this.attachmentsColumns || this.attachmentsColumns.length == 0)) {
272
+ this.configureColumns();
273
+ }
274
+ if (this.attachmentsList == null)
275
+ this.attachmentsList = new Array();
276
+ this.checkAttachmentImage();
277
+ if (this.allowedTypes.includes(3)) {
278
+ this.eqpAttachmentService.loadDropboxScript();
279
+ }
280
+ }
281
+ reloadData() {
282
+ if (this.attachmentTable)
283
+ this.attachmentTable.reloadDatatable();
284
+ }
285
+ checkAttachmentImage() {
286
+ this.attachmentsList.forEach((a) => {
287
+ a.IsImage = AttachmentHelperService.checkImageFromMimeType(a.FileContentType);
288
+ });
289
+ }
290
+ //#region Gestione elenco allegati
291
+ /**
292
+ * Configura le colonne per l'eqp-table nel caso in cui il parametro "multipleAttachments" è TRUE.
293
+ */
294
+ configureColumns() {
295
+ this.attachmentsColumns = [];
296
+ if (this.disableAction != true) {
297
+ this.attachmentsColumns.push({
298
+ key: "action",
299
+ display: "",
300
+ type: TypeColumn.MenuAction,
301
+ buttonMenuIcon: "more_vert",
302
+ styles: { flex: "0 0 6%" },
303
+ actions: [
304
+ { name: this.deleteLabel, icon: "delete", fn: (element, index, col) => this.deleteAttachment(element) }
305
+ ]
306
+ });
307
+ }
308
+ let downloadColumn = {
309
+ key: "attachment",
310
+ display: "",
311
+ type: TypeColumn.SimpleAction,
312
+ styles: { flex: "0 0 6%" },
313
+ actions: [
314
+ {
315
+ name: "",
316
+ fontawesome: true,
317
+ icon: (element) => {
318
+ return this.showInlinePreview
319
+ ? element.AttachmentType == AttachmentType.FILE
320
+ ? "fas fa-cloud-download-alt"
321
+ : "fas fa-external-link-alt"
322
+ : this.getAttachmentIcon(element);
323
+ },
324
+ fn: (element, col, elementIndex) => this.viewAttachment(element),
325
+ tooltip: {
326
+ tooltipText: (element) => {
327
+ return element.AttachmentType == AttachmentType.FILE ? this.downloadLabel : this.openLinkLabel;
328
+ },
329
+ tooltipPosition: this.downloadTooltipPosition
330
+ }
331
+ }
332
+ ]
333
+ };
334
+ let inlinePreviewColumn = {
335
+ key: "InlinePreview",
336
+ display: this.previewLabel,
337
+ type: TypeColumn.ExternalTemplate,
338
+ externalTemplate: this.inlinePreviewTemplate,
339
+ styles: { flex: "0 0 10%" }
340
+ };
341
+ let fileNameColumn = { key: "FileName", display: this.fileNameLabel };
342
+ if (this.showInlinePreview) {
343
+ this.attachmentsColumns.push(inlinePreviewColumn);
344
+ this.attachmentsColumns.push(fileNameColumn);
345
+ this.attachmentsColumns.push(downloadColumn);
346
+ }
347
+ else {
348
+ this.attachmentsColumns.push(downloadColumn);
349
+ this.attachmentsColumns.push(fileNameColumn);
350
+ }
351
+ }
352
+ /**
353
+ * Elimina un allegato eliminando anche il file presente nello storage di archiviazione utilizzato (AWS o cartella progetto)
354
+ * @param element IAttachmentDTO da cancellare
355
+ */
356
+ deleteAttachment(element) {
357
+ EqpAttachmentDialogService.Confirm(this.deleteDialogMessage, () => {
358
+ this.removeAttachmentFromList(this.attachmentsList.indexOf(element));
359
+ }, true, this.deleteDialogTitle);
360
+ }
361
+ /**
362
+ * Rimuove l'allegato selezionato dalla lista "attachmentsList" e invoca l'evento di output che restituisce la lista aggiornata.
363
+ * @param attachmentIndex Indice dell'attachment da rimuovere
364
+ */
365
+ removeAttachmentFromList(attachmentIndex) {
366
+ this.onDeleteAttachment.emit(this.attachmentsList[attachmentIndex]);
367
+ this.attachmentsList.splice(attachmentIndex, 1);
368
+ if (this.attachmentTable)
369
+ this.attachmentTable.reloadDatatable();
370
+ this.localEditedAttachments.emit(this.attachmentsList);
371
+ }
372
+ /**
373
+ * Scarica l'allegato o apre il link
374
+ * @param element Allegato da mostrare
375
+ */
376
+ viewAttachment(attachment) {
377
+ if (attachment.AttachmentType == AttachmentType.LINK) {
378
+ window.open(attachment.FilePath, "_blank");
379
+ return;
380
+ }
381
+ if (attachment.FileDataBase64 && attachment.FileContentType && attachment.FileName) {
382
+ let source = `data:${attachment.FileContentType};base64,${attachment.FileDataBase64}`;
383
+ const link = document.createElement("a");
384
+ link.href = source;
385
+ link.download = `${attachment.FileName}`;
386
+ link.click();
387
+ }
388
+ else {
389
+ this.downloadAttachment.emit(attachment);
390
+ }
391
+ }
392
+ /**
393
+ * Ridefinisce l'icona da mostrare nella colonna dell'eqp-table per ogni file.
394
+ * L'icona varia in base all'estensione del file
395
+ * @param attachment
396
+ */
397
+ getAttachmentIcon(attachment) {
398
+ if (attachment.AttachmentType == AttachmentType.LINK)
399
+ return "fas fa-link";
400
+ else
401
+ return AttachmentHelperService.getIconFromFileExtensione(attachment.FileExtension);
402
+ }
403
+ //#endregion
404
+ /**
405
+ * In caso di allegato singolo, sceglie quale metodo richiamare in base al tipo di allegato
406
+ */
407
+ addFile(attachmentType, imageInput = null) {
408
+ if (attachmentType == AttachmentType.LINK) {
409
+ this.switchToAddingLinkMode();
410
+ }
411
+ else if (attachmentType == AttachmentType.FILE) {
412
+ imageInput.click();
413
+ }
414
+ else {
415
+ this.chooseDropboxFile();
416
+ }
417
+ }
418
+ createAttachmentForm() {
419
+ //Crea la form per la validazione dei campi
420
+ this.newAttachmentForm = this.formBuilder.group({
421
+ type: [this.newAttachment.AttachmentType, Validators.required],
422
+ name: [this.newAttachment.FileName],
423
+ path: [this.newAttachment.FilePath],
424
+ customHeight: [this.customHeight],
425
+ customWidth: [this.customWidth]
426
+ });
427
+ }
428
+ close(emitCloseEvent = true) {
429
+ this.newAttachment = {};
430
+ this.newMultipleAttachments = new Array();
431
+ this.abortFile();
432
+ if (this.newAttachmentForm)
433
+ this.newAttachmentForm.reset();
434
+ this.dialogRefCropImage.close();
435
+ this.restoreOriginalDimensions();
436
+ if (emitCloseEvent == true && this.abortAddAttachment)
437
+ this.abortAddAttachment.emit();
438
+ }
439
+ /**
440
+ * In base al tipo di allegato controlla se disabilitare o meno il pulsante per salvare.
441
+ * Funzione usata nel [disable] del pulsante "Salva" del dialog per l'aggiunta di un allegato.
442
+ * @returns
443
+ */
444
+ disableSave() {
445
+ if (this.loadMultipleFiles != true) {
446
+ if (this.newAttachment.AttachmentType == AttachmentType.FILE) {
447
+ return !this.newAttachment.FileDataBase64;
448
+ }
449
+ else {
450
+ return !this.newAttachment.FilePath;
451
+ }
452
+ }
453
+ else {
454
+ return (this.newMultipleAttachments.filter((p) => (p.AttachmentType == AttachmentType.FILE && !p.FileDataBase64) ||
455
+ (p.AttachmentType == AttachmentType.LINK && !p.FilePath)).length > 0);
456
+ }
457
+ }
458
+ confirmAddAttachment() {
459
+ if (this.newAttachment.IsImage) {
460
+ this.newAttachment.FileDataBase64 = this.imageCropper.crop().base64.split(";base64,")[1];
461
+ }
462
+ if (this.loadMultipleFiles != true) {
463
+ if (this.newAttachment.AttachmentType == AttachmentType.LINK && !this.newAttachment.FileName)
464
+ this.newAttachment.FileName = this.newAttachment.FilePath;
465
+ if (this.attachmentsList == null)
466
+ this.attachmentsList = new Array();
467
+ this.attachmentsList.push(this.newAttachment);
468
+ }
469
+ else {
470
+ if (this.newMultipleAttachments == null || this.newMultipleAttachments.length == 0)
471
+ return;
472
+ if (this.attachmentsList == null)
473
+ this.attachmentsList = new Array();
474
+ this.attachmentsList = this.attachmentsList.concat(this.newMultipleAttachments);
475
+ }
476
+ if (this.attachmentTable)
477
+ this.attachmentTable.reloadDatatable();
478
+ this.localEditedAttachments.emit(this.attachmentsList);
479
+ if (this.newAttachment.IsImage) {
480
+ this.dialogRefCropImage.close();
481
+ this.restoreOriginalDimensions();
482
+ }
483
+ }
484
+ /**
485
+ * Apre il dialog per l'anteprima dell'allegato selezionato.
486
+ * @param row
487
+ * @returns
488
+ */
489
+ async openPreviewDialog(row) {
490
+ this.selectedAttachment = JSON.parse(JSON.stringify(row));
491
+ if (this.selectedAttachment.AttachmentType == AttachmentType.FILE) {
492
+ if (this.selectedAttachment.FileContentType.startsWith("video")) {
493
+ EqpAttachmentDialogService.Warning(this.videoPreviewErrorMessage);
494
+ return;
495
+ }
496
+ else if (this.selectedAttachment.FileContentType.startsWith("audio")) {
497
+ EqpAttachmentDialogService.Warning(this.audioPreviewErrorMessage);
498
+ return;
499
+ }
500
+ }
501
+ if (this.getAttachmentEndpoint && this.selectedAttachment.IsImage && !this.selectedAttachment.FileDataBase64) {
502
+ await this.getAttachmentByID()
503
+ .then((res) => {
504
+ this.selectedAttachment.FileDataBase64 = res.FileDataBase64;
505
+ })
506
+ .catch((err) => {
507
+ EqpAttachmentDialogService.Error(err);
508
+ });
509
+ }
510
+ if (this.selectedAttachment.AttachmentType == AttachmentType.LINK) {
511
+ this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.selectedAttachment.FilePath);
512
+ }
513
+ else if (this.selectedAttachment.IsImage &&
514
+ !this.selectedAttachment.FileDataBase64 &&
515
+ !this.selectedAttachment.FileThumbnailBase64) {
516
+ EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima dell'allegato, file mancante.");
517
+ return;
518
+ }
519
+ else if (!this.selectedAttachment.IsImage) {
520
+ if (this.selectedAttachment.FilePath && this.productionBaseUrl) {
521
+ this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://docs.google.com/gview?url=" +
522
+ this.productionBaseUrl +
523
+ "/" +
524
+ this.selectedAttachment.FilePath +
525
+ "&embedded=true");
526
+ }
527
+ else {
528
+ EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima del documento!");
529
+ return;
530
+ }
531
+ }
532
+ this.dialog.open(this.dialogPreview, {
533
+ disableClose: true,
534
+ hasBackdrop: true
535
+ });
536
+ }
537
+ async getAttachmentByID() {
538
+ return this.http.post(this.getAttachmentEndpoint, this.selectedAttachment).toPromise();
539
+ }
540
+ //#region Gestione caricamento file
541
+ /**
542
+ * Evento scatenato alla selezione del file (o dei file).
543
+ * Se il caricamento è SINGOLO o se comunque è stato selezionato un solo file allora si occupa di controllare se si tratta di un immagine in modo da
544
+ * mostrare le funzionalità del croppie (per ritagliare l'immagine) oppure no.
545
+ * Se il file caricato non è un immagine allora genera direttamente il base64 e lo associa all'allegato da salvare.
546
+ * Se invece il caricamento dei file è MULTIPLO e sono presenti più file allora esegue le stesse operazioni ignorando però il contrllo
547
+ * immagine per il croppie (in caso di caricamento multiplo le funzionalità del croppie sono disabilitate).
548
+ */
549
+ async onFileAdded(event, isFileDropped = false) {
550
+ this.showCropImage = false;
551
+ let filesOnInput = isFileDropped ? event : event.target.files;
552
+ //Se è stato richiesto il caricamento SINGOLO oppure se il caricamento è MULTIPLO ma è stato selezionato un solo file
553
+ //allora verifica se il file è un immagine (per mostrare il CROPPIE)
554
+ if ([...filesOnInput].length == 1 || this.loadMultipleFiles != true) {
555
+ this.selectedFile = filesOnInput[0];
556
+ this.selectedFiles = filesOnInput;
557
+ if (!this.selectedFile)
558
+ return;
559
+ //Memorizza i dati per l'allegato
560
+ this.newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFile, false);
561
+ this.newMultipleAttachments = new Array();
562
+ this.newMultipleAttachments.push(this.newAttachment);
563
+ //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
564
+ let checkOnlyImage = this.checkAllowOnlyImageFile(this.newAttachment);
565
+ if (checkOnlyImage == false)
566
+ return;
567
+ this.createAttachmentForm();
568
+ //Verifica se il file caricato è un'immagine oppure no. Se è un immagine, prima di caricarla mostra il croppie per il resize.
569
+ //Se non è un immagine allora genera il Base64
570
+ if (this.newAttachment.IsImage == true) {
571
+ this.getImageDimensions(filesOnInput[0]);
572
+ //Mostra il croppie e disabilita la form finchè non termina la modifica dell'immagine
573
+ this.newAttachmentForm.disable();
574
+ this.newAttachmentForm.controls["customWidth"].enable();
575
+ this.newAttachmentForm.controls["customHeight"].enable();
576
+ this.showCropImage = true;
577
+ this.imageFile = event;
578
+ this.dialogRefCropImage = this.dialog.open(this.dialogCropImage, {
579
+ disableClose: true,
580
+ hasBackdrop: true,
581
+ width: "60%",
582
+ maxHeight: "80%",
583
+ maxWidth: "70vh"
584
+ });
585
+ }
586
+ else {
587
+ this.showCropImage = false;
588
+ let base64Result = await this.getBase64FromFile(this.selectedFile);
589
+ this.newAttachment.FileDataBase64 = base64Result.Base64File;
590
+ this.newAttachment.FileContentType = base64Result.ContentType;
591
+ this.confirmAddAttachment();
592
+ }
593
+ }
594
+ else {
595
+ this.selectedFiles = filesOnInput;
596
+ if (!this.selectedFiles || this.selectedFiles.length == 0)
597
+ return;
598
+ this.newMultipleAttachments = new Array();
599
+ for (let i = 0; i < this.selectedFiles.length; i++) {
600
+ let newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFiles[i], true, true);
601
+ //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
602
+ let checkOnlyImage = this.checkAllowOnlyImageFile(newAttachment);
603
+ if (checkOnlyImage == false)
604
+ return;
605
+ this.newMultipleAttachments.push(newAttachment);
606
+ }
607
+ this.confirmAddAttachment();
608
+ }
609
+ //Resetto il valore del file input in modo da scatenare il change anche se si dovesse caricare lo stesso file
610
+ if (!isFileDropped)
611
+ event.target.value = "";
612
+ }
613
+ /**
614
+ * A partire dal FILE ricevuto in input ricostruisce l'oggetto IAttachmentDTO e lo restituisce.
615
+ * Se il parametro getBase64 viene passato a TRUE allora, sempre a partire dal file,genera il base64 e
616
+ * ricava il ContentType da associare all'oggetto IAttachmentDTO da restituire
617
+ * @param currentFile Oggetto FILE da processare
618
+ * @param getBase64 Se TRUE allora calcola base64 e ContentType del file passato in input
619
+ * @returns Restituisce un oggetto di tipo IAttachmentDTO
620
+ */
621
+ async createAttachmentFromUploadedFile(currentFile, getBase64 = true, cropFile = false) {
622
+ let newAttachment = {};
623
+ //Memorizza i dati per l'allegato
624
+ newAttachment.AttachmentType = AttachmentType.FILE;
625
+ newAttachment.FileContentType = currentFile.type;
626
+ newAttachment.FileName = currentFile.name;
627
+ newAttachment.FileExtension = currentFile.name.substr(currentFile.name.lastIndexOf(".") + 1);
628
+ newAttachment.IsImage = AttachmentHelperService.checkImageFromMimeType(currentFile.type);
629
+ if (getBase64 == true) {
630
+ let base64Result = await this.getBase64FromFile(currentFile);
631
+ newAttachment.FileDataBase64 = base64Result.Base64File;
632
+ newAttachment.FileContentType = base64Result.ContentType;
633
+ if (newAttachment.IsImage && newAttachment.FileDataBase64 && cropFile) {
634
+ this.getCroppedAndUpload(`data:${base64Result.ContentType};base64,${base64Result.Base64File}`, newAttachment);
635
+ }
636
+ }
637
+ return newAttachment;
638
+ }
639
+ /**
640
+ * A partire dal file passato in input restituisce un oggetto
641
+ * contenente il base64 del file e il suo contentType
642
+ * @param currentFile Oggetto File da cui estrapolare base64 e contentType
643
+ * @returns Restituisce un oggetto avente le proprietà Base64File e ContentType
644
+ */
645
+ async getBase64FromFile(currentFile) {
646
+ let base64File = await toBase64(currentFile);
647
+ let contentType = null;
648
+ if (base64File) {
649
+ // Loris 20/01/2022: PROBLEMA - Quando eseguo l'upload di un file .sql non viene salvato/scaricato correttamente.
650
+ // Questo succede perchè non viene popolato il FileContentType. Per risolvere il problema
651
+ // faccio un controllo e se non esiste il FileContentType allora lo recupero dal base64 ottenuto.
652
+ contentType = base64File.split(",")[0].split(":")[1].split(";")[0];
653
+ // Un altro metodo per leggere il ccontent type del file è tramite una regular expression:
654
+ base64File = base64File.split(",")[1];
655
+ }
656
+ let result = {
657
+ Base64File: base64File,
658
+ ContentType: contentType
659
+ };
660
+ return result;
661
+ }
662
+ /**
663
+ * Controlla se il file che si sta caricando è supportato dal sistema.
664
+ * @returns
665
+ */
666
+ checkAcceptedFiles() {
667
+ if ((this.loadMultipleFiles != true && this.selectedFile.type.startsWith("video")) ||
668
+ (this.loadMultipleFiles == true && [...this.selectedFiles].filter((p) => p.type.startsWith("video")).length > 0))
669
+ return false;
670
+ if (this.acceptedFileTypes == "*")
671
+ return true;
672
+ //Verifica che i tipi del file (o dei file) caricati siano coerenti con quelli accettati dalla direttiva
673
+ let accepted = true;
674
+ if (this.loadMultipleFiles != true)
675
+ accepted = this.acceptedFileTypes.includes(this.selectedFile.type);
676
+ else {
677
+ let uploadedFileTypes = [...this.selectedFiles].map((p) => p.type);
678
+ uploadedFileTypes.forEach((type) => {
679
+ if (!this.acceptedFileTypes.includes(type))
680
+ accepted = false;
681
+ });
682
+ }
683
+ //Questo controllo permette di gestire le casistiche per cui vengono indicati come tipi validi, ad esempio, 'image/*'
684
+ if (!accepted && this.loadMultipleFiles != true) {
685
+ for (let t of this.acceptedFileTypes.split(",").filter((t) => t.includes("*"))) {
686
+ accepted = this.selectedFile.type.startsWith(t.split("*")[0]);
687
+ if (accepted)
688
+ break;
689
+ }
690
+ }
691
+ return accepted;
692
+ }
693
+ /**
694
+ * Se eqp-attachments è stata configurata per il caricamento delle sole immagini allora verifica che il file passato in
695
+ * input sia effettivamente un immagine o no.
696
+ * Se il controllo va a buon fine restituisce TRUE altrimenti mostra un messaggio d'errore e restituisce FALSE
697
+ */
698
+ checkAllowOnlyImageFile(newAttachment) {
699
+ if (this.allowOnlyImages == true && newAttachment.IsImage != true) {
700
+ EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage);
701
+ this.abortFile();
702
+ return false;
703
+ }
704
+ else if (!this.checkAcceptedFiles()) {
705
+ EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage);
706
+ this.abortFile();
707
+ return false;
708
+ }
709
+ return true;
710
+ }
711
+ //#region Gestione crop file
712
+ getImageDimensions(img) {
713
+ const reader = new FileReader();
714
+ reader.onload = (e) => {
715
+ const image = new Image();
716
+ image.src = e.target.result;
717
+ image.onload = (rs) => {
718
+ this.originalHeight = rs.currentTarget["height"];
719
+ this.originalWidth = rs.currentTarget["width"];
720
+ if (this.originalWidth > 1280) {
721
+ this.customWidth = 1280;
722
+ this.customHeight = Math.round((1280 * this.originalHeight) / this.originalWidth);
723
+ }
724
+ else {
725
+ this.customHeight = rs.currentTarget["height"];
726
+ this.customWidth = rs.currentTarget["width"];
727
+ }
728
+ };
729
+ };
730
+ reader.readAsDataURL(img);
731
+ }
732
+ restoreOriginalDimensions() {
733
+ this.customWidth = this.originalWidth;
734
+ this.customHeight = this.originalHeight;
735
+ this.canvasRotation = 0;
736
+ this.transform = {};
737
+ }
738
+ onDimensionsChange(dimension) {
739
+ if (dimension == "H") {
740
+ this.customWidth = Math.round((this.customHeight * this.originalWidth) / this.originalHeight);
741
+ }
742
+ else if (dimension == "W") {
743
+ this.customHeight = Math.round((this.customWidth * this.originalHeight) / this.originalWidth);
744
+ }
745
+ }
746
+ imageCropped(event) {
747
+ this.croppedImage = event.base64;
748
+ this.getCroppedAndUpload(this.croppedImage, this.newAttachment);
749
+ }
750
+ getCroppedAndUpload(file, newAttachment) {
751
+ var self = this;
752
+ var file = base64ToFile(file);
753
+ const options = this.compressionOptions;
754
+ /**
755
+ * Comprime l'immagine passando come parametri le options create nell'oggetto sopra, e il file dal reader principale
756
+ */
757
+ imageCompression(file, options).then((fileCompressed) => {
758
+ let fileReader = new FileReader();
759
+ //Faccio la push di ogni file all'interno dell'array di file dell'item da mandare al server
760
+ fileReader.onload = function () {
761
+ let resultReader = fileReader.result;
762
+ var marker = ";base64,";
763
+ newAttachment.FileDataBase64 = resultReader.substring(resultReader.indexOf(marker) + marker.length);
764
+ self.showCropImage = false;
765
+ if (self.newAttachmentForm) {
766
+ self.newAttachmentForm.enable();
767
+ }
768
+ };
769
+ fileReader.readAsDataURL(fileCompressed);
770
+ });
771
+ }
772
+ // confirmCrop() {
773
+ // this.imageCropper.crop();
774
+ // this.dialogRefCropImage.close();
775
+ // this.restoreOriginalDimensions();
776
+ // }
777
+ rotateLeft() {
778
+ this.canvasRotation--;
779
+ this.flipAfterRotate();
780
+ }
781
+ rotateRight() {
782
+ this.canvasRotation++;
783
+ this.flipAfterRotate();
784
+ }
785
+ flipAfterRotate() {
786
+ const flippedH = this.transform.flipH;
787
+ const flippedV = this.transform.flipV;
788
+ this.transform = {
789
+ ...this.transform,
790
+ flipH: flippedV,
791
+ flipV: flippedH
792
+ };
793
+ }
794
+ flipHorizontal() {
795
+ this.transform = {
796
+ ...this.transform,
797
+ flipH: !this.transform.flipH
798
+ };
799
+ }
800
+ flipVertical() {
801
+ this.transform = {
802
+ ...this.transform,
803
+ flipV: !this.transform.flipV
804
+ };
805
+ }
806
+ //#endregion
807
+ /**
808
+ * Annulla la selezione del file, svuotando l'input e resettando tutte le proprietà dell'IAttachmentDTO
809
+ */
810
+ abortFile() {
811
+ if (this.imageInput)
812
+ this.imageInput.nativeElement.value = "";
813
+ this.selectedFile = null;
814
+ this.selectedFiles = null;
815
+ this.showCropImage = false;
816
+ this.newAttachment.IsImage = false;
817
+ this.newAttachment.FileDataBase64 = null;
818
+ this.newAttachment.FileName = null;
819
+ this.newAttachment.FileExtension = null;
820
+ this.newAttachment.FileContentType = null;
821
+ this.newMultipleAttachments = new Array();
822
+ this.customHeight = null;
823
+ this.customWidth = null;
824
+ this.originalHeight = null;
825
+ this.originalWidth = null;
826
+ this.dialogRefCropImage.close();
827
+ this.restoreOriginalDimensions();
828
+ }
829
+ //#endregion
830
+ // Viene creato un'array observables per memorizzare tutti gli observable creati dalle chiamate a fileEntry.file().
831
+ // Dopo che tutti gli observables sono stati completati, viene utilizzato il metodo subscribe() per eseguire la funzione onFileAdded().
832
+ fileDropped(files) {
833
+ let filesDropped = [];
834
+ const observables = [];
835
+ for (let i = 0; i < files.length; i++) {
836
+ if (files[i].fileEntry.isFile) {
837
+ const fileEntry = files[i].fileEntry;
838
+ const observable = new Observable((observer) => {
839
+ fileEntry.file((file) => {
840
+ filesDropped.push(file);
841
+ observer.next();
842
+ observer.complete();
843
+ });
844
+ });
845
+ observables.push(observable);
846
+ }
847
+ else {
848
+ const fileEntry = files[i].fileEntry;
849
+ console.log(files[i].relativePath, fileEntry);
850
+ }
851
+ }
852
+ from(observables)
853
+ .pipe(concatMap((observable) => observable))
854
+ .subscribe({
855
+ complete: () => {
856
+ this.onFileAdded(filesDropped, true);
857
+ }
858
+ });
859
+ }
860
+ // Se il caricamento del file dropbox va a buon fine, la funzione di callback restituisce un array di oggetti.
861
+ // Viene poi fatta una XMLHttpRequest con responseType 'blob' per convertire il primo elemento della response in un Blob.
862
+ chooseDropboxFile() {
863
+ var options = {
864
+ success: (files) => {
865
+ const xhr = new XMLHttpRequest();
866
+ xhr.open("GET", files[0].link);
867
+ xhr.setRequestHeader("Authorization", `Bearer ${AttachmentHelperService.dropboxCredentials.accessToken}`);
868
+ xhr.responseType = "blob";
869
+ xhr.onload = () => {
870
+ const blob = xhr.response;
871
+ const file = new File([blob], files[0].name, { type: blob.type });
872
+ let filesAdded = [file];
873
+ this.onFileAdded(filesAdded, true);
874
+ };
875
+ xhr.send();
876
+ },
877
+ linkType: "direct",
878
+ multiselect: false,
879
+ extensions: [".jpg", ".png", ".pdf", ".doc", ".docx", ".txt"]
880
+ };
881
+ Dropbox.choose(options);
882
+ }
883
+ // Workaround dropzone: disabilito il click degli elementi inclusi nella dropzone per evitare di cliccare due volte
884
+ onSelectFile(event, fileInput) {
885
+ if (event.target.tagName === "BUTTON" ||
886
+ event.target.tagName === "INPUT" ||
887
+ this.addingLinkMode == true) {
888
+ return;
889
+ }
890
+ fileInput.click();
891
+ }
892
+ // Metodo per visualizzare la form di aggiunta di un link
893
+ switchToAddingLinkMode() {
894
+ this.addingLinkMode = true;
895
+ this.newAttachment = {};
896
+ this.newAttachment.IsImage = false;
897
+ this.newAttachment.AttachmentType = this.attachmentType.LINK;
898
+ this.newMultipleAttachments = new Array();
899
+ this.newMultipleAttachments.push(this.newAttachment);
900
+ this.createAttachmentForm();
901
+ }
902
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EqpAttachmentsComponent, deps: [{ token: i1.MatDialog }, { token: i2.FormBuilder }, { token: i3.DomSanitizer }, { token: i4.HttpClient }, { token: i0.ChangeDetectorRef }, { token: i5.EqpAttachmentService }], target: i0.ɵɵFactoryTarget.Component });
903
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: EqpAttachmentsComponent, selector: "eqp-attachments", inputs: { disableAction: "disableAction", showHeader: "showHeader", headerTitle: "headerTitle", attachmentsList: "attachmentsList", showMatCard: "showMatCard", multipleAttachment: "multipleAttachment", loadMultipleFiles: "loadMultipleFiles", attachmentsColumns: "attachmentsColumns", emptyTableMessage: "emptyTableMessage", allowOnlyImages: "allowOnlyImages", acceptedFileTypes: "acceptedFileTypes", isDisabled: "isDisabled", showInlinePreview: "showInlinePreview", getAttachmentEndpoint: "getAttachmentEndpoint", productionBaseUrl: "productionBaseUrl", compressionOptions: "compressionOptions", allowedTypes: "allowedTypes", isEqpTableMultiLanguage: "isEqpTableMultiLanguage", tablePaginatorVisible: "tablePaginatorVisible", isTableSearcheable: "isTableSearcheable", tablePaginatorSize: "tablePaginatorSize", separatedUploadButtons: "separatedUploadButtons", showPreview: "showPreview", singleAttachmentDragAndDrop: "singleAttachmentDragAndDrop", cropOptions: "cropOptions", cropDialogClass: "cropDialogClass", downloadTooltipPosition: "downloadTooltipPosition", openLinkLabel: "openLinkLabel", addButtonLabel: "addButtonLabel", downloadLabel: "downloadLabel", deleteLabel: "deleteLabel", fileNameLabel: "fileNameLabel", previewLabel: "previewLabel", uploadFileLabel: "uploadFileLabel", confirmLabel: "confirmLabel", abortLabel: "abortLabel", saveLabel: "saveLabel", exitLabel: "exitLabel", uploadWithDropboxLabel: "uploadWithDropboxLabel", cropLabel: "cropLabel", eqpTableSearchText: "eqpTableSearchText", deleteDialogTitle: "deleteDialogTitle", deleteDialogMessage: "deleteDialogMessage", noImageSelectedErrorMessage: "noImageSelectedErrorMessage", wrongTypeSelectedErrorMessage: "wrongTypeSelectedErrorMessage", videoPreviewErrorMessage: "videoPreviewErrorMessage", audioPreviewErrorMessage: ["videoPreviewErrorMessage", "audioPreviewErrorMessage"], flipHorinzontalLabel: "flipHorinzontalLabel", flipVerticalLabel: "flipVerticalLabel", rotateRightLabel: "rotateRightLabel", rotateLeftLabel: "rotateLeftLabel" }, outputs: { localEditedAttachments: "localEditedAttachments", abortAddAttachment: "abortAddAttachment", downloadAttachment: "downloadAttachment", onDeleteAttachment: "onDeleteAttachment" }, viewQueries: [{ propertyName: "dialogAddAttachment", first: true, predicate: ["dialogAddAttachment"], descendants: true, static: true }, { propertyName: "dialogAddMultipleAttachment", first: true, predicate: ["dialogAddMultipleAttachment"], descendants: true, static: true }, { propertyName: "dialogCropImage", first: true, predicate: ["dialogCropImage"], descendants: true, static: true }, { propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true }, { propertyName: "attachmentTable", first: true, predicate: ["attachmentTable"], descendants: true }, { propertyName: "inlinePreviewTemplate", first: true, predicate: ["inlinePreviewTemplate"], descendants: true, static: true }, { propertyName: "dialogPreview", first: true, predicate: ["dialogPreview"], descendants: true, static: true }], ngImport: i0, template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n<div *ngIf=\"multipleAttachment != true\">\r\n <div *ngIf=\"!singleAttachmentDragAndDrop\">\r\n <!-- Template del button per l'aggiunta di un allegato -->\r\n <div *ngIf=\"!addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addAttachmentButton\"></ng-container>\r\n </div>\r\n <!-- Template della form per l'aggiunta di un link -->\r\n <div *ngIf=\"addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </div>\r\n </div>\r\n <div *ngIf=\"singleAttachmentDragAndDrop\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop\r\n (onFileDrop)=\"fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.includes(1) &&\r\n (!attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n </div>\r\n <div class=\"text-center\">\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-download-btn\"\r\n (click)=\"viewAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n color=\"primary\">\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType == AttachmentType.FILE\">download</mat-icon>\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType != AttachmentType.FILE\">open_in_new</mat-icon>\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-preview-btn\"\r\n (click)=\"openPreviewDialog(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"primary\"\r\n *ngIf=\"\r\n showPreview &&\r\n attachmentsList &&\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n (!attachmentsList[0].FileContentType ||\r\n (!attachmentsList[0].FileContentType.startsWith('video') &&\r\n !attachmentsList[0].FileContentType.startsWith('audio'))) &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n </div>\r\n <div\r\n class=\"row\"\r\n style=\"margin-top: 10px\"\r\n *ngIf=\"\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n attachmentsList[0].FileDataBase64 &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <div class=\"col-sm-12 d-flex justify-content-center\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{ attachmentsList[0].FileDataBase64 }}\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\" *ngIf=\"attachmentsList.length > 0 && attachmentsList[0] && attachmentsList[0].IsImage != true\">\r\n <div class=\"col-sm-12\">\r\n <mat-form-field>\r\n <mat-label>{{ fileNameLabel }}</mat-label>\r\n <input readonly matInput [(ngModel)]=\"attachmentsList[0].FileName\" />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"multipleAttachment == true\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop (onFileDrop)=\"fileDropped($event)\" (click)=\"onSelectFile($event, fileInput)\">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n <div class=\"mt-2\">\r\n <eqp-table\r\n #attachmentTable\r\n [createMatCard]=\"false\"\r\n #table\r\n [tableColumnFields]=\"attachmentsColumns\"\r\n [isMultiLanguage]=\"isEqpTableMultiLanguage\"\r\n [data]=\"attachmentsList\"\r\n [paginatorVisible]=\"tablePaginatorVisible\"\r\n [matPaginatorSize]=\"tablePaginatorSize\"\r\n [emptyTableMessage]=\"emptyTableMessage\"\r\n [searchText]=\"eqpTableSearchText\"\r\n [isTableSearcheable]=\"isTableSearcheable\">\r\n </eqp-table>\r\n </div>\r\n</div>\r\n\r\n<ng-template #dialogCropImage>\r\n <!-- Richiama il template per le funzionalit\u00E0 del CROPPIE -->\r\n <div style=\"overflow-x: hidden\" [ngClass]=\"cropDialogClass\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"croppieTemplate\"\r\n [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\"\r\n *ngIf=\"showCropImage == true\"></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <img src=\"data:image/png;base64,{{ row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64 }}\" />\r\n </div>\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && !row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #dialogPreview>\r\n <mat-card class=\"example-card\" *ngIf=\"selectedAttachment\">\r\n <mat-card-content>\r\n <div class=\"row\">\r\n <div class=\"header-title-standard\">\r\n {{ previewLabel }} {{ selectedAttachment?.AttachmentType == attachmentType.FILE ? \"File\" : \"Link\" }}\r\n <button\r\n type=\"button\"\r\n class=\"btn-close closeButton\"\r\n mat-dialog-close\r\n (click)=\"selectedAttachment = null\"></button>\r\n </div>\r\n </div>\r\n <div class=\"row mt-2\">\r\n <!-- ANTEPRIMA IMMAGINE -->\r\n <div class=\"col-12 text-center preview-container\" *ngIf=\"selectedAttachment.IsImage\">\r\n <img\r\n class=\"image-preview\"\r\n src=\"data:image/png;base64,{{\r\n selectedAttachment.FileDataBase64\r\n ? selectedAttachment.FileDataBase64\r\n : selectedAttachment.FileThumbnailBase64\r\n }}\" />\r\n </div>\r\n\r\n <!-- ANTEPRIMA LINK -->\r\n <div class=\"col-12 preview-container\" *ngIf=\"!selectedAttachment.IsImage\">\r\n <iframe\r\n class=\"link-preview\"\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n </div>\r\n <div class=\"row mt-3\">\r\n <div class=\"col-sm-12 text-center\">\r\n <button\r\n mat-mini-fab\r\n color=\"primary\"\r\n matTooltip=\"Download\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n *ngIf=\"selectedAttachment.AttachmentType != AttachmentType.LINK\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <!--\r\n Pulsanti per l'aggiunta di un file o un link. Ne viene visualizzato uno se:\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di pi\u00F9 allegati (multipleAttachment == true)\r\n OPPURE\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di un singolo allegato (multipleAttachment == true) e non ne \u00E8 ancora stato selezionato uno (ovvero attachmentsList non esiste o non ha elementi)\r\n -->\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.length == 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\"\r\n [disabled]=\"isDisabled\">\r\n <!-- Per l'aggiunta dei file mostro un'icona diversa dall'aggiunta dei link -->\r\n <mat-icon *ngIf=\"allowedTypes[0] == 1\">cloud_upload</mat-icon>\r\n <i class=\"fas fa-link\" *ngIf=\"allowedTypes[0] == 2\"></i>\r\n <i class=\"fa-brands fa-dropbox\" *ngIf=\"allowedTypes[0] == 3\"></i>\r\n <span style=\"margin-left: 10px\">\r\n {{\r\n allowedTypes[0] == 1\r\n ? addButtonLabel + \" file\"\r\n : allowedTypes[0] == 2\r\n ? addButtonLabel + \" link\"\r\n : uploadWithDropboxLabel\r\n }}</span\r\n >\r\n </button>\r\n\r\n <!-- Pulsante per aprire il menu per la scelta del tipo di Attachment da creare -->\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"\r\n [disabled]=\"isDisabled\"\r\n *ngIf=\"\r\n !separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <mat-icon *ngIf=\"multipleAttachment != true\">cloud_upload</mat-icon>\r\n <mat-icon *ngIf=\"multipleAttachment == true\">add</mat-icon>\r\n <span style=\"margin-left: 0px\"> {{ addButtonLabel }} </span>\r\n </button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"imageInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n\r\n <div\r\n *ngIf=\"\r\n separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <div class=\"btn-group\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n (click)=\"imageInput.click()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"row m-3\">\r\n <h4>{{ cropLabel }}</h4>\r\n </div>\r\n <div class=\"row m-2 crop-large\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n [matTooltip]=\"rotateLeftLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateLeft()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_left</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"rotateRightLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateRight()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_right</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipHorinzontalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipHorizontal()\">\r\n <mat-icon style=\"vertical-align: middle\">flip_horizontal</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipVerticalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipVertical()\">\r\n <div style=\"transform: rotate(90deg)\"><mat-icon style=\"vertical-align: middle\">flip_vertical</mat-icon></div>\r\n </button>\r\n <button\r\n [matTooltip]=\"'Reset'\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"restoreOriginalDimensions()\">\r\n <mat-icon style=\"vertical-align: middle\">replay</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row m-2 crop-small\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <mat-icon *ngIf=\"cropOptions.includes(1)\" style=\"font-size: 27px; vertical-align: middle\" (click)=\"rotateLeft()\"\r\n >rotate_left</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"rotateRight()\"\r\n >rotate_right</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipHorizontal()\"\r\n >flip_horizontal</mat-icon\r\n >\r\n <div class=\"ms-3\" style=\"transform: rotate(90deg)\">\r\n <mat-icon\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipVertical()\"\r\n >flip_vertical</mat-icon\r\n >\r\n </div>\r\n <mat-icon class=\"ms-3\" (click)=\"restoreOriginalDimensions()\" style=\"font-size: 27px; vertical-align: middle\"\r\n >replay</mat-icon\r\n >\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <div class=\"crop-container\">\r\n <image-cropper\r\n [imageFile]=\"selectedFile\"\r\n [maintainAspectRatio]=\"false\"\r\n [autoCrop]=\"false\"\r\n [containWithinAspectRatio]=\"false\"\r\n [aspectRatio]=\"4 / 3\"\r\n [cropperMinWidth]=\"128\"\r\n [onlyScaleDown]=\"true\"\r\n [roundCropper]=\"false\"\r\n [canvasRotation]=\"0\"\r\n [transform]=\"transform\"\r\n [alignImage]=\"'left'\"\r\n format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\"\r\n [canvasRotation]=\"canvasRotation\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-large\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button eqp-attachments-confirm-btn me-2\"\r\n type=\"button\"\r\n (click)=\"confirmAddAttachment()\">\r\n {{ confirmLabel }}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-abort-btn\" type=\"button\" (click)=\"abortFile()\">\r\n {{ abortLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-small\">\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-times\" (click)=\"abortFile()\"></i>\r\n </div>\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-check\" (click)=\"confirmAddAttachment()\"></i>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <span class=\"mb-1\" style=\"font-size: 20px\"><i class=\"fa fa-link\"></i>Inserisci l'URL</span>\r\n <form [formGroup]=\"newAttachmentForm\" *ngIf=\"newAttachmentForm\">\r\n <div class=\"row mb-2\" style=\"height: 80px\">\r\n <div class=\"col-6 d-grid gap-2 mx-auto\">\r\n <div class=\"input-group mb-1\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"{{ fileNameLabel }}\"\r\n formControlName=\"name\"\r\n [(ngModel)]=\"newAttachment.FileName\" />\r\n </div>\r\n </div>\r\n <div class=\"col-12 d-grid gap-2\">\r\n <div class=\"input-group\">\r\n <input\r\n required\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Link\"\r\n formControlName=\"path\"\r\n [(ngModel)]=\"newAttachment.FilePath\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-secondary mat-raised-button\"\r\n (click)=\"selectedAttachment = null; addingLinkMode = false\"\r\n type=\"button\">\r\n {{ exitLabel }}\r\n </button>\r\n </div>\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button\"\r\n type=\"submit\"\r\n (click)=\"confirmAddAttachment(); selectedAttachment = null; addingLinkMode = false\">\r\n {{ saveLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n</ng-template>\r\n", styles: ["ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone{min-height:30vh;border-radius:5px!important;background-color:#e4e6ea!important;cursor:pointer;font-size:17px!important;border:dotted!important;padding-top:7vh}ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone .ngx-file-drop__content{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#73777a!important;margin:auto}.custom-height .mat-form-field-wrapper{height:20px}.eqp-attachments-header-title{font-weight:700;font-size:19px;line-height:24px;margin-bottom:auto}.single-attachment-inline-preview-container{max-height:400px;max-width:400px;display:flex;align-items:center}.single-attachment-inline-preview-container img{max-width:100%;max-height:120px}.inline-preview-container{max-height:100px;max-width:100px;display:flex;align-items:center;justify-content:center;width:100%;cursor:pointer}.inline-preview-container img{max-width:100%;max-height:100px}.inline-preview-container i{font-size:25px;margin:auto}.preview-container{max-height:60vh;max-width:100%}.preview-container .image-preview{max-width:100%;max-height:100%}.preview-container .link-preview{width:70vw;height:55vh}.closeButton{float:right}@media (max-width: 768px){.crop-large{display:none}}@media (min-width: 768px){.crop-small{display:none}}@media (max-width: 768px){.crop-container{max-width:55%}}@media (min-width: 768px){.crop-container{max-width:35%}}\n"], dependencies: [{ kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab]", exportAs: ["matButton"] }, { 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.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i10.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i11.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i13.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i13.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i13.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i14.ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "cropperFrameAriaLabel", "output", "format", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "autoCrop", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "cropper", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange"] }, { kind: "component", type: i15.EqpTableComponent, selector: "eqp-table" }, { kind: "component", type: i16.NgxFileDropComponent, selector: "ngx-file-drop", inputs: ["accept", "directory", "multiple", "dropZoneLabel", "dropZoneClassName", "useDragEnter", "contentClassName", "showBrowseBtn", "browseBtnClassName", "browseBtnLabel", "disabled"], outputs: ["onFileDrop", "onFileOver", "onFileLeave"] }, { kind: "directive", type: i16.NgxFileDropContentTemplateDirective, selector: "[ngx-file-drop-content-tmp]" }] });
904
+ }
905
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EqpAttachmentsComponent, decorators: [{
906
+ type: Component,
907
+ args: [{ selector: "eqp-attachments", template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n<div *ngIf=\"multipleAttachment != true\">\r\n <div *ngIf=\"!singleAttachmentDragAndDrop\">\r\n <!-- Template del button per l'aggiunta di un allegato -->\r\n <div *ngIf=\"!addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addAttachmentButton\"></ng-container>\r\n </div>\r\n <!-- Template della form per l'aggiunta di un link -->\r\n <div *ngIf=\"addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </div>\r\n </div>\r\n <div *ngIf=\"singleAttachmentDragAndDrop\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop\r\n (onFileDrop)=\"fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.includes(1) &&\r\n (!attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n </div>\r\n <div class=\"text-center\">\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-download-btn\"\r\n (click)=\"viewAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n color=\"primary\">\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType == AttachmentType.FILE\">download</mat-icon>\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType != AttachmentType.FILE\">open_in_new</mat-icon>\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-preview-btn\"\r\n (click)=\"openPreviewDialog(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"primary\"\r\n *ngIf=\"\r\n showPreview &&\r\n attachmentsList &&\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n (!attachmentsList[0].FileContentType ||\r\n (!attachmentsList[0].FileContentType.startsWith('video') &&\r\n !attachmentsList[0].FileContentType.startsWith('audio'))) &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n </div>\r\n <div\r\n class=\"row\"\r\n style=\"margin-top: 10px\"\r\n *ngIf=\"\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n attachmentsList[0].FileDataBase64 &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <div class=\"col-sm-12 d-flex justify-content-center\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{ attachmentsList[0].FileDataBase64 }}\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\" *ngIf=\"attachmentsList.length > 0 && attachmentsList[0] && attachmentsList[0].IsImage != true\">\r\n <div class=\"col-sm-12\">\r\n <mat-form-field>\r\n <mat-label>{{ fileNameLabel }}</mat-label>\r\n <input readonly matInput [(ngModel)]=\"attachmentsList[0].FileName\" />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"multipleAttachment == true\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop (onFileDrop)=\"fileDropped($event)\" (click)=\"onSelectFile($event, fileInput)\">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n <div class=\"mt-2\">\r\n <eqp-table\r\n #attachmentTable\r\n [createMatCard]=\"false\"\r\n #table\r\n [tableColumnFields]=\"attachmentsColumns\"\r\n [isMultiLanguage]=\"isEqpTableMultiLanguage\"\r\n [data]=\"attachmentsList\"\r\n [paginatorVisible]=\"tablePaginatorVisible\"\r\n [matPaginatorSize]=\"tablePaginatorSize\"\r\n [emptyTableMessage]=\"emptyTableMessage\"\r\n [searchText]=\"eqpTableSearchText\"\r\n [isTableSearcheable]=\"isTableSearcheable\">\r\n </eqp-table>\r\n </div>\r\n</div>\r\n\r\n<ng-template #dialogCropImage>\r\n <!-- Richiama il template per le funzionalit\u00E0 del CROPPIE -->\r\n <div style=\"overflow-x: hidden\" [ngClass]=\"cropDialogClass\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"croppieTemplate\"\r\n [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\"\r\n *ngIf=\"showCropImage == true\"></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <img src=\"data:image/png;base64,{{ row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64 }}\" />\r\n </div>\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && !row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #dialogPreview>\r\n <mat-card class=\"example-card\" *ngIf=\"selectedAttachment\">\r\n <mat-card-content>\r\n <div class=\"row\">\r\n <div class=\"header-title-standard\">\r\n {{ previewLabel }} {{ selectedAttachment?.AttachmentType == attachmentType.FILE ? \"File\" : \"Link\" }}\r\n <button\r\n type=\"button\"\r\n class=\"btn-close closeButton\"\r\n mat-dialog-close\r\n (click)=\"selectedAttachment = null\"></button>\r\n </div>\r\n </div>\r\n <div class=\"row mt-2\">\r\n <!-- ANTEPRIMA IMMAGINE -->\r\n <div class=\"col-12 text-center preview-container\" *ngIf=\"selectedAttachment.IsImage\">\r\n <img\r\n class=\"image-preview\"\r\n src=\"data:image/png;base64,{{\r\n selectedAttachment.FileDataBase64\r\n ? selectedAttachment.FileDataBase64\r\n : selectedAttachment.FileThumbnailBase64\r\n }}\" />\r\n </div>\r\n\r\n <!-- ANTEPRIMA LINK -->\r\n <div class=\"col-12 preview-container\" *ngIf=\"!selectedAttachment.IsImage\">\r\n <iframe\r\n class=\"link-preview\"\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n </div>\r\n <div class=\"row mt-3\">\r\n <div class=\"col-sm-12 text-center\">\r\n <button\r\n mat-mini-fab\r\n color=\"primary\"\r\n matTooltip=\"Download\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n *ngIf=\"selectedAttachment.AttachmentType != AttachmentType.LINK\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <!--\r\n Pulsanti per l'aggiunta di un file o un link. Ne viene visualizzato uno se:\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di pi\u00F9 allegati (multipleAttachment == true)\r\n OPPURE\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di un singolo allegato (multipleAttachment == true) e non ne \u00E8 ancora stato selezionato uno (ovvero attachmentsList non esiste o non ha elementi)\r\n -->\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.length == 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\"\r\n [disabled]=\"isDisabled\">\r\n <!-- Per l'aggiunta dei file mostro un'icona diversa dall'aggiunta dei link -->\r\n <mat-icon *ngIf=\"allowedTypes[0] == 1\">cloud_upload</mat-icon>\r\n <i class=\"fas fa-link\" *ngIf=\"allowedTypes[0] == 2\"></i>\r\n <i class=\"fa-brands fa-dropbox\" *ngIf=\"allowedTypes[0] == 3\"></i>\r\n <span style=\"margin-left: 10px\">\r\n {{\r\n allowedTypes[0] == 1\r\n ? addButtonLabel + \" file\"\r\n : allowedTypes[0] == 2\r\n ? addButtonLabel + \" link\"\r\n : uploadWithDropboxLabel\r\n }}</span\r\n >\r\n </button>\r\n\r\n <!-- Pulsante per aprire il menu per la scelta del tipo di Attachment da creare -->\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"\r\n [disabled]=\"isDisabled\"\r\n *ngIf=\"\r\n !separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <mat-icon *ngIf=\"multipleAttachment != true\">cloud_upload</mat-icon>\r\n <mat-icon *ngIf=\"multipleAttachment == true\">add</mat-icon>\r\n <span style=\"margin-left: 0px\"> {{ addButtonLabel }} </span>\r\n </button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"imageInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n\r\n <div\r\n *ngIf=\"\r\n separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <div class=\"btn-group\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n (click)=\"imageInput.click()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"row m-3\">\r\n <h4>{{ cropLabel }}</h4>\r\n </div>\r\n <div class=\"row m-2 crop-large\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n [matTooltip]=\"rotateLeftLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateLeft()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_left</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"rotateRightLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateRight()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_right</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipHorinzontalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipHorizontal()\">\r\n <mat-icon style=\"vertical-align: middle\">flip_horizontal</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipVerticalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipVertical()\">\r\n <div style=\"transform: rotate(90deg)\"><mat-icon style=\"vertical-align: middle\">flip_vertical</mat-icon></div>\r\n </button>\r\n <button\r\n [matTooltip]=\"'Reset'\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"restoreOriginalDimensions()\">\r\n <mat-icon style=\"vertical-align: middle\">replay</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row m-2 crop-small\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <mat-icon *ngIf=\"cropOptions.includes(1)\" style=\"font-size: 27px; vertical-align: middle\" (click)=\"rotateLeft()\"\r\n >rotate_left</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"rotateRight()\"\r\n >rotate_right</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipHorizontal()\"\r\n >flip_horizontal</mat-icon\r\n >\r\n <div class=\"ms-3\" style=\"transform: rotate(90deg)\">\r\n <mat-icon\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipVertical()\"\r\n >flip_vertical</mat-icon\r\n >\r\n </div>\r\n <mat-icon class=\"ms-3\" (click)=\"restoreOriginalDimensions()\" style=\"font-size: 27px; vertical-align: middle\"\r\n >replay</mat-icon\r\n >\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <div class=\"crop-container\">\r\n <image-cropper\r\n [imageFile]=\"selectedFile\"\r\n [maintainAspectRatio]=\"false\"\r\n [autoCrop]=\"false\"\r\n [containWithinAspectRatio]=\"false\"\r\n [aspectRatio]=\"4 / 3\"\r\n [cropperMinWidth]=\"128\"\r\n [onlyScaleDown]=\"true\"\r\n [roundCropper]=\"false\"\r\n [canvasRotation]=\"0\"\r\n [transform]=\"transform\"\r\n [alignImage]=\"'left'\"\r\n format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\"\r\n [canvasRotation]=\"canvasRotation\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-large\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button eqp-attachments-confirm-btn me-2\"\r\n type=\"button\"\r\n (click)=\"confirmAddAttachment()\">\r\n {{ confirmLabel }}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-abort-btn\" type=\"button\" (click)=\"abortFile()\">\r\n {{ abortLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-small\">\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-times\" (click)=\"abortFile()\"></i>\r\n </div>\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-check\" (click)=\"confirmAddAttachment()\"></i>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <span class=\"mb-1\" style=\"font-size: 20px\"><i class=\"fa fa-link\"></i>Inserisci l'URL</span>\r\n <form [formGroup]=\"newAttachmentForm\" *ngIf=\"newAttachmentForm\">\r\n <div class=\"row mb-2\" style=\"height: 80px\">\r\n <div class=\"col-6 d-grid gap-2 mx-auto\">\r\n <div class=\"input-group mb-1\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"{{ fileNameLabel }}\"\r\n formControlName=\"name\"\r\n [(ngModel)]=\"newAttachment.FileName\" />\r\n </div>\r\n </div>\r\n <div class=\"col-12 d-grid gap-2\">\r\n <div class=\"input-group\">\r\n <input\r\n required\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Link\"\r\n formControlName=\"path\"\r\n [(ngModel)]=\"newAttachment.FilePath\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-secondary mat-raised-button\"\r\n (click)=\"selectedAttachment = null; addingLinkMode = false\"\r\n type=\"button\">\r\n {{ exitLabel }}\r\n </button>\r\n </div>\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button\"\r\n type=\"submit\"\r\n (click)=\"confirmAddAttachment(); selectedAttachment = null; addingLinkMode = false\">\r\n {{ saveLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n</ng-template>\r\n", styles: ["ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone{min-height:30vh;border-radius:5px!important;background-color:#e4e6ea!important;cursor:pointer;font-size:17px!important;border:dotted!important;padding-top:7vh}ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone .ngx-file-drop__content{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#73777a!important;margin:auto}.custom-height .mat-form-field-wrapper{height:20px}.eqp-attachments-header-title{font-weight:700;font-size:19px;line-height:24px;margin-bottom:auto}.single-attachment-inline-preview-container{max-height:400px;max-width:400px;display:flex;align-items:center}.single-attachment-inline-preview-container img{max-width:100%;max-height:120px}.inline-preview-container{max-height:100px;max-width:100px;display:flex;align-items:center;justify-content:center;width:100%;cursor:pointer}.inline-preview-container img{max-width:100%;max-height:100px}.inline-preview-container i{font-size:25px;margin:auto}.preview-container{max-height:60vh;max-width:100%}.preview-container .image-preview{max-width:100%;max-height:100%}.preview-container .link-preview{width:70vw;height:55vh}.closeButton{float:right}@media (max-width: 768px){.crop-large{display:none}}@media (min-width: 768px){.crop-small{display:none}}@media (max-width: 768px){.crop-container{max-width:55%}}@media (min-width: 768px){.crop-container{max-width:35%}}\n"] }]
908
+ }], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2.FormBuilder }, { type: i3.DomSanitizer }, { type: i4.HttpClient }, { type: i0.ChangeDetectorRef }, { type: i5.EqpAttachmentService }], propDecorators: { disableAction: [{
909
+ type: Input,
910
+ args: ["disableAction"]
911
+ }], showHeader: [{
912
+ type: Input,
913
+ args: ["showHeader"]
914
+ }], headerTitle: [{
915
+ type: Input,
916
+ args: ["headerTitle"]
917
+ }], attachmentsList: [{
918
+ type: Input,
919
+ args: ["attachmentsList"]
920
+ }], showMatCard: [{
921
+ type: Input,
922
+ args: ["showMatCard"]
923
+ }], multipleAttachment: [{
924
+ type: Input,
925
+ args: ["multipleAttachment"]
926
+ }], loadMultipleFiles: [{
927
+ type: Input,
928
+ args: ["loadMultipleFiles"]
929
+ }], attachmentsColumns: [{
930
+ type: Input,
931
+ args: ["attachmentsColumns"]
932
+ }], emptyTableMessage: [{
933
+ type: Input,
934
+ args: ["emptyTableMessage"]
935
+ }], allowOnlyImages: [{
936
+ type: Input,
937
+ args: ["allowOnlyImages"]
938
+ }], acceptedFileTypes: [{
939
+ type: Input,
940
+ args: ["acceptedFileTypes"]
941
+ }], isDisabled: [{
942
+ type: Input,
943
+ args: ["isDisabled"]
944
+ }], showInlinePreview: [{
945
+ type: Input,
946
+ args: ["showInlinePreview"]
947
+ }], getAttachmentEndpoint: [{
948
+ type: Input,
949
+ args: ["getAttachmentEndpoint"]
950
+ }], productionBaseUrl: [{
951
+ type: Input,
952
+ args: ["productionBaseUrl"]
953
+ }], compressionOptions: [{
954
+ type: Input,
955
+ args: ["compressionOptions"]
956
+ }], allowedTypes: [{
957
+ type: Input,
958
+ args: ["allowedTypes"]
959
+ }], isEqpTableMultiLanguage: [{
960
+ type: Input,
961
+ args: ["isEqpTableMultiLanguage"]
962
+ }], tablePaginatorVisible: [{
963
+ type: Input,
964
+ args: ["tablePaginatorVisible"]
965
+ }], isTableSearcheable: [{
966
+ type: Input,
967
+ args: ["isTableSearcheable"]
968
+ }], tablePaginatorSize: [{
969
+ type: Input,
970
+ args: ["tablePaginatorSize"]
971
+ }], separatedUploadButtons: [{
972
+ type: Input,
973
+ args: ["separatedUploadButtons"]
974
+ }], showPreview: [{
975
+ type: Input,
976
+ args: ["showPreview"]
977
+ }], singleAttachmentDragAndDrop: [{
978
+ type: Input,
979
+ args: ["singleAttachmentDragAndDrop"]
980
+ }], cropOptions: [{
981
+ type: Input,
982
+ args: ["cropOptions"]
983
+ }], cropDialogClass: [{
984
+ type: Input,
985
+ args: ["cropDialogClass"]
986
+ }], downloadTooltipPosition: [{
987
+ type: Input,
988
+ args: ["downloadTooltipPosition"]
989
+ }], openLinkLabel: [{
990
+ type: Input,
991
+ args: ["openLinkLabel"]
992
+ }], addButtonLabel: [{
993
+ type: Input,
994
+ args: ["addButtonLabel"]
995
+ }], downloadLabel: [{
996
+ type: Input,
997
+ args: ["downloadLabel"]
998
+ }], deleteLabel: [{
999
+ type: Input,
1000
+ args: ["deleteLabel"]
1001
+ }], fileNameLabel: [{
1002
+ type: Input,
1003
+ args: ["fileNameLabel"]
1004
+ }], previewLabel: [{
1005
+ type: Input,
1006
+ args: ["previewLabel"]
1007
+ }], uploadFileLabel: [{
1008
+ type: Input,
1009
+ args: ["uploadFileLabel"]
1010
+ }], confirmLabel: [{
1011
+ type: Input,
1012
+ args: ["confirmLabel"]
1013
+ }], abortLabel: [{
1014
+ type: Input,
1015
+ args: ["abortLabel"]
1016
+ }], saveLabel: [{
1017
+ type: Input,
1018
+ args: ["saveLabel"]
1019
+ }], exitLabel: [{
1020
+ type: Input,
1021
+ args: ["exitLabel"]
1022
+ }], uploadWithDropboxLabel: [{
1023
+ type: Input,
1024
+ args: ["uploadWithDropboxLabel"]
1025
+ }], cropLabel: [{
1026
+ type: Input,
1027
+ args: ["cropLabel"]
1028
+ }], eqpTableSearchText: [{
1029
+ type: Input,
1030
+ args: ["eqpTableSearchText"]
1031
+ }], deleteDialogTitle: [{
1032
+ type: Input,
1033
+ args: ["deleteDialogTitle"]
1034
+ }], deleteDialogMessage: [{
1035
+ type: Input,
1036
+ args: ["deleteDialogMessage"]
1037
+ }], noImageSelectedErrorMessage: [{
1038
+ type: Input,
1039
+ args: ["noImageSelectedErrorMessage"]
1040
+ }], wrongTypeSelectedErrorMessage: [{
1041
+ type: Input,
1042
+ args: ["wrongTypeSelectedErrorMessage"]
1043
+ }], videoPreviewErrorMessage: [{
1044
+ type: Input,
1045
+ args: ["videoPreviewErrorMessage"]
1046
+ }], audioPreviewErrorMessage: [{
1047
+ type: Input,
1048
+ args: ["videoPreviewErrorMessage"]
1049
+ }], flipHorinzontalLabel: [{
1050
+ type: Input,
1051
+ args: ["flipHorinzontalLabel"]
1052
+ }], flipVerticalLabel: [{
1053
+ type: Input,
1054
+ args: ["flipVerticalLabel"]
1055
+ }], rotateRightLabel: [{
1056
+ type: Input,
1057
+ args: ["rotateRightLabel"]
1058
+ }], rotateLeftLabel: [{
1059
+ type: Input,
1060
+ args: ["rotateLeftLabel"]
1061
+ }], localEditedAttachments: [{
1062
+ type: Output
1063
+ }], abortAddAttachment: [{
1064
+ type: Output
1065
+ }], downloadAttachment: [{
1066
+ type: Output,
1067
+ args: ["downloadAttachment"]
1068
+ }], onDeleteAttachment: [{
1069
+ type: Output,
1070
+ args: ["onDeleteAttachment"]
1071
+ }], dialogAddAttachment: [{
1072
+ type: ViewChild,
1073
+ args: ["dialogAddAttachment", { static: true }]
1074
+ }], dialogAddMultipleAttachment: [{
1075
+ type: ViewChild,
1076
+ args: ["dialogAddMultipleAttachment", { static: true }]
1077
+ }], dialogCropImage: [{
1078
+ type: ViewChild,
1079
+ args: ["dialogCropImage", { static: true }]
1080
+ }], imageCropper: [{
1081
+ type: ViewChild,
1082
+ args: [ImageCropperComponent]
1083
+ }], imageInput: [{
1084
+ type: ViewChild,
1085
+ args: ["imageInput"]
1086
+ }], attachmentTable: [{
1087
+ type: ViewChild,
1088
+ args: ["attachmentTable", { static: false }]
1089
+ }], inlinePreviewTemplate: [{
1090
+ type: ViewChild,
1091
+ args: ["inlinePreviewTemplate", { static: true }]
1092
+ }], dialogPreview: [{
1093
+ type: ViewChild,
1094
+ args: ["dialogPreview", { static: true }]
1095
+ }] } });
1096
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2VxcC1hdHRhY2htZW50cy9zcmMvbGliL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtYXR0YWNobWVudHMvc3JjL2xpYi9lcXAtYXR0YWNobWVudHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUVMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFTixTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUEwQixVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUlwRSxPQUFPLEVBQW9CLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFGLE9BQU8sZ0JBQWdCLE1BQU0sMkJBQTJCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBcUIscUJBQXFCLEVBQWtCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0csT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGNBQWMsRUFBa0MsTUFBTSwwQkFBMEIsQ0FBQztBQUUxRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUl0RixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUduRCxNQUFNLFFBQVEsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQ3hCLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBQ3RDLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7SUFDaEMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQixNQUFNLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDeEQsTUFBTSxDQUFDLE9BQU8sR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzVDLENBQUMsQ0FBQyxDQUFDO0FBT0wsTUFBTSxPQUFPLHVCQUF1QjtJQWdReEI7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBcFFWLCtCQUErQjtJQUUvQjs7T0FFRztJQUNxQixhQUFhLEdBQVksS0FBSyxDQUFDO0lBRXZEOztPQUVHO0lBQ2tCLFVBQVUsR0FBWSxJQUFJLENBQUM7SUFFaEQ7O09BRUc7SUFDbUIsV0FBVyxHQUFXLGlCQUFpQixDQUFDO0lBRTlEOztPQUVHO0lBQ3VCLGVBQWUsR0FBMEIsSUFBSSxDQUFDO0lBRXhFOztPQUVHO0lBQ21CLFdBQVcsR0FBWSxJQUFJLENBQUM7SUFFbEQ7OztPQUdHO0lBQzBCLGtCQUFrQixHQUFZLElBQUksQ0FBQztJQUVoRTs7O09BR0c7SUFDeUIsaUJBQWlCLEdBQVksS0FBSyxDQUFDO0lBRS9EOztPQUVHO0lBQzBCLGtCQUFrQixHQUE0QixJQUFJLENBQUM7SUFFaEY7O09BRUc7SUFDeUIsaUJBQWlCLEdBQVcscUJBQXFCLENBQUM7SUFFOUU7Ozs7T0FJRztJQUN1QixlQUFlLEdBQVksS0FBSyxDQUFDO0lBRTNEOztPQUVHO0lBQ3lCLGlCQUFpQixDQUFTO0lBRXREOztPQUVHO0lBQ2tCLFVBQVUsR0FBWSxLQUFLLENBQUM7SUFFakQ7O09BRUc7SUFDeUIsaUJBQWlCLEdBQVksS0FBSyxDQUFDO0lBRS9EOzs7OztPQUtHO0lBQzZCLHFCQUFxQixHQUFXLElBQUksQ0FBQztJQUVyRTs7Ozs7T0FLRztJQUN5QixpQkFBaUIsR0FBVyxJQUFJLENBQUM7SUFFN0Q7O09BRUc7SUFDMEIsa0JBQWtCLEdBQWE7UUFDMUQsU0FBUyxFQUFFLEdBQUc7UUFDZCxnQkFBZ0IsRUFBRSxJQUFJO1FBQ3RCLFlBQVksRUFBRSxJQUFJO0tBQ25CLENBQUM7SUFFRjs7T0FFRztJQUNvQixZQUFZLEdBQTBCLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFeEc7OztPQUdHO0lBQytCLHVCQUF1QixHQUFZLEtBQUssQ0FBQztJQUUzRTs7O09BR0c7SUFDNkIscUJBQXFCLEdBQVksSUFBSSxDQUFDO0lBRXRFOzs7T0FHRztJQUMwQixrQkFBa0IsR0FBWSxJQUFJLENBQUM7SUFFaEU7OztPQUdHO0lBQzBCLGtCQUFrQixHQUFXLElBQUksQ0FBQztJQUUvRDs7T0FFRztJQUNILGtGQUFrRjtJQUVsRjs7T0FFRztJQUM4QixzQkFBc0IsR0FBWSxLQUFLLENBQUM7SUFFekU7O09BRUc7SUFDbUIsV0FBVyxHQUFZLElBQUksQ0FBQztJQUVsRDs7T0FFRztJQUNtQywyQkFBMkIsR0FBWSxLQUFLLENBQUM7SUFFbkY7O09BRUc7SUFDbUIsV0FBVyxHQUEwQixFQUFFLENBQUM7SUFFOUQ7O09BRUc7SUFDdUIsZUFBZSxDQUFTO0lBRWxEOztPQUVHO0lBQytCLHVCQUF1QixHQUF3QixtQkFBbUIsQ0FBQyxLQUFLLENBQUM7SUFDbkYsYUFBYSxHQUFXLFdBQVcsQ0FBQztJQUNuQyxjQUFjLEdBQVcsVUFBVSxDQUFDO0lBQ3JDLGFBQWEsR0FBVyxVQUFVLENBQUM7SUFDckMsV0FBVyxHQUFXLFNBQVMsQ0FBQztJQUM5QixhQUFhLEdBQVcsV0FBVyxDQUFDO0lBQ3JDLFlBQVksR0FBVyxXQUFXLENBQUM7SUFDaEMsZUFBZSxHQUFXLGFBQWEsQ0FBQztJQUMzQyxZQUFZLEdBQVcsVUFBVSxDQUFDO0lBQ3BDLFVBQVUsR0FBVyxTQUFTLENBQUM7SUFDaEMsU0FBUyxHQUFXLE9BQU8sQ0FBQztJQUM1QixTQUFTLEdBQVcsTUFBTSxDQUFDO0lBQ2Qsc0JBQXNCLEdBQVcsb0JBQW9CLENBQUM7SUFDbkUsU0FBUyxHQUFXLG9DQUFvQyxDQUFDO0lBQ2hELGtCQUFrQixHQUFXLE9BQU8sQ0FBQztJQUN0QyxpQkFBaUIsR0FBVyxJQUFJLENBQUM7SUFDL0IsbUJBQW1CLEdBQVcsZ0RBQWdELENBQUM7SUFDdkUsMkJBQTJCLEdBQy9ELDhEQUE4RCxDQUFDO0lBQ3pCLDZCQUE2QixHQUNuRSwrQ0FBK0MsQ0FBQztJQUNmLHdCQUF3QixHQUN6RCxrREFBa0QsQ0FBQztJQUNsQix3QkFBd0IsR0FDekQsa0RBQWtELENBQUM7SUFDdEIsb0JBQW9CLEdBQVcsMkJBQTJCLENBQUM7SUFDOUQsaUJBQWlCLEdBQVcseUJBQXlCLENBQUM7SUFDdkQsZ0JBQWdCLEdBQVcsZ0JBQWdCLENBQUM7SUFDN0MsZUFBZSxHQUFXLGtCQUFrQixDQUFDO0lBQ3ZFLFlBQVk7SUFFWixnQ0FBZ0M7SUFFaEM7O09BRUc7SUFDTyxzQkFBc0IsR0FBd0MsSUFBSSxZQUFZLEVBQXlCLENBQUM7SUFFbEg7O09BRUc7SUFDTyxrQkFBa0IsR0FBc0IsSUFBSSxZQUFZLEVBQU8sQ0FBQztJQUUxRTs7T0FFRztJQUMyQixrQkFBa0IsR0FBaUMsSUFBSSxZQUFZLEVBQWtCLENBQUM7SUFFcEg7O09BRUc7SUFDMkIsa0JBQWtCLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDO0lBRXBILFlBQVk7SUFFWiwyREFBMkQ7SUFDM0QsYUFBYSxHQUFtQixFQUFvQixDQUFDO0lBQ3JELHNCQUFzQixHQUEwQixFQUFFLENBQUM7SUFDbkQsY0FBYyxHQUFHLGNBQWMsQ0FBQztJQUNoQyxtQ0FBbUM7SUFDbkMsaUJBQWlCLENBQVk7SUFDN0IsWUFBWSxHQUFTLElBQUksQ0FBQztJQUMxQixhQUFhLEdBQWdCLElBQUksQ0FBQztJQUNsQyxhQUFhLEdBQVksS0FBSyxDQUFDO0lBQ3FCLG1CQUFtQixDQUFtQjtJQUMxRixzQkFBc0IsQ0FBaUM7SUFDSywyQkFBMkIsQ0FBbUI7SUFDMUcsa0JBQWtCLENBQWlDO0lBQ0gsZUFBZSxDQUFtQjtJQUNsRixZQUFZO0lBRVoscUVBQXFFO0lBQ3JFLGlCQUFpQixHQUFRLEVBQUUsQ0FBQztJQUM1QixZQUFZLEdBQVEsRUFBRSxDQUFDO0lBQ3ZCLFNBQVMsR0FBbUIsRUFBRSxDQUFDO0lBQy9CLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDZSxZQUFZLENBQXdCO0lBQzdDLFVBQVUsQ0FBTTtJQUN6QyxZQUFZO0lBRVosY0FBYyxHQUFHLGNBQWMsQ0FBQztJQUNoQyxrQkFBa0IsQ0FBaUI7SUFFbkMsYUFBYSxDQUFTO0lBQ3RCLGNBQWMsQ0FBUztJQUN2QixXQUFXLENBQVM7SUFDcEIsWUFBWSxDQUFTO0lBRTRCLGVBQWUsQ0FBb0I7SUFDOUIscUJBQXFCLENBQW1CO0lBQ2hELGFBQWEsQ0FBbUI7SUFFOUUsU0FBUyxDQUFPO0lBRWhCLGNBQWMsR0FBWSxLQUFLLENBQUM7SUFFaEMsWUFDVSxNQUFpQixFQUNqQixXQUF3QixFQUN4QixTQUF1QixFQUN2QixJQUFnQixFQUNoQixFQUFxQixFQUNyQixvQkFBMEM7UUFMMUMsV0FBTSxHQUFOLE1BQU0sQ0FBVztRQUNqQixnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixjQUFTLEdBQVQsU0FBUyxDQUFjO1FBQ3ZCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUFDckIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtJQUNqRCxDQUFDO0lBRUosS0FBSyxDQUFDLFFBQVE7UUFDWix1SEFBdUg7UUFDdkgsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUI7WUFDekIsSUFBSSxJQUFJLENBQUMsZUFBZSxJQUFJLElBQUk7Z0JBQUUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQzs7Z0JBQ2hFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxHQUFHLENBQUM7UUFFcEMsc0hBQXNIO1FBQ3RILElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxJQUFJLENBQUM7WUFDckQsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDcEYsSUFDSCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLGNBQWMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLGNBQWMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFDbEg7WUFDQSwwQkFBMEIsQ0FBQyxPQUFPLENBQ2hDLHNGQUFzRixDQUN2RixDQUFDO1lBQ0YsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDeEY7UUFFRCx1RkFBdUY7UUFDdkYsSUFBSSxJQUFJLENBQUMsa0JBQWtCLElBQUksSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRTtZQUN4RyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUN6QjtRQUVELElBQUksSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJO1lBQUUsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLEtBQUssRUFBa0IsQ0FBQztRQUVyRixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUU1QixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1NBQy9DO0lBQ0gsQ0FBQztJQUVNLFVBQVU7UUFDZixJQUFJLElBQUksQ0FBQyxlQUFlO1lBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUNuRSxDQUFDO0lBRUQsb0JBQW9CO1FBQ2xCLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDakMsQ0FBQyxDQUFDLE9BQU8sR0FBRyx1QkFBdUIsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDaEYsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsa0NBQWtDO0lBRWxDOztPQUVHO0lBQ0gsZ0JBQWdCO1FBQ2QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztRQUM3QixJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxFQUFFO1lBQzlCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUM7Z0JBQzNCLEdBQUcsRUFBRSxRQUFRO2dCQUNiLE9BQU8sRUFBRSxFQUFFO2dCQUNYLElBQUksRUFBRSxVQUFVLENBQUMsVUFBVTtnQkFDM0IsY0FBYyxFQUFFLFdBQVc7Z0JBQzNCLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7Z0JBQzFCLE9BQU8sRUFBRTtvQkFDUCxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsRUFBRTtpQkFDeEc7YUFDRixDQUFDLENBQUM7U0FDSjtRQUVELElBQUksY0FBYyxHQUFHO1lBQ25CLEdBQUcsRUFBRSxZQUFZO1lBQ2pCLE9BQU8sRUFBRSxFQUFFO1lBQ1gsSUFBSSxFQUFFLFVBQVUsQ0FBQyxZQUFZO1lBQzdCLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7WUFDMUIsT0FBTyxFQUFFO2dCQUNQO29CQUNFLElBQUksRUFBRSxFQUFFO29CQUNSLFdBQVcsRUFBRSxJQUFJO29CQUNqQixJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTt3QkFDaEIsT0FBTyxJQUFJLENBQUMsaUJBQWlCOzRCQUMzQixDQUFDLENBQUMsT0FBTyxDQUFDLGNBQWMsSUFBSSxjQUFjLENBQUMsSUFBSTtnQ0FDN0MsQ0FBQyxDQUFDLDJCQUEyQjtnQ0FDN0IsQ0FBQyxDQUFDLDBCQUEwQjs0QkFDOUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDdEMsQ0FBQztvQkFDRCxFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUM7b0JBQ2hFLE9BQU8sRUFBRTt3QkFDUCxXQUFXLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTs0QkFDdkIsT0FBTyxPQUFPLENBQUMsY0FBYyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7d0JBQ2pHLENBQUM7d0JBQ0QsZUFBZSxFQUFFLElBQUksQ0FBQyx1QkFBdUI7cUJBQzlDO2lCQUNGO2FBQ0Y7U0FDRixDQUFDO1FBRUYsSUFBSSxtQkFBbUIsR0FBRztZQUN4QixHQUFHLEVBQUUsZUFBZTtZQUNwQixPQUFPLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDMUIsSUFBSSxFQUFFLFVBQVUsQ0FBQyxnQkFBZ0I7WUFDakMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLHFCQUFxQjtZQUM1QyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO1NBQzVCLENBQUM7UUFFRixJQUFJLGNBQWMsR0FBRyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUV0RSxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtZQUMxQixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1NBQzlDO2FBQU07WUFDTCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzdDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7U0FDOUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsZ0JBQWdCLENBQUMsT0FBdUI7UUFDdEMsMEJBQTBCLENBQUMsT0FBTyxDQUNoQyxJQUFJLENBQUMsbUJBQW1CLEVBQ3hCLEdBQUcsRUFBRTtZQUNILElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLENBQUMsRUFDRCxJQUFJLEVBQ0osSUFBSSxDQUFDLGlCQUFpQixDQUN2QixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILHdCQUF3QixDQUFDLGVBQXVCO1FBQzlDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO1FBRXBFLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNoRCxJQUFJLElBQUksQ0FBQyxlQUFlO1lBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUNqRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLFVBQTBCO1FBQ3ZDLElBQUksVUFBVSxDQUFDLGNBQWMsSUFBSSxjQUFjLENBQUMsSUFBSSxFQUFFO1lBQ3BELE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMzQyxPQUFPO1NBQ1I7UUFFRCxJQUFJLFVBQVUsQ0FBQyxjQUFjLElBQUksVUFBVSxDQUFDLGVBQWUsSUFBSSxVQUFVLENBQUMsUUFBUSxFQUFFO1lBQ2xGLElBQUksTUFBTSxHQUFHLFFBQVEsVUFBVSxDQUFDLGVBQWUsV0FBVyxVQUFVLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdEYsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN6QyxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQztZQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3pDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUNkO2FBQU07WUFDTCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQzFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxpQkFBaUIsQ0FBQyxVQUEwQjtRQUMxQyxJQUFJLFVBQVUsQ0FBQyxjQUFjLElBQUksY0FBYyxDQUFDLElBQUk7WUFBRSxPQUFPLGFBQWEsQ0FBQzs7WUFDdEUsT0FBTyx1QkFBdUIsQ0FBQyx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDMUYsQ0FBQztJQUVELFlBQVk7SUFFWjs7T0FFRztJQUNILE9BQU8sQ0FBQyxjQUE4QixFQUFFLFVBQVUsR0FBRyxJQUFJO1FBQ3ZELElBQUksY0FBYyxJQUFJLGNBQWMsQ0FBQyxJQUFJLEVBQUU7WUFDekMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7U0FDL0I7YUFBTSxJQUFJLGNBQWMsSUFBSSxjQUFjLENBQUMsSUFBSSxFQUFFO1lBQ2hELFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztTQUNwQjthQUFNO1lBQ0wsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7U0FDMUI7SUFDSCxDQUFDO0lBRUQsb0JBQW9CO1FBQ2xCLDJDQUEyQztRQUMzQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDOUMsSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQztZQUM5RCxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQztZQUNuQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQztZQUNuQyxZQUFZLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQ2pDLFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7U0FDaEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjLEdBQUcsSUFBSTtRQUN6QixJQUFJLENBQUMsYUFBYSxHQUFHLEVBQW9CLENBQUM7UUFDMUMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksS0FBSyxFQUFrQixDQUFDO1FBQzFELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNqQixJQUFJLElBQUksQ0FBQyxpQkFBaUI7WUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFM0QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBRWpDLElBQUksY0FBYyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsa0JBQWtCO1lBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3hGLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsV0FBVztRQUNULElBQUksSUFBSSxDQUFDLGlCQUFpQixJQUFJLElBQUksRUFBRTtZQUNsQyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxJQUFJLGNBQWMsQ0FBQyxJQUFJLEVBQUU7Z0JBQzVELE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQzthQUMzQztpQkFBTTtnQkFDTCxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7YUFDckM7U0FDRjthQUFNO1lBQ0wsT0FBTyxDQUNMLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQ2hDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FDSixDQUFDLENBQUMsQ0FBQyxjQUFjLElBQUksY0FBYyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUM7Z0JBQzlELENBQUMsQ0FBQyxDQUFDLGNBQWMsSUFBSSxjQUFjLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUMzRCxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQ2IsQ0FBQztTQUNIO0lBQ0gsQ0FBQztJQUVELG9CQUFvQjtRQUNsQixJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFO1lBQzlCLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUMxRjtRQUVELElBQUksSUFBSSxDQUFDLGlCQUFpQixJQUFJLElBQUksRUFBRTtZQUNsQyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsY0FBYyxJQUFJLGNBQWMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVE7Z0JBQzFGLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO1lBRTVELElBQUksSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJO2dCQUFFLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxLQUFLLEVBQWtCLENBQUM7WUFFckYsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQy9DO2FBQU07WUFDTCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sSUFBSSxDQUFDO2dCQUFFLE9BQU87WUFFM0YsSUFBSSxJQUFJLENBQUMsZUFBZSxJQUFJLElBQUk7Z0JBQUUsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLEtBQUssRUFBa0IsQ0FBQztZQUVyRixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1NBQ2pGO1FBRUQsSUFBSSxJQUFJLENBQUMsZUFBZTtZQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFakUsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFdkQsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRTtZQUM5QixJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7U0FDbEM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxHQUFtQjtRQUN6QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFMUQsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxJQUFJLGNBQWMsQ0FBQyxJQUFJLEVBQUU7WUFDakUsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDL0QsMEJBQTBCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO2dCQUNsRSxPQUFPO2FBQ1I7aUJBQU0sSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtnQkFDdEUsMEJBQTBCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO2dCQUNsRSxPQUFPO2FBQ1I7U0FDRjtRQUVELElBQUksSUFBSSxDQUFDLHFCQUFxQixJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxFQUFFO1lBQzVHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixFQUFFO2lCQUMzQixJQUFJLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDWixJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxHQUFHLEdBQUcsQ0FBQyxjQUFjLENBQUM7WUFDOUQsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNiLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN4QyxDQUFDLENBQUMsQ0FBQztTQUNOO1FBRUQsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxJQUFJLGNBQWMsQ0FBQyxJQUFJLEVBQUU7WUFDakUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLDhCQUE4QixDQUNoRixJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUNqQyxDQUFDO1NBQ0g7YUFBTSxJQUNMLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPO1lBQy9CLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGNBQWM7WUFDdkMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLEVBQzVDO1lBQ0EsMEJBQTBCLENBQUMsSUFBSSxDQUFDLDhEQUE4RCxDQUFDLENBQUM7WUFDaEcsT0FBTztTQUNSO2FBQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUU7WUFDM0MsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDOUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLDhCQUE4QixDQUNoRixvQ0FBb0M7b0JBQ2xDLElBQUksQ0FBQyxpQkFBaUI7b0JBQ3RCLEdBQUc7b0JBQ0gsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFFBQVE7b0JBQ2hDLGdCQUFnQixDQUNuQixDQUFDO2FBQ0g7aUJBQU07Z0JBQ0wsMEJBQTBCLENBQUMsSUFBSSxDQUFDLCtDQUErQyxDQUFDLENBQUM7Z0JBQ2pGLE9BQU87YUFDUjtTQUNGO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNuQyxZQUFZLEVBQUUsSUFBSTtZQUNsQixXQUFXLEVBQUUsSUFBSTtTQUNsQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLGlCQUFpQjtRQUNyQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFpQixJQUFJLENBQUMscUJBQXFCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDekcsQ0FBQztJQUVELG1DQUFtQztJQUVuQzs7Ozs7OztPQU9HO0lBQ0gsS0FBSyxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsZ0JBQXlCLEtBQUs7UUFDckQsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDM0IsSUFBSSxZQUFZLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1FBRTlELHFIQUFxSDtRQUNySCxvRUFBb0U7UUFDcEUsSUFBSSxDQUFDLEdBQUcsWUFBWSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSSxFQUFFO1lBQ25FLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BDLElBQUksQ0FBQyxhQUFhLEdBQUcsWUFBWSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWTtnQkFBRSxPQUFPO1lBRS9CLGlDQUFpQztZQUNqQyxJQUFJLENBQUMsYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdDQUFnQyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDM0YsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksS0FBSyxFQUFrQixDQUFDO1lBQzFELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRXJELHNIQUFzSDtZQUN0SCxJQUFJLGNBQWMsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3RFLElBQUksY0FBYyxJQUFJLEtBQUs7Z0JBQUUsT0FBTztZQUVwQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUU1Qiw2SEFBNkg7WUFDN0gsOENBQThDO1lBQzlDLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLElBQUksSUFBSSxFQUFFO2dCQUN0QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXpDLHFGQUFxRjtnQkFDckYsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNqQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN4RCxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN6RCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztnQkFDMUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7Z0JBRXZCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFO29CQUMvRCxZQUFZLEVBQUUsSUFBSTtvQkFDbEIsV0FBVyxFQUFFLElBQUk7b0JBQ2pCLEtBQUssRUFBRSxLQUFLO29CQUNaLFNBQVMsRUFBRSxLQUFLO29CQUNoQixRQUFRLEVBQUUsTUFBTTtpQkFDakIsQ0FBQyxDQUFDO2FBQ0o7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7Z0JBQzNCLElBQUksWUFBWSxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDbkUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEdBQUcsWUFBWSxDQUFDLFVBQVUsQ0FBQztnQkFDNUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxlQUFlLEdBQUcsWUFBWSxDQUFDLFdBQVcsQ0FBQztnQkFDOUQsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7YUFDN0I7U0FDRjthQUFNO1lBQ0wsSUFBSSxDQUFDLGFBQWEsR0FBRyxZQUFZLENBQUM7WUFDbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLElBQUksQ0FBQztnQkFBRSxPQUFPO1lBRWxFLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLEtBQUssRUFBa0IsQ0FBQztZQUMxRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2xELElBQUksYUFBYSxHQUFtQixNQUFNLElBQUksQ0FBQyxnQ0FBZ0MsQ0FDN0UsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFDckIsSUFBSSxFQUNKLElBQUksQ0FDTCxDQUFDO2dCQUNGLHNIQUFzSDtnQkFDdEgsSUFBSSxjQUFjLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUNqRSxJQUFJLGNBQWMsSUFBSSxLQUFLO29CQUFFLE9BQU87Z0JBRXBDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7YUFDakQ7WUFDRCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztTQUM3QjtRQUVELDZHQUE2RztRQUM3RyxJQUFJLENBQUMsYUFBYTtZQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNLLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FDNUMsV0FBaUIsRUFDakIsWUFBcUIsSUFBSSxFQUN6QixXQUFvQixLQUFLO1FBRXpCLElBQUksYUFBYSxHQUFtQixFQUFvQixDQUFDO1FBQ3pELGlDQUFpQztRQUNqQyxhQUFhLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUM7UUFDbkQsYUFBYSxDQUFDLGVBQWUsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDO1FBQ2pELGFBQWEsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQztRQUMxQyxhQUFhLENBQUMsYUFBYSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzdGLGFBQWEsQ0FBQyxPQUFPLEdBQUcsdUJBQXVCLENBQUMsc0JBQXNCLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXpGLElBQUksU0FBUyxJQUFJLElBQUksRUFBRTtZQUNyQixJQUFJLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM3RCxhQUFhLENBQUMsY0FBYyxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUM7WUFDdkQsYUFBYSxDQUFDLGVBQWUsR0FBRyxZQUFZLENBQUMsV0FBVyxDQUFDO1lBRXpELElBQUksYUFBYSxDQUFDLE9BQU8sSUFBSSxhQUFhLENBQUMsY0FBYyxJQUFJLFFBQVEsRUFBRTtnQkFDckUsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsWUFBWSxDQUFDLFdBQVcsV0FBVyxZQUFZLENBQUMsVUFBVSxFQUFFLEVBQUUsYUFBYSxDQUFDLENBQUM7YUFDL0c7U0FDRjtRQUVELE9BQU8sYUFBYSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxXQUFpQjtRQUMvQyxJQUFJLFVBQVUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM3QyxJQUFJLFdBQVcsR0FBVyxJQUFJLENBQUM7UUFDL0IsSUFBSSxVQUFVLEVBQUU7WUFDZCxpSEFBaUg7WUFDakgsMkdBQTJHO1lBQzNHLG1IQUFtSDtZQUNuSCxXQUFXLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25FLDBGQUEwRjtZQUMxRixVQUFVLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN2QztRQUVELElBQUksTUFBTSxHQUFHO1lBQ1gsVUFBVSxFQUFFLFVBQVU7WUFDdEIsV0FBVyxFQUFFLFdBQVc7U0FDekIsQ0FBQztRQUVGLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRDs7O09BR0c7SUFDSyxrQkFBa0I7UUFDeEIsSUFDRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzlFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixJQUFJLElBQUksSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBRWhILE9BQU8sS0FBSyxDQUFDO1FBRWYsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksR0FBRztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBRS9DLHdHQUF3RztRQUN4RyxJQUFJLFFBQVEsR0FBWSxJQUFJLENBQUM7UUFDN0IsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSTtZQUFFLFFBQVEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDbEc7WUFDSCxJQUFJLGlCQUFpQixHQUFhLENBQUMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDN0UsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7Z0JBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztvQkFBRSxRQUFRLEdBQUcsS0FBSyxDQUFDO1lBQy9ELENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFFRCxxSEFBcUg7UUFDckgsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSSxFQUFFO1lBQy9DLEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRTtnQkFDOUUsUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzlELElBQUksUUFBUTtvQkFBRSxNQUFNO2FBQ3JCO1NBQ0Y7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLHVCQUF1QixDQUFDLGFBQWE7UUFDM0MsSUFBSSxJQUFJLENBQUMsZUFBZSxJQUFJLElBQUksSUFBSSxhQUFhLENBQUMsT0FBTyxJQUFJLElBQUksRUFBRTtZQUNqRSwwQkFBMEIsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFDbkUsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pCLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7YUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUU7WUFDckMsMEJBQTBCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQ3JFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNqQixPQUFPLEtBQUssQ0FBQztTQUNkO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsNEJBQTRCO0lBRTVCLGtCQUFrQixDQUFDLEdBQVE7UUFDekIsTUFBTSxNQUFNLEdBQUcsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNoQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBTSxFQUFFLEVBQUU7WUFDekIsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUMxQixLQUFLLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQzVCLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRTtnQkFDcEIsSUFBSSxDQUFDLGNBQWMsR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUNqRCxJQUFJLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRS9DLElBQUksSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLEVBQUU7b0JBQzdCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO29CQUN4QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztpQkFDbkY7cUJBQU07b0JBQ0wsSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUMvQyxJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQzlDO1lBQ0gsQ0FBQyxDQUFDO1FBQ0osQ0FBQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQseUJBQXlCO1FBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUN0QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUM7UUFDeEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVELGtCQUFrQixDQUFDLFNBQWlCO1FBQ2xDLElBQUksU0FBUyxJQUFJLEdBQUcsRUFBRTtZQUNwQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7U0FDL0Y7YUFBTSxJQUFJLFNBQVMsSUFBSSxHQUFHLEVBQUU7WUFDM0IsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQy9GO0lBQ0gsQ0FBQztJQUVELFlBQVksQ0FBQyxLQUF3QjtRQUNuQyxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDakMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFRCxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsYUFBNkI7UUFDckQsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWhCLElBQUksSUFBSSxHQUFRLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVuQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUM7UUFFeEM7O1dBRUc7UUFDSCxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsY0FBYyxFQUFFLEVBQUU7WUFDdEQsSUFBSSxVQUFVLEdBQUcsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUVsQywyRkFBMkY7WUFDM0YsVUFBVSxDQUFDLE1BQU0sR0FBRztnQkFDbEIsSUFBSSxZQUFZLEdBQVcsVUFBVSxDQUFDLE1BQU0sQ0FBQztnQkFDN0MsSUFBSSxNQUFNLEdBQUcsVUFBVSxDQUFDO2dCQUN4QixhQUFhLENBQUMsY0FBYyxHQUFHLFlBQVksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3BHLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO2dCQUMzQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtvQkFDMUIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDO2lCQUNqQztZQUNILENBQUMsQ0FBQztZQUVGLFVBQVUsQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDM0MsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLDhCQUE4QjtJQUM5QixxQ0FBcUM7SUFDckMsc0NBQXNDO0lBQ3RDLElBQUk7SUFFSixVQUFVO1FBQ1IsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVPLGVBQWU7UUFDckIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFDdEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFDdEMsSUFBSSxDQUFDLFNBQVMsR0FBRztZQUNmLEdBQUcsSUFBSSxDQUFDLFNBQVM7WUFDakIsS0FBSyxFQUFFLFFBQVE7WUFDZixLQUFLLEVBQUUsUUFBUTtTQUNoQixDQUFDO0lBQ0osQ0FBQztJQUVELGNBQWM7UUFDWixJQUFJLENBQUMsU0FBUyxHQUFHO1lBQ2YsR0FBRyxJQUFJLENBQUMsU0FBUztZQUNqQixLQUFLLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUs7U0FDN0IsQ0FBQztJQUNKLENBQUM7SUFFRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLFNBQVMsR0FBRztZQUNmLEdBQUcsSUFBSSxDQUFDLFNBQVM7WUFDakIsS0FBSyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLO1NBQzdCLENBQUM7SUFDSixDQUFDO0lBRUQsWUFBWTtJQUVaOztPQUVHO0lBQ0gsU0FBUztRQUNQLElBQUksSUFBSSxDQUFDLFVBQVU7WUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBRTlELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBQzFCLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBRTNCLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNuQyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFDekMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ25DLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUN4QyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUM7UUFFMUMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksS0FBSyxFQUFrQixDQUFDO1FBRTFELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO1FBQzNCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBRTFCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsWUFBWTtJQUVaLG1IQUFtSDtJQUNuSCx1SUFBdUk7SUFDdkksV0FBVyxDQUFDLEtBQUs7UUFDZixJQUFJLFlBQVksR0FBRyxFQUFFLENBQUM7UUFFdEIsTUFBTSxXQUFXLEdBQXNCLEVBQUUsQ0FBQztRQUMxQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNyQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFO2dCQUM3QixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBZ0MsQ0FBQztnQkFDNUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtvQkFDN0MsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQVUsRUFBRSxFQUFFO3dCQUM1QixZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO3dCQUV4QixRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7d0JBQ2hCLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDdEIsQ0FBQyxDQUFDLENBQUM7Z0JBQ0wsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUM5QjtpQkFBTTtnQkFDTCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBcUMsQ0FBQztnQkFDakUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDO2FBQy9DO1NBQ0Y7UUFFRCxJQUFJLENBQUMsV0FBVyxDQUFDO2FBQ2QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDM0MsU0FBUyxDQUFDO1lBQ1QsUUFBUSxFQUFFLEdBQUcsRUFBRTtnQkFDYixJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FBQztZQUN2QyxDQUFDO1NBQ0YsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELDhHQUE4RztJQUM5Ryx5SEFBeUg7SUFDekgsaUJBQWlCO1FBQ2YsSUFBSSxPQUFPLEdBQUc7WUFDWixPQUFPLEVBQUUsQ0FBQyxLQUFZLEVBQUUsRUFBRTtnQkFDeEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDakMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUMvQixHQUFHLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxFQUFFLFVBQVUsdUJBQXVCLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDMUcsR0FBRyxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUM7Z0JBRTFCLEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxFQUFFO29CQUNoQixNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDO29CQUMxQixNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQ2xFLElBQUksVUFBVSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNyQyxDQUFDLENBQUM7Z0JBRUYsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2IsQ0FBQztZQUNELFFBQVEsRUFBRSxRQUFRO1lBQ2xCLFdBQVcsRUFBRSxLQUFLO1lBQ2xCLFVBQVUsRUFBRSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDO1NBQzlELENBQUM7UUFDRixPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFFRCxtSEFBbUg7SUFDbkgsWUFBWSxDQUFDLEtBQUssRUFBRSxTQUFTO1FBQzNCLElBQ0csS0FBSyxDQUFDLE1BQTRCLENBQUMsT0FBTyxLQUFLLFFBQVE7WUFDdkQsS0FBSyxDQUFDLE1BQTRCLENBQUMsT0FBTyxLQUFLLE9BQU87WUFDdkQsSUFBSSxDQUFDLGNBQWMsSUFBSSxJQUFJLEVBQzNCO1lBQ0EsT0FBTztTQUNSO1FBQ0QsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCx5REFBeUQ7SUFDekQsc0JBQXNCO1FBQ3BCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO1FBQzNCLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBb0IsQ0FBQztRQUMxQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDbkMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7UUFDN0QsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksS0FBSyxFQUFrQixDQUFDO1FBQzFELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXJELElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQzlCLENBQUM7d0dBMytCVSx1QkFBdUI7NEZBQXZCLHVCQUF1QiwybkZBMk92QixxQkFBcUIsOGRDcFJsQywrbndCQW9tQkE7OzRGRDNqQmEsdUJBQXVCO2tCQUxuQyxTQUFTOytCQUNFLGlCQUFpQjsrTkFVSCxhQUFhO3NCQUFwQyxLQUFLO3VCQUFDLGVBQWU7Z0JBS0QsVUFBVTtzQkFBOUIsS0FBSzt1QkFBQyxZQUFZO2dCQUtHLFdBQVc7c0JBQWhDLEtBQUs7dUJBQUMsYUFBYTtnQkFLTSxlQUFlO3NCQUF4QyxLQUFLO3VCQUFDLGlCQUFpQjtnQkFLRixXQUFXO3NCQUFoQyxLQUFLO3VCQUFDLGFBQWE7Z0JBTVMsa0JBQWtCO3NCQUE5QyxLQUFLO3VCQUFDLG9CQUFvQjtnQkFNQyxpQkFBaUI7c0JBQTVDLEtBQUs7dUJBQUMsbUJBQW1CO2dCQUtHLGtCQUFrQjtzQkFBOUMsS0FBSzt1QkFBQyxvQkFBb0I7Z0JBS0MsaUJBQWlCO3NCQUE1QyxLQUFLO3VCQUFDLG1CQUFtQjtnQkFPQSxlQUFlO3NCQUF4QyxLQUFLO3VCQUFDLGlCQUFpQjtnQkFLSSxpQkFBaUI7c0JBQTVDLEtBQUs7dUJBQUMsbUJBQW1CO2dCQUtMLFVBQVU7c0JBQTlCLEtBQUs7dUJBQUMsWUFBWTtnQkFLUyxpQkFBaUI7c0JBQTVDLEtBQUs7dUJBQUMsbUJBQW1CO2dCQVFNLHFCQUFxQjtzQkFBcEQsS0FBSzt1QkFBQyx1QkFBdUI7Z0JBUUYsaUJBQWlCO3NCQUE1QyxLQUFLO3VCQUFDLG1CQUFtQjtnQkFLRyxrQkFBa0I7c0JBQTlDLEtBQUs7dUJBQUMsb0JBQW9CO2dCQVNKLFlBQVk7c0JBQWxDLEtBQUs7dUJBQUMsY0FBYztnQkFNYSx1QkFBdUI7c0JBQXhELEtBQUs7dUJBQUMseUJBQXlCO2dCQU1BLHFCQUFxQjtzQkFBcEQsS0FBSzt1QkFBQyx1QkFBdUI7Z0JBTUQsa0JBQWtCO3NCQUE5QyxLQUFLO3VCQUFDLG9CQUFvQjtnQkFNRSxrQkFBa0I7c0JBQTlDLEtBQUs7dUJBQUMsb0JBQW9CO2dCQVVNLHNCQUFzQjtzQkFBdEQsS0FBSzt1QkFBQyx3QkFBd0I7Z0JBS1QsV0FBVztzQkFBaEMsS0FBSzt1QkFBQyxhQUFhO2dCQUtrQiwyQkFBMkI7c0JBQWhFLEtBQUs7dUJBQUMsNkJBQTZCO2dCQUtkLFdBQVc7c0JBQWhDLEtBQUs7dUJBQUMsYUFBYTtnQkFLTSxlQUFlO3NCQUF4QyxLQUFLO3VCQUFDLGlCQUFpQjtnQkFLVSx1QkFBdUI7c0JBQXhELEtBQUs7dUJBQUMseUJBQXlCO2dCQUNSLGFBQWE7c0JBQXBDLEtBQUs7dUJBQUMsZUFBZTtnQkFDRyxjQUFjO3NCQUF0QyxLQUFLO3VCQUFDLGdCQUFnQjtnQkFDQyxhQUFhO3NCQUFwQyxLQUFLO3VCQUFDLGVBQWU7Z0JBQ0EsV0FBVztzQkFBaEMsS0FBSzt1QkFBQyxhQUFhO2dCQUNJLGFBQWE7c0JBQXBDLEtBQUs7dUJBQUMsZUFBZTtnQkFDQyxZQUFZO3NCQUFsQyxLQUFLO3VCQUFDLGNBQWM7Z0JBQ0ssZUFBZTtzQkFBeEMsS0FBSzt1QkFBQyxpQkFBaUI7Z0JBQ0QsWUFBWTtzQkFBbEMsS0FBSzt1QkFBQyxjQUFjO2dCQUNBLFVBQVU7c0JBQTlCLEtBQUs7dUJBQUMsWUFBWTtnQkFDQyxTQUFTO3NCQUE1QixLQUFLO3VCQUFDLFdBQVc7Z0JBQ0UsU0FBUztzQkFBNUIsS0FBSzt1QkFBQyxXQUFXO2dCQUNlLHNCQUFzQjtzQkFBdEQsS0FBSzt1QkFBQyx3QkFBd0I7Z0JBQ1gsU0FBUztzQkFBNUIsS0FBSzt1QkFBQyxXQUFXO2dCQUNXLGtCQUFrQjtzQkFBOUMsS0FBSzt1QkFBQyxvQkFBb0I7Z0JBQ0MsaUJBQWlCO3NCQUE1QyxLQUFLO3VCQUFDLG1CQUFtQjtnQkFDSSxtQkFBbUI7c0JBQWhELEtBQUs7dUJBQUMscUJBQXFCO2dCQUNVLDJCQUEyQjtzQkFBaEUsS0FBSzt1QkFBQyw2QkFBNkI7Z0JBRUksNkJBQTZCO3NCQUFwRSxLQUFLO3VCQUFDLCtCQUErQjtnQkFFSCx3QkFBd0I7c0JBQTFELEtBQUs7dUJBQUMsMEJBQTBCO2dCQUVFLHdCQUF3QjtzQkFBMUQsS0FBSzt1QkFBQywwQkFBMEI7Z0JBRUYsb0JBQW9CO3NCQUFsRCxLQUFLO3VCQUFDLHNCQUFzQjtnQkFDRCxpQkFBaUI7c0JBQTVDLEtBQUs7dUJBQUMsbUJBQW1CO2dCQUNDLGdCQUFnQjtzQkFBMUMsS0FBSzt1QkFBQyxrQkFBa0I7Z0JBQ0MsZUFBZTtzQkFBeEMsS0FBSzt1QkFBQyxpQkFBaUI7Z0JBUWQsc0JBQXNCO3NCQUEvQixNQUFNO2dCQUtHLGtCQUFrQjtzQkFBM0IsTUFBTTtnQkFLdUIsa0JBQWtCO3NCQUEvQyxNQUFNO3VCQUFDLG9CQUFvQjtnQkFLRSxrQkFBa0I7c0JBQS9DLE1BQU07dUJBQUMsb0JBQW9CO2dCQWF3QixtQkFBbUI7c0JBQXRFLFNBQVM7dUJBQUMscUJBQXFCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUVVLDJCQUEyQjtzQkFBdEYsU0FBUzt1QkFBQyw2QkFBNkIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRVYsZUFBZTtzQkFBOUQsU0FBUzt1QkFBQyxpQkFBaUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBUVosWUFBWTtzQkFBN0MsU0FBUzt1QkFBQyxxQkFBcUI7Z0JBQ1AsVUFBVTtzQkFBbEMsU0FBUzt1QkFBQyxZQUFZO2dCQVcwQixlQUFlO3NCQUEvRCxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFDTyxxQkFBcUI7c0JBQTFFLFNBQVM7dUJBQUMsdUJBQXVCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNOLGFBQWE7c0JBQTFELFNBQVM7dUJBQUMsZUFBZSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHtcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIElucHV0LFxyXG4gIE9uSW5pdCxcclxuICBPdXRwdXQsXHJcbiAgVGVtcGxhdGVSZWYsXHJcbiAgVmlld0NoaWxkXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xyXG5pbXBvcnQgeyBNYXREaWFsb2csIE1hdERpYWxvZ1JlZiB9IGZyb20gXCJAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2dcIjtcclxuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSBcIkBhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXJcIjtcclxuaW1wb3J0IHsgRXFwVGFibGVDb21wb25lbnQgfSBmcm9tIFwiQGVxcHJvamVjdC9lcXAtdGFibGVcIjtcclxuaW1wb3J0IHsgVGFibGVDb2x1bW5GaWVsZCwgVG9vbHRpcFBvc2l0aW9uVHlwZSwgVHlwZUNvbHVtbiB9IGZyb20gXCJAZXFwcm9qZWN0L2VxcC1jb21tb25cIjtcclxuaW1wb3J0IGltYWdlQ29tcHJlc3Npb24gZnJvbSBcImJyb3dzZXItaW1hZ2UtY29tcHJlc3Npb25cIjtcclxuaW1wb3J0IHsgYmFzZTY0VG9GaWxlLCBJbWFnZUNyb3BwZWRFdmVudCwgSW1hZ2VDcm9wcGVyQ29tcG9uZW50LCBJbWFnZVRyYW5zZm9ybSB9IGZyb20gXCJuZ3gtaW1hZ2UtY3JvcHBlclwiO1xyXG5pbXBvcnQgeyBBdHRhY2htZW50SGVscGVyU2VydmljZSB9IGZyb20gXCIuL2hlbHBlcnMvYXR0YWNobWVudC5oZWxwZXJcIjtcclxuaW1wb3J0IHsgQXR0YWNobWVudFR5cGUsIENyb3BPcHRpb25FbnVtLCBJQXR0YWNobWVudERUTyB9IGZyb20gXCIuL2ludGVyZmFjZXMvSUF0dGFjaG1lbnRcIjtcclxuaW1wb3J0IHsgSU9wdGlvbnMgfSBmcm9tIFwiLi9pbnRlcmZhY2VzL0lPcHRpb25zXCI7XHJcbmltcG9ydCB7IEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvZXFwLWF0dGFjaG1lbnQtZGlhbG9nLnNlcnZpY2VcIjtcclxuXHJcbmRlY2xhcmUgdmFyIERyb3Bib3g6IGFueTtcclxuXHJcbmltcG9ydCB7IGNvbmNhdE1hcCwgZnJvbSwgT2JzZXJ2YWJsZSB9IGZyb20gXCJyeGpzXCI7XHJcbmltcG9ydCB7IEVxcEF0dGFjaG1lbnRTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvZXFwLWF0dGFjaG1lbnQuc2VydmljZVwiO1xyXG5cclxuY29uc3QgdG9CYXNlNjQgPSAoZmlsZSkgPT5cclxuICBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcclxuICAgIHJlYWRlci5vbmxvYWQgPSAoKSA9PiByZXNvbHZlKHJlYWRlci5yZXN1bHQudG9TdHJpbmcoKSk7XHJcbiAgICByZWFkZXIub25lcnJvciA9IChlcnJvcikgPT4gcmVqZWN0KGVycm9yKTtcclxuICB9KTtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiBcImVxcC1hdHRhY2htZW50c1wiLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmxzOiBbXCIuL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQuc2Nzc1wiXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRXFwQXR0YWNobWVudHNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gIC8vI3JlZ2lvbiBASW5wdXQgZGVsIGNvbXBvbmVudGVcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgbmFzY29uZGUgbGEgY29sb25uYSBwZXIgbGUgYXppb25pIHN1bGwnYWxsZWdhdG8gKG5lbCBjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZGlzYWJsZUFjdGlvblwiKSBkaXNhYmxlQWN0aW9uOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgbW9zdHJhIGlsIHRpdG9sbyBuZWxsJ2hlYWRlciBuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFIChcIkVsZW5jbyBhbGxlZ2F0aVwiIGRpIGRlZmF1bHQpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dIZWFkZXJcIikgc2hvd0hlYWRlcjogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRpdG9sbyBkYSB2aXN1YWxpenphcmUgc2UgaWwgcGFyYW1ldHJvIFwic2hvd0hlYWRlclwiIMOoIFRSVUUuIERpIGRldmF1bHQgdmllbmUgdmlzdWFsaXp6YXRvIFwiRWxlbmNvIGFsbGVnYXRpXCIuXHJcbiAgICovXHJcbiAgQElucHV0KFwiaGVhZGVyVGl0bGVcIikgaGVhZGVyVGl0bGU6IHN0cmluZyA9IFwiRWxlbmNvIGFsbGVnYXRpXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNvcmdlbnRlIGRhdGkgZGEgdmlzdWFsaXp6YXJlLiBOZWwgY2FzbyBzaSB2dW9sZSBnZXN0aXJlIHVuIHNpbmdvbG8gYWxsZWdhdG8gdmEgcGFzc2F0byBpbiBvZ25pIGNhc28gY29tZSBBcnJheS5cclxuICAgKi9cclxuICBASW5wdXQoXCJhdHRhY2htZW50c0xpc3RcIikgYXR0YWNobWVudHNMaXN0OiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIG5vbiBtb3N0cmEgbGEgTWF0Q2FyZCAobmVsIGNhc28gaW4gY3VpIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwic2hvd01hdENhcmRcIikgc2hvd01hdENhcmQ6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBGQUxTRSBhbGxvcmEgaWwgY29tcG9uZW50ZSBtb3N0cmEgc29sbyBpbCBwdWxzYW50ZSBkaSBjYXJpY2FtZW50byBkaSB1biBzaW5nb2xvIGZpbGUsIHVuYSB2b2x0YSBjYXJpY2F0byBpbCBmaWxlIGludm9jYSBsJ2V2ZW50byBkaSBvdXRwdXQgXCJsb2NhbEVkaXRlZEF0dGFjaG1lbnRzXCIuXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgaWwgY29tcG9uZW50ZSBtb3N0cmEgbCdlbGVuY28gZGkgdHV0dGkgZ2xpIGFsbGVnYXRpIHJpY2V2dXRvIG5lbCBwYXJhbWV0cm8gXCJhdHRhY2htZW50c0xpc3RcIi5cclxuICAgKi9cclxuICBASW5wdXQoXCJtdWx0aXBsZUF0dGFjaG1lbnRcIikgbXVsdGlwbGVBdHRhY2htZW50OiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgYXNzdW1lIGlsIHZhbG9yZSBUUlVFIGFsbG9yYSBzYXLDoCBwb3NzaWJpbGUgY2FyaWNhcmUgcGnDuSBmaWxlIHBlciB2b2x0YS4gUXVlc3RhIGZ1bnppb25hbGl0w6Agw6ggYXR0aXZhXHJcbiAgICogU09MTyBzZSBzaSBnZXN0aXNjb25vIGFsbGVnYXRpIG11bHRpcGxpLCBxdWluZGkgc2UgbCdpbnB1dCAnbXVsdGlwbGVBdHRhY2htZW50JyBhc3N1bWUgaWwgdmFsb3JlIFRSVUUsIGFsdHJpbWVudGkgw6ggc2VtcHJlIGRpc2FiaWxpdGF0YS5cclxuICAgKi9cclxuICBASW5wdXQoXCJsb2FkTXVsdGlwbGVGaWxlc1wiKSBsb2FkTXVsdGlwbGVGaWxlczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBDb25maWd1cmF6aW9uZSBkZWxsZSBjb2xvbm5lIGRlbGxhIGVxcC10YWJsZSBwZXIgbGEgdmlzdWFsaXp6YXppb25lIGRlZ2xpIGFsbGVnYXRpIChjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiYXR0YWNobWVudHNDb2x1bW5zXCIpIGF0dGFjaG1lbnRzQ29sdW1uczogQXJyYXk8VGFibGVDb2x1bW5GaWVsZD4gPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBJbXBvc3RhIGlsIG1lc3NhZ2dpbyBkYSB2aXN1YWxpenphcmUgbmVsIGNhc28gaW4gY3VpIGxhIHRhYmVsbGEgZGVnbGkgYWxsZWdhdGkgKG5lbCBjYXNvIGluIGN1aSBcIm11bHRpcGxlQXR0YWNobWVudFwiIMOoIFRSVUUpIMOoIHZ1b3RhLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImVtcHR5VGFibGVNZXNzYWdlXCIpIGVtcHR5VGFibGVNZXNzYWdlOiBzdHJpbmcgPSBcIk5lc3N1biBkYXRvIHRyb3ZhdG9cIjtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgcGVybWV0dGUgZGkgc2VsZXppb25hcmUgc29sdGFudG8gZmlsZSBkaSB0aXBvIGltbWFnaW5lLCBhdmVudGUgdW5vIGRlaSBtaW1ldHlwZVxyXG4gICAqIHNwZWNpZmljYXRpIGRlbnRybyBBdHRhY2htZW50SGVscGVyU2VydmljZS5cclxuICAgKiBTZSBGQUxTRSBwZXJtZXR0ZSBkaSBzZWxlemlvbmFyZSBxdWFsc2lhc2kgdGlwbyBkaSBmaWxlXHJcbiAgICovXHJcbiAgQElucHV0KFwiYWxsb3dPbmx5SW1hZ2VzXCIpIGFsbG93T25seUltYWdlczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBTcGVjaWZpY2EgaSB0aXBpIGRpIGZpbGUgY2hlIMOoIHBvc3NpYmlsZSBjYXJpY2FyZVxyXG4gICAqL1xyXG4gIEBJbnB1dChcImFjY2VwdGVkRmlsZVR5cGVzXCIpIGFjY2VwdGVkRmlsZVR5cGVzOiBzdHJpbmc7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgZGlzYWJpbGl0YSBpbCBwdWxzYW50ZSBkaSBBZ2dpdW50YSBhbGxlZ2F0byAoYSBwcmVzY2luZGVyZSBkYWwgdmFsb3JlIGRlbCBwYXJhbWV0cm8gXCJtdWx0aXBsZUF0dGFjaG1lbnRcIikuXHJcbiAgICovXHJcbiAgQElucHV0KFwiaXNEaXNhYmxlZFwiKSBpc0Rpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIE1vc3RyYS9uYXNjb25kZSBsYSBjb2xvbm5hIHBlciB2aXN1YWxpenphcmUgbCdhbnRlcHJpbWEgZGVpIGZpbGUgbmVsbGEgdGFiZWxsYSAoY2FzbyBtdWx0aXBsZUF0YXRjaG1lbnRzID0gdHJ1ZSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwic2hvd0lubGluZVByZXZpZXdcIikgc2hvd0lubGluZVByZXZpZXc6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogRW5kcG9pbnQgZGEgY2hpYW1hcmUgcGVyIHJlY3VlcHJhcmUgbCdJQXR0YWNobWVudERUTyBjb21wbGV0byBkYSB2ZWRlcmUgbmVsbCdhbnRlcHJpbWEuIExhIGNoaWFtYXRhIHNhcsOgIGluIFBPU1QgZSBuZWwgYm9keVxyXG4gICAqIGNvbnRlcnLDoCBsJ0lBdHRhY2htZW50RFRPIHNlbGV6aW9uYXRvIGRhbGwndXRlbnRlLlxyXG4gICAqIExhIGNoaWFtYXRhIHZpZW5lIGVzZWd1aXRhIHNvbG8gcGVyIGwnYW50ZXByaW1hIGRlbGxlIGltbWFnaW5pIGVzc2VuZG8gbmVjZXNzYXJpbyBpbCBiYXNlNjQgY29tcGxldG8gZGVsbCdpbW1hZ2luZSBhIGRpbWVuc2lvbmUgcmVhbGUuXHJcbiAgICogUGVyIGRvY3VtZW50aS9saW5rIGJhc3RhIGNoZSBzaWEgcG9wb2xhdGEgbGEgcHJvcHJpZXTDoCBGaWxlUGF0aCBkaSBJQXR0YWNobWVudERUTy5cclxuICAgKi9cclxuICBASW5wdXQoXCJnZXRBdHRhY2htZW50RW5kcG9pbnRcIikgZ2V0QXR0YWNobWVudEVuZHBvaW50OiBzdHJpbmcgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBIb3N0bmFtZSBkZWxsJ2FtYmllbnRlIGRpIHByb2R1emlvbmUgZGVsbCdhcHBsaWNhdGl2by4gTmVjZXNzYXJpbyBwZXIgdmlzdWFsaXp6YXJlIGwnYW50ZXByaW1hIGRlaSBkb2N1bWVudGlcclxuICAgKiB0cmFtaXRlIGlsIHZpZXdlciBkaSBnb29nbGUuXHJcbiAgICogTk9UQTogUGVyIHZpc3VhbGl6emFyZSBsJ2FudGVwcmltYSDDqCBuZWNlc3NhcmlvIGNoZSBsYSBwcm9yaWV0w6AgRmlsZVBhdGggZGVsbCdJQXR0YWNobWVudERUTyBzaWEgcG9wb2xhdGEgZSBjaGVcclxuICAgKiBzaWEgYWJpbGl0YXRvIGwnYWNjZXNzbyBhbGxhIGNhcnRlbGxhIHN1bCBzZXJ2ZXIgdHJhbWl0ZSBob3N0bmFtZS5cclxuICAgKi9cclxuICBASW5wdXQoXCJwcm9kdWN0aW9uQmFzZVVybFwiKSBwcm9kdWN0aW9uQmFzZVVybDogc3RyaW5nID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogT3B6aW9uaSBwZXIgbGEgY29tcHJlc3Npb25lIGRlbGxlIGltbWFnaW5pIGNhcmljYXRlLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImNvbXByZXNzaW9uT3B0aW9uc1wiKSBjb21wcmVzc2lvbk9wdGlvbnM6IElPcHRpb25zID0ge1xyXG4gICAgbWF4U2l6ZU1COiAwLjUsXHJcbiAgICBtYXhXaWR0aE9ySGVpZ2h0OiAxOTIwLFxyXG4gICAgdXNlV2ViV29ya2VyOiB0cnVlXHJcbiAgfTtcclxuXHJcbiAgLyoqXHJcbiAgICogQXJyYXkgZGkgQXR0YWNobWVudFR5cGUgY2hlIHNpIHBvc3Nvbm8gYWdnaXVuZ2VyZVxyXG4gICAqL1xyXG4gIEBJbnB1dChcImFsbG93ZWRUeXBlc1wiKSBhbGxvd2VkVHlwZXM6IEFycmF5PEF0dGFjaG1lbnRUeXBlPiA9IFtBdHRhY2htZW50VHlwZS5GSUxFLCBBdHRhY2htZW50VHlwZS5MSU5LXTtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc3RhYmlsaXJlIHNlIGxhIGVxcC10YWJsZSBjb250ZW5lbnRlIGwnZWxlbmNvIGRlZ2xpIGFsbGVnYXRpIHV0aWxpenphXHJcbiAgICogaWwgbXVsdGlsaW5ndWEgb3BwdXJlIG5vXHJcbiAgICovXHJcbiAgQElucHV0KFwiaXNFcXBUYWJsZU11bHRpTGFuZ3VhZ2VcIikgaXNFcXBUYWJsZU11bHRpTGFuZ3VhZ2U6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc3RhYmlsaXJlLCBpbiBjYXNvIGRpIGdlc3Rpb25lIGFsbGVnYXRpIG11bHRpcGxpLCBzZSBsYSB0YWJlbGxhIGNvbnRlbmVudGUgbCdlbGVuY29cclxuICAgKiBkZWdsaSBhbGxlZ2F0aSBkZXZlIGVzc2VyZSBwYWdpbmF0YSBvcHB1cmUgbm9cclxuICAgKi9cclxuICBASW5wdXQoXCJ0YWJsZVBhZ2luYXRvclZpc2libGVcIikgdGFibGVQYWdpbmF0b3JWaXNpYmxlOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc3RhYmlsaXJlLCBpbiBjYXNvIGRpIGdlc3Rpb25lIGFsbGVnYXRpIG11bHRpcGxpLCBzZSBsYSB0YWJlbGxhIGNvbnRlbmVudGUgbCdlbGVuY29cclxuICAgKiBkZWdsaSBhbGxlZ2F0aSBkZXZlIGNvbnRlbmVyZSBpbCBjYW1wbyBkaSByaWNlcmNhIG9wcHVyZSBub1xyXG4gICAqL1xyXG4gIEBJbnB1dChcImlzVGFibGVTZWFyY2hlYWJsZVwiKSBpc1RhYmxlU2VhcmNoZWFibGU6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBJbiBjYXNvIGRpIGdlc3Rpb25lIGFsbGVnYXRpIG11bHRpcGxpLCBwZXJtZXR0ZSBkaSBzdGFiaWxpcmUgbGEgZGltZW5zaW9uZSBwYWdpbmEgZGkgZGVmYXVsdFxyXG4gICAqIHBlciBsYSB0YWJlbGxhIGNvbnRlbmVudGUgbCdlbGVuY28gZGVnbGkgYWxsZWdhdGlcclxuICAgKi9cclxuICBASW5wdXQoXCJ0YWJsZVBhZ2luYXRvclNpemVcIikgdGFibGVQYWdpbmF0b3JTaXplOiBudW1iZXIgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBQZXJtZXR0ZSBkaSBzY2VnbGllcmUgaWwgbW9kbyBpbiBjdWkgaSBmaWxlIGRldm9ubyBlc3NlcmUgY2FyaWNhdGlcclxuICAgKi9cclxuICAvLyBASW5wdXQoXCJ1cGxvYWRUeXBlXCIpIHVwbG9hZFR5cGU6IFVwbG9hZFR5cGVFbnVtID0gVXBsb2FkVHlwZUVudW0uRklMRV9BTkRfTElOSztcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc3RhYmlsaXJlIHNlIGkgcHVsc2FudGkgcGVyIGlsIGNhcmljYW1lbnRvIGRlaSBmaWxlIHNvbm8gc2VwYXJhdGkgbyBpbiB1biBtZW7DuSBhIHRlbmRpbmFcclxuICAgKi9cclxuICBASW5wdXQoXCJzZXBhcmF0ZWRVcGxvYWRCdXR0b25zXCIpIHNlcGFyYXRlZFVwbG9hZEJ1dHRvbnM6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc2NlZ2xpZXJlIHNlIGRhcmUgbGEgcG9zc2liaWxpdMOgIGRpIHZlZGVyZSBvIG5vIGwnYW50ZXByaW1hXHJcbiAgICovXHJcbiAgQElucHV0KFwic2hvd1ByZXZpZXdcIikgc2hvd1ByZXZpZXc6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBJbiBjYXNvIGRpIGFsbGVnYXRvIHNpbmdvbG8sIHBlcm1ldHRlIGRpIHNjZWdsaWVyZSBzZSBhZ2dpdW5nZXJlIGZpbGUgdHJhbWl0ZSBkcmFnIGFuZCBkcm9wXHJcbiAgICovXHJcbiAgQElucHV0KFwic2luZ2xlQXR0YWNobWVudERyYWdBbmREcm9wXCIpIHNpbmdsZUF0dGFjaG1lbnREcmFnQW5kRHJvcDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBBcnJheSBkaSBvcHppb25pIGNoZSBzaSBwb3Nzb25vIHV0aWxpenphcmUgcGVyIGlsIGNyb3BcclxuICAgKi9cclxuICBASW5wdXQoXCJjcm9wT3B0aW9uc1wiKSBjcm9wT3B0aW9uczogQXJyYXk8Q3JvcE9wdGlvbkVudW0+ID0gW107XHJcblxyXG4gIC8qKlxyXG4gICAqIENsYXNzZSBjdXN0b20gZGEgYXNzZWduYXJlIGFsIGRpYWxvZyBkZWwgY3JvcCBpbW1hZ2luaVxyXG4gICAqL1xyXG4gIEBJbnB1dChcImNyb3BEaWFsb2dDbGFzc1wiKSBjcm9wRGlhbG9nQ2xhc3M6IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogSW5wdXQgcGVyIGRlZmluaXJlIGxlIGxhYmVsIGRhIHVzYXJlIG5lbCBjb21wb25lbnRlXHJcbiAgICovXHJcbiAgQElucHV0KFwiZG93bmxvYWRUb29sdGlwUG9zaXRpb25cIikgZG93bmxvYWRUb29sdGlwUG9zaXRpb246IFRvb2x0aXBQb3NpdGlvblR5cGUgPSBUb29sdGlwUG9zaXRpb25UeXBlLkJlbG93O1xyXG4gIEBJbnB1dChcIm9wZW5MaW5rTGFiZWxcIikgb3BlbkxpbmtMYWJlbDogc3RyaW5nID0gXCJBcHJpIGxpbmtcIjtcclxuICBASW5wdXQoXCJhZGRCdXR0b25MYWJlbFwiKSBhZGRCdXR0b25MYWJlbDogc3RyaW5nID0gXCJBZ2dpdW5naVwiO1xyXG4gIEBJbnB1dChcImRvd25sb2FkTGFiZWxcIikgZG93bmxvYWRMYWJlbDogc3RyaW5nID0gXCJEb3dubG9hZFwiO1xyXG4gIEBJbnB1dChcImRlbGV0ZUxhYmVsXCIpIGRlbGV0ZUxhYmVsOiBzdHJpbmcgPSBcIkVsaW1pbmFcIjtcclxuICBASW5wdXQoXCJmaWxlTmFtZUxhYmVsXCIpIGZpbGVOYW1lTGFiZWw6IHN0cmluZyA9IFwiTm9tZSBmaWxlXCI7XHJcbiAgQElucHV0KFwicHJldmlld0xhYmVsXCIpIHByZXZpZXdMYWJlbDogc3RyaW5nID0gXCJBbnRlcHJpbWFcIjtcclxuICBASW5wdXQoXCJ1cGxvYWRGaWxlTGFiZWxcIikgdXBsb2FkRmlsZUxhYmVsOiBzdHJpbmcgPSBcIkNhcmljYSBmaWxlXCI7XHJcbiAgQElucHV0KFwiY29uZmlybUxhYmVsXCIpIGNvbmZpcm1MYWJlbDogc3RyaW5nID0gXCJDb25mZXJtYVwiO1xyXG4gIEBJbnB1dChcImFib3J0TGFiZWxcIikgYWJvcnRMYWJlbDogc3RyaW5nID0gXCJBbm51bGxhXCI7XHJcbiAgQElucHV0KFwic2F2ZUxhYmVsXCIpIHNhdmVMYWJlbDogc3RyaW5nID0gXCJTYWx2YVwiO1xyXG4gIEBJbnB1dChcImV4aXRMYWJlbFwiKSBleGl0TGFiZWw6IHN0cmluZyA9IFwiRXNjaVwiO1xyXG4gIEBJbnB1dChcInVwbG9hZFdpdGhEcm9wYm94TGFiZWxcIikgdXBsb2FkV2l0aERyb3Bib3hMYWJlbDogc3RyaW5nID0gXCJDYXJpY2EgY29uIERyb3Bib3hcIjtcclxuICBASW5wdXQoXCJjcm9wTGFiZWxcIikgY3JvcExhYmVsOiBzdHJpbmcgPSBcIlNjZWdsaSBsZSBkaW1lbnNpb25pIGRlbGwnaW1tYWdpbmVcIjtcclxuICBASW5wdXQoXCJlcXBUYWJsZVNlYXJjaFRleHRcIikgZXFwVGFibGVTZWFyY2hUZXh0OiBzdHJpbmcgPSBcIkNlcmNhXCI7XHJcbiAgQElucHV0KFwiZGVsZXRlRGlhbG9nVGl0bGVcIikgZGVsZXRlRGlhbG9nVGl0bGU6IHN0cmluZyA9IG51bGw7XHJcbiAgQElucHV0KFwiZGVsZXRlRGlhbG9nTWVzc2FnZVwiKSBkZWxldGVEaWFsb2dNZXNzYWdlOiBzdHJpbmcgPSBcIlNlaSBzaWN1cm8gZGkgdm9sZXIgY2FuY2VsbGFyZSBxdWVzdCdhbGxlZ2F0bz9cIjtcclxuICBASW5wdXQoXCJub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2VcIikgbm9JbWFnZVNlbGVjdGVkRXJyb3JNZXNzYWdlOiBzdHJpbmcgPVxyXG4gICAgXCJOb24gw6ggcG9zc2liaWxlIHNlbGV6aW9uYXJlIHVuIGZpbGUgY2hlIG5vbiBzaWEgdW4naW1tYWdpbmUuXCI7XHJcbiAgQElucHV0KFwid3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2VcIikgd3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIk5vbiDDqCBwb3NzaWJpbGUgY2FyaWNhcmUgaWwgZmlsZSBzZWxlemlvbmF0by5cIjtcclxuICBASW5wdXQoXCJ2aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2VcIikgdmlkZW9QcmV2aWV3RXJyb3JNZXNzYWdlOiBzdHJpbmcgPVxyXG4gICAgXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGkgdW4gZmlsZSB2aWRlby5cIjtcclxuICBASW5wdXQoXCJ2aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2VcIikgYXVkaW9QcmV2aWV3RXJyb3JNZXNzYWdlOiBzdHJpbmcgPVxyXG4gICAgXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGkgdW4gZmlsZSBhdWRpby5cIjtcclxuICBASW5wdXQoXCJmbGlwSG9yaW56b250YWxMYWJlbFwiKSBmbGlwSG9yaW56b250YWxMYWJlbDogc3RyaW5nID0gXCJDYXBvdm9sZ2kgb3JpenpvbnRhbG1lbnRlXCI7XHJcbiAgQElucHV0KFwiZmxpcFZlcnRpY2FsTGFiZWxcIikgZmxpcFZlcnRpY2FsTGFiZWw6IHN0cmluZyA9IFwiQ2Fwb3ZvbGdpIHZlcnRpY2FsbWVudGVcIjtcclxuICBASW5wdXQoXCJyb3RhdGVSaWdodExhYmVsXCIpIHJvdGF0ZVJpZ2h0TGFiZWw6IHN0cmluZyA9IFwiUnVvdGEgYSBkZXN0cmFcIjtcclxuICBASW5wdXQoXCJyb3RhdGVMZWZ0TGFiZWxcIikgcm90YXRlTGVmdExhYmVsOiBzdHJpbmcgPSBcIlJ1b3RhIGEgc2luaXN0cmFcIjtcclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIEBPdXRwdXQgZGVsIGNvbXBvbmVudGVcclxuXHJcbiAgLyoqXHJcbiAgICogUmVzdGl0dWlzY2UgbGEgbGlzdGEgYWdnaW9ybmF0YSBkZWdsaSBhbGxlZ2F0aS5cclxuICAgKi9cclxuICBAT3V0cHV0KCkgbG9jYWxFZGl0ZWRBdHRhY2htZW50czogRXZlbnRFbWl0dGVyPEFycmF5PElBdHRhY2htZW50RFRPPj4gPSBuZXcgRXZlbnRFbWl0dGVyPEFycmF5PElBdHRhY2htZW50RFRPPj4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnRvIHNjYXRlbmF0byBhbGxhIHByZXNzaW9uZSBkZWwgcHVsc2FudGUgRVNDSSBkZWxsYSBtb2RhbGUgZGkgY2FyaWNhbWVudG8gZmlsZS5cclxuICAgKi9cclxuICBAT3V0cHV0KCkgYWJvcnRBZGRBdHRhY2htZW50OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsJ0lBdHRhY2htZW50RFRPIHNlbGV6aW9uYXRvIHBlciBpbCBkb3dubG9hZCBuZWwgY2FzbyBGaWxlRGF0YUJhc2U2NCwgRmlsZUNvbnRlbnRUeXBlIG8gRmlsZU5hbWUgbm9uIGZvc3Nlcm8gc3BlY2lmaWNhdGkuXHJcbiAgICovXHJcbiAgQE91dHB1dChcImRvd25sb2FkQXR0YWNobWVudFwiKSBkb3dubG9hZEF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4gPSBuZXcgRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsJ2VsZW1lbnRvIGVsaW1pbmF0byBwcmltYSBjaGUgcXVlc3RvIHZlbmdhIGVmZmV0dGl2YW1lbnRlIHJpc21vc3NvIGRhbGxhIGxpc3RhLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoXCJvbkRlbGV0ZUF0dGFjaG1lbnRcIikgb25EZWxldGVBdHRhY2htZW50OiBFdmVudEVtaXR0ZXI8SUF0dGFjaG1lbnREVE8+ID0gbmV3IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8vI3JlZ2lvbiBQcm9wcmlldMOgIHBlciBnZXN0aW9uZSBjYXJpY2FtZW50byBudW92byBhbGxlZ2F0b1xyXG4gIG5ld0F0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgbmV3TXVsdGlwbGVBdHRhY2htZW50czogQXJyYXk8SUF0dGFjaG1lbnREVE8+ID0gW107XHJcbiAgYXR0YWNobWVudFR5cGUgPSBBdHRhY2htZW50VHlwZTtcclxuICAvLyB1cGxvYWRUeXBlRW51bSA9IFVwbG9hZFR5cGVFbnVtO1xyXG4gIG5ld0F0dGFjaG1lbnRGb3JtOiBGb3JtR3JvdXA7XHJcbiAgc2VsZWN0ZWRGaWxlOiBGaWxlID0gbnVsbDtcclxuICBzZWxlY3RlZEZpbGVzOiBBcnJheTxGaWxlPiA9IG51bGw7XHJcbiAgc2hvd0Nyb3BJbWFnZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBWaWV3Q2hpbGQoXCJkaWFsb2dBZGRBdHRhY2htZW50XCIsIHsgc3RhdGljOiB0cnVlIH0pIGRpYWxvZ0FkZEF0dGFjaG1lbnQ6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgZGlhbG9nUmVmQWRkQXR0YWNobWVudDogTWF0RGlhbG9nUmVmPFRlbXBsYXRlUmVmPGFueT4+O1xyXG4gIEBWaWV3Q2hpbGQoXCJkaWFsb2dBZGRNdWx0aXBsZUF0dGFjaG1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nQWRkTXVsdGlwbGVBdHRhY2htZW50OiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIGRpYWxvZ1JlZkNyb3BJbWFnZTogTWF0RGlhbG9nUmVmPFRlbXBsYXRlUmVmPGFueT4+O1xyXG4gIEBWaWV3Q2hpbGQoXCJkaWFsb2dDcm9wSW1hZ2VcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nQ3JvcEltYWdlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvLyNyZWdpb24gUHJvcHJpZXTDoCBwZXIgZ2VzdGlvbmUgcmlkaW1lbnNpb25hbWVudG8gZmlsZSBkaSB0aXBvIGltYWdlXHJcbiAgaW1hZ2VDaGFuZ2VkRXZlbnQ6IGFueSA9IFwiXCI7XHJcbiAgY3JvcHBlZEltYWdlOiBhbnkgPSBcIlwiO1xyXG4gIHRyYW5zZm9ybTogSW1hZ2VUcmFuc2Zvcm0gPSB7fTtcclxuICBjYW52YXNSb3RhdGlvbiA9IDA7XHJcbiAgQFZpZXdDaGlsZChJbWFnZUNyb3BwZXJDb21wb25lbnQpIGltYWdlQ3JvcHBlcjogSW1hZ2VDcm9wcGVyQ29tcG9uZW50O1xyXG4gIEBWaWV3Q2hpbGQoXCJpbWFnZUlucHV0XCIpIGltYWdlSW5wdXQ6IGFueTtcclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgQXR0YWNobWVudFR5cGUgPSBBdHRhY2htZW50VHlwZTtcclxuICBzZWxlY3RlZEF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPO1xyXG5cclxuICBvcmlnaW5hbFdpZHRoOiBudW1iZXI7XHJcbiAgb3JpZ2luYWxIZWlnaHQ6IG51bWJlcjtcclxuICBjdXN0b21XaWR0aDogbnVtYmVyO1xyXG4gIGN1c3RvbUhlaWdodDogbnVtYmVyO1xyXG5cclxuICBAVmlld0NoaWxkKFwiYXR0YWNobWVudFRhYmxlXCIsIHsgc3RhdGljOiBmYWxzZSB9KSBhdHRhY2htZW50VGFibGU6IEVxcFRhYmxlQ29tcG9uZW50O1xyXG4gIEBWaWV3Q2hpbGQoXCJpbmxpbmVQcmV2aWV3VGVtcGxhdGVcIiwgeyBzdGF0aWM6IHRydWUgfSkgaW5saW5lUHJldmlld1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBWaWV3Q2hpbGQoXCJkaWFsb2dQcmV2aWV3XCIsIHsgc3RhdGljOiB0cnVlIH0pIGRpYWxvZ1ByZXZpZXc6IFRlbXBsYXRlUmVmPGFueT47XHJcblxyXG4gIGltYWdlRmlsZTogRmlsZTtcclxuXHJcbiAgYWRkaW5nTGlua01vZGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIGRpYWxvZzogTWF0RGlhbG9nLFxyXG4gICAgcHJpdmF0ZSBmb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXIsXHJcbiAgICBwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyLFxyXG4gICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxyXG4gICAgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgICBwcml2YXRlIGVxcEF0dGFjaG1lbnRTZXJ2aWNlOiBFcXBBdHRhY2htZW50U2VydmljZVxyXG4gICkge31cclxuXHJcbiAgYXN5bmMgbmdPbkluaXQoKSB7XHJcbiAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIGFsbG9yYSBpbXBvc3RhIGlsIGZpbHRybyBwZXIgbGUgZXN0ZW5zaW9uaSBwb3NzaWJpbGkgZGEgY2FyaWNhcmVcclxuICAgIGlmICghdGhpcy5hY2NlcHRlZEZpbGVUeXBlcylcclxuICAgICAgaWYgKHRoaXMuYWxsb3dPbmx5SW1hZ2VzID09IHRydWUpIHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMgPSBcImltYWdlLypcIjtcclxuICAgICAgZWxzZSB0aGlzLmFjY2VwdGVkRmlsZVR5cGVzID0gXCIqXCI7XHJcblxyXG4gICAgLy8gU2Ugbm9uIHNvbm8gc3RhdGkgc3BlY2lmaWNhdGkgaSB0aXBpIGRhIGdlc3RpcmUgbWEgw6ggc3RhdG8gcGFzc2F0byBudWxsIG8gdW4gYXJyYXkgdnVvdG8gaW1wb3N0byBpIHRpcGkgZGkgZGVmYXVsdC5cclxuICAgIGlmICghdGhpcy5hbGxvd2VkVHlwZXMgfHwgdGhpcy5hbGxvd2VkVHlwZXMubGVuZ3RoID09IDApXHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzID0gW0F0dGFjaG1lbnRUeXBlLkZJTEUsIEF0dGFjaG1lbnRUeXBlLkxJTkssIEF0dGFjaG1lbnRUeXBlLkRST1BCT1hdO1xyXG4gICAgZWxzZSBpZiAoXHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzLmZpbmQoKHQpID0+IHQgIT0gQXR0YWNobWVudFR5cGUuRklMRSAmJiB0ICE9IEF0dGFjaG1lbnRUeXBlLkxJTksgJiYgdCAhPSBBdHRhY2htZW50VHlwZS5EUk9QQk9YKVxyXG4gICAgKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLldhcm5pbmcoXHJcbiAgICAgICAgJ0FsbWVubyB1bm8gZGVnbGkgQXR0YWNobWVudFR5cGUgc2VsZXppb25hdGkgbmVsIHBhcmFtZXRybyBcImFsbG93ZWRUeXBlc1wiIG5vbiBlc2lzdGUuJ1xyXG4gICAgICApO1xyXG4gICAgICB0aGlzLmFsbG93ZWRUeXBlcyA9IFtBdHRhY2htZW50VHlwZS5GSUxFLCBBdHRhY2htZW50VHlwZS5MSU5LLCBBdHRhY2htZW50VHlwZS5EUk9QQk9YXTtcclxuICAgIH1cclxuXHJcbiAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBtdWx0aXBsYSBkZWdsaSBhbGxlZ2F0aSBhbGxvcmEgY29uZmlndXJhIGwnZXFwLXRhYmxlXHJcbiAgICBpZiAodGhpcy5tdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSAmJiAoIXRoaXMuYXR0YWNobWVudHNDb2x1bW5zIHx8IHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLmxlbmd0aCA9PSAwKSkge1xyXG4gICAgICB0aGlzLmNvbmZpZ3VyZUNvbHVtbnMoKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50c0xpc3QgPT0gbnVsbCkgdGhpcy5hdHRhY2htZW50c0xpc3QgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgdGhpcy5jaGVja0F0dGFjaG1lbnRJbWFnZSgpO1xyXG5cclxuICAgIGlmICh0aGlzLmFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKSkge1xyXG4gICAgICB0aGlzLmVxcEF0dGFjaG1lbnRTZXJ2aWNlLmxvYWREcm9wYm94U2NyaXB0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgcmVsb2FkRGF0YSgpIHtcclxuICAgIGlmICh0aGlzLmF0dGFjaG1lbnRUYWJsZSkgdGhpcy5hdHRhY2htZW50VGFibGUucmVsb2FkRGF0YXRhYmxlKCk7XHJcbiAgfVxyXG5cclxuICBjaGVja0F0dGFjaG1lbnRJbWFnZSgpIHtcclxuICAgIHRoaXMuYXR0YWNobWVudHNMaXN0LmZvckVhY2goKGEpID0+IHtcclxuICAgICAgYS5Jc0ltYWdlID0gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuY2hlY2tJbWFnZUZyb21NaW1lVHlwZShhLkZpbGVDb250ZW50VHlwZSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vI3JlZ2lvbiBHZXN0aW9uZSBlbGVuY28gYWxsZWdhdGlcclxuXHJcbiAgLyoqXHJcbiAgICogQ29uZmlndXJhIGxlIGNvbG9ubmUgcGVyIGwnZXFwLXRhYmxlIG5lbCBjYXNvIGluIGN1aSBpbCBwYXJhbWV0cm8gXCJtdWx0aXBsZUF0dGFjaG1lbnRzXCIgw6ggVFJVRS5cclxuICAgKi9cclxuICBjb25maWd1cmVDb2x1bW5zKCkge1xyXG4gICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMgPSBbXTtcclxuICAgIGlmICh0aGlzLmRpc2FibGVBY3Rpb24gIT0gdHJ1ZSkge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKHtcclxuICAgICAgICBrZXk6IFwiYWN0aW9uXCIsXHJcbiAgICAgICAgZGlzcGxheTogXCJcIixcclxuICAgICAgICB0eXBlOiBUeXBlQ29sdW1uLk1lbnVBY3Rpb24sXHJcbiAgICAgICAgYnV0dG9uTWVudUljb246IFwibW9yZV92ZXJ0XCIsXHJcbiAgICAgICAgc3R5bGVzOiB7IGZsZXg6IFwiMCAwIDYlXCIgfSxcclxuICAgICAgICBhY3Rpb25zOiBbXHJcbiAgICAgICAgICB7IG5hbWU6IHRoaXMuZGVsZXRlTGFiZWwsIGljb246IFwiZGVsZXRlXCIsIGZuOiAoZWxlbWVudCwgaW5kZXgsIGNvbCkgPT4gdGhpcy5kZWxldGVBdHRhY2htZW50KGVsZW1lbnQpIH1cclxuICAgICAgICBdXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCBkb3dubG9hZENvbHVtbiA9IHtcclxuICAgICAga2V5OiBcImF0dGFjaG1lbnRcIixcclxuICAgICAgZGlzcGxheTogXCJcIixcclxuICAgICAgdHlwZTogVHlwZUNvbHVtbi5TaW1wbGVBY3Rpb24sXHJcbiAgICAgIHN0eWxlczogeyBmbGV4OiBcIjAgMCA2JVwiIH0sXHJcbiAgICAgIGFjdGlvbnM6IFtcclxuICAgICAgICB7XHJcbiAgICAgICAgICBuYW1lOiBcIlwiLFxyXG4gICAgICAgICAgZm9udGF3ZXNvbWU6IHRydWUsXHJcbiAgICAgICAgICBpY29uOiAoZWxlbWVudCkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zaG93SW5saW5lUHJldmlld1xyXG4gICAgICAgICAgICAgID8gZWxlbWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFXHJcbiAgICAgICAgICAgICAgICA/IFwiZmFzIGZhLWNsb3VkLWRvd25sb2FkLWFsdFwiXHJcbiAgICAgICAgICAgICAgICA6IFwiZmFzIGZhLWV4dGVybmFsLWxpbmstYWx0XCJcclxuICAgICAgICAgICAgICA6IHRoaXMuZ2V0QXR0YWNobWVudEljb24oZWxlbWVudCk7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgZm46IChlbGVtZW50LCBjb2wsIGVsZW1lbnRJbmRleCkgPT4gdGhpcy52aWV3QXR0YWNobWVudChlbGVtZW50KSxcclxuICAgICAgICAgIHRvb2x0aXA6IHtcclxuICAgICAgICAgICAgdG9vbHRpcFRleHQ6IChlbGVtZW50KSA9PiB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSA/IHRoaXMuZG93bmxvYWRMYWJlbCA6IHRoaXMub3BlbkxpbmtMYWJlbDtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgdG9vbHRpcFBvc2l0aW9uOiB0aGlzLmRvd25sb2FkVG9vbHRpcFBvc2l0aW9uXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICBdXHJcbiAgICB9O1xyXG5cclxuICAgIGxldCBpbmxpbmVQcmV2aWV3Q29sdW1uID0ge1xyXG4gICAgICBrZXk6IFwiSW5saW5lUHJldmlld1wiLFxyXG4gICAgICBkaXNwbGF5OiB0aGlzLnByZXZpZXdMYWJlbCxcclxuICAgICAgdHlwZTogVHlwZUNvbHVtbi5FeHRlcm5hbFRlbXBsYXRlLFxyXG4gICAgICBleHRlcm5hbFRlbXBsYXRlOiB0aGlzLmlubGluZVByZXZpZXdUZW1wbGF0ZSxcclxuICAgICAgc3R5bGVzOiB7IGZsZXg6IFwiMCAwIDEwJVwiIH1cclxuICAgIH07XHJcblxyXG4gICAgbGV0IGZpbGVOYW1lQ29sdW1uID0geyBrZXk6IFwiRmlsZU5hbWVcIiwgZGlzcGxheTogdGhpcy5maWxlTmFtZUxhYmVsIH07XHJcblxyXG4gICAgaWYgKHRoaXMuc2hvd0lubGluZVByZXZpZXcpIHtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChpbmxpbmVQcmV2aWV3Q29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChmaWxlTmFtZUNvbHVtbik7XHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLnB1c2goZG93bmxvYWRDb2x1bW4pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChkb3dubG9hZENvbHVtbik7XHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLnB1c2goZmlsZU5hbWVDb2x1bW4pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRWxpbWluYSB1biBhbGxlZ2F0byBlbGltaW5hbmRvIGFuY2hlIGlsIGZpbGUgcHJlc2VudGUgbmVsbG8gc3RvcmFnZSBkaSBhcmNoaXZpYXppb25lIHV0aWxpenphdG8gKEFXUyBvIGNhcnRlbGxhIHByb2dldHRvKVxyXG4gICAqIEBwYXJhbSBlbGVtZW50IElBdHRhY2htZW50RFRPIGRhIGNhbmNlbGxhcmVcclxuICAgKi9cclxuICBkZWxldGVBdHRhY2htZW50KGVsZW1lbnQ6IElBdHRhY2htZW50RFRPKSB7XHJcbiAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5Db25maXJtKFxyXG4gICAgICB0aGlzLmRlbGV0ZURpYWxvZ01lc3NhZ2UsXHJcbiAgICAgICgpID0+IHtcclxuICAgICAgICB0aGlzLnJlbW92ZUF0dGFjaG1lbnRGcm9tTGlzdCh0aGlzLmF0dGFjaG1lbnRzTGlzdC5pbmRleE9mKGVsZW1lbnQpKTtcclxuICAgICAgfSxcclxuICAgICAgdHJ1ZSxcclxuICAgICAgdGhpcy5kZWxldGVEaWFsb2dUaXRsZVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJpbXVvdmUgbCdhbGxlZ2F0byBzZWxlemlvbmF0byBkYWxsYSBsaXN0YSBcImF0dGFjaG1lbnRzTGlzdFwiIGUgaW52b2NhIGwnZXZlbnRvIGRpIG91dHB1dCBjaGUgcmVzdGl0dWlzY2UgbGEgbGlzdGEgYWdnaW9ybmF0YS5cclxuICAgKiBAcGFyYW0gYXR0YWNobWVudEluZGV4IEluZGljZSBkZWxsJ2F0dGFjaG1lbnQgZGEgcmltdW92ZXJlXHJcbiAgICovXHJcbiAgcmVtb3ZlQXR0YWNobWVudEZyb21MaXN0KGF0dGFjaG1lbnRJbmRleDogbnVtYmVyKSB7XHJcbiAgICB0aGlzLm9uRGVsZXRlQXR0YWNobWVudC5lbWl0KHRoaXMuYXR0YWNobWVudHNMaXN0W2F0dGFjaG1lbnRJbmRleF0pO1xyXG5cclxuICAgIHRoaXMuYXR0YWNobWVudHNMaXN0LnNwbGljZShhdHRhY2htZW50SW5kZXgsIDEpO1xyXG4gICAgaWYgKHRoaXMuYXR0YWNobWVudFRhYmxlKSB0aGlzLmF0dGFjaG1lbnRUYWJsZS5yZWxvYWREYXRhdGFibGUoKTtcclxuICAgIHRoaXMubG9jYWxFZGl0ZWRBdHRhY2htZW50cy5lbWl0KHRoaXMuYXR0YWNobWVudHNMaXN0KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNjYXJpY2EgbCdhbGxlZ2F0byBvIGFwcmUgaWwgbGlua1xyXG4gICAqIEBwYXJhbSBlbGVtZW50IEFsbGVnYXRvIGRhIG1vc3RyYXJlXHJcbiAgICovXHJcbiAgdmlld0F0dGFjaG1lbnQoYXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIGlmIChhdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTkspIHtcclxuICAgICAgd2luZG93Lm9wZW4oYXR0YWNobWVudC5GaWxlUGF0aCwgXCJfYmxhbmtcIik7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoYXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiBhdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSAmJiBhdHRhY2htZW50LkZpbGVOYW1lKSB7XHJcbiAgICAgIGxldCBzb3VyY2UgPSBgZGF0YToke2F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlfTtiYXNlNjQsJHthdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0fWA7XHJcbiAgICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcclxuICAgICAgbGluay5ocmVmID0gc291cmNlO1xyXG4gICAgICBsaW5rLmRvd25sb2FkID0gYCR7YXR0YWNobWVudC5GaWxlTmFtZX1gO1xyXG4gICAgICBsaW5rLmNsaWNrKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmRvd25sb2FkQXR0YWNobWVudC5lbWl0KGF0dGFjaG1lbnQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmlkZWZpbmlzY2UgbCdpY29uYSBkYSBtb3N0cmFyZSBuZWxsYSBjb2xvbm5hIGRlbGwnZXFwLXRhYmxlIHBlciBvZ25pIGZpbGUuXHJcbiAgICogTCdpY29uYSB2YXJpYSBpbiBiYXNlIGFsbCdlc3RlbnNpb25lIGRlbCBmaWxlXHJcbiAgICogQHBhcmFtIGF0dGFjaG1lbnRcclxuICAgKi9cclxuICBnZXRBdHRhY2htZW50SWNvbihhdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgaWYgKGF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykgcmV0dXJuIFwiZmFzIGZhLWxpbmtcIjtcclxuICAgIGVsc2UgcmV0dXJuIEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmdldEljb25Gcm9tRmlsZUV4dGVuc2lvbmUoYXR0YWNobWVudC5GaWxlRXh0ZW5zaW9uKTtcclxuICB9XHJcblxyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvKipcclxuICAgKiBJbiBjYXNvIGRpIGFsbGVnYXRvIHNpbmdvbG8sIHNjZWdsaWUgcXVhbGUgbWV0b2RvIHJpY2hpYW1hcmUgaW4gYmFzZSBhbCB0aXBvIGRpIGFsbGVnYXRvXHJcbiAgICovXHJcbiAgYWRkRmlsZShhdHRhY2htZW50VHlwZTogQXR0YWNobWVudFR5cGUsIGltYWdlSW5wdXQgPSBudWxsKSB7XHJcbiAgICBpZiAoYXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICB0aGlzLnN3aXRjaFRvQWRkaW5nTGlua01vZGUoKTtcclxuICAgIH0gZWxzZSBpZiAoYXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSkge1xyXG4gICAgICBpbWFnZUlucHV0LmNsaWNrKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmNob29zZURyb3Bib3hGaWxlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjcmVhdGVBdHRhY2htZW50Rm9ybSgpIHtcclxuICAgIC8vQ3JlYSBsYSBmb3JtIHBlciBsYSB2YWxpZGF6aW9uZSBkZWkgY2FtcGlcclxuICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0gPSB0aGlzLmZvcm1CdWlsZGVyLmdyb3VwKHtcclxuICAgICAgdHlwZTogW3RoaXMubmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSwgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXHJcbiAgICAgIG5hbWU6IFt0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZU5hbWVdLFxyXG4gICAgICBwYXRoOiBbdGhpcy5uZXdBdHRhY2htZW50LkZpbGVQYXRoXSxcclxuICAgICAgY3VzdG9tSGVpZ2h0OiBbdGhpcy5jdXN0b21IZWlnaHRdLFxyXG4gICAgICBjdXN0b21XaWR0aDogW3RoaXMuY3VzdG9tV2lkdGhdXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGNsb3NlKGVtaXRDbG9zZUV2ZW50ID0gdHJ1ZSkge1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50ID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcbiAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudEZvcm0pIHRoaXMubmV3QXR0YWNobWVudEZvcm0ucmVzZXQoKTtcclxuXHJcbiAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZS5jbG9zZSgpO1xyXG4gICAgdGhpcy5yZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKCk7XHJcblxyXG4gICAgaWYgKGVtaXRDbG9zZUV2ZW50ID09IHRydWUgJiYgdGhpcy5hYm9ydEFkZEF0dGFjaG1lbnQpIHRoaXMuYWJvcnRBZGRBdHRhY2htZW50LmVtaXQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGJhc2UgYWwgdGlwbyBkaSBhbGxlZ2F0byBjb250cm9sbGEgc2UgZGlzYWJpbGl0YXJlIG8gbWVubyBpbCBwdWxzYW50ZSBwZXIgc2FsdmFyZS5cclxuICAgKiBGdW56aW9uZSB1c2F0YSBuZWwgW2Rpc2FibGVdIGRlbCBwdWxzYW50ZSBcIlNhbHZhXCIgZGVsIGRpYWxvZyBwZXIgbCdhZ2dpdW50YSBkaSB1biBhbGxlZ2F0by5cclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGRpc2FibGVTYXZlKCkge1xyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUpIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NDtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMubmV3QXR0YWNobWVudC5GaWxlUGF0aDtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIChcclxuICAgICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMuZmlsdGVyKFxyXG4gICAgICAgICAgKHApID0+XHJcbiAgICAgICAgICAgIChwLkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUgJiYgIXAuRmlsZURhdGFCYXNlNjQpIHx8XHJcbiAgICAgICAgICAgIChwLkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTksgJiYgIXAuRmlsZVBhdGgpXHJcbiAgICAgICAgKS5sZW5ndGggPiAwXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25maXJtQWRkQXR0YWNobWVudCgpIHtcclxuICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSkge1xyXG4gICAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSB0aGlzLmltYWdlQ3JvcHBlci5jcm9wKCkuYmFzZTY0LnNwbGl0KFwiO2Jhc2U2NCxcIilbMV07XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTksgJiYgIXRoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZSlcclxuICAgICAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZU5hbWUgPSB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZVBhdGg7XHJcblxyXG4gICAgICBpZiAodGhpcy5hdHRhY2htZW50c0xpc3QgPT0gbnVsbCkgdGhpcy5hdHRhY2htZW50c0xpc3QgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzTGlzdC5wdXNoKHRoaXMubmV3QXR0YWNobWVudCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID09IG51bGwgfHwgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLmxlbmd0aCA9PSAwKSByZXR1cm47XHJcblxyXG4gICAgICBpZiAodGhpcy5hdHRhY2htZW50c0xpc3QgPT0gbnVsbCkgdGhpcy5hdHRhY2htZW50c0xpc3QgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IHRoaXMuYXR0YWNobWVudHNMaXN0LmNvbmNhdCh0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmF0dGFjaG1lbnRUYWJsZSkgdGhpcy5hdHRhY2htZW50VGFibGUucmVsb2FkRGF0YXRhYmxlKCk7XHJcblxyXG4gICAgdGhpcy5sb2NhbEVkaXRlZEF0dGFjaG1lbnRzLmVtaXQodGhpcy5hdHRhY2htZW50c0xpc3QpO1xyXG5cclxuICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSkge1xyXG4gICAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZS5jbG9zZSgpO1xyXG4gICAgICB0aGlzLnJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFwcmUgaWwgZGlhbG9nIHBlciBsJ2FudGVwcmltYSBkZWxsJ2FsbGVnYXRvIHNlbGV6aW9uYXRvLlxyXG4gICAqIEBwYXJhbSByb3dcclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGFzeW5jIG9wZW5QcmV2aWV3RGlhbG9nKHJvdzogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShyb3cpKTtcclxuXHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSkge1xyXG4gICAgICBpZiAodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlLnN0YXJ0c1dpdGgoXCJ2aWRlb1wiKSkge1xyXG4gICAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLldhcm5pbmcodGhpcy52aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2UpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfSBlbHNlIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUuc3RhcnRzV2l0aChcImF1ZGlvXCIpKSB7XHJcbiAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuV2FybmluZyh0aGlzLmF1ZGlvUHJldmlld0Vycm9yTWVzc2FnZSk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuZ2V0QXR0YWNobWVudEVuZHBvaW50ICYmIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2UgJiYgIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0KSB7XHJcbiAgICAgIGF3YWl0IHRoaXMuZ2V0QXR0YWNobWVudEJ5SUQoKVxyXG4gICAgICAgIC50aGVuKChyZXMpID0+IHtcclxuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gcmVzLkZpbGVEYXRhQmFzZTY0O1xyXG4gICAgICAgIH0pXHJcbiAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcclxuICAgICAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkVycm9yKGVycik7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTkspIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuVHJ1c3RlZFVybCA9IHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybChcclxuICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aFxyXG4gICAgICApO1xyXG4gICAgfSBlbHNlIGlmIChcclxuICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuSXNJbWFnZSAmJlxyXG4gICAgICAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgJiZcclxuICAgICAgIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVUaHVtYm5haWxCYXNlNjRcclxuICAgICkge1xyXG4gICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5JbmZvKFwiSW1wb3NzaWJpbGUgYXByaXJlIGwnYW50ZXByaW1hIGRlbGwnYWxsZWdhdG8sIGZpbGUgbWFuY2FudGUuXCIpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9IGVsc2UgaWYgKCF0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aCAmJiB0aGlzLnByb2R1Y3Rpb25CYXNlVXJsKSB7XHJcbiAgICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuVHJ1c3RlZFVybCA9IHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybChcclxuICAgICAgICAgIFwiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vZ3ZpZXc/dXJsPVwiICtcclxuICAgICAgICAgICAgdGhpcy5wcm9kdWN0aW9uQmFzZVVybCArXHJcbiAgICAgICAgICAgIFwiL1wiICtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVBhdGggK1xyXG4gICAgICAgICAgICBcIiZlbWJlZGRlZD10cnVlXCJcclxuICAgICAgICApO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkluZm8oXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGVsIGRvY3VtZW50byFcIik7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5kaWFsb2cub3Blbih0aGlzLmRpYWxvZ1ByZXZpZXcsIHtcclxuICAgICAgZGlzYWJsZUNsb3NlOiB0cnVlLFxyXG4gICAgICBoYXNCYWNrZHJvcDogdHJ1ZVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRBdHRhY2htZW50QnlJRCgpIHtcclxuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdDxJQXR0YWNobWVudERUTz4odGhpcy5nZXRBdHRhY2htZW50RW5kcG9pbnQsIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50KS50b1Byb21pc2UoKTtcclxuICB9XHJcblxyXG4gIC8vI3JlZ2lvbiBHZXN0aW9uZSBjYXJpY2FtZW50byBmaWxlXHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBzY2F0ZW5hdG8gYWxsYSBzZWxlemlvbmUgZGVsIGZpbGUgKG8gZGVpIGZpbGUpLlxyXG4gICAqIFNlIGlsIGNhcmljYW1lbnRvIMOoIFNJTkdPTE8gbyBzZSBjb211bnF1ZSDDqCBzdGF0byBzZWxlemlvbmF0byB1biBzb2xvIGZpbGUgYWxsb3JhIHNpIG9jY3VwYSBkaSBjb250cm9sbGFyZSBzZSBzaSB0cmF0dGEgZGkgdW4gaW1tYWdpbmUgaW4gbW9kbyBkYVxyXG4gICAqIG1vc3RyYXJlIGxlIGZ1bnppb25hbGl0w6AgZGVsIGNyb3BwaWUgKHBlciByaXRhZ2xpYXJlIGwnaW1tYWdpbmUpIG9wcHVyZSBuby5cclxuICAgKiBTZSBpbCBmaWxlIGNhcmljYXRvIG5vbiDDqCB1biBpbW1hZ2luZSBhbGxvcmEgZ2VuZXJhIGRpcmV0dGFtZW50ZSBpbCBiYXNlNjQgZSBsbyBhc3NvY2lhIGFsbCdhbGxlZ2F0byBkYSBzYWx2YXJlLlxyXG4gICAqIFNlIGludmVjZSBpbCBjYXJpY2FtZW50byBkZWkgZmlsZSDDqCBNVUxUSVBMTyBlIHNvbm8gcHJlc2VudGkgcGnDuSBmaWxlIGFsbG9yYSBlc2VndWUgbGUgc3Rlc3NlIG9wZXJhemlvbmkgaWdub3JhbmRvIHBlcsOyIGlsIGNvbnRybGxvXHJcbiAgICogaW1tYWdpbmUgcGVyIGlsIGNyb3BwaWUgKGluIGNhc28gZGkgY2FyaWNhbWVudG8gbXVsdGlwbG8gbGUgZnVuemlvbmFsaXTDoCBkZWwgY3JvcHBpZSBzb25vIGRpc2FiaWxpdGF0ZSkuXHJcbiAgICovXHJcbiAgYXN5bmMgb25GaWxlQWRkZWQoZXZlbnQsIGlzRmlsZURyb3BwZWQ6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG4gICAgdGhpcy5zaG93Q3JvcEltYWdlID0gZmFsc2U7XHJcbiAgICBsZXQgZmlsZXNPbklucHV0ID0gaXNGaWxlRHJvcHBlZCA/IGV2ZW50IDogZXZlbnQudGFyZ2V0LmZpbGVzO1xyXG5cclxuICAgIC8vU2Ugw6ggc3RhdG8gcmljaGllc3RvIGlsIGNhcmljYW1lbnRvIFNJTkdPTE8gb3BwdXJlIHNlIGlsIGNhcmljYW1lbnRvIMOoIE1VTFRJUExPIG1hIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIHNvbG8gZmlsZVxyXG4gICAgLy9hbGxvcmEgdmVyaWZpY2Egc2UgaWwgZmlsZSDDqCB1biBpbW1hZ2luZSAocGVyIG1vc3RyYXJlIGlsIENST1BQSUUpXHJcbiAgICBpZiAoWy4uLmZpbGVzT25JbnB1dF0ubGVuZ3RoID09IDEgfHwgdGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlID0gZmlsZXNPbklucHV0WzBdO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSBmaWxlc09uSW5wdXQ7XHJcbiAgICAgIGlmICghdGhpcy5zZWxlY3RlZEZpbGUpIHJldHVybjtcclxuXHJcbiAgICAgIC8vTWVtb3JpenphIGkgZGF0aSBwZXIgbCdhbGxlZ2F0b1xyXG4gICAgICB0aGlzLm5ld0F0dGFjaG1lbnQgPSBhd2FpdCB0aGlzLmNyZWF0ZUF0dGFjaG1lbnRGcm9tVXBsb2FkZWRGaWxlKHRoaXMuc2VsZWN0ZWRGaWxlLCBmYWxzZSk7XHJcbiAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuXHJcbiAgICAgIC8vU2Ugw6ggc3RhdGEgcmljaGllc3RhIGxhIGdlc3Rpb25lIGRlbGxlIHNvbGUgaW1tYWdpbmkgbWEgcGVyIGVycm9yZSDDqCBzdGF0byBzZWxlemlvbmF0byB1biBmaWxlIGNoZSBub24gw6ggdW4gaW1tYWdpbmVcclxuICAgICAgbGV0IGNoZWNrT25seUltYWdlID0gdGhpcy5jaGVja0FsbG93T25seUltYWdlRmlsZSh0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG4gICAgICBpZiAoY2hlY2tPbmx5SW1hZ2UgPT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgIHRoaXMuY3JlYXRlQXR0YWNobWVudEZvcm0oKTtcclxuXHJcbiAgICAgIC8vVmVyaWZpY2Egc2UgaWwgZmlsZSBjYXJpY2F0byDDqCB1bidpbW1hZ2luZSBvcHB1cmUgbm8uIFNlIMOoIHVuIGltbWFnaW5lLCBwcmltYSBkaSBjYXJpY2FybGEgbW9zdHJhIGlsIGNyb3BwaWUgcGVyIGlsIHJlc2l6ZS5cclxuICAgICAgLy9TZSBub24gw6ggdW4gaW1tYWdpbmUgYWxsb3JhIGdlbmVyYSBpbCBCYXNlNjRcclxuICAgICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlID09IHRydWUpIHtcclxuICAgICAgICB0aGlzLmdldEltYWdlRGltZW5zaW9ucyhmaWxlc09uSW5wdXRbMF0pO1xyXG5cclxuICAgICAgICAvL01vc3RyYSBpbCBjcm9wcGllIGUgZGlzYWJpbGl0YSBsYSBmb3JtIGZpbmNow6ggbm9uIHRlcm1pbmEgbGEgbW9kaWZpY2EgZGVsbCdpbW1hZ2luZVxyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0uZGlzYWJsZSgpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0uY29udHJvbHNbXCJjdXN0b21XaWR0aFwiXS5lbmFibGUoKTtcclxuICAgICAgICB0aGlzLm5ld0F0dGFjaG1lbnRGb3JtLmNvbnRyb2xzW1wiY3VzdG9tSGVpZ2h0XCJdLmVuYWJsZSgpO1xyXG4gICAgICAgIHRoaXMuc2hvd0Nyb3BJbWFnZSA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5pbWFnZUZpbGUgPSBldmVudDtcclxuXHJcbiAgICAgICAgdGhpcy5kaWFsb2dSZWZDcm9wSW1hZ2UgPSB0aGlzLmRpYWxvZy5vcGVuKHRoaXMuZGlhbG9nQ3JvcEltYWdlLCB7XHJcbiAgICAgICAgICBkaXNhYmxlQ2xvc2U6IHRydWUsXHJcbiAgICAgICAgICBoYXNCYWNrZHJvcDogdHJ1ZSxcclxuICAgICAgICAgIHdpZHRoOiBcIjYwJVwiLFxyXG4gICAgICAgICAgbWF4SGVpZ2h0OiBcIjgwJVwiLFxyXG4gICAgICAgICAgbWF4V2lkdGg6IFwiNzB2aFwiXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zaG93Q3JvcEltYWdlID0gZmFsc2U7XHJcbiAgICAgICAgbGV0IGJhc2U2NFJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0QmFzZTY0RnJvbUZpbGUodGhpcy5zZWxlY3RlZEZpbGUpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IGJhc2U2NFJlc3VsdC5CYXNlNjRGaWxlO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBiYXNlNjRSZXN1bHQuQ29udGVudFR5cGU7XHJcbiAgICAgICAgdGhpcy5jb25maXJtQWRkQXR0YWNobWVudCgpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSBmaWxlc09uSW5wdXQ7XHJcbiAgICAgIGlmICghdGhpcy5zZWxlY3RlZEZpbGVzIHx8IHRoaXMuc2VsZWN0ZWRGaWxlcy5sZW5ndGggPT0gMCkgcmV0dXJuO1xyXG5cclxuICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VsZWN0ZWRGaWxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGxldCBuZXdBdHRhY2htZW50OiBJQXR0YWNobWVudERUTyA9IGF3YWl0IHRoaXMuY3JlYXRlQXR0YWNobWVudEZyb21VcGxvYWRlZEZpbGUoXHJcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkRmlsZXNbaV0sXHJcbiAgICAgICAgICB0cnVlLFxyXG4gICAgICAgICAgdHJ1ZVxyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy9TZSDDqCBzdGF0YSByaWNoaWVzdGEgbGEgZ2VzdGlvbmUgZGVsbGUgc29sZSBpbW1hZ2luaSBtYSBwZXIgZXJyb3JlIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIGZpbGUgY2hlIG5vbiDDqCB1biBpbW1hZ2luZVxyXG4gICAgICAgIGxldCBjaGVja09ubHlJbWFnZSA9IHRoaXMuY2hlY2tBbGxvd09ubHlJbWFnZUZpbGUobmV3QXR0YWNobWVudCk7XHJcbiAgICAgICAgaWYgKGNoZWNrT25seUltYWdlID09IGZhbHNlKSByZXR1cm47XHJcblxyXG4gICAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5wdXNoKG5ld0F0dGFjaG1lbnQpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuY29uZmlybUFkZEF0dGFjaG1lbnQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvL1Jlc2V0dG8gaWwgdmFsb3JlIGRlbCBmaWxlIGlucHV0IGluIG1vZG8gZGEgc2NhdGVuYXJlIGlsIGNoYW5nZSBhbmNoZSBzZSBzaSBkb3Zlc3NlIGNhcmljYXJlIGxvIHN0ZXNzbyBmaWxlXHJcbiAgICBpZiAoIWlzRmlsZURyb3BwZWQpIGV2ZW50LnRhcmdldC52YWx1ZSA9IFwiXCI7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBIHBhcnRpcmUgZGFsIEZJTEUgcmljZXZ1dG8gaW4gaW5wdXQgcmljb3N0cnVpc2NlIGwnb2dnZXR0byBJQXR0YWNobWVudERUTyBlIGxvIHJlc3RpdHVpc2NlLlxyXG4gICAqIFNlIGlsIHBhcmFtZXRybyBnZXRCYXNlNjQgdmllbmUgcGFzc2F0byBhIFRSVUUgYWxsb3JhLCBzZW1wcmUgYSBwYXJ0aXJlIGRhbCBmaWxlLGdlbmVyYSBpbCBiYXNlNjQgZVxyXG4gICAqIHJpY2F2YSBpbCBDb250ZW50VHlwZSBkYSBhc3NvY2lhcmUgYWxsJ29nZ2V0dG8gSUF0dGFjaG1lbnREVE8gZGEgcmVzdGl0dWlyZVxyXG4gICAqIEBwYXJhbSBjdXJyZW50RmlsZSBPZ2dldHRvIEZJTEUgZGEgcHJvY2Vzc2FyZVxyXG4gICAqIEBwYXJhbSBnZXRCYXNlNjQgU2UgVFJVRSBhbGxvcmEgY2FsY29sYSBiYXNlNjQgZSBDb250ZW50VHlwZSBkZWwgZmlsZSBwYXNzYXRvIGluIGlucHV0XHJcbiAgICogQHJldHVybnMgUmVzdGl0dWlzY2UgdW4gb2dnZXR0byBkaSB0aXBvIElBdHRhY2htZW50RFRPXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyBjcmVhdGVBdHRhY2htZW50RnJvbVVwbG9hZGVkRmlsZShcclxuICAgIGN1cnJlbnRGaWxlOiBGaWxlLFxyXG4gICAgZ2V0QmFzZTY0OiBib29sZWFuID0gdHJ1ZSxcclxuICAgIGNyb3BGaWxlOiBib29sZWFuID0gZmFsc2VcclxuICApOiBQcm9taXNlPElBdHRhY2htZW50RFRPPiB7XHJcbiAgICBsZXQgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8gPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICAgIC8vTWVtb3JpenphIGkgZGF0aSBwZXIgbCdhbGxlZ2F0b1xyXG4gICAgbmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlLkZJTEU7XHJcbiAgICBuZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IGN1cnJlbnRGaWxlLnR5cGU7XHJcbiAgICBuZXdBdHRhY2htZW50LkZpbGVOYW1lID0gY3VycmVudEZpbGUubmFtZTtcclxuICAgIG5ld0F0dGFjaG1lbnQuRmlsZUV4dGVuc2lvbiA9IGN1cnJlbnRGaWxlLm5hbWUuc3Vic3RyKGN1cnJlbnRGaWxlLm5hbWUubGFzdEluZGV4T2YoXCIuXCIpICsgMSk7XHJcbiAgICBuZXdBdHRhY2htZW50LklzSW1hZ2UgPSBBdHRhY2htZW50SGVscGVyU2VydmljZS5jaGVja0ltYWdlRnJvbU1pbWVUeXBlKGN1cnJlbnRGaWxlLnR5cGUpO1xyXG5cclxuICAgIGlmIChnZXRCYXNlNjQgPT0gdHJ1ZSkge1xyXG4gICAgICBsZXQgYmFzZTY0UmVzdWx0ID0gYXdhaXQgdGhpcy5nZXRCYXNlNjRGcm9tRmlsZShjdXJyZW50RmlsZSk7XHJcbiAgICAgIG5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSBiYXNlNjRSZXN1bHQuQmFzZTY0RmlsZTtcclxuICAgICAgbmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBiYXNlNjRSZXN1bHQuQ29udGVudFR5cGU7XHJcblxyXG4gICAgICBpZiAobmV3QXR0YWNobWVudC5Jc0ltYWdlICYmIG5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgJiYgY3JvcEZpbGUpIHtcclxuICAgICAgICB0aGlzLmdldENyb3BwZWRBbmRVcGxvYWQoYGRhdGE6JHtiYXNlNjRSZXN1bHQuQ29udGVudFR5cGV9O2Jhc2U2NCwke2Jhc2U2NFJlc3VsdC5CYXNlNjRGaWxlfWAsIG5ld0F0dGFjaG1lbnQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5ld0F0dGFjaG1lbnQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBIHBhcnRpcmUgZGFsIGZpbGUgcGFzc2F0byBpbiBpbnB1dCByZXN0aXR1aXNjZSB1biBvZ2dldHRvXHJcbiAgICogY29udGVuZW50ZSBpbCBiYXNlNjQgZGVsIGZpbGUgZSBpbCBzdW8gY29udGVudFR5cGVcclxuICAgKiBAcGFyYW0gY3VycmVudEZpbGUgT2dnZXR0byBGaWxlIGRhIGN1aSBlc3RyYXBvbGFyZSBiYXNlNjQgZSBjb250ZW50VHlwZVxyXG4gICAqIEByZXR1cm5zIFJlc3RpdHVpc2NlIHVuIG9nZ2V0dG8gYXZlbnRlIGxlIHByb3ByaWV0w6AgQmFzZTY0RmlsZSBlIENvbnRlbnRUeXBlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyBnZXRCYXNlNjRGcm9tRmlsZShjdXJyZW50RmlsZTogRmlsZSk6IFByb21pc2U8YW55PiB7XHJcbiAgICBsZXQgYmFzZTY0RmlsZSA9IGF3YWl0IHRvQmFzZTY0KGN1cnJlbnRGaWxlKTtcclxuICAgIGxldCBjb250ZW50VHlwZTogc3RyaW5nID0gbnVsbDtcclxuICAgIGlmIChiYXNlNjRGaWxlKSB7XHJcbiAgICAgIC8vIExvcmlzIDIwLzAxLzIwMjI6IFBST0JMRU1BIC0gUXVhbmRvIGVzZWd1byBsJ3VwbG9hZCBkaSB1biBmaWxlIC5zcWwgbm9uIHZpZW5lIHNhbHZhdG8vc2NhcmljYXRvIGNvcnJldHRhbWVudGUuXHJcbiAgICAgIC8vICAgICAgICAgICAgICAgICAgIFF1ZXN0byBzdWNjZWRlIHBlcmNow6ggbm9uIHZpZW5lIHBvcG9sYXRvIGlsIEZpbGVDb250ZW50VHlwZS4gUGVyIHJpc29sdmVyZSBpbCBwcm9ibGVtYVxyXG4gICAgICAvLyAgICAgICAgICAgICAgICAgICBmYWNjaW8gdW4gY29udHJvbGxvIGUgc2Ugbm9uIGVzaXN0ZSBpbCBGaWxlQ29udGVudFR5cGUgYWxsb3JhIGxvIHJlY3VwZXJvIGRhbCBiYXNlNjQgb3R0ZW51dG8uXHJcbiAgICAgIGNvbnRlbnRUeXBlID0gYmFzZTY0RmlsZS5zcGxpdChcIixcIilbMF0uc3BsaXQoXCI6XCIpWzFdLnNwbGl0KFwiO1wiKVswXTtcclxuICAgICAgLy8gVW4gYWx0cm8gbWV0b2RvIHBlciBsZWdnZXJlIGlsIGNjb250ZW50IHR5cGUgZGVsIGZpbGUgw6ggdHJhbWl0ZSB1bmEgcmVndWxhciBleHByZXNzaW9uOlxyXG4gICAgICBiYXNlNjRGaWxlID0gYmFzZTY0RmlsZS5zcGxpdChcIixcIilbMV07XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHJlc3VsdCA9IHtcclxuICAgICAgQmFzZTY0RmlsZTogYmFzZTY0RmlsZSxcclxuICAgICAgQ29udGVudFR5cGU6IGNvbnRlbnRUeXBlXHJcbiAgICB9O1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb250cm9sbGEgc2UgaWwgZmlsZSBjaGUgc2kgc3RhIGNhcmljYW5kbyDDqCBzdXBwb3J0YXRvIGRhbCBzaXN0ZW1hLlxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjaGVja0FjY2VwdGVkRmlsZXMoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoXHJcbiAgICAgICh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUgJiYgdGhpcy5zZWxlY3RlZEZpbGUudHlwZS5zdGFydHNXaXRoKFwidmlkZW9cIikpIHx8XHJcbiAgICAgICh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzID09IHRydWUgJiYgWy4uLnRoaXMuc2VsZWN0ZWRGaWxlc10uZmlsdGVyKChwKSA9PiBwLnR5cGUuc3RhcnRzV2l0aChcInZpZGVvXCIpKS5sZW5ndGggPiAwKVxyXG4gICAgKVxyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgaWYgKHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMgPT0gXCIqXCIpIHJldHVybiB0cnVlO1xyXG5cclxuICAgIC8vVmVyaWZpY2EgY2hlIGkgdGlwaSBkZWwgZmlsZSAobyBkZWkgZmlsZSkgY2FyaWNhdGkgc2lhbm8gY29lcmVudGkgY29uIHF1ZWxsaSBhY2NldHRhdGkgZGFsbGEgZGlyZXR0aXZhXHJcbiAgICBsZXQgYWNjZXB0ZWQ6IGJvb2xlYW4gPSB0cnVlO1xyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkgYWNjZXB0ZWQgPSB0aGlzLmFjY2VwdGVkRmlsZVR5cGVzLmluY2x1ZGVzKHRoaXMuc2VsZWN0ZWRGaWxlLnR5cGUpO1xyXG4gICAgZWxzZSB7XHJcbiAgICAgIGxldCB1cGxvYWRlZEZpbGVUeXBlczogc3RyaW5nW10gPSBbLi4udGhpcy5zZWxlY3RlZEZpbGVzXS5tYXAoKHApID0+IHAudHlwZSk7XHJcbiAgICAgIHVwbG9hZGVkRmlsZVR5cGVzLmZvckVhY2goKHR5cGUpID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMuaW5jbHVkZXModHlwZSkpIGFjY2VwdGVkID0gZmFsc2U7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vUXVlc3RvIGNvbnRyb2xsbyBwZXJtZXR0ZSBkaSBnZXN0aXJlIGxlIGNhc2lzdGljaGUgcGVyIGN1aSB2ZW5nb25vIGluZGljYXRpIGNvbWUgdGlwaSB2YWxpZGksIGFkIGVzZW1waW8sICdpbWFnZS8qJ1xyXG4gICAgaWYgKCFhY2NlcHRlZCAmJiB0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpIHtcclxuICAgICAgZm9yIChsZXQgdCBvZiB0aGlzLmFjY2VwdGVkRmlsZVR5cGVzLnNwbGl0KFwiLFwiKS5maWx0ZXIoKHQpID0+IHQuaW5jbHVkZXMoXCIqXCIpKSkge1xyXG4gICAgICAgIGFjY2VwdGVkID0gdGhpcy5zZWxlY3RlZEZpbGUudHlwZS5zdGFydHNXaXRoKHQuc3BsaXQoXCIqXCIpWzBdKTtcclxuICAgICAgICBpZiAoYWNjZXB0ZWQpIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYWNjZXB0ZWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZSBlcXAtYXR0YWNobWVudHMgw6ggc3RhdGEgY29uZmlndXJhdGEgcGVyIGlsIGNhcmljYW1lbnRvIGRlbGxlIHNvbGUgaW1tYWdpbmkgYWxsb3JhIHZlcmlmaWNhIGNoZSBpbCBmaWxlIHBhc3NhdG8gaW5cclxuICAgKiBpbnB1dCBzaWEgZWZmZXR0aXZhbWVudGUgdW4gaW1tYWdpbmUgbyBuby5cclxuICAgKiBTZSBpbCBjb250cm9sbG8gdmEgYSBidW9uIGZpbmUgcmVzdGl0dWlzY2UgVFJVRSBhbHRyaW1lbnRpIG1vc3RyYSB1biBtZXNzYWdnaW8gZCdlcnJvcmUgZSByZXN0aXR1aXNjZSBGQUxTRVxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2hlY2tBbGxvd09ubHlJbWFnZUZpbGUobmV3QXR0YWNobWVudCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuYWxsb3dPbmx5SW1hZ2VzID09IHRydWUgJiYgbmV3QXR0YWNobWVudC5Jc0ltYWdlICE9IHRydWUpIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IodGhpcy5ub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2UpO1xyXG4gICAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9IGVsc2UgaWYgKCF0aGlzLmNoZWNrQWNjZXB0ZWRGaWxlcygpKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkVycm9yKHRoaXMud3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2UpO1xyXG4gICAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICAvLyNyZWdpb24gR2VzdGlvbmUgY3JvcCBmaWxlXHJcblxyXG4gIGdldEltYWdlRGltZW5zaW9ucyhpbWc6IGFueSkge1xyXG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgIHJlYWRlci5vbmxvYWQgPSAoZTogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XHJcbiAgICAgIGltYWdlLnNyYyA9IGUudGFyZ2V0LnJlc3VsdDtcclxuICAgICAgaW1hZ2Uub25sb2FkID0gKHJzKSA9PiB7XHJcbiAgICAgICAgdGhpcy5vcmlnaW5hbEhlaWdodCA9IHJzLmN1cnJlbnRUYXJnZXRbXCJoZWlnaHRcIl07XHJcbiAgICAgICAgdGhpcy5vcmlnaW5hbFdpZHRoID0gcnMuY3VycmVudFRhcmdldFtcIndpZHRoXCJdO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5vcmlnaW5hbFdpZHRoID4gMTI4MCkge1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21XaWR0aCA9IDEyODA7XHJcbiAgICAgICAgICB0aGlzLmN1c3RvbUhlaWdodCA9IE1hdGgucm91bmQoKDEyODAgKiB0aGlzLm9yaWdpbmFsSGVpZ2h0KSAvIHRoaXMub3JpZ2luYWxXaWR0aCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gcnMuY3VycmVudFRhcmdldFtcImhlaWdodFwiXTtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tV2lkdGggPSBycy5jdXJyZW50VGFyZ2V0W1wid2lkdGhcIl07XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG4gICAgfTtcclxuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGltZyk7XHJcbiAgfVxyXG5cclxuICByZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKCkge1xyXG4gICAgdGhpcy5jdXN0b21XaWR0aCA9IHRoaXMub3JpZ2luYWxXaWR0aDtcclxuICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gdGhpcy5vcmlnaW5hbEhlaWdodDtcclxuICAgIHRoaXMuY2FudmFzUm90YXRpb24gPSAwO1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7fTtcclxuICB9XHJcblxyXG4gIG9uRGltZW5zaW9uc0NoYW5nZShkaW1lbnNpb246IHN0cmluZykge1xyXG4gICAgaWYgKGRpbWVuc2lvbiA9PSBcIkhcIikge1xyXG4gICAgICB0aGlzLmN1c3RvbVdpZHRoID0gTWF0aC5yb3VuZCgodGhpcy5jdXN0b21IZWlnaHQgKiB0aGlzLm9yaWdpbmFsV2lkdGgpIC8gdGhpcy5vcmlnaW5hbEhlaWdodCk7XHJcbiAgICB9IGVsc2UgaWYgKGRpbWVuc2lvbiA9PSBcIldcIikge1xyXG4gICAgICB0aGlzLmN1c3RvbUhlaWdodCA9IE1hdGgucm91bmQoKHRoaXMuY3VzdG9tV2lkdGggKiB0aGlzLm9yaWdpbmFsSGVpZ2h0KSAvIHRoaXMub3JpZ2luYWxXaWR0aCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbWFnZUNyb3BwZWQoZXZlbnQ6IEltYWdlQ3JvcHBlZEV2ZW50KSB7XHJcbiAgICB0aGlzLmNyb3BwZWRJbWFnZSA9IGV2ZW50LmJhc2U2NDtcclxuICAgIHRoaXMuZ2V0Q3JvcHBlZEFuZFVwbG9hZCh0aGlzLmNyb3BwZWRJbWFnZSwgdGhpcy5uZXdBdHRhY2htZW50KTtcclxuICB9XHJcblxyXG4gIGdldENyb3BwZWRBbmRVcGxvYWQoZmlsZSwgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIHZhciBzZWxmID0gdGhpcztcclxuXHJcbiAgICB2YXIgZmlsZTogYW55ID0gYmFzZTY0VG9GaWxlKGZpbGUpO1xyXG5cclxuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmNvbXByZXNzaW9uT3B0aW9ucztcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbXByaW1lIGwnaW1tYWdpbmUgcGFzc2FuZG8gY29tZSBwYXJhbWV0cmkgbGUgb3B0aW9ucyBjcmVhdGUgbmVsbCdvZ2dldHRvIHNvcHJhLCBlIGlsIGZpbGUgZGFsIHJlYWRlciBwcmluY2lwYWxlXHJcbiAgICAgKi9cclxuICAgIGltYWdlQ29tcHJlc3Npb24oZmlsZSwgb3B0aW9ucykudGhlbigoZmlsZUNvbXByZXNzZWQpID0+IHtcclxuICAgICAgbGV0IGZpbGVSZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG5cclxuICAgICAgLy9GYWNjaW8gbGEgcHVzaCBkaSBvZ25pIGZpbGUgYWxsJ2ludGVybm8gZGVsbCdhcnJheSBkaSBmaWxlIGRlbGwnaXRlbSBkYSBtYW5kYXJlIGFsIHNlcnZlclxyXG4gICAgICBmaWxlUmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBsZXQgcmVzdWx0UmVhZGVyID0gPHN0cmluZz5maWxlUmVhZGVyLnJlc3VsdDtcclxuICAgICAgICB2YXIgbWFya2VyID0gXCI7YmFzZTY0LFwiO1xyXG4gICAgICAgIG5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSByZXN1bHRSZWFkZXIuc3Vic3RyaW5nKHJlc3VsdFJlYWRlci5pbmRleE9mKG1hcmtlcikgKyBtYXJrZXIubGVuZ3RoKTtcclxuICAgICAgICBzZWxmLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgICAgICBpZiAoc2VsZi5uZXdBdHRhY2htZW50Rm9ybSkge1xyXG4gICAgICAgICAgc2VsZi5uZXdBdHRhY2htZW50Rm9ybS5lbmFibGUoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICBmaWxlUmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZUNvbXByZXNzZWQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyBjb25maXJtQ3JvcCgpIHtcclxuICAvLyAgIHRoaXMuaW1hZ2VDcm9wcGVyLmNyb3AoKTtcclxuICAvLyAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgLy8gICB0aGlzLnJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKTtcclxuICAvLyB9XHJcblxyXG4gIHJvdGF0ZUxlZnQoKSB7XHJcbiAgICB0aGlzLmNhbnZhc1JvdGF0aW9uLS07XHJcbiAgICB0aGlzLmZsaXBBZnRlclJvdGF0ZSgpO1xyXG4gIH1cclxuXHJcbiAgcm90YXRlUmlnaHQoKSB7XHJcbiAgICB0aGlzLmNhbnZhc1JvdGF0aW9uKys7XHJcbiAgICB0aGlzLmZsaXBBZnRlclJvdGF0ZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmbGlwQWZ0ZXJSb3RhdGUoKSB7XHJcbiAgICBjb25zdCBmbGlwcGVkSCA9IHRoaXMudHJhbnNmb3JtLmZsaXBIO1xyXG4gICAgY29uc3QgZmxpcHBlZFYgPSB0aGlzLnRyYW5zZm9ybS5mbGlwVjtcclxuICAgIHRoaXMudHJhbnNmb3JtID0ge1xyXG4gICAgICAuLi50aGlzLnRyYW5zZm9ybSxcclxuICAgICAgZmxpcEg6IGZsaXBwZWRWLFxyXG4gICAgICBmbGlwVjogZmxpcHBlZEhcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBmbGlwSG9yaXpvbnRhbCgpIHtcclxuICAgIHRoaXMudHJhbnNmb3JtID0ge1xyXG4gICAgICAuLi50aGlzLnRyYW5zZm9ybSxcclxuICAgICAgZmxpcEg6ICF0aGlzLnRyYW5zZm9ybS5mbGlwSFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGZsaXBWZXJ0aWNhbCgpIHtcclxuICAgIHRoaXMudHJhbnNmb3JtID0ge1xyXG4gICAgICAuLi50aGlzLnRyYW5zZm9ybSxcclxuICAgICAgZmxpcFY6ICF0aGlzLnRyYW5zZm9ybS5mbGlwVlxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvKipcclxuICAgKiBBbm51bGxhIGxhIHNlbGV6aW9uZSBkZWwgZmlsZSwgc3Z1b3RhbmRvIGwnaW5wdXQgZSByZXNldHRhbmRvIHR1dHRlIGxlIHByb3ByaWV0w6AgZGVsbCdJQXR0YWNobWVudERUT1xyXG4gICAqL1xyXG4gIGFib3J0RmlsZSgpIHtcclxuICAgIGlmICh0aGlzLmltYWdlSW5wdXQpIHRoaXMuaW1hZ2VJbnB1dC5uYXRpdmVFbGVtZW50LnZhbHVlID0gXCJcIjtcclxuXHJcbiAgICB0aGlzLnNlbGVjdGVkRmlsZSA9IG51bGw7XHJcbiAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSBudWxsO1xyXG4gICAgdGhpcy5zaG93Q3JvcEltYWdlID0gZmFsc2U7XHJcblxyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LklzSW1hZ2UgPSBmYWxzZTtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IG51bGw7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZU5hbWUgPSBudWxsO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVFeHRlbnNpb24gPSBudWxsO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IG51bGw7XHJcblxyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gbnVsbDtcclxuICAgIHRoaXMuY3VzdG9tV2lkdGggPSBudWxsO1xyXG4gICAgdGhpcy5vcmlnaW5hbEhlaWdodCA9IG51bGw7XHJcbiAgICB0aGlzLm9yaWdpbmFsV2lkdGggPSBudWxsO1xyXG5cclxuICAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgICB0aGlzLnJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKTtcclxuICB9XHJcblxyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvLyBWaWVuZSBjcmVhdG8gdW4nYXJyYXkgb2JzZXJ2YWJsZXMgcGVyIG1lbW9yaXp6YXJlIHR1dHRpIGdsaSBvYnNlcnZhYmxlIGNyZWF0aSBkYWxsZSBjaGlhbWF0ZSBhIGZpbGVFbnRyeS5maWxlKCkuXHJcbiAgLy8gRG9wbyBjaGUgdHV0dGkgZ2xpIG9ic2VydmFibGVzIHNvbm8gc3RhdGkgY29tcGxldGF0aSwgdmllbmUgdXRpbGl6emF0byBpbCBtZXRvZG8gc3Vic2NyaWJlKCkgcGVyIGVzZWd1aXJlIGxhIGZ1bnppb25lIG9uRmlsZUFkZGVkKCkuXHJcbiAgZmlsZURyb3BwZWQoZmlsZXMpIHtcclxuICAgIGxldCBmaWxlc0Ryb3BwZWQgPSBbXTtcclxuXHJcbiAgICBjb25zdCBvYnNlcnZhYmxlczogT2JzZXJ2YWJsZTxhbnk+W10gPSBbXTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgaWYgKGZpbGVzW2ldLmZpbGVFbnRyeS5pc0ZpbGUpIHtcclxuICAgICAgICBjb25zdCBmaWxlRW50cnkgPSBmaWxlc1tpXS5maWxlRW50cnkgYXMgRmlsZVN5c3RlbUZpbGVFbnRyeTtcclxuICAgICAgICBjb25zdCBvYnNlcnZhYmxlID0gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XHJcbiAgICAgICAgICBmaWxlRW50cnkuZmlsZSgoZmlsZTogRmlsZSkgPT4ge1xyXG4gICAgICAgICAgICBmaWxlc0Ryb3BwZWQucHVzaChmaWxlKTtcclxuXHJcbiAgICAgICAgICAgIG9ic2VydmVyLm5leHQoKTtcclxuICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIG9ic2VydmFibGVzLnB1c2gob2JzZXJ2YWJsZSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgY29uc3QgZmlsZUVudHJ5ID0gZmlsZXNbaV0uZmlsZUVudHJ5IGFzIEZpbGVTeXN0ZW1EaXJlY3RvcnlFbnRyeTtcclxuICAgICAgICBjb25zb2xlLmxvZyhmaWxlc1tpXS5yZWxhdGl2ZVBhdGgsIGZpbGVFbnRyeSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmcm9tKG9ic2VydmFibGVzKVxyXG4gICAgICAucGlwZShjb25jYXRNYXAoKG9ic2VydmFibGUpID0+IG9ic2VydmFibGUpKVxyXG4gICAgICAuc3Vic2NyaWJlKHtcclxuICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5vbkZpbGVBZGRlZChmaWxlc0Ryb3BwZWQsIHRydWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyBTZSBpbCBjYXJpY2FtZW50byBkZWwgZmlsZSBkcm9wYm94IHZhIGEgYnVvbiBmaW5lLCBsYSBmdW56aW9uZSBkaSBjYWxsYmFjayByZXN0aXR1aXNjZSB1biBhcnJheSBkaSBvZ2dldHRpLlxyXG4gIC8vIFZpZW5lIHBvaSBmYXR0YSB1bmEgWE1MSHR0cFJlcXVlc3QgY29uIHJlc3BvbnNlVHlwZSAnYmxvYicgcGVyIGNvbnZlcnRpcmUgaWwgcHJpbW8gZWxlbWVudG8gZGVsbGEgcmVzcG9uc2UgaW4gdW4gQmxvYi5cclxuICBjaG9vc2VEcm9wYm94RmlsZSgpIHtcclxuICAgIHZhciBvcHRpb25zID0ge1xyXG4gICAgICBzdWNjZXNzOiAoZmlsZXM6IGFueVtdKSA9PiB7XHJcbiAgICAgICAgY29uc3QgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XHJcbiAgICAgICAgeGhyLm9wZW4oXCJHRVRcIiwgZmlsZXNbMF0ubGluayk7XHJcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoXCJBdXRob3JpemF0aW9uXCIsIGBCZWFyZXIgJHtBdHRhY2htZW50SGVscGVyU2VydmljZS5kcm9wYm94Q3JlZGVudGlhbHMuYWNjZXNzVG9rZW59YCk7XHJcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9IFwiYmxvYlwiO1xyXG5cclxuICAgICAgICB4aHIub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICAgICAgY29uc3QgYmxvYiA9IHhoci5yZXNwb25zZTtcclxuICAgICAgICAgIGNvbnN0IGZpbGUgPSBuZXcgRmlsZShbYmxvYl0sIGZpbGVzWzBdLm5hbWUsIHsgdHlwZTogYmxvYi50eXBlIH0pO1xyXG4gICAgICAgICAgbGV0IGZpbGVzQWRkZWQgPSBbZmlsZV07XHJcbiAgICAgICAgICB0aGlzLm9uRmlsZUFkZGVkKGZpbGVzQWRkZWQsIHRydWUpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHhoci5zZW5kKCk7XHJcbiAgICAgIH0sXHJcbiAgICAgIGxpbmtUeXBlOiBcImRpcmVjdFwiLFxyXG4gICAgICBtdWx0aXNlbGVjdDogZmFsc2UsXHJcbiAgICAgIGV4dGVuc2lvbnM6IFtcIi5qcGdcIiwgXCIucG5nXCIsIFwiLnBkZlwiLCBcIi5kb2NcIiwgXCIuZG9jeFwiLCBcIi50eHRcIl1cclxuICAgIH07XHJcbiAgICBEcm9wYm94LmNob29zZShvcHRpb25zKTtcclxuICB9XHJcblxyXG4gIC8vIFdvcmthcm91bmQgZHJvcHpvbmU6IGRpc2FiaWxpdG8gaWwgY2xpY2sgZGVnbGkgZWxlbWVudGkgaW5jbHVzaSBuZWxsYSBkcm9wem9uZSBwZXIgZXZpdGFyZSBkaSBjbGljY2FyZSBkdWUgdm9sdGVcclxuICBvblNlbGVjdEZpbGUoZXZlbnQsIGZpbGVJbnB1dCkge1xyXG4gICAgaWYgKFxyXG4gICAgICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxCdXR0b25FbGVtZW50KS50YWdOYW1lID09PSBcIkJVVFRPTlwiIHx8XHJcbiAgICAgIChldmVudC50YXJnZXQgYXMgSFRNTEJ1dHRvbkVsZW1lbnQpLnRhZ05hbWUgPT09IFwiSU5QVVRcIiB8fFxyXG4gICAgICB0aGlzLmFkZGluZ0xpbmtNb2RlID09IHRydWVcclxuICAgICkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBmaWxlSW5wdXQuY2xpY2soKTtcclxuICB9XHJcblxyXG4gIC8vIE1ldG9kbyBwZXIgdmlzdWFsaXp6YXJlIGxhIGZvcm0gZGkgYWdnaXVudGEgZGkgdW4gbGlua1xyXG4gIHN3aXRjaFRvQWRkaW5nTGlua01vZGUoKSB7XHJcbiAgICB0aGlzLmFkZGluZ0xpbmtNb2RlID0gdHJ1ZTtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudCA9IHt9IGFzIElBdHRhY2htZW50RFRPO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LklzSW1hZ2UgPSBmYWxzZTtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9IHRoaXMuYXR0YWNobWVudFR5cGUuTElOSztcclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5wdXNoKHRoaXMubmV3QXR0YWNobWVudCk7XHJcblxyXG4gICAgdGhpcy5jcmVhdGVBdHRhY2htZW50Rm9ybSgpO1xyXG4gIH1cclxufVxyXG4iLCI8IS0tIFNlIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBzaW5nb2xhIG1vc3RyYSBpbCBwdWxzYW50ZSBkaSBjYXJpY2FtZW50byBkaSB1biBzaW5nb2xvIGZpbGUgLS0+XHJcbjxkaXYgKm5nSWY9XCJtdWx0aXBsZUF0dGFjaG1lbnQgIT0gdHJ1ZVwiPlxyXG4gIDxkaXYgKm5nSWY9XCIhc2luZ2xlQXR0YWNobWVudERyYWdBbmREcm9wXCI+XHJcbiAgICA8IS0tIFRlbXBsYXRlIGRlbCBidXR0b24gcGVyIGwnYWdnaXVudGEgZGkgdW4gYWxsZWdhdG8gLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwiIWFkZGluZ0xpbmtNb2RlXCIgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYWRkQXR0YWNobWVudEJ1dHRvblwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8IS0tIFRlbXBsYXRlIGRlbGxhIGZvcm0gcGVyIGwnYWdnaXVudGEgZGkgdW4gbGluayAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCJhZGRpbmdMaW5rTW9kZVwiIGNsYXNzPVwidGV4dC1jZW50ZXJcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImFkZGluZ0xpbmtUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiAqbmdJZj1cInNpbmdsZUF0dGFjaG1lbnREcmFnQW5kRHJvcFwiPlxyXG4gICAgPGlucHV0XHJcbiAgICAgICNmaWxlSW5wdXRcclxuICAgICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgICAgaWQ9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgICBuYW1lPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgICAgdHlwZT1cImZpbGVcIlxyXG4gICAgICAoY2hhbmdlKT1cIm9uRmlsZUFkZGVkKCRldmVudClcIlxyXG4gICAgICBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCJcclxuICAgICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICAgIDxuZ3gtZmlsZS1kcm9wXHJcbiAgICAgIChvbkZpbGVEcm9wKT1cImZpbGVEcm9wcGVkKCRldmVudClcIlxyXG4gICAgICAoY2xpY2spPVwib25TZWxlY3RGaWxlKCRldmVudCwgZmlsZUlucHV0KVwiXHJcbiAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgYWxsb3dlZFR5cGVzICYmXHJcbiAgICAgICAgYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDEpICYmXHJcbiAgICAgICAgKCFhdHRhY2htZW50c0xpc3QgfHwgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8IChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgICAgXCI+XHJcbiAgICAgIDxuZy10ZW1wbGF0ZSBuZ3gtZmlsZS1kcm9wLWNvbnRlbnQtdG1wICpuZ0lmPVwiIWFkZGluZ0xpbmtNb2RlXCI+XHJcbiAgICAgICAgPGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1jbG91ZC11cGxvYWQtYWx0IGZhLTN4IG10LTNcIj48L2k+XHJcbiAgICAgICAgVHJhc2NpbmEgaSBmaWxlIHF1aVxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXAgbXQtMVwiIHJvbGU9XCJncm91cFwiPlxyXG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IGJvcmRlci1lbmRcIiAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIj5TY2VnbGkgdW4gZmlsZTwvYnV0dG9uPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiIHJvbGU9XCJncm91cFwiPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IGJvcmRlci1zdGFydCBkcm9wZG93bi10b2dnbGVcIlxyXG4gICAgICAgICAgICAgIFttYXRNZW51VHJpZ2dlckZvcl09XCJhdHRhY2htZW50VHlwZU1lbnVcIj48L2J1dHRvbj5cclxuICAgICAgICAgICAgPG1hdC1tZW51ICNhdHRhY2htZW50VHlwZU1lbnU9XCJtYXRNZW51XCI+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImZpbGVJbnB1dC5jbGljaygpXCJcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWZpbGUtYnRuXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1maWxlXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkZpbGU8L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiXHJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1saW5rLWJ0blwiPlxyXG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgICAgICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5MaW5rPC9zcGFuPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpXCJcclxuICAgICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCJcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkRyb3Bib3g8L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvbWF0LW1lbnU+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgICAgPG5nLXRlbXBsYXRlIG5neC1maWxlLWRyb3AtY29udGVudC10bXAgKm5nSWY9XCJhZGRpbmdMaW5rTW9kZVwiPlxyXG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhZGRpbmdMaW5rVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgIDwvbmd4LWZpbGUtZHJvcD5cclxuICA8L2Rpdj5cclxuICA8ZGl2IGNsYXNzPVwidGV4dC1jZW50ZXJcIj5cclxuICAgIDxidXR0b25cclxuICAgICAgY2xhc3M9XCJtYi0yIG1lLTIgZXFwLWF0dGFjaG1lbnRzLWRvd25sb2FkLWJ0blwiXHJcbiAgICAgIChjbGljayk9XCJ2aWV3QXR0YWNobWVudChhdHRhY2htZW50c0xpc3RbMF0pXCJcclxuICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgICpuZ0lmPVwiYXR0YWNobWVudHNMaXN0ICYmIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmIGF0dGFjaG1lbnRzTGlzdFswXVwiXHJcbiAgICAgIGNvbG9yPVwicHJpbWFyeVwiPlxyXG4gICAgICA8bWF0LWljb24gKm5nSWY9XCJhdHRhY2htZW50c0xpc3RbMF0uQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRVwiPmRvd25sb2FkPC9tYXQtaWNvbj5cclxuICAgICAgPG1hdC1pY29uICpuZ0lmPVwiYXR0YWNobWVudHNMaXN0WzBdLkF0dGFjaG1lbnRUeXBlICE9IEF0dGFjaG1lbnRUeXBlLkZJTEVcIj5vcGVuX2luX25ldzwvbWF0LWljb24+XHJcbiAgICAgIHt7IGF0dGFjaG1lbnRzTGlzdFswXS5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFID8gZG93bmxvYWRMYWJlbCA6IG9wZW5MaW5rTGFiZWwgfX1cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICBjbGFzcz1cIm1iLTIgbWUtMiBlcXAtYXR0YWNobWVudHMtcHJldmlldy1idG5cIlxyXG4gICAgICAoY2xpY2spPVwib3BlblByZXZpZXdEaWFsb2coYXR0YWNobWVudHNMaXN0WzBdKVwiXHJcbiAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAqbmdJZj1cIlxyXG4gICAgICAgIHNob3dQcmV2aWV3ICYmXHJcbiAgICAgICAgYXR0YWNobWVudHNMaXN0ICYmXHJcbiAgICAgICAgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiZcclxuICAgICAgICBhdHRhY2htZW50c0xpc3RbMF0gJiZcclxuICAgICAgICAoIWF0dGFjaG1lbnRzTGlzdFswXS5GaWxlQ29udGVudFR5cGUgfHxcclxuICAgICAgICAgICghYXR0YWNobWVudHNMaXN0WzBdLkZpbGVDb250ZW50VHlwZS5zdGFydHNXaXRoKCd2aWRlbycpICYmXHJcbiAgICAgICAgICAgICFhdHRhY2htZW50c0xpc3RbMF0uRmlsZUNvbnRlbnRUeXBlLnN0YXJ0c1dpdGgoJ2F1ZGlvJykpKSAmJlxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdFswXS5Jc0ltYWdlID09IHRydWVcclxuICAgICAgXCI+XHJcbiAgICAgIDxtYXQtaWNvbj52aXNpYmlsaXR5PC9tYXQtaWNvbj4ge3sgcHJldmlld0xhYmVsIH19XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIDxidXR0b25cclxuICAgICAgY2xhc3M9XCJtYi0yIGVxcC1hdHRhY2htZW50cy1kZWxldGUtYnRuXCJcclxuICAgICAgKGNsaWNrKT1cImRlbGV0ZUF0dGFjaG1lbnQoYXR0YWNobWVudHNMaXN0WzBdKVwiXHJcbiAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgICAqbmdJZj1cImF0dGFjaG1lbnRzTGlzdCAmJiBhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiBhdHRhY2htZW50c0xpc3RbMF1cIlxyXG4gICAgICBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiPlxyXG4gICAgICA8bWF0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj4ge3sgZGVsZXRlTGFiZWwgfX1cclxuICAgIDwvYnV0dG9uPlxyXG4gIDwvZGl2PlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwicm93XCJcclxuICAgIHN0eWxlPVwibWFyZ2luLXRvcDogMTBweFwiXHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICBhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJlxyXG4gICAgICBhdHRhY2htZW50c0xpc3RbMF0gJiZcclxuICAgICAgYXR0YWNobWVudHNMaXN0WzBdLkZpbGVEYXRhQmFzZTY0ICYmXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdFswXS5Jc0ltYWdlID09IHRydWVcclxuICAgIFwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMiBkLWZsZXgganVzdGlmeS1jb250ZW50LWNlbnRlclwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwic2luZ2xlLWF0dGFjaG1lbnQtaW5saW5lLXByZXZpZXctY29udGFpbmVyXCI+XHJcbiAgICAgICAgPGltZyBzcmM9XCJkYXRhOmltYWdlL3BuZztiYXNlNjQse3sgYXR0YWNobWVudHNMaXN0WzBdLkZpbGVEYXRhQmFzZTY0IH19XCIgLz5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8ZGl2IGNsYXNzPVwicm93XCIgKm5nSWY9XCJhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiBhdHRhY2htZW50c0xpc3RbMF0gJiYgYXR0YWNobWVudHNMaXN0WzBdLklzSW1hZ2UgIT0gdHJ1ZVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMlwiPlxyXG4gICAgICA8bWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgPG1hdC1sYWJlbD57eyBmaWxlTmFtZUxhYmVsIH19PC9tYXQtbGFiZWw+XHJcbiAgICAgICAgPGlucHV0IHJlYWRvbmx5IG1hdElucHV0IFsobmdNb2RlbCldPVwiYXR0YWNobWVudHNMaXN0WzBdLkZpbGVOYW1lXCIgLz5cclxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxuXHJcbjxkaXYgKm5nSWY9XCJtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZVwiPlxyXG4gIDxpbnB1dFxyXG4gICAgI2ZpbGVJbnB1dFxyXG4gICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgIGlkPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgdHlwZT1cImZpbGVcIlxyXG4gICAgKGNoYW5nZSk9XCJvbkZpbGVBZGRlZCgkZXZlbnQpXCJcclxuICAgIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxyXG4gICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICA8bmd4LWZpbGUtZHJvcCAob25GaWxlRHJvcCk9XCJmaWxlRHJvcHBlZCgkZXZlbnQpXCIgKGNsaWNrKT1cIm9uU2VsZWN0RmlsZSgkZXZlbnQsIGZpbGVJbnB1dClcIj5cclxuICAgIDxuZy10ZW1wbGF0ZSBuZ3gtZmlsZS1kcm9wLWNvbnRlbnQtdG1wICpuZ0lmPVwiIWFkZGluZ0xpbmtNb2RlXCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmEtc29saWQgZmEtY2xvdWQtdXBsb2FkLWFsdCBmYS0zeCBtdC0zXCI+PC9pPlxyXG4gICAgICBUcmFzY2luYSBpIGZpbGUgcXVpXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXAgbXQtMVwiIHJvbGU9XCJncm91cFwiPlxyXG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1saWdodCBib3JkZXItZW5kXCIgKGNsaWNrKT1cImZpbGVJbnB1dC5jbGljaygpXCI+U2NlZ2xpIHVuIGZpbGU8L2J1dHRvbj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHQgYm9yZGVyLXN0YXJ0IGRyb3Bkb3duLXRvZ2dsZVwiXHJcbiAgICAgICAgICAgIFttYXRNZW51VHJpZ2dlckZvcl09XCJhdHRhY2htZW50VHlwZU1lbnVcIj48L2J1dHRvbj5cclxuICAgICAgICAgIDxtYXQtbWVudSAjYXR0YWNobWVudFR5cGVNZW51PVwibWF0TWVudVwiPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgICAgICAgICAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWZpbGUtYnRuXCI+XHJcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZmlsZVwiPjwvaT5cclxuICAgICAgICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RmlsZTwvc3Bhbj5cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygyKVwiXHJcbiAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJzd2l0Y2hUb0FkZGluZ0xpbmtNb2RlKClcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+TGluazwvc3Bhbj5cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKVwiXHJcbiAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1saW5rLWJ0blwiPlxyXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEtYnJhbmRzIGZhLWRyb3Bib3hcIj48L2k+XHJcbiAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkRyb3Bib3g8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPC9tYXQtbWVudT5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgPG5nLXRlbXBsYXRlIG5neC1maWxlLWRyb3AtY29udGVudC10bXAgKm5nSWY9XCJhZGRpbmdMaW5rTW9kZVwiPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYWRkaW5nTGlua1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XHJcbiAgICA8L25nLXRlbXBsYXRlPlxyXG4gIDwvbmd4LWZpbGUtZHJvcD5cclxuICA8ZGl2IGNsYXNzPVwibXQtMlwiPlxyXG4gICAgPGVxcC10YWJsZVxyXG4gICAgICAjYXR0YWNobWVudFRhYmxlXHJcbiAgICAgIFtjcmVhdGVNYXRDYXJkXT1cImZhbHNlXCJcclxuICAgICAgI3RhYmxlXHJcbiAgICAgIFt0YWJsZUNvbHVtbkZpZWxkc109XCJhdHRhY2htZW50c0NvbHVtbnNcIlxyXG4gICAgICBbaXNNdWx0aUxhbmd1YWdlXT1cImlzRXFwVGFibGVNdWx0aUxhbmd1YWdlXCJcclxuICAgICAgW2RhdGFdPVwiYXR0YWNobWVudHNMaXN0XCJcclxuICAgICAgW3BhZ2luYXRvclZpc2libGVdPVwidGFibGVQYWdpbmF0b3JWaXNpYmxlXCJcclxuICAgICAgW21hdFBhZ2luYXRvclNpemVdPVwidGFibGVQYWdpbmF0b3JTaXplXCJcclxuICAgICAgW2VtcHR5VGFibGVNZXNzYWdlXT1cImVtcHR5VGFibGVNZXNzYWdlXCJcclxuICAgICAgW3NlYXJjaFRleHRdPVwiZXFwVGFibGVTZWFyY2hUZXh0XCJcclxuICAgICAgW2lzVGFibGVTZWFyY2hlYWJsZV09XCJpc1RhYmxlU2VhcmNoZWFibGVcIj5cclxuICAgIDwvZXFwLXRhYmxlPlxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxuXHJcbjxuZy10ZW1wbGF0ZSAjZGlhbG9nQ3JvcEltYWdlPlxyXG4gIDwhLS0gUmljaGlhbWEgaWwgdGVtcGxhdGUgcGVyIGxlIGZ1bnppb25hbGl0w6AgZGVsIENST1BQSUUgLS0+XHJcbiAgPGRpdiBzdHlsZT1cIm92ZXJmbG93LXg6IGhpZGRlblwiIFtuZ0NsYXNzXT1cImNyb3BEaWFsb2dDbGFzc1wiPlxyXG4gICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjcm9wcGllVGVtcGxhdGVcIlxyXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyBmb3JtOiBuZXdBdHRhY2htZW50Rm9ybSB9XCJcclxuICAgICAgKm5nSWY9XCJzaG93Q3JvcEltYWdlID09IHRydWVcIj48L25nLWNvbnRhaW5lcj5cclxuICA8L2Rpdj5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjxuZy10ZW1wbGF0ZSAjaW5saW5lUHJldmlld1RlbXBsYXRlIGxldC1yb3c9XCJyb3dcIj5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImlubGluZS1wcmV2aWV3LWNvbnRhaW5lclwiXHJcbiAgICAqbmdJZj1cInJvdy5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5MSU5LICYmIHJvdy5Jc0ltYWdlXCJcclxuICAgIChjbGljayk9XCJvcGVuUHJldmlld0RpYWxvZyhyb3cpXCI+XHJcbiAgICA8aW1nIHNyYz1cImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCx7eyByb3cuRmlsZVRodW1ibmFpbEJhc2U2NCA/IHJvdy5GaWxlVGh1bWJuYWlsQmFzZTY0IDogcm93LkZpbGVEYXRhQmFzZTY0IH19XCIgLz5cclxuICA8L2Rpdj5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImlubGluZS1wcmV2aWV3LWNvbnRhaW5lclwiXHJcbiAgICAqbmdJZj1cInJvdy5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5MSU5LICYmICFyb3cuSXNJbWFnZVwiXHJcbiAgICAoY2xpY2spPVwib3BlblByZXZpZXdEaWFsb2cocm93KVwiPlxyXG4gICAgPGkgW25nQ2xhc3NdPVwiZ2V0QXR0YWNobWVudEljb24ocm93KVwiPjwvaT5cclxuICA8L2Rpdj5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjxuZy10ZW1wbGF0ZSAjZGlhbG9nUHJldmlldz5cclxuICA8bWF0LWNhcmQgY2xhc3M9XCJleGFtcGxlLWNhcmRcIiAqbmdJZj1cInNlbGVjdGVkQXR0YWNobWVudFwiPlxyXG4gICAgPG1hdC1jYXJkLWNvbnRlbnQ+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLXRpdGxlLXN0YW5kYXJkXCI+XHJcbiAgICAgICAgICB7eyBwcmV2aWV3TGFiZWwgfX0ge3sgc2VsZWN0ZWRBdHRhY2htZW50Py5BdHRhY2htZW50VHlwZSA9PSBhdHRhY2htZW50VHlwZS5GSUxFID8gXCJGaWxlXCIgOiBcIkxpbmtcIiB9fVxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgY2xhc3M9XCJidG4tY2xvc2UgY2xvc2VCdXR0b25cIlxyXG4gICAgICAgICAgICBtYXQtZGlhbG9nLWNsb3NlXHJcbiAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RlZEF0dGFjaG1lbnQgPSBudWxsXCI+PC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicm93IG10LTJcIj5cclxuICAgICAgICA8IS0tIEFOVEVQUklNQSBJTU1BR0lORSAtLT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIHRleHQtY2VudGVyIHByZXZpZXctY29udGFpbmVyXCIgKm5nSWY9XCJzZWxlY3RlZEF0dGFjaG1lbnQuSXNJbWFnZVwiPlxyXG4gICAgICAgICAgPGltZ1xyXG4gICAgICAgICAgICBjbGFzcz1cImltYWdlLXByZXZpZXdcIlxyXG4gICAgICAgICAgICBzcmM9XCJkYXRhOmltYWdlL3BuZztiYXNlNjQse3tcclxuICAgICAgICAgICAgICBzZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjRcclxuICAgICAgICAgICAgICAgID8gc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0XHJcbiAgICAgICAgICAgICAgICA6IHNlbGVjdGVkQXR0YWNobWVudC5GaWxlVGh1bWJuYWlsQmFzZTY0XHJcbiAgICAgICAgICAgIH19XCIgLz5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPCEtLSBBTlRFUFJJTUEgTElOSyAtLT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIHByZXZpZXctY29udGFpbmVyXCIgKm5nSWY9XCIhc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2VcIj5cclxuICAgICAgICAgIDxpZnJhbWVcclxuICAgICAgICAgICAgY2xhc3M9XCJsaW5rLXByZXZpZXdcIlxyXG4gICAgICAgICAgICBbc3JjXT1cInNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsXCJcclxuICAgICAgICAgICAgW3RpdGxlXT1cInNlbGVjdGVkQXR0YWNobWVudC5GaWxlTmFtZVwiPjwvaWZyYW1lPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cInJvdyBtdC0zXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMiB0ZXh0LWNlbnRlclwiPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICBtYXQtbWluaS1mYWJcclxuICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkRvd25sb2FkXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cInZpZXdBdHRhY2htZW50KHNlbGVjdGVkQXR0YWNobWVudClcIlxyXG4gICAgICAgICAgICAqbmdJZj1cInNlbGVjdGVkQXR0YWNobWVudC5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5MSU5LXCI+XHJcbiAgICAgICAgICAgIDxtYXQtaWNvbj5kb3dubG9hZDwvbWF0LWljb24+XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XHJcbiAgPC9tYXQtY2FyZD5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjwhLS0gVEVNUExBVEUgUEVSIElMIFBVTFNBTlRFIERJIEFHR0lVTlRBIE5VT1ZPIEFMTEVHQVRPIC0tPlxyXG48bmctdGVtcGxhdGUgI2FkZEF0dGFjaG1lbnRCdXR0b24+XHJcbiAgPCEtLVxyXG4gICAgICAgIFB1bHNhbnRpIHBlciBsJ2FnZ2l1bnRhIGRpIHVuIGZpbGUgbyB1biBsaW5rLiBOZSB2aWVuZSB2aXN1YWxpenphdG8gdW5vIHNlOlxyXG4gICAgICAgIC0gZ2xpIGFsbG93ZWRUeXBlcyBzb25vIHN0YXRpIHNwZWNpZmljYXRpLCBuZWxsJ2FycmF5IG5lIMOoIHByZXNlbnRlIHVubyBzb2xvLCBxdWVsbG8gaW5zZXJpdG8gw6ggQXR0YWNobWVudFR5cGUuRklMRSAobyBBdHRhY2htZW50VHlwZS5MSU5LKVxyXG4gICAgICAgIGUgc29ubyBuZWxsYSBnZXN0aW9uZSBkaSBwacO5IGFsbGVnYXRpIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSlcclxuICAgICAgICBPUFBVUkVcclxuICAgICAgICAtIGdsaSBhbGxvd2VkVHlwZXMgc29ubyBzdGF0aSBzcGVjaWZpY2F0aSwgbmVsbCdhcnJheSBuZSDDqCBwcmVzZW50ZSB1bm8gc29sbywgcXVlbGxvIGluc2VyaXRvIMOoIEF0dGFjaG1lbnRUeXBlLkZJTEUgKG8gQXR0YWNobWVudFR5cGUuTElOSylcclxuICAgICAgICBlIHNvbm8gbmVsbGEgZ2VzdGlvbmUgZGkgdW4gc2luZ29sbyBhbGxlZ2F0byAobXVsdGlwbGVBdHRhY2htZW50ID09IHRydWUpIGUgbm9uIG5lIMOoIGFuY29yYSBzdGF0byBzZWxlemlvbmF0byB1bm8gKG92dmVybyBhdHRhY2htZW50c0xpc3Qgbm9uIGVzaXN0ZSBvIG5vbiBoYSBlbGVtZW50aSlcclxuICAgIC0tPlxyXG4gIDxpbnB1dFxyXG4gICAgI2ZpbGVJbnB1dFxyXG4gICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgIGlkPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgdHlwZT1cImZpbGVcIlxyXG4gICAgKGNoYW5nZSk9XCJvbkZpbGVBZGRlZCgkZXZlbnQpXCJcclxuICAgIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxyXG4gICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICA8YnV0dG9uXHJcbiAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBtYi00IG1lLTUgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIlxyXG4gICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICpuZ0lmPVwiXHJcbiAgICAgIGFsbG93ZWRUeXBlcyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMubGVuZ3RoID09IDEgJiZcclxuICAgICAgKG11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlIHx8XHJcbiAgICAgICAgIWF0dGFjaG1lbnRzTGlzdCB8fFxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCB8fFxyXG4gICAgICAgIChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgIFwiXHJcbiAgICAoY2xpY2spPVwiYWRkRmlsZShhbGxvd2VkVHlwZXNbMF0sIGZpbGVJbnB1dClcIlxyXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIj5cclxuICAgIDwhLS0gUGVyIGwnYWdnaXVudGEgZGVpIGZpbGUgbW9zdHJvIHVuJ2ljb25hIGRpdmVyc2EgZGFsbCdhZ2dpdW50YSBkZWkgbGluayAtLT5cclxuICAgIDxtYXQtaWNvbiAqbmdJZj1cImFsbG93ZWRUeXBlc1swXSA9PSAxXCI+Y2xvdWRfdXBsb2FkPC9tYXQtaWNvbj5cclxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxpbmtcIiAqbmdJZj1cImFsbG93ZWRUeXBlc1swXSA9PSAyXCI+PC9pPlxyXG4gICAgPGkgY2xhc3M9XCJmYS1icmFuZHMgZmEtZHJvcGJveFwiICpuZ0lmPVwiYWxsb3dlZFR5cGVzWzBdID09IDNcIj48L2k+XHJcbiAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+XHJcbiAgICAgIHt7XHJcbiAgICAgICAgYWxsb3dlZFR5cGVzWzBdID09IDFcclxuICAgICAgICAgID8gYWRkQnV0dG9uTGFiZWwgKyBcIiBmaWxlXCJcclxuICAgICAgICAgIDogYWxsb3dlZFR5cGVzWzBdID09IDJcclxuICAgICAgICAgID8gYWRkQnV0dG9uTGFiZWwgKyBcIiBsaW5rXCJcclxuICAgICAgICAgIDogdXBsb2FkV2l0aERyb3Bib3hMYWJlbFxyXG4gICAgICB9fTwvc3BhblxyXG4gICAgPlxyXG4gIDwvYnV0dG9uPlxyXG5cclxuICA8IS0tIFB1bHNhbnRlIHBlciBhcHJpcmUgaWwgbWVudSBwZXIgbGEgc2NlbHRhIGRlbCB0aXBvIGRpIEF0dGFjaG1lbnQgZGEgY3JlYXJlIC0tPlxyXG4gIDxidXR0b25cclxuICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1iLTQgbWUtNSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiXHJcbiAgICBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImF0dGFjaG1lbnRUeXBlTWVudVwiXHJcbiAgICBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiXHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICAhc2VwYXJhdGVkVXBsb2FkQnV0dG9ucyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMgJiZcclxuICAgICAgYWxsb3dlZFR5cGVzLmxlbmd0aCA+IDEgJiZcclxuICAgICAgKG11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlIHx8XHJcbiAgICAgICAgIWF0dGFjaG1lbnRzTGlzdCB8fFxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCB8fFxyXG4gICAgICAgIChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgIFwiPlxyXG4gICAgPG1hdC1pY29uICpuZ0lmPVwibXVsdGlwbGVBdHRhY2htZW50ICE9IHRydWVcIj5jbG91ZF91cGxvYWQ8L21hdC1pY29uPlxyXG4gICAgPG1hdC1pY29uICpuZ0lmPVwibXVsdGlwbGVBdHRhY2htZW50ID09IHRydWVcIj5hZGQ8L21hdC1pY29uPlxyXG4gICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMHB4XCI+IHt7IGFkZEJ1dHRvbkxhYmVsIH19IDwvc3Bhbj5cclxuICA8L2J1dHRvbj5cclxuICA8bWF0LW1lbnUgI2F0dGFjaG1lbnRUeXBlTWVudT1cIm1hdE1lbnVcIj5cclxuICAgIDxpbnB1dFxyXG4gICAgICAjaW1hZ2VJbnB1dFxyXG4gICAgICBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIlxyXG4gICAgICBpZD1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICAgIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgICB0eXBlPVwiZmlsZVwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiXHJcbiAgICAgIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxyXG4gICAgICBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKVwiXHJcbiAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgKGNsaWNrKT1cImltYWdlSW5wdXQuY2xpY2soKVwiXHJcbiAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWZpbGUtYnRuXCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWZpbGVcIj48L2k+XHJcbiAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5GaWxlPC9zcGFuPlxyXG4gICAgPC9idXR0b24+XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpXCJcclxuICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCJcclxuICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkxpbms8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIDxidXR0b25cclxuICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMylcIlxyXG4gICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCJcclxuICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYS1icmFuZHMgZmEtZHJvcGJveFwiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkRyb3Bib3g8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICA8L21hdC1tZW51PlxyXG5cclxuICA8ZGl2XHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICBzZXBhcmF0ZWRVcGxvYWRCdXR0b25zICYmXHJcbiAgICAgIGFsbG93ZWRUeXBlcyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMubGVuZ3RoID4gMSAmJlxyXG4gICAgICAobXVsdGlwbGVBdHRhY2htZW50ID09IHRydWUgfHxcclxuICAgICAgICAhYXR0YWNobWVudHNMaXN0IHx8XHJcbiAgICAgICAgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8XHJcbiAgICAgICAgKGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmICFhdHRhY2htZW50c0xpc3RbMF0pKVxyXG4gICAgXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCI+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKVwiXHJcbiAgICAgICAgKGNsaWNrKT1cImltYWdlSW5wdXQuY2xpY2soKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiXHJcbiAgICAgICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgICAgICBjb2xvcj1cInNlY29uZGFyeVwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiPlxyXG4gICAgICAgIDxpIGNsYXNzPVwiZmEtc29saWQgZmEtY2xvdWQtdXBsb2FkXCI+PC9pPlxyXG4gICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5GaWxlPC9zcGFuPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGlucHV0XHJcbiAgICAgICAgI2ltYWdlSW5wdXRcclxuICAgICAgICBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIlxyXG4gICAgICAgIGlkPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgICAgICBuYW1lPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgICAgICB0eXBlPVwiZmlsZVwiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJvbkZpbGVBZGRlZCgkZXZlbnQpXCJcclxuICAgICAgICBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCJcclxuICAgICAgICBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgIChjbGljayk9XCJzd2l0Y2hUb0FkZGluZ0xpbmtNb2RlKClcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zZWNvbmRhcnkgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIlxyXG4gICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgICAgY29sb3I9XCJzZWNvbmRhcnlcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIj5cclxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1saW5rXCI+PC9pPlxyXG4gICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5MaW5rPC9zcGFuPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpXCJcclxuICAgICAgICAoY2xpY2spPVwiY2hvb3NlRHJvcGJveEZpbGUoKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiXHJcbiAgICAgICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgICAgICBjb2xvcj1cInNlY29uZGFyeVwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiPlxyXG4gICAgICAgIDxpIGNsYXNzPVwiZmEtYnJhbmRzIGZhLWRyb3Bib3hcIj48L2k+XHJcbiAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkRyb3Bib3g8L3NwYW4+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG48bmctdGVtcGxhdGUgI2Nyb3BwaWVUZW1wbGF0ZT5cclxuICA8ZGl2IGNsYXNzPVwicm93IG0tM1wiPlxyXG4gICAgPGg0Pnt7IGNyb3BMYWJlbCB9fTwvaDQ+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cInJvdyBtLTIgY3JvcC1sYXJnZVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC1tZC0xMiBkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGp1c3RpZnktY29udGVudC1jZW50ZXJcIj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIFttYXRUb29sdGlwXT1cInJvdGF0ZUxlZnRMYWJlbFwiXHJcbiAgICAgICAgKm5nSWY9XCJjcm9wT3B0aW9ucy5pbmNsdWRlcygxKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWF0LXJhaXNlZC1idXR0b24gbXMtMlwiXHJcbiAgICAgICAgKGNsaWNrKT1cInJvdGF0ZUxlZnQoKVwiPlxyXG4gICAgICAgIDxtYXQtaWNvbiBzdHlsZT1cInZlcnRpY2FsLWFsaWduOiBtaWRkbGVcIj5yb3RhdGVfbGVmdDwvbWF0LWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgW21hdFRvb2x0aXBdPVwicm90YXRlUmlnaHRMYWJlbFwiXHJcbiAgICAgICAgKm5nSWY9XCJjcm9wT3B0aW9ucy5pbmNsdWRlcygxKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWF0LXJhaXNlZC1idXR0b24gbXMtMlwiXHJcbiAgICAgICAgKGNsaWNrKT1cInJvdGF0ZVJpZ2h0KClcIj5cclxuICAgICAgICA8bWF0LWljb24gc3R5bGU9XCJ2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCI+cm90YXRlX3JpZ2h0PC9tYXQtaWNvbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBbbWF0VG9vbHRpcF09XCJmbGlwSG9yaW56b250YWxMYWJlbFwiXHJcbiAgICAgICAgKm5nSWY9XCJjcm9wT3B0aW9ucy5pbmNsdWRlcygyKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWF0LXJhaXNlZC1idXR0b24gbXMtMlwiXHJcbiAgICAgICAgKGNsaWNrKT1cImZsaXBIb3Jpem9udGFsKClcIj5cclxuICAgICAgICA8bWF0LWljb24gc3R5bGU9XCJ2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCI+ZmxpcF9ob3Jpem9udGFsPC9tYXQtaWNvbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBbbWF0VG9vbHRpcF09XCJmbGlwVmVydGljYWxMYWJlbFwiXHJcbiAgICAgICAgKm5nSWY9XCJjcm9wT3B0aW9ucy5pbmNsdWRlcygyKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWF0LXJhaXNlZC1idXR0b24gbXMtMlwiXHJcbiAgICAgICAgKGNsaWNrKT1cImZsaXBWZXJ0aWNhbCgpXCI+XHJcbiAgICAgICAgPGRpdiBzdHlsZT1cInRyYW5zZm9ybTogcm90YXRlKDkwZGVnKVwiPjxtYXQtaWNvbiBzdHlsZT1cInZlcnRpY2FsLWFsaWduOiBtaWRkbGVcIj5mbGlwX3ZlcnRpY2FsPC9tYXQtaWNvbj48L2Rpdj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBbbWF0VG9vbHRpcF09XCInUmVzZXQnXCJcclxuICAgICAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBtYXQtcmFpc2VkLWJ1dHRvbiBtcy0yXCJcclxuICAgICAgICAoY2xpY2spPVwicmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpXCI+XHJcbiAgICAgICAgPG1hdC1pY29uIHN0eWxlPVwidmVydGljYWwtYWxpZ246IG1pZGRsZVwiPnJlcGxheTwvbWF0LWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cInJvdyBtLTIgY3JvcC1zbWFsbFwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC1tZC0xMiBkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGp1c3RpZnktY29udGVudC1jZW50ZXJcIj5cclxuICAgICAgPG1hdC1pY29uICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMSlcIiBzdHlsZT1cImZvbnQtc2l6ZTogMjdweDsgdmVydGljYWwtYWxpZ246IG1pZGRsZVwiIChjbGljayk9XCJyb3RhdGVMZWZ0KClcIlxyXG4gICAgICAgID5yb3RhdGVfbGVmdDwvbWF0LWljb25cclxuICAgICAgPlxyXG4gICAgICA8bWF0LWljb25cclxuICAgICAgICBjbGFzcz1cIm1zLTNcIlxyXG4gICAgICAgICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgIHN0eWxlPVwiZm9udC1zaXplOiAyN3B4OyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCJcclxuICAgICAgICAoY2xpY2spPVwicm90YXRlUmlnaHQoKVwiXHJcbiAgICAgICAgPnJvdGF0ZV9yaWdodDwvbWF0LWljb25cclxuICAgICAgPlxyXG4gICAgICA8bWF0LWljb25cclxuICAgICAgICBjbGFzcz1cIm1zLTNcIlxyXG4gICAgICAgICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgIHN0eWxlPVwiZm9udC1zaXplOiAyN3B4OyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCJcclxuICAgICAgICAoY2xpY2spPVwiZmxpcEhvcml6b250YWwoKVwiXHJcbiAgICAgICAgPmZsaXBfaG9yaXpvbnRhbDwvbWF0LWljb25cclxuICAgICAgPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwibXMtM1wiIHN0eWxlPVwidHJhbnNmb3JtOiByb3RhdGUoOTBkZWcpXCI+XHJcbiAgICAgICAgPG1hdC1pY29uXHJcbiAgICAgICAgICAqbmdJZj1cImNyb3BPcHRpb25zLmluY2x1ZGVzKDIpXCJcclxuICAgICAgICAgIHN0eWxlPVwiZm9udC1zaXplOiAyN3B4OyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCJcclxuICAgICAgICAgIChjbGljayk9XCJmbGlwVmVydGljYWwoKVwiXHJcbiAgICAgICAgICA+ZmxpcF92ZXJ0aWNhbDwvbWF0LWljb25cclxuICAgICAgICA+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8bWF0LWljb24gY2xhc3M9XCJtcy0zXCIgKGNsaWNrKT1cInJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKVwiIHN0eWxlPVwiZm9udC1zaXplOiAyN3B4OyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCJcclxuICAgICAgICA+cmVwbGF5PC9tYXQtaWNvblxyXG4gICAgICA+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8ZGl2IGNsYXNzPVwicm93IGp1c3RpZnktY29udGVudC1jZW50ZXJcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjcm9wLWNvbnRhaW5lclwiPlxyXG4gICAgICAgIDxpbWFnZS1jcm9wcGVyXHJcbiAgICAgICAgICBbaW1hZ2VGaWxlXT1cInNlbGVjdGVkRmlsZVwiXHJcbiAgICAgICAgICBbbWFpbnRhaW5Bc3BlY3RSYXRpb109XCJmYWxzZVwiXHJcbiAgICAgICAgICBbYXV0b0Nyb3BdPVwiZmFsc2VcIlxyXG4gICAgICAgICAgW2NvbnRhaW5XaXRoaW5Bc3BlY3RSYXRpb109XCJmYWxzZVwiXHJcbiAgICAgICAgICBbYXNwZWN0UmF0aW9dPVwiNCAvIDNcIlxyXG4gICAgICAgICAgW2Nyb3BwZXJNaW5XaWR0aF09XCIxMjhcIlxyXG4gICAgICAgICAgW29ubHlTY2FsZURvd25dPVwidHJ1ZVwiXHJcbiAgICAgICAgICBbcm91bmRDcm9wcGVyXT1cImZhbHNlXCJcclxuICAgICAgICAgIFtjYW52YXNSb3RhdGlvbl09XCIwXCJcclxuICAgICAgICAgIFt0cmFuc2Zvcm1dPVwidHJhbnNmb3JtXCJcclxuICAgICAgICAgIFthbGlnbkltYWdlXT1cIidsZWZ0J1wiXHJcbiAgICAgICAgICBmb3JtYXQ9XCJwbmdcIlxyXG4gICAgICAgICAgKGltYWdlQ3JvcHBlZCk9XCJpbWFnZUNyb3BwZWQoJGV2ZW50KVwiXHJcbiAgICAgICAgICBbcmVzaXplVG9XaWR0aF09XCJjdXN0b21XaWR0aFwiXHJcbiAgICAgICAgICBbcmVzaXplVG9IZWlnaHRdPVwiY3VzdG9tSGVpZ2h0XCJcclxuICAgICAgICAgIFtjYW52YXNSb3RhdGlvbl09XCJjYW52YXNSb3RhdGlvblwiPlxyXG4gICAgICAgIDwvaW1hZ2UtY3JvcHBlcj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8ZGl2IGNsYXNzPVwicm93IGp1c3RpZnktY29udGVudC1jZW50ZXIgbXQtMiBtYi0yIGNyb3AtbGFyZ2VcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBtYXQtcmFpc2VkLWJ1dHRvbiBlcXAtYXR0YWNobWVudHMtY29uZmlybS1idG4gbWUtMlwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgKGNsaWNrKT1cImNvbmZpcm1BZGRBdHRhY2htZW50KClcIj5cclxuICAgICAgICB7eyBjb25maXJtTGFiZWwgfX1cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gbWF0LXJhaXNlZC1idXR0b24gZXFwLWF0dGFjaG1lbnRzLWFib3J0LWJ0blwiIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiYWJvcnRGaWxlKClcIj5cclxuICAgICAgICB7eyBhYm9ydExhYmVsIH19XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cInJvdyBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyIG10LTIgbWItMiBjcm9wLXNtYWxsXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLTYgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCIgc3R5bGU9XCJmb250LXNpemU6IDIwcHhcIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYSBmYS10aW1lc1wiIChjbGljayk9XCJhYm9ydEZpbGUoKVwiPjwvaT5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC02IGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIganVzdGlmeS1jb250ZW50LWNlbnRlclwiIHN0eWxlPVwiZm9udC1zaXplOiAyMHB4XCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmEgZmEtY2hlY2tcIiAoY2xpY2spPVwiY29uZmlybUFkZEF0dGFjaG1lbnQoKVwiPjwvaT5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG48L25nLXRlbXBsYXRlPlxyXG5cclxuPCEtLSBURU1QTEFURSBQRVIgRk9STSBESSBBR0dJVU5UQSBESSBVTiBMSU5LIC0tPlxyXG48bmctdGVtcGxhdGUgI2FkZGluZ0xpbmtUZW1wbGF0ZT5cclxuICA8c3BhbiBjbGFzcz1cIm1iLTFcIiBzdHlsZT1cImZvbnQtc2l6ZTogMjBweFwiPjxpIGNsYXNzPVwiZmEgZmEtbGlua1wiPjwvaT5JbnNlcmlzY2kgbCdVUkw8L3NwYW4+XHJcbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJuZXdBdHRhY2htZW50Rm9ybVwiICpuZ0lmPVwibmV3QXR0YWNobWVudEZvcm1cIj5cclxuICAgIDxkaXYgY2xhc3M9XCJyb3cgbWItMlwiIHN0eWxlPVwiaGVpZ2h0OiA4MHB4XCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtNiBkLWdyaWQgZ2FwLTIgbXgtYXV0b1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cCBtYi0xXCI+XHJcbiAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgZmlsZU5hbWVMYWJlbCB9fVwiXHJcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIm5hbWVcIlxyXG4gICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm5ld0F0dGFjaG1lbnQuRmlsZU5hbWVcIiAvPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMiBkLWdyaWQgZ2FwLTJcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXBcIj5cclxuICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICByZXF1aXJlZFxyXG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJMaW5rXCJcclxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGF0aFwiXHJcbiAgICAgICAgICAgIFsobmdNb2RlbCldPVwibmV3QXR0YWNobWVudC5GaWxlUGF0aFwiIC8+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwicm93XCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtNiBkLWdyaWQgZ2FwLTJcIj5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICBjbGFzcz1cImJ0biBidG4tc2Vjb25kYXJ5IG1hdC1yYWlzZWQtYnV0dG9uXCJcclxuICAgICAgICAgIChjbGljayk9XCJzZWxlY3RlZEF0dGFjaG1lbnQgPSBudWxsOyBhZGRpbmdMaW5rTW9kZSA9IGZhbHNlXCJcclxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIj5cclxuICAgICAgICAgIHt7IGV4aXRMYWJlbCB9fVxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNvbC02IGQtZ3JpZCBnYXAtMlwiPlxyXG4gICAgICAgIDxidXR0b25cclxuICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1hdC1yYWlzZWQtYnV0dG9uXCJcclxuICAgICAgICAgIHR5cGU9XCJzdWJtaXRcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cImNvbmZpcm1BZGRBdHRhY2htZW50KCk7IHNlbGVjdGVkQXR0YWNobWVudCA9IG51bGw7IGFkZGluZ0xpbmtNb2RlID0gZmFsc2VcIj5cclxuICAgICAgICAgIHt7IHNhdmVMYWJlbCB9fVxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZm9ybT5cclxuPC9uZy10ZW1wbGF0ZT5cclxuIl19