@testgorilla/tgo-ai-interview-test 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +32 -0
  2. package/esm2022/index.mjs +4 -0
  3. package/esm2022/lib/components/ai-interview-test/ai-interview-test.component.mjs +180 -0
  4. package/esm2022/lib/components/index.mjs +4 -0
  5. package/esm2022/lib/components/interview-stream/interview-stream.component.mjs +240 -0
  6. package/esm2022/lib/components/interview-video/interview-video.component.mjs +61 -0
  7. package/esm2022/lib/models/index.mjs +6 -0
  8. package/esm2022/lib/models/question-component.mjs +2 -0
  9. package/esm2022/lib/models/translations.mjs +3 -0
  10. package/esm2022/shared/index.mjs +5 -0
  11. package/esm2022/shared/lib/components/audio-animation/audio-animation.component.mjs +114 -0
  12. package/esm2022/shared/lib/components/audio-animation/index.mjs +2 -0
  13. package/esm2022/shared/lib/components/index.mjs +3 -0
  14. package/esm2022/shared/lib/components/vimeo-video/index.mjs +2 -0
  15. package/esm2022/shared/lib/components/vimeo-video/vimeo-video.component.mjs +101 -0
  16. package/esm2022/shared/lib/models/answer.mjs +2 -0
  17. package/esm2022/shared/lib/models/assessment.mjs +2 -0
  18. package/esm2022/shared/lib/models/environment.mjs +2 -0
  19. package/esm2022/shared/lib/models/index.mjs +9 -0
  20. package/esm2022/shared/lib/models/question-component.mjs +2 -0
  21. package/esm2022/shared/lib/models/question.mjs +2 -0
  22. package/esm2022/shared/lib/models/test.mjs +2 -0
  23. package/esm2022/shared/lib/models/translations.mjs +2 -0
  24. package/esm2022/shared/lib/models/window.mjs +2 -0
  25. package/esm2022/shared/lib/services/api/api.service.mjs +97 -0
  26. package/esm2022/shared/lib/services/api/mocked-api.service.mjs +131 -0
  27. package/esm2022/shared/lib/services/environment/environment.service.mjs +13 -0
  28. package/esm2022/shared/lib/services/index.mjs +10 -0
  29. package/esm2022/shared/lib/services/localization/languages.model.mjs +19 -0
  30. package/esm2022/shared/lib/services/localization/transloco-lazy-module-utils.mjs +27 -0
  31. package/esm2022/shared/lib/services/localization/transloco-testing.module.mjs +11 -0
  32. package/esm2022/shared/lib/services/media/media.service.mjs +129 -0
  33. package/esm2022/shared/lib/services/mixpanel/mixpanel.service.mjs +30 -0
  34. package/esm2022/shared/lib/services/theme/theme.service.mjs +24 -0
  35. package/esm2022/shared/test-mocks/assessment-test.mock.mjs +112 -0
  36. package/esm2022/shared/test-mocks/index.mjs +3 -0
  37. package/esm2022/shared/test-mocks/tgo-ui.mock.mjs +39 -0
  38. package/esm2022/testgorilla-tgo-ai-interview-test.mjs +5 -0
  39. package/fesm2022/testgorilla-tgo-ai-interview-test.mjs +484 -0
  40. package/fesm2022/testgorilla-tgo-ai-interview-test.mjs.map +1 -0
  41. package/lib/components/ai-interview-test/ai-interview-test.component.d.ts +44 -0
  42. package/lib/components/interview-stream/interview-stream.component.d.ts +46 -0
  43. package/lib/components/interview-video/interview-video.component.d.ts +16 -0
  44. package/lib/models/index.d.ts +3 -0
  45. package/lib/models/question-component.d.ts +5 -0
  46. package/lib/models/translations.d.ts +1 -0
  47. package/package.json +18 -9
  48. package/shared/index.d.ts +4 -0
  49. package/shared/lib/components/audio-animation/audio-animation.component.d.ts +27 -0
  50. package/shared/lib/components/audio-animation/index.d.ts +1 -0
  51. package/shared/lib/components/index.d.ts +2 -0
  52. package/shared/lib/components/vimeo-video/index.d.ts +1 -0
  53. package/shared/lib/components/vimeo-video/vimeo-video.component.d.ts +24 -0
  54. package/shared/lib/models/answer.d.ts +17 -0
  55. package/shared/lib/models/assessment.d.ts +80 -0
  56. package/shared/lib/models/environment.d.ts +1 -0
  57. package/shared/lib/models/index.d.ts +8 -0
  58. package/shared/lib/models/question-component.d.ts +54 -0
  59. package/shared/lib/models/question.d.ts +102 -0
  60. package/shared/lib/models/test.d.ts +81 -0
  61. package/shared/lib/models/translations.d.ts +1 -0
  62. package/shared/lib/models/window.d.ts +6 -0
  63. package/shared/lib/services/api/api.service.d.ts +25 -0
  64. package/shared/lib/services/api/mocked-api.service.d.ts +35 -0
  65. package/shared/lib/services/environment/environment.service.d.ts +6 -0
  66. package/shared/lib/services/index.d.ts +9 -0
  67. package/shared/lib/services/localization/languages.model.d.ts +15 -0
  68. package/shared/lib/services/localization/transloco-lazy-module-utils.d.ts +11 -0
  69. package/shared/lib/services/localization/transloco-testing.module.d.ts +2 -0
  70. package/shared/lib/services/media/media.service.d.ts +29 -0
  71. package/shared/lib/services/mixpanel/mixpanel.service.d.ts +10 -0
  72. package/shared/lib/services/theme/theme.service.d.ts +8 -0
  73. package/shared/test-mocks/assessment-test.mock.d.ts +21 -0
  74. package/shared/test-mocks/index.d.ts +2 -0
  75. package/shared/test-mocks/tgo-ui.mock.d.ts +21 -0
  76. package/.eslintrc.json +0 -46
  77. package/jest.config.ts +0 -29
  78. package/ng-package.json +0 -16
  79. package/project.json +0 -37
  80. package/src/lib/components/ai-interview-test/ai-interview-test.component.html +0 -42
  81. package/src/lib/components/ai-interview-test/ai-interview-test.component.scss +0 -167
  82. package/src/lib/components/ai-interview-test/ai-interview-test.component.spec.ts +0 -211
  83. package/src/lib/components/ai-interview-test/ai-interview-test.component.ts +0 -193
  84. package/src/lib/components/interview-stream/interview-stream.component.html +0 -9
  85. package/src/lib/components/interview-stream/interview-stream.component.scss +0 -5
  86. package/src/lib/components/interview-stream/interview-stream.component.spec.ts +0 -285
  87. package/src/lib/components/interview-stream/interview-stream.component.ts +0 -321
  88. package/src/lib/components/interview-video/interview-video.component.html +0 -8
  89. package/src/lib/components/interview-video/interview-video.component.scss +0 -7
  90. package/src/lib/components/interview-video/interview-video.component.spec.ts +0 -140
  91. package/src/lib/components/interview-video/interview-video.component.ts +0 -68
  92. package/src/lib/models/index.ts +0 -13
  93. package/src/lib/models/question-component.ts +0 -13
  94. package/src/lib/models/translations.ts +0 -3
  95. package/src/test-setup.ts +0 -28
  96. package/tsconfig.json +0 -17
  97. package/tsconfig.lib.json +0 -15
  98. package/tsconfig.lib.prod.json +0 -10
  99. package/tsconfig.spec.json +0 -13
  100. /package/{src/assets → assets}/i18n/en.json +0 -0
  101. /package/{src/index.ts → index.d.ts} +0 -0
  102. /package/{src/lib/components/index.ts → lib/components/index.d.ts} +0 -0
package/README.md CHANGED
@@ -32,6 +32,38 @@ import { AiInterviewTestComponent } from '@testgorilla/tgo-ai-interview-test';
32
32
  export class MyComponent {}
33
33
  ```
34
34
 
35
+ ## Assets (translations)
36
+
37
+ This package ships its translations under `assets/i18n`. Consumer apps must copy these assets into their build output so Transloco can load them at runtime.
38
+
39
+ - **Angular CLI / Nx**: add an `assets` entry pointing at the package:
40
+
41
+ ```json
42
+ {
43
+ "assets": [
44
+ "src/favicon.ico",
45
+ "src/assets",
46
+ {
47
+ "glob": "**/*",
48
+ "input": "node_modules/@testgorilla/tgo-ai-interview-test/assets",
49
+ "output": "assets/tgo-ai-interview-test"
50
+ }
51
+ ]
52
+ }
53
+ ```
54
+
55
+ If you develop inside this repo (consuming the workspace sources), also include the local path:
56
+
57
+ ```json
58
+ {
59
+ "glob": "**/*",
60
+ "input": "packages/tgo-ai-interview-test/src/assets",
61
+ "output": "assets/tgo-ai-interview-test"
62
+ }
63
+ ```
64
+
65
+ After adding the asset entries, rebuild/re-serve your app so `/assets/tgo-ai-interview-test/i18n/en.json` is available.
66
+
35
67
  ## API
36
68
 
37
69
  ### Inputs
@@ -0,0 +1,4 @@
1
+ export * from './lib/components';
2
+ export * from './lib/components/ai-interview-test/ai-interview-test.component';
3
+ export * from './lib/models';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wYWNrYWdlcy90Z28tYWktaW50ZXJ2aWV3LXRlc3Qvc3JjL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxnRUFBZ0UsQ0FBQztBQUMvRSxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMnO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvY29tcG9uZW50cy9haS1pbnRlcnZpZXctdGVzdC9haS1pbnRlcnZpZXctdGVzdC5jb21wb25lbnQnO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzJztcbiJdfQ==
@@ -0,0 +1,180 @@
1
+ import { InterviewStreamComponent } from '../interview-stream/interview-stream.component';
2
+ import { firstValueFrom, Observable, takeUntil } from 'rxjs';
3
+ import { transition, style, animate, trigger } from '@angular/animations';
4
+ import { ElementRef, signal, ViewChild, Component, EventEmitter, Input, Output, inject, Inject, ChangeDetectorRef, } from '@angular/core';
5
+ import { Subject } from 'rxjs';
6
+ import { ButtonComponentModule, DialogService, IconComponentModule, } from '@testgorilla/tgo-ui';
7
+ import { CommonModule } from '@angular/common';
8
+ import { TRANSLOCO_SCOPE, TranslocoModule, TranslocoService, } from '@ngneat/transloco';
9
+ import { AudioAnimationComponent, ROOT_TRANSLATIONS_SCOPE, MediaService, ThemeService, TranslocoLazyModuleUtils, getAvailableLangs, } from '../../../shared/index.mjs';
10
+ import * as i0 from "@angular/core";
11
+ import * as i1 from "@testgorilla/tgo-ui";
12
+ import * as i2 from "@angular/common";
13
+ export class AiInterviewTestComponent {
14
+ translationScope;
15
+ videoElement;
16
+ audioElement;
17
+ question;
18
+ test;
19
+ isFirstQuestion = false;
20
+ selectedMediaDevices;
21
+ conversationUrl;
22
+ mediaAccessChanged;
23
+ submissionStateChanged = new EventEmitter();
24
+ loadingStateChanged = new EventEmitter();
25
+ requestMediaAccess = new EventEmitter();
26
+ isInterviewInProgress = signal(false);
27
+ candidateVideoStreamReady = signal(false);
28
+ translations = {};
29
+ hasMediaPermissions = signal(false);
30
+ unsubscribe$ = new Subject();
31
+ mediaService = inject(MediaService);
32
+ translocoService = inject(TranslocoService);
33
+ cdr = inject(ChangeDetectorRef);
34
+ themeService = inject(ThemeService);
35
+ companyColor = this.themeService.getCompanyColor();
36
+ constructor(translationScope) {
37
+ this.translationScope = translationScope;
38
+ }
39
+ ngOnInit() {
40
+ this.initMediaAccessSubscription();
41
+ this.loadingStateChanged.emit(true);
42
+ this.mediaService.setSelectedMediaDevices(this.selectedMediaDevices);
43
+ void this.checkMediaPermissions();
44
+ void this.setTranslations();
45
+ void this.initVideoStream();
46
+ }
47
+ ngOnDestroy() {
48
+ this.unsubscribe$.next();
49
+ this.unsubscribe$.complete();
50
+ }
51
+ onVideoLoad() {
52
+ this.candidateVideoStreamReady.set(true);
53
+ }
54
+ interviewStarted() {
55
+ this.isInterviewInProgress.set(true);
56
+ this.loadingStateChanged.emit(false);
57
+ }
58
+ interviewEnded() {
59
+ this.isInterviewInProgress.set(false);
60
+ this.submissionStateChanged.emit({
61
+ text: '',
62
+ });
63
+ }
64
+ async checkMediaPermissions() {
65
+ if (!(await this.mediaService.checkPermission({ audio: true, video: false }))) {
66
+ this.hasMediaPermissions.set(false);
67
+ this.requestMediaAccess.emit();
68
+ return;
69
+ }
70
+ else {
71
+ this.hasMediaPermissions.set(true);
72
+ }
73
+ }
74
+ async initVideoStream() {
75
+ try {
76
+ const stream = await this.mediaService.getMediaStream({
77
+ video: true,
78
+ audio: false,
79
+ });
80
+ if (this.videoElement) {
81
+ this.videoElement.nativeElement.srcObject = stream;
82
+ await this.videoElement?.nativeElement.play();
83
+ }
84
+ }
85
+ catch (error) {
86
+ console.error('Error initializing video stream:', error);
87
+ this.candidateVideoStreamReady.set(false);
88
+ }
89
+ }
90
+ async setTranslations() {
91
+ this.translations = await firstValueFrom(this.translocoService.selectTranslateObject(`TEST`, {}, this.translationScope));
92
+ this.cdr.markForCheck();
93
+ }
94
+ initMediaAccessSubscription() {
95
+ this.mediaAccessChanged
96
+ ?.pipe(takeUntil(this.unsubscribe$))
97
+ .subscribe((selectedMediaDevices) => {
98
+ this.mediaService.setSelectedMediaDevices(selectedMediaDevices);
99
+ this.checkMediaPermissions();
100
+ void this.initVideoStream();
101
+ });
102
+ }
103
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AiInterviewTestComponent, deps: [{ token: TRANSLOCO_SCOPE }], target: i0.ɵɵFactoryTarget.Component });
104
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AiInterviewTestComponent, isStandalone: true, selector: "tgo-ai-interview-test", inputs: { question: "question", test: "test", isFirstQuestion: "isFirstQuestion", selectedMediaDevices: "selectedMediaDevices", conversationUrl: "conversationUrl", mediaAccessChanged: "mediaAccessChanged" }, outputs: { submissionStateChanged: "submissionStateChanged", loadingStateChanged: "loadingStateChanged", requestMediaAccess: "requestMediaAccess" }, providers: [
105
+ TranslocoLazyModuleUtils.getScopeProvider('tgo-ai-interview-test', getAvailableLangs(), ROOT_TRANSLATIONS_SCOPE, (lang) => {
106
+ // Fetch from app assets; demo app copies the library assets to
107
+ // /assets/tgo-ai-interview-test via project.json.
108
+ const url = new URL(`assets/tgo-ai-interview-test/i18n/${lang}.json`, document.baseURI).href;
109
+ return fetch(url).then((res) => res.json());
110
+ }),
111
+ DialogService,
112
+ ThemeService,
113
+ ], viewQueries: [{ propertyName: "videoElement", first: true, predicate: ["video"], descendants: true }, { propertyName: "audioElement", first: true, predicate: ["audio"], descendants: true }], ngImport: i0, template: "<div class=\"ai-interview-test\">\n <div class=\"test-container\">\n <div\n class=\"media-container\"\n [class.is-video-visible]=\"isInterviewInProgress()\"\n >\n <div class=\"candidate-no-camera\" *ngIf=\"!candidateVideoStreamReady()\">\n <h3>&nbsp;</h3>\n <ui-icon name=\"User-profile-in-line\" color=\"white\" size=\"24\"></ui-icon>\n <h3 class=\"bold\">{{ translations['YOU'] }}</h3>\n </div>\n <div class=\"candidate-camera\" [hidden]=\"!candidateVideoStreamReady()\">\n <video\n height\n #video\n id=\"video\"\n playsinline\n (loadedmetadata)=\"onVideoLoad()\"\n ></video>\n <h3 class=\"bold\" *ngIf=\"candidateVideoStreamReady()\">\n {{ translations['YOU'] }}\n </h3>\n </div>\n <tgo-audio-animation\n *ngIf=\"isInterviewInProgress()\"\n [fakeData]=\"true\"\n ></tgo-audio-animation>\n <div class=\"interview-stream-container\">\n <tgo-interview-stream\n *ngIf=\"conversationUrl && hasMediaPermissions()\"\n [selectedMediaDevices]=\"selectedMediaDevices\"\n [conversationUrl]=\"conversationUrl\"\n (streamStart)=\"interviewStarted()\"\n (streamEnd)=\"interviewEnded()\"\n (checkMediaPermissions)=\"checkMediaPermissions()\"\n [translations]=\"translations\"\n ></tgo-interview-stream>\n </div>\n </div>\n </div>\n</div>\n\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}.ai-interview-test{background-color:#242424;padding:24px;display:flex;justify-content:center;min-height:calc(100vh - 80px)}.ai-interview-test h3{color:#fff}.ai-interview-test .test-container{min-width:360px;width:100%;min-height:300px;height:min(725px,100%,max(100vw,100vh,200px));max-width:calc(177.7777777778vh - 80px - 48px);display:flex;flex-direction:column;justify-content:space-between;position:relative;background-color:#242424}.ai-interview-test .media-container{position:relative;color:#fff;flex-grow:1}.ai-interview-test .media-container .interview-stream-container{border-radius:10px;aspect-ratio:16/9;border:4px solid #0165FC;margin:0 auto}.ai-interview-test .media-container .candidate-no-camera{position:absolute;width:200px;aspect-ratio:16/9;z-index:3;top:32px;left:32px;border-radius:10px;background-color:#1a47aa;display:flex;justify-content:space-between;flex-direction:column;padding:16px}.ai-interview-test .media-container .candidate-no-camera ui-icon{margin:auto}.ai-interview-test .media-container .candidate-camera{position:absolute;width:200px;top:32px;left:32px;z-index:3}.ai-interview-test .media-container .candidate-camera video{width:200px;border-radius:10px}.ai-interview-test .media-container .candidate-camera h3{position:absolute;bottom:16px;left:16px}.ai-interview-test .media-container tgo-audio-animation{position:absolute;top:32px;right:32px;z-index:1}.ai-interview-test .media-container tgo-vimeo-video{display:none;position:absolute;height:100%;width:100%}.ai-interview-test .media-container.is-video-visible tgo-vimeo-video{display:block}.ai-interview-test .media-container.is-playing{border:4px solid #0165FC;border-bottom-width:3px}.ai-interview-test .media-container.is-answering .candidate-camera tgo-audio-animation,.ai-interview-test .media-container.is-answering .candidate-no-camera tgo-audio-animation{position:absolute;top:16px;right:16px}.ai-interview-test .media-container.is-answering .candidate-camera video,.ai-interview-test .media-container.is-answering .candidate-no-camera{border:3px solid #0165FC;border-radius:10px}.ai-interview-test .media-container.is-answering tgo-vimeo-video{display:block}.ai-interview-test .media-container .start,.ai-interview-test .media-container .audio-info,.ai-interview-test .media-container .overlay,.ai-interview-test .media-container .answer{display:flex;justify-content:center;align-items:center;flex-direction:column;gap:40px;height:100%}.ai-interview-test .media-container .preview{height:100%;display:flex;align-items:center;flex-direction:column;justify-content:flex-end;padding:24px}.ai-interview-test .media-container .preview p{color:#d3d3d3;margin:8px 0}.ai-interview-test .media-container .preview audio{margin:16px 0}.ai-interview-test .media-container .preview.hidden{display:none}@media screen and (max-width: 600px){.ai-interview-test{padding:0 24px;margin-top:16px}}\n"], dependencies: [{ kind: "ngmodule", type: TranslocoModule }, { kind: "ngmodule", type: ButtonComponentModule }, { kind: "ngmodule", type: IconComponentModule }, { kind: "component", type: i1.IconComponent, selector: "ui-icon", inputs: ["size", "cssClass", "name", "color", "filled", "toggleIconStyle", "applicationTheme", "useFullIconName"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: AudioAnimationComponent, selector: "tgo-audio-animation", inputs: ["volume", "fakeData"] }, { kind: "component", type: InterviewStreamComponent, selector: "tgo-interview-stream", inputs: ["conversationUrl", "selectedMediaDevices", "translations"], outputs: ["streamStart", "streamEnd", "checkMediaPermissions"] }], animations: [
114
+ trigger('fadeInFadeOut', [
115
+ transition(':enter', [
116
+ style({ opacity: 0 }),
117
+ animate('600ms', style({ opacity: 1 })),
118
+ ]),
119
+ transition(':leave', [animate('600ms', style({ opacity: 0 }))]),
120
+ ]),
121
+ ] });
122
+ }
123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AiInterviewTestComponent, decorators: [{
124
+ type: Component,
125
+ args: [{ selector: 'tgo-ai-interview-test', animations: [
126
+ trigger('fadeInFadeOut', [
127
+ transition(':enter', [
128
+ style({ opacity: 0 }),
129
+ animate('600ms', style({ opacity: 1 })),
130
+ ]),
131
+ transition(':leave', [animate('600ms', style({ opacity: 0 }))]),
132
+ ]),
133
+ ], standalone: true, imports: [
134
+ TranslocoModule,
135
+ ButtonComponentModule,
136
+ IconComponentModule,
137
+ CommonModule,
138
+ AudioAnimationComponent,
139
+ InterviewStreamComponent,
140
+ ], providers: [
141
+ TranslocoLazyModuleUtils.getScopeProvider('tgo-ai-interview-test', getAvailableLangs(), ROOT_TRANSLATIONS_SCOPE, (lang) => {
142
+ // Fetch from app assets; demo app copies the library assets to
143
+ // /assets/tgo-ai-interview-test via project.json.
144
+ const url = new URL(`assets/tgo-ai-interview-test/i18n/${lang}.json`, document.baseURI).href;
145
+ return fetch(url).then((res) => res.json());
146
+ }),
147
+ DialogService,
148
+ ThemeService,
149
+ ], template: "<div class=\"ai-interview-test\">\n <div class=\"test-container\">\n <div\n class=\"media-container\"\n [class.is-video-visible]=\"isInterviewInProgress()\"\n >\n <div class=\"candidate-no-camera\" *ngIf=\"!candidateVideoStreamReady()\">\n <h3>&nbsp;</h3>\n <ui-icon name=\"User-profile-in-line\" color=\"white\" size=\"24\"></ui-icon>\n <h3 class=\"bold\">{{ translations['YOU'] }}</h3>\n </div>\n <div class=\"candidate-camera\" [hidden]=\"!candidateVideoStreamReady()\">\n <video\n height\n #video\n id=\"video\"\n playsinline\n (loadedmetadata)=\"onVideoLoad()\"\n ></video>\n <h3 class=\"bold\" *ngIf=\"candidateVideoStreamReady()\">\n {{ translations['YOU'] }}\n </h3>\n </div>\n <tgo-audio-animation\n *ngIf=\"isInterviewInProgress()\"\n [fakeData]=\"true\"\n ></tgo-audio-animation>\n <div class=\"interview-stream-container\">\n <tgo-interview-stream\n *ngIf=\"conversationUrl && hasMediaPermissions()\"\n [selectedMediaDevices]=\"selectedMediaDevices\"\n [conversationUrl]=\"conversationUrl\"\n (streamStart)=\"interviewStarted()\"\n (streamEnd)=\"interviewEnded()\"\n (checkMediaPermissions)=\"checkMediaPermissions()\"\n [translations]=\"translations\"\n ></tgo-interview-stream>\n </div>\n </div>\n </div>\n</div>\n\n", styles: [".bg-teal-60b{background:#1c443c}.bg-teal-30b{background:#31766a}.bg-teal-default{background:#46a997}.bg-teal-30w{background:#7ec3b6}.bg-teal-60w{background:#b5ddd5}.bg-teal-secondary{background:#cbd6cb}.bg-teal-90w{background:#ecf6f5}.bg-petrol-60b{background:#102930}.bg-petrol-30b{background:#1b4754}.bg-petrol-default{background:#276678}.bg-petrol-30w{background:#6894a0}.bg-petrol-60w{background:#a9c2c9}.bg-petrol-secondary{background:#c8d7de}.bg-petrol-90w{background:#e9f0f1}.bg-error-60b{background:#513131}.bg-error-30b{background:#8e5655}.bg-error-60w{background:#e3c3c6}.bg-error-secondary{background:#f0dad9}.bg-error-default{background:#cb7b7a}.bg-warning-secondary{background:#f0d6bb}.bg-warning-default{background:#cca45f}.bg-black{background:#000}.bg-dark{background:#888}.bg-medium{background:#e0e0e0}.bg-grey{background:#ededed}.bg-light{background:#f6f6f6}.bg-white{background:#fff}.bg-box-shadow{background:#00000014}.bg-navigation-subtitle{background:#528593}.bgc-teal-60b{background-color:#1c443c}.bgc-teal-30b{background-color:#31766a}.bgc-teal-default{background-color:#46a997}.bgc-teal-30w{background-color:#7ec3b6}.bgc-teal-60w{background-color:#b5ddd5}.bgc-teal-secondary{background-color:#cbd6cb}.bgc-teal-90w{background-color:#ecf6f5}.bgc-petrol-60b{background-color:#102930}.bgc-petrol-30b{background-color:#1b4754}.bgc-petrol-default{background-color:#276678}.bgc-petrol-30w{background-color:#6894a0}.bgc-petrol-60w{background-color:#a9c2c9}.bgc-petrol-secondary{background-color:#c8d7de}.bgc-petrol-90w{background-color:#e9f0f1}.bgc-error-60b{background-color:#513131}.bgc-error-30b{background-color:#8e5655}.bgc-error-60w{background-color:#e3c3c6}.bgc-error-secondary{background-color:#f0dad9}.bgc-error-default{background-color:#cb7b7a}.bgc-warning-secondary{background-color:#f0d6bb}.bgc-warning-default{background-color:#cca45f}.bgc-black{background-color:#000}.bgc-dark{background-color:#888}.bgc-medium{background-color:#e0e0e0}.bgc-grey{background-color:#ededed}.bgc-light{background-color:#f6f6f6}.bgc-white{background-color:#fff}.bgc-box-shadow{background-color:#00000014}.bgc-navigation-subtitle{background-color:#528593}.ai-interview-test{background-color:#242424;padding:24px;display:flex;justify-content:center;min-height:calc(100vh - 80px)}.ai-interview-test h3{color:#fff}.ai-interview-test .test-container{min-width:360px;width:100%;min-height:300px;height:min(725px,100%,max(100vw,100vh,200px));max-width:calc(177.7777777778vh - 80px - 48px);display:flex;flex-direction:column;justify-content:space-between;position:relative;background-color:#242424}.ai-interview-test .media-container{position:relative;color:#fff;flex-grow:1}.ai-interview-test .media-container .interview-stream-container{border-radius:10px;aspect-ratio:16/9;border:4px solid #0165FC;margin:0 auto}.ai-interview-test .media-container .candidate-no-camera{position:absolute;width:200px;aspect-ratio:16/9;z-index:3;top:32px;left:32px;border-radius:10px;background-color:#1a47aa;display:flex;justify-content:space-between;flex-direction:column;padding:16px}.ai-interview-test .media-container .candidate-no-camera ui-icon{margin:auto}.ai-interview-test .media-container .candidate-camera{position:absolute;width:200px;top:32px;left:32px;z-index:3}.ai-interview-test .media-container .candidate-camera video{width:200px;border-radius:10px}.ai-interview-test .media-container .candidate-camera h3{position:absolute;bottom:16px;left:16px}.ai-interview-test .media-container tgo-audio-animation{position:absolute;top:32px;right:32px;z-index:1}.ai-interview-test .media-container tgo-vimeo-video{display:none;position:absolute;height:100%;width:100%}.ai-interview-test .media-container.is-video-visible tgo-vimeo-video{display:block}.ai-interview-test .media-container.is-playing{border:4px solid #0165FC;border-bottom-width:3px}.ai-interview-test .media-container.is-answering .candidate-camera tgo-audio-animation,.ai-interview-test .media-container.is-answering .candidate-no-camera tgo-audio-animation{position:absolute;top:16px;right:16px}.ai-interview-test .media-container.is-answering .candidate-camera video,.ai-interview-test .media-container.is-answering .candidate-no-camera{border:3px solid #0165FC;border-radius:10px}.ai-interview-test .media-container.is-answering tgo-vimeo-video{display:block}.ai-interview-test .media-container .start,.ai-interview-test .media-container .audio-info,.ai-interview-test .media-container .overlay,.ai-interview-test .media-container .answer{display:flex;justify-content:center;align-items:center;flex-direction:column;gap:40px;height:100%}.ai-interview-test .media-container .preview{height:100%;display:flex;align-items:center;flex-direction:column;justify-content:flex-end;padding:24px}.ai-interview-test .media-container .preview p{color:#d3d3d3;margin:8px 0}.ai-interview-test .media-container .preview audio{margin:16px 0}.ai-interview-test .media-container .preview.hidden{display:none}@media screen and (max-width: 600px){.ai-interview-test{padding:0 24px;margin-top:16px}}\n"] }]
150
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
151
+ type: Inject,
152
+ args: [TRANSLOCO_SCOPE]
153
+ }] }], propDecorators: { videoElement: [{
154
+ type: ViewChild,
155
+ args: ['video']
156
+ }], audioElement: [{
157
+ type: ViewChild,
158
+ args: ['audio']
159
+ }], question: [{
160
+ type: Input,
161
+ args: [{ required: true }]
162
+ }], test: [{
163
+ type: Input,
164
+ args: [{ required: true }]
165
+ }], isFirstQuestion: [{
166
+ type: Input
167
+ }], selectedMediaDevices: [{
168
+ type: Input
169
+ }], conversationUrl: [{
170
+ type: Input
171
+ }], mediaAccessChanged: [{
172
+ type: Input
173
+ }], submissionStateChanged: [{
174
+ type: Output
175
+ }], loadingStateChanged: [{
176
+ type: Output
177
+ }], requestMediaAccess: [{
178
+ type: Output
179
+ }] } });
180
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktaW50ZXJ2aWV3LXRlc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvdGdvLWFpLWludGVydmlldy10ZXN0L3NyYy9saWIvY29tcG9uZW50cy9haS1pbnRlcnZpZXctdGVzdC9haS1pbnRlcnZpZXctdGVzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy90Z28tYWktaW50ZXJ2aWV3LXRlc3Qvc3JjL2xpYi9jb21wb25lbnRzL2FpLWludGVydmlldy10ZXN0L2FpLWludGVydmlldy10ZXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGdEQUFnRCxDQUFDO0FBQzFGLE9BQU8sRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3RCxPQUFPLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUUsT0FBTyxFQUNMLFVBQVUsRUFFVixNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBRU4sTUFBTSxFQUNOLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsYUFBYSxFQUNiLG1CQUFtQixHQUNwQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsZUFBZSxFQUNmLGVBQWUsRUFFZixnQkFBZ0IsR0FDakIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQ0wsdUJB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QUNELGFBQWE7d0JBQ2IsWUFBWTtxQkFDYjs7MEJBa0NFLE1BQU07MkJBQUMsZUFBZTt5Q0E3QkwsWUFBWTtzQkFBL0IsU0FBUzt1QkFBQyxPQUFPO2dCQUNFLFlBQVk7c0JBQS9CLFNBQVM7dUJBQUMsT0FBTztnQkFDUyxRQUFRO3NCQUFsQyxLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFDRSxJQUFJO3NCQUE5QixLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFDaEIsZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBRUksc0JBQXNCO3NCQUEvQixNQUFNO2dCQUVHLG1CQUFtQjtzQkFBNUIsTUFBTTtnQkFFRyxrQkFBa0I7c0JBQTNCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbnRlcnZpZXdTdHJlYW1Db21wb25lbnQgfSBmcm9tICcuLi9pbnRlcnZpZXctc3RyZWFtL2ludGVydmlldy1zdHJlYW0uY29tcG9uZW50JztcbmltcG9ydCB7IGZpcnN0VmFsdWVGcm9tLCBPYnNlcnZhYmxlLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRyYW5zaXRpb24sIHN0eWxlLCBhbmltYXRlLCB0cmlnZ2VyIH0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQge1xuICBFbGVtZW50UmVmLFxuICBPbkRlc3Ryb3ksXG4gIHNpZ25hbCxcbiAgVmlld0NoaWxkLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgaW5qZWN0LFxuICBPbkluaXQsXG4gIEluamVjdCxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgQnV0dG9uQ29tcG9uZW50TW9kdWxlLFxuICBEaWFsb2dTZXJ2aWNlLFxuICBJY29uQ29tcG9uZW50TW9kdWxlLFxufSBmcm9tICdAdGVzdGdvcmlsbGEvdGdvLXVpJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBUUkFOU0xPQ09fU0NPUEUsXG4gIFRyYW5zbG9jb01vZHVsZSxcbiAgVHJhbnNsb2NvU2NvcGUsXG4gIFRyYW5zbG9jb1NlcnZpY2UsXG59IGZyb20gJ0BuZ25lYXQvdHJhbnNsb2NvJztcbmltcG9ydCB7XG4gIEF1ZGlvQW5pbWF0aW9uQ29tcG9uZW50LFxuICBRdWVzdGlvbixcbiAgVGVzdFJlc3VsdFJlYWQsXG4gIFNlbGVjdGVkTWVkaWFEZXZpY2VzLFxuICBJU3VibWlzc2lvblN0YXRlLFxuICBST09UX1RSQU5TTEFUSU9OU19TQ09QRSxcbiAgTWVkaWFTZXJ2aWNlLFxuICBUaGVtZVNlcnZpY2UsXG4gIFRyYW5zbG9jb0xhenlNb2R1bGVVdGlscyxcbiAgZ2V0QXZhaWxhYmxlTGFuZ3MsXG59IGZyb20gJ0B0ZXN0Z29yaWxsYS90Z28tdGVzdC1zaGFyZWQnO1xuaW1wb3J0IHsgSVF1ZXN0aW9uRGF0YUNvbnRyYWN0IH0gZnJvbSAnLi4vLi4vbW9kZWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGdvLWFpLWludGVydmlldy10ZXN0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2FpLWludGVydmlldy10ZXN0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2FpLWludGVydmlldy10ZXN0LmNvbXBvbmVudC5zY3NzJyxcbiAgYW5pbWF0aW9uczogW1xuICAgIHRyaWdnZXIoJ2ZhZGVJbkZhZGVPdXQnLCBbXG4gICAgICB0cmFuc2l0aW9uKCc6ZW50ZXInLCBbXG4gICAgICAgIHN0eWxlKHsgb3BhY2l0eTogMCB9KSxcbiAgICAgICAgYW5pbWF0ZSgnNjAwbXMnLCBzdHlsZSh7IG9wYWNpdHk6IDEgfSkpLFxuICAgICAgXSksXG4gICAgICB0cmFuc2l0aW9uKCc6bGVhdmUnLCBbYW5pbWF0ZSgnNjAwbXMnLCBzdHlsZSh7IG9wYWNpdHk6IDAgfSkpXSksXG4gICAgXSksXG4gIF0sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBUcmFuc2xvY29Nb2R1bGUsXG4gICAgQnV0dG9uQ29tcG9uZW50TW9kdWxlLFxuICAgIEljb25Db21wb25lbnRNb2R1bGUsXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIEF1ZGlvQW5pbWF0aW9uQ29tcG9uZW50LFxuICAgIEludGVydmlld1N0cmVhbUNvbXBvbmVudCxcbiAgXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgVHJhbnNsb2NvTGF6eU1vZHVsZVV0aWxzLmdldFNjb3BlUHJvdmlkZXIoXG4gICAgICAndGdvLWFpLWludGVydmlldy10ZXN0JyxcbiAgICAgIGdldEF2YWlsYWJsZUxhbmdzKCksXG4gICAgICBST09UX1RSQU5TTEFUSU9OU19TQ09QRSxcbiAgICAgIChsYW5nOiBzdHJpbmcpID0+IHtcbiAgICAgICAgLy8gRmV0Y2ggZnJvbSBhcHAgYXNzZXRzOyBkZW1vIGFwcCBjb3BpZXMgdGhlIGxpYnJhcnkgYXNzZXRzIHRvXG4gICAgICAgIC8vIC9hc3NldHMvdGdvLWFpLWludGVydmlldy10ZXN0IHZpYSBwcm9qZWN0Lmpzb24uXG4gICAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwoXG4gICAgICAgICAgYGFzc2V0cy90Z28tYWktaW50ZXJ2aWV3LXRlc3QvaTE4bi8ke2xhbmd9Lmpzb25gLFxuICAgICAgICAgIGRvY3VtZW50LmJhc2VVUklcbiAgICAgICAgKS5ocmVmO1xuICAgICAgICByZXR1cm4gZmV0Y2godXJsKS50aGVuKChyZXMpID0+IHJlcy5qc29uKCkpO1xuICAgICAgfVxuICAgICksXG4gICAgRGlhbG9nU2VydmljZSxcbiAgICBUaGVtZVNlcnZpY2UsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIEFpSW50ZXJ2aWV3VGVzdENvbXBvbmVudFxuICBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBJUXVlc3Rpb25EYXRhQ29udHJhY3RcbntcbiAgQFZpZXdDaGlsZCgndmlkZW8nKSB2aWRlb0VsZW1lbnQ/OiBFbGVtZW50UmVmPEhUTUxWaWRlb0VsZW1lbnQ+O1xuICBAVmlld0NoaWxkKCdhdWRpbycpIGF1ZGlvRWxlbWVudD86IEVsZW1lbnRSZWY8SFRNTEF1ZGlvRWxlbWVudD47XG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIHF1ZXN0aW9uITogUXVlc3Rpb247XG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIHRlc3QhOiBUZXN0UmVzdWx0UmVhZDtcbiAgQElucHV0KCkgaXNGaXJzdFF1ZXN0aW9uPzogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBzZWxlY3RlZE1lZGlhRGV2aWNlcz86IFNlbGVjdGVkTWVkaWFEZXZpY2VzO1xuICBASW5wdXQoKSBjb252ZXJzYXRpb25Vcmw/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIG1lZGlhQWNjZXNzQ2hhbmdlZD86IE9ic2VydmFibGU8U2VsZWN0ZWRNZWRpYURldmljZXM+IHwgdW5kZWZpbmVkO1xuXG4gIEBPdXRwdXQoKSBzdWJtaXNzaW9uU3RhdGVDaGFuZ2VkID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPElTdWJtaXNzaW9uU3RhdGUgfCBudWxsPigpO1xuICBAT3V0cHV0KCkgbG9hZGluZ1N0YXRlQ2hhbmdlZDogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID1cbiAgICBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG4gIEBPdXRwdXQoKSByZXF1ZXN0TWVkaWFBY2Nlc3M6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBpc0ludGVydmlld0luUHJvZ3Jlc3MgPSBzaWduYWwoZmFsc2UpO1xuICBjYW5kaWRhdGVWaWRlb1N0cmVhbVJlYWR5ID0gc2lnbmFsKGZhbHNlKTtcbiAgdHJhbnNsYXRpb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge307XG4gIGhhc01lZGlhUGVybWlzc2lvbnMgPSBzaWduYWwoZmFsc2UpO1xuXG4gIHByaXZhdGUgdW5zdWJzY3JpYmUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSBtZWRpYVNlcnZpY2UgPSBpbmplY3QoTWVkaWFTZXJ2aWNlKTtcbiAgcHJpdmF0ZSB0cmFuc2xvY29TZXJ2aWNlID0gaW5qZWN0KFRyYW5zbG9jb1NlcnZpY2UpO1xuICBwcml2YXRlIGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHByaXZhdGUgdGhlbWVTZXJ2aWNlID0gaW5qZWN0KFRoZW1lU2VydmljZSk7XG5cbiAgY29tcGFueUNvbG9yID0gdGhpcy50aGVtZVNlcnZpY2UuZ2V0Q29tcGFueUNvbG9yKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChUUkFOU0xPQ09fU0NPUEUpIHByaXZhdGUgdHJhbnNsYXRpb25TY29wZTogVHJhbnNsb2NvU2NvcGVcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuaW5pdE1lZGlhQWNjZXNzU3Vic2NyaXB0aW9uKCk7XG4gICAgdGhpcy5sb2FkaW5nU3RhdGVDaGFuZ2VkLmVtaXQodHJ1ZSk7XG4gICAgdGhpcy5tZWRpYVNlcnZpY2Uuc2V0U2VsZWN0ZWRNZWRpYURldmljZXModGhpcy5zZWxlY3RlZE1lZGlhRGV2aWNlcyk7XG4gICAgdm9pZCB0aGlzLmNoZWNrTWVkaWFQZXJtaXNzaW9ucygpO1xuXG4gICAgdm9pZCB0aGlzLnNldFRyYW5zbGF0aW9ucygpO1xuICAgIHZvaWQgdGhpcy5pbml0VmlkZW9TdHJlYW0oKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMudW5zdWJzY3JpYmUkLm5leHQoKTtcbiAgICB0aGlzLnVuc3Vic2NyaWJlJC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgb25WaWRlb0xvYWQoKSB7XG4gICAgdGhpcy5jYW5kaWRhdGVWaWRlb1N0cmVhbVJlYWR5LnNldCh0cnVlKTtcbiAgfVxuXG4gIGludGVydmlld1N0YXJ0ZWQoKSB7XG4gICAgdGhpcy5pc0ludGVydmlld0luUHJvZ3Jlc3Muc2V0KHRydWUpO1xuICAgIHRoaXMubG9hZGluZ1N0YXRlQ2hhbmdlZC5lbWl0KGZhbHNlKTtcbiAgfVxuXG4gIGludGVydmlld0VuZGVkKCkge1xuICAgIHRoaXMuaXNJbnRlcnZpZXdJblByb2dyZXNzLnNldChmYWxzZSk7XG4gICAgdGhpcy5zdWJtaXNzaW9uU3RhdGVDaGFuZ2VkLmVtaXQoe1xuICAgICAgdGV4dDogJycsXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBjaGVja01lZGlhUGVybWlzc2lvbnMoKSB7XG4gICAgaWYgKFxuICAgICAgIShhd2FpdCB0aGlzLm1lZGlhU2VydmljZS5jaGVja1Blcm1pc3Npb24oeyBhdWRpbzogdHJ1ZSwgdmlkZW86IGZhbHNlIH0pKVxuICAgICkge1xuICAgICAgdGhpcy5oYXNNZWRpYVBlcm1pc3Npb25zLnNldChmYWxzZSk7XG4gICAgICB0aGlzLnJlcXVlc3RNZWRpYUFjY2Vzcy5lbWl0KCk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGFzTWVkaWFQZXJtaXNzaW9ucy5zZXQodHJ1ZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbml0VmlkZW9TdHJlYW0oKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IHRoaXMubWVkaWFTZXJ2aWNlLmdldE1lZGlhU3RyZWFtKHtcbiAgICAgICAgdmlkZW86IHRydWUsXG4gICAgICAgIGF1ZGlvOiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgaWYgKHRoaXMudmlkZW9FbGVtZW50KSB7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3JjT2JqZWN0ID0gc3RyZWFtO1xuICAgICAgICBhd2FpdCB0aGlzLnZpZGVvRWxlbWVudD8ubmF0aXZlRWxlbWVudC5wbGF5KCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGluaXRpYWxpemluZyB2aWRlbyBzdHJlYW06JywgZXJyb3IpO1xuICAgICAgdGhpcy5jYW5kaWRhdGVWaWRlb1N0cmVhbVJlYWR5LnNldChmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXRUcmFuc2xhdGlvbnMoKSB7XG4gICAgdGhpcy50cmFuc2xhdGlvbnMgPSBhd2FpdCBmaXJzdFZhbHVlRnJvbShcbiAgICAgIHRoaXMudHJhbnNsb2NvU2VydmljZS5zZWxlY3RUcmFuc2xhdGVPYmplY3QoXG4gICAgICAgIGBURVNUYCxcbiAgICAgICAge30sXG4gICAgICAgIHRoaXMudHJhbnNsYXRpb25TY29wZSBhcyBzdHJpbmdcbiAgICAgIClcbiAgICApO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0TWVkaWFBY2Nlc3NTdWJzY3JpcHRpb24oKSB7XG4gICAgdGhpcy5tZWRpYUFjY2Vzc0NoYW5nZWRcbiAgICAgID8ucGlwZSh0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSQpKVxuICAgICAgLnN1YnNjcmliZSgoc2VsZWN0ZWRNZWRpYURldmljZXMpID0+IHtcbiAgICAgICAgdGhpcy5tZWRpYVNlcnZpY2Uuc2V0U2VsZWN0ZWRNZWRpYURldmljZXMoc2VsZWN0ZWRNZWRpYURldmljZXMpO1xuICAgICAgICB0aGlzLmNoZWNrTWVkaWFQZXJtaXNzaW9ucygpO1xuICAgICAgICB2b2lkIHRoaXMuaW5pdFZpZGVvU3RyZWFtKCk7XG4gICAgICB9KTtcbiAgfVxufVxuXG4iLCI8ZGl2IGNsYXNzPVwiYWktaW50ZXJ2aWV3LXRlc3RcIj5cbiAgPGRpdiBjbGFzcz1cInRlc3QtY29udGFpbmVyXCI+XG4gICAgPGRpdlxuICAgICAgY2xhc3M9XCJtZWRpYS1jb250YWluZXJcIlxuICAgICAgW2NsYXNzLmlzLXZpZGVvLXZpc2libGVdPVwiaXNJbnRlcnZpZXdJblByb2dyZXNzKClcIlxuICAgID5cbiAgICAgIDxkaXYgY2xhc3M9XCJjYW5kaWRhdGUtbm8tY2FtZXJhXCIgKm5nSWY9XCIhY2FuZGlkYXRlVmlkZW9TdHJlYW1SZWFkeSgpXCI+XG4gICAgICAgIDxoMz4mbmJzcDs8L2gzPlxuICAgICAgICA8dWktaWNvbiBuYW1lPVwiVXNlci1wcm9maWxlLWluLWxpbmVcIiBjb2xvcj1cIndoaXRlXCIgc2l6ZT1cIjI0XCI+PC91aS1pY29uPlxuICAgICAgICA8aDMgY2xhc3M9XCJib2xkXCI+e3sgdHJhbnNsYXRpb25zWydZT1UnXSB9fTwvaDM+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjYW5kaWRhdGUtY2FtZXJhXCIgW2hpZGRlbl09XCIhY2FuZGlkYXRlVmlkZW9TdHJlYW1SZWFkeSgpXCI+XG4gICAgICAgIDx2aWRlb1xuICAgICAgICAgIGhlaWdodFxuICAgICAgICAgICN2aWRlb1xuICAgICAgICAgIGlkPVwidmlkZW9cIlxuICAgICAgICAgIHBsYXlzaW5saW5lXG4gICAgICAgICAgKGxvYWRlZG1ldGFkYXRhKT1cIm9uVmlkZW9Mb2FkKClcIlxuICAgICAgICA+PC92aWRlbz5cbiAgICAgICAgPGgzIGNsYXNzPVwiYm9sZFwiICpuZ0lmPVwiY2FuZGlkYXRlVmlkZW9TdHJlYW1SZWFkeSgpXCI+XG4gICAgICAgICAge3sgdHJhbnNsYXRpb25zWydZT1UnXSB9fVxuICAgICAgICA8L2gzPlxuICAgICAgPC9kaXY+XG4gICAgICA8dGdvLWF1ZGlvLWFuaW1hdGlvblxuICAgICAgICAqbmdJZj1cImlzSW50ZXJ2aWV3SW5Qcm9ncmVzcygpXCJcbiAgICAgICAgW2Zha2VEYXRhXT1cInRydWVcIlxuICAgICAgPjwvdGdvLWF1ZGlvLWFuaW1hdGlvbj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnRlcnZpZXctc3RyZWFtLWNvbnRhaW5lclwiPlxuICAgICAgICA8dGdvLWludGVydmlldy1zdHJlYW1cbiAgICAgICAgICAqbmdJZj1cImNvbnZlcnNhdGlvblVybCAmJiBoYXNNZWRpYVBlcm1pc3Npb25zKClcIlxuICAgICAgICAgIFtzZWxlY3RlZE1lZGlhRGV2aWNlc109XCJzZWxlY3RlZE1lZGlhRGV2aWNlc1wiXG4gICAgICAgICAgW2NvbnZlcnNhdGlvblVybF09XCJjb252ZXJzYXRpb25VcmxcIlxuICAgICAgICAgIChzdHJlYW1TdGFydCk9XCJpbnRlcnZpZXdTdGFydGVkKClcIlxuICAgICAgICAgIChzdHJlYW1FbmQpPVwiaW50ZXJ2aWV3RW5kZWQoKVwiXG4gICAgICAgICAgKGNoZWNrTWVkaWFQZXJtaXNzaW9ucyk9XCJjaGVja01lZGlhUGVybWlzc2lvbnMoKVwiXG4gICAgICAgICAgW3RyYW5zbGF0aW9uc109XCJ0cmFuc2xhdGlvbnNcIlxuICAgICAgICA+PC90Z28taW50ZXJ2aWV3LXN0cmVhbT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuXG4iXX0=
@@ -0,0 +1,4 @@
1
+ export * from './ai-interview-test/ai-interview-test.component';
2
+ export * from './interview-stream/interview-stream.component';
3
+ export * from './interview-video/interview-video.component';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy90Z28tYWktaW50ZXJ2aWV3LXRlc3Qvc3JjL2xpYi9jb21wb25lbnRzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsaURBQWlELENBQUM7QUFDaEUsY0FBYywrQ0FBK0MsQ0FBQztBQUM5RCxjQUFjLDZDQUE2QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9haS1pbnRlcnZpZXctdGVzdC9haS1pbnRlcnZpZXctdGVzdC5jb21wb25lbnQnO1xuZXhwb3J0ICogZnJvbSAnLi9pbnRlcnZpZXctc3RyZWFtL2ludGVydmlldy1zdHJlYW0uY29tcG9uZW50JztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJ2aWV3LXZpZGVvL2ludGVydmlldy12aWRlby5jb21wb25lbnQnO1xuIl19
@@ -0,0 +1,240 @@
1
+ import { ChangeDetectorRef, Component, EventEmitter, inject, Input, Output, signal, } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import DailyIframe from '@daily-co/daily-js';
4
+ import { InterviewVideoComponent } from '../interview-video/interview-video.component';
5
+ import * as i0 from "@angular/core";
6
+ const PLAYABLE_STATE = 'playable';
7
+ const LOADING_STATE = 'loading';
8
+ export class InterviewStreamComponent {
9
+ conversationUrl;
10
+ selectedMediaDevices;
11
+ translations = {};
12
+ streamStart = new EventEmitter();
13
+ streamEnd = new EventEmitter();
14
+ checkMediaPermissions = new EventEmitter();
15
+ callObject;
16
+ avatarParticipant;
17
+ candidateJoined = signal(false);
18
+ cdr = inject(ChangeDetectorRef);
19
+ ngOnInit() {
20
+ void this.setupCall();
21
+ }
22
+ ngOnDestroy() {
23
+ if (!this.callObject)
24
+ return;
25
+ this.leaveCall();
26
+ this.callObject
27
+ .off('joined-meeting', this.candidateJoinMeeting)
28
+ .off('participant-joined', this.participantJoined)
29
+ .off('app-message', this.handleNewMessage)
30
+ .off('track-started', this.handleTrackStartedStopped)
31
+ .off('track-stopped', this.handleTrackStartedStopped)
32
+ .off('participant-left', this.handleParticipantLeft)
33
+ .off('left-meeting', this.handleLeftMeeting)
34
+ .off('error', this.handleError);
35
+ }
36
+ async setupCall() {
37
+ this.callObject = DailyIframe.getCallInstance();
38
+ if (!this.callObject) {
39
+ this.callObject = DailyIframe.createCallObject();
40
+ }
41
+ if (this.selectedMediaDevices) {
42
+ await this.callObject.setInputDevicesAsync({
43
+ videoDeviceId: this.selectedMediaDevices.videoDeviceId,
44
+ audioDeviceId: this.selectedMediaDevices.audioDeviceId,
45
+ });
46
+ }
47
+ this.callObject.startRecording({
48
+ type: 'cloud',
49
+ });
50
+ this.callObject
51
+ .on('joined-meeting', this.candidateJoinMeeting)
52
+ .on('participant-joined', this.participantJoined)
53
+ .on('app-message', this.handleNewMessage)
54
+ .on('track-started', this.handleTrackStartedStopped)
55
+ .on('track-stopped', this.handleTrackStartedStopped)
56
+ .on('participant-left', this.handleParticipantLeft)
57
+ .on('left-meeting', this.handleLeftMeeting)
58
+ .on('error', this.handleError);
59
+ await this.callObject.join({
60
+ userName: 'Candidate',
61
+ url: this.conversationUrl,
62
+ });
63
+ }
64
+ formatParticipantObj(participant) {
65
+ const { video, audio } = participant.tracks;
66
+ const videoTrack = video?.persistentTrack;
67
+ const audioTrack = audio?.persistentTrack;
68
+ return {
69
+ videoTrack: videoTrack,
70
+ audioTrack: audioTrack,
71
+ videoReady: !!(videoTrack &&
72
+ (video.state === PLAYABLE_STATE || video.state === LOADING_STATE)),
73
+ audioReady: !!(audioTrack &&
74
+ (audio.state === PLAYABLE_STATE || audio.state === LOADING_STATE)),
75
+ userName: participant.user_name,
76
+ local: participant.local,
77
+ sessionId: participant.session_id,
78
+ };
79
+ }
80
+ updateTrack(participant, newTrackType) {
81
+ if (!this.avatarParticipant ||
82
+ this.avatarParticipant.sessionId !== participant.session_id) {
83
+ return;
84
+ }
85
+ const existingParticipant = this.avatarParticipant;
86
+ const currentParticipantCopy = this.formatParticipantObj(participant);
87
+ if (newTrackType === 'video') {
88
+ if (existingParticipant.videoReady !== currentParticipantCopy.videoReady) {
89
+ existingParticipant.videoReady = currentParticipantCopy.videoReady;
90
+ }
91
+ if (currentParticipantCopy.videoReady &&
92
+ existingParticipant.videoTrack?.id !==
93
+ currentParticipantCopy.videoTrack?.id) {
94
+ existingParticipant.videoTrack = currentParticipantCopy.videoTrack;
95
+ }
96
+ return;
97
+ }
98
+ if (newTrackType === 'audio') {
99
+ if (existingParticipant.audioReady !== currentParticipantCopy.audioReady) {
100
+ existingParticipant.audioReady = currentParticipantCopy.audioReady;
101
+ }
102
+ if (currentParticipantCopy.audioReady &&
103
+ existingParticipant.audioTrack?.id !==
104
+ currentParticipantCopy.audioTrack?.id) {
105
+ existingParticipant.audioTrack = currentParticipantCopy.audioTrack;
106
+ }
107
+ }
108
+ }
109
+ candidateJoinMeeting = (event) => {
110
+ if (!event || !this.callObject)
111
+ return;
112
+ this.candidateJoined.set(true);
113
+ this.streamStart.emit();
114
+ };
115
+ participantJoined = (event) => {
116
+ if (!event)
117
+ return;
118
+ this.avatarParticipant = this.formatParticipantObj(event.participant);
119
+ };
120
+ handleTrackStartedStopped = (event) => {
121
+ if (!event || !event.participant || !this.candidateJoined())
122
+ return;
123
+ if (event.action === 'track-stopped') {
124
+ this.checkMediaPermissions.emit();
125
+ }
126
+ this.updateTrack(event.participant, event.type);
127
+ this.cdr.detectChanges();
128
+ };
129
+ handleParticipantLeft = (event) => {
130
+ if (!event)
131
+ return;
132
+ this.leaveCall();
133
+ };
134
+ handleError = (event) => {
135
+ if (!event)
136
+ return;
137
+ console.error('Interview stream error', event);
138
+ this.leaveCall();
139
+ };
140
+ handleLeftMeeting = (event) => {
141
+ this.callObject?.stopRecording();
142
+ if (!event || !this.callObject)
143
+ return;
144
+ this.candidateJoined.set(false);
145
+ this.callObject.destroy();
146
+ this.streamEnd.emit();
147
+ };
148
+ leaveCall() {
149
+ if (!this.callObject)
150
+ return;
151
+ this.callObject.leave();
152
+ }
153
+ handleNewMessage = (event) => {
154
+ if (!event)
155
+ return;
156
+ if (event.data.event_type === 'conversation.tool_call') {
157
+ this.handleToolCall(event.data.properties);
158
+ }
159
+ };
160
+ getConversationId() {
161
+ return this.conversationUrl?.replace('https://tavus.daily.co/', '');
162
+ }
163
+ /*
164
+ This is a test implementation of tool calling.
165
+ These events will only be triggered if configured with a Tavus persona. The message content will be further refined by the IP Team.
166
+ https://docs.tavus.io/sections/event-schemas/conversation-toolcall
167
+ */
168
+ handleToolCall = (properties) => {
169
+ switch (properties.name) {
170
+ case 'next_question':
171
+ try {
172
+ const args = JSON.parse(properties.arguments);
173
+ if (args?.questionsLeft > 0) {
174
+ this.sendMessage(this.getToolCallTranslation('NEXT_QUESTION'));
175
+ window.setTimeout(() => {
176
+ this.sendMessage('Read next question', 'respond');
177
+ }, 1000);
178
+ }
179
+ else {
180
+ throw new Error('No more questions left');
181
+ }
182
+ }
183
+ catch (err) {
184
+ console.error('Failed to parse arguments for next_question tool call', err);
185
+ this.sendMessage(this.getToolCallTranslation('ALL_FOR_TODAY'));
186
+ window.setTimeout(() => {
187
+ this.leaveCall();
188
+ }, 5000);
189
+ }
190
+ break;
191
+ case 'end_conversation':
192
+ window.setTimeout(() => {
193
+ this.leaveCall();
194
+ }, 5000);
195
+ break;
196
+ default:
197
+ console.warn('Unknown tool call code:', properties);
198
+ break;
199
+ }
200
+ };
201
+ /*
202
+ Echo message is a message that avatar reads and candidate can hear
203
+ Respond message is a message that avatar reads and candidate cannot hear
204
+ */
205
+ sendMessage(text, type = 'echo') {
206
+ if (!this.callObject)
207
+ return;
208
+ this.callObject.sendAppMessage({
209
+ message_type: 'conversation',
210
+ event_type: 'conversation.' + type,
211
+ conversation_id: this.getConversationId(),
212
+ properties: {
213
+ text,
214
+ },
215
+ });
216
+ }
217
+ getToolCallTranslation(key) {
218
+ const toolCallTranslations = this.translations['TOOL_CALL'];
219
+ return toolCallTranslations[key];
220
+ }
221
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InterviewStreamComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
222
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: InterviewStreamComponent, isStandalone: true, selector: "tgo-interview-stream", inputs: { conversationUrl: "conversationUrl", selectedMediaDevices: "selectedMediaDevices", translations: "translations" }, outputs: { streamStart: "streamStart", streamEnd: "streamEnd", checkMediaPermissions: "checkMediaPermissions" }, ngImport: i0, template: "<div class=\"interview-stream\">\n @if (avatarParticipant) {\n <tgo-interview-video\n [videoTrack]=\"avatarParticipant.videoTrack\"\n [audioTrack]=\"avatarParticipant.audioTrack\"\n ></tgo-interview-video>\n }\n</div>\n\n", styles: [".interview-stream{width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: InterviewVideoComponent, selector: "tgo-interview-video", inputs: ["videoTrack", "audioTrack"] }] });
223
+ }
224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InterviewStreamComponent, decorators: [{
225
+ type: Component,
226
+ args: [{ selector: 'tgo-interview-stream', standalone: true, imports: [CommonModule, InterviewVideoComponent], template: "<div class=\"interview-stream\">\n @if (avatarParticipant) {\n <tgo-interview-video\n [videoTrack]=\"avatarParticipant.videoTrack\"\n [audioTrack]=\"avatarParticipant.audioTrack\"\n ></tgo-interview-video>\n }\n</div>\n\n", styles: [".interview-stream{width:100%;height:100%}\n"] }]
227
+ }], propDecorators: { conversationUrl: [{
228
+ type: Input
229
+ }], selectedMediaDevices: [{
230
+ type: Input
231
+ }], translations: [{
232
+ type: Input
233
+ }], streamStart: [{
234
+ type: Output
235
+ }], streamEnd: [{
236
+ type: Output
237
+ }], checkMediaPermissions: [{
238
+ type: Output
239
+ }] } });
240
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJ2aWV3LXN0cmVhbS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy90Z28tYWktaW50ZXJ2aWV3LXRlc3Qvc3JjL2xpYi9jb21wb25lbnRzL2ludGVydmlldy1zdHJlYW0vaW50ZXJ2aWV3LXN0cmVhbS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy90Z28tYWktaW50ZXJ2aWV3LXRlc3Qvc3JjL2xpYi9jb21wb25lbnRzL2ludGVydmlldy1zdHJlYW0vaW50ZXJ2aWV3LXN0cmVhbS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFHTCxNQUFNLEVBQ04sTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLFdBVU4sTUFBTSxvQkFBb0IsQ0FBQztBQUU1QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQzs7QUFZdkYsTUFBTSxjQUFjLEdBQUcsVUFBVSxDQUFDO0FBQ2xDLE1BQU0sYUFBYSxHQUFHLFNBQVMsQ0FBQztBQWlCaEMsTUFBTSxPQUFPLHdCQUF3QjtJQUMxQixlQUFlLENBQXFCO0lBQ3BDLG9CQUFvQixDQUFtQztJQUN2RCxZQUFZLEdBQThCLEVBQUUsQ0FBQztJQUM1QyxXQUFXLEdBQXVCLElBQUksWUFBWSxFQUFFLENBQUM7SUFDckQsU0FBUyxHQUF1QixJQUFJLFlBQVksRUFBRSxDQUFDO0lBQ25ELHFCQUFxQixHQUF1QixJQUFJLFlBQVksRUFBRSxDQUFDO0lBRXpFLFVBQVUsQ0FBd0I7SUFDbEMsaUJBQWlCLENBQTBCO0lBQzNDLGVBQWUsR0FBRyxNQUFNLENBQUMsS0FBSyxD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SSxXQUNQLENBQUMsWUFBWSxFQUFFLHVCQUF1QixDQUFDOzhCQUd2QyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNJLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0csU0FBUztzQkFBbEIsTUFBTTtnQkFDRyxxQkFBcUI7c0JBQTlCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IERhaWx5SWZyYW1lLCB7XG4gIERhaWx5Q2FsbCxcbiAgRGFpbHlFdmVudE9iamVjdFBhcnRpY2lwYW50LFxuICBEYWlseVBhcnRpY2lwYW50LFxuICBEYWlseUV2ZW50T2JqZWN0RmF0YWxFcnJvcixcbiAgRGFpbHlFdmVudE9iamVjdFBhcnRpY2lwYW50cyxcbiAgRGFpbHlFdmVudE9iamVjdE5vUGF5bG9hZCxcbiAgRGFpbHlFdmVudE9iamVjdFBhcnRpY2lwYW50TGVmdCxcbiAgRGFpbHlFdmVudE9iamVjdFRyYWNrLFxuICBEYWlseUV2ZW50T2JqZWN0QXBwTWVzc2FnZSxcbn0gZnJvbSAnQGRhaWx5LWNvL2RhaWx5LWpzJztcbmltcG9ydCB7IFNlbGVjdGVkTWVkaWFEZXZpY2VzIH0gZnJvbSAnQHRlc3Rnb3JpbGxhL3Rnby10ZXN0LXNoYXJlZCc7XG5pbXBvcnQgeyBJbnRlcnZpZXdWaWRlb0NvbXBvbmVudCB9IGZyb20gJy4uL2ludGVydmlldy12aWRlby9pbnRlcnZpZXctdmlkZW8uY29tcG9uZW50JztcblxuZXhwb3J0IHR5cGUgUGFydGljaXBhbnQgPSB7XG4gIHZpZGVvVHJhY2s/OiBNZWRpYVN0cmVhbVRyYWNrIHwgdW5kZWZpbmVkO1xuICBhdWRpb1RyYWNrPzogTWVkaWFTdHJlYW1UcmFjayB8IHVuZGVmaW5lZDtcbiAgdmlkZW9SZWFkeTogYm9vbGVhbjtcbiAgYXVkaW9SZWFkeTogYm9vbGVhbjtcbiAgdXNlck5hbWU6IHN0cmluZztcbiAgbG9jYWw6IGJvb2xlYW47XG4gIHNlc3Npb25JZDogc3RyaW5nO1xufTtcblxuY29uc3QgUExBWUFCTEVfU1RBVEUgPSAncGxheWFibGUnO1xuY29uc3QgTE9BRElOR19TVEFURSA9ICdsb2FkaW5nJztcblxuaW50ZXJmYWNlIEV2ZW50RGF0YSB7XG4gIGV2ZW50X3R5cGU6IHN0cmluZztcbiAgcHJvcGVydGllczoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBhcmd1bWVudHM6IHN0cmluZztcbiAgfTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGdvLWludGVydmlldy1zdHJlYW0nLFxuICB0ZW1wbGF0ZVVybDogJy4vaW50ZXJ2aWV3LXN0cmVhbS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2ludGVydmlldy1zdHJlYW0uY29tcG9uZW50LnNjc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgSW50ZXJ2aWV3VmlkZW9Db21wb25lbnRdLFxufSlcbmV4cG9ydCBjbGFzcyBJbnRlcnZpZXdTdHJlYW1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIGNvbnZlcnNhdGlvblVybDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBASW5wdXQoKSBzZWxlY3RlZE1lZGlhRGV2aWNlczogU2VsZWN0ZWRNZWRpYURldmljZXMgfCB1bmRlZmluZWQ7XG4gIEBJbnB1dCgpIHRyYW5zbGF0aW9uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICBAT3V0cHV0KCkgc3RyZWFtU3RhcnQ6IEV2ZW50RW1pdHRlcjxudWxsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN0cmVhbUVuZDogRXZlbnRFbWl0dGVyPG51bGw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgY2hlY2tNZWRpYVBlcm1pc3Npb25zOiBFdmVudEVtaXR0ZXI8bnVsbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY2FsbE9iamVjdDogRGFpbHlDYWxsIHwgdW5kZWZpbmVkO1xuICBhdmF0YXJQYXJ0aWNpcGFudDogUGFydGljaXBhbnQgfCB1bmRlZmluZWQ7XG4gIGNhbmRpZGF0ZUpvaW5lZCA9IHNpZ25hbChmYWxzZSk7XG4gIHByaXZhdGUgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuc2V0dXBDYWxsKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FsbE9iamVjdCkgcmV0dXJuO1xuICAgIHRoaXMubGVhdmVDYWxsKCk7XG4gICAgdGhpcy5jYWxsT2JqZWN0XG4gICAgICAub2ZmKCdqb2luZWQtbWVldGluZycsIHRoaXMuY2FuZGlkYXRlSm9pbk1lZXRpbmcpXG4gICAgICAub2ZmKCdwYXJ0aWNpcGFudC1qb2luZWQnLCB0aGlzLnBhcnRpY2lwYW50Sm9pbmVkKVxuICAgICAgLm9mZignYXBwLW1lc3NhZ2UnLCB0aGlzLmhhbmRsZU5ld01lc3NhZ2UpXG4gICAgICAub2ZmKCd0cmFjay1zdGFydGVkJywgdGhpcy5oYW5kbGVUcmFja1N0YXJ0ZWRTdG9wcGVkKVxuICAgICAgLm9mZigndHJhY2stc3RvcHBlZCcsIHRoaXMuaGFuZGxlVHJhY2tTdGFydGVkU3RvcHBlZClcbiAgICAgIC5vZmYoJ3BhcnRpY2lwYW50LWxlZnQnLCB0aGlzLmhhbmRsZVBhcnRpY2lwYW50TGVmdClcbiAgICAgIC5vZmYoJ2xlZnQtbWVldGluZycsIHRoaXMuaGFuZGxlTGVmdE1lZXRpbmcpXG4gICAgICAub2ZmKCdlcnJvcicsIHRoaXMuaGFuZGxlRXJyb3IpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXR1cENhbGwoKSB7XG4gICAgdGhpcy5jYWxsT2JqZWN0ID0gRGFpbHlJZnJhbWUuZ2V0Q2FsbEluc3RhbmNlKCk7XG4gICAgaWYgKCF0aGlzLmNhbGxPYmplY3QpIHtcbiAgICAgIHRoaXMuY2FsbE9iamVjdCA9IERhaWx5SWZyYW1lLmNyZWF0ZUNhbGxPYmplY3QoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRNZWRpYURldmljZXMpIHtcbiAgICAgIGF3YWl0IHRoaXMuY2FsbE9iamVjdC5zZXRJbnB1dERldmljZXNBc3luYyh7XG4gICAgICAgIHZpZGVvRGV2aWNlSWQ6IHRoaXMuc2VsZWN0ZWRNZWRpYURldmljZXMudmlkZW9EZXZpY2VJZCxcbiAgICAgICAgYXVkaW9EZXZpY2VJZDogdGhpcy5zZWxlY3RlZE1lZGlhRGV2aWNlcy5hdWRpb0RldmljZUlkLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMuY2FsbE9iamVjdC5zdGFydFJlY29yZGluZyh7XG4gICAgICB0eXBlOiAnY2xvdWQnLFxuICAgIH0pO1xuXG4gICAgdGhpcy5jYWxsT2JqZWN0XG4gICAgICAub24oJ2pvaW5lZC1tZWV0aW5nJywgdGhpcy5jYW5kaWRhdGVKb2luTWVldGluZylcbiAgICAgIC5vbigncGFydGljaXBhbnQtam9pbmVkJywgdGhpcy5wYXJ0aWNpcGFudEpvaW5lZClcbiAgICAgIC5vbignYXBwLW1lc3NhZ2UnLCB0aGlzLmhhbmRsZU5ld01lc3NhZ2UpXG4gICAgICAub24oJ3RyYWNrLXN0YXJ0ZWQnLCB0aGlzLmhhbmRsZVRyYWNrU3RhcnRlZFN0b3BwZWQpXG4gICAgICAub24oJ3RyYWNrLXN0b3BwZWQnLCB0aGlzLmhhbmRsZVRyYWNrU3RhcnRlZFN0b3BwZWQpXG4gICAgICAub24oJ3BhcnRpY2lwYW50LWxlZnQnLCB0aGlzLmhhbmRsZVBhcnRpY2lwYW50TGVmdClcbiAgICAgIC5vbignbGVmdC1tZWV0aW5nJywgdGhpcy5oYW5kbGVMZWZ0TWVldGluZylcbiAgICAgIC5vbignZXJyb3InLCB0aGlzLmhhbmRsZUVycm9yKTtcblxuICAgIGF3YWl0IHRoaXMuY2FsbE9iamVjdC5qb2luKHtcbiAgICAgIHVzZXJOYW1lOiAnQ2FuZGlkYXRlJyxcbiAgICAgIHVybDogdGhpcy5jb252ZXJzYXRpb25VcmwsXG4gICAgfSk7XG4gIH1cblxuICBmb3JtYXRQYXJ0aWNpcGFudE9iaihwYXJ0aWNpcGFudDogRGFpbHlQYXJ0aWNpcGFudCk6IFBhcnRpY2lwYW50IHtcbiAgICBjb25zdCB7IHZpZGVvLCBhdWRpbyB9ID0gcGFydGljaXBhbnQudHJhY2tzO1xuXG4gICAgY29uc3QgdmlkZW9UcmFjayA9IHZpZGVvPy5wZXJzaXN0ZW50VHJhY2s7XG4gICAgY29uc3QgYXVkaW9UcmFjayA9IGF1ZGlvPy5wZXJzaXN0ZW50VHJhY2s7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZpZGVvVHJhY2s6IHZpZGVvVHJhY2ssXG4gICAgICBhdWRpb1RyYWNrOiBhdWRpb1RyYWNrLFxuICAgICAgdmlkZW9SZWFkeTogISEoXG4gICAgICAgIHZpZGVvVHJhY2sgJiZcbiAgICAgICAgKHZpZGVvLnN0YXRlID09PSBQTEFZQUJMRV9TVEFURSB8fCB2aWRlby5zdGF0ZSA9PT0gTE9BRElOR19TVEFURSlcbiAgICAgICksXG4gICAgICBhdWRpb1JlYWR5OiAhIShcbiAgICAgICAgYXVkaW9UcmFjayAmJlxuICAgICAgICAoYXVkaW8uc3RhdGUgPT09IFBMQVlBQkxFX1NUQVRFIHx8IGF1ZGlvLnN0YXRlID09PSBMT0FESU5HX1NUQVRFKVxuICAgICAgKSxcbiAgICAgIHVzZXJOYW1lOiBwYXJ0aWNpcGFudC51c2VyX25hbWUsXG4gICAgICBsb2NhbDogcGFydGljaXBhbnQubG9jYWwsXG4gICAgICBzZXNzaW9uSWQ6IHBhcnRpY2lwYW50LnNlc3Npb25faWQsXG4gICAgfTtcbiAgfVxuXG4gIHVwZGF0ZVRyYWNrKHBhcnRpY2lwYW50OiBEYWlseVBhcnRpY2lwYW50LCBuZXdUcmFja1R5cGU6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmIChcbiAgICAgICF0aGlzLmF2YXRhclBhcnRpY2lwYW50IHx8XG4gICAgICB0aGlzLmF2YXRhclBhcnRpY2lwYW50LnNlc3Npb25JZCAhPT0gcGFydGljaXBhbnQuc2Vzc2lvbl9pZFxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBleGlzdGluZ1BhcnRpY2lwYW50ID0gdGhpcy5hdmF0YXJQYXJ0aWNpcGFudCBhcyBQYXJ0aWNpcGFudDtcbiAgICBjb25zdCBjdXJyZW50UGFydGljaXBhbnRDb3B5ID0gdGhpcy5mb3JtYXRQYXJ0aWNpcGFudE9iaihwYXJ0aWNpcGFudCk7XG5cbiAgICBpZiAobmV3VHJhY2tUeXBlID09PSAndmlkZW8nKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnQudmlkZW9SZWFkeSAhPT0gY3VycmVudFBhcnRpY2lwYW50Q29weS52aWRlb1JlYWR5XG4gICAgICApIHtcbiAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudC52aWRlb1JlYWR5ID0gY3VycmVudFBhcnRpY2lwYW50Q29weS52aWRlb1JlYWR5O1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIGN1cnJlbnRQYXJ0aWNpcGFudENvcHkudmlkZW9SZWFkeSAmJlxuICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50LnZpZGVvVHJhY2s/LmlkICE9PVxuICAgICAgICAgIGN1cnJlbnRQYXJ0aWNpcGFudENvcHkudmlkZW9UcmFjaz8uaWRcbiAgICAgICkge1xuICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50LnZpZGVvVHJhY2sgPSBjdXJyZW50UGFydGljaXBhbnRDb3B5LnZpZGVvVHJhY2s7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKG5ld1RyYWNrVHlwZSA9PT0gJ2F1ZGlvJykge1xuICAgICAgaWYgKFxuICAgICAgICBleGlzdGluZ1BhcnRpY2lwYW50LmF1ZGlvUmVhZHkgIT09IGN1cnJlbnRQYXJ0aWNpcGFudENvcHkuYXVkaW9SZWFkeVxuICAgICAgKSB7XG4gICAgICAgIGV4aXN0aW5nUGFydGljaXBhbnQuYXVkaW9SZWFkeSA9IGN1cnJlbnRQYXJ0aWNpcGFudENvcHkuYXVkaW9SZWFkeTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBjdXJyZW50UGFydGljaXBhbnRDb3B5LmF1ZGlvUmVhZHkgJiZcbiAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudC5hdWRpb1RyYWNrPy5pZCAhPT1cbiAgICAgICAgICBjdXJyZW50UGFydGljaXBhbnRDb3B5LmF1ZGlvVHJhY2s/LmlkXG4gICAgICApIHtcbiAgICAgICAgZXhpc3RpbmdQYXJ0aWNpcGFudC5hdWRpb1RyYWNrID0gY3VycmVudFBhcnRpY2lwYW50Q29weS5hdWRpb1RyYWNrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2FuZGlkYXRlSm9pbk1lZXRpbmcgPSAoXG4gICAgZXZlbnQ6IERhaWx5RXZlbnRPYmplY3RQYXJ0aWNpcGFudHMgfCB1bmRlZmluZWRcbiAgKTogdm9pZCA9PiB7XG4gICAgaWYgKCFldmVudCB8fCAhdGhpcy5jYWxsT2JqZWN0KSByZXR1cm47XG4gICAgdGhpcy5jYW5kaWRhdGVKb2luZWQuc2V0KHRydWUpO1xuICAgIHRoaXMuc3RyZWFtU3RhcnQuZW1pdCgpO1xuICB9O1xuXG4gIHByaXZhdGUgcGFydGljaXBhbnRKb2luZWQgPSAoXG4gICAgZXZlbnQ6IERhaWx5RXZlbnRPYmplY3RQYXJ0aWNpcGFudCB8IHVuZGVmaW5lZFxuICApID0+IHtcbiAgICBpZiAoIWV2ZW50KSByZXR1cm47XG4gICAgdGhpcy5hdmF0YXJQYXJ0aWNpcGFudCA9IHRoaXMuZm9ybWF0UGFydGljaXBhbnRPYmooZXZlbnQucGFydGljaXBhbnQpO1xuICB9O1xuXG4gIHByaXZhdGUgaGFuZGxlVHJhY2tTdGFydGVkU3RvcHBlZCA9IChcbiAgICBldmVudDogRGFpbHlFdmVudE9iamVjdFRyYWNrIHwgdW5kZWZpbmVkXG4gICk6IHZvaWQgPT4ge1xuICAgIGlmICghZXZlbnQgfHwgIWV2ZW50LnBhcnRpY2lwYW50IHx8ICF0aGlzLmNhbmRpZGF0ZUpvaW5lZCgpKSByZXR1cm47XG4gICAgaWYgKGV2ZW50LmFjdGlvbiA9PT0gJ3RyYWNrLXN0b3BwZWQnKSB7XG4gICAgICB0aGlzLmNoZWNrTWVkaWFQZXJtaXNzaW9ucy5lbWl0KCk7XG4gICAgfVxuICAgIHRoaXMudXBkYXRlVHJhY2soZXZlbnQucGFydGljaXBhbnQsIGV2ZW50LnR5cGUpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgfTtcblxuICBwcml2YXRlIGhhbmRsZVBhcnRpY2lwYW50TGVmdCA9IChcbiAgICBldmVudDogRGFpbHlFdmVudE9iamVjdFBhcnRpY2lwYW50TGVmdCB8IHVuZGVmaW5lZFxuICApOiB2b2lkID0+IHtcbiAgICBpZiAoIWV2ZW50KSByZXR1cm47XG4gICAgdGhpcy5sZWF2ZUNhbGwoKTtcbiAgfTtcblxuICBwcml2YXRlIGhhbmRsZUVycm9yID0gKFxuICAgIGV2ZW50OiBEYWlseUV2ZW50T2JqZWN0RmF0YWxFcnJvciB8IHVuZGVmaW5lZFxuICApOiB2b2lkID0+IHtcbiAgICBpZiAoIWV2ZW50KSByZXR1cm47XG4gICAgY29uc29sZS5lcnJvcignSW50ZXJ2aWV3IHN0cmVhbSBlcnJvcicsIGV2ZW50KTtcbiAgICB0aGlzLmxlYXZlQ2FsbCgpO1xuICB9O1xuXG4gIHByaXZhdGUgaGFuZGxlTGVmdE1lZXRpbmcgPSAoXG4gICAgZXZlbnQ6IERhaWx5RXZlbnRPYmplY3ROb1BheWxvYWQgfCB1bmRlZmluZWRcbiAgKTogdm9pZCA9PiB7XG4gICAgdGhpcy5jYWxsT2JqZWN0Py5zdG9wUmVjb3JkaW5nKCk7XG4gICAgaWYgKCFldmVudCB8fCAhdGhpcy5jYWxsT2JqZWN0KSByZXR1cm47XG4gICAgdGhpcy5jYW5kaWRhdGVKb2luZWQuc2V0KGZhbHNlKTtcbiAgICB0aGlzLmNhbGxPYmplY3QuZGVzdHJveSgpO1xuICAgIHRoaXMuc3RyZWFtRW5kLmVtaXQoKTtcbiAgfTtcblxuICBwcml2YXRlIGxlYXZlQ2FsbCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FsbE9iamVjdCkgcmV0dXJuO1xuICAgIHRoaXMuY2FsbE9iamVjdC5sZWF2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVOZXdNZXNzYWdlID0gKFxuICAgIGV2ZW50OiBEYWlseUV2ZW50T2JqZWN0QXBwTWVzc2FnZTxFdmVudERhdGE+IHwgdW5kZWZpbmVkXG4gICk6IHZvaWQgPT4ge1xuICAgIGlmICghZXZlbnQpIHJldHVybjtcbiAgICBpZiAoZXZlbnQuZGF0YS5ldmVudF90eXBlID09PSAnY29udmVyc2F0aW9uLnRvb2xfY2FsbCcpIHtcbiAgICAgIHRoaXMuaGFuZGxlVG9vbENhbGwoZXZlbnQuZGF0YS5wcm9wZXJ0aWVzKTtcbiAgICB9XG4gIH07XG5cbiAgcHJpdmF0ZSBnZXRDb252ZXJzYXRpb25JZCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmNvbnZlcnNhdGlvblVybD8ucmVwbGFjZSgnaHR0cHM6Ly90YXZ1cy5kYWlseS5jby8nLCAnJyk7XG4gIH1cblxuICAvKlxuICAgIFRoaXMgaXMgYSB0ZXN0IGltcGxlbWVudGF0aW9uIG9mIHRvb2wgY2FsbGluZy5cbiAgICBUaGVzZSBldmVudHMgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBpZiBjb25maWd1cmVkIHdpdGggYSBUYXZ1cyBwZXJzb25hLiBUaGUgbWVzc2FnZSBjb250ZW50IHdpbGwgYmUgZnVydGhlciByZWZpbmVkIGJ5IHRoZSBJUCBUZWFtLlxuICAgIGh0dHBzOi8vZG9jcy50YXZ1cy5pby9zZWN0aW9ucy9ldmVudC1zY2hlbWFzL2NvbnZlcnNhdGlvbi10b29sY2FsbFxuICAqL1xuICBwcml2YXRlIGhhbmRsZVRvb2xDYWxsID0gKHByb3BlcnRpZXM6IHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgYXJndW1lbnRzOiBzdHJpbmc7XG4gIH0pOiB2b2lkID0+IHtcbiAgICBzd2l0Y2ggKHByb3BlcnRpZXMubmFtZSkge1xuICAgICAgY2FzZSAnbmV4dF9xdWVzdGlvbic6XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYXJncyA9IEpTT04ucGFyc2UocHJvcGVydGllcy5hcmd1bWVudHMpO1xuICAgICAgICAgIGlmIChhcmdzPy5xdWVzdGlvbnNMZWZ0ID4gMCkge1xuICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZSh0aGlzLmdldFRvb2xDYWxsVHJhbnNsYXRpb24oJ05FWFRfUVVFU1RJT04nKSk7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2UoJ1JlYWQgbmV4dCBxdWVzdGlvbicsICdyZXNwb25kJyk7XG4gICAgICAgICAgICB9LCAxMDAwKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBtb3JlIHF1ZXN0aW9ucyBsZWZ0Jyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgJ0ZhaWxlZCB0byBwYXJzZSBhcmd1bWVudHMgZm9yIG5leHRfcXVlc3Rpb24gdG9vbCBjYWxsJyxcbiAgICAgICAgICAgIGVyclxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlKHRoaXMuZ2V0VG9vbENhbGxUcmFuc2xhdGlvbignQUxMX0ZPUl9UT0RBWScpKTtcbiAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxlYXZlQ2FsbCgpO1xuICAgICAgICAgIH0sIDUwMDApO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZW5kX2NvbnZlcnNhdGlvbic6XG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICB0aGlzLmxlYXZlQ2FsbCgpO1xuICAgICAgICB9LCA1MDAwKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBjb25zb2xlLndhcm4oJ1Vua25vd24gdG9vbCBjYWxsIGNvZGU6JywgcHJvcGVydGllcyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfTtcblxuICAvKlxuICAgIEVjaG8gbWVzc2FnZSBpcyBhIG1lc3NhZ2UgdGhhdCBhdmF0YXIgcmVhZHMgYW5kIGNhbmRpZGF0ZSBjYW4gaGVhclxuICAgIFJlc3BvbmQgbWVzc2FnZSBpcyBhIG1lc3NhZ2UgdGhhdCBhdmF0YXIgcmVhZHMgYW5kIGNhbmRpZGF0ZSBjYW5ub3QgaGVhclxuICAqL1xuXG4gIHByaXZhdGUgc2VuZE1lc3NhZ2UodGV4dDogc3RyaW5nLCB0eXBlOiAnZWNobycgfCAncmVzcG9uZCcgPSAnZWNobycpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY2FsbE9iamVjdCkgcmV0dXJuO1xuXG4gICAgdGhpcy5jYWxsT2JqZWN0LnNlbmRBcHBNZXNzYWdlKHtcbiAgICAgIG1lc3NhZ2VfdHlwZTogJ2NvbnZlcnNhdGlvbicsXG4gICAgICBldmVudF90eXBlOiAnY29udmVyc2F0aW9uLicgKyB0eXBlLFxuICAgICAgY29udmVyc2F0aW9uX2lkOiB0aGlzLmdldENvbnZlcnNhdGlvbklkKCksXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIHRleHQsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUb29sQ2FsbFRyYW5zbGF0aW9uKGtleTogc3RyaW5nKSB7XG4gICAgY29uc3QgdG9vbENhbGxUcmFuc2xhdGlvbnMgPSB0aGlzLnRyYW5zbGF0aW9uc1snVE9PTF9DQUxMJ10gYXMgdW5rbm93biBhcyB7XG4gICAgICBba2V5OiBzdHJpbmddOiBzdHJpbmc7XG4gICAgfTtcbiAgICByZXR1cm4gdG9vbENhbGxUcmFuc2xhdGlvbnNba2V5XTtcbiAgfVxufVxuXG4iLCI8ZGl2IGNsYXNzPVwiaW50ZXJ2aWV3LXN0cmVhbVwiPlxuICBAaWYgKGF2YXRhclBhcnRpY2lwYW50KSB7XG4gIDx0Z28taW50ZXJ2aWV3LXZpZGVvXG4gICAgW3ZpZGVvVHJhY2tdPVwiYXZhdGFyUGFydGljaXBhbnQudmlkZW9UcmFja1wiXG4gICAgW2F1ZGlvVHJhY2tdPVwiYXZhdGFyUGFydGljaXBhbnQuYXVkaW9UcmFja1wiXG4gID48L3Rnby1pbnRlcnZpZXctdmlkZW8+XG4gIH1cbjwvZGl2PlxuXG4iXX0=