@myrmidon/gve-core 0.0.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/myrmidon-gve-core.mjs +370 -259
  3. package/fesm2022/myrmidon-gve-core.mjs.map +1 -1
  4. package/lib/components/batch-operation-editor/batch-operation-editor.component.d.ts +46 -0
  5. package/lib/components/chain-result-view/chain-result-view.component.d.ts +4 -1
  6. package/lib/components/feature-editor/feature-editor.component.d.ts +1 -1
  7. package/lib/components/feature-set-editor/feature-set-editor.component.d.ts +1 -1
  8. package/lib/components/snapshot-editor/snapshot-editor.component.d.ts +11 -9
  9. package/lib/components/steps-map/steps-map.component.d.ts +2 -0
  10. package/lib/models.d.ts +8 -0
  11. package/lib/services/gve-api.service.d.ts +33 -0
  12. package/package.json +10 -12
  13. package/public-api.d.ts +1 -0
  14. package/esm2022/lib/components/animation-timeline/animation-timeline.component.mjs +0 -207
  15. package/esm2022/lib/components/animation-timeline-set/animation-timeline-set.component.mjs +0 -154
  16. package/esm2022/lib/components/animation-tween/animation-tween.component.mjs +0 -184
  17. package/esm2022/lib/components/base-text-char/base-text-char.component.mjs +0 -46
  18. package/esm2022/lib/components/base-text-editor/base-text-editor.component.mjs +0 -115
  19. package/esm2022/lib/components/base-text-view/base-text-view.component.mjs +0 -159
  20. package/esm2022/lib/components/chain-operation-editor/chain-operation-editor.component.mjs +0 -570
  21. package/esm2022/lib/components/chain-result-view/chain-result-view.component.mjs +0 -222
  22. package/esm2022/lib/components/feature-editor/feature-editor.component.mjs +0 -200
  23. package/esm2022/lib/components/feature-set-editor/feature-set-editor.component.mjs +0 -175
  24. package/esm2022/lib/components/feature-set-view/feature-set-view.component.mjs +0 -100
  25. package/esm2022/lib/components/ln-heights-editor/ln-heights-editor.component.mjs +0 -126
  26. package/esm2022/lib/components/operation-source-editor/operation-source-editor.component.mjs +0 -131
  27. package/esm2022/lib/components/simple-tree/simple-tree.component.mjs +0 -72
  28. package/esm2022/lib/components/snapshot-editor/snapshot-editor.component.mjs +0 -863
  29. package/esm2022/lib/components/steps-map/steps-map.component.mjs +0 -77
  30. package/esm2022/lib/models.mjs +0 -2
  31. package/esm2022/lib/services/gve-api.service.mjs +0 -65
  32. package/esm2022/lib/services/settings.service.mjs +0 -87
  33. package/esm2022/lib/validators/svg-validators.mjs +0 -34
  34. package/esm2022/myrmidon-gve-core.mjs +0 -5
  35. package/esm2022/public-api.mjs +0 -22
@@ -1,570 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { Component, EventEmitter, Input, Output, } from '@angular/core';
3
- import { ReactiveFormsModule, Validators, } from '@angular/forms';
4
- import { debounceTime, filter } from 'rxjs/operators';
5
- // material
6
- import { ClipboardModule } from '@angular/cdk/clipboard';
7
- import { MatButtonModule } from '@angular/material/button';
8
- import { MatCheckboxModule } from '@angular/material/checkbox';
9
- import { MatExpansionModule } from '@angular/material/expansion';
10
- import { MatFormFieldModule } from '@angular/material/form-field';
11
- import { MatIconModule } from '@angular/material/icon';
12
- import { MatInputModule } from '@angular/material/input';
13
- import { MatSelectModule } from '@angular/material/select';
14
- import { MatTabsModule } from '@angular/material/tabs';
15
- import { MatTooltipModule } from '@angular/material/tooltip';
16
- // vendor
17
- import { NgeMonacoModule } from '@cisstech/nge/monaco';
18
- import { customAlphabet } from 'nanoid';
19
- // myrmidon
20
- import { NgToolsModule } from '@myrmidon/ng-tools';
21
- import { NgMatToolsModule } from '@myrmidon/ng-mat-tools';
22
- import { OperationType, } from '@myrmidon/gve-snapshot-view';
23
- // local
24
- import { FeatureSetEditorComponent } from '../feature-set-editor/feature-set-editor.component';
25
- import { OperationSourceEditorComponent } from '../operation-source-editor/operation-source-editor.component';
26
- import { SvgValidators } from '../../validators/svg-validators';
27
- import { SimpleTreeComponent } from '../simple-tree/simple-tree.component';
28
- import * as i0 from "@angular/core";
29
- import * as i1 from "@angular/forms";
30
- import * as i2 from "@angular/cdk/clipboard";
31
- import * as i3 from "../../services/settings.service";
32
- import * as i4 from "@myrmidon/ng-mat-tools";
33
- import * as i5 from "@angular/common";
34
- import * as i6 from "@angular/material/button";
35
- import * as i7 from "@angular/material/checkbox";
36
- import * as i8 from "@angular/material/expansion";
37
- import * as i9 from "@angular/material/form-field";
38
- import * as i10 from "@angular/material/icon";
39
- import * as i11 from "@angular/material/input";
40
- import * as i12 from "@angular/material/select";
41
- import * as i13 from "@angular/material/core";
42
- import * as i14 from "@angular/material/tabs";
43
- import * as i15 from "@angular/material/tooltip";
44
- import * as i16 from "@cisstech/nge/monaco";
45
- import * as i17 from "@myrmidon/ng-tools";
46
- /**
47
- * 🔑 `gve-chain-operation-editor`
48
- *
49
- * A component for editing a variant generation operation.
50
- * Used by the `gve-snapshot-editor` component.
51
- * - ▶️ `operation` (`CharChainOperation`): the operation to edit.
52
- * - ▶️ `snapshot` (`SnapshotBase`): the snapshot the operation refers to.
53
- * - ▶️ `hidePreview` (`boolean`): whether to hide the preview request button.
54
- * - 🔥 `operationChange` (`CharChainOperation`): emitted when the operation
55
- * is changed.
56
- * - 🔥 `operationPreview` (`CharChainOperation`): emitted when the operation
57
- * preview is requested.
58
- * - 🔥 `operationCancel` (`void`): emitted when operation editing is cancelled.
59
- *
60
- * The editor is composed of many sections:
61
- * - **general**:
62
- * - ID: each operation has an ID, automatically assigned. This is not used in
63
- * the context of the operation or of its transformations, but is provided as a
64
- * reference.
65
- * - at and run: coordinates for the selection of the base text targeted by
66
- * this operation. Check `idx` when `at` is index-based rather than ID-based.
67
- * - to and to-run: a second coordinate, used by some operations.
68
- * - value: the text value argument, for those operations requiring it.
69
- * - rank and group ID.
70
- * - input and output tags.
71
- * - features. These are metadata attached to this operation, and can be any
72
- * type of name=value pairs.
73
- * - **sources**: sources are a special type of metadata used when your text
74
- * versions come from more than a single source. In this case, you can specify
75
- * the source(s) for each operation, just like in a traditional apparatus you
76
- * specify witnesses for each variant. Each source has an ID, a type, a
77
- * probability rank (0=not specified, else 1-N), and an optional free text note.
78
- * - **diplomatic**: SVG `g` code. The diplomatic section is the approximate
79
- * diplomatic representation of the layout of the annotated text. It essentially
80
- * consists in a freely editable SVG code, always grouped into a single root `g`
81
- * element, encoding all the graphical traits representing this operation.
82
- * The visual part of each operation can be placed everywhere on the snapshot,
83
- * as specified by its coordinates.
84
- * - **elements**: features of any of the SVG code elements having an ID.
85
- * The elements section lists all the SVG elements having an `id` attribute in
86
- * the SVG code of the diplomatic section. The ID allows you to attach
87
- * any number of features (metadata modeled as name=value pairs) to each of
88
- * these elements. Among these features, you may use `style` or `class` for
89
- * renditional purposes, and any other name for your own metadata. Note that
90
- * element IDs will be required also when dealing with animations. So, ensure
91
- * to assign an ID to each element you want to animate.
92
- * - **dp feats**: diplomatic features: these are features (metadata modeled
93
- * as name=value pairs) for the diplomatic representation of this operation
94
- * as a whole.
95
- */
96
- export class ChainOperationEditorComponent {
97
- /**
98
- * The operation to edit.
99
- */
100
- get operation() {
101
- return this._operation || undefined;
102
- }
103
- set operation(value) {
104
- if (this._operation === value) {
105
- return;
106
- }
107
- this._operation = value;
108
- this.updateForm(value);
109
- }
110
- /**
111
- * The snapshot the operation refers to.
112
- */
113
- get snapshot() {
114
- return this._snapshot;
115
- }
116
- set snapshot(value) {
117
- if (this._snapshot === value) {
118
- return;
119
- }
120
- const dirty = this.hasTextChanges(value || undefined);
121
- this._snapshot = value || undefined;
122
- if (dirty) {
123
- this.requestPreview();
124
- this._editorModel?.setValue(this.svg.value || '');
125
- }
126
- }
127
- constructor(formBuilder, _clipboard, _settings, _dialogService) {
128
- this._clipboard = _clipboard;
129
- this._settings = _settings;
130
- this._dialogService = _dialogService;
131
- // monaco
132
- this._disposables = [];
133
- this._nanoid = customAlphabet('1234567890abcdef', 10);
134
- this._editedSourceIndex = -1;
135
- /**
136
- * Emitted when the operation is changed.
137
- */
138
- this.operationChange = new EventEmitter();
139
- /**
140
- * Emitted when the operation preview is requested.
141
- */
142
- this.operationPreview = new EventEmitter();
143
- /**
144
- * Emitted when operation editing is cancelled.
145
- */
146
- this.operationCancel = new EventEmitter();
147
- this.tabIndex = 0;
148
- this.hasTo = false;
149
- this.hasToRun = false;
150
- this.hasValue = false;
151
- this._subs = [];
152
- // general
153
- this.rank = formBuilder.control(0, { nonNullable: true });
154
- this.groupId = formBuilder.control(null);
155
- this.features = formBuilder.control([], { nonNullable: true });
156
- this.sources = formBuilder.control([], {
157
- nonNullable: true,
158
- });
159
- this.type = formBuilder.control(OperationType.replace, {
160
- validators: Validators.required,
161
- nonNullable: true,
162
- });
163
- this.at = formBuilder.control(0, {
164
- validators: Validators.required,
165
- nonNullable: true,
166
- });
167
- this.atAsIndex = formBuilder.control(false, { nonNullable: true });
168
- this.to = formBuilder.control(0, { nonNullable: true });
169
- this.toAsIndex = formBuilder.control(false, { nonNullable: true });
170
- this.inputTag = formBuilder.control(null);
171
- this.outputTag = formBuilder.control(null);
172
- this.run = formBuilder.control(0, {
173
- validators: Validators.required,
174
- nonNullable: true,
175
- });
176
- this.toRun = formBuilder.control(0, { nonNullable: true });
177
- this.value = formBuilder.control(null);
178
- // svg
179
- this.svg = formBuilder.control('', {
180
- validators: [SvgValidators.rootGValidator()],
181
- nonNullable: true,
182
- });
183
- this.elementFeatures = formBuilder.control({}, { nonNullable: true });
184
- this.dpFeatures = formBuilder.control([], { nonNullable: true });
185
- this.form = formBuilder.group({
186
- rank: this.rank,
187
- groupId: this.groupId,
188
- features: this.features,
189
- sources: this.sources,
190
- type: this.type,
191
- at: this.at,
192
- atAsIndex: this.atAsIndex,
193
- to: this.to,
194
- toAsIndex: this.toAsIndex,
195
- inputTag: this.inputTag,
196
- outputTag: this.outputTag,
197
- run: this.run,
198
- toRun: this.toRun,
199
- value: this.value,
200
- svg: this.svg,
201
- elementFeatures: this.elementFeatures,
202
- dpFeatures: this.dpFeatures,
203
- });
204
- // SVG elements
205
- this.elements = [];
206
- }
207
- ngOnInit() {
208
- // whenever svg or base change, update preview
209
- this._subs.push(this.form.valueChanges
210
- .pipe(filter((changes) => 'svg' in changes || 'snapshot' in changes), debounceTime(500))
211
- .subscribe(() => {
212
- this.requestPreview();
213
- }));
214
- // whenever type changes, update args UI
215
- this._subs.push(this.type.valueChanges.subscribe(() => this.updateArgsUI()));
216
- }
217
- ngOnDestroy() {
218
- this._disposables.forEach((d) => d.dispose());
219
- for (const sub of this._subs) {
220
- sub.unsubscribe();
221
- }
222
- }
223
- hasTextChanges(snapshot) {
224
- if ((!snapshot && this._snapshot) || (snapshot && !this._snapshot)) {
225
- return true;
226
- }
227
- if (snapshot?.size?.width !== this._snapshot?.size?.width ||
228
- snapshot?.size?.height !== this._snapshot?.size?.height) {
229
- return true;
230
- }
231
- if (snapshot?.style !== this._snapshot?.style ||
232
- snapshot?.text !== this._snapshot?.text ||
233
- snapshot?.textStyle !== this._snapshot?.textStyle) {
234
- return true;
235
- }
236
- // compare textOptions returning true if any different
237
- const options = snapshot?.textOptions;
238
- if (options?.lineHeightOffset !==
239
- this._snapshot?.textOptions?.lineHeightOffset ||
240
- options?.charSpacingOffset !==
241
- this._snapshot?.textOptions?.charSpacingOffset ||
242
- options?.spcWidthOffset !== this._snapshot?.textOptions?.spcWidthOffset) {
243
- return true;
244
- }
245
- return false;
246
- }
247
- onCreateEditor(editor) {
248
- console.log('creating editor');
249
- editor.updateOptions({
250
- minimap: {
251
- side: 'right',
252
- },
253
- wordWrap: 'on',
254
- automaticLayout: true,
255
- });
256
- this._editorModel =
257
- this._editorModel || monaco.editor.createModel(this.svg.value, 'xml');
258
- editor.setModel(this._editorModel);
259
- this._editor = editor;
260
- this._disposables.push(this._editorModel.onDidChangeContent((e) => {
261
- console.log('change content');
262
- const code = this._editorModel.getValue();
263
- if (code !== this.svg.value) {
264
- this.svg.setValue(code);
265
- this.svg.markAsDirty();
266
- this.svg.updateValueAndValidity();
267
- }
268
- }));
269
- }
270
- onFeaturesChange(features) {
271
- this.features.setValue(features);
272
- this.features.markAsDirty();
273
- }
274
- onDpFeaturesChange(features) {
275
- this.dpFeatures.setValue(features);
276
- this.dpFeatures.markAsDirty();
277
- }
278
- // #region sources
279
- addSource() {
280
- this.editedSource = { id: '', type: '' };
281
- this._editedSourceIndex = -1;
282
- }
283
- editSource(index) {
284
- this._editedSourceIndex = index;
285
- this.editedSource = this.sources.value[index];
286
- }
287
- closeSource() {
288
- this._editedSourceIndex = -1;
289
- this.editedSource = undefined;
290
- }
291
- onSourceChange(source) {
292
- const sources = [...this.sources.value];
293
- if (this._editedSourceIndex === -1) {
294
- sources.push(source);
295
- }
296
- else {
297
- sources[this._editedSourceIndex] = source;
298
- }
299
- this.sources.setValue(sources);
300
- this.closeSource();
301
- }
302
- // #endregion
303
- // #region svg
304
- saveSvg() {
305
- if (!this.svg.value) {
306
- return;
307
- }
308
- const blob = new Blob([this.svg.value], { type: 'application/xml' });
309
- const url = window.URL.createObjectURL(blob);
310
- const a = document.createElement('a');
311
- a.href = url;
312
- // create filename from date and time
313
- const now = new Date();
314
- const date = now.toISOString().split('T')[0];
315
- const time = now.toTimeString().split(' ')[0].replace(':', '-');
316
- a.download = `svg-${date}_${time}.svg`;
317
- a.click();
318
- window.URL.revokeObjectURL(url);
319
- }
320
- openSvgEditor() {
321
- const url = this._settings.get('svg-editor', 'https://editor.method.ac/'
322
- // 'https://boxy-svg.com/app'
323
- );
324
- if (url) {
325
- if (this.svg.value) {
326
- this._clipboard.copy(this.svg.value);
327
- }
328
- window.open(url, '_blank');
329
- }
330
- }
331
- loadSvg() {
332
- const input = document.createElement('input');
333
- input.type = 'file';
334
- input.accept = '.svg';
335
- input.onchange = () => {
336
- const file = input.files?.[0];
337
- if (file) {
338
- const reader = new FileReader();
339
- reader.onload = (e) => {
340
- this.svg.setValue(e.target?.result);
341
- };
342
- reader.readAsText(file);
343
- }
344
- };
345
- input.click();
346
- }
347
- setSvgFromClipboard() {
348
- navigator.clipboard.readText().then((text) => {
349
- this.svg.setValue(text);
350
- });
351
- }
352
- parseSvg(svg) {
353
- if (!svg) {
354
- return [];
355
- }
356
- try {
357
- // parse SVG code extracting all the SVG elements with an id attribute
358
- const parser = new DOMParser();
359
- const doc = parser.parseFromString(svg, 'image/svg+xml');
360
- const elements = Array.from(doc.querySelectorAll('[id]'));
361
- // for each element, read x and y and add a transform with a translate
362
- // equal to -x and -y so that the element is at the origin. This is useful
363
- // so that the element can be previewed in its box without wasting space
364
- // just because it happens not to be placed at the SVG origin
365
- for (const element of elements) {
366
- const x = parseFloat(element.getAttribute('x') || '0');
367
- const y = parseFloat(element.getAttribute('y') || '0');
368
- element.setAttribute('transform', `translate(${-x},${-y})`);
369
- }
370
- return elements;
371
- }
372
- catch (e) {
373
- this.svg.setErrors({ invalidSvg: true });
374
- return [];
375
- }
376
- }
377
- // #endregion
378
- // #region element features
379
- onTabIndexChange(index) {
380
- this.tabIndex = index;
381
- if (index === 3) {
382
- this.elements = this.parseSvg(this.svg.value);
383
- }
384
- }
385
- editElementFeatures(element) {
386
- const id = element.id;
387
- const features = this.elementFeatures.value[id] || [];
388
- this.elementFeatures.setValue({
389
- ...this.elementFeatures.value,
390
- [id]: features,
391
- });
392
- this.editedElementId = id;
393
- }
394
- deleteElementFeatures(element) {
395
- const id = element.id;
396
- const elementFeatures = { ...this.elementFeatures.value };
397
- if (!elementFeatures[id]) {
398
- return;
399
- }
400
- this._dialogService
401
- .confirm('Confirm', 'Delete element features?')
402
- .subscribe((yes) => {
403
- if (yes) {
404
- delete elementFeatures[id];
405
- this.elementFeatures.setValue(elementFeatures);
406
- if (this.editedElementId === id) {
407
- this.editedElementId = undefined;
408
- }
409
- }
410
- });
411
- }
412
- onElementFeaturesChange(features) {
413
- if (this.editedElementId) {
414
- this.elementFeatures.setValue({
415
- ...this.elementFeatures.value,
416
- [this.editedElementId]: features,
417
- });
418
- }
419
- }
420
- // #endregion
421
- updateArgsUI() {
422
- let to = false, toRun = false, value = false;
423
- switch (this.type.value) {
424
- case OperationType.moveAfter:
425
- case OperationType.moveBefore:
426
- to = true;
427
- break;
428
- case OperationType.swap:
429
- to = true;
430
- toRun = true;
431
- break;
432
- case OperationType.addAfter:
433
- case OperationType.addBefore:
434
- case OperationType.replace:
435
- value = true;
436
- break;
437
- }
438
- this.hasTo = to;
439
- this.hasToRun = toRun;
440
- this.hasValue = value;
441
- if (!to) {
442
- this.to.reset();
443
- }
444
- if (!toRun) {
445
- this.toRun.reset();
446
- }
447
- if (!value) {
448
- this.value.reset();
449
- }
450
- }
451
- updateForm(operation) {
452
- if (!operation) {
453
- this.form.reset();
454
- this.updateArgsUI();
455
- return;
456
- }
457
- // get or generate ID
458
- if (operation.id) {
459
- this.id = operation.id;
460
- }
461
- else {
462
- this.id = this._nanoid();
463
- }
464
- this.rank.setValue(operation.rank || 0);
465
- this.groupId.setValue(operation.groupId || null);
466
- this.features.setValue(operation.features || []);
467
- this.sources.setValue(operation.sources || []);
468
- this.dpFeatures.setValue(operation.diplomatics?.features || []);
469
- this.type.setValue(operation.type);
470
- this.at.setValue(operation.at);
471
- this.atAsIndex.setValue(operation.atAsIndex || false);
472
- this.to.setValue(operation.to || 0);
473
- this.toAsIndex.setValue(operation.toAsIndex || false);
474
- this.inputTag.setValue(operation.inputTag || null);
475
- this.outputTag.setValue(operation.outputTag || null);
476
- this.run.setValue(operation.run);
477
- this.toRun.setValue(operation.toRun || 0);
478
- this.value.setValue(operation.value || null);
479
- this.svg.setValue(operation.diplomatics?.g || '');
480
- this._editorModel?.setValue(this.svg.value || '');
481
- this.elementFeatures.setValue(operation.diplomatics?.elementFeatures || {});
482
- this.form.markAsPristine();
483
- this.elements = this.parseSvg(operation.diplomatics?.g);
484
- this.updateArgsUI();
485
- }
486
- cancel() {
487
- this.operationCancel.emit();
488
- }
489
- getOperation() {
490
- return {
491
- rank: this.rank.value || undefined,
492
- groupId: this.groupId.value || undefined,
493
- features: this.features.value?.length ? this.features.value : undefined,
494
- sources: this.sources.value?.length ? this.sources.value : undefined,
495
- diplomatics: {
496
- g: this.svg.value,
497
- features: this.dpFeatures.value,
498
- elementFeatures: this.elementFeatures.value,
499
- },
500
- id: this.id,
501
- type: this.type.value,
502
- at: this.at.value,
503
- atAsIndex: this.atAsIndex.value || undefined,
504
- to: this.to.value || undefined,
505
- toAsIndex: this.toAsIndex.value || undefined,
506
- inputTag: this.inputTag.value || undefined,
507
- outputTag: this.outputTag.value || undefined,
508
- run: this.run.value,
509
- toRun: this.toRun.value || undefined,
510
- value: this.value.value || undefined,
511
- };
512
- }
513
- requestPreview() {
514
- this.operationPreview.emit(this.getOperation());
515
- }
516
- save() {
517
- if (!this.form.valid) {
518
- return;
519
- }
520
- this._operation = this.getOperation();
521
- this.operationChange.emit(this._operation);
522
- }
523
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: ChainOperationEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i2.Clipboard }, { token: i3.SettingsService }, { token: i4.DialogService }], target: i0.ɵɵFactoryTarget.Component }); }
524
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: ChainOperationEditorComponent, isStandalone: true, selector: "gve-chain-operation-editor", inputs: { operation: "operation", snapshot: "snapshot", hidePreview: "hidePreview" }, outputs: { operationChange: "operationChange", operationPreview: "operationPreview", operationCancel: "operationCancel" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- tabs -->\r\n <mat-tab-group\r\n [selectedIndex]=\"tabIndex\"\r\n (selectedIndexChange)=\"onTabIndexChange($event)\"\r\n >\r\n <!-- GENERAL -->\r\n <mat-tab label=\"general\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <div id=\"id\" class=\"muted\">{{ id }}</div>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n <mat-option [value]=\"0\"><mat-icon>layers</mat-icon> replace</mat-option>\r\n <mat-option [value]=\"1\"><mat-icon>close</mat-icon>delete</mat-option>\r\n <mat-option [value]=\"2\"><mat-icon>last_page</mat-icon>add-before</mat-option>\r\n <mat-option [value]=\"3\"><mat-icon>first_page</mat-icon>add-after</mat-option>\r\n <mat-option [value]=\"4\"><mat-icon>login</mat-icon>move-before</mat-option>\r\n <mat-option [value]=\"5\"><mat-icon>logout</mat-icon>move-after</mat-option>\r\n <mat-option [value]=\"6\"><mat-icon>compare_arrows</mat-icon>swap</mat-option>\r\n <mat-option [value]=\"7\"><mat-icon>edit_note</mat-icon>annotate</mat-option>\r\n </mat-select>\r\n <mat-error\r\n *ngIf=\"$any(type).errors?.required && (type.dirty || type.touched)\"\r\n >type required</mat-error\r\n >\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- at -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>at</mat-label>\r\n <input matInput [formControl]=\"at\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(at).errors?.required && (at.dirty || at.touched)\"\r\n >at required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- atAsIndex -->\r\n <mat-checkbox [formControl]=\"atAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- run -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>run</mat-label>\r\n <input matInput [formControl]=\"run\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(run).errors?.required && (run.dirty || run.touched)\"\r\n >run required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- to -->\r\n @if (hasTo) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to</mat-label>\r\n <input matInput [formControl]=\"to\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(to).errors?.required && (to.dirty || to.touched)\"\r\n >to required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- toAsIndex -->\r\n <mat-checkbox [formControl]=\"toAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- toRun -->\r\n @if (hasToRun) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to run</mat-label>\r\n <input matInput [formControl]=\"toRun\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(toRun).errors?.required && (toRun.dirty || toRun.touched)\r\n \"\r\n >to run required</mat-error\r\n >\r\n </mat-form-field>\r\n } }\r\n\r\n <!-- value -->\r\n @if (hasValue) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n </mat-form-field>\r\n }\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(rank).errors?.required && (rank.dirty || rank.touched)\"\r\n >rank required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- groupId -->\r\n <mat-form-field>\r\n <mat-label>group ID</mat-label>\r\n <input matInput [formControl]=\"groupId\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(groupId).errors?.required &&\r\n (groupId.dirty || groupId.touched)\r\n \"\r\n >group ID required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- inputTag -->\r\n <mat-form-field>\r\n <mat-label>input tag</mat-label>\r\n <input matInput [formControl]=\"inputTag\" />\r\n <mat-hint>blank=latest</mat-hint>\r\n </mat-form-field>\r\n\r\n <!-- outputTag -->\r\n <mat-form-field>\r\n <mat-label>output tag</mat-label>\r\n <input matInput [formControl]=\"outputTag\" />\r\n <mat-hint>blank=auto (vN)</mat-hint>\r\n </mat-form-field>\r\n </div>\r\n <div>\r\n <!-- features -->\r\n <fieldset>\r\n <legend>operation features</legend>\r\n <gve-feature-set-editor\r\n [isVar]=\"true\"\r\n [features]=\"features.value\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </fieldset>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- SOURCES -->\r\n <mat-tab label=\"sources\">\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addSource()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n source\r\n </button>\r\n </div>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>type</th>\r\n <th>id</th>\r\n <th>rank</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of sources.value; track s) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n (click)=\"editSource($index)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button color=\"warn\">\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ s.type }}</td>\r\n <td>{{ s.id }}</td>\r\n <td>{{ s.rank }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n <!-- source editor -->\r\n <mat-expansion-panel [disabled]=\"!editedSource\" [expanded]=\"editedSource\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>source</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-operation-source-editor\r\n [source]=\"editedSource\"\r\n (sourceChange)=\"onSourceChange($event!)\"\r\n (sourceCancel)=\"closeSource()\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DIPLOMATIC -->\r\n <mat-tab label=\"diplomatic\">\r\n <div class=\"toolbar-row\">\r\n <button\r\n id=\"btn-save\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Save to file\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"saveSvg()\"\r\n >\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-load\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Load from file\"\r\n (click)=\"loadSvg()\"\r\n >\r\n <mat-icon>folder</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-copy\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy\"\r\n [cdkCopyToClipboard]=\"svg.value\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-paste\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Set SVG from clipboard\"\r\n (click)=\"setSvgFromClipboard()\"\r\n >\r\n <mat-icon>content_paste_go</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-editor\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open SVG external editor\"\r\n (click)=\"openSvgEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div id=\"code\">\r\n <nge-monaco-editor\r\n style=\"--editor-height: 400px\"\r\n (ready)=\"onCreateEditor($event)\"\r\n />\r\n @if (svg.invalid) {\r\n <mat-error>invalid SVG</mat-error>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- ELEMENTS -->\r\n <mat-tab label=\"elements\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>id</th>\r\n <th>visual</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (e of elements; track e.id) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Edit element features\"\r\n (click)=\"editElementFeatures(e)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n matTooltip=\"Delete all element features\"\r\n (click)=\"deleteElementFeatures(e)\"\r\n [disabled]=\"!$any(elementFeatures.value[e.id])?.length\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <span>{{$any(elementFeatures.value[e.id])?.length || 0}}</span>\r\n </td>\r\n <td class=\"feat-count\">{{ e.id }}</td>\r\n <td class=\"svg-cell\">\r\n <svg [innerHTML]=\"e.outerHTML | safeHtml : 'html'\"></svg>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <mat-expansion-panel\r\n [disabled]=\"!editedElementId\"\r\n [expanded]=\"editedElementId\"\r\n >\r\n <mat-expansion-panel-header>element</mat-expansion-panel-header>\r\n <gve-feature-set-editor\r\n [features]=\"elementFeatures.value[editedElementId!] || []\"\r\n (featuresChange)=\"onElementFeaturesChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DP FEATS -->\r\n <mat-tab label=\"d-features\">\r\n <gve-feature-set-editor\r\n [features]=\"dpFeatures.value\"\r\n (featuresChange)=\"onDpFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- buttons -->\r\n <div id=\"submit-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard operation\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n @if (!hidePreview) {\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Preview operation\"\r\n (click)=\"requestPreview()\"\r\n >\r\n <mat-icon class=\"mat-primary\">preview</mat-icon>\r\n </button>\r\n }\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save operation\"\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 </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}#submit-row{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px;border-top:1px solid silver}.toolbar-row{display:flex;align-items:center;flex-wrap:wrap}.nr{width:5em}.long-text{width:100%;max-width:800px}#id{border-radius:6px;padding:4px;background-color:#beb9b9;color:#fff;margin-top:-16px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:silver}table{width:100%;border-collapse:collapse;margin:8px 0}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}td.feat-count{vertical-align:super;font-size:smaller}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr{border-bottom:1px solid silver}th,td{text-align:center}#btn-save{color:#072d3e}#btn-load{color:#dbd112}#btn-copy{color:#22549f}#btn-preview{color:#095409}#code{height:500px;border:1px solid silver}#monaco{height:100%}.svg-cell{padding:0 8px}.svg-cell svg{border:1px solid silver;width:100%;height:auto}#preview{box-sizing:border-box;width:100%;border:1px solid silver;border-radius:4px;padding:8px}.tree-invisible{display:none}.tree ul,.tree li{margin-top:0;margin-bottom:0;list-style-type:none}.selected-node{background-color:#e5e5e5}.child-title{font-weight:700;margin:0;background-color:#ccc;color:#fff;padding:8px}#tree-container{display:grid;grid-template-rows:auto;grid-template-columns:auto 1fr;grid-template-areas:\"nav ed\";gap:0 16px;align-items:stretch}#tree-nav{grid-area:nav;border:1px solid silver;border-radius:6px;margin:8px 0;padding-right:8px}#tree-ed{grid-area:ed;border:1px solid silver;border-radius:6px;margin:8px 0}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"nav\" \"ed\";gap:16px 0;align-items:start}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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: "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:
525
- // material
526
- ClipboardModule }, { kind: "directive", type: i2.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { 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: MatCheckboxModule }, { kind: "component", type: i7.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { 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: "directive", type: i9.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i9.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: MatSelectModule }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i13.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i14.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i14.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: i15.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type:
527
- // monaco
528
- NgeMonacoModule }, { kind: "component", type: i16.NgeMonacoEditorComponent, selector: "nge-monaco-editor", inputs: ["autoLayout", "options"], outputs: ["ready"] }, { kind: "ngmodule", type: NgToolsModule }, { kind: "pipe", type: i17.SafeHtmlPipe, name: "safeHtml" }, { kind: "ngmodule", type: NgMatToolsModule }, { kind: "component", type:
529
- // myrmex
530
- FeatureSetEditorComponent, selector: "gve-feature-set-editor", inputs: ["isVar", "featNames", "featValues", "filterThreshold", "features"], outputs: ["featuresChange"] }, { kind: "component", type: OperationSourceEditorComponent, selector: "gve-operation-source-editor", inputs: ["source", "ids", "types"], outputs: ["sourceChange", "sourceCancel"] }] }); }
531
- }
532
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: ChainOperationEditorComponent, decorators: [{
533
- type: Component,
534
- args: [{ selector: 'gve-chain-operation-editor', standalone: true, imports: [
535
- CommonModule,
536
- ReactiveFormsModule,
537
- // material
538
- ClipboardModule,
539
- MatButtonModule,
540
- MatCheckboxModule,
541
- MatExpansionModule,
542
- MatFormFieldModule,
543
- MatIconModule,
544
- MatInputModule,
545
- MatSelectModule,
546
- MatTabsModule,
547
- MatTooltipModule,
548
- // monaco
549
- NgeMonacoModule,
550
- NgToolsModule,
551
- NgMatToolsModule,
552
- // myrmex
553
- FeatureSetEditorComponent,
554
- SimpleTreeComponent,
555
- OperationSourceEditorComponent,
556
- ], template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- tabs -->\r\n <mat-tab-group\r\n [selectedIndex]=\"tabIndex\"\r\n (selectedIndexChange)=\"onTabIndexChange($event)\"\r\n >\r\n <!-- GENERAL -->\r\n <mat-tab label=\"general\">\r\n <div class=\"form-row\">\r\n <!-- id -->\r\n <div id=\"id\" class=\"muted\">{{ id }}</div>\r\n\r\n <!-- type -->\r\n <mat-form-field>\r\n <mat-label>type</mat-label>\r\n <mat-select [formControl]=\"type\">\r\n <mat-option [value]=\"0\"><mat-icon>layers</mat-icon> replace</mat-option>\r\n <mat-option [value]=\"1\"><mat-icon>close</mat-icon>delete</mat-option>\r\n <mat-option [value]=\"2\"><mat-icon>last_page</mat-icon>add-before</mat-option>\r\n <mat-option [value]=\"3\"><mat-icon>first_page</mat-icon>add-after</mat-option>\r\n <mat-option [value]=\"4\"><mat-icon>login</mat-icon>move-before</mat-option>\r\n <mat-option [value]=\"5\"><mat-icon>logout</mat-icon>move-after</mat-option>\r\n <mat-option [value]=\"6\"><mat-icon>compare_arrows</mat-icon>swap</mat-option>\r\n <mat-option [value]=\"7\"><mat-icon>edit_note</mat-icon>annotate</mat-option>\r\n </mat-select>\r\n <mat-error\r\n *ngIf=\"$any(type).errors?.required && (type.dirty || type.touched)\"\r\n >type required</mat-error\r\n >\r\n </mat-form-field>\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- at -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>at</mat-label>\r\n <input matInput [formControl]=\"at\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(at).errors?.required && (at.dirty || at.touched)\"\r\n >at required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- atAsIndex -->\r\n <mat-checkbox [formControl]=\"atAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- run -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>run</mat-label>\r\n <input matInput [formControl]=\"run\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(run).errors?.required && (run.dirty || run.touched)\"\r\n >run required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- to -->\r\n @if (hasTo) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to</mat-label>\r\n <input matInput [formControl]=\"to\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(to).errors?.required && (to.dirty || to.touched)\"\r\n >to required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- toAsIndex -->\r\n <mat-checkbox [formControl]=\"toAsIndex\">idx</mat-checkbox>\r\n\r\n <!-- toRun -->\r\n @if (hasToRun) {\r\n <mat-form-field class=\"nr\">\r\n <mat-label>to run</mat-label>\r\n <input matInput [formControl]=\"toRun\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(toRun).errors?.required && (toRun.dirty || toRun.touched)\r\n \"\r\n >to run required</mat-error\r\n >\r\n </mat-form-field>\r\n } }\r\n\r\n <!-- value -->\r\n @if (hasValue) {\r\n <mat-form-field>\r\n <mat-label>value</mat-label>\r\n <input matInput [formControl]=\"value\" />\r\n </mat-form-field>\r\n }\r\n </div>\r\n <div class=\"form-row\">\r\n <!-- rank -->\r\n <mat-form-field class=\"nr\">\r\n <mat-label>rank</mat-label>\r\n <input matInput [formControl]=\"rank\" type=\"number\" min=\"0\" />\r\n <mat-error\r\n *ngIf=\"$any(rank).errors?.required && (rank.dirty || rank.touched)\"\r\n >rank required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- groupId -->\r\n <mat-form-field>\r\n <mat-label>group ID</mat-label>\r\n <input matInput [formControl]=\"groupId\" />\r\n <mat-error\r\n *ngIf=\"\r\n $any(groupId).errors?.required &&\r\n (groupId.dirty || groupId.touched)\r\n \"\r\n >group ID required</mat-error\r\n >\r\n </mat-form-field>\r\n\r\n <!-- inputTag -->\r\n <mat-form-field>\r\n <mat-label>input tag</mat-label>\r\n <input matInput [formControl]=\"inputTag\" />\r\n <mat-hint>blank=latest</mat-hint>\r\n </mat-form-field>\r\n\r\n <!-- outputTag -->\r\n <mat-form-field>\r\n <mat-label>output tag</mat-label>\r\n <input matInput [formControl]=\"outputTag\" />\r\n <mat-hint>blank=auto (vN)</mat-hint>\r\n </mat-form-field>\r\n </div>\r\n <div>\r\n <!-- features -->\r\n <fieldset>\r\n <legend>operation features</legend>\r\n <gve-feature-set-editor\r\n [isVar]=\"true\"\r\n [features]=\"features.value\"\r\n (featuresChange)=\"onFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </fieldset>\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- SOURCES -->\r\n <mat-tab label=\"sources\">\r\n <div>\r\n <button\r\n type=\"button\"\r\n mat-flat-button\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n (click)=\"addSource()\"\r\n >\r\n <mat-icon>add_circle</mat-icon>\r\n source\r\n </button>\r\n </div>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>type</th>\r\n <th>id</th>\r\n <th>rank</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (s of sources.value; track s) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n (click)=\"editSource($index)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button type=\"button\" mat-icon-button color=\"warn\">\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n </td>\r\n <td>{{ s.type }}</td>\r\n <td>{{ s.id }}</td>\r\n <td>{{ s.rank }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n <!-- source editor -->\r\n <mat-expansion-panel [disabled]=\"!editedSource\" [expanded]=\"editedSource\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>source</mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <gve-operation-source-editor\r\n [source]=\"editedSource\"\r\n (sourceChange)=\"onSourceChange($event!)\"\r\n (sourceCancel)=\"closeSource()\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DIPLOMATIC -->\r\n <mat-tab label=\"diplomatic\">\r\n <div class=\"toolbar-row\">\r\n <button\r\n id=\"btn-save\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Save to file\"\r\n [disabled]=\"!svg.value\"\r\n (click)=\"saveSvg()\"\r\n >\r\n <mat-icon>save</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-load\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Load from file\"\r\n (click)=\"loadSvg()\"\r\n >\r\n <mat-icon>folder</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-copy\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Copy\"\r\n [cdkCopyToClipboard]=\"svg.value\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-paste\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Set SVG from clipboard\"\r\n (click)=\"setSvgFromClipboard()\"\r\n >\r\n <mat-icon>content_paste_go</mat-icon>\r\n </button>\r\n <button\r\n id=\"btn-editor\"\r\n type=\"button\"\r\n mat-icon-button\r\n matTooltip=\"Open SVG external editor\"\r\n (click)=\"openSvgEditor()\"\r\n >\r\n <mat-icon>launch</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div id=\"code\">\r\n <nge-monaco-editor\r\n style=\"--editor-height: 400px\"\r\n (ready)=\"onCreateEditor($event)\"\r\n />\r\n @if (svg.invalid) {\r\n <mat-error>invalid SVG</mat-error>\r\n }\r\n </div>\r\n </mat-tab>\r\n\r\n <!-- ELEMENTS -->\r\n <mat-tab label=\"elements\">\r\n <table>\r\n <thead>\r\n <tr>\r\n <th></th>\r\n <th>id</th>\r\n <th>visual</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (e of elements; track e.id) {\r\n <tr>\r\n <td class=\"fit-width\">\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n matTooltip=\"Edit element features\"\r\n (click)=\"editElementFeatures(e)\"\r\n >\r\n <mat-icon class=\"mat-primary\">edit</mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"warn\"\r\n matTooltip=\"Delete all element features\"\r\n (click)=\"deleteElementFeatures(e)\"\r\n [disabled]=\"!$any(elementFeatures.value[e.id])?.length\"\r\n >\r\n <mat-icon class=\"mat-warn\">delete</mat-icon>\r\n </button>\r\n <span>{{$any(elementFeatures.value[e.id])?.length || 0}}</span>\r\n </td>\r\n <td class=\"feat-count\">{{ e.id }}</td>\r\n <td class=\"svg-cell\">\r\n <svg [innerHTML]=\"e.outerHTML | safeHtml : 'html'\"></svg>\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n\r\n <mat-expansion-panel\r\n [disabled]=\"!editedElementId\"\r\n [expanded]=\"editedElementId\"\r\n >\r\n <mat-expansion-panel-header>element</mat-expansion-panel-header>\r\n <gve-feature-set-editor\r\n [features]=\"elementFeatures.value[editedElementId!] || []\"\r\n (featuresChange)=\"onElementFeaturesChange($event)\"\r\n />\r\n </mat-expansion-panel>\r\n </mat-tab>\r\n\r\n <!-- DP FEATS -->\r\n <mat-tab label=\"d-features\">\r\n <gve-feature-set-editor\r\n [features]=\"dpFeatures.value\"\r\n (featuresChange)=\"onDpFeaturesChange($event)\"\r\n ></gve-feature-set-editor>\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <!-- buttons -->\r\n <div id=\"submit-row\">\r\n <button\r\n type=\"button\"\r\n color=\"warn\"\r\n mat-icon-button\r\n matTooltip=\"Discard operation\"\r\n (click)=\"cancel()\"\r\n >\r\n <mat-icon class=\"mat-warn\">clear</mat-icon>\r\n </button>\r\n @if (!hidePreview) {\r\n <button\r\n type=\"button\"\r\n color=\"primary\"\r\n mat-icon-button\r\n matTooltip=\"Preview operation\"\r\n (click)=\"requestPreview()\"\r\n >\r\n <mat-icon class=\"mat-primary\">preview</mat-icon>\r\n </button>\r\n }\r\n <button\r\n type=\"submit\"\r\n color=\"primary\"\r\n class=\"mat-primary\"\r\n mat-flat-button\r\n matTooltip=\"Save operation\"\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 </div>\r\n</form>\r\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}#submit-row{display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px;border-top:1px solid silver}.toolbar-row{display:flex;align-items:center;flex-wrap:wrap}.nr{width:5em}.long-text{width:100%;max-width:800px}#id{border-radius:6px;padding:4px;background-color:#beb9b9;color:#fff;margin-top:-16px}fieldset{border:1px solid silver;border-radius:6px;padding:8px;margin:8px 0}legend{color:silver}table{width:100%;border-collapse:collapse;margin:8px 0}th{color:#909090;font-weight:400;text-align:left;background-color:#e1e0e0}th,td{padding:4px;border-bottom:1px solid silver}td.feat-count{vertical-align:super;font-size:smaller}tbody tr:nth-child(2n){background-color:#e8e8e8}td.fit-width{width:1px;white-space:nowrap}tr{border-bottom:1px solid silver}th,td{text-align:center}#btn-save{color:#072d3e}#btn-load{color:#dbd112}#btn-copy{color:#22549f}#btn-preview{color:#095409}#code{height:500px;border:1px solid silver}#monaco{height:100%}.svg-cell{padding:0 8px}.svg-cell svg{border:1px solid silver;width:100%;height:auto}#preview{box-sizing:border-box;width:100%;border:1px solid silver;border-radius:4px;padding:8px}.tree-invisible{display:none}.tree ul,.tree li{margin-top:0;margin-bottom:0;list-style-type:none}.selected-node{background-color:#e5e5e5}.child-title{font-weight:700;margin:0;background-color:#ccc;color:#fff;padding:8px}#tree-container{display:grid;grid-template-rows:auto;grid-template-columns:auto 1fr;grid-template-areas:\"nav ed\";gap:0 16px;align-items:stretch}#tree-nav{grid-area:nav;border:1px solid silver;border-radius:6px;margin:8px 0;padding-right:8px}#tree-ed{grid-area:ed;border:1px solid silver;border-radius:6px;margin:8px 0}@media only screen and (max-width: 959px){div#container{grid-template-columns:1fr;grid-template-areas:\"nav\" \"ed\";gap:16px 0;align-items:start}}\n"] }]
557
- }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.Clipboard }, { type: i3.SettingsService }, { type: i4.DialogService }], propDecorators: { operation: [{
558
- type: Input
559
- }], snapshot: [{
560
- type: Input
561
- }], hidePreview: [{
562
- type: Input
563
- }], operationChange: [{
564
- type: Output
565
- }], operationPreview: [{
566
- type: Output
567
- }], operationCancel: [{
568
- type: Output
569
- }] } });
570
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhaW4tb3BlcmF0aW9uLWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9teXJtaWRvbi9ndmUtY29yZS9zcmMvbGliL2NvbXBvbmVudHMvY2hhaW4tb3BlcmF0aW9uLWVkaXRvci9jaGFpbi1vcGVyYXRpb24tZWRpdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL215cm1pZG9uL2d2ZS1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9jaGFpbi1vcGVyYXRpb24tZWRpdG9yL2NoYWluLW9wZXJhdGlvbi1lZGl0b3IuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUlMLG1CQUFtQixFQUNuQixVQUFVLEdBQ1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXRELFdBQVc7QUFDWCxPQUFPLEVBQWEsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlC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QUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxRQUFRLElBQUksRUFBRSxDQUFDLENBQUM7UUFFaEUsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25DLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQyxDQUFDO1FBQ3RELElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFNBQVMsSUFBSSxLQUFLLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDMUMsSUFB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SSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM3QyxDQUFDOzhHQXBpQlUsNkJBQTZCO2tHQUE3Qiw2QkFBNkIsdVNDckkxQyx5M1hBMldBLG04REQvUEksWUFBWSxrSUFDWixtQkFBbUI7Z0JBQ25CLFdBQVc7Z0JBQ1gsZUFBZSx5TkFDZixlQUFlLHdVQUNmLGlCQUFpQixvWUFDakIsa0JBQWtCLHlkQUNsQixrQkFBa0IsK2RBQ2xCLGFBQWEsb0xBQ2IsY0FBYywyV0FDZCxlQUFlLHFyQkFDZixhQUFhLDhvQkFDYixnQkFBZ0I7Z0JBQ2hCLFNBQVM7Z0JBQ1QsZUFBZSwrS0FDZixhQUFhLDBGQUNiLGdCQUFnQjtnQkFDaEIsU0FBUztnQkFDVCx5QkFBeUIsNktBRXpCLDhCQUE4Qjs7MkZBS3JCLDZCQUE2QjtrQkE3QnpDLFNBQVM7K0JBQ0UsNEJBQTRCLGNBQzFCLElBQUksV0FDUDt3QkFDUCxZQUFZO3dCQUNaLG1CQUFtQjt3QkFDbkIsV0FBVzt3QkFDWCxlQUFlO3dCQUNmLGVBQWU7d0JBQ2YsaUJBQWlCO3dCQUNqQixrQkFBa0I7d0JBQ2xCLGtCQUFrQjt3QkFDbEIsYUFBYTt3QkFDYixjQUFjO3dCQUNkLGVBQWU7d0JBQ2YsYUFBYTt3QkFDYixnQkFBZ0I7d0JBQ2hCLFNBQVM7d0JBQ1QsZUFBZTt3QkFDZixhQUFhO3dCQUNiLGdCQUFnQjt3QkFDaEIsU0FBUzt3QkFDVCx5QkFBeUI7d0JBQ3pCLG1CQUFtQjt3QkFDbkIsOEJBQThCO3FCQUMvQjtrS0FxQlUsU0FBUztzQkFEbkIsS0FBSztnQkFnQkssUUFBUTtzQkFEbEIsS0FBSztnQkFvQkMsV0FBVztzQkFEakIsS0FBSztnQkFPVSxlQUFlO3NCQUQ5QixNQUFNO2dCQU9TLGdCQUFnQjtzQkFEL0IsTUFBTTtnQkFPUyxlQUFlO3NCQUQ5QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveSxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIEZvcm1CdWlsZGVyLFxyXG4gIEZvcm1Db250cm9sLFxyXG4gIEZvcm1Hcm91cCxcclxuICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxyXG4gIFZhbGlkYXRvcnMsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBmaWx0ZXIgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG4vLyBtYXRlcmlhbFxyXG5pbXBvcnQgeyBDbGlwYm9hcmQsIENsaXBib2FyZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jbGlwYm9hcmQnO1xyXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xyXG5pbXBvcnQgeyBNYXRDaGVja2JveE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NoZWNrYm94JztcclxuaW1wb3J0IHsgTWF0RXhwYW5zaW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZXhwYW5zaW9uJztcclxuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XHJcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcclxuaW1wb3J0IHsgTWF0SW5wdXRNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XHJcbmltcG9ydCB7IE1hdFNlbGVjdE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XHJcbmltcG9ydCB7IE1hdFRhYnNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcclxuaW1wb3J0IHsgTWF0VG9vbHRpcE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnO1xyXG5cclxuLy8gdmVuZG9yXHJcbmltcG9ydCB7IE5nZU1vbmFjb01vZHVsZSB9IGZyb20gJ0BjaXNzdGVjaC9uZ2UvbW9uYWNvJztcclxuaW1wb3J0IHsgY3VzdG9tQWxwaGFiZXQgfSBmcm9tICduYW5vaWQnO1xyXG5cclxuLy8gbXlybWlkb25cclxuaW1wb3J0IHsgTmdUb29sc01vZHVsZSB9IGZyb20gJ0BteXJtaWRvbi9uZy10b29scyc7XHJcbmltcG9ydCB7IERpYWxvZ1NlcnZpY2UsIE5nTWF0VG9vbHNNb2R1bGUgfSBmcm9tICdAbXlybWlkb24vbmctbWF0LXRvb2xzJztcclxuaW1wb3J0IHtcclxuICBDaGFyQ2hhaW5PcGVyYXRpb24sXHJcbiAgRmVhdHVyZSxcclxuICBPcGVyYXRpb25GZWF0dXJlLFxyXG4gIE9wZXJhdGlvblR5cGUsXHJcbiAgT3BlcmF0aW9uU291cmNlLFxyXG4gIFNuYXBzaG90QmFzZSxcclxufSBmcm9tICdAbXlybWlkb24vZ3ZlLXNuYXBzaG90LXZpZXcnO1xyXG5cclxuLy8gbG9jYWxcclxuaW1wb3J0IHsgRmVhdHVyZVNldEVkaXRvckNvbXBvbmVudCB9IGZyb20gJy4uL2ZlYXR1cmUtc2V0LWVkaXRvci9mZWF0dXJlLXNldC1lZGl0b3IuY29tcG9uZW50JztcclxuaW1wb3J0IHsgT3BlcmF0aW9uU291cmNlRWRpdG9yQ29tcG9uZW50IH0gZnJvbSAnLi4vb3BlcmF0aW9uLXNvdXJjZS1lZGl0b3Ivb3BlcmF0aW9uLXNvdXJjZS1lZGl0b3IuY29tcG9uZW50JztcclxuaW1wb3J0IHsgU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvc2V0dGluZ3Muc2VydmljZSc7XHJcbmltcG9ydCB7IFN2Z1ZhbGlkYXRvcnMgfSBmcm9tICcuLi8uLi92YWxpZGF0b3JzL3N2Zy12YWxpZGF0b3JzJztcclxuaW1wb3J0IHsgU2ltcGxlVHJlZUNvbXBvbmVudCB9IGZyb20gJy4uL3NpbXBsZS10cmVlL3NpbXBsZS10cmVlLmNvbXBvbmVudCc7XHJcblxyXG4vKipcclxuICog8J+UkSBgZ3ZlLWNoYWluLW9wZXJhdGlvbi1lZGl0b3JgXHJcbiAqXHJcbiAqIEEgY29tcG9uZW50IGZvciBlZGl0aW5nIGEgdmFyaWFudCBnZW5lcmF0aW9uIG9wZXJhdGlvbi5cclxuICogVXNlZCBieSB0aGUgYGd2ZS1zbmFwc2hvdC1lZGl0b3JgIGNvbXBvbmVudC5cclxuICogLSDilrbvuI8gYG9wZXJhdGlvbmAgKGBDaGFyQ2hhaW5PcGVyYXRpb25gKTogdGhlIG9wZXJhdGlvbiB0byBlZGl0LlxyXG4gKiAtIOKWtu+4jyBgc25hcHNob3RgIChgU25hcHNob3RCYXNlYCk6IHRoZSBzbmFwc2hvdCB0aGUgb3BlcmF0aW9uIHJlZmVycyB0by5cclxuICogLSDilrbvuI8gYGhpZGVQcmV2aWV3YCAoYGJvb2xlYW5gKTogd2hldGhlciB0byBoaWRlIHRoZSBwcmV2aWV3IHJlcXVlc3QgYnV0dG9uLlxyXG4gKiAtIPCflKUgYG9wZXJhdGlvbkNoYW5nZWAgKGBDaGFyQ2hhaW5PcGVyYXRpb25gKTogZW1pdHRlZCB3aGVuIHRoZSBvcGVyYXRpb25cclxuICogaXMgY2hhbmdlZC5cclxuICogLSDwn5SlIGBvcGVyYXRpb25QcmV2aWV3YCAoYENoYXJDaGFpbk9wZXJhdGlvbmApOiBlbWl0dGVkIHdoZW4gdGhlIG9wZXJhdGlvblxyXG4gKiBwcmV2aWV3IGlzIHJlcXVlc3RlZC5cclxuICogLSDwn5SlIGBvcGVyYXRpb25DYW5jZWxgIChgdm9pZGApOiBlbWl0dGVkIHdoZW4gb3BlcmF0aW9uIGVkaXRpbmcgaXMgY2FuY2VsbGVkLlxyXG4gKlxyXG4gKiBUaGUgZWRpdG9yIGlzIGNvbXBvc2VkIG9mIG1hbnkgc2VjdGlvbnM6XHJcbiAqIC0gKipnZW5lcmFsKio6XHJcbiAqICAtIElEOiBlYWNoIG9wZXJhdGlvbiBoYXMgYW4gSUQsIGF1dG9tYXRpY2FsbHkgYXNzaWduZWQuIFRoaXMgaXMgbm90IHVzZWQgaW5cclxuICogdGhlIGNvbnRleHQgb2YgdGhlIG9wZXJhdGlvbiBvciBvZiBpdHMgdHJhbnNmb3JtYXRpb25zLCBidXQgaXMgcHJvdmlkZWQgYXMgYVxyXG4gKiByZWZlcmVuY2UuXHJcbiAqICAtIGF0IGFuZCBydW46IGNvb3JkaW5hdGVzIGZvciB0aGUgc2VsZWN0aW9uIG9mIHRoZSBiYXNlIHRleHQgdGFyZ2V0ZWQgYnlcclxuICogdGhpcyBvcGVyYXRpb24uIENoZWNrIGBpZHhgIHdoZW4gYGF0YCBpcyBpbmRleC1iYXNlZCByYXRoZXIgdGhhbiBJRC1iYXNlZC5cclxuICogIC0gdG8gYW5kIHRvLXJ1bjogYSBzZWNvbmQgY29vcmRpbmF0ZSwgdXNlZCBieSBzb21lIG9wZXJhdGlvbnMuXHJcbiAqICAtIHZhbHVlOiB0aGUgdGV4dCB2YWx1ZSBhcmd1bWVudCwgZm9yIHRob3NlIG9wZXJhdGlvbnMgcmVxdWlyaW5nIGl0LlxyXG4gKiAgLSByYW5rIGFuZCBncm91cCBJRC5cclxuICogIC0gaW5wdXQgYW5kIG91dHB1dCB0YWdzLlxyXG4gKiAgLSBmZWF0dXJlcy4gVGhlc2UgYXJlIG1ldGFkYXRhIGF0dGFjaGVkIHRvIHRoaXMgb3BlcmF0aW9uLCBhbmQgY2FuIGJlIGFueVxyXG4gKiB0eXBlIG9mIG5hbWU9dmFsdWUgcGFpcnMuXHJcbiAqIC0gKipzb3VyY2VzKio6IHNvdXJjZXMgYXJlIGEgc3BlY2lhbCB0eXBlIG9mIG1ldGFkYXRhIHVzZWQgd2hlbiB5b3VyIHRleHRcclxuICogdmVyc2lvbnMgY29tZSBmcm9tIG1vcmUgdGhhbiBhIHNpbmdsZSBzb3VyY2UuIEluIHRoaXMgY2FzZSwgeW91IGNhbiBzcGVjaWZ5XHJcbiAqIHRoZSBzb3VyY2UocykgZm9yIGVhY2ggb3BlcmF0aW9uLCBqdXN0IGxpa2UgaW4gYSB0cmFkaXRpb25hbCBhcHBhcmF0dXMgeW91XHJcbiAqIHNwZWNpZnkgd2l0bmVzc2VzIGZvciBlYWNoIHZhcmlhbnQuIEVhY2ggc291cmNlIGhhcyBhbiBJRCwgYSB0eXBlLCBhXHJcbiAqIHByb2JhYmlsaXR5IHJhbmsgKDA9bm90IHNwZWNpZmllZCwgZWxzZSAxLU4pLCBhbmQgYW4gb3B0aW9uYWwgZnJlZSB0ZXh0IG5vdGUuXHJcbiAqIC0gKipkaXBsb21hdGljKio6IFNWRyBgZ2AgY29kZS4gVGhlIGRpcGxvbWF0aWMgc2VjdGlvbiBpcyB0aGUgYXBwcm94aW1hdGVcclxuICogZGlwbG9tYXRpYyByZXByZXNlbnRhdGlvbiBvZiB0aGUgbGF5b3V0IG9mIHRoZSBhbm5vdGF0ZWQgdGV4dC4gSXQgZXNzZW50aWFsbHlcclxuICogY29uc2lzdHMgaW4gYSBmcmVlbHkgZWRpdGFibGUgU1ZHIGNvZGUsIGFsd2F5cyBncm91cGVkIGludG8gYSBzaW5nbGUgcm9vdCBgZ2BcclxuICogZWxlbWVudCwgZW5jb2RpbmcgYWxsIHRoZSBncmFwaGljYWwgdHJhaXRzIHJlcHJlc2VudGluZyB0aGlzIG9wZXJhdGlvbi5cclxuICogVGhlIHZpc3VhbCBwYXJ0IG9mIGVhY2ggb3BlcmF0aW9uIGNhbiBiZSBwbGFjZWQgZXZlcnl3aGVyZSBvbiB0aGUgc25hcHNob3QsXHJcbiAqIGFzIHNwZWNpZmllZCBieSBpdHMgY29vcmRpbmF0ZXMuXHJcbiAqIC0gKiplbGVtZW50cyoqOiBmZWF0dXJlcyBvZiBhbnkgb2YgdGhlIFNWRyBjb2RlIGVsZW1lbnRzIGhhdmluZyBhbiBJRC5cclxuICogVGhlIGVsZW1lbnRzIHNlY3Rpb24gbGlzdHMgYWxsIHRoZSBTVkcgZWxlbWVudHMgaGF2aW5nIGFuIGBpZGAgYXR0cmlidXRlIGluXHJcbiAqIHRoZSBTVkcgY29kZSBvZiB0aGUgZGlwbG9tYXRpYyBzZWN0aW9uLiBUaGUgSUQgYWxsb3dzIHlvdSB0byBhdHRhY2hcclxuICogYW55IG51bWJlciBvZiBmZWF0dXJlcyAobWV0YWRhdGEgbW9kZWxlZCBhcyBuYW1lPXZhbHVlIHBhaXJzKSB0byBlYWNoIG9mXHJcbiAqIHRoZXNlIGVsZW1lbnRzLiBBbW9uZyB0aGVzZSBmZWF0dXJlcywgeW91IG1heSB1c2UgYHN0eWxlYCBvciBgY2xhc3NgIGZvclxyXG4gKiByZW5kaXRpb25hbCBwdXJwb3NlcywgYW5kIGFueSBvdGhlciBuYW1lIGZvciB5b3VyIG93biBtZXRhZGF0YS4gTm90ZSB0aGF0XHJcbiAqIGVsZW1lbnQgSURzIHdpbGwgYmUgcmVxdWlyZWQgYWxzbyB3aGVuIGRlYWxpbmcgd2l0aCBhbmltYXRpb25zLiBTbywgZW5zdXJlXHJcbiAqIHRvIGFzc2lnbiBhbiBJRCB0byBlYWNoIGVsZW1lbnQgeW91IHdhbnQgdG8gYW5pbWF0ZS5cclxuICogLSAqKmRwIGZlYXRzKio6IGRpcGxvbWF0aWMgZmVhdHVyZXM6IHRoZXNlIGFyZSBmZWF0dXJlcyAobWV0YWRhdGEgbW9kZWxlZFxyXG4gKiBhcyBuYW1lPXZhbHVlIHBhaXJzKSBmb3IgdGhlIGRpcGxvbWF0aWMgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvcGVyYXRpb25cclxuICogYXMgYSB3aG9sZS5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZ3ZlLWNoYWluLW9wZXJhdGlvbi1lZGl0b3InLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW1xyXG4gICAgQ29tbW9uTW9kdWxlLFxyXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcclxuICAgIC8vIG1hdGVyaWFsXHJcbiAgICBDbGlwYm9hcmRNb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Nb2R1bGUsXHJcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcclxuICAgIE1hdEV4cGFuc2lvbk1vZHVsZSxcclxuICAgIE1hdEZvcm1GaWVsZE1vZHVsZSxcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRJbnB1dE1vZHVsZSxcclxuICAgIE1hdFNlbGVjdE1vZHVsZSxcclxuICAgIE1hdFRhYnNNb2R1bGUsXHJcbiAgICBNYXRUb29sdGlwTW9kdWxlLFxyXG4gICAgLy8gbW9uYWNvXHJcbiAgICBOZ2VNb25hY29Nb2R1bGUsXHJcbiAgICBOZ1Rvb2xzTW9kdWxlLFxyXG4gICAgTmdNYXRUb29sc01vZHVsZSxcclxuICAgIC8vIG15cm1leFxyXG4gICAgRmVhdHVyZVNldEVkaXRvckNvbXBvbmVudCxcclxuICAgIFNpbXBsZVRyZWVDb21wb25lbnQsXHJcbiAgICBPcGVyYXRpb25Tb3VyY2VFZGl0b3JDb21wb25lbnQsXHJcbiAgXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vY2hhaW4tb3BlcmF0aW9uLWVkaXRvci5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL2NoYWluLW9wZXJhdGlvbi1lZGl0b3IuY29tcG9uZW50LmNzcycsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDaGFpbk9wZXJhdGlvbkVkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICAvLyBtb25hY29cclxuICBwcml2YXRlIHJlYWRvbmx5IF9kaXNwb3NhYmxlczogbW9uYWNvLklEaXNwb3NhYmxlW10gPSBbXTtcclxuICBwcml2YXRlIF9lZGl0b3JNb2RlbD86IG1vbmFjby5lZGl0b3IuSVRleHRNb2RlbDtcclxuICBwcml2YXRlIF9lZGl0b3I/OiBtb25hY28uZWRpdG9yLklTdGFuZGFsb25lQ29kZUVkaXRvcjtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSBfc3ViczogU3Vic2NyaXB0aW9uW107XHJcbiAgcHJpdmF0ZSByZWFkb25seSBfbmFub2lkID0gY3VzdG9tQWxwaGFiZXQoJzEyMzQ1Njc4OTBhYmNkZWYnLCAxMCk7XHJcblxyXG4gIHByaXZhdGUgX29wZXJhdGlvbjogQ2hhckNoYWluT3BlcmF0aW9uIHwgdW5kZWZpbmVkO1xyXG4gIHByaXZhdGUgX2VkaXRlZFNvdXJjZUluZGV4ID0gLTE7XHJcbiAgcHJpdmF0ZSBfc25hcHNob3Q6IFNuYXBzaG90QmFzZSB8IHVuZGVmaW5lZDtcclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIG9wZXJhdGlvbiB0byBlZGl0LlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGdldCBvcGVyYXRpb24oKTogQ2hhckNoYWluT3BlcmF0aW9uIHwgdW5kZWZpbmVkIHwgbnVsbCB7XHJcbiAgICByZXR1cm4gdGhpcy5fb3BlcmF0aW9uIHx8IHVuZGVmaW5lZDtcclxuICB9XHJcbiAgcHVibGljIHNldCBvcGVyYXRpb24odmFsdWU6IENoYXJDaGFpbk9wZXJhdGlvbiB8IHVuZGVmaW5lZCkge1xyXG4gICAgaWYgKHRoaXMuX29wZXJhdGlvbiA9PT0gdmFsdWUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fb3BlcmF0aW9uID0gdmFsdWU7XHJcbiAgICB0aGlzLnVwZGF0ZUZvcm0odmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIHNuYXBzaG90IHRoZSBvcGVyYXRpb24gcmVmZXJzIHRvLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGdldCBzbmFwc2hvdCgpOiBTbmFwc2hvdEJhc2UgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMuX3NuYXBzaG90O1xyXG4gIH1cclxuICBwdWJsaWMgc2V0IHNuYXBzaG90KHZhbHVlOiBTbmFwc2hvdEJhc2UgfCB1bmRlZmluZWQgfCBudWxsKSB7XHJcbiAgICBpZiAodGhpcy5fc25hcHNob3QgPT09IHZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGNvbnN0IGRpcnR5ID0gdGhpcy5oYXNUZXh0Q2hhbmdlcyh2YWx1ZSB8fCB1bmRlZmluZWQpO1xyXG4gICAgdGhpcy5fc25hcHNob3QgPSB2YWx1ZSB8fCB1bmRlZmluZWQ7XHJcbiAgICBpZiAoZGlydHkpIHtcclxuICAgICAgdGhpcy5yZXF1ZXN0UHJldmlldygpO1xyXG4gICAgICB0aGlzLl9lZGl0b3JNb2RlbD8uc2V0VmFsdWUodGhpcy5zdmcudmFsdWUgfHwgJycpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogV2hldGhlciB0byBoaWRlIHRoZSBwcmV2aWV3IHJlcXVlc3QgYnV0dG9uLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIGhpZGVQcmV2aWV3PzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBvcGVyYXRpb24gaXMgY2hhbmdlZC5cclxuICAgKi9cclxuICBAT3V0cHV0KClcclxuICBwdWJsaWMgcmVhZG9ubHkgb3BlcmF0aW9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxDaGFyQ2hhaW5PcGVyYXRpb24+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgb3BlcmF0aW9uIHByZXZpZXcgaXMgcmVxdWVzdGVkLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKVxyXG4gIHB1YmxpYyByZWFkb25seSBvcGVyYXRpb25QcmV2aWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGFyQ2hhaW5PcGVyYXRpb24+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEVtaXR0ZWQgd2hlbiBvcGVyYXRpb24gZWRpdGluZyBpcyBjYW5jZWxsZWQuXHJcbiAgICovXHJcbiAgQE91dHB1dCgpXHJcbiAgcHVibGljIHJlYWRvbmx5IG9wZXJhdGlvbkNhbmNlbCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgcHVibGljIHRhYkluZGV4OiBudW1iZXIgPSAwO1xyXG4gIHB1YmxpYyBpZD86IHN0cmluZztcclxuICBwdWJsaWMgaGFzVG8gPSBmYWxzZTtcclxuICBwdWJsaWMgaGFzVG9SdW4gPSBmYWxzZTtcclxuICBwdWJsaWMgaGFzVmFsdWUgPSBmYWxzZTtcclxuXHJcbiAgLy8gZ2VuZXJhbFxyXG4gIHB1YmxpYyByYW5rOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBncm91cElkOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcclxuICBwdWJsaWMgZmVhdHVyZXM6IEZvcm1Db250cm9sPEZlYXR1cmVbXT47XHJcbiAgcHVibGljIHNvdXJjZXM6IEZvcm1Db250cm9sPE9wZXJhdGlvblNvdXJjZVtdPjtcclxuICBwdWJsaWMgdHlwZTogRm9ybUNvbnRyb2w8T3BlcmF0aW9uVHlwZT47XHJcbiAgcHVibGljIGF0OiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyBhdEFzSW5kZXg6IEZvcm1Db250cm9sPGJvb2xlYW4+O1xyXG4gIHB1YmxpYyB0bzogRm9ybUNvbnRyb2w8bnVtYmVyPjtcclxuICBwdWJsaWMgdG9Bc0luZGV4OiBGb3JtQ29udHJvbDxib29sZWFuPjtcclxuICBwdWJsaWMgaW5wdXRUYWc6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBvdXRwdXRUYWc6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xyXG4gIHB1YmxpYyBydW46IEZvcm1Db250cm9sPG51bWJlcj47XHJcbiAgcHVibGljIHRvUnVuOiBGb3JtQ29udHJvbDxudW1iZXI+O1xyXG4gIHB1YmxpYyB2YWx1ZTogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XHJcbiAgLy8gc3ZnXHJcbiAgcHVibGljIHN2ZzogRm9ybUNvbnRyb2w8c3RyaW5nPjtcclxuICAvLyBlbGVtZW50c1xyXG4gIHB1YmxpYyBlbGVtZW50RmVhdHVyZXM6IEZvcm1Db250cm9sPFJlY29yZDxzdHJpbmcsIEZlYXR1cmVbXT4+O1xyXG4gIC8vIGRpcGxvbWF0aWNcclxuICBwdWJsaWMgZHBGZWF0dXJlczogRm9ybUNvbnRyb2w8RmVhdHVyZVtdPjtcclxuICAvLyByb290XHJcbiAgcHVibGljIGZvcm06IEZvcm1Hcm91cDtcclxuXHJcbiAgLy8gZWxlbWVudHMgcGFyc2VkIGZyb20gU1ZHIGFuZCBoYXZpbmcgYW4gaWQgYXR0cmlidXRlO1xyXG4gIC8vIHdlIGNhbiBhdHRhY2ggZmVhdHVyZXMgdG8gZWFjaCBvZiB0aGVzZSBlbGVtZW50c1xyXG4gIHB1YmxpYyBlbGVtZW50czogU1ZHRWxlbWVudFtdO1xyXG4gIHB1YmxpYyBlZGl0ZWRFbGVtZW50SWQ/OiBzdHJpbmc7XHJcblxyXG4gIC8vIHNvdXJjZVxyXG4gIHB1YmxpYyBlZGl0ZWRTb3VyY2U/OiBPcGVyYXRpb25Tb3VyY2U7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyLFxyXG4gICAgcHJpdmF0ZSBfY2xpcGJvYXJkOiBDbGlwYm9hcmQsXHJcbiAgICBwcml2YXRlIF9zZXR0aW5nczogU2V0dGluZ3NTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBfZGlhbG9nU2VydmljZTogRGlhbG9nU2VydmljZVxyXG4gICkge1xyXG4gICAgdGhpcy5fc3VicyA9IFtdO1xyXG4gICAgLy8gZ2VuZXJhbFxyXG4gICAgdGhpcy5yYW5rID0gZm9ybUJ1aWxkZXIuY29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmdyb3VwSWQgPSBmb3JtQnVpbGRlci5jb250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG4gICAgdGhpcy5mZWF0dXJlcyA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8RmVhdHVyZVtdPihbXSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMuc291cmNlcyA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8T3BlcmF0aW9uU291cmNlW10+KFtdLCB7XHJcbiAgICAgIG5vbk51bGxhYmxlOiB0cnVlLFxyXG4gICAgfSk7XHJcbiAgICB0aGlzLnR5cGUgPSBmb3JtQnVpbGRlci5jb250cm9sPE9wZXJhdGlvblR5cGU+KE9wZXJhdGlvblR5cGUucmVwbGFjZSwge1xyXG4gICAgICB2YWxpZGF0b3JzOiBWYWxpZGF0b3JzLnJlcXVpcmVkLFxyXG4gICAgICBub25OdWxsYWJsZTogdHJ1ZSxcclxuICAgIH0pO1xyXG4gICAgdGhpcy5hdCA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8bnVtYmVyPigwLCB7XHJcbiAgICAgIHZhbGlkYXRvcnM6IFZhbGlkYXRvcnMucmVxdWlyZWQsXHJcbiAgICAgIG5vbk51bGxhYmxlOiB0cnVlLFxyXG4gICAgfSk7XHJcbiAgICB0aGlzLmF0QXNJbmRleCA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8Ym9vbGVhbj4oZmFsc2UsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLnRvID0gZm9ybUJ1aWxkZXIuY29udHJvbDxudW1iZXI+KDAsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLnRvQXNJbmRleCA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8Ym9vbGVhbj4oZmFsc2UsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcbiAgICB0aGlzLmlucHV0VGFnID0gZm9ybUJ1aWxkZXIuY29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuICAgIHRoaXMub3V0cHV0VGFnID0gZm9ybUJ1aWxkZXIuY29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuICAgIHRoaXMucnVuID0gZm9ybUJ1aWxkZXIuY29udHJvbDxudW1iZXI+KDAsIHtcclxuICAgICAgdmFsaWRhdG9yczogVmFsaWRhdG9ycy5yZXF1aXJlZCxcclxuICAgICAgbm9uTnVsbGFibGU6IHRydWUsXHJcbiAgICB9KTtcclxuICAgIHRoaXMudG9SdW4gPSBmb3JtQnVpbGRlci5jb250cm9sPG51bWJlcj4oMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcclxuICAgIHRoaXMudmFsdWUgPSBmb3JtQnVpbGRlci5jb250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG5cclxuICAgIC8vIHN2Z1xyXG4gICAgdGhpcy5zdmcgPSBmb3JtQnVpbGRlci5jb250cm9sPHN0cmluZz4oJycsIHtcclxuICAgICAgdmFsaWRhdG9yczogW1N2Z1ZhbGlkYXRvcnMucm9vdEdWYWxpZGF0b3IoKV0sXHJcbiAgICAgIG5vbk51bGxhYmxlOiB0cnVlLFxyXG4gICAgfSk7XHJcbiAgICB0aGlzLmVsZW1lbnRGZWF0dXJlcyA9IGZvcm1CdWlsZGVyLmNvbnRyb2w8UmVjb3JkPHN0cmluZywgRmVhdHVyZVtdPj4oXHJcbiAgICAgIHt9LFxyXG4gICAgICB7IG5vbk51bGxhYmxlOiB0cnVlIH1cclxuICAgICk7XHJcbiAgICB0aGlzLmRwRmVhdHVyZXMgPSBmb3JtQnVpbGRlci5jb250cm9sPEZlYXR1cmVbXT4oW10sIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XHJcblxyXG4gICAgdGhpcy5mb3JtID0gZm9ybUJ1aWxkZXIuZ3JvdXAoe1xyXG4gICAgICByYW5rOiB0aGlzLnJhbmssXHJcbiAgICAgIGdyb3VwSWQ6IHRoaXMuZ3JvdXBJZCxcclxuICAgICAgZmVhdHVyZXM6IHRoaXMuZmVhdHVyZXMsXHJcbiAgICAgIHNvdXJjZXM6IHRoaXMuc291cmNlcyxcclxuICAgICAgdHlwZTogdGhpcy50eXBlLFxyXG4gICAgICBhdDogdGhpcy5hdCxcclxuICAgICAgYXRBc0luZGV4OiB0aGlzLmF0QXNJbmRleCxcclxuICAgICAgdG86IHRoaXMudG8sXHJcbiAgICAgIHRvQXNJbmRleDogdGhpcy50b0FzSW5kZXgsXHJcbiAgICAgIGlucHV0VGFnOiB0aGlzLmlucHV0VGFnLFxyXG4gICAgICBvdXRwdXRUYWc6IHRoaXMub3V0cHV0VGFnLFxyXG4gICAgICBydW46IHRoaXMucnVuLFxyXG4gICAgICB0b1J1bjogdGhpcy50b1J1bixcclxuICAgICAgdmFsdWU6IHRoaXMudmFsdWUsXHJcbiAgICAgIHN2ZzogdGhpcy5zdmcsXHJcbiAgICAgIGVsZW1lbnRGZWF0dXJlczogdGhpcy5lbGVtZW50RmVhdHVyZXMsXHJcbiAgICAgIGRwRmVhdHVyZXM6IHRoaXMuZHBGZWF0dXJlcyxcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFNWRyBlbGVtZW50c1xyXG4gICAgdGhpcy5lbGVtZW50cyA9IFtdO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgLy8gd2hlbmV2ZXIgc3ZnIG9yIGJhc2UgY2hhbmdlLCB1cGRhdGUgcHJldmlld1xyXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxyXG4gICAgICB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzXHJcbiAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICBmaWx0ZXIoKGNoYW5nZXMpID0+ICdzdmcnIGluIGNoYW5nZXMgfHwgJ3NuYXBzaG90JyBpbiBjaGFuZ2VzKSxcclxuICAgICAgICAgIGRlYm91bmNlVGltZSg1MDApXHJcbiAgICAgICAgKVxyXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5yZXF1ZXN0UHJldmlldygpO1xyXG4gICAgICAgIH0pXHJcbiAgICApO1xyXG5cclxuICAgIC8vIHdoZW5ldmVyIHR5cGUgY2hhbmdlcywgdXBkYXRlIGFyZ3MgVUlcclxuICAgIHRoaXMuX3N1YnMucHVzaChcclxuICAgICAgdGhpcy50eXBlLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy51cGRhdGVBcmdzVUkoKSlcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLl9kaXNwb3NhYmxlcy5mb3JFYWNoKChkKSA9PiBkLmRpc3Bvc2UoKSk7XHJcbiAgICBmb3IgKGNvbnN0IHN1YiBvZiB0aGlzLl9zdWJzKSB7XHJcbiAgICAgIHN1Yi51bnN1YnNjcmliZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYXNUZXh0Q2hhbmdlcyhzbmFwc2hvdD86IFNuYXBzaG90QmFzZSk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCghc25hcHNob3QgJiYgdGhpcy5fc25hcHNob3QpIHx8IChzbmFwc2hvdCAmJiAhdGhpcy5fc25hcHNob3QpKSB7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG4gICAgaWYgKFxyXG4gICAgICBzbmFwc2hvdD8uc2l6ZT8ud2lkdGggIT09IHRoaXMuX3NuYXBzaG90Py5zaXplPy53aWR0aCB8fFxyXG4gICAgICBzbmFwc2hvdD8uc2l6ZT8uaGVpZ2h0ICE9PSB0aGlzLl9zbmFwc2hvdD8uc2l6ZT8uaGVpZ2h0XHJcbiAgICApIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICBpZiAoXHJcbiAgICAgIHNuYXBzaG90Py5zdHlsZSAhPT0gdGhpcy5fc25hcHNob3Q/LnN0eWxlIHx8XHJcbiAgICAgIHNuYXBzaG90Py50ZXh0ICE9PSB0aGlzLl9zbmFwc2hvdD8udGV4dCB8fFxyXG4gICAgICBzbmFwc2hvdD8udGV4dFN0eWxlICE9PSB0aGlzLl9zbmFwc2hvdD8udGV4dFN0eWxlXHJcbiAgICApIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgICAvLyBjb21wYXJlIHRleHRPcHRpb25zIHJldHVybmluZyB0cnVlIGlmIGFueSBkaWZmZXJlbnRcclxuICAgIGNvbnN0IG9wdGlvbnMgPSBzbmFwc2hvdD8udGV4dE9wdGlvbnM7XHJcbiAgICBpZiAoXHJcbiAgICAgIG9wdGlvbnM/LmxpbmVIZWlnaHRPZmZzZXQgIT09XHJcbiAgICAgICAgdGhpcy5fc25hcHNob3Q/LnRleHRPcHRpb25zPy5saW5lSGVpZ2h0T2Zmc2V0IHx8XHJcbiAgICAgIG9wdGlvbnM/LmNoYXJTcGFjaW5nT2Zmc2V0ICE9PVxyXG4gICAgICAgIHRoaXMuX3NuYXBzaG90Py50ZXh0T3B0aW9ucz8uY2hhclNwYWNpbmdPZmZzZXQgfHxcclxuICAgICAgb3B0aW9ucz8uc3BjV2lkdGhPZmZzZXQgIT09IHRoaXMuX3NuYXBzaG90Py50ZXh0T3B0aW9ucz8uc3BjV2lkdGhPZmZzZXRcclxuICAgICkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvbkNyZWF0ZUVkaXRvcihlZGl0b3I6IG1vbmFjby5lZGl0b3IuSUVkaXRvcikge1xyXG4gICAgY29uc29sZS5sb2coJ2NyZWF0aW5nIGVkaXRvcicpO1xyXG4gICAgZWRpdG9yLnVwZGF0ZU9wdGlvbnMoe1xyXG4gICAgICBtaW5pbWFwOiB7XHJcbiAgICAgICAgc2lkZTogJ3JpZ2h0JyxcclxuICAgICAgfSxcclxuICAgICAgd29yZFdyYXA6ICdvbicsXHJcbiAgICAgIGF1dG9tYXRpY0xheW91dDogdHJ1ZSxcclxuICAgIH0pO1xyXG4gICAgdGhpcy5fZWRpdG9yTW9kZWwgPVxyXG4gICAgICB0aGlzLl9lZGl0b3JNb2RlbCB8fCBtb25hY28uZWRpdG9yLmNyZWF0ZU1vZGVsKHRoaXMuc3ZnLnZhbHVlLCAneG1sJyk7XHJcbiAgICBlZGl0b3Iuc2V0TW9kZWwodGhpcy5fZWRpdG9yTW9kZWwpO1xyXG4gICAgdGhpcy5fZWRpdG9yID0gZWRpdG9yIGFzIG1vbmFjby5lZGl0b3IuSVN0YW5kYWxvbmVDb2RlRWRpdG9yO1xyXG5cclxuICAgIHRoaXMuX2Rpc3Bvc2FibGVzLnB1c2goXHJcbiAgICAgIHRoaXMuX2VkaXRvck1vZGVsLm9uRGlkQ2hhbmdlQ29udGVudCgoZSkgPT4ge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKCdjaGFuZ2UgY29udGVudCcpO1xyXG4gICAgICAgIGNvbnN0IGNvZGUgPSB0aGlzLl9lZGl0b3JNb2RlbCEuZ2V0VmFsdWUoKTtcclxuICAgICAgICBpZiAoY29kZSAhPT0gdGhpcy5zdmcudmFsdWUpIHtcclxuICAgICAgICAgIHRoaXMuc3ZnLnNldFZhbHVlKGNvZGUpO1xyXG4gICAgICAgICAgdGhpcy5zdmcubWFya0FzRGlydHkoKTtcclxuICAgICAgICAgIHRoaXMuc3ZnLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uRmVhdHVyZXNDaGFuZ2UoZmVhdHVyZXM6IE9wZXJhdGlvbkZlYXR1cmVbXSk6IHZvaWQge1xyXG4gICAgdGhpcy5mZWF0dXJlcy5zZXRWYWx1ZShmZWF0dXJlcyk7XHJcbiAgICB0aGlzLmZlYXR1cmVzLm1hcmtBc0RpcnR5KCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25EcEZlYXR1cmVzQ2hhbmdlKGZlYXR1cmVzOiBGZWF0dXJlW10pOiB2b2lkIHtcclxuICAgIHRoaXMuZHBGZWF0dXJlcy5zZXRWYWx1ZShmZWF0dXJlcyk7XHJcbiAgICB0aGlzLmRwRmVhdHVyZXMubWFya0FzRGlydHkoKTtcclxuICB9XHJcblxyXG4gIC8vICNyZWdpb24gc291cmNlc1xyXG4gIHB1YmxpYyBhZGRTb3VyY2UoKTogdm9pZCB7XHJcbiAgICB0aGlzLmVkaXRlZFNvdXJjZSA9IHsgaWQ6ICcnLCB0eXBlOiAnJyB9O1xyXG4gICAgdGhpcy5fZWRpdGVkU291cmNlSW5kZXggPSAtMTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBlZGl0U291cmNlKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMuX2VkaXRlZFNvdXJjZUluZGV4ID0gaW5kZXg7XHJcbiAgICB0aGlzLmVkaXRlZFNvdXJjZSA9IHRoaXMuc291cmNlcy52YWx1ZVtpbmRleF07XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgY2xvc2VTb3VyY2UoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9lZGl0ZWRTb3VyY2VJbmRleCA9IC0xO1xyXG4gICAgdGhpcy5lZGl0ZWRTb3VyY2UgPSB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25Tb3VyY2VDaGFuZ2Uoc291cmNlOiBPcGVyYXRpb25Tb3VyY2UpOiB2b2lkIHtcclxuICAgIGNvbnN0IHNvdXJjZXMgPSBbLi4udGhpcy5zb3VyY2VzLnZhbHVlXTtcclxuICAgIGlmICh0aGlzLl9lZGl0ZWRTb3VyY2VJbmRleCA9PT0gLTEpIHtcclxuICAgICAgc291cmNlcy5wdXNoKHNvdXJjZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBzb3VyY2VzW3RoaXMuX2VkaXRlZFNvdXJjZUluZGV4XSA9IHNvdXJjZTtcclxuICAgIH1cclxuICAgIHRoaXMuc291cmNlcy5zZXRWYWx1ZShzb3VyY2VzKTtcclxuICAgIHRoaXMuY2xvc2VTb3VyY2UoKTtcclxuICB9XHJcbiAgLy8gI2VuZHJlZ2lvblxyXG5cclxuICAvLyAjcmVnaW9uIHN2Z1xyXG4gIHB1YmxpYyBzYXZlU3ZnKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLnN2Zy52YWx1ZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW3RoaXMuc3ZnLnZhbHVlXSwgeyB0eXBlOiAnYXBwbGljYXRpb24veG1sJyB9KTtcclxuICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xyXG4gICAgY29uc3QgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcclxuICAgIGEuaHJlZiA9IHVybDtcclxuICAgIC8vIGNyZWF0ZSBmaWxlbmFtZSBmcm9tIGRhdGUgYW5kIHRpbWVcclxuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XHJcbiAgICBjb25zdCBkYXRlID0gbm93LnRvSVNPU3RyaW5nKCkuc3BsaXQoJ1QnKVswXTtcclxuICAgIGNvbnN0IHRpbWUgPSBub3cudG9UaW1lU3RyaW5nKCkuc3BsaXQoJyAnKVswXS5yZXBsYWNlKCc6JywgJy0nKTtcclxuICAgIGEuZG93bmxvYWQgPSBgc3ZnLSR7ZGF0ZX1fJHt0aW1lfS5zdmdgO1xyXG4gICAgYS5jbGljaygpO1xyXG4gICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBvcGVuU3ZnRWRpdG9yKCk6IHZvaWQge1xyXG4gICAgY29uc3QgdXJsID0gdGhpcy5fc2V0dGluZ3MuZ2V0PHN0cmluZz4oXHJcbiAgICAgICdzdmctZWRpdG9yJyxcclxuICAgICAgJ2h0dHBzOi8vZWRpdG9yLm1ldGhvZC5hYy8nXHJcbiAgICAgIC8vICdodHRwczovL2JveHktc3ZnLmNvbS9hcHAnXHJcbiAgICApO1xyXG4gICAgaWYgKHVybCkge1xyXG4gICAgICBpZiAodGhpcy5zdmcudmFsdWUpIHtcclxuICAgICAgICB0aGlzLl9jbGlwYm9hcmQuY29weSh0aGlzLnN2Zy52YWx1ZSk7XHJcbiAgICAgIH1cclxuICAgICAgd2luZG93Lm9wZW4odXJsLCAnX2JsYW5rJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgbG9hZFN2ZygpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcclxuICAgIGlucHV0LnR5cGUgPSAnZmlsZSc7XHJcbiAgICBpbnB1dC5hY2NlcHQgPSAnLnN2Zyc7XHJcbiAgICBpbnB1dC5vbmNoYW5nZSA9ICgpID0+IHtcclxuICAgICAgY29uc3QgZmlsZSA9IGlucHV0LmZpbGVzPy5bMF07XHJcbiAgICAgIGlmIChmaWxlKSB7XHJcbiAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgICAgICByZWFkZXIub25sb2FkID0gKGUpID0+IHtcclxuICAgICAgICAgIHRoaXMuc3ZnLnNldFZhbHVlKGUudGFyZ2V0Py5yZXN1bHQgYXMgc3RyaW5nKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIHJlYWRlci5yZWFkQXNUZXh0KGZpbGUpO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgaW5wdXQuY2xpY2soKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZXRTdmdGcm9tQ2xpcGJvYXJkKCk6IHZvaWQge1xyXG4gICAgbmF2aWdhdG9yLmNsaXBib2FyZC5yZWFkVGV4dCgpLnRoZW4oKHRleHQpID0+IHtcclxuICAgICAgdGhpcy5zdmcuc2V0VmFsdWUodGV4dCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcGFyc2VTdmcoc3ZnPzogc3RyaW5nKTogU1ZHRWxlbWVudFtdIHtcclxuICAgIGlmICghc3ZnKSB7XHJcbiAgICAgIHJldHVybiBbXTtcclxuICAgIH1cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIHBhcnNlIFNWRyBjb2RlIGV4dHJhY3RpbmcgYWxsIHRoZSBTVkcgZWxlbWVudHMgd2l0aCBhbiBpZCBhdHRyaWJ1dGVcclxuICAgICAgY29uc3QgcGFyc2VyID0gbmV3IERPTVBhcnNlcigpO1xyXG4gICAgICBjb25zdCBkb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKHN2ZywgJ2ltYWdlL3N2Zyt4bWwnKTtcclxuICAgICAgY29uc3QgZWxlbWVudHMgPSBBcnJheS5mcm9tKGRvYy5xdWVyeVNlbGVjdG9yQWxsKCdbaWRdJykpO1xyXG5cclxuICAgICAgLy8gZm9yIGVhY2ggZWxlbWVudCwgcmVhZCB4IGFuZCB5IGFuZCBhZGQgYSB0cmFuc2Zvcm0gd2l0aCBhIHRyYW5zbGF0ZVxyXG4gICAgICAvLyBlcXVhbCB0byAteCBhbmQgLXkgc28gdGhhdCB0aGUgZWxlbWVudCBpcyBhdCB0aGUgb3JpZ2luLiBUaGlzIGlzIHVzZWZ1bFxyXG4gICAgICAvLyBzbyB0aGF0IHRoZSBlbGVtZW50IGNhbiBiZSBwcmV2aWV3ZWQgaW4gaXRzIGJveCB3aXRob3V0IHdhc3Rpbmcgc3BhY2VcclxuICAgICAgLy8ganVzdCBiZWNhdXNlIGl0IGhhcHBlbnMgbm90IHRvIGJlIHBsYWNlZCBhdCB0aGUgU1ZHIG9yaWdpblxyXG4gICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcclxuICAgICAgICBjb25zdCB4ID0gcGFyc2VGbG9hdChlbGVtZW50LmdldEF0dHJpYnV0ZSgneCcpIHx8ICcwJyk7XHJcbiAgICAgICAgY29uc3QgeSA9IHBhcnNlRmxvYXQoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3knKSB8fCAnMCcpO1xyXG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCBgdHJhbnNsYXRlKCR7LXh9LCR7LXl9KWApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gZWxlbWVudHMgYXMgU1ZHRWxlbWVudFtdO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICB0aGlzLnN2Zy5zZXRFcnJvcnMoeyBpbnZhbGlkU3ZnOiB0cnVlIH0pO1xyXG4gICAgICByZXR1cm4gW107XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8vICNlbmRyZWdpb25cclxuXHJcbiAgLy8gI3JlZ2lvbiBlbGVtZW50IGZlYXR1cmVzXHJcbiAgcHVibGljIG9uVGFiSW5kZXhDaGFuZ2UoaW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy50YWJJbmRleCA9IGluZGV4O1xyXG4gICAgaWYgKGluZGV4ID09PSAzKSB7XHJcbiAgICAgIHRoaXMuZWxlbWVudHMgPSB0aGlzLnBhcnNlU3ZnKHRoaXMuc3ZnLnZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBlZGl0RWxlbWVudEZlYXR1cmVzKGVsZW1lbnQ6IFNWR0VsZW1lbnQpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlkID0gZWxlbWVudC5pZDtcclxuICAgIGNvbnN0IGZlYXR1cmVzID0gdGhpcy5lbGVtZW50RmVhdHVyZXMudmFsdWVbaWRdIHx8IFtdO1xyXG4gICAgdGhpcy5lbGVtZW50RmVhdHVyZXMuc2V0VmFsdWUoe1xyXG4gICAgICAuLi50aGlzLmVsZW1lbnRGZWF0dXJlcy52YWx1ZSxcclxuICAgICAgW2lkXTogZmVhdHVyZXMsXHJcbiAgICB9KTtcclxuICAgIHRoaXMuZWRpdGVkRWxlbWVudElkID0gaWQ7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZGVsZXRlRWxlbWVudEZlYXR1cmVzKGVsZW1lbnQ6IFNWR0VsZW1lbnQpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlkID0gZWxlbWVudC5pZDtcclxuICAgIGNvbnN0IGVsZW1lbnRGZWF0dXJlcyA9IHsgLi4udGhpcy5lbGVtZW50RmVhdHVyZXMudmFsdWUgfTtcclxuICAgIGlmICghZWxlbWVudEZlYXR1cmVzW2lkXSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5fZGlhbG9nU2VydmljZVxyXG4gICAgICAuY29uZmlybSgnQ29uZmlybScsICdEZWxldGUgZWxlbWVudCBmZWF0dXJlcz8nKVxyXG4gICAgICAuc3Vic2NyaWJlKCh5ZXM6IGJvb2xlYW4pID0+IHtcclxuICAgICAgICBpZiAoeWVzKSB7XHJcbiAgICAgICAgICBkZWxldGUgZWxlbWVudEZlYXR1cmVzW2lkXTtcclxuICAgICAgICAgIHRoaXMuZWxlbWVudEZlYXR1cmVzLnNldFZhbHVlKGVsZW1lbnRGZWF0dXJlcyk7XHJcblxyXG4gICAgICAgICAgaWYgKHRoaXMuZWRpdGVkRWxlbWVudElkID09PSBpZCkge1xyXG4gICAgICAgICAgICB0aGlzLmVkaXRlZEVsZW1lbnRJZCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG9uRWxlbWVudEZlYXR1cmVzQ2hhbmdlKGZlYXR1cmVzOiBGZWF0dXJlW10pOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmVkaXRlZEVsZW1lbnRJZCkge1xyXG4gICAgICB0aGlzLmVsZW1lbnRGZWF0dXJlcy5zZXRWYWx1ZSh7XHJcbiAgICAgICAgLi4udGhpcy5lbGVtZW50RmVhdHVyZXMudmFsdWUsXHJcbiAgICAgICAgW3RoaXMuZWRpdGVkRWxlbWVudElkXTogZmVhdHVyZXMsXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuICAvLyAjZW5kcmVnaW9uXHJcblxyXG4gIHByaXZhdGUgdXBkYXRlQXJnc1VJKCk6IHZvaWQge1xyXG4gICAgbGV0IHRvID0gZmFsc2UsXHJcbiAgICAgIHRvUnVuID0gZmFsc2UsXHJcbiAgICAgIHZhbHVlID0gZmFsc2U7XHJcbiAgICBzd2l0Y2ggKHRoaXMudHlwZS52YWx1ZSkge1xyXG4gICAgICBjYXNlIE9wZXJhdGlvblR5cGUubW92ZUFmdGVyOlxyXG4gICAgICBjYXNlIE9wZXJhdGlvblR5cGUubW92ZUJlZm9yZTpcclxuICAgICAgICB0byA9IHRydWU7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgT3BlcmF0aW9uVHlwZS5zd2FwOlxyXG4gICAgICAgIHRvID0gdHJ1ZTtcclxuICAgICAgICB0b1J1biA9IHRydWU7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgT3BlcmF0aW9uVHlwZS5hZGRBZnRlcjpcclxuICAgICAgY2FzZSBPcGVyYXRpb25UeXBlLmFkZEJlZm9yZTpcclxuICAgICAgY2FzZSBPcGVyYXRpb25UeXBlLnJlcGxhY2U6XHJcbiAgICAgICAgdmFsdWUgPSB0cnVlO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgfVxyXG4gICAgdGhpcy5oYXNUbyA9IHRvO1xyXG4gICAgdGhpcy5oYXNUb1J1biA9IHRvUnVuO1xyXG4gICAgdGhpcy5oYXNWYWx1ZSA9IHZhbHVlO1xyXG5cclxuICAgIGlmICghdG8pIHtcclxuICAgICAgdGhpcy50by5yZXNldCgpO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0b1J1bikge1xyXG4gICAgICB0aGlzLnRvUnVuLnJlc2V0KCk7XHJcbiAgICB9XHJcbiAgICBpZiAoIXZhbHVlKSB7XHJcbiAgICAgIHRoaXMudmFsdWUucmVzZXQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlRm9ybShvcGVyYXRpb24/OiBDaGFyQ2hhaW5PcGVyYXRpb24pOiB2b2lkIHtcclxuICAgIGlmICghb3BlcmF0aW9uKSB7XHJcbiAgICAgIHRoaXMuZm9ybS5yZXNldCgpO1xyXG4gICAgICB0aGlzLnVwZGF0ZUFyZ3NVSSgpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZ2V0IG9yIGdlbmVyYXRlIElEXHJcbiAgICBpZiAob3BlcmF0aW9uLmlkKSB7XHJcbiAgICAgIHRoaXMuaWQgPSBvcGVyYXRpb24uaWQ7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmlkID0gdGhpcy5fbmFub2lkKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5yYW5rLnNldFZhbHVlKG9wZXJhdGlvbi5yYW5rIHx8IDApO1xyXG4gICAgdGhpcy5ncm91cElkLnNldFZhbHVlKG9wZXJhdGlvbi5ncm91cElkIHx8IG51bGwpO1xyXG4gICAgdGhpcy5mZWF0dXJlcy5zZXRWYWx1ZShvcGVyYXRpb24uZmVhdHVyZXMgfHwgW10pO1xyXG4gICAgdGhpcy5zb3VyY2VzLnNldFZhbHVlKG9wZXJhdGlvbi5zb3VyY2VzIHx8IFtdKTtcclxuICAgIHRoaXMuZHBGZWF0dXJlcy5zZXRWYWx1ZShvcGVyYXRpb24uZGlwbG9tYXRpY3M/LmZlYXR1cmVzIHx8IFtdKTtcclxuXHJcbiAgICB0aGlzLnR5cGUuc2V0VmFsdWUob3BlcmF0aW9uLnR5cGUpO1xyXG4gICAgdGhpcy5hdC5zZXRWYWx1ZShvcGVyYXRpb24uYXQpO1xyXG4gICAgdGhpcy5hdEFzSW5kZXguc2V0VmFsdWUob3BlcmF0aW9uLmF0QXNJbmRleCB8fCBmYWxzZSk7XHJcbiAgICB0aGlzLnRvLnNldFZhbHVlKG9wZXJhdGlvbi50byB8fCAwKTtcclxuICAgIHRoaXMudG9Bc0luZGV4LnNldFZhbHVlKG9wZXJhdGlvbi50b0FzSW5kZXggfHwgZmFsc2UpO1xyXG4gICAgdGhpcy5pbnB1dFRhZy5zZXRWYWx1ZShvcGVyYXRpb24uaW5wdXRUYWcgfHwgbnVsbCk7XHJcbiAgICB0aGlzLm91dHB1dFRhZy5zZXRWYWx1ZShvcGVyYXRpb24ub3V0cHV0VGFnIHx8IG51bGwpO1xyXG4gICAgdGhpcy5ydW4uc2V0VmFsdWUob3BlcmF0aW9uLnJ1bik7XHJcbiAgICB0aGlzLnRvUnVuLnNldFZhbHVlKG9wZXJhdGlvbi50b1J1biB8fCAwKTtcclxuICAgIHRoaXMudmFsdWUuc2V0VmFsdWUob3BlcmF0aW9uLnZhbHVlIHx8IG51bGwpO1xyXG5cclxuICAgIHRoaXMuc3ZnLnNldFZhbHVlKG9wZXJhdGlvbi5kaXBsb21hdGljcz8uZyB8fCAnJyk7XHJcbiAgICB0aGlzLl9lZGl0b3JNb2RlbD8uc2V0VmFsdWUodGhpcy5zdmcudmFsdWUgfHwgJycpO1xyXG4gICAgdGhpcy5lbGVtZW50RmVhdHVyZXMuc2V0VmFsdWUob3BlcmF0aW9uLmRpcGxvbWF0aWNzPy5lbGVtZW50RmVhdHVyZXMgfHwge30pO1xyXG5cclxuICAgIHRoaXMuZm9ybS5tYXJrQXNQcmlzdGluZSgpO1xyXG5cclxuICAgIHRoaXMuZWxlbWVudHMgPSB0aGlzLnBhcnNlU3ZnKG9wZXJhdGlvbi5kaXBsb21hdGljcz8uZyk7XHJcblxyXG4gICAgdGhpcy51cGRhdGVBcmdzVUkoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBjYW5jZWwoKTogdm9pZCB7XHJcbiAgICB0aGlzLm9wZXJhdGlvbkNhbmNlbC5lbWl0KCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdldE9wZXJhdGlvbigpOiBDaGFyQ2hhaW5PcGVyYXRpb24ge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgcmFuazogdGhpcy5yYW5rLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgZ3JvdXBJZDogdGhpcy5ncm91cElkLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgZmVhdHVyZXM6IHRoaXMuZmVhdHVyZXMudmFsdWU/Lmxlbmd0aCA/IHRoaXMuZmVhdHVyZXMudmFsdWUgOiB1bmRlZmluZWQsXHJcbiAgICAgIHNvdXJjZXM6IHRoaXMuc291cmNlcy52YWx1ZT8ubGVuZ3RoID8gdGhpcy5zb3VyY2VzLnZhbHVlIDogdW5kZWZpbmVkLFxyXG4gICAgICBkaXBsb21hdGljczoge1xyXG4gICAgICAgIGc6IHRoaXMuc3ZnLnZhbHVlLFxyXG4gICAgICAgIGZlYXR1cmVzOiB0aGlzLmRwRmVhdHVyZXMudmFsdWUsXHJcbiAgICAgICAgZWxlbWVudEZlYXR1cmVzOiB0aGlzLmVsZW1lbnRGZWF0dXJlcy52YWx1ZSxcclxuICAgICAgfSxcclxuICAgICAgaWQ6IHRoaXMuaWQhLFxyXG4gICAgICB0eXBlOiB0aGlzLnR5cGUudmFsdWUsXHJcbiAgICAgIGF0OiB0aGlzLmF0LnZhbHVlLFxyXG4gICAgICBhdEFzSW5kZXg6IHRoaXMuYXRBc0luZGV4LnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgdG86IHRoaXMudG8udmFsdWUgfHwgdW5kZWZpbmVkLFxyXG4gICAgICB0b0FzSW5kZXg6IHRoaXMudG9Bc0luZGV4LnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgaW5wdXRUYWc6IHRoaXMuaW5wdXRUYWcudmFsdWUgfHwgdW5kZWZpbmVkLFxyXG4gICAgICBvdXRwdXRUYWc6IHRoaXMub3V0cHV0VGFnLnZhbHVlIHx8IHVuZGVmaW5lZCxcclxuICAgICAgcnVuOiB0aGlzLnJ1bi52YWx1ZSxcclxuICAgICAgdG9SdW46IHRoaXMudG9SdW4udmFsdWUgfHwgdW5kZWZpbmVkLFxyXG4gICAgICB2YWx1ZTogdGhpcy52YWx1ZS52YWx1ZSB8fCB1bmRlZmluZWQsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHJlcXVlc3RQcmV2aWV3KCk6IHZvaWQge1xyXG4gICAgdGhpcy5vcGVyYXRpb25QcmV2aWV3LmVtaXQodGhpcy5nZXRPcGVyYXRpb24oKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgc2F2ZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5mb3JtLnZhbGlkKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLl9vcGVyYXRpb24gPSB0aGlzLmdldE9wZXJhdGlvbigpO1xyXG4gICAgdGhpcy5vcGVyYXRpb25DaGFuZ2UuZW1pdCh0aGlzLl9vcGVyYXRpb24pO1xyXG4gIH1cclxufVxyXG4iLCI8Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1cIiAoc3VibWl0KT1cInNhdmUoKVwiPlxyXG4gIDwhLS0gdGFicyAtLT5cclxuICA8bWF0LXRhYi1ncm91cFxyXG4gICAgW3NlbGVjdGVkSW5kZXhdPVwidGFiSW5kZXhcIlxyXG4gICAgKHNlbGVjdGVkSW5kZXhDaGFuZ2UpPVwib25UYWJJbmRleENoYW5nZSgkZXZlbnQpXCJcclxuICA+XHJcbiAgICA8IS0tIEdFTkVSQUwgLS0+XHJcbiAgICA8bWF0LXRhYiBsYWJlbD1cImdlbmVyYWxcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgICAgPCEtLSBpZCAtLT5cclxuICAgICAgICA8ZGl2IGlkPVwiaWRcIiBjbGFzcz1cIm11dGVkXCI+e3sgaWQgfX08L2Rpdj5cclxuXHJcbiAgICAgICAgPCEtLSB0eXBlIC0tPlxyXG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgIDxtYXQtbGFiZWw+dHlwZTwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPG1hdC1zZWxlY3QgW2Zvcm1Db250cm9sXT1cInR5cGVcIj5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIjBcIj48bWF0LWljb24+bGF5ZXJzPC9tYXQtaWNvbj4gcmVwbGFjZTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIjFcIj48bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPmRlbGV0ZTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIjJcIj48bWF0LWljb24+bGFzdF9wYWdlPC9tYXQtaWNvbj5hZGQtYmVmb3JlPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwiM1wiPjxtYXQtaWNvbj5maXJzdF9wYWdlPC9tYXQtaWNvbj5hZGQtYWZ0ZXI8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCI0XCI+PG1hdC1pY29uPmxvZ2luPC9tYXQtaWNvbj5tb3ZlLWJlZm9yZTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIjVcIj48bWF0LWljb24+bG9nb3V0PC9tYXQtaWNvbj5tb3ZlLWFmdGVyPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwiNlwiPjxtYXQtaWNvbj5jb21wYXJlX2Fycm93czwvbWF0LWljb24+c3dhcDwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIjdcIj48bWF0LWljb24+ZWRpdF9ub3RlPC9tYXQtaWNvbj5hbm5vdGF0ZTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgICAgIDxtYXQtZXJyb3JcclxuICAgICAgICAgICAgKm5nSWY9XCIkYW55KHR5cGUpLmVycm9ycz8ucmVxdWlyZWQgJiYgKHR5cGUuZGlydHkgfHwgdHlwZS50b3VjaGVkKVwiXHJcbiAgICAgICAgICAgID50eXBlIHJlcXVpcmVkPC9tYXQtZXJyb3JcclxuICAgICAgICAgID5cclxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgICAgPCEtLSBhdCAtLT5cclxuICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJuclwiPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5hdDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPGlucHV0IG1hdElucHV0IFtmb3JtQ29udHJvbF09XCJhdFwiIHR5cGU9XCJudW1iZXJcIiBtaW49XCIwXCIgLz5cclxuICAgICAgICAgIDxtYXQtZXJyb3JcclxuICAgICAgICAgICAgKm5nSWY9XCIkYW55KGF0KS5lcnJvcnM/LnJlcXVpcmVkICYmIChhdC5kaXJ0eSB8fCBhdC50b3VjaGVkKVwiXHJcbiAgICAgICAgICAgID5hdCByZXF1aXJlZDwvbWF0LWVycm9yXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgPCEtLSBhdEFzSW5kZXggLS0+XHJcbiAgICAgICAgPG1hdC1jaGVja2JveCBbZm9ybUNvbnRyb2xdPVwiYXRBc0luZGV4XCI+aWR4PC9tYXQtY2hlY2tib3g+XHJcblxyXG4gICAgICAgIDwhLS0gcnVuIC0tPlxyXG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cIm5yXCI+XHJcbiAgICAgICAgICA8bWF0LWxhYmVsPnJ1bjwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPGlucHV0IG1hdElucHV0IFtmb3JtQ29udHJvbF09XCJydW5cIiB0eXBlPVwibnVtYmVyXCIgbWluPVwiMFwiIC8+XHJcbiAgICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAgICpuZ0lmPVwiJGFueShydW4pLmVycm9ycz8ucmVxdWlyZWQgJiYgKHJ1bi5kaXJ0eSB8fCBydW4udG91Y2hlZClcIlxyXG4gICAgICAgICAgICA+cnVuIHJlcXVpcmVkPC9tYXQtZXJyb3JcclxuICAgICAgICAgID5cclxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICA8IS0tIHRvIC0tPlxyXG4gICAgICAgIEBpZiAoaGFzVG8pIHtcclxuICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJuclwiPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD50bzwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPGlucHV0IG1hdElucHV0IFtmb3JtQ29udHJvbF09XCJ0b1wiIHR5cGU9XCJudW1iZXJcIiBtaW49XCIwXCIgLz5cclxuICAgICAgICAgIDxtYXQtZXJyb3JcclxuICAgICAgICAgICAgKm5nSWY9XCIkYW55KHRvKS5lcnJvcnM/LnJlcXVpcmVkICYmICh0by5kaXJ0eSB8fCB0by50b3VjaGVkKVwiXHJcbiAgICAgICAgICAgID50byByZXF1aXJlZDwvbWF0LWVycm9yXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgPCEtLSB0b0FzSW5kZXggLS0+XHJcbiAgICAgICAgPG1hdC1jaGVja2JveCBbZm9ybUNvbnRyb2xdPVwidG9Bc0luZGV4XCI+aWR4PC9tYXQtY2hlY2tib3g+XHJcblxyXG4gICAgICAgIDwhLS0gdG9SdW4gLS0+XHJcbiAgICAgICAgQGlmIChoYXNUb1J1bikge1xyXG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cIm5yXCI+XHJcbiAgICAgICAgICA8bWF0LWxhYmVsPnRvIHJ1bjwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPGlucHV0IG1hdElucHV0IFtmb3JtQ29udHJvbF09XCJ0b1J1blwiIHR5cGU9XCJudW1iZXJcIiBtaW49XCIwXCIgLz5cclxuICAgICAgICAgIDxtYXQtZXJyb3JcclxuICAgICAgICAgICAgKm5nSWY9XCJcclxuICAgICAgICAgICAgICAkYW55KHRvUnVuKS5lcnJvcnM/LnJlcXVpcmVkICYmICh0b1J1bi5kaXJ0eSB8fCB0b1J1bi50b3VjaGVkKVxyXG4gICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICA+dG8gcnVuIHJlcXVpcmVkPC9tYXQtZXJyb3JcclxuICAgICAgICAgID5cclxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgIH0gfVxyXG5cclxuICAgICAgICA8IS0tIHZhbHVlIC0tPlxyXG4gICAgICAgIEBpZiAoaGFzVmFsdWUpIHtcclxuICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8bWF0LWxhYmVsPnZhbHVlPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cInZhbHVlXCIgLz5cclxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxyXG4gICAgICAgIDwhLS0gcmFuayAtLT5cclxuICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJuclwiPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5yYW5rPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cInJhbmtcIiB0eXBlPVwibnVtYmVyXCIgbWluPVwiMFwiIC8+XHJcbiAgICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAgICpuZ0lmPVwiJGFueShyYW5rKS5lcnJvcnM/LnJlcXVpcmVkICYmIChyYW5rLmRpcnR5IHx8IHJhbmsudG91Y2hlZClcIlxyXG4gICAgICAgICAgICA+cmFuayByZXF1aXJlZDwvbWF0LWVycm9yXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgPCEtLSBncm91cElkIC0tPlxyXG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgIDxtYXQtbGFiZWw+Z3JvdXAgSUQ8L21hdC1sYWJlbD5cclxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBbZm9ybUNvbnRyb2xdPVwiZ3JvdXBJZFwiIC8+XHJcbiAgICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgJGFueShncm91cElkKS5lcnJvcnM/LnJlcXVpcmVkICYmXHJcbiAgICAgICAgICAgICAgKGdyb3VwSWQuZGlydHkgfHwgZ3JvdXBJZC50b3VjaGVkKVxyXG4gICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICA+Z3JvdXAgSUQgcmVxdWlyZWQ8L21hdC1lcnJvclxyXG4gICAgICAgICAgPlxyXG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgIDwhLS0gaW5wdXRUYWcgLS0+XHJcbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5pbnB1dCB0YWc8L21hdC1sYWJlbD5cclxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBbZm9ybUNvbnRyb2xdPVwiaW5wdXRUYWdcIiAvPlxyXG4gICAgICAgICAgPG1hdC1oaW50PmJsYW5rPWxhdGVzdDwvbWF0LWhpbnQ+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgPCEtLSBvdXRwdXRUYWcgLS0+XHJcbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5vdXRwdXQgdGFnPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cIm91dHB1dFRhZ1wiIC8+XHJcbiAgICAgICAgICA8bWF0LWhpbnQ+Ymxhbms9YXV0byAodk4pPC9tYXQtaGludD5cclxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdj5cclxuICAgICAgICA8IS0tIGZlYXR1cmVzIC0tPlxyXG4gICAgICAgIDxmaWVsZHNldD5cclxuICAgICAgICAgIDxsZWdlbmQ+b3BlcmF0aW9uIGZlYXR1cmVzPC9sZWdlbmQ+XHJcbiAgICAgICAgICA8Z3ZlLWZlYXR1cmUtc2V0LWVkaXRvclxyXG4gICAgICAgICAgICBbaXNWYXJdPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgIFtmZWF0dXJlc109XCJmZWF0dXJlcy52YWx1ZVwiXHJcbiAgICAgICAgICAgIChmZWF0dXJlc0NoYW5nZSk9XCJvbkZlYXR1cmVzQ2hhbmdlKCRldmVudClcIlxyXG4gICAgICAgICAgPjwvZ3ZlLWZlYXR1cmUtc2V0LWVkaXRvcj5cclxuICAgICAgICA8L2ZpZWxkc2V0PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvbWF0LXRhYj5cclxuXHJcbiAgICA8IS0tIFNPVVJDRVMgLS0+XHJcbiAgICA8bWF0LXRhYiBsYWJlbD1cInNvdXJjZXNcIj5cclxuICAgICAgPGRpdj5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgIG1hdC1mbGF0LWJ1dHRvblxyXG4gICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgIGNsYXNzPVwibWF0LXByaW1hcnlcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cImFkZFNvdXJjZSgpXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8bWF0LWljb24+YWRkX2NpcmNsZTwvbWF0LWljb24+XHJcbiAgICAgICAgICBzb3VyY2VcclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDx0YWJsZT5cclxuICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICA8dHI+XHJcbiAgICAgICAgICAgIDx0aD48L3RoPlxyXG4gICAgICAgICAgICA8dGg+dHlwZTwvdGg+XHJcbiAgICAgICAgICAgIDx0aD5pZDwvdGg+XHJcbiAgICAgICAgICAgIDx0aD5yYW5rPC90aD5cclxuICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgPC90aGVhZD5cclxuICAgICAgICA8dGJvZHk+XHJcbiAgICAgICAgICBAZm9yIChzIG9mIHNvdXJjZXMudmFsdWU7IHRyYWNrIHMpIHtcclxuICAgICAgICAgIDx0cj5cclxuICAgICAgICAgICAgPHRkIGNsYXNzPVwiZml0LXdpZHRoXCI+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiZWRpdFNvdXJjZSgkaW5kZXgpXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXQtcHJpbWFyeVwiPmVkaXQ8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIG1hdC1pY29uLWJ1dHRvbiBjb2xvcj1cIndhcm5cIj5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdC13YXJuXCI+ZGVsZXRlPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkPnt7IHMudHlwZSB9fTwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBzLmlkIH19PC90ZD5cclxuICAgICAgICAgICAgPHRkPnt7IHMucmFuayB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIDwvdGJvZHk+XHJcbiAgICAgIDwvdGFibGU+XHJcbiAgICAgIDwhLS0gc291cmNlIGVkaXRvciAtLT5cclxuICAgICAgPG1hdC1leHBhbnNpb24tcGFuZWwgW2Rpc2FibGVkXT1cIiFlZGl0ZWRTb3VyY2VcIiBbZXhwYW5kZWRdPVwiZWRpdGVkU291cmNlXCI+XHJcbiAgICAgICAgPG1hdC1leHBhbnNpb24tcGFuZWwtaGVhZGVyPlxyXG4gICAgICAgICAgPG1hdC1wYW5lbC10aXRsZT5zb3VyY2U8L21hdC1wYW5lbC10aXRsZT5cclxuICAgICAgICA8L21hdC1leHBhbnNpb24tcGFuZWwtaGVhZGVyPlxyXG4gICAgICAgIDxndmUtb3BlcmF0aW9uLXNvdXJjZS1lZGl0b3JcclxuICAgICAgICAgIFtzb3VyY2VdPVwiZWRpdGVkU291cmNlXCJcclxuICAgICAgICAgIChzb3VyY2VDaGFuZ2UpPVwib25Tb3VyY2VDaGFuZ2UoJGV2ZW50ISlcIlxyXG4gICAgICAgICAgKHNvdXJjZUNhbmNlbCk9XCJjbG9zZVNvdXJjZSgpXCJcclxuICAgICAgICAvPlxyXG4gICAgICA8L21hdC1leHBhbnNpb24tcGFuZWw+XHJcbiAgICA8L21hdC10YWI+XHJcblxyXG4gICAgPCEtLSBESVBMT01BVElDIC0tPlxyXG4gICAgPG1hdC10YWIgbGFiZWw9XCJkaXBsb21hdGljXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJ0b29sYmFyLXJvd1wiPlxyXG4gICAgICAgIDxidXR0b25cclxuICAgICAgICAgIGlkPVwiYnRuLXNhdmVcIlxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgIG1hdFRvb2x0aXA9XCJTYXZlIHRvIGZpbGVcIlxyXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFzdmcudmFsdWVcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cInNhdmVTdmcoKVwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPG1hdC1pY29uPnNhdmU8L21hdC1pY29uPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b25cclxuICAgICAgICAgIGlkPVwiYnRuLWxvYWRcIlxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgIG1hdFRvb2x0aXA9XCJMb2FkIGZyb20gZmlsZVwiXHJcbiAgICAgICAgICAoY2xpY2spPVwibG9hZFN2ZygpXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8bWF0LWljb24+Zm9sZGVyPC9tYXQtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICBpZD1cImJ0bi1jb3B5XCJcclxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICBtYXRUb29sdGlwPVwiQ29weVwiXHJcbiAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cInN2Zy52YWx1ZVwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPG1hdC1pY29uPmNvbnRlbnRfY29weTwvbWF0LWljb24+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgaWQ9XCJidG4tcGFzdGVcIlxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgIG1hdFRvb2x0aXA9XCJTZXQgU1ZHIGZyb20gY2xpcGJvYXJkXCJcclxuICAgICAgICAgIChjbGljayk9XCJzZXRTdmdGcm9tQ2xpcGJvYXJkKClcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X3Bhc3RlX2dvPC9tYXQtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICBpZD1cImJ0bi1lZGl0b3JcIlxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgIG1hdFRvb2x0aXA9XCJPcGVuIFNWRyBleHRlcm5hbCBlZGl0b3JcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cIm9wZW5TdmdFZGl0b3IoKVwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPG1hdC1pY29uPmxhdW5jaDwvbWF0LWljb24+XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPGRpdiBpZD1cImNvZGVcIj5cclxuICAgICAgICA8bmdlLW1vbmFjby1lZGl0b3JcclxuICAgICAgICAgIHN0eWxlPVwiLS1lZGl0b3ItaGVpZ2h0OiA0MDBweFwiXHJcbiAgICAgICAgICAocmVhZHkpPVwib25DcmVhdGVFZGl0b3IoJGV2ZW50KVwiXHJcbiAgICAgICAgLz5cclxuICAgICAgICBAaWYgKHN2Zy5pbnZhbGlkKSB7XHJcbiAgICAgICAgPG1hdC1lcnJvcj5pbnZhbGlkIFNWRzwvbWF0LWVycm9yPlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L21hdC10YWI+XHJcblxyXG4gICAgPCEtLSBFTEVNRU5UUyAtLT5cclxuICAgIDxtYXQtdGFiIGxhYmVsPVwiZWxlbWVudHNcIj5cclxuICAgICAgPHRhYmxlPlxyXG4gICAgICAgIDx0aGVhZD5cclxuICAgICAgICAgIDx0cj5cclxuICAgICAgICAgICAgPHRoPjwvdGg+XHJcbiAgICAgICAgICAgIDx0aD5pZDwvdGg+XHJcbiAgICAgICAgICAgIDx0aD52aXN1YWw8L3RoPlxyXG4gICAgICAgICAgPC90cj5cclxuICAgICAgICA8L3RoZWFkPlxyXG4gICAgICAgIDx0Ym9keT5cclxuICAgICAgICAgIEBmb3IgKGUgb2YgZWxlbWVudHM7IHRyYWNrIGUuaWQpIHtcclxuICAgICAgICAgIDx0cj5cclxuICAgICAgICAgICAgPHRkIGNsYXNzPVwiZml0LXdpZHRoXCI+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiRWRpdCBlbGVtZW50IGZlYXR1cmVzXCJcclxuICAgICAgICAgICAgICAgIChjbGljayk9XCJlZGl0RWxlbWVudEZlYXR1cmVzKGUpXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJtYXQtcHJpbWFyeVwiPmVkaXQ8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cIndhcm5cIlxyXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkRlbGV0ZSBhbGwgZWxlbWVudCBmZWF0dXJlc1wiXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlRWxlbWVudEZlYXR1cmVzKGUpXCJcclxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhJGFueShlbGVtZW50RmVhdHVyZXMudmFsdWVbZS5pZF0pPy5sZW5ndGhcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdC13YXJuXCI+ZGVsZXRlPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICA8c3Bhbj57eyRhbnkoZWxlbWVudEZlYXR1cmVzLnZhbHVlW2UuaWRdKT8ubGVuZ3RoIHx8IDB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkIGNsYXNzPVwiZmVhdC1jb3VudFwiPnt7IGUuaWQgfX08L3RkPlxyXG4gICAgICAgICAgICA8dGQgY2xhc3M9XCJzdmctY2VsbFwiPlxyXG4gICAgICAgICAgICAgIDxzdmcgW2lubmVySFRNTF09XCJlLm91dGVySFRNTCB8IHNhZmVIdG1sIDogJ2h0bWwnXCI+PC9zdmc+XHJcbiAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIDwvdGJvZHk+XHJcbiAgICAgIDwvdGFibGU+XHJcblxyXG4gICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbFxyXG4gICAgICAgIFtkaXNhYmxlZF09XCIhZWRpdGVkRWxlbWVudElkXCJcclxuICAgICAgICBbZXhwYW5kZWRdPVwiZWRpdGVkRWxlbWVudElkXCJcclxuICAgICAgPlxyXG4gICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5lbGVtZW50PC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cclxuICAgICAgICA8Z3ZlLWZlYXR1cmUtc2V0LWVkaXRvclxyXG4gICAgICAgICAgW2ZlYXR1cmVzXT1cImVsZW1lbnRGZWF0dXJlcy52YWx1ZVtlZGl0ZWRFbGVtZW50SWQhXSB8fCBbXVwiXHJcbiAgICAgICAgICAoZmVhdHVyZXNDaGFuZ2UpPVwib25FbGVtZW50RmVhdHVyZXNDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgLz5cclxuICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsPlxyXG4gICAgPC9tYXQtdGFiPlxyXG5cclxuICAgIDwhLS0gRFAgRkVBVFMgLS0+XHJcbiAgICA8bWF0LXRhYiBsYWJlbD1cImQtZmVhdHVyZXNcIj5cclxuICAgICAgPGd2ZS1mZWF0dXJlLXNldC1lZGl0b3JcclxuICAgICAgICBbZmVhdHVyZXNdPVwiZHBGZWF0dXJlcy52YWx1ZVwiXHJcbiAgICAgICAgKGZlYXR1cmVzQ2hhbmdlKT1cIm9uRHBGZWF0dXJlc0NoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgPjwvZ3ZlLWZlYXR1cmUtc2V0LWVkaXRvcj5cclxuICAgIDwvbWF0LXRhYj5cclxuICA8L21hdC10YWItZ3JvdXA+XHJcblxyXG4gIDwhLS0gYnV0dG9ucyAtLT5cclxuICA8ZGl2IGlkPVwic3VibWl0LXJvd1wiPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgY29sb3I9XCJ3YXJuXCJcclxuICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgIG1hdFRvb2x0aXA9XCJEaXNjYXJkIG9wZXJhdGlvblwiXHJcbiAgICAgIChjbGljayk9XCJjYW5jZWwoKVwiXHJcbiAgICA+XHJcbiAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIm1hdC13YXJuXCI+Y2xlYXI8L21hdC1pY29uPlxyXG4gICAgPC9idXR0b24+XHJcbiAgICBAaWYgKCFoaWRlUHJldmlldykge1xyXG4gICAgPGJ1dHRvblxyXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgIG1hdFRvb2x0aXA9XCJQcmV2aWV3IG9wZXJhdGlvblwiXHJcbiAgICAgIChjbGljayk9XCJyZXF1ZXN0UHJldmlldygpXCJcclxuICAgID5cclxuICAgICAgPG1hdC1pY29uIGNsYXNzPVwibWF0LXByaW1hcnlcIj5wcmV2aWV3PC9tYXQtaWNvbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgfVxyXG4gICAgPGJ1dHRvblxyXG4gICAgICB0eXBlPVwic3VibWl0XCJcclxuICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgY2xhc3M9XCJtYXQtcHJpbWFyeVwiXHJcbiAgICAgIG1hdC1mbGF0LWJ1dHRvblxyXG4gICAgICBtYXRUb29sdGlwPVwiU2F2ZSBvcGVyYXRpb25cIlxyXG4gICAgICBbZGlzYWJsZWRdPVwiZm9ybS5pbnZhbGlkIHx8IGZvcm0ucHJpc3RpbmVcIlxyXG4gICAgPlxyXG4gICAgICA8bWF0LWljb24+Y2hlY2tfY2lyY2xlPC9tYXQtaWNvbj5cclxuICAgICAgc2F2ZVxyXG4gICAgPC9idXR0b24+XHJcbiAgPC9kaXY+XHJcbjwvZm9ybT5cclxuIl19