@eqproject/eqp-dynamic-module 2.10.66 → 2.10.67

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 (71) hide show
  1. package/esm2020/lib/components/exported/eqp-dynamic-module/eqp-dynamic-module.component.mjs +33 -16
  2. package/esm2020/lib/components/exported/eqp-dynamic-module-configurator/eqp-dynamic-module-configurator.component.mjs +656 -32
  3. package/esm2020/lib/components/private/action-button-creator/action-button-creator.component.mjs +2 -2
  4. package/esm2020/lib/components/private/add-form-field/add-form-field.component.mjs +809 -15
  5. package/esm2020/lib/components/private/dynamic-module-field-fix/dynamic-module-field.component.mjs +1 -1
  6. package/esm2020/lib/components/private/field-templates/action-button-field-template/action-button-field-template.component.mjs +98 -20
  7. package/esm2020/lib/components/private/field-templates/attachment-field-template/attachment-field-template.component.mjs +132 -69
  8. package/esm2020/lib/components/private/field-templates/boolean-field-template/boolean-field-template.component.mjs +159 -24
  9. package/esm2020/lib/components/private/field-templates/date-field-template/date-field-template.component.mjs +152 -7
  10. package/esm2020/lib/components/private/field-templates/image-field-selector-template/image-field-selector-template.component.mjs +180 -39
  11. package/esm2020/lib/components/private/field-templates/image-field-template/image-field-template.component.mjs +100 -78
  12. package/esm2020/lib/components/private/field-templates/image-with-markers-field-template/image-with-markers-field-template.component.mjs +103 -88
  13. package/esm2020/lib/components/private/field-templates/label-field-template/label-field-template.component.mjs +90 -17
  14. package/esm2020/lib/components/private/field-templates/list-value-field-template/list-value-field-template.component.mjs +217 -54
  15. package/esm2020/lib/components/private/field-templates/numeric-field-template/numeric-field-template.component.mjs +220 -37
  16. package/esm2020/lib/components/private/field-templates/text-field-template/text-field-template.component.mjs +263 -29
  17. package/esm2020/lib/components/private/field-templates/textarea-field-template/textarea-field-template.component.mjs +210 -18
  18. package/esm2020/lib/components/private/form-records/add-form-record/add-form-record.component.mjs +33 -13
  19. package/esm2020/lib/components/private/form-records/list-view-form-record/list-view-form-record.component.mjs +1 -1
  20. package/esm2020/lib/components/private/form-records/list-view-form-record/single-record/single-record.component.mjs +1 -1
  21. package/esm2020/lib/components/private/tmw-image-marker/tmw-image-marker.component.mjs +4 -3
  22. package/esm2020/lib/components/private/trigger-creator/trigger-creator.component.mjs +2 -2
  23. package/esm2020/lib/models/endPointConfiguration.model.mjs +7 -2
  24. package/esm2020/lib/models/fields/actionButton.model.mjs +3 -1
  25. package/esm2020/lib/models/fields/attachmentField.model.mjs +3 -1
  26. package/esm2020/lib/models/fields/booleanField.model.mjs +3 -1
  27. package/esm2020/lib/models/fields/dateField.model.mjs +3 -1
  28. package/esm2020/lib/models/fields/imageField.model.mjs +3 -1
  29. package/esm2020/lib/models/fields/imageSelectorField.model.mjs +3 -1
  30. package/esm2020/lib/models/fields/imageWithMarkersField.model.mjs +3 -1
  31. package/esm2020/lib/models/fields/labelField.model.mjs +3 -1
  32. package/esm2020/lib/models/fields/listValueField.model.mjs +3 -1
  33. package/esm2020/lib/models/fields/numericField.model.mjs +8 -1
  34. package/esm2020/lib/models/fields/textField.model.mjs +3 -1
  35. package/esm2020/lib/models/fields/textareaField.model.mjs +8 -1
  36. package/esm2020/lib/models/form.model.mjs +1 -1
  37. package/fesm2015/eqproject-eqp-dynamic-module.mjs +3533 -528
  38. package/fesm2015/eqproject-eqp-dynamic-module.mjs.map +1 -1
  39. package/fesm2020/eqproject-eqp-dynamic-module.mjs +3452 -540
  40. package/fesm2020/eqproject-eqp-dynamic-module.mjs.map +1 -1
  41. package/lib/components/exported/eqp-dynamic-module/eqp-dynamic-module.component.d.ts +5 -1
  42. package/lib/components/exported/eqp-dynamic-module-configurator/eqp-dynamic-module-configurator.component.d.ts +74 -6
  43. package/lib/components/private/add-form-field/add-form-field.component.d.ts +208 -1
  44. package/lib/components/private/field-templates/action-button-field-template/action-button-field-template.component.d.ts +16 -10
  45. package/lib/components/private/field-templates/attachment-field-template/attachment-field-template.component.d.ts +17 -33
  46. package/lib/components/private/field-templates/boolean-field-template/boolean-field-template.component.d.ts +24 -11
  47. package/lib/components/private/field-templates/date-field-template/date-field-template.component.d.ts +21 -4
  48. package/lib/components/private/field-templates/image-field-selector-template/image-field-selector-template.component.d.ts +20 -16
  49. package/lib/components/private/field-templates/image-field-template/image-field-template.component.d.ts +15 -36
  50. package/lib/components/private/field-templates/image-with-markers-field-template/image-with-markers-field-template.component.d.ts +16 -37
  51. package/lib/components/private/field-templates/label-field-template/label-field-template.component.d.ts +16 -12
  52. package/lib/components/private/field-templates/list-value-field-template/list-value-field-template.component.d.ts +21 -28
  53. package/lib/components/private/field-templates/numeric-field-template/numeric-field-template.component.d.ts +25 -18
  54. package/lib/components/private/field-templates/text-field-template/text-field-template.component.d.ts +38 -10
  55. package/lib/components/private/field-templates/textarea-field-template/textarea-field-template.component.d.ts +26 -12
  56. package/lib/components/private/form-records/add-form-record/add-form-record.component.d.ts +12 -2
  57. package/lib/models/endPointConfiguration.model.d.ts +1 -0
  58. package/lib/models/fields/actionButton.model.d.ts +12 -0
  59. package/lib/models/fields/attachmentField.model.d.ts +31 -3
  60. package/lib/models/fields/booleanField.model.d.ts +15 -0
  61. package/lib/models/fields/dateField.model.d.ts +46 -0
  62. package/lib/models/fields/imageField.model.d.ts +9 -0
  63. package/lib/models/fields/imageSelectorField.model.d.ts +23 -0
  64. package/lib/models/fields/imageWithMarkersField.model.d.ts +9 -0
  65. package/lib/models/fields/labelField.model.d.ts +5 -0
  66. package/lib/models/fields/listValueField.model.d.ts +38 -0
  67. package/lib/models/fields/numericField.model.d.ts +34 -0
  68. package/lib/models/fields/textField.model.d.ts +33 -0
  69. package/lib/models/fields/textareaField.model.d.ts +39 -0
  70. package/lib/models/form.model.d.ts +6 -0
  71. package/package.json +3 -3
@@ -11,53 +11,285 @@ import * as i3 from "@angular/material/icon";
11
11
  import * as i4 from "@angular/forms";
12
12
  import * as i5 from "@angular/common";
13
13
  import * as i6 from "../../../../directives/speech-to-text/speech-to-text.directive";
14
+ // Selettori CSS MDC (Angular Material 15).
15
+ // Container → .mat-mdc-text-field-wrapper: box visuale esterno del campo outlined
16
+ // (escluso .mat-mdc-form-field-subscript-wrapper). Gestisce sfondo, bordo, border-radius esterno.
17
+ // Le regole di Container vengono duplicate anche sui .mdc-notched-outline__* per permettere
18
+ // di sovrascrivere il bordo di focus/hover di Material con la proprietà border-color dell'utente.
19
+ // Input → .mat-mdc-form-field-infix: area interna dove si digita il testo.
20
+ // Indipendente da Container: il suo background non copre il box esterno.
21
+ // Icona → container prefix + suffix (align-self: stretch iniettato strutturalmente).
22
+ // Microfono → stesso container suffix (viene dopo Icona nel loop, sovrascrive per il suffix).
23
+ const ELEMENT_SELECTORS = {
24
+ Container: ' .mat-mdc-text-field-wrapper',
25
+ Input: ' .mat-mdc-form-field-infix',
26
+ Descrizione: ' label.mat-mdc-floating-label',
27
+ Icona: [' .mat-mdc-form-field-icon-prefix', ' .mat-mdc-form-field-icon-suffix'],
28
+ Microfono: ' .mat-mdc-form-field-icon-suffix',
29
+ Errore: ' mat-error',
30
+ };
31
+ const ELEMENTS = Object.keys(ELEMENT_SELECTORS);
32
+ const STATES = ['Normale', 'Mouseover', 'Focused', 'NotValid', 'Readonly'];
33
+ // Stili di default per elemento+stato: emessi prima delle regole utente,
34
+ // che le sovrascrivono per effetto del cascade CSS (stessa specificità #uid, posizione successiva).
35
+ const DEFAULT_FIELD_STYLES = {
36
+ DescrizioneNormale: 'font-size: x-large;',
37
+ // Il wrapper outlined ha overflow:visible, quindi senza border-radius il background
38
+ // non rispetterebbe gli angoli arrotondati del notched-outline (4px default Angular Material).
39
+ ContainerNormale: 'border-radius: 4px;',
40
+ // Rientra il testo dalla sinistra dell'infix (padding-left rimosso dal wrapper con il fix icone).
41
+ InputNormale: 'padding-left: 5px;',
42
+ };
14
43
  export class TextFieldTemplateComponent {
15
- constructor() {
16
- //Variabili per l'input vocale
44
+ constructor(renderer) {
45
+ this.renderer = renderer;
17
46
  this.isStillRecoginze = false;
18
47
  this.source = interval(200);
19
48
  this.formulaObject = {};
20
49
  this.inConfig = false;
50
+ /** Incrementa dall'esterno per forzare il ricalcolo degli stili CSS (es. dal configuratore) */
51
+ this.styleVersion = 0;
52
+ /** Forza visivamente uno stato specifico nell'anteprima del configuratore */
53
+ this.forceState = null;
21
54
  this.recordChange = new EventEmitter();
22
55
  this.InputMaskEnum = TextMaskEnum;
23
56
  this.TextFieldIconPositionEnum = TextFieldIconPositionEnum;
24
57
  this.platform = Capacitor.getPlatform();
58
+ this.styleEl = null;
59
+ this.statusSub = null;
25
60
  }
26
61
  ngOnInit() {
62
+ this.fieldUid = 'tf-' + Math.random().toString(36).slice(2, 10);
27
63
  this.updateField();
28
64
  this.initStyles();
65
+ this.injectTextFieldStyles();
66
+ this.subscribeToFormStatus();
67
+ }
68
+ ngOnChanges(changes) {
69
+ if (changes['styleVersion'] && !changes['styleVersion'].firstChange) {
70
+ this.injectTextFieldStyles();
71
+ this.updateStateClasses();
72
+ }
73
+ if (changes['forceState']) {
74
+ this.updateStateClasses();
75
+ }
76
+ if (changes['record'] != undefined && changes['record'].firstChange == false
77
+ && JSON.stringify(changes['record'].currentValue) != JSON.stringify(changes['record'].previousValue)) {
78
+ this.record = changes['record'].currentValue;
79
+ this.updateField();
80
+ this.updateStateClasses();
81
+ }
82
+ }
83
+ ngOnDestroy() {
84
+ if (this.styleEl?.parentNode) {
85
+ this.styleEl.parentNode.removeChild(this.styleEl);
86
+ }
87
+ this.statusSub?.unsubscribe();
29
88
  }
30
89
  initStyles() {
31
- //Funzione per parsare il campo stylecss dell'oggetto field ed applicarlo all'html
32
90
  if (this.field.FieldstyleCSS != null || this.field.FieldstyleCSS != undefined)
33
91
  this.FieldstyleObj = UtilityHelperService.initStyles(this.field.FieldstyleCSS);
34
92
  if (this.field.LabelstyleCSS != null || this.field.LabelstyleCSS != undefined)
35
93
  this.LabelstyleObj = UtilityHelperService.initStyles(this.field.LabelstyleCSS);
36
94
  }
37
- ngOnChanges(changes) {
38
- // Se viene modificato il valore di "ngModelInput" allora aggiorna l'input
39
- if (changes['record'] != undefined && changes['record'].firstChange == false && JSON.stringify(changes['record'].currentValue) != JSON.stringify(changes['record'].previousValue)) {
40
- this.record = changes['record'].currentValue;
41
- this.updateField();
95
+ /** Rigenera il tag <style> con defaults + regole utente, entrambi scoped per #uid */
96
+ injectTextFieldStyles() {
97
+ if (!this.fieldUid)
98
+ return;
99
+ const css = this.field?.TextFieldStyleCSS ?? {};
100
+ let rules = this.buildCssRules(this.fieldUid, css);
101
+ // In anteprima configuratore la spaziatura inferiore del subscript-wrapper è indesiderata:
102
+ // esiste per il layout del form vero ma nel pannello di configurazione comprime l'anteprima.
103
+ if (this.inConfig) {
104
+ rules += `\n#${this.fieldUid} .mat-mdc-form-field-subscript-wrapper { display: none; }`;
105
+ }
106
+ if (!this.styleEl) {
107
+ this.styleEl = this.renderer.createElement('style');
108
+ this.styleEl.id = 'style-' + this.fieldUid;
109
+ this.renderer.appendChild(document.head, this.styleEl);
42
110
  }
111
+ this.styleEl.textContent = rules;
43
112
  }
44
- getInputType() {
45
- switch (Number(this.field.TextMask)) {
46
- case TextMaskEnum.Email:
47
- return 'email';
48
- case TextMaskEnum.Password:
49
- return 'password';
50
- case TextMaskEnum.Telefono:
51
- return 'tel';
52
- case TextMaskEnum.Url:
53
- return 'url';
54
- default:
55
- return 'text';
113
+ /** Costruisce il selettore CSS per un dato elemento e stato */
114
+ getSelector(uid, _el, state, s, _sub) {
115
+ switch (state) {
116
+ case 'Normale': return `#${uid}${s}`;
117
+ case 'Mouseover': return `#${uid}:hover${s}, #${uid}.eqp-state-hover${s}`;
118
+ case 'Focused': return `#${uid}:focus-within${s}, #${uid}.eqp-state-focused${s}`;
119
+ case 'NotValid': return `#${uid}.eqp-invalid${s}`;
120
+ case 'Readonly': return `#${uid}.eqp-readonly${s}`;
121
+ default: return null;
122
+ }
123
+ }
124
+ /** Propaga gli stili border di Container ai segmenti del bordo MDC (leading/notch/trailing)
125
+ * con logica differenziata per evitare il doppio bordo:
126
+ * - `border` shorthand o `border-width` → il bordo visivo è già sul wrapper → i segmenti
127
+ * vengono soppressi con border-color:transparent.
128
+ * - Solo `border-color` → applicato ai segmenti per sovrascrivere il ring blu/hover di
129
+ * Material (specificità #uid > specificità di classe Material).
130
+ * - `border-radius` e altre proprietà border-* non vengono propagate ai segmenti. */
131
+ applyBorderToOutline(selector, css, lines) {
132
+ if (!css?.trim())
133
+ return;
134
+ const decls = css.split(';').map(d => d.trim()).filter(d => /^border/i.test(d) && d.length > 0);
135
+ if (!decls.length)
136
+ return;
137
+ if (decls.some(d => /^border(?!-(color|radius))/i.test(d))) {
138
+ lines.push(`${selector} { border-color: transparent; }`);
139
+ }
140
+ else {
141
+ const colorDecls = decls.filter(d => /^border-color/i.test(d)).join('; ');
142
+ if (colorDecls.trim())
143
+ lines.push(`${selector} { ${colorDecls}; }`);
144
+ }
145
+ }
146
+ /** Selettore combinato per i tre segmenti del bordo MDC outlined (leading, notch, trailing).
147
+ * Usato per duplicare il CSS di Container sul bordo visuale e permettere l'override del ring. */
148
+ getOutlineSelector(uid, state) {
149
+ const segs = (pref) => [
150
+ `#${uid}${pref} .mdc-notched-outline__leading`,
151
+ `#${uid}${pref} .mdc-notched-outline__notch`,
152
+ `#${uid}${pref} .mdc-notched-outline__trailing`,
153
+ ].join(', ');
154
+ switch (state) {
155
+ case 'Normale': return segs('');
156
+ case 'Mouseover': return `${segs(':hover')}, ${segs('.eqp-state-hover')}`;
157
+ case 'Focused': return `${segs(':focus-within')}, ${segs('.eqp-state-focused')}`;
158
+ case 'NotValid': return segs('.eqp-invalid');
159
+ case 'Readonly': return segs('.eqp-readonly');
160
+ default: return null;
56
161
  }
57
162
  }
58
163
  /**
59
- * Metodo per aggiornare il valore del campo quando questo è rappresentato da una formula.
164
+ * Emette i default prima, i valori utente dopo.
165
+ * Stessa specificità #uid → il valore utente vince per posizione nel cascade.
166
+ * Icona ha due selettori (prefix + suffix): la stessa regola viene emessa per entrambi.
60
167
  */
168
+ buildCssRules(uid, css) {
169
+ const lines = [];
170
+ // Fix strutturale icone — tutto scoped a #uid per non toccare altri componenti:
171
+ //
172
+ // 1. Material applica .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper
173
+ // { padding-right: 0 } ma lascia il padding-left intatto. Quel padding-left residuo
174
+ // crea uno strip colorato a sinistra se Container ha un background. Lo azzeriamo.
175
+ // (mat-mdc-form-field-has-icon-suffix è sempre presente perché il microfono è sempre
176
+ // un matSuffix nel DOM, anche quando [hidden].)
177
+ lines.push(`#${uid} mat-form-field.mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper` +
178
+ ` { padding-left: 0; }`);
179
+ lines.push(`#${uid} mat-form-field.mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper` +
180
+ ` { padding-right: 0; }`);
181
+ //
182
+ // 2. Prefix: Material default è padding: 0 4px 0 0 — quel 4px crea lo strip a sinistra
183
+ // anche senza icona. Lo azzeriamo sempre. Quando l'icona non c'è: display:none.
184
+ // 3. Suffix: quando non c'è né icona destra né microfono attivo: display:none (Material
185
+ // lascia display:flex sul container anche quando il contenuto è [hidden]).
186
+ const tf = this.field;
187
+ const hasPrefix = !!(tf.IconName && tf.IconPosition !== TextFieldIconPositionEnum.Destra);
188
+ const hasSuffix = !!(tf.IconName && tf.IconPosition === TextFieldIconPositionEnum.Destra)
189
+ || !!(tf.Microphone && this.platform === 'web');
190
+ lines.push(`#${uid} .mat-mdc-form-field-icon-prefix { ${hasPrefix
191
+ ? 'align-self: stretch; display: flex; align-items: center; padding: 0;'
192
+ : 'display: none;'} }`);
193
+ lines.push(`#${uid} .mat-mdc-form-field-icon-suffix { ${hasSuffix
194
+ ? 'align-self: stretch; display: flex; align-items: center; padding: 0;'
195
+ : 'display: none;'} }`);
196
+ // Il .mdc-notched-outline (parent dei tre segmenti di bordo MDC) non deve avere mai un
197
+ // bordo proprio: il bordo visivo del campo viene dai segmenti figli o dal wrapper Container.
198
+ lines.push(`#${uid} .mdc-notched-outline { border: 0; }`);
199
+ // Angular Material imposta color direttamente sull'input (specificità 0,3,0), che batte
200
+ // qualsiasi valore ereditato dal wrapper. Con color:inherit forziamo l'ereditarietà
201
+ // (specificità 1,1,1 > 0,3,0), così il color impostato su InputNormale si propaga al testo.
202
+ lines.push(`#${uid} input.mat-mdc-input-element { color: inherit; }`);
203
+ for (const el of ELEMENTS) {
204
+ const sEntry = ELEMENT_SELECTORS[el];
205
+ const selList = Array.isArray(sEntry) ? sEntry : [sEntry];
206
+ for (const state of STATES) {
207
+ const key = el + state;
208
+ const defaultVal = DEFAULT_FIELD_STYLES[key];
209
+ const userVal = css[key];
210
+ if (!defaultVal?.trim() && !userVal?.trim())
211
+ continue;
212
+ for (const s of selList) {
213
+ const sub = s.trim();
214
+ const selector = this.getSelector(uid, el, state, s, sub);
215
+ if (!selector)
216
+ continue;
217
+ if (defaultVal?.trim())
218
+ lines.push(`${selector} { ${defaultVal} }`);
219
+ if (userVal?.trim())
220
+ lines.push(`${selector} { ${userVal} }`);
221
+ // Per Container: propaga le proprietà border ai segmenti MDC (notched-outline__*).
222
+ // Se il CSS imposta uno spessore (border/border-width) → il bordo visivo è già sul
223
+ // wrapper, i segmenti vengono soppressi (border-color:transparent) per evitare il
224
+ // doppio bordo. Se imposta solo border-color → viene applicato ai segmenti per
225
+ // sovrascrivere il ring blu/hover di Material (specificità 1,2,0 > 0,2,0).
226
+ if (el === 'Container') {
227
+ const outlineSel = this.getOutlineSelector(uid, state);
228
+ if (outlineSel) {
229
+ this.applyBorderToOutline(outlineSel, defaultVal ?? '', lines);
230
+ this.applyBorderToOutline(outlineSel, userVal ?? '', lines);
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
236
+ return lines.join('\n');
237
+ }
238
+ /** Aggiorna le classi di stato sul wrapper (eqp-invalid, eqp-readonly, eqp-state-*) */
239
+ updateStateClasses() {
240
+ if (!this.fieldUid)
241
+ return;
242
+ const wrapper = document.getElementById(this.fieldUid);
243
+ if (!wrapper)
244
+ return;
245
+ this.toggleClass(wrapper, 'eqp-state-hover', this.forceState === 'Mouseover');
246
+ this.toggleClass(wrapper, 'eqp-state-focused', this.forceState === 'Focused');
247
+ if (this.forceState === 'NotValid') {
248
+ this.toggleClass(wrapper, 'eqp-invalid', true);
249
+ this.toggleClass(wrapper, 'eqp-readonly', false);
250
+ return;
251
+ }
252
+ if (this.forceState === 'Readonly') {
253
+ this.toggleClass(wrapper, 'eqp-readonly', true);
254
+ this.toggleClass(wrapper, 'eqp-invalid', false);
255
+ return;
256
+ }
257
+ if (this.forceState === 'Normale' || this.forceState === 'Mouseover' || this.forceState === 'Focused') {
258
+ this.toggleClass(wrapper, 'eqp-invalid', false);
259
+ this.toggleClass(wrapper, 'eqp-readonly', false);
260
+ return;
261
+ }
262
+ const isReadonly = this.field.Readonly || (this.field.Formula != null && this.field.Formula !== '');
263
+ this.toggleClass(wrapper, 'eqp-readonly', isReadonly);
264
+ const ctrl = this.field.FormFormGroup?.controls?.[this.field.Name];
265
+ if (ctrl?.touched) {
266
+ this.toggleClass(wrapper, 'eqp-invalid', this.field.FormFormGroup.invalid);
267
+ }
268
+ else {
269
+ this.toggleClass(wrapper, 'eqp-invalid', false);
270
+ }
271
+ }
272
+ toggleClass(el, cls, condition) {
273
+ if (condition)
274
+ this.renderer.addClass(el, cls);
275
+ else
276
+ this.renderer.removeClass(el, cls);
277
+ }
278
+ subscribeToFormStatus() {
279
+ this.statusSub?.unsubscribe();
280
+ if (this.field?.FormFormGroup) {
281
+ this.statusSub = this.field.FormFormGroup.statusChanges.subscribe(() => this.updateStateClasses());
282
+ }
283
+ }
284
+ getInputType() {
285
+ switch (Number(this.field.TextMask)) {
286
+ case TextMaskEnum.Email: return 'email';
287
+ case TextMaskEnum.Password: return 'password';
288
+ case TextMaskEnum.Telefono: return 'tel';
289
+ case TextMaskEnum.Url: return 'url';
290
+ default: return 'text';
291
+ }
292
+ }
61
293
  updateField() {
62
294
  if (this.field.ReadonlyIf) {
63
295
  this.field.Readonly = UtilityHelperService.EvaluateFieldFormula(this.field.ReadonlyIf, this.record, this.formulaObject);
@@ -75,10 +307,8 @@ export class TextFieldTemplateComponent {
75
307
  this.record[this.field.Name] = this.field.DataGetter.DataGetterValue;
76
308
  }
77
309
  }
78
- /**
79
- * Metodo per emettere l'evento che il valore del record è cambiato.
80
- */
81
310
  onRecordValueChange() {
311
+ this.updateStateClasses();
82
312
  if (!this.field.Formula) {
83
313
  this.recordChange.emit(this.record);
84
314
  }
@@ -87,12 +317,12 @@ export class TextFieldTemplateComponent {
87
317
  }
88
318
  }
89
319
  }
90
- TextFieldTemplateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TextFieldTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
91
- TextFieldTemplateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TextFieldTemplateComponent, selector: "text-field-template", inputs: { field: "field", record: "record", formulaObject: "formulaObject", inConfig: "inConfig" }, outputs: { recordChange: "recordChange" }, usesOnChanges: true, ngImport: i0, template: "<mat-form-field [formGroup]=\"field.FormFormGroup\" appearance=\"outline\">\r\n <mat-label class=\"pt-1\" [ngStyle]=\"LabelstyleObj\">\r\n {{ field.Description }}\r\n </mat-label>\r\n <mat-icon *ngIf=\"field.IconName && field.IconPosition != TextFieldIconPositionEnum.Destra\" matPrefix>\r\n {{ field.IconName }}\r\n </mat-icon>\r\n <input\r\n [ngStyle]=\"FieldstyleObj\"\r\n matInput\r\n [type]=\"getInputType()\"\r\n [formControlName]=\"field.Name\"\r\n [readonly]=\"field.Readonly || (field.Formula != null && field.Formula != '')\"\r\n [required]=\"field.Required\"\r\n [(ngModel)]=\"record[field.Name]\"\r\n (ngModelChange)=\"onRecordValueChange()\"\r\n />\r\n <mat-error\r\n *ngIf=\"\r\n !field.FormFormGroup.valid &&\r\n field.FormFormGroup.controls[field.Name].touched &&\r\n !field.Readonly\r\n \"\r\n >\r\n Min. Caratteri: {{ field.MinLenght }} - Max. Caratteri:\r\n {{ field.MaxLenght }}\r\n </mat-error>\r\n <mat-icon\r\n *ngIf=\"field.IconName && field.IconPosition == TextFieldIconPositionEnum.Destra\"\r\n matSuffix\r\n >{{ field.IconName }}</mat-icon\r\n >\r\n <mat-icon\r\n [hidden]=\"!field.Microphone || platform != 'web'\"\r\n matSuffix\r\n SpeechToText\r\n [(bindedText)]=\"record[field.Name]\"\r\n style=\"cursor: pointer\"\r\n >keyboard_voice</mat-icon\r\n >\r\n</mat-form-field>\r\n", styles: ["::ng-deep .mat-form-field-label{font-size:x-large}.keyboard_speaking{color:red}\n"], dependencies: [{ kind: "directive", type: i1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.SpeechToTextDirective, selector: "[SpeechToText]", inputs: ["bindedText"], outputs: ["bindedTextChange"] }] });
320
+ TextFieldTemplateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TextFieldTemplateComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
321
+ TextFieldTemplateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TextFieldTemplateComponent, selector: "text-field-template", inputs: { field: "field", record: "record", formulaObject: "formulaObject", inConfig: "inConfig", styleVersion: "styleVersion", forceState: "forceState" }, outputs: { recordChange: "recordChange" }, usesOnChanges: true, ngImport: i0, template: "<div [id]=\"fieldUid\" class=\"eqp-tf-wrapper\">\r\n <mat-form-field [formGroup]=\"field.FormFormGroup\" appearance=\"outline\">\r\n <mat-label class=\"pt-1\" [ngStyle]=\"LabelstyleObj\">\r\n {{ field.Description }}\r\n </mat-label>\r\n <mat-icon *ngIf=\"field.IconName && field.IconPosition != TextFieldIconPositionEnum.Destra\" matPrefix>\r\n {{ field.IconName }}\r\n </mat-icon>\r\n <input\r\n [ngStyle]=\"FieldstyleObj\"\r\n matInput\r\n [type]=\"getInputType()\"\r\n [formControlName]=\"field.Name\"\r\n [readonly]=\"field.Readonly || (field.Formula != null && field.Formula != '')\"\r\n [required]=\"field.Required\"\r\n [(ngModel)]=\"record[field.Name]\"\r\n (ngModelChange)=\"onRecordValueChange()\"\r\n />\r\n <mat-error\r\n *ngIf=\"\r\n !field.FormFormGroup.valid &&\r\n field.FormFormGroup.controls[field.Name].touched &&\r\n !field.Readonly\r\n \"\r\n >\r\n Min. Caratteri: {{ field.MinLenght }} - Max. Caratteri:\r\n {{ field.MaxLenght }}\r\n </mat-error>\r\n <mat-icon\r\n *ngIf=\"field.IconName && field.IconPosition == TextFieldIconPositionEnum.Destra\"\r\n matSuffix\r\n >{{ field.IconName }}</mat-icon\r\n >\r\n <mat-icon\r\n [hidden]=\"!field.Microphone || platform != 'web'\"\r\n matSuffix\r\n class=\"eqp-microfono\"\r\n SpeechToText\r\n [(bindedText)]=\"record[field.Name]\"\r\n style=\"cursor: pointer\"\r\n >keyboard_voice</mat-icon\r\n >\r\n </mat-form-field>\r\n</div>\r\n", styles: [".eqp-tf-wrapper{display:block;width:100%}.keyboard_speaking{color:red}\n"], dependencies: [{ kind: "directive", type: i1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.SpeechToTextDirective, selector: "[SpeechToText]", inputs: ["bindedText"], outputs: ["bindedTextChange"] }] });
92
322
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TextFieldTemplateComponent, decorators: [{
93
323
  type: Component,
94
- args: [{ selector: 'text-field-template', template: "<mat-form-field [formGroup]=\"field.FormFormGroup\" appearance=\"outline\">\r\n <mat-label class=\"pt-1\" [ngStyle]=\"LabelstyleObj\">\r\n {{ field.Description }}\r\n </mat-label>\r\n <mat-icon *ngIf=\"field.IconName && field.IconPosition != TextFieldIconPositionEnum.Destra\" matPrefix>\r\n {{ field.IconName }}\r\n </mat-icon>\r\n <input\r\n [ngStyle]=\"FieldstyleObj\"\r\n matInput\r\n [type]=\"getInputType()\"\r\n [formControlName]=\"field.Name\"\r\n [readonly]=\"field.Readonly || (field.Formula != null && field.Formula != '')\"\r\n [required]=\"field.Required\"\r\n [(ngModel)]=\"record[field.Name]\"\r\n (ngModelChange)=\"onRecordValueChange()\"\r\n />\r\n <mat-error\r\n *ngIf=\"\r\n !field.FormFormGroup.valid &&\r\n field.FormFormGroup.controls[field.Name].touched &&\r\n !field.Readonly\r\n \"\r\n >\r\n Min. Caratteri: {{ field.MinLenght }} - Max. Caratteri:\r\n {{ field.MaxLenght }}\r\n </mat-error>\r\n <mat-icon\r\n *ngIf=\"field.IconName && field.IconPosition == TextFieldIconPositionEnum.Destra\"\r\n matSuffix\r\n >{{ field.IconName }}</mat-icon\r\n >\r\n <mat-icon\r\n [hidden]=\"!field.Microphone || platform != 'web'\"\r\n matSuffix\r\n SpeechToText\r\n [(bindedText)]=\"record[field.Name]\"\r\n style=\"cursor: pointer\"\r\n >keyboard_voice</mat-icon\r\n >\r\n</mat-form-field>\r\n", styles: ["::ng-deep .mat-form-field-label{font-size:x-large}.keyboard_speaking{color:red}\n"] }]
95
- }], ctorParameters: function () { return []; }, propDecorators: { field: [{
324
+ args: [{ selector: 'text-field-template', template: "<div [id]=\"fieldUid\" class=\"eqp-tf-wrapper\">\r\n <mat-form-field [formGroup]=\"field.FormFormGroup\" appearance=\"outline\">\r\n <mat-label class=\"pt-1\" [ngStyle]=\"LabelstyleObj\">\r\n {{ field.Description }}\r\n </mat-label>\r\n <mat-icon *ngIf=\"field.IconName && field.IconPosition != TextFieldIconPositionEnum.Destra\" matPrefix>\r\n {{ field.IconName }}\r\n </mat-icon>\r\n <input\r\n [ngStyle]=\"FieldstyleObj\"\r\n matInput\r\n [type]=\"getInputType()\"\r\n [formControlName]=\"field.Name\"\r\n [readonly]=\"field.Readonly || (field.Formula != null && field.Formula != '')\"\r\n [required]=\"field.Required\"\r\n [(ngModel)]=\"record[field.Name]\"\r\n (ngModelChange)=\"onRecordValueChange()\"\r\n />\r\n <mat-error\r\n *ngIf=\"\r\n !field.FormFormGroup.valid &&\r\n field.FormFormGroup.controls[field.Name].touched &&\r\n !field.Readonly\r\n \"\r\n >\r\n Min. Caratteri: {{ field.MinLenght }} - Max. Caratteri:\r\n {{ field.MaxLenght }}\r\n </mat-error>\r\n <mat-icon\r\n *ngIf=\"field.IconName && field.IconPosition == TextFieldIconPositionEnum.Destra\"\r\n matSuffix\r\n >{{ field.IconName }}</mat-icon\r\n >\r\n <mat-icon\r\n [hidden]=\"!field.Microphone || platform != 'web'\"\r\n matSuffix\r\n class=\"eqp-microfono\"\r\n SpeechToText\r\n [(bindedText)]=\"record[field.Name]\"\r\n style=\"cursor: pointer\"\r\n >keyboard_voice</mat-icon\r\n >\r\n </mat-form-field>\r\n</div>\r\n", styles: [".eqp-tf-wrapper{display:block;width:100%}.keyboard_speaking{color:red}\n"] }]
325
+ }], ctorParameters: function () { return [{ type: i0.Renderer2 }]; }, propDecorators: { field: [{
96
326
  type: Input
97
327
  }], record: [{
98
328
  type: Input
@@ -100,7 +330,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
100
330
  type: Input
101
331
  }], inConfig: [{
102
332
  type: Input
333
+ }], styleVersion: [{
334
+ type: Input
335
+ }], forceState: [{
336
+ type: Input
103
337
  }], recordChange: [{
104
338
  type: Output
105
339
  }] } });
106
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtZHluYW1pYy1tb2R1bGUvc3JjL2xpYi9jb21wb25lbnRzL3ByaXZhdGUvZmllbGQtdGVtcGxhdGVzL3RleHQtZmllbGQtdGVtcGxhdGUvdGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtZHluYW1pYy1tb2R1bGUvc3JjL2xpYi9jb21wb25lbnRzL3ByaXZhdGUvZmllbGQtdGVtcGxhdGVzL3RleHQtZmllbGQtdGVtcGxhdGUvdGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFFekcsT0FBTyxFQUFFLHlCQUF5QixFQUFFLFlBQVksRUFBYSxNQUFNLDJDQUEyQyxDQUFDO0FBRS9HLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ25GLE9BQU8sRUFBRSxRQUFRLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQzlDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7QUFPNUMsTUFBTSxPQUFPLDBCQUEwQjtJQXFCckM7UUFwQkEsOEJBQThCO1FBQzlCLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUN6QixXQUFNLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBTWQsa0JBQWEsR0FBUSxFQUFFLENBQUM7UUFDeEIsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUt6QixpQkFBWSxHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDO1FBQzFFLGtCQUFhLEdBQUcsWUFBWSxDQUFDO1FBQzdCLDhCQUF5QixHQUFHLHlCQUF5QixDQUFDO1FBRXRELGFBQVEsR0FBVyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7SUFHM0MsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFDRCxVQUFVO1FBQ04sa0ZBQWtGO1FBQ3BGLElBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxJQUFJLFNBQVM7WUFDMUUsSUFBSSxDQUFDLGFBQWEsR0FBRSxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNoRixJQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsSUFBSSxTQUFTO1lBQzFFLElBQUksQ0FBQyxhQUFhLEdBQUcsb0JBQW9CLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDcEYsQ0FBQztJQUVBLFdBQVcsQ0FBQyxPQUFzQjtRQUNoQywwRUFBMEU7UUFDMUUsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksU0FBUyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxXQUFXLElBQUksS0FBSyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLFlBQVksQ0FBQyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQ2pMLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLFlBQVksQ0FBQztZQUM3QyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDcEI7SUFDSCxDQUFDO0lBRUQsWUFBWTtRQUNWLFFBQVEsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDbkMsS0FBSyxZQUFZLENBQUMsS0FBSztnQkFDckIsT0FBTyxPQUFPLENBQUM7WUFDakIsS0FBSyxZQUFZLENBQUMsUUFBUTtnQkFDeEIsT0FBTyxVQUFVLENBQUM7WUFDcEIsS0FBSyxZQUFZLENBQUMsUUFBUTtnQkFDeEIsT0FBTyxLQUFLLENBQUM7WUFDZixLQUFLLFlBQVksQ0FBQyxHQUFHO2dCQUNuQixPQUFPLEtBQUssQ0FBQztZQUNmO2dCQUNFLE9BQU8sTUFBTSxDQUFDO1NBQ2pCO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUVULElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUU7WUFDekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsb0JBQW9CLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDekg7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsY0FBYyxJQUFJLGtCQUFrQixDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxjQUFjLElBQUksa0JBQWtCLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUU7WUFDcEssSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQy9IO1FBQ0QsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRTtZQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxvQkFBb0IsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN6SCxJQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBQztnQkFDdEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFDLElBQUksQ0FBQzthQUNuQztTQUNGO1FBQ0QsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxjQUFjLElBQUksa0JBQWtCLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDOUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQztTQUN0RTtJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILG1CQUFtQjtRQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUU7WUFDdkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3JDO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFO1lBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUNyQztJQUNILENBQUM7O3dIQTNGVSwwQkFBMEI7NEdBQTFCLDBCQUEwQiwrTkNkdkMsNjNDQXlDQTs0RkQzQmEsMEJBQTBCO2tCQUx0QyxTQUFTOytCQUNFLHFCQUFxQjswRUFXdEIsS0FBSztzQkFBYixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBS0ksWUFBWTtzQkFBckIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkluaXQsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBSZWNvcmQgfSBmcm9tICcuLi8uLi8uLi8uLi9tb2RlbHMvcmVjb3JkLm1vZGVsJztcclxuaW1wb3J0IHsgVGV4dEZpZWxkSWNvblBvc2l0aW9uRW51bSwgVGV4dE1hc2tFbnVtLCBUZXh0RmllbGQgfSBmcm9tICcuLi8uLi8uLi8uLi9tb2RlbHMvZmllbGRzL3RleHRGaWVsZC5tb2RlbCc7XHJcbmltcG9ydCB7IElCYXNlRmllbGRDb21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi8uLi9pbnRlcmZhY2VzL2lCYXNlRmllbGRDb21wb25lbnQuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgVXRpbGl0eUhlbHBlclNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi8uLi9zZXJ2aWNlcy91dGlsaXR5SGVscGVyLnNlcnZpY2VzJztcclxuaW1wb3J0IHsgaW50ZXJ2YWwsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBEYXRhR2V0dGVyVHlwZUVudW0gfSBmcm9tICcuLi8uLi8uLi8uLi9tb2RlbHMvYmFzZUZpZWxkLm1vZGVsJztcclxuaW1wb3J0IHsgQ2FwYWNpdG9yIH0gZnJvbSAnQGNhcGFjaXRvci9jb3JlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAndGV4dC1maWVsZC10ZW1wbGF0ZScsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RleHQtZmllbGQtdGVtcGxhdGUuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3RleHQtZmllbGQtdGVtcGxhdGUuY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgVGV4dEZpZWxkVGVtcGxhdGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgSUJhc2VGaWVsZENvbXBvbmVudCB7XHJcbiAgLy9WYXJpYWJpbGkgcGVyIGwnaW5wdXQgdm9jYWxlXHJcbiAgaXNTdGlsbFJlY29naW56ZSA9IGZhbHNlO1xyXG4gIHNvdXJjZSA9IGludGVydmFsKDIwMCk7XHJcbiAgbmV3dGV4dDogc3RyaW5nO1xyXG4gIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xyXG4gIC8vdmFyaWFiaWxpIGVzdGVybmUgcGVyIGwnaW5wdXQgZGVpIGNhbXBpXHJcbiAgQElucHV0KCkgZmllbGQ6IFRleHRGaWVsZDtcclxuICBASW5wdXQoKSByZWNvcmQ6IFJlY29yZDtcclxuICBASW5wdXQoKSBmb3JtdWxhT2JqZWN0OiBhbnkgPSB7fTtcclxuICBASW5wdXQoKSBpbkNvbmZpZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8vdmFyaWFiaWxpIHBlciBnZXN0aXJlIGlsIGNzcyBkZWxsYSBsYWJlbCBlIGRlbCBmaWVsZFxyXG4gIEZpZWxkc3R5bGVPYmo6IGFueTtcclxuICBMYWJlbHN0eWxlT2JqOiBhbnk7XHJcblxyXG4gIEBPdXRwdXQoKSByZWNvcmRDaGFuZ2U6IEV2ZW50RW1pdHRlcjxSZWNvcmQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxSZWNvcmQ+KCk7XHJcbiAgSW5wdXRNYXNrRW51bSA9IFRleHRNYXNrRW51bTtcclxuICBUZXh0RmllbGRJY29uUG9zaXRpb25FbnVtID0gVGV4dEZpZWxkSWNvblBvc2l0aW9uRW51bTtcclxuXHJcbiAgcGxhdGZvcm06IHN0cmluZyA9IENhcGFjaXRvci5nZXRQbGF0Zm9ybSgpO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy51cGRhdGVGaWVsZCgpO1xyXG4gICAgdGhpcy5pbml0U3R5bGVzKCk7XHJcbiAgfVxyXG4gIGluaXRTdHlsZXMoKSB7XHJcbiAgICAgIC8vRnVuemlvbmUgcGVyIHBhcnNhcmUgaWwgY2FtcG8gc3R5bGVjc3MgZGVsbCdvZ2dldHRvIGZpZWxkIGVkIGFwcGxpY2FybG8gYWxsJ2h0bWxcclxuICAgIGlmKHRoaXMuZmllbGQuRmllbGRzdHlsZUNTUyAhPSBudWxsIHx8IHRoaXMuZmllbGQuRmllbGRzdHlsZUNTUyAhPSB1bmRlZmluZWQpICAgXHJcbiAgICAgIHRoaXMuRmllbGRzdHlsZU9iaj0gVXRpbGl0eUhlbHBlclNlcnZpY2UuaW5pdFN0eWxlcyh0aGlzLmZpZWxkLkZpZWxkc3R5bGVDU1MpO1xyXG4gICAgaWYodGhpcy5maWVsZC5MYWJlbHN0eWxlQ1NTICE9IG51bGwgfHwgdGhpcy5maWVsZC5MYWJlbHN0eWxlQ1NTICE9IHVuZGVmaW5lZCkgICBcclxuICAgICAgdGhpcy5MYWJlbHN0eWxlT2JqID0gVXRpbGl0eUhlbHBlclNlcnZpY2UuaW5pdFN0eWxlcyh0aGlzLmZpZWxkLkxhYmVsc3R5bGVDU1MpO1xyXG4gfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICAvLyBTZSB2aWVuZSBtb2RpZmljYXRvIGlsIHZhbG9yZSBkaSBcIm5nTW9kZWxJbnB1dFwiIGFsbG9yYSBhZ2dpb3JuYSBsJ2lucHV0XHJcbiAgICBpZiAoY2hhbmdlc1sncmVjb3JkJ10gIT0gdW5kZWZpbmVkICYmIGNoYW5nZXNbJ3JlY29yZCddLmZpcnN0Q2hhbmdlID09IGZhbHNlICYmIEpTT04uc3RyaW5naWZ5KGNoYW5nZXNbJ3JlY29yZCddLmN1cnJlbnRWYWx1ZSkgIT0gSlNPTi5zdHJpbmdpZnkoY2hhbmdlc1sncmVjb3JkJ10ucHJldmlvdXNWYWx1ZSkpIHtcclxuICAgICAgdGhpcy5yZWNvcmQgPSBjaGFuZ2VzWydyZWNvcmQnXS5jdXJyZW50VmFsdWU7XHJcbiAgICAgIHRoaXMudXBkYXRlRmllbGQoKTtcclxuICAgIH1cclxuICB9XHJcbiAgXHJcbiAgZ2V0SW5wdXRUeXBlKCkge1xyXG4gICAgc3dpdGNoIChOdW1iZXIodGhpcy5maWVsZC5UZXh0TWFzaykpIHtcclxuICAgICAgY2FzZSBUZXh0TWFza0VudW0uRW1haWw6XHJcbiAgICAgICAgcmV0dXJuICdlbWFpbCc7XHJcbiAgICAgIGNhc2UgVGV4dE1hc2tFbnVtLlBhc3N3b3JkOlxyXG4gICAgICAgIHJldHVybiAncGFzc3dvcmQnO1xyXG4gICAgICBjYXNlIFRleHRNYXNrRW51bS5UZWxlZm9ubzpcclxuICAgICAgICByZXR1cm4gJ3RlbCc7XHJcbiAgICAgIGNhc2UgVGV4dE1hc2tFbnVtLlVybDpcclxuICAgICAgICByZXR1cm4gJ3VybCc7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgcmV0dXJuICd0ZXh0JztcclxuICAgIH1cclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogTWV0b2RvIHBlciBhZ2dpb3JuYXJlIGlsIHZhbG9yZSBkZWwgY2FtcG8gcXVhbmRvIHF1ZXN0byDDqCByYXBwcmVzZW50YXRvIGRhIHVuYSBmb3JtdWxhLlxyXG4gICAqL1xyXG4gIHVwZGF0ZUZpZWxkKCkge1xyXG4gICAgICAgIFxyXG4gICAgaWYgKHRoaXMuZmllbGQuUmVhZG9ubHlJZikge1xyXG4gICAgICB0aGlzLmZpZWxkLlJlYWRvbmx5ID0gVXRpbGl0eUhlbHBlclNlcnZpY2UuRXZhbHVhdGVGaWVsZEZvcm11bGEodGhpcy5maWVsZC5SZWFkb25seUlmLCB0aGlzLnJlY29yZCwgdGhpcy5mb3JtdWxhT2JqZWN0KTtcclxuICAgIH1cclxuICAgIGlmICgodGhpcy5maWVsZC5EYXRhR2V0dGVyLkRhdGFHZXR0ZXJUeXBlID09IERhdGFHZXR0ZXJUeXBlRW51bS5NYW51YWxlIHx8IHRoaXMuZmllbGQuRGF0YUdldHRlci5EYXRhR2V0dGVyVHlwZSA9PSBEYXRhR2V0dGVyVHlwZUVudW0uRm9ybXVsYSkgJiYgdGhpcy5maWVsZC5Gb3JtdWxhKSB7XHJcbiAgICAgIHRoaXMucmVjb3JkW3RoaXMuZmllbGQuTmFtZV0gPSBVdGlsaXR5SGVscGVyU2VydmljZS5FdmFsdWF0ZUZpZWxkRm9ybXVsYSh0aGlzLmZpZWxkLkZvcm11bGEsIHRoaXMucmVjb3JkLCB0aGlzLmZvcm11bGFPYmplY3QpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuZmllbGQuVmlzaWJsZUlmKSB7XHJcbiAgICAgIHRoaXMuZmllbGQuSW5MaXN0VmlldyA9IFV0aWxpdHlIZWxwZXJTZXJ2aWNlLkV2YWx1YXRlRmllbGRGb3JtdWxhKHRoaXMuZmllbGQuVmlzaWJsZUlmLCB0aGlzLnJlY29yZCwgdGhpcy5mb3JtdWxhT2JqZWN0KTtcclxuICAgICAgaWYoIXRoaXMuZmllbGQuSW5MaXN0VmlldyAmJiAhdGhpcy5maWVsZC5NYWludGFpbl9WYWx1ZSl7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRbdGhpcy5maWVsZC5OYW1lXT1udWxsO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5maWVsZC5EYXRhR2V0dGVyLkRhdGFHZXR0ZXJUeXBlID09IERhdGFHZXR0ZXJUeXBlRW51bS5NYW51YWxlICYmIHRoaXMucmVjb3JkW3RoaXMuZmllbGQuTmFtZV0gPT0gbnVsbCkge1xyXG4gICAgICB0aGlzLnJlY29yZFt0aGlzLmZpZWxkLk5hbWVdID0gdGhpcy5maWVsZC5EYXRhR2V0dGVyLkRhdGFHZXR0ZXJWYWx1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ldG9kbyBwZXIgZW1ldHRlcmUgbCdldmVudG8gY2hlIGlsIHZhbG9yZSBkZWwgcmVjb3JkIMOoIGNhbWJpYXRvLlxyXG4gICAqL1xyXG4gIG9uUmVjb3JkVmFsdWVDaGFuZ2UoKSB7XHJcbiAgICBpZiAoIXRoaXMuZmllbGQuRm9ybXVsYSkge1xyXG4gICAgICB0aGlzLnJlY29yZENoYW5nZS5lbWl0KHRoaXMucmVjb3JkKTtcclxuICAgIH1cclxuICAgIGlmICghdGhpcy5maWVsZC5WaXNpYmxlSWYpIHtcclxuICAgICAgdGhpcy5yZWNvcmRDaGFuZ2UuZW1pdCh0aGlzLnJlY29yZCk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsIjxtYXQtZm9ybS1maWVsZCBbZm9ybUdyb3VwXT1cImZpZWxkLkZvcm1Gb3JtR3JvdXBcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiPlxyXG4gIDxtYXQtbGFiZWwgY2xhc3M9XCJwdC0xXCIgW25nU3R5bGVdPVwiTGFiZWxzdHlsZU9ialwiPlxyXG4gICAge3sgZmllbGQuRGVzY3JpcHRpb24gfX1cclxuICA8L21hdC1sYWJlbD5cclxuICA8bWF0LWljb24gKm5nSWY9XCJmaWVsZC5JY29uTmFtZSAmJiBmaWVsZC5JY29uUG9zaXRpb24gIT0gVGV4dEZpZWxkSWNvblBvc2l0aW9uRW51bS5EZXN0cmFcIiBtYXRQcmVmaXg+XHJcbiAgICB7eyBmaWVsZC5JY29uTmFtZSB9fVxyXG4gIDwvbWF0LWljb24+XHJcbiAgPGlucHV0XHJcbiAgICBbbmdTdHlsZV09XCJGaWVsZHN0eWxlT2JqXCJcclxuICAgIG1hdElucHV0XHJcbiAgICBbdHlwZV09XCJnZXRJbnB1dFR5cGUoKVwiXHJcbiAgICBbZm9ybUNvbnRyb2xOYW1lXT1cImZpZWxkLk5hbWVcIlxyXG4gICAgW3JlYWRvbmx5XT1cImZpZWxkLlJlYWRvbmx5IHx8IChmaWVsZC5Gb3JtdWxhICE9IG51bGwgJiYgZmllbGQuRm9ybXVsYSAhPSAnJylcIlxyXG4gICAgW3JlcXVpcmVkXT1cImZpZWxkLlJlcXVpcmVkXCJcclxuICAgIFsobmdNb2RlbCldPVwicmVjb3JkW2ZpZWxkLk5hbWVdXCJcclxuICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uUmVjb3JkVmFsdWVDaGFuZ2UoKVwiXHJcbiAgLz5cclxuICA8bWF0LWVycm9yXHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICAhZmllbGQuRm9ybUZvcm1Hcm91cC52YWxpZCAmJlxyXG4gICAgICBmaWVsZC5Gb3JtRm9ybUdyb3VwLmNvbnRyb2xzW2ZpZWxkLk5hbWVdLnRvdWNoZWQgJiZcclxuICAgICAgIWZpZWxkLlJlYWRvbmx5XHJcbiAgICBcIlxyXG4gID5cclxuICAgIE1pbi4gQ2FyYXR0ZXJpOiB7eyBmaWVsZC5NaW5MZW5naHQgfX0gLSBNYXguIENhcmF0dGVyaTpcclxuICAgIHt7IGZpZWxkLk1heExlbmdodCB9fVxyXG4gIDwvbWF0LWVycm9yPlxyXG4gIDxtYXQtaWNvblxyXG4gICAgKm5nSWY9XCJmaWVsZC5JY29uTmFtZSAmJiBmaWVsZC5JY29uUG9zaXRpb24gPT0gVGV4dEZpZWxkSWNvblBvc2l0aW9uRW51bS5EZXN0cmFcIlxyXG4gICAgbWF0U3VmZml4XHJcbiAgICA+e3sgZmllbGQuSWNvbk5hbWUgfX08L21hdC1pY29uXHJcbiAgPlxyXG4gIDxtYXQtaWNvblxyXG4gICAgW2hpZGRlbl09XCIhZmllbGQuTWljcm9waG9uZSB8fCBwbGF0Zm9ybSAhPSAnd2ViJ1wiXHJcbiAgICBtYXRTdWZmaXhcclxuICAgIFNwZWVjaFRvVGV4dFxyXG4gICAgWyhiaW5kZWRUZXh0KV09XCJyZWNvcmRbZmllbGQuTmFtZV1cIlxyXG4gICAgc3R5bGU9XCJjdXJzb3I6IHBvaW50ZXJcIlxyXG4gICAgPmtleWJvYXJkX3ZvaWNlPC9tYXQtaWNvblxyXG4gID5cclxuPC9tYXQtZm9ybS1maWVsZD5cclxuIl19
340
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtZHluYW1pYy1tb2R1bGUvc3JjL2xpYi9jb21wb25lbnRzL3ByaXZhdGUvZmllbGQtdGVtcGxhdGVzL3RleHQtZmllbGQtdGVtcGxhdGUvdGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtZHluYW1pYy1tb2R1bGUvc3JjL2xpYi9jb21wb25lbnRzL3ByaXZhdGUvZmllbGQtdGVtcGxhdGVzL3RleHQtZmllbGQtdGVtcGxhdGUvdGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBNEIsTUFBTSxlQUFlLENBQUM7QUFFL0gsT0FBTyxFQUFFLHlCQUF5QixFQUFxQixZQUFZLEVBQWEsTUFBTSwyQ0FBMkMsQ0FBQztBQUVsSSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUNuRixPQUFPLEVBQUUsUUFBUSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUM5QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN4RSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7O0FBRTVDLDJDQUEyQztBQUMzQyxrRkFBa0Y7QUFDbEYsb0dBQW9HO0FBQ3BHLDhGQUE4RjtBQUM5RixvR0FBb0c7QUFDcEcsMkVBQTJFO0FBQzNFLDJFQUEyRTtBQUMzRSxxRkFBcUY7QUFDckYsOEZBQThGO0FBQzlGLE1BQU0saUJBQWlCLEdBQXlDO0lBQzlELFNBQVMsRUFBRSw4QkFBOEI7SUFDekMsS0FBSyxFQUFFLDRCQUE0QjtJQUNuQyxXQUFXLEVBQUUsK0JBQStCO0lBQzVDLEtBQUssRUFBRSxDQUFDLGtDQUFrQyxFQUFFLGtDQUFrQyxDQUFDO0lBQy9FLFNBQVMsRUFBRSxrQ0FBa0M7SUFDN0MsTUFBTSxFQUFFLFlBQVk7Q0FDckIsQ0FBQztBQUNGLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUNoRCxNQUFNLE1BQU0sR0FBRyxDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztBQUUzRSx5RUFBeUU7QUFDekUsb0dBQW9HO0FBQ3BHLE1BQU0sb0JBQW9CLEdBQThCO0lBQ3RELGtCQUFrQixFQUFFLHFCQUFxQjtJQUN6QyxvRkFBb0Y7SUFDcEYsK0ZBQStGO0lBQy9GLGdCQUFnQixFQUFFLHFCQUFxQjtJQUN2QyxrR0FBa0c7SUFDbEcsWUFBWSxFQUFFLG9CQUFvQjtDQUNuQyxDQUFDO0FBT0YsTUFBTSxPQUFPLDBCQUEwQjtJQTRCckMsWUFBb0IsUUFBbUI7UUFBbkIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQTNCdkMscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLFdBQU0sR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFNZCxrQkFBYSxHQUFRLEVBQUUsQ0FBQztRQUN4QixhQUFRLEdBQVksS0FBSyxDQUFDO1FBQ25DLCtGQUErRjtRQUN0RixpQkFBWSxHQUFXLENBQUMsQ0FBQztRQUNsQyw2RUFBNkU7UUFDcEUsZUFBVSxHQUFrQixJQUFJLENBQUM7UUFLaEMsaUJBQVksR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUMxRSxrQkFBYSxHQUFHLFlBQVksQ0FBQztRQUM3Qiw4QkFBeUIsR0FBRyx5QkFBeUIsQ0FBQztRQUV0RCxhQUFRLEdBQVcsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBR25DLFlBQU8sR0FBNEIsSUFBSSxDQUFDO1FBQ3hDLGNBQVMsR0FBd0IsSUFBSSxDQUFDO0lBRUosQ0FBQztJQUUzQyxRQUFRO1FBQ04sSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVELFdBQVcsQ0FBQyxPQUFzQjtRQUNoQyxJQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxXQUFXLEVBQUU7WUFDbkUsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7U0FDM0I7UUFDRCxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRTtZQUN6QixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztTQUMzQjtRQUNELElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFNBQVMsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsV0FBVyxJQUFJLEtBQUs7ZUFDdkUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDdEcsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsWUFBWSxDQUFDO1lBQzdDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztTQUMzQjtJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRTtZQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ25EO1FBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQsVUFBVTtRQUNSLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxJQUFJLFNBQVM7WUFDM0UsSUFBSSxDQUFDLGFBQWEsR0FBRyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNqRixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsSUFBSSxTQUFTO1lBQzNFLElBQUksQ0FBQyxhQUFhLEdBQUcsb0JBQW9CLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDbkYsQ0FBQztJQUVELHFGQUFxRjtJQUNyRixxQkFBcUI7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTztRQUMzQixNQUFNLEdBQUcsR0FBSSxJQUFJLENBQUMsS0FBbUIsRUFBRSxpQkFBaUIsSUFBSyxFQUF3QixDQUFDO1FBQ3RGLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNuRCwyRkFBMkY7UUFDM0YsNkZBQTZGO1FBQzdGLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNqQixLQUFLLElBQUksTUFBTSxJQUFJLENBQUMsUUFBUSwyREFBMkQsQ0FBQztTQUN6RjtRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFxQixDQUFDO1lBQ3hFLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1lBQzNDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ3hEO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO0lBQ25DLENBQUM7SUFFRCwrREFBK0Q7SUFDdkQsV0FBVyxDQUFDLEdBQVcsRUFBRSxHQUFXLEVBQUUsS0FBYSxFQUFFLENBQVMsRUFBRSxJQUFZO1FBQ2xGLFFBQVEsS0FBSyxFQUFFO1lBQ2IsS0FBSyxTQUFTLENBQUMsQ0FBRyxPQUFPLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLEtBQUssV0FBVyxDQUFDLENBQUMsT0FBTyxJQUFJLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQyxFQUFFLENBQUM7WUFDMUUsS0FBSyxTQUFTLENBQUMsQ0FBRyxPQUFPLElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcscUJBQXFCLENBQUMsRUFBRSxDQUFDO1lBQ25GLEtBQUssVUFBVSxDQUFDLENBQUUsT0FBTyxJQUFJLEdBQUcsZUFBZSxDQUFDLEVBQUUsQ0FBQztZQUNuRCxLQUFLLFVBQVUsQ0FBQyxDQUFFLE9BQU8sSUFBSSxHQUFHLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztZQUNwRCxPQUFPLENBQUMsQ0FBVSxPQUFPLElBQUksQ0FBQztTQUMvQjtJQUNILENBQUM7SUFFRDs7Ozs7OzBGQU1zRjtJQUM5RSxvQkFBb0IsQ0FBQyxRQUFnQixFQUFFLEdBQVcsRUFBRSxLQUFlO1FBQ3pFLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFO1lBQUUsT0FBTztRQUN6QixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU07WUFBRSxPQUFPO1FBQzFCLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLDZCQUE2QixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzFELEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLGlDQUFpQyxDQUFDLENBQUM7U0FDMUQ7YUFBTTtZQUNMLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUUsSUFBSSxVQUFVLENBQUMsSUFBSSxFQUFFO2dCQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLE1BQU0sVUFBVSxLQUFLLENBQUMsQ0FBQztTQUNyRTtJQUNILENBQUM7SUFFRDtzR0FDa0c7SUFDMUYsa0JBQWtCLENBQUMsR0FBVyxFQUFFLEtBQWE7UUFDbkQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDO1lBQzdCLElBQUksR0FBRyxHQUFHLElBQUksZ0NBQWdDO1lBQzlDLElBQUksR0FBRyxHQUFHLElBQUksOEJBQThCO1lBQzVDLElBQUksR0FBRyxHQUFHLElBQUksaUNBQWlDO1NBQ2hELENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2IsUUFBUSxLQUFLLEVBQUU7WUFDYixLQUFLLFNBQVMsQ0FBQyxDQUFHLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xDLEtBQUssV0FBVyxDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDO1lBQzFFLEtBQUssU0FBUyxDQUFDLENBQUcsT0FBTyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxJQUFJLENBQUMsb0JBQW9CLENBQUMsRUFBRSxDQUFDO1lBQ25GLEtBQUssVUFBVSxDQUFDLENBQUUsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDOUMsS0FBSyxVQUFVLENBQUMsQ0FBRSxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUMvQyxPQUFPLENBQUMsQ0FBVSxPQUFPLElBQUksQ0FBQztTQUMvQjtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssYUFBYSxDQUFDLEdBQVcsRUFBRSxHQUFzQjtRQUN2RCxNQUFNLEtBQUssR0FBYSxFQUFFLENBQUM7UUFFM0IsZ0ZBQWdGO1FBQ2hGLEVBQUU7UUFDRixzRkFBc0Y7UUFDdEYsdUZBQXVGO1FBQ3ZGLHFGQUFxRjtRQUNyRix3RkFBd0Y7UUFDeEYsbURBQW1EO1FBQ25ELEtBQUssQ0FBQyxJQUFJLENBQ1IsSUFBSSxHQUFHLGdGQUFnRjtZQUN2Rix1QkFBdUIsQ0FDeEIsQ0FBQztRQUNGLEtBQUssQ0FBQyxJQUFJLENBQ1IsSUFBSSxHQUFHLGdGQUFnRjtZQUN2Rix3QkFBd0IsQ0FDekIsQ0FBQztRQUNGLEVBQUU7UUFDRix1RkFBdUY7UUFDdkYsbUZBQW1GO1FBQ25GLHdGQUF3RjtRQUN4Riw4RUFBOEU7UUFDOUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQWtCLENBQUM7UUFDbkMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsWUFBWSxLQUFLLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFGLE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDLFlBQVksS0FBSyx5QkFBeUIsQ0FBQyxNQUFNLENBQUM7ZUFDdEUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLEtBQUssQ0FBQyxDQUFDO1FBQ2hFLEtBQUssQ0FBQyxJQUFJLENBQ1IsSUFBSSxHQUFHLHNDQUFzQyxTQUFTO1lBQ3BELENBQUMsQ0FBQyxzRUFBc0U7WUFDeEUsQ0FBQyxDQUFDLGdCQUFnQixJQUFJLENBQ3pCLENBQUM7UUFDRixLQUFLLENBQUMsSUFBSSxDQUNSLElBQUksR0FBRyxzQ0FBc0MsU0FBUztZQUNwRCxDQUFDLENBQUMsc0VBQXNFO1lBQ3hFLENBQUMsQ0FBQyxnQkFBZ0IsSUFBSSxDQUN6QixDQUFDO1FBQ0YsdUZBQXVGO1FBQ3ZGLDZGQUE2RjtRQUM3RixLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxzQ0FBc0MsQ0FBQyxDQUFDO1FBQzFELHdGQUF3RjtRQUN4RixvRkFBb0Y7UUFDcEYsNEZBQTRGO1FBQzVGLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLGtEQUFrRCxDQUFDLENBQUM7UUFFdEUsS0FBSyxNQUFNLEVBQUUsSUFBSSxRQUFRLEVBQUU7WUFDekIsTUFBTSxNQUFNLEdBQUcsaUJBQWlCLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDckMsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTFELEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFO2dCQUMxQixNQUFNLEdBQUcsR0FBRyxFQUFFLEdBQUcsS0FBSyxDQUFDO2dCQUN2QixNQUFNLFVBQVUsR0FBdUIsb0JBQW9CLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2pFLE1BQU0sT0FBTyxHQUF3QixHQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBRXRELElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFO29CQUFFLFNBQVM7Z0JBRXRELEtBQUssTUFBTSxDQUFDLElBQUksT0FBTyxFQUFFO29CQUN2QixNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQ3JCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO29CQUMxRCxJQUFJLENBQUMsUUFBUTt3QkFBRSxTQUFTO29CQUV4QixJQUFJLFVBQVUsRUFBRSxJQUFJLEVBQUU7d0JBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsTUFBTSxVQUFVLElBQUksQ0FBQyxDQUFDO29CQUNwRSxJQUFJLE9BQU8sRUFBRSxJQUFJLEVBQUU7d0JBQUssS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsTUFBTSxPQUFPLElBQUksQ0FBQyxDQUFDO29CQUVqRSxtRkFBbUY7b0JBQ25GLG1GQUFtRjtvQkFDbkYsa0ZBQWtGO29CQUNsRiwrRUFBK0U7b0JBQy9FLDJFQUEyRTtvQkFDM0UsSUFBSSxFQUFFLEtBQUssV0FBVyxFQUFFO3dCQUN0QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO3dCQUN2RCxJQUFJLFVBQVUsRUFBRTs0QkFDZCxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxFQUFFLFVBQVUsSUFBSSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7NEJBQy9ELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLEVBQUUsT0FBTyxJQUFJLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQzt5QkFDN0Q7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGO1FBRUQsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFFRCx1RkFBdUY7SUFDL0Usa0JBQWtCO1FBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFDM0IsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPO1FBRXJCLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLGlCQUFpQixFQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssV0FBVyxDQUFDLENBQUM7UUFDaEYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLFVBQVUsS0FBSyxTQUFTLENBQUMsQ0FBQztRQUU5RSxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFO1lBQ2xDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUMvQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDakQsT0FBTztTQUNSO1FBQ0QsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLFVBQVUsRUFBRTtZQUNsQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDaEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2hELE9BQU87U0FDUjtRQUNELElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxXQUFXLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUU7WUFDckcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2hELElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNqRCxPQUFPO1NBQ1I7UUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNwRyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFdEQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRSxJQUFJLElBQUksRUFBRSxPQUFPLEVBQUU7WUFDakIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQzVFO2FBQU07WUFDTCxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDakQ7SUFDSCxDQUFDO0lBRU8sV0FBVyxDQUFDLEVBQVcsRUFBRSxHQUFXLEVBQUUsU0FBa0I7UUFDOUQsSUFBSSxTQUFTO1lBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDOztZQUMxQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVPLHFCQUFxQjtRQUMzQixJQUFJLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxDQUFDO1FBQzlCLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUU7WUFDN0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBQUM7U0FDcEc7SUFDSCxDQUFDO0lBRUQsWUFBWTtRQUNWLFFBQVEsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDbkMsS0FBSyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUksT0FBTyxPQUFPLENBQUM7WUFDM0MsS0FBSyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUM7WUFDOUMsS0FBSyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxLQUFLLENBQUM7WUFDekMsS0FBSyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQU0sT0FBTyxLQUFLLENBQUM7WUFDekMsT0FBTyxDQUFDLENBQW9CLE9BQU8sTUFBTSxDQUFDO1NBQzNDO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1NBQ3pIO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLGNBQWMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsY0FBYyxJQUFJLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFO1lBQ3BLLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxvQkFBb0IsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUMvSDtRQUNELElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUU7WUFDeEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsb0JBQW9CLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDekgsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUU7Z0JBQ3hELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUM7YUFDckM7U0FDRjtRQUNELElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsY0FBYyxJQUFJLGtCQUFrQixDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFO1lBQzlHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUM7U0FDdEU7SUFDSCxDQUFDO0lBRUQsbUJBQW1CO1FBQ2pCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRTtZQUN2QixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDckM7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUU7WUFDekIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3JDO0lBQ0gsQ0FBQzs7d0hBcFRVLDBCQUEwQjs0R0FBMUIsMEJBQTBCLHVSQzdDdkMsOGlEQTRDQTs0RkRDYSwwQkFBMEI7a0JBTHRDLFNBQVM7K0JBQ0UscUJBQXFCO2dHQVV0QixLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBS0ksWUFBWTtzQkFBckIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBSZW5kZXJlcjIsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgUmVjb3JkIH0gZnJvbSAnLi4vLi4vLi4vLi4vbW9kZWxzL3JlY29yZC5tb2RlbCc7XHJcbmltcG9ydCB7IFRleHRGaWVsZEljb25Qb3NpdGlvbkVudW0sIFRleHRGaWVsZFN0eWxlQ1NTLCBUZXh0TWFza0VudW0sIFRleHRGaWVsZCB9IGZyb20gJy4uLy4uLy4uLy4uL21vZGVscy9maWVsZHMvdGV4dEZpZWxkLm1vZGVsJztcclxuaW1wb3J0IHsgSUJhc2VGaWVsZENvbXBvbmVudCB9IGZyb20gJy4uLy4uLy4uLy4uL2ludGVyZmFjZXMvaUJhc2VGaWVsZENvbXBvbmVudC5pbnRlcmZhY2UnO1xyXG5pbXBvcnQgeyBVdGlsaXR5SGVscGVyU2VydmljZSB9IGZyb20gJy4uLy4uLy4uLy4uL3NlcnZpY2VzL3V0aWxpdHlIZWxwZXIuc2VydmljZXMnO1xyXG5pbXBvcnQgeyBpbnRlcnZhbCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IERhdGFHZXR0ZXJUeXBlRW51bSB9IGZyb20gJy4uLy4uLy4uLy4uL21vZGVscy9iYXNlRmllbGQubW9kZWwnO1xyXG5pbXBvcnQgeyBDYXBhY2l0b3IgfSBmcm9tICdAY2FwYWNpdG9yL2NvcmUnO1xyXG5cclxuLy8gU2VsZXR0b3JpIENTUyBNREMgKEFuZ3VsYXIgTWF0ZXJpYWwgMTUpLlxyXG4vLyBDb250YWluZXIg4oaSIC5tYXQtbWRjLXRleHQtZmllbGQtd3JhcHBlcjogYm94IHZpc3VhbGUgZXN0ZXJubyBkZWwgY2FtcG8gb3V0bGluZWRcclxuLy8gICAoZXNjbHVzbyAubWF0LW1kYy1mb3JtLWZpZWxkLXN1YnNjcmlwdC13cmFwcGVyKS4gR2VzdGlzY2Ugc2ZvbmRvLCBib3JkbywgYm9yZGVyLXJhZGl1cyBlc3Rlcm5vLlxyXG4vLyAgIExlIHJlZ29sZSBkaSBDb250YWluZXIgdmVuZ29ubyBkdXBsaWNhdGUgYW5jaGUgc3VpIC5tZGMtbm90Y2hlZC1vdXRsaW5lX18qIHBlciBwZXJtZXR0ZXJlXHJcbi8vICAgZGkgc292cmFzY3JpdmVyZSBpbCBib3JkbyBkaSBmb2N1cy9ob3ZlciBkaSBNYXRlcmlhbCBjb24gbGEgcHJvcHJpZXTDoCBib3JkZXItY29sb3IgZGVsbCd1dGVudGUuXHJcbi8vIElucHV0IOKGkiAubWF0LW1kYy1mb3JtLWZpZWxkLWluZml4OiBhcmVhIGludGVybmEgZG92ZSBzaSBkaWdpdGEgaWwgdGVzdG8uXHJcbi8vICAgSW5kaXBlbmRlbnRlIGRhIENvbnRhaW5lcjogaWwgc3VvIGJhY2tncm91bmQgbm9uIGNvcHJlIGlsIGJveCBlc3Rlcm5vLlxyXG4vLyBJY29uYSDihpIgY29udGFpbmVyIHByZWZpeCArIHN1ZmZpeCAoYWxpZ24tc2VsZjogc3RyZXRjaCBpbmlldHRhdG8gc3RydXR0dXJhbG1lbnRlKS5cclxuLy8gTWljcm9mb25vIOKGkiBzdGVzc28gY29udGFpbmVyIHN1ZmZpeCAodmllbmUgZG9wbyBJY29uYSBuZWwgbG9vcCwgc292cmFzY3JpdmUgcGVyIGlsIHN1ZmZpeCkuXHJcbmNvbnN0IEVMRU1FTlRfU0VMRUNUT1JTOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdIH0gPSB7XHJcbiAgQ29udGFpbmVyOiAnIC5tYXQtbWRjLXRleHQtZmllbGQtd3JhcHBlcicsXHJcbiAgSW5wdXQ6ICcgLm1hdC1tZGMtZm9ybS1maWVsZC1pbmZpeCcsXHJcbiAgRGVzY3JpemlvbmU6ICcgbGFiZWwubWF0LW1kYy1mbG9hdGluZy1sYWJlbCcsXHJcbiAgSWNvbmE6IFsnIC5tYXQtbWRjLWZvcm0tZmllbGQtaWNvbi1wcmVmaXgnLCAnIC5tYXQtbWRjLWZvcm0tZmllbGQtaWNvbi1zdWZmaXgnXSxcclxuICBNaWNyb2Zvbm86ICcgLm1hdC1tZGMtZm9ybS1maWVsZC1pY29uLXN1ZmZpeCcsXHJcbiAgRXJyb3JlOiAnIG1hdC1lcnJvcicsXHJcbn07XHJcbmNvbnN0IEVMRU1FTlRTID0gT2JqZWN0LmtleXMoRUxFTUVOVF9TRUxFQ1RPUlMpO1xyXG5jb25zdCBTVEFURVMgPSBbJ05vcm1hbGUnLCAnTW91c2VvdmVyJywgJ0ZvY3VzZWQnLCAnTm90VmFsaWQnLCAnUmVhZG9ubHknXTtcclxuXHJcbi8vIFN0aWxpIGRpIGRlZmF1bHQgcGVyIGVsZW1lbnRvK3N0YXRvOiBlbWVzc2kgcHJpbWEgZGVsbGUgcmVnb2xlIHV0ZW50ZSxcclxuLy8gY2hlIGxlIHNvdnJhc2NyaXZvbm8gcGVyIGVmZmV0dG8gZGVsIGNhc2NhZGUgQ1NTIChzdGVzc2Egc3BlY2lmaWNpdMOgICN1aWQsIHBvc2l6aW9uZSBzdWNjZXNzaXZhKS5cclxuY29uc3QgREVGQVVMVF9GSUVMRF9TVFlMRVM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XHJcbiAgRGVzY3JpemlvbmVOb3JtYWxlOiAnZm9udC1zaXplOiB4LWxhcmdlOycsXHJcbiAgLy8gSWwgd3JhcHBlciBvdXRsaW5lZCBoYSBvdmVyZmxvdzp2aXNpYmxlLCBxdWluZGkgc2VuemEgYm9yZGVyLXJhZGl1cyBpbCBiYWNrZ3JvdW5kXHJcbiAgLy8gbm9uIHJpc3BldHRlcmViYmUgZ2xpIGFuZ29saSBhcnJvdG9uZGF0aSBkZWwgbm90Y2hlZC1vdXRsaW5lICg0cHggZGVmYXVsdCBBbmd1bGFyIE1hdGVyaWFsKS5cclxuICBDb250YWluZXJOb3JtYWxlOiAnYm9yZGVyLXJhZGl1czogNHB4OycsXHJcbiAgLy8gUmllbnRyYSBpbCB0ZXN0byBkYWxsYSBzaW5pc3RyYSBkZWxsJ2luZml4IChwYWRkaW5nLWxlZnQgcmltb3NzbyBkYWwgd3JhcHBlciBjb24gaWwgZml4IGljb25lKS5cclxuICBJbnB1dE5vcm1hbGU6ICdwYWRkaW5nLWxlZnQ6IDVweDsnLFxyXG59O1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICd0ZXh0LWZpZWxkLXRlbXBsYXRlJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vdGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vdGV4dC1maWVsZC10ZW1wbGF0ZS5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUZXh0RmllbGRUZW1wbGF0ZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIElCYXNlRmllbGRDb21wb25lbnQge1xyXG4gIGlzU3RpbGxSZWNvZ2luemUgPSBmYWxzZTtcclxuICBzb3VyY2UgPSBpbnRlcnZhbCgyMDApO1xyXG4gIG5ld3RleHQ6IHN0cmluZztcclxuICBzdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgQElucHV0KCkgZmllbGQ6IFRleHRGaWVsZDtcclxuICBASW5wdXQoKSByZWNvcmQ6IFJlY29yZDtcclxuICBASW5wdXQoKSBmb3JtdWxhT2JqZWN0OiBhbnkgPSB7fTtcclxuICBASW5wdXQoKSBpbkNvbmZpZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8qKiBJbmNyZW1lbnRhIGRhbGwnZXN0ZXJubyBwZXIgZm9yemFyZSBpbCByaWNhbGNvbG8gZGVnbGkgc3RpbGkgQ1NTIChlcy4gZGFsIGNvbmZpZ3VyYXRvcmUpICovXHJcbiAgQElucHV0KCkgc3R5bGVWZXJzaW9uOiBudW1iZXIgPSAwO1xyXG4gIC8qKiBGb3J6YSB2aXNpdmFtZW50ZSB1bm8gc3RhdG8gc3BlY2lmaWNvIG5lbGwnYW50ZXByaW1hIGRlbCBjb25maWd1cmF0b3JlICovXHJcbiAgQElucHV0KCkgZm9yY2VTdGF0ZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIEZpZWxkc3R5bGVPYmo6IGFueTtcclxuICBMYWJlbHN0eWxlT2JqOiBhbnk7XHJcblxyXG4gIEBPdXRwdXQoKSByZWNvcmRDaGFuZ2U6IEV2ZW50RW1pdHRlcjxSZWNvcmQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxSZWNvcmQ+KCk7XHJcbiAgSW5wdXRNYXNrRW51bSA9IFRleHRNYXNrRW51bTtcclxuICBUZXh0RmllbGRJY29uUG9zaXRpb25FbnVtID0gVGV4dEZpZWxkSWNvblBvc2l0aW9uRW51bTtcclxuXHJcbiAgcGxhdGZvcm06IHN0cmluZyA9IENhcGFjaXRvci5nZXRQbGF0Zm9ybSgpO1xyXG5cclxuICBmaWVsZFVpZDogc3RyaW5nO1xyXG4gIHByaXZhdGUgc3R5bGVFbDogSFRNTFN0eWxlRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgc3RhdHVzU3ViOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyKSB7fVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuZmllbGRVaWQgPSAndGYtJyArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnNsaWNlKDIsIDEwKTtcclxuICAgIHRoaXMudXBkYXRlRmllbGQoKTtcclxuICAgIHRoaXMuaW5pdFN0eWxlcygpO1xyXG4gICAgdGhpcy5pbmplY3RUZXh0RmllbGRTdHlsZXMoKTtcclxuICAgIHRoaXMuc3Vic2NyaWJlVG9Gb3JtU3RhdHVzKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICBpZiAoY2hhbmdlc1snc3R5bGVWZXJzaW9uJ10gJiYgIWNoYW5nZXNbJ3N0eWxlVmVyc2lvbiddLmZpcnN0Q2hhbmdlKSB7XHJcbiAgICAgIHRoaXMuaW5qZWN0VGV4dEZpZWxkU3R5bGVzKCk7XHJcbiAgICAgIHRoaXMudXBkYXRlU3RhdGVDbGFzc2VzKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1snZm9yY2VTdGF0ZSddKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlU3RhdGVDbGFzc2VzKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1sncmVjb3JkJ10gIT0gdW5kZWZpbmVkICYmIGNoYW5nZXNbJ3JlY29yZCddLmZpcnN0Q2hhbmdlID09IGZhbHNlXHJcbiAgICAgICYmIEpTT04uc3RyaW5naWZ5KGNoYW5nZXNbJ3JlY29yZCddLmN1cnJlbnRWYWx1ZSkgIT0gSlNPTi5zdHJpbmdpZnkoY2hhbmdlc1sncmVjb3JkJ10ucHJldmlvdXNWYWx1ZSkpIHtcclxuICAgICAgdGhpcy5yZWNvcmQgPSBjaGFuZ2VzWydyZWNvcmQnXS5jdXJyZW50VmFsdWU7XHJcbiAgICAgIHRoaXMudXBkYXRlRmllbGQoKTtcclxuICAgICAgdGhpcy51cGRhdGVTdGF0ZUNsYXNzZXMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuc3R5bGVFbD8ucGFyZW50Tm9kZSkge1xyXG4gICAgICB0aGlzLnN0eWxlRWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLnN0eWxlRWwpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5zdGF0dXNTdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG5cclxuICBpbml0U3R5bGVzKCkge1xyXG4gICAgaWYgKHRoaXMuZmllbGQuRmllbGRzdHlsZUNTUyAhPSBudWxsIHx8IHRoaXMuZmllbGQuRmllbGRzdHlsZUNTUyAhPSB1bmRlZmluZWQpXHJcbiAgICAgIHRoaXMuRmllbGRzdHlsZU9iaiA9IFV0aWxpdHlIZWxwZXJTZXJ2aWNlLmluaXRTdHlsZXModGhpcy5maWVsZC5GaWVsZHN0eWxlQ1NTKTtcclxuICAgIGlmICh0aGlzLmZpZWxkLkxhYmVsc3R5bGVDU1MgIT0gbnVsbCB8fCB0aGlzLmZpZWxkLkxhYmVsc3R5bGVDU1MgIT0gdW5kZWZpbmVkKVxyXG4gICAgICB0aGlzLkxhYmVsc3R5bGVPYmogPSBVdGlsaXR5SGVscGVyU2VydmljZS5pbml0U3R5bGVzKHRoaXMuZmllbGQuTGFiZWxzdHlsZUNTUyk7XHJcbiAgfVxyXG5cclxuICAvKiogUmlnZW5lcmEgaWwgdGFnIDxzdHlsZT4gY29uIGRlZmF1bHRzICsgcmVnb2xlIHV0ZW50ZSwgZW50cmFtYmkgc2NvcGVkIHBlciAjdWlkICovXHJcbiAgaW5qZWN0VGV4dEZpZWxkU3R5bGVzKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmZpZWxkVWlkKSByZXR1cm47XHJcbiAgICBjb25zdCBjc3MgPSAodGhpcy5maWVsZCBhcyBUZXh0RmllbGQpPy5UZXh0RmllbGRTdHlsZUNTUyA/PyAoe30gYXMgVGV4dEZpZWxkU3R5bGVDU1MpO1xyXG4gICAgbGV0IHJ1bGVzID0gdGhpcy5idWlsZENzc1J1bGVzKHRoaXMuZmllbGRVaWQsIGNzcyk7XHJcbiAgICAvLyBJbiBhbnRlcHJpbWEgY29uZmlndXJhdG9yZSBsYSBzcGF6aWF0dXJhIGluZmVyaW9yZSBkZWwgc3Vic2NyaXB0LXdyYXBwZXIgw6ggaW5kZXNpZGVyYXRhOlxyXG4gICAgLy8gZXNpc3RlIHBlciBpbCBsYXlvdXQgZGVsIGZvcm0gdmVybyBtYSBuZWwgcGFubmVsbG8gZGkgY29uZmlndXJhemlvbmUgY29tcHJpbWUgbCdhbnRlcHJpbWEuXHJcbiAgICBpZiAodGhpcy5pbkNvbmZpZykge1xyXG4gICAgICBydWxlcyArPSBgXFxuIyR7dGhpcy5maWVsZFVpZH0gLm1hdC1tZGMtZm9ybS1maWVsZC1zdWJzY3JpcHQtd3JhcHBlciB7IGRpc3BsYXk6IG5vbmU7IH1gO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5zdHlsZUVsKSB7XHJcbiAgICAgIHRoaXMuc3R5bGVFbCA9IHRoaXMucmVuZGVyZXIuY3JlYXRlRWxlbWVudCgnc3R5bGUnKSBhcyBIVE1MU3R5bGVFbGVtZW50O1xyXG4gICAgICB0aGlzLnN0eWxlRWwuaWQgPSAnc3R5bGUtJyArIHRoaXMuZmllbGRVaWQ7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuaGVhZCwgdGhpcy5zdHlsZUVsKTtcclxuICAgIH1cclxuICAgIHRoaXMuc3R5bGVFbC50ZXh0Q29udGVudCA9IHJ1bGVzO1xyXG4gIH1cclxuXHJcbiAgLyoqIENvc3RydWlzY2UgaWwgc2VsZXR0b3JlIENTUyBwZXIgdW4gZGF0byBlbGVtZW50byBlIHN0YXRvICovXHJcbiAgcHJpdmF0ZSBnZXRTZWxlY3Rvcih1aWQ6IHN0cmluZywgX2VsOiBzdHJpbmcsIHN0YXRlOiBzdHJpbmcsIHM6IHN0cmluZywgX3N1Yjogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBzd2l0Y2ggKHN0YXRlKSB7XHJcbiAgICAgIGNhc2UgJ05vcm1hbGUnOiAgIHJldHVybiBgIyR7dWlkfSR7c31gO1xyXG4gICAgICBjYXNlICdNb3VzZW92ZXInOiByZXR1cm4gYCMke3VpZH06aG92ZXIke3N9LCAjJHt1aWR9LmVxcC1zdGF0ZS1ob3ZlciR7c31gO1xyXG4gICAgICBjYXNlICdGb2N1c2VkJzogICByZXR1cm4gYCMke3VpZH06Zm9jdXMtd2l0aGluJHtzfSwgIyR7dWlkfS5lcXAtc3RhdGUtZm9jdXNlZCR7c31gO1xyXG4gICAgICBjYXNlICdOb3RWYWxpZCc6ICByZXR1cm4gYCMke3VpZH0uZXFwLWludmFsaWQke3N9YDtcclxuICAgICAgY2FzZSAnUmVhZG9ubHknOiAgcmV0dXJuIGAjJHt1aWR9LmVxcC1yZWFkb25seSR7c31gO1xyXG4gICAgICBkZWZhdWx0OiAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBQcm9wYWdhIGdsaSBzdGlsaSBib3JkZXIgZGkgQ29udGFpbmVyIGFpIHNlZ21lbnRpIGRlbCBib3JkbyBNREMgKGxlYWRpbmcvbm90Y2gvdHJhaWxpbmcpXHJcbiAgICogIGNvbiBsb2dpY2EgZGlmZmVyZW56aWF0YSBwZXIgZXZpdGFyZSBpbCBkb3BwaW8gYm9yZG86XHJcbiAgICogIC0gYGJvcmRlcmAgc2hvcnRoYW5kIG8gYGJvcmRlci13aWR0aGAg4oaSIGlsIGJvcmRvIHZpc2l2byDDqCBnacOgIHN1bCB3cmFwcGVyIOKGkiBpIHNlZ21lbnRpXHJcbiAgICogICAgdmVuZ29ubyBzb3BwcmVzc2kgY29uIGJvcmRlci1jb2xvcjp0cmFuc3BhcmVudC5cclxuICAgKiAgLSBTb2xvIGBib3JkZXItY29sb3JgIOKGkiBhcHBsaWNhdG8gYWkgc2VnbWVudGkgcGVyIHNvdnJhc2NyaXZlcmUgaWwgcmluZyBibHUvaG92ZXIgZGlcclxuICAgKiAgICBNYXRlcmlhbCAoc3BlY2lmaWNpdMOgICN1aWQgPiBzcGVjaWZpY2l0w6AgZGkgY2xhc3NlIE1hdGVyaWFsKS5cclxuICAgKiAgLSBgYm9yZGVyLXJhZGl1c2AgZSBhbHRyZSBwcm9wcmlldMOgIGJvcmRlci0qIG5vbiB2ZW5nb25vIHByb3BhZ2F0ZSBhaSBzZWdtZW50aS4gKi9cclxuICBwcml2YXRlIGFwcGx5Qm9yZGVyVG9PdXRsaW5lKHNlbGVjdG9yOiBzdHJpbmcsIGNzczogc3RyaW5nLCBsaW5lczogc3RyaW5nW10pOiB2b2lkIHtcclxuICAgIGlmICghY3NzPy50cmltKCkpIHJldHVybjtcclxuICAgIGNvbnN0IGRlY2xzID0gY3NzLnNwbGl0KCc7JykubWFwKGQgPT4gZC50cmltKCkpLmZpbHRlcihkID0+IC9eYm9yZGVyL2kudGVzdChkKSAmJiBkLmxlbmd0aCA+IDApO1xyXG4gICAgaWYgKCFkZWNscy5sZW5ndGgpIHJldHVybjtcclxuICAgIGlmIChkZWNscy5zb21lKGQgPT4gL15ib3JkZXIoPyEtKGNvbG9yfHJhZGl1cykpL2kudGVzdChkKSkpIHtcclxuICAgICAgbGluZXMucHVzaChgJHtzZWxlY3Rvcn0geyBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50OyB9YCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCBjb2xvckRlY2xzID0gZGVjbHMuZmlsdGVyKGQgPT4gL15ib3JkZXItY29sb3IvaS50ZXN0KGQpKS5qb2luKCc7ICcpO1xyXG4gICAgICBpZiAoY29sb3JEZWNscy50cmltKCkpIGxpbmVzLnB1c2goYCR7c2VsZWN0b3J9IHsgJHtjb2xvckRlY2xzfTsgfWApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFNlbGV0dG9yZSBjb21iaW5hdG8gcGVyIGkgdHJlIHNlZ21lbnRpIGRlbCBib3JkbyBNREMgb3V0bGluZWQgKGxlYWRpbmcsIG5vdGNoLCB0cmFpbGluZykuXHJcbiAgICogIFVzYXRvIHBlciBkdXBsaWNhcmUgaWwgQ1NTIGRpIENvbnRhaW5lciBzdWwgYm9yZG8gdmlzdWFsZSBlIHBlcm1ldHRlcmUgbCdvdmVycmlkZSBkZWwgcmluZy4gKi9cclxuICBwcml2YXRlIGdldE91dGxpbmVTZWxlY3Rvcih1aWQ6IHN0cmluZywgc3RhdGU6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgY29uc3Qgc2VncyA9IChwcmVmOiBzdHJpbmcpID0+IFtcclxuICAgICAgYCMke3VpZH0ke3ByZWZ9IC5tZGMtbm90Y2hlZC1vdXRsaW5lX19sZWFkaW5nYCxcclxuICAgICAgYCMke3VpZH0ke3ByZWZ9IC5tZGMtbm90Y2hlZC1vdXRsaW5lX19ub3RjaGAsXHJcbiAgICAgIGAjJHt1aWR9JHtwcmVmfSAubWRjLW5vdGNoZWQtb3V0bGluZV9fdHJhaWxpbmdgLFxyXG4gICAgXS5qb2luKCcsICcpO1xyXG4gICAgc3dpdGNoIChzdGF0ZSkge1xyXG4gICAgICBjYXNlICdOb3JtYWxlJzogICByZXR1cm4gc2VncygnJyk7XHJcbiAgICAgIGNhc2UgJ01vdXNlb3Zlcic6IHJldHVybiBgJHtzZWdzKCc6aG92ZXInKX0sICR7c2VncygnLmVxcC1zdGF0ZS1ob3ZlcicpfWA7XHJcbiAgICAgIGNhc2UgJ0ZvY3VzZWQnOiAgIHJldHVybiBgJHtzZWdzKCc6Zm9jdXMtd2l0aGluJyl9LCAke3NlZ3MoJy5lcXAtc3RhdGUtZm9jdXNlZCcpfWA7XHJcbiAgICAgIGNhc2UgJ05vdFZhbGlkJzogIHJldHVybiBzZWdzKCcuZXFwLWludmFsaWQnKTtcclxuICAgICAgY2FzZSAnUmVhZG9ubHknOiAgcmV0dXJuIHNlZ3MoJy5lcXAtcmVhZG9ubHknKTtcclxuICAgICAgZGVmYXVsdDogICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbWV0dGUgaSBkZWZhdWx0IHByaW1hLCBpIHZhbG9yaSB1dGVudGUgZG9wby5cclxuICAgKiBTdGVzc2Egc3BlY2lmaWNpdMOgICN1aWQg4oaSIGlsIHZhbG9yZSB1dGVudGUgdmluY2UgcGVyIHBvc2l6aW9uZSBuZWwgY2FzY2FkZS5cclxuICAgKiBJY29uYSBoYSBkdWUgc2VsZXR0b3JpIChwcmVmaXggKyBzdWZmaXgpOiBsYSBzdGVzc2EgcmVnb2xhIHZpZW5lIGVtZXNzYSBwZXIgZW50cmFtYmkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBidWlsZENzc1J1bGVzKHVpZDogc3RyaW5nLCBjc3M6IFRleHRGaWVsZFN0eWxlQ1NTKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8vIEZpeCBzdHJ1dHR1cmFsZSBpY29uZSDigJQgdHV0dG8gc2NvcGVkIGEgI3VpZCBwZXIgbm9uIHRvY2NhcmUgYWx0cmkgY29tcG9uZW50aTpcclxuICAgIC8vXHJcbiAgICAvLyAxLiBNYXRlcmlhbCBhcHBsaWNhIC5tYXQtbWRjLWZvcm0tZmllbGQtaGFzLWljb24tc3VmZml4IC5tYXQtbWRjLXRleHQtZmllbGQtd3JhcHBlclxyXG4gICAgLy8gICAgeyBwYWRkaW5nLXJpZ2h0OiAwIH0gbWEgbGFzY2lhIGlsIHBhZGRpbmctbGVmdCBpbnRhdHRvLiBRdWVsIHBhZGRpbmctbGVmdCByZXNpZHVvXHJcbiAgICAvLyAgICBjcmVhIHVubyBzdHJpcCBjb2xvcmF0byBhIHNpbmlzdHJhIHNlIENvbnRhaW5lciBoYSB1biBiYWNrZ3JvdW5kLiBMbyBhenplcmlhbW8uXHJcbiAgICAvLyAgICAobWF0LW1kYy1mb3JtLWZpZWxkLWhhcy1pY29uLXN1ZmZpeCDDqCBzZW1wcmUgcHJlc2VudGUgcGVyY2jDqSBpbCBtaWNyb2Zvbm8gw6ggc2VtcHJlXHJcbiAgICAvLyAgICB1biBtYXRTdWZmaXggbmVsIERPTSwgYW5jaGUgcXVhbmRvIFtoaWRkZW5dLilcclxuICAgIGxpbmVzLnB1c2goXHJcbiAgICAgIGAjJHt1aWR9IG1hdC1mb3JtLWZpZWxkLm1hdC1tZGMtZm9ybS1maWVsZC1oYXMtaWNvbi1zdWZmaXggLm1hdC1tZGMtdGV4dC1maWVsZC13cmFwcGVyYCArXHJcbiAgICAgIGAgeyBwYWRkaW5nLWxlZnQ6IDA7IH1gXHJcbiAgICApO1xyXG4gICAgbGluZXMucHVzaChcclxuICAgICAgYCMke3VpZH0gbWF0LWZvcm0tZmllbGQubWF0LW1kYy1mb3JtLWZpZWxkLWhhcy1pY29uLXByZWZpeCAubWF0LW1kYy10ZXh0LWZpZWxkLXdyYXBwZXJgICtcclxuICAgICAgYCB7IHBhZGRpbmctcmlnaHQ6IDA7IH1gXHJcbiAgICApO1xyXG4gICAgLy9cclxuICAgIC8vIDIuIFByZWZpeDogTWF0ZXJpYWwgZGVmYXVsdCDDqCBwYWRkaW5nOiAwIDRweCAwIDAg4oCUIHF1ZWwgNHB4IGNyZWEgbG8gc3RyaXAgYSBzaW5pc3RyYVxyXG4gICAgLy8gICAgYW5jaGUgc2VuemEgaWNvbmEuIExvIGF6emVyaWFtbyBzZW1wcmUuIFF1YW5kbyBsJ2ljb25hIG5vbiBjJ8OoOiBkaXNwbGF5Om5vbmUuXHJcbiAgICAvLyAzLiBTdWZmaXg6IHF1YW5kbyBub24gYyfDqCBuw6kgaWNvbmEgZGVzdHJhIG7DqSBtaWNyb2Zvbm8gYXR0aXZvOiBkaXNwbGF5Om5vbmUgKE1hdGVyaWFsXHJcbiAgICAvLyAgICBsYXNjaWEgZGlzcGxheTpmbGV4IHN1bCBjb250YWluZXIgYW5jaGUgcXVhbmRvIGlsIGNvbnRlbnV0byDDqCBbaGlkZGVuXSkuXHJcbiAgICBjb25zdCB0ZiA9IHRoaXMuZmllbGQgYXMgVGV4dEZpZWxkO1xyXG4gICAgY29uc3QgaGFzUHJlZml4ID0gISEodGYuSWNvbk5hbWUgJiYgdGYuSWNvblBvc2l0aW9uICE9PSBUZXh0RmllbGRJY29uUG9zaXRpb25FbnVtLkRlc3RyYSk7XHJcbiAgICBjb25zdCBoYXNTdWZmaXggPSAhISh0Zi5JY29uTmFtZSAmJiB0Zi5JY29uUG9zaXRpb24gPT09IFRleHRGaWVsZEljb25Qb3NpdGlvbkVudW0uRGVzdHJhKVxyXG4gICAgICAgICAgICAgICAgICAgIHx8ICEhKHRmLk1pY3JvcGhvbmUgJiYgdGhpcy5wbGF0Zm9ybSA9PT0gJ3dlYicpO1xyXG4gICAgbGluZXMucHVzaChcclxuICAgICAgYCMke3VpZH0gLm1hdC1tZGMtZm9ybS1maWVsZC1pY29uLXByZWZpeCB7ICR7aGFzUHJlZml4XHJcbiAgICAgICAgPyAnYWxpZ24tc2VsZjogc3RyZXRjaDsgZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsgcGFkZGluZzogMDsnXHJcbiAgICAgICAgOiAnZGlzcGxheTogbm9uZTsnfSB9YFxyXG4gICAgKTtcclxuICAgIGxpbmVzLnB1c2goXHJcbiAgICAgIGAjJHt1aWR9IC5tYXQtbWRjLWZvcm0tZmllbGQtaWNvbi1zdWZmaXggeyAke2hhc1N1ZmZpeFxyXG4gICAgICAgID8gJ2FsaWduLXNlbGY6IHN0cmV0Y2g7IGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IHBhZGRpbmc6IDA7J1xyXG4gICAgICAgIDogJ2Rpc3BsYXk6IG5vbmU7J30gfWBcclxuICAgICk7XHJcbiAgICAvLyBJbCAubWRjLW5vdGNoZWQtb3V0bGluZSAocGFyZW50IGRlaSB0cmUgc2VnbWVudGkgZGkgYm9yZG8gTURDKSBub24gZGV2ZSBhdmVyZSBtYWkgdW5cclxuICAgIC8vIGJvcmRvIHByb3ByaW86IGlsIGJvcmRvIHZpc2l2byBkZWwgY2FtcG8gdmllbmUgZGFpIHNlZ21lbnRpIGZpZ2xpIG8gZGFsIHdyYXBwZXIgQ29udGFpbmVyLlxyXG4gICAgbGluZXMucHVzaChgIyR7dWlkfSAubWRjLW5vdGNoZWQtb3V0bGluZSB7IGJvcmRlcjogMDsgfWApO1xyXG4gICAgLy8gQW5ndWxhciBNYXRlcmlhbCBpbXBvc3RhIGNvbG9yIGRpcmV0dGFtZW50ZSBzdWxsJ2lucHV0IChzcGVjaWZpY2l0w6AgMCwzLDApLCBjaGUgYmF0dGVcclxuICAgIC8vIHF1YWxzaWFzaSB2YWxvcmUgZXJlZGl0YXRvIGRhbCB3cmFwcGVyLiBDb24gY29sb3I6aW5oZXJpdCBmb3J6aWFtbyBsJ2VyZWRpdGFyaWV0w6BcclxuICAgIC8vIChzcGVjaWZpY2l0w6AgMSwxLDEgPiAwLDMsMCksIGNvc8OsIGlsIGNvbG9yIGltcG9zdGF0byBzdSBJbnB1dE5vcm1hbGUgc2kgcHJvcGFnYSBhbCB0ZXN0by5cclxuICAgIGxpbmVzLnB1c2goYCMke3VpZH0gaW5wdXQubWF0LW1kYy1pbnB1dC1lbGVtZW50IHsgY29sb3I6IGluaGVyaXQ7IH1gKTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IGVsIG9mIEVMRU1FTlRTKSB7XHJcbiAgICAgIGNvbnN0IHNFbnRyeSA9IEVMRU1FTlRfU0VMRUNUT1JTW2VsXTtcclxuICAgICAgY29uc3Qgc2VsTGlzdCA9IEFycmF5LmlzQXJyYXkoc0VudHJ5KSA/IHNFbnRyeSA6IFtzRW50cnldO1xyXG5cclxuICAgICAgZm9yIChjb25zdCBzdGF0ZSBvZiBTVEFURVMpIHtcclxuICAgICAgICBjb25zdCBrZXkgPSBlbCArIHN0YXRlO1xyXG4gICAgICAgIGNvbnN0IGRlZmF1bHRWYWw6IHN0cmluZyB8IHVuZGVmaW5lZCA9IERFRkFVTFRfRklFTERfU1RZTEVTW2tleV07XHJcbiAgICAgICAgY29uc3QgdXNlclZhbDogc3RyaW5nIHwgdW5kZWZpbmVkID0gKGNzcyBhcyBhbnkpW2tleV07XHJcblxyXG4gICAgICAgIGlmICghZGVmYXVsdFZhbD8udHJpbSgpICYmICF1c2VyVmFsPy50cmltKCkpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IHMgb2Ygc2VsTGlzdCkge1xyXG4gICAgICAgICAgY29uc3Qgc3ViID0gcy50cmltKCk7XHJcbiAgICAgICAgICBjb25zdCBzZWxlY3RvciA9IHRoaXMuZ2V0U2VsZWN0b3IodWlkLCBlbCwgc3RhdGUsIHMsIHN1Yik7XHJcbiAgICAgICAgICBpZiAoIXNlbGVjdG9yKSBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICBpZiAoZGVmYXVsdFZhbD8udHJpbSgpKSBsaW5lcy5wdXNoKGAke3NlbGVjdG9yfSB7ICR7ZGVmYXVsdFZhbH0gfWApO1xyXG4gICAgICAgICAgaWYgKHVzZXJWYWw/LnRyaW0oKSkgICAgbGluZXMucHVzaChgJHtzZWxlY3Rvcn0geyAke3VzZXJWYWx9IH1gKTtcclxuXHJcbiAgICAgICAgICAvLyBQZXIgQ29udGFpbmVyOiBwcm9wYWdhIGxlIHByb3ByaWV0w6AgYm9yZGVyIGFpIHNlZ21lbnRpIE1EQyAobm90Y2hlZC1vdXRsaW5lX18qKS5cclxuICAgICAgICAgIC8vIFNlIGlsIENTUyBpbXBvc3RhIHVubyBzcGVzc29yZSAoYm9yZGVyL2JvcmRlci13aWR0aCkg4oaSIGlsIGJvcmRvIHZpc2l2byDDqCBnacOgIHN1bFxyXG4gICAgICAgICAgLy8gd3JhcHBlciwgaSBzZWdtZW50aSB2ZW5nb25vIHNvcHByZXNzaSAoYm9yZGVyLWNvbG9yOnRyYW5zcGFyZW50KSBwZXIgZXZpdGFyZSBpbFxyXG4gICAgICAgICAgLy8gZG9wcGlvIGJvcmRvLiBTZSBpbXBvc3RhIHNvbG8gYm9yZGVyLWNvbG9yIOKGkiB2aWVuZSBhcHBsaWNhdG8gYWkgc2VnbWVudGkgcGVyXHJcbiAgICAgICAgICAvLyBzb3ZyYXNjcml2ZXJlIGlsIHJpbmcgYmx1L2hvdmVyIGRpIE1hdGVyaWFsIChzcGVjaWZpY2l0w6AgMSwyLDAgPiAwLDIsMCkuXHJcbiAgICAgICAgICBpZiAoZWwgPT09ICdDb250YWluZXInKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG91dGxpbmVTZWwgPSB0aGlzLmdldE91dGxpbmVTZWxlY3Rvcih1aWQsIHN0YXRlKTtcclxuICAgICAgICAgICAgaWYgKG91dGxpbmVTZWwpIHtcclxuICAgICAgICAgICAgICB0aGlzLmFwcGx5Qm9yZGVyVG9PdXRsaW5lKG91dGxpbmVTZWwsIGRlZmF1bHRWYWwgPz8gJycsIGxpbmVzKTtcclxuICAgICAgICAgICAgICB0aGlzLmFwcGx5Qm9yZGVyVG9PdXRsaW5lKG91dGxpbmVTZWwsIHVzZXJWYWwgPz8gJycsIGxpbmVzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcclxuICB9XHJcblxyXG4gIC8qKiBBZ2dpb3JuYSBsZSBjbGFzc2kgZGkgc3RhdG8gc3VsIHdyYXBwZXIgKGVxcC1pbnZhbGlkLCBlcXAtcmVhZG9ubHksIGVxcC1zdGF0ZS0qKSAqL1xyXG4gIHByaXZhdGUgdXBkYXRlU3RhdGVDbGFzc2VzKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmZpZWxkVWlkKSByZXR1cm47XHJcbiAgICBjb25zdCB3cmFwcGVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5maWVsZFVpZCk7XHJcbiAgICBpZiAoIXdyYXBwZXIpIHJldHVybjtcclxuXHJcbiAgICB0aGlzLnRvZ2dsZUNsYXNzKHdyYXBwZXIsICdlcXAtc3RhdGUtaG92ZXInLCAgIHRoaXMuZm9yY2VTdGF0ZSA9PT0gJ01vdXNlb3ZlcicpO1xyXG4gICAgdGhpcy50b2dnbGVDbGFzcyh3cmFwcGVyLCAnZXFwLXN0YXRlLWZvY3VzZWQnLCB0aGlzLmZvcmNlU3RhdGUgPT09ICdGb2N1c2VkJyk7XHJcblxyXG4gICAgaWYgKHRoaXMuZm9yY2VTdGF0ZSA9PT0gJ05vdFZhbGlkJykge1xyXG4gICAgICB0aGlzLnRvZ2dsZUNsYXNzKHdyYXBwZXIsICdlcXAtaW52YWxpZCcsIHRydWUpO1xyXG4gICAgICB0aGlzLnRvZ2dsZUNsYXNzKHdyYXBwZXIsICdlcXAtcmVhZG9ubHknLCBmYWxzZSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmZvcmNlU3RhdGUgPT09ICdSZWFkb25seScpIHtcclxuICAgICAgdGhpcy50b2dnbGVDbGFzcyh3cmFwcGVyLCAnZXFwLXJlYWRvbmx5JywgdHJ1ZSk7XHJcbiAgICAgIHRoaXMudG9nZ2xlQ2xhc3Mod3JhcHBlciwgJ2VxcC1pbnZhbGlkJywgZmFsc2UpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5mb3JjZVN0YXRlID09PSAnTm9ybWFsZScgfHwgdGhpcy5mb3JjZVN0YXRlID09PSAnTW91c2VvdmVyJyB8fCB0aGlzLmZvcmNlU3RhdGUgPT09ICdGb2N1c2VkJykge1xyXG4gICAgICB0aGlzLnRvZ2dsZUNsYXNzKHdyYXBwZXIsICdlcXAtaW52YWxpZCcsIGZhbHNlKTtcclxuICAgICAgdGhpcy50b2dnbGVDbGFzcyh3cmFwcGVyLCAnZXFwLXJlYWRvbmx5JywgZmFsc2UpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgaXNSZWFkb25seSA9IHRoaXMuZmllbGQuUmVhZG9ubHkgfHwgKHRoaXMuZmllbGQuRm9ybXVsYSAhPSBudWxsICYmIHRoaXMuZmllbGQuRm9ybXVsYSAhPT0gJycpO1xyXG4gICAgdGhpcy50b2dnbGVDbGFzcyh3cmFwcGVyLCAnZXFwLXJlYWRvbmx5JywgaXNSZWFkb25seSk7XHJcblxyXG4gICAgY29uc3QgY3RybCA9IHRoaXMuZmllbGQuRm9ybUZvcm1Hcm91cD8uY29udHJvbHM/Llt0aGlzLmZpZWxkLk5hbWVdO1xyXG4gICAgaWYgKGN0cmw/LnRvdWNoZWQpIHtcclxuICAgICAgdGhpcy50b2dnbGVDbGFzcyh3cmFwcGVyLCAnZXFwLWludmFsaWQnLCB0aGlzLmZpZWxkLkZvcm1Gb3JtR3JvdXAuaW52YWxpZCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnRvZ2dsZUNsYXNzKHdyYXBwZXIsICdlcXAtaW52YWxpZCcsIGZhbHNlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgdG9nZ2xlQ2xhc3MoZWw6IEVsZW1lbnQsIGNsczogc3RyaW5nLCBjb25kaXRpb246IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIGlmIChjb25kaXRpb24pIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3MoZWwsIGNscyk7XHJcbiAgICBlbHNlIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3MoZWwsIGNscyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN1YnNjcmliZVRvRm9ybVN0YXR1cygpOiB2b2lkIHtcclxuICAgIHRoaXMuc3RhdHVzU3ViPy51bnN1YnNjcmliZSgpO1xyXG4gICAgaWYgKHRoaXMuZmllbGQ/LkZvcm1Gb3JtR3JvdXApIHtcclxuICAgICAgdGhpcy5zdGF0dXNTdWIgPSB0aGlzLmZpZWxkLkZvcm1Gb3JtR3JvdXAuc3RhdHVzQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy51cGRhdGVTdGF0ZUNsYXNzZXMoKSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXRJbnB1dFR5cGUoKSB7XHJcbiAgICBzd2l0Y2ggKE51bWJlcih0aGlzLmZpZWxkLlRleHRNYXNrKSkge1xyXG4gICAgICBjYXNlIFRleHRNYXNrRW51bS5FbWFpbDogICAgcmV0dXJuICdlbWFpbCc7XHJcbiAgICAgIGNhc2UgVGV4dE1hc2tFbnVtLlBhc3N3b3JkOiByZXR1cm4gJ3Bhc3N3b3JkJztcclxuICAgICAgY2FzZSBUZXh0TWFza0VudW0uVGVsZWZvbm86IHJldHVybiAndGVsJztcclxuICAgICAgY2FzZSBUZXh0TWFza0VudW0uVXJsOiAgICAgIHJldHVybiAndXJsJztcclxuICAgICAgZGVmYXVsdDogICAgICAgICAgICAgICAgICAgIHJldHVybiAndGV4dCc7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB1cGRhdGVGaWVsZCgpIHtcclxuICAgIGlmICh0aGlzLmZpZWxkLlJlYWRvbmx5SWYpIHtcclxuICAgICAgdGhpcy5maWVsZC5SZWFkb25seSA9IFV0aWxpdHlIZWxwZXJTZXJ2aWNlLkV2YWx1YXRlRmllbGRGb3JtdWxhKHRoaXMuZmllbGQuUmVhZG9ubHlJZiwgdGhpcy5yZWNvcmQsIHRoaXMuZm9ybXVsYU9iamVjdCk7XHJcbiAgICB9XHJcbiAgICBpZiAoKHRoaXMuZmllbGQuRGF0YUdldHRlci5EYXRhR2V0dGVyVHlwZSA9PSBEYXRhR2V0dGVyVHlwZUVudW0uTWFudWFsZSB8fCB0aGlzLmZpZWxkLkRhdGFHZXR0ZXIuRGF0YUdldHRlclR5cGUgPT0gRGF0YUdldHRlclR5cGVFbnVtLkZvcm11bGEpICYmIHRoaXMuZmllbGQuRm9ybXVsYSkge1xyXG4gICAgICB0aGlzLnJlY29yZFt0aGlzLmZpZWxkLk5hbWVdID0gVXRpbGl0eUhlbHBlclNlcnZpY2UuRXZhbHVhdGVGaWVsZEZvcm11bGEodGhpcy5maWVsZC5Gb3JtdWxhLCB0aGlzLnJlY29yZCwgdGhpcy5mb3JtdWxhT2JqZWN0KTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmZpZWxkLlZpc2libGVJZikge1xyXG4gICAgICB0aGlzLmZpZWxkLkluTGlzdFZpZXcgPSBVdGlsaXR5SGVscGVyU2VydmljZS5FdmFsdWF0ZUZpZWxkRm9ybXVsYSh0aGlzLmZpZWxkLlZpc2libGVJZiwgdGhpcy5yZWNvcmQsIHRoaXMuZm9ybXVsYU9iamVjdCk7XHJcbiAgICAgIGlmICghdGhpcy5maWVsZC5Jbkxpc3RWaWV3ICYmICF0aGlzLmZpZWxkLk1haW50YWluX1ZhbHVlKSB7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRbdGhpcy5maWVsZC5OYW1lXSA9IG51bGw7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICh0aGlzLmZpZWxkLkRhdGFHZXR0ZXIuRGF0YUdldHRlclR5cGUgPT0gRGF0YUdldHRlclR5cGVFbnVtLk1hbnVhbGUgJiYgdGhpcy5yZWNvcmRbdGhpcy5maWVsZC5OYW1lXSA9PSBudWxsKSB7XHJcbiAgICAgIHRoaXMucmVjb3JkW3RoaXMuZmllbGQuTmFtZV0gPSB0aGlzLmZpZWxkLkRhdGFHZXR0ZXIuRGF0YUdldHRlclZhbHVlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25SZWNvcmRWYWx1ZUNoYW5nZSgpIHtcclxuICAgIHRoaXMudXBkYXRlU3RhdGVDbGFzc2VzKCk7XHJcbiAgICBpZiAoIXRoaXMuZmllbGQuRm9ybXVsYSkge1xyXG4gICAgICB0aGlzLnJlY29yZENoYW5nZS5lbWl0KHRoaXMucmVjb3JkKTtcclxuICAgIH1cclxuICAgIGlmICghdGhpcy5maWVsZC5WaXNpYmxlSWYpIHtcclxuICAgICAgdGhpcy5yZWNvcmRDaGFuZ2UuZW1pdCh0aGlzLnJlY29yZCk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgW2lkXT1cImZpZWxkVWlkXCIgY2xhc3M9XCJlcXAtdGYtd3JhcHBlclwiPlxyXG4gIDxtYXQtZm9ybS1maWVsZCBbZm9ybUdyb3VwXT1cImZpZWxkLkZvcm1Gb3JtR3JvdXBcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiPlxyXG4gICAgPG1hdC1sYWJlbCBjbGFzcz1cInB0LTFcIiBbbmdTdHlsZV09XCJMYWJlbHN0eWxlT2JqXCI+XHJcbiAgICAgIHt7IGZpZWxkLkRlc2NyaXB0aW9uIH19XHJcbiAgICA8L21hdC1sYWJlbD5cclxuICAgIDxtYXQtaWNvbiAqbmdJZj1cImZpZWxkLkljb25OYW1lICYmIGZpZWxkLkljb25Qb3NpdGlvbiAhPSBUZXh0RmllbGRJY29uUG9zaXRpb25FbnVtLkRlc3RyYVwiIG1hdFByZWZpeD5cclxuICAgICAge3sgZmllbGQuSWNvbk5hbWUgfX1cclxuICAgIDwvbWF0LWljb24+XHJcbiAgICA8aW5wdXRcclxuICAgICAgW25nU3R5bGVdPVwiRmllbGRzdHlsZU9ialwiXHJcbiAgICAgIG1hdElucHV0XHJcbiAgICAgIFt0eXBlXT1cImdldElucHV0VHlwZSgpXCJcclxuICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJmaWVsZC5OYW1lXCJcclxuICAgICAgW3JlYWRvbmx5XT1cImZpZWxkLlJlYWRvbmx5IHx8IChmaWVsZC5Gb3JtdWxhICE9IG51bGwgJiYgZmllbGQuRm9ybXVsYSAhPSAnJylcIlxyXG4gICAgICBbcmVxdWlyZWRdPVwiZmllbGQuUmVxdWlyZWRcIlxyXG4gICAgICBbKG5nTW9kZWwpXT1cInJlY29yZFtmaWVsZC5OYW1lXVwiXHJcbiAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uUmVjb3JkVmFsdWVDaGFuZ2UoKVwiXHJcbiAgICAvPlxyXG4gICAgPG1hdC1lcnJvclxyXG4gICAgICAqbmdJZj1cIlxyXG4gICAgICAgICFmaWVsZC5Gb3JtRm9ybUdyb3VwLnZhbGlkICYmXHJcbiAgICAgICAgZmllbGQuRm9ybUZvcm1Hcm91cC5jb250cm9sc1tmaWVsZC5OYW1lXS50b3VjaGVkICYmXHJcbiAgICAgICAgIWZpZWxkLlJlYWRvbmx5XHJcbiAgICAgIFwiXHJcbiAgICA+XHJcbiAgICAgIE1pbi4gQ2FyYXR0ZXJpOiB7eyBmaWVsZC5NaW5MZW5naHQgfX0gLSBNYXguIENhcmF0dGVyaTpcclxuICAgICAge3sgZmllbGQuTWF4TGVuZ2h0IH19XHJcbiAgICA8L21hdC1lcnJvcj5cclxuICAgIDxtYXQtaWNvblxyXG4gICAgICAqbmdJZj1cImZpZWxkLkljb25OYW1lICYmIGZpZWxkLkljb25Qb3NpdGlvbiA9PSBUZXh0RmllbGRJY29uUG9zaXRpb25FbnVtLkRlc3RyYVwiXHJcbiAgICAgIG1hdFN1ZmZpeFxyXG4gICAgICA+e3sgZmllbGQuSWNvbk5hbWUgfX08L21hdC1pY29uXHJcbiAgICA+XHJcbiAgICA8bWF0LWljb25cclxuICAgICAgW2hpZGRlbl09XCIhZmllbGQuTWljcm9waG9uZSB8fCBwbGF0Zm9ybSAhPSAnd2ViJ1wiXHJcbiAgICAgIG1hdFN1ZmZpeFxyXG4gICAgICBjbGFzcz1cImVxcC1taWNyb2Zvbm9cIlxyXG4gICAgICBTcGVlY2hUb1RleHRcclxuICAgICAgWyhiaW5kZWRUZXh0KV09XCJyZWNvcmRbZmllbGQuTmFtZV1cIlxyXG4gICAgICBzdHlsZT1cImN1cnNvcjogcG9pbnRlclwiXHJcbiAgICAgID5rZXlib2FyZF92b2ljZTwvbWF0LWljb25cclxuICAgID5cclxuICA8L21hdC1mb3JtLWZpZWxkPlxyXG48L2Rpdj5cclxuIl19