@hitsoft/fbdocumentflow 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/config/enums/index.d.ts +1 -0
- package/config/enums/route-names.d.ts +3 -0
- package/config/fbdocumentflow-config.module.d.ts +8 -0
- package/config/index.d.ts +5 -0
- package/config/providers/document-scenario-route.provider.d.ts +9 -0
- package/config/providers/document-transfer-route.provider.d.ts +9 -0
- package/config/providers/index.d.ts +6 -0
- package/config/providers/partner-mapping-route.provider.d.ts +9 -0
- package/config/providers/project-parameter-route.provider.d.ts +9 -0
- package/config/providers/route.provider.d.ts +8 -0
- package/config/providers/sap-company-profile-route.provider.d.ts +9 -0
- package/config/public-api.d.ts +3 -0
- package/esm2020/config/enums/index.mjs +2 -0
- package/esm2020/config/enums/route-names.mjs +2 -0
- package/esm2020/config/fbdocumentflow-config.module.mjs +30 -0
- package/esm2020/config/hitsoft-fbdocumentflow-config.mjs +5 -0
- package/esm2020/config/providers/document-scenario-route.provider.mjs +20 -0
- package/esm2020/config/providers/document-transfer-route.provider.mjs +20 -0
- package/esm2020/config/providers/index.mjs +7 -0
- package/esm2020/config/providers/partner-mapping-route.provider.mjs +20 -0
- package/esm2020/config/providers/project-parameter-route.provider.mjs +20 -0
- package/esm2020/config/providers/route.provider.mjs +24 -0
- package/esm2020/config/providers/sap-company-profile-route.provider.mjs +20 -0
- package/esm2020/config/public-api.mjs +4 -0
- package/esm2020/hitsoft-fbdocumentflow.mjs +5 -0
- package/esm2020/lib/components/fbdocumentflow.component.mjs +42 -0
- package/esm2020/lib/components/hit-document-scenarios/components/hit-document-scenario.component.mjs +151 -0
- package/esm2020/lib/components/hit-document-scenarios/hit-document-scenario-routing.module.mjs +26 -0
- package/esm2020/lib/components/hit-document-scenarios/hit-document-scenario.module.mjs +24 -0
- package/esm2020/lib/components/hit-document-transfers/components/hit-document-transfer-detail.component.mjs +474 -0
- package/esm2020/lib/components/hit-document-transfers/components/hit-document-transfer.component.mjs +241 -0
- package/esm2020/lib/components/hit-document-transfers/hit-document-transfer-routing.module.mjs +33 -0
- package/esm2020/lib/components/hit-document-transfers/hit-document-transfer.module.mjs +25 -0
- package/esm2020/lib/components/hit-partner-mappings/components/hit-partner-mapping.component.mjs +115 -0
- package/esm2020/lib/components/hit-partner-mappings/hit-partner-mapping-routing.module.mjs +26 -0
- package/esm2020/lib/components/hit-partner-mappings/hit-partner-mapping.module.mjs +24 -0
- package/esm2020/lib/components/hit-project-parameters/components/hit-project-parameter.component.mjs +125 -0
- package/esm2020/lib/components/hit-project-parameters/hit-project-parameter-routing.module.mjs +26 -0
- package/esm2020/lib/components/hit-project-parameters/hit-project-parameter.module.mjs +24 -0
- package/esm2020/lib/components/hit-sap-company-profiles/components/hit-sap-company-profile.component.mjs +88 -0
- package/esm2020/lib/components/hit-sap-company-profiles/hit-sap-company-profile-routing.module.mjs +26 -0
- package/esm2020/lib/components/hit-sap-company-profiles/hit-sap-company-profile.module.mjs +24 -0
- package/esm2020/lib/fbdocumentflow-routing.module.mjs +35 -0
- package/esm2020/lib/fbdocumentflow.module.mjs +29 -0
- package/esm2020/lib/proxy/document-scenarios/document-scenario.service.mjs +27 -0
- package/esm2020/lib/proxy/document-scenarios/index.mjs +3 -0
- package/esm2020/lib/proxy/document-scenarios/models.mjs +6 -0
- package/esm2020/lib/proxy/document-transfers/document-transfer.service.mjs +54 -0
- package/esm2020/lib/proxy/document-transfers/index.mjs +3 -0
- package/esm2020/lib/proxy/document-transfers/models.mjs +32 -0
- package/esm2020/lib/proxy/partner-mappings/index.mjs +3 -0
- package/esm2020/lib/proxy/partner-mappings/models.mjs +2 -0
- package/esm2020/lib/proxy/partner-mappings/partner-mapping.service.mjs +27 -0
- package/esm2020/lib/proxy/project-parameters/index.mjs +3 -0
- package/esm2020/lib/proxy/project-parameters/models.mjs +2 -0
- package/esm2020/lib/proxy/project-parameters/sap-project-parameter.service.mjs +25 -0
- package/esm2020/lib/proxy/sap-company-profiles/index.mjs +3 -0
- package/esm2020/lib/proxy/sap-company-profiles/models.mjs +7 -0
- package/esm2020/lib/proxy/sap-company-profiles/sap-company-profile.service.mjs +27 -0
- package/esm2020/lib/services/fbdocumentflow.service.mjs +21 -0
- package/esm2020/public-api.mjs +7 -0
- package/fesm2015/hitsoft-fbdocumentflow-config.mjs +144 -0
- package/fesm2015/hitsoft-fbdocumentflow-config.mjs.map +1 -0
- package/fesm2015/hitsoft-fbdocumentflow.mjs +1647 -0
- package/fesm2015/hitsoft-fbdocumentflow.mjs.map +1 -0
- package/fesm2020/hitsoft-fbdocumentflow-config.mjs +144 -0
- package/fesm2020/hitsoft-fbdocumentflow-config.mjs.map +1 -0
- package/fesm2020/hitsoft-fbdocumentflow.mjs +1621 -0
- package/fesm2020/hitsoft-fbdocumentflow.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/fbdocumentflow.component.d.ts +13 -0
- package/lib/components/hit-document-scenarios/components/hit-document-scenario.component.d.ts +41 -0
- package/lib/components/hit-document-scenarios/hit-document-scenario-routing.module.d.ts +7 -0
- package/lib/components/hit-document-scenarios/hit-document-scenario.module.d.ts +13 -0
- package/lib/components/hit-document-transfers/components/hit-document-transfer-detail.component.d.ts +88 -0
- package/lib/components/hit-document-transfers/components/hit-document-transfer.component.d.ts +61 -0
- package/lib/components/hit-document-transfers/hit-document-transfer-routing.module.d.ts +7 -0
- package/lib/components/hit-document-transfers/hit-document-transfer.module.d.ts +14 -0
- package/lib/components/hit-partner-mappings/components/hit-partner-mapping.component.d.ts +29 -0
- package/lib/components/hit-partner-mappings/hit-partner-mapping-routing.module.d.ts +7 -0
- package/lib/components/hit-partner-mappings/hit-partner-mapping.module.d.ts +13 -0
- package/lib/components/hit-project-parameters/components/hit-project-parameter.component.d.ts +36 -0
- package/lib/components/hit-project-parameters/hit-project-parameter-routing.module.d.ts +7 -0
- package/lib/components/hit-project-parameters/hit-project-parameter.module.d.ts +13 -0
- package/lib/components/hit-sap-company-profiles/components/hit-sap-company-profile.component.d.ts +28 -0
- package/lib/components/hit-sap-company-profiles/hit-sap-company-profile-routing.module.d.ts +7 -0
- package/lib/components/hit-sap-company-profiles/hit-sap-company-profile.module.d.ts +13 -0
- package/lib/fbdocumentflow-routing.module.d.ts +7 -0
- package/lib/fbdocumentflow.module.d.ts +13 -0
- package/lib/proxy/document-scenarios/document-scenario.service.d.ts +16 -0
- package/lib/proxy/document-scenarios/index.d.ts +2 -0
- package/lib/proxy/document-scenarios/models.d.ts +38 -0
- package/lib/proxy/document-transfers/document-transfer.service.d.ts +26 -0
- package/lib/proxy/document-transfers/index.d.ts +2 -0
- package/lib/proxy/document-transfers/models.d.ts +119 -0
- package/lib/proxy/partner-mappings/index.d.ts +2 -0
- package/lib/proxy/partner-mappings/models.d.ts +23 -0
- package/lib/proxy/partner-mappings/partner-mapping.service.d.ts +16 -0
- package/lib/proxy/project-parameters/index.d.ts +2 -0
- package/lib/proxy/project-parameters/models.d.ts +25 -0
- package/lib/proxy/project-parameters/sap-project-parameter.service.d.ts +14 -0
- package/lib/proxy/sap-company-profiles/index.d.ts +2 -0
- package/lib/proxy/sap-company-profiles/models.d.ts +26 -0
- package/lib/proxy/sap-company-profiles/sap-company-profile.service.d.ts +16 -0
- package/lib/services/fbdocumentflow.service.d.ts +10 -0
- package/package.json +41 -0
- package/public-api.d.ts +3 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import { Confirmation } from '@abp/ng.theme.shared';
|
|
3
|
+
import { from, of } from 'rxjs';
|
|
4
|
+
import { concatMap, finalize, switchMap, toArray } from 'rxjs/operators';
|
|
5
|
+
import { ConstructionDraftDocumentType, SapDocumentLifecycle, } from '../../../proxy/document-transfers';
|
|
6
|
+
import { LegBehavior } from '../../../proxy/document-scenarios';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "@angular/router";
|
|
9
|
+
import * as i2 from "../../../proxy/document-transfers";
|
|
10
|
+
import * as i3 from "../../../proxy/document-scenarios";
|
|
11
|
+
import * as i4 from "../../../proxy/sap-company-profiles";
|
|
12
|
+
import * as i5 from "@abp/ng.theme.shared";
|
|
13
|
+
import * as i6 from "@angular/common";
|
|
14
|
+
import * as i7 from "@angular/forms";
|
|
15
|
+
const DOCUMENT_TRANSFER_STATUS_DRAFT = 0;
|
|
16
|
+
const DOCUMENT_TRANSFER_STATUS_COMPLETED = 2;
|
|
17
|
+
const DOCUMENT_TRANSFER_STATUS_CANCELLED = 4;
|
|
18
|
+
const DOCUMENT_TRANSFER_LEG_STATUS_PENDING = 0;
|
|
19
|
+
const DOCUMENT_TRANSFER_LEG_STATUS_SUCCESS = 1;
|
|
20
|
+
const DOCUMENT_TRANSFER_LEG_STATUS_FAILED = 2;
|
|
21
|
+
export class HitDocumentTransferDetailComponent {
|
|
22
|
+
constructor(route, router, service, scenarioService, companyService, confirmation) {
|
|
23
|
+
this.route = route;
|
|
24
|
+
this.router = router;
|
|
25
|
+
this.service = service;
|
|
26
|
+
this.scenarioService = scenarioService;
|
|
27
|
+
this.companyService = companyService;
|
|
28
|
+
this.confirmation = confirmation;
|
|
29
|
+
this.isNew = false;
|
|
30
|
+
this.newState = null;
|
|
31
|
+
this.scenarios = [];
|
|
32
|
+
this.scenarioId = '';
|
|
33
|
+
this.isFetchingScenario = false;
|
|
34
|
+
this.companies = [];
|
|
35
|
+
this.legBehaviors = [
|
|
36
|
+
{ value: LegBehavior.IntermediateChain, label: 'Ara Şirket' },
|
|
37
|
+
{ value: LegBehavior.ConstructionChain, label: 'Construction' },
|
|
38
|
+
];
|
|
39
|
+
// Spec §14 (18.09.2026 kararı) - süreç parametrik. Aktarım henüz oluşturulmadıysa (isNew) kullanıcı bu
|
|
40
|
+
// ekranda "Hedef Belge Durumu"nu seçebilir (kaynaktan bağımsız). Aktarım oluştuktan sonra bu alan
|
|
41
|
+
// backend'de sabitlenir (DocumentTransfer.TargetDocumentLifecycle immutable), bu yüzden workingCopy
|
|
42
|
+
// varken salt-okunur gösterilir. Kullanıcı isteğiyle Kaynak Belge Durumu ile AYNI etiketler kullanılır.
|
|
43
|
+
this.documentLifecycleOptions = [
|
|
44
|
+
{ value: SapDocumentLifecycle.Posted, label: 'Kayıtlı Müşteri Faturası' },
|
|
45
|
+
{ value: SapDocumentLifecycle.Draft, label: 'Taslak Müşteri Faturası' },
|
|
46
|
+
];
|
|
47
|
+
// Spec ek karar (18.09.2026) - hedef Taslak iken Construction bacağının (OPOR→OPDN→OPCH) taban belge
|
|
48
|
+
// zinciri taslaklar arasında çalışmaz; bu durumda kullanıcı üç belge tipinden yalnızca birini seçer.
|
|
49
|
+
this.constructionDraftDocTypeOptions = [
|
|
50
|
+
{ value: ConstructionDraftDocumentType.PurchaseOrder, label: 'OPOR' },
|
|
51
|
+
{ value: ConstructionDraftDocumentType.GoodsReceipt, label: 'OPDN' },
|
|
52
|
+
{ value: ConstructionDraftDocumentType.APInvoice, label: 'OPCH' },
|
|
53
|
+
];
|
|
54
|
+
this.workingCopy = null;
|
|
55
|
+
this.isLoading = false;
|
|
56
|
+
this.isStarting = false;
|
|
57
|
+
this.isExecuting = false;
|
|
58
|
+
this.isMutatingLegs = false;
|
|
59
|
+
}
|
|
60
|
+
ngOnInit() {
|
|
61
|
+
this.scenarioService.getList({ maxResultCount: 1000, skipCount: 0, isActive: true }).subscribe(result => (this.scenarios = result.items));
|
|
62
|
+
this.companyService.getList({ maxResultCount: 1000, skipCount: 0, isActive: true }).subscribe(result => (this.companies = result.items));
|
|
63
|
+
const id = this.route.snapshot.paramMap.get('id');
|
|
64
|
+
if (id === 'new') {
|
|
65
|
+
this.isNew = true;
|
|
66
|
+
const state = history.state;
|
|
67
|
+
if (!state?.sourceCompanyId || state.docEntry == null) {
|
|
68
|
+
// Sayfa doğrudan yenilenmiş/yeni sekmede açılmışsa router state kaybolur; kaynak faturanın
|
|
69
|
+
// seçilmesi gereken listeye geri yönlendirilir.
|
|
70
|
+
this.router.navigate(['/fbdocumentflow/document-transfers']);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// sourceDocumentLifecycle, Belge Aktarımı listesindeki filtreden gelir ve sabittir (router state hiç
|
|
74
|
+
// taşınmadıysa - ör. doğrudan bağlantıyla gelinmişse - varsayılan Kayıtlı kabul edilir).
|
|
75
|
+
// targetDocumentLifecycle ise kullanıcının bu ekranda seçeceği, kaynaktan bağımsız bir değerdir;
|
|
76
|
+
// başlangıçta varsayılan olarak Kayıtlı gelir, kullanıcı isterse Taslak'a çevirir.
|
|
77
|
+
this.newState = {
|
|
78
|
+
...state,
|
|
79
|
+
sourceDocumentLifecycle: state.sourceDocumentLifecycle ?? SapDocumentLifecycle.Posted,
|
|
80
|
+
targetDocumentLifecycle: SapDocumentLifecycle.Posted,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
else if (id) {
|
|
84
|
+
this.loadWorkingCopy(id);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
companyName() {
|
|
88
|
+
return this.newState?.sourceCompanyName ?? this.workingCopy?.sourceCompanyName ?? '';
|
|
89
|
+
}
|
|
90
|
+
scenarioName() {
|
|
91
|
+
if (!this.workingCopy?.scenarioId) {
|
|
92
|
+
return 'Senaryosuz (yalnızca ilk hedef bacağı)';
|
|
93
|
+
}
|
|
94
|
+
return this.scenarios.find(s => s.id === this.workingCopy?.scenarioId)?.name ?? this.workingCopy.scenarioId;
|
|
95
|
+
}
|
|
96
|
+
// Bir senaryonun ilk bacağı belirli bir kaynak şirket ve hedef şirket için tanımlanmıştır. Spec §3 -
|
|
97
|
+
// kaynak belgenin ilk hedefi her zaman OINV.CardCode + Muhatap Eşleştirmeleri ile tespit edilir; hazır
|
|
98
|
+
// senaryo bu hedefi değiştiremez. Bu yüzden hem kaynak şirketi hem de zaten tespit edilmiş ilk hedefi
|
|
99
|
+
// uyuşmayan senaryolar seçilebilir listeden çıkarılır - aksi halde backend
|
|
100
|
+
// ScenarioSourceCompanyMismatch/ScenarioFirstTargetMismatch hatası verir.
|
|
101
|
+
availableScenarios() {
|
|
102
|
+
const sourceCompanyId = this.newState?.sourceCompanyId ?? this.workingCopy?.sourceCompanyId;
|
|
103
|
+
const resolvedTargetCompanyId = this.newState?.targetCompanyId ?? this.workingCopy?.legs?.[0]?.targetCompanyId;
|
|
104
|
+
if (!sourceCompanyId) {
|
|
105
|
+
return this.scenarios;
|
|
106
|
+
}
|
|
107
|
+
return this.scenarios.filter(s => {
|
|
108
|
+
const firstLeg = [...s.legs].sort((a, b) => a.sequenceNo - b.sequenceNo)[0];
|
|
109
|
+
if (!firstLeg) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
if (firstLeg.sourceCompanyId !== sourceCompanyId) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return !resolvedTargetCompanyId || firstLeg.targetCompanyId === resolvedTargetCompanyId;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
isDraft() {
|
|
119
|
+
return this.isNew || (this.workingCopy?.status ?? DOCUMENT_TRANSFER_STATUS_DRAFT) === DOCUMENT_TRANSFER_STATUS_DRAFT;
|
|
120
|
+
}
|
|
121
|
+
// Bekleyen bacaklar ilk kez çalıştırılabilir; hatalı bacaklar da tekrar denenebilir çünkü bu noktada
|
|
122
|
+
// henüz hiçbir SAP belgesi oluşmamıştır (aksi halde spec §13 gereği tüm zincir iptal edilip yeniden
|
|
123
|
+
// kurulmalıdır, tek bacak tekrarı değil).
|
|
124
|
+
// Spec §12-13 - iptal edilmiş (veya tamamlanmış) bir zincir tekrar çalıştırılmaz; kullanıcı yeniden
|
|
125
|
+
// oluşturma sürecini (kaynak faturadan yeni bir aktarım başlatarak, yeni bir Intercompany Id ile)
|
|
126
|
+
// başlatır. Bekleyen/Hatalı bir bacak kalmış olsa bile (zincir henüz tüm bacakları çalıştırmadan iptal
|
|
127
|
+
// edildiyse) bu bacaklar artık çalıştırılamaz - backend da bunu TransferNotEditable ile reddeder,
|
|
128
|
+
// burada buton en baştan devre dışı bırakılarak kullanıcıya net bir sinyal verilir.
|
|
129
|
+
canExecuteLeg(leg) {
|
|
130
|
+
const transferStatus = this.workingCopy?.status;
|
|
131
|
+
if (transferStatus === DOCUMENT_TRANSFER_STATUS_CANCELLED || transferStatus === DOCUMENT_TRANSFER_STATUS_COMPLETED) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (this.isConstructionDraftSelectable(leg) && leg.selectedConstructionDraftDocType == null) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return leg.status === DOCUMENT_TRANSFER_LEG_STATUS_PENDING || leg.status === DOCUMENT_TRANSFER_LEG_STATUS_FAILED;
|
|
138
|
+
}
|
|
139
|
+
// Spec ek karar (18.09.2026) - hedef Taslak iken Construction bacağının OPOR→OPDN→OPCH taban belge
|
|
140
|
+
// zinciri taslaklar arasında çalışmaz; bu bacaklarda kullanıcı zincir yerine TEK bir belge tipi seçer
|
|
141
|
+
// (bkz. ExecuteSingleDraftDocumentAsync, backend). Hedef Kayıtlı iken (normal zincir) bu geçerli değildir.
|
|
142
|
+
isConstructionDraftSelectable(leg) {
|
|
143
|
+
return leg.legBehavior === LegBehavior.ConstructionChain && this.workingCopy?.targetDocumentLifecycle === SapDocumentLifecycle.Draft;
|
|
144
|
+
}
|
|
145
|
+
hasMissingConstructionDraftSelection() {
|
|
146
|
+
return (this.workingCopy?.legs ?? []).some(l => this.isConstructionDraftSelectable(l) && l.selectedConstructionDraftDocType == null);
|
|
147
|
+
}
|
|
148
|
+
updateLegConstructionDraftDocType(leg, value) {
|
|
149
|
+
if (!this.workingCopy) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
leg.selectedConstructionDraftDocType = value ?? undefined;
|
|
153
|
+
this.persistLegChanges();
|
|
154
|
+
}
|
|
155
|
+
legTargetDocLabel(leg) {
|
|
156
|
+
const isLastLeg = leg.sequenceNo >= (this.workingCopy?.legs.length ?? 0);
|
|
157
|
+
if (leg.legBehavior === LegBehavior.ConstructionChain) {
|
|
158
|
+
if (this.isConstructionDraftSelectable(leg)) {
|
|
159
|
+
const selectedLabel = this.constructionDraftDocTypeOptions.find(o => o.value === leg.selectedConstructionDraftDocType)?.label ?? 'Seçilmedi';
|
|
160
|
+
return isLastLeg ? selectedLabel : `${selectedLabel} → OINV`;
|
|
161
|
+
}
|
|
162
|
+
return isLastLeg ? 'OPOR → OPDN → OPCH' : 'OPOR → OPDN → OPCH → OINV';
|
|
163
|
+
}
|
|
164
|
+
return isLastLeg ? 'OPCH' : 'OPCH → OINV';
|
|
165
|
+
}
|
|
166
|
+
// Spec §9 - artırım yalnızca IntermediateChain'de değil, ConstructionChain bacağının (sonraki bacak
|
|
167
|
+
// varsa) oluşturduğu devam Müşteri Faturasında da uygulanır - önceden yalnızca IntermediateChain
|
|
168
|
+
// kontrol ediliyordu, bu da bir Construction bacağının hedefinde artırım oranı tanımsızken kullanıcının
|
|
169
|
+
// hiç uyarılmadan sessizce artırımsız devam edilmesine yol açıyordu (kod incelemesiyle tespit edildi).
|
|
170
|
+
hasMissingIncreaseRate() {
|
|
171
|
+
return (this.workingCopy?.legs ?? []).some(l => (l.legBehavior === LegBehavior.IntermediateChain || l.legBehavior === LegBehavior.ConstructionChain) &&
|
|
172
|
+
l.plannedIncreaseRate == null);
|
|
173
|
+
}
|
|
174
|
+
// NumAtCard girişi yalnızca ara şirket bacaklarından, zincirin SON bacağı OLMAYANLAR için anlamlıdır
|
|
175
|
+
// (o bacakta aynı şirkette yeni bir Müşteri Faturası oluşuyor ve NumAtCard'ı kullanıcı belirler).
|
|
176
|
+
hasIntermediateNumAtCardLegs() {
|
|
177
|
+
const legs = this.workingCopy?.legs ?? [];
|
|
178
|
+
return legs.some(l => l.legBehavior === LegBehavior.IntermediateChain && l.sequenceNo < legs.length);
|
|
179
|
+
}
|
|
180
|
+
// Spec §4 - kullanıcı çalışma kopyasındaki bacakların hedef şirketini/davranışını (Ara Şirket veya
|
|
181
|
+
// Construction) değiştirebilmeli; bu değişiklik yalnızca bu aktarımın çalışma kopyasını etkiler, ana
|
|
182
|
+
// Hazır Senaryo tanımını (varsa) hiç değiştirmez. Kaynak şirket ayrıca düzenlenmez: zincirdeki her
|
|
183
|
+
// bacağın kaynağı, bir önceki bacağın hedefinden (veya ilk bacaksa aktarımın kendi kaynağından) backend
|
|
184
|
+
// tarafından otomatik türetilir (bkz. DocumentTransferAppService.AddLegAsync).
|
|
185
|
+
updateLegTarget(leg, targetCompanyId) {
|
|
186
|
+
if (!this.workingCopy) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
leg.targetCompanyId = targetCompanyId;
|
|
190
|
+
leg.targetCompanyName = this.companies.find(c => c.id === targetCompanyId)?.companyName;
|
|
191
|
+
this.persistLegChanges();
|
|
192
|
+
}
|
|
193
|
+
updateLegBehavior(leg, legBehavior) {
|
|
194
|
+
if (!this.workingCopy) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
leg.legBehavior = legBehavior;
|
|
198
|
+
this.persistLegChanges();
|
|
199
|
+
}
|
|
200
|
+
// Hedef/Davranış dropdown'ı değiştiğinde yalnızca O bacağı kaydedip sunucudan dönen tam workingCopy'yi
|
|
201
|
+
// olduğu gibi ekrana yansıtırsak, kullanıcının BAŞKA bir bacağa henüz yazdığı ama henüz senkronize
|
|
202
|
+
// edilmemiş NumAtCard/Döviz/Kur değerleri (bunlar yalnızca "Çalıştır"/"Başlat" öncesi toplu gönderilir)
|
|
203
|
+
// sunucudaki eski değerle geri gelen o bacak nesnesi tarafından sessizce ezilir/boşalır - gerçek
|
|
204
|
+
// ortamda doğrulandı. Bu yüzden dropdown değişikliğinde de TÜM bacaklardaki mevcut değerler
|
|
205
|
+
// (syncPendingLegChanges ile, sıralı/concurrency-safe) birlikte gönderilir.
|
|
206
|
+
persistLegChanges() {
|
|
207
|
+
if (!this.workingCopy) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.isMutatingLegs = true;
|
|
211
|
+
this.syncPendingLegChanges(this.workingCopy.legs)
|
|
212
|
+
.pipe(finalize(() => (this.isMutatingLegs = false)))
|
|
213
|
+
.subscribe(results => {
|
|
214
|
+
const last = results?.[results.length - 1];
|
|
215
|
+
if (last) {
|
|
216
|
+
this.workingCopy = last;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
// Zincire yeni bir bacak ekler: kaynağı otomatik olarak son bacağın hedefinden (ilk bacaksa aktarımın
|
|
221
|
+
// kendi kaynak şirketinden) türetilir. Varsayılan hedef, henüz zincirde olmayan ilk şirkettir; kullanıcı
|
|
222
|
+
// ekledikten sonra dropdown'lardan hedefi/davranışı değiştirebilir.
|
|
223
|
+
addLeg() {
|
|
224
|
+
if (!this.workingCopy || this.companies.length === 0) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Yeni bacağın kaynağı backend'de otomatik olarak son bacağın hedefinden türetilir (bkz.
|
|
228
|
+
// DocumentTransferAppService.AddLegAsync). Varsayılan HEDEF seçilirken bu kaynakla AYNI şirket asla
|
|
229
|
+
// önerilmemelidir - aksi halde bir şirketin kendi kendine fatura kestiği anlamsız bir bacak oluşur.
|
|
230
|
+
// Önceden şirket havuzu tükendiğinde (tüm şirketler zaten bir bacakta hedef olarak kullanılmışsa)
|
|
231
|
+
// fallback doğrudan companies[0]'a düşüyordu; bu tesadüfen kaynakla aynı şirkete denk gelip self-loop
|
|
232
|
+
// (Kaynak=Hedef) bacak oluşturabiliyordu (kullanıcı geri bildirimiyle tespit edildi).
|
|
233
|
+
const lastLeg = [...this.workingCopy.legs].sort((a, b) => a.sequenceNo - b.sequenceNo).slice(-1)[0];
|
|
234
|
+
const newLegSourceCompanyId = lastLeg?.targetCompanyId ?? this.workingCopy.sourceCompanyId;
|
|
235
|
+
const usedCompanyIds = new Set(this.workingCopy.legs.map(l => l.targetCompanyId));
|
|
236
|
+
const defaultTarget = this.companies.find(c => !usedCompanyIds.has(c.id) && c.id !== newLegSourceCompanyId) ??
|
|
237
|
+
this.companies.find(c => c.id !== newLegSourceCompanyId) ??
|
|
238
|
+
this.companies[0];
|
|
239
|
+
// Önce mevcut bacaklardaki henüz senkronize edilmemiş NumAtCard/Döviz/Kur değerleri kaydedilir -
|
|
240
|
+
// aksi halde yeni bacak eklendiğinde dönen tam workingCopy, kullanıcının az önce yazdığı ama hiç
|
|
241
|
+
// sunucuya gönderilmemiş değerleri eski/boş DB değeriyle ezerdi (persistLegChanges ile aynı sorun).
|
|
242
|
+
this.isMutatingLegs = true;
|
|
243
|
+
this.syncPendingLegChanges(this.workingCopy.legs)
|
|
244
|
+
.pipe(switchMap(() => this.service.addLeg(this.workingCopy.id, {
|
|
245
|
+
targetCompanyId: defaultTarget.id,
|
|
246
|
+
legBehavior: LegBehavior.IntermediateChain,
|
|
247
|
+
})), finalize(() => (this.isMutatingLegs = false)))
|
|
248
|
+
.subscribe(result => (this.workingCopy = result));
|
|
249
|
+
}
|
|
250
|
+
// Spec §5 - muhatap eşleştirmesi bulunamayan bacakta kullanıcıdan hedef SAP şirketindeki doğru
|
|
251
|
+
// Müşteri/Satıcı CardCode seçimi istenecektir; bu, Muhatap Eşleştirmeleri ekranına yönlendirilerek
|
|
252
|
+
// yaptırılabilir (spec tarafından açıkça izin verilen arayüz seçeneklerinden biri). "Bulunulan Şirket"
|
|
253
|
+
// burada hedef (OPCH'nin oluşacağı) şirkettir, "İlişkili Şirket" ise kaynak şirkettir - bkz.
|
|
254
|
+
// ResolveVendorCardCodeAsync(inCompanyId: hedef, forRelatedCompanyId: kaynak).
|
|
255
|
+
goToPartnerMapping(leg) {
|
|
256
|
+
this.router.navigate(['/fbdocumentflow/partner-mappings'], {
|
|
257
|
+
state: { sourceCompanyId: leg.targetCompanyId, relatedCompanyId: leg.sourceCompanyId },
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
removeLeg(leg) {
|
|
261
|
+
if (!this.workingCopy || this.workingCopy.legs.length <= 1) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
// Aynı nedenle (bkz. addLeg) silinmeyen diğer bacaklardaki senkronize edilmemiş değerler önce kaydedilir.
|
|
265
|
+
const remainingLegs = this.workingCopy.legs.filter(l => l.id !== leg.id);
|
|
266
|
+
this.isMutatingLegs = true;
|
|
267
|
+
this.syncPendingLegChanges(remainingLegs)
|
|
268
|
+
.pipe(switchMap(() => this.service.removeLeg(this.workingCopy.id, leg.id)), finalize(() => (this.isMutatingLegs = false)))
|
|
269
|
+
.subscribe(result => (this.workingCopy = result));
|
|
270
|
+
}
|
|
271
|
+
// Yeni bir aktarım için çalışma kopyasını ilk kez oluşturur. Zaten oluşturulmuş ama henüz
|
|
272
|
+
// çalıştırılmamış (taslak) bir aktarımda senaryo değiştirmek için applyScenario() kullanılır -
|
|
273
|
+
// örn. "İşlem Geçmişi"nden geri dönülen bir taslak kayıtta.
|
|
274
|
+
fetchScenario() {
|
|
275
|
+
if (!this.newState) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
this.isFetchingScenario = true;
|
|
279
|
+
this.service
|
|
280
|
+
.create({
|
|
281
|
+
sourceCompanyId: this.newState.sourceCompanyId,
|
|
282
|
+
sourceOinvDocEntry: this.newState.docEntry,
|
|
283
|
+
scenarioId: this.scenarioId || undefined,
|
|
284
|
+
sourceDocumentLifecycle: this.newState.sourceDocumentLifecycle,
|
|
285
|
+
targetDocumentLifecycle: this.newState.targetDocumentLifecycle,
|
|
286
|
+
})
|
|
287
|
+
.pipe(finalize(() => (this.isFetchingScenario = false)))
|
|
288
|
+
.subscribe(result => {
|
|
289
|
+
this.workingCopy = result;
|
|
290
|
+
this.isNew = false;
|
|
291
|
+
// URL'i oluşan kayda göre değiştir - sayfa yenilenirse veya geri/ileri gidilirse doğru kayıt yüklensin.
|
|
292
|
+
this.router.navigate(['/fbdocumentflow/document-transfers', result.id], { replaceUrl: true });
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
applyScenario() {
|
|
296
|
+
if (!this.workingCopy) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
this.isFetchingScenario = true;
|
|
300
|
+
this.service
|
|
301
|
+
.applyScenario(this.workingCopy.id, { scenarioId: this.scenarioId || undefined })
|
|
302
|
+
.pipe(finalize(() => (this.isFetchingScenario = false)))
|
|
303
|
+
.subscribe(result => {
|
|
304
|
+
this.workingCopy = result;
|
|
305
|
+
this.scenarioId = result.scenarioId ?? '';
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
loadWorkingCopy(id) {
|
|
309
|
+
this.isLoading = true;
|
|
310
|
+
this.service
|
|
311
|
+
.get(id)
|
|
312
|
+
.pipe(finalize(() => (this.isLoading = false)))
|
|
313
|
+
.subscribe(result => {
|
|
314
|
+
this.workingCopy = result;
|
|
315
|
+
this.scenarioId = result.scenarioId ?? '';
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
buildLegUpdateInput(leg) {
|
|
319
|
+
return {
|
|
320
|
+
targetCompanyId: leg.targetCompanyId,
|
|
321
|
+
legBehavior: leg.legBehavior,
|
|
322
|
+
numAtCard: leg.numAtCard,
|
|
323
|
+
currency: leg.currency,
|
|
324
|
+
exchangeRate: leg.exchangeRate,
|
|
325
|
+
freightAmount: leg.freightAmount,
|
|
326
|
+
selectedConstructionDraftDocType: leg.selectedConstructionDraftDocType,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
// NumAtCard/Döviz/Kur alanları kullanıcı yazarken/alanı terk ederken ayrı bir "kaydet" isteği
|
|
330
|
+
// göndermiyor (bu, art arda hızlı isteklerin ConcurrencyStamp yarış durumuna - AbpDbConcurrencyException,
|
|
331
|
+
// "veri başka bir kullanıcı tarafından değiştirilmiş" - yol açtığı gerçek ortamda gözlemlendi). Bunun
|
|
332
|
+
// yerine ekrandaki değerler yalnızca "Çalıştır"/"Belge Akışını Başlat" tetiklendiği anda, o çağrıdan
|
|
333
|
+
// hemen önce tek seferde backend'e senkronize edilir. Spec §10 - döviz/kur her bacak için (Construction
|
|
334
|
+
// dahil, son bacak dahil) geçerli olduğundan NumAtCard'ın aksine davranış/sıra bazlı filtrelenmez.
|
|
335
|
+
syncPendingLegChanges(legs) {
|
|
336
|
+
// Zaten Başarılı (Success) olmuş bir bacak backend'de artık düzenlenemez (EnsureLegIsEditable,
|
|
337
|
+
// FBDocumentFlow:010017 "LegAlreadySucceeded" fırlatır) - bu fonksiyona önceden TÜM bacaklar
|
|
338
|
+
// (zaten başarılı olanlar dahil) gönderiliyordu. Bu, örn. bir zincirde 1-2. bacak Başarılı, 3. bacak
|
|
339
|
+
// Hatalı iken 3. bacağı tekrar "Çalıştır"a basmayı TAMAMEN imkansız hale getiriyordu - senkronizasyon
|
|
340
|
+
// adımı, henüz 3. bacağa hiç sıra gelmeden, zaten başarılı 1. bacakta bu hatayla patlıyordu (gerçek
|
|
341
|
+
// ortamda gözlemlendi). Yalnızca hâlâ düzenlenebilir (Success olmayan) bacaklar senkronize edilir.
|
|
342
|
+
const editableLegs = legs.filter(l => l.status !== DOCUMENT_TRANSFER_LEG_STATUS_SUCCESS);
|
|
343
|
+
if (!this.workingCopy || editableLegs.length === 0) {
|
|
344
|
+
return of(null);
|
|
345
|
+
}
|
|
346
|
+
// Bacaklar aynı DocumentTransfer (aggregate root) kaydını paylaştığı için forkJoin ile paralel
|
|
347
|
+
// gönderilirse her istek aynı ConcurrencyStamp'i yükler; ilk kaydeden dışındakiler
|
|
348
|
+
// AbpDbConcurrencyException ("veri başka bir kullanıcı/istemci tarafından değiştirilmiş") alır -
|
|
349
|
+
// gerçek ortamda doğrulandı. concatMap ile sırayla gönderilir, her istek bir öncekinin
|
|
350
|
+
// kaydettiği güncel stamp üzerinden devam eder.
|
|
351
|
+
return from(editableLegs).pipe(concatMap(leg => this.service.updateLeg(this.workingCopy.id, leg.id, this.buildLegUpdateInput(leg))), toArray());
|
|
352
|
+
}
|
|
353
|
+
backToList() {
|
|
354
|
+
const sourceCompanyId = this.newState?.sourceCompanyId ?? this.workingCopy?.sourceCompanyId;
|
|
355
|
+
this.router.navigate(['/fbdocumentflow/document-transfers'], {
|
|
356
|
+
state: sourceCompanyId ? { sourceCompanyId } : undefined,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
startFlow() {
|
|
360
|
+
if (!this.workingCopy) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
// Spec §9 - U_Oran tanımsızken akış bloklanmaz; ancak kullanıcının bunu bilerek onaylaması gerekir.
|
|
364
|
+
if (this.hasMissingIncreaseRate()) {
|
|
365
|
+
this.confirmation
|
|
366
|
+
.warn('Bu şirkette bu proje için artırım oranı tanımlı değildir. Artırım uygulanmadan devam etmek istiyor musunuz?', 'FBDocumentFlow::AreYouSure')
|
|
367
|
+
.subscribe(status => {
|
|
368
|
+
if (status === Confirmation.Status.confirm) {
|
|
369
|
+
this.executeStartFlow();
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
this.executeStartFlow();
|
|
375
|
+
}
|
|
376
|
+
executeStartFlow() {
|
|
377
|
+
if (!this.workingCopy) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
this.isStarting = true;
|
|
381
|
+
this.syncPendingLegChanges(this.workingCopy.legs)
|
|
382
|
+
.pipe(switchMap(() => this.service.executeAll(this.workingCopy.id)), finalize(() => (this.isStarting = false)))
|
|
383
|
+
.subscribe({
|
|
384
|
+
next: result => (this.workingCopy = result),
|
|
385
|
+
// ABP zaten başarısız HTTP çağrılarında genel bir hata diyaloğu gösterir.
|
|
386
|
+
error: () => {
|
|
387
|
+
this.isStarting = false;
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
// Yalnızca [leg] (çalıştırılan bacak) senkronize edilirse, kullanıcının BAŞKA bir bacağa yazdığı ama
|
|
392
|
+
// henüz gönderilmemiş NumAtCard/Döviz/Kur değerleri hiç kaydedilmeden kalır - ardından çağrılan
|
|
393
|
+
// loadWorkingCopy() sunucudaki eski (boş) değerle o bacağı ezer, kullanıcı yazdığı değeri kaybeder
|
|
394
|
+
// (gerçek ortamda doğrulandı, executeStartFlow'daki gibi TÜM bacaklar senkronize edilmeli).
|
|
395
|
+
executeLeg(leg) {
|
|
396
|
+
if (!this.workingCopy || !this.canExecuteLeg(leg)) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
this.isExecuting = true;
|
|
400
|
+
this.syncPendingLegChanges(this.workingCopy.legs)
|
|
401
|
+
.pipe(switchMap(() => this.service.executeLeg(this.workingCopy.id, leg.id)), finalize(() => (this.isExecuting = false)))
|
|
402
|
+
.subscribe(() => this.loadWorkingCopy(this.workingCopy.id));
|
|
403
|
+
}
|
|
404
|
+
// "Zinciri İptal Et" yalnızca fiilen iptal edilecek bir şey varken (Devam Ediyor/Hatalı) anlamlıdır;
|
|
405
|
+
// zaten İptal Edildi veya Tamamlandı durumundaki bir aktarımda tekrar gösterilmesi kullanıcıyı
|
|
406
|
+
// yanıltır (spec §12-13 - iptal edilmiş bir zincir tekrar işleme alınmaz, yeniden oluşturma sürecine
|
|
407
|
+
// kaynak faturadan yeni bir aktarımla girilir).
|
|
408
|
+
canCancelChain() {
|
|
409
|
+
const status = this.workingCopy?.status;
|
|
410
|
+
return status === 1 || status === 3; // 1=Devam Ediyor, 3=Hatalı
|
|
411
|
+
}
|
|
412
|
+
cancelChain() {
|
|
413
|
+
if (!this.workingCopy) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
this.confirmation.warn('FBDocumentFlow::DeleteConfirmationMessage', 'FBDocumentFlow::AreYouSure').subscribe(status => {
|
|
417
|
+
if (status === Confirmation.Status.confirm && this.workingCopy) {
|
|
418
|
+
// İptalden sonra bu sayfada kalmak yerine listeye dönülür - backToList() zaten seçili kaynak
|
|
419
|
+
// şirketi router state ile taşıyıp liste ekranında aynı şirketin seçili kalmasını sağlıyor.
|
|
420
|
+
this.service.cancelChain(this.workingCopy.intercompanyId).subscribe(() => {
|
|
421
|
+
this.backToList();
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
statusLabel(status) {
|
|
427
|
+
return ['İşlem Bekliyor', 'Devam Ediyor', 'Tamamlandı', 'Hatalı', 'İptal Edildi'][status] ?? String(status);
|
|
428
|
+
}
|
|
429
|
+
// Spec §14 (18.09.2026 kararı) - süreç parametrik; Kaynak ve Hedef Belge Durumu için AYNI etiket
|
|
430
|
+
// kullanılır (kullanıcı isteğiyle netleştirildi).
|
|
431
|
+
sourceDocumentLifecycleLabel(lifecycle) {
|
|
432
|
+
if (lifecycle == null) {
|
|
433
|
+
return '';
|
|
434
|
+
}
|
|
435
|
+
return lifecycle === SapDocumentLifecycle.Draft ? 'Taslak Müşteri Faturası' : 'Kayıtlı Müşteri Faturası';
|
|
436
|
+
}
|
|
437
|
+
legStatusLabel(status) {
|
|
438
|
+
return ['Bekliyor', 'Başarılı', 'Hatalı', 'Atlandı'][status] ?? String(status);
|
|
439
|
+
}
|
|
440
|
+
// Bir bacakta (özellikle Construction: OPOR→OPDN→OPCH, veya Ara Şirket'te devam OINV oluştuğunda)
|
|
441
|
+
// BİRDEN FAZLA SAP belgesi oluşabilir; önceden yalnızca "son" belge (leg.createdDocType/createdDocEntry)
|
|
442
|
+
// gösteriliyordu, diğerleri (OPOR/OPDN, devam OINV) DTO'da vardı ama ekranda hiç görünmüyordu.
|
|
443
|
+
// Sonuç belge etiketleri (spec §15 - Teknik SAP B1 Alanları tablosundaki nesne kısaltmalarıyla birebir):
|
|
444
|
+
// OPOR/OPDN/OPCH/OINV. Önceden burada leg.createdDocType (backend'de her zaman ham SAP Service Layer
|
|
445
|
+
// entity set adı "PurchaseInvoices" olarak sabit) doğrudan gösteriliyordu - OPOR/OPDN gibi kısa SAP
|
|
446
|
+
// kodlarıyla aynı satırda karışık görünüp anlam karmaşasına yol açıyordu (kullanıcı geri bildirimiyle
|
|
447
|
+
// tespit edildi). Artık tüm belge tipleri aynı kısaltma setiyle, tutarlı şekilde gösteriliyor.
|
|
448
|
+
// Ekranda gösterilecek belge numarası her zaman DocNum üzerinden yürür (kullanıcı geri bildirimiyle
|
|
449
|
+
// netleştirildi) - DocEntry (SAP'ın dahili anahtarı) yalnızca fallback'tir, DocNum bir sebeple
|
|
450
|
+
// yakalanamadıysa (ör. çok eski bir kayıt) belge tamamen kaybolmuş görünmesin diye.
|
|
451
|
+
createdDocumentsSummary(leg) {
|
|
452
|
+
const parts = [];
|
|
453
|
+
if (leg.createdPurchaseOrderDocEntry) {
|
|
454
|
+
parts.push(`OPOR ${leg.createdPurchaseOrderDocNum ?? leg.createdPurchaseOrderDocEntry}`);
|
|
455
|
+
}
|
|
456
|
+
if (leg.createdGoodsReceiptDocEntry) {
|
|
457
|
+
parts.push(`OPDN ${leg.createdGoodsReceiptDocNum ?? leg.createdGoodsReceiptDocEntry}`);
|
|
458
|
+
}
|
|
459
|
+
if (leg.createdDocEntry) {
|
|
460
|
+
parts.push(`OPCH ${leg.createdDocNum ?? leg.createdDocEntry}`);
|
|
461
|
+
}
|
|
462
|
+
if (leg.createdInternalOinvDocEntry) {
|
|
463
|
+
parts.push(`OINV ${leg.createdInternalOinvDocNum ?? leg.createdInternalOinvDocEntry}`);
|
|
464
|
+
}
|
|
465
|
+
return parts.join(' → ');
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
HitDocumentTransferDetailComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: HitDocumentTransferDetailComponent, deps: [{ token: i1.ActivatedRoute }, { token: i1.Router }, { token: i2.DocumentTransferService }, { token: i3.DocumentScenarioService }, { token: i4.SapCompanyProfileService }, { token: i5.ConfirmationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
469
|
+
HitDocumentTransferDetailComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: HitDocumentTransferDetailComponent, selector: "hit-document-transfer-detail", ngImport: i0, template: "<div class=\"card\">\n <div class=\"card-header py-3\">\n <div class=\"row align-items-center\">\n <div class=\"col\">\n <h5 class=\"card-title mb-0\">Belge Ak\u0131\u015F\u0131 / Intercompany Aktar\u0131m\u0131</h5>\n </div>\n <div class=\"col-auto\">\n <button class=\"btn btn-sm btn-outline-secondary\" (click)=\"backToList()\">\n <i class=\"fa fa-arrow-left me-1\"></i>Listeye D\u00F6n\n </button>\n </div>\n </div>\n </div>\n <div class=\"card-body pt-3\">\n <div *ngIf=\"isLoading\" class=\"text-center py-5\">\n <div class=\"spinner-border text-primary\" role=\"status\"></div>\n <div class=\"mt-2 text-muted\">Y\u00FCkleniyor...</div>\n </div>\n\n <ng-container *ngIf=\"!isLoading\">\n <!-- Bu sat\u0131r hem \"yeni\" (hen\u00FCz kay\u0131t olu\u015Fmam\u0131\u015F) hem de kay\u0131t olu\u015Ftuktan sonraki taslak durumunda\n AYNI alan setini g\u00F6sterir - kay\u0131t olu\u015Funca ekran\u0131n alan seti de\u011Fi\u015Fip kullan\u0131c\u0131da \"ba\u015Fka bir\n kay\u0131t m\u0131 bu\" izlenimi vermesin diye. De\u011Ferler \u00F6nce newState'ten (istemcide tutulan \u00F6nizleme),\n o yoksa olu\u015Fan kayd\u0131n ilk baca\u011F\u0131ndan (workingCopy.legs[0]) okunur - ilk bacak her zaman\n newState'in temsil etti\u011Fi \"ilk hedef\" ad\u0131m\u0131yla ayn\u0131 belgedir. -->\n <div class=\"row g-3 mb-3\" *ngIf=\"newState || workingCopy\">\n <div class=\"col-md-3\">\n <label class=\"form-label\">Kaynak \u015Eirket</label>\n <input type=\"text\" class=\"form-control\" [value]=\"companyName()\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">Belge No</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.docNum ?? workingCopy?.sourceOinvDocNum\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">NumAtCard</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.numAtCard ?? workingCopy?.sourceOinvNumAtCard\" disabled />\n </div>\n <div class=\"col-md-1\">\n <label class=\"form-label\">Proje</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.projectCode ?? workingCopy?.projectCode\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">\u0130lk Hedef</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.targetCompanyName ?? workingCopy?.legs?.[0]?.targetCompanyName\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">D\u00F6viz</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.currency ?? workingCopy?.legs?.[0]?.currency\" disabled />\n </div>\n </div>\n\n <!-- Belge Durumu her zaman (yeni kay\u0131tta da) g\u00F6r\u00FCn\u00FCr; Intercompany Id/Aktar\u0131m Durumu/Senaryo yaln\u0131zca\n kay\u0131t olu\u015Ftuktan sonra vard\u0131r - kullan\u0131c\u0131 iste\u011Fiyle hepsi ayn\u0131 sat\u0131rda, Belge Durumu'nun yan\u0131na\n topland\u0131 (\u00F6nceden Intercompany Id/Aktar\u0131m Durumu ayr\u0131 bir sat\u0131rdayd\u0131). -->\n <div class=\"row g-3 mb-3\" *ngIf=\"newState || workingCopy\">\n <div class=\"col-md-2\">\n <label class=\"form-label\">Kaynak Belge Durumu</label>\n <input\n type=\"text\"\n class=\"form-control\"\n [value]=\"sourceDocumentLifecycleLabel(newState?.sourceDocumentLifecycle ?? workingCopy?.sourceDocumentLifecycle)\"\n disabled\n />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">Hedef Belge Durumu</label>\n <!-- Aktar\u0131m hen\u00FCz olu\u015Fturulmad\u0131ysa (isNew) burada se\u00E7ilebilir - kaynaktan ba\u011F\u0131ms\u0131z bir karard\u0131r\n (kullan\u0131c\u0131 geri bildirimiyle netle\u015Ftirildi: kayna\u011F\u0131n modu sabit, hedefin modu burada se\u00E7ilir).\n Olu\u015Ftuktan sonra backend'de sabitlendi\u011Fi i\u00E7in (workingCopy) salt-okunur g\u00F6sterilir. -->\n <select *ngIf=\"isNew && newState\" class=\"form-select\" [(ngModel)]=\"newState.targetDocumentLifecycle\">\n <option *ngFor=\"let o of documentLifecycleOptions\" [ngValue]=\"o.value\">{{ o.label }}</option>\n </select>\n <input\n *ngIf=\"!isNew || !newState\"\n type=\"text\"\n class=\"form-control\"\n [value]=\"sourceDocumentLifecycleLabel(newState?.targetDocumentLifecycle ?? workingCopy?.targetDocumentLifecycle)\"\n disabled\n />\n </div>\n <div class=\"col-md-3\" *ngIf=\"workingCopy\">\n <label class=\"form-label\">Intercompany Id</label>\n <input type=\"text\" class=\"form-control\" [value]=\"workingCopy.intercompanyId\" disabled />\n </div>\n <div class=\"col-md-2\" *ngIf=\"workingCopy\">\n <label class=\"form-label\">Aktar\u0131m Durumu</label>\n <input type=\"text\" class=\"form-control\" [value]=\"statusLabel(workingCopy.status)\" disabled />\n </div>\n <!-- Senaryo, aktar\u0131m hen\u00FCz \u00E7al\u0131\u015Ft\u0131r\u0131lmam\u0131\u015Fken (isDraft()) alt\u0131ndaki \"Haz\u0131r Senaryo\" dropdown'\u0131nda\n zaten d\u00FCzenlenebilir/g\u00F6r\u00FCn\u00FCr durumda - ayn\u0131 bilgiyi burada salt-okunur tekrar g\u00F6stermek\n (kullan\u0131c\u0131 geri bildirimiyle tespit edildi) kafa kar\u0131\u015Ft\u0131r\u0131yordu. Yaln\u0131zca aktar\u0131m art\u0131k\n d\u00FCzenlenemez hale geldi\u011Finde (dropdown kayboldu\u011Funda) burada g\u00F6sterilir. -->\n <div class=\"col-md-3\" *ngIf=\"workingCopy && !isDraft()\">\n <label class=\"form-label\">Senaryo</label>\n <input type=\"text\" class=\"form-control\" [value]=\"scenarioName()\" disabled />\n </div>\n </div>\n\n <!-- Taslak: haz\u0131r senaryo se\u00E7imi, hen\u00FCz \u00E7al\u0131\u015Ft\u0131r\u0131lmad\u0131. -->\n <ng-container *ngIf=\"isDraft()\">\n <div class=\"row g-3 align-items-end mb-3\">\n <div class=\"col-md-4\">\n <label class=\"form-label\">Haz\u0131r Senaryo</label>\n <select class=\"form-select\" [(ngModel)]=\"scenarioId\">\n <option [ngValue]=\"''\">Senaryosuz (yaln\u0131zca ilk hedef baca\u011F\u0131)</option>\n <option *ngFor=\"let s of availableScenarios()\" [ngValue]=\"s.id\">{{ s.name }}</option>\n </select>\n </div>\n <div class=\"col-md-2\">\n <button\n class=\"btn btn-outline-primary\"\n (click)=\"isNew ? fetchScenario() : applyScenario()\"\n [disabled]=\"isFetchingScenario\"\n >\n <span *ngIf=\"isFetchingScenario\" class=\"spinner-border spinner-border-sm me-1\"></span>\n {{ isNew ? 'Senaryoyu Getir' : 'Senaryoyu Uygula' }}\n </button>\n </div>\n </div>\n </ng-container>\n\n <!-- NumAtCard alanlar\u0131 art\u0131k isDraft()'a ba\u011Fl\u0131 DE\u011E\u0130L: taslakta d\u00FCzenlenebilir, \u00E7al\u0131\u015Ft\u0131r\u0131ld\u0131ktan\n sonra (isDraft() false olsa da) salt-okunur olarak ekranda kal\u0131r - \"Haz\u0131r Senaryo\" blo\u011Fuyla\n birlikte tamamen kaybolmas\u0131n diye. -->\n <ng-container *ngIf=\"workingCopy\">\n <div class=\"row g-3 align-items-end mb-3\" *ngIf=\"hasIntermediateNumAtCardLegs()\">\n <div class=\"col-md-3\" *ngFor=\"let leg of workingCopy.legs\">\n <ng-container *ngIf=\"leg.legBehavior === 0 && leg.sequenceNo < workingCopy.legs.length\">\n <label class=\"form-label\">{{ leg.sequenceNo }}. Bacak - {{ leg.targetCompanyName }} M\u00FC\u015Fteri Faturas\u0131 NumAtCard</label>\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"leg.numAtCard\" [disabled]=\"!isDraft()\" />\n </ng-container>\n </div>\n </div>\n\n <div class=\"alert alert-warning\" *ngIf=\"isDraft() && hasMissingIncreaseRate()\">\n Uyar\u0131: \u0130lgili \u015Firkette/projede art\u0131r\u0131m oran\u0131 0 / NULL. Art\u0131r\u0131m uygulanmadan devam etmek istiyor musunuz?\n </div>\n\n <div class=\"alert alert-warning\" *ngIf=\"isDraft() && hasMissingConstructionDraftSelection()\">\n Uyar\u0131: Hedef Belge Durumu Taslak oldu\u011Funda Construction bacaklar\u0131nda OPOR \u2192 OPDN \u2192 OPCH zinciri taslak belgeler aras\u0131nda\n \u00E7al\u0131\u015Fmaz. \"Hedefte Olu\u015Facak\" s\u00FCtunundan bu bacaklar i\u00E7in tek bir belge tipi (OPOR / OPDN / OPCH) se\u00E7melisiniz.\n </div>\n </ng-container>\n\n <!-- Tek tablo: taslakta da, \u00E7al\u0131\u015Ft\u0131r\u0131ld\u0131ktan sonra da AYNI s\u00FCtun seti (S\u0131ra..Art\u0131r\u0131m) korunur;\n Durum/Sonu\u00E7 Belge/Hata/\u00C7al\u0131\u015Ft\u0131r yaln\u0131zca \u00E7al\u0131\u015Ft\u0131r\u0131ld\u0131ktan sonra, her sat\u0131r\u0131n ALTINA ikinci bir\n sat\u0131r olarak eklenir - eskiden bu bilgiler ayr\u0131 ve daha dar bir tabloya ge\u00E7ilerek g\u00F6steriliyordu,\n bu da Kaynak Belge/Hedefte Olu\u015Facak gibi s\u00FCtunlar\u0131n \"kaybolmu\u015F\" g\u00F6r\u00FCnmesine yol a\u00E7\u0131yordu. -->\n <ng-container *ngIf=\"workingCopy\">\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <div>\n <h6 class=\"mb-0\">{{ isDraft() ? 'Senaryo \u00C7al\u0131\u015Fma Kopyas\u0131' : 'Aktar\u0131m Sonucu' }}</h6>\n <small class=\"text-muted\" *ngIf=\"isDraft()\">Bu tablo yaln\u0131zca \u00E7al\u0131\u015Fma kopyas\u0131n\u0131 d\u00FCzenler; ana senaryoyu de\u011Fi\u015Ftirmez.</small>\n </div>\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"addLeg()\" *ngIf=\"isDraft()\" [disabled]=\"isMutatingLegs\">\n <i class=\"fa fa-plus me-1\"></i>Bacak Ekle\n </button>\n <button class=\"btn btn-sm btn-outline-danger\" (click)=\"cancelChain()\" *ngIf=\"canCancelChain()\">\n <i class=\"fa fa-ban me-1\"></i>Zinciri \u0130ptal Et\n </button>\n </div>\n\n <div class=\"alert alert-secondary small\" *ngIf=\"workingCopy.status === 4\">\n Bu zincir iptal edildi, bacaklar\u0131 art\u0131k \u00E7al\u0131\u015Ft\u0131r\u0131lamaz/d\u00FCzenlenemez. Yeniden denemek i\u00E7in\n \"Listeye D\u00F6n\"den kaynak faturay\u0131 tekrar se\u00E7ip yeni bir aktar\u0131m ba\u015Flat\u0131n - bu, yeni bir Intercompany Id ile\n \u00E7al\u0131\u015F\u0131r.\n </div>\n\n <div class=\"table-responsive\">\n <table class=\"table table-sm table-bordered align-middle\">\n <thead>\n <tr>\n <th>S\u0131ra</th>\n <th>Kaynak</th>\n <th>Kaynak Belge</th>\n <th>Hedef</th>\n <th>Davran\u0131\u015F</th>\n <th>Hedefte Olu\u015Facak</th>\n <th>OPCH CardCode</th>\n <th>D\u00F6viz</th>\n <th>Kur</th>\n <th>Art\u0131r\u0131m</th>\n <th *ngIf=\"isDraft()\"></th>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let leg of workingCopy.legs\">\n <tr>\n <td>{{ leg.sequenceNo }}</td>\n <td>{{ leg.sourceCompanyName }}</td>\n <td>OINV</td>\n <td>\n <select\n *ngIf=\"isDraft(); else targetText\"\n class=\"form-select form-select-sm\"\n [ngModel]=\"leg.targetCompanyId\"\n (ngModelChange)=\"updateLegTarget(leg, $event)\"\n [disabled]=\"isMutatingLegs\"\n >\n <option *ngFor=\"let c of companies\" [ngValue]=\"c.id\">{{ c.companyName }}</option>\n </select>\n <ng-template #targetText>{{ leg.targetCompanyName }}</ng-template>\n </td>\n <td>\n <select\n *ngIf=\"isDraft(); else behaviorText\"\n class=\"form-select form-select-sm\"\n [ngModel]=\"leg.legBehavior\"\n (ngModelChange)=\"updateLegBehavior(leg, $event)\"\n [disabled]=\"isMutatingLegs\"\n >\n <option *ngFor=\"let b of legBehaviors\" [ngValue]=\"b.value\">{{ b.label }}</option>\n </select>\n <ng-template #behaviorText>{{ legBehaviors[leg.legBehavior]?.label }}</ng-template>\n </td>\n <td>\n <select\n *ngIf=\"isDraft() && isConstructionDraftSelectable(leg); else targetDocText\"\n class=\"form-select form-select-sm\"\n [ngModel]=\"leg.selectedConstructionDraftDocType\"\n (ngModelChange)=\"updateLegConstructionDraftDocType(leg, $event)\"\n [disabled]=\"isMutatingLegs\"\n >\n <option [ngValue]=\"null\">Se\u00E7iniz...</option>\n <option *ngFor=\"let o of constructionDraftDocTypeOptions\" [ngValue]=\"o.value\">{{ o.label }}</option>\n </select>\n <ng-template #targetDocText>{{ legTargetDocLabel(leg) }}</ng-template>\n </td>\n <td>\n <span *ngIf=\"leg.resolvedOpchCardCode\">{{ leg.resolvedOpchCardCode }}</span>\n <div *ngIf=\"!leg.resolvedOpchCardCode\" class=\"d-flex flex-column align-items-start py-1\">\n <span class=\"badge bg-danger\">E\u015Fle\u015Ftirilmedi</span>\n <button\n type=\"button\"\n class=\"btn btn-outline-danger btn-sm mt-2 py-0 px-2\"\n style=\"font-size: 0.72rem\"\n (click)=\"goToPartnerMapping(leg)\"\n title=\"Muhatap E\u015Fle\u015Ftirmeleri ekran\u0131na git\"\n >\n <i class=\"fa fa-link me-1\"></i>E\u015Fle\u015Ftir\n </button>\n </div>\n </td>\n <td>\n <input\n *ngIf=\"isDraft(); else currencyText\"\n type=\"text\"\n class=\"form-control form-control-sm\"\n style=\"width: 5.5rem\"\n [(ngModel)]=\"leg.currency\"\n [placeholder]=\"newState?.currency || 'Kaynaktan'\"\n />\n <ng-template #currencyText>{{ leg.currency || newState?.currency }}</ng-template>\n </td>\n <td>\n <input\n *ngIf=\"isDraft(); else rateText\"\n type=\"number\"\n class=\"form-control form-control-sm\"\n style=\"width: 6rem\"\n [(ngModel)]=\"leg.exchangeRate\"\n placeholder=\"Kaynaktan\"\n />\n <ng-template #rateText>{{ leg.exchangeRate ?? '-' }}</ng-template>\n </td>\n <!-- Spec \u00A79 - art\u0131r\u0131m YALNIZCA bu baca\u011F\u0131n olu\u015Fturdu\u011Fu devam M\u00FC\u015Fteri Faturas\u0131na (bir\n sonraki bacak varsa) uygulan\u0131r; bu hem IntermediateChain hem ConstructionChain i\u00E7in\n ge\u00E7erlidir (Construction'da da nextTargetCompanyId.HasValue ise devam OINV'i\n art\u0131r\u0131mla olu\u015Fturuluyor). \u00D6nceden Construction bacaklar\u0131 legBehavior'a bak\u0131larak\n KO\u015EULSUZ \"-\" g\u00F6steriyordu - zincirin SON baca\u011F\u0131 olmayan bir Construction baca\u011F\u0131n\u0131n\n hedefinde art\u0131r\u0131m oran\u0131 tan\u0131ms\u0131zken kullan\u0131c\u0131 hi\u00E7 uyar\u0131lm\u0131yordu (kod incelemesiyle\n tespit edildi). Do\u011Fru ko\u015Ful \"zincirin son baca\u011F\u0131 m\u0131\" (legTargetDocLabel'daki\n isLastLeg ile ayn\u0131 mant\u0131k), legBehavior de\u011Fil. -->\n <td>\n <span *ngIf=\"leg.sequenceNo >= (workingCopy?.legs?.length ?? 0)\">-</span>\n <ng-container *ngIf=\"leg.sequenceNo < (workingCopy?.legs?.length ?? 0)\">\n <span *ngIf=\"leg.increaseRateApplied ?? leg.plannedIncreaseRate as rate\">{{ rate | number: '1.2-2' }}</span>\n <span\n class=\"text-danger\"\n *ngIf=\"!(leg.increaseRateApplied ?? leg.plannedIncreaseRate)\"\n title=\"Bu \u015Firkette bu proje i\u00E7in art\u0131r\u0131m oran\u0131 tan\u0131ml\u0131 de\u011Fildir. Art\u0131r\u0131m uygulanmadan devam edilecektir.\"\n >\n Tan\u0131ms\u0131z\n </span>\n </ng-container>\n </td>\n <td *ngIf=\"isDraft()\">\n <button\n class=\"btn btn-sm btn-outline-danger\"\n (click)=\"removeLeg(leg)\"\n [disabled]=\"isMutatingLegs || workingCopy.legs.length <= 1\"\n title=\"Baca\u011F\u0131 Sil\"\n >\n <i class=\"fa fa-trash\"></i>\n </button>\n </td>\n </tr>\n <tr class=\"table-light\" *ngIf=\"!isDraft()\">\n <td></td>\n <td colspan=\"9\">\n <div class=\"d-flex align-items-center flex-wrap gap-3\">\n <span>\n <strong>Durum:</strong>\n <span\n class=\"badge ms-1\"\n [class.bg-secondary]=\"leg.status === 0\"\n [class.bg-success]=\"leg.status === 1\"\n [class.bg-danger]=\"leg.status === 2\"\n [class.bg-warning]=\"leg.status === 3\"\n >\n {{ legStatusLabel(leg.status) }}\n </span>\n </span>\n <span *ngIf=\"createdDocumentsSummary(leg) as docs\"><strong>Sonu\u00E7 Belge(ler):</strong> {{ docs }}</span>\n <span class=\"text-danger\" *ngIf=\"leg.errorMessage\"><strong>Hata:</strong> {{ leg.errorMessage }}</span>\n <button\n class=\"btn btn-sm btn-outline-primary ms-auto\"\n (click)=\"executeLeg(leg)\"\n [disabled]=\"isExecuting || !canExecuteLeg(leg)\"\n >\n <span *ngIf=\"isExecuting\" class=\"spinner-border spinner-border-sm me-1\"></span>\n \u00C7al\u0131\u015Ft\u0131r\n </button>\n </div>\n </td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </div>\n\n <ul class=\"text-muted small\" *ngIf=\"isDraft()\">\n <li>\u015Eirketler aras\u0131 OINV \u2192 OPCH ge\u00E7i\u015Finde kaynak NumAtCard hedef OPCH.NumAtCard alan\u0131na aynen ta\u015F\u0131n\u0131r.</li>\n <li>Art\u0131r\u0131m yaln\u0131zca ayn\u0131 \u015Firket i\u00E7inde olu\u015Fturulan yeni M\u00FC\u015Fteri Faturas\u0131na uygulan\u0131r; navlun art\u0131r\u0131m oran\u0131ndan etkilenmez.</li>\n <li>Muhatap kodlar\u0131 Muhatap E\u015Fle\u015Ftirmeleri \u00FCzerinden \u00E7\u00F6z\u00FCl\u00FCr. Kur kaynak belgeden gelir ve kullan\u0131c\u0131 taraf\u0131ndan de\u011Fi\u015Ftirilebilir.</li>\n </ul>\n </ng-container>\n\n <div class=\"d-flex justify-content-end gap-2 mt-3\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"backToList()\">{{ isDraft() ? 'Vazge\u00E7' : 'Kapat' }}</button>\n <button\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"startFlow()\"\n *ngIf=\"isDraft() && workingCopy\"\n [disabled]=\"isStarting || hasMissingConstructionDraftSelection()\"\n >\n <span *ngIf=\"isStarting\" class=\"spinner-border spinner-border-sm me-1\"></span>\n Belge Ak\u0131\u015F\u0131n\u0131 Ba\u015Flat\n </button>\n </div>\n </ng-container>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.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: i7.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i7.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i6.DecimalPipe, name: "number" }] });
|
|
470
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: HitDocumentTransferDetailComponent, decorators: [{
|
|
471
|
+
type: Component,
|
|
472
|
+
args: [{ selector: 'hit-document-transfer-detail', template: "<div class=\"card\">\n <div class=\"card-header py-3\">\n <div class=\"row align-items-center\">\n <div class=\"col\">\n <h5 class=\"card-title mb-0\">Belge Ak\u0131\u015F\u0131 / Intercompany Aktar\u0131m\u0131</h5>\n </div>\n <div class=\"col-auto\">\n <button class=\"btn btn-sm btn-outline-secondary\" (click)=\"backToList()\">\n <i class=\"fa fa-arrow-left me-1\"></i>Listeye D\u00F6n\n </button>\n </div>\n </div>\n </div>\n <div class=\"card-body pt-3\">\n <div *ngIf=\"isLoading\" class=\"text-center py-5\">\n <div class=\"spinner-border text-primary\" role=\"status\"></div>\n <div class=\"mt-2 text-muted\">Y\u00FCkleniyor...</div>\n </div>\n\n <ng-container *ngIf=\"!isLoading\">\n <!-- Bu sat\u0131r hem \"yeni\" (hen\u00FCz kay\u0131t olu\u015Fmam\u0131\u015F) hem de kay\u0131t olu\u015Ftuktan sonraki taslak durumunda\n AYNI alan setini g\u00F6sterir - kay\u0131t olu\u015Funca ekran\u0131n alan seti de\u011Fi\u015Fip kullan\u0131c\u0131da \"ba\u015Fka bir\n kay\u0131t m\u0131 bu\" izlenimi vermesin diye. De\u011Ferler \u00F6nce newState'ten (istemcide tutulan \u00F6nizleme),\n o yoksa olu\u015Fan kayd\u0131n ilk baca\u011F\u0131ndan (workingCopy.legs[0]) okunur - ilk bacak her zaman\n newState'in temsil etti\u011Fi \"ilk hedef\" ad\u0131m\u0131yla ayn\u0131 belgedir. -->\n <div class=\"row g-3 mb-3\" *ngIf=\"newState || workingCopy\">\n <div class=\"col-md-3\">\n <label class=\"form-label\">Kaynak \u015Eirket</label>\n <input type=\"text\" class=\"form-control\" [value]=\"companyName()\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">Belge No</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.docNum ?? workingCopy?.sourceOinvDocNum\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">NumAtCard</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.numAtCard ?? workingCopy?.sourceOinvNumAtCard\" disabled />\n </div>\n <div class=\"col-md-1\">\n <label class=\"form-label\">Proje</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.projectCode ?? workingCopy?.projectCode\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">\u0130lk Hedef</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.targetCompanyName ?? workingCopy?.legs?.[0]?.targetCompanyName\" disabled />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">D\u00F6viz</label>\n <input type=\"text\" class=\"form-control\" [value]=\"newState?.currency ?? workingCopy?.legs?.[0]?.currency\" disabled />\n </div>\n </div>\n\n <!-- Belge Durumu her zaman (yeni kay\u0131tta da) g\u00F6r\u00FCn\u00FCr; Intercompany Id/Aktar\u0131m Durumu/Senaryo yaln\u0131zca\n kay\u0131t olu\u015Ftuktan sonra vard\u0131r - kullan\u0131c\u0131 iste\u011Fiyle hepsi ayn\u0131 sat\u0131rda, Belge Durumu'nun yan\u0131na\n topland\u0131 (\u00F6nceden Intercompany Id/Aktar\u0131m Durumu ayr\u0131 bir sat\u0131rdayd\u0131). -->\n <div class=\"row g-3 mb-3\" *ngIf=\"newState || workingCopy\">\n <div class=\"col-md-2\">\n <label class=\"form-label\">Kaynak Belge Durumu</label>\n <input\n type=\"text\"\n class=\"form-control\"\n [value]=\"sourceDocumentLifecycleLabel(newState?.sourceDocumentLifecycle ?? workingCopy?.sourceDocumentLifecycle)\"\n disabled\n />\n </div>\n <div class=\"col-md-2\">\n <label class=\"form-label\">Hedef Belge Durumu</label>\n <!-- Aktar\u0131m hen\u00FCz olu\u015Fturulmad\u0131ysa (isNew) burada se\u00E7ilebilir - kaynaktan ba\u011F\u0131ms\u0131z bir karard\u0131r\n (kullan\u0131c\u0131 geri bildirimiyle netle\u015Ftirildi: kayna\u011F\u0131n modu sabit, hedefin modu burada se\u00E7ilir).\n Olu\u015Ftuktan sonra backend'de sabitlendi\u011Fi i\u00E7in (workingCopy) salt-okunur g\u00F6sterilir. -->\n <select *ngIf=\"isNew && newState\" class=\"form-select\" [(ngModel)]=\"newState.targetDocumentLifecycle\">\n <option *ngFor=\"let o of documentLifecycleOptions\" [ngValue]=\"o.value\">{{ o.label }}</option>\n </select>\n <input\n *ngIf=\"!isNew || !newState\"\n type=\"text\"\n class=\"form-control\"\n [value]=\"sourceDocumentLifecycleLabel(newState?.targetDocumentLifecycle ?? workingCopy?.targetDocumentLifecycle)\"\n disabled\n />\n </div>\n <div class=\"col-md-3\" *ngIf=\"workingCopy\">\n <label class=\"form-label\">Intercompany Id</label>\n <input type=\"text\" class=\"form-control\" [value]=\"workingCopy.intercompanyId\" disabled />\n </div>\n <div class=\"col-md-2\" *ngIf=\"workingCopy\">\n <label class=\"form-label\">Aktar\u0131m Durumu</label>\n <input type=\"text\" class=\"form-control\" [value]=\"statusLabel(workingCopy.status)\" disabled />\n </div>\n <!-- Senaryo, aktar\u0131m hen\u00FCz \u00E7al\u0131\u015Ft\u0131r\u0131lmam\u0131\u015Fken (isDraft()) alt\u0131ndaki \"Haz\u0131r Senaryo\" dropdown'\u0131nda\n zaten d\u00FCzenlenebilir/g\u00F6r\u00FCn\u00FCr durumda - ayn\u0131 bilgiyi burada salt-okunur tekrar g\u00F6stermek\n (kullan\u0131c\u0131 geri bildirimiyle tespit edildi) kafa kar\u0131\u015Ft\u0131r\u0131yordu. Yaln\u0131zca aktar\u0131m art\u0131k\n d\u00FCzenlenemez hale geldi\u011Finde (dropdown kayboldu\u011Funda) burada g\u00F6sterilir. -->\n <div class=\"col-md-3\" *ngIf=\"workingCopy && !isDraft()\">\n <label class=\"form-label\">Senaryo</label>\n <input type=\"text\" class=\"form-control\" [value]=\"scenarioName()\" disabled />\n </div>\n </div>\n\n <!-- Taslak: haz\u0131r senaryo se\u00E7imi, hen\u00FCz \u00E7al\u0131\u015Ft\u0131r\u0131lmad\u0131. -->\n <ng-container *ngIf=\"isDraft()\">\n <div class=\"row g-3 align-items-end mb-3\">\n <div class=\"col-md-4\">\n <label class=\"form-label\">Haz\u0131r Senaryo</label>\n <select class=\"form-select\" [(ngModel)]=\"scenarioId\">\n <option [ngValue]=\"''\">Senaryosuz (yaln\u0131zca ilk hedef baca\u011F\u0131)</option>\n <option *ngFor=\"let s of availableScenarios()\" [ngValue]=\"s.id\">{{ s.name }}</option>\n </select>\n </div>\n <div class=\"col-md-2\">\n <button\n class=\"btn btn-outline-primary\"\n (click)=\"isNew ? fetchScenario() : applyScenario()\"\n [disabled]=\"isFetchingScenario\"\n >\n <span *ngIf=\"isFetchingScenario\" class=\"spinner-border spinner-border-sm me-1\"></span>\n {{ isNew ? 'Senaryoyu Getir' : 'Senaryoyu Uygula' }}\n </button>\n </div>\n </div>\n </ng-container>\n\n <!-- NumAtCard alanlar\u0131 art\u0131k isDraft()'a ba\u011Fl\u0131 DE\u011E\u0130L: taslakta d\u00FCzenlenebilir, \u00E7al\u0131\u015Ft\u0131r\u0131ld\u0131ktan\n sonra (isDraft() false olsa da) salt-okunur olarak ekranda kal\u0131r - \"Haz\u0131r Senaryo\" blo\u011Fuyla\n birlikte tamamen kaybolmas\u0131n diye. -->\n <ng-container *ngIf=\"workingCopy\">\n <div class=\"row g-3 align-items-end mb-3\" *ngIf=\"hasIntermediateNumAtCardLegs()\">\n <div class=\"col-md-3\" *ngFor=\"let leg of workingCopy.legs\">\n <ng-container *ngIf=\"leg.legBehavior === 0 && leg.sequenceNo < workingCopy.legs.length\">\n <label class=\"form-label\">{{ leg.sequenceNo }}. Bacak - {{ leg.targetCompanyName }} M\u00FC\u015Fteri Faturas\u0131 NumAtCard</label>\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"leg.numAtCard\" [disabled]=\"!isDraft()\" />\n </ng-container>\n </div>\n </div>\n\n <div class=\"alert alert-warning\" *ngIf=\"isDraft() && hasMissingIncreaseRate()\">\n Uyar\u0131: \u0130lgili \u015Firkette/projede art\u0131r\u0131m oran\u0131 0 / NULL. Art\u0131r\u0131m uygulanmadan devam etmek istiyor musunuz?\n </div>\n\n <div class=\"alert alert-warning\" *ngIf=\"isDraft() && hasMissingConstructionDraftSelection()\">\n Uyar\u0131: Hedef Belge Durumu Taslak oldu\u011Funda Construction bacaklar\u0131nda OPOR \u2192 OPDN \u2192 OPCH zinciri taslak belgeler aras\u0131nda\n \u00E7al\u0131\u015Fmaz. \"Hedefte Olu\u015Facak\" s\u00FCtunundan bu bacaklar i\u00E7in tek bir belge tipi (OPOR / OPDN / OPCH) se\u00E7melisiniz.\n </div>\n </ng-container>\n\n <!-- Tek tablo: taslakta da, \u00E7al\u0131\u015Ft\u0131r\u0131ld\u0131ktan sonra da AYNI s\u00FCtun seti (S\u0131ra..Art\u0131r\u0131m) korunur;\n Durum/Sonu\u00E7 Belge/Hata/\u00C7al\u0131\u015Ft\u0131r yaln\u0131zca \u00E7al\u0131\u015Ft\u0131r\u0131ld\u0131ktan sonra, her sat\u0131r\u0131n ALTINA ikinci bir\n sat\u0131r olarak eklenir - eskiden bu bilgiler ayr\u0131 ve daha dar bir tabloya ge\u00E7ilerek g\u00F6steriliyordu,\n bu da Kaynak Belge/Hedefte Olu\u015Facak gibi s\u00FCtunlar\u0131n \"kaybolmu\u015F\" g\u00F6r\u00FCnmesine yol a\u00E7\u0131yordu. -->\n <ng-container *ngIf=\"workingCopy\">\n <div class=\"d-flex justify-content-between align-items-center mb-2\">\n <div>\n <h6 class=\"mb-0\">{{ isDraft() ? 'Senaryo \u00C7al\u0131\u015Fma Kopyas\u0131' : 'Aktar\u0131m Sonucu' }}</h6>\n <small class=\"text-muted\" *ngIf=\"isDraft()\">Bu tablo yaln\u0131zca \u00E7al\u0131\u015Fma kopyas\u0131n\u0131 d\u00FCzenler; ana senaryoyu de\u011Fi\u015Ftirmez.</small>\n </div>\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"addLeg()\" *ngIf=\"isDraft()\" [disabled]=\"isMutatingLegs\">\n <i class=\"fa fa-plus me-1\"></i>Bacak Ekle\n </button>\n <button class=\"btn btn-sm btn-outline-danger\" (click)=\"cancelChain()\" *ngIf=\"canCancelChain()\">\n <i class=\"fa fa-ban me-1\"></i>Zinciri \u0130ptal Et\n </button>\n </div>\n\n <div class=\"alert alert-secondary small\" *ngIf=\"workingCopy.status === 4\">\n Bu zincir iptal edildi, bacaklar\u0131 art\u0131k \u00E7al\u0131\u015Ft\u0131r\u0131lamaz/d\u00FCzenlenemez. Yeniden denemek i\u00E7in\n \"Listeye D\u00F6n\"den kaynak faturay\u0131 tekrar se\u00E7ip yeni bir aktar\u0131m ba\u015Flat\u0131n - bu, yeni bir Intercompany Id ile\n \u00E7al\u0131\u015F\u0131r.\n </div>\n\n <div class=\"table-responsive\">\n <table class=\"table table-sm table-bordered align-middle\">\n <thead>\n <tr>\n <th>S\u0131ra</th>\n <th>Kaynak</th>\n <th>Kaynak Belge</th>\n <th>Hedef</th>\n <th>Davran\u0131\u015F</th>\n <th>Hedefte Olu\u015Facak</th>\n <th>OPCH CardCode</th>\n <th>D\u00F6viz</th>\n <th>Kur</th>\n <th>Art\u0131r\u0131m</th>\n <th *ngIf=\"isDraft()\"></th>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let leg of workingCopy.legs\">\n <tr>\n <td>{{ leg.sequenceNo }}</td>\n <td>{{ leg.sourceCompanyName }}</td>\n <td>OINV</td>\n <td>\n <select\n *ngIf=\"isDraft(); else targetText\"\n class=\"form-select form-select-sm\"\n [ngModel]=\"leg.targetCompanyId\"\n (ngModelChange)=\"updateLegTarget(leg, $event)\"\n [disabled]=\"isMutatingLegs\"\n >\n <option *ngFor=\"let c of companies\" [ngValue]=\"c.id\">{{ c.companyName }}</option>\n </select>\n <ng-template #targetText>{{ leg.targetCompanyName }}</ng-template>\n </td>\n <td>\n <select\n *ngIf=\"isDraft(); else behaviorText\"\n class=\"form-select form-select-sm\"\n [ngModel]=\"leg.legBehavior\"\n (ngModelChange)=\"updateLegBehavior(leg, $event)\"\n [disabled]=\"isMutatingLegs\"\n >\n <option *ngFor=\"let b of legBehaviors\" [ngValue]=\"b.value\">{{ b.label }}</option>\n </select>\n <ng-template #behaviorText>{{ legBehaviors[leg.legBehavior]?.label }}</ng-template>\n </td>\n <td>\n <select\n *ngIf=\"isDraft() && isConstructionDraftSelectable(leg); else targetDocText\"\n class=\"form-select form-select-sm\"\n [ngModel]=\"leg.selectedConstructionDraftDocType\"\n (ngModelChange)=\"updateLegConstructionDraftDocType(leg, $event)\"\n [disabled]=\"isMutatingLegs\"\n >\n <option [ngValue]=\"null\">Se\u00E7iniz...</option>\n <option *ngFor=\"let o of constructionDraftDocTypeOptions\" [ngValue]=\"o.value\">{{ o.label }}</option>\n </select>\n <ng-template #targetDocText>{{ legTargetDocLabel(leg) }}</ng-template>\n </td>\n <td>\n <span *ngIf=\"leg.resolvedOpchCardCode\">{{ leg.resolvedOpchCardCode }}</span>\n <div *ngIf=\"!leg.resolvedOpchCardCode\" class=\"d-flex flex-column align-items-start py-1\">\n <span class=\"badge bg-danger\">E\u015Fle\u015Ftirilmedi</span>\n <button\n type=\"button\"\n class=\"btn btn-outline-danger btn-sm mt-2 py-0 px-2\"\n style=\"font-size: 0.72rem\"\n (click)=\"goToPartnerMapping(leg)\"\n title=\"Muhatap E\u015Fle\u015Ftirmeleri ekran\u0131na git\"\n >\n <i class=\"fa fa-link me-1\"></i>E\u015Fle\u015Ftir\n </button>\n </div>\n </td>\n <td>\n <input\n *ngIf=\"isDraft(); else currencyText\"\n type=\"text\"\n class=\"form-control form-control-sm\"\n style=\"width: 5.5rem\"\n [(ngModel)]=\"leg.currency\"\n [placeholder]=\"newState?.currency || 'Kaynaktan'\"\n />\n <ng-template #currencyText>{{ leg.currency || newState?.currency }}</ng-template>\n </td>\n <td>\n <input\n *ngIf=\"isDraft(); else rateText\"\n type=\"number\"\n class=\"form-control form-control-sm\"\n style=\"width: 6rem\"\n [(ngModel)]=\"leg.exchangeRate\"\n placeholder=\"Kaynaktan\"\n />\n <ng-template #rateText>{{ leg.exchangeRate ?? '-' }}</ng-template>\n </td>\n <!-- Spec \u00A79 - art\u0131r\u0131m YALNIZCA bu baca\u011F\u0131n olu\u015Fturdu\u011Fu devam M\u00FC\u015Fteri Faturas\u0131na (bir\n sonraki bacak varsa) uygulan\u0131r; bu hem IntermediateChain hem ConstructionChain i\u00E7in\n ge\u00E7erlidir (Construction'da da nextTargetCompanyId.HasValue ise devam OINV'i\n art\u0131r\u0131mla olu\u015Fturuluyor). \u00D6nceden Construction bacaklar\u0131 legBehavior'a bak\u0131larak\n KO\u015EULSUZ \"-\" g\u00F6steriyordu - zincirin SON baca\u011F\u0131 olmayan bir Construction baca\u011F\u0131n\u0131n\n hedefinde art\u0131r\u0131m oran\u0131 tan\u0131ms\u0131zken kullan\u0131c\u0131 hi\u00E7 uyar\u0131lm\u0131yordu (kod incelemesiyle\n tespit edildi). Do\u011Fru ko\u015Ful \"zincirin son baca\u011F\u0131 m\u0131\" (legTargetDocLabel'daki\n isLastLeg ile ayn\u0131 mant\u0131k), legBehavior de\u011Fil. -->\n <td>\n <span *ngIf=\"leg.sequenceNo >= (workingCopy?.legs?.length ?? 0)\">-</span>\n <ng-container *ngIf=\"leg.sequenceNo < (workingCopy?.legs?.length ?? 0)\">\n <span *ngIf=\"leg.increaseRateApplied ?? leg.plannedIncreaseRate as rate\">{{ rate | number: '1.2-2' }}</span>\n <span\n class=\"text-danger\"\n *ngIf=\"!(leg.increaseRateApplied ?? leg.plannedIncreaseRate)\"\n title=\"Bu \u015Firkette bu proje i\u00E7in art\u0131r\u0131m oran\u0131 tan\u0131ml\u0131 de\u011Fildir. Art\u0131r\u0131m uygulanmadan devam edilecektir.\"\n >\n Tan\u0131ms\u0131z\n </span>\n </ng-container>\n </td>\n <td *ngIf=\"isDraft()\">\n <button\n class=\"btn btn-sm btn-outline-danger\"\n (click)=\"removeLeg(leg)\"\n [disabled]=\"isMutatingLegs || workingCopy.legs.length <= 1\"\n title=\"Baca\u011F\u0131 Sil\"\n >\n <i class=\"fa fa-trash\"></i>\n </button>\n </td>\n </tr>\n <tr class=\"table-light\" *ngIf=\"!isDraft()\">\n <td></td>\n <td colspan=\"9\">\n <div class=\"d-flex align-items-center flex-wrap gap-3\">\n <span>\n <strong>Durum:</strong>\n <span\n class=\"badge ms-1\"\n [class.bg-secondary]=\"leg.status === 0\"\n [class.bg-success]=\"leg.status === 1\"\n [class.bg-danger]=\"leg.status === 2\"\n [class.bg-warning]=\"leg.status === 3\"\n >\n {{ legStatusLabel(leg.status) }}\n </span>\n </span>\n <span *ngIf=\"createdDocumentsSummary(leg) as docs\"><strong>Sonu\u00E7 Belge(ler):</strong> {{ docs }}</span>\n <span class=\"text-danger\" *ngIf=\"leg.errorMessage\"><strong>Hata:</strong> {{ leg.errorMessage }}</span>\n <button\n class=\"btn btn-sm btn-outline-primary ms-auto\"\n (click)=\"executeLeg(leg)\"\n [disabled]=\"isExecuting || !canExecuteLeg(leg)\"\n >\n <span *ngIf=\"isExecuting\" class=\"spinner-border spinner-border-sm me-1\"></span>\n \u00C7al\u0131\u015Ft\u0131r\n </button>\n </div>\n </td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </div>\n\n <ul class=\"text-muted small\" *ngIf=\"isDraft()\">\n <li>\u015Eirketler aras\u0131 OINV \u2192 OPCH ge\u00E7i\u015Finde kaynak NumAtCard hedef OPCH.NumAtCard alan\u0131na aynen ta\u015F\u0131n\u0131r.</li>\n <li>Art\u0131r\u0131m yaln\u0131zca ayn\u0131 \u015Firket i\u00E7inde olu\u015Fturulan yeni M\u00FC\u015Fteri Faturas\u0131na uygulan\u0131r; navlun art\u0131r\u0131m oran\u0131ndan etkilenmez.</li>\n <li>Muhatap kodlar\u0131 Muhatap E\u015Fle\u015Ftirmeleri \u00FCzerinden \u00E7\u00F6z\u00FCl\u00FCr. Kur kaynak belgeden gelir ve kullan\u0131c\u0131 taraf\u0131ndan de\u011Fi\u015Ftirilebilir.</li>\n </ul>\n </ng-container>\n\n <div class=\"d-flex justify-content-end gap-2 mt-3\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"backToList()\">{{ isDraft() ? 'Vazge\u00E7' : 'Kapat' }}</button>\n <button\n type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"startFlow()\"\n *ngIf=\"isDraft() && workingCopy\"\n [disabled]=\"isStarting || hasMissingConstructionDraftSelection()\"\n >\n <span *ngIf=\"isStarting\" class=\"spinner-border spinner-border-sm me-1\"></span>\n Belge Ak\u0131\u015F\u0131n\u0131 Ba\u015Flat\n </button>\n </div>\n </ng-container>\n </div>\n</div>\n" }]
|
|
473
|
+
}], ctorParameters: function () { return [{ type: i1.ActivatedRoute }, { type: i1.Router }, { type: i2.DocumentTransferService }, { type: i3.DocumentScenarioService }, { type: i4.SapCompanyProfileService }, { type: i5.ConfirmationService }]; } });
|
|
474
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGl0LWRvY3VtZW50LXRyYW5zZmVyLWRldGFpbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9mYmRvY3VtZW50Zmxvdy9zcmMvbGliL2NvbXBvbmVudHMvaGl0LWRvY3VtZW50LXRyYW5zZmVycy9jb21wb25lbnRzL2hpdC1kb2N1bWVudC10cmFuc2Zlci1kZXRhaWwuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZmJkb2N1bWVudGZsb3cvc3JjL2xpYi9jb21wb25lbnRzL2hpdC1kb2N1bWVudC10cmFuc2ZlcnMvY29tcG9uZW50cy9oaXQtZG9jdW1lbnQtdHJhbnNmZXItZGV0YWlsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFFbEQsT0FBTyxFQUFFLFlBQVksRUFBdUIsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNoQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUNMLDZCQUE2QixFQUk3QixvQkFBb0IsR0FDckIsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLEVBQWdELFdBQVcsRUFBRSxNQUFNLG1DQUFtQyxDQUFDOzs7Ozs7Ozs7QUFHOUcsTUFBTSw4QkFBOEIsR0FBRyxDQUFDLENBQUM7QUFDekMsTUFBTSxrQ0FBa0MsR0FBRyxDQUFDLENBQUM7QUFDN0MsTUFBTSxrQ0FBa0MsR0FBRyxDQUFDLENBQUM7QUFDN0MsTUFBTSxvQ0FBb0MsR0FBRyxDQUFDLENBQUM7QUFDL0MsTUFBTSxvQ0FBb0MsR0FBRyxDQUFDLENBQUM7QUFDL0MsTUFBTSxtQ0FB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QUFDO1FBQzNCLElBQUksR0FBRyxDQUFDLDRCQUE0QixFQUFFO1lBQ3BDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsMEJBQTBCLElBQUksR0FBRyxDQUFDLDRCQUE0QixFQUFFLENBQUMsQ0FBQztTQUMxRjtRQUNELElBQUksR0FBRyxDQUFDLDJCQUEyQixFQUFFO1lBQ25DLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMseUJBQXlCLElBQUksR0FBRyxDQUFDLDJCQUEyQixFQUFFLENBQUMsQ0FBQztTQUN4RjtRQUNELElBQUksR0FBRyxDQUFDLGVBQWUsRUFBRTtZQUN2QixLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLGFBQWEsSUFBSSxHQUFHLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQztTQUNoRTtRQUNELElBQUksR0FBRyxDQUFDLDJCQUEyQixFQUFFO1lBQ25DLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMseUJBQXlCLElBQUksR0FBRyxDQUFDLDJCQUEyQixFQUFFLENBQUMsQ0FBQztTQUN4RjtRQUNELE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQixDQUFDOzsrSEEvZ0JVLGtDQUFrQzttSEFBbEMsa0NBQWtDLG9FQ2hEL0MscXZwQkFtV0E7MkZEblRhLGtDQUFrQztrQkFKOUMsU0FBUzsrQkFDRSw4QkFBOEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBDb25maXJtYXRpb24sIENvbmZpcm1hdGlvblNlcnZpY2UgfSBmcm9tICdAYWJwL25nLnRoZW1lLnNoYXJlZCc7XG5pbXBvcnQgeyBmcm9tLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY29uY2F0TWFwLCBmaW5hbGl6ZSwgc3dpdGNoTWFwLCB0b0FycmF5IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtcbiAgQ29uc3RydWN0aW9uRHJhZnREb2N1bWVudFR5cGUsXG4gIERvY3VtZW50VHJhbnNmZXJEdG8sXG4gIERvY3VtZW50VHJhbnNmZXJMZWdEdG8sXG4gIERvY3VtZW50VHJhbnNmZXJTZXJ2aWNlLFxuICBTYXBEb2N1bWVudExpZmVjeWNsZSxcbn0gZnJvbSAnLi4vLi4vLi4vcHJveHkvZG9jdW1lbnQtdHJhbnNmZXJzJztcbmltcG9ydCB7IERvY3VtZW50U2NlbmFyaW9EdG8sIERvY3VtZW50U2NlbmFyaW9TZXJ2aWNlLCBMZWdCZWhhdmlvciB9IGZyb20gJy4uLy4uLy4uL3Byb3h5L2RvY3VtZW50LXNjZW5hcmlvcyc7XG5pbXBvcnQgeyBTYXBDb21wYW55UHJvZmlsZUR0bywgU2FwQ29tcGFueVByb2ZpbGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vcHJveHkvc2FwLWNvbXBhbnktcHJvZmlsZXMnO1xuXG5jb25zdCBET0NVTUVOVF9UUkFOU0ZFUl9TVEFUVVNfRFJBRlQgPSAwO1xuY29uc3QgRE9DVU1FTlRfVFJBTlNGRVJfU1RBVFVTX0NPTVBMRVRFRCA9IDI7XG5jb25zdCBET0NVTUVOVF9UUkFOU0ZFUl9TVEFUVVNfQ0FOQ0VMTEVEID0gNDtcbmNvbnN0IERPQ1VNRU5UX1RSQU5TRkVSX0xFR19TVEFUVVNfUEVORElORyA9IDA7XG5jb25zdCBET0NVTUVOVF9UUkFOU0ZFUl9MRUdfU1RBVFVTX1NVQ0NFU1MgPSAxO1xuY29uc3QgRE9DVU1FTlRfVFJBTlNGRVJfTEVHX1NUQVRVU19GQUlMRUQgPSAyO1xuXG4vLy8gQmVsZ2UgQWt0YXLEsW3EsSBsaXN0ZXNpbmRlbiBcIsSwxZ9sZW1sZXJcIiBpbGUgYnVyYXlhIGdlbGluaXIuIFBvcHVwIHllcmluZSBheXLEsSBiaXIgc2F5ZmEgb2xhcmFrXG4vLy8gdGFzYXJsYW5txLHFn3TEsXIga2kga3VsbGFuxLFjxLEgc29udWN1ICjDtnplbGxpa2xlIGhhdGEpIGtheWJldG1lZGVuIGluY2VsZXllYmlsc2luLCBzYXlmYXnEsSB5ZW5pbGV5ZWJpbHNpblxuLy8vIHZlIFwiTGlzdGV5ZSBEw7ZuXCIgaWxlIGhlciB6YW1hbiBheW7EsSB5ZXJlIGdlcmkgZMO2bmViaWxzaW4uXG5pbnRlcmZhY2UgTmV3VHJhbnNmZXJTdGF0ZSB7XG4gIHNvdXJjZUNvbXBhbnlJZDogc3RyaW5nO1xuICBzb3VyY2VDb21wYW55TmFtZT86IHN0cmluZztcbiAgZG9jRW50cnk6IG51bWJlcjtcbiAgZG9jTnVtPzogc3RyaW5nO1xuICBudW1BdENhcmQ/OiBzdHJpbmc7XG4gIHByb2plY3RDb2RlPzogc3RyaW5nO1xuICB0YXJnZXRDb21wYW55SWQ/OiBzdHJpbmc7XG4gIHRhcmdldENvbXBhbnlOYW1lPzogc3RyaW5nO1xuICBjdXJyZW5jeT86IHN0cmluZztcbiAgLy8gS2F5bmFrIGZhdHVyYW7EsW4ga2VuZGkgbW9kdSAtIEJlbGdlIEFrdGFyxLFtxLEgbGlzdGVzaW5kZWtpIGZpbHRyZWRlbiAoaGFuZ2kgZmF0dXJhIHNlw6dpbGRpeXNlIG9uYSBnw7ZyZSlcbiAgLy8gZ2VsaXIsIFNBQsSwVFTEsFIgdmUgYnUgZWtyYW5kYSBERcSexLDFnlTEsFLEsExFTUVaIChrdWxsYW7EsWPEsSBnZXJpIGJpbGRpcmltaXlsZSBuZXRsZcWfdGlyaWxkaToga2F5bmHEn8SxblxuICAvLyB0YXNsYWsvacWfbGVubWnFnyBvbG1hIGhhbGksIGhhbmdpIERvY0VudHJ5J25pbiBzZcOnaWxkacSfaW5lIGJhxJ9sxLEgZGXEn2nFn21leiBiaXIgZ2Vyw6dla3RpcikuXG4gIHNvdXJjZURvY3VtZW50TGlmZWN5Y2xlOiBTYXBEb2N1bWVudExpZmVjeWNsZTtcbiAgLy8gSGVkZWZ0ZSBvbHXFn2FjYWsgYmVsZ2VsZXJpbiBtb2R1IC0ga2F5bmFrdGFuIEJBxJ5JTVNJWiwga3VsbGFuxLFjxLEgYnUgZWtyYW5kYSBzZcOnZXIgKMO2ci4gS2F5xLF0bMSxIGJpclxuICAvLyBrYXluYWt0YW4gVGFzbGFrIGhlZGVmIGJlbGdlbGVyIMO8cmV0aWxlYmlsaXIpLlxuICB0YXJnZXREb2N1bWVudExpZmVjeWNsZTogU2FwRG9jdW1lbnRMaWZlY3ljbGU7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2hpdC1kb2N1bWVudC10cmFuc2Zlci1kZXRhaWwnLFxuICB0ZW1wbGF0ZVVybDogJy4vaGl0LWRvY3VtZW50LXRyYW5zZmVyLWRldGFpbC5jb21wb25lbnQuaHRtbCcsXG59KVxuZXhwb3J0IGNsYXNzIEhpdERvY3VtZW50VHJhbnNmZXJEZXRhaWxDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBpc05ldyA9IGZhbHNlO1xuICBuZXdTdGF0ZTogTmV3VHJhbnNmZXJTdGF0ZSB8IG51bGwgPSBudWxsO1xuXG4gIHNjZW5hcmlvczogRG9jdW1lbnRTY2VuYXJpb0R0b1tdID0gW107XG4gIHNjZW5hcmlvSWQgPSAnJztcbiAgaXNGZXRjaGluZ1NjZW5hcmlvID0gZmFsc2U7XG5cbiAgY29tcGFuaWVzOiBTYXBDb21wYW55UHJvZmlsZUR0b1tdID0gW107XG4gIGxlZ0JlaGF2aW9ycyA9IFtcbiAgICB7IHZhbHVlOiBMZWdCZWhhdmlvci5JbnRlcm1lZGlhdGVDaGFpbiwgbGFiZWw6ICdBcmEgxZ5pcmtldCcgfSxcbiAgICB7IHZhbHVlOiBMZWdCZWhhdmlvci5Db25zdHJ1Y3Rpb25DaGFpbiwgbGFiZWw6ICdDb25zdHJ1Y3Rpb24nIH0sXG4gIF07XG5cbiAgLy8gU3BlYyDCpzE0ICgxOC4wOS4yMDI2IGthcmFyxLEpIC0gc8O8cmXDpyBwYXJhbWV0cmlrLiBBa3RhcsSxbSBoZW7DvHogb2x1xZ90dXJ1bG1hZMSxeXNhIChpc05ldykga3VsbGFuxLFjxLEgYnVcbiAgLy8gZWtyYW5kYSBcIkhlZGVmIEJlbGdlIER1cnVtdVwibnUgc2XDp2ViaWxpciAoa2F5bmFrdGFuIGJhxJ/EsW1zxLF6KS4gQWt0YXLEsW0gb2x1xZ90dWt0YW4gc29ucmEgYnUgYWxhblxuICAvLyBiYWNrZW5kJ2RlIHNhYml0bGVuaXIgKERvY3VtZW50VHJhbnNmZXIuVGFyZ2V0RG9jdW1lbnRMaWZlY3ljbGUgaW1tdXRhYmxlKSwgYnUgecO8emRlbiB3b3JraW5nQ29weVxuICAvLyB2YXJrZW4gc2FsdC1va3VudXIgZ8O2c3RlcmlsaXIuIEt1bGxhbsSxY8SxIGlzdGXEn2l5bGUgS2F5bmFrIEJlbGdlIER1cnVtdSBpbGUgQVlOSSBldGlrZXRsZXIga3VsbGFuxLFsxLFyLlxuICBkb2N1bWVudExpZmVjeWNsZU9wdGlvbnMgPSBbXG4gICAgeyB2YWx1ZTogU2FwRG9jdW1lbnRMaWZlY3ljbGUuUG9zdGVkLCBsYWJlbDogJ0thecSxdGzEsSBNw7zFn3RlcmkgRmF0dXJhc8SxJyB9LFxuICAgIHsgdmFsdWU6IFNhcERvY3VtZW50TGlmZWN5Y2xlLkRyYWZ0LCBsYWJlbDogJ1Rhc2xhayBNw7zFn3RlcmkgRmF0dXJhc8SxJyB9LFxuICBdO1xuXG4gIC8vIFNwZWMgZWsga2FyYXIgKDE4LjA5LjIwMjYpIC0gaGVkZWYgVGFzbGFrIGlrZW4gQ29uc3RydWN0aW9uIGJhY2HEn8SxbsSxbiAoT1BPUuKGkk9QRE7ihpJPUENIKSB0YWJhbiBiZWxnZVxuICAvLyB6aW5jaXJpIHRhc2xha2xhciBhcmFzxLFuZGEgw6dhbMSxxZ9tYXo7IGJ1IGR1cnVtZGEga3VsbGFuxLFjxLEgw7zDpyBiZWxnZSB0aXBpbmRlbiB5YWxuxLF6Y2EgYmlyaW5pIHNlw6dlci5cbiAgY29uc3RydWN0aW9uRHJhZnREb2NUeXBlT3B0aW9ucyA9IFtcbiAgICB7IHZhbHVlOiBDb25zdHJ1Y3Rpb25EcmFmdERvY3VtZW50VHlwZS5QdXJjaGFzZU9yZGVyLCBsYWJlbDogJ09QT1InIH0sXG4gICAgeyB2YWx1ZTogQ29uc3RydWN0aW9uRHJhZnREb2N1bWVudFR5cGUuR29vZHNSZWNlaXB0LCBsYWJlbDogJ09QRE4nIH0sXG4gICAgeyB2YWx1ZTogQ29uc3RydWN0aW9uRHJhZnREb2N1bWVudFR5cGUuQVBJbnZvaWNlLCBsYWJlbDogJ09QQ0gnIH0sXG4gIF07XG5cbiAgd29ya2luZ0NvcHk6IERvY3VtZW50VHJhbnNmZXJEdG8gfCBudWxsID0gbnVsbDtcbiAgaXNMb2FkaW5nID0gZmFsc2U7XG4gIGlzU3RhcnRpbmcgPSBmYWxzZTtcbiAgaXNFeGVjdXRpbmcgPSBmYWxzZTtcbiAgaXNNdXRhdGluZ0xlZ3MgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgIHByaXZhdGUgc2VydmljZTogRG9jdW1lbnRUcmFuc2ZlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzY2VuYXJpb1NlcnZpY2U6IERvY3VtZW50U2NlbmFyaW9TZXJ2aWNlLFxuICAgIHByaXZhdGUgY29tcGFueVNlcnZpY2U6IFNhcENvbXBhbnlQcm9maWxlU2VydmljZSxcbiAgICBwcml2YXRlIGNvbmZpcm1hdGlvbjogQ29uZmlybWF0aW9uU2VydmljZVxuICApIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5zY2VuYXJpb1NlcnZpY2UuZ2V0TGlzdCh7IG1heFJlc3VsdENvdW50OiAxMDAwLCBza2lwQ291bnQ6IDAsIGlzQWN0aXZlOiB0cnVlIH0pLnN1YnNjcmliZShyZXN1bHQgPT4gKHRoaXMuc2NlbmFyaW9zID0gcmVzdWx0Lml0ZW1zKSk7XG4gICAgdGhpcy5jb21wYW55U2VydmljZS5nZXRMaXN0KHsgbWF4UmVzdWx0Q291bnQ6IDEwMDAsIHNraXBDb3VudDogMCwgaXNBY3RpdmU6IHRydWUgfSkuc3Vic2NyaWJlKHJlc3VsdCA9PiAodGhpcy5jb21wYW5pZXMgPSByZXN1bHQuaXRlbXMpKTtcblxuICAgIGNvbnN0IGlkID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5wYXJhbU1hcC5nZXQoJ2lkJyk7XG4gICAgaWYgKGlkID09PSAnbmV3Jykge1xuICAgICAgdGhpcy5pc05ldyA9IHRydWU7XG4gICAgICBjb25zdCBzdGF0ZSA9IGhpc3Rvcnkuc3RhdGUgYXMgTmV3VHJhbnNmZXJTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICAgIGlmICghc3RhdGU/LnNvdXJjZUNvbXBhbnlJZCB8fCBzdGF0ZS5kb2NFbnRyeSA9PSBudWxsKSB7XG4gICAgICAgIC8vIFNheWZhIGRvxJ9ydWRhbiB5ZW5pbGVubWnFny95ZW5pIHNla21lZGUgYcOnxLFsbcSxxZ9zYSByb3V0ZXIgc3RhdGUga2F5Ym9sdXI7IGtheW5hayBmYXR1cmFuxLFuXG4gICAgICAgIC8vIHNlw6dpbG1lc2kgZ2VyZWtlbiBsaXN0ZXllIGdlcmkgecO2bmxlbmRpcmlsaXIuXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2ZiZG9jdW1lbnRmbG93L2RvY3VtZW50LXRyYW5zZmVycyddKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gc291cmNlRG9jdW1lbnRMaWZlY3ljbGUsIEJlbGdlIEFrdGFyxLFtxLEgbGlzdGVzaW5kZWtpIGZpbHRyZWRlbiBnZWxpciB2ZSBzYWJpdHRpciAocm91dGVyIHN0YXRlIGhpw6dcbiAgICAgIC8vIHRhxZ/EsW5tYWTEsXlzYSAtIMO2ci4gZG/En3J1ZGFuIGJhxJ9sYW50xLF5bGEgZ2VsaW5tacWfc2UgLSB2YXJzYXnEsWxhbiBLYXnEsXRsxLEga2FidWwgZWRpbGlyKS5cbiAgICAgIC8vIHRhcmdldERvY3VtZW50TGlmZWN5Y2xlIGlzZSBrdWxsYW7EsWPEsW7EsW4gYnUgZWtyYW5kYSBzZcOnZWNlxJ9pLCBrYXluYWt0YW4gYmHEn8SxbXPEsXogYmlyIGRlxJ9lcmRpcjtcbiAgICAgIC8vIGJhxZ9sYW5nxLHDp3RhIHZhcnNhecSxbGFuIG9sYXJhayBLYXnEsXRsxLEgZ2VsaXIsIGt1bGxhbsSxY8SxIGlzdGVyc2UgVGFzbGFrJ2Egw6dldmlyaXIuXG4gICAgICB0aGlzLm5ld1N0YXRlID0ge1xuICAgICAgICAuLi5zdGF0ZSxcbiAgICAgICAgc291cmNlRG9jdW1lbnRMaWZlY3ljbGU6IHN0YXRlLnNvdXJjZURvY3VtZW50TGlmZWN5Y2xlID8/IFNhcERvY3VtZW50TGlmZWN5Y2xlLlBvc3RlZCxcbiAgICAgICAgdGFyZ2V0RG9jdW1lbnRMaWZlY3ljbGU6IFNhcERvY3VtZW50TGlmZWN5Y2xlLlBvc3RlZCxcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmIChpZCkge1xuICAgICAgdGhpcy5sb2FkV29ya2luZ0NvcHkoaWQpO1xuICAgIH1cbiAgfVxuXG4gIGNvbXBhbnlOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmV3U3RhdGU/LnNvdXJjZUNvbXBhbnlOYW1lID8/IHRoaXMud29ya2luZ0NvcHk/LnNvdXJjZUNvbXBhbnlOYW1lID8/ICcnO1xuICB9XG5cbiAgc2NlbmFyaW9OYW1lKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLndvcmtpbmdDb3B5Py5zY2VuYXJpb0lkKSB7XG4gICAgICByZXR1cm4gJ1NlbmFyeW9zdXogKHlhbG7EsXpjYSBpbGsgaGVkZWYgYmFjYcSfxLEpJztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2NlbmFyaW9zLmZpbmQocyA9PiBzLmlkID09PSB0aGlzLndvcmtpbmdDb3B5Py5zY2VuYXJpb0lkKT8ubmFtZSA/PyB0aGlzLndvcmtpbmdDb3B5LnNjZW5hcmlvSWQ7XG4gIH1cblxuICAvLyBCaXIgc2VuYXJ5b251biBpbGsgYmFjYcSfxLEgYmVsaXJsaSBiaXIga2F5bmFrIMWfaXJrZXQgdmUgaGVkZWYgxZ9pcmtldCBpw6dpbiB0YW7EsW1sYW5txLHFn3TEsXIuIFNwZWMgwqczIC1cbiAgLy8ga2F5bmFrIGJlbGdlbmluIGlsayBoZWRlZmkgaGVyIHphbWFuIE9JTlYuQ2FyZENvZGUgKyBNdWhhdGFwIEXFn2xlxZ90aXJtZWxlcmkgaWxlIHRlc3BpdCBlZGlsaXI7IGhhesSxclxuICAvLyBzZW5hcnlvIGJ1IGhlZGVmaSBkZcSfacWfdGlyZW1lei4gQnUgecO8emRlbiBoZW0ga2F5bmFrIMWfaXJrZXRpIGhlbSBkZSB6YXRlbiB0ZXNwaXQgZWRpbG1pxZ8gaWxrIGhlZGVmaVxuICAvLyB1eXXFn21heWFuIHNlbmFyeW9sYXIgc2XDp2lsZWJpbGlyIGxpc3RlZGVuIMOnxLFrYXLEsWzEsXIgLSBha3NpIGhhbGRlIGJhY2tlbmRcbiAgLy8gU2NlbmFyaW9Tb3VyY2VDb21wYW55TWlzbWF0Y2gvU2NlbmFyaW9GaXJzdFRhcmdldE1pc21hdGNoIGhhdGFzxLEgdmVyaXIuXG4gIGF2YWlsYWJsZVNjZW5hcmlvcygpOiBEb2N1bWVudFNjZW5hcmlvRHRvW10ge1xuICAgIGNvbnN0IHNvdXJjZUNvbXBhbnlJZCA9IHRoaXMubmV3U3RhdGU/LnNvdXJjZUNvbXBhbnlJZCA/PyB0aGlzLndvcmtpbmdDb3B5Py5zb3VyY2VDb21wYW55SWQ7XG4gICAgY29uc3QgcmVzb2x2ZWRUYXJnZXRDb21wYW55SWQgPSB0aGlzLm5ld1N0YXRlPy50YXJnZXRDb21wYW55SWQgPz8gdGhpcy53b3JraW5nQ29weT8ubGVncz8uWzBdPy50YXJnZXRDb21wYW55SWQ7XG4gICAgaWYgKCFzb3VyY2VDb21wYW55SWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnNjZW5hcmlvcztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zY2VuYXJpb3MuZmlsdGVyKHMgPT4ge1xuICAgICAgY29uc3QgZmlyc3RMZWcgPSBbLi4ucy5sZWdzXS5zb3J0KChhLCBiKSA9PiBhLnNlcXVlbmNlTm8gLSBiLnNlcXVlbmNlTm8pWzBdO1xuICAgICAgaWYgKCFmaXJzdExlZykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChmaXJzdExlZy5zb3VyY2VDb21wYW55SWQgIT09IHNvdXJjZUNvbXBhbnlJZCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gIXJlc29sdmVkVGFyZ2V0Q29tcGFueUlkIHx8IGZpcnN0TGVnLnRhcmdldENvbXBhbnlJZCA9PT0gcmVzb2x2ZWRUYXJnZXRDb21wYW55SWQ7XG4gICAgfSk7XG4gIH1cblxuICBpc0RyYWZ0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzTmV3IHx8ICh0aGlzLndvcmtpbmdDb3B5Py5zdGF0dXMgPz8gRE9DVU1FTlRfVFJBTlNGRVJfU1RBVFVTX0RSQUZUKSA9PT0gRE9DVU1FTlRfVFJBTlNGRVJfU1RBVFVTX0RSQUZUO1xuICB9XG5cbiAgLy8gQmVrbGV5ZW4gYmFjYWtsYXIgaWxrIGtleiDDp2FsxLHFn3TEsXLEsWxhYmlsaXI7IGhhdGFsxLEgYmFjYWtsYXIgZGEgdGVrcmFyIGRlbmVuZWJpbGlyIMOnw7xua8O8IGJ1IG5va3RhZGFcbiAgLy8gaGVuw7x6IGhpw6diaXIgU0FQIGJlbGdlc2kgb2x1xZ9tYW3EscWfdMSxciAoYWtzaSBoYWxkZSBzcGVjIMKnMTMgZ2VyZcSfaSB0w7xtIHppbmNpciBpcHRhbCBlZGlsaXAgeWVuaWRlblxuICAvLyBrdXJ1bG1hbMSxZMSxciwgdGVrIGJhY2FrIHRla3JhcsSxIGRlxJ9pbCkuXG4gIC8vIFNwZWMgwqcxMi0xMyAtIGlwdGFsIGVkaWxtacWfICh2ZXlhIHRhbWFtbGFubcSxxZ8pIGJpciB6aW5jaXIgdGVrcmFyIMOnYWzEscWfdMSxcsSxbG1hejsga3VsbGFuxLFjxLEgeWVuaWRlblxuICAvLyBvbHXFn3R1cm1hIHPDvHJlY2luaSAoa2F5bmFrIGZhdHVyYWRhbiB5ZW5pIGJpciBha3RhcsSxbSBiYcWfbGF0YXJhaywgeWVuaSBiaXIgSW50ZXJjb21wYW55IElkIGlsZSlcbiAgLy8gYmHFn2xhdMSxci4gQmVrbGV5ZW4vSGF0YWzEsSBiaXIgYmFjYWsga2FsbcSxxZ8gb2xzYSBiaWxlICh6aW5jaXIgaGVuw7x6IHTDvG0gYmFjYWtsYXLEsSDDp2FsxLHFn3TEsXJtYWRhbiBpcHRhbFxuICAvLyBlZGlsZGl5c2UpIGJ1IGJhY2FrbGFyIGFydMSxayDDp2FsxLHFn3TEsXLEsWxhbWF6IC0gYmFja2VuZCBkYSBidW51IFRyYW5zZmVyTm90RWRpdGFibGUgaWxlIHJlZGRlZGVyLFxuICAvLyBidXJhZGEgYnV0b24gZW4gYmHFn3RhbiBkZXZyZSBkxLHFn8SxIGLEsXJha8SxbGFyYWsga3VsbGFuxLFjxLF5YSBuZXQgYmlyIHNpbnlhbCB2ZXJpbGlyLlxuICBjYW5FeGVjdXRlTGVnKGxlZzogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0byk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRyYW5zZmVyU3RhdHVzID0gdGhpcy53b3JraW5nQ29weT8uc3RhdHVzO1xuICAgIGlmICh0cmFuc2ZlclN0YXR1cyA9PT0gRE9DVU1FTlRfVFJBTlNGRVJfU1RBVFVTX0NBTkNFTExFRCB8fCB0cmFuc2ZlclN0YXR1cyA9PT0gRE9DVU1FTlRfVFJBTlNGRVJfU1RBVFVTX0NPTVBMRVRFRCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAodGhpcy5pc0NvbnN0cnVjdGlvbkRyYWZ0U2VsZWN0YWJsZShsZWcpICYmIGxlZy5zZWxlY3RlZENvbnN0cnVjdGlvbkRyYWZ0RG9jVHlwZSA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBsZWcuc3RhdHVzID09PSBET0NVTUVOVF9UUkFOU0ZFUl9MRUdfU1RBVFVTX1BFTkRJTkcgfHwgbGVnLnN0YXR1cyA9PT0gRE9DVU1FTlRfVFJBTlNGRVJfTEVHX1NUQVRVU19GQUlMRUQ7XG4gIH1cblxuICAvLyBTcGVjIGVrIGthcmFyICgxOC4wOS4yMDI2KSAtIGhlZGVmIFRhc2xhayBpa2VuIENvbnN0cnVjdGlvbiBiYWNhxJ/EsW7EsW4gT1BPUuKGkk9QRE7ihpJPUENIIHRhYmFuIGJlbGdlXG4gIC8vIHppbmNpcmkgdGFzbGFrbGFyIGFyYXPEsW5kYSDDp2FsxLHFn21hejsgYnUgYmFjYWtsYXJkYSBrdWxsYW7EsWPEsSB6aW5jaXIgeWVyaW5lIFRFSyBiaXIgYmVsZ2UgdGlwaSBzZcOnZXJcbiAgLy8gKGJrei4gRXhlY3V0ZVNpbmdsZURyYWZ0RG9jdW1lbnRBc3luYywgYmFja2VuZCkuIEhlZGVmIEthecSxdGzEsSBpa2VuIChub3JtYWwgemluY2lyKSBidSBnZcOnZXJsaSBkZcSfaWxkaXIuXG4gIGlzQ29uc3RydWN0aW9uRHJhZnRTZWxlY3RhYmxlKGxlZzogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0byk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBsZWcubGVnQmVoYXZpb3IgPT09IExlZ0JlaGF2aW9yLkNvbnN0cnVjdGlvbkNoYWluICYmIHRoaXMud29ya2luZ0NvcHk/LnRhcmdldERvY3VtZW50TGlmZWN5Y2xlID09PSBTYXBEb2N1bWVudExpZmVjeWNsZS5EcmFmdDtcbiAgfVxuXG4gIGhhc01pc3NpbmdDb25zdHJ1Y3Rpb25EcmFmdFNlbGVjdGlvbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHRoaXMud29ya2luZ0NvcHk/LmxlZ3MgPz8gW10pLnNvbWUobCA9PiB0aGlzLmlzQ29uc3RydWN0aW9uRHJhZnRTZWxlY3RhYmxlKGwpICYmIGwuc2VsZWN0ZWRDb25zdHJ1Y3Rpb25EcmFmdERvY1R5cGUgPT0gbnVsbCk7XG4gIH1cblxuICB1cGRhdGVMZWdDb25zdHJ1Y3Rpb25EcmFmdERvY1R5cGUobGVnOiBEb2N1bWVudFRyYW5zZmVyTGVnRHRvLCB2YWx1ZTogQ29uc3RydWN0aW9uRHJhZnREb2N1bWVudFR5cGUgfCBudWxsKSB7XG4gICAgaWYgKCF0aGlzLndvcmtpbmdDb3B5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGVnLnNlbGVjdGVkQ29uc3RydWN0aW9uRHJhZnREb2NUeXBlID0gdmFsdWUgPz8gdW5kZWZpbmVkO1xuICAgIHRoaXMucGVyc2lzdExlZ0NoYW5nZXMoKTtcbiAgfVxuXG4gIGxlZ1RhcmdldERvY0xhYmVsKGxlZzogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0byk6IHN0cmluZyB7XG4gICAgY29uc3QgaXNMYXN0TGVnID0gbGVnLnNlcXVlbmNlTm8gPj0gKHRoaXMud29ya2luZ0NvcHk/LmxlZ3MubGVuZ3RoID8/IDApO1xuICAgIGlmIChsZWcubGVnQmVoYXZpb3IgPT09IExlZ0JlaGF2aW9yLkNvbnN0cnVjdGlvbkNoYWluKSB7XG4gICAgICBpZiAodGhpcy5pc0NvbnN0cnVjdGlvbkRyYWZ0U2VsZWN0YWJsZShsZWcpKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkTGFiZWwgPVxuICAgICAgICAgIHRoaXMuY29uc3RydWN0aW9uRHJhZnREb2NUeXBlT3B0aW9ucy5maW5kKG8gPT4gby52YWx1ZSA9PT0gbGVnLnNlbGVjdGVkQ29uc3RydWN0aW9uRHJhZnREb2NUeXBlKT8ubGFiZWwgPz8gJ1Nlw6dpbG1lZGknO1xuICAgICAgICByZXR1cm4gaXNMYXN0TGVnID8gc2VsZWN0ZWRMYWJlbCA6IGAke3NlbGVjdGVkTGFiZWx9IOKGkiBPSU5WYDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0xhc3RMZWcgPyAnT1BPUiDihpIgT1BETiDihpIgT1BDSCcgOiAnT1BPUiDihpIgT1BETiDihpIgT1BDSCDihpIgT0lOVic7XG4gICAgfVxuICAgIHJldHVybiBpc0xhc3RMZWcgPyAnT1BDSCcgOiAnT1BDSCDihpIgT0lOVic7XG4gIH1cblxuICAvLyBTcGVjIMKnOSAtIGFydMSxcsSxbSB5YWxuxLF6Y2EgSW50ZXJtZWRpYXRlQ2hhaW4nZGUgZGXEn2lsLCBDb25zdHJ1Y3Rpb25DaGFpbiBiYWNhxJ/EsW7EsW4gKHNvbnJha2kgYmFjYWtcbiAgLy8gdmFyc2EpIG9sdcWfdHVyZHXEn3UgZGV2YW0gTcO8xZ90ZXJpIEZhdHVyYXPEsW5kYSBkYSB1eWd1bGFuxLFyIC0gw7ZuY2VkZW4geWFsbsSxemNhIEludGVybWVkaWF0ZUNoYWluXG4gIC8vIGtvbnRyb2wgZWRpbGl5b3JkdSwgYnUgZGEgYmlyIENvbnN0cnVjdGlvbiBiYWNhxJ/EsW7EsW4gaGVkZWZpbmRlIGFydMSxcsSxbSBvcmFuxLEgdGFuxLFtc8SxemtlbiBrdWxsYW7EsWPEsW7EsW5cbiAgLy8gaGnDpyB1eWFyxLFsbWFkYW4gc2Vzc2l6Y2UgYXJ0xLFyxLFtc8SxeiBkZXZhbSBlZGlsbWVzaW5lIHlvbCBhw6fEsXlvcmR1IChrb2QgaW5jZWxlbWVzaXlsZSB0ZXNwaXQgZWRpbGRpKS5cbiAgaGFzTWlzc2luZ0luY3JlYXNlUmF0ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHRoaXMud29ya2luZ0NvcHk/LmxlZ3MgPz8gW10pLnNvbWUoXG4gICAgICBsID0+XG4gICAgICAgIChsLmxlZ0JlaGF2aW9yID09PSBMZWdCZWhhdmlvci5JbnRlcm1lZGlhdGVDaGFpbiB8fCBsLmxlZ0JlaGF2aW9yID09PSBMZWdCZWhhdmlvci5Db25zdHJ1Y3Rpb25DaGFpbikgJiZcbiAgICAgICAgbC5wbGFubmVkSW5jcmVhc2VSYXRlID09IG51bGxcbiAgICApO1xuICB9XG5cbiAgLy8gTnVtQXRDYXJkIGdpcmnFn2kgeWFsbsSxemNhIGFyYSDFn2lya2V0IGJhY2FrbGFyxLFuZGFuLCB6aW5jaXJpbiBTT04gYmFjYcSfxLEgT0xNQVlBTkxBUiBpw6dpbiBhbmxhbWzEsWTEsXJcbiAgLy8gKG8gYmFjYWt0YSBheW7EsSDFn2lya2V0dGUgeWVuaSBiaXIgTcO8xZ90ZXJpIEZhdHVyYXPEsSBvbHXFn3V5b3IgdmUgTnVtQXRDYXJkJ8SxIGt1bGxhbsSxY8SxIGJlbGlybGVyKS5cbiAgaGFzSW50ZXJtZWRpYXRlTnVtQXRDYXJkTGVncygpOiBib29sZWFuIHtcbiAgICBjb25zdCBsZWdzID0gdGhpcy53b3JraW5nQ29weT8ubGVncyA/PyBbXTtcbiAgICByZXR1cm4gbGVncy5zb21lKGwgPT4gbC5sZWdCZWhhdmlvciA9PT0gTGVnQmVoYXZpb3IuSW50ZXJtZWRpYXRlQ2hhaW4gJiYgbC5zZXF1ZW5jZU5vIDwgbGVncy5sZW5ndGgpO1xuICB9XG5cbiAgLy8gU3BlYyDCpzQgLSBrdWxsYW7EsWPEsSDDp2FsxLHFn21hIGtvcHlhc8SxbmRha2kgYmFjYWtsYXLEsW4gaGVkZWYgxZ9pcmtldGluaS9kYXZyYW7EscWfxLFuxLEgKEFyYSDFnmlya2V0IHZleWFcbiAgLy8gQ29uc3RydWN0aW9uKSBkZcSfacWfdGlyZWJpbG1lbGk7IGJ1IGRlxJ9pxZ9pa2xpayB5YWxuxLF6Y2EgYnUgYWt0YXLEsW3EsW4gw6dhbMSxxZ9tYSBrb3B5YXPEsW7EsSBldGtpbGVyLCBhbmFcbiAgLy8gSGF6xLFyIFNlbmFyeW8gdGFuxLFtxLFuxLEgKHZhcnNhKSBoacOnIGRlxJ9pxZ90aXJtZXouIEtheW5hayDFn2lya2V0IGF5csSxY2EgZMO8emVubGVubWV6OiB6aW5jaXJkZWtpIGhlclxuICAvLyBiYWNhxJ/EsW4ga2F5bmHEn8SxLCBiaXIgw7ZuY2VraSBiYWNhxJ/EsW4gaGVkZWZpbmRlbiAodmV5YSBpbGsgYmFjYWtzYSBha3RhcsSxbcSxbiBrZW5kaSBrYXluYcSfxLFuZGFuKSBiYWNrZW5kXG4gIC8vIHRhcmFmxLFuZGFuIG90b21hdGlrIHTDvHJldGlsaXIgKGJrei4gRG9jdW1lbnRUcmFuc2ZlckFwcFNlcnZpY2UuQWRkTGVnQXN5bmMpLlxuICB1cGRhdGVMZWdUYXJnZXQobGVnOiBEb2N1bWVudFRyYW5zZmVyTGVnRHRvLCB0YXJnZXRDb21wYW55SWQ6IHN0cmluZykge1xuICAgIGlmICghdGhpcy53b3JraW5nQ29weSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxlZy50YXJnZXRDb21wYW55SWQgPSB0YXJnZXRDb21wYW55SWQ7XG4gICAgbGVnLnRhcmdldENvbXBhbnlOYW1lID0gdGhpcy5jb21wYW5pZXMuZmluZChjID0+IGMuaWQgPT09IHRhcmdldENvbXBhbnlJZCk/LmNvbXBhbnlOYW1lO1xuICAgIHRoaXMucGVyc2lzdExlZ0NoYW5nZXMoKTtcbiAgfVxuXG4gIHVwZGF0ZUxlZ0JlaGF2aW9yKGxlZzogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0bywgbGVnQmVoYXZpb3I6IExlZ0JlaGF2aW9yKSB7XG4gICAgaWYgKCF0aGlzLndvcmtpbmdDb3B5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGVnLmxlZ0JlaGF2aW9yID0gbGVnQmVoYXZpb3I7XG4gICAgdGhpcy5wZXJzaXN0TGVnQ2hhbmdlcygpO1xuICB9XG5cbiAgLy8gSGVkZWYvRGF2cmFuxLHFnyBkcm9wZG93bifEsSBkZcSfacWfdGnEn2luZGUgeWFsbsSxemNhIE8gYmFjYcSfxLEga2F5ZGVkaXAgc3VudWN1ZGFuIGTDtm5lbiB0YW0gd29ya2luZ0NvcHkneWlcbiAgLy8gb2xkdcSfdSBnaWJpIGVrcmFuYSB5YW5zxLF0xLFyc2FrLCBrdWxsYW7EsWPEsW7EsW4gQkHFnktBIGJpciBiYWNhxJ9hIGhlbsO8eiB5YXpkxLHEn8SxIGFtYSBoZW7DvHogc2Vua3Jvbml6ZVxuICAvLyBlZGlsbWVtacWfIE51bUF0Q2FyZC9Ew7Z2aXovS3VyIGRlxJ9lcmxlcmkgKGJ1bmxhciB5YWxuxLF6Y2EgXCLDh2FsxLHFn3TEsXJcIi9cIkJhxZ9sYXRcIiDDtm5jZXNpIHRvcGx1IGfDtm5kZXJpbGlyKVxuICAvLyBzdW51Y3VkYWtpIGVza2kgZGXEn2VybGUgZ2VyaSBnZWxlbiBvIGJhY2FrIG5lc25lc2kgdGFyYWbEsW5kYW4gc2Vzc2l6Y2UgZXppbGlyL2JvxZ9hbMSxciAtIGdlcsOnZWtcbiAgLy8gb3J0YW1kYSBkb8SfcnVsYW5kxLEuIEJ1IHnDvHpkZW4gZHJvcGRvd24gZGXEn2nFn2lrbGnEn2luZGUgZGUgVMOcTSBiYWNha2xhcmRha2kgbWV2Y3V0IGRlxJ9lcmxlclxuICAvLyAoc3luY1BlbmRpbmdMZWdDaGFuZ2VzIGlsZSwgc8SxcmFsxLEvY29uY3VycmVuY3ktc2FmZSkgYmlybGlrdGUgZ8O2bmRlcmlsaXIuXG4gIHByaXZhdGUgcGVyc2lzdExlZ0NoYW5nZXMoKSB7XG4gICAgaWYgKCF0aGlzLndvcmtpbmdDb3B5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5pc011dGF0aW5nTGVncyA9IHRydWU7XG4gICAgdGhpcy5zeW5jUGVuZGluZ0xlZ0NoYW5nZXModGhpcy53b3JraW5nQ29weS5sZWdzKVxuICAgICAgLnBpcGUoZmluYWxpemUoKCkgPT4gKHRoaXMuaXNNdXRhdGluZ0xlZ3MgPSBmYWxzZSkpKVxuICAgICAgLnN1YnNjcmliZShyZXN1bHRzID0+IHtcbiAgICAgICAgY29uc3QgbGFzdCA9IHJlc3VsdHM/LltyZXN1bHRzLmxlbmd0aCAtIDFdO1xuICAgICAgICBpZiAobGFzdCkge1xuICAgICAgICAgIHRoaXMud29ya2luZ0NvcHkgPSBsYXN0O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFppbmNpcmUgeWVuaSBiaXIgYmFjYWsgZWtsZXI6IGtheW5hxJ/EsSBvdG9tYXRpayBvbGFyYWsgc29uIGJhY2HEn8SxbiBoZWRlZmluZGVuIChpbGsgYmFjYWtzYSBha3RhcsSxbcSxblxuICAvLyBrZW5kaSBrYXluYWsgxZ9pcmtldGluZGVuKSB0w7xyZXRpbGlyLiBWYXJzYXnEsWxhbiBoZWRlZiwgaGVuw7x6IHppbmNpcmRlIG9sbWF5YW4gaWxrIMWfaXJrZXR0aXI7IGt1bGxhbsSxY8SxXG4gIC8vIGVrbGVkaWt0ZW4gc29ucmEgZHJvcGRvd24nbGFyZGFuIGhlZGVmaS9kYXZyYW7EscWfxLEgZGXEn2nFn3RpcmViaWxpci5cbiAgYWRkTGVnKCkge1xuICAgIGlmICghdGhpcy53b3JraW5nQ29weSB8fCB0aGlzLmNvbXBhbmllcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBZZW5pIGJhY2HEn8SxbiBrYXluYcSfxLEgYmFja2VuZCdkZSBvdG9tYXRpayBvbGFyYWsgc29uIGJhY2HEn8SxbiBoZWRlZmluZGVuIHTDvHJldGlsaXIgKGJrei5cbiAgICAvLyBEb2N1bWVudFRyYW5zZmVyQXBwU2VydmljZS5BZGRMZWdBc3luYykuIFZhcnNhecSxbGFuIEhFREVGIHNlw6dpbGlya2VuIGJ1IGtheW5ha2xhIEFZTkkgxZ9pcmtldCBhc2xhXG4gICAgLy8gw7ZuZXJpbG1lbWVsaWRpciAtIGFrc2kgaGFsZGUgYmlyIMWfaXJrZXRpbiBrZW5kaSBrZW5kaW5lIGZhdHVyYSBrZXN0acSfaSBhbmxhbXPEsXogYmlyIGJhY2FrIG9sdcWfdXIuXG4gICAgLy8gw5ZuY2VkZW4gxZ9pcmtldCBoYXZ1enUgdMO8a2VuZGnEn2luZGUgKHTDvG0gxZ9pcmtldGxlciB6YXRlbiBiaXIgYmFjYWt0YSBoZWRlZiBvbGFyYWsga3VsbGFuxLFsbcSxxZ9zYSlcbiAgICAvLyBmYWxsYmFjayBkb8SfcnVkYW4gY29tcGFuaWVzWzBdJ2EgZMO8xZ/DvHlvcmR1OyBidSB0ZXNhZMO8ZmVuIGtheW5ha2xhIGF5bsSxIMWfaXJrZXRlIGRlbmsgZ2VsaXAgc2VsZi1sb29wXG4gICAgLy8gKEtheW5haz1IZWRlZikgYmFjYWsgb2x1xZ90dXJhYmlsaXlvcmR1IChrdWxsYW7EsWPEsSBnZXJpIGJpbGRpcmltaXlsZSB0ZXNwaXQgZWRpbGRpKS5cbiAgICBjb25zdCBsYXN0TGVnID0gWy4uLnRoaXMud29ya2luZ0NvcHkubGVnc10uc29ydCgoYSwgYikgPT4gYS5zZXF1ZW5jZU5vIC0gYi5zZXF1ZW5jZU5vKS5zbGljZSgtMSlbMF07XG4gICAgY29uc3QgbmV3TGVnU291cmNlQ29tcGFueUlkID0gbGFzdExlZz8udGFyZ2V0Q29tcGFueUlkID8/IHRoaXMud29ya2luZ0NvcHkuc291cmNlQ29tcGFueUlkO1xuXG4gICAgY29uc3QgdXNlZENvbXBhbnlJZHMgPSBuZXcgU2V0KHRoaXMud29ya2luZ0NvcHkubGVncy5tYXAobCA9PiBsLnRhcmdldENvbXBhbnlJZCkpO1xuICAgIGNvbnN0IGRlZmF1bHRUYXJnZXQgPVxuICAgICAgdGhpcy5jb21wYW5pZXMuZmluZChjID0+ICF1c2VkQ29tcGFueUlkcy5oYXMoYy5pZCkgJiYgYy5pZCAhPT0gbmV3TGVnU291cmNlQ29tcGFueUlkKSA/P1xuICAgICAgdGhpcy5jb21wYW5pZXMuZmluZChjID0+IGMuaWQgIT09IG5ld0xlZ1NvdXJjZUNvbXBhbnlJZCkgPz9cbiAgICAgIHRoaXMuY29tcGFuaWVzWzBdO1xuXG4gICAgLy8gw5ZuY2UgbWV2Y3V0IGJhY2FrbGFyZGFraSBoZW7DvHogc2Vua3Jvbml6ZSBlZGlsbWVtacWfIE51bUF0Q2FyZC9Ew7Z2aXovS3VyIGRlxJ9lcmxlcmkga2F5ZGVkaWxpciAtXG4gICAgLy8gYWtzaSBoYWxkZSB5ZW5pIGJhY2FrIGVrbGVuZGnEn2luZGUgZMO2bmVuIHRhbSB3b3JraW5nQ29weSwga3VsbGFuxLFjxLFuxLFuIGF6IMO2bmNlIHlhemTEscSfxLEgYW1hIGhpw6dcbiAgICAvLyBzdW51Y3V5YSBnw7ZuZGVyaWxtZW1pxZ8gZGXEn2VybGVyaSBlc2tpL2JvxZ8gREIgZGXEn2VyaXlsZSBlemVyZGkgKHBlcnNpc3RMZWdDaGFuZ2VzIGlsZSBheW7EsSBzb3J1bikuXG4gICAgdGhpcy5pc011dGF0aW5nTGVncyA9IHRydWU7XG4gICAgdGhpcy5zeW5jUGVuZGluZ0xlZ0NoYW5nZXModGhpcy53b3JraW5nQ29weS5sZWdzKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PlxuICAgICAgICAgIHRoaXMuc2VydmljZS5hZGRMZWcodGhpcy53b3JraW5nQ29weSEuaWQsIHtcbiAgICAgICAgICAgIHRhcmdldENvbXBhbnlJZDogZGVmYXVsdFRhcmdldC5pZCxcbiAgICAgICAgICAgIGxlZ0JlaGF2aW9yOiBMZWdCZWhhdmlvci5JbnRlcm1lZGlhdGVDaGFpbixcbiAgICAgICAgICB9KVxuICAgICAgICApLFxuICAgICAgICBmaW5hbGl6ZSgoKSA9PiAodGhpcy5pc011dGF0aW5nTGVncyA9IGZhbHNlKSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUocmVzdWx0ID0+ICh0aGlzLndvcmtpbmdDb3B5ID0gcmVzdWx0KSk7XG4gIH1cblxuICAvLyBTcGVjIMKnNSAtIG11aGF0YXAgZcWfbGXFn3Rpcm1lc2kgYnVsdW5hbWF5YW4gYmFjYWt0YSBrdWxsYW7EsWPEsWRhbiBoZWRlZiBTQVAgxZ9pcmtldGluZGVraSBkb8SfcnVcbiAgLy8gTcO8xZ90ZXJpL1NhdMSxY8SxIENhcmRDb2RlIHNlw6dpbWkgaXN0ZW5lY2VrdGlyOyBidSwgTXVoYXRhcCBFxZ9sZcWfdGlybWVsZXJpIGVrcmFuxLFuYSB5w7ZubGVuZGlyaWxlcmVrXG4gIC8vIHlhcHTEsXLEsWxhYmlsaXIgKHNwZWMgdGFyYWbEsW5kYW4gYcOnxLFrw6dhIGl6aW4gdmVyaWxlbiBhcmF5w7x6IHNlw6dlbmVrbGVyaW5kZW4gYmlyaSkuIFwiQnVsdW51bGFuIMWeaXJrZXRcIlxuICAvLyBidXJhZGEgaGVkZWYgKE9QQ0gnbmluIG9sdcWfYWNhxJ/EsSkgxZ9pcmtldHRpciwgXCLEsGxpxZ9raWxpIMWeaXJrZXRcIiBpc2Uga2F5bmFrIMWfaXJrZXR0aXIgLSBia3ouXG4gIC8vIFJlc29sdmVWZW5kb3JDYXJkQ29kZUFzeW5jKGluQ29tcGFueUlkOiBoZWRlZiwgZm9yUmVsYXRlZENvbXBhbnlJZDoga2F5bmFrKS5cbiAgZ29Ub1BhcnRuZXJNYXBwaW5nKGxlZzogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0bykge1xuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2ZiZG9jdW1lbnRmbG93L3BhcnRuZXItbWFwcGluZ3MnXSwge1xuICAgICAgc3RhdGU6IHsgc291cmNlQ29tcGFueUlkOiBsZWcudGFyZ2V0Q29tcGFueUlkLCByZWxhdGVkQ29tcGFueUlkOiBsZWcuc291cmNlQ29tcGFueUlkIH0sXG4gICAgfSk7XG4gIH1cblxuICByZW1vdmVMZWcobGVnOiBEb2N1bWVudFRyYW5zZmVyTGVnRHRvKSB7XG4gICAgaWYgKCF0aGlzLndvcmtpbmdDb3B5IHx8IHRoaXMud29ya2luZ0NvcHkubGVncy5sZW5ndGggPD0gMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEF5bsSxIG5lZGVubGUgKGJrei4gYWRkTGVnKSBzaWxpbm1leWVuIGRpxJ9lciBiYWNha2xhcmRha2kgc2Vua3Jvbml6ZSBlZGlsbWVtacWfIGRlxJ9lcmxlciDDtm5jZSBrYXlkZWRpbGlyLlxuICAgIGNvbnN0IHJlbWFpbmluZ0xlZ3MgPSB0aGlzLndvcmtpbmdDb3B5LmxlZ3MuZmlsdGVyKGwgPT4gbC5pZCAhPT0gbGVnLmlkKTtcbiAgICB0aGlzLmlzTXV0YXRpbmdMZWdzID0gdHJ1ZTtcbiAgICB0aGlzLnN5bmNQZW5kaW5nTGVnQ2hhbmdlcyhyZW1haW5pbmdMZWdzKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLnNlcnZpY2UucmVtb3ZlTGVnKHRoaXMud29ya2luZ0NvcHkhLmlkLCBsZWcuaWQpKSxcbiAgICAgICAgZmluYWxpemUoKCkgPT4gKHRoaXMuaXNNdXRhdGluZ0xlZ3MgPSBmYWxzZSkpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKHJlc3VsdCA9PiAodGhpcy53b3JraW5nQ29weSA9IHJlc3VsdCkpO1xuICB9XG5cbiAgLy8gWWVuaSBiaXIgYWt0YXLEsW0gacOnaW4gw6dhbMSxxZ9tYSBrb3B5YXPEsW7EsSBpbGsga2V6IG9sdcWfdHVydXIuIFphdGVuIG9sdcWfdHVydWxtdcWfIGFtYSBoZW7DvHpcbiAgLy8gw6dhbMSxxZ90xLFyxLFsbWFtxLHFnyAodGFzbGFrKSBiaXIgYWt0YXLEsW1kYSBzZW5hcnlvIGRlxJ9pxZ90aXJtZWsgacOnaW4gYXBwbHlTY2VuYXJpbygpIGt1bGxhbsSxbMSxciAtXG4gIC8vIMO2cm4uIFwixLDFn2xlbSBHZcOnbWnFn2lcIm5kZW4gZ2VyaSBkw7Zuw7xsZW4gYmlyIHRhc2xhayBrYXnEsXR0YS5cbiAgZmV0Y2hTY2VuYXJpbygpIHtcbiAgICBpZiAoIXRoaXMubmV3U3RhdGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlzRmV0Y2hpbmdTY2VuYXJpbyA9IHRydWU7XG4gICAgdGhpcy5zZXJ2aWNlXG4gICAgICAuY3JlYXRlKHtcbiAgICAgICAgc291cmNlQ29tcGFueUlkOiB0aGlzLm5ld1N0YXRlLnNvdXJjZUNvbXBhbnlJZCxcbiAgICAgICAgc291cmNlT2ludkRvY0VudHJ5OiB0aGlzLm5ld1N0YXRlLmRvY0VudHJ5LFxuICAgICAgICBzY2VuYXJpb0lkOiB0aGlzLnNjZW5hcmlvSWQgfHwgdW5kZWZpbmVkLFxuICAgICAgICBzb3VyY2VEb2N1bWVudExpZmVjeWNsZTogdGhpcy5uZXdTdGF0ZS5zb3VyY2VEb2N1bWVudExpZmVjeWNsZSxcbiAgICAgICAgdGFyZ2V0RG9jdW1lbnRMaWZlY3ljbGU6IHRoaXMubmV3U3RhdGUudGFyZ2V0RG9jdW1lbnRMaWZlY3ljbGUsXG4gICAgICB9KVxuICAgICAgLnBpcGUoZmluYWxpemUoKCkgPT4gKHRoaXMuaXNGZXRjaGluZ1NjZW5hcmlvID0gZmFsc2UpKSlcbiAgICAgIC5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgICAgdGhpcy53b3JraW5nQ29weSA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5pc05ldyA9IGZhbHNlO1xuICAgICAgICAvLyBVUkwnaSBvbHXFn2FuIGtheWRhIGfDtnJlIGRlxJ9pxZ90aXIgLSBzYXlmYSB5ZW5pbGVuaXJzZSB2ZXlhIGdlcmkvaWxlcmkgZ2lkaWxpcnNlIGRvxJ9ydSBrYXnEsXQgecO8a2xlbnNpbi5cbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvZmJkb2N1bWVudGZsb3cvZG9jdW1lbnQtdHJhbnNmZXJzJywgcmVzdWx0LmlkXSwgeyByZXBsYWNlVXJsOiB0cnVlIH0pO1xuICAgICAgfSk7XG4gIH1cblxuICBhcHBseVNjZW5hcmlvKCkge1xuICAgIGlmICghdGhpcy53b3JraW5nQ29weSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuaXNGZXRjaGluZ1NjZW5hcmlvID0gdHJ1ZTtcbiAgICB0aGlzLnNlcnZpY2VcbiAgICAgIC5hcHBseVNjZW5hcmlvKHRoaXMud29ya2luZ0NvcHkuaWQsIHsgc2NlbmFyaW9JZDogdGhpcy5zY2VuYXJpb0lkIHx8IHVuZGVmaW5lZCB9KVxuICAgICAgLnBpcGUoZmluYWxpemUoKCkgPT4gKHRoaXMuaXNGZXRjaGluZ1NjZW5hcmlvID0gZmFsc2UpKSlcbiAgICAgIC5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgICAgdGhpcy53b3JraW5nQ29weSA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5zY2VuYXJpb0lkID0gcmVzdWx0LnNjZW5hcmlvSWQgPz8gJyc7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbG9hZFdvcmtpbmdDb3B5KGlkOiBzdHJpbmcpIHtcbiAgICB0aGlzLmlzTG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5zZXJ2aWNlXG4gICAgICAuZ2V0KGlkKVxuICAgICAgLnBpcGUoZmluYWxpemUoKCkgPT4gKHRoaXMuaXNMb2FkaW5nID0gZmFsc2UpKSlcbiAgICAgIC5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgICAgdGhpcy53b3JraW5nQ29weSA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5zY2VuYXJpb0lkID0gcmVzdWx0LnNjZW5hcmlvSWQgPz8gJyc7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRMZWdVcGRhdGVJbnB1dChsZWc6IERvY3VtZW50VHJhbnNmZXJMZWdEdG8pIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGFyZ2V0Q29tcGFueUlkOiBsZWcudGFyZ2V0Q29tcGFueUlkLFxuICAgICAgbGVnQmVoYXZpb3I6IGxlZy5sZWdCZWhhdmlvcixcbiAgICAgIG51bUF0Q2FyZDogbGVnLm51bUF0Q2FyZCxcbiAgICAgIGN1cnJlbmN5OiBsZWcuY3VycmVuY3ksXG4gICAgICBleGNoYW5nZVJhdGU6IGxlZy5leGNoYW5nZVJhdGUsXG4gICAgICBmcmVpZ2h0QW1vdW50OiBsZWcuZnJlaWdodEFtb3VudCxcbiAgICAgIHNlbGVjdGVkQ29uc3RydWN0aW9uRHJhZnREb2NUeXBlOiBsZWcuc2VsZWN0ZWRDb25zdHJ1Y3Rpb25EcmFmdERvY1R5cGUsXG4gICAgfTtcbiAgfVxuXG4gIC8vIE51bUF0Q2FyZC9Ew7Z2aXovS3VyIGFsYW5sYXLEsSBrdWxsYW7EsWPEsSB5YXphcmtlbi9hbGFuxLEgdGVyayBlZGVya2VuIGF5csSxIGJpciBcImtheWRldFwiIGlzdGXEn2lcbiAgLy8gZ8O2bmRlcm1peW9yIChidSwgYXJ0IGFyZGEgaMSxemzEsSBpc3Rla2xlcmluIENvbmN1cnJlbmN5U3RhbXAgeWFyxLHFnyBkdXJ1bXVuYSAtIEFicERiQ29uY3VycmVuY3lFeGNlcHRpb24sXG4gIC8vIFwidmVyaSBiYcWfa2EgYmlyIGt1bGxhbsSxY8SxIHRhcmFmxLFuZGFuIGRlxJ9pxZ90aXJpbG1pxZ9cIiAtIHlvbCBhw6d0xLHEn8SxIGdlcsOnZWsgb3J0YW1kYSBnw7Z6bGVtbGVuZGkpLiBCdW51blxuICAvLyB5ZXJpbmUgZWtyYW5kYWtpIGRlxJ9lcmxlciB5YWxuxLF6Y2EgXCLDh2FsxLHFn3TEsXJcIi9cIkJlbGdlIEFrxLHFn8SxbsSxIEJhxZ9sYXRcIiB0ZXRpa2xlbmRpxJ9pIGFuZGEsIG8gw6dhxJ9yxLFkYW5cbiAgLy8gaGVtZW4gw7ZuY2UgdGVrIHNlZmVyZGUgYmFja2VuZCdlIHNlbmtyb25pemUgZWRpbGlyLiBTcGVjIMKnMTAgLSBkw7Z2aXova3VyIGhlciBiYWNhayBpw6dpbiAoQ29uc3RydWN0aW9uXG4gIC8vIGRhaGlsLCBzb24gYmFjYWsgZGFoaWwpIGdlw6dlcmxpIG9sZHXEn3VuZGFuIE51bUF0Q2FyZCfEsW4gYWtzaW5lIGRhdnJhbsSxxZ8vc8SxcmEgYmF6bMSxIGZpbHRyZWxlbm1lei5cbiAgcHJpdmF0ZSBzeW5jUGVuZGluZ0xlZ0NoYW5nZXMobGVnczogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0b1tdKSB7XG4gICAgLy8gWmF0ZW4gQmHFn2FyxLFsxLEgKFN1Y2Nlc3MpIG9sbXXFnyBiaXIgYmFjYWsgYmFja2VuZCdkZSBhcnTEsWsgZMO8emVubGVuZW1leiAoRW5zdXJlTGVnSXNFZGl0YWJsZSxcbiAgICAvLyBGQkRvY3VtZW50RmxvdzowMTAwMTcgXCJMZWdBbHJlYWR5U3VjY2VlZGVkXCIgZsSxcmxhdMSxcikgLSBidSBmb25rc2l5b25hIMO2bmNlZGVuIFTDnE0gYmFjYWtsYXJcbiAgICAvLyAoemF0ZW4gYmHFn2FyxLFsxLEgb2xhbmxhciBkYWhpbCkgZ8O2bmRlcmlsaXlvcmR1LiBCdSwgw7Zybi4gYmlyIHppbmNpcmRlIDEtMi4gYmFjYWsgQmHFn2FyxLFsxLEsIDMuIGJhY2FrXG4gICAgLy8gSGF0YWzEsSBpa2VuIDMuIGJhY2HEn8SxIHRla3JhciBcIsOHYWzEscWfdMSxclwiYSBiYXNtYXnEsSBUQU1BTUVOIGlta2Fuc8SxeiBoYWxlIGdldGlyaXlvcmR1IC0gc2Vua3Jvbml6YXN5b25cbiAgICAvLyBhZMSxbcSxLCBoZW7DvHogMy4gYmFjYcSfYSBoacOnIHPEsXJhIGdlbG1lZGVuLCB6YXRlbiBiYcWfYXLEsWzEsSAxLiBiYWNha3RhIGJ1IGhhdGF5bGEgcGF0bMSxeW9yZHUgKGdlcsOnZWtcbiAgICAvLyBvcnRhbWRhIGfDtnpsZW1sZW5kaSkuIFlhbG7EsXpjYSBow6Jsw6IgZMO8emVubGVuZWJpbGlyIChTdWNjZXNzIG9sbWF5YW4pIGJhY2FrbGFyIHNlbmtyb25pemUgZWRpbGlyLlxuICAgIGNvbnN0IGVkaXRhYmxlTGVncyA9IGxlZ3MuZmlsdGVyKGwgPT4gbC5zdGF0dXMgIT09IERPQ1VNRU5UX1RSQU5TRkVSX0xFR19TVEFUVVNfU1VDQ0VTUyk7XG5cbiAgICBpZiAoIXRoaXMud29ya2luZ0NvcHkgfHwgZWRpdGFibGVMZWdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgIH1cblxuICAgIC8vIEJhY2FrbGFyIGF5bsSxIERvY3VtZW50VHJhbnNmZXIgKGFnZ3JlZ2F0ZSByb290KSBrYXlkxLFuxLEgcGF5bGHFn3TEscSfxLEgacOnaW4gZm9ya0pvaW4gaWxlIHBhcmFsZWxcbiAgICAvLyBnw7ZuZGVyaWxpcnNlIGhlciBpc3RlayBheW7EsSBDb25jdXJyZW5jeVN0YW1wJ2kgecO8a2xlcjsgaWxrIGtheWRlZGVuIGTEscWfxLFuZGFraWxlclxuICAgIC8vIEFicERiQ29uY3VycmVuY3lFeGNlcHRpb24gKFwidmVyaSBiYcWfa2EgYmlyIGt1bGxhbsSxY8SxL2lzdGVtY2kgdGFyYWbEsW5kYW4gZGXEn2nFn3RpcmlsbWnFn1wiKSBhbMSxciAtXG4gICAgLy8gZ2Vyw6dlayBvcnRhbWRhIGRvxJ9ydWxhbmTEsS4gY29uY2F0TWFwIGlsZSBzxLFyYXlsYSBnw7ZuZGVyaWxpciwgaGVyIGlzdGVrIGJpciDDtm5jZWtpbmluXG4gICAgLy8ga2F5ZGV0dGnEn2kgZ8O8bmNlbCBzdGFtcCDDvHplcmluZGVuIGRldmFtIGVkZXIuXG4gICAgcmV0dXJuIGZyb20oZWRpdGFibGVMZWdzKS5waXBlKFxuICAgICAgY29uY2F0TWFwKGxlZyA9PiB0aGlzLnNlcnZpY2UudXBkYXRlTGVnKHRoaXMud29ya2luZ0NvcHkhLmlkLCBsZWcuaWQsIHRoaXMuYnVpbGRMZWdVcGRhdGVJbnB1dChsZWcpKSksXG4gICAgICB0b0FycmF5KClcbiAgICApO1xuICB9XG5cbiAgYmFja1RvTGlzdCgpIHtcbiAgICBjb25zdCBzb3VyY2VDb21wYW55SWQgPSB0aGlzLm5ld1N0YXRlPy5zb3VyY2VDb21wYW55SWQgPz8gdGhpcy53b3JraW5nQ29weT8uc291cmNlQ29tcGFueUlkO1xuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2ZiZG9jdW1lbnRmbG93L2RvY3VtZW50LXRyYW5zZmVycyddLCB7XG4gICAgICBzdGF0ZTogc291cmNlQ29tcGFueUlkID8geyBzb3VyY2VDb21wYW55SWQgfSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXJ0RmxvdygpIHtcbiAgICBpZiAoIXRoaXMud29ya2luZ0NvcHkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTcGVjIMKnOSAtIFVfT3JhbiB0YW7EsW1zxLF6a2VuIGFrxLHFnyBibG9rbGFubWF6OyBhbmNhayBrdWxsYW7EsWPEsW7EsW4gYnVudSBiaWxlcmVrIG9uYXlsYW1hc8SxIGdlcmVraXIuXG4gICAgaWYgKHRoaXMuaGFzTWlzc2luZ0luY3JlYXNlUmF0ZSgpKSB7XG4gICAgICB0aGlzLmNvbmZpcm1hdGlvblxuICAgICAgICAud2FybihcbiAgICAgICAgICAnQnUgxZ9pcmtldHRlIGJ1IHByb2plIGnDp2luIGFydMSxcsSxbSBvcmFuxLEgdGFuxLFtbMSxIGRlxJ9pbGRpci4gQXJ0xLFyxLFtIHV5Z3VsYW5tYWRhbiBkZXZhbSBldG1layBpc3RpeW9yIG11c3VudXo/JyxcbiAgICAgICAgICAnRkJEb2N1bWVudEZsb3c6OkFyZVlvdVN1cmUnXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZShzdGF0dXMgPT4ge1xuICAgICAgICAgIGlmIChzdGF0dXMgPT09IENvbmZpcm1hdGlvbi5TdGF0dXMuY29uZmlybSkge1xuICAgICAgICAgICAgdGhpcy5leGVjdXRlU3RhcnRGbG93KCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmV4ZWN1dGVTdGFydEZsb3coKTtcbiAgfVxuXG4gIHByaXZhdGUgZXhlY3V0ZVN0YXJ0RmxvdygpIHtcbiAgICBpZiAoIXRoaXMud29ya2luZ0NvcHkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlzU3RhcnRpbmcgPSB0cnVlO1xuICAgIHRoaXMuc3luY1BlbmRpbmdMZWdDaGFuZ2VzKHRoaXMud29ya2luZ0NvcHkubGVncylcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5zZXJ2aWNlLmV4ZWN1dGVBbGwodGhpcy53b3JraW5nQ29weSEuaWQpKSxcbiAgICAgICAgZmluYWxpemUoKCkgPT4gKHRoaXMuaXNTdGFydGluZyA9IGZhbHNlKSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiByZXN1bHQgPT4gKHRoaXMud29ya2luZ0NvcHkgPSByZXN1bHQpLFxuICAgICAgICAvLyBBQlAgemF0ZW4gYmHFn2FyxLFzxLF6IEhUVFAgw6dhxJ9yxLFsYXLEsW5kYSBnZW5lbCBiaXIgaGF0YSBkaXlhbG/En3UgZ8O2c3RlcmlyLlxuICAgICAgICBlcnJvcjogKCkgPT4ge1xuICAgICAgICAgIHRoaXMuaXNTdGFydGluZyA9IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICAvLyBZYWxuxLF6Y2EgW2xlZ10gKMOnYWzEscWfdMSxcsSxbGFuIGJhY2FrKSBzZW5rcm9uaXplIGVkaWxpcnNlLCBrdWxsYW7EsWPEsW7EsW4gQkHFnktBIGJpciBiYWNhxJ9hIHlhemTEscSfxLEgYW1hXG4gIC8vIGhlbsO8eiBnw7ZuZGVyaWxtZW1pxZ8gTnVtQXRDYXJkL0TDtnZpei9LdXIgZGXEn2VybGVyaSBoacOnIGtheWRlZGlsbWVkZW4ga2FsxLFyIC0gYXJkxLFuZGFuIMOnYcSfcsSxbGFuXG4gIC8vIGxvYWRXb3JraW5nQ29weSgpIHN1bnVjdWRha2kgZXNraSAoYm/FnykgZGXEn2VybGUgbyBiYWNhxJ/EsSBlemVyLCBrdWxsYW7EsWPEsSB5YXpkxLHEn8SxIGRlxJ9lcmkga2F5YmVkZXJcbiAgLy8gKGdlcsOnZWsgb3J0YW1kYSBkb8SfcnVsYW5kxLEsIGV4ZWN1dGVTdGFydEZsb3cnZGFraSBnaWJpIFTDnE0gYmFjYWtsYXIgc2Vua3Jvbml6ZSBlZGlsbWVsaSkuXG4gIGV4ZWN1dGVMZWcobGVnOiBEb2N1bWVudFRyYW5zZmVyTGVnRHRvKSB7XG4gICAgaWYgKCF0aGlzLndvcmtpbmdDb3B5IHx8ICF0aGlzLmNhbkV4ZWN1dGVMZWcobGVnKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuaXNFeGVjdXRpbmcgPSB0cnVlO1xuICAgIHRoaXMuc3luY1BlbmRpbmdMZWdDaGFuZ2VzKHRoaXMud29ya2luZ0NvcHkubGVncylcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5zZXJ2aWNlLmV4ZWN1dGVMZWcodGhpcy53b3JraW5nQ29weSEuaWQsIGxlZy5pZCkpLFxuICAgICAgICBmaW5hbGl6ZSgoKSA9PiAodGhpcy5pc0V4ZWN1dGluZyA9IGZhbHNlKSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5sb2FkV29ya2luZ0NvcHkodGhpcy53b3JraW5nQ29weSEuaWQpKTtcbiAgfVxuXG4gIC8vIFwiWmluY2lyaSDEsHB0YWwgRXRcIiB5YWxuxLF6Y2EgZmlpbGVuIGlwdGFsIGVkaWxlY2VrIGJpciDFn2V5IHZhcmtlbiAoRGV2YW0gRWRpeW9yL0hhdGFsxLEpIGFubGFtbMSxZMSxcjtcbiAgLy8gemF0ZW4gxLBwdGFsIEVkaWxkaSB2ZXlhIFRhbWFtbGFuZMSxIGR1cnVtdW5kYWtpIGJpciBha3RhcsSxbWRhIHRla3JhciBnw7ZzdGVyaWxtZXNpIGt1bGxhbsSxY8SxecSxXG4gIC8vIHlhbsSxbHTEsXIgKHNwZWMgwqcxMi0xMyAtIGlwdGFsIGVkaWxtacWfIGJpciB6aW5jaXIgdGVrcmFyIGnFn2xlbWUgYWzEsW5tYXosIHllbmlkZW4gb2x1xZ90dXJtYSBzw7xyZWNpbmVcbiAgLy8ga2F5bmFrIGZhdHVyYWRhbiB5ZW5pIGJpciBha3RhcsSxbWxhIGdpcmlsaXIpLlxuICBjYW5DYW5jZWxDaGFpbigpOiBib29sZWFuIHtcbiAgICBjb25zdCBzdGF0dXMgPSB0aGlzLndvcmtpbmdDb3B5Py5zdGF0dXM7XG4gICAgcmV0dXJuIHN0YXR1cyA9PT0gMSB8fCBzdGF0dXMgPT09IDM7IC8vIDE9RGV2YW0gRWRpeW9yLCAzPUhhdGFsxLFcbiAgfVxuXG4gIGNhbmNlbENoYWluKCkge1xuICAgIGlmICghdGhpcy53b3JraW5nQ29weSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY29uZmlybWF0aW9uLndhcm4oJ0ZCRG9jdW1lbnRGbG93OjpEZWxldGVDb25maXJtYXRpb25NZXNzYWdlJywgJ0ZCRG9jdW1lbnRGbG93OjpBcmVZb3VTdXJlJykuc3Vic2NyaWJlKHN0YXR1cyA9PiB7XG4gICAgICBpZiAoc3RhdHVzID09PSBDb25maXJtYXRpb24uU3RhdHVzLmNvbmZpcm0gJiYgdGhpcy53b3JraW5nQ29weSkge1xuICAgICAgICAvLyDEsHB0YWxkZW4gc29ucmEgYnUgc2F5ZmFkYSBrYWxtYWsgeWVyaW5lIGxpc3RleWUgZMO2bsO8bMO8ciAtIGJhY2tUb0xpc3QoKSB6YXRlbiBzZcOnaWxpIGtheW5ha1xuICAgICAgICAvLyDFn2lya2V0aSByb3V0ZXIgc3RhdGUgaWxlIHRhxZ/EsXnEsXAgbGlzdGUgZWtyYW7EsW5kYSBheW7EsSDFn2lya2V0aW4gc2XDp2lsaSBrYWxtYXPEsW7EsSBzYcSfbMSxeW9yLlxuICAgICAgICB0aGlzLnNlcnZpY2UuY2FuY2VsQ2hhaW4odGhpcy53b3JraW5nQ29weS5pbnRlcmNvbXBhbnlJZCkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICB0aGlzLmJhY2tUb0xpc3QoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBzdGF0dXNMYWJlbChzdGF0dXM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIFsnxLDFn2xlbSBCZWtsaXlvcicsICdEZXZhbSBFZGl5b3InLCAnVGFtYW1sYW5kxLEnLCAnSGF0YWzEsScsICfEsHB0YWwgRWRpbGRpJ11bc3RhdHVzXSA/PyBTdHJpbmcoc3RhdHVzKTtcbiAgfVxuXG4gIC8vIFNwZWMgwqcxNCAoMTguMDkuMjAyNiBrYXJhcsSxKSAtIHPDvHJlw6cgcGFyYW1ldHJpazsgS2F5bmFrIHZlIEhlZGVmIEJlbGdlIER1cnVtdSBpw6dpbiBBWU5JIGV0aWtldFxuICAvLyBrdWxsYW7EsWzEsXIgKGt1bGxhbsSxY8SxIGlzdGXEn2l5bGUgbmV0bGXFn3RpcmlsZGkpLlxuICBzb3VyY2VEb2N1bWVudExpZmVjeWNsZUxhYmVsKGxpZmVjeWNsZT86IFNhcERvY3VtZW50TGlmZWN5Y2xlKTogc3RyaW5nIHtcbiAgICBpZiAobGlmZWN5Y2xlID09IG51bGwpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIGxpZmVjeWNsZSA9PT0gU2FwRG9jdW1lbnRMaWZlY3ljbGUuRHJhZnQgPyAnVGFzbGFrIE3DvMWfdGVyaSBGYXR1cmFzxLEnIDogJ0thecSxdGzEsSBNw7zFn3RlcmkgRmF0dXJhc8SxJztcbiAgfVxuXG4gIGxlZ1N0YXR1c0xhYmVsKHN0YXR1czogbnVtYmVyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gWydCZWtsaXlvcicsICdCYcWfYXLEsWzEsScsICdIYXRhbMSxJywgJ0F0bGFuZMSxJ11bc3RhdHVzXSA/PyBTdHJpbmcoc3RhdHVzKTtcbiAgfVxuXG4gIC8vIEJpciBiYWNha3RhICjDtnplbGxpa2xlIENvbnN0cnVjdGlvbjogT1BPUuKGkk9QRE7ihpJPUENILCB2ZXlhIEFyYSDFnmlya2V0J3RlIGRldmFtIE9JTlYgb2x1xZ90dcSfdW5kYSlcbiAgLy8gQsSwUkRFTiBGQVpMQSBTQVAgYmVsZ2VzaSBvbHXFn2FiaWxpcjsgw7ZuY2VkZW4geWFsbsSxemNhIFwic29uXCIgYmVsZ2UgKGxlZy5jcmVhdGVkRG9jVHlwZS9jcmVhdGVkRG9jRW50cnkpXG4gIC8vIGfDtnN0ZXJpbGl5b3JkdSwgZGnEn2VybGVyaSAoT1BPUi9PUEROLCBkZXZhbSBPSU5WKSBEVE8nZGEgdmFyZMSxIGFtYSBla3JhbmRhIGhpw6cgZ8O2csO8bm3DvHlvcmR1LlxuICAvLyBTb251w6cgYmVsZ2UgZXRpa2V0bGVyaSAoc3BlYyDCpzE1IC0gVGVrbmlrIFNBUCBCMSBBbGFubGFyxLEgdGFibG9zdW5kYWtpIG5lc25lIGvEsXNhbHRtYWxhcsSxeWxhIGJpcmViaXIpOlxuICAvLyBPUE9SL09QRE4vT1BDSC9PSU5WLiDDlm5jZWRlbiBidXJhZGEgbGVnLmNyZWF0ZWREb2NUeXBlIChiYWNrZW5kJ2RlIGhlciB6YW1hbiBoYW0gU0FQIFNlcnZpY2UgTGF5ZXJcbiAgLy8gZW50aXR5IHNldCBhZMSxIFwiUHVyY2hhc2VJbnZvaWNlc1wiIG9sYXJhayBzYWJpdCkgZG/En3J1ZGFuIGfDtnN0ZXJpbGl5b3JkdSAtIE9QT1IvT1BETiBnaWJpIGvEsXNhIFNBUFxuICAvLyBrb2RsYXLEsXlsYSBheW7EsSBzYXTEsXJkYSBrYXLEscWfxLFrIGfDtnLDvG7DvHAgYW5sYW0ga2FybWHFn2FzxLFuYSB5b2wgYcOnxLF5b3JkdSAoa3VsbGFuxLFjxLEgZ2VyaSBiaWxkaXJpbWl5bGVcbiAgLy8gdGVzcGl0IGVkaWxkaSkuIEFydMSxayB0w7xtIGJlbGdlIHRpcGxlcmkgYXluxLEga8Sxc2FsdG1hIHNldGl5bGUsIHR1dGFybMSxIMWfZWtpbGRlIGfDtnN0ZXJpbGl5b3IuXG4gIC8vIEVrcmFuZGEgZ8O2c3RlcmlsZWNlayBiZWxnZSBudW1hcmFzxLEgaGVyIHphbWFuIERvY051bSDDvHplcmluZGVuIHnDvHLDvHIgKGt1bGxhbsSxY8SxIGdlcmkgYmlsZGlyaW1peWxlXG4gIC8vIG5ldGxlxZ90aXJpbGRpKSAtIERvY0VudHJ5IChTQVAnxLFuIGRhaGlsaSBhbmFodGFyxLEpIHlhbG7EsXpjYSBmYWxsYmFjayd0aXIsIERvY051bSBiaXIgc2ViZXBsZVxuICAvLyB5YWthbGFuYW1hZMSxeXNhICjDtnIuIMOnb2sgZXNraSBiaXIga2F5xLF0KSBiZWxnZSB0YW1hbWVuIGtheWJvbG11xZ8gZ8O2csO8bm1lc2luIGRpeWUuXG4gIGNyZWF0ZWREb2N1bWVudHNTdW1tYXJ5KGxlZzogRG9jdW1lbnRUcmFuc2ZlckxlZ0R0byk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG4gICAgaWYgKGxlZy5jcmVhdGVkUHVyY2hhc2VPcmRlckRvY0VudHJ5KSB7XG4gICAgICBwYXJ0cy5wdXNoKGBPUE9SICR7bGVnLmNyZWF0ZWRQdXJjaGFzZU9yZGVyRG9jTnVtID8/IGxlZy5jcmVhdGVkUHVyY2hhc2VPcmRlckRvY0VudHJ5fWApO1xuICAgIH1cbiAgICBpZiAobGVnLmNyZWF0ZWRHb29kc1JlY2VpcHREb2NFbnRyeSkge1xuICAgICAgcGFydHMucHVzaChgT1BETiAke2xlZy5jcmVhdGVkR29vZHNSZWNlaXB0RG9jTnVtID8/IGxlZy5jcmVhdGVkR29vZHNSZWNlaXB0RG9jRW50cnl9YCk7XG4gICAgfVxuICAgIGlmIChsZWcuY3JlYXRlZERvY0VudHJ5KSB7XG4gICAgICBwYXJ0cy5wdXNoKGBPUENIICR7bGVnLmNyZWF0ZWREb2NOdW0gPz8gbGVnLmNyZWF0ZWREb2NFbnRyeX1gKTtcbiAgICB9XG4gICAgaWYgKGxlZy5jcmVhdGVkSW50ZXJuYWxPaW52RG9jRW50cnkpIHtcbiAgICAgIHBhcnRzLnB1c2goYE9JTlYgJHtsZWcuY3JlYXRlZEludGVybmFsT2ludkRvY051bSA/PyBsZWcuY3JlYXRlZEludGVybmFsT2ludkRvY0VudHJ5fWApO1xuICAgIH1cbiAgICByZXR1cm4gcGFydHMuam9pbignIOKGkiAnKTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImNhcmRcIj5cbiAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZGVyIHB5LTNcIj5cbiAgICA8ZGl2IGNsYXNzPVwicm93IGFsaWduLWl0ZW1zLWNlbnRlclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbFwiPlxuICAgICAgICA8aDUgY2xhc3M9XCJjYXJkLXRpdGxlIG1iLTBcIj5CZWxnZSBBa8SxxZ/EsSAvIEludGVyY29tcGFueSBBa3RhcsSxbcSxPC9oNT5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC1hdXRvXCI+XG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXNlY29uZGFyeVwiIChjbGljayk9XCJiYWNrVG9MaXN0KClcIj5cbiAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLWFycm93LWxlZnQgbWUtMVwiPjwvaT5MaXN0ZXllIETDtm5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJjYXJkLWJvZHkgcHQtM1wiPlxuICAgIDxkaXYgKm5nSWY9XCJpc0xvYWRpbmdcIiBjbGFzcz1cInRleHQtY2VudGVyIHB5LTVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzcGlubmVyLWJvcmRlciB0ZXh0LXByaW1hcnlcIiByb2xlPVwic3RhdHVzXCI+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwibXQtMiB0ZXh0LW11dGVkXCI+WcO8a2xlbml5b3IuLi48L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNMb2FkaW5nXCI+XG4gICAgICA8IS0tIEJ1IHNhdMSxciBoZW0gXCJ5ZW5pXCIgKGhlbsO8eiBrYXnEsXQgb2x1xZ9tYW3EscWfKSBoZW0gZGUga2F5xLF0IG9sdcWfdHVrdGFuIHNvbnJha2kgdGFzbGFrIGR1cnVtdW5kYVxuICAgICAgICAgICBBWU5JIGFsYW4gc2V0aW5pIGfDtnN0ZXJpciAtIGthecSxdCBvbHXFn3VuY2EgZWtyYW7EsW4gYWxhbiBzZXRpIGRlxJ9pxZ9pcCBrdWxsYW7EsWPEsWRhIFwiYmHFn2thIGJpclxuICAgICAgICAgICBrYXnEsXQgbcSxIGJ1XCIgaXpsZW5pbWkgdmVybWVzaW4gZGl5ZS4gRGXEn2VybGVyIMO2bmNlIG5ld1N0YXRlJ3RlbiAoaXN0ZW1jaWRlIHR1dHVsYW4gw7ZuaXpsZW1lKSxcbiAgICAgICAgICAgbyB5b2tzYSBvbHXFn2FuIGtheWTEsW4gaWxrIGJhY2HEn8SxbmRhbiAod29ya2luZ0NvcHkubGVnc1swXSkgb2t1bnVyIC0gaWxrIGJhY2FrIGhlciB6YW1hblxuICAgICAgICAgICBuZXdTdGF0ZSdpbiB0ZW1zaWwgZXR0acSfaSBcImlsayBoZWRlZlwiIGFkxLFtxLF5bGEgYXluxLEgYmVsZ2VkaXIuIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInJvdyBnLTMgbWItM1wiICpuZ0lmPVwibmV3U3RhdGUgfHwgd29ya2luZ0NvcHlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0zXCI+XG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPktheW5hayDFnmlya2V0PC9sYWJlbD5cbiAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFt2YWx1ZV09XCJjb21wYW55TmFtZSgpXCIgZGlzYWJsZWQgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMlwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5CZWxnZSBObzwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBbdmFsdWVdPVwibmV3U3RhdGU/LmRvY051bSA/PyB3b3JraW5nQ29weT8uc291cmNlT2ludkRvY051bVwiIGRpc2FibGVkIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTJcIj5cbiAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+TnVtQXRDYXJkPC9sYWJlbD5cbiAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFt2YWx1ZV09XCJuZXdTdGF0ZT8ubnVtQXRDYXJkID8/IHdvcmtpbmdDb3B5Py5zb3VyY2VPaW52TnVtQXRDYXJkXCIgZGlzYWJsZWQgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMVwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5Qcm9qZTwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBbdmFsdWVdPVwibmV3U3RhdGU/LnByb2plY3RDb2RlID8/IHdvcmtpbmdDb3B5Py5wcm9qZWN0Q29kZVwiIGRpc2FibGVkIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTJcIj5cbiAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+xLBsayBIZWRlZjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBbdmFsdWVdPVwibmV3U3RhdGU/LnRhcmdldENvbXBhbnlOYW1lID8/IHdvcmtpbmdDb3B5Py5sZWdzPy5bMF0/LnRhcmdldENvbXBhbnlOYW1lXCIgZGlzYWJsZWQgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMlwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5Ew7Z2aXo8L2xhYmVsPlxuICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgW3ZhbHVlXT1cIm5ld1N0YXRlPy5jdXJyZW5jeSA/PyB3b3JraW5nQ29weT8ubGVncz8uWzBdPy5jdXJyZW5jeVwiIGRpc2FibGVkIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gQmVsZ2UgRHVydW11IGhlciB6YW1hbiAoeWVuaSBrYXnEsXR0YSBkYSkgZ8O2csO8bsO8cjsgSW50ZXJjb21wYW55IElkL0FrdGFyxLFtIER1cnVtdS9TZW5hcnlvIHlhbG7EsXpjYVxuICAgICAgICAgICBrYXnEsXQgb2x1xZ90dWt0YW4gc29ucmEgdmFyZMSxciAtIGt1bGxhbsSxY8SxIGlzdGXEn2l5bGUgaGVwc2kgYXluxLEgc2F0xLFyZGEsIEJlbGdlIER1cnVtdSdudW4geWFuxLFuYVxuICAgICAgICAgICB0b3BsYW5kxLEgKMO2bmNlZGVuIEludGVyY29tcGFueSBJZC9Ba3RhcsSxbSBEdXJ1bXUgYXlyxLEgYmlyIHNhdMSxcmRheWTEsSkuIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInJvdyBnLTMgbWItM1wiICpuZ0lmPVwibmV3U3RhdGUgfHwgd29ya2luZ0NvcHlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0yXCI+XG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPktheW5hayBCZWxnZSBEdXJ1bXU8L2xhYmVsPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgW3ZhbHVlXT1cInNvdXJjZURvY3VtZW50TGlmZWN5Y2xlTGFiZWwobmV3U3RhdGU/LnNvdXJjZURvY3VtZW50TGlmZWN5Y2xlID8/IHdvcmtpbmdDb3B5Py5zb3VyY2VEb2N1bWVudExpZmVjeWNsZSlcIlxuICAgICAgICAgICAgZGlzYWJsZWRcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0yXCI+XG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkhlZGVmIEJlbGdlIER1cnVtdTwvbGFiZWw+XG4gICAgICAgICAgPCEtLSBBa3RhcsSxbSBoZW7DvHogb2x1xZ90dXJ1bG1hZMSxeXNhIChpc05ldykgYnVyYWRhIHNlw6dpbGViaWxpciAtIGtheW5ha3RhbiBiYcSfxLFtc8SxeiBiaXIga2FyYXJkxLFyXG4gICAgICAgICAgICAgICAoa3VsbGFuxLFjxLEgZ2VyaSBiaWxkaXJpbWl5bGUgbmV0bGXFn3RpcmlsZGk6IGtheW5hxJ/EsW4gbW9kdSBzYWJpdCwgaGVkZWZpbiBtb2R1IGJ1cmFkYSBzZcOnaWxpcikuXG4gICAgICAgICAgICAgICBPbHXFn3R1a3RhbiBzb25yYSBiYWNrZW5kJ2RlIHNhYml0bGVuZGnEn2kgacOnaW4gKHdvcmtpbmdDb3B5KSBzYWx0LW9rdW51ciBnw7ZzdGVyaWxpci4gLS0+XG4gICAgICAgICAgPHNlbGVjdCAqbmdJZj1cImlzTmV3ICYmIG5ld1N0YXRlXCIgY2xhc3M9XCJmb3JtLXNlbGVjdFwiIFsobmdNb2RlbCldPVwibmV3U3RhdGUudGFyZ2V0RG9jdW1lbnRMaWZlY3ljbGVcIj5cbiAgICAgICAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IG8gb2YgZG9jdW1lbnRMaWZlY3ljbGVPcHRpb25zXCIgW25nVmFsdWVdPVwiby52YWx1ZVwiPnt7IG8ubGFiZWwgfX08L29wdGlvbj5cbiAgICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICpuZ0lmPVwiIWlzTmV3IHx8ICFuZXdTdGF0ZVwiXG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBbdmFsdWVdPVwic291cmNlRG9jdW1lbnRMaWZlY3ljbGVMYWJlbChuZXdTdGF0ZT8udGFyZ2V0RG9jdW1lbnRMaWZlY3ljbGUgPz8gd29ya2luZ0NvcHk/LnRhcmdldERvY3VtZW50TGlmZWN5Y2xlKVwiXG4gICAgICAgICAgICBkaXNhYmxlZFxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTNcIiAqbmdJZj1cIndvcmtpbmdDb3B5XCI+XG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkludGVyY29tcGFueSBJZDwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIiBbdmFsdWVdPVwid29ya2luZ0NvcHkuaW50ZXJjb21wYW55SWRcIiBkaXNhYmxlZCAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0yXCIgKm5nSWY9XCJ3b3JraW5nQ29weVwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5Ba3RhcsSxbSBEdXJ1bXU8L2xhYmVsPlxuICAgICAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgW3ZhbHVlXT1cInN0YXR1c0xhYmVsKHdvcmtpbmdDb3B5LnN0YXR1cylcIiBkaXNhYmxlZCAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPCEtLSBTZW5hcnlvLCBha3RhcsSxbSBoZW7DvHogw6dhbMSxxZ90xLFyxLFsbWFtxLHFn2tlbiAoaXNEcmFmdCgpKSBhbHTEsW5kYWtpIFwiSGF6xLFyIFNlbmFyeW9cIiBkcm9wZG93bifEsW5kYVxuICAgICAgICAgICAgIHphdGVuIGTDvHplbmxlbmViaWxpci9nw7Zyw7xuw7xyIGR1cnVtZGEgLSBheW7EsSBiaWxnaXlpIGJ1cmFkYSBzYWx0LW9rdW51ciB0ZWtyYXIgZ8O2c3Rlcm1la1xuICAgICAgICAgICAgIChrdWxsYW7EsWPEsSBnZXJpIGJpbGRpcmltaXlsZSB0ZXNwaXQgZWRpbGRpKSBrYWZhIGthcsSxxZ90xLFyxLF5b3JkdS4gWWFsbsSxemNhIGFrdGFyxLFtIGFydMSxa1xuICAgICAgICAgICAgIGTDvHplbmxlbmVtZXogaGFsZSBnZWxkacSfaW5kZSAoZHJvcGRvd24ga2F5Ym9sZHXEn3VuZGEpIGJ1cmFkYSBnw7ZzdGVyaWxpci4gLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtM1wiICpuZ0lmPVwid29ya2luZ0NvcHkgJiYgIWlzRHJhZnQoKVwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5TZW5hcnlvPC9sYWJlbD5cbiAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFt2YWx1ZV09XCJzY2VuYXJpb05hbWUoKVwiIGRpc2FibGVkIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gVGFzbGFrOiBoYXrEsXIgc2VuYXJ5byBzZcOnaW1pLCBoZW7DvHogw6dhbMSxxZ90xLFyxLFsbWFkxLEuIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzRHJhZnQoKVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicm93IGctMyBhbGlnbi1pdGVtcy1lbmQgbWItM1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtNFwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkhhesSxciBTZW5hcnlvPC9sYWJlbD5cbiAgICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdFwiIFsobmdNb2RlbCldPVwic2NlbmFyaW9JZFwiPlxuICAgICAgICAgICAgICA8b3B0aW9uIFtuZ1ZhbHVlXT1cIicnXCI+U2VuYXJ5b3N1eiAoeWFsbsSxemNhIGlsayBoZWRlZiBiYWNhxJ/EsSk8L29wdGlvbj5cbiAgICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgcyBvZiBhdmFpbGFibGVTY2VuYXJpb3MoKVwiIFtuZ1ZhbHVlXT1cInMuaWRcIj57eyBzLm5hbWUgfX08L29wdGlvbj5cbiAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMlwiPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImlzTmV3ID8gZmV0Y2hTY2VuYXJpbygpIDogYXBwbHlTY2VuYXJpbygpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImlzRmV0Y2hpbmdTY2VuYXJpb1wiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiaXNGZXRjaGluZ1NjZW5hcmlvXCIgY2xhc3M9XCJzcGlubmVyLWJvcmRlciBzcGlubmVyLWJvcmRlci1zbSBtZS0xXCI+PC9zcGFuPlxuICAgICAgICAgICAgICB7eyBpc05ldyA/ICdTZW5hcnlveXUgR2V0aXInIDogJ1NlbmFyeW95dSBVeWd1bGEnIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBOdW1BdENhcmQgYWxhbmxhcsSxIGFydMSxayBpc0RyYWZ0KCknYSBiYcSfbMSxIERFxJ7EsEw6IHRhc2xha3RhIGTDvHplbmxlbmViaWxpciwgw6dhbMSxxZ90xLFyxLFsZMSxa3RhblxuICAgICAgICAgICBzb25yYSAoaXNEcmFmdCgpIGZhbHNlIG9sc2EgZGEpIHNhbHQtb2t1bnVyIG9sYXJhayBla3JhbmRhIGthbMSxciAtIFwiSGF6xLFyIFNlbmFyeW9cIiBibG/En3V5bGFcbiAgICAgICAgICAgYmlybGlrdGUgdGFtYW1lbiBrYXlib2xtYXPEsW4gZGl5ZS4gLS0+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwid29ya2luZ0NvcHlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBnLTMgYWxpZ24taXRlbXMtZW5kIG1iLTNcIiAqbmdJZj1cImhhc0ludGVybWVkaWF0ZU51bUF0Q2FyZExlZ3MoKVwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtM1wiICpuZ0Zvcj1cImxldCBsZWcgb2Ygd29ya2luZ0NvcHkubGVnc1wiPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImxlZy5sZWdCZWhhdmlvciA9PT0gMCAmJiBsZWcuc2VxdWVuY2VObyA8IHdvcmtpbmdDb3B5LmxlZ3MubGVuZ3RoXCI+XG4gICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj57eyBsZWcuc2VxdWVuY2VObyB9fS4gQmFjYWsgLSB7eyBsZWcudGFyZ2V0Q29tcGFueU5hbWUgfX0gTcO8xZ90ZXJpIEZhdHVyYXPEsSBOdW1BdENhcmQ8L2xhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIFsobmdNb2RlbCldPVwibGVnLm51bUF0Q2FyZFwiIFtkaXNhYmxlZF09XCIhaXNEcmFmdCgpXCIgLz5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiICpuZ0lmPVwiaXNEcmFmdCgpICYmIGhhc01pc3NpbmdJbmNyZWFzZVJhdGUoKVwiPlxuICAgICAgICAgIFV5YXLEsTogxLBsZ2lsaSDFn2lya2V0dGUvcHJvamVkZSBhcnTEsXLEsW0gb3JhbsSxIDAgLyBOVUxMLiBBcnTEsXLEsW0gdXlndWxhbm1hZGFuIGRldmFtIGV0bWVrIGlzdGl5b3IgbXVzdW51ej9cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIiAqbmdJZj1cImlzRHJhZnQoKSAmJiBoYXNNaXNzaW5nQ29uc3RydWN0aW9uRHJhZnRTZWxlY3Rpb24oKVwiPlxuICAgICAgICAgIFV5YXLEsTogSGVkZWYgQmVsZ2UgRHVydW11IFRhc2xhayBvbGR1xJ91bmRhIENvbnN0cnVjdGlvbiBiYWNha2xhcsSxbmRhIE9QT1Ig4oaSIE9QRE4g4oaSIE9QQ0ggemluY2lyaSB0YXNsYWsgYmVsZ2VsZXIgYXJhc8SxbmRhXG4gICAgICAgICAgw6dhbMSxxZ9tYXouIFwiSGVkZWZ0ZSBPbHXFn2FjYWtcIiBzw7x0dW51bmRhbiBidSBiYWNha2xhciBpw6dpbiB0ZWsgYmlyIGJlbGdlIHRpcGkgKE9QT1IgLyBPUEROIC8gT1BDSCkgc2XDp21lbGlzaW5pei5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBUZWsgdGFibG86IHRhc2xha3RhIGRhLCDDp2FsxLHFn3TEsXLEsWxkxLFrdGFuIHNvbnJhIGRhIEFZTkkgc8O8dHVuIHNldGkgKFPEsXJhLi5BcnTEsXLEsW0pIGtvcnVudXI7XG4gICAgICAgICAgIER1cnVtL1NvbnXDpyBCZWxnZS9IYXRhL8OHYWzEscWfdMSxciB5YWxuxLF6Y2Egw6dhbMSxxZ90xLFyxLFsZMSxa3RhbiBzb25yYSwgaGVyIHNhdMSxcsSxbiBBTFRJTkEgaWtpbmNpIGJpclxuICAgICAgICAgICBzYXTEsXIgb2xhcmFrIGVrbGVuaXIgLSBlc2tpZGVuIGJ1IGJpbGdpbGVyIGF5csSxIHZlIGRhaGEgZGFyIGJpciB0YWJsb3lhIGdlw6dpbGVyZWsgZ8O2c3RlcmlsaXlvcmR1LFxuICAgICAgICAgICBidSBkYSBLYXluYWsgQmVsZ2UvSGVkZWZ0ZSBPbHXFn2FjYWsgZ2liaSBzw7x0dW5sYXLEsW4gXCJrYXlib2xtdcWfXCIgZ8O2csO8bm1lc2luZSB5b2wgYcOnxLF5b3JkdS4gLS0+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwid29ya2luZ0NvcHlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXIgbWItMlwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8aDYgY2xhc3M9XCJtYi0wXCI+e3sgaXNEcmFmdCgpID8gJ1NlbmFyeW8gw4dhbMSxxZ9tYSBLb3B5YXPEsScgOiAnQWt0YXLEsW0gU29udWN1JyB9fTwvaDY+XG4gICAgICAgICAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkXCIgKm5nSWY9XCJpc0RyYWZ0KClcIj5CdSB0YWJsbyB5YWxuxLF6Y2Egw6dhbMSxxZ9tYSBrb3B5YXPEsW7EsSBkw7x6ZW5sZXI7IGFuYSBzZW5hcnlveXUgZGXEn2nFn3Rpcm1lei48L3NtYWxsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnlcIiAoY2xpY2spPVwiYWRkTGVnKClcIiAqbmdJZj1cImlzRHJhZnQoKVwiIFtkaXNhYmxlZF09XCJpc011dGF0aW5nTGVnc1wiPlxuICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1wbHVzIG1lLTFcIj48L2k+QmFjYWsgRWtsZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLWRhbmdlclwiIChjbGljayk9XCJjYW5jZWxDaGFpbigpXCIgKm5nSWY9XCJjYW5DYW5jZWxDaGFpbigpXCI+XG4gICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLWJhbiBtZS0xXCI+PC9pPlppbmNpcmkgxLBwdGFsIEV0XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zZWNvbmRhcnkgc21hbGxcIiAqbmdJZj1cIndvcmtpbmdDb3B5LnN0YXR1cyA9PT0gNFwiPlxuICAgICAgICAgIEJ1IHppbmNpciBpcHRhbCBlZGlsZGksIGJhY2FrbGFyxLEgYXJ0xLFrIMOnYWzEscWfdMSxcsSxbGFtYXovZMO8emVubGVuZW1lei4gWWVuaWRlbiBkZW5lbWVrIGnDp2luXG4gICAgICAgICAgXCJMaXN0ZXllIETDtm5cImRlbiBrYXluYWsgZmF0dXJhecSxIHRla3JhciBzZcOnaXAgeWVuaSBiaXIgYWt0YXLEsW0gYmHFn2xhdMSxbiAtIGJ1LCB5ZW5pIGJpciBJbnRlcmNvbXBhbnkgSWQgaWxlXG4gICAgICAgICAgw6dhbMSxxZ/EsXIuXG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1yZXNwb25zaXZlXCI+XG4gICAgICAgICAgPHRhYmxlIGNsYXNzPVwidGFibGUgdGFibGUtc20gdGFibGUtYm9yZGVyZWQgYWxpZ24tbWlkZGxlXCI+XG4gICAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICA8dGg+U8SxcmE8L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5LYXluYWs8L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5LYXluYWsgQmVsZ2U8L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5IZWRlZjwvdGg+XG4gICAgICAgICAgICAgICAgPHRoPkRhdnJhbsSxxZ88L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5IZWRlZnRlIE9sdcWfYWNhazwvdGg+XG4gICAgICAgICAgICAgICAgPHRoPk9QQ0ggQ2FyZENvZGU8L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5Ew7Z2aXo8L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5LdXI8L3RoPlxuICAgICAgICAgICAgICAgIDx0aD5BcnTEsXLEsW08L3RoPlxuICAgICAgICAgICAgICAgIDx0aCAqbmdJZj1cImlzRHJhZnQoKVwiPjwvdGg+XG4gICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBsZWcgb2Ygd29ya2luZ0NvcHkubGVnc1wiPlxuICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgIDx0ZD57eyBsZWcuc2VxdWVuY2VObyB9fTwvdGQ+XG4gICAgICAgICAgICAgICAgICA8dGQ+e3sgbGVnLnNvdXJjZUNvbXBhbnlOYW1lIH19PC90ZD5cbiAgICAgICAgICAgICAgICAgIDx0ZD5PSU5WPC90ZD5cbiAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgPHNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiaXNEcmFmdCgpOyBlbHNlIHRhcmdldFRleHRcIlxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1zZWxlY3QgZm9ybS1zZWxlY3Qtc21cIlxuICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImxlZy50YXJnZXRDb21wYW55SWRcIlxuICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInVwZGF0ZUxlZ1RhcmdldChsZWcsICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJpc011dGF0aW5nTGVnc1wiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBjIG9mIGNvbXBhbmllc1wiIFtuZ1ZhbHVlXT1cImMuaWRcIj57eyBjLmNvbXBhbnlOYW1lIH19PC9vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI3RhcmdldFRleHQ+e3sgbGVnLnRhcmdldENvbXBhbnlOYW1lIH19PC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgICAgICAgIDxzZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImlzRHJhZnQoKTsgZWxzZSBiZWhhdmlvclRleHRcIlxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1zZWxlY3QgZm9ybS1zZWxlY3Qtc21cIlxuICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImxlZy5sZWdCZWhhdmlvclwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwidXBkYXRlTGVnQmVoYXZpb3IobGVnLCAkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNNdXRhdGluZ0xlZ3NcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgYiBvZiBsZWdCZWhhdmlvcnNcIiBbbmdWYWx1ZV09XCJiLnZhbHVlXCI+e3sgYi5sYWJlbCB9fTwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNiZWhhdmlvclRleHQ+e3sgbGVnQmVoYXZpb3JzW2xlZy5sZWdCZWhhdmlvcl0/LmxhYmVsIH19PC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgICAgICAgIDxzZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImlzRHJhZnQoKSAmJiBpc0NvbnN0cnVjdGlvbkRyYWZ0U2VsZWN0YWJsZShsZWcpOyBlbHNlIHRhcmdldERvY1RleHRcIlxuICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1zZWxlY3QgZm9ybS1zZWxlY3Qtc21cIlxuICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImxlZy5zZWxlY3RlZENvbnN0cnVjdGlvbkRyYWZ0RG9jVHlwZVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwidXBkYXRlTGVnQ29uc3RydWN0aW9uRHJhZnREb2NUeXBlKGxlZywgJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImlzTXV0YXRpbmdMZWdzXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gW25nVmFsdWVdPVwibnVsbFwiPlNlw6dpbml6Li4uPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgbyBvZiBjb25zdHJ1Y3Rpb25EcmFmdERvY1R5cGVPcHRpb25zXCIgW25nVmFsdWVdPVwiby52YWx1ZVwiPnt7IG8ubGFiZWwgfX08L29wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjdGFyZ2V0RG9jVGV4dD57eyBsZWdUYXJnZXREb2NMYWJlbChsZWcpIH19PC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwibGVnLnJlc29sdmVkT3BjaENhcmRDb2RlXCI+e3sgbGVnLnJlc29sdmVkT3BjaENhcmRDb2RlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWxlZy5yZXNvbHZlZE9wY2hDYXJkQ29kZVwiIGNsYXNzPVwiZC1mbGV4IGZsZXgtY29sdW1uIGFsaWduLWl0ZW1zLXN0YXJ0IHB5LTFcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIGJnLWRhbmdlclwiPkXFn2xlxZ90aXJpbG1lZGk8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1kYW5nZXIgYnRuLXNtIG10LTIgcHktMCBweC0yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlPVwiZm9udC1zaXplOiAwLjcycmVtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJnb1RvUGFydG5lck1hcHBpbmcobGVnKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT1cIk11aGF0YXAgRcWfbGXFn3Rpcm1lbGVyaSBla3JhbsSxbmEgZ2l0XCJcbiAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLWxpbmsgbWUtMVwiPjwvaT5FxZ9sZcWfdGlyXG4gICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJpc0RyYWZ0KCk7IGVsc2UgY3VycmVuY3lUZXh0XCJcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtXCJcbiAgICAgICAgICAgICAgICAgICAgICBzdHlsZT1cIndpZHRoOiA1LjVyZW1cIlxuICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwibGVnLmN1cnJlbmN5XCJcbiAgICAgICAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwibmV3U3RhdGU/LmN1cnJlbmN5IHx8ICdLYXluYWt0YW4nXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNjdXJyZW5jeVRleHQ+e3sgbGVnLmN1cnJlbmN5IHx8IG5ld1N0YXRlPy5jdXJyZW5jeSB9fTwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgPHRkPlxuICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImlzRHJhZnQoKTsgZWxzZSByYXRlVGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtXCJcbiAgICAgICAgICAgICAgICAgICAgICBzdHlsZT1cIndpZHRoOiA2cmVtXCJcbiAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImxlZy5leGNoYW5nZVJhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiS2F5bmFrdGFuXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNyYXRlVGV4dD57eyBsZWcuZXhjaGFuZ2VSYXRlID8/ICctJyB9fTwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgPCEtLSBTcGVjIMKnOSAtIGFydMSxcsSxbSBZQUxOSVpDQSBidSBiYWNhxJ/EsW4gb2x1xZ90dXJkdcSfdSBkZXZhbSBNw7zFn3RlcmkgRmF0dXJhc8SxbmEgKGJpclxuICAgICAgICAgICAgICAgICAgICAgICBzb25yYWtpIGJhY2FrIHZhcnNhKSB1eWd1bGFuxLFyOyBidSBoZW0gSW50ZXJtZWRpYXRlQ2hhaW4gaGVtIENvbnN0cnVjdGlvbkNoYWluIGnDp2luXG4gICAgICAgICAgICAgICAgICAgICAgIGdlw6dlcmxpZGlyIChDb25zdHJ1Y3Rpb24nZGEgZGEgbmV4dFRhcmdldENvbXBhbnlJZC5IYXNWYWx1ZSBpc2UgZGV2YW0gT0lOVidpXG4gICAgICAgICAgICAgICAgICAgICAgIGFydMSxcsSxbWxhIG9sdcWfdHVydWx1eW9yKS4gw5ZuY2VkZW4gQ29uc3RydWN0aW9uIGJhY2FrbGFyxLEgbGVnQmVoYXZpb3InYSBiYWvEsWxhcmFrXG4gICAgICAgICAgICAgICAgICAgICAgIEtPxZ5VTFNVWiBcIi1cIiBnw7ZzdGVyaXlvcmR1IC0gemluY2lyaW4gU09OIGJhY2HEn8SxIG9sbWF5YW4gYmlyIENvbnN0cnVjdGlvbiBiYWNhxJ/EsW7EsW5cbiAgICAgICAgICAgICAgICAgICAgICAgaGVkZWZpbmRlIGFydMSxcsSxbSBvcmFuxLEgdGFuxLFtc8SxemtlbiBrdWxsYW7EsWPEsSBoacOnIHV5YXLEsWxtxLF5b3JkdSAoa29kIGluY2VsZW1lc2l5bGVcbiAgICAgICAgICAgICAgICAgICAgICAgdGVzcGl0IGVkaWxkaSkuIERvxJ9ydSBrb8WfdWwgXCJ6aW5jaXJpbiBzb24gYmFjYcSfxLEgbcSxXCIgKGxlZ1RhcmdldERvY0xhYmVsJ2Rha2lcbiAgICAgICAgICAgICAgICAgICAgICAgaXNMYXN0TGVnIGlsZSBheW7EsSBtYW50xLFrKSwgbGVnQmVoYXZpb3IgZGXEn2lsLiAtLT5cbiAgICAgICAgICAgICAgICAgIDx0ZD5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJsZWcuc2VxdWVuY2VObyA+PSAod29ya2luZ0NvcHk/LmxlZ3M/Lmxlbmd0aCA/PyAwKVwiPi08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJsZWcuc2VxdWVuY2VObyA8ICh3b3JraW5nQ29weT8ubGVncz8ubGVuZ3RoID8/IDApXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJsZWcuaW5jcmVhc2VSYXRlQXBwbGllZCA/PyBsZWcucGxhbm5lZEluY3JlYXNlUmF0ZSBhcyByYXRlXCI+e3sgcmF0ZSB8IG51bWJlcjogJzEuMi0yJyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWRhbmdlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cIiEobGVnLmluY3JlYXNlUmF0ZUFwcGxpZWQgPz8gbGVnLnBsYW5uZWRJbmNyZWFzZVJhdGUpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPVwiQnUgxZ9pcmtldHRlIGJ1IHByb2plIGnDp2luIGFydMSxcsSxbSBvcmFuxLEgdGFuxLFtbMSxIGRlxJ9pbGRpci4gQXJ0xLFyxLFtIHV5Z3VsYW5tYWRhbiBkZXZhbSBlZGlsZWNla3Rpci5cIlxuICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIFRhbsSxbXPEsXpcbiAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImlzRHJhZnQoKVwiPlxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLWRhbmdlclwiXG4gICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUxlZyhsZWcpXCJcbiAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNNdXRhdGluZ0xlZ3MgfHwgd29ya2luZ0NvcHkubGVncy5sZW5ndGggPD0gMVwiXG4gICAgICAgICAgICAgICAgICAgICAgdGl0bGU9XCJCYWNhxJ/EsSBTaWxcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS10cmFzaFwiPjwvaT5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgPHRyIGNsYXNzPVwidGFibGUtbGlnaHRcIiAqbmdJZj1cIiFpc0RyYWZ0KClcIj5cbiAgICAgICAgICAgICAgICAgIDx0ZD48L3RkPlxuICAgICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49XCI5XCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGZsZXgtd3JhcCBnYXAtM1wiPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHN0cm9uZz5EdXJ1bTo8L3N0cm9uZz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYmFkZ2UgbXMtMVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5iZy1zZWNvbmRhcnldPVwibGVnLnN0YXR1cyA9PT0gMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5iZy1zdWNjZXNzXT1cImxlZy5zdGF0dXMgPT09IDFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuYmctZGFuZ2VyXT1cImxlZy5zdGF0dXMgPT09IDJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuYmctd2FybmluZ109XCJsZWcuc3RhdHVzID09PSAzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAge3sgbGVnU3RhdHVzTGFiZWwobGVnLnN0YXR1cykgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJjcmVhdGVkRG9jdW1lbnRzU3VtbWFyeShsZWcpIGFzIGRvY3NcIj48c3Ryb25nPlNvbnXDpyBCZWxnZShsZXIpOjwvc3Ryb25nPiB7eyBkb2NzIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1kYW5nZXJcIiAqbmdJZj1cImxlZy5lcnJvck1lc3NhZ2VcIj48c3Ryb25nPkhhdGE6PC9zdHJvbmc+IHt7IGxlZy5lcnJvck1lc3NhZ2UgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1vdXRsaW5lLXByaW1hcnkgbXMtYXV0b1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiZXhlY3V0ZUxlZyhsZWcpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJpc0V4ZWN1dGluZyB8fCAhY2FuRXhlY3V0ZUxlZyhsZWcpXCJcbiAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImlzRXhlY3V0aW5nXCIgY2xhc3M9XCJzcGlubmVyLWJvcmRlciBzcGlubmVyLWJvcmRlci1zbSBtZS0xXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgw4dhbMSxxZ90xLFyXG4gICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgPC90YWJsZT5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPHVsIGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbFwiICpuZ0lmPVwiaXNEcmFmdCgpXCI+XG4gICAgICAgICAgPGxpPsWeaXJrZXRsZXIgYXJhc8SxIE9JTlYg4oaSIE9QQ0ggZ2XDp2nFn2luZGUga2F5bmFrIE51bUF0Q2FyZCBoZWRlZiBPUENILk51bUF0Q2FyZCBhbGFuxLFuYSBheW5lbiB0YcWfxLFuxLFyLjwvbGk+XG4gICAgICAgICAgPGxpPkFydMSxcsSxbSB5YWxuxLF6Y2EgYXluxLEgxZ9pcmtldCBpw6dpbmRlIG9sdcWfdHVydWxhbiB5ZW5pIE3DvMWfdGVyaSBGYXR1cmFzxLFuYSB1eWd1bGFuxLFyOyBuYXZsdW4gYXJ0xLFyxLFtIG9yYW7EsW5kYW4gZXRraWxlbm1lei48L2xpPlxuICAgICAgICAgIDxsaT5NdWhhdGFwIGtvZGxhcsSxIE11aGF0YXAgRcWfbGXFn3Rpcm1lbGVyaSDDvHplcmluZGVuIMOnw7Z6w7xsw7xyLiBLdXIga2F5bmFrIGJlbGdlZGVuIGdlbGlyIHZlIGt1bGxhbsSxY8SxIHRhcmFmxLFuZGFuIGRlxJ9pxZ90aXJpbGViaWxpci48L2xpPlxuICAgICAgICA8L3VsPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWVuZCBnYXAtMiBtdC0zXCI+XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1zZWNvbmRhcnlcIiAoY2xpY2spPVwiYmFja1RvTGlzdCgpXCI+e3sgaXNEcmFmdCgpID8gJ1Zhemdlw6cnIDogJ0thcGF0JyB9fTwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgICAgICAgIChjbGljayk9XCJzdGFydEZsb3coKVwiXG4gICAgICAgICAgKm5nSWY9XCJpc0RyYWZ0KCkgJiYgd29ya2luZ0NvcHlcIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJpc1N0YXJ0aW5nIHx8IGhhc01pc3NpbmdDb25zdHJ1Y3Rpb25EcmFmdFNlbGVjdGlvbigpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiaXNTdGFydGluZ1wiIGNsYXNzPVwic3Bpbm5lci1ib3JkZXIgc3Bpbm5lci1ib3JkZXItc20gbWUtMVwiPjwvc3Bhbj5cbiAgICAgICAgICBCZWxnZSBBa8SxxZ/EsW7EsSBCYcWfbGF0XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=
|