1210 lines
180 KiB
JavaScript
1210 lines
180 KiB
JavaScript
/******************************************************************************
|
|
* Spine Runtimes License Agreement
|
|
* Last updated April 5, 2025. Replaces all prior versions.
|
|
*
|
|
* Copyright (c) 2013-2025, Esoteric Software LLC
|
|
*
|
|
* Integration of the Spine Runtimes into software or otherwise creating
|
|
* derivative works of the Spine Runtimes is permitted under the terms and
|
|
* conditions of Section 2 of the Spine Editor License Agreement:
|
|
* http://esotericsoftware.com/spine-editor-license
|
|
*
|
|
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
|
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
|
* "Products"), provided that each user of the Products must obtain their own
|
|
* Spine Editor license and redistribution of the Products in any form must
|
|
* include this license and copyright notice.
|
|
*
|
|
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
|
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*****************************************************************************/
|
|
/** biome-ignore-all lint/style/noNonNullAssertion: reference runtime expects some nullable to not be null */
|
|
import { Animation, AttachmentTimeline, DrawOrderFolderTimeline, DrawOrderTimeline, EventTimeline, MixFrom, RotateTimeline, Timeline } from "./Animation.js";
|
|
import { Interpolation, MathUtils, Pool, Utils } from "./Utils.js";
|
|
/** Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
|
|
* multiple animations on top of each other (layering).
|
|
*
|
|
* See [Applying Animations](http://esotericsoftware.com/spine-applying-animations#AnimationState-API) in the Spine Runtimes Guide. */
|
|
export class AnimationState {
|
|
static emptyAnimation = new Animation("<empty>", [], 0);
|
|
/** The AnimationStateData to look up mix durations. */
|
|
data;
|
|
/** The list of tracks that have had animations. May contain null entries for tracks that currently have no animation. */
|
|
tracks = [];
|
|
/** Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower
|
|
* or faster. Defaults to 1.
|
|
*
|
|
* See {@link TrackEntry.timeScale} to affect a single animation. */
|
|
timeScale = 1;
|
|
unkeyedState = 0;
|
|
events = [];
|
|
listeners = [];
|
|
queue = new EventQueue(this);
|
|
propertyIds = new Map();
|
|
animationsChanged = false;
|
|
trackEntryPool = new Pool(() => new TrackEntry());
|
|
constructor(data) {
|
|
this.data = data;
|
|
}
|
|
/** Increments each track entry {@link TrackEntry.trackTime}, setting queued animations as current if needed. */
|
|
update(delta) {
|
|
delta *= this.timeScale;
|
|
const tracks = this.tracks;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
const current = tracks[i];
|
|
if (!current)
|
|
continue;
|
|
current.animationLast = current.nextAnimationLast;
|
|
current.trackLast = current.nextTrackLast;
|
|
let currentDelta = delta * current.timeScale;
|
|
if (current.delay > 0) {
|
|
current.delay -= currentDelta;
|
|
if (current.delay > 0)
|
|
continue;
|
|
currentDelta = -current.delay;
|
|
current.delay = 0;
|
|
}
|
|
let next = current.next;
|
|
if (next) {
|
|
// When the next entry's delay is passed, change to the next entry, preserving leftover time.
|
|
const nextTime = current.trackLast - next.delay;
|
|
if (nextTime >= 0) {
|
|
next.delay = 0;
|
|
next.trackTime += current.timeScale === 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale;
|
|
current.trackTime += currentDelta;
|
|
this.setTrack(i, next, true);
|
|
while (next.mixingFrom) {
|
|
next.mixTime += delta;
|
|
next = next.mixingFrom;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
else if (current.trackLast >= current.trackEnd && !current.mixingFrom) {
|
|
tracks[i] = null;
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
continue;
|
|
}
|
|
if (current.mixingFrom && this.updateMixingFrom(current, delta)) {
|
|
// End mixing from entries once all have completed.
|
|
let from = current.mixingFrom;
|
|
current.mixingFrom = null;
|
|
if (from)
|
|
from.mixingTo = null;
|
|
while (from) {
|
|
this.queue.end(from);
|
|
from = from.mixingFrom;
|
|
}
|
|
}
|
|
current.trackTime += currentDelta;
|
|
}
|
|
this.queue.drain();
|
|
}
|
|
/** Returns true when all mixing from entries are complete. */
|
|
updateMixingFrom(to, delta) {
|
|
const from = to.mixingFrom;
|
|
if (!from)
|
|
return true;
|
|
const finished = this.updateMixingFrom(from, delta);
|
|
from.animationLast = from.nextAnimationLast;
|
|
from.trackLast = from.nextTrackLast;
|
|
// The from entry was applied at least once and the mix is complete.
|
|
if (to.nextTrackLast !== -1 && to.mixTime >= to.mixDuration) {
|
|
// Mixing is complete for all entries before the from entry or the mix is instantaneous.
|
|
if (from.totalAlpha === 0 || to.mixDuration === 0) {
|
|
to.mixingFrom = from.mixingFrom;
|
|
if (from.mixingFrom != null)
|
|
from.mixingFrom.mixingTo = to;
|
|
if (from.totalAlpha === 0) {
|
|
for (let next = to; next.mixingTo != null; next = next.mixingTo)
|
|
next.keepHold = true;
|
|
}
|
|
this.queue.end(from);
|
|
}
|
|
return finished;
|
|
}
|
|
from.trackTime += delta * from.timeScale;
|
|
to.mixTime += delta;
|
|
return false;
|
|
}
|
|
/** Poses the skeleton using the track entry animations. The animation state is not changed, so can be applied to multiple
|
|
* skeletons to pose them identically.
|
|
* @returns True if any animations were applied. */
|
|
apply(skeleton) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
if (this.animationsChanged)
|
|
this._animationsChanged();
|
|
const events = this.events;
|
|
const tracks = this.tracks;
|
|
let applied = false;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
const current = tracks[i];
|
|
if (!current || current.delay > 0)
|
|
continue;
|
|
applied = true;
|
|
// Apply mixing from entries first.
|
|
let alpha = current.alpha;
|
|
if (current.mixingFrom)
|
|
alpha *= this.applyMixingFrom(current, skeleton);
|
|
else if (current.trackTime >= current.trackEnd && !current.next)
|
|
alpha = 0;
|
|
// Apply current entry.
|
|
let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime;
|
|
let applyEvents = events;
|
|
if (current.reverse) {
|
|
applyTime = current.animation.duration - applyTime;
|
|
applyEvents = null;
|
|
}
|
|
const timelines = current.animation.timelines;
|
|
const timelineCount = timelines.length;
|
|
if ((i === 0 && alpha === 1)) {
|
|
for (let ii = 0; ii < timelineCount; ii++) {
|
|
// Fixes issue #302 on IOS9 where mix, blend sometimes became undefined and caused assets
|
|
// to sometimes stop rendering when using color correction, as their RGBA values become NaN.
|
|
// (https://github.com/pixijs/pixi-spine/issues/302)
|
|
Utils.webkit602BugfixHelper(alpha);
|
|
const timeline = timelines[ii];
|
|
if (timeline instanceof AttachmentTimeline)
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, MixFrom.setup, true);
|
|
else
|
|
timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, MixFrom.setup, false, false, false);
|
|
}
|
|
}
|
|
else {
|
|
const timelineMode = current.timelineMode;
|
|
const retainAttachments = alpha >= current.alphaAttachmentThreshold;
|
|
const add = current.additive, shortestRotation = add || current.shortestRotation;
|
|
const firstFrame = !shortestRotation && current.timelinesRotation.length !== timelineCount << 1;
|
|
if (firstFrame)
|
|
current.timelinesRotation.length = timelineCount << 1;
|
|
for (let ii = 0; ii < timelineCount; ii++) {
|
|
const timeline = timelines[ii];
|
|
const from = timelineMode[ii] & MODE;
|
|
if (!shortestRotation && timeline instanceof RotateTimeline) {
|
|
this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, from, current.timelinesRotation, ii << 1, firstFrame);
|
|
}
|
|
else if (timeline instanceof AttachmentTimeline) {
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, from, retainAttachments);
|
|
}
|
|
else {
|
|
// This fixes the WebKit 602 specific issue described at https://esotericsoftware.com/forum/d/10109-ios-10-disappearing-graphics
|
|
Utils.webkit602BugfixHelper(alpha);
|
|
timeline.apply(skeleton, animationLast, applyTime, applyEvents, alpha, from, add, false, false);
|
|
}
|
|
}
|
|
}
|
|
if (current.reverse)
|
|
this.eventsReverse(current, animationLast, animationTime);
|
|
this.queueEvents(current, animationTime);
|
|
events.length = 0;
|
|
current.nextAnimationLast = animationTime;
|
|
current.nextTrackLast = current.trackTime;
|
|
}
|
|
// Set slot attachments to the setup pose if they were set temporarily to apply deform timelines.
|
|
const setupState = this.unkeyedState + ATTACH_SETUP;
|
|
const slots = skeleton.slots;
|
|
for (let i = 0, n = skeleton.slots.length; i < n; i++) {
|
|
const slot = slots[i];
|
|
if (slot.attachmentState === setupState) {
|
|
const attachmentName = slot.data.attachmentName;
|
|
slot.pose.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));
|
|
}
|
|
}
|
|
this.unkeyedState += 2; // Reset.
|
|
this.queue.drain();
|
|
return applied;
|
|
}
|
|
applyMixingFrom(to, skeleton) {
|
|
const from = to.mixingFrom;
|
|
const fromMix = from.mixingFrom !== null ? this.applyMixingFrom(from, skeleton) : 1;
|
|
const mix = to.mix();
|
|
const a = from.alpha * fromMix, keep = 1 - mix * to.alpha;
|
|
const alphaMix = a * (1 - mix), alphaHold = keep > 0 ? alphaMix / keep : a;
|
|
const timelines = from.animation.timelines;
|
|
const timelineCount = timelines.length;
|
|
const timelineMode = from.timelineMode;
|
|
const timelineHoldMix = from.timelineHoldMix;
|
|
const retainAttachments = mix < from.mixAttachmentThreshold, drawOrder = mix < from.mixDrawOrderThreshold;
|
|
const add = from.additive, shortestRotation = add || from.shortestRotation;
|
|
const firstFrame = !shortestRotation && from.timelinesRotation.length !== timelineCount << 1;
|
|
if (firstFrame)
|
|
from.timelinesRotation.length = timelineCount << 1;
|
|
const timelinesRotation = from.timelinesRotation;
|
|
let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime;
|
|
let events = null;
|
|
if (from.reverse)
|
|
applyTime = from.animation.duration - applyTime;
|
|
else if (mix < from.eventThreshold) //
|
|
events = this.events;
|
|
from.totalAlpha = 0;
|
|
for (let i = 0; i < timelineCount; i++) {
|
|
const timeline = timelines[i];
|
|
const mode = timelineMode[i];
|
|
const mixFrom = mode & MODE;
|
|
let alpha = 0;
|
|
if ((mode & HOLD) !== 0) {
|
|
const holdMix = timelineHoldMix[i];
|
|
alpha = holdMix == null ? alphaHold : alphaHold * (1 - holdMix.mix());
|
|
}
|
|
else {
|
|
if (!drawOrder && timeline instanceof DrawOrderTimeline && mixFrom === MixFrom.current)
|
|
continue;
|
|
alpha = alphaMix;
|
|
}
|
|
from.totalAlpha += alpha;
|
|
if (!shortestRotation && timeline instanceof RotateTimeline) {
|
|
this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, mixFrom, timelinesRotation, i << 1, firstFrame);
|
|
}
|
|
else if (timeline instanceof AttachmentTimeline)
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, mixFrom, retainAttachments && alpha >= from.alphaAttachmentThreshold);
|
|
else {
|
|
const out = !drawOrder || !(timeline instanceof DrawOrderTimeline) || mixFrom === MixFrom.current;
|
|
timeline.apply(skeleton, animationLast, applyTime, events, alpha, mixFrom, add, out, false);
|
|
}
|
|
}
|
|
if (from.reverse && mix < from.eventThreshold)
|
|
this.eventsReverse(from, animationLast, animationTime);
|
|
if (to.mixDuration > 0)
|
|
this.queueEvents(from, animationTime);
|
|
this.events.length = 0;
|
|
from.nextAnimationLast = animationTime;
|
|
from.nextTrackLast = from.trackTime;
|
|
return mix;
|
|
}
|
|
/** Applies the attachment timeline and sets {@link Slot.attachmentState}.
|
|
* @param retain True if the attachment remains after apply, false if temporary for deform timelines. */
|
|
applyAttachmentTimeline(timeline, skeleton, time, from, retain) {
|
|
const slot = skeleton.slots[timeline.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
if (!retain && slot.attachmentState === this.unkeyedState + ATTACH_RETAIN)
|
|
return;
|
|
let setup = time < timeline.frames[0];
|
|
let name = null;
|
|
if (!setup) {
|
|
name = timeline.attachmentNames[Timeline.search(timeline.frames, time)];
|
|
setup = !retain && name == null;
|
|
}
|
|
if (setup) {
|
|
if (from === MixFrom.current)
|
|
return;
|
|
name = slot.data.attachmentName;
|
|
}
|
|
slot.pose.setAttachment(name == null ? null : skeleton.getAttachment(slot.data.index, name));
|
|
if (retain)
|
|
slot.attachmentState = this.unkeyedState + ATTACH_RETAIN;
|
|
else if (!setup) //
|
|
slot.attachmentState = this.unkeyedState + ATTACH_SETUP;
|
|
}
|
|
/** Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest
|
|
* the first time the mixing was applied. */
|
|
applyRotateTimeline(timeline, skeleton, time, alpha, from, timelinesRotation, i, firstFrame) {
|
|
if (firstFrame)
|
|
timelinesRotation[i] = 0;
|
|
if (alpha === 1) {
|
|
timeline.apply(skeleton, 0, time, null, 1, from, false, false, false);
|
|
return;
|
|
}
|
|
const bone = skeleton.bones[timeline.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
const pose = bone.pose, setup = bone.data.setupPose;
|
|
const frames = timeline.frames;
|
|
let r1, r2;
|
|
if (time < frames[0]) {
|
|
switch (from) {
|
|
case MixFrom.setup: {
|
|
pose.rotation = setup.rotation;
|
|
return;
|
|
}
|
|
case MixFrom.current: {
|
|
return;
|
|
}
|
|
}
|
|
r1 = pose.rotation;
|
|
r2 = setup.rotation;
|
|
}
|
|
else {
|
|
r1 = from === MixFrom.setup ? setup.rotation : pose.rotation;
|
|
r2 = setup.rotation + timeline.getCurveValue(time);
|
|
}
|
|
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
|
|
let total = 0, diff = r2 - r1;
|
|
diff -= Math.ceil(diff / 360 - 0.5) * 360;
|
|
if (diff === 0) {
|
|
total = timelinesRotation[i];
|
|
}
|
|
else {
|
|
let lastTotal = 0, lastDiff = 0;
|
|
if (firstFrame) {
|
|
lastTotal = 0;
|
|
lastDiff = diff;
|
|
}
|
|
else {
|
|
lastTotal = timelinesRotation[i];
|
|
lastDiff = timelinesRotation[i + 1];
|
|
}
|
|
const loops = lastTotal - lastTotal % 360;
|
|
total = diff + loops;
|
|
let current = diff >= 0, dir = lastTotal >= 0;
|
|
if (Math.abs(lastDiff) <= 90 && MathUtils.signum(lastDiff) !== MathUtils.signum(diff)) {
|
|
if (Math.abs(lastTotal - loops) > 180) {
|
|
total += 360 * MathUtils.signum(lastTotal);
|
|
dir = current;
|
|
}
|
|
else if (loops !== 0)
|
|
total -= 360 * MathUtils.signum(lastTotal);
|
|
else
|
|
dir = current;
|
|
}
|
|
if (dir !== current)
|
|
total += 360 * MathUtils.signum(lastTotal);
|
|
timelinesRotation[i] = total;
|
|
}
|
|
timelinesRotation[i + 1] = diff;
|
|
pose.rotation = r1 + total * alpha;
|
|
}
|
|
queueEvents(entry, animationTime) {
|
|
const animationStart = entry.animationStart, animationEnd = entry.animationEnd, duration = animationEnd - animationStart;
|
|
const reverse = entry.reverse;
|
|
let split = entry.trackLast % duration;
|
|
if (reverse)
|
|
split = duration - split;
|
|
// Queue events before complete.
|
|
const events = this.events;
|
|
let i = 0, n = events.length;
|
|
for (; i < n; i++) {
|
|
const event = events[i];
|
|
if ((event.time < split) !== reverse)
|
|
break; // java: if (event.time < split ^ reverse) break;
|
|
if (event.time >= animationStart && event.time <= animationEnd)
|
|
this.queue.event(entry, event);
|
|
}
|
|
// Queue complete if completed a loop iteration or the animation.
|
|
let complete = false;
|
|
if (entry.loop) {
|
|
if (duration === 0)
|
|
complete = true;
|
|
else {
|
|
const cycles = Math.floor(entry.trackTime / duration);
|
|
complete = cycles > 0 && cycles > Math.floor(entry.trackLast / duration);
|
|
}
|
|
}
|
|
else
|
|
complete = animationTime >= animationEnd && entry.animationLast < animationEnd;
|
|
if (complete)
|
|
this.queue.complete(entry);
|
|
// Queue events after complete.
|
|
for (; i < n; i++) {
|
|
const event = events[i];
|
|
if (event.time >= animationStart && event.time <= animationEnd)
|
|
this.queue.event(entry, event);
|
|
}
|
|
}
|
|
eventsReverse(entry, animationLast, animationTime) {
|
|
const duration = entry.animation.duration, from = duration - animationLast, to = duration - animationTime;
|
|
const timelines = entry.animation.timelines;
|
|
for (let i = 0, n = entry.animation.timelines.length; i < n; i++) {
|
|
const eventTimeline = timelines[i];
|
|
if (!(eventTimeline instanceof EventTimeline))
|
|
continue;
|
|
const timelineEvents = eventTimeline.events;
|
|
const frames = eventTimeline.frames;
|
|
const frameCount = frames.length;
|
|
if (from >= to) { // from -> to
|
|
for (let ii = 0; ii < frameCount; ii++) {
|
|
if (frames[ii] < to)
|
|
continue;
|
|
if (frames[ii] >= from)
|
|
break;
|
|
this.events.push(timelineEvents[ii]);
|
|
}
|
|
}
|
|
else {
|
|
for (let ii = 0; ii < frameCount; ii++) { // from -> 0
|
|
if (frames[ii] >= from)
|
|
break;
|
|
this.events.push(timelineEvents[ii]);
|
|
}
|
|
let ii = 0; // end -> to
|
|
for (; ii < frameCount; ii++)
|
|
if (frames[ii] >= to)
|
|
break;
|
|
for (; ii < frameCount; ii++)
|
|
this.events.push(timelineEvents[ii]);
|
|
}
|
|
}
|
|
}
|
|
/** Removes all animations from all tracks, leaving skeletons in their current pose.
|
|
*
|
|
* Usually you want to use {@link setEmptyAnimations} to mix the skeletons back to the setup pose, rather than leaving
|
|
* them in their current pose. */
|
|
clearTracks() {
|
|
const oldDrainDisabled = this.queue.drainDisabled;
|
|
this.queue.drainDisabled = true;
|
|
for (let i = 0, n = this.tracks.length; i < n; i++)
|
|
this.clearTrack(i);
|
|
this.tracks.length = 0;
|
|
this.queue.drainDisabled = oldDrainDisabled;
|
|
this.queue.drain();
|
|
}
|
|
/** Removes all animations from the track, leaving skeletons in their current pose.
|
|
*
|
|
* Usually you want to use {@link setEmptyAnimation} to mix the skeletons back to the setup pose, rather than
|
|
* leaving them in their current pose. */
|
|
clearTrack(trackIndex) {
|
|
if (trackIndex < 0)
|
|
throw new Error("trackIndex must be >= 0.");
|
|
if (trackIndex >= this.tracks.length)
|
|
return;
|
|
const current = this.tracks[trackIndex];
|
|
if (!current)
|
|
return;
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
let entry = current;
|
|
while (true) {
|
|
const from = entry.mixingFrom;
|
|
if (!from)
|
|
break;
|
|
this.queue.end(from);
|
|
entry.mixingFrom = null;
|
|
entry.mixingTo = null;
|
|
entry = from;
|
|
}
|
|
this.tracks[current.trackIndex] = null;
|
|
this.queue.drain();
|
|
}
|
|
setTrack(index, current, interrupt) {
|
|
const from = this.expandToIndex(index);
|
|
this.tracks[index] = current;
|
|
current.previous = null;
|
|
if (from) {
|
|
from.next = null;
|
|
if (interrupt)
|
|
this.queue.interrupt(from);
|
|
current.mixingFrom = from;
|
|
from.mixingTo = current;
|
|
current.mixTime = 0;
|
|
from.timelinesRotation.length = 0; // Reset rotation for mixing out, in case entry was mixed in.
|
|
}
|
|
this.queue.start(current);
|
|
}
|
|
setAnimation(trackIndex, animationNameOrAnimation, loop = false) {
|
|
if (typeof animationNameOrAnimation === "string")
|
|
return this.setAnimation1(trackIndex, animationNameOrAnimation, loop);
|
|
return this.setAnimation2(trackIndex, animationNameOrAnimation, loop);
|
|
}
|
|
setAnimation1(trackIndex, animationName, loop = false) {
|
|
const animation = this.data.skeletonData.findAnimation(animationName);
|
|
if (!animation)
|
|
throw new Error(`Animation not found: ${animationName}`);
|
|
return this.setAnimation2(trackIndex, animation, loop);
|
|
}
|
|
/** Sets the current animation for a track, discarding any queued animations.
|
|
*
|
|
* If the formerly current track entry is for the same animation and was never applied to a skeleton, it is replaced (not mixed
|
|
* from).
|
|
* @param loop If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
|
|
* duration. In either case {@link TrackEntry.getTrackEnd} determines when the track is cleared.
|
|
* @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
|
* after the {@link AnimationStateListener.dispose} event occurs. */
|
|
setAnimation2(trackIndex, animation, loop = false) {
|
|
if (trackIndex < 0)
|
|
throw new Error("trackIndex must be >= 0.");
|
|
if (!animation)
|
|
throw new Error("animation cannot be null.");
|
|
let interrupt = true;
|
|
let current = this.expandToIndex(trackIndex);
|
|
if (current) {
|
|
if (current.nextTrackLast === -1 && current.animation === animation) {
|
|
// Don't mix from an entry that was never applied.
|
|
this.tracks[trackIndex] = current.mixingFrom;
|
|
this.queue.interrupt(current);
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
current = current.mixingFrom;
|
|
interrupt = false;
|
|
}
|
|
else
|
|
this.clearNext(current);
|
|
}
|
|
const entry = this.trackEntry(trackIndex, animation, loop, current);
|
|
this.setTrack(trackIndex, entry, interrupt);
|
|
this.queue.drain();
|
|
return entry;
|
|
}
|
|
addAnimation(trackIndex, animationNameOrAnimation, loop = false, delay = 0) {
|
|
if (typeof animationNameOrAnimation === "string")
|
|
return this.addAnimation1(trackIndex, animationNameOrAnimation, loop, delay);
|
|
return this.addAnimation2(trackIndex, animationNameOrAnimation, loop, delay);
|
|
}
|
|
addAnimation1(trackIndex, animationName, loop = false, delay = 0) {
|
|
const animation = this.data.skeletonData.findAnimation(animationName);
|
|
if (!animation)
|
|
throw new Error(`Animation not found: ${animationName}`);
|
|
return this.addAnimation2(trackIndex, animation, loop, delay);
|
|
}
|
|
addAnimation2(trackIndex, animation, loop = false, delay = 0) {
|
|
if (trackIndex < 0)
|
|
throw new Error("trackIndex must be >= 0.");
|
|
if (!animation)
|
|
throw new Error("animation cannot be null.");
|
|
let last = this.expandToIndex(trackIndex);
|
|
if (last) {
|
|
while (last.next)
|
|
last = last.next;
|
|
}
|
|
const entry = this.trackEntry(trackIndex, animation, loop, last);
|
|
if (!last) {
|
|
this.setTrack(trackIndex, entry, true);
|
|
this.queue.drain();
|
|
if (delay < 0)
|
|
delay = 0;
|
|
}
|
|
else {
|
|
last.next = entry;
|
|
entry.previous = last;
|
|
if (delay <= 0)
|
|
delay = Math.max(delay + last.getTrackComplete() - entry.mixDuration, 0);
|
|
}
|
|
entry.delay = delay;
|
|
return entry;
|
|
}
|
|
/** Sets an empty animation for a track, discarding any queued animations, and sets the track entry's
|
|
* {@link TrackEntry.mixduration}. An empty animation has no timelines and serves as a placeholder for mixing in or out.
|
|
*
|
|
* Mixing out is done by setting an empty animation with a mix duration using either {@link setEmptyAnimation},
|
|
* {@link setEmptyAnimations}, or {@link addEmptyAnimation}. Mixing to an empty animation causes
|
|
* the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation
|
|
* transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of
|
|
* 0 still needs to be applied one more time to mix out, so the properties it was animating are reverted.
|
|
*
|
|
* Mixing in is done by first setting an empty animation, then adding an animation using
|
|
* {@link addAnimation} with the desired delay (an empty animation has a duration of 0) and on
|
|
* the returned track entry, set the {@link TrackEntry.setMixDuration}. Mixing from an empty animation causes the new
|
|
* animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value
|
|
* from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new animation.
|
|
*
|
|
* See <a href='https://esotericsoftware.com/spine-applying-animations#Empty-animations'>Empty animations</a> in the Spine
|
|
* Runtimes Guide. */
|
|
setEmptyAnimation(trackIndex, mixDuration = 0) {
|
|
const entry = this.setAnimation(trackIndex, AnimationState.emptyAnimation, false);
|
|
entry.mixDuration = mixDuration;
|
|
entry.trackEnd = mixDuration;
|
|
return entry;
|
|
}
|
|
/** Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
|
|
* {@link TrackEntry.mixDuration}. If the track has no entries, it is equivalent to calling
|
|
* {@link setEmptyAnimation}.
|
|
*
|
|
* See {@link setEmptyAnimation} and
|
|
* <a href='https://esotericsoftware.com/spine-applying-animations#Empty-animations'>Empty animations</a> in the Spine Runtimes
|
|
* Guide.
|
|
* @param delay If > 0, sets {@link TrackEntry.delay}. If <= 0, the delay set is the duration of the previous track entry minus
|
|
* any mix duration plus the specified `delay` (ie the mix ends at (when `delay` = 0) or before
|
|
* (when `delay` < 0) the previous track entry duration). If the previous entry is looping, its next loop
|
|
* completion is used instead of its duration.
|
|
* @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
|
|
* after the {@link AnimationStateListener.dispose} event occurs. */
|
|
addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) {
|
|
const entry = this.addAnimation(trackIndex, AnimationState.emptyAnimation, false, delay);
|
|
if (delay <= 0)
|
|
entry.delay = Math.max(entry.delay + entry.mixDuration - mixDuration, 0);
|
|
entry.mixDuration = mixDuration;
|
|
entry.trackEnd = mixDuration;
|
|
return entry;
|
|
}
|
|
/** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration.
|
|
*
|
|
* See <a href='https://esotericsoftware.com/spine-applying-animations#Empty-animations'>Empty animations</a> in the Spine
|
|
* Runtimes Guide. */
|
|
setEmptyAnimations(mixDuration = 0) {
|
|
const oldDrainDisabled = this.queue.drainDisabled;
|
|
this.queue.drainDisabled = true;
|
|
for (let i = 0, n = this.tracks.length; i < n; i++) {
|
|
const current = this.tracks[i];
|
|
if (current)
|
|
this.setEmptyAnimation(current.trackIndex, mixDuration);
|
|
}
|
|
this.queue.drainDisabled = oldDrainDisabled;
|
|
this.queue.drain();
|
|
}
|
|
expandToIndex(index) {
|
|
if (index < this.tracks.length)
|
|
return this.tracks[index];
|
|
Utils.ensureArrayCapacity(this.tracks, index + 1, null);
|
|
this.tracks.length = index + 1;
|
|
return null;
|
|
}
|
|
/** @param last May be null. */
|
|
trackEntry(trackIndex, animation, loop, last) {
|
|
const entry = this.trackEntryPool.obtain();
|
|
entry.reset();
|
|
entry.trackIndex = trackIndex;
|
|
entry.animation = animation;
|
|
entry.loop = loop;
|
|
entry.additive = false;
|
|
entry.reverse = false;
|
|
entry.shortestRotation = false;
|
|
entry.eventThreshold = 0;
|
|
entry.alphaAttachmentThreshold = 0;
|
|
entry.mixAttachmentThreshold = 0;
|
|
entry.mixDrawOrderThreshold = 0;
|
|
entry.animationStart = 0;
|
|
entry.animationEnd = animation.duration;
|
|
entry.animationLast = -1;
|
|
entry.nextAnimationLast = -1;
|
|
entry.delay = 0;
|
|
entry.trackTime = 0;
|
|
entry.trackLast = -1;
|
|
entry.nextTrackLast = -1;
|
|
entry.trackEnd = Number.MAX_VALUE;
|
|
entry.timeScale = 1;
|
|
entry.alpha = 1;
|
|
entry.mixTime = 0;
|
|
entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation);
|
|
entry.totalAlpha = 0;
|
|
entry.keepHold = false;
|
|
return entry;
|
|
}
|
|
/** Removes {@link TrackEntry.next} and all entries after it for the specified entry. */
|
|
clearNext(entry) {
|
|
let next = entry.next;
|
|
while (next) {
|
|
this.queue.dispose(next);
|
|
next = next.next;
|
|
}
|
|
entry.next = null;
|
|
}
|
|
_animationsChanged() {
|
|
this.animationsChanged = false;
|
|
const tracks = this.tracks;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
const track = tracks[i];
|
|
if (!track)
|
|
continue;
|
|
let entry = track;
|
|
while (entry.mixingFrom)
|
|
entry = entry.mixingFrom;
|
|
do {
|
|
this.computeHold(entry, track);
|
|
entry = entry.mixingTo;
|
|
} while (entry);
|
|
}
|
|
this.propertyIds.clear();
|
|
}
|
|
computeHold(entry, track) {
|
|
const timelines = entry.animation.timelines;
|
|
const timelinesCount = entry.animation.timelines.length;
|
|
const timelineMode = entry.timelineMode;
|
|
timelineMode.length = timelinesCount;
|
|
const timelineHoldMix = entry.timelineHoldMix;
|
|
timelineHoldMix.length = 0;
|
|
const add = entry.additive, keepHold = entry.keepHold;
|
|
const to = entry.mixingTo;
|
|
for (let i = 0; i < timelinesCount; i++) {
|
|
const timeline = timelines[i];
|
|
const ids = timeline.propertyIds;
|
|
const from = this.from(track, timeline, ids);
|
|
if (add && timeline.additive) {
|
|
timelineMode[i] = from;
|
|
continue;
|
|
}
|
|
// Hold if the next entry will overwrite this property.
|
|
let mode;
|
|
if (to === null || timeline.instant || (to.additive && timeline.additive) || !to.animation?.hasTimeline(ids))
|
|
mode = from;
|
|
else {
|
|
mode = from | HOLD;
|
|
// Find next entry that doesn't overwrite this property. Its mix fades out the hold, instead of it ending abruptly.
|
|
for (let next = to.mixingTo; next != null; next = next.mixingTo) {
|
|
if ((next.additive && timeline.additive) || !next.animation?.hasTimeline(ids)) {
|
|
if (next.mixDuration > 0)
|
|
timelineHoldMix[i] = next;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (keepHold)
|
|
mode = (mode & ~HOLD) | (timelineMode[i] & HOLD);
|
|
timelineMode[i] = mode;
|
|
}
|
|
}
|
|
from(track, timeline, ids) {
|
|
const propertyIds = this.propertyIds;
|
|
let from = SETUP;
|
|
// Reference runtime uses LongMap.putMissing. Map has no equivalent, so get/set preserves those semantics here.
|
|
for (let i = 0, n = ids.length; i < n; i++) {
|
|
const owner = propertyIds.get(ids[i]);
|
|
if (owner === undefined) {
|
|
propertyIds.set(ids[i], track);
|
|
}
|
|
else {
|
|
if (owner !== track) {
|
|
while (++i < n)
|
|
if (!propertyIds.has(ids[i]))
|
|
propertyIds.set(ids[i], track);
|
|
return CURRENT;
|
|
}
|
|
from = FIRST;
|
|
}
|
|
}
|
|
if (timeline instanceof DrawOrderFolderTimeline) {
|
|
const first = propertyIds.get(DrawOrderTimeline.propertyID);
|
|
if (first != null)
|
|
return first !== track ? CURRENT : FIRST;
|
|
}
|
|
return from;
|
|
}
|
|
/** Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing. */
|
|
getTrack(trackIndex) {
|
|
if (trackIndex < 0)
|
|
throw new Error("trackIndex must be >= 0.");
|
|
if (trackIndex >= this.tracks.length)
|
|
return null;
|
|
return this.tracks[trackIndex];
|
|
}
|
|
/** Adds a listener to receive events for all track entries. */
|
|
addListener(listener) {
|
|
if (!listener)
|
|
throw new Error("listener cannot be null.");
|
|
this.listeners.push(listener);
|
|
}
|
|
/** Removes the listener added with {@link addListener}. */
|
|
removeListener(listener) {
|
|
const index = this.listeners.indexOf(listener);
|
|
if (index >= 0)
|
|
this.listeners.splice(index, 1);
|
|
}
|
|
/** Removes all listeners added with {@link addListener}. */
|
|
clearListeners() {
|
|
this.listeners.length = 0;
|
|
}
|
|
/** Discards all listener notifications that have not yet been delivered. This can be useful to call from an
|
|
* {@link AnimationStateListener} when it is known that further notifications that may have been already queued for delivery
|
|
* are not wanted because new animations are being set. */
|
|
clearListenerNotifications() {
|
|
this.queue.clear();
|
|
}
|
|
}
|
|
/** Stores settings and other state for the playback of an animation on an {@link AnimationState} track.
|
|
*
|
|
* References to a track entry must not be kept after the {@link AnimationStateListener.dispose} event occurs. */
|
|
export class TrackEntry {
|
|
/** The animation to apply for this track entry. */
|
|
animation = null;
|
|
previous = null;
|
|
/** The animation queued to start after this animation, or null. `next` makes up a linked list. */
|
|
next = null;
|
|
/** The track entry for the previous animation when mixing to this animation, or null if no mixing is currently occurring.
|
|
* When mixing from multiple animations, `mixingFrom` makes up a doubly linked list. */
|
|
mixingFrom = null;
|
|
/** The track entry for the next animation when mixing from this animation, or null if no mixing is currently occurring.
|
|
* When mixing to multiple animations, `mixingTo` makes up a doubly linked list. */
|
|
mixingTo = null;
|
|
/** The listener for events generated by this track entry, or null.
|
|
*
|
|
* A track entry returned from {@link AnimationState.setAnimation} is already the current animation
|
|
* for the track, so the callback for listener {@link AnimationStateListener.start} will not be called. */
|
|
listener = null;
|
|
/** The index of the track where this track entry is either current or queued.
|
|
*
|
|
* See {@link AnimationState.getTrack}. */
|
|
trackIndex = 0;
|
|
/** If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
|
|
* duration. */
|
|
loop = false;
|
|
/** When true, timelines in this animation that support additive have their values added to the setup or current pose values
|
|
* instead of replacing them. Additive can be set for a new track entry only before {@link AnimationState.apply}
|
|
* is next called. */
|
|
additive = false;
|
|
/** If true, the animation will be applied in reverse. */
|
|
reverse = false;
|
|
/** If true, mixing rotation between tracks always uses the shortest rotation direction. If the rotation is animated, the
|
|
* shortest rotation direction may change during the mix.
|
|
*
|
|
* If false, the shortest rotation direction is remembered when the mix starts and the same direction is used for the rest
|
|
* of the mix. Defaults to false.
|
|
*
|
|
* See {@link resetRotationDirections}. */
|
|
shortestRotation = false;
|
|
keepHold = false;
|
|
/** When the interpolated mix percentage is less than the `eventThreshold` , event timelines are applied while
|
|
* this animation is being mixed out. Defaults to 0, so event timelines are not applied while this animation is being mixed
|
|
* out. */
|
|
eventThreshold = 0;
|
|
/** When the interpolated mix percentage is less than the `mixAttachmentThreshold`, attachment timelines are
|
|
* applied while this animation is being mixed out. Defaults to 0, so attachment timelines are not applied while this
|
|
* animation is being mixed out. */
|
|
mixAttachmentThreshold = 0;
|
|
/** When the computed alpha is greater than `alphaAttachmentThreshold`, attachment timelines are applied. The
|
|
* computed alpha includes {@link alpha} and the interpolated mix percentage. Defaults to 0, so attachment timelines are
|
|
* always applied. */
|
|
alphaAttachmentThreshold = 0;
|
|
/** When the interpolated mix percentage is less than the `mixAttachmentThreshold`, attachment timelines are
|
|
* applied while this animation is being mixed out. Defaults to 0, so attachment timelines are not applied while this
|
|
* animation is being mixed out. */
|
|
mixDrawOrderThreshold = 0;
|
|
/** The time in seconds for the first frame of this animation, both initially and after looping. Defaults to 0.
|
|
*
|
|
* When setting `animationStart` time, {@link animationLast} can be set to the same value to avoid firing events
|
|
* from the start of the animation. */
|
|
animationStart = 0;
|
|
/** The time in seconds for the last frame of this animation. Past this time, non-looping animations hold the pose at this
|
|
* time while looping animations will loop back to {@link animationStart}. Defaults to the {@link Animation.duration}. */
|
|
animationEnd = 0;
|
|
/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. For example, when
|
|
* this animation is applied, event timelines will fire all events between the `animationLast` time (exclusive)
|
|
* and `animationTime` (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this
|
|
* animation is applied. */
|
|
animationLast = 0;
|
|
nextAnimationLast = 0;
|
|
/** Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry,
|
|
* `delay` postpones incrementing the {@link trackTime}. When this track entry is queued, `delay` is
|
|
* the time from the start of the previous animation to when this track entry will become the current track entry (ie when
|
|
* the previous track entry {@link trackTime} >= this track entry's `delay`).
|
|
*
|
|
* {@link timeScale} affects the delay.
|
|
*
|
|
* When passing `delay` <= 0 to {@link AnimationState.addAnimation} this
|
|
* `delay` is set using a mix duration from {@link AnimationStateData}. To change the {@link mixDuration}
|
|
* afterward, use {@link setMixDuration} so this `delay` is adjusted. */
|
|
delay = 0;
|
|
/** The time in seconds this track entry has been the current track entry, starting at 0 and increasing forever. Compare to
|
|
* {@link getAnimationTime}, which is always between {@link animationStart} and {@link animationEnd}.
|
|
*
|
|
* The track time can be set to start the animation at a time other than 0, without affecting looping. When doing so,
|
|
* {@link animationLast} can be set to the same value to avoid firing events from the start of the animation.
|
|
*
|
|
* To set the time an animation starts and loops, use {@link animationStart} and {@link animationEnd}. */
|
|
trackTime = 0;
|
|
trackLast = 0;
|
|
nextTrackLast = 0;
|
|
/** The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float
|
|
* value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time
|
|
* is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the
|
|
* properties keyed by the animation are set to the setup pose and the track is cleared.
|
|
*
|
|
* Usually you want to use {@link AnimationState.addEmptyAnimation} rather than have the animation
|
|
* abruptly cease being applied, leaving the current pose. */
|
|
trackEnd = 0;
|
|
/** Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or
|
|
* faster. Defaults to 1.
|
|
*
|
|
* Values < 0 are not supported. To play an animation in reverse, use {@link reverse}.
|
|
*
|
|
* {@link mixTime} is not affected by track entry time scale, so {@link mixDuration} may need to be adjusted to match the
|
|
* animation speed.
|
|
*
|
|
* When using {@link AnimationState.addAnimation} with a `delay` <= 0, the
|
|
* {@link delay} is set using the mix duration from {@link AnimationState.data}, assuming time scale to be 1. If the time
|
|
* scale is not 1, the delay may need to be adjusted.
|
|
*
|
|
* See {@link AnimationState.timeScale} to affect all animations. */
|
|
timeScale = 0;
|
|
/** Values < 1 mix this animation with the skeleton's current pose (either the setup pose or the pose from lower tracks).
|
|
* Defaults to 1, which overwrites the skeleton's current pose with this animation.
|
|
*
|
|
* Alpha should be 1 on track 0.
|
|
*
|
|
* See {@link getAlphaAttachmentThreshold}. */
|
|
alpha = 0;
|
|
/** Seconds elapsed from 0 to the {@link mixDuration} when mixing from the previous animation to this animation. May
|
|
* be slightly more than `mixDuration` when the mix is complete. */
|
|
mixTime = 0;
|
|
/** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by
|
|
* {@link AnimationStateData.getMix} based on the animation before this animation (if any).
|
|
*
|
|
* A mix duration of 0 still needs to be applied one more time to mix out, so the the properties it was animating are
|
|
* reverted. A mix duration of 0 can be set at any time to end the mix on the next
|
|
* {@link AnimationState.update | update}.
|
|
*
|
|
* The `mixDuration` can be set manually rather than use the value from
|
|
* {@link AnimationStateData.getMix}. In that case, the `mixDuration` can be set for a new
|
|
* track entry only before {@link AnimationState.update} is next called.
|
|
*
|
|
* When using {@link AnimationState.addAnimation} with a `delay` <= 0, the
|
|
* {@link getDelay} is set using the mix duration from {@link AnimationState.data}. If `mixDuration` is set
|
|
* afterward, the delay needs to be adjusted:
|
|
*
|
|
* <pre>
|
|
* entry.mixDuration = 0.25;<br>
|
|
* entry.delay = entry.previous.getTrackComplete() - entry.mixDuration + 0;
|
|
* </pre>
|
|
*
|
|
* Alternatively, use {@link setMixDuration} to set both the mix duration and recompute the delay:<br>
|
|
*
|
|
* <pre>
|
|
entry.setMixDuration(0.25f, 0); // mixDuration, delay
|
|
* </pre>
|
|
*/
|
|
mixDuration = 0;
|
|
totalAlpha = 0;
|
|
mixInterpolation = Interpolation.linear;
|
|
/** Sets both {@link getMixDuration} and {@link getDelay}.
|
|
* @param delay If > 0, sets {@link getDelay}. If <= 0, the delay set is the duration of the previous track entry minus
|
|
* the specified mix duration plus the specified `delay` (ie the mix ends at (when `delay` =
|
|
* 0) or before (when `delay` < 0) the previous track entry duration). If the previous entry is
|
|
* looping, its next loop completion is used instead of its duration. */
|
|
setMixDuration(mixDuration, delay) {
|
|
this.mixDuration = mixDuration;
|
|
if (delay !== undefined) {
|
|
if (delay <= 0)
|
|
delay = this.previous == null ? 0 : Math.max(delay + this.previous.getTrackComplete() - mixDuration, 0);
|
|
this.delay = delay;
|
|
}
|
|
}
|
|
/** The interpolation to apply to the mix percentage ({@link mixTime} / {@link mixDuration}) when mixing from the previous
|
|
* animation to this animation. Defaults to linear. */
|
|
setMixInterpolation(mixInterpolation) {
|
|
if (!mixInterpolation)
|
|
throw new Error("mixInterpolation cannot be null.");
|
|
this.mixInterpolation = mixInterpolation;
|
|
}
|
|
mix() {
|
|
if (this.mixDuration === 0)
|
|
return 1;
|
|
let mix = this.mixTime / this.mixDuration;
|
|
if (mix >= 1)
|
|
return 1;
|
|
if (this.mixInterpolation === Interpolation.linear)
|
|
return mix;
|
|
mix = this.mixInterpolation.apply(mix);
|
|
if (mix < 0)
|
|
return 0;
|
|
if (mix > 1)
|
|
return 1;
|
|
return mix;
|
|
}
|
|
/** For each timeline:
|
|
* - Bits 0-1: MixFrom.
|
|
* - Bit 2, HOLD: 0 = mix out using alphaMix, 1 = apply full alpha to prevent dipping. Timeline is first on its track to
|
|
* set the property and the next entry (mixingTo) also sets it. When held, timelineHoldMix's mix controls how the hold fades
|
|
* out (for 3+ entry chains where the chain eventually stops setting the property). */
|
|
timelineMode = [];
|
|
timelineHoldMix = [];
|
|
timelinesRotation = [];
|
|
reset() {
|
|
this.next = null;
|
|
this.previous = null;
|
|
this.mixingFrom = null;
|
|
this.mixingTo = null;
|
|
this.mixInterpolation = Interpolation.linear;
|
|
this.animation = null;
|
|
this.listener = null;
|
|
this.timelineMode.length = 0;
|
|
this.timelineHoldMix.length = 0;
|
|
this.timelinesRotation.length = 0;
|
|
}
|
|
/** Uses {@link trackTime} to compute the `animationTime`, which is always between {@link animationStart} and
|
|
* {@link animationEnd}. When `trackTime` is 0, `animationTime` is equal to the
|
|
* `animationStart` time. */
|
|
getAnimationTime() {
|
|
if (!this.loop)
|
|
return Math.min(this.trackTime + this.animationStart, this.animationEnd);
|
|
const duration = this.animationEnd - this.animationStart;
|
|
if (duration === 0)
|
|
return this.animationStart;
|
|
return (this.trackTime % duration) + this.animationStart;
|
|
}
|
|
setAnimationLast(animationLast) {
|
|
this.animationLast = animationLast;
|
|
this.nextAnimationLast = animationLast;
|
|
}
|
|
/** Returns true if at least one loop has been completed.
|
|
*
|
|
* See {@link AnimationStateListener.complete}. */
|
|
isComplete() {
|
|
return this.trackTime >= this.animationEnd - this.animationStart;
|
|
}
|
|
/** When {@link shortestRotation} is false, this clears the directions for mixing this entry's rotation. This can be useful
|
|
* to avoid bones rotating the long way around when using {@link getAlpha} and starting animations on other tracks.
|
|
*
|
|
* Mixing involves finding a rotation between two others. There are two possible solutions: the short or the long way
|
|
* around. When the two rotations change over time, which direction is the short or long way can also change. If the short
|
|
* way was always chosen, bones flip to the other side when that direction became the long way. TrackEntry chooses the short
|
|
* way the first time it is applied and remembers that direction. Resetting that direction makes it choose a new short way
|
|
* on the next apply. */
|
|
resetRotationDirections() {
|
|
this.timelinesRotation.length = 0;
|
|
}
|
|
/** If this track entry is non-looping, this is the track time in seconds when {@link animationEnd} is reached, or the
|
|
* current {@link trackTime} if it has already been reached.
|
|
*
|
|
* If this track entry is looping, this is the track time when this animation will reach its next {@link animationEnd} (the
|
|
* next loop completion). */
|
|
getTrackComplete() {
|
|
const duration = this.animationEnd - this.animationStart;
|
|
if (duration !== 0) {
|
|
if (this.loop)
|
|
return duration * (1 + ((this.trackTime / duration) | 0)); // Completion of next loop.
|
|
if (this.trackTime < duration)
|
|
return duration; // Before duration.
|
|
}
|
|
return this.trackTime; // Next update.
|
|
}
|
|
/** Returns true if this track entry has been applied at least once.
|
|
*
|
|
* See {@link AnimationState.apply}. */
|
|
wasApplied() {
|
|
return this.nextTrackLast !== -1;
|
|
}
|
|
/** Returns true if there is a {@link next} track entry and it will become the current track entry during the next
|
|
* {@link AnimationState.update}. */
|
|
isNextReady() {
|
|
return this.next != null && this.nextTrackLast - this.next.delay >= 0;
|
|
}
|
|
}
|
|
export class EventQueue {
|
|
objects = [];
|
|
drainDisabled = false;
|
|
animState;
|
|
constructor(animState) {
|
|
this.animState = animState;
|
|
}
|
|
start(entry) {
|
|
this.objects.push(EventType.start);
|
|
this.objects.push(entry);
|
|
this.animState.animationsChanged = true;
|
|
}
|
|
interrupt(entry) {
|
|
this.objects.push(EventType.interrupt);
|
|
this.objects.push(entry);
|
|
}
|
|
end(entry) {
|
|
this.objects.push(EventType.end);
|
|
this.objects.push(entry);
|
|
this.animState.animationsChanged = true;
|
|
}
|
|
dispose(entry) {
|
|
this.objects.push(EventType.dispose);
|
|
this.objects.push(entry);
|
|
}
|
|
complete(entry) {
|
|
this.objects.push(EventType.complete);
|
|
this.objects.push(entry);
|
|
}
|
|
event(entry, event) {
|
|
this.objects.push(EventType.event);
|
|
this.objects.push(entry);
|
|
this.objects.push(event);
|
|
}
|
|
drain() {
|
|
if (this.drainDisabled)
|
|
return; // Not reentrant.
|
|
this.drainDisabled = true;
|
|
for (let i = 0; i < this.objects.length; i += 2) {
|
|
const objects = this.objects;
|
|
const type = objects[i];
|
|
const entry = objects[i + 1];
|
|
const listeners = this.animState.listeners.slice();
|
|
switch (type) {
|
|
case EventType.start:
|
|
if (entry.listener?.start)
|
|
entry.listener.start(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
const listener = listeners[ii];
|
|
if (listener.start)
|
|
listener.start(entry);
|
|
}
|
|
break;
|
|
case EventType.interrupt:
|
|
if (entry.listener?.interrupt)
|
|
entry.listener.interrupt(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
const listener = listeners[ii];
|
|
if (listener.interrupt)
|
|
listener.interrupt(entry);
|
|
}
|
|
break;
|
|
// biome-ignore lint/suspicious/noFallthroughSwitchClause: reference runtime does fall through
|
|
case EventType.end:
|
|
if (entry.listener?.end)
|
|
entry.listener.end(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
const listener = listeners[ii];
|
|
if (listener.end)
|
|
listener.end(entry);
|
|
}
|
|
// Fall through.
|
|
case EventType.dispose:
|
|
if (entry.listener?.dispose)
|
|
entry.listener.dispose(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
const listener = listeners[ii];
|
|
if (listener.dispose)
|
|
listener.dispose(entry);
|
|
}
|
|
this.animState.trackEntryPool.free(entry);
|
|
break;
|
|
case EventType.complete:
|
|
if (entry.listener?.complete)
|
|
entry.listener.complete(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
const listener = listeners[ii];
|
|
if (listener.complete)
|
|
listener.complete(entry);
|
|
}
|
|
break;
|
|
case EventType.event: {
|
|
const event = objects[i++ + 2];
|
|
if (entry.listener?.event)
|
|
entry.listener.event(entry, event);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
const listener = listeners[ii];
|
|
if (listener.event)
|
|
listener.event(entry, event);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
this.clear();
|
|
this.drainDisabled = false;
|
|
}
|
|
clear() {
|
|
this.objects.length = 0;
|
|
}
|
|
}
|
|
export var EventType;
|
|
(function (EventType) {
|
|
EventType[EventType["start"] = 0] = "start";
|
|
EventType[EventType["interrupt"] = 1] = "interrupt";
|
|
EventType[EventType["end"] = 2] = "end";
|
|
EventType[EventType["dispose"] = 3] = "dispose";
|
|
EventType[EventType["complete"] = 4] = "complete";
|
|
EventType[EventType["event"] = 5] = "event";
|
|
})(EventType || (EventType = {}));
|
|
export class AnimationStateAdapter {
|
|
start(entry) {
|
|
}
|
|
interrupt(entry) {
|
|
}
|
|
end(entry) {
|
|
}
|
|
dispose(entry) {
|
|
}
|
|
complete(entry) {
|
|
}
|
|
event(entry, event) {
|
|
}
|
|
}
|
|
export const CURRENT = 0;
|
|
export const SETUP = 1;
|
|
export const FIRST = 2;
|
|
export const MODE = 3;
|
|
export const HOLD = 4;
|
|
export const ATTACH_SETUP = 1;
|
|
export const ATTACH_RETAIN = 2;
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQW5pbWF0aW9uU3RhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvQW5pbWF0aW9uU3RhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRS9FLDZHQUE2RztBQUU3RyxPQUFPLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSzdKLE9BQU8sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFHbkU7OztzSUFHc0k7QUFDdEksTUFBTSxPQUFPLGNBQWM7SUFDMUIsTUFBTSxDQUFVLGNBQWMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRWpFLHVEQUF1RDtJQUN2RCxJQUFJLENBQXFCO0lBRXpCLHlIQUF5SDtJQUNoSCxNQUFNLEdBQUcsRUFBMkIsQ0FBQztJQUU5Qzs7O3dFQUdvRTtJQUNwRSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBQ2QsWUFBWSxHQUFHLENBQUMsQ0FBQztJQUVSLE1BQU0sR0FBRyxFQUFhLENBQUM7SUFDdkIsU0FBUyxHQUFHLEVBQThCLENBQUM7SUFDcEQsS0FBSyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBc0IsQ0FBQztJQUM1QyxpQkFBaUIsR0FBRyxLQUFLLENBQUM7SUFFMUIsY0FBYyxHQUFHLElBQUksSUFBSSxDQUFhLEdBQUcsRUFBRSxDQUFDLElBQUksVUFBVSxFQUFFLENBQUMsQ0FBQztJQUU5RCxZQUFhLElBQXdCO1FBQ3BDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ2xC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QUFHLFNBQVMsQ0FBQztJQUM1QixDQUFDO0lBRUQsS0FBSyxDQUFFLEtBQWlCO1FBQ3ZCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUN6QyxDQUFDO0lBRUQsU0FBUyxDQUFFLEtBQWlCO1FBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsR0FBRyxDQUFFLEtBQWlCO1FBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUN6QyxDQUFDO0lBRUQsT0FBTyxDQUFFLEtBQWlCO1FBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsUUFBUSxDQUFFLEtBQWlCO1FBQzFCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsS0FBSyxDQUFFLEtBQWlCLEVBQUUsS0FBWTtRQUNyQyxJQUFJLENBQUMsT0FBTyxDQUFDLElB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QUFHLENBQUMsQ0FBQztBQUM5QixNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBBcHJpbCA1LCAyMDI1LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjUsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRlxuICogVEhFIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4vKiogYmlvbWUtaWdub3JlLWFsbCBsaW50L3N0eWxlL25vTm9uTnVsbEFzc2VydGlvbjogcmVmZXJlbmNlIHJ1bnRpbWUgZXhwZWN0cyBzb21lIG51bGxhYmxlIHRvIG5vdCBiZSBudWxsICovXG5cbmltcG9ydCB7IEFuaW1hdGlvbiwgQXR0YWNobWVudFRpbWVsaW5lLCBEcmF3T3JkZXJGb2xkZXJUaW1lbGluZSwgRHJhd09yZGVyVGltZWxpbmUsIEV2ZW50VGltZWxpbmUsIE1peEZyb20sIFJvdGF0ZVRpbWVsaW5lLCBUaW1lbGluZSB9IGZyb20gXCIuL0FuaW1hdGlvbi5qc1wiO1xuaW1wb3J0IHR5cGUgeyBBbmltYXRpb25TdGF0ZURhdGEgfSBmcm9tIFwiLi9BbmltYXRpb25TdGF0ZURhdGEuanNcIjtcbmltcG9ydCB0eXBlIHsgRXZlbnQgfSBmcm9tIFwiLi9FdmVudC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBTa2VsZXRvbiB9IGZyb20gXCIuL1NrZWxldG9uLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFNsb3QgfSBmcm9tIFwiLi9TbG90LmpzXCI7XG5pbXBvcnQgeyBJbnRlcnBvbGF0aW9uLCBNYXRoVXRpbHMsIFBvb2wsIFV0aWxzIH0gZnJvbSBcIi4vVXRpbHMuanNcIjtcblxuXG4vKiogQXBwbGllcyBhbmltYXRpb25zIG92ZXIgdGltZSwgcXVldWVzIGFuaW1hdGlvbnMgZm9yIGxhdGVyIHBsYXliYWNrLCBtaXhlcyAoY3Jvc3NmYWRpbmcpIGJldHdlZW4gYW5pbWF0aW9ucywgYW5kIGFwcGxpZXNcbiAqIG11bHRpcGxlIGFuaW1hdGlvbnMgb24gdG9wIG9mIGVhY2ggb3RoZXIgKGxheWVyaW5nKS5cbiAqXG4gKiBTZWUgW0FwcGx5aW5nIEFuaW1hdGlvbnNdKGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1hcHBseWluZy1hbmltYXRpb25zI0FuaW1hdGlvblN0YXRlLUFQSSkgaW4gdGhlIFNwaW5lIFJ1bnRpbWVzIEd1aWRlLiAqL1xuZXhwb3J0IGNsYXNzIEFuaW1hdGlvblN0YXRlIHtcblx0c3RhdGljIHJlYWRvbmx5IGVtcHR5QW5pbWF0aW9uID0gbmV3IEFuaW1hdGlvbihcIjxlbXB0eT5cIiwgW10sIDApO1xuXG5cdC8qKiBUaGUgQW5pbWF0aW9uU3RhdGVEYXRhIHRvIGxvb2sgdXAgbWl4IGR1cmF0aW9ucy4gKi9cblx0ZGF0YTogQW5pbWF0aW9uU3RhdGVEYXRhO1xuXG5cdC8qKiBUaGUgbGlzdCBvZiB0cmFja3MgdGhhdCBoYXZlIGhhZCBhbmltYXRpb25zLiBNYXkgY29udGFpbiBudWxsIGVudHJpZXMgZm9yIHRyYWNrcyB0aGF0IGN1cnJlbnRseSBoYXZlIG5vIGFuaW1hdGlvbi4gKi9cblx0cmVhZG9ubHkgdHJhY2tzID0gW10gYXMgKFRyYWNrRW50cnkgfCBudWxsKVtdO1xuXG5cdC8qKiBNdWx0aXBsaWVyIGZvciB0aGUgZGVsdGEgdGltZSB3aGVuIHRoZSBhbmltYXRpb24gc3RhdGUgaXMgdXBkYXRlZCwgY2F1c2luZyB0aW1lIGZvciBhbGwgYW5pbWF0aW9ucyBhbmQgbWl4ZXMgdG8gcGxheSBzbG93ZXJcblx0ICogb3IgZmFzdGVyLiBEZWZhdWx0cyB0byAxLlxuXHQgKlxuXHQgKiBTZWUge0BsaW5rIFRyYWNrRW50cnkudGltZVNjYWxlfSB0byBhZmZlY3QgYSBzaW5nbGUgYW5pbWF0aW9uLiAqL1xuXHR0aW1lU2NhbGUgPSAxO1xuXHR1bmtleWVkU3RhdGUgPSAwO1xuXG5cdHJlYWRvbmx5IGV2ZW50cyA9IFtdIGFzIEV2ZW50W107XG5cdHJlYWRvbmx5IGxpc3RlbmVycyA9IFtdIGFzIEFuaW1hdGlvblN0YXRlTGlzdGVuZXJbXTtcblx0cXVldWUgPSBuZXcgRXZlbnRRdWV1ZSh0aGlzKTtcblx0cHJvcGVydHlJZHMgPSBuZXcgTWFwPHN0cmluZywgVHJhY2tFbnRyeT4oKTtcblx0YW5pbWF0aW9uc0NoYW5nZWQgPSBmYWxzZTtcblxuXHR0cmFja0VudHJ5UG9vbCA9IG5ldyBQb29sPFRyYWNrRW50cnk+KCgpID0+IG5ldyBUcmFja0VudHJ5KCkpO1xuXG5cdGNvbnN0cnVjdG9yIChkYXRhOiBBbmltYXRpb25TdGF0ZURhdGEpIHtcblx0XHR0aGlzLmRhdGEgPSBkYXRhO1xuXHR9XG5cblx0LyoqIEluY3JlbWVudHMgZWFjaCB0cmFjayBlbnRyeSB7QGxpbmsgVHJhY2tFbnRyeS50cmFja1RpbWV9LCBzZXR0aW5nIHF1ZXVlZCBhbmltYXRpb25zIGFzIGN1cnJlbnQgaWYgbmVlZGVkLiAqL1xuXHR1cGRhdGUgKGRlbHRhOiBudW1iZXIpIHtcblx0XHRkZWx0YSAqPSB0aGlzLnRpbWVTY2FsZTtcblx0XHRjb25zdCB0cmFja3MgPSB0aGlzLnRyYWNrcztcblx0XHRmb3IgKGxldCBpID0gMCwgbiA9IHRyYWNrcy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcblx0XHRcdGNvbnN0IGN1cnJlbnQgPSB0cmFja3NbaV07XG5cdFx0XHRpZiAoIWN1cnJlbnQpIGNvbnRpbnVlO1xuXG5cdFx0XHRjdXJyZW50LmFuaW1hdGlvbkxhc3QgPSBjdXJyZW50Lm5leHRBbmltYXRpb25MYXN0O1xuXHRcdFx0Y3VycmVudC50cmFja0xhc3QgPSBjdXJyZW50Lm5leHRUcmFja0xhc3Q7XG5cblx0XHRcdGxldCBjdXJyZW50RGVsdGEgPSBkZWx0YSAqIGN1cnJlbnQudGltZVNjYWxlO1xuXG5cdFx0XHRpZiAoY3VycmVudC5kZWxheSA+IDApIHtcblx0XHRcdFx0Y3VycmVudC5kZWxheSAtPSBjdXJyZW50RGVsdGE7XG5cdFx0XHRcdGlmIChjdXJyZW50LmRlbGF5ID4gMCkgY29udGludWU7XG5cdFx0XHRcdGN1cnJlbnREZWx0YSA9IC1jdXJyZW50LmRlbGF5O1xuXHRcdFx0XHRjdXJyZW50LmRlbGF5ID0gMDtcblx0XHRcdH1cblxuXHRcdFx0bGV0IG5leHQgPSBjdXJyZW50Lm5leHQ7XG5cdFx0XHRpZiAobmV4dCkge1xuXHRcdFx0XHQvLyBXaGVuIHRoZSBuZXh0IGVudHJ5J3MgZGVsYXkgaXMgcGFzc2VkLCBjaGFuZ2UgdG8gdGhlIG5leHQgZW50cnksIHByZXNlcnZpbmcgbGVmdG92ZXIgdGltZS5cblx0XHRcdFx0Y29uc3QgbmV4dFRpbWUgPSBjdXJyZW50LnRyYWNrTGFzdCAtIG5leHQuZGVsYXk7XG5cdFx0XHRcdGlmIChuZXh0VGltZSA+PSAwKSB7XG5cdFx0XHRcdFx0bmV4dC5kZWxheSA9IDA7XG5cdFx0XHRcdFx0bmV4dC50cmFja1RpbWUgKz0gY3VycmVudC50aW1lU2NhbGUgPT09IDAgPyAwIDogKG5leHRUaW1lIC8gY3VycmVudC50aW1lU2NhbGUgKyBkZWx0YSkgKiBuZXh0LnRpbWVTY2FsZTtcblx0XHRcdFx0XHRjdXJyZW50LnRyYWNrVGltZSArPSBjdXJyZW50RGVsdGE7XG5cdFx0XHRcdFx0dGhpcy5zZXRUcmFjayhpLCBuZXh0LCB0cnVlKTtcblx0XHRcdFx0XHR3aGlsZSAobmV4dC5taXhpbmdGcm9tKSB7XG5cdFx0XHRcdFx0XHRuZXh0Lm1peFRpbWUgKz0gZGVsdGE7XG5cdFx0XHRcdFx0XHRuZXh0ID0gbmV4dC5taXhpbmdGcm9tO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChjdXJyZW50LnRyYWNrTGFzdCA+PSBjdXJyZW50LnRyYWNrRW5kICYmICFjdXJyZW50Lm1peGluZ0Zyb20pIHtcblx0XHRcdFx0dHJhY2tzW2ldID0gbnVsbDtcblx0XHRcdFx0dGhpcy5xdWV1ZS5lbmQoY3VycmVudCk7XG5cdFx0XHRcdHRoaXMuY2xlYXJOZXh0KGN1cnJlbnQpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGlmIChjdXJyZW50Lm1peGluZ0Zyb20gJiYgdGhpcy51cGRhdGVNaXhpbmdGcm9tKGN1cnJlbnQsIGRlbHRhKSkge1xuXHRcdFx0XHQvLyBFbmQgbWl4aW5nIGZyb20gZW50cmllcyBvbmNlIGFsbCBoYXZlIGNvbXBsZXRlZC5cblx0XHRcdFx0bGV0IGZyb206IFRyYWNrRW50cnkgfCBudWxsID0gY3VycmVudC5taXhpbmdGcm9tO1xuXHRcdFx0XHRjdXJyZW50Lm1peGluZ0Zyb20gPSBudWxsO1xuXHRcdFx0XHRpZiAoZnJvbSkgZnJvbS5taXhpbmdUbyA9IG51bGw7XG5cdFx0XHRcdHdoaWxlIChmcm9tKSB7XG5cdFx0XHRcdFx0dGhpcy5xdWV1ZS5lbmQoZnJvbSk7XG5cdFx0XHRcdFx0ZnJvbSA9IGZyb20ubWl4aW5nRnJvbTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRjdXJyZW50LnRyYWNrVGltZSArPSBjdXJyZW50RGVsdGE7XG5cdFx0fVxuXG5cdFx0dGhpcy5xdWV1ZS5kcmFpbigpO1xuXHR9XG5cblx0LyoqIFJldHVybnMgdHJ1ZSB3aGVuIGFsbCBtaXhpbmcgZnJvbSBlbnRyaWVzIGFyZSBjb21wbGV0ZS4gKi9cblx0dXBkYXRlTWl4aW5nRnJvbSAodG86IFRyYWNrRW50cnksIGRlbHRhOiBudW1iZXIpOiBib29sZWFuIHtcblx0XHRjb25zdCBmcm9tID0gdG8ubWl4aW5nRnJvbTtcblx0XHRpZiAoIWZyb20pIHJldHVybiB0cnVlO1xuXG5cdFx0Y29uc3QgZmluaXNoZWQgPSB0aGlzLnVwZGF0ZU1peGluZ0Zyb20oZnJvbSwgZGVsdGEpO1xuXG5cdFx0ZnJvbS5hbmltYXRpb25MYXN0ID0gZnJvbS5uZXh0QW5pbWF0aW9uTGFzdDtcblx0XHRmcm9tLnRyYWNrTGFzdCA9IGZyb20ubmV4dFRyYWNrTGFzdDtcblxuXHRcdC8vIFRoZSBmcm9tIGVudHJ5IHdhcyBhcHBsaWVkIGF0IGxlYXN0IG9uY2UgYW5kIHRoZSBtaXggaXMgY29tcGxldGUuXG5cdFx0aWYgKHRvLm5leHRUcmFja0xhc3QgIT09IC0xICYmIHRvLm1peFRpbWUgPj0gdG8ubWl4RHVyYXRpb24pIHtcblx0XHRcdC8vIE1peGluZyBpcyBjb21wbGV0ZSBmb3IgYWxsIGVudHJpZXMgYmVmb3JlIHRoZSBmcm9tIGVudHJ5IG9yIHRoZSBtaXggaXMgaW5zdGFudGFuZW91cy5cblx0XHRcdGlmIChmcm9tLnRvdGFsQWxwaGEgPT09IDAgfHwgdG8ubWl4RHVyYXRpb24gPT09IDApIHtcblx0XHRcdFx0dG8ubWl4aW5nRnJvbSA9IGZyb20ubWl4aW5nRnJvbTtcblx0XHRcdFx0aWYgKGZyb20ubWl4aW5nRnJvbSAhPSBudWxsKSBmcm9tLm1peGluZ0Zyb20ubWl4aW5nVG8gPSB0bztcblx0XHRcdFx0aWYgKGZyb20udG90YWxBbHBoYSA9PT0gMCkge1xuXHRcdFx0XHRcdGZvciAobGV0IG5leHQgPSB0bzsgbmV4dC5taXhpbmdUbyAhPSBudWxsOyBuZXh0ID0gbmV4dC5taXhpbmdUbylcblx0XHRcdFx0XHRcdG5leHQua2VlcEhvbGQgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMucXVldWUuZW5kKGZyb20pO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGZpbmlzaGVkO1xuXHRcdH1cblxuXHRcdGZyb20udHJhY2tUaW1lICs9IGRlbHRhICogZnJvbS50aW1lU2NhbGU7XG5cdFx0dG8ubWl4VGltZSArPSBkZWx0YTtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvKiogUG9zZXMgdGhlIHNrZWxldG9uIHVzaW5nIHRoZSB0cmFjayBlbnRyeSBhbmltYXRpb25zLiBUaGUgYW5pbWF0aW9uIHN0YXRlIGlzIG5vdCBjaGFuZ2VkLCBzbyBjYW4gYmUgYXBwbGllZCB0byBtdWx0aXBsZVxuXHQgKiBza2VsZXRvbnMgdG8gcG9zZSB0aGVtIGlkZW50aWNhbGx5LlxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIGFueSBhbmltYXRpb25zIHdlcmUgYXBwbGllZC4gKi9cblx0YXBwbHkgKHNrZWxldG9uOiBTa2VsZXRvbik6IGJvb2xlYW4ge1xuXHRcdGlmICghc2tlbGV0b24pIHRocm93IG5ldyBFcnJvcihcInNrZWxldG9uIGNhbm5vdCBiZSBudWxsLlwiKTtcblx0XHRpZiAodGhpcy5hbmltYXRpb25zQ2hhbmdlZCkgdGhpcy5fYW5pbWF0aW9uc0NoYW5nZWQoKTtcblxuXHRcdGNvbnN0IGV2ZW50cyA9IHRoaXMuZXZlbnRzO1xuXHRcdGNvbnN0IHRyYWNrcyA9IHRoaXMudHJhY2tzO1xuXHRcdGxldCBhcHBsaWVkID0gZmFsc2U7XG5cblx0XHRmb3IgKGxldCBpID0gMCwgbiA9IHRyYWNrcy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcblx0XHRcdGNvbnN0IGN1cnJlbnQgPSB0cmFja3NbaV07XG5cdFx0XHRpZiAoIWN1cnJlbnQgfHwgY3VycmVudC5kZWxheSA+IDApIGNvbnRpbnVlO1xuXHRcdFx0YXBwbGllZCA9IHRydWU7XG5cblx0XHRcdC8vIEFwcGx5IG1peGluZyBmcm9tIGVudHJpZXMgZmlyc3QuXG5cdFx0XHRsZXQgYWxwaGEgPSBjdXJyZW50LmFscGhhO1xuXHRcdFx0aWYgKGN1cnJlbnQubWl4aW5nRnJvbSlcblx0XHRcdFx0YWxwaGEgKj0gdGhpcy5hcHBseU1peGluZ0Zyb20oY3VycmVudCwgc2tlbGV0b24pO1xuXHRcdFx0ZWxzZSBpZiAoY3VycmVudC50cmFja1RpbWUgPj0gY3VycmVudC50cmFja0VuZCAmJiAhY3VycmVudC5uZXh0KVxuXHRcdFx0XHRhbHBoYSA9IDA7XG5cblx0XHRcdC8vIEFwcGx5IGN1cnJlbnQgZW50cnkuXG5cdFx0XHRsZXQgYW5pbWF0aW9uTGFzdCA9IGN1cnJlbnQuYW5pbWF0aW9uTGFzdCwgYW5pbWF0aW9uVGltZSA9IGN1cnJlbnQuZ2V0QW5pbWF0aW9uVGltZSgpLCBhcHBseVRpbWUgPSBhbmltYXRpb25UaW1lO1xuXHRcdFx0bGV0IGFwcGx5RXZlbnRzOiBFdmVudFtdIHwgbnVsbCA9IGV2ZW50cztcblx0XHRcdGlmIChjdXJyZW50LnJldmVyc2UpIHtcblx0XHRcdFx0YXBwbHlUaW1lID0gY3VycmVudC5hbmltYXRpb24hLmR1cmF0aW9uIC0gYXBwbHlUaW1lO1xuXHRcdFx0XHRhcHBseUV2ZW50cyA9IG51bGw7XG5cdFx0XHR9XG5cdFx0XHRjb25zdCB0aW1lbGluZXMgPSBjdXJyZW50LmFuaW1hdGlvbiEudGltZWxpbmVzO1xuXHRcdFx0Y29uc3QgdGltZWxpbmVDb3VudCA9IHRpbWVsaW5lcy5sZW5ndGg7XG5cdFx0XHRpZiAoKGkgPT09IDAgJiYgYWxwaGEgPT09IDEpKSB7XG5cdFx0XHRcdGZvciAobGV0IGlpID0gMDsgaWkgPCB0aW1lbGluZUNvdW50OyBpaSsrKSB7XG5cdFx0XHRcdFx0Ly8gRml4ZXMgaXNzdWUgIzMwMiBvbiBJT1M5IHdoZXJlIG1peCwgYmxlbmQgc29tZXRpbWVzIGJlY2FtZSB1bmRlZmluZWQgYW5kIGNhdXNlZCBhc3NldHNcblx0XHRcdFx0XHQvLyB0byBzb21ldGltZXMgc3RvcCByZW5kZXJpbmcgd2hlbiB1c2luZyBjb2xvciBjb3JyZWN0aW9uLCBhcyB0aGVpciBSR0JBIHZhbHVlcyBiZWNvbWUgTmFOLlxuXHRcdFx0XHRcdC8vIChodHRwczovL2dpdGh1Yi5jb20vcGl4aWpzL3BpeGktc3BpbmUvaXNzdWVzLzMwMilcblx0XHRcdFx0XHRVdGlscy53ZWJraXQ2MDJCdWdmaXhIZWxwZXIoYWxwaGEpO1xuXHRcdFx0XHRcdGNvbnN0IHRpbWVsaW5lID0gdGltZWxpbmVzW2lpXTtcblx0XHRcdFx0XHRpZiAodGltZWxpbmUgaW5zdGFuY2VvZiBBdHRhY2htZW50VGltZWxpbmUpXG5cdFx0XHRcdFx0XHR0aGlzLmFwcGx5QXR0YWNobWVudFRpbWVsaW5lKHRpbWVsaW5lLCBza2VsZXRvbiwgYXBwbHlUaW1lLCBNaXhGcm9tLnNldHVwLCB0cnVlKTtcblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHR0aW1lbGluZS5hcHBseShza2VsZXRvbiwgYW5pbWF0aW9uTGFzdCwgYXBwbHlUaW1lLCBhcHBseUV2ZW50cywgYWxwaGEsIE1peEZyb20uc2V0dXAsIGZhbHNlLCBmYWxzZSwgZmFsc2UpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb25zdCB0aW1lbGluZU1vZGUgPSBjdXJyZW50LnRpbWVsaW5lTW9kZTtcblx0XHRcdFx0Y29uc3QgcmV0YWluQXR0YWNobWVudHMgPSBhbHBoYSA+PSBjdXJyZW50LmFscGhhQXR0YWNobWVudFRocmVzaG9sZDtcblx0XHRcdFx0Y29uc3QgYWRkID0gY3VycmVudC5hZGRpdGl2ZSwgc2hvcnRlc3RSb3RhdGlvbiA9IGFkZCB8fCBjdXJyZW50LnNob3J0ZXN0Um90YXRpb247XG5cdFx0XHRcdGNvbnN0IGZpcnN0RnJhbWUgPSAhc2hvcnRlc3RSb3RhdGlvbiAmJiBjdXJyZW50LnRpbWVsaW5lc1JvdGF0aW9uLmxlbmd0aCAhPT0gdGltZWxpbmVDb3VudCA8PCAxO1xuXHRcdFx0XHRpZiAoZmlyc3RGcmFtZSkgY3VycmVudC50aW1lbGluZXNSb3RhdGlvbi5sZW5ndGggPSB0aW1lbGluZUNvdW50IDw8IDE7XG5cblx0XHRcdFx0Zm9yIChsZXQgaWkgPSAwOyBpaSA8IHRpbWVsaW5lQ291bnQ7IGlpKyspIHtcblx0XHRcdFx0XHRjb25zdCB0aW1lbGluZSA9IHRpbWVsaW5lc1tpaV07XG5cdFx0XHRcdFx0Y29uc3QgZnJvbSA9IHRpbWVsaW5lTW9kZVtpaV0gJiBNT0RFO1xuXHRcdFx0XHRcdGlmICghc2hvcnRlc3RSb3RhdGlvbiAmJiB0aW1lbGluZSBpbnN0YW5jZW9mIFJvdGF0ZVRpbWVsaW5lKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmFwcGx5Um90YXRlVGltZWxpbmUodGltZWxpbmUsIHNrZWxldG9uLCBhcHBseVRpbWUsIGFscGhhLCBmcm9tLCBjdXJyZW50LnRpbWVsaW5lc1JvdGF0aW9uLCBpaSA8PCAxLCBmaXJzdEZyYW1lKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKHRpbWVsaW5lIGluc3RhbmNlb2YgQXR0YWNobWVudFRpbWVsaW5lKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmFwcGx5QXR0YWNobWVudFRpbWVsaW5lKHRpbWVsaW5lLCBza2VsZXRvbiwgYXBwbHlUaW1lLCBmcm9tLCByZXRhaW5BdHRhY2htZW50cyk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vIFRoaXMgZml4ZXMgdGhlIFdlYktpdCA2MDIgc3BlY2lmaWMgaXNzdWUgZGVzY3JpYmVkIGF0IGh0dHBzOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vZm9ydW0vZC8xMDEwOS1pb3MtMTAtZGlzYXBwZWFyaW5nLWdyYXBoaWNzXG5cdFx0XHRcdFx0XHRVdGlscy53ZWJraXQ2MDJCdWdmaXhIZWxwZXIoYWxwaGEpO1xuXHRcdFx0XHRcdFx0dGltZWxpbmUuYXBwbHkoc2tlbGV0b24sIGFuaW1hdGlvbkxhc3QsIGFwcGx5VGltZSwgYXBwbHlFdmVudHMsIGFscGhhLCBmcm9tLCBhZGQsIGZhbHNlLCBmYWxzZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoY3VycmVudC5yZXZlcnNlKSB0aGlzLmV2ZW50c1JldmVyc2UoY3VycmVudCwgYW5pbWF0aW9uTGFzdCwgYW5pbWF0aW9uVGltZSk7XG5cdFx0XHR0aGlzLnF1ZXVlRXZlbnRzKGN1cnJlbnQsIGFuaW1hdGlvblRpbWUpO1xuXHRcdFx0ZXZlbnRzLmxlbmd0aCA9IDA7XG5cdFx0XHRjdXJyZW50Lm5leHRBbmltYXRpb25MYXN0ID0gYW5pbWF0aW9uVGltZTtcblx0XHRcdGN1cnJlbnQubmV4dFRyYWNrTGFzdCA9IGN1cnJlbnQudHJhY2tUaW1lO1xuXHRcdH1cblxuXHRcdC8vIFNldCBzbG90IGF0dGFjaG1lbnRzIHRvIHRoZSBzZXR1cCBwb3NlIGlmIHRoZXkgd2VyZSBzZXQgdGVtcG9yYXJpbHkgdG8gYXBwbHkgZGVmb3JtIHRpbWVsaW5lcy5cblx0XHRjb25zdCBzZXR1cFN0YXRlID0gdGhpcy51bmtleWVkU3RhdGUgKyBBVFRBQ0hfU0VUVVA7XG5cdFx0Y29uc3Qgc2xvdHMgPSBza2VsZXRvbi5zbG90cztcblx0XHRmb3IgKGxldCBpID0gMCwgbiA9IHNrZWxldG9uLnNsb3RzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuXHRcdFx0Y29uc3Qgc2xvdCA9IHNsb3RzW2ldO1xuXHRcdFx0aWYgKHNsb3QuYXR0YWNobWVudFN0YXRlID09PSBzZXR1cFN0YXRlKSB7XG5cdFx0XHRcdGNvbnN0IGF0dGFjaG1lbnROYW1lID0gc2xvdC5kYXRhLmF0dGFjaG1lbnROYW1lO1xuXHRcdFx0XHRzbG90LnBvc2Uuc2V0QXR0YWNobWVudCghYXR0YWNobWVudE5hbWUgPyBudWxsIDogc2tlbGV0b24uZ2V0QXR0YWNobWVudChzbG90LmRhdGEuaW5kZXgsIGF0dGFjaG1lbnROYW1lKSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMudW5rZXllZFN0YXRlICs9IDI7IC8vIFJlc2V0LlxuXG5cdFx0dGhpcy5xdWV1ZS5kcmFpbigpO1xuXHRcdHJldHVybiBhcHBsaWVkO1xuXHR9XG5cblx0YXBwbHlNaXhpbmdGcm9tICh0bzogVHJhY2tFbnRyeSwgc2tlbGV0b246IFNrZWxldG9uKSB7XG5cdFx0Y29uc3QgZnJvbSA9IHRvLm1peGluZ0Zyb20hO1xuXHRcdGNvbnN0IGZyb21NaXggPSBmcm9tLm1peGluZ0Zyb20gIT09IG51bGwgPyB0aGlzLmFwcGx5TWl4aW5nRnJvbShmcm9tLCBza2VsZXRvbikgOiAxO1xuXHRcdGNvbnN0IG1peCA9IHRvLm1peCgpO1xuXG5cdFx0Y29uc3QgYSA9IGZyb20uYWxwaGEgKiBmcm9tTWl4LCBrZWVwID0gMSAtIG1peCAqIHRvLmFscGhhO1xuXHRcdGNvbnN0IGFscGhhTWl4ID0gYSAqICgxIC0gbWl4KSwgYWxwaGFIb2xkID0ga2VlcCA+IDAgPyBhbHBoYU1peCAvIGtlZXAgOiBhO1xuXG5cdFx0Y29uc3QgdGltZWxpbmVzID0gZnJvbS5hbmltYXRpb24hLnRpbWVsaW5lcztcblx0XHRjb25zdCB0aW1lbGluZUNvdW50ID0gdGltZWxpbmVzLmxlbmd0aDtcblx0XHRjb25zdCB0aW1lbGluZU1vZGUgPSBmcm9tLnRpbWVsaW5lTW9kZTtcblx0XHRjb25zdCB0aW1lbGluZUhvbGRNaXggPSBmcm9tLnRpbWVsaW5lSG9sZE1peDtcblxuXHRcdGNvbnN0IHJldGFpbkF0dGFjaG1lbnRzID0gbWl4IDwgZnJvbS5taXhBdHRhY2htZW50VGhyZXNob2xkLCBkcmF3T3JkZXIgPSBtaXggPCBmcm9tLm1peERyYXdPcmRlclRocmVzaG9sZDtcblx0XHRjb25zdCBhZGQgPSBmcm9tLmFkZGl0aXZlLCBzaG9ydGVzdFJvdGF0aW9uID0gYWRkIHx8IGZyb20uc2hvcnRlc3RSb3RhdGlvbjtcblx0XHRjb25zdCBmaXJzdEZyYW1lID0gIXNob3J0ZXN0Um90YXRpb24gJiYgZnJvbS50aW1lbGluZXNSb3RhdGlvbi5sZW5ndGggIT09IHRpbWVsaW5lQ291bnQgPDwgMTtcblx0XHRpZiAoZmlyc3RGcmFtZSkgZnJvbS50aW1lbGluZXNSb3RhdGlvbi5sZW5ndGggPSB0aW1lbGluZUNvdW50IDw8IDE7XG5cdFx0Y29uc3QgdGltZWxpbmVzUm90YXRpb24gPSBmcm9tLnRpbWVsaW5lc1JvdGF0aW9uO1xuXG5cdFx0bGV0IGFuaW1hdGlvbkxhc3QgPSBmcm9tLmFuaW1hdGlvbkxhc3QsIGFuaW1hdGlvblRpbWUgPSBmcm9tLmdldEFuaW1hdGlvblRpbWUoKSwgYXBwbHlUaW1lID0gYW5pbWF0aW9uVGltZTtcblx0XHRsZXQgZXZlbnRzID0gbnVsbDtcblx0XHRpZiAoZnJvbS5yZXZlcnNlKVxuXHRcdFx0YXBwbHlUaW1lID0gZnJvbS5hbmltYXRpb24hLmR1cmF0aW9uIC0gYXBwbHlUaW1lO1xuXHRcdGVsc2UgaWYgKG1peCA8IGZyb20uZXZlbnRUaHJlc2hvbGQpIC8vXG5cdFx0XHRldmVudHMgPSB0aGlzLmV2ZW50cztcblxuXHRcdGZyb20udG90YWxBbHBoYSA9IDA7XG5cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRpbWVsaW5lQ291bnQ7IGkrKykge1xuXHRcdFx0Y29uc3QgdGltZWxpbmUgPSB0aW1lbGluZXNbaV07XG5cdFx0XHRjb25zdCBtb2RlID0gdGltZWxpbmVNb2RlW2ldO1xuXHRcdFx0Y29uc3QgbWl4RnJvbSA9IG1vZGUgJiBNT0RFO1xuXHRcdFx0bGV0IGFscGhhID0gMDtcblx0XHRcdGlmICgobW9kZSAmIEhPTEQpICE9PSAwKSB7XG5cdFx0XHRcdGNvbnN0IGhvbGRNaXggPSB0aW1lbGluZUhvbGRNaXhbaV07XG5cdFx0XHRcdGFscGhhID0gaG9sZE1peCA9PSBudWxsID8gYWxwaGFIb2xkIDogYWxwaGFIb2xkICogKDEgLSBob2xkTWl4Lm1peCgpKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICghZHJhd09yZGVyICYmIHRpbWVsaW5lIGluc3RhbmNlb2YgRHJhd09yZGVyVGltZWxpbmUgJiYgbWl4RnJvbSA9PT0gTWl4RnJvbS5jdXJyZW50KSBjb250aW51ZTtcblx0XHRcdFx0YWxwaGEgPSBhbHBoYU1peDtcblx0XHRcdH1cblx0XHRcdGZyb20udG90YWxBbHBoYSArPSBhbHBoYTtcblx0XHRcdGlmICghc2hvcnRlc3RSb3RhdGlvbiAmJiB0aW1lbGluZSBpbnN0YW5jZW9mIFJvdGF0ZVRpbWVsaW5lKSB7XG5cdFx0XHRcdHRoaXMuYXBwbHlSb3RhdGVUaW1lbGluZSh0aW1lbGluZSwgc2tlbGV0b24sIGFwcGx5VGltZSwgYWxwaGEsIG1peEZyb20sIHRpbWVsaW5lc1JvdGF0aW9uLCBpIDw8IDEsIGZpcnN0RnJhbWUpO1xuXHRcdFx0fSBlbHNlIGlmICh0aW1lbGluZSBpbnN0YW5jZW9mIEF0dGFjaG1lbnRUaW1lbGluZSlcblx0XHRcdFx0dGhpcy5hcHBseUF0dGFjaG1lbnRUaW1lbGluZSh0aW1lbGluZSwgc2tlbGV0b24sIGFwcGx5VGltZSwgbWl4RnJvbSxcblx0XHRcdFx0XHRyZXRhaW5BdHRhY2htZW50cyAmJiBhbHBoYSA+PSBmcm9tLmFscGhhQXR0YWNobWVudFRocmVzaG9sZCk7XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0Y29uc3Qgb3V0ID0gIWRyYXdPcmRlciB8fCAhKHRpbWVsaW5lIGluc3RhbmNlb2YgRHJhd09yZGVyVGltZWxpbmUpIHx8IG1peEZyb20gPT09IE1peEZyb20uY3VycmVudDtcblx0XHRcdFx0dGltZWxpbmUuYXBwbHkoc2tlbGV0b24sIGFuaW1hdGlvbkxhc3QsIGFwcGx5VGltZSwgZXZlbnRzLCBhbHBoYSwgbWl4RnJvbSwgYWRkLCBvdXQsIGZhbHNlKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZnJvbS5yZXZlcnNlICYmIG1peCA8IGZyb20uZXZlbnRUaHJlc2hvbGQpIHRoaXMuZXZlbnRzUmV2ZXJzZShmcm9tLCBhbmltYXRpb25MYXN0LCBhbmltYXRpb25UaW1lKTtcblx0XHRpZiAodG8ubWl4RHVyYXRpb24gPiAwKSB0aGlzLnF1ZXVlRXZlbnRzKGZyb20sIGFuaW1hdGlvblRpbWUpO1xuXHRcdHRoaXMuZXZlbnRzLmxlbmd0aCA9IDA7XG5cblx0XHRmcm9tLm5leHRBbmltYXRpb25MYXN0ID0gYW5pbWF0aW9uVGltZTtcblx0XHRmcm9tLm5leHRUcmFja0xhc3QgPSBmcm9tLnRyYWNrVGltZTtcblx0XHRyZXR1cm4gbWl4O1xuXHR9XG5cblx0LyoqIEFwcGxpZXMgdGhlIGF0dGFjaG1lbnQgdGltZWxpbmUgYW5kIHNldHMge0BsaW5rIFNsb3QuYXR0YWNobWVudFN0YXRlfS5cblx0ICogQHBhcmFtIHJldGFpbiBUcnVlIGlmIHRoZSBhdHRhY2htZW50IHJlbWFpbnMgYWZ0ZXIgYXBwbHksIGZhbHNlIGlmIHRlbXBvcmFyeSBmb3IgZGVmb3JtIHRpbWVsaW5lcy4gKi9cblx0YXBwbHlBdHRhY2htZW50VGltZWxpbmUgKHRpbWVsaW5lOiBBdHRhY2htZW50VGltZWxpbmUsIHNrZWxldG9uOiBTa2VsZXRvbiwgdGltZTogbnVtYmVyLCBmcm9tOiBNaXhGcm9tLCByZXRhaW46IGJvb2xlYW4pIHtcblx0XHRjb25zdCBzbG90ID0gc2tlbGV0b24uc2xvdHNbdGltZWxpbmUuc2xvdEluZGV4XTtcblx0XHRpZiAoIXNsb3QuYm9uZS5hY3RpdmUpIHJldHVybjtcblx0XHRpZiAoIXJldGFpbiAmJiBzbG90LmF0dGFjaG1lbnRTdGF0ZSA9PT0gdGhpcy51bmtleWVkU3RhdGUgKyBBVFRBQ0hfUkVUQUlOKSByZXR1cm47XG5cblx0XHRsZXQgc2V0dXAgPSB0aW1lIDwgdGltZWxpbmUuZnJhbWVzWzBdO1xuXHRcdGxldCBuYW1lID0gbnVsbDtcblx0XHRpZiAoIXNldHVwKSB7XG5cdFx0XHRuYW1lID0gdGltZWxpbmUuYXR0YWNobWVudE5hbWVzW1RpbWVsaW5lLnNlYXJjaCh0aW1lbGluZS5mcmFtZXMsIHRpbWUpXTtcblx0XHRcdHNldHVwID0gIXJldGFpbiAmJiBuYW1lID09IG51bGw7XG5cdFx0fVxuXHRcdGlmIChzZXR1cCkge1xuXHRcdFx0aWYgKGZyb20gPT09IE1peEZyb20uY3VycmVudCkgcmV0dXJuO1xuXHRcdFx0bmFtZSA9IHNsb3QuZGF0YS5hdHRhY2htZW50TmFtZTtcblx0XHR9XG5cdFx0c2xvdC5wb3NlLnNldEF0dGFjaG1lbnQobmFtZSA9PSBudWxsID8gbnVsbCA6IHNrZWxldG9uLmdldEF0dGFjaG1lbnQoc2xvdC5kYXRhLmluZGV4LCBuYW1lKSk7XG5cdFx0aWYgKHJldGFpbilcblx0XHRcdHNsb3QuYXR0YWNobWVudFN0YXRlID0gdGhpcy51bmtleWVkU3RhdGUgKyBBVFRBQ0hfUkVUQUlOO1xuXHRcdGVsc2UgaWYgKCFzZXR1cCkgLy9cblx0XHRcdHNsb3QuYXR0YWNobWVudFN0YXRlID0gdGhpcy51bmtleWVkU3RhdGUgKyBBVFRBQ0hfU0VUVVA7XG5cdH1cblxuXHQvKiogQXBwbGllcyB0aGUgcm90YXRlIHRpbWVsaW5lLCBtaXhpbmcgd2l0aCB0aGUgY3VycmVudCBwb3NlIHdoaWxlIGtlZXBpbmcgdGhlIHNhbWUgcm90YXRpb24gZGlyZWN0aW9uIGNob3NlbiBhcyB0aGUgc2hvcnRlc3Rcblx0ICogdGhlIGZpcnN0IHRpbWUgdGhlIG1peGluZyB3YXMgYXBwbGllZC4gKi9cblx0YXBwbHlSb3RhdGVUaW1lbGluZSAodGltZWxpbmU6IFJvdGF0ZVRpbWVsaW5lLCBza2VsZXRvbjogU2tlbGV0b24sIHRpbWU6IG51bWJlciwgYWxwaGE6IG51bWJlciwgZnJvbTogTWl4RnJvbSxcblx0XHR0aW1lbGluZXNSb3RhdGlvbjogQXJyYXk8bnVtYmVyPiwgaTogbnVtYmVyLCBmaXJzdEZyYW1lOiBib29sZWFuKSB7XG5cblx0XHRpZiAoZmlyc3RGcmFtZSkgdGltZWxpbmVzUm90YXRpb25baV0gPSAwO1xuXG5cdFx0aWYgKGFscGhhID09PSAxKSB7XG5cdFx0XHR0aW1lbGluZS5hcHBseShza2VsZXRvbiwgMCwgdGltZSwgbnVsbCwgMSwgZnJvbSwgZmFsc2UsIGZhbHNlLCBmYWxzZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgYm9uZSA9IHNrZWxldG9uLmJvbmVzW3RpbWVsaW5lLmJvbmVJbmRleF07XG5cdFx0aWYgKCFib25lLmFjdGl2ZSkgcmV0dXJuO1xuXHRcdGNvbnN0IHBvc2UgPSBib25lLnBvc2UsIHNldHVwID0gYm9uZS5kYXRhLnNldHVwUG9zZTtcblx0XHRjb25zdCBmcmFtZXMgPSB0aW1lbGluZS5mcmFtZXM7XG5cdFx0bGV0IHIxOiBudW1iZXIsIHIyOiBudW1iZXI7XG5cdFx0aWYgKHRpbWUgPCBmcmFtZXNbMF0pIHtcblx0XHRcdHN3aXRjaCAoZnJvbSkge1xuXHRcdFx0XHRjYXNlIE1peEZyb20uc2V0dXA6IHtcblx0XHRcdFx0XHRwb3NlLnJvdGF0aW9uID0gc2V0dXAucm90YXRpb247XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNhc2UgTWl4RnJvbS5jdXJyZW50OiB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyMSA9IHBvc2Uucm90YXRpb247XG5cdFx0XHRyMiA9IHNldHVwLnJvdGF0aW9uO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyMSA9IGZyb20gPT09IE1peEZyb20uc2V0dXAgPyBzZXR1cC5yb3RhdGlvbiA6IHBvc2Uucm90YXRpb247XG5cdFx0XHRyMiA9IHNldHVwLnJvdGF0aW9uICsgdGltZWxpbmUuZ2V0Q3VydmVWYWx1ZSh0aW1lKTtcblx0XHR9XG5cblx0XHQvLyBNaXggYmV0d2VlbiByb3RhdGlvbnMgdXNpbmcgdGhlIGRpcmVjdGlvbiBvZiB0aGUgc2hvcnRlc3Qgcm91dGUgb24gdGhlIGZpcnN0IGZyYW1lIHdoaWxlIGRldGVjdGluZyBjcm9zc2VzLlxuXHRcdGxldCB0b3RhbCA9IDAsIGRpZmYgPSByMiAtIHIxO1xuXHRcdGRpZmYgLT0gTWF0aC5jZWlsKGRpZmYgLyAzNjAgLSAwLjUpICogMzYwO1xuXHRcdGlmIChkaWZmID09PSAwKSB7XG5cdFx0XHR0b3RhbCA9IHRpbWVsaW5lc1JvdGF0aW9uW2ldO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgbGFzdFRvdGFsID0gMCwgbGFzdERpZmYgPSAwO1xuXHRcdFx0aWYgKGZpcnN0RnJhbWUpIHtcblx0XHRcdFx0bGFzdFRvdGFsID0gMDtcblx0XHRcdFx0bGFzdERpZmYgPSBkaWZmO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bGFzdFRvdGFsID0gdGltZWxpbmVzUm90YXRpb25baV07XG5cdFx0XHRcdGxhc3REaWZmID0gdGltZWxpbmVzUm90YXRpb25baSArIDFdO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgbG9vcHMgPSBsYXN0VG90YWwgLSBsYXN0VG90YWwgJSAzNjA7XG5cdFx0XHR0b3RhbCA9IGRpZmYgKyBsb29wcztcblx0XHRcdGxldCBjdXJyZW50ID0gZGlmZiA+PSAwLCBkaXIgPSBsYXN0VG90YWwgPj0gMDtcblx0XHRcdGlmIChNYXRoLmFicyhsYXN0RGlmZikgPD0gOTAgJiYgTWF0aFV0aWxzLnNpZ251bShsYXN0RGlmZikgIT09IE1hdGhVdGlscy5zaWdudW0oZGlmZikpIHtcblx0XHRcdFx0aWYgKE1hdGguYWJzKGxhc3RUb3RhbCAtIGxvb3BzKSA+IDE4MCkge1xuXHRcdFx0XHRcdHRvdGFsICs9IDM2MCAqIE1hdGhVdGlscy5zaWdudW0obGFzdFRvdGFsKTtcblx0XHRcdFx0XHRkaXIgPSBjdXJyZW50O1xuXHRcdFx0XHR9IGVsc2UgaWYgKGxvb3BzICE9PSAwKVxuXHRcdFx0XHRcdHRvdGFsIC09IDM2MCAqIE1hdGhVdGlscy5zaWdudW0obGFzdFRvdGFsKTtcblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdGRpciA9IGN1cnJlbnQ7XG5cdFx0XHR9XG5cdFx0XHRpZiAoZGlyICE9PSBjdXJyZW50KSB0b3RhbCArPSAzNjAgKiBNYXRoVXRpbHMuc2lnbnVtKGxhc3RUb3RhbCk7XG5cdFx0XHR0aW1lbGluZXNSb3RhdGlvbltpXSA9IHRvdGFsO1xuXHRcdH1cblx0XHR0aW1lbGluZXNSb3RhdGlvbltpICsgMV0gPSBkaWZmO1xuXHRcdHBvc2Uucm90YXRpb24gPSByMSArIHRvdGFsICogYWxwaGE7XG5cdH1cblxuXHRxdWV1ZUV2ZW50cyAoZW50cnk6IFRyYWNrRW50cnksIGFuaW1hdGlvblRpbWU6IG51bWJlcikge1xuXHRcdGNvbnN0IGFuaW1hdGlvblN0YXJ0ID0gZW50cnkuYW5pbWF0aW9uU3RhcnQsIGFuaW1hdGlvbkVuZCA9IGVudHJ5LmFuaW1hdGlvbkVuZCwgZHVyYXRpb24gPSBhbmltYXRpb25FbmQgLSBhbmltYXRpb25TdGFydDtcblx0XHRjb25zdCByZXZlcnNlID0gZW50cnkucmV2ZXJzZTtcblx0XHRsZXQgc3BsaXQgPSBlbnRyeS50cmFja0xhc3QgJSBkdXJhdGlvbjtcblx0XHRpZiAocmV2ZXJzZSkgc3BsaXQgPSBkdXJhdGlvbiAtIHNwbGl0O1xuXG5cdFx0Ly8gUXVldWUgZXZlbnRzIGJlZm9yZSBjb21wbGV0ZS5cblx0XHRjb25zdCBldmVudHMgPSB0aGlzLmV2ZW50cztcblx0XHRsZXQgaSA9IDAsIG4gPSBldmVudHMubGVuZ3RoO1xuXHRcdGZvciAoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBldmVudCA9IGV2ZW50c1tpXTtcblx0XHRcdGlmICgoZXZlbnQudGltZSA8IHNwbGl0KSAhPT0gcmV2ZXJzZSkgYnJlYWs7IC8vIGphdmE6IGlmIChldmVudC50aW1lIDwgc3BsaXQgXiByZXZlcnNlKSBicmVhaztcblx0XHRcdGlmIChldmVudC50aW1lID49IGFuaW1hdGlvblN0YXJ0ICYmIGV2ZW50LnRpbWUgPD0gYW5pbWF0aW9uRW5kKSB0aGlzLnF1ZXVlLmV2ZW50KGVudHJ5LCBldmVudCk7XG5cdFx0fVxuXG5cdFx0Ly8gUXVldWUgY29tcGxldGUgaWYgY29tcGxldGVkIGEgbG9vcCBpdGVyYXRpb24gb3IgdGhlIGFuaW1hdGlvbi5cblx0XHRsZXQgY29tcGxldGUgPSBmYWxzZTtcblx0XHRpZiAoZW50cnkubG9vcCkge1xuXHRcdFx0aWYgKGR1cmF0aW9uID09PSAwKVxuXHRcdFx0XHRjb21wbGV0ZSA9IHRydWU7XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0Y29uc3QgY3ljbGVzID0gTWF0aC5mbG9vcihlbnRyeS50cmFja1RpbWUgLyBkdXJhdGlvbik7XG5cdFx0XHRcdGNvbXBsZXRlID0gY3ljbGVzID4gMCAmJiBjeWNsZXMgPiBNYXRoLmZsb29yKGVudHJ5LnRyYWNrTGFzdCAvIGR1cmF0aW9uKTtcblx0XHRcdH1cblx0XHR9IGVsc2Vcblx0XHRcdGNvbXBsZXRlID0gYW5pbWF0aW9uVGltZSA+PSBhbmltYXRpb25FbmQgJiYgZW50cnkuYW5pbWF0aW9uTGFzdCA8IGFuaW1hdGlvbkVuZDtcblx0XHRpZiAoY29tcGxldGUpIHRoaXMucXVldWUuY29tcGxldGUoZW50cnkpO1xuXG5cdFx0Ly8gUXVldWUgZXZlbnRzIGFmdGVyIGNvbXBsZXRlLlxuXHRcdGZvciAoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBldmVudCA9IGV2ZW50c1tpXTtcblx0XHRcdGlmIChldmVudC50aW1lID49IGFuaW1hdGlvblN0YXJ0ICYmIGV2ZW50LnRpbWUgPD0gYW5pbWF0aW9uRW5kKSB0aGlzLnF1ZXVlLmV2ZW50KGVudHJ5LCBldmVudCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBldmVudHNSZXZlcnNlIChlbnRyeTogVHJhY2tFbnRyeSwgYW5pbWF0aW9uTGFzdDogbnVtYmVyLCBhbmltYXRpb25UaW1lOiBudW1iZXIpIHtcblx0XHRjb25zdCBkdXJhdGlvbiA9IGVudHJ5LmFuaW1hdGlvbiEuZHVyYXRpb24sIGZyb20gPSBkdXJhdGlvbiAtIGFuaW1hdGlvbkxhc3QsIHRvID0gZHVyYXRpb24gLSBhbmltYXRpb25UaW1lO1xuXHRcdGNvbnN0IHRpbWVsaW5lcyA9IGVudHJ5LmFuaW1hdGlvbiEudGltZWxpbmVzO1xuXHRcdGZvciAobGV0IGkgPSAwLCBuID0gZW50cnkuYW5pbWF0aW9uIS50aW1lbGluZXMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBldmVudFRpbWVsaW5lID0gdGltZWxpbmVzW2ldO1xuXHRcdFx0aWYgKCEoZXZlbnRUaW1lbGluZSBpbnN0YW5jZW9mIEV2ZW50VGltZWxpbmUpKSBjb250aW51ZTtcblx0XHRcdGNvbnN0IHRpbWVsaW5lRXZlbnRzID0gZXZlbnRUaW1lbGluZS5ldmVudHM7XG5cdFx0XHRjb25zdCBmcmFtZXMgPSBldmVudFRpbWVsaW5lLmZyYW1lcztcblx0XHRcdGNvbnN0IGZyYW1lQ291bnQgPSBmcmFtZXMubGVuZ3RoO1xuXHRcdFx0aWYgKGZyb20gPj0gdG8pIHsgLy8gZnJvbSAtPiB0b1xuXHRcdFx0XHRmb3IgKGxldCBpaSA9IDA7IGlpIDwgZnJhbWVDb3VudDsgaWkrKykge1xuXHRcdFx0XHRcdGlmIChmcmFtZXNbaWldIDwgdG8pIGNvbnRpbnVlO1xuXHRcdFx0XHRcdGlmIChmcmFtZXNbaWldID49IGZyb20pIGJyZWFrO1xuXHRcdFx0XHRcdHRoaXMuZXZlbnRzLnB1c2godGltZWxpbmVFdmVudHNbaWldKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Zm9yIChsZXQgaWkgPSAwOyBpaSA8IGZyYW1lQ291bnQ7IGlpKyspIHsgLy8gZnJvbSAtPiAwXG5cdFx0XHRcdFx0aWYgKGZyYW1lc1tpaV0gPj0gZnJvbSkgYnJlYWs7XG5cdFx0XHRcdFx0dGhpcy5ldmVudHMucHVzaCh0aW1lbGluZUV2ZW50c1tpaV0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGxldCBpaSA9IDA7IC8vIGVuZCAtPiB0b1xuXHRcdFx0XHRmb3IgKDsgaWkgPCBmcmFtZUNvdW50OyBpaSsrKVxuXHRcdFx0XHRcdGlmIChmcmFtZXNbaWldID49IHRvKSBicmVhaztcblx0XHRcdFx0Zm9yICg7IGlpIDwgZnJhbWVDb3VudDsgaWkrKylcblx0XHRcdFx0XHR0aGlzLmV2ZW50cy5wdXNoKHRpbWVsaW5lRXZlbnRzW2lpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqIFJlbW92ZXMgYWxsIGFuaW1hdGlvbnMgZnJvbSBhbGwgdHJhY2tzLCBsZWF2aW5nIHNrZWxldG9ucyBpbiB0aGVpciBjdXJyZW50IHBvc2UuXG5cdCAqXG5cdCAqIFVzdWFsbHkgeW91IHdhbnQgdG8gdXNlIHtAbGluayBzZXRFbXB0eUFuaW1hdGlvbnN9IHRvIG1peCB0aGUgc2tlbGV0b25zIGJhY2sgdG8gdGhlIHNldHVwIHBvc2UsIHJhdGhlciB0aGFuIGxlYXZpbmdcblx0ICogdGhlbSBpbiB0aGVpciBjdXJyZW50IHBvc2UuICovXG5cdGNsZWFyVHJhY2tzICgpIHtcblx0XHRjb25zdCBvbGREcmFpbkRpc2FibGVkID0gdGhpcy5xdWV1ZS5kcmFpbkRpc2FibGVkO1xuXHRcdHRoaXMucXVldWUuZHJhaW5EaXNhYmxlZCA9IHRydWU7XG5cdFx0Zm9yIChsZXQgaSA9IDAsIG4gPSB0aGlzLnRyYWNrcy5sZW5ndGg7IGkgPCBuOyBpKyspXG5cdFx0XHR0aGlzLmNsZWFyVHJhY2soaSk7XG5cdFx0dGhpcy50cmFja3MubGVuZ3RoID0gMDtcblx0XHR0aGlzLnF1ZXVlLmRyYWluRGlzYWJsZWQgPSBvbGREcmFpbkRpc2FibGVkO1xuXHRcdHRoaXMucXVldWUuZHJhaW4oKTtcblx0fVxuXG5cdC8qKiBSZW1vdmVzIGFsbCBhbmltYXRpb25zIGZyb20gdGhlIHRyYWNrLCBsZWF2aW5nIHNrZWxldG9ucyBpbiB0aGVpciBjdXJyZW50IHBvc2UuXG5cdCAqXG5cdCAqIFVzdWFsbHkgeW91IHdhbnQgdG8gdXNlIHtAbGluayBzZXRFbXB0eUFuaW1hdGlvbn0gdG8gbWl4IHRoZSBza2VsZXRvbnMgYmFjayB0byB0aGUgc2V0dXAgcG9zZSwgcmF0aGVyIHRoYW5cblx0ICogbGVhdmluZyB0aGVtIGluIHRoZWlyIGN1cnJlbnQgcG9zZS4gKi9cblx0Y2xlYXJUcmFjayAodHJhY2tJbmRleDogbnVtYmVyKSB7XG5cdFx0aWYgKHRyYWNrSW5kZXggPCAwKSB0aHJvdyBuZXcgRXJyb3IoXCJ0cmFja0luZGV4IG11c3QgYmUgPj0gMC5cIik7XG5cdFx0aWYgKHRyYWNrSW5kZXggPj0gdGhpcy50cmFja3MubGVuZ3RoKSByZXR1cm47XG5cdFx0Y29uc3QgY3VycmVudCA9IHRoaXMudHJhY2tzW3RyYWNrSW5kZXhdO1xuXHRcdGlmICghY3VycmVudCkgcmV0dXJuO1xuXG5cdFx0dGhpcy5xdWV1ZS5lbmQoY3VycmVudCk7XG5cblx0XHR0aGlzLmNsZWFyTmV4dChjdXJyZW50KTtcblxuXHRcdGxldCBlbnRyeSA9IGN1cnJlbnQ7XG5cdFx0d2hpbGUgKHRydWUpIHtcblx0XHRcdGNvbnN0IGZyb20gPSBlbnRyeS5taXhpbmdGcm9tO1xuXHRcdFx0aWYgKCFmcm9tKSBicmVhaztcblx0XHRcdHRoaXMucXVldWUuZW5kKGZyb20pO1xuXHRcdFx0ZW50cnkubWl4aW5nRnJvbSA9IG51bGw7XG5cdFx0XHRlbnRyeS5taXhpbmdUbyA9IG51bGw7XG5cdFx0XHRlbnRyeSA9IGZyb207XG5cdFx0fVxuXG5cdFx0dGhpcy50cmFja3NbY3VycmVudC50cmFja0luZGV4XSA9IG51bGw7XG5cblx0XHR0aGlzLnF1ZXVlLmRyYWluKCk7XG5cdH1cblxuXHRzZXRUcmFjayAoaW5kZXg6IG51bWJlciwgY3VycmVudDogVHJhY2tFbnRyeSwgaW50ZXJydXB0OiBib29sZWFuKSB7XG5cdFx0Y29uc3QgZnJvbSA9IHRoaXMuZXhwYW5kVG9JbmRleChpbmRleCk7XG5cdFx0dGhpcy50cmFja3NbaW5kZXhdID0gY3VycmVudDtcblx0XHRjdXJyZW50LnByZXZpb3VzID0gbnVsbDtcblxuXHRcdGlmIChmcm9tKSB7XG5cdFx0XHRmcm9tLm5leHQgPSBudWxsO1xuXHRcdFx0aWYgKGludGVycnVwdCkgdGhpcy5xdWV1ZS5pbnRlcnJ1cHQoZnJvbSk7XG5cdFx0XHRjdXJyZW50Lm1peGluZ0Zyb20gPSBmcm9tO1xuXHRcdFx0ZnJvbS5taXhpbmdUbyA9IGN1cnJlbnQ7XG5cdFx0XHRjdXJyZW50Lm1peFRpbWUgPSAwO1xuXG5cdFx0XHRmcm9tLnRpbWVsaW5lc1JvdGF0aW9uLmxlbmd0aCA9IDA7IC8vIFJlc2V0IHJvdGF0aW9uIGZvciBtaXhpbmcgb3V0LCBpbiBjYXNlIGVudHJ5IHdhcyBtaXhlZCBpbi5cblx0XHR9XG5cblx0XHR0aGlzLnF1ZXVlLnN0YXJ0KGN1cnJlbnQpO1xuXHR9XG5cblx0LyoqIFNldHMgYW4gYW5pbWF0aW9uIGJ5IG5hbWUuXG5cdCAqXG5cdCAqIFNlZSB7QGxpbmsgc2V0QW5pbWF0aW9ufS4gKi9cblx0c2V0QW5pbWF0aW9uICh0cmFja0luZGV4OiBudW1iZXIsIGFuaW1hdGlvbk5hbWU6IHN0cmluZywgbG9vcD86IGJvb2xlYW4pOiBUcmFja0VudHJ5O1xuXG5cdC8qKiBTZXRzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBmb3IgYSB0cmFjaywgZGlzY2FyZGluZyBhbnkgcXVldWVkIGFuaW1hdGlvbnMuXG5cdCAqXG5cdCAqIElmIHRoZSBmb3JtZXJseSBjdXJyZW50IHRyYWNrIGVudHJ5IGlzIGZvciB0aGUgc2FtZSBhbmltYXRpb24gYW5kIHdhcyBuZXZlciBhcHBsaWVkIHRvIGEgc2tlbGV0b24sIGl0IGlzIHJlcGxhY2VkIChub3QgbWl4ZWRcblx0ICogZnJvbSkuXG5cdCAqIEBwYXJhbSBsb29wIElmIHRydWUsIHRoZSBhbmltYXRpb24gd2lsbCByZXBlYXQuIElmIGZhbHNlIGl0IHdpbGwgbm90LCBpbnN0ZWFkIGl0cyBsYXN0IGZyYW1lIGlzIGFwcGxpZWQgaWYgcGxheWVkIGJleW9uZCBpdHNcblx0ICogICAgICAgICAgIGR1cmF0aW9uLiBJbiBlaXRoZXIgY2FzZSB7QGxpbmsgVHJhY2tFbnRyeS50cmFja0VuZH0gZGV0ZXJtaW5lcyB3aGVuIHRoZSB0cmFjayBpcyBjbGVhcmVkLlxuXHQgKiBAcmV0dXJuIEEgdHJhY2sgZW50cnkgdG8gYWxsb3cgZnVydGhlciBjdXN0b21pemF0aW9uIG9mIGFuaW1hdGlvbiBwbGF5YmFjay4gUmVmZXJlbmNlcyB0byB0aGUgdHJhY2sgZW50cnkgbXVzdCBub3QgYmUga2VwdFxuXHQgKiAgICAgICAgIGFmdGVyIHRoZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lci5kaXNwb3NlfSBldmVudCBvY2N1cnMuICovXG5cdHNldEFuaW1hdGlvbiAodHJhY2tJbmRleDogbnVtYmVyLCBhbmltYXRpb246IEFuaW1hdGlvbiwgbG9vcD86IGJvb2xlYW4pOiBUcmFja0VudHJ5O1xuXG5cdHNldEFuaW1hdGlvbiAodHJhY2tJbmRleDogbnVtYmVyLCBhbmltYXRpb25OYW1lT3JBbmltYXRpb246IHN0cmluZyB8IEFuaW1hdGlvbiwgbG9vcCA9IGZhbHNlKTogVHJhY2tFbnRyeSB7XG5cdFx0aWYgKHR5cGVvZiBhbmltYXRpb25OYW1lT3JBbmltYXRpb24gPT09IFwic3RyaW5nXCIpXG5cdFx0XHRyZXR1cm4gdGhpcy5zZXRBbmltYXRpb24xKHRyYWNrSW5kZXgsIGFuaW1hdGlvbk5hbWVPckFuaW1hdGlvbiwgbG9vcCk7XG5cdFx0cmV0dXJuIHRoaXMuc2V0QW5pbWF0aW9uMih0cmFja0luZGV4LCBhbmltYXRpb25OYW1lT3JBbmltYXRpb24sIGxvb3ApO1xuXHR9XG5cblx0cHJpdmF0ZSBzZXRBbmltYXRpb24xICh0cmFja0luZGV4OiBudW1iZXIsIGFuaW1hdGlvbk5hbWU6IHN0cmluZywgbG9vcDogYm9vbGVhbiA9IGZhbHNlKSB7XG5cdFx0Y29uc3QgYW5pbWF0aW9uID0gdGhpcy5kYXRhLnNrZWxldG9uRGF0YS5maW5kQW5pbWF0aW9uKGFuaW1hdGlvbk5hbWUpO1xuXHRcdGlmICghYW5pbWF0aW9uKSB0aHJvdyBuZXcgRXJyb3IoYEFuaW1hdGlvbiBub3QgZm91bmQ6ICR7YW5pbWF0aW9uTmFtZX1gKTtcblx0XHRyZXR1cm4gdGhpcy5zZXRBbmltYXRpb24yKHRyYWNrSW5kZXgsIGFuaW1hdGlvbiwgbG9vcCk7XG5cdH1cblxuXHQvKiogU2V0cyB0aGUgY3VycmVudCBhbmltYXRpb24gZm9yIGEgdHJhY2ssIGRpc2NhcmRpbmcgYW55IHF1ZXVlZCBhbmltYXRpb25zLlxuXHQgKlxuXHQgKiBJZiB0aGUgZm9ybWVybHkgY3VycmVudCB0cmFjayBlbnRyeSBpcyBmb3IgdGhlIHNhbWUgYW5pbWF0aW9uIGFuZCB3YXMgbmV2ZXIgYXBwbGllZCB0byBhIHNrZWxldG9uLCBpdCBpcyByZXBsYWNlZCAobm90IG1peGVkXG5cdCAqIGZyb20pLlxuXHQgKiBAcGFyYW0gbG9vcCBJZiB0cnVlLCB0aGUgYW5pbWF0aW9uIHdpbGwgcmVwZWF0LiBJZiBmYWxzZSBpdCB3aWxsIG5vdCwgaW5zdGVhZCBpdHMgbGFzdCBmcmFtZSBpcyBhcHBsaWVkIGlmIHBsYXllZCBiZXlvbmQgaXRzXG5cdCAqICAgICAgICAgICBkdXJhdGlvbi4gSW4gZWl0aGVyIGNhc2Uge0BsaW5rIFRyYWNrRW50cnkuZ2V0VHJhY2tFbmR9IGRldGVybWluZXMgd2hlbiB0aGUgdHJhY2sgaXMgY2xlYXJlZC5cblx0ICogQHJldHVybiBBIHRyYWNrIGVudHJ5IHRvIGFsbG93IGZ1cnRoZXIgY3VzdG9taXphdGlvbiBvZiBhbmltYXRpb24gcGxheWJhY2suIFJlZmVyZW5jZXMgdG8gdGhlIHRyYWNrIGVudHJ5IG11c3Qgbm90IGJlIGtlcHRcblx0ICogICAgICAgICBhZnRlciB0aGUge0BsaW5rIEFuaW1hdGlvblN0YXRlTGlzdGVuZXIuZGlzcG9zZX0gZXZlbnQgb2NjdXJzLiAqL1xuXHRwcml2YXRlIHNldEFuaW1hdGlvbjIgKHRyYWNrSW5kZXg6IG51bWJlciwgYW5pbWF0aW9uOiBBbmltYXRpb24sIGxvb3A6IGJvb2xlYW4gPSBmYWxzZSkge1xuXHRcdGlmICh0cmFja0luZGV4IDwgMCkgdGhyb3cgbmV3IEVycm9yKFwidHJhY2tJbmRleCBtdXN0IGJlID49IDAuXCIpO1xuXHRcdGlmICghYW5pbWF0aW9uKSB0aHJvdyBuZXcgRXJyb3IoXCJhbmltYXRpb24gY2Fubm90IGJlIG51bGwuXCIpO1xuXHRcdGxldCBpbnRlcnJ1cHQgPSB0cnVlO1xuXHRcdGxldCBjdXJyZW50ID0gdGhpcy5leHBhbmRUb0luZGV4KHRyYWNrSW5kZXgpO1xuXHRcdGlmIChjdXJyZW50KSB7XG5cdFx0XHRpZiAoY3VycmVudC5uZXh0VHJhY2tMYXN0ID09PSAtMSAmJiBjdXJyZW50LmFuaW1hdGlvbiA9PT0gYW5pbWF0aW9uKSB7XG5cdFx0XHRcdC8vIERvbid0IG1peCBmcm9tIGFuIGVudHJ5IHRoYXQgd2FzIG5ldmVyIGFwcGxpZWQuXG5cdFx0XHRcdHRoaXMudHJhY2tzW3RyYWNrSW5kZXhdID0gY3VycmVudC5taXhpbmdGcm9tO1xuXHRcdFx0XHR0aGlzLnF1ZXVlLmludGVycnVwdChjdXJyZW50KTtcblx0XHRcdFx0dGhpcy5xdWV1ZS5lbmQoY3VycmVudCk7XG5cdFx0XHRcdHRoaXMuY2xlYXJOZXh0KGN1cnJlbnQpO1xuXHRcdFx0XHRjdXJyZW50ID0gY3VycmVudC5taXhpbmdGcm9tO1xuXHRcdFx0XHRpbnRlcnJ1cHQgPSBmYWxzZTtcblx0XHRcdH0gZWxzZVxuXHRcdFx0XHR0aGlzLmNsZWFyTmV4dChjdXJyZW50KTtcblx0XHR9XG5cdFx0Y29uc3QgZW50cnkgPSB0aGlzLnRyYWNrRW50cnkodHJhY2tJbmRleCwgYW5pbWF0aW9uLCBsb29wLCBjdXJyZW50KTtcblx0XHR0aGlzLnNldFRyYWNrKHRyYWNrSW5kZXgsIGVudHJ5LCBpbnRlcnJ1cHQpO1xuXHRcdHRoaXMucXVldWUuZHJhaW4oKTtcblx0XHRyZXR1cm4gZW50cnk7XG5cdH1cblxuXHQvKiogUXVldWVzIGFuIGFuaW1hdGlvbiBieSBuYW1lLlxuXHQgKlxuXHQgKiBTZWUge0BsaW5rIGFkZEFuaW1hdGlvbn0uICovXG5cdGFkZEFuaW1hdGlvbiAodHJhY2tJbmRleDogbnVtYmVyLCBhbmltYXRpb25OYW1lOiBzdHJpbmcsIGxvb3A/OiBib29sZWFuLCBkZWxheT86IG51bWJlcik6IFRyYWNrRW50cnk7XG5cblx0LyoqIEFkZHMgYW4gYW5pbWF0aW9uIHRvIGJlIHBsYXllZCBhZnRlciB0aGUgY3VycmVudCBvciBsYXN0IHF1ZXVlZCBhbmltYXRpb24gZm9yIGEgdHJhY2suIElmIHRoZSB0cmFjayBoYXMgbm8gZW50cmllcywgdGhpcyBpc1xuXHQgKiBlcXVpdmFsZW50IHRvIGNhbGxpbmcge0BsaW5rIHNldEFuaW1hdGlvbn0uXG5cdCAqIEBwYXJhbSBkZWxheSBJZiA+IDAsIHNldHMge0BsaW5rIFRyYWNrRW50cnkuZGVsYXl9LiBJZiA8PSAwLCB0aGUgZGVsYXkgc2V0IGlzIHRoZSBkdXJhdGlvbiBvZiB0aGUgcHJldmlvdXMgdHJhY2sgZW50cnlcblx0ICogICAgICAgICAgIG1pbnVzIGFueSBtaXggZHVyYXRpb24gKGZyb20ge0BsaW5rIGRhdGF9KSBwbHVzIHRoZSBzcGVjaWZpZWQgYGRlbGF5YCAoaWUgdGhlIG1peCBlbmRzIGF0ICh3aGVuXG5cdCAqICAgICAgICAgICBgZGVsYXlgID0gMCkgb3IgYmVmb3JlICh3aGVuIGBkZWxheWAgPCAwKSB0aGUgcHJldmlvdXMgdHJhY2sgZW50cnkgZHVyYXRpb24pLiBJZiB0aGVcblx0ICogICAgICAgICAgIHByZXZpb3VzIGVudHJ5IGlzIGxvb3BpbmcsIGl0cyBuZXh0IGxvb3AgY29tcGxldGlvbiBpcyB1c2VkIGluc3RlYWQgb2YgaXRzIGR1cmF0aW9uLlxuXHQgKiBAcmV0dXJuIEEgdHJhY2sgZW50cnkgdG8gYWxsb3cgZnVydGhlciBjdXN0b21pemF0aW9uIG9mIGFuaW1hdGlvbiBwbGF5YmFjay4gUmVmZXJlbmNlcyB0byB0aGUgdHJhY2sgZW50cnkgbXVzdCBub3QgYmUga2VwdFxuXHQgKiAgICAgICAgIGFmdGVyIHRoZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lci5kaXNwb3NlfSBldmVudCBvY2N1cnMuICovXG5cdGFkZEFuaW1hdGlvbiAodHJhY2tJbmRleDogbnVtYmVyLCBhbmltYXRpb246IEFuaW1hdGlvbiwgbG9vcD86IGJvb2xlYW4sIGRlbGF5PzogbnVtYmVyKTogVHJhY2tFbnRyeTtcblxuXHRhZGRBbmltYXRpb24gKHRyYWNrSW5kZXg6IG51bWJlciwgYW5pbWF0aW9uTmFtZU9yQW5pbWF0aW9uOiBzdHJpbmcgfCBBbmltYXRpb24sIGxvb3AgPSBmYWxzZSwgZGVsYXk6IG51bWJlciA9IDApOiBUcmFja0VudHJ5IHtcblx0XHRpZiAodHlwZW9mIGFuaW1hdGlvbk5hbWVPckFuaW1hdGlvbiA9PT0gXCJzdHJpbmdcIilcblx0XHRcdHJldHVybiB0aGlzLmFkZEFuaW1hdGlvbjEodHJhY2tJbmRleCwgYW5pbWF0aW9uTmFtZU9yQW5pbWF0aW9uLCBsb29wLCBkZWxheSk7XG5cdFx0cmV0dXJuIHRoaXMuYWRkQW5pbWF0aW9uMih0cmFja0luZGV4LCBhbmltYXRpb25OYW1lT3JBbmltYXRpb24sIGxvb3AsIGRlbGF5KTtcblx0fVxuXG5cdHByaXZhdGUgYWRkQW5pbWF0aW9uMSAodHJhY2tJbmRleDogbnVtYmVyLCBhbmltYXRpb25OYW1lOiBzdHJpbmcsIGxvb3A6IGJvb2xlYW4gPSBmYWxzZSwgZGVsYXk6IG51bWJlciA9IDApIHtcblx0XHRjb25zdCBhbmltYXRpb24gPSB0aGlzLmRhdGEuc2tlbGV0b25EYXRhLmZpbmRBbmltYXRpb24oYW5pbWF0aW9uTmFtZSk7XG5cdFx0aWYgKCFhbmltYXRpb24pIHRocm93IG5ldyBFcnJvcihgQW5pbWF0aW9uIG5vdCBmb3VuZDogJHthbmltYXRpb25OYW1lfWApO1xuXHRcdHJldHVybiB0aGlzLmFkZEFuaW1hdGlvbjIodHJhY2tJbmRleCwgYW5pbWF0aW9uLCBsb29wLCBkZWxheSk7XG5cdH1cblxuXHRwcml2YXRlIGFkZEFuaW1hdGlvbjIgKHRyYWNrSW5kZXg6IG51bWJlciwgYW5pbWF0aW9uOiBBbmltYXRpb24sIGxvb3A6IGJvb2xlYW4gPSBmYWxzZSwgZGVsYXk6IG51bWJlciA9IDApIHtcblx0XHRpZiAodHJhY2tJbmRleCA8IDApIHRocm93IG5ldyBFcnJvcihcInRyYWNrSW5kZXggbXVzdCBiZSA+PSAwLlwiKTtcblx0XHRpZiAoIWFuaW1hdGlvbikgdGhyb3cgbmV3IEVycm9yKFwiYW5pbWF0aW9uIGNhbm5vdCBiZSBudWxsLlwiKTtcblxuXHRcdGxldCBsYXN0ID0gdGhpcy5leHBhbmRUb0luZGV4KHRyYWNrSW5kZXgpO1xuXHRcdGlmIChsYXN0KSB7XG5cdFx0XHR3aGlsZSAobGFzdC5uZXh0KVxuXHRcdFx0XHRsYXN0ID0gbGFzdC5uZXh0O1xuXHRcdH1cblxuXHRcdGNvbnN0IGVudHJ5ID0gdGhpcy50cmFja0VudHJ5KHRyYWNrSW5kZXgsIGFuaW1hdGlvbiwgbG9vcCwgbGFzdCk7XG5cblx0XHRpZiAoIWxhc3QpIHtcblx0XHRcdHRoaXMuc2V0VHJhY2sodHJhY2tJbmRleCwgZW50cnksIHRydWUpO1xuXHRcdFx0dGhpcy5xdWV1ZS5kcmFpbigpO1xuXHRcdFx0aWYgKGRlbGF5IDwgMCkgZGVsYXkgPSAwO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsYXN0Lm5leHQgPSBlbnRyeTtcblx0XHRcdGVudHJ5LnByZXZpb3VzID0gbGFzdDtcblx0XHRcdGlmIChkZWxheSA8PSAwKSBkZWxheSA9IE1hdGgubWF4KGRlbGF5ICsgbGFzdC5nZXRUcmFja0NvbXBsZXRlKCkgLSBlbnRyeS5taXhEdXJhdGlvbiwgMCk7XG5cdFx0fVxuXG5cdFx0ZW50cnkuZGVsYXkgPSBkZWxheTtcblx0XHRyZXR1cm4gZW50cnk7XG5cdH1cblxuXHQvKiogU2V0cyBhbiBlbXB0eSBhbmltYXRpb24gZm9yIGEgdHJhY2ssIGRpc2NhcmRpbmcgYW55IHF1ZXVlZCBhbmltYXRpb25zLCBhbmQgc2V0cyB0aGUgdHJhY2sgZW50cnknc1xuXHQgKiB7QGxpbmsgVHJhY2tFbnRyeS5taXhkdXJhdGlvbn0uIEFuIGVtcHR5IGFuaW1hdGlvbiBoYXMgbm8gdGltZWxpbmVzIGFuZCBzZXJ2ZXMgYXMgYSBwbGFjZWhvbGRlciBmb3IgbWl4aW5nIGluIG9yIG91dC5cblx0ICpcblx0ICogTWl4aW5nIG91dCBpcyBkb25lIGJ5IHNldHRpbmcgYW4gZW1wdHkgYW5pbWF0aW9uIHdpdGggYSBtaXggZHVyYXRpb24gdXNpbmcgZWl0aGVyIHtAbGluayBzZXRFbXB0eUFuaW1hdGlvbn0sXG5cdCAqIHtAbGluayBzZXRFbXB0eUFuaW1hdGlvbnN9LCBvciB7QGxpbmsgYWRkRW1wdHlBbmltYXRpb259LiBNaXhpbmcgdG8gYW4gZW1wdHkgYW5pbWF0aW9uIGNhdXNlc1xuXHQgKiB0aGUgcHJldmlvdXMgYW5pbWF0aW9uIHRvIGJlIGFwcGxpZWQgbGVzcyBhbmQgbGVzcyBvdmVyIHRoZSBtaXggZHVyYXRpb24uIFByb3BlcnRpZXMga2V5ZWQgaW4gdGhlIHByZXZpb3VzIGFuaW1hdGlvblxuXHQgKiB0cmFuc2l0aW9uIHRvIHRoZSB2YWx1ZSBmcm9tIGxvd2VyIHRyYWNrcyBvciB0byB0aGUgc2V0dXAgcG9zZSB2YWx1ZSBpZiBubyBsb3dlciB0cmFja3Mga2V5IHRoZSBwcm9wZXJ0eS4gQSBtaXggZHVyYXRpb24gb2Zcblx0ICogMCBzdGlsbCBuZWVkcyB0byBiZSBhcHBsaWVkIG9uZSBtb3JlIHRpbWUgdG8gbWl4IG91dCwgc28gdGhlIHByb3BlcnRpZXMgaXQgd2FzIGFuaW1hdGluZyBhcmUgcmV2ZXJ0ZWQuXG5cdCAqXG5cdCAqIE1peGluZyBpbiBpcyBkb25lIGJ5IGZpcnN0IHNldHRpbmcgYW4gZW1wdHkgYW5pbWF0aW9uLCB0aGVuIGFkZGluZyBhbiBhbmltYXRpb24gdXNpbmdcblx0ICoge0BsaW5rIGFkZEFuaW1hdGlvbn0gd2l0aCB0aGUgZGVzaXJlZCBkZWxheSAoYW4gZW1wdHkgYW5pbWF0aW9uIGhhcyBhIGR1cmF0aW9uIG9mIDApIGFuZCBvblxuXHQgKiB0aGUgcmV0dXJuZWQgdHJhY2sgZW50cnksIHNldCB0aGUge0BsaW5rIFRyYWNrRW50cnkuc2V0TWl4RHVyYXRpb259LiBNaXhpbmcgZnJvbSBhbiBlbXB0eSBhbmltYXRpb24gY2F1c2VzIHRoZSBuZXdcblx0ICogYW5pbWF0aW9uIHRvIGJlIGFwcGxpZWQgbW9yZSBhbmQgbW9yZSBvdmVyIHRoZSBtaXggZHVyYXRpb24uIFByb3BlcnRpZXMga2V5ZWQgaW4gdGhlIG5ldyBhbmltYXRpb24gdHJhbnNpdGlvbiBmcm9tIHRoZSB2YWx1ZVxuXHQgKiBmcm9tIGxvd2VyIHRyYWNrcyBvciBmcm9tIHRoZSBzZXR1cCBwb3NlIHZhbHVlIGlmIG5vIGxvd2VyIHRyYWNrcyBrZXkgdGhlIHByb3BlcnR5IHRvIHRoZSB2YWx1ZSBrZXllZCBpbiB0aGUgbmV3IGFuaW1hdGlvbi5cblx0ICpcblx0ICogU2VlIDxhIGhyZWY9J2h0dHBzOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtYXBwbHlpbmctYW5pbWF0aW9ucyNFbXB0eS1hbmltYXRpb25zJz5FbXB0eSBhbmltYXRpb25zPC9hPiBpbiB0aGUgU3BpbmVcblx0ICogUnVudGltZXMgR3VpZGUuICovXG5cdHNldEVtcHR5QW5pbWF0aW9uICh0cmFja0luZGV4OiBudW1iZXIsIG1peER1cmF0aW9uOiBudW1iZXIgPSAwKSB7XG5cdFx0Y29uc3QgZW50cnkgPSB0aGlzLnNldEFuaW1hdGlvbih0cmFja0luZGV4LCBBbmltYXRpb25TdGF0ZS5lbXB0eUFuaW1hdGlvbiwgZmFsc2UpO1xuXHRcdGVudHJ5Lm1peER1cmF0aW9uID0gbWl4RHVyYXRpb247XG5cdFx0ZW50cnkudHJhY2tFbmQgPSBtaXhEdXJhdGlvbjtcblx0XHRyZXR1cm4gZW50cnk7XG5cdH1cblxuXHQvKiogQWRkcyBhbiBlbXB0eSBhbmltYXRpb24gdG8gYmUgcGxheWVkIGFmdGVyIHRoZSBjdXJyZW50IG9yIGxhc3QgcXVldWVkIGFuaW1hdGlvbiBmb3IgYSB0cmFjaywgYW5kIHNldHMgdGhlIHRyYWNrIGVudHJ5J3Ncblx0ICoge0BsaW5rIFRyYWNrRW50cnkubWl4RHVyYXRpb259LiBJZiB0aGUgdHJhY2sgaGFzIG5vIGVudHJpZXMsIGl0IGlzIGVxdWl2YWxlbnQgdG8gY2FsbGluZ1xuXHQgKiB7QGxpbmsgc2V0RW1wdHlBbmltYXRpb259LlxuXHQgKlxuXHQgKiBTZWUge0BsaW5rIHNldEVtcHR5QW5pbWF0aW9ufSBhbmRcblx0ICogPGEgaHJlZj0naHR0cHM6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1hcHBseWluZy1hbmltYXRpb25zI0VtcHR5LWFuaW1hdGlvbnMnPkVtcHR5IGFuaW1hdGlvbnM8L2E+IGluIHRoZSBTcGluZSBSdW50aW1lc1xuXHQgKiBHdWlkZS5cblx0ICogQHBhcmFtIGRlbGF5IElmID4gMCwgc2V0cyB7QGxpbmsgVHJhY2tFbnRyeS5kZWxheX0uIElmIDw9IDAsIHRoZSBkZWxheSBzZXQgaXMgdGhlIGR1cmF0aW9uIG9mIHRoZSBwcmV2aW91cyB0cmFjayBlbnRyeSBtaW51c1xuXHQgKiAgICAgICAgICAgYW55IG1peCBkdXJhdGlvbiBwbHVzIHRoZSBzcGVjaWZpZWQgYGRlbGF5YCAoaWUgdGhlIG1peCBlbmRzIGF0ICh3aGVuIGBkZWxheWAgPSAwKSBvciBiZWZvcmVcblx0ICogICAgICAgICAgICh3aGVuIGBkZWxheWAgPCAwKSB0aGUgcHJldmlvdXMgdHJhY2sgZW50cnkgZHVyYXRpb24pLiBJZiB0aGUgcHJldmlvdXMgZW50cnkgaXMgbG9vcGluZywgaXRzIG5leHQgbG9vcFxuXHQgKiAgICAgICAgICAgY29tcGxldGlvbiBpcyB1c2VkIGluc3RlYWQgb2YgaXRzIGR1cmF0aW9uLlxuXHQgKiBAcmV0dXJuIEEgdHJhY2sgZW50cnkgdG8gYWxsb3cgZnVydGhlciBjdXN0b21pemF0aW9uIG9mIGFuaW1hdGlvbiBwbGF5YmFjay4gUmVmZXJlbmNlcyB0byB0aGUgdHJhY2sgZW50cnkgbXVzdCBub3QgYmUga2VwdFxuXHQgKiAgICAgICAgIGFmdGVyIHRoZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lci5kaXNwb3NlfSBldmVudCBvY2N1cnMuICovXG5cdGFkZEVtcHR5QW5pbWF0aW9uICh0cmFja0luZGV4OiBudW1iZXIsIG1peER1cmF0aW9uOiBudW1iZXIgPSAwLCBkZWxheTogbnVtYmVyID0gMCkge1xuXHRcdGNvbnN0IGVudHJ5ID0gdGhpcy5hZGRBbmltYXRpb24odHJhY2tJbmRleCwgQW5pbWF0aW9uU3RhdGUuZW1wdHlBbmltYXRpb24sIGZhbHNlLCBkZWxheSk7XG5cdFx0aWYgKGRlbGF5IDw9IDApIGVudHJ5LmRlbGF5ID0gTWF0aC5tYXgoZW50cnkuZGVsYXkgKyBlbnRyeS5taXhEdXJhdGlvbiAtIG1peER1cmF0aW9uLCAwKTtcblx0XHRlbnRyeS5taXhEdXJhdGlvbiA9IG1peER1cmF0aW9uO1xuXHRcdGVudHJ5LnRyYWNrRW5kID0gbWl4RHVyYXRpb247XG5cdFx0cmV0dXJuIGVudHJ5O1xuXHR9XG5cblx0LyoqIFNldHMgYW4gZW1wdHkgYW5pbWF0aW9uIGZvciBldmVyeSB0cmFjaywgZGlzY2FyZGluZyBhbnkgcXVldWVkIGFuaW1hdGlvbnMsIGFuZCBtaXhlcyB0byBpdCBvdmVyIHRoZSBzcGVjaWZpZWQgbWl4IGR1cmF0aW9uLlxuXHQgKlxuXHQgKiBTZWUgPGEgaHJlZj0naHR0cHM6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1hcHBseWluZy1hbmltYXRpb25zI0VtcHR5LWFuaW1hdGlvbnMnPkVtcHR5IGFuaW1hdGlvbnM8L2E+IGluIHRoZSBTcGluZVxuXHQgKiBSdW50aW1lcyBHdWlkZS4gKi9cblx0c2V0RW1wdHlBbmltYXRpb25zIChtaXhEdXJhdGlvbjogbnVtYmVyID0gMCkge1xuXHRcdGNvbnN0IG9sZERyYWluRGlzYWJsZWQgPSB0aGlzLnF1ZXVlLmRyYWluRGlzYWJsZWQ7XG5cdFx0dGhpcy5xdWV1ZS5kcmFpbkRpc2FibGVkID0gdHJ1ZTtcblx0XHRmb3IgKGxldCBpID0gMCwgbiA9IHRoaXMudHJhY2tzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuXHRcdFx0Y29uc3QgY3VycmVudCA9IHRoaXMudHJhY2tzW2ldO1xuXHRcdFx0aWYgKGN1cnJlbnQpIHRoaXMuc2V0RW1wdHlBbmltYXRpb24oY3VycmVudC50cmFja0luZGV4LCBtaXhEdXJhdGlvbik7XG5cdFx0fVxuXHRcdHRoaXMucXVldWUuZHJhaW5EaXNhYmxlZCA9IG9sZERyYWluRGlzYWJsZWQ7XG5cdFx0dGhpcy5xdWV1ZS5kcmFpbigpO1xuXHR9XG5cblx0ZXhwYW5kVG9JbmRleCAoaW5kZXg6IG51bWJlcikge1xuXHRcdGlmIChpbmRleCA8IHRoaXMudHJhY2tzLmxlbmd0aCkgcmV0dXJuIHRoaXMudHJhY2tzW2luZGV4XTtcblx0XHRVdGlscy5lbnN1cmVBcnJheUNhcGFjaXR5KHRoaXMudHJhY2tzLCBpbmRleCArIDEsIG51bGwpO1xuXHRcdHRoaXMudHJhY2tzLmxlbmd0aCA9IGluZGV4ICsgMTtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdC8qKiBAcGFyYW0gbGFzdCBNYXkgYmUgbnVsbC4gKi9cblx0dHJhY2tFbnRyeSAodHJhY2tJbmRleDogbnVtYmVyLCBhbmltYXRpb246IEFuaW1hdGlvbiwgbG9vcDogYm9vbGVhbiwgbGFzdDogVHJhY2tFbnRyeSB8IG51bGwpIHtcblx0XHRjb25zdCBlbnRyeSA9IHRoaXMudHJhY2tFbnRyeVBvb2wub2J0YWluKCk7XG5cdFx0ZW50cnkucmVzZXQoKTtcblx0XHRlbnRyeS50cmFja0luZGV4ID0gdHJhY2tJbmRleDtcblx0XHRlbnRyeS5hbmltYXRpb24gPSBhbmltYXRpb247XG5cdFx0ZW50cnkubG9vcCA9IGxvb3A7XG5cblx0XHRlbnRyeS5hZGRpdGl2ZSA9IGZhbHNlO1xuXHRcdGVudHJ5LnJldmVyc2UgPSBmYWxzZTtcblx0XHRlbnRyeS5zaG9ydGVzdFJvdGF0aW9uID0gZmFsc2U7XG5cblx0XHRlbnRyeS5ldmVudFRocmVzaG9sZCA9IDA7XG5cdFx0ZW50cnkuYWxwaGFBdHRhY2htZW50VGhyZXNob2xkID0gMDtcblx0XHRlbnRyeS5taXhBdHRhY2htZW50VGhyZXNob2xkID0gMDtcblx0XHRlbnRyeS5taXhEcmF3T3JkZXJUaHJlc2hvbGQgPSAwO1xuXG5cdFx0ZW50cnkuYW5pbWF0aW9uU3RhcnQgPSAwO1xuXHRcdGVudHJ5LmFuaW1hdGlvbkVuZCA9IGFuaW1hdGlvbi5kdXJhdGlvbjtcblx0XHRlbnRyeS5hbmltYXRpb25MYXN0ID0gLTE7XG5cdFx0ZW50cnkubmV4dEFuaW1hdGlvbkxhc3QgPSAtMTtcblxuXHRcdGVudHJ5LmRlbGF5ID0gMDtcblx0XHRlbnRyeS50cmFja1RpbWUgPSAwO1xuXHRcdGVudHJ5LnRyYWNrTGFzdCA9IC0xO1xuXHRcdGVudHJ5Lm5leHRUcmFja0xhc3QgPSAtMTtcblx0XHRlbnRyeS50cmFja0VuZCA9IE51bWJlci5NQVhfVkFMVUU7XG5cdFx0ZW50cnkudGltZVNjYWxlID0gMTtcblxuXHRcdGVudHJ5LmFscGhhID0gMTtcblx0XHRlbnRyeS5taXhUaW1lID0gMDtcblx0XHRlbnRyeS5taXhEdXJhdGlvbiA9ICFsYXN0ID8gMCA6IHRoaXMuZGF0YS5nZXRNaXgobGFzdC5hbmltYXRpb24hLCBhbmltYXRpb24pO1xuXHRcdGVudHJ5LnRvdGFsQWxwaGEgPSAwO1xuXHRcdGVudHJ5LmtlZXBIb2xkID0gZmFsc2U7XG5cdFx0cmV0dXJuIGVudHJ5O1xuXHR9XG5cblx0LyoqIFJlbW92ZXMge0BsaW5rIFRyYWNrRW50cnkubmV4dH0gYW5kIGFsbCBlbnRyaWVzIGFmdGVyIGl0IGZvciB0aGUgc3BlY2lmaWVkIGVudHJ5LiAqL1xuXHRjbGVhck5leHQgKGVudHJ5OiBUcmFja0VudHJ5KSB7XG5cdFx0bGV0IG5leHQgPSBlbnRyeS5uZXh0O1xuXHRcdHdoaWxlIChuZXh0KSB7XG5cdFx0XHR0aGlzLnF1ZXVlLmRpc3Bvc2UobmV4dCk7XG5cdFx0XHRuZXh0ID0gbmV4dC5uZXh0O1xuXHRcdH1cblx0XHRlbnRyeS5uZXh0ID0gbnVsbDtcblx0fVxuXG5cdF9hbmltYXRpb25zQ2hhbmdlZCAoKSB7XG5cdFx0dGhpcy5hbmltYXRpb25zQ2hhbmdlZCA9IGZhbHNlO1xuXG5cdFx0Y29uc3QgdHJhY2tzID0gdGhpcy50cmFja3M7XG5cdFx0Zm9yIChsZXQgaSA9IDAsIG4gPSB0cmFja3MubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCB0cmFjayA9IHRyYWNrc1tpXTtcblx0XHRcdGlmICghdHJhY2spIGNvbnRpbnVlO1xuXHRcdFx0bGV0IGVudHJ5OiBUcmFja0VudHJ5IHwgbnVsbCA9IHRyYWNrO1xuXHRcdFx0d2hpbGUgKGVudHJ5Lm1peGluZ0Zyb20pXG5cdFx0XHRcdGVudHJ5ID0gZW50cnkubWl4aW5nRnJvbTtcblx0XHRcdGRvIHtcblx0XHRcdFx0dGhpcy5jb21wdXRlSG9sZChlbnRyeSwgdHJhY2spO1xuXHRcdFx0XHRlbnRyeSA9IGVudHJ5Lm1peGluZ1RvO1xuXHRcdFx0fSB3aGlsZSAoZW50cnkpO1xuXHRcdH1cblx0XHR0aGlzLnByb3BlcnR5SWRzLmNsZWFyKCk7XG5cdH1cblxuXHRjb21wdXRlSG9sZCAoZW50cnk6IFRyYWNrRW50cnksIHRyYWNrOiBUcmFja0VudHJ5KSB7XG5cdFx0Y29uc3QgdGltZWxpbmVzID0gZW50cnkuYW5pbWF0aW9uIS50aW1lbGluZXM7XG5cdFx0Y29uc3QgdGltZWxpbmVzQ291bnQgPSBlbnRyeS5hbmltYXRpb24hLnRpbWVsaW5lcy5sZW5ndGg7XG5cdFx0Y29uc3QgdGltZWxpbmVNb2RlID0gZW50cnkudGltZWxpbmVNb2RlO1xuXHRcdHRpbWVsaW5lTW9kZS5sZW5ndGggPSB0aW1lbGluZXNDb3VudDtcblx0XHRjb25zdCB0aW1lbGluZUhvbGRNaXggPSBlbnRyeS50aW1lbGluZUhvbGRNaXg7XG5cdFx0dGltZWxpbmVIb2xkTWl4Lmxlbmd0aCA9IDA7XG5cdFx0Y29uc3QgYWRkID0gZW50cnkuYWRkaXRpdmUsIGtlZXBIb2xkID0gZW50cnkua2VlcEhvbGQ7XG5cdFx0Y29uc3QgdG8gPSBlbnRyeS5taXhpbmdUbztcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdGltZWxpbmVzQ291bnQ7IGkrKykge1xuXHRcdFx0Y29uc3QgdGltZWxpbmUgPSB0aW1lbGluZXNbaV07XG5cdFx0XHRjb25zdCBpZHMgPSB0aW1lbGluZS5wcm9wZXJ0eUlkcztcblx0XHRcdGNvbnN0IGZyb20gPSB0aGlzLmZyb20odHJhY2ssIHRpbWVsaW5lLCBpZHMpO1xuXG5cdFx0XHRpZiAoYWRkICYmIHRpbWVsaW5lLmFkZGl0aXZlKSB7XG5cdFx0XHRcdHRpbWVsaW5lTW9kZVtpXSA9IGZyb207XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBIb2xkIGlmIHRoZSBuZXh0IGVudHJ5IHdpbGwgb3ZlcndyaXRlIHRoaXMgcHJvcGVydHkuXG5cdFx0XHRsZXQgbW9kZTogbnVtYmVyO1xuXHRcdFx0aWYgKHRvID09PSBudWxsIHx8IHRpbWVsaW5lLmluc3RhbnQgfHwgKHRvLmFkZGl0aXZlICYmIHRpbWVsaW5lLmFkZGl0aXZlKSB8fCAhdG8uYW5pbWF0aW9uPy5oYXNUaW1lbGluZShpZHMpKVxuXHRcdFx0XHRtb2RlID0gZnJvbTtcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRtb2RlID0gZnJvbSB8IEhPTEQ7XG5cdFx0XHRcdC8vIEZpbmQgbmV4dCBlbnRyeSB0aGF0IGRvZXNuJ3Qgb3ZlcndyaXRlIHRoaXMgcHJvcGVydHkuIEl0cyBtaXggZmFkZXMgb3V0IHRoZSBob2xkLCBpbnN0ZWFkIG9mIGl0IGVuZGluZyBhYnJ1cHRseS5cblx0XHRcdFx0Zm9yIChsZXQgbmV4dCA9IHRvLm1peGluZ1RvOyBuZXh0ICE9IG51bGw7IG5leHQgPSBuZXh0Lm1peGluZ1RvKSB7XG5cdFx0XHRcdFx0aWYgKChuZXh0LmFkZGl0aXZlICYmIHRpbWVsaW5lLmFkZGl0aXZlKSB8fCAhbmV4dC5hbmltYXRpb24/Lmhhc1RpbWVsaW5lKGlkcykpIHtcblx0XHRcdFx0XHRcdGlmIChuZXh0Lm1peER1cmF0aW9uID4gMCkgdGltZWxpbmVIb2xkTWl4W2ldID0gbmV4dDtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKGtlZXBIb2xkKSBtb2RlID0gKG1vZGUgJiB+SE9MRCkgfCAodGltZWxpbmVNb2RlW2ldICYgSE9MRCk7XG5cdFx0XHR0aW1lbGluZU1vZGVbaV0gPSBtb2RlO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgZnJvbSAodHJhY2s6IFRyYWNrRW50cnksIHRpbWVsaW5lOiBUaW1lbGluZSwgaWRzOiBzdHJpbmdbXSk6IG51bWJlciB7XG5cdFx0Y29uc3QgcHJvcGVydHlJZHMgPSB0aGlzLnByb3BlcnR5SWRzO1xuXHRcdGxldCBmcm9tID0gU0VUVVA7XG5cdFx0Ly8gUmVmZXJlbmNlIHJ1bnRpbWUgdXNlcyBMb25nTWFwLnB1dE1pc3NpbmcuIE1hcCBoYXMgbm8gZXF1aXZhbGVudCwgc28gZ2V0L3NldCBwcmVzZXJ2ZXMgdGhvc2Ugc2VtYW50aWNzIGhlcmUuXG5cdFx0Zm9yIChsZXQgaSA9IDAsIG4gPSBpZHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBvd25lciA9IHByb3BlcnR5SWRzLmdldChpZHNbaV0pO1xuXHRcdFx0aWYgKG93bmVyID09PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0cHJvcGVydHlJZHMuc2V0KGlkc1tpXSwgdHJhY2spO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKG93bmVyICE9PSB0cmFjaykge1xuXHRcdFx0XHRcdHdoaWxlICgrK2kgPCBuKVxuXHRcdFx0XHRcdFx0aWYgKCFwcm9wZXJ0eUlkcy5oYXMoaWRzW2ldKSkgcHJvcGVydHlJZHMuc2V0KGlkc1tpXSwgdHJhY2spO1xuXHRcdFx0XHRcdHJldHVybiBDVVJSRU5UO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGZyb20gPSBGSVJTVDtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHRpbWVsaW5lIGluc3RhbmNlb2YgRHJhd09yZGVyRm9sZGVyVGltZWxpbmUpIHtcblx0XHRcdGNvbnN0IGZpcnN0ID0gcHJvcGVydHlJZHMuZ2V0KERyYXdPcmRlclRpbWVsaW5lLnByb3BlcnR5SUQpO1xuXHRcdFx0aWYgKGZpcnN0ICE9IG51bGwpIHJldHVybiBmaXJzdCAhPT0gdHJhY2sgPyBDVVJSRU5UIDogRklSU1Q7XG5cdFx0fVxuXHRcdHJldHVybiBmcm9tO1xuXHR9XG5cblx0LyoqIFJldHVybnMgdGhlIHRyYWNrIGVudHJ5IGZvciB0aGUgYW5pbWF0aW9uIGN1cnJlbnRseSBwbGF5aW5nIG9uIHRoZSB0cmFjaywgb3IgbnVsbCBpZiBubyBhbmltYXRpb24gaXMgY3VycmVudGx5IHBsYXlpbmcuICovXG5cdGdldFRyYWNrICh0cmFja0luZGV4OiBudW1iZXIpIHtcblx0XHRpZiAodHJhY2tJbmRleCA8IDApIHRocm93IG5ldyBFcnJvcihcInRyYWNrSW5kZXggbXVzdCBiZSA+PSAwLlwiKTtcblx0XHRpZiAodHJhY2tJbmRleCA+PSB0aGlzLnRyYWNrcy5sZW5ndGgpIHJldHVybiBudWxsO1xuXHRcdHJldHVybiB0aGlzLnRyYWNrc1t0cmFja0luZGV4XTtcblx0fVxuXG5cblx0LyoqIEFkZHMgYSBsaXN0ZW5lciB0byByZWNlaXZlIGV2ZW50cyBmb3IgYWxsIHRyYWNrIGVudHJpZXMuICovXG5cdGFkZExpc3RlbmVyIChsaXN0ZW5lcjogQW5pbWF0aW9uU3RhdGVMaXN0ZW5lcikge1xuXHRcdGlmICghbGlzdGVuZXIpIHRocm93IG5ldyBFcnJvcihcImxpc3RlbmVyIGNhbm5vdCBiZSBudWxsLlwiKTtcblx0XHR0aGlzLmxpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcblx0fVxuXG5cdC8qKiBSZW1vdmVzIHRoZSBsaXN0ZW5lciBhZGRlZCB3aXRoIHtAbGluayBhZGRMaXN0ZW5lcn0uICovXG5cdHJlbW92ZUxpc3RlbmVyIChsaXN0ZW5lcjogQW5pbWF0aW9uU3RhdGVMaXN0ZW5lcikge1xuXHRcdGNvbnN0IGluZGV4ID0gdGhpcy5saXN0ZW5lcnMuaW5kZXhPZihsaXN0ZW5lcik7XG5cdFx0aWYgKGluZGV4ID49IDApIHRoaXMubGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XG5cdH1cblxuXHQvKiogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGFkZGVkIHdpdGgge0BsaW5rIGFkZExpc3RlbmVyfS4gKi9cblx0Y2xlYXJMaXN0ZW5lcnMgKCkge1xuXHRcdHRoaXMubGlzdGVuZXJzLmxlbmd0aCA9IDA7XG5cdH1cblxuXHQvKiogRGlzY2FyZHMgYWxsIGxpc3RlbmVyIG5vdGlmaWNhdGlvbnMgdGhhdCBoYXZlIG5vdCB5ZXQgYmVlbiBkZWxpdmVyZWQuIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBjYWxsIGZyb20gYW5cblx0ICoge0BsaW5rIEFuaW1hdGlvblN0YXRlTGlzdGVuZXJ9IHdoZW4gaXQgaXMga25vd24gdGhhdCBmdXJ0aGVyIG5vdGlmaWNhdGlvbnMgdGhhdCBtYXkgaGF2ZSBiZWVuIGFscmVhZHkgcXVldWVkIGZvciBkZWxpdmVyeVxuXHQgKiBhcmUgbm90IHdhbnRlZCBiZWNhdXNlIG5ldyBhbmltYXRpb25zIGFyZSBiZWluZyBzZXQuICovXG5cdGNsZWFyTGlzdGVuZXJOb3RpZmljYXRpb25zICgpIHtcblx0XHR0aGlzLnF1ZXVlLmNsZWFyKCk7XG5cdH1cbn1cblxuLyoqIFN0b3JlcyBzZXR0aW5ncyBhbmQgb3RoZXIgc3RhdGUgZm9yIHRoZSBwbGF5YmFjayBvZiBhbiBhbmltYXRpb24gb24gYW4ge0BsaW5rIEFuaW1hdGlvblN0YXRlfSB0cmFjay5cbiAqXG4gKiBSZWZlcmVuY2VzIHRvIGEgdHJhY2sgZW50cnkgbXVzdCBub3QgYmUga2VwdCBhZnRlciB0aGUge0BsaW5rIEFuaW1hdGlvblN0YXRlTGlzdGVuZXIuZGlzcG9zZX0gZXZlbnQgb2NjdXJzLiAqL1xuZXhwb3J0IGNsYXNzIFRyYWNrRW50cnkge1xuXHQvKiogVGhlIGFuaW1hdGlvbiB0byBhcHBseSBmb3IgdGhpcyB0cmFjayBlbnRyeS4gKi9cblx0YW5pbWF0aW9uOiBBbmltYXRpb24gfCBudWxsID0gbnVsbDtcblxuXHRwcmV2aW91czogVHJhY2tFbnRyeSB8IG51bGwgPSBudWxsO1xuXG5cdC8qKiBUaGUgYW5pbWF0aW9uIHF1ZXVlZCB0byBzdGFydCBhZnRlciB0aGlzIGFuaW1hdGlvbiwgb3IgbnVsbC4gYG5leHRgIG1ha2VzIHVwIGEgbGlua2VkIGxpc3QuICovXG5cdG5leHQ6IFRyYWNrRW50cnkgfCBudWxsID0gbnVsbDtcblxuXHQvKiogVGhlIHRyYWNrIGVudHJ5IGZvciB0aGUgcHJldmlvdXMgYW5pbWF0aW9uIHdoZW4gbWl4aW5nIHRvIHRoaXMgYW5pbWF0aW9uLCBvciBudWxsIGlmIG5vIG1peGluZyBpcyBjdXJyZW50bHkgb2NjdXJyaW5nLlxuXHQgKiBXaGVuIG1peGluZyBmcm9tIG11bHRpcGxlIGFuaW1hdGlvbnMsIGBtaXhpbmdGcm9tYCBtYWtlcyB1cCBhIGRvdWJseSBsaW5rZWQgbGlzdC4gKi9cblx0bWl4aW5nRnJvbTogVHJhY2tFbnRyeSB8IG51bGwgPSBudWxsO1xuXG5cdC8qKiBUaGUgdHJhY2sgZW50cnkgZm9yIHRoZSBuZXh0IGFuaW1hdGlvbiB3aGVuIG1peGluZyBmcm9tIHRoaXMgYW5pbWF0aW9uLCBvciBudWxsIGlmIG5vIG1peGluZyBpcyBjdXJyZW50bHkgb2NjdXJyaW5nLlxuXHQgKiBXaGVuIG1peGluZyB0byBtdWx0aXBsZSBhbmltYXRpb25zLCBgbWl4aW5nVG9gIG1ha2VzIHVwIGEgZG91Ymx5IGxpbmtlZCBsaXN0LiAqL1xuXHRtaXhpbmdUbzogVHJhY2tFbnRyeSB8IG51bGwgPSBudWxsO1xuXG5cdC8qKiBUaGUgbGlzdGVuZXIgZm9yIGV2ZW50cyBnZW5lcmF0ZWQgYnkgdGhpcyB0cmFjayBlbnRyeSwgb3IgbnVsbC5cblx0ICpcblx0ICogQSB0cmFjayBlbnRyeSByZXR1cm5lZCBmcm9tIHtAbGluayBBbmltYXRpb25TdGF0ZS5zZXRBbmltYXRpb259IGlzIGFscmVhZHkgdGhlIGN1cnJlbnQgYW5pbWF0aW9uXG5cdCAqIGZvciB0aGUgdHJhY2ssIHNvIHRoZSBjYWxsYmFjayBmb3IgbGlzdGVuZXIge0BsaW5rIEFuaW1hdGlvblN0YXRlTGlzdGVuZXIuc3RhcnR9IHdpbGwgbm90IGJlIGNhbGxlZC4gKi9cblx0bGlzdGVuZXI6IEFuaW1hdGlvblN0YXRlTGlzdGVuZXIgfCBudWxsID0gbnVsbDtcblxuXHQvKiogVGhlIGluZGV4IG9mIHRoZSB0cmFjayB3aGVyZSB0aGlzIHRyYWNrIGVudHJ5IGlzIGVpdGhlciBjdXJyZW50IG9yIHF1ZXVlZC5cblx0ICpcblx0ICogU2VlIHtAbGluayBBbmltYXRpb25TdGF0ZS5nZXRUcmFja30uICovXG5cdHRyYWNrSW5kZXggPSAwO1xuXG5cdC8qKiBJZiB0cnVlLCB0aGUgYW5pbWF0aW9uIHdpbGwgcmVwZWF0LiBJZiBmYWxzZSBpdCB3aWxsIG5vdCwgaW5zdGVhZCBpdHMgbGFzdCBmcmFtZSBpcyBhcHBsaWVkIGlmIHBsYXllZCBiZXlvbmQgaXRzXG5cdCAqIGR1cmF0aW9uLiAqL1xuXHRsb29wID0gZmFsc2U7XG5cblx0LyoqIFdoZW4gdHJ1ZSwgdGltZWxpbmVzIGluIHRoaXMgYW5pbWF0aW9uIHRoYXQgc3VwcG9ydCBhZGRpdGl2ZSBoYXZlIHRoZWlyIHZhbHVlcyBhZGRlZCB0byB0aGUgc2V0dXAgb3IgY3VycmVudCBwb3NlIHZhbHVlc1xuXHQgKiBpbnN0ZWFkIG9mIHJlcGxhY2luZyB0aGVtLiBBZGRpdGl2ZSBjYW4gYmUgc2V0IGZvciBhIG5ldyB0cmFjayBlbnRyeSBvbmx5IGJlZm9yZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYXBwbHl9XG5cdCAqIGlzIG5leHQgY2FsbGVkLiAqL1xuXHRhZGRpdGl2ZSA9IGZhbHNlO1xuXG5cdC8qKiBJZiB0cnVlLCB0aGUgYW5pbWF0aW9uIHdpbGwgYmUgYXBwbGllZCBpbiByZXZlcnNlLiAqL1xuXHRyZXZlcnNlID0gZmFsc2U7XG5cblx0LyoqIElmIHRydWUsIG1peGluZyByb3RhdGlvbiBiZXR3ZWVuIHRyYWNrcyBhbHdheXMgdXNlcyB0aGUgc2hvcnRlc3Qgcm90YXRpb24gZGlyZWN0aW9uLiBJZiB0aGUgcm90YXRpb24gaXMgYW5pbWF0ZWQsIHRoZVxuXHQgKiBzaG9ydGVzdCByb3RhdGlvbiBkaXJlY3Rpb24gbWF5IGNoYW5nZSBkdXJpbmcgdGhlIG1peC5cblx0ICpcblx0ICogSWYgZmFsc2UsIHRoZSBzaG9ydGVzdCByb3RhdGlvbiBkaXJlY3Rpb24gaXMgcmVtZW1iZXJlZCB3aGVuIHRoZSBtaXggc3RhcnRzIGFuZCB0aGUgc2FtZSBkaXJlY3Rpb24gaXMgdXNlZCBmb3IgdGhlIHJlc3Rcblx0ICogb2YgdGhlIG1peC4gRGVmYXVsdHMgdG8gZmFsc2UuXG5cdCAqXG5cdCAqIFNlZSB7QGxpbmsgcmVzZXRSb3RhdGlvbkRpcmVjdGlvbnN9LiAqL1xuXHRzaG9ydGVzdFJvdGF0aW9uID0gZmFsc2U7XG5cblx0a2VlcEhvbGQgPSBmYWxzZTtcblxuXHQvKiogV2hlbiB0aGUgaW50ZXJwb2xhdGVkIG1peCBwZXJjZW50YWdlIGlzIGxlc3MgdGhhbiB0aGUgYGV2ZW50VGhyZXNob2xkYCAsIGV2ZW50IHRpbWVsaW5lcyBhcmUgYXBwbGllZCB3aGlsZVxuXHQgKiB0aGlzIGFuaW1hdGlvbiBpcyBiZWluZyBtaXhlZCBvdXQuIERlZmF1bHRzIHRvIDAsIHNvIGV2ZW50IHRpbWVsaW5lcyBhcmUgbm90IGFwcGxpZWQgd2hpbGUgdGhpcyBhbmltYXRpb24gaXMgYmVpbmcgbWl4ZWRcblx0ICogb3V0LiAqL1xuXHRldmVudFRocmVzaG9sZCA9IDA7XG5cblx0LyoqIFdoZW4gdGhlIGludGVycG9sYXRlZCBtaXggcGVyY2VudGFnZSBpcyBsZXNzIHRoYW4gdGhlIGBtaXhBdHRhY2htZW50VGhyZXNob2xkYCwgYXR0YWNobWVudCB0aW1lbGluZXMgYXJlXG5cdCAqIGFwcGxpZWQgd2hpbGUgdGhpcyBhbmltYXRpb24gaXMgYmVpbmcgbWl4ZWQgb3V0LiBEZWZhdWx0cyB0byAwLCBzbyBhdHRhY2htZW50IHRpbWVsaW5lcyBhcmUgbm90IGFwcGxpZWQgd2hpbGUgdGhpc1xuXHQgKiBhbmltYXRpb24gaXMgYmVpbmcgbWl4ZWQgb3V0LiAqL1xuXHRtaXhBdHRhY2htZW50VGhyZXNob2xkID0gMDtcblxuXHQvKiogV2hlbiB0aGUgY29tcHV0ZWQgYWxwaGEgaXMgZ3JlYXRlciB0aGFuIGBhbHBoYUF0dGFjaG1lbnRUaHJlc2hvbGRgLCBhdHRhY2htZW50IHRpbWVsaW5lcyBhcmUgYXBwbGllZC4gVGhlXG5cdCAqIGNvbXB1dGVkIGFscGhhIGluY2x1ZGVzIHtAbGluayBhbHBoYX0gYW5kIHRoZSBpbnRlcnBvbGF0ZWQgbWl4IHBlcmNlbnRhZ2UuIERlZmF1bHRzIHRvIDAsIHNvIGF0dGFjaG1lbnQgdGltZWxpbmVzIGFyZVxuXHQgKiBhbHdheXMgYXBwbGllZC4gKi9cblx0YWxwaGFBdHRhY2htZW50VGhyZXNob2xkID0gMDtcblxuXHQvKiogV2hlbiB0aGUgaW50ZXJwb2xhdGVkIG1peCBwZXJjZW50YWdlIGlzIGxlc3MgdGhhbiB0aGUgYG1peEF0dGFjaG1lbnRUaHJlc2hvbGRgLCBhdHRhY2htZW50IHRpbWVsaW5lcyBhcmVcblx0ICogYXBwbGllZCB3aGlsZSB0aGlzIGFuaW1hdGlvbiBpcyBiZWluZyBtaXhlZCBvdXQuIERlZmF1bHRzIHRvIDAsIHNvIGF0dGFjaG1lbnQgdGltZWxpbmVzIGFyZSBub3QgYXBwbGllZCB3aGlsZSB0aGlzXG5cdCAqIGFuaW1hdGlvbiBpcyBiZWluZyBtaXhlZCBvdXQuICovXG5cdG1peERyYXdPcmRlclRocmVzaG9sZCA9IDA7XG5cblx0LyoqIFRoZSB0aW1lIGluIHNlY29uZHMgZm9yIHRoZSBmaXJzdCBmcmFtZSBvZiB0aGlzIGFuaW1hdGlvbiwgYm90aCBpbml0aWFsbHkgYW5kIGFmdGVyIGxvb3BpbmcuIERlZmF1bHRzIHRvIDAuXG5cdCAqXG5cdCAqIFdoZW4gc2V0dGluZyBgYW5pbWF0aW9uU3RhcnRgIHRpbWUsIHtAbGluayBhbmltYXRpb25MYXN0fSBjYW4gYmUgc2V0IHRvIHRoZSBzYW1lIHZhbHVlIHRvIGF2b2lkIGZpcmluZyBldmVudHNcblx0ICogZnJvbSB0aGUgc3RhcnQgb2YgdGhlIGFuaW1hdGlvbi4gKi9cblx0YW5pbWF0aW9uU3RhcnQgPSAwO1xuXG5cdC8qKiBUaGUgdGltZSBpbiBzZWNvbmRzIGZvciB0aGUgbGFzdCBmcmFtZSBvZiB0aGlzIGFuaW1hdGlvbi4gUGFzdCB0aGlzIHRpbWUsIG5vbi1sb29waW5nIGFuaW1hdGlvbnMgaG9sZCB0aGUgcG9zZSBhdCB0aGlzXG5cdCAqIHRpbWUgd2hpbGUgbG9vcGluZyBhbmltYXRpb25zIHdpbGwgbG9vcCBiYWNrIHRvIHtAbGluayBhbmltYXRpb25TdGFydH0uIERlZmF1bHRzIHRvIHRoZSB7QGxpbmsgQW5pbWF0aW9uLmR1cmF0aW9ufS4gKi9cblx0YW5pbWF0aW9uRW5kID0gMDtcblxuXG5cdC8qKiBUaGUgdGltZSBpbiBzZWNvbmRzIHRoaXMgYW5pbWF0aW9uIHdhcyBsYXN0IGFwcGxpZWQuIFNvbWUgdGltZWxpbmVzIHVzZSB0aGlzIGZvciBvbmUtdGltZSB0cmlnZ2Vycy4gRm9yIGV4YW1wbGUsIHdoZW5cblx0ICogdGhpcyBhbmltYXRpb24gaXMgYXBwbGllZCwgZXZlbnQgdGltZWxpbmVzIHdpbGwgZmlyZSBhbGwgZXZlbnRzIGJldHdlZW4gdGhlIGBhbmltYXRpb25MYXN0YCB0aW1lIChleGNsdXNpdmUpXG5cdCAqIGFuZCBgYW5pbWF0aW9uVGltZWAgKGluY2x1c2l2ZSkuIERlZmF1bHRzIHRvIC0xIHRvIGVuc3VyZSB0cmlnZ2VycyBvbiBmcmFtZSAwIGhhcHBlbiB0aGUgZmlyc3QgdGltZSB0aGlzXG5cdCAqIGFuaW1hdGlvbiBpcyBhcHBsaWVkLiAqL1xuXHRhbmltYXRpb25MYXN0ID0gMDtcblxuXHRuZXh0QW5pbWF0aW9uTGFzdCA9IDA7XG5cblx0LyoqIFNlY29uZHMgdG8gcG9zdHBvbmUgcGxheWluZyB0aGUgYW5pbWF0aW9uLiBNdXN0IGJlID49IDAuIFdoZW4gdGhpcyB0cmFjayBlbnRyeSBpcyB0aGUgY3VycmVudCB0cmFjayBlbnRyeSxcblx0ICogYGRlbGF5YCBwb3N0cG9uZXMgaW5jcmVtZW50aW5nIHRoZSB7QGxpbmsgdHJhY2tUaW1lfS4gV2hlbiB0aGlzIHRyYWNrIGVudHJ5IGlzIHF1ZXVlZCwgYGRlbGF5YCBpc1xuXHQgKiB0aGUgdGltZSBmcm9tIHRoZSBzdGFydCBvZiB0aGUgcHJldmlvdXMgYW5pbWF0aW9uIHRvIHdoZW4gdGhpcyB0cmFjayBlbnRyeSB3aWxsIGJlY29tZSB0aGUgY3VycmVudCB0cmFjayBlbnRyeSAoaWUgd2hlblxuXHQgKiB0aGUgcHJldmlvdXMgdHJhY2sgZW50cnkge0BsaW5rIHRyYWNrVGltZX0gPj0gdGhpcyB0cmFjayBlbnRyeSdzIGBkZWxheWApLlxuXHQgKlxuXHQgKiB7QGxpbmsgdGltZVNjYWxlfSBhZmZlY3RzIHRoZSBkZWxheS5cblx0ICpcblx0ICogV2hlbiBwYXNzaW5nIGBkZWxheWAgPD0gMCB0byB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYWRkQW5pbWF0aW9ufSB0aGlzXG5cdCAqIGBkZWxheWAgaXMgc2V0IHVzaW5nIGEgbWl4IGR1cmF0aW9uIGZyb20ge0BsaW5rIEFuaW1hdGlvblN0YXRlRGF0YX0uIFRvIGNoYW5nZSB0aGUge0BsaW5rIG1peER1cmF0aW9ufVxuXHQgKiBhZnRlcndhcmQsIHVzZSB7QGxpbmsgc2V0TWl4RHVyYXRpb259IHNvIHRoaXMgYGRlbGF5YCBpcyBhZGp1c3RlZC4gKi9cblx0ZGVsYXkgPSAwO1xuXG5cdC8qKiBUaGUgdGltZSBpbiBzZWNvbmRzIHRoaXMgdHJhY2sgZW50cnkgaGFzIGJlZW4gdGhlIGN1cnJlbnQgdHJhY2sgZW50cnksIHN0YXJ0aW5nIGF0IDAgYW5kIGluY3JlYXNpbmcgZm9yZXZlci4gQ29tcGFyZSB0b1xuXHQgKiB7QGxpbmsgZ2V0QW5pbWF0aW9uVGltZX0sIHdoaWNoIGlzIGFsd2F5cyBiZXR3ZWVuIHtAbGluayBhbmltYXRpb25TdGFydH0gYW5kIHtAbGluayBhbmltYXRpb25FbmR9LlxuXHQgKlxuXHQgKiBUaGUgdHJhY2sgdGltZSBjYW4gYmUgc2V0IHRvIHN0YXJ0IHRoZSBhbmltYXRpb24gYXQgYSB0aW1lIG90aGVyIHRoYW4gMCwgd2l0aG91dCBhZmZlY3RpbmcgbG9vcGluZy4gV2hlbiBkb2luZyBzbyxcblx0ICoge0BsaW5rIGFuaW1hdGlvbkxhc3R9IGNhbiBiZSBzZXQgdG8gdGhlIHNhbWUgdmFsdWUgdG8gYXZvaWQgZmlyaW5nIGV2ZW50cyBmcm9tIHRoZSBzdGFydCBvZiB0aGUgYW5pbWF0aW9uLlxuXHQgKlxuXHQgKiBUbyBzZXQgdGhlIHRpbWUgYW4gYW5pbWF0aW9uIHN0YXJ0cyBhbmQgbG9vcHMsIHVzZSB7QGxpbmsgYW5pbWF0aW9uU3RhcnR9IGFuZCB7QGxpbmsgYW5pbWF0aW9uRW5kfS4gKi9cblx0dHJhY2tUaW1lID0gMDtcblxuXHR0cmFja0xhc3QgPSAwOyBuZXh0VHJhY2tMYXN0ID0gMDtcblxuXHQvKiogVGhlIHRyYWNrIHRpbWUgaW4gc2Vjb25kcyB3aGVuIHRoaXMgYW5pbWF0aW9uIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSB0cmFjay4gRGVmYXVsdHMgdG8gdGhlIGhpZ2hlc3QgcG9zc2libGUgZmxvYXRcblx0ICogdmFsdWUsIG1lYW5pbmcgdGhlIGFuaW1hdGlvbiB3aWxsIGJlIGFwcGxpZWQgdW50aWwgYSBuZXcgYW5pbWF0aW9uIGlzIHNldCBvciB0aGUgdHJhY2sgaXMgY2xlYXJlZC4gSWYgdGhlIHRyYWNrIGVuZCB0aW1lXG5cdCAqIGlzIHJlYWNoZWQsIG5vIG90aGVyIGFuaW1hdGlvbnMgYXJlIHF1ZXVlZCBmb3IgcGxheWJhY2ssIGFuZCBtaXhpbmcgZnJvbSBhbnkgcHJldmlvdXMgYW5pbWF0aW9ucyBpcyBjb21wbGV0ZSwgdGhlbiB0aGVcblx0ICogcHJvcGVydGllcyBrZXllZCBieSB0aGUgYW5pbWF0aW9uIGFyZSBzZXQgdG8gdGhlIHNldHVwIHBvc2UgYW5kIHRoZSB0cmFjayBpcyBjbGVhcmVkLlxuXHQgKlxuXHQgKiBVc3VhbGx5IHlvdSB3YW50IHRvIHVzZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYWRkRW1wdHlBbmltYXRpb259IHJhdGhlciB0aGFuIGhhdmUgdGhlIGFuaW1hdGlvblxuXHQgKiBhYnJ1cHRseSBjZWFzZSBiZWluZyBhcHBsaWVkLCBsZWF2aW5nIHRoZSBjdXJyZW50IHBvc2UuICovXG5cdHRyYWNrRW5kID0gMDtcblxuXHQvKiogTXVsdGlwbGllciBmb3IgdGhlIGRlbHRhIHRpbWUgd2hlbiB0aGlzIHRyYWNrIGVudHJ5IGlzIHVwZGF0ZWQsIGNhdXNpbmcgdGltZSBmb3IgdGhpcyBhbmltYXRpb24gdG8gcGFzcyBzbG93ZXIgb3Jcblx0ICogZmFzdGVyLiBEZWZhdWx0cyB0byAxLlxuXHQgKlxuXHQgKiBWYWx1ZXMgPCAwIGFyZSBub3Qgc3VwcG9ydGVkLiBUbyBwbGF5IGFuIGFuaW1hdGlvbiBpbiByZXZlcnNlLCB1c2Uge0BsaW5rIHJldmVyc2V9LlxuXHQgKlxuXHQgKiB7QGxpbmsgbWl4VGltZX0gaXMgbm90IGFmZmVjdGVkIGJ5IHRyYWNrIGVudHJ5IHRpbWUgc2NhbGUsIHNvIHtAbGluayBtaXhEdXJhdGlvbn0gbWF5IG5lZWQgdG8gYmUgYWRqdXN0ZWQgdG8gbWF0Y2ggdGhlXG5cdCAqIGFuaW1hdGlvbiBzcGVlZC5cblx0ICpcblx0ICogV2hlbiB1c2luZyB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYWRkQW5pbWF0aW9ufSB3aXRoIGEgYGRlbGF5YCA8PSAwLCB0aGVcblx0ICoge0BsaW5rIGRlbGF5fSBpcyBzZXQgdXNpbmcgdGhlIG1peCBkdXJhdGlvbiBmcm9tIHtAbGluayBBbmltYXRpb25TdGF0ZS5kYXRhfSwgYXNzdW1pbmcgdGltZSBzY2FsZSB0byBiZSAxLiBJZiB0aGUgdGltZVxuXHQgKiBzY2FsZSBpcyBub3QgMSwgdGhlIGRlbGF5IG1heSBuZWVkIHRvIGJlIGFkanVzdGVkLlxuXHQgKlxuXHQgKiBTZWUge0BsaW5rIEFuaW1hdGlvblN0YXRlLnRpbWVTY2FsZX0gdG8gYWZmZWN0IGFsbCBhbmltYXRpb25zLiAqL1xuXHR0aW1lU2NhbGUgPSAwO1xuXG5cdC8qKiBWYWx1ZXMgPCAxIG1peCB0aGlzIGFuaW1hdGlvbiB3aXRoIHRoZSBza2VsZXRvbidzIGN1cnJlbnQgcG9zZSAoZWl0aGVyIHRoZSBzZXR1cCBwb3NlIG9yIHRoZSBwb3NlIGZyb20gbG93ZXIgdHJhY2tzKS5cblx0ICogRGVmYXVsdHMgdG8gMSwgd2hpY2ggb3ZlcndyaXRlcyB0aGUgc2tlbGV0b24ncyBjdXJyZW50IHBvc2Ugd2l0aCB0aGlzIGFuaW1hdGlvbi5cblx0ICpcblx0ICogQWxwaGEgc2hvdWxkIGJlIDEgb24gdHJhY2sgMC5cblx0ICpcblx0ICogU2VlIHtAbGluayBnZXRBbHBoYUF0dGFjaG1lbnRUaHJlc2hvbGR9LiAqL1xuXHRhbHBoYSA9IDA7XG5cblx0LyoqIFNlY29uZHMgZWxhcHNlZCBmcm9tIDAgdG8gdGhlIHtAbGluayBtaXhEdXJhdGlvbn0gd2hlbiBtaXhpbmcgZnJvbSB0aGUgcHJldmlvdXMgYW5pbWF0aW9uIHRvIHRoaXMgYW5pbWF0aW9uLiBNYXlcblx0ICogYmUgc2xpZ2h0bHkgbW9yZSB0aGFuIGBtaXhEdXJhdGlvbmAgd2hlbiB0aGUgbWl4IGlzIGNvbXBsZXRlLiAqL1xuXHRtaXhUaW1lID0gMDtcblxuXHQvKiogU2Vjb25kcyBmb3IgbWl4aW5nIGZyb20gdGhlIHByZXZpb3VzIGFuaW1hdGlvbiB0byB0aGlzIGFuaW1hdGlvbi4gRGVmYXVsdHMgdG8gdGhlIHZhbHVlIHByb3ZpZGVkIGJ5XG5cdCAqIHtAbGluayBBbmltYXRpb25TdGF0ZURhdGEuZ2V0TWl4fSBiYXNlZCBvbiB0aGUgYW5pbWF0aW9uIGJlZm9yZSB0aGlzIGFuaW1hdGlvbiAoaWYgYW55KS5cblx0ICpcblx0ICogQSBtaXggZHVyYXRpb24gb2YgMCBzdGlsbCBuZWVkcyB0byBiZSBhcHBsaWVkIG9uZSBtb3JlIHRpbWUgdG8gbWl4IG91dCwgc28gdGhlIHRoZSBwcm9wZXJ0aWVzIGl0IHdhcyBhbmltYXRpbmcgYXJlXG5cdCAqIHJldmVydGVkLiBBIG1peCBkdXJhdGlvbiBvZiAwIGNhbiBiZSBzZXQgYXQgYW55IHRpbWUgdG8gZW5kIHRoZSBtaXggb24gdGhlIG5leHRcblx0ICoge0BsaW5rIEFuaW1hdGlvblN0YXRlLnVwZGF0ZSB8IHVwZGF0ZX0uXG5cdCAqXG5cdCAqIFRoZSBgbWl4RHVyYXRpb25gIGNhbiBiZSBzZXQgbWFudWFsbHkgcmF0aGVyIHRoYW4gdXNlIHRoZSB2YWx1ZSBmcm9tXG5cdCAqIHtAbGluayBBbmltYXRpb25TdGF0ZURhdGEuZ2V0TWl4fS4gSW4gdGhhdCBjYXNlLCB0aGUgYG1peER1cmF0aW9uYCBjYW4gYmUgc2V0IGZvciBhIG5ld1xuXHQgKiB0cmFjayBlbnRyeSBvbmx5IGJlZm9yZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGUudXBkYXRlfSBpcyBuZXh0IGNhbGxlZC5cblx0ICpcblx0ICogV2hlbiB1c2luZyB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYWRkQW5pbWF0aW9ufSB3aXRoIGEgYGRlbGF5YCA8PSAwLCB0aGVcblx0ICoge0BsaW5rIGdldERlbGF5fSBpcyBzZXQgdXNpbmcgdGhlIG1peCBkdXJhdGlvbiBmcm9tIHtAbGluayBBbmltYXRpb25TdGF0ZS5kYXRhfS4gSWYgYG1peER1cmF0aW9uYCBpcyBzZXRcblx0ICogYWZ0ZXJ3YXJkLCB0aGUgZGVsYXkgbmVlZHMgdG8gYmUgYWRqdXN0ZWQ6XG5cdCAqXG5cdCAqIDxwcmU+XG5cdCAqIGVudHJ5Lm1peER1cmF0aW9uID0gMC4yNTs8YnI+XG5cdCAqIGVudHJ5LmRlbGF5ID0gZW50cnkucHJldmlvdXMuZ2V0VHJhY2tDb21wbGV0ZSgpIC0gZW50cnkubWl4RHVyYXRpb24gKyAwO1xuXHQgKiA8L3ByZT5cblx0ICpcblx0ICogQWx0ZXJuYXRpdmVseSwgdXNlIHtAbGluayBzZXRNaXhEdXJhdGlvbn0gdG8gc2V0IGJvdGggdGhlIG1peCBkdXJhdGlvbiBhbmQgcmVjb21wdXRlIHRoZSBkZWxheTo8YnI+XG5cdCAqXG5cdCAqIDxwcmU+XG5cdCAgZW50cnkuc2V0TWl4RHVyYXRpb24oMC4yNWYsIDApOyAvLyBtaXhEdXJhdGlvbiwgZGVsYXlcblx0ICogPC9wcmU+XG5cdCAqL1xuXHRtaXhEdXJhdGlvbiA9IDA7XG5cblx0dG90YWxBbHBoYSA9IDA7XG5cblx0bWl4SW50ZXJwb2xhdGlvbjogSW50ZXJwb2xhdGlvbiA9IEludGVycG9sYXRpb24ubGluZWFyO1xuXG5cdC8qKiBTZXRzIGJvdGgge0BsaW5rIGdldE1peER1cmF0aW9ufSBhbmQge0BsaW5rIGdldERlbGF5fS5cblx0ICogQHBhcmFtIGRlbGF5IElmID4gMCwgc2V0cyB7QGxpbmsgZ2V0RGVsYXl9LiBJZiA8PSAwLCB0aGUgZGVsYXkgc2V0IGlzIHRoZSBkdXJhdGlvbiBvZiB0aGUgcHJldmlvdXMgdHJhY2sgZW50cnkgbWludXNcblx0ICogICAgICAgICAgIHRoZSBzcGVjaWZpZWQgbWl4IGR1cmF0aW9uIHBsdXMgdGhlIHNwZWNpZmllZCBgZGVsYXlgIChpZSB0aGUgbWl4IGVuZHMgYXQgKHdoZW4gYGRlbGF5YCA9XG5cdCAqICAgICAgICAgICAwKSBvciBiZWZvcmUgKHdoZW4gYGRlbGF5YCA8IDApIHRoZSBwcmV2aW91cyB0cmFjayBlbnRyeSBkdXJhdGlvbikuIElmIHRoZSBwcmV2aW91cyBlbnRyeSBpc1xuXHQgKiAgICAgICAgICAgbG9vcGluZywgaXRzIG5leHQgbG9vcCBjb21wbGV0aW9uIGlzIHVzZWQgaW5zdGVhZCBvZiBpdHMgZHVyYXRpb24uICovXG5cdHNldE1peER1cmF0aW9uIChtaXhEdXJhdGlvbjogbnVtYmVyLCBkZWxheT86IG51bWJlcikge1xuXHRcdHRoaXMubWl4RHVyYXRpb24gPSBtaXhEdXJhdGlvbjtcblx0XHRpZiAoZGVsYXkgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0aWYgKGRlbGF5IDw9IDApIGRlbGF5ID0gdGhpcy5wcmV2aW91cyA9PSBudWxsID8gMCA6IE1hdGgubWF4KGRlbGF5ICsgdGhpcy5wcmV2aW91cy5nZXRUcmFja0NvbXBsZXRlKCkgLSBtaXhEdXJhdGlvbiwgMCk7XG5cdFx0XHR0aGlzLmRlbGF5ID0gZGVsYXk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIFRoZSBpbnRlcnBvbGF0aW9uIHRvIGFwcGx5IHRvIHRoZSBtaXggcGVyY2VudGFnZSAoe0BsaW5rIG1peFRpbWV9IC8ge0BsaW5rIG1peER1cmF0aW9ufSkgd2hlbiBtaXhpbmcgZnJvbSB0aGUgcHJldmlvdXNcblx0ICogYW5pbWF0aW9uIHRvIHRoaXMgYW5pbWF0aW9uLiBEZWZhdWx0cyB0byBsaW5lYXIuICovXG5cdHNldE1peEludGVycG9sYXRpb24gKG1peEludGVycG9sYXRpb246IEludGVycG9sYXRpb24pIHtcblx0XHRpZiAoIW1peEludGVycG9sYXRpb24pIHRocm93IG5ldyBFcnJvcihcIm1peEludGVycG9sYXRpb24gY2Fubm90IGJlIG51bGwuXCIpO1xuXHRcdHRoaXMubWl4SW50ZXJwb2xhdGlvbiA9IG1peEludGVycG9sYXRpb247XG5cdH1cblxuXHRtaXggKCk6IG51bWJlciB7XG5cdFx0aWYgKHRoaXMubWl4RHVyYXRpb24gPT09IDApIHJldHVybiAxO1xuXHRcdGxldCBtaXggPSB0aGlzLm1peFRpbWUgLyB0aGlzLm1peER1cmF0aW9uO1xuXHRcdGlmIChtaXggPj0gMSkgcmV0dXJuIDE7XG5cdFx0aWYgKHRoaXMubWl4SW50ZXJwb2xhdGlvbiA9PT0gSW50ZXJwb2xhdGlvbi5saW5lYXIpIHJldHVybiBtaXg7XG5cdFx0bWl4ID0gdGhpcy5taXhJbnRlcnBvbGF0aW9uLmFwcGx5KG1peCk7XG5cdFx0aWYgKG1peCA8IDApIHJldHVybiAwO1xuXHRcdGlmIChtaXggPiAxKSByZXR1cm4gMTtcblx0XHRyZXR1cm4gbWl4O1xuXHR9XG5cblx0LyoqIEZvciBlYWNoIHRpbWVsaW5lOlxuXHQgKiAtIEJpdHMgMC0xOiBNaXhGcm9tLlxuXHQgKiAtIEJpdCAyLCBIT0xEOiAwID0gbWl4IG91dCB1c2luZyBhbHBoYU1peCwgMSA9IGFwcGx5IGZ1bGwgYWxwaGEgdG8gcHJldmVudCBkaXBwaW5nLiBUaW1lbGluZSBpcyBmaXJzdCBvbiBpdHMgdHJhY2sgdG9cblx0ICogc2V0IHRoZSBwcm9wZXJ0eSBhbmQgdGhlIG5leHQgZW50cnkgKG1peGluZ1RvKSBhbHNvIHNldHMgaXQuIFdoZW4gaGVsZCwgdGltZWxpbmVIb2xkTWl4J3MgbWl4IGNvbnRyb2xzIGhvdyB0aGUgaG9sZCBmYWRlc1xuXHQgKiBvdXQgKGZvciAzKyBlbnRyeSBjaGFpbnMgd2hlcmUgdGhlIGNoYWluIGV2ZW50dWFsbHkgc3RvcHMgc2V0dGluZyB0aGUgcHJvcGVydHkpLiAqL1xuXHR0aW1lbGluZU1vZGUgPSBbXSBhcyBudW1iZXJbXTtcblx0dGltZWxpbmVIb2xkTWl4ID0gW10gYXMgVHJhY2tFbnRyeVtdO1xuXHR0aW1lbGluZXNSb3RhdGlvbiA9IFtdIGFzIG51bWJlcltdO1xuXG5cdHJlc2V0ICgpIHtcblx0XHR0aGlzLm5leHQgPSBudWxsO1xuXHRcdHRoaXMucHJldmlvdXMgPSBudWxsO1xuXHRcdHRoaXMubWl4aW5nRnJvbSA9IG51bGw7XG5cdFx0dGhpcy5taXhpbmdUbyA9IG51bGw7XG5cdFx0dGhpcy5taXhJbnRlcnBvbGF0aW9uID0gSW50ZXJwb2xhdGlvbi5saW5lYXI7XG5cdFx0dGhpcy5hbmltYXRpb24gPSBudWxsO1xuXHRcdHRoaXMubGlzdGVuZXIgPSBudWxsO1xuXHRcdHRoaXMudGltZWxpbmVNb2RlLmxlbmd0aCA9IDA7XG5cdFx0dGhpcy50aW1lbGluZUhvbGRNaXgubGVuZ3RoID0gMDtcblx0XHR0aGlzLnRpbWVsaW5lc1JvdGF0aW9uLmxlbmd0aCA9IDA7XG5cdH1cblxuXHQvKiogVXNlcyB7QGxpbmsgdHJhY2tUaW1lfSB0byBjb21wdXRlIHRoZSBgYW5pbWF0aW9uVGltZWAsIHdoaWNoIGlzIGFsd2F5cyBiZXR3ZWVuIHtAbGluayBhbmltYXRpb25TdGFydH0gYW5kXG5cdCAqIHtAbGluayBhbmltYXRpb25FbmR9LiBXaGVuIGB0cmFja1RpbWVgIGlzIDAsIGBhbmltYXRpb25UaW1lYCBpcyBlcXVhbCB0byB0aGVcblx0ICogYGFuaW1hdGlvblN0YXJ0YCB0aW1lLiAqL1xuXHRnZXRBbmltYXRpb25UaW1lICgpIHtcblx0XHRpZiAoIXRoaXMubG9vcCkgcmV0dXJuIE1hdGgubWluKHRoaXMudHJhY2tUaW1lICsgdGhpcy5hbmltYXRpb25TdGFydCwgdGhpcy5hbmltYXRpb25FbmQpO1xuXHRcdGNvbnN0IGR1cmF0aW9uID0gdGhpcy5hbmltYXRpb25FbmQgLSB0aGlzLmFuaW1hdGlvblN0YXJ0O1xuXHRcdGlmIChkdXJhdGlvbiA9PT0gMCkgcmV0dXJuIHRoaXMuYW5pbWF0aW9uU3RhcnQ7XG5cdFx0cmV0dXJuICh0aGlzLnRyYWNrVGltZSAlIGR1cmF0aW9uKSArIHRoaXMuYW5pbWF0aW9uU3RhcnQ7XG5cdH1cblxuXHRzZXRBbmltYXRpb25MYXN0IChhbmltYXRpb25MYXN0OiBudW1iZXIpIHtcblx0XHR0aGlzLmFuaW1hdGlvbkxhc3QgPSBhbmltYXRpb25MYXN0O1xuXHRcdHRoaXMubmV4dEFuaW1hdGlvbkxhc3QgPSBhbmltYXRpb25MYXN0O1xuXHR9XG5cblx0LyoqIFJldHVybnMgdHJ1ZSBpZiBhdCBsZWFzdCBvbmUgbG9vcCBoYXMgYmVlbiBjb21wbGV0ZWQuXG5cdCAqXG5cdCAqIFNlZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lci5jb21wbGV0ZX0uICovXG5cdGlzQ29tcGxldGUgKCkge1xuXHRcdHJldHVybiB0aGlzLnRyYWNrVGltZSA+PSB0aGlzLmFuaW1hdGlvbkVuZCAtIHRoaXMuYW5pbWF0aW9uU3RhcnQ7XG5cdH1cblxuXHQvKiogV2hlbiB7QGxpbmsgc2hvcnRlc3RSb3RhdGlvbn0gaXMgZmFsc2UsIHRoaXMgY2xlYXJzIHRoZSBkaXJlY3Rpb25zIGZvciBtaXhpbmcgdGhpcyBlbnRyeSdzIHJvdGF0aW9uLiBUaGlzIGNhbiBiZSB1c2VmdWxcblx0ICogdG8gYXZvaWQgYm9uZXMgcm90YXRpbmcgdGhlIGxvbmcgd2F5IGFyb3VuZCB3aGVuIHVzaW5nIHtAbGluayBnZXRBbHBoYX0gYW5kIHN0YXJ0aW5nIGFuaW1hdGlvbnMgb24gb3RoZXIgdHJhY2tzLlxuXHQgKlxuXHQgKiBNaXhpbmcgaW52b2x2ZXMgZmluZGluZyBhIHJvdGF0aW9uIGJldHdlZW4gdHdvIG90aGVycy4gVGhlcmUgYXJlIHR3byBwb3NzaWJsZSBzb2x1dGlvbnM6IHRoZSBzaG9ydCBvciB0aGUgbG9uZyB3YXlcblx0ICogYXJvdW5kLiBXaGVuIHRoZSB0d28gcm90YXRpb25zIGNoYW5nZSBvdmVyIHRpbWUsIHdoaWNoIGRpcmVjdGlvbiBpcyB0aGUgc2hvcnQgb3IgbG9uZyB3YXkgY2FuIGFsc28gY2hhbmdlLiBJZiB0aGUgc2hvcnRcblx0ICogd2F5IHdhcyBhbHdheXMgY2hvc2VuLCBib25lcyBmbGlwIHRvIHRoZSBvdGhlciBzaWRlIHdoZW4gdGhhdCBkaXJlY3Rpb24gYmVjYW1lIHRoZSBsb25nIHdheS4gVHJhY2tFbnRyeSBjaG9vc2VzIHRoZSBzaG9ydFxuXHQgKiB3YXkgdGhlIGZpcnN0IHRpbWUgaXQgaXMgYXBwbGllZCBhbmQgcmVtZW1iZXJzIHRoYXQgZGlyZWN0aW9uLiBSZXNldHRpbmcgdGhhdCBkaXJlY3Rpb24gbWFrZXMgaXQgY2hvb3NlIGEgbmV3IHNob3J0IHdheVxuXHQgKiBvbiB0aGUgbmV4dCBhcHBseS4gKi9cblx0cmVzZXRSb3RhdGlvbkRpcmVjdGlvbnMgKCkge1xuXHRcdHRoaXMudGltZWxpbmVzUm90YXRpb24ubGVuZ3RoID0gMDtcblx0fVxuXG5cdC8qKiBJZiB0aGlzIHRyYWNrIGVudHJ5IGlzIG5vbi1sb29waW5nLCB0aGlzIGlzIHRoZSB0cmFjayB0aW1lIGluIHNlY29uZHMgd2hlbiB7QGxpbmsgYW5pbWF0aW9uRW5kfSBpcyByZWFjaGVkLCBvciB0aGVcblx0ICogY3VycmVudCB7QGxpbmsgdHJhY2tUaW1lfSBpZiBpdCBoYXMgYWxyZWFkeSBiZWVuIHJlYWNoZWQuXG5cdCAqXG5cdCAqIElmIHRoaXMgdHJhY2sgZW50cnkgaXMgbG9vcGluZywgdGhpcyBpcyB0aGUgdHJhY2sgdGltZSB3aGVuIHRoaXMgYW5pbWF0aW9uIHdpbGwgcmVhY2ggaXRzIG5leHQge0BsaW5rIGFuaW1hdGlvbkVuZH0gKHRoZVxuXHQgKiBuZXh0IGxvb3AgY29tcGxldGlvbikuICovXG5cdGdldFRyYWNrQ29tcGxldGUgKCkge1xuXHRcdGNvbnN0IGR1cmF0aW9uID0gdGhpcy5hbmltYXRpb25FbmQgLSB0aGlzLmFuaW1hdGlvblN0YXJ0O1xuXHRcdGlmIChkdXJhdGlvbiAhPT0gMCkge1xuXHRcdFx0aWYgKHRoaXMubG9vcCkgcmV0dXJuIGR1cmF0aW9uICogKDEgKyAoKHRoaXMudHJhY2tUaW1lIC8gZHVyYXRpb24pIHwgMCkpOyAvLyBDb21wbGV0aW9uIG9mIG5leHQgbG9vcC5cblx0XHRcdGlmICh0aGlzLnRyYWNrVGltZSA8IGR1cmF0aW9uKSByZXR1cm4gZHVyYXRpb247IC8vIEJlZm9yZSBkdXJhdGlvbi5cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMudHJhY2tUaW1lOyAvLyBOZXh0IHVwZGF0ZS5cblx0fVxuXG5cdC8qKiBSZXR1cm5zIHRydWUgaWYgdGhpcyB0cmFjayBlbnRyeSBoYXMgYmVlbiBhcHBsaWVkIGF0IGxlYXN0IG9uY2UuXG5cdCAqXG5cdCAqIFNlZSB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYXBwbHl9LiAqL1xuXHR3YXNBcHBsaWVkICgpIHtcblx0XHRyZXR1cm4gdGhpcy5uZXh0VHJhY2tMYXN0ICE9PSAtMTtcblx0fVxuXG5cdC8qKiBSZXR1cm5zIHRydWUgaWYgdGhlcmUgaXMgYSB7QGxpbmsgbmV4dH0gdHJhY2sgZW50cnkgYW5kIGl0IHdpbGwgYmVjb21lIHRoZSBjdXJyZW50IHRyYWNrIGVudHJ5IGR1cmluZyB0aGUgbmV4dFxuXHQgKiB7QGxpbmsgQW5pbWF0aW9uU3RhdGUudXBkYXRlfS4gKi9cblx0aXNOZXh0UmVhZHkgKCkge1xuXHRcdHJldHVybiB0aGlzLm5leHQgIT0gbnVsbCAmJiB0aGlzLm5leHRUcmFja0xhc3QgLSB0aGlzLm5leHQuZGVsYXkgPj0gMDtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgRXZlbnRRdWV1ZSB7XG5cdG9iamVjdHM6IEFycmF5PEV2ZW50VHlwZSB8IFRyYWNrRW50cnkgfCBFdmVudD4gPSBbXTtcblx0ZHJhaW5EaXNhYmxlZCA9IGZhbHNlO1xuXHRhbmltU3RhdGU6IEFuaW1hdGlvblN0YXRlO1xuXG5cdGNvbnN0cnVjdG9yIChhbmltU3RhdGU6IEFuaW1hdGlvblN0YXRlKSB7XG5cdFx0dGhpcy5hbmltU3RhdGUgPSBhbmltU3RhdGU7XG5cdH1cblxuXHRzdGFydCAoZW50cnk6IFRyYWNrRW50cnkpIHtcblx0XHR0aGlzLm9iamVjdHMucHVzaChFdmVudFR5cGUuc3RhcnQpO1xuXHRcdHRoaXMub2JqZWN0cy5wdXNoKGVudHJ5KTtcblx0XHR0aGlzLmFuaW1TdGF0ZS5hbmltYXRpb25zQ2hhbmdlZCA9IHRydWU7XG5cdH1cblxuXHRpbnRlcnJ1cHQgKGVudHJ5OiBUcmFja0VudHJ5KSB7XG5cdFx0dGhpcy5vYmplY3RzLnB1c2goRXZlbnRUeXBlLmludGVycnVwdCk7XG5cdFx0dGhpcy5vYmplY3RzLnB1c2goZW50cnkpO1xuXHR9XG5cblx0ZW5kIChlbnRyeTogVHJhY2tFbnRyeSkge1xuXHRcdHRoaXMub2JqZWN0cy5wdXNoKEV2ZW50VHlwZS5lbmQpO1xuXHRcdHRoaXMub2JqZWN0cy5wdXNoKGVudHJ5KTtcblx0XHR0aGlzLmFuaW1TdGF0ZS5hbmltYXRpb25zQ2hhbmdlZCA9IHRydWU7XG5cdH1cblxuXHRkaXNwb3NlIChlbnRyeTogVHJhY2tFbnRyeSkge1xuXHRcdHRoaXMub2JqZWN0cy5wdXNoKEV2ZW50VHlwZS5kaXNwb3NlKTtcblx0XHR0aGlzLm9iamVjdHMucHVzaChlbnRyeSk7XG5cdH1cblxuXHRjb21wbGV0ZSAoZW50cnk6IFRyYWNrRW50cnkpIHtcblx0XHR0aGlzLm9iamVjdHMucHVzaChFdmVudFR5cGUuY29tcGxldGUpO1xuXHRcdHRoaXMub2JqZWN0cy5wdXNoKGVudHJ5KTtcblx0fVxuXG5cdGV2ZW50IChlbnRyeTogVHJhY2tFbnRyeSwgZXZlbnQ6IEV2ZW50KSB7XG5cdFx0dGhpcy5vYmplY3RzLnB1c2goRXZlbnRUeXBlLmV2ZW50KTtcblx0XHR0aGlzLm9iamVjdHMucHVzaChlbnRyeSk7XG5cdFx0dGhpcy5vYmplY3RzLnB1c2goZXZlbnQpO1xuXHR9XG5cblx0ZHJhaW4gKCkge1xuXHRcdGlmICh0aGlzLmRyYWluRGlzYWJsZWQpIHJldHVybjsgLy8gTm90IHJlZW50cmFudC5cblx0XHR0aGlzLmRyYWluRGlzYWJsZWQgPSB0cnVlO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm9iamVjdHMubGVuZ3RoOyBpICs9IDIpIHtcblx0XHRcdGNvbnN0IG9iamVjdHMgPSB0aGlzLm9iamVjdHM7XG5cdFx0XHRjb25zdCB0eXBlID0gb2JqZWN0c1tpXSBhcyBFdmVudFR5cGU7XG5cdFx0XHRjb25zdCBlbnRyeSA9IG9iamVjdHNbaSArIDFdIGFzIFRyYWNrRW50cnk7XG5cdFx0XHRjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLmFuaW1TdGF0ZS5saXN0ZW5lcnMuc2xpY2UoKTtcblx0XHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdFx0XHRjYXNlIEV2ZW50VHlwZS5zdGFydDpcblx0XHRcdFx0XHRpZiAoZW50cnkubGlzdGVuZXI/LnN0YXJ0KSBlbnRyeS5saXN0ZW5lci5zdGFydChlbnRyeSk7XG5cdFx0XHRcdFx0Zm9yIChsZXQgaWkgPSAwOyBpaSA8IGxpc3RlbmVycy5sZW5ndGg7IGlpKyspIHtcblx0XHRcdFx0XHRcdGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2lpXTtcblx0XHRcdFx0XHRcdGlmIChsaXN0ZW5lci5zdGFydCkgbGlzdGVuZXIuc3RhcnQoZW50cnkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBFdmVudFR5cGUuaW50ZXJydXB0OlxuXHRcdFx0XHRcdGlmIChlbnRyeS5saXN0ZW5lcj8uaW50ZXJydXB0KSBlbnRyeS5saXN0ZW5lci5pbnRlcnJ1cHQoZW50cnkpO1xuXHRcdFx0XHRcdGZvciAobGV0IGlpID0gMDsgaWkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpaSsrKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpaV07XG5cdFx0XHRcdFx0XHRpZiAobGlzdGVuZXIuaW50ZXJydXB0KSBsaXN0ZW5lci5pbnRlcnJ1cHQoZW50cnkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0ZhbGx0aHJvdWdoU3dpdGNoQ2xhdXNlOiByZWZlcmVuY2UgcnVudGltZSBkb2VzIGZhbGwgdGhyb3VnaFxuXHRcdFx0XHRjYXNlIEV2ZW50VHlwZS5lbmQ6XG5cdFx0XHRcdFx0aWYgKGVudHJ5Lmxpc3RlbmVyPy5lbmQpIGVudHJ5Lmxpc3RlbmVyLmVuZChlbnRyeSk7XG5cdFx0XHRcdFx0Zm9yIChsZXQgaWkgPSAwOyBpaSA8IGxpc3RlbmVycy5sZW5ndGg7IGlpKyspIHtcblx0XHRcdFx0XHRcdGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2lpXTtcblx0XHRcdFx0XHRcdGlmIChsaXN0ZW5lci5lbmQpIGxpc3RlbmVyLmVuZChlbnRyeSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHQvLyBGYWxsIHRocm91Z2guXG5cdFx0XHRcdGNhc2UgRXZlbnRUeXBlLmRpc3Bvc2U6XG5cdFx0XHRcdFx0aWYgKGVudHJ5Lmxpc3RlbmVyPy5kaXNwb3NlKSBlbnRyeS5saXN0ZW5lci5kaXNwb3NlKGVudHJ5KTtcblx0XHRcdFx0XHRmb3IgKGxldCBpaSA9IDA7IGlpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaWkrKykge1xuXHRcdFx0XHRcdFx0Y29uc3QgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaWldO1xuXHRcdFx0XHRcdFx0aWYgKGxpc3RlbmVyLmRpc3Bvc2UpIGxpc3RlbmVyLmRpc3Bvc2UoZW50cnkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0aGlzLmFuaW1TdGF0ZS50cmFja0VudHJ5UG9vbC5mcmVlKGVudHJ5KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBFdmVudFR5cGUuY29tcGxldGU6XG5cdFx0XHRcdFx0aWYgKGVudHJ5Lmxpc3RlbmVyPy5jb21wbGV0ZSkgZW50cnkubGlzdGVuZXIuY29tcGxldGUoZW50cnkpO1xuXHRcdFx0XHRcdGZvciAobGV0IGlpID0gMDsgaWkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpaSsrKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBsaXN0ZW5lciA9IGxpc3RlbmVyc1tpaV07XG5cdFx0XHRcdFx0XHRpZiAobGlzdGVuZXIuY29tcGxldGUpIGxpc3RlbmVyLmNvbXBsZXRlKGVudHJ5KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgRXZlbnRUeXBlLmV2ZW50OiB7XG5cdFx0XHRcdFx0Y29uc3QgZXZlbnQgPSBvYmplY3RzW2krKyArIDJdIGFzIEV2ZW50O1xuXHRcdFx0XHRcdGlmIChlbnRyeS5saXN0ZW5lcj8uZXZlbnQpIGVudHJ5Lmxpc3RlbmVyLmV2ZW50KGVudHJ5LCBldmVudCk7XG5cdFx0XHRcdFx0Zm9yIChsZXQgaWkgPSAwOyBpaSA8IGxpc3RlbmVycy5sZW5ndGg7IGlpKyspIHtcblx0XHRcdFx0XHRcdGNvbnN0IGxpc3RlbmVyID0gbGlzdGVuZXJzW2lpXTtcblx0XHRcdFx0XHRcdGlmIChsaXN0ZW5lci5ldmVudCkgbGlzdGVuZXIuZXZlbnQoZW50cnksIGV2ZW50KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0dGhpcy5jbGVhcigpO1xuXG5cdFx0dGhpcy5kcmFpbkRpc2FibGVkID0gZmFsc2U7XG5cdH1cblxuXHRjbGVhciAoKSB7XG5cdFx0dGhpcy5vYmplY3RzLmxlbmd0aCA9IDA7XG5cdH1cbn1cblxuZXhwb3J0IGVudW0gRXZlbnRUeXBlIHtcblx0c3RhcnQsIGludGVycnVwdCwgZW5kLCBkaXNwb3NlLCBjb21wbGV0ZSwgZXZlbnRcbn1cblxuLyoqIFRoZSBpbnRlcmZhY2UgdG8gaW1wbGVtZW50IGZvciByZWNlaXZpbmcgVHJhY2tFbnRyeSBldmVudHMuIEl0IGlzIGFsd2F5cyBzYWZlIHRvIGNhbGwgQW5pbWF0aW9uU3RhdGUgbWV0aG9kcyB3aGVuIHJlY2VpdmluZ1xuICogZXZlbnRzLlxuICpcbiAqIFRyYWNrRW50cnkgZXZlbnRzIGFyZSBjb2xsZWN0ZWQgZHVyaW5nIHtAbGluayBBbmltYXRpb25TdGF0ZS51cGRhdGV9IGFuZCB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYXBwbHl9IGFuZFxuICogZmlyZWQgb25seSBhZnRlciB0aG9zZSBtZXRob2RzIGFyZSBmaW5pc2hlZC5cbiAqXG4gKiBTZWUge0BsaW5rIFRyYWNrRW50cnkubGlzdGVuZXJ9IGFuZFxuICoge0BsaW5rIEFuaW1hdGlvblN0YXRlLmFkZExpc3RlbmVyfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lciB7XG5cdC8qKiBJbnZva2VkIHdoZW4gdGhpcyBlbnRyeSBoYXMgYmVlbiBzZXQgYXMgdGhlIGN1cnJlbnQgZW50cnkuIHtAbGluayBlbmR9IHdpbGwgb2NjdXIgd2hlbiB0aGlzIGVudHJ5IHdpbGwgbm9cblx0ICogbG9uZ2VyIGJlIGFwcGxpZWQuXG5cdCAqXG5cdCAqIFdoZW4gdGhpcyBldmVudCBpcyB0cmlnZ2VyZWQgYnkgY2FsbGluZyB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuc2V0QW5pbWF0aW9ufSwgdGFrZSBjYXJlIG5vdCB0b1xuXHQgKiBjYWxsIHtAbGluayBBbmltYXRpb25TdGF0ZS51cGRhdGV9IHVudGlsIGFmdGVyIHRoZSBUcmFja0VudHJ5IGhhcyBiZWVuIGNvbmZpZ3VyZWQuICovXG5cdHN0YXJ0PzogKGVudHJ5OiBUcmFja0VudHJ5KSA9PiB2b2lkO1xuXG5cdC8qKiBJbnZva2VkIHdoZW4gYW5vdGhlciBlbnRyeSBoYXMgcmVwbGFjZWQgdGhpcyBlbnRyeSBhcyB0aGUgY3VycmVudCBlbnRyeS4gVGhpcyBlbnRyeSBtYXkgY29udGludWUgYmVpbmcgYXBwbGllZCBmb3Jcblx0ICogbWl4aW5nLiAqL1xuXHRpbnRlcnJ1cHQ/OiAoZW50cnk6IFRyYWNrRW50cnkpID0+IHZvaWQ7XG5cblx0LyoqIEludm9rZWQgd2hlbiB0aGlzIGVudHJ5IHdpbGwgbmV2ZXIgYmUgYXBwbGllZCBhZ2Fpbi4gVGhpcyBvbmx5IG9jY3VycyBpZiB0aGlzIGVudHJ5IGhhcyBwcmV2aW91c2x5IGJlZW4gc2V0IGFzIHRoZVxuXHQgKiBjdXJyZW50IGVudHJ5ICh7QGxpbmsgc3RhcnR9IHdhcyBpbnZva2VkKS4gKi9cblx0ZW5kPzogKGVudHJ5OiBUcmFja0VudHJ5KSA9PiB2b2lkO1xuXG5cdC8qKiBJbnZva2VkIHdoZW4gdGhpcyBlbnRyeSB3aWxsIGJlIGRpc3Bvc2VkLiBUaGlzIG1heSBvY2N1ciB3aXRob3V0IHRoZSBlbnRyeSBldmVyIGJlaW5nIHNldCBhcyB0aGUgY3VycmVudCBlbnRyeS5cblx0ICogUmVmZXJlbmNlcyB0byB0aGUgZW50cnkgc2hvdWxkIG5vdCBiZSBrZXB0IGFmdGVyIGRpc3Bvc2UgaXMgY2FsbGVkLCBhcyBpdCBtYXkgYmUgZGVzdHJveWVkIG9yIHJldXNlZC4gKi9cblx0ZGlzcG9zZT86IChlbnRyeTogVHJhY2tFbnRyeSkgPT4gdm9pZDtcblxuXHQvKiogSW52b2tlZCBldmVyeSB0aW1lIHRoaXMgZW50cnkncyBhbmltYXRpb24gY29tcGxldGVzIGEgbG9vcC4gVGhpcyBtYXkgb2NjdXIgZHVyaW5nIG1peGluZyAoYWZ0ZXJcblx0ICoge0BsaW5rIGludGVycnVwdH0pLlxuXHQgKlxuXHQgKiBJZiB0aGlzIGVudHJ5J3Mge0BsaW5rIFRyYWNrRW50cnkubWl4aW5nVG99IGlzIG5vdCBudWxsLCB0aGlzIGVudHJ5IGlzIG1peGluZyBvdXQgKGl0IGlzIG5vdCB0aGUgY3VycmVudCBlbnRyeSkuXG5cdCAqXG5cdCAqIEJlY2F1c2UgdGhpcyBldmVudCBpcyB0cmlnZ2VyZWQgYXQgdGhlIGVuZCBvZiB7QGxpbmsgQW5pbWF0aW9uU3RhdGUuYXBwbHl9LCBhbnkgYW5pbWF0aW9ucyBzZXQgaW4gcmVzcG9uc2UgdG9cblx0ICogdGhlIGV2ZW50IHdvbid0IGJlIGFwcGxpZWQgdW50aWwgdGhlIG5leHQgdGltZSB0aGUgQW5pbWF0aW9uU3RhdGUgaXMgYXBwbGllZC4gKi9cblx0Y29tcGxldGU/OiAoZW50cnk6IFRyYWNrRW50cnkpID0+IHZvaWQ7XG5cblx0LyoqIEludm9rZWQgd2hlbiB0aGlzIGVudHJ5J3MgYW5pbWF0aW9uIHRyaWdnZXJzIGFuIGV2ZW50LiAqL1xuXHRldmVudD86IChlbnRyeTogVHJhY2tFbnRyeSwgZXZlbnQ6IEV2ZW50KSA9PiB2b2lkO1xufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQW5pbWF0aW9uU3RhdGVBZGFwdGVyIGltcGxlbWVudHMgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lciB7XG5cdHN0YXJ0IChlbnRyeTogVHJhY2tFbnRyeSkge1xuXHR9XG5cblx0aW50ZXJydXB0IChlbnRyeTogVHJhY2tFbnRyeSkge1xuXHR9XG5cblx0ZW5kIChlbnRyeTogVHJhY2tFbnRyeSkge1xuXHR9XG5cblx0ZGlzcG9zZSAoZW50cnk6IFRyYWNrRW50cnkpIHtcblx0fVxuXG5cdGNvbXBsZXRlIChlbnRyeTogVHJhY2tFbnRyeSkge1xuXHR9XG5cblx0ZXZlbnQgKGVudHJ5OiBUcmFja0VudHJ5LCBldmVudDogRXZlbnQpIHtcblx0fVxufVxuXG5leHBvcnQgY29uc3QgQ1VSUkVOVCA9IDA7XG5leHBvcnQgY29uc3QgU0VUVVAgPSAxO1xuZXhwb3J0IGNvbnN0IEZJUlNUID0gMjtcbmV4cG9ydCBjb25zdCBNT0RFID0gMztcbmV4cG9ydCBjb25zdCBIT0xEID0gNDtcblxuZXhwb3J0IGNvbnN0IEFUVEFDSF9TRVRVUCA9IDE7XG5leHBvcnQgY29uc3QgQVRUQUNIX1JFVEFJTiA9IDI7XG4iXX0=
|