@sunbird-cb/cbp-ai 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/esm2022/lib/ai-cbp-routing.module.mjs +56 -0
- package/esm2022/lib/ai-cbp.component.mjs +14 -0
- package/esm2022/lib/ai-cbp.module.mjs +263 -0
- package/esm2022/lib/ai-cbp.service.mjs +14 -0
- package/esm2022/lib/components/add-course/add-course.component.mjs +444 -0
- package/esm2022/lib/components/add-designation/add-designation.component.mjs +460 -0
- package/esm2022/lib/components/add-personalisation/add-personalisation.component.mjs +33 -0
- package/esm2022/lib/components/approval-request-form/approval-request-form.component.mjs +392 -0
- package/esm2022/lib/components/approval-requests/approval-requests.component.mjs +398 -0
- package/esm2022/lib/components/dashboard/dashboard.component.mjs +265 -0
- package/esm2022/lib/components/delete-role-mapping/delete-role-mapping.component.mjs +53 -0
- package/esm2022/lib/components/delete-role-mapping-popup/delete-role-mapping-popup.component.mjs +39 -0
- package/esm2022/lib/components/edit-cbp-plan/edit-cbp-plan.component.mjs +699 -0
- package/esm2022/lib/components/gap-analysis-recommended-course/gap-analysis-recommended-course.component.mjs +188 -0
- package/esm2022/lib/components/generate-course-recommendation/generate-course-recommendation.component.mjs +1949 -0
- package/esm2022/lib/components/list-popup/list-popup.component.mjs +32 -0
- package/esm2022/lib/components/review-request/review-request.component.mjs +138 -0
- package/esm2022/lib/components/role-mapping-generation/role-mapping-generation.component.mjs +1082 -0
- package/esm2022/lib/components/role-mapping-list/role-mapping-list.component.mjs +714 -0
- package/esm2022/lib/components/suggest-more-courses/suggest-more-courses.component.mjs +370 -0
- package/esm2022/lib/components/update-designation-hierarchy/update-designation-hierarchy.component.mjs +235 -0
- package/esm2022/lib/components/view-cbp-plan/view-cbp-plan.component.mjs +125 -0
- package/esm2022/lib/components/view-course-recommendation/view-course-recommendation.component.mjs +397 -0
- package/esm2022/lib/components/view-final-cbp-plan/view-final-cbp-plan.component.mjs +883 -0
- package/esm2022/lib/modules/initial-screen/initial-screen.component.mjs +127 -0
- package/esm2022/lib/modules/shared/constant/app.constant.mjs +2036 -0
- package/esm2022/lib/modules/shared/directives/clickoutside.directive.mjs +38 -0
- package/esm2022/lib/modules/shared/directives/directive.module.mjs +21 -0
- package/esm2022/lib/modules/shared/pipes/order-by-name.pipe.mjs +23 -0
- package/esm2022/lib/modules/shared/services/event.service.mjs +24 -0
- package/esm2022/lib/modules/shared/services/events.mjs +125 -0
- package/esm2022/lib/modules/shared/services/init.service.mjs +41 -0
- package/esm2022/lib/modules/shared/services/role-mapping.service.mjs +261 -0
- package/esm2022/lib/modules/shared/services/shared.service.mjs +869 -0
- package/esm2022/lib/modules/upload-document-page/progress-dialog/progress-dialog.component.mjs +53 -0
- package/esm2022/lib/modules/upload-document-page/upload-dialog/upload-dialog.component.mjs +186 -0
- package/esm2022/lib/modules/upload-document-page/upload-document-page.component.mjs +367 -0
- package/esm2022/lib/pipe-public-URL/pipe-public-URL.module.mjs +20 -0
- package/esm2022/lib/pipe-public-URL/pipe-public-URL.pipe.mjs +23 -0
- package/esm2022/public-api.mjs +14 -0
- package/esm2022/sunbird-cb-cbp-ai.mjs +5 -0
- package/fesm2022/sunbird-cb-cbp-ai.mjs +12952 -0
- package/fesm2022/sunbird-cb-cbp-ai.mjs.map +1 -0
- package/index.d.ts +6 -0
- package/lib/ai-cbp-routing.module.d.ts +8 -0
- package/lib/ai-cbp-routing.module.d.ts.map +1 -0
- package/lib/ai-cbp.component.d.ts +7 -0
- package/lib/ai-cbp.component.d.ts.map +1 -0
- package/lib/ai-cbp.module.d.ts +68 -0
- package/lib/ai-cbp.module.d.ts.map +1 -0
- package/lib/ai-cbp.service.d.ts +7 -0
- package/lib/ai-cbp.service.d.ts.map +1 -0
- package/lib/components/add-course/add-course.component.d.ts +67 -0
- package/lib/components/add-course/add-course.component.d.ts.map +1 -0
- package/lib/components/add-designation/add-designation.component.d.ts +52 -0
- package/lib/components/add-designation/add-designation.component.d.ts.map +1 -0
- package/lib/components/add-personalisation/add-personalisation.component.d.ts +16 -0
- package/lib/components/add-personalisation/add-personalisation.component.d.ts.map +1 -0
- package/lib/components/approval-request-form/approval-request-form.component.d.ts +48 -0
- package/lib/components/approval-request-form/approval-request-form.component.d.ts.map +1 -0
- package/lib/components/approval-requests/approval-requests.component.d.ts +80 -0
- package/lib/components/approval-requests/approval-requests.component.d.ts.map +1 -0
- package/lib/components/dashboard/dashboard.component.d.ts +55 -0
- package/lib/components/dashboard/dashboard.component.d.ts.map +1 -0
- package/lib/components/delete-role-mapping/delete-role-mapping.component.d.ts +18 -0
- package/lib/components/delete-role-mapping/delete-role-mapping.component.d.ts.map +1 -0
- package/lib/components/delete-role-mapping-popup/delete-role-mapping-popup.component.d.ts +18 -0
- package/lib/components/delete-role-mapping-popup/delete-role-mapping-popup.component.d.ts.map +1 -0
- package/lib/components/edit-cbp-plan/edit-cbp-plan.component.d.ts +94 -0
- package/lib/components/edit-cbp-plan/edit-cbp-plan.component.d.ts.map +1 -0
- package/lib/components/gap-analysis-recommended-course/gap-analysis-recommended-course.component.d.ts +35 -0
- package/lib/components/gap-analysis-recommended-course/gap-analysis-recommended-course.component.d.ts.map +1 -0
- package/lib/components/generate-course-recommendation/generate-course-recommendation.component.d.ts +198 -0
- package/lib/components/generate-course-recommendation/generate-course-recommendation.component.d.ts.map +1 -0
- package/lib/components/list-popup/list-popup.component.d.ts +13 -0
- package/lib/components/list-popup/list-popup.component.d.ts.map +1 -0
- package/lib/components/review-request/review-request.component.d.ts +39 -0
- package/lib/components/review-request/review-request.component.d.ts.map +1 -0
- package/lib/components/role-mapping-generation/role-mapping-generation.component.d.ts +99 -0
- package/lib/components/role-mapping-generation/role-mapping-generation.component.d.ts.map +1 -0
- package/lib/components/role-mapping-list/role-mapping-list.component.d.ts +83 -0
- package/lib/components/role-mapping-list/role-mapping-list.component.d.ts.map +1 -0
- package/lib/components/suggest-more-courses/suggest-more-courses.component.d.ts +48 -0
- package/lib/components/suggest-more-courses/suggest-more-courses.component.d.ts.map +1 -0
- package/lib/components/update-designation-hierarchy/update-designation-hierarchy.component.d.ts +41 -0
- package/lib/components/update-designation-hierarchy/update-designation-hierarchy.component.d.ts.map +1 -0
- package/lib/components/view-cbp-plan/view-cbp-plan.component.d.ts +29 -0
- package/lib/components/view-cbp-plan/view-cbp-plan.component.d.ts.map +1 -0
- package/lib/components/view-course-recommendation/view-course-recommendation.component.d.ts +49 -0
- package/lib/components/view-course-recommendation/view-course-recommendation.component.d.ts.map +1 -0
- package/lib/components/view-final-cbp-plan/view-final-cbp-plan.component.d.ts +73 -0
- package/lib/components/view-final-cbp-plan/view-final-cbp-plan.component.d.ts.map +1 -0
- package/lib/modules/initial-screen/initial-screen.component.d.ts +85 -0
- package/lib/modules/initial-screen/initial-screen.component.d.ts.map +1 -0
- package/lib/modules/shared/constant/app.constant.d.ts +457 -0
- package/lib/modules/shared/constant/app.constant.d.ts.map +1 -0
- package/lib/modules/shared/directives/clickoutside.directive.d.ts +13 -0
- package/lib/modules/shared/directives/clickoutside.directive.d.ts.map +1 -0
- package/lib/modules/shared/directives/directive.module.d.ts +8 -0
- package/lib/modules/shared/directives/directive.module.d.ts.map +1 -0
- package/lib/modules/shared/pipes/order-by-name.pipe.d.ts +8 -0
- package/lib/modules/shared/pipes/order-by-name.pipe.d.ts.map +1 -0
- package/lib/modules/shared/services/event.service.d.ts +12 -0
- package/lib/modules/shared/services/event.service.d.ts.map +1 -0
- package/lib/modules/shared/services/events.d.ts +200 -0
- package/lib/modules/shared/services/events.d.ts.map +1 -0
- package/lib/modules/shared/services/init.service.d.ts +13 -0
- package/lib/modules/shared/services/init.service.d.ts.map +1 -0
- package/lib/modules/shared/services/role-mapping.service.d.ts +21 -0
- package/lib/modules/shared/services/role-mapping.service.d.ts.map +1 -0
- package/lib/modules/shared/services/shared.service.d.ts +108 -0
- package/lib/modules/shared/services/shared.service.d.ts.map +1 -0
- package/lib/modules/upload-document-page/progress-dialog/progress-dialog.component.d.ts +14 -0
- package/lib/modules/upload-document-page/progress-dialog/progress-dialog.component.d.ts.map +1 -0
- package/lib/modules/upload-document-page/upload-dialog/upload-dialog.component.d.ts +29 -0
- package/lib/modules/upload-document-page/upload-dialog/upload-dialog.component.d.ts.map +1 -0
- package/lib/modules/upload-document-page/upload-document-page.component.d.ts +64 -0
- package/lib/modules/upload-document-page/upload-document-page.component.d.ts.map +1 -0
- package/lib/pipe-public-URL/pipe-public-URL.module.d.ts +9 -0
- package/lib/pipe-public-URL/pipe-public-URL.module.d.ts.map +1 -0
- package/lib/pipe-public-URL/pipe-public-URL.pipe.d.ts +11 -0
- package/lib/pipe-public-URL/pipe-public-URL.pipe.d.ts.map +1 -0
- package/package.json +28 -0
- package/public-api.d.ts +11 -0
- package/public-api.d.ts.map +1 -0
- package/sunbird-cb-cbp-ai-0.0.1.tgz +0 -0
- package/sunbird-cb-cbp-ai.d.ts.map +1 -0
|
@@ -0,0 +1,1949 @@
|
|
|
1
|
+
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
2
|
+
import { Component, Inject, ViewChild } from '@angular/core';
|
|
3
|
+
import { SuggestMoreCoursesComponent } from '../suggest-more-courses/suggest-more-courses.component';
|
|
4
|
+
import { AddCourseComponent } from '../add-course/add-course.component';
|
|
5
|
+
import html2pdf from 'html2pdf.js';
|
|
6
|
+
import { interval, of } from 'rxjs';
|
|
7
|
+
import { switchMap, takeWhile, tap, catchError, finalize } from 'rxjs/operators';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
import * as i1 from "@angular/material/dialog";
|
|
10
|
+
import * as i2 from "../../modules/shared/services/shared.service";
|
|
11
|
+
import * as i3 from "@angular/material/snack-bar";
|
|
12
|
+
import * as i4 from "@angular/forms";
|
|
13
|
+
import * as i5 from "@angular/common";
|
|
14
|
+
import * as i6 from "@angular/material/legacy-form-field";
|
|
15
|
+
import * as i7 from "@angular/material/legacy-input";
|
|
16
|
+
import * as i8 from "@angular/material/legacy-button";
|
|
17
|
+
import * as i9 from "@angular/material/icon";
|
|
18
|
+
import * as i10 from "@angular/material/legacy-select";
|
|
19
|
+
import * as i11 from "@angular/material/legacy-core";
|
|
20
|
+
import * as i12 from "@angular/material/legacy-checkbox";
|
|
21
|
+
import * as i13 from "@angular/material/progress-spinner";
|
|
22
|
+
import * as i14 from "@angular/material/tabs";
|
|
23
|
+
import * as i15 from "../gap-analysis-recommended-course/gap-analysis-recommended-course.component";
|
|
24
|
+
export class GenerateCourseRecommendationComponent {
|
|
25
|
+
constructor(dialogRef, data, sharedService, snackBar, dialog, fb) {
|
|
26
|
+
this.dialogRef = dialogRef;
|
|
27
|
+
this.data = data;
|
|
28
|
+
this.sharedService = sharedService;
|
|
29
|
+
this.snackBar = snackBar;
|
|
30
|
+
this.dialog = dialog;
|
|
31
|
+
this.fb = fb;
|
|
32
|
+
this.loading = false;
|
|
33
|
+
this.dataLoaded = false; // Track if initial data has been loaded
|
|
34
|
+
this.isRegeneratingWithProgress = false; // Track regeneration with progress loading
|
|
35
|
+
this.recommended_course_id = '';
|
|
36
|
+
// Progressive loading for course generation
|
|
37
|
+
this.currentProcessingStage = '';
|
|
38
|
+
this.progressPercentage = 0;
|
|
39
|
+
this.processingStages = [
|
|
40
|
+
'Analyzing roles and responsibilities...',
|
|
41
|
+
'Detailing competency requirements...',
|
|
42
|
+
'Preparing iGOT course recommendations...',
|
|
43
|
+
'Generating public course suggestions...',
|
|
44
|
+
'Computing comprehensive gap analysis...',
|
|
45
|
+
'Finalizing course recommendation plan...'
|
|
46
|
+
];
|
|
47
|
+
this.stageStartTime = 0;
|
|
48
|
+
this.searchText = '';
|
|
49
|
+
this.filterdCourses = [];
|
|
50
|
+
this.originalData = [];
|
|
51
|
+
this.selectFilterCourses = [];
|
|
52
|
+
this.suggestedCourses = []; // Track iGOT suggested courses separately
|
|
53
|
+
this.userAddedCourses = []; // Track user-added courses separately
|
|
54
|
+
this.mode = 'add';
|
|
55
|
+
this.cbp_plan_id = '';
|
|
56
|
+
this.expandedCompetencies = {}; // Track expanded state for each course and competency type
|
|
57
|
+
this.outerTabActiveIndex = 0;
|
|
58
|
+
this.innerTabActiveIndex = 0;
|
|
59
|
+
this.outerTabActiveText = 'all';
|
|
60
|
+
this.innerTabActiveText = 'all';
|
|
61
|
+
this.selectedCategory = 'all';
|
|
62
|
+
this.competencyCoveredCount = 0;
|
|
63
|
+
this.overallCoverage = 0;
|
|
64
|
+
this.behavioralCompetencyCoveredCount = 0;
|
|
65
|
+
this.behavioralTotalCompetencies = 0;
|
|
66
|
+
this.behavioralCoverage = 0;
|
|
67
|
+
this.functionalCompetencyCoveredCount = 0;
|
|
68
|
+
this.functionalTotalCompetencies = 0;
|
|
69
|
+
this.functionalCoverage = 0;
|
|
70
|
+
this.domainCompetencyCoveredCount = 0;
|
|
71
|
+
this.domainTotalCompetencies = 0;
|
|
72
|
+
this.domainCoverage = 0;
|
|
73
|
+
this.competencyNotMatchedByCategory = [];
|
|
74
|
+
this.competencyMatchedByCategory = [];
|
|
75
|
+
this.menuItems = [
|
|
76
|
+
{ key: 'all', label: 'All Categories' },
|
|
77
|
+
{ key: 'behavioral', label: 'Behavioural' },
|
|
78
|
+
{ key: 'functional', label: 'Functional' },
|
|
79
|
+
{ key: 'domain', label: 'Domain' }
|
|
80
|
+
];
|
|
81
|
+
this.behaviouralNotMatched = [];
|
|
82
|
+
this.functionalNotMatched = [];
|
|
83
|
+
this.domainNotMatched = [];
|
|
84
|
+
this.selectedThemeFilter = '';
|
|
85
|
+
this.originalFilteredCourses = [];
|
|
86
|
+
this.isRegenerating = false;
|
|
87
|
+
this.isPDFDownload = false;
|
|
88
|
+
this.behaviouralMatched = [];
|
|
89
|
+
this.functionalMatched = [];
|
|
90
|
+
this.domainMatched = [];
|
|
91
|
+
this.competenciesType = ['All', 'Behavioural', 'Functional', 'Domain'];
|
|
92
|
+
this.ratings = ['4.5 and above', '4.0 and above', '3.5 and above', '2.5 and above', '1 and above'];
|
|
93
|
+
this.languages = ['English', 'Hindi', 'Tamil', 'Kannada', 'Telugu', 'Malayalam', 'Assamese', 'Bengali', 'Gujarati', 'Marathi', 'Odia', 'Punjabi', 'Konkani', 'Bodo', 'Dogri', 'Kashmiri', 'Maithili', 'Manipuri', 'Nepali', 'Sanskrit', 'Santali', 'Sindhi', 'Urdu'];
|
|
94
|
+
this.durations = ['< 1 Hour', '1-5 Hours', '5+ Hours'];
|
|
95
|
+
this.providers = [];
|
|
96
|
+
this.filteredCompetency = [...this.competenciesType];
|
|
97
|
+
this.filteredRatings = [...this.ratings];
|
|
98
|
+
this.filteredLanguages = [...this.languages];
|
|
99
|
+
this.filteredDurations = [...this.durations];
|
|
100
|
+
this.filteredProviders = [...this.providers];
|
|
101
|
+
this.fullCourseList = [];
|
|
102
|
+
// Selected filters
|
|
103
|
+
this.selectedCompetency = 'All';
|
|
104
|
+
this.selectedRating = null;
|
|
105
|
+
this.selectedLanguage = null;
|
|
106
|
+
this.selectedDuration = null;
|
|
107
|
+
this.selectedProvider = null;
|
|
108
|
+
this.planData = data;
|
|
109
|
+
}
|
|
110
|
+
selectCategory(category) {
|
|
111
|
+
this.selectedCategory = category;
|
|
112
|
+
this.gapAnalysisStats();
|
|
113
|
+
}
|
|
114
|
+
ngOnInit() {
|
|
115
|
+
this.filterForm = this.fb.group({
|
|
116
|
+
competency: [[]],
|
|
117
|
+
rating: [[]],
|
|
118
|
+
language: [[]],
|
|
119
|
+
duration: [[]],
|
|
120
|
+
provider: [[]]
|
|
121
|
+
});
|
|
122
|
+
this.loadComponentData();
|
|
123
|
+
}
|
|
124
|
+
applyFilter(value) {
|
|
125
|
+
console.log('this.searchText', value);
|
|
126
|
+
this.searchText = value;
|
|
127
|
+
this.filterdCourses = this.filterData(this.searchText);
|
|
128
|
+
}
|
|
129
|
+
searchData() {
|
|
130
|
+
// this.filterdCourses = this.filterData(this.searchText);
|
|
131
|
+
}
|
|
132
|
+
selectedFilterCourses(event, item) {
|
|
133
|
+
console.log('event', event);
|
|
134
|
+
console.log('item', item);
|
|
135
|
+
if (event.checked) {
|
|
136
|
+
if (this.selectFilterCourses.indexOf(item?.identifier) < 0) {
|
|
137
|
+
this.selectFilterCourses.push(item?.identifier);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const index = this.selectFilterCourses.findIndex(control => control === item.identifier);
|
|
142
|
+
if (index !== -1) {
|
|
143
|
+
this.selectFilterCourses.splice(index, 1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log('this.selectFilterCourses', this.selectFilterCourses);
|
|
147
|
+
}
|
|
148
|
+
closeDialog() {
|
|
149
|
+
this.dialogRef.close();
|
|
150
|
+
}
|
|
151
|
+
saveCourses() {
|
|
152
|
+
this.loading = true;
|
|
153
|
+
console.log('this.planData', this.planData);
|
|
154
|
+
let reqBody = {
|
|
155
|
+
"role_mapping_id": this.planData.id,
|
|
156
|
+
"recommended_course_id": this.recommended_course_id,
|
|
157
|
+
"course_identifiers": this.selectFilterCourses
|
|
158
|
+
};
|
|
159
|
+
console.log('reqBody, ', reqBody);
|
|
160
|
+
if (this.mode === 'add') {
|
|
161
|
+
this.sharedService.saveCourse(reqBody).subscribe({
|
|
162
|
+
next: (res) => {
|
|
163
|
+
// Success handling
|
|
164
|
+
console.log('Success:', res);
|
|
165
|
+
this.loading = false;
|
|
166
|
+
this.dialogRef.close('saved');
|
|
167
|
+
this.snackBar.open('Courses Saved Successfully', 'X', {
|
|
168
|
+
duration: 3000,
|
|
169
|
+
panelClass: ['snackbar-success']
|
|
170
|
+
});
|
|
171
|
+
//this.successRoleMapping.emit(this.roleMappingForm)
|
|
172
|
+
},
|
|
173
|
+
error: (error) => {
|
|
174
|
+
console.log('error', error);
|
|
175
|
+
this.dialogRef.close();
|
|
176
|
+
// Handle 409 Conflict here
|
|
177
|
+
// alert('Conflict detected: The resource already exists or action conflicts.');
|
|
178
|
+
//this.get
|
|
179
|
+
// Or you can set a UI error message variable
|
|
180
|
+
this.snackBar.open(error?.error?.detail, 'X', {
|
|
181
|
+
duration: 3000,
|
|
182
|
+
panelClass: ['snackbar-error']
|
|
183
|
+
});
|
|
184
|
+
this.loading = false;
|
|
185
|
+
//this.alreadyAvailableRoleMapping.emit(this.roleMappingForm)
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
if (this.cbp_plan_id) {
|
|
191
|
+
this.sharedService.updateCourse(reqBody, this.cbp_plan_id).subscribe({
|
|
192
|
+
next: (res) => {
|
|
193
|
+
// Success handling
|
|
194
|
+
console.log('Success:', res);
|
|
195
|
+
this.loading = false;
|
|
196
|
+
this.dialogRef.close('saved');
|
|
197
|
+
this.snackBar.open('Courses Updated Successfully', 'X', {
|
|
198
|
+
duration: 3000,
|
|
199
|
+
panelClass: ['snackbar-success']
|
|
200
|
+
});
|
|
201
|
+
//this.successRoleMapping.emit(this.roleMappingForm)
|
|
202
|
+
},
|
|
203
|
+
error: (error) => {
|
|
204
|
+
console.log('error', error);
|
|
205
|
+
this.dialogRef.close();
|
|
206
|
+
// Handle 409 Conflict here
|
|
207
|
+
// alert('Conflict detected: The resource already exists or action conflicts.');
|
|
208
|
+
//this.get
|
|
209
|
+
// Or you can set a UI error message variable
|
|
210
|
+
this.snackBar.open(error?.error?.detail, 'X', {
|
|
211
|
+
duration: 3000,
|
|
212
|
+
panelClass: ['snackbar-error']
|
|
213
|
+
});
|
|
214
|
+
this.loading = false;
|
|
215
|
+
//this.alreadyAvailableRoleMapping.emit(this.roleMappingForm)
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
// Handle case when cbp_plan_id is not available
|
|
221
|
+
this.loading = false;
|
|
222
|
+
console.error('cbp_plan_id is not available for update operation');
|
|
223
|
+
this.snackBar.open('Unable to update courses: missing plan ID', 'X', {
|
|
224
|
+
duration: 3000,
|
|
225
|
+
panelClass: ['snackbar-error']
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
getCourses() {
|
|
231
|
+
let role_mapping_id = this.planData.id;
|
|
232
|
+
this.loading = true;
|
|
233
|
+
this.sharedService.getCourse(role_mapping_id).subscribe({
|
|
234
|
+
next: (res) => {
|
|
235
|
+
// Success handling
|
|
236
|
+
this.loading = false;
|
|
237
|
+
console.log('res', res);
|
|
238
|
+
this.cbp_plan_id = res?.id;
|
|
239
|
+
if (res && res?.selected_courses && res?.selected_courses?.length) {
|
|
240
|
+
this.mode = 'edit';
|
|
241
|
+
for (let i = 0; i < res?.selected_courses.length; i++) {
|
|
242
|
+
this.selectFilterCourses.push(res.selected_courses[i]?.identifier);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
//this.successRoleMapping.emit(this.roleMappingForm)
|
|
246
|
+
},
|
|
247
|
+
error: (error) => {
|
|
248
|
+
console.log('error', error);
|
|
249
|
+
this.loading = false;
|
|
250
|
+
// Handle 409 Conflict here
|
|
251
|
+
// alert('Conflict detected: The resource already exists or action conflicts.');
|
|
252
|
+
//this.get
|
|
253
|
+
// Or you can set a UI error message variable
|
|
254
|
+
this.loading = false;
|
|
255
|
+
//this.alreadyAvailableRoleMapping.emit(this.roleMappingForm)
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
getSuggestedCourse() {
|
|
260
|
+
let role_mapping_id = this.planData.id;
|
|
261
|
+
this.loading = true;
|
|
262
|
+
this.sharedService.getSuggestedCourses(role_mapping_id).subscribe({
|
|
263
|
+
next: (res) => {
|
|
264
|
+
// Success handling
|
|
265
|
+
this.loading = false;
|
|
266
|
+
console.log('getSuggestedCourses res', res);
|
|
267
|
+
console.log('this.filterdCourses', this.filterdCourses);
|
|
268
|
+
// Store suggested courses separately
|
|
269
|
+
this.suggestedCourses = [...res];
|
|
270
|
+
// Rebuild filterdCourses to include all course types
|
|
271
|
+
this.rebuildFilteredCourses();
|
|
272
|
+
// Update gap analysis stats after suggested courses are added
|
|
273
|
+
this.updateGapAnalysisAfterCoursesUpdate();
|
|
274
|
+
//this.successRoleMapping.emit(this.roleMappingForm)
|
|
275
|
+
},
|
|
276
|
+
error: (error) => {
|
|
277
|
+
console.log('error', error);
|
|
278
|
+
this.loading = false;
|
|
279
|
+
if (error.status === 401) {
|
|
280
|
+
console.log('Unauthorized access - user will be redirected to login');
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// Handle other errors gracefully
|
|
284
|
+
console.error('Failed to load suggested courses');
|
|
285
|
+
}
|
|
286
|
+
// Or you can set a UI error message variable
|
|
287
|
+
this.loading = false;
|
|
288
|
+
//this.alreadyAvailableRoleMapping.emit(this.roleMappingForm)
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
getUserCourse() {
|
|
293
|
+
let role_mapping_id = this.planData.id;
|
|
294
|
+
this.loading = true;
|
|
295
|
+
this.sharedService.getUserCourse(role_mapping_id).subscribe({
|
|
296
|
+
next: (res) => {
|
|
297
|
+
// Success handling
|
|
298
|
+
this.loading = false;
|
|
299
|
+
console.log('getUserCourse API response:', res);
|
|
300
|
+
console.log('Current filterdCourses before adding user courses:', this.filterdCourses);
|
|
301
|
+
// Store user-added courses separately (reset to avoid duplicates)
|
|
302
|
+
this.userAddedCourses = [...res];
|
|
303
|
+
// Process user-added courses to ensure proper structure
|
|
304
|
+
for (let i = 0; i < res.length; i++) {
|
|
305
|
+
const userCourse = res[i];
|
|
306
|
+
console.log(`User course ${i} competencies:`, userCourse.competencies);
|
|
307
|
+
// Ensure user-added courses have the expected structure for display
|
|
308
|
+
if (userCourse && !userCourse.course_type) {
|
|
309
|
+
userCourse.course_type = 'User Added';
|
|
310
|
+
}
|
|
311
|
+
// Add identifier if missing (needed for course selection logic)
|
|
312
|
+
if (userCourse && !userCourse.identifier) {
|
|
313
|
+
userCourse.identifier = userCourse.id || `user_course_${i}_${Date.now()}`;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Rebuild filterdCourses to include all course types
|
|
317
|
+
this.rebuildFilteredCourses();
|
|
318
|
+
console.log('filterdCourses after adding user courses:', this.filterdCourses);
|
|
319
|
+
//this.successRoleMapping.emit(this.roleMappingForm)
|
|
320
|
+
},
|
|
321
|
+
error: (error) => {
|
|
322
|
+
console.log('error', error);
|
|
323
|
+
this.loading = false;
|
|
324
|
+
// Handle 409 Conflict here
|
|
325
|
+
// alert('Conflict detected: The resource already exists or action conflicts.');
|
|
326
|
+
//this.get
|
|
327
|
+
// Or you can set a UI error message variable
|
|
328
|
+
this.loading = false;
|
|
329
|
+
//this.alreadyAvailableRoleMapping.emit(this.roleMappingForm)
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
checkIfCourseExists(item) {
|
|
334
|
+
let flag = false;
|
|
335
|
+
if (this.selectFilterCourses.indexOf(item?.identifier) > -1) {
|
|
336
|
+
flag = true;
|
|
337
|
+
}
|
|
338
|
+
return flag;
|
|
339
|
+
}
|
|
340
|
+
selectAllCourses(event) {
|
|
341
|
+
if (event.checked) {
|
|
342
|
+
for (let i = 0; i < this.filterdCourses.length; i++) {
|
|
343
|
+
this.selectFilterCourses.push(this.filterdCourses[i].identifier);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
this.selectFilterCourses = [];
|
|
348
|
+
}
|
|
349
|
+
if (this.cbp_plan_id) {
|
|
350
|
+
this.mode = 'update';
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
this.mode = 'add';
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
getSectors(sector) {
|
|
357
|
+
if (sector && sector.length) {
|
|
358
|
+
return Array.isArray(sector) ? sector.join('/ ') : '';
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
filterData(searchText) {
|
|
362
|
+
const filter = searchText.trim().toLowerCase();
|
|
363
|
+
return this.originalData.filter(item => {
|
|
364
|
+
const stringified = this.flattenObjectToString(item).toLowerCase();
|
|
365
|
+
return stringified.includes(filter);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
flattenObjectToString(obj) {
|
|
369
|
+
let result = '';
|
|
370
|
+
for (const key in obj) {
|
|
371
|
+
const value = obj[key];
|
|
372
|
+
if (typeof value === 'string') {
|
|
373
|
+
result += ' ' + value;
|
|
374
|
+
}
|
|
375
|
+
else if (Array.isArray(value)) {
|
|
376
|
+
value.forEach(val => {
|
|
377
|
+
if (typeof val === 'string') {
|
|
378
|
+
result += ' ' + val;
|
|
379
|
+
}
|
|
380
|
+
else if (typeof val === 'object') {
|
|
381
|
+
result += ' ' + this.flattenObjectToString(val);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
else if (typeof value === 'object' && value !== null) {
|
|
386
|
+
result += ' ' + this.flattenObjectToString(value);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
suggestMoreCourses() {
|
|
392
|
+
// this.dialogRef.close()
|
|
393
|
+
const dialogRefNew = this.dialog.open(SuggestMoreCoursesComponent, {
|
|
394
|
+
width: '1000px',
|
|
395
|
+
data: { recommended_course_id: this.recommended_course_id, role_mapping_id: this.planData.id },
|
|
396
|
+
panelClass: 'view-cbp-plan-popup',
|
|
397
|
+
minHeight: '400px',
|
|
398
|
+
maxHeight: '90vh',
|
|
399
|
+
disableClose: true // Optional: prevent closing with outside click
|
|
400
|
+
});
|
|
401
|
+
dialogRefNew.afterClosed().subscribe(result => {
|
|
402
|
+
if (result === 'saved') {
|
|
403
|
+
console.log('Changes saved!');
|
|
404
|
+
// Refresh data or show a toast here
|
|
405
|
+
this.getSuggestedCourse();
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
this.getSuggestedCourse();
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
generateCourseRecommendation(element) {
|
|
413
|
+
console.log('Generate Course Recommendation clicked', element);
|
|
414
|
+
// this.activeRowElement = element
|
|
415
|
+
console.log('Edit Role Mapping clicked', element);
|
|
416
|
+
// Navigate or open modal
|
|
417
|
+
console.log('View CBP Plan clicked', element);
|
|
418
|
+
const dialogRef = this.dialog.open(GenerateCourseRecommendationComponent, {
|
|
419
|
+
width: '1000px',
|
|
420
|
+
data: element,
|
|
421
|
+
panelClass: 'view-cbp-plan-popup',
|
|
422
|
+
minHeight: '400px',
|
|
423
|
+
maxHeight: '90vh',
|
|
424
|
+
disableClose: true // Optional: prevent closing with outside click
|
|
425
|
+
});
|
|
426
|
+
dialogRef.afterClosed().subscribe(result => {
|
|
427
|
+
if (result === 'saved') {
|
|
428
|
+
console.log('Changes saved!');
|
|
429
|
+
// Refresh data or show a toast here
|
|
430
|
+
console.log(this.sharedService.cbpPlanFinalObj);
|
|
431
|
+
if (this.sharedService.cbpPlanFinalObj && this.sharedService.cbpPlanFinalObj.ministry && this.sharedService.cbpPlanFinalObj.ministry.id) {
|
|
432
|
+
this.sharedService.getRoleMappingByStateCenter(this.sharedService.cbpPlanFinalObj.ministry.id).subscribe((res) => {
|
|
433
|
+
console.log('res', res);
|
|
434
|
+
// this.dataSource.data = res
|
|
435
|
+
// this.dataSource.paginator = this.paginator;
|
|
436
|
+
this.originalData = res;
|
|
437
|
+
// console.log('this.dataSource',this.dataSource)
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
getCompetenciesByType(type, index) {
|
|
446
|
+
const course = this.filterdCourses[index];
|
|
447
|
+
if (!course) {
|
|
448
|
+
console.log(`No course found at index ${index}`);
|
|
449
|
+
return [];
|
|
450
|
+
}
|
|
451
|
+
// Handle different competency property names
|
|
452
|
+
// AI Recommended & Public courses use 'competencies'
|
|
453
|
+
// Manually Suggested - iGOT courses use 'competencies_v6'
|
|
454
|
+
// User Added courses use 'competencies'
|
|
455
|
+
let competencies = [];
|
|
456
|
+
if (course.competencies && Array.isArray(course.competencies)) {
|
|
457
|
+
competencies = course.competencies;
|
|
458
|
+
// console.log(`Course ${index} (${course.course_type || course.name || 'Unknown'}) using 'competencies' property:`, competencies);
|
|
459
|
+
}
|
|
460
|
+
else if (course.competencies_v6 && Array.isArray(course.competencies_v6)) {
|
|
461
|
+
competencies = course.competencies_v6;
|
|
462
|
+
// console.log(`Course ${index} (${course.course_type || course.name || 'Unknown'}) using 'competencies_v6' property:`, competencies);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
// console.log(`Course ${index} (${course.course_type || course.name || 'Unknown'}) has no valid competencies property:`, {
|
|
466
|
+
// hasCompetencies: !!course.competencies,
|
|
467
|
+
// competenciesType: typeof course.competencies,
|
|
468
|
+
// hasCompetenciesV6: !!course.competencies_v6,
|
|
469
|
+
// competenciesV6Type: typeof course.competencies_v6,
|
|
470
|
+
// courseKeys: Object.keys(course)
|
|
471
|
+
// });
|
|
472
|
+
}
|
|
473
|
+
if (competencies.length === 0) {
|
|
474
|
+
// console.log(`No competencies found for course ${index} and type ${type}`);
|
|
475
|
+
return [];
|
|
476
|
+
}
|
|
477
|
+
// Normalize the type for comparison (case-insensitive + handle spelling variations)
|
|
478
|
+
const normalizedType = type.toLowerCase().trim();
|
|
479
|
+
const matchedCompetencies = competencies.filter(c => {
|
|
480
|
+
if (!c || !c.competencyAreaName) {
|
|
481
|
+
console.log(`Invalid competency structure in course ${index}:`, c);
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
const competencyArea = c.competencyAreaName.toLowerCase().trim();
|
|
485
|
+
// Handle both "behavioral" and "behavioural" spellings
|
|
486
|
+
if (normalizedType === 'behavioural' || normalizedType === 'behavioral') {
|
|
487
|
+
return competencyArea === 'behavioral' || competencyArea === 'behavioural';
|
|
488
|
+
}
|
|
489
|
+
// For other types, do case-insensitive comparison
|
|
490
|
+
return competencyArea === normalizedType;
|
|
491
|
+
});
|
|
492
|
+
// console.log(`Found ${matchedCompetencies.length} competencies of type ${type} for course ${index}:`, matchedCompetencies);
|
|
493
|
+
return matchedCompetencies;
|
|
494
|
+
}
|
|
495
|
+
getCompetenciesByBehviouralType(index) {
|
|
496
|
+
const course = this.filterdCourses[index];
|
|
497
|
+
if (!course) {
|
|
498
|
+
return '';
|
|
499
|
+
}
|
|
500
|
+
// Handle different competency property names
|
|
501
|
+
let competencies = [];
|
|
502
|
+
if (course.competencies && Array.isArray(course.competencies)) {
|
|
503
|
+
competencies = course.competencies;
|
|
504
|
+
}
|
|
505
|
+
else if (course.competencies_v6 && Array.isArray(course.competencies_v6)) {
|
|
506
|
+
competencies = course.competencies_v6;
|
|
507
|
+
}
|
|
508
|
+
if (competencies.length === 0) {
|
|
509
|
+
return '';
|
|
510
|
+
}
|
|
511
|
+
return competencies
|
|
512
|
+
.filter(c => c && (c.competencyAreaName === 'Behavioral' || c.competencyAreaName === 'Behavioural'))
|
|
513
|
+
.map(c => `${c.competencyThemeName || ''} - ${c.competencySubThemeName || ''}`)
|
|
514
|
+
.join(', ');
|
|
515
|
+
}
|
|
516
|
+
getDisplayedCompetencies(type, index) {
|
|
517
|
+
const competencies = this.getCompetenciesByType(type, index);
|
|
518
|
+
const key = `${index}-${type}`;
|
|
519
|
+
if (this.expandedCompetencies[key]) {
|
|
520
|
+
return competencies;
|
|
521
|
+
}
|
|
522
|
+
return competencies.slice(0, 2);
|
|
523
|
+
}
|
|
524
|
+
toggleCompetencies(type, index) {
|
|
525
|
+
const key = `${index}-${type}`;
|
|
526
|
+
this.expandedCompetencies[key] = !this.expandedCompetencies[key];
|
|
527
|
+
}
|
|
528
|
+
isExpanded(type, index) {
|
|
529
|
+
const key = `${index}-${type}`;
|
|
530
|
+
return this.expandedCompetencies[key] || false;
|
|
531
|
+
}
|
|
532
|
+
hasMoreThanTwo(type, index) {
|
|
533
|
+
return this.getCompetenciesByType(type, index).length > 2;
|
|
534
|
+
}
|
|
535
|
+
getRemainingCount(type, index) {
|
|
536
|
+
const totalCount = this.getCompetenciesByType(type, index).length;
|
|
537
|
+
return totalCount - 2;
|
|
538
|
+
}
|
|
539
|
+
onOuterTabChange(event) {
|
|
540
|
+
this.outerTabActiveIndex = event.index;
|
|
541
|
+
this.outerTabActiveText = event.tab.textLabel;
|
|
542
|
+
console.log('Outer Tab Index:', event.index);
|
|
543
|
+
console.log('Outer Tab Label:', event.tab.textLabel);
|
|
544
|
+
if (event.index === 1) {
|
|
545
|
+
this.gapAnalysisStats();
|
|
546
|
+
}
|
|
547
|
+
if (event.index === 0) {
|
|
548
|
+
// this.getCourses()
|
|
549
|
+
// this.getSuggestedCourse()
|
|
550
|
+
this.getUserCourse();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
onInnerTabChange(event) {
|
|
554
|
+
this.innerTabActiveIndex = event.index;
|
|
555
|
+
this.innerTabActiveText = event.tab.textLabel;
|
|
556
|
+
this.selectedThemeFilter = ''; // Reset theme filter when switching tabs
|
|
557
|
+
console.log('Inner Tab Index:', event.index);
|
|
558
|
+
console.log('Inner Tab Label:', event.tab.textLabel);
|
|
559
|
+
let tabIndex = event.index;
|
|
560
|
+
this.competencyMatchedByCategory = [];
|
|
561
|
+
// Get all available courses (original + suggested + user added)
|
|
562
|
+
const allAvailableCourses = this.getAllAvailableCourses();
|
|
563
|
+
switch (tabIndex) {
|
|
564
|
+
case 0: // All
|
|
565
|
+
this.filterdCourses = allAvailableCourses;
|
|
566
|
+
break;
|
|
567
|
+
case 1: // Behavioral
|
|
568
|
+
this.filterdCourses = this.behavioralFilter(allAvailableCourses);
|
|
569
|
+
this.competencyMatchedByCategory = this.behavioralCompetencyFilter(this.planData.competencies);
|
|
570
|
+
break;
|
|
571
|
+
case 2: // Functional
|
|
572
|
+
this.filterdCourses = this.functionalFilter(allAvailableCourses);
|
|
573
|
+
this.competencyMatchedByCategory = this.functionalCompetencyFilter(this.planData.competencies);
|
|
574
|
+
break;
|
|
575
|
+
case 3: // Domain
|
|
576
|
+
this.filterdCourses = this.domainFilter(allAvailableCourses);
|
|
577
|
+
this.competencyMatchedByCategory = this.domainCompetencyFilter(this.planData.competencies);
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
console.log('this.filterdCourses', this.filterdCourses);
|
|
581
|
+
console.log('this.competencyMatchedByCategory', this.competencyMatchedByCategory);
|
|
582
|
+
}
|
|
583
|
+
getAllAvailableCourses() {
|
|
584
|
+
// Start with original data (AI recommended courses)
|
|
585
|
+
const allCourses = [...this.originalData];
|
|
586
|
+
const seenIdentifiers = new Set();
|
|
587
|
+
// Track original course identifiers
|
|
588
|
+
this.originalData.forEach(course => {
|
|
589
|
+
if (course.identifier)
|
|
590
|
+
seenIdentifiers.add(course.identifier);
|
|
591
|
+
if (course.id)
|
|
592
|
+
seenIdentifiers.add(course.id);
|
|
593
|
+
});
|
|
594
|
+
// Add suggested courses (iGOT platform courses)
|
|
595
|
+
this.suggestedCourses.forEach(course => {
|
|
596
|
+
const courseId = course.identifier || course.id;
|
|
597
|
+
if (courseId && !seenIdentifiers.has(courseId)) {
|
|
598
|
+
allCourses.push(course);
|
|
599
|
+
seenIdentifiers.add(courseId);
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
// Add user-added courses
|
|
603
|
+
this.userAddedCourses.forEach(course => {
|
|
604
|
+
const courseId = course.identifier || course.id;
|
|
605
|
+
if (courseId && !seenIdentifiers.has(courseId)) {
|
|
606
|
+
// Ensure user-added courses have proper structure
|
|
607
|
+
if (!course.course_type) {
|
|
608
|
+
course.course_type = 'User Added';
|
|
609
|
+
}
|
|
610
|
+
if (!course.identifier && course.id) {
|
|
611
|
+
course.identifier = course.id;
|
|
612
|
+
}
|
|
613
|
+
allCourses.push(course);
|
|
614
|
+
seenIdentifiers.add(courseId);
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
console.log('getAllAvailableCourses breakdown:', {
|
|
618
|
+
originalData: this.originalData.length,
|
|
619
|
+
suggestedCourses: this.suggestedCourses.length,
|
|
620
|
+
userAddedCourses: this.userAddedCourses.length,
|
|
621
|
+
totalAvailable: allCourses.length
|
|
622
|
+
});
|
|
623
|
+
console.log('allCourses--', allCourses);
|
|
624
|
+
allCourses.forEach((item) => {
|
|
625
|
+
if (item && item.organisation && item.organisation.length) {
|
|
626
|
+
if (this.filteredProviders.indexOf(item.organisation[0]) < 0) {
|
|
627
|
+
this.filteredProviders.push(item.organisation[0]);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
this.fullCourseList = allCourses;
|
|
632
|
+
let identifiersArr = [];
|
|
633
|
+
this.fullCourseList.map((item) => {
|
|
634
|
+
identifiersArr.push(item?.identifier);
|
|
635
|
+
});
|
|
636
|
+
this.sharedService.getAdditionalParameterforSuggestedCourses(identifiersArr).subscribe((response) => {
|
|
637
|
+
if (response && response.result && response.result.content && response.result.content.length) {
|
|
638
|
+
for (let i = 0; i < response.result.content.length; i++) {
|
|
639
|
+
for (let j = 0; j < this.fullCourseList.length; j++) {
|
|
640
|
+
if (this.fullCourseList[j]['identifier'] === response.result.content[i]['identifier']) {
|
|
641
|
+
this.fullCourseList[j]['language'] = response.result.content[i]['language'];
|
|
642
|
+
this.fullCourseList[j]['avgRating'] = response.result.content[i]['avgRating'];
|
|
643
|
+
this.fullCourseList[j]['course'] = response.result.content[i]['name'];
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
return allCourses;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Rebuild filterdCourses array with all available course types
|
|
654
|
+
* This ensures consistency across the application
|
|
655
|
+
*/
|
|
656
|
+
rebuildFilteredCourses() {
|
|
657
|
+
this.filterdCourses = this.getAllAvailableCourses();
|
|
658
|
+
console.log('Rebuilt filterdCourses with all course types:', {
|
|
659
|
+
total: this.filterdCourses.length,
|
|
660
|
+
breakdown: {
|
|
661
|
+
original: this.originalData.length,
|
|
662
|
+
suggested: this.suggestedCourses.length,
|
|
663
|
+
userAdded: this.userAddedCourses.length
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
behavioralFilter(data) {
|
|
668
|
+
return data.filter(item => {
|
|
669
|
+
if (!item)
|
|
670
|
+
return false;
|
|
671
|
+
// Handle different competency property names
|
|
672
|
+
let competencies = [];
|
|
673
|
+
if (item.competencies && Array.isArray(item.competencies)) {
|
|
674
|
+
competencies = item.competencies;
|
|
675
|
+
}
|
|
676
|
+
else if (item.competencies_v6 && Array.isArray(item.competencies_v6)) {
|
|
677
|
+
competencies = item.competencies_v6;
|
|
678
|
+
}
|
|
679
|
+
return competencies.some(c => c && ((c?.competencyAreaName?.toLowerCase() === 'behavioral') || c?.competencyAreaName?.toLowerCase() === 'behavioural'));
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
behavioralCompetencyFilter(data) {
|
|
683
|
+
console.log('data--', data);
|
|
684
|
+
const behavioralThemes = data
|
|
685
|
+
.filter(item => item?.type &&
|
|
686
|
+
['behavioral', 'behavioural'].includes(item.type.toLowerCase()))
|
|
687
|
+
.map(item => `${item.theme}-${item.sub_theme}`)
|
|
688
|
+
.filter((theme) => Boolean(theme)); // Ensures type safety
|
|
689
|
+
const uniqueBehavioralThemes = Array.from(new Set(behavioralThemes));
|
|
690
|
+
console.log(uniqueBehavioralThemes);
|
|
691
|
+
return uniqueBehavioralThemes;
|
|
692
|
+
}
|
|
693
|
+
functionalCompetencyFilter(data) {
|
|
694
|
+
const functionalThemes = data
|
|
695
|
+
.filter(item => item?.type &&
|
|
696
|
+
['functional'].includes(item.type.toLowerCase()))
|
|
697
|
+
.map(item => `${item.theme}-${item.sub_theme}`)
|
|
698
|
+
.filter((theme) => Boolean(theme)); // Ensures type safety
|
|
699
|
+
const uniqueFunctionalThemes = Array.from(new Set(functionalThemes));
|
|
700
|
+
console.log(uniqueFunctionalThemes);
|
|
701
|
+
return uniqueFunctionalThemes;
|
|
702
|
+
// console.log(uniqueCompetencyAreaNames);
|
|
703
|
+
}
|
|
704
|
+
domainCompetencyFilter(data) {
|
|
705
|
+
const domainThemes = data
|
|
706
|
+
.filter(item => item?.type &&
|
|
707
|
+
['domain'].includes(item.type.toLowerCase()))
|
|
708
|
+
.map(item => `${item.theme}-${item.sub_theme}`)
|
|
709
|
+
.filter((theme) => Boolean(theme)); // Ensures type safety
|
|
710
|
+
const uniqueDomainThemes = Array.from(new Set(domainThemes));
|
|
711
|
+
console.log(uniqueDomainThemes);
|
|
712
|
+
return uniqueDomainThemes;
|
|
713
|
+
// console.log(uniqueCompetencyAreaNames);
|
|
714
|
+
}
|
|
715
|
+
functionalFilter(data) {
|
|
716
|
+
return data.filter(item => {
|
|
717
|
+
if (!item)
|
|
718
|
+
return false;
|
|
719
|
+
// Handle different competency property names
|
|
720
|
+
let competencies = [];
|
|
721
|
+
if (item.competencies && Array.isArray(item.competencies)) {
|
|
722
|
+
competencies = item.competencies;
|
|
723
|
+
}
|
|
724
|
+
else if (item.competencies_v6 && Array.isArray(item.competencies_v6)) {
|
|
725
|
+
competencies = item.competencies_v6;
|
|
726
|
+
}
|
|
727
|
+
return competencies.some(c => c && c?.competencyAreaName?.toLowerCase() === 'functional');
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
domainFilter(data) {
|
|
731
|
+
return data.filter(item => {
|
|
732
|
+
if (!item)
|
|
733
|
+
return false;
|
|
734
|
+
// Handle different competency property names
|
|
735
|
+
let competencies = [];
|
|
736
|
+
if (item.competencies && Array.isArray(item.competencies)) {
|
|
737
|
+
competencies = item.competencies;
|
|
738
|
+
}
|
|
739
|
+
else if (item.competencies_v6 && Array.isArray(item.competencies_v6)) {
|
|
740
|
+
competencies = item.competencies_v6;
|
|
741
|
+
}
|
|
742
|
+
return competencies.some(c => c && c?.competencyAreaName?.toLowerCase() === 'domain');
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
gapAnalysisStats() {
|
|
746
|
+
console.log('this.planData', this.planData);
|
|
747
|
+
// Always use ALL competencies for calculating overall stats
|
|
748
|
+
const allCompetencies = this.planData.competencies;
|
|
749
|
+
// Filter for category-specific calculations
|
|
750
|
+
let categorySpecificCompetencies = this.planData.competencies;
|
|
751
|
+
if (this.selectedCategory === 'all') {
|
|
752
|
+
categorySpecificCompetencies = this.planData.competencies;
|
|
753
|
+
}
|
|
754
|
+
else if (this.selectedCategory === 'behavioral') {
|
|
755
|
+
categorySpecificCompetencies = this.planData.competencies.filter(item => item.type?.toLowerCase() === this.selectedCategory);
|
|
756
|
+
}
|
|
757
|
+
else if (this.selectedCategory === 'functional') {
|
|
758
|
+
categorySpecificCompetencies = this.planData.competencies.filter(item => item.type?.toLowerCase() === this.selectedCategory);
|
|
759
|
+
}
|
|
760
|
+
else if (this.selectedCategory === 'domain') {
|
|
761
|
+
categorySpecificCompetencies = this.planData.competencies.filter(item => item.type?.toLowerCase() === this.selectedCategory);
|
|
762
|
+
}
|
|
763
|
+
// Count ALL competencies by category (not just filtered ones)
|
|
764
|
+
const masterListByCategory = { total: allCompetencies.length, behavioural: 0, functional: 0, domain: 0 };
|
|
765
|
+
// IMPORTANT: Use all available courses for consistent coverage calculation
|
|
766
|
+
// This should match what's available in the Filter By Competency section
|
|
767
|
+
const allCourseCompetencies = [];
|
|
768
|
+
const allAvailableCoursesForStats = this.getAllAvailableCourses();
|
|
769
|
+
allAvailableCoursesForStats.forEach(course => {
|
|
770
|
+
// Handle different competency property names
|
|
771
|
+
let competencies = [];
|
|
772
|
+
if (course && course.competencies && Array.isArray(course.competencies)) {
|
|
773
|
+
competencies = course.competencies;
|
|
774
|
+
}
|
|
775
|
+
else if (course && course.competencies_v6 && Array.isArray(course.competencies_v6)) {
|
|
776
|
+
competencies = course.competencies_v6;
|
|
777
|
+
}
|
|
778
|
+
competencies.forEach((list) => {
|
|
779
|
+
allCourseCompetencies.push(list);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
console.log('allCompetencies', allCompetencies);
|
|
783
|
+
console.log('categorySpecificCompetencies', categorySpecificCompetencies);
|
|
784
|
+
console.log('allCourseCompetencies', allCourseCompetencies);
|
|
785
|
+
// Count all competencies by type for proper totals
|
|
786
|
+
for (let i = 0; i < allCompetencies.length; i++) {
|
|
787
|
+
const competencyType = allCompetencies[i]['type']?.toLowerCase();
|
|
788
|
+
console.log(`Competency ${i}: type="${competencyType}", data:`, allCompetencies[i]);
|
|
789
|
+
if (competencyType === 'behavioural' || competencyType === 'behavioral') {
|
|
790
|
+
masterListByCategory['behavioural'] = masterListByCategory['behavioural'] + 1;
|
|
791
|
+
}
|
|
792
|
+
if (competencyType === 'functional') {
|
|
793
|
+
masterListByCategory['functional'] = masterListByCategory['functional'] + 1;
|
|
794
|
+
}
|
|
795
|
+
if (competencyType === 'domain') {
|
|
796
|
+
masterListByCategory['domain'] = masterListByCategory['domain'] + 1;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
console.log('masterListByCategory after counting:', masterListByCategory);
|
|
800
|
+
// Get matching results for ALL competencies (for overall coverage)
|
|
801
|
+
const overallResult = this.getMatchedCompetencyStats(allCompetencies, allCourseCompetencies);
|
|
802
|
+
// Get matching results for category-specific competencies (for filtered view)
|
|
803
|
+
const categoryResult = this.getMatchedCompetencyStats(categorySpecificCompetencies, allCourseCompetencies);
|
|
804
|
+
// Set competencyCoveredCount based on selected category (for the filtered numbers)
|
|
805
|
+
if (this.selectedCategory === 'all') {
|
|
806
|
+
this.competencyCoveredCount = overallResult['total'];
|
|
807
|
+
}
|
|
808
|
+
else if (this.selectedCategory === 'behavioral') {
|
|
809
|
+
this.competencyCoveredCount = categoryResult['behavioral'] || 0;
|
|
810
|
+
}
|
|
811
|
+
else if (this.selectedCategory === 'functional') {
|
|
812
|
+
this.competencyCoveredCount = categoryResult['functional'] || 0;
|
|
813
|
+
}
|
|
814
|
+
else if (this.selectedCategory === 'domain') {
|
|
815
|
+
this.competencyCoveredCount = categoryResult['domain'] || 0;
|
|
816
|
+
}
|
|
817
|
+
// IMPORTANT: Overall Coverage should ALWAYS be based on ALL competencies, not filtered
|
|
818
|
+
let totalCompetencies = this.planData.competencies.length; // Always use total count
|
|
819
|
+
let overallCoveredCount = overallResult['total']; // Always use overall results
|
|
820
|
+
let mathRound = Math.round((overallCoveredCount / totalCompetencies) * 100);
|
|
821
|
+
this.overallCoverage = `${mathRound}%`;
|
|
822
|
+
console.log('Overall Coverage Calculation:', {
|
|
823
|
+
totalCompetencies: totalCompetencies,
|
|
824
|
+
overallCoveredCount: overallCoveredCount,
|
|
825
|
+
overallCoverage: this.overallCoverage,
|
|
826
|
+
selectedCategory: this.selectedCategory,
|
|
827
|
+
competencyCoveredCount: this.competencyCoveredCount
|
|
828
|
+
});
|
|
829
|
+
// Always calculate all category-specific metrics regardless of selected category
|
|
830
|
+
// This ensures the data is available when switching between categories
|
|
831
|
+
// Use overallResult for consistent calculations across all categories
|
|
832
|
+
this.behavioralCompetencyCoveredCount = overallResult['behavioral'] || 0;
|
|
833
|
+
this.behavioralTotalCompetencies = masterListByCategory['behavioural'];
|
|
834
|
+
let behavioralMathRound = this.behavioralTotalCompetencies > 0 ? Math.round((this.behavioralCompetencyCoveredCount / this.behavioralTotalCompetencies) * 100) : 0;
|
|
835
|
+
this.behavioralCoverage = `${behavioralMathRound}%`;
|
|
836
|
+
this.functionalCompetencyCoveredCount = overallResult['functional'] || 0;
|
|
837
|
+
this.functionalTotalCompetencies = masterListByCategory['functional'];
|
|
838
|
+
let functionalMathRound = this.functionalTotalCompetencies > 0 ? Math.round((this.functionalCompetencyCoveredCount / this.functionalTotalCompetencies) * 100) : 0;
|
|
839
|
+
this.functionalCoverage = `${functionalMathRound}%`;
|
|
840
|
+
this.domainCompetencyCoveredCount = overallResult['domain'] || 0;
|
|
841
|
+
this.domainTotalCompetencies = masterListByCategory['domain'];
|
|
842
|
+
let domainMathRound = this.domainTotalCompetencies > 0 ? Math.round((this.domainCompetencyCoveredCount / this.domainTotalCompetencies) * 100) : 0;
|
|
843
|
+
this.domainCoverage = `${domainMathRound}%`;
|
|
844
|
+
console.log('All category metrics calculated:', {
|
|
845
|
+
behavioral: { covered: this.behavioralCompetencyCoveredCount, total: this.behavioralTotalCompetencies, coverage: this.behavioralCoverage },
|
|
846
|
+
functional: { covered: this.functionalCompetencyCoveredCount, total: this.functionalTotalCompetencies, coverage: this.functionalCoverage },
|
|
847
|
+
domain: { covered: this.domainCompetencyCoveredCount, total: this.domainTotalCompetencies, coverage: this.domainCoverage },
|
|
848
|
+
overall: { covered: overallCoveredCount, total: totalCompetencies, coverage: this.overallCoverage },
|
|
849
|
+
selectedCategory: this.selectedCategory,
|
|
850
|
+
competencyCoveredCountForCategory: this.competencyCoveredCount
|
|
851
|
+
});
|
|
852
|
+
console.log('Overall Result:', overallResult);
|
|
853
|
+
console.log('Category Result:', categoryResult);
|
|
854
|
+
console.log('this.competencyNotMatchedByCategory', this.competencyNotMatchedByCategory);
|
|
855
|
+
this.behaviouralNotMatched = this.getCompetencyByCategoryNotMatching('behavioral');
|
|
856
|
+
this.functionalNotMatched = this.getCompetencyByCategoryNotMatching('functional');
|
|
857
|
+
this.domainNotMatched = this.getCompetencyByCategoryNotMatching('domain');
|
|
858
|
+
this.getBehaviouralMatched();
|
|
859
|
+
this.getFunctionalMatched();
|
|
860
|
+
this.getDomainMatched();
|
|
861
|
+
}
|
|
862
|
+
getMatchedCompetencyStats(primaryArray, secondaryArray) {
|
|
863
|
+
// Convert both arrays to ensure consistent casing
|
|
864
|
+
const counts = {
|
|
865
|
+
behavioral: 0,
|
|
866
|
+
functional: 0,
|
|
867
|
+
domain: 0,
|
|
868
|
+
total: 0
|
|
869
|
+
};
|
|
870
|
+
// Clear the competencyNotMatchedByCategory array for fresh calculation
|
|
871
|
+
this.competencyNotMatchedByCategory = [];
|
|
872
|
+
// Set to keep track of unique matches
|
|
873
|
+
const seen = new Set();
|
|
874
|
+
const matchedCompetencies = new Set();
|
|
875
|
+
for (const primary of primaryArray) {
|
|
876
|
+
const typeKey = primary.type?.toLowerCase().trim();
|
|
877
|
+
const themeKey = primary.theme?.toLowerCase().trim();
|
|
878
|
+
const subThemeKey = primary.sub_theme?.toLowerCase().trim();
|
|
879
|
+
let isMatched = false;
|
|
880
|
+
for (const secondary of secondaryArray) {
|
|
881
|
+
// Normalize secondary keys
|
|
882
|
+
let secType = secondary?.competencyAreaName?.toLowerCase().trim();
|
|
883
|
+
let secTheme = secondary?.competencyThemeName?.toLowerCase().trim();
|
|
884
|
+
let secSubTheme = secondary?.competencySubThemeName?.toLowerCase().trim();
|
|
885
|
+
// Fix for data inconsistency
|
|
886
|
+
if (secType === 'behavioural')
|
|
887
|
+
secType = 'behavioral';
|
|
888
|
+
// Create unique match key for primary competency
|
|
889
|
+
const matchKey = `${typeKey}|${themeKey}|${subThemeKey}`;
|
|
890
|
+
// Enhanced cross-matching logic as requested:
|
|
891
|
+
// 1. Role mapping Theme vs Course Theme
|
|
892
|
+
// 2. Role mapping Sub Theme vs Course Sub Theme
|
|
893
|
+
// 3. Role mapping Theme vs Course Sub Theme
|
|
894
|
+
// 4. Role mapping Sub Theme vs Course Theme
|
|
895
|
+
const themeToThemeMatch = themeKey === secTheme;
|
|
896
|
+
const subThemeToSubThemeMatch = subThemeKey === secSubTheme;
|
|
897
|
+
const themeToSubThemeMatch = themeKey === secSubTheme;
|
|
898
|
+
const subThemeToThemeMatch = subThemeKey === secTheme;
|
|
899
|
+
let matchType = '';
|
|
900
|
+
let isMatch = false;
|
|
901
|
+
if (typeKey === secType && !seen.has(matchKey)) {
|
|
902
|
+
if (themeToThemeMatch) {
|
|
903
|
+
matchType = 'Theme-to-Theme';
|
|
904
|
+
isMatch = true;
|
|
905
|
+
}
|
|
906
|
+
else if (subThemeToSubThemeMatch) {
|
|
907
|
+
matchType = 'SubTheme-to-SubTheme';
|
|
908
|
+
isMatch = true;
|
|
909
|
+
}
|
|
910
|
+
else if (themeToSubThemeMatch) {
|
|
911
|
+
matchType = 'Theme-to-SubTheme';
|
|
912
|
+
isMatch = true;
|
|
913
|
+
}
|
|
914
|
+
else if (subThemeToThemeMatch) {
|
|
915
|
+
matchType = 'SubTheme-to-Theme';
|
|
916
|
+
isMatch = true;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
if (isMatch) {
|
|
920
|
+
console.log(`✅ MATCH FOUND [${matchType}]:`, {
|
|
921
|
+
roleMapping: { type: typeKey, theme: themeKey, subTheme: subThemeKey },
|
|
922
|
+
course: { type: secType, theme: secTheme, subTheme: secSubTheme },
|
|
923
|
+
matchType: matchType
|
|
924
|
+
});
|
|
925
|
+
// Store matched competency info for later use
|
|
926
|
+
let obj = {};
|
|
927
|
+
obj[typeKey] = [themeKey]; // Store the original theme, not the course theme
|
|
928
|
+
this.competencyNotMatchedByCategory.push(obj);
|
|
929
|
+
seen.add(matchKey);
|
|
930
|
+
matchedCompetencies.add(themeKey); // Track matched themes
|
|
931
|
+
isMatched = true;
|
|
932
|
+
if (counts.hasOwnProperty(typeKey)) {
|
|
933
|
+
counts[typeKey]++;
|
|
934
|
+
}
|
|
935
|
+
else {
|
|
936
|
+
counts[typeKey] = 1;
|
|
937
|
+
}
|
|
938
|
+
counts.total++;
|
|
939
|
+
break; // Stop looking for matches for this primary competency
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return counts;
|
|
944
|
+
}
|
|
945
|
+
getCompetencyByCategoryNotMatching(categoryType) {
|
|
946
|
+
// Get all competencies for the given category from role mapping
|
|
947
|
+
let allCategoryCompetencies = [];
|
|
948
|
+
for (let i = 0; i < this.planData.competencies.length; i++) {
|
|
949
|
+
if (this.planData.competencies[i]['type']?.toLowerCase() === categoryType?.toLowerCase()) {
|
|
950
|
+
allCategoryCompetencies.push(this.planData.competencies[i]['theme']?.toLowerCase().trim());
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
// Get matched competencies for this category from courses
|
|
954
|
+
let matchedCompetencies = [];
|
|
955
|
+
for (let i = 0; i < this.competencyNotMatchedByCategory.length; i++) {
|
|
956
|
+
if (this.competencyNotMatchedByCategory[i][categoryType?.toLowerCase()]) {
|
|
957
|
+
// Extract matched themes from course competencies
|
|
958
|
+
this.competencyNotMatchedByCategory[i][categoryType?.toLowerCase()].forEach(theme => {
|
|
959
|
+
if (theme) {
|
|
960
|
+
matchedCompetencies.push(theme.toLowerCase().trim());
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
// Enhanced matching: check both theme and subtheme from courses against FRAC competencies
|
|
966
|
+
// IMPORTANT: Use all available courses for consistent coverage calculation
|
|
967
|
+
const allCoursesForMatching = this.getAllAvailableCourses();
|
|
968
|
+
allCoursesForMatching.forEach(course => {
|
|
969
|
+
// Handle different competency property names
|
|
970
|
+
let competencies = [];
|
|
971
|
+
if (course && course.competencies && Array.isArray(course.competencies)) {
|
|
972
|
+
competencies = course.competencies;
|
|
973
|
+
}
|
|
974
|
+
else if (course && course.competencies_v6 && Array.isArray(course.competencies_v6)) {
|
|
975
|
+
competencies = course.competencies_v6;
|
|
976
|
+
}
|
|
977
|
+
competencies.forEach((comp) => {
|
|
978
|
+
let secType = comp?.competencyAreaName?.toLowerCase().trim();
|
|
979
|
+
if (secType === 'behavioural')
|
|
980
|
+
secType = 'behavioral';
|
|
981
|
+
if (secType === categoryType?.toLowerCase()) {
|
|
982
|
+
const courseTheme = comp.competencyThemeName?.toLowerCase().trim();
|
|
983
|
+
const courseSubTheme = comp.competencySubThemeName?.toLowerCase().trim();
|
|
984
|
+
// Check if any FRAC competency matches this course competency
|
|
985
|
+
for (let i = 0; i < this.planData.competencies.length; i++) {
|
|
986
|
+
const fracComp = this.planData.competencies[i];
|
|
987
|
+
if (fracComp['type']?.toLowerCase() === categoryType?.toLowerCase()) {
|
|
988
|
+
const fracTheme = fracComp['theme']?.toLowerCase().trim();
|
|
989
|
+
const fracSubTheme = fracComp['sub_theme']?.toLowerCase().trim();
|
|
990
|
+
// Enhanced cross-matching logic (same as in getMatchedCompetencyStats):
|
|
991
|
+
// 1. Course Theme vs FRAC Theme
|
|
992
|
+
// 2. Course Sub Theme vs FRAC Sub Theme
|
|
993
|
+
// 3. Course Theme vs FRAC Sub Theme
|
|
994
|
+
// 4. Course Sub Theme vs FRAC Theme
|
|
995
|
+
const courseThemeToFracTheme = courseTheme === fracTheme;
|
|
996
|
+
const courseSubThemeToFracSubTheme = courseSubTheme === fracSubTheme;
|
|
997
|
+
const courseThemeToFracSubTheme = courseTheme === fracSubTheme;
|
|
998
|
+
const courseSubThemeToFracTheme = courseSubTheme === fracTheme;
|
|
999
|
+
if (courseThemeToFracTheme || courseSubThemeToFracSubTheme ||
|
|
1000
|
+
courseThemeToFracSubTheme || courseSubThemeToFracTheme) {
|
|
1001
|
+
let matchType = '';
|
|
1002
|
+
if (courseThemeToFracTheme)
|
|
1003
|
+
matchType = 'CourseTheme-to-FRACTheme';
|
|
1004
|
+
else if (courseSubThemeToFracSubTheme)
|
|
1005
|
+
matchType = 'CourseSubTheme-to-FRACSubTheme';
|
|
1006
|
+
else if (courseThemeToFracSubTheme)
|
|
1007
|
+
matchType = 'CourseTheme-to-FRACSubTheme';
|
|
1008
|
+
else if (courseSubThemeToFracTheme)
|
|
1009
|
+
matchType = 'CourseSubTheme-to-FRACTheme';
|
|
1010
|
+
console.log(`✅ COMPETENCY MATCH FOUND [${matchType}] for ${categoryType}:`, {
|
|
1011
|
+
course: { theme: courseTheme, subTheme: courseSubTheme },
|
|
1012
|
+
frac: { theme: fracTheme, subTheme: fracSubTheme },
|
|
1013
|
+
matchType: matchType
|
|
1014
|
+
});
|
|
1015
|
+
matchedCompetencies.push(fracTheme);
|
|
1016
|
+
break; // Found a match, move to next course competency
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
// Remove duplicates from matched competencies
|
|
1024
|
+
matchedCompetencies = [...new Set(matchedCompetencies)];
|
|
1025
|
+
console.log(`\n=== ${categoryType.toUpperCase()} COMPETENCY MATCHING ===`);
|
|
1026
|
+
console.log(`${categoryType} - All FRAC competencies:`, allCategoryCompetencies);
|
|
1027
|
+
console.log(`${categoryType} - Matched from courses:`, matchedCompetencies);
|
|
1028
|
+
console.log(`${categoryType} - Match rate: ${matchedCompetencies.length}/${allCategoryCompetencies.length} (${Math.round((matchedCompetencies.length / allCategoryCompetencies.length) * 100)}%)`);
|
|
1029
|
+
// Return unmatched competencies (those in role mapping but not covered by courses)
|
|
1030
|
+
return this.compareStringArrays(allCategoryCompetencies, matchedCompetencies);
|
|
1031
|
+
}
|
|
1032
|
+
compareStringArrays(arr1, arr2) {
|
|
1033
|
+
console.log('All competencies in category:', arr1);
|
|
1034
|
+
console.log('Matched competencies from courses:', arr2);
|
|
1035
|
+
// Return items in arr1 that are NOT in arr2 (unmatched competencies)
|
|
1036
|
+
const unmatched = arr1.filter(item => !arr2.includes(item));
|
|
1037
|
+
console.log('Unmatched competencies:', unmatched);
|
|
1038
|
+
return unmatched;
|
|
1039
|
+
}
|
|
1040
|
+
addCourse(missingCompetency, competencyType) {
|
|
1041
|
+
let dialogData = { ...this.planData };
|
|
1042
|
+
// If competency parameters are provided, add them to the dialog data
|
|
1043
|
+
if (missingCompetency && competencyType) {
|
|
1044
|
+
// Parse the theme from the missing competency string (assumes format "theme-subtheme" or just "theme")
|
|
1045
|
+
const theme = missingCompetency.trim();
|
|
1046
|
+
dialogData.prefillCompetency = {
|
|
1047
|
+
type: competencyType,
|
|
1048
|
+
theme: theme
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
const dialogRef = this.dialog.open(AddCourseComponent, {
|
|
1052
|
+
width: '1000px',
|
|
1053
|
+
data: dialogData,
|
|
1054
|
+
panelClass: 'view-cbp-plan-popup',
|
|
1055
|
+
minHeight: '400px',
|
|
1056
|
+
maxHeight: '90vh',
|
|
1057
|
+
disableClose: true // Optional: prevent closing with outside click
|
|
1058
|
+
});
|
|
1059
|
+
dialogRef.afterClosed().subscribe(result => {
|
|
1060
|
+
if (result === 'saved') {
|
|
1061
|
+
console.log('Course added successfully! Refreshing data...');
|
|
1062
|
+
// Refresh user courses to include the newly added course
|
|
1063
|
+
this.getUserCourse();
|
|
1064
|
+
// Refresh gap analysis with the latest data
|
|
1065
|
+
setTimeout(() => {
|
|
1066
|
+
this.updateGapAnalysisAfterCoursesUpdate();
|
|
1067
|
+
console.log('Gap analysis refreshed after course addition');
|
|
1068
|
+
}, 500); // Small delay to ensure data is loaded
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
filterOnCompetencyTheme(themeItem) {
|
|
1073
|
+
this.selectedThemeFilter = themeItem;
|
|
1074
|
+
let themeName = themeItem?.split("-")[0]?.trim();
|
|
1075
|
+
let subThemeName = themeItem?.split("-")[1]?.trim();
|
|
1076
|
+
console.log('Filtering by theme:', themeName, 'subTheme:', subThemeName, 'Tab index:', this.innerTabActiveIndex);
|
|
1077
|
+
// Get the current competency type based on the active tab
|
|
1078
|
+
let competencyType = '';
|
|
1079
|
+
if (this.innerTabActiveIndex === 1) {
|
|
1080
|
+
competencyType = 'behavioral';
|
|
1081
|
+
}
|
|
1082
|
+
else if (this.innerTabActiveIndex === 2) {
|
|
1083
|
+
competencyType = 'functional';
|
|
1084
|
+
}
|
|
1085
|
+
else if (this.innerTabActiveIndex === 3) {
|
|
1086
|
+
competencyType = 'domain';
|
|
1087
|
+
}
|
|
1088
|
+
// Get all available courses using the helper method
|
|
1089
|
+
const allAvailableCourses = this.getAllAvailableCourses();
|
|
1090
|
+
console.log('Total courses to filter from:', allAvailableCourses.length);
|
|
1091
|
+
this.filterdCourses = allAvailableCourses.filter(course => {
|
|
1092
|
+
if (!course)
|
|
1093
|
+
return false;
|
|
1094
|
+
// Handle different competency property names
|
|
1095
|
+
let competencies = [];
|
|
1096
|
+
if (course.competencies && Array.isArray(course.competencies)) {
|
|
1097
|
+
competencies = course.competencies;
|
|
1098
|
+
}
|
|
1099
|
+
else if (course.competencies_v6 && Array.isArray(course.competencies_v6)) {
|
|
1100
|
+
competencies = course.competencies_v6;
|
|
1101
|
+
}
|
|
1102
|
+
if (competencies.length === 0)
|
|
1103
|
+
return false;
|
|
1104
|
+
// Filter by competency type and theme/subtheme
|
|
1105
|
+
return competencies.some(comp => {
|
|
1106
|
+
if (!comp)
|
|
1107
|
+
return false;
|
|
1108
|
+
// Check competency type matches current tab
|
|
1109
|
+
let compType = comp?.competencyAreaName?.toLowerCase();
|
|
1110
|
+
if (compType === 'behavioural')
|
|
1111
|
+
compType = 'behavioral'; // Normalize spelling
|
|
1112
|
+
if (compType !== competencyType)
|
|
1113
|
+
return false;
|
|
1114
|
+
// Check cross-matching like gap analysis: theme vs subtheme and subtheme vs theme
|
|
1115
|
+
const compTheme = comp?.competencyThemeName?.toLowerCase()?.trim();
|
|
1116
|
+
const compSubTheme = comp?.competencySubThemeName?.toLowerCase()?.trim();
|
|
1117
|
+
const searchTheme = themeName?.toLowerCase();
|
|
1118
|
+
const searchSubTheme = subThemeName?.toLowerCase();
|
|
1119
|
+
// Enhanced cross-matching logic like gap analysis:
|
|
1120
|
+
// 1. Selected Theme vs Course Theme
|
|
1121
|
+
// 2. Selected Sub Theme vs Course Sub Theme
|
|
1122
|
+
// 3. Selected Theme vs Course Sub Theme
|
|
1123
|
+
// 4. Selected Sub Theme vs Course Theme
|
|
1124
|
+
const themeToThemeMatch = searchTheme && compTheme === searchTheme;
|
|
1125
|
+
const subThemeToSubThemeMatch = searchSubTheme && compSubTheme === searchSubTheme;
|
|
1126
|
+
const themeToSubThemeMatch = searchTheme && compSubTheme === searchTheme;
|
|
1127
|
+
const subThemeToThemeMatch = searchSubTheme && compTheme === searchSubTheme;
|
|
1128
|
+
const isMatch = themeToThemeMatch || subThemeToSubThemeMatch || themeToSubThemeMatch || subThemeToThemeMatch;
|
|
1129
|
+
// Log matches for debugging (similar to gap analysis)
|
|
1130
|
+
if (isMatch) {
|
|
1131
|
+
let matchType = '';
|
|
1132
|
+
if (themeToThemeMatch)
|
|
1133
|
+
matchType = 'Theme-to-Theme';
|
|
1134
|
+
else if (subThemeToSubThemeMatch)
|
|
1135
|
+
matchType = 'SubTheme-to-SubTheme';
|
|
1136
|
+
else if (themeToSubThemeMatch)
|
|
1137
|
+
matchType = 'Theme-to-SubTheme';
|
|
1138
|
+
else if (subThemeToThemeMatch)
|
|
1139
|
+
matchType = 'SubTheme-to-Theme';
|
|
1140
|
+
console.log(`✅ FILTER MATCH FOUND [${matchType}]:`, {
|
|
1141
|
+
selected: { theme: searchTheme, subTheme: searchSubTheme },
|
|
1142
|
+
course: { type: compType, theme: compTheme, subTheme: compSubTheme },
|
|
1143
|
+
matchType: matchType
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
// Match if any of the cross-matching conditions are met
|
|
1147
|
+
return isMatch;
|
|
1148
|
+
});
|
|
1149
|
+
});
|
|
1150
|
+
console.log('Filtered courses for theme:', themeName, 'Count:', this.filterdCourses.length);
|
|
1151
|
+
console.log('Filtered courses:', this.filterdCourses.map(c => c.name || c.course));
|
|
1152
|
+
}
|
|
1153
|
+
clearThemeFilter() {
|
|
1154
|
+
this.selectedThemeFilter = '';
|
|
1155
|
+
// Reset to category filtered courses by calling the tab change method
|
|
1156
|
+
this.onInnerTabChange({
|
|
1157
|
+
index: this.innerTabActiveIndex,
|
|
1158
|
+
tab: { textLabel: this.innerTabActiveText }
|
|
1159
|
+
});
|
|
1160
|
+
console.log('Theme filter cleared, showing all courses for category:', this.innerTabActiveText);
|
|
1161
|
+
}
|
|
1162
|
+
isThemeSelected(theme) {
|
|
1163
|
+
return this.selectedThemeFilter === theme;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Add course for the currently selected theme filter with prefilled competency data
|
|
1167
|
+
*/
|
|
1168
|
+
addCourseForSelectedTheme() {
|
|
1169
|
+
if (!this.selectedThemeFilter) {
|
|
1170
|
+
console.warn('No theme selected for adding course');
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
// Parse theme and sub-theme from selectedThemeFilter (format: "Theme - SubTheme")
|
|
1174
|
+
const themeParts = this.selectedThemeFilter.split('-');
|
|
1175
|
+
const theme = themeParts[0]?.trim();
|
|
1176
|
+
const subTheme = themeParts[1]?.trim();
|
|
1177
|
+
// Get the current competency type based on the active tab
|
|
1178
|
+
// Map the tab labels to the format expected by AddCourseComponent
|
|
1179
|
+
let competencyType = '';
|
|
1180
|
+
if (this.innerTabActiveIndex === 1) {
|
|
1181
|
+
competencyType = 'Behavioral'; // Tab label is "behavioural"
|
|
1182
|
+
}
|
|
1183
|
+
else if (this.innerTabActiveIndex === 2) {
|
|
1184
|
+
competencyType = 'Functional'; // Tab label is "functional"
|
|
1185
|
+
}
|
|
1186
|
+
else if (this.innerTabActiveIndex === 3) {
|
|
1187
|
+
competencyType = 'Domain'; // Tab label is "domain"
|
|
1188
|
+
}
|
|
1189
|
+
console.log('Tab mapping - innerTabActiveIndex:', this.innerTabActiveIndex, 'innerTabActiveText:', this.innerTabActiveText, 'mapped competencyType:', competencyType);
|
|
1190
|
+
console.log('Adding course for missing competency:', {
|
|
1191
|
+
competencyType,
|
|
1192
|
+
theme,
|
|
1193
|
+
subTheme,
|
|
1194
|
+
selectedThemeFilter: this.selectedThemeFilter
|
|
1195
|
+
});
|
|
1196
|
+
// Create dialog data with prefilled competency information
|
|
1197
|
+
let dialogData = { ...this.planData };
|
|
1198
|
+
dialogData.prefillCompetency = {
|
|
1199
|
+
type: competencyType,
|
|
1200
|
+
theme: theme,
|
|
1201
|
+
subTheme: subTheme || '' // Include sub-theme if available
|
|
1202
|
+
};
|
|
1203
|
+
const dialogRef = this.dialog.open(AddCourseComponent, {
|
|
1204
|
+
width: '800px',
|
|
1205
|
+
data: dialogData,
|
|
1206
|
+
panelClass: 'view-cbp-plan-popup',
|
|
1207
|
+
minHeight: '400px',
|
|
1208
|
+
maxHeight: '90vh',
|
|
1209
|
+
disableClose: true
|
|
1210
|
+
});
|
|
1211
|
+
dialogRef.afterClosed().subscribe(result => {
|
|
1212
|
+
if (result === 'saved') {
|
|
1213
|
+
console.log('Course added successfully for competency! Refreshing data...');
|
|
1214
|
+
// Refresh user courses to include the newly added course
|
|
1215
|
+
this.getUserCourse();
|
|
1216
|
+
// Update gap analysis after course addition
|
|
1217
|
+
this.updateGapAnalysisAfterCoursesUpdate();
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
getDuration(time) {
|
|
1222
|
+
return this.sharedService.convert(time);
|
|
1223
|
+
}
|
|
1224
|
+
getBehaviouralMatched() {
|
|
1225
|
+
this.behaviouralMatched = [];
|
|
1226
|
+
console.log('this.planData.competencies', this.planData);
|
|
1227
|
+
console.log('this.behaviouralNotMatched', this.behaviouralNotMatched);
|
|
1228
|
+
this.planData.competencies.map((item) => {
|
|
1229
|
+
if (item && item?.type === 'Behavioral' && this.behaviouralNotMatched.indexOf(item?.theme?.toLowerCase()) < 0) {
|
|
1230
|
+
this.behaviouralMatched.push(item);
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
console.log('this.behaviouralMatched--', this.behaviouralMatched);
|
|
1234
|
+
}
|
|
1235
|
+
getFunctionalMatched() {
|
|
1236
|
+
this.functionalMatched = [];
|
|
1237
|
+
this.planData.competencies.map((item) => {
|
|
1238
|
+
if (item && item?.type === 'Functional' && this.functionalNotMatched.indexOf(item?.theme?.toLowerCase()) < 0) {
|
|
1239
|
+
this.functionalMatched.push(item);
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
return this.functionalMatched;
|
|
1243
|
+
}
|
|
1244
|
+
getDomainMatched() {
|
|
1245
|
+
this.domainMatched = [];
|
|
1246
|
+
this.planData.competencies.map((item) => {
|
|
1247
|
+
if (item && item?.type === 'Domain' && this.domainNotMatched.indexOf(item?.theme?.toLowerCase()) < 0) {
|
|
1248
|
+
this.domainMatched.push(item);
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
console.log('this.domainMatched--', this.domainMatched);
|
|
1252
|
+
}
|
|
1253
|
+
downloadPDF() {
|
|
1254
|
+
this.isPDFDownload = true;
|
|
1255
|
+
this.loading = true;
|
|
1256
|
+
const element = this.pdfContent.nativeElement;
|
|
1257
|
+
// Wait for images to load
|
|
1258
|
+
const images = element.querySelectorAll('img');
|
|
1259
|
+
const promises = Array.from(images).map((img) => {
|
|
1260
|
+
if (img.complete)
|
|
1261
|
+
return Promise.resolve();
|
|
1262
|
+
return new Promise(resolve => img.onload = resolve);
|
|
1263
|
+
});
|
|
1264
|
+
Promise.all(promises).then(() => {
|
|
1265
|
+
const options = {
|
|
1266
|
+
margin: 0.20,
|
|
1267
|
+
filename: 'Gap Analysis.pdf',
|
|
1268
|
+
image: { type: 'jpeg', quality: 0.98 },
|
|
1269
|
+
html2canvas: {
|
|
1270
|
+
scale: 2,
|
|
1271
|
+
useCORS: true,
|
|
1272
|
+
scrollY: 0,
|
|
1273
|
+
},
|
|
1274
|
+
jsPDF: {
|
|
1275
|
+
unit: 'in',
|
|
1276
|
+
format: 'a4',
|
|
1277
|
+
orientation: 'portrait'
|
|
1278
|
+
},
|
|
1279
|
+
pagebreak: {
|
|
1280
|
+
mode: ['css', 'legacy'],
|
|
1281
|
+
before: '.page-break',
|
|
1282
|
+
avoid: ['.no-break']
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
html2pdf().from(element).set(options).save();
|
|
1286
|
+
setTimeout(() => {
|
|
1287
|
+
this.isPDFDownload = false;
|
|
1288
|
+
this.loading = false;
|
|
1289
|
+
}, 3000);
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
redirectToToc(item) {
|
|
1293
|
+
if (item?.public_link) {
|
|
1294
|
+
window.open(item?.public_link, '_blank');
|
|
1295
|
+
}
|
|
1296
|
+
else {
|
|
1297
|
+
let url = `https://portal.igotkarmayogi.gov.in/app/toc/${item?.identifier}/overview?`;
|
|
1298
|
+
window.open(url, '_blank');
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Initialize gap analysis stats after initial data load
|
|
1303
|
+
*/
|
|
1304
|
+
initializeGapAnalysisStats() {
|
|
1305
|
+
// Set a small timeout to ensure all async operations complete
|
|
1306
|
+
setTimeout(() => {
|
|
1307
|
+
if (this.filterdCourses && this.filterdCourses.length > 0) {
|
|
1308
|
+
this.gapAnalysisStats();
|
|
1309
|
+
}
|
|
1310
|
+
}, 100);
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Update gap analysis stats after courses are updated (like suggested courses added)
|
|
1314
|
+
*/
|
|
1315
|
+
updateGapAnalysisAfterCoursesUpdate() {
|
|
1316
|
+
// Don't modify originalData - it should remain as AI recommended courses only
|
|
1317
|
+
// The gap analysis already properly includes all course types
|
|
1318
|
+
// Recalculate gap analysis stats
|
|
1319
|
+
this.gapAnalysisStats();
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Regenerate course recommendations by deleting existing recommendations and generating new ones
|
|
1323
|
+
*/
|
|
1324
|
+
async regenerateCourseRecommendations() {
|
|
1325
|
+
if (this.isRegenerating) {
|
|
1326
|
+
return; // Prevent multiple simultaneous regenerations
|
|
1327
|
+
}
|
|
1328
|
+
try {
|
|
1329
|
+
this.isRegenerating = true;
|
|
1330
|
+
// Show confirmation dialog
|
|
1331
|
+
const confirmed = await this.showConfirmationDialog();
|
|
1332
|
+
if (!confirmed) {
|
|
1333
|
+
this.isRegenerating = false;
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
console.log('Starting course recommendation regeneration...');
|
|
1337
|
+
// Set regeneration progress state
|
|
1338
|
+
this.isRegeneratingWithProgress = true;
|
|
1339
|
+
this.dataLoaded = false; // Hide main content during regeneration
|
|
1340
|
+
// Step 1: Delete existing course recommendations
|
|
1341
|
+
await this.deleteCourseRecommendations();
|
|
1342
|
+
// Step 2: Generate new course recommendations
|
|
1343
|
+
await this.generateNewCourseRecommendations();
|
|
1344
|
+
// Step 3: Refresh the current data
|
|
1345
|
+
this.refreshComponent();
|
|
1346
|
+
console.log('Course recommendation regeneration completed successfully');
|
|
1347
|
+
// Show success message
|
|
1348
|
+
this.snackBar.open('Course recommendations regenerated successfully!', 'Close', {
|
|
1349
|
+
duration: 5000,
|
|
1350
|
+
panelClass: ['success-snackbar']
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
catch (error) {
|
|
1354
|
+
console.error('Error during course recommendation regeneration:', error);
|
|
1355
|
+
// Show error message
|
|
1356
|
+
this.snackBar.open('Failed to regenerate course recommendations. Please try again.', 'Close', {
|
|
1357
|
+
duration: 5000,
|
|
1358
|
+
panelClass: ['error-snackbar']
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
finally {
|
|
1362
|
+
this.isRegenerating = false;
|
|
1363
|
+
this.isRegeneratingWithProgress = false;
|
|
1364
|
+
this.dataLoaded = true; // Ensure main content is shown after regeneration
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Show confirmation dialog for regenerate action
|
|
1369
|
+
*/
|
|
1370
|
+
showConfirmationDialog() {
|
|
1371
|
+
return new Promise((resolve) => {
|
|
1372
|
+
// Create a custom confirmation dialog
|
|
1373
|
+
const dialogRef = this.dialog.open(RegenerateConfirmationDialog, {
|
|
1374
|
+
width: '450px',
|
|
1375
|
+
panelClass: 'regenerate-confirmation-dialog',
|
|
1376
|
+
disableClose: true
|
|
1377
|
+
});
|
|
1378
|
+
dialogRef.afterClosed().subscribe(result => {
|
|
1379
|
+
resolve(result === true);
|
|
1380
|
+
});
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
/**
|
|
1384
|
+
* Delete existing course recommendations for the current role mapping
|
|
1385
|
+
*/
|
|
1386
|
+
deleteCourseRecommendations() {
|
|
1387
|
+
return new Promise((resolve, reject) => {
|
|
1388
|
+
const roleMapId = this.planData?.id;
|
|
1389
|
+
if (!roleMapId) {
|
|
1390
|
+
reject(new Error('Role mapping ID not found'));
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
console.log('Deleting course recommendations for role mapping:', roleMapId);
|
|
1394
|
+
this.sharedService.deleteCourseRecommendations(roleMapId).subscribe({
|
|
1395
|
+
next: (response) => {
|
|
1396
|
+
console.log('Course recommendations deleted successfully:', response);
|
|
1397
|
+
resolve(response);
|
|
1398
|
+
},
|
|
1399
|
+
error: (error) => {
|
|
1400
|
+
console.error('Error deleting course recommendations:', error);
|
|
1401
|
+
reject(error);
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Generate new course recommendations during regeneration
|
|
1408
|
+
*/
|
|
1409
|
+
generateNewCourseRecommendations() {
|
|
1410
|
+
console.log('Generating new course recommendations...');
|
|
1411
|
+
return this.getRecommendedCourseForRegeneration(this.planData.id);
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* Enhanced course generation specifically for regeneration with progressive loading
|
|
1415
|
+
*/
|
|
1416
|
+
getRecommendedCourseForRegeneration(role_mapping_id) {
|
|
1417
|
+
return new Promise((resolve, reject) => {
|
|
1418
|
+
// Start the progressive loading simulation for regeneration
|
|
1419
|
+
this.startRegenerativeProgressiveLoading();
|
|
1420
|
+
// Make the actual API call
|
|
1421
|
+
// this.sharedService.getRecommendedCourse(role_mapping_id).subscribe({
|
|
1422
|
+
// next: (response) => {
|
|
1423
|
+
// // Stop progressive loading and show completion
|
|
1424
|
+
// this.isRegeneratingWithProgress = false; // This will stop the interval
|
|
1425
|
+
// this.progressPercentage = 100;
|
|
1426
|
+
// this.currentProcessingStage = 'Course recommendations regenerated successfully!';
|
|
1427
|
+
// // Clear the loading state after showing completion
|
|
1428
|
+
// setTimeout(() => {
|
|
1429
|
+
// this.currentProcessingStage = '';
|
|
1430
|
+
// this.progressPercentage = 0;
|
|
1431
|
+
// resolve(response);
|
|
1432
|
+
// }, 2000);
|
|
1433
|
+
// },
|
|
1434
|
+
// error: (error) => {
|
|
1435
|
+
// // Stop progressive loading
|
|
1436
|
+
// this.isRegeneratingWithProgress = false;
|
|
1437
|
+
// this.currentProcessingStage = '';
|
|
1438
|
+
// this.progressPercentage = 0;
|
|
1439
|
+
// // Handle specific error cases
|
|
1440
|
+
// if (error.status === 409 || error.error?.detail?.includes('already exists')) {
|
|
1441
|
+
// // Course recommendations already exist - this is normal
|
|
1442
|
+
// console.log('Course recommendations already exist, loading existing data...');
|
|
1443
|
+
// this.currentProcessingStage = 'Loading existing course recommendations...';
|
|
1444
|
+
// // Try to get existing data
|
|
1445
|
+
// this.sharedService.getRecommendedCourse(role_mapping_id).subscribe({
|
|
1446
|
+
// next: (existingResponse) => {
|
|
1447
|
+
// console.log('Successfully loaded existing course recommendations');
|
|
1448
|
+
// this.progressPercentage = 100;
|
|
1449
|
+
// this.currentProcessingStage = 'Loaded existing course recommendations successfully!';
|
|
1450
|
+
// setTimeout(() => {
|
|
1451
|
+
// this.currentProcessingStage = '';
|
|
1452
|
+
// this.progressPercentage = 0;
|
|
1453
|
+
// resolve(existingResponse);
|
|
1454
|
+
// }, 2000);
|
|
1455
|
+
// },
|
|
1456
|
+
// error: (loadError) => {
|
|
1457
|
+
// console.error('Failed to load existing course recommendations:', loadError);
|
|
1458
|
+
// this.currentProcessingStage = '';
|
|
1459
|
+
// this.progressPercentage = 0;
|
|
1460
|
+
// reject(loadError);
|
|
1461
|
+
// }
|
|
1462
|
+
// });
|
|
1463
|
+
// } else {
|
|
1464
|
+
// console.error('Error during course recommendation regeneration:', error);
|
|
1465
|
+
// reject(error);
|
|
1466
|
+
// }
|
|
1467
|
+
// }
|
|
1468
|
+
// });
|
|
1469
|
+
this.isRegeneratingWithProgress = true;
|
|
1470
|
+
this.progressPercentage = 0;
|
|
1471
|
+
this.currentProcessingStage = 'Generating course recommendations...';
|
|
1472
|
+
interval(5000)
|
|
1473
|
+
.pipe(switchMap(() => this.sharedService.getRecommendedCourse(role_mapping_id).pipe(catchError(error => {
|
|
1474
|
+
// Pass error through observable so polling logic can inspect it
|
|
1475
|
+
return of({ error });
|
|
1476
|
+
}))), tap(res => console.log("Polling result:", res)),
|
|
1477
|
+
/**
|
|
1478
|
+
* ⬇️ STOP POLLING only when:
|
|
1479
|
+
* - SUCCESS → res.status === COMPLETED
|
|
1480
|
+
* - ERROR → conflict / already exists
|
|
1481
|
+
*/
|
|
1482
|
+
takeWhile(res => {
|
|
1483
|
+
if (res?.status === 'COMPLETED')
|
|
1484
|
+
return false; // Stop
|
|
1485
|
+
if (res?.error?.status === 409)
|
|
1486
|
+
return false; // Stop
|
|
1487
|
+
if (res?.error?.error?.detail?.includes('already exists'))
|
|
1488
|
+
return false; // Stop
|
|
1489
|
+
return true; // Keep polling
|
|
1490
|
+
}, true) // include final emission
|
|
1491
|
+
)
|
|
1492
|
+
.subscribe({
|
|
1493
|
+
next: (res) => {
|
|
1494
|
+
/** -------------------------------
|
|
1495
|
+
* SUCCESS CASE (status COMPLETED)
|
|
1496
|
+
-------------------------------- */
|
|
1497
|
+
if (res?.status === 'COMPLETED') {
|
|
1498
|
+
this.isRegeneratingWithProgress = false;
|
|
1499
|
+
this.progressPercentage = 100;
|
|
1500
|
+
this.currentProcessingStage = 'Course recommendations regenerated successfully!';
|
|
1501
|
+
setTimeout(() => {
|
|
1502
|
+
this.currentProcessingStage = '';
|
|
1503
|
+
this.progressPercentage = 0;
|
|
1504
|
+
resolve(res);
|
|
1505
|
+
}, 2000);
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
/** -----------------------------------
|
|
1509
|
+
* ERROR CASE (409 / already exists)
|
|
1510
|
+
------------------------------------ */
|
|
1511
|
+
if (res?.error) {
|
|
1512
|
+
const error = res.error;
|
|
1513
|
+
if (error.status === 409 || error?.error?.detail?.includes('already exists')) {
|
|
1514
|
+
this.currentProcessingStage = 'Loading existing course recommendations...';
|
|
1515
|
+
this.sharedService.getRecommendedCourse(role_mapping_id).subscribe({
|
|
1516
|
+
next: (existingData) => {
|
|
1517
|
+
this.progressPercentage = 100;
|
|
1518
|
+
this.currentProcessingStage = 'Loaded existing course recommendations successfully!';
|
|
1519
|
+
setTimeout(() => {
|
|
1520
|
+
this.currentProcessingStage = '';
|
|
1521
|
+
this.progressPercentage = 0;
|
|
1522
|
+
resolve(existingData);
|
|
1523
|
+
}, 2000);
|
|
1524
|
+
},
|
|
1525
|
+
error: loadError => reject(loadError)
|
|
1526
|
+
});
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
/** Any other error → stop & reject */
|
|
1530
|
+
this.isRegeneratingWithProgress = false;
|
|
1531
|
+
this.currentProcessingStage = '';
|
|
1532
|
+
this.progressPercentage = 0;
|
|
1533
|
+
reject(error);
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
/** ------------------------------
|
|
1537
|
+
* STILL PROCESSING (keep polling)
|
|
1538
|
+
------------------------------- */
|
|
1539
|
+
this.progressPercentage = Math.min(this.progressPercentage + 10, 95);
|
|
1540
|
+
this.currentProcessingStage = 'Still processing course recommendations...';
|
|
1541
|
+
},
|
|
1542
|
+
error: err => reject(err)
|
|
1543
|
+
});
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
// Progressive loading methods for regeneration
|
|
1547
|
+
startRegenerativeProgressiveLoading() {
|
|
1548
|
+
this.currentProcessingStage = this.processingStages[0];
|
|
1549
|
+
this.progressPercentage = 0;
|
|
1550
|
+
this.stageStartTime = Date.now();
|
|
1551
|
+
this.simulateRegenerativeProgressiveStages();
|
|
1552
|
+
}
|
|
1553
|
+
simulateRegenerativeProgressiveStages() {
|
|
1554
|
+
let currentStageIndex = 0;
|
|
1555
|
+
const totalDuration = 60000; // 60 seconds estimated duration
|
|
1556
|
+
const stageInterval = totalDuration / this.processingStages.length;
|
|
1557
|
+
const progressInterval = setInterval(() => {
|
|
1558
|
+
// Stop if regeneration is complete
|
|
1559
|
+
if (!this.isRegeneratingWithProgress) {
|
|
1560
|
+
clearInterval(progressInterval);
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
const elapsed = Date.now() - this.stageStartTime;
|
|
1564
|
+
const currentStageProgress = (elapsed % stageInterval) / stageInterval;
|
|
1565
|
+
const stageIndex = Math.min(Math.floor(elapsed / stageInterval), this.processingStages.length - 1);
|
|
1566
|
+
// Update stage if needed
|
|
1567
|
+
if (stageIndex !== currentStageIndex && stageIndex < this.processingStages.length) {
|
|
1568
|
+
currentStageIndex = stageIndex;
|
|
1569
|
+
this.currentProcessingStage = this.processingStages[stageIndex];
|
|
1570
|
+
}
|
|
1571
|
+
// Calculate overall progress (each stage is worth ~16.67%)
|
|
1572
|
+
const baseProgress = (stageIndex / this.processingStages.length) * 100;
|
|
1573
|
+
const stageProgress = (currentStageProgress / this.processingStages.length) * 100;
|
|
1574
|
+
this.progressPercentage = Math.min(Math.round(baseProgress + stageProgress), 95);
|
|
1575
|
+
}, 1000);
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* Refresh the component data after regeneration
|
|
1579
|
+
*/
|
|
1580
|
+
refreshComponent() {
|
|
1581
|
+
console.log('Refreshing component data...');
|
|
1582
|
+
// Reset all filters and selections
|
|
1583
|
+
this.selectedThemeFilter = '';
|
|
1584
|
+
this.selectFilterCourses = [];
|
|
1585
|
+
this.filterdCourses = [];
|
|
1586
|
+
this.originalFilteredCourses = [];
|
|
1587
|
+
this.suggestedCourses = [];
|
|
1588
|
+
this.userAddedCourses = [];
|
|
1589
|
+
// Reset tab states
|
|
1590
|
+
this.innerTabActiveIndex = 0;
|
|
1591
|
+
this.outerTabActiveIndex = 0;
|
|
1592
|
+
// Call the data loading methods directly to avoid resetting dataLoaded
|
|
1593
|
+
this.loadComponentData();
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Load component data (separated from ngOnInit for reuse)
|
|
1597
|
+
*/
|
|
1598
|
+
loadComponentData() {
|
|
1599
|
+
this.getRecommendedCourseWithProgress(this.planData.id).then((res) => {
|
|
1600
|
+
console.log('res', res);
|
|
1601
|
+
this.recommended_course_id = res.id;
|
|
1602
|
+
let allCoures = [];
|
|
1603
|
+
if (res && res.filtered_courses && res.filtered_courses.length) {
|
|
1604
|
+
res?.filtered_courses.forEach((item) => {
|
|
1605
|
+
if (item?.relevancy >= 85) {
|
|
1606
|
+
allCoures.push(item);
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
this.originalData = allCoures;
|
|
1610
|
+
this.filterdCourses = allCoures;
|
|
1611
|
+
}
|
|
1612
|
+
console.log('this.filterdCourses', this.filterdCourses);
|
|
1613
|
+
this.getCourses();
|
|
1614
|
+
this.getSuggestedCourse();
|
|
1615
|
+
// Initialize gap analysis stats after courses are loaded
|
|
1616
|
+
this.initializeGapAnalysisStats();
|
|
1617
|
+
this.getUserCourse();
|
|
1618
|
+
// Mark data as loaded after all initial operations
|
|
1619
|
+
this.dataLoaded = true;
|
|
1620
|
+
}).catch((error) => {
|
|
1621
|
+
console.error('Error getting recommended courses:', error);
|
|
1622
|
+
if (error.status === 401) {
|
|
1623
|
+
console.log('Unauthorized access - user will be redirected to login');
|
|
1624
|
+
}
|
|
1625
|
+
else if (error.status !== 409) {
|
|
1626
|
+
// Don't log error for 409 (already exists) as it's handled in the method
|
|
1627
|
+
console.error('Failed to load course recommendations');
|
|
1628
|
+
}
|
|
1629
|
+
// Mark data as loaded even if there's an error to show the dialog content
|
|
1630
|
+
this.dataLoaded = true;
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
// Progressive loading methods for course generation
|
|
1634
|
+
startProgressiveLoading() {
|
|
1635
|
+
this.currentProcessingStage = this.processingStages[0];
|
|
1636
|
+
this.progressPercentage = 0;
|
|
1637
|
+
this.stageStartTime = Date.now();
|
|
1638
|
+
this.simulateProgressiveStages();
|
|
1639
|
+
}
|
|
1640
|
+
simulateProgressiveStages() {
|
|
1641
|
+
let currentStageIndex = 0;
|
|
1642
|
+
const totalDuration = 60000; // 60 seconds estimated duration
|
|
1643
|
+
const stageInterval = totalDuration / this.processingStages.length;
|
|
1644
|
+
const progressInterval = setInterval(() => {
|
|
1645
|
+
const elapsed = Date.now() - this.stageStartTime;
|
|
1646
|
+
const currentStageProgress = (elapsed % stageInterval) / stageInterval;
|
|
1647
|
+
const stageIndex = Math.min(Math.floor(elapsed / stageInterval), this.processingStages.length - 1);
|
|
1648
|
+
// Update stage if needed
|
|
1649
|
+
if (stageIndex !== currentStageIndex && stageIndex < this.processingStages.length) {
|
|
1650
|
+
currentStageIndex = stageIndex;
|
|
1651
|
+
this.currentProcessingStage = this.processingStages[stageIndex];
|
|
1652
|
+
}
|
|
1653
|
+
// Calculate overall progress (each stage is worth ~16.67%)
|
|
1654
|
+
const baseProgress = (stageIndex / this.processingStages.length) * 100;
|
|
1655
|
+
const stageProgress = (currentStageProgress / this.processingStages.length) * 100;
|
|
1656
|
+
this.progressPercentage = Math.min(Math.round(baseProgress + stageProgress), 95);
|
|
1657
|
+
// Clear interval when loading stops
|
|
1658
|
+
if (!this.loading) {
|
|
1659
|
+
clearInterval(progressInterval);
|
|
1660
|
+
this.progressPercentage = 100;
|
|
1661
|
+
this.currentProcessingStage = 'Course recommendations generated successfully!';
|
|
1662
|
+
}
|
|
1663
|
+
}, 1000);
|
|
1664
|
+
}
|
|
1665
|
+
// Enhanced course generation with progressive loading
|
|
1666
|
+
getRecommendedCourseWithProgress(role_mapping_id) {
|
|
1667
|
+
return new Promise((resolve, reject) => {
|
|
1668
|
+
this.loading = true;
|
|
1669
|
+
this.currentProcessingStage = 'Generating course recommendations...';
|
|
1670
|
+
this.progressPercentage = 30;
|
|
1671
|
+
this.startProgressiveLoading();
|
|
1672
|
+
interval(5000) // ⏱ poll every 5 seconds
|
|
1673
|
+
.pipe(tap(() => {
|
|
1674
|
+
this.currentProcessingStage = 'Processing...';
|
|
1675
|
+
}), switchMap(() => this.sharedService.getRecommendedCourse(role_mapping_id)),
|
|
1676
|
+
// Continue polling while status !== COMPLETED
|
|
1677
|
+
takeWhile((response) => response?.status !== 'COMPLETED', true), finalize(() => {
|
|
1678
|
+
this.loading = false;
|
|
1679
|
+
}))
|
|
1680
|
+
.subscribe({
|
|
1681
|
+
next: (response) => {
|
|
1682
|
+
if (response?.status === 'COMPLETED') {
|
|
1683
|
+
this.progressPercentage = 100;
|
|
1684
|
+
this.currentProcessingStage = 'Course recommendations generated successfully!';
|
|
1685
|
+
setTimeout(() => {
|
|
1686
|
+
this.currentProcessingStage = '';
|
|
1687
|
+
this.progressPercentage = 0;
|
|
1688
|
+
}, 2000);
|
|
1689
|
+
this.snackBar.open('Recommendations ready!', 'X', {
|
|
1690
|
+
duration: 3000,
|
|
1691
|
+
panelClass: ['snackbar-success']
|
|
1692
|
+
});
|
|
1693
|
+
resolve(response);
|
|
1694
|
+
}
|
|
1695
|
+
},
|
|
1696
|
+
error: (error) => {
|
|
1697
|
+
this.loading = false;
|
|
1698
|
+
this.currentProcessingStage = '';
|
|
1699
|
+
this.progressPercentage = 0;
|
|
1700
|
+
if (error.status === 409 || error.error?.detail?.includes('already exists')) {
|
|
1701
|
+
this.snackBar.open('Course recommendations already exist.', 'X', {
|
|
1702
|
+
duration: 3000,
|
|
1703
|
+
panelClass: ['snackbar-success']
|
|
1704
|
+
});
|
|
1705
|
+
resolve(null); // not a real error
|
|
1706
|
+
}
|
|
1707
|
+
else {
|
|
1708
|
+
this.snackBar.open('Failed to generate course recommendations.', 'X', {
|
|
1709
|
+
duration: 3000,
|
|
1710
|
+
panelClass: ['snackbar-error']
|
|
1711
|
+
});
|
|
1712
|
+
reject(error);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
});
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
resetFilters() {
|
|
1719
|
+
this.filterForm.reset({
|
|
1720
|
+
competency: [],
|
|
1721
|
+
rating: [],
|
|
1722
|
+
language: [],
|
|
1723
|
+
duration: [],
|
|
1724
|
+
provider: []
|
|
1725
|
+
});
|
|
1726
|
+
// Reset filtered dropdown lists
|
|
1727
|
+
this.filteredCompetency = [...this.competenciesType];
|
|
1728
|
+
this.filteredRatings = [...this.ratings];
|
|
1729
|
+
this.filteredLanguages = [...this.languages];
|
|
1730
|
+
this.filteredDurations = [...this.durations];
|
|
1731
|
+
this.filteredProviders = [...this.providers];
|
|
1732
|
+
// Reset course list
|
|
1733
|
+
this.filterdCourses = [...this.fullCourseList];
|
|
1734
|
+
// this.fullCourseList.forEach((item)=>{
|
|
1735
|
+
// if(item && item.organisation && item.organisation.length) {
|
|
1736
|
+
// if(this.filteredProviders.indexOf(item.organisation[0]) < 0) {
|
|
1737
|
+
// this.filteredProviders.push(item.organisation[0])
|
|
1738
|
+
// }
|
|
1739
|
+
// }
|
|
1740
|
+
// })
|
|
1741
|
+
this.getAllAvailableCourses();
|
|
1742
|
+
}
|
|
1743
|
+
filterList(value, type) {
|
|
1744
|
+
const search = value.toLowerCase();
|
|
1745
|
+
switch (type) {
|
|
1746
|
+
case 'competency':
|
|
1747
|
+
this.filteredCompetency = this.competenciesType.filter(v => v.toLowerCase().includes(search));
|
|
1748
|
+
break;
|
|
1749
|
+
case 'rating':
|
|
1750
|
+
this.filteredRatings = this.ratings.filter(v => v.toLowerCase().includes(search));
|
|
1751
|
+
break;
|
|
1752
|
+
case 'language':
|
|
1753
|
+
this.filteredLanguages = this.languages.filter(v => v.toLowerCase().includes(search));
|
|
1754
|
+
break;
|
|
1755
|
+
case 'duration':
|
|
1756
|
+
this.filteredDurations = this.durations.filter(v => v.toLowerCase().includes(search));
|
|
1757
|
+
break;
|
|
1758
|
+
case 'provider':
|
|
1759
|
+
this.filteredProviders = this.providers.filter(v => v.toLowerCase().includes(search));
|
|
1760
|
+
break;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
normalizeCompetency(value) {
|
|
1764
|
+
if (!value)
|
|
1765
|
+
return '';
|
|
1766
|
+
const v = value.toLowerCase();
|
|
1767
|
+
if (v === 'all')
|
|
1768
|
+
return 'all';
|
|
1769
|
+
if (v.includes('behavioural') || v.includes('behavioral'))
|
|
1770
|
+
return 'behavioral';
|
|
1771
|
+
if (v.includes('functional'))
|
|
1772
|
+
return 'functional';
|
|
1773
|
+
if (v.includes('domain'))
|
|
1774
|
+
return 'domain';
|
|
1775
|
+
return '';
|
|
1776
|
+
}
|
|
1777
|
+
applyFilters() {
|
|
1778
|
+
const { competency = [], rating = [], language = [], duration = [], provider = [] } = this.filterForm.value;
|
|
1779
|
+
console.log('this.fullCourseList--', this.fullCourseList);
|
|
1780
|
+
this.filterdCourses = this.fullCourseList.filter(course => {
|
|
1781
|
+
/* ---------------- Competency ---------------- */
|
|
1782
|
+
const courseCompetencies = [
|
|
1783
|
+
...(course.competencies || []),
|
|
1784
|
+
...(course.competencies_v6 || [])
|
|
1785
|
+
];
|
|
1786
|
+
const selectedCompetencies = competency
|
|
1787
|
+
.map((c) => this.normalizeCompetency(c))
|
|
1788
|
+
.filter(c => c !== '');
|
|
1789
|
+
const competencyMatch = selectedCompetencies.length === 0 ||
|
|
1790
|
+
selectedCompetencies.includes('all') ||
|
|
1791
|
+
courseCompetencies.some((c) => selectedCompetencies.includes(this.normalizeCompetency(c.competencyAreaName)));
|
|
1792
|
+
/* ---------------- Rating ---------------- */
|
|
1793
|
+
const ratingMatch = rating.length === 0 ||
|
|
1794
|
+
this.matchRating(course, rating);
|
|
1795
|
+
/* ---------------- Language ---------------- */
|
|
1796
|
+
const languageMatch = language.length === 0 ||
|
|
1797
|
+
language.some((l) => course.language === l ||
|
|
1798
|
+
course.language?.includes?.(l) ||
|
|
1799
|
+
course.language?.[0]?.includes?.(l));
|
|
1800
|
+
/* ---------------- Duration ---------------- */
|
|
1801
|
+
const durationMatch = duration.length === 0 ||
|
|
1802
|
+
this.matchDuration(course.duration, duration);
|
|
1803
|
+
/* ---------------- Provider ---------------- */
|
|
1804
|
+
const providerMatch = provider.length === 0 ||
|
|
1805
|
+
provider.some((p) => course.organisation?.includes(p));
|
|
1806
|
+
return (competencyMatch &&
|
|
1807
|
+
ratingMatch &&
|
|
1808
|
+
languageMatch &&
|
|
1809
|
+
durationMatch &&
|
|
1810
|
+
providerMatch);
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
matchRating(course, selectedRatings) {
|
|
1814
|
+
if (!selectedRatings || selectedRatings.length === 0) {
|
|
1815
|
+
return true; // no filter selected → match everything
|
|
1816
|
+
}
|
|
1817
|
+
let rating = null;
|
|
1818
|
+
// 1️⃣ Use avgRating if available
|
|
1819
|
+
if (course.avgRating != null && !isNaN(course.avgRating)) {
|
|
1820
|
+
rating = Number(course.avgRating);
|
|
1821
|
+
}
|
|
1822
|
+
// 2️⃣ Map relevancy if avgRating missing
|
|
1823
|
+
else if (course.relevancy != null && !isNaN(course.relevancy)) {
|
|
1824
|
+
const rel = Number(course.relevancy);
|
|
1825
|
+
if (rel >= 90)
|
|
1826
|
+
rating = 4.5;
|
|
1827
|
+
else if (rel >= 80)
|
|
1828
|
+
rating = 4.0;
|
|
1829
|
+
else if (rel >= 70)
|
|
1830
|
+
rating = 3.5;
|
|
1831
|
+
else if (rel >= 50)
|
|
1832
|
+
rating = 2.5;
|
|
1833
|
+
else
|
|
1834
|
+
rating = 1.0;
|
|
1835
|
+
}
|
|
1836
|
+
// 3️⃣ No usable rating → exclude
|
|
1837
|
+
if (rating === null)
|
|
1838
|
+
return false;
|
|
1839
|
+
// 4️⃣ Match selected rating ranges
|
|
1840
|
+
return selectedRatings.some(r => {
|
|
1841
|
+
switch (r) {
|
|
1842
|
+
case '4.5 and above': return rating >= 4.5;
|
|
1843
|
+
case '4.0 and above': return rating >= 4.0;
|
|
1844
|
+
case '3.5 and above': return rating >= 3.5;
|
|
1845
|
+
case '2.5 and above': return rating >= 2.5;
|
|
1846
|
+
case '1 and above': return rating >= 1.0;
|
|
1847
|
+
default: return false;
|
|
1848
|
+
}
|
|
1849
|
+
});
|
|
1850
|
+
}
|
|
1851
|
+
matchDuration(durationInSeconds, selectedRanges) {
|
|
1852
|
+
const hours = Number(durationInSeconds) / 3600;
|
|
1853
|
+
return selectedRanges.some(range => {
|
|
1854
|
+
switch (range) {
|
|
1855
|
+
case '< 1 Hour':
|
|
1856
|
+
return hours < 1;
|
|
1857
|
+
case '1-5 Hours':
|
|
1858
|
+
return hours >= 1 && hours <= 5;
|
|
1859
|
+
case '5+ Hours':
|
|
1860
|
+
return hours > 5;
|
|
1861
|
+
default:
|
|
1862
|
+
return true;
|
|
1863
|
+
}
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GenerateCourseRecommendationComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: i2.SharedService }, { token: i3.MatSnackBar }, { token: i1.MatDialog }, { token: i4.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1867
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: GenerateCourseRecommendationComponent, selector: "app-generate-course-recommendation", viewQueries: [{ propertyName: "pdfContent", first: true, predicate: ["pdfContent"], descendants: true }], ngImport: i0, template: "<div class=\"view-cbp-plan\">\n <div class=\"popup-container\">\n \n <!-- Initial Loading Screen (for initial load and regeneration) -->\n <div class=\"initial-loading-container\" *ngIf=\"!dataLoaded || isRegeneratingWithProgress\">\n <div class=\"loading-content\">\n <mat-spinner diameter=\"50\"></mat-spinner>\n <div class=\"loading-text mt-3\">\n <p class=\"main-message\">{{ currentProcessingStage || (isRegeneratingWithProgress ? 'Regenerating course recommendations...' : 'Loading course recommendations...') }}</p>\n <div class=\"progress-details\" *ngIf=\"progressPercentage > 0\">\n <div class=\"progress-indicator\">\n <div class=\"progress-bar-container\">\n <div class=\"progress-bar\" \n [style.width.%]=\"progressPercentage\">\n </div>\n </div>\n <small class=\"progress-text\">{{ progressPercentage }}% Complete</small>\n </div>\n <small class=\"time-estimate\">\n Real-time course generation in progress. This may take 1-2 minutes.\n </small>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Main Content -->\n <div class=\"main-content\" *ngIf=\"dataLoaded && !isRegeneratingWithProgress\">\n <div class=\"popup-header\">\n <div class=\"header-left\">\n <div class=\"heading\">Save Courses (<span>{{sharedService?.cbpPlanFinalObj?.ministry?.orgName}} <span\n *ngIf=\"planData?.designation_name \">/ {{planData?.designation_name}}</span></span>)</div>\n </div>\n <div class=\"header-actions\">\n <button class=\"regenerate-btn\" (click)=\"regenerateCourseRecommendations()\"\n [disabled]=\"isRegenerating\"\n mat-raised-button color=\"primary\">\n <mat-icon *ngIf=\"!isRegenerating\">refresh</mat-icon>\n <mat-spinner *ngIf=\"isRegenerating\" diameter=\"20\"></mat-spinner>\n <span>{{isRegenerating ? 'Regenerating...' : 'Regenerate Recommendations'}}</span>\n </button>\n <div class=\"cursor-pointer close-btn\" (click)=\"closeDialog()\">\n <mat-icon>close</mat-icon>\n </div>\n </div>\n </div>\n <div class=\"section-container mt-4\">\n <mat-tab-group (selectedTabChange)=\"onOuterTabChange($event)\">\n <!-- First Main Tab -->\n <mat-tab label=\"course recommendation\">\n <!-- Nested Tabs -->\n <!-- <mat-tab-group (selectedTabChange)=\"onInnerTabChange($event)\">\n <mat-tab label=\"all\">\n\n </mat-tab>\n <mat-tab label=\"behavioural\">\n\n </mat-tab>\n <mat-tab label=\"functional\">\n\n </mat-tab>\n <mat-tab label=\"domain\">\n\n </mat-tab>\n </mat-tab-group> -->\n </mat-tab>\n\n <!-- Second Main Tab -->\n <mat-tab label=\"gap analysis\">\n <!-- <p>Gap analysis content goes here</p> -->\n </mat-tab>\n </mat-tab-group>\n <form [formGroup]=\"filterForm\" class=\"filters-container\">\n <div class=\"role-mapping-container\"\n *ngIf=\"outerTabActiveIndex === 0 && (innerTabActiveIndex === 0 || innerTabActiveIndex === 1 || innerTabActiveIndex === 2 || innerTabActiveIndex === 3 )\">\n <div class=\"container\">\n <div class=\"section-header-improved mt-3\">\n <div class=\"search-and-buttons-container\">\n <div>\n <label>Search Courses</label>\n </div> \n <div class=\"search-container-compact\">\n <div class=\"rsearch\">\n <mat-icon class=\"search-icon\">search</mat-icon>\n <input class=\"sinput-compact\" [(ngModel)]=\"searchText\"\n (input)=\"applyFilter($event.target.value);\"\n placeholder=\"Search Courses\" type=\"text\">\n </div>\n </div>\n \n </div>\n \n\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Competency</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.competency?.length ? '' : 'Competency' }}\n </mat-label>\n \n <mat-select\n formControlName=\"competency\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Competency\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'competency')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredCompetency\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div> \n \n </div>\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Rating</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.rating?.length ? '' : 'Rating' }}\n </mat-label>\n \n <mat-select\n formControlName=\"rating\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Reatings\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'rating')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredRatings\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n \n \n \n \n </div>\n <div class=\"section-header-improved-sec-2 mt-4\">\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Language</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.language?.length ? '' : 'Language' }}\n </mat-label>\n \n <mat-select\n formControlName=\"language\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Languages\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'language')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredLanguages\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Duration</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.duration?.length ? '' : 'Duration' }}\n </mat-label>\n \n <mat-select\n formControlName=\"duration\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Duration\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'duration')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredDurations\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Provider</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.provider?.length ? '' : 'Provider' }}\n </mat-label>\n \n <mat-select\n formControlName=\"provider\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Provider\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'provider')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredProviders\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div style=\"margin-top: 45px;margin-left: 20px;\">\n <input class=\"btn-active\" type=\"button\" value=\"Reset All Filters\"\n (click)=\"resetFilters()\" />\n </div>\n </div>\n <div class=\"mt-4\">\n <div style=\"font-size:16px;font-weight:bold;color:#000\">\n Filtered Course Count : {{filterdCourses?.length}}\n </div>\n </div>\n <div class=\"mt-5 sub-heading select-all-container\" *ngIf=\"filterdCourses?.length\">\n <div style=\"margin-left: 16px;\">\n <mat-checkbox [checked]=\"false\" (change)=\"selectAllCourses($event)\">Select All\n Courses</mat-checkbox>\n </div>\n <div class=\"btn-group-compact\">\n <div>\n <input class=\"btn-active\" type=\"button\" value=\"Suggest More Course From iGOT\"\n (click)=\"suggestMoreCourses()\" />\n </div>\n <div class=\"pl-2\">\n <input [disabled]=\"selectFilterCourses?.length > 0 ? false : true\"\n [ngClass]=\"selectFilterCourses?.length > 0 ? 'btn-active' : 'btn-disable'\"\n type=\"button\" [value]=\"mode === 'add' ? 'Save Courses' : 'Update Courses'\"\n (click)=\"saveCourses()\" />\n </div>\n </div>\n </div>\n <div class=\"disclaimer-container mt-2\" *ngIf=\"filterdCourses?.length\">\n <div class=\"disclaimer-message mt-4\">\n <strong>Disclaimer:</strong> Please verify the public course URL before adding it to the plan.\n </div>\n </div>\n <div class=\"mt-2\">\n\n <div class=\"course-list-container\">\n <div\n [ngClass]=\"innerTabActiveIndex > 0 ? 'course-list-container-flex':'course-list-container-right-flex' \">\n <div *ngIf=\"innerTabActiveIndex > 0\"\n [ngClass]=\"innerTabActiveIndex > 0 ? 'left-panel':''\">\n <ng-container *ngIf=\"innerTabActiveIndex === 1\">\n <div class=\"sub-heading\">\n <p>Competencies in Behavioural</p>\n </div>\n <div class=\"theme-filter-controls mb-2\" *ngIf=\"selectedThemeFilter\">\n <button class=\"clear-filter-btn\" (click)=\"clearThemeFilter()\">\n <mat-icon>clear</mat-icon> Clear Filter\n </button>\n </div>\n <div (click)=\"filterOnCompetencyTheme(item)\"\n class=\"category-list-item cursor-pointer mt-2\"\n [ngClass]=\"{'selected-theme': isThemeSelected(item)}\"\n *ngFor=\"let item of competencyMatchedByCategory\">\n {{item}}\n </div>\n </ng-container>\n <ng-container *ngIf=\"innerTabActiveIndex === 2\">\n <div class=\"sub-heading\">\n <p>Competencies in Functional</p>\n </div>\n <div class=\"theme-filter-controls mb-2\" *ngIf=\"selectedThemeFilter\">\n <button class=\"clear-filter-btn\" (click)=\"clearThemeFilter()\">\n <mat-icon>clear</mat-icon> Clear Filter\n </button>\n </div>\n <div (click)=\"filterOnCompetencyTheme(item)\"\n class=\"category-list-item cursor-pointer mt-2\"\n [ngClass]=\"{'selected-theme': isThemeSelected(item)}\"\n *ngFor=\"let item of competencyMatchedByCategory\">\n {{item}}\n </div>\n </ng-container>\n <ng-container *ngIf=\"innerTabActiveIndex === 3\">\n <div class=\"sub-heading\">\n <p>Competencies in Domain</p>\n </div>\n <div class=\"theme-filter-controls mb-2\" *ngIf=\"selectedThemeFilter\">\n <button class=\"clear-filter-btn\" (click)=\"clearThemeFilter()\">\n <mat-icon>clear</mat-icon> Clear Filter\n </button>\n </div>\n <div (click)=\"filterOnCompetencyTheme(item)\"\n class=\"category-list-item cursor-pointer mt-2\"\n [ngClass]=\"{'selected-theme': isThemeSelected(item)}\"\n *ngFor=\"let item of competencyMatchedByCategory\">\n {{item}}\n </div>\n </ng-container>\n </div>\n <div [ngClass]=\"innerTabActiveIndex > 0 ? 'right-panel':'right-panel-flex'\">\n <!-- No Course Found Message in Right Panel -->\n <div class=\"no-course-found-container\"\n *ngIf=\"filterdCourses?.length === 0 && selectedThemeFilter\">\n <div class=\"no-course-card\">\n <div class=\"no-course-icon\">\n <mat-icon>search_off</mat-icon>\n </div>\n <div class=\"no-course-content\">\n <h4>No Courses Found</h4>\n <p>No courses found for the selected theme:\n <strong>{{selectedThemeFilter}}</strong></p>\n <p>Would you like to add a course for this competency?</p>\n <button class=\"suggest-course-btn\"\n (click)=\"addCourseForSelectedTheme()\">\n <mat-icon>add_circle</mat-icon>\n Add Course\n </button>\n </div>\n </div>\n </div>\n\n <!-- Courses List -->\n <div class=\"course-list-item\" *ngFor=\"let item of filterdCourses;let i=index\">\n\n <div class=\"course-content\">\n <div class=\"course-header\">\n <div class=\"checked-course-container\">\n <div>\n <mat-checkbox [checked]=\"checkIfCourseExists(item)\"\n (change)=\"selectedFilterCourses($event, item)\"></mat-checkbox>\n </div>\n <div class=\"ml-2\">\n <div class=\"course-pill-container\">\n <div class=\"course-pill\">\n <div class=\"course-pill-text\">\n <span><img\n src=\"assets/icons/course.svg\"></span> <span>Course</span>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n\n <!-- <div>\n <div class=\"ai-recommened-pill\">\n <div class=\"ai-recommened-pill-text\">\n <span class=\"ai-loader-icon\"><img src=\"assets/icons/ai-loader.gif\"></span>\n\n <span *ngIf=\"item?.rationale\">AI Recommended\n <span *ngIf=\"item?.is_public\"> - Public</span>\n <span *ngIf=\"!item?.is_public\"> - iGOT</span>\n </span>\n <span *ngIf=\"!item?.rationale\">Manually Suggested - iGOT</span>\n\n </div>\n </div>\n </div> -->\n <div *ngIf=\"item?.rationale && !item?.is_public\">\n <div class=\"ai-recommened-pill-green\">\n <div class=\"ai-recommened-pill-green-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n\n <span>AI Recommended - iGOT </span>\n\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.platform\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <a class=\"cursor-pointer\" [href]=\"item?.public_link\"\n target=\"_blank\"><span>Platform -\n {{item?.platform}}</span></a>\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.organisation?.length\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <span>Provider - {{item?.organisation[0]}}</span>\n </div>\n </div>\n </div>\n <div *ngIf=\"item?.rationale && item?.is_public\">\n <div class=\"ai-recommened-pill-public\">\n <div class=\"ai-recommened-pill-public-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n\n <span>AI Recommended - Public </span>\n\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.platform\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <a class=\"cursor-pointer\" [href]=\"item?.public_link\"\n target=\"_blank\"><span>Platform -\n {{item?.platform}}</span></a>\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.organisation?.length\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <span>Provider - {{item?.organisation[0]}}</span>\n </div>\n </div>\n </div>\n <div *ngIf=\"!item?.rationale\">\n <div class=\"ai-recommened-pill-gray\">\n <div class=\"ai-recommened-pill-gray-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n\n <span>Manually Suggested - iGOT </span>\n\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.platform\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <a class=\"cursor-pointer\" [href]=\"item?.public_link\"\n target=\"_blank\"><span>Platform -\n {{item?.platform}}</span></a>\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.organisation?.length\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <span>Provider - {{item?.organisation[0]}}</span>\n </div>\n </div>\n </div>\n\n </div>\n <div class=\"course-title mt-3 cursor-pointer\" (click)=\"redirectToToc(item)\">\n <span *ngIf=\"item?.course\">{{item?.course}}</span>\n <!-- <span *ngIf=\"item?.name\">{{item?.name}}****</span> -->\n <span style=\"margin-left:10px;\" (click)=\"redirectToToc(item)\"><img\n height=\"18px\" width=\"18px\"\n src=\"assets/icons/redirect.png\" /></span>\n </div>\n <div class=\"course-desc mt-2\">\n <!-- <span *ngIf=\"item?.rationale\">{{item?.rationale}}</span> -->\n <span *ngIf=\"item?.description\">{{item?.description}}</span>\n </div>\n <div class=\"mt-3\" *ngIf=\"getCompetenciesByType('Behavioural',i)?.length\">\n <div class=\"competency-sub-heading\">Behavioural Competencies</div>\n <ul class=\"competency-list mt-1\">\n <li class=\"behavioural-pill\"\n *ngFor=\"let comp of getDisplayedCompetencies('Behavioural',i)\">\n <span class=\"competency-text\"> {{ comp.competencyThemeName }} -\n {{\n comp.competencySubThemeName }} </span>\n </li>\n <li *ngIf=\"hasMoreThanTwo('Behavioural',i)\"\n class=\"show-more-competency\">\n <span class=\"show-more-link cursor-pointer\"\n (click)=\"toggleCompetencies('Behavioural',i)\">\n {{ isExpanded('Behavioural',i) ? 'Show Less' : '+' +\n getRemainingCount('Behavioural',i) + ' More' }}\n </span>\n </li>\n </ul>\n </div>\n <div class=\"mt-2\" *ngIf=\"getCompetenciesByType('Functional',i)?.length\">\n <div class=\"competency-sub-heading\">Functional Competencies</div>\n <ul class=\"competency-list mt-1\">\n <li class=\"functional-pill\"\n *ngFor=\"let comp of getDisplayedCompetencies('Functional',i)\">\n <span class=\"competency-text\"> {{ comp.competencyThemeName }} -\n {{\n comp.competencySubThemeName }} </span>\n </li>\n <li *ngIf=\"hasMoreThanTwo('Functional',i)\"\n class=\"show-more-competency\">\n <span class=\"show-more-link cursor-pointer\"\n (click)=\"toggleCompetencies('Functional',i)\">\n {{ isExpanded('Functional',i) ? 'Show Less' : '+' +\n getRemainingCount('Functional',i) + ' More' }}\n </span>\n </li>\n </ul>\n </div>\n <div class=\"mt-2\" *ngIf=\"getCompetenciesByType('Domain',i)?.length\">\n <div class=\"competency-sub-heading\">Domain Competencies</div>\n <ul class=\"competency-list mt-1\">\n <li class=\"domain-pill\"\n *ngFor=\"let comp of getDisplayedCompetencies('Domain',i)\">\n <span class=\"competency-text\"> {{ comp.competencyThemeName }} -\n {{\n comp.competencySubThemeName }} </span>\n </li>\n <li *ngIf=\"hasMoreThanTwo('Domain',i)\" class=\"show-more-competency\">\n <span class=\"show-more-link cursor-pointer\"\n (click)=\"toggleCompetencies('Domain',i)\">\n {{ isExpanded('Domain',i) ? 'Show Less' : '+' +\n getRemainingCount('Domain',i) + ' More' }}\n </span>\n </li>\n </ul>\n </div>\n\n\n </div>\n\n <!-- Relevancy and Duration section -->\n <div class=\"course-footer\" *ngIf=\"item?.relevancy\">\n <div class=\"relevancy-pill-green\">\n <div class=\"relevancy-container\">\n <div class=\"relevancy\">Relevancy</div>\n <div class=\"dash\">-</div>\n <div class=\"percentage\">{{item?.relevancy}}%</div>\n </div>\n </div>\n <div class=\"relevancy-pill-green\">\n <div class=\"relevancy-container\">\n <div class=\"relevancy\">Duration</div>\n <div class=\"dash\">-</div>\n <div class=\"percentage\">\n <span\n *ngIf=\"item?.duration\">{{getDuration(item?.duration)}}</span>\n <span *ngIf=\"!(item?.duration)\">N/A</span>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- General No Data Message (only when no theme filter is active) -->\n <div class=\"mt-2 sub-heading\" *ngIf=\"filterdCourses?.length === 0 && !selectedThemeFilter\">\n <p>No Data Found</p>\n </div>\n </div>\n </div>\n </form>\n <div class=\"role-mapping-container\" *ngIf=\"outerTabActiveIndex === 1\">\n <div id=\"gap-analysis-content\">\n\n <div class=\"download-pdf mt-4 mb-2\">\n <div>\n <input class=\"btn-active\" type=\"button\" value=\"Download\" (click)=\"downloadPDF()\" />\n </div>\n </div>\n <div>\n <!-- <div *ngIf=\"isPDFDownload\">\n <div class=\"pdf-heading\">{{sharedService?.cbpPlanFinalObj?.ministry?.name}} <span\n *ngIf=\"planData?.designation_name \">_{{planData?.designation_name}}_Gap_Analysis</span>\n </div>\n </div> -->\n <div class=\"d-flex vh-100\" [ngClass]=\"isPDFDownload ? 'mt-4':''\">\n <!-- Sidebar -->\n <div class=\"d-flex flex-column p-3 bg-light border-end\" style=\"width: 250px;\">\n <h5 class=\"mb-4\">Analyze by Category</h5>\n <button *ngFor=\"let item of menuItems\"\n class=\"btn btn-outline-primary mb-2 text-start menu-list-item\"\n [class.active]=\"selectedCategory === item.key\" (click)=\"selectCategory(item.key)\">\n {{ item.label }}\n </button>\n </div>\n\n <!-- Main Content -->\n <div class=\"flex-grow-1 p-4\">\n <div class=\"d-flex justify-content-between gap-3 \">\n <div class=\"p-3 gray-bg\">\n <div class=\"div-label sub-heading\">\n <p>Competencies Covered</p>\n </div>\n <div class=\"div-count\">{{competencyCoveredCount}}</div>\n </div>\n <div class=\"p-3 gray-bg\">\n <div class=\"div-label sub-heading\">\n <p *ngIf=\"selectedCategory === 'all'\">Total Competencies</p>\n <p *ngIf=\"selectedCategory === 'behavioral'\">Total Behavioural Competencies\n </p>\n <p *ngIf=\"selectedCategory === 'functional'\">Total Functional Competencies\n </p>\n <p *ngIf=\"selectedCategory === 'domain'\">Total Domain Competencies</p>\n </div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'all'\">\n {{this.planData?.competencies?.length}}</div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'behavioral'\">\n {{behavioralTotalCompetencies}}</div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'functional'\">\n {{functionalTotalCompetencies}}</div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'domain'\">\n {{domainTotalCompetencies}}</div>\n </div>\n <div class=\"p-3 green-bg\">\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'all'\">Overall Coverage\n </div>\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'behavioral'\">\n Behavioural Coverage</div>\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'functional'\">\n Functional Coverage</div>\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'domain'\">Domain\n Coverage</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'all'\">\n {{overallCoverage}}</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'behavioral'\">\n {{behavioralCoverage}}</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'functional'\">\n {{functionalCoverage}}</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'domain'\">\n {{domainCoverage}}</div>\n </div>\n </div>\n <div class=\"mt-4 all-category-list\" [ngSwitch]=\"selectedCategory\">\n <div *ngSwitchCase=\"'all'\">\n <h4>All Categories</h4>\n\n <!-- Show Behavioural section only if there are unmatched behavioural competencies -->\n <div class=\"mt-4\"\n *ngIf=\"behaviouralNotMatched && behaviouralNotMatched.length > 0\">\n <div class=\"sub-heading\">\n <p>Behavioural</p>\n </div>\n <div class=\"gray-bg-item\" *ngFor=\"let item of behaviouralNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item | titlecase}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Behavioral')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New\n Course</span></div>\n </div>\n </div>\n </div>\n\n <!-- Show Functional section only if there are unmatched functional competencies -->\n <div class=\"mt-4\"\n *ngIf=\"functionalNotMatched && functionalNotMatched.length > 0\">\n <div class=\"sub-heading\">\n <p>Functional</p>\n </div>\n <div class=\"gray-bg-item\" *ngFor=\"let item of functionalNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item | titlecase}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Functional')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New\n Course</span></div>\n </div>\n </div>\n </div>\n\n <!-- Show Domain section only if there are unmatched domain competencies -->\n <div class=\"mt-4\" *ngIf=\"domainNotMatched && domainNotMatched.length > 0\">\n <div class=\"sub-heading\">\n <p>Domain</p>\n </div>\n <div class=\"gray-bg-item\" *ngFor=\"let item of domainNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item | titlecase}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Domain')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New\n Course</span></div>\n </div>\n </div>\n </div>\n\n <!-- Show message when all competencies are covered -->\n <div class=\"mt-4 text-center\"\n *ngIf=\"(!behaviouralNotMatched || behaviouralNotMatched.length === 0) && \n (!functionalNotMatched || functionalNotMatched.length === 0) && \n (!domainNotMatched || domainNotMatched.length === 0)\">\n <div class=\"no-gaps-message\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <h4>Excellent! All competencies are covered</h4>\n <p>All required competencies have been addressed by the selected\n courses.</p>\n </div>\n </div>\n\n </div>\n\n <div *ngSwitchCase=\"'behavioral'\">\n <h4>Behavioural</h4>\n <div class=\"mt-4\" *ngIf=\"behavioralCoverage !== '100%'\">\n <!-- <div class=\"sub-heading\">\n <p>Behavioural</p>\n </div> -->\n <div class=\"gray-bg-item\" *ngFor=\"let item of behaviouralNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Behavioral')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New Course </span></div>\n </div>\n </div>\n </div>\n <div class=\"mt-4\" *ngIf=\"behavioralCoverage === '100%'\">\n <div class=\"p-3\"\n style=\"background-color: #e8f5e8; border: 1px solid #4caf50; border-radius: 8px; text-align: center;\">\n <div style=\"color: #2e7d32; font-weight: 600; font-size: 16px;\">\n \uD83C\uDF89 Excellent! All behavioral competencies are covered by the\n selected courses.\n </div>\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"'functional'\">\n <h4>Functional</h4>\n <div class=\"mt-4\" *ngIf=\"functionalCoverage !== '100%'\">\n <!-- <div class=\"sub-heading\">\n <p>Functional</p>\n </div> -->\n <div class=\"gray-bg-item\" *ngFor=\"let item of functionalNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Functional')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New Course</span></div>\n </div>\n </div>\n </div>\n <div class=\"mt-4\" *ngIf=\"functionalCoverage === '100%'\">\n <div class=\"p-3\"\n style=\"background-color: #e8f5e8; border: 1px solid #4caf50; border-radius: 8px; text-align: center;\">\n <div style=\"color: #2e7d32; font-weight: 600; font-size: 16px;\">\n \uD83C\uDF89 Excellent! All functional competencies are covered by the\n selected courses.\n </div>\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"'domain'\">\n <h4>Domain</h4>\n <div class=\"mt-4\" *ngIf=\"domainCoverage !== '100%'\">\n <!-- <div class=\"sub-heading\">\n <p>Domain</p>\n </div> -->\n <div class=\"gray-bg-item\" *ngFor=\"let item of domainNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Domain')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New Course </span></div>\n </div>\n </div>\n </div>\n <div class=\"mt-4\" *ngIf=\"domainCoverage === '100%'\">\n <div class=\"p-3\"\n style=\"background-color: #e8f5e8; border: 1px solid #4caf50; border-radius: 8px; text-align: center;\">\n <div style=\"color: #2e7d32; font-weight: 600; font-size: 16px;\">\n \uD83C\uDF89 Excellent! All domain competencies are covered by the selected\n courses.\n </div>\n </div>\n </div>\n </div>\n\n <div *ngSwitchDefault>\n <p>Please select a category.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n </div> <!-- Close main-content div -->\n\n </div>\n</div>\n\n\n<div [hidden]=\"!isPDFDownload\" class=\"gap-analysis-pdf-container\" #pdfContent>\n <div class=\"gap-analysis-pdf-header\">\n <img src=\"assets/icons/karmayogiLogo-min.png\" alt=\"Karmayogi Bharat Logo\" class=\"logo\" />\n <h1><span>\n <span *ngIf=\"sharedService?.cbpPlanFinalObj?.ministry?.sbOrgType === 'state'\">{{sharedService?.cbpPlanFinalObj?.department_name?.name}}</span> \n <span *ngIf=\"sharedService?.cbpPlanFinalObj?.ministry?.sbOrgType === 'ministry'\">{{sharedService?.cbpPlanFinalObj?.ministry?.name}}</span> \n <span *ngIf=\"planData?.designation_name \">/ {{planData?.designation_name}}</span>\n </span></h1>\n <p class=\"subtitle\">A detailed breakdown of competencies Gap Analysis</p>\n \n </div>\n \n <div class=\"competency-snapshot\">\n <h2>Competency Snapshot</h2>\n <div class=\"snapshot-content\">\n <div class=\"circle-wrapper\">\n <svg class=\"progress-ring\" width=\"120\" height=\"120\">\n <circle class=\"progress-ring-bg\" cx=\"60\" cy=\"60\" r=\"52\" />\n <circle class=\"progress-ring-circle\" cx=\"60\" cy=\"60\" r=\"52\" />\n </svg>\n <div class=\"percentage-text\">{{overallCoverage}}<br /><span>Overall Coverage</span></div>\n </div>\n \n <div class=\"competency-container\">\n <!-- Total Competencies Box -->\n <div class=\"total-box\">\n <div class=\"title\">Total Competencies</div>\n <div class=\"count\">{{this.planData?.competencies?.length}}</div>\n </div>\n \n <!-- Progress Bars -->\n <div class=\"progress-group\">\n <div class=\"progress-label\">\n <span class=\"label-text behavioral\">Behavioural</span>\n <span class=\"covered-text\">{{behavioralCompetencyCoveredCount}} / {{behavioralTotalCompetencies}} Covered</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill behavioral\" [style.width.%]=\"(behavioralCompetencyCoveredCount / behavioralTotalCompetencies) * 100\"></div>\n </div>\n </div>\n \n <div class=\"progress-group\">\n <div class=\"progress-label\">\n <span class=\"label-text functional\">Functional</span>\n <span class=\"covered-text\">{{functionalCompetencyCoveredCount}} / {{functionalTotalCompetencies}} Covered</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill functional\" [style.width.%]=\"(functionalCompetencyCoveredCount / functionalTotalCompetencies) * 100\"></div>\n </div>\n </div>\n \n <div class=\"progress-group\">\n <div class=\"progress-label\">\n <span class=\"label-text domain\">Domain</span>\n <span class=\"covered-text\">{{domainCompetencyCoveredCount}} / {{domainTotalCompetencies}} Covered</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill domain\" [style.width.%]=\"(domainCompetencyCoveredCount / domainTotalCompetencies) * 100\"></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <div class=\"gap-section mb-4\">\n <h2>Detailed Competency Analysis</h2>\n <div class=\"gap-box\">\n Bridge Your Competencies Gap\n <p class=\"subtitle\">Here are {{this.planData?.competencies?.length - (behavioralCompetencyCoveredCount + functionalCompetencyCoveredCount + domainCompetencyCoveredCount)}} key areas for development.</p>\n </div>\n </div>\n <div class=\"sub-heading mb-4\">\n <p>Gap to Address <span *ngIf=\"(this.planData?.competencies?.length - (behavioralCompetencyCoveredCount + functionalCompetencyCoveredCount + domainCompetencyCoveredCount)) > 0\">({{this.planData?.competencies?.length - (behavioralCompetencyCoveredCount + functionalCompetencyCoveredCount + domainCompetencyCoveredCount)}})</span></p>\n \n </div>\n <div class=\"competency-card behavioral\" *ngFor=\"let item of behaviouralNotMatched\">\n <div class=\"title\">{{item | titlecase}}</div>\n <div class=\"subtitle\">\n \u2022 \n <span class=\"tag behavioral\">Behavioural</span>\n </div>\n </div>\n \n <div class=\"competency-card functional\" *ngFor=\"let item of functionalNotMatched\">\n <div class=\"title\">{{item | titlecase}}</div>\n <div class=\"subtitle\">\n \u2022 \n <span class=\"tag functional\">Functional</span>\n </div>\n </div>\n \n <div class=\"competency-card domain\" *ngFor=\"let item of domainNotMatched\">\n <div class=\"title\">{{item | titlecase}}</div>\n <div class=\"subtitle\">\n <!-- Project Management -->\n \u2022 \n <span class=\"tag domain\">Domain</span>\n </div>\n </div>\n <div class=\"sub-heading mb-4\">\n <p>Covered Competencies <span>({{this.planData?.competencies?.length - (behaviouralNotMatched?.length + functionalNotMatched?.length + domainNotMatched?.length)}})</span></p> \n </div>\n <div class=\"gap-section mb-4\">\n \n <div class=\"green-bg\">\n <div class=\"div-green-label mb-2\">\n Congratulations!\n </div> \n <p>You have successfully covered </p>\n <p class=\"subtitle\">{{this.planData?.competencies?.length - (behaviouralNotMatched?.length + functionalNotMatched?.length + domainNotMatched?.length)}} key competencies, forming a strong professional foundation.</p>\n </div>\n </div>\n <div class=\"competency-card behavioral\" *ngFor=\"let item of behaviouralMatched\">\n <div class=\"title\">{{item?.theme | titlecase}}</div>\n <div class=\"subtitle\">\n {{item?.sub_theme}} \u2022 \n <span class=\"tag behavioral\">Behavioural</span>\n </div>\n </div>\n \n <div class=\"competency-card functional\" *ngFor=\"let item of functionalMatched\">\n <div class=\"title\">{{item?.theme | titlecase}}</div>\n <div class=\"subtitle\">\n {{item?.sub_theme}} \u2022 \n <span class=\"tag functional\">Functional</span>\n </div>\n </div>\n \n <div class=\"competency-card domain\" *ngFor=\"let item of domainMatched\">\n <div class=\"title\">{{item?.theme | titlecase}}</div>\n <div class=\"subtitle\">\n <!-- Project Management -->\n {{item?.sub_theme}} \u2022 \n <span class=\"tag domain\">Domain</span>\n </div>\n </div>\n <div class=\"gap-section mb-4\">\n <h2>Recommended Courses</h2>\n </div>\n <app-gap-analysis-recommended-course [planData]=\"planData\"></app-gap-analysis-recommended-course>\n</div>\n \n\n\n<div class=\"overlay-loader\" *ngIf=\"loading && dataLoaded && !isRegeneratingWithProgress\">\n <div class=\"loading-content\">\n <mat-spinner diameter=\"50\"></mat-spinner>\n <div class=\"loading-text mt-3\">\n <p class=\"main-message\">{{ currentProcessingStage || 'Preparing course recommendation generation...' }}</p>\n <div class=\"progress-details\">\n <div class=\"progress-indicator\" *ngIf=\"progressPercentage > 0\">\n <div class=\"progress-bar-container\">\n <div class=\"progress-bar\" \n [style.width.%]=\"progressPercentage\">\n </div>\n </div>\n <small class=\"progress-text\">{{ progressPercentage }}% Complete</small>\n </div>\n <small class=\"time-estimate\">\n Real-time course generation in progress. This may take 1-2 minutes.\n </small>\n </div>\n </div>\n </div>\n</div>", styles: ["@charset \"UTF-8\";.container{margin:10px auto}.sub-heading p{color:#000;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal}.radio-label{color:#000;font-family:Lato;font-size:16px;font-style:normal;font-weight:400;line-height:normal}.radio-btn-group{display:flex;width:32px;height:32px;padding:2px;gap:10px}.label{color:var(--Body-Text-Body-Color, #212529);font-family:Lato;font-size:16px;font-style:normal;font-weight:700;line-height:150%}::ng-deep mat-form-field{background-color:#fff!important;border-radius:25px!important;padding-left:12px;padding-right:12px;height:42px;width:100%}::ng-deep mat-select{border-radius:25px!important;background-color:#fff!important}::ng-deep .mat-select-panel{background-color:#fff!important}::ng-deep .mat-select-panel .mat-option{border-radius:0!important}::ng-deep mat-form-field .mat-form-field-underline{display:none!important}::ng-deep mat-select .mat-select-placeholder{color:#0006;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal}::ng-deep mat-select .mat-select-value-text{color:#000;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal;line-height:normal!important;padding-top:0!important;padding-bottom:0!important}::ng-deep mat-select .mat-select-value{display:flex!important;align-items:center!important;height:100%!important}.additional-details textarea{display:flex;padding:16px 16px 0;flex-direction:column;align-items:flex-start;gap:10px;flex:1 0 0;align-self:stretch;width:100%;color:#000;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal;resize:none}.section-header{display:flex;flex-direction:row;align-items:center;justify-content:space-between}.btn-disable{border-radius:var(--Radius-Full-Round, 9999999px);opacity:.4;background:var(--Primary-KB-Primary-Light, #1B4CA1);color:var(--white-kb-white-100, #FFF);text-align:center;font-family:Lato;font-size:14px;font-style:normal;font-weight:700;line-height:normal;display:flex;height:32px;padding:0 16px;justify-content:center;align-items:center;gap:8px;border:none}.btn-group{display:flex;flex-direction:row;justify-content:space-between}.pl-2{padding-left:5px}.search-filter-section{display:flex;flex-direction:row;justify-content:space-between}.search .rsearch{position:relative}.search .search-icon{position:absolute;top:15px;font-size:20px;left:10px}.search .sinput{border-radius:32px;border:1px solid #d5d0d0;padding:15px 36px;font:400 14px Lato;width:800px}.select-map-route-container{display:flex;flex-direction:row}.selected-mapping-route p{color:#1b4ca1;font-family:Lato;font-size:20px;font-style:normal;font-weight:400;line-height:normal;text-decoration-line:underline;text-decoration-style:solid;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;text-decoration-thickness:auto;text-underline-offset:auto;text-underline-position:from-font}.edit-plan{display:flex;padding:4px;justify-content:center;align-items:center;gap:8px;border-radius:4px;background:#1b4ca129;color:#1b4ca1;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal;margin-left:10px}.search-container{display:flex;flex-direction:row}.course-container{display:flex;width:100%;padding:16px;flex-direction:column;align-items:flex-start;gap:24px;grid-row:2/span 1;grid-column:1/span 1;border-radius:12px;border:1px solid var(--borders-black-border-16-black, rgba(0, 0, 0, .16));background:#fff}.course-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;width:100%;gap:8px}.course-pill{display:flex;height:24px;padding:8px;align-items:center;gap:4px;border-radius:16px;border:1px solid var(--borders-border-fill-focussed-4-light-100, #EF951E);background:#fefaf4}.ai-recommened-pill-green{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#0080001c}.ai-recommened-pill-green-text{color:#006400;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-public{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#1b4ca129}.ai-recommened-pill-public-text{color:#1b4ca1;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-gray{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#d3d3d3}.ai-recommened-pill-gray-text{color:#000;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-orange{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#ffa50052}.ai-recommened-pill-orange-text{color:#5a3f0d;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-orange-text a{color:#5a3f0d!important;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.igot-platform-pill{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);border:1px solid #EF951E;background:#ef951e29}.course-title{color:var(--Primary-KB-Primary-Light, #1B4CA1);font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:22px}.course-desc{color:#0009;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:1.4;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.relevancy,.competencies-matched{color:#6c757d;font-family:Lato;font-size:12px;font-style:normal;font-weight:500;line-height:normal;align-items:center}.percentage{color:#1b4ca1;font-family:Lato;font-size:14px;font-style:normal;font-weight:600;line-height:normal}.relevancy-container,.competencies-matched-container{display:flex;flex-direction:row;align-items:center}.dash{padding:0 5px}::ng-deep .mat-radio-checked .mat-radio-inner-circle{background:#1b4ca1!important}.course-list-container{display:flex;flex-wrap:wrap;gap:16px;width:100%;padding:1rem}.course-list-item{flex:1 1 calc(50% - 10px);min-width:350px;max-width:500px;box-sizing:border-box;border:1px solid #e0e0e0;padding:16px;background-color:#fff;border-radius:12px;min-height:auto;box-shadow:0 2px 4px #0000001a;transition:box-shadow .2s ease;display:flex;flex-direction:column}.course-list-item:hover{box-shadow:0 4px 8px #00000026}.course-list-item:only-child{flex:1 1 auto;max-width:800px}.checked-course-container{display:flex;width:60%}.ml-2{margin-left:8px}::ng-deep .mat-checkbox-checked .mat-checkbox-background{background:#1b4ca1!important}.igot-platform-pill-text{color:#1b4ca1;font-family:Lato;font-size:12px;font-style:normal;font-weight:700;line-height:normal}.course-pill-text{color:var(--accessbility-shades-without-opacity-kb-greys-black-87, #212121);text-align:center;font-family:Poppins;font-size:12px;font-style:normal;font-weight:400;line-height:normal}.ai-loader-icon img,.igot-platform-icon img{width:15.714px;height:15.714px;flex-shrink:0}.competency-container{display:flex;justify-content:space-between;flex-direction:row}.outside-layer-total{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #1B4CA1;background:#edf1f8;width:132px}.outside-layer-functional{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #E24577;background:#f8d2de;width:132px}.outside-layer-domain{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #7B47A4;background:#dfd3e9;width:132px}.outside-layer-behavioral{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #F8B861;background:#fde8cc;width:132px}.inside-layer{color:#1b4ca1;font-family:Lato;font-size:12px;font-style:normal;font-weight:400;line-height:normal}.count{color:#1b4ca1;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal}.suggest-courses-header{display:flex;flex-direction:row;justify-content:space-between}.suggest-course-control{display:flex;flex-direction:row}.course-card-container{width:172px;border-radius:3.307px;border:.827px solid var(--borders-border-8-black, rgba(0, 0, 0, .08));background-color:#fff}.highlight-ai{font-family:Montserrat;font-size:24px;font-style:normal;font-weight:600;line-height:normal;background:linear-gradient(90deg,#3b27ff,#2de3d6);background-clip:text;-webkit-background-clip:text;color:transparent;-webkit-text-fill-color:transparent;display:inline-block}.ai-loader-icon-medium img{width:40px;height:40px;flex-shrink:0}.heading{color:#000;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal;margin:10px 0}.pdf-heading{color:#000;font-family:Montserrat;font-size:18px;font-style:normal;font-weight:600;line-height:normal;margin:10px 0;text-align:center}.popup-header{display:flex;justify-content:space-between;align-items:center;padding:16px;border-bottom:1px solid #e0e0e0}.header-left{flex:1}.header-actions{display:flex;align-items:center;gap:12px}.regenerate-btn{display:flex;align-items:center;gap:8px;padding:8px 16px;border-radius:6px;font-size:14px;font-weight:500;min-width:auto}.regenerate-btn .mat-icon{margin:0;font-size:18px;width:18px;height:18px}.regenerate-btn .mat-spinner{margin:0}.regenerate-btn:disabled{opacity:.7;cursor:not-allowed}.close-btn{padding:8px;border-radius:4px;transition:background-color .2s ease}.close-btn:hover{background-color:#f5f5f5}.close-btn .mat-icon{font-size:20px;width:20px;height:20px}.progress-popup{display:flex;flex-direction:column;justify-content:center;align-items:center}.progress-popup .desc{color:#000000de;text-align:center;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal}.behavioural-pill{display:flex;padding:2px 6px;justify-content:center;align-items:center;gap:4px;border-radius:16px;border:1px solid #F8B861;background:linear-gradient(0deg,#f8b86152 0% 100%),#fff;margin:2px 4px 2px 0;font-size:12px}.functional-pill{display:flex;padding:2px 6px;justify-content:center;align-items:center;gap:4px;border-radius:16px;border:1px solid #E24577;background:linear-gradient(0deg,#e245773d 0% 100%),#fff;margin:2px 4px 2px 0;font-size:12px}.domain-pill{display:flex;padding:2px 6px;justify-content:center;align-items:center;gap:4px;border-radius:16px;border:1px solid #7B47A4;background:linear-gradient(0deg,#7b47a43d 0% 100%),#fff;margin:2px 4px 2px 0;font-size:12px}.popup-header{display:flex;flex-direction:row;justify-content:space-between}.popup-footer{display:flex;flex-direction:row;justify-content:end}.view-cbp-plan{margin:10px;padding:10px}.view-cbp-plan-popup{padding:24px;max-height:70vh;overflow-y:auto}.section{border-radius:8px;background:#1b4ca114;padding:16px}.popup-header{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #ddd;font-weight:700;flex-shrink:0}.popup-footer{display:flex;justify-content:flex-end;gap:16px;padding:16px 24px;border-top:1px solid #ddd;background-color:#fff;flex-shrink:0;position:sticky;bottom:0}.section-container{overflow-y:auto;flex:1 1 auto}.competency-list{display:flex;flex-direction:row;gap:0px;flex-wrap:wrap;margin:0;padding:0;list-style:none}.competency-text{color:#000;font-family:Lato;font-size:12px;font-style:normal;font-weight:400;line-height:normal;padding:3px 6px}.competency-text-behavioral{color:#654321;font-family:Lato;font-size:14px;font-style:normal;line-height:normal;font-weight:550}.competency-text-functional{color:#b01669;font-family:Lato;font-size:14px;font-style:normal;line-height:normal;font-weight:550}.competency-text-domain{color:#301934;font-family:Lato;font-size:14px;font-style:normal;line-height:normal;font-weight:550}.competency-sub-heading{color:#1b4ca1;font-family:Montserrat;font-size:14px;font-style:normal;font-weight:600;line-height:normal}.cursor-pointer{cursor:pointer}.btn-active{border-radius:var(--Radius-Full-Round, 9999999px);opacity:1;background:var(--Primary-KB-Primary-Light, #1B4CA1);color:var(--white-kb-white-100, #FFF);text-align:center;font-family:Lato;font-size:14px;font-style:normal;font-weight:700;line-height:normal;display:flex;height:32px;padding:0 16px;justify-content:center;align-items:center;gap:8px;border:none}.custom-textarea{color:#000;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal}.initial-loading-container{display:flex;justify-content:center;align-items:center;min-height:400px;width:100%}.initial-loading-container .loading-content{display:flex;flex-direction:column;align-items:center;text-align:center;padding:3rem 2rem}.initial-loading-container .loading-content .loading-text{color:#1b4ca1;font-family:Lato,sans-serif;min-width:320px}.initial-loading-container .loading-content .loading-text .main-message{font-size:16px;font-weight:600;margin-bottom:1rem;color:#1b4ca1}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator{margin-bottom:.5rem}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container{width:300px;height:8px;background-color:#e0e0e0;border-radius:4px;overflow:hidden;margin-bottom:.5rem}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container .progress-bar{height:100%;background:linear-gradient(90deg,#1b4ca1,#4caf50);border-radius:4px;transition:width .3s ease-in-out}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator .progress-text{font-size:12px;color:#666;font-weight:500}.initial-loading-container .loading-content .loading-text .progress-details .time-estimate{font-size:12px;color:#888;font-style:italic}.overlay-loader{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#ffffffbf;z-index:9999;display:flex;justify-content:center;align-items:center}.overlay-loader .loading-content{display:flex;flex-direction:column;align-items:center;text-align:center;background:#fff;padding:2rem;border-radius:8px;box-shadow:0 4px 12px #00000026}.overlay-loader .loading-content .loading-text{color:#1b4ca1;font-family:Lato,sans-serif;min-width:320px}.overlay-loader .loading-content .loading-text .main-message{margin:0 0 16px;font-size:18px;font-weight:600;text-align:center}.overlay-loader .loading-content .loading-text .progress-details{margin-top:16px}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator{margin-bottom:12px}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container{width:100%;height:8px;background-color:#e0e0e0;border-radius:4px;overflow:hidden;margin-bottom:8px}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container .progress-bar{height:100%;background:linear-gradient(90deg,#1b4ca1,#2563eb);border-radius:4px;transition:width .5s ease-in-out}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator .progress-text{font-size:14px;font-weight:500;color:#1b4ca1;display:block;text-align:center}.overlay-loader .loading-content .loading-text .progress-details .time-estimate{color:#666;font-size:12px;font-style:italic;display:block;text-align:center;margin-top:8px}.competencis-grid{display:flex;flex-direction:row;justify-content:space-between;gap:16px}.grid-list-item-behavioral div{border-left:2px solid darkorange}.grid-list-item-functional div{border-left:2px solid #ff1493}.grid-list-item-domain div{border-left:2px solid #6b21a8}.competencies-grid-3{width:33%}.bg-blue-50{background-color:#fde8cc;border-radius:4px}.bg-green-50{background-color:#f8d2de;border-radius:4px}.bg-purple-50{background-color:#dfd3e9;border-radius:4px}.grid-list-item div{padding:5px 10px;margin:10px 0}.course-pill-container{display:flex;gap:8px}.relevancy-pill-green{display:flex;padding:4px 8px;align-items:center;gap:4px;border-radius:16px;border:1px solid #e0e0e0;background:#f8f9fa}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.show-more-competency{display:inline-flex;align-items:center}.show-more-link{color:#1b4ca1;font-family:Lato;font-size:12px;font-style:normal;font-weight:500;line-height:normal;margin:2px 4px 2px 0;text-decoration:none}.show-more-link:hover{text-decoration:underline}.course-content{flex:1;display:flex;flex-direction:column}.course-footer{margin-top:auto;padding-top:12px;display:flex;justify-content:space-between}::ng-deep .mdc-tab__text-label{font-weight:700;font-family:Montserrat!important;font-size:16px;color:#000!important;text-transform:capitalize}.competency-tag{display:inline-block;padding:.25rem .75rem;border-radius:9999px;font-size:.75rem;font-weight:500;margin-right:.5rem;margin-bottom:.5rem}.menu-list-item.active{background-color:#1b4ca1;color:#fff}.menu-list-item:hover{background-color:#1b4ca1;color:#fff;border-color:#1b4ca1}.gray-bg{background-color:rgb(248,250,252,var(--tw-bg-opacity, 1));border-radius:8px;border:1px solid #ccc}.div-count{font-family:Lato;font-size:20px;font-weight:700}.green-bg{background-color:#0080001c;border:1px solid #006400;border-radius:8px}.div-green-count{font-family:Lato;font-size:20px;font-weight:700;color:#006400}.div-green-label{color:#006400;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal}.gray-bg-item{background-color:rgb(248,250,252,var(--tw-bg-opacity, 1));border-radius:8px;border:1px solid #ccc;padding:4px 8px;margin:10px}.add-btn{color:#1b4ca1;font-size:14px;font-family:Lato}.list-flex{display:flex;flex-direction:row;justify-content:space-between}.all-category-list .mat-icon{vertical-align:middle}.course-list-container-flex{display:flex;align-items:flex-start;gap:2rem}.left-panel{flex:0 0 250px;font-weight:700;text-align:left}.right-panel{flex:1;display:flex;flex-direction:row;flex-wrap:wrap;gap:20px;align-content:flex-start;justify-content:flex-start}.category-list-item{font-weight:400;font-size:16px;font-family:Lato;padding:5px}.right-panel-flex{display:flex;flex:0 0 100%;width:100%;flex-direction:row;flex-wrap:wrap;gap:20px;justify-content:flex-start}.course-list-container-right-flex{display:flex}.no-gaps-message{display:flex;flex-direction:column;align-items:center;padding:24px;background:linear-gradient(135deg,#4caf501a,#81c7841a);border:2px solid #4CAF50;border-radius:16px;margin:16px 0}.no-gaps-message .success-icon{font-size:25px;color:#4caf50;margin-bottom:16px}.no-gaps-message h4{color:#2e7d32;font-family:Montserrat;font-size:20px;font-weight:600;margin:0 0 8px;text-align:center}.no-gaps-message p{color:#388e3c;font-family:Lato;font-size:14px;font-weight:400;margin:0;text-align:center;line-height:1.5}.section-header-improved,.section-header-improved-sec-2{display:flex;flex-direction:row;gap:0px;width:100%}.search-and-buttons-container{display:flex;justify-content:space-between;gap:5px;flex-direction:column;flex-wrap:wrap;width:37%;margin:0 5px}.search-container-compact{flex:0 0 auto;min-width:180px}.search-container-compact .rsearch{position:relative;display:flex;align-items:center}.search-container-compact .search-icon{position:absolute;left:12px;color:#666;font-size:20px;z-index:1}.search-container-compact .sinput-compact{border-radius:25px;border:2px solid #ccc;padding:20px 12px 20px 40px;height:32px;width:100%;font:400 14px Lato;box-sizing:border-box;transition:border-color .3s ease}.search-container-compact .sinput-compact:focus{outline:none;border-color:#1b4ca1;box-shadow:0 0 0 2px #1b4ca11a}.search-container-compact .sinput-compact::placeholder{color:#999}.btn-group-compact{display:flex;gap:8px;flex:0 0 auto}.category-list-item{padding:8px 12px!important;border-radius:6px;border:1px solid transparent;transition:all .3s ease;background:#f8f9fa;color:#333;font-family:Lato;font-size:14px!important;font-weight:400!important}.category-list-item:hover{background:#1b4ca10d;border-color:#1b4ca133}.category-list-item.selected-theme{background:#1b4ca11a;border-color:#1b4ca1;color:#1b4ca1;font-weight:600!important}.category-list-item.selected-theme:before{content:\"\\2713 \";color:#1b4ca1;font-weight:700}.theme-filter-controls{margin-bottom:8px}.clear-filter-btn{background:#f8f9fa;border:1px solid #ddd;border-radius:20px;padding:4px 12px;font-size:12px;color:#666;cursor:pointer;transition:all .3s ease;display:flex;align-items:center;gap:4px}.clear-filter-btn:hover{background:#e9ecef;border-color:#adb5bd}.clear-filter-btn mat-icon{font-size:16px;width:16px;height:16px}.no-course-found-container{display:flex;justify-content:center;align-items:center;min-height:300px;padding:20px}.no-course-card{background:linear-gradient(135deg,#f8f9fa,#e9ecef);border:2px dashed #ced4da;border-radius:16px;padding:40px;text-align:center;max-width:500px;box-shadow:0 4px 12px #0000000d}.no-course-card .no-course-icon{margin-bottom:20px}.no-course-card .no-course-icon mat-icon{font-size:48px;width:48px;height:48px;color:#6c757d}.no-course-card .no-course-content h4{color:#495057;font-family:Montserrat;font-size:24px;font-weight:600;margin-bottom:12px}.no-course-card .no-course-content p{color:#6c757d;font-family:Lato;font-size:16px;line-height:1.5;margin-bottom:12px}.no-course-card .no-course-content p strong{color:#1b4ca1;font-weight:600}.no-course-card .suggest-course-btn{background:linear-gradient(135deg,#1b4ca1,#164080);color:#fff;border:none;border-radius:25px;padding:12px 24px;font-family:Lato;font-size:14px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;margin:20px auto 0;transition:all .3s ease;box-shadow:0 4px 12px #1b4ca14d}.no-course-card .suggest-course-btn:hover{background:linear-gradient(135deg,#164080,#0f2f5f);transform:translateY(-2px);box-shadow:0 6px 16px #1b4ca166}.no-course-card .suggest-course-btn:active{transform:translateY(0)}.no-course-card .suggest-course-btn mat-icon{font-size:18px;width:18px;height:18px}.left-panel{flex:0 0 280px!important;background:#f8f9fa;border-radius:12px;padding:16px;border:1px solid #e9ecef;max-height:600px;overflow-y:auto;font-weight:400!important}@media (max-width: 1200px){.search-and-buttons-container{flex-direction:column;align-items:stretch}.search-container-compact{min-width:auto;width:100%}.btn-group-compact{justify-content:center;flex-wrap:wrap}}@media (max-width: 1200px) and (min-width: 769px){.course-list-item{flex:1 1 calc(50% - 10px);min-width:300px;max-width:none}}@media (max-width: 768px){.course-list-container-flex{flex-direction:column}.left-panel{flex:none!important;max-height:300px}.course-list-item{flex:0 0 100%;max-width:100%}.no-course-card{padding:20px}.no-course-card .no-course-content h4{font-size:20px}.no-course-card .no-course-content p{font-size:14px}}::ng-deep .error-snackbar{background-color:#f44336!important;color:#fff!important;font-weight:500}::ng-deep .error-snackbar .mat-simple-snackbar-action{color:#fff!important}::ng-deep .session-expired-snackbar{background-color:#ff9800!important;color:#fff!important;font-weight:600}::ng-deep .session-expired-snackbar .mat-simple-snackbar-action{color:#fff!important;font-weight:700}.download-pdf{justify-content:end;display:flex;flex-direction:row}.gap-analysis-pdf-container{font-family:Lato;max-width:900px;margin:auto;color:#212121}.gap-analysis-pdf-header{text-align:center;margin-bottom:2rem}.gap-analysis-pdf-header .logo{height:60px;margin-bottom:.5rem}.gap-analysis-pdf-header h1{font-size:1.8rem;font-weight:600;margin:.5rem 0}.gap-analysis-pdf-header .subtitle{color:#555;font-size:.95rem}.gap-analysis-pdf-header .download-btn{background:#5e00ff;color:#fff;border:none;padding:10px 20px;border-radius:6px;margin-top:1rem;font-weight:500;cursor:pointer}.competency-snapshot{background:#fafafa;border-radius:12px;padding:2rem;margin-bottom:2rem}.competency-snapshot h2{font-size:1.4rem;font-weight:600;margin-bottom:1.5rem}.competency-snapshot .snapshot-content{display:flex;gap:2rem;align-items:center;justify-content:space-between}.competency-snapshot .snapshot-content .circle-wrapper{position:relative;width:120px;height:120px}.competency-snapshot .snapshot-content .circle-wrapper .progress-ring-bg{fill:none;stroke:#eee;stroke-width:10}.competency-snapshot .snapshot-content .circle-wrapper .progress-ring-circle{fill:none;stroke:#6c63ff;stroke-width:10;stroke-linecap:round;stroke-dasharray:326.72;stroke-dashoffset:117.6192;transform:rotate(-90deg);transform-origin:center;transition:stroke-dashoffset .35s}.competency-snapshot .snapshot-content .circle-wrapper .percentage-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-weight:600;font-size:1.4rem;text-align:center}.competency-snapshot .snapshot-content .circle-wrapper .percentage-text span{display:block;font-size:.75rem;font-weight:400;color:#555}.competency-snapshot .snapshot-content .details{flex-grow:1}.competency-snapshot .snapshot-content .details .total-competencies{font-size:1.2rem;margin-bottom:1rem}.competency-snapshot .snapshot-content .details .bar{margin:.5rem 0;padding:.6rem 1rem;border-radius:6px;font-weight:500;display:flex;justify-content:space-between;color:#fff}.competency-snapshot .snapshot-content .details .bar.behavioral{background:#7b1fa2}.competency-snapshot .snapshot-content .details .bar.functional{background:#0288d1}.competency-snapshot .snapshot-content .details .bar.domain{background:#f57c00}.gap-section{margin-top:2rem}.gap-section h2{font-size:1.3rem;margin-bottom:1rem}.gap-section .gap-box{background:#eef1ff;border-left:5px solid #6c63ff;padding:1rem;border-radius:6px;font-weight:500;color:#333}.gap-section .green-bg{background-color:#0080001c;border-left:5px solid #2d9b2d;padding:1rem;border-radius:6px;font-weight:500;color:#006400}.competency-container{width:100%;margin:0 auto;font-family:Segoe UI,sans-serif;color:#212121;display:flex;flex-direction:column}.total-box{background:#f8f9fc;border-radius:10px;padding:1.5rem;text-align:center;border:1px solid #e0e0e0;margin-bottom:1.5rem}.total-box .title{font-size:1rem;color:#666}.total-box .count{font-size:2rem;font-weight:700;color:#111;margin-top:.5rem}.progress-group{margin-bottom:1.5rem}.progress-group .progress-label{display:flex;justify-content:space-between;margin-bottom:6px}.progress-group .progress-label .label-text{font-weight:600}.progress-group .progress-label .covered-text{font-size:.9rem;color:#444}.progress-group .progress-label .behavioral{color:#f8b861}.progress-group .progress-label .functional{color:#e24577}.progress-group .progress-label .domain{color:#7b47a4}.progress-group .progress-bar{height:10px;background-color:#e0e0e0;border-radius:5px;overflow:hidden}.progress-group .progress-bar .progress-fill{height:100%;border-radius:5px;transition:width .5s ease-in-out}.progress-group .progress-bar .progress-fill.behavioral{background:#f8b861}.progress-group .progress-bar .progress-fill.functional{background:#e24577}.progress-group .progress-bar .progress-fill.domain{background:#7b47a4}.competency-card{border-radius:8px;padding:1rem 1.5rem;margin-bottom:1rem;border:1px solid transparent}.competency-card .title{font-weight:600;font-size:1.1rem;color:#222;margin-bottom:.4rem}.competency-card .subtitle{font-size:.95rem;color:#555}.competency-card .subtitle .tag{font-weight:500}.competency-card .subtitle .behavioral,.competency-card .subtitle .domain,.competency-card .subtitle .functional{color:#000}.competency-card.behavioral{background:linear-gradient(0deg,#f8b86152 0% 100%),#fff;border-color:#f8b861}.competency-card.functional{background:linear-gradient(0deg,#e245773d 0% 100%),#fff;border-color:#e24577}.competency-card.domain{background:linear-gradient(0deg,#7b47a43d 0% 100%),#fff;border-color:#7b47a4}.disclaimer-container{margin:8px 16px 0}.disclaimer-message{background-color:#fff3cd;border:1px solid #ffeaa7;border-radius:20px;padding:8px 16px;font-family:Lato;font-size:14px;color:#333;line-height:1.2}.disclaimer-message strong{color:#000;font-weight:600}.select-all-container{display:flex;flex-direction:row;justify-content:space-between}:host ::ng-deep .search-and-buttons-container .mat-form-field-infix{padding:10px!important}:host ::ng-deep .search-and-buttons-container .mat-form-field-wrapper{width:100%!important}:host ::ng-deep .select-search-panel{border:1px solid #ccc!important;border-radius:12px!important;box-shadow:0 8px 20px #0000001f}:host ::ng-deep .mat-select-arrow-wrapper{margin-top:5px!important}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline{color:#ccc}:host ::ng-deep .mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick{color:#1b4ca1;border-color:#1b4ca1!important}:host ::ng-deep .select-search-panel .mat-option.mat-selected:not(.mat-option-disabled){background-color:#1b4ca1!important;color:#fff!important}:host ::ng-deep .mat-form-field-appearance-outline{border-radius:25px;border:1px solid #ccc}:host ::ng-deep .mat-form-field-focused .mat-form-field-appearance-outline{border-color:#1b4ca1!important}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline-start{border-radius:25px 0 0 25px;border:none!important}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline-end{border-right:none!important;border:none!important;border-radius:0 25px 25px 0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline-gap{border:none!important;border-radius:25px}:host::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{background-color:transparent!important}:host ::ng-deep .search-and-buttons-container .mat-option-text{color:#fff!important}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i5.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.MatLegacyFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLegacyLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatLegacyInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", exportAs: ["matInput"] }, { kind: "component", type: i8.MatLegacyButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i9.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i10.MatLegacySelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i11.MatLegacyOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i12.MatLegacyCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i13.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i14.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i14.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "component", type: i15.GapAnalysisRecommendedCourseComponent, selector: "app-gap-analysis-recommended-course", inputs: ["planData"] }, { kind: "pipe", type: i5.TitleCasePipe, name: "titlecase" }] }); }
|
|
1868
|
+
}
|
|
1869
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GenerateCourseRecommendationComponent, decorators: [{
|
|
1870
|
+
type: Component,
|
|
1871
|
+
args: [{ selector: 'app-generate-course-recommendation', template: "<div class=\"view-cbp-plan\">\n <div class=\"popup-container\">\n \n <!-- Initial Loading Screen (for initial load and regeneration) -->\n <div class=\"initial-loading-container\" *ngIf=\"!dataLoaded || isRegeneratingWithProgress\">\n <div class=\"loading-content\">\n <mat-spinner diameter=\"50\"></mat-spinner>\n <div class=\"loading-text mt-3\">\n <p class=\"main-message\">{{ currentProcessingStage || (isRegeneratingWithProgress ? 'Regenerating course recommendations...' : 'Loading course recommendations...') }}</p>\n <div class=\"progress-details\" *ngIf=\"progressPercentage > 0\">\n <div class=\"progress-indicator\">\n <div class=\"progress-bar-container\">\n <div class=\"progress-bar\" \n [style.width.%]=\"progressPercentage\">\n </div>\n </div>\n <small class=\"progress-text\">{{ progressPercentage }}% Complete</small>\n </div>\n <small class=\"time-estimate\">\n Real-time course generation in progress. This may take 1-2 minutes.\n </small>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Main Content -->\n <div class=\"main-content\" *ngIf=\"dataLoaded && !isRegeneratingWithProgress\">\n <div class=\"popup-header\">\n <div class=\"header-left\">\n <div class=\"heading\">Save Courses (<span>{{sharedService?.cbpPlanFinalObj?.ministry?.orgName}} <span\n *ngIf=\"planData?.designation_name \">/ {{planData?.designation_name}}</span></span>)</div>\n </div>\n <div class=\"header-actions\">\n <button class=\"regenerate-btn\" (click)=\"regenerateCourseRecommendations()\"\n [disabled]=\"isRegenerating\"\n mat-raised-button color=\"primary\">\n <mat-icon *ngIf=\"!isRegenerating\">refresh</mat-icon>\n <mat-spinner *ngIf=\"isRegenerating\" diameter=\"20\"></mat-spinner>\n <span>{{isRegenerating ? 'Regenerating...' : 'Regenerate Recommendations'}}</span>\n </button>\n <div class=\"cursor-pointer close-btn\" (click)=\"closeDialog()\">\n <mat-icon>close</mat-icon>\n </div>\n </div>\n </div>\n <div class=\"section-container mt-4\">\n <mat-tab-group (selectedTabChange)=\"onOuterTabChange($event)\">\n <!-- First Main Tab -->\n <mat-tab label=\"course recommendation\">\n <!-- Nested Tabs -->\n <!-- <mat-tab-group (selectedTabChange)=\"onInnerTabChange($event)\">\n <mat-tab label=\"all\">\n\n </mat-tab>\n <mat-tab label=\"behavioural\">\n\n </mat-tab>\n <mat-tab label=\"functional\">\n\n </mat-tab>\n <mat-tab label=\"domain\">\n\n </mat-tab>\n </mat-tab-group> -->\n </mat-tab>\n\n <!-- Second Main Tab -->\n <mat-tab label=\"gap analysis\">\n <!-- <p>Gap analysis content goes here</p> -->\n </mat-tab>\n </mat-tab-group>\n <form [formGroup]=\"filterForm\" class=\"filters-container\">\n <div class=\"role-mapping-container\"\n *ngIf=\"outerTabActiveIndex === 0 && (innerTabActiveIndex === 0 || innerTabActiveIndex === 1 || innerTabActiveIndex === 2 || innerTabActiveIndex === 3 )\">\n <div class=\"container\">\n <div class=\"section-header-improved mt-3\">\n <div class=\"search-and-buttons-container\">\n <div>\n <label>Search Courses</label>\n </div> \n <div class=\"search-container-compact\">\n <div class=\"rsearch\">\n <mat-icon class=\"search-icon\">search</mat-icon>\n <input class=\"sinput-compact\" [(ngModel)]=\"searchText\"\n (input)=\"applyFilter($event.target.value);\"\n placeholder=\"Search Courses\" type=\"text\">\n </div>\n </div>\n \n </div>\n \n\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Competency</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.competency?.length ? '' : 'Competency' }}\n </mat-label>\n \n <mat-select\n formControlName=\"competency\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Competency\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'competency')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredCompetency\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div> \n \n </div>\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Rating</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.rating?.length ? '' : 'Rating' }}\n </mat-label>\n \n <mat-select\n formControlName=\"rating\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Reatings\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'rating')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredRatings\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n \n \n \n \n </div>\n <div class=\"section-header-improved-sec-2 mt-4\">\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Language</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.language?.length ? '' : 'Language' }}\n </mat-label>\n \n <mat-select\n formControlName=\"language\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Languages\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'language')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredLanguages\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Duration</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.duration?.length ? '' : 'Duration' }}\n </mat-label>\n \n <mat-select\n formControlName=\"duration\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Duration\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'duration')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredDurations\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"search-and-buttons-container\">\n <div style=\"margin-left: 10px;\">\n <label>Select Provider</label>\n </div> \n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>\n {{ filterForm.value.provider?.length ? '' : 'Provider' }}\n </mat-label>\n \n <mat-select\n formControlName=\"provider\"\n multiple\n panelClass=\"select-search-panel\"\n (selectionChange)=\"applyFilters()\">\n \n <!-- Search box -->\n <input style=\"border:1px solid #ccc; padding: 5px;width: 92%;margin: 5px;\"\n matInput\n placeholder=\"Search Provider\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (keyup)=\"filterList($any($event.target).value, 'provider')\" />\n \n <!-- Values -->\n <mat-option\n *ngFor=\"let r of filteredProviders\"\n [value]=\"r\">\n {{ r }}\n </mat-option>\n \n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div style=\"margin-top: 45px;margin-left: 20px;\">\n <input class=\"btn-active\" type=\"button\" value=\"Reset All Filters\"\n (click)=\"resetFilters()\" />\n </div>\n </div>\n <div class=\"mt-4\">\n <div style=\"font-size:16px;font-weight:bold;color:#000\">\n Filtered Course Count : {{filterdCourses?.length}}\n </div>\n </div>\n <div class=\"mt-5 sub-heading select-all-container\" *ngIf=\"filterdCourses?.length\">\n <div style=\"margin-left: 16px;\">\n <mat-checkbox [checked]=\"false\" (change)=\"selectAllCourses($event)\">Select All\n Courses</mat-checkbox>\n </div>\n <div class=\"btn-group-compact\">\n <div>\n <input class=\"btn-active\" type=\"button\" value=\"Suggest More Course From iGOT\"\n (click)=\"suggestMoreCourses()\" />\n </div>\n <div class=\"pl-2\">\n <input [disabled]=\"selectFilterCourses?.length > 0 ? false : true\"\n [ngClass]=\"selectFilterCourses?.length > 0 ? 'btn-active' : 'btn-disable'\"\n type=\"button\" [value]=\"mode === 'add' ? 'Save Courses' : 'Update Courses'\"\n (click)=\"saveCourses()\" />\n </div>\n </div>\n </div>\n <div class=\"disclaimer-container mt-2\" *ngIf=\"filterdCourses?.length\">\n <div class=\"disclaimer-message mt-4\">\n <strong>Disclaimer:</strong> Please verify the public course URL before adding it to the plan.\n </div>\n </div>\n <div class=\"mt-2\">\n\n <div class=\"course-list-container\">\n <div\n [ngClass]=\"innerTabActiveIndex > 0 ? 'course-list-container-flex':'course-list-container-right-flex' \">\n <div *ngIf=\"innerTabActiveIndex > 0\"\n [ngClass]=\"innerTabActiveIndex > 0 ? 'left-panel':''\">\n <ng-container *ngIf=\"innerTabActiveIndex === 1\">\n <div class=\"sub-heading\">\n <p>Competencies in Behavioural</p>\n </div>\n <div class=\"theme-filter-controls mb-2\" *ngIf=\"selectedThemeFilter\">\n <button class=\"clear-filter-btn\" (click)=\"clearThemeFilter()\">\n <mat-icon>clear</mat-icon> Clear Filter\n </button>\n </div>\n <div (click)=\"filterOnCompetencyTheme(item)\"\n class=\"category-list-item cursor-pointer mt-2\"\n [ngClass]=\"{'selected-theme': isThemeSelected(item)}\"\n *ngFor=\"let item of competencyMatchedByCategory\">\n {{item}}\n </div>\n </ng-container>\n <ng-container *ngIf=\"innerTabActiveIndex === 2\">\n <div class=\"sub-heading\">\n <p>Competencies in Functional</p>\n </div>\n <div class=\"theme-filter-controls mb-2\" *ngIf=\"selectedThemeFilter\">\n <button class=\"clear-filter-btn\" (click)=\"clearThemeFilter()\">\n <mat-icon>clear</mat-icon> Clear Filter\n </button>\n </div>\n <div (click)=\"filterOnCompetencyTheme(item)\"\n class=\"category-list-item cursor-pointer mt-2\"\n [ngClass]=\"{'selected-theme': isThemeSelected(item)}\"\n *ngFor=\"let item of competencyMatchedByCategory\">\n {{item}}\n </div>\n </ng-container>\n <ng-container *ngIf=\"innerTabActiveIndex === 3\">\n <div class=\"sub-heading\">\n <p>Competencies in Domain</p>\n </div>\n <div class=\"theme-filter-controls mb-2\" *ngIf=\"selectedThemeFilter\">\n <button class=\"clear-filter-btn\" (click)=\"clearThemeFilter()\">\n <mat-icon>clear</mat-icon> Clear Filter\n </button>\n </div>\n <div (click)=\"filterOnCompetencyTheme(item)\"\n class=\"category-list-item cursor-pointer mt-2\"\n [ngClass]=\"{'selected-theme': isThemeSelected(item)}\"\n *ngFor=\"let item of competencyMatchedByCategory\">\n {{item}}\n </div>\n </ng-container>\n </div>\n <div [ngClass]=\"innerTabActiveIndex > 0 ? 'right-panel':'right-panel-flex'\">\n <!-- No Course Found Message in Right Panel -->\n <div class=\"no-course-found-container\"\n *ngIf=\"filterdCourses?.length === 0 && selectedThemeFilter\">\n <div class=\"no-course-card\">\n <div class=\"no-course-icon\">\n <mat-icon>search_off</mat-icon>\n </div>\n <div class=\"no-course-content\">\n <h4>No Courses Found</h4>\n <p>No courses found for the selected theme:\n <strong>{{selectedThemeFilter}}</strong></p>\n <p>Would you like to add a course for this competency?</p>\n <button class=\"suggest-course-btn\"\n (click)=\"addCourseForSelectedTheme()\">\n <mat-icon>add_circle</mat-icon>\n Add Course\n </button>\n </div>\n </div>\n </div>\n\n <!-- Courses List -->\n <div class=\"course-list-item\" *ngFor=\"let item of filterdCourses;let i=index\">\n\n <div class=\"course-content\">\n <div class=\"course-header\">\n <div class=\"checked-course-container\">\n <div>\n <mat-checkbox [checked]=\"checkIfCourseExists(item)\"\n (change)=\"selectedFilterCourses($event, item)\"></mat-checkbox>\n </div>\n <div class=\"ml-2\">\n <div class=\"course-pill-container\">\n <div class=\"course-pill\">\n <div class=\"course-pill-text\">\n <span><img\n src=\"assets/icons/course.svg\"></span> <span>Course</span>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n\n <!-- <div>\n <div class=\"ai-recommened-pill\">\n <div class=\"ai-recommened-pill-text\">\n <span class=\"ai-loader-icon\"><img src=\"assets/icons/ai-loader.gif\"></span>\n\n <span *ngIf=\"item?.rationale\">AI Recommended\n <span *ngIf=\"item?.is_public\"> - Public</span>\n <span *ngIf=\"!item?.is_public\"> - iGOT</span>\n </span>\n <span *ngIf=\"!item?.rationale\">Manually Suggested - iGOT</span>\n\n </div>\n </div>\n </div> -->\n <div *ngIf=\"item?.rationale && !item?.is_public\">\n <div class=\"ai-recommened-pill-green\">\n <div class=\"ai-recommened-pill-green-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n\n <span>AI Recommended - iGOT </span>\n\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.platform\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <a class=\"cursor-pointer\" [href]=\"item?.public_link\"\n target=\"_blank\"><span>Platform -\n {{item?.platform}}</span></a>\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.organisation?.length\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <span>Provider - {{item?.organisation[0]}}</span>\n </div>\n </div>\n </div>\n <div *ngIf=\"item?.rationale && item?.is_public\">\n <div class=\"ai-recommened-pill-public\">\n <div class=\"ai-recommened-pill-public-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n\n <span>AI Recommended - Public </span>\n\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.platform\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <a class=\"cursor-pointer\" [href]=\"item?.public_link\"\n target=\"_blank\"><span>Platform -\n {{item?.platform}}</span></a>\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.organisation?.length\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <span>Provider - {{item?.organisation[0]}}</span>\n </div>\n </div>\n </div>\n <div *ngIf=\"!item?.rationale\">\n <div class=\"ai-recommened-pill-gray\">\n <div class=\"ai-recommened-pill-gray-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n\n <span>Manually Suggested - iGOT </span>\n\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.platform\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <a class=\"cursor-pointer\" [href]=\"item?.public_link\"\n target=\"_blank\"><span>Platform -\n {{item?.platform}}</span></a>\n </div>\n </div>\n <div class=\"ai-recommened-pill-orange mt-2\" *ngIf=\"item?.organisation?.length\">\n <div class=\"ai-recommened-pill-orange-text\">\n <span class=\"ai-loader-icon\"><img\n src=\"assets/icons/ai-loader.gif\"></span>\n <span>Provider - {{item?.organisation[0]}}</span>\n </div>\n </div>\n </div>\n\n </div>\n <div class=\"course-title mt-3 cursor-pointer\" (click)=\"redirectToToc(item)\">\n <span *ngIf=\"item?.course\">{{item?.course}}</span>\n <!-- <span *ngIf=\"item?.name\">{{item?.name}}****</span> -->\n <span style=\"margin-left:10px;\" (click)=\"redirectToToc(item)\"><img\n height=\"18px\" width=\"18px\"\n src=\"assets/icons/redirect.png\" /></span>\n </div>\n <div class=\"course-desc mt-2\">\n <!-- <span *ngIf=\"item?.rationale\">{{item?.rationale}}</span> -->\n <span *ngIf=\"item?.description\">{{item?.description}}</span>\n </div>\n <div class=\"mt-3\" *ngIf=\"getCompetenciesByType('Behavioural',i)?.length\">\n <div class=\"competency-sub-heading\">Behavioural Competencies</div>\n <ul class=\"competency-list mt-1\">\n <li class=\"behavioural-pill\"\n *ngFor=\"let comp of getDisplayedCompetencies('Behavioural',i)\">\n <span class=\"competency-text\"> {{ comp.competencyThemeName }} -\n {{\n comp.competencySubThemeName }} </span>\n </li>\n <li *ngIf=\"hasMoreThanTwo('Behavioural',i)\"\n class=\"show-more-competency\">\n <span class=\"show-more-link cursor-pointer\"\n (click)=\"toggleCompetencies('Behavioural',i)\">\n {{ isExpanded('Behavioural',i) ? 'Show Less' : '+' +\n getRemainingCount('Behavioural',i) + ' More' }}\n </span>\n </li>\n </ul>\n </div>\n <div class=\"mt-2\" *ngIf=\"getCompetenciesByType('Functional',i)?.length\">\n <div class=\"competency-sub-heading\">Functional Competencies</div>\n <ul class=\"competency-list mt-1\">\n <li class=\"functional-pill\"\n *ngFor=\"let comp of getDisplayedCompetencies('Functional',i)\">\n <span class=\"competency-text\"> {{ comp.competencyThemeName }} -\n {{\n comp.competencySubThemeName }} </span>\n </li>\n <li *ngIf=\"hasMoreThanTwo('Functional',i)\"\n class=\"show-more-competency\">\n <span class=\"show-more-link cursor-pointer\"\n (click)=\"toggleCompetencies('Functional',i)\">\n {{ isExpanded('Functional',i) ? 'Show Less' : '+' +\n getRemainingCount('Functional',i) + ' More' }}\n </span>\n </li>\n </ul>\n </div>\n <div class=\"mt-2\" *ngIf=\"getCompetenciesByType('Domain',i)?.length\">\n <div class=\"competency-sub-heading\">Domain Competencies</div>\n <ul class=\"competency-list mt-1\">\n <li class=\"domain-pill\"\n *ngFor=\"let comp of getDisplayedCompetencies('Domain',i)\">\n <span class=\"competency-text\"> {{ comp.competencyThemeName }} -\n {{\n comp.competencySubThemeName }} </span>\n </li>\n <li *ngIf=\"hasMoreThanTwo('Domain',i)\" class=\"show-more-competency\">\n <span class=\"show-more-link cursor-pointer\"\n (click)=\"toggleCompetencies('Domain',i)\">\n {{ isExpanded('Domain',i) ? 'Show Less' : '+' +\n getRemainingCount('Domain',i) + ' More' }}\n </span>\n </li>\n </ul>\n </div>\n\n\n </div>\n\n <!-- Relevancy and Duration section -->\n <div class=\"course-footer\" *ngIf=\"item?.relevancy\">\n <div class=\"relevancy-pill-green\">\n <div class=\"relevancy-container\">\n <div class=\"relevancy\">Relevancy</div>\n <div class=\"dash\">-</div>\n <div class=\"percentage\">{{item?.relevancy}}%</div>\n </div>\n </div>\n <div class=\"relevancy-pill-green\">\n <div class=\"relevancy-container\">\n <div class=\"relevancy\">Duration</div>\n <div class=\"dash\">-</div>\n <div class=\"percentage\">\n <span\n *ngIf=\"item?.duration\">{{getDuration(item?.duration)}}</span>\n <span *ngIf=\"!(item?.duration)\">N/A</span>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- General No Data Message (only when no theme filter is active) -->\n <div class=\"mt-2 sub-heading\" *ngIf=\"filterdCourses?.length === 0 && !selectedThemeFilter\">\n <p>No Data Found</p>\n </div>\n </div>\n </div>\n </form>\n <div class=\"role-mapping-container\" *ngIf=\"outerTabActiveIndex === 1\">\n <div id=\"gap-analysis-content\">\n\n <div class=\"download-pdf mt-4 mb-2\">\n <div>\n <input class=\"btn-active\" type=\"button\" value=\"Download\" (click)=\"downloadPDF()\" />\n </div>\n </div>\n <div>\n <!-- <div *ngIf=\"isPDFDownload\">\n <div class=\"pdf-heading\">{{sharedService?.cbpPlanFinalObj?.ministry?.name}} <span\n *ngIf=\"planData?.designation_name \">_{{planData?.designation_name}}_Gap_Analysis</span>\n </div>\n </div> -->\n <div class=\"d-flex vh-100\" [ngClass]=\"isPDFDownload ? 'mt-4':''\">\n <!-- Sidebar -->\n <div class=\"d-flex flex-column p-3 bg-light border-end\" style=\"width: 250px;\">\n <h5 class=\"mb-4\">Analyze by Category</h5>\n <button *ngFor=\"let item of menuItems\"\n class=\"btn btn-outline-primary mb-2 text-start menu-list-item\"\n [class.active]=\"selectedCategory === item.key\" (click)=\"selectCategory(item.key)\">\n {{ item.label }}\n </button>\n </div>\n\n <!-- Main Content -->\n <div class=\"flex-grow-1 p-4\">\n <div class=\"d-flex justify-content-between gap-3 \">\n <div class=\"p-3 gray-bg\">\n <div class=\"div-label sub-heading\">\n <p>Competencies Covered</p>\n </div>\n <div class=\"div-count\">{{competencyCoveredCount}}</div>\n </div>\n <div class=\"p-3 gray-bg\">\n <div class=\"div-label sub-heading\">\n <p *ngIf=\"selectedCategory === 'all'\">Total Competencies</p>\n <p *ngIf=\"selectedCategory === 'behavioral'\">Total Behavioural Competencies\n </p>\n <p *ngIf=\"selectedCategory === 'functional'\">Total Functional Competencies\n </p>\n <p *ngIf=\"selectedCategory === 'domain'\">Total Domain Competencies</p>\n </div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'all'\">\n {{this.planData?.competencies?.length}}</div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'behavioral'\">\n {{behavioralTotalCompetencies}}</div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'functional'\">\n {{functionalTotalCompetencies}}</div>\n <div class=\"div-count\" *ngIf=\"selectedCategory === 'domain'\">\n {{domainTotalCompetencies}}</div>\n </div>\n <div class=\"p-3 green-bg\">\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'all'\">Overall Coverage\n </div>\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'behavioral'\">\n Behavioural Coverage</div>\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'functional'\">\n Functional Coverage</div>\n <div class=\"div-green-label\" *ngIf=\"selectedCategory === 'domain'\">Domain\n Coverage</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'all'\">\n {{overallCoverage}}</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'behavioral'\">\n {{behavioralCoverage}}</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'functional'\">\n {{functionalCoverage}}</div>\n <div class=\"div-green-count\" *ngIf=\"selectedCategory === 'domain'\">\n {{domainCoverage}}</div>\n </div>\n </div>\n <div class=\"mt-4 all-category-list\" [ngSwitch]=\"selectedCategory\">\n <div *ngSwitchCase=\"'all'\">\n <h4>All Categories</h4>\n\n <!-- Show Behavioural section only if there are unmatched behavioural competencies -->\n <div class=\"mt-4\"\n *ngIf=\"behaviouralNotMatched && behaviouralNotMatched.length > 0\">\n <div class=\"sub-heading\">\n <p>Behavioural</p>\n </div>\n <div class=\"gray-bg-item\" *ngFor=\"let item of behaviouralNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item | titlecase}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Behavioral')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New\n Course</span></div>\n </div>\n </div>\n </div>\n\n <!-- Show Functional section only if there are unmatched functional competencies -->\n <div class=\"mt-4\"\n *ngIf=\"functionalNotMatched && functionalNotMatched.length > 0\">\n <div class=\"sub-heading\">\n <p>Functional</p>\n </div>\n <div class=\"gray-bg-item\" *ngFor=\"let item of functionalNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item | titlecase}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Functional')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New\n Course</span></div>\n </div>\n </div>\n </div>\n\n <!-- Show Domain section only if there are unmatched domain competencies -->\n <div class=\"mt-4\" *ngIf=\"domainNotMatched && domainNotMatched.length > 0\">\n <div class=\"sub-heading\">\n <p>Domain</p>\n </div>\n <div class=\"gray-bg-item\" *ngFor=\"let item of domainNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item | titlecase}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Domain')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New\n Course</span></div>\n </div>\n </div>\n </div>\n\n <!-- Show message when all competencies are covered -->\n <div class=\"mt-4 text-center\"\n *ngIf=\"(!behaviouralNotMatched || behaviouralNotMatched.length === 0) && \n (!functionalNotMatched || functionalNotMatched.length === 0) && \n (!domainNotMatched || domainNotMatched.length === 0)\">\n <div class=\"no-gaps-message\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <h4>Excellent! All competencies are covered</h4>\n <p>All required competencies have been addressed by the selected\n courses.</p>\n </div>\n </div>\n\n </div>\n\n <div *ngSwitchCase=\"'behavioral'\">\n <h4>Behavioural</h4>\n <div class=\"mt-4\" *ngIf=\"behavioralCoverage !== '100%'\">\n <!-- <div class=\"sub-heading\">\n <p>Behavioural</p>\n </div> -->\n <div class=\"gray-bg-item\" *ngFor=\"let item of behaviouralNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Behavioral')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New Course </span></div>\n </div>\n </div>\n </div>\n <div class=\"mt-4\" *ngIf=\"behavioralCoverage === '100%'\">\n <div class=\"p-3\"\n style=\"background-color: #e8f5e8; border: 1px solid #4caf50; border-radius: 8px; text-align: center;\">\n <div style=\"color: #2e7d32; font-weight: 600; font-size: 16px;\">\n \uD83C\uDF89 Excellent! All behavioral competencies are covered by the\n selected courses.\n </div>\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"'functional'\">\n <h4>Functional</h4>\n <div class=\"mt-4\" *ngIf=\"functionalCoverage !== '100%'\">\n <!-- <div class=\"sub-heading\">\n <p>Functional</p>\n </div> -->\n <div class=\"gray-bg-item\" *ngFor=\"let item of functionalNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Functional')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New Course</span></div>\n </div>\n </div>\n </div>\n <div class=\"mt-4\" *ngIf=\"functionalCoverage === '100%'\">\n <div class=\"p-3\"\n style=\"background-color: #e8f5e8; border: 1px solid #4caf50; border-radius: 8px; text-align: center;\">\n <div style=\"color: #2e7d32; font-weight: 600; font-size: 16px;\">\n \uD83C\uDF89 Excellent! All functional competencies are covered by the\n selected courses.\n </div>\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"'domain'\">\n <h4>Domain</h4>\n <div class=\"mt-4\" *ngIf=\"domainCoverage !== '100%'\">\n <!-- <div class=\"sub-heading\">\n <p>Domain</p>\n </div> -->\n <div class=\"gray-bg-item\" *ngFor=\"let item of domainNotMatched\">\n <div class=\"list-flex\">\n <div><span>{{item}}</span></div>\n <div class=\"cursor-pointer\" (click)=\"addCourse(item, 'Domain')\">\n <span class=\"add-btn\"><mat-icon>add</mat-icon> Add New Course </span></div>\n </div>\n </div>\n </div>\n <div class=\"mt-4\" *ngIf=\"domainCoverage === '100%'\">\n <div class=\"p-3\"\n style=\"background-color: #e8f5e8; border: 1px solid #4caf50; border-radius: 8px; text-align: center;\">\n <div style=\"color: #2e7d32; font-weight: 600; font-size: 16px;\">\n \uD83C\uDF89 Excellent! All domain competencies are covered by the selected\n courses.\n </div>\n </div>\n </div>\n </div>\n\n <div *ngSwitchDefault>\n <p>Please select a category.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n </div>\n </div> <!-- Close main-content div -->\n\n </div>\n</div>\n\n\n<div [hidden]=\"!isPDFDownload\" class=\"gap-analysis-pdf-container\" #pdfContent>\n <div class=\"gap-analysis-pdf-header\">\n <img src=\"assets/icons/karmayogiLogo-min.png\" alt=\"Karmayogi Bharat Logo\" class=\"logo\" />\n <h1><span>\n <span *ngIf=\"sharedService?.cbpPlanFinalObj?.ministry?.sbOrgType === 'state'\">{{sharedService?.cbpPlanFinalObj?.department_name?.name}}</span> \n <span *ngIf=\"sharedService?.cbpPlanFinalObj?.ministry?.sbOrgType === 'ministry'\">{{sharedService?.cbpPlanFinalObj?.ministry?.name}}</span> \n <span *ngIf=\"planData?.designation_name \">/ {{planData?.designation_name}}</span>\n </span></h1>\n <p class=\"subtitle\">A detailed breakdown of competencies Gap Analysis</p>\n \n </div>\n \n <div class=\"competency-snapshot\">\n <h2>Competency Snapshot</h2>\n <div class=\"snapshot-content\">\n <div class=\"circle-wrapper\">\n <svg class=\"progress-ring\" width=\"120\" height=\"120\">\n <circle class=\"progress-ring-bg\" cx=\"60\" cy=\"60\" r=\"52\" />\n <circle class=\"progress-ring-circle\" cx=\"60\" cy=\"60\" r=\"52\" />\n </svg>\n <div class=\"percentage-text\">{{overallCoverage}}<br /><span>Overall Coverage</span></div>\n </div>\n \n <div class=\"competency-container\">\n <!-- Total Competencies Box -->\n <div class=\"total-box\">\n <div class=\"title\">Total Competencies</div>\n <div class=\"count\">{{this.planData?.competencies?.length}}</div>\n </div>\n \n <!-- Progress Bars -->\n <div class=\"progress-group\">\n <div class=\"progress-label\">\n <span class=\"label-text behavioral\">Behavioural</span>\n <span class=\"covered-text\">{{behavioralCompetencyCoveredCount}} / {{behavioralTotalCompetencies}} Covered</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill behavioral\" [style.width.%]=\"(behavioralCompetencyCoveredCount / behavioralTotalCompetencies) * 100\"></div>\n </div>\n </div>\n \n <div class=\"progress-group\">\n <div class=\"progress-label\">\n <span class=\"label-text functional\">Functional</span>\n <span class=\"covered-text\">{{functionalCompetencyCoveredCount}} / {{functionalTotalCompetencies}} Covered</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill functional\" [style.width.%]=\"(functionalCompetencyCoveredCount / functionalTotalCompetencies) * 100\"></div>\n </div>\n </div>\n \n <div class=\"progress-group\">\n <div class=\"progress-label\">\n <span class=\"label-text domain\">Domain</span>\n <span class=\"covered-text\">{{domainCompetencyCoveredCount}} / {{domainTotalCompetencies}} Covered</span>\n </div>\n <div class=\"progress-bar\">\n <div class=\"progress-fill domain\" [style.width.%]=\"(domainCompetencyCoveredCount / domainTotalCompetencies) * 100\"></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <div class=\"gap-section mb-4\">\n <h2>Detailed Competency Analysis</h2>\n <div class=\"gap-box\">\n Bridge Your Competencies Gap\n <p class=\"subtitle\">Here are {{this.planData?.competencies?.length - (behavioralCompetencyCoveredCount + functionalCompetencyCoveredCount + domainCompetencyCoveredCount)}} key areas for development.</p>\n </div>\n </div>\n <div class=\"sub-heading mb-4\">\n <p>Gap to Address <span *ngIf=\"(this.planData?.competencies?.length - (behavioralCompetencyCoveredCount + functionalCompetencyCoveredCount + domainCompetencyCoveredCount)) > 0\">({{this.planData?.competencies?.length - (behavioralCompetencyCoveredCount + functionalCompetencyCoveredCount + domainCompetencyCoveredCount)}})</span></p>\n \n </div>\n <div class=\"competency-card behavioral\" *ngFor=\"let item of behaviouralNotMatched\">\n <div class=\"title\">{{item | titlecase}}</div>\n <div class=\"subtitle\">\n \u2022 \n <span class=\"tag behavioral\">Behavioural</span>\n </div>\n </div>\n \n <div class=\"competency-card functional\" *ngFor=\"let item of functionalNotMatched\">\n <div class=\"title\">{{item | titlecase}}</div>\n <div class=\"subtitle\">\n \u2022 \n <span class=\"tag functional\">Functional</span>\n </div>\n </div>\n \n <div class=\"competency-card domain\" *ngFor=\"let item of domainNotMatched\">\n <div class=\"title\">{{item | titlecase}}</div>\n <div class=\"subtitle\">\n <!-- Project Management -->\n \u2022 \n <span class=\"tag domain\">Domain</span>\n </div>\n </div>\n <div class=\"sub-heading mb-4\">\n <p>Covered Competencies <span>({{this.planData?.competencies?.length - (behaviouralNotMatched?.length + functionalNotMatched?.length + domainNotMatched?.length)}})</span></p> \n </div>\n <div class=\"gap-section mb-4\">\n \n <div class=\"green-bg\">\n <div class=\"div-green-label mb-2\">\n Congratulations!\n </div> \n <p>You have successfully covered </p>\n <p class=\"subtitle\">{{this.planData?.competencies?.length - (behaviouralNotMatched?.length + functionalNotMatched?.length + domainNotMatched?.length)}} key competencies, forming a strong professional foundation.</p>\n </div>\n </div>\n <div class=\"competency-card behavioral\" *ngFor=\"let item of behaviouralMatched\">\n <div class=\"title\">{{item?.theme | titlecase}}</div>\n <div class=\"subtitle\">\n {{item?.sub_theme}} \u2022 \n <span class=\"tag behavioral\">Behavioural</span>\n </div>\n </div>\n \n <div class=\"competency-card functional\" *ngFor=\"let item of functionalMatched\">\n <div class=\"title\">{{item?.theme | titlecase}}</div>\n <div class=\"subtitle\">\n {{item?.sub_theme}} \u2022 \n <span class=\"tag functional\">Functional</span>\n </div>\n </div>\n \n <div class=\"competency-card domain\" *ngFor=\"let item of domainMatched\">\n <div class=\"title\">{{item?.theme | titlecase}}</div>\n <div class=\"subtitle\">\n <!-- Project Management -->\n {{item?.sub_theme}} \u2022 \n <span class=\"tag domain\">Domain</span>\n </div>\n </div>\n <div class=\"gap-section mb-4\">\n <h2>Recommended Courses</h2>\n </div>\n <app-gap-analysis-recommended-course [planData]=\"planData\"></app-gap-analysis-recommended-course>\n</div>\n \n\n\n<div class=\"overlay-loader\" *ngIf=\"loading && dataLoaded && !isRegeneratingWithProgress\">\n <div class=\"loading-content\">\n <mat-spinner diameter=\"50\"></mat-spinner>\n <div class=\"loading-text mt-3\">\n <p class=\"main-message\">{{ currentProcessingStage || 'Preparing course recommendation generation...' }}</p>\n <div class=\"progress-details\">\n <div class=\"progress-indicator\" *ngIf=\"progressPercentage > 0\">\n <div class=\"progress-bar-container\">\n <div class=\"progress-bar\" \n [style.width.%]=\"progressPercentage\">\n </div>\n </div>\n <small class=\"progress-text\">{{ progressPercentage }}% Complete</small>\n </div>\n <small class=\"time-estimate\">\n Real-time course generation in progress. This may take 1-2 minutes.\n </small>\n </div>\n </div>\n </div>\n</div>", styles: ["@charset \"UTF-8\";.container{margin:10px auto}.sub-heading p{color:#000;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal}.radio-label{color:#000;font-family:Lato;font-size:16px;font-style:normal;font-weight:400;line-height:normal}.radio-btn-group{display:flex;width:32px;height:32px;padding:2px;gap:10px}.label{color:var(--Body-Text-Body-Color, #212529);font-family:Lato;font-size:16px;font-style:normal;font-weight:700;line-height:150%}::ng-deep mat-form-field{background-color:#fff!important;border-radius:25px!important;padding-left:12px;padding-right:12px;height:42px;width:100%}::ng-deep mat-select{border-radius:25px!important;background-color:#fff!important}::ng-deep .mat-select-panel{background-color:#fff!important}::ng-deep .mat-select-panel .mat-option{border-radius:0!important}::ng-deep mat-form-field .mat-form-field-underline{display:none!important}::ng-deep mat-select .mat-select-placeholder{color:#0006;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal}::ng-deep mat-select .mat-select-value-text{color:#000;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal;line-height:normal!important;padding-top:0!important;padding-bottom:0!important}::ng-deep mat-select .mat-select-value{display:flex!important;align-items:center!important;height:100%!important}.additional-details textarea{display:flex;padding:16px 16px 0;flex-direction:column;align-items:flex-start;gap:10px;flex:1 0 0;align-self:stretch;width:100%;color:#000;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal;resize:none}.section-header{display:flex;flex-direction:row;align-items:center;justify-content:space-between}.btn-disable{border-radius:var(--Radius-Full-Round, 9999999px);opacity:.4;background:var(--Primary-KB-Primary-Light, #1B4CA1);color:var(--white-kb-white-100, #FFF);text-align:center;font-family:Lato;font-size:14px;font-style:normal;font-weight:700;line-height:normal;display:flex;height:32px;padding:0 16px;justify-content:center;align-items:center;gap:8px;border:none}.btn-group{display:flex;flex-direction:row;justify-content:space-between}.pl-2{padding-left:5px}.search-filter-section{display:flex;flex-direction:row;justify-content:space-between}.search .rsearch{position:relative}.search .search-icon{position:absolute;top:15px;font-size:20px;left:10px}.search .sinput{border-radius:32px;border:1px solid #d5d0d0;padding:15px 36px;font:400 14px Lato;width:800px}.select-map-route-container{display:flex;flex-direction:row}.selected-mapping-route p{color:#1b4ca1;font-family:Lato;font-size:20px;font-style:normal;font-weight:400;line-height:normal;text-decoration-line:underline;text-decoration-style:solid;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;text-decoration-thickness:auto;text-underline-offset:auto;text-underline-position:from-font}.edit-plan{display:flex;padding:4px;justify-content:center;align-items:center;gap:8px;border-radius:4px;background:#1b4ca129;color:#1b4ca1;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal;margin-left:10px}.search-container{display:flex;flex-direction:row}.course-container{display:flex;width:100%;padding:16px;flex-direction:column;align-items:flex-start;gap:24px;grid-row:2/span 1;grid-column:1/span 1;border-radius:12px;border:1px solid var(--borders-black-border-16-black, rgba(0, 0, 0, .16));background:#fff}.course-header{display:flex;flex-direction:row;justify-content:space-between;align-items:flex-start;width:100%;gap:8px}.course-pill{display:flex;height:24px;padding:8px;align-items:center;gap:4px;border-radius:16px;border:1px solid var(--borders-border-fill-focussed-4-light-100, #EF951E);background:#fefaf4}.ai-recommened-pill-green{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#0080001c}.ai-recommened-pill-green-text{color:#006400;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-public{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#1b4ca129}.ai-recommened-pill-public-text{color:#1b4ca1;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-gray{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#d3d3d3}.ai-recommened-pill-gray-text{color:#000;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-orange{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);background:#ffa50052}.ai-recommened-pill-orange-text{color:#5a3f0d;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.ai-recommened-pill-orange-text a{color:#5a3f0d!important;font-family:Lato;font-size:11px;font-style:normal;font-weight:600;line-height:normal}.igot-platform-pill{display:flex;padding:4px 8px;align-items:center;gap:8px;border-radius:var(--Radius-4, 4px);border:1px solid #EF951E;background:#ef951e29}.course-title{color:var(--Primary-KB-Primary-Light, #1B4CA1);font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:22px}.course-desc{color:#0009;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:1.4;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis}.relevancy,.competencies-matched{color:#6c757d;font-family:Lato;font-size:12px;font-style:normal;font-weight:500;line-height:normal;align-items:center}.percentage{color:#1b4ca1;font-family:Lato;font-size:14px;font-style:normal;font-weight:600;line-height:normal}.relevancy-container,.competencies-matched-container{display:flex;flex-direction:row;align-items:center}.dash{padding:0 5px}::ng-deep .mat-radio-checked .mat-radio-inner-circle{background:#1b4ca1!important}.course-list-container{display:flex;flex-wrap:wrap;gap:16px;width:100%;padding:1rem}.course-list-item{flex:1 1 calc(50% - 10px);min-width:350px;max-width:500px;box-sizing:border-box;border:1px solid #e0e0e0;padding:16px;background-color:#fff;border-radius:12px;min-height:auto;box-shadow:0 2px 4px #0000001a;transition:box-shadow .2s ease;display:flex;flex-direction:column}.course-list-item:hover{box-shadow:0 4px 8px #00000026}.course-list-item:only-child{flex:1 1 auto;max-width:800px}.checked-course-container{display:flex;width:60%}.ml-2{margin-left:8px}::ng-deep .mat-checkbox-checked .mat-checkbox-background{background:#1b4ca1!important}.igot-platform-pill-text{color:#1b4ca1;font-family:Lato;font-size:12px;font-style:normal;font-weight:700;line-height:normal}.course-pill-text{color:var(--accessbility-shades-without-opacity-kb-greys-black-87, #212121);text-align:center;font-family:Poppins;font-size:12px;font-style:normal;font-weight:400;line-height:normal}.ai-loader-icon img,.igot-platform-icon img{width:15.714px;height:15.714px;flex-shrink:0}.competency-container{display:flex;justify-content:space-between;flex-direction:row}.outside-layer-total{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #1B4CA1;background:#edf1f8;width:132px}.outside-layer-functional{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #E24577;background:#f8d2de;width:132px}.outside-layer-domain{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #7B47A4;background:#dfd3e9;width:132px}.outside-layer-behavioral{display:flex;padding:4px 12px;justify-content:center;align-items:center;gap:16px;border-radius:12px 4px 4px 12px;border-left:2px solid #F8B861;background:#fde8cc;width:132px}.inside-layer{color:#1b4ca1;font-family:Lato;font-size:12px;font-style:normal;font-weight:400;line-height:normal}.count{color:#1b4ca1;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal}.suggest-courses-header{display:flex;flex-direction:row;justify-content:space-between}.suggest-course-control{display:flex;flex-direction:row}.course-card-container{width:172px;border-radius:3.307px;border:.827px solid var(--borders-border-8-black, rgba(0, 0, 0, .08));background-color:#fff}.highlight-ai{font-family:Montserrat;font-size:24px;font-style:normal;font-weight:600;line-height:normal;background:linear-gradient(90deg,#3b27ff,#2de3d6);background-clip:text;-webkit-background-clip:text;color:transparent;-webkit-text-fill-color:transparent;display:inline-block}.ai-loader-icon-medium img{width:40px;height:40px;flex-shrink:0}.heading{color:#000;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal;margin:10px 0}.pdf-heading{color:#000;font-family:Montserrat;font-size:18px;font-style:normal;font-weight:600;line-height:normal;margin:10px 0;text-align:center}.popup-header{display:flex;justify-content:space-between;align-items:center;padding:16px;border-bottom:1px solid #e0e0e0}.header-left{flex:1}.header-actions{display:flex;align-items:center;gap:12px}.regenerate-btn{display:flex;align-items:center;gap:8px;padding:8px 16px;border-radius:6px;font-size:14px;font-weight:500;min-width:auto}.regenerate-btn .mat-icon{margin:0;font-size:18px;width:18px;height:18px}.regenerate-btn .mat-spinner{margin:0}.regenerate-btn:disabled{opacity:.7;cursor:not-allowed}.close-btn{padding:8px;border-radius:4px;transition:background-color .2s ease}.close-btn:hover{background-color:#f5f5f5}.close-btn .mat-icon{font-size:20px;width:20px;height:20px}.progress-popup{display:flex;flex-direction:column;justify-content:center;align-items:center}.progress-popup .desc{color:#000000de;text-align:center;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal}.behavioural-pill{display:flex;padding:2px 6px;justify-content:center;align-items:center;gap:4px;border-radius:16px;border:1px solid #F8B861;background:linear-gradient(0deg,#f8b86152 0% 100%),#fff;margin:2px 4px 2px 0;font-size:12px}.functional-pill{display:flex;padding:2px 6px;justify-content:center;align-items:center;gap:4px;border-radius:16px;border:1px solid #E24577;background:linear-gradient(0deg,#e245773d 0% 100%),#fff;margin:2px 4px 2px 0;font-size:12px}.domain-pill{display:flex;padding:2px 6px;justify-content:center;align-items:center;gap:4px;border-radius:16px;border:1px solid #7B47A4;background:linear-gradient(0deg,#7b47a43d 0% 100%),#fff;margin:2px 4px 2px 0;font-size:12px}.popup-header{display:flex;flex-direction:row;justify-content:space-between}.popup-footer{display:flex;flex-direction:row;justify-content:end}.view-cbp-plan{margin:10px;padding:10px}.view-cbp-plan-popup{padding:24px;max-height:70vh;overflow-y:auto}.section{border-radius:8px;background:#1b4ca114;padding:16px}.popup-header{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #ddd;font-weight:700;flex-shrink:0}.popup-footer{display:flex;justify-content:flex-end;gap:16px;padding:16px 24px;border-top:1px solid #ddd;background-color:#fff;flex-shrink:0;position:sticky;bottom:0}.section-container{overflow-y:auto;flex:1 1 auto}.competency-list{display:flex;flex-direction:row;gap:0px;flex-wrap:wrap;margin:0;padding:0;list-style:none}.competency-text{color:#000;font-family:Lato;font-size:12px;font-style:normal;font-weight:400;line-height:normal;padding:3px 6px}.competency-text-behavioral{color:#654321;font-family:Lato;font-size:14px;font-style:normal;line-height:normal;font-weight:550}.competency-text-functional{color:#b01669;font-family:Lato;font-size:14px;font-style:normal;line-height:normal;font-weight:550}.competency-text-domain{color:#301934;font-family:Lato;font-size:14px;font-style:normal;line-height:normal;font-weight:550}.competency-sub-heading{color:#1b4ca1;font-family:Montserrat;font-size:14px;font-style:normal;font-weight:600;line-height:normal}.cursor-pointer{cursor:pointer}.btn-active{border-radius:var(--Radius-Full-Round, 9999999px);opacity:1;background:var(--Primary-KB-Primary-Light, #1B4CA1);color:var(--white-kb-white-100, #FFF);text-align:center;font-family:Lato;font-size:14px;font-style:normal;font-weight:700;line-height:normal;display:flex;height:32px;padding:0 16px;justify-content:center;align-items:center;gap:8px;border:none}.custom-textarea{color:#000;font-family:Lato;font-size:14px;font-style:normal;font-weight:400;line-height:normal}.initial-loading-container{display:flex;justify-content:center;align-items:center;min-height:400px;width:100%}.initial-loading-container .loading-content{display:flex;flex-direction:column;align-items:center;text-align:center;padding:3rem 2rem}.initial-loading-container .loading-content .loading-text{color:#1b4ca1;font-family:Lato,sans-serif;min-width:320px}.initial-loading-container .loading-content .loading-text .main-message{font-size:16px;font-weight:600;margin-bottom:1rem;color:#1b4ca1}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator{margin-bottom:.5rem}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container{width:300px;height:8px;background-color:#e0e0e0;border-radius:4px;overflow:hidden;margin-bottom:.5rem}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container .progress-bar{height:100%;background:linear-gradient(90deg,#1b4ca1,#4caf50);border-radius:4px;transition:width .3s ease-in-out}.initial-loading-container .loading-content .loading-text .progress-details .progress-indicator .progress-text{font-size:12px;color:#666;font-weight:500}.initial-loading-container .loading-content .loading-text .progress-details .time-estimate{font-size:12px;color:#888;font-style:italic}.overlay-loader{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#ffffffbf;z-index:9999;display:flex;justify-content:center;align-items:center}.overlay-loader .loading-content{display:flex;flex-direction:column;align-items:center;text-align:center;background:#fff;padding:2rem;border-radius:8px;box-shadow:0 4px 12px #00000026}.overlay-loader .loading-content .loading-text{color:#1b4ca1;font-family:Lato,sans-serif;min-width:320px}.overlay-loader .loading-content .loading-text .main-message{margin:0 0 16px;font-size:18px;font-weight:600;text-align:center}.overlay-loader .loading-content .loading-text .progress-details{margin-top:16px}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator{margin-bottom:12px}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container{width:100%;height:8px;background-color:#e0e0e0;border-radius:4px;overflow:hidden;margin-bottom:8px}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator .progress-bar-container .progress-bar{height:100%;background:linear-gradient(90deg,#1b4ca1,#2563eb);border-radius:4px;transition:width .5s ease-in-out}.overlay-loader .loading-content .loading-text .progress-details .progress-indicator .progress-text{font-size:14px;font-weight:500;color:#1b4ca1;display:block;text-align:center}.overlay-loader .loading-content .loading-text .progress-details .time-estimate{color:#666;font-size:12px;font-style:italic;display:block;text-align:center;margin-top:8px}.competencis-grid{display:flex;flex-direction:row;justify-content:space-between;gap:16px}.grid-list-item-behavioral div{border-left:2px solid darkorange}.grid-list-item-functional div{border-left:2px solid #ff1493}.grid-list-item-domain div{border-left:2px solid #6b21a8}.competencies-grid-3{width:33%}.bg-blue-50{background-color:#fde8cc;border-radius:4px}.bg-green-50{background-color:#f8d2de;border-radius:4px}.bg-purple-50{background-color:#dfd3e9;border-radius:4px}.grid-list-item div{padding:5px 10px;margin:10px 0}.course-pill-container{display:flex;gap:8px}.relevancy-pill-green{display:flex;padding:4px 8px;align-items:center;gap:4px;border-radius:16px;border:1px solid #e0e0e0;background:#f8f9fa}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.show-more-competency{display:inline-flex;align-items:center}.show-more-link{color:#1b4ca1;font-family:Lato;font-size:12px;font-style:normal;font-weight:500;line-height:normal;margin:2px 4px 2px 0;text-decoration:none}.show-more-link:hover{text-decoration:underline}.course-content{flex:1;display:flex;flex-direction:column}.course-footer{margin-top:auto;padding-top:12px;display:flex;justify-content:space-between}::ng-deep .mdc-tab__text-label{font-weight:700;font-family:Montserrat!important;font-size:16px;color:#000!important;text-transform:capitalize}.competency-tag{display:inline-block;padding:.25rem .75rem;border-radius:9999px;font-size:.75rem;font-weight:500;margin-right:.5rem;margin-bottom:.5rem}.menu-list-item.active{background-color:#1b4ca1;color:#fff}.menu-list-item:hover{background-color:#1b4ca1;color:#fff;border-color:#1b4ca1}.gray-bg{background-color:rgb(248,250,252,var(--tw-bg-opacity, 1));border-radius:8px;border:1px solid #ccc}.div-count{font-family:Lato;font-size:20px;font-weight:700}.green-bg{background-color:#0080001c;border:1px solid #006400;border-radius:8px}.div-green-count{font-family:Lato;font-size:20px;font-weight:700;color:#006400}.div-green-label{color:#006400;font-family:Montserrat;font-size:16px;font-style:normal;font-weight:600;line-height:normal}.gray-bg-item{background-color:rgb(248,250,252,var(--tw-bg-opacity, 1));border-radius:8px;border:1px solid #ccc;padding:4px 8px;margin:10px}.add-btn{color:#1b4ca1;font-size:14px;font-family:Lato}.list-flex{display:flex;flex-direction:row;justify-content:space-between}.all-category-list .mat-icon{vertical-align:middle}.course-list-container-flex{display:flex;align-items:flex-start;gap:2rem}.left-panel{flex:0 0 250px;font-weight:700;text-align:left}.right-panel{flex:1;display:flex;flex-direction:row;flex-wrap:wrap;gap:20px;align-content:flex-start;justify-content:flex-start}.category-list-item{font-weight:400;font-size:16px;font-family:Lato;padding:5px}.right-panel-flex{display:flex;flex:0 0 100%;width:100%;flex-direction:row;flex-wrap:wrap;gap:20px;justify-content:flex-start}.course-list-container-right-flex{display:flex}.no-gaps-message{display:flex;flex-direction:column;align-items:center;padding:24px;background:linear-gradient(135deg,#4caf501a,#81c7841a);border:2px solid #4CAF50;border-radius:16px;margin:16px 0}.no-gaps-message .success-icon{font-size:25px;color:#4caf50;margin-bottom:16px}.no-gaps-message h4{color:#2e7d32;font-family:Montserrat;font-size:20px;font-weight:600;margin:0 0 8px;text-align:center}.no-gaps-message p{color:#388e3c;font-family:Lato;font-size:14px;font-weight:400;margin:0;text-align:center;line-height:1.5}.section-header-improved,.section-header-improved-sec-2{display:flex;flex-direction:row;gap:0px;width:100%}.search-and-buttons-container{display:flex;justify-content:space-between;gap:5px;flex-direction:column;flex-wrap:wrap;width:37%;margin:0 5px}.search-container-compact{flex:0 0 auto;min-width:180px}.search-container-compact .rsearch{position:relative;display:flex;align-items:center}.search-container-compact .search-icon{position:absolute;left:12px;color:#666;font-size:20px;z-index:1}.search-container-compact .sinput-compact{border-radius:25px;border:2px solid #ccc;padding:20px 12px 20px 40px;height:32px;width:100%;font:400 14px Lato;box-sizing:border-box;transition:border-color .3s ease}.search-container-compact .sinput-compact:focus{outline:none;border-color:#1b4ca1;box-shadow:0 0 0 2px #1b4ca11a}.search-container-compact .sinput-compact::placeholder{color:#999}.btn-group-compact{display:flex;gap:8px;flex:0 0 auto}.category-list-item{padding:8px 12px!important;border-radius:6px;border:1px solid transparent;transition:all .3s ease;background:#f8f9fa;color:#333;font-family:Lato;font-size:14px!important;font-weight:400!important}.category-list-item:hover{background:#1b4ca10d;border-color:#1b4ca133}.category-list-item.selected-theme{background:#1b4ca11a;border-color:#1b4ca1;color:#1b4ca1;font-weight:600!important}.category-list-item.selected-theme:before{content:\"\\2713 \";color:#1b4ca1;font-weight:700}.theme-filter-controls{margin-bottom:8px}.clear-filter-btn{background:#f8f9fa;border:1px solid #ddd;border-radius:20px;padding:4px 12px;font-size:12px;color:#666;cursor:pointer;transition:all .3s ease;display:flex;align-items:center;gap:4px}.clear-filter-btn:hover{background:#e9ecef;border-color:#adb5bd}.clear-filter-btn mat-icon{font-size:16px;width:16px;height:16px}.no-course-found-container{display:flex;justify-content:center;align-items:center;min-height:300px;padding:20px}.no-course-card{background:linear-gradient(135deg,#f8f9fa,#e9ecef);border:2px dashed #ced4da;border-radius:16px;padding:40px;text-align:center;max-width:500px;box-shadow:0 4px 12px #0000000d}.no-course-card .no-course-icon{margin-bottom:20px}.no-course-card .no-course-icon mat-icon{font-size:48px;width:48px;height:48px;color:#6c757d}.no-course-card .no-course-content h4{color:#495057;font-family:Montserrat;font-size:24px;font-weight:600;margin-bottom:12px}.no-course-card .no-course-content p{color:#6c757d;font-family:Lato;font-size:16px;line-height:1.5;margin-bottom:12px}.no-course-card .no-course-content p strong{color:#1b4ca1;font-weight:600}.no-course-card .suggest-course-btn{background:linear-gradient(135deg,#1b4ca1,#164080);color:#fff;border:none;border-radius:25px;padding:12px 24px;font-family:Lato;font-size:14px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:8px;margin:20px auto 0;transition:all .3s ease;box-shadow:0 4px 12px #1b4ca14d}.no-course-card .suggest-course-btn:hover{background:linear-gradient(135deg,#164080,#0f2f5f);transform:translateY(-2px);box-shadow:0 6px 16px #1b4ca166}.no-course-card .suggest-course-btn:active{transform:translateY(0)}.no-course-card .suggest-course-btn mat-icon{font-size:18px;width:18px;height:18px}.left-panel{flex:0 0 280px!important;background:#f8f9fa;border-radius:12px;padding:16px;border:1px solid #e9ecef;max-height:600px;overflow-y:auto;font-weight:400!important}@media (max-width: 1200px){.search-and-buttons-container{flex-direction:column;align-items:stretch}.search-container-compact{min-width:auto;width:100%}.btn-group-compact{justify-content:center;flex-wrap:wrap}}@media (max-width: 1200px) and (min-width: 769px){.course-list-item{flex:1 1 calc(50% - 10px);min-width:300px;max-width:none}}@media (max-width: 768px){.course-list-container-flex{flex-direction:column}.left-panel{flex:none!important;max-height:300px}.course-list-item{flex:0 0 100%;max-width:100%}.no-course-card{padding:20px}.no-course-card .no-course-content h4{font-size:20px}.no-course-card .no-course-content p{font-size:14px}}::ng-deep .error-snackbar{background-color:#f44336!important;color:#fff!important;font-weight:500}::ng-deep .error-snackbar .mat-simple-snackbar-action{color:#fff!important}::ng-deep .session-expired-snackbar{background-color:#ff9800!important;color:#fff!important;font-weight:600}::ng-deep .session-expired-snackbar .mat-simple-snackbar-action{color:#fff!important;font-weight:700}.download-pdf{justify-content:end;display:flex;flex-direction:row}.gap-analysis-pdf-container{font-family:Lato;max-width:900px;margin:auto;color:#212121}.gap-analysis-pdf-header{text-align:center;margin-bottom:2rem}.gap-analysis-pdf-header .logo{height:60px;margin-bottom:.5rem}.gap-analysis-pdf-header h1{font-size:1.8rem;font-weight:600;margin:.5rem 0}.gap-analysis-pdf-header .subtitle{color:#555;font-size:.95rem}.gap-analysis-pdf-header .download-btn{background:#5e00ff;color:#fff;border:none;padding:10px 20px;border-radius:6px;margin-top:1rem;font-weight:500;cursor:pointer}.competency-snapshot{background:#fafafa;border-radius:12px;padding:2rem;margin-bottom:2rem}.competency-snapshot h2{font-size:1.4rem;font-weight:600;margin-bottom:1.5rem}.competency-snapshot .snapshot-content{display:flex;gap:2rem;align-items:center;justify-content:space-between}.competency-snapshot .snapshot-content .circle-wrapper{position:relative;width:120px;height:120px}.competency-snapshot .snapshot-content .circle-wrapper .progress-ring-bg{fill:none;stroke:#eee;stroke-width:10}.competency-snapshot .snapshot-content .circle-wrapper .progress-ring-circle{fill:none;stroke:#6c63ff;stroke-width:10;stroke-linecap:round;stroke-dasharray:326.72;stroke-dashoffset:117.6192;transform:rotate(-90deg);transform-origin:center;transition:stroke-dashoffset .35s}.competency-snapshot .snapshot-content .circle-wrapper .percentage-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-weight:600;font-size:1.4rem;text-align:center}.competency-snapshot .snapshot-content .circle-wrapper .percentage-text span{display:block;font-size:.75rem;font-weight:400;color:#555}.competency-snapshot .snapshot-content .details{flex-grow:1}.competency-snapshot .snapshot-content .details .total-competencies{font-size:1.2rem;margin-bottom:1rem}.competency-snapshot .snapshot-content .details .bar{margin:.5rem 0;padding:.6rem 1rem;border-radius:6px;font-weight:500;display:flex;justify-content:space-between;color:#fff}.competency-snapshot .snapshot-content .details .bar.behavioral{background:#7b1fa2}.competency-snapshot .snapshot-content .details .bar.functional{background:#0288d1}.competency-snapshot .snapshot-content .details .bar.domain{background:#f57c00}.gap-section{margin-top:2rem}.gap-section h2{font-size:1.3rem;margin-bottom:1rem}.gap-section .gap-box{background:#eef1ff;border-left:5px solid #6c63ff;padding:1rem;border-radius:6px;font-weight:500;color:#333}.gap-section .green-bg{background-color:#0080001c;border-left:5px solid #2d9b2d;padding:1rem;border-radius:6px;font-weight:500;color:#006400}.competency-container{width:100%;margin:0 auto;font-family:Segoe UI,sans-serif;color:#212121;display:flex;flex-direction:column}.total-box{background:#f8f9fc;border-radius:10px;padding:1.5rem;text-align:center;border:1px solid #e0e0e0;margin-bottom:1.5rem}.total-box .title{font-size:1rem;color:#666}.total-box .count{font-size:2rem;font-weight:700;color:#111;margin-top:.5rem}.progress-group{margin-bottom:1.5rem}.progress-group .progress-label{display:flex;justify-content:space-between;margin-bottom:6px}.progress-group .progress-label .label-text{font-weight:600}.progress-group .progress-label .covered-text{font-size:.9rem;color:#444}.progress-group .progress-label .behavioral{color:#f8b861}.progress-group .progress-label .functional{color:#e24577}.progress-group .progress-label .domain{color:#7b47a4}.progress-group .progress-bar{height:10px;background-color:#e0e0e0;border-radius:5px;overflow:hidden}.progress-group .progress-bar .progress-fill{height:100%;border-radius:5px;transition:width .5s ease-in-out}.progress-group .progress-bar .progress-fill.behavioral{background:#f8b861}.progress-group .progress-bar .progress-fill.functional{background:#e24577}.progress-group .progress-bar .progress-fill.domain{background:#7b47a4}.competency-card{border-radius:8px;padding:1rem 1.5rem;margin-bottom:1rem;border:1px solid transparent}.competency-card .title{font-weight:600;font-size:1.1rem;color:#222;margin-bottom:.4rem}.competency-card .subtitle{font-size:.95rem;color:#555}.competency-card .subtitle .tag{font-weight:500}.competency-card .subtitle .behavioral,.competency-card .subtitle .domain,.competency-card .subtitle .functional{color:#000}.competency-card.behavioral{background:linear-gradient(0deg,#f8b86152 0% 100%),#fff;border-color:#f8b861}.competency-card.functional{background:linear-gradient(0deg,#e245773d 0% 100%),#fff;border-color:#e24577}.competency-card.domain{background:linear-gradient(0deg,#7b47a43d 0% 100%),#fff;border-color:#7b47a4}.disclaimer-container{margin:8px 16px 0}.disclaimer-message{background-color:#fff3cd;border:1px solid #ffeaa7;border-radius:20px;padding:8px 16px;font-family:Lato;font-size:14px;color:#333;line-height:1.2}.disclaimer-message strong{color:#000;font-weight:600}.select-all-container{display:flex;flex-direction:row;justify-content:space-between}:host ::ng-deep .search-and-buttons-container .mat-form-field-infix{padding:10px!important}:host ::ng-deep .search-and-buttons-container .mat-form-field-wrapper{width:100%!important}:host ::ng-deep .select-search-panel{border:1px solid #ccc!important;border-radius:12px!important;box-shadow:0 8px 20px #0000001f}:host ::ng-deep .mat-select-arrow-wrapper{margin-top:5px!important}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline{color:#ccc}:host ::ng-deep .mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick{color:#1b4ca1;border-color:#1b4ca1!important}:host ::ng-deep .select-search-panel .mat-option.mat-selected:not(.mat-option-disabled){background-color:#1b4ca1!important;color:#fff!important}:host ::ng-deep .mat-form-field-appearance-outline{border-radius:25px;border:1px solid #ccc}:host ::ng-deep .mat-form-field-focused .mat-form-field-appearance-outline{border-color:#1b4ca1!important}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline-start{border-radius:25px 0 0 25px;border:none!important}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline-end{border-right:none!important;border:none!important;border-radius:0 25px 25px 0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline-gap{border:none!important;border-radius:25px}:host::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{background-color:transparent!important}:host ::ng-deep .search-and-buttons-container .mat-option-text{color:#fff!important}\n"] }]
|
|
1872
|
+
}], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
|
|
1873
|
+
type: Inject,
|
|
1874
|
+
args: [MAT_DIALOG_DATA]
|
|
1875
|
+
}] }, { type: i2.SharedService }, { type: i3.MatSnackBar }, { type: i1.MatDialog }, { type: i4.FormBuilder }]; }, propDecorators: { pdfContent: [{
|
|
1876
|
+
type: ViewChild,
|
|
1877
|
+
args: ['pdfContent', { static: false }]
|
|
1878
|
+
}] } });
|
|
1879
|
+
// Confirmation Dialog Component
|
|
1880
|
+
export class RegenerateConfirmationDialog {
|
|
1881
|
+
constructor(dialogRef) {
|
|
1882
|
+
this.dialogRef = dialogRef;
|
|
1883
|
+
}
|
|
1884
|
+
onCancel() {
|
|
1885
|
+
this.dialogRef.close(false);
|
|
1886
|
+
}
|
|
1887
|
+
onConfirm() {
|
|
1888
|
+
this.dialogRef.close(true);
|
|
1889
|
+
}
|
|
1890
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RegenerateConfirmationDialog, deps: [{ token: i1.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1891
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RegenerateConfirmationDialog, selector: "regenerate-confirmation-dialog", ngImport: i0, template: `
|
|
1892
|
+
<div class="confirmation-dialog-container">
|
|
1893
|
+
<div class="dialog-header">
|
|
1894
|
+
<mat-icon class="warning-icon">refresh</mat-icon>
|
|
1895
|
+
<h2 mat-dialog-title>Regenerate Course Recommendations</h2>
|
|
1896
|
+
</div>
|
|
1897
|
+
|
|
1898
|
+
<mat-dialog-content class="dialog-content">
|
|
1899
|
+
<p class="main-message">
|
|
1900
|
+
This will delete all current course recommendations and generate new ones based on the latest role mapping.
|
|
1901
|
+
</p>
|
|
1902
|
+
<p class="sub-message">
|
|
1903
|
+
Are you sure you want to continue?
|
|
1904
|
+
</p>
|
|
1905
|
+
</mat-dialog-content>
|
|
1906
|
+
|
|
1907
|
+
<mat-dialog-actions class="dialog-actions">
|
|
1908
|
+
<button mat-button (click)="onCancel()" class="cancel-btn">
|
|
1909
|
+
Cancel
|
|
1910
|
+
</button>
|
|
1911
|
+
<button mat-raised-button color="primary" (click)="onConfirm()" class="confirm-btn">
|
|
1912
|
+
<mat-icon>refresh</mat-icon>
|
|
1913
|
+
Yes, Regenerate
|
|
1914
|
+
</button>
|
|
1915
|
+
</mat-dialog-actions>
|
|
1916
|
+
</div>
|
|
1917
|
+
`, isInline: true, styles: [".confirmation-dialog-container{padding:0}.dialog-header{display:flex;align-items:center;gap:12px;padding:24px 24px 16px;border-bottom:1px solid #e0e0e0}.warning-icon{font-size:24px;width:24px;height:24px;color:#ff9800}h2{margin:0;font-size:18px;font-weight:600;color:#333}.dialog-content{padding:24px}.main-message{font-size:16px;color:#333;margin:0 0 12px;line-height:1.5}.sub-message{font-size:14px;color:#666;margin:0;font-weight:500}.dialog-actions{padding:16px 24px 24px;gap:12px;justify-content:flex-end}.cancel-btn{color:#666}.confirm-btn{display:flex;align-items:center;gap:8px;.mat-icon{font-size:18px;width:18px;height:18px;margin:0}}\n"], dependencies: [{ kind: "component", type: i8.MatLegacyButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i9.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] }); }
|
|
1918
|
+
}
|
|
1919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RegenerateConfirmationDialog, decorators: [{
|
|
1920
|
+
type: Component,
|
|
1921
|
+
args: [{ selector: 'regenerate-confirmation-dialog', template: `
|
|
1922
|
+
<div class="confirmation-dialog-container">
|
|
1923
|
+
<div class="dialog-header">
|
|
1924
|
+
<mat-icon class="warning-icon">refresh</mat-icon>
|
|
1925
|
+
<h2 mat-dialog-title>Regenerate Course Recommendations</h2>
|
|
1926
|
+
</div>
|
|
1927
|
+
|
|
1928
|
+
<mat-dialog-content class="dialog-content">
|
|
1929
|
+
<p class="main-message">
|
|
1930
|
+
This will delete all current course recommendations and generate new ones based on the latest role mapping.
|
|
1931
|
+
</p>
|
|
1932
|
+
<p class="sub-message">
|
|
1933
|
+
Are you sure you want to continue?
|
|
1934
|
+
</p>
|
|
1935
|
+
</mat-dialog-content>
|
|
1936
|
+
|
|
1937
|
+
<mat-dialog-actions class="dialog-actions">
|
|
1938
|
+
<button mat-button (click)="onCancel()" class="cancel-btn">
|
|
1939
|
+
Cancel
|
|
1940
|
+
</button>
|
|
1941
|
+
<button mat-raised-button color="primary" (click)="onConfirm()" class="confirm-btn">
|
|
1942
|
+
<mat-icon>refresh</mat-icon>
|
|
1943
|
+
Yes, Regenerate
|
|
1944
|
+
</button>
|
|
1945
|
+
</mat-dialog-actions>
|
|
1946
|
+
</div>
|
|
1947
|
+
`, styles: [".confirmation-dialog-container{padding:0}.dialog-header{display:flex;align-items:center;gap:12px;padding:24px 24px 16px;border-bottom:1px solid #e0e0e0}.warning-icon{font-size:24px;width:24px;height:24px;color:#ff9800}h2{margin:0;font-size:18px;font-weight:600;color:#333}.dialog-content{padding:24px}.main-message{font-size:16px;color:#333;margin:0 0 12px;line-height:1.5}.sub-message{font-size:14px;color:#666;margin:0;font-weight:500}.dialog-actions{padding:16px 24px 24px;gap:12px;justify-content:flex-end}.cancel-btn{color:#666}.confirm-btn{display:flex;align-items:center;gap:8px;.mat-icon{font-size:18px;width:18px;height:18px;margin:0}}\n"] }]
|
|
1948
|
+
}], ctorParameters: function () { return [{ type: i1.MatDialogRef }]; } });
|
|
1949
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtY291cnNlLXJlY29tbWVuZGF0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL2xpYnJhcnkvc3VuYmlyZC1jYi9jYnAtYWkvc3JjL2xpYi9jb21wb25lbnRzL2dlbmVyYXRlLWNvdXJzZS1yZWNvbW1lbmRhdGlvbi9nZW5lcmF0ZS1jb3Vyc2UtcmVjb21tZW5kYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicmFyeS9zdW5iaXJkLWNiL2NicC1haS9zcmMvbGliL2NvbXBvbmVudHMvZ2VuZXJhdGUtY291cnNlLXJlY29tbWVuZGF0aW9uL2dlbmVyYXRlLWNvdXJzZS1yZWNvbW1lbmRhdGlvbi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUEyQixNQUFNLDBCQUEwQixDQUFDO0FBQ3BGLE9BQU8sRUFBcUIsU0FBUyxFQUFjLE1BQU0sRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHcEcsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sd0RBQXdELENBQUM7QUFFckcsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDeEUsT0FBTyxRQUFRLE1BQU0sYUFBYSxDQUFDO0FBQ25DLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBT2pGLE1BQU0sT0FBTyxxQ0FBcUM7SUFvQmhELFlBQW1CLFNBQThELEVBQy9DLElBQVMsRUFBUyxhQUE0QixFQUN0RSxRQUFxQixFQUFTLE1BQWlCLEVBQy9DLEVBQWU7UUFITixjQUFTLEdBQVQsU0FBUyxD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YWxvZywgTWF0RGlhbG9nUmVmIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEluamVjdCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1CdWlsZGVyLCBGb3JtR3JvdXAsIEZvcm1BcnJheSwgVmFsaWRhdG9ycywgRm9ybUNvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBNYXRTbmFja0JhciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NuYWNrLWJhcic7XG5pbXBvcnQgeyBTdWdnZXN0TW9yZUNvdXJzZXNDb21wb25lbnQgfSBmcm9tICcuLi9zdWdnZXN0LW1vcmUtY291cnNlcy9zdWdnZXN0LW1vcmUtY291cnNlcy5jb21wb25lbnQnO1xuaW1wb3J0IHsgTWF0VGFiQ2hhbmdlRXZlbnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcbmltcG9ydCB7IEFkZENvdXJzZUNvbXBvbmVudCB9IGZyb20gJy4uL2FkZC1jb3Vyc2UvYWRkLWNvdXJzZS5jb21wb25lbnQnO1xuaW1wb3J0IGh0bWwycGRmIGZyb20gJ2h0bWwycGRmLmpzJztcbmltcG9ydCB7IGludGVydmFsLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgc3dpdGNoTWFwLCB0YWtlV2hpbGUsIHRhcCwgY2F0Y2hFcnJvciwgZmluYWxpemUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBTaGFyZWRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbW9kdWxlcy9zaGFyZWQvc2VydmljZXMvc2hhcmVkLnNlcnZpY2UnO1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLWdlbmVyYXRlLWNvdXJzZS1yZWNvbW1lbmRhdGlvbicsXG4gIHRlbXBsYXRlVXJsOiAnLi9nZW5lcmF0ZS1jb3Vyc2UtcmVjb21tZW5kYXRpb24uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9nZW5lcmF0ZS1jb3Vyc2UtcmVjb21tZW5kYXRpb24uY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBHZW5lcmF0ZUNvdXJzZVJlY29tbWVuZGF0aW9uQ29tcG9uZW50IHtcbiAgQFZpZXdDaGlsZCgncGRmQ29udGVudCcsIHsgc3RhdGljOiBmYWxzZSB9KSBwZGZDb250ZW50ITogRWxlbWVudFJlZjtcbiAgcGxhbkRhdGE6IGFueVxuICBsb2FkaW5nID0gZmFsc2VcbiAgZGF0YUxvYWRlZCA9IGZhbHNlIC8vIFRyYWNrIGlmIGluaXRpYWwgZGF0YSBoYXMgYmVlbiBsb2FkZWRcbiAgaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3MgPSBmYWxzZSAvLyBUcmFjayByZWdlbmVyYXRpb24gd2l0aCBwcm9ncmVzcyBsb2FkaW5nXG4gIHJlY29tbWVuZGVkX2NvdXJzZV9pZCA9ICcnXG4gIFxuICAvLyBQcm9ncmVzc2l2ZSBsb2FkaW5nIGZvciBjb3Vyc2UgZ2VuZXJhdGlvblxuICBjdXJyZW50UHJvY2Vzc2luZ1N0YWdlOiBzdHJpbmcgPSAnJztcbiAgcHJvZ3Jlc3NQZXJjZW50YWdlOiBudW1iZXIgPSAwO1xuICBwcm9jZXNzaW5nU3RhZ2VzID0gW1xuICAgICdBbmFseXppbmcgcm9sZXMgYW5kIHJlc3BvbnNpYmlsaXRpZXMuLi4nLFxuICAgICdEZXRhaWxpbmcgY29tcGV0ZW5jeSByZXF1aXJlbWVudHMuLi4nLFxuICAgICdQcmVwYXJpbmcgaUdPVCBjb3Vyc2UgcmVjb21tZW5kYXRpb25zLi4uJyxcbiAgICAnR2VuZXJhdGluZyBwdWJsaWMgY291cnNlIHN1Z2dlc3Rpb25zLi4uJyxcbiAgICAnQ29tcHV0aW5nIGNvbXByZWhlbnNpdmUgZ2FwIGFuYWx5c2lzLi4uJyxcbiAgICAnRmluYWxpemluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb24gcGxhbi4uLidcbiAgXTtcbiAgc3RhZ2VTdGFydFRpbWU6IG51bWJlciA9IDA7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBkaWFsb2dSZWY6IE1hdERpYWxvZ1JlZjxHZW5lcmF0ZUNvdXJzZVJlY29tbWVuZGF0aW9uQ29tcG9uZW50PixcbiAgICBASW5qZWN0KE1BVF9ESUFMT0dfREFUQSkgcHVibGljIGRhdGE6IGFueSwgcHVibGljIHNoYXJlZFNlcnZpY2U6IFNoYXJlZFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzbmFja0JhcjogTWF0U25hY2tCYXIsIHB1YmxpYyBkaWFsb2c6IE1hdERpYWxvZyxcbiAgICBwcml2YXRlIGZiOiBGb3JtQnVpbGRlcikge1xuICAgIHRoaXMucGxhbkRhdGEgPSBkYXRhXG4gIH1cbiAgc2VhcmNoVGV4dCA9ICcnXG4gIGZpbHRlcmRDb3Vyc2VzOiBhbnkgPSBbXVxuICBvcmlnaW5hbERhdGE6IGFueSA9IFtdXG4gIHNlbGVjdEZpbHRlckNvdXJzZXM6IGFueSA9IFtdXG4gIHN1Z2dlc3RlZENvdXJzZXM6IGFueSA9IFtdIC8vIFRyYWNrIGlHT1Qgc3VnZ2VzdGVkIGNvdXJzZXMgc2VwYXJhdGVseVxuICB1c2VyQWRkZWRDb3Vyc2VzOiBhbnkgPSBbXSAvLyBUcmFjayB1c2VyLWFkZGVkIGNvdXJzZXMgc2VwYXJhdGVseVxuICBtb2RlID0gJ2FkZCdcbiAgY2JwX3BsYW5faWQgPSAnJ1xuICBleHBhbmRlZENvbXBldGVuY2llczogYW55ID0ge307IC8vIFRyYWNrIGV4cGFuZGVkIHN0YXRlIGZvciBlYWNoIGNvdXJzZSBhbmQgY29tcGV0ZW5jeSB0eXBlXG4gIG91dGVyVGFiQWN0aXZlSW5kZXggPSAwXG4gIGlubmVyVGFiQWN0aXZlSW5kZXggPSAwXG4gIG91dGVyVGFiQWN0aXZlVGV4dCA9ICdhbGwnXG4gIGlubmVyVGFiQWN0aXZlVGV4dCA9ICdhbGwnXG4gIHNlbGVjdGVkQ2F0ZWdvcnkgPSAnYWxsJztcbiAgY29tcGV0ZW5jeUNvdmVyZWRDb3VudCA9IDBcbiAgb3ZlcmFsbENvdmVyYWdlOmFueSA9IDBcbiAgYmVoYXZpb3JhbENvbXBldGVuY3lDb3ZlcmVkQ291bnQgPSAwXG4gIGJlaGF2aW9yYWxUb3RhbENvbXBldGVuY2llcyA9IDBcbiAgYmVoYXZpb3JhbENvdmVyYWdlOiBhbnkgPSAwXG4gIGZ1bmN0aW9uYWxDb21wZXRlbmN5Q292ZXJlZENvdW50ID0gMFxuICBmdW5jdGlvbmFsVG90YWxDb21wZXRlbmNpZXMgPSAwXG4gIGZ1bmN0aW9uYWxDb3ZlcmFnZTogYW55ID0gMFxuICBkb21haW5Db21wZXRlbmN5Q292ZXJlZENvdW50ID0gMFxuICBkb21haW5Ub3RhbENvbXBldGVuY2llcyA9IDBcbiAgZG9tYWluQ292ZXJhZ2U6IGFueSA9IDBcbiAgY29tcGV0ZW5jeU5vdE1hdGNoZWRCeUNhdGVnb3J5ID0gW11cbiAgY29tcGV0ZW5jeU1hdGNoZWRCeUNhdGVnb3J5ID0gW11cbiAgbWVudUl0ZW1zID0gW1xuICAgIHsga2V5OiAnYWxsJywgbGFiZWw6ICdBbGwgQ2F0ZWdvcmllcycgfSxcbiAgICB7IGtleTogJ2JlaGF2aW9yYWwnLCBsYWJlbDogJ0JlaGF2aW91cmFsJyB9LFxuICAgIHsga2V5OiAnZnVuY3Rpb25hbCcsIGxhYmVsOiAnRnVuY3Rpb25hbCcgfSxcbiAgICB7IGtleTogJ2RvbWFpbicsIGxhYmVsOiAnRG9tYWluJyB9XG4gIF07XG4gIGJlaGF2aW91cmFsTm90TWF0Y2hlZCA9IFtdXG4gIGZ1bmN0aW9uYWxOb3RNYXRjaGVkID0gW11cbiAgZG9tYWluTm90TWF0Y2hlZCA9IFtdXG4gIHNlbGVjdGVkVGhlbWVGaWx0ZXIgPSAnJ1xuICBvcmlnaW5hbEZpbHRlcmVkQ291cnNlcyA9IFtdXG4gIGlzUmVnZW5lcmF0aW5nID0gZmFsc2VcbiAgaXNQREZEb3dubG9hZCA9IGZhbHNlXG4gIGJlaGF2aW91cmFsTWF0Y2hlZCA9IFtdXG4gIGZ1bmN0aW9uYWxNYXRjaGVkID0gW11cbiAgZG9tYWluTWF0Y2hlZCA9IFtdXG4gIGZpbHRlckZvcm0hOiBGb3JtR3JvdXA7XG4gIGNvbXBldGVuY2llc1R5cGU9IFsnQWxsJywnQmVoYXZpb3VyYWwnLCdGdW5jdGlvbmFsJywgJ0RvbWFpbicgXVxuICByYXRpbmdzID0gWyc0LjUgYW5kIGFib3ZlJywgJzQuMCBhbmQgYWJvdmUnLCAnMy41IGFuZCBhYm92ZScsJzIuNSBhbmQgYWJvdmUnLCcxIGFuZCBhYm92ZSddO1xuICBsYW5ndWFnZXMgPSBbJ0VuZ2xpc2gnLCAnSGluZGknLCAnVGFtaWwnLCdLYW5uYWRhJywgJ1RlbHVndScsICdNYWxheWFsYW0nLCAnQXNzYW1lc2UnLCAnQmVuZ2FsaScsICdHdWphcmF0aScsICdNYXJhdGhpJywnT2RpYScsICdQdW5qYWJpJywgJ0tvbmthbmknLCAnQm9kbycsICdEb2dyaScsICdLYXNobWlyaScsICdNYWl0aGlsaScsJ01hbmlwdXJpJywgJ05lcGFsaScsJ1NhbnNrcml0JywnU2FudGFsaScsJ1NpbmRoaScsJ1VyZHUnXTtcbiAgZHVyYXRpb25zID0gWyc8IDEgSG91cicsICcxLTUgSG91cnMnLCAnNSsgSG91cnMnXTtcbiAgcHJvdmlkZXJzID0gW107XG4gIGZpbHRlcmVkQ29tcGV0ZW5jeSA9IFsuLi50aGlzLmNvbXBldGVuY2llc1R5cGVdO1xuICBmaWx0ZXJlZFJhdGluZ3MgPSBbLi4udGhpcy5yYXRpbmdzXTtcbiAgZmlsdGVyZWRMYW5ndWFnZXMgPSBbLi4udGhpcy5sYW5ndWFnZXNdO1xuICBmaWx0ZXJlZER1cmF0aW9ucyA9IFsuLi50aGlzLmR1cmF0aW9uc107XG4gIGZpbHRlcmVkUHJvdmlkZXJzID0gWy4uLnRoaXMucHJvdmlkZXJzXTtcbiAgZnVsbENvdXJzZUxpc3QgPSBbXVxuICAgLy8gU2VsZWN0ZWQgZmlsdGVyc1xuICBzZWxlY3RlZENvbXBldGVuY3kgPSAnQWxsJztcbiAgc2VsZWN0ZWRSYXRpbmc6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBzZWxlY3RlZExhbmd1YWdlOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgc2VsZWN0ZWREdXJhdGlvbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHNlbGVjdGVkUHJvdmlkZXI6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIHNlbGVjdENhdGVnb3J5KGNhdGVnb3J5OiBzdHJpbmcpIHtcbiAgICB0aGlzLnNlbGVjdGVkQ2F0ZWdvcnkgPSBjYXRlZ29yeTtcbiAgICB0aGlzLmdhcEFuYWx5c2lzU3RhdHMoKVxuICB9XG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZmlsdGVyRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgY29tcGV0ZW5jeTogW1tdXSxcbiAgICAgIHJhdGluZzogW1tdXSxcbiAgICAgIGxhbmd1YWdlOiBbW11dLFxuICAgICAgZHVyYXRpb246IFtbXV0sXG4gICAgICBwcm92aWRlcjogW1tdXVxuICAgIH0pO1xuICAgIHRoaXMubG9hZENvbXBvbmVudERhdGEoKTtcbiAgfVxuXG4gIGFwcGx5RmlsdGVyKHZhbHVlOmFueSkge1xuICAgIGNvbnNvbGUubG9nKCd0aGlzLnNlYXJjaFRleHQnLCB2YWx1ZSlcbiAgICB0aGlzLnNlYXJjaFRleHQgPSB2YWx1ZVxuICAgIHRoaXMuZmlsdGVyZENvdXJzZXMgPSB0aGlzLmZpbHRlckRhdGEodGhpcy5zZWFyY2hUZXh0KTtcbiAgfVxuXG4gIHNlYXJjaERhdGEoKSB7XG4gICAgLy8gIHRoaXMuZmlsdGVyZENvdXJzZXMgPSB0aGlzLmZpbHRlckRhdGEodGhpcy5zZWFyY2hUZXh0KTtcbiAgfVxuXG4gIHNlbGVjdGVkRmlsdGVyQ291cnNlcyhldmVudCwgaXRlbSkge1xuICAgIGNvbnNvbGUubG9nKCdldmVudCcsIGV2ZW50KVxuICAgIGNvbnNvbGUubG9nKCdpdGVtJywgaXRlbSlcbiAgICBpZiAoZXZlbnQuY2hlY2tlZCkge1xuICAgICAgaWYodGhpcy5zZWxlY3RGaWx0ZXJDb3Vyc2VzLmluZGV4T2YoaXRlbT8uaWRlbnRpZmllcikgPCAwKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0RmlsdGVyQ291cnNlcy5wdXNoKGl0ZW0/LmlkZW50aWZpZXIpXG4gICAgICB9ICBcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnNlbGVjdEZpbHRlckNvdXJzZXMuZmluZEluZGV4KFxuICAgICAgICBjb250cm9sID0+IGNvbnRyb2wgPT09IGl0ZW0uaWRlbnRpZmllclxuICAgICAgKTtcblxuICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICB0aGlzLnNlbGVjdEZpbHRlckNvdXJzZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc29sZS5sb2coJ3RoaXMuc2VsZWN0RmlsdGVyQ291cnNlcycsIHRoaXMuc2VsZWN0RmlsdGVyQ291cnNlcylcbiAgfVxuXG4gIGNsb3NlRGlhbG9nKCkge1xuICAgIHRoaXMuZGlhbG9nUmVmLmNsb3NlKClcbiAgfVxuXG4gIHNhdmVDb3Vyc2VzKCkge1xuICAgIHRoaXMubG9hZGluZyA9IHRydWVcbiAgICBjb25zb2xlLmxvZygndGhpcy5wbGFuRGF0YScsIHRoaXMucGxhbkRhdGEpXG4gICAgbGV0IHJlcUJvZHkgPSB7XG4gICAgICBcInJvbGVfbWFwcGluZ19pZFwiOiB0aGlzLnBsYW5EYXRhLmlkLFxuICAgICAgXCJyZWNvbW1lbmRlZF9jb3Vyc2VfaWRcIjogdGhpcy5yZWNvbW1lbmRlZF9jb3Vyc2VfaWQsXG4gICAgICBcImNvdXJzZV9pZGVudGlmaWVyc1wiOiB0aGlzLnNlbGVjdEZpbHRlckNvdXJzZXNcbiAgICB9XG4gICAgY29uc29sZS5sb2coJ3JlcUJvZHksICcsIHJlcUJvZHkpXG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2FkZCcpIHtcbiAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5zYXZlQ291cnNlKHJlcUJvZHkpLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgICAvLyBTdWNjZXNzIGhhbmRsaW5nXG4gICAgICAgICAgY29uc29sZS5sb2coJ1N1Y2Nlc3M6JywgcmVzKTtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICAgIHRoaXMuZGlhbG9nUmVmLmNsb3NlKCdzYXZlZCcpXG4gICAgICAgICAgdGhpcy5zbmFja0Jhci5vcGVuKCdDb3Vyc2VzIFNhdmVkIFN1Y2Nlc3NmdWxseScsICdYJywge1xuICAgICAgICAgICAgZHVyYXRpb246IDMwMDAsXG4gICAgICAgICAgICBwYW5lbENsYXNzOiBbJ3NuYWNrYmFyLXN1Y2Nlc3MnXVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIC8vdGhpcy5zdWNjZXNzUm9sZU1hcHBpbmcuZW1pdCh0aGlzLnJvbGVNYXBwaW5nRm9ybSlcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdlcnJvcicsIGVycm9yKVxuICAgICAgICAgIHRoaXMuZGlhbG9nUmVmLmNsb3NlKClcbiAgICAgICAgICAvLyBIYW5kbGUgNDA5IENvbmZsaWN0IGhlcmVcbiAgICAgICAgICAvLyBhbGVydCgnQ29uZmxpY3QgZGV0ZWN0ZWQ6IFRoZSByZXNvdXJjZSBhbHJlYWR5IGV4aXN0cyBvciBhY3Rpb24gY29uZmxpY3RzLicpO1xuICAgICAgICAgIC8vdGhpcy5nZXRcbiAgICAgICAgICAvLyBPciB5b3UgY2FuIHNldCBhIFVJIGVycm9yIG1lc3NhZ2UgdmFyaWFibGVcbiAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oZXJyb3I/LmVycm9yPy5kZXRhaWwsICdYJywge1xuICAgICAgICAgICAgZHVyYXRpb246IDMwMDAsXG4gICAgICAgICAgICBwYW5lbENsYXNzOiBbJ3NuYWNrYmFyLWVycm9yJ11cbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICAgIC8vdGhpcy5hbHJlYWR5QXZhaWxhYmxlUm9sZU1hcHBpbmcuZW1pdCh0aGlzLnJvbGVNYXBwaW5nRm9ybSlcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLmNicF9wbGFuX2lkKSB7XG4gICAgICAgIHRoaXMuc2hhcmVkU2VydmljZS51cGRhdGVDb3Vyc2UocmVxQm9keSwgdGhpcy5jYnBfcGxhbl9pZCkuc3Vic2NyaWJlKHtcbiAgICAgICAgICBuZXh0OiAocmVzKSA9PiB7XG4gICAgICAgICAgICAvLyBTdWNjZXNzIGhhbmRsaW5nXG4gICAgICAgICAgICBjb25zb2xlLmxvZygnU3VjY2VzczonLCByZXMpO1xuICAgICAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2VcbiAgICAgICAgICAgIHRoaXMuZGlhbG9nUmVmLmNsb3NlKCdzYXZlZCcpXG4gICAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oJ0NvdXJzZXMgVXBkYXRlZCBTdWNjZXNzZnVsbHknLCAnWCcsIHtcbiAgICAgICAgICAgICAgZHVyYXRpb246IDMwMDAsXG4gICAgICAgICAgICAgIHBhbmVsQ2xhc3M6IFsnc25hY2tiYXItc3VjY2VzcyddXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vdGhpcy5zdWNjZXNzUm9sZU1hcHBpbmcuZW1pdCh0aGlzLnJvbGVNYXBwaW5nRm9ybSlcbiAgICAgICAgICB9LFxuICAgICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdlcnJvcicsIGVycm9yKVxuICAgICAgICAgICAgdGhpcy5kaWFsb2dSZWYuY2xvc2UoKVxuICAgICAgICAgICAgLy8gSGFuZGxlIDQwOSBDb25mbGljdCBoZXJlXG4gICAgICAgICAgICAvLyBhbGVydCgnQ29uZmxpY3QgZGV0ZWN0ZWQ6IFRoZSByZXNvdXJjZSBhbHJlYWR5IGV4aXN0cyBvciBhY3Rpb24gY29uZmxpY3RzLicpO1xuICAgICAgICAgICAgLy90aGlzLmdldFxuICAgICAgICAgICAgLy8gT3IgeW91IGNhbiBzZXQgYSBVSSBlcnJvciBtZXNzYWdlIHZhcmlhYmxlXG4gICAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oZXJyb3I/LmVycm9yPy5kZXRhaWwsICdYJywge1xuICAgICAgICAgICAgICBkdXJhdGlvbjogMzAwMCxcbiAgICAgICAgICAgICAgcGFuZWxDbGFzczogWydzbmFja2Jhci1lcnJvciddXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlXG4gICAgICAgICAgICAvL3RoaXMuYWxyZWFkeUF2YWlsYWJsZVJvbGVNYXBwaW5nLmVtaXQodGhpcy5yb2xlTWFwcGluZ0Zvcm0pXG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEhhbmRsZSBjYXNlIHdoZW4gY2JwX3BsYW5faWQgaXMgbm90IGF2YWlsYWJsZVxuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICBjb25zb2xlLmVycm9yKCdjYnBfcGxhbl9pZCBpcyBub3QgYXZhaWxhYmxlIGZvciB1cGRhdGUgb3BlcmF0aW9uJyk7XG4gICAgICAgIHRoaXMuc25hY2tCYXIub3BlbignVW5hYmxlIHRvIHVwZGF0ZSBjb3Vyc2VzOiBtaXNzaW5nIHBsYW4gSUQnLCAnWCcsIHtcbiAgICAgICAgICBkdXJhdGlvbjogMzAwMCxcbiAgICAgICAgICBwYW5lbENsYXNzOiBbJ3NuYWNrYmFyLWVycm9yJ11cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICB9XG5cbiAgfVxuXG4gIGdldENvdXJzZXMoKSB7XG4gICAgbGV0IHJvbGVfbWFwcGluZ19pZCA9IHRoaXMucGxhbkRhdGEuaWRcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlXG4gICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmdldENvdXJzZShyb2xlX21hcHBpbmdfaWQpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAocmVzKSA9PiB7XG4gICAgICAgIC8vIFN1Y2Nlc3MgaGFuZGxpbmdcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2VcbiAgICAgICAgY29uc29sZS5sb2coJ3JlcycsIHJlcylcbiAgICAgICAgdGhpcy5jYnBfcGxhbl9pZCA9IHJlcz8uaWRcbiAgICAgICAgaWYgKHJlcyAmJiByZXM/LnNlbGVjdGVkX2NvdXJzZXMgJiYgcmVzPy5zZWxlY3RlZF9jb3Vyc2VzPy5sZW5ndGgpIHtcbiAgICAgICAgICB0aGlzLm1vZGUgPSAnZWRpdCdcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlcz8uc2VsZWN0ZWRfY291cnNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RGaWx0ZXJDb3Vyc2VzLnB1c2gocmVzLnNlbGVjdGVkX2NvdXJzZXNbaV0/LmlkZW50aWZpZXIpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vdGhpcy5zdWNjZXNzUm9sZU1hcHBpbmcuZW1pdCh0aGlzLnJvbGVNYXBwaW5nRm9ybSlcbiAgICAgIH0sXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdlcnJvcicsIGVycm9yKVxuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICAvLyBIYW5kbGUgNDA5IENvbmZsaWN0IGhlcmVcbiAgICAgICAgLy8gYWxlcnQoJ0NvbmZsaWN0IGRldGVjdGVkOiBUaGUgcmVzb3VyY2UgYWxyZWFkeSBleGlzdHMgb3IgYWN0aW9uIGNvbmZsaWN0cy4nKTtcbiAgICAgICAgLy90aGlzLmdldFxuICAgICAgICAvLyBPciB5b3UgY2FuIHNldCBhIFVJIGVycm9yIG1lc3NhZ2UgdmFyaWFibGVcblxuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICAvL3RoaXMuYWxyZWFkeUF2YWlsYWJsZVJvbGVNYXBwaW5nLmVtaXQodGhpcy5yb2xlTWFwcGluZ0Zvcm0pXG4gICAgICB9XG5cblxuICAgIH0pXG4gIH1cbiAgZ2V0U3VnZ2VzdGVkQ291cnNlKCkge1xuICAgIGxldCByb2xlX21hcHBpbmdfaWQgPSB0aGlzLnBsYW5EYXRhLmlkXG4gICAgdGhpcy5sb2FkaW5nID0gdHJ1ZVxuICAgIHRoaXMuc2hhcmVkU2VydmljZS5nZXRTdWdnZXN0ZWRDb3Vyc2VzKHJvbGVfbWFwcGluZ19pZCkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgLy8gU3VjY2VzcyBoYW5kbGluZ1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICBjb25zb2xlLmxvZygnZ2V0U3VnZ2VzdGVkQ291cnNlcyByZXMnLCByZXMpXG4gICAgICAgIGNvbnNvbGUubG9nKCd0aGlzLmZpbHRlcmRDb3Vyc2VzJywgdGhpcy5maWx0ZXJkQ291cnNlcylcbiAgICAgICAgLy8gU3RvcmUgc3VnZ2VzdGVkIGNvdXJzZXMgc2VwYXJhdGVseVxuICAgICAgICB0aGlzLnN1Z2dlc3RlZENvdXJzZXMgPSBbLi4ucmVzXTtcbiAgICAgICAgXG4gICAgICAgIC8vIFJlYnVpbGQgZmlsdGVyZENvdXJzZXMgdG8gaW5jbHVkZSBhbGwgY291cnNlIHR5cGVzXG4gICAgICAgIHRoaXMucmVidWlsZEZpbHRlcmVkQ291cnNlcygpO1xuICAgICAgICBcbiAgICAgICAgLy8gVXBkYXRlIGdhcCBhbmFseXNpcyBzdGF0cyBhZnRlciBzdWdnZXN0ZWQgY291cnNlcyBhcmUgYWRkZWRcbiAgICAgICAgdGhpcy51cGRhdGVHYXBBbmFseXNpc0FmdGVyQ291cnNlc1VwZGF0ZSgpXG4gICAgICAgIC8vdGhpcy5zdWNjZXNzUm9sZU1hcHBpbmcuZW1pdCh0aGlzLnJvbGVNYXBwaW5nRm9ybSlcbiAgICAgIH0sXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdlcnJvcicsIGVycm9yKVxuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDEpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnVW5hdXRob3JpemVkIGFjY2VzcyAtIHVzZXIgd2lsbCBiZSByZWRpcmVjdGVkIHRvIGxvZ2luJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gSGFuZGxlIG90aGVyIGVycm9ycyBncmFjZWZ1bGx5XG4gICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgc3VnZ2VzdGVkIGNvdXJzZXMnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBPciB5b3UgY2FuIHNldCBhIFVJIGVycm9yIG1lc3NhZ2UgdmFyaWFibGVcblxuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICAvL3RoaXMuYWxyZWFkeUF2YWlsYWJsZVJvbGVNYXBwaW5nLmVtaXQodGhpcy5yb2xlTWFwcGluZ0Zvcm0pXG4gICAgICB9XG5cblxuICAgIH0pXG4gIH1cblxuICBnZXRVc2VyQ291cnNlKCkge1xuICAgIGxldCByb2xlX21hcHBpbmdfaWQgPSB0aGlzLnBsYW5EYXRhLmlkXG4gICAgdGhpcy5sb2FkaW5nID0gdHJ1ZVxuICAgIHRoaXMuc2hhcmVkU2VydmljZS5nZXRVc2VyQ291cnNlKHJvbGVfbWFwcGluZ19pZCkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgLy8gU3VjY2VzcyBoYW5kbGluZ1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZVxuICAgICAgICBjb25zb2xlLmxvZygnZ2V0VXNlckNvdXJzZSBBUEkgcmVzcG9uc2U6JywgcmVzKVxuICAgICAgICBjb25zb2xlLmxvZygnQ3VycmVudCBmaWx0ZXJkQ291cnNlcyBiZWZvcmUgYWRkaW5nIHVzZXIgY291cnNlczonLCB0aGlzLmZpbHRlcmRDb3Vyc2VzKVxuICAgICAgICBcbiAgICAgICAgLy8gU3RvcmUgdXNlci1hZGRlZCBjb3Vyc2VzIHNlcGFyYXRlbHkgKHJlc2V0IHRvIGF2b2lkIGR1cGxpY2F0ZXMpXG4gICAgICAgIHRoaXMudXNlckFkZGVkQ291cnNlcyA9IFsuLi5yZXNdO1xuICAgICAgICBcbiAgICAgICAgLy8gUHJvY2VzcyB1c2VyLWFkZGVkIGNvdXJzZXMgdG8gZW5zdXJlIHByb3BlciBzdHJ1Y3R1cmVcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjb25zdCB1c2VyQ291cnNlID0gcmVzW2ldO1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBVc2VyIGNvdXJzZSAke2l9IGNvbXBldGVuY2llczpgLCB1c2VyQ291cnNlLmNvbXBldGVuY2llcyk7XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gRW5zdXJlIHVzZXItYWRkZWQgY291cnNlcyBoYXZlIHRoZSBleHBlY3RlZCBzdHJ1Y3R1cmUgZm9yIGRpc3BsYXlcbiAgICAgICAgICBpZiAodXNlckNvdXJzZSAmJiAhdXNlckNvdXJzZS5jb3Vyc2VfdHlwZSkge1xuICAgICAgICAgICAgdXNlckNvdXJzZS5jb3Vyc2VfdHlwZSA9ICdVc2VyIEFkZGVkJztcbiAgICAgICAgICB9XG4gICAgICAgICAgXG4gICAgICAgICAgLy8gQWRkIGlkZW50aWZpZXIgaWYgbWlzc2luZyAobmVlZGVkIGZvciBjb3Vyc2Ugc2VsZWN0aW9uIGxvZ2ljKVxuICAgICAgICAgIGlmICh1c2VyQ291cnNlICYmICF1c2VyQ291cnNlLmlkZW50aWZpZXIpIHtcbiAgICAgICAgICAgIHVzZXJDb3Vyc2UuaWRlbnRpZmllciA9IHVzZXJDb3Vyc2UuaWQgfHwgYHVzZXJfY291cnNlXyR7aX1fJHtEYXRlLm5vdygpfWA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBSZWJ1aWxkIGZpbHRlcmRDb3Vyc2VzIHRvIGluY2x1ZGUgYWxsIGNvdXJzZSB0eXBlc1xuICAgICAgICB0aGlzLnJlYnVpbGRGaWx0ZXJlZENvdXJzZXMoKTtcbiAgICAgICAgXG4gICAgICAgIGNvbnNvbGUubG9nKCdmaWx0ZXJkQ291cnNlcyBhZnRlciBhZGRpbmcgdXNlciBjb3Vyc2VzOicsIHRoaXMuZmlsdGVyZENvdXJzZXMpO1xuICAgICAgICAvL3RoaXMuc3VjY2Vzc1JvbGVNYXBwaW5nLmVtaXQodGhpcy5yb2xlTWFwcGluZ0Zvcm0pXG4gICAgICB9LFxuICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZygnZXJyb3InLCBlcnJvcilcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2VcbiAgICAgICAgLy8gSGFuZGxlIDQwOSBDb25mbGljdCBoZXJlXG4gICAgICAgIC8vIGFsZXJ0KCdDb25mbGljdCBkZXRlY3RlZDogVGhlIHJlc291cmNlIGFscmVhZHkgZXhpc3RzIG9yIGFjdGlvbiBjb25mbGljdHMuJyk7XG4gICAgICAgIC8vdGhpcy5nZXRcbiAgICAgICAgLy8gT3IgeW91IGNhbiBzZXQgYSBVSSBlcnJvciBtZXNzYWdlIHZhcmlhYmxlXG5cbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2VcbiAgICAgICAgLy90aGlzLmFscmVhZHlBdmFpbGFibGVSb2xlTWFwcGluZy5lbWl0KHRoaXMucm9sZU1hcHBpbmdGb3JtKVxuICAgICAgfVxuXG5cbiAgICB9KVxuICB9XG5cbiAgY2hlY2tJZkNvdXJzZUV4aXN0cyhpdGVtKSB7XG4gICAgbGV0IGZsYWcgPSBmYWxzZVxuICAgIGlmICh0aGlzLnNlbGVjdEZpbHRlckNvdXJzZXMuaW5kZXhPZihpdGVtPy5pZGVudGlmaWVyKSA+IC0xKSB7XG4gICAgICBmbGFnID0gdHJ1ZVxuICAgIH1cbiAgICByZXR1cm4gZmxhZ1xuICB9XG5cbiAgc2VsZWN0QWxsQ291cnNlcyhldmVudCkge1xuICAgIGlmIChldmVudC5jaGVja2VkKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZmlsdGVyZENvdXJzZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5zZWxlY3RGaWx0ZXJDb3Vyc2VzLnB1c2godGhpcy5maWx0ZXJkQ291cnNlc1tpXS5pZGVudGlmaWVyKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNlbGVjdEZpbHRlckNvdXJzZXMgPSBbXVxuICAgICAgXG4gICAgfVxuICAgIGlmKHRoaXMuY2JwX3BsYW5faWQpIHtcbiAgICAgIHRoaXMubW9kZSA9ICd1cGRhdGUnXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubW9kZSA9ICdhZGQnXG4gICAgfVxuXG5cbiAgfVxuICBnZXRTZWN0b3JzKHNlY3Rvcikge1xuICAgIGlmIChzZWN0b3IgJiYgc2VjdG9yLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoc2VjdG9yKSA/IHNlY3Rvci5qb2luKCcvICcpIDogJydcbiAgICB9XG5cbiAgfVxuXG4gIGZpbHRlckRhdGEoc2VhcmNoVGV4dDogc3RyaW5nKTogYW55W10ge1xuICAgIGNvbnN0IGZpbHRlciA9IHNlYXJjaFRleHQudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICByZXR1cm4gdGhpcy5vcmlnaW5hbERhdGEuZmlsdGVyKGl0ZW0gPT4ge1xuICAgICAgY29uc3Qgc3RyaW5naWZpZWQgPSB0aGlzLmZsYXR0ZW5PYmplY3RUb1N0cmluZyhpdGVtKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgcmV0dXJuIHN0cmluZ2lmaWVkLmluY2x1ZGVzKGZpbHRlcik7XG4gICAgfSk7XG4gIH1cblxuICBmbGF0dGVuT2JqZWN0VG9TdHJpbmcob2JqOiBhbnkpOiBzdHJpbmcge1xuICAgIGxldCByZXN1bHQgPSAnJztcblxuICAgIGZvciAoY29uc3Qga2V5IGluIG9iaikge1xuICAgICAgY29uc3QgdmFsdWUgPSBvYmpba2V5XTtcblxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmVzdWx0ICs9ICcgJyArIHZhbHVlO1xuICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICB2YWx1ZS5mb3JFYWNoKHZhbCA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXN1bHQgKz0gJyAnICsgdmFsO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJlc3VsdCArPSAnICcgKyB0aGlzLmZsYXR0ZW5PYmplY3RUb1N0cmluZyh2YWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgcmVzdWx0ICs9ICcgJyArIHRoaXMuZmxhdHRlbk9iamVjdFRvU3RyaW5nKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc3VnZ2VzdE1vcmVDb3Vyc2VzKCkge1xuICAgIC8vIHRoaXMuZGlhbG9nUmVmLmNsb3NlKClcbiAgICBjb25zdCBkaWFsb2dSZWZOZXcgPSB0aGlzLmRpYWxvZy5vcGVuKFN1Z2dlc3RNb3JlQ291cnNlc0NvbXBvbmVudCwge1xuICAgICAgd2lkdGg6ICcxMDAwcHgnLFxuICAgICAgZGF0YTogeyByZWNvbW1lbmRlZF9jb3Vyc2VfaWQ6IHRoaXMucmVjb21tZW5kZWRfY291cnNlX2lkLCByb2xlX21hcHBpbmdfaWQ6IHRoaXMucGxhbkRhdGEuaWQgfSxcbiAgICAgIHBhbmVsQ2xhc3M6ICd2aWV3LWNicC1wbGFuLXBvcHVwJyxcbiAgICAgIG1pbkhlaWdodDogJzQwMHB4JywgICAgICAgICAgLy8gU2V0IG1pbmltdW0gaGVpZ2h0XG4gICAgICBtYXhIZWlnaHQ6ICc5MHZoJywgICAgICAgICAgIC8vIFByZXZlbnQgaXQgZnJvbSBnb2luZyBiZXlvbmQgdmlld3BvcnRcbiAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSAvLyBPcHRpb25hbDogcHJldmVudCBjbG9zaW5nIHdpdGggb3V0c2lkZSBjbGlja1xuICAgIH0pO1xuXG4gICAgZGlhbG9nUmVmTmV3LmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0ID09PSAnc2F2ZWQnKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdDaGFuZ2VzIHNhdmVkIScpO1xuICAgICAgICAvLyBSZWZyZXNoIGRhdGEgb3Igc2hvdyBhIHRvYXN0IGhlcmVcbiAgICAgICAgdGhpcy5nZXRTdWdnZXN0ZWRDb3Vyc2UoKVxuICAgICAgfSAgZWxzZSB7XG4gICAgICAgIHRoaXMuZ2V0U3VnZ2VzdGVkQ291cnNlKClcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGdlbmVyYXRlQ291cnNlUmVjb21tZW5kYXRpb24oZWxlbWVudDogYW55KSB7XG4gICAgY29uc29sZS5sb2coJ0dlbmVyYXRlIENvdXJzZSBSZWNvbW1lbmRhdGlvbiBjbGlja2VkJywgZWxlbWVudCk7XG4gICAgLy8gdGhpcy5hY3RpdmVSb3dFbGVtZW50ID0gZWxlbWVudFxuICAgIGNvbnNvbGUubG9nKCdFZGl0IFJvbGUgTWFwcGluZyBjbGlja2VkJywgZWxlbWVudCk7XG4gICAgLy8gTmF2aWdhdGUgb3Igb3BlbiBtb2RhbFxuICAgIGNvbnNvbGUubG9nKCdWaWV3IENCUCBQbGFuIGNsaWNrZWQnLCBlbGVtZW50KTtcbiAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKEdlbmVyYXRlQ291cnNlUmVjb21tZW5kYXRpb25Db21wb25lbnQsIHtcbiAgICAgIHdpZHRoOiAnMTAwMHB4JyxcbiAgICAgIGRhdGE6IGVsZW1lbnQsXG4gICAgICAgcGFuZWxDbGFzczogJ3ZpZXctY2JwLXBsYW4tcG9wdXAnLFxuICAgICAgbWluSGVpZ2h0OiAnNDAwcHgnLCAgICAgICAgICAvLyBTZXQgbWluaW11bSBoZWlnaHRcbiAgICAgIG1heEhlaWdodDogJzkwdmgnLCAgICAgICAgICAgLy8gUHJldmVudCBpdCBmcm9tIGdvaW5nIGJleW9uZCB2aWV3cG9ydFxuICAgICAgZGlzYWJsZUNsb3NlOiB0cnVlIC8vIE9wdGlvbmFsOiBwcmV2ZW50IGNsb3Npbmcgd2l0aCBvdXRzaWRlIGNsaWNrXG4gICAgfSk7XG4gIFxuICAgIGRpYWxvZ1JlZi5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShyZXN1bHQgPT4ge1xuICAgICAgaWYgKHJlc3VsdCA9PT0gJ3NhdmVkJykge1xuICAgICAgICBjb25zb2xlLmxvZygnQ2hhbmdlcyBzYXZlZCEnKTtcbiAgICAgICAgLy8gUmVmcmVzaCBkYXRhIG9yIHNob3cgYSB0b2FzdCBoZXJlXG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMuc2hhcmVkU2VydmljZS5jYnBQbGFuRmluYWxPYmopXG4gICAgICAgIGlmKHRoaXMuc2hhcmVkU2VydmljZS5jYnBQbGFuRmluYWxPYmogJiYgdGhpcy5zaGFyZWRTZXJ2aWNlLmNicFBsYW5GaW5hbE9iai5taW5pc3RyeSAmJiB0aGlzLnNoYXJlZFNlcnZpY2UuY2JwUGxhbkZpbmFsT2JqLm1pbmlzdHJ5LmlkKSB7XG4gICAgICAgICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmdldFJvbGVNYXBwaW5nQnlTdGF0ZUNlbnRlcih0aGlzLnNoYXJlZFNlcnZpY2UuY2JwUGxhbkZpbmFsT2JqLm1pbmlzdHJ5LmlkKS5zdWJzY3JpYmUoKHJlcyk9PntcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdyZXMnLCByZXMpXG4gICAgICAgICAgICAvLyB0aGlzLmRhdGFTb3VyY2UuZGF0YSA9IHJlc1xuICAgICAgICAgICAgLy8gdGhpcy5kYXRhU291cmNlLnBhZ2luYXRvciA9IHRoaXMucGFnaW5hdG9yO1xuICAgICAgICAgICAgdGhpcy5vcmlnaW5hbERhdGEgPSByZXM7XG4gICAgICAgICAgLy8gIGNvbnNvbGUubG9nKCd0aGlzLmRhdGFTb3VyY2UnLHRoaXMuZGF0YVNvdXJjZSlcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBnZXRDb21wZXRlbmNpZXNCeVR5cGUodHlwZTogc3RyaW5nLCBpbmRleCk6IGFueVtdIHtcbiAgICBjb25zdCBjb3Vyc2UgPSB0aGlzLmZpbHRlcmRDb3Vyc2VzW2luZGV4XTtcbiAgICBpZiAoIWNvdXJzZSkge1xuICAgICAgY29uc29sZS5sb2coYE5vIGNvdXJzZSBmb3VuZCBhdCBpbmRleCAke2luZGV4fWApO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBcbiAgICAvLyBIYW5kbGUgZGlmZmVyZW50IGNvbXBldGVuY3kgcHJvcGVydHkgbmFtZXNcbiAgICAvLyBBSSBSZWNvbW1lbmRlZCAmIFB1YmxpYyBjb3Vyc2VzIHVzZSAnY29tcGV0ZW5jaWVzJ1xuICAgIC8vIE1hbnVhbGx5IFN1Z2dlc3RlZCAtIGlHT1QgY291cnNlcyB1c2UgJ2NvbXBldGVuY2llc192NidcbiAgICAvLyBVc2VyIEFkZGVkIGNvdXJzZXMgdXNlICdjb21wZXRlbmNpZXMnXG4gICAgbGV0IGNvbXBldGVuY2llcyA9IFtdO1xuICAgIGlmIChjb3Vyc2UuY29tcGV0ZW5jaWVzICYmIEFycmF5LmlzQXJyYXkoY291cnNlLmNvbXBldGVuY2llcykpIHtcbiAgICAgIGNvbXBldGVuY2llcyA9IGNvdXJzZS5jb21wZXRlbmNpZXM7XG4gICAgLy8gIGNvbnNvbGUubG9nKGBDb3Vyc2UgJHtpbmRleH0gKCR7Y291cnNlLmNvdXJzZV90eXBlIHx8IGNvdXJzZS5uYW1lIHx8ICdVbmtub3duJ30pIHVzaW5nICdjb21wZXRlbmNpZXMnIHByb3BlcnR5OmAsIGNvbXBldGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChjb3Vyc2UuY29tcGV0ZW5jaWVzX3Y2ICYmIEFycmF5LmlzQXJyYXkoY291cnNlLmNvbXBldGVuY2llc192NikpIHtcbiAgICAgIGNvbXBldGVuY2llcyA9IGNvdXJzZS5jb21wZXRlbmNpZXNfdjY7XG4gICAgIC8vIGNvbnNvbGUubG9nKGBDb3Vyc2UgJHtpbmRleH0gKCR7Y291cnNlLmNvdXJzZV90eXBlIHx8IGNvdXJzZS5uYW1lIHx8ICdVbmtub3duJ30pIHVzaW5nICdjb21wZXRlbmNpZXNfdjYnIHByb3BlcnR5OmAsIGNvbXBldGVuY2llcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGNvbnNvbGUubG9nKGBDb3Vyc2UgJHtpbmRleH0gKCR7Y291cnNlLmNvdXJzZV90eXBlIHx8IGNvdXJzZS5uYW1lIHx8ICdVbmtub3duJ30pIGhhcyBubyB2YWxpZCBjb21wZXRlbmNpZXMgcHJvcGVydHk6YCwge1xuICAgICAgLy8gICBoYXNDb21wZXRlbmNpZXM6ICEhY291cnNlLmNvbXBldGVuY2llcyxcbiAgICAgIC8vICAgY29tcGV0ZW5jaWVzVHlwZTogdHlwZW9mIGNvdXJzZS5jb21wZXRlbmNpZXMsXG4gICAgICAvLyAgIGhhc0NvbXBldGVuY2llc1Y2OiAhIWNvdXJzZS5jb21wZXRlbmNpZXNfdjYsXG4gICAgICAvLyAgIGNvbXBldGVuY2llc1Y2VHlwZTogdHlwZW9mIGNvdXJzZS5jb21wZXRlbmNpZXNfdjYsXG4gICAgICAvLyAgIGNvdXJzZUtleXM6IE9iamVjdC5rZXlzKGNvdXJzZSlcbiAgICAgIC8vIH0pO1xuICAgIH1cbiAgICBcbiAgICBpZiAoY29tcGV0ZW5jaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vICBjb25zb2xlLmxvZyhgTm8gY29tcGV0ZW5jaWVzIGZvdW5kIGZvciBjb3Vyc2UgJHtpbmRleH0gYW5kIHR5cGUgJHt0eXBlfWApO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBcbiAgICAvLyBOb3JtYWxpemUgdGhlIHR5cGUgZm9yIGNvbXBhcmlzb24gKGNhc2UtaW5zZW5zaXRpdmUgKyBoYW5kbGUgc3BlbGxpbmcgdmFyaWF0aW9ucylcbiAgICBjb25zdCBub3JtYWxpemVkVHlwZSA9IHR5cGUudG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgXG4gICAgY29uc3QgbWF0Y2hlZENvbXBldGVuY2llcyA9IGNvbXBldGVuY2llcy5maWx0ZXIoYyA9PiB7XG4gICAgICBpZiAoIWMgfHwgIWMuY29tcGV0ZW5jeUFyZWFOYW1lKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBJbnZhbGlkIGNvbXBldGVuY3kgc3RydWN0dXJlIGluIGNvdXJzZSAke2luZGV4fTpgLCBjKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb25zdCBjb21wZXRlbmN5QXJlYSA9IGMuY29tcGV0ZW5jeUFyZWFOYW1lLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgXG4gICAgICAvLyBIYW5kbGUgYm90aCBcImJlaGF2aW9yYWxcIiBhbmQgXCJiZWhhdmlvdXJhbFwiIHNwZWxsaW5nc1xuICAgICAgaWYgKG5vcm1hbGl6ZWRUeXBlID09PSAnYmVoYXZpb3VyYWwnIHx8IG5vcm1hbGl6ZWRUeXBlID09PSAnYmVoYXZpb3JhbCcpIHtcbiAgICAgICAgcmV0dXJuIGNvbXBldGVuY3lBcmVhID09PSAnYmVoYXZpb3JhbCcgfHwgY29tcGV0ZW5jeUFyZWEgPT09ICdiZWhhdmlvdXJhbCc7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEZvciBvdGhlciB0eXBlcywgZG8gY2FzZS1pbnNlbnNpdGl2ZSBjb21wYXJpc29uXG4gICAgICByZXR1cm4gY29tcGV0ZW5jeUFyZWEgPT09IG5vcm1hbGl6ZWRUeXBlO1xuICAgIH0pO1xuICAgIFxuICAgLy8gY29uc29sZS5sb2coYEZvdW5kICR7bWF0Y2hlZENvbXBldGVuY2llcy5sZW5ndGh9IGNvbXBldGVuY2llcyBvZiB0eXBlICR7dHlwZX0gZm9yIGNvdXJzZSAke2luZGV4fTpgLCBtYXRjaGVkQ29tcGV0ZW5jaWVzKTtcbiAgICByZXR1cm4gbWF0Y2hlZENvbXBldGVuY2llcztcbiAgfVxuXG4gIGdldENvbXBldGVuY2llc0J5QmVodmlvdXJhbFR5cGUoaW5kZXgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvdXJzZSA9IHRoaXMuZmlsdGVyZENvdXJzZXNbaW5kZXhdO1xuICAgIGlmICghY291cnNlKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIFxuICAgIC8vIEhhbmRsZSBkaWZmZXJlbnQgY29tcGV0ZW5jeSBwcm9wZXJ0eSBuYW1lc1xuICAgIGxldCBjb21wZXRlbmNpZXMgPSBbXTtcbiAgICBpZiAoY291cnNlLmNvbXBldGVuY2llcyAmJiBBcnJheS5pc0FycmF5KGNvdXJzZS5jb21wZXRlbmNpZXMpKSB7XG4gICAgICBjb21wZXRlbmNpZXMgPSBjb3Vyc2UuY29tcGV0ZW5jaWVzO1xuICAgIH0gZWxzZSBpZiAoY291cnNlLmNvbXBldGVuY2llc192NiAmJiBBcnJheS5pc0FycmF5KGNvdXJzZS5jb21wZXRlbmNpZXNfdjYpKSB7XG4gICAgICBjb21wZXRlbmNpZXMgPSBjb3Vyc2UuY29tcGV0ZW5jaWVzX3Y2O1xuICAgIH1cbiAgICBcbiAgICBpZiAoY29tcGV0ZW5jaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gY29tcGV0ZW5jaWVzXG4gICAgICAuZmlsdGVyKGMgPT4gYyAmJiAoYy5jb21wZXRlbmN5QXJlYU5hbWUgPT09ICdCZWhhdmlvcmFsJyB8fCBjLmNvbXBldGVuY3lBcmVhTmFtZSA9PT0gJ0JlaGF2aW91cmFsJykpXG4gICAgICAubWFwKGMgPT4gYCR7Yy5jb21wZXRlbmN5VGhlbWVOYW1lIHx8ICcnfSAtICR7Yy5jb21wZXRlbmN5U3ViVGhlbWVOYW1lIHx8ICcnfWApXG4gICAgICAuam9pbignLCAnKTtcbiAgfVxuXG4gIGdldERpc3BsYXllZENvbXBldGVuY2llcyh0eXBlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpOiBhbnlbXSB7XG4gICAgY29uc3QgY29tcGV0ZW5jaWVzID0gdGhpcy5nZXRDb21wZXRlbmNpZXNCeVR5cGUodHlwZSwgaW5kZXgpO1xuICAgIGNvbnN0IGtleSA9IGAke2luZGV4fS0ke3R5cGV9YDtcblxuICAgIGlmICh0aGlzLmV4cGFuZGVkQ29tcGV0ZW5jaWVzW2tleV0pIHtcbiAgICAgIHJldHVybiBjb21wZXRlbmNpZXM7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbXBldGVuY2llcy5zbGljZSgwLCAyKTtcbiAgfVxuXG4gIHRvZ2dsZUNvbXBldGVuY2llcyh0eXBlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBrZXkgPSBgJHtpbmRleH0tJHt0eXBlfWA7XG4gICAgdGhpcy5leHBhbmRlZENvbXBldGVuY2llc1trZXldID0gIXRoaXMuZXhwYW5kZWRDb21wZXRlbmNpZXNba2V5XTtcbiAgfVxuXG4gIGlzRXhwYW5kZWQodHlwZTogc3RyaW5nLCBpbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3Qga2V5ID0gYCR7aW5kZXh9LSR7dHlwZX1gO1xuICAgIHJldHVybiB0aGlzLmV4cGFuZGVkQ29tcGV0ZW5jaWVzW2tleV0gfHwgZmFsc2U7XG4gIH1cblxuICBoYXNNb3JlVGhhblR3byh0eXBlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nZXRDb21wZXRlbmNpZXNCeVR5cGUodHlwZSwgaW5kZXgpLmxlbmd0aCA+IDI7XG4gIH1cblxuICBnZXRSZW1haW5pbmdDb3VudCh0eXBlOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHRvdGFsQ291bnQgPSB0aGlzLmdldENvbXBldGVuY2llc0J5VHlwZSh0eXBlLCBpbmRleCkubGVuZ3RoO1xuICAgIHJldHVybiB0b3RhbENvdW50IC0gMjtcbiAgfVxuXG4gIG9uT3V0ZXJUYWJDaGFuZ2UoZXZlbnQ6IE1hdFRhYkNoYW5nZUV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5vdXRlclRhYkFjdGl2ZUluZGV4ID0gZXZlbnQuaW5kZXhcbiAgICB0aGlzLm91dGVyVGFiQWN0aXZlVGV4dCA9IGV2ZW50LnRhYi50ZXh0TGFiZWxcbiAgICBjb25zb2xlLmxvZygnT3V0ZXIgVGFiIEluZGV4OicsIGV2ZW50LmluZGV4KTtcbiAgICBjb25zb2xlLmxvZygnT3V0ZXIgVGFiIExhYmVsOicsIGV2ZW50LnRhYi50ZXh0TGFiZWwpO1xuICAgIGlmKGV2ZW50LmluZGV4ID09PSAxKSB7XG4gICAgICB0aGlzLmdhcEFuYWx5c2lzU3RhdHMoKVxuICAgIH1cbiAgICBpZihldmVudC5pbmRleCA9PT0gMCkge1xuICAgICAgLy8gdGhpcy5nZXRDb3Vyc2VzKClcbiAgICAgIC8vIHRoaXMuZ2V0U3VnZ2VzdGVkQ291cnNlKClcbiAgICAgIHRoaXMuZ2V0VXNlckNvdXJzZSgpXG4gICAgfVxuICB9XG5cbiAgb25Jbm5lclRhYkNoYW5nZShldmVudDogTWF0VGFiQ2hhbmdlRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmlubmVyVGFiQWN0aXZlSW5kZXggPSBldmVudC5pbmRleFxuICAgIHRoaXMuaW5uZXJUYWJBY3RpdmVUZXh0ID0gZXZlbnQudGFiLnRleHRMYWJlbFxuICAgIHRoaXMuc2VsZWN0ZWRUaGVtZUZpbHRlciA9ICcnOyAvLyBSZXNldCB0aGVtZSBmaWx0ZXIgd2hlbiBzd2l0Y2hpbmcgdGFic1xuICAgIGNvbnNvbGUubG9nKCdJbm5lciBUYWIgSW5kZXg6JywgZXZlbnQuaW5kZXgpO1xuICAgIGNvbnNvbGUubG9nKCdJbm5lciBUYWIgTGFiZWw6JywgZXZlbnQudGFiLnRleHRMYWJlbCk7XG4gICAgbGV0IHRhYkluZGV4ID0gZXZlbnQuaW5kZXhcbiAgICB0aGlzLmNvbXBldGVuY3lNYXRjaGVkQnlDYXRlZ29yeSA9IFtdXG4gICAgXG4gICAgLy8gR2V0IGFsbCBhdmFpbGFibGUgY291cnNlcyAob3JpZ2luYWwgKyBzdWdnZXN0ZWQgKyB1c2VyIGFkZGVkKVxuICAgIGNvbnN0IGFsbEF2YWlsYWJsZUNvdXJzZXMgPSB0aGlzLmdldEFsbEF2YWlsYWJsZUNvdXJzZXMoKTtcblxuXG4gICAgXG4gICAgc3dpdGNoICh0YWJJbmRleCkge1xuICAgICAgY2FzZSAwOiAvLyBBbGxcbiAgICAgICAgdGhpcy5maWx0ZXJkQ291cnNlcyA9IGFsbEF2YWlsYWJsZUNvdXJzZXM7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxOiAvLyBCZWhhdmlvcmFsXG4gICAgICAgIHRoaXMuZmlsdGVyZENvdXJzZXMgPSB0aGlzLmJlaGF2aW9yYWxGaWx0ZXIoYWxsQXZhaWxhYmxlQ291cnNlcyk7XG4gICAgICAgIHRoaXMuY29tcGV0ZW5jeU1hdGNoZWRCeUNhdGVnb3J5ID0gdGhpcy5iZWhhdmlvcmFsQ29tcGV0ZW5jeUZpbHRlcih0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOiAvLyBGdW5jdGlvbmFsXG4gICAgICAgIHRoaXMuZmlsdGVyZENvdXJzZXMgPSB0aGlzLmZ1bmN0aW9uYWxGaWx0ZXIoYWxsQXZhaWxhYmxlQ291cnNlcyk7XG4gICAgICAgIHRoaXMuY29tcGV0ZW5jeU1hdGNoZWRCeUNhdGVnb3J5ID0gdGhpcy5mdW5jdGlvbmFsQ29tcGV0ZW5jeUZpbHRlcih0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzOiAvLyBEb21haW5cbiAgICAgICAgdGhpcy5maWx0ZXJkQ291cnNlcyA9IHRoaXMuZG9tYWluRmlsdGVyKGFsbEF2YWlsYWJsZUNvdXJzZXMpO1xuICAgICAgICB0aGlzLmNvbXBldGVuY3lNYXRjaGVkQnlDYXRlZ29yeSA9IHRoaXMuZG9tYWluQ29tcGV0ZW5jeUZpbHRlcih0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZygndGhpcy5maWx0ZXJkQ291cnNlcycsdGhpcy5maWx0ZXJkQ291cnNlcylcbiAgICBjb25zb2xlLmxvZygndGhpcy5jb21wZXRlbmN5TWF0Y2hlZEJ5Q2F0ZWdvcnknLHRoaXMuY29tcGV0ZW5jeU1hdGNoZWRCeUNhdGVnb3J5KVxuICB9XG4gIFxuICBnZXRBbGxBdmFpbGFibGVDb3Vyc2VzKCkge1xuICAgIC8vIFN0YXJ0IHdpdGggb3JpZ2luYWwgZGF0YSAoQUkgcmVjb21tZW5kZWQgY291cnNlcylcbiAgICBjb25zdCBhbGxDb3Vyc2VzID0gWy4uLnRoaXMub3JpZ2luYWxEYXRhXTtcbiAgICBjb25zdCBzZWVuSWRlbnRpZmllcnMgPSBuZXcgU2V0KCk7XG4gICAgXG4gICAgLy8gVHJhY2sgb3JpZ2luYWwgY291cnNlIGlkZW50aWZpZXJzXG4gICAgdGhpcy5vcmlnaW5hbERhdGEuZm9yRWFjaChjb3Vyc2UgPT4ge1xuICAgICAgaWYgKGNvdXJzZS5pZGVudGlmaWVyKSBzZWVuSWRlbnRpZmllcnMuYWRkKGNvdXJzZS5pZGVudGlmaWVyKTtcbiAgICAgIGlmIChjb3Vyc2UuaWQpIHNlZW5JZGVudGlmaWVycy5hZGQoY291cnNlLmlkKTtcbiAgICB9KTtcbiAgICBcbiAgICAvLyBBZGQgc3VnZ2VzdGVkIGNvdXJzZXMgKGlHT1QgcGxhdGZvcm0gY291cnNlcylcbiAgICB0aGlzLnN1Z2dlc3RlZENvdXJzZXMuZm9yRWFjaChjb3Vyc2UgPT4ge1xuICAgICAgY29uc3QgY291cnNlSWQgPSBjb3Vyc2UuaWRlbnRpZmllciB8fCBjb3Vyc2UuaWQ7XG4gICAgICBpZiAoY291cnNlSWQgJiYgIXNlZW5JZGVudGlmaWVycy5oYXMoY291cnNlSWQpKSB7XG4gICAgICAgIGFsbENvdXJzZXMucHVzaChjb3Vyc2UpO1xuICAgICAgICBzZWVuSWRlbnRpZmllcnMuYWRkKGNvdXJzZUlkKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICAvLyBBZGQgdXNlci1hZGRlZCBjb3Vyc2VzXG4gICAgdGhpcy51c2VyQWRkZWRDb3Vyc2VzLmZvckVhY2goY291cnNlID0+IHtcbiAgICAgIGNvbnN0IGNvdXJzZUlkID0gY291cnNlLmlkZW50aWZpZXIgfHwgY291cnNlLmlkO1xuICAgICAgaWYgKGNvdXJzZUlkICYmICFzZWVuSWRlbnRpZmllcnMuaGFzKGNvdXJzZUlkKSkge1xuICAgICAgICAvLyBFbnN1cmUgdXNlci1hZGRlZCBjb3Vyc2VzIGhhdmUgcHJvcGVyIHN0cnVjdHVyZVxuICAgICAgICBpZiAoIWNvdXJzZS5jb3Vyc2VfdHlwZSkge1xuICAgICAgICAgIGNvdXJzZS5jb3Vyc2VfdHlwZSA9ICdVc2VyIEFkZGVkJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvdXJzZS5pZGVudGlmaWVyICYmIGNvdXJzZS5pZCkge1xuICAgICAgICAgIGNvdXJzZS5pZGVudGlmaWVyID0gY291cnNlLmlkO1xuICAgICAgICB9XG4gICAgICAgIGFsbENvdXJzZXMucHVzaChjb3Vyc2UpO1xuICAgICAgICBzZWVuSWRlbnRpZmllcnMuYWRkKGNvdXJzZUlkKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICBjb25zb2xlLmxvZygnZ2V0QWxsQXZhaWxhYmxlQ291cnNlcyBicmVha2Rvd246Jywge1xuICAgICAgb3JpZ2luYWxEYXRhOiB0aGlzLm9yaWdpbmFsRGF0YS5sZW5ndGgsXG4gICAgICBzdWdnZXN0ZWRDb3Vyc2VzOiB0aGlzLnN1Z2dlc3RlZENvdXJzZXMubGVuZ3RoLFxuICAgICAgdXNlckFkZGVkQ291cnNlczogdGhpcy51c2VyQWRkZWRDb3Vyc2VzLmxlbmd0aCxcbiAgICAgIHRvdGFsQXZhaWxhYmxlOiBhbGxDb3Vyc2VzLmxlbmd0aFxuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coJ2FsbENvdXJzZXMtLScsIGFsbENvdXJzZXMpXG4gICAgYWxsQ291cnNlcy5mb3JFYWNoKChpdGVtKT0+e1xuICAgICAgaWYoaXRlbSAmJiBpdGVtLm9yZ2FuaXNhdGlvbiAmJiBpdGVtLm9yZ2FuaXNhdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgaWYodGhpcy5maWx0ZXJlZFByb3ZpZGVycy5pbmRleE9mKGl0ZW0ub3JnYW5pc2F0aW9uWzBdKSA8IDApIHtcbiAgICAgICAgICB0aGlzLmZpbHRlcmVkUHJvdmlkZXJzLnB1c2goaXRlbS5vcmdhbmlzYXRpb25bMF0pXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICB9XG4gICAgfSlcbiAgICB0aGlzLmZ1bGxDb3Vyc2VMaXN0ID0gYWxsQ291cnNlc1xuICAgIGxldCBpZGVudGlmaWVyc0FyciA9IFtdXG4gICAgdGhpcy5mdWxsQ291cnNlTGlzdC5tYXAoKGl0ZW0pPT57XG4gICAgICBpZGVudGlmaWVyc0Fyci5wdXNoKGl0ZW0/LmlkZW50aWZpZXIpXG4gICAgfSlcbiAgICB0aGlzLnNoYXJlZFNlcnZpY2UuZ2V0QWRkaXRpb25hbFBhcmFtZXRlcmZvclN1Z2dlc3RlZENvdXJzZXMoaWRlbnRpZmllcnNBcnIpLnN1YnNjcmliZSgocmVzcG9uc2UpPT57XG4gICAgICBpZihyZXNwb25zZSAmJiByZXNwb25zZS5yZXN1bHQgJiYgcmVzcG9uc2UucmVzdWx0LmNvbnRlbnQgJiYgcmVzcG9uc2UucmVzdWx0LmNvbnRlbnQubGVuZ3RoKSB7XG4gICAgICAgIGZvcihsZXQgaT0wOyBpIDwgcmVzcG9uc2UucmVzdWx0LmNvbnRlbnQubGVuZ3RoO2krKykge1xuICAgICAgICAgIGZvcihsZXQgaj0wOyBqPHRoaXMuZnVsbENvdXJzZUxpc3QubGVuZ3RoO2orKykge1xuICAgICAgICAgICAgaWYodGhpcy5mdWxsQ291cnNlTGlzdFtqXVsnaWRlbnRpZmllciddID09PSByZXNwb25zZS5yZXN1bHQuY29udGVudFtpXVsnaWRlbnRpZmllciddICkge1xuICAgICAgICAgICAgICB0aGlzLmZ1bGxDb3Vyc2VMaXN0W2pdWydsYW5ndWFnZSddID0gcmVzcG9uc2UucmVzdWx0LmNvbnRlbnRbaV1bJ2xhbmd1YWdlJ11cbiAgICAgICAgICAgICAgdGhpcy5mdWxsQ291cnNlTGlzdFtqXVsnYXZnUmF0aW5nJ10gPSByZXNwb25zZS5yZXN1bHQuY29udGVudFtpXVsnYXZnUmF0aW5nJ11cbiAgICAgICAgICAgICAgdGhpcy5mdWxsQ291cnNlTGlzdFtqXVsnY291cnNlJ10gPSByZXNwb25zZS5yZXN1bHQuY29udGVudFtpXVsnbmFtZSddXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgfSlcbiAgICByZXR1cm4gYWxsQ291cnNlcztcbiAgfVxuXG4gIFxuICAvKipcbiAgICogUmVidWlsZCBmaWx0ZXJkQ291cnNlcyBhcnJheSB3aXRoIGFsbCBhdmFpbGFibGUgY291cnNlIHR5cGVzXG4gICAqIFRoaXMgZW5zdXJlcyBjb25zaXN0ZW5jeSBhY3Jvc3MgdGhlIGFwcGxpY2F0aW9uXG4gICAqL1xuICByZWJ1aWxkRmlsdGVyZWRDb3Vyc2VzKCkge1xuICAgIHRoaXMuZmlsdGVyZENvdXJzZXMgPSB0aGlzLmdldEFsbEF2YWlsYWJsZUNvdXJzZXMoKTtcbiAgICBcbiAgICBjb25zb2xlLmxvZygnUmVidWlsdCBmaWx0ZXJkQ291cnNlcyB3aXRoIGFsbCBjb3Vyc2UgdHlwZXM6Jywge1xuICAgICAgdG90YWw6IHRoaXMuZmlsdGVyZENvdXJzZXMubGVuZ3RoLFxuICAgICAgYnJlYWtkb3duOiB7XG4gICAgICAgIG9yaWdpbmFsOiB0aGlzLm9yaWdpbmFsRGF0YS5sZW5ndGgsXG4gICAgICAgIHN1Z2dlc3RlZDogdGhpcy5zdWdnZXN0ZWRDb3Vyc2VzLmxlbmd0aCxcbiAgICAgICAgdXNlckFkZGVkOiB0aGlzLnVzZXJBZGRlZENvdXJzZXMubGVuZ3RoXG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBiZWhhdmlvcmFsRmlsdGVyKGRhdGE6IGFueVtdKTogYW55W10ge1xuICAgIHJldHVybiBkYXRhLmZpbHRlcihpdGVtID0+IHtcbiAgICAgIGlmICghaXRlbSkgcmV0dXJuIGZhbHNlO1xuICAgICAgXG4gICAgICAvLyBIYW5kbGUgZGlmZmVyZW50IGNvbXBldGVuY3kgcHJvcGVydHkgbmFtZXNcbiAgICAgIGxldCBjb21wZXRlbmNpZXMgPSBbXTtcbiAgICAgIGlmIChpdGVtLmNvbXBldGVuY2llcyAmJiBBcnJheS5pc0FycmF5KGl0ZW0uY29tcGV0ZW5jaWVzKSkge1xuICAgICAgICBjb21wZXRlbmNpZXMgPSBpdGVtLmNvbXBldGVuY2llcztcbiAgICAgIH0gZWxzZSBpZiAoaXRlbS5jb21wZXRlbmNpZXNfdjYgJiYgQXJyYXkuaXNBcnJheShpdGVtLmNvbXBldGVuY2llc192NikpIHtcbiAgICAgICAgY29tcGV0ZW5jaWVzID0gaXRlbS5jb21wZXRlbmNpZXNfdjY7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHJldHVybiBjb21wZXRlbmNpZXMuc29tZShjID0+IGMgJiYgKChjPy5jb21wZXRlbmN5QXJlYU5hbWU/LnRvTG93ZXJDYXNlKCkgPT09ICdiZWhhdmlvcmFsJykgfHwgYz8uY29tcGV0ZW5jeUFyZWFOYW1lPy50b0xvd2VyQ2FzZSgpID09PSAnYmVoYXZpb3VyYWwnKSk7XG4gICAgfSk7XG4gIH1cblxuICBiZWhhdmlvcmFsQ29tcGV0ZW5jeUZpbHRlcihkYXRhOiBhbnlbXSk6IHN0cmluZ1tdIHtcbiAgICBjb25zb2xlLmxvZygnZGF0YS0tJywgZGF0YSlcbiAgICBjb25zdCBiZWhhdmlvcmFsVGhlbWVzID0gZGF0YVxuICAgICAgLmZpbHRlcihpdGVtID0+XG4gICAgICAgIGl0ZW0/LnR5cGUgJiZcbiAgICAgICAgWydiZWhhdmlvcmFsJywgJ2JlaGF2aW91cmFsJ10uaW5jbHVkZXMoaXRlbS50eXBlLnRvTG93ZXJDYXNlKCkpXG4gICAgICApXG4gICAgICAubWFwKGl0ZW0gPT4gYCR7aXRlbS50aGVtZX0tJHtpdGVtLnN1Yl90aGVtZX1gKVxuICAgICAgLmZpbHRlcigodGhlbWUpOiB0aGVtZSBpcyBzdHJpbmcgPT4gQm9vbGVhbih0aGVtZSkpOyAvLyBFbnN1cmVzIHR5cGUgc2FmZXR5XG4gIFxuICAgIGNvbnN0IHVuaXF1ZUJlaGF2aW9yYWxUaGVtZXMgPSBBcnJheS5mcm9tKG5ldyBTZXQoYmVoYXZpb3JhbFRoZW1lcykpO1xuICAgIFxuICAgIGNvbnNvbGUubG9nKHVuaXF1ZUJlaGF2aW9yYWxUaGVtZXMpO1xuICAgIHJldHVybiB1bmlxdWVCZWhhdmlvcmFsVGhlbWVzO1xuICB9XG5cbiAgZnVuY3Rpb25hbENvbXBldGVuY3lGaWx0ZXIoZGF0YTphbnlbXSk6YW55IHtcbiAgICBjb25zdCBmdW5jdGlvbmFsVGhlbWVzID0gZGF0YVxuICAgICAgLmZpbHRlcihpdGVtID0+XG4gICAgICAgIGl0ZW0/LnR5cGUgJiZcbiAgICAgICAgWydmdW5jdGlvbmFsJ10uaW5jbHVkZXMoaXRlbS50eXBlLnRvTG93ZXJDYXNlKCkpXG4gICAgICApXG4gICAgICAubWFwKGl0ZW0gPT4gYCR7aXRlbS50aGVtZX0tJHtpdGVtLnN1Yl90aGVtZX1gKVxuICAgICAgLmZpbHRlcigodGhlbWUpOiB0aGVtZSBpcyBzdHJpbmcgPT4gQm9vbGVhbih0aGVtZSkpOyAvLyBFbnN1cmVzIHR5cGUgc2FmZXR5XG4gIFxuICAgIGNvbnN0IHVuaXF1ZUZ1bmN0aW9uYWxUaGVtZXMgPSBBcnJheS5mcm9tKG5ldyBTZXQoZnVuY3Rpb25hbFRoZW1lcykpO1xuICAgIFxuICAgIGNvbnNvbGUubG9nKHVuaXF1ZUZ1bmN0aW9uYWxUaGVtZXMpO1xuICAgIHJldHVybiB1bmlxdWVGdW5jdGlvbmFsVGhlbWVzO1xuICAgIFxuICAgIC8vIGNvbnNvbGUubG9nKHVuaXF1ZUNvbXBldGVuY3lBcmVhTmFtZXMpO1xuICB9XG5cbiAgZG9tYWluQ29tcGV0ZW5jeUZpbHRlcihkYXRhOmFueVtdKTphbnkge1xuICAgIGNvbnN0IGRvbWFpblRoZW1lcyA9IGRhdGFcbiAgICAuZmlsdGVyKGl0ZW0gPT5cbiAgICAgIGl0ZW0/LnR5cGUgJiZcbiAgICAgIFsnZG9tYWluJ10uaW5jbHVkZXMoaXRlbS50eXBlLnRvTG93ZXJDYXNlKCkpXG4gICAgKVxuICAgIC5tYXAoaXRlbSA9PiBgJHtpdGVtLnRoZW1lfS0ke2l0ZW0uc3ViX3RoZW1lfWApXG4gICAgLmZpbHRlcigodGhlbWUpOiB0aGVtZSBpcyBzdHJpbmcgPT4gQm9vbGVhbih0aGVtZSkpOyAvLyBFbnN1cmVzIHR5cGUgc2FmZXR5XG5cbiAgY29uc3QgdW5pcXVlRG9tYWluVGhlbWVzID0gQXJyYXkuZnJvbShuZXcgU2V0KGRvbWFpblRoZW1lcykpO1xuICBcbiAgY29uc29sZS5sb2codW5pcXVlRG9tYWluVGhlbWVzKTtcbiAgcmV0dXJuIHVuaXF1ZURvbWFpblRoZW1lcztcbiAgICBcbiAgICAvLyBjb25zb2xlLmxvZyh1bmlxdWVDb21wZXRlbmN5QXJlYU5hbWVzKTtcbiAgfVxuXG5cbiAgZnVuY3Rpb25hbEZpbHRlcihkYXRhOiBhbnlbXSk6IGFueVtdIHtcbiAgICByZXR1cm4gZGF0YS5maWx0ZXIoaXRlbSA9PiB7XG4gICAgICBpZiAoIWl0ZW0pIHJldHVybiBmYWxzZTtcbiAgICAgIFxuICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBjb21wZXRlbmN5IHByb3BlcnR5IG5hbWVzXG4gICAgICBsZXQgY29tcGV0ZW5jaWVzID0gW107XG4gICAgICBpZiAoaXRlbS5jb21wZXRlbmNpZXMgJiYgQXJyYXkuaXNBcnJheShpdGVtLmNvbXBldGVuY2llcykpIHtcbiAgICAgICAgY29tcGV0ZW5jaWVzID0gaXRlbS5jb21wZXRlbmNpZXM7XG4gICAgICB9IGVsc2UgaWYgKGl0ZW0uY29tcGV0ZW5jaWVzX3Y2ICYmIEFycmF5LmlzQXJyYXkoaXRlbS5jb21wZXRlbmNpZXNfdjYpKSB7XG4gICAgICAgIGNvbXBldGVuY2llcyA9IGl0ZW0uY29tcGV0ZW5jaWVzX3Y2O1xuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4gY29tcGV0ZW5jaWVzLnNvbWUoYyA9PiBjICYmIGM/LmNvbXBldGVuY3lBcmVhTmFtZT8udG9Mb3dlckNhc2UoKSA9PT0gJ2Z1bmN0aW9uYWwnKTtcbiAgICB9KTtcbiAgfVxuXG4gIGRvbWFpbkZpbHRlcihkYXRhOiBhbnlbXSk6IGFueVtdIHtcbiAgICByZXR1cm4gZGF0YS5maWx0ZXIoaXRlbSA9PiB7XG4gICAgICBpZiAoIWl0ZW0pIHJldHVybiBmYWxzZTtcbiAgICAgIFxuICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBjb21wZXRlbmN5IHByb3BlcnR5IG5hbWVzXG4gICAgICBsZXQgY29tcGV0ZW5jaWVzID0gW107XG4gICAgICBpZiAoaXRlbS5jb21wZXRlbmNpZXMgJiYgQXJyYXkuaXNBcnJheShpdGVtLmNvbXBldGVuY2llcykpIHtcbiAgICAgICAgY29tcGV0ZW5jaWVzID0gaXRlbS5jb21wZXRlbmNpZXM7XG4gICAgICB9IGVsc2UgaWYgKGl0ZW0uY29tcGV0ZW5jaWVzX3Y2ICYmIEFycmF5LmlzQXJyYXkoaXRlbS5jb21wZXRlbmNpZXNfdjYpKSB7XG4gICAgICAgIGNvbXBldGVuY2llcyA9IGl0ZW0uY29tcGV0ZW5jaWVzX3Y2O1xuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4gY29tcGV0ZW5jaWVzLnNvbWUoYyA9PiBjICYmIGM/LmNvbXBldGVuY3lBcmVhTmFtZT8udG9Mb3dlckNhc2UoKSA9PT0gJ2RvbWFpbicpO1xuICAgIH0pO1xuICB9XG5cbiAgZ2FwQW5hbHlzaXNTdGF0cyAoKSB7XG4gICAgY29uc29sZS5sb2coJ3RoaXMucGxhbkRhdGEnLHRoaXMucGxhbkRhdGEpXG4gICAgXG4gICAgLy8gQWx3YXlzIHVzZSBBTEwgY29tcGV0ZW5jaWVzIGZvciBjYWxjdWxhdGluZyBvdmVyYWxsIHN0YXRzXG4gICAgY29uc3QgYWxsQ29tcGV0ZW5jaWVzID0gdGhpcy5wbGFuRGF0YS5jb21wZXRlbmNpZXM7XG4gICAgXG4gICAgLy8gRmlsdGVyIGZvciBjYXRlZ29yeS1zcGVjaWZpYyBjYWxjdWxhdGlvbnNcbiAgICBsZXQgY2F0ZWdvcnlTcGVjaWZpY0NvbXBldGVuY2llczphbnkgPSB0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcztcbiAgICBpZih0aGlzLnNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdhbGwnKSB7XG4gICAgICBjYXRlZ29yeVNwZWNpZmljQ29tcGV0ZW5jaWVzID0gdGhpcy5wbGFuRGF0YS5jb21wZXRlbmNpZXNcbiAgICB9IGVsc2UgaWYodGhpcy5zZWxlY3RlZENhdGVnb3J5ID09PSAnYmVoYXZpb3JhbCcpIHtcbiAgICAgIGNhdGVnb3J5U3BlY2lmaWNDb21wZXRlbmNpZXMgPSB0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcy5maWx0ZXIoaXRlbSA9PiBpdGVtLnR5cGU/LnRvTG93ZXJDYXNlKCkgPT09IHRoaXMuc2VsZWN0ZWRDYXRlZ29yeSk7XG4gICAgfSBlbHNlIGlmKHRoaXMuc2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2Z1bmN0aW9uYWwnKSB7XG4gICAgICBjYXRlZ29yeVNwZWNpZmljQ29tcGV0ZW5jaWVzID0gdGhpcy5wbGFuRGF0YS5jb21wZXRlbmNpZXMuZmlsdGVyKGl0ZW0gPT4gaXRlbS50eXBlPy50b0xvd2VyQ2FzZSgpID09PSB0aGlzLnNlbGVjdGVkQ2F0ZWdvcnkpO1xuICAgIH0gXG4gICAgZWxzZSBpZih0aGlzLnNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdkb21haW4nKSB7XG4gICAgICBjYXRlZ29yeVNwZWNpZmljQ29tcGV0ZW5jaWVzID0gdGhpcy5wbGFuRGF0YS5jb21wZXRlbmNpZXMuZmlsdGVyKGl0ZW0gPT4gaXRlbS50eXBlPy50b0xvd2VyQ2FzZSgpID09PSB0aGlzLnNlbGVjdGVkQ2F0ZWdvcnkpO1xuICAgIH0gXG5cbiAgICAvLyBDb3VudCBBTEwgY29tcGV0ZW5jaWVzIGJ5IGNhdGVnb3J5IChub3QganVzdCBmaWx0ZXJlZCBvbmVzKVxuICAgIGNvbnN0IG1hc3Rlckxpc3RCeUNhdGVnb3J5ID0ge3RvdGFsOiBhbGxDb21wZXRlbmNpZXMubGVuZ3RoLCBiZWhhdmlvdXJhbDogMCwgZnVuY3Rpb25hbDowLCBkb21haW46MH1cbiAgICBcbiAgICAvLyBJTVBPUlRBTlQ6IFVzZSBhbGwgYXZhaWxhYmxlIGNvdXJzZXMgZm9yIGNvbnNpc3RlbnQgY292ZXJhZ2UgY2FsY3VsYXRpb25cbiAgICAvLyBUaGlzIHNob3VsZCBtYXRjaCB3aGF0J3MgYXZhaWxhYmxlIGluIHRoZSBGaWx0ZXIgQnkgQ29tcGV0ZW5jeSBzZWN0aW9uXG4gICAgY29uc3QgYWxsQ291cnNlQ29tcGV0ZW5jaWVzID0gW11cbiAgICBjb25zdCBhbGxBdmFpbGFibGVDb3Vyc2VzRm9yU3RhdHMgPSB0aGlzLmdldEFsbEF2YWlsYWJsZUNvdXJzZXMoKTtcbiAgICBcbiAgICBhbGxBdmFpbGFibGVDb3Vyc2VzRm9yU3RhdHMuZm9yRWFjaChjb3Vyc2UgPT4ge1xuICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBjb21wZXRlbmN5IHByb3BlcnR5IG5hbWVzXG4gICAgICBsZXQgY29tcGV0ZW5jaWVzID0gW107XG4gICAgICBpZiAoY291cnNlICYmIGNvdXJzZS5jb21wZXRlbmNpZXMgJiYgQXJyYXkuaXNBcnJheShjb3Vyc2UuY29tcGV0ZW5jaWVzKSkge1xuICAgICAgICBjb21wZXRlbmNpZXMgPSBjb3Vyc2UuY29tcGV0ZW5jaWVzO1xuICAgICAgfSBlbHNlIGlmIChjb3Vyc2UgJiYgY291cnNlLmNvbXBldGVuY2llc192NiAmJiBBcnJheS5pc0FycmF5KGNvdXJzZS5jb21wZXRlbmNpZXNfdjYpKSB7XG4gICAgICAgIGNvbXBldGVuY2llcyA9IGNvdXJzZS5jb21wZXRlbmNpZXNfdjY7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbXBldGVuY2llcy5mb3JFYWNoKChsaXN0OmFueSkgPT4ge1xuICAgICAgICAgYWxsQ291cnNlQ29tcGV0ZW5jaWVzLnB1c2gobGlzdClcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIFxuICAgIGNvbnNvbGUubG9nKCdhbGxDb21wZXRlbmNpZXMnLCBhbGxDb21wZXRlbmNpZXMpXG4gICAgY29uc29sZS5sb2coJ2NhdGVnb3J5U3BlY2lmaWNDb21wZXRlbmNpZXMnLCBjYXRlZ29yeVNwZWNpZmljQ29tcGV0ZW5jaWVzKVxuICAgIGNvbnNvbGUubG9nKCdhbGxDb3Vyc2VDb21wZXRlbmNpZXMnLCBhbGxDb3Vyc2VDb21wZXRlbmNpZXMpXG4gICAgXG4gICAgLy8gQ291bnQgYWxsIGNvbXBldGVuY2llcyBieSB0eXBlIGZvciBwcm9wZXIgdG90YWxzXG4gICAgZm9yKGxldCBpPTA7IGk8YWxsQ29tcGV0ZW5jaWVzLmxlbmd0aDtpKyspIHtcbiAgICAgIGNvbnN0IGNvbXBldGVuY3lUeXBlID0gYWxsQ29tcGV0ZW5jaWVzW2ldWyd0eXBlJ10/LnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zb2xlLmxvZyhgQ29tcGV0ZW5jeSAke2l9OiB0eXBlPVwiJHtjb21wZXRlbmN5VHlwZX1cIiwgZGF0YTpgLCBhbGxDb21wZXRlbmNpZXNbaV0pO1xuICAgICAgaWYoY29tcGV0ZW5jeVR5cGUgPT09ICdiZWhhdmlvdXJhbCcgfHwgY29tcGV0ZW5jeVR5cGUgPT09ICdiZWhhdmlvcmFsJykge1xuICAgICAgICBtYXN0ZXJMaXN0QnlDYXRlZ29yeVsnYmVoYXZpb3VyYWwnXSA9IG1hc3Rlckxpc3RCeUNhdGVnb3J5WydiZWhhdmlvdXJhbCddICsgMVxuICAgICAgfVxuICAgICAgaWYoY29tcGV0ZW5jeVR5cGUgPT09ICdmdW5jdGlvbmFsJykge1xuICAgICAgICBtYXN0ZXJMaXN0QnlDYXRlZ29yeVsnZnVuY3Rpb25hbCddID0gbWFzdGVyTGlzdEJ5Q2F0ZWdvcnlbJ2Z1bmN0aW9uYWwnXSArIDFcbiAgICAgIH1cbiAgICAgIGlmKGNvbXBldGVuY3lUeXBlID09PSAnZG9tYWluJykge1xuICAgICAgICBtYXN0ZXJMaXN0QnlDYXRlZ29yeVsnZG9tYWluJ10gPSBtYXN0ZXJMaXN0QnlDYXRlZ29yeVsnZG9tYWluJ10gKyAxXG4gICAgICB9XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKCdtYXN0ZXJMaXN0QnlDYXRlZ29yeSBhZnRlciBjb3VudGluZzonLCBtYXN0ZXJMaXN0QnlDYXRlZ29yeSlcbiAgICBcbiAgICAvLyBHZXQgbWF0Y2hpbmcgcmVzdWx0cyBmb3IgQUxMIGNvbXBldGVuY2llcyAoZm9yIG92ZXJhbGwgY292ZXJhZ2UpXG4gICAgY29uc3Qgb3ZlcmFsbFJlc3VsdCA9IHRoaXMuZ2V0TWF0Y2hlZENvbXBldGVuY3lTdGF0cyhhbGxDb21wZXRlbmNpZXMsIGFsbENvdXJzZUNvbXBldGVuY2llcyk7XG4gICAgXG4gICAgLy8gR2V0IG1hdGNoaW5nIHJlc3VsdHMgZm9yIGNhdGVnb3J5LXNwZWNpZmljIGNvbXBldGVuY2llcyAoZm9yIGZpbHRlcmVkIHZpZXcpXG4gICAgY29uc3QgY2F0ZWdvcnlSZXN1bHQgPSB0aGlzLmdldE1hdGNoZWRDb21wZXRlbmN5U3RhdHMoY2F0ZWdvcnlTcGVjaWZpY0NvbXBldGVuY2llcywgYWxsQ291cnNlQ29tcGV0ZW5jaWVzKTtcbiAgICBcbiAgICAvLyBTZXQgY29tcGV0ZW5jeUNvdmVyZWRDb3VudCBiYXNlZCBvbiBzZWxlY3RlZCBjYXRlZ29yeSAoZm9yIHRoZSBmaWx0ZXJlZCBudW1iZXJzKVxuICAgIGlmKHRoaXMuc2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2FsbCcpIHtcbiAgICAgIHRoaXMuY29tcGV0ZW5jeUNvdmVyZWRDb3VudCA9IG92ZXJhbGxSZXN1bHRbJ3RvdGFsJ107XG4gICAgfSBlbHNlIGlmKHRoaXMuc2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2JlaGF2aW9yYWwnKSB7XG4gICAgICB0aGlzLmNvbXBldGVuY3lDb3ZlcmVkQ291bnQgPSBjYXRlZ29yeVJlc3VsdFsnYmVoYXZpb3JhbCddIHx8IDA7XG4gICAgfSBlbHNlIGlmKHRoaXMuc2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2Z1bmN0aW9uYWwnKSB7XG4gICAgICB0aGlzLmNvbXBldGVuY3lDb3ZlcmVkQ291bnQgPSBjYXRlZ29yeVJlc3VsdFsnZnVuY3Rpb25hbCddIHx8IDA7XG4gICAgfSBlbHNlIGlmKHRoaXMuc2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2RvbWFpbicpIHtcbiAgICAgIHRoaXMuY29tcGV0ZW5jeUNvdmVyZWRDb3VudCA9IGNhdGVnb3J5UmVzdWx0Wydkb21haW4nXSB8fCAwO1xuICAgIH1cbiAgICBcbiAgICAvLyBJTVBPUlRBTlQ6IE92ZXJhbGwgQ292ZXJhZ2Ugc2hvdWxkIEFMV0FZUyBiZSBiYXNlZCBvbiBBTEwgY29tcGV0ZW5jaWVzLCBub3QgZmlsdGVyZWRcbiAgICBsZXQgdG90YWxDb21wZXRlbmNpZXMgPSB0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcy5sZW5ndGg7IC8vIEFsd2F5cyB1c2UgdG90YWwgY291bnRcbiAgICBsZXQgb3ZlcmFsbENvdmVyZWRDb3VudCA9IG92ZXJhbGxSZXN1bHRbJ3RvdGFsJ107IC8vIEFsd2F5cyB1c2Ugb3ZlcmFsbCByZXN1bHRzXG4gICAgbGV0IG1hdGhSb3VuZCA9IE1hdGgucm91bmQoKG92ZXJhbGxDb3ZlcmVkQ291bnQvdG90YWxDb21wZXRlbmNpZXMpKjEwMClcbiAgICB0aGlzLm92ZXJhbGxDb3ZlcmFnZSA9IGAke21hdGhSb3VuZH0lYFxuICAgIFxuICAgIGNvbnNvbGUubG9nKCdPdmVyYWxsIENvdmVyYWdlIENhbGN1bGF0aW9uOicsIHtcbiAgICAgIHRvdGFsQ29tcGV0ZW5jaWVzOiB0b3RhbENvbXBldGVuY2llcyxcbiAgICAgIG92ZXJhbGxDb3ZlcmVkQ291bnQ6IG92ZXJhbGxDb3ZlcmVkQ291bnQsXG4gICAgICBvdmVyYWxsQ292ZXJhZ2U6IHRoaXMub3ZlcmFsbENvdmVyYWdlLFxuICAgICAgc2VsZWN0ZWRDYXRlZ29yeTogdGhpcy5zZWxlY3RlZENhdGVnb3J5LFxuICAgICAgY29tcGV0ZW5jeUNvdmVyZWRDb3VudDogdGhpcy5jb21wZXRlbmN5Q292ZXJlZENvdW50XG4gICAgfSk7XG4gICAgXG4gICAgLy8gQWx3YXlzIGNhbGN1bGF0ZSBhbGwgY2F0ZWdvcnktc3BlY2lmaWMgbWV0cmljcyByZWdhcmRsZXNzIG9mIHNlbGVjdGVkIGNhdGVnb3J5XG4gICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBkYXRhIGlzIGF2YWlsYWJsZSB3aGVuIHN3aXRjaGluZyBiZXR3ZWVuIGNhdGVnb3JpZXNcbiAgICAvLyBVc2Ugb3ZlcmFsbFJlc3VsdCBmb3IgY29uc2lzdGVudCBjYWxjdWxhdGlvbnMgYWNyb3NzIGFsbCBjYXRlZ29yaWVzXG4gICAgdGhpcy5iZWhhdmlvcmFsQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCA9IG92ZXJhbGxSZXN1bHRbJ2JlaGF2aW9yYWwnXSB8fCAwO1xuICAgIHRoaXMuYmVoYXZpb3JhbFRvdGFsQ29tcGV0ZW5jaWVzID0gbWFzdGVyTGlzdEJ5Q2F0ZWdvcnlbJ2JlaGF2aW91cmFsJ107XG4gICAgbGV0IGJlaGF2aW9yYWxNYXRoUm91bmQgPSB0aGlzLmJlaGF2aW9yYWxUb3RhbENvbXBldGVuY2llcyA+IDAgPyBNYXRoLnJvdW5kKCh0aGlzLmJlaGF2aW9yYWxDb21wZXRlbmN5Q292ZXJlZENvdW50L3RoaXMuYmVoYXZpb3JhbFRvdGFsQ29tcGV0ZW5jaWVzKSoxMDApIDogMDtcbiAgICB0aGlzLmJlaGF2aW9yYWxDb3ZlcmFnZSA9IGAke2JlaGF2aW9yYWxNYXRoUm91bmR9JWA7XG4gICAgXG4gICAgdGhpcy5mdW5jdGlvbmFsQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCA9IG92ZXJhbGxSZXN1bHRbJ2Z1bmN0aW9uYWwnXSB8fCAwO1xuICAgIHRoaXMuZnVuY3Rpb25hbFRvdGFsQ29tcGV0ZW5jaWVzID0gbWFzdGVyTGlzdEJ5Q2F0ZWdvcnlbJ2Z1bmN0aW9uYWwnXTtcbiAgICBsZXQgZnVuY3Rpb25hbE1hdGhSb3VuZCA9IHRoaXMuZnVuY3Rpb25hbFRvdGFsQ29tcGV0ZW5jaWVzID4gMCA/IE1hdGgucm91bmQoKHRoaXMuZnVuY3Rpb25hbENvbXBldGVuY3lDb3ZlcmVkQ291bnQvdGhpcy5mdW5jdGlvbmFsVG90YWxDb21wZXRlbmNpZXMpKjEwMCkgOiAwO1xuICAgIHRoaXMuZnVuY3Rpb25hbENvdmVyYWdlID0gYCR7ZnVuY3Rpb25hbE1hdGhSb3VuZH0lYDtcbiAgICBcbiAgICB0aGlzLmRvbWFpbkNvbXBldGVuY3lDb3ZlcmVkQ291bnQgPSBvdmVyYWxsUmVzdWx0Wydkb21haW4nXSB8fCAwO1xuICAgIHRoaXMuZG9tYWluVG90YWxDb21wZXRlbmNpZXMgPSBtYXN0ZXJMaXN0QnlDYXRlZ29yeVsnZG9tYWluJ107XG4gICAgbGV0IGRvbWFpbk1hdGhSb3VuZCA9IHRoaXMuZG9tYWluVG90YWxDb21wZXRlbmNpZXMgPiAwID8gTWF0aC5yb3VuZCgodGhpcy5kb21haW5Db21wZXRlbmN5Q292ZXJlZENvdW50L3RoaXMuZG9tYWluVG90YWxDb21wZXRlbmNpZXMpKjEwMCkgOiAwO1xuICAgIHRoaXMuZG9tYWluQ292ZXJhZ2UgPSBgJHtkb21haW5NYXRoUm91bmR9JWA7XG4gICAgXG4gICAgY29uc29sZS5sb2coJ0FsbCBjYXRlZ29yeSBtZXRyaWNzIGNhbGN1bGF0ZWQ6Jywge1xuICAgICAgYmVoYXZpb3JhbDogeyBjb3ZlcmVkOiB0aGlzLmJlaGF2aW9yYWxDb21wZXRlbmN5Q292ZXJlZENvdW50LCB0b3RhbDogdGhpcy5iZWhhdmlvcmFsVG90YWxDb21wZXRlbmNpZXMsIGNvdmVyYWdlOiB0aGlzLmJlaGF2aW9yYWxDb3ZlcmFnZSB9LFxuICAgICAgZnVuY3Rpb25hbDogeyBjb3ZlcmVkOiB0aGlzLmZ1bmN0aW9uYWxDb21wZXRlbmN5Q292ZXJlZENvdW50LCB0b3RhbDogdGhpcy5mdW5jdGlvbmFsVG90YWxDb21wZXRlbmNpZXMsIGNvdmVyYWdlOiB0aGlzLmZ1bmN0aW9uYWxDb3ZlcmFnZSB9LFxuICAgICAgZG9tYWluOiB7IGNvdmVyZWQ6IHRoaXMuZG9tYWluQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCwgdG90YWw6IHRoaXMuZG9tYWluVG90YWxDb21wZXRlbmNpZXMsIGNvdmVyYWdlOiB0aGlzLmRvbWFpbkNvdmVyYWdlIH0sXG4gICAgICBvdmVyYWxsOiB7IGNvdmVyZWQ6IG92ZXJhbGxDb3ZlcmVkQ291bnQsIHRvdGFsOiB0b3RhbENvbXBldGVuY2llcywgY292ZXJhZ2U6IHRoaXMub3ZlcmFsbENvdmVyYWdlIH0sXG4gICAgICBzZWxlY3RlZENhdGVnb3J5OiB0aGlzLnNlbGVjdGVkQ2F0ZWdvcnksXG4gICAgICBjb21wZXRlbmN5Q292ZXJlZENvdW50Rm9yQ2F0ZWdvcnk6IHRoaXMuY29tcGV0ZW5jeUNvdmVyZWRDb3VudFxuICAgIH0pO1xuICAgIGNvbnNvbGUubG9nKCdPdmVyYWxsIFJlc3VsdDonLCBvdmVyYWxsUmVzdWx0KTtcbiAgICBjb25zb2xlLmxvZygnQ2F0ZWdvcnkgUmVzdWx0OicsIGNhdGVnb3J5UmVzdWx0KTtcbiAgICBjb25zb2xlLmxvZygndGhpcy5jb21wZXRlbmN5Tm90TWF0Y2hlZEJ5Q2F0ZWdvcnknLHRoaXMuY29tcGV0ZW5jeU5vdE1hdGNoZWRCeUNhdGVnb3J5KVxuICAgIHRoaXMuYmVoYXZpb3VyYWxOb3RNYXRjaGVkID0gdGhpcy5nZXRDb21wZXRlbmN5QnlDYXRlZ29yeU5vdE1hdGNoaW5nKCdiZWhhdmlvcmFsJylcbiAgICB0aGlzLmZ1bmN0aW9uYWxOb3RNYXRjaGVkID0gdGhpcy5nZXRDb21wZXRlbmN5QnlDYXRlZ29yeU5vdE1hdGNoaW5nKCdmdW5jdGlvbmFsJylcbiAgICB0aGlzLmRvbWFpbk5vdE1hdGNoZWQgPSB0aGlzLmdldENvbXBldGVuY3lCeUNhdGVnb3J5Tm90TWF0Y2hpbmcoJ2RvbWFpbicpXG5cbiAgICB0aGlzLmdldEJlaGF2aW91cmFsTWF0Y2hlZCgpXG4gICAgdGhpcy5nZXRGdW5jdGlvbmFsTWF0Y2hlZCgpXG4gICAgdGhpcy5nZXREb21haW5NYXRjaGVkKClcbiAgfVxuXG4gIGdldE1hdGNoZWRDb21wZXRlbmN5U3RhdHMocHJpbWFyeUFycmF5OiBhbnlbXSwgc2Vjb25kYXJ5QXJyYXk6IGFueVtdKSB7XG4gICAgLy8gQ29udmVydCBib3RoIGFycmF5cyB0byBlbnN1cmUgY29uc2lzdGVudCBjYXNpbmdcbiAgICBjb25zdCBjb3VudHM6IGFueSA9IHtcbiAgICAgIGJlaGF2aW9yYWw6IDAsXG4gICAgICBmdW5jdGlvbmFsOiAwLFxuICAgICAgZG9tYWluOiAwLFxuICAgICAgdG90YWw6IDBcbiAgICB9O1xuICAgIFxuICAgIC8vIENsZWFyIHRoZSBjb21wZXRlbmN5Tm90TWF0Y2hlZEJ5Q2F0ZWdvcnkgYXJyYXkgZm9yIGZyZXNoIGNhbGN1bGF0aW9uXG4gICAgdGhpcy5jb21wZXRlbmN5Tm90TWF0Y2hlZEJ5Q2F0ZWdvcnkgPSBbXTtcbiAgICBcbiAgICAvLyBTZXQgdG8ga2VlcCB0cmFjayBvZiB1bmlxdWUgbWF0Y2hlc1xuICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCBtYXRjaGVkQ29tcGV0ZW5jaWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgXG4gICAgZm9yIChjb25zdCBwcmltYXJ5IG9mIHByaW1hcnlBcnJheSkge1xuICAgICAgY29uc3QgdHlwZUtleSA9IHByaW1hcnkudHlwZT8udG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgICBjb25zdCB0aGVtZUtleSA9IHByaW1hcnkudGhlbWU/LnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgY29uc3Qgc3ViVGhlbWVLZXkgPSBwcmltYXJ5LnN1Yl90aGVtZT8udG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgXG4gICAgICBsZXQgaXNNYXRjaGVkID0gZmFsc2U7XG4gICAgICBcbiAgICAgIGZvciAoY29uc3Qgc2Vjb25kYXJ5IG9mIHNlY29uZGFyeUFycmF5KSB7XG4gICAgICAgIC8vIE5vcm1hbGl6ZSBzZWNvbmRhcnkga2V5c1xuICAgICAgICBsZXQgc2VjVHlwZSA9IHNlY29uZGFyeT8uY29tcGV0ZW5jeUFyZWFOYW1lPy50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcbiAgICAgICAgbGV0IHNlY1RoZW1lID0gc2Vjb25kYXJ5Py5jb21wZXRlbmN5VGhlbWVOYW1lPy50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcbiAgICAgICAgbGV0IHNlY1N1YlRoZW1lID0gc2Vjb25kYXJ5Py5jb21wZXRlbmN5U3ViVGhlbWVOYW1lPy50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcbiAgICBcbiAgICAgICAgLy8gRml4IGZvciBkYXRhIGluY29uc2lzdGVuY3lcbiAgICAgICAgaWYgKHNlY1R5cGUgPT09ICdiZWhhdmlvdXJhbCcpIHNlY1R5cGUgPSAnYmVoYXZpb3JhbCc7XG4gICAgXG4gICAgICAgIC8vIENyZWF0ZSB1bmlxdWUgbWF0Y2gga2V5IGZvciBwcmltYXJ5IGNvbXBldGVuY3lcbiAgICAgICAgY29uc3QgbWF0Y2hLZXkgPSBgJHt0eXBlS2V5fXwke3RoZW1lS2V5fXwke3N1YlRoZW1lS2V5fWA7XG4gICAgXG4gICAgICAgIC8vIEVuaGFuY2VkIGNyb3NzLW1hdGNoaW5nIGxvZ2ljIGFzIHJlcXVlc3RlZDpcbiAgICAgICAgLy8gMS4gUm9sZSBtYXBwaW5nIFRoZW1lIHZzIENvdXJzZSBUaGVtZVxuICAgICAgICAvLyAyLiBSb2xlIG1hcHBpbmcgU3ViIFRoZW1lIHZzIENvdXJzZSBTdWIgVGhlbWUgIFxuICAgICAgICAvLyAzLiBSb2xlIG1hcHBpbmcgVGhlbWUgdnMgQ291cnNlIFN1YiBUaGVtZVxuICAgICAgICAvLyA0LiBSb2xlIG1hcHBpbmcgU3ViIFRoZW1lIHZzIENvdXJzZSBUaGVtZVxuICAgICAgICBjb25zdCB0aGVtZVRvVGhlbWVNYXRjaCA9IHRoZW1lS2V5ID09PSBzZWNUaGVtZTtcbiAgICAgICAgY29uc3Qgc3ViVGhlbWVUb1N1YlRoZW1lTWF0Y2ggPSBzdWJUaGVtZUtleSA9PT0gc2VjU3ViVGhlbWU7XG4gICAgICAgIGNvbnN0IHRoZW1lVG9TdWJUaGVtZU1hdGNoID0gdGhlbWVLZXkgPT09IHNlY1N1YlRoZW1lO1xuICAgICAgICBjb25zdCBzdWJUaGVtZVRvVGhlbWVNYXRjaCA9IHN1YlRoZW1lS2V5ID09PSBzZWNUaGVtZTtcbiAgICAgICAgXG4gICAgICAgIGxldCBtYXRjaFR5cGUgPSAnJztcbiAgICAgICAgbGV0IGlzTWF0Y2ggPSBmYWxzZTtcbiAgICAgICAgXG4gICAgICAgIGlmICh0eXBlS2V5ID09PSBzZWNUeXBlICYmICFzZWVuLmhhcyhtYXRjaEtleSkpIHtcbiAgICAgICAgICBpZiAodGhlbWVUb1RoZW1lTWF0Y2gpIHtcbiAgICAgICAgICAgIG1hdGNoVHlwZSA9ICdUaGVtZS10by1UaGVtZSc7XG4gICAgICAgICAgICBpc01hdGNoID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHN1YlRoZW1lVG9TdWJUaGVtZU1hdGNoKSB7XG4gICAgICAgICAgICBtYXRjaFR5cGUgPSAnU3ViVGhlbWUtdG8tU3ViVGhlbWUnO1xuICAgICAgICAgICAgaXNNYXRjaCA9IHRydWU7XG4gICAgICAgICAgfSBlbHNlIGlmICh0aGVtZVRvU3ViVGhlbWVNYXRjaCkge1xuICAgICAgICAgICAgbWF0Y2hUeXBlID0gJ1RoZW1lLXRvLVN1YlRoZW1lJztcbiAgICAgICAgICAgIGlzTWF0Y2ggPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoc3ViVGhlbWVUb1RoZW1lTWF0Y2gpIHtcbiAgICAgICAgICAgIG1hdGNoVHlwZSA9ICdTdWJUaGVtZS10by1UaGVtZSc7XG4gICAgICAgICAgICBpc01hdGNoID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNNYXRjaCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGDinIUgTUFUQ0ggRk9VTkQgWyR7bWF0Y2hUeXBlfV06YCwge1xuICAgICAgICAgICAgcm9sZU1hcHBpbmc6IHsgdHlwZTogdHlwZUtleSwgdGhlbWU6IHRoZW1lS2V5LCBzdWJUaGVtZTogc3ViVGhlbWVLZXkgfSxcbiAgICAgICAgICAgIGNvdXJzZTogeyB0eXBlOiBzZWNUeXBlLCB0aGVtZTogc2VjVGhlbWUsIHN1YlRoZW1lOiBzZWNTdWJUaGVtZSB9LFxuICAgICAgICAgICAgbWF0Y2hUeXBlOiBtYXRjaFR5cGVcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBTdG9yZSBtYXRjaGVkIGNvbXBldGVuY3kgaW5mbyBmb3IgbGF0ZXIgdXNlXG4gICAgICAgICAgbGV0IG9iaiA9IHt9O1xuICAgICAgICAgIG9ialt0eXBlS2V5XSA9IFt0aGVtZUtleV07IC8vIFN0b3JlIHRoZSBvcmlnaW5hbCB0aGVtZSwgbm90IHRoZSBjb3Vyc2UgdGhlbWVcbiAgICAgICAgICB0aGlzLmNvbXBldGVuY3lOb3RNYXRjaGVkQnlDYXRlZ29yeS5wdXNoKG9iaik7XG4gICAgICAgICAgc2Vlbi5hZGQobWF0Y2hLZXkpO1xuICAgICAgICAgIG1hdGNoZWRDb21wZXRlbmNpZXMuYWRkKHRoZW1lS2V5KTsgLy8gVHJhY2sgbWF0Y2hlZCB0aGVtZXNcbiAgICAgICAgICBpc01hdGNoZWQgPSB0cnVlO1xuICAgICAgICAgIFxuICAgICAgICAgIGlmIChjb3VudHMuaGFzT3duUHJvcGVydHkodHlwZUtleSkpIHtcbiAgICAgICAgICAgIGNvdW50c1t0eXBlS2V5XSsrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb3VudHNbdHlwZUtleV0gPSAxO1xuICAgICAgICAgIH1cbiAgICBcbiAgICAgICAgICBjb3VudHMudG90YWwrKztcbiAgICAgICAgICBicmVhazsgLy8gU3RvcCBsb29raW5nIGZvciBtYXRjaGVzIGZvciB0aGlzIHByaW1hcnkgY29tcGV0ZW5jeVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBjb3VudHM7XG4gIH1cbiAgZ2V0Q29tcGV0ZW5jeUJ5Q2F0ZWdvcnlOb3RNYXRjaGluZyhjYXRlZ29yeVR5cGUpIHtcbiAgICAvLyBHZXQgYWxsIGNvbXBldGVuY2llcyBmb3IgdGhlIGdpdmVuIGNhdGVnb3J5IGZyb20gcm9sZSBtYXBwaW5nXG4gICAgbGV0IGFsbENhdGVnb3J5Q29tcGV0ZW5jaWVzID0gW107XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IHRoaXMucGxhbkRhdGEuY29tcGV0ZW5jaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZih0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llc1tpXVsndHlwZSddPy50b0xvd2VyQ2FzZSgpID09PSBjYXRlZ29yeVR5cGU/LnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgYWxsQ2F0ZWdvcnlDb21wZXRlbmNpZXMucHVzaCh0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llc1tpXVsndGhlbWUnXT8udG9Mb3dlckNhc2UoKS50cmltKCkpO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvLyBHZXQgbWF0Y2hlZCBjb21wZXRlbmNpZXMgZm9yIHRoaXMgY2F0ZWdvcnkgZnJvbSBjb3Vyc2VzXG4gICAgbGV0IG1hdGNoZWRDb21wZXRlbmNpZXMgPSBbXTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jb21wZXRlbmN5Tm90TWF0Y2hlZEJ5Q2F0ZWdvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmKHRoaXMuY29tcGV0ZW5jeU5vdE1hdGNoZWRCeUNhdGVnb3J5W2ldW2NhdGVnb3J5VHlwZT8udG9Mb3dlckNhc2UoKV0pIHtcbiAgICAgICAgLy8gRXh0cmFjdCBtYXRjaGVkIHRoZW1lcyBmcm9tIGNvdXJzZSBjb21wZXRlbmNpZXNcbiAgICAgICAgdGhpcy5jb21wZXRlbmN5Tm90TWF0Y2hlZEJ5Q2F0ZWdvcnlbaV1bY2F0ZWdvcnlUeXBlPy50b0xvd2VyQ2FzZSgpXS5mb3JFYWNoKHRoZW1lID0+IHtcbiAgICAgICAgICBpZih0aGVtZSkge1xuICAgICAgICAgICAgbWF0Y2hlZENvbXBldGVuY2llcy5wdXNoKHRoZW1lLnRvTG93ZXJDYXNlKCkudHJpbSgpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvLyBFbmhhbmNlZCBtYXRjaGluZzogY2hlY2sgYm90aCB0aGVtZSBhbmQgc3VidGhlbWUgZnJvbSBjb3Vyc2VzIGFnYWluc3QgRlJBQyBjb21wZXRlbmNpZXNcbiAgICAvLyBJTVBPUlRBTlQ6IFVzZSBhbGwgYXZhaWxhYmxlIGNvdXJzZXMgZm9yIGNvbnNpc3RlbnQgY292ZXJhZ2UgY2FsY3VsYXRpb25cbiAgICBjb25zdCBhbGxDb3Vyc2VzRm9yTWF0Y2hpbmcgPSB0aGlzLmdldEFsbEF2YWlsYWJsZUNvdXJzZXMoKTtcbiAgICBcbiAgICBhbGxDb3Vyc2VzRm9yTWF0Y2hpbmcuZm9yRWFjaChjb3Vyc2UgPT4ge1xuICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBjb21wZXRlbmN5IHByb3BlcnR5IG5hbWVzXG4gICAgICBsZXQgY29tcGV0ZW5jaWVzID0gW107XG4gICAgICBpZiAoY291cnNlICYmIGNvdXJzZS5jb21wZXRlbmNpZXMgJiYgQXJyYXkuaXNBcnJheShjb3Vyc2UuY29tcGV0ZW5jaWVzKSkge1xuICAgICAgICBjb21wZXRlbmNpZXMgPSBjb3Vyc2UuY29tcGV0ZW5jaWVzO1xuICAgICAgfSBlbHNlIGlmIChjb3Vyc2UgJiYgY291cnNlLmNvbXBldGVuY2llc192NiAmJiBBcnJheS5pc0FycmF5KGNvdXJzZS5jb21wZXRlbmNpZXNfdjYpKSB7XG4gICAgICAgIGNvbXBldGVuY2llcyA9IGNvdXJzZS5jb21wZXRlbmNpZXNfdjY7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbXBldGVuY2llcy5mb3JFYWNoKChjb21wOiBhbnkpID0+IHtcbiAgICAgICAgbGV0IHNlY1R5cGUgPSBjb21wPy5jb21wZXRlbmN5QXJlYU5hbWU/LnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICBpZihzZWNUeXBlID09PSAnYmVoYXZpb3VyYWwnKSBzZWNUeXBlID0gJ2JlaGF2aW9yYWwnO1xuICAgICAgICBcbiAgICAgICAgaWYoc2VjVHlwZSA9PT0gY2F0ZWdvcnlUeXBlPy50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgY29uc3QgY291cnNlVGhlbWUgPSBjb21wLmNvbXBldGVuY3lUaGVtZU5hbWU/LnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICAgIGNvbnN0IGNvdXJzZVN1YlRoZW1lID0gY29tcC5jb21wZXRlbmN5U3ViVGhlbWVOYW1lPy50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBDaGVjayBpZiBhbnkgRlJBQyBjb21wZXRlbmN5IG1hdGNoZXMgdGhpcyBjb3Vyc2UgY29tcGV0ZW5jeVxuICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgZnJhY0NvbXAgPSB0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llc1tpXTtcbiAgICAgICAgICAgIGlmKGZyYWNDb21wWyd0eXBlJ10/LnRvTG93ZXJDYXNlKCkgPT09IGNhdGVnb3J5VHlwZT8udG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgICBjb25zdCBmcmFjVGhlbWUgPSBmcmFjQ29tcFsndGhlbWUnXT8udG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgICAgICAgICAgIGNvbnN0IGZyYWNTdWJUaGVtZSA9IGZyYWNDb21wWydzdWJfdGhlbWUnXT8udG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAvLyBFbmhhbmNlZCBjcm9zcy1tYXRjaGluZyBsb2dpYyAoc2FtZSBhcyBpbiBnZXRNYXRjaGVkQ29tcGV0ZW5jeVN0YXRzKTpcbiAgICAgICAgICAgICAgLy8gMS4gQ291cnNlIFRoZW1lIHZzIEZSQUMgVGhlbWVcbiAgICAgICAgICAgICAgLy8gMi4gQ291cnNlIFN1YiBUaGVtZSB2cyBGUkFDIFN1YiBUaGVtZSAgXG4gICAgICAgICAgICAgIC8vIDMuIENvdXJzZSBUaGVtZSB2cyBGUkFDIFN1YiBUaGVtZVxuICAgICAgICAgICAgICAvLyA0LiBDb3Vyc2UgU3ViIFRoZW1lIHZzIEZSQUMgVGhlbWVcbiAgICAgICAgICAgICAgY29uc3QgY291cnNlVGhlbWVUb0ZyYWNUaGVtZSA9IGNvdXJzZVRoZW1lID09PSBmcmFjVGhlbWU7XG4gICAgICAgICAgICAgIGNvbnN0IGNvdXJzZVN1YlRoZW1lVG9GcmFjU3ViVGhlbWUgPSBjb3Vyc2VTdWJUaGVtZSA9PT0gZnJhY1N1YlRoZW1lO1xuICAgICAgICAgICAgICBjb25zdCBjb3Vyc2VUaGVtZVRvRnJhY1N1YlRoZW1lID0gY291cnNlVGhlbWUgPT09IGZyYWNTdWJUaGVtZTtcbiAgICAgICAgICAgICAgY29uc3QgY291cnNlU3ViVGhlbWVUb0ZyYWNUaGVtZSA9IGNvdXJzZVN1YlRoZW1lID09PSBmcmFjVGhlbWU7XG4gICAgICAgICAgICAgIFxuICAgICAgICAgICAgICBpZihjb3Vyc2VUaGVtZVRvRnJhY1RoZW1lIHx8IGNvdXJzZVN1YlRoZW1lVG9GcmFjU3ViVGhlbWUgfHwgXG4gICAgICAgICAgICAgICAgIGNvdXJzZVRoZW1lVG9GcmFjU3ViVGhlbWUgfHwgY291cnNlU3ViVGhlbWVUb0ZyYWNUaGVtZSkge1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGxldCBtYXRjaFR5cGUgPSAnJztcbiAgICAgICAgICAgICAgICBpZiAoY291cnNlVGhlbWVUb0ZyYWNUaGVtZSkgbWF0Y2hUeXBlID0gJ0NvdXJzZVRoZW1lLXRvLUZSQUNUaGVtZSc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY291cnNlU3ViVGhlbWVUb0ZyYWNTdWJUaGVtZSkgbWF0Y2hUeXBlID0gJ0NvdXJzZVN1YlRoZW1lLXRvLUZSQUNTdWJUaGVtZSc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY291cnNlVGhlbWVUb0ZyYWNTdWJUaGVtZSkgbWF0Y2hUeXBlID0gJ0NvdXJzZVRoZW1lLXRvLUZSQUNTdWJUaGVtZSc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY291cnNlU3ViVGhlbWVUb0ZyYWNUaGVtZSkgbWF0Y2hUeXBlID0gJ0NvdXJzZVN1YlRoZW1lLXRvLUZSQUNUaGVtZSc7XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coYOKchSBDT01QRVRFTkNZIE1BVENIIEZPVU5EIFske21hdGNoVHlwZX1dIGZvciAke2NhdGVnb3J5VHlwZX06YCwge1xuICAgICAgICAgICAgICAgICAgY291cnNlOiB7IHRoZW1lOiBjb3Vyc2VUaGVtZSwgc3ViVGhlbWU6IGNvdXJzZVN1YlRoZW1lIH0sXG4gICAgICAgICAgICAgICAgICBmcmFjOiB7IHRoZW1lOiBmcmFjVGhlbWUsIHN1YlRoZW1lOiBmcmFjU3ViVGhlbWUgfSxcbiAgICAgICAgICAgICAgICAgIG1hdGNoVHlwZTogbWF0Y2hUeXBlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgbWF0Y2hlZENvbXBldGVuY2llcy5wdXNoKGZyYWNUaGVtZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7IC8vIEZvdW5kIGEgbWF0Y2gsIG1vdmUgdG8gbmV4dCBjb3Vyc2UgY29tcGV0ZW5jeVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBcbiAgICAvLyBSZW1vdmUgZHVwbGljYXRlcyBmcm9tIG1hdGNoZWQgY29tcGV0ZW5jaWVzXG4gICAgbWF0Y2hlZENvbXBldGVuY2llcyA9IFsuLi5uZXcgU2V0KG1hdGNoZWRDb21wZXRlbmNpZXMpXTtcbiAgICBcbiAgICBjb25zb2xlLmxvZyhgXFxuPT09ICR7Y2F0ZWdvcnlUeXBlLnRvVXBwZXJDYXNlKCl9IENPTVBFVEVOQ1kgTUFUQ0hJTkcgPT09YCk7XG4gICAgY29uc29sZS5sb2coYCR7Y2F0ZWdvcnlUeXBlfSAtIEFsbCBGUkFDIGNvbXBldGVuY2llczpgLCBhbGxDYXRlZ29yeUNvbXBldGVuY2llcyk7XG4gICAgY29uc29sZS5sb2coYCR7Y2F0ZWdvcnlUeXBlfSAtIE1hdGNoZWQgZnJvbSBjb3Vyc2VzOmAsIG1hdGNoZWRDb21wZXRlbmNpZXMpO1xuICAgIGNvbnNvbGUubG9nKGAke2NhdGVnb3J5VHlwZX0gLSBNYXRjaCByYXRlOiAke21hdGNoZWRDb21wZXRlbmNpZXMubGVuZ3RofS8ke2FsbENhdGVnb3J5Q29tcGV0ZW5jaWVzLmxlbmd0aH0gKCR7TWF0aC5yb3VuZCgobWF0Y2hlZENvbXBldGVuY2llcy5sZW5ndGgvYWxsQ2F0ZWdvcnlDb21wZXRlbmNpZXMubGVuZ3RoKSoxMDApfSUpYCk7XG4gICAgXG4gICAgLy8gUmV0dXJuIHVubWF0Y2hlZCBjb21wZXRlbmNpZXMgKHRob3NlIGluIHJvbGUgbWFwcGluZyBidXQgbm90IGNvdmVyZWQgYnkgY291cnNlcylcbiAgICByZXR1cm4gdGhpcy5jb21wYXJlU3RyaW5nQXJyYXlzKGFsbENhdGVnb3J5Q29tcGV0ZW5jaWVzLCBtYXRjaGVkQ29tcGV0ZW5jaWVzKTtcbiAgfVxuXG4gIGNvbXBhcmVTdHJpbmdBcnJheXMoYXJyMTogc3RyaW5nW10sIGFycjI6IHN0cmluZ1tdKSB7XG4gICAgY29uc29sZS5sb2coJ0FsbCBjb21wZXRlbmNpZXMgaW4gY2F0ZWdvcnk6JywgYXJyMSk7XG4gICAgY29uc29sZS5sb2coJ01hdGNoZWQgY29tcGV0ZW5jaWVzIGZyb20gY291cnNlczonLCBhcnIyKTtcbiAgICBcbiAgICAvLyBSZXR1cm4gaXRlbXMgaW4gYXJyMSB0aGF0IGFyZSBOT1QgaW4gYXJyMiAodW5tYXRjaGVkIGNvbXBldGVuY2llcylcbiAgICBjb25zdCB1bm1hdGNoZWQgPSBhcnIxLmZpbHRlcihpdGVtID0+ICFhcnIyLmluY2x1ZGVzKGl0ZW0pKTtcbiAgICBjb25zb2xlLmxvZygnVW5tYXRjaGVkIGNvbXBldGVuY2llczonLCB1bm1hdGNoZWQpO1xuICAgIFxuICAgIHJldHVybiB1bm1hdGNoZWQ7XG4gIH1cbiAgXG4gIGFkZENvdXJzZShtaXNzaW5nQ29tcGV0ZW5jeT86IHN0cmluZywgY29tcGV0ZW5jeVR5cGU/OiBzdHJpbmcpIHtcbiAgICBsZXQgZGlhbG9nRGF0YSA9IHsgLi4udGhpcy5wbGFuRGF0YSB9O1xuICAgIFxuICAgIC8vIElmIGNvbXBldGVuY3kgcGFyYW1ldGVycyBhcmUgcHJvdmlkZWQsIGFkZCB0aGVtIHRvIHRoZSBkaWFsb2cgZGF0YVxuICAgIGlmIChtaXNzaW5nQ29tcGV0ZW5jeSAmJiBjb21wZXRlbmN5VHlwZSkge1xuICAgICAgLy8gUGFyc2UgdGhlIHRoZW1lIGZyb20gdGhlIG1pc3NpbmcgY29tcGV0ZW5jeSBzdHJpbmcgKGFzc3VtZXMgZm9ybWF0IFwidGhlbWUtc3VidGhlbWVcIiBvciBqdXN0IFwidGhlbWVcIilcbiAgICAgIGNvbnN0IHRoZW1lID0gbWlzc2luZ0NvbXBldGVuY3kudHJpbSgpO1xuICAgICAgXG4gICAgICBkaWFsb2dEYXRhLnByZWZpbGxDb21wZXRlbmN5ID0ge1xuICAgICAgICB0eXBlOiBjb21wZXRlbmN5VHlwZSxcbiAgICAgICAgdGhlbWU6IHRoZW1lXG4gICAgICB9O1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKEFkZENvdXJzZUNvbXBvbmVudCwge1xuICAgICAgd2lkdGg6ICcxMDAwcHgnLFxuICAgICAgZGF0YTogZGlhbG9nRGF0YSxcbiAgICAgICBwYW5lbENsYXNzOiAndmlldy1jYnAtcGxhbi1wb3B1cCcsXG4gICAgICBtaW5IZWlnaHQ6ICc0MDBweCcsICAgICAgICAgIC8vIFNldCBtaW5pbXVtIGhlaWdodFxuICAgICAgbWF4SGVpZ2h0OiAnOTB2aCcsICAgICAgICAgICAvLyBQcmV2ZW50IGl0IGZyb20gZ29pbmcgYmV5b25kIHZpZXdwb3J0XG4gICAgICBkaXNhYmxlQ2xvc2U6IHRydWUgLy8gT3B0aW9uYWw6IHByZXZlbnQgY2xvc2luZyB3aXRoIG91dHNpZGUgY2xpY2tcbiAgICB9KTtcbiAgXG4gICAgZGlhbG9nUmVmLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0ID09PSAnc2F2ZWQnKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdDb3Vyc2UgYWRkZWQgc3VjY2Vzc2Z1bGx5ISBSZWZyZXNoaW5nIGRhdGEuLi4nKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFJlZnJlc2ggdXNlciBjb3Vyc2VzIHRvIGluY2x1ZGUgdGhlIG5ld2x5IGFkZGVkIGNvdXJzZVxuICAgICAgICB0aGlzLmdldFVzZXJDb3Vyc2UoKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFJlZnJlc2ggZ2FwIGFuYWx5c2lzIHdpdGggdGhlIGxhdGVzdCBkYXRhXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMudXBkYXRlR2FwQW5hbHlzaXNBZnRlckNvdXJzZXNVcGRhdGUoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZygnR2FwIGFuYWx5c2lzIHJlZnJlc2hlZCBhZnRlciBjb3Vyc2UgYWRkaXRpb24nKTtcbiAgICAgICAgfSwgNTAwKTsgLy8gU21hbGwgZGVsYXkgdG8gZW5zdXJlIGRhdGEgaXMgbG9hZGVkXG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBmaWx0ZXJPbkNvbXBldGVuY3lUaGVtZSh0aGVtZUl0ZW0pIHtcbiAgICB0aGlzLnNlbGVjdGVkVGhlbWVGaWx0ZXIgPSB0aGVtZUl0ZW07XG4gICAgbGV0IHRoZW1lTmFtZSA9IHRoZW1lSXRlbT8uc3BsaXQoXCItXCIpWzBdPy50cmltKCk7XG4gICAgbGV0IHN1YlRoZW1lTmFtZSA9IHRoZW1lSXRlbT8uc3BsaXQoXCItXCIpWzFdPy50cmltKCk7XG4gICAgXG4gICAgY29uc29sZS5sb2coJ0ZpbHRlcmluZyBieSB0aGVtZTonLCB0aGVtZU5hbWUsICdzdWJUaGVtZTonLCBzdWJUaGVtZU5hbWUsICdUYWIgaW5kZXg6JywgdGhpcy5pbm5lclRhYkFjdGl2ZUluZGV4KTtcbiAgICBcbiAgICAvLyBHZXQgdGhlIGN1cnJlbnQgY29tcGV0ZW5jeSB0eXBlIGJhc2VkIG9uIHRoZSBhY3RpdmUgdGFiXG4gICAgbGV0IGNvbXBldGVuY3lUeXBlID0gJyc7XG4gICAgaWYodGhpcy5pbm5lclRhYkFjdGl2ZUluZGV4ID09PSAxKSB7XG4gICAgICBjb21wZXRlbmN5VHlwZSA9ICdiZWhhdmlvcmFsJztcbiAgICB9IGVsc2UgaWYodGhpcy5pbm5lclRhYkFjdGl2ZUluZGV4ID09PSAyKSB7XG4gICAgICBjb21wZXRlbmN5VHlwZSA9ICdmdW5jdGlvbmFsJztcbiAgICB9IGVsc2UgaWYodGhpcy5pbm5lclRhYkFjdGl2ZUluZGV4ID09PSAzKSB7XG4gICAgICBjb21wZXRlbmN5VHlwZSA9ICdkb21haW4nO1xuICAgIH1cbiAgICBcbiAgICAvLyBHZXQgYWxsIGF2YWlsYWJsZSBjb3Vyc2VzIHVzaW5nIHRoZSBoZWxwZXIgbWV0aG9kXG4gICAgY29uc3QgYWxsQXZhaWxhYmxlQ291cnNlcyA9IHRoaXMuZ2V0QWxsQXZhaWxhYmxlQ291cnNlcygpO1xuICAgIGNvbnNvbGUubG9nKCdUb3RhbCBjb3Vyc2VzIHRvIGZpbHRlciBmcm9tOicsIGFsbEF2YWlsYWJsZUNvdXJzZXMubGVuZ3RoKTtcbiAgICBcbiAgICB0aGlzLmZpbHRlcmRDb3Vyc2VzID0gYWxsQXZhaWxhYmxlQ291cnNlcy5maWx0ZXIoY291cnNlID0+IHtcbiAgICAgIGlmICghY291cnNlKSByZXR1cm4gZmFsc2U7XG4gICAgICBcbiAgICAgIC8vIEhhbmRsZSBkaWZmZXJlbnQgY29tcGV0ZW5jeSBwcm9wZXJ0eSBuYW1lc1xuICAgICAgbGV0IGNvbXBldGVuY2llcyA9IFtdO1xuICAgICAgaWYgKGNvdXJzZS5jb21wZXRlbmNpZXMgJiYgQXJyYXkuaXNBcnJheShjb3Vyc2UuY29tcGV0ZW5jaWVzKSkge1xuICAgICAgICBjb21wZXRlbmNpZXMgPSBjb3Vyc2UuY29tcGV0ZW5jaWVzO1xuICAgICAgfSBlbHNlIGlmIChjb3Vyc2UuY29tcGV0ZW5jaWVzX3Y2ICYmIEFycmF5LmlzQXJyYXkoY291cnNlLmNvbXBldGVuY2llc192NikpIHtcbiAgICAgICAgY29tcGV0ZW5jaWVzID0gY291cnNlLmNvbXBldGVuY2llc192NjtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKGNvbXBldGVuY2llcy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgICAgIFxuICAgICAgLy8gRmlsdGVyIGJ5IGNvbXBldGVuY3kgdHlwZSBhbmQgdGhlbWUvc3VidGhlbWVcbiAgICAgIHJldHVybiBjb21wZXRlbmNpZXMuc29tZShjb21wID0+IHtcbiAgICAgICAgaWYgKCFjb21wKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIFxuICAgICAgICAvLyBDaGVjayBjb21wZXRlbmN5IHR5cGUgbWF0Y2hlcyBjdXJyZW50IHRhYlxuICAgICAgICBsZXQgY29tcFR5cGUgPSBjb21wPy5jb21wZXRlbmN5QXJlYU5hbWU/LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmIChjb21wVHlwZSA9PT0gJ2JlaGF2aW91cmFsJykgY29tcFR5cGUgPSAnYmVoYXZpb3JhbCc7IC8vIE5vcm1hbGl6ZSBzcGVsbGluZ1xuICAgICAgICBcbiAgICAgICAgaWYgKGNvbXBUeXBlICE9PSBjb21wZXRlbmN5VHlwZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBcbiAgICAgICAgLy8gQ2hlY2sgY3Jvc3MtbWF0Y2hpbmcgbGlrZSBnYXAgYW5hbHlzaXM6IHRoZW1lIHZzIHN1YnRoZW1lIGFuZCBzdWJ0aGVtZSB2cyB0aGVtZVxuICAgICAgICBjb25zdCBjb21wVGhlbWUgPSBjb21wPy5jb21wZXRlbmN5VGhlbWVOYW1lPy50b0xvd2VyQ2FzZSgpPy50cmltKCk7XG4gICAgICAgIGNvbnN0IGNvbXBTdWJUaGVtZSA9IGNvbXA/LmNvbXBldGVuY3lTdWJUaGVtZU5hbWU/LnRvTG93ZXJDYXNlKCk/LnRyaW0oKTtcbiAgICAgICAgY29uc3Qgc2VhcmNoVGhlbWUgPSB0aGVtZU5hbWU/LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGNvbnN0IHNlYXJjaFN1YlRoZW1lID0gc3ViVGhlbWVOYW1lPy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBcbiAgICAgICAgLy8gRW5oYW5jZWQgY3Jvc3MtbWF0Y2hpbmcgbG9naWMgbGlrZSBnYXAgYW5hbHlzaXM6XG4gICAgICAgIC8vIDEuIFNlbGVjdGVkIFRoZW1lIHZzIENvdXJzZSBUaGVtZVxuICAgICAgICAvLyAyLiBTZWxlY3RlZCBTdWIgVGhlbWUgdnMgQ291cnNlIFN1YiBUaGVtZSAgXG4gICAgICAgIC8vIDMuIFNlbGVjdGVkIFRoZW1lIHZzIENvdXJzZSBTdWIgVGhlbWVcbiAgICAgICAgLy8gNC4gU2VsZWN0ZWQgU3ViIFRoZW1lIHZzIENvdXJzZSBUaGVtZVxuICAgICAgICBjb25zdCB0aGVtZVRvVGhlbWVNYXRjaCA9IHNlYXJjaFRoZW1lICYmIGNvbXBUaGVtZSA9PT0gc2VhcmNoVGhlbWU7XG4gICAgICAgIGNvbnN0IHN1YlRoZW1lVG9TdWJUaGVtZU1hdGNoID0gc2VhcmNoU3ViVGhlbWUgJiYgY29tcFN1YlRoZW1lID09PSBzZWFyY2hTdWJUaGVtZTtcbiAgICAgICAgY29uc3QgdGhlbWVUb1N1YlRoZW1lTWF0Y2ggPSBzZWFyY2hUaGVtZSAmJiBjb21wU3ViVGhlbWUgPT09IHNlYXJjaFRoZW1lO1xuICAgICAgICBjb25zdCBzdWJUaGVtZVRvVGhlbWVNYXRjaCA9IHNlYXJjaFN1YlRoZW1lICYmIGNvbXBUaGVtZSA9PT0gc2VhcmNoU3ViVGhlbWU7XG4gICAgICAgIFxuICAgICAgICBjb25zdCBpc01hdGNoID0gdGhlbWVUb1RoZW1lTWF0Y2ggfHwgc3ViVGhlbWVUb1N1YlRoZW1lTWF0Y2ggfHwgdGhlbWVUb1N1YlRoZW1lTWF0Y2ggfHwgc3ViVGhlbWVUb1RoZW1lTWF0Y2g7XG4gICAgICAgIFxuICAgICAgICAvLyBMb2cgbWF0Y2hlcyBmb3IgZGVidWdnaW5nIChzaW1pbGFyIHRvIGdhcCBhbmFseXNpcylcbiAgICAgICAgaWYgKGlzTWF0Y2gpIHtcbiAgICAgICAgICBsZXQgbWF0Y2hUeXBlID0gJyc7XG4gICAgICAgICAgaWYgKHRoZW1lVG9UaGVtZU1hdGNoKSBtYXRjaFR5cGUgPSAnVGhlbWUtdG8tVGhlbWUnO1xuICAgICAgICAgIGVsc2UgaWYgKHN1YlRoZW1lVG9TdWJUaGVtZU1hdGNoKSBtYXRjaFR5cGUgPSAnU3ViVGhlbWUtdG8tU3ViVGhlbWUnO1xuICAgICAgICAgIGVsc2UgaWYgKHRoZW1lVG9TdWJUaGVtZU1hdGNoKSBtYXRjaFR5cGUgPSAnVGhlbWUtdG8tU3ViVGhlbWUnO1xuICAgICAgICAgIGVsc2UgaWYgKHN1YlRoZW1lVG9UaGVtZU1hdGNoKSBtYXRjaFR5cGUgPSAnU3ViVGhlbWUtdG8tVGhlbWUnO1xuICAgICAgICAgIFxuICAgICAgICAgIGNvbnNvbGUubG9nKGDinIUgRklMVEVSIE1BVENIIEZPVU5EIFske21hdGNoVHlwZX1dOmAsIHtcbiAgICAgICAgICAgIHNlbGVjdGVkOiB7IHRoZW1lOiBzZWFyY2hUaGVtZSwgc3ViVGhlbWU6IHNlYXJjaFN1YlRoZW1lIH0sXG4gICAgICAgICAgICBjb3Vyc2U6IHsgdHlwZTogY29tcFR5cGUsIHRoZW1lOiBjb21wVGhlbWUsIHN1YlRoZW1lOiBjb21wU3ViVGhlbWUgfSxcbiAgICAgICAgICAgIG1hdGNoVHlwZTogbWF0Y2hUeXBlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIE1hdGNoIGlmIGFueSBvZiB0aGUgY3Jvc3MtbWF0Y2hpbmcgY29uZGl0aW9ucyBhcmUgbWV0XG4gICAgICAgIHJldHVybiBpc01hdGNoO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgXG4gICAgY29uc29sZS5sb2coJ0ZpbHRlcmVkIGNvdXJzZXMgZm9yIHRoZW1lOicsIHRoZW1lTmFtZSwgJ0NvdW50OicsIHRoaXMuZmlsdGVyZENvdXJzZXMubGVuZ3RoKTtcbiAgICBjb25zb2xlLmxvZygnRmlsdGVyZWQgY291cnNlczonLCB0aGlzLmZpbHRlcmRDb3Vyc2VzLm1hcChjID0+IGMubmFtZSB8fCBjLmNvdXJzZSkpO1xuICB9XG4gIFxuICBjbGVhclRoZW1lRmlsdGVyKCkge1xuICAgIHRoaXMuc2VsZWN0ZWRUaGVtZUZpbHRlciA9ICcnO1xuICAgIC8vIFJlc2V0IHRvIGNhdGVnb3J5IGZpbHRlcmVkIGNvdXJzZXMgYnkgY2FsbGluZyB0aGUgdGFiIGNoYW5nZSBtZXRob2RcbiAgICB0aGlzLm9uSW5uZXJUYWJDaGFuZ2UoeyBcbiAgICAgIGluZGV4OiB0aGlzLmlubmVyVGFiQWN0aXZlSW5kZXgsIFxuICAgICAgdGFiOiB7IHRleHRMYWJlbDogdGhpcy5pbm5lclRhYkFjdGl2ZVRleHQgfSBcbiAgICB9IGFzIGFueSk7XG4gICAgY29uc29sZS5sb2coJ1RoZW1lIGZpbHRlciBjbGVhcmVkLCBzaG93aW5nIGFsbCBjb3Vyc2VzIGZvciBjYXRlZ29yeTonLCB0aGlzLmlubmVyVGFiQWN0aXZlVGV4dCk7XG4gIH1cbiAgXG4gIGlzVGhlbWVTZWxlY3RlZCh0aGVtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRUaGVtZUZpbHRlciA9PT0gdGhlbWU7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGNvdXJzZSBmb3IgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCB0aGVtZSBmaWx0ZXIgd2l0aCBwcmVmaWxsZWQgY29tcGV0ZW5jeSBkYXRhXG4gICAqL1xuICBhZGRDb3Vyc2VGb3JTZWxlY3RlZFRoZW1lKCkge1xuICAgIGlmICghdGhpcy5zZWxlY3RlZFRoZW1lRmlsdGVyKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ05vIHRoZW1lIHNlbGVjdGVkIGZvciBhZGRpbmcgY291cnNlJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUGFyc2UgdGhlbWUgYW5kIHN1Yi10aGVtZSBmcm9tIHNlbGVjdGVkVGhlbWVGaWx0ZXIgKGZvcm1hdDogXCJUaGVtZSAtIFN1YlRoZW1lXCIpXG4gICAgY29uc3QgdGhlbWVQYXJ0cyA9IHRoaXMuc2VsZWN0ZWRUaGVtZUZpbHRlci5zcGxpdCgnLScpO1xuICAgIGNvbnN0IHRoZW1lID0gdGhlbWVQYXJ0c1swXT8udHJpbSgpO1xuICAgIGNvbnN0IHN1YlRoZW1lID0gdGhlbWVQYXJ0c1sxXT8udHJpbSgpO1xuXG4gICAgLy8gR2V0IHRoZSBjdXJyZW50IGNvbXBldGVuY3kgdHlwZSBiYXNlZCBvbiB0aGUgYWN0aXZlIHRhYlxuICAgIC8vIE1hcCB0aGUgdGFiIGxhYmVscyB0byB0aGUgZm9ybWF0IGV4cGVjdGVkIGJ5IEFkZENvdXJzZUNvbXBvbmVudFxuICAgIGxldCBjb21wZXRlbmN5VHlwZSA9ICcnO1xuICAgIGlmICh0aGlzLmlubmVyVGFiQWN0aXZlSW5kZXggPT09IDEpIHtcbiAgICAgIGNvbXBldGVuY3lUeXBlID0gJ0JlaGF2aW9yYWwnOyAvLyBUYWIgbGFiZWwgaXMgXCJiZWhhdmlvdXJhbFwiXG4gICAgfSBlbHNlIGlmICh0aGlzLmlubmVyVGFiQWN0aXZlSW5kZXggPT09IDIpIHtcbiAgICAgIGNvbXBldGVuY3lUeXBlID0gJ0Z1bmN0aW9uYWwnOyAvLyBUYWIgbGFiZWwgaXMgXCJmdW5jdGlvbmFsXCJcbiAgICB9IGVsc2UgaWYgKHRoaXMuaW5uZXJUYWJBY3RpdmVJbmRleCA9PT0gMykge1xuICAgICAgY29tcGV0ZW5jeVR5cGUgPSAnRG9tYWluJzsgLy8gVGFiIGxhYmVsIGlzIFwiZG9tYWluXCJcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZygnVGFiIG1hcHBpbmcgLSBpbm5lclRhYkFjdGl2ZUluZGV4OicsIHRoaXMuaW5uZXJUYWJBY3RpdmVJbmRleCwgXG4gICAgICAgICAgICAgICAgJ2lubmVyVGFiQWN0aXZlVGV4dDonLCB0aGlzLmlubmVyVGFiQWN0aXZlVGV4dCwgXG4gICAgICAgICAgICAgICAgJ21hcHBlZCBjb21wZXRlbmN5VHlwZTonLCBjb21wZXRlbmN5VHlwZSk7XG5cbiAgICBjb25zb2xlLmxvZygnQWRkaW5nIGNvdXJzZSBmb3IgbWlzc2luZyBjb21wZXRlbmN5OicsIHtcbiAgICAgIGNvbXBldGVuY3lUeXBlLFxuICAgICAgdGhlbWUsXG4gICAgICBzdWJUaGVtZSxcbiAgICAgIHNlbGVjdGVkVGhlbWVGaWx0ZXI6IHRoaXMuc2VsZWN0ZWRUaGVtZUZpbHRlclxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIGRpYWxvZyBkYXRhIHdpdGggcHJlZmlsbGVkIGNvbXBldGVuY3kgaW5mb3JtYXRpb25cbiAgICBsZXQgZGlhbG9nRGF0YSA9IHsgLi4udGhpcy5wbGFuRGF0YSB9O1xuICAgIGRpYWxvZ0RhdGEucHJlZmlsbENvbXBldGVuY3kgPSB7XG4gICAgICB0eXBlOiBjb21wZXRlbmN5VHlwZSxcbiAgICAgIHRoZW1lOiB0aGVtZSxcbiAgICAgIHN1YlRoZW1lOiBzdWJUaGVtZSB8fCAnJyAvLyBJbmNsdWRlIHN1Yi10aGVtZSBpZiBhdmFpbGFibGVcbiAgICB9O1xuXG4gICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihBZGRDb3Vyc2VDb21wb25lbnQsIHtcbiAgICAgIHdpZHRoOiAnODAwcHgnLFxuICAgICAgZGF0YTogZGlhbG9nRGF0YSxcbiAgICAgIHBhbmVsQ2xhc3M6ICd2aWV3LWNicC1wbGFuLXBvcHVwJyxcbiAgICAgIG1pbkhlaWdodDogJzQwMHB4JyxcbiAgICAgIG1heEhlaWdodDogJzkwdmgnLFxuICAgICAgZGlzYWJsZUNsb3NlOiB0cnVlXG4gICAgfSk7XG5cbiAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgIGlmIChyZXN1bHQgPT09ICdzYXZlZCcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ0NvdXJzZSBhZGRlZCBzdWNjZXNzZnVsbHkgZm9yIGNvbXBldGVuY3khIFJlZnJlc2hpbmcgZGF0YS4uLicpO1xuICAgICAgICBcbiAgICAgICAgLy8gUmVmcmVzaCB1c2VyIGNvdXJzZXMgdG8gaW5jbHVkZSB0aGUgbmV3bHkgYWRkZWQgY291cnNlXG4gICAgICAgIHRoaXMuZ2V0VXNlckNvdXJzZSgpO1xuICAgICAgICBcbiAgICAgICAgLy8gVXBkYXRlIGdhcCBhbmFseXNpcyBhZnRlciBjb3Vyc2UgYWRkaXRpb25cbiAgICAgICAgdGhpcy51cGRhdGVHYXBBbmFseXNpc0FmdGVyQ291cnNlc1VwZGF0ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZ2V0RHVyYXRpb24odGltZTphbnkpIHtcbiAgICByZXR1cm4gdGhpcy5zaGFyZWRTZXJ2aWNlLmNvbnZlcnQodGltZSk7XG4gIH1cblxuXG4gIGdldEJlaGF2aW91cmFsTWF0Y2hlZCgpIHtcbiAgICB0aGlzLmJlaGF2aW91cmFsTWF0Y2hlZCA9IFtdXG4gICAgY29uc29sZS5sb2coJ3RoaXMucGxhbkRhdGEuY29tcGV0ZW5jaWVzJywgdGhpcy5wbGFuRGF0YSlcbiAgICBjb25zb2xlLmxvZygndGhpcy5iZWhhdmlvdXJhbE5vdE1hdGNoZWQnLCB0aGlzLmJlaGF2aW91cmFsTm90TWF0Y2hlZClcbiAgICB0aGlzLnBsYW5EYXRhLmNvbXBldGVuY2llcy5tYXAoKGl0ZW0pPT57XG4gICAgICBpZihpdGVtICYmIGl0ZW0/LnR5cGUgPT09ICdCZWhhdmlvcmFsJyAmJiB0aGlzLmJlaGF2aW91cmFsTm90TWF0Y2hlZC5pbmRleE9mKGl0ZW0/LnRoZW1lPy50b0xvd2VyQ2FzZSgpKSA8IDApIHtcbiAgICAgICAgdGhpcy5iZWhhdmlvdXJhbE1hdGNoZWQucHVzaChpdGVtKVxuICAgICAgfVxuICAgIH0pXG5cbiAgICBjb25zb2xlLmxvZygndGhpcy5iZWhhdmlvdXJhbE1hdGNoZWQtLScsIHRoaXMuYmVoYXZpb3VyYWxNYXRjaGVkKVxuICB9XG5cbiAgZ2V0RnVuY3Rpb25hbE1hdGNoZWQoKSB7XG4gICAgdGhpcy5mdW5jdGlvbmFsTWF0Y2hlZCA9IFtdXG4gICAgdGhpcy5wbGFuRGF0YS5jb21wZXRlbmNpZXMubWFwKChpdGVtKT0+e1xuICAgICAgaWYoaXRlbSAmJiBpdGVtPy50eXBlID09PSAnRnVuY3Rpb25hbCcgJiYgdGhpcy5mdW5jdGlvbmFsTm90TWF0Y2hlZC5pbmRleE9mKGl0ZW0/LnRoZW1lPy50b0xvd2VyQ2FzZSgpKSA8IDApIHtcbiAgICAgICAgdGhpcy5mdW5jdGlvbmFsTWF0Y2hlZC5wdXNoKGl0ZW0pXG4gICAgICB9XG4gICAgfSlcbiAgICByZXR1cm4gdGhpcy5mdW5jdGlvbmFsTWF0Y2hlZFxuICB9XG5cbiAgZ2V0RG9tYWluTWF0Y2hlZCgpIHtcbiAgICB0aGlzLmRvbWFpbk1hdGNoZWQgPSBbXVxuICAgIHRoaXMucGxhbkRhdGEuY29tcGV0ZW5jaWVzLm1hcCgoaXRlbSk9PntcbiAgICAgIGlmKGl0ZW0gJiYgaXRlbT8udHlwZSA9PT0gJ0RvbWFpbicgJiYgdGhpcy5kb21haW5Ob3RNYXRjaGVkLmluZGV4T2YoaXRlbT8udGhlbWU/LnRvTG93ZXJDYXNlKCkpIDwgMCkge1xuICAgICAgICB0aGlzLmRvbWFpbk1hdGNoZWQucHVzaChpdGVtKVxuICAgICAgfVxuICAgIH0pXG4gICAgY29uc29sZS5sb2coJ3RoaXMuZG9tYWluTWF0Y2hlZC0tJywgdGhpcy5kb21haW5NYXRjaGVkKVxuICB9XG5cbiAgZG93bmxvYWRQREYoKSB7XG4gICAgdGhpcy5pc1BERkRvd25sb2FkID0gdHJ1ZVxuICAgIHRoaXMubG9hZGluZyA9IHRydWVcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5wZGZDb250ZW50Lm5hdGl2ZUVsZW1lbnQ7XG5cbiAgLy8gV2FpdCBmb3IgaW1hZ2VzIHRvIGxvYWRcbiAgY29uc3QgaW1hZ2VzID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdpbWcnKTtcbiAgY29uc3QgcHJvbWlzZXMgPSBBcnJheS5mcm9tKGltYWdlcykubWFwKChpbWc6IEhUTUxJbWFnZUVsZW1lbnQpID0+IHtcbiAgICBpZiAoaW1nLmNvbXBsZXRlKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gaW1nLm9ubG9hZCA9IHJlc29sdmUpO1xuICB9KTtcblxuICBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgIG1hcmdpbjogMC4yMCxcbiAgICAgIGZpbGVuYW1lOiAnR2FwIEFuYWx5c2lzLnBkZicsXG4gICAgICBpbWFnZTogeyB0eXBlOiAnanBlZycsIHF1YWxpdHk6IDAuOTggfSxcbiAgICAgIGh0bWwyY2FudmFzOiB7XG4gICAgICAgIHNjYWxlOiAyLFxuICAgICAgICB1c2VDT1JTOiB0cnVlLFxuICAgICAgICBzY3JvbGxZOiAwLFxuICAgICAgfSxcbiAgICAgIGpzUERGOiB7XG4gICAgICAgIHVuaXQ6ICdpbicsXG4gICAgICAgIGZvcm1hdDogJ2E0JyxcbiAgICAgICAgb3JpZW50YXRpb246ICdwb3J0cmFpdCdcbiAgICAgIH0sXG4gICAgICBwYWdlYnJlYWs6IHtcbiAgICAgICAgbW9kZTogWydjc3MnLCAnbGVnYWN5J10sXG4gICAgICAgIGJlZm9yZTogJy5wYWdlLWJyZWFrJyxcbiAgICAgICAgYXZvaWQ6IFsnLm5vLWJyZWFrJ11cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgaHRtbDJwZGYoKS5mcm9tKGVsZW1lbnQpLnNldChvcHRpb25zKS5zYXZlKClcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuaXNQREZEb3dubG9hZCA9IGZhbHNlXG4gICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICB9LCAzMDAwKTsgXG4gIH0pO1xuICB9XG5cblxuICByZWRpcmVjdFRvVG9jKGl0ZW0pIHtcbiAgICBpZihpdGVtPy5wdWJsaWNfbGluaykge1xuICAgICAgd2luZG93Lm9wZW4oaXRlbT8ucHVibGljX2xpbmssICdfYmxhbmsnKVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgdXJsID0gYGh0dHBzOi8vcG9ydGFsLmlnb3RrYXJtYXlvZ2kuZ292LmluL2FwcC90b2MvJHtpdGVtPy5pZGVudGlmaWVyfS9vdmVydmlldz9gXG4gICAgd2luZG93Lm9wZW4odXJsLCAnX2JsYW5rJylcbiAgICB9XG4gICAgXG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBnYXAgYW5hbHlzaXMgc3RhdHMgYWZ0ZXIgaW5pdGlhbCBkYXRhIGxvYWRcbiAgICovXG4gIGluaXRpYWxpemVHYXBBbmFseXNpc1N0YXRzKCkge1xuICAgIC8vIFNldCBhIHNtYWxsIHRpbWVvdXQgdG8gZW5zdXJlIGFsbCBhc3luYyBvcGVyYXRpb25zIGNvbXBsZXRlXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5maWx0ZXJkQ291cnNlcyAmJiB0aGlzLmZpbHRlcmRDb3Vyc2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5nYXBBbmFseXNpc1N0YXRzKCk7XG4gICAgICB9XG4gICAgfSwgMTAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgZ2FwIGFuYWx5c2lzIHN0YXRzIGFmdGVyIGNvdXJzZXMgYXJlIHVwZGF0ZWQgKGxpa2Ugc3VnZ2VzdGVkIGNvdXJzZXMgYWRkZWQpXG4gICAqL1xuICB1cGRhdGVHYXBBbmFseXNpc0FmdGVyQ291cnNlc1VwZGF0ZSgpIHtcbiAgICAvLyBEb24ndCBtb2RpZnkgb3JpZ2luYWxEYXRhIC0gaXQgc2hvdWxkIHJlbWFpbiBhcyBBSSByZWNvbW1lbmRlZCBjb3Vyc2VzIG9ubHlcbiAgICAvLyBUaGUgZ2FwIGFuYWx5c2lzIGFscmVhZHkgcHJvcGVybHkgaW5jbHVkZXMgYWxsIGNvdXJzZSB0eXBlc1xuICAgIFxuICAgIC8vIFJlY2FsY3VsYXRlIGdhcCBhbmFseXNpcyBzdGF0c1xuICAgIHRoaXMuZ2FwQW5hbHlzaXNTdGF0cygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2VuZXJhdGUgY291cnNlIHJlY29tbWVuZGF0aW9ucyBieSBkZWxldGluZyBleGlzdGluZyByZWNvbW1lbmRhdGlvbnMgYW5kIGdlbmVyYXRpbmcgbmV3IG9uZXNcbiAgICovXG4gIGFzeW5jIHJlZ2VuZXJhdGVDb3Vyc2VSZWNvbW1lbmRhdGlvbnMoKSB7XG4gICAgaWYgKHRoaXMuaXNSZWdlbmVyYXRpbmcpIHtcbiAgICAgIHJldHVybjsgLy8gUHJldmVudCBtdWx0aXBsZSBzaW11bHRhbmVvdXMgcmVnZW5lcmF0aW9uc1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICB0aGlzLmlzUmVnZW5lcmF0aW5nID0gdHJ1ZTtcbiAgICAgIFxuICAgICAgLy8gU2hvdyBjb25maXJtYXRpb24gZGlhbG9nXG4gICAgICBjb25zdCBjb25maXJtZWQgPSBhd2FpdCB0aGlzLnNob3dDb25maXJtYXRpb25EaWFsb2coKTtcbiAgICAgIFxuICAgICAgaWYgKCFjb25maXJtZWQpIHtcbiAgICAgICAgdGhpcy5pc1JlZ2VuZXJhdGluZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdTdGFydGluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb24gcmVnZW5lcmF0aW9uLi4uJyk7XG4gICAgICBcbiAgICAgIC8vIFNldCByZWdlbmVyYXRpb24gcHJvZ3Jlc3Mgc3RhdGVcbiAgICAgIHRoaXMuaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgdGhpcy5kYXRhTG9hZGVkID0gZmFsc2U7IC8vIEhpZGUgbWFpbiBjb250ZW50IGR1cmluZyByZWdlbmVyYXRpb25cbiAgICAgIFxuICAgICAgLy8gU3RlcCAxOiBEZWxldGUgZXhpc3RpbmcgY291cnNlIHJlY29tbWVuZGF0aW9uc1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGVDb3Vyc2VSZWNvbW1lbmRhdGlvbnMoKTtcbiAgICAgIFxuICAgICAgLy8gU3RlcCAyOiBHZW5lcmF0ZSBuZXcgY291cnNlIHJlY29tbWVuZGF0aW9uc1xuICAgICAgYXdhaXQgdGhpcy5nZW5lcmF0ZU5ld0NvdXJzZVJlY29tbWVuZGF0aW9ucygpO1xuICAgICAgXG4gICAgICAvLyBTdGVwIDM6IFJlZnJlc2ggdGhlIGN1cnJlbnQgZGF0YVxuICAgICAgdGhpcy5yZWZyZXNoQ29tcG9uZW50KCk7XG4gICAgICBcbiAgICAgIGNvbnNvbGUubG9nKCdDb3Vyc2UgcmVjb21tZW5kYXRpb24gcmVnZW5lcmF0aW9uIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgIFxuICAgICAgLy8gU2hvdyBzdWNjZXNzIG1lc3NhZ2VcbiAgICAgIHRoaXMuc25hY2tCYXIub3BlbignQ291cnNlIHJlY29tbWVuZGF0aW9ucyByZWdlbmVyYXRlZCBzdWNjZXNzZnVsbHkhJywgJ0Nsb3NlJywge1xuICAgICAgICBkdXJhdGlvbjogNTAwMCxcbiAgICAgICAgcGFuZWxDbGFzczogWydzdWNjZXNzLXNuYWNrYmFyJ11cbiAgICAgIH0pO1xuICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGR1cmluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb24gcmVnZW5lcmF0aW9uOicsIGVycm9yKTtcbiAgICAgIFxuICAgICAgLy8gU2hvdyBlcnJvciBtZXNzYWdlXG4gICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oJ0ZhaWxlZCB0byByZWdlbmVyYXRlIGNvdXJzZSByZWNvbW1lbmRhdGlvbnMuIFBsZWFzZSB0cnkgYWdhaW4uJywgJ0Nsb3NlJywge1xuICAgICAgICBkdXJhdGlvbjogNTAwMCxcbiAgICAgICAgcGFuZWxDbGFzczogWydlcnJvci1zbmFja2JhciddXG4gICAgICB9KTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5pc1JlZ2VuZXJhdGluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5pc1JlZ2VuZXJhdGluZ1dpdGhQcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgdGhpcy5kYXRhTG9hZGVkID0gdHJ1ZTsgLy8gRW5zdXJlIG1haW4gY29udGVudCBpcyBzaG93biBhZnRlciByZWdlbmVyYXRpb25cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2hvdyBjb25maXJtYXRpb24gZGlhbG9nIGZvciByZWdlbmVyYXRlIGFjdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBzaG93Q29uZmlybWF0aW9uRGlhbG9nKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgLy8gQ3JlYXRlIGEgY3VzdG9tIGNvbmZpcm1hdGlvbiBkaWFsb2dcbiAgICAgIGNvbnN0IGRpYWxvZ1JlZiA9IHRoaXMuZGlhbG9nLm9wZW4oUmVnZW5lcmF0ZUNvbmZpcm1hdGlvbkRpYWxvZywge1xuICAgICAgICB3aWR0aDogJzQ1MHB4JyxcbiAgICAgICAgcGFuZWxDbGFzczogJ3JlZ2VuZXJhdGUtY29uZmlybWF0aW9uLWRpYWxvZycsXG4gICAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZVxuICAgICAgfSk7XG5cbiAgICAgIGRpYWxvZ1JlZi5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShyZXN1bHQgPT4ge1xuICAgICAgICByZXNvbHZlKHJlc3VsdCA9PT0gdHJ1ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgZXhpc3RpbmcgY291cnNlIHJlY29tbWVuZGF0aW9ucyBmb3IgdGhlIGN1cnJlbnQgcm9sZSBtYXBwaW5nXG4gICAqL1xuICBwcml2YXRlIGRlbGV0ZUNvdXJzZVJlY29tbWVuZGF0aW9ucygpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByb2xlTWFwSWQgPSB0aGlzLnBsYW5EYXRhPy5pZDtcbiAgICAgIFxuICAgICAgaWYgKCFyb2xlTWFwSWQpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignUm9sZSBtYXBwaW5nIElEIG5vdCBmb3VuZCcpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zb2xlLmxvZygnRGVsZXRpbmcgY291cnNlIHJlY29tbWVuZGF0aW9ucyBmb3Igcm9sZSBtYXBwaW5nOicsIHJvbGVNYXBJZCk7XG4gICAgICBcbiAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5kZWxldGVDb3Vyc2VSZWNvbW1lbmRhdGlvbnMocm9sZU1hcElkKS5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnQ291cnNlIHJlY29tbWVuZGF0aW9ucyBkZWxldGVkIHN1Y2Nlc3NmdWxseTonLCByZXNwb25zZSk7XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSk7XG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBkZWxldGluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb25zOicsIGVycm9yKTtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBuZXcgY291cnNlIHJlY29tbWVuZGF0aW9ucyBkdXJpbmcgcmVnZW5lcmF0aW9uXG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlTmV3Q291cnNlUmVjb21tZW5kYXRpb25zKCk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc29sZS5sb2coJ0dlbmVyYXRpbmcgbmV3IGNvdXJzZSByZWNvbW1lbmRhdGlvbnMuLi4nKTtcbiAgICByZXR1cm4gdGhpcy5nZXRSZWNvbW1lbmRlZENvdXJzZUZvclJlZ2VuZXJhdGlvbih0aGlzLnBsYW5EYXRhLmlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmhhbmNlZCBjb3Vyc2UgZ2VuZXJhdGlvbiBzcGVjaWZpY2FsbHkgZm9yIHJlZ2VuZXJhdGlvbiB3aXRoIHByb2dyZXNzaXZlIGxvYWRpbmdcbiAgICovXG4gIHByaXZhdGUgZ2V0UmVjb21tZW5kZWRDb3Vyc2VGb3JSZWdlbmVyYXRpb24ocm9sZV9tYXBwaW5nX2lkOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBTdGFydCB0aGUgcHJvZ3Jlc3NpdmUgbG9hZGluZyBzaW11bGF0aW9uIGZvciByZWdlbmVyYXRpb25cbiAgICAgIHRoaXMuc3RhcnRSZWdlbmVyYXRpdmVQcm9ncmVzc2l2ZUxvYWRpbmcoKTtcbiAgICAgIFxuICAgICAgLy8gTWFrZSB0aGUgYWN0dWFsIEFQSSBjYWxsXG4gICAgICAvLyB0aGlzLnNoYXJlZFNlcnZpY2UuZ2V0UmVjb21tZW5kZWRDb3Vyc2Uocm9sZV9tYXBwaW5nX2lkKS5zdWJzY3JpYmUoe1xuICAgICAgLy8gICBuZXh0OiAocmVzcG9uc2UpID0+IHtcbiAgICAgIC8vICAgICAvLyBTdG9wIHByb2dyZXNzaXZlIGxvYWRpbmcgYW5kIHNob3cgY29tcGxldGlvblxuICAgICAgLy8gICAgIHRoaXMuaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3MgPSBmYWxzZTsgLy8gVGhpcyB3aWxsIHN0b3AgdGhlIGludGVydmFsXG4gICAgICAvLyAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSAxMDA7XG4gICAgICAvLyAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJ0NvdXJzZSByZWNvbW1lbmRhdGlvbnMgcmVnZW5lcmF0ZWQgc3VjY2Vzc2Z1bGx5ISc7XG4gICAgICAgICAgXG4gICAgICAvLyAgICAgLy8gQ2xlYXIgdGhlIGxvYWRpbmcgc3RhdGUgYWZ0ZXIgc2hvd2luZyBjb21wbGV0aW9uXG4gICAgICAvLyAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAvLyAgICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSAnJztcbiAgICAgIC8vICAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gMDtcbiAgICAgIC8vICAgICAgIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgLy8gICAgIH0sIDIwMDApO1xuICAgICAgLy8gICB9LFxuICAgICAgLy8gICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAvLyAgICAgLy8gU3RvcCBwcm9ncmVzc2l2ZSBsb2FkaW5nXG4gICAgICAvLyAgICAgdGhpcy5pc1JlZ2VuZXJhdGluZ1dpdGhQcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgLy8gICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICcnO1xuICAgICAgLy8gICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gMDtcbiAgICAgICAgICBcbiAgICAgIC8vICAgICAvLyBIYW5kbGUgc3BlY2lmaWMgZXJyb3IgY2FzZXNcbiAgICAgIC8vICAgICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDkgfHwgZXJyb3IuZXJyb3I/LmRldGFpbD8uaW5jbHVkZXMoJ2FscmVhZHkgZXhpc3RzJykpIHtcbiAgICAgIC8vICAgICAgIC8vIENvdXJzZSByZWNvbW1lbmRhdGlvbnMgYWxyZWFkeSBleGlzdCAtIHRoaXMgaXMgbm9ybWFsXG4gICAgICAvLyAgICAgICBjb25zb2xlLmxvZygnQ291cnNlIHJlY29tbWVuZGF0aW9ucyBhbHJlYWR5IGV4aXN0LCBsb2FkaW5nIGV4aXN0aW5nIGRhdGEuLi4nKTtcbiAgICAgICAgICAgIFxuICAgICAgLy8gICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJ0xvYWRpbmcgZXhpc3RpbmcgY291cnNlIHJlY29tbWVuZGF0aW9ucy4uLic7XG4gICAgICAgICAgICBcbiAgICAgIC8vICAgICAgIC8vIFRyeSB0byBnZXQgZXhpc3RpbmcgZGF0YVxuICAgICAgLy8gICAgICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmdldFJlY29tbWVuZGVkQ291cnNlKHJvbGVfbWFwcGluZ19pZCkuc3Vic2NyaWJlKHtcbiAgICAgIC8vICAgICAgICAgbmV4dDogKGV4aXN0aW5nUmVzcG9uc2UpID0+IHtcbiAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZygnU3VjY2Vzc2Z1bGx5IGxvYWRlZCBleGlzdGluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb25zJyk7XG4gICAgICAvLyAgICAgICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSAxMDA7XG4gICAgICAvLyAgICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJ0xvYWRlZCBleGlzdGluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb25zIHN1Y2Nlc3NmdWxseSEnO1xuICAgICAgICAgICAgICAgIFxuICAgICAgLy8gICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gICAgICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJyc7XG4gICAgICAvLyAgICAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG4gICAgICAvLyAgICAgICAgICAgICByZXNvbHZlKGV4aXN0aW5nUmVzcG9uc2UpO1xuICAgICAgLy8gICAgICAgICAgIH0sIDIwMDApO1xuICAgICAgLy8gICAgICAgICB9LFxuICAgICAgLy8gICAgICAgICBlcnJvcjogKGxvYWRFcnJvcikgPT4ge1xuICAgICAgLy8gICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBsb2FkIGV4aXN0aW5nIGNvdXJzZSByZWNvbW1lbmRhdGlvbnM6JywgbG9hZEVycm9yKTtcbiAgICAgIC8vICAgICAgICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSAnJztcbiAgICAgIC8vICAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG4gICAgICAvLyAgICAgICAgICAgcmVqZWN0KGxvYWRFcnJvcik7XG4gICAgICAvLyAgICAgICAgIH1cbiAgICAgIC8vICAgICAgIH0pO1xuICAgICAgLy8gICAgIH0gZWxzZSB7XG4gICAgICAvLyAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBkdXJpbmcgY291cnNlIHJlY29tbWVuZGF0aW9uIHJlZ2VuZXJhdGlvbjonLCBlcnJvcik7XG4gICAgICAvLyAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgLy8gICAgIH1cbiAgICAgIC8vICAgfVxuICAgICAgLy8gfSk7XG4gICAgICB0aGlzLmlzUmVnZW5lcmF0aW5nV2l0aFByb2dyZXNzID0gdHJ1ZTtcbiAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gMDtcbiAgICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICdHZW5lcmF0aW5nIGNvdXJzZSByZWNvbW1lbmRhdGlvbnMuLi4nO1xuICBcbiAgICAgIGludGVydmFsKDUwMDApXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PlxuICAgICAgICAgICAgdGhpcy5zaGFyZWRTZXJ2aWNlLmdldFJlY29tbWVuZGVkQ291cnNlKHJvbGVfbWFwcGluZ19pZCkucGlwZShcbiAgICAgICAgICAgICAgY2F0Y2hFcnJvcihlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gUGFzcyBlcnJvciB0aHJvdWdoIG9ic2VydmFibGUgc28gcG9sbGluZyBsb2dpYyBjYW4gaW5zcGVjdCBpdFxuICAgICAgICAgICAgICAgIHJldHVybiBvZih7IGVycm9yIH0pO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKVxuICAgICAgICAgICksXG4gIFxuICAgICAgICAgIHRhcChyZXMgPT4gY29uc29sZS5sb2coXCJQb2xsaW5nIHJlc3VsdDpcIiwgcmVzKSksXG4gIFxuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIOKsh++4jyBTVE9QIFBPTExJTkcgb25seSB3aGVuOlxuICAgICAgICAgICAqIC0gU1VDQ0VTUyDihpIgcmVzLnN0YXR1cyA9PT0gQ09NUExFVEVEXG4gICAgICAgICAgICogLSBFUlJPUiDihpIgY29uZmxpY3QgLyBhbHJlYWR5IGV4aXN0c1xuICAgICAgICAgICAqL1xuICAgICAgICAgIHRha2VXaGlsZShyZXMgPT4ge1xuICAgICAgICAgICAgaWYgKHJlcz8uc3RhdHVzID09PSAnQ09NUExFVEVEJykgcmV0dXJuIGZhbHNlOyAgICAgICAvLyBTdG9wXG4gICAgICAgICAgICBpZiAocmVzPy5lcnJvcj8uc3RhdHVzID09PSA0MDkpIHJldHVybiBmYWxzZTsgICAgICAgIC8vIFN0b3BcbiAgICAgICAgICAgIGlmIChyZXM/LmVycm9yPy5lcnJvcj8uZGV0YWlsPy5pbmNsdWRlcygnYWxyZWFkeSBleGlzdHMnKSkgcmV0dXJuIGZhbHNlOyAvLyBTdG9wXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gS2VlcCBwb2xsaW5nXG4gICAgICAgICAgfSwgdHJ1ZSkgLy8gaW5jbHVkZSBmaW5hbCBlbWlzc2lvblxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgIG5leHQ6IChyZXMpID0+IHtcbiAgICAgICAgICAgIC8qKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgICAgICAgKiAgU1VDQ0VTUyBDQVNFIChzdGF0dXMgQ09NUExFVEVEKVxuICAgICAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG4gICAgICAgICAgICBpZiAocmVzPy5zdGF0dXMgPT09ICdDT01QTEVURUQnKSB7XG4gICAgICAgICAgICAgIHRoaXMuaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSAxMDA7XG4gICAgICAgICAgICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICdDb3Vyc2UgcmVjb21tZW5kYXRpb25zIHJlZ2VuZXJhdGVkIHN1Y2Nlc3NmdWxseSEnO1xuICBcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJyc7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSAwO1xuICAgICAgICAgICAgICAgIHJlc29sdmUocmVzKTtcbiAgICAgICAgICAgICAgfSwgMjAwMCk7XG4gIFxuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gIFxuICAgICAgICAgICAgLyoqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgICAgICAgKiAgRVJST1IgQ0FTRSAoNDA5IC8gYWxyZWFkeSBleGlzdHMpXG4gICAgICAgICAgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG4gICAgICAgICAgICBpZiAocmVzPy5lcnJvcikge1xuICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IHJlcy5lcnJvcjtcbiAgXG4gICAgICAgICAgICAgIGlmIChlcnJvci5zdGF0dXMgPT09IDQwOSB8fCBlcnJvcj8uZXJyb3I/LmRldGFpbD8uaW5jbHVkZXMoJ2FscmVhZHkgZXhpc3RzJykpIHtcbiAgXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJ0xvYWRpbmcgZXhpc3RpbmcgY291cnNlIHJlY29tbWVuZGF0aW9ucy4uLic7XG4gIFxuICAgICAgICAgICAgICAgIHRoaXMuc2hhcmVkU2VydmljZS5nZXRSZWNvbW1lbmRlZENvdXJzZShyb2xlX21hcHBpbmdfaWQpLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgICAgICBuZXh0OiAoZXhpc3RpbmdEYXRhKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gMTAwO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSAnTG9hZGVkIGV4aXN0aW5nIGNvdXJzZSByZWNvbW1lbmRhdGlvbnMgc3VjY2Vzc2Z1bGx5ISc7XG4gIFxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShleGlzdGluZ0RhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9LCAyMDAwKTtcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBlcnJvcjogbG9hZEVycm9yID0+IHJlamVjdChsb2FkRXJyb3IpXG4gICAgICAgICAgICAgICAgfSk7XG4gIFxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgfVxuICBcbiAgICAgICAgICAgICAgLyoqIEFueSBvdGhlciBlcnJvciDihpIgc3RvcCAmIHJlamVjdCAqL1xuICAgICAgICAgICAgICB0aGlzLmlzUmVnZW5lcmF0aW5nV2l0aFByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICcnO1xuICAgICAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgXG4gICAgICAgICAgICAvKiogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgICAgICAgKiAgU1RJTEwgUFJPQ0VTU0lORyAoa2VlcCBwb2xsaW5nKVxuICAgICAgICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgICAgICAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gTWF0aC5taW4odGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgKyAxMCwgOTUpO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJ1N0aWxsIHByb2Nlc3NpbmcgY291cnNlIHJlY29tbWVuZGF0aW9ucy4uLic7XG4gICAgICAgICAgfSxcbiAgXG4gICAgICAgICAgZXJyb3I6IGVyciA9PiByZWplY3QoZXJyKVxuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gXG5cbiAgLy8gUHJvZ3Jlc3NpdmUgbG9hZGluZyBtZXRob2RzIGZvciByZWdlbmVyYXRpb25cbiAgc3RhcnRSZWdlbmVyYXRpdmVQcm9ncmVzc2l2ZUxvYWRpbmcoKSB7XG4gICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gdGhpcy5wcm9jZXNzaW5nU3RhZ2VzWzBdO1xuICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gMDtcbiAgICB0aGlzLnN0YWdlU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICB0aGlzLnNpbXVsYXRlUmVnZW5lcmF0aXZlUHJvZ3Jlc3NpdmVTdGFnZXMoKTtcbiAgfVxuXG4gIHNpbXVsYXRlUmVnZW5lcmF0aXZlUHJvZ3Jlc3NpdmVTdGFnZXMoKSB7XG4gICAgbGV0IGN1cnJlbnRTdGFnZUluZGV4ID0gMDtcbiAgICBjb25zdCB0b3RhbER1cmF0aW9uID0gNjAwMDA7IC8vIDYwIHNlY29uZHMgZXN0aW1hdGVkIGR1cmF0aW9uXG4gICAgY29uc3Qgc3RhZ2VJbnRlcnZhbCA9IHRvdGFsRHVyYXRpb24gLyB0aGlzLnByb2Nlc3NpbmdTdGFnZXMubGVuZ3RoO1xuICAgIFxuICAgIGNvbnN0IHByb2dyZXNzSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAvLyBTdG9wIGlmIHJlZ2VuZXJhdGlvbiBpcyBjb21wbGV0ZVxuICAgICAgaWYgKCF0aGlzLmlzUmVnZW5lcmF0aW5nV2l0aFByb2dyZXNzKSB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwocHJvZ3Jlc3NJbnRlcnZhbCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgY29uc3QgZWxhcHNlZCA9IERhdGUubm93KCkgLSB0aGlzLnN0YWdlU3RhcnRUaW1lO1xuICAgICAgY29uc3QgY3VycmVudFN0YWdlUHJvZ3Jlc3MgPSAoZWxhcHNlZCAlIHN0YWdlSW50ZXJ2YWwpIC8gc3RhZ2VJbnRlcnZhbDtcbiAgICAgIGNvbnN0IHN0YWdlSW5kZXggPSBNYXRoLm1pbihNYXRoLmZsb29yKGVsYXBzZWQgLyBzdGFnZUludGVydmFsKSwgdGhpcy5wcm9jZXNzaW5nU3RhZ2VzLmxlbmd0aCAtIDEpO1xuICAgICAgXG4gICAgICAvLyBVcGRhdGUgc3RhZ2UgaWYgbmVlZGVkXG4gICAgICBpZiAoc3RhZ2VJbmRleCAhPT0gY3VycmVudFN0YWdlSW5kZXggJiYgc3RhZ2VJbmRleCA8IHRoaXMucHJvY2Vzc2luZ1N0YWdlcy5sZW5ndGgpIHtcbiAgICAgICAgY3VycmVudFN0YWdlSW5kZXggPSBzdGFnZUluZGV4O1xuICAgICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSB0aGlzLnByb2Nlc3NpbmdTdGFnZXNbc3RhZ2VJbmRleF07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIENhbGN1bGF0ZSBvdmVyYWxsIHByb2dyZXNzIChlYWNoIHN0YWdlIGlzIHdvcnRoIH4xNi42NyUpXG4gICAgICBjb25zdCBiYXNlUHJvZ3Jlc3MgPSAoc3RhZ2VJbmRleCAvIHRoaXMucHJvY2Vzc2luZ1N0YWdlcy5sZW5ndGgpICogMTAwO1xuICAgICAgY29uc3Qgc3RhZ2VQcm9ncmVzcyA9IChjdXJyZW50U3RhZ2VQcm9ncmVzcyAvIHRoaXMucHJvY2Vzc2luZ1N0YWdlcy5sZW5ndGgpICogMTAwO1xuICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSBNYXRoLm1pbihNYXRoLnJvdW5kKGJhc2VQcm9ncmVzcyArIHN0YWdlUHJvZ3Jlc3MpLCA5NSk7XG4gICAgfSwgMTAwMCk7XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzaCB0aGUgY29tcG9uZW50IGRhdGEgYWZ0ZXIgcmVnZW5lcmF0aW9uXG4gICAqL1xuICBwcml2YXRlIHJlZnJlc2hDb21wb25lbnQoKSB7XG4gICAgY29uc29sZS5sb2coJ1JlZnJlc2hpbmcgY29tcG9uZW50IGRhdGEuLi4nKTtcbiAgICBcbiAgICAvLyBSZXNldCBhbGwgZmlsdGVycyBhbmQgc2VsZWN0aW9uc1xuICAgIHRoaXMuc2VsZWN0ZWRUaGVtZUZpbHRlciA9ICcnO1xuICAgIHRoaXMuc2VsZWN0RmlsdGVyQ291cnNlcyA9IFtdO1xuICAgIHRoaXMuZmlsdGVyZENvdXJzZXMgPSBbXTtcbiAgICB0aGlzLm9yaWdpbmFsRmlsdGVyZWRDb3Vyc2VzID0gW107XG4gICAgdGhpcy5zdWdnZXN0ZWRDb3Vyc2VzID0gW107XG4gICAgdGhpcy51c2VyQWRkZWRDb3Vyc2VzID0gW107XG4gICAgXG4gICAgLy8gUmVzZXQgdGFiIHN0YXRlc1xuICAgIHRoaXMuaW5uZXJUYWJBY3RpdmVJbmRleCA9IDA7XG4gICAgdGhpcy5vdXRlclRhYkFjdGl2ZUluZGV4ID0gMDtcbiAgICBcbiAgICAvLyBDYWxsIHRoZSBkYXRhIGxvYWRpbmcgbWV0aG9kcyBkaXJlY3RseSB0byBhdm9pZCByZXNldHRpbmcgZGF0YUxvYWRlZFxuICAgIHRoaXMubG9hZENvbXBvbmVudERhdGEoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIGNvbXBvbmVudCBkYXRhIChzZXBhcmF0ZWQgZnJvbSBuZ09uSW5pdCBmb3IgcmV1c2UpXG4gICAqL1xuICBwcml2YXRlIGxvYWRDb21wb25lbnREYXRhKCkge1xuICAgIHRoaXMuZ2V0UmVjb21tZW5kZWRDb3Vyc2VXaXRoUHJvZ3Jlc3ModGhpcy5wbGFuRGF0YS5pZCkudGhlbigocmVzKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZygncmVzJywgcmVzKVxuICAgICAgdGhpcy5yZWNvbW1lbmRlZF9jb3Vyc2VfaWQgPSByZXMuaWRcbiAgICAgIGxldCBhbGxDb3VyZXMgPSBbXVxuICAgICAgaWYgKHJlcyAmJiByZXMuZmlsdGVyZWRfY291cnNlcyAmJiByZXMuZmlsdGVyZWRfY291cnNlcy5sZW5ndGgpIHtcbiAgICAgICAgcmVzPy5maWx0ZXJlZF9jb3Vyc2VzLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgICBpZiAoaXRlbT8ucmVsZXZhbmN5ID49IDg1KSB7XG4gICAgICAgICAgICBhbGxDb3VyZXMucHVzaChpdGVtKVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgdGhpcy5vcmlnaW5hbERhdGEgPSBhbGxDb3VyZXNcbiAgICAgICAgdGhpcy5maWx0ZXJkQ291cnNlcyA9IGFsbENvdXJlc1xuICAgICAgfVxuXG4gICAgICBjb25zb2xlLmxvZygndGhpcy5maWx0ZXJkQ291cnNlcycsIHRoaXMuZmlsdGVyZENvdXJzZXMpXG4gICAgICB0aGlzLmdldENvdXJzZXMoKVxuICAgICAgdGhpcy5nZXRTdWdnZXN0ZWRDb3Vyc2UoKVxuICAgICAgXG4gICAgICAvLyBJbml0aWFsaXplIGdhcCBhbmFseXNpcyBzdGF0cyBhZnRlciBjb3Vyc2VzIGFyZSBsb2FkZWRcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZUdhcEFuYWx5c2lzU3RhdHMoKVxuICAgICAgdGhpcy5nZXRVc2VyQ291cnNlKClcbiAgICAgIFxuICAgICAgLy8gTWFyayBkYXRhIGFzIGxvYWRlZCBhZnRlciBhbGwgaW5pdGlhbCBvcGVyYXRpb25zXG4gICAgICB0aGlzLmRhdGFMb2FkZWQgPSB0cnVlO1xuICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2V0dGluZyByZWNvbW1lbmRlZCBjb3Vyc2VzOicsIGVycm9yKTtcbiAgICAgIGlmIChlcnJvci5zdGF0dXMgPT09IDQwMSkge1xuICAgICAgICBjb25zb2xlLmxvZygnVW5hdXRob3JpemVkIGFjY2VzcyAtIHVzZXIgd2lsbCBiZSByZWRpcmVjdGVkIHRvIGxvZ2luJyk7XG4gICAgICB9IGVsc2UgaWYgKGVycm9yLnN0YXR1cyAhPT0gNDA5KSB7XG4gICAgICAgIC8vIERvbid0IGxvZyBlcnJvciBmb3IgNDA5IChhbHJlYWR5IGV4aXN0cykgYXMgaXQncyBoYW5kbGVkIGluIHRoZSBtZXRob2RcbiAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGxvYWQgY291cnNlIHJlY29tbWVuZGF0aW9ucycpO1xuICAgICAgfVxuICAgICAgLy8gTWFyayBkYXRhIGFzIGxvYWRlZCBldmVuIGlmIHRoZXJlJ3MgYW4gZXJyb3IgdG8gc2hvdyB0aGUgZGlhbG9nIGNvbnRlbnRcbiAgICAgIHRoaXMuZGF0YUxvYWRlZCA9IHRydWU7XG4gICAgfSk7XG4gIH1cblxuICAvLyBQcm9ncmVzc2l2ZSBsb2FkaW5nIG1ldGhvZHMgZm9yIGNvdXJzZSBnZW5lcmF0aW9uXG4gIHN0YXJ0UHJvZ3Jlc3NpdmVMb2FkaW5nKCkge1xuICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9IHRoaXMucHJvY2Vzc2luZ1N0YWdlc1swXTtcbiAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG4gICAgdGhpcy5zdGFnZVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgdGhpcy5zaW11bGF0ZVByb2dyZXNzaXZlU3RhZ2VzKCk7XG4gIH1cblxuICBzaW11bGF0ZVByb2dyZXNzaXZlU3RhZ2VzKCkge1xuICAgIGxldCBjdXJyZW50U3RhZ2VJbmRleCA9IDA7XG4gICAgY29uc3QgdG90YWxEdXJhdGlvbiA9IDYwMDAwOyAvLyA2MCBzZWNvbmRzIGVzdGltYXRlZCBkdXJhdGlvblxuICAgIGNvbnN0IHN0YWdlSW50ZXJ2YWwgPSB0b3RhbER1cmF0aW9uIC8gdGhpcy5wcm9jZXNzaW5nU3RhZ2VzLmxlbmd0aDtcbiAgICBcbiAgICBjb25zdCBwcm9ncmVzc0ludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgY29uc3QgZWxhcHNlZCA9IERhdGUubm93KCkgLSB0aGlzLnN0YWdlU3RhcnRUaW1lO1xuICAgICAgY29uc3QgY3VycmVudFN0YWdlUHJvZ3Jlc3MgPSAoZWxhcHNlZCAlIHN0YWdlSW50ZXJ2YWwpIC8gc3RhZ2VJbnRlcnZhbDtcbiAgICAgIGNvbnN0IHN0YWdlSW5kZXggPSBNYXRoLm1pbihNYXRoLmZsb29yKGVsYXBzZWQgLyBzdGFnZUludGVydmFsKSwgdGhpcy5wcm9jZXNzaW5nU3RhZ2VzLmxlbmd0aCAtIDEpO1xuICAgICAgXG4gICAgICAvLyBVcGRhdGUgc3RhZ2UgaWYgbmVlZGVkXG4gICAgICBpZiAoc3RhZ2VJbmRleCAhPT0gY3VycmVudFN0YWdlSW5kZXggJiYgc3RhZ2VJbmRleCA8IHRoaXMucHJvY2Vzc2luZ1N0YWdlcy5sZW5ndGgpIHtcbiAgICAgICAgY3VycmVudFN0YWdlSW5kZXggPSBzdGFnZUluZGV4O1xuICAgICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSB0aGlzLnByb2Nlc3NpbmdTdGFnZXNbc3RhZ2VJbmRleF07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIENhbGN1bGF0ZSBvdmVyYWxsIHByb2dyZXNzIChlYWNoIHN0YWdlIGlzIHdvcnRoIH4xNi42NyUpXG4gICAgICBjb25zdCBiYXNlUHJvZ3Jlc3MgPSAoc3RhZ2VJbmRleCAvIHRoaXMucHJvY2Vzc2luZ1N0YWdlcy5sZW5ndGgpICogMTAwO1xuICAgICAgY29uc3Qgc3RhZ2VQcm9ncmVzcyA9IChjdXJyZW50U3RhZ2VQcm9ncmVzcyAvIHRoaXMucHJvY2Vzc2luZ1N0YWdlcy5sZW5ndGgpICogMTAwO1xuICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSBNYXRoLm1pbihNYXRoLnJvdW5kKGJhc2VQcm9ncmVzcyArIHN0YWdlUHJvZ3Jlc3MpLCA5NSk7XG4gICAgICBcbiAgICAgIC8vIENsZWFyIGludGVydmFsIHdoZW4gbG9hZGluZyBzdG9wc1xuICAgICAgaWYgKCF0aGlzLmxvYWRpbmcpIHtcbiAgICAgICAgY2xlYXJJbnRlcnZhbChwcm9ncmVzc0ludGVydmFsKTtcbiAgICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSAxMDA7XG4gICAgICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICdDb3Vyc2UgcmVjb21tZW5kYXRpb25zIGdlbmVyYXRlZCBzdWNjZXNzZnVsbHkhJztcbiAgICAgIH1cbiAgICB9LCAxMDAwKTtcbiAgfVxuXG4gIC8vIEVuaGFuY2VkIGNvdXJzZSBnZW5lcmF0aW9uIHdpdGggcHJvZ3Jlc3NpdmUgbG9hZGluZ1xuICBnZXRSZWNvbW1lbmRlZENvdXJzZVdpdGhQcm9ncmVzcyhyb2xlX21hcHBpbmdfaWQ6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgICB0aGlzLmN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgPSAnR2VuZXJhdGluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb25zLi4uJztcbiAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50YWdlID0gMzA7XG4gICAgICB0aGlzLnN0YXJ0UHJvZ3Jlc3NpdmVMb2FkaW5nKCk7XG4gICAgICBcbiAgICAgIGludGVydmFsKDUwMDApIC8vIOKPsSBwb2xsIGV2ZXJ5IDUgc2Vjb25kc1xuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJ1Byb2Nlc3NpbmcuLi4nO1xuICAgICAgICB9KSxcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuc2hhcmVkU2VydmljZS5nZXRSZWNvbW1lbmRlZENvdXJzZShyb2xlX21hcHBpbmdfaWQpKSxcblxuICAgICAgICAvLyBDb250aW51ZSBwb2xsaW5nIHdoaWxlIHN0YXR1cyAhPT0gQ09NUExFVEVEXG4gICAgICAgIHRha2VXaGlsZSgocmVzcG9uc2U6IGFueSkgPT4gcmVzcG9uc2U/LnN0YXR1cyAhPT0gJ0NPTVBMRVRFRCcsIHRydWUpLFxuXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICAgIGlmIChyZXNwb25zZT8uc3RhdHVzID09PSAnQ09NUExFVEVEJykge1xuXG4gICAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDEwMDtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICdDb3Vyc2UgcmVjb21tZW5kYXRpb25zIGdlbmVyYXRlZCBzdWNjZXNzZnVsbHkhJztcblxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuY3VycmVudFByb2Nlc3NpbmdTdGFnZSA9ICcnO1xuICAgICAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG4gICAgICAgICAgICB9LCAyMDAwKTtcblxuICAgICAgICAgICAgdGhpcy5zbmFja0Jhci5vcGVuKCdSZWNvbW1lbmRhdGlvbnMgcmVhZHkhJywgJ1gnLCB7XG4gICAgICAgICAgICAgIGR1cmF0aW9uOiAzMDAwLFxuICAgICAgICAgICAgICBwYW5lbENsYXNzOiBbJ3NuYWNrYmFyLXN1Y2Nlc3MnXVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5jdXJyZW50UHJvY2Vzc2luZ1N0YWdlID0gJyc7XG4gICAgICAgICAgdGhpcy5wcm9ncmVzc1BlcmNlbnRhZ2UgPSAwO1xuXG4gICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDA5IHx8IGVycm9yLmVycm9yPy5kZXRhaWw/LmluY2x1ZGVzKCdhbHJlYWR5IGV4aXN0cycpKSB7XG4gICAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oJ0NvdXJzZSByZWNvbW1lbmRhdGlvbnMgYWxyZWFkeSBleGlzdC4nLCAnWCcsIHtcbiAgICAgICAgICAgICAgZHVyYXRpb246IDMwMDAsXG4gICAgICAgICAgICAgIHBhbmVsQ2xhc3M6IFsnc25hY2tiYXItc3VjY2VzcyddXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmVzb2x2ZShudWxsKTsgLy8gbm90IGEgcmVhbCBlcnJvclxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oJ0ZhaWxlZCB0byBnZW5lcmF0ZSBjb3Vyc2UgcmVjb21tZW5kYXRpb25zLicsICdYJywge1xuICAgICAgICAgICAgICBkdXJhdGlvbjogMzAwMCxcbiAgICAgICAgICAgICAgcGFuZWxDbGFzczogWydzbmFja2Jhci1lcnJvciddXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHJlc2V0RmlsdGVycygpOiB2b2lkIHtcbiAgICB0aGlzLmZpbHRlckZvcm0ucmVzZXQoe1xuICAgICAgY29tcGV0ZW5jeTogW10sXG4gICAgICByYXRpbmc6IFtdLFxuICAgICAgbGFuZ3VhZ2U6IFtdLFxuICAgICAgZHVyYXRpb246IFtdLFxuICAgICAgcHJvdmlkZXI6IFtdXG4gICAgfSk7XG4gIFxuICAgIC8vIFJlc2V0IGZpbHRlcmVkIGRyb3Bkb3duIGxpc3RzXG4gICAgdGhpcy5maWx0ZXJlZENvbXBldGVuY3kgPSBbLi4udGhpcy5jb21wZXRlbmNpZXNUeXBlXTtcbiAgICB0aGlzLmZpbHRlcmVkUmF0aW5ncyA9IFsuLi50aGlzLnJhdGluZ3NdO1xuICAgIHRoaXMuZmlsdGVyZWRMYW5ndWFnZXMgPSBbLi4udGhpcy5sYW5ndWFnZXNdO1xuICAgIHRoaXMuZmlsdGVyZWREdXJhdGlvbnMgPSBbLi4udGhpcy5kdXJhdGlvbnNdO1xuICAgIHRoaXMuZmlsdGVyZWRQcm92aWRlcnMgPSBbLi4udGhpcy5wcm92aWRlcnNdO1xuICBcbiAgICAvLyBSZXNldCBjb3Vyc2UgbGlzdFxuICAgIHRoaXMuZmlsdGVyZENvdXJzZXMgPSBbLi4udGhpcy5mdWxsQ291cnNlTGlzdF07XG4gICAgLy8gdGhpcy5mdWxsQ291cnNlTGlzdC5mb3JFYWNoKChpdGVtKT0+e1xuICAgIC8vICAgaWYoaXRlbSAmJiBpdGVtLm9yZ2FuaXNhdGlvbiAmJiBpdGVtLm9yZ2FuaXNhdGlvbi5sZW5ndGgpIHtcbiAgICAvLyAgICAgaWYodGhpcy5maWx0ZXJlZFByb3ZpZGVycy5pbmRleE9mKGl0ZW0ub3JnYW5pc2F0aW9uWzBdKSA8IDApIHtcbiAgICAvLyAgICAgICB0aGlzLmZpbHRlcmVkUHJvdmlkZXJzLnB1c2goaXRlbS5vcmdhbmlzYXRpb25bMF0pXG4gICAgLy8gICAgIH1cbiAgICAgICAgXG4gICAgLy8gICB9XG4gICAgLy8gfSlcbiAgICB0aGlzLmdldEFsbEF2YWlsYWJsZUNvdXJzZXMoKVxuICB9XG5cbiAgZmlsdGVyTGlzdCh2YWx1ZTogc3RyaW5nLCB0eXBlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBzZWFyY2ggPSB2YWx1ZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdjb21wZXRlbmN5JzpcbiAgICAgICAgdGhpcy5maWx0ZXJlZENvbXBldGVuY3kgPSB0aGlzLmNvbXBldGVuY2llc1R5cGUuZmlsdGVyKHYgPT4gdi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaCkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JhdGluZyc6XG4gICAgICAgIHRoaXMuZmlsdGVyZWRSYXRpbmdzID0gdGhpcy5yYXRpbmdzLmZpbHRlcih2ID0+IHYudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhzZWFyY2gpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdsYW5ndWFnZSc6XG4gICAgICAgIHRoaXMuZmlsdGVyZWRMYW5ndWFnZXMgPSB0aGlzLmxhbmd1YWdlcy5maWx0ZXIodiA9PiB2LnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2VhcmNoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZHVyYXRpb24nOlxuICAgICAgICB0aGlzLmZpbHRlcmVkRHVyYXRpb25zID0gdGhpcy5kdXJhdGlvbnMuZmlsdGVyKHYgPT4gdi50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaCkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3Byb3ZpZGVyJzpcbiAgICAgICAgdGhpcy5maWx0ZXJlZFByb3ZpZGVycyA9IHRoaXMucHJvdmlkZXJzLmZpbHRlcih2ID0+IHYudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhzZWFyY2gpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgbm9ybWFsaXplQ29tcGV0ZW5jeSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXZhbHVlKSByZXR1cm4gJyc7XG4gICAgY29uc3QgdiA9IHZhbHVlLnRvTG93ZXJDYXNlKCk7XG4gIFxuICAgIGlmICh2ID09PSAnYWxsJykgcmV0dXJuICdhbGwnO1xuICAgIGlmICh2LmluY2x1ZGVzKCdiZWhhdmlvdXJhbCcpIHx8IHYuaW5jbHVkZXMoJ2JlaGF2aW9yYWwnKSkgcmV0dXJuICdiZWhhdmlvcmFsJztcbiAgICBpZiAodi5pbmNsdWRlcygnZnVuY3Rpb25hbCcpKSByZXR1cm4gJ2Z1bmN0aW9uYWwnO1xuICAgIGlmICh2LmluY2x1ZGVzKCdkb21haW4nKSkgcmV0dXJuICdkb21haW4nO1xuICBcbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBhcHBseUZpbHRlcnMoKTogdm9pZCB7XG4gICAgY29uc3Qge1xuICAgICAgY29tcGV0ZW5jeSA9IFtdLFxuICAgICAgcmF0aW5nID0gW10sXG4gICAgICBsYW5ndWFnZSA9IFtdLFxuICAgICAgZHVyYXRpb24gPSBbXSxcbiAgICAgIHByb3ZpZGVyID0gW11cbiAgICB9ID0gdGhpcy5maWx0ZXJGb3JtLnZhbHVlO1xuXG4gICAgY29uc29sZS5sb2coJ3RoaXMuZnVsbENvdXJzZUxpc3QtLScsdGhpcy5mdWxsQ291cnNlTGlzdClcbiAgXG4gICAgdGhpcy5maWx0ZXJkQ291cnNlcyA9IHRoaXMuZnVsbENvdXJzZUxpc3QuZmlsdGVyKGNvdXJzZSA9PiB7XG4gIFxuICAgICAgLyogLS0tLS0tLS0tLS0tLS0tLSBDb21wZXRlbmN5IC0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgICAgIGNvbnN0IGNvdXJzZUNvbXBldGVuY2llcyA9IFtcbiAgICAgICAgLi4uKGNvdXJzZS5jb21wZXRlbmNpZXMgfHwgW10pLFxuICAgICAgICAuLi4oY291cnNlLmNvbXBldGVuY2llc192NiB8fCBbXSlcbiAgICAgIF07XG4gIFxuICAgICAgY29uc3Qgc2VsZWN0ZWRDb21wZXRlbmNpZXMgPSBjb21wZXRlbmN5XG4gICAgICAgIC5tYXAoKGM6IHN0cmluZykgPT4gdGhpcy5ub3JtYWxpemVDb21wZXRlbmN5KGMpKVxuICAgICAgICAuZmlsdGVyKGMgPT4gYyAhPT0gJycpO1xuXG4gICAgICBjb25zdCBjb21wZXRlbmN5TWF0Y2ggPVxuICAgICAgICBzZWxlY3RlZENvbXBldGVuY2llcy5sZW5ndGggPT09IDAgfHxcbiAgICAgICAgc2VsZWN0ZWRDb21wZXRlbmNpZXMuaW5jbHVkZXMoJ2FsbCcpIHx8XG4gICAgICAgIGNvdXJzZUNvbXBldGVuY2llcy5zb21lKChjOiBhbnkpID0+XG4gICAgICAgICAgc2VsZWN0ZWRDb21wZXRlbmNpZXMuaW5jbHVkZXMoXG4gICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZUNvbXBldGVuY3koYy5jb21wZXRlbmN5QXJlYU5hbWUpXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICBcbiAgICAgIC8qIC0tLS0tLS0tLS0tLS0tLS0gUmF0aW5nIC0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgICAgIGNvbnN0IHJhdGluZ01hdGNoID1cbiAgICAgICAgcmF0aW5nLmxlbmd0aCA9PT0gMCB8fFxuICAgICAgICB0aGlzLm1hdGNoUmF0aW5nKGNvdXJzZSwgcmF0aW5nKTtcbiAgXG4gICAgICAvKiAtLS0tLS0tLS0tLS0tLS0tIExhbmd1YWdlIC0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgICAgIGNvbnN0IGxhbmd1YWdlTWF0Y2ggPVxuICAgICAgICBsYW5ndWFnZS5sZW5ndGggPT09IDAgfHxcbiAgICAgICAgbGFuZ3VhZ2Uuc29tZSgobDogc3RyaW5nKSA9PlxuICAgICAgICAgIGNvdXJzZS5sYW5ndWFnZSA9PT0gbCB8fFxuICAgICAgICAgIGNvdXJzZS5sYW5ndWFnZT8uaW5jbHVkZXM/LihsKSB8fFxuICAgICAgICAgIGNvdXJzZS5sYW5ndWFnZT8uWzBdPy5pbmNsdWRlcz8uKGwpXG4gICAgICAgICk7XG4gIFxuICAgICAgLyogLS0tLS0tLS0tLS0tLS0tLSBEdXJhdGlvbiAtLS0tLS0tLS0tLS0tLS0tICovXG4gICAgICBjb25zdCBkdXJhdGlvbk1hdGNoID1cbiAgICAgICAgZHVyYXRpb24ubGVuZ3RoID09PSAwIHx8XG4gICAgICAgIHRoaXMubWF0Y2hEdXJhdGlvbihjb3Vyc2UuZHVyYXRpb24sIGR1cmF0aW9uKTtcbiAgXG4gICAgICAvKiAtLS0tLS0tLS0tLS0tLS0tIFByb3ZpZGVyIC0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgICAgIGNvbnN0IHByb3ZpZGVyTWF0Y2ggPVxuICAgICAgICBwcm92aWRlci5sZW5ndGggPT09IDAgfHxcbiAgICAgICAgcHJvdmlkZXIuc29tZSgocDogc3RyaW5nKSA9PlxuICAgICAgICAgIGNvdXJzZS5vcmdhbmlzYXRpb24/LmluY2x1ZGVzKHApXG4gICAgICAgICk7XG4gIFxuICAgICAgcmV0dXJuIChcbiAgICAgICAgY29tcGV0ZW5jeU1hdGNoICYmXG4gICAgICAgIHJhdGluZ01hdGNoICYmXG4gICAgICAgIGxhbmd1YWdlTWF0Y2ggJiZcbiAgICAgICAgZHVyYXRpb25NYXRjaCAmJlxuICAgICAgICBwcm92aWRlck1hdGNoXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgbWF0Y2hSYXRpbmcoY291cnNlOiBhbnksIHNlbGVjdGVkUmF0aW5nczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICBpZiAoIXNlbGVjdGVkUmF0aW5ncyB8fCBzZWxlY3RlZFJhdGluZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTsgLy8gbm8gZmlsdGVyIHNlbGVjdGVkIOKGkiBtYXRjaCBldmVyeXRoaW5nXG4gICAgfVxuICBcbiAgICBsZXQgcmF0aW5nID0gbnVsbDtcbiAgXG4gICAgLy8gMe+4j+KDoyBVc2UgYXZnUmF0aW5nIGlmIGF2YWlsYWJsZVxuICAgIGlmIChjb3Vyc2UuYXZnUmF0aW5nICE9IG51bGwgJiYgIWlzTmFOKGNvdXJzZS5hdmdSYXRpbmcpKSB7XG4gICAgICByYXRpbmcgPSBOdW1iZXIoY291cnNlLmF2Z1JhdGluZyk7XG4gICAgfSBcbiAgICAvLyAy77iP4oOjIE1hcCByZWxldmFuY3kgaWYgYXZnUmF0aW5nIG1pc3NpbmdcbiAgICBlbHNlIGlmIChjb3Vyc2UucmVsZXZhbmN5ICE9IG51bGwgJiYgIWlzTmFOKGNvdXJzZS5yZWxldmFuY3kpKSB7XG4gICAgICBjb25zdCByZWwgPSBOdW1iZXIoY291cnNlLnJlbGV2YW5jeSk7XG4gICAgICBpZiAocmVsID49IDkwKSByYXRpbmcgPSA0LjU7XG4gICAgICBlbHNlIGlmIChyZWwgPj0gODApIHJhdGluZyA9IDQuMDtcbiAgICAgIGVsc2UgaWYgKHJlbCA+PSA3MCkgcmF0aW5nID0gMy41O1xuICAgICAgZWxzZSBpZiAocmVsID49IDUwKSByYXRpbmcgPSAyLjU7XG4gICAgICBlbHNlIHJhdGluZyA9IDEuMDtcbiAgICB9XG4gIFxuICAgIC8vIDPvuI/ig6MgTm8gdXNhYmxlIHJhdGluZyDihpIgZXhjbHVkZVxuICAgIGlmIChyYXRpbmcgPT09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgXG4gICAgLy8gNO+4j+KDoyBNYXRjaCBzZWxlY3RlZCByYXRpbmcgcmFuZ2VzXG4gICAgcmV0dXJuIHNlbGVjdGVkUmF0aW5ncy5zb21lKHIgPT4ge1xuICAgICAgc3dpdGNoIChyKSB7XG4gICAgICAgIGNhc2UgJzQuNSBhbmQgYWJvdmUnOiByZXR1cm4gcmF0aW5nID49IDQuNTtcbiAgICAgICAgY2FzZSAnNC4wIGFuZCBhYm92ZSc6IHJldHVybiByYXRpbmcgPj0gNC4wO1xuICAgICAgICBjYXNlICczLjUgYW5kIGFib3ZlJzogcmV0dXJuIHJhdGluZyA+PSAzLjU7XG4gICAgICAgIGNhc2UgJzIuNSBhbmQgYWJvdmUnOiByZXR1cm4gcmF0aW5nID49IDIuNTtcbiAgICAgICAgY2FzZSAnMSBhbmQgYWJvdmUnOiByZXR1cm4gcmF0aW5nID49IDEuMDtcbiAgICAgICAgZGVmYXVsdDogcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIFxuXG4gIG1hdGNoRHVyYXRpb24oZHVyYXRpb25JblNlY29uZHM6IG51bWJlciB8IHN0cmluZywgc2VsZWN0ZWRSYW5nZXM6IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgY29uc3QgaG91cnMgPSBOdW1iZXIoZHVyYXRpb25JblNlY29uZHMpIC8gMzYwMDtcbiAgXG4gICAgcmV0dXJuIHNlbGVjdGVkUmFuZ2VzLnNvbWUocmFuZ2UgPT4ge1xuICAgICAgc3dpdGNoIChyYW5nZSkge1xuICAgICAgICBjYXNlICc8IDEgSG91cic6XG4gICAgICAgICAgcmV0dXJuIGhvdXJzIDwgMTtcbiAgICAgICAgY2FzZSAnMS01IEhvdXJzJzpcbiAgICAgICAgICByZXR1cm4gaG91cnMgPj0gMSAmJiBob3VycyA8PSA1O1xuICAgICAgICBjYXNlICc1KyBIb3Vycyc6XG4gICAgICAgICAgcmV0dXJuIGhvdXJzID4gNTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG4vLyBDb25maXJtYXRpb24gRGlhbG9nIENvbXBvbmVudFxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAncmVnZW5lcmF0ZS1jb25maXJtYXRpb24tZGlhbG9nJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwiY29uZmlybWF0aW9uLWRpYWxvZy1jb250YWluZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctaGVhZGVyXCI+XG4gICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cIndhcm5pbmctaWNvblwiPnJlZnJlc2g8L21hdC1pY29uPlxuICAgICAgICA8aDIgbWF0LWRpYWxvZy10aXRsZT5SZWdlbmVyYXRlIENvdXJzZSBSZWNvbW1lbmRhdGlvbnM8L2gyPlxuICAgICAgPC9kaXY+XG4gICAgICBcbiAgICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQgY2xhc3M9XCJkaWFsb2ctY29udGVudFwiPlxuICAgICAgICA8cCBjbGFzcz1cIm1haW4tbWVzc2FnZVwiPlxuICAgICAgICAgIFRoaXMgd2lsbCBkZWxldGUgYWxsIGN1cnJlbnQgY291cnNlIHJlY29tbWVuZGF0aW9ucyBhbmQgZ2VuZXJhdGUgbmV3IG9uZXMgYmFzZWQgb24gdGhlIGxhdGVzdCByb2xlIG1hcHBpbmcuXG4gICAgICAgIDwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJzdWItbWVzc2FnZVwiPlxuICAgICAgICAgIEFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBjb250aW51ZT9cbiAgICAgICAgPC9wPlxuICAgICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICBcbiAgICAgIDxtYXQtZGlhbG9nLWFjdGlvbnMgY2xhc3M9XCJkaWFsb2ctYWN0aW9uc1wiPlxuICAgICAgICA8YnV0dG9uIG1hdC1idXR0b24gKGNsaWNrKT1cIm9uQ2FuY2VsKClcIiBjbGFzcz1cImNhbmNlbC1idG5cIj5cbiAgICAgICAgICBDYW5jZWxcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCIgKGNsaWNrKT1cIm9uQ29uZmlybSgpXCIgY2xhc3M9XCJjb25maXJtLWJ0blwiPlxuICAgICAgICAgIDxtYXQtaWNvbj5yZWZyZXNoPC9tYXQtaWNvbj5cbiAgICAgICAgICBZZXMsIFJlZ2VuZXJhdGVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L21hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbYFxuICAgIC5jb25maXJtYXRpb24tZGlhbG9nLWNvbnRhaW5lciB7XG4gICAgICBwYWRkaW5nOiAwO1xuICAgIH1cbiAgICBcbiAgICAuZGlhbG9nLWhlYWRlciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgIGdhcDogMTJweDtcbiAgICAgIHBhZGRpbmc6IDI0cHggMjRweCAxNnB4IDI0cHg7XG4gICAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2UwZTBlMDtcbiAgICB9XG4gICAgXG4gICAgLndhcm5pbmctaWNvbiB7XG4gICAgICBmb250LXNpemU6IDI0cHg7XG4gICAgICB3aWR0aDogMjRweDtcbiAgICAgIGhlaWdodDogMjRweDtcbiAgICAgIGNvbG9yOiAjZmY5ODAwO1xuICAgIH1cbiAgICBcbiAgICBoMiB7XG4gICAgICBtYXJnaW46IDA7XG4gICAgICBmb250LXNpemU6IDE4cHg7XG4gICAgICBmb250LXdlaWdodDogNjAwO1xuICAgICAgY29sb3I6ICMzMzM7XG4gICAgfVxuICAgIFxuICAgIC5kaWFsb2ctY29udGVudCB7XG4gICAgICBwYWRkaW5nOiAyNHB4O1xuICAgIH1cbiAgICBcbiAgICAubWFpbi1tZXNzYWdlIHtcbiAgICAgIGZvbnQtc2l6ZTogMTZweDtcbiAgICAgIGNvbG9yOiAjMzMzO1xuICAgICAgbWFyZ2luOiAwIDAgMTJweCAwO1xuICAgICAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgICB9XG4gICAgXG4gICAgLnN1Yi1tZXNzYWdlIHtcbiAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICAgIGNvbG9yOiAjNjY2O1xuICAgICAgbWFyZ2luOiAwO1xuICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICB9XG4gICAgXG4gICAgLmRpYWxvZy1hY3Rpb25zIHtcbiAgICAgIHBhZGRpbmc6IDE2cHggMjRweCAyNHB4IDI0cHg7XG4gICAgICBnYXA6IDEycHg7XG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kO1xuICAgIH1cbiAgICBcbiAgICAuY2FuY2VsLWJ0biB7XG4gICAgICBjb2xvcjogIzY2NjtcbiAgICB9XG4gICAgXG4gICAgLmNvbmZpcm0tYnRuIHtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgZ2FwOiA4cHg7XG4gICAgICBcbiAgICAgIC5tYXQtaWNvbiB7XG4gICAgICAgIGZvbnQtc2l6ZTogMThweDtcbiAgICAgICAgd2lkdGg6IDE4cHg7XG4gICAgICAgIGhlaWdodDogMThweDtcbiAgICAgICAgbWFyZ2luOiAwO1xuICAgICAgfVxuICAgIH1cbiAgYF1cbn0pXG5leHBvcnQgY2xhc3MgUmVnZW5lcmF0ZUNvbmZpcm1hdGlvbkRpYWxvZyB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBkaWFsb2dSZWY6IE1hdERpYWxvZ1JlZjxSZWdlbmVyYXRlQ29uZmlybWF0aW9uRGlhbG9nPlxuICApIHt9XG5cbiAgb25DYW5jZWwoKTogdm9pZCB7XG4gICAgdGhpcy5kaWFsb2dSZWYuY2xvc2UoZmFsc2UpO1xuICB9XG5cbiAgb25Db25maXJtKCk6IHZvaWQge1xuICAgIHRoaXMuZGlhbG9nUmVmLmNsb3NlKHRydWUpO1xuICB9XG5cbiBcbn1cbiIsIjxkaXYgY2xhc3M9XCJ2aWV3LWNicC1wbGFuXCI+XG4gICAgPGRpdiBjbGFzcz1cInBvcHVwLWNvbnRhaW5lclwiPlxuICAgICAgICBcbiAgICAgICAgPCEtLSBJbml0aWFsIExvYWRpbmcgU2NyZWVuIChmb3IgaW5pdGlhbCBsb2FkIGFuZCByZWdlbmVyYXRpb24pIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiaW5pdGlhbC1sb2FkaW5nLWNvbnRhaW5lclwiICpuZ0lmPVwiIWRhdGFMb2FkZWQgfHwgaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3NcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICA8bWF0LXNwaW5uZXIgZGlhbWV0ZXI9XCI1MFwiPjwvbWF0LXNwaW5uZXI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxvYWRpbmctdGV4dCBtdC0zXCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWFpbi1tZXNzYWdlXCI+e3sgY3VycmVudFByb2Nlc3NpbmdTdGFnZSB8fCAoaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3MgPyAnUmVnZW5lcmF0aW5nIGNvdXJzZSByZWNvbW1lbmRhdGlvbnMuLi4nIDogJ0xvYWRpbmcgY291cnNlIHJlY29tbWVuZGF0aW9ucy4uLicpIH19PC9wPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZGV0YWlsc1wiICpuZ0lmPVwicHJvZ3Jlc3NQZXJjZW50YWdlID4gMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWluZGljYXRvclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXItY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJwcm9ncmVzc1BlcmNlbnRhZ2VcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPVwicHJvZ3Jlc3MtdGV4dFwiPnt7IHByb2dyZXNzUGVyY2VudGFnZSB9fSUgQ29tcGxldGU8L3NtYWxsPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJ0aW1lLWVzdGltYXRlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVhbC10aW1lIGNvdXJzZSBnZW5lcmF0aW9uIGluIHByb2dyZXNzLiBUaGlzIG1heSB0YWtlIDEtMiBtaW51dGVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zbWFsbD5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPCEtLSBNYWluIENvbnRlbnQgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtYWluLWNvbnRlbnRcIiAqbmdJZj1cImRhdGFMb2FkZWQgJiYgIWlzUmVnZW5lcmF0aW5nV2l0aFByb2dyZXNzXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJwb3B1cC1oZWFkZXJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItbGVmdFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkaW5nXCI+U2F2ZSBDb3Vyc2VzICg8c3Bhbj57e3NoYXJlZFNlcnZpY2U/LmNicFBsYW5GaW5hbE9iaj8ubWluaXN0cnk/Lm9yZ05hbWV9fSA8c3BhblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwicGxhbkRhdGE/LmRlc2lnbmF0aW9uX25hbWUgXCI+LyB7e3BsYW5EYXRhPy5kZXNpZ25hdGlvbl9uYW1lfX08L3NwYW4+PC9zcGFuPik8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci1hY3Rpb25zXCI+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInJlZ2VuZXJhdGUtYnRuXCIgKGNsaWNrKT1cInJlZ2VuZXJhdGVDb3Vyc2VSZWNvbW1lbmRhdGlvbnMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNSZWdlbmVyYXRpbmdcIlxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0LXJhaXNlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCI+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiAqbmdJZj1cIiFpc1JlZ2VuZXJhdGluZ1wiPnJlZnJlc2g8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LXNwaW5uZXIgKm5nSWY9XCJpc1JlZ2VuZXJhdGluZ1wiIGRpYW1ldGVyPVwiMjBcIj48L21hdC1zcGlubmVyPlxuICAgICAgICAgICAgICAgICAgICA8c3Bhbj57e2lzUmVnZW5lcmF0aW5nID8gJ1JlZ2VuZXJhdGluZy4uLicgOiAnUmVnZW5lcmF0ZSBSZWNvbW1lbmRhdGlvbnMnfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImN1cnNvci1wb2ludGVyIGNsb3NlLWJ0blwiIChjbGljayk9XCJjbG9zZURpYWxvZygpXCI+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLWNvbnRhaW5lciBtdC00XCI+XG4gICAgICAgICAgICA8bWF0LXRhYi1ncm91cCAoc2VsZWN0ZWRUYWJDaGFuZ2UpPVwib25PdXRlclRhYkNoYW5nZSgkZXZlbnQpXCI+XG4gICAgICAgICAgICAgICAgPCEtLSBGaXJzdCBNYWluIFRhYiAtLT5cbiAgICAgICAgICAgICAgICA8bWF0LXRhYiBsYWJlbD1cImNvdXJzZSByZWNvbW1lbmRhdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICA8IS0tIE5lc3RlZCBUYWJzIC0tPlxuICAgICAgICAgICAgICAgICAgICA8IS0tIDxtYXQtdGFiLWdyb3VwIChzZWxlY3RlZFRhYkNoYW5nZSk9XCJvbklubmVyVGFiQ2hhbmdlKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtdGFiIGxhYmVsPVwiYWxsXCI+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtdGFiIGxhYmVsPVwiYmVoYXZpb3VyYWxcIj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtdGFiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC10YWIgbGFiZWw9XCJmdW5jdGlvbmFsXCI+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtdGFiIGxhYmVsPVwiZG9tYWluXCI+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtdGFiLWdyb3VwPiAtLT5cbiAgICAgICAgICAgICAgICA8L21hdC10YWI+XG5cbiAgICAgICAgICAgICAgICA8IS0tIFNlY29uZCBNYWluIFRhYiAtLT5cbiAgICAgICAgICAgICAgICA8bWF0LXRhYiBsYWJlbD1cImdhcCBhbmFseXNpc1wiPlxuICAgICAgICAgICAgICAgICAgICA8IS0tIDxwPkdhcCBhbmFseXNpcyBjb250ZW50IGdvZXMgaGVyZTwvcD4gLS0+XG4gICAgICAgICAgICAgICAgPC9tYXQtdGFiPlxuICAgICAgICAgICAgPC9tYXQtdGFiLWdyb3VwPlxuICAgICAgICAgICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmaWx0ZXJGb3JtXCIgY2xhc3M9XCJmaWx0ZXJzLWNvbnRhaW5lclwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvbGUtbWFwcGluZy1jb250YWluZXJcIlxuICAgICAgICAgICAgICAgICpuZ0lmPVwib3V0ZXJUYWJBY3RpdmVJbmRleCA9PT0gMCAmJiAoaW5uZXJUYWJBY3RpdmVJbmRleCA9PT0gMCB8fCBpbm5lclRhYkFjdGl2ZUluZGV4ID09PSAxIHx8IGlubmVyVGFiQWN0aXZlSW5kZXggPT09IDIgfHwgaW5uZXJUYWJBY3RpdmVJbmRleCA9PT0gMyApXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VjdGlvbi1oZWFkZXItaW1wcm92ZWQgbXQtM1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlYXJjaC1hbmQtYnV0dG9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWw+U2VhcmNoIENvdXJzZXM8L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VhcmNoLWNvbnRhaW5lci1jb21wYWN0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyc2VhcmNoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJzZWFyY2gtaWNvblwiPnNlYXJjaDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJzaW5wdXQtY29tcGFjdFwiIFsobmdNb2RlbCldPVwic2VhcmNoVGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGlucHV0KT1cImFwcGx5RmlsdGVyKCRldmVudC50YXJnZXQudmFsdWUpO1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggQ291cnNlc1wiIHR5cGU9XCJ0ZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICBcblxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlYXJjaC1hbmQtYnV0dG9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbD5TZWxlY3QgQ29tcGV0ZW5jeTwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+ICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGZpbHRlckZvcm0udmFsdWUuY29tcGV0ZW5jeT8ubGVuZ3RoID8gJycgOiAnQ29tcGV0ZW5jeScgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJjb21wZXRlbmN5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWxDbGFzcz1cInNlbGVjdC1zZWFyY2gtcGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cImFwcGx5RmlsdGVycygpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gU2VhcmNoIGJveCAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgc3R5bGU9XCJib3JkZXI6MXB4IHNvbGlkICNjY2M7IHBhZGRpbmc6IDVweDt3aWR0aDogOTIlO21hcmdpbjogNXB4O1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggQ29tcGV0ZW5jeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXlkb3duKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5dXApPVwiZmlsdGVyTGlzdCgkYW55KCRldmVudC50YXJnZXQpLnZhbHVlLCAnY29tcGV0ZW5jeScpXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBWYWx1ZXMgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IHIgb2YgZmlsdGVyZWRDb21wZXRlbmN5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHIgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+ICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlYXJjaC1hbmQtYnV0dG9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbD5TZWxlY3QgUmF0aW5nPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGZpbHRlckZvcm0udmFsdWUucmF0aW5nPy5sZW5ndGggPyAnJyA6ICdSYXRpbmcnIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmF0aW5nXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWxDbGFzcz1cInNlbGVjdC1zZWFyY2gtcGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cImFwcGx5RmlsdGVycygpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gU2VhcmNoIGJveCAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgc3R5bGU9XCJib3JkZXI6MXB4IHNvbGlkICNjY2M7IHBhZGRpbmc6IDVweDt3aWR0aDogOTIlO21hcmdpbjogNXB4O1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggUmVhdGluZ3NcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGtleXVwKT1cImZpbHRlckxpc3QoJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSwgJ3JhdGluZycpXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBWYWx1ZXMgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IHIgb2YgZmlsdGVyZWRSYXRpbmdzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHIgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24taGVhZGVyLWltcHJvdmVkLXNlYy0yIG10LTRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtYW5kLWJ1dHRvbnMtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4O1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWw+U2VsZWN0IExhbmd1YWdlPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGZpbHRlckZvcm0udmFsdWUubGFuZ3VhZ2U/Lmxlbmd0aCA/ICcnIDogJ0xhbmd1YWdlJyB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImxhbmd1YWdlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWxDbGFzcz1cInNlbGVjdC1zZWFyY2gtcGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cImFwcGx5RmlsdGVycygpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gU2VhcmNoIGJveCAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgc3R5bGU9XCJib3JkZXI6MXB4IHNvbGlkICNjY2M7IHBhZGRpbmc6IDVweDt3aWR0aDogOTIlO21hcmdpbjogNXB4O1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggTGFuZ3VhZ2VzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGtleWRvd24pPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXl1cCk9XCJmaWx0ZXJMaXN0KCRhbnkoJGV2ZW50LnRhcmdldCkudmFsdWUsICdsYW5ndWFnZScpXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBWYWx1ZXMgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IHIgb2YgZmlsdGVyZWRMYW5ndWFnZXNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgciB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlYXJjaC1hbmQtYnV0dG9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbD5TZWxlY3QgRHVyYXRpb248L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgZmlsdGVyRm9ybS52YWx1ZS5kdXJhdGlvbj8ubGVuZ3RoID8gJycgOiAnRHVyYXRpb24nIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZHVyYXRpb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYW5lbENsYXNzPVwic2VsZWN0LXNlYXJjaC1wYW5lbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZWxlY3Rpb25DaGFuZ2UpPVwiYXBwbHlGaWx0ZXJzKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBTZWFyY2ggYm94IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBzdHlsZT1cImJvcmRlcjoxcHggc29saWQgI2NjYzsgcGFkZGluZzogNXB4O3dpZHRoOiA5MiU7bWFyZ2luOiA1cHg7XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaCBEdXJhdGlvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXlkb3duKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5dXApPVwiZmlsdGVyTGlzdCgkYW55KCRldmVudC50YXJnZXQpLnZhbHVlLCAnZHVyYXRpb24nKVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gVmFsdWVzIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCByIG9mIGZpbHRlcmVkRHVyYXRpb25zXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IHIgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtYW5kLWJ1dHRvbnMtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4O1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWw+U2VsZWN0IFByb3ZpZGVyPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGZpbHRlckZvcm0udmFsdWUucHJvdmlkZXI/Lmxlbmd0aCA/ICcnIDogJ1Byb3ZpZGVyJyB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInByb3ZpZGVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFuZWxDbGFzcz1cInNlbGVjdC1zZWFyY2gtcGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cImFwcGx5RmlsdGVycygpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gU2VhcmNoIGJveCAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgc3R5bGU9XCJib3JkZXI6MXB4IHNvbGlkICNjY2M7IHBhZGRpbmc6IDVweDt3aWR0aDogOTIlO21hcmdpbjogNXB4O1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggUHJvdmlkZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGtleXVwKT1cImZpbHRlckxpc3QoJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSwgJ3Byb3ZpZGVyJylcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFZhbHVlcyAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgciBvZiBmaWx0ZXJlZFByb3ZpZGVyc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyByIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwibWFyZ2luLXRvcDogNDVweDttYXJnaW4tbGVmdDogMjBweDtcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJidG4tYWN0aXZlXCIgdHlwZT1cImJ1dHRvblwiIHZhbHVlPVwiUmVzZXQgQWxsIEZpbHRlcnNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVzZXRGaWx0ZXJzKClcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImZvbnQtc2l6ZToxNnB4O2ZvbnQtd2VpZ2h0OmJvbGQ7Y29sb3I6IzAwMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZpbHRlcmVkIENvdXJzZSBDb3VudCA6IHt7ZmlsdGVyZENvdXJzZXM/Lmxlbmd0aH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC01IHN1Yi1oZWFkaW5nIHNlbGVjdC1hbGwtY29udGFpbmVyXCIgKm5nSWY9XCJmaWx0ZXJkQ291cnNlcz8ubGVuZ3RoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwibWFyZ2luLWxlZnQ6IDE2cHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1jaGVja2JveCBbY2hlY2tlZF09XCJmYWxzZVwiIChjaGFuZ2UpPVwic2VsZWN0QWxsQ291cnNlcygkZXZlbnQpXCI+U2VsZWN0IEFsbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb3Vyc2VzPC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXAtY29tcGFjdFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImJ0bi1hY3RpdmVcIiB0eXBlPVwiYnV0dG9uXCIgdmFsdWU9XCJTdWdnZXN0IE1vcmUgQ291cnNlIEZyb20gaUdPVFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwic3VnZ2VzdE1vcmVDb3Vyc2VzKClcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwbC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBbZGlzYWJsZWRdPVwic2VsZWN0RmlsdGVyQ291cnNlcz8ubGVuZ3RoID4gMCA/IGZhbHNlIDogdHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJzZWxlY3RGaWx0ZXJDb3Vyc2VzPy5sZW5ndGggPiAwID8gJ2J0bi1hY3RpdmUnIDogJ2J0bi1kaXNhYmxlJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCIgW3ZhbHVlXT1cIm1vZGUgPT09ICdhZGQnID8gJ1NhdmUgQ291cnNlcycgOiAnVXBkYXRlIENvdXJzZXMnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzYXZlQ291cnNlcygpXCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRpc2NsYWltZXItY29udGFpbmVyIG10LTJcIiAqbmdJZj1cImZpbHRlcmRDb3Vyc2VzPy5sZW5ndGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaXNjbGFpbWVyLW1lc3NhZ2UgbXQtNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzdHJvbmc+RGlzY2xhaW1lcjo8L3N0cm9uZz4gUGxlYXNlIHZlcmlmeSB0aGUgcHVibGljIGNvdXJzZSBVUkwgYmVmb3JlIGFkZGluZyBpdCB0byB0aGUgcGxhbi5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTJcIj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvdXJzZS1saXN0LWNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiaW5uZXJUYWJBY3RpdmVJbmRleCA+IDAgPyAnY291cnNlLWxpc3QtY29udGFpbmVyLWZsZXgnOidjb3Vyc2UtbGlzdC1jb250YWluZXItcmlnaHQtZmxleCcgXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJpbm5lclRhYkFjdGl2ZUluZGV4ID4gMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJpbm5lclRhYkFjdGl2ZUluZGV4ID4gMCA/ICdsZWZ0LXBhbmVsJzonJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlubmVyVGFiQWN0aXZlSW5kZXggPT09IDFcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViLWhlYWRpbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+Q29tcGV0ZW5jaWVzIGluIEJlaGF2aW91cmFsPC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aGVtZS1maWx0ZXItY29udHJvbHMgbWItMlwiICpuZ0lmPVwic2VsZWN0ZWRUaGVtZUZpbHRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiY2xlYXItZmlsdGVyLWJ0blwiIChjbGljayk9XCJjbGVhclRoZW1lRmlsdGVyKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jbGVhcjwvbWF0LWljb24+IENsZWFyIEZpbHRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IChjbGljayk9XCJmaWx0ZXJPbkNvbXBldGVuY3lUaGVtZShpdGVtKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNhdGVnb3J5LWxpc3QtaXRlbSBjdXJzb3ItcG9pbnRlciBtdC0yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsnc2VsZWN0ZWQtdGhlbWUnOiBpc1RoZW1lU2VsZWN0ZWQoaXRlbSl9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGNvbXBldGVuY3lNYXRjaGVkQnlDYXRlZ29yeVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2l0ZW19fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaW5uZXJUYWJBY3RpdmVJbmRleCA9PT0gMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWItaGVhZGluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cD5Db21wZXRlbmNpZXMgaW4gRnVuY3Rpb25hbDwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGhlbWUtZmlsdGVyLWNvbnRyb2xzIG1iLTJcIiAqbmdJZj1cInNlbGVjdGVkVGhlbWVGaWx0ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImNsZWFyLWZpbHRlci1idG5cIiAoY2xpY2spPVwiY2xlYXJUaGVtZUZpbHRlcigpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2xlYXI8L21hdC1pY29uPiBDbGVhciBGaWx0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAoY2xpY2spPVwiZmlsdGVyT25Db21wZXRlbmN5VGhlbWUoaXRlbSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjYXRlZ29yeS1saXN0LWl0ZW0gY3Vyc29yLXBvaW50ZXIgbXQtMlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7J3NlbGVjdGVkLXRoZW1lJzogaXNUaGVtZVNlbGVjdGVkKGl0ZW0pfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBjb21wZXRlbmN5TWF0Y2hlZEJ5Q2F0ZWdvcnlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tpdGVtfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlubmVyVGFiQWN0aXZlSW5kZXggPT09IDNcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3ViLWhlYWRpbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+Q29tcGV0ZW5jaWVzIGluIERvbWFpbjwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGhlbWUtZmlsdGVyLWNvbnRyb2xzIG1iLTJcIiAqbmdJZj1cInNlbGVjdGVkVGhlbWVGaWx0ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImNsZWFyLWZpbHRlci1idG5cIiAoY2xpY2spPVwiY2xlYXJUaGVtZUZpbHRlcigpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2xlYXI8L21hdC1pY29uPiBDbGVhciBGaWx0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAoY2xpY2spPVwiZmlsdGVyT25Db21wZXRlbmN5VGhlbWUoaXRlbSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNhdGVnb3J5LWxpc3QtaXRlbSBjdXJzb3ItcG9pbnRlciBtdC0yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieydzZWxlY3RlZC10aGVtZSc6IGlzVGhlbWVTZWxlY3RlZChpdGVtKX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBjb21wZXRlbmN5TWF0Y2hlZEJ5Q2F0ZWdvcnlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tpdGVtfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBbbmdDbGFzc109XCJpbm5lclRhYkFjdGl2ZUluZGV4ID4gMCA/ICdyaWdodC1wYW5lbCc6J3JpZ2h0LXBhbmVsLWZsZXgnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIE5vIENvdXJzZSBGb3VuZCBNZXNzYWdlIGluIFJpZ2h0IFBhbmVsIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vLWNvdXJzZS1mb3VuZC1jb250YWluZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiZmlsdGVyZENvdXJzZXM/Lmxlbmd0aCA9PT0gMCAmJiBzZWxlY3RlZFRoZW1lRmlsdGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vLWNvdXJzZS1jYXJkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuby1jb3Vyc2UtaWNvblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPnNlYXJjaF9vZmY8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vLWNvdXJzZS1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aDQ+Tm8gQ291cnNlcyBGb3VuZDwvaDQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cD5ObyBjb3Vyc2VzIGZvdW5kIGZvciB0aGUgc2VsZWN0ZWQgdGhlbWU6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz57e3NlbGVjdGVkVGhlbWVGaWx0ZXJ9fTwvc3Ryb25nPjwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwPldvdWxkIHlvdSBsaWtlIHRvIGFkZCBhIGNvdXJzZSBmb3IgdGhpcyBjb21wZXRlbmN5PzwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJzdWdnZXN0LWNvdXJzZS1idG5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGRDb3Vyc2VGb3JTZWxlY3RlZFRoZW1lKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+YWRkX2NpcmNsZTwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQWRkIENvdXJzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gQ291cnNlcyBMaXN0IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvdXJzZS1saXN0LWl0ZW1cIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBmaWx0ZXJkQ291cnNlcztsZXQgaT1pbmRleFwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvdXJzZS1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb3Vyc2UtaGVhZGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2hlY2tlZC1jb3Vyc2UtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1jaGVja2JveCBbY2hlY2tlZF09XCJjaGVja0lmQ291cnNlRXhpc3RzKGl0ZW0pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwic2VsZWN0ZWRGaWx0ZXJDb3Vyc2VzKCRldmVudCwgaXRlbSlcIj48L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWwtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY291cnNlLXBpbGwtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY291cnNlLXBpbGxcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY291cnNlLXBpbGwtdGV4dFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjPVwiYXNzZXRzL2ljb25zL2NvdXJzZS5zdmdcIj48L3NwYW4+Jm5ic3A7PHNwYW4+Q291cnNlPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGxcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFpLXJlY29tbWVuZWQtcGlsbC10ZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFpLWxvYWRlci1pY29uXCI+PGltZyBzcmM9XCJhc3NldHMvaWNvbnMvYWktbG9hZGVyLmdpZlwiPjwvc3Bhbj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJpdGVtPy5yYXRpb25hbGVcIj5BSSBSZWNvbW1lbmRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiaXRlbT8uaXNfcHVibGljXCI+IC0gUHVibGljPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiIWl0ZW0/LmlzX3B1YmxpY1wiPiAtIGlHT1Q8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiFpdGVtPy5yYXRpb25hbGVcIj5NYW51YWxseSBTdWdnZXN0ZWQgLSBpR09UPC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIml0ZW0/LnJhdGlvbmFsZSAmJiAhaXRlbT8uaXNfcHVibGljXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFpLXJlY29tbWVuZWQtcGlsbC1ncmVlblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLWdyZWVuLXRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWktbG9hZGVyLWljb25cIj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9haS1sb2FkZXIuZ2lmXCI+PC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj5BSSBSZWNvbW1lbmRlZCAtIGlHT1QgPC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlIG10LTJcIiAqbmdJZj1cIml0ZW0/LnBsYXRmb3JtXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlLXRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWktbG9hZGVyLWljb25cIj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9haS1sb2FkZXIuZ2lmXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9XCJjdXJzb3ItcG9pbnRlclwiIFtocmVmXT1cIml0ZW0/LnB1YmxpY19saW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIj48c3Bhbj5QbGF0Zm9ybSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7aXRlbT8ucGxhdGZvcm19fTwvc3Bhbj48L2E+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlIG10LTJcIiAqbmdJZj1cIml0ZW0/Lm9yZ2FuaXNhdGlvbj8ubGVuZ3RoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlLXRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWktbG9hZGVyLWljb25cIj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9haS1sb2FkZXIuZ2lmXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+UHJvdmlkZXIgLSB7e2l0ZW0/Lm9yZ2FuaXNhdGlvblswXX19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIml0ZW0/LnJhdGlvbmFsZSAmJiBpdGVtPy5pc19wdWJsaWNcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLXB1YmxpY1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLXB1YmxpYy10ZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFpLWxvYWRlci1pY29uXCI+PGltZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcmM9XCJhc3NldHMvaWNvbnMvYWktbG9hZGVyLmdpZlwiPjwvc3Bhbj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+QUkgUmVjb21tZW5kZWQgLSBQdWJsaWMgPC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlIG10LTJcIiAqbmdJZj1cIml0ZW0/LnBsYXRmb3JtXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlLXRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWktbG9hZGVyLWljb25cIj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9haS1sb2FkZXIuZ2lmXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgY2xhc3M9XCJjdXJzb3ItcG9pbnRlclwiIFtocmVmXT1cIml0ZW0/LnB1YmxpY19saW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIj48c3Bhbj5QbGF0Zm9ybSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7aXRlbT8ucGxhdGZvcm19fTwvc3Bhbj48L2E+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlIG10LTJcIiAqbmdJZj1cIml0ZW0/Lm9yZ2FuaXNhdGlvbj8ubGVuZ3RoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhaS1yZWNvbW1lbmVkLXBpbGwtb3JhbmdlLXRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWktbG9hZGVyLWljb25cIj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9haS1sb2FkZXIuZ2lmXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4+UHJvdmlkZXIgLSB7e2l0ZW0/Lm9yZ2FuaXNhdGlvblswXX19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiFpdGVtPy5yYXRpb25hbGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLWdyYXlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFpLXJlY29tbWVuZWQtcGlsbC1ncmF5LXRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWktbG9hZGVyLWljb25cIj48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9haS1sb2FkZXIuZ2lmXCI+PC9zcGFuPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj5NYW51YWxseSBTdWdnZXN0ZWQgLSBpR09UIDwvc3Bhbj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLW9yYW5nZSBtdC0yXCIgKm5nSWY9XCJpdGVtPy5wbGF0Zm9ybVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLW9yYW5nZS10ZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFpLWxvYWRlci1pY29uXCI+PGltZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcmM9XCJhc3NldHMvaWNvbnMvYWktbG9hZGVyLmdpZlwiPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIGNsYXNzPVwiY3Vyc29yLXBvaW50ZXJcIiBbaHJlZl09XCJpdGVtPy5wdWJsaWNfbGlua1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCI+PHNwYW4+UGxhdGZvcm0gLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2l0ZW0/LnBsYXRmb3JtfX08L3NwYW4+PC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLW9yYW5nZSBtdC0yXCIgKm5nSWY9XCJpdGVtPy5vcmdhbmlzYXRpb24/Lmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWktcmVjb21tZW5lZC1waWxsLW9yYW5nZS10ZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFpLWxvYWRlci1pY29uXCI+PGltZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcmM9XCJhc3NldHMvaWNvbnMvYWktbG9hZGVyLmdpZlwiPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuPlByb3ZpZGVyIC0ge3tpdGVtPy5vcmdhbmlzYXRpb25bMF19fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvdXJzZS10aXRsZSBtdC0zIGN1cnNvci1wb2ludGVyXCIgKGNsaWNrKT1cInJlZGlyZWN0VG9Ub2MoaXRlbSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiaXRlbT8uY291cnNlXCI+e3tpdGVtPy5jb3Vyc2V9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gPHNwYW4gKm5nSWY9XCJpdGVtPy5uYW1lXCI+e3tpdGVtPy5uYW1lfX0qKioqPC9zcGFuPiAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6MTBweDtcIiAoY2xpY2spPVwicmVkaXJlY3RUb1RvYyhpdGVtKVwiPjxpbWdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0PVwiMThweFwiIHdpZHRoPVwiMThweFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyYz1cImFzc2V0cy9pY29ucy9yZWRpcmVjdC5wbmdcIiAvPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb3Vyc2UtZGVzYyBtdC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxzcGFuICpuZ0lmPVwiaXRlbT8ucmF0aW9uYWxlXCI+e3tpdGVtPy5yYXRpb25hbGV9fTwvc3Bhbj4gLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIml0ZW0/LmRlc2NyaXB0aW9uXCI+e3tpdGVtPy5kZXNjcmlwdGlvbn19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTNcIiAqbmdJZj1cImdldENvbXBldGVuY2llc0J5VHlwZSgnQmVoYXZpb3VyYWwnLGkpPy5sZW5ndGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb21wZXRlbmN5LXN1Yi1oZWFkaW5nXCI+QmVoYXZpb3VyYWwgQ29tcGV0ZW5jaWVzPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJjb21wZXRlbmN5LWxpc3QgbXQtMVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImJlaGF2aW91cmFsLXBpbGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgY29tcCBvZiBnZXREaXNwbGF5ZWRDb21wZXRlbmNpZXMoJ0JlaGF2aW91cmFsJyxpKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNvbXBldGVuY3ktdGV4dFwiPiB7eyBjb21wLmNvbXBldGVuY3lUaGVtZU5hbWUgfX0gLVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXAuY29tcGV0ZW5jeVN1YlRoZW1lTmFtZSB9fSA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgKm5nSWY9XCJoYXNNb3JlVGhhblR3bygnQmVoYXZpb3VyYWwnLGkpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzaG93LW1vcmUtY29tcGV0ZW5jeVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNob3ctbW9yZS1saW5rIGN1cnNvci1wb2ludGVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVDb21wZXRlbmNpZXMoJ0JlaGF2aW91cmFsJyxpKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgaXNFeHBhbmRlZCgnQmVoYXZpb3VyYWwnLGkpID8gJ1Nob3cgTGVzcycgOiAnKycgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0UmVtYWluaW5nQ291bnQoJ0JlaGF2aW91cmFsJyxpKSArICcgTW9yZScgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3VsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTJcIiAqbmdJZj1cImdldENvbXBldGVuY2llc0J5VHlwZSgnRnVuY3Rpb25hbCcsaSk/Lmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbXBldGVuY3ktc3ViLWhlYWRpbmdcIj5GdW5jdGlvbmFsIENvbXBldGVuY2llczwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHVsIGNsYXNzPVwiY29tcGV0ZW5jeS1saXN0IG10LTFcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJmdW5jdGlvbmFsLXBpbGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgY29tcCBvZiBnZXREaXNwbGF5ZWRDb21wZXRlbmNpZXMoJ0Z1bmN0aW9uYWwnLGkpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiY29tcGV0ZW5jeS10ZXh0XCI+IHt7IGNvbXAuY29tcGV0ZW5jeVRoZW1lTmFtZSB9fSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcC5jb21wZXRlbmN5U3ViVGhlbWVOYW1lIH19IDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSAqbmdJZj1cImhhc01vcmVUaGFuVHdvKCdGdW5jdGlvbmFsJyxpKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwic2hvdy1tb3JlLWNvbXBldGVuY3lcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzaG93LW1vcmUtbGluayBjdXJzb3ItcG9pbnRlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlQ29tcGV0ZW5jaWVzKCdGdW5jdGlvbmFsJyxpKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgaXNFeHBhbmRlZCgnRnVuY3Rpb25hbCcsaSkgPyAnU2hvdyBMZXNzJyA6ICcrJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRSZW1haW5pbmdDb3VudCgnRnVuY3Rpb25hbCcsaSkgKyAnIE1vcmUnIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC91bD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC0yXCIgKm5nSWY9XCJnZXRDb21wZXRlbmNpZXNCeVR5cGUoJ0RvbWFpbicsaSk/Lmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbXBldGVuY3ktc3ViLWhlYWRpbmdcIj5Eb21haW4gQ29tcGV0ZW5jaWVzPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJjb21wZXRlbmN5LWxpc3QgbXQtMVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImRvbWFpbi1waWxsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGNvbXAgb2YgZ2V0RGlzcGxheWVkQ29tcGV0ZW5jaWVzKCdEb21haW4nLGkpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiY29tcGV0ZW5jeS10ZXh0XCI+IHt7IGNvbXAuY29tcGV0ZW5jeVRoZW1lTmFtZSB9fSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcC5jb21wZXRlbmN5U3ViVGhlbWVOYW1lIH19IDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSAqbmdJZj1cImhhc01vcmVUaGFuVHdvKCdEb21haW4nLGkpXCIgY2xhc3M9XCJzaG93LW1vcmUtY29tcGV0ZW5jeVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNob3ctbW9yZS1saW5rIGN1cnNvci1wb2ludGVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVDb21wZXRlbmNpZXMoJ0RvbWFpbicsaSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGlzRXhwYW5kZWQoJ0RvbWFpbicsaSkgPyAnU2hvdyBMZXNzJyA6ICcrJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRSZW1haW5pbmdDb3VudCgnRG9tYWluJyxpKSArICcgTW9yZScgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3VsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFJlbGV2YW5jeSBhbmQgRHVyYXRpb24gc2VjdGlvbiAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY291cnNlLWZvb3RlclwiICpuZ0lmPVwiaXRlbT8ucmVsZXZhbmN5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyZWxldmFuY3ktcGlsbC1ncmVlblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlbGV2YW5jeS1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicmVsZXZhbmN5XCI+UmVsZXZhbmN5PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhc2hcIj4tPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBlcmNlbnRhZ2VcIj57e2l0ZW0/LnJlbGV2YW5jeX19JTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicmVsZXZhbmN5LXBpbGwtZ3JlZW5cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyZWxldmFuY3ktY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlbGV2YW5jeVwiPkR1cmF0aW9uPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhc2hcIj4tPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBlcmNlbnRhZ2VcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiaXRlbT8uZHVyYXRpb25cIj57e2dldER1cmF0aW9uKGl0ZW0/LmR1cmF0aW9uKX19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cIiEoaXRlbT8uZHVyYXRpb24pXCI+Ti9BPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBHZW5lcmFsIE5vIERhdGEgTWVzc2FnZSAob25seSB3aGVuIG5vIHRoZW1lIGZpbHRlciBpcyBhY3RpdmUpIC0tPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtMiBzdWItaGVhZGluZ1wiICpuZ0lmPVwiZmlsdGVyZENvdXJzZXM/Lmxlbmd0aCA9PT0gMCAmJiAhc2VsZWN0ZWRUaGVtZUZpbHRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHA+Tm8gRGF0YSBGb3VuZDwvcD5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9mb3JtPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvbGUtbWFwcGluZy1jb250YWluZXJcIiAqbmdJZj1cIm91dGVyVGFiQWN0aXZlSW5kZXggPT09IDFcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGlkPVwiZ2FwLWFuYWx5c2lzLWNvbnRlbnRcIj5cblxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZG93bmxvYWQtcGRmIG10LTQgbWItMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJidG4tYWN0aXZlXCIgdHlwZT1cImJ1dHRvblwiIHZhbHVlPVwiRG93bmxvYWRcIiAoY2xpY2spPVwiZG93bmxvYWRQREYoKVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxkaXYgKm5nSWY9XCJpc1BERkRvd25sb2FkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBkZi1oZWFkaW5nXCI+e3tzaGFyZWRTZXJ2aWNlPy5jYnBQbGFuRmluYWxPYmo/Lm1pbmlzdHJ5Py5uYW1lfX0gPHNwYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwicGxhbkRhdGE/LmRlc2lnbmF0aW9uX25hbWUgXCI+X3t7cGxhbkRhdGE/LmRlc2lnbmF0aW9uX25hbWV9fV9HYXBfQW5hbHlzaXM8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4gLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IHZoLTEwMFwiIFtuZ0NsYXNzXT1cImlzUERGRG93bmxvYWQgPyAnbXQtNCc6JydcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFNpZGViYXIgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBmbGV4LWNvbHVtbiBwLTMgYmctbGlnaHQgYm9yZGVyLWVuZFwiIHN0eWxlPVwid2lkdGg6IDI1MHB4O1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aDUgY2xhc3M9XCJtYi00XCI+QW5hbHl6ZSBieSBDYXRlZ29yeTwvaDU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgbWVudUl0ZW1zXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgbWItMiB0ZXh0LXN0YXJ0IG1lbnUtbGlzdC1pdGVtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwic2VsZWN0ZWRDYXRlZ29yeSA9PT0gaXRlbS5rZXlcIiAoY2xpY2spPVwic2VsZWN0Q2F0ZWdvcnkoaXRlbS5rZXkpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBNYWluIENvbnRlbnQgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgtZ3Jvdy0xIHAtNFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGdhcC0zIFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtMyBncmF5LWJnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRpdi1sYWJlbCBzdWItaGVhZGluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cD5Db21wZXRlbmNpZXMgQ292ZXJlZDwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWNvdW50XCI+e3tjb21wZXRlbmN5Q292ZXJlZENvdW50fX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtMyBncmF5LWJnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRpdi1sYWJlbCBzdWItaGVhZGluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cCAqbmdJZj1cInNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdhbGwnXCI+VG90YWwgQ29tcGV0ZW5jaWVzPC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cCAqbmdJZj1cInNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdiZWhhdmlvcmFsJ1wiPlRvdGFsIEJlaGF2aW91cmFsIENvbXBldGVuY2llc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwICpuZ0lmPVwic2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2Z1bmN0aW9uYWwnXCI+VG90YWwgRnVuY3Rpb25hbCBDb21wZXRlbmNpZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cCAqbmdJZj1cInNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdkb21haW4nXCI+VG90YWwgRG9tYWluIENvbXBldGVuY2llczwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWNvdW50XCIgKm5nSWY9XCJzZWxlY3RlZENhdGVnb3J5ID09PSAnYWxsJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e3RoaXMucGxhbkRhdGE/LmNvbXBldGVuY2llcz8ubGVuZ3RofX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWNvdW50XCIgKm5nSWY9XCJzZWxlY3RlZENhdGVnb3J5ID09PSAnYmVoYXZpb3JhbCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tiZWhhdmlvcmFsVG90YWxDb21wZXRlbmNpZXN9fTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaXYtY291bnRcIiAqbmdJZj1cInNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdmdW5jdGlvbmFsJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2Z1bmN0aW9uYWxUb3RhbENvbXBldGVuY2llc319PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRpdi1jb3VudFwiICpuZ0lmPVwic2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2RvbWFpbidcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tkb21haW5Ub3RhbENvbXBldGVuY2llc319PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLTMgZ3JlZW4tYmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWdyZWVuLWxhYmVsXCIgKm5nSWY9XCJzZWxlY3RlZENhdGVnb3J5ID09PSAnYWxsJ1wiPk92ZXJhbGwgQ292ZXJhZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWdyZWVuLWxhYmVsXCIgKm5nSWY9XCJzZWxlY3RlZENhdGVnb3J5ID09PSAnYmVoYXZpb3JhbCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQmVoYXZpb3VyYWwgQ292ZXJhZ2U8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWdyZWVuLWxhYmVsXCIgKm5nSWY9XCJzZWxlY3RlZENhdGVnb3J5ID09PSAnZnVuY3Rpb25hbCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnVuY3Rpb25hbCBDb3ZlcmFnZTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaXYtZ3JlZW4tbGFiZWxcIiAqbmdJZj1cInNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdkb21haW4nXCI+RG9tYWluXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvdmVyYWdlPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRpdi1ncmVlbi1jb3VudFwiICpuZ0lmPVwic2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2FsbCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tvdmVyYWxsQ292ZXJhZ2V9fTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaXYtZ3JlZW4tY291bnRcIiAqbmdJZj1cInNlbGVjdGVkQ2F0ZWdvcnkgPT09ICdiZWhhdmlvcmFsJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2JlaGF2aW9yYWxDb3ZlcmFnZX19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRpdi1ncmVlbi1jb3VudFwiICpuZ0lmPVwic2VsZWN0ZWRDYXRlZ29yeSA9PT0gJ2Z1bmN0aW9uYWwnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ZnVuY3Rpb25hbENvdmVyYWdlfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWdyZWVuLWNvdW50XCIgKm5nSWY9XCJzZWxlY3RlZENhdGVnb3J5ID09PSAnZG9tYWluJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2RvbWFpbkNvdmVyYWdlfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTQgYWxsLWNhdGVnb3J5LWxpc3RcIiBbbmdTd2l0Y2hdPVwic2VsZWN0ZWRDYXRlZ29yeVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ2FsbCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aDQ+QWxsIENhdGVnb3JpZXM8L2g0PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBTaG93IEJlaGF2aW91cmFsIHNlY3Rpb24gb25seSBpZiB0aGVyZSBhcmUgdW5tYXRjaGVkIGJlaGF2aW91cmFsIGNvbXBldGVuY2llcyAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtNFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiYmVoYXZpb3VyYWxOb3RNYXRjaGVkICYmIGJlaGF2aW91cmFsTm90TWF0Y2hlZC5sZW5ndGggPiAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWItaGVhZGluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+QmVoYXZpb3VyYWw8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JheS1iZy1pdGVtXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgYmVoYXZpb3VyYWxOb3RNYXRjaGVkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlzdC1mbGV4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj48c3Bhbj57e2l0ZW0gfCB0aXRsZWNhc2V9fTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3Vyc29yLXBvaW50ZXJcIiAoY2xpY2spPVwiYWRkQ291cnNlKGl0ZW0sICdCZWhhdmlvcmFsJylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJhZGQtYnRuXCI+PG1hdC1pY29uPmFkZDwvbWF0LWljb24+IEFkZCBOZXdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvdXJzZTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gU2hvdyBGdW5jdGlvbmFsIHNlY3Rpb24gb25seSBpZiB0aGVyZSBhcmUgdW5tYXRjaGVkIGZ1bmN0aW9uYWwgY29tcGV0ZW5jaWVzIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC00XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJmdW5jdGlvbmFsTm90TWF0Y2hlZCAmJiBmdW5jdGlvbmFsTm90TWF0Y2hlZC5sZW5ndGggPiAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWItaGVhZGluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+RnVuY3Rpb25hbDwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJncmF5LWJnLWl0ZW1cIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBmdW5jdGlvbmFsTm90TWF0Y2hlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxpc3QtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+PHNwYW4+e3tpdGVtIHwgdGl0bGVjYXNlfX08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImN1cnNvci1wb2ludGVyXCIgKGNsaWNrKT1cImFkZENvdXJzZShpdGVtLCAnRnVuY3Rpb25hbCcpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWRkLWJ0blwiPjxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPiBBZGQgTmV3XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb3Vyc2U8L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFNob3cgRG9tYWluIHNlY3Rpb24gb25seSBpZiB0aGVyZSBhcmUgdW5tYXRjaGVkIGRvbWFpbiBjb21wZXRlbmNpZXMgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTRcIiAqbmdJZj1cImRvbWFpbk5vdE1hdGNoZWQgJiYgZG9tYWluTm90TWF0Y2hlZC5sZW5ndGggPiAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdWItaGVhZGluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+RG9tYWluPC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImdyYXktYmctaXRlbVwiICpuZ0Zvcj1cImxldCBpdGVtIG9mIGRvbWFpbk5vdE1hdGNoZWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2PjxzcGFuPnt7aXRlbSB8IHRpdGxlY2FzZX19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjdXJzb3ItcG9pbnRlclwiIChjbGljayk9XCJhZGRDb3Vyc2UoaXRlbSwgJ0RvbWFpbicpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWRkLWJ0blwiPjxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPiBBZGQgTmV3XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb3Vyc2U8L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFNob3cgbWVzc2FnZSB3aGVuIGFsbCBjb21wZXRlbmNpZXMgYXJlIGNvdmVyZWQgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTQgdGV4dC1jZW50ZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cIighYmVoYXZpb3VyYWxOb3RNYXRjaGVkIHx8IGJlaGF2aW91cmFsTm90TWF0Y2hlZC5sZW5ndGggPT09IDApICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCFmdW5jdGlvbmFsTm90TWF0Y2hlZCB8fCBmdW5jdGlvbmFsTm90TWF0Y2hlZC5sZW5ndGggPT09IDApICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCFkb21haW5Ob3RNYXRjaGVkIHx8IGRvbWFpbk5vdE1hdGNoZWQubGVuZ3RoID09PSAwKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibm8tZ2Fwcy1tZXNzYWdlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJzdWNjZXNzLWljb25cIj5jaGVja19jaXJjbGU8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg0PkV4Y2VsbGVudCEgQWxsIGNvbXBldGVuY2llcyBhcmUgY292ZXJlZDwvaDQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cD5BbGwgcmVxdWlyZWQgY29tcGV0ZW5jaWVzIGhhdmUgYmVlbiBhZGRyZXNzZWQgYnkgdGhlIHNlbGVjdGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291cnNlcy48L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ2JlaGF2aW9yYWwnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg0PkJlaGF2aW91cmFsPC9oND5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtNFwiICpuZ0lmPVwiYmVoYXZpb3JhbENvdmVyYWdlICE9PSAnMTAwJSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSA8ZGl2IGNsYXNzPVwic3ViLWhlYWRpbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+QmVoYXZpb3VyYWw8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JheS1iZy1pdGVtXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgYmVoYXZpb3VyYWxOb3RNYXRjaGVkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlzdC1mbGV4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj48c3Bhbj57e2l0ZW19fTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3Vyc29yLXBvaW50ZXJcIiAoY2xpY2spPVwiYWRkQ291cnNlKGl0ZW0sICdCZWhhdmlvcmFsJylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJhZGQtYnRuXCI+PG1hdC1pY29uPmFkZDwvbWF0LWljb24+IEFkZCBOZXcgQ291cnNlIDwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtNFwiICpuZ0lmPVwiYmVoYXZpb3JhbENvdmVyYWdlID09PSAnMTAwJSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6ICNlOGY1ZTg7IGJvcmRlcjogMXB4IHNvbGlkICM0Y2FmNTA7IGJvcmRlci1yYWRpdXM6IDhweDsgdGV4dC1hbGlnbjogY2VudGVyO1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImNvbG9yOiAjMmU3ZDMyOyBmb250LXdlaWdodDogNjAwOyBmb250LXNpemU6IDE2cHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+OiSBFeGNlbGxlbnQhIEFsbCBiZWhhdmlvcmFsIGNvbXBldGVuY2llcyBhcmUgY292ZXJlZCBieSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZCBjb3Vyc2VzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidmdW5jdGlvbmFsJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoND5GdW5jdGlvbmFsPC9oND5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtNFwiICpuZ0lmPVwiZnVuY3Rpb25hbENvdmVyYWdlICE9PSAnMTAwJSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSA8ZGl2IGNsYXNzPVwic3ViLWhlYWRpbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+RnVuY3Rpb25hbDwvcD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj4gLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJncmF5LWJnLWl0ZW1cIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBmdW5jdGlvbmFsTm90TWF0Y2hlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxpc3QtZmxleFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+PHNwYW4+e3tpdGVtfX08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImN1cnNvci1wb2ludGVyXCIgKGNsaWNrKT1cImFkZENvdXJzZShpdGVtLCAnRnVuY3Rpb25hbCcpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWRkLWJ0blwiPjxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPiBBZGQgTmV3IENvdXJzZTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtNFwiICpuZ0lmPVwiZnVuY3Rpb25hbENvdmVyYWdlID09PSAnMTAwJSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6ICNlOGY1ZTg7IGJvcmRlcjogMXB4IHNvbGlkICM0Y2FmNTA7IGJvcmRlci1yYWRpdXM6IDhweDsgdGV4dC1hbGlnbjogY2VudGVyO1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImNvbG9yOiAjMmU3ZDMyOyBmb250LXdlaWdodDogNjAwOyBmb250LXNpemU6IDE2cHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+OiSBFeGNlbGxlbnQhIEFsbCBmdW5jdGlvbmFsIGNvbXBldGVuY2llcyBhcmUgY292ZXJlZCBieSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZCBjb3Vyc2VzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidkb21haW4nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg0PkRvbWFpbjwvaDQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTRcIiAqbmdJZj1cImRvbWFpbkNvdmVyYWdlICE9PSAnMTAwJSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSA8ZGl2IGNsYXNzPVwic3ViLWhlYWRpbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHA+RG9tYWluPC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PiAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImdyYXktYmctaXRlbVwiICpuZ0Zvcj1cImxldCBpdGVtIG9mIGRvbWFpbk5vdE1hdGNoZWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2PjxzcGFuPnt7aXRlbX19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjdXJzb3ItcG9pbnRlclwiIChjbGljayk9XCJhZGRDb3Vyc2UoaXRlbSwgJ0RvbWFpbicpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWRkLWJ0blwiPjxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPiBBZGQgTmV3IENvdXJzZSA8L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTRcIiAqbmdJZj1cImRvbWFpbkNvdmVyYWdlID09PSAnMTAwJSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInAtM1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6ICNlOGY1ZTg7IGJvcmRlcjogMXB4IHNvbGlkICM0Y2FmNTA7IGJvcmRlci1yYWRpdXM6IDhweDsgdGV4dC1hbGlnbjogY2VudGVyO1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImNvbG9yOiAjMmU3ZDMyOyBmb250LXdlaWdodDogNjAwOyBmb250LXNpemU6IDE2cHg7XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg8J+OiSBFeGNlbGxlbnQhIEFsbCBkb21haW4gY29tcGV0ZW5jaWVzIGFyZSBjb3ZlcmVkIGJ5IHRoZSBzZWxlY3RlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdXJzZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwPlBsZWFzZSBzZWxlY3QgYSBjYXRlZ29yeS48L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+IDwhLS0gQ2xvc2UgbWFpbi1jb250ZW50IGRpdiAtLT5cblxuICAgIDwvZGl2PlxuPC9kaXY+XG5cblxuPGRpdiBbaGlkZGVuXT1cIiFpc1BERkRvd25sb2FkXCIgY2xhc3M9XCJnYXAtYW5hbHlzaXMtcGRmLWNvbnRhaW5lclwiICNwZGZDb250ZW50PlxuICAgIDxkaXYgY2xhc3M9XCJnYXAtYW5hbHlzaXMtcGRmLWhlYWRlclwiPlxuICAgICAgPGltZyBzcmM9XCJhc3NldHMvaWNvbnMva2FybWF5b2dpTG9nby1taW4ucG5nXCIgYWx0PVwiS2FybWF5b2dpIEJoYXJhdCBMb2dvXCIgY2xhc3M9XCJsb2dvXCIgLz5cbiAgICAgIDxoMT48c3Bhbj5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJzaGFyZWRTZXJ2aWNlPy5jYnBQbGFuRmluYWxPYmo/Lm1pbmlzdHJ5Py5zYk9yZ1R5cGUgPT09ICdzdGF0ZSdcIj57e3NoYXJlZFNlcnZpY2U/LmNicFBsYW5GaW5hbE9iaj8uZGVwYXJ0bWVudF9uYW1lPy5uYW1lfX08L3NwYW4+IFxuICAgICAgICA8c3BhbiAqbmdJZj1cInNoYXJlZFNlcnZpY2U/LmNicFBsYW5GaW5hbE9iaj8ubWluaXN0cnk/LnNiT3JnVHlwZSA9PT0gJ21pbmlzdHJ5J1wiPnt7c2hhcmVkU2VydmljZT8uY2JwUGxhbkZpbmFsT2JqPy5taW5pc3RyeT8ubmFtZX19PC9zcGFuPiAgIFxuICAgICAgICA8c3BhbiAqbmdJZj1cInBsYW5EYXRhPy5kZXNpZ25hdGlvbl9uYW1lIFwiPi8ge3twbGFuRGF0YT8uZGVzaWduYXRpb25fbmFtZX19PC9zcGFuPlxuICAgICAgICA8L3NwYW4+PC9oMT5cbiAgICAgIDxwIGNsYXNzPVwic3VidGl0bGVcIj5BIGRldGFpbGVkIGJyZWFrZG93biBvZiBjb21wZXRlbmNpZXMgR2FwIEFuYWx5c2lzPC9wPlxuICAgICBcbiAgICA8L2Rpdj5cbiAgXG4gICAgPGRpdiBjbGFzcz1cImNvbXBldGVuY3ktc25hcHNob3RcIj5cbiAgICAgIDxoMj5Db21wZXRlbmN5IFNuYXBzaG90PC9oMj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzbmFwc2hvdC1jb250ZW50XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjaXJjbGUtd3JhcHBlclwiPlxuICAgICAgICAgIDxzdmcgY2xhc3M9XCJwcm9ncmVzcy1yaW5nXCIgd2lkdGg9XCIxMjBcIiBoZWlnaHQ9XCIxMjBcIj5cbiAgICAgICAgICAgIDxjaXJjbGUgY2xhc3M9XCJwcm9ncmVzcy1yaW5nLWJnXCIgY3g9XCI2MFwiIGN5PVwiNjBcIiByPVwiNTJcIiAvPlxuICAgICAgICAgICAgPGNpcmNsZSBjbGFzcz1cInByb2dyZXNzLXJpbmctY2lyY2xlXCIgY3g9XCI2MFwiIGN5PVwiNjBcIiByPVwiNTJcIiAvPlxuICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwZXJjZW50YWdlLXRleHRcIj57e292ZXJhbGxDb3ZlcmFnZX19PGJyIC8+PHNwYW4+T3ZlcmFsbCBDb3ZlcmFnZTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gIFxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29tcGV0ZW5jeS1jb250YWluZXJcIj5cbiAgICAgICAgICAgIDwhLS0gVG90YWwgQ29tcGV0ZW5jaWVzIEJveCAtLT5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0b3RhbC1ib3hcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlXCI+VG90YWwgQ29tcGV0ZW5jaWVzPC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb3VudFwiPnt7dGhpcy5wbGFuRGF0YT8uY29tcGV0ZW5jaWVzPy5sZW5ndGh9fTwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgXG4gICAgICAgICAgICA8IS0tIFByb2dyZXNzIEJhcnMgLS0+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZ3JvdXBcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWxhYmVsXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbC10ZXh0IGJlaGF2aW9yYWxcIj5CZWhhdmlvdXJhbDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNvdmVyZWQtdGV4dFwiPnt7YmVoYXZpb3JhbENvbXBldGVuY3lDb3ZlcmVkQ291bnR9fSAvIHt7YmVoYXZpb3JhbFRvdGFsQ29tcGV0ZW5jaWVzfX0gQ292ZXJlZDwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZmlsbCBiZWhhdmlvcmFsXCIgW3N0eWxlLndpZHRoLiVdPVwiKGJlaGF2aW9yYWxDb21wZXRlbmN5Q292ZXJlZENvdW50IC8gYmVoYXZpb3JhbFRvdGFsQ29tcGV0ZW5jaWVzKSAqIDEwMFwiPjwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWdyb3VwXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1sYWJlbFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtdGV4dCBmdW5jdGlvbmFsXCI+RnVuY3Rpb25hbDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNvdmVyZWQtdGV4dFwiPnt7ZnVuY3Rpb25hbENvbXBldGVuY3lDb3ZlcmVkQ291bnR9fSAvIHt7ZnVuY3Rpb25hbFRvdGFsQ29tcGV0ZW5jaWVzfX0gQ292ZXJlZDwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZmlsbCBmdW5jdGlvbmFsXCIgW3N0eWxlLndpZHRoLiVdPVwiKGZ1bmN0aW9uYWxDb21wZXRlbmN5Q292ZXJlZENvdW50IC8gZnVuY3Rpb25hbFRvdGFsQ29tcGV0ZW5jaWVzKSAqIDEwMFwiPjwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWdyb3VwXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1sYWJlbFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtdGV4dCBkb21haW5cIj5Eb21haW48L3NwYW4+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjb3ZlcmVkLXRleHRcIj57e2RvbWFpbkNvbXBldGVuY3lDb3ZlcmVkQ291bnR9fSAvIHt7ZG9tYWluVG90YWxDb21wZXRlbmNpZXN9fSBDb3ZlcmVkPC9zcGFuPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhclwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1maWxsIGRvbWFpblwiIFtzdHlsZS53aWR0aC4lXT1cIihkb21haW5Db21wZXRlbmN5Q292ZXJlZENvdW50IC8gZG9tYWluVG90YWxDb21wZXRlbmNpZXMpICogMTAwXCI+PC9kaXY+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgXG4gICAgPGRpdiBjbGFzcz1cImdhcC1zZWN0aW9uIG1iLTRcIj5cbiAgICAgIDxoMj5EZXRhaWxlZCBDb21wZXRlbmN5IEFuYWx5c2lzPC9oMj5cbiAgICAgIDxkaXYgY2xhc3M9XCJnYXAtYm94XCI+XG4gICAgICAgIEJyaWRnZSBZb3VyIENvbXBldGVuY2llcyBHYXBcbiAgICAgICAgPHAgY2xhc3M9XCJzdWJ0aXRsZVwiPkhlcmUgYXJlIHt7dGhpcy5wbGFuRGF0YT8uY29tcGV0ZW5jaWVzPy5sZW5ndGggLSAoYmVoYXZpb3JhbENvbXBldGVuY3lDb3ZlcmVkQ291bnQgKyBmdW5jdGlvbmFsQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCArIGRvbWFpbkNvbXBldGVuY3lDb3ZlcmVkQ291bnQpfX0ga2V5IGFyZWFzIGZvciBkZXZlbG9wbWVudC48L3A+XG4gICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInN1Yi1oZWFkaW5nIG1iLTRcIj5cbiAgICAgICAgPHA+R2FwIHRvIEFkZHJlc3MgPHNwYW4gKm5nSWY9XCIodGhpcy5wbGFuRGF0YT8uY29tcGV0ZW5jaWVzPy5sZW5ndGggLSAoYmVoYXZpb3JhbENvbXBldGVuY3lDb3ZlcmVkQ291bnQgKyBmdW5jdGlvbmFsQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCArIGRvbWFpbkNvbXBldGVuY3lDb3ZlcmVkQ291bnQpKSA+IDBcIj4oe3t0aGlzLnBsYW5EYXRhPy5jb21wZXRlbmNpZXM/Lmxlbmd0aCAtIChiZWhhdmlvcmFsQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCArIGZ1bmN0aW9uYWxDb21wZXRlbmN5Q292ZXJlZENvdW50ICsgZG9tYWluQ29tcGV0ZW5jeUNvdmVyZWRDb3VudCl9fSk8L3NwYW4+PC9wPlxuICAgICAgICBcbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiY29tcGV0ZW5jeS1jYXJkIGJlaGF2aW9yYWxcIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBiZWhhdmlvdXJhbE5vdE1hdGNoZWRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlXCI+e3tpdGVtIHwgdGl0bGVjYXNlfX08L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInN1YnRpdGxlXCI+XG4gICAgICAgICAgJm5ic3A7IOKAoiAmbmJzcDtcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhZyBiZWhhdmlvcmFsXCI+QmVoYXZpb3VyYWw8L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgICAgXG4gICAgICA8ZGl2IGNsYXNzPVwiY29tcGV0ZW5jeS1jYXJkIGZ1bmN0aW9uYWxcIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBmdW5jdGlvbmFsTm90TWF0Y2hlZFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGVcIj57e2l0ZW0gfCB0aXRsZWNhc2V9fTwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwic3VidGl0bGVcIj5cbiAgICAgICAgICAgJm5ic3A7IOKAoiAmbmJzcDtcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhZyBmdW5jdGlvbmFsXCI+RnVuY3Rpb25hbDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIFxuICAgICAgPGRpdiBjbGFzcz1cImNvbXBldGVuY3ktY2FyZCBkb21haW5cIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBkb21haW5Ob3RNYXRjaGVkXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0aXRsZVwiPnt7aXRlbSB8IHRpdGxlY2FzZX19PC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdWJ0aXRsZVwiPlxuICAgICAgICAgIDwhLS0gUHJvamVjdCBNYW5hZ2VtZW50ICAtLT5cbiAgICAgICAgICAmbmJzcDsg4oCiICZuYnNwO1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGFnIGRvbWFpblwiPkRvbWFpbjwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzdWItaGVhZGluZyBtYi00XCI+XG4gICAgICAgIDxwPkNvdmVyZWQgQ29tcGV0ZW5jaWVzIDxzcGFuPih7e3RoaXMucGxhbkRhdGE/LmNvbXBldGVuY2llcz8ubGVuZ3RoIC0gKGJlaGF2aW91cmFsTm90TWF0Y2hlZD8ubGVuZ3RoICsgZnVuY3Rpb25hbE5vdE1hdGNoZWQ/Lmxlbmd0aCArIGRvbWFpbk5vdE1hdGNoZWQ/Lmxlbmd0aCl9fSk8L3NwYW4+PC9wPiAgICAgICAgXG4gICAgIDwvZGl2PlxuICAgICA8ZGl2IGNsYXNzPVwiZ2FwLXNlY3Rpb24gbWItNFwiPlxuICAgICAgICBcbiAgICAgICAgPGRpdiBjbGFzcz1cImdyZWVuLWJnXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2LWdyZWVuLWxhYmVsIG1iLTJcIj5cbiAgICAgICAgICAgICAgICBDb25ncmF0dWxhdGlvbnMhXG4gICAgICAgICAgICA8L2Rpdj4gICAgICAgICAgICBcbiAgICAgICAgICAgIDxwPllvdSBoYXZlIHN1Y2Nlc3NmdWxseSBjb3ZlcmVkIDwvcD5cbiAgICAgICAgICA8cCBjbGFzcz1cInN1YnRpdGxlXCI+e3t0aGlzLnBsYW5EYXRhPy5jb21wZXRlbmNpZXM/Lmxlbmd0aCAtIChiZWhhdmlvdXJhbE5vdE1hdGNoZWQ/Lmxlbmd0aCArIGZ1bmN0aW9uYWxOb3RNYXRjaGVkPy5sZW5ndGggKyBkb21haW5Ob3RNYXRjaGVkPy5sZW5ndGgpfX0ga2V5IGNvbXBldGVuY2llcywgZm9ybWluZyBhIHN0cm9uZyBwcm9mZXNzaW9uYWwgZm91bmRhdGlvbi48L3A+XG4gICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNvbXBldGVuY3ktY2FyZCBiZWhhdmlvcmFsXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgYmVoYXZpb3VyYWxNYXRjaGVkXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0aXRsZVwiPnt7aXRlbT8udGhlbWUgfCB0aXRsZWNhc2V9fTwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwic3VidGl0bGVcIj5cbiAgICAgICAgICB7e2l0ZW0/LnN1Yl90aGVtZX19Jm5ic3A7IOKAoiAmbmJzcDtcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhZyBiZWhhdmlvcmFsXCI+QmVoYXZpb3VyYWw8L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgICAgXG4gICAgICA8ZGl2IGNsYXNzPVwiY29tcGV0ZW5jeS1jYXJkIGZ1bmN0aW9uYWxcIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBmdW5jdGlvbmFsTWF0Y2hlZFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGVcIj57e2l0ZW0/LnRoZW1lIHwgdGl0bGVjYXNlfX08L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInN1YnRpdGxlXCI+XG4gICAgICAgICAgICB7e2l0ZW0/LnN1Yl90aGVtZX19Jm5ic3A7IOKAoiAmbmJzcDtcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhZyBmdW5jdGlvbmFsXCI+RnVuY3Rpb25hbDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIFxuICAgICAgPGRpdiBjbGFzcz1cImNvbXBldGVuY3ktY2FyZCBkb21haW5cIiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBkb21haW5NYXRjaGVkXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0aXRsZVwiPnt7aXRlbT8udGhlbWUgfCB0aXRsZWNhc2V9fTwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwic3VidGl0bGVcIj5cbiAgICAgICAgICA8IS0tIFByb2plY3QgTWFuYWdlbWVudCAgLS0+XG4gICAgICAgICAge3tpdGVtPy5zdWJfdGhlbWV9fSZuYnNwOyDigKIgJm5ic3A7XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0YWcgZG9tYWluXCI+RG9tYWluPC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImdhcC1zZWN0aW9uIG1iLTRcIj5cbiAgICAgICAgPGgyPlJlY29tbWVuZGVkIENvdXJzZXM8L2gyPlxuICAgICAgPC9kaXY+XG4gICAgICA8YXBwLWdhcC1hbmFseXNpcy1yZWNvbW1lbmRlZC1jb3Vyc2UgW3BsYW5EYXRhXT1cInBsYW5EYXRhXCI+PC9hcHAtZ2FwLWFuYWx5c2lzLXJlY29tbWVuZGVkLWNvdXJzZT5cbjwvZGl2PlxuICBcblxuXG48ZGl2IGNsYXNzPVwib3ZlcmxheS1sb2FkZXJcIiAqbmdJZj1cImxvYWRpbmcgJiYgZGF0YUxvYWRlZCAmJiAhaXNSZWdlbmVyYXRpbmdXaXRoUHJvZ3Jlc3NcIj5cbiAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1jb250ZW50XCI+XG4gICAgICAgIDxtYXQtc3Bpbm5lciBkaWFtZXRlcj1cIjUwXCI+PC9tYXQtc3Bpbm5lcj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImxvYWRpbmctdGV4dCBtdC0zXCI+XG4gICAgICAgICAgICA8cCBjbGFzcz1cIm1haW4tbWVzc2FnZVwiPnt7IGN1cnJlbnRQcm9jZXNzaW5nU3RhZ2UgfHwgJ1ByZXBhcmluZyBjb3Vyc2UgcmVjb21tZW5kYXRpb24gZ2VuZXJhdGlvbi4uLicgfX08L3A+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZGV0YWlsc1wiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1pbmRpY2F0b3JcIiAqbmdJZj1cInByb2dyZXNzUGVyY2VudGFnZSA+IDBcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhci1jb250YWluZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoLiVdPVwicHJvZ3Jlc3NQZXJjZW50YWdlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDxzbWFsbCBjbGFzcz1cInByb2dyZXNzLXRleHRcIj57eyBwcm9ncmVzc1BlcmNlbnRhZ2UgfX0lIENvbXBsZXRlPC9zbWFsbD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJ0aW1lLWVzdGltYXRlXCI+XG4gICAgICAgICAgICAgICAgICAgIFJlYWwtdGltZSBjb3Vyc2UgZ2VuZXJhdGlvbiBpbiBwcm9ncmVzcy4gVGhpcyBtYXkgdGFrZSAxLTIgbWludXRlcy5cbiAgICAgICAgICAgICAgICA8L3NtYWxsPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC9kaXY+Il19
|