ngx-scandoc 0.0.1 → 1.0.2
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/base.component.d.ts +6 -0
- package/core/components/camera-switch/camera-switch.component.d.ts +11 -0
- package/core/components/components.module.d.ts +15 -0
- package/core/components/scan/scan.component.d.ts +120 -0
- package/core/components/scan-results/scan-results.component.d.ts +20 -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 +205 -0
- package/core/components/webcam/webcam.module.d.ts +9 -0
- package/core/interfaces/config.d.ts +16 -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 +16 -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-profile/scan-profile.component.d.ts +18 -0
- package/dialogs/components/scan-selfie/scan-selfie.component.d.ts +83 -0
- package/dialogs/components/turn-document/turn-document.component.d.ts +12 -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/base.component.mjs +15 -0
- package/esm2020/core/components/camera-switch/camera-switch.component.mjs +22 -0
- package/esm2020/core/components/components.module.mjs +46 -0
- package/esm2020/core/components/scan/scan.component.mjs +587 -0
- package/esm2020/core/components/scan-results/scan-results.component.mjs +38 -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 +867 -0
- package/esm2020/core/components/webcam/webcam.module.mjs +22 -0
- package/esm2020/core/interfaces/config.mjs +2 -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 +46 -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-profile/scan-profile.component.mjs +48 -0
- package/esm2020/dialogs/components/scan-selfie/scan-selfie.component.mjs +392 -0
- package/esm2020/dialogs/components/turn-document/turn-document.component.mjs +32 -0
- package/esm2020/dialogs/dialogs.core.provider.mjs +109 -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 +58 -0
- package/esm2020/providers/camera.provider.mjs +40 -0
- package/esm2020/providers/interceptor.provider.mjs +61 -0
- package/esm2020/providers/layout.provider.mjs +28 -0
- package/esm2020/providers/scan.form.mjs +386 -0
- package/esm2020/providers/scan.provider.mjs +488 -0
- package/esm2020/providers/translation.provider.mjs +50 -0
- package/esm2020/providers/webrtc.provider.mjs +58 -0
- package/esm2020/public-api.mjs +24 -4
- package/fesm2015/ngx-scandoc.mjs +4190 -31
- package/fesm2015/ngx-scandoc.mjs.map +1 -1
- package/fesm2020/ngx-scandoc.mjs +4166 -31
- 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 +6 -2
- package/package.json +6 -2
- package/providers/auth.provider.d.ts +21 -0
- package/providers/camera.provider.d.ts +17 -0
- package/providers/interceptor.provider.d.ts +13 -0
- package/providers/layout.provider.d.ts +11 -0
- package/providers/scan.form.d.ts +13 -0
- package/providers/scan.provider.d.ts +237 -0
- package/providers/translation.provider.d.ts +9 -0
- package/providers/webrtc.provider.d.ts +11 -0
- package/public-api.d.ts +23 -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,867 @@
|
|
|
1
|
+
import { Component, EventEmitter, HostListener, Input, Output, ViewChild, } from '@angular/core';
|
|
2
|
+
import { WebcamImage } from '../domain/webcam-image';
|
|
3
|
+
import { from, Observable, of } from 'rxjs';
|
|
4
|
+
import { WebcamUtil } from '../util/webcam.util';
|
|
5
|
+
import { Breakpoints, } from '@angular/cdk/layout';
|
|
6
|
+
import { switchMap } from 'rxjs/operators';
|
|
7
|
+
import { workertext } from '../../../app.worker';
|
|
8
|
+
import { BaseComponent } from '../../base.component';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
import * as i1 from "@angular/cdk/layout";
|
|
11
|
+
import * as i2 from "@angular/cdk/platform";
|
|
12
|
+
import * as i3 from "../../../../providers/camera.provider";
|
|
13
|
+
import * as i4 from "@angular/common";
|
|
14
|
+
export class WebcamComponent extends BaseComponent {
|
|
15
|
+
constructor(breakpointObserver, platform, cd, zone, cameraProvider) {
|
|
16
|
+
super();
|
|
17
|
+
this.breakpointObserver = breakpointObserver;
|
|
18
|
+
this.platform = platform;
|
|
19
|
+
this.cd = cd;
|
|
20
|
+
this.zone = zone;
|
|
21
|
+
this.cameraProvider = cameraProvider;
|
|
22
|
+
/** Defines the max width of the webcam area in px */
|
|
23
|
+
this.width = 640;
|
|
24
|
+
/** Defines the max height of the webcam area in px */
|
|
25
|
+
this.height = 480;
|
|
26
|
+
/** Defines base constraints to apply when requesting video track from UserMedia */
|
|
27
|
+
this.videoOptions = WebcamComponent.DEFAULT_VIDEO_OPTIONS;
|
|
28
|
+
/** Flag to enable/disable camera switch. If enabled, a switch icon will be displayed if multiple cameras were found */
|
|
29
|
+
this.allowCameraSwitch = true;
|
|
30
|
+
/** Flag to control whether an ImageData object is stored into the WebcamImage object. */
|
|
31
|
+
this.captureImageData = false;
|
|
32
|
+
/** The image type to use when capturing snapshots */
|
|
33
|
+
this.imageType = WebcamComponent.DEFAULT_IMAGE_TYPE;
|
|
34
|
+
/** The image quality to use when capturing snapshots (number between 0 and 1) */
|
|
35
|
+
this.imageQuality = WebcamComponent.DEFAULT_IMAGE_QUALITY;
|
|
36
|
+
/** EventEmitter which fires when an image has been captured */
|
|
37
|
+
this.imageCapture = new EventEmitter();
|
|
38
|
+
/** Emits a mediaError if webcam cannot be initialized (e.g. missing user permissions) */
|
|
39
|
+
this.initError = new EventEmitter();
|
|
40
|
+
/** Emits when the webcam video was clicked */
|
|
41
|
+
this.imageClick = new EventEmitter();
|
|
42
|
+
/** Emits the active deviceId after the active video device was switched */
|
|
43
|
+
this.cameraSwitched = new EventEmitter();
|
|
44
|
+
this.videoReady = new EventEmitter();
|
|
45
|
+
this.showVideo = false;
|
|
46
|
+
this.destroyed = new EventEmitter();
|
|
47
|
+
/** available video devices */
|
|
48
|
+
this.availableVideoInputs = [];
|
|
49
|
+
/** Indicates whether the video device is ready to be switched */
|
|
50
|
+
this.videoInitialized = false;
|
|
51
|
+
this.canvasEl = document.createElement('canvas');
|
|
52
|
+
/** Index of active video in availableVideoInputs */
|
|
53
|
+
this.activeVideoInputIndex = -1;
|
|
54
|
+
/** MediaStream object in use for streaming UserMedia data */
|
|
55
|
+
this.mediaStream = null;
|
|
56
|
+
this.shutdown = false;
|
|
57
|
+
this.canStart = true;
|
|
58
|
+
this.videoSize = { width: 1920, height: 1080 };
|
|
59
|
+
this.canvasSize = { width: 1280, height: 720 };
|
|
60
|
+
this.landscape = true;
|
|
61
|
+
// if (typeof Worker !== 'undefined') {
|
|
62
|
+
// // Create a new
|
|
63
|
+
// this.worker = new Worker(
|
|
64
|
+
// new URL('./../../../../app/app.worker', import.meta.url)
|
|
65
|
+
// );
|
|
66
|
+
// this.worker.onmessage = ({ data }) => {
|
|
67
|
+
// console.log(`page got message: ${data}`);
|
|
68
|
+
// };
|
|
69
|
+
// console.log('POST');
|
|
70
|
+
// this.worker.postMessage('hello');
|
|
71
|
+
// } else {
|
|
72
|
+
// // Web workers are not supported in this environment.
|
|
73
|
+
// // You should add a fallback so that your program still executes correctly.
|
|
74
|
+
// }
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* If the given Observable emits, an image will be captured and emitted through 'imageCapture' EventEmitter
|
|
78
|
+
*/
|
|
79
|
+
set trigger(trigger) {
|
|
80
|
+
if (this.triggerSubscription) {
|
|
81
|
+
this.triggerSubscription.unsubscribe();
|
|
82
|
+
}
|
|
83
|
+
// Subscribe to events from this Observable to take snapshots
|
|
84
|
+
this.triggerSubscription = trigger.subscribe((time) => {
|
|
85
|
+
this.takeSnapshot(time);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
onResize() {
|
|
89
|
+
this.videoReady.next(false);
|
|
90
|
+
this.resizeStage();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get MediaTrackConstraints to request streaming the given device
|
|
94
|
+
* @param deviceId
|
|
95
|
+
* @param baseMediaTrackConstraints base constraints to merge deviceId-constraint into
|
|
96
|
+
* @returns
|
|
97
|
+
*/
|
|
98
|
+
static getMediaConstraintsForDevice(deviceId, baseMediaTrackConstraints) {
|
|
99
|
+
const result = baseMediaTrackConstraints
|
|
100
|
+
? baseMediaTrackConstraints
|
|
101
|
+
: this.DEFAULT_VIDEO_OPTIONS;
|
|
102
|
+
if (deviceId) {
|
|
103
|
+
result.deviceId = { exact: deviceId };
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Tries to harvest the deviceId from the given mediaStreamTrack object.
|
|
109
|
+
* Browsers populate this object differently; this method tries some different approaches
|
|
110
|
+
* to read the id.
|
|
111
|
+
* @param mediaStreamTrack
|
|
112
|
+
* @returns deviceId if found in the mediaStreamTrack
|
|
113
|
+
*/
|
|
114
|
+
static getDeviceIdFromMediaStreamTrack(mediaStreamTrack) {
|
|
115
|
+
if (mediaStreamTrack.getSettings &&
|
|
116
|
+
mediaStreamTrack.getSettings() &&
|
|
117
|
+
mediaStreamTrack.getSettings().deviceId) {
|
|
118
|
+
return mediaStreamTrack.getSettings().deviceId;
|
|
119
|
+
}
|
|
120
|
+
else if (mediaStreamTrack.getConstraints &&
|
|
121
|
+
mediaStreamTrack.getConstraints() &&
|
|
122
|
+
mediaStreamTrack.getConstraints().deviceId) {
|
|
123
|
+
const deviceIdObj = mediaStreamTrack.getConstraints().deviceId;
|
|
124
|
+
return WebcamComponent.getValueFromConstrainDOMString(deviceIdObj);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Tries to harvest the facingMode from the given mediaStreamTrack object.
|
|
129
|
+
* Browsers populate this object differently; this method tries some different approaches
|
|
130
|
+
* to read the value.
|
|
131
|
+
* @param mediaStreamTrack
|
|
132
|
+
* @returns facingMode if found in the mediaStreamTrack
|
|
133
|
+
*/
|
|
134
|
+
static getFacingModeFromMediaStreamTrack(mediaStreamTrack) {
|
|
135
|
+
if (mediaStreamTrack) {
|
|
136
|
+
if (mediaStreamTrack.getSettings &&
|
|
137
|
+
mediaStreamTrack.getSettings() &&
|
|
138
|
+
mediaStreamTrack.getSettings().facingMode) {
|
|
139
|
+
return mediaStreamTrack.getSettings().facingMode;
|
|
140
|
+
}
|
|
141
|
+
else if (mediaStreamTrack.getConstraints &&
|
|
142
|
+
mediaStreamTrack.getConstraints() &&
|
|
143
|
+
mediaStreamTrack.getConstraints().facingMode) {
|
|
144
|
+
const facingModeConstraint = mediaStreamTrack.getConstraints().facingMode;
|
|
145
|
+
return WebcamComponent.getValueFromConstrainDOMString(facingModeConstraint);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Determines whether the given mediaStreamTrack claims itself as user facing
|
|
151
|
+
* @param mediaStreamTrack
|
|
152
|
+
*/
|
|
153
|
+
static isUserFacing(mediaStreamTrack) {
|
|
154
|
+
const facingMode = WebcamComponent.getFacingModeFromMediaStreamTrack(mediaStreamTrack);
|
|
155
|
+
return facingMode ? 'user' === facingMode.toLowerCase() : false;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Extracts the value from the given ConstrainDOMString
|
|
159
|
+
* @param constrainDOMString
|
|
160
|
+
*/
|
|
161
|
+
static getValueFromConstrainDOMString(constrainDOMString) {
|
|
162
|
+
if (constrainDOMString) {
|
|
163
|
+
if (constrainDOMString instanceof String) {
|
|
164
|
+
return String(constrainDOMString);
|
|
165
|
+
}
|
|
166
|
+
else if (Array.isArray(constrainDOMString) &&
|
|
167
|
+
Array(constrainDOMString).length > 0) {
|
|
168
|
+
return String(constrainDOMString[0]);
|
|
169
|
+
}
|
|
170
|
+
else if (typeof constrainDOMString === 'object') {
|
|
171
|
+
if (constrainDOMString['exact']) {
|
|
172
|
+
return String(constrainDOMString['exact']);
|
|
173
|
+
}
|
|
174
|
+
else if (constrainDOMString['ideal']) {
|
|
175
|
+
return String(constrainDOMString['ideal']);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
resizeStage() {
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
this.updateSize();
|
|
184
|
+
this.updatecanvasSize();
|
|
185
|
+
this.drawRectangle();
|
|
186
|
+
this.cd.detectChanges();
|
|
187
|
+
this.videoReady.next(true);
|
|
188
|
+
}, 10);
|
|
189
|
+
}
|
|
190
|
+
get canvasHeight() {
|
|
191
|
+
const landscape = this.width > this.height;
|
|
192
|
+
const aspect = this.videoSize.width / this.videoSize.height;
|
|
193
|
+
if (!landscape) {
|
|
194
|
+
return this.width * aspect;
|
|
195
|
+
}
|
|
196
|
+
return this.height;
|
|
197
|
+
}
|
|
198
|
+
updatecanvasSize() {
|
|
199
|
+
console.log(this.width, this.height);
|
|
200
|
+
const landscape = this.width > this.height;
|
|
201
|
+
const aspect = this.videoSize.width / this.videoSize.height;
|
|
202
|
+
let width = this.width;
|
|
203
|
+
let height = this.height;
|
|
204
|
+
if (landscape) {
|
|
205
|
+
height = width / aspect;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
height = width / aspect;
|
|
209
|
+
}
|
|
210
|
+
if (height > this.height) {
|
|
211
|
+
height = this.height;
|
|
212
|
+
width = this.height * aspect;
|
|
213
|
+
}
|
|
214
|
+
this.canvasSize = { width: Math.round(width), height: Math.round(height) };
|
|
215
|
+
console.log(this.canvasSize, this.videoSize);
|
|
216
|
+
if (this.isMobile) {
|
|
217
|
+
this.video.nativeElement.setAttribute('height', this.canvasSize.height);
|
|
218
|
+
this.video.nativeElement.setAttribute('width', this.canvasSize.width);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (this.videoSize.width > this.videoSize.hight) {
|
|
222
|
+
this.video.nativeElement.setAttribute('height', this.canvasSize.height);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
this.video.nativeElement.setAttribute('width', this.canvasSize.width);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
this.cd.detectChanges();
|
|
229
|
+
}
|
|
230
|
+
setupWorker() {
|
|
231
|
+
if (typeof Worker !== 'undefined') {
|
|
232
|
+
// Create a new
|
|
233
|
+
if (this.type !== 'selfie') {
|
|
234
|
+
this.zone.runOutsideAngular(() => {
|
|
235
|
+
var blob = new Blob([workertext], { type: 'text/javascript' });
|
|
236
|
+
var url = URL.createObjectURL(blob);
|
|
237
|
+
this.worker = new Worker(url);
|
|
238
|
+
this.worker.onmessage = ({ data }) => {
|
|
239
|
+
if (data.base64) {
|
|
240
|
+
data.type == 'data';
|
|
241
|
+
this.imageHandler.next(data);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
ngAfterViewInit() {
|
|
249
|
+
this.setupWorker();
|
|
250
|
+
if (this.imageHandler) {
|
|
251
|
+
this.__subs(this.imageHandler).subscribe((resp) => {
|
|
252
|
+
if (resp.type === 'stop') {
|
|
253
|
+
this.worker?.postMessage({ type: 'stop' });
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
this.__subs(this.breakpointObserver
|
|
258
|
+
.observe([Breakpoints.HandsetPortrait, Breakpoints.HandsetLandscape]))
|
|
259
|
+
.subscribe((state) => {
|
|
260
|
+
if (this.platform.IOS || this.platform.ANDROID) {
|
|
261
|
+
// this.landscape = state.breakpoints[Breakpoints.HandsetLandscape];
|
|
262
|
+
}
|
|
263
|
+
const mobile = this.platform.IOS;
|
|
264
|
+
if (state.matches && mobile) {
|
|
265
|
+
this.updateSize();
|
|
266
|
+
this.updatecanvasSize();
|
|
267
|
+
this.drawRectangle();
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
if (this.switchCamera) {
|
|
271
|
+
if (this.switchCameraSubscription) {
|
|
272
|
+
this.switchCameraSubscription.unsubscribe();
|
|
273
|
+
}
|
|
274
|
+
// Subscribe to events from this Observable to switch video device
|
|
275
|
+
this.switchCameraSubscription = this.switchCamera.subscribe((value) => {
|
|
276
|
+
this.switchToVideoInput(value);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
this.detectAvailableDevices()
|
|
280
|
+
.then(() => {
|
|
281
|
+
// start video
|
|
282
|
+
if (this.canStart) {
|
|
283
|
+
this.switchToVideoInput('');
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
.catch((err) => {
|
|
287
|
+
this.initError.next({ message: err });
|
|
288
|
+
// fallback: still try to load webcam, even if device enumeration failed
|
|
289
|
+
if (this.canStart) {
|
|
290
|
+
this.switchToVideoInput('');
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
ngOnDestroy() {
|
|
295
|
+
this.canStart = false;
|
|
296
|
+
this.nativeVideoElement.pause();
|
|
297
|
+
this.destroyed.emit(true);
|
|
298
|
+
this.stopMediaTracks();
|
|
299
|
+
this.unsubscribeFromSubscriptions();
|
|
300
|
+
this.shutdown = true;
|
|
301
|
+
// shut down worker
|
|
302
|
+
if (this.imageHandler) {
|
|
303
|
+
this.imageHandler.next({ type: 'stop' });
|
|
304
|
+
}
|
|
305
|
+
if (this.nativeVideoElement.srcObject) {
|
|
306
|
+
this.nativeVideoElement.srcObject
|
|
307
|
+
.getTracks()
|
|
308
|
+
.forEach((track) => {
|
|
309
|
+
track.stop();
|
|
310
|
+
});
|
|
311
|
+
this.nativeVideoElement.srcObject = null;
|
|
312
|
+
}
|
|
313
|
+
this.__destroy();
|
|
314
|
+
// this.nativeVideoElement.src = null;
|
|
315
|
+
// this.nativeVideoElement.srcObject = null;
|
|
316
|
+
}
|
|
317
|
+
takeSelfie() {
|
|
318
|
+
const _video = this.nativeVideoElement;
|
|
319
|
+
const mimeType = this.imageType
|
|
320
|
+
? this.imageType
|
|
321
|
+
: WebcamComponent.DEFAULT_IMAGE_TYPE;
|
|
322
|
+
let _canvas = document.createElement('canvas'); //this.canvasSnapshot.nativeElement;
|
|
323
|
+
const { width, height } = this.videoSize;
|
|
324
|
+
console.log(width, height);
|
|
325
|
+
const { padding, top, rWidth, rHeight } = this.snapRectangle;
|
|
326
|
+
_canvas.width = rWidth;
|
|
327
|
+
_canvas.height = rHeight;
|
|
328
|
+
const ctx = _canvas.getContext('2d', {
|
|
329
|
+
alpha: false,
|
|
330
|
+
powerPreference: 'high-performance',
|
|
331
|
+
antialias: false,
|
|
332
|
+
depth: false,
|
|
333
|
+
desynchronized: true,
|
|
334
|
+
});
|
|
335
|
+
if (ctx) {
|
|
336
|
+
ctx.drawImage(_video, padding, top, rWidth, rHeight, 0, 0, rWidth, rHeight);
|
|
337
|
+
const imgAsUrl = _canvas.toDataURL(mimeType, 1);
|
|
338
|
+
this.imageCapture.emit(new WebcamImage(imgAsUrl, mimeType, new ImageData(1, 1), null));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Takes a snapshot of the current webcam's view and emits the image as an event
|
|
343
|
+
*/
|
|
344
|
+
takeSnapshot(time) {
|
|
345
|
+
if (this.type === 'selfie') {
|
|
346
|
+
this.takeSelfie();
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (this.trackProcessor) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
this.zone.runOutsideAngular(() => {
|
|
353
|
+
const canvasSmalSize = 384;
|
|
354
|
+
const _video = this.nativeVideoElement;
|
|
355
|
+
const mimeType = this.imageType
|
|
356
|
+
? this.imageType
|
|
357
|
+
: WebcamComponent.DEFAULT_IMAGE_TYPE;
|
|
358
|
+
let _canvas = document.createElement('canvas'); //this.canvasSnapshot.nativeElement;
|
|
359
|
+
const { width, height } = this.videoSize;
|
|
360
|
+
_canvas.width = width;
|
|
361
|
+
_canvas.height = height;
|
|
362
|
+
const ctx = _canvas.getContext('2d', {
|
|
363
|
+
alpha: false,
|
|
364
|
+
powerPreference: 'high-performance',
|
|
365
|
+
antialias: false,
|
|
366
|
+
depth: false,
|
|
367
|
+
desynchronized: true,
|
|
368
|
+
});
|
|
369
|
+
const canvas = document.createElement('canvas'); // needs an initial size
|
|
370
|
+
canvas.height = canvasSmalSize;
|
|
371
|
+
canvas.width = canvasSmalSize;
|
|
372
|
+
const ctxO = canvas.getContext('2d', {
|
|
373
|
+
alpha: false,
|
|
374
|
+
powerPreference: 'high-performance',
|
|
375
|
+
antialias: false,
|
|
376
|
+
depth: false,
|
|
377
|
+
desynchronized: true,
|
|
378
|
+
});
|
|
379
|
+
if (ctx && ctxO) {
|
|
380
|
+
ctx.imageSmoothingEnabled = false;
|
|
381
|
+
ctx.drawImage(_video, 0, 0);
|
|
382
|
+
ctxO.drawImage(_video, 0, 0, canvasSmalSize, canvasSmalSize);
|
|
383
|
+
const imData = ctx.getImageData(0, 0, this.videoSize.width, this.videoSize.height);
|
|
384
|
+
const resize = canvas.toDataURL(mimeType, 1);
|
|
385
|
+
const currentTime = new Date().getTime();
|
|
386
|
+
const diff = currentTime - time;
|
|
387
|
+
const delay = diff > 100 ? 0 : 100 - diff;
|
|
388
|
+
const timeout = setTimeout(() => {
|
|
389
|
+
this.imageCapture.emit(new WebcamImage('', mimeType, imData, resize));
|
|
390
|
+
clearTimeout(timeout);
|
|
391
|
+
}, delay);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
update() { }
|
|
396
|
+
resizeImage(base64data) {
|
|
397
|
+
return new Observable((observer) => {
|
|
398
|
+
let canvas = document.createElement('canvas');
|
|
399
|
+
const ctx = canvas.getContext('2d');
|
|
400
|
+
const max_size = 384;
|
|
401
|
+
let image = new Image();
|
|
402
|
+
image.src = base64data;
|
|
403
|
+
image.onload = () => {
|
|
404
|
+
let width = image.width;
|
|
405
|
+
let height = image.height;
|
|
406
|
+
if (width < height) {
|
|
407
|
+
height *= max_size / width;
|
|
408
|
+
width = max_size;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
width *= max_size / height;
|
|
412
|
+
height = max_size;
|
|
413
|
+
}
|
|
414
|
+
canvas.width = width;
|
|
415
|
+
canvas.height = height;
|
|
416
|
+
// console.log(width, height);
|
|
417
|
+
if (ctx) {
|
|
418
|
+
// ctx.rotate((90 * Math.PI) / 180);
|
|
419
|
+
// ctx.translate(0, -canvas.width);
|
|
420
|
+
ctx.drawImage(image, 0, 0, 384, 384);
|
|
421
|
+
observer.next(canvas.toDataURL());
|
|
422
|
+
ctx.clearRect(0, 0, 1, 1);
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
observer.error({ type: 'generic error' });
|
|
426
|
+
}
|
|
427
|
+
image = null;
|
|
428
|
+
canvas = null;
|
|
429
|
+
};
|
|
430
|
+
image.onerror = (e) => {
|
|
431
|
+
observer.error(e);
|
|
432
|
+
};
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Switches to the next/previous video device
|
|
437
|
+
* @param forward
|
|
438
|
+
*/
|
|
439
|
+
rotateVideoInput(forward) {
|
|
440
|
+
if (this.availableVideoInputs && this.availableVideoInputs.length > 1) {
|
|
441
|
+
const increment = forward
|
|
442
|
+
? 1
|
|
443
|
+
: this.availableVideoInputs.length - 1;
|
|
444
|
+
const nextInputIndex = (this.activeVideoInputIndex + increment) %
|
|
445
|
+
this.availableVideoInputs.length;
|
|
446
|
+
this.switchToVideoInput(this.availableVideoInputs[nextInputIndex].deviceId);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Switches the camera-view to the specified video device
|
|
451
|
+
*/
|
|
452
|
+
switchToVideoInput(deviceId) {
|
|
453
|
+
// if(deviceId){
|
|
454
|
+
this.videoInitialized = false;
|
|
455
|
+
this.stopMediaTracks();
|
|
456
|
+
this.initWebcam(deviceId, this.videoOptions);
|
|
457
|
+
// }
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Event-handler for video resize event.
|
|
461
|
+
* Triggers Angular change detection so that new video dimensions get applied
|
|
462
|
+
*/
|
|
463
|
+
videoResize() {
|
|
464
|
+
// here to trigger Angular change detection
|
|
465
|
+
}
|
|
466
|
+
get videoWidth() {
|
|
467
|
+
const videoRatio = this.getVideoAspectRatio();
|
|
468
|
+
return Math.min(this.width, this.height * videoRatio);
|
|
469
|
+
}
|
|
470
|
+
get videoHeight() {
|
|
471
|
+
const videoRatio = this.getVideoAspectRatio();
|
|
472
|
+
return Math.min(this.height, this.width / videoRatio);
|
|
473
|
+
}
|
|
474
|
+
get videoStyleClasses() {
|
|
475
|
+
let classes = '';
|
|
476
|
+
if (this.isMirrorImage()) {
|
|
477
|
+
classes += 'mirrored ';
|
|
478
|
+
}
|
|
479
|
+
return classes.trim();
|
|
480
|
+
}
|
|
481
|
+
get nativeVideoElement() {
|
|
482
|
+
return this.video.nativeElement;
|
|
483
|
+
}
|
|
484
|
+
// public get smallVideoElement() {
|
|
485
|
+
// return this.videoSmall;
|
|
486
|
+
// }
|
|
487
|
+
/**
|
|
488
|
+
* Returns the video aspect ratio of the active video stream
|
|
489
|
+
*/
|
|
490
|
+
getVideoAspectRatio() {
|
|
491
|
+
// calculate ratio from video element dimensions if present
|
|
492
|
+
const videoElement = this.nativeVideoElement;
|
|
493
|
+
if (videoElement.videoWidth &&
|
|
494
|
+
videoElement.videoWidth > 0 &&
|
|
495
|
+
videoElement.videoHeight &&
|
|
496
|
+
videoElement.videoHeight > 0) {
|
|
497
|
+
return videoElement.videoWidth / videoElement.videoHeight;
|
|
498
|
+
}
|
|
499
|
+
// nothing present - calculate ratio based on width/height params
|
|
500
|
+
return this.width / this.height;
|
|
501
|
+
}
|
|
502
|
+
updateSize() {
|
|
503
|
+
const track = this.mediaStream?.getTracks()[0];
|
|
504
|
+
if (track) {
|
|
505
|
+
let desired = {
|
|
506
|
+
width: {
|
|
507
|
+
ideal: 0,
|
|
508
|
+
},
|
|
509
|
+
height: {
|
|
510
|
+
ideal: 0,
|
|
511
|
+
},
|
|
512
|
+
// facingMode:'user',
|
|
513
|
+
frameRate: { min: 20, ideal: 24, max: 24 },
|
|
514
|
+
};
|
|
515
|
+
if (typeof track.getCapabilities === 'function') {
|
|
516
|
+
const { width, height } = track.getCapabilities();
|
|
517
|
+
desired = {
|
|
518
|
+
width: {
|
|
519
|
+
ideal: this.landscape && this.isMobile ? height?.max : width?.max,
|
|
520
|
+
},
|
|
521
|
+
height: {
|
|
522
|
+
ideal: this.landscape && this.isMobile ? width?.max : height?.max,
|
|
523
|
+
},
|
|
524
|
+
// facingMode:'user',
|
|
525
|
+
frameRate: { min: 20, ideal: 24, max: 24 },
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
desired = {
|
|
530
|
+
width: {
|
|
531
|
+
ideal: 1920,
|
|
532
|
+
},
|
|
533
|
+
height: {
|
|
534
|
+
ideal: 1080,
|
|
535
|
+
},
|
|
536
|
+
// facingMode:'user',
|
|
537
|
+
frameRate: { min: 20, ideal: 30, max: 31 },
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
if (desired.height.ideal && desired.height.ideal >= 1600) {
|
|
541
|
+
desired.height.ideal = 1600;
|
|
542
|
+
desired.width.ideal = 1600;
|
|
543
|
+
}
|
|
544
|
+
if (this.platform.ANDROID) {
|
|
545
|
+
//desired.width.ideal = 2160;
|
|
546
|
+
//desired.height.ideal = 2160;
|
|
547
|
+
// if (!this.landscape) {
|
|
548
|
+
// } else {
|
|
549
|
+
// desired.width.ideal = width?.max;
|
|
550
|
+
// desired.height.ideal = height?.max;
|
|
551
|
+
// }
|
|
552
|
+
}
|
|
553
|
+
track.applyConstraints(desired);
|
|
554
|
+
//track.getSettings().facingMode!=='user';
|
|
555
|
+
this.videoSize = {
|
|
556
|
+
height: this.landscape
|
|
557
|
+
? track.getSettings().height
|
|
558
|
+
: track.getSettings().width,
|
|
559
|
+
width: this.landscape
|
|
560
|
+
? track.getSettings().width
|
|
561
|
+
: track.getSettings().height,
|
|
562
|
+
};
|
|
563
|
+
this.cd.detectChanges();
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
getStreamTrack(stream) {
|
|
567
|
+
return stream.getVideoTracks()[0];
|
|
568
|
+
}
|
|
569
|
+
getTrackSettings() { }
|
|
570
|
+
accesVideoTrack(videoTrackConstraints) {
|
|
571
|
+
return from(navigator.mediaDevices.getUserMedia(videoTrackConstraints)).pipe(switchMap((stream) => {
|
|
572
|
+
// default resolution 1280x720, check max resolution
|
|
573
|
+
const track = this.getStreamTrack(stream);
|
|
574
|
+
const capabilities = track.getCapabilities();
|
|
575
|
+
const { facingMode, height, width } = capabilities;
|
|
576
|
+
const desired = {
|
|
577
|
+
width: {
|
|
578
|
+
min: this.landscape && this.isMobile ? height?.max : width?.max,
|
|
579
|
+
},
|
|
580
|
+
// height: {
|
|
581
|
+
// exact: this.landscape && this.isMobile ? width?.max : height?.max,
|
|
582
|
+
// },
|
|
583
|
+
// facingMode:'en',
|
|
584
|
+
// frameRate: { min: 25, ideal: 30, max: 31 },
|
|
585
|
+
};
|
|
586
|
+
// get max width
|
|
587
|
+
const { width: sWidth, height: sHeight } = track.getSettings();
|
|
588
|
+
if (desired.width.min != sWidth) {
|
|
589
|
+
return this.accesVideoTrack({ video: desired });
|
|
590
|
+
}
|
|
591
|
+
//return this.accesVideoTrack({video:desired});
|
|
592
|
+
return of(stream);
|
|
593
|
+
}));
|
|
594
|
+
}
|
|
595
|
+
drawRectangle() {
|
|
596
|
+
const _canvas = this.canvas.nativeElement;
|
|
597
|
+
const ctx = _canvas.getContext('2d');
|
|
598
|
+
ctx.clearRect(0, 0, _canvas.width, _canvas.height);
|
|
599
|
+
// ctx.drawImage(_video, 0, 0, _canvas.width, _canvas.height);
|
|
600
|
+
const { padding, top, rWidth, rHeight } = this.cardRectangle;
|
|
601
|
+
ctx.strokeStyle = 'red';
|
|
602
|
+
ctx.strokeRect(padding, top, rWidth, rHeight);
|
|
603
|
+
}
|
|
604
|
+
getMaxAvailableResolution() { }
|
|
605
|
+
/**
|
|
606
|
+
* Init webcam live view
|
|
607
|
+
*/
|
|
608
|
+
initWebcam(deviceId, userVideoTrackConstraints) {
|
|
609
|
+
const _video = this.nativeVideoElement;
|
|
610
|
+
// const videoStreamer = this.videoStreamer.nativeElement;
|
|
611
|
+
// const videoSmall = document.createElement('video');
|
|
612
|
+
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
|
613
|
+
// merge deviceId -> userVideoTrackConstraints
|
|
614
|
+
const videoTrackConstraints = WebcamComponent.getMediaConstraintsForDevice(deviceId, userVideoTrackConstraints);
|
|
615
|
+
// // if (deviceId) {
|
|
616
|
+
// this.accesVideoTrack({ video: videoTrackConstraints }).subscribe(
|
|
617
|
+
// (stream: MediaStream) => {
|
|
618
|
+
// console.log(
|
|
619
|
+
// 'VALID SETTINGS',
|
|
620
|
+
// stream.getVideoTracks()[0].getSettings()
|
|
621
|
+
// );
|
|
622
|
+
// }
|
|
623
|
+
// );
|
|
624
|
+
// }
|
|
625
|
+
if (this.platform.ANDROID) {
|
|
626
|
+
videoTrackConstraints.width = 1600;
|
|
627
|
+
videoTrackConstraints.height = 1600;
|
|
628
|
+
}
|
|
629
|
+
const constraints = {
|
|
630
|
+
exact: deviceId,
|
|
631
|
+
width: { min: 480, ideal: 1280 },
|
|
632
|
+
height: { min: 480, ideal: 720 },
|
|
633
|
+
// aspectRatio: 3 / 2,
|
|
634
|
+
frameRate: { min: 20 },
|
|
635
|
+
};
|
|
636
|
+
navigator.mediaDevices
|
|
637
|
+
.getUserMedia({ video: videoTrackConstraints })
|
|
638
|
+
.then((stream) => {
|
|
639
|
+
this.mediaStream = stream;
|
|
640
|
+
_video.srcObject = stream;
|
|
641
|
+
this.updateSize();
|
|
642
|
+
this.updatecanvasSize();
|
|
643
|
+
_video.play();
|
|
644
|
+
_video.onplay = () => {
|
|
645
|
+
this.setActiveCamera(stream);
|
|
646
|
+
this.drawRectangle();
|
|
647
|
+
};
|
|
648
|
+
})
|
|
649
|
+
.catch((err) => {
|
|
650
|
+
console.log(err);
|
|
651
|
+
this.initError.next({
|
|
652
|
+
message: err.message,
|
|
653
|
+
mediaStreamError: err,
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
this.initError.next({
|
|
659
|
+
message: 'Cannot read UserMedia from MediaDevices.',
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
get isMobile() {
|
|
664
|
+
return this.platform.ANDROID || this.platform.IOS;
|
|
665
|
+
}
|
|
666
|
+
get cardRectangle() {
|
|
667
|
+
const _canvas = this.canvas.nativeElement;
|
|
668
|
+
const docSize = this.type === 'selfie' ? 1 : 86 / 55;
|
|
669
|
+
let padding = 10;
|
|
670
|
+
let rWidth = _canvas.width - 2 * padding;
|
|
671
|
+
let rHeight = rWidth / docSize;
|
|
672
|
+
let top = (_canvas.height - rHeight) / 2;
|
|
673
|
+
if (!this.isMobile) {
|
|
674
|
+
padding = 40;
|
|
675
|
+
rHeight = _canvas.height - 2 * padding;
|
|
676
|
+
rWidth = rHeight * docSize;
|
|
677
|
+
top = (_canvas.height - rHeight) / 2;
|
|
678
|
+
padding = (_canvas.width - rWidth) / 2;
|
|
679
|
+
}
|
|
680
|
+
return { padding, top, rWidth, rHeight };
|
|
681
|
+
}
|
|
682
|
+
get snapRectangle() {
|
|
683
|
+
const _canvas = this.canvas.nativeElement;
|
|
684
|
+
const ar = this.videoSize.width / _canvas.width;
|
|
685
|
+
let { padding, top, rWidth, rHeight } = this.cardRectangle;
|
|
686
|
+
padding = padding * ar;
|
|
687
|
+
top = top * ar;
|
|
688
|
+
rWidth = rWidth * ar;
|
|
689
|
+
rHeight = rHeight * ar;
|
|
690
|
+
return { padding, top, rWidth, rHeight };
|
|
691
|
+
}
|
|
692
|
+
setActiveCamera(stream) {
|
|
693
|
+
this.videoReady.next(false);
|
|
694
|
+
this.showVideo = false;
|
|
695
|
+
this.activeVideoSettings = stream.getVideoTracks()[0].getSettings();
|
|
696
|
+
const activeDeviceId = WebcamComponent.getDeviceIdFromMediaStreamTrack(stream.getVideoTracks()[0]);
|
|
697
|
+
const videoTrack = stream.getTracks()[0];
|
|
698
|
+
this.trackSettings = videoTrack.getSettings();
|
|
699
|
+
this.cameraProvider.cameraWasSwitched(activeDeviceId);
|
|
700
|
+
this.cameraSwitched.next(activeDeviceId);
|
|
701
|
+
setTimeout(() => {
|
|
702
|
+
this.zone.run(() => {
|
|
703
|
+
this.resizeStage();
|
|
704
|
+
this.showVideo = true;
|
|
705
|
+
this.videoReady.next(true);
|
|
706
|
+
if (MediaStreamTrackProcessor) {
|
|
707
|
+
this.trackProcessor = new MediaStreamTrackProcessor(videoTrack);
|
|
708
|
+
let frameStream = this.trackProcessor.readable;
|
|
709
|
+
if (!this.shutdown) {
|
|
710
|
+
this.worker?.postMessage({
|
|
711
|
+
type: 'start',
|
|
712
|
+
frameStream: frameStream,
|
|
713
|
+
trackSettings: this.trackSettings,
|
|
714
|
+
}, [frameStream]);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
}, 500);
|
|
719
|
+
}
|
|
720
|
+
getActiveVideoTrack() {
|
|
721
|
+
return this.mediaStream ? this.mediaStream.getVideoTracks()[0] : null;
|
|
722
|
+
}
|
|
723
|
+
isMirrorImage() {
|
|
724
|
+
if (!this.getActiveVideoTrack()) {
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
727
|
+
// check for explicit mirror override parameter
|
|
728
|
+
{
|
|
729
|
+
let mirror = 'auto';
|
|
730
|
+
if (this.mirrorImage) {
|
|
731
|
+
if (typeof this.mirrorImage === 'string') {
|
|
732
|
+
mirror = String(this.mirrorImage).toLowerCase();
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
// WebcamMirrorProperties
|
|
736
|
+
if (this.mirrorImage.x) {
|
|
737
|
+
mirror = this.mirrorImage.x.toLowerCase();
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
switch (mirror) {
|
|
742
|
+
case 'always':
|
|
743
|
+
return true;
|
|
744
|
+
case 'never':
|
|
745
|
+
return false;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
// default: enable mirroring if webcam is user facing
|
|
749
|
+
return WebcamComponent.isUserFacing(this.getActiveVideoTrack());
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Stops all active media tracks.
|
|
753
|
+
* This prevents the webcam from being indicated as active,
|
|
754
|
+
* even if it is no longer used by this component.
|
|
755
|
+
*/
|
|
756
|
+
stopMediaTracks() {
|
|
757
|
+
// this.video.nativeElement.pause();
|
|
758
|
+
if (this.video.nativeElement.srcObject) {
|
|
759
|
+
this.video.nativeElement.srcObject
|
|
760
|
+
.getTracks()
|
|
761
|
+
.forEach((track) => {
|
|
762
|
+
track.stop();
|
|
763
|
+
});
|
|
764
|
+
this.video.nativeElement.srcObject = null;
|
|
765
|
+
this.video.nativeElement.src = '';
|
|
766
|
+
}
|
|
767
|
+
if (this.mediaStream && this.mediaStream.getTracks) {
|
|
768
|
+
// getTracks() returns all media tracks (video+audio)
|
|
769
|
+
this.mediaStream
|
|
770
|
+
.getTracks()
|
|
771
|
+
.forEach((track) => track.stop());
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Unsubscribe from all open subscriptions
|
|
776
|
+
*/
|
|
777
|
+
unsubscribeFromSubscriptions() {
|
|
778
|
+
if (this.triggerSubscription) {
|
|
779
|
+
this.triggerSubscription.unsubscribe();
|
|
780
|
+
}
|
|
781
|
+
if (this.switchCameraSubscription) {
|
|
782
|
+
this.switchCameraSubscription.unsubscribe();
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Reads available input devices
|
|
787
|
+
*/
|
|
788
|
+
detectAvailableDevices() {
|
|
789
|
+
return new Promise((resolve, reject) => {
|
|
790
|
+
WebcamUtil.getAvailableVideoInputs().subscribe((devices) => {
|
|
791
|
+
this.availableVideoInputs = devices;
|
|
792
|
+
resolve(devices);
|
|
793
|
+
}, (err) => {
|
|
794
|
+
this.availableVideoInputs = [];
|
|
795
|
+
reject(err);
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
WebcamComponent.DEFAULT_VIDEO_OPTIONS = {
|
|
801
|
+
facingMode: 'environment',
|
|
802
|
+
};
|
|
803
|
+
WebcamComponent.DEFAULT_IMAGE_TYPE = 'image/jpeg';
|
|
804
|
+
WebcamComponent.DEFAULT_IMAGE_QUALITY = 1;
|
|
805
|
+
WebcamComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WebcamComponent, deps: [{ token: i1.BreakpointObserver }, { token: i2.Platform }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i3.NgxScandocCameraProvider }], target: i0.ɵɵFactoryTarget.Component });
|
|
806
|
+
WebcamComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: WebcamComponent, selector: "app-webcam", inputs: { imageHandler: "imageHandler", id: "id", type: "type", width: "width", height: "height", videoOptions: "videoOptions", allowCameraSwitch: "allowCameraSwitch", mirrorImage: "mirrorImage", captureImageData: "captureImageData", imageType: "imageType", imageQuality: "imageQuality", trigger: "trigger", switchCamera: "switchCamera" }, outputs: { imageCapture: "imageCapture", initError: "initError", imageClick: "imageClick", cameraSwitched: "cameraSwitched", videoReady: "videoReady", destroyed: "destroyed" }, host: { listeners: { "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "video", first: true, predicate: ["video"], descendants: true, static: true }, { propertyName: "videoStreamer", first: true, predicate: ["videoStreamer"], descendants: true, static: true }, { propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true, static: true }, { propertyName: "canvasSnapshot", first: true, predicate: ["canvasSnapshot"], descendants: true, static: true }, { propertyName: "canvasResize", first: true, predicate: ["canvasResize"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"webcam-wrapper\">\n <div>\n <video\n #video\n autoplay\n muted\n style=\"display: block\"\n playsinline\n\n ></video>\n\n <div class=\"rectangle\">\n\n <canvas\n #canvas\n [ngStyle]=\"{ visibility: showVideo ? 'visible' : 'hidden' }\"\n [width]=\"canvasSize.width\"\n [height]=\"canvasSize.height\"\n ></canvas>\n </div>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex:1;transform:transale3d(0,0,0);background-color:#000}.webcam-wrapper{display:flex;flex-direction:row;align-items:center;flex:1;justify-content:center}.webcam-wrapper canvas{transform:transale3d(0,0,0);display:block;position:relative;z-index:20;left:0;top:0}.webcam-wrapper .rectangle{position:absolute;left:0;top:0;display:flex;flex-direction:row;align-items:center;justify-content:center;width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
807
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WebcamComponent, decorators: [{
|
|
808
|
+
type: Component,
|
|
809
|
+
args: [{ selector: 'app-webcam', template: "<div class=\"webcam-wrapper\">\n <div>\n <video\n #video\n autoplay\n muted\n style=\"display: block\"\n playsinline\n\n ></video>\n\n <div class=\"rectangle\">\n\n <canvas\n #canvas\n [ngStyle]=\"{ visibility: showVideo ? 'visible' : 'hidden' }\"\n [width]=\"canvasSize.width\"\n [height]=\"canvasSize.height\"\n ></canvas>\n </div>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex:1;transform:transale3d(0,0,0);background-color:#000}.webcam-wrapper{display:flex;flex-direction:row;align-items:center;flex:1;justify-content:center}.webcam-wrapper canvas{transform:transale3d(0,0,0);display:block;position:relative;z-index:20;left:0;top:0}.webcam-wrapper .rectangle{position:absolute;left:0;top:0;display:flex;flex-direction:row;align-items:center;justify-content:center;width:100%;height:100%}\n"] }]
|
|
810
|
+
}], ctorParameters: function () { return [{ type: i1.BreakpointObserver }, { type: i2.Platform }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i3.NgxScandocCameraProvider }]; }, propDecorators: { imageHandler: [{
|
|
811
|
+
type: Input
|
|
812
|
+
}], id: [{
|
|
813
|
+
type: Input
|
|
814
|
+
}], type: [{
|
|
815
|
+
type: Input
|
|
816
|
+
}], width: [{
|
|
817
|
+
type: Input
|
|
818
|
+
}], height: [{
|
|
819
|
+
type: Input
|
|
820
|
+
}], videoOptions: [{
|
|
821
|
+
type: Input
|
|
822
|
+
}], allowCameraSwitch: [{
|
|
823
|
+
type: Input
|
|
824
|
+
}], mirrorImage: [{
|
|
825
|
+
type: Input
|
|
826
|
+
}], captureImageData: [{
|
|
827
|
+
type: Input
|
|
828
|
+
}], imageType: [{
|
|
829
|
+
type: Input
|
|
830
|
+
}], imageQuality: [{
|
|
831
|
+
type: Input
|
|
832
|
+
}], imageCapture: [{
|
|
833
|
+
type: Output
|
|
834
|
+
}], initError: [{
|
|
835
|
+
type: Output
|
|
836
|
+
}], imageClick: [{
|
|
837
|
+
type: Output
|
|
838
|
+
}], cameraSwitched: [{
|
|
839
|
+
type: Output
|
|
840
|
+
}], videoReady: [{
|
|
841
|
+
type: Output
|
|
842
|
+
}], destroyed: [{
|
|
843
|
+
type: Output
|
|
844
|
+
}], video: [{
|
|
845
|
+
type: ViewChild,
|
|
846
|
+
args: ['video', { static: true }]
|
|
847
|
+
}], videoStreamer: [{
|
|
848
|
+
type: ViewChild,
|
|
849
|
+
args: ['videoStreamer', { static: true }]
|
|
850
|
+
}], canvas: [{
|
|
851
|
+
type: ViewChild,
|
|
852
|
+
args: ['canvas', { static: true }]
|
|
853
|
+
}], canvasSnapshot: [{
|
|
854
|
+
type: ViewChild,
|
|
855
|
+
args: ['canvasSnapshot', { static: true }]
|
|
856
|
+
}], canvasResize: [{
|
|
857
|
+
type: ViewChild,
|
|
858
|
+
args: ['canvasResize', { static: true }]
|
|
859
|
+
}], trigger: [{
|
|
860
|
+
type: Input
|
|
861
|
+
}], switchCamera: [{
|
|
862
|
+
type: Input
|
|
863
|
+
}], onResize: [{
|
|
864
|
+
type: HostListener,
|
|
865
|
+
args: ['window:resize', ['$event']]
|
|
866
|
+
}] } });
|
|
867
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViY2FtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zY2FuZG9jL3NyYy9jb3JlL2NvbXBvbmVudHMvd2ViY2FtL3dlYmNhbS93ZWJjYW0uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNjYW5kb2Mvc3JjL2NvcmUvY29tcG9uZW50cy93ZWJjYW0vd2ViY2FtL3dlYmNhbS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR0wsU0FBUyxFQUNULFlBQVksRUFDWixZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBeUIsTUFBTSxNQUFNLENBQUM7QUFDbkUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWpELE9BQU8sRUFFTCxXQUFXLEdBRVosTUFBTSxxQkFBcUIsQ0FBQztBQUU3QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWpELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7Ozs7O0FBU3JELE1BQU0sT0FBTyxlQUNYLFNBQVEsYUFBYTtJQXdIckIsWUFDUyxrQkFBc0MsRUFDdEMsUUFBa0IsRUFDakIsRUFBcUIsRUFDckIsSUFBWSxFQUVaLGNBQXdDO1FBRWhELEtBQUssRUFBRSxDQUFDO1FBUEQsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUN0QyxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2pCLE9BQUUsR0FBRixFQUFF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QU07c0JBQXBELFNBQVM7dUJBQUMsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFHa0IsY0FBYztzQkFBcEUsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRVEsWUFBWTtzQkFBaEUsU0FBUzt1QkFBQyxjQUFjLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQWNoQyxPQUFPO3NCQURqQixLQUFLO2dCQW1CRyxZQUFZO3NCQUFwQixLQUFLO2dCQUdOLFFBQVE7c0JBRFAsWUFBWTt1QkFBQyxlQUFlLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBXZWJjYW1Jbml0RXJyb3IgfSBmcm9tICcuLi9kb21haW4vd2ViY2FtLWluaXQtZXJyb3InO1xuaW1wb3J0IHsgV2ViY2FtSW1hZ2UgfSBmcm9tICcuLi9kb21haW4vd2ViY2FtLWltYWdlJztcbmltcG9ydCB7IGZyb20sIE9ic2VydmFibGUsIG9mLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFdlYmNhbVV0aWwgfSBmcm9tICcuLi91dGlsL3dlYmNhbS51dGlsJztcbmltcG9ydCB7IFdlYmNhbU1pcnJvclByb3BlcnRpZXMgfSBmcm9tICcuLi9kb21haW4vd2ViY2FtLW1pcnJvci1wcm9wZXJ0aWVzJztcbmltcG9ydCB7XG4gIEJyZWFrcG9pbnRPYnNlcnZlcixcbiAgQnJlYWtwb2ludHMsXG4gIEJyZWFrcG9pbnRTdGF0ZSxcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2xheW91dCc7XG5pbXBvcnQgeyBQbGF0Zm9ybSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wbGF0Zm9ybSc7XG5pbXBvcnQgeyBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyB3b3JrZXJ0ZXh0IH0gZnJvbSAnLi4vLi4vLi4vYXBwLndvcmtlcic7XG5pbXBvcnQgeyBOZ3hTY2FuZG9jQ2FtZXJhUHJvdmlkZXIgfSBmcm9tICcuLi8uLi8uLi8uLi9wcm92aWRlcnMvY2FtZXJhLnByb3ZpZGVyJztcbmltcG9ydCB7IEJhc2VDb21wb25lbnQgfSBmcm9tICcuLi8uLi9iYXNlLmNvbXBvbmVudCc7XG5cbmRlY2xhcmUgdmFyIE1lZGlhU3RyZWFtVHJhY2tQcm9jZXNzb3I6IGFueTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXdlYmNhbScsXG4gIHRlbXBsYXRlVXJsOiAnLi93ZWJjYW0uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi93ZWJjYW0uY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgV2ViY2FtQ29tcG9uZW50XG4gIGV4dGVuZHMgQmFzZUNvbXBvbmVudFxuICBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveVxue1xuICB0cmFja1Byb2Nlc3NvcjogYW55O1xuICB0cmFja1NldHRpbmdzOiBhbnk7XG5cbiAgQElucHV0KCkgaW1hZ2VIYW5kbGVyITogU3ViamVjdDxhbnk+O1xuXG4gIHByaXZhdGUgc3RhdGljIERFRkFVTFRfVklERU9fT1BUSU9OUzogTWVkaWFUcmFja0NvbnN0cmFpbnRzID0ge1xuICAgIGZhY2luZ01vZGU6ICdlbnZpcm9ubWVudCcsXG4gIH07XG4gIHByaXZhdGUgc3RhdGljIERFRkFVTFRfSU1BR0VfVFlQRTogc3RyaW5nID0gJ2ltYWdlL2pwZWcnO1xuICBwcml2YXRlIHN0YXRpYyBERUZBVUxUX0lNQUdFX1FVQUxJVFk6IG51bWJlciA9IDE7XG5cbiAgQElucHV0KCkgcHVibGljIGlkPzogYW55O1xuICBASW5wdXQoKSBwdWJsaWMgdHlwZT86ICdkb2N1bWVudCcgfCAnc2VsZmllJztcbiAgLyoqIERlZmluZXMgdGhlIG1heCB3aWR0aCBvZiB0aGUgd2ViY2FtIGFyZWEgaW4gcHggKi9cbiAgQElucHV0KCkgcHVibGljIHdpZHRoOiBudW1iZXIgPSA2NDA7XG4gIC8qKiBEZWZpbmVzIHRoZSBtYXggaGVpZ2h0IG9mIHRoZSB3ZWJjYW0gYXJlYSBpbiBweCAqL1xuICBASW5wdXQoKSBwdWJsaWMgaGVpZ2h0OiBudW1iZXIgPSA0ODA7XG4gIC8qKiBEZWZpbmVzIGJhc2UgY29uc3RyYWludHMgdG8gYXBwbHkgd2hlbiByZXF1ZXN0aW5nIHZpZGVvIHRyYWNrIGZyb20gVXNlck1lZGlhICovXG4gIEBJbnB1dCgpIHB1YmxpYyB2aWRlb09wdGlvbnM6IE1lZGlhVHJhY2tDb25zdHJhaW50cyA9XG4gICAgV2ViY2FtQ29tcG9uZW50LkRFRkFVTFRfVklERU9fT1BUSU9OUztcbiAgLyoqIEZsYWcgdG8gZW5hYmxlL2Rpc2FibGUgY2FtZXJhIHN3aXRjaC4gSWYgZW5hYmxlZCwgYSBzd2l0Y2ggaWNvbiB3aWxsIGJlIGRpc3BsYXllZCBpZiBtdWx0aXBsZSBjYW1lcmFzIHdlcmUgZm91bmQgKi9cbiAgQElucHV0KCkgcHVibGljIGFsbG93Q2FtZXJhU3dpdGNoOiBib29sZWFuID0gdHJ1ZTtcbiAgLyoqIFBhcmFtZXRlciB0byBjb250cm9sIGltYWdlIG1pcnJvcmluZyAoaS5lLiBmb3IgdXNlci1mYWNpbmcgY2FtZXJhKS4gW1wiYXV0b1wiLCBcImFsd2F5c1wiLCBcIm5ldmVyXCJdICovXG4gIEBJbnB1dCgpIHB1YmxpYyBtaXJyb3JJbWFnZT86IHN0cmluZyB8IFdlYmNhbU1pcnJvclByb3BlcnRpZXM7XG4gIC8qKiBGbGFnIHRvIGNvbnRyb2wgd2hldGhlciBhbiBJbWFnZURhdGEgb2JqZWN0IGlzIHN0b3JlZCBpbnRvIHRoZSBXZWJjYW1JbWFnZSBvYmplY3QuICovXG4gIEBJbnB1dCgpIHB1YmxpYyBjYXB0dXJlSW1hZ2VEYXRhOiBib29sZWFuID0gZmFsc2U7XG4gIC8qKiBUaGUgaW1hZ2UgdHlwZSB0byB1c2Ugd2hlbiBjYXB0dXJpbmcgc25hcHNob3RzICovXG4gIEBJbnB1dCgpIHB1YmxpYyBpbWFnZVR5cGU6IHN0cmluZyA9IFdlYmNhbUNvbXBvbmVudC5ERUZBVUxUX0lNQUdFX1RZUEU7XG4gIC8qKiBUaGUgaW1hZ2UgcXVhbGl0eSB0byB1c2Ugd2hlbiBjYXB0dXJpbmcgc25hcHNob3RzIChudW1iZXIgYmV0d2VlbiAwIGFuZCAxKSAqL1xuICBASW5wdXQoKSBwdWJsaWMgaW1hZ2VRdWFsaXR5OiBudW1iZXIgPSBXZWJjYW1Db21wb25lbnQuREVGQVVMVF9JTUFHRV9RVUFMSVRZO1xuXG4gIC8qKiBFdmVudEVtaXR0ZXIgd2hpY2ggZmlyZXMgd2hlbiBhbiBpbWFnZSBoYXMgYmVlbiBjYXB0dXJlZCAqL1xuICBAT3V0cHV0KCkgcHVibGljIGltYWdlQ2FwdHVyZTogRXZlbnRFbWl0dGVyPFdlYmNhbUltYWdlPiA9XG4gICAgbmV3IEV2ZW50RW1pdHRlcjxXZWJjYW1JbWFnZT4oKTtcbiAgLyoqIEVtaXRzIGEgbWVkaWFFcnJvciBpZiB3ZWJjYW0gY2Fubm90IGJlIGluaXRpYWxpemVkIChlLmcuIG1pc3NpbmcgdXNlciBwZXJtaXNzaW9ucykgKi9cbiAgQE91dHB1dCgpIHB1YmxpYyBpbml0RXJyb3I6IEV2ZW50RW1pdHRlcjxXZWJjYW1Jbml0RXJyb3I+ID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPFdlYmNhbUluaXRFcnJvcj4oKTtcbiAgLyoqIEVtaXRzIHdoZW4gdGhlIHdlYmNhbSB2aWRlbyB3YXMgY2xpY2tlZCAqL1xuICBAT3V0cHV0KCkgcHVibGljIGltYWdlQ2xpY2s6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqIEVtaXRzIHRoZSBhY3RpdmUgZGV2aWNlSWQgYWZ0ZXIgdGhlIGFjdGl2ZSB2aWRlbyBkZXZpY2Ugd2FzIHN3aXRjaGVkICovXG4gIEBPdXRwdXQoKSBwdWJsaWMgY2FtZXJhU3dpdGNoZWQ6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBAT3V0cHV0KCkgcHVibGljIHZpZGVvUmVhZHk6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9XG4gICAgbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICBzaG93VmlkZW8gPSBmYWxzZTtcbiAgQE91dHB1dCgpIGRlc3Ryb3llZCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAvKiogYXZhaWxhYmxlIHZpZGVvIGRldmljZXMgKi9cbiAgcHVibGljIGF2YWlsYWJsZVZpZGVvSW5wdXRzOiBNZWRpYURldmljZUluZm9bXSA9IFtdO1xuXG4gIC8qKiBJbmRpY2F0ZXMgd2hldGhlciB0aGUgdmlkZW8gZGV2aWNlIGlzIHJlYWR5IHRvIGJlIHN3aXRjaGVkICovXG4gIHB1YmxpYyB2aWRlb0luaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgY2FudmFzRWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcblxuICAvKiogSWYgdGhlIE9ic2VydmFibGUgcmVwcmVzZW50ZWQgYnkgdGhpcyBzdWJzY3JpcHRpb24gZW1pdHMsIGFuIGltYWdlIHdpbGwgYmUgY2FwdHVyZWQgYW5kIGVtaXR0ZWQgdGhyb3VnaFxuICAgKiB0aGUgJ2ltYWdlQ2FwdHVyZScgRXZlbnRFbWl0dGVyICovXG4gIHByaXZhdGUgdHJpZ2dlclN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcbiAgLyoqIEluZGV4IG9mIGFjdGl2ZSB2aWRlbyBpbiBhdmFpbGFibGVWaWRlb0lucHV0cyAqL1xuICBwcml2YXRlIGFjdGl2ZVZpZGVvSW5wdXRJbmRleDogbnVtYmVyID0gLTE7XG4gIC8qKiBTdWJzY3JpcHRpb24gdG8gc3dpdGNoQ2FtZXJhIGV2ZW50cyAqL1xuICBwcml2YXRlIHN3aXRjaENhbWVyYVN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcbiAgLyoqIE1lZGlhU3RyZWFtIG9iamVjdCBpbiB1c2UgZm9yIHN0cmVhbWluZyBVc2VyTWVkaWEgZGF0YSAqL1xuICBwcml2YXRlIG1lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSB8IG51bGwgPSBudWxsO1xuICAvLyBPcmlnaW5hbCB2aWRlb1xuICBAVmlld0NoaWxkKCd2aWRlbycsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgdmlkZW86IGFueTtcbiAgLy8gQWRqdXN0ZWQgZm9yIFVJXG4gIEBWaWV3Q2hpbGQoJ3ZpZGVvU3RyZWFtZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIHZpZGVvU3RyZWFtZXI6IGFueTtcblxuICAvL0BWaWV3Q2hpbGQoJ3ZpZGVvU21hbGwnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIHZpZGVvU21hbGw6IGFueTtcbiAgLy92aWRlb1NtYWxsOiBIVE1MVmlkZW9FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgLyoqIENhbnZhcyBmb3IgVmlkZW8gU25hcHNob3RzICovXG4gIEBWaWV3Q2hpbGQoJ2NhbnZhcycsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgY2FudmFzOiBhbnk7XG5cbiAgLyoqIENhbnZhcyBmb3IgVmlkZW8gU25hcHNob3RzICovXG4gIEBWaWV3Q2hpbGQoJ2NhbnZhc1NuYXBzaG90JywgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSBjYW52YXNTbmFwc2hvdDogYW55O1xuXG4gIEBWaWV3Q2hpbGQoJ2NhbnZhc1Jlc2l6ZScsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgY2FudmFzUmVzaXplOiBhbnk7XG4gIC8qKiB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBhY3RpdmUgdmlkZW8gc3RyZWFtICovXG4gIGFjdGl2ZVZpZGVvU2V0dGluZ3M6IGFueTtcblxuICBzaHV0ZG93biA9IGZhbHNlO1xuICBwcml2YXRlIGNhblN0YXJ0ID0gdHJ1ZTtcbiAgdmlkZW9TaXplOiBhbnkgPSB7IHdpZHRoOiAxOTIwLCBoZWlnaHQ6IDEwODAgfTtcbiAgY2FudmFzU2l6ZTogYW55ID0geyB3aWR0aDogMTI4MCwgaGVpZ2h0OiA3MjAgfTtcblxuICB3b3JrZXI/OiBXb3JrZXI7XG4gIC8qKlxuICAgKiBJZiB0aGUgZ2l2ZW4gT2JzZXJ2YWJsZSBlbWl0cywgYW4gaW1hZ2Ugd2lsbCBiZSBjYXB0dXJlZCBhbmQgZW1pdHRlZCB0aHJvdWdoICdpbWFnZUNhcHR1cmUnIEV2ZW50RW1pdHRlclxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHNldCB0cmlnZ2VyKHRyaWdnZXI6IE9ic2VydmFibGU8bnVtYmVyPikge1xuICAgIGlmICh0aGlzLnRyaWdnZXJTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMudHJpZ2dlclN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIC8vIFN1YnNjcmliZSB0byBldmVudHMgZnJvbSB0aGlzIE9ic2VydmFibGUgdG8gdGFrZSBzbmFwc2hvdHNcbiAgICB0aGlzLnRyaWdnZXJTdWJzY3JpcHRpb24gPSB0cmlnZ2VyLnN1YnNjcmliZSgodGltZSkgPT4ge1xuICAgICAgdGhpcy50YWtlU25hcHNob3QodGltZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhlIGdpdmVuIE9ic2VydmFibGUgZW1pdHMsIHRoZSBhY3RpdmUgd2ViY2FtIHdpbGwgYmUgc3dpdGNoZWQgdG8gdGhlIG9uZSBpbmRpY2F0ZWQgYnkgdGhlIGVtaXR0ZWQgdmFsdWUuXG4gICAqIEBwYXJhbSBzd2l0Y2hDYW1lcmEgSW5kaWNhdGVzIHdoaWNoIHdlYmNhbSB0byBzd2l0Y2ggdG9cbiAgICogICB0cnVlOiBjeWNsZSBmb3J3YXJkcyB0aHJvdWdoIGF2YWlsYWJsZSB3ZWJjYW1zXG4gICAqICAgZmFsc2U6IGN5Y2xlIGJhY2t3YXJkcyB0aHJvdWdoIGF2YWlsYWJsZSB3ZWJjYW1zXG4gICAqICAgc3RyaW5nOiBhY3RpdmF0ZSB0aGUgd2ViY2FtIHdpdGggdGhlIGdpdmVuIGlkXG4gICAqL1xuICBASW5wdXQoKSBzd2l0Y2hDYW1lcmE6IGFueTtcblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJywgWyckZXZlbnQnXSlcbiAgb25SZXNpemUoKSB7XG4gICAgdGhpcy52aWRlb1JlYWR5Lm5leHQoZmFsc2UpO1xuICAgIHRoaXMucmVzaXplU3RhZ2UoKTtcbiAgfVxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgYnJlYWtwb2ludE9ic2VydmVyOiBCcmVha3BvaW50T2JzZXJ2ZXIsXG4gICAgcHVibGljIHBsYXRmb3JtOiBQbGF0Zm9ybSxcbiAgICBwcml2YXRlIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIHpvbmU6IE5nWm9uZSxcblxuICAgIHByaXZhdGUgY2FtZXJhUHJvdmlkZXI6IE5neFNjYW5kb2NDYW1lcmFQcm92aWRlclxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIC8vIGlmICh0eXBlb2YgV29ya2VyICE9PSAndW5kZWZpbmVkJykge1xuICAgIC8vICAgLy8gQ3JlYXRlIGEgbmV3XG4gICAgLy8gICB0aGlzLndvcmtlciA9IG5ldyBXb3JrZXIoXG4gICAgLy8gICAgIG5ldyBVUkwoJy4vLi4vLi4vLi4vLi4vYXBwL2FwcC53b3JrZXInLCBpbXBvcnQubWV0YS51cmwpXG4gICAgLy8gICApO1xuICAgIC8vICAgdGhpcy53b3JrZXIub25tZXNzYWdlID0gKHsgZGF0YSB9KSA9PiB7XG4gICAgLy8gICAgIGNvbnNvbGUubG9nKGBwYWdlIGdvdCBtZXNzYWdlOiAke2RhdGF9YCk7XG4gICAgLy8gICB9O1xuICAgIC8vICAgY29uc29sZS5sb2coJ1BPU1QnKTtcbiAgICAvLyAgIHRoaXMud29ya2VyLnBvc3RNZXNzYWdlKCdoZWxsbycpO1xuICAgIC8vIH0gZWxzZSB7XG4gICAgLy8gICAvLyBXZWIgd29ya2VycyBhcmUgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGVudmlyb25tZW50LlxuICAgIC8vICAgLy8gWW91IHNob3VsZCBhZGQgYSBmYWxsYmFjayBzbyB0aGF0IHlvdXIgcHJvZ3JhbSBzdGlsbCBleGVjdXRlcyBjb3JyZWN0bHkuXG4gICAgLy8gfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBNZWRpYVRyYWNrQ29uc3RyYWludHMgdG8gcmVxdWVzdCBzdHJlYW1pbmcgdGhlIGdpdmVuIGRldmljZVxuICAgKiBAcGFyYW0gZGV2aWNlSWRcbiAgICogQHBhcmFtIGJhc2VNZWRpYVRyYWNrQ29uc3RyYWludHMgYmFzZSBjb25zdHJhaW50cyB0byBtZXJnZSBkZXZpY2VJZC1jb25zdHJhaW50IGludG9cbiAgICogQHJldHVybnNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldE1lZGlhQ29uc3RyYWludHNGb3JEZXZpY2UoXG4gICAgZGV2aWNlSWQ6IHN0cmluZyxcbiAgICBiYXNlTWVkaWFUcmFja0NvbnN0cmFpbnRzOiBNZWRpYVRyYWNrQ29uc3RyYWludHNcbiAgKTogTWVkaWFUcmFja0NvbnN0cmFpbnRzIHtcbiAgICBjb25zdCByZXN1bHQ6IE1lZGlhVHJhY2tDb25zdHJhaW50cyA9IGJhc2VNZWRpYVRyYWNrQ29uc3RyYWludHNcbiAgICAgID8gYmFzZU1lZGlhVHJhY2tDb25zdHJhaW50c1xuICAgICAgOiB0aGlzLkRFRkFVTFRfVklERU9fT1BUSU9OUztcbiAgICBpZiAoZGV2aWNlSWQpIHtcbiAgICAgIHJlc3VsdC5kZXZpY2VJZCA9IHsgZXhhY3Q6IGRldmljZUlkIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmllcyB0byBoYXJ2ZXN0IHRoZSBkZXZpY2VJZCBmcm9tIHRoZSBnaXZlbiBtZWRpYVN0cmVhbVRyYWNrIG9iamVjdC5cbiAgICogQnJvd3NlcnMgcG9wdWxhdGUgdGhpcyBvYmplY3QgZGlmZmVyZW50bHk7IHRoaXMgbWV0aG9kIHRyaWVzIHNvbWUgZGlmZmVyZW50IGFwcHJvYWNoZXNcbiAgICogdG8gcmVhZCB0aGUgaWQuXG4gICAqIEBwYXJhbSBtZWRpYVN0cmVhbVRyYWNrXG4gICAqIEByZXR1cm5zIGRldmljZUlkIGlmIGZvdW5kIGluIHRoZSBtZWRpYVN0cmVhbVRyYWNrXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBnZXREZXZpY2VJZEZyb21NZWRpYVN0cmVhbVRyYWNrKFxuICAgIG1lZGlhU3RyZWFtVHJhY2s6IE1lZGlhU3RyZWFtVHJhY2tcbiAgKTogYW55IHtcbiAgICBpZiAoXG4gICAgICBtZWRpYVN0cmVhbVRyYWNrLmdldFNldHRpbmdzICYmXG4gICAgICBtZWRpYVN0cmVhbVRyYWNrLmdldFNldHRpbmdzKCkgJiZcbiAgICAgIG1lZGlhU3RyZWFtVHJhY2suZ2V0U2V0dGluZ3MoKS5kZXZpY2VJZFxuICAgICkge1xuICAgICAgcmV0dXJuIG1lZGlhU3RyZWFtVHJhY2suZ2V0U2V0dGluZ3MoKS5kZXZpY2VJZDtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgbWVkaWFTdHJlYW1UcmFjay5nZXRDb25zdHJhaW50cyAmJlxuICAgICAgbWVkaWFTdHJlYW1UcmFjay5nZXRDb25zdHJhaW50cygpICYmXG4gICAgICBtZWRpYVN0cmVhbVRyYWNrLmdldENvbnN0cmFpbnRzKCkuZGV2aWNlSWRcbiAgICApIHtcbiAgICAgIGNvbnN0IGRldmljZUlkT2JqOiBhbnkgPSBtZWRpYVN0cmVhbVRyYWNrLmdldENvbnN0cmFpbnRzKCkuZGV2aWNlSWQ7XG5cbiAgICAgIHJldHVybiBXZWJjYW1Db21wb25lbnQuZ2V0VmFsdWVGcm9tQ29uc3RyYWluRE9NU3RyaW5nKGRldmljZUlkT2JqKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJpZXMgdG8gaGFydmVzdCB0aGUgZmFjaW5nTW9kZSBmcm9tIHRoZSBnaXZlbiBtZWRpYVN0cmVhbVRyYWNrIG9iamVjdC5cbiAgICogQnJvd3NlcnMgcG9wdWxhdGUgdGhpcyBvYmplY3QgZGlmZmVyZW50bHk7IHRoaXMgbWV0aG9kIHRyaWVzIHNvbWUgZGlmZmVyZW50IGFwcHJvYWNoZXNcbiAgICogdG8gcmVhZCB0aGUgdmFsdWUuXG4gICAqIEBwYXJhbSBtZWRpYVN0cmVhbVRyYWNrXG4gICAqIEByZXR1cm5zIGZhY2luZ01vZGUgaWYgZm91bmQgaW4gdGhlIG1lZGlhU3RyZWFtVHJhY2tcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldEZhY2luZ01vZGVGcm9tTWVkaWFTdHJlYW1UcmFjayhcbiAgICBtZWRpYVN0cmVhbVRyYWNrOiBNZWRpYVN0cmVhbVRyYWNrXG4gICk6IGFueSB7XG4gICAgaWYgKG1lZGlhU3RyZWFtVHJhY2spIHtcbiAgICAgIGlmIChcbiAgICAgICAgbWVkaWFTdHJlYW1UcmFjay5nZXRTZXR0aW5ncyAmJlxuICAgICAgICBtZWRpYVN0cmVhbVRyYWNrLmdldFNldHRpbmdzKCkgJiZcbiAgICAgICAgbWVkaWFTdHJlYW1UcmFjay5nZXRTZXR0aW5ncygpLmZhY2luZ01vZGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbWVkaWFTdHJlYW1UcmFjay5nZXRTZXR0aW5ncygpLmZhY2luZ01vZGU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBtZWRpYVN0cmVhbVRyYWNrLmdldENvbnN0cmFpbnRzICYmXG4gICAgICAgIG1lZGlhU3RyZWFtVHJhY2suZ2V0Q29uc3RyYWludHMoKSAmJlxuICAgICAgICBtZWRpYVN0cmVhbVRyYWNrLmdldENvbnN0cmFpbnRzKCkuZmFjaW5nTW9kZVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IGZhY2luZ01vZGVDb25zdHJhaW50OiBhbnkgPVxuICAgICAgICAgIG1lZGlhU3RyZWFtVHJhY2suZ2V0Q29uc3RyYWludHMoKS5mYWNpbmdNb2RlO1xuICAgICAgICByZXR1cm4gV2ViY2FtQ29tcG9uZW50LmdldFZhbHVlRnJvbUNvbnN0cmFpbkRPTVN0cmluZyhcbiAgICAgICAgICBmYWNpbmdNb2RlQ29uc3RyYWludFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGdpdmVuIG1lZGlhU3RyZWFtVHJhY2sgY2xhaW1zIGl0c2VsZiBhcyB1c2VyIGZhY2luZ1xuICAgKiBAcGFyYW0gbWVkaWFTdHJlYW1UcmFja1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgaXNVc2VyRmFjaW5nKG1lZGlhU3RyZWFtVHJhY2s6IE1lZGlhU3RyZWFtVHJhY2spOiBib29sZWFuIHtcbiAgICBjb25zdCBmYWNpbmdNb2RlOiBzdHJpbmcgPVxuICAgICAgV2ViY2FtQ29tcG9uZW50LmdldEZhY2luZ01vZGVGcm9tTWVkaWFTdHJlYW1UcmFjayhtZWRpYVN0cmVhbVRyYWNrKTtcbiAgICByZXR1cm4gZmFjaW5nTW9kZSA/ICd1c2VyJyA9PT0gZmFjaW5nTW9kZS50b0xvd2VyQ2FzZSgpIDogZmFsc2U7XG4gIH1cbiAgbGFuZHNjYXBlID0gdHJ1ZTtcbiAgLyoqXG4gICAqIEV4dHJhY3RzIHRoZSB2YWx1ZSBmcm9tIHRoZSBnaXZlbiBDb25zdHJhaW5ET01TdHJpbmdcbiAgICogQHBhcmFtIGNvbnN0cmFpbkRPTVN0cmluZ1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0VmFsdWVGcm9tQ29uc3RyYWluRE9NU3RyaW5nKGNvbnN0cmFpbkRPTVN0cmluZzogYW55KTogYW55IHtcbiAgICBpZiAoY29uc3RyYWluRE9NU3RyaW5nKSB7XG4gICAgICBpZiAoY29uc3RyYWluRE9NU3RyaW5nIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoY29uc3RyYWluRE9NU3RyaW5nKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIEFycmF5LmlzQXJyYXkoY29uc3RyYWluRE9NU3RyaW5nKSAmJlxuICAgICAgICBBcnJheShjb25zdHJhaW5ET01TdHJpbmcpLmxlbmd0aCA+IDBcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gU3RyaW5nKGNvbnN0cmFpbkRPTVN0cmluZ1swXSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjb25zdHJhaW5ET01TdHJpbmcgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGlmIChjb25zdHJhaW5ET01TdHJpbmdbJ2V4YWN0J10pIHtcbiAgICAgICAgICByZXR1cm4gU3RyaW5nKGNvbnN0cmFpbkRPTVN0cmluZ1snZXhhY3QnXSk7XG4gICAgICAgIH0gZWxzZSBpZiAoY29uc3RyYWluRE9NU3RyaW5nWydpZGVhbCddKSB7XG4gICAgICAgICAgcmV0dXJuIFN0cmluZyhjb25zdHJhaW5ET01TdHJpbmdbJ2lkZWFsJ10pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXNpemVTdGFnZSgpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgdGhpcy51cGRhdGVjYW52YXNTaXplKCk7XG4gICAgICB0aGlzLmRyYXdSZWN0YW5nbGUoKTtcbiAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgdGhpcy52aWRlb1JlYWR5Lm5leHQodHJ1ZSk7XG4gICAgfSwgMTApO1xuICB9XG5cbiAgZ2V0IGNhbnZhc0hlaWdodCgpIHtcbiAgICBjb25zdCBsYW5kc2NhcGUgPSB0aGlzLndpZHRoID4gdGhpcy5oZWlnaHQ7XG4gICAgY29uc3QgYXNwZWN0ID0gdGhpcy52aWRlb1NpemUud2lkdGggLyB0aGlzLnZpZGVvU2l6ZS5oZWlnaHQ7XG4gICAgaWYgKCFsYW5kc2NhcGUpIHtcbiAgICAgIHJldHVybiB0aGlzLndpZHRoICogYXNwZWN0O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5oZWlnaHQ7XG4gIH1cbiAgdXBkYXRlY2FudmFzU2l6ZSgpIHtcbiAgICBjb25zb2xlLmxvZyh0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7XG4gICAgY29uc3QgbGFuZHNjYXBlID0gdGhpcy53aWR0aCA+IHRoaXMuaGVpZ2h0O1xuICAgIGNvbnN0IGFzcGVjdCA9IHRoaXMudmlkZW9TaXplLndpZHRoIC8gdGhpcy52aWRlb1NpemUuaGVpZ2h0O1xuXG4gICAgbGV0IHdpZHRoID0gdGhpcy53aWR0aDtcbiAgICBsZXQgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7XG5cbiAgICBpZiAobGFuZHNjYXBlKSB7XG4gICAgICBoZWlnaHQgPSB3aWR0aCAvIGFzcGVjdDtcbiAgICB9IGVsc2Uge1xuICAgICAgaGVpZ2h0ID0gd2lkdGggLyBhc3BlY3Q7XG4gICAgfVxuXG4gICAgaWYgKGhlaWdodCA+IHRoaXMuaGVpZ2h0KSB7XG4gICAgICBoZWlnaHQgPSB0aGlzLmhlaWdodDtcbiAgICAgIHdpZHRoID0gdGhpcy5oZWlnaHQgKiBhc3BlY3Q7XG4gICAgfVxuXG4gICAgdGhpcy5jYW52YXNTaXplID0geyB3aWR0aDogTWF0aC5yb3VuZCh3aWR0aCksIGhlaWdodDogTWF0aC5yb3VuZChoZWlnaHQpIH07XG5cbiAgICBjb25zb2xlLmxvZyh0aGlzLmNhbnZhc1NpemUsIHRoaXMudmlkZW9TaXplKTtcblxuICAgIGlmICh0aGlzLmlzTW9iaWxlKSB7XG4gICAgICB0aGlzLnZpZGVvLm5hdGl2ZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCB0aGlzLmNhbnZhc1NpemUuaGVpZ2h0KTtcbiAgICAgIHRoaXMudmlkZW8ubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgdGhpcy5jYW52YXNTaXplLndpZHRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMudmlkZW9TaXplLndpZHRoID4gdGhpcy52aWRlb1NpemUuaGlnaHQpIHtcbiAgICAgICAgdGhpcy52aWRlby5uYXRpdmVFbGVtZW50LnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgdGhpcy5jYW52YXNTaXplLmhlaWdodCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnZpZGVvLm5hdGl2ZUVsZW1lbnQuc2V0QXR0cmlidXRlKCd3aWR0aCcsIHRoaXMuY2FudmFzU2l6ZS53aWR0aCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwV29ya2VyKCkge1xuICAgIGlmICh0eXBlb2YgV29ya2VyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gQ3JlYXRlIGEgbmV3XG5cbiAgICAgIGlmICh0aGlzLnR5cGUgIT09ICdzZWxmaWUnKSB7XG4gICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgdmFyIGJsb2IgPSBuZXcgQmxvYihbd29ya2VydGV4dF0sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSk7XG5cbiAgICAgICAgICB2YXIgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcblxuICAgICAgICAgIHRoaXMud29ya2VyID0gbmV3IFdvcmtlcih1cmwpO1xuICAgICAgICAgIHRoaXMud29ya2VyLm9ubWVzc2FnZSA9ICh7IGRhdGEgfSkgPT4ge1xuICAgICAgICAgICAgaWYgKGRhdGEuYmFzZTY0KSB7XG4gICAgICAgICAgICAgIGRhdGEudHlwZSA9PSAnZGF0YSc7XG4gICAgICAgICAgICAgIHRoaXMuaW1hZ2VIYW5kbGVyLm5leHQoZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnNldHVwV29ya2VyKCk7XG5cbiAgICBpZiAodGhpcy5pbWFnZUhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX19zdWJzKHRoaXMuaW1hZ2VIYW5kbGVyKS5zdWJzY3JpYmUoKHJlc3ApID0+IHtcbiAgICAgICAgaWYgKHJlc3AudHlwZSA9PT0gJ3N0b3AnKSB7XG4gICAgICAgICAgdGhpcy53b3JrZXI/LnBvc3RNZXNzYWdlKHsgdHlwZTogJ3N0b3AnIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgdGhpcy5fX3N1YnModGhpcy5icmVha3BvaW50T2JzZXJ2ZXJcbiAgICAgIC5vYnNlcnZlKFtCcmVha3BvaW50cy5IYW5kc2V0UG9ydHJhaXQsIEJyZWFrcG9pbnRzLkhhbmRzZXRMYW5kc2NhcGVdKSlcbiAgICAgIC5zdWJzY3JpYmUoKHN0YXRlOiBCcmVha3BvaW50U3RhdGUpID0+IHtcbiAgICAgICAgaWYgKHRoaXMucGxhdGZvcm0uSU9TIHx8IHRoaXMucGxhdGZvcm0uQU5EUk9JRCkge1xuICAgICAgICAgIC8vIHRoaXMubGFuZHNjYXBlID0gc3RhdGUuYnJlYWtwb2ludHNbQnJlYWtwb2ludHMuSGFuZHNldExhbmRzY2FwZV07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbW9iaWxlID0gdGhpcy5wbGF0Zm9ybS5JT1M7XG4gICAgICAgIGlmIChzdGF0ZS5tYXRjaGVzICYmIG1vYmlsZSkge1xuICAgICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICAgIHRoaXMudXBkYXRlY2FudmFzU2l6ZSgpO1xuICAgICAgICAgIHRoaXMuZHJhd1JlY3RhbmdsZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICBpZiAodGhpcy5zd2l0Y2hDYW1lcmEpIHtcbiAgICAgIGlmICh0aGlzLnN3aXRjaENhbWVyYVN1YnNjcmlwdGlvbikge1xuICAgICAgICB0aGlzLnN3aXRjaENhbWVyYVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgfVxuXG4gICAgICAvLyBTdWJzY3JpYmUgdG8gZXZlbnRzIGZyb20gdGhpcyBPYnNlcnZhYmxlIHRvIHN3aXRjaCB2aWRlbyBkZXZpY2VcbiAgICAgIHRoaXMuc3dpdGNoQ2FtZXJhU3Vic2NyaXB0aW9uID0gdGhpcy5zd2l0Y2hDYW1lcmEuc3Vic2NyaWJlKFxuICAgICAgICAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHRoaXMuc3dpdGNoVG9WaWRlb0lucHV0KHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmRldGVjdEF2YWlsYWJsZURldmljZXMoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBzdGFydCB2aWRlb1xuXG4gICAgICAgIGlmICh0aGlzLmNhblN0YXJ0KSB7XG4gICAgICAgICAgdGhpcy5zd2l0Y2hUb1ZpZGVvSW5wdXQoJycpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnI6IHN0cmluZykgPT4ge1xuICAgICAgICB0aGlzLmluaXRFcnJvci5uZXh0KDxXZWJjYW1Jbml0RXJyb3I+eyBtZXNzYWdlOiBlcnIgfSk7XG4gICAgICAgIC8vIGZhbGxiYWNrOiBzdGlsbCB0cnkgdG8gbG9hZCB3ZWJjYW0sIGV2ZW4gaWYgZGV2aWNlIGVudW1lcmF0aW9uIGZhaWxlZFxuICAgICAgICBpZiAodGhpcy5jYW5TdGFydCkge1xuICAgICAgICAgIHRoaXMuc3dpdGNoVG9WaWRlb0lucHV0KCcnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5jYW5TdGFydCA9IGZhbHNlO1xuICAgIHRoaXMubmF0aXZlVmlkZW9FbGVtZW50LnBhdXNlKCk7XG4gICAgdGhpcy5kZXN0cm95ZWQuZW1pdCh0cnVlKTtcbiAgICB0aGlzLnN0b3BNZWRpYVRyYWNrcygpO1xuICAgIHRoaXMudW5zdWJzY3JpYmVGcm9tU3Vic2NyaXB0aW9ucygpO1xuICAgIHRoaXMuc2h1dGRvd24gPSB0cnVlO1xuXG4gICAgLy8gc2h1dCBkb3duIHdvcmtlclxuICAgIGlmICh0aGlzLmltYWdlSGFuZGxlcikge1xuICAgICAgdGhpcy5pbWFnZUhhbmRsZXIubmV4dCh7IHR5cGU6ICdzdG9wJyB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5uYXRpdmVWaWRlb0VsZW1lbnQuc3JjT2JqZWN0KSB7XG4gICAgICAoKHRoaXMubmF0aXZlVmlkZW9FbGVtZW50IGFzIEhUTUxWaWRlb0VsZW1lbnQpLnNyY09iamVjdCBhcyBNZWRpYVN0cmVhbSlcbiAgICAgICAgLmdldFRyYWNrcygpXG4gICAgICAgIC5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgfSk7XG4gICAgICB0aGlzLm5hdGl2ZVZpZGVvRWxlbWVudC5zcmNPYmplY3QgPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuX19kZXN0cm95KCk7XG5cbiAgICAvLyB0aGlzLm5hdGl2ZVZpZGVvRWxlbWVudC5zcmMgPSBudWxsO1xuICAgIC8vIHRoaXMubmF0aXZlVmlkZW9FbGVtZW50LnNyY09iamVjdCA9IG51bGw7XG4gIH1cblxuICBwcml2YXRlIHRha2VTZWxmaWUoKSB7XG4gICAgY29uc3QgX3ZpZGVvID0gdGhpcy5uYXRpdmVWaWRlb0VsZW1lbnQ7XG5cbiAgICBjb25zdCBtaW1lVHlwZTogc3RyaW5nID0gdGhpcy5pbWFnZVR5cGVcbiAgICAgID8gdGhpcy5pbWFnZVR5cGVcbiAgICAgIDogV2ViY2FtQ29tcG9uZW50LkRFRkFVTFRfSU1BR0VfVFlQRTtcblxuICAgIGxldCBfY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpOyAvL3RoaXMuY2FudmFzU25hcHNob3QubmF0aXZlRWxlbWVudDtcblxuICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gdGhpcy52aWRlb1NpemU7XG4gICAgY29uc29sZS5sb2cod2lkdGgsIGhlaWdodCk7XG5cbiAgICBjb25zdCB7IHBhZGRpbmcsIHRvcCwgcldpZHRoLCBySGVpZ2h0IH0gPSB0aGlzLnNuYXBSZWN0YW5nbGU7XG4gICAgX2NhbnZhcy53aWR0aCA9IHJXaWR0aDtcbiAgICBfY2FudmFzLmhlaWdodCA9IHJIZWlnaHQ7XG5cbiAgICBjb25zdCBjdHg6IGFueSA9IF9jYW52YXMuZ2V0Q29udGV4dCgnMmQnLCB7XG4gICAgICBhbHBoYTogZmFsc2UsXG4gICAgICBwb3dlclByZWZlcmVuY2U6ICdoaWdoLXBlcmZvcm1hbmNlJyxcbiAgICAgIGFudGlhbGlhczogZmFsc2UsXG4gICAgICBkZXB0aDogZmFsc2UsXG4gICAgICBkZXN5bmNocm9uaXplZDogdHJ1ZSxcbiAgICB9KTtcblxuICAgIGlmIChjdHgpIHtcbiAgICAgIGN0eC5kcmF3SW1hZ2UoXG4gICAgICAgIF92aWRlbyxcbiAgICAgICAgcGFkZGluZyxcbiAgICAgICAgdG9wLFxuICAgICAgICByV2lkdGgsXG4gICAgICAgIHJIZWlnaHQsXG4gICAgICAgIDAsXG4gICAgICAgIDAsXG4gICAgICAgIHJXaWR0aCxcbiAgICAgICAgckhlaWdodFxuICAgICAgKTtcblxuICAgICAgY29uc3QgaW1nQXNVcmw6IGFueSA9IF9jYW52YXMudG9EYXRhVVJMKG1pbWVUeXBlLCAxKTtcblxuICAgICAgdGhpcy5pbWFnZUNhcHR1cmUuZW1pdChcbiAgICAgICAgbmV3IFdlYmNhbUltYWdlKGltZ0FzVXJsLCBtaW1lVHlwZSwgbmV3IEltYWdlRGF0YSgxLCAxKSwgbnVsbClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgc25hcHNob3Qgb2YgdGhlIGN1cnJlbnQgd2ViY2FtJ3MgdmlldyBhbmQgZW1pdHMgdGhlIGltYWdlIGFzIGFuIGV2ZW50XG4gICAqL1xuXG4gIHB1YmxpYyB0YWtlU25hcHNob3QodGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudHlwZSA9PT0gJ3NlbGZpZScpIHtcbiAgICAgIHRoaXMudGFrZVNlbGZpZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRyYWNrUHJvY2Vzc29yKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBjb25zdCBjYW52YXNTbWFsU2l6ZSA9IDM4NDtcblxuICAgICAgY29uc3QgX3ZpZGVvID0gdGhpcy5uYXRpdmVWaWRlb0VsZW1lbnQ7XG5cbiAgICAgIGNvbnN0IG1pbWVUeXBlOiBzdHJpbmcgPSB0aGlzLmltYWdlVHlwZVxuICAgICAgICA/IHRoaXMuaW1hZ2VUeXBlXG4gICAgICAgIDogV2ViY2FtQ29tcG9uZW50LkRFRkFVTFRfSU1BR0VfVFlQRTtcblxuICAgICAgbGV0IF9jYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7IC8vdGhpcy5jYW52YXNTbmFwc2hvdC5uYXRpdmVFbGVtZW50O1xuXG4gICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IHRoaXMudmlkZW9TaXplO1xuXG4gICAgICBfY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICBfY2FudmFzLmhlaWdodCA9IGhlaWdodDtcblxuICAgICAgY29uc3QgY3R4OiBhbnkgPSBfY2FudmFzLmdldENvbnRleHQoJzJkJywge1xuICAgICAgICBhbHBoYTogZmFsc2UsXG4gICAgICAgIHBvd2VyUHJlZmVyZW5jZTogJ2hpZ2gtcGVyZm9ybWFuY2UnLFxuICAgICAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgICAgICBkZXB0aDogZmFsc2UsXG4gICAgICAgIGRlc3luY2hyb25pemVkOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpOyAvLyBuZWVkcyBhbiBpbml0aWFsIHNpemVcbiAgICAgIGNhbnZhcy5oZWlnaHQgPSBjYW52YXNTbWFsU2l6ZTtcbiAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhc1NtYWxTaXplO1xuXG4gICAgICBjb25zdCBjdHhPOiBhbnkgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnLCB7XG4gICAgICAgIGFscGhhOiBmYWxzZSxcbiAgICAgICAgcG93ZXJQcmVmZXJlbmNlOiAnaGlnaC1wZXJmb3JtYW5jZScsXG4gICAgICAgIGFudGlhbGlhczogZmFsc2UsXG4gICAgICAgIGRlcHRoOiBmYWxzZSxcbiAgICAgICAgZGVzeW5jaHJvbml6ZWQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgaWYgKGN0eCAmJiBjdHhPKSB7XG4gICAgICAgIGN0eC5pbWFnZVNtb290aGluZ0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICBjdHguZHJhd0ltYWdlKF92aWRlbywgMCwgMCk7XG4gICAgICAgIGN0eE8uZHJhd0ltYWdlKF92aWRlbywgMCwgMCwgY2FudmFzU21hbFNpemUsIGNhbnZhc1NtYWxTaXplKTtcblxuICAgICAgICBjb25zdCBpbURhdGE6IGFueSA9IGN0eC5nZXRJbWFnZURhdGEoXG4gICAgICAgICAgMCxcbiAgICAgICAgICAwLFxuICAgICAgICAgIHRoaXMudmlkZW9TaXplLndpZHRoLFxuICAgICAgICAgIHRoaXMudmlkZW9TaXplLmhlaWdodFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHJlc2l6ZSA9IGNhbnZhcy50b0RhdGFVUkwobWltZVR5cGUsIDEpO1xuXG4gICAgICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgIGNvbnN0IGRpZmYgPSBjdXJyZW50VGltZSAtIHRpbWU7XG5cbiAgICAgICAgY29uc3QgZGVsYXkgPSBkaWZmID4gMTAwID8gMCA6IDEwMCAtIGRpZmY7XG5cbiAgICAgICAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuaW1hZ2VDYXB0dXJlLmVtaXQobmV3IFdlYmNhbUltYWdlKCcnLCBtaW1lVHlwZSwgaW1EYXRhLCByZXNpemUpKTtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIH0sIGRlbGF5KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlKCkge31cblxuICByZXNpemVJbWFnZShiYXNlNjRkYXRhOiBhbnkpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcbiAgICAgIGxldCBjYW52YXM6IGFueSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICBjb25zdCBtYXhfc2l6ZSA9IDM4NDtcbiAgICAgIGxldCBpbWFnZTogYW55ID0gbmV3IEltYWdlKCk7XG5cbiAgICAgIGltYWdlLnNyYyA9IGJhc2U2NGRhdGE7XG4gICAgICBpbWFnZS5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgIGxldCB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgICAgICBsZXQgaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuXG4gICAgICAgIGlmICh3aWR0aCA8IGhlaWdodCkge1xuICAgICAgICAgIGhlaWdodCAqPSBtYXhfc2l6ZSAvIHdpZHRoO1xuICAgICAgICAgIHdpZHRoID0gbWF4X3NpemU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgd2lkdGggKj0gbWF4X3NpemUgLyBoZWlnaHQ7XG4gICAgICAgICAgaGVpZ2h0ID0gbWF4X3NpemU7XG4gICAgICAgIH1cbiAgICAgICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cbiAgICAgICAgLy8gY29uc29sZS5sb2cod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgaWYgKGN0eCkge1xuICAgICAgICAgIC8vIGN0eC5yb3RhdGUoKDkwICogTWF0aC5QSSkgLyAxODApO1xuICAgICAgICAgIC8vIGN0eC50cmFuc2xhdGUoMCwgLWNhbnZhcy53aWR0aCk7XG4gICAgICAgICAgY3R4LmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgMzg0LCAzODQpO1xuXG4gICAgICAgICAgb2JzZXJ2ZXIubmV4dChjYW52YXMudG9EYXRhVVJMKCkpO1xuICAgICAgICAgIGN0eC5jbGVhclJlY3QoMCwgMCwgMSwgMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoeyB0eXBlOiAnZ2VuZXJpYyBlcnJvcicgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaW1hZ2UgPSBudWxsO1xuICAgICAgICBjYW52YXMgPSBudWxsO1xuICAgICAgfTtcbiAgICAgIGltYWdlLm9uZXJyb3IgPSAoZTogYW55KSA9PiB7XG4gICAgICAgIG9ic2VydmVyLmVycm9yKGUpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTd2l0Y2hlcyB0byB0aGUgbmV4dC9wcmV2aW91cyB2aWRlbyBkZXZpY2VcbiAgICogQHBhcmFtIGZvcndhcmRcbiAgICovXG4gIHB1YmxpYyByb3RhdGVWaWRlb0lucHV0KGZvcndhcmQ6IGJvb2xlYW4pIHtcbiAgICBpZiAodGhpcy5hdmFpbGFibGVWaWRlb0lucHV0cyAmJiB0aGlzLmF2YWlsYWJsZVZpZGVvSW5wdXRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGNvbnN0IGluY3JlbWVudDogbnVtYmVyID0gZm9yd2FyZFxuICAgICAgICA/IDFcbiAgICAgICAgOiB0aGlzLmF2YWlsYWJsZVZpZGVvSW5wdXRzLmxlbmd0aCAtIDE7XG4gICAgICBjb25zdCBuZXh0SW5wdXRJbmRleCA9XG4gICAgICAgICh0aGlzLmFjdGl2ZVZpZGVvSW5wdXRJbmRleCArIGluY3JlbWVudCkgJVxuICAgICAgICB0aGlzLmF2YWlsYWJsZVZpZGVvSW5wdXRzLmxlbmd0aDtcbiAgICAgIHRoaXMuc3dpdGNoVG9WaWRlb0lucHV0KFxuICAgICAgICB0aGlzLmF2YWlsYWJsZVZpZGVvSW5wdXRzW25leHRJbnB1dEluZGV4XS5kZXZpY2VJZFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3dpdGNoZXMgdGhlIGNhbWVyYS12aWV3IHRvIHRoZSBzcGVjaWZpZWQgdmlkZW8gZGV2aWNlXG4gICAqL1xuICBwdWJsaWMgc3dpdGNoVG9WaWRlb0lucHV0KGRldmljZUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBpZihkZXZpY2VJZCl7XG4gICAgdGhpcy52aWRlb0luaXRpYWxpemVkID0gZmFsc2U7XG4gICAgdGhpcy5zdG9wTWVkaWFUcmFja3MoKTtcbiAgICB0aGlzLmluaXRXZWJjYW0oZGV2aWNlSWQsIHRoaXMudmlkZW9PcHRpb25zKTtcbiAgICAvLyB9XG4gIH1cblxuICAvKipcbiAgICogRXZlbnQtaGFuZGxlciBmb3IgdmlkZW8gcmVzaXplIGV2ZW50LlxuICAgKiBUcmlnZ2VycyBBbmd1bGFyIGNoYW5nZSBkZXRlY3Rpb24gc28gdGhhdCBuZXcgdmlkZW8gZGltZW5zaW9ucyBnZXQgYXBwbGllZFxuICAgKi9cbiAgcHVibGljIHZpZGVvUmVzaXplKCk6IHZvaWQge1xuICAgIC8vIGhlcmUgdG8gdHJpZ2dlciBBbmd1bGFyIGNoYW5nZSBkZXRlY3Rpb25cbiAgfVxuXG4gIHB1YmxpYyBnZXQgdmlkZW9XaWR0aCgpIHtcbiAgICBjb25zdCB2aWRlb1JhdGlvID0gdGhpcy5nZXRWaWRlb0FzcGVjdFJhdGlvKCk7XG4gICAgcmV0dXJuIE1hdGgubWluKHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0ICogdmlkZW9SYXRpbyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHZpZGVvSGVpZ2h0KCkge1xuICAgIGNvbnN0IHZpZGVvUmF0aW8gPSB0aGlzLmdldFZpZGVvQXNwZWN0UmF0aW8oKTtcbiAgICByZXR1cm4gTWF0aC5taW4odGhpcy5oZWlnaHQsIHRoaXMud2lkdGggLyB2aWRlb1JhdGlvKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdmlkZW9TdHlsZUNsYXNzZXMoKSB7XG4gICAgbGV0IGNsYXNzZXM6IHN0cmluZyA9ICcnO1xuXG4gICAgaWYgKHRoaXMuaXNNaXJyb3JJbWFnZSgpKSB7XG4gICAgICBjbGFzc2VzICs9ICdtaXJyb3JlZCAnO1xuICAgIH1cblxuICAgIHJldHVybiBjbGFzc2VzLnRyaW0oKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgbmF0aXZlVmlkZW9FbGVtZW50KCkge1xuICAgIHJldHVybiB0aGlzLnZpZGVvLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cbiAgLy8gcHVibGljIGdldCBzbWFsbFZpZGVvRWxlbWVudCgpIHtcbiAgLy8gICByZXR1cm4gdGhpcy52aWRlb1NtYWxsO1xuICAvLyB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHZpZGVvIGFzcGVjdCByYXRpbyBvZiB0aGUgYWN0aXZlIHZpZGVvIHN0cmVhbVxuICAgKi9cbiAgcHJpdmF0ZSBnZXRWaWRlb0FzcGVjdFJhdGlvKCk6IG51bWJlciB7XG4gICAgLy8gY2FsY3VsYXRlIHJhdGlvIGZyb20gdmlkZW8gZWxlbWVudCBkaW1lbnNpb25zIGlmIHByZXNlbnRcbiAgICBjb25zdCB2aWRlb0VsZW1lbnQgPSB0aGlzLm5hdGl2ZVZpZGVvRWxlbWVudDtcbiAgICBpZiAoXG4gICAgICB2aWRlb0VsZW1lbnQudmlkZW9XaWR0aCAmJlxuICAgICAgdmlkZW9FbGVtZW50LnZpZGVvV2lkdGggPiAwICYmXG4gICAgICB2aWRlb0VsZW1lbnQudmlkZW9IZWlnaHQgJiZcbiAgICAgIHZpZGVvRWxlbWVudC52aWRlb0hlaWdodCA+IDBcbiAgICApIHtcbiAgICAgIHJldHVybiB2aWRlb0VsZW1lbnQudmlkZW9XaWR0aCAvIHZpZGVvRWxlbWVudC52aWRlb0hlaWdodDtcbiAgICB9XG5cbiAgICAvLyBub3RoaW5nIHByZXNlbnQgLSBjYWxjdWxhdGUgcmF0aW8gYmFzZWQgb24gd2lkdGgvaGVpZ2h0IHBhcmFtc1xuICAgIHJldHVybiB0aGlzLndpZHRoIC8gdGhpcy5oZWlnaHQ7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVNpemUoKSB7XG4gICAgY29uc3QgdHJhY2s6IE1lZGlhU3RyZWFtVHJhY2sgfCB1bmRlZmluZWQgPVxuICAgICAgdGhpcy5tZWRpYVN0cmVhbT8uZ2V0VHJhY2tzKClbMF07XG5cbiAgICBpZiAodHJhY2spIHtcbiAgICAgIGxldCBkZXNpcmVkOiBhbnkgPSB7XG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgaWRlYWw6IDAsXG4gICAgICAgIH0sXG4gICAgICAgIGhlaWdodDoge1xuICAgICAgICAgIGlkZWFsOiAwLFxuICAgICAgICB9LFxuXG4gICAgICAgIC8vICBmYWNpbmdNb2RlOid1c2VyJyxcbiAgICAgICAgZnJhbWVSYXRlOiB7IG1pbjogMjAsIGlkZWFsOiAyNCwgbWF4OiAyNCB9LFxuICAgICAgfTtcbiAgICAgIGlmICh0eXBlb2YgdHJhY2suZ2V0Q2FwYWJpbGl0aWVzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gdHJhY2suZ2V0Q2FwYWJpbGl0aWVzKCk7XG4gICAgICAgIGRlc2lyZWQgPSB7XG4gICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgIGlkZWFsOiB0aGlzLmxhbmRzY2FwZSAmJiB0aGlzLmlzTW9iaWxlID8gaGVpZ2h0Py5tYXggOiB3aWR0aD8ubWF4LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogdGhpcy5sYW5kc2NhcGUgJiYgdGhpcy5pc01vYmlsZSA/IHdpZHRoPy5tYXggOiBoZWlnaHQ/Lm1heCxcbiAgICAgICAgICB9LFxuXG4gICAgICAgICAgLy8gIGZhY2luZ01vZGU6J3VzZXInLFxuICAgICAgICAgIGZyYW1lUmF0ZTogeyBtaW46IDIwLCBpZGVhbDogMjQsIG1heDogMjQgfSxcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlc2lyZWQgPSB7XG4gICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgIGlkZWFsOiAxOTIwLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICBpZGVhbDogMTA4MCxcbiAgICAgICAgICB9LFxuXG4gICAgICAgICAgLy8gIGZhY2luZ01vZGU6J3VzZXInLFxuICAgICAgICAgIGZyYW1lUmF0ZTogeyBtaW46IDIwLCBpZGVhbDogMzAsIG1heDogMzEgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKGRlc2lyZWQuaGVpZ2h0LmlkZWFsICYmIGRlc2lyZWQuaGVpZ2h0LmlkZWFsID49IDE2MDApIHtcbiAgICAgICAgZGVzaXJlZC5oZWlnaHQuaWRlYWwgPSAxNjAwO1xuICAgICAgICBkZXNpcmVkLndpZHRoLmlkZWFsID0gMTYwMDtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucGxhdGZvcm0uQU5EUk9JRCkge1xuICAgICAgICAvL2Rlc2lyZWQud2lkdGguaWRlYWwgPSAyMTYwO1xuICAgICAgICAvL2Rlc2lyZWQuaGVpZ2h0LmlkZWFsID0gMjE2MDtcbiAgICAgICAgLy8gaWYgKCF0aGlzLmxhbmRzY2FwZSkge1xuICAgICAgICAvLyB9IGVsc2Uge1xuICAgICAgICAvLyAgIGRlc2lyZWQud2lkdGguaWRlYWwgPSB3aWR0aD8ubWF4O1xuICAgICAgICAvLyAgIGRlc2lyZWQuaGVpZ2h0LmlkZWFsID0gaGVpZ2h0Py5tYXg7XG4gICAgICAgIC8vIH1cbiAgICAgIH1cblxuICAgICAgdHJhY2suYXBwbHlDb25zdHJhaW50cyhkZXNpcmVkKTtcblxuICAgICAgLy90cmFjay5nZXRTZXR0aW5ncygpLmZhY2luZ01vZGUhPT0ndXNlcic7XG5cbiAgICAgIHRoaXMudmlkZW9TaXplID0ge1xuICAgICAgICBoZWlnaHQ6IHRoaXMubGFuZHNjYXBlXG4gICAgICAgICAgPyB0cmFjay5nZXRTZXR0aW5ncygpLmhlaWdodFxuICAgICAgICAgIDogdHJhY2suZ2V0U2V0dGluZ3MoKS53aWR0aCxcbiAgICAgICAgd2lkdGg6IHRoaXMubGFuZHNjYXBlXG4gICAgICAgICAgPyB0cmFjay5nZXRTZXR0aW5ncygpLndpZHRoXG4gICAgICAgICAgOiB0cmFjay5nZXRTZXR0aW5ncygpLmhlaWdodCxcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIGdldFN0cmVhbVRyYWNrKHN0cmVhbTogTWVkaWFTdHJlYW0pIHtcbiAgICByZXR1cm4gc3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gIH1cblxuICBnZXRUcmFja1NldHRpbmdzKCkge31cblxuICBhY2Nlc1ZpZGVvVHJhY2sodmlkZW9UcmFja0NvbnN0cmFpbnRzOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzKTogYW55IHtcbiAgICByZXR1cm4gZnJvbShcbiAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHZpZGVvVHJhY2tDb25zdHJhaW50cylcbiAgICApLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKHN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgICAgLy8gZGVmYXVsdCByZXNvbHV0aW9uIDEyODB4NzIwLCBjaGVjayBtYXggcmVzb2x1dGlvblxuXG4gICAgICAgIGNvbnN0IHRyYWNrID0gdGhpcy5nZXRTdHJlYW1UcmFjayhzdHJlYW0pO1xuXG4gICAgICAgIGNvbnN0IGNhcGFiaWxpdGllcyA9IHRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuXG4gICAgICAgIGNvbnN0IHsgZmFjaW5nTW9kZSwgaGVpZ2h0LCB3aWR0aCB9ID0gY2FwYWJpbGl0aWVzO1xuXG4gICAgICAgIGNvbnN0IGRlc2lyZWQgPSB7XG4gICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgIG1pbjogdGhpcy5sYW5kc2NhcGUgJiYgdGhpcy5pc01vYmlsZSA/IGhlaWdodD8ubWF4IDogd2lkdGg/Lm1heCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIC8vIGhlaWdodDoge1xuICAgICAgICAgIC8vICAgZXhhY3Q6IHRoaXMubGFuZHNjYXBlICYmIHRoaXMuaXNNb2JpbGUgPyB3aWR0aD8ubWF4IDogaGVpZ2h0Py5tYXgsXG4gICAgICAgICAgLy8gfSxcbiAgICAgICAgICAvLyBmYWNpbmdNb2RlOidlbicsXG4gICAgICAgICAgLy8gZnJhbWVSYXRlOiB7IG1pbjogMjUsIGlkZWFsOiAzMCwgbWF4OiAzMSB9LFxuICAgICAgICB9O1xuICAgICAgICAvLyBnZXQgbWF4IHdpZHRoXG5cbiAgICAgICAgY29uc3QgeyB3aWR0aDogc1dpZHRoLCBoZWlnaHQ6IHNIZWlnaHQgfSA9IHRyYWNrLmdldFNldHRpbmdzKCk7XG5cbiAgICAgICAgaWYgKGRlc2lyZWQud2lkdGgubWluICE9IHNXaWR0aCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLmFjY2VzVmlkZW9UcmFjayh7IHZpZGVvOiBkZXNpcmVkIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9yZXR1cm4gdGhpcy5hY2Nlc1ZpZGVvVHJhY2soe3ZpZGVvOmRlc2lyZWR9KTtcblxuICAgICAgICByZXR1cm4gb2Yoc3RyZWFtKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZHJhd1JlY3RhbmdsZSgpIHtcbiAgICBjb25zdCBfY2FudmFzID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudDtcblxuICAgIGNvbnN0IGN0eCA9IF9jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHguY2xlYXJSZWN0KDAsIDAsIF9jYW52YXMud2lkdGgsIF9jYW52YXMuaGVpZ2h0KTtcblxuICAgIC8vIGN0eC5kcmF3SW1hZ2UoX3ZpZGVvLCAwLCAwLCBfY2FudmFzLndpZHRoLCBfY2FudmFzLmhlaWdodCk7XG5cbiAgICBjb25zdCB7IHBhZGRpbmcsIHRvcCwgcldpZHRoLCBySGVpZ2h0IH0gPSB0aGlzLmNhcmRSZWN0YW5nbGU7XG5cbiAgICBjdHguc3Ryb2tlU3R5bGUgPSAncmVkJztcblxuICAgIGN0eC5zdHJva2VSZWN0KHBhZGRpbmcsIHRvcCwgcldpZHRoLCBySGVpZ2h0KTtcbiAgfVxuXG4gIGdldE1heEF2YWlsYWJsZVJlc29sdXRpb24oKSB7fVxuICAvKipcbiAgICogSW5pdCB3ZWJjYW0gbGl2ZSB2aWV3XG4gICAqL1xuICBwcml2YXRlIGluaXRXZWJjYW0oXG4gICAgZGV2aWNlSWQ6IHN0cmluZyxcbiAgICB1c2VyVmlkZW9UcmFja0NvbnN0cmFpbnRzOiBNZWRpYVRyYWNrQ29uc3RyYWludHNcbiAgKSB7XG4gICAgY29uc3QgX3ZpZGVvID0gdGhpcy5uYXRpdmVWaWRlb0VsZW1lbnQ7XG4gICAgLy8gY29uc3QgdmlkZW9TdHJlYW1lciA9IHRoaXMudmlkZW9TdHJlYW1lci5uYXRpdmVFbGVtZW50O1xuICAgIC8vIGNvbnN0IHZpZGVvU21hbGwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xuICAgIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmIG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKSB7XG4gICAgICAvLyBtZXJnZSBkZXZpY2VJZCAtPiB1c2VyVmlkZW9UcmFja0NvbnN0cmFpbnRzXG4gICAgICBjb25zdCB2aWRlb1RyYWNrQ29uc3RyYWludHMgPVxuICAgICAgICBXZWJjYW1Db21wb25lbnQuZ2V0TWVkaWFDb25zdHJhaW50c0ZvckRldmljZShcbiAgICAgICAgICBkZXZpY2VJZCxcbiAgICAgICAgICB1c2VyVmlkZW9UcmFja0NvbnN0cmFpbnRzXG4gICAgICAgICk7XG5cbiAgICAgIC8vIC8vIGlmIChkZXZpY2VJZCkge1xuICAgICAgLy8gdGhpcy5hY2Nlc1ZpZGVvVHJhY2soeyB2aWRlbzogdmlkZW9UcmFja0NvbnN0cmFpbnRzIH0pLnN1YnNjcmliZShcbiAgICAgIC8vICAgKHN0cmVhbTogTWVkaWFTdHJlYW0pID0+IHtcbiAgICAgIC8vICAgICBjb25zb2xlLmxvZyhcbiAgICAgIC8vICAgICAgICdWQUxJRCBTRVRUSU5HUycsXG4gICAgICAvLyAgICAgICBzdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpXG4gICAgICAvLyAgICAgKTtcbiAgICAgIC8vICAgfVxuICAgICAgLy8gKTtcbiAgICAgIC8vIH1cbiAgICAgIGlmICh0aGlzLnBsYXRmb3JtLkFORFJPSUQpIHtcbiAgICAgICAgdmlkZW9UcmFja0NvbnN0cmFpbnRzLndpZHRoID0gMTYwMDtcbiAgICAgICAgdmlkZW9UcmFja0NvbnN0cmFpbnRzLmhlaWdodCA9IDE2MDA7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbnN0cmFpbnRzID0ge1xuICAgICAgICBleGFjdDogZGV2aWNlSWQsXG4gICAgICAgIHdpZHRoOiB7IG1pbjogNDgwLCBpZGVhbDogMTI4MCB9LFxuICAgICAgICBoZWlnaHQ6IHsgbWluOiA0ODAsIGlkZWFsOiA3MjAgfSxcbiAgICAgICAgLy8gYXNwZWN0UmF0aW86IDMgLyAyLFxuICAgICAgICBmcmFtZVJhdGU6IHsgbWluOiAyMCB9LFxuICAgICAgfTtcblxuICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1xuICAgICAgICAuZ2V0VXNlck1lZGlhKDxNZWRpYVN0cmVhbUNvbnN0cmFpbnRzPnsgdmlkZW86IHZpZGVvVHJhY2tDb25zdHJhaW50cyB9KVxuICAgICAgICAudGhlbigoc3RyZWFtOiBNZWRpYVN0cmVhbSkgPT4ge1xuICAgICAgICAgIHRoaXMubWVkaWFTdHJlYW0gPSBzdHJlYW07XG4gICAgICAgICAgX3ZpZGVvLnNyY09iamVjdCA9IHN0cmVhbTtcblxuICAgICAgICAgIHRoaXMudXBkYXRlU2l6ZSgpO1xuICAgICAgICAgIHRoaXMudXBkYXRlY2FudmFzU2l6ZSgpO1xuXG4gICAgICAgICAgX3ZpZGVvLnBsYXkoKTtcblxuICAgICAgICAgIF92aWRlby5vbnBsYXkgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNldEFjdGl2ZUNhbWVyYShzdHJlYW0pO1xuICAgICAgICAgICAgdGhpcy5kcmF3UmVjdGFuZ2xlKCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKChlcnI6IGFueSkgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGVycik7XG4gICAgICAgICAgdGhpcy5pbml0RXJyb3IubmV4dCg8V2ViY2FtSW5pdEVycm9yPntcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgbWVkaWFTdHJlYW1FcnJvcjogZXJyLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pbml0RXJyb3IubmV4dCg8V2ViY2FtSW5pdEVycm9yPntcbiAgICAgICAgbWVzc2FnZTogJ0Nhbm5vdCByZWFkIFVzZXJNZWRpYSBmcm9tIE1lZGlhRGV2aWNlcy4nLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGlzTW9iaWxlKCkge1xuICAgIHJldHVybiB0aGlzLnBsYXRmb3JtLkFORFJPSUQgfHwgdGhpcy5wbGF0Zm9ybS5JT1M7XG4gIH1cblxuICBnZXQgY2FyZFJlY3RhbmdsZSgpIHtcbiAgICBjb25zdCBfY2FudmFzID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCBkb2NTaXplID0gdGhpcy50eXBlID09PSAnc2VsZmllJyA/IDEgOiA4NiAvIDU1O1xuXG4gICAgbGV0IHBhZGRpbmcgPSAxMDtcblxuICAgIGxldCByV2lkdGggPSBfY2FudmFzLndpZHRoIC0gMiAqIHBhZGRpbmc7XG4gICAgbGV0IHJIZWlnaHQgPSByV2lkdGggLyBkb2NTaXplO1xuICAgIGxldCB0b3AgPSAoX2NhbnZhcy5oZWlnaHQgLSBySGVpZ2h0KSAvIDI7XG5cbiAgICBpZiAoIXRoaXMuaXNNb2JpbGUpIHtcbiAgICAgIHBhZGRpbmcgPSA0MDtcblxuICAgICAgckhlaWdodCA9IF9jYW52YXMuaGVpZ2h0IC0gMiAqIHBhZGRpbmc7XG4gICAgICByV2lkdGggPSBySGVpZ2h0ICogZG9jU2l6ZTtcbiAgICAgIHRvcCA9IChfY2FudmFzLmhlaWdodCAtIHJIZWlnaHQpIC8gMjtcbiAgICAgIHBhZGRpbmcgPSAoX2NhbnZhcy53aWR0aCAtIHJXaWR0aCkgLyAyO1xuICAgIH1cblxuICAgIHJldHVybiB7IHBhZGRpbmcsIHRvcCwgcldpZHRoLCBySGVpZ2h0IH07XG4gIH1cbiAgZ2V0IHNuYXBSZWN0YW5nbGUoKSB7XG4gICAgY29uc3QgX2NhbnZhcyA9IHRoaXMuY2FudmFzLm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICBjb25zdCBhciA9IHRoaXMudmlkZW9TaXplLndpZHRoIC8gX2NhbnZhcy53aWR0aDtcblxuICAgIGxldCB7IHBhZGRpbmcsIHRvcCwgcldpZHRoLCBySGVpZ2h0IH0gPSB0aGlzLmNhcmRSZWN0YW5nbGU7XG5cbiAgICBwYWRkaW5nID0gcGFkZGluZyAqIGFyO1xuICAgIHRvcCA9IHRvcCAqIGFyO1xuICAgIHJXaWR0aCA9IHJXaWR0aCAqIGFyO1xuICAgIHJIZWlnaHQgPSBySGVpZ2h0ICogYXI7XG5cbiAgICByZXR1cm4geyBwYWRkaW5nLCB0b3AsIHJXaWR0aCwgckhlaWdodCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRBY3RpdmVDYW1lcmEoc3RyZWFtOiBhbnkpIHtcbiAgICB0aGlzLnZpZGVvUmVhZHkubmV4dChmYWxzZSk7XG4gICAgdGhpcy5zaG93VmlkZW8gPSBmYWxzZTtcbiAgICB0aGlzLmFjdGl2ZVZpZGVvU2V0dGluZ3MgPSBzdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXS5nZXRTZXR0aW5ncygpO1xuICAgIGNvbnN0IGFjdGl2ZURldmljZUlkOiBzdHJpbmcgPVxuICAgICAgV2ViY2FtQ29tcG9uZW50LmdldERldmljZUlkRnJvbU1lZGlhU3RyZWFtVHJhY2soXG4gICAgICAgIHN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdXG4gICAgICApO1xuXG4gICAgY29uc3QgdmlkZW9UcmFjayA9IHN0cmVhbS5nZXRUcmFja3MoKVswXTtcbiAgICB0aGlzLnRyYWNrU2V0dGluZ3MgPSB2aWRlb1RyYWNrLmdldFNldHRpbmdzKCk7XG5cbiAgICB0aGlzLmNhbWVyYVByb3ZpZGVyLmNhbWVyYVdhc1N3aXRjaGVkKGFjdGl2ZURldmljZUlkKTtcblxuICAgIHRoaXMuY2FtZXJhU3dpdGNoZWQubmV4dChhY3RpdmVEZXZpY2VJZCk7XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnJlc2l6ZVN0YWdlKCk7XG4gICAgICAgIHRoaXMuc2hvd1ZpZGVvID0gdHJ1ZTtcbiAgICAgICAgdGhpcy52aWRlb1JlYWR5Lm5leHQodHJ1ZSk7XG5cbiAgICAgICAgaWYgKE1lZGlhU3RyZWFtVHJhY2tQcm9jZXNzb3IpIHtcbiAgICAgICAgICB0aGlzLnRyYWNrUHJvY2Vzc29yID0gbmV3IE1lZGlhU3RyZWFtVHJhY2tQcm9jZXNzb3IodmlkZW9UcmFjayk7XG4gICAgICAgICAgbGV0IGZyYW1lU3RyZWFtID0gdGhpcy50cmFja1Byb2Nlc3Nvci5yZWFkYWJsZTtcbiAgICAgICAgICBpZiAoIXRoaXMuc2h1dGRvd24pIHtcbiAgICAgICAgICAgIHRoaXMud29ya2VyPy5wb3N0TWVzc2FnZShcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdzdGFydCcsXG5cbiAgICAgICAgICAgICAgICBmcmFtZVN0cmVhbTogZnJhbWVTdHJlYW0sXG4gICAgICAgICAgICAgICAgdHJhY2tTZXR0aW5nczogdGhpcy50cmFja1NldHRpbmdzLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBbZnJhbWVTdHJlYW1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSwgNTAwKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWN0aXZlVmlkZW9UcmFjaygpOiBNZWRpYVN0cmVhbVRyYWNrIHwgYW55IHtcbiAgICByZXR1cm4gdGhpcy5tZWRpYVN0cmVhbSA/IHRoaXMubWVkaWFTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXSA6IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGlzTWlycm9ySW1hZ2UoKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmdldEFjdGl2ZVZpZGVvVHJhY2soKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGZvciBleHBsaWNpdCBtaXJyb3Igb3ZlcnJpZGUgcGFyYW1ldGVyXG4gICAge1xuICAgICAgbGV0IG1pcnJvcjogc3RyaW5nID0gJ2F1dG8nO1xuICAgICAgaWYgKHRoaXMubWlycm9ySW1hZ2UpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm1pcnJvckltYWdlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIG1pcnJvciA9IFN0cmluZyh0aGlzLm1pcnJvckltYWdlKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFdlYmNhbU1pcnJvclByb3BlcnRpZXNcbiAgICAgICAgICBpZiAodGhpcy5taXJyb3JJbWFnZS54KSB7XG4gICAgICAgICAgICBtaXJyb3IgPSB0aGlzLm1pcnJvckltYWdlLngudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc3dpdGNoIChtaXJyb3IpIHtcbiAgICAgICAgY2FzZSAnYWx3YXlzJzpcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgY2FzZSAnbmV2ZXInOlxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkZWZhdWx0OiBlbmFibGUgbWlycm9yaW5nIGlmIHdlYmNhbSBpcyB1c2VyIGZhY2luZ1xuICAgIHJldHVybiBXZWJjYW1Db21wb25lbnQuaXNVc2VyRmFjaW5nKHRoaXMuZ2V0QWN0aXZlVmlkZW9UcmFjaygpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdG9wcyBhbGwgYWN0aXZlIG1lZGlhIHRyYWNrcy5cbiAgICogVGhpcyBwcmV2ZW50cyB0aGUgd2ViY2FtIGZyb20gYmVpbmcgaW5kaWNhdGVkIGFzIGFjdGl2ZSxcbiAgICogZXZlbiBpZiBpdCBpcyBubyBsb25nZXIgdXNlZCBieSB0aGlzIGNvbXBvbmVudC5cbiAgICovXG4gIHByaXZhdGUgc3RvcE1lZGlhVHJhY2tzKCkge1xuICAgIC8vIHRoaXMudmlkZW8ubmF0aXZlRWxlbWVudC5wYXVzZSgpO1xuICAgIGlmICh0aGlzLnZpZGVvLm5hdGl2ZUVsZW1lbnQuc3JjT2JqZWN0KSB7XG4gICAgICAoKHRoaXMudmlkZW8ubmF0aXZlRWxlbWVudCBhcyBIVE1MVmlkZW9FbGVtZW50KS5zcmNPYmplY3QgYXMgTWVkaWFTdHJlYW0pXG4gICAgICAgIC5nZXRUcmFja3MoKVxuICAgICAgICAuZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgICAgICB0cmFjay5zdG9wKCk7XG4gICAgICAgIH0pO1xuICAgICAgdGhpcy52aWRlby5uYXRpdmVFbGVtZW50LnNyY09iamVjdCA9IG51bGw7XG4gICAgICB0aGlzLnZpZGVvLm5hdGl2ZUVsZW1lbnQuc3JjID0gJyc7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubWVkaWFTdHJlYW0gJiYgdGhpcy5tZWRpYVN0cmVhbS5nZXRUcmFja3MpIHtcbiAgICAgIC8vIGdldFRyYWNrcygpIHJldHVybnMgYWxsIG1lZGlhIHRyYWNrcyAodmlkZW8rYXVkaW8pXG5cbiAgICAgIHRoaXMubWVkaWFTdHJlYW1cbiAgICAgICAgLmdldFRyYWNrcygpXG4gICAgICAgIC5mb3JFYWNoKCh0cmFjazogTWVkaWFTdHJlYW1UcmFjaykgPT4gdHJhY2suc3RvcCgpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW5zdWJzY3JpYmUgZnJvbSBhbGwgb3BlbiBzdWJzY3JpcHRpb25zXG4gICAqL1xuICBwcml2YXRlIHVuc3Vic2NyaWJlRnJvbVN1YnNjcmlwdGlvbnMoKSB7XG4gICAgaWYgKHRoaXMudHJpZ2dlclN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy50cmlnZ2VyU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnN3aXRjaENhbWVyYVN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5zd2l0Y2hDYW1lcmFTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgYXZhaWxhYmxlIGlucHV0IGRldmljZXNcbiAgICovXG4gIHByaXZhdGUgZGV0ZWN0QXZhaWxhYmxlRGV2aWNlcygpOiBQcm9taXNlPE1lZGlhRGV2aWNlSW5mb1tdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIFdlYmNhbVV0aWwuZ2V0QXZhaWxhYmxlVmlkZW9JbnB1dHMoKS5zdWJzY3JpYmUoXG4gICAgICAgIChkZXZpY2VzOiBNZWRpYURldmljZUluZm9bXSkgPT4ge1xuICAgICAgICAgIHRoaXMuYXZhaWxhYmxlVmlkZW9JbnB1dHMgPSBkZXZpY2VzO1xuICAgICAgICAgIHJlc29sdmUoZGV2aWNlcyk7XG4gICAgICAgIH0sXG4gICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICB0aGlzLmF2YWlsYWJsZVZpZGVvSW5wdXRzID0gW107XG4gICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJ3ZWJjYW0td3JhcHBlclwiPlxuICA8ZGl2PlxuICAgIDx2aWRlb1xuICAgICAgI3ZpZGVvXG4gICAgICBhdXRvcGxheVxuICAgICAgbXV0ZWRcbiAgICAgIHN0eWxlPVwiZGlzcGxheTogYmxvY2tcIlxuICAgICAgcGxheXNpbmxpbmVcblxuICAgID48L3ZpZGVvPlxuXG4gICAgPGRpdiBjbGFzcz1cInJlY3RhbmdsZVwiPlxuXG4gICAgICA8Y2FudmFzXG4gICAgICAgICNjYW52YXNcbiAgICAgICAgW25nU3R5bGVdPVwieyB2aXNpYmlsaXR5OiBzaG93VmlkZW8gPyAndmlzaWJsZScgOiAnaGlkZGVuJyB9XCJcbiAgICAgICAgW3dpZHRoXT1cImNhbnZhc1NpemUud2lkdGhcIlxuICAgICAgICBbaGVpZ2h0XT1cImNhbnZhc1NpemUuaGVpZ2h0XCJcbiAgICAgID48L2NhbnZhcz5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==
|