@myrmidon/gve-core 0.0.4 → 0.0.5

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 (45) hide show
  1. package/README.md +43 -77
  2. package/esm2022/lib/components/animation-timeline/animation-timeline.component.mjs +50 -19
  3. package/esm2022/lib/components/animation-timeline-set/animation-timeline-set.component.mjs +32 -8
  4. package/esm2022/lib/components/animation-tween/animation-tween.component.mjs +48 -25
  5. package/esm2022/lib/components/base-text-char/base-text-char.component.mjs +13 -4
  6. package/esm2022/lib/components/base-text-editor/base-text-editor.component.mjs +10 -6
  7. package/esm2022/lib/components/base-text-view/base-text-view.component.mjs +39 -5
  8. package/esm2022/lib/components/chain-operation-editor/chain-operation-editor.component.mjs +97 -39
  9. package/esm2022/lib/components/chain-result-view/chain-result-view.component.mjs +44 -12
  10. package/esm2022/lib/components/feature-editor/feature-editor.component.mjs +27 -12
  11. package/esm2022/lib/components/feature-set-editor/feature-set-editor.component.mjs +32 -9
  12. package/esm2022/lib/components/feature-set-view/feature-set-view.component.mjs +28 -8
  13. package/esm2022/lib/components/ln-heights-editor/ln-heights-editor.component.mjs +38 -7
  14. package/esm2022/lib/components/operation-source-editor/operation-source-editor.component.mjs +29 -4
  15. package/esm2022/lib/components/simple-tree/simple-tree.component.mjs +20 -4
  16. package/esm2022/lib/components/snapshot-editor/snapshot-editor.component.mjs +419 -114
  17. package/esm2022/lib/components/steps-map/steps-map.component.mjs +31 -9
  18. package/esm2022/lib/services/gve-api.service.mjs +3 -3
  19. package/esm2022/lib/services/settings.service.mjs +6 -5
  20. package/esm2022/lib/validators/svg-validators.mjs +7 -1
  21. package/esm2022/public-api.mjs +1 -2
  22. package/fesm2022/myrmidon-gve-core.mjs +947 -388
  23. package/fesm2022/myrmidon-gve-core.mjs.map +1 -1
  24. package/lib/components/animation-timeline/animation-timeline.component.d.ts +31 -9
  25. package/lib/components/animation-timeline-set/animation-timeline-set.component.d.ts +28 -4
  26. package/lib/components/animation-tween/animation-tween.component.d.ts +25 -12
  27. package/lib/components/base-text-char/base-text-char.component.d.ts +16 -0
  28. package/lib/components/base-text-editor/base-text-editor.component.d.ts +5 -1
  29. package/lib/components/base-text-view/base-text-view.component.d.ts +37 -0
  30. package/lib/components/chain-operation-editor/chain-operation-editor.component.d.ts +53 -5
  31. package/lib/components/chain-result-view/chain-result-view.component.d.ts +17 -3
  32. package/lib/components/feature-editor/feature-editor.component.d.ts +20 -6
  33. package/lib/components/feature-set-editor/feature-set-editor.component.d.ts +28 -5
  34. package/lib/components/feature-set-view/feature-set-view.component.d.ts +23 -3
  35. package/lib/components/ln-heights-editor/ln-heights-editor.component.d.ts +22 -0
  36. package/lib/components/operation-source-editor/operation-source-editor.component.d.ts +31 -0
  37. package/lib/components/simple-tree/simple-tree.component.d.ts +19 -0
  38. package/lib/components/snapshot-editor/snapshot-editor.component.d.ts +178 -15
  39. package/lib/components/steps-map/steps-map.component.d.ts +20 -3
  40. package/lib/services/settings.service.d.ts +2 -1
  41. package/lib/validators/svg-validators.d.ts +6 -0
  42. package/package.json +4 -4
  43. package/public-api.d.ts +0 -1
  44. package/esm2022/lib/components/animation-vars/animation-vars.component.mjs +0 -141
  45. package/lib/components/animation-vars/animation-vars.component.d.ts +0 -30
@@ -1,4 +1,4 @@
1
- import { CUSTOM_ELEMENTS_SCHEMA, Component, EventEmitter, Input, Output, } from '@angular/core';
1
+ import { CUSTOM_ELEMENTS_SCHEMA, Component, EventEmitter, Input, Output, ViewChild, } from '@angular/core';
2
2
  import { FormControl, FormsModule, ReactiveFormsModule, Validators, } from '@angular/forms';
3
3
  import { CommonModule } from '@angular/common';
4
4
  import { MatButtonModule } from '@angular/material/button';
@@ -37,9 +37,21 @@ import * as i12 from "@angular/material/progress-bar";
37
37
  import * as i13 from "@angular/material/tabs";
38
38
  import * as i14 from "@angular/material/tooltip";
39
39
  import * as i15 from "@myrmidon/ng-tools";
40
+ // default snapshot view title
40
41
  const VIEW_TITLE = 'preview';
42
+ // suffix for IDs of SVG elements to be made transparent at first rendition
43
+ const SVG_TRANSP_SUFFIX = '_t';
41
44
  /**
42
- * A component to edit a text snapshot.
45
+ * 🔑 `gve-snapshot-editor`
46
+ *
47
+ * A component to edit a text snapshot. This is the top level component in the GVE core
48
+ * library.
49
+ *
50
+ * - ▶️ `snapshot` (`Snapshot`): the snapshot to edit.
51
+ * - ▶️ `batchOps` (`string`): the batch operations text to set for the editor.
52
+ * - ▶️ `noSave` (`boolean`): true to disable saving.
53
+ * - 🔥 `snapshotChange` (`Snapshot`): emitted when the user saves the edited snapshot.
54
+ * - 🔥 `snapshotCancel` (`void`): emitted when the user cancels the snapshot editing.
43
55
  */
44
56
  export class SnapshotEditorComponent {
45
57
  /**
@@ -54,7 +66,9 @@ export class SnapshotEditorComponent {
54
66
  }
55
67
  this._snapshot = value || undefined;
56
68
  this.updateForm(this._snapshot);
57
- this.updateViewData();
69
+ setTimeout(() => {
70
+ this.runToLast();
71
+ }, 0);
58
72
  }
59
73
  constructor(formBuilder, _api, _dialogService, _snackbar) {
60
74
  this._api = _api;
@@ -69,9 +83,13 @@ export class SnapshotEditorComponent {
69
83
  * Emitted when the user cancels the snapshot editing.
70
84
  */
71
85
  this.snapshotCancel = new EventEmitter();
72
- this.editedOpIndex = -1;
86
+ // list of operations output tags
73
87
  this.opTags = [];
88
+ // list of operation diplomatic.g element IDs
74
89
  this.opElementIds = [];
90
+ // the lines count for the current base text
91
+ this.lineCount = 0;
92
+ this.editedOpIndex = -1;
75
93
  this.opTypeMap = {
76
94
  0: 'replace',
77
95
  1: 'delete',
@@ -82,9 +100,10 @@ export class SnapshotEditorComponent {
82
100
  6: 'swap',
83
101
  7: 'annotate',
84
102
  };
85
- this.lineCount = 0;
103
+ // snapshot view data
86
104
  this.viewTitle = VIEW_TITLE;
87
105
  this.rulers = true;
106
+ this.initialStepIndex = -1;
88
107
  // general
89
108
  this.width = new FormControl(800, { nonNullable: true });
90
109
  this.height = new FormControl(600, { nonNullable: true });
@@ -119,6 +138,7 @@ export class SnapshotEditorComponent {
119
138
  this.timelines = new FormControl([], {
120
139
  nonNullable: true,
121
140
  });
141
+ // form
122
142
  this.form = formBuilder.group({
123
143
  width: this.width,
124
144
  height: this.height,
@@ -147,42 +167,44 @@ export class SnapshotEditorComponent {
147
167
  });
148
168
  }
149
169
  ngOnInit() {
170
+ // if there are any batch operations, parse them into snapshot operations
150
171
  if (this.batchOps) {
151
172
  this.inputOps.setValue(this.batchOps);
152
173
  this.parseOperations();
153
174
  }
154
175
  }
155
- updateViewData(newOperation, snapshot, title = VIEW_TITLE) {
156
- console.log('update view data');
176
+ /**
177
+ * Set the view data for the snapshot view.
178
+ *
179
+ * @param snapshot The optional snapshot data to use. If not provided,
180
+ * a snapshot will be created from the form data.
181
+ * @param title The optional title to set for the view.
182
+ */
183
+ setViewData(snapshot, title = VIEW_TITLE) {
184
+ console.log('set view data');
185
+ // get the snapshot to use
157
186
  if (!snapshot) {
158
187
  snapshot = this.getSnapshot();
159
188
  }
160
- // update or add new operation in copy
161
- if (newOperation) {
162
- const index = snapshot.operations.findIndex((op) => op.id === newOperation.id);
163
- if (index > -1) {
164
- snapshot.operations.splice(index, 1, newOperation);
165
- }
166
- else {
167
- snapshot.operations.push(newOperation);
168
- }
169
- }
170
189
  // update view data
171
190
  this.viewTitle = title;
172
191
  this.visualInfo = undefined;
173
192
  this.viewData = {
174
193
  snapshot: snapshot,
175
194
  options: {
176
- // debug: true,
195
+ debug: this.debug,
177
196
  delayedRender: true,
178
197
  showRulers: true,
179
198
  showGrid: true,
180
199
  panZoom: true,
200
+ transparentIds: this._transparentIds,
181
201
  },
182
202
  };
183
- console.log(`view data: ${this.viewData}`);
203
+ console.log('view data: ', this.viewData);
184
204
  }
185
205
  updateForm(snapshot) {
206
+ this._transparentIds = undefined;
207
+ this.initialStepIndex = -1;
186
208
  if (!snapshot) {
187
209
  this.form.reset();
188
210
  }
@@ -217,9 +239,74 @@ export class SnapshotEditorComponent {
217
239
  }
218
240
  this.timelines.setValue(timelines);
219
241
  }
242
+ this.updateLineCount(this.baseText.value);
243
+ this.updateOpLists();
220
244
  this.form.markAsPristine();
221
245
  }
246
+ // #region base text
247
+ /**
248
+ * Update the line count based on the received text.
249
+ * @param text The text to use for counting lines.
250
+ */
251
+ updateLineCount(text) {
252
+ if (!text.length) {
253
+ this.lineCount = 0;
254
+ }
255
+ else {
256
+ this.lineCount = text.filter((c) => c.data === '\n').length + 1;
257
+ }
258
+ }
259
+ /**
260
+ * Handle the event fired by the base text editor to pick a text range.
261
+ * @param range The picked range.
262
+ */
263
+ onRangePick(range) {
264
+ this.textRange = range;
265
+ }
266
+ /**
267
+ * Handle the event fired by the base text editor to change the base text.
268
+ * @param text The text to set.
269
+ */
270
+ onTextChange(text) {
271
+ console.log('text change: ' + text);
272
+ // update the form control and reset the current text range
273
+ this.baseText.setValue(text);
274
+ this.baseText.updateValueAndValidity();
275
+ this.baseText.markAsDirty();
276
+ this.textRange = undefined;
277
+ // update the line count
278
+ this.updateLineCount(text);
279
+ // remove all operations and update the view data
280
+ this.removeAllOperations();
281
+ }
282
+ // #endregion
283
+ // #region operations
284
+ /**
285
+ * Update the lists of operation output tags and element IDs by collecting
286
+ * all the operation tags and the IDs of the elements in their diplomatic.g
287
+ * SVG code if any.
288
+ */
289
+ updateOpLists() {
290
+ const tags = new Set();
291
+ const ids = new Set();
292
+ let n = 0;
293
+ for (const op of this.operations.value) {
294
+ // output tag
295
+ n++;
296
+ tags.add(op.outputTag || `v${n}`);
297
+ // element IDs
298
+ if (op.diplomatics?.g) {
299
+ this.parseSvgIds(op.diplomatics.g)?.forEach((id) => ids.add(id));
300
+ }
301
+ }
302
+ this.opTags = [...tags];
303
+ this.opElementIds = [...ids];
304
+ }
305
+ /**
306
+ * Edit a new operation.
307
+ */
222
308
  editNewOperation() {
309
+ // create a new operation and edit it
223
310
  this.editedOp = {
224
311
  id: this._nanoid(),
225
312
  type: 0,
@@ -228,66 +315,91 @@ export class SnapshotEditorComponent {
228
315
  };
229
316
  this.editedOpIndex = -1;
230
317
  }
318
+ /**
319
+ * Edit (a copy of) the operation at the specified index.
320
+ * @param index The operation index.
321
+ */
231
322
  editOperation(index) {
232
323
  this.editedOpIndex = index;
233
324
  this.editedOp = deepCopy(this.operations.value[index]);
234
325
  }
235
- closeEditedOp() {
326
+ /**
327
+ * Close the currently edited operation.
328
+ */
329
+ closeEditedOperation() {
236
330
  this.editedOpIndex = -1;
237
331
  this.editedOp = undefined;
238
332
  }
333
+ /**
334
+ * Handle the event fired by the operation editor to cancel
335
+ * the current operation edits.
336
+ */
239
337
  onOperationCancel() {
240
- this.closeEditedOp();
338
+ this.closeEditedOperation();
241
339
  }
242
- onOperationChange(op) {
340
+ /**
341
+ * Handle the event fired by the operation editor to change
342
+ * the currently edited operation, or add a new one if that
343
+ * was a new operation.
344
+ * @param op The changed operation.
345
+ */
346
+ async onOperationChange(op) {
243
347
  console.log('operation change');
244
348
  const operations = [...this.operations.value];
349
+ // replace or add the operation
350
+ let i = this.editedOpIndex;
245
351
  if (this.editedOpIndex > -1) {
246
352
  operations.splice(this.editedOpIndex, 1, op);
247
353
  }
248
354
  else {
249
355
  operations.push(op);
356
+ i = operations.length - 1;
250
357
  }
358
+ // update the operations form control
251
359
  this.operations.setValue(operations);
252
360
  this.operations.markAsDirty();
253
361
  this.operations.updateValueAndValidity();
254
- this.closeEditedOp();
362
+ // update the operation lists
363
+ this.updateOpLists();
364
+ // update the view data
365
+ await this.runTo(i);
366
+ // close the edited operation
367
+ this.closeEditedOperation();
255
368
  }
369
+ /**
370
+ * Delete the operation at the specified index.
371
+ * @param index The index of the operation to delete.
372
+ */
256
373
  deleteOperation(index) {
257
374
  this._dialogService
258
375
  .confirm('Confirm Deletion', `Delete operation "${this.operations.value[index].id}"?`)
259
376
  .subscribe((yes) => {
260
377
  if (yes) {
378
+ // close the edited operation if it is the one being deleted
379
+ if (this.editedOpIndex === index) {
380
+ this.closeEditedOperation();
381
+ }
382
+ // reset the result operation ID if it is the one being deleted
261
383
  if (this.resultOperationId === this.operations.value[index].id) {
262
384
  this.resultOperationId = undefined;
263
385
  }
386
+ // delete the operation and update the form control
264
387
  const operations = [...this.operations.value];
265
388
  operations.splice(index, 1);
266
389
  this.operations.setValue(operations);
267
390
  this.operations.markAsDirty();
268
391
  this.operations.updateValueAndValidity();
392
+ // update the operation lists
393
+ this.updateOpLists();
394
+ // update the view data
395
+ this.runToLast();
269
396
  }
270
397
  });
271
398
  }
272
- onTextChange(text) {
273
- console.log('text change: ' + text);
274
- this.baseText.setValue(text);
275
- this.baseText.updateValueAndValidity();
276
- this.baseText.markAsDirty();
277
- if (!text.length) {
278
- this.lineCount = 0;
279
- }
280
- else {
281
- this.lineCount = text.filter((c) => c.data === '\n').length + 1;
282
- }
283
- this.textRange = undefined;
284
- this.closeEditedOp();
285
- this.operations.reset();
286
- this.updateViewData();
287
- }
288
- onRangePick(range) {
289
- this.textRange = range;
290
- }
399
+ /**
400
+ * Parse the operations from their text and append them to the current
401
+ * snapshot operations.
402
+ */
291
403
  parseOperations() {
292
404
  if (this.busy || !this.inputOps.value) {
293
405
  return;
@@ -305,7 +417,10 @@ export class SnapshotEditorComponent {
305
417
  this.operations.setValue(operations);
306
418
  this.operations.markAsDirty();
307
419
  this.operations.updateValueAndValidity();
308
- this.updateViewData();
420
+ // update the operation lists
421
+ this.updateOpLists();
422
+ // update the view data
423
+ this.runToLast();
309
424
  },
310
425
  error: (error) => {
311
426
  this.parseError = error.message;
@@ -317,103 +432,257 @@ export class SnapshotEditorComponent {
317
432
  }
318
433
  });
319
434
  }
435
+ removeAllOperations() {
436
+ this.resultOperationId = undefined;
437
+ this.closeEditedOperation();
438
+ this.operations.reset();
439
+ this.operations.markAsDirty();
440
+ this.operations.updateValueAndValidity();
441
+ this.opTags = [];
442
+ this.opElementIds = [];
443
+ this.setViewData();
444
+ }
445
+ /**
446
+ * Remove all the operations.
447
+ */
320
448
  clearOperations() {
321
449
  this._dialogService
322
450
  .confirm('Confirm', 'Remove all operations?')
323
451
  .subscribe((yes) => {
324
452
  if (yes) {
325
- this.resultOperationId = undefined;
326
- this.operations.reset();
327
- this.operations.markAsDirty();
328
- this.operations.updateValueAndValidity();
329
- this.updateViewData();
453
+ this.removeAllOperations();
454
+ }
455
+ });
456
+ }
457
+ /**
458
+ * Parse all the id attributes from the received SVG code and
459
+ * return them as an array.
460
+ *
461
+ * @param svg The SVG content to parse or undefined.
462
+ * @returns Array of IDs found in the SVG content or undefined.
463
+ */
464
+ parseSvgIds(svg) {
465
+ if (!svg) {
466
+ return undefined;
467
+ }
468
+ const regex = /<[^>]+\bid=(["'])(.*?)\1/g;
469
+ const ids = [];
470
+ let match;
471
+ while ((match = regex.exec(svg)) !== null) {
472
+ ids.push(match[2]);
473
+ }
474
+ return ids;
475
+ }
476
+ /**
477
+ * Run the operations up to the specified index (included).
478
+ * This is called when:
479
+ * - a preview is requested by the operation editor.
480
+ * - the currently edited operation is saved.
481
+ * - the user picks a step in the chain result view.
482
+ * - runToLast is called, which happens when:
483
+ * - setting the snapshot.
484
+ * - parsing a batch of operations.
485
+ * - deleting an operation.
486
+ *
487
+ * @param index The index of the operation to run to.
488
+ * @param lastOperation The operation to use in place of the existing
489
+ * operation in the snapshot at index. This is used when previewing
490
+ * the edited operation from within the operation editor.
491
+ */
492
+ runTo(index, lastOperation) {
493
+ return new Promise((resolve, reject) => {
494
+ if (this.busy) {
495
+ return reject('Busy');
496
+ }
497
+ console.log('run to: ' + index);
498
+ // get the snapshot to run operations on
499
+ const snapshot = this.getSnapshot();
500
+ if (!snapshot.text) {
501
+ return reject('No snapshot text');
502
+ }
503
+ // run operations up to the specified index, but replace the last
504
+ // operation when this was received as a parameter
505
+ const operations = [...this.operations.value];
506
+ if (lastOperation) {
507
+ operations.slice(0, index);
508
+ operations.push(lastOperation);
509
+ }
510
+ else {
511
+ operations.slice(0, index + 1);
330
512
  }
513
+ this.busy = true;
514
+ this.initialStepIndex = index;
515
+ this._api
516
+ .runOperations(snapshot.text, operations)
517
+ .subscribe({
518
+ next: (wrapper) => {
519
+ // handle operation (non-fatal) error or result
520
+ if (wrapper.error) {
521
+ this._snackbar.open(wrapper.error, 'OK');
522
+ reject(wrapper.error);
523
+ return;
524
+ }
525
+ // extract the IDs from the last operation's diplomatics and filter
526
+ // them so that only the ones ending with _t are kept. By convention,
527
+ // all the IDs ending with this suffix are to be made invisible at
528
+ // their first rendition (opacity=0). An animation will then make
529
+ // them visible.
530
+ this._transparentIds = this.parseSvgIds(operations[index].diplomatics?.g)?.filter((id) => id.endsWith(SVG_TRANSP_SUFFIX));
531
+ this.setViewData(snapshot, snapshot.operations[index].outputTag);
532
+ this.result = wrapper.result;
533
+ resolve();
534
+ },
535
+ error: (error) => {
536
+ console.error(error);
537
+ this._transparentIds = undefined;
538
+ this._snackbar.open('Error running operations', 'OK');
539
+ reject(error);
540
+ },
541
+ complete: () => {
542
+ this.busy = false;
543
+ },
544
+ });
331
545
  });
332
546
  }
547
+ /**
548
+ * Run the operations up to the last operation if any.
549
+ * Otherwise, just update the snapshot view.
550
+ */
551
+ runToLast() {
552
+ if (this.operations.value.length) {
553
+ this.runTo(this.operations.value.length - 1);
554
+ }
555
+ else {
556
+ this.setViewData();
557
+ }
558
+ }
559
+ /**
560
+ * Update the snapshot view by running the operations up to the
561
+ * currently edited operation if any.
562
+ *
563
+ * @param operation The operation being previewed.
564
+ */
333
565
  onOperationPreview(operation) {
334
- if (this._previewing) {
566
+ // no multiple previews or previewing a new operation
567
+ if (this._previewing || this.editedOpIndex < 0) {
335
568
  return;
336
569
  }
337
570
  this._previewing = true;
338
571
  setTimeout(() => {
339
- this.updateViewData(operation);
572
+ this.runTo(this.editedOpIndex, operation);
340
573
  this._previewing = false;
341
574
  }, 0);
342
575
  }
343
- runTo(index) {
344
- const snapshot = this.getSnapshot();
345
- if (!snapshot.text) {
346
- return;
347
- }
348
- const operations = this.operations.value.slice(0, index + 1);
349
- this.busy = true;
350
- this._api.runOperations(snapshot.text, operations).subscribe({
351
- next: (wrapper) => {
352
- if (wrapper.error) {
353
- this._snackbar.open(wrapper.error, 'OK');
354
- return;
355
- }
356
- this.result = wrapper.result;
357
- // TODO update view
358
- // this.updateViewData(
359
- // undefined,
360
- // snapshot,
361
- // this.operations.value[index].outputTag
362
- // );
363
- },
364
- error: (error) => {
365
- console.error(error);
366
- this._snackbar.open('Error running operations', 'OK');
367
- },
368
- complete: () => {
369
- this.busy = false;
370
- },
371
- });
372
- }
373
- onStepPick(step) {
576
+ // #endregion
577
+ /**
578
+ * Build the snapshot at the specified execution step. This implies adding
579
+ * the nodes introduced by the operations up to the specified step, and
580
+ * updating the features of the nodes introduced by the specified step.
581
+ * Also, the operations after the specified step are removed from the
582
+ * snapshot.
583
+ *
584
+ * @param step The step to build the snapshot at.
585
+ * @returns The snapshot at the specified step.
586
+ */
587
+ buildSnapshotAtStep(step) {
588
+ // no result, nothing to do
374
589
  if (!this.result) {
375
- return;
590
+ return null;
376
591
  }
377
- this.resultOperationId = step.operation.id;
378
- // get snapshot for preview by updating its text and
379
- // removing operations past the last executed
380
- const stepNodes = this.result.taggedNodes[step.outputTag];
381
- // we always display the original base text, just updating
382
- // its nodes features to those of the picked step, and adding
383
- // new nodes if they are not in the original text. It is assumed
384
- // that these new nodes have a manually set position.
592
+ // get the currently edited snapshot
385
593
  const snapshot = this.getSnapshot();
386
- const nodes = deepCopy(snapshot.text);
594
+ // find the max ID in snapshot.text (=original) nodes,
595
+ // so that any ID greater than it belongs to new nodes
596
+ const maxOriginalId = snapshot.text.reduce((max, n) => Math.max(max, n.id), 0);
597
+ // get a copy of the nodes of the snapshot base text
598
+ const snapNodes = deepCopy(snapshot.text);
599
+ // get the nodes of the picked step
600
+ const stepNodes = this.result.taggedNodes[step.outputTag];
601
+ // update the snapshot text nodes copies with the picked step nodes,
602
+ // by updating their features if existing, or adding new nodes if not.
387
603
  for (const sn of stepNodes) {
388
- const i = nodes.findIndex((n) => n.id === sn.id);
604
+ // find the node in the original snapshot text
605
+ const i = snapNodes.findIndex((n) => n.id === sn.id);
606
+ // if found, update its features, else add it
389
607
  if (i > -1) {
390
- nodes[i].features = sn.features;
608
+ snapNodes[i].features = sn.features;
391
609
  }
392
610
  else {
393
- nodes.push(sn);
611
+ // new node: we assume that it has a manually set position (x,y features)
612
+ snapNodes.push(sn);
394
613
  }
395
614
  }
396
- // find max ID in snapshot.text (=original) nodes,
397
- // so that any ID greater than it belongs to new nodes
398
- const maxOriginalId = snapshot.text.reduce((max, n) => Math.max(max, n.id), 0);
399
- // append nodes introduced before the picked step if any
615
+ // append nodes introduced *before* the picked step, if any
400
616
  // (those introduced by the picked step have already been added)
401
617
  const stepIndex = this.result.steps.indexOf(step);
402
618
  for (let i = 0; i < stepIndex; i++) {
403
619
  const stepNodes = this.result.taggedNodes[this.result.steps[i].outputTag];
404
620
  for (const n of stepNodes) {
405
- if (n.id > maxOriginalId && !nodes.find((x) => x.id === n.id)) {
406
- nodes.push(n);
621
+ if (n.id > maxOriginalId && !snapNodes.find((x) => x.id === n.id)) {
622
+ snapNodes.push(n);
407
623
  }
408
624
  }
409
625
  }
410
- snapshot.text = nodes;
626
+ // update the snapshot text nodes
627
+ snapshot.text = snapNodes;
628
+ // remove from the snapshot the operations after the picked step
411
629
  const i = snapshot.operations.findIndex((o) => o.id === step.operation.id);
412
630
  if (i > -1) {
413
631
  snapshot.operations = snapshot.operations.slice(0, i + 1);
414
632
  }
415
- this.updateViewData(undefined, snapshot, step.outputTag);
633
+ return snapshot;
416
634
  }
635
+ playTimeline(tl) {
636
+ const shadowRoot = this.snapshotView?.nativeElement?.shadowRoot;
637
+ if (tl && shadowRoot) {
638
+ console.log('play timeline', tl);
639
+ this._renderer?.playTimeline(tl, undefined, shadowRoot);
640
+ }
641
+ else {
642
+ if (!this.snapshotView) {
643
+ console.warn('no snapshotView for timeline');
644
+ }
645
+ else {
646
+ console.warn('no shadowRoot for timeline');
647
+ }
648
+ }
649
+ }
650
+ /**
651
+ * Handle the event fired by the chain result view to pick a step.
652
+ *
653
+ * @param step The step to pick.
654
+ */
655
+ async onStepPick(step) {
656
+ if (!this.result || this._stepPickFrozen) {
657
+ return;
658
+ }
659
+ // get the currently edited snapshot
660
+ const snapshot = this.buildSnapshotAtStep(step);
661
+ // update result operation ID
662
+ this.resultOperationId = step.operation.id;
663
+ // update view data
664
+ this.setViewData(snapshot, step.outputTag);
665
+ // play animation if any
666
+ const tl = this.timelines.value.find((t) => t.tag === step.outputTag);
667
+ if (tl) {
668
+ this._stepPickFrozen = true;
669
+ // find the index of the picked step in the snapshot operations
670
+ const i = snapshot.operations.findIndex((o) => o.id === step.operation.id);
671
+ // run the operations up to the picked step as we need to hide
672
+ // those visuals to be revealed by the animation
673
+ await this.runTo(i);
674
+ this._stepPickFrozen = false;
675
+ // play the timeline
676
+ setTimeout(() => {
677
+ this.playTimeline(tl);
678
+ }, 0);
679
+ }
680
+ }
681
+ /**
682
+ * Handle the event fired by a visual in the snapshot view.
683
+ *
684
+ * @param event The event.
685
+ */
417
686
  onVisualEvent(event) {
418
687
  const d = event.detail;
419
688
  if (d.event.type === 'mouseover') {
@@ -426,6 +695,7 @@ export class SnapshotEditorComponent {
426
695
  sb.push(visual.data.label);
427
696
  }
428
697
  if (visual.data?.features?.length) {
698
+ sb.push(' ');
429
699
  sb.push(visual.data.features
430
700
  .map((f) => `${f.name}=${f.value}`)
431
701
  .join('\n'));
@@ -433,23 +703,55 @@ export class SnapshotEditorComponent {
433
703
  this.visualInfo = sb.join('');
434
704
  }
435
705
  }
706
+ /**
707
+ * Handle the change of line heights by updating the form control.
708
+ *
709
+ * @param heights The line heights.
710
+ */
436
711
  onHeightsChange(heights) {
437
712
  this.lnHeights.setValue(heights || null);
438
713
  this.lnHeights.markAsDirty();
439
714
  this.lnHeights.updateValueAndValidity();
440
715
  }
716
+ /**
717
+ * Handle the change of timelines by updating the form control.
718
+ *
719
+ * @param timelines The timelines.
720
+ */
721
+ onTimelinesChange(timelines) {
722
+ this.timelines.setValue(timelines);
723
+ this.timelines.markAsDirty();
724
+ this.timelines.updateValueAndValidity();
725
+ }
726
+ /**
727
+ * Emit the cancel event for this snapshot edit.
728
+ */
441
729
  close() {
442
730
  this.snapshotCancel.emit();
443
731
  }
732
+ /**
733
+ * Handle the render event from the snapshot view to get a reference
734
+ * to the renderer.
735
+ *
736
+ * @param event The rendition event.
737
+ */
444
738
  onSnapshotRender(event) {
445
739
  this._renderer = event.detail.renderer;
446
740
  }
741
+ /**
742
+ * Toggle rulers in the snapshot view.
743
+ */
447
744
  toggleRulers() {
448
745
  if (!this._renderer) {
449
746
  return;
450
747
  }
451
748
  this.rulers = this._renderer.toggleRulers();
452
749
  }
750
+ /**
751
+ * Get a snapshot from the form data.
752
+ *
753
+ * @returns New snapshot object.
754
+ */
453
755
  getSnapshot() {
454
756
  const snapshot = {
455
757
  size: {
@@ -472,7 +774,6 @@ export class SnapshotEditorComponent {
472
774
  },
473
775
  operations: [...this.operations.value],
474
776
  opStyle: this.opStyle.value || undefined,
475
- timelines: {}, // TODO
476
777
  };
477
778
  // image
478
779
  if (this.imageUrl.value) {
@@ -504,11 +805,10 @@ export class SnapshotEditorComponent {
504
805
  }
505
806
  return snapshot;
506
807
  }
507
- onTimelinesChange(timelines) {
508
- this.timelines.setValue(timelines);
509
- this.timelines.markAsDirty();
510
- this.timelines.updateValueAndValidity();
511
- }
808
+ /**
809
+ * Get a snapshot from the form data and emit it
810
+ * in the snapshot change event.
811
+ */
512
812
  save() {
513
813
  if (this.form.invalid || this.noSave) {
514
814
  return;
@@ -516,10 +816,10 @@ export class SnapshotEditorComponent {
516
816
  this._snapshot = this.getSnapshot();
517
817
  this.snapshotChange.emit(this._snapshot);
518
818
  }
519
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: SnapshotEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i2.GveApiService }, { token: i3.DialogService }, { token: i4.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component }); }
520
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.6", type: SnapshotEditorComponent, isStandalone: true, selector: "gve-snapshot-editor", inputs: { snapshot: "snapshot", batchOps: "batchOps", noSave: "noSave" }, outputs: { snapshotChange: "snapshotChange", snapshotCancel: "snapshotCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab label=\"text\">\r\n <mat-expansion-panel [expanded]=\"!baseText.value\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-base-text-editor\r\n [text]=\"baseText.value\"\r\n (textChange)=\"onTextChange($event)\"\r\n />\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div>\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount\"\r\n [heights]=\"lnHeights.value\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab label=\"operations\">\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary right\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [ngClass]=\"{ selected: operation.id === resultOperationId }\"\r\n [ngClass]=\"{ edited: operation.id === editedOp?.id }\"\r\n >\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n <mat-expansion-panel [expanded]=\"editedOp\" [disabled]=\"!editedOp\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [operation]=\"editedOp\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"busy\" />\r\n </div>\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- batch ops -->\r\n <div>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>batch operations</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <div id=\"batch-container\">\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"inputOps\"\r\n placeholder=\"operations\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy\"\r\n (click)=\"clearOperations()\"\r\n >\r\n clear\r\n </button>\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text and add results to the operations\"\r\n [disabled]=\"!inputOps.value || busy\"\r\n (click)=\"parseOperations()\"\r\n >\r\n batch add\r\n </button>\r\n @if (parseError) {\r\n <span class=\"error\">{{ parseError }}</span>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>&gt;[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>&gt;]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong>&lt;&gt;</strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or\r\n output tags, separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>&#x40;</code> to AT to use character\r\n indexes (0-N) rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>,\r\n separated by space, where:\r\n </li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove\r\n feature (no value). Suffixes:\r\n <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple),\r\n <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </ul>\r\n </div>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </div>\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab label=\"image\">\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img alt=\"background\" [src]=\"imageUrl.value\" width=\"600\" />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab label=\"animation\">\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags\"\r\n [elementIds]=\"opElementIds\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- preview -->\r\n @if (snapshot) {\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n <button\r\n color=\"primary\"\r\n mat-icon-button\r\n type=\"button\"\r\n matTooltip=\"Refresh preview\"\r\n (click)=\"updateViewData()\"\r\n >\r\n <mat-icon class=\"mat-primary\">refresh</mat-icon>\r\n </button>\r\n </legend>\r\n <gve-snapshot-view\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div>\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row *.right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}div#batch-container{display:grid;gap:16px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"batch-input batch-help\"}div#batch-input{grid-area:batch-input}div#batch-help{grid-area:batch-help}div#batch-help strong{color:#ff8c00}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}@media only screen and (max-width: 959px){div#batch-container{grid-template-columns:1fr;grid-template-areas:\"batch-input\" \"batch-help\"}div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { 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.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "component", type: i7.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i11.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: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i12.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i13.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i13.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i14.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: NgToolsModule }, { kind: "pipe", type: i15.FlatLookupPipe, name: "flatLookup" }, { kind: "component", type: BaseTextEditorComponent, selector: "gve-base-text-editor", inputs: ["text"], outputs: ["textChange"] }, { kind: "component", type: ChainOperationEditorComponent, selector: "gve-chain-operation-editor", inputs: ["operation", "snapshot", "hidePreview"], outputs: ["operationChange", "operationPreview", "operationCancel"] }, { kind: "component", type: ChainResultViewComponent, selector: "gve-chain-result-view", inputs: ["result"], outputs: ["stepPick"] }, { kind: "component", type: LnHeightsEditorComponent, selector: "gve-ln-heights-editor", inputs: ["lineCount", "heights"], outputs: ["heightsChange"] }, { kind: "component", type: AnimationTimelineSetComponent, selector: "gve-animation-timeline-set", inputs: ["timelines", "elementIds", "tags"], outputs: ["timelinesChange", "cancel"] }] }); }
819
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: SnapshotEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i2.GveApiService }, { token: i3.DialogService }, { token: i4.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component }); }
820
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: SnapshotEditorComponent, isStandalone: true, selector: "gve-snapshot-editor", inputs: { snapshot: "snapshot", batchOps: "batchOps", noSave: "noSave", debug: "debug" }, outputs: { snapshotChange: "snapshotChange", snapshotCancel: "snapshotCancel" }, viewQueries: [{ propertyName: "snapshotView", first: true, predicate: ["snapshotView"], descendants: true }], ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>article</mat-icon> <span class=\"label\">text</span>\r\n </ng-template>\r\n <mat-expansion-panel [expanded]=\"!baseText.value\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-base-text-editor\r\n [text]=\"baseText.value\"\r\n (textChange)=\"onTextChange($event)\"\r\n />\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div class=\"boxed\">\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount\"\r\n [heights]=\"lnHeights.value\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>edit</mat-icon> <span class=\"label\">operations</span>\r\n </ng-template>\r\n\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary right\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [ngClass]=\"{ selected: operation.id === resultOperationId }\"\r\n [ngClass]=\"{ edited: operation.id === editedOp?.id }\"\r\n >\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n <mat-expansion-panel [expanded]=\"editedOp\" [disabled]=\"!editedOp\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [hidePreview]=\"editedOpIndex === -1\"\r\n [operation]=\"editedOp\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- batch ops -->\r\n <div>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>batch operations</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <div id=\"batch-container\">\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"inputOps\"\r\n placeholder=\"operations\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy\"\r\n (click)=\"clearOperations()\"\r\n >\r\n clear\r\n </button>\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text and add results to the operations\"\r\n [disabled]=\"!inputOps.value || busy\"\r\n (click)=\"parseOperations()\"\r\n >\r\n batch add\r\n </button>\r\n @if (parseError) {\r\n <span class=\"error\">{{ parseError }}</span>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>&gt;[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>&gt;]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong>&lt;&gt;</strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or\r\n output tags, separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>&#x40;</code> to AT to use character\r\n indexes (0-N) rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>,\r\n separated by space, where:\r\n </li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove\r\n feature (no value). Suffixes:\r\n <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple),\r\n <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </ul>\r\n </div>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>image</mat-icon> <span class=\"label\">image</span>\r\n </ng-template>\r\n\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img alt=\"background\" [src]=\"imageUrl.value\" width=\"600\" />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>animation</mat-icon> <span class=\"label\">animation</span>\r\n </ng-template>\r\n\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags\"\r\n [elementIds]=\"opElementIds\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- progress -->\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"busy\" />\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n [initialStepIndex]=\"initialStepIndex\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- snapshot view -->\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n </legend>\r\n <gve-snapshot-view\r\n #snapshotView\r\n [debug]=\"debug\"\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div>\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row *.right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}div#batch-container{display:grid;gap:16px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"batch-input batch-help\"}div#batch-input{grid-area:batch-input}div#batch-help{grid-area:batch-help}div#batch-help strong{color:#ff8c00}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}.boxed{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}span.label{margin-left:8px}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}@media only screen and (max-width: 959px){div#batch-container{grid-template-columns:1fr;grid-template-areas:\"batch-input\" \"batch-help\"}div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { 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.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "component", type: i7.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i11.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: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i12.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i13.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i13.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i13.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i14.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: NgToolsModule }, { kind: "pipe", type: i15.FlatLookupPipe, name: "flatLookup" }, { kind: "component", type: BaseTextEditorComponent, selector: "gve-base-text-editor", inputs: ["text"], outputs: ["textChange"] }, { kind: "component", type: ChainOperationEditorComponent, selector: "gve-chain-operation-editor", inputs: ["operation", "snapshot", "hidePreview"], outputs: ["operationChange", "operationPreview", "operationCancel"] }, { kind: "component", type: ChainResultViewComponent, selector: "gve-chain-result-view", inputs: ["result", "initialStepIndex"], outputs: ["stepPick"] }, { kind: "component", type: LnHeightsEditorComponent, selector: "gve-ln-heights-editor", inputs: ["lineCount", "heights"], outputs: ["heightsChange"] }, { kind: "component", type: AnimationTimelineSetComponent, selector: "gve-animation-timeline-set", inputs: ["timelines", "elementIds", "tags"], outputs: ["timelinesChange", "timelinesCancel"] }] }); }
521
821
  }
522
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: SnapshotEditorComponent, decorators: [{
822
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: SnapshotEditorComponent, decorators: [{
523
823
  type: Component,
524
824
  args: [{ selector: 'gve-snapshot-editor', standalone: true, imports: [
525
825
  CommonModule,
@@ -543,16 +843,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImpor
543
843
  ChainResultViewComponent,
544
844
  LnHeightsEditorComponent,
545
845
  AnimationTimelineSetComponent,
546
- ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab label=\"text\">\r\n <mat-expansion-panel [expanded]=\"!baseText.value\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-base-text-editor\r\n [text]=\"baseText.value\"\r\n (textChange)=\"onTextChange($event)\"\r\n />\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div>\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount\"\r\n [heights]=\"lnHeights.value\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab label=\"operations\">\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary right\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [ngClass]=\"{ selected: operation.id === resultOperationId }\"\r\n [ngClass]=\"{ edited: operation.id === editedOp?.id }\"\r\n >\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n <mat-expansion-panel [expanded]=\"editedOp\" [disabled]=\"!editedOp\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [operation]=\"editedOp\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"busy\" />\r\n </div>\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- batch ops -->\r\n <div>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>batch operations</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <div id=\"batch-container\">\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"inputOps\"\r\n placeholder=\"operations\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy\"\r\n (click)=\"clearOperations()\"\r\n >\r\n clear\r\n </button>\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text and add results to the operations\"\r\n [disabled]=\"!inputOps.value || busy\"\r\n (click)=\"parseOperations()\"\r\n >\r\n batch add\r\n </button>\r\n @if (parseError) {\r\n <span class=\"error\">{{ parseError }}</span>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>&gt;[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>&gt;]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong>&lt;&gt;</strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or\r\n output tags, separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>&#x40;</code> to AT to use character\r\n indexes (0-N) rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>,\r\n separated by space, where:\r\n </li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove\r\n feature (no value). Suffixes:\r\n <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple),\r\n <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </ul>\r\n </div>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </div>\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab label=\"image\">\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img alt=\"background\" [src]=\"imageUrl.value\" width=\"600\" />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab label=\"animation\">\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags\"\r\n [elementIds]=\"opElementIds\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- preview -->\r\n @if (snapshot) {\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n <button\r\n color=\"primary\"\r\n mat-icon-button\r\n type=\"button\"\r\n matTooltip=\"Refresh preview\"\r\n (click)=\"updateViewData()\"\r\n >\r\n <mat-icon class=\"mat-primary\">refresh</mat-icon>\r\n </button>\r\n </legend>\r\n <gve-snapshot-view\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div>\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid || form.pristine\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row *.right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}div#batch-container{display:grid;gap:16px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"batch-input batch-help\"}div#batch-input{grid-area:batch-input}div#batch-help{grid-area:batch-help}div#batch-help strong{color:#ff8c00}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}@media only screen and (max-width: 959px){div#batch-container{grid-template-columns:1fr;grid-template-areas:\"batch-input\" \"batch-help\"}div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"] }]
547
- }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.GveApiService }, { type: i3.DialogService }, { type: i4.MatSnackBar }], propDecorators: { snapshot: [{
846
+ ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <mat-tab-group>\r\n <!-- text -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>article</mat-icon> <span class=\"label\">text</span>\r\n </ng-template>\r\n <mat-expansion-panel [expanded]=\"!baseText.value\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title> base text </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-base-text-editor\r\n [text]=\"baseText.value\"\r\n (textChange)=\"onTextChange($event)\"\r\n />\r\n <fieldset>\r\n <div class=\"form-row\">\r\n <!-- offsetX -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetX\"\r\n placeholder=\"X offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- offsetY -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"offsetY\"\r\n placeholder=\"Y offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- lineHeightOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>ln h-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"lineHeightOffset\"\r\n placeholder=\"ln h-offset\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- charSpacingOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>char spacing</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"charSpacingOffset\"\r\n placeholder=\"char spacing\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- spcWidthOffset -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>spc w-offset</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"spcWidthOffset\"\r\n placeholder=\"spc w-offset\"\r\n />\r\n </mat-form-field>\r\n <!-- minLineHeights -->\r\n <div class=\"boxed\">\r\n <gve-ln-heights-editor\r\n [lineCount]=\"lineCount\"\r\n [heights]=\"lnHeights.value\"\r\n (heightsChange)=\"onHeightsChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n <!-- textStyle -->\r\n <div>\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>text style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"textStyle\"\r\n placeholder=\"text style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- operations -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>edit</mat-icon> <span class=\"label\">operations</span>\r\n </ng-template>\r\n\r\n <div id=\"snapshot-container\">\r\n <div id=\"general\">\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"width\"\r\n placeholder=\"width\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"height\"\r\n placeholder=\"height\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- add op -->\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary right\"\r\n [disabled]=\"!baseText.value\"\r\n (click)=\"editNewOperation()\"\r\n >\r\n <mat-icon>add_circle</mat-icon> operation\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- ops -->\r\n <div id=\"ops\">\r\n <!-- operations list -->\r\n @if (operations.value.length) {\r\n <table id=\"list\">\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>ID</th>\r\n <th>type</th>\r\n <th>at</th>\r\n <th>run</th>\r\n <th>value</th>\r\n <th>itag</th>\r\n <th>otag</th>\r\n <th>gid</th>\r\n <th>feats</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (operation of operations.value; track operation.id; let\r\n index=$index) {\r\n <tr\r\n [ngClass]=\"{ selected: operation.id === resultOperationId }\"\r\n [ngClass]=\"{ edited: operation.id === editedOp?.id }\"\r\n >\r\n <td class=\"fit-width\">\r\n <!-- edit -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-primary\"\r\n (click)=\"editOperation(index)\"\r\n matTooltip=\"Edit operation\"\r\n >\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <!-- delete -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-warn\"\r\n (click)=\"deleteOperation(index)\"\r\n matTooltip=\"Delete operation\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <!-- run to -->\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n class=\"mat-accent\"\r\n (click)=\"runTo(index)\"\r\n matTooltip=\"Run to this operation\"\r\n >\r\n <mat-icon class=\"mat-accent\">subscriptions</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ operation.id }}</td>\r\n <td>{{ operation.type | flatLookup : opTypeMap }}</td>\r\n <td>{{ operation.at }}</td>\r\n <td>{{ operation.run }}</td>\r\n <td>{{ operation.value }}</td>\r\n <td>{{ operation.inputTag }}</td>\r\n <td>{{ operation.outputTag }}</td>\r\n <td>{{ operation.groupId }}</td>\r\n <td>{{ operation.features?.length }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n\r\n <!-- operation editor -->\r\n <mat-expansion-panel [expanded]=\"editedOp\" [disabled]=\"!editedOp\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>operation {{ editedOp?.id }}</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <gve-chain-operation-editor\r\n [hidePreview]=\"editedOpIndex === -1\"\r\n [operation]=\"editedOp\"\r\n (operationCancel)=\"onOperationCancel()\"\r\n (operationChange)=\"onOperationChange($event)\"\r\n (operationPreview)=\"onOperationPreview($event)\"\r\n />\r\n </fieldset>\r\n </mat-expansion-panel>\r\n\r\n <!-- opStyle -->\r\n <div id=\"opStyle\">\r\n <mat-form-field class=\"long-text\" appearance=\"outline\">\r\n <mat-label>operations style</mat-label>\r\n <textarea\r\n matInput\r\n [formControl]=\"opStyle\"\r\n placeholder=\"operations style\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- batch ops -->\r\n <div>\r\n <mat-expansion-panel>\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>batch operations</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <fieldset>\r\n <div id=\"batch-container\">\r\n <div id=\"batch-input\">\r\n <div>\r\n <mat-form-field class=\"full-width\">\r\n <mat-label>operations</mat-label>\r\n <textarea\r\n class=\"code\"\r\n matInput\r\n [formControl]=\"inputOps\"\r\n placeholder=\"operations\"\r\n rows=\"8\"\r\n spellcheck=\"false\"\r\n ></textarea>\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Remove all the operations\"\r\n [disabled]=\"!operations.value.length || busy\"\r\n (click)=\"clearOperations()\"\r\n >\r\n clear\r\n </button>\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Parse text and add results to the operations\"\r\n [disabled]=\"!inputOps.value || busy\"\r\n (click)=\"parseOperations()\"\r\n >\r\n batch add\r\n </button>\r\n @if (parseError) {\r\n <span class=\"error\">{{ parseError }}</span>\r\n }\r\n </div>\r\n </div>\r\n <div id=\"batch-help\">\r\n <ul>\r\n <li>\r\n <strong>replace</strong>:\r\n <code>ATxRUN<strong>=</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>delete</strong>:\r\n <code>ATxRUN<strong>-</strong></code>\r\n </li>\r\n <li>\r\n <strong>add-before</strong>:\r\n <code>ATxRUN<strong>+[</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>add-after</strong>:\r\n <code>ATxRUN<strong>+]</strong>\"VALUE\"</code>\r\n </li>\r\n <li>\r\n <strong>move-before</strong>:\r\n <code>ATxRUN<strong>&gt;[</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>move-after</strong>:\r\n <code>ATxRUN<strong>&gt;]</strong>TO</code>\r\n </li>\r\n <li>\r\n <strong>swap</strong>:\r\n <code>ATxRUN<strong>&lt;&gt;</strong>TOxRUN</code>\r\n </li>\r\n <li>\r\n <strong>annotate</strong>:\r\n <code>ATxRUN<strong>:</strong></code>\r\n </li>\r\n </ul>\r\n <p>For all the operations:</p>\r\n <ul>\r\n <li>\r\n prefix <code>(ITAG:OTAG)</code> to define input and/or\r\n output tags, separated by colon.\r\n </li>\r\n <li>\r\n prepend <code>&#x40;</code> to AT to use character\r\n indexes (0-N) rather than IDs.\r\n </li>\r\n <li>RUN (where applicable) defaults to 1.</li>\r\n <li>\r\n append features like <code>[NAME OPERATOR VALUE]</code>,\r\n separated by space, where:\r\n </li>\r\n <ol>\r\n <li>\r\n NAME is an arbitrary string. Prefixes:\r\n <code>*</code>=global features, <code>!</code>=remove\r\n feature (no value). Suffixes:\r\n <code>^</code>=short-lived (like\r\n <code>*version^=alpha</code>).\r\n </li>\r\n <li>\r\n OPERATOR is <code>=</code> (multiple),\r\n <code>:=</code> (single),\r\n <code>==</code> (first-single).\r\n </li>\r\n <li>\r\n VALUE is a string. If it includes spaces, wrap it in\r\n <code>\"\"</code>.\r\n </li>\r\n </ol>\r\n </ul>\r\n </div>\r\n </div>\r\n </fieldset>\r\n </mat-expansion-panel>\r\n </div>\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- image -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>image</mat-icon> <span class=\"label\">image</span>\r\n </ng-template>\r\n\r\n <div id=\"image\">\r\n <div id=\"image-ctl\">\r\n <!-- url -->\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>URL</mat-label>\r\n <input matInput [formControl]=\"imageUrl\" />\r\n </mat-form-field>\r\n <div class=\"form-row\">\r\n <!-- x -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>X</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageX\"\r\n placeholder=\"X\"\r\n />\r\n </mat-form-field>\r\n <!-- y -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>Y</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [formControl]=\"imageY\"\r\n placeholder=\"Y\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- width -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>width</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageWidth\"\r\n />\r\n </mat-form-field>\r\n <!-- height -->\r\n <mat-form-field class=\"input-nr\">\r\n <mat-label>height</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n min=\"0\"\r\n [formControl]=\"imageHeight\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n <!-- defs -->\r\n <div>\r\n <mat-form-field class=\"long-text\">\r\n <mat-label>defs</mat-label>\r\n <textarea matInput [formControl]=\"defs\" rows=\"3\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n <div id=\"image-view\">\r\n @if (imageUrl.value) {\r\n <img alt=\"background\" [src]=\"imageUrl.value\" width=\"600\" />\r\n }\r\n </div>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- timelines -->\r\n <mat-tab>\r\n <ng-template mat-tab-label>\r\n <mat-icon>animation</mat-icon> <span class=\"label\">animation</span>\r\n </ng-template>\r\n\r\n <gve-animation-timeline-set\r\n [tags]=\"opTags\"\r\n [elementIds]=\"opElementIds\"\r\n [timelines]=\"timelines.value\"\r\n (timelinesChange)=\"onTimelinesChange($event)\"\r\n />\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- progress -->\r\n <div>\r\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"busy\" />\r\n </div>\r\n\r\n <!-- result -->\r\n @if (result) {\r\n <fieldset id=\"result\">\r\n <legend>result</legend>\r\n <gve-chain-result-view\r\n [result]=\"result\"\r\n [initialStepIndex]=\"initialStepIndex\"\r\n (stepPick)=\"onStepPick($event)\"\r\n />\r\n </fieldset>\r\n }\r\n\r\n <!-- snapshot view -->\r\n <fieldset id=\"preview\">\r\n <legend class=\"button-row\">\r\n <span>{{ viewTitle }}</span>\r\n </legend>\r\n <gve-snapshot-view\r\n #snapshotView\r\n [debug]=\"debug\"\r\n [data]=\"viewData\"\r\n (snapshotRender)=\"onSnapshotRender($any($event))\"\r\n (visualEvent)=\"onVisualEvent($any($event))\"\r\n />\r\n <div>\r\n <mat-button-toggle\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Toggle rulers\"\r\n [checked]=\"rulers\"\r\n (change)=\"toggleRulers()\"\r\n >\r\n <mat-icon class=\"mat-primary\">straighten</mat-icon>\r\n </mat-button-toggle>\r\n </div>\r\n @if (visualInfo) {\r\n <div id=\"visual-info\">{{ visualInfo }}</div>\r\n }\r\n </fieldset>\r\n\r\n <!--buttons -->\r\n <div class=\"form-row-center\">\r\n <button\r\n type=\"button\"\r\n class=\"mat-warn\"\r\n mat-flat-button\r\n matTooltip=\"Discard changes\"\r\n (click)=\"close()\"\r\n >\r\n <mat-icon>clear</mat-icon>\r\n close\r\n </button>\r\n @if (!noSave) {\r\n <button\r\n type=\"submit\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save changes\"\r\n [disabled]=\"form.invalid\"\r\n >\r\n <mat-icon>check_circle</mat-icon>\r\n save\r\n </button>\r\n }\r\n </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row-center{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}.form-row,.form-row-center *{flex:0 0 auto}.form-row *.right{margin-left:auto}.button-row{display:flex;align-items:center;flex-wrap:wrap}.button-row *{flex:0 0 auto}.long-text{width:100%;max-width:800px}#text-range{margin:8px;border:1px solid silver;border-radius:6px;padding:6px}mat-expansion-panel{margin:8px 0}div#visual-info{font-size:95%;color:#909090;margin:8px}div#batch-container{display:grid;gap:16px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"batch-input batch-help\"}div#batch-input{grid-area:batch-input}div#batch-help{grid-area:batch-help}div#batch-help strong{color:#ff8c00}#list{margin:8px 0}#opStyle{margin-top:8px}table{width:100%;border-collapse:collapse}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr.selected{background-color:#c8d9eb}tr.edited{background-color:#f6f6e4}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:#909090}.error{color:red}.input-nr{width:6em}.full-width{width:100%}.code{font-family:Courier New,Courier,monospace}.boxed{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}span.label{margin-left:8px}gve-animation-timeline-set{margin:8px 0}div#image{display:grid;gap:8px;grid-template-rows:auto;grid-template-columns:1fr auto;grid-template-areas:\"image-ctl image-view\"}div#image-ctl{grid-area:image-ctl}div#image-view{grid-area:image-view}@media only screen and (max-width: 959px){div#batch-container{grid-template-columns:1fr;grid-template-areas:\"batch-input\" \"batch-help\"}div#image{grid-template-columns:1fr;grid-template-areas:\"image-ctl\" \"image-view\"}}\n"] }]
847
+ }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.GveApiService }, { type: i3.DialogService }, { type: i4.MatSnackBar }], propDecorators: { snapshotView: [{
848
+ type: ViewChild,
849
+ args: ['snapshotView', { static: false }]
850
+ }], snapshot: [{
548
851
  type: Input
549
852
  }], batchOps: [{
550
853
  type: Input
551
854
  }], noSave: [{
552
855
  type: Input
856
+ }], debug: [{
857
+ type: Input
553
858
  }], snapshotChange: [{
554
859
  type: Output
555
860
  }], snapshotCancel: [{
556
861
  type: Output
557
862
  }] } });
558
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcHNob3QtZWRpdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9zbmFwc2hvdC1lZGl0b3Ivc25hcHNob3QtZWRpdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9zbmFwc2hvdC1lZGl0b3Ivc25hcHNob3QtZWRpdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFFTCxXQUFXLEVBRVgsV0FBVyxFQUNYLG1CQUFtQixFQUNuQixVQUFVLEdBQ1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFL0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxF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LENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQztZQUM1QyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQztZQUNwRCxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQztZQUN6RCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztZQUM3RCxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDL0QsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsTUFB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TTtnQkFPUyxjQUFjO3NCQUQ3QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDVVNUT01fRUxFTUVOVFNfU0NIRU1BLFxyXG4gIENvbXBvbmVudCxcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtcclxuICBGb3JtQnVpbGRlcixcclxuICBGb3JtQ29udHJvbCxcclxuICBGb3JtR3JvdXAsXHJcbiAgRm9ybXNNb2R1bGUsXHJcbiAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcclxuICBWYWxpZGF0b3JzLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuXHJcbmltcG9ydCB7IE1hdEJ1dHRvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XHJcbmltcG9ydCB7IE1hdEJ1dHRvblRvZ2dsZU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbi10b2dnbGUnO1xyXG5pbXBvcnQgeyBNYXRDaGVja2JveE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NoZWNrYm94JztcclxuaW1wb3J0IHsgTWF0RXhwYW5zaW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZXhwYW5zaW9uJztcclxuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XHJcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcclxuaW1wb3J0IHsgTWF0SW5wdXRNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XHJcbmltcG9ydCB7IE1hdFByb2dyZXNzQmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvcHJvZ3Jlc3MtYmFyJztcclxuaW1wb3J0IHsgTWF0U25hY2tCYXIsIE1hdFNuYWNrQmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc25hY2stYmFyJztcclxuaW1wb3J0IHsgTWF0VGFic01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYnMnO1xyXG5pbXBvcnQgeyBNYXRUb29sdGlwTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XHJcblxyXG5pbXBvcnQgeyBjdXN0b21BbHBoYWJldCB9IGZyb20gJ25hbm9pZCc7XHJcblxyXG5pbXBvcnQgeyBOZ1Rvb2xzTW9kdWxlLCBkZWVwQ29weSB9IGZyb20gJ0BteXJtaWRvbi9uZy10b29scyc7XHJcbmltcG9ydCB7IERpYWxvZ1NlcnZpY2UgfSBmcm9tICdAbXlybWlkb24vbmctbWF0LXRvb2xzJztcclxuXHJcbmltcG9ydCB7XHJcbiAgQ2hhckNoYWluT3BlcmF0aW9uLFxyXG4gIENoYXJOb2RlLFxyXG4gIERFRkFVTFRfU1ZHX0JBU0VfVEVYVF9PUFRJT05TLFxyXG4gIEZlYXR1cmUsXHJcbiAgR3ZlQW5pbWF0aW9uVGltZWxpbmUsXHJcbiAgR3ZlVmlzdWFsRXZlbnQsXHJcbiAgU25hcHNob3QsXHJcbiAgU25hcHNob3RWaWV3RGF0YSxcclxuICBTbmFwc2hvdFZpZXdSZW5kZXJFdmVudCxcclxuICBTbmFwc2hvdFZpZXdTZXJ2aWNlLFxyXG59IGZyb20gJ0BteXJtaWRvbi9ndmUtc25hcHNob3Qtdmlldyc7XHJcblxyXG5pbXBvcnQge1xyXG4gIEJhc2VUZXh0Vmlld0NvbXBvbmVudCxcclxuICBWYXJCYXNlVGV4dFJhbmdlLFxyXG59IGZyb20gJy4uL2Jhc2UtdGV4dC12aWV3L2Jhc2UtdGV4dC12aWV3LmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IENoYWluT3BlcmF0aW9uRWRpdG9yQ29tcG9uZW50IH0gZnJvbSAnLi4vY2hhaW4tb3BlcmF0aW9uLWVkaXRvci9jaGFpbi1vcGVyYXRpb24tZWRpdG9yLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7XHJcbiAgQ2hhaW5PcGVyYXRpb25Db250ZXh0U3RlcCxcclxuICBDaGFyQ2hhaW5SZXN1bHQsXHJcbiAgR3ZlQXBpU2VydmljZSxcclxufSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9ndmUtYXBpLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBDaGFpblJlc3VsdFZpZXdDb21wb25lbnQgfSBmcm9tICcuLi9jaGFpbi1yZXN1bHQtdmlldy9jaGFpbi1yZXN1bHQtdmlldy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBMbkhlaWdodHNFZGl0b3JDb21wb25lbnQgfSBmcm9tICcuLi9sbi1oZWlnaHRzLWVkaXRvci9sbi1oZWlnaHRzLWVkaXRvci5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBCYXNlVGV4dEVkaXRvckNvbXBvbmVudCB9IGZyb20gJy4uL2Jhc2UtdGV4dC1lZGl0b3IvYmFzZS10ZXh0LWVkaXRvci5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBBbmltYXRpb25UaW1lbGluZVNldENvbXBvbmVudCB9IGZyb20gJy4uL2FuaW1hdGlvbi10aW1lbGluZS1zZXQvYW5pbWF0aW9uLXRpbWVsaW5lLXNldC5jb21wb25lbnQnO1xyXG5cclxuY29uc3QgVklFV19USVRMRSA9ICdwcmV2aWV3JztcclxuXHJcbi8qKlxyXG4gKiBBIGNvbXBvbmVudCB0byBlZGl0IGEgdGV4dCBzbmFwc2hvdC5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZ3ZlLXNuYXBzaG90LWVkaXRvcicsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXHJcbiAgICBDb21tb25Nb2R1bGUsXHJcbiAgICBGb3Jtc01vZHVsZSxcclxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Nb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Ub2dnbGVNb2R1bGUsXHJcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcclxuICAgIE1hdEV4cGFuc2lvbk1vZHVsZSxcclxuICAgIE1hdEZvcm1GaWVsZE1vZHVsZSxcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRJbnB1dE1vZHVsZSxcclxuICAgIE1hdFByb2dyZXNzQmFyTW9kdWxlLFxyXG4gICAgTWF0U25hY2tCYXJNb2R1bGUsXHJcbiAgICBNYXRUYWJzTW9kdWxlLFxyXG4gICAgTWF0VG9vbHRpcE1vZHVsZSxcclxuICAgIE5nVG9vbHNNb2R1bGUsXHJcbiAgICBCYXNlVGV4dEVkaXRvckNvbXBvbmVudCxcclxuICAgIEJhc2VUZXh0Vmlld0NvbXBvbmVudCxcclxuICAgIENoYWluT3BlcmF0aW9uRWRpdG9yQ29tcG9uZW50LFxyXG4gICAgQ2hhaW5SZXN1bHRWaWV3Q29tcG9uZW50LFxyXG4gICAgTG5IZWlnaHRzRWRpdG9yQ29tcG9uZW50LFxyXG4gICAgQW5pbWF0aW9uVGltZWxpbmVTZXRDb21wb25lbnQsXHJcbiAgXSxcclxuICBzY2hlbWFzOiBbQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQV0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3NuYXBzaG90LWVkaXRvci5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3NuYXBzaG90LWVkaXRvci5jb21wb25lbnQuY3NzJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIFNuYXBzaG90RWRpdG9yQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICBwcml2YXRlIHJlYWRvbmx5IF9uYW5vaWQgPSBjdXN0b21BbHBoYWJldCgnMTIzNDU2Nzg5MGFiY2RlZicsIDEwKTtcclxuICBwcml2YXRlIF9zbmFwc2hvdD86IFNuYXBzaG90O1xyXG4gIHByaXZhdGUgX3JlbmRlcmVyPzogU25hcHNob3RWaWV3U2VydmljZTtcclxuICBwcml2YXRlIF9wcmV2aWV3aW5nPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIHNuYXBzaG90IHRvIGVkaXQuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgZ2V0IHNuYXBzaG90KCk6IFNuYXBzaG90IHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl9zbmFwc2hvdDtcclxuICB9XHJcbiAgcHVibGljIHNldCBzbmFwc2hvdCh2YWx1ZTogU25hcHNob3QgfCB1bmRlZmluZWQgfCBudWxsKSB7XHJcbiAgICBpZiAodGhpcy5fc25hcHNob3QgPT09IHZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuX3NuYXBzaG90ID0gdmFsdWUgfHwgdW5kZWZpbmVkO1xyXG4gICAgdGhpcy51cGRhdGVGb3JtKHRoaXMuX3NuYXBzaG90KTtcclxuICAgIHRoaXMudXBkYXRlVmlld0RhdGEoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSBiYXRjaCBvcGVyYXRpb25zIHRleHQgdG8gc2V0IGZvciB0aGUgZWRpdG9yLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGJhdGNoT3BzPzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBUcnVlIHRvIGRpc2FibGUgc2F2aW5nLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIG5vU2F2ZT86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgdXNlciBzYXZlcyB0aGUgZWRpdGVkIHNuYXBzaG90LlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKVxyXG4gIHB1YmxpYyByZWFkb25seSBzbmFwc2hvdENoYW5nZTogRXZlbnRFbWl0dGVyPFNuYXBzaG90PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRW1pdHRlZCB3aGVuIHRoZSB1c2VyIGNhbmNlbHMgdGhlIHNuYXBzaG90IGVkaXRpbmcuXHJcbiAgICovXHJcbiAgQE91dHB1dCgpXHJcbiAgcHVibGljIHJlYWRvbmx5IHNuYXBzaG90Q2FuY2VsID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICAvLyBnZW5lcmFsXHJcbiAgcHVibGljIHdpZHRoOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBoZWlnaHQ6IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIHN0eWxlOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcclxuICAvLyBiYXNlIHRleHRcclxuICBwdWJsaWMgYmFzZVRleHQ6IEZvcm1Db250cm9sPENoYXJOb2RlW10gfCBzdHJpbmc+O1xyXG4gIHB1YmxpYyBvZmZzZXRYOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBvZmZzZXRZOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBsaW5lSGVpZ2h0T2Zmc2V0OiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBsbkhlaWdodHM6IEZvcm1Db250cm9sPFJlY29yZDxudW1iZXIsIG51bWJlcj4gfCBudWxsPjtcclxuICBwdWJsaWMgY2hhclNwYWNpbmdPZmZzZXQ6IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIHNwY1dpZHRoT2Zmc2V0OiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyB0ZXh0U3R5bGU6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIC8vIG9wZXJhdGlvbnNcclxuICBwdWJsaWMgb3BlcmF0aW9uczogRm9ybUNvbnRyb2w8Q2hhckNoYWluT3BlcmF0aW9uW10+O1xyXG4gIHB1YmxpYyBpbnB1dE9wczogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XHJcbiAgcHVibGljIG9wU3R5bGU6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBmb3JtOiBGb3JtR3JvdXA7XHJcbiAgLy8gaW1hZ2UgYW5kIGRlZnNcclxuICBwdWJsaWMgaW1hZ2VVcmw6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBpbWFnZU9wYWNpdHk6IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIGltYWdlWDogRm9ybUNvbnRyb2w8bnVtYmVyPjtcclxuICBwdWJsaWMgaW1hZ2VZOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBpbWFnZVdpZHRoOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBpbWFnZUhlaWdodDogRm9ybUNvbnRyb2w8bnVtYmVyPjtcclxuICBwdWJsaWMgZGVmczogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XHJcbiAgLy8gdGltZWxpbmVzXHJcbiAgcHVibGljIHRpbWVsaW5lczogRm9ybUNvbnRyb2w8R3ZlQW5pbWF0aW9uVGltZWxpbmVbXT47XHJcblxyXG4gIHB1YmxpYyB0ZXh0UmFuZ2U/OiBWYXJCYXNlVGV4dFJhbmdlO1xyXG4gIHB1YmxpYyBlZGl0ZWRPcD86IENoYXJDaGFpbk9wZXJhdGlvbjtcclxuICBwdWJsaWMgZWRpdGVkT3BJbmRleCA9IC0xO1xyXG5cclxuICBwdWJsaWMgb3BUYWdzOiBzdHJpbmdbXSA9IFtdO1xyXG4gIHB1YmxpYyBvcEVsZW1lbnRJZHM6IHN0cmluZ1tdID0gW107XHJcbiAgLy8gVE9ETzogYWRkIGNvZGUgdG8gdXBkYXRlIG9wVGFncyBhbmQgb3BFbGVtZW50SWRzXHJcblxyXG4gIHB1YmxpYyBidXN5PzogYm9vbGVhbjtcclxuICBwdWJsaWMgcGFyc2VFcnJvcj86IHN0cmluZztcclxuICBwdWJsaWMgb3BUeXBlTWFwID0ge1xyXG4gICAgMDogJ3JlcGxhY2UnLFxyXG4gICAgMTogJ2RlbGV0ZScsXHJcbiAgICAyOiAnYWRkLWJlZm9yZScsXHJcbiAgICAzOiAnYWRkLWFmdGVyJyxcclxuICAgIDQ6ICdtb3ZlLWJlZm9yZScsXHJcbiAgICA1OiAnbW92ZS1hZnRlcicsXHJcbiAgICA2OiAnc3dhcCcsXHJcbiAgICA3OiAnYW5ub3RhdGUnLFxyXG4gIH07XHJcbiAgcHVibGljIGxpbmVDb3VudCA9IDA7XHJcblxyXG4gIHB1YmxpYyB2aWV3VGl0bGUgPSBWSUVXX1RJVExFO1xyXG4gIHB1YmxpYyB2aWV3RGF0YT86IFNuYXBzaG90Vmlld0RhdGE7XHJcbiAgcHVibGljIHZpc3VhbEluZm8/OiBzdHJpbmc7XHJcbiAgcHVibGljIHJ1bGVycyA9IHRydWU7XHJcbiAgLy8gcnVuIHJlc3VsdFxyXG4gIHB1YmxpYyByZXN1bHQ/OiBDaGFyQ2hhaW5SZXN1bHQ7XHJcbiAgcHVibGljIHJlc3VsdE9wZXJhdGlvbklkPzogc3RyaW5nO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcclxuICAgIHByaXZhdGUgX2FwaTogR3ZlQXBpU2VydmljZSxcclxuICAgIHByaXZhdGUgX2RpYWxvZ1NlcnZpY2U6IERpYWxvZ1NlcnZpY2UsXHJcbiAgICBwcml2YXRlIF9zbmFja2JhcjogTWF0U25hY2tCYXJcclxuICApIHtcclxuICAgIC8vIGdlbmVyYWxcclxuICAgIHRoaXMud2lkdGggPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPig4MDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmhlaWdodCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDYwMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMuc3R5bGUgPSBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcbiAgICAvLyBiYXNlIHRleHRcclxuICAgIHRoaXMuYmFzZVRleHQgPSBuZXcgRm9ybUNvbnRyb2w8Q2hhck5vZGVbXSB8IHN0cmluZz4oW10sIHtcclxuICAgICAgbm9uTnVsbGFibGU6IHRydWUsXHJcbiAgICAgIHZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkXSxcclxuICAgIH0pO1xyXG4gICAgdGhpcy5vZmZzZXRYID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMub2Zmc2V0WSA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmxpbmVIZWlnaHRPZmZzZXQgPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPihcclxuICAgICAgREVGQVVMVF9TVkdfQkFTRV9URVhUX09QVElPTlMubGluZUhlaWdodE9mZnNldCxcclxuICAgICAgeyBub25OdWxsYWJsZTogdHJ1ZSB9XHJcbiAgICApO1xyXG4gICAgdGhpcy5sbkhlaWdodHMgPSBuZXcgRm9ybUNvbnRyb2w8UmVjb3JkPG51bWJlciwgbnVtYmVyPiB8IG51bGw+KG51bGwpO1xyXG4gICAgdGhpcy5jaGFyU3BhY2luZ09mZnNldCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLnNwY1dpZHRoT2Zmc2V0ID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMudGV4dFN0eWxlID0gbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG5cclxuICAgIC8vIG9wZXJhdGlvbnNcclxuICAgIHRoaXMub3BlcmF0aW9ucyA9IG5ldyBGb3JtQ29udHJvbDxDaGFyQ2hhaW5PcGVyYXRpb25bXT4oW10sIHtcclxuICAgICAgbm9uTnVsbGFibGU6IHRydWUsXHJcbiAgICB9KTtcclxuICAgIHRoaXMuaW5wdXRPcHMgPSBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcbiAgICB0aGlzLm9wU3R5bGUgPSBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcbiAgICAvLyBpbWFnZVxyXG4gICAgdGhpcy5pbWFnZVVybCA9IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuICAgIHRoaXMuaW1hZ2VPcGFjaXR5ID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oMSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMuaW1hZ2VYID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMuaW1hZ2VZID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMuaW1hZ2VXaWR0aCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmltYWdlSGVpZ2h0ID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMuZGVmcyA9IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuXHJcbiAgICAvLyB0aW1lbGluZXNcclxuICAgIHRoaXMudGltZWxpbmVzID0gbmV3IEZvcm1Db250cm9sPEd2ZUFuaW1hdGlvblRpbWVsaW5lW10+KFtdLCB7XHJcbiAgICAgIG5vbk51bGxhYmxlOiB0cnVlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgdGhpcy5mb3JtID0gZm9ybUJ1aWxkZXIuZ3JvdXAoe1xyXG4gICAgICB3aWR0aDogdGhpcy53aWR0aCxcclxuICAgICAgaGVpZ2h0OiB0aGlzLmhlaWdodCxcclxuICAgICAgc3R5bGU6IHRoaXMuc3R5bGUsXHJcbiAgICAgIGJhc2VUZXh0OiB0aGlzLmJhc2VUZXh0LFxyXG4gICAgICBvZmZzZXRYOiB0aGlzLm9mZnNldFgsXHJcbiAgICAgIG9mZnNldFk6IHRoaXMub2Zmc2V0WSxcclxuICAgICAgbGluZUhlaWdodE9mZnNldDogdGhpcy5saW5lSGVpZ2h0T2Zmc2V0LFxyXG4gICAgICBsbkhlaWdodHM6IHRoaXMubG5IZWlnaHRzLFxyXG4gICAgICBjaGFyU3BhY2luZ09mZnNldDogdGhpcy5jaGFyU3BhY2luZ09mZnNldCxcclxuICAgICAgc3BjV2lkdGhPZmZzZXQ6IHRoaXMuc3BjV2lkdGhPZmZzZXQsXHJcbiAgICAgIHRleHRTdHlsZTogdGhpcy50ZXh0U3R5bGUsXHJcbiAgICAgIG9wZXJhdGlvbnM6IHRoaXMub3BlcmF0aW9ucyxcclxuICAgICAgaW5wdXRPcHM6IHRoaXMuaW5wdXRPcHMsXHJcbiAgICAgIG9wU3R5bGU6IHRoaXMub3BTdHlsZSxcclxuICAgICAgLy8gaW1hZ2VcclxuICAgICAgaW1hZ2VVcmw6IHRoaXMuaW1hZ2VVcmwsXHJcbiAgICAgIGltYWdlT3BhY2l0eTogdGhpcy5pbWFnZU9wYWNpdHksXHJcbiAgICAgIGltYWdlWDogdGhpcy5pbWFnZVgsXHJcbiAgICAgIGltYWdlWTogdGhpcy5pbWFnZVksXHJcbiAgICAgIGltYWdlV2lkdGg6IHRoaXMuaW1hZ2VXaWR0aCxcclxuICAgICAgaW1hZ2VIZWlnaHQ6IHRoaXMuaW1hZ2VIZWlnaHQsXHJcbiAgICAgIGRlZnM6IHRoaXMuZGVmcyxcclxuICAgICAgLy8gdGltZWxpbmVzXHJcbiAgICAgIHRpbWVsaW5lczogdGhpcy50aW1lbGluZXMsXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmJhdGNoT3BzKSB7XHJcbiAgICAgIHRoaXMuaW5wdXRPcHMuc2V0VmFsdWUodGhpcy5iYXRjaE9wcyk7XHJcbiAgICAgIHRoaXMucGFyc2VPcGVyYXRpb25zKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgdXBkYXRlVmlld0RhdGEoXHJcbiAgICBuZXdPcGVyYXRpb24/OiBDaGFyQ2hhaW5PcGVyYXRpb24sXHJcbiAgICBzbmFwc2hvdD86IFNuYXBzaG90LFxyXG4gICAgdGl0bGUgPSBWSUVXX1RJVExFXHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zb2xlLmxvZygndXBkYXRlIHZpZXcgZGF0YScpO1xyXG4gICAgaWYgKCFzbmFwc2hvdCkge1xyXG4gICAgICBzbmFwc2hvdCA9IHRoaXMuZ2V0U25hcHNob3QoKTtcclxuICAgIH1cclxuICAgIC8vIHVwZGF0ZSBvciBhZGQgbmV3IG9wZXJhdGlvbiBpbiBjb3B5XHJcbiAgICBpZiAobmV3T3BlcmF0aW9uKSB7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gc25hcHNob3Qub3BlcmF0aW9ucy5maW5kSW5kZXgoXHJcbiAgICAgICAgKG9wKSA9PiBvcC5pZCA9PT0gbmV3T3BlcmF0aW9uLmlkXHJcbiAgICAgICk7XHJcbiAgICAgIGlmIChpbmRleCA+IC0xKSB7XHJcbiAgICAgICAgc25hcHNob3Qub3BlcmF0aW9ucy5zcGxpY2UoaW5kZXgsIDEsIG5ld09wZXJhdGlvbik7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgc25hcHNob3Qub3BlcmF0aW9ucy5wdXNoKG5ld09wZXJhdGlvbik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyB1cGRhdGUgdmlldyBkYXRhXHJcbiAgICB0aGlzLnZpZXdUaXRsZSA9IHRpdGxlO1xyXG4gICAgdGhpcy52aXN1YWxJbmZvID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy52aWV3RGF0YSA9IHtcclxuICAgICAgc25hcHNob3Q6IHNuYXBzaG90LFxyXG4gICAgICBvcHRpb25zOiB7XHJcbiAgICAgICAgLy8gZGVidWc6IHRydWUsXHJcbiAgICAgICAgZGVsYXllZFJlbmRlcjogdHJ1ZSxcclxuICAgICAgICBzaG93UnVsZXJzOiB0cnVlLFxyXG4gICAgICAgIHNob3dHcmlkOiB0cnVlLFxyXG4gICAgICAgIHBhblpvb206IHRydWUsXHJcbiAgICAgIH0sXHJcbiAgICB9O1xyXG4gICAgY29uc29sZS5sb2coYHZpZXcgZGF0YTogJHt0aGlzLnZpZXdEYXRhfWApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVGb3JtKHNuYXBzaG90OiBTbmFwc2hvdCB8IHVuZGVmaW5lZCkge1xyXG4gICAgaWYgKCFzbmFwc2hvdCkge1xyXG4gICAgICB0aGlzLmZvcm0ucmVzZXQoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMud2lkdGguc2V0VmFsdWUoc25hcHNob3Quc2l6ZS53aWR0aCk7XHJcbiAgICAgIHRoaXMuaGVpZ2h0LnNldFZhbHVlKHNuYXBzaG90LnNpemUuaGVpZ2h0KTtcclxuICAgICAgdGhpcy5zdHlsZS5zZXRWYWx1ZShzbmFwc2hvdC5zdHlsZSB8fCBudWxsKTtcclxuICAgICAgdGhpcy5pbWFnZVVybC5zZXRWYWx1ZShzbmFwc2hvdC5pbWFnZT8udXJsIHx8IG51bGwpO1xyXG4gICAgICB0aGlzLmltYWdlT3BhY2l0eS5zZXRWYWx1ZShzbmFwc2hvdC5pbWFnZT8ub3BhY2l0eSB8fCAwKTtcclxuICAgICAgdGhpcy5pbWFnZVguc2V0VmFsdWUoc25hcHNob3QuaW1hZ2U/LmNhbnZhcz8ueCB8fCAwKTtcclxuICAgICAgdGhpcy5pbWFnZVkuc2V0VmFsdWUoc25hcHNob3QuaW1hZ2U/LmNhbnZhcz8ueSB8fCAwKTtcclxuICAgICAgdGhpcy5pbWFnZVdpZHRoLnNldFZhbHVlKHNuYXBzaG90LmltYWdlPy5jYW52YXM/LndpZHRoIHx8IDApO1xyXG4gICAgICB0aGlzLmltYWdlSGVpZ2h0LnNldFZhbHVlKHNuYXBzaG90LmltYWdlPy5jYW52YXM/LmhlaWdodCB8fCAwKTtcclxuICAgICAgdGhpcy5kZWZzLnNldFZhbHVlKHNuYXBzaG90LmRlZnMgfHwgbnVsbCk7XHJcbiAgICAgIHRoaXMuYmFzZVRleHQuc2V0VmFsdWUoc25hcHNob3QudGV4dCk7XHJcbiAgICAgIHRoaXMub2Zmc2V0WC5zZXRWYWx1ZShzbmFwc2hvdC50ZXh0T3B0aW9ucz8ub2Zmc2V0Py54IHx8IDApO1xyXG4gICAgICB0aGlzLm9mZnNldFkuc2V0VmFsdWUoc25hcHNob3QudGV4dE9wdGlvbnM/Lm9mZnNldD8ueSB8fCAwKTtcclxuICAgICAgdGhpcy5saW5lSGVpZ2h0T2Zmc2V0LnNldFZhbHVlKHNuYXBzaG90LnRleHRPcHRpb25zPy5saW5lSGVpZ2h0T2Zmc2V0KTtcclxuICAgICAgdGhpcy5sbkhlaWdodHMuc2V0VmFsdWUoc25hcHNob3QudGV4dE9wdGlvbnM/Lm1pbkxpbmVIZWlnaHRzIHx8IG51bGwpO1xyXG4gICAgICB0aGlzLmNoYXJTcGFjaW5nT2Zmc2V0LnNldFZhbHVlKHNuYXBzaG90LnRleHRPcHRpb25zPy5jaGFyU3BhY2luZ09mZnNldCk7XHJcbiAgICAgIHRoaXMuc3BjV2lkdGhPZmZzZXQuc2V0VmFsdWUoc25hcHNob3QudGV4dE9wdGlvbnM/LnNwY1dpZHRoT2Zmc2V0KTtcclxuICAgICAgdGhpcy50ZXh0U3R5bGUuc2V0VmFsdWUoc25hcHNob3QudGV4dFN0eWxlIHx8IG51bGwpO1xyXG4gICAgICB0aGlzLm9wZXJhdGlvbnMuc2V0VmFsdWUoc25hcHNob3Qub3BlcmF0aW9ucyk7XHJcbiAgICAgIHRoaXMuaW5wdXRPcHMucmVzZXQoKTtcclxuICAgICAgdGhpcy5vcFN0eWxlLnNldFZhbHVlKHNuYXBzaG90Lm9wU3R5bGUgfHwgbnVsbCk7XHJcbiAgICAgIC8vIHRpbWVsaW5lc1xyXG4gICAgICBjb25zdCB0aW1lbGluZXM6IEd2ZUFuaW1hdGlvblRpbWVsaW5lW10gPSBbXTtcclxuICAgICAgaWYgKHNuYXBzaG90LnRpbWVsaW5lcykge1xyXG4gICAgICAgIGZvciAobGV0IHRhZyBpbiBzbmFwc2hvdC50aW1lbGluZXMpIHtcclxuICAgICAgICAgIHRpbWVsaW5lcy5wdXNoKHNuYXBzaG90LnRpbWVsaW5lc1t0YWddKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy50aW1lbGluZXMuc2V0VmFsdWUodGltZWxpbmVzKTtcclxuICAgIH1cclxuICAgIHRoaXMuZm9ybS5tYXJrQXNQcmlzdGluZSgpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGVkaXROZXdPcGVyYXRpb24oKSB7XHJcbiAgICB0aGlzLmVkaXRlZE9wID0ge1xyXG4gICAgICBpZDogdGhpcy5fbmFub2lkKCksXHJcbiAgICAgIHR5cGU6IDAsXHJcbiAgICAgIGF0OiB0aGlzLnRleHRSYW5nZT8uYXQgfHwgMCxcclxuICAgICAgcnVuOiB0aGlzLnRleHRSYW5nZT8ucnVuIHx8IDEsXHJcbiAgICB9O1xyXG4gICAgdGhpcy5lZGl0ZWRPcEluZGV4ID0gLTE7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZWRpdE9wZXJhdGlvbihpbmRleDogbnVtYmVyKSB7XHJcbiAgICB0aGlzLmVkaXRlZE9wSW5kZXggPSBpbmRleDtcclxuICAgIHRoaXMuZWRpdGVkT3AgPSBkZWVwQ29weSh0aGlzLm9wZXJhdGlvbnMudmFsdWVbaW5kZXhdKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY2xvc2VFZGl0ZWRPcCgpIHtcclxuICAgIHRoaXMuZWRpdGVkT3BJbmRleCA9IC0xO1xyXG4gICAgdGhpcy5lZGl0ZWRPcCA9IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvbk9wZXJhdGlvbkNhbmNlbCgpIHtcclxuICAgIHRoaXMuY2xvc2VFZGl0ZWRPcCgpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uT3BlcmF0aW9uQ2hhbmdlKG9wOiBDaGFyQ2hhaW5PcGVyYXRpb24pIHtcclxuICAgIGNvbnNvbGUubG9nKCdvcGVyYXRpb24gY2hhbmdlJyk7XHJcbiAgICBjb25zdCBvcGVyYXRpb25zID0gWy4uLnRoaXMub3BlcmF0aW9ucy52YWx1ZV07XHJcblxyXG4gICAgaWYgKHRoaXMuZWRpdGVkT3BJbmRleCA+IC0xKSB7XHJcbiAgICAgIG9wZXJhdGlvbnMuc3BsaWNlKHRoaXMuZWRpdGVkT3BJbmRleCwgMSwgb3ApO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgb3BlcmF0aW9ucy5wdXNoKG9wKTtcclxuICAgIH1cclxuICAgIHRoaXMub3BlcmF0aW9ucy5zZXRWYWx1ZShvcGVyYXRpb25zKTtcclxuICAgIHRoaXMub3BlcmF0aW9ucy5tYXJrQXNEaXJ0eSgpO1xyXG4gICAgdGhpcy5vcGVyYXRpb25zLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuXHJcbiAgICB0aGlzLmNsb3NlRWRpdGVkT3AoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBkZWxldGVPcGVyYXRpb24oaW5kZXg6IG51bWJlcikge1xyXG4gICAgdGhpcy5fZGlhbG9nU2VydmljZVxyXG4gICAgICAuY29uZmlybShcclxuICAgICAgICAnQ29uZmlybSBEZWxldGlvbicsXHJcbiAgICAgICAgYERlbGV0ZSBvcGVyYXRpb24gXCIke3RoaXMub3BlcmF0aW9ucy52YWx1ZVtpbmRleF0uaWR9XCI/YFxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKHllczogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgIGlmICh5ZXMpIHtcclxuICAgICAgICAgIGlmICh0aGlzLnJlc3VsdE9wZXJhdGlvbklkID09PSB0aGlzLm9wZXJhdGlvbnMudmFsdWVbaW5kZXhdLmlkKSB7XHJcbiAgICAgICAgICAgIHRoaXMucmVzdWx0T3BlcmF0aW9uSWQgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBjb25zdCBvcGVyYXRpb25zID0gWy4uLnRoaXMub3BlcmF0aW9ucy52YWx1ZV07XHJcbiAgICAgICAgICBvcGVyYXRpb25zLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMuc2V0VmFsdWUob3BlcmF0aW9ucyk7XHJcbiAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMubWFya0FzRGlydHkoKTtcclxuICAgICAgICAgIHRoaXMub3BlcmF0aW9ucy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvblRleHRDaGFuZ2UodGV4dDogQ2hhck5vZGVbXSkge1xyXG4gICAgY29uc29sZS5sb2coJ3RleHQgY2hhbmdlOiAnICsgdGV4dCk7XHJcbiAgICB0aGlzLmJhc2VUZXh0LnNldFZhbHVlKHRleHQpO1xyXG4gICAgdGhpcy5iYXNlVGV4dC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcbiAgICB0aGlzLmJhc2VUZXh0Lm1hcmtBc0RpcnR5KCk7XHJcbiAgICBpZiAoIXRleHQubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMubGluZUNvdW50ID0gMDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMubGluZUNvdW50ID0gdGV4dC5maWx0ZXIoKGMpID0+IGMuZGF0YSA9PT0gJ1xcbicpLmxlbmd0aCArIDE7XHJcbiAgICB9XHJcbiAgICB0aGlzLnRleHRSYW5nZSA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuY2xvc2VFZGl0ZWRPcCgpO1xyXG4gICAgdGhpcy5vcGVyYXRpb25zLnJlc2V0KCk7XHJcbiAgICB0aGlzLnVwZGF0ZVZpZXdEYXRhKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25SYW5nZVBpY2socmFuZ2U6IFZhckJhc2VUZXh0UmFuZ2UpIHtcclxuICAgIHRoaXMudGV4dFJhbmdlID0gcmFuZ2U7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgcGFyc2VPcGVyYXRpb25zKCkge1xyXG4gICAgaWYgKHRoaXMuYnVzeSB8fCAhdGhpcy5pbnB1dE9wcy52YWx1ZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLl9kaWFsb2dTZXJ2aWNlXHJcbiAgICAgIC5jb25maXJtKCdDb25maXJtJywgJ1BhcnNlIG9wZXJhdGlvbnM/JylcclxuICAgICAgLnN1YnNjcmliZSgoeWVzOiBib29sZWFuKSA9PiB7XHJcbiAgICAgICAgaWYgKHllcykge1xyXG4gICAgICAgICAgdGhpcy5idXN5ID0gdHJ1ZTtcclxuICAgICAgICAgIHRoaXMucGFyc2VFcnJvciA9IHVuZGVmaW5lZDtcclxuXHJcbiAgICAgICAgICB0aGlzLl9hcGkucGFyc2VPcGVyYXRpb25zKHRoaXMuaW5wdXRPcHMudmFsdWUhKS5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgICBuZXh0OiAod3JhcHBlcikgPT4ge1xyXG4gICAgICAgICAgICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBbLi4udGhpcy5vcGVyYXRpb25zLnZhbHVlXTtcclxuICAgICAgICAgICAgICBvcGVyYXRpb25zLnB1c2goLi4ud3JhcHBlci5yZXN1bHQhKTtcclxuICAgICAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMuc2V0VmFsdWUob3BlcmF0aW9ucyk7XHJcbiAgICAgICAgICAgICAgdGhpcy5vcGVyYXRpb25zLm1hcmtBc0RpcnR5KCk7XHJcbiAgICAgICAgICAgICAgdGhpcy5vcGVyYXRpb25zLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVZpZXdEYXRhKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSBlcnJvci5tZXNzYWdlO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMuYnVzeSA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBjbGVhck9wZXJhdGlvbnMoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9kaWFsb2dTZXJ2aWNlXHJcbiAgICAgIC5jb25maXJtKCdDb25maXJtJywgJ1JlbW92ZSBhbGwgb3BlcmF0aW9ucz8nKVxyXG4gICAgICAuc3Vic2NyaWJlKCh5ZXM6IGJvb2xlYW4pID0+IHtcclxuICAgICAgICBpZiAoeWVzKSB7XHJcbiAgICAgICAgICB0aGlzLnJlc3VsdE9wZXJhdGlvbklkID0gdW5kZWZpbmVkO1xyXG4gICAgICAgICAgdGhpcy5vcGVyYXRpb25zLnJlc2V0KCk7XHJcbiAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMubWFya0FzRGlydHkoKTtcclxuICAgICAgICAgIHRoaXMub3BlcmF0aW9ucy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcbiAgICAgICAgICB0aGlzLnVwZGF0ZVZpZXdEYXRhKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvbk9wZXJhdGlvblByZXZpZXcob3BlcmF0aW9uOiBDaGFyQ2hhaW5PcGVyYXRpb24pOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLl9wcmV2aWV3aW5nKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuX3ByZXZpZXdpbmcgPSB0cnVlO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHRoaXMudXBkYXRlVmlld0RhdGEob3BlcmF0aW9uKTtcclxuICAgICAgdGhpcy5fcHJldmlld2luZyA9IGZhbHNlO1xyXG4gICAgfSwgMCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgcnVuVG8oaW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLmdldFNuYXBzaG90KCk7XHJcbiAgICBpZiAoIXNuYXBzaG90LnRleHQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3Qgb3BlcmF0aW9ucyA9IHRoaXMub3BlcmF0aW9ucy52YWx1ZS5zbGljZSgwLCBpbmRleCArIDEpO1xyXG4gICAgdGhpcy5idXN5ID0gdHJ1ZTtcclxuICAgIHRoaXMuX2FwaS5ydW5PcGVyYXRpb25zKHNuYXBzaG90LnRleHQgYXMgQ2hhck5vZGVbXSwgb3BlcmF0aW9ucykuc3Vic2NyaWJlKHtcclxuICAgICAgbmV4dDogKHdyYXBwZXIpID0+IHtcclxuICAgICAgICBpZiAod3JhcHBlci5lcnJvcikge1xyXG4gICAgICAgICAgdGhpcy5fc25hY2tiYXIub3Blbih3cmFwcGVyLmVycm9yLCAnT0snKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5yZXN1bHQgPSB3cmFwcGVyLnJlc3VsdCE7XHJcbiAgICAgICAgLy8gVE9ETyB1cGRhdGUgdmlld1xyXG4gICAgICAgIC8vIHRoaXMudXBkYXRlVmlld0RhdGEoXHJcbiAgICAgICAgLy8gICB1bmRlZmluZWQsXHJcbiAgICAgICAgLy8gICBzbmFwc2hvdCxcclxuICAgICAgICAvLyAgIHRoaXMub3BlcmF0aW9ucy52YWx1ZVtpbmRleF0ub3V0cHV0VGFnXHJcbiAgICAgICAgLy8gKTtcclxuICAgICAgfSxcclxuICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgIHRoaXMuX3NuYWNrYmFyLm9wZW4oJ0Vycm9yIHJ1bm5pbmcgb3BlcmF0aW9ucycsICdPSycpO1xyXG4gICAgICB9LFxyXG4gICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgIHRoaXMuYnVzeSA9IGZhbHNlO1xyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25TdGVwUGljayhzdGVwOiBDaGFpbk9wZXJhdGlvbkNvbnRleHRTdGVwKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMucmVzdWx0KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMucmVzdWx0T3BlcmF0aW9uSWQgPSBzdGVwLm9wZXJhdGlvbi5pZDtcclxuXHJcbiAgICAvLyBnZXQgc25hcHNob3QgZm9yIHByZXZpZXcgYnkgdXBkYXRpbmcgaXRzIHRleHQgYW5kXHJcbiAgICAvLyByZW1vdmluZyBvcGVyYXRpb25zIHBhc3QgdGhlIGxhc3QgZXhlY3V0ZWRcclxuICAgIGNvbnN0IHN0ZXBOb2RlcyA9IHRoaXMucmVzdWx0LnRhZ2dlZE5vZGVzW3N0ZXAub3V0cHV0VGFnXTtcclxuXHJcbiAgICAvLyB3ZSBhbHdheXMgZGlzcGxheSB0aGUgb3JpZ2luYWwgYmFzZSB0ZXh0LCBqdXN0IHVwZGF0aW5nXHJcbiAgICAvLyBpdHMgbm9kZXMgZmVhdHVyZXMgdG8gdGhvc2Ugb2YgdGhlIHBpY2tlZCBzdGVwLCBhbmQgYWRkaW5nXHJcbiAgICAvLyBuZXcgbm9kZXMgaWYgdGhleSBhcmUgbm90IGluIHRoZSBvcmlnaW5hbCB0ZXh0LiBJdCBpcyBhc3N1bWVkXHJcbiAgICAvLyB0aGF0IHRoZXNlIG5ldyBub2RlcyBoYXZlIGEgbWFudWFsbHkgc2V0IHBvc2l0aW9uLlxyXG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLmdldFNuYXBzaG90KCk7XHJcbiAgICBjb25zdCBub2RlczogQ2hhck5vZGVbXSA9IGRlZXBDb3B5KHNuYXBzaG90LnRleHQgYXMgQ2hhck5vZGVbXSk7XHJcbiAgICBmb3IgKGNvbnN0IHNuIG9mIHN0ZXBOb2Rlcykge1xyXG4gICAgICBjb25zdCBpID0gbm9kZXMuZmluZEluZGV4KChuKSA9PiBuLmlkID09PSBzbi5pZCk7XHJcbiAgICAgIGlmIChpID4gLTEpIHtcclxuICAgICAgICBub2Rlc1tpXS5mZWF0dXJlcyA9IHNuLmZlYXR1cmVzO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIG5vZGVzLnB1c2goc24pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZmluZCBtYXggSUQgaW4gc25hcHNob3QudGV4dCAoPW9yaWdpbmFsKSBub2RlcyxcclxuICAgIC8vIHNvIHRoYXQgYW55IElEIGdyZWF0ZXIgdGhhbiBpdCBiZWxvbmdzIHRvIG5ldyBub2Rlc1xyXG4gICAgY29uc3QgbWF4T3JpZ2luYWxJZCA9IChzbmFwc2hvdC50ZXh0IGFzIENoYXJOb2RlW10pLnJlZHVjZShcclxuICAgICAgKG1heCwgbikgPT4gTWF0aC5tYXgobWF4LCBuLmlkKSxcclxuICAgICAgMFxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBhcHBlbmQgbm9kZXMgaW50cm9kdWNlZCBiZWZvcmUgdGhlIHBpY2tlZCBzdGVwIGlmIGFueVxyXG4gICAgLy8gKHRob3NlIGludHJvZHVjZWQgYnkgdGhlIHBpY2tlZCBzdGVwIGhhdmUgYWxyZWFkeSBiZWVuIGFkZGVkKVxyXG4gICAgY29uc3Qgc3RlcEluZGV4ID0gdGhpcy5yZXN1bHQuc3RlcHMuaW5kZXhPZihzdGVwKTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RlcEluZGV4OyBpKyspIHtcclxuICAgICAgY29uc3Qgc3RlcE5vZGVzID0gdGhpcy5yZXN1bHQudGFnZ2VkTm9kZXNbdGhpcy5yZXN1bHQuc3RlcHNbaV0ub3V0cHV0VGFnXTtcclxuICAgICAgZm9yIChjb25zdCBuIG9mIHN0ZXBOb2Rlcykge1xyXG4gICAgICAgIGlmIChuLmlkID4gbWF4T3JpZ2luYWxJZCAmJiAhbm9kZXMuZmluZCgoeCkgPT4geC5pZCA9PT0gbi5pZCkpIHtcclxuICAgICAgICAgIG5vZGVzLnB1c2gobik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgc25hcHNob3QudGV4dCA9IG5vZGVzO1xyXG4gICAgY29uc3QgaSA9IHNuYXBzaG90Lm9wZXJhdGlvbnMuZmluZEluZGV4KChvKSA9PiBvLmlkID09PSBzdGVwLm9wZXJhdGlvbi5pZCk7XHJcbiAgICBpZiAoaSA+IC0xKSB7XHJcbiAgICAgIHNuYXBzaG90Lm9wZXJhdGlvbnMgPSBzbmFwc2hvdC5vcGVyYXRpb25zLnNsaWNlKDAsIGkgKyAxKTtcclxuICAgIH1cclxuICAgIHRoaXMudXBkYXRlVmlld0RhdGEodW5kZWZpbmVkLCBzbmFwc2hvdCwgc3RlcC5vdXRwdXRUYWcpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uVmlzdWFsRXZlbnQoZXZlbnQ6IEN1c3RvbUV2ZW50PEd2ZVZpc3VhbEV2ZW50Pik6IHZvaWQge1xyXG4gICAgY29uc3QgZCA9IGV2ZW50LmRldGFpbDtcclxuICAgIGlmIChkLmV2ZW50LnR5cGUgPT09ICdtb3VzZW92ZXInKSB7XHJcbiAgICAgIGNvbnN0IHZpc3VhbCA9IGQuc291cmNlO1xyXG4gICAgICBjb25zdCBzYjogc3RyaW5nW10gPSBbXTtcclxuICAgICAgc2IucHVzaCgnIycgKyB2aXN1YWwuaWQpO1xyXG4gICAgICBzYi5wdXNoKGAgKCR7dmlzdWFsLnR5cGV9KWApO1xyXG4gICAgICBpZiAodmlzdWFsLmRhdGE/LmxhYmVsKSB7XHJcbiAgICAgICAgc2IucHVzaCgnOiAnKTtcclxuICAgICAgICBzYi5wdXNoKHZpc3VhbC5kYXRhLmxhYmVsKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAodmlzdWFsLmRhdGE/LmZlYXR1cmVzPy5sZW5ndGgpIHtcclxuICAgICAgICBzYi5wdXNoKFxyXG4gICAgICAgICAgdmlzdWFsLmRhdGEuZmVhdHVyZXNcclxuICAgICAgICAgICAgLm1hcCgoZjogRmVhdHVyZSkgPT4gYCR7Zi5uYW1lfT0ke2YudmFsdWV9YClcclxuICAgICAgICAgICAgLmpvaW4oJ1xcbicpXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnZpc3VhbEluZm8gPSBzYi5qb2luKCcnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBvbkhlaWdodHNDaGFuZ2UoaGVpZ2h0czogUmVjb3JkPG51bWJlciwgbnVtYmVyPiB8IHVuZGVmaW5lZCk6IHZvaWQge1xyXG4gICAgdGhpcy5sbkhlaWdodHMuc2V0VmFsdWUoaGVpZ2h0cyB8fCBudWxsKTtcclxuICAgIHRoaXMubG5IZWlnaHRzLm1hcmtBc0RpcnR5KCk7XHJcbiAgICB0aGlzLmxuSGVpZ2h0cy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2xvc2UoKTogdm9pZCB7XHJcbiAgICB0aGlzLnNuYXBzaG90Q2FuY2VsLmVtaXQoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvblNuYXBzaG90UmVuZGVyKGV2ZW50OiBDdXN0b21FdmVudDxTbmFwc2hvdFZpZXdSZW5kZXJFdmVudD4pOiB2b2lkIHtcclxuICAgIHRoaXMuX3JlbmRlcmVyID0gKGV2ZW50LmRldGFpbCBhcyBTbmFwc2hvdFZpZXdSZW5kZXJFdmVudCkucmVuZGVyZXI7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgdG9nZ2xlUnVsZXJzKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLl9yZW5kZXJlcikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnJ1bGVycyA9IHRoaXMuX3JlbmRlcmVyLnRvZ2dsZVJ1bGVycygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRTbmFwc2hvdCgpOiBTbmFwc2hvdCB7XHJcbiAgICBjb25zdCBzbmFwc2hvdDogU25hcHNob3QgPSB7XHJcbiAgICAgIHNpemU6IHtcclxuICAgICAgICB3aWR0aDogdGhpcy53aWR0aC52YWx1ZSxcclxuICAgICAgICBoZWlnaHQ6IHRoaXMuaGVpZ2h0LnZhbHVlLFxyXG4gICAgICB9LFxyXG4gICAgICBzdHlsZTogdGhpcy5zdHlsZS52YWx1ZSB8fCB1bmRlZmluZWQsXHJcbiAgICAgIGRlZnM6IHRoaXMuZGVmcy52YWx1ZSB8fCB1bmRlZmluZWQsXHJcbiAgICAgIHRleHQ6IHRoaXMuYmFzZVRleHQudmFsdWUhLFxyXG4gICAgICB0ZXh0U3R5bGU6IHRoaXMudGV4dFN0eWxlLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgdGV4dE9wdGlvbnM6IHtcclxuICAgICAgICBsaW5lSGVpZ2h0T2Zmc2V0OiB0aGlzLmxpbmVIZWlnaHRPZmZzZXQudmFsdWUsXHJcbiAgICAgICAgbWluTGluZUhlaWdodHM6IHRoaXMubG5IZWlnaHRzLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgICBjaGFyU3BhY2luZ09mZnNldDogdGhpcy5jaGFyU3BhY2luZ09mZnNldC52YWx1ZSxcclxuICAgICAgICBzcGNXaWR0aE9mZnNldDogdGhpcy5zcGNXaWR0aE9mZnNldC52YWx1ZSxcclxuICAgICAgICBvZmZzZXQ6IHtcclxuICAgICAgICAgIHg6IHRoaXMub2Zmc2V0WC52YWx1ZSxcclxuICAgICAgICAgIHk6IHRoaXMub2Zmc2V0WS52YWx1ZSxcclxuICAgICAgICB9LFxyXG4gICAgICB9LFxyXG4gICAgICBvcGVyYXRpb25zOiBbLi4udGhpcy5vcGVyYXRpb25zLnZhbHVlXSxcclxuICAgICAgb3BTdHlsZTogdGhpcy5vcFN0eWxlLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgdGltZWxpbmVzOiB7fSwgLy8gVE9ET1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBpbWFnZVxyXG4gICAgaWYgKHRoaXMuaW1hZ2VVcmwudmFsdWUpIHtcclxuICAgICAgc25hcHNob3QuaW1hZ2UgPSB7XHJcbiAgICAgICAgdXJsOiB0aGlzLmltYWdlVXJsLnZhbHVlLFxyXG4gICAgICAgIG9wYWNpdHk6IHRoaXMuaW1hZ2VPcGFjaXR5LnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgfTtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHRoaXMuaW1hZ2VYLnZhbHVlIHx8XHJcbiAgICAgICAgdGhpcy5pbWFnZVkudmFsdWUgfHxcclxuICAgICAgICB0aGlzLmltYWdlV2lkdGgudmFsdWUgfHxcclxuICAgICAgICB0aGlzLmltYWdlSGVpZ2h0LnZhbHVlXHJcbiAgICAgICkge1xyXG4gICAgICAgIHNuYXBzaG90LmltYWdlLmNhbnZhcyA9IHtcclxuICAgICAgICAgIHg6IHRoaXMuaW1hZ2VYLnZhbHVlLFxyXG4gICAgICAgICAgeTogdGhpcy5pbWFnZVkudmFsdWUsXHJcbiAgICAgICAgICB3aWR0aDogdGhpcy5pbWFnZVdpZHRoLnZhbHVlLFxyXG4gICAgICAgICAgaGVpZ2h0OiB0aGlzLmltYWdlSGVpZ2h0LnZhbHVlLFxyXG4gICAgICAgIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyB0aW1lbGluZXNcclxuICAgIGlmICh0aGlzLnRpbWVsaW5lcy52YWx1ZS5sZW5ndGgpIHtcclxuICAgICAgc25hcHNob3QudGltZWxpbmVzID0ge307XHJcbiAgICAgIHRoaXMudGltZWxpbmVzLnZhbHVlLmZvckVhY2goKHQpID0+IHtcclxuICAgICAgICBzbmFwc2hvdC50aW1lbGluZXMhW3QudGFnXSA9IHQ7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc25hcHNob3QudGltZWxpbmVzID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBzbmFwc2hvdDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvblRpbWVsaW5lc0NoYW5nZSh0aW1lbGluZXM6IEd2ZUFuaW1hdGlvblRpbWVsaW5lW10pOiB2b2lkIHtcclxuICAgIHRoaXMudGltZWxpbmVzLnNldFZhbHVlKHRpbWVsaW5lcyk7XHJcbiAgICB0aGlzLnRpbWVsaW5lcy5tYXJrQXNEaXJ0eSgpO1xyXG4gICAgdGhpcy50aW1lbGluZXMudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHNhdmUoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5mb3JtLmludmFsaWQgfHwgdGhpcy5ub1NhdmUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fc25hcHNob3QgPSB0aGlzLmdldFNuYXBzaG90KCk7XHJcbiAgICB0aGlzLnNuYXBzaG90Q2hhbmdlLmVtaXQodGhpcy5fc25hcHNob3QpO1xyXG4gIH1cclxufVxyXG4iLCI8Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1cIiAoc3VibWl0KT1cInNhdmUoKVwiPlxyXG4gIDxtYXQtdGFiLWdyb3VwPlxyXG4gICAgPCEtLSB0ZXh0IC0tPlxyXG4gICAgPG1hdC10YWIgbGFiZWw9XCJ0ZXh0XCI+XHJcbiAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsIFtleHBhbmRlZF09XCIhYmFzZVRleHQudmFsdWVcIj5cclxuICAgICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgICAgICA8bWF0LXBhbmVsLXRpdGxlPiBiYXNlIHRleHQgPC9tYXQtcGFuZWwtdGl0bGU+XHJcbiAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICA8Z3ZlLWJhc2UtdGV4dC1lZGl0b3JcclxuICAgICAgICAgIFt0ZXh0XT1cImJhc2VUZXh0LnZhbHVlXCJcclxuICAgICAgICAgICh0ZXh0Q2hhbmdlKT1cIm9uVGV4dENoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICAvPlxyXG4gICAgICAgIDxmaWVsZHNldD5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gICAgICAgICAgICA8IS0tIG9mZnNldFggLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5YIG9mZnNldDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIm9mZnNldFhcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJYIG9mZnNldFwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gb2Zmc2V0WSAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPlkgb2Zmc2V0PC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwib2Zmc2V0WVwiXHJcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlkgb2Zmc2V0XCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICAgICAgPCEtLSBsaW5lSGVpZ2h0T2Zmc2V0IC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+bG4gaC1vZmZzZXQ8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJsaW5lSGVpZ2h0T2Zmc2V0XCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwibG4gaC1vZmZzZXRcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgICAgICA8IS0tIGNoYXJTcGFjaW5nT2Zmc2V0IC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+Y2hhciBzcGFjaW5nPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiY2hhclNwYWNpbmdPZmZzZXRcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJjaGFyIHNwYWNpbmdcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgICAgICA8IS0tIHNwY1dpZHRoT2Zmc2V0IC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+c3BjIHctb2Zmc2V0PC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwic3BjV2lkdGhPZmZzZXRcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJzcGMgdy1vZmZzZXRcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgIDwhLS0gbWluTGluZUhlaWdodHMgLS0+XHJcbiAgICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgICAgPGd2ZS1sbi1oZWlnaHRzLWVkaXRvclxyXG4gICAgICAgICAgICAgICAgW2xpbmVDb3VudF09XCJsaW5lQ291bnRcIlxyXG4gICAgICAgICAgICAgICAgW2hlaWdodHNdPVwibG5IZWlnaHRzLnZhbHVlXCJcclxuICAgICAgICAgICAgICAgIChoZWlnaHRzQ2hhbmdlKT1cIm9uSGVpZ2h0c0NoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPCEtLSB0ZXh0U3R5bGUgLS0+XHJcbiAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+dGV4dCBzdHlsZTwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDx0ZXh0YXJlYVxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJ0ZXh0U3R5bGVcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJ0ZXh0IHN0eWxlXCJcclxuICAgICAgICAgICAgICA+PC90ZXh0YXJlYT5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZmllbGRzZXQ+XHJcbiAgICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cclxuICAgIDwvbWF0LXRhYj5cclxuXHJcbiAgICA8IS0tIG9wZXJhdGlvbnMgLS0+XHJcbiAgICA8bWF0LXRhYiBsYWJlbD1cIm9wZXJhdGlvbnNcIj5cclxuICAgICAgPGRpdiBpZD1cInNuYXBzaG90LWNvbnRhaW5lclwiPlxyXG4gICAgICAgIDxkaXYgaWQ9XCJnZW5lcmFsXCI+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1yb3dcIj5cclxuICAgICAgICAgICAgPCEtLSB3aWR0aCAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPndpZHRoPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBtaW49XCIwXCJcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJ3aWR0aFwiXHJcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIndpZHRoXCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICAgICAgPCEtLSBoZWlnaHQgLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5oZWlnaHQ8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxyXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cImhlaWdodFwiXHJcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cImhlaWdodFwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gYWRkIG9wIC0tPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgbWF0LWZsYXQtYnV0dG9uXHJcbiAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgICBjbGFzcz1cIm1hdC1wcmltYXJ5IHJpZ2h0XCJcclxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWJhc2VUZXh0LnZhbHVlXCJcclxuICAgICAgICAgICAgICAoY2xpY2spPVwiZWRpdE5ld09wZXJhdGlvbigpXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDxtYXQtaWNvbj5hZGRfY2lyY2xlPC9tYXQtaWNvbj4gb3BlcmF0aW9uXHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDwhLS0gb3BzIC0tPlxyXG4gICAgICAgIDxkaXYgaWQ9XCJvcHNcIj5cclxuICAgICAgICAgIDwhLS0gb3BlcmF0aW9ucyBsaXN0IC0tPlxyXG4gICAgICAgICAgQGlmIChvcGVyYXRpb25zLnZhbHVlLmxlbmd0aCkge1xyXG4gICAgICAgICAgPHRhYmxlIGlkPVwibGlzdFwiPlxyXG4gICAgICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgPHRoPjwvdGg+XHJcbiAgICAgICAgICAgICAgICA8dGg+SUQ8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPnR5cGU8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPmF0PC90aD5cclxuICAgICAgICAgICAgICAgIDx0aD5ydW48L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPnZhbHVlPC90aD5cclxuICAgICAgICAgICAgICAgIDx0aD5pdGFnPC90aD5cclxuICAgICAgICAgICAgICAgIDx0aD5vdGFnPC90aD5cclxuICAgICAgICAgICAgICAgIDx0aD5naWQ8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPmZlYXRzPC90aD5cclxuICAgICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICA8L3RoZWFkPlxyXG4gICAgICAgICAgICA8dGJvZHk+XHJcbiAgICAgICAgICAgICAgQGZvciAob3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMudmFsdWU7IHRyYWNrIG9wZXJhdGlvbi5pZDsgbGV0XHJcbiAgICAgICAgICAgICAgaW5kZXg9JGluZGV4KSB7XHJcbiAgICAgICAgICAgICAgPHRyXHJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7IHNlbGVjdGVkOiBvcGVyYXRpb24uaWQgPT09IHJlc3VsdE9wZXJhdGlvbklkIH1cIlxyXG4gICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyBlZGl0ZWQ6IG9wZXJhdGlvbi5pZCA9PT0gZWRpdGVkT3A/LmlkIH1cIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cImZpdC13aWR0aFwiPlxyXG4gICAgICAgICAgICAgICAgICA8IS0tIGVkaXQgLS0+XHJcbiAgICAgICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWF0LXByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJlZGl0T3BlcmF0aW9uKGluZGV4KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkVkaXQgb3BlcmF0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5lZGl0PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgIDwhLS0gZGVsZXRlIC0tPlxyXG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgY29sb3I9XCJ3YXJuXCJcclxuICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlT3BlcmF0aW9uKGluZGV4KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkRlbGV0ZSBvcGVyYXRpb25cIlxyXG4gICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0LXdhcm5cIj5kZWxldGU8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgPCEtLSBydW4gdG8gLS0+XHJcbiAgICAgICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgICAgICBjb2xvcj1cImFjY2VudFwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJ1blRvKGluZGV4KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlJ1biB0byB0aGlzIG9wZXJhdGlvblwiXHJcbiAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXQtYWNjZW50XCI+c3Vic2NyaXB0aW9uczwvbWF0LWljb24+XHJcbiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZD57eyBvcGVyYXRpb24uaWQgfX08L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPnt7IG9wZXJhdGlvbi50eXBlIHwgZmxhdExvb2t1cCA6IG9wVHlwZU1hcCB9fTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e3sgb3BlcmF0aW9uLmF0IH19PC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZD57eyBvcGVyYXRpb24ucnVuIH19PC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZD57eyBvcGVyYXRpb24udmFsdWUgfX08L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPnt7IG9wZXJhdGlvbi5pbnB1dFRhZyB9fTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e3sgb3BlcmF0aW9uLm91dHB1dFRhZyB9fTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e3sgb3BlcmF0aW9uLmdyb3VwSWQgfX08L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPnt7IG9wZXJhdGlvbi5mZWF0dXJlcz8ubGVuZ3RoIH19PC90ZD5cclxuICAgICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgPC90Ym9keT5cclxuICAgICAgICAgIDwvdGFibGU+XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgPCEtLSBvcGVyYXRpb24gZWRpdG9yIC0tPlxyXG4gICAgICAgICAgPG1hdC1leHBhbnNpb24tcGFuZWwgW2V4cGFuZGVkXT1cImVkaXRlZE9wXCIgW2Rpc2FibGVkXT1cIiFlZGl0ZWRPcFwiPlxyXG4gICAgICAgICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgICAgICAgICAgPG1hdC1wYW5lbC10aXRsZT5vcGVyYXRpb24ge3sgZWRpdGVkT3A/LmlkIH19PC9tYXQtcGFuZWwtdGl0bGU+XHJcbiAgICAgICAgICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgICAgICAgIDxmaWVsZHNldD5cclxuICAgICAgICAgICAgICA8Z3ZlLWNoYWluLW9wZXJhdGlvbi1lZGl0b3JcclxuICAgICAgICAgICAgICAgIFtvcGVyYXRpb25dPVwiZWRpdGVkT3BcIlxyXG4gICAgICAgICAgICAgICAgKG9wZXJhdGlvbkNhbmNlbCk9XCJvbk9wZXJhdGlvbkNhbmNlbCgpXCJcclxuICAgICAgICAgICAgICAgIChvcGVyYXRpb25DaGFuZ2UpPVwib25PcGVyYXRpb25DaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAob3BlcmF0aW9uUHJldmlldyk9XCJvbk9wZXJhdGlvblByZXZpZXcoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9maWVsZHNldD5cclxuICAgICAgICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cclxuXHJcbiAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICA8bWF0LXByb2dyZXNzLWJhciBtb2RlPVwiaW5kZXRlcm1pbmF0ZVwiICpuZ0lmPVwiYnVzeVwiIC8+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIG9wU3R5bGUgLS0+XHJcbiAgICAgICAgICA8ZGl2IGlkPVwib3BTdHlsZVwiPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+b3BlcmF0aW9ucyBzdHlsZTwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDx0ZXh0YXJlYVxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJvcFN0eWxlXCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwib3BlcmF0aW9ucyBzdHlsZVwiXHJcbiAgICAgICAgICAgICAgPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIGJhdGNoIG9wcyAtLT5cclxuICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsPlxyXG4gICAgICAgICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICAgICAgICAgIDxtYXQtcGFuZWwtdGl0bGU+YmF0Y2ggb3BlcmF0aW9uczwvbWF0LXBhbmVsLXRpdGxlPlxyXG4gICAgICAgICAgICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgICAgICAgICAgPGZpZWxkc2V0PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBpZD1cImJhdGNoLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgICA8ZGl2IGlkPVwiYmF0Y2gtaW5wdXRcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPm9wZXJhdGlvbnM8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRleHRhcmVhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjb2RlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJpbnB1dE9wc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJvcGVyYXRpb25zXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICByb3dzPVwiOFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlbGxjaGVjaz1cImZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9XCJ3YXJuXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtYXQtd2FyblwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdC1mbGF0LWJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiUmVtb3ZlIGFsbCB0aGUgb3BlcmF0aW9uc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhb3BlcmF0aW9ucy52YWx1ZS5sZW5ndGggfHwgYnVzeVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhck9wZXJhdGlvbnMoKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyXHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWF0LXByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXQtZmxhdC1idXR0b25cclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlBhcnNlIHRleHQgYW5kIGFkZCByZXN1bHRzIHRvIHRoZSBvcGVyYXRpb25zXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFpbnB1dE9wcy52YWx1ZSB8fCBidXN5XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInBhcnNlT3BlcmF0aW9ucygpXCJcclxuICAgICAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2ggYWRkXHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgIEBpZiAocGFyc2VFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJlcnJvclwiPnt7IHBhcnNlRXJyb3IgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICA8ZGl2IGlkPVwiYmF0Y2gtaGVscFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx1bD5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5yZXBsYWNlPC9zdHJvbmc+OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5BVHhSVU48c3Ryb25nPj08L3N0cm9uZz5cIlZBTFVFXCI8L2NvZGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPmRlbGV0ZTwvc3Ryb25nPjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+QVR4UlVOPHN0cm9uZz4tPC9zdHJvbmc+PC9jb2RlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5hZGQtYmVmb3JlPC9zdHJvbmc+OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5BVHhSVU48c3Ryb25nPitbPC9zdHJvbmc+XCJWQUxVRVwiPC9jb2RlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5hZGQtYWZ0ZXI8L3N0cm9uZz46XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPkFUeFJVTjxzdHJvbmc+K108L3N0cm9uZz5cIlZBTFVFXCI8L2NvZGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPm1vdmUtYmVmb3JlPC9zdHJvbmc+OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5BVHhSVU48c3Ryb25nPiZndDtbPC9zdHJvbmc+VE88L2NvZGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPm1vdmUtYWZ0ZXI8L3N0cm9uZz46XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPkFUeFJVTjxzdHJvbmc+Jmd0O108L3N0cm9uZz5UTzwvY29kZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzdHJvbmc+c3dhcDwvc3Ryb25nPjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+QVR4UlVOPHN0cm9uZz4mbHQ7Jmd0Ozwvc3Ryb25nPlRPeFJVTjwvY29kZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzdHJvbmc+YW5ub3RhdGU8L3N0cm9uZz46XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPkFUeFJVTjxzdHJvbmc+Ojwvc3Ryb25nPjwvY29kZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgPC91bD5cclxuICAgICAgICAgICAgICAgICAgICA8cD5Gb3IgYWxsIHRoZSBvcGVyYXRpb25zOjwvcD5cclxuICAgICAgICAgICAgICAgICAgICA8dWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCA8Y29kZT4oSVRBRzpPVEFHKTwvY29kZT4gdG8gZGVmaW5lIGlucHV0IGFuZC9vclxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgdGFncywgc2VwYXJhdGVkIGJ5IGNvbG9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlcGVuZCA8Y29kZT4mI3g0MDs8L2NvZGU+IHRvIEFUIHRvIHVzZSBjaGFyYWN0ZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhlcyAoMC1OKSByYXRoZXIgdGhhbiBJRHMuXHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlJVTiAod2hlcmUgYXBwbGljYWJsZSkgZGVmYXVsdHMgdG8gMS48L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBlbmQgZmVhdHVyZXMgbGlrZSA8Y29kZT5bTkFNRSBPUEVSQVRPUiBWQUxVRV08L2NvZGU+LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0ZWQgYnkgc3BhY2UsIHdoZXJlOlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxvbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIE5BTUUgaXMgYW4gYXJiaXRyYXJ5IHN0cmluZy4gUHJlZml4ZXM6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+KjwvY29kZT49Z2xvYmFsIGZlYXR1cmVzLCA8Y29kZT4hPC9jb2RlPj1yZW1vdmVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlIChubyB2YWx1ZSkuIFN1ZmZpeGVzOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPl48L2NvZGU+PXNob3J0LWxpdmVkIChsaWtlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+KnZlcnNpb25ePWFscGhhPC9jb2RlPikuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICBPUEVSQVRPUiBpcyA8Y29kZT49PC9jb2RlPiAobXVsdGlwbGUpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPjo9PC9jb2RlPiAoc2luZ2xlKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT49PTwvY29kZT4gKGZpcnN0LXNpbmdsZSkuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICBWQUxVRSBpcyBhIHN0cmluZy4gSWYgaXQgaW5jbHVkZXMgc3BhY2VzLCB3cmFwIGl0IGluXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+XCJcIjwvY29kZT4uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L29sPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvdWw+XHJcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgPC9maWVsZHNldD5cclxuICAgICAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDwhLS0gcmVzdWx0IC0tPlxyXG4gICAgICAgIEBpZiAocmVzdWx0KSB7XHJcbiAgICAgICAgPGZpZWxkc2V0IGlkPVwicmVzdWx0XCI+XHJcbiAgICAgICAgICA8bGVnZW5kPnJlc3VsdDwvbGVnZW5kPlxyXG4gICAgICAgICAgPGd2ZS1jaGFpbi1yZXN1bHQtdmlld1xyXG4gICAgICAgICAgICBbcmVzdWx0XT1cInJlc3VsdFwiXHJcbiAgICAgICAgICAgIChzdGVwUGljayk9XCJvblN0ZXBQaWNrKCRldmVudClcIlxyXG4gICAgICAgICAgLz5cclxuICAgICAgICA8L2ZpZWxkc2V0PlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L21hdC10YWI+XHJcblxyXG4gICAgPCEtLSBpbWFnZSAtLT5cclxuICAgIDxtYXQtdGFiIGxhYmVsPVwiaW1hZ2VcIj5cclxuICAgICAgPGRpdiBpZD1cImltYWdlXCI+XHJcbiAgICAgICAgPGRpdiBpZD1cImltYWdlLWN0bFwiPlxyXG4gICAgICAgICAgPCEtLSB1cmwgLS0+XHJcbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIj5cclxuICAgICAgICAgICAgPG1hdC1sYWJlbD5VUkw8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IFtmb3JtQ29udHJvbF09XCJpbWFnZVVybFwiIC8+XHJcbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgICAgICAgIDwhLS0geCAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPlg8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJpbWFnZVhcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJYXCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICA8IS0tIHkgLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5ZPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiaW1hZ2VZXCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiWVwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgICAgICAgIDwhLS0gd2lkdGggLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD53aWR0aDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgICAgbWluPVwiMFwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiaW1hZ2VXaWR0aFwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgPCEtLSBoZWlnaHQgLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5oZWlnaHQ8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxyXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cImltYWdlSGVpZ2h0XCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8IS0tIGRlZnMgLS0+XHJcbiAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPmRlZnM8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8dGV4dGFyZWEgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cImRlZnNcIiByb3dzPVwiM1wiPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8ZGl2IGlkPVwiaW1hZ2Utdmlld1wiPlxyXG4gICAgICAgICAgQGlmIChpbWFnZVVybC52YWx1ZSkge1xyXG4gICAgICAgICAgPGltZyBhbHQ9XCJiYWNrZ3JvdW5kXCIgW3NyY109XCJpbWFnZVVybC52YWx1ZVwiIHdpZHRoPVwiNjAwXCIgLz5cclxuICAgICAgICAgIH1cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L21hdC10YWI+XHJcblxyXG4gICAgPCEtLSB0aW1lbGluZXMgLS0+XHJcbiAgICA8bWF0LXRhYiBsYWJlbD1cImFuaW1hdGlvblwiPlxyXG4gICAgICA8Z3ZlLWFuaW1hdGlvbi10aW1lbGluZS1zZXRcclxuICAgICAgICBbdGFnc109XCJvcFRhZ3NcIlxyXG4gICAgICAgIFtlbGVtZW50SWRzXT1cIm9wRWxlbWVudElkc1wiXHJcbiAgICAgICAgW3RpbWVsaW5lc109XCJ0aW1lbGluZXMudmFsdWVcIlxyXG4gICAgICAgICh0aW1lbGluZXNDaGFuZ2UpPVwib25UaW1lbGluZXNDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgIC8+XHJcbiAgICA8L21hdC10YWI+XHJcbiAgPC9tYXQtdGFiLWdyb3VwPlxyXG5cclxuICA8IS0tIHByZXZpZXcgLS0+XHJcbiAgQGlmIChzbmFwc2hvdCkge1xyXG4gIDxmaWVsZHNldCBpZD1cInByZXZpZXdcIj5cclxuICAgIDxsZWdlbmQgY2xhc3M9XCJidXR0b24tcm93XCI+XHJcbiAgICAgIDxzcGFuPnt7IHZpZXdUaXRsZSB9fTwvc3Bhbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgbWF0VG9vbHRpcD1cIlJlZnJlc2ggcHJldmlld1wiXHJcbiAgICAgICAgKGNsaWNrKT1cInVwZGF0ZVZpZXdEYXRhKClcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0LXByaW1hcnlcIj5yZWZyZXNoPC9tYXQtaWNvbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICA8L2xlZ2VuZD5cclxuICAgIDxndmUtc25hcHNob3Qtdmlld1xyXG4gICAgICBbZGF0YV09XCJ2aWV3RGF0YVwiXHJcbiAgICAgIChzbmFwc2hvdFJlbmRlcik9XCJvblNuYXBzaG90UmVuZGVyKCRhbnkoJGV2ZW50KSlcIlxyXG4gICAgICAodmlzdWFsRXZlbnQpPVwib25WaXN1YWxFdmVudCgkYW55KCRldmVudCkpXCJcclxuICAgIC8+XHJcbiAgICA8ZGl2PlxyXG4gICAgICA8bWF0LWJ1dHRvbi10b2dnbGVcclxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgIG1hdFRvb2x0aXA9XCJUb2dnbGUgcnVsZXJzXCJcclxuICAgICAgICBbY2hlY2tlZF09XCJydWxlcnNcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwidG9nZ2xlUnVsZXJzKClcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0LXByaW1hcnlcIj5zdHJhaWdodGVuPC9tYXQtaWNvbj5cclxuICAgICAgPC9tYXQtYnV0dG9uLXRvZ2dsZT5cclxuICAgIDwvZGl2PlxyXG4gICAgQGlmICh2aXN1YWxJbmZvKSB7XHJcbiAgICA8ZGl2IGlkPVwidmlzdWFsLWluZm9cIj57eyB2aXN1YWxJbmZvIH19PC9kaXY+XHJcbiAgICB9XHJcbiAgPC9maWVsZHNldD5cclxuICB9XHJcblxyXG4gIDwhLS1idXR0b25zIC0tPlxyXG4gIDxkaXYgY2xhc3M9XCJmb3JtLXJvdy1jZW50ZXJcIj5cclxuICAgIDxidXR0b25cclxuICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgIGNsYXNzPVwibWF0LXdhcm5cIlxyXG4gICAgICBtYXQtZmxhdC1idXR0b25cclxuICAgICAgbWF0VG9vbHRpcD1cIkRpc2NhcmQgY2hhbmdlc1wiXHJcbiAgICAgIChjbGljayk9XCJjbG9zZSgpXCJcclxuICAgID5cclxuICAgICAgPG1hdC1pY29uPmNsZWFyPC9tYXQtaWNvbj5cclxuICAgICAgY2xvc2VcclxuICAgIDwvYnV0dG9uPlxyXG4gICAgQGlmICghbm9TYXZlKSB7XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgIHR5cGU9XCJzdWJtaXRcIlxyXG4gICAgICBjbGFzcz1cIm1hdC1wcmltYXJ5XCJcclxuICAgICAgbWF0LWZsYXQtYnV0dG9uXHJcbiAgICAgIG1hdFRvb2x0aXA9XCJTYXZlIGNoYW5nZXNcIlxyXG4gICAgICBbZGlzYWJsZWRdPVwiZm9ybS5pbnZhbGlkIHx8IGZvcm0ucHJpc3RpbmVcIlxyXG4gICAgPlxyXG4gICAgICA8bWF0LWljb24+Y2hlY2tfY2lyY2xlPC9tYXQtaWNvbj5cclxuICAgICAgc2F2ZVxyXG4gICAgPC9idXR0b24+XHJcbiAgICB9XHJcbiAgPC9kaXY+XHJcbjwvZm9ybT5cclxuIl19
863
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcHNob3QtZWRpdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9zbmFwc2hvdC1lZGl0b3Ivc25hcHNob3QtZWRpdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9zbmFwc2hvdC1lZGl0b3Ivc25hcHNob3QtZWRpdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBRUwsV0FBVyxFQUVYLFdBQVcsRUFDWCxtQkFBbUIsRUFDbkIsVUFBVSxHQUNYLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRS9DLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FB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QUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxDQUFDO1lBQzVDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDO1lBQ3BELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3pELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUNyRCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzdELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sSUFBSSxDQUFDLENBQUMsQ0FBQztZQUMvRCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxDQUFDO1lBQzFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDNUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxD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akIsYUFBYTt3QkFDYixnQkFBZ0I7d0JBQ2hCLGFBQWE7d0JBQ2IsdUJBQXVCO3dCQUN2QixxQkFBcUI7d0JBQ3JCLDZCQUE2Qjt3QkFDN0Isd0JBQXdCO3dCQUN4Qix3QkFBd0I7d0JBQ3hCLDZCQUE2QjtxQkFDOUIsV0FDUSxDQUFDLHNCQUFzQixDQUFDO2tLQWExQixZQUFZO3NCQURsQixTQUFTO3VCQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBT2pDLFFBQVE7c0JBRGxCLEtBQUs7Z0JBbUJDLFFBQVE7c0JBRGQsS0FBSztnQkFPQyxNQUFNO3NCQURaLEtBQUs7Z0JBT0MsS0FBSztzQkFEWCxLQUFLO2dCQU9VLGNBQWM7c0JBRDdCLE1BQU07Z0JBT1MsY0FBYztzQkFEN0IsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQSxcclxuICBDb21wb25lbnQsXHJcbiAgRWxlbWVudFJlZixcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxuICBWaWV3Q2hpbGQsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgRm9ybUJ1aWxkZXIsXHJcbiAgRm9ybUNvbnRyb2wsXHJcbiAgRm9ybUdyb3VwLFxyXG4gIEZvcm1zTW9kdWxlLFxyXG4gIFJlYWN0aXZlRm9ybXNNb2R1bGUsXHJcbiAgVmFsaWRhdG9ycyxcclxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcblxyXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xyXG5pbXBvcnQgeyBNYXRCdXR0b25Ub2dnbGVNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24tdG9nZ2xlJztcclxuaW1wb3J0IHsgTWF0Q2hlY2tib3hNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jaGVja2JveCc7XHJcbmltcG9ydCB7IE1hdEV4cGFuc2lvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2V4cGFuc2lvbic7XHJcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcbmltcG9ydCB7IE1hdElucHV0TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xyXG5pbXBvcnQgeyBNYXRQcm9ncmVzc0Jhck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Byb2dyZXNzLWJhcic7XHJcbmltcG9ydCB7IE1hdFNuYWNrQmFyLCBNYXRTbmFja0Jhck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NuYWNrLWJhcic7XHJcbmltcG9ydCB7IE1hdFRhYnNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcclxuaW1wb3J0IHsgTWF0VG9vbHRpcE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnO1xyXG5cclxuaW1wb3J0IHsgY3VzdG9tQWxwaGFiZXQgfSBmcm9tICduYW5vaWQnO1xyXG5cclxuaW1wb3J0IHsgTmdUb29sc01vZHVsZSwgZGVlcENvcHkgfSBmcm9tICdAbXlybWlkb24vbmctdG9vbHMnO1xyXG5pbXBvcnQgeyBEaWFsb2dTZXJ2aWNlIH0gZnJvbSAnQG15cm1pZG9uL25nLW1hdC10b29scyc7XHJcblxyXG5pbXBvcnQge1xyXG4gIENoYXJDaGFpbk9wZXJhdGlvbixcclxuICBDaGFyTm9kZSxcclxuICBERUZBVUxUX1NWR19CQVNFX1RFWFRfT1BUSU9OUyxcclxuICBGZWF0dXJlLFxyXG4gIEd2ZUFuaW1hdGlvblRpbWVsaW5lLFxyXG4gIEd2ZVZpc3VhbEV2ZW50LFxyXG4gIFNuYXBzaG90LFxyXG4gIFNuYXBzaG90Vmlld0NvbXBvbmVudCxcclxuICBTbmFwc2hvdFZpZXdEYXRhLFxyXG4gIFNuYXBzaG90Vmlld1JlbmRlckV2ZW50LFxyXG4gIFNuYXBzaG90Vmlld1NlcnZpY2UsXHJcbn0gZnJvbSAnQG15cm1pZG9uL2d2ZS1zbmFwc2hvdC12aWV3JztcclxuXHJcbmltcG9ydCB7XHJcbiAgQmFzZVRleHRWaWV3Q29tcG9uZW50LFxyXG4gIFZhckJhc2VUZXh0UmFuZ2UsXHJcbn0gZnJvbSAnLi4vYmFzZS10ZXh0LXZpZXcvYmFzZS10ZXh0LXZpZXcuY29tcG9uZW50JztcclxuaW1wb3J0IHsgQ2hhaW5PcGVyYXRpb25FZGl0b3JDb21wb25lbnQgfSBmcm9tICcuLi9jaGFpbi1vcGVyYXRpb24tZWRpdG9yL2NoYWluLW9wZXJhdGlvbi1lZGl0b3IuY29tcG9uZW50JztcclxuaW1wb3J0IHtcclxuICBDaGFpbk9wZXJhdGlvbkNvbnRleHRTdGVwLFxyXG4gIENoYXJDaGFpblJlc3VsdCxcclxuICBHdmVBcGlTZXJ2aWNlLFxyXG59IGZyb20gJy4uLy4uL3NlcnZpY2VzL2d2ZS1hcGkuc2VydmljZSc7XHJcbmltcG9ydCB7IENoYWluUmVzdWx0Vmlld0NvbXBvbmVudCB9IGZyb20gJy4uL2NoYWluLXJlc3VsdC12aWV3L2NoYWluLXJlc3VsdC12aWV3LmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IExuSGVpZ2h0c0VkaXRvckNvbXBvbmVudCB9IGZyb20gJy4uL2xuLWhlaWdodHMtZWRpdG9yL2xuLWhlaWdodHMtZWRpdG9yLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEJhc2VUZXh0RWRpdG9yQ29tcG9uZW50IH0gZnJvbSAnLi4vYmFzZS10ZXh0LWVkaXRvci9iYXNlLXRleHQtZWRpdG9yLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEFuaW1hdGlvblRpbWVsaW5lU2V0Q29tcG9uZW50IH0gZnJvbSAnLi4vYW5pbWF0aW9uLXRpbWVsaW5lLXNldC9hbmltYXRpb24tdGltZWxpbmUtc2V0LmNvbXBvbmVudCc7XHJcblxyXG4vLyBkZWZhdWx0IHNuYXBzaG90IHZpZXcgdGl0bGVcclxuY29uc3QgVklFV19USVRMRSA9ICdwcmV2aWV3JztcclxuXHJcbi8vIHN1ZmZpeCBmb3IgSURzIG9mIFNWRyBlbGVtZW50cyB0byBiZSBtYWRlIHRyYW5zcGFyZW50IGF0IGZpcnN0IHJlbmRpdGlvblxyXG5jb25zdCBTVkdfVFJBTlNQX1NVRkZJWCA9ICdfdCc7XHJcblxyXG4vKipcclxuICog8J+UkSBgZ3ZlLXNuYXBzaG90LWVkaXRvcmBcclxuICpcclxuICogQSBjb21wb25lbnQgdG8gZWRpdCBhIHRleHQgc25hcHNob3QuIFRoaXMgaXMgdGhlIHRvcCBsZXZlbCBjb21wb25lbnQgaW4gdGhlIEdWRSBjb3JlXHJcbiAqIGxpYnJhcnkuXHJcbiAqXHJcbiAqIC0g4pa277iPIGBzbmFwc2hvdGAgKGBTbmFwc2hvdGApOiB0aGUgc25hcHNob3QgdG8gZWRpdC5cclxuICogLSDilrbvuI8gYGJhdGNoT3BzYCAoYHN0cmluZ2ApOiB0aGUgYmF0Y2ggb3BlcmF0aW9ucyB0ZXh0IHRvIHNldCBmb3IgdGhlIGVkaXRvci5cclxuICogLSDilrbvuI8gYG5vU2F2ZWAgKGBib29sZWFuYCk6IHRydWUgdG8gZGlzYWJsZSBzYXZpbmcuXHJcbiAqIC0g8J+UpSBgc25hcHNob3RDaGFuZ2VgIChgU25hcHNob3RgKTogZW1pdHRlZCB3aGVuIHRoZSB1c2VyIHNhdmVzIHRoZSBlZGl0ZWQgc25hcHNob3QuXHJcbiAqIC0g8J+UpSBgc25hcHNob3RDYW5jZWxgIChgdm9pZGApOiBlbWl0dGVkIHdoZW4gdGhlIHVzZXIgY2FuY2VscyB0aGUgc25hcHNob3QgZWRpdGluZy5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZ3ZlLXNuYXBzaG90LWVkaXRvcicsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXHJcbiAgICBDb21tb25Nb2R1bGUsXHJcbiAgICBGb3Jtc01vZHVsZSxcclxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Nb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Ub2dnbGVNb2R1bGUsXHJcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcclxuICAgIE1hdEV4cGFuc2lvbk1vZHVsZSxcclxuICAgIE1hdEZvcm1GaWVsZE1vZHVsZSxcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRJbnB1dE1vZHVsZSxcclxuICAgIE1hdFByb2dyZXNzQmFyTW9kdWxlLFxyXG4gICAgTWF0U25hY2tCYXJNb2R1bGUsXHJcbiAgICBNYXRUYWJzTW9kdWxlLFxyXG4gICAgTWF0VG9vbHRpcE1vZHVsZSxcclxuICAgIE5nVG9vbHNNb2R1bGUsXHJcbiAgICBCYXNlVGV4dEVkaXRvckNvbXBvbmVudCxcclxuICAgIEJhc2VUZXh0Vmlld0NvbXBvbmVudCxcclxuICAgIENoYWluT3BlcmF0aW9uRWRpdG9yQ29tcG9uZW50LFxyXG4gICAgQ2hhaW5SZXN1bHRWaWV3Q29tcG9uZW50LFxyXG4gICAgTG5IZWlnaHRzRWRpdG9yQ29tcG9uZW50LFxyXG4gICAgQW5pbWF0aW9uVGltZWxpbmVTZXRDb21wb25lbnQsXHJcbiAgXSxcclxuICBzY2hlbWFzOiBbQ1VTVE9NX0VMRU1FTlRTX1NDSEVNQV0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3NuYXBzaG90LWVkaXRvci5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3NuYXBzaG90LWVkaXRvci5jb21wb25lbnQuY3NzJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIFNuYXBzaG90RWRpdG9yQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICBwcml2YXRlIHJlYWRvbmx5IF9uYW5vaWQgPSBjdXN0b21BbHBoYWJldCgnMTIzNDU2Nzg5MGFiY2RlZicsIDEwKTtcclxuICBwcml2YXRlIF9zbmFwc2hvdD86IFNuYXBzaG90O1xyXG4gIHByaXZhdGUgX3JlbmRlcmVyPzogU25hcHNob3RWaWV3U2VydmljZTtcclxuICBwcml2YXRlIF9wcmV2aWV3aW5nPzogYm9vbGVhbjtcclxuICBwcml2YXRlIF90cmFuc3BhcmVudElkcz86IHN0cmluZ1tdO1xyXG4gIHByaXZhdGUgX3N0ZXBQaWNrRnJvemVuPzogYm9vbGVhbjtcclxuXHJcbiAgQFZpZXdDaGlsZCgnc25hcHNob3RWaWV3JywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgcHVibGljIHNuYXBzaG90Vmlldz86IEVsZW1lbnRSZWY8U25hcHNob3RWaWV3Q29tcG9uZW50PjtcclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIHNuYXBzaG90IHRvIGVkaXQuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBwdWJsaWMgZ2V0IHNuYXBzaG90KCk6IFNuYXBzaG90IHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl9zbmFwc2hvdDtcclxuICB9XHJcbiAgcHVibGljIHNldCBzbmFwc2hvdCh2YWx1ZTogU25hcHNob3QgfCB1bmRlZmluZWQgfCBudWxsKSB7XHJcbiAgICBpZiAodGhpcy5fc25hcHNob3QgPT09IHZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuX3NuYXBzaG90ID0gdmFsdWUgfHwgdW5kZWZpbmVkO1xyXG4gICAgdGhpcy51cGRhdGVGb3JtKHRoaXMuX3NuYXBzaG90KTtcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLnJ1blRvTGFzdCgpO1xyXG4gICAgfSwgMCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgYmF0Y2ggb3BlcmF0aW9ucyB0ZXh0IHRvIHNldCBmb3IgdGhlIGVkaXRvci5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBiYXRjaE9wcz86IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogVHJ1ZSB0byBkaXNhYmxlIHNhdmluZy5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBub1NhdmU/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBUcnVlIHRvIGVuYWJsZSBkZWJ1ZyBtb2RlIGZvciB2aWV3IHJlbmRpdGlvbi5cclxuICAgKi9cclxuICBASW5wdXQoKVxyXG4gIHB1YmxpYyBkZWJ1Zz86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgdXNlciBzYXZlcyB0aGUgZWRpdGVkIHNuYXBzaG90LlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKVxyXG4gIHB1YmxpYyByZWFkb25seSBzbmFwc2hvdENoYW5nZTogRXZlbnRFbWl0dGVyPFNuYXBzaG90PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRW1pdHRlZCB3aGVuIHRoZSB1c2VyIGNhbmNlbHMgdGhlIHNuYXBzaG90IGVkaXRpbmcuXHJcbiAgICovXHJcbiAgQE91dHB1dCgpXHJcbiAgcHVibGljIHJlYWRvbmx5IHNuYXBzaG90Q2FuY2VsID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICAvLyBnZW5lcmFsXHJcbiAgcHVibGljIHdpZHRoOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBoZWlnaHQ6IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIHN0eWxlOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcclxuICAvLyBiYXNlIHRleHRcclxuICBwdWJsaWMgYmFzZVRleHQ6IEZvcm1Db250cm9sPENoYXJOb2RlW10gfCBzdHJpbmc+O1xyXG4gIHB1YmxpYyBvZmZzZXRYOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBvZmZzZXRZOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBsaW5lSGVpZ2h0T2Zmc2V0OiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBsbkhlaWdodHM6IEZvcm1Db250cm9sPFJlY29yZDxudW1iZXIsIG51bWJlcj4gfCBudWxsPjtcclxuICBwdWJsaWMgY2hhclNwYWNpbmdPZmZzZXQ6IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIHNwY1dpZHRoT2Zmc2V0OiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyB0ZXh0U3R5bGU6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIC8vIG9wZXJhdGlvbnNcclxuICBwdWJsaWMgb3BlcmF0aW9uczogRm9ybUNvbnRyb2w8Q2hhckNoYWluT3BlcmF0aW9uW10+O1xyXG4gIHB1YmxpYyBpbnB1dE9wczogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XHJcbiAgcHVibGljIG9wU3R5bGU6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBmb3JtOiBGb3JtR3JvdXA7XHJcbiAgLy8gaW1hZ2UgYW5kIGRlZnNcclxuICBwdWJsaWMgaW1hZ2VVcmw6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBpbWFnZU9wYWNpdHk6IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIGltYWdlWDogRm9ybUNvbnRyb2w8bnVtYmVyPjtcclxuICBwdWJsaWMgaW1hZ2VZOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBpbWFnZVdpZHRoOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBpbWFnZUhlaWdodDogRm9ybUNvbnRyb2w8bnVtYmVyPjtcclxuICBwdWJsaWMgZGVmczogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XHJcbiAgLy8gdGltZWxpbmVzXHJcbiAgcHVibGljIHRpbWVsaW5lczogRm9ybUNvbnRyb2w8R3ZlQW5pbWF0aW9uVGltZWxpbmVbXT47XHJcbiAgLy8gbGlzdCBvZiBvcGVyYXRpb25zIG91dHB1dCB0YWdzXHJcbiAgcHVibGljIG9wVGFnczogc3RyaW5nW10gPSBbXTtcclxuICAvLyBsaXN0IG9mIG9wZXJhdGlvbiBkaXBsb21hdGljLmcgZWxlbWVudCBJRHNcclxuICBwdWJsaWMgb3BFbGVtZW50SWRzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAvLyB0aGUgY3VycmVudGx5IHBpY2tlZCBiYXNlIHRleHQgcmFuZ2VcclxuICBwdWJsaWMgdGV4dFJhbmdlPzogVmFyQmFzZVRleHRSYW5nZTtcclxuICAvLyB0aGUgbGluZXMgY291bnQgZm9yIHRoZSBjdXJyZW50IGJhc2UgdGV4dFxyXG4gIHB1YmxpYyBsaW5lQ291bnQgPSAwO1xyXG5cclxuICAvLyB0aGUgY3VycmVudGx5IGVkaXRlZCBvcGVyYXRpb25cclxuICBwdWJsaWMgZWRpdGVkT3A/OiBDaGFyQ2hhaW5PcGVyYXRpb247XHJcbiAgcHVibGljIGVkaXRlZE9wSW5kZXggPSAtMTtcclxuXHJcbiAgcHVibGljIGJ1c3k/OiBib29sZWFuO1xyXG4gIHB1YmxpYyBwYXJzZUVycm9yPzogc3RyaW5nO1xyXG4gIHB1YmxpYyBvcFR5cGVNYXAgPSB7XHJcbiAgICAwOiAncmVwbGFjZScsXHJcbiAgICAxOiAnZGVsZXRlJyxcclxuICAgIDI6ICdhZGQtYmVmb3JlJyxcclxuICAgIDM6ICdhZGQtYWZ0ZXInLFxyXG4gICAgNDogJ21vdmUtYmVmb3JlJyxcclxuICAgIDU6ICdtb3ZlLWFmdGVyJyxcclxuICAgIDY6ICdzd2FwJyxcclxuICAgIDc6ICdhbm5vdGF0ZScsXHJcbiAgfTtcclxuXHJcbiAgLy8gc25hcHNob3QgdmlldyBkYXRhXHJcbiAgcHVibGljIHZpZXdUaXRsZSA9IFZJRVdfVElUTEU7XHJcbiAgcHVibGljIHZpZXdEYXRhPzogU25hcHNob3RWaWV3RGF0YTtcclxuICBwdWJsaWMgdmlzdWFsSW5mbz86IHN0cmluZztcclxuICBwdWJsaWMgcnVsZXJzID0gdHJ1ZTtcclxuXHJcbiAgLy8gb3BlcmF0aW9ucyBleGVjdXRpb24gcmVzdWx0XHJcbiAgcHVibGljIHJlc3VsdD86IENoYXJDaGFpblJlc3VsdDtcclxuICBwdWJsaWMgcmVzdWx0T3BlcmF0aW9uSWQ/OiBzdHJpbmc7XHJcbiAgcHVibGljIGluaXRpYWxTdGVwSW5kZXggPSAtMTtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBmb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXIsXHJcbiAgICBwcml2YXRlIF9hcGk6IEd2ZUFwaVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIF9kaWFsb2dTZXJ2aWNlOiBEaWFsb2dTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBfc25hY2tiYXI6IE1hdFNuYWNrQmFyXHJcbiAgKSB7XHJcbiAgICAvLyBnZW5lcmFsXHJcbiAgICB0aGlzLndpZHRoID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oODAwLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xyXG4gICAgdGhpcy5oZWlnaHQgPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPig2MDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLnN0eWxlID0gbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG4gICAgLy8gYmFzZSB0ZXh0XHJcbiAgICB0aGlzLmJhc2VUZXh0ID0gbmV3IEZvcm1Db250cm9sPENoYXJOb2RlW10gfCBzdHJpbmc+KFtdLCB7XHJcbiAgICAgIG5vbk51bGxhYmxlOiB0cnVlLFxyXG4gICAgICB2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF0sXHJcbiAgICB9KTtcclxuICAgIHRoaXMub2Zmc2V0WCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLm9mZnNldFkgPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPigwLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xyXG4gICAgdGhpcy5saW5lSGVpZ2h0T2Zmc2V0ID0gbmV3IEZvcm1Db250cm9sPG51bWJlcj4oXHJcbiAgICAgIERFRkFVTFRfU1ZHX0JBU0VfVEVYVF9PUFRJT05TLmxpbmVIZWlnaHRPZmZzZXQsXHJcbiAgICAgIHsgbm9uTnVsbGFibGU6IHRydWUgfVxyXG4gICAgKTtcclxuICAgIHRoaXMubG5IZWlnaHRzID0gbmV3IEZvcm1Db250cm9sPFJlY29yZDxudW1iZXIsIG51bWJlcj4gfCBudWxsPihudWxsKTtcclxuICAgIHRoaXMuY2hhclNwYWNpbmdPZmZzZXQgPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPigwLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xyXG4gICAgdGhpcy5zcGNXaWR0aE9mZnNldCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLnRleHRTdHlsZSA9IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuXHJcbiAgICAvLyBvcGVyYXRpb25zXHJcbiAgICB0aGlzLm9wZXJhdGlvbnMgPSBuZXcgRm9ybUNvbnRyb2w8Q2hhckNoYWluT3BlcmF0aW9uW10+KFtdLCB7XHJcbiAgICAgIG5vbk51bGxhYmxlOiB0cnVlLFxyXG4gICAgfSk7XHJcbiAgICB0aGlzLmlucHV0T3BzID0gbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG4gICAgdGhpcy5vcFN0eWxlID0gbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG4gICAgLy8gaW1hZ2VcclxuICAgIHRoaXMuaW1hZ2VVcmwgPSBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcbiAgICB0aGlzLmltYWdlT3BhY2l0eSA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDEsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmltYWdlWCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmltYWdlWSA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmltYWdlV2lkdGggPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPigwLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xyXG4gICAgdGhpcy5pbWFnZUhlaWdodCA9IG5ldyBGb3JtQ29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmRlZnMgPSBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcblxyXG4gICAgLy8gdGltZWxpbmVzXHJcbiAgICB0aGlzLnRpbWVsaW5lcyA9IG5ldyBGb3JtQ29udHJvbDxHdmVBbmltYXRpb25UaW1lbGluZVtdPihbXSwge1xyXG4gICAgICBub25OdWxsYWJsZTogdHJ1ZSxcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIGZvcm1cclxuICAgIHRoaXMuZm9ybSA9IGZvcm1CdWlsZGVyLmdyb3VwKHtcclxuICAgICAgd2lkdGg6IHRoaXMud2lkdGgsXHJcbiAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQsXHJcbiAgICAgIHN0eWxlOiB0aGlzLnN0eWxlLFxyXG4gICAgICBiYXNlVGV4dDogdGhpcy5iYXNlVGV4dCxcclxuICAgICAgb2Zmc2V0WDogdGhpcy5vZmZzZXRYLFxyXG4gICAgICBvZmZzZXRZOiB0aGlzLm9mZnNldFksXHJcbiAgICAgIGxpbmVIZWlnaHRPZmZzZXQ6IHRoaXMubGluZUhlaWdodE9mZnNldCxcclxuICAgICAgbG5IZWlnaHRzOiB0aGlzLmxuSGVpZ2h0cyxcclxuICAgICAgY2hhclNwYWNpbmdPZmZzZXQ6IHRoaXMuY2hhclNwYWNpbmdPZmZzZXQsXHJcbiAgICAgIHNwY1dpZHRoT2Zmc2V0OiB0aGlzLnNwY1dpZHRoT2Zmc2V0LFxyXG4gICAgICB0ZXh0U3R5bGU6IHRoaXMudGV4dFN0eWxlLFxyXG4gICAgICBvcGVyYXRpb25zOiB0aGlzLm9wZXJhdGlvbnMsXHJcbiAgICAgIGlucHV0T3BzOiB0aGlzLmlucHV0T3BzLFxyXG4gICAgICBvcFN0eWxlOiB0aGlzLm9wU3R5bGUsXHJcbiAgICAgIC8vIGltYWdlXHJcbiAgICAgIGltYWdlVXJsOiB0aGlzLmltYWdlVXJsLFxyXG4gICAgICBpbWFnZU9wYWNpdHk6IHRoaXMuaW1hZ2VPcGFjaXR5LFxyXG4gICAgICBpbWFnZVg6IHRoaXMuaW1hZ2VYLFxyXG4gICAgICBpbWFnZVk6IHRoaXMuaW1hZ2VZLFxyXG4gICAgICBpbWFnZVdpZHRoOiB0aGlzLmltYWdlV2lkdGgsXHJcbiAgICAgIGltYWdlSGVpZ2h0OiB0aGlzLmltYWdlSGVpZ2h0LFxyXG4gICAgICBkZWZzOiB0aGlzLmRlZnMsXHJcbiAgICAgIC8vIHRpbWVsaW5lc1xyXG4gICAgICB0aW1lbGluZXM6IHRoaXMudGltZWxpbmVzLFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICAvLyBpZiB0aGVyZSBhcmUgYW55IGJhdGNoIG9wZXJhdGlvbnMsIHBhcnNlIHRoZW0gaW50byBzbmFwc2hvdCBvcGVyYXRpb25zXHJcbiAgICBpZiAodGhpcy5iYXRjaE9wcykge1xyXG4gICAgICB0aGlzLmlucHV0T3BzLnNldFZhbHVlKHRoaXMuYmF0Y2hPcHMpO1xyXG4gICAgICB0aGlzLnBhcnNlT3BlcmF0aW9ucygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0IHRoZSB2aWV3IGRhdGEgZm9yIHRoZSBzbmFwc2hvdCB2aWV3LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHNuYXBzaG90IFRoZSBvcHRpb25hbCBzbmFwc2hvdCBkYXRhIHRvIHVzZS4gSWYgbm90IHByb3ZpZGVkLFxyXG4gICAqIGEgc25hcHNob3Qgd2lsbCBiZSBjcmVhdGVkIGZyb20gdGhlIGZvcm0gZGF0YS5cclxuICAgKiBAcGFyYW0gdGl0bGUgVGhlIG9wdGlvbmFsIHRpdGxlIHRvIHNldCBmb3IgdGhlIHZpZXcuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzZXRWaWV3RGF0YShzbmFwc2hvdD86IFNuYXBzaG90LCB0aXRsZSA9IFZJRVdfVElUTEUpOiB2b2lkIHtcclxuICAgIGNvbnNvbGUubG9nKCdzZXQgdmlldyBkYXRhJyk7XHJcblxyXG4gICAgLy8gZ2V0IHRoZSBzbmFwc2hvdCB0byB1c2VcclxuICAgIGlmICghc25hcHNob3QpIHtcclxuICAgICAgc25hcHNob3QgPSB0aGlzLmdldFNuYXBzaG90KCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdXBkYXRlIHZpZXcgZGF0YVxyXG4gICAgdGhpcy52aWV3VGl0bGUgPSB0aXRsZTtcclxuICAgIHRoaXMudmlzdWFsSW5mbyA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMudmlld0RhdGEgPSB7XHJcbiAgICAgIHNuYXBzaG90OiBzbmFwc2hvdCxcclxuICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgIGRlYnVnOiB0aGlzLmRlYnVnLFxyXG4gICAgICAgIGRlbGF5ZWRSZW5kZXI6IHRydWUsXHJcbiAgICAgICAgc2hvd1J1bGVyczogdHJ1ZSxcclxuICAgICAgICBzaG93R3JpZDogdHJ1ZSxcclxuICAgICAgICBwYW5ab29tOiB0cnVlLFxyXG4gICAgICAgIHRyYW5zcGFyZW50SWRzOiB0aGlzLl90cmFuc3BhcmVudElkcyxcclxuICAgICAgfSxcclxuICAgIH07XHJcblxyXG4gICAgY29uc29sZS5sb2coJ3ZpZXcgZGF0YTogJywgdGhpcy52aWV3RGF0YSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZUZvcm0oc25hcHNob3Q6IFNuYXBzaG90IHwgdW5kZWZpbmVkKSB7XHJcbiAgICB0aGlzLl90cmFuc3BhcmVudElkcyA9IHVuZGVmaW5lZDtcclxuICAgIHRoaXMuaW5pdGlhbFN0ZXBJbmRleCA9IC0xO1xyXG5cclxuICAgIGlmICghc25hcHNob3QpIHtcclxuICAgICAgdGhpcy5mb3JtLnJlc2V0KCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLndpZHRoLnNldFZhbHVlKHNuYXBzaG90LnNpemUud2lkdGgpO1xyXG4gICAgICB0aGlzLmhlaWdodC5zZXRWYWx1ZShzbmFwc2hvdC5zaXplLmhlaWdodCk7XHJcbiAgICAgIHRoaXMuc3R5bGUuc2V0VmFsdWUoc25hcHNob3Quc3R5bGUgfHwgbnVsbCk7XHJcbiAgICAgIHRoaXMuaW1hZ2VVcmwuc2V0VmFsdWUoc25hcHNob3QuaW1hZ2U/LnVybCB8fCBudWxsKTtcclxuICAgICAgdGhpcy5pbWFnZU9wYWNpdHkuc2V0VmFsdWUoc25hcHNob3QuaW1hZ2U/Lm9wYWNpdHkgfHwgMCk7XHJcbiAgICAgIHRoaXMuaW1hZ2VYLnNldFZhbHVlKHNuYXBzaG90LmltYWdlPy5jYW52YXM/LnggfHwgMCk7XHJcbiAgICAgIHRoaXMuaW1hZ2VZLnNldFZhbHVlKHNuYXBzaG90LmltYWdlPy5jYW52YXM/LnkgfHwgMCk7XHJcbiAgICAgIHRoaXMuaW1hZ2VXaWR0aC5zZXRWYWx1ZShzbmFwc2hvdC5pbWFnZT8uY2FudmFzPy53aWR0aCB8fCAwKTtcclxuICAgICAgdGhpcy5pbWFnZUhlaWdodC5zZXRWYWx1ZShzbmFwc2hvdC5pbWFnZT8uY2FudmFzPy5oZWlnaHQgfHwgMCk7XHJcbiAgICAgIHRoaXMuZGVmcy5zZXRWYWx1ZShzbmFwc2hvdC5kZWZzIHx8IG51bGwpO1xyXG4gICAgICB0aGlzLmJhc2VUZXh0LnNldFZhbHVlKHNuYXBzaG90LnRleHQpO1xyXG4gICAgICB0aGlzLm9mZnNldFguc2V0VmFsdWUoc25hcHNob3QudGV4dE9wdGlvbnM/Lm9mZnNldD8ueCB8fCAwKTtcclxuICAgICAgdGhpcy5vZmZzZXRZLnNldFZhbHVlKHNuYXBzaG90LnRleHRPcHRpb25zPy5vZmZzZXQ/LnkgfHwgMCk7XHJcbiAgICAgIHRoaXMubGluZUhlaWdodE9mZnNldC5zZXRWYWx1ZShzbmFwc2hvdC50ZXh0T3B0aW9ucz8ubGluZUhlaWdodE9mZnNldCk7XHJcbiAgICAgIHRoaXMubG5IZWlnaHRzLnNldFZhbHVlKHNuYXBzaG90LnRleHRPcHRpb25zPy5taW5MaW5lSGVpZ2h0cyB8fCBudWxsKTtcclxuICAgICAgdGhpcy5jaGFyU3BhY2luZ09mZnNldC5zZXRWYWx1ZShzbmFwc2hvdC50ZXh0T3B0aW9ucz8uY2hhclNwYWNpbmdPZmZzZXQpO1xyXG4gICAgICB0aGlzLnNwY1dpZHRoT2Zmc2V0LnNldFZhbHVlKHNuYXBzaG90LnRleHRPcHRpb25zPy5zcGNXaWR0aE9mZnNldCk7XHJcbiAgICAgIHRoaXMudGV4dFN0eWxlLnNldFZhbHVlKHNuYXBzaG90LnRleHRTdHlsZSB8fCBudWxsKTtcclxuICAgICAgdGhpcy5vcGVyYXRpb25zLnNldFZhbHVlKHNuYXBzaG90Lm9wZXJhdGlvbnMpO1xyXG4gICAgICB0aGlzLmlucHV0T3BzLnJlc2V0KCk7XHJcbiAgICAgIHRoaXMub3BTdHlsZS5zZXRWYWx1ZShzbmFwc2hvdC5vcFN0eWxlIHx8IG51bGwpO1xyXG4gICAgICAvLyB0aW1lbGluZXNcclxuICAgICAgY29uc3QgdGltZWxpbmVzOiBHdmVBbmltYXRpb25UaW1lbGluZVtdID0gW107XHJcbiAgICAgIGlmIChzbmFwc2hvdC50aW1lbGluZXMpIHtcclxuICAgICAgICBmb3IgKGxldCB0YWcgaW4gc25hcHNob3QudGltZWxpbmVzKSB7XHJcbiAgICAgICAgICB0aW1lbGluZXMucHVzaChzbmFwc2hvdC50aW1lbGluZXNbdGFnXSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudGltZWxpbmVzLnNldFZhbHVlKHRpbWVsaW5lcyk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnVwZGF0ZUxpbmVDb3VudCh0aGlzLmJhc2VUZXh0LnZhbHVlIGFzIENoYXJOb2RlW10pO1xyXG4gICAgdGhpcy51cGRhdGVPcExpc3RzKCk7XHJcblxyXG4gICAgdGhpcy5mb3JtLm1hcmtBc1ByaXN0aW5lKCk7XHJcbiAgfVxyXG5cclxuICAvLyAjcmVnaW9uIGJhc2UgdGV4dFxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZSB0aGUgbGluZSBjb3VudCBiYXNlZCBvbiB0aGUgcmVjZWl2ZWQgdGV4dC5cclxuICAgKiBAcGFyYW0gdGV4dCBUaGUgdGV4dCB0byB1c2UgZm9yIGNvdW50aW5nIGxpbmVzLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgdXBkYXRlTGluZUNvdW50KHRleHQ6IENoYXJOb2RlW10pIHtcclxuICAgIGlmICghdGV4dC5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5saW5lQ291bnQgPSAwO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5saW5lQ291bnQgPSB0ZXh0LmZpbHRlcigoYykgPT4gYy5kYXRhID09PSAnXFxuJykubGVuZ3RoICsgMTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZSB0aGUgZXZlbnQgZmlyZWQgYnkgdGhlIGJhc2UgdGV4dCBlZGl0b3IgdG8gcGljayBhIHRleHQgcmFuZ2UuXHJcbiAgICogQHBhcmFtIHJhbmdlIFRoZSBwaWNrZWQgcmFuZ2UuXHJcbiAgICovXHJcbiAgcHVibGljIG9uUmFuZ2VQaWNrKHJhbmdlOiBWYXJCYXNlVGV4dFJhbmdlKSB7XHJcbiAgICB0aGlzLnRleHRSYW5nZSA9IHJhbmdlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlIHRoZSBldmVudCBmaXJlZCBieSB0aGUgYmFzZSB0ZXh0IGVkaXRvciB0byBjaGFuZ2UgdGhlIGJhc2UgdGV4dC5cclxuICAgKiBAcGFyYW0gdGV4dCBUaGUgdGV4dCB0byBzZXQuXHJcbiAgICovXHJcbiAgcHVibGljIG9uVGV4dENoYW5nZSh0ZXh0OiBDaGFyTm9kZVtdKSB7XHJcbiAgICBjb25zb2xlLmxvZygndGV4dCBjaGFuZ2U6ICcgKyB0ZXh0KTtcclxuXHJcbiAgICAvLyB1cGRhdGUgdGhlIGZvcm0gY29udHJvbCBhbmQgcmVzZXQgdGhlIGN1cnJlbnQgdGV4dCByYW5nZVxyXG4gICAgdGhpcy5iYXNlVGV4dC5zZXRWYWx1ZSh0ZXh0KTtcclxuICAgIHRoaXMuYmFzZVRleHQudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgdGhpcy5iYXNlVGV4dC5tYXJrQXNEaXJ0eSgpO1xyXG4gICAgdGhpcy50ZXh0UmFuZ2UgPSB1bmRlZmluZWQ7XHJcblxyXG4gICAgLy8gdXBkYXRlIHRoZSBsaW5lIGNvdW50XHJcbiAgICB0aGlzLnVwZGF0ZUxpbmVDb3VudCh0ZXh0KTtcclxuXHJcbiAgICAvLyByZW1vdmUgYWxsIG9wZXJhdGlvbnMgYW5kIHVwZGF0ZSB0aGUgdmlldyBkYXRhXHJcbiAgICB0aGlzLnJlbW92ZUFsbE9wZXJhdGlvbnMoKTtcclxuICB9XHJcbiAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAvLyAjcmVnaW9uIG9wZXJhdGlvbnNcclxuICAvKipcclxuICAgKiBVcGRhdGUgdGhlIGxpc3RzIG9mIG9wZXJhdGlvbiBvdXRwdXQgdGFncyBhbmQgZWxlbWVudCBJRHMgYnkgY29sbGVjdGluZ1xyXG4gICAqIGFsbCB0aGUgb3BlcmF0aW9uIHRhZ3MgYW5kIHRoZSBJRHMgb2YgdGhlIGVsZW1lbnRzIGluIHRoZWlyIGRpcGxvbWF0aWMuZ1xyXG4gICAqIFNWRyBjb2RlIGlmIGFueS5cclxuICAgKi9cclxuICBwcml2YXRlIHVwZGF0ZU9wTGlzdHMoKSB7XHJcbiAgICBjb25zdCB0YWdzID0gbmV3IFNldDxzdHJpbmc+KCk7XHJcbiAgICBjb25zdCBpZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcclxuXHJcbiAgICBsZXQgbiA9IDA7XHJcbiAgICBmb3IgKGNvbnN0IG9wIG9mIHRoaXMub3BlcmF0aW9ucy52YWx1ZSkge1xyXG4gICAgICAvLyBvdXRwdXQgdGFnXHJcbiAgICAgIG4rKztcclxuICAgICAgdGFncy5hZGQob3Aub3V0cHV0VGFnIHx8IGB2JHtufWApO1xyXG5cclxuICAgICAgLy8gZWxlbWVudCBJRHNcclxuICAgICAgaWYgKG9wLmRpcGxvbWF0aWNzPy5nKSB7XHJcbiAgICAgICAgdGhpcy5wYXJzZVN2Z0lkcyhvcC5kaXBsb21hdGljcy5nKT8uZm9yRWFjaCgoaWQpID0+IGlkcy5hZGQoaWQpKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMub3BUYWdzID0gWy4uLnRhZ3NdO1xyXG4gICAgdGhpcy5vcEVsZW1lbnRJZHMgPSBbLi4uaWRzXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEVkaXQgYSBuZXcgb3BlcmF0aW9uLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBlZGl0TmV3T3BlcmF0aW9uKCkge1xyXG4gICAgLy8gY3JlYXRlIGEgbmV3IG9wZXJhdGlvbiBhbmQgZWRpdCBpdFxyXG4gICAgdGhpcy5lZGl0ZWRPcCA9IHtcclxuICAgICAgaWQ6IHRoaXMuX25hbm9pZCgpLFxyXG4gICAgICB0eXBlOiAwLFxyXG4gICAgICBhdDogdGhpcy50ZXh0UmFuZ2U/LmF0IHx8IDAsXHJcbiAgICAgIHJ1bjogdGhpcy50ZXh0UmFuZ2U/LnJ1biB8fCAxLFxyXG4gICAgfTtcclxuICAgIHRoaXMuZWRpdGVkT3BJbmRleCA9IC0xO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRWRpdCAoYSBjb3B5IG9mKSB0aGUgb3BlcmF0aW9uIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguXHJcbiAgICogQHBhcmFtIGluZGV4IFRoZSBvcGVyYXRpb24gaW5kZXguXHJcbiAgICovXHJcbiAgcHVibGljIGVkaXRPcGVyYXRpb24oaW5kZXg6IG51bWJlcikge1xyXG4gICAgdGhpcy5lZGl0ZWRPcEluZGV4ID0gaW5kZXg7XHJcbiAgICB0aGlzLmVkaXRlZE9wID0gZGVlcENvcHkodGhpcy5vcGVyYXRpb25zLnZhbHVlW2luZGV4XSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbG9zZSB0aGUgY3VycmVudGx5IGVkaXRlZCBvcGVyYXRpb24uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjbG9zZUVkaXRlZE9wZXJhdGlvbigpIHtcclxuICAgIHRoaXMuZWRpdGVkT3BJbmRleCA9IC0xO1xyXG4gICAgdGhpcy5lZGl0ZWRPcCA9IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZSB0aGUgZXZlbnQgZmlyZWQgYnkgdGhlIG9wZXJhdGlvbiBlZGl0b3IgdG8gY2FuY2VsXHJcbiAgICogdGhlIGN1cnJlbnQgb3BlcmF0aW9uIGVkaXRzLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBvbk9wZXJhdGlvbkNhbmNlbCgpIHtcclxuICAgIHRoaXMuY2xvc2VFZGl0ZWRPcGVyYXRpb24oKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZSB0aGUgZXZlbnQgZmlyZWQgYnkgdGhlIG9wZXJhdGlvbiBlZGl0b3IgdG8gY2hhbmdlXHJcbiAgICogdGhlIGN1cnJlbnRseSBlZGl0ZWQgb3BlcmF0aW9uLCBvciBhZGQgYSBuZXcgb25lIGlmIHRoYXRcclxuICAgKiB3YXMgYSBuZXcgb3BlcmF0aW9uLlxyXG4gICAqIEBwYXJhbSBvcCBUaGUgY2hhbmdlZCBvcGVyYXRpb24uXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIG9uT3BlcmF0aW9uQ2hhbmdlKG9wOiBDaGFyQ2hhaW5PcGVyYXRpb24pIHtcclxuICAgIGNvbnNvbGUubG9nKCdvcGVyYXRpb24gY2hhbmdlJyk7XHJcbiAgICBjb25zdCBvcGVyYXRpb25zID0gWy4uLnRoaXMub3BlcmF0aW9ucy52YWx1ZV07XHJcblxyXG4gICAgLy8gcmVwbGFjZSBvciBhZGQgdGhlIG9wZXJhdGlvblxyXG4gICAgbGV0IGkgPSB0aGlzLmVkaXRlZE9wSW5kZXg7XHJcbiAgICBpZiAodGhpcy5lZGl0ZWRPcEluZGV4ID4gLTEpIHtcclxuICAgICAgb3BlcmF0aW9ucy5zcGxpY2UodGhpcy5lZGl0ZWRPcEluZGV4LCAxLCBvcCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBvcGVyYXRpb25zLnB1c2gob3ApO1xyXG4gICAgICBpID0gb3BlcmF0aW9ucy5sZW5ndGggLSAxO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHVwZGF0ZSB0aGUgb3BlcmF0aW9ucyBmb3JtIGNvbnRyb2xcclxuICAgIHRoaXMub3BlcmF0aW9ucy5zZXRWYWx1ZShvcGVyYXRpb25zKTtcclxuICAgIHRoaXMub3BlcmF0aW9ucy5tYXJrQXNEaXJ0eSgpO1xyXG4gICAgdGhpcy5vcGVyYXRpb25zLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuXHJcbiAgICAvLyB1cGRhdGUgdGhlIG9wZXJhdGlvbiBsaXN0c1xyXG4gICAgdGhpcy51cGRhdGVPcExpc3RzKCk7XHJcblxyXG4gICAgLy8gdXBkYXRlIHRoZSB2aWV3IGRhdGFcclxuICAgIGF3YWl0IHRoaXMucnVuVG8oaSk7XHJcblxyXG4gICAgLy8gY2xvc2UgdGhlIGVkaXRlZCBvcGVyYXRpb25cclxuICAgIHRoaXMuY2xvc2VFZGl0ZWRPcGVyYXRpb24oKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlbGV0ZSB0aGUgb3BlcmF0aW9uIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguXHJcbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgb3BlcmF0aW9uIHRvIGRlbGV0ZS5cclxuICAgKi9cclxuICBwdWJsaWMgZGVsZXRlT3BlcmF0aW9uKGluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMuX2RpYWxvZ1NlcnZpY2VcclxuICAgICAgLmNvbmZpcm0oXHJcbiAgICAgICAgJ0NvbmZpcm0gRGVsZXRpb24nLFxyXG4gICAgICAgIGBEZWxldGUgb3BlcmF0aW9uIFwiJHt0aGlzLm9wZXJhdGlvbnMudmFsdWVbaW5kZXhdLmlkfVwiP2BcclxuICAgICAgKVxyXG4gICAgICAuc3Vic2NyaWJlKCh5ZXM6IGJvb2xlYW4pID0+IHtcclxuICAgICAgICBpZiAoeWVzKSB7XHJcbiAgICAgICAgICAvLyBjbG9zZSB0aGUgZWRpdGVkIG9wZXJhdGlvbiBpZiBpdCBpcyB0aGUgb25lIGJlaW5nIGRlbGV0ZWRcclxuICAgICAgICAgIGlmICh0aGlzLmVkaXRlZE9wSW5kZXggPT09IGluZGV4KSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2xvc2VFZGl0ZWRPcGVyYXRpb24oKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIC8vIHJlc2V0IHRoZSByZXN1bHQgb3BlcmF0aW9uIElEIGlmIGl0IGlzIHRoZSBvbmUgYmVpbmcgZGVsZXRlZFxyXG4gICAgICAgICAgaWYgKHRoaXMucmVzdWx0T3BlcmF0aW9uSWQgPT09IHRoaXMub3BlcmF0aW9ucy52YWx1ZVtpbmRleF0uaWQpIHtcclxuICAgICAgICAgICAgdGhpcy5yZXN1bHRPcGVyYXRpb25JZCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIC8vIGRlbGV0ZSB0aGUgb3BlcmF0aW9uIGFuZCB1cGRhdGUgdGhlIGZvcm0gY29udHJvbFxyXG4gICAgICAgICAgY29uc3Qgb3BlcmF0aW9ucyA9IFsuLi50aGlzLm9wZXJhdGlvbnMudmFsdWVdO1xyXG4gICAgICAgICAgb3BlcmF0aW9ucy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICAgICAgdGhpcy5vcGVyYXRpb25zLnNldFZhbHVlKG9wZXJhdGlvbnMpO1xyXG4gICAgICAgICAgdGhpcy5vcGVyYXRpb25zLm1hcmtBc0RpcnR5KCk7XHJcbiAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG5cclxuICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgb3BlcmF0aW9uIGxpc3RzXHJcbiAgICAgICAgICB0aGlzLnVwZGF0ZU9wTGlzdHMoKTtcclxuXHJcbiAgICAgICAgICAvLyB1cGRhdGUgdGhlIHZpZXcgZGF0YVxyXG4gICAgICAgICAgdGhpcy5ydW5Ub0xhc3QoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGFyc2UgdGhlIG9wZXJhdGlvbnMgZnJvbSB0aGVpciB0ZXh0IGFuZCBhcHBlbmQgdGhlbSB0byB0aGUgY3VycmVudFxyXG4gICAqIHNuYXBzaG90IG9wZXJhdGlvbnMuXHJcbiAgICovXHJcbiAgcHVibGljIHBhcnNlT3BlcmF0aW9ucygpIHtcclxuICAgIGlmICh0aGlzLmJ1c3kgfHwgIXRoaXMuaW5wdXRPcHMudmFsdWUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fZGlhbG9nU2VydmljZVxyXG4gICAgICAuY29uZmlybSgnQ29uZmlybScsICdQYXJzZSBvcGVyYXRpb25zPycpXHJcbiAgICAgIC5zdWJzY3JpYmUoKHllczogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgIGlmICh5ZXMpIHtcclxuICAgICAgICAgIHRoaXMuYnVzeSA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSB1bmRlZmluZWQ7XHJcblxyXG4gICAgICAgICAgdGhpcy5fYXBpLnBhcnNlT3BlcmF0aW9ucyh0aGlzLmlucHV0T3BzLnZhbHVlISkuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgbmV4dDogKHdyYXBwZXIpID0+IHtcclxuICAgICAgICAgICAgICBjb25zdCBvcGVyYXRpb25zID0gWy4uLnRoaXMub3BlcmF0aW9ucy52YWx1ZV07XHJcbiAgICAgICAgICAgICAgb3BlcmF0aW9ucy5wdXNoKC4uLndyYXBwZXIucmVzdWx0ISk7XHJcbiAgICAgICAgICAgICAgdGhpcy5vcGVyYXRpb25zLnNldFZhbHVlKG9wZXJhdGlvbnMpO1xyXG4gICAgICAgICAgICAgIHRoaXMub3BlcmF0aW9ucy5tYXJrQXNEaXJ0eSgpO1xyXG4gICAgICAgICAgICAgIHRoaXMub3BlcmF0aW9ucy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcbiAgICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSBvcGVyYXRpb24gbGlzdHNcclxuICAgICAgICAgICAgICB0aGlzLnVwZGF0ZU9wTGlzdHMoKTtcclxuICAgICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHZpZXcgZGF0YVxyXG4gICAgICAgICAgICAgIHRoaXMucnVuVG9MYXN0KCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSBlcnJvci5tZXNzYWdlO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgICAgIHRoaXMuYnVzeSA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVtb3ZlQWxsT3BlcmF0aW9ucygpOiB2b2lkIHtcclxuICAgIHRoaXMucmVzdWx0T3BlcmF0aW9uSWQgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLmNsb3NlRWRpdGVkT3BlcmF0aW9uKCk7XHJcbiAgICB0aGlzLm9wZXJhdGlvbnMucmVzZXQoKTtcclxuICAgIHRoaXMub3BlcmF0aW9ucy5tYXJrQXNEaXJ0eSgpO1xyXG4gICAgdGhpcy5vcGVyYXRpb25zLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgIHRoaXMub3BUYWdzID0gW107XHJcbiAgICB0aGlzLm9wRWxlbWVudElkcyA9IFtdO1xyXG4gICAgdGhpcy5zZXRWaWV3RGF0YSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIGFsbCB0aGUgb3BlcmF0aW9ucy5cclxuICAgKi9cclxuICBwdWJsaWMgY2xlYXJPcGVyYXRpb25zKCk6IHZvaWQge1xyXG4gICAgdGhpcy5fZGlhbG9nU2VydmljZVxyXG4gICAgICAuY29uZmlybSgnQ29uZmlybScsICdSZW1vdmUgYWxsIG9wZXJhdGlvbnM/JylcclxuICAgICAgLnN1YnNjcmliZSgoeWVzOiBib29sZWFuKSA9PiB7XHJcbiAgICAgICAgaWYgKHllcykge1xyXG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxPcGVyYXRpb25zKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBhcnNlIGFsbCB0aGUgaWQgYXR0cmlidXRlcyBmcm9tIHRoZSByZWNlaXZlZCBTVkcgY29kZSBhbmRcclxuICAgKiByZXR1cm4gdGhlbSBhcyBhbiBhcnJheS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBzdmcgVGhlIFNWRyBjb250ZW50IHRvIHBhcnNlIG9yIHVuZGVmaW5lZC5cclxuICAgKiBAcmV0dXJucyBBcnJheSBvZiBJRHMgZm91bmQgaW4gdGhlIFNWRyBjb250ZW50IG9yIHVuZGVmaW5lZC5cclxuICAgKi9cclxuICBwcml2YXRlIHBhcnNlU3ZnSWRzKHN2Zz86IHN0cmluZyk6IHN0cmluZ1tdIHwgdW5kZWZpbmVkIHtcclxuICAgIGlmICghc3ZnKSB7XHJcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgcmVnZXggPSAvPFtePl0rXFxiaWQ9KFtcIiddKSguKj8pXFwxL2c7XHJcbiAgICBjb25zdCBpZHM6IHN0cmluZ1tdID0gW107XHJcbiAgICBsZXQgbWF0Y2g6IFJlZ0V4cEV4ZWNBcnJheSB8IG51bGw7XHJcblxyXG4gICAgd2hpbGUgKChtYXRjaCA9IHJlZ2V4LmV4ZWMoc3ZnKSkgIT09IG51bGwpIHtcclxuICAgICAgaWRzLnB1c2gobWF0Y2hbMl0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBpZHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSdW4gdGhlIG9wZXJhdGlvbnMgdXAgdG8gdGhlIHNwZWNpZmllZCBpbmRleCAoaW5jbHVkZWQpLlxyXG4gICAqIFRoaXMgaXMgY2FsbGVkIHdoZW46XHJcbiAgICogLSBhIHByZXZpZXcgaXMgcmVxdWVzdGVkIGJ5IHRoZSBvcGVyYXRpb24gZWRpdG9yLlxyXG4gICAqIC0gdGhlIGN1cnJlbnRseSBlZGl0ZWQgb3BlcmF0aW9uIGlzIHNhdmVkLlxyXG4gICAqIC0gdGhlIHVzZXIgcGlja3MgYSBzdGVwIGluIHRoZSBjaGFpbiByZXN1bHQgdmlldy5cclxuICAgKiAtIHJ1blRvTGFzdCBpcyBjYWxsZWQsIHdoaWNoIGhhcHBlbnMgd2hlbjpcclxuICAgKiAgIC0gc2V0dGluZyB0aGUgc25hcHNob3QuXHJcbiAgICogICAtIHBhcnNpbmcgYSBiYXRjaCBvZiBvcGVyYXRpb25zLlxyXG4gICAqICAgLSBkZWxldGluZyBhbiBvcGVyYXRpb24uXHJcbiAgICpcclxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBvcGVyYXRpb24gdG8gcnVuIHRvLlxyXG4gICAqIEBwYXJhbSBsYXN0T3BlcmF0aW9uIFRoZSBvcGVyYXRpb24gdG8gdXNlIGluIHBsYWNlIG9mIHRoZSBleGlzdGluZ1xyXG4gICAqIG9wZXJhdGlvbiBpbiB0aGUgc25hcHNob3QgYXQgaW5kZXguIFRoaXMgaXMgdXNlZCB3aGVuIHByZXZpZXdpbmdcclxuICAgKiB0aGUgZWRpdGVkIG9wZXJhdGlvbiBmcm9tIHdpdGhpbiB0aGUgb3BlcmF0aW9uIGVkaXRvci5cclxuICAgKi9cclxuICBwdWJsaWMgcnVuVG8oXHJcbiAgICBpbmRleDogbnVtYmVyLFxyXG4gICAgbGFzdE9wZXJhdGlvbj86IENoYXJDaGFpbk9wZXJhdGlvblxyXG4gICk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgaWYgKHRoaXMuYnVzeSkge1xyXG4gICAgICAgIHJldHVybiByZWplY3QoJ0J1c3knKTtcclxuICAgICAgfVxyXG4gICAgICBjb25zb2xlLmxvZygncnVuIHRvOiAnICsgaW5kZXgpO1xyXG5cclxuICAgICAgLy8gZ2V0IHRoZSBzbmFwc2hvdCB0byBydW4gb3BlcmF0aW9ucyBvblxyXG4gICAgICBjb25zdCBzbmFwc2hvdCA9IHRoaXMuZ2V0U25hcHNob3QoKTtcclxuICAgICAgaWYgKCFzbmFwc2hvdC50ZXh0KSB7XHJcbiAgICAgICAgcmV0dXJuIHJlamVjdCgnTm8gc25hcHNob3QgdGV4dCcpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBydW4gb3BlcmF0aW9ucyB1cCB0byB0aGUgc3BlY2lmaWVkIGluZGV4LCBidXQgcmVwbGFjZSB0aGUgbGFzdFxyXG4gICAgICAvLyBvcGVyYXRpb24gd2hlbiB0aGlzIHdhcyByZWNlaXZlZCBhcyBhIHBhcmFtZXRlclxyXG4gICAgICBjb25zdCBvcGVyYXRpb25zID0gWy4uLnRoaXMub3BlcmF0aW9ucy52YWx1ZV07XHJcblxyXG4gICAgICBpZiAobGFzdE9wZXJhdGlvbikge1xyXG4gICAgICAgIG9wZXJhdGlvbnMuc2xpY2UoMCwgaW5kZXgpO1xyXG4gICAgICAgIG9wZXJhdGlvbnMucHVzaChsYXN0T3BlcmF0aW9uKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBvcGVyYXRpb25zLnNsaWNlKDAsIGluZGV4ICsgMSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRoaXMuYnVzeSA9IHRydWU7XHJcbiAgICAgIHRoaXMuaW5pdGlhbFN0ZXBJbmRleCA9IGluZGV4O1xyXG4gICAgICB0aGlzLl9hcGlcclxuICAgICAgICAucnVuT3BlcmF0aW9ucyhzbmFwc2hvdC50ZXh0IGFzIENoYXJOb2RlW10sIG9wZXJhdGlvbnMpXHJcbiAgICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICBuZXh0OiAod3JhcHBlcikgPT4ge1xyXG4gICAgICAgICAgICAvLyBoYW5kbGUgb3BlcmF0aW9uIChub24tZmF0YWwpIGVycm9yIG9yIHJlc3VsdFxyXG4gICAgICAgICAgICBpZiAod3JhcHBlci5lcnJvcikge1xyXG4gICAgICAgICAgICAgIHRoaXMuX3NuYWNrYmFyLm9wZW4od3JhcHBlci5lcnJvciwgJ09LJyk7XHJcbiAgICAgICAgICAgICAgcmVqZWN0KHdyYXBwZXIuZXJyb3IpO1xyXG4gICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gZXh0cmFjdCB0aGUgSURzIGZyb20gdGhlIGxhc3Qgb3BlcmF0aW9uJ3MgZGlwbG9tYXRpY3MgYW5kIGZpbHRlclxyXG4gICAgICAgICAgICAvLyB0aGVtIHNvIHRoYXQgb25seSB0aGUgb25lcyBlbmRpbmcgd2l0aCBfdCBhcmUga2VwdC4gQnkgY29udmVudGlvbixcclxuICAgICAgICAgICAgLy8gYWxsIHRoZSBJRHMgZW5kaW5nIHdpdGggdGhpcyBzdWZmaXggYXJlIHRvIGJlIG1hZGUgaW52aXNpYmxlIGF0XHJcbiAgICAgICAgICAgIC8vIHRoZWlyIGZpcnN0IHJlbmRpdGlvbiAob3BhY2l0eT0wKS4gQW4gYW5pbWF0aW9uIHdpbGwgdGhlbiBtYWtlXHJcbiAgICAgICAgICAgIC8vIHRoZW0gdmlzaWJsZS5cclxuICAgICAgICAgICAgdGhpcy5fdHJhbnNwYXJlbnRJZHMgPSB0aGlzLnBhcnNlU3ZnSWRzKFxyXG4gICAgICAgICAgICAgIG9wZXJhdGlvbnNbaW5kZXhdLmRpcGxvbWF0aWNzPy5nXHJcbiAgICAgICAgICAgICk/LmZpbHRlcigoaWQpID0+IGlkLmVuZHNXaXRoKFNWR19UUkFOU1BfU1VGRklYKSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFZpZXdEYXRhKHNuYXBzaG90LCBzbmFwc2hvdC5vcGVyYXRpb25zW2luZGV4XS5vdXRwdXRUYWcpO1xyXG4gICAgICAgICAgICB0aGlzLnJlc3VsdCA9IHdyYXBwZXIucmVzdWx0ITtcclxuXHJcbiAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xyXG4gICAgICAgICAgICB0aGlzLl90cmFuc3BhcmVudElkcyA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgdGhpcy5fc25hY2tiYXIub3BlbignRXJyb3IgcnVubmluZyBvcGVyYXRpb25zJywgJ09LJyk7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5idXN5ID0gZmFsc2U7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSdW4gdGhlIG9wZXJhdGlvbnMgdXAgdG8gdGhlIGxhc3Qgb3BlcmF0aW9uIGlmIGFueS5cclxuICAgKiBPdGhlcndpc2UsIGp1c3QgdXBkYXRlIHRoZSBzbmFwc2hvdCB2aWV3LlxyXG4gICAqL1xyXG4gIHB1YmxpYyBydW5Ub0xhc3QoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5vcGVyYXRpb25zLnZhbHVlLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnJ1blRvKHRoaXMub3BlcmF0aW9ucy52YWx1ZS5sZW5ndGggLSAxKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2V0Vmlld0RhdGEoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZSB0aGUgc25hcHNob3QgdmlldyBieSBydW5uaW5nIHRoZSBvcGVyYXRpb25zIHVwIHRvIHRoZVxyXG4gICAqIGN1cnJlbnRseSBlZGl0ZWQgb3BlcmF0aW9uIGlmIGFueS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBvcGVyYXRpb24gVGhlIG9wZXJhdGlvbiBiZWluZyBwcmV2aWV3ZWQuXHJcbiAgICovXHJcbiAgcHVibGljIG9uT3BlcmF0aW9uUHJldmlldyhvcGVyYXRpb246IENoYXJDaGFpbk9wZXJhdGlvbik6IHZvaWQge1xyXG4gICAgLy8gbm8gbXVsdGlwbGUgcHJldmlld3Mgb3IgcHJldmlld2luZyBhIG5ldyBvcGVyYXRpb25cclxuICAgIGlmICh0aGlzLl9wcmV2aWV3aW5nIHx8IHRoaXMuZWRpdGVkT3BJbmRleCA8IDApIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fcHJldmlld2luZyA9IHRydWU7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5ydW5Ubyh0aGlzLmVkaXRlZE9wSW5kZXgsIG9wZXJhdGlvbik7XHJcbiAgICAgIHRoaXMuX3ByZXZpZXdpbmcgPSBmYWxzZTtcclxuICAgIH0sIDApO1xyXG4gIH1cclxuICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gIC8qKlxyXG4gICAqIEJ1aWxkIHRoZSBzbmFwc2hvdCBhdCB0aGUgc3BlY2lmaWVkIGV4ZWN1dGlvbiBzdGVwLiBUaGlzIGltcGxpZXMgYWRkaW5nXHJcbiAgICogdGhlIG5vZGVzIGludHJvZHVjZWQgYnkgdGhlIG9wZXJhdGlvbnMgdXAgdG8gdGhlIHNwZWNpZmllZCBzdGVwLCBhbmRcclxuICAgKiB1cGRhdGluZyB0aGUgZmVhdHVyZXMgb2YgdGhlIG5vZGVzIGludHJvZHVjZWQgYnkgdGhlIHNwZWNpZmllZCBzdGVwLlxyXG4gICAqIEFsc28sIHRoZSBvcGVyYXRpb25zIGFmdGVyIHRoZSBzcGVjaWZpZWQgc3RlcCBhcmUgcmVtb3ZlZCBmcm9tIHRoZVxyXG4gICAqIHNuYXBzaG90LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHN0ZXAgVGhlIHN0ZXAgdG8gYnVpbGQgdGhlIHNuYXBzaG90IGF0LlxyXG4gICAqIEByZXR1cm5zIFRoZSBzbmFwc2hvdCBhdCB0aGUgc3BlY2lmaWVkIHN0ZXAuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZFNuYXBzaG90QXRTdGVwKFxyXG4gICAgc3RlcDogQ2hhaW5PcGVyYXRpb25Db250ZXh0U3RlcFxyXG4gICk6IFNuYXBzaG90IHwgbnVsbCB7XHJcbiAgICAvLyBubyByZXN1bHQsIG5vdGhpbmcgdG8gZG9cclxuICAgIGlmICghdGhpcy5yZXN1bHQpIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZ2V0IHRoZSBjdXJyZW50bHkgZWRpdGVkIHNuYXBzaG90XHJcbiAgICBjb25zdCBzbmFwc2hvdCA9IHRoaXMuZ2V0U25hcHNob3QoKTtcclxuICAgIC8vIGZpbmQgdGhlIG1heCBJRCBpbiBzbmFwc2hvdC50ZXh0ICg9b3JpZ2luYWwpIG5vZGVzLFxyXG4gICAgLy8gc28gdGhhdCBhbnkgSUQgZ3JlYXRlciB0aGFuIGl0IGJlbG9uZ3MgdG8gbmV3IG5vZGVzXHJcbiAgICBjb25zdCBtYXhPcmlnaW5hbElkID0gKHNuYXBzaG90LnRleHQgYXMgQ2hhck5vZGVbXSkucmVkdWNlKFxyXG4gICAgICAobWF4LCBuKSA9PiBNYXRoLm1heChtYXgsIG4uaWQpLFxyXG4gICAgICAwXHJcbiAgICApO1xyXG4gICAgLy8gZ2V0IGEgY29weSBvZiB0aGUgbm9kZXMgb2YgdGhlIHNuYXBzaG90IGJhc2UgdGV4dFxyXG4gICAgY29uc3Qgc25hcE5vZGVzOiBDaGFyTm9kZVtdID0gZGVlcENvcHkoc25hcHNob3QudGV4dCBhcyBDaGFyTm9kZVtdKTtcclxuXHJcbiAgICAvLyBnZXQgdGhlIG5vZGVzIG9mIHRoZSBwaWNrZWQgc3RlcFxyXG4gICAgY29uc3Qgc3RlcE5vZGVzID0gdGhpcy5yZXN1bHQudGFnZ2VkTm9kZXNbc3RlcC5vdXRwdXRUYWddO1xyXG5cclxuICAgIC8vIHVwZGF0ZSB0aGUgc25hcHNob3QgdGV4dCBub2RlcyBjb3BpZXMgd2l0aCB0aGUgcGlja2VkIHN0ZXAgbm9kZXMsXHJcbiAgICAvLyBieSB1cGRhdGluZyB0aGVpciBmZWF0dXJlcyBpZiBleGlzdGluZywgb3IgYWRkaW5nIG5ldyBub2RlcyBpZiBub3QuXHJcbiAgICBmb3IgKGNvbnN0IHNuIG9mIHN0ZXBOb2Rlcykge1xyXG4gICAgICAvLyBmaW5kIHRoZSBub2RlIGluIHRoZSBvcmlnaW5hbCBzbmFwc2hvdCB0ZXh0XHJcbiAgICAgIGNvbnN0IGkgPSBzbmFwTm9kZXMuZmluZEluZGV4KChuKSA9PiBuLmlkID09PSBzbi5pZCk7XHJcbiAgICAgIC8vIGlmIGZvdW5kLCB1cGRhdGUgaXRzIGZlYXR1cmVzLCBlbHNlIGFkZCBpdFxyXG4gICAgICBpZiAoaSA+IC0xKSB7XHJcbiAgICAgICAgc25hcE5vZGVzW2ldLmZlYXR1cmVzID0gc24uZmVhdHVyZXM7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gbmV3IG5vZGU6IHdlIGFzc3VtZSB0aGF0IGl0IGhhcyBhIG1hbnVhbGx5IHNldCBwb3NpdGlvbiAoeCx5IGZlYXR1cmVzKVxyXG4gICAgICAgIHNuYXBOb2Rlcy5wdXNoKHNuKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIGFwcGVuZCBub2RlcyBpbnRyb2R1Y2VkICpiZWZvcmUqIHRoZSBwaWNrZWQgc3RlcCwgaWYgYW55XHJcbiAgICAvLyAodGhvc2UgaW50cm9kdWNlZCBieSB0aGUgcGlja2VkIHN0ZXAgaGF2ZSBhbHJlYWR5IGJlZW4gYWRkZWQpXHJcbiAgICBjb25zdCBzdGVwSW5kZXggPSB0aGlzLnJlc3VsdC5zdGVwcy5pbmRleE9mKHN0ZXApO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RlcEluZGV4OyBpKyspIHtcclxuICAgICAgY29uc3Qgc3RlcE5vZGVzID0gdGhpcy5yZXN1bHQudGFnZ2VkTm9kZXNbdGhpcy5yZXN1bHQuc3RlcHNbaV0ub3V0cHV0VGFnXTtcclxuXHJcbiAgICAgIGZvciAoY29uc3QgbiBvZiBzdGVwTm9kZXMpIHtcclxuICAgICAgICBpZiAobi5pZCA+IG1heE9yaWdpbmFsSWQgJiYgIXNuYXBOb2Rlcy5maW5kKCh4KSA9PiB4LmlkID09PSBuLmlkKSkge1xyXG4gICAgICAgICAgc25hcE5vZGVzLnB1c2gobik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdXBkYXRlIHRoZSBzbmFwc2hvdCB0ZXh0IG5vZGVzXHJcbiAgICBzbmFwc2hvdC50ZXh0ID0gc25hcE5vZGVzO1xyXG5cclxuICAgIC8vIHJlbW92ZSBmcm9tIHRoZSBzbmFwc2hvdCB0aGUgb3BlcmF0aW9ucyBhZnRlciB0aGUgcGlja2VkIHN0ZXBcclxuICAgIGNvbnN0IGkgPSBzbmFwc2hvdC5vcGVyYXRpb25zLmZpbmRJbmRleCgobykgPT4gby5pZCA9PT0gc3RlcC5vcGVyYXRpb24uaWQpO1xyXG4gICAgaWYgKGkgPiAtMSkge1xyXG4gICAgICBzbmFwc2hvdC5vcGVyYXRpb25zID0gc25hcHNob3Qub3BlcmF0aW9ucy5zbGljZSgwLCBpICsgMSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHNuYXBzaG90O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwbGF5VGltZWxpbmUodGw6IEd2ZUFuaW1hdGlvblRpbWVsaW5lKTogdm9pZCB7XHJcbiAgICBjb25zdCBzaGFkb3dSb290ID0gdGhpcy5zbmFwc2hvdFZpZXc/Lm5hdGl2ZUVsZW1lbnQ/LnNoYWRvd1Jvb3Q7XHJcbiAgICBpZiAodGwgJiYgc2hhZG93Um9vdCkge1xyXG4gICAgICBjb25zb2xlLmxvZygncGxheSB0aW1lbGluZScsIHRsKTtcclxuICAgICAgdGhpcy5fcmVuZGVyZXI/LnBsYXlUaW1lbGluZSh0bCwgdW5kZWZpbmVkLCBzaGFkb3dSb290KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICghdGhpcy5zbmFwc2hvdFZpZXcpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oJ25vIHNuYXBzaG90VmlldyBmb3IgdGltZWxpbmUnKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oJ25vIHNoYWRvd1Jvb3QgZm9yIHRpbWVsaW5lJyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZSB0aGUgZXZlbnQgZmlyZWQgYnkgdGhlIGNoYWluIHJlc3VsdCB2aWV3IHRvIHBpY2sgYSBzdGVwLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHN0ZXAgVGhlIHN0ZXAgdG8gcGljay5cclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgb25TdGVwUGljayhzdGVwOiBDaGFpbk9wZXJhdGlvbkNvbnRleHRTdGVwKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXRoaXMucmVzdWx0IHx8IHRoaXMuX3N0ZXBQaWNrRnJvemVuKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBnZXQgdGhlIGN1cnJlbnRseSBlZGl0ZWQgc25hcHNob3RcclxuICAgIGNvbnN0IHNuYXBzaG90ID0gdGhpcy5idWlsZFNuYXBzaG90QXRTdGVwKHN0ZXApITtcclxuICAgIC8vIHVwZGF0ZSByZXN1bHQgb3BlcmF0aW9uIElEXHJcbiAgICB0aGlzLnJlc3VsdE9wZXJhdGlvbklkID0gc3RlcC5vcGVyYXRpb24uaWQ7XHJcbiAgICAvLyB1cGRhdGUgdmlldyBkYXRhXHJcbiAgICB0aGlzLnNldFZpZXdEYXRhKHNuYXBzaG90LCBzdGVwLm91dHB1dFRhZyk7XHJcblxyXG4gICAgLy8gcGxheSBhbmltYXRpb24gaWYgYW55XHJcbiAgICBjb25zdCB0bCA9IHRoaXMudGltZWxpbmVzLnZhbHVlLmZpbmQoKHQpID0+IHQudGFnID09PSBzdGVwLm91dHB1dFRhZyk7XHJcbiAgICBpZiAodGwpIHtcclxuICAgICAgdGhpcy5fc3RlcFBpY2tGcm96ZW4gPSB0cnVlO1xyXG5cclxuICAgICAgLy8gZmluZCB0aGUgaW5kZXggb2YgdGhlIHBpY2tlZCBzdGVwIGluIHRoZSBzbmFwc2hvdCBvcGVyYXRpb25zXHJcbiAgICAgIGNvbnN0IGkgPSBzbmFwc2hvdC5vcGVyYXRpb25zLmZpbmRJbmRleChcclxuICAgICAgICAobykgPT4gby5pZCA9PT0gc3RlcC5vcGVyYXRpb24uaWRcclxuICAgICAgKTtcclxuICAgICAgLy8gcnVuIHRoZSBvcGVyYXRpb25zIHVwIHRvIHRoZSBwaWNrZWQgc3RlcCBhcyB3ZSBuZWVkIHRvIGhpZGVcclxuICAgICAgLy8gdGhvc2UgdmlzdWFscyB0byBiZSByZXZlYWxlZCBieSB0aGUgYW5pbWF0aW9uXHJcbiAgICAgIGF3YWl0IHRoaXMucnVuVG8oaSk7XHJcbiAgICAgIHRoaXMuX3N0ZXBQaWNrRnJvemVuID0gZmFsc2U7XHJcblxyXG4gICAgICAvLyBwbGF5IHRoZSB0aW1lbGluZVxyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICB0aGlzLnBsYXlUaW1lbGluZSh0bCk7XHJcbiAgICAgIH0sIDApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlIHRoZSBldmVudCBmaXJlZCBieSBhIHZpc3VhbCBpbiB0aGUgc25hcHNob3Qgdmlldy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBldmVudCBUaGUgZXZlbnQuXHJcbiAgICovXHJcbiAgcHVibGljIG9uVmlzdWFsRXZlbnQoZXZlbnQ6IEN1c3RvbUV2ZW50PEd2ZVZpc3VhbEV2ZW50Pik6IHZvaWQge1xyXG4gICAgY29uc3QgZCA9IGV2ZW50LmRldGFpbDtcclxuXHJcbiAgICBpZiAoZC5ldmVudC50eXBlID09PSAnbW91c2VvdmVyJykge1xyXG4gICAgICBjb25zdCB2aXN1YWwgPSBkLnNvdXJjZTtcclxuICAgICAgY29uc3Qgc2I6IHN0cmluZ1tdID0gW107XHJcbiAgICAgIHNiLnB1c2goJyMnICsgdmlzdWFsLmlkKTtcclxuICAgICAgc2IucHVzaChgICgke3Zpc3VhbC50eXBlfSlgKTtcclxuICAgICAgaWYgKHZpc3VhbC5kYXRhPy5sYWJlbCkge1xyXG4gICAgICAgIHNiLnB1c2goJzogJyk7XHJcbiAgICAgICAgc2IucHVzaCh2aXN1YWwuZGF0YS5sYWJlbCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHZpc3VhbC5kYXRhPy5mZWF0dXJlcz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgc2IucHVzaCgnICcpO1xyXG4gICAgICAgIHNiLnB1c2goXHJcbiAgICAgICAgICB2aXN1YWwuZGF0YS5mZWF0dXJlc1xyXG4gICAgICAgICAgICAubWFwKChmOiBGZWF0dXJlKSA9PiBgJHtmLm5hbWV9PSR7Zi52YWx1ZX1gKVxyXG4gICAgICAgICAgICAuam9pbignXFxuJylcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudmlzdWFsSW5mbyA9IHNiLmpvaW4oJycpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlIHRoZSBjaGFuZ2Ugb2YgbGluZSBoZWlnaHRzIGJ5IHVwZGF0aW5nIHRoZSBmb3JtIGNvbnRyb2wuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gaGVpZ2h0cyBUaGUgbGluZSBoZWlnaHRzLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBvbkhlaWdodHNDaGFuZ2UoaGVpZ2h0czogUmVjb3JkPG51bWJlciwgbnVtYmVyPiB8IHVuZGVmaW5lZCk6IHZvaWQge1xyXG4gICAgdGhpcy5sbkhlaWdodHMuc2V0VmFsdWUoaGVpZ2h0cyB8fCBudWxsKTtcclxuICAgIHRoaXMubG5IZWlnaHRzLm1hcmtBc0RpcnR5KCk7XHJcbiAgICB0aGlzLmxuSGVpZ2h0cy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBIYW5kbGUgdGhlIGNoYW5nZSBvZiB0aW1lbGluZXMgYnkgdXBkYXRpbmcgdGhlIGZvcm0gY29udHJvbC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB0aW1lbGluZXMgVGhlIHRpbWVsaW5lcy5cclxuICAgKi9cclxuICBwdWJsaWMgb25UaW1lbGluZXNDaGFuZ2UodGltZWxpbmVzOiBHdmVBbmltYXRpb25UaW1lbGluZVtdKTogdm9pZCB7XHJcbiAgICB0aGlzLnRpbWVsaW5lcy5zZXRWYWx1ZSh0aW1lbGluZXMpO1xyXG4gICAgdGhpcy50aW1lbGluZXMubWFya0FzRGlydHkoKTtcclxuICAgIHRoaXMudGltZWxpbmVzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEVtaXQgdGhlIGNhbmNlbCBldmVudCBmb3IgdGhpcyBzbmFwc2hvdCBlZGl0LlxyXG4gICAqL1xyXG4gIHB1YmxpYyBjbG9zZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuc25hcHNob3RDYW5jZWwuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlIHRoZSByZW5kZXIgZXZlbnQgZnJvbSB0aGUgc25hcHNob3QgdmlldyB0byBnZXQgYSByZWZlcmVuY2VcclxuICAgKiB0byB0aGUgcmVuZGVyZXIuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIHJlbmRpdGlvbiBldmVudC5cclxuICAgKi9cclxuICBwdWJsaWMgb25TbmFwc2hvdFJlbmRlcihldmVudDogQ3VzdG9tRXZlbnQ8U25hcHNob3RWaWV3UmVuZGVyRXZlbnQ+KTogdm9pZCB7XHJcbiAgICB0aGlzLl9yZW5kZXJlciA9IChldmVudC5kZXRhaWwgYXMgU25hcHNob3RWaWV3UmVuZGVyRXZlbnQpLnJlbmRlcmVyO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVG9nZ2xlIHJ1bGVycyBpbiB0aGUgc25hcHNob3Qgdmlldy5cclxuICAgKi9cclxuICBwdWJsaWMgdG9nZ2xlUnVsZXJzKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLl9yZW5kZXJlcikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnJ1bGVycyA9IHRoaXMuX3JlbmRlcmVyLnRvZ2dsZVJ1bGVycygpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0IGEgc25hcHNob3QgZnJvbSB0aGUgZm9ybSBkYXRhLlxyXG4gICAqXHJcbiAgICogQHJldHVybnMgTmV3IHNuYXBzaG90IG9iamVjdC5cclxuICAgKi9cclxuICBwcml2YXRlIGdldFNuYXBzaG90KCk6IFNuYXBzaG90IHtcclxuICAgIGNvbnN0IHNuYXBzaG90OiBTbmFwc2hvdCA9IHtcclxuICAgICAgc2l6ZToge1xyXG4gICAgICAgIHdpZHRoOiB0aGlzLndpZHRoLnZhbHVlLFxyXG4gICAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQudmFsdWUsXHJcbiAgICAgIH0sXHJcbiAgICAgIHN0eWxlOiB0aGlzLnN0eWxlLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgZGVmczogdGhpcy5kZWZzLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgdGV4dDogdGhpcy5iYXNlVGV4dC52YWx1ZSEsXHJcbiAgICAgIHRleHRTdHlsZTogdGhpcy50ZXh0U3R5bGUudmFsdWUgfHwgdW5kZWZpbmVkLFxyXG4gICAgICB0ZXh0T3B0aW9uczoge1xyXG4gICAgICAgIGxpbmVIZWlnaHRPZmZzZXQ6IHRoaXMubGluZUhlaWdodE9mZnNldC52YWx1ZSxcclxuICAgICAgICBtaW5MaW5lSGVpZ2h0czogdGhpcy5sbkhlaWdodHMudmFsdWUgfHwgdW5kZWZpbmVkLFxyXG4gICAgICAgIGNoYXJTcGFjaW5nT2Zmc2V0OiB0aGlzLmNoYXJTcGFjaW5nT2Zmc2V0LnZhbHVlLFxyXG4gICAgICAgIHNwY1dpZHRoT2Zmc2V0OiB0aGlzLnNwY1dpZHRoT2Zmc2V0LnZhbHVlLFxyXG4gICAgICAgIG9mZnNldDoge1xyXG4gICAgICAgICAgeDogdGhpcy5vZmZzZXRYLnZhbHVlLFxyXG4gICAgICAgICAgeTogdGhpcy5vZmZzZXRZLnZhbHVlLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0sXHJcbiAgICAgIG9wZXJhdGlvbnM6IFsuLi50aGlzLm9wZXJhdGlvbnMudmFsdWVdLFxyXG4gICAgICBvcFN0eWxlOiB0aGlzLm9wU3R5bGUudmFsdWUgfHwgdW5kZWZpbmVkLFxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBpbWFnZVxyXG4gICAgaWYgKHRoaXMuaW1hZ2VVcmwudmFsdWUpIHtcclxuICAgICAgc25hcHNob3QuaW1hZ2UgPSB7XHJcbiAgICAgICAgdXJsOiB0aGlzLmltYWdlVXJsLnZhbHVlLFxyXG4gICAgICAgIG9wYWNpdHk6IHRoaXMuaW1hZ2VPcGFjaXR5LnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgfTtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHRoaXMuaW1hZ2VYLnZhbHVlIHx8XHJcbiAgICAgICAgdGhpcy5pbWFnZVkudmFsdWUgfHxcclxuICAgICAgICB0aGlzLmltYWdlV2lkdGgudmFsdWUgfHxcclxuICAgICAgICB0aGlzLmltYWdlSGVpZ2h0LnZhbHVlXHJcbiAgICAgICkge1xyXG4gICAgICAgIHNuYXBzaG90LmltYWdlLmNhbnZhcyA9IHtcclxuICAgICAgICAgIHg6IHRoaXMuaW1hZ2VYLnZhbHVlLFxyXG4gICAgICAgICAgeTogdGhpcy5pbWFnZVkudmFsdWUsXHJcbiAgICAgICAgICB3aWR0aDogdGhpcy5pbWFnZVdpZHRoLnZhbHVlLFxyXG4gICAgICAgICAgaGVpZ2h0OiB0aGlzLmltYWdlSGVpZ2h0LnZhbHVlLFxyXG4gICAgICAgIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyB0aW1lbGluZXNcclxuICAgIGlmICh0aGlzLnRpbWVsaW5lcy52YWx1ZS5sZW5ndGgpIHtcclxuICAgICAgc25hcHNob3QudGltZWxpbmVzID0ge307XHJcbiAgICAgIHRoaXMudGltZWxpbmVzLnZhbHVlLmZvckVhY2goKHQpID0+IHtcclxuICAgICAgICBzbmFwc2hvdC50aW1lbGluZXMhW3QudGFnXSA9IHQ7XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgc25hcHNob3QudGltZWxpbmVzID0gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBzbmFwc2hvdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBhIHNuYXBzaG90IGZyb20gdGhlIGZvcm0gZGF0YSBhbmQgZW1pdCBpdFxyXG4gICAqIGluIHRoZSBzbmFwc2hvdCBjaGFuZ2UgZXZlbnQuXHJcbiAgICovXHJcbiAgcHVibGljIHNhdmUoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5mb3JtLmludmFsaWQgfHwgdGhpcy5ub1NhdmUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fc25hcHNob3QgPSB0aGlzLmdldFNuYXBzaG90KCk7XHJcbiAgICB0aGlzLnNuYXBzaG90Q2hhbmdlLmVtaXQodGhpcy5fc25hcHNob3QpO1xyXG4gIH1cclxufVxyXG4iLCI8Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1cIiAoc3VibWl0KT1cInNhdmUoKVwiPlxyXG4gIDxtYXQtdGFiLWdyb3VwPlxyXG4gICAgPCEtLSB0ZXh0IC0tPlxyXG4gICAgPG1hdC10YWI+XHJcbiAgICAgIDxuZy10ZW1wbGF0ZSBtYXQtdGFiLWxhYmVsPlxyXG4gICAgICAgIDxtYXQtaWNvbj5hcnRpY2xlPC9tYXQtaWNvbj4gPHNwYW4gY2xhc3M9XCJsYWJlbFwiPnRleHQ8L3NwYW4+XHJcbiAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsIFtleHBhbmRlZF09XCIhYmFzZVRleHQudmFsdWVcIj5cclxuICAgICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgICAgICA8bWF0LXBhbmVsLXRpdGxlPiBiYXNlIHRleHQgPC9tYXQtcGFuZWwtdGl0bGU+XHJcbiAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICA8Z3ZlLWJhc2UtdGV4dC1lZGl0b3JcclxuICAgICAgICAgIFt0ZXh0XT1cImJhc2VUZXh0LnZhbHVlXCJcclxuICAgICAgICAgICh0ZXh0Q2hhbmdlKT1cIm9uVGV4dENoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICAvPlxyXG4gICAgICAgIDxmaWVsZHNldD5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gICAgICAgICAgICA8IS0tIG9mZnNldFggLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5YIG9mZnNldDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIm9mZnNldFhcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJYIG9mZnNldFwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gb2Zmc2V0WSAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPlkgb2Zmc2V0PC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwib2Zmc2V0WVwiXHJcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlkgb2Zmc2V0XCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICAgICAgPCEtLSBsaW5lSGVpZ2h0T2Zmc2V0IC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+bG4gaC1vZmZzZXQ8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJsaW5lSGVpZ2h0T2Zmc2V0XCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwibG4gaC1vZmZzZXRcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgICAgICA8IS0tIGNoYXJTcGFjaW5nT2Zmc2V0IC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+Y2hhciBzcGFjaW5nPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiY2hhclNwYWNpbmdPZmZzZXRcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJjaGFyIHNwYWNpbmdcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgICAgICA8IS0tIHNwY1dpZHRoT2Zmc2V0IC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+c3BjIHctb2Zmc2V0PC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwic3BjV2lkdGhPZmZzZXRcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJzcGMgdy1vZmZzZXRcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgIDwhLS0gbWluTGluZUhlaWdodHMgLS0+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJib3hlZFwiPlxyXG4gICAgICAgICAgICAgIDxndmUtbG4taGVpZ2h0cy1lZGl0b3JcclxuICAgICAgICAgICAgICAgIFtsaW5lQ291bnRdPVwibGluZUNvdW50XCJcclxuICAgICAgICAgICAgICAgIFtoZWlnaHRzXT1cImxuSGVpZ2h0cy52YWx1ZVwiXHJcbiAgICAgICAgICAgICAgICAoaGVpZ2h0c0NoYW5nZSk9XCJvbkhlaWdodHNDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDwhLS0gdGV4dFN0eWxlIC0tPlxyXG4gICAgICAgICAgPGRpdj5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwibG9uZy10ZXh0XCIgYXBwZWFyYW5jZT1cIm91dGxpbmVcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPnRleHQgc3R5bGU8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8dGV4dGFyZWFcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwidGV4dFN0eWxlXCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwidGV4dCBzdHlsZVwiXHJcbiAgICAgICAgICAgICAgPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2ZpZWxkc2V0PlxyXG4gICAgICA8L21hdC1leHBhbnNpb24tcGFuZWw+XHJcbiAgICA8L21hdC10YWI+XHJcblxyXG4gICAgPCEtLSBvcGVyYXRpb25zIC0tPlxyXG4gICAgPG1hdC10YWI+XHJcbiAgICAgIDxuZy10ZW1wbGF0ZSBtYXQtdGFiLWxhYmVsPlxyXG4gICAgICAgIDxtYXQtaWNvbj5lZGl0PC9tYXQtaWNvbj4gPHNwYW4gY2xhc3M9XCJsYWJlbFwiPm9wZXJhdGlvbnM8L3NwYW4+XHJcbiAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICA8ZGl2IGlkPVwic25hcHNob3QtY29udGFpbmVyXCI+XHJcbiAgICAgICAgPGRpdiBpZD1cImdlbmVyYWxcIj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gICAgICAgICAgICA8IS0tIHdpZHRoIC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJpbnB1dC1uclwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+d2lkdGg8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxyXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIndpZHRoXCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwid2lkdGhcIlxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgICAgICA8IS0tIGhlaWdodCAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPmhlaWdodDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgICAgbWluPVwiMFwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiaGVpZ2h0XCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiaGVpZ2h0XCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICAgICAgPCEtLSBhZGQgb3AgLS0+XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICBtYXQtZmxhdC1idXR0b25cclxuICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwibWF0LXByaW1hcnkgcmlnaHRcIlxyXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhYmFzZVRleHQudmFsdWVcIlxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJlZGl0TmV3T3BlcmF0aW9uKClcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPG1hdC1pY29uPmFkZF9jaXJjbGU8L21hdC1pY29uPiBvcGVyYXRpb25cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPCEtLSBvcHMgLS0+XHJcbiAgICAgICAgPGRpdiBpZD1cIm9wc1wiPlxyXG4gICAgICAgICAgPCEtLSBvcGVyYXRpb25zIGxpc3QgLS0+XHJcbiAgICAgICAgICBAaWYgKG9wZXJhdGlvbnMudmFsdWUubGVuZ3RoKSB7XHJcbiAgICAgICAgICA8dGFibGUgaWQ9XCJsaXN0XCI+XHJcbiAgICAgICAgICAgIDx0aGVhZD5cclxuICAgICAgICAgICAgICA8dHI+XHJcbiAgICAgICAgICAgICAgICA8dGg+PC90aD5cclxuICAgICAgICAgICAgICAgIDx0aD5JRDwvdGg+XHJcbiAgICAgICAgICAgICAgICA8dGg+dHlwZTwvdGg+XHJcbiAgICAgICAgICAgICAgICA8dGg+YXQ8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPnJ1bjwvdGg+XHJcbiAgICAgICAgICAgICAgICA8dGg+dmFsdWU8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPml0YWc8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPm90YWc8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRoPmdpZDwvdGg+XHJcbiAgICAgICAgICAgICAgICA8dGg+ZmVhdHM8L3RoPlxyXG4gICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDwvdGhlYWQ+XHJcbiAgICAgICAgICAgIDx0Ym9keT5cclxuICAgICAgICAgICAgICBAZm9yIChvcGVyYXRpb24gb2Ygb3BlcmF0aW9ucy52YWx1ZTsgdHJhY2sgb3BlcmF0aW9uLmlkOyBsZXRcclxuICAgICAgICAgICAgICBpbmRleD0kaW5kZXgpIHtcclxuICAgICAgICAgICAgICA8dHJcclxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgc2VsZWN0ZWQ6IG9wZXJhdGlvbi5pZCA9PT0gcmVzdWx0T3BlcmF0aW9uSWQgfVwiXHJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7IGVkaXRlZDogb3BlcmF0aW9uLmlkID09PSBlZGl0ZWRPcD8uaWQgfVwiXHJcbiAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwiZml0LXdpZHRoXCI+XHJcbiAgICAgICAgICAgICAgICAgIDwhLS0gZWRpdCAtLT5cclxuICAgICAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWF0LXByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJlZGl0T3BlcmF0aW9uKGluZGV4KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkVkaXQgb3BlcmF0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5lZGl0PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgIDwhLS0gZGVsZXRlIC0tPlxyXG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtYXQtd2FyblwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImRlbGV0ZU9wZXJhdGlvbihpbmRleClcIlxyXG4gICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJEZWxldGUgb3BlcmF0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdC13YXJuXCI+ZGVsZXRlPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgIDwhLS0gcnVuIHRvIC0tPlxyXG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtYXQtYWNjZW50XCJcclxuICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwicnVuVG8oaW5kZXgpXCJcclxuICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiUnVuIHRvIHRoaXMgb3BlcmF0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdC1hY2NlbnRcIj5zdWJzY3JpcHRpb25zPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPnt7IG9wZXJhdGlvbi5pZCB9fTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e3sgb3BlcmF0aW9uLnR5cGUgfCBmbGF0TG9va3VwIDogb3BUeXBlTWFwIH19PC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZD57eyBvcGVyYXRpb24uYXQgfX08L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPnt7IG9wZXJhdGlvbi5ydW4gfX08L3RkPlxyXG4gICAgICAgICAgICAgICAgPHRkPnt7IG9wZXJhdGlvbi52YWx1ZSB9fTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e3sgb3BlcmF0aW9uLmlucHV0VGFnIH19PC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZD57eyBvcGVyYXRpb24ub3V0cHV0VGFnIH19PC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZD57eyBvcGVyYXRpb24uZ3JvdXBJZCB9fTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e3sgb3BlcmF0aW9uLmZlYXR1cmVzPy5sZW5ndGggfX08L3RkPlxyXG4gICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICA8L3Rib2R5PlxyXG4gICAgICAgICAgPC90YWJsZT5cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICA8IS0tIG9wZXJhdGlvbiBlZGl0b3IgLS0+XHJcbiAgICAgICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbCBbZXhwYW5kZWRdPVwiZWRpdGVkT3BcIiBbZGlzYWJsZWRdPVwiIWVkaXRlZE9wXCI+XHJcbiAgICAgICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICAgICAgICA8bWF0LXBhbmVsLXRpdGxlPm9wZXJhdGlvbiB7eyBlZGl0ZWRPcD8uaWQgfX08L21hdC1wYW5lbC10aXRsZT5cclxuICAgICAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICAgICAgPGZpZWxkc2V0PlxyXG4gICAgICAgICAgICAgIDxndmUtY2hhaW4tb3BlcmF0aW9uLWVkaXRvclxyXG4gICAgICAgICAgICAgICAgW2hpZGVQcmV2aWV3XT1cImVkaXRlZE9wSW5kZXggPT09IC0xXCJcclxuICAgICAgICAgICAgICAgIFtvcGVyYXRpb25dPVwiZWRpdGVkT3BcIlxyXG4gICAgICAgICAgICAgICAgKG9wZXJhdGlvbkNhbmNlbCk9XCJvbk9wZXJhdGlvbkNhbmNlbCgpXCJcclxuICAgICAgICAgICAgICAgIChvcGVyYXRpb25DaGFuZ2UpPVwib25PcGVyYXRpb25DaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAob3BlcmF0aW9uUHJldmlldyk9XCJvbk9wZXJhdGlvblByZXZpZXcoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9maWVsZHNldD5cclxuICAgICAgICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cclxuXHJcbiAgICAgICAgICA8IS0tIG9wU3R5bGUgLS0+XHJcbiAgICAgICAgICA8ZGl2IGlkPVwib3BTdHlsZVwiPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+b3BlcmF0aW9ucyBzdHlsZTwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDx0ZXh0YXJlYVxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJvcFN0eWxlXCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwib3BlcmF0aW9ucyBzdHlsZVwiXHJcbiAgICAgICAgICAgICAgPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIGJhdGNoIG9wcyAtLT5cclxuICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsPlxyXG4gICAgICAgICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICAgICAgICAgIDxtYXQtcGFuZWwtdGl0bGU+YmF0Y2ggb3BlcmF0aW9uczwvbWF0LXBhbmVsLXRpdGxlPlxyXG4gICAgICAgICAgICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgICAgICAgICAgPGZpZWxkc2V0PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBpZD1cImJhdGNoLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgICA8ZGl2IGlkPVwiYmF0Y2gtaW5wdXRcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPm9wZXJhdGlvbnM8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRleHRhcmVhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjb2RlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJpbnB1dE9wc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJvcGVyYXRpb25zXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICByb3dzPVwiOFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlbGxjaGVjaz1cImZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9XCJ3YXJuXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtYXQtd2FyblwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdC1mbGF0LWJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiUmVtb3ZlIGFsbCB0aGUgb3BlcmF0aW9uc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhb3BlcmF0aW9ucy52YWx1ZS5sZW5ndGggfHwgYnVzeVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhck9wZXJhdGlvbnMoKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyXHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWF0LXByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXQtZmxhdC1idXR0b25cclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlBhcnNlIHRleHQgYW5kIGFkZCByZXN1bHRzIHRvIHRoZSBvcGVyYXRpb25zXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFpbnB1dE9wcy52YWx1ZSB8fCBidXN5XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInBhcnNlT3BlcmF0aW9ucygpXCJcclxuICAgICAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2ggYWRkXHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgIEBpZiAocGFyc2VFcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJlcnJvclwiPnt7IHBhcnNlRXJyb3IgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICA8ZGl2IGlkPVwiYmF0Y2gtaGVscFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx1bD5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5yZXBsYWNlPC9zdHJvbmc+OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5BVHhSVU48c3Ryb25nPj08L3N0cm9uZz5cIlZBTFVFXCI8L2NvZGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPmRlbGV0ZTwvc3Ryb25nPjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+QVR4UlVOPHN0cm9uZz4tPC9zdHJvbmc+PC9jb2RlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5hZGQtYmVmb3JlPC9zdHJvbmc+OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5BVHhSVU48c3Ryb25nPitbPC9zdHJvbmc+XCJWQUxVRVwiPC9jb2RlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5hZGQtYWZ0ZXI8L3N0cm9uZz46XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPkFUeFJVTjxzdHJvbmc+K108L3N0cm9uZz5cIlZBTFVFXCI8L2NvZGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPm1vdmUtYmVmb3JlPC9zdHJvbmc+OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT5BVHhSVU48c3Ryb25nPiZndDtbPC9zdHJvbmc+VE88L2NvZGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPm1vdmUtYWZ0ZXI8L3N0cm9uZz46XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPkFUeFJVTjxzdHJvbmc+Jmd0O108L3N0cm9uZz5UTzwvY29kZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzdHJvbmc+c3dhcDwvc3Ryb25nPjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+QVR4UlVOPHN0cm9uZz4mbHQ7Jmd0Ozwvc3Ryb25nPlRPeFJVTjwvY29kZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzdHJvbmc+YW5ub3RhdGU8L3N0cm9uZz46XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPkFUeFJVTjxzdHJvbmc+Ojwvc3Ryb25nPjwvY29kZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgPC91bD5cclxuICAgICAgICAgICAgICAgICAgICA8cD5Gb3IgYWxsIHRoZSBvcGVyYXRpb25zOjwvcD5cclxuICAgICAgICAgICAgICAgICAgICA8dWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCA8Y29kZT4oSVRBRzpPVEFHKTwvY29kZT4gdG8gZGVmaW5lIGlucHV0IGFuZC9vclxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgdGFncywgc2VwYXJhdGVkIGJ5IGNvbG9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlcGVuZCA8Y29kZT4mI3g0MDs8L2NvZGU+IHRvIEFUIHRvIHVzZSBjaGFyYWN0ZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhlcyAoMC1OKSByYXRoZXIgdGhhbiBJRHMuXHJcbiAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlJVTiAod2hlcmUgYXBwbGljYWJsZSkgZGVmYXVsdHMgdG8gMS48L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBlbmQgZmVhdHVyZXMgbGlrZSA8Y29kZT5bTkFNRSBPUEVSQVRPUiBWQUxVRV08L2NvZGU+LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0ZWQgYnkgc3BhY2UsIHdoZXJlOlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxvbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIE5BTUUgaXMgYW4gYXJiaXRyYXJ5IHN0cmluZy4gUHJlZml4ZXM6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+KjwvY29kZT49Z2xvYmFsIGZlYXR1cmVzLCA8Y29kZT4hPC9jb2RlPj1yZW1vdmVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0dXJlIChubyB2YWx1ZSkuIFN1ZmZpeGVzOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPl48L2NvZGU+PXNob3J0LWxpdmVkIChsaWtlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+KnZlcnNpb25ePWFscGhhPC9jb2RlPikuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICBPUEVSQVRPUiBpcyA8Y29kZT49PC9jb2RlPiAobXVsdGlwbGUpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxjb2RlPjo9PC9jb2RlPiAoc2luZ2xlKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8Y29kZT49PTwvY29kZT4gKGZpcnN0LXNpbmdsZSkuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICBWQUxVRSBpcyBhIHN0cmluZy4gSWYgaXQgaW5jbHVkZXMgc3BhY2VzLCB3cmFwIGl0IGluXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGNvZGU+XCJcIjwvY29kZT4uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8L29sPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvdWw+XHJcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgPC9maWVsZHNldD5cclxuICAgICAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9tYXQtdGFiPlxyXG5cclxuICAgIDwhLS0gaW1hZ2UgLS0+XHJcbiAgICA8bWF0LXRhYj5cclxuICAgICAgPG5nLXRlbXBsYXRlIG1hdC10YWItbGFiZWw+XHJcbiAgICAgICAgPG1hdC1pY29uPmltYWdlPC9tYXQtaWNvbj4gPHNwYW4gY2xhc3M9XCJsYWJlbFwiPmltYWdlPC9zcGFuPlxyXG4gICAgICA8L25nLXRlbXBsYXRlPlxyXG5cclxuICAgICAgPGRpdiBpZD1cImltYWdlXCI+XHJcbiAgICAgICAgPGRpdiBpZD1cImltYWdlLWN0bFwiPlxyXG4gICAgICAgICAgPCEtLSB1cmwgLS0+XHJcbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIj5cclxuICAgICAgICAgICAgPG1hdC1sYWJlbD5VUkw8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IFtmb3JtQ29udHJvbF09XCJpbWFnZVVybFwiIC8+XHJcbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgICAgICAgIDwhLS0geCAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiaW5wdXQtbnJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPlg8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJpbWFnZVhcIlxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJYXCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICA8IS0tIHkgLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5ZPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiaW1hZ2VZXCJcclxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiWVwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgICAgICAgIDwhLS0gd2lkdGggLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD53aWR0aDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgICAgbWluPVwiMFwiXHJcbiAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiaW1hZ2VXaWR0aFwiXHJcbiAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgPCEtLSBoZWlnaHQgLS0+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImlucHV0LW5yXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5oZWlnaHQ8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICAgIG1pbj1cIjBcIlxyXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cImltYWdlSGVpZ2h0XCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8IS0tIGRlZnMgLS0+XHJcbiAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJsb25nLXRleHRcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPmRlZnM8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8dGV4dGFyZWEgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cImRlZnNcIiByb3dzPVwiM1wiPjwvdGV4dGFyZWE+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8ZGl2IGlkPVwiaW1hZ2Utdmlld1wiPlxyXG4gICAgICAgICAgQGlmIChpbWFnZVVybC52YWx1ZSkge1xyXG4gICAgICAgICAgPGltZyBhbHQ9XCJiYWNrZ3JvdW5kXCIgW3NyY109XCJpbWFnZVVybC52YWx1ZVwiIHdpZHRoPVwiNjAwXCIgLz5cclxuICAgICAgICAgIH1cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L21hdC10YWI+XHJcblxyXG4gICAgPCEtLSB0aW1lbGluZXMgLS0+XHJcbiAgICA8bWF0LXRhYj5cclxuICAgICAgPG5nLXRlbXBsYXRlIG1hdC10YWItbGFiZWw+XHJcbiAgICAgICAgPG1hdC1pY29uPmFuaW1hdGlvbjwvbWF0LWljb24+IDxzcGFuIGNsYXNzPVwibGFiZWxcIj5hbmltYXRpb248L3NwYW4+XHJcbiAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICA8Z3ZlLWFuaW1hdGlvbi10aW1lbGluZS1zZXRcclxuICAgICAgICBbdGFnc109XCJvcFRhZ3NcIlxyXG4gICAgICAgIFtlbGVtZW50SWRzXT1cIm9wRWxlbWVudElkc1wiXHJcbiAgICAgICAgW3RpbWVsaW5lc109XCJ0aW1lbGluZXMudmFsdWVcIlxyXG4gICAgICAgICh0aW1lbGluZXNDaGFuZ2UpPVwib25UaW1lbGluZXNDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgIC8+XHJcbiAgICA8L21hdC10YWI+XHJcbiAgPC9tYXQtdGFiLWdyb3VwPlxyXG5cclxuICA8IS0tIHByb2dyZXNzIC0tPlxyXG4gIDxkaXY+XHJcbiAgICA8bWF0LXByb2dyZXNzLWJhciBtb2RlPVwiaW5kZXRlcm1pbmF0ZVwiICpuZ0lmPVwiYnVzeVwiIC8+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDwhLS0gcmVzdWx0IC0tPlxyXG4gIEBpZiAocmVzdWx0KSB7XHJcbiAgPGZpZWxkc2V0IGlkPVwicmVzdWx0XCI+XHJcbiAgICA8bGVnZW5kPnJlc3VsdDwvbGVnZW5kPlxyXG4gICAgPGd2ZS1jaGFpbi1yZXN1bHQtdmlld1xyXG4gICAgICBbcmVzdWx0XT1cInJlc3VsdFwiXHJcbiAgICAgIFtpbml0aWFsU3RlcEluZGV4XT1cImluaXRpYWxTdGVwSW5kZXhcIlxyXG4gICAgICAoc3RlcFBpY2spPVwib25TdGVwUGljaygkZXZlbnQpXCJcclxuICAgIC8+XHJcbiAgPC9maWVsZHNldD5cclxuICB9XHJcblxyXG4gIDwhLS0gc25hcHNob3QgdmlldyAtLT5cclxuICA8ZmllbGRzZXQgaWQ9XCJwcmV2aWV3XCI+XHJcbiAgICA8bGVnZW5kIGNsYXNzPVwiYnV0dG9uLXJvd1wiPlxyXG4gICAgICA8c3Bhbj57eyB2aWV3VGl0bGUgfX08L3NwYW4+XHJcbiAgICA8L2xlZ2VuZD5cclxuICAgIDxndmUtc25hcHNob3Qtdmlld1xyXG4gICAgICAjc25hcHNob3RWaWV3XHJcbiAgICAgIFtkZWJ1Z109XCJkZWJ1Z1wiXHJcbiAgICAgIFtkYXRhXT1cInZpZXdEYXRhXCJcclxuICAgICAgKHNuYXBzaG90UmVuZGVyKT1cIm9uU25hcHNob3RSZW5kZXIoJGFueSgkZXZlbnQpKVwiXHJcbiAgICAgICh2aXN1YWxFdmVudCk9XCJvblZpc3VhbEV2ZW50KCRhbnkoJGV2ZW50KSlcIlxyXG4gICAgLz5cclxuICAgIDxkaXY+XHJcbiAgICAgIDxtYXQtYnV0dG9uLXRvZ2dsZVxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxyXG4gICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgbWF0VG9vbHRpcD1cIlRvZ2dsZSBydWxlcnNcIlxyXG4gICAgICAgIFtjaGVja2VkXT1cInJ1bGVyc1wiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJ0b2dnbGVSdWxlcnMoKVwiXHJcbiAgICAgID5cclxuICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXQtcHJpbWFyeVwiPnN0cmFpZ2h0ZW48L21hdC1pY29uPlxyXG4gICAgICA8L21hdC1idXR0b24tdG9nZ2xlPlxyXG4gICAgPC9kaXY+XHJcbiAgICBAaWYgKHZpc3VhbEluZm8pIHtcclxuICAgIDxkaXYgaWQ9XCJ2aXN1YWwtaW5mb1wiPnt7IHZpc3VhbEluZm8gfX08L2Rpdj5cclxuICAgIH1cclxuICA8L2ZpZWxkc2V0PlxyXG5cclxuICA8IS0tYnV0dG9ucyAtLT5cclxuICA8ZGl2IGNsYXNzPVwiZm9ybS1yb3ctY2VudGVyXCI+XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICBjbGFzcz1cIm1hdC13YXJuXCJcclxuICAgICAgbWF0LWZsYXQtYnV0dG9uXHJcbiAgICAgIG1hdFRvb2x0aXA9XCJEaXNjYXJkIGNoYW5nZXNcIlxyXG4gICAgICAoY2xpY2spPVwiY2xvc2UoKVwiXHJcbiAgICA+XHJcbiAgICAgIDxtYXQtaWNvbj5jbGVhcjwvbWF0LWljb24+XHJcbiAgICAgIGNsb3NlXHJcbiAgICA8L2J1dHRvbj5cclxuICAgIEBpZiAoIW5vU2F2ZSkge1xyXG4gICAgPGJ1dHRvblxyXG4gICAgICB0eXBlPVwic3VibWl0XCJcclxuICAgICAgY2xhc3M9XCJtYXQtcHJpbWFyeVwiXHJcbiAgICAgIG1hdC1mbGF0LWJ1dHRvblxyXG4gICAgICBtYXRUb29sdGlwPVwiU2F2ZSBjaGFuZ2VzXCJcclxuICAgICAgW2Rpc2FibGVkXT1cImZvcm0uaW52YWxpZFwiXHJcbiAgICA+XHJcbiAgICAgIDxtYXQtaWNvbj5jaGVja19jaXJjbGU8L21hdC1pY29uPlxyXG4gICAgICBzYXZlXHJcbiAgICA8L2J1dHRvbj5cclxuICAgIH1cclxuICA8L2Rpdj5cclxuPC9mb3JtPlxyXG4iXX0=