/****************************************************************************** * 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("", [], 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 Empty animations 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 * Empty animations 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 Empty animations 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: * *
     * entry.mixDuration = 0.25;
* entry.delay = entry.previous.getTrackComplete() - entry.mixDuration + 0; *
* * Alternatively, use {@link setMixDuration} to set both the mix duration and recompute the delay:
* *
      entry.setMixDuration(0.25f, 0); // mixDuration, delay
     * 
*/ 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=