UNPKG

resig.js

Version:

Universal reactive signal library with complete platform features: signals, animations, CRDTs, scheduling, DOM integration. Works identically across React, SolidJS, Svelte, Vue, and Qwik.

372 lines 29.9 kB
"use strict"; /** * Animation Composition System - Operadic Composition * Following category-theoretic principles for animation composition */ Object.defineProperty(exports, "__esModule", { value: true }); exports.repeat = exports.stagger = exports.timeline = exports.sequence = exports.parallel = void 0; const signal_1 = require("../core/signal"); const core_1 = require("./core"); // Parallel composition (Tensor product ⊗) const parallel = (anim1, anim2) => { const id = `parallel-${anim1.id}-${anim2.id}`; const duration = Math.max(anim1.duration, anim2.duration); // Combined state signal const stateSignal = (0, signal_1.signal)({ value: { ...anim1.from, ...anim2.from }, progress: 0, isComplete: false, startTime: 0, duration, elapsedTime: 0, }); const valueSignal = stateSignal.map((state) => state.value); const progressSignal = stateSignal.map((state) => state.progress); const isCompleteSignal = stateSignal.map((state) => state.isComplete); // Sync animations const syncAnimations = () => { const state1 = anim1.state.value(); const state2 = anim2.state.value(); const combinedProgress = Math.max(state1.progress, state2.progress); const combinedValue = { ...state1.value, ...state2.value }; const isComplete = state1.isComplete && state2.isComplete; stateSignal._set({ value: combinedValue, progress: combinedProgress, isComplete, startTime: Math.min(state1.startTime, state2.startTime), duration, elapsedTime: Math.max(state1.elapsedTime, state2.elapsedTime), }); }; // Subscribe to both animations anim1.state.subscribe(syncAnimations); anim2.state.subscribe(syncAnimations); const instance = { id, duration, from: { ...anim1.from, ...anim2.from }, to: { ...anim1.to, ...anim2.to }, interpolator: ((from, to, _t) => { // This is a simplified interpolator - in practice, you'd want more sophisticated handling return { ...from, ...to }; }), easing: anim1.easing, // Use first animation's easing state: stateSignal, value: valueSignal, progress: progressSignal, isComplete: isCompleteSignal, first: anim1, second: anim2, map: (f, newInterpolator) => { return (0, core_1.animation)(f(instance.from), f(instance.to), duration, newInterpolator, instance.easing); }, ease: (newEasing) => { return (0, exports.parallel)(anim1.ease(newEasing), anim2.ease(newEasing)); }, start: () => { anim1.start(); anim2.start(); }, pause: () => { anim1.pause(); anim2.pause(); }, resume: () => { anim1.resume(); anim2.resume(); }, stop: () => { anim1.stop(); anim2.stop(); }, seek: (progress) => { anim1.seek(progress); anim2.seek(progress); }, onComplete: (callback) => { return isCompleteSignal.subscribe((isComplete) => { if (isComplete) { callback(valueSignal.value()); } }); }, onUpdate: (callback) => { return stateSignal.subscribe(callback); }, }; return instance; }; exports.parallel = parallel; // Sequential composition (Free monoidal category →) const sequence = (first, second) => { const id = `sequence-${first.id}-${second.id}`; const duration = first.duration + second.duration; const phaseSignal = (0, signal_1.signal)('first'); const stateSignal = (0, signal_1.signal)({ value: first.from, progress: 0, isComplete: false, startTime: 0, duration, elapsedTime: 0, }); const valueSignal = stateSignal.map((state) => state.value); const progressSignal = stateSignal.map((state) => state.progress); const isCompleteSignal = stateSignal.map((state) => state.isComplete); let hasStartedSecond = false; // Handle phase transitions first.onComplete(() => { if (!hasStartedSecond) { hasStartedSecond = true; phaseSignal._set('second'); second.start(); } }); second.onComplete(() => { phaseSignal._set('complete'); }); // Update combined state const updateState = () => { const phase = phaseSignal.value(); const firstState = first.state.value(); const secondState = second.state.value(); let combinedProgress; let currentValue; let isComplete; if (phase === 'first') { combinedProgress = firstState.progress * 0.5; currentValue = firstState.value; isComplete = false; } else if (phase === 'second') { combinedProgress = 0.5 + secondState.progress * 0.5; currentValue = secondState.value; isComplete = secondState.isComplete; } else { combinedProgress = 1; currentValue = secondState.value; isComplete = true; } stateSignal._set({ value: currentValue, progress: combinedProgress, isComplete, startTime: firstState.startTime, duration, elapsedTime: firstState.elapsedTime + secondState.elapsedTime, }); }; first.state.subscribe(updateState); second.state.subscribe(updateState); phaseSignal.subscribe(updateState); const instance = { id, duration, from: first.from, to: second.to, interpolator: ((from, to, t) => { // Simplified interpolator for sequential animations return t < 0.5 ? from : to; }), easing: first.easing, state: stateSignal, value: valueSignal, progress: progressSignal, isComplete: isCompleteSignal, first, second, currentPhase: phaseSignal, map: (f, newInterpolator) => { return (0, core_1.animation)(f(instance.from), f(instance.to), duration, newInterpolator, instance.easing); }, ease: (newEasing) => { return (0, exports.sequence)(first.ease(newEasing), second.ease(newEasing)); }, start: () => { hasStartedSecond = false; phaseSignal._set('first'); first.start(); }, pause: () => { first.pause(); second.pause(); }, resume: () => { first.resume(); second.resume(); }, stop: () => { first.stop(); second.stop(); phaseSignal._set('first'); hasStartedSecond = false; }, seek: (progress) => { const clampedProgress = Math.max(0, Math.min(1, progress)); if (clampedProgress < 0.5) { // First animation phaseSignal._set('first'); first.seek(clampedProgress * 2); second.seek(0); hasStartedSecond = false; } else { // Second animation phaseSignal._set('second'); first.seek(1); second.seek((clampedProgress - 0.5) * 2); hasStartedSecond = true; } }, onComplete: (callback) => { return isCompleteSignal.subscribe((isComplete) => { if (isComplete) { callback(valueSignal.value()); } }); }, onUpdate: (callback) => { return stateSignal.subscribe(callback); }, }; return instance; }; exports.sequence = sequence; // Timeline implementation for coordinating multiple animations const timeline = () => { const id = `timeline-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; let animations = []; let duration = 0; const progressSignal = (0, signal_1.signal)(0); const isCompleteSignal = (0, signal_1.signal)(false); let startTime = 0; let isPaused = false; let animationFrameId = null; const updateTimeline = (currentTime) => { if (isPaused) return; const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); progressSignal._set(progress); // Update individual animations based on timeline progress animations.forEach(({ animation: anim, offset }) => { const animStart = offset; const animEnd = offset + anim.duration; if (elapsed >= animStart && elapsed <= animEnd) { const animProgress = (elapsed - animStart) / anim.duration; anim.seek(Math.max(0, Math.min(1, animProgress))); } else if (elapsed > animEnd) { anim.seek(1); } }); if (progress >= 1) { isCompleteSignal._set(true); } else { animationFrameId = requestAnimationFrame(updateTimeline); } }; const recalculateDuration = () => { duration = Math.max(...animations.map(({ animation: anim, offset }) => offset + anim.duration), 0); }; const instance = { id, get duration() { return duration; }, progress: progressSignal, isComplete: isCompleteSignal, get animations() { return [...animations]; }, add: (animation, offset = 0) => { animations.push({ animation, offset }); recalculateDuration(); return instance; }, remove: (animationId) => { animations = animations.filter(({ animation: anim }) => anim.id !== animationId); recalculateDuration(); return instance; }, start: () => { startTime = performance.now(); isPaused = false; progressSignal._set(0); isCompleteSignal._set(false); animationFrameId = requestAnimationFrame(updateTimeline); }, pause: () => { isPaused = true; if (animationFrameId) { cancelAnimationFrame(animationFrameId); animationFrameId = null; } animations.forEach(({ animation: anim }) => anim.pause()); }, resume: () => { if (isPaused) { const currentTime = performance.now(); const elapsed = progressSignal.value() * duration; startTime = currentTime - elapsed; isPaused = false; animationFrameId = requestAnimationFrame(updateTimeline); animations.forEach(({ animation: anim }) => anim.resume()); } }, stop: () => { isPaused = true; if (animationFrameId) { cancelAnimationFrame(animationFrameId); animationFrameId = null; } progressSignal._set(0); isCompleteSignal._set(false); animations.forEach(({ animation: anim }) => anim.stop()); }, seek: (progress) => { const clampedProgress = Math.max(0, Math.min(1, progress)); const elapsed = clampedProgress * duration; progressSignal._set(clampedProgress); animations.forEach(({ animation: anim, offset }) => { const animStart = offset; const animEnd = offset + anim.duration; if (elapsed >= animStart && elapsed <= animEnd) { const animProgress = (elapsed - animStart) / anim.duration; anim.seek(animProgress); } else if (elapsed > animEnd) { anim.seek(1); } else { anim.seek(0); } }); }, }; return instance; }; exports.timeline = timeline; // Utility functions for common composition patterns const stagger = (animations, staggerDelay) => { const tl = (0, exports.timeline)(); animations.forEach((anim, index) => { tl.add(anim, index * staggerDelay); }); return tl; }; exports.stagger = stagger; const repeat = (animation, count, delay = 0) => { const tl = (0, exports.timeline)(); for (let i = 0; i < count; i++) { // Create a copy of the animation for each repetition const animCopy = animation.map((v) => v, animation.interpolator); tl.add(animCopy, i * (animation.duration + delay)); } return tl; }; exports.repeat = repeat; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9zZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYW5pbWF0aW9uL2NvbXBvc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7OztBQUVILDJDQUFnRDtBQUNoRCxpQ0FNZ0I7QUFnQ2hCLDBDQUEwQztBQUNuQyxNQUFNLFFBQVEsR0FBRyxDQUN0QixLQUFtQixFQUNuQixLQUFtQixFQUNNLEVBQUU7SUFDM0IsTUFBTSxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsRUFBRSxJQUFJLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUM5QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRTFELHdCQUF3QjtJQUN4QixNQUFNLFdBQVcsR0FBRyxJQUFBLGVBQU0sRUFBd0I7UUFDaEQsS0FBSyxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBVztRQUNoRCxRQUFRLEVBQUUsQ0FBQztRQUNYLFVBQVUsRUFBRSxLQUFLO1FBQ2pCLFNBQVMsRUFBRSxDQUFDO1FBQ1osUUFBUTtRQUNSLFdBQVcsRUFBRSxDQUFDO0tBQ2YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVELE1BQU0sY0FBYyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNsRSxNQUFNLGdCQUFnQixHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUV0RSxrQkFBa0I7SUFDbEIsTUFBTSxjQUFjLEdBQUcsR0FBRyxFQUFFO1FBQzFCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkMsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVuQyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDcEUsTUFBTSxhQUFhLEdBQUcsRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFXLENBQUM7UUFDcEUsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsSUFBSSxNQUFNLENBQUMsVUFBVSxDQUFDO1FBRTFELFdBQVcsQ0FBQyxJQUFJLENBQUM7WUFDZixLQUFLLEVBQUUsYUFBYTtZQUNwQixRQUFRLEVBQUUsZ0JBQWdCO1lBQzFCLFVBQVU7WUFDVixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUM7WUFDdkQsUUFBUTtZQUNSLFdBQVcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQztTQUM5RCxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUM7SUFFRiwrQkFBK0I7SUFDL0IsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDdEMsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLENBQUM7SUFFdEMsTUFBTSxRQUFRLEdBQTRCO1FBQ3hDLEVBQUU7UUFDRixRQUFRO1FBQ1IsSUFBSSxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBVztRQUMvQyxFQUFFLEVBQUUsRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxFQUFXO1FBQ3pDLFlBQVksRUFBRSxDQUFDLENBQUMsSUFBVyxFQUFFLEVBQVMsRUFBRSxFQUFVLEVBQUUsRUFBRTtZQUNwRCwwRkFBMEY7WUFDMUYsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFXLENBQUM7UUFDckMsQ0FBQyxDQUF3QjtRQUN6QixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSwrQkFBK0I7UUFDckQsS0FBSyxFQUFFLFdBQVc7UUFDbEIsS0FBSyxFQUFFLFdBQVc7UUFDbEIsUUFBUSxFQUFFLGNBQWM7UUFDeEIsVUFBVSxFQUFFLGdCQUFnQjtRQUM1QixLQUFLLEVBQUUsS0FBSztRQUNaLE1BQU0sRUFBRSxLQUFLO1FBRWIsR0FBRyxFQUFFLENBQUksQ0FBc0IsRUFBRSxlQUFnQyxFQUFFLEVBQUU7WUFDbkUsT0FBTyxJQUFBLGdCQUFTLEVBQ2QsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFDaEIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsRUFDZCxRQUFRLEVBQ1IsZUFBZSxFQUNmLFFBQVEsQ0FBQyxNQUFNLENBQ2hCLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxFQUFFLENBQUMsU0FBeUIsRUFBRSxFQUFFO1lBQ2xDLE9BQU8sSUFBQSxnQkFBUSxFQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7UUFFRCxLQUFLLEVBQUUsR0FBRyxFQUFFO1lBQ1YsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2QsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2hCLENBQUM7UUFFRCxLQUFLLEVBQUUsR0FBRyxFQUFFO1lBQ1YsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2QsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2hCLENBQUM7UUFFRCxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ1gsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2YsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pCLENBQUM7UUFFRCxJQUFJLEVBQUUsR0FBRyxFQUFFO1lBQ1QsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2IsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2YsQ0FBQztRQUVELElBQUksRUFBRSxDQUFDLFFBQWdCLEVBQUUsRUFBRTtZQUN6QixLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3JCLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUVELFVBQVUsRUFBRSxDQUFDLFFBQWdDLEVBQUUsRUFBRTtZQUMvQyxPQUFPLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFO2dCQUMvQyxJQUFJLFVBQVUsRUFBRSxDQUFDO29CQUNmLFFBQVEsQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDaEMsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELFFBQVEsRUFBRSxDQUFDLFFBQWdELEVBQUUsRUFBRTtZQUM3RCxPQUFPLFdBQVcsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekMsQ0FBQztLQUNGLENBQUM7SUFFRixPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFsSFcsUUFBQSxRQUFRLFlBa0huQjtBQUVGLG9EQUFvRDtBQUM3QyxNQUFNLFFBQVEsR0FBRyxDQUN0QixLQUFtQixFQUNuQixNQUFvQixFQUNPLEVBQUU7SUFDN0IsTUFBTSxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsRUFBRSxJQUFJLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUMvQyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUM7SUFFbEQsTUFBTSxXQUFXLEdBQUcsSUFBQSxlQUFNLEVBQWtDLE9BQU8sQ0FBQyxDQUFDO0lBRXJFLE1BQU0sV0FBVyxHQUFHLElBQUEsZUFBTSxFQUF3QjtRQUNoRCxLQUFLLEVBQUUsS0FBSyxDQUFDLElBQUk7UUFDakIsUUFBUSxFQUFFLENBQUM7UUFDWCxVQUFVLEVBQUUsS0FBSztRQUNqQixTQUFTLEVBQUUsQ0FBQztRQUNaLFFBQVE7UUFDUixXQUFXLEVBQUUsQ0FBQztLQUNmLENBQUMsQ0FBQztJQUVILE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM1RCxNQUFNLGNBQWMsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEUsTUFBTSxnQkFBZ0IsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFFdEUsSUFBSSxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFFN0IsMkJBQTJCO0lBQzNCLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ3BCLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3RCLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUN4QixXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNyQixXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQy9CLENBQUMsQ0FBQyxDQUFDO0lBRUgsd0JBQXdCO0lBQ3hCLE1BQU0sV0FBVyxHQUFHLEdBQUcsRUFBRTtRQUN2QixNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbEMsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN2QyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRXpDLElBQUksZ0JBQXdCLENBQUM7UUFDN0IsSUFBSSxZQUFtQixDQUFDO1FBQ3hCLElBQUksVUFBbUIsQ0FBQztRQUV4QixJQUFJLEtBQUssS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUN0QixnQkFBZ0IsR0FBRyxVQUFVLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQztZQUM3QyxZQUFZLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQztZQUNoQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3JCLENBQUM7YUFBTSxJQUFJLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM5QixnQkFBZ0IsR0FBRyxHQUFHLEdBQUcsV0FBVyxDQUFDLFFBQVEsR0FBRyxHQUFHLENBQUM7WUFDcEQsWUFBWSxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDakMsVUFBVSxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUM7UUFDdEMsQ0FBQzthQUFNLENBQUM7WUFDTixnQkFBZ0IsR0FBRyxDQUFDLENBQUM7WUFDckIsWUFBWSxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDakMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUNwQixDQUFDO1FBRUQsV0FBVyxDQUFDLElBQUksQ0FBQztZQUNmLEtBQUssRUFBRSxZQUFZO1lBQ25CLFFBQVEsRUFBRSxnQkFBZ0I7WUFDMUIsVUFBVTtZQUNWLFNBQVMsRUFBRSxVQUFVLENBQUMsU0FBUztZQUMvQixRQUFRO1lBQ1IsV0FBVyxFQUFFLFVBQVUsQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDLFdBQVc7U0FDOUQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDO0lBRUYsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDbkMsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDcEMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUVuQyxNQUFNLFFBQVEsR0FBOEI7UUFDMUMsRUFBRTtRQUNGLFFBQVE7UUFDUixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7UUFDaEIsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFO1FBQ2IsWUFBWSxFQUFFLENBQUMsQ0FBQyxJQUFXLEVBQUUsRUFBUyxFQUFFLENBQVMsRUFBRSxFQUFFO1lBQ25ELG9EQUFvRDtZQUNwRCxPQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzdCLENBQUMsQ0FBd0I7UUFDekIsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQ3BCLEtBQUssRUFBRSxXQUFXO1FBQ2xCLEtBQUssRUFBRSxXQUFXO1FBQ2xCLFFBQVEsRUFBRSxjQUFjO1FBQ3hCLFVBQVUsRUFBRSxnQkFBZ0I7UUFDNUIsS0FBSztRQUNMLE1BQU07UUFDTixZQUFZLEVBQUUsV0FBVztRQUV6QixHQUFHLEVBQUUsQ0FBSSxDQUFzQixFQUFFLGVBQWdDLEVBQUUsRUFBRTtZQUNuRSxPQUFPLElBQUEsZ0JBQVMsRUFDZCxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUNoQixDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUNkLFFBQVEsRUFDUixlQUFlLEVBQ2YsUUFBUSxDQUFDLE1BQU0sQ0FDaEIsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLEVBQUUsQ0FBQyxTQUF5QixFQUFFLEVBQUU7WUFDbEMsT0FBTyxJQUFBLGdCQUFRLEVBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELEtBQUssRUFBRSxHQUFHLEVBQUU7WUFDVixnQkFBZ0IsR0FBRyxLQUFLLENBQUM7WUFDekIsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMxQixLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDaEIsQ0FBQztRQUVELEtBQUssRUFBRSxHQUFHLEVBQUU7WUFDVixLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDZCxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDakIsQ0FBQztRQUVELE1BQU0sRUFBRSxHQUFHLEVBQUU7WUFDWCxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbEIsQ0FBQztRQUVELElBQUksRUFBRSxHQUFHLEVBQUU7WUFDVCxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDYixNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDZCxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzFCLGdCQUFnQixHQUFHLEtBQUssQ0FBQztRQUMzQixDQUFDO1FBRUQsSUFBSSxFQUFFLENBQUMsUUFBZ0IsRUFBRSxFQUFFO1lBQ3pCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFFM0QsSUFBSSxlQUFlLEdBQUcsR0FBRyxFQUFFLENBQUM7Z0JBQzFCLGtCQUFrQjtnQkFDbEIsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDMUIsS0FBSyxDQUFDLElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2YsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO1lBQzNCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixtQkFBbUI7Z0JBQ25CLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQzNCLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2QsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLGVBQWUsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDekMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1lBQzFCLENBQUM7UUFDSCxDQUFDO1FBRUQsVUFBVSxFQUFFLENBQUMsUUFBZ0MsRUFBRSxFQUFFO1lBQy9DLE9BQU8sZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7Z0JBQy9DLElBQUksVUFBVSxFQUFFLENBQUM7b0JBQ2YsUUFBUSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQyxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsUUFBUSxFQUFFLENBQUMsUUFBZ0QsRUFBRSxFQUFFO1lBQzdELE9BQU8sV0FBVyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6QyxDQUFDO0tBQ0YsQ0FBQztJQUVGLE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQWxLVyxRQUFBLFFBQVEsWUFrS25CO0FBRUYsK0RBQStEO0FBQ3hELE1BQU0sUUFBUSxHQUFHLEdBQWEsRUFBRTtJQUNyQyxNQUFNLEVBQUUsR0FBRyxZQUFZLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUUvRSxJQUFJLFVBQVUsR0FBeUQsRUFBRSxDQUFDO0lBQzFFLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztJQUVqQixNQUFNLGNBQWMsR0FBRyxJQUFBLGVBQU0sRUFBQyxDQUFDLENBQUMsQ0FBQztJQUNqQyxNQUFNLGdCQUFnQixHQUFHLElBQUEsZUFBTSxFQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXZDLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztJQUNsQixJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDckIsSUFBSSxnQkFBZ0IsR0FBa0IsSUFBSSxDQUFDO0lBRTNDLE1BQU0sY0FBYyxHQUFHLENBQUMsV0FBbUIsRUFBRSxFQUFFO1FBQzdDLElBQUksUUFBUTtZQUFFLE9BQU87UUFFckIsTUFBTSxPQUFPLEdBQUcsV0FBVyxHQUFHLFNBQVMsQ0FBQztRQUN4QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sR0FBRyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFakQsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU5QiwwREFBMEQ7UUFDMUQsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFO1lBQ2pELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQztZQUN6QixNQUFNLE9BQU8sR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUV2QyxJQUFJLE9BQU8sSUFBSSxTQUFTLElBQUksT0FBTyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUMvQyxNQUFNLFlBQVksR0FBRyxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO2dCQUMzRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwRCxDQUFDO2lCQUFNLElBQUksT0FBTyxHQUFHLE9BQU8sRUFBRSxDQUFDO2dCQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDbEIsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzlCLENBQUM7YUFBTSxDQUFDO1lBQ04sZ0JBQWdCLEdBQUcscUJBQXFCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDM0QsQ0FBQztJQUNILENBQUMsQ0FBQztJQUVGLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxFQUFFO1FBQy9CLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUNqQixHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQ2YsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUN4RCxFQUNELENBQUMsQ0FDRixDQUFDO0lBQ0osQ0FBQyxDQUFDO0lBRUYsTUFBTSxRQUFRLEdBQWE7UUFDekIsRUFBRTtRQUNGLElBQUksUUFBUTtZQUNWLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLENBQUM7UUFDRCxRQUFRLEVBQUUsY0FBYztRQUN4QixVQUFVLEVBQUUsZ0JBQWdCO1FBQzVCLElBQUksVUFBVTtZQUNaLE9BQU8sQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFFRCxHQUFHLEVBQUUsQ0FBSSxTQUF1QixFQUFFLFNBQWlCLENBQUMsRUFBRSxFQUFFO1lBQ3RELFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUN2QyxtQkFBbUIsRUFBRSxDQUFDO1lBQ3RCLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLENBQUM7UUFFRCxNQUFNLEVBQUUsQ0FBQyxXQUFtQixFQUFFLEVBQUU7WUFDOUIsVUFBVSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQzVCLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssV0FBVyxDQUNqRCxDQUFDO1lBQ0YsbUJBQW1CLEVBQUUsQ0FBQztZQUN0QixPQUFPLFFBQVEsQ0FBQztRQUNsQixDQUFDO1FBRUQsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNWLFNBQVMsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDOUIsUUFBUSxHQUFHLEtBQUssQ0FBQztZQUNqQixjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3ZCLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QixnQkFBZ0IsR0FBRyxxQkFBcUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUMzRCxDQUFDO1FBRUQsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNWLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDaEIsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQixvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUN2QyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7WUFDMUIsQ0FBQztZQUNELFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDNUQsQ0FBQztRQUVELE1BQU0sRUFBRSxHQUFHLEVBQUU7WUFDWCxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNiLE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDdEMsTUFBTSxPQUFPLEdBQUcsY0FBYyxDQUFDLEtBQUssRUFBRSxHQUFHLFFBQVEsQ0FBQztnQkFDbEQsU0FBUyxHQUFHLFdBQVcsR0FBRyxPQUFPLENBQUM7Z0JBQ2xDLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQ2pCLGdCQUFnQixHQUFHLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUN6RCxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQzdELENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxFQUFFLEdBQUcsRUFBRTtZQUNULFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDaEIsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQixvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUN2QyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7WUFDMUIsQ0FBQztZQUNELGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkIsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzdCLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUVELElBQUksRUFBRSxDQUFDLFFBQWdCLEVBQUUsRUFBRTtZQUN6QixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQzNELE1BQU0sT0FBTyxHQUFHLGVBQWUsR0FBRyxRQUFRLENBQUM7WUFFM0MsY0FBYyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUVyQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7Z0JBQ2pELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQztnQkFDekIsTUFBTSxPQUFPLEdBQUcsTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7Z0JBRXZDLElBQUksT0FBTyxJQUFJLFNBQVMsSUFBSSxPQUFPLElBQUksT0FBTyxFQUFFLENBQUM7b0JBQy9DLE1BQU0sWUFBWSxHQUFHLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7b0JBQzNELElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQzFCLENBQUM7cUJBQU0sSUFBSSxPQUFPLEdBQUcsT0FBTyxFQUFFLENBQUM7b0JBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2YsQ0FBQztxQkFBTSxDQUFDO29CQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2YsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztLQUNGLENBQUM7SUFFRixPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUF6SVcsUUFBQSxRQUFRLFlBeUluQjtBQUVGLG9EQUFvRDtBQUM3QyxNQUFNLE9BQU8sR0FBRyxDQUNyQixVQUEwQixFQUMxQixZQUFvQixFQUNWLEVBQUU7SUFDWixNQUFNLEVBQUUsR0FBRyxJQUFBLGdCQUFRLEdBQUUsQ0FBQztJQUV0QixVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQ2pDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssR0FBRyxZQUFZLENBQUMsQ0FBQztJQUNyQyxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQyxDQUFDO0FBWFcsUUFBQSxPQUFPLFdBV2xCO0FBRUssTUFBTSxNQUFNLEdBQUcsQ0FDcEIsU0FBdUIsRUFDdkIsS0FBYSxFQUNiLFFBQWdCLENBQUMsRUFDUCxFQUFFO0lBQ1osTUFBTSxFQUFFLEdBQUcsSUFBQSxnQkFBUSxHQUFFLENBQUM7SUFFdEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQy9CLHFEQUFxRDtRQUNyRCxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2pFLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDLENBQUM7QUFkVyxRQUFBLE1BQU0sVUFjakIifQ==