@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
230 lines • 38.7 kB
JavaScript
import { Injectable } from '@angular/core';
import { InventoryService, OperationService, OperationStatus, QueriesUtil } from '@c8y/client';
import { AlertService, gettext } from '@c8y/ngx-components';
import { get, isEmpty, isNil, keyBy, keys, mapValues, omitBy, pickBy, sortBy, toArray, uniqBy } from 'lodash-es';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "@c8y/ngx-components";
export class DeviceProfileService {
constructor(inventoryService, operationService, alertService) {
this.inventoryService = inventoryService;
this.operationService = operationService;
this.alertService = alertService;
this.dateFrom = new Date(0);
this.dateTo = new Date(Date.now() + 86400000); // 1 day in the future
this.NOT_INSTALLED_WARNING = gettext('Not installed on the device');
this.VERSION_MISSMATCH_WARNING = gettext('Version mismatch');
this.SAME_URL_WARNING = gettext('Installed configuration has the same URL but different name or type than the one in the profile');
this.queriesUtil = new QueriesUtil();
}
createDeviceProfile(deviceProfile) {
if (get(deviceProfile, 'c8y_Filter.type') === '') {
delete deviceProfile.c8y_Filter.type;
}
return this.inventoryService.create(deviceProfile);
}
/**
* Determines the available device profiles for a given device by considering device type
* and the supported software types declared by the devices. Because of limitations in the
* Inventory Query API the methods return profile that contain at least one of the supported
* software types and omits profiles having only non-supported software types. Resulting device
* profiles need to be further filtered on the client side to exclude the ones that contain
* non-supported software types next to the supported ones.
*
* @param device A device MO
* @param name Optional device profile name filter
* @returns Candidate device profiles that contain at least on software with supported type.
*/
getDeviceProfilesByDevice(device, name = null) {
const deviceTypeFilter = {
__or: [
{ 'c8y_Filter.type': device.type },
{ 'c8y_Filter.type': '' },
{ __not: { __has: 'c8y_Filter.type' } }
]
};
let softwareTypeFilter = {};
if (!isEmpty(device.c8y_SupportedSoftwareTypes)) {
softwareTypeFilter = {
__hasany: device.c8y_SupportedSoftwareTypes.map((type) => `softwareType!${type}`)
};
}
let query = this.queriesUtil.addAndFilter(deviceTypeFilter, softwareTypeFilter);
let profileNameFilter = {};
if (!isEmpty(name)) {
profileNameFilter = { name: `*${name}*` };
}
query = this.queriesUtil.addAndFilter(query, profileNameFilter);
return this.getDeviceProfiles(query);
}
/**
* @deprecated Use `getDeviceProfilesByDevice` instead as it also considers the supported software types.
*/
getDeviceProfilesByDeviceType(deviceType) {
const deviceTypeFilter = {
__or: [
{ 'c8y_Filter.type': deviceType },
{ 'c8y_Filter.type': '' },
{ __not: { __has: 'c8y_Filter.type' } }
]
};
return this.getDeviceProfiles(deviceTypeFilter);
}
getDeviceProfiles(andQuery) {
let query = {
type: 'c8y_Profile'
};
const filter = {
pageSize: 100,
withTotalPages: true
};
query = this.queriesUtil.addAndFilter(query, andQuery || {});
return this.inventoryService.listQuery(query, filter);
}
async getProfileOperation(deviceId) {
const filter = {
deviceId,
fragmentType: 'c8y_DeviceProfile',
dateFrom: this.dateFrom.toISOString(),
dateTo: this.dateTo.toISOString(),
revert: true,
pageSize: 1
};
const operation = (await this.operationService.list(filter)).data[0];
return operation && operation.status !== OperationStatus.SUCCESSFUL ? operation : undefined;
}
async createProfileOperation(device, deviceProfile) {
let operation;
const operationCfg = {
deviceId: device.id,
profileId: deviceProfile.id,
profileName: deviceProfile.name,
c8y_DeviceProfile: deviceProfile.c8y_DeviceProfile,
description: `Assign device profile ${deviceProfile.name} to device ${device.name}`
};
try {
const { data } = await this.operationService.create(operationCfg);
operation = data;
}
catch (ex) {
this.alertService.addServerFailure(ex);
}
return operation;
}
getFirmwareItems(device, selectedProfile) {
const deviceFirmware = device.c8y_Firmware;
const profileFirmware = get(selectedProfile, 'c8y_DeviceProfile.firmware');
const deviceItems = [];
const profileItems = [];
if (deviceFirmware) {
deviceItems.push(deviceFirmware);
}
if (profileFirmware) {
profileItems.push(profileFirmware);
}
return this.createProfileComparison(deviceItems, profileItems, 'name', 'version', null, this.getAlert('firmware'));
}
getSoftwareItems(device, selectedProfile) {
const deviceSoftware = device.c8y_SoftwareList;
const profileSoftware = get(selectedProfile, 'c8y_DeviceProfile.software');
return this.createProfileComparison(deviceSoftware, profileSoftware, 'name', 'version', 'softwareType', this.getAlert('software'));
}
getConfigurationItems(device, selectedProfile) {
const deviceConfiguration = [];
Object.keys(device).forEach(key => {
if (key.slice(0, 18) === 'c8y_Configuration_') {
deviceConfiguration.push(device[key]);
}
});
const profileConfiguration = get(selectedProfile, 'c8y_DeviceProfile.configuration');
return this.createProfileComparison(deviceConfiguration, profileConfiguration, 'url', null, 'type', this.getAlert('configuration'));
}
/**
* Aligns device profile managed object's `softwareType!*` fragments to the software items
* included in the device profile. Removes obsolete software type fragments and adds new.
*
* @param profilePartial The device profile managed object which `softwareType!*` fragments will be adjusted.
* @returns The adjusted device profile managed object.
*/
alignSoftwareTypeFragments(profilePartial, profile) {
if (!profilePartial?.c8y_DeviceProfile?.software || !profile) {
return profilePartial;
}
const removedSoftwareTypes = mapValues(omitBy(profile, (_, key) => typeof key === 'string' && !key.startsWith('softwareType!')), () => null);
const softwareTypesToAdd = mapValues(keyBy(uniqBy(profilePartial.c8y_DeviceProfile.software, 'softwareType'), (profile) => `softwareType!${profile.softwareType}`), () => ({}));
const result = { ...profilePartial, ...removedSoftwareTypes, ...softwareTypesToAdd };
return result;
}
getSoftwareTypes(profile) {
return keys(pickBy(profile, (_, key) => typeof key === 'string' && key.startsWith('softwareType!'))).map(softwareType => softwareType.substr('softwareType!'.length));
}
getAlert(itemType) {
const notInstalled = (comparisionResult) => {
return !comparisionResult.device ? this.NOT_INSTALLED_WARNING : '';
};
switch (itemType) {
case 'firmware':
case 'software':
return (comparisionResult) => {
return comparisionResult.device &&
comparisionResult.profile &&
comparisionResult.device.itemDetails !== comparisionResult.profile.itemDetails
? this.VERSION_MISSMATCH_WARNING
: notInstalled(comparisionResult);
};
case 'configuration':
return (comparisionResult) => {
return comparisionResult.device &&
comparisionResult.profile &&
(comparisionResult.device.itemName !== comparisionResult.profile.itemName ||
comparisionResult.device.itemDetails !== comparisionResult.profile.itemDetails)
? this.SAME_URL_WARNING
: notInstalled(comparisionResult);
};
default:
return notInstalled;
}
}
createProfileComparison(deviceItems = [], profileItems = [], mergeByProperty, propertyNameWithDetails, propertyNameWithType, getAlert) {
const comparisonObj = this.createProfileComparisonFromDeviceItems(deviceItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType);
const extendedComparisonObj = this.extendProfileComparisonWithProfileItems(comparisonObj, profileItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType, getAlert);
return sortBy(toArray(extendedComparisonObj), 'name');
}
createProfileComparisonFromDeviceItems(deviceItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType) {
return deviceItems.reduce((comapritionItem, deviceItem) => Object.assign(comapritionItem, {
[deviceItem[mergeByProperty]]: {
device: omitBy({
itemName: deviceItem.name,
itemDetails: deviceItem[propertyNameWithDetails],
itemType: deviceItem[propertyNameWithType],
itemUrl: deviceItem.url
}, isNil),
profile: undefined
}
}), {});
}
extendProfileComparisonWithProfileItems(comparisonObj, profileItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType, getAlert) {
profileItems.forEach(profileItem => {
const comparisionResult = {
profile: omitBy({
itemName: profileItem.name,
itemDetails: profileItem[propertyNameWithDetails],
itemType: profileItem[propertyNameWithType],
itemUrl: profileItem.url
}, isNil),
device: comparisonObj[profileItem[mergeByProperty]]
? comparisonObj[profileItem[mergeByProperty]].device
: undefined
};
comparisionResult.comparisonAlert = getAlert(comparisionResult);
comparisonObj[profileItem[mergeByProperty]] = comparisionResult;
});
return comparisonObj;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProfileService, deps: [{ token: i1.InventoryService }, { token: i1.OperationService }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProfileService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProfileService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.InventoryService }, { type: i1.OperationService }, { type: i2.AlertService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLXByb2ZpbGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2RldmljZS1wcm9maWxlL2RldmljZS1wcm9maWxlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBRUwsZ0JBQWdCLEVBR2hCLGdCQUFnQixFQUNoQixlQUFlLEVBQ2YsV0FBVyxFQUNaLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDNUQsT0FBTyxFQUNMLEdBQUcsRUFDSCxPQUFPLEVBQ1AsS0FBSyxFQUNMLEtBQUssRUFDTCxJQUFJLEVBQ0osU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sTUFBTSxFQUNOLE9BQU8sRUFDUCxNQUFNLEVBQ1AsTUFBTSxXQUFXLENBQUM7Ozs7QUFTbkIsTUFBTSxPQUFPLG9CQUFvQjtJQVcvQixZQUNVLGdCQUFrQyxFQUNsQyxnQkFBa0MsRUFDbEMsWUFBMEI7UUFGMUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ2xDLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBYjNCLGFBQVEsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixXQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsc0JBQXNCO1FBR2pFLDBCQUFxQixHQUFHLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBQy9ELDhCQUF5QixHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3hELHFCQUFnQixHQUFHLE9BQU8sQ0FDaEMsaUdBQWlHLENBQ2xHLENBQUM7UUFPQSxJQUFJLENB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Ozs0RkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSU1hbmFnZWRPYmplY3QsXG4gIEludmVudG9yeVNlcnZpY2UsXG4gIElPcGVyYXRpb24sXG4gIElSZXN1bHRMaXN0LFxuICBPcGVyYXRpb25TZXJ2aWNlLFxuICBPcGVyYXRpb25TdGF0dXMsXG4gIFF1ZXJpZXNVdGlsXG59IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IEFsZXJ0U2VydmljZSwgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHtcbiAgZ2V0LFxuICBpc0VtcHR5LFxuICBpc05pbCxcbiAga2V5QnksXG4gIGtleXMsXG4gIG1hcFZhbHVlcyxcbiAgb21pdEJ5LFxuICBwaWNrQnksXG4gIHNvcnRCeSxcbiAgdG9BcnJheSxcbiAgdW5pcUJ5XG59IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQge1xuICBDb21wYXJpc29uUmVzdWx0LFxuICBEZXZpY2VQcm9maWxlLFxuICBEZXZpY2VQcm9maWxlRmlybXdhcmUsXG4gIERldmljZVByb2ZpbGVTb2Z0d2FyZVxufSBmcm9tICcuL2RldmljZS1wcm9maWxlLm1vZGVsJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERldmljZVByb2ZpbGVTZXJ2aWNlIHtcbiAgcmVhZG9ubHkgZGF0ZUZyb20gPSBuZXcgRGF0ZSgwKTtcbiAgcmVhZG9ubHkgZGF0ZVRvID0gbmV3IERhdGUoRGF0ZS5ub3coKSArIDg2NDAwMDAwKTsgLy8gMSBkYXkgaW4gdGhlIGZ1dHVyZVxuICBwcml2YXRlIHF1ZXJpZXNVdGlsOiBRdWVyaWVzVXRpbDtcblxuICBwcml2YXRlIE5PVF9JTlNUQUxMRURfV0FSTklORyA9IGdldHRleHQoJ05vdCBpbnN0YWxsZWQgb24gdGhlIGRldmljZScpO1xuICBwcml2YXRlIFZFUlNJT05fTUlTU01BVENIX1dBUk5JTkcgPSBnZXR0ZXh0KCdWZXJzaW9uIG1pc21hdGNoJyk7XG4gIHByaXZhdGUgU0FNRV9VUkxfV0FSTklORyA9IGdldHRleHQoXG4gICAgJ0luc3RhbGxlZCBjb25maWd1cmF0aW9uIGhhcyB0aGUgc2FtZSBVUkwgYnV0IGRpZmZlcmVudCBuYW1lIG9yIHR5cGUgdGhhbiB0aGUgb25lIGluIHRoZSBwcm9maWxlJ1xuICApO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaW52ZW50b3J5U2VydmljZTogSW52ZW50b3J5U2VydmljZSxcbiAgICBwcml2YXRlIG9wZXJhdGlvblNlcnZpY2U6IE9wZXJhdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhbGVydFNlcnZpY2U6IEFsZXJ0U2VydmljZVxuICApIHtcbiAgICB0aGlzLnF1ZXJpZXNVdGlsID0gbmV3IFF1ZXJpZXNVdGlsKCk7XG4gIH1cblxuICBjcmVhdGVEZXZpY2VQcm9maWxlKGRldmljZVByb2ZpbGU6IFBhcnRpYWw8RGV2aWNlUHJvZmlsZT4pIHtcbiAgICBpZiAoZ2V0KGRldmljZVByb2ZpbGUsICdjOHlfRmlsdGVyLnR5cGUnKSA9PT0gJycpIHtcbiAgICAgIGRlbGV0ZSBkZXZpY2VQcm9maWxlLmM4eV9GaWx0ZXIudHlwZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaW52ZW50b3J5U2VydmljZS5jcmVhdGUoZGV2aWNlUHJvZmlsZSBhcyBJTWFuYWdlZE9iamVjdCk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgYXZhaWxhYmxlIGRldmljZSBwcm9maWxlcyBmb3IgYSBnaXZlbiBkZXZpY2UgYnkgY29uc2lkZXJpbmcgZGV2aWNlIHR5cGVcbiAgICogYW5kIHRoZSBzdXBwb3J0ZWQgc29mdHdhcmUgdHlwZXMgZGVjbGFyZWQgYnkgdGhlIGRldmljZXMuIEJlY2F1c2Ugb2YgbGltaXRhdGlvbnMgaW4gdGhlXG4gICAqIEludmVudG9yeSBRdWVyeSBBUEkgdGhlIG1ldGhvZHMgcmV0dXJuIHByb2ZpbGUgdGhhdCBjb250YWluIGF0IGxlYXN0IG9uZSBvZiB0aGUgc3VwcG9ydGVkXG4gICAqIHNvZnR3YXJlIHR5cGVzIGFuZCBvbWl0cyBwcm9maWxlcyBoYXZpbmcgb25seSBub24tc3VwcG9ydGVkIHNvZnR3YXJlIHR5cGVzLiBSZXN1bHRpbmcgZGV2aWNlXG4gICAqIHByb2ZpbGVzIG5lZWQgdG8gYmUgZnVydGhlciBmaWx0ZXJlZCBvbiB0aGUgY2xpZW50IHNpZGUgdG8gZXhjbHVkZSB0aGUgb25lcyB0aGF0IGNvbnRhaW5cbiAgICogbm9uLXN1cHBvcnRlZCBzb2Z0d2FyZSB0eXBlcyBuZXh0IHRvIHRoZSBzdXBwb3J0ZWQgb25lcy5cbiAgICpcbiAgICogQHBhcmFtIGRldmljZSBBIGRldmljZSBNT1xuICAgKiBAcGFyYW0gbmFtZSBPcHRpb25hbCBkZXZpY2UgcHJvZmlsZSBuYW1lIGZpbHRlclxuICAgKiBAcmV0dXJucyBDYW5kaWRhdGUgZGV2aWNlIHByb2ZpbGVzIHRoYXQgY29udGFpbiBhdCBsZWFzdCBvbiBzb2Z0d2FyZSB3aXRoIHN1cHBvcnRlZCB0eXBlLlxuICAgKi9cbiAgZ2V0RGV2aWNlUHJvZmlsZXNCeURldmljZShcbiAgICBkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LFxuICAgIG5hbWU6IHN0cmluZyA9IG51bGxcbiAgKTogUHJvbWlzZTxJUmVzdWx0TGlzdDxJTWFuYWdlZE9iamVjdD4+IHtcbiAgICBjb25zdCBkZXZpY2VUeXBlRmlsdGVyID0ge1xuICAgICAgX19vcjogW1xuICAgICAgICB7ICdjOHlfRmlsdGVyLnR5cGUnOiBkZXZpY2UudHlwZSB9LFxuICAgICAgICB7ICdjOHlfRmlsdGVyLnR5cGUnOiAnJyB9LFxuICAgICAgICB7IF9fbm90OiB7IF9faGFzOiAnYzh5X0ZpbHRlci50eXBlJyB9IH1cbiAgICAgIF1cbiAgICB9O1xuXG4gICAgbGV0IHNvZnR3YXJlVHlwZUZpbHRlciA9IHt9O1xuICAgIGlmICghaXNFbXB0eShkZXZpY2UuYzh5X1N1cHBvcnRlZFNvZnR3YXJlVHlwZXMpKSB7XG4gICAgICBzb2Z0d2FyZVR5cGVGaWx0ZXIgPSB7XG4gICAgICAgIF9faGFzYW55OiBkZXZpY2UuYzh5X1N1cHBvcnRlZFNvZnR3YXJlVHlwZXMubWFwKCh0eXBlOiBzdHJpbmcpID0+IGBzb2Z0d2FyZVR5cGUhJHt0eXBlfWApXG4gICAgICB9O1xuICAgIH1cbiAgICBsZXQgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihkZXZpY2VUeXBlRmlsdGVyLCBzb2Z0d2FyZVR5cGVGaWx0ZXIpO1xuXG4gICAgbGV0IHByb2ZpbGVOYW1lRmlsdGVyID0ge307XG4gICAgaWYgKCFpc0VtcHR5KG5hbWUpKSB7XG4gICAgICBwcm9maWxlTmFtZUZpbHRlciA9IHsgbmFtZTogYCoke25hbWV9KmAgfTtcbiAgICB9XG4gICAgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihxdWVyeSwgcHJvZmlsZU5hbWVGaWx0ZXIpO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2V0RGV2aWNlUHJvZmlsZXMocXVlcnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIFVzZSBgZ2V0RGV2aWNlUHJvZmlsZXNCeURldmljZWAgaW5zdGVhZCBhcyBpdCBhbHNvIGNvbnNpZGVycyB0aGUgc3VwcG9ydGVkIHNvZnR3YXJlIHR5cGVzLlxuICAgKi9cbiAgZ2V0RGV2aWNlUHJvZmlsZXNCeURldmljZVR5cGUoZGV2aWNlVHlwZTogc3RyaW5nKTogUHJvbWlzZTxJUmVzdWx0TGlzdDxJTWFuYWdlZE9iamVjdD4+IHtcbiAgICBjb25zdCBkZXZpY2VUeXBlRmlsdGVyID0ge1xuICAgICAgX19vcjogW1xuICAgICAgICB7ICdjOHlfRmlsdGVyLnR5cGUnOiBkZXZpY2VUeXBlIH0sXG4gICAgICAgIHsgJ2M4eV9GaWx0ZXIudHlwZSc6ICcnIH0sXG4gICAgICAgIHsgX19ub3Q6IHsgX19oYXM6ICdjOHlfRmlsdGVyLnR5cGUnIH0gfVxuICAgICAgXVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuZ2V0RGV2aWNlUHJvZmlsZXMoZGV2aWNlVHlwZUZpbHRlcik7XG4gIH1cblxuICBnZXREZXZpY2VQcm9maWxlcyhhbmRRdWVyeT86IGFueSk6IFByb21pc2U8SVJlc3VsdExpc3Q8SU1hbmFnZWRPYmplY3Q+PiB7XG4gICAgbGV0IHF1ZXJ5OiBvYmplY3QgPSB7XG4gICAgICB0eXBlOiAnYzh5X1Byb2ZpbGUnXG4gICAgfTtcbiAgICBjb25zdCBmaWx0ZXI6IG9iamVjdCA9IHtcbiAgICAgIHBhZ2VTaXplOiAxMDAsXG4gICAgICB3aXRoVG90YWxQYWdlczogdHJ1ZVxuICAgIH07XG4gICAgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihxdWVyeSwgYW5kUXVlcnkgfHwge30pO1xuICAgIHJldHVybiB0aGlzLmludmVudG9yeVNlcnZpY2UubGlzdFF1ZXJ5KHF1ZXJ5LCBmaWx0ZXIpO1xuICB9XG5cbiAgYXN5bmMgZ2V0UHJvZmlsZU9wZXJhdGlvbihkZXZpY2VJZDogc3RyaW5nIHwgbnVtYmVyKSB7XG4gICAgY29uc3QgZmlsdGVyOiBvYmplY3QgPSB7XG4gICAgICBkZXZpY2VJZCxcbiAgICAgIGZyYWdtZW50VHlwZTogJ2M4eV9EZXZpY2VQcm9maWxlJyxcbiAgICAgIGRhdGVGcm9tOiB0aGlzLmRhdGVGcm9tLnRvSVNPU3RyaW5nKCksXG4gICAgICBkYXRlVG86IHRoaXMuZGF0ZVRvLnRvSVNPU3RyaW5nKCksXG4gICAgICByZXZlcnQ6IHRydWUsXG4gICAgICBwYWdlU2l6ZTogMVxuICAgIH07XG5cbiAgICBjb25zdCBvcGVyYXRpb24gPSAoYXdhaXQgdGhpcy5vcGVyYXRpb25TZXJ2aWNlLmxpc3QoZmlsdGVyKSkuZGF0YVswXTtcbiAgICByZXR1cm4gb3BlcmF0aW9uICYmIG9wZXJhdGlvbi5zdGF0dXMgIT09IE9wZXJhdGlvblN0YXR1cy5TVUNDRVNTRlVMID8gb3BlcmF0aW9uIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlUHJvZmlsZU9wZXJhdGlvbihkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LCBkZXZpY2VQcm9maWxlOiBQYXJ0aWFsPERldmljZVByb2ZpbGU+KSB7XG4gICAgbGV0IG9wZXJhdGlvbjtcbiAgICBjb25zdCBvcGVyYXRpb25DZmc6IElPcGVyYXRpb24gPSB7XG4gICAgICBkZXZpY2VJZDogZGV2aWNlLmlkLFxuICAgICAgcHJvZmlsZUlkOiBkZXZpY2VQcm9maWxlLmlkLFxuICAgICAgcHJvZmlsZU5hbWU6IGRldmljZVByb2ZpbGUubmFtZSxcbiAgICAgIGM4eV9EZXZpY2VQcm9maWxlOiBkZXZpY2VQcm9maWxlLmM4eV9EZXZpY2VQcm9maWxlLFxuICAgICAgZGVzY3JpcHRpb246IGBBc3NpZ24gZGV2aWNlIHByb2ZpbGUgJHtkZXZpY2VQcm9maWxlLm5hbWV9IHRvIGRldmljZSAke2RldmljZS5uYW1lfWBcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IHRoaXMub3BlcmF0aW9uU2VydmljZS5jcmVhdGUob3BlcmF0aW9uQ2ZnKTtcbiAgICAgIG9wZXJhdGlvbiA9IGRhdGE7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmFkZFNlcnZlckZhaWx1cmUoZXgpO1xuICAgIH1cbiAgICByZXR1cm4gb3BlcmF0aW9uO1xuICB9XG5cbiAgZ2V0RmlybXdhcmVJdGVtcyhcbiAgICBkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LFxuICAgIHNlbGVjdGVkUHJvZmlsZTogUGFydGlhbDxEZXZpY2VQcm9maWxlPlxuICApOiBDb21wYXJpc29uUmVzdWx0W10ge1xuICAgIGNvbnN0IGRldmljZUZpcm13YXJlID0gZGV2aWNlLmM4eV9GaXJtd2FyZTtcbiAgICBjb25zdCBwcm9maWxlRmlybXdhcmUgPSBnZXQoc2VsZWN0ZWRQcm9maWxlLCAnYzh5X0RldmljZVByb2ZpbGUuZmlybXdhcmUnKTtcbiAgICBjb25zdCBkZXZpY2VJdGVtcyA9IFtdO1xuICAgIGNvbnN0IHByb2ZpbGVJdGVtcyA9IFtdO1xuXG4gICAgaWYgKGRldmljZUZpcm13YXJlKSB7XG4gICAgICBkZXZpY2VJdGVtcy5wdXNoKGRldmljZUZpcm13YXJlKTtcbiAgICB9XG4gICAgaWYgKHByb2ZpbGVGaXJtd2FyZSkge1xuICAgICAgcHJvZmlsZUl0ZW1zLnB1c2gocHJvZmlsZUZpcm13YXJlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlUHJvZmlsZUNvbXBhcmlzb24oXG4gICAgICBkZXZpY2VJdGVtcyxcbiAgICAgIHByb2ZpbGVJdGVtcyxcbiAgICAgICduYW1lJyxcbiAgICAgICd2ZXJzaW9uJyxcbiAgICAgIG51bGwsXG4gICAgICB0aGlzLmdldEFsZXJ0KCdmaXJtd2FyZScpXG4gICAgKTtcbiAgfVxuXG4gIGdldFNvZnR3YXJlSXRlbXMoXG4gICAgZGV2aWNlOiBJTWFuYWdlZE9iamVjdCxcbiAgICBzZWxlY3RlZFByb2ZpbGU6IFBhcnRpYWw8RGV2aWNlUHJvZmlsZT5cbiAgKTogQ29tcGFyaXNvblJlc3VsdFtdIHtcbiAgICBjb25zdCBkZXZpY2VTb2Z0d2FyZSA9IGRldmljZS5jOHlfU29mdHdhcmVMaXN0O1xuICAgIGNvbnN0IHByb2ZpbGVTb2Z0d2FyZSA9IGdldChzZWxlY3RlZFByb2ZpbGUsICdjOHlfRGV2aWNlUHJvZmlsZS5zb2Z0d2FyZScpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVByb2ZpbGVDb21wYXJpc29uKFxuICAgICAgZGV2aWNlU29mdHdhcmUsXG4gICAgICBwcm9maWxlU29mdHdhcmUsXG4gICAgICAnbmFtZScsXG4gICAgICAndmVyc2lvbicsXG4gICAgICAnc29mdHdhcmVUeXBlJyxcbiAgICAgIHRoaXMuZ2V0QWxlcnQoJ3NvZnR3YXJlJylcbiAgICApO1xuICB9XG5cbiAgZ2V0Q29uZmlndXJhdGlvbkl0ZW1zKFxuICAgIGRldmljZTogSU1hbmFnZWRPYmplY3QsXG4gICAgc2VsZWN0ZWRQcm9maWxlOiBQYXJ0aWFsPERldmljZVByb2ZpbGU+XG4gICk6IENvbXBhcmlzb25SZXN1bHRbXSB7XG4gICAgY29uc3QgZGV2aWNlQ29uZmlndXJhdGlvbiA9IFtdO1xuICAgIE9iamVjdC5rZXlzKGRldmljZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgaWYgKGtleS5zbGljZSgwLCAxOCkgPT09ICdjOHlfQ29uZmlndXJhdGlvbl8nKSB7XG4gICAgICAgIGRldmljZUNvbmZpZ3VyYXRpb24ucHVzaChkZXZpY2Vba2V5XSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uc3QgcHJvZmlsZUNvbmZpZ3VyYXRpb24gPSBnZXQoc2VsZWN0ZWRQcm9maWxlLCAnYzh5X0RldmljZVByb2ZpbGUuY29uZmlndXJhdGlvbicpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVByb2ZpbGVDb21wYXJpc29uKFxuICAgICAgZGV2aWNlQ29uZmlndXJhdGlvbixcbiAgICAgIHByb2ZpbGVDb25maWd1cmF0aW9uLFxuICAgICAgJ3VybCcsXG4gICAgICBudWxsLFxuICAgICAgJ3R5cGUnLFxuICAgICAgdGhpcy5nZXRBbGVydCgnY29uZmlndXJhdGlvbicpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGlnbnMgZGV2aWNlIHByb2ZpbGUgbWFuYWdlZCBvYmplY3QncyBgc29mdHdhcmVUeXBlISpgIGZyYWdtZW50cyB0byB0aGUgc29mdHdhcmUgaXRlbXNcbiAgICogaW5jbHVkZWQgaW4gdGhlIGRldmljZSBwcm9maWxlLiBSZW1vdmVzIG9ic29sZXRlIHNvZnR3YXJlIHR5cGUgZnJhZ21lbnRzIGFuZCBhZGRzIG5ldy5cbiAgICpcbiAgICogQHBhcmFtIHByb2ZpbGVQYXJ0aWFsIFRoZSBkZXZpY2UgcHJvZmlsZSBtYW5hZ2VkIG9iamVjdCB3aGljaCBgc29mdHdhcmVUeXBlISpgIGZyYWdtZW50cyB3aWxsIGJlIGFkanVzdGVkLlxuICAgKiBAcmV0dXJucyBUaGUgYWRqdXN0ZWQgZGV2aWNlIHByb2ZpbGUgbWFuYWdlZCBvYmplY3QuXG4gICAqL1xuICBhbGlnblNvZnR3YXJlVHlwZUZyYWdtZW50cyhcbiAgICBwcm9maWxlUGFydGlhbDogUGFydGlhbDxEZXZpY2VQcm9maWxlPixcbiAgICBwcm9maWxlOiBEZXZpY2VQcm9maWxlXG4gICk6IFBhcnRpYWw8RGV2aWNlUHJvZmlsZT4ge1xuICAgIGlmICghcHJvZmlsZVBhcnRpYWw/LmM4eV9EZXZpY2VQcm9maWxlPy5zb2Z0d2FyZSB8fCAhcHJvZmlsZSkge1xuICAgICAgcmV0dXJuIHByb2ZpbGVQYXJ0aWFsO1xuICAgIH1cblxuICAgIGNvbnN0IHJlbW92ZWRTb2Z0d2FyZVR5cGVzID0gbWFwVmFsdWVzKFxuICAgICAgb21pdEJ5KFxuICAgICAgICBwcm9maWxlLFxuICAgICAgICAoXzogdW5rbm93biwga2V5OiBQcm9wZXJ0eUtleSkgPT5cbiAgICAgICAgICB0eXBlb2Yga2V5ID09PSAnc3RyaW5nJyAmJiAha2V5LnN0YXJ0c1dpdGgoJ3NvZnR3YXJlVHlwZSEnKVxuICAgICAgKSxcbiAgICAgICgpID0+IG51bGxcbiAgICApO1xuICAgIGNvbnN0IHNvZnR3YXJlVHlwZXNUb0FkZDogeyBba2V5OiBQcm9wZXJ0eUtleV06IFJlY29yZDxQcm9wZXJ0eUtleSwgbmV2ZXI+IH0gPSBtYXBWYWx1ZXMoXG4gICAgICBrZXlCeShcbiAgICAgICAgdW5pcUJ5KHByb2ZpbGVQYXJ0aWFsLmM4eV9EZXZpY2VQcm9maWxlLnNvZnR3YXJlLCAnc29mdHdhcmVUeXBlJyksXG4gICAgICAgIChwcm9maWxlOiBEZXZpY2VQcm9maWxlU29mdHdhcmUpID0+IGBzb2Z0d2FyZVR5cGUhJHtwcm9maWxlLnNvZnR3YXJlVHlwZX1gXG4gICAgICApLFxuICAgICAgKCkgPT4gKHt9KVxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHQgPSB7IC4uLnByb2ZpbGVQYXJ0aWFsLCAuLi5yZW1vdmVkU29mdHdhcmVUeXBlcywgLi4uc29mdHdhcmVUeXBlc1RvQWRkIH07XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGdldFNvZnR3YXJlVHlwZXMocHJvZmlsZTogRGV2aWNlUHJvZmlsZSk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4ga2V5cyhcbiAgICAgIHBpY2tCeShcbiAgICAgICAgcHJvZmlsZSxcbiAgICAgICAgKF86IHVua25vd24sIGtleTogUHJvcGVydHlLZXkpID0+IHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnICYmIGtleS5zdGFydHNXaXRoKCdzb2Z0d2FyZVR5cGUhJylcbiAgICAgIClcbiAgICApLm1hcChzb2Z0d2FyZVR5cGUgPT4gc29mdHdhcmVUeXBlLnN1YnN0cignc29mdHdhcmVUeXBlIScubGVuZ3RoKSk7XG4gIH1cblxuICBwcml2YXRlIGdldEFsZXJ0KGl0ZW1UeXBlOiBzdHJpbmcpOiAoY29tcGFyaXNpb25SZXN1bHQ6IENvbXBhcmlzb25SZXN1bHQpID0+IHN0cmluZyB7XG4gICAgY29uc3Qgbm90SW5zdGFsbGVkID0gKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiB7XG4gICAgICByZXR1cm4gIWNvbXBhcmlzaW9uUmVzdWx0LmRldmljZSA/IHRoaXMuTk9UX0lOU1RBTExFRF9XQVJOSU5HIDogJyc7XG4gICAgfTtcblxuICAgIHN3aXRjaCAoaXRlbVR5cGUpIHtcbiAgICAgIGNhc2UgJ2Zpcm13YXJlJzpcbiAgICAgIGNhc2UgJ3NvZnR3YXJlJzpcbiAgICAgICAgcmV0dXJuIChjb21wYXJpc2lvblJlc3VsdDogQ29tcGFyaXNvblJlc3VsdCkgPT4ge1xuICAgICAgICAgIHJldHVybiBjb21wYXJpc2lvblJlc3VsdC5kZXZpY2UgJiZcbiAgICAgICAgICAgIGNvbXBhcmlzaW9uUmVzdWx0LnByb2ZpbGUgJiZcbiAgICAgICAgICAgIGNvbXBhcmlzaW9uUmVzdWx0LmRldmljZS5pdGVtRGV0YWlscyAhPT0gY29tcGFyaXNpb25SZXN1bHQucHJvZmlsZS5pdGVtRGV0YWlsc1xuICAgICAgICAgICAgPyB0aGlzLlZFUlNJT05fTUlTU01BVENIX1dBUk5JTkdcbiAgICAgICAgICAgIDogbm90SW5zdGFsbGVkKGNvbXBhcmlzaW9uUmVzdWx0KTtcbiAgICAgICAgfTtcbiAgICAgIGNhc2UgJ2NvbmZpZ3VyYXRpb24nOlxuICAgICAgICByZXR1cm4gKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGNvbXBhcmlzaW9uUmVzdWx0LmRldmljZSAmJlxuICAgICAgICAgICAgY29tcGFyaXNpb25SZXN1bHQucHJvZmlsZSAmJlxuICAgICAgICAgICAgKGNvbXBhcmlzaW9uUmVzdWx0LmRldmljZS5pdGVtTmFtZSAhPT0gY29tcGFyaXNpb25SZXN1bHQucHJvZmlsZS5pdGVtTmFtZSB8fFxuICAgICAgICAgICAgICBjb21wYXJpc2lvblJlc3VsdC5kZXZpY2UuaXRlbURldGFpbHMgIT09IGNvbXBhcmlzaW9uUmVzdWx0LnByb2ZpbGUuaXRlbURldGFpbHMpXG4gICAgICAgICAgICA/IHRoaXMuU0FNRV9VUkxfV0FSTklOR1xuICAgICAgICAgICAgOiBub3RJbnN0YWxsZWQoY29tcGFyaXNpb25SZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIG5vdEluc3RhbGxlZDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVByb2ZpbGVDb21wYXJpc29uKFxuICAgIGRldmljZUl0ZW1zOiBhbnlbXSA9IFtdLFxuICAgIHByb2ZpbGVJdGVtczogQXJyYXk8RGV2aWNlUHJvZmlsZVNvZnR3YXJlIHwgRGV2aWNlUHJvZmlsZUZpcm13YXJlPiA9IFtdLFxuICAgIG1lcmdlQnlQcm9wZXJ0eTogc3RyaW5nLFxuICAgIHByb3BlcnR5TmFtZVdpdGhEZXRhaWxzOiBzdHJpbmcsXG4gICAgcHJvcGVydHlOYW1lV2l0aFR5cGU6IHN0cmluZyxcbiAgICBnZXRBbGVydDogKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiBzdHJpbmdcbiAgKTogQ29tcGFyaXNvblJlc3VsdFtdIHtcbiAgICBjb25zdCBjb21wYXJpc29uT2JqID0gdGhpcy5jcmVhdGVQcm9maWxlQ29tcGFyaXNvbkZyb21EZXZpY2VJdGVtcyhcbiAgICAgIGRldmljZUl0ZW1zLFxuICAgICAgbWVyZ2VCeVByb3BlcnR5LFxuICAgICAgcHJvcGVydHlOYW1lV2l0aERldGFpbHMsXG4gICAgICBwcm9wZXJ0eU5hbWVXaXRoVHlwZVxuICAgICk7XG4gICAgY29uc3QgZXh0ZW5kZWRDb21wYXJpc29uT2JqID0gdGhpcy5leHRlbmRQcm9maWxlQ29tcGFyaXNvbldpdGhQcm9maWxlSXRlbXMoXG4gICAgICBjb21wYXJpc29uT2JqLFxuICAgICAgcHJvZmlsZUl0ZW1zLFxuICAgICAgbWVyZ2VCeVByb3BlcnR5LFxuICAgICAgcHJvcGVydHlOYW1lV2l0aERldGFpbHMsXG4gICAgICBwcm9wZXJ0eU5hbWVXaXRoVHlwZSxcbiAgICAgIGdldEFsZXJ0XG4gICAgKTtcbiAgICByZXR1cm4gc29ydEJ5KHRvQXJyYXkoZXh0ZW5kZWRDb21wYXJpc29uT2JqKSwgJ25hbWUnKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUHJvZmlsZUNvbXBhcmlzb25Gcm9tRGV2aWNlSXRlbXMoXG4gICAgZGV2aWNlSXRlbXM6IGFueVtdLFxuICAgIG1lcmdlQnlQcm9wZXJ0eTogc3RyaW5nLFxuICAgIHByb3BlcnR5TmFtZVdpdGhEZXRhaWxzOiBzdHJpbmcsXG4gICAgcHJvcGVydHlOYW1lV2l0aFR5cGU6IHN0cmluZ1xuICApOiBhbnkge1xuICAgIHJldHVybiBkZXZpY2VJdGVtcy5yZWR1Y2UoXG4gICAgICAoY29tYXByaXRpb25JdGVtLCBkZXZpY2VJdGVtKSA9PlxuICAgICAgICBPYmplY3QuYXNzaWduKGNvbWFwcml0aW9uSXRlbSwge1xuICAgICAgICAgIFtkZXZpY2VJdGVtW21lcmdlQnlQcm9wZXJ0eV1dOiB7XG4gICAgICAgICAgICBkZXZpY2U6IG9taXRCeShcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGl0ZW1OYW1lOiBkZXZpY2VJdGVtLm5hbWUsXG4gICAgICAgICAgICAgICAgaXRlbURldGFpbHM6IGRldmljZUl0ZW1bcHJvcGVydHlOYW1lV2l0aERldGFpbHNdLFxuICAgICAgICAgICAgICAgIGl0ZW1UeXBlOiBkZXZpY2VJdGVtW3Byb3BlcnR5TmFtZVdpdGhUeXBlXSxcbiAgICAgICAgICAgICAgICBpdGVtVXJsOiBkZXZpY2VJdGVtLnVybFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBpc05pbFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHByb2ZpbGU6IHVuZGVmaW5lZFxuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICB7fVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGV4dGVuZFByb2ZpbGVDb21wYXJpc29uV2l0aFByb2ZpbGVJdGVtcyhcbiAgICBjb21wYXJpc29uT2JqOiBvYmplY3QsXG4gICAgcHJvZmlsZUl0ZW1zOiBBcnJheTxEZXZpY2VQcm9maWxlU29mdHdhcmUgfCBEZXZpY2VQcm9maWxlRmlybXdhcmU+LFxuICAgIG1lcmdlQnlQcm9wZXJ0eTogc3RyaW5nLFxuICAgIHByb3BlcnR5TmFtZVdpdGhEZXRhaWxzOiBzdHJpbmcsXG4gICAgcHJvcGVydHlOYW1lV2l0aFR5cGU6IHN0cmluZyxcbiAgICBnZXRBbGVydDogKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiBzdHJpbmdcbiAgKSB7XG4gICAgcHJvZmlsZUl0ZW1zLmZvckVhY2gocHJvZmlsZUl0ZW0gPT4ge1xuICAgICAgY29uc3QgY29tcGFyaXNpb25SZXN1bHQ6IENvbXBhcmlzb25SZXN1bHQgPSB7XG4gICAgICAgIHByb2ZpbGU6IG9taXRCeShcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpdGVtTmFtZTogcHJvZmlsZUl0ZW0ubmFtZSxcbiAgICAgICAgICAgIGl0ZW1EZXRhaWxzOiBwcm9maWxlSXRlbVtwcm9wZXJ0eU5hbWVXaXRoRGV0YWlsc10sXG4gICAgICAgICAgICBpdGVtVHlwZTogcHJvZmlsZUl0ZW1bcHJvcGVydHlOYW1lV2l0aFR5cGVdLFxuICAgICAgICAgICAgaXRlbVVybDogcHJvZmlsZUl0ZW0udXJsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBpc05pbFxuICAgICAgICApLFxuICAgICAgICBkZXZpY2U6IGNvbXBhcmlzb25PYmpbcHJvZmlsZUl0ZW1bbWVyZ2VCeVByb3BlcnR5XV1cbiAgICAgICAgICA/IGNvbXBhcmlzb25PYmpbcHJvZmlsZUl0ZW1bbWVyZ2VCeVByb3BlcnR5XV0uZGV2aWNlXG4gICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgICBjb21wYXJpc2lvblJlc3VsdC5jb21wYXJpc29uQWxlcnQgPSBnZXRBbGVydChjb21wYXJpc2lvblJlc3VsdCk7XG4gICAgICBjb21wYXJpc29uT2JqW3Byb2ZpbGVJdGVtW21lcmdlQnlQcm9wZXJ0eV1dID0gY29tcGFyaXNpb25SZXN1bHQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbXBhcmlzb25PYmo7XG4gIH1cbn1cbiJdfQ==