@wertzui/ngx-restworld-client 1.0.2 → 2.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 (31) hide show
  1. package/bundles/wertzui-ngx-restworld-client.umd.js +1101 -301
  2. package/bundles/wertzui-ngx-restworld-client.umd.js.map +1 -1
  3. package/esm2015/lib/models/problem-details.js +2 -2
  4. package/esm2015/lib/pipes/as.pipe.js +25 -0
  5. package/esm2015/lib/pipes/safe-url.pipe.js +23 -0
  6. package/esm2015/lib/restworld-client.module.js +68 -8
  7. package/esm2015/lib/services/avatar-generator.js +2 -2
  8. package/esm2015/lib/services/form.service.js +69 -0
  9. package/esm2015/lib/services/restworld-client-collection.js +1 -1
  10. package/esm2015/lib/services/restworld-client.js +46 -8
  11. package/esm2015/lib/views/restworld-edit-form/restworld-edit-form.component.js +238 -0
  12. package/esm2015/lib/views/restworld-edit-view/restworld-edit-view.component.js +209 -143
  13. package/esm2015/lib/views/restworld-file-view/restworld-file-view.component.js +63 -0
  14. package/esm2015/lib/views/restworld-image-view/restworld-image-view.component.js +107 -0
  15. package/esm2015/lib/views/restworld-list-view/restworld-list-view.component.js +64 -37
  16. package/esm2015/public-api.js +7 -1
  17. package/fesm2015/wertzui-ngx-restworld-client.js +880 -220
  18. package/fesm2015/wertzui-ngx-restworld-client.js.map +1 -1
  19. package/lib/models/problem-details.d.ts +4 -8
  20. package/lib/pipes/as.pipe.d.ts +18 -0
  21. package/lib/pipes/safe-url.pipe.d.ts +10 -0
  22. package/lib/restworld-client.module.d.ts +35 -21
  23. package/lib/services/form.service.d.ts +14 -0
  24. package/lib/services/restworld-client.d.ts +4 -1
  25. package/lib/views/restworld-edit-form/restworld-edit-form.component.d.ts +69 -0
  26. package/lib/views/restworld-edit-view/restworld-edit-view.component.d.ts +53 -32
  27. package/lib/views/restworld-file-view/restworld-file-view.component.d.ts +21 -0
  28. package/lib/views/restworld-image-view/restworld-image-view.component.d.ts +38 -0
  29. package/lib/views/restworld-list-view/restworld-list-view.component.d.ts +20 -8
  30. package/package.json +29 -8
  31. package/public-api.d.ts +6 -0
@@ -1,7 +1,7 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { Component, Input } from '@angular/core';
3
- import * as _ from 'lodash';
4
- import { FormControl, FormGroup } from '@angular/forms';
3
+ import { PropertyType } from '@wertzui/ngx-hal-client';
4
+ import { FormGroup } from '@angular/forms';
5
5
  import { ProblemDetails } from '../../models/problem-details';
6
6
  import { ContentChild } from '@angular/core';
7
7
  import * as i0 from "@angular/core";
@@ -9,34 +9,41 @@ import * as i1 from "../../services/restworld-client-collection";
9
9
  import * as i2 from "primeng/api";
10
10
  import * as i3 from "@angular/common";
11
11
  import * as i4 from "@angular/router";
12
- import * as i5 from "primeng/tabview";
13
- import * as i6 from "primeng/skeleton";
14
- import * as i7 from "primeng/calendar";
15
- import * as i8 from "primeng/inputnumber";
16
- import * as i9 from "primeng/checkbox";
12
+ import * as i5 from "../../services/form.service";
13
+ import * as i6 from "ngx-valdemort";
14
+ import * as i7 from "primeng/tabview";
15
+ import * as i8 from "primeng/skeleton";
16
+ import * as i9 from "../restworld-edit-form/restworld-edit-form.component";
17
17
  import * as i10 from "primeng/progressspinner";
18
18
  import * as i11 from "primeng/toast";
19
19
  import * as i12 from "primeng/confirmdialog";
20
20
  import * as i13 from "@angular/forms";
21
- import * as i14 from "primeng/inputtext";
22
- import * as i15 from "primeng/button";
23
- import * as i16 from "primeng/ripple";
21
+ import * as i14 from "primeng/button";
22
+ import * as i15 from "primeng/ripple";
24
23
  export class RESTworldEditViewComponent {
25
- constructor(_clients, _confirmationService, _messageService, _location, _router) {
24
+ constructor(_clients, _confirmationService, _messageService, _location, _router, _formService, valdemortConfig) {
26
25
  this._clients = _clients;
27
26
  this._confirmationService = _confirmationService;
28
27
  this._messageService = _messageService;
29
28
  this._location = _location;
30
29
  this._router = _router;
31
- this._properties = [];
32
- this._formGroup = new FormGroup({});
30
+ this._formService = _formService;
31
+ this._templates = {};
32
+ this._formTabs = {};
33
33
  this.isLoading = false;
34
+ valdemortConfig.errorClasses = 'p-error text-sm';
34
35
  }
35
- get properties() {
36
- return this._properties;
36
+ get PropertyType() {
37
+ return PropertyType;
37
38
  }
38
- get formGroup() {
39
- return this._formGroup;
39
+ get templates() {
40
+ return this._templates;
41
+ }
42
+ get isLoadingForTheFirstTime() {
43
+ return Object.keys(this.templates).length === 0 && this.isLoading;
44
+ }
45
+ get formTabs() {
46
+ return this._formTabs;
40
47
  }
41
48
  set apiName(value) {
42
49
  this._apiName = value;
@@ -73,39 +80,68 @@ export class RESTworldEditViewComponent {
73
80
  const length = (_b = (_a = this.resource) === null || _a === void 0 ? void 0 : _a._links["delete"]) === null || _b === void 0 ? void 0 : _b.length;
74
81
  return length !== undefined && length > 0;
75
82
  }
76
- get dateFormat() {
77
- return new Date(3333, 10, 22)
78
- .toLocaleDateString()
79
- .replace("22", "dd")
80
- .replace("11", "mm")
81
- .replace("3333", "yy")
82
- .replace("33", "y");
83
+ canSubmit(templateName) {
84
+ const form = this.formTabs[templateName];
85
+ return form && form.valid;
86
+ }
87
+ getTooltip(resource, keysToExclude) {
88
+ const tooltip = Object.entries(resource)
89
+ .filter(([key]) => !(key.startsWith('_') || ['createdAt', 'createdBy', 'lastChangedAt', 'lastChangedBy', 'timestamp'].includes(key) || (keysToExclude === null || keysToExclude === void 0 ? void 0 : keysToExclude.includes(key))))
90
+ .reduce((prev, [key, value], index) => `${prev}${index === 0 ? '' : '\n'}${key}: ${RESTworldEditViewComponent.jsonStringifyWithElipsis(value)}`, '');
91
+ return tooltip;
92
+ }
93
+ static jsonStringifyWithElipsis(value) {
94
+ const maxLength = 200;
95
+ const end = 10;
96
+ const start = maxLength - end - 2;
97
+ const json = JSON.stringify(value);
98
+ const shortened = json.length > maxLength ? json.substring(0, start) + '…' + json.substring(json.length - end) : json;
99
+ return shortened;
83
100
  }
84
101
  getClient() {
85
102
  if (!this.apiName)
86
103
  throw new Error('Cannot get a client, because the apiName is not set.');
87
104
  return this._clients.getClient(this.apiName);
88
105
  }
89
- save() {
106
+ submit(templateName, template, formValue) {
90
107
  return __awaiter(this, void 0, void 0, function* () {
91
- if (!this.apiName || !this.uri || !this.resource)
92
- return;
93
- Object.assign(this.resource, this.formGroup.value);
94
- const selfHrefBeforeSave = this.resource._links.self[0].href;
95
108
  this.isLoading = true;
96
- const response = yield this.getClient().save(this.resource);
97
- this.isLoading = false;
98
- if (!response.ok || ProblemDetails.isProblemDetails(response.body)) {
99
- const message = response.status === 409 /* Conflict */ ? 'Someone else modified the resource. Try reloading it and apply your changes again.' : 'Error while saving the resource.';
100
- this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response });
101
- }
102
- else {
103
- const selfHrefAfterSave = this.resource._links.self[0].href;
104
- setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Saved', detail: 'The resource has been saved.' }), 100);
105
- if (selfHrefBeforeSave !== selfHrefAfterSave) {
106
- this._router.navigate(['/edit', this.apiName, selfHrefAfterSave]);
109
+ try {
110
+ const targetBeforeSave = template.target;
111
+ const response = yield this.getClient().submit(template, formValue);
112
+ if (!response.ok) {
113
+ let summary = 'Error';
114
+ let detail = 'Error while saving the resource.';
115
+ if (ProblemDetails.isProblemDetails(response.body)) {
116
+ const problemDetails = response.body;
117
+ summary = problemDetails.title || summary;
118
+ detail = problemDetails.detail || detail;
119
+ // display validation errors
120
+ if (problemDetails['errors']) {
121
+ const form = this.formTabs[templateName];
122
+ for (const [key, errorsForKey] of Object.entries(problemDetails['errors'])) {
123
+ const path = key.split(/\.|\[/).map(e => e.replace("]", ""));
124
+ const formControl = path.reduce((control, pathElement) => (control instanceof FormGroup ? control.controls[pathElement] : control) || control, form);
125
+ formControl.setErrors({ remote: errorsForKey });
126
+ }
127
+ }
128
+ }
129
+ this._messageService.add({ severity: 'error', summary: summary, detail: detail, data: response, life: 10000 });
107
130
  }
131
+ else {
132
+ const responseResource = response.body;
133
+ const targetAfterSave = responseResource._templates[templateName].target;
134
+ setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Saved', detail: 'The resource has been saved.' }), 100);
135
+ if (targetBeforeSave !== targetAfterSave) {
136
+ this._router.navigate(['/edit', this.apiName, responseResource._links.self[0].href]);
137
+ }
138
+ }
139
+ }
140
+ catch (e) {
141
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: `An unknown error occurred. ${JSON.stringify(e)}`, life: 10000 });
142
+ console.log(e);
108
143
  }
144
+ this.isLoading = false;
109
145
  });
110
146
  }
111
147
  showDeleteConfirmatioModal() {
@@ -120,7 +156,7 @@ export class RESTworldEditViewComponent {
120
156
  return __awaiter(this, void 0, void 0, function* () {
121
157
  if (!this.apiName || !this.uri || !this.resource)
122
158
  return;
123
- Object.assign(this.resource, this.formGroup.value);
159
+ Object.assign(this.resource, this.formTabs.value);
124
160
  yield this.getClient().delete(this.resource);
125
161
  setTimeout(() => this._messageService.add({ severity: 'success', summary: 'Deleted', detail: 'The resource has been deleted.' }), 100);
126
162
  this._location.back();
@@ -137,133 +173,163 @@ export class RESTworldEditViewComponent {
137
173
  }
138
174
  else {
139
175
  this._resource = response.body;
140
- this._properties = RESTworldEditViewComponent.createProperyInfos(this._resource);
141
- this._formGroup = RESTworldEditViewComponent.createFormGroup(this._properties);
176
+ this._templates = yield this.getAllTemplates(this._resource);
177
+ this._formTabs = this._formService.createFormGroupsFromTemplates(this._templates);
142
178
  }
143
179
  this.isLoading = false;
144
180
  });
145
181
  }
146
- static createFormGroup(properties) {
147
- const controls = Object.fromEntries(properties.map(p => [
148
- p.field,
149
- p.type === 'object' && p.children ? RESTworldEditViewComponent.createFormGroup(p.children) : new FormControl(p.value)
150
- ]));
151
- const formGroup = new FormGroup(controls);
152
- return formGroup;
182
+ setInitialSelectedOptionsElementsForTemplates(templates) {
183
+ return __awaiter(this, void 0, void 0, function* () {
184
+ return Promise.all(Object.values(templates)
185
+ .map(template => this.setInitialSelectedOptionsElementsForTemplate(template)));
186
+ });
153
187
  }
154
- static createProperyInfos(resource) {
155
- if (!resource)
156
- return [];
157
- // Get all distinct properties from all rows
158
- // We look at all rows to eliminate possible undefined values
159
- const properties = Object.entries(resource)
160
- .filter(p => p[0] !== '_links' &&
161
- p[0] !== '_embedded' &&
162
- p[0] !== 'id' &&
163
- p[0] !== 'timestamp');
164
- // Check if the rows are entities with change tracking
165
- const withoutChangeTrackingProperties = properties.filter(p => p[0] !== 'createdAt' &&
166
- p[0] !== 'createdBy' &&
167
- p[0] !== 'lastChangedAt' &&
168
- p[0] !== 'lastChangedBy');
169
- const hasChangeTrackingProperties = withoutChangeTrackingProperties.length < properties.length;
170
- // First the id, then all other properties
171
- const sortedProperties = [];
172
- if (Object.hasOwnProperty('id'))
173
- sortedProperties.push(['id', resource['id']]);
174
- sortedProperties.push(...withoutChangeTrackingProperties);
175
- // And change tracking properties at the end
176
- if (hasChangeTrackingProperties) {
177
- sortedProperties.push(['createdAt', resource['createdAt']]);
178
- sortedProperties.push(['createdBy', resource['createdBy']]);
179
- sortedProperties.push(['lastChangedAt', resource['lastChangedAt']]);
180
- sortedProperties.push(['lastChangedBy', resource['lastChangedBy']]);
181
- }
182
- const propertyDescriptions = sortedProperties
183
- .map(p => ({
184
- field: p[0],
185
- value: p[1],
186
- label: RESTworldEditViewComponent.toTitleCase(p[0]),
187
- type: RESTworldEditViewComponent.getColumnType(p[0], p[1]),
188
- isReadOnly: RESTworldEditViewComponent.getIsReadOnly(p[0])
189
- }));
190
- for (var description of propertyDescriptions) {
191
- if (description.type === 'object') {
192
- const children = RESTworldEditViewComponent.createProperyInfos(description.value);
193
- children.forEach(d => description.field + '.' + d.field);
194
- description.children = children;
195
- }
196
- }
197
- return propertyDescriptions;
188
+ imageChanged(formControl, event) {
189
+ const file = event.files[0];
190
+ console.log(file);
191
+ const reader = new FileReader();
192
+ reader.onload = () => {
193
+ const uri = reader.result;
194
+ console.log(uri);
195
+ formControl.setValue(uri);
196
+ };
197
+ reader.readAsDataURL(file);
198
198
  }
199
- static getIsReadOnly(field) {
200
- return field === 'id' || field === 'createdAt' || field === 'createdBy' || field === 'lastChangedAt' || field === 'lastChangedBy';
199
+ setInitialSelectedOptionsElementsForTemplate(template) {
200
+ return __awaiter(this, void 0, void 0, function* () {
201
+ return Promise.all(template.properties
202
+ .filter(property => { var _a, _b; return (_b = (_a = property === null || property === void 0 ? void 0 : property.options) === null || _a === void 0 ? void 0 : _a.link) === null || _b === void 0 ? void 0 : _b.href; })
203
+ .map(property => this.setInitialSelectedOptionsElementForProperty(property)));
204
+ });
201
205
  }
202
- static getColumnType(field, value) {
203
- if (value === null || value === undefined)
204
- return 'text';
205
- if (_.isNumber(value))
206
- return 'numeric';
207
- if (_.isDate(value))
208
- return 'date';
209
- if (_.isString(value)) {
210
- return 'text';
211
- }
212
- if (_.isBoolean(value))
213
- return 'boolean';
214
- if (_.isObject(value))
215
- return 'object';
216
- if (_.isArray(value))
217
- return 'array';
218
- return 'text';
206
+ setInitialSelectedOptionsElementForProperty(property) {
207
+ var _a;
208
+ return __awaiter(this, void 0, void 0, function* () {
209
+ const options = property === null || property === void 0 ? void 0 : property.options;
210
+ if (!((_a = options === null || options === void 0 ? void 0 : options.link) === null || _a === void 0 ? void 0 : _a.href))
211
+ return;
212
+ const templatedUri = options.link.href;
213
+ const filter = `${options.valueField} eq ${property.value}`;
214
+ const response = yield this.getClient().getListByUri(templatedUri, { $filter: filter, $top: 10 });
215
+ if (!response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body) {
216
+ const message = `An error occurred while getting the filtered items.`;
217
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: message, data: response });
218
+ return;
219
+ }
220
+ const items = response.body._embedded.items;
221
+ options.inline = items;
222
+ });
219
223
  }
220
- static toTitleCase(anyCase) {
221
- return anyCase
222
- .replace(/(_)+/g, ' ') // underscore to whitespace
223
- .replace(/([a-z])([A-Z][a-z])/g, "$1 $2") // insert space before each new word if there is none
224
- .replace(/([A-Z][a-z])([A-Z])/g, "$1 $2") // insert space after each word if there is none
225
- .replace(/([a-z])([A-Z]+[a-z])/g, "$1 $2") // insert space after single letter word if there is none
226
- .replace(/([A-Z]+)([A-Z][a-z][a-z])/g, "$1 $2") // insert space before single letter word if there is none
227
- .replace(/([a-z]+)([A-Z0-9]+)/g, "$1 $2") // insert space after numbers
228
- .replace(/^./, (match) => match.toUpperCase()); // change first letter to be upper case
224
+ getAllTemplates(resource) {
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ const formResponses = yield this.getClient().getAllForms(resource);
227
+ const failedResponses = formResponses.filter(response => !response.ok || ProblemDetails.isProblemDetails(response.body) || !response.body);
228
+ if (failedResponses.length !== 0) {
229
+ for (const response of failedResponses) {
230
+ this._messageService.add({ severity: 'error', summary: 'Error', detail: 'Error while loading the resource from the API.', data: response });
231
+ }
232
+ return Promise.resolve({});
233
+ }
234
+ const formTemplates = Object.assign({}, ...formResponses.map(response => response.body._templates));
235
+ yield this.setInitialSelectedOptionsElementsForTemplates(formTemplates);
236
+ return formTemplates;
237
+ });
229
238
  }
230
239
  }
231
- RESTworldEditViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldEditViewComponent, deps: [{ token: i1.RESTworldClientCollection }, { token: i2.ConfirmationService }, { token: i2.MessageService }, { token: i3.Location }, { token: i4.Router }], target: i0.ɵɵFactoryTarget.Component });
232
- RESTworldEditViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTworldEditViewComponent, selector: "restworld-edit-view", inputs: { apiName: "apiName", uri: "uri" }, queries: [{ propertyName: "visualTabRef", first: true, predicate: ["visualTab"], descendants: true }, { propertyName: "formRef", first: true, predicate: ["form"], descendants: true }, { propertyName: "formRowRef", first: true, predicate: ["formRow"], descendants: true }, { propertyName: "formLabelRef", first: true, predicate: ["formLabel"], descendants: true }, { propertyName: "formInputRef", first: true, predicate: ["formInput"], descendants: true }, { propertyName: "visualTabAdditionalRef", first: true, predicate: ["visualTabAdditional"], descendants: true }, { propertyName: "rawTabRef", first: true, predicate: ["rawTab"], descendants: true }, { propertyName: "buttonsRef", first: true, predicate: ["buttonsRef"], descendants: true }], ngImport: i0, template: "<div class=\"grid\">\r\n <div class=\"col\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n</div>\r\n\r\n<form [formGroup]=\"formGroup\" (ngSubmit)=\"save()\">\r\n <p-tabView>\r\n <p-tabPanel header=\"Visual\" [disabled]=\"!resource || isLoading\">\r\n <ng-template #defaultVisualTab>\r\n <ng-container *ngIf=\"!resource && isLoading\">\r\n <div *ngFor=\"let i of [1, 2, 3, 4, 5]\" class=\"grid field\">\r\n <p-skeleton class=\"col-12 mb-2 md:col-2 md:mb-0\" height=\"39px\"></p-skeleton>\r\n <div class=\"col-12 md:col-10\">\r\n <p-skeleton class=\"w-full\" height=\"39px\"></p-skeleton>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <div *ngIf=\"resource\" class=\"blockable-container\">\r\n <div class=\"blockable-element\">\r\n <ng-template #defaultForm let-properties=\"properties\" let-formGroup=\"formGroup\">\r\n <div [formGroup]=\"formGroup\">\r\n <div *ngFor=\"let property of properties\" class=\"grid field\">\r\n <ng-template #defaultFormRow>\r\n <ng-template #defaultFormLabel>\r\n <label [attr.for]=\"property.field\" class=\"col-12 mb-2 md:col-2 md:mb-0\" [class.p-disabled]=\"property.isReadOnly\" [class.hasChildren]=\"property.children?.length > 0\">{{property.label}}</label>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formLabelRef || defaultFormLabel; context:{ $implicit: property }\"></ng-container>\r\n <ng-template #defaultFormInput let-property let-formGroup=\"formGroup\">\r\n <div [ngSwitch]=\"property.type\" class=\"col-12 md:col-10\">\r\n <input *ngSwitchCase=\"'text'\" [formControlName]=\"property.field\" [id]=\"property.field\" type=\"text\" pInputText class=\"w-full\" [class.p-disabled]=\"property.isReadOnly\">\r\n <p-calendar *ngSwitchCase=\"'date'\" [formControlName]=\"property.field\" [id]=\"property.field\" [dateFormat]=\"dateFormat\" [showTime]=\"true\" [showIcon]=\"true\" styleClass=\"w-full\" [class.p-disabled]=\"property.isReadOnly\"></p-calendar>\r\n <p-inputNumber *ngSwitchCase=\"'numeric'\" [formControlName]=\"property.field\" [id]=\"property.field\" mode=\"decimal\" [showButtons]=\"!property.isReadOnly\" class=\"w-full\" styleClass=\"w-full\" [class.p-disabled]=\"property.isReadOnly\"></p-inputNumber>\r\n <p-checkbox *ngSwitchCase=\"'boolean'\" [formControl]=\"formGroup.controls[property.field]\" [id]=\"property.field\" [readonly]=\"property.isReadOnly\"></p-checkbox>\r\n <div *ngSwitchCase=\"'object'\">\r\n <ng-container *ngTemplateOutlet=\"formRef || defaultForm; context:{ properties: property.children, formGroup: formGroup.controls[property.field] }\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formInputRef || defaultFormInput; context:{ $implicit: property, formGroup: formGroup }\"></ng-container>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formRowRef || defaultFormRow; context:{ $implicit: property }\"></ng-container>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"formRef || defaultForm; context: { properties: properties, formGroup: formGroup }\"></ng-container>\r\n </div>\r\n <div class=\"blockable-overlay\" *ngIf=\"isLoading\">\r\n <p-progressSpinner></p-progressSpinner>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"visualTabRef || defaultVisualTab\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"visualTabAdditionalRef || null; context:{ $implicit: resource, properties: properties, isLoading: isLoading }\"></ng-container>\r\n </p-tabPanel>\r\n\r\n <p-tabPanel header=\"Raw\" [disabled]=\"!resource || isLoading\">\r\n <ng-template #defaultRawTab>\r\n <pre>{{resource | json}}</pre>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"rawTabRef || defaultRawTab\"></ng-container>\r\n </p-tabPanel>\r\n </p-tabView>\r\n\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <ng-template #defaultButtons>\r\n <button pButton pRipple type=\"submit\" label=\"Save\" icon=\"far fa-save\" class=\"mx-2 p-button-success\" [disabled]=\"!resource || isLoading || !canSave\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Reload\" icon=\"fas fa-redo\" class=\"mx-2 p-button-info\" (click)=\"load()\" [disabled]=\"isLoading\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Delete\" icon=\"far fa-trash-alt\" class=\"mx-2 p-button-danger\" (click)=\"showDeleteConfirmatioModal()\" [disabled]=\"!resource || isLoading || !canDelete\"></button>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"buttonsRef || defaultButtons\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n</form>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: [".blockable-container{display:grid;place-items:center;grid-template-areas:\"inner\"}.blockable-element{grid-area:inner;width:100%}.blockable-overlay{grid-area:inner;height:100%;width:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:1}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"], components: [{ type: i5.TabView, selector: "p-tabView", inputs: ["orientation", "style", "styleClass", "controlClose", "scrollable", "activeIndex"], outputs: ["onChange", "onClose", "activeIndexChange"] }, { type: i5.TabPanel, selector: "p-tabPanel", inputs: ["closable", "headerStyle", "headerStyleClass", "cache", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "selected", "disabled", "header", "leftIcon", "rightIcon"] }, { type: i6.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { type: i7.Calendar, selector: "p-calendar", inputs: ["style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "numberOfMonths", "view", "touchUI", "timeSeparator", "focusTrap", "firstDayOfWeek", "showTransitionOptions", "hideTransitionOptions", "tabindex", "defaultDate", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "locale"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { type: i8.InputNumber, selector: "p-inputNumber", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "disabled"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown"] }, { type: i9.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "trueValue", "falseValue"], outputs: ["onChange"] }, { type: i10.ProgressSpinner, selector: "p-progressSpinner", inputs: ["style", "styleClass", "strokeWidth", "fill", "animationDuration"] }, { type: i11.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { type: i12.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }], directives: [{ type: i13.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i13.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i13.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i13.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i14.InputText, selector: "[pInputText]" }, { type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i13.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i13.FormControlDirective, selector: "[formControl]", inputs: ["disabled", "formControl", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i15.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i16.Ripple, selector: "[pRipple]" }], pipes: { "json": i3.JsonPipe } });
240
+ RESTworldEditViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldEditViewComponent, deps: [{ token: i1.RESTworldClientCollection }, { token: i2.ConfirmationService }, { token: i2.MessageService }, { token: i3.Location }, { token: i4.Router }, { token: i5.FormService }, { token: i6.ValdemortConfig }], target: i0.ɵɵFactoryTarget.Component });
241
+ RESTworldEditViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.11", type: RESTworldEditViewComponent, selector: "rw-edit", inputs: { apiName: "apiName", uri: "uri" }, queries: [{ propertyName: "extraTabsRef", first: true, predicate: ["extraTabs"], descendants: true }, { propertyName: "buttonsRef", first: true, predicate: ["buttons"], descendants: true }, { propertyName: "inputOptionsSingleRef", first: true, predicate: ["inputOptionsSingle"], descendants: true }, { propertyName: "inputOptionsMultipleRef", first: true, predicate: ["inputOptionsMultiple"], descendants: true }, { propertyName: "inputOptionsRef", first: true, predicate: ["inputOptions"], descendants: true }, { propertyName: "inputHiddenRef", first: true, predicate: ["inputHidden"], descendants: true }, { propertyName: "inputTextRef", first: true, predicate: ["inputText"], descendants: true }, { propertyName: "inputTextareaRef", first: true, predicate: ["inputTextarea"], descendants: true }, { propertyName: "inputSearchRef", first: true, predicate: ["inputSearch"], descendants: true }, { propertyName: "inputTelRef", first: true, predicate: ["inputTel"], descendants: true }, { propertyName: "inputUrlRef", first: true, predicate: ["inputUrl"], descendants: true }, { propertyName: "inputEmailRef", first: true, predicate: ["inputEmail"], descendants: true }, { propertyName: "inputPasswordRef", first: true, predicate: ["inputPassword"], descendants: true }, { propertyName: "inputDateRef", first: true, predicate: ["inputDate"], descendants: true }, { propertyName: "inputMonthRef", first: true, predicate: ["inputMonth"], descendants: true }, { propertyName: "inputWeekRef", first: true, predicate: ["inputWeek"], descendants: true }, { propertyName: "inputTimeRef", first: true, predicate: ["inputTime"], descendants: true }, { propertyName: "inputDatetimeLocalRef", first: true, predicate: ["inputDatetimeLocal"], descendants: true }, { propertyName: "inputNumberRef", first: true, predicate: ["inputNumber"], descendants: true }, { propertyName: "inputRangeRef", first: true, predicate: ["inputRange"], descendants: true }, { propertyName: "inputColorRef", first: true, predicate: ["inputColor"], descendants: true }, { propertyName: "inputBoolRef", first: true, predicate: ["inputBool"], descendants: true }, { propertyName: "inputDatetimeOffsetRef", first: true, predicate: ["inputDatetimeOffset"], descendants: true }, { propertyName: "inputDurationRef", first: true, predicate: ["inputDuration"], descendants: true }, { propertyName: "inputImageRef", first: true, predicate: ["inputImage"], descendants: true }, { propertyName: "inputFileRef", first: true, predicate: ["inputFile"], descendants: true }, { propertyName: "inputDefaultRef", first: true, predicate: ["inputDefault"], descendants: true }], ngImport: i0, template: "<div class=\"grid\">\r\n <div class=\"col\">\r\n <h1>Edit resource</h1>\r\n </div>\r\n</div>\r\n\r\n<p-tabView>\r\n\r\n <p-tabPanel *ngIf=\"isLoadingForTheFirstTime\" header=\"Loading\">\r\n <div *ngFor=\"let i of [1, 2, 3, 4, 5]\" class=\"grid field\">\r\n <p-skeleton class=\"col-12 mb-2 md:col-2 md:mb-0\" height=\"39px\"></p-skeleton>\r\n <div class=\"col-12 md:col-10\">\r\n <p-skeleton class=\"w-full\" height=\"39px\"></p-skeleton>\r\n </div>\r\n </div>\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n <p-skeleton width=\"120px\" height=\"39px\" class=\"mx-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabPanel>\r\n\r\n <p-tabPanel *ngFor=\"let item of templates | keyvalue\" [header]=\"item.value.title || item.key\" [disabled]=\"isLoading\">\r\n <form [formGroup]=\"formTabs[item.key]\" (ngSubmit)=\"submit(item.key, item.value, formTabs[item.key].value)\">\r\n <div class=\"blockable-container\">\r\n <div class=\"blockable-element\">\r\n <rw-form [formGroup]=\"formTabs[item.key]\" [template]=\"item.value\" [apiName]=\"apiName\"></rw-form>\r\n </div>\r\n <div class=\"blockable-overlay\" *ngIf=\"isLoading\">\r\n <p-progressSpinner></p-progressSpinner>\r\n </div>\r\n </div>\r\n\r\n <div class=\"grid\">\r\n <div class=\"col\">\r\n <div class=\"flex justify-content-end w-full\">\r\n <ng-template #defaultButtons>\r\n <button pButton pRipple type=\"submit\" label=\"Save\" icon=\"far fa-save\" class=\"mx-2 p-button-success\" [disabled]=\"isLoading || !canSubmit(item.key)\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Reload\" icon=\"fas fa-redo\" class=\"mx-2 p-button-info\" (click)=\"load()\" [disabled]=\"isLoading\"></button>\r\n <button pButton pRipple type=\"button\" label=\"Delete\" icon=\"far fa-trash-alt\" class=\"ml-2 p-button-danger\" (click)=\"showDeleteConfirmatioModal()\" [disabled]=\"!resource || isLoading || !canDelete\"></button>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"buttonsRef || defaultButtons\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </form>\r\n </p-tabPanel>\r\n\r\n <ng-template #defaultExtraTabs>\r\n </ng-template>\r\n <ng-container *ngTemplateOutlet=\"extraTabsRef || defaultExtraTabs\"></ng-container>\r\n\r\n</p-tabView>\r\n\r\n<p-toast></p-toast>\r\n<p-confirmDialog></p-confirmDialog>\r\n", styles: ["::ng-deep .p-tooltip{max-width:-webkit-fit-content!important;max-width:-moz-fit-content!important;max-width:fit-content!important}.blockable-container{display:grid;place-items:center;grid-template-areas:\"inner\"}.blockable-element{grid-area:inner;width:100%}.blockable-overlay{grid-area:inner;height:100%;width:100%;background-color:#0006;display:flex;align-items:center;justify-content:center;z-index:1}.field.grid>label.hasChildren{border-right:1px solid rgba(0,0,0,.1)}\n"], components: [{ type: i7.TabView, selector: "p-tabView", inputs: ["orientation", "style", "styleClass", "controlClose", "scrollable", "activeIndex"], outputs: ["onChange", "onClose", "activeIndexChange"] }, { type: i7.TabPanel, selector: "p-tabPanel", inputs: ["closable", "headerStyle", "headerStyleClass", "cache", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "selected", "disabled", "header", "leftIcon", "rightIcon"] }, { type: i8.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "style", "shape", "animation", "borderRadius", "size", "width", "height"] }, { type: i9.RestworldEditFormComponent, selector: "rw-form", inputs: ["formGroup", "template", "apiName"] }, { type: i10.ProgressSpinner, selector: "p-progressSpinner", inputs: ["style", "styleClass", "strokeWidth", "fill", "animationDuration"] }, { type: i11.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { type: i12.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i13.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i13.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i13.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i14.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { type: i15.Ripple, selector: "[pRipple]" }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "keyvalue": i3.KeyValuePipe } });
233
242
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.11", ngImport: i0, type: RESTworldEditViewComponent, decorators: [{
234
243
  type: Component,
235
244
  args: [{
236
- selector: 'restworld-edit-view',
245
+ selector: 'rw-edit',
237
246
  templateUrl: './restworld-edit-view.component.html',
238
247
  styleUrls: ['./restworld-edit-view.component.css']
239
248
  }]
240
- }], ctorParameters: function () { return [{ type: i1.RESTworldClientCollection }, { type: i2.ConfirmationService }, { type: i2.MessageService }, { type: i3.Location }, { type: i4.Router }]; }, propDecorators: { apiName: [{
249
+ }], ctorParameters: function () { return [{ type: i1.RESTworldClientCollection }, { type: i2.ConfirmationService }, { type: i2.MessageService }, { type: i3.Location }, { type: i4.Router }, { type: i5.FormService }, { type: i6.ValdemortConfig }]; }, propDecorators: { apiName: [{
241
250
  type: Input
242
251
  }], uri: [{
243
252
  type: Input
244
- }], visualTabRef: [{
253
+ }], extraTabsRef: [{
245
254
  type: ContentChild,
246
- args: ['visualTab', { static: false }]
247
- }], formRef: [{
255
+ args: ['extraTabs', { static: false }]
256
+ }], buttonsRef: [{
248
257
  type: ContentChild,
249
- args: ['form', { static: false }]
250
- }], formRowRef: [{
258
+ args: ['buttons', { static: false }]
259
+ }], inputOptionsSingleRef: [{
251
260
  type: ContentChild,
252
- args: ['formRow', { static: false }]
253
- }], formLabelRef: [{
261
+ args: ['inputOptionsSingle', { static: false }]
262
+ }], inputOptionsMultipleRef: [{
254
263
  type: ContentChild,
255
- args: ['formLabel', { static: false }]
256
- }], formInputRef: [{
264
+ args: ['inputOptionsMultiple', { static: false }]
265
+ }], inputOptionsRef: [{
257
266
  type: ContentChild,
258
- args: ['formInput', { static: false }]
259
- }], visualTabAdditionalRef: [{
267
+ args: ['inputOptions', { static: false }]
268
+ }], inputHiddenRef: [{
260
269
  type: ContentChild,
261
- args: ['visualTabAdditional', { static: false }]
262
- }], rawTabRef: [{
270
+ args: ['inputHidden', { static: false }]
271
+ }], inputTextRef: [{
263
272
  type: ContentChild,
264
- args: ['rawTab', { static: false }]
265
- }], buttonsRef: [{
273
+ args: ['inputText', { static: false }]
274
+ }], inputTextareaRef: [{
275
+ type: ContentChild,
276
+ args: ['inputTextarea', { static: false }]
277
+ }], inputSearchRef: [{
278
+ type: ContentChild,
279
+ args: ['inputSearch', { static: false }]
280
+ }], inputTelRef: [{
281
+ type: ContentChild,
282
+ args: ['inputTel', { static: false }]
283
+ }], inputUrlRef: [{
284
+ type: ContentChild,
285
+ args: ['inputUrl', { static: false }]
286
+ }], inputEmailRef: [{
287
+ type: ContentChild,
288
+ args: ['inputEmail', { static: false }]
289
+ }], inputPasswordRef: [{
290
+ type: ContentChild,
291
+ args: ['inputPassword', { static: false }]
292
+ }], inputDateRef: [{
293
+ type: ContentChild,
294
+ args: ['inputDate', { static: false }]
295
+ }], inputMonthRef: [{
296
+ type: ContentChild,
297
+ args: ['inputMonth', { static: false }]
298
+ }], inputWeekRef: [{
299
+ type: ContentChild,
300
+ args: ['inputWeek', { static: false }]
301
+ }], inputTimeRef: [{
302
+ type: ContentChild,
303
+ args: ['inputTime', { static: false }]
304
+ }], inputDatetimeLocalRef: [{
305
+ type: ContentChild,
306
+ args: ['inputDatetimeLocal', { static: false }]
307
+ }], inputNumberRef: [{
308
+ type: ContentChild,
309
+ args: ['inputNumber', { static: false }]
310
+ }], inputRangeRef: [{
311
+ type: ContentChild,
312
+ args: ['inputRange', { static: false }]
313
+ }], inputColorRef: [{
314
+ type: ContentChild,
315
+ args: ['inputColor', { static: false }]
316
+ }], inputBoolRef: [{
317
+ type: ContentChild,
318
+ args: ['inputBool', { static: false }]
319
+ }], inputDatetimeOffsetRef: [{
320
+ type: ContentChild,
321
+ args: ['inputDatetimeOffset', { static: false }]
322
+ }], inputDurationRef: [{
323
+ type: ContentChild,
324
+ args: ['inputDuration', { static: false }]
325
+ }], inputImageRef: [{
326
+ type: ContentChild,
327
+ args: ['inputImage', { static: false }]
328
+ }], inputFileRef: [{
329
+ type: ContentChild,
330
+ args: ['inputFile', { static: false }]
331
+ }], inputDefaultRef: [{
266
332
  type: ContentChild,
267
- args: ['buttonsRef', { static: false }]
333
+ args: ['inputDefault', { static: false }]
268
334
  }] } });
269
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdHdvcmxkLWVkaXQtdmlldy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL3ZpZXdzL3Jlc3R3b3JsZC1lZGl0LXZpZXcvcmVzdHdvcmxkLWVkaXQtdmlldy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL3ZpZXdzL3Jlc3R3b3JsZC1lZGl0LXZpZXcvcmVzdHdvcmxkLWVkaXQtdmlldy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFHekQsT0FBTyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUE7QUFFM0IsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUl4RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFFOUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBaUI3QyxNQUFNLE9BQU8sMEJBQTBCO0lBcUZyQyxZQUNVLFFBQW1DLEVBQ25DLG9CQUF5QyxFQUN6QyxlQUErQixFQUMvQixTQUFtQixFQUNuQixPQUFlO1FBSmYsYUFBUSxHQUFSLFFBQVEsQ0FBMkI7UUFDbkMseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFxQjtRQUN6QyxvQkFBZSxHQUFmLGVBQWUsQ0FBZ0I7UUFDL0IsY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUNuQixZQUFPLEdBQVAsT0FBTyxDQUFRO1FBdEZqQixnQkFBVyxHQUEwQixFQUFFLENBQUM7UUFLeEMsZUFBVSxHQUFjLElBQUksU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBaUMzQyxjQUFTLEdBQUcsS0FBSyxDQUFDO0lBa0R6QixDQUFDO0lBM0ZELElBQVcsVUFBVTtRQUNuQixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQztJQUdELElBQVcsU0FBUztRQUNsQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUdELElBQ1csT0FBTyxDQUFDLEtBQXlCO1FBQzFDLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFDRCxJQUFXLE9BQU87UUFDaEIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxVQUFVO0lBQ1YsNkNBQTZDO0lBQzdDLHNCQUFzQjtJQUN0QixHQUFHO0lBQ0gsd0NBQXdDO0lBQ3hDLHFCQUFxQjtJQUNyQixHQUFHO0lBQ0gsd0JBQXdCO0lBQ3hCLElBQ1csR0FBRyxDQUFDLEtBQXlCO1FBQ3RDLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFDRCxJQUFXLEdBQUc7UUFDWixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQUdELElBQVcsUUFBUTtRQUNqQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUdELElBQVcsT0FBTzs7UUFDaEIsTUFBTSxNQUFNLEdBQUcsTUFBQSxNQUFBLElBQUksQ0FBQyxRQUFRLDBDQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsMENBQUUsTUFBTSxDQUFDO1FBQ3JELE9BQU8sTUFBTSxLQUFLLFNBQVMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFDRCxJQUFXLFNBQVM7O1FBQ2xCLE1BQU0sTUFBTSxHQUFHLE1BQUEsTUFBQSxJQUFJLENBQUMsUUFBUSwwQ0FBRSxNQUFNLENBQUMsUUFBUSxDQUFDLDBDQUFFLE1BQU0sQ0FBQztRQUN2RCxPQUFPLE1BQU0sS0FBSyxTQUFTLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsSUFBVyxVQUFVO1FBQ25CLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUM7YUFDMUIsa0JBQWtCLEVBQUU7YUFDcEIsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUM7YUFDbkIsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUM7YUFDbkIsT0FBTyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUM7YUFDckIsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBbUNPLFNBQVM7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU87WUFDZixNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7UUFFMUUsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVZLElBQUk7O1lBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVE7Z0JBQzlDLE9BQU87WUFFVCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuRCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFFN0QsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7WUFDdEIsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1RCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUV2QixJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxjQUFjLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUNsRSxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsTUFBTSx1QkFBNEIsQ0FBQyxDQUFDLENBQUMsb0ZBQW9GLENBQUMsQ0FBQyxDQUFDLGtDQUFrQyxDQUFDO2dCQUN4TCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO2FBQ3BHO2lCQUNJO2dCQUNILE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFFNUQsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUNkLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSw4QkFBOEIsRUFBRSxDQUFDLEVBQzNHLEdBQUcsQ0FBQyxDQUFDO2dCQUVQLElBQUksa0JBQWtCLEtBQUssaUJBQWlCLEVBQUU7b0JBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO2lCQUNuRTthQUNGO1FBRUgsQ0FBQztLQUFBO0lBRU0sMEJBQTBCO1FBQy9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUM7WUFDaEMsT0FBTyxFQUFFLDZDQUE2QztZQUN0RCxNQUFNLEVBQUUsZ0JBQWdCO1lBQ3hCLElBQUksRUFBRSxrQkFBa0I7WUFDeEIsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7U0FDNUIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVZLE1BQU07O1lBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO2dCQUM5QyxPQUFPO1lBRVQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFbkQsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3QyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQ2QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLGdDQUFnQyxFQUFFLENBQUMsRUFDL0csR0FBRyxDQUFDLENBQUM7WUFFUCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hCLENBQUM7S0FBQTtJQUVZLElBQUk7O1lBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRztnQkFDNUIsT0FBTztZQUVULElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1lBRXRCLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDNUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLElBQUksY0FBYyxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ3BGLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxnREFBZ0QsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQTthQUM1STtpQkFDSTtnQkFDSCxJQUFJLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxXQUFXLEdBQUcsMEJBQTBCLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNqRixJQUFJLENBQUMsVUFBVSxHQUFHLDBCQUEwQixDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDaEY7WUFFRCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN6QixDQUFDO0tBQUE7SUFFRCxNQUFNLENBQUMsZUFBZSxDQUFDLFVBQWlDO1FBQ3RELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3RELENBQUMsQ0FBQyxLQUFLO1lBQ1AsQ0FBQyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsMEJBQTBCLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztTQUN0SCxDQUFDLENBQUMsQ0FBQztRQUNKLE1BQU0sU0FBUyxHQUFHLElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzFDLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFTyxNQUFNLENBQUMsa0JBQWtCLENBQUMsUUFBYTtRQUM3QyxJQUFJLENBQUMsUUFBUTtZQUNYLE9BQU8sRUFBRSxDQUFDO1FBRVosNENBQTRDO1FBQzVDLDZEQUE2RDtRQUM3RCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQzthQUN4QyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FDVixDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssUUFBUTtZQUNqQixDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssV0FBVztZQUNwQixDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtZQUNiLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxXQUFXLENBQUMsQ0FBQztRQUUxQixzREFBc0Q7UUFDdEQsTUFBTSwrQkFBK0IsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQzVELENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxXQUFXO1lBQ3BCLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxXQUFXO1lBQ3BCLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxlQUFlO1lBQ3hCLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxlQUFlLENBQUMsQ0FBQztRQUM1QixNQUFNLDJCQUEyQixHQUFHLCtCQUErQixDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO1FBRS9GLDBDQUEwQztRQUMxQyxNQUFNLGdCQUFnQixHQUFvQixFQUFFLENBQUM7UUFDN0MsSUFBSSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQztZQUM3QixnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVoRCxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsR0FBRywrQkFBK0IsQ0FBQyxDQUFDO1FBRTFELDRDQUE0QztRQUM1QyxJQUFJLDJCQUEyQixFQUFFO1lBQy9CLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVELGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVELGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLGVBQWUsRUFBRSxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BFLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLGVBQWUsRUFBRSxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3JFO1FBRUQsTUFBTSxvQkFBb0IsR0FBMEIsZ0JBQWdCO2FBQ2pFLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDVCxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNYLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ1gsS0FBSyxFQUFFLDBCQUEwQixDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkQsSUFBSSxFQUFFLDBCQUEwQixDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFELFVBQVUsRUFBRSwwQkFBMEIsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzNELENBQUMsQ0FBQyxDQUFDO1FBRU4sS0FBSyxJQUFJLFdBQVcsSUFBSSxvQkFBb0IsRUFBRTtZQUM1QyxJQUFJLFdBQVcsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO2dCQUNqQyxNQUFNLFFBQVEsR0FBRywwQkFBMEIsQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2xGLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3pELFdBQVcsQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO2FBQ2pDO1NBQ0Y7UUFFRCxPQUFPLG9CQUFvQixDQUFDO0lBQzlCLENBQUM7SUFFTyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQWE7UUFDeEMsT0FBTyxLQUFLLEtBQUssSUFBSSxJQUFJLEtBQUssS0FBSyxXQUFXLElBQUksS0FBSyxLQUFLLFdBQVcsSUFBSSxLQUFLLEtBQUssZUFBZSxJQUFJLEtBQUssS0FBSyxlQUFlLENBQUM7SUFDcEksQ0FBQztJQUVPLE1BQU0sQ0FBQyxhQUFhLENBQUMsS0FBYSxFQUFFLEtBQVU7UUFDcEQsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLEtBQUssS0FBSyxTQUFTO1lBQ3ZDLE9BQU8sTUFBTSxDQUFDO1FBRWhCLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7WUFDbkIsT0FBTyxTQUFTLENBQUM7UUFFbkIsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztZQUNqQixPQUFPLE1BQU0sQ0FBQTtRQUVmLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNyQixPQUFPLE1BQU0sQ0FBQztTQUNmO1FBRUQsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQztZQUNwQixPQUFPLFNBQVMsQ0FBQztRQUVuQixJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO1lBQ25CLE9BQU8sUUFBUSxDQUFBO1FBRWpCLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDbEIsT0FBTyxPQUFPLENBQUE7UUFFaEIsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0lBRU8sTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFlO1FBQ3hDLE9BQU8sT0FBTzthQUNYLE9BQU8sQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQThCLDJCQUEyQjthQUM5RSxPQUFPLENBQUMsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLENBQVcscURBQXFEO2FBQ3hHLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxPQUFPLENBQUMsQ0FBVyxnREFBZ0Q7YUFDbkcsT0FBTyxDQUFDLHVCQUF1QixFQUFFLE9BQU8sQ0FBQyxDQUFVLHlEQUF5RDthQUM1RyxPQUFPLENBQUMsNEJBQTRCLEVBQUUsT0FBTyxDQUFDLENBQUssMERBQTBEO2FBQzdHLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxPQUFPLENBQUMsQ0FBVyw2QkFBNkI7YUFDaEYsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBSyx1Q0FBdUM7SUFDL0YsQ0FBQzs7d0hBcFJVLDBCQUEwQjs0R0FBMUIsMEJBQTBCLGkxQkM1QnZDLGkxS0FrRkE7NEZEdERhLDBCQUEwQjtrQkFMdEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUscUJBQXFCO29CQUMvQixXQUFXLEVBQUUsc0NBQXNDO29CQUNuRCxTQUFTLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQztpQkFDbkQ7Mk5BYVksT0FBTztzQkFEakIsS0FBSztnQkFrQkssR0FBRztzQkFEYixLQUFLO2dCQWtDTixZQUFZO3NCQURYLFlBQVk7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFJNUMsT0FBTztzQkFETixZQUFZO3VCQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBSXZDLFVBQVU7c0JBRFQsWUFBWTt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUkxQyxZQUFZO3NCQURYLFlBQVk7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFJNUMsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBSTVDLHNCQUFzQjtzQkFEckIsWUFBWTt1QkFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBSXRELFNBQVM7c0JBRFIsWUFBWTt1QkFBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUl6QyxVQUFVO3NCQURULFlBQVk7dUJBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBSZXNvdXJjZSB9IGZyb20gJ0B3ZXJ0enVpL25neC1oYWwtY2xpZW50JztcclxuaW1wb3J0IHsgUkVTVHdvcmxkQ2xpZW50IH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVzdHdvcmxkLWNsaWVudCc7XHJcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJ1xyXG5pbXBvcnQgeyBSRVNUd29ybGRDbGllbnRDb2xsZWN0aW9uIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVzdHdvcmxkLWNsaWVudC1jb2xsZWN0aW9uJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgQ29uZmlybWF0aW9uU2VydmljZSwgTWVzc2FnZVNlcnZpY2UgfSBmcm9tICdwcmltZW5nL2FwaSc7XHJcbmltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgUHJvYmxlbURldGFpbHMgfSBmcm9tICcuLi8uLi9tb2RlbHMvcHJvYmxlbS1kZXRhaWxzJztcclxuaW1wb3J0IHsgSHR0cFN0YXR1c0NvZGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IENvbnRlbnRDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW50ZXJmYWNlIFByb3BlcnR5RGVzY3JpcHRpb24ge1xyXG4gIGZpZWxkOiBzdHJpbmcsXHJcbiAgdmFsdWU6IGFueSxcclxuICBsYWJlbDogc3RyaW5nLFxyXG4gIHR5cGU6ICd0ZXh0JyB8ICdudW1lcmljJyB8ICdkYXRlJyB8ICdib29sZWFuJyB8ICdvYmplY3QnIHwgJ2FycmF5JyxcclxuICBpc1JlYWRPbmx5OiBib29sZWFuLFxyXG4gIGNoaWxkcmVuPzogUHJvcGVydHlEZXNjcmlwdGlvbltdXHJcbn1cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAncmVzdHdvcmxkLWVkaXQtdmlldycsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3Jlc3R3b3JsZC1lZGl0LXZpZXcuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3Jlc3R3b3JsZC1lZGl0LXZpZXcuY29tcG9uZW50LmNzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBSRVNUd29ybGRFZGl0Vmlld0NvbXBvbmVudCB7XHJcbiAgcHVibGljIGdldCBwcm9wZXJ0aWVzKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuX3Byb3BlcnRpZXM7XHJcbiAgfVxyXG4gIHByaXZhdGUgX3Byb3BlcnRpZXM6IFByb3BlcnR5RGVzY3JpcHRpb25bXSA9IFtdO1xyXG5cclxuICBwdWJsaWMgZ2V0IGZvcm1Hcm91cCgpIHtcclxuICAgIHJldHVybiB0aGlzLl9mb3JtR3JvdXA7XHJcbiAgfVxyXG4gIHByaXZhdGUgX2Zvcm1Hcm91cDogRm9ybUdyb3VwID0gbmV3IEZvcm1Hcm91cCh7fSk7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIHNldCBhcGlOYW1lKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcclxuICAgIHRoaXMuX2FwaU5hbWUgPSB2YWx1ZTtcclxuICAgIHRoaXMubG9hZCgpO1xyXG4gIH1cclxuICBwdWJsaWMgZ2V0IGFwaU5hbWUoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl9hcGlOYW1lO1xyXG4gIH1cclxuICBwcml2YXRlIF9hcGlOYW1lPzogc3RyaW5nO1xyXG4gIC8vQElucHV0KClcclxuICAvL3B1YmxpYyBzZXQgcmVsKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcclxuICAvLyAgdGhpcy5fcmVsID0gdmFsdWU7XHJcbiAgLy99XHJcbiAgLy9wdWJsaWMgZ2V0IHJlbCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gIC8vICByZXR1cm4gdGhpcy5fcmVsO1xyXG4gIC8vfVxyXG4gIC8vcHJpdmF0ZSBfcmVsPzogc3RyaW5nO1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIHNldCB1cmkodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xyXG4gICAgdGhpcy5fdXJpID0gdmFsdWU7XHJcbiAgICB0aGlzLmxvYWQoKTtcclxuICB9XHJcbiAgcHVibGljIGdldCB1cmkoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl91cmk7XHJcbiAgfVxyXG4gIHByaXZhdGUgX3VyaT86IHN0cmluZztcclxuXHJcbiAgcHVibGljIGdldCByZXNvdXJjZSgpIHtcclxuICAgIHJldHVybiB0aGlzLl9yZXNvdXJjZTtcclxuICB9XHJcbiAgcHJpdmF0ZSBfcmVzb3VyY2U/OiBSZXNvdXJjZTtcclxuICBwdWJsaWMgaXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgcHVibGljIGdldCBjYW5TYXZlKCkge1xyXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5yZXNvdXJjZT8uX2xpbmtzW1wic2F2ZVwiXT8ubGVuZ3RoO1xyXG4gICAgcmV0dXJuIGxlbmd0aCAhPT0gdW5kZWZpbmVkICYmIGxlbmd0aCA+IDA7XHJcbiAgfVxyXG4gIHB1YmxpYyBnZXQgY2FuRGVsZXRlKCkge1xyXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5yZXNvdXJjZT8uX2xpbmtzW1wiZGVsZXRlXCJdPy5sZW5ndGg7XHJcbiAgICByZXR1cm4gbGVuZ3RoICE9PSB1bmRlZmluZWQgJiYgbGVuZ3RoID4gMDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBnZXQgZGF0ZUZvcm1hdCgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIG5ldyBEYXRlKDMzMzMsIDEwLCAyMilcclxuICAgICAgLnRvTG9jYWxlRGF0ZVN0cmluZygpXHJcbiAgICAgIC5yZXBsYWNlKFwiMjJcIiwgXCJkZFwiKVxyXG4gICAgICAucmVwbGFjZShcIjExXCIsIFwibW1cIilcclxuICAgICAgLnJlcGxhY2UoXCIzMzMzXCIsIFwieXlcIilcclxuICAgICAgLnJlcGxhY2UoXCIzM1wiLCBcInlcIik7XHJcbiAgfVxyXG5cclxuICBAQ29udGVudENoaWxkKCd2aXN1YWxUYWInLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICB2aXN1YWxUYWJSZWY/OiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdmb3JtJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgZm9ybVJlZj86IFRlbXBsYXRlUmVmPGFueT47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2Zvcm1Sb3cnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBmb3JtUm93UmVmPzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnZm9ybUxhYmVsJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgZm9ybUxhYmVsUmVmPzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnZm9ybUlucHV0JywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgZm9ybUlucHV0UmVmPzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgndmlzdWFsVGFiQWRkaXRpb25hbCcsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIHZpc3VhbFRhYkFkZGl0aW9uYWxSZWY/OiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdyYXdUYWInLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICByYXdUYWJSZWY/OiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdidXR0b25zUmVmJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgYnV0dG9uc1JlZj86IFRlbXBsYXRlUmVmPGFueT47XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBfY2xpZW50czogUkVTVHdvcmxkQ2xpZW50Q29sbGVjdGlvbixcclxuICAgIHByaXZhdGUgX2NvbmZpcm1hdGlvblNlcnZpY2U6IENvbmZpcm1hdGlvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIF9tZXNzYWdlU2VydmljZTogTWVzc2FnZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIF9sb2NhdGlvbjogTG9jYXRpb24sXHJcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcikge1xyXG5cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0Q2xpZW50KCk6IFJFU1R3b3JsZENsaWVudCB7XHJcbiAgICBpZiAoIXRoaXMuYXBpTmFtZSlcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZ2V0IGEgY2xpZW50LCBiZWNhdXNlIHRoZSBhcGlOYW1lIGlzIG5vdCBzZXQuJyk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudHMuZ2V0Q2xpZW50KHRoaXMuYXBpTmFtZSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgc2F2ZSgpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICghdGhpcy5hcGlOYW1lIHx8ICF0aGlzLnVyaSB8fCAhdGhpcy5yZXNvdXJjZSlcclxuICAgICAgcmV0dXJuO1xyXG5cclxuICAgIE9iamVjdC5hc3NpZ24odGhpcy5yZXNvdXJjZSwgdGhpcy5mb3JtR3JvdXAudmFsdWUpO1xyXG4gICAgY29uc3Qgc2VsZkhyZWZCZWZvcmVTYXZlID0gdGhpcy5yZXNvdXJjZS5fbGlua3Muc2VsZlswXS5ocmVmO1xyXG5cclxuICAgIHRoaXMuaXNMb2FkaW5nID0gdHJ1ZTtcclxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKS5zYXZlKHRoaXMucmVzb3VyY2UpO1xyXG4gICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZTtcclxuXHJcbiAgICBpZiAoIXJlc3BvbnNlLm9rIHx8IFByb2JsZW1EZXRhaWxzLmlzUHJvYmxlbURldGFpbHMocmVzcG9uc2UuYm9keSkpIHtcclxuICAgICAgY29uc3QgbWVzc2FnZSA9IHJlc3BvbnNlLnN0YXR1cyA9PT0gSHR0cFN0YXR1c0NvZGUuQ29uZmxpY3QgPyAnU29tZW9uZSBlbHNlIG1vZGlmaWVkIHRoZSByZXNvdXJjZS4gVHJ5IHJlbG9hZGluZyBpdCBhbmQgYXBwbHkgeW91ciBjaGFuZ2VzIGFnYWluLicgOiAnRXJyb3Igd2hpbGUgc2F2aW5nIHRoZSByZXNvdXJjZS4nO1xyXG4gICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5hZGQoeyBzZXZlcml0eTogJ2Vycm9yJywgc3VtbWFyeTogJ0Vycm9yJywgZGV0YWlsOiBtZXNzYWdlLCBkYXRhOiByZXNwb25zZSB9KTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICBjb25zdCBzZWxmSHJlZkFmdGVyU2F2ZSA9IHRoaXMucmVzb3VyY2UuX2xpbmtzLnNlbGZbMF0uaHJlZjtcclxuXHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT5cclxuICAgICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5hZGQoeyBzZXZlcml0eTogJ3N1Y2Nlc3MnLCBzdW1tYXJ5OiAnU2F2ZWQnLCBkZXRhaWw6ICdUaGUgcmVzb3VyY2UgaGFzIGJlZW4gc2F2ZWQuJyB9KSxcclxuICAgICAgICAxMDApO1xyXG5cclxuICAgICAgaWYgKHNlbGZIcmVmQmVmb3JlU2F2ZSAhPT0gc2VsZkhyZWZBZnRlclNhdmUpIHtcclxuICAgICAgICB0aGlzLl9yb3V0ZXIubmF2aWdhdGUoWycvZWRpdCcsIHRoaXMuYXBpTmFtZSwgc2VsZkhyZWZBZnRlclNhdmVdKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIHB1YmxpYyBzaG93RGVsZXRlQ29uZmlybWF0aW9Nb2RhbCgpIHtcclxuICAgIHRoaXMuX2NvbmZpcm1hdGlvblNlcnZpY2UuY29uZmlybSh7XHJcbiAgICAgIG1lc3NhZ2U6ICdEbyB5b3UgcmVhbGx5IHdhbnQgdG8gZGVsZXRlIHRoaXMgcmVzb3VyY2U/JyxcclxuICAgICAgaGVhZGVyOiAnQ29uZmlybSBkZWxldGUnLFxyXG4gICAgICBpY29uOiAnZmFyIGZhLXRyYXNoLWFsdCcsXHJcbiAgICAgIGFjY2VwdDogKCkgPT4gdGhpcy5kZWxldGUoKVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgZGVsZXRlKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgaWYgKCF0aGlzLmFwaU5hbWUgfHwgIXRoaXMudXJpIHx8ICF0aGlzLnJlc291cmNlKVxyXG4gICAgICByZXR1cm47XHJcblxyXG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLnJlc291cmNlLCB0aGlzLmZvcm1Hcm91cC52YWx1ZSk7XHJcblxyXG4gICAgYXdhaXQgdGhpcy5nZXRDbGllbnQoKS5kZWxldGUodGhpcy5yZXNvdXJjZSk7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+XHJcbiAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLmFkZCh7IHNldmVyaXR5OiAnc3VjY2VzcycsIHN1bW1hcnk6ICdEZWxldGVkJywgZGV0YWlsOiAnVGhlIHJlc291cmNlIGhhcyBiZWVuIGRlbGV0ZWQuJyB9KSxcclxuICAgICAgMTAwKTtcclxuXHJcbiAgICB0aGlzLl9sb2NhdGlvbi5iYWNrKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgbG9hZCgpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICghdGhpcy5hcGlOYW1lIHx8ICF0aGlzLnVyaSlcclxuICAgICAgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMuaXNMb2FkaW5nID0gdHJ1ZTtcclxuXHJcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCkuZ2V0U2luZ2xlKHRoaXMudXJpKTtcclxuICAgIGlmICghcmVzcG9uc2Uub2sgfHwgUHJvYmxlbURldGFpbHMuaXNQcm9ibGVtRGV0YWlscyhyZXNwb25zZS5ib2R5KSB8fCAhcmVzcG9uc2UuYm9keSkge1xyXG4gICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5hZGQoeyBzZXZlcml0eTogJ2Vycm9yJywgc3VtbWFyeTogJ0Vycm9yJywgZGV0YWlsOiAnRXJyb3Igd2hpbGUgbG9hZGluZyB0aGUgcmVzb3VyY2UgZnJvbSB0aGUgQVBJLicsIGRhdGE6IHJlc3BvbnNlIH0pXHJcbiAgICB9XHJcbiAgICBlbHNlIHtcclxuICAgICAgdGhpcy5fcmVzb3VyY2UgPSByZXNwb25zZS5ib2R5O1xyXG4gICAgICB0aGlzLl9wcm9wZXJ0aWVzID0gUkVTVHdvcmxkRWRpdFZpZXdDb21wb25lbnQuY3JlYXRlUHJvcGVyeUluZm9zKHRoaXMuX3Jlc291cmNlKTtcclxuICAgICAgdGhpcy5fZm9ybUdyb3VwID0gUkVTVHdvcmxkRWRpdFZpZXdDb21wb25lbnQuY3JlYXRlRm9ybUdyb3VwKHRoaXMuX3Byb3BlcnRpZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgY3JlYXRlRm9ybUdyb3VwKHByb3BlcnRpZXM6IFByb3BlcnR5RGVzY3JpcHRpb25bXSk6IEZvcm1Hcm91cCB7XHJcbiAgICBjb25zdCBjb250cm9scyA9IE9iamVjdC5mcm9tRW50cmllcyhwcm9wZXJ0aWVzLm1hcChwID0+IFtcclxuICAgICAgcC5maWVsZCxcclxuICAgICAgcC50eXBlID09PSAnb2JqZWN0JyAmJiBwLmNoaWxkcmVuID8gUkVTVHdvcmxkRWRpdFZpZXdDb21wb25lbnQuY3JlYXRlRm9ybUdyb3VwKHAuY2hpbGRyZW4pIDogbmV3IEZvcm1Db250cm9sKHAudmFsdWUpXHJcbiAgICBdKSk7XHJcbiAgICBjb25zdCBmb3JtR3JvdXAgPSBuZXcgRm9ybUdyb3VwKGNvbnRyb2xzKTtcclxuICAgIHJldHVybiBmb3JtR3JvdXA7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXRpYyBjcmVhdGVQcm9wZXJ5SW5mb3MocmVzb3VyY2U6IGFueSk6IFByb3BlcnR5RGVzY3JpcHRpb25bXSB7XHJcbiAgICBpZiAoIXJlc291cmNlKVxyXG4gICAgICByZXR1cm4gW107XHJcblxyXG4gICAgLy8gR2V0IGFsbCBkaXN0aW5jdCBwcm9wZXJ0aWVzIGZyb20gYWxsIHJvd3NcclxuICAgIC8vIFdlIGxvb2sgYXQgYWxsIHJvd3MgdG8gZWxpbWluYXRlIHBvc3NpYmxlIHVuZGVmaW5lZCB2YWx1ZXNcclxuICAgIGNvbnN0IHByb3BlcnRpZXMgPSBPYmplY3QuZW50cmllcyhyZXNvdXJjZSlcclxuICAgICAgLmZpbHRlcihwID0+XHJcbiAgICAgICAgcFswXSAhPT0gJ19saW5rcycgJiZcclxuICAgICAgICBwWzBdICE9PSAnX2VtYmVkZGVkJyAmJlxyXG4gICAgICAgIHBbMF0gIT09ICdpZCcgJiZcclxuICAgICAgICBwWzBdICE9PSAndGltZXN0YW1wJyk7XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHJvd3MgYXJlIGVudGl0aWVzIHdpdGggY2hhbmdlIHRyYWNraW5nXHJcbiAgICBjb25zdCB3aXRob3V0Q2hhbmdlVHJhY2tpbmdQcm9wZXJ0aWVzID0gcHJvcGVydGllcy5maWx0ZXIocCA9PlxyXG4gICAgICBwWzBdICE9PSAnY3JlYXRlZEF0JyAmJlxyXG4gICAgICBwWzBdICE9PSAnY3JlYXRlZEJ5JyAmJlxyXG4gICAgICBwWzBdICE9PSAnbGFzdENoYW5nZWRBdCcgJiZcclxuICAgICAgcFswXSAhPT0gJ2xhc3RDaGFuZ2VkQnknKTtcclxuICAgIGNvbnN0IGhhc0NoYW5nZVRyYWNraW5nUHJvcGVydGllcyA9IHdpdGhvdXRDaGFuZ2VUcmFja2luZ1Byb3BlcnRpZXMubGVuZ3RoIDwgcHJvcGVydGllcy5sZW5ndGg7XHJcblxyXG4gICAgLy8gRmlyc3QgdGhlIGlkLCB0aGVuIGFsbCBvdGhlciBwcm9wZXJ0aWVzXHJcbiAgICBjb25zdCBzb3J0ZWRQcm9wZXJ0aWVzOiBbc3RyaW5nLCBhbnldW10gPSBbXTtcclxuICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkoJ2lkJykpXHJcbiAgICAgIHNvcnRlZFByb3BlcnRpZXMucHVzaChbJ2lkJywgcmVzb3VyY2VbJ2lkJ11dKTtcclxuXHJcbiAgICBzb3J0ZWRQcm9wZXJ0aWVzLnB1c2goLi4ud2l0aG91dENoYW5nZVRyYWNraW5nUHJvcGVydGllcyk7XHJcblxyXG4gICAgLy8gQW5kIGNoYW5nZSB0cmFja2luZyBwcm9wZXJ0aWVzIGF0IHRoZSBlbmRcclxuICAgIGlmIChoYXNDaGFuZ2VUcmFja2luZ1Byb3BlcnRpZXMpIHtcclxuICAgICAgc29ydGVkUHJvcGVydGllcy5wdXNoKFsnY3JlYXRlZEF0JywgcmVzb3VyY2VbJ2NyZWF0ZWRBdCddXSk7XHJcbiAgICAgIHNvcnRlZFByb3BlcnRpZXMucHVzaChbJ2NyZWF0ZWRCeScsIHJlc291cmNlWydjcmVhdGVkQnknXV0pO1xyXG4gICAgICBzb3J0ZWRQcm9wZXJ0aWVzLnB1c2goWydsYXN0Q2hhbmdlZEF0JywgcmVzb3VyY2VbJ2xhc3RDaGFuZ2VkQXQnXV0pO1xyXG4gICAgICBzb3J0ZWRQcm9wZXJ0aWVzLnB1c2goWydsYXN0Q2hhbmdlZEJ5JywgcmVzb3VyY2VbJ2xhc3RDaGFuZ2VkQnknXV0pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHByb3BlcnR5RGVzY3JpcHRpb25zOiBQcm9wZXJ0eURlc2NyaXB0aW9uW10gPSBzb3J0ZWRQcm9wZXJ0aWVzXHJcbiAgICAgIC5tYXAocCA9PiAoe1xyXG4gICAgICAgIGZpZWxkOiBwWzBdLFxyXG4gICAgICAgIHZhbHVlOiBwWzFdLFxyXG4gICAgICAgIGxhYmVsOiBSRVNUd29ybGRFZGl0Vmlld0NvbXBvbmVudC50b1RpdGxlQ2FzZShwWzBdKSxcclxuICAgICAgICB0eXBlOiBSRVNUd29ybGRFZGl0Vmlld0NvbXBvbmVudC5nZXRDb2x1bW5UeXBlKHBbMF0sIHBbMV0pLFxyXG4gICAgICAgIGlzUmVhZE9ubHk6IFJFU1R3b3JsZEVkaXRWaWV3Q29tcG9uZW50LmdldElzUmVhZE9ubHkocFswXSlcclxuICAgICAgfSkpO1xyXG5cclxuICAgIGZvciAodmFyIGRlc2NyaXB0aW9uIG9mIHByb3BlcnR5RGVzY3JpcHRpb25zKSB7XHJcbiAgICAgIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gUkVTVHdvcmxkRWRpdFZpZXdDb21wb25lbnQuY3JlYXRlUHJvcGVyeUluZm9zKGRlc2NyaXB0aW9uLnZhbHVlKTtcclxuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKGQgPT4gZGVzY3JpcHRpb24uZmllbGQgKyAnLicgKyBkLmZpZWxkKTtcclxuICAgICAgICBkZXNjcmlwdGlvbi5jaGlsZHJlbiA9IGNoaWxkcmVuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHByb3BlcnR5RGVzY3JpcHRpb25zO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0SXNSZWFkT25seShmaWVsZDogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gZmllbGQgPT09ICdpZCcgfHwgZmllbGQgPT09ICdjcmVhdGVkQXQnIHx8IGZpZWxkID09PSAnY3JlYXRlZEJ5JyB8fCBmaWVsZCA9PT0gJ2xhc3RDaGFuZ2VkQXQnIHx8IGZpZWxkID09PSAnbGFzdENoYW5nZWRCeSc7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXRpYyBnZXRDb2x1bW5UeXBlKGZpZWxkOiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcclxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKVxyXG4gICAgICByZXR1cm4gJ3RleHQnO1xyXG5cclxuICAgIGlmIChfLmlzTnVtYmVyKHZhbHVlKSlcclxuICAgICAgcmV0dXJuICdudW1lcmljJztcclxuXHJcbiAgICBpZiAoXy5pc0RhdGUodmFsdWUpKVxyXG4gICAgICByZXR1cm4gJ2RhdGUnXHJcblxyXG4gICAgaWYgKF8uaXNTdHJpbmcodmFsdWUpKSB7XHJcbiAgICAgIHJldHVybiAndGV4dCc7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKF8uaXNCb29sZWFuKHZhbHVlKSlcclxuICAgICAgcmV0dXJuICdib29sZWFuJztcclxuXHJcbiAgICBpZiAoXy5pc09iamVjdCh2YWx1ZSkpXHJcbiAgICAgIHJldHVybiAnb2JqZWN0J1xyXG5cclxuICAgIGlmIChfLmlzQXJyYXkodmFsdWUpKVxyXG4gICAgICByZXR1cm4gJ2FycmF5J1xyXG5cclxuICAgIHJldHVybiAndGV4dCdcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RhdGljIHRvVGl0bGVDYXNlKGFueUNhc2U6IHN0cmluZykge1xyXG4gICAgcmV0dXJuIGFueUNhc2VcclxuICAgICAgLnJlcGxhY2UoLyhfKSsvZywgJyAnKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVuZGVyc2NvcmUgdG8gd2hpdGVzcGFjZVxyXG4gICAgICAucmVwbGFjZSgvKFthLXpdKShbQS1aXVthLXpdKS9nLCBcIiQxICQyXCIpICAgICAgICAgICAvLyBpbnNlcnQgc3BhY2UgYmVmb3JlIGVhY2ggbmV3IHdvcmQgaWYgdGhlcmUgaXMgbm9uZVxyXG4gICAgICAucmVwbGFjZSgvKFtBLVpdW2Etel0pKFtBLVpdKS9nLCBcIiQxICQyXCIpICAgICAgICAgICAvLyBpbnNlcnQgc3BhY2UgYWZ0ZXIgZWFjaCB3b3JkIGlmIHRoZXJlIGlzIG5vbmVcclxuICAgICAgLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0rW2Etel0pL2csIFwiJDEgJDJcIikgICAgICAgICAgLy8gaW5zZXJ0IHNwYWNlIGFmdGVyIHNpbmdsZSBsZXR0ZXIgd29yZCBpZiB0aGVyZSBpcyBub25lXHJcbiAgICAgIC5yZXBsYWNlKC8oW0EtWl0rKShbQS1aXVthLXpdW2Etel0pL2csIFwiJDEgJDJcIikgICAgIC8vIGluc2VydCBzcGFjZSBiZWZvcmUgc2luZ2xlIGxldHRlciB3b3JkIGlmIHRoZXJlIGlzIG5vbmVcclxuICAgICAgLnJlcGxhY2UoLyhbYS16XSspKFtBLVowLTldKykvZywgXCIkMSAkMlwiKSAgICAgICAgICAgLy8gaW5zZXJ0IHNwYWNlIGFmdGVyIG51bWJlcnNcclxuICAgICAgLnJlcGxhY2UoL14uLywgKG1hdGNoKSA9PiBtYXRjaC50b1VwcGVyQ2FzZSgpKTsgICAgIC8vIGNoYW5nZSBmaXJzdCBsZXR0ZXIgdG8gYmUgdXBwZXIgY2FzZVxyXG4gIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiZ3JpZFwiPlxyXG4gIDxkaXYgY2xhc3M9XCJjb2xcIj5cclxuICAgIDxoMT5FZGl0IHJlc291cmNlPC9oMT5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1Hcm91cFwiIChuZ1N1Ym1pdCk9XCJzYXZlKClcIj5cclxuICA8cC10YWJWaWV3PlxyXG4gICAgPHAtdGFiUGFuZWwgaGVhZGVyPVwiVmlzdWFsXCIgW2Rpc2FibGVkXT1cIiFyZXNvdXJjZSB8fCBpc0xvYWRpbmdcIj5cclxuICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0VmlzdWFsVGFiPlxyXG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhcmVzb3VyY2UgJiYgaXNMb2FkaW5nXCI+XHJcbiAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBpIG9mIFsxLCAyLCAzLCA0LCA1XVwiIGNsYXNzPVwiZ3JpZCBmaWVsZFwiPlxyXG4gICAgICAgICAgICA8cC1za2VsZXRvbiBjbGFzcz1cImNvbC0xMiBtYi0yIG1kOmNvbC0yIG1kOm1iLTBcIiBoZWlnaHQ9XCIzOXB4XCI+PC9wLXNrZWxldG9uPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIG1kOmNvbC0xMFwiPlxyXG4gICAgICAgICAgICAgIDxwLXNrZWxldG9uIGNsYXNzPVwidy1mdWxsXCIgaGVpZ2h0PVwiMzlweFwiPjwvcC1za2VsZXRvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgPGRpdiAqbmdJZj1cInJlc291cmNlXCIgY2xhc3M9XCJibG9ja2FibGUtY29udGFpbmVyXCI+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmxvY2thYmxlLWVsZW1lbnRcIj5cclxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0Rm9ybSBsZXQtcHJvcGVydGllcz1cInByb3BlcnRpZXNcIiBsZXQtZm9ybUdyb3VwPVwiZm9ybUdyb3VwXCI+XHJcbiAgICAgICAgICAgICAgPGRpdiBbZm9ybUdyb3VwXT1cImZvcm1Hcm91cFwiPlxyXG4gICAgICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgcHJvcGVydHkgb2YgcHJvcGVydGllc1wiIGNsYXNzPVwiZ3JpZCBmaWVsZFwiPlxyXG4gICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRGb3JtUm93PlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjZGVmYXVsdEZvcm1MYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwicHJvcGVydHkuZmllbGRcIiBjbGFzcz1cImNvbC0xMiBtYi0yIG1kOmNvbC0yIG1kOm1iLTBcIiBbY2xhc3MucC1kaXNhYmxlZF09XCJwcm9wZXJ0eS5pc1JlYWRPbmx5XCIgW2NsYXNzLmhhc0NoaWxkcmVuXT1cInByb3BlcnR5LmNoaWxkcmVuPy5sZW5ndGggPiAwXCI+e3twcm9wZXJ0eS5sYWJlbH19PC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJmb3JtTGFiZWxSZWYgfHwgZGVmYXVsdEZvcm1MYWJlbDsgY29udGV4dDp7ICRpbXBsaWNpdDogcHJvcGVydHkgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjZGVmYXVsdEZvcm1JbnB1dCBsZXQtcHJvcGVydHkgbGV0LWZvcm1Hcm91cD1cImZvcm1Hcm91cFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IFtuZ1N3aXRjaF09XCJwcm9wZXJ0eS50eXBlXCIgY2xhc3M9XCJjb2wtMTIgbWQ6Y29sLTEwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgKm5nU3dpdGNoQ2FzZT1cIid0ZXh0J1wiIFtmb3JtQ29udHJvbE5hbWVdPVwicHJvcGVydHkuZmllbGRcIiBbaWRdPVwicHJvcGVydHkuZmllbGRcIiB0eXBlPVwidGV4dFwiIHBJbnB1dFRleHQgY2xhc3M9XCJ3LWZ1bGxcIiBbY2xhc3MucC1kaXNhYmxlZF09XCJwcm9wZXJ0eS5pc1JlYWRPbmx5XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1jYWxlbmRhciAqbmdTd2l0Y2hDYXNlPVwiJ2RhdGUnXCIgW2Zvcm1Db250cm9sTmFtZV09XCJwcm9wZXJ0eS5maWVsZFwiIFtpZF09XCJwcm9wZXJ0eS5maWVsZFwiIFtkYXRlRm9ybWF0XT1cImRhdGVGb3JtYXRcIiBbc2hvd1RpbWVdPVwidHJ1ZVwiIFtzaG93SWNvbl09XCJ0cnVlXCIgc3R5bGVDbGFzcz1cInctZnVsbFwiIFtjbGFzcy5wLWRpc2FibGVkXT1cInByb3BlcnR5LmlzUmVhZE9ubHlcIj48L3AtY2FsZW5kYXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1pbnB1dE51bWJlciAqbmdTd2l0Y2hDYXNlPVwiJ251bWVyaWMnXCIgW2Zvcm1Db250cm9sTmFtZV09XCJwcm9wZXJ0eS5maWVsZFwiIFtpZF09XCJwcm9wZXJ0eS5maWVsZFwiIG1vZGU9XCJkZWNpbWFsXCIgW3Nob3dCdXR0b25zXT1cIiFwcm9wZXJ0eS5pc1JlYWRPbmx5XCIgY2xhc3M9XCJ3LWZ1bGxcIiBzdHlsZUNsYXNzPVwidy1mdWxsXCIgW2NsYXNzLnAtZGlzYWJsZWRdPVwicHJvcGVydHkuaXNSZWFkT25seVwiPjwvcC1pbnB1dE51bWJlcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwLWNoZWNrYm94ICpuZ1N3aXRjaENhc2U9XCInYm9vbGVhbidcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybUdyb3VwLmNvbnRyb2xzW3Byb3BlcnR5LmZpZWxkXVwiIFtpZF09XCJwcm9wZXJ0eS5maWVsZFwiIFtyZWFkb25seV09XCJwcm9wZXJ0eS5pc1JlYWRPbmx5XCI+PC9wLWNoZWNrYm94PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ29iamVjdCdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZm9ybVJlZiB8fCBkZWZhdWx0Rm9ybTsgY29udGV4dDp7IHByb3BlcnRpZXM6IHByb3BlcnR5LmNoaWxkcmVuLCBmb3JtR3JvdXA6IGZvcm1Hcm91cC5jb250cm9sc1twcm9wZXJ0eS5maWVsZF0gfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImZvcm1JbnB1dFJlZiB8fCBkZWZhdWx0Rm9ybUlucHV0OyBjb250ZXh0OnsgJGltcGxpY2l0OiBwcm9wZXJ0eSwgZm9ybUdyb3VwOiBmb3JtR3JvdXAgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZm9ybVJvd1JlZiB8fCBkZWZhdWx0Rm9ybVJvdzsgY29udGV4dDp7ICRpbXBsaWNpdDogcHJvcGVydHkgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJmb3JtUmVmIHx8IGRlZmF1bHRGb3JtOyBjb250ZXh0OiB7IHByb3BlcnRpZXM6IHByb3BlcnRpZXMsIGZvcm1Hcm91cDogZm9ybUdyb3VwIH1cIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJsb2NrYWJsZS1vdmVybGF5XCIgKm5nSWY9XCJpc0xvYWRpbmdcIj5cclxuICAgICAgICAgICAgPHAtcHJvZ3Jlc3NTcGlubmVyPjwvcC1wcm9ncmVzc1NwaW5uZXI+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInZpc3VhbFRhYlJlZiB8fCBkZWZhdWx0VmlzdWFsVGFiXCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ2aXN1YWxUYWJBZGRpdGlvbmFsUmVmIHx8IG51bGw7IGNvbnRleHQ6eyAkaW1wbGljaXQ6IHJlc291cmNlLCBwcm9wZXJ0aWVzOiBwcm9wZXJ0aWVzLCBpc0xvYWRpbmc6IGlzTG9hZGluZyB9XCI+PC9uZy1jb250YWluZXI+XHJcbiAgICA8L3AtdGFiUGFuZWw+XHJcblxyXG4gICAgPHAtdGFiUGFuZWwgaGVhZGVyPVwiUmF3XCIgW2Rpc2FibGVkXT1cIiFyZXNvdXJjZSB8fCBpc0xvYWRpbmdcIj5cclxuICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0UmF3VGFiPlxyXG4gICAgICAgIDxwcmU+e3tyZXNvdXJjZSB8IGpzb259fTwvcHJlPlxyXG4gICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwicmF3VGFiUmVmIHx8IGRlZmF1bHRSYXdUYWJcIj48L25nLWNvbnRhaW5lcj5cclxuICAgIDwvcC10YWJQYW5lbD5cclxuICA8L3AtdGFiVmlldz5cclxuXHJcbiAgPGRpdiBjbGFzcz1cImdyaWRcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2xcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImZsZXgganVzdGlmeS1jb250ZW50LWVuZCB3LWZ1bGxcIj5cclxuICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRCdXR0b25zPlxyXG4gICAgICAgICAgPGJ1dHRvbiBwQnV0dG9uIHBSaXBwbGUgdHlwZT1cInN1Ym1pdFwiIGxhYmVsPVwiU2F2ZVwiIGljb249XCJmYXIgZmEtc2F2ZVwiIGNsYXNzPVwibXgtMiBwLWJ1dHRvbi1zdWNjZXNzXCIgW2Rpc2FibGVkXT1cIiFyZXNvdXJjZSB8fCBpc0xvYWRpbmcgfHwgIWNhblNhdmVcIj48L2J1dHRvbj5cclxuICAgICAgICAgIDxidXR0b24gcEJ1dHRvbiBwUmlwcGxlIHR5cGU9XCJidXR0b25cIiBsYWJlbD1cIlJlbG9hZFwiIGljb249XCJmYXMgZmEtcmVkb1wiIGNsYXNzPVwibXgtMiBwLWJ1dHRvbi1pbmZvXCIgKGNsaWNrKT1cImxvYWQoKVwiIFtkaXNhYmxlZF09XCJpc0xvYWRpbmdcIj48L2J1dHRvbj5cclxuICAgICAgICAgIDxidXR0b24gcEJ1dHRvbiBwUmlwcGxlIHR5cGU9XCJidXR0b25cIiBsYWJlbD1cIkRlbGV0ZVwiIGljb249XCJmYXIgZmEtdHJhc2gtYWx0XCIgY2xhc3M9XCJteC0yIHAtYnV0dG9uLWRhbmdlclwiIChjbGljayk9XCJzaG93RGVsZXRlQ29uZmlybWF0aW9Nb2RhbCgpXCIgW2Rpc2FibGVkXT1cIiFyZXNvdXJjZSB8fCBpc0xvYWRpbmcgfHwgIWNhbkRlbGV0ZVwiPjwvYnV0dG9uPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImJ1dHRvbnNSZWYgfHwgZGVmYXVsdEJ1dHRvbnNcIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuXHJcbjwvZm9ybT5cclxuXHJcbjxwLXRvYXN0PjwvcC10b2FzdD5cclxuPHAtY29uZmlybURpYWxvZz48L3AtY29uZmlybURpYWxvZz5cclxuIl19
335
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdHdvcmxkLWVkaXQtdmlldy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL3ZpZXdzL3Jlc3R3b3JsZC1lZGl0LXZpZXcvcmVzdHdvcmxkLWVkaXQtdmlldy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtcmVzdHdvcmxkLWNsaWVudC9zcmMvbGliL3ZpZXdzL3Jlc3R3b3JsZC1lZGl0LXZpZXcvcmVzdHdvcmxkLWVkaXQtdmlldy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFFLFlBQVksRUFBMEQsTUFBTSx5QkFBeUIsQ0FBQztBQUcvRyxPQUFPLEVBQWdDLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSXpFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7OztBQVU3QyxNQUFNLE9BQU8sMEJBQTBCO0lBZ0pyQyxZQUNVLFFBQW1DLEVBQ25DLG9CQUF5QyxFQUN6QyxlQUErQixFQUMvQixTQUFtQixFQUNuQixPQUFlLEVBQ2YsWUFBeUIsRUFDakMsZUFBZ0M7UUFOeEIsYUFBUSxHQUFSLFFBQVEsQ0FBMkI7UUFDbkMseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFxQjtRQUN6QyxvQkFBZSxHQUFmLGVBQWUsQ0FBZ0I7UUFDL0IsY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUNuQixZQUFPLEdBQVAsT0FBTyxDQUFRO1FBQ2YsaUJBQVksR0FBWixZQUFZLENBQWE7UUEvSTNCLGVBQVUsR0FBYyxFQUFFLENBQUM7UUFTM0IsY0FBUyxHQUFr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LEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFJN0MsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBSTVDLHNCQUFzQjtzQkFEckIsWUFBWTt1QkFBQyxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBSXRELGdCQUFnQjtzQkFEZixZQUFZO3VCQUFDLGVBQWUsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBSWhELGFBQWE7c0JBRFosWUFBWTt1QkFBQyxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUk3QyxZQUFZO3NCQURYLFlBQVk7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFJNUMsZUFBZTtzQkFEZCxZQUFZO3VCQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFByb3BlcnR5VHlwZSwgUmVzb3VyY2UsIFRlbXBsYXRlLCBUZW1wbGF0ZXMsIEZvcm1zUmVzb3VyY2UsIFByb3BlcnR5IH0gZnJvbSAnQHdlcnR6dWkvbmd4LWhhbC1jbGllbnQnO1xyXG5pbXBvcnQgeyBSRVNUd29ybGRDbGllbnQgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9yZXN0d29ybGQtY2xpZW50JztcclxuaW1wb3J0IHsgUkVTVHdvcmxkQ2xpZW50Q29sbGVjdGlvbiB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3Jlc3R3b3JsZC1jbGllbnQtY29sbGVjdGlvbic7XHJcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgQ29uZmlybWF0aW9uU2VydmljZSwgTWVzc2FnZVNlcnZpY2UgfSBmcm9tICdwcmltZW5nL2FwaSc7XHJcbmltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgUHJvYmxlbURldGFpbHMgfSBmcm9tICcuLi8uLi9tb2RlbHMvcHJvYmxlbS1kZXRhaWxzJztcclxuaW1wb3J0IHsgQ29udGVudENoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFZhbGRlbW9ydENvbmZpZyB9IGZyb20gJ25neC12YWxkZW1vcnQnO1xyXG5pbXBvcnQgeyBGb3JtU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2Zvcm0uc2VydmljZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ3J3LWVkaXQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9yZXN0d29ybGQtZWRpdC12aWV3LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9yZXN0d29ybGQtZWRpdC12aWV3LmNvbXBvbmVudC5jc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgUkVTVHdvcmxkRWRpdFZpZXdDb21wb25lbnQge1xyXG4gIHB1YmxpYyBnZXQgUHJvcGVydHlUeXBlKCkge1xyXG4gICAgcmV0dXJuIFByb3BlcnR5VHlwZTtcclxuICB9XHJcbiAgcHVibGljIGdldCB0ZW1wbGF0ZXMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fdGVtcGxhdGVzO1xyXG4gIH1cclxuICBwcml2YXRlIF90ZW1wbGF0ZXM6IFRlbXBsYXRlcyA9IHt9O1xyXG5cclxuICBwdWJsaWMgZ2V0IGlzTG9hZGluZ0ZvclRoZUZpcnN0VGltZSgpIHtcclxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnRlbXBsYXRlcykubGVuZ3RoID09PSAwICYmIHRoaXMuaXNMb2FkaW5nO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGdldCBmb3JtVGFicygpIHtcclxuICAgIHJldHVybiB0aGlzLl9mb3JtVGFicztcclxuICB9XHJcbiAgcHJpdmF0ZSBfZm9ybVRhYnM6IHsgW25hbWU6IHN0cmluZ106IEZvcm1Hcm91cCB9ID0ge307XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIHNldCBhcGlOYW1lKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcclxuICAgIHRoaXMuX2FwaU5hbWUgPSB2YWx1ZTtcclxuICAgIHRoaXMubG9hZCgpO1xyXG4gIH1cclxuICBwdWJsaWMgZ2V0IGFwaU5hbWUoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl9hcGlOYW1lO1xyXG4gIH1cclxuICBwcml2YXRlIF9hcGlOYW1lPzogc3RyaW5nO1xyXG4gIC8vQElucHV0KClcclxuICAvL3B1YmxpYyBzZXQgcmVsKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcclxuICAvLyAgdGhpcy5fcmVsID0gdmFsdWU7XHJcbiAgLy99XHJcbiAgLy9wdWJsaWMgZ2V0IHJlbCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gIC8vICByZXR1cm4gdGhpcy5fcmVsO1xyXG4gIC8vfVxyXG4gIC8vcHJpdmF0ZSBfcmVsPzogc3RyaW5nO1xyXG4gIEBJbnB1dCgpXHJcbiAgcHVibGljIHNldCB1cmkodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xyXG4gICAgdGhpcy5fdXJpID0gdmFsdWU7XHJcbiAgICB0aGlzLmxvYWQoKTtcclxuICB9XHJcbiAgcHVibGljIGdldCB1cmkoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl91cmk7XHJcbiAgfVxyXG4gIHByaXZhdGUgX3VyaT86IHN0cmluZztcclxuXHJcbiAgcHVibGljIGdldCByZXNvdXJjZSgpIHtcclxuICAgIHJldHVybiB0aGlzLl9yZXNvdXJjZTtcclxuICB9XHJcbiAgcHJpdmF0ZSBfcmVzb3VyY2U/OiBSZXNvdXJjZTtcclxuICBwdWJsaWMgaXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgcHVibGljIGdldCBjYW5TYXZlKCkge1xyXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5yZXNvdXJjZT8uX2xpbmtzW1wic2F2ZVwiXT8ubGVuZ3RoO1xyXG4gICAgcmV0dXJuIGxlbmd0aCAhPT0gdW5kZWZpbmVkICYmIGxlbmd0aCA+IDA7XHJcbiAgfVxyXG4gIHB1YmxpYyBnZXQgY2FuRGVsZXRlKCkge1xyXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5yZXNvdXJjZT8uX2xpbmtzW1wiZGVsZXRlXCJdPy5sZW5ndGg7XHJcbiAgICByZXR1cm4gbGVuZ3RoICE9PSB1bmRlZmluZWQgJiYgbGVuZ3RoID4gMDtcclxuICB9XHJcbiAgcHVibGljIGNhblN1Ym1pdCh0ZW1wbGF0ZU5hbWU6IHN0cmluZykge1xyXG4gICAgY29uc3QgZm9ybSA9IHRoaXMuZm9ybVRhYnNbdGVtcGxhdGVOYW1lXTtcclxuICAgIHJldHVybiBmb3JtICYmIGZvcm0udmFsaWQ7XHJcbiAgfVxyXG5cclxuICBAQ29udGVudENoaWxkKCdleHRyYVRhYnMnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBleHRyYVRhYnNSZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnYnV0dG9ucycsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGJ1dHRvbnNSZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaW5wdXRPcHRpb25zU2luZ2xlJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRPcHRpb25zU2luZ2xlUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0T3B0aW9uc011bHRpcGxlJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRPcHRpb25zTXVsdGlwbGVSZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaW5wdXRPcHRpb25zJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRPcHRpb25zUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0SGlkZGVuJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRIaWRkZW5SZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaW5wdXRUZXh0JywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRUZXh0UmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0VGV4dGFyZWEnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dFRleHRhcmVhUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0U2VhcmNoJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRTZWFyY2hSZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaW5wdXRUZWwnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dFRlbFJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dFVybCcsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGlucHV0VXJsUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0RW1haWwnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dEVtYWlsUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0UGFzc3dvcmQnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dFBhc3N3b3JkUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0RGF0ZScsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGlucHV0RGF0ZVJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dE1vbnRoJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRNb250aFJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dFdlZWsnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dFdlZWtSZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaW5wdXRUaW1lJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRUaW1lUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0RGF0ZXRpbWVMb2NhbCcsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGlucHV0RGF0ZXRpbWVMb2NhbFJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dE51bWJlcicsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGlucHV0TnVtYmVyUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0UmFuZ2UnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dFJhbmdlUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0Q29sb3InLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dENvbG9yUmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2lucHV0Qm9vbCcsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGlucHV0Qm9vbFJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dERhdGV0aW1lT2Zmc2V0JywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXREYXRldGltZU9mZnNldFJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dER1cmF0aW9uJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXREdXJhdGlvblJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dEltYWdlJywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXRJbWFnZVJlZj86IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG5cclxuICBAQ29udGVudENoaWxkKCdpbnB1dEZpbGUnLCB7IHN0YXRpYzogZmFsc2UgfSlcclxuICBpbnB1dEZpbGVSZWY/OiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgQENvbnRlbnRDaGlsZCgnaW5wdXREZWZhdWx0JywgeyBzdGF0aWM6IGZhbHNlIH0pXHJcbiAgaW5wdXREZWZhdWx0UmVmPzogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBfY2xpZW50czogUkVTVHdvcmxkQ2xpZW50Q29sbGVjdGlvbixcclxuICAgIHByaXZhdGUgX2NvbmZpcm1hdGlvblNlcnZpY2U6IENvbmZpcm1hdGlvblNlcnZpY2UsXHJcbiAgICBwcml2YXRlIF9tZXNzYWdlU2VydmljZTogTWVzc2FnZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIF9sb2NhdGlvbjogTG9jYXRpb24sXHJcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcixcclxuICAgIHByaXZhdGUgX2Zvcm1TZXJ2aWNlOiBGb3JtU2VydmljZSxcclxuICAgIHZhbGRlbW9ydENvbmZpZzogVmFsZGVtb3J0Q29uZmlnKSB7XHJcbiAgICB2YWxkZW1vcnRDb25maWcuZXJyb3JDbGFzc2VzID0gJ3AtZXJyb3IgdGV4dC1zbSc7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgZ2V0VG9vbHRpcChyZXNvdXJjZTogUmVzb3VyY2UsIGtleXNUb0V4Y2x1ZGU/OiBzdHJpbmdbXSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCB0b29sdGlwID0gT2JqZWN0LmVudHJpZXMocmVzb3VyY2UpXHJcbiAgICAgIC5maWx0ZXIoKFtrZXldKSA9PiAhKGtleS5zdGFydHNXaXRoKCdfJykgfHwgWydjcmVhdGVkQXQnLCAnY3JlYXRlZEJ5JywgJ2xhc3RDaGFuZ2VkQXQnLCAnbGFzdENoYW5nZWRCeScsICd0aW1lc3RhbXAnXS5pbmNsdWRlcyhrZXkpIHx8IGtleXNUb0V4Y2x1ZGU/LmluY2x1ZGVzKGtleSkpKVxyXG4gICAgICAucmVkdWNlKChwcmV2LCBba2V5LCB2YWx1ZV0sIGluZGV4KSA9PiBgJHtwcmV2fSR7aW5kZXggPT09IDAgPyAnJyA6ICdcXG4nfSR7a2V5fTogJHtSRVNUd29ybGRFZGl0Vmlld0NvbXBvbmVudC5qc29uU3RyaW5naWZ5V2l0aEVsaXBzaXModmFsdWUpfWAsICcnKTtcclxuXHJcbiAgICByZXR1cm4gdG9vbHRpcDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RhdGljIGpzb25TdHJpbmdpZnlXaXRoRWxpcHNpcyh2YWx1ZTogdW5rbm93bikge1xyXG4gICAgY29uc3QgbWF4TGVuZ3RoID0gMjAwO1xyXG4gICAgY29uc3QgZW5kID0gMTA7XHJcbiAgICBjb25zdCBzdGFydCA9IG1heExlbmd0aCAtIGVuZCAtIDI7XHJcbiAgICBjb25zdCBqc29uID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xyXG4gICAgY29uc3Qgc2hvcnRlbmVkID0ganNvbi5sZW5ndGggPiBtYXhMZW5ndGggPyBqc29uLnN1YnN0cmluZygwLCBzdGFydCkgKyAn4oCmJyArIGpzb24uc3Vic3RyaW5nKGpzb24ubGVuZ3RoIC0gZW5kKSA6IGpzb247XHJcblxyXG4gICAgcmV0dXJuIHNob3J0ZW5lZDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0Q2xpZW50KCk6IFJFU1R3b3JsZENsaWVudCB7XHJcbiAgICBpZiAoIXRoaXMuYXBpTmFtZSlcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZ2V0IGEgY2xpZW50LCBiZWNhdXNlIHRoZSBhcGlOYW1lIGlzIG5vdCBzZXQuJyk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuX2NsaWVudHMuZ2V0Q2xpZW50KHRoaXMuYXBpTmFtZSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgc3VibWl0KHRlbXBsYXRlTmFtZTogc3RyaW5nLCB0ZW1wbGF0ZTogVGVtcGxhdGUsIGZvcm1WYWx1ZToge30pIHtcclxuICAgIHRoaXMuaXNMb2FkaW5nID0gdHJ1ZTtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCB0YXJnZXRCZWZvcmVTYXZlID0gdGVtcGxhdGUudGFyZ2V0O1xyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCkuc3VibWl0KHRlbXBsYXRlLCBmb3JtVmFsdWUpO1xyXG5cclxuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xyXG4gICAgICAgIGxldCBzdW1tYXJ5ID0gJ0Vycm9yJztcclxuICAgICAgICBsZXQgZGV0YWlsID0gJ0Vycm9yIHdoaWxlIHNhdmluZyB0aGUgcmVzb3VyY2UuJztcclxuICAgICAgICBpZiAoUHJvYmxlbURldGFpbHMuaXNQcm9ibGVtRGV0YWlscyhyZXNwb25zZS5ib2R5KSkge1xyXG4gICAgICAgICAgY29uc3QgcHJvYmxlbURldGFpbHMgPSByZXNwb25zZS5ib2R5IGFzIFByb2JsZW1EZXRhaWxzO1xyXG4gICAgICAgICAgc3VtbWFyeSA9IHByb2JsZW1EZXRhaWxzLnRpdGxlIHx8IHN1bW1hcnk7XHJcbiAgICAgICAgICBkZXRhaWwgPSBwcm9ibGVtRGV0YWlscy5kZXRhaWwgfHwgZGV0YWlsO1xyXG4gICAgICAgICAgLy8gZGlzcGxheSB2YWxpZGF0aW9uIGVycm9yc1xyXG4gICAgICAgICAgaWYgKHByb2JsZW1EZXRhaWxzWydlcnJvcnMnXSBhcyB7fSkge1xyXG4gICAgICAgICAgICBjb25zdCBmb3JtID0gdGhpcy5mb3JtVGFic1t0ZW1wbGF0ZU5hbWVdO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIGVycm9yc0ZvcktleV0gb2YgT2JqZWN0LmVudHJpZXMocHJvYmxlbURldGFpbHNbJ2Vycm9ycyddIGFzIHt9KSkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IHBhdGggPSBrZXkuc3BsaXQoL1xcLnxcXFsvKS5tYXAoZSA9PiBlLnJlcGxhY2UoXCJdXCIsIFwiXCIpKTtcclxuICAgICAgICAgICAgICBjb25zdCBmb3JtQ29udHJvbCA9IHBhdGgucmVkdWNlPEFic3RyYWN0Q29udHJvbD4oKGNvbnRyb2wsIHBhdGhFbGVtZW50KSA9PiAoY29udHJvbCBpbnN0YW5jZW9mIEZvcm1Hcm91cCA/IGNvbnRyb2wuY29udHJvbHNbcGF0aEVsZW1lbnRdIDogY29udHJvbCkgfHwgY29udHJvbCwgZm9ybSk7XHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2wuc2V0RXJyb3JzKHsgcmVtb3RlOiBlcnJvcnNGb3JLZXkgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLmFkZCh7IHNldmVyaXR5OiAnZXJyb3InLCBzdW1tYXJ5OiBzdW1tYXJ5LCBkZXRhaWw6IGRldGFpbCwgZGF0YTogcmVzcG9uc2UsIGxpZmU6IDEwMDAwIH0pO1xyXG4gICAgICB9XHJcbiAgICAgIGVsc2Uge1xyXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlUmVzb3VyY2UgPSAocmVzcG9uc2UuYm9keSBhcyBGb3Jtc1Jlc291cmNlKTtcclxuICAgICAgICBjb25zdCB0YXJnZXRBZnRlclNhdmUgPSByZXNwb25zZVJlc291cmNlLl90ZW1wbGF0ZXNbdGVtcGxhdGVOYW1lXS50YXJnZXQ7XHJcblxyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT5cclxuICAgICAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLmFkZCh7IHNldmVyaXR5OiAnc3VjY2VzcycsIHN1bW1hcnk6ICdTYXZlZCcsIGRldGFpbDogJ1RoZSByZXNvdXJjZSBoYXMgYmVlbiBzYXZlZC4nIH0pLFxyXG4gICAgICAgICAgMTAwKTtcclxuXHJcbiAgICAgICAgaWYgKHRhcmdldEJlZm9yZVNhdmUgIT09IHRhcmdldEFmdGVyU2F2ZSkge1xyXG4gICAgICAgICAgdGhpcy5fcm91dGVyLm5hdmlnYXRlKFsnL2VkaXQnLCB0aGlzLmFwaU5hbWUsIHJlc3BvbnNlUmVzb3VyY2UuX2xpbmtzLnNlbGZbMF0uaHJlZl0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgIH1cclxuICAgIGNhdGNoIChlOiB1bmtub3duKSB7XHJcbiAgICAgIHRoaXMuX21lc3NhZ2VTZXJ2aWNlLmFkZCh7IHNldmVyaXR5OiAnZXJyb3InLCBzdW1tYXJ5OiAnRXJyb3InLCBkZXRhaWw6IGBBbiB1bmtub3duIGVycm9yIG9jY3VycmVkLiAke0pTT04uc3RyaW5naWZ5KGUpfWAsIGxpZmU6IDEwMDAwIH0pO1xyXG4gICAgICBjb25zb2xlLmxvZyhlKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHNob3dEZWxldGVDb25maXJtYXRpb01vZGFsKCkge1xyXG4gICAgdGhpcy5fY29uZmlybWF0aW9uU2VydmljZS5jb25maXJtKHtcclxuICAgICAgbWVzc2FnZTogJ0RvIHlvdSByZWFsbHkgd2FudCB0byBkZWxldGUgdGhpcyByZXNvdXJjZT8nLFxyXG4gICAgICBoZWFkZXI6ICdDb25maXJtIGRlbGV0ZScsXHJcbiAgICAgIGljb246ICdmYXIgZmEtdHJhc2gtYWx0JyxcclxuICAgICAgYWNjZXB0OiAoKSA9PiB0aGlzLmRlbGV0ZSgpXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBkZWxldGUoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXRoaXMuYXBpTmFtZSB8fCAhdGhpcy51cmkgfHwgIXRoaXMucmVzb3VyY2UpXHJcbiAgICAgIHJldHVybjtcclxuXHJcbiAgICBPYmplY3QuYXNzaWduKHRoaXMucmVzb3VyY2UsIHRoaXMuZm9ybVRhYnMudmFsdWUpO1xyXG5cclxuICAgIGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCkuZGVsZXRlKHRoaXMucmVzb3VyY2UpO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PlxyXG4gICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5hZGQoeyBzZXZlcml0eTogJ3N1Y2Nlc3MnLCBzdW1tYXJ5OiAnRGVsZXRlZCcsIGRldGFpbDogJ1RoZSByZXNvdXJjZSBoYXMgYmVlbiBkZWxldGVkLicgfSksXHJcbiAgICAgIDEwMCk7XHJcblxyXG4gICAgdGhpcy5fbG9jYXRpb24uYmFjaygpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIGxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXRoaXMuYXBpTmFtZSB8fCAhdGhpcy51cmkpXHJcbiAgICAgIHJldHVybjtcclxuXHJcbiAgICB0aGlzLmlzTG9hZGluZyA9IHRydWU7XHJcblxyXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpLmdldFNpbmdsZSh0aGlzLnVyaSk7XHJcbiAgICBpZiAoIXJlc3BvbnNlLm9rIHx8IFByb2JsZW1EZXRhaWxzLmlzUHJvYmxlbURldGFpbHMocmVzcG9uc2UuYm9keSkgfHwgIXJlc3BvbnNlLmJvZHkpIHtcclxuICAgICAgdGhpcy5fbWVzc2FnZVNlcnZpY2UuYWRkKHsgc2V2ZXJpdHk6ICdlcnJvcicsIHN1bW1hcnk6ICdFcnJvcicsIGRldGFpbDogJ0Vycm9yIHdoaWxlIGxvYWRpbmcgdGhlIHJlc291cmNlIGZyb20gdGhlIEFQSS4nLCBkYXRhOiByZXNwb25zZSB9KTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICB0aGlzLl9yZXNvdXJjZSA9IHJlc3BvbnNlLmJvZHk7XHJcbiAgICAgIHRoaXMuX3RlbXBsYXRlcyA9IGF3YWl0IHRoaXMuZ2V0QWxsVGVtcGxhdGVzKHRoaXMuX3Jlc291cmNlKTtcclxuICAgICAgdGhpcy5fZm9ybVRhYnMgPSB0aGlzLl9mb3JtU2VydmljZS5jcmVhdGVGb3JtR3JvdXBzRnJvbVRlbXBsYXRlcyh0aGlzLl90ZW1wbGF0ZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIHNldEluaXRpYWxTZWxlY3RlZE9wdGlvbnNFbGVtZW50c0ZvclRlbXBsYXRlcyh0ZW1wbGF0ZXM6IFRlbXBsYXRlcykge1xyXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKE9iamVjdC52YWx1ZXModGVtcGxhdGVzKVxyXG4gICAgICAubWFwKHRlbXBsYXRlID0+IHRoaXMuc2V0SW5pdGlhbFNlbGVjdGVkT3B0aW9uc0VsZW1lbnRzRm9yVGVtcGxhdGUodGVtcGxhdGUpKSk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgaW1hZ2VDaGFuZ2VkKGZvcm1Db250cm9sOiBGb3JtQ29udHJvbCwgZXZlbnQ6IHsgZmlsZXM6IEZpbGVbXSB9KTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWxlID0gZXZlbnQuZmlsZXNbMF07XHJcbiAgICBjb25zb2xlLmxvZyhmaWxlKTtcclxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICByZWFkZXIub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICBjb25zdCB1cmkgPSByZWFkZXIucmVzdWx0O1xyXG4gICAgICBjb25zb2xlLmxvZyh1cmkpO1xyXG4gICAgICBmb3JtQ29udHJvbC5zZXRWYWx1ZSh1cmkpO1xyXG4gICAgfTtcclxuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBzZXRJbml0aWFsU2VsZWN0ZWRPcHRpb25zRWxlbWVudHNGb3JUZW1wbGF0ZSh0ZW1wbGF0ZTogVGVtcGxhdGUpIHtcclxuICAgIHJldHVybiBQcm9taXNlLmFsbCh0ZW1wbGF0ZS5wcm9wZXJ0aWVzXHJcbiAgICAgIC5maWx0ZXIocHJvcGVydHkgPT4gcHJvcGVydHk/Lm9wdGlvbnM/Lmxpbms/LmhyZWYpXHJcbiAgICAgIC5tYXAocHJvcGVydHkgPT4gdGhpcy5zZXRJbml0aWFsU2VsZWN0ZWRPcHRpb25zRWxlbWVudEZvclByb3BlcnR5KHByb3BlcnR5KSkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBzZXRJbml0aWFsU2VsZWN0ZWRPcHRpb25zRWxlbWVudEZvclByb3BlcnR5KHByb3BlcnR5OiBQcm9wZXJ0eSkge1xyXG4gICAgY29uc3Qgb3B0aW9ucyA9IHByb3BlcnR5Py5vcHRpb25zO1xyXG5cclxuICAgIGlmICghb3B0aW9ucz8ubGluaz8uaHJlZilcclxuICAgICAgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IHRlbXBsYXRlZFVyaSA9IG9wdGlvbnMubGluay5ocmVmO1xyXG4gICAgY29uc3QgZmlsdGVyID0gYCR7b3B0aW9ucy52YWx1ZUZpZWxkfSBlcSAke3Byb3BlcnR5LnZhbHVlfWA7XHJcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCkuZ2V0TGlzdEJ5VXJpKHRlbXBsYXRlZFVyaSwgeyAkZmlsdGVyOiBmaWx0ZXIsICR0b3A6IDEwIH0pO1xyXG4gICAgaWYgKCFyZXNwb25zZS5vayB8fCBQcm9ibGVtRGV0YWlscy5pc1Byb2JsZW1EZXRhaWxzKHJlc3BvbnNlLmJvZHkpIHx8ICFyZXNwb25zZS5ib2R5KSB7XHJcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgQW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgZ2V0dGluZyB0aGUgZmlsdGVyZWQgaXRlbXMuYDtcclxuICAgICAgdGhpcy5fbWVzc2FnZVNlcnZpY2UuYWRkKHsgc2V2ZXJpdHk6ICdlcnJvcicsIHN1bW1hcnk6ICdFcnJvcicsIGRldGFpbDogbWVzc2FnZSwgZGF0YTogcmVzcG9uc2UgfSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBpdGVtcyA9IHJlc3BvbnNlLmJvZHkuX2VtYmVkZGVkLml0ZW1zO1xyXG4gICAgb3B0aW9ucy5pbmxpbmUgPSBpdGVtcztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgZ2V0QWxsVGVtcGxhdGVzKHJlc291cmNlOiBSZXNvdXJjZSk6IFByb21pc2U8VGVtcGxhdGVzPiB7XHJcbiAgICBjb25zdCBmb3JtUmVzcG9uc2VzID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKS5nZXRBbGxGb3JtcyhyZXNvdXJjZSk7XHJcblxyXG4gICAgY29uc3QgZmFpbGVkUmVzcG9uc2VzID0gZm9ybVJlc3BvbnNlcy5maWx0ZXIocmVzcG9uc2UgPT4gIXJlc3BvbnNlLm9rIHx8IFByb2JsZW1EZXRhaWxzLmlzUHJvYmxlbURldGFpbHMocmVzcG9uc2UuYm9keSkgfHwgIXJlc3BvbnNlLmJvZHkpO1xyXG4gICAgaWYgKGZhaWxlZFJlc3BvbnNlcy5sZW5ndGggIT09IDApIHtcclxuICAgICAgZm9yIChjb25zdCByZXNwb25zZSBvZiBmYWlsZWRSZXNwb25zZXMpIHtcclxuICAgICAgICB0aGlzLl9tZXNzYWdlU2VydmljZS5hZGQoeyBzZXZlcml0eTogJ2Vycm9yJywgc3VtbWFyeTogJ0Vycm9yJywgZGV0YWlsOiAnRXJyb3Igd2hpbGUgbG9hZGluZyB0aGUgcmVzb3VyY2UgZnJvbSB0aGUgQVBJLicsIGRhdGE6IHJlc3BvbnNlIH0pO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe30pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZvcm1UZW1wbGF0ZXMgPSBPYmplY3QuYXNzaWduKHt9LCAuLi5mb3JtUmVzcG9uc2VzLm1hcChyZXNwb25zZSA9PiAocmVzcG9uc2UuYm9keSBhcyBGb3Jtc1Jlc291cmNlKS5fdGVtcGxhdGVzKSkgYXMgVGVtcGxhdGVzO1xyXG5cclxuICAgIGF3YWl0IHRoaXMuc2V0SW5pdGlhbFNlbGVjdGVkT3B0aW9uc0VsZW1lbnRzRm9yVGVtcGxhdGVzKGZvcm1UZW1wbGF0ZXMpO1xyXG5cclxuICAgIHJldHVybiBmb3JtVGVtcGxhdGVzO1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiZ3JpZFwiPlxyXG4gIDxkaXYgY2xhc3M9XCJjb2xcIj5cclxuICAgIDxoMT5FZGl0IHJlc291cmNlPC9oMT5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48cC10YWJWaWV3PlxyXG5cclxuICA8cC10YWJQYW5lbCAqbmdJZj1cImlzTG9hZGluZ0ZvclRoZUZpcnN0VGltZVwiIGhlYWRlcj1cIkxvYWRpbmdcIj5cclxuICAgIDxkaXYgKm5nRm9yPVwibGV0IGkgb2YgWzEsIDIsIDMsIDQsIDVdXCIgY2xhc3M9XCJncmlkIGZpZWxkXCI+XHJcbiAgICAgIDxwLXNrZWxldG9uIGNsYXNzPVwiY29sLTEyIG1iLTIgbWQ6Y29sLTIgbWQ6bWItMFwiIGhlaWdodD1cIjM5cHhcIj48L3Atc2tlbGV0b24+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgbWQ6Y29sLTEwXCI+XHJcbiAgICAgICAgPHAtc2tlbGV0b24gY2xhc3M9XCJ3LWZ1bGxcIiBoZWlnaHQ9XCIzOXB4XCI+PC9wLXNrZWxldG9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImdyaWRcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNvbFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGp1c3RpZnktY29udGVudC1lbmQgdy1mdWxsXCI+XHJcbiAgICAgICAgICA8cC1za2VsZXRvbiB3aWR0aD1cIjEyMHB4XCIgaGVpZ2h0PVwiMzlweFwiIGNsYXNzPVwibXgtMlwiPjwvcC1za2VsZXRvbj5cclxuICAgICAgICAgIDxwLXNrZWxldG9uIHdpZHRoPVwiMTIwcHhcIiBoZWlnaHQ9XCIzOXB4XCIgY2xhc3M9XCJteC0yXCI+PC9wLXNrZWxldG9uPlxyXG4gICAgICAgICAgPHAtc2tlbGV0b24gd2lkdGg9XCIxMjBweFwiIGhlaWdodD1cIjM5cHhcIiBjbGFzcz1cIm14LTJcIj48L3Atc2tlbGV0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9wLXRhYlBhbmVsPlxyXG5cclxuICA8cC10YWJQYW5lbCAqbmdGb3I9XCJsZXQgaXRlbSBvZiB0ZW1wbGF0ZXMgfCBrZXl2YWx1ZVwiIFtoZWFkZXJdPVwiaXRlbS52YWx1ZS50aXRsZSB8fCBpdGVtLmtleVwiIFtkaXNhYmxlZF09XCJpc0xvYWRpbmdcIj5cclxuICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZm9ybVRhYnNbaXRlbS5rZXldXCIgKG5nU3VibWl0KT1cInN1Ym1pdChpdGVtLmtleSwgaXRlbS52YWx1ZSwgZm9ybVRhYnNbaXRlbS5rZXldLnZhbHVlKVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiYmxvY2thYmxlLWNvbnRhaW5lclwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJibG9ja2FibGUtZWxlbWVudFwiPlxyXG4gICAgICAgICAgPHJ3LWZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtVGFic1tpdGVtLmtleV1cIiBbdGVtcGxhdGVdPVwiaXRlbS52YWx1ZVwiIFthcGlOYW1lXT1cImFwaU5hbWVcIj48L3J3LWZvcm0+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImJsb2NrYWJsZS1vdmVybGF5XCIgKm5nSWY9XCJpc0xvYWRpbmdcIj5cclxuICAgICAgICAgIDxwLXByb2dyZXNzU3Bpbm5lcj48L3AtcHJvZ3Jlc3NTcGlubmVyPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJncmlkXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbFwiPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgganVzdGlmeS1jb250ZW50LWVuZCB3LWZ1bGxcIj5cclxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0QnV0dG9ucz5cclxuICAgICAgICAgICAgICA8YnV0dG9uIHBCdXR0b24gcFJpcHBsZSB0eXBlPVwic3VibWl0XCIgbGFiZWw9XCJTYXZlXCIgaWNvbj1cImZhciBmYS1zYXZlXCIgY2xhc3M9XCJteC0yIHAtYnV0dG9uLXN1Y2Nlc3NcIiBbZGlzYWJsZWRdPVwiaXNMb2FkaW5nIHx8ICFjYW5TdWJtaXQoaXRlbS5rZXkpXCI+PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvbiBwQnV0dG9uIHBSaXBwbGUgdHlwZT1cImJ1dHRvblwiIGxhYmVsPVwiUmVsb2FkXCIgaWNvbj1cImZhcyBmYS1yZWRvXCIgY2xhc3M9XCJteC0yIHAtYnV0dG9uLWluZm9cIiAoY2xpY2spPVwibG9hZCgpXCIgW2Rpc2FibGVkXT1cImlzTG9hZGluZ1wiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIDxidXR0b24gcEJ1dHRvbiBwUmlwcGxlIHR5cGU9XCJidXR0b25cIiBsYWJlbD1cIkRlbGV0ZVwiIGljb249XCJmYXIgZmEtdHJhc2gtYWx0XCIgY2xhc3M9XCJtbC0yIHAtYnV0dG9uLWRhbmdlclwiIChjbGljayk9XCJzaG93RGVsZXRlQ29uZmlybWF0aW9Nb2RhbCgpXCIgW2Rpc2FibGVkXT1cIiFyZXNvdXJjZSB8fCBpc0xvYWRpbmcgfHwgIWNhbkRlbGV0ZVwiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYnV0dG9uc1JlZiB8fCBkZWZhdWx0QnV0dG9uc1wiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9mb3JtPlxyXG4gIDwvcC10YWJQYW5lbD5cclxuXHJcbiAgPG5nLXRlbXBsYXRlICNkZWZhdWx0RXh0cmFUYWJzPlxyXG4gIDwvbmctdGVtcGxhdGU+XHJcbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImV4dHJhVGFic1JlZiB8fCBkZWZhdWx0RXh0cmFUYWJzXCI+PC9uZy1jb250YWluZXI+XHJcblxyXG48L3AtdGFiVmlldz5cclxuXHJcbjxwLXRvYXN0PjwvcC10b2FzdD5cclxuPHAtY29uZmlybURpYWxvZz48L3AtY29uZmlybURpYWxvZz5cclxuIl19