truly-ui
Version:
Web Components for Desktop Applications.
210 lines • 30.6 kB
JavaScript
import { Injectable } from '@angular/core';
import { Cluster, Graph, Node } from '../types/graph';
import { elvis } from '../../core/helper/elvis';
import * as i0 from "@angular/core";
const WIDTH_SCROLL = 17;
export class GenerateEventsService {
constructor() {
this.heightSchedule = 0;
this.widthSchedule = 0;
this.events = [];
this.originalEvents = [];
this.workScaleInMileseconds = [];
}
with(events) {
if (this.scheduleSlats) {
if (events.length > 0 && this.scheduleSlats.length > 0) {
this.originalEvents = JSON.parse(JSON.stringify(events));
events = JSON.parse(JSON.stringify(events));
this.events = events;
this.transformDateToPixel();
return this.generateEvents();
}
}
}
initializeArray(workScaleInMileseconds, scheduleSlats) {
if (scheduleSlats && scheduleSlats) {
if (scheduleSlats.length > 0 && workScaleInMileseconds.length > 0) {
this.workScaleInMileseconds = workScaleInMileseconds;
this.scheduleSlats = scheduleSlats;
this.scheduleSlats.toArray().forEach((item) => {
this.heightSchedule = this.heightSchedule + item.nativeElement.offsetHeight;
});
this.widthSchedule = this.scheduleSlats.first.nativeElement.offsetWidth - WIDTH_SCROLL;
}
}
}
transformDateToPixel() {
for (let i = 0; i <= this.events.length - 1; i++) {
this.events[i].date = Object.assign({}, {
start: Math.round(this.convertMillisecondsToPixel(this.events[i].date.start)),
end: Math.round(this.convertMillisecondsToPixel(this.events[i].date.end))
});
}
}
convertMillisecondsToPixel(date = new Date().getTime()) {
let heightBody;
let startDayMilliseconds;
let endDayMilliseconds;
let converted;
let currentDate;
let position = -1;
let offsetHeight = 0;
this.workScaleInMileseconds.forEach((item, index, array) => {
if (date >= this.workScaleInMileseconds[index].start) {
position++;
const slotObject = this.scheduleSlats.find((slot, idx) => idx === (index - 1));
offsetHeight = offsetHeight + elvis(slotObject, 'nativeElement.offsetHeight') || 0;
}
});
if (position < 0 && offsetHeight <= 0) {
return -1000;
}
startDayMilliseconds = Math.floor(this.workScaleInMileseconds[position].start / 100000);
endDayMilliseconds = Math.floor(this.workScaleInMileseconds[position].end / 100000);
heightBody = elvis(this.scheduleSlats.find((item, idx) => idx === position), 'nativeElement.offsetHeight') || 0;
date = Math.floor(date / 100000);
currentDate = date - startDayMilliseconds;
converted = (heightBody * currentDate) / (endDayMilliseconds - startDayMilliseconds);
return converted > heightBody ? -1000 : (converted + offsetHeight);
}
generateEvents() {
const eventsWithPositioning = [];
const histogram = this.createHistogram();
const graph = this.createTheGraph(histogram);
this.setClusterWidth(graph);
this.setNodesPosition(graph);
for (const nodeId in graph.nodes) {
if (graph.nodes.hasOwnProperty(nodeId)) {
if (graph.nodes[nodeId].cluster) {
const node = graph.nodes[nodeId];
const event = {
positions: {
id: node.id,
top: node.start,
left: node.position * node.cluster.width,
height: node.end - node.start,
width: node.cluster.width
},
data: this.originalEvents.filter((e) => e.value === node.id)[0]
};
eventsWithPositioning.push(event);
}
}
}
return eventsWithPositioning;
}
createHistogram() {
// initializing the minutes array
const minutes = new Array(this.heightSchedule);
for (let i = 0; i < minutes.length; i++) {
minutes[i] = [];
}
// setting which events occurs at each minute
this.events.forEach((event) => {
for (let i = event.date.start; i <= event.date.end - 1; i++) {
if (minutes[i]) {
minutes[i].push(event.value);
}
}
});
return minutes;
}
createTheGraph(minutes) {
const graph = new Graph();
const nodeMap = {};
// creating the nodes
this.events.forEach((event) => {
const node = new Node(event.value, event.date.start, event.date.end);
nodeMap[node.id] = node;
});
// creating the clusters
let cluster = null;
// cluster is a group of nodes which have a connectivity path, when the minute array length is 0 it means that
// there are n more nodes in the cluster - cluster can be "closed".
minutes.forEach((minute, index, arrayMinutes) => {
if (minute.length > 0) {
if (arrayMinutes[index - 1]) {
if ((minute[0] !== arrayMinutes[index - 1][0]) && (minute.length !== arrayMinutes[index - 1].length) && cluster) {
graph.clusters.push(cluster);
cluster = null;
}
}
cluster = cluster || new Cluster();
minute.forEach((eventId) => {
if (!cluster.nodes[eventId]) {
cluster.nodes[eventId] = nodeMap[eventId];
nodeMap[eventId].cluster = cluster;
}
});
}
else {
if (cluster !== null) {
graph.clusters.push(cluster);
}
cluster = null;
}
});
if (cluster !== null) {
graph.clusters.push(cluster);
}
// adding neighbours to nodes, neighbours is the group of colliding nodes (events).
// adding the biggest clique for each site
minutes.forEach((minute) => {
minute.forEach((eventId) => {
const sourceNode = nodeMap[eventId];
// a max clique is a biggest group of colliding events
sourceNode.biggestCliqueSize = Math.max(sourceNode.biggestCliqueSize, minute.length);
minute.forEach((targetEventId) => {
if (eventId !== targetEventId) {
sourceNode.neighbours[targetEventId] = nodeMap[targetEventId];
}
});
});
});
graph.nodes = nodeMap;
return graph;
}
setClusterWidth(graph) {
graph.clusters.forEach((cluster) => {
let maxCliqueSize = 1;
for (const nodeId in cluster.nodes) {
if (cluster.nodes.hasOwnProperty(nodeId)) {
maxCliqueSize = Math.max(maxCliqueSize, cluster.nodes[nodeId].biggestCliqueSize);
}
}
cluster.maxCliqueSize = maxCliqueSize;
cluster.width = this.widthSchedule / (maxCliqueSize);
});
}
setNodesPosition(graph) {
graph.clusters.forEach((cluster) => {
for (const nodeId in cluster.nodes) {
if (cluster.nodes.hasOwnProperty(nodeId)) {
const node = cluster.nodes[nodeId];
const positionArray = new Array(node.cluster.maxCliqueSize);
for (const neighbourId in node.neighbours) {
if (node.neighbours.hasOwnProperty(neighbourId)) {
const neighbour = node.neighbours[neighbourId];
if (neighbour.position != null) {
positionArray[neighbour.position] = true;
}
}
}
for (let i = 0; i < positionArray.length; i++) {
if (!positionArray[i]) {
node.position = i;
break;
}
}
}
}
});
}
}
/** @nocollapse */ GenerateEventsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GenerateEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ GenerateEventsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GenerateEventsService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GenerateEventsService, decorators: [{
type: Injectable
}], ctorParameters: function () { return []; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGUtZXZlbnRzLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90cnVseS11aS9zcmMvY29tcG9uZW50cy9zY2hlZHVsZS9zZXJ2aWNlcy9nZW5lcmF0ZS1ldmVudHMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7QUFHaEQsTUFBTSxZQUFZLEdBQUcsRUFBRSxDQUFDO0FBR3hCLE1BQU0sT0FBTyxxQkFBcUI7SUFjaEM7UUFaUSxtQkFBYyxHQUFHLENBQUMsQ0FBQztRQUVuQixrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUVsQixXQUFNLEdBQUcsRUFBRSxDQUFDO1FBRVosbUJBQWMsR0FBRyxFQUFFLENBQUM7UUFFcEIsMkJBQXNCLEdBQUcsRUFBRSxDQUFDO0lBSXJCLENBQUM7SUFFaEIsSUFBSSxDQUFHLE1BQTRCO1FBQ2pDLElBQU0sSUFBSSxDQUFDLGFBQWEsRUFBRztZQUN6QixJQUFLLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRztnQkFDeEQsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFFLElBQUksQ0FBQyxTQUFTLENBQUUsTUFBTSxDQUFFLENBQUUsQ0FBQztnQkFDN0QsTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBRSxNQUFNLENBQUUsQ0FBRSxDQUFDO2dCQUVoRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztnQkFDckIsSUFBSSxDQUFDLG9C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QyxRQUFRLENBQUMsT0FBTyxDQUFFLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDbEMsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFO2dCQUNsQyxJQUFLLE9BQU8sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFHO29CQUMxQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUNuQyxNQUFNLGFBQWEsR0FBRyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO29CQUU1RCxLQUFLLE1BQU0sV0FBVyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7d0JBQ3pDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLEVBQUU7NEJBQy9DLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7NEJBQy9DLElBQUksU0FBUyxDQUFDLFFBQVEsSUFBSSxJQUFJLEVBQUU7Z0NBQzlCLGFBQWEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsSUFBSSxDQUFDOzZCQUMxQzt5QkFDRjtxQkFDRjtvQkFFRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTt3QkFDN0MsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRTs0QkFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7NEJBQ2xCLE1BQU07eUJBQ1A7cUJBQ0Y7aUJBQ0Y7YUFDRjtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7c0lBNU9VLHFCQUFxQjswSUFBckIscUJBQXFCOzRGQUFyQixxQkFBcUI7a0JBRGpDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBRdWVyeUxpc3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENsdXN0ZXIsIEdyYXBoLCBOb2RlIH0gZnJvbSAnLi4vdHlwZXMvZ3JhcGgnO1xuaW1wb3J0IHsgZWx2aXMgfSBmcm9tICcuLi8uLi9jb3JlL2hlbHBlci9lbHZpcyc7XG5pbXBvcnQgeyBTY2hlZHVsZURhdGFTb3VyY2UgfSBmcm9tICcuLi90eXBlcy9kYXRhc291cmNlLnR5cGUnO1xuXG5jb25zdCBXSURUSF9TQ1JPTEwgPSAxNztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEdlbmVyYXRlRXZlbnRzU2VydmljZSB7XG5cbiAgcHJpdmF0ZSBoZWlnaHRTY2hlZHVsZSA9IDA7XG5cbiAgcHJpdmF0ZSB3aWR0aFNjaGVkdWxlID0gMDtcblxuICBwcml2YXRlIGV2ZW50cyA9IFtdO1xuXG4gIHByaXZhdGUgb3JpZ2luYWxFdmVudHMgPSBbXTtcblxuICBwcml2YXRlIHdvcmtTY2FsZUluTWlsZXNlY29uZHMgPSBbXTtcblxuICBwcml2YXRlIHNjaGVkdWxlU2xhdHM6IFF1ZXJ5TGlzdDxhbnk+O1xuXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICB3aXRoKCAgZXZlbnRzOiBTY2hlZHVsZURhdGFTb3VyY2VbXSApIHtcbiAgICBpZiAoICB0aGlzLnNjaGVkdWxlU2xhdHMgKSB7XG4gICAgICBpZiAoIGV2ZW50cy5sZW5ndGggPiAwICYmIHRoaXMuc2NoZWR1bGVTbGF0cy5sZW5ndGggPiAwICkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsRXZlbnRzID0gSlNPTi5wYXJzZSggSlNPTi5zdHJpbmdpZnkoIGV2ZW50cyApICk7XG4gICAgICAgIGV2ZW50cyA9IEpTT04ucGFyc2UoIEpTT04uc3RyaW5naWZ5KCBldmVudHMgKSApO1xuXG4gICAgICAgIHRoaXMuZXZlbnRzID0gZXZlbnRzO1xuICAgICAgICB0aGlzLnRyYW5zZm9ybURhdGVUb1BpeGVsKCk7XG4gICAgICAgIHJldHVybiB0aGlzLmdlbmVyYXRlRXZlbnRzKCk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICBpbml0aWFsaXplQXJyYXkoIHdvcmtTY2FsZUluTWlsZXNlY29uZHMsIHNjaGVkdWxlU2xhdHM6IFF1ZXJ5TGlzdDxhbnk+ICApIHtcbiAgICBpZiAoIHNjaGVkdWxlU2xhdHMgJiYgc2NoZWR1bGVTbGF0cykge1xuICAgICAgaWYgKCBzY2hlZHVsZVNsYXRzLmxlbmd0aCA+IDAgJiYgd29ya1NjYWxlSW5NaWxlc2Vjb25kcy5sZW5ndGggPiAwICkge1xuICAgICAgICB0aGlzLndvcmtTY2FsZUluTWlsZXNlY29uZHMgPSB3b3JrU2NhbGVJbk1pbGVzZWNvbmRzO1xuICAgICAgICB0aGlzLnNjaGVkdWxlU2xhdHMgPSBzY2hlZHVsZVNsYXRzO1xuICAgICAgICB0aGlzLnNjaGVkdWxlU2xhdHMudG9BcnJheSgpLmZvckVhY2goIChpdGVtKSA9PiB7XG4gICAgICAgICAgdGhpcy5oZWlnaHRTY2hlZHVsZSA9IHRoaXMuaGVpZ2h0U2NoZWR1bGUgKyBpdGVtLm5hdGl2ZUVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy53aWR0aFNjaGVkdWxlID0gdGhpcy5zY2hlZHVsZVNsYXRzLmZpcnN0Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGggLSBXSURUSF9TQ1JPTEw7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB0cmFuc2Zvcm1EYXRlVG9QaXhlbCgpIHtcbiAgICBmb3IgKCBsZXQgaSA9IDA7IGkgPD0gdGhpcy5ldmVudHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICB0aGlzLmV2ZW50c1tpXS5kYXRlID0gT2JqZWN0LmFzc2lnbih7fSwge1xuICAgICAgICBzdGFydDogTWF0aC5yb3VuZCh0aGlzLmNvbnZlcnRNaWxsaXNlY29uZHNUb1BpeGVsKCB0aGlzLmV2ZW50c1tpXS5kYXRlLnN0YXJ0ICkpLFxuICAgICAgICBlbmQ6ICBNYXRoLnJvdW5kKHRoaXMuY29udmVydE1pbGxpc2Vjb25kc1RvUGl4ZWwoIHRoaXMuZXZlbnRzW2ldLmRhdGUuZW5kICkpXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjb252ZXJ0TWlsbGlzZWNvbmRzVG9QaXhlbChkYXRlID0gbmV3IERhdGUoKS5nZXRUaW1lKCkpIHtcbiAgICBsZXQgaGVpZ2h0Qm9keTtcbiAgICBsZXQgc3RhcnREYXlNaWxsaXNlY29uZHM7XG4gICAgbGV0IGVuZERheU1pbGxpc2Vjb25kcztcbiAgICBsZXQgY29udmVydGVkO1xuICAgIGxldCBjdXJyZW50RGF0ZTtcbiAgICBsZXQgcG9zaXRpb24gPSAtMTtcbiAgICBsZXQgb2Zmc2V0SGVpZ2h0ID0gMDtcblxuICAgIHRoaXMud29ya1NjYWxlSW5NaWxlc2Vjb25kcy5mb3JFYWNoKCggaXRlbSwgaW5kZXgsIGFycmF5KSA9PiB7XG4gICAgICBpZiAoIGRhdGUgPj0gdGhpcy53b3JrU2NhbGVJbk1pbGVzZWNvbmRzW2luZGV4XS5zdGFydCApIHtcbiAgICAgICAgcG9zaXRpb24rKztcbiAgICAgICAgY29uc3Qgc2xvdE9iamVjdCA9IHRoaXMuc2NoZWR1bGVTbGF0cy5maW5kKCAoc2xvdCwgaWR4KSA9PiBpZHggPT09ICggaW5kZXggLSAxKSk7XG4gICAgICAgIG9mZnNldEhlaWdodCA9IG9mZnNldEhlaWdodCArIGVsdmlzKHNsb3RPYmplY3QsICduYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCcpIHx8IDA7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoIHBvc2l0aW9uIDwgMCAmJiBvZmZzZXRIZWlnaHQgPD0gMCkge1xuICAgICAgcmV0dXJuIC0xMDAwO1xuICAgIH1cblxuICAgIHN0YXJ0RGF5TWlsbGlzZWNvbmRzID0gTWF0aC5mbG9vcih0aGlzLndvcmtTY2FsZUluTWlsZXNlY29uZHNbcG9zaXRpb25dLnN0YXJ0IC8gMTAwMDAwICk7XG4gICAgZW5kRGF5TWlsbGlzZWNvbmRzID0gTWF0aC5mbG9vcih0aGlzLndvcmtTY2FsZUluTWlsZXNlY29uZHNbcG9zaXRpb25dLmVuZCAvIDEwMDAwMCApO1xuICAgIGhlaWdodEJvZHkgPSBlbHZpcyh0aGlzLnNjaGVkdWxlU2xhdHMuZmluZCggKGl0ZW0sIGlkeCkgPT4gaWR4ID09PSBwb3NpdGlvbiksICduYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCcpIHx8IDA7XG4gICAgZGF0ZSA9IE1hdGguZmxvb3IoZGF0ZSAvIDEwMDAwMCApO1xuICAgIGN1cnJlbnREYXRlID0gZGF0ZSAtIHN0YXJ0RGF5TWlsbGlzZWNvbmRzO1xuICAgIGNvbnZlcnRlZCA9ICggaGVpZ2h0Qm9keSAqIGN1cnJlbnREYXRlICkgLyAoIGVuZERheU1pbGxpc2Vjb25kcyAtIHN0YXJ0RGF5TWlsbGlzZWNvbmRzKTtcblxuICAgIHJldHVybiBjb252ZXJ0ZWQgPiBoZWlnaHRCb2R5ICA/IC0xMDAwIDogKCBjb252ZXJ0ZWQgKyBvZmZzZXRIZWlnaHQgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2VuZXJhdGVFdmVudHMoKSB7XG4gICAgY29uc3QgZXZlbnRzV2l0aFBvc2l0aW9uaW5nID0gW107XG4gICAgY29uc3QgaGlzdG9ncmFtID0gdGhpcy5jcmVhdGVIaXN0b2dyYW0oKTtcbiAgICBjb25zdCBncmFwaCA9IHRoaXMuY3JlYXRlVGhlR3JhcGgoIGhpc3RvZ3JhbSApO1xuICAgIHRoaXMuc2V0Q2x1c3RlcldpZHRoKCBncmFwaCApO1xuICAgIHRoaXMuc2V0Tm9kZXNQb3NpdGlvbiggZ3JhcGggKTtcblxuICAgIGZvciAoIGNvbnN0IG5vZGVJZCBpbiBncmFwaC5ub2RlcyApIHtcbiAgICAgIGlmICggZ3JhcGgubm9kZXMuaGFzT3duUHJvcGVydHkobm9kZUlkKSApIHtcbiAgICAgICAgaWYgKCBncmFwaC5ub2Rlc1tub2RlSWRdLmNsdXN0ZXIgKSB7XG4gICAgICAgICAgY29uc3Qgbm9kZSA9IGdyYXBoLm5vZGVzW25vZGVJZF07XG4gICAgICAgICAgY29uc3QgZXZlbnQgPSB7XG4gICAgICAgICAgICBwb3NpdGlvbnM6IHtcbiAgICAgICAgICAgICAgaWQ6IG5vZGUuaWQsXG4gICAgICAgICAgICAgIHRvcDogbm9kZS5zdGFydCxcbiAgICAgICAgICAgICAgbGVmdDogbm9kZS5wb3NpdGlvbiAqIG5vZGUuY2x1c3Rlci53aWR0aCxcbiAgICAgICAgICAgICAgaGVpZ2h0OiBub2RlLmVuZCAtIG5vZGUuc3RhcnQsXG4gICAgICAgICAgICAgIHdpZHRoOiBub2RlLmNsdXN0ZXIud2lkdGhcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkYXRhOiB0aGlzLm9yaWdpbmFsRXZlbnRzLmZpbHRlcigoIGUgKSA9PiBlLnZhbHVlID09PSBub2RlLmlkIClbMF1cbiAgICAgICAgICB9O1xuICAgICAgICAgIGV2ZW50c1dpdGhQb3NpdGlvbmluZy5wdXNoKGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXZlbnRzV2l0aFBvc2l0aW9uaW5nO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVIaXN0b2dyYW0oKSB7XG5cbiAgICAvLyBpbml0aWFsaXppbmcgdGhlIG1pbnV0ZXMgYXJyYXlcbiAgICBjb25zdCBtaW51dGVzID0gbmV3IEFycmF5KCB0aGlzLmhlaWdodFNjaGVkdWxlICk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtaW51dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBtaW51dGVzW2ldID0gW107XG4gICAgfVxuXG4gICAgLy8gc2V0dGluZyB3aGljaCBldmVudHMgb2NjdXJzIGF0IGVhY2ggbWludXRlXG4gICAgdGhpcy5ldmVudHMuZm9yRWFjaCggKGV2ZW50KSA9PiB7XG4gICAgICBmb3IgKCBsZXQgaSA9IGV2ZW50LmRhdGUuc3RhcnQ7IGkgPD0gZXZlbnQuZGF0ZS5lbmQgLSAxOyBpKysgKSB7XG4gICAgICAgIGlmICggbWludXRlc1tpXSApIHtcbiAgICAgICAgICBtaW51dGVzW2ldLnB1c2goZXZlbnQudmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG1pbnV0ZXM7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVRoZUdyYXBoKCBtaW51dGVzICkge1xuICAgIGNvbnN0IGdyYXBoID0gbmV3IEdyYXBoKCk7XG4gICAgY29uc3Qgbm9kZU1hcCA9IHt9O1xuXG4gICAgLy8gY3JlYXRpbmcgdGhlIG5vZGVzXG4gICAgdGhpcy5ldmVudHMuZm9yRWFjaCggKGV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBub2RlID0gbmV3IE5vZGUoZXZlbnQudmFsdWUsIGV2ZW50LmRhdGUuc3RhcnQsIGV2ZW50LmRhdGUuZW5kKTtcbiAgICAgIG5vZGVNYXBbbm9kZS5pZF0gPSBub2RlO1xuICAgIH0pO1xuXG4gICAgLy8gY3JlYXRpbmcgdGhlIGNsdXN0ZXJzXG4gICAgbGV0IGNsdXN0ZXIgPSBudWxsO1xuXG4gICAgLy8gY2x1c3RlciBpcyBhIGdyb3VwIG9mIG5vZGVzIHdoaWNoIGhhdmUgYSBjb25uZWN0aXZpdHkgcGF0aCwgd2hlbiB0aGUgbWludXRlIGFycmF5IGxlbmd0aCBpcyAwIGl0IG1lYW5zIHRoYXRcbiAgICAvLyB0aGVyZSBhcmUgbiBtb3JlIG5vZGVzIGluIHRoZSBjbHVzdGVyIC0gY2x1c3RlciBjYW4gYmUgXCJjbG9zZWRcIi5cbiAgICBtaW51dGVzLmZvckVhY2goIChtaW51dGUsIGluZGV4LCBhcnJheU1pbnV0ZXMgKSA9PiB7XG4gICAgICBpZiAobWludXRlLmxlbmd0aCA+IDApIHtcblxuICAgICAgICBpZiAoIGFycmF5TWludXRlc1tpbmRleCAtIDFdICkge1xuICAgICAgICAgIGlmICggKCBtaW51dGVbMF0gIT09IGFycmF5TWludXRlc1tpbmRleCAtIDFdWzBdICkgJiYgKCBtaW51dGUubGVuZ3RoICE9PSBhcnJheU1pbnV0ZXNbaW5kZXggLSAxXS5sZW5ndGggKSAgJiYgY2x1c3Rlcikge1xuICAgICAgICAgICAgZ3JhcGguY2x1c3RlcnMucHVzaChjbHVzdGVyKTtcbiAgICAgICAgICAgIGNsdXN0ZXIgPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG5cbiAgICAgICAgY2x1c3RlciA9IGNsdXN0ZXIgfHwgbmV3IENsdXN0ZXIoKTtcbiAgICAgICAgbWludXRlLmZvckVhY2goICggZXZlbnRJZCApID0+IHtcbiAgICAgICAgICBpZiAoIWNsdXN0ZXIubm9kZXNbZXZlbnRJZF0pIHtcbiAgICAgICAgICAgIGNsdXN0ZXIubm9kZXNbZXZlbnRJZF0gPSBub2RlTWFwW2V2ZW50SWRdO1xuICAgICAgICAgICAgbm9kZU1hcFtldmVudElkXS5jbHVzdGVyID0gY2x1c3RlcjtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGNsdXN0ZXIgIT09IG51bGwpIHtcbiAgICAgICAgICBncmFwaC5jbHVzdGVycy5wdXNoKGNsdXN0ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY2x1c3RlciA9IG51bGw7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoY2x1c3RlciAhPT0gbnVsbCkge1xuICAgICAgZ3JhcGguY2x1c3RlcnMucHVzaChjbHVzdGVyKTtcbiAgICB9XG5cbiAgICAvLyBhZGRpbmcgbmVpZ2hib3VycyB0byBub2RlcywgbmVpZ2hib3VycyBpcyB0aGUgZ3JvdXAgb2YgY29sbGlkaW5nIG5vZGVzIChldmVudHMpLlxuICAgIC8vIGFkZGluZyB0aGUgYmlnZ2VzdCBjbGlxdWUgZm9yIGVhY2ggc2l0ZVxuICAgIG1pbnV0ZXMuZm9yRWFjaCgobWludXRlKSA9PiB7XG4gICAgICBtaW51dGUuZm9yRWFjaCggKGV2ZW50SWQpID0+IHtcbiAgICAgICAgY29uc3Qgc291cmNlTm9kZSA9IG5vZGVNYXBbZXZlbnRJZF07XG5cbiAgICAgICAgLy8gYSBtYXggY2xpcXVlIGlzIGEgYmlnZ2VzdCBncm91cCBvZiBjb2xsaWRpbmcgZXZlbnRzXG4gICAgICAgIHNvdXJjZU5vZGUuYmlnZ2VzdENsaXF1ZVNpemUgPSBNYXRoLm1heChzb3VyY2VOb2RlLmJpZ2dlc3RDbGlxdWVTaXplLCBtaW51dGUubGVuZ3RoKTtcbiAgICAgICAgbWludXRlLmZvckVhY2goICh0YXJnZXRFdmVudElkKSA9PiB7XG4gICAgICAgICAgaWYgKGV2ZW50SWQgIT09IHRhcmdldEV2ZW50SWQpIHtcbiAgICAgICAgICAgIHNvdXJjZU5vZGUubmVpZ2hib3Vyc1t0YXJnZXRFdmVudElkXSA9IG5vZGVNYXBbdGFyZ2V0RXZlbnRJZF07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZ3JhcGgubm9kZXMgPSBub2RlTWFwO1xuICAgIHJldHVybiBncmFwaDtcbiAgfVxuXG4gIHByaXZhdGUgc2V0Q2x1c3RlcldpZHRoKCBncmFwaCApIHtcbiAgICBncmFwaC5jbHVzdGVycy5mb3JFYWNoKCAoY2x1c3RlcikgPT4ge1xuXG4gICAgICBsZXQgbWF4Q2xpcXVlU2l6ZSA9IDE7XG4gICAgICBmb3IgKCBjb25zdCBub2RlSWQgaW4gY2x1c3Rlci5ub2RlcyApIHtcbiAgICAgICAgaWYgKCBjbHVzdGVyLm5vZGVzLmhhc093blByb3BlcnR5KG5vZGVJZCkgKSB7XG4gICAgICAgICAgbWF4Q2xpcXVlU2l6ZSA9IE1hdGgubWF4KG1heENsaXF1ZVNpemUsIGNsdXN0ZXIubm9kZXNbbm9kZUlkXS5iaWdnZXN0Q2xpcXVlU2l6ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY2x1c3Rlci5tYXhDbGlxdWVTaXplID0gbWF4Q2xpcXVlU2l6ZTtcbiAgICAgIGNsdXN0ZXIud2lkdGggPSB0aGlzLndpZHRoU2NoZWR1bGUgLyAobWF4Q2xpcXVlU2l6ZSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNldE5vZGVzUG9zaXRpb24oIGdyYXBoICkge1xuICAgIGdyYXBoLmNsdXN0ZXJzLmZvckVhY2goIChjbHVzdGVyKSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IG5vZGVJZCBpbiBjbHVzdGVyLm5vZGVzKSB7XG4gICAgICAgIGlmICggY2x1c3Rlci5ub2Rlcy5oYXNPd25Qcm9wZXJ0eShub2RlSWQpICkge1xuICAgICAgICAgIGNvbnN0IG5vZGUgPSBjbHVzdGVyLm5vZGVzW25vZGVJZF07XG4gICAgICAgICAgY29uc3QgcG9zaXRpb25BcnJheSA9IG5ldyBBcnJheShub2RlLmNsdXN0ZXIubWF4Q2xpcXVlU2l6ZSk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IG5laWdoYm91cklkIGluIG5vZGUubmVpZ2hib3Vycykge1xuICAgICAgICAgICAgaWYgKG5vZGUubmVpZ2hib3Vycy5oYXNPd25Qcm9wZXJ0eShuZWlnaGJvdXJJZCkpIHtcbiAgICAgICAgICAgICAgY29uc3QgbmVpZ2hib3VyID0gbm9kZS5uZWlnaGJvdXJzW25laWdoYm91cklkXTtcbiAgICAgICAgICAgICAgaWYgKG5laWdoYm91ci5wb3NpdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcG9zaXRpb25BcnJheVtuZWlnaGJvdXIucG9zaXRpb25dID0gdHJ1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zaXRpb25BcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKCFwb3NpdGlvbkFycmF5W2ldKSB7XG4gICAgICAgICAgICAgIG5vZGUucG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG5cbn1cbiJdfQ==