ngx-scandoc 1.2.3 → 1.3.0

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