@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
219 lines • 32.3 kB
JavaScript
import { Injectable } from '@angular/core';
import { InventoryService, MeasurementService } from '@c8y/client';
import { AppStateService, ColorService, MAX_PAGE_SIZE } from '@c8y/ngx-components';
import { get, sortBy, uniq } from 'lodash-es';
import { filter } from 'rxjs/operators';
import { DATAPOINT_LIBRARY_FRAGMENT } from './datapoint-selection.model';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "@c8y/ngx-components";
export class DatapointLibraryService {
constructor(inventory, appState, measurements, color) {
this.inventory = inventory;
this.appState = appState;
this.measurements = measurements;
this.color = color;
this.appState.currentUser.pipe(filter(user => !user)).subscribe(() => {
this.cache = undefined;
});
}
async getAllDatapointLibraryEntriesCached(forceCacheRenew = false) {
if (forceCacheRenew) {
this.cache = undefined;
}
if (!this.cache) {
this.cache = this.getAllDatapointLibraryEntries();
}
return this.cache;
}
async getFirstDatapointLibraryPage() {
const filterObj = {
currentPage: 1,
pageSize: 50,
fragmentType: DATAPOINT_LIBRARY_FRAGMENT,
withTotalPages: true
};
return (await this.inventory.list(filterObj));
}
async getAllDatapointLibraryItemsCached() {
if (!this.cache) {
this.cache = this.getAllDatapointLibraryEntries();
}
const res = await this.cache;
return res.map(tmp => tmp[DATAPOINT_LIBRARY_FRAGMENT]);
}
async updateDatapoints(datapoints, skipUpdatingTarget = false) {
if (!Array.isArray(datapoints)) {
return datapoints;
}
const currentTargetsPromise = !skipUpdatingTarget
? this.getCurrentVersionOfTargetsFromDatapoints(datapoints)
: Promise.resolve([]);
const [currentTemplates, currentTargets] = await Promise.all([
this.getCurrentTemplatesFromDatapoints(datapoints),
currentTargetsPromise
]);
const currentTemplateVersions = currentTemplates
.map(tmp => this.mapDatapointLibraryEntry(tmp))
.filter(tmp => !!tmp);
for (const datapoint of datapoints) {
const { fragment, series, __active, __target, color, label, __template } = datapoint;
const foundCurrentTemplateVersion = currentTemplateVersions.find(tmp => tmp.__template === datapoint.__template);
if (foundCurrentTemplateVersion) {
Object.assign(datapoint, foundCurrentTemplateVersion);
Object.assign(datapoint, {
fragment,
series,
__active,
__target,
color,
label,
__template
});
}
const foundCurrentTarget = currentTargets.find(target => target.id === __target?.id);
if (foundCurrentTarget) {
const { id, name } = foundCurrentTarget;
datapoint.__target = { id, name };
}
}
return datapoints;
}
async getDatapointsOfAsset(parentReference, ignoreDatapointTemplates, datapointTemplatesOnly = false) {
const [kpiResponse, details] = await Promise.all([
(ignoreDatapointTemplates
? Promise.resolve(null)
: this.inventory.assetKPIsList(parentReference, { pageSize: MAX_PAGE_SIZE })),
this.inventory.getMeasurementsAndSeries(parentReference)
]);
const kpis = kpiResponse && kpiResponse.data ? kpiResponse.data : [];
const sortedDetails = sortBy(details, ['fragment', 'series']);
return await this.combineFragmentSeriesTuplesWithDetails(sortedDetails, parentReference, kpis, datapointTemplatesOnly);
}
/**
* Requests the last measurement with the given fragment and series to extract it's unit.
* If the source attribute is provided, it will check the last measurement for this specific source.
* @returns found unit or an empty string instead
*/
async guessUnitOfDatapoint(fragment, series, source) {
const measurementfilter = {
valueFragmentSeries: series,
valueFragmentType: fragment,
pageSize: 1,
revert: true,
dateFrom: '1970-01-01'
};
if (source?.id) {
measurementfilter.source = source?.id;
}
try {
const { data: lastMeasurements } = await this.measurements.list(measurementfilter);
const measurement = lastMeasurements[0];
if (measurement) {
const pathToUnit = `${fragment}.${series}.unit`;
const unit = get(measurement, pathToUnit);
if (unit?.length && typeof unit === 'string') {
return unit;
}
}
}
catch {
// nothing to do
}
return '';
}
async combineFragmentSeriesTuplesWithDetails(tuples, target, kpis, datapointTemplatesOnly = false) {
const datapoints = tuples
.map(tuple => {
const foundDatapointLibraryEntry = kpis.find(kpi => kpi[DATAPOINT_LIBRARY_FRAGMENT] &&
kpi[DATAPOINT_LIBRARY_FRAGMENT].fragment === tuple.fragment &&
kpi[DATAPOINT_LIBRARY_FRAGMENT].series === tuple.series);
if (!foundDatapointLibraryEntry && datapointTemplatesOnly) {
return null;
}
const datapoint = this.mapDatapointLibraryEntry(foundDatapointLibraryEntry) || tuple;
if (!datapoint.label) {
datapoint.label = `${datapoint.fragment} → ${datapoint.series}`;
}
if (!datapoint.unit?.length) {
datapoint.unit = '';
}
datapoint.__target = target;
return datapoint;
})
.filter(Boolean);
await this.assignColorToDatapoints(datapoints);
return datapoints;
}
async assignColorToDatapoints(datapoints) {
const datapointsWithoutColor = datapoints.filter(datapoint => !datapoint.color);
await Promise.all(datapointsWithoutColor.map(datapoint => this.color
.generateColorForDatapoint(datapoint.fragment, datapoint.series)
.then(color => (datapoint.color = color))));
}
async getAllDatapointLibraryEntries() {
const entries = new Array();
const filterObj = {
currentPage: 1,
pageSize: MAX_PAGE_SIZE,
fragmentType: DATAPOINT_LIBRARY_FRAGMENT
};
let res = await this.inventory.list(filterObj);
while (res.data.length) {
entries.push(...res.data);
if (res.data.length < res.paging.pageSize) {
break;
}
if (!res.paging.nextPage) {
break;
}
res = await res.paging.next();
}
return entries;
}
mapDatapointLibraryEntry(entry) {
if (!entry || !entry[DATAPOINT_LIBRARY_FRAGMENT]) {
return null;
}
const datapoint = entry[DATAPOINT_LIBRARY_FRAGMENT];
datapoint.__template = entry.id;
return datapoint;
}
async getCurrentTemplatesFromDatapoints(datapoints) {
const datapointsWithTemplateId = datapoints.filter(dp => !!dp.__template);
const usedTemplateIds = datapointsWithTemplateId.map(dp => dp.__template);
return await this.getMOsByIds(usedTemplateIds);
}
async getCurrentVersionOfTargetsFromDatapoints(datapoints) {
const datapointsWithTarget = datapoints.filter(dp => !!dp.__target?.id);
const usedTargetIds = datapointsWithTarget.map(dp => dp.__target.id);
return await this.getMOsByIds(usedTargetIds);
}
async getMOsByIds(ids) {
const uniqManagedObjectIds = uniq(ids);
if (!uniqManagedObjectIds.length) {
return [];
}
try {
const { data: managedObjects } = await this.inventory.list({
ids: uniqManagedObjectIds.join(),
pageSize: MAX_PAGE_SIZE
});
return managedObjects;
}
catch {
// Fail silently in case we are not able to talk to the inventory API.
// Should only be reached in case of an server side error.
// instead of failing, pretend like we didn't receive any items.
console.warn(`Failed to get the current version of the following managedObjects: ${uniqManagedObjectIds.join()}.`);
return [];
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatapointLibraryService, deps: [{ token: i1.InventoryService }, { token: i2.AppStateService }, { token: i1.MeasurementService }, { token: i2.ColorService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatapointLibraryService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatapointLibraryService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1.InventoryService }, { type: i2.AppStateService }, { type: i1.MeasurementService }, { type: i2.ColorService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXBvaW50LWxpYnJhcnkuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2RhdGFwb2ludC1zZWxlY3Rvci9kYXRhcG9pbnQtbGlicmFyeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUdMLGdCQUFnQixFQUVoQixrQkFBa0IsRUFDbkIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbkYsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzlDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsMEJBQTBCLEVBRzNCLE1BQU0sNkJBQTZCLENBQUM7Ozs7QUFHckMsTUFBTSxPQUFPLHVCQUF1QjtJQUVsQyxZQUNVLFNBQTJCLEVBQzNCLFFBQXlCLEVBQ3pCLFlBQWdDLEVBQ2hDLEtBQW1CO1FBSG5CLGNBQVMsR0FBVCxTQUFTLENBQWtCO1FBQzNCLGFBQVEsR0FBUixRQUFRLENBQWlCO1FBQ3pCLGlCQUFZLEdBQVosWUFBWSxDQUFvQjtRQUNoQyxVQUFLLEdBQUwsS0FBSyxDQUFjO1FBRTNCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtZQUNuRSxJQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsbUNBQW1DLENBQUMsZUFBZSxHQUFHLEtBQUs7UUFDL0QsSUFBSSxl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O1FBQ1osQ0FBQztRQUNELElBQUksQ0FBQztZQUNILE1BQU0sRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDekQsR0FBRyxFQUFFLG9CQUFvQixDQUFDLElBQUksRUFBRTtnQkFDaEMsUUFBUSxFQUFFLGFBQWE7YUFDeEIsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxjQUFjLENBQUM7UUFDeEIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLHNFQUFzRTtZQUN0RSwwREFBMEQ7WUFDMUQsZ0VBQWdFO1lBQ2hFLE9BQU8sQ0FBQyxJQUFJLENBQ1Ysc0VBQXNFLG9CQUFvQixDQUFDLElBQUksRUFBRSxHQUFHLENBQ3JHLENBQUM7WUFDRixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7SUFDSCxDQUFDOytHQWpRVSx1QkFBdUI7bUhBQXZCLHVCQUF1QixjQURWLE1BQU07OzRGQUNuQix1QkFBdUI7a0JBRG5DLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSUlkZW50aWZpZWQsXG4gIElNYW5hZ2VkT2JqZWN0LFxuICBJbnZlbnRvcnlTZXJ2aWNlLFxuICBJUmVzdWx0TGlzdCxcbiAgTWVhc3VyZW1lbnRTZXJ2aWNlXG59IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IEFwcFN0YXRlU2VydmljZSwgQ29sb3JTZXJ2aWNlLCBNQVhfUEFHRV9TSVpFIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBnZXQsIHNvcnRCeSwgdW5pcSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBmaWx0ZXIgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1xuICBEQVRBUE9JTlRfTElCUkFSWV9GUkFHTUVOVCxcbiAgS1BJRGV0YWlscyxcbiAgTWFuYWdlZE9iamVjdEtQSVxufSBmcm9tICcuL2RhdGFwb2ludC1zZWxlY3Rpb24ubW9kZWwnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIERhdGFwb2ludExpYnJhcnlTZXJ2aWNlIHtcbiAgcHJvdGVjdGVkIGNhY2hlOiBQcm9taXNlPE1hbmFnZWRPYmplY3RLUElbXT47XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaW52ZW50b3J5OiBJbnZlbnRvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgYXBwU3RhdGU6IEFwcFN0YXRlU2VydmljZSxcbiAgICBwcml2YXRlIG1lYXN1cmVtZW50czogTWVhc3VyZW1lbnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29sb3I6IENvbG9yU2VydmljZVxuICApIHtcbiAgICB0aGlzLmFwcFN0YXRlLmN1cnJlbnRVc2VyLnBpcGUoZmlsdGVyKHVzZXIgPT4gIXVzZXIpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgdGhpcy5jYWNoZSA9IHVuZGVmaW5lZDtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGdldEFsbERhdGFwb2ludExpYnJhcnlFbnRyaWVzQ2FjaGVkKGZvcmNlQ2FjaGVSZW5ldyA9IGZhbHNlKTogUHJvbWlzZTxNYW5hZ2VkT2JqZWN0S1BJW10+IHtcbiAgICBpZiAoZm9yY2VDYWNoZVJlbmV3KSB7XG4gICAgICB0aGlzLmNhY2hlID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuY2FjaGUpIHtcbiAgICAgIHRoaXMuY2FjaGUgPSB0aGlzLmdldEFsbERhdGFwb2ludExpYnJhcnlFbnRyaWVzKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNhY2hlO1xuICB9XG5cbiAgYXN5bmMgZ2V0Rmlyc3REYXRhcG9pbnRMaWJyYXJ5UGFnZSgpOiBQcm9taXNlPElSZXN1bHRMaXN0PE1hbmFnZWRPYmplY3RLUEk+PiB7XG4gICAgY29uc3QgZmlsdGVyT2JqID0ge1xuICAgICAgY3VycmVudFBhZ2U6IDEsXG4gICAgICBwYWdlU2l6ZTogNTAsXG4gICAgICBmcmFnbWVudFR5cGU6IERBVEFQT0lOVF9MSUJSQVJZX0ZSQUdNRU5ULFxuICAgICAgd2l0aFRvdGFsUGFnZXM6IHRydWVcbiAgICB9O1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnZlbnRvcnkubGlzdChmaWx0ZXJPYmopKSBhcyBJUmVzdWx0TGlzdDxNYW5hZ2VkT2JqZWN0S1BJPjtcbiAgfVxuXG4gIGFzeW5jIGdldEFsbERhdGFwb2ludExpYnJhcnlJdGVtc0NhY2hlZCgpOiBQcm9taXNlPEtQSURldGFpbHNbXT4ge1xuICAgIGlmICghdGhpcy5jYWNoZSkge1xuICAgICAgdGhpcy5jYWNoZSA9IHRoaXMuZ2V0QWxsRGF0YXBvaW50TGlicmFyeUVudHJpZXMoKTtcbiAgICB9XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5jYWNoZTtcbiAgICByZXR1cm4gcmVzLm1hcCh0bXAgPT4gdG1wW0RBVEFQT0lOVF9MSUJSQVJZX0ZSQUdNRU5UXSk7XG4gIH1cblxuICBhc3luYyB1cGRhdGVEYXRhcG9pbnRzKFxuICAgIGRhdGFwb2ludHM6IEtQSURldGFpbHNbXSxcbiAgICBza2lwVXBkYXRpbmdUYXJnZXQgPSBmYWxzZVxuICApOiBQcm9taXNlPEtQSURldGFpbHNbXT4ge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhcG9pbnRzKSkge1xuICAgICAgcmV0dXJuIGRhdGFwb2ludHM7XG4gICAgfVxuICAgIGNvbnN0IGN1cnJlbnRUYXJnZXRzUHJvbWlzZTogUHJvbWlzZTxJTWFuYWdlZE9iamVjdFtdPiA9ICFza2lwVXBkYXRpbmdUYXJnZXRcbiAgICAgID8gdGhpcy5nZXRDdXJyZW50VmVyc2lvbk9mVGFyZ2V0c0Zyb21EYXRhcG9pbnRzKGRhdGFwb2ludHMpXG4gICAgICA6IFByb21pc2UucmVzb2x2ZShbXSk7XG4gICAgY29uc3QgW2N1cnJlbnRUZW1wbGF0ZXMsIGN1cnJlbnRUYXJnZXRzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIHRoaXMuZ2V0Q3VycmVudFRlbXBsYXRlc0Zyb21EYXRhcG9pbnRzKGRhdGFwb2ludHMpLFxuICAgICAgY3VycmVudFRhcmdldHNQcm9taXNlXG4gICAgXSk7XG4gICAgY29uc3QgY3VycmVudFRlbXBsYXRlVmVyc2lvbnMgPSBjdXJyZW50VGVtcGxhdGVzXG4gICAgICAubWFwKHRtcCA9PiB0aGlzLm1hcERhdGFwb2ludExpYnJhcnlFbnRyeSh0bXAgYXMgTWFuYWdlZE9iamVjdEtQSSkpXG4gICAgICAuZmlsdGVyKHRtcCA9PiAhIXRtcCk7XG4gICAgZm9yIChjb25zdCBkYXRhcG9pbnQgb2YgZGF0YXBvaW50cykge1xuICAgICAgY29uc3QgeyBmcmFnbWVudCwgc2VyaWVzLCBfX2FjdGl2ZSwgX190YXJnZXQsIGNvbG9yLCBsYWJlbCwgX190ZW1wbGF0ZSB9ID0gZGF0YXBvaW50O1xuICAgICAgY29uc3QgZm91bmRDdXJyZW50VGVtcGxhdGVWZXJzaW9uID0gY3VycmVudFRlbXBsYXRlVmVyc2lvbnMuZmluZChcbiAgICAgICAgdG1wID0+IHRtcC5fX3RlbXBsYXRlID09PSBkYXRhcG9pbnQuX190ZW1wbGF0ZVxuICAgICAgKTtcbiAgICAgIGlmIChmb3VuZEN1cnJlbnRUZW1wbGF0ZVZlcnNpb24pIHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihkYXRhcG9pbnQsIGZvdW5kQ3VycmVudFRlbXBsYXRlVmVyc2lvbik7XG4gICAgICAgIE9iamVjdC5hc3NpZ24oZGF0YXBvaW50LCB7XG4gICAgICAgICAgZnJhZ21lbnQsXG4gICAgICAgICAgc2VyaWVzLFxuICAgICAgICAgIF9fYWN0aXZlLFxuICAgICAgICAgIF9fdGFyZ2V0LFxuICAgICAgICAgIGNvbG9yLFxuICAgICAgICAgIGxhYmVsLFxuICAgICAgICAgIF9fdGVtcGxhdGVcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZvdW5kQ3VycmVudFRhcmdldCA9IGN1cnJlbnRUYXJnZXRzLmZpbmQodGFyZ2V0ID0+IHRhcmdldC5pZCA9PT0gX190YXJnZXQ/LmlkKTtcbiAgICAgIGlmIChmb3VuZEN1cnJlbnRUYXJnZXQpIHtcbiAgICAgICAgY29uc3QgeyBpZCwgbmFtZSB9ID0gZm91bmRDdXJyZW50VGFyZ2V0O1xuICAgICAgICBkYXRhcG9pbnQuX190YXJnZXQgPSB7IGlkLCBuYW1lIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkYXRhcG9pbnRzO1xuICB9XG5cbiAgYXN5bmMgZ2V0RGF0YXBvaW50c09mQXNzZXQoXG4gICAgcGFyZW50UmVmZXJlbmNlOiBJSWRlbnRpZmllZCxcbiAgICBpZ25vcmVEYXRhcG9pbnRUZW1wbGF0ZXM/OiBib29sZWFuLFxuICAgIGRhdGFwb2ludFRlbXBsYXRlc09ubHkgPSBmYWxzZVxuICApOiBQcm9taXNlPEtQSURldGFpbHNbXT4ge1xuICAgIGNvbnN0IFtrcGlSZXNwb25zZSwgZGV0YWlsc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAoaWdub3JlRGF0YXBvaW50VGVtcGxhdGVzXG4gICAgICAgID8gUHJvbWlzZS5yZXNvbHZlKG51bGwpXG4gICAgICAgIDogdGhpcy5pbnZlbnRvcnkuYXNzZXRLUElzTGlzdChwYXJlbnRSZWZlcmVuY2UsIHsgcGFnZVNpemU6IE1BWF9QQUdFX1NJWkUgfSkpIGFzIFByb21pc2U8XG4gICAgICAgIElSZXN1bHRMaXN0PE1hbmFnZWRPYmplY3RLUEk+XG4gICAgICA+LFxuICAgICAgdGhpcy5pbnZlbnRvcnkuZ2V0TWVhc3VyZW1lbnRzQW5kU2VyaWVzKHBhcmVudFJlZmVyZW5jZSlcbiAgICBdKTtcbiAgICBjb25zdCBrcGlzID0ga3BpUmVzcG9uc2UgJiYga3BpUmVzcG9uc2UuZGF0YSA/IGtwaVJlc3BvbnNlLmRhdGEgOiBbXTtcbiAgICBjb25zdCBzb3J0ZWREZXRhaWxzID0gc29ydEJ5KGRldGFpbHMsIFsnZnJhZ21lbnQnLCAnc2VyaWVzJ10pO1xuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuY29tYmluZUZyYWdtZW50U2VyaWVzVHVwbGVzV2l0aERldGFpbHMoXG4gICAgICBzb3J0ZWREZXRhaWxzLFxuICAgICAgcGFyZW50UmVmZXJlbmNlLFxuICAgICAga3BpcyxcbiAgICAgIGRhdGFwb2ludFRlbXBsYXRlc09ubHlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3RzIHRoZSBsYXN0IG1lYXN1cmVtZW50IHdpdGggdGhlIGdpdmVuIGZyYWdtZW50IGFuZCBzZXJpZXMgdG8gZXh0cmFjdCBpdCdzIHVuaXQuXG4gICAqIElmIHRoZSBzb3VyY2UgYXR0cmlidXRlIGlzIHByb3ZpZGVkLCBpdCB3aWxsIGNoZWNrIHRoZSBsYXN0IG1lYXN1cmVtZW50IGZvciB0aGlzIHNwZWNpZmljIHNvdXJjZS5cbiAgICogQHJldHVybnMgZm91bmQgdW5pdCBvciBhbiBlbXB0eSBzdHJpbmcgaW5zdGVhZFxuICAgKi9cbiAgYXN5bmMgZ3Vlc3NVbml0T2ZEYXRhcG9pbnQoXG4gICAgZnJhZ21lbnQ6IHN0cmluZyxcbiAgICBzZXJpZXM6IHN0cmluZyxcbiAgICBzb3VyY2U/OiBJSWRlbnRpZmllZFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IG1lYXN1cmVtZW50ZmlsdGVyOiBhbnkgPSB7XG4gICAgICB2YWx1ZUZyYWdtZW50U2VyaWVzOiBzZXJpZXMsXG4gICAgICB2YWx1ZUZyYWdtZW50VHlwZTogZnJhZ21lbnQsXG4gICAgICBwYWdlU2l6ZTogMSxcbiAgICAgIHJldmVydDogdHJ1ZSxcbiAgICAgIGRhdGVGcm9tOiAnMTk3MC0wMS0wMSdcbiAgICB9O1xuICAgIGlmIChzb3VyY2U/LmlkKSB7XG4gICAgICBtZWFzdXJlbWVudGZpbHRlci5zb3VyY2UgPSBzb3VyY2U/LmlkO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBkYXRhOiBsYXN0TWVhc3VyZW1lbnRzIH0gPSBhd2FpdCB0aGlzLm1lYXN1cmVtZW50cy5saXN0KG1lYXN1cmVtZW50ZmlsdGVyKTtcbiAgICAgIGNvbnN0IG1lYXN1cmVtZW50ID0gbGFzdE1lYXN1cmVtZW50c1swXTtcbiAgICAgIGlmIChtZWFzdXJlbWVudCkge1xuICAgICAgICBjb25zdCBwYXRoVG9Vbml0ID0gYCR7ZnJhZ21lbnR9LiR7c2VyaWVzfS51bml0YDtcbiAgICAgICAgY29uc3QgdW5pdCA9IGdldChtZWFzdXJlbWVudCwgcGF0aFRvVW5pdCk7XG4gICAgICAgIGlmICh1bml0Py5sZW5ndGggJiYgdHlwZW9mIHVuaXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcmV0dXJuIHVuaXQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIG5vdGhpbmcgdG8gZG9cbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGNvbWJpbmVGcmFnbWVudFNlcmllc1R1cGxlc1dpdGhEZXRhaWxzKFxuICAgIHR1cGxlczogQXJyYXk8eyBmcmFnbWVudDogc3RyaW5nOyBzZXJpZXM6IHN0cmluZyB9PixcbiAgICB0YXJnZXQ6IElJZGVudGlmaWVkLFxuICAgIGtwaXM6IE1hbmFnZWRPYmplY3RLUElbXSxcbiAgICBkYXRhcG9pbnRUZW1wbGF0ZXNPbmx5ID0gZmFsc2VcbiAgKSB7XG4gICAgY29uc3QgZGF0YXBvaW50cyA9IHR1cGxlc1xuICAgICAgLm1hcCh0dXBsZSA9PiB7XG4gICAgICAgIGNvbnN0IGZvdW5kRGF0YXBvaW50TGlicmFyeUVudHJ5ID0ga3Bpcy5maW5kKFxuICAgICAgICAgIGtwaSA9PlxuICAgICAgICAgICAga3BpW0RBVEFQT0lOVF9MSUJSQVJZX0ZSQUdNRU5UXSAmJlxuICAgICAgICAgICAga3BpW0RBVEFQT0lOVF9MSUJSQVJZX0ZSQUdNRU5UXS5mcmFnbWVudCA9PT0gdHVwbGUuZnJhZ21lbnQgJiZcbiAgICAgICAgICAgIGtwaVtEQVRBUE9JTlRfTElCUkFSWV9GUkFHTUVOVF0uc2VyaWVzID09PSB0dXBsZS5zZXJpZXNcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFmb3VuZERhdGFwb2ludExpYnJhcnlFbnRyeSAmJiBkYXRhcG9pbnRUZW1wbGF0ZXNPbmx5KSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YXBvaW50OiBLUElEZXRhaWxzID1cbiAgICAgICAgICB0aGlzLm1hcERhdGFwb2ludExpYnJhcnlFbnRyeShmb3VuZERhdGFwb2ludExpYnJhcnlFbnRyeSkgfHwgdHVwbGU7XG4gICAgICAgIGlmICghZGF0YXBvaW50LmxhYmVsKSB7XG4gICAgICAgICAgZGF0YXBvaW50LmxhYmVsID0gYCR7ZGF0YXBvaW50LmZyYWdtZW50fSDihpIgJHtkYXRhcG9pbnQuc2VyaWVzfWA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRhcG9pbnQudW5pdD8ubGVuZ3RoKSB7XG4gICAgICAgICAgZGF0YXBvaW50LnVuaXQgPSAnJztcbiAgICAgICAgfVxuICAgICAgICBkYXRhcG9pbnQuX190YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIHJldHVybiBkYXRhcG9pbnQ7XG4gICAgICB9KVxuICAgICAgLmZpbHRlcihCb29sZWFuKTtcbiAgICBhd2FpdCB0aGlzLmFzc2lnbkNvbG9yVG9EYXRhcG9pbnRzKGRhdGFwb2ludHMpO1xuICAgIHJldHVybiBkYXRhcG9pbnRzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGFzc2lnbkNvbG9yVG9EYXRhcG9pbnRzKGRhdGFwb2ludHM6IEtQSURldGFpbHNbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRhdGFwb2ludHNXaXRob3V0Q29sb3IgPSBkYXRhcG9pbnRzLmZpbHRlcihkYXRhcG9pbnQgPT4gIWRhdGFwb2ludC5jb2xvcik7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBkYXRhcG9pbnRzV2l0aG91dENvbG9yLm1hcChkYXRhcG9pbnQgPT5cbiAgICAgICAgdGhpcy5jb2xvclxuICAgICAgICAgIC5nZW5lcmF0ZUNvbG9yRm9yRGF0YXBvaW50KGRhdGFwb2ludC5mcmFnbWVudCwgZGF0YXBvaW50LnNlcmllcylcbiAgICAgICAgICAudGhlbihjb2xvciA9PiAoZGF0YXBvaW50LmNvbG9yID0gY29sb3IpKVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0QWxsRGF0YXBvaW50TGlicmFyeUVudHJpZXMoKTogUHJvbWlzZTxNYW5hZ2VkT2JqZWN0S1BJW10+IHtcbiAgICBjb25zdCBlbnRyaWVzID0gbmV3IEFycmF5PE1hbmFnZWRPYmplY3RLUEk+KCk7XG4gICAgY29uc3QgZmlsdGVyT2JqID0ge1xuICAgICAgY3VycmVudFBhZ2U6IDEsXG4gICAgICBwYWdlU2l6ZTogTUFYX1BBR0VfU0laRSxcbiAgICAgIGZyYWdtZW50VHlwZTogREFUQVBPSU5UX0xJQlJBUllfRlJBR01FTlRcbiAgICB9O1xuICAgIGxldCByZXMgPSBhd2FpdCB0aGlzLmludmVudG9yeS5saXN0KGZpbHRlck9iaik7XG4gICAgd2hpbGUgKHJlcy5kYXRhLmxlbmd0aCkge1xuICAgICAgZW50cmllcy5wdXNoKC4uLihyZXMuZGF0YSBhcyBNYW5hZ2VkT2JqZWN0S1BJW10pKTtcbiAgICAgIGlmIChyZXMuZGF0YS5sZW5ndGggPCByZXMucGFnaW5nLnBhZ2VTaXplKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKCFyZXMucGFnaW5nLm5leHRQYWdlKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICByZXMgPSBhd2FpdCByZXMucGFnaW5nLm5leHQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGVudHJpZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFwRGF0YXBvaW50TGlicmFyeUVudHJ5KGVudHJ5OiBNYW5hZ2VkT2JqZWN0S1BJKTogS1BJRGV0YWlscyB7XG4gICAgaWYgKCFlbnRyeSB8fCAhZW50cnlbREFUQVBPSU5UX0xJQlJBUllfRlJBR01FTlRdKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhcG9pbnQgPSBlbnRyeVtEQVRBUE9JTlRfTElCUkFSWV9GUkFHTUVOVF07XG4gICAgZGF0YXBvaW50Ll9fdGVtcGxhdGUgPSBlbnRyeS5pZDtcbiAgICByZXR1cm4gZGF0YXBvaW50O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEN1cnJlbnRUZW1wbGF0ZXNGcm9tRGF0YXBvaW50cyhcbiAgICBkYXRhcG9pbnRzOiBLUElEZXRhaWxzW11cbiAgKTogUHJvbWlzZTxJTWFuYWdlZE9iamVjdFtdPiB7XG4gICAgY29uc3QgZGF0YXBvaW50c1dpdGhUZW1wbGF0ZUlkID0gZGF0YXBvaW50cy5maWx0ZXIoZHAgPT4gISFkcC5fX3RlbXBsYXRlKTtcbiAgICBjb25zdCB1c2VkVGVtcGxhdGVJZHMgPSBkYXRhcG9pbnRzV2l0aFRlbXBsYXRlSWQubWFwKGRwID0+IGRwLl9fdGVtcGxhdGUpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmdldE1Pc0J5SWRzKHVzZWRUZW1wbGF0ZUlkcyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0Q3VycmVudFZlcnNpb25PZlRhcmdldHNGcm9tRGF0YXBvaW50cyhcbiAgICBkYXRhcG9pbnRzOiBLUElEZXRhaWxzW11cbiAgKTogUHJvbWlzZTxJTWFuYWdlZE9iamVjdFtdPiB7XG4gICAgY29uc3QgZGF0YXBvaW50c1dpdGhUYXJnZXQgPSBkYXRhcG9pbnRzLmZpbHRlcihkcCA9PiAhIWRwLl9fdGFyZ2V0Py5pZCk7XG4gICAgY29uc3QgdXNlZFRhcmdldElkcyA9IGRhdGFwb2ludHNXaXRoVGFyZ2V0Lm1hcChkcCA9PiBkcC5fX3RhcmdldC5pZCk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0TU9zQnlJZHModXNlZFRhcmdldElkcyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0TU9zQnlJZHMoaWRzOiBBcnJheTxzdHJpbmcgfCBudW1iZXI+KTogUHJvbWlzZTxJTWFuYWdlZE9iamVjdFtdPiB7XG4gICAgY29uc3QgdW5pcU1hbmFnZWRPYmplY3RJZHMgPSB1bmlxKGlkcyk7XG4gICAgaWYgKCF1bmlxTWFuYWdlZE9iamVjdElkcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgZGF0YTogbWFuYWdlZE9iamVjdHMgfSA9IGF3YWl0IHRoaXMuaW52ZW50b3J5Lmxpc3Qoe1xuICAgICAgICBpZHM6IHVuaXFNYW5hZ2VkT2JqZWN0SWRzLmpvaW4oKSxcbiAgICAgICAgcGFnZVNpemU6IE1BWF9QQUdFX1NJWkVcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG1hbmFnZWRPYmplY3RzO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gRmFpbCBzaWxlbnRseSBpbiBjYXNlIHdlIGFyZSBub3QgYWJsZSB0byB0YWxrIHRvIHRoZSBpbnZlbnRvcnkgQVBJLlxuICAgICAgLy8gU2hvdWxkIG9ubHkgYmUgcmVhY2hlZCBpbiBjYXNlIG9mIGFuIHNlcnZlciBzaWRlIGVycm9yLlxuICAgICAgLy8gaW5zdGVhZCBvZiBmYWlsaW5nLCBwcmV0ZW5kIGxpa2Ugd2UgZGlkbid0IHJlY2VpdmUgYW55IGl0ZW1zLlxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgRmFpbGVkIHRvIGdldCB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBmb2xsb3dpbmcgbWFuYWdlZE9iamVjdHM6ICR7dW5pcU1hbmFnZWRPYmplY3RJZHMuam9pbigpfS5gXG4gICAgICApO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxufVxuIl19