cacophony 0.20.6 → 0.20.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +356 -356
- package/dist/index.mjs.map +1 -1
- package/docs/classes/AudioCache.html +6 -6
- package/docs/classes/Cacophony.html +13 -13
- package/docs/classes/Group.html +12 -12
- package/docs/classes/MicrophonePlayback.html +3 -3
- package/docs/classes/Playback.html +31 -31
- package/docs/classes/Sound.html +18 -18
- package/docs/classes/Synth.html +15 -15
- package/docs/classes/SynthGroup.html +2 -2
- package/docs/enums/SoundType.html +2 -2
- package/docs/interfaces/AudioBuffer.html +2 -2
- package/docs/interfaces/AudioBufferSourceNode.html +4 -4
- package/docs/interfaces/AudioEventCallbacks.html +2 -2
- package/docs/interfaces/AudioListener.html +2 -2
- package/docs/interfaces/AudioNode.html +3 -3
- package/docs/interfaces/AudioParam.html +2 -2
- package/docs/interfaces/AudioWorkletNode.html +3 -3
- package/docs/interfaces/BaseAudioEvents.html +2 -2
- package/docs/interfaces/BaseContext.html +2 -2
- package/docs/interfaces/BaseSound.html +2 -2
- package/docs/interfaces/BiquadFilterNode.html +4 -4
- package/docs/interfaces/CacheErrorEvent.html +2 -2
- package/docs/interfaces/CacheHitEvent.html +2 -2
- package/docs/interfaces/CacheMissEvent.html +2 -2
- package/docs/interfaces/CacophonyEvents.html +2 -2
- package/docs/interfaces/ChannelMergerNode.html +3 -3
- package/docs/interfaces/ChannelSplitterNode.html +3 -3
- package/docs/interfaces/FadeStartEvent.html +2 -2
- package/docs/interfaces/GainNode.html +3 -3
- package/docs/interfaces/GlobalPlaybackEvent.html +2 -2
- package/docs/interfaces/LoadingCompleteEvent.html +2 -2
- package/docs/interfaces/LoadingErrorEvent.html +2 -2
- package/docs/interfaces/LoadingProgressEvent.html +2 -2
- package/docs/interfaces/LoadingStartEvent.html +2 -2
- package/docs/interfaces/MediaElementSourceNode.html +3 -3
- package/docs/interfaces/MediaStreamAudioSourceNode.html +3 -3
- package/docs/interfaces/OfflineOptions.html +2 -2
- package/docs/interfaces/OscillatorNode.html +4 -4
- package/docs/interfaces/PannerNode.html +3 -3
- package/docs/interfaces/PlayOptions.html +2 -2
- package/docs/interfaces/PlaybackErrorEvent.html +2 -2
- package/docs/interfaces/PlaybackEvents.html +2 -2
- package/docs/interfaces/RuntimeOptions.html +2 -2
- package/docs/interfaces/SoundCleanupHoldings.html +2 -2
- package/docs/interfaces/SoundErrorEvent.html +2 -2
- package/docs/interfaces/SoundEvents.html +2 -2
- package/docs/interfaces/StereoPannerNode.html +3 -3
- package/docs/interfaces/SynthEvents.html +2 -2
- package/docs/types/CacheEventCallback.html +1 -1
- package/docs/types/ErrorEventCallback.html +1 -1
- package/docs/types/FadeType.html +1 -1
- package/docs/types/LoadingEventCallback.html +1 -1
- package/docs/types/LoopCount.html +1 -1
- package/docs/types/Orientation.html +1 -1
- package/docs/types/PanType.html +1 -1
- package/docs/types/Position.html +1 -1
- package/docs/types/SourceNode.html +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class R{maxSize;cache;constructor(e){this.maxSize=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;const t=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,t),t}set(e,t){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.maxSize){const g=this.cache.keys().next().value;g!==void 0&&this.cache.delete(g)}this.cache.set(e,t)}has(e){return this.cache.has(e)}}const W=100;function Y(A){if(!A)return null;const e=A.match(/max-age\s*=\s*"?(\d+)"?/i);return e?parseInt(e[1],10):null}function E(A){return A?/(?:^|,)\s*(no-cache|no-store|must-revalidate)\s*(?:,|$)/i.test(A):!1}function k(A){return A instanceof DOMException&&A.name==="AbortError"?"abort":A instanceof Error?"network":"unknown"}class r{static pendingRequests=new Map;static pendingCallbacks=new Map;static decodedBuffers=new R(W);static cacheExpirationTime=1440*60*1e3;static setCacheExpirationTime(e){r.cacheExpirationTime=e}static async openCache(){try{return await caches.open("audio-cache")}catch(e){throw console.error("Failed to open cache:",e),e}}static callAllCallbacks(e,t,g){const s=r.pendingCallbacks.get(e);s&&s.forEach(o=>{const I=o[t];if(I)try{I(g)}catch(n){console.error(`Error in ${t} callback:`,n)}})}static async getOrCreatePendingRequest(e,t,g,s){if(g?.aborted)throw new DOMException("Operation was aborted","AbortError");if(s){const I=r.pendingCallbacks.get(e)||[];I.push(s),r.pendingCallbacks.set(e,I)}const o=r.pendingRequests.get(e);if(!o){const I=(async()=>{try{const n=await t();if(n===void 0)throw new Error("Failed to create audio buffer.");return n}finally{r.pendingRequests.delete(e),r.pendingCallbacks.delete(e)}})();return g?.addEventListener("abort",()=>{g.aborted&&(r.pendingRequests.delete(e),r.pendingCallbacks.delete(e))},{once:!0}),r.pendingRequests.set(e,I),I}return o}static async updateMetadata(e,t,g){const s={url:t,timestamp:Date.now(),...g};await e.put(`${t}:meta`,new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json"}}))}static async getBufferFromCache(e,t){try{const g=await t.match(e);return g?.ok?await g.arrayBuffer():null}catch(g){return console.error("Failed to get data from cache:",g),null}}static async fetchAndCacheBuffer(e,t,g,s,o,I){const n=new Headers;g&&n.append("If-None-Match",g),s&&n.append("If-Modified-Since",s),console.debug(`[AudioCache] Fetching ${e}`,{headers:Object.fromEntries(n.entries()),hasEtag:!!g,hasLastModified:!!s});const i=await fetch(e,{headers:n,signal:o});if(console.debug(`[AudioCache] Response ${e}`,{status:i.status,statusText:i.statusText,etag:i.headers?.get("ETag"),lastModified:i.headers?.get("Last-Modified"),cacheControl:i.headers?.get("Cache-Control")}),i.status===304){const C=await t.match(e);if(C){I?.onCacheHit&&I.onCacheHit({url:e,cacheType:"conditional",timestamp:Date.now()});const a=Date.now(),c=i.headers?.get("Cache-Control");return await r.updateMetadata(t,e,{timestamp:a,etag:g,lastModified:s,...c?{cacheControl:c}:{}}),await C.arrayBuffer()}else{console.warn(`Cache inconsistency detected for ${e}: 304 response but no cached body. Re-fetching.`);const a=await fetch(e,{signal:o});if(a.status===200){const c=a.clone(),h=a.headers.get("ETag"),p=a.headers.get("Last-Modified"),m=a.headers.get("Cache-Control");try{await Promise.all([t.put(e,c),r.updateMetadata(t,e,{timestamp:Date.now(),etag:h||void 0,lastModified:p||void 0,cacheControl:m||void 0})])}catch(d){throw await t.delete(e),await t.delete(`${e}:meta`),d}if(a.body){const{stream:d,total:S}=r.createProgressTrackingStream(a,e);return await r.collectStreamToArrayBuffer(d,S||void 0)}else return await a.arrayBuffer()}else throw new Error(`Failed to fetch resource after cache inconsistency: ${a.status} ${a.statusText}`)}}if(i.status===200){const C=i.clone(),a=i.headers.get("ETag"),c=i.headers.get("Last-Modified"),h=i.headers.get("Cache-Control");try{await Promise.all([t.put(e,C),r.updateMetadata(t,e,{timestamp:Date.now(),etag:a||void 0,lastModified:c||void 0,cacheControl:h||void 0})])}catch(p){throw await t.delete(e),await t.delete(`${e}:meta`),p}}if(o?.aborted)throw new DOMException("Operation was aborted","AbortError");if(i.body){const{stream:C,total:a}=r.createProgressTrackingStream(i,e);return await r.collectStreamToArrayBuffer(C,a||void 0)}else return await i.arrayBuffer()}static createProgressTrackingStream(e,t){const g=e.headers.get("content-length"),s=g?parseInt(g,10):null;let o=0;if(!e.body)throw new Error("Response body is null");const I=e.body.getReader();return{stream:new ReadableStream({start(i){function C(){return I.read().then(({done:a,value:c})=>{if(a){r.callAllCallbacks(t,"onLoadingProgress",{url:t,loaded:o,total:s,progress:s?1:-1,timestamp:Date.now()}),i.close();return}if(c){o+=c.byteLength;const h=s?o/s:-1;r.callAllCallbacks(t,"onLoadingProgress",{url:t,loaded:o,total:s,progress:h,timestamp:Date.now()}),i.enqueue(c)}return C()}).catch(a=>{i.error(a)})}return C()},cancel(i){return I.cancel(i)}}),total:s}}static async collectStreamToArrayBuffer(e,t){const g=e.getReader();try{if(t!==void 0&&t>0){const s=new ArrayBuffer(t),o=new Uint8Array(s);let I=0;for(;;){const{done:n,value:i}=await g.read();if(n)break;i&&(o.set(i,I),I+=i.byteLength)}return s}else{let s=new Uint8Array(8192),o=0;for(;;){const{done:I,value:n}=await g.read();if(I)break;if(n){if(o+n.byteLength>s.length){const i=Math.max(s.length*2,o+n.byteLength),C=new Uint8Array(i);C.set(s.subarray(0,o)),s=C}s.set(n,o),o+=n.byteLength}}return s.slice(0,o).buffer}}finally{g.releaseLock()}}static async decodeAudioData(e,t){try{return await e.decodeAudioData(t)}catch(g){throw console.error("Failed to decode audio data:",g),g}}static async getMetadataFromCache(e,t){try{const g=await t.match(`${e}:meta`);return g?.ok?await g.json():null}catch(g){return console.error("Failed to get metadata from cache:",g),null}}async getAudioBuffer(e,t,g,s){if(s?.onLoadingStart&&s.onLoadingStart({url:t,timestamp:Date.now()}),r.decodedBuffers.has(t))return s?.onCacheHit&&s.onCacheHit({url:t,cacheType:"memory",timestamp:Date.now()}),r.decodedBuffers.get(t);if(t.startsWith("data:")){const i=t.split(",")[1],C=Uint8Array.from(atob(i),c=>c.charCodeAt(0)).buffer,a=await r.decodeAudioData(e,C);return r.decodedBuffers.set(t,a),a}const o=await r.openCache(),I=await r.getMetadataFromCache(t,o),n=(()=>{if(!I||E(I.cacheControl))return!0;const i=Y(I.cacheControl);if(i!==null){const C=(Date.now()-I.timestamp)/1e3;if(i>0&&C<i)return!1}return I.etag||I.lastModified?!0:Date.now()-I.timestamp>r.cacheExpirationTime})();return r.getOrCreatePendingRequest(t,async()=>{if(n){s?.onCacheMiss&&s.onCacheMiss({url:t,reason:I?"expired":"not-found",timestamp:Date.now()});try{const i=await r.fetchAndCacheBuffer(t,o,I?.etag,I?.lastModified,g,{onCacheHit:s?.onCacheHit});let C;try{C=await r.decodeAudioData(e,i)}catch(a){throw s?.onLoadingError&&s.onLoadingError({url:t,error:a,errorType:"decode",timestamp:Date.now()}),a}return s?.onLoadingComplete&&s.onLoadingComplete({url:t,duration:C.duration,size:i.byteLength,timestamp:Date.now()}),r.decodedBuffers.set(t,C),C}catch(i){throw s?.onLoadingError&&s.onLoadingError({url:t,error:i,errorType:k(i),timestamp:Date.now()}),s?.onCacheError&&s.onCacheError({url:t,error:i,operation:"get",timestamp:Date.now()}),i}}else{const i=await r.getBufferFromCache(t,o);if(i){s?.onCacheHit&&s.onCacheHit({url:t,cacheType:"browser",timestamp:Date.now()});const C=await r.decodeAudioData(e,i);return r.decodedBuffers.set(t,C),C}else{s?.onCacheError&&s.onCacheError({url:t,error:new Error("Cache inconsistency: metadata exists but body is missing"),operation:"get",timestamp:Date.now()});try{const C=await r.fetchAndCacheBuffer(t,o,I?.etag,I?.lastModified,g,{onCacheHit:s?.onCacheHit});let a;try{a=await r.decodeAudioData(e,C)}catch(c){throw s?.onLoadingError&&s.onLoadingError({url:t,error:c,errorType:"decode",timestamp:Date.now()}),c}return s?.onLoadingComplete&&s.onLoadingComplete({url:t,duration:a.duration,size:C.byteLength,timestamp:Date.now()}),r.decodedBuffers.set(t,a),a}catch(C){throw s?.onLoadingError&&s.onLoadingError({url:t,error:C,errorType:k(C),timestamp:Date.now()}),C}}}},g,{onLoadingProgress:s?.onLoadingProgress})}clearMemoryCache(){r.decodedBuffers=new R(W),r.pendingRequests.clear()}}const D="data:text/javascript;base64,dmFyIHBoYXNlVm9jb2RlciA9IChmdW5jdGlvbiAoZXhwb3J0cykgewoJJ3VzZSBzdHJpY3QnOwoKCWZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzICh4KSB7CgkJcmV0dXJuIHggJiYgeC5fX2VzTW9kdWxlICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh4LCAnZGVmYXVsdCcpID8geFsnZGVmYXVsdCddIDogeDsKCX0KCglmdW5jdGlvbiBGRlQoc2l6ZSkgewoJICB0aGlzLnNpemUgPSBzaXplIHwgMDsKCSAgaWYgKHRoaXMuc2l6ZSA8PSAxIHx8ICh0aGlzLnNpemUgJiAodGhpcy5zaXplIC0gMSkpICE9PSAwKQoJICAgIHRocm93IG5ldyBFcnJvcignRkZUIHNpemUgbXVzdCBiZSBhIHBvd2VyIG9mIHR3byBhbmQgYmlnZ2VyIHRoYW4gMScpOwoKCSAgdGhpcy5fY3NpemUgPSBzaXplIDw8IDE7CgoJICAvLyBOT1RFOiBVc2Ugb2YgYHZhcmAgaXMgaW50ZW50aW9uYWwgZm9yIG9sZCBWOCB2ZXJzaW9ucwoJICB2YXIgdGFibGUgPSBuZXcgQXJyYXkodGhpcy5zaXplICogMik7CgkgIGZvciAodmFyIGkgPSAwOyBpIDwgdGFibGUubGVuZ3RoOyBpICs9IDIpIHsKCSAgICBjb25zdCBhbmdsZSA9IE1hdGguUEkgKiBpIC8gdGhpcy5zaXplOwoJICAgIHRhYmxlW2ldID0gTWF0aC5jb3MoYW5nbGUpOwoJICAgIHRhYmxlW2kgKyAxXSA9IC1NYXRoLnNpbihhbmdsZSk7CgkgIH0KCSAgdGhpcy50YWJsZSA9IHRhYmxlOwoKCSAgLy8gRmluZCBzaXplJ3MgcG93ZXIgb2YgdHdvCgkgIHZhciBwb3dlciA9IDA7CgkgIGZvciAodmFyIHQgPSAxOyB0aGlzLnNpemUgPiB0OyB0IDw8PSAxKQoJICAgIHBvd2VyKys7CgoJICAvLyBDYWxjdWxhdGUgaW5pdGlhbCBzdGVwJ3Mgd2lkdGg6CgkgIC8vICAgKiBJZiB3ZSBhcmUgZnVsbCByYWRpeC00IC0gaXQgaXMgMnggc21hbGxlciB0byBnaXZlIGluaXRhbCBsZW49OAoJICAvLyAgICogT3RoZXJ3aXNlIGl0IGlzIHRoZSBzYW1lIGFzIGBwb3dlcmAgdG8gZ2l2ZSBsZW49NAoJICB0aGlzLl93aWR0aCA9IHBvd2VyICUgMiA9PT0gMCA/IHBvd2VyIC0gMSA6IHBvd2VyOwoKCSAgLy8gUHJlLWNvbXB1dGUgYml0LXJldmVyc2FsIHBhdHRlcm5zCgkgIHRoaXMuX2JpdHJldiA9IG5ldyBBcnJheSgxIDw8IHRoaXMuX3dpZHRoKTsKCSAgZm9yICh2YXIgaiA9IDA7IGogPCB0aGlzLl9iaXRyZXYubGVuZ3RoOyBqKyspIHsKCSAgICB0aGlzLl9iaXRyZXZbal0gPSAwOwoJICAgIGZvciAodmFyIHNoaWZ0ID0gMDsgc2hpZnQgPCB0aGlzLl93aWR0aDsgc2hpZnQgKz0gMikgewoJICAgICAgdmFyIHJldlNoaWZ0ID0gdGhpcy5fd2lkdGggLSBzaGlmdCAtIDI7CgkgICAgICB0aGlzLl9iaXRyZXZbal0gfD0gKChqID4+PiBzaGlmdCkgJiAzKSA8PCByZXZTaGlmdDsKCSAgICB9CgkgIH0KCgkgIHRoaXMuX291dCA9IG51bGw7CgkgIHRoaXMuX2RhdGEgPSBudWxsOwoJICB0aGlzLl9pbnYgPSAwOwoJfQoJdmFyIGZmdCA9IEZGVDsKCglGRlQucHJvdG90eXBlLmZyb21Db21wbGV4QXJyYXkgPSBmdW5jdGlvbiBmcm9tQ29tcGxleEFycmF5KGNvbXBsZXgsIHN0b3JhZ2UpIHsKCSAgdmFyIHJlcyA9IHN0b3JhZ2UgfHwgbmV3IEFycmF5KGNvbXBsZXgubGVuZ3RoID4+PiAxKTsKCSAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb21wbGV4Lmxlbmd0aDsgaSArPSAyKQoJICAgIHJlc1tpID4+PiAxXSA9IGNvbXBsZXhbaV07CgkgIHJldHVybiByZXM7Cgl9OwoKCUZGVC5wcm90b3R5cGUuY3JlYXRlQ29tcGxleEFycmF5ID0gZnVuY3Rpb24gY3JlYXRlQ29tcGxleEFycmF5KCkgewoJICBjb25zdCByZXMgPSBuZXcgQXJyYXkodGhpcy5fY3NpemUpOwoJICBmb3IgKHZhciBpID0gMDsgaSA8IHJlcy5sZW5ndGg7IGkrKykKCSAgICByZXNbaV0gPSAwOwoJICByZXR1cm4gcmVzOwoJfTsKCglGRlQucHJvdG90eXBlLnRvQ29tcGxleEFycmF5ID0gZnVuY3Rpb24gdG9Db21wbGV4QXJyYXkoaW5wdXQsIHN0b3JhZ2UpIHsKCSAgdmFyIHJlcyA9IHN0b3JhZ2UgfHwgdGhpcy5jcmVhdGVDb21wbGV4QXJyYXkoKTsKCSAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMubGVuZ3RoOyBpICs9IDIpIHsKCSAgICByZXNbaV0gPSBpbnB1dFtpID4+PiAxXTsKCSAgICByZXNbaSArIDFdID0gMDsKCSAgfQoJICByZXR1cm4gcmVzOwoJfTsKCglGRlQucHJvdG90eXBlLmNvbXBsZXRlU3BlY3RydW0gPSBmdW5jdGlvbiBjb21wbGV0ZVNwZWN0cnVtKHNwZWN0cnVtKSB7CgkgIHZhciBzaXplID0gdGhpcy5fY3NpemU7CgkgIHZhciBoYWxmID0gc2l6ZSA+Pj4gMTsKCSAgZm9yICh2YXIgaSA9IDI7IGkgPCBoYWxmOyBpICs9IDIpIHsKCSAgICBzcGVjdHJ1bVtzaXplIC0gaV0gPSBzcGVjdHJ1bVtpXTsKCSAgICBzcGVjdHJ1bVtzaXplIC0gaSArIDFdID0gLXNwZWN0cnVtW2kgKyAxXTsKCSAgfQoJfTsKCglGRlQucHJvdG90eXBlLnRyYW5zZm9ybSA9IGZ1bmN0aW9uIHRyYW5zZm9ybShvdXQsIGRhdGEpIHsKCSAgaWYgKG91dCA9PT0gZGF0YSkKCSAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBtdXN0IGJlIGRpZmZlcmVudCcpOwoKCSAgdGhpcy5fb3V0ID0gb3V0OwoJICB0aGlzLl9kYXRhID0gZGF0YTsKCSAgdGhpcy5faW52ID0gMDsKCSAgdGhpcy5fdHJhbnNmb3JtNCgpOwoJICB0aGlzLl9vdXQgPSBudWxsOwoJICB0aGlzLl9kYXRhID0gbnVsbDsKCX07CgoJRkZULnByb3RvdHlwZS5yZWFsVHJhbnNmb3JtID0gZnVuY3Rpb24gcmVhbFRyYW5zZm9ybShvdXQsIGRhdGEpIHsKCSAgaWYgKG91dCA9PT0gZGF0YSkKCSAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBtdXN0IGJlIGRpZmZlcmVudCcpOwoKCSAgdGhpcy5fb3V0ID0gb3V0OwoJICB0aGlzLl9kYXRhID0gZGF0YTsKCSAgdGhpcy5faW52ID0gMDsKCSAgdGhpcy5fcmVhbFRyYW5zZm9ybTQoKTsKCSAgdGhpcy5fb3V0ID0gbnVsbDsKCSAgdGhpcy5fZGF0YSA9IG51bGw7Cgl9OwoKCUZGVC5wcm90b3R5cGUuaW52ZXJzZVRyYW5zZm9ybSA9IGZ1bmN0aW9uIGludmVyc2VUcmFuc2Zvcm0ob3V0LCBkYXRhKSB7CgkgIGlmIChvdXQgPT09IGRhdGEpCgkgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMgbXVzdCBiZSBkaWZmZXJlbnQnKTsKCgkgIHRoaXMuX291dCA9IG91dDsKCSAgdGhpcy5fZGF0YSA9IGRhdGE7CgkgIHRoaXMuX2ludiA9IDE7CgkgIHRoaXMuX3RyYW5zZm9ybTQoKTsKCSAgZm9yICh2YXIgaSA9IDA7IGkgPCBvdXQubGVuZ3RoOyBpKyspCgkgICAgb3V0W2ldIC89IHRoaXMuc2l6ZTsKCSAgdGhpcy5fb3V0ID0gbnVsbDsKCSAgdGhpcy5fZGF0YSA9IG51bGw7Cgl9OwoKCS8vIHJhZGl4LTQgaW1wbGVtZW50YXRpb24KCS8vCgkvLyBOT1RFOiBVc2VzIG9mIGB2YXJgIGFyZSBpbnRlbnRpb25hbCBmb3Igb2xkZXIgVjggdmVyc2lvbiB0aGF0IGRvIG5vdAoJLy8gc3VwcG9ydCBib3RoIGBsZXQgY29tcG91bmQgYXNzaWdubWVudHNgIGFuZCBgY29uc3QgcGhpYAoJRkZULnByb3RvdHlwZS5fdHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF90cmFuc2Zvcm00KCkgewoJICB2YXIgb3V0ID0gdGhpcy5fb3V0OwoJICB2YXIgc2l6ZSA9IHRoaXMuX2NzaXplOwoKCSAgLy8gSW5pdGlhbCBzdGVwIChwZXJtdXRlIGFuZCB0cmFuc2Zvcm0pCgkgIHZhciB3aWR0aCA9IHRoaXMuX3dpZHRoOwoJICB2YXIgc3RlcCA9IDEgPDwgd2lkdGg7CgkgIHZhciBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CgoJICB2YXIgb3V0T2ZmOwoJICB2YXIgdDsKCSAgdmFyIGJpdHJldiA9IHRoaXMuX2JpdHJldjsKCSAgaWYgKGxlbiA9PT0gNCkgewoJICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewoJICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwoJICAgICAgdGhpcy5fc2luZ2xlVHJhbnNmb3JtMihvdXRPZmYsIG9mZiwgc3RlcCk7CgkgICAgfQoJICB9IGVsc2UgewoJICAgIC8vIGxlbiA9PT0gOAoJICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewoJICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwoJICAgICAgdGhpcy5fc2luZ2xlVHJhbnNmb3JtNChvdXRPZmYsIG9mZiwgc3RlcCk7CgkgICAgfQoJICB9CgoJICAvLyBMb29wIHRocm91Z2ggc3RlcHMgaW4gZGVjcmVhc2luZyBvcmRlcgoJICB2YXIgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwoJICB2YXIgdGFibGUgPSB0aGlzLnRhYmxlOwoJICBmb3IgKHN0ZXAgPj49IDI7IHN0ZXAgPj0gMjsgc3RlcCA+Pj0gMikgewoJICAgIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCSAgICB2YXIgcXVhcnRlckxlbiA9IGxlbiA+Pj4gMjsKCgkgICAgLy8gTG9vcCB0aHJvdWdoIG9mZnNldHMgaW4gdGhlIGRhdGEKCSAgICBmb3IgKG91dE9mZiA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4pIHsKCSAgICAgIC8vIEZ1bGwgY2FzZQoJICAgICAgdmFyIGxpbWl0ID0gb3V0T2ZmICsgcXVhcnRlckxlbjsKCSAgICAgIGZvciAodmFyIGkgPSBvdXRPZmYsIGsgPSAwOyBpIDwgbGltaXQ7IGkgKz0gMiwgayArPSBzdGVwKSB7CgkgICAgICAgIGNvbnN0IEEgPSBpOwoJICAgICAgICBjb25zdCBCID0gQSArIHF1YXJ0ZXJMZW47CgkgICAgICAgIGNvbnN0IEMgPSBCICsgcXVhcnRlckxlbjsKCSAgICAgICAgY29uc3QgRCA9IEMgKyBxdWFydGVyTGVuOwoKCSAgICAgICAgLy8gT3JpZ2luYWwgdmFsdWVzCgkgICAgICAgIGNvbnN0IEFyID0gb3V0W0FdOwoJICAgICAgICBjb25zdCBBaSA9IG91dFtBICsgMV07CgkgICAgICAgIGNvbnN0IEJyID0gb3V0W0JdOwoJICAgICAgICBjb25zdCBCaSA9IG91dFtCICsgMV07CgkgICAgICAgIGNvbnN0IENyID0gb3V0W0NdOwoJICAgICAgICBjb25zdCBDaSA9IG91dFtDICsgMV07CgkgICAgICAgIGNvbnN0IERyID0gb3V0W0RdOwoJICAgICAgICBjb25zdCBEaSA9IG91dFtEICsgMV07CgoJICAgICAgICAvLyBNaWRkbGUgdmFsdWVzCgkgICAgICAgIGNvbnN0IE1BciA9IEFyOwoJICAgICAgICBjb25zdCBNQWkgPSBBaTsKCgkgICAgICAgIGNvbnN0IHRhYmxlQnIgPSB0YWJsZVtrXTsKCSAgICAgICAgY29uc3QgdGFibGVCaSA9IGludiAqIHRhYmxlW2sgKyAxXTsKCSAgICAgICAgY29uc3QgTUJyID0gQnIgKiB0YWJsZUJyIC0gQmkgKiB0YWJsZUJpOwoJICAgICAgICBjb25zdCBNQmkgPSBCciAqIHRhYmxlQmkgKyBCaSAqIHRhYmxlQnI7CgoJICAgICAgICBjb25zdCB0YWJsZUNyID0gdGFibGVbMiAqIGtdOwoJICAgICAgICBjb25zdCB0YWJsZUNpID0gaW52ICogdGFibGVbMiAqIGsgKyAxXTsKCSAgICAgICAgY29uc3QgTUNyID0gQ3IgKiB0YWJsZUNyIC0gQ2kgKiB0YWJsZUNpOwoJICAgICAgICBjb25zdCBNQ2kgPSBDciAqIHRhYmxlQ2kgKyBDaSAqIHRhYmxlQ3I7CgoJICAgICAgICBjb25zdCB0YWJsZURyID0gdGFibGVbMyAqIGtdOwoJICAgICAgICBjb25zdCB0YWJsZURpID0gaW52ICogdGFibGVbMyAqIGsgKyAxXTsKCSAgICAgICAgY29uc3QgTURyID0gRHIgKiB0YWJsZURyIC0gRGkgKiB0YWJsZURpOwoJICAgICAgICBjb25zdCBNRGkgPSBEciAqIHRhYmxlRGkgKyBEaSAqIHRhYmxlRHI7CgoJICAgICAgICAvLyBQcmUtRmluYWwgdmFsdWVzCgkgICAgICAgIGNvbnN0IFQwciA9IE1BciArIE1DcjsKCSAgICAgICAgY29uc3QgVDBpID0gTUFpICsgTUNpOwoJICAgICAgICBjb25zdCBUMXIgPSBNQXIgLSBNQ3I7CgkgICAgICAgIGNvbnN0IFQxaSA9IE1BaSAtIE1DaTsKCSAgICAgICAgY29uc3QgVDJyID0gTUJyICsgTURyOwoJICAgICAgICBjb25zdCBUMmkgPSBNQmkgKyBNRGk7CgkgICAgICAgIGNvbnN0IFQzciA9IGludiAqIChNQnIgLSBNRHIpOwoJICAgICAgICBjb25zdCBUM2kgPSBpbnYgKiAoTUJpIC0gTURpKTsKCgkgICAgICAgIC8vIEZpbmFsIHZhbHVlcwoJICAgICAgICBjb25zdCBGQXIgPSBUMHIgKyBUMnI7CgkgICAgICAgIGNvbnN0IEZBaSA9IFQwaSArIFQyaTsKCgkgICAgICAgIGNvbnN0IEZDciA9IFQwciAtIFQycjsKCSAgICAgICAgY29uc3QgRkNpID0gVDBpIC0gVDJpOwoKCSAgICAgICAgY29uc3QgRkJyID0gVDFyICsgVDNpOwoJICAgICAgICBjb25zdCBGQmkgPSBUMWkgLSBUM3I7CgoJICAgICAgICBjb25zdCBGRHIgPSBUMXIgLSBUM2k7CgkgICAgICAgIGNvbnN0IEZEaSA9IFQxaSArIFQzcjsKCgkgICAgICAgIG91dFtBXSA9IEZBcjsKCSAgICAgICAgb3V0W0EgKyAxXSA9IEZBaTsKCSAgICAgICAgb3V0W0JdID0gRkJyOwoJICAgICAgICBvdXRbQiArIDFdID0gRkJpOwoJICAgICAgICBvdXRbQ10gPSBGQ3I7CgkgICAgICAgIG91dFtDICsgMV0gPSBGQ2k7CgkgICAgICAgIG91dFtEXSA9IEZEcjsKCSAgICAgICAgb3V0W0QgKyAxXSA9IEZEaTsKCSAgICAgIH0KCSAgICB9CgkgIH0KCX07CgoJLy8gcmFkaXgtMiBpbXBsZW1lbnRhdGlvbgoJLy8KCS8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49NAoJRkZULnByb3RvdHlwZS5fc2luZ2xlVHJhbnNmb3JtMiA9IGZ1bmN0aW9uIF9zaW5nbGVUcmFuc2Zvcm0yKG91dE9mZiwgb2ZmLAoJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKCSAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwoJICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKCgkgIGNvbnN0IGV2ZW5SID0gZGF0YVtvZmZdOwoJICBjb25zdCBldmVuSSA9IGRhdGFbb2ZmICsgMV07CgkgIGNvbnN0IG9kZFIgPSBkYXRhW29mZiArIHN0ZXBdOwoJICBjb25zdCBvZGRJID0gZGF0YVtvZmYgKyBzdGVwICsgMV07CgoJICBjb25zdCBsZWZ0UiA9IGV2ZW5SICsgb2RkUjsKCSAgY29uc3QgbGVmdEkgPSBldmVuSSArIG9kZEk7CgkgIGNvbnN0IHJpZ2h0UiA9IGV2ZW5SIC0gb2RkUjsKCSAgY29uc3QgcmlnaHRJID0gZXZlbkkgLSBvZGRJOwoKCSAgb3V0W291dE9mZl0gPSBsZWZ0UjsKCSAgb3V0W291dE9mZiArIDFdID0gbGVmdEk7CgkgIG91dFtvdXRPZmYgKyAyXSA9IHJpZ2h0UjsKCSAgb3V0W291dE9mZiArIDNdID0gcmlnaHRJOwoJfTsKCgkvLyByYWRpeC00CgkvLwoJLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj04CglGRlQucHJvdG90eXBlLl9zaW5nbGVUcmFuc2Zvcm00ID0gZnVuY3Rpb24gX3NpbmdsZVRyYW5zZm9ybTQob3V0T2ZmLCBvZmYsCgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewoJICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CgkgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwoJICBjb25zdCBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CgkgIGNvbnN0IHN0ZXAyID0gc3RlcCAqIDI7CgkgIGNvbnN0IHN0ZXAzID0gc3RlcCAqIDM7CgoJICAvLyBPcmlnaW5hbCB2YWx1ZXMKCSAgY29uc3QgQXIgPSBkYXRhW29mZl07CgkgIGNvbnN0IEFpID0gZGF0YVtvZmYgKyAxXTsKCSAgY29uc3QgQnIgPSBkYXRhW29mZiArIHN0ZXBdOwoJICBjb25zdCBCaSA9IGRhdGFbb2ZmICsgc3RlcCArIDFdOwoJICBjb25zdCBDciA9IGRhdGFbb2ZmICsgc3RlcDJdOwoJICBjb25zdCBDaSA9IGRhdGFbb2ZmICsgc3RlcDIgKyAxXTsKCSAgY29uc3QgRHIgPSBkYXRhW29mZiArIHN0ZXAzXTsKCSAgY29uc3QgRGkgPSBkYXRhW29mZiArIHN0ZXAzICsgMV07CgoJICAvLyBQcmUtRmluYWwgdmFsdWVzCgkgIGNvbnN0IFQwciA9IEFyICsgQ3I7CgkgIGNvbnN0IFQwaSA9IEFpICsgQ2k7CgkgIGNvbnN0IFQxciA9IEFyIC0gQ3I7CgkgIGNvbnN0IFQxaSA9IEFpIC0gQ2k7CgkgIGNvbnN0IFQyciA9IEJyICsgRHI7CgkgIGNvbnN0IFQyaSA9IEJpICsgRGk7CgkgIGNvbnN0IFQzciA9IGludiAqIChCciAtIERyKTsKCSAgY29uc3QgVDNpID0gaW52ICogKEJpIC0gRGkpOwoKCSAgLy8gRmluYWwgdmFsdWVzCgkgIGNvbnN0IEZBciA9IFQwciArIFQycjsKCSAgY29uc3QgRkFpID0gVDBpICsgVDJpOwoKCSAgY29uc3QgRkJyID0gVDFyICsgVDNpOwoJICBjb25zdCBGQmkgPSBUMWkgLSBUM3I7CgoJICBjb25zdCBGQ3IgPSBUMHIgLSBUMnI7CgkgIGNvbnN0IEZDaSA9IFQwaSAtIFQyaTsKCgkgIGNvbnN0IEZEciA9IFQxciAtIFQzaTsKCSAgY29uc3QgRkRpID0gVDFpICsgVDNyOwoKCSAgb3V0W291dE9mZl0gPSBGQXI7CgkgIG91dFtvdXRPZmYgKyAxXSA9IEZBaTsKCSAgb3V0W291dE9mZiArIDJdID0gRkJyOwoJICBvdXRbb3V0T2ZmICsgM10gPSBGQmk7CgkgIG91dFtvdXRPZmYgKyA0XSA9IEZDcjsKCSAgb3V0W291dE9mZiArIDVdID0gRkNpOwoJICBvdXRbb3V0T2ZmICsgNl0gPSBGRHI7CgkgIG91dFtvdXRPZmYgKyA3XSA9IEZEaTsKCX07CgoJLy8gUmVhbCBpbnB1dCByYWRpeC00IGltcGxlbWVudGF0aW9uCglGRlQucHJvdG90eXBlLl9yZWFsVHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF9yZWFsVHJhbnNmb3JtNCgpIHsKCSAgdmFyIG91dCA9IHRoaXMuX291dDsKCSAgdmFyIHNpemUgPSB0aGlzLl9jc2l6ZTsKCgkgIC8vIEluaXRpYWwgc3RlcCAocGVybXV0ZSBhbmQgdHJhbnNmb3JtKQoJICB2YXIgd2lkdGggPSB0aGlzLl93aWR0aDsKCSAgdmFyIHN0ZXAgPSAxIDw8IHdpZHRoOwoJICB2YXIgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwoKCSAgdmFyIG91dE9mZjsKCSAgdmFyIHQ7CgkgIHZhciBiaXRyZXYgPSB0aGlzLl9iaXRyZXY7CgkgIGlmIChsZW4gPT09IDQpIHsKCSAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKCSAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKCSAgICAgIHRoaXMuX3NpbmdsZVJlYWxUcmFuc2Zvcm0yKG91dE9mZiwgb2ZmID4+PiAxLCBzdGVwID4+PiAxKTsKCSAgICB9CgkgIH0gZWxzZSB7CgkgICAgLy8gbGVuID09PSA4CgkgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CgkgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CgkgICAgICB0aGlzLl9zaW5nbGVSZWFsVHJhbnNmb3JtNChvdXRPZmYsIG9mZiA+Pj4gMSwgc3RlcCA+Pj4gMSk7CgkgICAgfQoJICB9CgoJICAvLyBMb29wIHRocm91Z2ggc3RlcHMgaW4gZGVjcmVhc2luZyBvcmRlcgoJICB2YXIgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwoJICB2YXIgdGFibGUgPSB0aGlzLnRhYmxlOwoJICBmb3IgKHN0ZXAgPj49IDI7IHN0ZXAgPj0gMjsgc3RlcCA+Pj0gMikgewoJICAgIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCSAgICB2YXIgaGFsZkxlbiA9IGxlbiA+Pj4gMTsKCSAgICB2YXIgcXVhcnRlckxlbiA9IGhhbGZMZW4gPj4+IDE7CgkgICAgdmFyIGhxdWFydGVyTGVuID0gcXVhcnRlckxlbiA+Pj4gMTsKCgkgICAgLy8gTG9vcCB0aHJvdWdoIG9mZnNldHMgaW4gdGhlIGRhdGEKCSAgICBmb3IgKG91dE9mZiA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4pIHsKCSAgICAgIGZvciAodmFyIGkgPSAwLCBrID0gMDsgaSA8PSBocXVhcnRlckxlbjsgaSArPSAyLCBrICs9IHN0ZXApIHsKCSAgICAgICAgdmFyIEEgPSBvdXRPZmYgKyBpOwoJICAgICAgICB2YXIgQiA9IEEgKyBxdWFydGVyTGVuOwoJICAgICAgICB2YXIgQyA9IEIgKyBxdWFydGVyTGVuOwoJICAgICAgICB2YXIgRCA9IEMgKyBxdWFydGVyTGVuOwoKCSAgICAgICAgLy8gT3JpZ2luYWwgdmFsdWVzCgkgICAgICAgIHZhciBBciA9IG91dFtBXTsKCSAgICAgICAgdmFyIEFpID0gb3V0W0EgKyAxXTsKCSAgICAgICAgdmFyIEJyID0gb3V0W0JdOwoJICAgICAgICB2YXIgQmkgPSBvdXRbQiArIDFdOwoJICAgICAgICB2YXIgQ3IgPSBvdXRbQ107CgkgICAgICAgIHZhciBDaSA9IG91dFtDICsgMV07CgkgICAgICAgIHZhciBEciA9IG91dFtEXTsKCSAgICAgICAgdmFyIERpID0gb3V0W0QgKyAxXTsKCgkgICAgICAgIC8vIE1pZGRsZSB2YWx1ZXMKCSAgICAgICAgdmFyIE1BciA9IEFyOwoJICAgICAgICB2YXIgTUFpID0gQWk7CgoJICAgICAgICB2YXIgdGFibGVCciA9IHRhYmxlW2tdOwoJICAgICAgICB2YXIgdGFibGVCaSA9IGludiAqIHRhYmxlW2sgKyAxXTsKCSAgICAgICAgdmFyIE1CciA9IEJyICogdGFibGVCciAtIEJpICogdGFibGVCaTsKCSAgICAgICAgdmFyIE1CaSA9IEJyICogdGFibGVCaSArIEJpICogdGFibGVCcjsKCgkgICAgICAgIHZhciB0YWJsZUNyID0gdGFibGVbMiAqIGtdOwoJICAgICAgICB2YXIgdGFibGVDaSA9IGludiAqIHRhYmxlWzIgKiBrICsgMV07CgkgICAgICAgIHZhciBNQ3IgPSBDciAqIHRhYmxlQ3IgLSBDaSAqIHRhYmxlQ2k7CgkgICAgICAgIHZhciBNQ2kgPSBDciAqIHRhYmxlQ2kgKyBDaSAqIHRhYmxlQ3I7CgoJICAgICAgICB2YXIgdGFibGVEciA9IHRhYmxlWzMgKiBrXTsKCSAgICAgICAgdmFyIHRhYmxlRGkgPSBpbnYgKiB0YWJsZVszICogayArIDFdOwoJICAgICAgICB2YXIgTURyID0gRHIgKiB0YWJsZURyIC0gRGkgKiB0YWJsZURpOwoJICAgICAgICB2YXIgTURpID0gRHIgKiB0YWJsZURpICsgRGkgKiB0YWJsZURyOwoKCSAgICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwoJICAgICAgICB2YXIgVDByID0gTUFyICsgTUNyOwoJICAgICAgICB2YXIgVDBpID0gTUFpICsgTUNpOwoJICAgICAgICB2YXIgVDFyID0gTUFyIC0gTUNyOwoJICAgICAgICB2YXIgVDFpID0gTUFpIC0gTUNpOwoJICAgICAgICB2YXIgVDJyID0gTUJyICsgTURyOwoJICAgICAgICB2YXIgVDJpID0gTUJpICsgTURpOwoJICAgICAgICB2YXIgVDNyID0gaW52ICogKE1CciAtIE1Ecik7CgkgICAgICAgIHZhciBUM2kgPSBpbnYgKiAoTUJpIC0gTURpKTsKCgkgICAgICAgIC8vIEZpbmFsIHZhbHVlcwoJICAgICAgICB2YXIgRkFyID0gVDByICsgVDJyOwoJICAgICAgICB2YXIgRkFpID0gVDBpICsgVDJpOwoKCSAgICAgICAgdmFyIEZCciA9IFQxciArIFQzaTsKCSAgICAgICAgdmFyIEZCaSA9IFQxaSAtIFQzcjsKCgkgICAgICAgIG91dFtBXSA9IEZBcjsKCSAgICAgICAgb3V0W0EgKyAxXSA9IEZBaTsKCSAgICAgICAgb3V0W0JdID0gRkJyOwoJICAgICAgICBvdXRbQiArIDFdID0gRkJpOwoKCSAgICAgICAgLy8gT3V0cHV0IGZpbmFsIG1pZGRsZSBwb2ludAoJICAgICAgICBpZiAoaSA9PT0gMCkgewoJICAgICAgICAgIHZhciBGQ3IgPSBUMHIgLSBUMnI7CgkgICAgICAgICAgdmFyIEZDaSA9IFQwaSAtIFQyaTsKCSAgICAgICAgICBvdXRbQ10gPSBGQ3I7CgkgICAgICAgICAgb3V0W0MgKyAxXSA9IEZDaTsKCSAgICAgICAgICBjb250aW51ZTsKCSAgICAgICAgfQoKCSAgICAgICAgLy8gRG8gbm90IG92ZXJ3cml0ZSBvdXJzZWx2ZXMKCSAgICAgICAgaWYgKGkgPT09IGhxdWFydGVyTGVuKQoJICAgICAgICAgIGNvbnRpbnVlOwoKCSAgICAgICAgLy8gSW4gdGhlIGZsaXBwZWQgY2FzZToKCSAgICAgICAgLy8gTUFpID0gLU1BaQoJICAgICAgICAvLyBNQnI9LU1CaSwgTUJpPS1NQnIKCSAgICAgICAgLy8gTUNyPS1NQ3IKCSAgICAgICAgLy8gTURyPU1EaSwgTURpPU1EcgoJICAgICAgICB2YXIgU1QwciA9IFQxcjsKCSAgICAgICAgdmFyIFNUMGkgPSAtVDFpOwoJICAgICAgICB2YXIgU1QxciA9IFQwcjsKCSAgICAgICAgdmFyIFNUMWkgPSAtVDBpOwoJICAgICAgICB2YXIgU1QyciA9IC1pbnYgKiBUM2k7CgkgICAgICAgIHZhciBTVDJpID0gLWludiAqIFQzcjsKCSAgICAgICAgdmFyIFNUM3IgPSAtaW52ICogVDJpOwoJICAgICAgICB2YXIgU1QzaSA9IC1pbnYgKiBUMnI7CgoJICAgICAgICB2YXIgU0ZBciA9IFNUMHIgKyBTVDJyOwoJICAgICAgICB2YXIgU0ZBaSA9IFNUMGkgKyBTVDJpOwoKCSAgICAgICAgdmFyIFNGQnIgPSBTVDFyICsgU1QzaTsKCSAgICAgICAgdmFyIFNGQmkgPSBTVDFpIC0gU1QzcjsKCgkgICAgICAgIHZhciBTQSA9IG91dE9mZiArIHF1YXJ0ZXJMZW4gLSBpOwoJICAgICAgICB2YXIgU0IgPSBvdXRPZmYgKyBoYWxmTGVuIC0gaTsKCgkgICAgICAgIG91dFtTQV0gPSBTRkFyOwoJICAgICAgICBvdXRbU0EgKyAxXSA9IFNGQWk7CgkgICAgICAgIG91dFtTQl0gPSBTRkJyOwoJICAgICAgICBvdXRbU0IgKyAxXSA9IFNGQmk7CgkgICAgICB9CgkgICAgfQoJICB9Cgl9OwoKCS8vIHJhZGl4LTIgaW1wbGVtZW50YXRpb24KCS8vCgkvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTQKCUZGVC5wcm90b3R5cGUuX3NpbmdsZVJlYWxUcmFuc2Zvcm0yID0gZnVuY3Rpb24gX3NpbmdsZVJlYWxUcmFuc2Zvcm0yKG91dE9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKCSAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwoJICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKCgkgIGNvbnN0IGV2ZW5SID0gZGF0YVtvZmZdOwoJICBjb25zdCBvZGRSID0gZGF0YVtvZmYgKyBzdGVwXTsKCgkgIGNvbnN0IGxlZnRSID0gZXZlblIgKyBvZGRSOwoJICBjb25zdCByaWdodFIgPSBldmVuUiAtIG9kZFI7CgoJICBvdXRbb3V0T2ZmXSA9IGxlZnRSOwoJICBvdXRbb3V0T2ZmICsgMV0gPSAwOwoJICBvdXRbb3V0T2ZmICsgMl0gPSByaWdodFI7CgkgIG91dFtvdXRPZmYgKyAzXSA9IDA7Cgl9OwoKCS8vIHJhZGl4LTQKCS8vCgkvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTgKCUZGVC5wcm90b3R5cGUuX3NpbmdsZVJlYWxUcmFuc2Zvcm00ID0gZnVuY3Rpb24gX3NpbmdsZVJlYWxUcmFuc2Zvcm00KG91dE9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKCSAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwoJICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKCSAgY29uc3QgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwoJICBjb25zdCBzdGVwMiA9IHN0ZXAgKiAyOwoJICBjb25zdCBzdGVwMyA9IHN0ZXAgKiAzOwoKCSAgLy8gT3JpZ2luYWwgdmFsdWVzCgkgIGNvbnN0IEFyID0gZGF0YVtvZmZdOwoJICBjb25zdCBCciA9IGRhdGFbb2ZmICsgc3RlcF07CgkgIGNvbnN0IENyID0gZGF0YVtvZmYgKyBzdGVwMl07CgkgIGNvbnN0IERyID0gZGF0YVtvZmYgKyBzdGVwM107CgoJICAvLyBQcmUtRmluYWwgdmFsdWVzCgkgIGNvbnN0IFQwciA9IEFyICsgQ3I7CgkgIGNvbnN0IFQxciA9IEFyIC0gQ3I7CgkgIGNvbnN0IFQyciA9IEJyICsgRHI7CgkgIGNvbnN0IFQzciA9IGludiAqIChCciAtIERyKTsKCgkgIC8vIEZpbmFsIHZhbHVlcwoJICBjb25zdCBGQXIgPSBUMHIgKyBUMnI7CgoJICBjb25zdCBGQnIgPSBUMXI7CgkgIGNvbnN0IEZCaSA9IC1UM3I7CgoJICBjb25zdCBGQ3IgPSBUMHIgLSBUMnI7CgoJICBjb25zdCBGRHIgPSBUMXI7CgkgIGNvbnN0IEZEaSA9IFQzcjsKCgkgIG91dFtvdXRPZmZdID0gRkFyOwoJICBvdXRbb3V0T2ZmICsgMV0gPSAwOwoJICBvdXRbb3V0T2ZmICsgMl0gPSBGQnI7CgkgIG91dFtvdXRPZmYgKyAzXSA9IEZCaTsKCSAgb3V0W291dE9mZiArIDRdID0gRkNyOwoJICBvdXRbb3V0T2ZmICsgNV0gPSAwOwoJICBvdXRbb3V0T2ZmICsgNl0gPSBGRHI7CgkgIG91dFtvdXRPZmYgKyA3XSA9IEZEaTsKCX07CgoJdmFyIEZGVCQxID0gLypAX19QVVJFX18qL2dldERlZmF1bHRFeHBvcnRGcm9tQ2pzKGZmdCk7CgoJY29uc3QgV0VCQVVESU9fQkxPQ0tfU0laRSA9IDEyODsKCWNvbnN0IERFRkFVTFRfQkxPQ0tfU0laRSA9IDEwMjQ7IC8vIERlZmF1bHQgYmxvY2sgc2l6ZSBpZiBub3QgcHJvdmlkZWQgaW4gb3B0aW9ucwoJLyoqIE92ZXJsYXAtQWRkIE5vZGUgKi8KCWNsYXNzIE9MQVByb2Nlc3NvciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CgkgICAgbmJJbnB1dHM7CgkgICAgbmJPdXRwdXRzOwoJICAgIGJsb2NrU2l6ZTsKCSAgICBob3BTaXplOwoJICAgIG5iT3ZlcmxhcHM7CgkgICAgaW5wdXRCdWZmZXJzID0gW107CgkgICAgaW5wdXRCdWZmZXJzSGVhZCA9IFtdOwoJICAgIGlucHV0QnVmZmVyc1RvU2VuZCA9IFtdOwoJICAgIG91dHB1dEJ1ZmZlcnMgPSBbXTsKCSAgICBvdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSA9IFtdOwoJICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKCSAgICAgICAgc3VwZXIob3B0aW9ucyk7CgkgICAgICAgIHRoaXMubmJJbnB1dHMgPSBvcHRpb25zLm51bWJlck9mSW5wdXRzIHx8IDE7CgkgICAgICAgIHRoaXMubmJPdXRwdXRzID0gb3B0aW9ucy5udW1iZXJPZk91dHB1dHMgfHwgMTsKCSAgICAgICAgdGhpcy5ibG9ja1NpemUgPSBvcHRpb25zLnByb2Nlc3Nvck9wdGlvbnMuYmxvY2tTaXplIHx8IERFRkFVTFRfQkxPQ0tfU0laRTsKCSAgICAgICAgdGhpcy5ob3BTaXplID0gV0VCQVVESU9fQkxPQ0tfU0laRTsKCSAgICAgICAgdGhpcy5uYk92ZXJsYXBzID0gTWF0aC5mbG9vcih0aGlzLmJsb2NrU2l6ZSAvIHRoaXMuaG9wU2l6ZSk7CgkgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcnMoKTsKCSAgICB9CgkgICAgaW5pdGlhbGl6ZUJ1ZmZlcnMoKSB7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwoJICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWQgPSBuZXcgQXJyYXkodGhpcy5uYklucHV0cyk7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwoJICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnMgPSBuZXcgQXJyYXkodGhpcy5uYk91dHB1dHMpOwoJICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlID0gbmV3IEFycmF5KHRoaXMubmJPdXRwdXRzKTsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVJbnB1dENoYW5uZWxzKGksIDEpOwoJICAgICAgICB9CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgdGhpcy5hbGxvY2F0ZU91dHB1dENoYW5uZWxzKGksIDEpOwoJICAgICAgICB9CgkgICAgfQoJICAgIGFsbG9jYXRlSW5wdXRDaGFubmVscyhpbnB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwoJICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWRbaW5wdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwoJICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewoJICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplICsgV0VCQVVESU9fQkxPQ0tfU0laRSk7CgkgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpbnB1dEluZGV4XVtpXS5maWxsKDApOwoJICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2lucHV0SW5kZXhdW2ldID0gdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0uc3ViYXJyYXkoMCwgdGhpcy5ibG9ja1NpemUpOwoJICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmRbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKCSAgICAgICAgfQoJICAgIH0KCSAgICBhbGxvY2F0ZU91dHB1dENoYW5uZWxzKG91dHB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CgkgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CgkgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbb3V0cHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwoJICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewoJICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5ibG9ja1NpemUpOwoJICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXS5maWxsKDApOwoJICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZVtvdXRwdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKCSAgICAgICAgfQoJICAgIH0KCSAgICByZWFsbG9jYXRlQ2hhbm5lbHNJZk5lZWRlZChpbnB1dHMsIG91dHB1dHMpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIGNvbnN0IG5iQ2hhbm5lbHMgPSBpbnB1dHNbaV0ubGVuZ3RoOwoJICAgICAgICAgICAgaWYgKG5iQ2hhbm5lbHMgIT09IHRoaXMuaW5wdXRCdWZmZXJzW2ldLmxlbmd0aCkgewoJICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVJbnB1dENoYW5uZWxzKGksIG5iQ2hhbm5lbHMpOwoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgY29uc3QgbmJDaGFubmVscyA9IG91dHB1dHNbaV0ubGVuZ3RoOwoJICAgICAgICAgICAgaWYgKG5iQ2hhbm5lbHMgIT09IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGgpIHsKCSAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlT3V0cHV0Q2hhbm5lbHMoaSwgbmJDaGFubmVscyk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgcmVhZElucHV0cyhpbnB1dHMpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKCSAgICAgICAgICAgICAgICBjb25zdCB3ZWJBdWRpb0Jsb2NrID0gaW5wdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2ldW2pdLnNldCh3ZWJBdWRpb0Jsb2NrLCB0aGlzLmJsb2NrU2l6ZSk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgd3JpdGVPdXRwdXRzKG91dHB1dHMpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CgkgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewoJICAgICAgICAgICAgICAgIGNvbnN0IHdlYkF1ZGlvQmxvY2sgPSBvdXRwdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHdlYkF1ZGlvQmxvY2suc2V0KHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXS5zdWJhcnJheSgwLCBXRUJBVURJT19CTE9DS19TSVpFKSk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgc2hpZnRJbnB1dEJ1ZmZlcnMoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CgkgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMuaW5wdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CgkgICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaV1bal0uY29weVdpdGhpbigwLCBXRUJBVURJT19CTE9DS19TSVpFKTsKCSAgICAgICAgICAgIH0KCSAgICAgICAgfQoJICAgIH0KCSAgICBzaGlmdE91dHB1dEJ1ZmZlcnMoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm91dHB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKCSAgICAgICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal0uY29weVdpdGhpbigwLCBXRUJBVURJT19CTE9DS19TSVpFKTsKCSAgICAgICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal0uZmlsbCgwLCB0aGlzLmJsb2NrU2l6ZSAtIFdFQkFVRElPX0JMT0NLX1NJWkUpOwoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgfQoJICAgIHByZXBhcmVJbnB1dEJ1ZmZlcnNUb1NlbmQoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CgkgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMuaW5wdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CgkgICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmRbaV1bal0uc2V0KHRoaXMuaW5wdXRCdWZmZXJzSGVhZFtpXVtqXSk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgaGFuZGxlT3V0cHV0QnVmZmVyc1RvUmV0cmlldmUoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm91dHB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKCSAgICAgICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRoaXMuYmxvY2tTaXplOyBrKyspIHsKCSAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdW2tdICs9IHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbaV1bal1ba10gLyB0aGlzLm5iT3ZlcmxhcHM7CgkgICAgICAgICAgICAgICAgfQoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgfQoJICAgIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CgkgICAgICAgIHRoaXMucmVhbGxvY2F0ZUNoYW5uZWxzSWZOZWVkZWQoaW5wdXRzLCBvdXRwdXRzKTsKCSAgICAgICAgdGhpcy5yZWFkSW5wdXRzKGlucHV0cyk7CgkgICAgICAgIHRoaXMuc2hpZnRJbnB1dEJ1ZmZlcnMoKTsKCSAgICAgICAgdGhpcy5wcmVwYXJlSW5wdXRCdWZmZXJzVG9TZW5kKCk7CgkgICAgICAgIHRoaXMucHJvY2Vzc09MQSh0aGlzLmlucHV0QnVmZmVyc1RvU2VuZCwgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSwgcGFyYW1ldGVycyk7CgkgICAgICAgIHRoaXMuaGFuZGxlT3V0cHV0QnVmZmVyc1RvUmV0cmlldmUoKTsKCSAgICAgICAgdGhpcy53cml0ZU91dHB1dHMob3V0cHV0cyk7CgkgICAgICAgIHRoaXMuc2hpZnRPdXRwdXRCdWZmZXJzKCk7CgkgICAgICAgIHJldHVybiB0cnVlOwoJICAgIH0KCX0KCgljb25zdCBCVUZGRVJFRF9CTE9DS19TSVpFID0gMjA0ODsKCWZ1bmN0aW9uIGdlbkhhbm5XaW5kb3cobGVuZ3RoKSB7CgkgICAgY29uc3Qgd2luID0gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpOwoJICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKCSAgICAgICAgd2luW2ldID0gMC41ICogKDEgLSBNYXRoLmNvcygoMiAqIE1hdGguUEkgKiBpKSAvIGxlbmd0aCkpOwoJICAgIH0KCSAgICByZXR1cm4gd2luOwoJfQoJY2xhc3MgUGhhc2VWb2NvZGVyUHJvY2Vzc29yIGV4dGVuZHMgT0xBUHJvY2Vzc29yIHsKCSAgICBmZnRTaXplOwoJICAgIHRpbWVDdXJzb3I7CgkgICAgaGFubldpbmRvdzsKCSAgICBmZnQ7CgkgICAgZnJlcUNvbXBsZXhCdWZmZXI7CgkgICAgZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkOwoJICAgIHRpbWVDb21wbGV4QnVmZmVyOwoJICAgIG1hZ25pdHVkZXM7CgkgICAgcGVha0luZGV4ZXM7CgkgICAgbmJQZWFrczsKCSAgICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewoJICAgICAgICByZXR1cm4gWwoJICAgICAgICAgICAgewoJICAgICAgICAgICAgICAgIG5hbWU6ICJwaXRjaEZhY3RvciIsCgkgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxLjAsCgkgICAgICAgICAgICB9LAoJICAgICAgICBdOwoJICAgIH0KCSAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CgkgICAgICAgIG9wdGlvbnMucHJvY2Vzc29yT3B0aW9ucyA9IHsKCSAgICAgICAgICAgIGJsb2NrU2l6ZTogQlVGRkVSRURfQkxPQ0tfU0laRSwKCSAgICAgICAgfTsKCSAgICAgICAgc3VwZXIob3B0aW9ucyk7CgkgICAgICAgIHRoaXMuZmZ0U2l6ZSA9IHRoaXMuYmxvY2tTaXplOwoJICAgICAgICB0aGlzLnRpbWVDdXJzb3IgPSAwOwoJICAgICAgICB0aGlzLmhhbm5XaW5kb3cgPSBnZW5IYW5uV2luZG93KHRoaXMuYmxvY2tTaXplKTsKCSAgICAgICAgLy8gcHJlcGFyZSBGRlQgYW5kIHByZS1hbGxvY2F0ZSBidWZmZXJzCgkgICAgICAgIHRoaXMuZmZ0ID0gbmV3IEZGVCQxKHRoaXMuZmZ0U2l6ZSk7CgkgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKCSAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKCSAgICAgICAgdGhpcy50aW1lQ29tcGxleEJ1ZmZlciA9IHRoaXMuZmZ0LmNyZWF0ZUNvbXBsZXhBcnJheSgpOwoJICAgICAgICB0aGlzLm1hZ25pdHVkZXMgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZmZ0U2l6ZSAvIDIgKyAxKTsKCSAgICAgICAgdGhpcy5wZWFrSW5kZXhlcyA9IG5ldyBJbnQzMkFycmF5KHRoaXMubWFnbml0dWRlcy5sZW5ndGgpOwoJICAgICAgICB0aGlzLm5iUGVha3MgPSAwOwoJICAgIH0KCSAgICBwcm9jZXNzT0xBKGlucHV0cywgb3V0cHV0cywgcGFyYW1ldGVycykgewoJICAgICAgICBjb25zdCBwaXRjaEZhY3RvciA9IHBhcmFtZXRlcnMucGl0Y2hGYWN0b3JbcGFyYW1ldGVycy5waXRjaEZhY3Rvci5sZW5ndGggLSAxXTsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaW5wdXRzW2ldLmxlbmd0aDsgaisrKSB7CgkgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gaW5wdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBvdXRwdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHRoaXMuYXBwbHlIYW5uV2luZG93KGlucHV0KTsKCSAgICAgICAgICAgICAgICB0aGlzLmZmdC5yZWFsVHJhbnNmb3JtKHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIsIGlucHV0KTsKCSAgICAgICAgICAgICAgICB0aGlzLmNvbXB1dGVNYWduaXR1ZGVzKCk7CgkgICAgICAgICAgICAgICAgdGhpcy5maW5kUGVha3MoKTsKCSAgICAgICAgICAgICAgICB0aGlzLnNoaWZ0UGVha3MocGl0Y2hGYWN0b3IpOwoJICAgICAgICAgICAgICAgIHRoaXMuZmZ0LmNvbXBsZXRlU3BlY3RydW0odGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQpOwoJICAgICAgICAgICAgICAgIHRoaXMuZmZ0LmludmVyc2VUcmFuc2Zvcm0odGhpcy50aW1lQ29tcGxleEJ1ZmZlciwgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQpOwoJICAgICAgICAgICAgICAgIHRoaXMuZmZ0LmZyb21Db21wbGV4QXJyYXkodGhpcy50aW1lQ29tcGxleEJ1ZmZlciwgb3V0cHV0KTsKCSAgICAgICAgICAgICAgICB0aGlzLmFwcGx5SGFubldpbmRvdyhvdXRwdXQpOwoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgICAgIHRoaXMudGltZUN1cnNvciArPSB0aGlzLmhvcFNpemU7CgkgICAgICAgIHJldHVybiB0cnVlOwoJICAgIH0KCSAgICBhcHBseUhhbm5XaW5kb3coaW5wdXQpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmJsb2NrU2l6ZTsgaSsrKSB7CgkgICAgICAgICAgICBpbnB1dFtpXSAqPSB0aGlzLmhhbm5XaW5kb3dbaV07CgkgICAgICAgIH0KCSAgICB9CgkgICAgY29tcHV0ZU1hZ25pdHVkZXMoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IHRoaXMubWFnbml0dWRlcy5sZW5ndGg7IGkrKywgaiArPSAyKSB7CgkgICAgICAgICAgICBjb25zdCByZWFsID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltqXTsKCSAgICAgICAgICAgIGNvbnN0IGltYWcgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2ogKyAxXTsKCSAgICAgICAgICAgIHRoaXMubWFnbml0dWRlc1tpXSA9IHJlYWwgKiogMiArIGltYWcgKiogMjsKCSAgICAgICAgfQoJICAgIH0KCSAgICBmaW5kUGVha3MoKSB7CgkgICAgICAgIHRoaXMubmJQZWFrcyA9IDA7CgkgICAgICAgIGZvciAobGV0IGkgPSAyLCBlbmQgPSB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoIC0gMjsgaSA8IGVuZDsgaSsrKSB7CgkgICAgICAgICAgICBjb25zdCBtYWcgPSB0aGlzLm1hZ25pdHVkZXNbaV07CgkgICAgICAgICAgICBpZiAodGhpcy5tYWduaXR1ZGVzW2kgLSAxXSA+PSBtYWcgfHwKCSAgICAgICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXNbaSAtIDJdID49IG1hZyB8fAoJICAgICAgICAgICAgICAgIHRoaXMubWFnbml0dWRlc1tpICsgMV0gPj0gbWFnIHx8CgkgICAgICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzW2kgKyAyXSA+PSBtYWcpIHsKCSAgICAgICAgICAgICAgICBjb250aW51ZTsKCSAgICAgICAgICAgIH0KCSAgICAgICAgICAgIHRoaXMucGVha0luZGV4ZXNbdGhpcy5uYlBlYWtzKytdID0gaTsKCSAgICAgICAgfQoJICAgIH0KCSAgICBzaGlmdFBlYWtzKHBpdGNoRmFjdG9yKSB7CgkgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkLmZpbGwoMCk7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYlBlYWtzOyBpKyspIHsKCSAgICAgICAgICAgIGNvbnN0IHBlYWtJbmRleCA9IHRoaXMucGVha0luZGV4ZXNbaV07CgkgICAgICAgICAgICBjb25zdCBwZWFrSW5kZXhTaGlmdGVkID0gTWF0aC5yb3VuZChwZWFrSW5kZXggKiBwaXRjaEZhY3Rvcik7CgkgICAgICAgICAgICBpZiAocGVha0luZGV4U2hpZnRlZCA+IHRoaXMubWFnbml0dWRlcy5sZW5ndGgpIHsKCSAgICAgICAgICAgICAgICBicmVhazsKCSAgICAgICAgICAgIH0KCSAgICAgICAgICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBpID4gMCA/IHBlYWtJbmRleCAtIE1hdGguZmxvb3IoKHBlYWtJbmRleCAtIHRoaXMucGVha0luZGV4ZXNbaSAtIDFdKSAvIDIpIDogMDsKCSAgICAgICAgICAgIGNvbnN0IGVuZEluZGV4ID0gaSA8IHRoaXMubmJQZWFrcyAtIDEgPyBwZWFrSW5kZXggKyBNYXRoLmNlaWwoKHRoaXMucGVha0luZGV4ZXNbaSArIDFdIC0gcGVha0luZGV4KSAvIDIpIDogdGhpcy5mZnRTaXplOwoJICAgICAgICAgICAgZm9yIChsZXQgaiA9IHN0YXJ0SW5kZXggLSBwZWFrSW5kZXg7IGogPCBlbmRJbmRleCAtIHBlYWtJbmRleDsgaisrKSB7CgkgICAgICAgICAgICAgICAgY29uc3QgYmluSW5kZXggPSBwZWFrSW5kZXggKyBqOwoJICAgICAgICAgICAgICAgIGNvbnN0IGJpbkluZGV4U2hpZnRlZCA9IHBlYWtJbmRleFNoaWZ0ZWQgKyBqOwoJICAgICAgICAgICAgICAgIGlmIChiaW5JbmRleFNoaWZ0ZWQgPj0gdGhpcy5tYWduaXR1ZGVzLmxlbmd0aCkgewoJICAgICAgICAgICAgICAgICAgICBicmVhazsKCSAgICAgICAgICAgICAgICB9CgkgICAgICAgICAgICAgICAgY29uc3Qgb21lZ2FEZWx0YSA9ICgyICogTWF0aC5QSSAqIChiaW5JbmRleFNoaWZ0ZWQgLSBiaW5JbmRleCkpIC8gdGhpcy5mZnRTaXplOwoJICAgICAgICAgICAgICAgIGNvbnN0IHBoYXNlU2hpZnRSZWFsID0gTWF0aC5jb3Mob21lZ2FEZWx0YSAqIHRoaXMudGltZUN1cnNvcik7CgkgICAgICAgICAgICAgICAgY29uc3QgcGhhc2VTaGlmdEltYWcgPSBNYXRoLnNpbihvbWVnYURlbHRhICogdGhpcy50aW1lQ3Vyc29yKTsKCSAgICAgICAgICAgICAgICBjb25zdCBpbmRleFJlYWwgPSBiaW5JbmRleCAqIDI7CgkgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhJbWFnID0gaW5kZXhSZWFsICsgMTsKCSAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVJlYWwgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2luZGV4UmVhbF07CgkgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVJbWFnID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltpbmRleEltYWddOwoJICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZFJlYWwgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0UmVhbCAtIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRJbWFnOwoJICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZEltYWcgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0SW1hZyArIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRSZWFsOwoJICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZFJlYWwgPSBiaW5JbmRleFNoaWZ0ZWQgKiAyOwoJICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZEltYWcgPSBpbmRleFNoaWZ0ZWRSZWFsICsgMTsKCSAgICAgICAgICAgICAgICB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZFtpbmRleFNoaWZ0ZWRSZWFsXSArPSB2YWx1ZVNoaWZ0ZWRSZWFsOwoJICAgICAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkW2luZGV4U2hpZnRlZEltYWddICs9IHZhbHVlU2hpZnRlZEltYWc7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9Cgl9CgkvLyBAdHMtZXhwZWN0LWVycm9yCglyZWdpc3RlclByb2Nlc3NvcigicGhhc2Utdm9jb2RlciIsIFBoYXNlVm9jb2RlclByb2Nlc3Nvcik7Cgljb25zb2xlLmxvZygiUGhhc2VWb2NvZGVyUHJvY2Vzc29yIHJlZ2lzdGVyZWQiKTsKCglleHBvcnRzLlBoYXNlVm9jb2RlclByb2Nlc3NvciA9IFBoYXNlVm9jb2RlclByb2Nlc3NvcjsKCglyZXR1cm4gZXhwb3J0czsKCn0pKHt9KTsKLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGhhc2Utdm9jb2Rlci1idW5kbGUuanMubWFwCg==",v="data:text/javascript;base64,dmFyIHN0ZXJlb1RvQmZvcm1hdCA9IChmdW5jdGlvbiAoZXhwb3J0cykgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNvbnN0IEJVVFRFUldPUlRIX1EgPSBNYXRoLlNRUlQxXzI7CiAgICBjb25zdCBMT1dfQ1VUT0ZGX0haID0gMjUwOwogICAgY29uc3QgSElHSF9DVVRPRkZfSFogPSAyMDAwOwogICAgLy8gVGllciAxIHBlcmNlcHR1YWwgdHVuaW5nOgogICAgLy8gLSBLZWVwIGxvdy1iYW5kIGVuZXJneSBtb3N0bHkgb21uaWRpcmVjdGlvbmFsLgogICAgLy8gLSBSZWR1Y2UgVyByZWxhdGl2ZSB0byB0aGUgb3JpZ2luYWwgc3FydCgxLzIpIG1hcHBpbmcuCiAgICAvLyAtIExldCB1cHBlciBiYW5kcyBjYXJyeSBtb3JlIG9mIHRoZSBob3Jpem9udGFsIGN1ZS4KICAgIGNvbnN0IFdfR0FJTl9MT1cgPSAwLjU7CiAgICBjb25zdCBXX0dBSU5fTUlEID0gMC40NTsKICAgIGNvbnN0IFdfR0FJTl9ISUdIID0gMC4zNTsKICAgIGNvbnN0IFhfR0FJTl9MT1cgPSAwOwogICAgY29uc3QgWF9HQUlOX01JRCA9IDAuMzU7CiAgICBjb25zdCBYX0dBSU5fSElHSCA9IDAuNTU7CiAgICBjb25zdCBZX0dBSU5fTE9XID0gMDsKICAgIGNvbnN0IFlfR0FJTl9NSUQgPSAwLjU7CiAgICBjb25zdCBZX0dBSU5fSElHSCA9IDAuODU7CiAgICBjbGFzcyBCaXF1YWRGaWx0ZXIgewogICAgICAgIGIwID0gMDsKICAgICAgICBiMSA9IDA7CiAgICAgICAgYjIgPSAwOwogICAgICAgIGExID0gMDsKICAgICAgICBhMiA9IDA7CiAgICAgICAgeDEgPSAwOwogICAgICAgIHgyID0gMDsKICAgICAgICB5MSA9IDA7CiAgICAgICAgeTIgPSAwOwogICAgICAgIGNvbnN0cnVjdG9yKHR5cGUsIHNhbXBsZVJhdGUsIGN1dG9mZkh6LCBxID0gQlVUVEVSV09SVEhfUSkgewogICAgICAgICAgICB0aGlzLmNvbmZpZ3VyZSh0eXBlLCBzYW1wbGVSYXRlLCBjdXRvZmZIeiwgcSk7CiAgICAgICAgfQogICAgICAgIGNvbmZpZ3VyZSh0eXBlLCBzYW1wbGVSYXRlLCBjdXRvZmZIeiwgcSkgewogICAgICAgICAgICBjb25zdCBjbGFtcGVkQ3V0b2ZmID0gTWF0aC5tYXgoMSwgTWF0aC5taW4oY3V0b2ZmSHosIHNhbXBsZVJhdGUgKiAwLjQ1KSk7CiAgICAgICAgICAgIGNvbnN0IG9tZWdhID0gKDIgKiBNYXRoLlBJICogY2xhbXBlZEN1dG9mZikgLyBzYW1wbGVSYXRlOwogICAgICAgICAgICBjb25zdCBzaW4gPSBNYXRoLnNpbihvbWVnYSk7CiAgICAgICAgICAgIGNvbnN0IGNvcyA9IE1hdGguY29zKG9tZWdhKTsKICAgICAgICAgICAgY29uc3QgYWxwaGEgPSBzaW4gLyAoMiAqIHEpOwogICAgICAgICAgICBsZXQgYjA7CiAgICAgICAgICAgIGxldCBiMTsKICAgICAgICAgICAgbGV0IGIyOwogICAgICAgICAgICBpZiAodHlwZSA9PT0gImxvd3Bhc3MiKSB7CiAgICAgICAgICAgICAgICBiMCA9ICgxIC0gY29zKSAvIDI7CiAgICAgICAgICAgICAgICBiMSA9IDEgLSBjb3M7CiAgICAgICAgICAgICAgICBiMiA9ICgxIC0gY29zKSAvIDI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBiMCA9ICgxICsgY29zKSAvIDI7CiAgICAgICAgICAgICAgICBiMSA9IC0oMSArIGNvcyk7CiAgICAgICAgICAgICAgICBiMiA9ICgxICsgY29zKSAvIDI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYTAgPSAxICsgYWxwaGE7CiAgICAgICAgICAgIGNvbnN0IGExID0gLTIgKiBjb3M7CiAgICAgICAgICAgIGNvbnN0IGEyID0gMSAtIGFscGhhOwogICAgICAgICAgICB0aGlzLmIwID0gYjAgLyBhMDsKICAgICAgICAgICAgdGhpcy5iMSA9IGIxIC8gYTA7CiAgICAgICAgICAgIHRoaXMuYjIgPSBiMiAvIGEwOwogICAgICAgICAgICB0aGlzLmExID0gYTEgLyBhMDsKICAgICAgICAgICAgdGhpcy5hMiA9IGEyIC8gYTA7CiAgICAgICAgfQogICAgICAgIHByb2Nlc3MoaW5wdXQpIHsKICAgICAgICAgICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5iMCAqIGlucHV0ICsgdGhpcy5iMSAqIHRoaXMueDEgKyB0aGlzLmIyICogdGhpcy54MiAtIHRoaXMuYTEgKiB0aGlzLnkxIC0gdGhpcy5hMiAqIHRoaXMueTI7CiAgICAgICAgICAgIHRoaXMueDIgPSB0aGlzLngxOwogICAgICAgICAgICB0aGlzLngxID0gaW5wdXQ7CiAgICAgICAgICAgIHRoaXMueTIgPSB0aGlzLnkxOwogICAgICAgICAgICB0aGlzLnkxID0gb3V0cHV0OwogICAgICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgICAgIH0KICAgIH0KICAgIGNsYXNzIFN0ZXJlb1RvRm9hVXBtaXhlciB7CiAgICAgICAgbG93TGVmdDsKICAgICAgICBsb3dSaWdodDsKICAgICAgICBoaWdoTGVmdDsKICAgICAgICBoaWdoUmlnaHQ7CiAgICAgICAgY29uc3RydWN0b3Ioc2FtcGxlUmF0ZSkgewogICAgICAgICAgICB0aGlzLmxvd0xlZnQgPSBuZXcgQmlxdWFkRmlsdGVyKCJsb3dwYXNzIiwgc2FtcGxlUmF0ZSwgTE9XX0NVVE9GRl9IWik7CiAgICAgICAgICAgIHRoaXMubG93UmlnaHQgPSBuZXcgQmlxdWFkRmlsdGVyKCJsb3dwYXNzIiwgc2FtcGxlUmF0ZSwgTE9XX0NVVE9GRl9IWik7CiAgICAgICAgICAgIHRoaXMuaGlnaExlZnQgPSBuZXcgQmlxdWFkRmlsdGVyKCJoaWdocGFzcyIsIHNhbXBsZVJhdGUsIEhJR0hfQ1VUT0ZGX0haKTsKICAgICAgICAgICAgdGhpcy5oaWdoUmlnaHQgPSBuZXcgQmlxdWFkRmlsdGVyKCJoaWdocGFzcyIsIHNhbXBsZVJhdGUsIEhJR0hfQ1VUT0ZGX0haKTsKICAgICAgICB9CiAgICAgICAgcHJvY2VzcyhsZWZ0LCByaWdodCwgdywgeSwgeiwgeCkgewogICAgICAgICAgICBjb25zdCBmcmFtZUNvdW50ID0gTWF0aC5taW4obGVmdC5sZW5ndGgsIHJpZ2h0Lmxlbmd0aCwgdy5sZW5ndGgsIHgubGVuZ3RoLCB5Lmxlbmd0aCwgei5sZW5ndGgpOwogICAgICAgICAgICBmb3IgKGxldCBmcmFtZSA9IDA7IGZyYW1lIDwgZnJhbWVDb3VudDsgZnJhbWUrKykgewogICAgICAgICAgICAgICAgY29uc3QgbGVmdFNhbXBsZSA9IGxlZnRbZnJhbWVdOwogICAgICAgICAgICAgICAgY29uc3QgcmlnaHRTYW1wbGUgPSByaWdodFtmcmFtZV07CiAgICAgICAgICAgICAgICBjb25zdCBsb3dMZWZ0ID0gdGhpcy5sb3dMZWZ0LnByb2Nlc3MobGVmdFNhbXBsZSk7CiAgICAgICAgICAgICAgICBjb25zdCBsb3dSaWdodCA9IHRoaXMubG93UmlnaHQucHJvY2VzcyhyaWdodFNhbXBsZSk7CiAgICAgICAgICAgICAgICBjb25zdCBoaWdoTGVmdCA9IHRoaXMuaGlnaExlZnQucHJvY2VzcyhsZWZ0U2FtcGxlKTsKICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hSaWdodCA9IHRoaXMuaGlnaFJpZ2h0LnByb2Nlc3MocmlnaHRTYW1wbGUpOwogICAgICAgICAgICAgICAgY29uc3QgbWlkTGVmdCA9IGxlZnRTYW1wbGUgLSBsb3dMZWZ0IC0gaGlnaExlZnQ7CiAgICAgICAgICAgICAgICBjb25zdCBtaWRSaWdodCA9IHJpZ2h0U2FtcGxlIC0gbG93UmlnaHQgLSBoaWdoUmlnaHQ7CiAgICAgICAgICAgICAgICBjb25zdCBsb3dNaWQgPSAobG93TGVmdCArIGxvd1JpZ2h0KSAqIDAuNTsKICAgICAgICAgICAgICAgIGNvbnN0IGxvd1NpZGUgPSAobG93TGVmdCAtIGxvd1JpZ2h0KSAqIDAuNTsKICAgICAgICAgICAgICAgIGNvbnN0IG1pZE1pZCA9IChtaWRMZWZ0ICsgbWlkUmlnaHQpICogMC41OwogICAgICAgICAgICAgICAgY29uc3QgbWlkU2lkZSA9IChtaWRMZWZ0IC0gbWlkUmlnaHQpICogMC41OwogICAgICAgICAgICAgICAgY29uc3QgaGlnaE1pZCA9IChoaWdoTGVmdCArIGhpZ2hSaWdodCkgKiAwLjU7CiAgICAgICAgICAgICAgICBjb25zdCBoaWdoU2lkZSA9IChoaWdoTGVmdCAtIGhpZ2hSaWdodCkgKiAwLjU7CiAgICAgICAgICAgICAgICB3W2ZyYW1lXSA9IGxvd01pZCAqIFdfR0FJTl9MT1cgKyBtaWRNaWQgKiBXX0dBSU5fTUlEICsgaGlnaE1pZCAqIFdfR0FJTl9ISUdIOwogICAgICAgICAgICAgICAgeVtmcmFtZV0gPSBsb3dTaWRlICogWV9HQUlOX0xPVyArIG1pZFNpZGUgKiBZX0dBSU5fTUlEICsgaGlnaFNpZGUgKiBZX0dBSU5fSElHSDsKICAgICAgICAgICAgICAgIHpbZnJhbWVdID0gMDsKICAgICAgICAgICAgICAgIHhbZnJhbWVdID0gbG93TWlkICogWF9HQUlOX0xPVyArIG1pZE1pZCAqIFhfR0FJTl9NSUQgKyBoaWdoTWlkICogWF9HQUlOX0hJR0g7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgY29uc3QgV09SS0xFVF9MT0dfUFJFRklYID0gIltjYWNvcGhvbnkvd29ya2xldDpzdGVyZW8tdG8tYmZvcm1hdF0iOwogICAgY2xhc3MgU3RlcmVvVG9CRm9ybWF0UHJvY2Vzc29yIGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICAgICAgICBmcmFtZXNQcm9jZXNzZWQgPSAwOwogICAgICAgIGZyYW1lc1Nob3J0SW5wdXQgPSAwOwogICAgICAgIGxhc3RSZXBvcnRGcmFtZSA9IDA7CiAgICAgICAgdXBtaXhlciA9IG5ldyBTdGVyZW9Ub0ZvYVVwbWl4ZXIoc2FtcGxlUmF0ZSk7CiAgICAgICAgcHJvY2VzcyhpbnB1dHMsIG91dHB1dHMpIHsKICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBpbnB1dHNbMF07CiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dHNbMF07CiAgICAgICAgICAgIGlmICghaW5wdXQgfHwgaW5wdXQubGVuZ3RoIDwgMiB8fCAhb3V0cHV0IHx8IG91dHB1dC5sZW5ndGggPCA0KSB7CiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lc1Nob3J0SW5wdXQrKzsKICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVzUHJvY2Vzc2VkKys7CiAgICAgICAgICAgICAgICB0aGlzLm1heWJlUmVwb3J0KGlucHV0Py5sZW5ndGggPz8gMCwgInNob3J0LWlucHV0IiwgaW5wdXQsIG91dHB1dCk7CiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnVwbWl4ZXIucHJvY2VzcyhpbnB1dFswXSwgaW5wdXRbMV0sIG91dHB1dFswXSwgb3V0cHV0WzFdLCBvdXRwdXRbMl0sIG91dHB1dFszXSk7CiAgICAgICAgICAgIHRoaXMuZnJhbWVzUHJvY2Vzc2VkKys7CiAgICAgICAgICAgIHRoaXMubWF5YmVSZXBvcnQoaW5wdXQubGVuZ3RoLCAib2siLCBpbnB1dCwgb3V0cHV0KTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIG1heWJlUmVwb3J0KGNoYW5uZWxzLCBraW5kLCBpbnB1dCwgb3V0cHV0KSB7CiAgICAgICAgICAgIGlmICh0aGlzLmZyYW1lc1Byb2Nlc3NlZCAtIHRoaXMubGFzdFJlcG9ydEZyYW1lIDwgNzUwKQogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB0aGlzLmxhc3RSZXBvcnRGcmFtZSA9IHRoaXMuZnJhbWVzUHJvY2Vzc2VkOwogICAgICAgICAgICBsZXQgc3RhdHMgPSAiIjsKICAgICAgICAgICAgaWYgKGlucHV0ICYmIGlucHV0Lmxlbmd0aCA+PSAyICYmIG91dHB1dCAmJiBvdXRwdXQubGVuZ3RoID49IDQpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHBlYWsgPSAoYSkgPT4gewogICAgICAgICAgICAgICAgICAgIGxldCBtID0gMDsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdiA9IE1hdGguYWJzKGFbaV0pOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodiA+IG0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtID0gdjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG07CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgc3RhdHMgPQogICAgICAgICAgICAgICAgICAgIGAgcGVha0w9JHtwZWFrKGlucHV0WzBdKS50b0ZpeGVkKDQpfWAgKwogICAgICAgICAgICAgICAgICAgICAgICBgIHBlYWtSPSR7cGVhayhpbnB1dFsxXSkudG9GaXhlZCg0KX1gICsKICAgICAgICAgICAgICAgICAgICAgICAgYCBwZWFrVz0ke3BlYWsob3V0cHV0WzBdKS50b0ZpeGVkKDQpfWAgKwogICAgICAgICAgICAgICAgICAgICAgICBgIHBlYWtZPSR7cGVhayhvdXRwdXRbMV0pLnRvRml4ZWQoNCl9YCArCiAgICAgICAgICAgICAgICAgICAgICAgIGAgcGVha1o9JHtwZWFrKG91dHB1dFsyXSkudG9GaXhlZCg0KX1gICsKICAgICAgICAgICAgICAgICAgICAgICAgYCBwZWFrWD0ke3BlYWsob3V0cHV0WzNdKS50b0ZpeGVkKDQpfWA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc29sZS5pbmZvKGAke1dPUktMRVRfTE9HX1BSRUZJWH0gcHJvY2VzcyB0aWNrIGZyYW1lc1RvdGFsPSR7dGhpcy5mcmFtZXNQcm9jZXNzZWR9IHNob3J0SW5wdXQ9JHt0aGlzLmZyYW1lc1Nob3J0SW5wdXR9IGNoYW5uZWxzVGhpc1RpY2s9JHtjaGFubmVsc30ga2luZD0ke2tpbmR9JHtzdGF0c31gKTsKICAgICAgICB9CiAgICB9CiAgICBjb25zb2xlLmluZm8oYCR7V09SS0xFVF9MT0dfUFJFRklYfSBtb2R1bGUgZXZhbHVhdGluZ2ApOwogICAgdHJ5IHsKICAgICAgICBjb25zb2xlLmluZm8oYCR7V09SS0xFVF9MT0dfUFJFRklYfSByZWdpc3RlclByb2Nlc3NvciBzdGFydGApOwogICAgICAgIHJlZ2lzdGVyUHJvY2Vzc29yKCJzdGVyZW8tdG8tYmZvcm1hdCIsIFN0ZXJlb1RvQkZvcm1hdFByb2Nlc3Nvcik7CiAgICAgICAgY29uc29sZS5pbmZvKGAke1dPUktMRVRfTE9HX1BSRUZJWH0gcmVnaXN0ZXJQcm9jZXNzb3IgY29tcGxldGVgKTsKICAgIH0KICAgIGNhdGNoIChlcnJvcikgewogICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7V09SS0xFVF9MT0dfUFJFRklYfSByZWdpc3RlclByb2Nlc3NvciBmYWlsZWRgLCBlcnJvcik7CiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICB9CgogICAgZXhwb3J0cy5TdGVyZW9Ub0JGb3JtYXRQcm9jZXNzb3IgPSBTdGVyZW9Ub0JGb3JtYXRQcm9jZXNzb3I7CgogICAgcmV0dXJuIGV4cG9ydHM7Cgp9KSh7fSk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0ZXJlby10by1iZm9ybWF0LWJ1bmRsZS5qcy5tYXAK";class G{listeners={};on(e,t){return this.listeners[e]=this.listeners[e]??[],this.listeners[e].push({fn:t,once:!1}),()=>this.off(e,t)}once(e,t){return this.listeners[e]=this.listeners[e]??[],this.listeners[e].push({fn:t,once:!0}),()=>this.off(e,t)}off(e,t){const g=this.listeners[e];g&&(this.listeners[e]=g.filter(s=>s.fn!==t))}emit(e,t){const g=this.listeners[e];g&&(g.forEach(s=>s.fn(t)),this.listeners[e]=g.filter(s=>!s.once))}emitAsync(e,t){const g=this.listeners[e];if(g){const s=g.map(o=>Promise.resolve().then(()=>o.fn(t)).catch(I=>console.error(`Error in listener for event ${e}:`,I)));return this.listeners[e]=g.filter(o=>!o.once),Promise.all(s).then(()=>{})}return Promise.resolve()}removeAllListeners(){this.listeners={}}}class w{constructor(e=[]){this.sounds=e}_position=[0,0,0];loopCount=0;playIndex=0;preplayRandom(){if(this.sounds.length===0)return;const t=this.randomSound().preplay();return t.length>0?t[0]:void 0}playRandom(){const e=this.preplayRandom();return e&&e.play(),e}preplayOrdered(e=!0){if(this.sounds.length===0||this.playIndex>=this.sounds.length)return;const g=this.sounds[this.playIndex].preplay();if(g.length!==0)return this.playIndex=(this.playIndex+1)%this.sounds.length,!e&&this.playIndex===0&&(this.playIndex=this.sounds.length),g[0]}playOrdered(e=!0){const t=this.preplayOrdered(e);return t&&t.play(),t}get duration(){return this.sounds.map(e=>e.duration).reduce((e,t)=>Math.max(e,t),0)}seek(e){this.sounds.forEach(t=>t.seek?.(e))}addSound(e){this.sounds.push(e)}randomSound(){if(this.sounds.length===0)throw new Error("Cannot get a random sound from an empty group");const e=Math.floor(Math.random()*this.sounds.length);return this.sounds[e]}preplay(){return this.sounds.map(t=>t.preplay()).flat()}play(){const e=[];return this.preplay().forEach(t=>{t.play(),e.push(t)}),e}get isPlaying(){return this.sounds.some(e=>e.isPlaying)}stop(){this.sounds.forEach(e=>e.stop())}pause(){this.sounds.forEach(e=>e.pause())}fadeTo(e,t,g){return Promise.all(this.sounds.map(s=>s.fadeTo(e,t,g))).then(()=>{})}fadeIn(e,t){return Promise.all(this.sounds.map(g=>g.fadeIn(e,t))).then(()=>{})}fadeOut(e,t){return Promise.all(this.sounds.map(g=>g.fadeOut(e,t))).then(()=>{})}stopWithFade(e,t){return Promise.all(this.sounds.map(g=>g.stopWithFade(e,t))).then(()=>{})}loop(e){return e===void 0?this.loopCount:(this.loopCount=e,this.sounds.forEach(t=>t.loop(e)),this.loopCount)}addFilter(e){this.sounds.forEach(t=>t.addFilter(e))}removeFilter(e){this.sounds.forEach(t=>t.removeFilter(e))}set position(e){this._position=e,this.sounds.forEach(t=>t.position=this._position)}get position(){return this._position}get volume(){return this.sounds.length===0?1:this.sounds.map(e=>e.volume).reduce((e,t)=>e+t,0)/this.sounds.length}set volume(e){this.sounds.forEach(t=>t.volume=e)}get playbackRate(){return this.sounds.length===0?1:this.sounds[0].playbackRate}set playbackRate(e){this.sounds.forEach(t=>t.playbackRate=e)}}class y{_filters=[];addFilter(e){if(this._filters.includes(e))throw new Error("Cannot add the same filter instance twice");this._filters.push(e)}removeFilter(e){const t=this._filters.length;if(this._filters=this._filters.filter(g=>g!==e),this._filters.length===t)throw new Error("Cannot remove filter that was never added to this container")}applyFilters(e){return this._filters.reduce((t,g)=>(t.connect(g),g),e),this._filters.length>0?this._filters[this._filters.length-1]:e}get filters(){return this._filters}addFilters(e){e.forEach(t=>this.addFilter(t))}removeFilters(e){e.forEach(t=>this.removeFilter(t))}cleanup(){this._filters.forEach(e=>e.disconnect()),this._filters=[]}}class X extends y{context;source;gainNode;panner;constructor(e,t,g,s=0){super(),this.source=e,this.gainNode=t,this.context=g,this.panner=g.createPanner(),e.connect(this.panner).connect(this.gainNode),this.refreshFilters()}get duration(){return 0}play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");return[this]}get isPlaying(){return!!this.source}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(e){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=e}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.stop())}pause(){if(!this.source)throw new Error("Cannot pause a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.enabled=!1)}resume(){if(!this.source)throw new Error("Cannot resume a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.enabled=!0)}addFilter(e){super.addFilter(e),this.refreshFilters()}removeFilter(e){super.removeFilter(e),this.refreshFilters()}set position(e){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");const[t,g,s]=e;this.panner.positionX.value=t,this.panner.positionY.value=g,this.panner.positionZ.value=s}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");return[this.panner.positionX.value,this.panner.positionY.value,this.panner.positionZ.value]}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}get playbackRate(){return 1}set playbackRate(e){}}class T extends y{context;_position=[0,0,0];loopCount=0;prevVolume=1;microphoneGainNode;streamPlayback;stream;streamSource;constructor(e,t){super(),this.context=e,this.microphoneGainNode=this.context.createGain(),t&&(this.stream=t,this.streamSource=this.createStreamSource(t))}createStreamSource(e){if(!this.context.createMediaStreamSource)throw new Error("Media stream sources are not supported on this audio context (e.g. OfflineAudioContext).");return this.context.createMediaStreamSource(e)}play(){return this.stream?(this.streamPlayback||(this.streamSource=this.streamSource??this.createStreamSource(this.stream),this.streamPlayback=new X(this.streamSource,this.microphoneGainNode,this.context)),[this.streamPlayback]):(navigator.mediaDevices.getUserMedia({audio:!0}).then(e=>{this.stream=e,this.streamSource=this.createStreamSource(this.stream),this.streamPlayback=new X(this.streamSource,this.microphoneGainNode,this.context),this.streamPlayback.play()}).catch(e=>{console.error("Error initializing microphone stream:",e)}),[])}get duration(){return 0}seek(e){}get isPlaying(){return!!this.streamPlayback}stop(){this.streamPlayback&&(this.streamPlayback.stop(),this.streamPlayback=void 0)}pause(){this.streamPlayback&&this.streamPlayback.pause()}resume(){this.streamPlayback&&this.streamPlayback.resume()}addFilter(e){this.streamPlayback&&this.streamPlayback.addFilter(e)}removeFilter(e){this.streamPlayback&&this.streamPlayback.removeFilter(e)}get volume(){return this.streamPlayback?this.streamPlayback.volume:0}set volume(e){this.streamPlayback&&(this.streamPlayback.volume=e)}get position(){return[0,0,0]}set position(e){}loop(e){return 0}get playbackRate(){return 1}set playbackRate(e){}}function J(A){class e extends A{playbacks=[];_position=[0,0,0];_stereoPan=0;_threeDOptions={coneInnerAngle:360,coneOuterAngle:360,coneOuterGain:0,distanceModel:"inverse",maxDistance:1e4,channelCount:2,channelCountMode:"clamped-max",channelInterpretation:"speakers",panningModel:"HRTF",refDistance:1,rolloffFactor:1,positionX:0,positionY:0,positionZ:0,orientationX:0,orientationY:0,orientationZ:0};_volume=1;play(){const g=this.preplay();return g.forEach(s=>s.play()),g}stop(){this.playbacks.forEach(g=>{g.stop(),g.cleanup()}),this.playbacks=[]}pause(){this.playbacks.forEach(g=>g.pause())}addFilter(g){super.addFilter(g)}removeFilter(g){super.removeFilter(g)}get isPlaying(){return this.playbacks.some(g=>g.isPlaying)}get position(){return[this._threeDOptions.positionX,this._threeDOptions.positionY,this._threeDOptions.positionZ]}set position(g){this._threeDOptions.positionX=g[0],this._threeDOptions.positionY=g[1],this._threeDOptions.positionZ=g[2],this.playbacks.forEach(s=>s.position=g)}get threeDOptions(){return this._threeDOptions}set threeDOptions(g){this._threeDOptions={...this._threeDOptions,...g},this.playbacks.forEach(s=>s.threeDOptions=this._threeDOptions)}get stereoPan(){return this._stereoPan}set stereoPan(g){this._stereoPan=g,this.playbacks.forEach(s=>s.stereoPan=g)}get volume(){return this._volume}set volume(g){this._volume=g,this.playbacks.forEach(s=>s.volume=g)}fadeTo(g,s,o){return this._volume=g,Promise.all(this.playbacks.map(I=>I.fadeTo(g,s,o))).then(()=>{})}fadeIn(g,s){return Promise.all(this.playbacks.map(o=>o.fadeIn(g,s))).then(()=>{})}fadeOut(g,s){return Promise.all(this.playbacks.map(o=>o.fadeOut(g,s))).then(()=>{})}stopWithFade(g,s){return this.fadeOut(g,s).then(()=>this.stop())}}return e}function H(A){class e extends A{panner;_panType="stereo";get panType(){return this._panType}setPanType(g,s){this._panType===g&&this.panner||(this.panner&&this.panner.disconnect(),this._panType=g,g==="stereo"?this.panner=s.createStereoPanner():this.panner=s.createPanner())}setPannerNode(g){this.panner=g}get stereoPan(){return this.panType==="stereo"?this.panner.pan.value:null}set stereoPan(g){if(this.panType!=="stereo")throw new Error("Stereo panning is not available when using HRTF.");if(!this.panner)throw new Error("Cannot set stereo pan of a sound that has been cleaned up");if(g<-1||g>1)throw new RangeError("Stereo pan must be between -1 and 1.");this.panner.pan.setValueAtTime(g,this.panner.context.currentTime)}get threeDOptions(){if(!this.panner)throw new Error("Cannot get 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get 3D options of a sound that is not using HRTF");const g=this.panner;return{coneInnerAngle:g.coneInnerAngle,coneOuterAngle:g.coneOuterAngle,coneOuterGain:g.coneOuterGain,distanceModel:g.distanceModel,maxDistance:g.maxDistance,channelCount:this.panner.channelCount,channelCountMode:g.channelCountMode,channelInterpretation:g.channelInterpretation,panningModel:g.panningModel,refDistance:g.refDistance,rolloffFactor:g.rolloffFactor,positionX:g.positionX.value,positionY:g.positionY.value,positionZ:g.positionZ.value,orientationX:g.orientationX.value,orientationY:g.orientationY.value,orientationZ:g.orientationZ.value}}set threeDOptions(g){if(!this.panner)throw new Error("Cannot set 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot set 3D options of a sound that is not using HRTF");const s=this.panner;s.coneInnerAngle=g.coneInnerAngle!==void 0?g.coneInnerAngle:s.coneInnerAngle,s.coneOuterAngle=g.coneOuterAngle!==void 0?g.coneOuterAngle:s.coneOuterAngle,s.coneOuterGain=g.coneOuterGain!==void 0?g.coneOuterGain:s.coneOuterGain,s.distanceModel=g.distanceModel||s.distanceModel,s.maxDistance=g.maxDistance!==void 0?g.maxDistance:s.maxDistance,s.channelCount=g.channelCount!==void 0?g.channelCount:s.channelCount,s.channelCountMode=g.channelCountMode||s.channelCountMode,s.channelInterpretation=g.channelInterpretation||s.channelInterpretation,s.panningModel=g.panningModel||s.panningModel,s.refDistance=g.refDistance!==void 0?g.refDistance:s.refDistance,s.rolloffFactor=g.rolloffFactor!==void 0?g.rolloffFactor:s.rolloffFactor,s.positionX.value=g.positionX!==void 0?g.positionX:s.positionX.value,s.positionY.value=g.positionY!==void 0?g.positionY:s.positionY.value,s.positionZ.value=g.positionZ!==void 0?g.positionZ:s.positionZ.value,s.orientationX.value=g.orientationX!==void 0?g.orientationX:s.orientationX.value,s.orientationY.value=g.orientationY!==void 0?g.orientationY:s.orientationY.value,s.orientationZ.value=g.orientationZ!==void 0?g.orientationZ:s.orientationZ.value}set position(g){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot move a sound that is not using HRTF");const[s,o,I]=g,n=this.panner;n.positionX.value=s,n.positionY.value=o,n.positionZ.value=I}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get position of a sound that is not using HRTF");const g=this.panner;return[g.positionX.value,g.positionY.value,g.positionZ.value]}cleanup(){this.panner&&(this.panner.disconnect(),this.panner=void 0),super.cleanup()}}return e}function F(A){class e extends A{gainNode;_fadeTimeout;_isFading=!1;setGainNode(g){this.gainNode=g}cleanup(){this.cancelFade(),this.gainNode&&(this.gainNode.disconnect(),this.gainNode=void 0),super.cleanup()}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(g){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.cancelFade(),this.gainNode.gain.value=g}get isFading(){return this._isFading}fadeTo(g,s,o="linear"){if(!this.gainNode)throw new Error("Cannot fade a sound that has been cleaned up");this.cancelFade();const I=this.gainNode.context.currentTime,n=I+s/1e3;return this.gainNode.gain.setValueAtTime(this.gainNode.gain.value,I),o==="exponential"?this.gainNode.gain.exponentialRampToValueAtTime(g===0?1e-4:g,n):this.gainNode.gain.linearRampToValueAtTime(g,n),this._isFading=!0,new Promise(i=>{this._fadeTimeout=setTimeout(()=>{this._isFading=!1,g===0&&o==="exponential"&&this.gainNode&&(this.gainNode.gain.value=0),i()},s)})}cancelFade(){if(this._fadeTimeout&&(clearTimeout(this._fadeTimeout),this._fadeTimeout=void 0),this._isFading&&this.gainNode){const g=this.gainNode.context.currentTime;this.gainNode.gain.cancelScheduledValues(g),this.gainNode.gain.setValueAtTime(this.gainNode.gain.value,g)}this._isFading=!1}fadeIn(g,s){if(!this.gainNode)throw new Error("Cannot fade a sound that has been cleaned up");const o=this.gainNode.gain.value;return this.gainNode.gain.setValueAtTime(1e-4,this.gainNode.context.currentTime),this.fadeTo(o,g,s)}fadeOut(g,s){return this.fadeTo(0,g,s)}}return e}class K extends H(F(y)){source;_playing=!1;origin;eventEmitter=new G;constructor(){super()}get isPlaying(){return this.source?this._playing:!1}on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}fadeTo(e,t,g="linear"){return this.emit("fadeStart",{target:e,duration:t,type:g}),super.fadeTo(e,t,g).then(()=>{this.emit("fadeEnd",void 0)})}cancelFade(){const e=this._isFading;super.cancelFade(),e&&this.emit("fadeCancel",void 0)}cleanup(){this.eventEmitter.removeAllListeners(),super.cleanup()}}class Z extends K{constructor(e,t,g){super(),this.origin=e,this.context=e.context,this.loopCount=e.loopCount,this.setPanType(e.panType,e.context),this.source=t,"buffer"in t&&t.buffer&&(this.buffer=t.buffer),this.setupSourceNode(t),this.source.connect(this.panner),this.setGainNode(g),this.panner.connect(this.gainNode),this.refreshFilters()}context;loopCount=0;currentLoop=0;buffer;_offset=0;_startTime=0;_state=0;_playbackRate=1;_fadeInConfig;_fadeOutConfig;_loopEndCallback;setupSourceNode(e){if("mediaElement"in e&&e.mediaElement)e.mediaElement.onended=this.loopEnded;else if("onended"in e)e.onended=this.loopEnded;else throw new Error("Unsupported source type")}get isPlaying(){return this._state===1}get duration(){if(!this.source)throw new Error("Cannot get duration of a sound that has been cleaned up");return"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.duration:this.buffer?this.buffer.duration||NaN:NaN}get playbackRate(){return this._playbackRate}get volume(){return super.volume}set volume(e){super.volume=e,this.emit("volumeChange",e)}set playbackRate(e){if(e<=0)throw new Error("Playback rate must be greater than 0");if(this._state===1){const t=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=t,this._startTime=this.context.currentTime}this._playbackRate=e,this.source&&("playbackRate"in this.source&&(this.source.playbackRate.value=e),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.playbackRate=e))}loopEnded=()=>{!this.source||this._state!==1||(this.currentLoop++,this.loopCount!=="infinite"&&this.currentLoop>this.loopCount?(this.emit("ended",void 0),this._fadeOutConfig?this.fadeOut(this._fadeOutConfig.duration,this._fadeOutConfig.type).then(()=>{this.stop(),this.removeFromOrigin()}):(this.stop(),this.removeFromOrigin())):(this._loopEndCallback?.(),this.seek(0),this._state!==1&&!("mediaElement"in this.source)&&this.play(),this._fadeInConfig?.perLoop&&this.gainNode&&(this.gainNode.gain.setValueAtTime(1e-4,this.gainNode.context.currentTime),this.fadeTo(this._fadeInConfig.targetVolume,this._fadeInConfig.duration,this._fadeInConfig.type))))};play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");if(this._state===1)return[this];const e=this._state===2;try{let t;if(this._state===2?"mediaElement"in this.source&&this.source.mediaElement?t=this.source.mediaElement.play():(this.recreateSource(),"start"in this.source&&this.source.start&&this.source.start(0,this._offset)):"mediaElement"in this.source&&this.source.mediaElement?(this.source.mediaElement.currentTime=this._offset,t=this.source.mediaElement.play()):"start"in this.source&&this.source.start&&(this.recreateSource(),this.source.start(0,this._offset)),t){const g=this._state;t.then(()=>{this._startTime=this.context.currentTime,this._state=1,this.emit("play",this),e&&this.emit("resume",void 0),this.origin.cacophony?.emit("globalPlay",{source:this.origin,timestamp:Date.now()})},s=>{this._state=g,this.emitAsync("error",{error:s,errorType:"source",timestamp:Date.now(),recoverable:!0})})}else this._startTime=this.context.currentTime,this._state=1,this.emit("play",this),e&&this.emit("resume",void 0),this.origin.cacophony?.emit("globalPlay",{source:this.origin,timestamp:Date.now()});return[this]}catch(t){throw this.emitAsync("error",{error:t,errorType:"source",timestamp:Date.now(),recoverable:!0}),t}}pause(){if(!this.source||this._state!==1)return;const e=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=e,"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.pause():"stop"in this.source&&this.source.stop(),this._state=2,this.emit("pause",void 0),this.origin.cacophony?.emit("globalPause",{source:this.origin,timestamp:Date.now()})}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this._state===3||this._state===0||(this.cancelFade(),"stop"in this.source&&this._state===1&&this.source.stop(),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.pause(),this.source.mediaElement.currentTime=0),this._offset=0,this._startTime=0,this._state=3,this.emit("stop",void 0),this.origin.cacophony?.emit("globalStop",{source:this.origin,timestamp:Date.now()}))}fadeIn(e,t,g){return g?.perLoop&&(this._fadeInConfig={duration:e,type:t||"linear",perLoop:!0,targetVolume:this.gainNode.gain.value}),super.fadeIn(e,t)}configureFadeOut(e,t){this._fadeOutConfig={duration:e,type:t||"linear"}}stopWithFade(e,t){return this.fadeOut(e,t).then(()=>this.stop())}seek(e){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot seek a sound that has been cleaned up");if(!Number.isFinite(e)||e<0)throw new Error("Invalid time value for seek");const t=this._state===1;t&&this.pause(),this._offset=e,"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.currentTime=e),t&&this.play()}get currentTime(){if(this._state===1){const e=(this.context.currentTime-this._startTime)*this._playbackRate;return this._offset+e}else return this._offset}removeFromOrigin(){const e=this.origin.playbacks.indexOf(this);e!==-1&&this.origin.playbacks.splice(e,1)}recreateSource(){if(!this.buffer||!this.panner||!this.context||!this.gainNode)throw new Error("Cannot recreate source of a sound that has been cleaned up");try{this.source&&(!("mediaElement"in this.source)&&"onended"in this.source&&(this.source.onended=null),this.source.disconnect()),this.source=this.context.createBufferSource(),this.source.buffer=this.buffer,this.source.connect(this.panner),this.source.onended=this.loopEnded,this.playbackRate=this._playbackRate,this.refreshFilters()}catch(e){throw this.emitAsync("error",{error:e,errorType:"source",timestamp:Date.now(),recoverable:!1}),e}}set sourceLoop(e){if(!this.source)throw new Error("Cannot set loop on a sound that has been cleaned up");"loop"in this.source&&(this.source.loop=e),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.loop=e)}cleanup(){this.source&&("mediaElement"in this.source&&this.source.mediaElement?(this.source.mediaElement.pause(),this.source.mediaElement.currentTime=0,this.source.mediaElement.loop=!1,this.source.mediaElement.onended=null):"onended"in this.source&&(this.source.onended=null),this._offset=0,this._startTime=0,this._state=3,this.currentLoop=0,this.source.disconnect(),this.source=void 0,super.cleanup())}assertNotCleanedUp(){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot perform operation on a sound that has been cleaned up")}addFilter(e){this.assertNotCleanedUp(),super.addFilter(e),this.refreshFilters()}removeFilter(e){this.assertNotCleanedUp(),super.removeFilter(e),this.refreshFilters()}loop(e){if(!this.source)throw new Error("Cannot loop a sound that has been cleaned up");if(e!==void 0&&(this.loopCount=e==="infinite"?"infinite":Math.max(0,e),this.currentLoop=0),"mediaElement"in this.source&&this.source.mediaElement){const t=this.source.mediaElement;t.loop=this.loopCount==="infinite"}else if("loop"in this.source)this.source.loop=this.loopCount==="infinite",this.source.buffer&&(this.source.loopEnd=this.source.buffer.duration,this.source.loopStart=0);else throw new Error("Unsupported source type");return this.loopCount}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}get outputNode(){if(!this.gainNode)throw new Error("Cannot access output node of a playback that has been cleaned up");return this.gainNode}connect(e){return this.outputNode.connect(e)}disconnect(e){e?this.outputNode.disconnect(e):this.outputNode.disconnect()}clone(e={}){if(!this.source||!this.gainNode||!this.context)throw new Error("Cannot clone a sound that has been cleaned up");const t=e.panType||this.panType,g=this.context.createGain();let s;if("buffer"in this.source&&this.source.buffer)s=this.context.createBufferSource(),s.buffer=this.source.buffer;else if("mediaElement"in this.source&&this.source.mediaElement){if(!this.context.createMediaElementSource)throw new Error("Media element sources are not supported on this audio context.");s=this.context.createMediaElementSource(this.source.mediaElement)}else throw new Error("Unsupported source type");const o=e.loopCount!==void 0?e.loopCount:this.loopCount,I=new Z(this.origin,s,g);return I.loopCount=o,I.currentLoop=this.currentLoop,I.setPanType(t,this.context),I.volume=this.volume,I.playbackRate=this._playbackRate,I._offset=this._offset,I._state=this._state,this._filters.forEach(n=>{const i=this.context.createBiquadFilter();i.type=n.type,i.frequency.value=n.frequency.value,i.Q.value=n.Q.value,i.gain.value=n.gain.value,I.addFilter(i)}),this._state===1&&I.play(),I}}class b extends J(y){constructor(e,t,g,s,o=f.Buffer,I="HRTF",n){super(),this.url=e,this.globalGainNode=s,this.soundType=o,this.panType=I,this._cacophony=n,this.buffer=t,this.context=g,this._cacophony?.registerSoundForCleanup(this,this._holdings,this._unregisterToken)}buffer;context;loopCount=0;_playbackRate=1;eventEmitter=new G;_holdings={sources:[],gainNodes:[],mediaElements:[]};_unregisterToken={};get cacophony(){return this._cacophony}get volume(){return super.volume}on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}clone(e={}){const t=e.panType||this.panType,g=e.stereoPan!==void 0?e.stereoPan:this.stereoPan,s=e.threeDOptions||this.threeDOptions,o=e.loopCount!==void 0?e.loopCount:this.loopCount,I=e.playbackRate||this.playbackRate,n=e.volume!==void 0?e.volume:this.volume,i=e.position!==void 0?e.position:this.position,C=e.filters?.length?e.filters:this._filters,a=new b(this.url,this.buffer,this.context,this.globalGainNode,this.soundType,t,this.cacophony);return a.loop(o),a.playbackRate=I,a.volume=n,t==="HRTF"?(a.threeDOptions=s,a.position=i):a.stereoPan=g,a.addFilters(C),a}preplay(){try{let e;if(this.buffer)e=this.context.createBufferSource(),e.buffer=this.buffer;else{if(!this.context.createMediaElementSource)throw new Error("Media element sources are not supported on this audio context (e.g. OfflineAudioContext). Use buffer-based sounds instead.");const s=new Audio;s.crossOrigin="anonymous",s.src=this.url,s.preload="auto",e=this.context.createMediaElementSource(s)}const t=this.context.createGain();t.connect(this.globalGainNode);const g=new Z(this,e,t);return this._holdings.sources.push(e),this._holdings.gainNodes.push(t),"mediaElement"in e&&e.mediaElement&&this._holdings.mediaElements.push(e.mediaElement),g.setGainNode(t),g.volume=this.volume,g.playbackRate=this.playbackRate,this._filters.forEach(s=>{const o=this.context.createBiquadFilter();o.type=s.type,o.frequency.value=s.frequency.value,o.Q.value=s.Q.value,o.gain.value=s.gain.value,g.addFilter(o)}),this.panType==="HRTF"?(g.threeDOptions=this.threeDOptions,g.position=this.position):this.panType==="stereo"&&(g.stereoPan=this.stereoPan),g.on("ended",()=>{this.emit("ended",void 0)}),g._loopEndCallback=()=>{this.emit("loopEnd",void 0)},g.on("error",s=>{this.emitAsync("soundError",{url:this.url,error:s.error,errorType:"playback",timestamp:s.timestamp,recoverable:s.recoverable})}),this.playbacks.push(g),[g]}catch(e){const t={url:this.url,error:e,errorType:"playback",timestamp:Date.now(),recoverable:!0};throw this.emitAsync("soundError",t),e}}play(e){const t=this.preplay();for(const g of t){const s=I=>{o(),this.emit("play",I)},o=()=>{g.off("play",s),g.off("error",o)};g.on("play",s),g.on("error",o);try{g.play()}catch(I){throw o(),I}}if(e)for(const g of t)e.fadeIn!==void 0&&g.fadeIn(e.fadeIn,e.fadeType,{perLoop:e.fadeInPerLoop}),e.fadeOut!==void 0&&g.configureFadeOut(e.fadeOut,e.fadeType);return t}stop(){this._holdings.sources.length=0,this._holdings.gainNodes.length=0,this._holdings.mediaElements.length=0,super.stop(),this.emit("stop",void 0)}pause(){super.pause(),this.emit("pause",void 0)}resume(){this.playbacks.forEach(e=>e.play()),this.emit("resume",void 0)}seek(e){this.playbacks.forEach(t=>t.seek(e))}get duration(){return this.playbacks.length>0?this.playbacks[0].duration:this.buffer?.duration||NaN}loop(e){return e===void 0?this.loopCount:(this.loopCount=e,this.playbacks.forEach(t=>t.loop(e)),this.loopCount)}get playbackRate(){return this._playbackRate}set playbackRate(e){this._playbackRate=e,this.playbacks.forEach(t=>t.playbackRate=e),this.emit("rateChange",e)}set volume(e){super.volume=e,this.emit("volumeChange",e)}cleanup(){this._cacophony?.unregisterSoundCleanup(this._unregisterToken),this._holdings.sources.length=0,this._holdings.gainNodes.length=0,this._holdings.mediaElements.length=0,this.playbacks.forEach(e=>e.cleanup()),this.playbacks=[],this.eventEmitter.removeAllListeners()}}function M(A){class e extends K{_oscillatorOptions={};get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(g){this._oscillatorOptions=g,this.source&&(this.oscillatorOptions.detune!==void 0&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type))}play(){if(!this.source)throw new Error("No source node found");return this.oscillatorOptions.detune!==void 0&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type),this.source.start(),this._playing=!0,[this]}stop(){this.source?.stop&&(this.source.stop(),this._playing=!1)}pause(){this.stop()}get frequency(){return this.source.frequency.value}set frequency(g){this.source.frequency.value=g,this.oscillatorOptions.frequency=g}get detune(){return this.source.detune.value}set detune(g){this.source.detune.value=g,this.oscillatorOptions.detune=g}get type(){return this.source.type}set type(g){this.source.type=g,this.oscillatorOptions.type=g}}return e}class x extends M(H(F(y))){constructor(e,t,g){super(),this.origin=e,this.source=t,this.context=e.context,this.setPanType(e.panType,e.context),this.source.connect(this.panner),this.setGainNode(g),this.panner.connect(this.gainNode),this.refreshFilters(),this.oscillatorOptions={detune:t.detune.value,frequency:t.frequency.value,type:t.type}}context;_state=0;play(){if(!this.source||!this.panner)throw new Error("Cannot play a synth that has been cleaned up");return this._state===1?[this]:((this._state===2||this._state===3)&&this.recreateSource(),this.oscillatorOptions.detune!==void 0&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type),this.source.start(),this._playing=!0,this._state=1,[this])}pause(){!this.source||this._state!==1||(this.source.stop(),this._playing=!1,this._state=2)}stop(){!this.source||this._state===0||this._state===3||(this._state===1&&this.source.stop(),this._playing=!1,this._state=3)}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}cleanup(){this.panner&&this.gainNode&&(this.source.disconnect(this.panner),this.panner.disconnect(),this.gainNode.disconnect()),this.eventEmitter.removeAllListeners()}recreateSource(){if(!this.panner)throw new Error("Cannot recreate source of a synth that has been cleaned up");this.source.disconnect(),this.source=this.context.createOscillator(),this.source.connect(this.panner)}}class B extends J(y){constructor(e,t,g=f.Oscillator,s="HRTF",o={},I){super(),this.context=e,this.globalGainNode=t,this.soundType=g,this.panType=s,this.cacophony=I,this.context=e,this._oscillatorOptions=o}_oscillatorOptions;playbacks=[];eventEmitter=new G;on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}clone(e={}){const t=e.panType||this.panType,g=e.stereoPan!==void 0?e.stereoPan:this.stereoPan??0,s=e.threeDOptions||this.threeDOptions,o=e.volume!==void 0?e.volume:this.volume,I=e.position?.length?e.position:this.position,n=e.filters?.length?e.filters:this._filters,i=e.oscillatorOptions||this._oscillatorOptions,C=new B(this.context,this.globalGainNode,this.soundType,t,i,this.cacophony);return C._volume=o,C._position=I,C._stereoPan=g,C._threeDOptions=s,C.addFilters(n),C}preplay(){const e=this.context.createOscillator();return this.createPlayback(e)}createPlayback(e){this.oscillatorOptions.detune!==void 0&&(e.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(e.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(e.type=this.oscillatorOptions.type);const t=this.context.createGain();t.connect(this.globalGainNode);const g=new x(this,e,t);return g.volume=this.volume,this._filters.forEach(s=>{const o=this.context.createBiquadFilter();o.type=s.type,o.frequency.value=s.frequency.value,o.Q.value=s.Q.value,o.gain.value=s.gain.value,g.addFilter(o)}),this.panType==="HRTF"?(g.threeDOptions=this.threeDOptions,g.position=this.position):this.panType==="stereo"&&(g.stereoPan=this.stereoPan),this.playbacks.push(g),[g]}play(){const e=super.play();return this.emit("play",e[0]),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()}),e}stop(){super.stop(),this.emit("stop",void 0),this.cacophony?.emit("globalStop",{source:this,timestamp:Date.now()})}pause(){super.pause(),this.emit("pause",void 0),this.cacophony?.emit("globalPause",{source:this,timestamp:Date.now()})}resume(){this.playbacks.forEach(e=>e.play()),this.emit("resume",void 0),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()})}get volume(){return super.volume}set volume(e){super.volume=e,this.emit("volumeChange",e)}get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(e){this._oscillatorOptions=e,this.playbacks.forEach(t=>{t.source&&(this.oscillatorOptions.detune!==void 0&&(t.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(t.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(t.source.type=this.oscillatorOptions.type))})}get frequency(){return this.oscillatorOptions.frequency??440}set frequency(e){this._oscillatorOptions.frequency=e,this.playbacks.forEach(t=>t.frequency=e),this.emit("frequencyChange",e)}get detune(){return this.oscillatorOptions.detune}set detune(e){this._oscillatorOptions.detune=e,this.playbacks.forEach(t=>t.detune=e),this.emit("detuneChange",e)}get type(){return this.oscillatorOptions.type||"sine"}set type(e){this._oscillatorOptions.type=e,this.playbacks.forEach(t=>t.type=e),this.emit("typeChange",e)}}var f=(A=>(A.HTML="HTML",A.Streaming="Streaming",A.Buffer="Buffer",A.Oscillator="oscillator",A))(f||{});const u="[cacophony/worklet]";class V{context;globalGainNode;listener;prevVolume=1;loadedAudioWorklets=new Set;finalizationRegistry;eventEmitter=new G;cache;createAudioWorkletNode;constructor(e,t,g={}){this.context=e||new AudioContext,this.listener=this.context.listener,this.globalGainNode=this.context.createGain(),this.globalGainNode.connect(this.context.destination),this.cache=t||new r,this.createAudioWorkletNode=g.createAudioWorkletNode||((s,o,I)=>new AudioWorkletNode(s,o,I)),this.finalizationRegistry=new FinalizationRegistry(s=>{for(const o of s.sources)o.disconnect();for(const o of s.gainNodes)o.disconnect();for(const o of s.mediaElements)o.pause(),o.removeAttribute("src"),o.load()})}registerSoundForCleanup(e,t,g){this.finalizationRegistry.register(e,t,g)}unregisterSoundCleanup(e){this.finalizationRegistry.unregister(e)}static createOffline(e,t){const g=e.context||new OfflineAudioContext(e.numberOfChannels,e.length,e.sampleRate);return new V(g,t)}get isOffline(){return typeof this.context.startRendering=="function"}async startRendering(){if(typeof this.context.startRendering!="function")throw new Error("startRendering() is only available on offline audio contexts. Use Cacophony.createOffline() to create one.");return this.context.startRendering()}on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}async loadWorklets(e){this.context.audioWorklet?(await this.createWorkletNode("phase-vocoder",D,e),await this.loadStereoToBFormatWorklet(e)):console.warn("AudioWorklet not supported")}async loadStereoToBFormatWorklet(e){await this.loadAudioWorkletModule("stereo-to-bformat",v,e)}async createWorkletNode(e,t,g,s){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");try{const o=this.createAudioWorkletNode(this.context,e,s);return console.info(`${u} construct succeeded`,{name:e,loaded:this.loadedAudioWorklets.has(e)}),o}catch(o){console.warn(`${u} construct failed`,{name:e,loaded:this.loadedAudioWorklets.has(e),error:o});try{await this.loadAudioWorkletModule(e,t,g)}catch(I){throw console.error(`${u} load failed`,{name:e,error:I}),I}try{const I=this.createAudioWorkletNode(this.context,e,s);return console.info(`${u} construct after load succeeded`,{name:e}),I}catch(I){throw console.error(`${u} construct after load failed`,{name:e,error:I}),I}}}async createStereoToBFormatNode(e){return this.createWorkletNode("stereo-to-bformat",v,e,{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[4],channelCount:2,channelCountMode:"explicit",channelInterpretation:"speakers"})}async loadAudioWorkletModule(e,t,g){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");if(this.loadedAudioWorklets.has(e)){console.info(`${u} load skipped`,{name:e});return}console.info(`${u} addModule start`,{name:e,url:t,aborted:g?.aborted??!1});try{await this.context.audioWorklet.addModule(t,{credentials:"same-origin",...g&&{signal:g}}),this.loadedAudioWorklets.add(e),console.info(`${u} addModule resolved`,{name:e})}catch(s){throw console.error(`${u} addModule rejected`,{name:e,error:s}),s}}createAbortError(){return new DOMException("Operation was aborted","AbortError")}createMediaSound(e,t,g,s){return s?.aborted?Promise.reject(this.createAbortError()):new Promise((o,I)=>{const n=new Audio;let i=!1;const C=()=>{n.removeEventListener("loadedmetadata",h),n.removeEventListener("error",p),s?.removeEventListener("abort",m)},a=()=>{n.pause(),n.src="",n.load()},c=d=>{i||(i=!0,C(),d())},h=()=>{c(()=>{o(new b(e,void 0,this.context,this.globalGainNode,t,g,this))})},p=()=>{const d=new Error(`Failed to load audio from ${e}`);c(()=>{a(),I(d)})},m=()=>{const d=this.createAbortError();c(()=>{a(),I(d)})};n.crossOrigin="anonymous",n.preload="auto",n.addEventListener("loadedmetadata",h),n.addEventListener("error",p),s?.addEventListener("abort",m,{once:!0}),n.src=e,n.load()})}clearMemoryCache(){this.cache.clearMemoryCache()}createOscillator(e,t="HRTF"){return new B(this.context,this.globalGainNode,"oscillator",t,e,this)}async createSound(e,t="Buffer",g="HRTF",s){if(typeof e=="object")return Promise.resolve(new b("",e,this.context,this.globalGainNode,"Buffer",g,this));const o=e;return t==="HTML"?this.createMediaSound(o,"HTML",g,s):t==="Streaming"?this.createMediaSound(o,"Streaming",g,s):this.cache.getAudioBuffer(this.context,o,s,{onLoadingStart:I=>this.emitAsync("loadingStart",I),onLoadingProgress:I=>this.emitAsync("loadingProgress",I),onLoadingComplete:I=>this.emitAsync("loadingComplete",I),onLoadingError:I=>this.emitAsync("loadingError",I),onCacheHit:I=>this.emitAsync("cacheHit",I),onCacheMiss:I=>this.emitAsync("cacheMiss",I),onCacheError:I=>this.emitAsync("cacheError",I)}).then(I=>new b(o,I,this.context,this.globalGainNode,t,g,this))}async createGroup(e){const t=new w;return e.forEach(g=>t.addSound(g)),t}async createGroupFromUrls(e,t="Buffer",g="HRTF",s){const o=new w;return(await Promise.all(e.map(n=>this.createSound(n,t,g,s)))).forEach(n=>o.addSound(n)),o}async createStream(e,t){return this.createMediaSound(e,"Streaming","HRTF",t)}createBiquadFilter=({type:e,frequency:t,gain:g,Q:s})=>{t===void 0&&(t=350);const o=this.context.createBiquadFilter();return o.type=e||"lowpass",o.frequency.value=t,o.gain.value=g||0,o.Q.value=s||1,o};createSplitter(e=2){if(!this.context.createChannelSplitter)throw new Error("ChannelSplitterNode not supported");return this.context.createChannelSplitter(e)}createMerger(e=2){if(!this.context.createChannelMerger)throw new Error("ChannelMergerNode not supported");return this.context.createChannelMerger(e)}createPanner({coneInnerAngle:e,coneOuterAngle:t,coneOuterGain:g,distanceModel:s,maxDistance:o,channelCount:I,channelCountMode:n,channelInterpretation:i,panningModel:C,refDistance:a,rolloffFactor:c,positionX:h,positionY:p,positionZ:m,orientationX:d,orientationY:S,orientationZ:N}){const l=this.context.createPanner();return l.coneInnerAngle=e||360,l.coneOuterAngle=t||360,l.coneOuterGain=g||0,l.distanceModel=s||"inverse",l.maxDistance=o||1e4,l.channelCount=I||2,l.channelCountMode=n||"clamped-max",l.channelInterpretation=i||"speakers",l.panningModel=C||"HRTF",l.refDistance=a||1,l.rolloffFactor=c||1,l.positionX.value=h||0,l.positionY.value=p||0,l.positionZ.value=m||0,l.orientationX.value=d||0,l.orientationY.value=S||0,l.orientationZ.value=N||0,l}pause(){this.context.suspend&&(this.context.suspend(),this.emit("suspend",void 0))}resume(){this.context.resume&&(this.context.resume(),this.emit("resume",void 0))}setGlobalVolume(e){this.globalGainNode.gain.value!==e&&(this.globalGainNode.gain.value=e,this.emit("volumeChange",e))}get volume(){return this.globalGainNode.gain.value}set volume(e){if(this.muted){this.prevVolume=e;return}this.setGlobalVolume(e)}mute(){this.muted||(this.prevVolume=this.globalGainNode.gain.value,this.setGlobalVolume(0),this.emit("mute",void 0))}unmute(){this.muted&&(this.setGlobalVolume(this.prevVolume),this.emit("unmute",void 0))}get muted(){return this.globalGainNode.gain.value===0}set muted(e){e!==this.muted&&(e?this.mute():this.unmute())}getMicrophoneStream(){return new Promise((e,t)=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(g=>{const s=new T(this.context,g);e(s)}).catch(g=>{t(g)})})}get listenerOrientation(){return{forward:[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value],up:[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}}set listenerOrientation(e){const{forward:t,up:g}=e,[s,o,I]=t,[n,i,C]=g;this.listener.forwardX.value=s,this.listener.forwardY.value=o,this.listener.forwardZ.value=I,this.listener.upX.value=n,this.listener.upY.value=i,this.listener.upZ.value=C}get listenerUpOrientation(){return[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}set listenerUpOrientation(e){const[t,g,s]=e;this.listener.upX.value=t,this.listener.upY.value=g,this.listener.upZ.value=s}get listenerForwardOrientation(){return[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value]}set listenerForwardOrientation(e){const[t,g,s]=e;this.listener.forwardX.value=t,this.listener.forwardY.value=g,this.listener.forwardZ.value=s}get listenerPosition(){return[this.listener.positionX.value,this.listener.positionY.value,this.listener.positionZ.value]}set listenerPosition(e){const[t,g,s]=e,o=this.context.currentTime;this.listener.positionX.setValueAtTime(t,o),this.listener.positionY.setValueAtTime(g,o),this.listener.positionZ.setValueAtTime(s,o)}}class Q{constructor(e=[]){this.synths=e}addSynth(e){this.synths.push(e)}removeSynth(e){const t=this.synths.indexOf(e);if(t!==-1)this.synths.splice(t,1);else throw new Error("Synth not found in group")}play(){return this.synths.flatMap(e=>e.play())}stop(){this.synths.forEach(e=>e.stop())}pause(){this.synths.forEach(e=>e.pause())}resume(){this.synths.forEach(e=>e.resume())}get isPlaying(){return this.synths.some(e=>e.isPlaying)}addFilter(e){this.synths.forEach(t=>t.addFilter(e))}removeFilter(e){this.synths.forEach(t=>t.removeFilter(e))}fadeTo(e,t,g){return Promise.all(this.synths.map(s=>s.fadeTo(e,t,g))).then(()=>{})}fadeIn(e,t){return Promise.all(this.synths.map(g=>g.fadeIn(e,t))).then(()=>{})}fadeOut(e,t){return Promise.all(this.synths.map(g=>g.fadeOut(e,t))).then(()=>{})}stopWithFade(e,t){return Promise.all(this.synths.map(g=>g.stopWithFade(e,t))).then(()=>{})}get volume(){return this.synths.length===0?1:this.synths.map(e=>e.volume).reduce((e,t)=>e+t,0)/this.synths.length}set volume(e){this.synths.forEach(t=>t.volume=e)}get stereoPan(){return this.synths.length===0?null:this.synths[0].stereoPan}set stereoPan(e){this.synths.forEach(t=>t.stereoPan=e)}get position(){return this.synths.length===0?[0,0,0]:this.synths[0].position}set position(e){this.synths.forEach(t=>t.position=e)}get frequency(){return this.synths.length===0?440:this.synths[0].frequency}set frequency(e){this.synths.forEach(t=>t.frequency=e)}get detune(){return this.synths[0]?.detune}set detune(e){this.synths.forEach(t=>t.detune=e)}get type(){return this.synths.length===0?"sine":this.synths[0].type}set type(e){this.synths.forEach(t=>t.type=e)}}exports.AudioCache=r;exports.Cacophony=V;exports.Group=w;exports.MicrophonePlayback=X;exports.Playback=Z;exports.Sound=b;exports.SoundType=f;exports.Synth=B;exports.SynthGroup=Q;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class R{maxSize;cache;constructor(e){this.maxSize=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;const t=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,t),t}set(e,t){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.maxSize){const g=this.cache.keys().next().value;g!==void 0&&this.cache.delete(g)}this.cache.set(e,t)}has(e){return this.cache.has(e)}}const W=100;function Y(r){if(!r)return null;const e=r.match(/max-age\s*=\s*"?(\d+)"?/i);return e?parseInt(e[1],10):null}function E(r){return r?/(?:^|,)\s*(no-cache|no-store|must-revalidate)\s*(?:,|$)/i.test(r):!1}function v(r){return r instanceof DOMException&&r.name==="AbortError"?"abort":r instanceof Error?"network":"unknown"}class A{static pendingRequests=new Map;static pendingCallbacks=new Map;static decodedBuffers=new R(W);static cacheExpirationTime=1440*60*1e3;static setCacheExpirationTime(e){A.cacheExpirationTime=e}static async openCache(){try{return await caches.open("audio-cache")}catch(e){throw console.error("Failed to open cache:",e),e}}static callAllCallbacks(e,t,g){const I=A.pendingCallbacks.get(e);I&&I.forEach(o=>{const s=o[t];if(s)try{s(g)}catch(i){console.error(`Error in ${t} callback:`,i)}})}static async getOrCreatePendingRequest(e,t,g,I){if(g?.aborted)throw new DOMException("Operation was aborted","AbortError");if(I){const s=A.pendingCallbacks.get(e)||[];s.push(I),A.pendingCallbacks.set(e,s)}const o=A.pendingRequests.get(e);if(!o){const s=(async()=>{try{const i=await t();if(i===void 0)throw new Error("Failed to create audio buffer.");return i}finally{A.pendingRequests.delete(e),A.pendingCallbacks.delete(e)}})();return g?.addEventListener("abort",()=>{g.aborted&&(A.pendingRequests.delete(e),A.pendingCallbacks.delete(e))},{once:!0}),A.pendingRequests.set(e,s),s}return o}static async updateMetadata(e,t,g){const I={url:t,timestamp:Date.now(),...g};await e.put(`${t}:meta`,new Response(JSON.stringify(I),{headers:{"Content-Type":"application/json"}}))}static async getBufferFromCache(e,t){try{const g=await t.match(e);return g?.ok?await g.arrayBuffer():null}catch(g){return console.error("Failed to get data from cache:",g),null}}static async fetchAndCacheBuffer(e,t,g,I,o,s){const i=new Headers;g&&i.append("If-None-Match",g),I&&i.append("If-Modified-Since",I),console.debug(`[AudioCache] Fetching ${e}`,{headers:Object.fromEntries(i.entries()),hasEtag:!!g,hasLastModified:!!I});const C=await fetch(e,{headers:i,signal:o});if(console.debug(`[AudioCache] Response ${e}`,{status:C.status,statusText:C.statusText,etag:C.headers?.get("ETag"),lastModified:C.headers?.get("Last-Modified"),cacheControl:C.headers?.get("Cache-Control")}),C.status===304){const n=await t.match(e);if(n){s?.onCacheHit&&s.onCacheHit({url:e,cacheType:"conditional",timestamp:Date.now()});const a=Date.now(),c=C.headers?.get("Cache-Control");return await A.updateMetadata(t,e,{timestamp:a,etag:g,lastModified:I,...c?{cacheControl:c}:{}}),await n.arrayBuffer()}else{console.warn(`Cache inconsistency detected for ${e}: 304 response but no cached body. Re-fetching.`);const a=await fetch(e,{signal:o});if(a.status===200){const c=a.clone(),h=a.headers.get("ETag"),m=a.headers.get("Last-Modified"),p=a.headers.get("Cache-Control");try{await Promise.all([t.put(e,c),A.updateMetadata(t,e,{timestamp:Date.now(),etag:h||void 0,lastModified:m||void 0,cacheControl:p||void 0})])}catch(d){throw await t.delete(e),await t.delete(`${e}:meta`),d}if(a.body){const{stream:d,total:w}=A.createProgressTrackingStream(a,e);return await A.collectStreamToArrayBuffer(d,w||void 0)}else return await a.arrayBuffer()}else throw new Error(`Failed to fetch resource after cache inconsistency: ${a.status} ${a.statusText}`)}}if(C.status===200){const n=C.clone(),a=C.headers.get("ETag"),c=C.headers.get("Last-Modified"),h=C.headers.get("Cache-Control");try{await Promise.all([t.put(e,n),A.updateMetadata(t,e,{timestamp:Date.now(),etag:a||void 0,lastModified:c||void 0,cacheControl:h||void 0})])}catch(m){throw await t.delete(e),await t.delete(`${e}:meta`),m}}if(o?.aborted)throw new DOMException("Operation was aborted","AbortError");if(C.body){const{stream:n,total:a}=A.createProgressTrackingStream(C,e);return await A.collectStreamToArrayBuffer(n,a||void 0)}else return await C.arrayBuffer()}static createProgressTrackingStream(e,t){const g=e.headers.get("content-length"),I=g?parseInt(g,10):null;let o=0;if(!e.body)throw new Error("Response body is null");const s=e.body.getReader();return{stream:new ReadableStream({start(C){function n(){return s.read().then(({done:a,value:c})=>{if(a){A.callAllCallbacks(t,"onLoadingProgress",{url:t,loaded:o,total:I,progress:I?1:-1,timestamp:Date.now()}),C.close();return}if(c){o+=c.byteLength;const h=I?o/I:-1;A.callAllCallbacks(t,"onLoadingProgress",{url:t,loaded:o,total:I,progress:h,timestamp:Date.now()}),C.enqueue(c)}return n()}).catch(a=>{C.error(a)})}return n()},cancel(C){return s.cancel(C)}}),total:I}}static async collectStreamToArrayBuffer(e,t){const g=e.getReader();try{if(t!==void 0&&t>0){const I=new ArrayBuffer(t),o=new Uint8Array(I);let s=0;for(;;){const{done:i,value:C}=await g.read();if(i)break;C&&(o.set(C,s),s+=C.byteLength)}return I}else{let I=new Uint8Array(8192),o=0;for(;;){const{done:s,value:i}=await g.read();if(s)break;if(i){if(o+i.byteLength>I.length){const C=Math.max(I.length*2,o+i.byteLength),n=new Uint8Array(C);n.set(I.subarray(0,o)),I=n}I.set(i,o),o+=i.byteLength}}return I.slice(0,o).buffer}}finally{g.releaseLock()}}static async decodeAudioData(e,t){try{return await e.decodeAudioData(t)}catch(g){throw console.error("Failed to decode audio data:",g),g}}static async getMetadataFromCache(e,t){try{const g=await t.match(`${e}:meta`);return g?.ok?await g.json():null}catch(g){return console.error("Failed to get metadata from cache:",g),null}}async getAudioBuffer(e,t,g,I){if(I?.onLoadingStart&&I.onLoadingStart({url:t,timestamp:Date.now()}),A.decodedBuffers.has(t))return I?.onCacheHit&&I.onCacheHit({url:t,cacheType:"memory",timestamp:Date.now()}),A.decodedBuffers.get(t);if(t.startsWith("data:")){const C=t.split(",")[1],n=Uint8Array.from(atob(C),c=>c.charCodeAt(0)).buffer,a=await A.decodeAudioData(e,n);return A.decodedBuffers.set(t,a),a}const o=await A.openCache(),s=await A.getMetadataFromCache(t,o),i=(()=>{if(!s||E(s.cacheControl))return!0;const C=Y(s.cacheControl);if(C!==null){const n=(Date.now()-s.timestamp)/1e3;if(C>0&&n<C)return!1}return s.etag||s.lastModified?!0:Date.now()-s.timestamp>A.cacheExpirationTime})();return A.getOrCreatePendingRequest(t,async()=>{if(i){I?.onCacheMiss&&I.onCacheMiss({url:t,reason:s?"expired":"not-found",timestamp:Date.now()});try{const C=await A.fetchAndCacheBuffer(t,o,s?.etag,s?.lastModified,g,{onCacheHit:I?.onCacheHit});let n;try{n=await A.decodeAudioData(e,C)}catch(a){throw I?.onLoadingError&&I.onLoadingError({url:t,error:a,errorType:"decode",timestamp:Date.now()}),a}return I?.onLoadingComplete&&I.onLoadingComplete({url:t,duration:n.duration,size:C.byteLength,timestamp:Date.now()}),A.decodedBuffers.set(t,n),n}catch(C){throw I?.onLoadingError&&I.onLoadingError({url:t,error:C,errorType:v(C),timestamp:Date.now()}),I?.onCacheError&&I.onCacheError({url:t,error:C,operation:"get",timestamp:Date.now()}),C}}else{const C=await A.getBufferFromCache(t,o);if(C){I?.onCacheHit&&I.onCacheHit({url:t,cacheType:"browser",timestamp:Date.now()});const n=await A.decodeAudioData(e,C);return A.decodedBuffers.set(t,n),n}else{I?.onCacheError&&I.onCacheError({url:t,error:new Error("Cache inconsistency: metadata exists but body is missing"),operation:"get",timestamp:Date.now()});try{const n=await A.fetchAndCacheBuffer(t,o,s?.etag,s?.lastModified,g,{onCacheHit:I?.onCacheHit});let a;try{a=await A.decodeAudioData(e,n)}catch(c){throw I?.onLoadingError&&I.onLoadingError({url:t,error:c,errorType:"decode",timestamp:Date.now()}),c}return I?.onLoadingComplete&&I.onLoadingComplete({url:t,duration:a.duration,size:n.byteLength,timestamp:Date.now()}),A.decodedBuffers.set(t,a),a}catch(n){throw I?.onLoadingError&&I.onLoadingError({url:t,error:n,errorType:v(n),timestamp:Date.now()}),n}}}},g,{onLoadingProgress:I?.onLoadingProgress})}clearMemoryCache(){A.decodedBuffers=new R(W),A.pendingRequests.clear()}}const D="data:text/javascript;base64,dmFyIHBoYXNlVm9jb2RlciA9IChmdW5jdGlvbiAoZXhwb3J0cykgewoJJ3VzZSBzdHJpY3QnOwoKCWZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzICh4KSB7CgkJcmV0dXJuIHggJiYgeC5fX2VzTW9kdWxlICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh4LCAnZGVmYXVsdCcpID8geFsnZGVmYXVsdCddIDogeDsKCX0KCglmdW5jdGlvbiBGRlQoc2l6ZSkgewoJICB0aGlzLnNpemUgPSBzaXplIHwgMDsKCSAgaWYgKHRoaXMuc2l6ZSA8PSAxIHx8ICh0aGlzLnNpemUgJiAodGhpcy5zaXplIC0gMSkpICE9PSAwKQoJICAgIHRocm93IG5ldyBFcnJvcignRkZUIHNpemUgbXVzdCBiZSBhIHBvd2VyIG9mIHR3byBhbmQgYmlnZ2VyIHRoYW4gMScpOwoKCSAgdGhpcy5fY3NpemUgPSBzaXplIDw8IDE7CgoJICAvLyBOT1RFOiBVc2Ugb2YgYHZhcmAgaXMgaW50ZW50aW9uYWwgZm9yIG9sZCBWOCB2ZXJzaW9ucwoJICB2YXIgdGFibGUgPSBuZXcgQXJyYXkodGhpcy5zaXplICogMik7CgkgIGZvciAodmFyIGkgPSAwOyBpIDwgdGFibGUubGVuZ3RoOyBpICs9IDIpIHsKCSAgICBjb25zdCBhbmdsZSA9IE1hdGguUEkgKiBpIC8gdGhpcy5zaXplOwoJICAgIHRhYmxlW2ldID0gTWF0aC5jb3MoYW5nbGUpOwoJICAgIHRhYmxlW2kgKyAxXSA9IC1NYXRoLnNpbihhbmdsZSk7CgkgIH0KCSAgdGhpcy50YWJsZSA9IHRhYmxlOwoKCSAgLy8gRmluZCBzaXplJ3MgcG93ZXIgb2YgdHdvCgkgIHZhciBwb3dlciA9IDA7CgkgIGZvciAodmFyIHQgPSAxOyB0aGlzLnNpemUgPiB0OyB0IDw8PSAxKQoJICAgIHBvd2VyKys7CgoJICAvLyBDYWxjdWxhdGUgaW5pdGlhbCBzdGVwJ3Mgd2lkdGg6CgkgIC8vICAgKiBJZiB3ZSBhcmUgZnVsbCByYWRpeC00IC0gaXQgaXMgMnggc21hbGxlciB0byBnaXZlIGluaXRhbCBsZW49OAoJICAvLyAgICogT3RoZXJ3aXNlIGl0IGlzIHRoZSBzYW1lIGFzIGBwb3dlcmAgdG8gZ2l2ZSBsZW49NAoJICB0aGlzLl93aWR0aCA9IHBvd2VyICUgMiA9PT0gMCA/IHBvd2VyIC0gMSA6IHBvd2VyOwoKCSAgLy8gUHJlLWNvbXB1dGUgYml0LXJldmVyc2FsIHBhdHRlcm5zCgkgIHRoaXMuX2JpdHJldiA9IG5ldyBBcnJheSgxIDw8IHRoaXMuX3dpZHRoKTsKCSAgZm9yICh2YXIgaiA9IDA7IGogPCB0aGlzLl9iaXRyZXYubGVuZ3RoOyBqKyspIHsKCSAgICB0aGlzLl9iaXRyZXZbal0gPSAwOwoJICAgIGZvciAodmFyIHNoaWZ0ID0gMDsgc2hpZnQgPCB0aGlzLl93aWR0aDsgc2hpZnQgKz0gMikgewoJICAgICAgdmFyIHJldlNoaWZ0ID0gdGhpcy5fd2lkdGggLSBzaGlmdCAtIDI7CgkgICAgICB0aGlzLl9iaXRyZXZbal0gfD0gKChqID4+PiBzaGlmdCkgJiAzKSA8PCByZXZTaGlmdDsKCSAgICB9CgkgIH0KCgkgIHRoaXMuX291dCA9IG51bGw7CgkgIHRoaXMuX2RhdGEgPSBudWxsOwoJICB0aGlzLl9pbnYgPSAwOwoJfQoJdmFyIGZmdCA9IEZGVDsKCglGRlQucHJvdG90eXBlLmZyb21Db21wbGV4QXJyYXkgPSBmdW5jdGlvbiBmcm9tQ29tcGxleEFycmF5KGNvbXBsZXgsIHN0b3JhZ2UpIHsKCSAgdmFyIHJlcyA9IHN0b3JhZ2UgfHwgbmV3IEFycmF5KGNvbXBsZXgubGVuZ3RoID4+PiAxKTsKCSAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb21wbGV4Lmxlbmd0aDsgaSArPSAyKQoJICAgIHJlc1tpID4+PiAxXSA9IGNvbXBsZXhbaV07CgkgIHJldHVybiByZXM7Cgl9OwoKCUZGVC5wcm90b3R5cGUuY3JlYXRlQ29tcGxleEFycmF5ID0gZnVuY3Rpb24gY3JlYXRlQ29tcGxleEFycmF5KCkgewoJICBjb25zdCByZXMgPSBuZXcgQXJyYXkodGhpcy5fY3NpemUpOwoJICBmb3IgKHZhciBpID0gMDsgaSA8IHJlcy5sZW5ndGg7IGkrKykKCSAgICByZXNbaV0gPSAwOwoJICByZXR1cm4gcmVzOwoJfTsKCglGRlQucHJvdG90eXBlLnRvQ29tcGxleEFycmF5ID0gZnVuY3Rpb24gdG9Db21wbGV4QXJyYXkoaW5wdXQsIHN0b3JhZ2UpIHsKCSAgdmFyIHJlcyA9IHN0b3JhZ2UgfHwgdGhpcy5jcmVhdGVDb21wbGV4QXJyYXkoKTsKCSAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMubGVuZ3RoOyBpICs9IDIpIHsKCSAgICByZXNbaV0gPSBpbnB1dFtpID4+PiAxXTsKCSAgICByZXNbaSArIDFdID0gMDsKCSAgfQoJICByZXR1cm4gcmVzOwoJfTsKCglGRlQucHJvdG90eXBlLmNvbXBsZXRlU3BlY3RydW0gPSBmdW5jdGlvbiBjb21wbGV0ZVNwZWN0cnVtKHNwZWN0cnVtKSB7CgkgIHZhciBzaXplID0gdGhpcy5fY3NpemU7CgkgIHZhciBoYWxmID0gc2l6ZSA+Pj4gMTsKCSAgZm9yICh2YXIgaSA9IDI7IGkgPCBoYWxmOyBpICs9IDIpIHsKCSAgICBzcGVjdHJ1bVtzaXplIC0gaV0gPSBzcGVjdHJ1bVtpXTsKCSAgICBzcGVjdHJ1bVtzaXplIC0gaSArIDFdID0gLXNwZWN0cnVtW2kgKyAxXTsKCSAgfQoJfTsKCglGRlQucHJvdG90eXBlLnRyYW5zZm9ybSA9IGZ1bmN0aW9uIHRyYW5zZm9ybShvdXQsIGRhdGEpIHsKCSAgaWYgKG91dCA9PT0gZGF0YSkKCSAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBtdXN0IGJlIGRpZmZlcmVudCcpOwoKCSAgdGhpcy5fb3V0ID0gb3V0OwoJICB0aGlzLl9kYXRhID0gZGF0YTsKCSAgdGhpcy5faW52ID0gMDsKCSAgdGhpcy5fdHJhbnNmb3JtNCgpOwoJICB0aGlzLl9vdXQgPSBudWxsOwoJICB0aGlzLl9kYXRhID0gbnVsbDsKCX07CgoJRkZULnByb3RvdHlwZS5yZWFsVHJhbnNmb3JtID0gZnVuY3Rpb24gcmVhbFRyYW5zZm9ybShvdXQsIGRhdGEpIHsKCSAgaWYgKG91dCA9PT0gZGF0YSkKCSAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBtdXN0IGJlIGRpZmZlcmVudCcpOwoKCSAgdGhpcy5fb3V0ID0gb3V0OwoJICB0aGlzLl9kYXRhID0gZGF0YTsKCSAgdGhpcy5faW52ID0gMDsKCSAgdGhpcy5fcmVhbFRyYW5zZm9ybTQoKTsKCSAgdGhpcy5fb3V0ID0gbnVsbDsKCSAgdGhpcy5fZGF0YSA9IG51bGw7Cgl9OwoKCUZGVC5wcm90b3R5cGUuaW52ZXJzZVRyYW5zZm9ybSA9IGZ1bmN0aW9uIGludmVyc2VUcmFuc2Zvcm0ob3V0LCBkYXRhKSB7CgkgIGlmIChvdXQgPT09IGRhdGEpCgkgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMgbXVzdCBiZSBkaWZmZXJlbnQnKTsKCgkgIHRoaXMuX291dCA9IG91dDsKCSAgdGhpcy5fZGF0YSA9IGRhdGE7CgkgIHRoaXMuX2ludiA9IDE7CgkgIHRoaXMuX3RyYW5zZm9ybTQoKTsKCSAgZm9yICh2YXIgaSA9IDA7IGkgPCBvdXQubGVuZ3RoOyBpKyspCgkgICAgb3V0W2ldIC89IHRoaXMuc2l6ZTsKCSAgdGhpcy5fb3V0ID0gbnVsbDsKCSAgdGhpcy5fZGF0YSA9IG51bGw7Cgl9OwoKCS8vIHJhZGl4LTQgaW1wbGVtZW50YXRpb24KCS8vCgkvLyBOT1RFOiBVc2VzIG9mIGB2YXJgIGFyZSBpbnRlbnRpb25hbCBmb3Igb2xkZXIgVjggdmVyc2lvbiB0aGF0IGRvIG5vdAoJLy8gc3VwcG9ydCBib3RoIGBsZXQgY29tcG91bmQgYXNzaWdubWVudHNgIGFuZCBgY29uc3QgcGhpYAoJRkZULnByb3RvdHlwZS5fdHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF90cmFuc2Zvcm00KCkgewoJICB2YXIgb3V0ID0gdGhpcy5fb3V0OwoJICB2YXIgc2l6ZSA9IHRoaXMuX2NzaXplOwoKCSAgLy8gSW5pdGlhbCBzdGVwIChwZXJtdXRlIGFuZCB0cmFuc2Zvcm0pCgkgIHZhciB3aWR0aCA9IHRoaXMuX3dpZHRoOwoJICB2YXIgc3RlcCA9IDEgPDwgd2lkdGg7CgkgIHZhciBsZW4gPSAoc2l6ZSAvIHN0ZXApIDw8IDE7CgoJICB2YXIgb3V0T2ZmOwoJICB2YXIgdDsKCSAgdmFyIGJpdHJldiA9IHRoaXMuX2JpdHJldjsKCSAgaWYgKGxlbiA9PT0gNCkgewoJICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewoJICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwoJICAgICAgdGhpcy5fc2luZ2xlVHJhbnNmb3JtMihvdXRPZmYsIG9mZiwgc3RlcCk7CgkgICAgfQoJICB9IGVsc2UgewoJICAgIC8vIGxlbiA9PT0gOAoJICAgIGZvciAob3V0T2ZmID0gMCwgdCA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4sIHQrKykgewoJICAgICAgY29uc3Qgb2ZmID0gYml0cmV2W3RdOwoJICAgICAgdGhpcy5fc2luZ2xlVHJhbnNmb3JtNChvdXRPZmYsIG9mZiwgc3RlcCk7CgkgICAgfQoJICB9CgoJICAvLyBMb29wIHRocm91Z2ggc3RlcHMgaW4gZGVjcmVhc2luZyBvcmRlcgoJICB2YXIgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwoJICB2YXIgdGFibGUgPSB0aGlzLnRhYmxlOwoJICBmb3IgKHN0ZXAgPj49IDI7IHN0ZXAgPj0gMjsgc3RlcCA+Pj0gMikgewoJICAgIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCSAgICB2YXIgcXVhcnRlckxlbiA9IGxlbiA+Pj4gMjsKCgkgICAgLy8gTG9vcCB0aHJvdWdoIG9mZnNldHMgaW4gdGhlIGRhdGEKCSAgICBmb3IgKG91dE9mZiA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4pIHsKCSAgICAgIC8vIEZ1bGwgY2FzZQoJICAgICAgdmFyIGxpbWl0ID0gb3V0T2ZmICsgcXVhcnRlckxlbjsKCSAgICAgIGZvciAodmFyIGkgPSBvdXRPZmYsIGsgPSAwOyBpIDwgbGltaXQ7IGkgKz0gMiwgayArPSBzdGVwKSB7CgkgICAgICAgIGNvbnN0IEEgPSBpOwoJICAgICAgICBjb25zdCBCID0gQSArIHF1YXJ0ZXJMZW47CgkgICAgICAgIGNvbnN0IEMgPSBCICsgcXVhcnRlckxlbjsKCSAgICAgICAgY29uc3QgRCA9IEMgKyBxdWFydGVyTGVuOwoKCSAgICAgICAgLy8gT3JpZ2luYWwgdmFsdWVzCgkgICAgICAgIGNvbnN0IEFyID0gb3V0W0FdOwoJICAgICAgICBjb25zdCBBaSA9IG91dFtBICsgMV07CgkgICAgICAgIGNvbnN0IEJyID0gb3V0W0JdOwoJICAgICAgICBjb25zdCBCaSA9IG91dFtCICsgMV07CgkgICAgICAgIGNvbnN0IENyID0gb3V0W0NdOwoJICAgICAgICBjb25zdCBDaSA9IG91dFtDICsgMV07CgkgICAgICAgIGNvbnN0IERyID0gb3V0W0RdOwoJICAgICAgICBjb25zdCBEaSA9IG91dFtEICsgMV07CgoJICAgICAgICAvLyBNaWRkbGUgdmFsdWVzCgkgICAgICAgIGNvbnN0IE1BciA9IEFyOwoJICAgICAgICBjb25zdCBNQWkgPSBBaTsKCgkgICAgICAgIGNvbnN0IHRhYmxlQnIgPSB0YWJsZVtrXTsKCSAgICAgICAgY29uc3QgdGFibGVCaSA9IGludiAqIHRhYmxlW2sgKyAxXTsKCSAgICAgICAgY29uc3QgTUJyID0gQnIgKiB0YWJsZUJyIC0gQmkgKiB0YWJsZUJpOwoJICAgICAgICBjb25zdCBNQmkgPSBCciAqIHRhYmxlQmkgKyBCaSAqIHRhYmxlQnI7CgoJICAgICAgICBjb25zdCB0YWJsZUNyID0gdGFibGVbMiAqIGtdOwoJICAgICAgICBjb25zdCB0YWJsZUNpID0gaW52ICogdGFibGVbMiAqIGsgKyAxXTsKCSAgICAgICAgY29uc3QgTUNyID0gQ3IgKiB0YWJsZUNyIC0gQ2kgKiB0YWJsZUNpOwoJICAgICAgICBjb25zdCBNQ2kgPSBDciAqIHRhYmxlQ2kgKyBDaSAqIHRhYmxlQ3I7CgoJICAgICAgICBjb25zdCB0YWJsZURyID0gdGFibGVbMyAqIGtdOwoJICAgICAgICBjb25zdCB0YWJsZURpID0gaW52ICogdGFibGVbMyAqIGsgKyAxXTsKCSAgICAgICAgY29uc3QgTURyID0gRHIgKiB0YWJsZURyIC0gRGkgKiB0YWJsZURpOwoJICAgICAgICBjb25zdCBNRGkgPSBEciAqIHRhYmxlRGkgKyBEaSAqIHRhYmxlRHI7CgoJICAgICAgICAvLyBQcmUtRmluYWwgdmFsdWVzCgkgICAgICAgIGNvbnN0IFQwciA9IE1BciArIE1DcjsKCSAgICAgICAgY29uc3QgVDBpID0gTUFpICsgTUNpOwoJICAgICAgICBjb25zdCBUMXIgPSBNQXIgLSBNQ3I7CgkgICAgICAgIGNvbnN0IFQxaSA9IE1BaSAtIE1DaTsKCSAgICAgICAgY29uc3QgVDJyID0gTUJyICsgTURyOwoJICAgICAgICBjb25zdCBUMmkgPSBNQmkgKyBNRGk7CgkgICAgICAgIGNvbnN0IFQzciA9IGludiAqIChNQnIgLSBNRHIpOwoJICAgICAgICBjb25zdCBUM2kgPSBpbnYgKiAoTUJpIC0gTURpKTsKCgkgICAgICAgIC8vIEZpbmFsIHZhbHVlcwoJICAgICAgICBjb25zdCBGQXIgPSBUMHIgKyBUMnI7CgkgICAgICAgIGNvbnN0IEZBaSA9IFQwaSArIFQyaTsKCgkgICAgICAgIGNvbnN0IEZDciA9IFQwciAtIFQycjsKCSAgICAgICAgY29uc3QgRkNpID0gVDBpIC0gVDJpOwoKCSAgICAgICAgY29uc3QgRkJyID0gVDFyICsgVDNpOwoJICAgICAgICBjb25zdCBGQmkgPSBUMWkgLSBUM3I7CgoJICAgICAgICBjb25zdCBGRHIgPSBUMXIgLSBUM2k7CgkgICAgICAgIGNvbnN0IEZEaSA9IFQxaSArIFQzcjsKCgkgICAgICAgIG91dFtBXSA9IEZBcjsKCSAgICAgICAgb3V0W0EgKyAxXSA9IEZBaTsKCSAgICAgICAgb3V0W0JdID0gRkJyOwoJICAgICAgICBvdXRbQiArIDFdID0gRkJpOwoJICAgICAgICBvdXRbQ10gPSBGQ3I7CgkgICAgICAgIG91dFtDICsgMV0gPSBGQ2k7CgkgICAgICAgIG91dFtEXSA9IEZEcjsKCSAgICAgICAgb3V0W0QgKyAxXSA9IEZEaTsKCSAgICAgIH0KCSAgICB9CgkgIH0KCX07CgoJLy8gcmFkaXgtMiBpbXBsZW1lbnRhdGlvbgoJLy8KCS8vIE5PVEU6IE9ubHkgY2FsbGVkIGZvciBsZW49NAoJRkZULnByb3RvdHlwZS5fc2luZ2xlVHJhbnNmb3JtMiA9IGZ1bmN0aW9uIF9zaW5nbGVUcmFuc2Zvcm0yKG91dE9mZiwgb2ZmLAoJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKCSAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwoJICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKCgkgIGNvbnN0IGV2ZW5SID0gZGF0YVtvZmZdOwoJICBjb25zdCBldmVuSSA9IGRhdGFbb2ZmICsgMV07CgkgIGNvbnN0IG9kZFIgPSBkYXRhW29mZiArIHN0ZXBdOwoJICBjb25zdCBvZGRJID0gZGF0YVtvZmYgKyBzdGVwICsgMV07CgoJICBjb25zdCBsZWZ0UiA9IGV2ZW5SICsgb2RkUjsKCSAgY29uc3QgbGVmdEkgPSBldmVuSSArIG9kZEk7CgkgIGNvbnN0IHJpZ2h0UiA9IGV2ZW5SIC0gb2RkUjsKCSAgY29uc3QgcmlnaHRJID0gZXZlbkkgLSBvZGRJOwoKCSAgb3V0W291dE9mZl0gPSBsZWZ0UjsKCSAgb3V0W291dE9mZiArIDFdID0gbGVmdEk7CgkgIG91dFtvdXRPZmYgKyAyXSA9IHJpZ2h0UjsKCSAgb3V0W291dE9mZiArIDNdID0gcmlnaHRJOwoJfTsKCgkvLyByYWRpeC00CgkvLwoJLy8gTk9URTogT25seSBjYWxsZWQgZm9yIGxlbj04CglGRlQucHJvdG90eXBlLl9zaW5nbGVUcmFuc2Zvcm00ID0gZnVuY3Rpb24gX3NpbmdsZVRyYW5zZm9ybTQob3V0T2ZmLCBvZmYsCgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCkgewoJICBjb25zdCBvdXQgPSB0aGlzLl9vdXQ7CgkgIGNvbnN0IGRhdGEgPSB0aGlzLl9kYXRhOwoJICBjb25zdCBpbnYgPSB0aGlzLl9pbnYgPyAtMSA6IDE7CgkgIGNvbnN0IHN0ZXAyID0gc3RlcCAqIDI7CgkgIGNvbnN0IHN0ZXAzID0gc3RlcCAqIDM7CgoJICAvLyBPcmlnaW5hbCB2YWx1ZXMKCSAgY29uc3QgQXIgPSBkYXRhW29mZl07CgkgIGNvbnN0IEFpID0gZGF0YVtvZmYgKyAxXTsKCSAgY29uc3QgQnIgPSBkYXRhW29mZiArIHN0ZXBdOwoJICBjb25zdCBCaSA9IGRhdGFbb2ZmICsgc3RlcCArIDFdOwoJICBjb25zdCBDciA9IGRhdGFbb2ZmICsgc3RlcDJdOwoJICBjb25zdCBDaSA9IGRhdGFbb2ZmICsgc3RlcDIgKyAxXTsKCSAgY29uc3QgRHIgPSBkYXRhW29mZiArIHN0ZXAzXTsKCSAgY29uc3QgRGkgPSBkYXRhW29mZiArIHN0ZXAzICsgMV07CgoJICAvLyBQcmUtRmluYWwgdmFsdWVzCgkgIGNvbnN0IFQwciA9IEFyICsgQ3I7CgkgIGNvbnN0IFQwaSA9IEFpICsgQ2k7CgkgIGNvbnN0IFQxciA9IEFyIC0gQ3I7CgkgIGNvbnN0IFQxaSA9IEFpIC0gQ2k7CgkgIGNvbnN0IFQyciA9IEJyICsgRHI7CgkgIGNvbnN0IFQyaSA9IEJpICsgRGk7CgkgIGNvbnN0IFQzciA9IGludiAqIChCciAtIERyKTsKCSAgY29uc3QgVDNpID0gaW52ICogKEJpIC0gRGkpOwoKCSAgLy8gRmluYWwgdmFsdWVzCgkgIGNvbnN0IEZBciA9IFQwciArIFQycjsKCSAgY29uc3QgRkFpID0gVDBpICsgVDJpOwoKCSAgY29uc3QgRkJyID0gVDFyICsgVDNpOwoJICBjb25zdCBGQmkgPSBUMWkgLSBUM3I7CgoJICBjb25zdCBGQ3IgPSBUMHIgLSBUMnI7CgkgIGNvbnN0IEZDaSA9IFQwaSAtIFQyaTsKCgkgIGNvbnN0IEZEciA9IFQxciAtIFQzaTsKCSAgY29uc3QgRkRpID0gVDFpICsgVDNyOwoKCSAgb3V0W291dE9mZl0gPSBGQXI7CgkgIG91dFtvdXRPZmYgKyAxXSA9IEZBaTsKCSAgb3V0W291dE9mZiArIDJdID0gRkJyOwoJICBvdXRbb3V0T2ZmICsgM10gPSBGQmk7CgkgIG91dFtvdXRPZmYgKyA0XSA9IEZDcjsKCSAgb3V0W291dE9mZiArIDVdID0gRkNpOwoJICBvdXRbb3V0T2ZmICsgNl0gPSBGRHI7CgkgIG91dFtvdXRPZmYgKyA3XSA9IEZEaTsKCX07CgoJLy8gUmVhbCBpbnB1dCByYWRpeC00IGltcGxlbWVudGF0aW9uCglGRlQucHJvdG90eXBlLl9yZWFsVHJhbnNmb3JtNCA9IGZ1bmN0aW9uIF9yZWFsVHJhbnNmb3JtNCgpIHsKCSAgdmFyIG91dCA9IHRoaXMuX291dDsKCSAgdmFyIHNpemUgPSB0aGlzLl9jc2l6ZTsKCgkgIC8vIEluaXRpYWwgc3RlcCAocGVybXV0ZSBhbmQgdHJhbnNmb3JtKQoJICB2YXIgd2lkdGggPSB0aGlzLl93aWR0aDsKCSAgdmFyIHN0ZXAgPSAxIDw8IHdpZHRoOwoJICB2YXIgbGVuID0gKHNpemUgLyBzdGVwKSA8PCAxOwoKCSAgdmFyIG91dE9mZjsKCSAgdmFyIHQ7CgkgIHZhciBiaXRyZXYgPSB0aGlzLl9iaXRyZXY7CgkgIGlmIChsZW4gPT09IDQpIHsKCSAgICBmb3IgKG91dE9mZiA9IDAsIHQgPSAwOyBvdXRPZmYgPCBzaXplOyBvdXRPZmYgKz0gbGVuLCB0KyspIHsKCSAgICAgIGNvbnN0IG9mZiA9IGJpdHJldlt0XTsKCSAgICAgIHRoaXMuX3NpbmdsZVJlYWxUcmFuc2Zvcm0yKG91dE9mZiwgb2ZmID4+PiAxLCBzdGVwID4+PiAxKTsKCSAgICB9CgkgIH0gZWxzZSB7CgkgICAgLy8gbGVuID09PSA4CgkgICAgZm9yIChvdXRPZmYgPSAwLCB0ID0gMDsgb3V0T2ZmIDwgc2l6ZTsgb3V0T2ZmICs9IGxlbiwgdCsrKSB7CgkgICAgICBjb25zdCBvZmYgPSBiaXRyZXZbdF07CgkgICAgICB0aGlzLl9zaW5nbGVSZWFsVHJhbnNmb3JtNChvdXRPZmYsIG9mZiA+Pj4gMSwgc3RlcCA+Pj4gMSk7CgkgICAgfQoJICB9CgoJICAvLyBMb29wIHRocm91Z2ggc3RlcHMgaW4gZGVjcmVhc2luZyBvcmRlcgoJICB2YXIgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwoJICB2YXIgdGFibGUgPSB0aGlzLnRhYmxlOwoJICBmb3IgKHN0ZXAgPj49IDI7IHN0ZXAgPj0gMjsgc3RlcCA+Pj0gMikgewoJICAgIGxlbiA9IChzaXplIC8gc3RlcCkgPDwgMTsKCSAgICB2YXIgaGFsZkxlbiA9IGxlbiA+Pj4gMTsKCSAgICB2YXIgcXVhcnRlckxlbiA9IGhhbGZMZW4gPj4+IDE7CgkgICAgdmFyIGhxdWFydGVyTGVuID0gcXVhcnRlckxlbiA+Pj4gMTsKCgkgICAgLy8gTG9vcCB0aHJvdWdoIG9mZnNldHMgaW4gdGhlIGRhdGEKCSAgICBmb3IgKG91dE9mZiA9IDA7IG91dE9mZiA8IHNpemU7IG91dE9mZiArPSBsZW4pIHsKCSAgICAgIGZvciAodmFyIGkgPSAwLCBrID0gMDsgaSA8PSBocXVhcnRlckxlbjsgaSArPSAyLCBrICs9IHN0ZXApIHsKCSAgICAgICAgdmFyIEEgPSBvdXRPZmYgKyBpOwoJICAgICAgICB2YXIgQiA9IEEgKyBxdWFydGVyTGVuOwoJICAgICAgICB2YXIgQyA9IEIgKyBxdWFydGVyTGVuOwoJICAgICAgICB2YXIgRCA9IEMgKyBxdWFydGVyTGVuOwoKCSAgICAgICAgLy8gT3JpZ2luYWwgdmFsdWVzCgkgICAgICAgIHZhciBBciA9IG91dFtBXTsKCSAgICAgICAgdmFyIEFpID0gb3V0W0EgKyAxXTsKCSAgICAgICAgdmFyIEJyID0gb3V0W0JdOwoJICAgICAgICB2YXIgQmkgPSBvdXRbQiArIDFdOwoJICAgICAgICB2YXIgQ3IgPSBvdXRbQ107CgkgICAgICAgIHZhciBDaSA9IG91dFtDICsgMV07CgkgICAgICAgIHZhciBEciA9IG91dFtEXTsKCSAgICAgICAgdmFyIERpID0gb3V0W0QgKyAxXTsKCgkgICAgICAgIC8vIE1pZGRsZSB2YWx1ZXMKCSAgICAgICAgdmFyIE1BciA9IEFyOwoJICAgICAgICB2YXIgTUFpID0gQWk7CgoJICAgICAgICB2YXIgdGFibGVCciA9IHRhYmxlW2tdOwoJICAgICAgICB2YXIgdGFibGVCaSA9IGludiAqIHRhYmxlW2sgKyAxXTsKCSAgICAgICAgdmFyIE1CciA9IEJyICogdGFibGVCciAtIEJpICogdGFibGVCaTsKCSAgICAgICAgdmFyIE1CaSA9IEJyICogdGFibGVCaSArIEJpICogdGFibGVCcjsKCgkgICAgICAgIHZhciB0YWJsZUNyID0gdGFibGVbMiAqIGtdOwoJICAgICAgICB2YXIgdGFibGVDaSA9IGludiAqIHRhYmxlWzIgKiBrICsgMV07CgkgICAgICAgIHZhciBNQ3IgPSBDciAqIHRhYmxlQ3IgLSBDaSAqIHRhYmxlQ2k7CgkgICAgICAgIHZhciBNQ2kgPSBDciAqIHRhYmxlQ2kgKyBDaSAqIHRhYmxlQ3I7CgoJICAgICAgICB2YXIgdGFibGVEciA9IHRhYmxlWzMgKiBrXTsKCSAgICAgICAgdmFyIHRhYmxlRGkgPSBpbnYgKiB0YWJsZVszICogayArIDFdOwoJICAgICAgICB2YXIgTURyID0gRHIgKiB0YWJsZURyIC0gRGkgKiB0YWJsZURpOwoJICAgICAgICB2YXIgTURpID0gRHIgKiB0YWJsZURpICsgRGkgKiB0YWJsZURyOwoKCSAgICAgICAgLy8gUHJlLUZpbmFsIHZhbHVlcwoJICAgICAgICB2YXIgVDByID0gTUFyICsgTUNyOwoJICAgICAgICB2YXIgVDBpID0gTUFpICsgTUNpOwoJICAgICAgICB2YXIgVDFyID0gTUFyIC0gTUNyOwoJICAgICAgICB2YXIgVDFpID0gTUFpIC0gTUNpOwoJICAgICAgICB2YXIgVDJyID0gTUJyICsgTURyOwoJICAgICAgICB2YXIgVDJpID0gTUJpICsgTURpOwoJICAgICAgICB2YXIgVDNyID0gaW52ICogKE1CciAtIE1Ecik7CgkgICAgICAgIHZhciBUM2kgPSBpbnYgKiAoTUJpIC0gTURpKTsKCgkgICAgICAgIC8vIEZpbmFsIHZhbHVlcwoJICAgICAgICB2YXIgRkFyID0gVDByICsgVDJyOwoJICAgICAgICB2YXIgRkFpID0gVDBpICsgVDJpOwoKCSAgICAgICAgdmFyIEZCciA9IFQxciArIFQzaTsKCSAgICAgICAgdmFyIEZCaSA9IFQxaSAtIFQzcjsKCgkgICAgICAgIG91dFtBXSA9IEZBcjsKCSAgICAgICAgb3V0W0EgKyAxXSA9IEZBaTsKCSAgICAgICAgb3V0W0JdID0gRkJyOwoJICAgICAgICBvdXRbQiArIDFdID0gRkJpOwoKCSAgICAgICAgLy8gT3V0cHV0IGZpbmFsIG1pZGRsZSBwb2ludAoJICAgICAgICBpZiAoaSA9PT0gMCkgewoJICAgICAgICAgIHZhciBGQ3IgPSBUMHIgLSBUMnI7CgkgICAgICAgICAgdmFyIEZDaSA9IFQwaSAtIFQyaTsKCSAgICAgICAgICBvdXRbQ10gPSBGQ3I7CgkgICAgICAgICAgb3V0W0MgKyAxXSA9IEZDaTsKCSAgICAgICAgICBjb250aW51ZTsKCSAgICAgICAgfQoKCSAgICAgICAgLy8gRG8gbm90IG92ZXJ3cml0ZSBvdXJzZWx2ZXMKCSAgICAgICAgaWYgKGkgPT09IGhxdWFydGVyTGVuKQoJICAgICAgICAgIGNvbnRpbnVlOwoKCSAgICAgICAgLy8gSW4gdGhlIGZsaXBwZWQgY2FzZToKCSAgICAgICAgLy8gTUFpID0gLU1BaQoJICAgICAgICAvLyBNQnI9LU1CaSwgTUJpPS1NQnIKCSAgICAgICAgLy8gTUNyPS1NQ3IKCSAgICAgICAgLy8gTURyPU1EaSwgTURpPU1EcgoJICAgICAgICB2YXIgU1QwciA9IFQxcjsKCSAgICAgICAgdmFyIFNUMGkgPSAtVDFpOwoJICAgICAgICB2YXIgU1QxciA9IFQwcjsKCSAgICAgICAgdmFyIFNUMWkgPSAtVDBpOwoJICAgICAgICB2YXIgU1QyciA9IC1pbnYgKiBUM2k7CgkgICAgICAgIHZhciBTVDJpID0gLWludiAqIFQzcjsKCSAgICAgICAgdmFyIFNUM3IgPSAtaW52ICogVDJpOwoJICAgICAgICB2YXIgU1QzaSA9IC1pbnYgKiBUMnI7CgoJICAgICAgICB2YXIgU0ZBciA9IFNUMHIgKyBTVDJyOwoJICAgICAgICB2YXIgU0ZBaSA9IFNUMGkgKyBTVDJpOwoKCSAgICAgICAgdmFyIFNGQnIgPSBTVDFyICsgU1QzaTsKCSAgICAgICAgdmFyIFNGQmkgPSBTVDFpIC0gU1QzcjsKCgkgICAgICAgIHZhciBTQSA9IG91dE9mZiArIHF1YXJ0ZXJMZW4gLSBpOwoJICAgICAgICB2YXIgU0IgPSBvdXRPZmYgKyBoYWxmTGVuIC0gaTsKCgkgICAgICAgIG91dFtTQV0gPSBTRkFyOwoJICAgICAgICBvdXRbU0EgKyAxXSA9IFNGQWk7CgkgICAgICAgIG91dFtTQl0gPSBTRkJyOwoJICAgICAgICBvdXRbU0IgKyAxXSA9IFNGQmk7CgkgICAgICB9CgkgICAgfQoJICB9Cgl9OwoKCS8vIHJhZGl4LTIgaW1wbGVtZW50YXRpb24KCS8vCgkvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTQKCUZGVC5wcm90b3R5cGUuX3NpbmdsZVJlYWxUcmFuc2Zvcm0yID0gZnVuY3Rpb24gX3NpbmdsZVJlYWxUcmFuc2Zvcm0yKG91dE9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKCSAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwoJICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKCgkgIGNvbnN0IGV2ZW5SID0gZGF0YVtvZmZdOwoJICBjb25zdCBvZGRSID0gZGF0YVtvZmYgKyBzdGVwXTsKCgkgIGNvbnN0IGxlZnRSID0gZXZlblIgKyBvZGRSOwoJICBjb25zdCByaWdodFIgPSBldmVuUiAtIG9kZFI7CgoJICBvdXRbb3V0T2ZmXSA9IGxlZnRSOwoJICBvdXRbb3V0T2ZmICsgMV0gPSAwOwoJICBvdXRbb3V0T2ZmICsgMl0gPSByaWdodFI7CgkgIG91dFtvdXRPZmYgKyAzXSA9IDA7Cgl9OwoKCS8vIHJhZGl4LTQKCS8vCgkvLyBOT1RFOiBPbmx5IGNhbGxlZCBmb3IgbGVuPTgKCUZGVC5wcm90b3R5cGUuX3NpbmdsZVJlYWxUcmFuc2Zvcm00ID0gZnVuY3Rpb24gX3NpbmdsZVJlYWxUcmFuc2Zvcm00KG91dE9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZiwKCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXApIHsKCSAgY29uc3Qgb3V0ID0gdGhpcy5fb3V0OwoJICBjb25zdCBkYXRhID0gdGhpcy5fZGF0YTsKCSAgY29uc3QgaW52ID0gdGhpcy5faW52ID8gLTEgOiAxOwoJICBjb25zdCBzdGVwMiA9IHN0ZXAgKiAyOwoJICBjb25zdCBzdGVwMyA9IHN0ZXAgKiAzOwoKCSAgLy8gT3JpZ2luYWwgdmFsdWVzCgkgIGNvbnN0IEFyID0gZGF0YVtvZmZdOwoJICBjb25zdCBCciA9IGRhdGFbb2ZmICsgc3RlcF07CgkgIGNvbnN0IENyID0gZGF0YVtvZmYgKyBzdGVwMl07CgkgIGNvbnN0IERyID0gZGF0YVtvZmYgKyBzdGVwM107CgoJICAvLyBQcmUtRmluYWwgdmFsdWVzCgkgIGNvbnN0IFQwciA9IEFyICsgQ3I7CgkgIGNvbnN0IFQxciA9IEFyIC0gQ3I7CgkgIGNvbnN0IFQyciA9IEJyICsgRHI7CgkgIGNvbnN0IFQzciA9IGludiAqIChCciAtIERyKTsKCgkgIC8vIEZpbmFsIHZhbHVlcwoJICBjb25zdCBGQXIgPSBUMHIgKyBUMnI7CgoJICBjb25zdCBGQnIgPSBUMXI7CgkgIGNvbnN0IEZCaSA9IC1UM3I7CgoJICBjb25zdCBGQ3IgPSBUMHIgLSBUMnI7CgoJICBjb25zdCBGRHIgPSBUMXI7CgkgIGNvbnN0IEZEaSA9IFQzcjsKCgkgIG91dFtvdXRPZmZdID0gRkFyOwoJICBvdXRbb3V0T2ZmICsgMV0gPSAwOwoJICBvdXRbb3V0T2ZmICsgMl0gPSBGQnI7CgkgIG91dFtvdXRPZmYgKyAzXSA9IEZCaTsKCSAgb3V0W291dE9mZiArIDRdID0gRkNyOwoJICBvdXRbb3V0T2ZmICsgNV0gPSAwOwoJICBvdXRbb3V0T2ZmICsgNl0gPSBGRHI7CgkgIG91dFtvdXRPZmYgKyA3XSA9IEZEaTsKCX07CgoJdmFyIEZGVCQxID0gLypAX19QVVJFX18qL2dldERlZmF1bHRFeHBvcnRGcm9tQ2pzKGZmdCk7CgoJY29uc3QgV0VCQVVESU9fQkxPQ0tfU0laRSA9IDEyODsKCWNvbnN0IERFRkFVTFRfQkxPQ0tfU0laRSA9IDEwMjQ7IC8vIERlZmF1bHQgYmxvY2sgc2l6ZSBpZiBub3QgcHJvdmlkZWQgaW4gb3B0aW9ucwoJLyoqIE92ZXJsYXAtQWRkIE5vZGUgKi8KCWNsYXNzIE9MQVByb2Nlc3NvciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CgkgICAgbmJJbnB1dHM7CgkgICAgbmJPdXRwdXRzOwoJICAgIGJsb2NrU2l6ZTsKCSAgICBob3BTaXplOwoJICAgIG5iT3ZlcmxhcHM7CgkgICAgaW5wdXRCdWZmZXJzID0gW107CgkgICAgaW5wdXRCdWZmZXJzSGVhZCA9IFtdOwoJICAgIGlucHV0QnVmZmVyc1RvU2VuZCA9IFtdOwoJICAgIG91dHB1dEJ1ZmZlcnMgPSBbXTsKCSAgICBvdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSA9IFtdOwoJICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKCSAgICAgICAgc3VwZXIob3B0aW9ucyk7CgkgICAgICAgIHRoaXMubmJJbnB1dHMgPSBvcHRpb25zLm51bWJlck9mSW5wdXRzIHx8IDE7CgkgICAgICAgIHRoaXMubmJPdXRwdXRzID0gb3B0aW9ucy5udW1iZXJPZk91dHB1dHMgfHwgMTsKCSAgICAgICAgdGhpcy5ibG9ja1NpemUgPSBvcHRpb25zLnByb2Nlc3Nvck9wdGlvbnMuYmxvY2tTaXplIHx8IERFRkFVTFRfQkxPQ0tfU0laRTsKCSAgICAgICAgdGhpcy5ob3BTaXplID0gV0VCQVVESU9fQkxPQ0tfU0laRTsKCSAgICAgICAgdGhpcy5uYk92ZXJsYXBzID0gTWF0aC5mbG9vcih0aGlzLmJsb2NrU2l6ZSAvIHRoaXMuaG9wU2l6ZSk7CgkgICAgICAgIHRoaXMuaW5pdGlhbGl6ZUJ1ZmZlcnMoKTsKCSAgICB9CgkgICAgaW5pdGlhbGl6ZUJ1ZmZlcnMoKSB7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwoJICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWQgPSBuZXcgQXJyYXkodGhpcy5uYklucHV0cyk7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kID0gbmV3IEFycmF5KHRoaXMubmJJbnB1dHMpOwoJICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnMgPSBuZXcgQXJyYXkodGhpcy5uYk91dHB1dHMpOwoJICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNUb1JldHJpZXZlID0gbmV3IEFycmF5KHRoaXMubmJPdXRwdXRzKTsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVJbnB1dENoYW5uZWxzKGksIDEpOwoJICAgICAgICB9CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgdGhpcy5hbGxvY2F0ZU91dHB1dENoYW5uZWxzKGksIDEpOwoJICAgICAgICB9CgkgICAgfQoJICAgIGFsbG9jYXRlSW5wdXRDaGFubmVscyhpbnB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwoJICAgICAgICB0aGlzLmlucHV0QnVmZmVyc0hlYWRbaW5wdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CgkgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzVG9TZW5kW2lucHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwoJICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewoJICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplICsgV0VCQVVESU9fQkxPQ0tfU0laRSk7CgkgICAgICAgICAgICB0aGlzLmlucHV0QnVmZmVyc1tpbnB1dEluZGV4XVtpXS5maWxsKDApOwoJICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNIZWFkW2lucHV0SW5kZXhdW2ldID0gdGhpcy5pbnB1dEJ1ZmZlcnNbaW5wdXRJbmRleF1baV0uc3ViYXJyYXkoMCwgdGhpcy5ibG9ja1NpemUpOwoJICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmRbaW5wdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKCSAgICAgICAgfQoJICAgIH0KCSAgICBhbGxvY2F0ZU91dHB1dENoYW5uZWxzKG91dHB1dEluZGV4LCBuYkNoYW5uZWxzKSB7CgkgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1tvdXRwdXRJbmRleF0gPSBuZXcgQXJyYXkobmJDaGFubmVscyk7CgkgICAgICAgIHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbb3V0cHV0SW5kZXhdID0gbmV3IEFycmF5KG5iQ2hhbm5lbHMpOwoJICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iQ2hhbm5lbHM7IGkrKykgewoJICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5ibG9ja1NpemUpOwoJICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW291dHB1dEluZGV4XVtpXS5maWxsKDApOwoJICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZVtvdXRwdXRJbmRleF1baV0gPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuYmxvY2tTaXplKTsKCSAgICAgICAgfQoJICAgIH0KCSAgICByZWFsbG9jYXRlQ2hhbm5lbHNJZk5lZWRlZChpbnB1dHMsIG91dHB1dHMpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIGNvbnN0IG5iQ2hhbm5lbHMgPSBpbnB1dHNbaV0ubGVuZ3RoOwoJICAgICAgICAgICAgaWYgKG5iQ2hhbm5lbHMgIT09IHRoaXMuaW5wdXRCdWZmZXJzW2ldLmxlbmd0aCkgewoJICAgICAgICAgICAgICAgIHRoaXMuYWxsb2NhdGVJbnB1dENoYW5uZWxzKGksIG5iQ2hhbm5lbHMpOwoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgY29uc3QgbmJDaGFubmVscyA9IG91dHB1dHNbaV0ubGVuZ3RoOwoJICAgICAgICAgICAgaWYgKG5iQ2hhbm5lbHMgIT09IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGgpIHsKCSAgICAgICAgICAgICAgICB0aGlzLmFsbG9jYXRlT3V0cHV0Q2hhbm5lbHMoaSwgbmJDaGFubmVscyk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgcmVhZElucHV0cyhpbnB1dHMpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5pbnB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKCSAgICAgICAgICAgICAgICBjb25zdCB3ZWJBdWRpb0Jsb2NrID0gaW5wdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHRoaXMuaW5wdXRCdWZmZXJzW2ldW2pdLnNldCh3ZWJBdWRpb0Jsb2NrLCB0aGlzLmJsb2NrU2l6ZSk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgd3JpdGVPdXRwdXRzKG91dHB1dHMpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iT3V0cHV0czsgaSsrKSB7CgkgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMub3V0cHV0QnVmZmVyc1tpXS5sZW5ndGg7IGorKykgewoJICAgICAgICAgICAgICAgIGNvbnN0IHdlYkF1ZGlvQmxvY2sgPSBvdXRwdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHdlYkF1ZGlvQmxvY2suc2V0KHRoaXMub3V0cHV0QnVmZmVyc1tpXVtqXS5zdWJhcnJheSgwLCBXRUJBVURJT19CTE9DS19TSVpFKSk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgc2hpZnRJbnB1dEJ1ZmZlcnMoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CgkgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMuaW5wdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CgkgICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNbaV1bal0uY29weVdpdGhpbigwLCBXRUJBVURJT19CTE9DS19TSVpFKTsKCSAgICAgICAgICAgIH0KCSAgICAgICAgfQoJICAgIH0KCSAgICBzaGlmdE91dHB1dEJ1ZmZlcnMoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm91dHB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKCSAgICAgICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal0uY29weVdpdGhpbigwLCBXRUJBVURJT19CTE9DS19TSVpFKTsKCSAgICAgICAgICAgICAgICB0aGlzLm91dHB1dEJ1ZmZlcnNbaV1bal0uZmlsbCgwLCB0aGlzLmJsb2NrU2l6ZSAtIFdFQkFVRElPX0JMT0NLX1NJWkUpOwoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgfQoJICAgIHByZXBhcmVJbnB1dEJ1ZmZlcnNUb1NlbmQoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYklucHV0czsgaSsrKSB7CgkgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRoaXMuaW5wdXRCdWZmZXJzW2ldLmxlbmd0aDsgaisrKSB7CgkgICAgICAgICAgICAgICAgdGhpcy5pbnB1dEJ1ZmZlcnNUb1NlbmRbaV1bal0uc2V0KHRoaXMuaW5wdXRCdWZmZXJzSGVhZFtpXVtqXSk7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9CgkgICAgaGFuZGxlT3V0cHV0QnVmZmVyc1RvUmV0cmlldmUoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYk91dHB1dHM7IGkrKykgewoJICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLm91dHB1dEJ1ZmZlcnNbaV0ubGVuZ3RoOyBqKyspIHsKCSAgICAgICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRoaXMuYmxvY2tTaXplOyBrKyspIHsKCSAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRCdWZmZXJzW2ldW2pdW2tdICs9IHRoaXMub3V0cHV0QnVmZmVyc1RvUmV0cmlldmVbaV1bal1ba10gLyB0aGlzLm5iT3ZlcmxhcHM7CgkgICAgICAgICAgICAgICAgfQoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgfQoJICAgIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CgkgICAgICAgIHRoaXMucmVhbGxvY2F0ZUNoYW5uZWxzSWZOZWVkZWQoaW5wdXRzLCBvdXRwdXRzKTsKCSAgICAgICAgdGhpcy5yZWFkSW5wdXRzKGlucHV0cyk7CgkgICAgICAgIHRoaXMuc2hpZnRJbnB1dEJ1ZmZlcnMoKTsKCSAgICAgICAgdGhpcy5wcmVwYXJlSW5wdXRCdWZmZXJzVG9TZW5kKCk7CgkgICAgICAgIHRoaXMucHJvY2Vzc09MQSh0aGlzLmlucHV0QnVmZmVyc1RvU2VuZCwgdGhpcy5vdXRwdXRCdWZmZXJzVG9SZXRyaWV2ZSwgcGFyYW1ldGVycyk7CgkgICAgICAgIHRoaXMuaGFuZGxlT3V0cHV0QnVmZmVyc1RvUmV0cmlldmUoKTsKCSAgICAgICAgdGhpcy53cml0ZU91dHB1dHMob3V0cHV0cyk7CgkgICAgICAgIHRoaXMuc2hpZnRPdXRwdXRCdWZmZXJzKCk7CgkgICAgICAgIHJldHVybiB0cnVlOwoJICAgIH0KCX0KCgljb25zdCBCVUZGRVJFRF9CTE9DS19TSVpFID0gMjA0ODsKCWZ1bmN0aW9uIGdlbkhhbm5XaW5kb3cobGVuZ3RoKSB7CgkgICAgY29uc3Qgd2luID0gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpOwoJICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKCSAgICAgICAgd2luW2ldID0gMC41ICogKDEgLSBNYXRoLmNvcygoMiAqIE1hdGguUEkgKiBpKSAvIGxlbmd0aCkpOwoJICAgIH0KCSAgICByZXR1cm4gd2luOwoJfQoJY2xhc3MgUGhhc2VWb2NvZGVyUHJvY2Vzc29yIGV4dGVuZHMgT0xBUHJvY2Vzc29yIHsKCSAgICBmZnRTaXplOwoJICAgIHRpbWVDdXJzb3I7CgkgICAgaGFubldpbmRvdzsKCSAgICBmZnQ7CgkgICAgZnJlcUNvbXBsZXhCdWZmZXI7CgkgICAgZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkOwoJICAgIHRpbWVDb21wbGV4QnVmZmVyOwoJICAgIG1hZ25pdHVkZXM7CgkgICAgcGVha0luZGV4ZXM7CgkgICAgbmJQZWFrczsKCSAgICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewoJICAgICAgICByZXR1cm4gWwoJICAgICAgICAgICAgewoJICAgICAgICAgICAgICAgIG5hbWU6ICJwaXRjaEZhY3RvciIsCgkgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiAxLjAsCgkgICAgICAgICAgICB9LAoJICAgICAgICBdOwoJICAgIH0KCSAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CgkgICAgICAgIG9wdGlvbnMucHJvY2Vzc29yT3B0aW9ucyA9IHsKCSAgICAgICAgICAgIGJsb2NrU2l6ZTogQlVGRkVSRURfQkxPQ0tfU0laRSwKCSAgICAgICAgfTsKCSAgICAgICAgc3VwZXIob3B0aW9ucyk7CgkgICAgICAgIHRoaXMuZmZ0U2l6ZSA9IHRoaXMuYmxvY2tTaXplOwoJICAgICAgICB0aGlzLnRpbWVDdXJzb3IgPSAwOwoJICAgICAgICB0aGlzLmhhbm5XaW5kb3cgPSBnZW5IYW5uV2luZG93KHRoaXMuYmxvY2tTaXplKTsKCSAgICAgICAgLy8gcHJlcGFyZSBGRlQgYW5kIHByZS1hbGxvY2F0ZSBidWZmZXJzCgkgICAgICAgIHRoaXMuZmZ0ID0gbmV3IEZGVCQxKHRoaXMuZmZ0U2l6ZSk7CgkgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKCSAgICAgICAgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQgPSB0aGlzLmZmdC5jcmVhdGVDb21wbGV4QXJyYXkoKTsKCSAgICAgICAgdGhpcy50aW1lQ29tcGxleEJ1ZmZlciA9IHRoaXMuZmZ0LmNyZWF0ZUNvbXBsZXhBcnJheSgpOwoJICAgICAgICB0aGlzLm1hZ25pdHVkZXMgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZmZ0U2l6ZSAvIDIgKyAxKTsKCSAgICAgICAgdGhpcy5wZWFrSW5kZXhlcyA9IG5ldyBJbnQzMkFycmF5KHRoaXMubWFnbml0dWRlcy5sZW5ndGgpOwoJICAgICAgICB0aGlzLm5iUGVha3MgPSAwOwoJICAgIH0KCSAgICBwcm9jZXNzT0xBKGlucHV0cywgb3V0cHV0cywgcGFyYW1ldGVycykgewoJICAgICAgICBjb25zdCBwaXRjaEZhY3RvciA9IHBhcmFtZXRlcnMucGl0Y2hGYWN0b3JbcGFyYW1ldGVycy5waXRjaEZhY3Rvci5sZW5ndGggLSAxXTsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5iSW5wdXRzOyBpKyspIHsKCSAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaW5wdXRzW2ldLmxlbmd0aDsgaisrKSB7CgkgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gaW5wdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBvdXRwdXRzW2ldW2pdOwoJICAgICAgICAgICAgICAgIHRoaXMuYXBwbHlIYW5uV2luZG93KGlucHV0KTsKCSAgICAgICAgICAgICAgICB0aGlzLmZmdC5yZWFsVHJhbnNmb3JtKHRoaXMuZnJlcUNvbXBsZXhCdWZmZXIsIGlucHV0KTsKCSAgICAgICAgICAgICAgICB0aGlzLmNvbXB1dGVNYWduaXR1ZGVzKCk7CgkgICAgICAgICAgICAgICAgdGhpcy5maW5kUGVha3MoKTsKCSAgICAgICAgICAgICAgICB0aGlzLnNoaWZ0UGVha3MocGl0Y2hGYWN0b3IpOwoJICAgICAgICAgICAgICAgIHRoaXMuZmZ0LmNvbXBsZXRlU3BlY3RydW0odGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQpOwoJICAgICAgICAgICAgICAgIHRoaXMuZmZ0LmludmVyc2VUcmFuc2Zvcm0odGhpcy50aW1lQ29tcGxleEJ1ZmZlciwgdGhpcy5mcmVxQ29tcGxleEJ1ZmZlclNoaWZ0ZWQpOwoJICAgICAgICAgICAgICAgIHRoaXMuZmZ0LmZyb21Db21wbGV4QXJyYXkodGhpcy50aW1lQ29tcGxleEJ1ZmZlciwgb3V0cHV0KTsKCSAgICAgICAgICAgICAgICB0aGlzLmFwcGx5SGFubldpbmRvdyhvdXRwdXQpOwoJICAgICAgICAgICAgfQoJICAgICAgICB9CgkgICAgICAgIHRoaXMudGltZUN1cnNvciArPSB0aGlzLmhvcFNpemU7CgkgICAgICAgIHJldHVybiB0cnVlOwoJICAgIH0KCSAgICBhcHBseUhhbm5XaW5kb3coaW5wdXQpIHsKCSAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmJsb2NrU2l6ZTsgaSsrKSB7CgkgICAgICAgICAgICBpbnB1dFtpXSAqPSB0aGlzLmhhbm5XaW5kb3dbaV07CgkgICAgICAgIH0KCSAgICB9CgkgICAgY29tcHV0ZU1hZ25pdHVkZXMoKSB7CgkgICAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IHRoaXMubWFnbml0dWRlcy5sZW5ndGg7IGkrKywgaiArPSAyKSB7CgkgICAgICAgICAgICBjb25zdCByZWFsID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltqXTsKCSAgICAgICAgICAgIGNvbnN0IGltYWcgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2ogKyAxXTsKCSAgICAgICAgICAgIHRoaXMubWFnbml0dWRlc1tpXSA9IHJlYWwgKiogMiArIGltYWcgKiogMjsKCSAgICAgICAgfQoJICAgIH0KCSAgICBmaW5kUGVha3MoKSB7CgkgICAgICAgIHRoaXMubmJQZWFrcyA9IDA7CgkgICAgICAgIGZvciAobGV0IGkgPSAyLCBlbmQgPSB0aGlzLm1hZ25pdHVkZXMubGVuZ3RoIC0gMjsgaSA8IGVuZDsgaSsrKSB7CgkgICAgICAgICAgICBjb25zdCBtYWcgPSB0aGlzLm1hZ25pdHVkZXNbaV07CgkgICAgICAgICAgICBpZiAodGhpcy5tYWduaXR1ZGVzW2kgLSAxXSA+PSBtYWcgfHwKCSAgICAgICAgICAgICAgICB0aGlzLm1hZ25pdHVkZXNbaSAtIDJdID49IG1hZyB8fAoJICAgICAgICAgICAgICAgIHRoaXMubWFnbml0dWRlc1tpICsgMV0gPj0gbWFnIHx8CgkgICAgICAgICAgICAgICAgdGhpcy5tYWduaXR1ZGVzW2kgKyAyXSA+PSBtYWcpIHsKCSAgICAgICAgICAgICAgICBjb250aW51ZTsKCSAgICAgICAgICAgIH0KCSAgICAgICAgICAgIHRoaXMucGVha0luZGV4ZXNbdGhpcy5uYlBlYWtzKytdID0gaTsKCSAgICAgICAgfQoJICAgIH0KCSAgICBzaGlmdFBlYWtzKHBpdGNoRmFjdG9yKSB7CgkgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkLmZpbGwoMCk7CgkgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5uYlBlYWtzOyBpKyspIHsKCSAgICAgICAgICAgIGNvbnN0IHBlYWtJbmRleCA9IHRoaXMucGVha0luZGV4ZXNbaV07CgkgICAgICAgICAgICBjb25zdCBwZWFrSW5kZXhTaGlmdGVkID0gTWF0aC5yb3VuZChwZWFrSW5kZXggKiBwaXRjaEZhY3Rvcik7CgkgICAgICAgICAgICBpZiAocGVha0luZGV4U2hpZnRlZCA+IHRoaXMubWFnbml0dWRlcy5sZW5ndGgpIHsKCSAgICAgICAgICAgICAgICBicmVhazsKCSAgICAgICAgICAgIH0KCSAgICAgICAgICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBpID4gMCA/IHBlYWtJbmRleCAtIE1hdGguZmxvb3IoKHBlYWtJbmRleCAtIHRoaXMucGVha0luZGV4ZXNbaSAtIDFdKSAvIDIpIDogMDsKCSAgICAgICAgICAgIGNvbnN0IGVuZEluZGV4ID0gaSA8IHRoaXMubmJQZWFrcyAtIDEgPyBwZWFrSW5kZXggKyBNYXRoLmNlaWwoKHRoaXMucGVha0luZGV4ZXNbaSArIDFdIC0gcGVha0luZGV4KSAvIDIpIDogdGhpcy5mZnRTaXplOwoJICAgICAgICAgICAgZm9yIChsZXQgaiA9IHN0YXJ0SW5kZXggLSBwZWFrSW5kZXg7IGogPCBlbmRJbmRleCAtIHBlYWtJbmRleDsgaisrKSB7CgkgICAgICAgICAgICAgICAgY29uc3QgYmluSW5kZXggPSBwZWFrSW5kZXggKyBqOwoJICAgICAgICAgICAgICAgIGNvbnN0IGJpbkluZGV4U2hpZnRlZCA9IHBlYWtJbmRleFNoaWZ0ZWQgKyBqOwoJICAgICAgICAgICAgICAgIGlmIChiaW5JbmRleFNoaWZ0ZWQgPj0gdGhpcy5tYWduaXR1ZGVzLmxlbmd0aCkgewoJICAgICAgICAgICAgICAgICAgICBicmVhazsKCSAgICAgICAgICAgICAgICB9CgkgICAgICAgICAgICAgICAgY29uc3Qgb21lZ2FEZWx0YSA9ICgyICogTWF0aC5QSSAqIChiaW5JbmRleFNoaWZ0ZWQgLSBiaW5JbmRleCkpIC8gdGhpcy5mZnRTaXplOwoJICAgICAgICAgICAgICAgIGNvbnN0IHBoYXNlU2hpZnRSZWFsID0gTWF0aC5jb3Mob21lZ2FEZWx0YSAqIHRoaXMudGltZUN1cnNvcik7CgkgICAgICAgICAgICAgICAgY29uc3QgcGhhc2VTaGlmdEltYWcgPSBNYXRoLnNpbihvbWVnYURlbHRhICogdGhpcy50aW1lQ3Vyc29yKTsKCSAgICAgICAgICAgICAgICBjb25zdCBpbmRleFJlYWwgPSBiaW5JbmRleCAqIDI7CgkgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhJbWFnID0gaW5kZXhSZWFsICsgMTsKCSAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVJlYWwgPSB0aGlzLmZyZXFDb21wbGV4QnVmZmVyW2luZGV4UmVhbF07CgkgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVJbWFnID0gdGhpcy5mcmVxQ29tcGxleEJ1ZmZlcltpbmRleEltYWddOwoJICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZFJlYWwgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0UmVhbCAtIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRJbWFnOwoJICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU2hpZnRlZEltYWcgPSB2YWx1ZVJlYWwgKiBwaGFzZVNoaWZ0SW1hZyArIHZhbHVlSW1hZyAqIHBoYXNlU2hpZnRSZWFsOwoJICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZFJlYWwgPSBiaW5JbmRleFNoaWZ0ZWQgKiAyOwoJICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4U2hpZnRlZEltYWcgPSBpbmRleFNoaWZ0ZWRSZWFsICsgMTsKCSAgICAgICAgICAgICAgICB0aGlzLmZyZXFDb21wbGV4QnVmZmVyU2hpZnRlZFtpbmRleFNoaWZ0ZWRSZWFsXSArPSB2YWx1ZVNoaWZ0ZWRSZWFsOwoJICAgICAgICAgICAgICAgIHRoaXMuZnJlcUNvbXBsZXhCdWZmZXJTaGlmdGVkW2luZGV4U2hpZnRlZEltYWddICs9IHZhbHVlU2hpZnRlZEltYWc7CgkgICAgICAgICAgICB9CgkgICAgICAgIH0KCSAgICB9Cgl9CgkvLyBAdHMtZXhwZWN0LWVycm9yCglyZWdpc3RlclByb2Nlc3NvcigicGhhc2Utdm9jb2RlciIsIFBoYXNlVm9jb2RlclByb2Nlc3Nvcik7Cgljb25zb2xlLmxvZygiUGhhc2VWb2NvZGVyUHJvY2Vzc29yIHJlZ2lzdGVyZWQiKTsKCglleHBvcnRzLlBoYXNlVm9jb2RlclByb2Nlc3NvciA9IFBoYXNlVm9jb2RlclByb2Nlc3NvcjsKCglyZXR1cm4gZXhwb3J0czsKCn0pKHt9KTsKLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGhhc2Utdm9jb2Rlci1idW5kbGUuanMubWFwCg==",k="data:text/javascript;base64,dmFyIHN0ZXJlb1RvQmZvcm1hdCA9IChmdW5jdGlvbiAoZXhwb3J0cykgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIGNvbnN0IEJVVFRFUldPUlRIX1EgPSBNYXRoLlNRUlQxXzI7CiAgICBjb25zdCBMT1dfQ1VUT0ZGX0haID0gMjUwOwogICAgY29uc3QgSElHSF9DVVRPRkZfSFogPSAyMDAwOwogICAgLy8gVGllciAxIHBlcmNlcHR1YWwgdHVuaW5nOgogICAgLy8gLSBLZWVwIGxvdy1iYW5kIGVuZXJneSBtb3N0bHkgb21uaWRpcmVjdGlvbmFsLgogICAgLy8gLSBSZWR1Y2UgVyByZWxhdGl2ZSB0byB0aGUgb3JpZ2luYWwgc3FydCgxLzIpIG1hcHBpbmcuCiAgICAvLyAtIExldCB1cHBlciBiYW5kcyBjYXJyeSBtb3JlIG9mIHRoZSBob3Jpem9udGFsIGN1ZS4KICAgIGNvbnN0IFdfR0FJTl9MT1cgPSAwLjU7CiAgICBjb25zdCBXX0dBSU5fTUlEID0gMC40NTsKICAgIGNvbnN0IFdfR0FJTl9ISUdIID0gMC4zNTsKICAgIGNvbnN0IFhfR0FJTl9MT1cgPSAwOwogICAgY29uc3QgWF9HQUlOX01JRCA9IDAuMzU7CiAgICBjb25zdCBYX0dBSU5fSElHSCA9IDAuNTU7CiAgICBjb25zdCBZX0dBSU5fTE9XID0gMDsKICAgIGNvbnN0IFlfR0FJTl9NSUQgPSAwLjU7CiAgICBjb25zdCBZX0dBSU5fSElHSCA9IDAuODU7CiAgICAvLyBDb2hlcmVuY2Ugc21vb3RoaW5nLiBFeHBvbmVudGlhbCBmaXJzdC1vcmRlciBsb3ctcGFzcyBvbiBwZXItYmFuZCBwb3dlcgogICAgLy8gYW5kIGNyb3NzLXBvd2VyLiBBbHBoYSBjbG9zZXIgdG8gMSBtZWFucyBzbG93ZXIgdHJhY2tpbmc7IHRoaXMgdmFsdWUgZ2l2ZXMKICAgIC8vIGEgdGltZSBjb25zdGFudCBvZiBhYm91dCAyMCBtcyBhdCA0OCBrSHosIHdoaWNoIGxpbmVzIHVwIHdpdGggQkNDLXBhcGVyCiAgICAvLyByZWNvbW1lbmRhdGlvbnMgZm9yIHBlcmNlcHR1YWwtY3VlIHNtb290aGluZy4KICAgIGNvbnN0IENPSEVSRU5DRV9TTU9PVEhJTkdfQUxQSEEgPSAwLjk5OTsKICAgIC8vIE51bWVyaWNhbCBmbG9vciBvbiBwZXItYmFuZCBwb3dlciBzbyB0aGUgSUNDIGRlbm9taW5hdG9yIG5ldmVyIGJsb3dzIHVwCiAgICAvLyBkdXJpbmcgc2lsZW5jZS4KICAgIGNvbnN0IENPSEVSRU5DRV9QT1dFUl9FUFNJTE9OID0gMWUtMTI7CiAgICBjbGFzcyBCaXF1YWRGaWx0ZXIgewogICAgICAgIGIwID0gMDsKICAgICAgICBiMSA9IDA7CiAgICAgICAgYjIgPSAwOwogICAgICAgIGExID0gMDsKICAgICAgICBhMiA9IDA7CiAgICAgICAgeDEgPSAwOwogICAgICAgIHgyID0gMDsKICAgICAgICB5MSA9IDA7CiAgICAgICAgeTIgPSAwOwogICAgICAgIGNvbnN0cnVjdG9yKHR5cGUsIHNhbXBsZVJhdGUsIGN1dG9mZkh6LCBxID0gQlVUVEVSV09SVEhfUSkgewogICAgICAgICAgICB0aGlzLmNvbmZpZ3VyZSh0eXBlLCBzYW1wbGVSYXRlLCBjdXRvZmZIeiwgcSk7CiAgICAgICAgfQogICAgICAgIGNvbmZpZ3VyZSh0eXBlLCBzYW1wbGVSYXRlLCBjdXRvZmZIeiwgcSkgewogICAgICAgICAgICBjb25zdCBjbGFtcGVkQ3V0b2ZmID0gTWF0aC5tYXgoMSwgTWF0aC5taW4oY3V0b2ZmSHosIHNhbXBsZVJhdGUgKiAwLjQ1KSk7CiAgICAgICAgICAgIGNvbnN0IG9tZWdhID0gKDIgKiBNYXRoLlBJICogY2xhbXBlZEN1dG9mZikgLyBzYW1wbGVSYXRlOwogICAgICAgICAgICBjb25zdCBzaW4gPSBNYXRoLnNpbihvbWVnYSk7CiAgICAgICAgICAgIGNvbnN0IGNvcyA9IE1hdGguY29zKG9tZWdhKTsKICAgICAgICAgICAgY29uc3QgYWxwaGEgPSBzaW4gLyAoMiAqIHEpOwogICAgICAgICAgICBsZXQgYjA7CiAgICAgICAgICAgIGxldCBiMTsKICAgICAgICAgICAgbGV0IGIyOwogICAgICAgICAgICBpZiAodHlwZSA9PT0gImxvd3Bhc3MiKSB7CiAgICAgICAgICAgICAgICBiMCA9ICgxIC0gY29zKSAvIDI7CiAgICAgICAgICAgICAgICBiMSA9IDEgLSBjb3M7CiAgICAgICAgICAgICAgICBiMiA9ICgxIC0gY29zKSAvIDI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBiMCA9ICgxICsgY29zKSAvIDI7CiAgICAgICAgICAgICAgICBiMSA9IC0oMSArIGNvcyk7CiAgICAgICAgICAgICAgICBiMiA9ICgxICsgY29zKSAvIDI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYTAgPSAxICsgYWxwaGE7CiAgICAgICAgICAgIGNvbnN0IGExID0gLTIgKiBjb3M7CiAgICAgICAgICAgIGNvbnN0IGEyID0gMSAtIGFscGhhOwogICAgICAgICAgICB0aGlzLmIwID0gYjAgLyBhMDsKICAgICAgICAgICAgdGhpcy5iMSA9IGIxIC8gYTA7CiAgICAgICAgICAgIHRoaXMuYjIgPSBiMiAvIGEwOwogICAgICAgICAgICB0aGlzLmExID0gYTEgLyBhMDsKICAgICAgICAgICAgdGhpcy5hMiA9IGEyIC8gYTA7CiAgICAgICAgfQogICAgICAgIHByb2Nlc3MoaW5wdXQpIHsKICAgICAgICAgICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5iMCAqIGlucHV0ICsgdGhpcy5iMSAqIHRoaXMueDEgKyB0aGlzLmIyICogdGhpcy54MiAtIHRoaXMuYTEgKiB0aGlzLnkxIC0gdGhpcy5hMiAqIHRoaXMueTI7CiAgICAgICAgICAgIHRoaXMueDIgPSB0aGlzLngxOwogICAgICAgICAgICB0aGlzLngxID0gaW5wdXQ7CiAgICAgICAgICAgIHRoaXMueTIgPSB0aGlzLnkxOwogICAgICAgICAgICB0aGlzLnkxID0gb3V0cHV0OwogICAgICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogUnVubmluZyBwZXItYmFuZCBpbnRlci1jaGFubmVsIGNvaGVyZW5jZSBlc3RpbWF0b3IuCiAgICAgKgogICAgICogTWFpbnRhaW5zIGV4cG9uZW50aWFsbHkgc21vb3RoZWQgZXN0aW1hdGVzIG9mIEwqTCwgUipSLCBhbmQgTCpSLCB0aGVuCiAgICAgKiBkZXJpdmVzIGEgbm9ybWFsaXplZCBjb2hlcmVuY2UgdmFsdWUgYHw8TFI+fCAvIHNxcnQoPEzCsj4gKiA8UsKyPilgIGluCiAgICAgKiB0aGUgcmFuZ2UgWzAsIDFdLiBIaWdoIGNvaGVyZW5jZSBpbmRpY2F0ZXMgYSBzdGFibGUgaW4tcGhhc2UgLyBwYW5uZWQKICAgICAqIHNvdXJjZTsgbG93IGNvaGVyZW5jZSBpbmRpY2F0ZXMgZGVjb3JyZWxhdGVkIGRpZmZ1c2UgY29udGVudCBsaWtlIHJvb20KICAgICAqIHJldmVyYi4KICAgICAqCiAgICAgKiBUaGUgc2lnbiBvZiA8TFI+IGlzIHByZXNlcnZlZCBpbnRlcm5hbGx5IHNvIGNhbGxlcnMgY2FuIGRpZmZlcmVudGlhdGUKICAgICAqIHBvc2l0aXZlIChpbi1waGFzZSAvIGNlbnRlcikgZnJvbSBuZWdhdGl2ZSAoYW50aS1waGFzZSkgY29ycmVsYXRpb24sCiAgICAgKiBidXQgdGhlIHB1YmxpYyBgY29oZXJlbmNlKClgIGhlbHBlciByZXR1cm5zIG1hZ25pdHVkZSBvbmx5LgogICAgICovCiAgICBjbGFzcyBDcm9zc0NvcnJlbGF0b3IgewogICAgICAgIHNtb290aGVkTEwgPSAwOwogICAgICAgIHNtb290aGVkUlIgPSAwOwogICAgICAgIHNtb290aGVkTFIgPSAwOwogICAgICAgIGFscGhhOwogICAgICAgIG9uZU1pbnVzQWxwaGE7CiAgICAgICAgY29uc3RydWN0b3IoYWxwaGEgPSBDT0hFUkVOQ0VfU01PT1RISU5HX0FMUEhBKSB7CiAgICAgICAgICAgIHRoaXMuYWxwaGEgPSBhbHBoYTsKICAgICAgICAgICAgdGhpcy5vbmVNaW51c0FscGhhID0gMSAtIGFscGhhOwogICAgICAgIH0KICAgICAgICB1cGRhdGUobGVmdCwgcmlnaHQpIHsKICAgICAgICAgICAgdGhpcy5zbW9vdGhlZExMID0gdGhpcy5hbHBoYSAqIHRoaXMuc21vb3RoZWRMTCArIHRoaXMub25lTWludXNBbHBoYSAqIGxlZnQgKiBsZWZ0OwogICAgICAgICAgICB0aGlzLnNtb290aGVkUlIgPSB0aGlzLmFscGhhICogdGhpcy5zbW9vdGhlZFJSICsgdGhpcy5vbmVNaW51c0FscGhhICogcmlnaHQgKiByaWdodDsKICAgICAgICAgICAgdGhpcy5zbW9vdGhlZExSID0gdGhpcy5hbHBoYSAqIHRoaXMuc21vb3RoZWRMUiArIHRoaXMub25lTWludXNBbHBoYSAqIGxlZnQgKiByaWdodDsKICAgICAgICB9CiAgICAgICAgLyoqIE1hZ25pdHVkZSBvZiBub3JtYWxpemVkIGNyb3NzLWNvcnJlbGF0aW9uIGluIFswLCAxXS4gKi8KICAgICAgICBjb2hlcmVuY2UoKSB7CiAgICAgICAgICAgIGNvbnN0IGRlbm9tID0gTWF0aC5zcXJ0KHRoaXMuc21vb3RoZWRMTCAqIHRoaXMuc21vb3RoZWRSUikgKyBDT0hFUkVOQ0VfUE9XRVJfRVBTSUxPTjsKICAgICAgICAgICAgY29uc3QgYyA9IE1hdGguYWJzKHRoaXMuc21vb3RoZWRMUikgLyBkZW5vbTsKICAgICAgICAgICAgcmV0dXJuIGMgPiAxID8gMSA6IGM7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIFNpZ25lZCBub3JtYWxpemVkIGNyb3NzLWNvcnJlbGF0aW9uIGluIFstMSwgKzFdLgogICAgICAgICAqCiAgICAgICAgICogLSArMTogcGVyZmVjdGx5IGluLXBoYXNlIChMIGFuZCBSIG1vdmUgdG9nZXRoZXIsIG1vbm8gLyBjZW50ZXIgcGFuKQogICAgICAgICAqIC0gMDogdW5jb3JyZWxhdGVkIChkaWZmdXNlIGFtYmllbnQsIGhhcmQtcGFubmVkIHNpbmdsZSBzb3VyY2UpCiAgICAgICAgICogLSAtMTogcGVyZmVjdGx5IGFudGktcGhhc2UgKEwgYW5kIFIgbW92ZSBvcHBvc2l0ZWx5LCBzdGVyZW8gd2lkdGgKICAgICAgICAgKiAgIHRyaWNrcyBvciBvdXQtb2YtcGhhc2UgY29udGVudCkKICAgICAgICAgKgogICAgICAgICAqIEZyb250L2JhY2sgcm91dGluZyB3YW50cyBwb3NpdGl2ZSBjb3JyZWxhdGlvbiAocmVhbCBjZW50ZXIgbWF0ZXJpYWwpLgogICAgICAgICAqIExlZnQvcmlnaHQgcm91dGluZyB3YW50cyB3aGF0ZXZlciBpc24ndCBpbi1waGFzZSAoYW55dGhpbmcgdGhhdCBoYXMKICAgICAgICAgKiBhIHN0YWJsZSBkaWZmZXJlbmNlIGJldHdlZW4gY2hhbm5lbHMsIGluY2x1ZGluZyBoYXJkIHBhbnMpLgogICAgICAgICAqLwogICAgICAgIHNpZ25lZENvaGVyZW5jZSgpIHsKICAgICAgICAgICAgY29uc3QgZGVub20gPSBNYXRoLnNxcnQodGhpcy5zbW9vdGhlZExMICogdGhpcy5zbW9vdGhlZFJSKSArIENPSEVSRU5DRV9QT1dFUl9FUFNJTE9OOwogICAgICAgICAgICBjb25zdCBjID0gdGhpcy5zbW9vdGhlZExSIC8gZGVub207CiAgICAgICAgICAgIGlmIChjID4gMSkKICAgICAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgICAgICBpZiAoYyA8IC0xKQogICAgICAgICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgICAgICByZXR1cm4gYzsKICAgICAgICB9CiAgICB9CiAgICBjbGFzcyBTdGVyZW9Ub0ZvYVVwbWl4ZXIgewogICAgICAgIGxvd0xlZnQ7CiAgICAgICAgbG93UmlnaHQ7CiAgICAgICAgaGlnaExlZnQ7CiAgICAgICAgaGlnaFJpZ2h0OwogICAgICAgIGxvd0NvaGVyZW5jZTsKICAgICAgICBtaWRDb2hlcmVuY2U7CiAgICAgICAgaGlnaENvaGVyZW5jZTsKICAgICAgICBjb25zdHJ1Y3RvcihzYW1wbGVSYXRlKSB7CiAgICAgICAgICAgIHRoaXMubG93TGVmdCA9IG5ldyBCaXF1YWRGaWx0ZXIoImxvd3Bhc3MiLCBzYW1wbGVSYXRlLCBMT1dfQ1VUT0ZGX0haKTsKICAgICAgICAgICAgdGhpcy5sb3dSaWdodCA9IG5ldyBCaXF1YWRGaWx0ZXIoImxvd3Bhc3MiLCBzYW1wbGVSYXRlLCBMT1dfQ1VUT0ZGX0haKTsKICAgICAgICAgICAgdGhpcy5oaWdoTGVmdCA9IG5ldyBCaXF1YWRGaWx0ZXIoImhpZ2hwYXNzIiwgc2FtcGxlUmF0ZSwgSElHSF9DVVRPRkZfSFopOwogICAgICAgICAgICB0aGlzLmhpZ2hSaWdodCA9IG5ldyBCaXF1YWRGaWx0ZXIoImhpZ2hwYXNzIiwgc2FtcGxlUmF0ZSwgSElHSF9DVVRPRkZfSFopOwogICAgICAgICAgICB0aGlzLmxvd0NvaGVyZW5jZSA9IG5ldyBDcm9zc0NvcnJlbGF0b3IoKTsKICAgICAgICAgICAgdGhpcy5taWRDb2hlcmVuY2UgPSBuZXcgQ3Jvc3NDb3JyZWxhdG9yKCk7CiAgICAgICAgICAgIHRoaXMuaGlnaENvaGVyZW5jZSA9IG5ldyBDcm9zc0NvcnJlbGF0b3IoKTsKICAgICAgICB9CiAgICAgICAgcHJvY2VzcyhsZWZ0LCByaWdodCwgdywgeSwgeiwgeCkgewogICAgICAgICAgICBjb25zdCBmcmFtZUNvdW50ID0gTWF0aC5taW4obGVmdC5sZW5ndGgsIHJpZ2h0Lmxlbmd0aCwgdy5sZW5ndGgsIHgubGVuZ3RoLCB5Lmxlbmd0aCwgei5sZW5ndGgpOwogICAgICAgICAgICBmb3IgKGxldCBmcmFtZSA9IDA7IGZyYW1lIDwgZnJhbWVDb3VudDsgZnJhbWUrKykgewogICAgICAgICAgICAgICAgY29uc3QgbGVmdFNhbXBsZSA9IGxlZnRbZnJhbWVdOwogICAgICAgICAgICAgICAgY29uc3QgcmlnaHRTYW1wbGUgPSByaWdodFtmcmFtZV07CiAgICAgICAgICAgICAgICBjb25zdCBsb3dMZWZ0ID0gdGhpcy5sb3dMZWZ0LnByb2Nlc3MobGVmdFNhbXBsZSk7CiAgICAgICAgICAgICAgICBjb25zdCBsb3dSaWdodCA9IHRoaXMubG93UmlnaHQucHJvY2VzcyhyaWdodFNhbXBsZSk7CiAgICAgICAgICAgICAgICBjb25zdCBoaWdoTGVmdCA9IHRoaXMuaGlnaExlZnQucHJvY2VzcyhsZWZ0U2FtcGxlKTsKICAgICAgICAgICAgICAgIGNvbnN0IGhpZ2hSaWdodCA9IHRoaXMuaGlnaFJpZ2h0LnByb2Nlc3MocmlnaHRTYW1wbGUpOwogICAgICAgICAgICAgICAgY29uc3QgbWlkTGVmdCA9IGxlZnRTYW1wbGUgLSBsb3dMZWZ0IC0gaGlnaExlZnQ7CiAgICAgICAgICAgICAgICBjb25zdCBtaWRSaWdodCA9IHJpZ2h0U2FtcGxlIC0gbG93UmlnaHQgLSBoaWdoUmlnaHQ7CiAgICAgICAgICAgICAgICB0aGlzLmxvd0NvaGVyZW5jZS51cGRhdGUobG93TGVmdCwgbG93UmlnaHQpOwogICAgICAgICAgICAgICAgdGhpcy5taWRDb2hlcmVuY2UudXBkYXRlKG1pZExlZnQsIG1pZFJpZ2h0KTsKICAgICAgICAgICAgICAgIHRoaXMuaGlnaENvaGVyZW5jZS51cGRhdGUoaGlnaExlZnQsIGhpZ2hSaWdodCk7CiAgICAgICAgICAgICAgICBjb25zdCBsb3dNaWQgPSAobG93TGVmdCArIGxvd1JpZ2h0KSAqIDAuNTsKICAgICAgICAgICAgICAgIGNvbnN0IGxvd1NpZGUgPSAobG93TGVmdCAtIGxvd1JpZ2h0KSAqIDAuNTsKICAgICAgICAgICAgICAgIGNvbnN0IG1pZE1pZCA9IChtaWRMZWZ0ICsgbWlkUmlnaHQpICogMC41OwogICAgICAgICAgICAgICAgY29uc3QgbWlkU2lkZSA9IChtaWRMZWZ0IC0gbWlkUmlnaHQpICogMC41OwogICAgICAgICAgICAgICAgY29uc3QgaGlnaE1pZCA9IChoaWdoTGVmdCArIGhpZ2hSaWdodCkgKiAwLjU7CiAgICAgICAgICAgICAgICBjb25zdCBoaWdoU2lkZSA9IChoaWdoTGVmdCAtIGhpZ2hSaWdodCkgKiAwLjU7CiAgICAgICAgICAgICAgICAvLyBDb2hlcmVuY2UgZ2F0aW5nIHVzZXMgc2lnbmVkIGNyb3NzLWNvcnJlbGF0aW9uIHBlciBiYW5kOgogICAgICAgICAgICAgICAgLy8gICDPgSDiiYggKzE6IGluLXBoYXNlIC8gY2VudGVyIG1hdGVyaWFsIOKGkiBmcm9udGFsIFggY3VlLCBubyBZCiAgICAgICAgICAgICAgICAvLyAgIM+BIOKJiCAgMDogaGFyZC1wYW5uZWQgc2luZ2xlIHNvdXJjZSBvciBkaWZmdXNlIGFtYmllbnQg4oaSIFkgb3BlbiwgWCBzdXBwcmVzc2VkCiAgICAgICAgICAgICAgICAvLyAgIM+BIOKJiCAtMTogYW50aS1waGFzZSAvIGludmVydGVkLXBhaXIgc3RlcmVvIHRyaWNrZXJ5IOKGkiBZIG9wZW4sIFggc3VwcHJlc3NlZAogICAgICAgICAgICAgICAgLy8KICAgICAgICAgICAgICAgIC8vIFggZ2FpbiBmYWN0b3IgPSBtYXgoMCwgz4EpLiBPbmx5IHBvc2l0aXZlIGluLXBoYXNlIGNvbnRlbnQgc3RlZXJzCiAgICAgICAgICAgICAgICAvLyBmb3J3YXJkOyBkZWNvcnJlbGF0ZWQgYW5kIGFudGktcGhhc2UgY29udGVudCBzdGF5cyBvdXQgb2YgWC4KICAgICAgICAgICAgICAgIC8vCiAgICAgICAgICAgICAgICAvLyBZIGdhaW4gZmFjdG9yID0gMSAtIG1heCgwLCDPgSkuIENlbnRlciBtYXRlcmlhbCAoaGlnaCArz4EpCiAgICAgICAgICAgICAgICAvLyBzdXBwcmVzc2VzIFk7IGV2ZXJ5dGhpbmcgZWxzZSAoaGFyZCBwYW5zLCBhbnRpLXBoYXNlLCBhbWJpZW50KQogICAgICAgICAgICAgICAgLy8ga2VlcHMgdGhlIHNpZGUgY3VlLgogICAgICAgICAgICAgICAgY29uc3QgbG93UmhvID0gTWF0aC5tYXgoMCwgdGhpcy5sb3dDb2hlcmVuY2Uuc2lnbmVkQ29oZXJlbmNlKCkpOwogICAgICAgICAgICAgICAgY29uc3QgbWlkUmhvID0gTWF0aC5tYXgoMCwgdGhpcy5taWRDb2hlcmVuY2Uuc2lnbmVkQ29oZXJlbmNlKCkpOwogICAgICAgICAgICAgICAgY29uc3QgaGlnaFJobyA9IE1hdGgubWF4KDAsIHRoaXMuaGlnaENvaGVyZW5jZS5zaWduZWRDb2hlcmVuY2UoKSk7CiAgICAgICAgICAgICAgICB3W2ZyYW1lXSA9IGxvd01pZCAqIFdfR0FJTl9MT1cgKyBtaWRNaWQgKiBXX0dBSU5fTUlEICsgaGlnaE1pZCAqIFdfR0FJTl9ISUdIOwogICAgICAgICAgICAgICAgeVtmcmFtZV0gPQogICAgICAgICAgICAgICAgICAgIGxvd1NpZGUgKiBZX0dBSU5fTE9XICogKDEgLSBsb3dSaG8pICsKICAgICAgICAgICAgICAgICAgICAgICAgbWlkU2lkZSAqIFlfR0FJTl9NSUQgKiAoMSAtIG1pZFJobykgKwogICAgICAgICAgICAgICAgICAgICAgICBoaWdoU2lkZSAqIFlfR0FJTl9ISUdIICogKDEgLSBoaWdoUmhvKTsKICAgICAgICAgICAgICAgIHpbZnJhbWVdID0gMDsKICAgICAgICAgICAgICAgIHhbZnJhbWVdID0gbG93TWlkICogWF9HQUlOX0xPVyAqIGxvd1JobyArIG1pZE1pZCAqIFhfR0FJTl9NSUQgKiBtaWRSaG8gKyBoaWdoTWlkICogWF9HQUlOX0hJR0ggKiBoaWdoUmhvOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGNvbnN0IFdPUktMRVRfTE9HX1BSRUZJWCA9ICJbY2Fjb3Bob255L3dvcmtsZXQ6c3RlcmVvLXRvLWJmb3JtYXRdIjsKICAgIGNsYXNzIFN0ZXJlb1RvQkZvcm1hdFByb2Nlc3NvciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CiAgICAgICAgZnJhbWVzUHJvY2Vzc2VkID0gMDsKICAgICAgICBmcmFtZXNTaG9ydElucHV0ID0gMDsKICAgICAgICBsYXN0UmVwb3J0RnJhbWUgPSAwOwogICAgICAgIHVwbWl4ZXIgPSBuZXcgU3RlcmVvVG9Gb2FVcG1peGVyKHNhbXBsZVJhdGUpOwogICAgICAgIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzKSB7CiAgICAgICAgICAgIGNvbnN0IGlucHV0ID0gaW5wdXRzWzBdOwogICAgICAgICAgICBjb25zdCBvdXRwdXQgPSBvdXRwdXRzWzBdOwogICAgICAgICAgICBpZiAoIWlucHV0IHx8IGlucHV0Lmxlbmd0aCA8IDIgfHwgIW91dHB1dCB8fCBvdXRwdXQubGVuZ3RoIDwgNCkgewogICAgICAgICAgICAgICAgdGhpcy5mcmFtZXNTaG9ydElucHV0Kys7CiAgICAgICAgICAgICAgICB0aGlzLmZyYW1lc1Byb2Nlc3NlZCsrOwogICAgICAgICAgICAgICAgdGhpcy5tYXliZVJlcG9ydChpbnB1dD8ubGVuZ3RoID8/IDAsICJzaG9ydC1pbnB1dCIsIGlucHV0LCBvdXRwdXQpOwogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy51cG1peGVyLnByb2Nlc3MoaW5wdXRbMF0sIGlucHV0WzFdLCBvdXRwdXRbMF0sIG91dHB1dFsxXSwgb3V0cHV0WzJdLCBvdXRwdXRbM10pOwogICAgICAgICAgICB0aGlzLmZyYW1lc1Byb2Nlc3NlZCsrOwogICAgICAgICAgICB0aGlzLm1heWJlUmVwb3J0KGlucHV0Lmxlbmd0aCwgIm9rIiwgaW5wdXQsIG91dHB1dCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBtYXliZVJlcG9ydChjaGFubmVscywga2luZCwgaW5wdXQsIG91dHB1dCkgewogICAgICAgICAgICBpZiAodGhpcy5mcmFtZXNQcm9jZXNzZWQgLSB0aGlzLmxhc3RSZXBvcnRGcmFtZSA8IDc1MCkKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgdGhpcy5sYXN0UmVwb3J0RnJhbWUgPSB0aGlzLmZyYW1lc1Byb2Nlc3NlZDsKICAgICAgICAgICAgbGV0IHN0YXRzID0gIiI7CiAgICAgICAgICAgIGlmIChpbnB1dCAmJiBpbnB1dC5sZW5ndGggPj0gMiAmJiBvdXRwdXQgJiYgb3V0cHV0Lmxlbmd0aCA+PSA0KSB7CiAgICAgICAgICAgICAgICBjb25zdCBwZWFrID0gKGEpID0+IHsKICAgICAgICAgICAgICAgICAgICBsZXQgbSA9IDA7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHYgPSBNYXRoLmFicyhhW2ldKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHYgPiBtKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbSA9IHY7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBtOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHN0YXRzID0KICAgICAgICAgICAgICAgICAgICBgIHBlYWtMPSR7cGVhayhpbnB1dFswXSkudG9GaXhlZCg0KX1gICsKICAgICAgICAgICAgICAgICAgICAgICAgYCBwZWFrUj0ke3BlYWsoaW5wdXRbMV0pLnRvRml4ZWQoNCl9YCArCiAgICAgICAgICAgICAgICAgICAgICAgIGAgcGVha1c9JHtwZWFrKG91dHB1dFswXSkudG9GaXhlZCg0KX1gICsKICAgICAgICAgICAgICAgICAgICAgICAgYCBwZWFrWT0ke3BlYWsob3V0cHV0WzFdKS50b0ZpeGVkKDQpfWAgKwogICAgICAgICAgICAgICAgICAgICAgICBgIHBlYWtaPSR7cGVhayhvdXRwdXRbMl0pLnRvRml4ZWQoNCl9YCArCiAgICAgICAgICAgICAgICAgICAgICAgIGAgcGVha1g9JHtwZWFrKG91dHB1dFszXSkudG9GaXhlZCg0KX1gOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhgJHtXT1JLTEVUX0xPR19QUkVGSVh9IHByb2Nlc3MgdGljayBmcmFtZXNUb3RhbD0ke3RoaXMuZnJhbWVzUHJvY2Vzc2VkfSBzaG9ydElucHV0PSR7dGhpcy5mcmFtZXNTaG9ydElucHV0fSBjaGFubmVsc1RoaXNUaWNrPSR7Y2hhbm5lbHN9IGtpbmQ9JHtraW5kfSR7c3RhdHN9YCk7CiAgICAgICAgfQogICAgfQogICAgY29uc29sZS5pbmZvKGAke1dPUktMRVRfTE9HX1BSRUZJWH0gbW9kdWxlIGV2YWx1YXRpbmdgKTsKICAgIHRyeSB7CiAgICAgICAgY29uc29sZS5pbmZvKGAke1dPUktMRVRfTE9HX1BSRUZJWH0gcmVnaXN0ZXJQcm9jZXNzb3Igc3RhcnRgKTsKICAgICAgICByZWdpc3RlclByb2Nlc3Nvcigic3RlcmVvLXRvLWJmb3JtYXQiLCBTdGVyZW9Ub0JGb3JtYXRQcm9jZXNzb3IpOwogICAgICAgIGNvbnNvbGUuaW5mbyhgJHtXT1JLTEVUX0xPR19QUkVGSVh9IHJlZ2lzdGVyUHJvY2Vzc29yIGNvbXBsZXRlYCk7CiAgICB9CiAgICBjYXRjaCAoZXJyb3IpIHsKICAgICAgICBjb25zb2xlLmVycm9yKGAke1dPUktMRVRfTE9HX1BSRUZJWH0gcmVnaXN0ZXJQcm9jZXNzb3IgZmFpbGVkYCwgZXJyb3IpOwogICAgICAgIHRocm93IGVycm9yOwogICAgfQoKICAgIGV4cG9ydHMuU3RlcmVvVG9CRm9ybWF0UHJvY2Vzc29yID0gU3RlcmVvVG9CRm9ybWF0UHJvY2Vzc29yOwoKICAgIHJldHVybiBleHBvcnRzOwoKfSkoe30pOwovLyMgc291cmNlTWFwcGluZ1VSTD1zdGVyZW8tdG8tYmZvcm1hdC1idW5kbGUuanMubWFwCg==";class y{listeners={};on(e,t){return this.listeners[e]=this.listeners[e]??[],this.listeners[e].push({fn:t,once:!1}),()=>this.off(e,t)}once(e,t){return this.listeners[e]=this.listeners[e]??[],this.listeners[e].push({fn:t,once:!0}),()=>this.off(e,t)}off(e,t){const g=this.listeners[e];g&&(this.listeners[e]=g.filter(I=>I.fn!==t))}emit(e,t){const g=this.listeners[e];g&&(g.forEach(I=>I.fn(t)),this.listeners[e]=g.filter(I=>!I.once))}emitAsync(e,t){const g=this.listeners[e];if(g){const I=g.map(o=>Promise.resolve().then(()=>o.fn(t)).catch(s=>console.error(`Error in listener for event ${e}:`,s)));return this.listeners[e]=g.filter(o=>!o.once),Promise.all(I).then(()=>{})}return Promise.resolve()}removeAllListeners(){this.listeners={}}}class f{constructor(e=[]){this.sounds=e}_position=[0,0,0];loopCount=0;playIndex=0;preplayRandom(){if(this.sounds.length===0)return;const t=this.randomSound().preplay();return t.length>0?t[0]:void 0}playRandom(){const e=this.preplayRandom();return e&&e.play(),e}preplayOrdered(e=!0){if(this.sounds.length===0||this.playIndex>=this.sounds.length)return;const g=this.sounds[this.playIndex].preplay();if(g.length!==0)return this.playIndex=(this.playIndex+1)%this.sounds.length,!e&&this.playIndex===0&&(this.playIndex=this.sounds.length),g[0]}playOrdered(e=!0){const t=this.preplayOrdered(e);return t&&t.play(),t}get duration(){return this.sounds.map(e=>e.duration).reduce((e,t)=>Math.max(e,t),0)}seek(e){this.sounds.forEach(t=>t.seek?.(e))}addSound(e){this.sounds.push(e)}randomSound(){if(this.sounds.length===0)throw new Error("Cannot get a random sound from an empty group");const e=Math.floor(Math.random()*this.sounds.length);return this.sounds[e]}preplay(){return this.sounds.map(t=>t.preplay()).flat()}play(){const e=[];return this.preplay().forEach(t=>{t.play(),e.push(t)}),e}get isPlaying(){return this.sounds.some(e=>e.isPlaying)}stop(){this.sounds.forEach(e=>e.stop())}pause(){this.sounds.forEach(e=>e.pause())}fadeTo(e,t,g){return Promise.all(this.sounds.map(I=>I.fadeTo(e,t,g))).then(()=>{})}fadeIn(e,t){return Promise.all(this.sounds.map(g=>g.fadeIn(e,t))).then(()=>{})}fadeOut(e,t){return Promise.all(this.sounds.map(g=>g.fadeOut(e,t))).then(()=>{})}stopWithFade(e,t){return Promise.all(this.sounds.map(g=>g.stopWithFade(e,t))).then(()=>{})}loop(e){return e===void 0?this.loopCount:(this.loopCount=e,this.sounds.forEach(t=>t.loop(e)),this.loopCount)}addFilter(e){this.sounds.forEach(t=>t.addFilter(e))}removeFilter(e){this.sounds.forEach(t=>t.removeFilter(e))}set position(e){this._position=e,this.sounds.forEach(t=>t.position=this._position)}get position(){return this._position}get volume(){return this.sounds.length===0?1:this.sounds.map(e=>e.volume).reduce((e,t)=>e+t,0)/this.sounds.length}set volume(e){this.sounds.forEach(t=>t.volume=e)}get playbackRate(){return this.sounds.length===0?1:this.sounds[0].playbackRate}set playbackRate(e){this.sounds.forEach(t=>t.playbackRate=e)}}class G{_filters=[];addFilter(e){if(this._filters.includes(e))throw new Error("Cannot add the same filter instance twice");this._filters.push(e)}removeFilter(e){const t=this._filters.length;if(this._filters=this._filters.filter(g=>g!==e),this._filters.length===t)throw new Error("Cannot remove filter that was never added to this container")}applyFilters(e){return this._filters.reduce((t,g)=>(t.connect(g),g),e),this._filters.length>0?this._filters[this._filters.length-1]:e}get filters(){return this._filters}addFilters(e){e.forEach(t=>this.addFilter(t))}removeFilters(e){e.forEach(t=>this.removeFilter(t))}cleanup(){this._filters.forEach(e=>e.disconnect()),this._filters=[]}}class X extends G{context;source;gainNode;panner;constructor(e,t,g,I=0){super(),this.source=e,this.gainNode=t,this.context=g,this.panner=g.createPanner(),e.connect(this.panner).connect(this.gainNode),this.refreshFilters()}get duration(){return 0}play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");return[this]}get isPlaying(){return!!this.source}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(e){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.gainNode.gain.value=e}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.stop())}pause(){if(!this.source)throw new Error("Cannot pause a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.enabled=!1)}resume(){if(!this.source)throw new Error("Cannot resume a sound that has been cleaned up");this.source.mediaStream.getTracks().forEach(e=>e.enabled=!0)}addFilter(e){super.addFilter(e),this.refreshFilters()}removeFilter(e){super.removeFilter(e),this.refreshFilters()}set position(e){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");const[t,g,I]=e;this.panner.positionX.value=t,this.panner.positionY.value=g,this.panner.positionZ.value=I}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");return[this.panner.positionX.value,this.panner.positionY.value,this.panner.positionZ.value]}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}get playbackRate(){return 1}set playbackRate(e){}}class T extends G{context;_position=[0,0,0];loopCount=0;prevVolume=1;microphoneGainNode;streamPlayback;stream;streamSource;constructor(e,t){super(),this.context=e,this.microphoneGainNode=this.context.createGain(),t&&(this.stream=t,this.streamSource=this.createStreamSource(t))}createStreamSource(e){if(!this.context.createMediaStreamSource)throw new Error("Media stream sources are not supported on this audio context (e.g. OfflineAudioContext).");return this.context.createMediaStreamSource(e)}play(){return this.stream?(this.streamPlayback||(this.streamSource=this.streamSource??this.createStreamSource(this.stream),this.streamPlayback=new X(this.streamSource,this.microphoneGainNode,this.context)),[this.streamPlayback]):(navigator.mediaDevices.getUserMedia({audio:!0}).then(e=>{this.stream=e,this.streamSource=this.createStreamSource(this.stream),this.streamPlayback=new X(this.streamSource,this.microphoneGainNode,this.context),this.streamPlayback.play()}).catch(e=>{console.error("Error initializing microphone stream:",e)}),[])}get duration(){return 0}seek(e){}get isPlaying(){return!!this.streamPlayback}stop(){this.streamPlayback&&(this.streamPlayback.stop(),this.streamPlayback=void 0)}pause(){this.streamPlayback&&this.streamPlayback.pause()}resume(){this.streamPlayback&&this.streamPlayback.resume()}addFilter(e){this.streamPlayback&&this.streamPlayback.addFilter(e)}removeFilter(e){this.streamPlayback&&this.streamPlayback.removeFilter(e)}get volume(){return this.streamPlayback?this.streamPlayback.volume:0}set volume(e){this.streamPlayback&&(this.streamPlayback.volume=e)}get position(){return[0,0,0]}set position(e){}loop(e){return 0}get playbackRate(){return 1}set playbackRate(e){}}function J(r){class e extends r{playbacks=[];_position=[0,0,0];_stereoPan=0;_threeDOptions={coneInnerAngle:360,coneOuterAngle:360,coneOuterGain:0,distanceModel:"inverse",maxDistance:1e4,channelCount:2,channelCountMode:"clamped-max",channelInterpretation:"speakers",panningModel:"HRTF",refDistance:1,rolloffFactor:1,positionX:0,positionY:0,positionZ:0,orientationX:0,orientationY:0,orientationZ:0};_volume=1;play(){const g=this.preplay();return g.forEach(I=>I.play()),g}stop(){this.playbacks.forEach(g=>{g.stop(),g.cleanup()}),this.playbacks=[]}pause(){this.playbacks.forEach(g=>g.pause())}addFilter(g){super.addFilter(g)}removeFilter(g){super.removeFilter(g)}get isPlaying(){return this.playbacks.some(g=>g.isPlaying)}get position(){return[this._threeDOptions.positionX,this._threeDOptions.positionY,this._threeDOptions.positionZ]}set position(g){this._threeDOptions.positionX=g[0],this._threeDOptions.positionY=g[1],this._threeDOptions.positionZ=g[2],this.playbacks.forEach(I=>I.position=g)}get threeDOptions(){return this._threeDOptions}set threeDOptions(g){this._threeDOptions={...this._threeDOptions,...g},this.playbacks.forEach(I=>I.threeDOptions=this._threeDOptions)}get stereoPan(){return this._stereoPan}set stereoPan(g){this._stereoPan=g,this.playbacks.forEach(I=>I.stereoPan=g)}get volume(){return this._volume}set volume(g){this._volume=g,this.playbacks.forEach(I=>I.volume=g)}fadeTo(g,I,o){return this._volume=g,Promise.all(this.playbacks.map(s=>s.fadeTo(g,I,o))).then(()=>{})}fadeIn(g,I){return Promise.all(this.playbacks.map(o=>o.fadeIn(g,I))).then(()=>{})}fadeOut(g,I){return Promise.all(this.playbacks.map(o=>o.fadeOut(g,I))).then(()=>{})}stopWithFade(g,I){return this.fadeOut(g,I).then(()=>this.stop())}}return e}function F(r){class e extends r{panner;_panType="stereo";get panType(){return this._panType}setPanType(g,I){this._panType===g&&this.panner||(this.panner&&this.panner.disconnect(),this._panType=g,g==="stereo"?this.panner=I.createStereoPanner():this.panner=I.createPanner())}setPannerNode(g){this.panner=g}get stereoPan(){return this.panType==="stereo"?this.panner.pan.value:null}set stereoPan(g){if(this.panType!=="stereo")throw new Error("Stereo panning is not available when using HRTF.");if(!this.panner)throw new Error("Cannot set stereo pan of a sound that has been cleaned up");if(g<-1||g>1)throw new RangeError("Stereo pan must be between -1 and 1.");this.panner.pan.setValueAtTime(g,this.panner.context.currentTime)}get threeDOptions(){if(!this.panner)throw new Error("Cannot get 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get 3D options of a sound that is not using HRTF");const g=this.panner;return{coneInnerAngle:g.coneInnerAngle,coneOuterAngle:g.coneOuterAngle,coneOuterGain:g.coneOuterGain,distanceModel:g.distanceModel,maxDistance:g.maxDistance,channelCount:this.panner.channelCount,channelCountMode:g.channelCountMode,channelInterpretation:g.channelInterpretation,panningModel:g.panningModel,refDistance:g.refDistance,rolloffFactor:g.rolloffFactor,positionX:g.positionX.value,positionY:g.positionY.value,positionZ:g.positionZ.value,orientationX:g.orientationX.value,orientationY:g.orientationY.value,orientationZ:g.orientationZ.value}}set threeDOptions(g){if(!this.panner)throw new Error("Cannot set 3D options of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot set 3D options of a sound that is not using HRTF");const I=this.panner;I.coneInnerAngle=g.coneInnerAngle!==void 0?g.coneInnerAngle:I.coneInnerAngle,I.coneOuterAngle=g.coneOuterAngle!==void 0?g.coneOuterAngle:I.coneOuterAngle,I.coneOuterGain=g.coneOuterGain!==void 0?g.coneOuterGain:I.coneOuterGain,I.distanceModel=g.distanceModel||I.distanceModel,I.maxDistance=g.maxDistance!==void 0?g.maxDistance:I.maxDistance,I.channelCount=g.channelCount!==void 0?g.channelCount:I.channelCount,I.channelCountMode=g.channelCountMode||I.channelCountMode,I.channelInterpretation=g.channelInterpretation||I.channelInterpretation,I.panningModel=g.panningModel||I.panningModel,I.refDistance=g.refDistance!==void 0?g.refDistance:I.refDistance,I.rolloffFactor=g.rolloffFactor!==void 0?g.rolloffFactor:I.rolloffFactor,I.positionX.value=g.positionX!==void 0?g.positionX:I.positionX.value,I.positionY.value=g.positionY!==void 0?g.positionY:I.positionY.value,I.positionZ.value=g.positionZ!==void 0?g.positionZ:I.positionZ.value,I.orientationX.value=g.orientationX!==void 0?g.orientationX:I.orientationX.value,I.orientationY.value=g.orientationY!==void 0?g.orientationY:I.orientationY.value,I.orientationZ.value=g.orientationZ!==void 0?g.orientationZ:I.orientationZ.value}set position(g){if(!this.panner)throw new Error("Cannot move a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot move a sound that is not using HRTF");const[I,o,s]=g,i=this.panner;i.positionX.value=I,i.positionY.value=o,i.positionZ.value=s}get position(){if(!this.panner)throw new Error("Cannot get position of a sound that has been cleaned up");if(this.panType!=="HRTF")throw new Error("Cannot get position of a sound that is not using HRTF");const g=this.panner;return[g.positionX.value,g.positionY.value,g.positionZ.value]}cleanup(){this.panner&&(this.panner.disconnect(),this.panner=void 0),super.cleanup()}}return e}function H(r){class e extends r{gainNode;_fadeTimeout;_isFading=!1;setGainNode(g){this.gainNode=g}cleanup(){this.cancelFade(),this.gainNode&&(this.gainNode.disconnect(),this.gainNode=void 0),super.cleanup()}get volume(){if(!this.gainNode)throw new Error("Cannot get volume of a sound that has been cleaned up");return this.gainNode.gain.value}set volume(g){if(!this.gainNode)throw new Error("Cannot set volume of a sound that has been cleaned up");this.cancelFade(),this.gainNode.gain.value=g}get isFading(){return this._isFading}fadeTo(g,I,o="linear"){if(!this.gainNode)throw new Error("Cannot fade a sound that has been cleaned up");this.cancelFade();const s=this.gainNode.context.currentTime,i=s+I/1e3;return this.gainNode.gain.setValueAtTime(this.gainNode.gain.value,s),o==="exponential"?this.gainNode.gain.exponentialRampToValueAtTime(g===0?1e-4:g,i):this.gainNode.gain.linearRampToValueAtTime(g,i),this._isFading=!0,new Promise(C=>{this._fadeTimeout=setTimeout(()=>{this._isFading=!1,g===0&&o==="exponential"&&this.gainNode&&(this.gainNode.gain.value=0),C()},I)})}cancelFade(){if(this._fadeTimeout&&(clearTimeout(this._fadeTimeout),this._fadeTimeout=void 0),this._isFading&&this.gainNode){const g=this.gainNode.context.currentTime;this.gainNode.gain.cancelScheduledValues(g),this.gainNode.gain.setValueAtTime(this.gainNode.gain.value,g)}this._isFading=!1}fadeIn(g,I){if(!this.gainNode)throw new Error("Cannot fade a sound that has been cleaned up");const o=this.gainNode.gain.value;return this.gainNode.gain.setValueAtTime(1e-4,this.gainNode.context.currentTime),this.fadeTo(o,g,I)}fadeOut(g,I){return this.fadeTo(0,g,I)}}return e}class N extends F(H(G)){source;_playing=!1;origin;eventEmitter=new y;constructor(){super()}get isPlaying(){return this.source?this._playing:!1}on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}fadeTo(e,t,g="linear"){return this.emit("fadeStart",{target:e,duration:t,type:g}),super.fadeTo(e,t,g).then(()=>{this.emit("fadeEnd",void 0)})}cancelFade(){const e=this._isFading;super.cancelFade(),e&&this.emit("fadeCancel",void 0)}cleanup(){this.eventEmitter.removeAllListeners(),super.cleanup()}}class Z extends N{constructor(e,t,g){super(),this.origin=e,this.context=e.context,this.loopCount=e.loopCount,this.setPanType(e.panType,e.context),this.source=t,"buffer"in t&&t.buffer&&(this.buffer=t.buffer),this.setupSourceNode(t),this.source.connect(this.panner),this.setGainNode(g),this.panner.connect(this.gainNode),this.refreshFilters()}context;loopCount=0;currentLoop=0;buffer;_offset=0;_startTime=0;_state=0;_playbackRate=1;_fadeInConfig;_fadeOutConfig;_loopEndCallback;setupSourceNode(e){if("mediaElement"in e&&e.mediaElement)e.mediaElement.onended=this.loopEnded;else if("onended"in e)e.onended=this.loopEnded;else throw new Error("Unsupported source type")}get isPlaying(){return this._state===1}get duration(){if(!this.source)throw new Error("Cannot get duration of a sound that has been cleaned up");return"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.duration:this.buffer?this.buffer.duration||NaN:NaN}get playbackRate(){return this._playbackRate}get volume(){return super.volume}set volume(e){super.volume=e,this.emit("volumeChange",e)}set playbackRate(e){if(e<=0)throw new Error("Playback rate must be greater than 0");if(this._state===1){const t=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=t,this._startTime=this.context.currentTime}this._playbackRate=e,this.source&&("playbackRate"in this.source&&(this.source.playbackRate.value=e),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.playbackRate=e))}loopEnded=()=>{!this.source||this._state!==1||(this.currentLoop++,this.loopCount!=="infinite"&&this.currentLoop>this.loopCount?(this.emit("ended",void 0),this._fadeOutConfig?this.fadeOut(this._fadeOutConfig.duration,this._fadeOutConfig.type).then(()=>{this.stop(),this.removeFromOrigin()}):(this.stop(),this.removeFromOrigin())):(this._loopEndCallback?.(),this.seek(0),this._state!==1&&!("mediaElement"in this.source)&&this.play(),this._fadeInConfig?.perLoop&&this.gainNode&&(this.gainNode.gain.setValueAtTime(1e-4,this.gainNode.context.currentTime),this.fadeTo(this._fadeInConfig.targetVolume,this._fadeInConfig.duration,this._fadeInConfig.type))))};play(){if(!this.source)throw new Error("Cannot play a sound that has been cleaned up");if(this._state===1)return[this];const e=this._state===2;try{let t;if(this._state===2?"mediaElement"in this.source&&this.source.mediaElement?t=this.source.mediaElement.play():(this.recreateSource(),"start"in this.source&&this.source.start&&this.source.start(0,this._offset)):"mediaElement"in this.source&&this.source.mediaElement?(this.source.mediaElement.currentTime=this._offset,t=this.source.mediaElement.play()):"start"in this.source&&this.source.start&&(this.recreateSource(),this.source.start(0,this._offset)),t){const g=this._state;t.then(()=>{this._startTime=this.context.currentTime,this._state=1,this.emit("play",this),e&&this.emit("resume",void 0),this.origin.cacophony?.emit("globalPlay",{source:this.origin,timestamp:Date.now()})},I=>{this._state=g,this.emitAsync("error",{error:I,errorType:"source",timestamp:Date.now(),recoverable:!0})})}else this._startTime=this.context.currentTime,this._state=1,this.emit("play",this),e&&this.emit("resume",void 0),this.origin.cacophony?.emit("globalPlay",{source:this.origin,timestamp:Date.now()});return[this]}catch(t){throw this.emitAsync("error",{error:t,errorType:"source",timestamp:Date.now(),recoverable:!0}),t}}pause(){if(!this.source||this._state!==1)return;const e=(this.context.currentTime-this._startTime)*this._playbackRate;this._offset+=e,"mediaElement"in this.source&&this.source.mediaElement?this.source.mediaElement.pause():"stop"in this.source&&this.source.stop(),this._state=2,this.emit("pause",void 0),this.origin.cacophony?.emit("globalPause",{source:this.origin,timestamp:Date.now()})}stop(){if(!this.source)throw new Error("Cannot stop a sound that has been cleaned up");this._state===3||this._state===0||(this.cancelFade(),"stop"in this.source&&this._state===1&&this.source.stop(),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.pause(),this.source.mediaElement.currentTime=0),this._offset=0,this._startTime=0,this._state=3,this.emit("stop",void 0),this.origin.cacophony?.emit("globalStop",{source:this.origin,timestamp:Date.now()}))}fadeIn(e,t,g){return g?.perLoop&&(this._fadeInConfig={duration:e,type:t||"linear",perLoop:!0,targetVolume:this.gainNode.gain.value}),super.fadeIn(e,t)}configureFadeOut(e,t){this._fadeOutConfig={duration:e,type:t||"linear"}}stopWithFade(e,t){return this.fadeOut(e,t).then(()=>this.stop())}seek(e){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot seek a sound that has been cleaned up");if(!Number.isFinite(e)||e<0)throw new Error("Invalid time value for seek");const t=this._state===1;t&&this.pause(),this._offset=e,"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.currentTime=e),t&&this.play()}get currentTime(){if(this._state===1){const e=(this.context.currentTime-this._startTime)*this._playbackRate;return this._offset+e}else return this._offset}removeFromOrigin(){const e=this.origin.playbacks.indexOf(this);e!==-1&&this.origin.playbacks.splice(e,1)}recreateSource(){if(!this.buffer||!this.panner||!this.context||!this.gainNode)throw new Error("Cannot recreate source of a sound that has been cleaned up");try{this.source&&(!("mediaElement"in this.source)&&"onended"in this.source&&(this.source.onended=null),this.source.disconnect()),this.source=this.context.createBufferSource(),this.source.buffer=this.buffer,this.source.connect(this.panner),this.source.onended=this.loopEnded,this.playbackRate=this._playbackRate,this.refreshFilters()}catch(e){throw this.emitAsync("error",{error:e,errorType:"source",timestamp:Date.now(),recoverable:!1}),e}}set sourceLoop(e){if(!this.source)throw new Error("Cannot set loop on a sound that has been cleaned up");"loop"in this.source&&(this.source.loop=e),"mediaElement"in this.source&&this.source.mediaElement&&(this.source.mediaElement.loop=e)}cleanup(){this.source&&("mediaElement"in this.source&&this.source.mediaElement?(this.source.mediaElement.pause(),this.source.mediaElement.currentTime=0,this.source.mediaElement.loop=!1,this.source.mediaElement.onended=null):"onended"in this.source&&(this.source.onended=null),this._offset=0,this._startTime=0,this._state=3,this.currentLoop=0,this.source.disconnect(),this.source=void 0,super.cleanup())}assertNotCleanedUp(){if(!this.source||!this.gainNode||!this.panner)throw new Error("Cannot perform operation on a sound that has been cleaned up")}addFilter(e){this.assertNotCleanedUp(),super.addFilter(e),this.refreshFilters()}removeFilter(e){this.assertNotCleanedUp(),super.removeFilter(e),this.refreshFilters()}loop(e){if(!this.source)throw new Error("Cannot loop a sound that has been cleaned up");if(e!==void 0&&(this.loopCount=e==="infinite"?"infinite":Math.max(0,e),this.currentLoop=0),"mediaElement"in this.source&&this.source.mediaElement){const t=this.source.mediaElement;t.loop=this.loopCount==="infinite"}else if("loop"in this.source)this.source.loop=this.loopCount==="infinite",this.source.buffer&&(this.source.loopEnd=this.source.buffer.duration,this.source.loopStart=0);else throw new Error("Unsupported source type");return this.loopCount}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}get outputNode(){if(!this.gainNode)throw new Error("Cannot access output node of a playback that has been cleaned up");return this.gainNode}connect(e){return this.outputNode.connect(e)}disconnect(e){e?this.outputNode.disconnect(e):this.outputNode.disconnect()}clone(e={}){if(!this.source||!this.gainNode||!this.context)throw new Error("Cannot clone a sound that has been cleaned up");const t=e.panType||this.panType,g=this.context.createGain();let I;if("buffer"in this.source&&this.source.buffer)I=this.context.createBufferSource(),I.buffer=this.source.buffer;else if("mediaElement"in this.source&&this.source.mediaElement){if(!this.context.createMediaElementSource)throw new Error("Media element sources are not supported on this audio context.");I=this.context.createMediaElementSource(this.source.mediaElement)}else throw new Error("Unsupported source type");const o=e.loopCount!==void 0?e.loopCount:this.loopCount,s=new Z(this.origin,I,g);return s.loopCount=o,s.currentLoop=this.currentLoop,s.setPanType(t,this.context),s.volume=this.volume,s.playbackRate=this._playbackRate,s._offset=this._offset,s._state=this._state,this._filters.forEach(i=>{const C=this.context.createBiquadFilter();C.type=i.type,C.frequency.value=i.frequency.value,C.Q.value=i.Q.value,C.gain.value=i.gain.value,s.addFilter(C)}),this._state===1&&s.play(),s}}class b extends J(G){constructor(e,t,g,I,o=S.Buffer,s="HRTF",i){super(),this.url=e,this.globalGainNode=I,this.soundType=o,this.panType=s,this._cacophony=i,this.buffer=t,this.context=g,this._cacophony?.registerSoundForCleanup(this,this._holdings,this._unregisterToken)}buffer;context;loopCount=0;_playbackRate=1;eventEmitter=new y;_holdings={sources:[],gainNodes:[],mediaElements:[]};_unregisterToken={};get cacophony(){return this._cacophony}get volume(){return super.volume}on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}clone(e={}){const t=e.panType||this.panType,g=e.stereoPan!==void 0?e.stereoPan:this.stereoPan,I=e.threeDOptions||this.threeDOptions,o=e.loopCount!==void 0?e.loopCount:this.loopCount,s=e.playbackRate||this.playbackRate,i=e.volume!==void 0?e.volume:this.volume,C=e.position!==void 0?e.position:this.position,n=e.filters?.length?e.filters:this._filters,a=new b(this.url,this.buffer,this.context,this.globalGainNode,this.soundType,t,this.cacophony);return a.loop(o),a.playbackRate=s,a.volume=i,t==="HRTF"?(a.threeDOptions=I,a.position=C):a.stereoPan=g,a.addFilters(n),a}preplay(){try{let e;if(this.buffer)e=this.context.createBufferSource(),e.buffer=this.buffer;else{if(!this.context.createMediaElementSource)throw new Error("Media element sources are not supported on this audio context (e.g. OfflineAudioContext). Use buffer-based sounds instead.");const I=new Audio;I.crossOrigin="anonymous",I.src=this.url,I.preload="auto",e=this.context.createMediaElementSource(I)}const t=this.context.createGain();t.connect(this.globalGainNode);const g=new Z(this,e,t);return this._holdings.sources.push(e),this._holdings.gainNodes.push(t),"mediaElement"in e&&e.mediaElement&&this._holdings.mediaElements.push(e.mediaElement),g.setGainNode(t),g.volume=this.volume,g.playbackRate=this.playbackRate,this._filters.forEach(I=>{const o=this.context.createBiquadFilter();o.type=I.type,o.frequency.value=I.frequency.value,o.Q.value=I.Q.value,o.gain.value=I.gain.value,g.addFilter(o)}),this.panType==="HRTF"?(g.threeDOptions=this.threeDOptions,g.position=this.position):this.panType==="stereo"&&(g.stereoPan=this.stereoPan),g.on("ended",()=>{this.emit("ended",void 0)}),g._loopEndCallback=()=>{this.emit("loopEnd",void 0)},g.on("error",I=>{this.emitAsync("soundError",{url:this.url,error:I.error,errorType:"playback",timestamp:I.timestamp,recoverable:I.recoverable})}),this.playbacks.push(g),[g]}catch(e){const t={url:this.url,error:e,errorType:"playback",timestamp:Date.now(),recoverable:!0};throw this.emitAsync("soundError",t),e}}play(e){const t=this.preplay();for(const g of t){const I=s=>{o(),this.emit("play",s)},o=()=>{g.off("play",I),g.off("error",o)};g.on("play",I),g.on("error",o);try{g.play()}catch(s){throw o(),s}}if(e)for(const g of t)e.fadeIn!==void 0&&g.fadeIn(e.fadeIn,e.fadeType,{perLoop:e.fadeInPerLoop}),e.fadeOut!==void 0&&g.configureFadeOut(e.fadeOut,e.fadeType);return t}stop(){this._holdings.sources.length=0,this._holdings.gainNodes.length=0,this._holdings.mediaElements.length=0,super.stop(),this.emit("stop",void 0)}pause(){super.pause(),this.emit("pause",void 0)}resume(){this.playbacks.forEach(e=>e.play()),this.emit("resume",void 0)}seek(e){this.playbacks.forEach(t=>t.seek(e))}get duration(){return this.playbacks.length>0?this.playbacks[0].duration:this.buffer?.duration||NaN}loop(e){return e===void 0?this.loopCount:(this.loopCount=e,this.playbacks.forEach(t=>t.loop(e)),this.loopCount)}get playbackRate(){return this._playbackRate}set playbackRate(e){this._playbackRate=e,this.playbacks.forEach(t=>t.playbackRate=e),this.emit("rateChange",e)}set volume(e){super.volume=e,this.emit("volumeChange",e)}cleanup(){this._cacophony?.unregisterSoundCleanup(this._unregisterToken),this._holdings.sources.length=0,this._holdings.gainNodes.length=0,this._holdings.mediaElements.length=0,this.playbacks.forEach(e=>e.cleanup()),this.playbacks=[],this.eventEmitter.removeAllListeners()}}function M(r){class e extends N{_oscillatorOptions={};get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(g){this._oscillatorOptions=g,this.source&&(this.oscillatorOptions.detune!==void 0&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type))}play(){if(!this.source)throw new Error("No source node found");return this.oscillatorOptions.detune!==void 0&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type),this.source.start(),this._playing=!0,[this]}stop(){this.source?.stop&&(this.source.stop(),this._playing=!1)}pause(){this.stop()}get frequency(){return this.source.frequency.value}set frequency(g){this.source.frequency.value=g,this.oscillatorOptions.frequency=g}get detune(){return this.source.detune.value}set detune(g){this.source.detune.value=g,this.oscillatorOptions.detune=g}get type(){return this.source.type}set type(g){this.source.type=g,this.oscillatorOptions.type=g}}return e}class x extends M(F(H(G))){constructor(e,t,g){super(),this.origin=e,this.source=t,this.context=e.context,this.setPanType(e.panType,e.context),this.source.connect(this.panner),this.setGainNode(g),this.panner.connect(this.gainNode),this.refreshFilters(),this.oscillatorOptions={detune:t.detune.value,frequency:t.frequency.value,type:t.type}}context;_state=0;play(){if(!this.source||!this.panner)throw new Error("Cannot play a synth that has been cleaned up");return this._state===1?[this]:((this._state===2||this._state===3)&&this.recreateSource(),this.oscillatorOptions.detune!==void 0&&(this.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(this.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(this.source.type=this.oscillatorOptions.type),this.source.start(),this._playing=!0,this._state=1,[this])}pause(){!this.source||this._state!==1||(this.source.stop(),this._playing=!1,this._state=2)}stop(){!this.source||this._state===0||this._state===3||(this._state===1&&this.source.stop(),this._playing=!1,this._state=3)}refreshFilters(){if(!this.panner||!this.gainNode)throw new Error("Cannot update filters on a sound that has been cleaned up");let e=this.panner;e.disconnect(),e=this.applyFilters(e),e.connect(this.gainNode)}cleanup(){this.panner&&this.gainNode&&(this.source.disconnect(this.panner),this.panner.disconnect(),this.gainNode.disconnect()),this.eventEmitter.removeAllListeners()}recreateSource(){if(!this.panner)throw new Error("Cannot recreate source of a synth that has been cleaned up");this.source.disconnect(),this.source=this.context.createOscillator(),this.source.connect(this.panner)}}class B extends J(G){constructor(e,t,g=S.Oscillator,I="HRTF",o={},s){super(),this.context=e,this.globalGainNode=t,this.soundType=g,this.panType=I,this.cacophony=s,this.context=e,this._oscillatorOptions=o}_oscillatorOptions;playbacks=[];eventEmitter=new y;on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}clone(e={}){const t=e.panType||this.panType,g=e.stereoPan!==void 0?e.stereoPan:this.stereoPan??0,I=e.threeDOptions||this.threeDOptions,o=e.volume!==void 0?e.volume:this.volume,s=e.position?.length?e.position:this.position,i=e.filters?.length?e.filters:this._filters,C=e.oscillatorOptions||this._oscillatorOptions,n=new B(this.context,this.globalGainNode,this.soundType,t,C,this.cacophony);return n._volume=o,n._position=s,n._stereoPan=g,n._threeDOptions=I,n.addFilters(i),n}preplay(){const e=this.context.createOscillator();return this.createPlayback(e)}createPlayback(e){this.oscillatorOptions.detune!==void 0&&(e.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(e.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(e.type=this.oscillatorOptions.type);const t=this.context.createGain();t.connect(this.globalGainNode);const g=new x(this,e,t);return g.volume=this.volume,this._filters.forEach(I=>{const o=this.context.createBiquadFilter();o.type=I.type,o.frequency.value=I.frequency.value,o.Q.value=I.Q.value,o.gain.value=I.gain.value,g.addFilter(o)}),this.panType==="HRTF"?(g.threeDOptions=this.threeDOptions,g.position=this.position):this.panType==="stereo"&&(g.stereoPan=this.stereoPan),this.playbacks.push(g),[g]}play(){const e=super.play();return this.emit("play",e[0]),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()}),e}stop(){super.stop(),this.emit("stop",void 0),this.cacophony?.emit("globalStop",{source:this,timestamp:Date.now()})}pause(){super.pause(),this.emit("pause",void 0),this.cacophony?.emit("globalPause",{source:this,timestamp:Date.now()})}resume(){this.playbacks.forEach(e=>e.play()),this.emit("resume",void 0),this.cacophony?.emit("globalPlay",{source:this,timestamp:Date.now()})}get volume(){return super.volume}set volume(e){super.volume=e,this.emit("volumeChange",e)}get oscillatorOptions(){return this._oscillatorOptions}set oscillatorOptions(e){this._oscillatorOptions=e,this.playbacks.forEach(t=>{t.source&&(this.oscillatorOptions.detune!==void 0&&(t.source.detune.value=this.oscillatorOptions.detune),this.oscillatorOptions.frequency!==void 0&&(t.source.frequency.value=this.oscillatorOptions.frequency),this.oscillatorOptions.type&&(t.source.type=this.oscillatorOptions.type))})}get frequency(){return this.oscillatorOptions.frequency??440}set frequency(e){this._oscillatorOptions.frequency=e,this.playbacks.forEach(t=>t.frequency=e),this.emit("frequencyChange",e)}get detune(){return this.oscillatorOptions.detune}set detune(e){this._oscillatorOptions.detune=e,this.playbacks.forEach(t=>t.detune=e),this.emit("detuneChange",e)}get type(){return this.oscillatorOptions.type||"sine"}set type(e){this._oscillatorOptions.type=e,this.playbacks.forEach(t=>t.type=e),this.emit("typeChange",e)}}var S=(r=>(r.HTML="HTML",r.Streaming="Streaming",r.Buffer="Buffer",r.Oscillator="oscillator",r))(S||{});const u="[cacophony/worklet]";class V{context;globalGainNode;listener;prevVolume=1;loadedAudioWorklets=new Set;finalizationRegistry;eventEmitter=new y;cache;createAudioWorkletNode;constructor(e,t,g={}){this.context=e||new AudioContext,this.listener=this.context.listener,this.globalGainNode=this.context.createGain(),this.globalGainNode.connect(this.context.destination),this.cache=t||new A,this.createAudioWorkletNode=g.createAudioWorkletNode||((I,o,s)=>new AudioWorkletNode(I,o,s)),this.finalizationRegistry=new FinalizationRegistry(I=>{for(const o of I.sources)o.disconnect();for(const o of I.gainNodes)o.disconnect();for(const o of I.mediaElements)o.pause(),o.removeAttribute("src"),o.load()})}registerSoundForCleanup(e,t,g){this.finalizationRegistry.register(e,t,g)}unregisterSoundCleanup(e){this.finalizationRegistry.unregister(e)}static createOffline(e,t){const g=e.context||new OfflineAudioContext(e.numberOfChannels,e.length,e.sampleRate);return new V(g,t)}get isOffline(){return typeof this.context.startRendering=="function"}async startRendering(){if(typeof this.context.startRendering!="function")throw new Error("startRendering() is only available on offline audio contexts. Use Cacophony.createOffline() to create one.");return this.context.startRendering()}on(e,t){return this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}emit(e,t){this.eventEmitter.emit(e,t)}async emitAsync(e,t){return this.eventEmitter.emitAsync(e,t)}async loadWorklets(e){this.context.audioWorklet?(await this.createWorkletNode("phase-vocoder",D,e),await this.loadStereoToBFormatWorklet(e)):console.warn("AudioWorklet not supported")}async loadStereoToBFormatWorklet(e){await this.loadAudioWorkletModule("stereo-to-bformat",k,e)}async createWorkletNode(e,t,g,I){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");try{const o=this.createAudioWorkletNode(this.context,e,I);return console.info(`${u} construct succeeded`,{name:e,loaded:this.loadedAudioWorklets.has(e)}),o}catch(o){console.warn(`${u} construct failed`,{name:e,loaded:this.loadedAudioWorklets.has(e),error:o});try{await this.loadAudioWorkletModule(e,t,g)}catch(s){throw console.error(`${u} load failed`,{name:e,error:s}),s}try{const s=this.createAudioWorkletNode(this.context,e,I);return console.info(`${u} construct after load succeeded`,{name:e}),s}catch(s){throw console.error(`${u} construct after load failed`,{name:e,error:s}),s}}}async createStereoToBFormatNode(e){return this.createWorkletNode("stereo-to-bformat",k,e,{numberOfInputs:1,numberOfOutputs:1,outputChannelCount:[4],channelCount:2,channelCountMode:"explicit",channelInterpretation:"speakers"})}async loadAudioWorkletModule(e,t,g){if(!this.context.audioWorklet)throw new Error("AudioWorklet not supported");if(this.loadedAudioWorklets.has(e)){console.info(`${u} load skipped`,{name:e});return}console.info(`${u} addModule start`,{name:e,url:t,aborted:g?.aborted??!1});try{await this.context.audioWorklet.addModule(t,{credentials:"same-origin",...g&&{signal:g}}),this.loadedAudioWorklets.add(e),console.info(`${u} addModule resolved`,{name:e})}catch(I){throw console.error(`${u} addModule rejected`,{name:e,error:I}),I}}createAbortError(){return new DOMException("Operation was aborted","AbortError")}createMediaSound(e,t,g,I){return I?.aborted?Promise.reject(this.createAbortError()):new Promise((o,s)=>{const i=new Audio;let C=!1;const n=()=>{i.removeEventListener("loadedmetadata",h),i.removeEventListener("error",m),I?.removeEventListener("abort",p)},a=()=>{i.pause(),i.src="",i.load()},c=d=>{C||(C=!0,n(),d())},h=()=>{c(()=>{o(new b(e,void 0,this.context,this.globalGainNode,t,g,this))})},m=()=>{const d=new Error(`Failed to load audio from ${e}`);c(()=>{a(),s(d)})},p=()=>{const d=this.createAbortError();c(()=>{a(),s(d)})};i.crossOrigin="anonymous",i.preload="auto",i.addEventListener("loadedmetadata",h),i.addEventListener("error",m),I?.addEventListener("abort",p,{once:!0}),i.src=e,i.load()})}clearMemoryCache(){this.cache.clearMemoryCache()}createOscillator(e,t="HRTF"){return new B(this.context,this.globalGainNode,"oscillator",t,e,this)}async createSound(e,t="Buffer",g="HRTF",I){if(typeof e=="object")return Promise.resolve(new b("",e,this.context,this.globalGainNode,"Buffer",g,this));const o=e;return t==="HTML"?this.createMediaSound(o,"HTML",g,I):t==="Streaming"?this.createMediaSound(o,"Streaming",g,I):this.cache.getAudioBuffer(this.context,o,I,{onLoadingStart:s=>this.emitAsync("loadingStart",s),onLoadingProgress:s=>this.emitAsync("loadingProgress",s),onLoadingComplete:s=>this.emitAsync("loadingComplete",s),onLoadingError:s=>this.emitAsync("loadingError",s),onCacheHit:s=>this.emitAsync("cacheHit",s),onCacheMiss:s=>this.emitAsync("cacheMiss",s),onCacheError:s=>this.emitAsync("cacheError",s)}).then(s=>new b(o,s,this.context,this.globalGainNode,t,g,this))}async createGroup(e){const t=new f;return e.forEach(g=>t.addSound(g)),t}async createGroupFromUrls(e,t="Buffer",g="HRTF",I){const o=new f;return(await Promise.all(e.map(i=>this.createSound(i,t,g,I)))).forEach(i=>o.addSound(i)),o}async createStream(e,t){return this.createMediaSound(e,"Streaming","HRTF",t)}createBiquadFilter=({type:e,frequency:t,gain:g,Q:I})=>{t===void 0&&(t=350);const o=this.context.createBiquadFilter();return o.type=e||"lowpass",o.frequency.value=t,o.gain.value=g||0,o.Q.value=I||1,o};createSplitter(e=2){if(!this.context.createChannelSplitter)throw new Error("ChannelSplitterNode not supported");return this.context.createChannelSplitter(e)}createMerger(e=2){if(!this.context.createChannelMerger)throw new Error("ChannelMergerNode not supported");return this.context.createChannelMerger(e)}createPanner({coneInnerAngle:e,coneOuterAngle:t,coneOuterGain:g,distanceModel:I,maxDistance:o,channelCount:s,channelCountMode:i,channelInterpretation:C,panningModel:n,refDistance:a,rolloffFactor:c,positionX:h,positionY:m,positionZ:p,orientationX:d,orientationY:w,orientationZ:K}){const l=this.context.createPanner();return l.coneInnerAngle=e||360,l.coneOuterAngle=t||360,l.coneOuterGain=g||0,l.distanceModel=I||"inverse",l.maxDistance=o||1e4,l.channelCount=s||2,l.channelCountMode=i||"clamped-max",l.channelInterpretation=C||"speakers",l.panningModel=n||"HRTF",l.refDistance=a||1,l.rolloffFactor=c||1,l.positionX.value=h||0,l.positionY.value=m||0,l.positionZ.value=p||0,l.orientationX.value=d||0,l.orientationY.value=w||0,l.orientationZ.value=K||0,l}pause(){this.context.suspend&&(this.context.suspend(),this.emit("suspend",void 0))}resume(){this.context.resume&&(this.context.resume(),this.emit("resume",void 0))}setGlobalVolume(e){this.globalGainNode.gain.value!==e&&(this.globalGainNode.gain.value=e,this.emit("volumeChange",e))}get volume(){return this.globalGainNode.gain.value}set volume(e){if(this.muted){this.prevVolume=e;return}this.setGlobalVolume(e)}mute(){this.muted||(this.prevVolume=this.globalGainNode.gain.value,this.setGlobalVolume(0),this.emit("mute",void 0))}unmute(){this.muted&&(this.setGlobalVolume(this.prevVolume),this.emit("unmute",void 0))}get muted(){return this.globalGainNode.gain.value===0}set muted(e){e!==this.muted&&(e?this.mute():this.unmute())}getMicrophoneStream(){return new Promise((e,t)=>{navigator.mediaDevices.getUserMedia({audio:!0}).then(g=>{const I=new T(this.context,g);e(I)}).catch(g=>{t(g)})})}get listenerOrientation(){return{forward:[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value],up:[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}}set listenerOrientation(e){const{forward:t,up:g}=e,[I,o,s]=t,[i,C,n]=g;this.listener.forwardX.value=I,this.listener.forwardY.value=o,this.listener.forwardZ.value=s,this.listener.upX.value=i,this.listener.upY.value=C,this.listener.upZ.value=n}get listenerUpOrientation(){return[this.listener.upX.value,this.listener.upY.value,this.listener.upZ.value]}set listenerUpOrientation(e){const[t,g,I]=e;this.listener.upX.value=t,this.listener.upY.value=g,this.listener.upZ.value=I}get listenerForwardOrientation(){return[this.listener.forwardX.value,this.listener.forwardY.value,this.listener.forwardZ.value]}set listenerForwardOrientation(e){const[t,g,I]=e;this.listener.forwardX.value=t,this.listener.forwardY.value=g,this.listener.forwardZ.value=I}get listenerPosition(){return[this.listener.positionX.value,this.listener.positionY.value,this.listener.positionZ.value]}set listenerPosition(e){const[t,g,I]=e,o=this.context.currentTime;this.listener.positionX.setValueAtTime(t,o),this.listener.positionY.setValueAtTime(g,o),this.listener.positionZ.setValueAtTime(I,o)}}class z{constructor(e=[]){this.synths=e}addSynth(e){this.synths.push(e)}removeSynth(e){const t=this.synths.indexOf(e);if(t!==-1)this.synths.splice(t,1);else throw new Error("Synth not found in group")}play(){return this.synths.flatMap(e=>e.play())}stop(){this.synths.forEach(e=>e.stop())}pause(){this.synths.forEach(e=>e.pause())}resume(){this.synths.forEach(e=>e.resume())}get isPlaying(){return this.synths.some(e=>e.isPlaying)}addFilter(e){this.synths.forEach(t=>t.addFilter(e))}removeFilter(e){this.synths.forEach(t=>t.removeFilter(e))}fadeTo(e,t,g){return Promise.all(this.synths.map(I=>I.fadeTo(e,t,g))).then(()=>{})}fadeIn(e,t){return Promise.all(this.synths.map(g=>g.fadeIn(e,t))).then(()=>{})}fadeOut(e,t){return Promise.all(this.synths.map(g=>g.fadeOut(e,t))).then(()=>{})}stopWithFade(e,t){return Promise.all(this.synths.map(g=>g.stopWithFade(e,t))).then(()=>{})}get volume(){return this.synths.length===0?1:this.synths.map(e=>e.volume).reduce((e,t)=>e+t,0)/this.synths.length}set volume(e){this.synths.forEach(t=>t.volume=e)}get stereoPan(){return this.synths.length===0?null:this.synths[0].stereoPan}set stereoPan(e){this.synths.forEach(t=>t.stereoPan=e)}get position(){return this.synths.length===0?[0,0,0]:this.synths[0].position}set position(e){this.synths.forEach(t=>t.position=e)}get frequency(){return this.synths.length===0?440:this.synths[0].frequency}set frequency(e){this.synths.forEach(t=>t.frequency=e)}get detune(){return this.synths[0]?.detune}set detune(e){this.synths.forEach(t=>t.detune=e)}get type(){return this.synths.length===0?"sine":this.synths[0].type}set type(e){this.synths.forEach(t=>t.type=e)}}exports.AudioCache=A;exports.Cacophony=V;exports.Group=f;exports.MicrophonePlayback=X;exports.Playback=Z;exports.Sound=b;exports.SoundType=S;exports.Synth=B;exports.SynthGroup=z;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|