@thecodeblogs/blog 0.15.5 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/fesm2022/thecodeblogs-blog.mjs +2018 -0
  2. package/fesm2022/thecodeblogs-blog.mjs.map +1 -0
  3. package/lib/components/entry-creator/entry-creator.component.d.ts +1 -1
  4. package/lib/components/entry-renderer/entry-renderer.component.d.ts +1 -1
  5. package/lib/components/entry-renderer-wrapper/entry-renderer-wrapper.component.d.ts +1 -1
  6. package/lib/components/entry-selector-dialog/entry-selector-dialog.component.d.ts +1 -1
  7. package/lib/components/entry-summary/entry-summary.component.d.ts +1 -1
  8. package/lib/components/json-renderer/json-renderer.component.d.ts +1 -1
  9. package/lib/components/landing-page/landing-page.component.d.ts +1 -1
  10. package/lib/components/main/main.component.d.ts +1 -1
  11. package/lib/components/media-upload-modal/media-upload-modal.component.d.ts +4 -2
  12. package/lib/components/outline-view/outline-view.component.d.ts +1 -1
  13. package/lib/components/schedule-publish-dialog/schedule-publish-dialog.component.d.ts +1 -1
  14. package/lib/components/side-navigation/side-navigation.component.d.ts +1 -1
  15. package/lib/components/static-html/static-html.component.d.ts +1 -1
  16. package/lib/core.module.d.ts +38 -39
  17. package/lib/pipes/LinkyPipe.d.ts +1 -1
  18. package/lib/pipes/TimeAgoPipe.d.ts +1 -1
  19. package/package.json +22 -26
  20. package/esm2020/lib/components/entry-creator/entry-creator.component.mjs +0 -341
  21. package/esm2020/lib/components/entry-renderer/entry-renderer.component.mjs +0 -108
  22. package/esm2020/lib/components/entry-renderer-wrapper/entry-renderer-wrapper.component.mjs +0 -75
  23. package/esm2020/lib/components/entry-selector-dialog/entry-selector-dialog-data.mjs +0 -3
  24. package/esm2020/lib/components/entry-selector-dialog/entry-selector-dialog.component.mjs +0 -54
  25. package/esm2020/lib/components/entry-summary/entry-summary.component.mjs +0 -28
  26. package/esm2020/lib/components/json-renderer/json-renderer.component.mjs +0 -26
  27. package/esm2020/lib/components/landing-page/landing-page.component.mjs +0 -35
  28. package/esm2020/lib/components/main/main.component.mjs +0 -56
  29. package/esm2020/lib/components/media-upload-modal/media-upload-modal.component.mjs +0 -160
  30. package/esm2020/lib/components/outline-view/outline-view.component.mjs +0 -38
  31. package/esm2020/lib/components/schedule-publish-dialog/schedule-publish-dialog-data.mjs +0 -3
  32. package/esm2020/lib/components/schedule-publish-dialog/schedule-publish-dialog.component.mjs +0 -33
  33. package/esm2020/lib/components/side-navigation/side-navigation.component.mjs +0 -230
  34. package/esm2020/lib/components/static-html/static-html.component.mjs +0 -28
  35. package/esm2020/lib/core.module.mjs +0 -213
  36. package/esm2020/lib/data/base.mjs +0 -7
  37. package/esm2020/lib/data/content-type.mjs +0 -10
  38. package/esm2020/lib/data/content.mjs +0 -5
  39. package/esm2020/lib/data/core-event-type.enum.mjs +0 -7
  40. package/esm2020/lib/data/core-event.mjs +0 -7
  41. package/esm2020/lib/data/entry.mjs +0 -79
  42. package/esm2020/lib/data/guid.mjs +0 -12
  43. package/esm2020/lib/data/identity.mjs +0 -2
  44. package/esm2020/lib/data/list-response.mjs +0 -3
  45. package/esm2020/lib/data/section.mjs +0 -11
  46. package/esm2020/lib/data/tag.mjs +0 -7
  47. package/esm2020/lib/data/visitor-profile.mjs +0 -3
  48. package/esm2020/lib/pipes/LinkyPipe.mjs +0 -15
  49. package/esm2020/lib/pipes/TimeAgoPipe.mjs +0 -100
  50. package/esm2020/lib/routing/routes.mjs +0 -25
  51. package/esm2020/lib/services/analytics/interaction.service.mjs +0 -20
  52. package/esm2020/lib/services/analytics/view.service.mjs +0 -20
  53. package/esm2020/lib/services/comment.service.mjs +0 -28
  54. package/esm2020/lib/services/django-rest-framework-endpoint.service.mjs +0 -50
  55. package/esm2020/lib/services/entry.service.mjs +0 -106
  56. package/esm2020/lib/services/identity.service.mjs +0 -20
  57. package/esm2020/lib/services/interaction.mjs +0 -3
  58. package/esm2020/lib/services/prism.service.mjs +0 -39
  59. package/esm2020/lib/services/static-html.service.mjs +0 -22
  60. package/esm2020/lib/services/tag.service.mjs +0 -33
  61. package/esm2020/lib/services/upload.mjs +0 -3
  62. package/esm2020/lib/services/upload.service.mjs +0 -22
  63. package/esm2020/lib/services/view.mjs +0 -3
  64. package/esm2020/lib/services/visitor-profile.service.mjs +0 -35
  65. package/esm2020/public-api.mjs +0 -45
  66. package/esm2020/thecodeblogs-blog.mjs +0 -5
  67. package/fesm2015/thecodeblogs-blog.mjs +0 -1942
  68. package/fesm2015/thecodeblogs-blog.mjs.map +0 -1
  69. package/fesm2020/thecodeblogs-blog.mjs +0 -1936
  70. package/fesm2020/thecodeblogs-blog.mjs.map +0 -1
@@ -1,341 +0,0 @@
1
- import { COMMA, ENTER, TAB } from '@angular/cdk/keycodes';
2
- import { Component, ViewChild, Input } from '@angular/core';
3
- import { Entry } from '../../data/entry';
4
- import { Section } from '../../data/section';
5
- import { Content } from '../../data/content';
6
- import { ContentType } from '../../data/content-type';
7
- import { map as loMap, filter } from 'lodash';
8
- import { EntrySelectorDialogComponent } from '../../components/entry-selector-dialog/entry-selector-dialog.component';
9
- import { FileUploader } from 'ng2-file-upload';
10
- import { MediaUploadModalComponent } from '../../components/media-upload-modal/media-upload-modal.component';
11
- import { map, startWith } from 'rxjs/operators';
12
- import { UntypedFormControl } from '@angular/forms';
13
- import * as i0 from "@angular/core";
14
- import * as i1 from "../../services/entry.service";
15
- import * as i2 from "../../services/tag.service";
16
- import * as i3 from "../../services/identity.service";
17
- import * as i4 from "@angular/material/dialog";
18
- import * as i5 from "@angular/common";
19
- import * as i6 from "@angular/forms";
20
- import * as i7 from "@angular/material/card";
21
- import * as i8 from "@angular/material/button";
22
- import * as i9 from "@angular/material/input";
23
- import * as i10 from "@angular/material/form-field";
24
- import * as i11 from "@angular/cdk/text-field";
25
- import * as i12 from "@angular/material/radio";
26
- import * as i13 from "@angular/material/autocomplete";
27
- import * as i14 from "@angular/material/core";
28
- import * as i15 from "@angular/material/chips";
29
- import * as i16 from "@angular/material/icon";
30
- import * as i17 from "@angular/material/datepicker";
31
- import * as i18 from "ngx-material-timepicker";
32
- export class EntryCreatorComponent {
33
- static getCookie(name) {
34
- const ca = document.cookie.split(';');
35
- const caLen = ca.length;
36
- const cookieName = `${name}=`;
37
- let c;
38
- for (let i = 0; i < caLen; i += 1) {
39
- c = ca[i].replace(/^\s+/g, '');
40
- if (c.indexOf(cookieName) === 0) {
41
- return c.substring(cookieName.length, c.length);
42
- }
43
- }
44
- return '';
45
- }
46
- constructor(entryService, tagService, identityService, cdr, dialog) {
47
- this.entryService = entryService;
48
- this.tagService = tagService;
49
- this.identityService = identityService;
50
- this.cdr = cdr;
51
- this.dialog = dialog;
52
- this.ContentType = ContentType;
53
- this.Object = Object;
54
- this.entry = null;
55
- this.separatorKeysCodes = [ENTER, COMMA, TAB];
56
- this.removable = true;
57
- this.all_tags = ['Angular', 'Bash', 'MacOS', 'Typescript', 'NPM', 'Databases'];
58
- this.tagCtrl = new UntypedFormControl();
59
- this.publishDateControl = new UntypedFormControl();
60
- this.selectable = false;
61
- this.scheduling = false;
62
- this.customScheduleTime = '';
63
- this.today = new Date();
64
- this.allowedMimeTypes = [
65
- 'image/jpeg',
66
- 'image/gif',
67
- 'image/png',
68
- 'image/jpg',
69
- 'video/mp4',
70
- 'video/webm',
71
- 'video/ogg',
72
- ];
73
- this.uploadUrlKey = 'path_to_file';
74
- this.uploader = new FileUploader({
75
- url: '/file_api/uploads/create_image/',
76
- itemAlias: 'file',
77
- authToken: '',
78
- headers: [
79
- {
80
- name: 'X-CSRFToken',
81
- value: EntryCreatorComponent.getCookie('csrftoken')
82
- },
83
- ],
84
- additionalParameter: {
85
- 'csrf_token': EntryCreatorComponent.getCookie('csrftoken')
86
- },
87
- removeAfterUpload: true,
88
- allowedMimeType: this.allowedMimeTypes,
89
- });
90
- const scheduledDate = new Date();
91
- this.customScheduleTime = scheduledDate.getHours() + ':' + scheduledDate.getMinutes() + ' AM';
92
- }
93
- _filter(value) {
94
- const filterValue = value.toLowerCase();
95
- return this.all_tags.filter(tag => tag.toLowerCase().indexOf(filterValue) === 0);
96
- }
97
- add(event) {
98
- const input = event.input;
99
- const value = event.value;
100
- // Add our tag
101
- if ((value || '').trim()) {
102
- this.tags.push(value.trim());
103
- }
104
- // Reset the input value
105
- if (input) {
106
- input.value = '';
107
- }
108
- this.tagCtrl.setValue(null);
109
- this.onChange();
110
- }
111
- remove(fruit) {
112
- const index = this.tags.indexOf(fruit);
113
- if (index >= 0) {
114
- this.tags.splice(index, 1);
115
- }
116
- this.onChange();
117
- }
118
- selected(event) {
119
- this.tags.push(event.option.viewValue);
120
- this.tagInput.nativeElement.value = '';
121
- this.tagCtrl.setValue(null);
122
- this.onChange();
123
- }
124
- refreshTags() {
125
- this.tagService.get().subscribe((response) => {
126
- this.all_tags = loMap(response.results, (t) => t.label);
127
- this.filtered_tags = this.tagCtrl.valueChanges.pipe(startWith(null), map((tag) => tag ? this._filter(tag) : this.all_tags.slice()));
128
- });
129
- }
130
- createNewEntry() {
131
- this.entry = new Entry();
132
- this.entry.title = EntryCreatorComponent.DEFAULT_NEW_ENTRY_TITLE;
133
- this.entry.published = false;
134
- this.entry.version = 1;
135
- this.entryService.create(this.entry).subscribe((response) => {
136
- this.entry = response;
137
- this.entry.sort();
138
- setTimeout(() => {
139
- this.entryService.currentlyEditedEntry.next(this.entry);
140
- }, 10);
141
- });
142
- }
143
- ngOnInit() {
144
- this.refreshTags();
145
- this.identityService.getMe().subscribe((me) => {
146
- this.me = me;
147
- });
148
- const savedEntry = localStorage.getItem(EntryCreatorComponent.CURRENT_ENTRY);
149
- if (savedEntry) {
150
- this.entry = new Entry(JSON.parse(savedEntry));
151
- if (this.entry.should_publish_in_future && this.entry.future_publish_date < new Date()) {
152
- this.createNewEntry();
153
- }
154
- this.entry.sort();
155
- if (this.entry.should_publish_in_future) {
156
- // Restore scheduling settings
157
- this.scheduling = true;
158
- let hours = this.entry.future_publish_date.getHours();
159
- let minutes = this.entry.future_publish_date.getMinutes();
160
- const ampm = hours >= 12 ? 'PM' : 'AM';
161
- if (hours >= 12) {
162
- hours = hours % 12;
163
- hours = hours ? hours : 12;
164
- }
165
- minutes = minutes < 10 ? '0' + minutes : minutes;
166
- this.customScheduleTime = hours + ':' + minutes + ' ' + ampm;
167
- }
168
- setTimeout(() => {
169
- this.entryService.currentlyEditedEntry.next(this.entry);
170
- }, 10);
171
- }
172
- else {
173
- this.seeEntries();
174
- }
175
- this.uploader.onCompleteItem = (item, response) => {
176
- // const responseObj = JSON.parse(response)
177
- // this.uploadId = responseObj.id;
178
- };
179
- this.uploader.onWhenAddingFileFailed = (item, uploadFilter, options) => {
180
- // this.error = 'This file is not a supported mimetype.'
181
- // this.uploading = false;
182
- };
183
- this.tags = this.entry.tags;
184
- }
185
- onFileSelected(e) {
186
- this.uploader.uploadAll();
187
- }
188
- startUploader(content) {
189
- const dialogRef = this.dialog.open(MediaUploadModalComponent, {});
190
- dialogRef.componentInstance.allowedMimeTypes = this.allowedMimeTypes;
191
- dialogRef.componentInstance.uploadUrlKey = this.uploadUrlKey;
192
- dialogRef.afterClosed().subscribe(() => {
193
- content.value = dialogRef.componentInstance.imgLink;
194
- content.additional = [];
195
- content.additional.push({ key: Content.KEY_MIMETYPE, value: dialogRef.componentInstance.mimeType });
196
- this.onChange();
197
- });
198
- }
199
- addSection() {
200
- this.entry.sections.push(new Section());
201
- this.onChange();
202
- }
203
- removeSection(section) {
204
- const remove = confirm('Are you sure you want to remove this section?');
205
- if (remove) {
206
- this.entry.sections =
207
- filter(this.entry.sections, (sct) => sct.id !== section.id);
208
- this.onChange();
209
- }
210
- }
211
- addContent(section) {
212
- section.contents.push(new Content());
213
- this.onChange();
214
- }
215
- removeContent(content) {
216
- const remove = confirm('Are you sure you want to remove this content?');
217
- if (remove) {
218
- for (const section of this.entry.sections) {
219
- section.contents = filter(section.contents, (ct) => ct.id !== content.id);
220
- }
221
- this.onChange();
222
- }
223
- }
224
- onChange() {
225
- this.entry.slug = this.entryService.slugify(this.entry.title).toLowerCase();
226
- localStorage.setItem(EntryCreatorComponent.CURRENT_ENTRY, JSON.stringify(this.entry));
227
- this.entry.sort();
228
- this.cdr.detectChanges();
229
- this.entryService.currentlyEditedEntry.next(this.entry);
230
- this.entryService._currentlyEditedEntry = this.entry;
231
- }
232
- resetDate() {
233
- this.entry.create_date = new Date();
234
- this.entry.edit_date = new Date();
235
- this.onChange();
236
- }
237
- startNew() {
238
- const finish = confirm('Are you sure your finished? The JSON and entry displayed will be removed. Make sure you have already copied it.');
239
- if (finish) {
240
- this.entry = new Entry();
241
- this.entry.title = EntryCreatorComponent.DEFAULT_NEW_ENTRY_TITLE;
242
- this.entry.published = false;
243
- this.entry.version = 1;
244
- this.entryService.currentlyEditedEntry.next(this.entry);
245
- localStorage.setItem(EntryCreatorComponent.CURRENT_ENTRY, JSON.stringify(this.entry));
246
- this.entryService.create(this.entry).subscribe((next) => {
247
- });
248
- }
249
- }
250
- seeEntries() {
251
- const dialogRef = this.dialog.open(EntrySelectorDialogComponent, {
252
- width: '800px',
253
- data: { name: 'test', animal: 'test' }
254
- });
255
- dialogRef.afterClosed().subscribe((id) => {
256
- if (id) {
257
- this.entryService.getUnpublishedById(id).subscribe((result) => {
258
- const entry = result;
259
- this.entryService.currentlyEditedEntry.next(entry);
260
- localStorage.setItem(EntryCreatorComponent.CURRENT_ENTRY, JSON.stringify(entry));
261
- this.entry = entry;
262
- });
263
- }
264
- });
265
- }
266
- postPublishCallback() {
267
- this.entryService.currentlyEditedEntry.next(null);
268
- this.entry = null;
269
- this.seeEntries();
270
- }
271
- cancelScheduling() {
272
- this.entry.future_publish_date = null;
273
- this.entry.should_publish_in_future = false;
274
- this.scheduling = false;
275
- this.onChange();
276
- }
277
- exposeScheduling() {
278
- const scheduledDate = new Date();
279
- scheduledDate.setDate(scheduledDate.getDate() + 1);
280
- this.entry.future_publish_date = scheduledDate;
281
- this.setTime(this.customScheduleTime);
282
- this.entry.should_publish_in_future = true;
283
- this.scheduling = true;
284
- this.onChange();
285
- }
286
- publish() {
287
- const publish = confirm('Are you sure you want to publish? Once an article is published it is available to everyone.');
288
- if (publish) {
289
- this.entry.published = true;
290
- this.entry.publish_date = new Date();
291
- this.entry.edit_date = new Date();
292
- this.entryService.updateUnpublishedEntry(this.entry).subscribe(this.postPublishCallback.bind(this));
293
- }
294
- }
295
- delete() {
296
- const confirmDelete = confirm('Are you sure you want to delete this draft? Once it is deleted it cannot be recovered.');
297
- if (confirmDelete) {
298
- this.entryService.delete(this.entry).subscribe(() => {
299
- this.entry = null;
300
- this.entryService.currentlyEditedEntry.next(null);
301
- localStorage.removeItem(EntryCreatorComponent.CURRENT_ENTRY);
302
- });
303
- }
304
- }
305
- onDateChange() {
306
- this.entry.future_publish_date.setHours(this.hours);
307
- this.entry.future_publish_date.setMinutes(this.minutes);
308
- this.onChange();
309
- }
310
- setTime(e) {
311
- const firstTimeSplit = e.split(' ');
312
- const secondTimeSplit = firstTimeSplit[0].split(':');
313
- this.hours = Number(secondTimeSplit[0]);
314
- this.minutes = Number(secondTimeSplit[1]);
315
- if (firstTimeSplit[1] === 'PM') {
316
- this.hours = Number(this.hours) + 12;
317
- }
318
- this.entry.future_publish_date.setHours(this.hours);
319
- this.entry.future_publish_date.setMinutes(this.minutes);
320
- this.onChange();
321
- }
322
- }
323
- EntryCreatorComponent.CURRENT_ENTRY = 'current_entry';
324
- EntryCreatorComponent.DEFAULT_NEW_ENTRY_TITLE = 'A New Entry';
325
- EntryCreatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: EntryCreatorComponent, deps: [{ token: i1.EntryService }, { token: i2.TagService }, { token: i3.IdentityService }, { token: i0.ChangeDetectorRef }, { token: i4.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
326
- EntryCreatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.4", type: EntryCreatorComponent, selector: "app-entry-creator", inputs: { allowedMimeTypes: "allowedMimeTypes", uploadUrlKey: "uploadUrlKey" }, viewQueries: [{ propertyName: "tagInput", first: true, predicate: ["tagInput"], descendants: true }, { propertyName: "matAutocomplete", first: true, predicate: ["tagauto"], descendants: true }], ngImport: i0, template: "<div class=\"section creator fields\">\n <form #createForm=\"ngForm\" (change)=\"onChange()\" *ngIf=\"this.entry\">\n <div class=\"form-group\">\n <mat-form-field class=\"full-width\">\n <mat-label>Title</mat-label>\n <input matInput\n [(ngModel)]=\"entry.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n <mat-card class=\"form-section tags\">\n <div>\n <mat-form-field class=\"full-width\" hintLabel=\"Use a comma to seperate different tags\">\n <mat-chip-listbox #tagList aria-label=\"Tags\">\n <mat-chip-option\n *ngFor=\"let tag of tags\"\n [selectable]=\"selectable\"\n [removable]=\"removable\"\n (removed)=\"remove(tag)\">\n {{tag}}\n <mat-icon matChipRemove *ngIf=\"removable\">cancel</mat-icon>\n </mat-chip-option>\n <input\n matInput\n placeholder=\"Tags...\"\n #tagInput\n [formControl]=\"tagCtrl\"\n [matAutocomplete]=\"tagauto\"\n [matChipInputFor]=\"tagList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\">\n </mat-chip-listbox>\n <mat-autocomplete #tagauto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n <mat-option *ngFor=\"let tag of filtered_tags | async\" [value]=\"tag\">\n {{tag}}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n </div>\n </mat-card>\n <mat-card class=\"form-section\" *ngFor=\"let section of entry.sections\">\n <div>\n <mat-form-field class=\"full-width\">\n <mat-label>Subheading</mat-label>\n <input matInput\n [(ngModel)]=\"section.subheading\"\n name=\"{{section.id}}-subheading\">\n </mat-form-field>\n <div class=\"form-content\" *ngFor=\"let content of section.contents\">\n <div class=\"form-group\">\n <mat-radio-group\n aria-label=\"Select the Content Type\"\n name=\"{{content.id}}-content-type\"\n class=\"radio-group\"\n [(ngModel)]=\"content.type\">\n <mat-radio-button\n *ngFor=\"let value of Object.values(ContentType)\"\n class=\"radio-button\"\n [value]=\"value\">{{value}}\n </mat-radio-button>\n </mat-radio-group>\n </div>\n <ng-container [ngSwitch]=\"content.type\">\n <ng-container *ngSwitchCase=\"ContentType.URL\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Title</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-title\"\n [(ngModel)]=\"content.title\">\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.TEXT\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <textarea matInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"3\"\n cdkAutosizeMaxRows=\"20\"\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\"\n ></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.HTML\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <textarea matInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"3\"\n cdkAutosizeMaxRows=\"20\"\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\"\n ></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.CODE\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <textarea matInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"10\"\n cdkAutosizeMaxRows=\"100\"\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\"\n ></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.IMAGE\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-source\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Description</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-description\"\n [(ngModel)]=\"content.description\">\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.MEDIA\">\n <div class=\"full-width\">\n <ng-container *ngIf=\"content.value\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Description</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-description\"\n [(ngModel)]=\"content.description\">\n </mat-form-field>\n </ng-container>\n <ng-container *ngIf=\"content.additional\">\n <ng-container *ngFor=\"let add of content.additional\">\n <mat-form-field class=\"full-width\">\n <mat-label>{{add.key}}</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-{{add.key}}\"\n [(ngModel)]=\"add.value\"\n [disabled]=\"true\"\n >\n </mat-form-field>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!content.value\">\n <button mat-raised-button (click)=startUploader(content)>Upload</button>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n <button mat-raised-button (click)=removeContent(content)>Remove Content</button>\n <button mat-raised-button (click)=\"addContent(section)\">+ Add Content</button>\n </div>\n <button mat-raised-button (click)=\"removeSection(section)\">Remove Section</button>\n <button mat-raised-button (click)=\"addContent(section)\" *ngIf=\"section.contents.length === 0\">+ Add\n Content\n </button>\n <button mat-raised-button (click)=\"addSection()\">+ Add Section</button>\n </div>\n\n </mat-card>\n <button mat-raised-button (click)=\"addSection()\" *ngIf=\"entry.sections?.length === 0\">+ Add Section</button>\n <button mat-raised-button (click)=\"addSection()\" *ngIf=\"!entry.sections\">+ Add Section</button>\n\n <div class=\"controls\">\n <button mat-raised-button (click)=\"resetDate()\">Reset the Date</button>\n <button mat-raised-button (click)=\"delete()\">Delete</button>\n <button mat-raised-button [disabled]=\"scheduling\" (click)=\"publish()\">Publish</button>\n <button mat-raised-button [disabled]=\"scheduling\" (click)=\"exposeScheduling()\">Schedule</button>\n <button mat-raised-button (click)=\"startNew()\">New</button>\n </div>\n <p *ngIf=\"scheduling\">Publishing is disabled while scheduling is being used.</p>\n\n <mat-card [hidden]=\"!scheduling\">\n <h4>\n Scheduling Options\n </h4>\n\n <div class=\"form-group\">\n <mat-form-field class=\"full-width\">\n <mat-label>Date</mat-label>\n <input\n #futurePublishDate\n matInput\n [matDatepicker]=\"picker\"\n [min]=\"today\"\n (dateInput)=\"onDateChange()\"\n (dateChange)=\"onDateChange()\"\n [(ngModel)]=\"entry.future_publish_date\"\n name=\"future-publish-date\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker\n #picker></mat-datepicker>\n </mat-form-field>\n\n <mat-label>Time</mat-label>\n <ngx-timepicker-field\n [defaultTime]=\"customScheduleTime\"\n [format]=\"12\"\n [buttonAlign]=\"'left'\"\n (timeChanged)=\"setTime($event)\"\n ></ngx-timepicker-field>\n <p>Times are represented in your local time zone</p>\n </div>\n\n <div mat-dialog-actions>\n <div class=\"controls\">\n <button mat-raised-button (click)=\"cancelScheduling()\">Cancel Scheduling</button>\n </div>\n </div>\n <p>This post will be published as soon as its scheduled date and time arrive. No further action is needed by you. If you do not\n want to use scheduling, you can cancel scheduling and manually publish.</p>\n </mat-card>\n </form>\n <div class=\"controls\">\n <button mat-raised-button (click)=\"seeEntries()\">See Entries</button>\n <button *ngIf=\"!this.entry\" mat-raised-button (click)=\"startNew()\">New</button>\n </div>\n</div>\n", styles: [".creator{min-height:calc(100vh - 100px)}form{padding:20px}.content{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}button{margin:4px}.radio-group{display:flex;flex-direction:column;margin:15px 0}.radio-button{margin:4px}.full-width{width:100%}.content-card{margin:0 0 10px}.form-section{margin-bottom:10px}.form-content:not(:last-child){border-bottom:1px dotted #aaa;padding-bottom:10px}.controls{display:inline-block;width:100%;padding:10px}[hidden]{display:none!important}\n"], dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i7.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i11.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i12.MatRadioGroup, selector: "mat-radio-group", exportAs: ["matRadioGroup"] }, { kind: "component", type: i12.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: i13.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i14.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "directive", type: i13.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { kind: "directive", type: i15.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: i15.MatChipListbox, selector: "mat-chip-listbox", inputs: ["tabIndex", "multiple", "aria-orientation", "selectable", "compareWith", "required", "value"], outputs: ["change"] }, { kind: "component", type: i15.MatChipOption, selector: "mat-basic-chip-option, mat-chip-option", inputs: ["color", "disabled", "disableRipple", "tabIndex", "selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: i15.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i16.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i17.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i17.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i17.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i18.NgxTimepickerFieldComponent, selector: "ngx-timepicker-field", inputs: ["buttonAlign", "format", "min", "max", "defaultTime", "disabled", "toggleIcon", "clockTheme", "controlOnly", "cancelBtnTmpl", "confirmBtnTmpl"], outputs: ["timeChanged"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] });
327
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.4", ngImport: i0, type: EntryCreatorComponent, decorators: [{
328
- type: Component,
329
- args: [{ selector: 'app-entry-creator', template: "<div class=\"section creator fields\">\n <form #createForm=\"ngForm\" (change)=\"onChange()\" *ngIf=\"this.entry\">\n <div class=\"form-group\">\n <mat-form-field class=\"full-width\">\n <mat-label>Title</mat-label>\n <input matInput\n [(ngModel)]=\"entry.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n <mat-card class=\"form-section tags\">\n <div>\n <mat-form-field class=\"full-width\" hintLabel=\"Use a comma to seperate different tags\">\n <mat-chip-listbox #tagList aria-label=\"Tags\">\n <mat-chip-option\n *ngFor=\"let tag of tags\"\n [selectable]=\"selectable\"\n [removable]=\"removable\"\n (removed)=\"remove(tag)\">\n {{tag}}\n <mat-icon matChipRemove *ngIf=\"removable\">cancel</mat-icon>\n </mat-chip-option>\n <input\n matInput\n placeholder=\"Tags...\"\n #tagInput\n [formControl]=\"tagCtrl\"\n [matAutocomplete]=\"tagauto\"\n [matChipInputFor]=\"tagList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"add($event)\">\n </mat-chip-listbox>\n <mat-autocomplete #tagauto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n <mat-option *ngFor=\"let tag of filtered_tags | async\" [value]=\"tag\">\n {{tag}}\n </mat-option>\n </mat-autocomplete>\n </mat-form-field>\n </div>\n </mat-card>\n <mat-card class=\"form-section\" *ngFor=\"let section of entry.sections\">\n <div>\n <mat-form-field class=\"full-width\">\n <mat-label>Subheading</mat-label>\n <input matInput\n [(ngModel)]=\"section.subheading\"\n name=\"{{section.id}}-subheading\">\n </mat-form-field>\n <div class=\"form-content\" *ngFor=\"let content of section.contents\">\n <div class=\"form-group\">\n <mat-radio-group\n aria-label=\"Select the Content Type\"\n name=\"{{content.id}}-content-type\"\n class=\"radio-group\"\n [(ngModel)]=\"content.type\">\n <mat-radio-button\n *ngFor=\"let value of Object.values(ContentType)\"\n class=\"radio-button\"\n [value]=\"value\">{{value}}\n </mat-radio-button>\n </mat-radio-group>\n </div>\n <ng-container [ngSwitch]=\"content.type\">\n <ng-container *ngSwitchCase=\"ContentType.URL\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Title</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-title\"\n [(ngModel)]=\"content.title\">\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.TEXT\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <textarea matInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"3\"\n cdkAutosizeMaxRows=\"20\"\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\"\n ></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.HTML\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <textarea matInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"3\"\n cdkAutosizeMaxRows=\"20\"\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\"\n ></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.CODE\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <textarea matInput\n cdkTextareaAutosize\n #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"10\"\n cdkAutosizeMaxRows=\"100\"\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\"\n ></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.IMAGE\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-source\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Description</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-description\"\n [(ngModel)]=\"content.description\">\n </mat-form-field>\n </ng-container>\n <ng-container *ngSwitchCase=\"ContentType.MEDIA\">\n <div class=\"full-width\">\n <ng-container *ngIf=\"content.value\">\n <mat-form-field class=\"full-width\">\n <mat-label>Value</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-value\"\n [(ngModel)]=\"content.value\">\n </mat-form-field>\n <mat-form-field class=\"full-width\">\n <mat-label>Description</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-description\"\n [(ngModel)]=\"content.description\">\n </mat-form-field>\n </ng-container>\n <ng-container *ngIf=\"content.additional\">\n <ng-container *ngFor=\"let add of content.additional\">\n <mat-form-field class=\"full-width\">\n <mat-label>{{add.key}}</mat-label>\n <input\n matInput\n name=\"{{content.id}}-content-{{add.key}}\"\n [(ngModel)]=\"add.value\"\n [disabled]=\"true\"\n >\n </mat-form-field>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!content.value\">\n <button mat-raised-button (click)=startUploader(content)>Upload</button>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n <button mat-raised-button (click)=removeContent(content)>Remove Content</button>\n <button mat-raised-button (click)=\"addContent(section)\">+ Add Content</button>\n </div>\n <button mat-raised-button (click)=\"removeSection(section)\">Remove Section</button>\n <button mat-raised-button (click)=\"addContent(section)\" *ngIf=\"section.contents.length === 0\">+ Add\n Content\n </button>\n <button mat-raised-button (click)=\"addSection()\">+ Add Section</button>\n </div>\n\n </mat-card>\n <button mat-raised-button (click)=\"addSection()\" *ngIf=\"entry.sections?.length === 0\">+ Add Section</button>\n <button mat-raised-button (click)=\"addSection()\" *ngIf=\"!entry.sections\">+ Add Section</button>\n\n <div class=\"controls\">\n <button mat-raised-button (click)=\"resetDate()\">Reset the Date</button>\n <button mat-raised-button (click)=\"delete()\">Delete</button>\n <button mat-raised-button [disabled]=\"scheduling\" (click)=\"publish()\">Publish</button>\n <button mat-raised-button [disabled]=\"scheduling\" (click)=\"exposeScheduling()\">Schedule</button>\n <button mat-raised-button (click)=\"startNew()\">New</button>\n </div>\n <p *ngIf=\"scheduling\">Publishing is disabled while scheduling is being used.</p>\n\n <mat-card [hidden]=\"!scheduling\">\n <h4>\n Scheduling Options\n </h4>\n\n <div class=\"form-group\">\n <mat-form-field class=\"full-width\">\n <mat-label>Date</mat-label>\n <input\n #futurePublishDate\n matInput\n [matDatepicker]=\"picker\"\n [min]=\"today\"\n (dateInput)=\"onDateChange()\"\n (dateChange)=\"onDateChange()\"\n [(ngModel)]=\"entry.future_publish_date\"\n name=\"future-publish-date\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker\n #picker></mat-datepicker>\n </mat-form-field>\n\n <mat-label>Time</mat-label>\n <ngx-timepicker-field\n [defaultTime]=\"customScheduleTime\"\n [format]=\"12\"\n [buttonAlign]=\"'left'\"\n (timeChanged)=\"setTime($event)\"\n ></ngx-timepicker-field>\n <p>Times are represented in your local time zone</p>\n </div>\n\n <div mat-dialog-actions>\n <div class=\"controls\">\n <button mat-raised-button (click)=\"cancelScheduling()\">Cancel Scheduling</button>\n </div>\n </div>\n <p>This post will be published as soon as its scheduled date and time arrive. No further action is needed by you. If you do not\n want to use scheduling, you can cancel scheduling and manually publish.</p>\n </mat-card>\n </form>\n <div class=\"controls\">\n <button mat-raised-button (click)=\"seeEntries()\">See Entries</button>\n <button *ngIf=\"!this.entry\" mat-raised-button (click)=\"startNew()\">New</button>\n </div>\n</div>\n", styles: [".creator{min-height:calc(100vh - 100px)}form{padding:20px}.content{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}button{margin:4px}.radio-group{display:flex;flex-direction:column;margin:15px 0}.radio-button{margin:4px}.full-width{width:100%}.content-card{margin:0 0 10px}.form-section{margin-bottom:10px}.form-content:not(:last-child){border-bottom:1px dotted #aaa;padding-bottom:10px}.controls{display:inline-block;width:100%;padding:10px}[hidden]{display:none!important}\n"] }]
330
- }], ctorParameters: function () { return [{ type: i1.EntryService }, { type: i2.TagService }, { type: i3.IdentityService }, { type: i0.ChangeDetectorRef }, { type: i4.MatDialog }]; }, propDecorators: { tagInput: [{
331
- type: ViewChild,
332
- args: ['tagInput']
333
- }], matAutocomplete: [{
334
- type: ViewChild,
335
- args: ['tagauto']
336
- }], allowedMimeTypes: [{
337
- type: Input
338
- }], uploadUrlKey: [{
339
- type: Input
340
- }] } });
341
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50cnktY3JlYXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb3JlL3NyYy9saWIvY29tcG9uZW50cy9lbnRyeS1jcmVhdG9yL2VudHJ5LWNyZWF0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29yZS9zcmMvbGliL2NvbXBvbmVudHMvZW50cnktY3JlYXRvci9lbnRyeS1jcmVhdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQ3hELE9BQU8sRUFBb0IsU0FBUyxFQUFVLFNBQVMsRUFBb0MsS0FBSyxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBRXZILE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUN2QyxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDM0MsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQzNDLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQU1wRCxPQUFPLEVBQUMsR0FBRyxJQUFJLEtBQUssRUFBRSxNQUFNLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFHNUMsT0FBTyxFQUFDLDRCQUE0QixFQUFDLE1BQU0sd0VBQXdFLENBQUM7QUFDcEgsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzdDLE9BQU8sRUFBQyx5QkFBeUIsRUFBQyxNQUFNLGtFQUFrRSxDQUFDO0FBRTNHLE9BQU8sRUFBQyxHQUFHLEVBQUUsU0FBUyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUMsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBVWxELE1BQU0sT0FBTyxxQkFBcUI7SUE4RDlCLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBWTtRQUN6QixNQUFNLEVBQUUsR0FBa0IsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckQsTUFBTSxLQUFLLEdBQVcsRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNoQyxNQUFNLFVBQVUsR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDO1FBQzlCLElBQUksQ0FBUyxDQUFDO1FBRWQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQy9CLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUM3QixPQUFPLENBQUMsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDbkQ7U0FDSjtRQUNELE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVELFlBQ1ksWUFBMEIsRUFDMUIsVUFBc0IsRUFDdEIsZUFBZ0MsRUFDaEMsR0FBc0IsRUFDdEIsTUFBaUI7UUFKakIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0QixvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMsUUFBRyxHQUFILEdBQUcsQ0FBbUI7UUFDdEIsV0FBTSxHQUFOLE1BQU0sQ0FBVztRQTdFN0IsZ0JBQVcsR0FBRyxXQUFXLENBQUM7UUFDMUIsV0FBTSxHQUFHLE1BQU0sQ0FBQztRQUVoQixVQUFLLEdBQVUsSUFBSSxDQUFDO1FBR3BCLHVCQUFrQixHQUFhLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNuRCxjQUFTLEdBQUcsSUFBSSxDQUFDO1FBRWpCLGFBQVEsR0FBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFLcEYsWUFBTyxHQUFHLElBQUksa0JBQWtCLEVBQUUsQ0FBQztRQUNuQyx1QkFBa0IsR0FBRyxJQUFJLGtCQUFrQixFQUFFLENBQUM7UUFHOUMsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUVuQixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ25CLHVCQUFrQixHQUFHLEVBQUUsQ0FBQztRQUN4QixVQUFLLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUlWLHFCQUFnQixHQUFHO1lBQ2hCLFlBQVk7WUFDWixXQUFXO1lBQ1gsV0FBVztZQUNYLFdBQVc7WUFDWCxXQUFXO1lBQ1gsWUFBWTtZQUNaLFdBQVc7U0FDdEIsQ0FBQztRQUVPLGlCQUFZLEdBQUcsY0FBYyxDQUFDO1FBRWhDLGFBQVEsR0FBaUIsSUFBSSxZQUFZLENBQzVDO1lBQ0ksR0FBRyxFQUFFLGlDQUFpQztZQUN0QyxTQUFTLEVBQUUsTUFBTTtZQUNqQixTQUFTLEVBQUUsRUFBRTtZQUNiLE9BQU8sRUFBRTtnQkFDTDtvQkFDSSxJQUFJLEVBQUUsYUFBYTtvQkFDbkIsS0FBSyxFQUFFLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUM7aUJBQ3REO2FBQ0o7WUFDRCxtQkFBbUIsRUFBRTtnQkFDakIsWUFBWSxFQUFFLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUM7YUFDN0Q7WUFDRCxpQkFBaUIsRUFBRSxJQUFJO1lBQ3ZCLGVBQWUsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO1NBQ3pDLENBQ0osQ0FBQztRQXdCRSxNQUFNLGFBQWEsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxhQUFhLENBQUMsUUFBUSxFQUFFLEdBQUcsR0FBRyxHQUFHLGFBQWEsQ0FBQyxVQUFVLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDbEcsQ0FBQztJQUVPLE9BQU8sQ0FBQyxLQUFhO1FBQ3pCLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN4QyxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBRUQsR0FBRyxDQUFDLEtBQXdCO1FBQ3hCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDMUIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztRQUUxQixjQUFjO1FBQ2QsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUNoQztRQUVELHdCQUF3QjtRQUN4QixJQUFJLEtBQUssRUFBRTtZQUNQLEtBQUssQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1NBQ3BCO1FBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxNQUFNLENBQUMsS0FBYTtRQUNoQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV2QyxJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUU7WUFDWixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDOUI7UUFDRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELFFBQVEsQ0FBQyxLQUFtQztRQUN4QyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxXQUFXO1FBQ1AsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtZQUN6QyxJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEQsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQy9DLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFDZixHQUFHLENBQUMsQ0FBQyxHQUFrQixFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELGNBQWM7UUFDVixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcscUJBQXFCLENBQUMsdUJBQXVCLENBQUM7UUFDakUsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztRQUV2QixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7WUFDeEQsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7WUFDdEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNsQixVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNaLElBQUksQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1RCxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxRQUFRO1FBQ0osSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25CLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUU7WUFDMUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDakIsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLFVBQVUsR0FDWixZQUFZLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTlELElBQUksVUFBVSxFQUFFO1lBQ1osSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFFL0MsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLHdCQUF3QixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxJQUFJLEVBQUUsRUFBRTtnQkFDcEYsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2FBQ3pCO1lBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNsQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEVBQUU7Z0JBQ3JDLDhCQUE4QjtnQkFDOUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ3ZCLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ3RELElBQUksT0FBTyxHQUFvQixJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUMzRSxNQUFNLElBQUksR0FBRyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDdkMsSUFBSSxLQUFLLElBQUksRUFBRSxFQUFFO29CQUNiLEtBQUssR0FBRyxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUNuQixLQUFLLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztpQkFDOUI7Z0JBQ0QsT0FBTyxHQUFHLE9BQU8sR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztnQkFDakQsSUFBSSxDQUFDLGtCQUFrQixHQUFHLEtBQUssR0FBRyxHQUFHLEdBQUcsT0FBTyxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUM7YUFDaEU7WUFDRCxVQUFVLENBQUMsR0FBRyxFQUFFO2dCQUNaLElBQUksQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1RCxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDVjthQUFNO1lBQ0gsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1NBQ3JCO1FBRUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLEdBQUcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDOUMsMkNBQTJDO1lBQzNDLGtDQUFrQztRQUN0QyxDQUFDLENBQUM7UUFFRixJQUFJLENBQUMsUUFBUSxDQUFDLHNCQUFzQixHQUFHLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNuRSx3REFBd0Q7WUFDeEQsMEJBQTBCO1FBQzlCLENBQUMsQ0FBQztRQUVGLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7SUFDaEMsQ0FBQztJQUVELGNBQWMsQ0FBQyxDQUFDO1FBQ1osSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQsYUFBYSxDQUFDLE9BQU87UUFDakIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUUsRUFDN0QsQ0FBQyxDQUFDO1FBQ0gsU0FBUyxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztRQUNyRSxTQUFTLENBQUMsaUJBQWlCLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDN0QsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDbkMsT0FBTyxDQUFDLEtBQUssR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDO1lBQ3BELE9BQU8sQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUMsQ0FBQyxDQUFDO1lBQ2xHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxVQUFVO1FBQ04sSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksT0FBTyxFQUFFLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELGFBQWEsQ0FBQyxPQUFPO1FBQ2pCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO1FBQ3hFLElBQUksTUFBTSxFQUFFO1lBQ1IsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRO2dCQUNmLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDaEUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1NBQ25CO0lBQ0wsQ0FBQztJQUVELFVBQVUsQ0FBQyxPQUFPO1FBQ2QsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQsYUFBYSxDQUFDLE9BQU87UUFDakIsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLCtDQUErQyxDQUFDLENBQUM7UUFFeEUsSUFBSSxNQUFNLEVBQUU7WUFDUixLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFO2dCQUN2QyxPQUFPLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FDckIsT0FBTyxDQUFDLFFBQVEsRUFDaEIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssT0FBTyxDQUFDLEVBQUUsQ0FDL0IsQ0FBQzthQUNMO1lBQ0QsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1NBQ25CO0lBQ0wsQ0FBQztJQUVELFFBQVE7UUFDSixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzVFLFlBQVksQ0FBQyxPQUFPLENBQ2hCLHFCQUFxQixDQUFDLGFBQWEsRUFDbkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQzdCLENBQUM7UUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxZQUFZLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztJQUN6RCxDQUFDO0lBRUQsU0FBUztRQUNMLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDcEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUVsQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELFFBQVE7UUFDSixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsaUhBQWlILENBQUMsQ0FBQztRQUMxSSxJQUFJLE1BQU0sRUFBRTtZQUVSLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxxQkFBcUIsQ0FBQyx1QkFBdUIsQ0FBQztZQUNqRSxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7WUFDN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1lBRXZCLElBQUksQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4RCxZQUFZLENBQUMsT0FBTyxDQUNoQixxQkFBcUIsQ0FBQyxhQUFhLEVBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUM3QixDQUFDO1lBQ0YsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3hELENBQUMsQ0FBQyxDQUFDO1NBQ047SUFDTCxDQUFDO0lBRUQsVUFBVTtRQUNOLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFO1lBQzdELEtBQUssRUFBRSxPQUFPO1lBQ2QsSUFBSSxFQUFFLEVBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFDO1NBQ3ZDLENBQUMsQ0FBQztRQUVILFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRTtZQUNyQyxJQUFJLEVBQUUsRUFBRTtnQkFDSixJQUFJLENBQUMsWUFBWSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO29CQUMxRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUM7b0JBQ3JCLElBQUksQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNuRCxZQUFZLENBQUMsT0FBTyxDQUNoQixxQkFBcUIsQ0FBQyxhQUFhLEVBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQ3hCLENBQUM7b0JBQ0YsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7Z0JBQ3ZCLENBQUMsQ0FBQyxDQUFDO2FBQ047UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxtQkFBbUI7UUFDakIsSUFBSSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDbEIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxnQkFBZ0I7UUFDWixJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQztRQUN0QyxJQUFJLENBQUMsS0FBSyxDQUFDLHdCQUF3QixHQUFHLEtBQUssQ0FBQztRQUM1QyxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN4QixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELGdCQUFnQjtRQUNaLE1BQU0sYUFBYSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDakMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFbkQsSUFBSSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsR0FBRyxhQUFhLENBQUM7UUFDL0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUV0QyxJQUFJLENBQUMsS0FBSyxDQUFDLHdCQUF3QixHQUFHLElBQUksQ0FBQztRQUMzQyxJQUFJLENBQUMsVUFBVSxHQUFJLElBQUksQ0FBQztRQUN4QixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUNELE9BQU87UUFDSCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsNkZBQTZGLENBQUMsQ0FBQztRQUN2SCxJQUFJLE9BQU8sRUFBRTtZQUNULElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztZQUM1QixJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7WUFDbEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztTQUN2RztJQUNMLENBQUM7SUFDRCxNQUFNO1FBQ0YsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLHdGQUF3RixDQUFDLENBQUM7UUFDeEgsSUFBSSxhQUFhLEVBQUU7WUFDZixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtnQkFDaEQsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBQ2xCLElBQUksQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNsRCxZQUFZLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2pFLENBQUMsQ0FBQyxDQUFDO1NBQ047SUFDTCxDQUFDO0lBQ0QsWUFBWTtRQUNSLElBQUksQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFHRCxPQUFPLENBQUMsQ0FBQztRQUNMLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEMsTUFBTSxlQUFlLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUxQyxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDNUIsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUN4QztRQUVELElBQUksQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFeEQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7O0FBcFhNLG1DQUFhLEdBQUcsZUFBZSxDQUFDO0FBQ2hDLDZDQUF1QixHQUFHLGFBQWEsQ0FBQztrSEFIdEMscUJBQXFCO3NHQUFyQixxQkFBcUIsNFVDOUJsQyxrNFZBd1BBOzJGRDFOYSxxQkFBcUI7a0JBTGpDLFNBQVM7K0JBQ0ksbUJBQW1CO2tOQW9CTixRQUFRO3NCQUE5QixTQUFTO3VCQUFDLFVBQVU7Z0JBQ0MsZUFBZTtzQkFBcEMsU0FBUzt1QkFBQyxTQUFTO2dCQWNYLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFVRyxZQUFZO3NCQUFwQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtDT01NQSwgRU5URVIsIFRBQn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcbmltcG9ydCB7Q2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgT25Jbml0LCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgT3V0cHV0LCBJbnB1dH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7RW50cnl9IGZyb20gJy4uLy4uL2RhdGEvZW50cnknO1xuaW1wb3J0IHtTZWN0aW9ufSBmcm9tICcuLi8uLi9kYXRhL3NlY3Rpb24nO1xuaW1wb3J0IHtDb250ZW50fSBmcm9tICcuLi8uLi9kYXRhL2NvbnRlbnQnO1xuaW1wb3J0IHtDb250ZW50VHlwZX0gZnJvbSAnLi4vLi4vZGF0YS9jb250ZW50LXR5cGUnO1xuaW1wb3J0IHtJZGVudGl0eX0gZnJvbSAnLi4vLi4vZGF0YS9pZGVudGl0eSc7XG5cbmltcG9ydCB7RW50cnlTZXJ2aWNlfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9lbnRyeS5zZXJ2aWNlJztcbmltcG9ydCB7SWRlbnRpdHlTZXJ2aWNlfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9pZGVudGl0eS5zZXJ2aWNlJztcblxuaW1wb3J0IHttYXAgYXMgbG9NYXAsIGZpbHRlcn0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7TWF0RGlhbG9nfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHtNYXRBdXRvY29tcGxldGVTZWxlY3RlZEV2ZW50LCBNYXRBdXRvY29tcGxldGV9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2F1dG9jb21wbGV0ZSc7XG5pbXBvcnQge0VudHJ5U2VsZWN0b3JEaWFsb2dDb21wb25lbnR9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvZW50cnktc2VsZWN0b3ItZGlhbG9nL2VudHJ5LXNlbGVjdG9yLWRpYWxvZy5jb21wb25lbnQnO1xuaW1wb3J0IHtGaWxlVXBsb2FkZXJ9IGZyb20gJ25nMi1maWxlLXVwbG9hZCc7XG5pbXBvcnQge01lZGlhVXBsb2FkTW9kYWxDb21wb25lbnR9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvbWVkaWEtdXBsb2FkLW1vZGFsL21lZGlhLXVwbG9hZC1tb2RhbC5jb21wb25lbnQnO1xuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tICdyeGpzJztcbmltcG9ydCB7bWFwLCBzdGFydFdpdGh9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7VW50eXBlZEZvcm1Db250cm9sfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge01hdENoaXBJbnB1dEV2ZW50fSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jaGlwcyc7XG5pbXBvcnQge1RhZ1NlcnZpY2V9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RhZy5zZXJ2aWNlJztcbmltcG9ydCB7U2NoZWR1bGVQdWJsaXNoRGlhbG9nQ29tcG9uZW50fSBmcm9tICcuLi9zY2hlZHVsZS1wdWJsaXNoLWRpYWxvZy9zY2hlZHVsZS1wdWJsaXNoLWRpYWxvZy5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2FwcC1lbnRyeS1jcmVhdG9yJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZW50cnktY3JlYXRvci5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZW50cnktY3JlYXRvci5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIEVudHJ5Q3JlYXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgICBzdGF0aWMgQ1VSUkVOVF9FTlRSWSA9ICdjdXJyZW50X2VudHJ5JztcbiAgICBzdGF0aWMgREVGQVVMVF9ORVdfRU5UUllfVElUTEUgPSAnQSBOZXcgRW50cnknO1xuXG4gICAgQ29udGVudFR5cGUgPSBDb250ZW50VHlwZTtcbiAgICBPYmplY3QgPSBPYmplY3Q7XG5cbiAgICBlbnRyeTogRW50cnkgPSBudWxsO1xuICAgIG1lOiBJZGVudGl0eTtcblxuICAgIHNlcGFyYXRvcktleXNDb2RlczogbnVtYmVyW10gPSBbRU5URVIsIENPTU1BLCBUQUJdO1xuICAgIHJlbW92YWJsZSA9IHRydWU7XG4gICAgdGFnczogc3RyaW5nW107XG4gICAgYWxsX3RhZ3M6IHN0cmluZ1tdID0gWydBbmd1bGFyJywgJ0Jhc2gnLCAnTWFjT1MnLCAnVHlwZXNjcmlwdCcsICdOUE0nLCAnRGF0YWJhc2VzJ107XG4gICAgZmlsdGVyZWRfdGFnczogT2JzZXJ2YWJsZTxzdHJpbmdbXT47XG4gICAgQFZpZXdDaGlsZCgndGFnSW5wdXQnKSB0YWdJbnB1dDogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcbiAgICBAVmlld0NoaWxkKCd0YWdhdXRvJykgbWF0QXV0b2NvbXBsZXRlOiBNYXRBdXRvY29tcGxldGU7XG5cbiAgICB0YWdDdHJsID0gbmV3IFVudHlwZWRGb3JtQ29udHJvbCgpO1xuICAgIHB1Ymxpc2hEYXRlQ29udHJvbCA9IG5ldyBVbnR5cGVkRm9ybUNvbnRyb2woKTtcblxuICAgIHRhZ190b19hZGQ6IHN0cmluZztcbiAgICBzZWxlY3RhYmxlID0gZmFsc2U7XG5cbiAgICBzY2hlZHVsaW5nID0gZmFsc2U7XG4gICAgY3VzdG9tU2NoZWR1bGVUaW1lID0gJyc7XG4gICAgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuICAgIGhvdXJzOiBudW1iZXI7XG4gICAgbWludXRlczogbnVtYmVyO1xuXG4gICAgQElucHV0KCkgYWxsb3dlZE1pbWVUeXBlcyA9IFtcbiAgICAgICAgICAgICAgICAnaW1hZ2UvanBlZycsXG4gICAgICAgICAgICAgICAgJ2ltYWdlL2dpZicsXG4gICAgICAgICAgICAgICAgJ2ltYWdlL3BuZycsXG4gICAgICAgICAgICAgICAgJ2ltYWdlL2pwZycsXG4gICAgICAgICAgICAgICAgJ3ZpZGVvL21wNCcsXG4gICAgICAgICAgICAgICAgJ3ZpZGVvL3dlYm0nLFxuICAgICAgICAgICAgICAgICd2aWRlby9vZ2cnLFxuICAgIF07XG5cbiAgICBASW5wdXQoKSB1cGxvYWRVcmxLZXkgPSAncGF0aF90b19maWxlJztcblxuICAgIHB1YmxpYyB1cGxvYWRlcjogRmlsZVVwbG9hZGVyID0gbmV3IEZpbGVVcGxvYWRlcihcbiAgICAgICAge1xuICAgICAgICAgICAgdXJsOiAnL2ZpbGVfYXBpL3VwbG9hZHMvY3JlYXRlX2ltYWdlLycsXG4gICAgICAgICAgICBpdGVtQWxpYXM6ICdmaWxlJyxcbiAgICAgICAgICAgIGF1dGhUb2tlbjogJycsXG4gICAgICAgICAgICBoZWFkZXJzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiAnWC1DU1JGVG9rZW4nLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogRW50cnlDcmVhdG9yQ29tcG9uZW50LmdldENvb2tpZSgnY3NyZnRva2VuJylcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGFkZGl0aW9uYWxQYXJhbWV0ZXI6IHtcbiAgICAgICAgICAgICAgICAnY3NyZl90b2tlbic6IEVudHJ5Q3JlYXRvckNvbXBvbmVudC5nZXRDb29raWUoJ2NzcmZ0b2tlbicpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVtb3ZlQWZ0ZXJVcGxvYWQ6IHRydWUsXG4gICAgICAgICAgICBhbGxvd2VkTWltZVR5cGU6IHRoaXMuYWxsb3dlZE1pbWVUeXBlcyxcbiAgICAgICAgfVxuICAgICk7XG5cbiAgICBzdGF0aWMgZ2V0Q29va2llKG5hbWU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBjYTogQXJyYXk8c3RyaW5nPiA9IGRvY3VtZW50LmNvb2tpZS5zcGxpdCgnOycpO1xuICAgICAgICBjb25zdCBjYUxlbjogbnVtYmVyID0gY2EubGVuZ3RoO1xuICAgICAgICBjb25zdCBjb29raWVOYW1lID0gYCR7bmFtZX09YDtcbiAgICAgICAgbGV0IGM6IHN0cmluZztcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNhTGVuOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGMgPSBjYVtpXS5yZXBsYWNlKC9eXFxzKy9nLCAnJyk7XG4gICAgICAgICAgICBpZiAoYy5pbmRleE9mKGNvb2tpZU5hbWUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGMuc3Vic3RyaW5nKGNvb2tpZU5hbWUubGVuZ3RoLCBjLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIGVudHJ5U2VydmljZTogRW50cnlTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHRhZ1NlcnZpY2U6IFRhZ1NlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgaWRlbnRpdHlTZXJ2aWNlOiBJZGVudGl0eVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHJpdmF0ZSBkaWFsb2c6IE1hdERpYWxvZyxcbiAgICApIHtcbiAgICAgICAgY29uc3Qgc2NoZWR1bGVkRGF0ZSA9IG5ldyBEYXRlKCk7XG4gICAgICAgIHRoaXMuY3VzdG9tU2NoZWR1bGVUaW1lID0gc2NoZWR1bGVkRGF0ZS5nZXRIb3VycygpICsgJzonICsgc2NoZWR1bGVkRGF0ZS5nZXRNaW51dGVzKCkgKyAnIEFNJztcbiAgICB9XG5cbiAgICBwcml2YXRlIF9maWx0ZXIodmFsdWU6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICAgICAgY29uc3QgZmlsdGVyVmFsdWUgPSB2YWx1ZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gdGhpcy5hbGxfdGFncy5maWx0ZXIodGFnID0+IHRhZy50b0xvd2VyQ2FzZSgpLmluZGV4T2YoZmlsdGVyVmFsdWUpID09PSAwKTtcbiAgICB9XG5cbiAgICBhZGQoZXZlbnQ6IE1hdENoaXBJbnB1dEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGlucHV0ID0gZXZlbnQuaW5wdXQ7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZXZlbnQudmFsdWU7XG5cbiAgICAgICAgLy8gQWRkIG91ciB0YWdcbiAgICAgICAgaWYgKCh2YWx1ZSB8fCAnJykudHJpbSgpKSB7XG4gICAgICAgICAgICB0aGlzLnRhZ3MucHVzaCh2YWx1ZS50cmltKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzZXQgdGhlIGlucHV0IHZhbHVlXG4gICAgICAgIGlmIChpbnB1dCkge1xuICAgICAgICAgICAgaW5wdXQudmFsdWUgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudGFnQ3RybC5zZXRWYWx1ZShudWxsKTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSgpO1xuICAgIH1cblxuICAgIHJlbW92ZShmcnVpdDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy50YWdzLmluZGV4T2YoZnJ1aXQpO1xuXG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnRhZ3Muc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uQ2hhbmdlKCk7XG4gICAgfVxuXG4gICAgc2VsZWN0ZWQoZXZlbnQ6IE1hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50YWdzLnB1c2goZXZlbnQub3B0aW9uLnZpZXdWYWx1ZSk7XG4gICAgICAgIHRoaXMudGFnSW5wdXQubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuICAgICAgICB0aGlzLnRhZ0N0cmwuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgIHRoaXMub25DaGFuZ2UoKTtcbiAgICB9XG5cbiAgICByZWZyZXNoVGFncygpIHtcbiAgICAgICAgdGhpcy50YWdTZXJ2aWNlLmdldCgpLnN1YnNjcmliZSgocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIHRoaXMuYWxsX3RhZ3MgPSBsb01hcChyZXNwb25zZS5yZXN1bHRzLCAodCkgPT4gdC5sYWJlbCk7XG4gICAgICAgICAgICB0aGlzLmZpbHRlcmVkX3RhZ3MgPSB0aGlzLnRhZ0N0cmwudmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICAgICAgICAgICAgc3RhcnRXaXRoKG51bGwpLFxuICAgICAgICAgICAgICAgIG1hcCgodGFnOiBzdHJpbmcgfCBudWxsKSA9PiB0YWcgPyB0aGlzLl9maWx0ZXIodGFnKSA6IHRoaXMuYWxsX3RhZ3Muc2xpY2UoKSkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjcmVhdGVOZXdFbnRyeSgpIHtcbiAgICAgICAgdGhpcy5lbnRyeSA9IG5ldyBFbnRyeSgpO1xuICAgICAgICB0aGlzLmVudHJ5LnRpdGxlID0gRW50cnlDcmVhdG9yQ29tcG9uZW50LkRFRkFVTFRfTkVXX0VOVFJZX1RJVExFO1xuICAgICAgICB0aGlzLmVudHJ5LnB1Ymxpc2hlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVudHJ5LnZlcnNpb24gPSAxO1xuXG4gICAgICAgIHRoaXMuZW50cnlTZXJ2aWNlLmNyZWF0ZSh0aGlzLmVudHJ5KS5zdWJzY3JpYmUoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVudHJ5ID0gcmVzcG9uc2U7XG4gICAgICAgICAgICB0aGlzLmVudHJ5LnNvcnQoKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZW50cnlTZXJ2aWNlLmN1cnJlbnRseUVkaXRlZEVudHJ5Lm5leHQodGhpcy5lbnRyeSk7XG4gICAgICAgICAgICB9LCAxMCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLnJlZnJlc2hUYWdzKCk7XG4gICAgICAgIHRoaXMuaWRlbnRpdHlTZXJ2aWNlLmdldE1lKCkuc3Vic2NyaWJlKChtZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5tZSA9IG1lO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBzYXZlZEVudHJ5ID1cbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5nZXRJdGVtKEVudHJ5Q3JlYXRvckNvbXBvbmVudC5DVVJSRU5UX0VOVFJZKTtcblxuICAgICAgICBpZiAoc2F2ZWRFbnRyeSkge1xuICAgICAgICAgICAgdGhpcy5lbnRyeSA9IG5ldyBFbnRyeShKU09OLnBhcnNlKHNhdmVkRW50cnkpKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZW50cnkuc2hvdWxkX3B1Ymxpc2hfaW5fZnV0dXJlICYmIHRoaXMuZW50cnkuZnV0dXJlX3B1Ymxpc2hfZGF0ZSA8IG5ldyBEYXRlKCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZU5ld0VudHJ5KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZW50cnkuc29ydCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZW50cnkuc2hvdWxkX3B1Ymxpc2hfaW5fZnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVzdG9yZSBzY2hlZHVsaW5nIHNldHRpbmdzXG4gICAgICAgICAgICAgICAgdGhpcy5zY2hlZHVsaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBsZXQgaG91cnMgPSB0aGlzLmVudHJ5LmZ1dHVyZV9wdWJsaXNoX2RhdGUuZ2V0SG91cnMoKTtcbiAgICAgICAgICAgICAgICBsZXQgbWludXRlczogc3RyaW5nIHwgbnVtYmVyID0gdGhpcy5lbnRyeS5mdXR1cmVfcHVibGlzaF9kYXRlLmdldE1pbnV0ZXMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhbXBtID0gaG91cnMgPj0gMTIgPyAnUE0nIDogJ0FNJztcbiAgICAgICAgICAgICAgICBpZiAoaG91cnMgPj0gMTIpIHtcbiAgICAgICAgICAgICAgICAgICAgaG91cnMgPSBob3VycyAlIDEyO1xuICAgICAgICAgICAgICAgICAgICBob3VycyA9IGhvdXJzID8gaG91cnMgOiAxMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbWludXRlcyA9IG1pbnV0ZXMgPCAxMCA/ICcwJyArIG1pbnV0ZXMgOiBtaW51dGVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY3VzdG9tU2NoZWR1bGVUaW1lID0gaG91cnMgKyAnOicgKyBtaW51dGVzICsgJyAnICsgYW1wbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZW50cnlTZXJ2aWNlLmN1cnJlbnRseUVkaXRlZEVudHJ5Lm5leHQodGhpcy5lbnRyeSk7XG4gICAgICAgICAgICB9LCAxMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNlZUVudHJpZXMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudXBsb2FkZXIub25Db21wbGV0ZUl0ZW0gPSAoaXRlbSwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgIC8vIGNvbnN0IHJlc3BvbnNlT2JqID0gSlNPTi5wYXJzZShyZXNwb25zZSlcbiAgICAgICAgICAgIC8vIHRoaXMudXBsb2FkSWQgPSByZXNwb25zZU9iai5pZDtcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnVwbG9hZGVyLm9uV2hlbkFkZGluZ0ZpbGVGYWlsZWQgPSAoaXRlbSwgdXBsb2FkRmlsdGVyLCBvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAvLyB0aGlzLmVycm9yID0gJ1RoaXMgZmlsZSBpcyBub3QgYSBzdXBwb3J0ZWQgbWltZXR5cGUuJ1xuICAgICAgICAgICAgLy8gdGhpcy51cGxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnRhZ3MgPSB0aGlzLmVudHJ5LnRhZ3M7XG4gICAgfVxuXG4gICAgb25GaWxlU2VsZWN0ZWQoZSkge1xuICAgICAgICB0aGlzLnVwbG9hZGVyLnVwbG9hZEFsbCgpO1xuICAgIH1cblxuICAgIHN0YXJ0VXBsb2FkZXIoY29udGVudCkge1xuICAgICAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKE1lZGlhVXBsb2FkTW9kYWxDb21wb25lbnQsIHtcbiAgICAgICAgfSk7XG4gICAgICAgIGRpYWxvZ1JlZi5jb21wb25lbnRJbnN0YW5jZS5hbGxvd2VkTWltZVR5cGVzID0gdGhpcy5hbGxvd2VkTWltZVR5cGVzO1xuICAgICAgICBkaWFsb2dSZWYuY29tcG9uZW50SW5zdGFuY2UudXBsb2FkVXJsS2V5ID0gdGhpcy51cGxvYWRVcmxLZXk7XG4gICAgICAgIGRpYWxvZ1JlZi5hZnRlckNsb3NlZCgpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICBjb250ZW50LnZhbHVlID0gZGlhbG9nUmVmLmNvbXBvbmVudEluc3RhbmNlLmltZ0xpbms7XG4gICAgICAgICAgICBjb250ZW50LmFkZGl0aW9uYWwgPSBbXTtcbiAgICAgICAgICAgIGNvbnRlbnQuYWRkaXRpb25hbC5wdXNoKHtrZXk6IENvbnRlbnQuS0VZX01JTUVUWVBFLCB2YWx1ZTogZGlhbG9nUmVmLmNvbXBvbmVudEluc3RhbmNlLm1pbWVUeXBlfSk7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFkZFNlY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuZW50cnkuc2VjdGlvbnMucHVzaChuZXcgU2VjdGlvbigpKTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSgpO1xuICAgIH1cblxuICAgIHJlbW92ZVNlY3Rpb24oc2VjdGlvbikge1xuICAgICAgICBjb25zdCByZW1vdmUgPSBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmVtb3ZlIHRoaXMgc2VjdGlvbj8nKTtcbiAgICAgICAgaWYgKHJlbW92ZSkge1xuICAgICAgICAgICAgdGhpcy5lbnRyeS5zZWN0aW9ucyA9XG4gICAgICAgICAgICAgICAgZmlsdGVyKHRoaXMuZW50cnkuc2VjdGlvbnMsIChzY3QpID0+IHNjdC5pZCAhPT0gc2VjdGlvbi5pZCk7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhZGRDb250ZW50KHNlY3Rpb24pIHtcbiAgICAgICAgc2VjdGlvbi5jb250ZW50cy5wdXNoKG5ldyBDb250ZW50KCkpO1xuICAgICAgICB0aGlzLm9uQ2hhbmdlKCk7XG4gICAgfVxuXG4gICAgcmVtb3ZlQ29udGVudChjb250ZW50KSB7XG4gICAgICAgIGNvbnN0IHJlbW92ZSA9IGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhpcyBjb250ZW50PycpO1xuXG4gICAgICAgIGlmIChyZW1vdmUpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3Qgc2VjdGlvbiBvZiB0aGlzLmVudHJ5LnNlY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgc2VjdGlvbi5jb250ZW50cyA9IGZpbHRlcihcbiAgICAgICAgICAgICAgICAgICAgc2VjdGlvbi5jb250ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgKGN0KSA9PiBjdC5pZCAhPT0gY29udGVudC5pZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbkNoYW5nZSgpIHtcbiAgICAgICAgdGhpcy5lbnRyeS5zbHVnID0gdGhpcy5lbnRyeVNlcnZpY2Uuc2x1Z2lmeSh0aGlzLmVudHJ5LnRpdGxlKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcbiAgICAgICAgICAgIEVudHJ5Q3JlYXRvckNvbXBvbmVudC5DVVJSRU5UX0VOVFJZLFxuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkodGhpcy5lbnRyeSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5lbnRyeS5zb3J0KCk7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgdGhpcy5lbnRyeVNlcnZpY2UuY3VycmVudGx5RWRpdGVkRW50cnkubmV4dCh0aGlzLmVudHJ5KTtcbiAgICAgICAgdGhpcy5lbnRyeVNlcnZpY2UuX2N1cnJlbnRseUVkaXRlZEVudHJ5ID0gdGhpcy5lbnRyeTtcbiAgICB9XG5cbiAgICByZXNldERhdGUoKSB7XG4gICAgICAgIHRoaXMuZW50cnkuY3JlYXRlX2RhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgICB0aGlzLmVudHJ5LmVkaXRfZGF0ZSA9IG5ldyBEYXRlKCk7XG5cbiAgICAgICAgdGhpcy5vbkNoYW5nZSgpO1xuICAgIH1cblxuICAgIHN0YXJ0TmV3KCkge1xuICAgICAgICBjb25zdCBmaW5pc2ggPSBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91ciBmaW5pc2hlZD8gVGhlIEpTT04gYW5kIGVudHJ5IGRpc3BsYXllZCB3aWxsIGJlIHJlbW92ZWQuIE1ha2Ugc3VyZSB5b3UgaGF2ZSBhbHJlYWR5IGNvcGllZCBpdC4nKTtcbiAgICAgICAgaWYgKGZpbmlzaCkge1xuXG4gICAgICAgICAgICB0aGlzLmVudHJ5ID0gbmV3IEVudHJ5KCk7XG4gICAgICAgICAgICB0aGlzLmVudHJ5LnRpdGxlID0gRW50cnlDcmVhdG9yQ29tcG9uZW50LkRFRkFVTFRfTkVXX0VOVFJZX1RJVExFO1xuICAgICAgICAgICAgdGhpcy5lbnRyeS5wdWJsaXNoZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuZW50cnkudmVyc2lvbiA9IDE7XG5cbiAgICAgICAgICAgIHRoaXMuZW50cnlTZXJ2aWNlLmN1cnJlbnRseUVkaXRlZEVudHJ5Lm5leHQodGhpcy5lbnRyeSk7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcbiAgICAgICAgICAgICAgICBFbnRyeUNyZWF0b3JDb21wb25lbnQuQ1VSUkVOVF9FTlRSWSxcbiAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeSh0aGlzLmVudHJ5KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuZW50cnlTZXJ2aWNlLmNyZWF0ZSh0aGlzLmVudHJ5KS5zdWJzY3JpYmUoKG5leHQpID0+IHtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2VlRW50cmllcygpIHtcbiAgICAgICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihFbnRyeVNlbGVjdG9yRGlhbG9nQ29tcG9uZW50LCB7XG4gICAgICAgICAgICB3aWR0aDogJzgwMHB4JyxcbiAgICAgICAgICAgIGRhdGE6IHtuYW1lOiAndGVzdCcsIGFuaW1hbDogJ3Rlc3QnfVxuICAgICAgICB9KTtcblxuICAgICAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoKGlkKSA9PiB7XG4gICAgICAgICAgICBpZiAoaWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVudHJ5U2VydmljZS5nZXRVbnB1Ymxpc2hlZEJ5SWQoaWQpLnN1YnNjcmliZSgocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVudHJ5U2VydmljZS5jdXJyZW50bHlFZGl0ZWRFbnRyeS5uZXh0KGVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oXG4gICAgICAgICAgICAgICAgICAgICAgICBFbnRyeUNyZWF0b3JDb21wb25lbnQuQ1VSUkVOVF9FTlRSWSxcbiAgICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGVudHJ5KVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVudHJ5ID0gZW50cnk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHBvc3RQdWJsaXNoQ2FsbGJhY2soKSB7XG4gICAgICB0aGlzLmVudHJ5U2VydmljZS5jdXJyZW50bHlFZGl0ZWRFbnRyeS5uZXh0KG51bGwpO1xuICAgICAgdGhpcy5lbnRyeSA9IG51bGw7XG4gICAgICB0aGlzLnNlZUVudHJpZXMoKTtcbiAgICB9XG5cbiAgICBjYW5jZWxTY2hlZHVsaW5nKCkge1xuICAgICAgICB0aGlzLmVudHJ5LmZ1dHVyZV9wdWJsaXNoX2RhdGUgPSBudWxsO1xuICAgICAgICB0aGlzLmVudHJ5LnNob3VsZF9wdWJsaXNoX2luX2Z1dHVyZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnNjaGVkdWxpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSgpO1xuICAgIH1cblxuICAgIGV4cG9zZVNjaGVkdWxpbmcoKSB7XG4gICAgICAgIGNvbnN0IHNjaGVkdWxlZERhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBzY2hlZHVsZWREYXRlLnNldERhdGUoc2NoZWR1bGVkRGF0ZS5nZXREYXRlKCkgKyAxKTtcblxuICAgICAgICB0aGlzLmVudHJ5LmZ1dHVyZV9wdWJsaXNoX2RhdGUgPSBzY2hlZHVsZWREYXRlO1xuICAgICAgICB0aGlzLnNldFRpbWUodGhpcy5jdXN0b21TY2hlZHVsZVRpbWUpO1xuXG4gICAgICAgIHRoaXMuZW50cnkuc2hvdWxkX3B1Ymxpc2hfaW5fZnV0dXJlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zY2hlZHVsaW5nID0gIHRydWU7XG4gICAgICAgIHRoaXMub25DaGFuZ2UoKTtcbiAgICB9XG4gICAgcHVibGlzaCgpIHtcbiAgICAgICAgY29uc3QgcHVibGlzaCA9IGNvbmZpcm0oJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBwdWJsaXNoPyBPbmNlIGFuIGFydGljbGUgaXMgcHVibGlzaGVkIGl0IGlzIGF2YWlsYWJsZSB0byBldmVyeW9uZS4nKTtcbiAgICAgICAgaWYgKHB1Ymxpc2gpIHtcbiAgICAgICAgICAgIHRoaXMuZW50cnkucHVibGlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuZW50cnkucHVibGlzaF9kYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuZW50cnkuZWRpdF9kYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgIHRoaXMuZW50cnlTZXJ2aWNlLnVwZGF0ZVVucHVibGlzaGVkRW50cnkodGhpcy5lbnRyeSkuc3Vic2NyaWJlKHRoaXMucG9zdFB1Ymxpc2hDYWxsYmFjay5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZWxldGUoKSB7XG4gICAgICAgIGNvbnN0IGNvbmZpcm1EZWxldGUgPSBjb25maXJtKCdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoaXMgZHJhZnQ/IE9uY2UgaXQgaXMgZGVsZXRlZCBpdCBjYW5ub3QgYmUgcmVjb3ZlcmVkLicpO1xuICAgICAgICBpZiAoY29uZmlybURlbGV0ZSkge1xuICAgICAgICAgICAgdGhpcy5lbnRyeVNlcnZpY2UuZGVsZXRlKHRoaXMuZW50cnkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbnRyeSA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5lbnRyeVNlcnZpY2UuY3VycmVudGx5RWRpdGVkRW50cnkubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShFbnRyeUNyZWF0b3JDb21wb25lbnQuQ1VSUkVOVF9FTlRSWSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBvbkRhdGVDaGFuZ2UoKSB7XG4gICAgICAgIHRoaXMuZW50cnkuZnV0dXJlX3B1Ymxpc2hfZGF0ZS5zZXRIb3Vycyh0aGlzLmhvdXJzKTtcbiAgICAgICAgdGhpcy5lbnRyeS5mdXR1cmVfcHVibGlzaF9kYXRlLnNldE1pbnV0ZXModGhpcy5taW51dGVzKTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSgpO1xuICAgIH1cblxuXG4gICAgc2V0VGltZShlKSB7XG4gICAgICAgIGNvbnN0IGZpcnN0VGltZVNwbGl0ID0gZS5zcGxpdCgnICcpO1xuICAgICAgICBjb25zdCBzZWNvbmRUaW1lU3BsaXQgPSBmaXJzdFRpbWVTcGxpdFswXS5zcGxpdCgnOicpO1xuICAgICAgICB0aGlzLmhvdXJzID0gTnVtYmVyKHNlY29uZFRpbWVTcGxpdFswXSk7XG4gICAgICAgIHRoaXMubWludXRlcyA9IE51bWJlcihzZWNvbmRUaW1lU3BsaXRbMV0pO1xuXG4gICAgICAgIGlmIChmaXJzdFRpbWVTcGxpdFsxXSA9PT0gJ1BNJykge1xuICAgICAgICAgICAgdGhpcy5ob3VycyA9IE51bWJlcih0aGlzLmhvdXJzKSArIDEyO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5lbnRyeS5mdXR1cmVfcHVibGlzaF9kYXRlLnNldEhvdXJzKHRoaXMuaG91cnMpO1xuICAgICAgICB0aGlzLmVudHJ5LmZ1dHVyZV9wdWJsaXNoX2RhdGUuc2V0TWludXRlcyh0aGlzLm1pbnV0ZXMpO1xuXG4gICAgICAgIHRoaXMub25DaGFuZ2UoKTtcbiAgICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwic2VjdGlvbiBjcmVhdG9yIGZpZWxkc1wiPlxuICA8Zm9ybSAjY3JlYXRlRm9ybT1cIm5nRm9ybVwiIChjaGFuZ2UpPVwib25DaGFuZ2UoKVwiICpuZ0lmPVwidGhpcy5lbnRyeVwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgIDxtYXQtbGFiZWw+VGl0bGU8L21hdC1sYWJlbD5cbiAgICAgICAgPGlucHV0IG1hdElucHV0XG4gICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudHJ5LnRpdGxlXCJcbiAgICAgICAgICAgICAgIG5hbWU9XCJ0aXRsZVwiPlxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICA8L2Rpdj5cbiAgICA8bWF0LWNhcmQgY2xhc3M9XCJmb3JtLXNlY3Rpb24gdGFnc1wiPlxuICAgICAgPGRpdj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiIGhpbnRMYWJlbD1cIlVzZSBhIGNvbW1hIHRvIHNlcGVyYXRlIGRpZmZlcmVudCB0YWdzXCI+XG4gICAgICAgICAgPG1hdC1jaGlwLWxpc3Rib3ggI3RhZ0xpc3QgYXJpYS1sYWJlbD1cIlRhZ3NcIj5cbiAgICAgICAgICAgIDxtYXQtY2hpcC1vcHRpb25cbiAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgdGFnIG9mIHRhZ3NcIlxuICAgICAgICAgICAgICAgIFtzZWxlY3RhYmxlXT1cInNlbGVjdGFibGVcIlxuICAgICAgICAgICAgICAgIFtyZW1vdmFibGVdPVwicmVtb3ZhYmxlXCJcbiAgICAgICAgICAgICAgICAocmVtb3ZlZCk9XCJyZW1vdmUodGFnKVwiPlxuICAgICAgICAgICAgICB7e3RhZ319XG4gICAgICAgICAgICAgIDxtYXQtaWNvbiBtYXRDaGlwUmVtb3ZlICpuZ0lmPVwicmVtb3ZhYmxlXCI+Y2FuY2VsPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvbWF0LWNoaXAtb3B0aW9uPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlRhZ3MuLi5cIlxuICAgICAgICAgICAgICAgICN0YWdJbnB1dFxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJ0YWdDdHJsXCJcbiAgICAgICAgICAgICAgICBbbWF0QXV0b2NvbXBsZXRlXT1cInRhZ2F1dG9cIlxuICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRGb3JdPVwidGFnTGlzdFwiXG4gICAgICAgICAgICAgICAgW21hdENoaXBJbnB1dFNlcGFyYXRvcktleUNvZGVzXT1cInNlcGFyYXRvcktleXNDb2Rlc1wiXG4gICAgICAgICAgICAgICAgKG1hdENoaXBJbnB1dFRva2VuRW5kKT1cImFkZCgkZXZlbnQpXCI+XG4gICAgICAgICAgPC9tYXQtY2hpcC1saXN0Ym94PlxuICAgICAgICAgIDxtYXQtYXV0b2NvbXBsZXRlICN0YWdhdXRvPVwibWF0QXV0b2NvbXBsZXRlXCIgKG9wdGlvblNlbGVjdGVkKT1cInNlbGVjdGVkKCRldmVudClcIj5cbiAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCB0YWcgb2YgZmlsdGVyZWRfdGFncyB8IGFzeW5jXCIgW3ZhbHVlXT1cInRhZ1wiPlxuICAgICAgICAgICAgICB7e3RhZ319XG4gICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgPC9tYXQtYXV0b2NvbXBsZXRlPlxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgPC9kaXY+XG4gICAgPC9tYXQtY2FyZD5cbiAgICA8bWF0LWNhcmQgY2xhc3M9XCJmb3JtLXNlY3Rpb25cIiAqbmdGb3I9XCJsZXQgc2VjdGlvbiBvZiBlbnRyeS5zZWN0aW9uc1wiPlxuICAgICAgPGRpdj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgIDxtYXQtbGFiZWw+U3ViaGVhZGluZzwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInNlY3Rpb24uc3ViaGVhZGluZ1wiXG4gICAgICAgICAgICAgICAgIG5hbWU9XCJ7e3NlY3Rpb24uaWR9fS1zdWJoZWFkaW5nXCI+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNvbnRlbnRcIiAqbmdGb3I9XCJsZXQgY29udGVudCBvZiBzZWN0aW9uLmNvbnRlbnRzXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICAgIDxtYXQtcmFkaW8tZ3JvdXBcbiAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiU2VsZWN0IHRoZSBDb250ZW50IFR5cGVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJ7e2NvbnRlbnQuaWR9fS1jb250ZW50LXR5cGVcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwicmFkaW8tZ3JvdXBcIlxuICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiY29udGVudC50eXBlXCI+XG4gICAgICAgICAgICAgIDxtYXQtcmFkaW8tYnV0dG9uXG4gICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgdmFsdWUgb2YgT2JqZWN0LnZhbHVlcyhDb250ZW50VHlwZSlcIlxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJyYWRpby1idXR0b25cIlxuICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInZhbHVlXCI+e3t2YWx1ZX19XG4gICAgICAgICAgICAgIDwvbWF0LXJhZGlvLWJ1dHRvbj5cbiAgICAgICAgICAgIDwvbWF0LXJhZGlvLWdyb3VwPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cImNvbnRlbnQudHlwZVwiPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiQ29udGVudFR5cGUuVVJMXCI+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlZhbHVlPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ7e2NvbnRlbnQuaWR9fS1jb250ZW50LXZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjb250ZW50LnZhbHVlXCI+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlRpdGxlPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ7e2NvbnRlbnQuaWR9fS1jb250ZW50LXRpdGxlXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjb250ZW50LnRpdGxlXCI+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIkNvbnRlbnRUeXBlLlRFWFRcIj5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+VmFsdWU8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8dGV4dGFyZWEgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2RrVGV4dGFyZWFBdXRvc2l6ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAjYXV0b3NpemU9XCJjZGtUZXh0YXJlYUF1dG9zaXplXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2RrQXV0b3NpemVNaW5Sb3dzPVwiM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNka0F1dG9zaXplTWF4Um93cz1cIjIwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInt7Y29udGVudC5pZH19LWNvbnRlbnQtdmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvbnRlbnQudmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICA+PC90ZXh0YXJlYT5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiQ29udGVudFR5cGUuSFRNTFwiPlxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5WYWx1ZTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDx0ZXh0YXJlYSBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjZGtUZXh0YXJlYUF1dG9zaXplXG4gICAgICAgICAgICAgICAgICAgICAgICAgICNhdXRvc2l6ZT1cImNka1RleHRhcmVhQXV0b3NpemVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBjZGtBdXRvc2l6ZU1pblJvd3M9XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2RrQXV0b3NpemVNYXhSb3dzPVwiMjBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwie3tjb250ZW50LmlkfX0tY29udGVudC12YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiY29udGVudC52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgID48L3RleHRhcmVhPlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCJDb250ZW50VHlwZS5DT0RFXCI+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlZhbHVlPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPHRleHRhcmVhIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNka1RleHRhcmVhQXV0b3NpemVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgI2F1dG9zaXplPVwiY2RrVGV4dGFyZWFBdXRvc2l6ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNka0F1dG9zaXplTWluUm93cz1cIjEwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2RrQXV0b3NpemVNYXhSb3dzPVwiMTAwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInt7Y29udGVudC5pZH19LWNvbnRlbnQtdmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvbnRlbnQudmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICA+PC90ZXh0YXJlYT5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiQ29udGVudFR5cGUuSU1BR0VcIj5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+VmFsdWU8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInt7Y29udGVudC5pZH19LWNvbnRlbnQtdmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvbnRlbnQudmFsdWVcIj5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+VmFsdWU8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInt7Y29udGVudC5pZH19LWNvbnRlbnQtc291cmNlXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjb250ZW50LnZhbHVlXCI+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPkRlc2NyaXB0aW9uPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ7e2NvbnRlbnQuaWR9fS1jb250ZW50LWRlc2NyaXB0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjb250ZW50LmRlc2NyaXB0aW9uXCI+XG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIkNvbnRlbnRUeXBlLk1FRElBXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvbnRlbnQudmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5WYWx1ZTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwie3tjb250ZW50LmlkfX0tY29udGVudC12YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImNvbnRlbnQudmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJmdWxsLXdpZHRoXCI+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+RGVzY3JpcHRpb248L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInt7Y29udGVudC5pZH19LWNvbnRlbnQtZGVzY3JpcHRpb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjb250ZW50LmRlc2NyaXB0aW9uXCI+XG4gICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJjb250ZW50LmFkZGl0aW9uYWxcIj5cbiAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGFkZCBvZiBjb250ZW50LmFkZGl0aW9uYWxcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZnVsbC13aWR0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3thZGQua2V5fX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInt7Y29udGVudC5pZH19LWNvbnRlbnQte3thZGQua2V5fX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFkZC52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFjb250ZW50LnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9c3RhcnRVcGxvYWRlcihjb250ZW50KT5VcGxvYWQ8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9cmVtb3ZlQ29udGVudChjb250ZW50KT5SZW1vdmUgQ29udGVudDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cImFkZENvbnRlbnQoc2VjdGlvbilcIj4rIEFkZCBDb250ZW50PC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJyZW1vdmVTZWN0aW9uKHNlY3Rpb24pXCI+UmVtb3ZlIFNlY3Rpb248L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtcmFpc2VkLWJ1dHRvbiAoY2xpY2spPVwiYWRkQ29udGVudChzZWN0aW9uKVwiICpuZ0lmPVwic2VjdGlvbi5jb250ZW50cy5sZW5ndGggPT09IDBcIj4rIEFkZFxuICAgICAgICAgIENvbnRlbnRcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cImFkZFNlY3Rpb24oKVwiPisgQWRkIFNlY3Rpb248L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuXG4gICAgPC9tYXQtY2FyZD5cbiAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJhZGRTZWN0aW9uKClcIiAqbmdJZj1cImVudHJ5LnNlY3Rpb25zPy5sZW5ndGggPT09IDBcIj4rIEFkZCBTZWN0aW9uPC9idXR0b24+XG4gICAgPGJ1dHRvbiBtYXQtcmFpc2VkLWJ1dHRvbiAoY2xpY2spPVwiYWRkU2VjdGlvbigpXCIgKm5nSWY9XCIhZW50cnkuc2VjdGlvbnNcIj4rIEFkZCBTZWN0aW9uPC9idXR0b24+XG5cbiAgICA8ZGl2IGNsYXNzPVwiY29udHJvbHNcIj5cbiAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cInJlc2V0RGF0ZSgpXCI+UmVzZXQgdGhlIERhdGU8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cImRlbGV0ZSgpXCI+RGVsZXRlPC9idXR0b24+XG4gICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIFtkaXNhYmxlZF09XCJzY2hlZHVsaW5nXCIgKGNsaWNrKT1cInB1Ymxpc2goKVwiPlB1Ymxpc2g8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gW2Rpc2FibGVkXT1cInNjaGVkdWxpbmdcIiAoY2xpY2spPVwiZXhwb3NlU2NoZWR1bGluZygpXCI+U2NoZWR1bGU8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cInN0YXJ0TmV3KClcIj5OZXc8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICA8cCAqbmdJZj1cInNjaGVkdWxpbmdcIj5QdWJsaXNoaW5nIGlzIGRpc2FibGVkIHdoaWxlIHNjaGVkdWxpbmcgaXMgYmVpbmcgdXNlZC48L3A+XG5cbiAgICA8bWF0LWNhcmQgW2hpZGRlbl09XCIhc2NoZWR1bGluZ1wiPlxuICAgICAgPGg0PlxuICAgICAgICBTY2hlZHVsaW5nIE9wdGlvbnNcbiAgICAgIDwvaDQ+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImZ1bGwtd2lkdGhcIj5cbiAgICAgICAgICA8bWF0LWxhYmVsPkRhdGU8L21hdC1sYWJlbD5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgI2Z1dHVyZVB1Ymxpc2hEYXRlXG4gICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgIFttYXREYXRlcGlja2VyXT1cInBpY2tlclwiXG4gICAgICAgICAgICAgIFttaW5dPVwidG9kYXlcIlxuICAgICAgICAgICAgICAoZGF0ZUlucHV0KT1cIm9uRGF0ZUNoYW5nZSgpXCJcbiAgICAgICAgICAgICAgKGRhdGVDaGFuZ2UpPVwib25EYXRlQ2hhbmdlKClcIlxuICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVudHJ5LmZ1dHVyZV9wdWJsaXNoX2RhdGVcIlxuICAgICAgICAgICAgICBuYW1lPVwiZnV0dXJlLXB1Ymxpc2gtZGF0ZVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyLXRvZ2dsZSBtYXRTdWZmaXggW2Zvcl09XCJwaWNrZXJcIj48L21hdC1kYXRlcGlja2VyLXRvZ2dsZT5cbiAgICAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyXG4gICAgICAgICAgICAgICAgICAjcGlja2VyPjwvbWF0LWRhdGVwaWNrZXI+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgICAgPG1hdC1sYWJlbD5UaW1lPC9tYXQtbGFiZWw+XG4gICAgICAgIDxuZ3gtdGltZXBpY2tlci1maWVsZFxuICAgICAgICAgICAgW2RlZmF1bHRUaW1lXT1cImN1c3RvbVNjaGVkdWxlVGltZVwiXG4gICAgICAgICAgICBbZm9ybWF0XT1cIjEyXCJcbiAgICAgICAgICAgIFtidXR0b25BbGlnbl09XCInbGVmdCdcIlxuICAgICAgICAgICAgKHRpbWVDaGFuZ2VkKT1cInNldFRpbWUoJGV2ZW50KVwiXG4gICAgICAgICAgICA+PC9uZ3gtdGltZXBpY2tlci1maWVsZD5cbiAgICAgICAgPHA+VGltZXMgYXJlIHJlcHJlc2VudGVkIGluIHlvdXIgbG9jYWwgdGltZSB6b25lPC9wPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgbWF0LWRpYWxvZy1hY3Rpb25zPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29udHJvbHNcIj5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJjYW5jZWxTY2hlZHVsaW5nKClcIj5DYW5jZWwgU2NoZWR1bGluZzwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPHA+VGhpcyBwb3N0IHdpbGwgYmUgcHVibGlzaGVkIGFzIHNvb24gYXMgaXRzIHNjaGVkdWxlZCBkYXRlIGFuZCB0aW1lIGFycml2ZS4gTm8gZnVydGhlciBhY3Rpb24gaXMgbmVlZGVkIGJ5IHlvdS4gSWYgeW91IGRvIG5vdFxuICAgICAgd2FudCB0byB1c2Ugc2NoZWR1bGluZywgeW91IGNhbiBjYW5jZWwgc2NoZWR1bGluZyBhbmQgbWFudWFsbHkgcHVibGlzaC48L3A+XG4gICAgPC9tYXQtY2FyZD5cbiAgPC9mb3JtPlxuICA8ZGl2IGNsYXNzPVwiY29udHJvbHNcIj5cbiAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJzZWVFbnRyaWVzKClcIj5TZWUgRW50cmllczwvYnV0dG9uPlxuICAgIDxidXR0b24gKm5nSWY9XCIhdGhpcy5lbnRyeVwiIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJzdGFydE5ldygpXCI+TmV3PC9idXR0b24+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=