webglimpse
Version:
Webglimpse is a data visualization library for the web.
432 lines • 73.5 kB
JavaScript
import { formatTime_ISO8601, hasval } from '../util/util';
import { indexAfter, indexBefore, indexAtOrAfter } from '../util/sorted_arrays';
export class TimelineLaneArray {
constructor(model, row, ui, allowMultipleLanes) {
this._model = model;
this._row = row;
this._ui = ui;
this._lanes = [];
this._laneNums = {};
this._eventAttrsListeners = {};
const self = this;
function findAvailableLaneNum(event, startLaneNum, endLaneNum) {
for (let n = startLaneNum; n < endLaneNum; n++) {
if (self._lanes[n].couldFitEvent(event)) {
return n;
}
}
return null;
}
function firstAvailableLaneNum(event) {
const laneNum = findAvailableLaneNum(event, 0, self._lanes.length);
return (hasval(laneNum) ? laneNum : self._lanes.length);
}
function addEventToLane(event, laneNum) {
if (!self._lanes[laneNum]) {
self._lanes[laneNum] = allowMultipleLanes ? new TimelineLaneStack(ui) : new TimelineLaneSimple(ui);
}
self._lanes[laneNum].add(event);
self._laneNums[event.eventGuid] = laneNum;
}
function fillVacancy(vacancyLaneNum, vacancyEdges_PMILLIS) {
const vacancyLane = self._lanes[vacancyLaneNum];
for (let n = vacancyLaneNum + 1; n < self._lanes.length; n++) {
const lane = self._lanes[n];
const possibleTenants = lane.collisionsWithInterval(vacancyEdges_PMILLIS[0], vacancyEdges_PMILLIS[1]);
for (let p = 0; p < possibleTenants.length; p++) {
const event = possibleTenants[p];
if (vacancyLane.couldFitEvent(event)) {
lane.remove(event);
addEventToLane(event, vacancyLaneNum);
fillVacancy(n, effectiveEdges_PMILLIS(ui, event));
}
}
}
}
function trimEmptyLanes() {
for (let n = self._lanes.length - 1; n >= 0; n--) {
if (self._lanes[n].isEmpty()) {
self._lanes.splice(n, 1);
}
else {
break;
}
}
}
// adds event to lane, may be called multiple times
this._addEvent = function (eventGuid) {
if (hasval(self._laneNums[eventGuid])) {
throw new Error('Lanes-array already contains this event: row-guid = ' + row.rowGuid + ', lane = ' + self._laneNums[eventGuid] + ', event-guid = ' + eventGuid);
}
const event = model.event(eventGuid);
const laneNum = firstAvailableLaneNum(event);
addEventToLane(event, laneNum);
};
row.eventGuids.forEach(this._addEvent);
row.eventGuids.valueAdded.on(this._addEvent);
// attaches listeners to event, should be called only once
// when an event is first added to the row model
this._newEvent = function (eventGuid) {
const event = model.event(eventGuid);
let oldEdges_PMILLIS = effectiveEdges_PMILLIS(ui, event);
const updateLaneAssignment = function () {
const newEdges_PMILLIS = effectiveEdges_PMILLIS(ui, event);
if (newEdges_PMILLIS[0] !== oldEdges_PMILLIS[0] || newEdges_PMILLIS[1] !== oldEdges_PMILLIS[1]) {
const oldLaneNum = self._laneNums[event.eventGuid];
const oldLane = self._lanes[oldLaneNum];
const betterLaneNum = findAvailableLaneNum(event, 0, oldLaneNum);
if (hasval(betterLaneNum)) {
// Move to a better lane
oldLane.remove(event);
addEventToLane(event, betterLaneNum);
}
else if (oldLane.eventStillFits(event)) {
// Stay in the current lane
oldLane.update(event);
}
else {
// Take whatever lane we can get
let newLaneNum = findAvailableLaneNum(event, oldLaneNum + 1, self._lanes.length);
if (!hasval(newLaneNum)) {
newLaneNum = self._lanes.length;
}
oldLane.remove(event);
addEventToLane(event, newLaneNum);
}
fillVacancy(oldLaneNum, oldEdges_PMILLIS);
trimEmptyLanes();
oldEdges_PMILLIS = newEdges_PMILLIS;
}
};
event.attrsChanged.on(updateLaneAssignment);
self._eventAttrsListeners[eventGuid] = updateLaneAssignment;
};
row.eventGuids.forEach(this._newEvent);
row.eventGuids.valueAdded.on(this._newEvent);
this._removeEvent = function (eventGuid) {
const event = model.event(eventGuid);
const oldLaneNum = self._laneNums[eventGuid];
delete self._laneNums[eventGuid];
self._lanes[oldLaneNum].remove(event);
fillVacancy(oldLaneNum, effectiveEdges_PMILLIS(ui, event));
trimEmptyLanes();
event.attrsChanged.off(self._eventAttrsListeners[eventGuid]);
delete self._eventAttrsListeners[eventGuid];
};
row.eventGuids.valueRemoved.on(this._removeEvent);
self._rebuildLanes = function () {
const oldLanes = self._lanes;
self._lanes = [];
self._laneNums = {};
for (let l = 0; l < oldLanes.length; l++) {
const lane = oldLanes[l];
for (let e = 0; e < lane.length; e++) {
const event = lane.event(e);
self._addEvent(event.eventGuid);
}
}
};
const hasIcons = function () {
const oldLanes = self._lanes;
for (let l = 0; l < oldLanes.length; l++) {
const lane = oldLanes[l];
for (let e = 0; e < lane.length; e++) {
const event = lane.event(e);
const style = ui.eventStyle(event.styleGuid);
if (event.labelIcon || style.numIcons > 0) {
return true;
}
}
}
return false;
};
self._rebuildLanesMouseWheel = function () {
if (hasIcons()) {
self._rebuildLanes();
}
};
ui.millisPerPx.changed.on(self._rebuildLanesMouseWheel);
ui.eventStyles.valueAdded.on(self._rebuildLanes);
ui.eventStyles.valueRemoved.on(self._rebuildLanes);
}
get length() {
return this._lanes.length;
}
lane(index) {
return this._lanes[index];
}
get numEvents() {
return this._row.eventGuids.length;
}
eventAt(laneNum, time_PMILLIS) {
const lane = this._lanes[laneNum];
return (lane && lane.eventAtTime(time_PMILLIS));
}
dispose() {
this._row.eventGuids.valueAdded.off(this._addEvent);
this._row.eventGuids.valueRemoved.off(this._removeEvent);
this._row.eventGuids.valueAdded.off(this._newEvent);
this._ui.millisPerPx.changed.off(this._rebuildLanesMouseWheel);
this._ui.eventStyles.valueAdded.off(this._rebuildLanes);
this._ui.eventStyles.valueRemoved.off(this._rebuildLanes);
for (const eventGuid in this._eventAttrsListeners) {
if (this._eventAttrsListeners.hasOwnProperty(eventGuid)) {
const listener = this._eventAttrsListeners[eventGuid];
const event = this._model.event(eventGuid);
if (listener && event) {
event.attrsChanged.off(listener);
}
}
}
}
}
export function effectiveEdges_PMILLIS(ui, event) {
let start_PMILLIS = event.start_PMILLIS;
let end_PMILLIS = event.end_PMILLIS;
const millisPerPx = ui.millisPerPx.value;
const eventStyle = ui.eventStyle(event.styleGuid);
for (let n = 0; n < eventStyle.numIcons; n++) {
const icon = eventStyle.icon(n);
const iconTime_PMILLIS = event.start_PMILLIS + icon.hPos * (event.end_PMILLIS - event.start_PMILLIS);
const iconStart_PMILLIS = iconTime_PMILLIS - (millisPerPx * icon.hAlign * icon.displayWidth);
const iconEnd_PMILLIS = iconTime_PMILLIS + (millisPerPx * (1 - icon.hAlign) * icon.displayWidth);
start_PMILLIS = Math.trunc(Math.min(start_PMILLIS, iconStart_PMILLIS));
end_PMILLIS = Math.trunc(Math.max(end_PMILLIS, iconEnd_PMILLIS));
}
return [start_PMILLIS, end_PMILLIS];
}
// a TimelineLane where no events start/end time overlap
export class TimelineLaneStack {
constructor(ui) {
this._events = [];
this._starts_PMILLIS = [];
this._ends_PMILLIS = [];
this._indices = {};
this._ui = ui;
}
get length() {
return this._events.length;
}
event(index) {
return this._events[index];
}
isEmpty() {
return (this._events.length === 0);
}
eventAtTime(time_PMILLIS) {
if (hasval(time_PMILLIS)) {
// Check the first event ending after time
const iFirst = indexAfter(this._ends_PMILLIS, time_PMILLIS);
if (iFirst < this._events.length) {
const eventFirst = this._events[iFirst];
const startFirst_PMILLIS = effectiveEdges_PMILLIS(this._ui, eventFirst)[0];
if (time_PMILLIS >= startFirst_PMILLIS) {
return eventFirst;
}
}
// Check the previous event, in case we're in its icon-slop
const iPrev = iFirst - 1;
if (iPrev >= 0) {
const eventPrev = this._events[iPrev];
const endPrev_PMILLIS = effectiveEdges_PMILLIS(this._ui, eventPrev)[1];
if (time_PMILLIS < endPrev_PMILLIS) {
return eventPrev;
}
}
}
return null;
}
add(event) {
const eventGuid = event.eventGuid;
if (hasval(this._indices[eventGuid])) {
throw new Error('Lane already contains this event: event = ' + formatEvent(event));
}
const i = indexAfter(this._starts_PMILLIS, event.start_PMILLIS);
if (!this._eventFitsBetween(event, i - 1, i)) {
throw new Error('New event does not fit between existing events: new = ' + formatEvent(event) + ', before = ' + formatEvent(this._events[i - 1]) + ', after = ' + formatEvent(this._events[i]));
}
this._events.splice(i, 0, event);
this._starts_PMILLIS.splice(i, 0, event.start_PMILLIS);
this._ends_PMILLIS.splice(i, 0, event.end_PMILLIS);
this._indices[eventGuid] = i;
for (let n = i; n < this._events.length; n++) {
this._indices[this._events[n].eventGuid] = n;
}
}
remove(event) {
const eventGuid = event.eventGuid;
const i = this._indices[eventGuid];
if (!hasval(i)) {
throw new Error('Event not found in this lane: event = ' + formatEvent(event));
}
this._events.splice(i, 1);
this._starts_PMILLIS.splice(i, 1);
this._ends_PMILLIS.splice(i, 1);
delete this._indices[eventGuid];
for (let n = i; n < this._events.length; n++) {
this._indices[this._events[n].eventGuid] = n;
}
}
eventStillFits(event) {
const i = this._indices[event.eventGuid];
if (!hasval(i)) {
throw new Error('Event not found in this lane: event = ' + formatEvent(event));
}
return this._eventFitsBetween(event, i - 1, i + 1);
}
update(event) {
const i = this._indices[event.eventGuid];
if (!hasval(i)) {
throw new Error('Event not found in this lane: event = ' + formatEvent(event));
}
this._starts_PMILLIS[i] = event.start_PMILLIS;
this._ends_PMILLIS[i] = event.end_PMILLIS;
}
collisionsWithInterval(start_PMILLIS, end_PMILLIS) {
// Find the first event ending after start
let iFirst = indexAfter(this._ends_PMILLIS, start_PMILLIS);
const iPrev = iFirst - 1;
if (iPrev >= 0) {
const endPrev_PMILLIS = effectiveEdges_PMILLIS(this._ui, this._events[iPrev])[1];
if (start_PMILLIS < endPrev_PMILLIS) {
iFirst = iPrev;
}
}
// Find the last event starting before end
let iLast = indexBefore(this._starts_PMILLIS, end_PMILLIS);
const iPost = iLast + 1;
if (iPost < this._events.length) {
const startPost_PMILLIS = effectiveEdges_PMILLIS(this._ui, this._events[iPost])[0];
if (end_PMILLIS > startPost_PMILLIS) {
iLast = iPost;
}
}
// Return that section
return this._events.slice(iFirst, iLast + 1);
}
couldFitEvent(event) {
const iAfter = indexAfter(this._starts_PMILLIS, event.start_PMILLIS);
const iBefore = iAfter - 1;
return this._eventFitsBetween(event, iBefore, iAfter);
}
_eventFitsBetween(event, iBefore, iAfter) {
const edges_PMILLIS = effectiveEdges_PMILLIS(this._ui, event);
if (iBefore >= 0) {
// Comparing one start-time (inclusive) and one end-time (exclusive), so equality means no collision
const edgesBefore_PMILLIS = effectiveEdges_PMILLIS(this._ui, this._events[iBefore]);
if (edges_PMILLIS[0] < edgesBefore_PMILLIS[1]) {
return false;
}
}
if (iAfter < this._events.length) {
// Comparing one start-time (inclusive) and one end-time (exclusive), so equality means no collision
const edgesAfter_PMILLIS = effectiveEdges_PMILLIS(this._ui, this._events[iAfter]);
if (edges_PMILLIS[1] > edgesAfter_PMILLIS[0]) {
return false;
}
}
return true;
}
}
// a TimelineLane where events are allowed to overlap arbitrarily
// because of this assumptions like the index for an event in the _starts_PMILLIS
// and _ends_PMILLIS arrays being the same no longer hold
//
// does not make any assumptions about event overlapping and uses
// an inefficient O(n) brute force search to find events (an interval tree
// would be needed for efficient search in the general case)
export class TimelineLaneSimple {
constructor(ui) {
this._events = [];
this._orders = [];
this._ids = {};
this._ui = ui;
}
get length() {
return this._events.length;
}
event(index) {
return this._events[index];
}
isEmpty() {
return (this._events.length === 0);
}
eventAtTime(time_PMILLIS) {
let bestEvent;
// start at end of events list so that eventAtTime result
// favors events drawn on top (in cases where events are unordered
// those that happen to be at end end of the list are drawn last
for (let n = this._events.length - 1; n >= 0; n--) {
const event = this._events[n];
const eventEdges_PMILLIS = effectiveEdges_PMILLIS(this._ui, event);
if (time_PMILLIS > eventEdges_PMILLIS[0] &&
time_PMILLIS < eventEdges_PMILLIS[1] &&
(bestEvent === undefined || bestEvent.order < event.order)) {
bestEvent = event;
}
}
return bestEvent;
}
add(event) {
const eventGuid = event.eventGuid;
if (hasval(this._ids[eventGuid])) {
throw new Error('Lane already contains this event: event = ' + formatEvent(event));
}
// for events with undefined order, replace with largest possible negative order so sort is correct
const orderVal = hasval(event.order) ? event.order : Number.NEGATIVE_INFINITY;
const i = indexAtOrAfter(this._orders, orderVal);
this._ids[eventGuid] = eventGuid;
this._orders.splice(i, 0, orderVal);
this._events.splice(i, 0, event);
}
remove(event) {
const eventGuid = event.eventGuid;
if (!hasval(this._ids[eventGuid])) {
throw new Error('Event not found in this lane: event = ' + formatEvent(event));
}
delete this._ids[eventGuid];
const i = this._getIndex(event);
this._orders.splice(i, 1);
this._events.splice(i, 1);
}
update(event) {
this.remove(event);
this.add(event);
}
collisionsWithInterval(start_PMILLIS, end_PMILLIS) {
const results = [];
for (let n = 0; n < this._events.length; n++) {
const event = this._events[n];
if (!(start_PMILLIS > event.end_PMILLIS || end_PMILLIS < event.start_PMILLIS)) {
results.push(event);
}
}
return results;
}
// we can always fit more events because overlaps are allowed
eventStillFits(event) {
return true;
}
// we can always fit more events because overlaps are allowed
couldFitEvent(event) {
return true;
}
_getIndex(queryEvent) {
for (let n = 0; n < this._events.length; n++) {
const event = this._events[n];
if (queryEvent.eventGuid === event.eventGuid) {
return n;
}
}
throw new Error('Event not found in this lane: event = ' + formatEvent(queryEvent));
}
}
function formatEvent(event) {
if (!hasval(event)) {
return '' + event;
}
else {
return (event.label + ' [ ' + formatTime_ISO8601(event.start_PMILLIS) + ' ... ' + formatTime_ISO8601(event.end_PMILLIS) + ' ]');
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZWxpbmVfbGFuZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd2ViZ2xpbXBzZS90aW1lbGluZS90aW1lbGluZV9sYW5lcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUErQkEsT0FBTyxFQUFvQixrQkFBa0IsRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFNUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFaEYsTUFBTSxPQUFPLGlCQUFpQjtJQWlCMUIsWUFBWSxLQUFvQixFQUFFLEdBQXFCLEVBQUUsRUFBYyxFQUFFLGtCQUEyQjtRQUNoRyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUNoQixJQUFJLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUVkLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxFQUFFLENBQUM7UUFFL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWxCLFNBQVMsb0JBQW9CLENBQUMsS0FBeUIsRUFBRSxZQUFvQixFQUFFLFVBQWtCO1lBQzdGLEtBQUssSUFBSSxDQUFDLEdBQUcsWUFBWSxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQzVDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3JDLE9BQU8sQ0FBQyxDQUFDO2lCQUNaO2FBQ0o7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNoQixDQUFDO1FBRUQsU0FBUyxxQkFBcUIsQ0FBQyxLQUF5QjtZQUNwRCxNQUFNLE9BQU8sR0FBRyxvQkFBb0Is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QUFDLEVBQUU7Z0JBQzNFLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDdkI7U0FDSjtRQUVELE9BQU8sT0FBTyxDQUFDO0lBQ25CLENBQUM7SUFFRCw2REFBNkQ7SUFDN0QsY0FBYyxDQUFDLEtBQXlCO1FBQ3BDLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCw2REFBNkQ7SUFDN0QsYUFBYSxDQUFDLEtBQXlCO1FBQ25DLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxTQUFTLENBQUMsVUFBOEI7UUFDcEMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzFDLE1BQU0sS0FBSyxHQUF1QixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xELElBQUksVUFBVSxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsU0FBUyxFQUFFO2dCQUMxQyxPQUFPLENBQUMsQ0FBQzthQUNaO1NBQ0o7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3hGLENBQUM7Q0FDSjtBQUVELFNBQVMsV0FBVyxDQUFDLEtBQXlCO0lBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDaEIsT0FBTyxFQUFFLEdBQUcsS0FBSyxDQUFDO0tBQ3JCO1NBQ0k7UUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLEdBQUcsa0JBQWtCLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7S0FDbkk7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogQ29weXJpZ2h0IChjKSAyMDE0LCBNZXRyb24sIEluYy5cclxuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICpcclxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcclxuICogYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxyXG4gKlxyXG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuICogICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXHJcbiAqXHJcbiAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuICogICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxyXG4gKiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cclxuICpcclxuICogMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cyBjb250cmlidXRvcnNcclxuICogICAgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXRcclxuICogICAgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxyXG4gKlxyXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcclxuICogQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcclxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxyXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxyXG4gKiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcclxuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xyXG4gKiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cclxuICogQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcclxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcclxuICogU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXHJcbiAqL1xyXG5pbXBvcnQgeyBUaW1lbGluZVVpIH0gZnJvbSAnLi90aW1lbGluZV91aSc7XHJcbmltcG9ydCB7IFRpbWVsaW5lUm93TW9kZWwsIFRpbWVsaW5lTW9kZWwsIFRpbWVsaW5lRXZlbnRNb2RlbCB9IGZyb20gJy4vdGltZWxpbmVfbW9kZWwnO1xyXG5pbXBvcnQgeyBTdHJpbmdNYXAsIG9yZGVyLCBmb3JtYXRUaW1lX0lTTzg2MDEsIGhhc3ZhbCB9IGZyb20gJy4uL3V0aWwvdXRpbCc7XHJcbmltcG9ydCB7IExpc3RlbmVyIH0gZnJvbSAnLi4vdXRpbC9ub3RpZmljYXRpb24nO1xyXG5pbXBvcnQgeyBpbmRleEFmdGVyLCBpbmRleEJlZm9yZSwgaW5kZXhBdE9yQWZ0ZXIgfSBmcm9tICcuLi91dGlsL3NvcnRlZF9hcnJheXMnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFRpbWVsaW5lTGFuZUFycmF5IHtcclxuICAgIHByaXZhdGUgX3VpOiBUaW1lbGluZVVpO1xyXG4gICAgcHJpdmF0ZSBfcm93OiBUaW1lbGluZVJvd01vZGVsO1xyXG4gICAgcHJpdmF0ZSBfbGFuZXM6IFRpbWVsaW5lTGFuZVtdO1xyXG4gICAgcHJpdmF0ZSBfbGFuZU51bXM6IFN0cmluZ01hcDxudW1iZXI+O1xyXG5cclxuICAgIHByaXZhdGUgX3JlYnVpbGRMYW5lc01vdXNlV2hlZWw6ICgpID0+IHZvaWQ7XHJcbiAgICBwcml2YXRlIF9yZWJ1aWxkTGFuZXM6ICgpID0+IHZvaWQ7XHJcbiAgICBwcml2YXRlIF9uZXdFdmVudDogKGV2ZW50R3VpZDogc3RyaW5nKSA9PiB2b2lkO1xyXG4gICAgcHJpdmF0ZSBfYWRkRXZlbnQ6IChldmVudEd1aWQ6IHN0cmluZykgPT4gdm9pZDtcclxuICAgIHByaXZhdGUgX3JlbW92ZUV2ZW50OiAoZXZlbnRHdWlkOiBzdHJpbmcpID0+IHZvaWQ7XHJcblxyXG4gICAgcHJpdmF0ZSBfbW9kZWw6IFRpbWVsaW5lTW9kZWw7XHJcblxyXG4gICAgLy8gS2VlcCByZWZlcmVuY2VzIHRvIGxpc3RlbmVycywgc28gdGhhdCB3ZSBjYW4gcmVtb3ZlIHRoZW0gbGF0ZXJcclxuICAgIHByaXZhdGUgX2V2ZW50QXR0cnNMaXN0ZW5lcnM6IFN0cmluZ01hcDxMaXN0ZW5lcj47XHJcblxyXG4gICAgY29uc3RydWN0b3IobW9kZWw6IFRpbWVsaW5lTW9kZWwsIHJvdzogVGltZWxpbmVSb3dNb2RlbCwgdWk6IFRpbWVsaW5lVWksIGFsbG93TXVsdGlwbGVMYW5lczogYm9vbGVhbikge1xyXG4gICAgICAgIHRoaXMuX21vZGVsID0gbW9kZWw7XHJcbiAgICAgICAgdGhpcy5fcm93ID0gcm93O1xyXG4gICAgICAgIHRoaXMuX3VpID0gdWk7XHJcblxyXG4gICAgICAgIHRoaXMuX2xhbmVzID0gW107XHJcbiAgICAgICAgdGhpcy5fbGFuZU51bXMgPSB7fTtcclxuICAgICAgICB0aGlzLl9ldmVudEF0dHJzTGlzdGVuZXJzID0ge307XHJcblxyXG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xyXG5cclxuICAgICAgICBmdW5jdGlvbiBmaW5kQXZhaWxhYmxlTGFuZU51bShldmVudDogVGltZWxpbmVFdmVudE1vZGVsLCBzdGFydExhbmVOdW06IG51bWJlciwgZW5kTGFuZU51bTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgICAgICAgICAgZm9yIChsZXQgbiA9IHN0YXJ0TGFuZU51bTsgbiA8IGVuZExhbmVOdW07IG4rKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKHNlbGYuX2xhbmVzW25dLmNvdWxkRml0RXZlbnQoZXZlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmdW5jdGlvbiBmaXJzdEF2YWlsYWJsZUxhbmVOdW0oZXZlbnQ6IFRpbWVsaW5lRXZlbnRNb2RlbCk6IG51bWJlciB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxhbmVOdW0gPSBmaW5kQXZhaWxhYmxlTGFuZU51bShldmVudCwgMCwgc2VsZi5fbGFuZXMubGVuZ3RoKTtcclxuICAgICAgICAgICAgcmV0dXJuIChoYXN2YWwobGFuZU51bSkgPyBsYW5lTnVtIDogc2VsZi5fbGFuZXMubGVuZ3RoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIGFkZEV2ZW50VG9MYW5lKGV2ZW50OiBUaW1lbGluZUV2ZW50TW9kZWwsIGxhbmVOdW06IG51bWJlcikge1xyXG4gICAgICAgICAgICBpZiAoIXNlbGYuX2xhbmVzW2xhbmVOdW1dKSB7XHJcbiAgICAgICAgICAgICAgICBzZWxmLl9sYW5lc1tsYW5lTnVtXSA9IGFsbG93TXVsdGlwbGVMYW5lcyA/IG5ldyBUaW1lbGluZUxhbmVTdGFjayh1aSkgOiBuZXcgVGltZWxpbmVMYW5lU2ltcGxlKHVpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzZWxmLl9sYW5lc1tsYW5lTnVtXS5hZGQoZXZlbnQpO1xyXG4gICAgICAgICAgICBzZWxmLl9sYW5lTnVtc1tldmVudC5ldmVudEd1aWRdID0gbGFuZU51bTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIGZpbGxWYWNhbmN5KHZhY2FuY3lMYW5lTnVtOiBudW1iZXIsIHZhY2FuY3lFZGdlc19QTUlMTElTOiBudW1iZXJbXSkge1xyXG4gICAgICAgICAgICBjb25zdCB2YWNhbmN5TGFuZSA9IHNlbGYuX2xhbmVzW3ZhY2FuY3lMYW5lTnVtXTtcclxuICAgICAgICAgICAgZm9yIChsZXQgbiA9IHZhY2FuY3lMYW5lTnVtICsgMTsgbiA8IHNlbGYuX2xhbmVzLmxlbmd0aDsgbisrKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsYW5lID0gc2VsZi5fbGFuZXNbbl07XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwb3NzaWJsZVRlbmFudHMgPSBsYW5lLmNvbGxpc2lvbnNXaXRoSW50ZXJ2YWwodmFjYW5jeUVkZ2VzX1BNSUxMSVNbMF0sIHZhY2FuY3lFZGdlc19QTUlMTElTWzFdKTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IHAgPSAwOyBwIDwgcG9zc2libGVUZW5hbnRzLmxlbmd0aDsgcCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBwb3NzaWJsZVRlbmFudHNbcF07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhY2FuY3lMYW5lLmNvdWxkRml0RXZlbnQoZXZlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhbmUucmVtb3ZlKGV2ZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYWRkRXZlbnRUb0xhbmUoZXZlbnQsIHZhY2FuY3lMYW5lTnVtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsbFZhY2FuY3kobiwgZWZmZWN0aXZlRWRnZXNfUE1JTExJUyh1aSwgZXZlbnQpKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHRyaW1FbXB0eUxhbmVzKCkge1xyXG4gICAgICAgICAgICBmb3IgKGxldCBuID0gc2VsZi5fbGFuZXMubGVuZ3RoIC0gMTsgbiA+PSAwOyBuLS0pIHtcclxuICAgICAgICAgICAgICAgIGlmIChzZWxmLl9sYW5lc1tuXS5pc0VtcHR5KCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBzZWxmLl9sYW5lcy5zcGxpY2UobiwgMSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gYWRkcyBldmVudCB0byBsYW5lLCBtYXkgYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzXHJcbiAgICAgICAgdGhpcy5fYWRkRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnRHdWlkOiBzdHJpbmcpIHtcclxuICAgICAgICAgICAgaWYgKGhhc3ZhbChzZWxmLl9sYW5lTnVtc1tldmVudEd1aWRdKSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdMYW5lcy1hcnJheSBhbHJlYWR5IGNvbnRhaW5zIHRoaXMgZXZlbnQ6IHJvdy1ndWlkID0gJyArIHJvdy5yb3dHdWlkICsgJywgbGFuZSA9ICcgKyBzZWxmLl9sYW5lTnVtc1tldmVudEd1aWRdICsgJywgZXZlbnQtZ3VpZCA9ICcgKyBldmVudEd1aWQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbW9kZWwuZXZlbnQoZXZlbnRHdWlkKTtcclxuICAgICAgICAgICAgY29uc3QgbGFuZU51bSA9IGZpcnN0QXZhaWxhYmxlTGFuZU51bShldmVudCk7XHJcbiAgICAgICAgICAgIGFkZEV2ZW50VG9MYW5lKGV2ZW50LCBsYW5lTnVtKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICByb3cuZXZlbnRHdWlkcy5mb3JFYWNoKHRoaXMuX2FkZEV2ZW50KTtcclxuICAgICAgICByb3cuZXZlbnRHdWlkcy52YWx1ZUFkZGVkLm9uKHRoaXMuX2FkZEV2ZW50KTtcclxuXHJcbiAgICAgICAgLy8gYXR0YWNoZXMgbGlzdGVuZXJzIHRvIGV2ZW50LCBzaG91bGQgYmUgY2FsbGVkIG9ubHkgb25jZVxyXG4gICAgICAgIC8vIHdoZW4gYW4gZXZlbnQgaXMgZmlyc3QgYWRkZWQgdG8gdGhlIHJvdyBtb2RlbFxyXG4gICAgICAgIHRoaXMuX25ld0V2ZW50ID0gZnVuY3Rpb24gKGV2ZW50R3VpZDogc3RyaW5nKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbW9kZWwuZXZlbnQoZXZlbnRHdWlkKTtcclxuICAgICAgICAgICAgbGV0IG9sZEVkZ2VzX1BNSUxMSVMgPSBlZmZlY3RpdmVFZGdlc19QTUlMTElTKHVpLCBldmVudCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZUxhbmVBc3NpZ25tZW50ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbmV3RWRnZXNfUE1JTExJUyA9IGVmZmVjdGl2ZUVkZ2VzX1BNSUxMSVModWksIGV2ZW50KTtcclxuICAgICAgICAgICAgICAgIGlmIChuZXdFZGdlc19QTUlMTElTWzBdICE9PSBvbGRFZGdlc19QTUlMTElTWzBdIHx8IG5ld0VkZ2VzX1BNSUxMSVNbMV0gIT09IG9sZEVkZ2VzX1BNSUxMSVNbMV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRMYW5lTnVtID0gc2VsZi5fbGFuZU51bXNbZXZlbnQuZXZlbnRHdWlkXTtcclxuICAgICAgICAgICAgICAgICAgICBjb