UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

432 lines 73.5 kB
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