ngx-scandoc 0.0.1 → 1.0.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.
- package/core/app.worker.d.ts +1 -0
- package/core/components/components.module.d.ts +8 -0
- package/core/components/webcam/domain/webcam-image.d.ts +35 -0
- package/core/components/webcam/domain/webcam-init-error.d.ts +4 -0
- package/core/components/webcam/domain/webcam-mirror-properties.d.ts +3 -0
- package/core/components/webcam/util/webcam.util.d.ts +8 -0
- package/core/components/webcam/webcam/webcam.component.d.ts +202 -0
- package/core/components/webcam/webcam.module.d.ts +9 -0
- package/core/pipes/pipes.module.d.ts +7 -0
- package/core/pipes/safeResourceUrl.pipe.d.ts +10 -0
- package/core/shared/material.module.d.ts +28 -0
- package/dialogs/components/blank/blank.component.d.ts +17 -0
- package/dialogs/components/confirm/confirm.component.d.ts +30 -0
- package/dialogs/components/loading/loading.component.d.ts +5 -0
- package/dialogs/components/scan-mobile/scan-mobile.component.d.ts +16 -0
- package/dialogs/components/scan-profile/scan-profile.component.d.ts +124 -0
- package/dialogs/components/scan-selfie/scan-selfie.component.d.ts +83 -0
- package/dialogs/dialogs.core.provider.d.ts +18 -0
- package/dialogs/dialogs.module.d.ts +21 -0
- package/esm2020/core/app.worker.mjs +236 -0
- package/esm2020/core/components/components.module.mjs +18 -0
- package/esm2020/core/components/webcam/domain/webcam-image.mjs +58 -0
- package/esm2020/core/components/webcam/domain/webcam-init-error.mjs +3 -0
- package/esm2020/core/components/webcam/domain/webcam-mirror-properties.mjs +3 -0
- package/esm2020/core/components/webcam/util/webcam.util.mjs +48 -0
- package/esm2020/core/components/webcam/webcam/webcam.component.mjs +861 -0
- package/esm2020/core/components/webcam/webcam.module.mjs +22 -0
- package/esm2020/core/pipes/pipes.module.mjs +19 -0
- package/esm2020/core/pipes/safeResourceUrl.pipe.mjs +20 -0
- package/esm2020/core/shared/material.module.mjs +162 -0
- package/esm2020/dialogs/components/blank/blank.component.mjs +47 -0
- package/esm2020/dialogs/components/confirm/confirm.component.mjs +53 -0
- package/esm2020/dialogs/components/loading/loading.component.mjs +12 -0
- package/esm2020/dialogs/components/scan-mobile/scan-mobile.component.mjs +43 -0
- package/esm2020/dialogs/components/scan-profile/scan-profile.component.mjs +756 -0
- package/esm2020/dialogs/components/scan-selfie/scan-selfie.component.mjs +392 -0
- package/esm2020/dialogs/dialogs.core.provider.mjs +100 -0
- package/esm2020/dialogs/dialogs.module.mjs +89 -0
- package/esm2020/forms/form.module.mjs +87 -0
- package/esm2020/forms/types/avatar.type.mjs +53 -0
- package/esm2020/forms/types/profile.image.type.mjs +54 -0
- package/esm2020/forms/types/title.type.mjs +60 -0
- package/esm2020/lib/ngx-scandoc.module.mjs +28 -11
- package/esm2020/providers/auth.provider.mjs +57 -0
- package/esm2020/providers/interceptor.provider.mjs +61 -0
- package/esm2020/providers/scan.form.mjs +386 -0
- package/esm2020/providers/scan.provider.mjs +490 -0
- package/esm2020/providers/translation.provider.mjs +50 -0
- package/esm2020/providers/webrtc.provider.mjs +58 -0
- package/esm2020/public-api.mjs +22 -4
- package/fesm2015/ngx-scandoc.mjs +4178 -32
- package/fesm2015/ngx-scandoc.mjs.map +1 -1
- package/fesm2020/ngx-scandoc.mjs +4154 -32
- package/fesm2020/ngx-scandoc.mjs.map +1 -1
- package/forms/form.module.d.ts +18 -0
- package/forms/types/avatar.type.d.ts +14 -0
- package/forms/types/profile.image.type.d.ts +14 -0
- package/forms/types/title.type.d.ts +12 -0
- package/lib/ngx-scandoc.module.d.ts +20 -2
- package/package.json +6 -2
- package/providers/auth.provider.d.ts +21 -0
- package/providers/interceptor.provider.d.ts +13 -0
- package/providers/scan.form.d.ts +13 -0
- package/providers/scan.provider.d.ts +239 -0
- package/providers/translation.provider.d.ts +9 -0
- package/providers/webrtc.provider.d.ts +11 -0
- package/public-api.d.ts +21 -3
- package/esm2020/lib/ngx-scandoc.component.mjs +0 -22
- package/esm2020/lib/ngx-scandoc.service.mjs +0 -14
- package/lib/ngx-scandoc.component.d.ts +0 -8
- package/lib/ngx-scandoc.service.d.ts +0 -6
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
import { Component, ViewChild, EventEmitter, Output, HostListener, ChangeDetectionStrategy, Input, } from '@angular/core';
|
|
2
|
+
import { Subject, Observable, of } from 'rxjs';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
import { FormGroup } from '@angular/forms';
|
|
5
|
+
import { switchMap } from 'rxjs/operators';
|
|
6
|
+
import { WebcamUtil } from '../../../core/components/webcam/util/webcam.util';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "../../../providers/scan.provider";
|
|
9
|
+
import * as i2 from "../../../dialogs/dialogs.core.provider";
|
|
10
|
+
import * as i3 from "../../../providers/scan.form";
|
|
11
|
+
import * as i4 from "@ngx-translate/core";
|
|
12
|
+
import * as i5 from "../../../providers/auth.provider";
|
|
13
|
+
import * as i6 from "@angular/forms";
|
|
14
|
+
import * as i7 from "@angular/common";
|
|
15
|
+
import * as i8 from "@ngx-formly/core";
|
|
16
|
+
import * as i9 from "@angular/material/form-field";
|
|
17
|
+
import * as i10 from "@angular/material/select";
|
|
18
|
+
import * as i11 from "@angular/material/core";
|
|
19
|
+
import * as i12 from "@angular/material/card";
|
|
20
|
+
import * as i13 from "@angular/material/icon";
|
|
21
|
+
import * as i14 from "@angular/material/button";
|
|
22
|
+
import * as i15 from "@angular/material/progress-bar";
|
|
23
|
+
import * as i16 from "../../../core/components/webcam/webcam/webcam.component";
|
|
24
|
+
import * as i17 from "@angular/flex-layout";
|
|
25
|
+
import * as i18 from "@angular/flex-layout/extended";
|
|
26
|
+
export class ScanProfileComponent {
|
|
27
|
+
constructor(cd, scanProvider, dialogs, formProvider, zone, translate, auth // private api: ServerProvider
|
|
28
|
+
) {
|
|
29
|
+
this.cd = cd;
|
|
30
|
+
this.scanProvider = scanProvider;
|
|
31
|
+
this.dialogs = dialogs;
|
|
32
|
+
this.formProvider = formProvider;
|
|
33
|
+
this.zone = zone;
|
|
34
|
+
this.translate = translate;
|
|
35
|
+
this.auth = auth;
|
|
36
|
+
this.scanBlastData = [
|
|
37
|
+
{
|
|
38
|
+
title: 'pms.dialogs.components.scanProfile.front',
|
|
39
|
+
description: 'pms.dialogs.components.scanProfile.frontDescription',
|
|
40
|
+
side: 'FRONT',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: 'pms.dialogs.components.scanProfile.back',
|
|
44
|
+
description: 'pms.dialogs.components.scanProfile.backDescription',
|
|
45
|
+
disabled: true,
|
|
46
|
+
side: 'BACK',
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
this.type = 'desktop';
|
|
50
|
+
this.actions = new EventEmitter();
|
|
51
|
+
this.mediaDevices = [];
|
|
52
|
+
this.videoOptions = {
|
|
53
|
+
width: 1920,
|
|
54
|
+
height: 1080,
|
|
55
|
+
facingMode: 'environment',
|
|
56
|
+
};
|
|
57
|
+
this.startTime = 0;
|
|
58
|
+
this.isDebug = false;
|
|
59
|
+
this.multipleWebcamsAvailable = false;
|
|
60
|
+
this.scanInProgress = false;
|
|
61
|
+
// webcam snapshot trigger
|
|
62
|
+
this.documentTypeSelected = false;
|
|
63
|
+
this.preview = null;
|
|
64
|
+
this.errorCode = '1000';
|
|
65
|
+
this.displayInfo = 'Position document inside rectange and hold steady.';
|
|
66
|
+
this.allowCameraSwitch = true;
|
|
67
|
+
this.verificationErrorSent = false;
|
|
68
|
+
this.error = false;
|
|
69
|
+
this.cameraReady = false;
|
|
70
|
+
this.scaning = false;
|
|
71
|
+
this.imageHandler = new Subject();
|
|
72
|
+
this.logData = {
|
|
73
|
+
AcceptTermsAndConditions: true,
|
|
74
|
+
Request: null,
|
|
75
|
+
Response: null,
|
|
76
|
+
ExpectedOutput: null,
|
|
77
|
+
};
|
|
78
|
+
this.scanDatas = [];
|
|
79
|
+
this.idScan = null;
|
|
80
|
+
this.validation = false;
|
|
81
|
+
this.scannedImages = [];
|
|
82
|
+
this.scanDelay = 0;
|
|
83
|
+
this.trigger = new Subject();
|
|
84
|
+
// switch to next / previous / specific webcam; true/false: forward/backwards, string: deviceId
|
|
85
|
+
this.nextWebcam = new Subject();
|
|
86
|
+
this.imageVerified = false;
|
|
87
|
+
this.form = new FormGroup({});
|
|
88
|
+
this.scanImageTimestamps = {
|
|
89
|
+
time: 0,
|
|
90
|
+
load: 0,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
onResize() {
|
|
94
|
+
if (this.wraper) {
|
|
95
|
+
this.width = this.wraper.nativeElement.clientWidth;
|
|
96
|
+
this.height = this.wraper.nativeElement.clientHeight;
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
const video = this.wraper?.nativeElement.querySelector('video');
|
|
99
|
+
if (video) {
|
|
100
|
+
// console.log(video.clientWidth, video.clientHeight);
|
|
101
|
+
this.videoWidth = video.clientWidth;
|
|
102
|
+
this.videoHeight = video.clientHeight;
|
|
103
|
+
}
|
|
104
|
+
this.cd.detectChanges();
|
|
105
|
+
}, 100);
|
|
106
|
+
this.cd.detectChanges();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
resetLogData() {
|
|
110
|
+
this.logData = {
|
|
111
|
+
Request: null,
|
|
112
|
+
Response: null,
|
|
113
|
+
ExpectedOutput: null,
|
|
114
|
+
AcceptTermsAndConditions: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
ngOnDestroy() {
|
|
118
|
+
if (this.scanTimeout) {
|
|
119
|
+
clearTimeout(this.scanTimeout);
|
|
120
|
+
}
|
|
121
|
+
if (this.imageHandlerSubscription) {
|
|
122
|
+
this.imageHandlerSubscription.unsubscribe();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
init() {
|
|
126
|
+
this.auth.accesToken.subscribe();
|
|
127
|
+
this.resetLogData();
|
|
128
|
+
// this.result=true;
|
|
129
|
+
// this.result ={};
|
|
130
|
+
this.fields = this.formProvider.document();
|
|
131
|
+
WebcamUtil.getAvailableVideoInputs().subscribe((mediaDevices) => {
|
|
132
|
+
console.log('[DEVICES]', mediaDevices.map((d) => d.label));
|
|
133
|
+
this.mediaDevices = mediaDevices;
|
|
134
|
+
this.multipleWebcamsAvailable = mediaDevices && mediaDevices.length > 1;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
scan() {
|
|
138
|
+
// this.triggerSnapshot();
|
|
139
|
+
// this.scanDatas[0] = true;
|
|
140
|
+
// if (this.scanTimeout) {
|
|
141
|
+
// clearTimeout(this.scanTimeout);
|
|
142
|
+
// }
|
|
143
|
+
// this.scanTimeout = setTimeout(() => {
|
|
144
|
+
// this.scan();
|
|
145
|
+
// }, 1);
|
|
146
|
+
}
|
|
147
|
+
DataUrlFromImage() { }
|
|
148
|
+
handleImage(webcamImage) {
|
|
149
|
+
// console.log('[received webcam image]', webcamImage);
|
|
150
|
+
this.zone.runOutsideAngular(() => {
|
|
151
|
+
const consoleBackground = "font-size:300px;background-image: url('" +
|
|
152
|
+
webcamImage.imageResized +
|
|
153
|
+
"');background-size: contain; background-repeat: no-repeat;";
|
|
154
|
+
// console.log('%c ', consoleBackground);
|
|
155
|
+
const time = new Date().getTime();
|
|
156
|
+
if (this.scanImageTimestamps.load > 0) {
|
|
157
|
+
const { load } = this.scanImageTimestamps;
|
|
158
|
+
const diff = time - load;
|
|
159
|
+
// console.log('time:', diff);
|
|
160
|
+
this.scanDelay = diff;
|
|
161
|
+
}
|
|
162
|
+
this.scanImageTimestamps.load = time;
|
|
163
|
+
if (webcamImage.imageData) {
|
|
164
|
+
this.scannedImages.push(webcamImage);
|
|
165
|
+
}
|
|
166
|
+
this.cd.detectChanges();
|
|
167
|
+
if (this.scannedImages.length > 4 && !this.validation) {
|
|
168
|
+
console.timeEnd('scan');
|
|
169
|
+
console.time('scan');
|
|
170
|
+
// get last 10
|
|
171
|
+
console.log('CAPTURED:', this.scannedImages.length);
|
|
172
|
+
const images = this.scannedImages.slice(-5);
|
|
173
|
+
// set images to 0
|
|
174
|
+
this.scannedImages = [];
|
|
175
|
+
const imagesArray = images.map((m) => m.imageResized.split(',')[1]);
|
|
176
|
+
this.validation = true;
|
|
177
|
+
this.handleBurstData(imagesArray, images);
|
|
178
|
+
// this.scanProvider.burst(imagesArray).subscribe((resp: any) => {
|
|
179
|
+
// // console.clear()
|
|
180
|
+
// console.log([resp.Info]);
|
|
181
|
+
// this.validation = false;
|
|
182
|
+
// this.displayInfo = resp.Info;
|
|
183
|
+
// if (resp.Validated) {
|
|
184
|
+
// if (this.scanTimeout) {
|
|
185
|
+
// clearTimeout(this.scanTimeout);
|
|
186
|
+
// }
|
|
187
|
+
// this.webcamImage = images[resp.Index];
|
|
188
|
+
// // this.preview = this.webcamImage.imageAsDataUrl;
|
|
189
|
+
// this.cd.detectChanges();
|
|
190
|
+
// const { DocType, Series, Side } = resp;
|
|
191
|
+
// // For ID ask for other side
|
|
192
|
+
// if (DocType === 'ID') {
|
|
193
|
+
// if (Side === 'FRONT') {
|
|
194
|
+
// this.scanBlastData[0].image = this.webcamImage;
|
|
195
|
+
// } else {
|
|
196
|
+
// this.scanBlastData[1].image = this.webcamImage;
|
|
197
|
+
// }
|
|
198
|
+
// if (this.scanBlastData[0].image && this.scanBlastData[1].image) {
|
|
199
|
+
// console.warn('UPLOAD');
|
|
200
|
+
// this.scanBlastFinish();
|
|
201
|
+
// } else {
|
|
202
|
+
// const num = Side === 'FRONT' ? 1 : 0;
|
|
203
|
+
// this.singleScan(this.scanBlastData[num]);
|
|
204
|
+
// this.scan();
|
|
205
|
+
// this.idScan = this.scanBlastData[num].side;
|
|
206
|
+
// console.log('ID SIDE', this.idScan);
|
|
207
|
+
// this.displayInfo = 'Please turn the document over!';
|
|
208
|
+
// }
|
|
209
|
+
// } else {
|
|
210
|
+
// this.scanBlastData[0].image = this.webcamImage;
|
|
211
|
+
// console.warn('UPLOAD');
|
|
212
|
+
// this.scanBlastFinish();
|
|
213
|
+
// }
|
|
214
|
+
// console.log(DocType, Series, Side);
|
|
215
|
+
// this.scannedImages = [];
|
|
216
|
+
// }
|
|
217
|
+
// });
|
|
218
|
+
}
|
|
219
|
+
if (this.cameraReady) {
|
|
220
|
+
// console.log('delay', this.scanDelay);
|
|
221
|
+
//console.log('timeD', new Date().getTime());
|
|
222
|
+
this.trigger.next(new Date().getTime());
|
|
223
|
+
// if (this.scanDelay < 100) {
|
|
224
|
+
// const diff = 100 - this.scanDelay;
|
|
225
|
+
// console.log(diff);
|
|
226
|
+
// const time2 = new Date().getTime();
|
|
227
|
+
// // const sub = of(1)
|
|
228
|
+
// // .pipe(delay(diff))
|
|
229
|
+
// // .subscribe((resp) => {
|
|
230
|
+
// // console.log(new Date().getTime()-time);
|
|
231
|
+
// // this.trigger.next();
|
|
232
|
+
// // sub.unsubscribe();
|
|
233
|
+
// // });
|
|
234
|
+
// const timeout = setTimeout(() => {
|
|
235
|
+
// console.log('TO', new Date().getTime() - time2);
|
|
236
|
+
// this.trigger.next();
|
|
237
|
+
// clearTimeout(timeout);
|
|
238
|
+
// }, diff);
|
|
239
|
+
// } else {
|
|
240
|
+
// this.trigger.next();
|
|
241
|
+
// }
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
// this.scanImageTimestamps = {
|
|
245
|
+
// time: new Date().getTime(),
|
|
246
|
+
// load:
|
|
247
|
+
// };
|
|
248
|
+
// this.webcamImage = webcamImage;
|
|
249
|
+
// this.preview = webcamImage.imageAsDataUrl;
|
|
250
|
+
// this.cd.detectChanges();
|
|
251
|
+
}
|
|
252
|
+
handleBurstData(imagesArray, images, type = 'plain') {
|
|
253
|
+
this.scanProvider.burst(imagesArray).subscribe((resp) => {
|
|
254
|
+
this.displayInfo = resp.Info;
|
|
255
|
+
console.timeEnd('validationPOST');
|
|
256
|
+
console.log('AnalysisTime', resp.AnalysisTime);
|
|
257
|
+
const { DocType, Series, Side, InfoCode } = resp;
|
|
258
|
+
// if (InfoCode === '1006' && this.idScan) {
|
|
259
|
+
// this.handleLongValidationError(image);
|
|
260
|
+
// }
|
|
261
|
+
if (resp.Validated) {
|
|
262
|
+
console.log('[SCANNED INDEX]', resp.Index);
|
|
263
|
+
const selectedImage = images[resp.Index];
|
|
264
|
+
// this.preview = this.webcamImage.imageAsDataUrl;
|
|
265
|
+
this.cd.detectChanges();
|
|
266
|
+
let image = selectedImage;
|
|
267
|
+
if (type == 'worker') {
|
|
268
|
+
const dataUrl = this.handleBitmapImage(selectedImage.bitmap);
|
|
269
|
+
image = { dataUrl };
|
|
270
|
+
}
|
|
271
|
+
if (InfoCode === '1007') {
|
|
272
|
+
// For ID ask for other side
|
|
273
|
+
if (Side === 'FRONT') {
|
|
274
|
+
this.scanBlastData[0].image = image;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
this.scanBlastData[1].image = image;
|
|
278
|
+
}
|
|
279
|
+
if (this.scanBlastData[0].image && this.scanBlastData[1].image) {
|
|
280
|
+
console.warn('UPLOAD');
|
|
281
|
+
if (type == 'worker') {
|
|
282
|
+
this.imageHandler.next({ type: 'stop' });
|
|
283
|
+
}
|
|
284
|
+
this.scanBlastFinish();
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
const num = Side === 'FRONT' ? 1 : 0;
|
|
288
|
+
this.singleScan(this.scanBlastData[num]);
|
|
289
|
+
this.scan();
|
|
290
|
+
this.idScan = this.scanBlastData[num].side;
|
|
291
|
+
console.log('ID SIDE', this.idScan);
|
|
292
|
+
this.displayInfo = 'Please turn the document over!';
|
|
293
|
+
this.validation = false;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
this.scanBlastData[0].image = image;
|
|
298
|
+
console.warn('UPLOAD');
|
|
299
|
+
if (type == 'worker') {
|
|
300
|
+
this.imageHandler.next({ type: 'stop' });
|
|
301
|
+
}
|
|
302
|
+
this.scanBlastFinish();
|
|
303
|
+
}
|
|
304
|
+
this.scannedImages = [];
|
|
305
|
+
// this.scanBlastData[0].image = selectedImage;
|
|
306
|
+
//this.scanBlastFinish();
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
this.validation = false;
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
handleInitError(error) {
|
|
314
|
+
console.log(error);
|
|
315
|
+
}
|
|
316
|
+
get scanBlastCanUpload() {
|
|
317
|
+
return this.scanBlastData[0].image ? true : false;
|
|
318
|
+
}
|
|
319
|
+
cameraWasSwitched(deviceId) {
|
|
320
|
+
console.log('[active device]', deviceId);
|
|
321
|
+
this.deviceId = deviceId;
|
|
322
|
+
this.cameraReady = true;
|
|
323
|
+
this.defaultDevice = deviceId;
|
|
324
|
+
setTimeout(() => {
|
|
325
|
+
this.onResize();
|
|
326
|
+
this.scan();
|
|
327
|
+
}, 300);
|
|
328
|
+
}
|
|
329
|
+
get nextWebcamObservable() {
|
|
330
|
+
return this.nextWebcam.asObservable();
|
|
331
|
+
}
|
|
332
|
+
handleLongValidationError(img) {
|
|
333
|
+
// save current image after 10sec
|
|
334
|
+
const diff = (Date.now() - this.startTime) / 1000;
|
|
335
|
+
if (diff > 15 && !this.verificationErrorSent) {
|
|
336
|
+
this.verificationErrorSent = true;
|
|
337
|
+
const dataUrl = this.handleBitmapImage(img.bitmap);
|
|
338
|
+
console.warn('SENT');
|
|
339
|
+
this.displayInfo = 'Cant detect document!';
|
|
340
|
+
this.logData.Request = this.scanProvider
|
|
341
|
+
.sendLog({
|
|
342
|
+
AcceptTermsAndConditions: true,
|
|
343
|
+
ExpectedOutput: {},
|
|
344
|
+
Request: {
|
|
345
|
+
verification: dataUrl.split(',')[1],
|
|
346
|
+
},
|
|
347
|
+
Response: {
|
|
348
|
+
TransactionID: uuidv4(),
|
|
349
|
+
},
|
|
350
|
+
})
|
|
351
|
+
.subscribe();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
ngAfterViewInit() {
|
|
355
|
+
this.cd.detectChanges();
|
|
356
|
+
this.autoScan();
|
|
357
|
+
this.imageHandlerSubscription = this.imageHandler.subscribe((webcamImage) => {
|
|
358
|
+
// return;
|
|
359
|
+
if (this.startTime === 0) {
|
|
360
|
+
this.startTime = Date.now();
|
|
361
|
+
}
|
|
362
|
+
this.zone.runOutsideAngular(() => {
|
|
363
|
+
if (webcamImage.base64) {
|
|
364
|
+
const time = new Date().getTime();
|
|
365
|
+
if (this.scanImageTimestamps.load > 0) {
|
|
366
|
+
const { load } = this.scanImageTimestamps;
|
|
367
|
+
const diff = time - load;
|
|
368
|
+
console.warn('TIME', diff);
|
|
369
|
+
this.scanDelay = diff;
|
|
370
|
+
}
|
|
371
|
+
this.scanImageTimestamps.load = time;
|
|
372
|
+
this.scannedImages.push(webcamImage);
|
|
373
|
+
this.handleLongValidationError(webcamImage);
|
|
374
|
+
}
|
|
375
|
+
// this.cd.detectChanges();
|
|
376
|
+
if (this.scannedImages.length > 4 && !this.validation) {
|
|
377
|
+
// get last 10
|
|
378
|
+
console.timeEnd('validationTOTAL_UI');
|
|
379
|
+
console.time('validationTOTAL_UI');
|
|
380
|
+
const images = this.scannedImages.slice(-5);
|
|
381
|
+
// set images to 0
|
|
382
|
+
this.scannedImages = [];
|
|
383
|
+
console.log(images);
|
|
384
|
+
const imagesArray = images.map((m) => m.base64.split(',')[1]);
|
|
385
|
+
this.validation = true;
|
|
386
|
+
this.handleBurstData(imagesArray, images, 'worker');
|
|
387
|
+
console.time('validationPOST');
|
|
388
|
+
}
|
|
389
|
+
this.cd.detectChanges();
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
handleBitmapImage(bitmap) {
|
|
394
|
+
const { width, height } = bitmap;
|
|
395
|
+
const offscreenSmall = document.createElement('canvas');
|
|
396
|
+
offscreenSmall.width = width;
|
|
397
|
+
offscreenSmall.height = height;
|
|
398
|
+
const ctx = offscreenSmall.getContext('bitmaprenderer');
|
|
399
|
+
if (ctx) {
|
|
400
|
+
ctx.imageSmoothingEnabled = false;
|
|
401
|
+
ctx.transferFromImageBitmap(bitmap);
|
|
402
|
+
bitmap.close();
|
|
403
|
+
const data = ctx.canvas.toDataURL('image/jpeg');
|
|
404
|
+
return data;
|
|
405
|
+
}
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
autoScan() {
|
|
409
|
+
const side = this.scanBlastData[0];
|
|
410
|
+
this.idScan = null;
|
|
411
|
+
this.singleScan(side);
|
|
412
|
+
}
|
|
413
|
+
selectCamera(event) {
|
|
414
|
+
this.cameraReady = false;
|
|
415
|
+
this.nextWebcam.next(event.value);
|
|
416
|
+
this.scanInProgress = false;
|
|
417
|
+
}
|
|
418
|
+
close() {
|
|
419
|
+
this.dialogRef?.close();
|
|
420
|
+
}
|
|
421
|
+
singleScan(side) {
|
|
422
|
+
this.scanType = side.side;
|
|
423
|
+
this.preview = null;
|
|
424
|
+
this.selectedSide = side;
|
|
425
|
+
this.selectedSide.image = null;
|
|
426
|
+
this.documentTypeSelected = true;
|
|
427
|
+
this.scanBlastData[1].disabled = false;
|
|
428
|
+
this.cd.detectChanges();
|
|
429
|
+
setTimeout(() => {
|
|
430
|
+
this.onResize();
|
|
431
|
+
}, 10);
|
|
432
|
+
}
|
|
433
|
+
getBase64(file) {
|
|
434
|
+
return new Observable((observer) => {
|
|
435
|
+
const reader = new FileReader();
|
|
436
|
+
reader.readAsDataURL(file);
|
|
437
|
+
reader.onload = () => {
|
|
438
|
+
observer.next(reader.result);
|
|
439
|
+
};
|
|
440
|
+
reader.onerror = (error) => {
|
|
441
|
+
observer.error(error);
|
|
442
|
+
};
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
handleFileInput(target, event, side) {
|
|
446
|
+
const files = target.files;
|
|
447
|
+
this.selectedSide = side;
|
|
448
|
+
console.log(files);
|
|
449
|
+
const file = files.item(0);
|
|
450
|
+
this.resolutionLimit(file)
|
|
451
|
+
.pipe(switchMap((valid) => {
|
|
452
|
+
return valid ? this.getBase64(file) : of(false);
|
|
453
|
+
}))
|
|
454
|
+
.subscribe((imageAsDataUrl) => {
|
|
455
|
+
// console.log(imageAsDataUrl);
|
|
456
|
+
event.target.value = null;
|
|
457
|
+
if (!imageAsDataUrl) {
|
|
458
|
+
this.dialogs.alert('core.page.error', this.translate.instant('pms.dialogs.components.scanProfile.minResolution'));
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
side.image = {
|
|
462
|
+
imageAsDataUrl,
|
|
463
|
+
};
|
|
464
|
+
if (this.selectedSide.side === 'FRONT') {
|
|
465
|
+
this.scanBlastData[1].disabled = false;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
this.cd.detectChanges();
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
rotateBase64Image(base64data) {
|
|
472
|
+
return new Observable((observer) => {
|
|
473
|
+
const canvas = document.createElement('canvas');
|
|
474
|
+
const ctx = canvas.getContext('2d');
|
|
475
|
+
var image = new Image();
|
|
476
|
+
image.src = base64data;
|
|
477
|
+
image.onload = () => {
|
|
478
|
+
console.log(canvas);
|
|
479
|
+
canvas.width = image.height;
|
|
480
|
+
canvas.height = image.width;
|
|
481
|
+
if (ctx) {
|
|
482
|
+
ctx.rotate((90 * Math.PI) / 180);
|
|
483
|
+
ctx.translate(0, -canvas.width);
|
|
484
|
+
ctx.drawImage(image, 0, 0);
|
|
485
|
+
observer.next(canvas.toDataURL());
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
observer.error({ type: 'generic error' });
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
image.onerror = (e) => {
|
|
492
|
+
observer.error(e);
|
|
493
|
+
};
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
sendMobile() {
|
|
497
|
+
this.dialogs.scanMobile({ id: 1 });
|
|
498
|
+
}
|
|
499
|
+
singleScanRotate(side) {
|
|
500
|
+
console.log(side);
|
|
501
|
+
this.rotateBase64Image(side.image.imageAsDataUrl).subscribe((data) => {
|
|
502
|
+
side.image = { imageAsDataUrl: data };
|
|
503
|
+
this.cd.detectChanges();
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
singleScanRemove(side) {
|
|
507
|
+
side.image = null;
|
|
508
|
+
if (side.side === 'FRONT') {
|
|
509
|
+
this.scanBlastData[1].disabled = true;
|
|
510
|
+
}
|
|
511
|
+
this.cd.detectChanges();
|
|
512
|
+
}
|
|
513
|
+
resolutionLimit(file) {
|
|
514
|
+
const minWidth = 1280;
|
|
515
|
+
const minHeight = 720;
|
|
516
|
+
return new Observable((observer) => {
|
|
517
|
+
const img = new Image();
|
|
518
|
+
img.src = window.URL.createObjectURL(file);
|
|
519
|
+
img.onload = () => {
|
|
520
|
+
const width = img.naturalWidth;
|
|
521
|
+
const height = img.naturalHeight;
|
|
522
|
+
let valid = false;
|
|
523
|
+
if (width > height) {
|
|
524
|
+
valid = width >= minWidth && height >= minHeight;
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
valid = width >= minHeight && height >= minWidth;
|
|
528
|
+
}
|
|
529
|
+
observer.next(valid);
|
|
530
|
+
};
|
|
531
|
+
img.onerror = (error) => {
|
|
532
|
+
observer.error(error);
|
|
533
|
+
};
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
getImgBase64(num) {
|
|
537
|
+
console.log('GET 64');
|
|
538
|
+
return this.scanBlastData[num].image.dataUrl.split(',')[1];
|
|
539
|
+
}
|
|
540
|
+
scanBlastFinish() {
|
|
541
|
+
console.time('upload');
|
|
542
|
+
if (this.type === 'mobile') {
|
|
543
|
+
this.actions.emit({ data: this.scanBlastData });
|
|
544
|
+
this.retake();
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
this.idScan = null;
|
|
548
|
+
// const loading = this.dialogs.loading();
|
|
549
|
+
this.scaning = true;
|
|
550
|
+
this.cd.detectChanges();
|
|
551
|
+
console.time('payload');
|
|
552
|
+
const payload = {
|
|
553
|
+
AcceptTermsAndConditions: true,
|
|
554
|
+
DataFields: {
|
|
555
|
+
FrontImageType: 'base64',
|
|
556
|
+
FrontImageCropped: false,
|
|
557
|
+
BackImageType: 'base64',
|
|
558
|
+
BackImageCropped: false,
|
|
559
|
+
FrontImage: this.getImgBase64(0),
|
|
560
|
+
BackImage: this.scanBlastData[1].image ? this.getImgBase64(1) : null,
|
|
561
|
+
},
|
|
562
|
+
Settings: {
|
|
563
|
+
ShouldValidate: true,
|
|
564
|
+
ShouldReturnDocumentImage: true,
|
|
565
|
+
ShouldReturnFaceIfDetected: true,
|
|
566
|
+
SkipImageSizeCheck: true,
|
|
567
|
+
CanStoreImages: this.scanProvider.canStoreImages,
|
|
568
|
+
},
|
|
569
|
+
// CallBackUrl: 'http://demo:5000/report/extracted/',
|
|
570
|
+
};
|
|
571
|
+
if (!this.scanBlastData[1].image) {
|
|
572
|
+
payload.Settings.IgnoreBackImage = true;
|
|
573
|
+
}
|
|
574
|
+
this.logData.Request = JSON.parse(JSON.stringify(payload));
|
|
575
|
+
console.timeEnd('payload');
|
|
576
|
+
this.scanProvider
|
|
577
|
+
.blastPost(payload)
|
|
578
|
+
.subscribe((data) => {
|
|
579
|
+
//console.log(data);
|
|
580
|
+
const results = data.Data;
|
|
581
|
+
console.timeEnd('upload');
|
|
582
|
+
console.time('parse');
|
|
583
|
+
// data.InfoCode = '1001';
|
|
584
|
+
this.logData.Response = JSON.parse(JSON.stringify(data));
|
|
585
|
+
//loading.close();
|
|
586
|
+
this.documentTypeSelected = true;
|
|
587
|
+
this.scaning = false;
|
|
588
|
+
if (data.InfoCode === '1001') {
|
|
589
|
+
this.error = true;
|
|
590
|
+
console.log('[ERROR] 1001');
|
|
591
|
+
this.errorCode = '1001';
|
|
592
|
+
// this.scanSide = 0;
|
|
593
|
+
this.preview = true;
|
|
594
|
+
this.cd.detectChanges();
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
if (data.InfoCode === '1002') {
|
|
598
|
+
this.error = true;
|
|
599
|
+
console.log('[ERROR] 1002');
|
|
600
|
+
this.errorCode = '1002';
|
|
601
|
+
// this.scanSide = 0;
|
|
602
|
+
this.preview = true;
|
|
603
|
+
this.cd.detectChanges();
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
if (results && data.Metadata.length > 0 && data.InfoCode === '1000') {
|
|
607
|
+
console.log('Extraction time', data.AnalysisTime);
|
|
608
|
+
this.zone.run(() => {
|
|
609
|
+
if (data.ImageData?.Documents) {
|
|
610
|
+
const { Documents } = data.ImageData;
|
|
611
|
+
this.images = Documents.map((image, i) => {
|
|
612
|
+
return { data: 'data:image/jpeg;base64,' + Documents[i] };
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
this.result = this.scanProvider.parseBlast(results);
|
|
616
|
+
console.log('RES', this.result);
|
|
617
|
+
this.cd.detectChanges();
|
|
618
|
+
this.model = this.result.model;
|
|
619
|
+
if (data.ImageData?.FaceImage) {
|
|
620
|
+
this.model._avatar =
|
|
621
|
+
'data:image/jpeg;base64,' + data.ImageData?.FaceImage;
|
|
622
|
+
}
|
|
623
|
+
console.log('MODEL', this.model);
|
|
624
|
+
this.cd.detectChanges();
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
console.log('ERROR');
|
|
629
|
+
// this.scanSide = 0;
|
|
630
|
+
this.error = true;
|
|
631
|
+
this.preview = true;
|
|
632
|
+
this.cd.detectChanges();
|
|
633
|
+
// this.documentTypeSelected = false;
|
|
634
|
+
// this.retry();
|
|
635
|
+
}
|
|
636
|
+
this.cd.detectChanges();
|
|
637
|
+
console.timeEnd('parse');
|
|
638
|
+
}, (err) => {
|
|
639
|
+
// loading.close();
|
|
640
|
+
// this.scanSide = 0;
|
|
641
|
+
this.error = true;
|
|
642
|
+
this.preview = true;
|
|
643
|
+
this.documentTypeSelected = true;
|
|
644
|
+
this.scaning = false;
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
cameraOff(ev) {
|
|
648
|
+
this.cameraReady = false;
|
|
649
|
+
this.cd.detectChanges();
|
|
650
|
+
}
|
|
651
|
+
continue() {
|
|
652
|
+
this.documentTypeSelected = false;
|
|
653
|
+
setTimeout(() => {
|
|
654
|
+
this.selectedSide.image = this.webcamImage;
|
|
655
|
+
if (this.selectedSide.side === 'FRONT') {
|
|
656
|
+
this.scanBlastData[1].disabled = false;
|
|
657
|
+
}
|
|
658
|
+
this.cd.detectChanges();
|
|
659
|
+
}, 200);
|
|
660
|
+
}
|
|
661
|
+
retry() {
|
|
662
|
+
this.preview = false;
|
|
663
|
+
this.validation = false;
|
|
664
|
+
this.errorCode = '1000';
|
|
665
|
+
this.result = false;
|
|
666
|
+
if (this.error) {
|
|
667
|
+
this.documentTypeSelected = false;
|
|
668
|
+
this.scanBlastData.forEach((element) => {
|
|
669
|
+
element.image = null;
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
this.error = false;
|
|
673
|
+
this.autoScan();
|
|
674
|
+
this.cd.detectChanges();
|
|
675
|
+
}
|
|
676
|
+
triggerSnapshot() {
|
|
677
|
+
this.trigger.next(0);
|
|
678
|
+
}
|
|
679
|
+
retake() {
|
|
680
|
+
this.validation = false;
|
|
681
|
+
this.preview = false;
|
|
682
|
+
this.error = false;
|
|
683
|
+
this.result = false;
|
|
684
|
+
this.scanSide = 0;
|
|
685
|
+
this.imageVerified = false;
|
|
686
|
+
this.scanDatas = [];
|
|
687
|
+
this.scaning = false;
|
|
688
|
+
this.images = [];
|
|
689
|
+
this.scanInProgress = false;
|
|
690
|
+
this.documentTypeSelected = false;
|
|
691
|
+
this.scanBlastData.forEach((m) => {
|
|
692
|
+
m.image = null;
|
|
693
|
+
});
|
|
694
|
+
this.autoScan();
|
|
695
|
+
this.cd.detectChanges();
|
|
696
|
+
}
|
|
697
|
+
cancel() {
|
|
698
|
+
this.documentTypeSelected = false;
|
|
699
|
+
}
|
|
700
|
+
use() {
|
|
701
|
+
// save images??
|
|
702
|
+
if (this.scanProvider.canStoreImages) {
|
|
703
|
+
this.logData.ExpectedOutput = JSON.parse(JSON.stringify(this.model));
|
|
704
|
+
if (this.logData.ExpectedOutput?._avatar) {
|
|
705
|
+
delete this.logData.ExpectedOutput._avatar;
|
|
706
|
+
}
|
|
707
|
+
this.scanProvider.sendLog(this.logData).subscribe();
|
|
708
|
+
console.log(this.logData);
|
|
709
|
+
}
|
|
710
|
+
this.dialogRef?.close({
|
|
711
|
+
model: this.model,
|
|
712
|
+
images: this.images,
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
selfie() {
|
|
716
|
+
this.dialogs
|
|
717
|
+
.scanSelfie({ avatar: this.model._avatar })
|
|
718
|
+
.afterClosed()
|
|
719
|
+
.subscribe((resp) => {
|
|
720
|
+
if (resp) {
|
|
721
|
+
console.log(resp);
|
|
722
|
+
if (this.scanProvider.enableVerification) {
|
|
723
|
+
this.imageVerified = true;
|
|
724
|
+
}
|
|
725
|
+
this.model._avatar = resp.imageAsDataUrl;
|
|
726
|
+
this.cd.detectChanges();
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
videoReady(event) {
|
|
731
|
+
this.cameraReady = event;
|
|
732
|
+
if (this.cameraReady && !this.scanInProgress) {
|
|
733
|
+
this.scanInProgress = true;
|
|
734
|
+
setTimeout(() => {
|
|
735
|
+
this.trigger.next(new Date().getTime());
|
|
736
|
+
}, 1000);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
ScanProfileComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ScanProfileComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.ScanProvider }, { token: i2.DialogsCoreProvider }, { token: i3.ScanFieldsProvider }, { token: i0.NgZone }, { token: i4.TranslateService }, { token: i5.AuthProvider }], target: i0.ɵɵFactoryTarget.Component });
|
|
741
|
+
ScanProfileComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: ScanProfileComponent, selector: "app-scan-profile", inputs: { type: "type" }, outputs: { actions: "actions" }, host: { listeners: { "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "wraper", first: true, predicate: ["wraper"], descendants: true }], ngImport: i0, template: "<!-- <div *ngIf=\"isDebug\" class=\"debug\">\n <ng-container *ngFor=\"let img of scannedImages; let index = index\">\n <div style=\"display: flex; flex-direction: column\">\n <img [src]=\"img.imageResized\" />\n {{ index }}\n </div>\n </ng-container>\n</div> -->\n\n<header class=\"page-header\">\n <div class=\"title\" ngClass.lt-sm=\"title-small\">Scan</div>\n\n <span fxFlex></span>\n\n <!-- <mat-slide-toggle style=\"margin:0px 20px\" [(ngModel)]=\"isDebug\"\n >Debug</mat-slide-toggle\n > -->\n\n <ng-container\n *ngIf=\"\n documentTypeSelected &&\n !result &&\n !error &&\n multipleWebcamsAvailable &&\n !preview\n \"\n >\n <div class=\"separator\"></div>\n <div style=\"padding: 0px 16px\">\n <div fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <mat-form-field\n style=\"font-size: 14px; width: 200px; margin-top: 8px\"\n class=\"w-100 mr-16 mt-8\"\n >\n <mat-label> Camera </mat-label>\n <mat-select\n (selectionChange)=\"selectCamera($event)\"\n [(ngModel)]=\"deviceId\"\n >\n <mat-option\n *ngFor=\"let device of mediaDevices\"\n [value]=\"device.deviceId\"\n >\n {{ device.label }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"type === 'desktop'\">\n <!-- <div class=\"separator\"></div>\n <button mat-button (click)=\"sendMobile()\">\n <mat-icon>tablet_mac</mat-icon>\n </button> -->\n\n <div class=\"separator\"></div>\n\n <button mat-button (click)=\"close()\">\n <mat-icon>close</mat-icon>\n </button>\n </ng-container>\n</header>\n\n<div *ngIf=\"result\" fxFlex fxLayout=\"column\">\n <!-- <div *ngIf=\"result\" fxFlex fxLayout=\"column\"> -->\n <div\n fxFlex\n #wraper\n class=\"wraper\"\n fxLayout=\"row\"\n style=\"overflow: auto\"\n protelPerfectScrollbar\n class=\"pt-8 pr-8\"\n fxLayout.lt-md=\"column\"\n >\n <div fxFlex class=\"\">\n <div fxFlex>\n <mat-card style=\"margin: 4px; padding: 4px 16px\">\n <h3>Avatar</h3>\n <div\n style=\"display: flex; flex-direction: row; align-items: center\"\n class=\"selfieContainer\"\n >\n <div class=\"selfie\" style=\"width: 200px\">\n <img\n *ngIf=\"model?._avatar\"\n class=\"preview\"\n style=\"width: 120px; height: 120px; border-radius: 60px\"\n [src]=\"model._avatar\"\n />\n </div>\n <button\n [disabled]=\"imageVerified\"\n (click)=\"selfie()\"\n mat-raised-button\n >\n Take selfie\n </button>\n </div>\n </mat-card>\n\n <form\n fxLayout=\"row\"\n fxLayoutAlign=\"start center\"\n class=\"px-16 py-0 w-100-p\"\n [formGroup]=\"form\"\n >\n <formly-form\n ngClass.lt-md=\"mobile\"\n fxFlex\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n >\n </formly-form>\n </form>\n </div>\n </div>\n <div fxFlex class=\"pr-16 m-4\">\n <mat-card style=\"margin: 4px; padding-top: 2px\" class=\"images\">\n <h3>Images</h3>\n <ng-container *ngFor=\"let img of images\">\n <div fxLayout=\"column\">\n <ng-container *ngIf=\"img.side === 0\">\n <div class=\"title\">Front Side</div>\n </ng-container>\n <ng-container *ngIf=\"img.side === 1\">\n <div class=\"title\">Back Side</div>\n </ng-container>\n <img\n class=\"preview\"\n style=\"max-width: 460px; border-radius: 1rem\"\n [src]=\"img.data\"\n />\n </div>\n </ng-container>\n </mat-card>\n </div>\n </div>\n\n <div></div>\n\n <footer fxLayout=\"row\" class=\"p-8\">\n <div class=\"w-100-p\" fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <button fxFlex class=\"mr-8\" mat-raised-button (click)=\"retake()\">\n {{ \"pms.dialogs.components.scanProfile.reTake\" | translate }}\n </button>\n <button\n [disabled]=\"error || form.invalid\"\n fxFlex\n class=\"ml-8\"\n mat-raised-button\n (click)=\"use()\"\n >\n {{ \"pms.dialogs.components.scanProfile.useData\" | translate }}\n </button>\n </div>\n </footer>\n</div>\n\n<div\n style=\"position: relative\"\n *ngIf=\"!result && documentTypeSelected\"\n fxFlex\n fxLayout=\"column\"\n>\n <div fxFlex #wraper class=\"wraper\" fxLayout=\"row\">\n <div\n style=\"\n position: absolute;\n top: 0px;\n left: 0px;\n right: 0px;\n bottom: 0px;\n z-index: 20;\n background-color: whitesmoke;\n \"\n *ngIf=\"!cameraReady && !preview\"\n >\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n </div>\n\n <div *ngIf=\"!preview\" style=\"position: absolute; left: 0px\">\n DELAY:{{ scanDelay }}\n </div>\n\n <div\n *ngIf=\"scaning\"\n style=\"\n position: absolute;\n z-index: 200;\n width: 100%;\n height: 100%;\n top: 0px;\n left: 0px;\n \"\n fxlayout=\"row\"\n fxLayoutAlign=\"center center\"\n >\n <!-- <mat-progress-spinner\n mode=\"indeterminate\"\n color=\"accent\"\n [strokeWidth]=\"10\"\n ></mat-progress-spinner> -->\n </div>\n\n <ng-container *ngIf=\"!error\">\n <!-- <div\n class=\"rectangle\"\n [ngStyle]=\"{\n 'width.px': videoHeight * 0.75 * 1.588,\n 'height.px': videoHeight * 0.75\n }\"\n ></div>\n <svg\n *ngIf=\"videoWidth\"\n style=\"position: absolute; left: 0px; top: 0px\"\n width=\"0\"\n height=\"0\"\n >\n <defs>\n <clipPath id=\"myClip\">\n <rect\n stroke-width=\"6\"\n stroke-color=\"red\"\n [attr.x]=\"(videoWidth - videoHeight * 0.75 * 1.588) / 2\"\n [attr.y]=\"(videoHeight * 0.25) / 2\"\n [attr.width]=\"videoHeight * 0.75 * 1.588\"\n [attr.height]=\"videoHeight * 0.75\"\n rx=\"25\"\n />\n </clipPath>\n </defs>\n </svg> -->\n\n <app-webcam\n *ngIf=\"!preview && !scaning\"\n class=\"main\"\n [imageQuality]=\"1\"\n #webcam\n fxFlex\n type=\"document\"\n [trigger]=\"trigger\"\n [imageHandler]=\"imageHandler\"\n (imageCapture)=\"handleImage($event)\"\n [allowCameraSwitch]=\"allowCameraSwitch\"\n [videoOptions]=\"videoOptions\"\n [switchCamera]=\"nextWebcamObservable\"\n (cameraSwitched)=\"cameraWasSwitched($event)\"\n (initError)=\"handleInitError($event)\"\n [width]=\"width\"\n [height]=\"height\"\n (destroyed)=\"cameraOff($event)\"\n (videoReady)=\"videoReady($event)\"\n >\n </app-webcam>\n </ng-container>\n <div\n fxLayout=\"row\"\n fxFlex\n class=\"previewData\"\n *ngIf=\"preview\"\n style=\"z-index: 20; position: absolute; width: 100%; height: 100%\"\n >\n <div class=\"p-16 error\" *ngIf=\"error\">\n <div style=\"max-width: \">\n <div class=\"title\" fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <mat-icon>error_outline</mat-icon\n ><span class=\"ml-8\">{{\n \"pms.dialogs.components.scanProfile.unableToDetectId\" | translate\n }}</span>\n </div>\n\n <ng-container *ngIf=\"errorCode === '1001'\">\n <div>\n Could not classify the given object as a supported document.\n </div>\n </ng-container>\n <ng-container *ngIf=\"errorCode === '1002'\">\n <div>\n Something is wrong with extraction data. Please try again.\n </div>\n </ng-container>\n\n <ul *ngIf=\"errorCode === '1000'\">\n <li>\n {{\n \"pms.dialogs.components.scanProfile.placeIdCloseToDevice\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.ensureSufficientLight\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.holdDocumentSteady\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.makeSureAllEdgesOfTheIdAreVisible\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.makeSureThereAreNoGlareAndShadowsOnTheId\"\n | translate\n }}\n </li>\n </ul>\n </div>\n </div>\n\n <div\n class=\"scanPreview\"\n fxFlex\n fxLayout=\"column\"\n *ngIf=\"!error && !scaning\"\n >\n <!-- <div class=\"py-16\" style=\"font-size: 16px\">\n {{\n \"pms.dialogs.components.scanProfile.ensureAllTextsAreVisible\"\n | translate\n }}\n </div> -->\n <div\n fxFlex\n class=\"image\"\n [style.background-image]=\"'url(' + preview + ')'\"\n ></div>\n </div>\n </div>\n </div>\n\n <footer fxLayout=\"row\" style=\"height: 80px\" class=\"p-8\">\n <div class=\"displayInfo\" ngClass.lt-sm=\"mobile\" *ngIf=\"!preview && cameraReady\">\n {{ displayInfo }}\n </div>\n <div style=\"height: 26px\">\n <div\n style=\"text-align: center; font-size: 18px\"\n *ngIf=\"idScan && !preview && cameraReady\"\n >\n <ng-container *ngIf=\"idScan === 'BACK'\">\n Turn document and:\n {{ \"pms.dialogs.components.scanProfile.captureBack\" | translate }}\n </ng-container>\n <ng-container *ngIf=\"idScan === 'FRONT'\">\n Turn document and:\n {{ \"pms.dialogs.components.scanProfile.captureFront\" | translate }}\n </ng-container>\n </div>\n </div>\n\n <!-- <button\n [disabled]=\"!cameraReady\"\n class=\"w-100-p\"\n *ngIf=\"!preview\"\n mat-raised-button\n (click)=\"scan()\"\n >\n <ng-container>\n <ng-container *ngIf=\"scanType === 'FRONT'\">{{\n \"pms.dialogs.components.scanProfile.captureFront\" | translate\n }}</ng-container>\n <ng-container *ngIf=\"scanType === 'BACK'\">{{\n \"pms.dialogs.components.scanProfile.captureBack\" | translate\n }}</ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"scanSide === 1\">{{\n \"pms.dialogs.components.scanProfile.captureBackOfId\" | translate\n }}</ng-container>\n </button> -->\n\n <div\n class=\"w-100-p\"\n *ngIf=\"preview\"\n fxLayout=\"row\"\n fxLayoutAlign=\"start center\"\n fxFlex\n >\n <button fxFlex class=\"mr-4\" mat-raised-button (click)=\"retry()\">\n {{ \"pms.dialogs.components.scanProfile.retry\" | translate }}\n </button>\n\n <button\n [disabled]=\"error\"\n fxFlex\n class=\"ml-4\"\n mat-raised-button\n (click)=\"continue()\"\n >\n {{\n \"pms.dialogs.components.scanProfile.continueWithSelectedImage\"\n | translate\n }}\n </button>\n </div>\n </footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column!important;flex:1;background-color:#f5f5f5}.page-header{display:flex;flex-direction:row;align-items:center}.page-header button{height:100%}.debug{position:absolute;left:0;width:100%;height:80px;top:0;border-bottom:1px solid #ccc;background-color:#f8f8f8;display:flex;overflow:hidden;color:#000}.debug img{height:50px;border:1px solid #000}.displayInfo{text-align:center;height:20px;flex:1;position:absolute;width:100%;background-color:#000;height:30px;bottom:55px;left:0;line-height:30px;color:#fff;z-index:200}.displayInfo.mobile{font-size:12px}.element{margin-bottom:8px}.element label{font-size:14px}.element div{font-size:18px}.wraper{position:relative;overflow:hidden}.preview{width:100%;border-radius:1%}.documentTypeWraper{width:400px}.documentTypeWraper .label{font-size:14px;margin-bottom:20px}.documentTypeWraper button{box-shadow:none}.overPane{position:absolute;width:100%;height:100%;top:0;left:0}.overPane app-webcam{clip-path:url(#myClip)}.subhead{height:55px;padding-top:8px}.rectangle{z-index:2;position:absolute;top:50%;left:50%;width:85.6mm;height:53.98mm;transform:translate(-50%,-50%);box-sizing:border-box;border:2px dashed #459be5;border-radius:3mm}.mask{z-index:1;position:absolute;width:100%;height:100%;background-position:center center;background-size:380mm;background-repeat:no-repeat}.label{font-size:11px;margin-top:4px}footer button{box-shadow:none!important;height:45px;min-height:45px;text-transform:uppercase}h4{font-size:16px}.images .title{padding:8px 0;font-weight:600}.images img{margin-bottom:16px}.error{display:flex;align-items:center;justify-content:center;flex:1}.error .title{font-size:20px;margin-bottom:8px}.error .title mat-icon{margin-right:8px}.error ul{font-size:18px;list-style-type:none}.photo{width:120px;height:120px;overflow:hidden}.signature{width:200px}mat-card{box-shadow:none!important}.scanBlastWraper button{text-transform:uppercase}.scanBlastWraper.mobile mat-card{margin:4px!important}.scanBlastWraper.mobile .description{flex-direction:row!important}.scanBlastWraper.mobile .description .imgWrap{padding:0!important}.scanBlastWraper.mobile .description .btnActions{position:absolute;right:0}.scanBlastWraper.mobile .description button{margin:0!important;position:absolute;right:16px}.scanBlastWraper.mobile .description button.rotateButton{top:58px}.scanBlastWraper.mobile .description button.remButton{top:8px}.scanBlastWraper.mobile .description button mat-icon{margin:0!important}.scanBlastWraper.mobile .description button div.label{display:none}.scanBlast{display:flex;flex-direction:row;flex:1;padding:0 4px}.scanBlast mat-card{padding:0;box-shadow:none;margin:8px 4px;flex:1}.scanBlast mat-card .head{display:flex;flex-direction:row;align-items:center;justify-items:center;border-bottom:1px solid rgba(0,0,0,.12);height:60px;padding:8px}.scanBlast mat-card .head.small{height:30px!important;padding:4px 8px!important}.scanBlast mat-card .head.small .title{font-size:12px!important;margin-left:4px!important}.scanBlast mat-card .head button{max-width:120px;height:40px;box-shadow:none;border:1px solid rgba(0,0,0,.12)}.scanBlast mat-card .head .title{margin-left:16px;color:#459ae5;font-size:16px}.scanBlast mat-card .content{margin:8px;flex:1}.scanBlast mat-card .description{text-align:center;color:#888}.scanBlast mat-card .actions{background-color:#e9e9e9;display:flex;flex-direction:row}.scanBlast mat-card .actions .mat-button-disabled{background-color:#fff!important}.scanBlast mat-card .actions button{box-shadow:none;width:50%;margin:8px;height:40px;font-size:12px}.scanBlast mat-card .actions button mat-icon{margin-right:8px}.scanBlast mat-card .previewPlaceholder{flex:1;border-radius:6px;display:flex;flex-direction:column}.scanBlast mat-card .previewPlaceholder .description{display:flex;flex:1;flex-direction:column;justify-content:center}.scanBlast mat-card .previewPlaceholder button{box-shadow:none;margin-top:8px;height:40px;font-size:12px}.scanBlast mat-card .previewPlaceholder button mat-icon{margin-right:8px}.scanBlast mat-card .previewPlaceholder .imgWrap{flex-direction:column;flex:1;padding:8px;background-color:#f5f5f5;border-radius:4px}.scanBlast mat-card .previewPlaceholder .imgWrap img{width:100%;border-radius:4px}.scanBlast mat-card .previewPlaceholder .imgWrap .image{background-position:center;background-repeat:no-repeat;background-size:contain}.mr-4{margin-right:4px}.ml-4{margin-left:4px}.p-16{padding:16px}.p-8{padding:8px}.py-16{padding:16px 0}.w-100-p{width:100%}.scanPreview{padding:16px}.scanPreview .image{background-position:center;background-repeat:no-repeat;background-size:contain}.empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center}\n", ".page-header{z-index:2000;height:64px;padding:0;background-color:#fff;border-bottom:1px solid rgba(0,0,0,.12)}.page-header .title{padding-left:24px;line-height:64px;font-size:18px}.page-header .separator{width:1px;background-color:#0000001f;height:100%}.page-header .total{line-height:64px}.page-header .total span{font-weight:700}.page-footer{height:64px}.page-footer button{margin-left:24px;box-shadow:none!important}\n"], dependencies: [{ kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i11.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i12.MatCard, selector: "mat-card", exportAs: ["matCard"] }, { kind: "component", type: i13.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i14.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i15.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i16.WebcamComponent, selector: "app-webcam", inputs: ["imageHandler", "id", "type", "width", "height", "videoOptions", "allowCameraSwitch", "mirrorImage", "captureImageData", "imageType", "imageQuality", "trigger", "switchCamera"], outputs: ["imageCapture", "initError", "imageClick", "cameraSwitched", "videoReady", "destroyed"] }, { kind: "directive", type: i17.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i17.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i17.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i18.DefaultClassDirective, selector: " [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
742
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ScanProfileComponent, decorators: [{
|
|
743
|
+
type: Component,
|
|
744
|
+
args: [{ selector: 'app-scan-profile', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- <div *ngIf=\"isDebug\" class=\"debug\">\n <ng-container *ngFor=\"let img of scannedImages; let index = index\">\n <div style=\"display: flex; flex-direction: column\">\n <img [src]=\"img.imageResized\" />\n {{ index }}\n </div>\n </ng-container>\n</div> -->\n\n<header class=\"page-header\">\n <div class=\"title\" ngClass.lt-sm=\"title-small\">Scan</div>\n\n <span fxFlex></span>\n\n <!-- <mat-slide-toggle style=\"margin:0px 20px\" [(ngModel)]=\"isDebug\"\n >Debug</mat-slide-toggle\n > -->\n\n <ng-container\n *ngIf=\"\n documentTypeSelected &&\n !result &&\n !error &&\n multipleWebcamsAvailable &&\n !preview\n \"\n >\n <div class=\"separator\"></div>\n <div style=\"padding: 0px 16px\">\n <div fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <mat-form-field\n style=\"font-size: 14px; width: 200px; margin-top: 8px\"\n class=\"w-100 mr-16 mt-8\"\n >\n <mat-label> Camera </mat-label>\n <mat-select\n (selectionChange)=\"selectCamera($event)\"\n [(ngModel)]=\"deviceId\"\n >\n <mat-option\n *ngFor=\"let device of mediaDevices\"\n [value]=\"device.deviceId\"\n >\n {{ device.label }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"type === 'desktop'\">\n <!-- <div class=\"separator\"></div>\n <button mat-button (click)=\"sendMobile()\">\n <mat-icon>tablet_mac</mat-icon>\n </button> -->\n\n <div class=\"separator\"></div>\n\n <button mat-button (click)=\"close()\">\n <mat-icon>close</mat-icon>\n </button>\n </ng-container>\n</header>\n\n<div *ngIf=\"result\" fxFlex fxLayout=\"column\">\n <!-- <div *ngIf=\"result\" fxFlex fxLayout=\"column\"> -->\n <div\n fxFlex\n #wraper\n class=\"wraper\"\n fxLayout=\"row\"\n style=\"overflow: auto\"\n protelPerfectScrollbar\n class=\"pt-8 pr-8\"\n fxLayout.lt-md=\"column\"\n >\n <div fxFlex class=\"\">\n <div fxFlex>\n <mat-card style=\"margin: 4px; padding: 4px 16px\">\n <h3>Avatar</h3>\n <div\n style=\"display: flex; flex-direction: row; align-items: center\"\n class=\"selfieContainer\"\n >\n <div class=\"selfie\" style=\"width: 200px\">\n <img\n *ngIf=\"model?._avatar\"\n class=\"preview\"\n style=\"width: 120px; height: 120px; border-radius: 60px\"\n [src]=\"model._avatar\"\n />\n </div>\n <button\n [disabled]=\"imageVerified\"\n (click)=\"selfie()\"\n mat-raised-button\n >\n Take selfie\n </button>\n </div>\n </mat-card>\n\n <form\n fxLayout=\"row\"\n fxLayoutAlign=\"start center\"\n class=\"px-16 py-0 w-100-p\"\n [formGroup]=\"form\"\n >\n <formly-form\n ngClass.lt-md=\"mobile\"\n fxFlex\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n >\n </formly-form>\n </form>\n </div>\n </div>\n <div fxFlex class=\"pr-16 m-4\">\n <mat-card style=\"margin: 4px; padding-top: 2px\" class=\"images\">\n <h3>Images</h3>\n <ng-container *ngFor=\"let img of images\">\n <div fxLayout=\"column\">\n <ng-container *ngIf=\"img.side === 0\">\n <div class=\"title\">Front Side</div>\n </ng-container>\n <ng-container *ngIf=\"img.side === 1\">\n <div class=\"title\">Back Side</div>\n </ng-container>\n <img\n class=\"preview\"\n style=\"max-width: 460px; border-radius: 1rem\"\n [src]=\"img.data\"\n />\n </div>\n </ng-container>\n </mat-card>\n </div>\n </div>\n\n <div></div>\n\n <footer fxLayout=\"row\" class=\"p-8\">\n <div class=\"w-100-p\" fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <button fxFlex class=\"mr-8\" mat-raised-button (click)=\"retake()\">\n {{ \"pms.dialogs.components.scanProfile.reTake\" | translate }}\n </button>\n <button\n [disabled]=\"error || form.invalid\"\n fxFlex\n class=\"ml-8\"\n mat-raised-button\n (click)=\"use()\"\n >\n {{ \"pms.dialogs.components.scanProfile.useData\" | translate }}\n </button>\n </div>\n </footer>\n</div>\n\n<div\n style=\"position: relative\"\n *ngIf=\"!result && documentTypeSelected\"\n fxFlex\n fxLayout=\"column\"\n>\n <div fxFlex #wraper class=\"wraper\" fxLayout=\"row\">\n <div\n style=\"\n position: absolute;\n top: 0px;\n left: 0px;\n right: 0px;\n bottom: 0px;\n z-index: 20;\n background-color: whitesmoke;\n \"\n *ngIf=\"!cameraReady && !preview\"\n >\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n </div>\n\n <div *ngIf=\"!preview\" style=\"position: absolute; left: 0px\">\n DELAY:{{ scanDelay }}\n </div>\n\n <div\n *ngIf=\"scaning\"\n style=\"\n position: absolute;\n z-index: 200;\n width: 100%;\n height: 100%;\n top: 0px;\n left: 0px;\n \"\n fxlayout=\"row\"\n fxLayoutAlign=\"center center\"\n >\n <!-- <mat-progress-spinner\n mode=\"indeterminate\"\n color=\"accent\"\n [strokeWidth]=\"10\"\n ></mat-progress-spinner> -->\n </div>\n\n <ng-container *ngIf=\"!error\">\n <!-- <div\n class=\"rectangle\"\n [ngStyle]=\"{\n 'width.px': videoHeight * 0.75 * 1.588,\n 'height.px': videoHeight * 0.75\n }\"\n ></div>\n <svg\n *ngIf=\"videoWidth\"\n style=\"position: absolute; left: 0px; top: 0px\"\n width=\"0\"\n height=\"0\"\n >\n <defs>\n <clipPath id=\"myClip\">\n <rect\n stroke-width=\"6\"\n stroke-color=\"red\"\n [attr.x]=\"(videoWidth - videoHeight * 0.75 * 1.588) / 2\"\n [attr.y]=\"(videoHeight * 0.25) / 2\"\n [attr.width]=\"videoHeight * 0.75 * 1.588\"\n [attr.height]=\"videoHeight * 0.75\"\n rx=\"25\"\n />\n </clipPath>\n </defs>\n </svg> -->\n\n <app-webcam\n *ngIf=\"!preview && !scaning\"\n class=\"main\"\n [imageQuality]=\"1\"\n #webcam\n fxFlex\n type=\"document\"\n [trigger]=\"trigger\"\n [imageHandler]=\"imageHandler\"\n (imageCapture)=\"handleImage($event)\"\n [allowCameraSwitch]=\"allowCameraSwitch\"\n [videoOptions]=\"videoOptions\"\n [switchCamera]=\"nextWebcamObservable\"\n (cameraSwitched)=\"cameraWasSwitched($event)\"\n (initError)=\"handleInitError($event)\"\n [width]=\"width\"\n [height]=\"height\"\n (destroyed)=\"cameraOff($event)\"\n (videoReady)=\"videoReady($event)\"\n >\n </app-webcam>\n </ng-container>\n <div\n fxLayout=\"row\"\n fxFlex\n class=\"previewData\"\n *ngIf=\"preview\"\n style=\"z-index: 20; position: absolute; width: 100%; height: 100%\"\n >\n <div class=\"p-16 error\" *ngIf=\"error\">\n <div style=\"max-width: \">\n <div class=\"title\" fxLayout=\"row\" fxLayoutAlign=\"start center\">\n <mat-icon>error_outline</mat-icon\n ><span class=\"ml-8\">{{\n \"pms.dialogs.components.scanProfile.unableToDetectId\" | translate\n }}</span>\n </div>\n\n <ng-container *ngIf=\"errorCode === '1001'\">\n <div>\n Could not classify the given object as a supported document.\n </div>\n </ng-container>\n <ng-container *ngIf=\"errorCode === '1002'\">\n <div>\n Something is wrong with extraction data. Please try again.\n </div>\n </ng-container>\n\n <ul *ngIf=\"errorCode === '1000'\">\n <li>\n {{\n \"pms.dialogs.components.scanProfile.placeIdCloseToDevice\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.ensureSufficientLight\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.holdDocumentSteady\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.makeSureAllEdgesOfTheIdAreVisible\"\n | translate\n }}\n </li>\n <li>\n {{\n \"pms.dialogs.components.scanProfile.makeSureThereAreNoGlareAndShadowsOnTheId\"\n | translate\n }}\n </li>\n </ul>\n </div>\n </div>\n\n <div\n class=\"scanPreview\"\n fxFlex\n fxLayout=\"column\"\n *ngIf=\"!error && !scaning\"\n >\n <!-- <div class=\"py-16\" style=\"font-size: 16px\">\n {{\n \"pms.dialogs.components.scanProfile.ensureAllTextsAreVisible\"\n | translate\n }}\n </div> -->\n <div\n fxFlex\n class=\"image\"\n [style.background-image]=\"'url(' + preview + ')'\"\n ></div>\n </div>\n </div>\n </div>\n\n <footer fxLayout=\"row\" style=\"height: 80px\" class=\"p-8\">\n <div class=\"displayInfo\" ngClass.lt-sm=\"mobile\" *ngIf=\"!preview && cameraReady\">\n {{ displayInfo }}\n </div>\n <div style=\"height: 26px\">\n <div\n style=\"text-align: center; font-size: 18px\"\n *ngIf=\"idScan && !preview && cameraReady\"\n >\n <ng-container *ngIf=\"idScan === 'BACK'\">\n Turn document and:\n {{ \"pms.dialogs.components.scanProfile.captureBack\" | translate }}\n </ng-container>\n <ng-container *ngIf=\"idScan === 'FRONT'\">\n Turn document and:\n {{ \"pms.dialogs.components.scanProfile.captureFront\" | translate }}\n </ng-container>\n </div>\n </div>\n\n <!-- <button\n [disabled]=\"!cameraReady\"\n class=\"w-100-p\"\n *ngIf=\"!preview\"\n mat-raised-button\n (click)=\"scan()\"\n >\n <ng-container>\n <ng-container *ngIf=\"scanType === 'FRONT'\">{{\n \"pms.dialogs.components.scanProfile.captureFront\" | translate\n }}</ng-container>\n <ng-container *ngIf=\"scanType === 'BACK'\">{{\n \"pms.dialogs.components.scanProfile.captureBack\" | translate\n }}</ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"scanSide === 1\">{{\n \"pms.dialogs.components.scanProfile.captureBackOfId\" | translate\n }}</ng-container>\n </button> -->\n\n <div\n class=\"w-100-p\"\n *ngIf=\"preview\"\n fxLayout=\"row\"\n fxLayoutAlign=\"start center\"\n fxFlex\n >\n <button fxFlex class=\"mr-4\" mat-raised-button (click)=\"retry()\">\n {{ \"pms.dialogs.components.scanProfile.retry\" | translate }}\n </button>\n\n <button\n [disabled]=\"error\"\n fxFlex\n class=\"ml-4\"\n mat-raised-button\n (click)=\"continue()\"\n >\n {{\n \"pms.dialogs.components.scanProfile.continueWithSelectedImage\"\n | translate\n }}\n </button>\n </div>\n </footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column!important;flex:1;background-color:#f5f5f5}.page-header{display:flex;flex-direction:row;align-items:center}.page-header button{height:100%}.debug{position:absolute;left:0;width:100%;height:80px;top:0;border-bottom:1px solid #ccc;background-color:#f8f8f8;display:flex;overflow:hidden;color:#000}.debug img{height:50px;border:1px solid #000}.displayInfo{text-align:center;height:20px;flex:1;position:absolute;width:100%;background-color:#000;height:30px;bottom:55px;left:0;line-height:30px;color:#fff;z-index:200}.displayInfo.mobile{font-size:12px}.element{margin-bottom:8px}.element label{font-size:14px}.element div{font-size:18px}.wraper{position:relative;overflow:hidden}.preview{width:100%;border-radius:1%}.documentTypeWraper{width:400px}.documentTypeWraper .label{font-size:14px;margin-bottom:20px}.documentTypeWraper button{box-shadow:none}.overPane{position:absolute;width:100%;height:100%;top:0;left:0}.overPane app-webcam{clip-path:url(#myClip)}.subhead{height:55px;padding-top:8px}.rectangle{z-index:2;position:absolute;top:50%;left:50%;width:85.6mm;height:53.98mm;transform:translate(-50%,-50%);box-sizing:border-box;border:2px dashed #459be5;border-radius:3mm}.mask{z-index:1;position:absolute;width:100%;height:100%;background-position:center center;background-size:380mm;background-repeat:no-repeat}.label{font-size:11px;margin-top:4px}footer button{box-shadow:none!important;height:45px;min-height:45px;text-transform:uppercase}h4{font-size:16px}.images .title{padding:8px 0;font-weight:600}.images img{margin-bottom:16px}.error{display:flex;align-items:center;justify-content:center;flex:1}.error .title{font-size:20px;margin-bottom:8px}.error .title mat-icon{margin-right:8px}.error ul{font-size:18px;list-style-type:none}.photo{width:120px;height:120px;overflow:hidden}.signature{width:200px}mat-card{box-shadow:none!important}.scanBlastWraper button{text-transform:uppercase}.scanBlastWraper.mobile mat-card{margin:4px!important}.scanBlastWraper.mobile .description{flex-direction:row!important}.scanBlastWraper.mobile .description .imgWrap{padding:0!important}.scanBlastWraper.mobile .description .btnActions{position:absolute;right:0}.scanBlastWraper.mobile .description button{margin:0!important;position:absolute;right:16px}.scanBlastWraper.mobile .description button.rotateButton{top:58px}.scanBlastWraper.mobile .description button.remButton{top:8px}.scanBlastWraper.mobile .description button mat-icon{margin:0!important}.scanBlastWraper.mobile .description button div.label{display:none}.scanBlast{display:flex;flex-direction:row;flex:1;padding:0 4px}.scanBlast mat-card{padding:0;box-shadow:none;margin:8px 4px;flex:1}.scanBlast mat-card .head{display:flex;flex-direction:row;align-items:center;justify-items:center;border-bottom:1px solid rgba(0,0,0,.12);height:60px;padding:8px}.scanBlast mat-card .head.small{height:30px!important;padding:4px 8px!important}.scanBlast mat-card .head.small .title{font-size:12px!important;margin-left:4px!important}.scanBlast mat-card .head button{max-width:120px;height:40px;box-shadow:none;border:1px solid rgba(0,0,0,.12)}.scanBlast mat-card .head .title{margin-left:16px;color:#459ae5;font-size:16px}.scanBlast mat-card .content{margin:8px;flex:1}.scanBlast mat-card .description{text-align:center;color:#888}.scanBlast mat-card .actions{background-color:#e9e9e9;display:flex;flex-direction:row}.scanBlast mat-card .actions .mat-button-disabled{background-color:#fff!important}.scanBlast mat-card .actions button{box-shadow:none;width:50%;margin:8px;height:40px;font-size:12px}.scanBlast mat-card .actions button mat-icon{margin-right:8px}.scanBlast mat-card .previewPlaceholder{flex:1;border-radius:6px;display:flex;flex-direction:column}.scanBlast mat-card .previewPlaceholder .description{display:flex;flex:1;flex-direction:column;justify-content:center}.scanBlast mat-card .previewPlaceholder button{box-shadow:none;margin-top:8px;height:40px;font-size:12px}.scanBlast mat-card .previewPlaceholder button mat-icon{margin-right:8px}.scanBlast mat-card .previewPlaceholder .imgWrap{flex-direction:column;flex:1;padding:8px;background-color:#f5f5f5;border-radius:4px}.scanBlast mat-card .previewPlaceholder .imgWrap img{width:100%;border-radius:4px}.scanBlast mat-card .previewPlaceholder .imgWrap .image{background-position:center;background-repeat:no-repeat;background-size:contain}.mr-4{margin-right:4px}.ml-4{margin-left:4px}.p-16{padding:16px}.p-8{padding:8px}.py-16{padding:16px 0}.w-100-p{width:100%}.scanPreview{padding:16px}.scanPreview .image{background-position:center;background-repeat:no-repeat;background-size:contain}.empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center}\n", ".page-header{z-index:2000;height:64px;padding:0;background-color:#fff;border-bottom:1px solid rgba(0,0,0,.12)}.page-header .title{padding-left:24px;line-height:64px;font-size:18px}.page-header .separator{width:1px;background-color:#0000001f;height:100%}.page-header .total{line-height:64px}.page-header .total span{font-weight:700}.page-footer{height:64px}.page-footer button{margin-left:24px;box-shadow:none!important}\n"] }]
|
|
745
|
+
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.ScanProvider }, { type: i2.DialogsCoreProvider }, { type: i3.ScanFieldsProvider }, { type: i0.NgZone }, { type: i4.TranslateService }, { type: i5.AuthProvider }]; }, propDecorators: { type: [{
|
|
746
|
+
type: Input
|
|
747
|
+
}], actions: [{
|
|
748
|
+
type: Output
|
|
749
|
+
}], wraper: [{
|
|
750
|
+
type: ViewChild,
|
|
751
|
+
args: ['wraper']
|
|
752
|
+
}], onResize: [{
|
|
753
|
+
type: HostListener,
|
|
754
|
+
args: ['window:resize', ['$event']]
|
|
755
|
+
}] } });
|
|
756
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nhbi1wcm9maWxlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zY2FuZG9jL3NyYy9kaWFsb2dzL2NvbXBvbmVudHMvc2Nhbi1wcm9maWxlL3NjYW4tcHJvZmlsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc2NhbmRvYy9zcmMvZGlhbG9ncy9jb21wb25lbnRzL3NjYW4tcHJvZmlsZS9zY2FuLXByb2ZpbGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxTQUFTLEVBQ1QsWUFBWSxFQUNaLE1BQU0sRUFDTixZQUFZLEVBSVosdUJBQXVCLEVBQ3ZCLEtBQUssR0FHTixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQWdDLE1BQU0sTUFBTSxDQUFDO0FBQzdFLE9BQU8sRUFBRSxFQUFFLElBQUksTUFBTSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXBDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsU0FBUyxFQUFjLE1BQU0sZ0JBQWdCLENBQUM7QUFPdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtEQUFrRCxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJCOUUsTUFBTSxPQUFPLG9CQUFvQjtJQW9HL0IsWUFDUyxFQUFxQixFQUNyQixZQUEwQixFQUN6QixPQUE0QixFQUM1QixZQUFnQyxFQUNoQyxJQUFZLEVBQ1osU0FBMkIsRUFFM0IsSUFBa0IsQ0FBQyw4QkFBOEI7O1FBUGxELE9BQUUsR0FBRixFQUFFLENBQW1CO1FBQ3JCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQ3pCLFlBQU8sR0FBUCxPQUFPLENBQXFCO1FBQzVCLGlCQUFZLEdBQVosWUFBWSxD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QkFDSSxPQUFPO3NCQUFoQixNQUFNO2dCQWlFYyxNQUFNO3NCQUExQixTQUFTO3VCQUFDLFFBQVE7Z0JBR25CLFFBQVE7c0JBRFAsWUFBWTt1QkFBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIFZpZXdDaGlsZCxcbiAgRXZlbnRFbWl0dGVyLFxuICBPdXRwdXQsXG4gIEhvc3RMaXN0ZW5lcixcbiAgRWxlbWVudFJlZixcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBOZ1pvbmUsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTWF0RGlhbG9nUmVmIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IFN1YmplY3QsIE9ic2VydmFibGUsIG9mLCBmb3JrSm9pbiwgZnJvbSwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB2NCBhcyB1dWlkdjQgfSBmcm9tICd1dWlkJztcblxuaW1wb3J0IHsgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBzd2l0Y2hNYXAsIG1hcCwgZGVsYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbi8vaW1wb3J0IHsgU2NhbkZpZWxkc1Byb3ZpZGVyIH0gZnJvbSAnYXBwL3Byb3ZpZGVycy9zY2FuLmZvcm0nO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgU2NhblByb3ZpZGVyIH0gZnJvbSAnLi4vLi4vLi4vcHJvdmlkZXJzL3NjYW4ucHJvdmlkZXInO1xuaW1wb3J0IHsgRGlhbG9nc0NvcmVQcm92aWRlciB9IGZyb20gJy4uLy4uLy4uL2RpYWxvZ3MvZGlhbG9ncy5jb3JlLnByb3ZpZGVyJztcbmltcG9ydCB7IFdlYmNhbUltYWdlIH0gZnJvbSAnLi4vLi4vLi4vY29yZS9jb21wb25lbnRzL3dlYmNhbS9kb21haW4vd2ViY2FtLWltYWdlJztcbmltcG9ydCB7IFdlYmNhbVV0aWwgfSBmcm9tICcuLi8uLi8uLi9jb3JlL2NvbXBvbmVudHMvd2ViY2FtL3V0aWwvd2ViY2FtLnV0aWwnO1xuaW1wb3J0IHsgV2ViY2FtSW5pdEVycm9yIH0gZnJvbSAnLi4vLi4vLi4vY29yZS9jb21wb25lbnRzL3dlYmNhbS9kb21haW4vd2ViY2FtLWluaXQtZXJyb3InO1xuaW1wb3J0IHsgU2NhbkZpZWxkc1Byb3ZpZGVyIH0gZnJvbSAnLi4vLi4vLi4vcHJvdmlkZXJzL3NjYW4uZm9ybSc7XG5pbXBvcnQgeyBBdXRoUHJvdmlkZXIgfSBmcm9tICcuLi8uLi8uLi9wcm92aWRlcnMvYXV0aC5wcm92aWRlcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVdpbmRvdyBleHRlbmRzIFdpbmRvdyB7XG4gIFRleHREZXRlY3RvcjogYW55O1xufVxuXG5pbnRlcmZhY2UgVHJvdWJsZXNob290aW5nIHtcbiAgUmVxdWVzdDogYW55O1xuICBSZXNwb25zZTogYW55O1xuICBFeHBlY3RlZE91dHB1dDogYW55O1xuICBBY2NlcHRUZXJtc0FuZENvbmRpdGlvbnM6IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBUaW1lc3RhbXBzIHtcbiAgdGltZTogbnVtYmVyO1xuICBsb2FkOiBudW1iZXI7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1zY2FuLXByb2ZpbGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vc2Nhbi1wcm9maWxlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vc2Nhbi1wcm9maWxlLmNvbXBvbmVudC5zY3NzJywgJy4uLy4uL3Njc3MvZGlhbG9nLnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFNjYW5Qcm9maWxlQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgc2NhbkJsYXN0RGF0YTogYW55ID0gW1xuICAgIHtcbiAgICAgIHRpdGxlOiAncG1zLmRpYWxvZ3MuY29tcG9uZW50cy5zY2FuUHJvZmlsZS5mcm9udCcsXG4gICAgICBkZXNjcmlwdGlvbjogJ3Btcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUuZnJvbnREZXNjcmlwdGlvbicsXG4gICAgICBzaWRlOiAnRlJPTlQnLFxuICAgIH0sXG4gICAge1xuICAgICAgdGl0bGU6ICdwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLmJhY2snLFxuICAgICAgZGVzY3JpcHRpb246ICdwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLmJhY2tEZXNjcmlwdGlvbicsXG4gICAgICBkaXNhYmxlZDogdHJ1ZSxcbiAgICAgIHNpZGU6ICdCQUNLJyxcbiAgICB9LFxuICBdO1xuICBASW5wdXQoKSB0eXBlID0gJ2Rlc2t0b3AnO1xuICBAT3V0cHV0KCkgYWN0aW9ucyA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgbWVkaWFEZXZpY2VzOiBhbnkgPSBbXTtcbiAgcHVibGljIGRldmljZUlkPzogc3RyaW5nO1xuICBwdWJsaWMgdmlkZW9PcHRpb25zOiBNZWRpYVRyYWNrQ29uc3RyYWludHMgPSB7XG4gICAgd2lkdGg6IDE5MjAsXG4gICAgaGVpZ2h0OiAxMDgwLFxuICAgIGZhY2luZ01vZGU6ICdlbnZpcm9ubWVudCcsXG4gIH07XG4gIGRpYWxvZ1JlZj86IE1hdERpYWxvZ1JlZjxhbnk+O1xuICBkYXRhOiBhbnk7XG4gIHN0YXJ0VGltZTogbnVtYmVyID0gMDtcbiAgaXNEZWJ1ZyA9IGZhbHNlO1xuICBtdWx0aXBsZVdlYmNhbXNBdmFpbGFibGUgPSBmYWxzZTtcbiAgc2NhbkluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgZmllbGRzOiBhbnk7XG4gIC8vIHdlYmNhbSBzbmFwc2hvdCB0cmlnZ2VyXG4gIGRvY3VtZW50VHlwZVNlbGVjdGVkID0gZmFsc2U7XG4gIGltYWdlSGFuZGxlclN1YnNjcmlwdGlvbiE6IFN1YnNjcmlwdGlvbjtcbiAgc2VsZWN0ZWRTaWRlOiBhbnk7XG4gIGltYWdlczogYW55O1xuICBzY2FuVGltZW91dDogYW55O1xuICBwcmV2aWV3OiBhbnkgPSBudWxsO1xuICBzY2FuVHlwZTogYW55O1xuICB3aWR0aDogYW55O1xuICBoZWlnaHQ6IGFueTtcbiAgdmlkZW9XaWR0aDogYW55O1xuICB2aWRlb0hlaWdodDogYW55O1xuICBlcnJvckNvZGUgPSAnMTAwMCc7XG4gIGRpc3BsYXlJbmZvOiBhbnkgPSAnUG9zaXRpb24gZG9jdW1lbnQgaW5zaWRlIHJlY3RhbmdlIGFuZCBob2xkIHN0ZWFkeS4nO1xuICBhbGxvd0NhbWVyYVN3aXRjaCA9IHRydWU7XG4gIHZlcmlmaWNhdGlvbkVycm9yU2VudCA9IGZhbHNlO1xuICBlcnJvciA9IGZhbHNlO1xuICBjYW1lcmFSZWFkeSA9IGZhbHNlO1xuICByZXN1bHQ6IGFueTtcbiAgc2NhbmluZyA9IGZhbHNlO1xuXG4gIGltYWdlSGFuZGxlciA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgbG9nRGF0YTogVHJvdWJsZXNob290aW5nID0ge1xuICAgIEFjY2VwdFRlcm1zQW5kQ29uZGl0aW9uczogdHJ1ZSxcbiAgICBSZXF1ZXN0OiBudWxsLFxuICAgIFJlc3BvbnNlOiBudWxsLFxuICAgIEV4cGVjdGVkT3V0cHV0OiBudWxsLFxuICB9O1xuICBkZWZhdWx0RGV2aWNlOiBhbnk7XG4gIHNjYW5EYXRhczogYW55ID0gW107XG4gIHNjYW5TaWRlOiBhbnk7XG4gIGlkU2NhbjogYW55ID0gbnVsbDtcbiAgd2ViY2FtSW1hZ2U/OiBXZWJjYW1JbWFnZTtcbiAgbW9kZWw6IGFueTtcbiAgdmFsaWRhdGlvbiA9IGZhbHNlO1xuICBzY2FubmVkSW1hZ2VzOiBhbnlbXSA9IFtdO1xuICBzY2FuRGVsYXk6IGFueSA9IDA7XG4gIHB1YmxpYyB0cmlnZ2VyOiBTdWJqZWN0PG51bWJlcj4gPSBuZXcgU3ViamVjdDxudW1iZXI+KCk7XG4gIC8vIHN3aXRjaCB0byBuZXh0IC8gcHJldmlvdXMgLyBzcGVjaWZpYyB3ZWJjYW07IHRydWUvZmFsc2U6IGZvcndhcmQvYmFja3dhcmRzLCBzdHJpbmc6IGRldmljZUlkXG4gIHB1YmxpYyBuZXh0V2ViY2FtOiBTdWJqZWN0PGJvb2xlYW4gfCBzdHJpbmc+ID0gbmV3IFN1YmplY3Q8XG4gICAgYm9vbGVhbiB8IHN0cmluZ1xuICA+KCk7XG4gIGltYWdlVmVyaWZpZWQgPSBmYWxzZTtcbiAgZm9ybSA9IG5ldyBGb3JtR3JvdXAoe30pO1xuXG4gIHNjYW5JbWFnZVRpbWVzdGFtcHM6IFRpbWVzdGFtcHMgPSB7XG4gICAgdGltZTogMCxcbiAgICBsb2FkOiAwLFxuICB9O1xuICBAVmlld0NoaWxkKCd3cmFwZXInKSB3cmFwZXI/OiBFbGVtZW50UmVmO1xuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbJyRldmVudCddKVxuICBvblJlc2l6ZSgpIHtcbiAgICBpZiAodGhpcy53cmFwZXIpIHtcbiAgICAgIHRoaXMud2lkdGggPSB0aGlzLndyYXBlci5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoO1xuICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLndyYXBlci5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodDtcblxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHZpZGVvID0gdGhpcy53cmFwZXI/Lm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcigndmlkZW8nKTtcbiAgICAgICAgaWYgKHZpZGVvKSB7XG4gICAgICAgICAgLy8gICBjb25zb2xlLmxvZyh2aWRlby5jbGllbnRXaWR0aCwgdmlkZW8uY2xpZW50SGVpZ2h0KTtcbiAgICAgICAgICB0aGlzLnZpZGVvV2lkdGggPSB2aWRlby5jbGllbnRXaWR0aDtcbiAgICAgICAgICB0aGlzLnZpZGVvSGVpZ2h0ID0gdmlkZW8uY2xpZW50SGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSwgMTAwKTtcbiAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgY2Q6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHB1YmxpYyBzY2FuUHJvdmlkZXI6IFNjYW5Qcm92aWRlcixcbiAgICBwcml2YXRlIGRpYWxvZ3M6IERpYWxvZ3NDb3JlUHJvdmlkZXIsXG4gICAgcHJpdmF0ZSBmb3JtUHJvdmlkZXI6IFNjYW5GaWVsZHNQcm92aWRlcixcbiAgICBwcml2YXRlIHpvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcblxuICAgIHByaXZhdGUgYXV0aDogQXV0aFByb3ZpZGVyIC8vIHByaXZhdGUgYXBpOiBTZXJ2ZXJQcm92aWRlclxuICApIHt9XG5cbiAgcHJpdmF0ZSByZXNldExvZ0RhdGEoKSB7XG4gICAgdGhpcy5sb2dEYXRhID0ge1xuICAgICAgUmVxdWVzdDogbnVsbCxcbiAgICAgIFJlc3BvbnNlOiBudWxsLFxuICAgICAgRXhwZWN0ZWRPdXRwdXQ6IG51bGwsXG4gICAgICBBY2NlcHRUZXJtc0FuZENvbmRpdGlvbnM6IHRydWUsXG4gICAgfTtcbiAgfVxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zY2FuVGltZW91dCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuc2NhblRpbWVvdXQpO1xuICAgIH1cbiAgICBpZiAodGhpcy5pbWFnZUhhbmRsZXJTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuaW1hZ2VIYW5kbGVyU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG4gIGluaXQoKSB7XG4gICAgdGhpcy5hdXRoLmFjY2VzVG9rZW4uc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5yZXNldExvZ0RhdGEoKTtcbiAgICAvLyB0aGlzLnJlc3VsdD10cnVlO1xuICAgIC8vIHRoaXMucmVzdWx0ID17fTtcblxuICAgIHRoaXMuZmllbGRzID0gdGhpcy5mb3JtUHJvdmlkZXIuZG9jdW1lbnQoKTtcblxuICAgIFdlYmNhbVV0aWwuZ2V0QXZhaWxhYmxlVmlkZW9JbnB1dHMoKS5zdWJzY3JpYmUoXG4gICAgICAobWVkaWFEZXZpY2VzOiBNZWRpYURldmljZUluZm9bXSkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAnW0RFVklDRVNdJyxcbiAgICAgICAgICBtZWRpYURldmljZXMubWFwKChkKSA9PiBkLmxhYmVsKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1lZGlhRGV2aWNlcyA9IG1lZGlhRGV2aWNlcztcbiAgICAgICAgdGhpcy5tdWx0aXBsZVdlYmNhbXNBdmFpbGFibGUgPSBtZWRpYURldmljZXMgJiYgbWVkaWFEZXZpY2VzLmxlbmd0aCA+IDE7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHNjYW4oKSB7XG4gICAgLy8gdGhpcy50cmlnZ2VyU25hcHNob3QoKTtcbiAgICAvLyAgIHRoaXMuc2NhbkRhdGFzWzBdID0gdHJ1ZTtcbiAgICAvLyBpZiAodGhpcy5zY2FuVGltZW91dCkge1xuICAgIC8vICAgY2xlYXJUaW1lb3V0KHRoaXMuc2NhblRpbWVvdXQpO1xuICAgIC8vIH1cbiAgICAvLyB0aGlzLnNjYW5UaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgLy8gICB0aGlzLnNjYW4oKTtcbiAgICAvLyB9LCAxKTtcbiAgfVxuXG4gIHByaXZhdGUgRGF0YVVybEZyb21JbWFnZSgpIHt9XG4gIHB1YmxpYyBoYW5kbGVJbWFnZSh3ZWJjYW1JbWFnZTogV2ViY2FtSW1hZ2UpOiB2b2lkIHtcbiAgICAvLyBjb25zb2xlLmxvZygnW3JlY2VpdmVkIHdlYmNhbSBpbWFnZV0nLCB3ZWJjYW1JbWFnZSk7XG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIGNvbnN0IGNvbnNvbGVCYWNrZ3JvdW5kID1cbiAgICAgICAgXCJmb250LXNpemU6MzAwcHg7YmFja2dyb3VuZC1pbWFnZTogdXJsKCdcIiArXG4gICAgICAgIHdlYmNhbUltYWdlLmltYWdlUmVzaXplZCArXG4gICAgICAgIFwiJyk7YmFja2dyb3VuZC1zaXplOiBjb250YWluOyBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0O1wiO1xuICAgICAgLy8gIGNvbnNvbGUubG9nKCclYyAgICAnLCBjb25zb2xlQmFja2dyb3VuZCk7XG4gICAgICBjb25zdCB0aW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICAgIGlmICh0aGlzLnNjYW5JbWFnZVRpbWVzdGFtcHMubG9hZCA+IDApIHtcbiAgICAgICAgY29uc3QgeyBsb2FkIH0gPSB0aGlzLnNjYW5JbWFnZVRpbWVzdGFtcHM7XG4gICAgICAgIGNvbnN0IGRpZmYgPSB0aW1lIC0gbG9hZDtcbiAgICAgICAgLy8gICBjb25zb2xlLmxvZygndGltZTonLCBkaWZmKTtcbiAgICAgICAgdGhpcy5zY2FuRGVsYXkgPSBkaWZmO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNjYW5JbWFnZVRpbWVzdGFtcHMubG9hZCA9IHRpbWU7XG5cbiAgICAgIGlmICh3ZWJjYW1JbWFnZS5pbWFnZURhdGEpIHtcbiAgICAgICAgdGhpcy5zY2FubmVkSW1hZ2VzLnB1c2god2ViY2FtSW1hZ2UpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIGlmICh0aGlzLnNjYW5uZWRJbWFnZXMubGVuZ3RoID4gNCAmJiAhdGhpcy52YWxpZGF0aW9uKSB7XG4gICAgICAgIGNvbnNvbGUudGltZUVuZCgnc2NhbicpO1xuICAgICAgICBjb25zb2xlLnRpbWUoJ3NjYW4nKTtcbiAgICAgICAgLy8gZ2V0IGxhc3QgMTBcbiAgICAgICAgY29uc29sZS5sb2coJ0NBUFRVUkVEOicsIHRoaXMuc2Nhbm5lZEltYWdlcy5sZW5ndGgpO1xuICAgICAgICBjb25zdCBpbWFnZXMgPSB0aGlzLnNjYW5uZWRJbWFnZXMuc2xpY2UoLTUpO1xuICAgICAgICAvLyBzZXQgaW1hZ2VzIHRvIDBcbiAgICAgICAgdGhpcy5zY2FubmVkSW1hZ2VzID0gW107XG4gICAgICAgIGNvbnN0IGltYWdlc0FycmF5ID0gaW1hZ2VzLm1hcCgobSkgPT4gbS5pbWFnZVJlc2l6ZWQuc3BsaXQoJywnKVsxXSk7XG4gICAgICAgIHRoaXMudmFsaWRhdGlvbiA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5oYW5kbGVCdXJzdERhdGEoaW1hZ2VzQXJyYXksIGltYWdlcyk7XG4gICAgICAgIC8vIHRoaXMuc2NhblByb3ZpZGVyLmJ1cnN0KGltYWdlc0FycmF5KS5zdWJzY3JpYmUoKHJlc3A6IGFueSkgPT4ge1xuICAgICAgICAvLyAgIC8vIGNvbnNvbGUuY2xlYXIoKVxuICAgICAgICAvLyAgIGNvbnNvbGUubG9nKFtyZXNwLkluZm9dKTtcbiAgICAgICAgLy8gICB0aGlzLnZhbGlkYXRpb24gPSBmYWxzZTtcblxuICAgICAgICAvLyAgIHRoaXMuZGlzcGxheUluZm8gPSByZXNwLkluZm87XG4gICAgICAgIC8vICAgaWYgKHJlc3AuVmFsaWRhdGVkKSB7XG4gICAgICAgIC8vICAgICBpZiAodGhpcy5zY2FuVGltZW91dCkge1xuICAgICAgICAvLyAgICAgICBjbGVhclRpbWVvdXQodGhpcy5zY2FuVGltZW91dCk7XG4gICAgICAgIC8vICAgICB9XG4gICAgICAgIC8vICAgICB0aGlzLndlYmNhbUltYWdlID0gaW1hZ2VzW3Jlc3AuSW5kZXhdO1xuXG4gICAgICAgIC8vICAgICAvLyB0aGlzLnByZXZpZXcgPSB0aGlzLndlYmNhbUltYWdlLmltYWdlQXNEYXRhVXJsO1xuICAgICAgICAvLyAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG5cbiAgICAgICAgLy8gICAgIGNvbnN0IHsgRG9jVHlwZSwgU2VyaWVzLCBTaWRlIH0gPSByZXNwO1xuXG4gICAgICAgIC8vICAgICAvLyBGb3IgSUQgYXNrIGZvciBvdGhlciBzaWRlXG4gICAgICAgIC8vICAgICBpZiAoRG9jVHlwZSA9PT0gJ0lEJykge1xuICAgICAgICAvLyAgICAgICBpZiAoU2lkZSA9PT0gJ0ZST05UJykge1xuICAgICAgICAvLyAgICAgICAgIHRoaXMuc2NhbkJsYXN0RGF0YVswXS5pbWFnZSA9IHRoaXMud2ViY2FtSW1hZ2U7XG4gICAgICAgIC8vICAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vICAgICAgICAgdGhpcy5zY2FuQmxhc3REYXRhWzFdLmltYWdlID0gdGhpcy53ZWJjYW1JbWFnZTtcbiAgICAgICAgLy8gICAgICAgfVxuXG4gICAgICAgIC8vICAgICAgIGlmICh0aGlzLnNjYW5CbGFzdERhdGFbMF0uaW1hZ2UgJiYgdGhpcy5zY2FuQmxhc3REYXRhWzFdLmltYWdlKSB7XG4gICAgICAgIC8vICAgICAgICAgY29uc29sZS53YXJuKCdVUExPQUQnKTtcbiAgICAgICAgLy8gICAgICAgICB0aGlzLnNjYW5CbGFzdEZpbmlzaCgpO1xuICAgICAgICAvLyAgICAgICB9IGVsc2Uge1xuICAgICAgICAvLyAgICAgICAgIGNvbnN0IG51bSA9IFNpZGUgPT09ICdGUk9OVCcgPyAxIDogMDtcblxuICAgICAgICAvLyAgICAgICAgIHRoaXMuc2luZ2xlU2Nhbih0aGlzLnNjYW5CbGFzdERhdGFbbnVtXSk7XG4gICAgICAgIC8vICAgICAgICAgdGhpcy5zY2FuKCk7XG4gICAgICAgIC8vICAgICAgICAgdGhpcy5pZFNjYW4gPSB0aGlzLnNjYW5CbGFzdERhdGFbbnVtXS5zaWRlO1xuICAgICAgICAvLyAgICAgICAgIGNvbnNvbGUubG9nKCdJRCBTSURFJywgdGhpcy5pZFNjYW4pO1xuXG4gICAgICAgIC8vICAgICAgICAgdGhpcy5kaXNwbGF5SW5mbyA9ICdQbGVhc2UgdHVybiB0aGUgZG9jdW1lbnQgb3ZlciEnO1xuICAgICAgICAvLyAgICAgICB9XG4gICAgICAgIC8vICAgICB9IGVsc2Uge1xuICAgICAgICAvLyAgICAgICB0aGlzLnNjYW5CbGFzdERhdGFbMF0uaW1hZ2UgPSB0aGlzLndlYmNhbUltYWdlO1xuICAgICAgICAvLyAgICAgICBjb25zb2xlLndhcm4oJ1VQTE9BRCcpO1xuICAgICAgICAvLyAgICAgICB0aGlzLnNjYW5CbGFzdEZpbmlzaCgpO1xuICAgICAgICAvLyAgICAgfVxuICAgICAgICAvLyAgICAgY29uc29sZS5sb2coRG9jVHlwZSwgU2VyaWVzLCBTaWRlKTtcblxuICAgICAgICAvLyAgICAgdGhpcy5zY2FubmVkSW1hZ2VzID0gW107XG4gICAgICAgIC8vICAgfVxuICAgICAgICAvLyB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuY2FtZXJhUmVhZHkpIHtcbiAgICAgICAgLy8gY29uc29sZS5sb2coJ2RlbGF5JywgdGhpcy5zY2FuRGVsYXkpO1xuICAgICAgICAvL2NvbnNvbGUubG9nKCd0aW1lRCcsIG5ldyBEYXRlKCkuZ2V0VGltZSgpKTtcbiAgICAgICAgdGhpcy50cmlnZ2VyLm5leHQobmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgICAgICAvLyBpZiAodGhpcy5zY2FuRGVsYXkgPCAxMDApIHtcbiAgICAgICAgLy8gICBjb25zdCBkaWZmID0gMTAwIC0gdGhpcy5zY2FuRGVsYXk7XG4gICAgICAgIC8vICAgY29uc29sZS5sb2coZGlmZik7XG4gICAgICAgIC8vICAgY29uc3QgdGltZTIgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgLy8gICAvLyBjb25zdCBzdWIgPSBvZigxKVxuICAgICAgICAvLyAgIC8vICAgLnBpcGUoZGVsYXkoZGlmZikpXG4gICAgICAgIC8vICAgLy8gICAuc3Vic2NyaWJlKChyZXNwKSA9PiB7XG4gICAgICAgIC8vICAgLy8gICAgIGNvbnNvbGUubG9nKG5ldyBEYXRlKCkuZ2V0VGltZSgpLXRpbWUpO1xuICAgICAgICAvLyAgIC8vICAgICAgdGhpcy50cmlnZ2VyLm5leHQoKTtcbiAgICAgICAgLy8gICAvLyAgICAgc3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIC8vICAgLy8gICB9KTtcbiAgICAgICAgLy8gICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIC8vICAgICBjb25zb2xlLmxvZygnVE8nLCBuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIHRpbWUyKTtcbiAgICAgICAgLy8gICAgIHRoaXMudHJpZ2dlci5uZXh0KCk7XG4gICAgICAgIC8vICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIC8vICAgfSwgZGlmZik7XG4gICAgICAgIC8vIH0gZWxzZSB7XG4gICAgICAgIC8vICAgdGhpcy50cmlnZ2VyLm5leHQoKTtcbiAgICAgICAgLy8gfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gdGhpcy5zY2FuSW1hZ2VUaW1lc3RhbXBzID0ge1xuICAgIC8vICAgdGltZTogbmV3IERhdGUoKS5nZXRUaW1lKCksXG4gICAgLy8gICBsb2FkOlxuICAgIC8vIH07XG5cbiAgICAvLyAgdGhpcy53ZWJjYW1JbWFnZSA9IHdlYmNhbUltYWdlO1xuICAgIC8vICB0aGlzLnByZXZpZXcgPSB3ZWJjYW1JbWFnZS5pbWFnZUFzRGF0YVVybDtcbiAgICAvLyAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUJ1cnN0RGF0YShcbiAgICBpbWFnZXNBcnJheTogYW55LFxuICAgIGltYWdlczogYW55LFxuICAgIHR5cGU6ICd3b3JrZXInIHwgJ3BsYWluJyA9ICdwbGFpbidcbiAgKSB7XG4gICAgdGhpcy5zY2FuUHJvdmlkZXIuYnVyc3QoaW1hZ2VzQXJyYXkpLnN1YnNjcmliZSgocmVzcDogYW55KSA9PiB7XG4gICAgICB0aGlzLmRpc3BsYXlJbmZvID0gcmVzcC5JbmZvO1xuICAgICAgY29uc29sZS50aW1lRW5kKCd2YWxpZGF0aW9uUE9TVCcpO1xuICAgICAgY29uc29sZS5sb2coJ0FuYWx5c2lzVGltZScsIHJlc3AuQW5hbHlzaXNUaW1lKTtcbiAgICAgIGNvbnN0IHsgRG9jVHlwZSwgU2VyaWVzLCBTaWRlLCBJbmZvQ29kZSB9ID0gcmVzcDtcblxuICAgICAgLy8gaWYgKEluZm9Db2RlID09PSAnMTAwNicgJiYgdGhpcy5pZFNjYW4pIHtcbiAgICAgIC8vICAgdGhpcy5oYW5kbGVMb25nVmFsaWRhdGlvbkVycm9yKGltYWdlKTtcbiAgICAgIC8vIH1cblxuICAgICAgaWYgKHJlc3AuVmFsaWRhdGVkKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbU0NBTk5FRCBJTkRFWF0nLCByZXNwLkluZGV4KTtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRJbWFnZSA9IGltYWdlc1tyZXNwLkluZGV4XTtcblxuICAgICAgICAvLyB0aGlzLnByZXZpZXcgPSB0aGlzLndlYmNhbUltYWdlLmltYWdlQXNEYXRhVXJsO1xuICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcblxuICAgICAgICBsZXQgaW1hZ2UgPSBzZWxlY3RlZEltYWdlO1xuICAgICAgICBpZiAodHlwZSA9PSAnd29ya2VyJykge1xuICAgICAgICAgIGNvbnN0IGRhdGFVcmwgPSB0aGlzLmhhbmRsZUJpdG1hcEltYWdlKHNlbGVjdGVkSW1hZ2UuYml0bWFwKTtcbiAgICAgICAgICBpbWFnZSA9IHsgZGF0YVVybCB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEluZm9Db2RlID09PSAnMTAwNycpIHtcbiAgICAgICAgICAvLyBGb3IgSUQgYXNrIGZvciBvdGhlciBzaWRlXG4gICAgICAgICAgaWYgKFNpZGUgPT09ICdGUk9OVCcpIHtcbiAgICAgICAgICAgIHRoaXMuc2NhbkJsYXN0RGF0YVswXS5pbWFnZSA9IGltYWdlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNjYW5CbGFzdERhdGFbMV0uaW1hZ2UgPSBpbWFnZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5zY2FuQmxhc3REYXRhWzBdLmltYWdlICYmIHRoaXMuc2NhbkJsYXN0RGF0YVsxXS5pbWFnZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdVUExPQUQnKTtcbiAgICAgICAgICAgIGlmICh0eXBlID09ICd3b3JrZXInKSB7XG4gICAgICAgICAgICAgIHRoaXMuaW1hZ2VIYW5kbGVyLm5leHQoeyB0eXBlOiAnc3RvcCcgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNjYW5CbGFzdEZpbmlzaCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBudW0gPSBTaWRlID09PSAnRlJPTlQnID8gMSA6IDA7XG5cbiAgICAgICAgICAgIHRoaXMuc2luZ2xlU2Nhbih0aGlzLnNjYW5CbGFzdERhdGFbbnVtXSk7XG4gICAgICAgICAgICB0aGlzLnNjYW4oKTtcbiAgICAgICAgICAgIHRoaXMuaWRTY2FuID0gdGhpcy5zY2FuQmxhc3REYXRhW251bV0uc2lkZTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdJRCBTSURFJywgdGhpcy5pZFNjYW4pO1xuXG4gICAgICAgICAgICB0aGlzLmRpc3BsYXlJbmZvID0gJ1BsZWFzZSB0dXJuIHRoZSBkb2N1bWVudCBvdmVyISc7XG4gICAgICAgICAgICB0aGlzLnZhbGlkYXRpb24gPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5zY2FuQmxhc3REYXRhWzBdLmltYWdlID0gaW1hZ2U7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdVUExPQUQnKTtcbiAgICAgICAgICBpZiAodHlwZSA9PSAnd29ya2VyJykge1xuICAgICAgICAgICAgdGhpcy5pbWFnZUhhbmRsZXIubmV4dCh7IHR5cGU6ICdzdG9wJyB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5zY2FuQmxhc3RGaW5pc2goKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2Nhbm5lZEltYWdlcyA9IFtdO1xuXG4gICAgICAgIC8vIHRoaXMuc2NhbkJsYXN0RGF0YVswXS5pbWFnZSA9IHNlbGVjdGVkSW1hZ2U7XG5cbiAgICAgICAgLy90aGlzLnNjYW5CbGFzdEZpbmlzaCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWxpZGF0aW9uID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgaGFuZGxlSW5pdEVycm9yKGVycm9yOiBXZWJjYW1Jbml0RXJyb3IpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gIH1cblxuICBnZXQgc2NhbkJsYXN0Q2FuVXBsb2FkKCkge1xuICAgIHJldHVybiB0aGlzLnNjYW5CbGFzdERhdGFbMF0uaW1hZ2UgPyB0cnVlIDogZmFsc2U7XG4gIH1cbiAgcHVibGljIGNhbWVyYVdhc1N3aXRjaGVkKGRldmljZUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZygnW2FjdGl2ZSBkZXZpY2VdJywgZGV2aWNlSWQpO1xuICAgIHRoaXMuZGV2aWNlSWQgPSBkZXZpY2VJZDtcbiAgICB0aGlzLmNhbWVyYVJlYWR5ID0gdHJ1ZTtcbiAgICB0aGlzLmRlZmF1bHREZXZpY2UgPSBkZXZpY2VJZDtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5vblJlc2l6ZSgpO1xuICAgICAgdGhpcy5zY2FuKCk7XG4gICAgfSwgMzAwKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgbmV4dFdlYmNhbU9ic2VydmFibGUoKTogT2JzZXJ2YWJsZTxib29sZWFuIHwgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMubmV4dFdlYmNhbS5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlTG9uZ1ZhbGlkYXRpb25FcnJvcihpbWc6IGFueSkge1xuICAgIC8vIHNhdmUgY3VycmVudCBpbWFnZSBhZnRlciAxMHNlY1xuXG4gICAgY29uc3QgZGlmZiA9IChEYXRlLm5vdygpIC0gdGhpcy5zdGFydFRpbWUpIC8gMTAwMDtcblxuICAgIGlmIChkaWZmID4gMTUgJiYgIXRoaXMudmVyaWZpY2F0aW9uRXJyb3JTZW50KSB7XG4gICAgICB0aGlzLnZlcmlmaWNhdGlvbkVycm9yU2VudCA9IHRydWU7XG4gICAgICBjb25zdCBkYXRhVXJsID0gdGhpcy5oYW5kbGVCaXRtYXBJbWFnZShpbWcuYml0bWFwKTtcblxuICAgICAgY29uc29sZS53YXJuKCdTRU5UJyk7XG4gICAgICB0aGlzLmRpc3BsYXlJbmZvID0gJ0NhbnQgZGV0ZWN0IGRvY3VtZW50ISc7XG4gICAgICB0aGlzLmxvZ0RhdGEuUmVxdWVzdCA9IHRoaXMuc2NhblByb3ZpZGVyXG4gICAgICAgIC5zZW5kTG9nKHtcbiAgICAgICAgICBBY2NlcHRUZXJtc0FuZENvbmRpdGlvbnM6IHRydWUsXG4gICAgICAgICAgRXhwZWN0ZWRPdXRwdXQ6IHt9LFxuICAgICAgICAgIFJlcXVlc3Q6IHtcbiAgICAgICAgICAgIHZlcmlmaWNhdGlvbjogZGF0YVVybC5zcGxpdCgnLCcpWzFdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgUmVzcG9uc2U6IHtcbiAgICAgICAgICAgIFRyYW5zYWN0aW9uSUQ6IHV1aWR2NCgpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIHRoaXMuYXV0b1NjYW4oKTtcblxuICAgIHRoaXMuaW1hZ2VIYW5kbGVyU3Vic2NyaXB0aW9uID0gdGhpcy5pbWFnZUhhbmRsZXIuc3Vic2NyaWJlKFxuICAgICAgKHdlYmNhbUltYWdlOiBhbnkpID0+IHtcbiAgICAgICAvLyByZXR1cm47XG4gICAgICAgIGlmICh0aGlzLnN0YXJ0VGltZSA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgaWYgKHdlYmNhbUltYWdlLmJhc2U2NCkge1xuICAgICAgICAgICAgY29uc3QgdGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zY2FuSW1hZ2VUaW1lc3RhbXBzLmxvYWQgPiAwKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgbG9hZCB9ID0gdGhpcy5zY2FuSW1hZ2VUaW1lc3RhbXBzO1xuICAgICAgICAgICAgICBjb25zdCBkaWZmID0gdGltZSAtIGxvYWQ7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignVElNRScsIGRpZmYpO1xuICAgICAgICAgICAgICB0aGlzLnNjYW5EZWxheSA9IGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuc2NhbkltYWdlVGltZXN0YW1wcy5sb2FkID0gdGltZTtcblxuICAgICAgICAgICAgdGhpcy5zY2FubmVkSW1hZ2VzLnB1c2god2ViY2FtSW1hZ2UpO1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVMb25nVmFsaWRhdGlvbkVycm9yKHdlYmNhbUltYWdlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICBpZiAodGhpcy5zY2FubmVkSW1hZ2VzLmxlbmd0aCA+IDQgJiYgIXRoaXMudmFsaWRhdGlvbikge1xuICAgICAgICAgICAgLy8gZ2V0IGxhc3QgMTBcbiAgICAgICAgICAgIGNvbnNvbGUudGltZUVuZCgndmFsaWRhdGlvblRPVEFMX1VJJyk7XG4gICAgICAgICAgICBjb25zb2xlLnRpbWUoJ3ZhbGlkYXRpb25UT1RBTF9VSScpO1xuICAgICAgICAgICAgY29uc3QgaW1hZ2VzID0gdGhpcy5zY2FubmVkSW1hZ2VzLnNsaWNlKC01KTtcbiAgICAgICAgICAgIC8vIHNldCBpbWFnZXMgdG8gMFxuICAgICAgICAgICAgdGhpcy5zY2FubmVkSW1hZ2VzID0gW107XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhpbWFnZXMpO1xuXG4gICAgICAgICAgICBjb25zdCBpbWFnZXNBcnJheSA9IGltYWdlcy5tYXAoKG0pID0+IG0uYmFzZTY0LnNwbGl0KCcsJylbMV0pO1xuICAgICAgICAgICAgdGhpcy52YWxpZGF0aW9uID0gdHJ1ZTtcblxuICAgICAgICAgICAgdGhpcy5oYW5kbGVCdXJzdERhdGEoaW1hZ2VzQXJyYXksIGltYWdlcywgJ3dvcmtlcicpO1xuXG4gICAgICAgICAgICBjb25zb2xlLnRpbWUoJ3ZhbGlkYXRpb25QT1NUJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgaGFuZGxlQml0bWFwSW1hZ2UoYml0bWFwOiBhbnkpIHtcbiAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IGJpdG1hcDtcblxuICAgIGNvbnN0IG9mZnNjcmVlblNtYWxsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgb2Zmc2NyZWVuU21hbGwud2lkdGggPSB3aWR0aDtcbiAgICBvZmZzY3JlZW5TbWFsbC5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgY29uc3QgY3R4OiBhbnkgPSBvZmZzY3JlZW5TbWFsbC5nZXRDb250ZXh0KCdiaXRtYXByZW5kZXJlcicpO1xuXG4gICAgaWYgKGN0eCkge1xuICAgICAgY3R4LmltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGZhbHNlO1xuICAgICAgY3R4LnRyYW5zZmVyRnJvbUltYWdlQml0bWFwKGJpdG1hcCk7XG4gICAgICBiaXRtYXAuY2xvc2UoKTtcbiAgICAgIGNvbnN0IGRhdGEgPSBjdHguY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvanBlZycpO1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgYXV0b1NjYW4oKSB7XG4gICAgY29uc3Qgc2lkZSA9IHRoaXMuc2NhbkJsYXN0RGF0YVswXTtcbiAgICB0aGlzLmlkU2NhbiA9IG51bGw7XG4gICAgdGhpcy5zaW5nbGVTY2FuKHNpZGUpO1xuICB9XG5cbiAgc2VsZWN0Q2FtZXJhKGV2ZW50OiBhbnkpIHtcbiAgICB0aGlzLmNhbWVyYVJlYWR5ID0gZmFsc2U7XG4gICAgdGhpcy5uZXh0V2ViY2FtLm5leHQoZXZlbnQudmFsdWUpO1xuICAgIHRoaXMuc2NhbkluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgfVxuICBjbG9zZSgpIHtcbiAgICB0aGlzLmRpYWxvZ1JlZj8uY2xvc2UoKTtcbiAgfVxuICBzaW5nbGVTY2FuKHNpZGU6IGFueSkge1xuICAgIHRoaXMuc2NhblR5cGUgPSBzaWRlLnNpZGU7XG4gICAgdGhpcy5wcmV2aWV3ID0gbnVsbDtcbiAgICB0aGlzLnNlbGVjdGVkU2lkZSA9IHNpZGU7XG5cbiAgICB0aGlzLnNlbGVjdGVkU2lkZS5pbWFnZSA9IG51bGw7XG4gICAgdGhpcy5kb2N1bWVudFR5cGVTZWxlY3RlZCA9IHRydWU7XG4gICAgdGhpcy5zY2FuQmxhc3REYXRhWzFdLmRpc2FibGVkID0gZmFsc2U7XG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLm9uUmVzaXplKCk7XG4gICAgfSwgMTApO1xuICB9XG4gIGdldEJhc2U2NChmaWxlOiBhbnkpIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7XG4gICAgICByZWFkZXIub25sb2FkID0gKCkgPT4ge1xuICAgICAgICBvYnNlcnZlci5uZXh0KHJlYWRlci5yZXN1bHQpO1xuICAgICAgfTtcbiAgICAgIHJlYWRlci5vbmVycm9yID0gKGVycm9yKSA9PiB7XG4gICAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVGaWxlSW5wdXQodGFyZ2V0OiBhbnksIGV2ZW50OiBhbnksIHNpZGU6IGFueSkge1xuICAgIGNvbnN0IGZpbGVzOiBGaWxlTGlzdCA9IHRhcmdldC5maWxlcztcbiAgICB0aGlzLnNlbGVjdGVkU2lkZSA9IHNpZGU7XG4gICAgY29uc29sZS5sb2coZmlsZXMpO1xuICAgIGNvbnN0IGZpbGUgPSBmaWxlcy5pdGVtKDApO1xuXG4gICAgdGhpcy5yZXNvbHV0aW9uTGltaXQoZmlsZSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKHZhbGlkOiBhbnkpID0+IHtcbiAgICAgICAgICByZXR1cm4gdmFsaWQgPyB0aGlzLmdldEJhc2U2NChmaWxlKSA6IG9mKGZhbHNlKTtcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKGltYWdlQXNEYXRhVXJsKSA9PiB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGltYWdlQXNEYXRhVXJsKTtcbiAgICAgICAgZXZlbnQudGFyZ2V0LnZhbHVlID0gbnVsbDtcbiAgICAgICAgaWYgKCFpbWFnZUFzRGF0YVVybCkge1xuICAgICAgICAgIHRoaXMuZGlhbG9ncy5hbGVydChcbiAgICAgICAgICAgICdjb3JlLnBhZ2UuZXJyb3InLFxuICAgICAgICAgICAgdGhpcy50cmFuc2xhdGUuaW5zdGFudChcbiAgICAgICAgICAgICAgJ3Btcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUubWluUmVzb2x1dGlvbidcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNpZGUuaW1hZ2UgPSB7XG4gICAgICAgICAgICBpbWFnZUFzRGF0YVVybCxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkU2lkZS5zaWRlID09PSAnRlJPTlQnKSB7XG4gICAgICAgICAgICB0aGlzLnNjYW5CbGFzdERhdGFbMV0uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9KTtcbiAgfVxuICByb3RhdGVCYXNlNjRJbWFnZShiYXNlNjRkYXRhOiBhbnkpIHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgICBpbWFnZS5zcmMgPSBiYXNlNjRkYXRhO1xuICAgICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhjYW52YXMpO1xuICAgICAgICBjYW52YXMud2lkdGggPSBpbWFnZS5oZWlnaHQ7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBpbWFnZS53aWR0aDtcbiAgICAgICAgaWYgKGN0eCkge1xuICAgICAgICAgIGN0eC5yb3RhdGUoKDkwICogTWF0aC5QSSkgLyAxODApO1xuICAgICAgICAgIGN0eC50cmFuc2xhdGUoMCwgLWNhbnZhcy53aWR0aCk7XG4gICAgICAgICAgY3R4LmRyYXdJbWFnZShpbWFnZSwgMCwgMCk7XG4gICAgICAgICAgb2JzZXJ2ZXIubmV4dChjYW52YXMudG9EYXRhVVJMKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9ic2VydmVyLmVycm9yKHsgdHlwZTogJ2dlbmVyaWMgZXJyb3InIH0pO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaW1hZ2Uub25lcnJvciA9IChlKSA9PiB7XG4gICAgICAgIG9ic2VydmVyLmVycm9yKGUpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIHNlbmRNb2JpbGUoKSB7XG4gICAgdGhpcy5kaWFsb2dzLnNjYW5Nb2JpbGUoeyBpZDogMSB9KTtcbiAgfVxuICBzaW5nbGVTY2FuUm90YXRlKHNpZGU6IGFueSkge1xuICAgIGNvbnNvbGUubG9nKHNpZGUpO1xuICAgIHRoaXMucm90YXRlQmFzZTY0SW1hZ2Uoc2lkZS5pbWFnZS5pbWFnZUFzRGF0YVVybCkuc3Vic2NyaWJlKChkYXRhKSA9PiB7XG4gICAgICBzaWRlLmltYWdlID0geyBpbWFnZUFzRGF0YVVybDogZGF0YSB9O1xuICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgfSk7XG4gIH1cblxuICBzaW5nbGVTY2FuUmVtb3ZlKHNpZGU6IGFueSkge1xuICAgIHNpZGUuaW1hZ2UgPSBudWxsO1xuICAgIGlmIChzaWRlLnNpZGUgPT09ICdGUk9OVCcpIHtcbiAgICAgIHRoaXMuc2NhbkJsYXN0RGF0YVsxXS5kaXNhYmxlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICByZXNvbHV0aW9uTGltaXQoZmlsZTogYW55KSB7XG4gICAgY29uc3QgbWluV2lkdGggPSAxMjgwO1xuICAgIGNvbnN0IG1pbkhlaWdodCA9IDcyMDtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9ic2VydmVyKSA9PiB7XG4gICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgIGltZy5zcmMgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcbiAgICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHdpZHRoID0gaW1nLm5hdHVyYWxXaWR0aDtcbiAgICAgICAgY29uc3QgaGVpZ2h0ID0gaW1nLm5hdHVyYWxIZWlnaHQ7XG5cbiAgICAgICAgbGV0IHZhbGlkID0gZmFsc2U7XG4gICAgICAgIGlmICh3aWR0aCA+IGhlaWdodCkge1xuICAgICAgICAgIHZhbGlkID0gd2lkdGggPj0gbWluV2lkdGggJiYgaGVpZ2h0ID49IG1pbkhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWxpZCA9IHdpZHRoID49IG1pbkhlaWdodCAmJiBoZWlnaHQgPj0gbWluV2lkdGg7XG4gICAgICAgIH1cblxuICAgICAgICBvYnNlcnZlci5uZXh0KHZhbGlkKTtcbiAgICAgIH07XG4gICAgICBpbWcub25lcnJvciA9IChlcnJvcikgPT4ge1xuICAgICAgICBvYnNlcnZlci5lcnJvcihlcnJvcik7XG4gICAgICB9O1xuICAgIH0pO1xuICB9XG4gIHByaXZhdGUgZ2V0SW1nQmFzZTY0KG51bTogYW55KSB7XG4gICAgY29uc29sZS5sb2coJ0dFVCA2NCcpO1xuICAgIHJldHVybiB0aGlzLnNjYW5CbGFzdERhdGFbbnVtXS5pbWFnZS5kYXRhVXJsLnNwbGl0KCcsJylbMV07XG4gIH1cbiAgc2NhbkJsYXN0RmluaXNoKCkge1xuICAgIGNvbnNvbGUudGltZSgndXBsb2FkJyk7XG4gICAgaWYgKHRoaXMudHlwZSA9PT0gJ21vYmlsZScpIHtcbiAgICAgIHRoaXMuYWN0aW9ucy5lbWl0KHsgZGF0YTogdGhpcy5zY2FuQmxhc3REYXRhIH0pO1xuICAgICAgdGhpcy5yZXRha2UoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5pZFNjYW4gPSBudWxsO1xuICAgIC8vIGNvbnN0IGxvYWRpbmcgPSB0aGlzLmRpYWxvZ3MubG9hZGluZygpO1xuICAgIHRoaXMuc2NhbmluZyA9IHRydWU7XG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgY29uc29sZS50aW1lKCdwYXlsb2FkJyk7XG4gICAgY29uc3QgcGF5bG9hZDogYW55ID0ge1xuICAgICAgQWNjZXB0VGVybXNBbmRDb25kaXRpb25zOiB0cnVlLFxuICAgICAgRGF0YUZpZWxkczoge1xuICAgICAgICBGcm9udEltYWdlVHlwZTogJ2Jhc2U2NCcsXG4gICAgICAgIEZyb250SW1hZ2VDcm9wcGVkOiBmYWxzZSxcbiAgICAgICAgQmFja0ltYWdlVHlwZTogJ2Jhc2U2NCcsXG4gICAgICAgIEJhY2tJbWFnZUNyb3BwZWQ6IGZhbHNlLFxuICAgICAgICBGcm9udEltYWdlOiB0aGlzLmdldEltZ0Jhc2U2NCgwKSxcbiAgICAgICAgQmFja0ltYWdlOiB0aGlzLnNjYW5CbGFzdERhdGFbMV0uaW1hZ2UgPyB0aGlzLmdldEltZ0Jhc2U2NCgxKSA6IG51bGwsXG4gICAgICB9LFxuICAgICAgU2V0dGluZ3M6IHtcbiAgICAgICAgU2hvdWxkVmFsaWRhdGU6IHRydWUsXG4gICAgICAgIFNob3VsZFJldHVybkRvY3VtZW50SW1hZ2U6IHRydWUsXG4gICAgICAgIFNob3VsZFJldHVybkZhY2VJZkRldGVjdGVkOiB0cnVlLFxuICAgICAgICBTa2lwSW1hZ2VTaXplQ2hlY2s6IHRydWUsXG4gICAgICAgIENhblN0b3JlSW1hZ2VzOiB0aGlzLnNjYW5Qcm92aWRlci5jYW5TdG9yZUltYWdlcyxcbiAgICAgIH0sXG4gICAgICAvLyBDYWxsQmFja1VybDogJ2h0dHA6Ly9kZW1vOjUwMDAvcmVwb3J0L2V4dHJhY3RlZC8nLFxuICAgIH07XG4gICAgaWYgKCF0aGlzLnNjYW5CbGFzdERhdGFbMV0uaW1hZ2UpIHtcbiAgICAgIHBheWxvYWQuU2V0dGluZ3MuSWdub3JlQmFja0ltYWdlID0gdHJ1ZTtcbiAgICB9XG4gICAgdGhpcy5sb2dEYXRhLlJlcXVlc3QgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcblxuICAgIGNvbnNvbGUudGltZUVuZCgncGF5bG9hZCcpO1xuICAgIHRoaXMuc2NhblByb3ZpZGVyXG4gICAgICAuYmxhc3RQb3N0KHBheWxvYWQpXG5cbiAgICAgIC5zdWJzY3JpYmUoXG4gICAgICAgIChkYXRhOiBhbnkpID0+IHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKGRhdGEpO1xuICAgICAgICAgIGNvbnN0IHJlc3VsdHMgPSBkYXRhLkRhdGE7XG4gICAgICAgICAgY29uc29sZS50aW1lRW5kKCd1cGxvYWQnKTtcbiAgICAgICAgICBjb25zb2xlLnRpbWUoJ3BhcnNlJyk7XG4gICAgICAgICAgLy8gZGF0YS5JbmZvQ29kZSA9ICcxMDAxJztcbiAgICAgICAgICB0aGlzLmxvZ0RhdGEuUmVzcG9uc2UgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGRhdGEpKTtcbiAgICAgICAgICAvL2xvYWRpbmcuY2xvc2UoKTtcbiAgICAgICAgICB0aGlzLmRvY3VtZW50VHlwZVNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLnNjYW5pbmcgPSBmYWxzZTtcblxuICAgICAgICAgIGlmIChkYXRhLkluZm9Db2RlID09PSAnMTAwMScpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ1tFUlJPUl0gMTAwMScpO1xuICAgICAgICAgICAgdGhpcy5lcnJvckNvZGUgPSAnMTAwMSc7XG4gICAgICAgICAgICAvLyB0aGlzLnNjYW5TaWRlID0gMDtcblxuICAgICAgICAgICAgdGhpcy5wcmV2aWV3ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZGF0YS5JbmZvQ29kZSA9PT0gJzEwMDInKSB7XG4gICAgICAgICAgICB0aGlzLmVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdbRVJST1JdIDEwMDInKTtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JDb2RlID0gJzEwMDInO1xuICAgICAgICAgICAgLy8gdGhpcy5zY2FuU2lkZSA9IDA7XG5cbiAgICAgICAgICAgIHRoaXMucHJldmlldyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHJlc3VsdHMgJiYgZGF0YS5NZXRhZGF0YS5sZW5ndGggPiAwICYmIGRhdGEuSW5mb0NvZGUgPT09ICcxMDAwJykge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ0V4dHJhY3Rpb24gdGltZScsIGRhdGEuQW5hbHlzaXNUaW1lKTtcbiAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZGF0YS5JbWFnZURhdGE/LkRvY3VtZW50cykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgRG9jdW1lbnRzIH0gPSBkYXRhLkltYWdlRGF0YTtcbiAgICAgICAgICAgICAgICB0aGlzLmltYWdlcyA9IERvY3VtZW50cy5tYXAoKGltYWdlOiBhbnksIGk6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZGF0YTogJ2RhdGE6aW1hZ2UvanBlZztiYXNlNjQsJyArIERvY3VtZW50c1tpXSB9O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgdGhpcy5yZXN1bHQgPSB0aGlzLnNjYW5Qcm92aWRlci5wYXJzZUJsYXN0KHJlc3VsdHMpO1xuICAgICAgICAgICAgICBjb25zb2xlLmxvZygnUkVTJywgdGhpcy5yZXN1bHQpO1xuICAgICAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcblxuICAgICAgICAgICAgICB0aGlzLm1vZGVsID0gdGhpcy5yZXN1bHQubW9kZWw7XG4gICAgICAgICAgICAgIGlmIChkYXRhLkltYWdlRGF0YT8uRmFjZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tb2RlbC5fYXZhdGFyID1cbiAgICAgICAgICAgICAgICAgICdkYXRhOmltYWdlL2pwZWc7YmFzZTY0LCcgKyBkYXRhLkltYWdlRGF0YT8uRmFjZUltYWdlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdNT0RFTCcsIHRoaXMubW9kZWwpO1xuICAgICAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnRVJST1InKTtcbiAgICAgICAgICAgIC8vIHRoaXMuc2NhblNpZGUgPSAwO1xuICAgICAgICAgICAgdGhpcy5lcnJvciA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnByZXZpZXcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgICAvLyB0aGlzLmRvY3VtZW50VHlwZVNlbGVjdGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIHRoaXMucmV0cnkoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICBjb25zb2xlLnRpbWVFbmQoJ3BhcnNlJyk7XG4gICAgICAgIH0sXG4gICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAvLyBsb2FkaW5nLmNsb3NlKCk7XG4gICAgICAgICAgLy8gdGhpcy5zY2FuU2lkZSA9IDA7XG4gICAgICAgICAgdGhpcy5lcnJvciA9IHRydWU7XG4gICAgICAgICAgdGhpcy5wcmV2aWV3ID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLmRvY3VtZW50VHlwZVNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLnNjYW5pbmcgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgfVxuICBjYW1lcmFPZmYoZXY6IGFueSkge1xuICAgIHRoaXMuY2FtZXJhUmVhZHkgPSBmYWxzZTtcbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuICBjb250aW51ZSgpIHtcbiAgICB0aGlzLmRvY3VtZW50VHlwZVNlbGVjdGVkID0gZmFsc2U7XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRTaWRlLmltYWdlID0gdGhpcy53ZWJjYW1JbWFnZTtcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkU2lkZS5zaWRlID09PSAnRlJPTlQnKSB7XG4gICAgICAgIHRoaXMuc2NhbkJsYXN0RGF0YVsxXS5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgfSwgMjAwKTtcbiAgfVxuICByZXRyeSgpIHtcbiAgICB0aGlzLnByZXZpZXcgPSBmYWxzZTtcbiAgICB0aGlzLnZhbGlkYXRpb24gPSBmYWxzZTtcbiAgICB0aGlzLmVycm9yQ29kZSA9ICcxMDAwJztcbiAgICB0aGlzLnJlc3VsdCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmVycm9yKSB7XG4gICAgICB0aGlzLmRvY3VtZW50VHlwZVNlbGVjdGVkID0gZmFsc2U7XG4gICAgICB0aGlzLnNjYW5CbGFzdERhdGEuZm9yRWFjaCgoZWxlbWVudDogYW55KSA9PiB7XG4gICAgICAgIGVsZW1lbnQuaW1hZ2UgPSBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMuZXJyb3IgPSBmYWxzZTtcbiAgICB0aGlzLmF1dG9TY2FuKCk7XG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cbiAgcHVibGljIHRyaWdnZXJTbmFwc2hvdCgpOiB2b2lkIHtcbiAgICB0aGlzLnRyaWdnZXIubmV4dCgwKTtcbiAgfVxuXG4gIHB1YmxpYyByZXRha2UoKSB7XG4gICAgdGhpcy52YWxpZGF0aW9uID0gZmFsc2U7XG4gICAgdGhpcy5wcmV2aWV3ID0gZmFsc2U7XG4gICAgdGhpcy5lcnJvciA9IGZhbHNlO1xuICAgIHRoaXMucmVzdWx0ID0gZmFsc2U7XG4gICAgdGhpcy5zY2FuU2lkZSA9IDA7XG5cbiAgICB0aGlzLmltYWdlVmVyaWZpZWQgPSBmYWxzZTtcbiAgICB0aGlzLnNjYW5EYXRhcyA9IFtdO1xuICAgIHRoaXMuc2NhbmluZyA9IGZhbHNlO1xuICAgIHRoaXMuaW1hZ2VzID0gW107XG4gICAgdGhpcy5zY2FuSW5Qcm9ncmVzcyA9IGZhbHNlO1xuXG4gICAgdGhpcy5kb2N1bWVudFR5cGVTZWxlY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuc2NhbkJsYXN0RGF0YS5mb3JFYWNoKChtOiBhbnkpID0+IHtcbiAgICAgIG0uaW1hZ2UgPSBudWxsO1xuICAgIH0pO1xuXG4gICAgdGhpcy5hdXRvU2NhbigpO1xuXG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cbiAgY2FuY2VsKCkge1xuICAgIHRoaXMuZG9jdW1lbnRUeXBlU2VsZWN0ZWQgPSBmYWxzZTtcbiAgfVxuICB1c2UoKSB7XG4gICAgLy8gc2F2ZSBpbWFnZXM/P1xuXG4gICAgaWYgKHRoaXMuc2NhblByb3ZpZGVyLmNhblN0b3JlSW1hZ2VzKSB7XG4gICAgICB0aGlzLmxvZ0RhdGEuRXhwZWN0ZWRPdXRwdXQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMubW9kZWwpKTtcbiAgICAgIGlmICh0aGlzLmxvZ0RhdGEuRXhwZWN0ZWRPdXRwdXQ/Ll9hdmF0YXIpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMubG9nRGF0YS5FeHBlY3RlZE91dHB1dC5fYXZhdGFyO1xuICAgICAgfVxuICAgICAgdGhpcy5zY2FuUHJvdmlkZXIuc2VuZExvZyh0aGlzLmxvZ0RhdGEpLnN1YnNjcmliZSgpO1xuICAgICAgY29uc29sZS5sb2codGhpcy5sb2dEYXRhKTtcbiAgICB9XG4gICAgdGhpcy5kaWFsb2dSZWY/LmNsb3NlKHtcbiAgICAgIG1vZGVsOiB0aGlzLm1vZGVsLFxuICAgICAgaW1hZ2VzOiB0aGlzLmltYWdlcyxcbiAgICB9KTtcbiAgfVxuICBzZWxmaWUoKSB7XG4gICAgdGhpcy5kaWFsb2dzXG4gICAgICAuc2NhblNlbGZpZSh7IGF2YXRhcjogdGhpcy5tb2RlbC5fYXZhdGFyIH0pXG4gICAgICAuYWZ0ZXJDbG9zZWQoKVxuICAgICAgLnN1YnNjcmliZSgocmVzcCkgPT4ge1xuICAgICAgICBpZiAocmVzcCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKHJlc3ApO1xuICAgICAgICAgIGlmICh0aGlzLnNjYW5Qcm92aWRlci5lbmFibGVWZXJpZmljYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VWZXJpZmllZCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMubW9kZWwuX2F2YXRhciA9IHJlc3AuaW1hZ2VBc0RhdGFVcmw7XG4gICAgICAgICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgdmlkZW9SZWFkeShldmVudDogYm9vbGVhbikge1xuICAgIHRoaXMuY2FtZXJhUmVhZHkgPSBldmVudDtcbiAgICBpZiAodGhpcy5jYW1lcmFSZWFkeSAmJiAhdGhpcy5zY2FuSW5Qcm9ncmVzcykge1xuICAgICAgdGhpcy5zY2FuSW5Qcm9ncmVzcyA9IHRydWU7XG5cbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnRyaWdnZXIubmV4dChuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgICB9LCAxMDAwKTtcbiAgICB9XG4gIH1cbn1cbiIsIjwhLS0gPGRpdiAqbmdJZj1cImlzRGVidWdcIiBjbGFzcz1cImRlYnVnXCI+XG4gIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGltZyBvZiBzY2FubmVkSW1hZ2VzOyBsZXQgaW5kZXggPSBpbmRleFwiPlxuICAgIDxkaXYgc3R5bGU9XCJkaXNwbGF5OiBmbGV4OyBmbGV4LWRpcmVjdGlvbjogY29sdW1uXCI+XG4gICAgICA8aW1nIFtzcmNdPVwiaW1nLmltYWdlUmVzaXplZFwiIC8+XG4gICAgICB7eyBpbmRleCB9fVxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PiAtLT5cblxuPGhlYWRlciBjbGFzcz1cInBhZ2UtaGVhZGVyXCI+XG4gIDxkaXYgY2xhc3M9XCJ0aXRsZVwiIG5nQ2xhc3MubHQtc209XCJ0aXRsZS1zbWFsbFwiPlNjYW48L2Rpdj5cblxuICA8c3BhbiBmeEZsZXg+PC9zcGFuPlxuXG4gIDwhLS0gPG1hdC1zbGlkZS10b2dnbGUgc3R5bGU9XCJtYXJnaW46MHB4IDIwcHhcIiBbKG5nTW9kZWwpXT1cImlzRGVidWdcIlxuICAgID5EZWJ1ZzwvbWF0LXNsaWRlLXRvZ2dsZVxuICA+IC0tPlxuXG4gIDxuZy1jb250YWluZXJcbiAgICAqbmdJZj1cIlxuICAgICAgZG9jdW1lbnRUeXBlU2VsZWN0ZWQgJiZcbiAgICAgICFyZXN1bHQgJiZcbiAgICAgICFlcnJvciAmJlxuICAgICAgbXVsdGlwbGVXZWJjYW1zQXZhaWxhYmxlICYmXG4gICAgICAhcHJldmlld1xuICAgIFwiXG4gID5cbiAgICA8ZGl2IGNsYXNzPVwic2VwYXJhdG9yXCI+PC9kaXY+XG4gICAgPGRpdiBzdHlsZT1cInBhZGRpbmc6IDBweCAxNnB4XCI+XG4gICAgICA8ZGl2IGZ4TGF5b3V0PVwicm93XCIgZnhMYXlvdXRBbGlnbj1cImVuZCBjZW50ZXJcIj5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkXG4gICAgICAgICAgc3R5bGU9XCJmb250LXNpemU6IDE0cHg7IHdpZHRoOiAyMDBweDsgbWFyZ2luLXRvcDogOHB4XCJcbiAgICAgICAgICBjbGFzcz1cInctMTAwIG1yLTE2IG10LThcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1sYWJlbD4gQ2FtZXJhIDwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cInNlbGVjdENhbWVyYSgkZXZlbnQpXCJcbiAgICAgICAgICAgIFsobmdNb2RlbCldPVwiZGV2aWNlSWRcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxtYXQtb3B0aW9uXG4gICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBkZXZpY2Ugb2YgbWVkaWFEZXZpY2VzXCJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImRldmljZS5kZXZpY2VJZFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IGRldmljZS5sYWJlbCB9fVxuICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cblxuICA8bmctY29udGFpbmVyICpuZ0lmPVwidHlwZSA9PT0gJ2Rlc2t0b3AnXCI+XG4gICAgPCEtLSA8ZGl2ICBjbGFzcz1cInNlcGFyYXRvclwiPjwvZGl2PlxuICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cInNlbmRNb2JpbGUoKVwiPlxuICAgIDxtYXQtaWNvbj50YWJsZXRfbWFjPC9tYXQtaWNvbj5cbiAgPC9idXR0b24+IC0tPlxuXG4gICAgPGRpdiBjbGFzcz1cInNlcGFyYXRvclwiPjwvZGl2PlxuXG4gICAgPGJ1dHRvbiBtYXQtYnV0dG9uIChjbGljayk9XCJjbG9zZSgpXCI+XG4gICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgIDwvYnV0dG9uPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvaGVhZGVyPlxuXG48ZGl2ICpuZ0lmPVwicmVzdWx0XCIgZnhGbGV4IGZ4TGF5b3V0PVwiY29sdW1uXCI+XG4gIDwhLS0gPGRpdiAqbmdJZj1cInJlc3VsdFwiIGZ4RmxleCBmeExheW91dD1cImNvbHVtblwiPiAtLT5cbiAgPGRpdlxuICAgIGZ4RmxleFxuICAgICN3cmFwZXJcbiAgICBjbGFzcz1cIndyYXBlclwiXG4gICAgZnhMYXlvdXQ9XCJyb3dcIlxuICAgIHN0eWxlPVwib3ZlcmZsb3c6IGF1dG9cIlxuICAgIHByb3RlbFBlcmZlY3RTY3JvbGxiYXJcbiAgICBjbGFzcz1cInB0LTggcHItOFwiXG4gICAgZnhMYXlvdXQubHQtbWQ9XCJjb2x1bW5cIlxuICA+XG4gICAgPGRpdiBmeEZsZXggY2xhc3M9XCJcIj5cbiAgICAgIDxkaXYgZnhGbGV4PlxuICAgICAgICA8bWF0LWNhcmQgc3R5bGU9XCJtYXJnaW46IDRweDsgcGFkZGluZzogNHB4IDE2cHhcIj5cbiAgICAgICAgICA8aDM+QXZhdGFyPC9oMz5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBzdHlsZT1cImRpc3BsYXk6IGZsZXg7IGZsZXgtZGlyZWN0aW9uOiByb3c7IGFsaWduLWl0ZW1zOiBjZW50ZXJcIlxuICAgICAgICAgICAgY2xhc3M9XCJzZWxmaWVDb250YWluZXJcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWxmaWVcIiBzdHlsZT1cIndpZHRoOiAyMDBweFwiPlxuICAgICAgICAgICAgICA8aW1nXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJtb2RlbD8uX2F2YXRhclwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJwcmV2aWV3XCJcbiAgICAgICAgICAgICAgICBzdHlsZT1cIndpZHRoOiAxMjBweDsgaGVpZ2h0OiAxMjBweDsgYm9yZGVyLXJhZGl1czogNjBweFwiXG4gICAgICAgICAgICAgICAgW3NyY109XCJtb2RlbC5fYXZhdGFyXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaW1hZ2VWZXJpZmllZFwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJzZWxmaWUoKVwiXG4gICAgICAgICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIFRha2Ugc2VsZmllXG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9tYXQtY2FyZD5cblxuICAgICAgICA8Zm9ybVxuICAgICAgICAgIGZ4TGF5b3V0PVwicm93XCJcbiAgICAgICAgICBmeExheW91dEFsaWduPVwic3RhcnQgY2VudGVyXCJcbiAgICAgICAgICBjbGFzcz1cInB4LTE2IHB5LTAgdy0xMDAtcFwiXG4gICAgICAgICAgW2Zvcm1Hcm91cF09XCJmb3JtXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxmb3JtbHktZm9ybVxuICAgICAgICAgICAgbmdDbGFzcy5sdC1tZD1cIm1vYmlsZVwiXG4gICAgICAgICAgICBmeEZsZXhcbiAgICAgICAgICAgIFtmb3JtXT1cImZvcm1cIlxuICAgICAgICAgICAgW2ZpZWxkc109XCJmaWVsZHNcIlxuICAgICAgICAgICAgW21vZGVsXT1cIm1vZGVsXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9mb3JtbHktZm9ybT5cbiAgICAgICAgPC9mb3JtPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBmeEZsZXggY2xhc3M9XCJwci0xNiBtLTRcIj5cbiAgICAgIDxtYXQtY2FyZCBzdHlsZT1cIm1hcmdpbjogNHB4OyBwYWRkaW5nLXRvcDogMnB4XCIgY2xhc3M9XCJpbWFnZXNcIj5cbiAgICAgICAgPGgzPkltYWdlczwvaDM+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGltZyBvZiBpbWFnZXNcIj5cbiAgICAgICAgICA8ZGl2IGZ4TGF5b3V0PVwiY29sdW1uXCI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaW1nLnNpZGUgPT09IDBcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlXCI+RnJvbnQgU2lkZTwvZGl2PlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaW1nLnNpZGUgPT09IDFcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlXCI+QmFjayBTaWRlPC9kaXY+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDxpbWdcbiAgICAgICAgICAgICAgY2xhc3M9XCJwcmV2aWV3XCJcbiAgICAgICAgICAgICAgc3R5bGU9XCJtYXgtd2lkdGg6IDQ2MHB4OyBib3JkZXItcmFkaXVzOiAxcmVtXCJcbiAgICAgICAgICAgICAgW3NyY109XCJpbWcuZGF0YVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvbWF0LWNhcmQ+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDxkaXY+PC9kaXY+XG5cbiAgPGZvb3RlciBmeExheW91dD1cInJvd1wiIGNsYXNzPVwicC04XCI+XG4gICAgPGRpdiBjbGFzcz1cInctMTAwLXBcIiBmeExheW91dD1cInJvd1wiIGZ4TGF5b3V0QWxpZ249XCJzdGFydCBjZW50ZXJcIj5cbiAgICAgIDxidXR0b24gZnhGbGV4IGNsYXNzPVwibXItOFwiIG1hdC1yYWlzZWQtYnV0dG9uIChjbGljayk9XCJyZXRha2UoKVwiPlxuICAgICAgICB7eyBcInBtcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUucmVUYWtlXCIgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBbZGlzYWJsZWRdPVwiZXJyb3IgfHwgZm9ybS5pbnZhbGlkXCJcbiAgICAgICAgZnhGbGV4XG4gICAgICAgIGNsYXNzPVwibWwtOFwiXG4gICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXG4gICAgICAgIChjbGljayk9XCJ1c2UoKVwiXG4gICAgICA+XG4gICAgICAgIHt7IFwicG1zLmRpYWxvZ3MuY29tcG9uZW50cy5zY2FuUHJvZmlsZS51c2VEYXRhXCIgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Zvb3Rlcj5cbjwvZGl2PlxuXG48ZGl2XG4gIHN0eWxlPVwicG9zaXRpb246IHJlbGF0aXZlXCJcbiAgKm5nSWY9XCIhcmVzdWx0ICYmIGRvY3VtZW50VHlwZVNlbGVjdGVkXCJcbiAgZnhGbGV4XG4gIGZ4TGF5b3V0PVwiY29sdW1uXCJcbj5cbiAgPGRpdiBmeEZsZXggI3dyYXBlciBjbGFzcz1cIndyYXBlclwiIGZ4TGF5b3V0PVwicm93XCI+XG4gICAgPGRpdlxuICAgICAgc3R5bGU9XCJcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICB0b3A6IDBweDtcbiAgICAgICAgbGVmdDogMHB4O1xuICAgICAgICByaWdodDogMHB4O1xuICAgICAgICBib3R0b206IDBweDtcbiAgICAgICAgei1pbmRleDogMjA7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHdoaXRlc21va2U7XG4gICAgICBcIlxuICAgICAgKm5nSWY9XCIhY2FtZXJhUmVhZHkgJiYgIXByZXZpZXdcIlxuICAgID5cbiAgICAgIDxtYXQtcHJvZ3Jlc3MtYmFyIG1vZGU9XCJpbmRldGVybWluYXRlXCI+PC9tYXQtcHJvZ3Jlc3MtYmFyPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiAqbmdJZj1cIiFwcmV2aWV3XCIgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IGxlZnQ6IDBweFwiPlxuICAgICAgREVMQVk6e3sgc2NhbkRlbGF5IH19XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2XG4gICAgICAqbmdJZj1cInNjYW5pbmdcIlxuICAgICAgc3R5bGU9XCJcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICB6LWluZGV4OiAyMDA7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICAgIHRvcDogMHB4O1xuICAgICAgICBsZWZ0OiAwcHg7XG4gICAgICBcIlxuICAgICAgZnhsYXlvdXQ9XCJyb3dcIlxuICAgICAgZnhMYXlvdXRBbGlnbj1cImNlbnRlciBjZW50ZXJcIlxuICAgID5cbiAgICAgIDwhLS0gPG1hdC1wcm9ncmVzcy1zcGlubmVyXG4gICAgICAgIG1vZGU9XCJpbmRldGVybWluYXRlXCJcbiAgICAgICAgY29sb3I9XCJhY2NlbnRcIlxuICAgICAgICBbc3Ryb2tlV2lkdGhdPVwiMTBcIlxuICAgICAgPjwvbWF0LXByb2dyZXNzLXNwaW5uZXI+IC0tPlxuICAgIDwvZGl2PlxuXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFlcnJvclwiPlxuICAgICAgPCEtLSA8ZGl2XG4gICAgICBjbGFzcz1cInJlY3RhbmdsZVwiXG4gICAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAgICd3aWR0aC5weCc6IHZpZGVvSGVpZ2h0ICogMC43NSAqIDEuNTg4LFxuICAgICAgICAnaGVpZ2h0LnB4JzogdmlkZW9IZWlnaHQgKiAwLjc1XG4gICAgICB9XCJcbiAgICA+PC9kaXY+XG4gICAgPHN2Z1xuICAgICAgKm5nSWY9XCJ2aWRlb1dpZHRoXCJcbiAgICAgIHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyBsZWZ0OiAwcHg7IHRvcDogMHB4XCJcbiAgICAgIHdpZHRoPVwiMFwiXG4gICAgICBoZWlnaHQ9XCIwXCJcbiAgICA+XG4gICAgICA8ZGVmcz5cbiAgICAgICAgPGNsaXBQYXRoIGlkPVwibXlDbGlwXCI+XG4gICAgICAgICAgPHJlY3RcbiAgICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjZcIlxuICAgICAgICAgICAgc3Ryb2tlLWNvbG9yPVwicmVkXCJcbiAgICAgICAgICAgIFthdHRyLnhdPVwiKHZpZGVvV2lkdGggLSB2aWRlb0hlaWdodCAqIDAuNzUgKiAxLjU4OCkgLyAyXCJcbiAgICAgICAgICAgIFthdHRyLnldPVwiKHZpZGVvSGVpZ2h0ICogMC4yNSkgLyAyXCJcbiAgICAgICAgICAgIFthdHRyLndpZHRoXT1cInZpZGVvSGVpZ2h0ICogMC43NSAqIDEuNTg4XCJcbiAgICAgICAgICAgIFthdHRyLmhlaWdodF09XCJ2aWRlb0hlaWdodCAqIDAuNzVcIlxuICAgICAgICAgICAgcng9XCIyNVwiXG4gICAgICAgICAgLz5cbiAgICAgICAgPC9jbGlwUGF0aD5cbiAgICAgIDwvZGVmcz5cbiAgICA8L3N2Zz4gLS0+XG5cbiAgICAgIDxhcHAtd2ViY2FtXG4gICAgICAgICpuZ0lmPVwiIXByZXZpZXcgJiYgIXNjYW5pbmdcIlxuICAgICAgICBjbGFzcz1cIm1haW5cIlxuICAgICAgICBbaW1hZ2VRdWFsaXR5XT1cIjFcIlxuICAgICAgICAjd2ViY2FtXG4gICAgICAgIGZ4RmxleFxuICAgICAgICB0eXBlPVwiZG9jdW1lbnRcIlxuICAgICAgICBbdHJpZ2dlcl09XCJ0cmlnZ2VyXCJcbiAgICAgICAgW2ltYWdlSGFuZGxlcl09XCJpbWFnZUhhbmRsZXJcIlxuICAgICAgICAoaW1hZ2VDYXB0dXJlKT1cImhhbmRsZUltYWdlKCRldmVudClcIlxuICAgICAgICBbYWxsb3dDYW1lcmFTd2l0Y2hdPVwiYWxsb3dDYW1lcmFTd2l0Y2hcIlxuICAgICAgICBbdmlkZW9PcHRpb25zXT1cInZpZGVvT3B0aW9uc1wiXG4gICAgICAgIFtzd2l0Y2hDYW1lcmFdPVwibmV4dFdlYmNhbU9ic2VydmFibGVcIlxuICAgICAgICAoY2FtZXJhU3dpdGNoZWQpPVwiY2FtZXJhV2FzU3dpdGNoZWQoJGV2ZW50KVwiXG4gICAgICAgIChpbml0RXJyb3IpPVwiaGFuZGxlSW5pdEVycm9yKCRldmVudClcIlxuICAgICAgICBbd2lkdGhdPVwid2lkdGhcIlxuICAgICAgICBbaGVpZ2h0XT1cImhlaWdodFwiXG4gICAgICAgIChkZXN0cm95ZWQpPVwiY2FtZXJhT2ZmKCRldmVudClcIlxuICAgICAgICAodmlkZW9SZWFkeSk9XCJ2aWRlb1JlYWR5KCRldmVudClcIlxuICAgICAgPlxuICAgICAgPC9hcHAtd2ViY2FtPlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxkaXZcbiAgICAgIGZ4TGF5b3V0PVwicm93XCJcbiAgICAgIGZ4RmxleFxuICAgICAgY2xhc3M9XCJwcmV2aWV3RGF0YVwiXG4gICAgICAqbmdJZj1cInByZXZpZXdcIlxuICAgICAgc3R5bGU9XCJ6LWluZGV4OiAyMDsgcG9zaXRpb246IGFic29sdXRlOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlXCJcbiAgICA+XG4gICAgICA8ZGl2IGNsYXNzPVwicC0xNiBlcnJvclwiICpuZ0lmPVwiZXJyb3JcIj5cbiAgICAgICAgPGRpdiBzdHlsZT1cIm1heC13aWR0aDogXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlXCIgZnhMYXlvdXQ9XCJyb3dcIiBmeExheW91dEFsaWduPVwic3RhcnQgY2VudGVyXCI+XG4gICAgICAgICAgICA8bWF0LWljb24+ZXJyb3Jfb3V0bGluZTwvbWF0LWljb25cbiAgICAgICAgICAgID48c3BhbiBjbGFzcz1cIm1sLThcIj57e1xuICAgICAgICAgICAgICBcInBtcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUudW5hYmxlVG9EZXRlY3RJZFwiIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICB9fTwvc3Bhbj5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlcnJvckNvZGUgPT09ICcxMDAxJ1wiPlxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgQ291bGQgbm90IGNsYXNzaWZ5IHRoZSBnaXZlbiBvYmplY3QgYXMgYSBzdXBwb3J0ZWQgZG9jdW1lbnQuXG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZXJyb3JDb2RlID09PSAnMTAwMidcIj5cbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgIFNvbWV0aGluZyBpcyB3cm9uZyB3aXRoIGV4dHJhY3Rpb24gZGF0YS4gUGxlYXNlIHRyeSBhZ2Fpbi5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgICAgPHVsICpuZ0lmPVwiZXJyb3JDb2RlID09PSAnMTAwMCdcIj5cbiAgICAgICAgICAgIDxsaT5cbiAgICAgICAgICAgICAge3tcbiAgICAgICAgICAgICAgICBcInBtcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUucGxhY2VJZENsb3NlVG9EZXZpY2VcIlxuICAgICAgICAgICAgICAgICAgfCB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgXCJwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLmVuc3VyZVN1ZmZpY2llbnRMaWdodFwiXG4gICAgICAgICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgIDxsaT5cbiAgICAgICAgICAgICAge3tcbiAgICAgICAgICAgICAgICBcInBtcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUuaG9sZERvY3VtZW50U3RlYWR5XCJcbiAgICAgICAgICAgICAgICAgIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgIFwicG1zLmRpYWxvZ3MuY29tcG9uZW50cy5zY2FuUHJvZmlsZS5tYWtlU3VyZUFsbEVkZ2VzT2ZUaGVJZEFyZVZpc2libGVcIlxuICAgICAgICAgICAgICAgICAgfCB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgXCJwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLm1ha2VTdXJlVGhlcmVBcmVOb0dsYXJlQW5kU2hhZG93c09uVGhlSWRcIlxuICAgICAgICAgICAgICAgICAgfCB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgPC91bD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cInNjYW5QcmV2aWV3XCJcbiAgICAgICAgZnhGbGV4XG4gICAgICAgIGZ4TGF5b3V0PVwiY29sdW1uXCJcbiAgICAgICAgKm5nSWY9XCIhZXJyb3IgJiYgIXNjYW5pbmdcIlxuICAgICAgPlxuICAgICAgICA8IS0tIDxkaXYgY2xhc3M9XCJweS0xNlwiIHN0eWxlPVwiZm9udC1zaXplOiAxNnB4XCI+XG4gICAgICAgICAge3tcbiAgICAgICAgICAgIFwicG1zLmRpYWxvZ3MuY29tcG9uZW50cy5zY2FuUHJvZmlsZS5lbnN1cmVBbGxUZXh0c0FyZVZpc2libGVcIlxuICAgICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgIH19XG4gICAgICAgIDwvZGl2PiAtLT5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGZ4RmxleFxuICAgICAgICAgIGNsYXNzPVwiaW1hZ2VcIlxuICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kLWltYWdlXT1cIid1cmwoJyArIHByZXZpZXcgKyAnKSdcIlxuICAgICAgICA+PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGZvb3RlciBmeExheW91dD1cInJvd1wiIHN0eWxlPVwiaGVpZ2h0OiA4MHB4XCIgY2xhc3M9XCJwLThcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZGlzcGxheUluZm9cIiBuZ0NsYXNzLmx0LXNtPVwibW9iaWxlXCIgKm5nSWY9XCIhcHJldmlldyAmJiBjYW1lcmFSZWFkeVwiPlxuICAgICAge3sgZGlzcGxheUluZm8gfX1cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IHN0eWxlPVwiaGVpZ2h0OiAyNnB4XCI+XG4gICAgICA8ZGl2XG4gICAgICAgIHN0eWxlPVwidGV4dC1hbGlnbjogY2VudGVyOyBmb250LXNpemU6IDE4cHhcIlxuICAgICAgICAqbmdJZj1cImlkU2NhbiAmJiAhcHJldmlldyAmJiBjYW1lcmFSZWFkeVwiXG4gICAgICA+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpZFNjYW4gPT09ICdCQUNLJ1wiPlxuICAgICAgICAgIFR1cm4gZG9jdW1lbnQgYW5kOlxuICAgICAgICAgIHt7IFwicG1zLmRpYWxvZ3MuY29tcG9uZW50cy5zY2FuUHJvZmlsZS5jYXB0dXJlQmFja1wiIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaWRTY2FuID09PSAnRlJPTlQnXCI+XG4gICAgICAgICAgVHVybiBkb2N1bWVudCBhbmQ6XG4gICAgICAgICAge3sgXCJwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLmNhcHR1cmVGcm9udFwiIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIDxidXR0b25cbiAgICAgIFtkaXNhYmxlZF09XCIhY2FtZXJhUmVhZHlcIlxuICAgICAgY2xhc3M9XCJ3LTEwMC1wXCJcbiAgICAgICpuZ0lmPVwiIXByZXZpZXdcIlxuICAgICAgbWF0LXJhaXNlZC1idXR0b25cbiAgICAgIChjbGljayk9XCJzY2FuKClcIlxuICAgID5cbiAgICAgIDxuZy1jb250YWluZXI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzY2FuVHlwZSA9PT0gJ0ZST05UJ1wiPnt7XG4gICAgICAgICAgXCJwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLmNhcHR1cmVGcm9udFwiIHwgdHJhbnNsYXRlXG4gICAgICAgIH19PC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzY2FuVHlwZSA9PT0gJ0JBQ0snXCI+e3tcbiAgICAgICAgICBcInBtcy5kaWFsb2dzLmNvbXBvbmVudHMuc2NhblByb2ZpbGUuY2FwdHVyZUJhY2tcIiB8IHRyYW5zbGF0ZVxuICAgICAgICB9fTwvbmctY29udGFpbmVyPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzY2FuU2lkZSA9PT0gMVwiPnt7XG4gICAgICAgIFwicG1zLmRpYWxvZ3MuY29tcG9uZW50cy5zY2FuUHJvZmlsZS5jYXB0dXJlQmFja09mSWRcIiB8IHRyYW5zbGF0ZVxuICAgICAgfX08L25nLWNvbnRhaW5lcj5cbiAgICA8L2J1dHRvbj4gLS0+XG5cbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cInctMTAwLXBcIlxuICAgICAgKm5nSWY9XCJwcmV2aWV3XCJcbiAgICAgIGZ4TGF5b3V0PVwicm93XCJcbiAgICAgIGZ4TGF5b3V0QWxpZ249XCJzdGFydCBjZW50ZXJcIlxuICAgICAgZnhGbGV4XG4gICAgPlxuICAgICAgPGJ1dHRvbiBmeEZsZXggY2xhc3M9XCJtci00XCIgbWF0LXJhaXNlZC1idXR0b24gKGNsaWNrKT1cInJldHJ5KClcIj5cbiAgICAgICAge3sgXCJwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLnJldHJ5XCIgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8YnV0dG9uXG4gICAgICAgIFtkaXNhYmxlZF09XCJlcnJvclwiXG4gICAgICAgIGZ4RmxleFxuICAgICAgICBjbGFzcz1cIm1sLTRcIlxuICAgICAgICBtYXQtcmFpc2VkLWJ1dHRvblxuICAgICAgICAoY2xpY2spPVwiY29udGludWUoKVwiXG4gICAgICA+XG4gICAgICAgIHt7XG4gICAgICAgICAgXCJwbXMuZGlhbG9ncy5jb21wb25lbnRzLnNjYW5Qcm9maWxlLmNvbnRpbnVlV2l0aFNlbGVjdGVkSW1hZ2VcIlxuICAgICAgICAgICAgfCB0cmFuc2xhdGVcbiAgICAgICAgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Zvb3Rlcj5cbjwvZGl2PlxuIl19
|