playlist-data-engine 1.4.0 → 1.4.1
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.
|
@@ -46,7 +46,7 @@ ${E.map(t=>` - ${t}`).join(`
|
|
|
46
46
|
|
|
47
47
|
`)}G.write("payload.value = newResult;"),G.write("return payload;");const l=G.compile();return(F,m)=>l(s,F,m)};let E;const i=HI,C=!te.jitless,e=C&&Wn.value,o=A.catchall;let t;Q._zod.parse=(s,G)=>{t??(t=g.value);const n=s.value;return i(n)?C&&e&&G?.async===!1&&G.jitless!==!0?(E||(E=I(A.shape)),s=E(s,G),o?Ue([],n,s,G,t,Q):s):B(s,G):(s.issues.push({expected:"object",code:"invalid_type",input:n,inst:Q}),s)}});function ke(Q,A,B,g){for(const E of Q)if(E.issues.length===0)return A.value=E.value,A;const I=Q.filter(E=>!sg(E));return I.length===1?(A.value=I[0].value,I[0]):(A.issues.push({code:"invalid_union",input:A.value,inst:B,errors:Q.map(E=>E.issues.map(i=>WB(i,g,UB())))}),A)}const Fc=Z("$ZodUnion",(Q,A)=>{FA.init(Q,A),tA(Q._zod,"optin",()=>A.options.some(I=>I._zod.optin==="optional")?"optional":void 0),tA(Q._zod,"optout",()=>A.options.some(I=>I._zod.optout==="optional")?"optional":void 0),tA(Q._zod,"values",()=>{if(A.options.every(I=>I._zod.values))return new Set(A.options.flatMap(I=>Array.from(I._zod.values)))}),tA(Q._zod,"pattern",()=>{if(A.options.every(I=>I._zod.pattern)){const I=A.options.map(E=>E._zod.pattern);return new RegExp(`^(${I.map(E=>fE(E.source)).join("|")})$`)}});const B=A.options.length===1,g=A.options[0]._zod.run;Q._zod.parse=(I,E)=>{if(B)return g(I,E);let i=!1;const C=[];for(const a of A.options){const e=a._zod.run({value:I.value,issues:[]},E);if(e instanceof Promise)C.push(e),i=!0;else{if(e.issues.length===0)return e;C.push(e)}}return i?Promise.all(C).then(a=>ke(a,I,Q,E)):ke(C,I,Q,E)}}),Mc=Z("$ZodIntersection",(Q,A)=>{FA.init(Q,A),Q._zod.parse=(B,g)=>{const I=B.value,E=A.left._zod.run({value:I,issues:[]},g),i=A.right._zod.run({value:I,issues:[]},g);return E instanceof Promise||i instanceof Promise?Promise.all([E,i]).then(([a,e])=>Ze(B,a,e)):Ze(B,E,i)}});function VE(Q,A){if(Q===A)return{valid:!0,data:Q};if(Q instanceof Date&&A instanceof Date&&+Q==+A)return{valid:!0,data:Q};if(tg(Q)&&tg(A)){const B=Object.keys(A),g=Object.keys(Q).filter(E=>B.indexOf(E)!==-1),I={...Q,...A};for(const E of g){const i=VE(Q[E],A[E]);if(!i.valid)return{valid:!1,mergeErrorPath:[E,...i.mergeErrorPath]};I[E]=i.data}return{valid:!0,data:I}}if(Array.isArray(Q)&&Array.isArray(A)){if(Q.length!==A.length)return{valid:!1,mergeErrorPath:[]};const B=[];for(let g=0;g<Q.length;g++){const I=Q[g],E=A[g],i=VE(I,E);if(!i.valid)return{valid:!1,mergeErrorPath:[g,...i.mergeErrorPath]};B.push(i.data)}return{valid:!0,data:B}}return{valid:!1,mergeErrorPath:[]}}function Ze(Q,A,B){const g=new Map;let I;for(const C of A.issues)if(C.code==="unrecognized_keys"){I??(I=C);for(const a of C.keys)g.has(a)||g.set(a,{}),g.get(a).l=!0}else Q.issues.push(C);for(const C of B.issues)if(C.code==="unrecognized_keys")for(const a of C.keys)g.has(a)||g.set(a,{}),g.get(a).r=!0;else Q.issues.push(C);const E=[...g].filter(([,C])=>C.l&&C.r).map(([C])=>C);if(E.length&&I&&Q.issues.push({...I,keys:E}),sg(Q))return Q;const i=VE(A.value,B.value);if(!i.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(i.mergeErrorPath)}`);return Q.value=i.data,Q}const wc=Z("$ZodRecord",(Q,A)=>{FA.init(Q,A),Q._zod.parse=(B,g)=>{const I=B.value;if(!tg(I))return B.issues.push({expected:"record",code:"invalid_type",input:I,inst:Q}),B;const E=[],i=A.keyType._zod.values;if(i){B.value={};const C=new Set;for(const e of i)if(typeof e=="string"||typeof e=="number"||typeof e=="symbol"){C.add(typeof e=="number"?e.toString():e);const o=A.valueType._zod.run({value:I[e],issues:[]},g);o instanceof Promise?E.push(o.then(t=>{t.issues.length&&B.issues.push(...Gg(e,t.issues)),B.value[e]=t.value})):(o.issues.length&&B.issues.push(...Gg(e,o.issues)),B.value[e]=o.value)}let a;for(const e in I)C.has(e)||(a=a??[],a.push(e));a&&a.length>0&&B.issues.push({code:"unrecognized_keys",input:I,inst:Q,keys:a})}else{B.value={};for(const C of Reflect.ownKeys(I)){if(C==="__proto__")continue;let a=A.keyType._zod.run({value:C,issues:[]},g);if(a instanceof Promise)throw new Error("Async schemas not supported in object keys currently");if(typeof C=="string"&&ye.test(C)&&a.issues.length){const t=A.keyType._zod.run({value:Number(C),issues:[]},g);if(t instanceof Promise)throw new Error("Async schemas not supported in object keys currently");t.issues.length===0&&(a=t)}if(a.issues.length){A.mode==="loose"?B.value[C]=I[C]:B.issues.push({code:"invalid_key",origin:"record",issues:a.issues.map(t=>WB(t,g,UB())),input:C,path:[C],inst:Q});continue}const o=A.valueType._zod.run({value:I[C],issues:[]},g);o instanceof Promise?E.push(o.then(t=>{t.issues.length&&B.issues.push(...Gg(C,t.issues)),B.value[a.value]=t.value})):(o.issues.length&&B.issues.push(...Gg(C,o.issues)),B.value[a.value]=o.value)}}return E.length?Promise.all(E).then(()=>B):B}}),yc=Z("$ZodEnum",(Q,A)=>{FA.init(Q,A);const B=se(A.entries),g=new Set(B);Q._zod.values=g,Q._zod.pattern=new RegExp(`^(${B.filter(I=>Hn.has(typeof I)).map(I=>typeof I=="string"?fI(I):I.toString()).join("|")})$`),Q._zod.parse=(I,E)=>{const i=I.value;return g.has(i)||I.issues.push({code:"invalid_value",values:B,input:i,inst:Q}),I}}),Rc=Z("$ZodTransform",(Q,A)=>{FA.init(Q,A),Q._zod.parse=(B,g)=>{if(g.direction==="backward")throw new oe(Q.constructor.name);const I=A.transform(B.value,B);if(g.async)return(I instanceof Promise?I:Promise.resolve(I)).then(i=>(B.value=i,B));if(I instanceof Promise)throw new og;return B.value=I,B}});function We(Q,A){return Q.issues.length&&A===void 0?{issues:[],value:void 0}:Q}const He=Z("$ZodOptional",(Q,A)=>{FA.init(Q,A),Q._zod.optin="optional",Q._zod.optout="optional",tA(Q._zod,"values",()=>A.innerType._zod.values?new Set([...A.innerType._zod.values,void 0]):void 0),tA(Q._zod,"pattern",()=>{const B=A.innerType._zod.pattern;return B?new RegExp(`^(${fE(B.source)})?$`):void 0}),Q._zod.parse=(B,g)=>{if(A.innerType._zod.optin==="optional"){const I=A.innerType._zod.run(B,g);return I instanceof Promise?I.then(E=>We(E,B.value)):We(I,B.value)}return B.value===void 0?B:A.innerType._zod.run(B,g)}}),mc=Z("$ZodExactOptional",(Q,A)=>{He.init(Q,A),tA(Q._zod,"values",()=>A.innerType._zod.values),tA(Q._zod,"pattern",()=>A.innerType._zod.pattern),Q._zod.parse=(B,g)=>A.innerType._zod.run(B,g)}),uc=Z("$ZodNullable",(Q,A)=>{FA.init(Q,A),tA(Q._zod,"optin",()=>A.innerType._zod.optin),tA(Q._zod,"optout",()=>A.innerType._zod.optout),tA(Q._zod,"pattern",()=>{const B=A.innerType._zod.pattern;return B?new RegExp(`^(${fE(B.source)}|null)$`):void 0}),tA(Q._zod,"values",()=>A.innerType._zod.values?new Set([...A.innerType._zod.values,null]):void 0),Q._zod.parse=(B,g)=>B.value===null?B:A.innerType._zod.run(B,g)}),Sc=Z("$ZodDefault",(Q,A)=>{FA.init(Q,A),Q._zod.optin="optional",tA(Q._zod,"values",()=>A.innerType._zod.values),Q._zod.parse=(B,g)=>{if(g.direction==="backward")return A.innerType._zod.run(B,g);if(B.value===void 0)return B.value=A.defaultValue,B;const I=A.innerType._zod.run(B,g);return I instanceof Promise?I.then(E=>fe(E,A)):fe(I,A)}});function fe(Q,A){return Q.value===void 0&&(Q.value=A.defaultValue),Q}const bc=Z("$ZodPrefault",(Q,A)=>{FA.init(Q,A),Q._zod.optin="optional",tA(Q._zod,"values",()=>A.innerType._zod.values),Q._zod.parse=(B,g)=>(g.direction==="backward"||B.value===void 0&&(B.value=A.defaultValue),A.innerType._zod.run(B,g))}),pc=Z("$ZodNonOptional",(Q,A)=>{FA.init(Q,A),tA(Q._zod,"values",()=>{const B=A.innerType._zod.values;return B?new Set([...B].filter(g=>g!==void 0)):void 0}),Q._zod.parse=(B,g)=>{const I=A.innerType._zod.run(B,g);return I instanceof Promise?I.then(E=>Ne(E,Q)):Ne(I,Q)}});function Ne(Q,A){return!Q.issues.length&&Q.value===void 0&&Q.issues.push({code:"invalid_type",expected:"nonoptional",input:Q.value,inst:A}),Q}const Yc=Z("$ZodCatch",(Q,A)=>{FA.init(Q,A),tA(Q._zod,"optin",()=>A.innerType._zod.optin),tA(Q._zod,"optout",()=>A.innerType._zod.optout),tA(Q._zod,"values",()=>A.innerType._zod.values),Q._zod.parse=(B,g)=>{if(g.direction==="backward")return A.innerType._zod.run(B,g);const I=A.innerType._zod.run(B,g);return I instanceof Promise?I.then(E=>(B.value=E.value,E.issues.length&&(B.value=A.catchValue({...B,error:{issues:E.issues.map(i=>WB(i,g,UB()))},input:B.value}),B.issues=[]),B)):(B.value=I.value,I.issues.length&&(B.value=A.catchValue({...B,error:{issues:I.issues.map(E=>WB(E,g,UB()))},input:B.value}),B.issues=[]),B)}}),Uc=Z("$ZodPipe",(Q,A)=>{FA.init(Q,A),tA(Q._zod,"values",()=>A.in._zod.values),tA(Q._zod,"optin",()=>A.in._zod.optin),tA(Q._zod,"optout",()=>A.out._zod.optout),tA(Q._zod,"propValues",()=>A.in._zod.propValues),Q._zod.parse=(B,g)=>{if(g.direction==="backward"){const E=A.out._zod.run(B,g);return E instanceof Promise?E.then(i=>LI(i,A.in,g)):LI(E,A.in,g)}const I=A.in._zod.run(B,g);return I instanceof Promise?I.then(E=>LI(E,A.out,g)):LI(I,A.out,g)}});function LI(Q,A,B){return Q.issues.length?(Q.aborted=!0,Q):A._zod.run({value:Q.value,issues:Q.issues},B)}const kc=Z("$ZodReadonly",(Q,A)=>{FA.init(Q,A),tA(Q._zod,"propValues",()=>A.innerType._zod.propValues),tA(Q._zod,"values",()=>A.innerType._zod.values),tA(Q._zod,"optin",()=>A.innerType?._zod?.optin),tA(Q._zod,"optout",()=>A.innerType?._zod?.optout),Q._zod.parse=(B,g)=>{if(g.direction==="backward")return A.innerType._zod.run(B,g);const I=A.innerType._zod.run(B,g);return I instanceof Promise?I.then(Je):Je(I)}});function Je(Q){return Q.value=Object.freeze(Q.value),Q}const Zc=Z("$ZodCustom",(Q,A)=>{vA.init(Q,A),FA.init(Q,A),Q._zod.parse=(B,g)=>B,Q._zod.check=B=>{const g=B.value,I=A.fn(g);if(I instanceof Promise)return I.then(E=>qe(E,B,g,Q));qe(I,B,g,Q)}});function qe(Q,A,B,g){if(!Q){const I={code:"custom",input:B,inst:g,path:[...g._zod.def.path??[]],continue:!g._zod.def.abort};g._zod.def.params&&(I.params=g._zod.def.params),A.issues.push(xg(I))}}var xe;class Wc{constructor(){this._map=new WeakMap,this._idmap=new Map}add(A,...B){const g=B[0];return this._map.set(A,g),g&&typeof g=="object"&&"id"in g&&this._idmap.set(g.id,A),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(A){const B=this._map.get(A);return B&&typeof B=="object"&&"id"in B&&this._idmap.delete(B.id),this._map.delete(A),this}get(A){const B=A._zod.parent;if(B){const g={...this.get(B)??{}};delete g.id;const I={...g,...this._map.get(A)};return Object.keys(I).length?I:void 0}return this._map.get(A)}has(A){return this._map.has(A)}}function Hc(){return new Wc}(xe=globalThis).__zod_globalRegistry??(xe.__zod_globalRegistry=Hc());const Vg=globalThis.__zod_globalRegistry;function fc(Q,A){return new Q({type:"string",...$(A)})}function Nc(Q,A){return new Q({type:"string",format:"email",check:"string_format",abort:!1,...$(A)})}function Ve(Q,A){return new Q({type:"string",format:"guid",check:"string_format",abort:!1,...$(A)})}function Jc(Q,A){return new Q({type:"string",format:"uuid",check:"string_format",abort:!1,...$(A)})}function qc(Q,A){return new Q({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...$(A)})}function xc(Q,A){return new Q({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...$(A)})}function Vc(Q,A){return new Q({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...$(A)})}function Lc(Q,A){return new Q({type:"string",format:"url",check:"string_format",abort:!1,...$(A)})}function Xc(Q,A){return new Q({type:"string",format:"emoji",check:"string_format",abort:!1,...$(A)})}function vc(Q,A){return new Q({type:"string",format:"nanoid",check:"string_format",abort:!1,...$(A)})}function Kc(Q,A){return new Q({type:"string",format:"cuid",check:"string_format",abort:!1,...$(A)})}function zc(Q,A){return new Q({type:"string",format:"cuid2",check:"string_format",abort:!1,...$(A)})}function Tc(Q,A){return new Q({type:"string",format:"ulid",check:"string_format",abort:!1,...$(A)})}function jc(Q,A){return new Q({type:"string",format:"xid",check:"string_format",abort:!1,...$(A)})}function Oc(Q,A){return new Q({type:"string",format:"ksuid",check:"string_format",abort:!1,...$(A)})}function Pc(Q,A){return new Q({type:"string",format:"ipv4",check:"string_format",abort:!1,...$(A)})}function _c(Q,A){return new Q({type:"string",format:"ipv6",check:"string_format",abort:!1,...$(A)})}function $c(Q,A){return new Q({type:"string",format:"cidrv4",check:"string_format",abort:!1,...$(A)})}function Ar(Q,A){return new Q({type:"string",format:"cidrv6",check:"string_format",abort:!1,...$(A)})}function Br(Q,A){return new Q({type:"string",format:"base64",check:"string_format",abort:!1,...$(A)})}function gr(Q,A){return new Q({type:"string",format:"base64url",check:"string_format",abort:!1,...$(A)})}function Ir(Q,A){return new Q({type:"string",format:"e164",check:"string_format",abort:!1,...$(A)})}function Qr(Q,A){return new Q({type:"string",format:"jwt",check:"string_format",abort:!1,...$(A)})}function Er(Q,A){return new Q({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...$(A)})}function ir(Q,A){return new Q({type:"string",format:"date",check:"string_format",...$(A)})}function Cr(Q,A){return new Q({type:"string",format:"time",check:"string_format",precision:null,...$(A)})}function ar(Q,A){return new Q({type:"string",format:"duration",check:"string_format",...$(A)})}function er(Q,A){return new Q({type:"number",checks:[],...$(A)})}function or(Q,A){return new Q({type:"number",check:"number_format",abort:!1,format:"safeint",...$(A)})}function tr(Q,A){return new Q({type:"boolean",...$(A)})}function sr(Q){return new Q({type:"unknown"})}function Gr(Q,A){return new Q({type:"never",...$(A)})}function Le(Q,A){return new me({check:"less_than",...$(A),value:Q,inclusive:!1})}function LE(Q,A){return new me({check:"less_than",...$(A),value:Q,inclusive:!0})}function Xe(Q,A){return new ue({check:"greater_than",...$(A),value:Q,inclusive:!1})}function XE(Q,A){return new ue({check:"greater_than",...$(A),value:Q,inclusive:!0})}function ve(Q,A){return new bh({check:"multiple_of",...$(A),value:Q})}function Ke(Q,A){return new Yh({check:"max_length",...$(A),maximum:Q})}function XI(Q,A){return new Uh({check:"min_length",...$(A),minimum:Q})}function ze(Q,A){return new kh({check:"length_equals",...$(A),length:Q})}function nr(Q,A){return new Zh({check:"string_format",format:"regex",...$(A),pattern:Q})}function hr(Q){return new Wh({check:"string_format",format:"lowercase",...$(Q)})}function cr(Q){return new Hh({check:"string_format",format:"uppercase",...$(Q)})}function rr(Q,A){return new fh({check:"string_format",format:"includes",...$(A),includes:Q})}function lr(Q,A){return new Nh({check:"string_format",format:"starts_with",...$(A),prefix:Q})}function Dr(Q,A){return new Jh({check:"string_format",format:"ends_with",...$(A),suffix:Q})}function ng(Q){return new qh({check:"overwrite",tx:Q})}function dr(Q){return ng(A=>A.normalize(Q))}function Fr(){return ng(Q=>Q.trim())}function Mr(){return ng(Q=>Q.toLowerCase())}function wr(){return ng(Q=>Q.toUpperCase())}function yr(){return ng(Q=>Zn(Q))}function Rr(Q,A,B){return new Q({type:"array",element:A,...$(B)})}function mr(Q,A,B){return new Q({type:"custom",check:"custom",fn:A,...$(B)})}function ur(Q){const A=Sr(B=>(B.addIssue=g=>{if(typeof g=="string")B.issues.push(xg(g,B.value,A._zod.def));else{const I=g;I.fatal&&(I.continue=!1),I.code??(I.code="custom"),I.input??(I.input=B.value),I.inst??(I.inst=A),I.continue??(I.continue=!A._zod.def.abort),B.issues.push(xg(I))}},Q(B.value,B)));return A}function Sr(Q,A){const B=new vA({check:"custom",...$(A)});return B._zod.check=Q,B}function Te(Q){let A=Q?.target??"draft-2020-12";return A==="draft-4"&&(A="draft-04"),A==="draft-7"&&(A="draft-07"),{processors:Q.processors??{},metadataRegistry:Q?.metadata??Vg,target:A,unrepresentable:Q?.unrepresentable??"throw",override:Q?.override??(()=>{}),io:Q?.io??"output",counter:0,seen:new Map,cycles:Q?.cycles??"ref",reused:Q?.reused??"inline",external:Q?.external??void 0}}function mA(Q,A,B={path:[],schemaPath:[]}){var g;const I=Q._zod.def,E=A.seen.get(Q);if(E)return E.count++,B.schemaPath.includes(Q)&&(E.cycle=B.path),E.schema;const i={schema:{},count:1,cycle:void 0,path:B.path};A.seen.set(Q,i);const C=Q._zod.toJSONSchema?.();if(C)i.schema=C;else{const o={...B,schemaPath:[...B.schemaPath,Q],path:B.path};if(Q._zod.processJSONSchema)Q._zod.processJSONSchema(A,i.schema,o);else{const s=i.schema,G=A.processors[I.type];if(!G)throw new Error(`[toJSONSchema]: Non-representable type encountered: ${I.type}`);G(Q,A,s,o)}const t=Q._zod.parent;t&&(i.ref||(i.ref=t),mA(t,A,o),A.seen.get(t).isParent=!0)}const a=A.metadataRegistry.get(Q);return a&&Object.assign(i.schema,a),A.io==="input"&&xA(Q)&&(delete i.schema.examples,delete i.schema.default),A.io==="input"&&i.schema._prefault&&((g=i.schema).default??(g.default=i.schema._prefault)),delete i.schema._prefault,A.seen.get(Q).schema}function je(Q,A){const B=Q.seen.get(A);if(!B)throw new Error("Unprocessed schema. This is a bug in Zod.");const g=new Map;for(const i of Q.seen.entries()){const C=Q.metadataRegistry.get(i[0])?.id;if(C){const a=g.get(C);if(a&&a!==i[0])throw new Error(`Duplicate schema id "${C}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);g.set(C,i[0])}}const I=i=>{const C=Q.target==="draft-2020-12"?"$defs":"definitions";if(Q.external){const t=Q.external.registry.get(i[0])?.id,s=Q.external.uri??(n=>n);if(t)return{ref:s(t)};const G=i[1].defId??i[1].schema.id??`schema${Q.counter++}`;return i[1].defId=G,{defId:G,ref:`${s("__shared")}#/${C}/${G}`}}if(i[1]===B)return{ref:"#"};const e=`#/${C}/`,o=i[1].schema.id??`__schema${Q.counter++}`;return{defId:o,ref:e+o}},E=i=>{if(i[1].schema.$ref)return;const C=i[1],{ref:a,defId:e}=I(i);C.def={...C.schema},e&&(C.defId=e);const o=C.schema;for(const t in o)delete o[t];o.$ref=a};if(Q.cycles==="throw")for(const i of Q.seen.entries()){const C=i[1];if(C.cycle)throw new Error(`Cycle detected: #/${C.cycle?.join("/")}/<root>
|
|
48
48
|
|
|
49
|
-
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const i of Q.seen.entries()){const C=i[1];if(A===i[0]){E(i);continue}if(Q.external){const e=Q.external.registry.get(i[0])?.id;if(A!==i[0]&&e){E(i);continue}}if(Q.metadataRegistry.get(i[0])?.id){E(i);continue}if(C.cycle){E(i);continue}if(C.count>1&&Q.reused==="ref"){E(i);continue}}}function Oe(Q,A){const B=Q.seen.get(A);if(!B)throw new Error("Unprocessed schema. This is a bug in Zod.");const g=i=>{const C=Q.seen.get(i);if(C.ref===null)return;const a=C.def??C.schema,e={...a},o=C.ref;if(C.ref=null,o){g(o);const s=Q.seen.get(o),G=s.schema;if(G.$ref&&(Q.target==="draft-07"||Q.target==="draft-04"||Q.target==="openapi-3.0")?(a.allOf=a.allOf??[],a.allOf.push(G)):Object.assign(a,G),Object.assign(a,e),i._zod.parent===o)for(const h in a)h==="$ref"||h==="allOf"||h in e||delete a[h];if(G.$ref&&s.def)for(const h in a)h==="$ref"||h==="allOf"||h in s.def&&JSON.stringify(a[h])===JSON.stringify(s.def[h])&&delete a[h]}const t=i._zod.parent;if(t&&t!==o){g(t);const s=Q.seen.get(t);if(s?.schema.$ref&&(a.$ref=s.schema.$ref,s.def))for(const G in a)G==="$ref"||G==="allOf"||G in s.def&&JSON.stringify(a[G])===JSON.stringify(s.def[G])&&delete a[G]}Q.override({zodSchema:i,jsonSchema:a,path:C.path??[]})};for(const i of[...Q.seen.entries()].reverse())g(i[0]);const I={};if(Q.target==="draft-2020-12"?I.$schema="https://json-schema.org/draft/2020-12/schema":Q.target==="draft-07"?I.$schema="http://json-schema.org/draft-07/schema#":Q.target==="draft-04"?I.$schema="http://json-schema.org/draft-04/schema#":Q.target,Q.external?.uri){const i=Q.external.registry.get(A)?.id;if(!i)throw new Error("Schema is missing an `id` property");I.$id=Q.external.uri(i)}Object.assign(I,B.def??B.schema);const E=Q.external?.defs??{};for(const i of Q.seen.entries()){const C=i[1];C.def&&C.defId&&(E[C.defId]=C.def)}Q.external||Object.keys(E).length>0&&(Q.target==="draft-2020-12"?I.$defs=E:I.definitions=E);try{const i=JSON.parse(JSON.stringify(I));return Object.defineProperty(i,"~standard",{value:{...A["~standard"],jsonSchema:{input:vI(A,"input",Q.processors),output:vI(A,"output",Q.processors)}},enumerable:!1,writable:!1}),i}catch{throw new Error("Error converting schema to JSON.")}}function xA(Q,A){const B=A??{seen:new Set};if(B.seen.has(Q))return!1;B.seen.add(Q);const g=Q._zod.def;if(g.type==="transform")return!0;if(g.type==="array")return xA(g.element,B);if(g.type==="set")return xA(g.valueType,B);if(g.type==="lazy")return xA(g.getter(),B);if(g.type==="promise"||g.type==="optional"||g.type==="nonoptional"||g.type==="nullable"||g.type==="readonly"||g.type==="default"||g.type==="prefault")return xA(g.innerType,B);if(g.type==="intersection")return xA(g.left,B)||xA(g.right,B);if(g.type==="record"||g.type==="map")return xA(g.keyType,B)||xA(g.valueType,B);if(g.type==="pipe")return xA(g.in,B)||xA(g.out,B);if(g.type==="object"){for(const I in g.shape)if(xA(g.shape[I],B))return!0;return!1}if(g.type==="union"){for(const I of g.options)if(xA(I,B))return!0;return!1}if(g.type==="tuple"){for(const I of g.items)if(xA(I,B))return!0;return!!(g.rest&&xA(g.rest,B))}return!1}const br=(Q,A={})=>B=>{const g=Te({...B,processors:A});return mA(Q,g),je(g,Q),Oe(g,Q)},vI=(Q,A,B={})=>g=>{const{libraryOptions:I,target:E}=g??{},i=Te({...I??{},target:E,io:A,processors:B});return mA(Q,i),je(i,Q),Oe(i,Q)},pr={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},Yr=(Q,A,B,g)=>{const I=B;I.type="string";const{minimum:E,maximum:i,format:C,patterns:a,contentEncoding:e}=Q._zod.bag;if(typeof E=="number"&&(I.minLength=E),typeof i=="number"&&(I.maxLength=i),C&&(I.format=pr[C]??C,I.format===""&&delete I.format,C==="time"&&delete I.format),e&&(I.contentEncoding=e),a&&a.size>0){const o=[...a];o.length===1?I.pattern=o[0].source:o.length>1&&(I.allOf=[...o.map(t=>({...A.target==="draft-07"||A.target==="draft-04"||A.target==="openapi-3.0"?{type:"string"}:{},pattern:t.source}))])}},Ur=(Q,A,B,g)=>{const I=B,{minimum:E,maximum:i,format:C,multipleOf:a,exclusiveMaximum:e,exclusiveMinimum:o}=Q._zod.bag;typeof C=="string"&&C.includes("int")?I.type="integer":I.type="number",typeof o=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(I.minimum=o,I.exclusiveMinimum=!0):I.exclusiveMinimum=o),typeof E=="number"&&(I.minimum=E,typeof o=="number"&&A.target!=="draft-04"&&(o>=E?delete I.minimum:delete I.exclusiveMinimum)),typeof e=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(I.maximum=e,I.exclusiveMaximum=!0):I.exclusiveMaximum=e),typeof i=="number"&&(I.maximum=i,typeof e=="number"&&A.target!=="draft-04"&&(e<=i?delete I.maximum:delete I.exclusiveMaximum)),typeof a=="number"&&(I.multipleOf=a)},kr=(Q,A,B,g)=>{B.type="boolean"},Zr=(Q,A,B,g)=>{B.not={}},Wr=(Q,A,B,g)=>{},Hr=(Q,A,B,g)=>{const I=Q._zod.def,E=se(I.entries);E.every(i=>typeof i=="number")&&(B.type="number"),E.every(i=>typeof i=="string")&&(B.type="string"),B.enum=E},fr=(Q,A,B,g)=>{if(A.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},Nr=(Q,A,B,g)=>{if(A.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},Jr=(Q,A,B,g)=>{const I=B,E=Q._zod.def,{minimum:i,maximum:C}=Q._zod.bag;typeof i=="number"&&(I.minItems=i),typeof C=="number"&&(I.maxItems=C),I.type="array",I.items=mA(E.element,A,{...g,path:[...g.path,"items"]})},qr=(Q,A,B,g)=>{const I=B,E=Q._zod.def;I.type="object",I.properties={};const i=E.shape;for(const e in i)I.properties[e]=mA(i[e],A,{...g,path:[...g.path,"properties",e]});const C=new Set(Object.keys(i)),a=new Set([...C].filter(e=>{const o=E.shape[e]._zod;return A.io==="input"?o.optin===void 0:o.optout===void 0}));a.size>0&&(I.required=Array.from(a)),E.catchall?._zod.def.type==="never"?I.additionalProperties=!1:E.catchall?E.catchall&&(I.additionalProperties=mA(E.catchall,A,{...g,path:[...g.path,"additionalProperties"]})):A.io==="output"&&(I.additionalProperties=!1)},xr=(Q,A,B,g)=>{const I=Q._zod.def,E=I.inclusive===!1,i=I.options.map((C,a)=>mA(C,A,{...g,path:[...g.path,E?"oneOf":"anyOf",a]}));E?B.oneOf=i:B.anyOf=i},Vr=(Q,A,B,g)=>{const I=Q._zod.def,E=mA(I.left,A,{...g,path:[...g.path,"allOf",0]}),i=mA(I.right,A,{...g,path:[...g.path,"allOf",1]}),C=e=>"allOf"in e&&Object.keys(e).length===1,a=[...C(E)?E.allOf:[E],...C(i)?i.allOf:[i]];B.allOf=a},Lr=(Q,A,B,g)=>{const I=B,E=Q._zod.def;I.type="object";const i=E.keyType,a=i._zod.bag?.patterns;if(E.mode==="loose"&&a&&a.size>0){const o=mA(E.valueType,A,{...g,path:[...g.path,"patternProperties","*"]});I.patternProperties={};for(const t of a)I.patternProperties[t.source]=o}else(A.target==="draft-07"||A.target==="draft-2020-12")&&(I.propertyNames=mA(E.keyType,A,{...g,path:[...g.path,"propertyNames"]})),I.additionalProperties=mA(E.valueType,A,{...g,path:[...g.path,"additionalProperties"]});const e=i._zod.values;if(e){const o=[...e].filter(t=>typeof t=="string"||typeof t=="number");o.length>0&&(I.required=o)}},Xr=(Q,A,B,g)=>{const I=Q._zod.def,E=mA(I.innerType,A,g),i=A.seen.get(Q);A.target==="openapi-3.0"?(i.ref=I.innerType,B.nullable=!0):B.anyOf=[E,{type:"null"}]},vr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType},Kr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType,B.default=JSON.parse(JSON.stringify(I.defaultValue))},zr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType,A.io==="input"&&(B._prefault=JSON.parse(JSON.stringify(I.defaultValue)))},Tr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType;let i;try{i=I.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}B.default=i},jr=(Q,A,B,g)=>{const I=Q._zod.def,E=A.io==="input"?I.in._zod.def.type==="transform"?I.out:I.in:I.out;mA(E,A,g);const i=A.seen.get(Q);i.ref=E},Or=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType,B.readOnly=!0},Pe=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType},Pr=Z("ZodISODateTime",(Q,A)=>{Ac.init(Q,A),lA.init(Q,A)});function _r(Q){return Er(Pr,Q)}const $r=Z("ZodISODate",(Q,A)=>{Bc.init(Q,A),lA.init(Q,A)});function Al(Q){return ir($r,Q)}const Bl=Z("ZodISOTime",(Q,A)=>{gc.init(Q,A),lA.init(Q,A)});function gl(Q){return Cr(Bl,Q)}const Il=Z("ZodISODuration",(Q,A)=>{Ic.init(Q,A),lA.init(Q,A)});function Ql(Q){return ar(Il,Q)}const PA=Z("ZodError",(Q,A)=>{le.init(Q,A),Q.name="ZodError",Object.defineProperties(Q,{format:{value:B=>zn(Q,B)},flatten:{value:B=>Kn(Q,B)},addIssue:{value:B=>{Q.issues.push(B),Q.message=JSON.stringify(Q.issues,ZE,2)}},addIssues:{value:B=>{Q.issues.push(...B),Q.message=JSON.stringify(Q.issues,ZE,2)}},isEmpty:{get(){return Q.issues.length===0}}})},{Parent:Error}),El=JE(PA),il=qE(PA),Cl=JI(PA),al=qI(PA),el=On(PA),ol=Pn(PA),tl=_n(PA),sl=$n(PA),Gl=Ah(PA),nl=Bh(PA),hl=gh(PA),cl=Ih(PA),MA=Z("ZodType",(Q,A)=>(FA.init(Q,A),Object.assign(Q["~standard"],{jsonSchema:{input:vI(Q,"input"),output:vI(Q,"output")}}),Q.toJSONSchema=br(Q,{}),Q.def=A,Q.type=A.type,Object.defineProperty(Q,"_def",{value:A}),Q.check=(...B)=>Q.clone(kB(A,{checks:[...A.checks??[],...B.map(g=>typeof g=="function"?{_zod:{check:g,def:{check:"custom"},onattach:[]}}:g)]}),{parent:!0}),Q.with=Q.check,Q.clone=(B,g)=>ZB(Q,B,g),Q.brand=()=>Q,Q.register=((B,g)=>(B.add(Q,g),Q)),Q.parse=(B,g)=>El(Q,B,g,{callee:Q.parse}),Q.safeParse=(B,g)=>Cl(Q,B,g),Q.parseAsync=async(B,g)=>il(Q,B,g,{callee:Q.parseAsync}),Q.safeParseAsync=async(B,g)=>al(Q,B,g),Q.spa=Q.safeParseAsync,Q.encode=(B,g)=>el(Q,B,g),Q.decode=(B,g)=>ol(Q,B,g),Q.encodeAsync=async(B,g)=>tl(Q,B,g),Q.decodeAsync=async(B,g)=>sl(Q,B,g),Q.safeEncode=(B,g)=>Gl(Q,B,g),Q.safeDecode=(B,g)=>nl(Q,B,g),Q.safeEncodeAsync=async(B,g)=>hl(Q,B,g),Q.safeDecodeAsync=async(B,g)=>cl(Q,B,g),Q.refine=(B,g)=>Q.check(aD(B,g)),Q.superRefine=B=>Q.check(eD(B)),Q.overwrite=B=>Q.check(ng(B)),Q.optional=()=>Qo(Q),Q.exactOptional=()=>jl(Q),Q.nullable=()=>Eo(Q),Q.nullish=()=>Qo(Eo(Q)),Q.nonoptional=B=>BD(Q,B),Q.array=()=>UA(Q),Q.or=B=>KE([Q,B]),Q.and=B=>Xl(Q,B),Q.transform=B=>Co(Q,zl(B)),Q.default=B=>_l(Q,B),Q.prefault=B=>AD(Q,B),Q.catch=B=>ID(Q,B),Q.pipe=B=>Co(Q,B),Q.readonly=()=>iD(Q),Q.describe=B=>{const g=Q.clone();return Vg.add(g,{description:B}),g},Object.defineProperty(Q,"description",{get(){return Vg.get(Q)?.description},configurable:!0}),Q.meta=(...B)=>{if(B.length===0)return Vg.get(Q);const g=Q.clone();return Vg.add(g,B[0]),g},Q.isOptional=()=>Q.safeParse(void 0).success,Q.isNullable=()=>Q.safeParse(null).success,Q.apply=B=>B(Q),Q)),_e=Z("_ZodString",(Q,A)=>{xE.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(g,I,E)=>Yr(Q,g,I);const B=Q._zod.bag;Q.format=B.format??null,Q.minLength=B.minimum??null,Q.maxLength=B.maximum??null,Q.regex=(...g)=>Q.check(nr(...g)),Q.includes=(...g)=>Q.check(rr(...g)),Q.startsWith=(...g)=>Q.check(lr(...g)),Q.endsWith=(...g)=>Q.check(Dr(...g)),Q.min=(...g)=>Q.check(XI(...g)),Q.max=(...g)=>Q.check(Ke(...g)),Q.length=(...g)=>Q.check(ze(...g)),Q.nonempty=(...g)=>Q.check(XI(1,...g)),Q.lowercase=g=>Q.check(hr(g)),Q.uppercase=g=>Q.check(cr(g)),Q.trim=()=>Q.check(Fr()),Q.normalize=(...g)=>Q.check(dr(...g)),Q.toLowerCase=()=>Q.check(Mr()),Q.toUpperCase=()=>Q.check(wr()),Q.slugify=()=>Q.check(yr())}),rl=Z("ZodString",(Q,A)=>{xE.init(Q,A),_e.init(Q,A),Q.email=B=>Q.check(Nc(ll,B)),Q.url=B=>Q.check(Lc(Dl,B)),Q.jwt=B=>Q.check(Qr(Zl,B)),Q.emoji=B=>Q.check(Xc(dl,B)),Q.guid=B=>Q.check(Ve($e,B)),Q.uuid=B=>Q.check(Jc(KI,B)),Q.uuidv4=B=>Q.check(qc(KI,B)),Q.uuidv6=B=>Q.check(xc(KI,B)),Q.uuidv7=B=>Q.check(Vc(KI,B)),Q.nanoid=B=>Q.check(vc(Fl,B)),Q.guid=B=>Q.check(Ve($e,B)),Q.cuid=B=>Q.check(Kc(Ml,B)),Q.cuid2=B=>Q.check(zc(wl,B)),Q.ulid=B=>Q.check(Tc(yl,B)),Q.base64=B=>Q.check(Br(Yl,B)),Q.base64url=B=>Q.check(gr(Ul,B)),Q.xid=B=>Q.check(jc(Rl,B)),Q.ksuid=B=>Q.check(Oc(ml,B)),Q.ipv4=B=>Q.check(Pc(ul,B)),Q.ipv6=B=>Q.check(_c(Sl,B)),Q.cidrv4=B=>Q.check($c(bl,B)),Q.cidrv6=B=>Q.check(Ar(pl,B)),Q.e164=B=>Q.check(Ir(kl,B)),Q.datetime=B=>Q.check(_r(B)),Q.date=B=>Q.check(Al(B)),Q.time=B=>Q.check(gl(B)),Q.duration=B=>Q.check(Ql(B))});function z(Q){return fc(rl,Q)}const lA=Z("ZodStringFormat",(Q,A)=>{cA.init(Q,A),_e.init(Q,A)}),ll=Z("ZodEmail",(Q,A)=>{vh.init(Q,A),lA.init(Q,A)}),$e=Z("ZodGUID",(Q,A)=>{Lh.init(Q,A),lA.init(Q,A)}),KI=Z("ZodUUID",(Q,A)=>{Xh.init(Q,A),lA.init(Q,A)}),Dl=Z("ZodURL",(Q,A)=>{Kh.init(Q,A),lA.init(Q,A)}),dl=Z("ZodEmoji",(Q,A)=>{zh.init(Q,A),lA.init(Q,A)}),Fl=Z("ZodNanoID",(Q,A)=>{Th.init(Q,A),lA.init(Q,A)}),Ml=Z("ZodCUID",(Q,A)=>{jh.init(Q,A),lA.init(Q,A)}),wl=Z("ZodCUID2",(Q,A)=>{Oh.init(Q,A),lA.init(Q,A)}),yl=Z("ZodULID",(Q,A)=>{Ph.init(Q,A),lA.init(Q,A)}),Rl=Z("ZodXID",(Q,A)=>{_h.init(Q,A),lA.init(Q,A)}),ml=Z("ZodKSUID",(Q,A)=>{$h.init(Q,A),lA.init(Q,A)}),ul=Z("ZodIPv4",(Q,A)=>{Qc.init(Q,A),lA.init(Q,A)}),Sl=Z("ZodIPv6",(Q,A)=>{Ec.init(Q,A),lA.init(Q,A)}),bl=Z("ZodCIDRv4",(Q,A)=>{ic.init(Q,A),lA.init(Q,A)}),pl=Z("ZodCIDRv6",(Q,A)=>{Cc.init(Q,A),lA.init(Q,A)}),Yl=Z("ZodBase64",(Q,A)=>{ac.init(Q,A),lA.init(Q,A)}),Ul=Z("ZodBase64URL",(Q,A)=>{oc.init(Q,A),lA.init(Q,A)}),kl=Z("ZodE164",(Q,A)=>{tc.init(Q,A),lA.init(Q,A)}),Zl=Z("ZodJWT",(Q,A)=>{Gc.init(Q,A),lA.init(Q,A)}),Ao=Z("ZodNumber",(Q,A)=>{be.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(g,I,E)=>Ur(Q,g,I),Q.gt=(g,I)=>Q.check(Xe(g,I)),Q.gte=(g,I)=>Q.check(XE(g,I)),Q.min=(g,I)=>Q.check(XE(g,I)),Q.lt=(g,I)=>Q.check(Le(g,I)),Q.lte=(g,I)=>Q.check(LE(g,I)),Q.max=(g,I)=>Q.check(LE(g,I)),Q.int=g=>Q.check(Bo(g)),Q.safe=g=>Q.check(Bo(g)),Q.positive=g=>Q.check(Xe(0,g)),Q.nonnegative=g=>Q.check(XE(0,g)),Q.negative=g=>Q.check(Le(0,g)),Q.nonpositive=g=>Q.check(LE(0,g)),Q.multipleOf=(g,I)=>Q.check(ve(g,I)),Q.step=(g,I)=>Q.check(ve(g,I)),Q.finite=()=>Q;const B=Q._zod.bag;Q.minValue=Math.max(B.minimum??Number.NEGATIVE_INFINITY,B.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,Q.maxValue=Math.min(B.maximum??Number.POSITIVE_INFINITY,B.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,Q.isInt=(B.format??"").includes("int")||Number.isSafeInteger(B.multipleOf??.5),Q.isFinite=!0,Q.format=B.format??null});function X(Q){return er(Ao,Q)}const Wl=Z("ZodNumberFormat",(Q,A)=>{nc.init(Q,A),Ao.init(Q,A)});function Bo(Q){return or(Wl,Q)}const Hl=Z("ZodBoolean",(Q,A)=>{hc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>kr(Q,B,g)});function vE(Q){return tr(Hl,Q)}const fl=Z("ZodUnknown",(Q,A)=>{cc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Wr()});function go(){return sr(fl)}const Nl=Z("ZodNever",(Q,A)=>{rc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Zr(Q,B,g)});function Jl(Q){return Gr(Nl,Q)}const ql=Z("ZodArray",(Q,A)=>{lc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Jr(Q,B,g,I),Q.element=A.element,Q.min=(B,g)=>Q.check(XI(B,g)),Q.nonempty=B=>Q.check(XI(1,B)),Q.max=(B,g)=>Q.check(Ke(B,g)),Q.length=(B,g)=>Q.check(ze(B,g)),Q.unwrap=()=>Q.element});function UA(Q,A){return Rr(ql,Q,A)}const xl=Z("ZodObject",(Q,A)=>{dc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>qr(Q,B,g,I),tA(Q,"shape",()=>A.shape),Q.keyof=()=>TI(Object.keys(Q._zod.def.shape)),Q.catchall=B=>Q.clone({...Q._zod.def,catchall:B}),Q.passthrough=()=>Q.clone({...Q._zod.def,catchall:go()}),Q.loose=()=>Q.clone({...Q._zod.def,catchall:go()}),Q.strict=()=>Q.clone({...Q._zod.def,catchall:Jl()}),Q.strip=()=>Q.clone({...Q._zod.def,catchall:void 0}),Q.extend=B=>xn(Q,B),Q.safeExtend=B=>Vn(Q,B),Q.merge=B=>Ln(Q,B),Q.pick=B=>Jn(Q,B),Q.omit=B=>qn(Q,B),Q.partial=(...B)=>Xn(Io,Q,B[0]),Q.required=(...B)=>vn(io,Q,B[0])});function nA(Q,A){const B={type:"object",shape:Q??{},...$(A)};return new xl(B)}const Vl=Z("ZodUnion",(Q,A)=>{Fc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>xr(Q,B,g,I),Q.options=A.options});function KE(Q,A){return new Vl({type:"union",options:Q,...$(A)})}const Ll=Z("ZodIntersection",(Q,A)=>{Mc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Vr(Q,B,g,I)});function Xl(Q,A){return new Ll({type:"intersection",left:Q,right:A})}const vl=Z("ZodRecord",(Q,A)=>{wc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Lr(Q,B,g,I),Q.keyType=A.keyType,Q.valueType=A.valueType});function zI(Q,A,B){return new vl({type:"record",keyType:Q,valueType:A,...$(B)})}const zE=Z("ZodEnum",(Q,A)=>{yc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(g,I,E)=>Hr(Q,g,I),Q.enum=A.entries,Q.options=Object.values(A.entries);const B=new Set(Object.keys(A.entries));Q.extract=(g,I)=>{const E={};for(const i of g)if(B.has(i))E[i]=A.entries[i];else throw new Error(`Key ${i} not found in enum`);return new zE({...A,checks:[],...$(I),entries:E})},Q.exclude=(g,I)=>{const E={...A.entries};for(const i of g)if(B.has(i))delete E[i];else throw new Error(`Key ${i} not found in enum`);return new zE({...A,checks:[],...$(I),entries:E})}});function TI(Q,A){const B=Array.isArray(Q)?Object.fromEntries(Q.map(g=>[g,g])):Q;return new zE({type:"enum",entries:B,...$(A)})}const Kl=Z("ZodTransform",(Q,A)=>{Rc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Nr(Q,B),Q._zod.parse=(B,g)=>{if(g.direction==="backward")throw new oe(Q.constructor.name);B.addIssue=E=>{if(typeof E=="string")B.issues.push(xg(E,B.value,A));else{const i=E;i.fatal&&(i.continue=!1),i.code??(i.code="custom"),i.input??(i.input=B.value),i.inst??(i.inst=Q),B.issues.push(xg(i))}};const I=A.transform(B.value,B);return I instanceof Promise?I.then(E=>(B.value=E,B)):(B.value=I,B)}});function zl(Q){return new Kl({type:"transform",transform:Q})}const Io=Z("ZodOptional",(Q,A)=>{He.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Pe(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function Qo(Q){return new Io({type:"optional",innerType:Q})}const Tl=Z("ZodExactOptional",(Q,A)=>{mc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Pe(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function jl(Q){return new Tl({type:"optional",innerType:Q})}const Ol=Z("ZodNullable",(Q,A)=>{uc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Xr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function Eo(Q){return new Ol({type:"nullable",innerType:Q})}const Pl=Z("ZodDefault",(Q,A)=>{Sc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Kr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType,Q.removeDefault=Q.unwrap});function _l(Q,A){return new Pl({type:"default",innerType:Q,get defaultValue(){return typeof A=="function"?A():ce(A)}})}const $l=Z("ZodPrefault",(Q,A)=>{bc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>zr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function AD(Q,A){return new $l({type:"prefault",innerType:Q,get defaultValue(){return typeof A=="function"?A():ce(A)}})}const io=Z("ZodNonOptional",(Q,A)=>{pc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>vr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function BD(Q,A){return new io({type:"nonoptional",innerType:Q,...$(A)})}const gD=Z("ZodCatch",(Q,A)=>{Yc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Tr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType,Q.removeCatch=Q.unwrap});function ID(Q,A){return new gD({type:"catch",innerType:Q,catchValue:typeof A=="function"?A:()=>A})}const QD=Z("ZodPipe",(Q,A)=>{Uc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>jr(Q,B,g,I),Q.in=A.in,Q.out=A.out});function Co(Q,A){return new QD({type:"pipe",in:Q,out:A})}const ED=Z("ZodReadonly",(Q,A)=>{kc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Or(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function iD(Q){return new ED({type:"readonly",innerType:Q})}const CD=Z("ZodCustom",(Q,A)=>{Zc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>fr(Q,B)});function aD(Q,A={}){return mr(CD,Q,A)}function eD(Q){return ur(Q)}const oD=pB.map(Q=>Q),ao=nA({id:z(),uuid:z(),playlist_index:X().nonnegative(),chain_name:z(),token_address:z().optional(),token_id:z().optional(),tx_id:z().optional(),platform:z(),title:z(),artist:z(),description:z().optional(),album:z().optional(),image_url:z().url(),image_thumb_url:z().url().optional(),audio_url:z().url(),audio_url_lossless:z().url().optional(),duration:X().nonnegative(),genre:z(),tags:UA(z()),bpm:X().positive().optional(),key:z().optional(),attributes:zI(z(),KE([z(),X()])).optional()}).refine(Q=>Q.chain_name==="AR"?!!Q.tx_id:!!Q.token_address&&!!Q.token_id,{message:"AR chain tracks must have tx_id; other chains must have token_address and token_id",path:["chain_name"]}),tD=nA({name:z(),description:z().optional(),image:z().url(),creator:z(),genre:z().optional(),tags:UA(z()).optional(),tracks:UA(ao)}),sD=nA({bass_dominance:X().min(0).max(1),mid_dominance:X().min(0).max(1),treble_dominance:X().min(0).max(1),average_amplitude:X().min(0).max(1),spectral_centroid:X().optional(),spectral_rolloff:X().optional(),zero_crossing_rate:X().optional(),color_palette:nA({colors:UA(z()),primary_color:z(),secondary_color:z().optional(),accent_color:z().optional(),brightness:X().min(0).max(1),saturation:X().min(0).max(1),is_monochrome:vE()}).optional(),analysis_metadata:nA({duration_analyzed:X().positive(),full_buffer_analyzed:vE(),sample_positions:UA(X()),analyzed_at:z()})}),TE=nA({STR:X().min(1).max(20),DEX:X().min(1).max(20),CON:X().min(1).max(20),INT:X().min(1).max(20),WIS:X().min(1).max(20),CHA:X().min(1).max(20)}),GD=nA({name:z(),race:TI(["Human","Elf","Dwarf","Halfling","Dragonborn","Gnome","Half-Elf","Half-Orc","Tiefling"]),class:TI(oD),level:X().min(1).max(20),ability_scores:TE,ability_modifiers:TE,proficiency_bonus:X().min(2).max(6),hp:nA({current:X().nonnegative(),max:X().positive(),temp:X().nonnegative()}),armor_class:X().positive(),initiative:X(),speed:X().positive(),skills:zI(z(),TI(["none","proficient","expertise"])),saving_throws:zI(z(),vE()),racial_traits:UA(z()),class_features:UA(z()),spells:nA({spell_slots:zI(z(),nA({total:X().nonnegative(),used:X().nonnegative()})),known_spells:UA(z()),cantrips:UA(z())}).optional(),equipment:nA({weapons:UA(z()),armor:UA(z()),items:UA(z())}).optional(),appearance:nA({body_type:z(),skin_tone:z(),hair_style:z(),hair_color:z(),eye_color:z(),facial_features:UA(z()),primary_color:z().optional(),secondary_color:z().optional(),aura_color:z().optional()}).optional(),xp:nA({current:X().nonnegative(),next_level:X().positive()}),seed:z(),generated_at:z()});var eo=(Q=>(Q[Q.DEBUG=0]="DEBUG",Q[Q.INFO=1]="INFO",Q[Q.WARN=2]="WARN",Q[Q.ERROR=3]="ERROR",Q[Q.NONE=4]="NONE",Q))(eo||{});const nD={0:"DEBUG",1:"INFO",2:"WARN",3:"ERROR",4:"NONE"};let eB=1,jE=!0,OE=!0,jI=null,OI=!1,Lg=!1;class SA{constructor(A){this.context=A}static for(A){return new SA(A)}static enableDiagnosticMode(){OI=!0,eB=0}static disableDiagnosticMode(){OI=!1,eB=1}static isDiagnosticMode(){return OI}static enableVerbose(){Lg=!0,eB=0}static disableVerbose(){Lg=!1,eB=1}static isVerbose(){return Lg}static setVerbose(A){Lg=A,eB=A?0:1}static setLevel(A){eB=A}static getLevel(){return eB}static configure(A){A.level!==void 0&&(eB=A.level),A.includeTimestamp!==void 0&&(jE=A.includeTimestamp),A.includeContext!==void 0&&(OE=A.includeContext),A.customHandler!==void 0&&(jI=A.customHandler)}static reset(){eB=1,jE=!0,OE=!0,jI=null,OI=!1,Lg=!1}debug(A,B){this.log(0,A,B)}info(A,B){this.log(1,A,B)}warn(A,B){this.log(2,A,B)}error(A,B){this.log(3,A,B)}log(A,B,g){if(A<eB)return;const I={timestamp:new Date,level:A,context:this.context,message:B,data:g};if(jI){jI(I);return}const E=this.formatMessage(I);switch(A){case 0:g!==void 0?console.debug(E,g):console.debug(E);break;case 1:g!==void 0?console.info(E,g):console.info(E);break;case 2:g!==void 0?console.warn(E,g):console.warn(E);break;case 3:g!==void 0?console.error(E,g):console.error(E);break}}formatMessage(A){const B=[];return jE&&B.push(this.formatTimestamp(A.timestamp)),B.push(`[${nD[A.level]}]`),OE&&A.context&&B.push(`[${A.context}]`),B.push(A.message),B.join(" ")}formatTimestamp(A){const B=A.getHours().toString().padStart(2,"0"),g=A.getMinutes().toString().padStart(2,"0"),I=A.getSeconds().toString().padStart(2,"0"),E=A.getMilliseconds().toString().padStart(3,"0");return`${B}:${g}:${I}.${E}`}}function hD(Q){return SA.for(Q)}class IA{static extractAudioUrl(A){const B=["mp3_url","lossy_audio","audio_url","lossless_audio","animation_url","audio","multimedia_url","losslessAudio"];for(const g of B)if(A[g]&&typeof A[g]=="string")return A[g];return null}static extractAudioUrlLossless(A){const B=["audio_url","lossless_audio","wav_url","flac_url","losslessAudio"];for(const g of B)if(A[g]&&typeof A[g]=="string")return A[g];return null}static extractImageUrl(A){const B=["image_small","image","image_large","image_thumb","image_url","image_uri","image_preview"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];const g=[this.extractNestedUri(A,"artwork","uri"),this.extractNestedUri(A,"project","artwork","uri"),this.extractNestedUri(A,"primaryMedia","uri")];for(const I of g)if(I)return I;return null}static extractImageThumbUrl(A){return A.image_thumb_url&&typeof A.image_thumb_url=="string"?A.image_thumb_url:A.image_thumb&&typeof A.image_thumb=="string"?A.image_thumb:null}static extractTitle(A){return A.name&&typeof A.name=="string"?A.name:A.title&&typeof A.title=="string"?A.title:null}static extractArtist(A){const B=["artist","created_by","minter"];for(const g of B)if(A[g]&&typeof A[g]=="string")return A[g];return null}static parseMetadata(A){if(!A)return null;if(typeof A=="object"&&!Array.isArray(A))return A;if(typeof A=="string")try{const B=JSON.parse(A);if(typeof B=="object"&&!Array.isArray(B))return B}catch(B){return console.warn("Failed to parse metadata:",B),null}return null}static extractGenre(A){if(typeof A.genre=="string")return A.genre;if(Array.isArray(A.genre)&&A.genre.length>0){const B=A.genre[0];return typeof B=="string"?B:""}if(Array.isArray(A.attributes)){const B=A.attributes.find(g=>g.trait_type?.toLowerCase()==="genre"&&g.value!==void 0);if(B){if(typeof B.value=="string")return B.value;if(Array.isArray(B.value)&&B.value.length>0){const g=B.value[0];return typeof g=="string"?g:""}}}return""}static convertAttributes(A){if(!Array.isArray(A))return null;const B={};for(const g of A)g.trait_type&&g.value!==void 0&&(B[g.trait_type]=g.value);return Object.keys(B).length>0?B:null}static extractNestedUri(A,...B){let g=A;for(const I of B)if(g&&typeof g=="object"&&!Array.isArray(g))g=g[I];else return null;return typeof g=="string"?g:null}}function PE(Q){if("audio_url"in Q&&typeof Q.audio_url=="string")return Q.audio_url;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractAudioUrl(A)}return null}function cD(Q){if("audio_url_lossless"in Q&&typeof Q.audio_url_lossless=="string")return Q.audio_url_lossless;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractAudioUrlLossless(A)}return null}function _E(Q){if("image_url"in Q&&typeof Q.image_url=="string")return Q.image_url;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractImageUrl(A)}return null}function oo(Q){if("image_thumb_url"in Q&&typeof Q.image_thumb_url=="string")return Q.image_thumb_url;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractImageThumbUrl(A)}return null}function to(Q){if("audio_url"in Q)return null;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A&&typeof A.vrm=="string"&&A.vrm)return A.vrm}return null}function rD(Q){const A=[];for(const B of Q.tracks){const g=PE(B);g&&A.push(g)}return A}function lD(Q){const A=[];for(const B of Q.tracks){const g=_E(B);g&&A.push(g)}return A}function DD(Q){const A=[];for(const B of Q.tracks){if("title"in B&&typeof B.title=="string"){A.push(B.title);continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g){const I=IA.extractTitle(g);I&&A.push(I)}}}return A}function dD(Q){const A=[];for(const B of Q.tracks){if("artist"in B&&typeof B.artist=="string"){A.push(B.artist);continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g){const I=IA.extractArtist(g);I&&A.push(I)}}}return A}function FD(Q){const A=new Set;for(const B of Q.tracks){if("genre"in B&&typeof B.genre=="string"&&B.genre){A.add(B.genre);continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);g&&typeof g.genre=="string"&&g.genre&&A.add(g.genre)}}return Array.from(A).sort()}function MD(Q){const A=new Set;for(const B of Q.tracks){if("tags"in B&&Array.isArray(B.tags)){for(const g of B.tags)g&&A.add(g.toLowerCase());continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g&&Array.isArray(g.tags))for(const I of g.tags)I&&A.add(String(I).toLowerCase())}}return Array.from(A).sort()}function wD(Q){let A=0;for(const B of Q.tracks){if("duration"in B&&typeof B.duration=="number"){A+=B.duration;continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);g&&typeof g.duration=="number"&&(A+=g.duration)}}return A}function yD(Q){return Q.tracks.length}function RD(Q){const A=[];for(const B of Q.tracks){const g=PE(B),I=_E(B),E=oo(B);let i="",C="";if("title"in B)i=B.title||"",C=B.artist||"";else if("metadata"in B){const a=IA.parseMetadata(B.metadata);a&&(i=IA.extractTitle(a)||"",C=IA.extractArtist(a)||"")}if(g){const a={title:i,artist:C,audio_url:g,image_url:I||""},e=cD(B);e&&e!==g&&(a.audio_url_lossless=e),E&&(a.image_thumb_url=E),"audioIpfsHash"in B&&typeof B.audioIpfsHash=="string"&&(a.audioIpfsHash=B.audioIpfsHash),"artworkIpfsHash"in B&&typeof B.artworkIpfsHash=="string"&&(a.artworkIpfsHash=B.artworkIpfsHash),A.push(a)}}return A}function mD(Q){const A=[];for(const B of Q.tracks){if("audio_url"in B){A.push({...B});continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g){const I=IA.extractAudioUrlLossless(g),E=IA.extractAudioUrl(g);A.push({id:B.chain_name==="AR"?`AR-${B.tx_id}`:`${B.chain_name}-${B.token_address}-${B.token_id}`,chain_name:B.chain_name,token_address:B.token_address,token_id:B.token_id,tx_id:B.tx_id,platform:B.platform,title:IA.extractTitle(g),artist:IA.extractArtist(g),audio_url:E,image_url:IA.extractImageUrl(g),image_thumb_url:IA.extractImageThumbUrl(g),duration:g.duration,genre:g.genre,tags:g.tags,bpm:g.bpm,key:g.key,album:g.album,description:g.description,attributes:IA.convertAttributes(g.attributes),...I&&I!==E?{audio_url_lossless:I}:{},...B.audioUrl?{audioUrl:B.audioUrl}:{},...B.artworkUrl?{artworkUrl:B.artworkUrl}:{},...B.audioIpfsHash?{audioIpfsHash:B.audioIpfsHash}:{},...B.artworkIpfsHash?{artworkIpfsHash:B.artworkIpfsHash}:{},...B["Mint-Function"]?{"Mint-Function":B["Mint-Function"]}:{},...B["Mint-Price"]?{"Mint-Price":B["Mint-Price"]}:{},...B["Mint-Snapshot-Time"]!=null?{"Mint-Snapshot-Time":B["Mint-Snapshot-Time"]}:{},...B["Mint-Token"]?{"Mint-Token":B["Mint-Token"]}:{}})}}}return A}function uD(Q){const A=[];for(const B of Q.tracks){const g=to(B);g&&A.push(g)}return A}function SD(Q){const A=[];for(const B of Q.tracks){const g=to(B);if(!g)continue;const I=PE(B),E=_E(B),i=oo(B);let C="",a="";if("title"in B)C=B.title||"",a=B.artist||"";else if("metadata"in B){const o=IA.parseMetadata(B.metadata);o&&(C=IA.extractTitle(o)||"",a=IA.extractArtist(o)||"")}const e={title:C,artist:a,audio_url:I||"",image_url:E||"",vrm:g};i&&(e.image_thumb_url=i),A.push(e)}return A}const $E=[{host:"arweave.net",protocol:"https",priority:3},{host:"ardrive.net",protocol:"https",priority:2},{host:"turbo-gateway.com",protocol:"https",priority:1}],Ai=["arweave.net","arweave.dev","www.arweave.net","ardrive.net","turbo-gateway.com","irys.xyz","ar-io.dev","ar-io.net","arweave.rocks","g8way.io"];function hg(Q){if(!Q||typeof Q!="string")return!1;if(Q.startsWith("ar://"))return!0;const A=Q.toLowerCase();try{const B=new URL(Q).hostname;return Ai.some(g=>B===g||B.endsWith("."+g))}catch{return Ai.some(B=>A.includes(B))}}function cg(Q){if(!Q||typeof Q!="string"||!hg(Q))return null;let A=null,B="";if(Q.startsWith("ar://")){const i=Q.slice(5),C=i.indexOf("/");return C!==-1?(A=i.slice(0,C),B=i.slice(C)):A=i,A.length===43&&/^[A-Za-z0-9_-]+$/.test(A)?{txId:A,originalUrl:Q,pathSuffix:B}:null}let g=Q;try{const i=new URL(Q);g=i.pathname+i.search}catch{}const I=/[A-Za-z0-9_-]{43}/g,E=g.match(I);if(E&&E.length>0){A=E[0];const i=Q.indexOf(A);if(i!==-1){const C=Q.slice(i+43),a=Math.min(C.indexOf("?")===-1?1/0:C.indexOf("?"),C.indexOf("#")===-1?1/0:C.indexOf("#"));a===1/0?B=C:B=C.slice(0,a)}return{txId:A,originalUrl:Q,pathSuffix:B}}return null}function oB(Q,A,B=""){return`${A.protocol||"https"}://${A.host}/${Q}${B}`}function bD(Q,A=$E,B=""){return A.sort((g,I)=>g.priority-I.priority).map(g=>oB(Q,g,B))}async function pD(){try{return await import("@ar.io/wayfinder-core")}catch{return null}}async function YD(){try{return await import("@ar.io/sdk")}catch{return null}}const UD=5e3,kD=864e5,Bi="arweave_active_gateway";class so{constructor(A){this.cache=new Map,this.logger=SA.for("ArweaveGateway"),this.hitCount=0,this.missCount=0,this.healthData=new Map,this.originalPriorities=new Map,this.MAX_HEALTH_RECORDS=50,this.inflightResolves=new Map,this.inflightControllers=new Map,this.wayfinder=null,this.activeGateway=null,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.gateways=(A?.gateways??$E).map(B=>({...B})),this.timeout=A?.timeout??UD,this.cacheTTL=A?.cacheTTL??kD,this.slowResponseThreshold=A?.slowResponseThreshold??8e3,this.maxSlowResponses=A?.maxSlowResponses??3,this.gateways.sort((B,g)=>B.priority-g.priority),this.gateways.forEach(B=>{this.originalPriorities.set(B.host,B.priority)}),this.activeGateway=this.loadPersistedGateway(),Promise.all([pD(),YD()]).then(([B,g])=>{if(B&&g)try{const{FastestPingRoutingStrategy:I,RandomRoutingStrategy:E,CompositeRoutingStrategy:i,NetworkGatewaysProvider:C}=B,a=g.ARIO,e=new C({ario:a.mainnet(),sortBy:"operatorStake",limit:10}),o=new C({ario:a.mainnet(),sortBy:"operatorStake",limit:20});this.wayfinder=B.createWayfinderClient({routingStrategy:new i({strategies:[new I({timeoutMs:3e3,gatewaysProvider:e}),new E({gatewaysProvider:o})]})}),this.logger.info("Wayfinder client initialized with FastestPing + Random fallback routing")}catch(I){this.logger.warn("Failed to configure Wayfinder routing strategy, using defaults",{error:I}),this.wayfinder=B.createWayfinderClient(),this.logger.info("Wayfinder client initialized with default routing")}else B&&(this.wayfinder=B.createWayfinderClient(),this.logger.info("Wayfinder client initialized with default routing (SDK unavailable)"))}).catch(()=>{this.logger.debug("Wayfinder client initialization failed, using static gateways")}),this.logger.info("Gateway manager initialized",{gateways:this.gateways.map(B=>B.host),timeout:this.timeout,cacheTTL:this.cacheTTL,activeGateway:this.activeGateway?.host??null})}withTimeout(A,B,g){return new Promise((I,E)=>{const i=setTimeout(()=>E(new Error(g)),B);A.then(C=>{clearTimeout(i),I(C)},C=>{clearTimeout(i),E(C)})})}resolveUrlSimple(A){if(!hg(A))return A;const B=cg(A);if(!B)return A;const g=this.activeGateway??this.gateways[0];return this.logger.debug("[gateway] resolveUrlSimple",{txId:B.txId,gateway:g.host,pathSuffix:B.pathSuffix||void 0}),oB(B.txId,g,B.pathSuffix)}setPreferredGateway(A){const B=this.gateways.find(g=>g.host===A);return B?(this.activeGateway=B,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.persistGateway(B),this.logger.info("Preferred gateway set",{host:A}),!0):(this.logger.warn("Cannot set preferred gateway — not in gateway list",{host:A,available:this.gateways.map(g=>g.host)}),!1)}clearPreferredGateway(){this.activeGateway=null,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.clearPersistedGateway(),this.cache.clear(),this.logger.info("Preferred gateway cleared, will re-discover on next resolve")}getDiagnostics(){const A=this.gateways.map(B=>{const g=this.healthData.get(B.host)??[],I=g.length,E=I>0?Math.round(g.reduce((C,a)=>C+a.responseTime,0)/I):0,i=I>0?g.filter(C=>C.success).length/I:1;return{host:B.host,avgMs:E,successRate:Math.round(i*100)/100,checks:I}});return{activeGateway:this.activeGateway?.host??null,activeGatewayAge:null,availableGateways:this.gateways.map(B=>B.host),lastFetchTiming:this.lastFetchTiming,consecutiveSlowResponses:this.consecutiveSlowResponses,healthSummary:A}}async resolveUrl(A,B){const g=B?.signal;if(g?.aborted)return this.logger.debug("resolveUrl called with already-aborted signal, returning original URL"),A;if(!hg(A))return A;const I=cg(A);if(!I)return this.logger.warn("Failed to parse Arweave URL, returning original",{url:A}),A;const{txId:E,pathSuffix:i}=I,C=this.getCachedGateway(E);if(C){this.hitCount++;const s=oB(E,C,i);return this.logger.debug("Cache hit for txId",{txId:E,gateway:C.host,pathSuffix:i}),s}const a=this.activeGateway?.host??"none";this.consecutiveSlowResponses>=this.maxSlowResponses&&(this.logger.warn("Proactive gateway rotation triggered",{slowCount:this.consecutiveSlowResponses,threshold:this.maxSlowResponses,previousGateway:a}),this.activeGateway=null,this.consecutiveSlowResponses=0,this.clearPersistedGateway(),this.cache.clear());const e=this.inflightResolves.get(E);if(e)return this.logger.debug("Reusing in-flight resolve for txId",{txId:E}),e;const o=new AbortController;g&&g.addEventListener("abort",()=>o.abort(),{once:!0});const t=this.resolveGatewayChain(A,E,i,o.signal,B).finally(()=>{this.inflightResolves.delete(E),this.inflightControllers.delete(E)});return this.inflightResolves.set(E,t),this.inflightControllers.set(E,o),t}async resolveGatewayChain(A,B,g,I,E){const i=Date.now(),C=E?.bypassArweaveNet??!1;let a=null;if(A.startsWith("https://")||A.startsWith("http://"))try{const s=new URL(A),G={host:s.host,protocol:s.protocol.replace(":",""),priority:0},n=Date.now(),h=await this.checkAndSetGateway(A,B,g,G,I),c=Date.now()-n;if(h)return this.logger.info("[gateway] Step 0 (original): success",{host:G.host,ms:c,totalMs:Date.now()-i}),h;this.logger.info("[gateway] Step 0 (original): failed",{host:G.host,ms:c}),a=G.host}catch{}if(this.activeGateway&&this.activeGateway.host!==a){const s=Date.now(),G=await this.checkAndSetGateway(A,B,g,this.activeGateway,I),n=Date.now()-s;if(G)return this.logger.info("[gateway] Step 1 (persisted): success",{host:this.activeGateway.host,ms:n,totalMs:Date.now()-i}),G;this.logger.info("[gateway] Step 1 (persisted): failed, clearing",{ms:n}),this.activeGateway=null,this.clearPersistedGateway()}if(!C&&a!=="arweave.net"){const s=this.gateways.find(G=>G.host==="arweave.net");if(s){const G=Date.now(),n=await this.checkAndSetGateway(A,B,g,s,I),h=Date.now()-G;if(n)return this.logger.info("[gateway] Step 2 (arweave.net): success",{ms:h,totalMs:Date.now()-i}),n;this.logger.info("[gateway] Step 2 (arweave.net): failed",{ms:h})}}const e=Date.now(),o=await this.tryFallbackGateways(A,B,g,I,a),t=Date.now()-e;if(o)return this.logger.info("[gateway] Step 3 (fallbacks): success",{ms:t,totalMs:Date.now()-i}),o;if(this.logger.info("[gateway] Step 3 (fallbacks): failed",{ms:t}),this.wayfinder){const s=Date.now();this.logger.info("[gateway] Step 4 (wayfinder): trying");const G=await this.tryWayfinder(A,B,g,I,a),n=Date.now()-s;if(G)return this.logger.info("[gateway] Step 4 (wayfinder): success",{ms:n,totalMs:Date.now()-i}),G;this.logger.info("[gateway] Step 4 (wayfinder): failed",{ms:n})}return this.logger.warn("All gateways (arweave.net + Wayfinder + fallbacks) failed, returning original URL",{txId:B,pathSuffix:g,originalUrl:A}),A}async reportGatewayFailure(A,B){const{signal:g,reason:I,excludeHost:E}=B??{};if(g?.aborted)return this.logger.debug("reportGatewayFailure called with already-aborted signal, returning original URL"),A;if(I==="user-cancel-fast")return this.logger.debug("User cancelled quickly, keeping current gateway"),A;const i=cg(A);if(!i)return A;const{txId:C,pathSuffix:a}=i;this.logger.warn("Gateway failure reported, finding new gateway",{failedHost:this.activeGateway?.host,txId:C,reason:I??"load-error"});const e=this.activeGateway?.host??E;this.activeGateway=null,this.cache.delete(C),this.clearPersistedGateway();const o=this.gateways.find(G=>G.host==="arweave.net"&&G.host!==e);if(o){const G=await this.checkAndSetGateway(A,C,a,o,g);if(G)return G}if(this.wayfinder){const G=await this.tryWayfinder(A,C,a,g);if(G)return G}const t=this.gateways;e&&(this.gateways=this.gateways.filter(G=>G.host!==e));const s=await this.tryFallbackGateways(A,C,a,g);return this.gateways=t,s||A}reportFetchSuccess(A){this.lastFetchTiming=A,A>=this.slowResponseThreshold?(this.consecutiveSlowResponses++,this.logger.warn("Slow fetch response recorded",{timingMs:A,threshold:this.slowResponseThreshold,consecutiveSlow:this.consecutiveSlowResponses,maxAllowed:this.maxSlowResponses,gateway:this.activeGateway?.host??"none"})):(this.consecutiveSlowResponses>0&&this.logger.info("Fetch timing recovered, resetting slow counter",{timingMs:A,previousSlowCount:this.consecutiveSlowResponses}),this.consecutiveSlowResponses=0)}async checkAndSetGateway(A,B,g,I,E){if(E?.aborted)return null;const i=await this.checkGateway(B,I,g,E);if(i===!0){this.setActiveGateway(I,B);const C=oB(B,I,g);return this.logger.info("Gateway resolved",{txId:B,gateway:I.host,pathSuffix:g,workingUrl:C}),C}if(i==="maybe"){const C=oB(B,I,g);return this.logger.info("Gateway maybe resolved (no-cors)",{txId:B,gateway:I.host,pathSuffix:g,workingUrl:C}),C}return null}async tryFallbackGateways(A,B,g,I,E){this.missCount++;const i=.7,C=3,a=this.gateways.filter(G=>G.host!=="arweave.net"&&G.host!==E),e=a.filter(G=>{const{rate:n,totalChecks:h}=this.getFailureRate(G.host);return!(h>=C&&n>i)}),o=e.length>0?e:a;if(I?.aborted||o.length===0)return null;const t=async G=>{if(I?.aborted||G.length===0)return null;const n=new AbortController,h=()=>n.abort();I?.addEventListener("abort",h,{once:!0});let c=!1;try{return await Promise.any(G.map(async l=>{const F=await this.checkGateway(B,l,g,n.signal);if(F){const m=oB(B,l,g);return c||(c=!0,F===!0?(this.setActiveGateway(l,B),this.logger.info("Gateway resolved via fallback",{txId:B,gateway:l.host,pathSuffix:g,workingUrl:m})):this.logger.info("Gateway maybe resolved via fallback (no-cors)",{txId:B,gateway:l.host,pathSuffix:g,workingUrl:m})),m}throw new Error(`Gateway ${l.host} failed check`)}))}catch{return null}finally{I?.removeEventListener("abort",h)}},s=await t(o);if(s)return s;if(e.length<a.length&&!I?.aborted){const G=a.filter(h=>!e.some(c=>c.host===h.host)).map(h=>h.host);this.logger.debug("Healthy gateways exhausted, retrying with previously unhealthy",{excludedHosts:G});const n=await t(a);if(n)return n}return null}async tryWayfinder(A,B,g,I,E){if(!this.wayfinder)return null;const i=3;for(let C=1;C<=i;C++){if(I?.aborted)return null;try{this.logger.debug(`Resolving via Wayfinder (attempt ${C}/${i})`,{txId:B});const a=await this.withTimeout(this.wayfinder.resolveUrl({originalUrl:A}),this.timeout+2e3,"Wayfinder resolution timed out");if(I?.aborted)return null;const e=a.hostname;if(E&&e===E){this.logger.debug(`Wayfinder resolved to already-failed host ${e}, retrying`,{attempt:C});continue}const o=a.protocol.replace(":",""),t={host:e,protocol:o,priority:0},s=await this.checkGateway(B,t,g,I);if(s){const G=oB(B,t,g);return s===!0?(this.setActiveGateway(t,B),this.logger.info("Gateway resolved via Wayfinder",{txId:B,gateway:e,attempt:C,pathSuffix:g,workingUrl:G})):this.logger.info("Gateway maybe resolved via Wayfinder (no-cors)",{txId:B,gateway:e,attempt:C,pathSuffix:g,workingUrl:G}),G}this.logger.debug(`Wayfinder attempt ${C} gateway did not pass check`,{host:e})}catch(a){this.logger.debug(`Wayfinder attempt ${C} failed`,{error:a})}}return null}setActiveGateway(A,B){this.activeGateway=A,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.setCache(B,A),this.persistGateway(A)}loadPersistedGateway(){try{if(typeof localStorage>"u")return null;const A=localStorage.getItem(Bi);if(!A)return null;const B=JSON.parse(A);if(B&&typeof B.host=="string"&&typeof B.protocol=="string"){if(typeof B.timestamp=="number"&&Date.now()-B.timestamp>72e5)return this.logger.info("Ignoring persisted gateway — expired (older than 2 hours)",{host:B.host}),this.clearPersistedGateway(),null;this.logger.info("Restored active gateway from localStorage",{host:B.host});const{timestamp:I,...E}=B;return E}}catch{}return null}persistGateway(A){try{if(typeof localStorage>"u")return;const B={...A,timestamp:Date.now()};localStorage.setItem(Bi,JSON.stringify(B))}catch{}}clearPersistedGateway(){try{if(typeof localStorage>"u")return;localStorage.removeItem(Bi)}catch{}}async checkGateway(A,B,g="",I){const E=oB(A,B,g),i=Date.now(),C=new AbortController,a=setTimeout(()=>C.abort(),this.timeout),e=()=>C.abort();I?.addEventListener("abort",e,{once:!0});try{const o=await fetch(E,{method:"HEAD",mode:"cors",signal:C.signal});clearTimeout(a),I?.removeEventListener("abort",e);const t=Date.now()-i,s=o.ok||o.status>=200&&o.status<400;return this.recordGatewayResponse(B.host,t,s),s}catch(o){clearTimeout(a),I?.removeEventListener("abort",e);const t=Date.now()-i;if(this.recordGatewayResponse(B.host,t,!1),o instanceof Error&&o.name==="AbortError"){const s=I?.aborted;return this.logger.debug(s?"Gateway check aborted by external signal":"Gateway check timed out",{txId:A,gateway:B.host,timeout:this.timeout}),!1}if(o instanceof TypeError){this.logger.debug("HEAD failed (likely CORS), retrying with no-cors",{txId:A,gateway:B.host,error:o.message});try{await fetch(E,{method:"GET",mode:"no-cors",signal:C.signal});const s=Date.now()-i;return this.recordGatewayResponse(B.host,s,!0),"maybe"}catch{const s=Date.now()-i;return this.recordGatewayResponse(B.host,s,!1),!1}}return this.logger.debug("Gateway HEAD failed",{txId:A,gateway:B.host,error:o instanceof Error?o.message:String(o)}),!1}}getCachedGateway(A){const B=this.cache.get(A);return B?this.isCacheValid(B)?B.workingGateway:(this.cache.delete(A),null):null}setCache(A,B){const g={txId:A,workingGateway:B,timestamp:Date.now(),ttl:this.cacheTTL};this.cache.set(A,g),this.logger.debug("Cached working gateway",{txId:A,gateway:B.host})}clearCache(){const A=this.cache.size;this.cache.clear(),this.hitCount=0,this.missCount=0,this.logger.info("Cache cleared",{entriesRemoved:A})}invalidateCacheForUrl(A){if(!hg(A))return;const B=cg(A);B&&(this.cache.delete(B.txId),this.activeGateway=null,this.clearPersistedGateway())}async prefetchUrls(A,B){const g=B?.concurrency??5,I=B?.continueOnError??!0,E=[];let i=0,C=0,a=0;for(let e=0;e<A.length;e+=g){const o=A.slice(e,e+g),t=await Promise.allSettled(o.map(async s=>{if(!hg(s))return{url:s,txId:"",success:!1,error:"Not an Arweave URL"};const G=cg(s);if(!G)return{url:s,txId:"",success:!1,error:"Failed to parse Arweave URL"};const n=this.getCachedGateway(G.txId);if(n)return{url:s,txId:G.txId,success:!0,gateway:n};await this.resolveUrl(s);const h=this.getCachedGateway(G.txId);return h?{url:s,txId:G.txId,success:!0,gateway:h}:{url:s,txId:G.txId,success:!1,error:"All gateways failed"}}));for(const s of t)if(s.status==="fulfilled"){const G=s.value;E.push(G),G.error==="Not an Arweave URL"?a++:G.success?i++:C++}else C++,E.push({url:"unknown",txId:"",success:!1,error:s.reason?.message??"Unknown error"});if(!I&&C>0){this.logger.warn("Prefetch stopped due to failures",{failed:C,processed:E.length});break}}return this.logger.info("Prefetch complete",{total:A.length,succeeded:i,failed:C,skipped:a}),{total:A.length,succeeded:i,failed:C,skipped:a,entries:E}}getCacheStats(){const A=Array.from(this.cache.entries()),B=Date.now(),g=A.filter(([,I])=>B-I.timestamp<I.ttl).map(([I])=>I);return{size:g.length,txIds:g,hitCount:this.hitCount,missCount:this.missCount,ttl:this.cacheTTL}}getCacheEntries(){return Array.from(this.cache.values())}isCacheValid(A){return Date.now()-A.timestamp<A.ttl}getFailureRate(A){const B=this.healthData.get(A);return!B||B.length===0?{rate:0,totalChecks:0}:{rate:B.filter(I=>!I.success).length/B.length,totalChecks:B.length}}getAverageResponseTime(A){const B=this.healthData.get(A);return!B||B.length===0?0:B.reduce((g,I)=>g+I.responseTime,0)/B.length}recordGatewayResponse(A,B,g){this.healthData.has(A)||this.healthData.set(A,[]);const I=this.healthData.get(A);I.push({responseTime:B,success:g,timestamp:Date.now()}),I.length>this.MAX_HEALTH_RECORDS&&I.shift()}reportFetchTiming(A,B,g){this.recordGatewayResponse(A,B,g),this.logger.debug("Fetch timing reported",{host:A,timingMs:B,success:g})}getGatewayHealth(A){const B=this.gateways.find(s=>s.host===A);if(!B)return;const g=this.healthData.get(A)||[],I=this.originalPriorities.get(A)??B.priority;if(g.length===0)return{host:A,priority:B.priority,originalPriority:I,successCount:0,failureCount:0,totalChecks:0,successRate:0,averageResponseTime:0,lastSuccess:null,lastFailure:null,isHealthy:!0};const E=g.filter(s=>s.success).length,i=g.filter(s=>!s.success).length,C=E/g.length,a=Math.round(g.reduce((s,G)=>s+G.responseTime,0)/g.length),e=g.filter(s=>s.success).pop()?.timestamp??null,o=g.filter(s=>!s.success).pop()?.timestamp??null,t=C>=.5;return{host:A,priority:B.priority,originalPriority:I,successCount:E,failureCount:i,totalChecks:g.length,successRate:C,averageResponseTime:a,lastSuccess:e,lastFailure:o,isHealthy:t}}getAllGatewayHealth(){return this.gateways.map(A=>this.getGatewayHealth(A.host))}adjustGatewayPriorities(A){const B=A?.minChecks??3,g=A?.healthyThreshold??.5,E=this.getAllGatewayHealth().reduce((e,o)=>e+o.totalChecks,0);if(E<B)return this.logger.debug("Not enough health data to adjust priorities",{totalChecks:E,required:B}),[...this.gateways];const i=this.gateways.map((e,o)=>({gateway:e,originalIndex:o}));i.sort((e,o)=>{const t=this.getGatewayHealth(e.gateway.host),s=this.getGatewayHealth(o.gateway.host),G=t.successRate>=g||t.totalChecks===0,n=s.successRate>=g||s.totalChecks===0;if(G&&!n)return-1;if(!G&&n)return 1;if(t.totalChecks>0&&s.totalChecks>0){const h=t.averageResponseTime-s.averageResponseTime;if(Math.abs(h)>100)return h}if(t.totalChecks>0&&s.totalChecks>0){const h=s.successRate-t.successRate;if(Math.abs(h)>.1)return h}return e.originalIndex-o.originalIndex});const C=i.map(e=>e.gateway),a=Math.min(...Array.from(this.originalPriorities.values()));return C.forEach((e,o)=>{e.priority=a+o}),this.gateways=C,this.logger.info("Gateway priorities adjusted",{newOrder:this.gateways.map(e=>({host:e.host,priority:e.priority,health:this.getGatewayHealth(e.host)}))}),[...this.gateways]}async runHealthCheck(A){const B=Date.now(),g=A?.txId??"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk012345",I=A?.healthyThreshold??.5;A?.fastThreshold,this.logger.info("Starting gateway health check",{txId:g,gateways:this.gateways.map(n=>n.host)});const E=this.gateways.map(async n=>{const h=Date.now();let c=!1,d=this.timeout;try{const l=oB(g,n),F=new AbortController,m=setTimeout(()=>F.abort(),this.timeout),y=await fetch(l,{method:"HEAD",mode:"cors",signal:F.signal});clearTimeout(m),d=Date.now()-h,c=y.ok||y.status>=200&&y.status<400}catch{d=Date.now()-h,c=!1}return this.recordGatewayResponse(n.host,d,c),{host:n.host,success:c,responseTime:d}}),i=await Promise.all(E),C=this.getAllGatewayHealth(),a=[],e=[];let o=null,t=1/0;for(const n of i){const h=C.find(c=>c.host===n.host);n.success&&n.responseTime<t&&(t=n.responseTime,o=n.host),(h.successRate>=I||h.totalChecks===1)&&n.success?a.push(n.host):e.push(n.host)}const s=Date.now()-B;A?.adjustPriorities&&this.adjustGatewayPriorities({minChecks:A.minChecksForAdjustment??1,healthyThreshold:I});const G={timestamp:B,gateways:C,healthyGateways:a,unhealthyGateways:e,fastestGateway:o,totalTime:s};return this.logger.info("Health check complete",{healthyGateways:a,unhealthyGateways:e,fastestGateway:o,totalTime:s}),G}resetGatewayPriorities(){this.gateways.forEach(A=>{const B=this.originalPriorities.get(A.host);B!==void 0&&(A.priority=B)}),this.gateways.sort((A,B)=>{const g=this.originalPriorities.get(A.host)??A.priority,I=this.originalPriorities.get(B.host)??B.priority;return g-I}),this.logger.info("Gateway priorities reset to original values",{gateways:this.gateways.map(A=>({host:A.host,priority:A.priority}))})}clearHealthData(){this.healthData.clear(),this.logger.info("Health data cleared")}}const kA=new so,PI=["ipfs.io","cloudflare-ipfs.com","dweb.link","gateway.pinata.cloud","ipfs.infura.io","nftstorage.link","web3-music-pipeline.mypinata.cloud","soundxyz.mypinata.cloud","gold-broad-gibbon-29.mypinata.cloud","bonfire.mypinata.cloud","spinamp.mypinata.cloud","catalogworks.b-cdn.net","www.heds.cloud"],Go="ipfs.io",gi="/ipfs/";function no(Q){if(!Q||typeof Q!="string")return null;if(Q.startsWith("ipfs://ipfs/"))return Q.slice(12);if(Q.startsWith("ipfs://"))return Q.slice(7);try{const A=new URL(Q),{hostname:B,pathname:g}=A,I=B.match(/^([A-Za-z0-9]+)\.ipfs\.dweb\.link$/);if(I)return`${I[1]}${g}`;if(PI.some(i=>B===i||B.endsWith("."+i))&&g.startsWith(gi))return g.slice(gi.length)}catch{}return null}function ZD(Q){if(!Q||typeof Q!="string")return!1;if(Q.startsWith("ipfs://"))return!0;try{const A=new URL(Q),{hostname:B,pathname:g}=A;if(/^[A-Za-z0-9]+\.ipfs\.dweb\.link$/.test(B)||PI.some(E=>B===E||B.endsWith("."+E))&&g.startsWith(gi))return!0}catch{}return!1}function WD(Q){if(!(!Q||Q.startsWith("ipfs://")))try{const{hostname:A}=new URL(Q);return PI.some(g=>A===g||A.endsWith("."+g))?A:void 0}catch{return}}function HD(Q,A={}){if(!Q)return Q;const B=typeof A=="string"?{gatewayHost:A}:A,{gatewayHost:g=Go,preserveOriginalGateway:I=!1}=B,E=no(Q);if(E){if(I){const i=WD(Q);if(i)return`https://${i}/ipfs/${E}`}return`https://${g}/ipfs/${E}`}return Q}function _I(Q){throw new Error('Could not dynamically require "'+Q+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Ii={exports:{}};var ho;function fD(){return ho||(ho=1,(function(Q,A){(function(B){Q.exports=B()})(function(){return(function B(g,I,E){function i(e,o){if(!I[e]){if(!g[e]){var t=typeof _I=="function"&&_I;if(!o&&t)return t(e,!0);if(C)return C(e,!0);var s=new Error("Cannot find module '"+e+"'");throw s.code="MODULE_NOT_FOUND",s}var G=I[e]={exports:{}};g[e][0].call(G.exports,function(n){var h=g[e][1][n];return i(h||n)},G,G.exports,B,g,I,E)}return I[e].exports}for(var C=typeof _I=="function"&&_I,a=0;a<E.length;a++)i(E[a]);return i})({1:[function(B,g,I){(function(E){var i=E.MutationObserver||E.WebKitMutationObserver,C;if(i){var a=0,e=new i(n),o=E.document.createTextNode("");e.observe(o,{characterData:!0}),C=function(){o.data=a=++a%2}}else if(!E.setImmediate&&typeof E.MessageChannel<"u"){var t=new E.MessageChannel;t.port1.onmessage=n,C=function(){t.port2.postMessage(0)}}else"document"in E&&"onreadystatechange"in E.document.createElement("script")?C=function(){var c=E.document.createElement("script");c.onreadystatechange=function(){n(),c.onreadystatechange=null,c.parentNode.removeChild(c),c=null},E.document.documentElement.appendChild(c)}:C=function(){setTimeout(n,0)};var s,G=[];function n(){s=!0;for(var c,d,l=G.length;l;){for(d=G,G=[],c=-1;++c<l;)d[c]();l=G.length}s=!1}g.exports=h;function h(c){G.push(c)===1&&!s&&C()}}).call(this,typeof dI<"u"?dI:typeof self<"u"?self:typeof window<"u"?window:{})},{}],2:[function(B,g,I){var E=B(1);function i(){}var C={},a=["REJECTED"],e=["FULFILLED"],o=["PENDING"];g.exports=t;function t(y){if(typeof y!="function")throw new TypeError("resolver must be a function");this.state=o,this.queue=[],this.outcome=void 0,y!==i&&h(this,y)}t.prototype.catch=function(y){return this.then(null,y)},t.prototype.then=function(y,p){if(typeof y!="function"&&this.state===e||typeof p!="function"&&this.state===a)return this;var k=new this.constructor(i);if(this.state!==o){var H=this.state===e?y:p;G(k,H,this.outcome)}else this.queue.push(new s(k,y,p));return k};function s(y,p,k){this.promise=y,typeof p=="function"&&(this.onFulfilled=p,this.callFulfilled=this.otherCallFulfilled),typeof k=="function"&&(this.onRejected=k,this.callRejected=this.otherCallRejected)}s.prototype.callFulfilled=function(y){C.resolve(this.promise,y)},s.prototype.otherCallFulfilled=function(y){G(this.promise,this.onFulfilled,y)},s.prototype.callRejected=function(y){C.reject(this.promise,y)},s.prototype.otherCallRejected=function(y){G(this.promise,this.onRejected,y)};function G(y,p,k){E(function(){var H;try{H=p(k)}catch(T){return C.reject(y,T)}H===y?C.reject(y,new TypeError("Cannot resolve promise with itself")):C.resolve(y,H)})}C.resolve=function(y,p){var k=c(n,p);if(k.status==="error")return C.reject(y,k.value);var H=k.value;if(H)h(y,H);else{y.state=e,y.outcome=p;for(var T=-1,q=y.queue.length;++T<q;)y.queue[T].callFulfilled(p)}return y},C.reject=function(y,p){y.state=a,y.outcome=p;for(var k=-1,H=y.queue.length;++k<H;)y.queue[k].callRejected(p);return y};function n(y){var p=y&&y.then;if(y&&(typeof y=="object"||typeof y=="function")&&typeof p=="function")return function(){p.apply(y,arguments)}}function h(y,p){var k=!1;function H(EA){k||(k=!0,C.reject(y,EA))}function T(EA){k||(k=!0,C.resolve(y,EA))}function q(){p(T,H)}var v=c(q);v.status==="error"&&H(v.value)}function c(y,p){var k={};try{k.value=y(p),k.status="success"}catch(H){k.status="error",k.value=H}return k}t.resolve=d;function d(y){return y instanceof this?y:C.resolve(new this(i),y)}t.reject=l;function l(y){var p=new this(i);return C.reject(p,y)}t.all=F;function F(y){var p=this;if(Object.prototype.toString.call(y)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=y.length,H=!1;if(!k)return this.resolve([]);for(var T=new Array(k),q=0,v=-1,EA=new this(i);++v<k;)aA(y[v],v);return EA;function aA(GA,rA){p.resolve(GA).then(P,function(BA){H||(H=!0,C.reject(EA,BA))});function P(BA){T[rA]=BA,++q===k&&!H&&(H=!0,C.resolve(EA,T))}}}t.race=m;function m(y){var p=this;if(Object.prototype.toString.call(y)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=y.length,H=!1;if(!k)return this.resolve([]);for(var T=-1,q=new this(i);++T<k;)v(y[T]);return q;function v(EA){p.resolve(EA).then(function(aA){H||(H=!0,C.resolve(q,aA))},function(aA){H||(H=!0,C.reject(q,aA))})}}},{1:1}],3:[function(B,g,I){(function(E){typeof E.Promise!="function"&&(E.Promise=B(2))}).call(this,typeof dI<"u"?dI:typeof self<"u"?self:typeof window<"u"?window:{})},{2:2}],4:[function(B,g,I){var E=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(M){return typeof M}:function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M};function i(M,u){if(!(M instanceof u))throw new TypeError("Cannot call a class as a function")}function C(){try{if(typeof indexedDB<"u")return indexedDB;if(typeof webkitIndexedDB<"u")return webkitIndexedDB;if(typeof mozIndexedDB<"u")return mozIndexedDB;if(typeof OIndexedDB<"u")return OIndexedDB;if(typeof msIndexedDB<"u")return msIndexedDB}catch{return}}var a=C();function e(){try{if(!a||!a.open)return!1;var M=typeof openDatabase<"u"&&/(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&!/BlackBerry/.test(navigator.platform),u=typeof fetch=="function"&&fetch.toString().indexOf("[native code")!==-1;return(!M||u)&&typeof indexedDB<"u"&&typeof IDBKeyRange<"u"}catch{return!1}}function o(M,u){M=M||[],u=u||{};try{return new Blob(M,u)}catch(b){if(b.name!=="TypeError")throw b;for(var R=typeof BlobBuilder<"u"?BlobBuilder:typeof MSBlobBuilder<"u"?MSBlobBuilder:typeof MozBlobBuilder<"u"?MozBlobBuilder:WebKitBlobBuilder,Y=new R,U=0;U<M.length;U+=1)Y.append(M[U]);return Y.getBlob(u.type)}}typeof Promise>"u"&&B(3);var t=Promise;function s(M,u){u&&M.then(function(R){u(null,R)},function(R){u(R)})}function G(M,u,R){typeof u=="function"&&M.then(u),typeof R=="function"&&M.catch(R)}function n(M){return typeof M!="string"&&(console.warn(M+" used as a key, but it is not a string."),M=String(M)),M}function h(){if(arguments.length&&typeof arguments[arguments.length-1]=="function")return arguments[arguments.length-1]}var c="local-forage-detect-blob-support",d=void 0,l={},F=Object.prototype.toString,m="readonly",y="readwrite";function p(M){for(var u=M.length,R=new ArrayBuffer(u),Y=new Uint8Array(R),U=0;U<u;U++)Y[U]=M.charCodeAt(U);return R}function k(M){return new t(function(u){var R=M.transaction(c,y),Y=o([""]);R.objectStore(c).put(Y,"key"),R.onabort=function(U){U.preventDefault(),U.stopPropagation(),u(!1)},R.oncomplete=function(){var U=navigator.userAgent.match(/Chrome\/(\d+)/),b=navigator.userAgent.match(/Edge\//);u(b||!U||parseInt(U[1],10)>=43)}}).catch(function(){return!1})}function H(M){return typeof d=="boolean"?t.resolve(d):k(M).then(function(u){return d=u,d})}function T(M){var u=l[M.name],R={};R.promise=new t(function(Y,U){R.resolve=Y,R.reject=U}),u.deferredOperations.push(R),u.dbReady?u.dbReady=u.dbReady.then(function(){return R.promise}):u.dbReady=R.promise}function q(M){var u=l[M.name],R=u.deferredOperations.pop();if(R)return R.resolve(),R.promise}function v(M,u){var R=l[M.name],Y=R.deferredOperations.pop();if(Y)return Y.reject(u),Y.promise}function EA(M,u){return new t(function(R,Y){if(l[M.name]=l[M.name]||DA(),M.db)if(u)T(M),M.db.close();else return R(M.db);var U=[M.name];u&&U.push(M.version);var b=a.open.apply(a,U);u&&(b.onupgradeneeded=function(W){var f=b.result;try{f.createObjectStore(M.storeName),W.oldVersion<=1&&f.createObjectStore(c)}catch(N){if(N.name==="ConstraintError")console.warn('The database "'+M.name+'" has been upgraded from version '+W.oldVersion+" to version "+W.newVersion+', but the storage "'+M.storeName+'" already exists.');else throw N}}),b.onerror=function(W){W.preventDefault(),Y(b.error)},b.onsuccess=function(){var W=b.result;W.onversionchange=function(f){f.target.close()},R(W),q(M)}})}function aA(M){return EA(M,!1)}function GA(M){return EA(M,!0)}function rA(M,u){if(!M.db)return!0;var R=!M.db.objectStoreNames.contains(M.storeName),Y=M.version<M.db.version,U=M.version>M.db.version;if(Y&&(M.version!==u&&console.warn('The database "'+M.name+`" can't be downgraded from version `+M.db.version+" to version "+M.version+"."),M.version=M.db.version),U||R){if(R){var b=M.db.version+1;b>M.version&&(M.version=b)}return!0}return!1}function P(M){return new t(function(u,R){var Y=new FileReader;Y.onerror=R,Y.onloadend=function(U){var b=btoa(U.target.result||"");u({__local_forage_encoded_blob:!0,data:b,type:M.type})},Y.readAsBinaryString(M)})}function BA(M){var u=p(atob(M.data));return o([u],{type:M.type})}function wA(M){return M&&M.__local_forage_encoded_blob}function yA(M){var u=this,R=u._initReady().then(function(){var Y=l[u._dbInfo.name];if(Y&&Y.dbReady)return Y.dbReady});return G(R,M,M),R}function jQ(M){T(M);for(var u=l[M.name],R=u.forages,Y=0;Y<R.length;Y++){var U=R[Y];U._dbInfo.db&&(U._dbInfo.db.close(),U._dbInfo.db=null)}return M.db=null,aA(M).then(function(b){return M.db=b,rA(M)?GA(M):b}).then(function(b){M.db=u.db=b;for(var W=0;W<R.length;W++)R[W]._dbInfo.db=b}).catch(function(b){throw v(M,b),b})}function QA(M,u,R,Y){Y===void 0&&(Y=1);try{var U=M.db.transaction(M.storeName,u);R(null,U)}catch(b){if(Y>0&&(!M.db||b.name==="InvalidStateError"||b.name==="NotFoundError"))return t.resolve().then(function(){if(!M.db||b.name==="NotFoundError"&&!M.db.objectStoreNames.contains(M.storeName)&&M.version<=M.db.version)return M.db&&(M.version=M.db.version+1),GA(M)}).then(function(){return jQ(M).then(function(){QA(M,u,R,Y-1)})}).catch(R);R(b)}}function DA(){return{forages:[],db:null,dbReady:null,deferredOperations:[]}}function Qg(M){var u=this,R={db:null};if(M)for(var Y in M)R[Y]=M[Y];var U=l[R.name];U||(U=DA(),l[R.name]=U),U.forages.push(u),u._initReady||(u._initReady=u.ready,u.ready=yA);var b=[];function W(){return t.resolve()}for(var f=0;f<U.forages.length;f++){var N=U.forages[f];N!==u&&b.push(N._initReady().catch(W))}var J=U.forages.slice(0);return t.all(b).then(function(){return R.db=U.db,aA(R)}).then(function(V){return R.db=V,rA(R,u._defaultConfig.version)?GA(R):V}).then(function(V){R.db=U.db=V,u._dbInfo=R;for(var O=0;O<J.length;O++){var iA=J[O];iA!==u&&(iA._dbInfo.db=R.db,iA._dbInfo.version=R.version)}})}function pC(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){QA(R._dbInfo,m,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=N.get(M);J.onsuccess=function(){var V=J.result;V===void 0&&(V=null),wA(V)&&(V=BA(V)),U(V)},J.onerror=function(){b(J.error)}}catch(V){b(V)}})}).catch(b)});return s(Y,u),Y}function Ls(M,u){var R=this,Y=new t(function(U,b){R.ready().then(function(){QA(R._dbInfo,m,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=N.openCursor(),V=1;J.onsuccess=function(){var O=J.result;if(O){var iA=O.value;wA(iA)&&(iA=BA(iA));var oA=M(iA,O.key,V++);oA!==void 0?U(oA):O.continue()}else U()},J.onerror=function(){b(J.error)}}catch(O){b(O)}})}).catch(b)});return s(Y,u),Y}function hR(M,u,R){var Y=this;M=n(M);var U=new t(function(b,W){var f;Y.ready().then(function(){return f=Y._dbInfo,F.call(u)==="[object Blob]"?H(f.db).then(function(N){return N?u:P(u)}):u}).then(function(N){QA(Y._dbInfo,y,function(J,V){if(J)return W(J);try{var O=V.objectStore(Y._dbInfo.storeName);N===null&&(N=void 0);var iA=O.put(N,M);V.oncomplete=function(){N===void 0&&(N=null),b(N)},V.onabort=V.onerror=function(){var oA=iA.error?iA.error:iA.transaction.error;W(oA)}}catch(oA){W(oA)}})}).catch(W)});return s(U,R),U}function cR(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){QA(R._dbInfo,y,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=N.delete(M);f.oncomplete=function(){U()},f.onerror=function(){b(J.error)},f.onabort=function(){var V=J.error?J.error:J.transaction.error;b(V)}}catch(V){b(V)}})}).catch(b)});return s(Y,u),Y}function rR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){QA(u._dbInfo,y,function(b,W){if(b)return U(b);try{var f=W.objectStore(u._dbInfo.storeName),N=f.clear();W.oncomplete=function(){Y()},W.onabort=W.onerror=function(){var J=N.error?N.error:N.transaction.error;U(J)}}catch(J){U(J)}})}).catch(U)});return s(R,M),R}function lR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){QA(u._dbInfo,m,function(b,W){if(b)return U(b);try{var f=W.objectStore(u._dbInfo.storeName),N=f.count();N.onsuccess=function(){Y(N.result)},N.onerror=function(){U(N.error)}}catch(J){U(J)}})}).catch(U)});return s(R,M),R}function DR(M,u){var R=this,Y=new t(function(U,b){if(M<0){U(null);return}R.ready().then(function(){QA(R._dbInfo,m,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=!1,V=N.openKeyCursor();V.onsuccess=function(){var O=V.result;if(!O){U(null);return}M===0||J?U(O.key):(J=!0,O.advance(M))},V.onerror=function(){b(V.error)}}catch(O){b(O)}})}).catch(b)});return s(Y,u),Y}function dR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){QA(u._dbInfo,m,function(b,W){if(b)return U(b);try{var f=W.objectStore(u._dbInfo.storeName),N=f.openKeyCursor(),J=[];N.onsuccess=function(){var V=N.result;if(!V){Y(J);return}J.push(V.key),V.continue()},N.onerror=function(){U(N.error)}}catch(V){U(V)}})}).catch(U)});return s(R,M),R}function FR(M,u){u=h.apply(this,arguments);var R=this.config();M=typeof M!="function"&&M||{},M.name||(M.name=M.name||R.name,M.storeName=M.storeName||R.storeName);var Y=this,U;if(!M.name)U=t.reject("Invalid arguments");else{var b=M.name===R.name&&Y._dbInfo.db,W=b?t.resolve(Y._dbInfo.db):aA(M).then(function(f){var N=l[M.name],J=N.forages;N.db=f;for(var V=0;V<J.length;V++)J[V]._dbInfo.db=f;return f});M.storeName?U=W.then(function(f){if(f.objectStoreNames.contains(M.storeName)){var N=f.version+1;T(M);var J=l[M.name],V=J.forages;f.close();for(var O=0;O<V.length;O++){var iA=V[O];iA._dbInfo.db=null,iA._dbInfo.version=N}var oA=new t(function(sA,uA){var RA=a.open(M.name,N);RA.onerror=function(IB){var sI=RA.result;sI.close(),uA(IB)},RA.onupgradeneeded=function(){var IB=RA.result;IB.deleteObjectStore(M.storeName)},RA.onsuccess=function(){var IB=RA.result;IB.close(),sA(IB)}});return oA.then(function(sA){J.db=sA;for(var uA=0;uA<V.length;uA++){var RA=V[uA];RA._dbInfo.db=sA,q(RA._dbInfo)}}).catch(function(sA){throw(v(M,sA)||t.resolve()).catch(function(){}),sA})}}):U=W.then(function(f){T(M);var N=l[M.name],J=N.forages;f.close();for(var V=0;V<J.length;V++){var O=J[V];O._dbInfo.db=null}var iA=new t(function(oA,sA){var uA=a.deleteDatabase(M.name);uA.onerror=function(){var RA=uA.result;RA&&RA.close(),sA(uA.error)},uA.onblocked=function(){console.warn('dropInstance blocked for database "'+M.name+'" until all open connections are closed')},uA.onsuccess=function(){var RA=uA.result;RA&&RA.close(),oA(RA)}});return iA.then(function(oA){N.db=oA;for(var sA=0;sA<J.length;sA++){var uA=J[sA];q(uA._dbInfo)}}).catch(function(oA){throw(v(M,oA)||t.resolve()).catch(function(){}),oA})})}return s(U,u),U}var MR={_driver:"asyncStorage",_initStorage:Qg,_support:e(),iterate:Ls,getItem:pC,setItem:hR,removeItem:cR,clear:rR,length:lR,key:DR,keys:dR,dropInstance:FR};function wR(){return typeof openDatabase=="function"}var xB="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",yR="~~local_forage_type~",Xs=/^~~local_forage_type~([^~]+)~/,OQ="__lfsc__:",YC=OQ.length,UC="arbf",kC="blob",vs="si08",Ks="ui08",zs="uic8",Ts="si16",js="si32",Os="ur16",Ps="ui32",_s="fl32",$s="fl64",AG=YC+UC.length,BG=Object.prototype.toString;function gG(M){var u=M.length*.75,R=M.length,Y,U=0,b,W,f,N;M[M.length-1]==="="&&(u--,M[M.length-2]==="="&&u--);var J=new ArrayBuffer(u),V=new Uint8Array(J);for(Y=0;Y<R;Y+=4)b=xB.indexOf(M[Y]),W=xB.indexOf(M[Y+1]),f=xB.indexOf(M[Y+2]),N=xB.indexOf(M[Y+3]),V[U++]=b<<2|W>>4,V[U++]=(W&15)<<4|f>>2,V[U++]=(f&3)<<6|N&63;return J}function ZC(M){var u=new Uint8Array(M),R="",Y;for(Y=0;Y<u.length;Y+=3)R+=xB[u[Y]>>2],R+=xB[(u[Y]&3)<<4|u[Y+1]>>4],R+=xB[(u[Y+1]&15)<<2|u[Y+2]>>6],R+=xB[u[Y+2]&63];return u.length%3===2?R=R.substring(0,R.length-1)+"=":u.length%3===1&&(R=R.substring(0,R.length-2)+"=="),R}function RR(M,u){var R="";if(M&&(R=BG.call(M)),M&&(R==="[object ArrayBuffer]"||M.buffer&&BG.call(M.buffer)==="[object ArrayBuffer]")){var Y,U=OQ;M instanceof ArrayBuffer?(Y=M,U+=UC):(Y=M.buffer,R==="[object Int8Array]"?U+=vs:R==="[object Uint8Array]"?U+=Ks:R==="[object Uint8ClampedArray]"?U+=zs:R==="[object Int16Array]"?U+=Ts:R==="[object Uint16Array]"?U+=Os:R==="[object Int32Array]"?U+=js:R==="[object Uint32Array]"?U+=Ps:R==="[object Float32Array]"?U+=_s:R==="[object Float64Array]"?U+=$s:u(new Error("Failed to get type for BinaryArray"))),u(U+ZC(Y))}else if(R==="[object Blob]"){var b=new FileReader;b.onload=function(){var W=yR+M.type+"~"+ZC(this.result);u(OQ+kC+W)},b.readAsArrayBuffer(M)}else try{u(JSON.stringify(M))}catch(W){console.error("Couldn't convert value into a JSON string: ",M),u(null,W)}}function mR(M){if(M.substring(0,YC)!==OQ)return JSON.parse(M);var u=M.substring(AG),R=M.substring(YC,AG),Y;if(R===kC&&Xs.test(u)){var U=u.match(Xs);Y=U[1],u=u.substring(U[0].length)}var b=gG(u);switch(R){case UC:return b;case kC:return o([b],{type:Y});case vs:return new Int8Array(b);case Ks:return new Uint8Array(b);case zs:return new Uint8ClampedArray(b);case Ts:return new Int16Array(b);case Os:return new Uint16Array(b);case js:return new Int32Array(b);case Ps:return new Uint32Array(b);case _s:return new Float32Array(b);case $s:return new Float64Array(b);default:throw new Error("Unkown type: "+R)}}var WC={serialize:RR,deserialize:mR,stringToBuffer:gG,bufferToString:ZC};function IG(M,u,R,Y){M.executeSql("CREATE TABLE IF NOT EXISTS "+u.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],R,Y)}function uR(M){var u=this,R={db:null};if(M)for(var Y in M)R[Y]=typeof M[Y]!="string"?M[Y].toString():M[Y];var U=new t(function(b,W){try{R.db=openDatabase(R.name,String(R.version),R.description,R.size)}catch(f){return W(f)}R.db.transaction(function(f){IG(f,R,function(){u._dbInfo=R,b()},function(N,J){W(J)})},W)});return R.serializer=WC,U}function VB(M,u,R,Y,U,b){M.executeSql(R,Y,U,function(W,f){f.code===f.SYNTAX_ERR?W.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?",[u.storeName],function(N,J){J.rows.length?b(N,f):IG(N,u,function(){N.executeSql(R,Y,U,b)},b)},b):b(W,f)},b)}function SR(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"SELECT * FROM "+W.storeName+" WHERE key = ? LIMIT 1",[M],function(N,J){var V=J.rows.length?J.rows.item(0).value:null;V&&(V=W.serializer.deserialize(V)),U(V)},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function bR(M,u){var R=this,Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"SELECT * FROM "+W.storeName,[],function(N,J){for(var V=J.rows,O=V.length,iA=0;iA<O;iA++){var oA=V.item(iA),sA=oA.value;if(sA&&(sA=W.serializer.deserialize(sA)),sA=M(sA,oA.key,iA+1),sA!==void 0){U(sA);return}}U()},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function QG(M,u,R,Y){var U=this;M=n(M);var b=new t(function(W,f){U.ready().then(function(){u===void 0&&(u=null);var N=u,J=U._dbInfo;J.serializer.serialize(u,function(V,O){O?f(O):J.db.transaction(function(iA){VB(iA,J,"INSERT OR REPLACE INTO "+J.storeName+" (key, value) VALUES (?, ?)",[M,V],function(){W(N)},function(oA,sA){f(sA)})},function(iA){if(iA.code===iA.QUOTA_ERR){if(Y>0){W(QG.apply(U,[M,N,R,Y-1]));return}f(iA)}})})}).catch(f)});return s(b,R),b}function pR(M,u,R){return QG.apply(this,[M,u,R,1])}function YR(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"DELETE FROM "+W.storeName+" WHERE key = ?",[M],function(){U()},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function UR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){var b=u._dbInfo;b.db.transaction(function(W){VB(W,b,"DELETE FROM "+b.storeName,[],function(){Y()},function(f,N){U(N)})})}).catch(U)});return s(R,M),R}function kR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){var b=u._dbInfo;b.db.transaction(function(W){VB(W,b,"SELECT COUNT(key) as c FROM "+b.storeName,[],function(f,N){var J=N.rows.item(0).c;Y(J)},function(f,N){U(N)})})}).catch(U)});return s(R,M),R}function ZR(M,u){var R=this,Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"SELECT key FROM "+W.storeName+" WHERE id = ? LIMIT 1",[M+1],function(N,J){var V=J.rows.length?J.rows.item(0).key:null;U(V)},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function WR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){var b=u._dbInfo;b.db.transaction(function(W){VB(W,b,"SELECT key FROM "+b.storeName,[],function(f,N){for(var J=[],V=0;V<N.rows.length;V++)J.push(N.rows.item(V).key);Y(J)},function(f,N){U(N)})})}).catch(U)});return s(R,M),R}function HR(M){return new t(function(u,R){M.transaction(function(Y){Y.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'",[],function(U,b){for(var W=[],f=0;f<b.rows.length;f++)W.push(b.rows.item(f).name);u({db:M,storeNames:W})},function(U,b){R(b)})},function(Y){R(Y)})})}function fR(M,u){u=h.apply(this,arguments);var R=this.config();M=typeof M!="function"&&M||{},M.name||(M.name=M.name||R.name,M.storeName=M.storeName||R.storeName);var Y=this,U;return M.name?U=new t(function(b){var W;M.name===R.name?W=Y._dbInfo.db:W=openDatabase(M.name,"","",0),M.storeName?b({db:W,storeNames:[M.storeName]}):b(HR(W))}).then(function(b){return new t(function(W,f){b.db.transaction(function(N){function J(oA){return new t(function(sA,uA){N.executeSql("DROP TABLE IF EXISTS "+oA,[],function(){sA()},function(RA,IB){uA(IB)})})}for(var V=[],O=0,iA=b.storeNames.length;O<iA;O++)V.push(J(b.storeNames[O]));t.all(V).then(function(){W()}).catch(function(oA){f(oA)})},function(N){f(N)})})}):U=t.reject("Invalid arguments"),s(U,u),U}var NR={_driver:"webSQLStorage",_initStorage:uR,_support:wR(),iterate:bR,getItem:SR,setItem:pR,removeItem:YR,clear:UR,length:kR,key:ZR,keys:WR,dropInstance:fR};function JR(){try{return typeof localStorage<"u"&&"setItem"in localStorage&&!!localStorage.setItem}catch{return!1}}function EG(M,u){var R=M.name+"/";return M.storeName!==u.storeName&&(R+=M.storeName+"/"),R}function qR(){var M="_localforage_support_test";try{return localStorage.setItem(M,!0),localStorage.removeItem(M),!1}catch{return!0}}function xR(){return!qR()||localStorage.length>0}function VR(M){var u=this,R={};if(M)for(var Y in M)R[Y]=M[Y];return R.keyPrefix=EG(M,u._defaultConfig),xR()?(u._dbInfo=R,R.serializer=WC,t.resolve()):t.reject()}function LR(M){var u=this,R=u.ready().then(function(){for(var Y=u._dbInfo.keyPrefix,U=localStorage.length-1;U>=0;U--){var b=localStorage.key(U);b.indexOf(Y)===0&&localStorage.removeItem(b)}});return s(R,M),R}function XR(M,u){var R=this;M=n(M);var Y=R.ready().then(function(){var U=R._dbInfo,b=localStorage.getItem(U.keyPrefix+M);return b&&(b=U.serializer.deserialize(b)),b});return s(Y,u),Y}function vR(M,u){var R=this,Y=R.ready().then(function(){for(var U=R._dbInfo,b=U.keyPrefix,W=b.length,f=localStorage.length,N=1,J=0;J<f;J++){var V=localStorage.key(J);if(V.indexOf(b)===0){var O=localStorage.getItem(V);if(O&&(O=U.serializer.deserialize(O)),O=M(O,V.substring(W),N++),O!==void 0)return O}}});return s(Y,u),Y}function KR(M,u){var R=this,Y=R.ready().then(function(){var U=R._dbInfo,b;try{b=localStorage.key(M)}catch{b=null}return b&&(b=b.substring(U.keyPrefix.length)),b});return s(Y,u),Y}function zR(M){var u=this,R=u.ready().then(function(){for(var Y=u._dbInfo,U=localStorage.length,b=[],W=0;W<U;W++){var f=localStorage.key(W);f.indexOf(Y.keyPrefix)===0&&b.push(f.substring(Y.keyPrefix.length))}return b});return s(R,M),R}function TR(M){var u=this,R=u.keys().then(function(Y){return Y.length});return s(R,M),R}function jR(M,u){var R=this;M=n(M);var Y=R.ready().then(function(){var U=R._dbInfo;localStorage.removeItem(U.keyPrefix+M)});return s(Y,u),Y}function OR(M,u,R){var Y=this;M=n(M);var U=Y.ready().then(function(){u===void 0&&(u=null);var b=u;return new t(function(W,f){var N=Y._dbInfo;N.serializer.serialize(u,function(J,V){if(V)f(V);else try{localStorage.setItem(N.keyPrefix+M,J),W(b)}catch(O){(O.name==="QuotaExceededError"||O.name==="NS_ERROR_DOM_QUOTA_REACHED")&&f(O),f(O)}})})});return s(U,R),U}function PR(M,u){if(u=h.apply(this,arguments),M=typeof M!="function"&&M||{},!M.name){var R=this.config();M.name=M.name||R.name,M.storeName=M.storeName||R.storeName}var Y=this,U;return M.name?U=new t(function(b){M.storeName?b(EG(M,Y._defaultConfig)):b(M.name+"/")}).then(function(b){for(var W=localStorage.length-1;W>=0;W--){var f=localStorage.key(W);f.indexOf(b)===0&&localStorage.removeItem(f)}}):U=t.reject("Invalid arguments"),s(U,u),U}var _R={_driver:"localStorageWrapper",_initStorage:VR,_support:JR(),iterate:vR,getItem:XR,setItem:OR,removeItem:jR,clear:LR,length:TR,key:KR,keys:zR,dropInstance:PR},$R=function(u,R){return u===R||typeof u=="number"&&typeof R=="number"&&isNaN(u)&&isNaN(R)},Am=function(u,R){for(var Y=u.length,U=0;U<Y;){if($R(u[U],R))return!0;U++}return!1},iG=Array.isArray||function(M){return Object.prototype.toString.call(M)==="[object Array]"},tI={},CG={},Ug={INDEXEDDB:MR,WEBSQL:NR,LOCALSTORAGE:_R},Bm=[Ug.INDEXEDDB._driver,Ug.WEBSQL._driver,Ug.LOCALSTORAGE._driver],PQ=["dropInstance"],HC=["clear","getItem","iterate","key","keys","length","removeItem","setItem"].concat(PQ),gm={description:"",driver:Bm.slice(),name:"localforage",size:4980736,storeName:"keyvaluepairs",version:1};function Im(M,u){M[u]=function(){var R=arguments;return M.ready().then(function(){return M[u].apply(M,R)})}}function fC(){for(var M=1;M<arguments.length;M++){var u=arguments[M];if(u)for(var R in u)u.hasOwnProperty(R)&&(iG(u[R])?arguments[0][R]=u[R].slice():arguments[0][R]=u[R])}return arguments[0]}var Qm=(function(){function M(u){i(this,M);for(var R in Ug)if(Ug.hasOwnProperty(R)){var Y=Ug[R],U=Y._driver;this[R]=U,tI[U]||this.defineDriver(Y)}this._defaultConfig=fC({},gm),this._config=fC({},this._defaultConfig,u),this._driverSet=null,this._initDriver=null,this._ready=!1,this._dbInfo=null,this._wrapLibraryMethodsWithReady(),this.setDriver(this._config.driver).catch(function(){})}return M.prototype.config=function(R){if((typeof R>"u"?"undefined":E(R))==="object"){if(this._ready)return new Error("Can't call config() after localforage has been used.");for(var Y in R){if(Y==="storeName"&&(R[Y]=R[Y].replace(/\W/g,"_")),Y==="version"&&typeof R[Y]!="number")return new Error("Database version must be a number.");this._config[Y]=R[Y]}return"driver"in R&&R.driver?this.setDriver(this._config.driver):!0}else return typeof R=="string"?this._config[R]:this._config},M.prototype.defineDriver=function(R,Y,U){var b=new t(function(W,f){try{var N=R._driver,J=new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver");if(!R._driver){f(J);return}for(var V=HC.concat("_initStorage"),O=0,iA=V.length;O<iA;O++){var oA=V[O],sA=!Am(PQ,oA);if((sA||R[oA])&&typeof R[oA]!="function"){f(J);return}}var uA=function(){for(var sI=function(Cm){return function(){var am=new Error("Method "+Cm+" is not implemented by the current driver"),aG=t.reject(am);return s(aG,arguments[arguments.length-1]),aG}},NC=0,im=PQ.length;NC<im;NC++){var JC=PQ[NC];R[JC]||(R[JC]=sI(JC))}};uA();var RA=function(sI){tI[N]&&console.info("Redefining LocalForage driver: "+N),tI[N]=R,CG[N]=sI,W()};"_support"in R?R._support&&typeof R._support=="function"?R._support().then(RA,f):RA(!!R._support):RA(!0)}catch(IB){f(IB)}});return G(b,Y,U),b},M.prototype.driver=function(){return this._driver||null},M.prototype.getDriver=function(R,Y,U){var b=tI[R]?t.resolve(tI[R]):t.reject(new Error("Driver not found."));return G(b,Y,U),b},M.prototype.getSerializer=function(R){var Y=t.resolve(WC);return G(Y,R),Y},M.prototype.ready=function(R){var Y=this,U=Y._driverSet.then(function(){return Y._ready===null&&(Y._ready=Y._initDriver()),Y._ready});return G(U,R,R),U},M.prototype.setDriver=function(R,Y,U){var b=this;iG(R)||(R=[R]);var W=this._getSupportedDrivers(R);function f(){b._config.driver=b.driver()}function N(O){return b._extend(O),f(),b._ready=b._initStorage(b._config),b._ready}function J(O){return function(){var iA=0;function oA(){for(;iA<O.length;){var sA=O[iA];return iA++,b._dbInfo=null,b._ready=null,b.getDriver(sA).then(N).catch(oA)}f();var uA=new Error("No available storage method found.");return b._driverSet=t.reject(uA),b._driverSet}return oA()}}var V=this._driverSet!==null?this._driverSet.catch(function(){return t.resolve()}):t.resolve();return this._driverSet=V.then(function(){var O=W[0];return b._dbInfo=null,b._ready=null,b.getDriver(O).then(function(iA){b._driver=iA._driver,f(),b._wrapLibraryMethodsWithReady(),b._initDriver=J(W)})}).catch(function(){f();var O=new Error("No available storage method found.");return b._driverSet=t.reject(O),b._driverSet}),G(this._driverSet,Y,U),this._driverSet},M.prototype.supports=function(R){return!!CG[R]},M.prototype._extend=function(R){fC(this,R)},M.prototype._getSupportedDrivers=function(R){for(var Y=[],U=0,b=R.length;U<b;U++){var W=R[U];this.supports(W)&&Y.push(W)}return Y},M.prototype._wrapLibraryMethodsWithReady=function(){for(var R=0,Y=HC.length;R<Y;R++)Im(this,HC[R])},M.prototype.createInstance=function(R){return new M(R)},M})(),Em=new Qm;g.exports=Em},{3:3}]},{},[4])(4)})})(Ii)),Ii.exports}var ND=fD();const JD=ca(ND);function rg(Q){return`model:${Q}`}function qD(Q){const A=Q.lastIndexOf("/");return A>=0?Q.substring(0,A+1):""}async function xD(Q,A=3,B=1e3){let g=null;for(let I=0;I<A;I++)try{const E=await fetch(Q);if(!E.ok)throw new Error(`HTTP ${E.status}: ${E.statusText}`);return E}catch(E){if(g=E,I===A-1)throw E;const i=B*Math.pow(2,I);console.warn(`[ModelCache] Fetch failed (attempt ${I+1}/${A}), retrying in ${i}ms...`,{url:Q,error:String(E)}),await new Promise(C=>setTimeout(C,i))}throw g}async function co(Q,A,B,g=3,I=1e3){let E=null;for(let i=0;i<g;i++){const C=A?await A(Q):Q;try{const a=await fetch(C);if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);const e=await a.text(),o=JSON.parse(e),t=qD(C),s={},G=[];if(o.weightsManifest&&Array.isArray(o.weightsManifest)){for(const h of o.weightsManifest)if(h.paths&&Array.isArray(h.paths))for(const c of h.paths)G.push(c)}const n=G.map(async h=>{const c=t+h,d=await xD(c,g,I);s[h]=await d.arrayBuffer()});return await Promise.all(n),{manifest:e,weights:s,savedAt:Date.now(),originalUrl:Q}}catch(a){if(E=a,i===g-1)throw a;B?.(Q);const e=I*Math.pow(2,i);console.warn(`[ModelCache] Model fetch failed (attempt ${i+1}/${g}), re-resolving and retrying in ${e}ms...`,{url:Q,resolvedUrl:C,error:String(a)}),await new Promise(o=>setTimeout(o,e))}}throw E}function Qi(Q,A){return JSON.parse(A.manifest),{load:async()=>ro(A)}}function ro(Q){const A=JSON.parse(Q.manifest),B=[],g=[];if(A.weightsManifest&&Array.isArray(A.weightsManifest))for(const I of A.weightsManifest){if(I.weights&&Array.isArray(I.weights))for(const E of I.weights)g.push(E);if(I.paths&&Array.isArray(I.paths))for(const E of I.paths){const i=Q.weights[E];if(!i)throw new Error(`[ModelCache] Weight shard "${E}" not found in cache`);B.push(i)}}return{modelTopology:A.modelTopology,format:A.format??"graph-model",generatedBy:A.generatedBy,convertedBy:A.convertedBy,weightSpecs:g.length>0?g:void 0,weightData:B.length>0?B.length===1?B[0]:B:void 0}}const lo=new Map;let Do=!1;function VD(){Do||(Do=!0,import("@tensorflow/tfjs").then(Q=>{Q.io.registerLoadRouter((A=>{if(typeof A=="string"&&A.startsWith("cached://")){const B=lo.get(A);if(B)return{load:async()=>{const g=await B.store.getItem(B.key);if(!g)throw new Error(`[ModelCache] Model not in cache: ${A}`);return ro(g)}}}return null}))}))}VD();class Fo{constructor(A={}){this.store=JD.createInstance({name:A.storeName??"playlist-data-engine-models",description:A.description??"Cached TF.js model artifacts for playlist-data-engine"})}async has(A){return await this.store.getItem(rg(A))!=null}async getCacheInfo(A){const B=await this.store.getItem(rg(A));if(!B)return{cached:!1};let g=B.manifest.length;for(const I of Object.values(B.weights))g+=I.byteLength;return{cached:!0,savedAt:B.savedAt,size:g}}async loadFromCache(A,B){const g=await this.store.getItem(rg(B));if(!g)throw new Error(`[ModelCache] Model not cached: ${B}`);return A.loadGraphModel(Qi(A,g))}async getOrFetchGraphModel(A,B,g={}){const I=rg(B);try{const i=await this.store.getItem(I);if(i)return console.info(`[ModelCache] Loading model from cache: ${B}`),await A.loadGraphModel(Qi(A,i))}catch(i){console.warn("[ModelCache] Cache load failed, clearing and re-fetching:",i),await this.store.removeItem(I)}console.info(`[ModelCache] Downloading model: ${B}`);const E=await co(B,g.resolveUrl,g.invalidateUrlCache,g.maxRetries??3,g.baseDelayMs??1e3);return await this.store.setItem(I,E),console.info(`[ModelCache] Model cached: ${B} (${Object.keys(E.weights).length} shards)`),A.loadGraphModel(Qi(A,E))}async getOrFetchEssentiaUrl(A,B={}){const g=rg(A),I=`cached://${A}`;if(await this.store.getItem(g))console.info(`[ModelCache] Loading Essentia model from cache: ${A}`);else{console.info(`[ModelCache] Downloading model for Essentia: ${A}`);const i=await co(A,B.resolveUrl,B.invalidateUrlCache,B.maxRetries??3,B.baseDelayMs??1e3);await this.store.setItem(g,i),console.info(`[ModelCache] Model cached: ${A} (${Object.keys(i.weights).length} shards)`)}return lo.set(I,{store:this.store,key:g}),I}async clear(A){A?(await this.store.removeItem(rg(A)),console.info(`[ModelCache] Cleared cache for: ${A}`)):(await this.store.clear(),console.info("[ModelCache] Cleared all cached models"))}async listCachedModels(){return(await this.store.keys()).filter(B=>B.startsWith("model:")).map(B=>B.replace("model:",""))}async totalCacheSize(){let A=0;return await this.store.iterate(B=>{if(B){A+=B.manifest.length;for(const g of Object.values(B.weights))A+=g.byteLength}}),A}}const lg=new Fo;function LD(Q){if(!Q||!Q.metadata)return null;if(typeof Q.metadata=="string")try{const A=JSON.parse(Q.metadata);return typeof A=="object"&&A!==null&&!Array.isArray(A)?A:null}catch{return null}return typeof Q.metadata=="object"&&!Array.isArray(Q.metadata)?Q.metadata:null}function Mo(Q){const A={stems:[],mixes:[],hasExtras:!1};if(!Q)return A;const B=zD(Q),g=TD(Q),I=typeof Q.vrm=="string"?Q.vrm:void 0,E=XD(Q.lyrics),i=wo(Q.visualizer),C=wo(Q.video),a=vD(Q.merch),e=KD(Q.credits),o=typeof Q.midi=="string"?Q.midi:void 0,t=typeof Q.step_mania=="string"?Q.step_mania:void 0,s=typeof Q.clone_hero=="string"?Q.clone_hero:void 0,G=typeof Q.external_url=="string"?Q.external_url:void 0;return{hasExtras:B.length>0||g.length>0||!!I||!!E||!!i||!!C||!!a||!!e||!!o||!!t||!!s||!!G,...B.length>0?{stems:B}:{},...g.length>0?{mixes:g}:{},...I?{vrm:I}:{},...E?{lyrics:E}:{},...i?{visualizer:i}:{},...C?{video:C}:{},...a?{merch:a}:{},...e?{credits:e}:{},...o?{midi:o}:{},...t?{step_mania:t}:{},...s?{clone_hero:s}:{},...G?{external_url:G}:{}}}function XD(Q){if(Q){if(typeof Q=="string")return{text:Q};if(typeof Q=="object"&&!Array.isArray(Q)){const A=Q;return{text:typeof A.text=="string"?A.text:void 0}}}}function wo(Q){if(!Q||typeof Q!="object"||Array.isArray(Q))return;const A=Q;if(typeof A.uri=="string")return{uri:A.uri,mime_type:typeof A.mime_type=="string"?A.mime_type:void 0}}function vD(Q){if(!Q||typeof Q!="object"||Array.isArray(Q))return;const A=Q;if(typeof A.uri=="string")return{uri:A.uri,mime_type:typeof A.mime_type=="string"?A.mime_type:void 0,type:typeof A.type=="string"?A.type:void 0}}function KD(Q){if(!Array.isArray(Q))return;const A=[];for(const B of Q)if(B&&typeof B=="object"){const g=B;typeof g.name=="string"&&typeof g.credit=="string"&&A.push({name:g.name,credit:g.credit})}return A.length>0?A:void 0}function zD(Q){const A=Q.stems;if(!Array.isArray(A))return[];const B=[];for(const g of A)if(g&&typeof g=="object"){const I=g;B.push({name:typeof I.name=="string"?I.name:"",uri:typeof I.uri=="string"?I.uri:void 0,mime_type:typeof I.mime_type=="string"?I.mime_type:void 0})}return B}function TD(Q){const A=Q.mixes;if(!Array.isArray(A))return[];const B=[];for(const g of A)if(g&&typeof g=="object"){const I=g,E=jD(I.name),i=OD(I.conditions);B.push({name:E||"",uri:typeof I.uri=="string"?I.uri:void 0,mime_type:typeof I.mime_type=="string"?I.mime_type:void 0,conditions:i})}return B}function jD(Q){if(typeof Q=="string")return Q;if(Q&&typeof Q=="object"&&!Array.isArray(Q)){const A=Q;if(typeof A.value=="string")return A.value}return""}function OD(Q){if(!Array.isArray(Q))return[];const A=[];for(const B of Q)if(B&&typeof B=="object"){const g=B;typeof g.type=="string"&&typeof g.value=="string"&&A.push({type:g.type,value:g.value})}return A}function PD(Q,A){const B=[],g=new Date;for(const I of Q.mixes||[]){if(I.conditions.length===0){B.push({mix:I,conditions:[],allMet:!0,unmetConditions:[]});continue}const E=[],i=[];for(const C of I.conditions){const a=_D(C,A,g);E.push(a),a.met||i.push(a)}B.push({mix:I,conditions:E,allMet:i.length===0,unmetConditions:i})}return B}function _D(Q,A,B=new Date){const{type:g,value:I}=Q,E=A?.environment,i=A?.appState;switch(g){case"weather":{const C=E?.weather?.weatherType||"",a=C.toLowerCase()===I.toLowerCase();return{type:g,value:I,met:a,reason:a?`Weather is ${C}`:`Weather is ${C} (need ${I})`}}case"day":{const a=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][B.getDay()],e=a.toLowerCase()===I.toLowerCase();return{type:g,value:I,met:e,reason:e?`Today is ${a}`:`Today is ${a} (need ${I})`}}case"start_time":{const C=B.getHours()*60+B.getMinutes(),a=yo(I),e=C>=a;return{type:g,value:I,met:e,reason:e?`Time is after ${I}`:`Time is before ${I}`}}case"end_time":{const C=B.getHours()*60+B.getMinutes(),a=yo(I),e=C<a;return{type:g,value:I,met:e,reason:e?`Time is before ${I}`:`Time is after ${I}`}}case"min_plays":{const C=parseInt(I,10),a=i?.playCount??0,e=a>=C;return{type:g,value:I,met:e,reason:e?`Played ${a} times (need ${C})`:`Played ${a} times (need ${C})`}}case"max_plays":{const C=parseInt(I,10),a=i?.playCount??0,e=a<=C;return{type:g,value:I,met:e,reason:e?`Played ${a} times (max ${C})`:`Played ${a} times (exceeds max ${C})`}}case"every_x_plays":{const C=parseInt(I,10),a=i?.playCount??0,e=C>0&&a>0&&a%C===0;return{type:g,value:I,met:e,reason:e?`Play #${a} (every ${C} plays)`:`Play #${a} (not a multiple of ${C})`}}case"altitude":{const C=E?.geolocation?.altitude;if(C==null)return{type:g,value:I,met:!1,reason:"Altitude unavailable"};const a=$D(I),e=Ad(C,a.operator,a.threshold);return{type:g,value:I,met:e,reason:e?`Altitude ${C}m ${a.operator} ${a.threshold}m`:`Altitude ${C}m (need ${a.operator} ${a.threshold}m)`}}case"favorite":{const C=i?.isFavorite??!1,a=I.toLowerCase()==="true",e=C===a;return{type:g,value:I,met:e,reason:e?C?"Track is favorited":"Track is not favorited":C?"Track is favorited (need unfavorited)":"Track is not favorited (need favorited)"}}case"birthday":{if(!i?.userBirthday)return{type:g,value:I,met:!1,reason:"Birthday not set"};const a=`${String(B.getMonth()+1).padStart(2,"0")}-${String(B.getDate()).padStart(2,"0")}`===i.userBirthday;return{type:g,value:I,met:a,reason:a?"It's your birthday!":`Not your birthday (need ${i.userBirthday})`}}case"weight":return{type:g,value:I,met:!0,reason:`Weight ${I} (used for random selection, always available)`};default:return{type:g,value:I,met:!0,reason:`Custom condition: ${g} = ${I}`}}}function yo(Q){const A=Q.split(":");if(A.length!==2)return 0;const B=parseInt(A[0],10),g=parseInt(A[1],10);return isNaN(B)||isNaN(g)?0:B*60+g}function $D(Q){const A=Q.match(/^(>=|<=|>|<|=)?\s*(\d+(?:\.\d+)?)\s*$/);return A?{operator:A[1]||">=",threshold:parseFloat(A[2])}:{operator:">=",threshold:parseFloat(Q)||0}}function Ad(Q,A,B){switch(A){case">":return Q>B;case">=":return Q>=B;case"<":return Q<B;case"<=":return Q<=B;case"=":case"==":return Q===B;default:return Q>=B}}class Ro{generateName(A,B,g,I,E=!1){const i=this.cleanTitle(B.title),C=E?A:`${A}-${Date.now()}-${Math.random()}`,a=new QB(C);switch(this.selectFormat(a)){case"class_title":return this.formatClassTitle(i,I,a);case"adjective_construct":return this.formatAdjectiveConstruct(i,B.genre,g,a);case"clan_construct":return this.formatClanConstruct(i,B.artist,a);case"descriptive_epithet":return this.formatDescriptiveEpithet(i,I,g,a);case"compound_adjective":return this.formatCompoundAdjective(i,B.genre,g,a);case"artist_inspired":return this.formatArtistInspired(i,B.artist,I,a);case"mononym_subtitle":return this.formatMononymSubtitle(i,g,B.genre,a);default:return i}}cleanTitle(A){let B=A;return B=B.replace(/\s*[([].*?(video|official|remix|mix|edit|feat|ft\.|version|remaster).*?[)\]]/gi,""),B=B.replace(/^\s*\d+[\s.-]+/,""),B=B.replace(/\.(mp3|wav|flac|m4a)$/i,""),B.trim()}selectFormat(A){const B=A.random();return B<.2?"class_title":B<.4?"adjective_construct":B<.5?"clan_construct":B<.7?"descriptive_epithet":B<.85?"compound_adjective":B<.95?"artist_inspired":"mononym_subtitle"}formatClassTitle(A,B,g){return`${A} the ${B}`}formatAdjectiveConstruct(A,B,g,I){const E=this.findGenreKey(B),i=aB.adjectives[E]||aB.adjectives.default,C=this.calculateBalancedAdjectiveWeights(g),a=I.weightedChoice(C),e=i[a];return`${I.randomChoice(e)} ${A}`}formatClanConstruct(A,B,g){return`${A} of ${B}`}formatDescriptiveEpithet(A,B,g,I){const E=I.randomChoice(aB.descriptors),i=aB.classAspects[B]||["Wanderer","Seeker","Sage","Hero"],C=I.randomChoice(i);return`${A}, the ${E} ${C}`}formatCompoundAdjective(A,B,g,I){const E=I.randomChoice(aB.prefixes),i=I.randomChoice(aB.suffixes);return`${E}-${i} ${A}`}formatArtistInspired(A,B,g,I){const E=B.split(" ")[0],i=I.randomChoice(aB.occupations),C=`${E}${i}`,a=I.randomChoice(aB.realms);return`${C} of the ${a}`}formatMononymSubtitle(A,B,g,I){const E=A.split(" "),i=E[0];let C;return E.length>1?C=E.slice(1).join(" "):C=I.randomChoice(aB.subtitlePrefixes),`${i} [${C}]`}calculateBalancedAdjectiveWeights(A){const g={bass:A.bass_dominance,treble:A.treble_dominance,mid:A.mid_dominance,quiet:A.average_amplitude<.4?.5:0,loud:A.average_amplitude>.6?.5:0};return[["bass",1+g.bass],["treble",1+g.treble],["mid",1+g.mid],["quiet",1+g.quiet],["loud",1+g.loud]]}findGenreKey(A){const B=A.toLowerCase(),g=Object.keys(aB.adjectives).filter(I=>I!=="default"&&B.includes(I));return g.length>0?g[0]:"default"}}class _A{static select(A,B,g,I="relative"){if(A.length===0)throw new Error("Cannot select from empty items array");const E=this.getFinalWeights(A,B,I),i=A.map(C=>{const a=this.getItemKey(C),e=a in E?E[a]:1;return[C,e]});return g.weightedChoice(i)}static selectMultiple(A,B,g,I,E="relative"){if(A.length===0)return[];if(I<=0)return[];if(I>=A.length)return g.shuffle(A);const i=[],C=[...A],a={...B};for(let e=0;e<I&&C.length>0;e++){const o=this.select(C,a,g,E);i.push(o);const t=C.indexOf(o);if(t!==-1){const s=this.getItemKey(o);C.splice(t,1),delete a[s]}}return i}static getProbabilities(A,B,g="relative"){if(A.length===0)return{};const I=this.getFinalWeights(A,B,g),E=Object.values(I).reduce((C,a)=>C+a,0);if(E===0){const C={};for(const a of A){const e=this.getItemKey(a);C[e]=1/A.length}return C}const i={};for(const C of A){const a=this.getItemKey(C),e=I[a]||0;i[a]=E>0?e/E:0}return i}static normalizeWeights(A,B,g="relative"){if(A.length===0)return{};const I=_A.getFinalWeights(A,B,g),E=Object.values(I).reduce((C,a)=>C+a,0);if(E===0){const C={};for(const a of A){const e=_A.getItemKey(a);C[e]=1/A.length}return C}const i={};for(const C of A){const a=_A.getItemKey(C);i[a]=I[a]/E}return i}static getItemKey(A){return typeof A=="string"?A:A&&typeof A=="object"&&"name"in A?String(A.name):String(A)}static getFinalWeights(A,B,g){const I={};if(g==="default")for(const E of A){const i=this.getItemKey(E);I[i]=1}else if(g==="absolute")for(const E of A){const i=this.getItemKey(E);I[i]=B[i]!==void 0?B[i]:1}else for(const E of A){const i=this.getItemKey(E);I[i]=B[i]!==void 0?B[i]:1}return I}}const Ei=[{id:"barbarian_rage",name:"Rage",description:"In battle, you fight with primal fury. On your turn, you can enter a rage as a bonus action. While raging, you gain the following benefits if you aren't wearing heavy armor: Advantage on Strength checks and Strength saving throws, +2 damage bonus with melee weapons using Strength, resistance to bludgeoning, piercing, and slashing damage.",type:"active",level:1,class:"Barbarian",effects:[{type:"stat_bonus",target:"melee_damage",value:2,condition:"while raging"}],source:"default",tags:["combat","damage"]},{id:"barbarian_unarmored_defense",name:"Unarmored Defense",description:"While you are not wearing any armor, your Armor Class equals 10 + your Dexterity modifier + your Constitution modifier.",type:"passive",level:1,class:"Barbarian",source:"default",tags:["defense"]},{id:"barbarian_reckless_attack",name:"Reckless Attack",description:"You can throw aside all concern for defense to attack with fierce desperation. When you make your first attack on your turn, you can decide to attack recklessly. Doing so gives you advantage on melee weapon attack rolls using Strength during this turn, but attack rolls against you have advantage until your next turn.",type:"active",level:2,class:"Barbarian",source:"default",tags:["combat"]},{id:"barbarian_danger_sense",name:"Danger Sense",description:"You gain an uncanny sense of when things nearby aren't as they should be, giving you edge when you attempt to dodge a danger or react to a hidden threat. You have advantage on Dexterity saving throws against effects that you can see, such as traps and spells.",type:"passive",level:2,class:"Barbarian",source:"default",tags:["defense","perception"]},{id:"barbarian_extra_attack",name:"Extra Attack",description:"You can attack twice, instead of once, whenever you take the Attack action on your turn.",type:"passive",level:5,class:"Barbarian",source:"default",tags:["combat"]},{id:"barbarian_fast_movement",name:"Fast Movement",description:"Your speed increases by 10 feet while you aren't wearing heavy armor.",type:"passive",level:5,class:"Barbarian",effects:[{type:"passive_modifier",target:"speed",value:10,condition:"unarmored"}],source:"default",tags:["movement"]},{id:"barbarian_feral_instinct",name:"Feral Instinct",description:"Your instincts are so honed that you have advantage on initiative rolls. Additionally, if you are surprised at the start of combat and aren't incapacitated, you can act normally on your first turn.",type:"passive",level:7,class:"Barbarian",source:"default",tags:["combat","perception"]},{id:"barbarian_brutal_critical",name:"Brutal Critical",description:"When you score a critical hit with a melee weapon attack, you can roll one of the weapon's damage dice one additional time and add it to the extra damage of the critical hit.",type:"passive",level:9,class:"Barbarian",source:"default",tags:["combat","damage"]},{id:"barbarian_relentless_endurance",name:"Relentless Endurance",description:"When you are reduced to 0 hit points but not killed outright, you can drop to 1 hit point instead. You can't use this feature again until you finish a long rest.",type:"active",level:11,class:"Barbarian",source:"default",tags:["survival"]},{id:"barbarian_persistent_rage",name:"Persistent Rage",description:"Your rage can't end early due to fatigue.",type:"passive",level:11,class:"Barbarian",source:"default",tags:["combat"]},{id:"barbarian_indomitable_might",name:"Indomitable Might",description:"Your Strength score increases by 4, and your maximum for that score becomes 24.",type:"passive",level:18,class:"Barbarian",effects:[{type:"stat_bonus",target:"STR",value:4},{type:"passive_modifier",target:"STR_max",value:24}],source:"default",tags:["ability"]},{id:"barbarian_primal_champion",name:"Primal Champion",description:"Your Strength and Constitution scores increase by 4, and your maximum for those scores becomes 24.",type:"passive",level:20,class:"Barbarian",effects:[{type:"stat_bonus",target:"STR",value:4},{type:"stat_bonus",target:"CON",value:4},{type:"passive_modifier",target:"STR_max",value:24},{type:"passive_modifier",target:"CON_max",value:24}],source:"default",tags:["ability"]},{id:"bardic_inspiration",name:"Bardic Inspiration",description:"You can inspire others through stirring words or music. To do so, you use a bonus action on your turn to choose one creature other than yourself within 60 feet of you who can hear you. That creature gains one Bardic Inspiration die, a d6.",type:"resource",level:1,class:"Bard",source:"default",tags:["support","resource"]},{id:"jack_of_all_trades",name:"Jack of All Trades",description:"You can add half your proficiency bonus, rounded down, to any ability check you make that doesn't already include your proficiency bonus.",type:"passive",level:2,class:"Bard",source:"default",tags:["skill"]},{id:"song_of_rest",name:"Song of Rest",description:"You can use soothing music or oration to help revitalize your wounded allies during a short rest. If you or any friendly creatures who can hear your performance regain hit points at the end of the short rest, each of those creatures regains an extra 1d6 hit points.",type:"passive",level:2,class:"Bard",source:"default",tags:["healing","support"]},{id:"bard_college",name:"Bard College",description:"At 3rd level, you delve into the advanced techniques of a bard college of your choice. Your choice grants you features at 3rd level and again at 6th and 14th level.",type:"passive",level:3,class:"Bard",source:"default",tags:["subclass"]},{id:"bardic_versatility",name:"Bardic Versatility",description:"Whenever you reach a level in this class that grants the Ability Score Improvement feature, you can do one of the following: Replace one of your skills with another skill from the bard list, gain proficiency in one skill of your choice, gain proficiency with one musical instrument of your choice, or gain proficiency with one tool of your choice.",type:"passive",level:4,class:"Bard",source:"default",tags:["skill","proficiency"]},{id:"font_of_inspiration",name:"Font of Inspiration",description:"When you roll initiative and have no uses of Bardic Inspiration left, you regain one use.",type:"passive",level:5,class:"Bard",source:"default",tags:["resource"]},{id:"countercharm",name:"Countercharm",description:"You gain the ability to use musical notes or words of power to disrupt mind-influencing effects. As an action, you can start a performance that lasts until the end of your next turn. During that time, you and any friendly creatures within 30 feet of you have advantage on saving throws against being frightened or charmed.",type:"active",level:6,class:"Bard",source:"default",tags:["support","defense"]},{id:"superior_inspiration",name:"Superior Inspiration",description:"When you roll initiative and have no uses of Bardic Inspiration left, you regain two uses.",type:"passive",level:10,class:"Bard",source:"default",tags:["resource"]},{id:"magical_secrets",name:"Magical Secrets",description:"You learn two spells of your choice from any class. A spell you choose must be of a level you can cast, as shown on the Bard table, or a cantrip. The chosen spells count as bard spells for you.",type:"passive",level:10,class:"Bard",source:"default",tags:["magic"]},{id:"unforgettable_face",name:"Unforgettable Face",description:"When you speak to a creature for the first time, you can choose one creature. That creature has disadvantage on attack rolls against you for 1 minute.",type:"active",level:14,class:"Bard",source:"default",tags:["social","defense"]},{id:"magical_secrets_2",name:"Magical Secrets",description:"You learn two spells of your choice from any class.",type:"passive",level:14,class:"Bard",source:"default",tags:["magic"]},{id:"bardic_inspiration_d8",name:"Bardic Inspiration (d8)",description:"Your Bardic Inspiration die changes to a d8.",type:"passive",level:15,class:"Bard",source:"default",tags:["resource"]},{id:"magical_secrets_3",name:"Magical Secrets",description:"You learn two spells of your choice from any class.",type:"passive",level:18,class:"Bard",source:"default",tags:["magic"]},{id:"bardic_inspiration_d10",name:"Bardic Inspiration (d10)",description:"Your Bardic Inspiration die changes to a d10.",type:"passive",level:20,class:"Bard",source:"default",tags:["resource"]},{id:"superior_inspiration_3",name:"Superior Inspiration",description:"When you roll initiative and have no uses of Bardic Inspiration left, you regain three uses.",type:"passive",level:20,class:"Bard",source:"default",tags:["resource"]},{id:"divine_domain",name:"Divine Domain",description:"Choose one domain related to your deity: Knowledge, Life, Light, Nature, Tempest, Trickery, or War. Each domain grants domain spells and other features at levels 1, 2, 6, 8, and 17.",type:"passive",level:1,class:"Cleric",source:"default",tags:["subclass","magic"]},{id:"divine_intervention",name:"Divine Intervention",description:"You can call on your deity to intervene on your behalf. Your deity intervenes by causing a effect related to their portfolio. You can use this feature once between long rests.",type:"active",level:10,class:"Cleric",source:"default",tags:["magic","divine"]},{id:"destroy_undead",name:"Destroy Undead",description:"When an undead fails its saving throw against your Turn Undead feature, the creature is instantly destroyed if its challenge rating is at or below a threshold shown on the Cleric table.",type:"passive",level:5,class:"Cleric",source:"default",tags:["combat","divine"]},{id:"divine_intervention_improved",name:"Divine Intervention (Improved)",description:"You can use Divine Intervention twice between long rests.",type:"active",level:20,class:"Cleric",source:"default",tags:["magic","divine"]},{id:"druidic",name:"Druidic",description:"You know Druidic, the secret language of druids. You can speak the language and use it to leave hidden messages. You and others who know this language automatically spot such a message. Others spot the message's presence with a successful DC 15 Wisdom (Perception) check but can't decipher it without magic.",type:"passive",level:1,class:"Druid",source:"default",tags:["language","secret"]},{id:"wild_shape",name:"Wild Shape",description:"You can use your action to magically assume the shape of a beast that you have seen before. You can transform into a beast with a challenge rating as shown on the Druid table.",type:"active",level:2,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"wild_shape_combat",name:"Wild Shape (Combat)",description:"You can transform into a beast with a challenge rating up to 1.",type:"passive",level:2,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"druid_circle",name:"Druid Circle",description:"At 2nd level, you choose to identify with a circle of druids. Your choice grants you features at 2nd level and again at 6th, 10th, and 14th level.",type:"passive",level:2,class:"Druid",source:"default",tags:["subclass"]},{id:"wild_shape_aquatic",name:"Wild Shape (Aquatic)",description:"You can transform into a beast with a swimming speed.",type:"passive",level:4,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"wild_shape_cr_2",name:"Wild Shape (CR 2)",description:"You can transform into a beast with a challenge rating up to 2.",type:"passive",level:8,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"wild_shape_cr_3",name:"Wild Shape (CR 3)",description:"You can transform into a beast with a challenge rating up to 3.",type:"passive",level:8,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"timeless_body",name:"Timeless Body",description:"You age slowly, appearing no older than you did at the start of your druidic studies.",type:"passive",level:18,class:"Druid",source:"default",tags:["ability"]},{id:"beast_spells",name:"Beast Spells",description:"You can cast many of your druid spells in any shape you assume using Wild Shape.",type:"passive",level:18,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"archdruid",name:"Archdruid",description:"You can use your Wild Shape an unlimited number of times.",type:"passive",level:20,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"fighting_style",name:"Fighting Style",description:"You adopt a style of fighting as your specialty. Choose one of the following: Archery, Defense, Dueling, Great Weapon Fighting, Protection, Two-Weapon Fighting, or Unarmed Fighting.",type:"passive",level:1,class:"Fighter",source:"default",tags:["combat","style"]},{id:"second_wind",name:"Second Wind",description:"You have a limited well of stamina you can draw on to protect yourself. As a bonus action, you can regain hit points equal to 1d10 + your fighter level.",type:"active",level:1,class:"Fighter",source:"default",tags:["healing","combat"]},{id:"action_surge",name:"Action Surge",description:"You can push yourself beyond your normal limits for a moment. On your turn, you can take one additional action.",type:"active",level:2,class:"Fighter",source:"default",tags:["combat"]},{id:"martial_archetype",name:"Martial Archetype",description:"At 3rd level, you choose an archetype that you strive to emulate in your combat styles. Your choice grants you features at 3rd level and again at 7th, 10th, 15th, and 18th level.",type:"passive",level:3,class:"Fighter",source:"default",tags:["subclass"]},{id:"fighter_extra_attack",name:"Extra Attack",description:"You can attack twice, instead of once, whenever you take the Attack action on your turn.",type:"passive",level:5,class:"Fighter",source:"default",tags:["combat"]},{id:"indomitable",name:"Indomitable",description:"You can reroll a saving throw that you fail. If you do so, you must use the new roll.",type:"active",level:9,class:"Fighter",source:"default",tags:["defense","combat"]},{id:"indomitable_2",name:"Indomitable (Twice)",description:"You can use Indomitable twice between long rests.",type:"active",level:13,class:"Fighter",source:"default",tags:["defense","combat"]},{id:"indomitable_3",name:"Indomitable (Thrice)",description:"You can use Indomitable three times between long rests.",type:"active",level:17,class:"Fighter",source:"default",tags:["defense","combat"]},{id:"action_surge_2",name:"Action Surge (Improved)",description:"You can use Action Surge twice between short rests.",type:"passive",level:17,class:"Fighter",source:"default",tags:["combat"]},{id:"unarmored_defense_monk",name:"Unarmored Defense",description:"Beginning at 1st level, while you are wearing no armor and not wielding a shield, your AC equals 10 + your Dexterity modifier + your Wisdom modifier.",type:"passive",level:1,class:"Monk",source:"default",tags:["defense"]},{id:"martial_arts",name:"Martial Arts",description:"You gain the following benefits while you are unarmed or wielding only monk weapons and you aren't wearing armor or wielding a shield: You can use Dexterity instead of Strength for attacks and damage rolls with your unarmed strikes and monk weapons, you can roll a d4 in place of the normal damage of your monk weapon or unarmed strike, and when you use the Attack action with an unarmed strike or a monk weapon, you can make one unarmed strike as a bonus action.",type:"passive",level:1,class:"Monk",source:"default",tags:["combat"]},{id:"ki",name:"Ki",description:"Starting at 2nd level, your training allows you to harness the mystic energy of ki. Your access to this energy is represented by a number of Ki points. You have a number of Ki points equal to your monk level.",type:"resource",level:2,class:"Monk",source:"default",tags:["resource","magic"]},{id:"flurry_of_blows",name:"Flurry of Blows",description:"Immediately after you take the Attack action on your turn, you can spend 1 Ki point to make two unarmed strikes as a bonus action.",type:"active",level:2,class:"Monk",source:"default",tags:["combat"]},{id:"patient_defense",name:"Patient Defense",description:"You can spend 1 Ki point to take the Dodge action as a bonus action on your turn.",type:"active",level:2,class:"Monk",source:"default",tags:["defense","combat"]},{id:"step_of_the_wind",name:"Step of the Wind",description:"You can spend 1 Ki point to take the Disengage or Dash action as a bonus action on your turn, and your jump distance is doubled for the turn.",type:"active",level:2,class:"Monk",source:"default",tags:["movement","combat"]},{id:"monastic_tradition",name:"Monastic Tradition",description:"When you reach 3rd level, you commit yourself to a monastic tradition. Your tradition grants you features at 3rd level and again at 6th, 11th, and 17th level.",type:"passive",level:3,class:"Monk",source:"default",tags:["subclass"]},{id:"slow_fall",name:"Slow Fall",description:"At 4th level, you can use your reaction when you fall to reduce any falling damage you take by an amount equal to five times your monk level.",type:"passive",level:4,class:"Monk",source:"default",tags:["defense","movement"]},{id:"extra_attack_monk",name:"Extra Attack",description:"You can attack twice, instead of once, whenever you take the Attack action on your turn.",type:"passive",level:5,class:"Monk",source:"default",tags:["combat"]},{id:"stunning_strike",name:"Stunning Strike",description:"Starting at 5th level, you can interfere with the flow of ki in an opponent's body. When you hit another creature with a melee weapon attack, you can spend 1 Ki point to attempt a stunning strike. The target must succeed on a Constitution saving throw or be stunned until the end of your next turn.",type:"active",level:5,class:"Monk",source:"default",tags:["combat"]},{id:"ki_empowered_strikes",name:"Ki-Empowered Strikes",description:"Starting at 6th level, your unarmed strikes count as magical for the purpose of overcoming resistance and immunity to nonmagical attacks and damage.",type:"passive",level:6,class:"Monk",source:"default",tags:["combat","magic"]},{id:"stillness_of_mind",name:"Stillness of Mind",description:"At 7th level, you can use your action to end one effect on yourself that is causing you to be charmed or frightened.",type:"active",level:7,class:"Monk",source:"default",tags:["defense"]},{id:"unarmored_movement",name:"Unarmored Movement",description:"Your speed increases by 10 feet while you are not wearing armor or wielding a shield. This bonus increases when you reach certain monk levels.",type:"passive",level:2,class:"Monk",effects:[{type:"passive_modifier",target:"speed",value:10,condition:"unarmored"}],source:"default",tags:["movement"]},{id:"pure_body",name:"Purity of Body",description:"At 10th level, your mastery of the ki flowing through you makes you immune to disease and poison.",type:"passive",level:10,class:"Monk",source:"default",tags:["defense","ability"]},{id:"tongue_of_the_sun_and_moon",name:"Tongue of the Sun and Moon",description:"At 13th level, you learn to touch the ki of other minds so that you understand all spoken languages. Moreover, any creature that can understand a language can understand what you say.",type:"passive",level:13,class:"Monk",source:"default",tags:["language","social"]},{id:"empty_body",name:"Empty Body",description:"At 18th level, you can spend 4 Ki points to start becoming invisible for 1 minute. During that time, you also have resistance to all damage but force damage.",type:"active",level:18,class:"Monk",source:"default",tags:["defense","magic"]},{id:"divine_sense",name:"Divine Sense",description:"As an action, you can detect good and evil. You can sense the presence of any celestial, fiend, or undead within 60 feet of you.",type:"active",level:1,class:"Paladin",source:"default",tags:["perception","divine"]},{id:"lay_on_hands",name:"Lay on Hands",description:"Your blessed touch can heal wounds. You have a pool of healing power that replenishes when you take a long rest. With that pool, you can restore a total number of hit points equal to your paladin level × 5.",type:"active",level:2,class:"Paladin",source:"default",tags:["healing","divine"]},{id:"fighting_style_paladin",name:"Fighting Style",description:"You adopt a style of fighting as your specialty. Choose one of the following: Defense, Dueling, Great Weapon Fighting, Protection, or Two-Weapon Fighting.",type:"passive",level:2,class:"Paladin",source:"default",tags:["combat","style"]},{id:"divine_smite",name:"Divine Smite",description:"When you hit a creature with a melee weapon attack, you can expend one spell slot to deal radiant damage to the target.",type:"active",level:2,class:"Paladin",source:"default",tags:["combat","divine"]},{id:"sacred_oath",name:"Sacred Oath",description:"When you reach 3rd level, you swear the oath that binds you as a paladin forever. Your choice grants you features at 3rd level and again at 7th, 15th, and 20th level.",type:"passive",level:3,class:"Paladin",source:"default",tags:["subclass","divine"]},{id:"aura_of_protection",name:"Aura of Protection",description:"Starting at 6th level, you and friendly creatures within 10 feet of you gain a bonus to all saving throws equal to your Charisma modifier (minimum of +1).",type:"passive",level:6,class:"Paladin",source:"default",tags:["defense","aura"]},{id:"aura_of_courage",name:"Aura of Courage",description:"Starting at 10th level, you and friendly creatures within 10 feet of you can't be frightened.",type:"passive",level:10,class:"Paladin",source:"default",tags:["defense","aura"]},{id:"improved_divine_smite",name:"Improved Divine Smite",description:"Starting at 11th level, you are so suffused with righteous might that all your melee weapon strikes carry divine power with them. Whenever you hit a creature with a melee weapon, the creature takes an extra 1d8 radiant damage.",type:"passive",level:11,class:"Paladin",source:"default",tags:["combat","divine"]},{id:"cleansing_touch",name:"Cleansing Touch",description:"At 14th level, you can use your action to end one spell or effect on yourself or one willing creature that you touch.",type:"active",level:14,class:"Paladin",source:"default",tags:["defense","divine"]},{id:"aura_improvements",name:"Aura Improvements",description:"At 18th level, the range of your auras increases to 30 feet.",type:"passive",level:18,class:"Paladin",source:"default",tags:["aura"]},{id:"favored_enemy",name:"Favored Enemy",description:"You have significant experience studying, tracking, hunting, and even talking to a certain type of enemy. Choose a type of favored enemy: aberrations, beasts, celestials, constructs, dragons, elementals, fey, fiends, giants, monstrosities, oozes, plants, or undead. You gain a bonus to damage rolls against creatures of the chosen type.",type:"passive",level:1,class:"Ranger",source:"default",tags:["combat"]},{id:"natural_explorer",name:"Natural Explorer",description:"You are a master of navigating the natural world. You choose a type of favored terrain: arctic, coast, desert, forest, grassland, mountain, swamp, or the Underdark. While traveling for an hour or more in your favored terrain, you gain the following benefits: Difficult terrain doesn't slow your group's travel, your group can't become lost except by magical means, and you remain alert to danger even when you are engaged in another activity.",type:"passive",level:1,class:"Ranger",source:"default",tags:["exploration"]},{id:"fighting_style_ranger",name:"Fighting Style",description:"You adopt a style of fighting as your specialty. Choose one of the following: Archery, Defense, Dueling, Great Weapon Fighting, Two-Weapon Fighting, or Mariner (if you have a swimming speed).",type:"passive",level:2,class:"Ranger",source:"default",tags:["combat","style"]},{id:"spellcasting_ranger",name:"Spellcasting",description:"By the time you reach 2nd level, you have learned to use the magical essence of nature to cast spells, much as a druid does.",type:"passive",level:2,class:"Ranger",source:"default",tags:["magic"]},{id:"ranger_archetype",name:"Ranger Archetype",description:"At 3rd level, you choose an archetype that you strive to emulate in your combat styles and techniques. Your choice grants you features at 3rd level and again at 5th, 7th, 11th, and 15th level.",type:"passive",level:3,class:"Ranger",source:"default",tags:["subclass"]},{id:"prime_awareness",name:"Prime-Aware Explorer",description:"At 6th level, your mastery of the wild allows you to navigate with ease. You can use the Hide action as a bonus action. You also gain an additional Favored Enemy and Favored Terrain.",type:"passive",level:6,class:"Ranger",source:"default",tags:["exploration","stealth"]},{id:"fleet_of_foot",name:"Fleet of Foot",description:"Your speed increases by 5 feet.",type:"passive",level:8,class:"Ranger",effects:[{type:"passive_modifier",target:"speed",value:5}],source:"default",tags:["movement"]},{id:"hide_in_plain_sight",name:"Hide in Plain Sight",description:"Starting at 10th level, you can remain perfectly still for long periods to blend in with your surroundings. You can spend 1 minute creating camouflage and gain advantage on Stealth checks.",type:"active",level:10,class:"Ranger",source:"default",tags:["stealth"]},{id:"vanish",name:"Vanish",description:"Starting at 14th level, you can use the Hide action as a bonus action on your turn. Also, you can't be tracked by nonmagical means.",type:"passive",level:14,class:"Ranger",source:"default",tags:["stealth"]},{id:"feral_senses",name:"Feral Senses",description:"At 18th level, you gain preternatural senses that help you fight creatures you can't see. When you attack a creature you can't see, your inability to see it doesn't impose disadvantage on your attack rolls. You are also aware of the location of any invisible creature within 30 feet of you.",type:"passive",level:18,class:"Ranger",source:"default",tags:["perception","combat"]},{id:"sneak_attack",name:"Sneak Attack",description:"You know how to strike subtly and exploit a foe's distraction. Once per turn, you can deal an extra 1d6 damage to one creature you hit with an attack if you have advantage on the attack roll.",type:"passive",level:1,class:"Rogue",source:"default",tags:["combat","damage"]},{id:"thieves_cant",name:"Thieves' Cant",description:"During your rogue training you learned thieves' cant, a secret mix of dialect, hand signs, and body language that allows you to hide messages in seemingly normal conversation.",type:"passive",level:1,class:"Rogue",source:"default",tags:["language","secret"]},{id:"cunning_action",name:"Cunning Action",description:"You can take a bonus action on each of your turns in combat. This action can be used only to take the Dash, Disengage, or Hide action.",type:"active",level:2,class:"Rogue",source:"default",tags:["combat","movement"]},{id:"roguish_archetype",name:"Roguish Archetype",description:"At 3rd level, you choose an archetype that you strive to emulate in your combat styles and techniques. Your choice grants you features at 3rd level and then again at 9th, 13th, and 17th level.",type:"passive",level:3,class:"Rogue",source:"default",tags:["subclass"]},{id:"ability_score_improvement_rogue",name:"Ability Score Improvement",description:"At 4th level, you can increase one ability score by 2 or two ability scores by 1.",type:"passive",level:4,class:"Rogue",source:"default",tags:["ability"]},{id:"uncanny_dodge",name:"Uncanny Dodge",description:"Starting at 5th level, when an attacker that you can see hits you with an attack, you can use your reaction to halve the attack's damage against you.",type:"active",level:5,class:"Rogue",source:"default",tags:["defense","combat"]},{id:"evasion",name:"Evasion",description:"Starting at 7th level, you can nimbly dodge out of the way of certain area effects. When you are subjected to an effect that allows you to make a Dexterity saving throw to take only half damage, you instead take no damage if you succeed and only half damage if you fail.",type:"passive",level:7,class:"Rogue",source:"default",tags:["defense"]},{id:"slippery_mind",name:"Slippery Mind",description:"At 11th level, you have acquired greater mental strength. You gain proficiency in Wisdom saving throws.",type:"passive",level:11,class:"Rogue",source:"default",tags:["defense"]},{id:"elusive",name:"Elusive",description:"Beginning at 18th level, you are so evasive that attackers rarely gain the upper hand against you. No attack roll has advantage against you while you aren't incapacitated.",type:"passive",level:18,class:"Rogue",source:"default",tags:["defense"]},{id:"stroke_of_luck",name:"Stroke of Luck",description:"At 20th level, you have an uncanny knack for succeeding when you need to. If your attack misses a target within range, you can turn the miss into a hit. Alternatively, if you fail an ability check, you can treat the d20 roll as a 20.",type:"active",level:20,class:"Rogue",source:"default",tags:["combat","luck"]},{id:"sorcerous_restoration",name:"Sorcerous Restoration",description:"You can regain 4 sorcery points on a short rest.",type:"passive",level:20,class:"Sorcerer",source:"default",tags:["resource"]},{id:"font_of_magic",name:"Font of Magic",description:"You can manipulate the weave of magic to your advantage. You have 2 sorcery points. You gain more as you level. You can use sorcery points to create additional spell slots or gain spell slots.",type:"resource",level:2,class:"Sorcerer",source:"default",tags:["resource","magic"]},{id:"metamagic",name:"Metamagic",description:"At 3rd level, you gain the ability to twist your spells to suit your needs. You gain two metamagic options of your choice: Careful Spell, Distant Spell, Empowered Spell, Extended Spell, Heightened Spell, Quickened Spell, Subtle Spell, Twinned Spell.",type:"active",level:3,class:"Sorcerer",source:"default",tags:["magic"]},{id:"sorcerous_origin",name:"Sorcerous Origin",description:"Choose a sorcerous origin, which describes the source of your magical power: Draconic Bloodline, Wild Magic, or another origin.",type:"passive",level:1,class:"Sorcerer",source:"default",tags:["subclass"]},{id:"metamagic_3",name:"Metamagic (3 options)",description:"At 10th level, you gain a third metamagic option.",type:"active",level:10,class:"Sorcerer",source:"default",tags:["magic"]},{id:"metamagic_4",name:"Metamagic (4 options)",description:"At 17th level, you gain a fourth metamagic option.",type:"active",level:17,class:"Sorcerer",source:"default",tags:["magic"]},{id:"otherworldly_patron",name:"Otherworldly Patron",description:"At 1st level, you have struck a bargain with an otherworldly being of power. Your choice grants you features at 1st level and again at 6th, 10th, and 14th level.",type:"passive",level:1,class:"Warlock",source:"default",tags:["subclass"]},{id:"pact_magic",name:"Pact Magic",description:"You have learned to delve into the secrets of magic to harness the power of your patron. You know two cantrips and a number of spells.",type:"passive",level:1,class:"Warlock",source:"default",tags:["magic"]},{id:"eldritch_master",name:"Eldritch Master",description:"At 20th level, you can draw on your inner reserve of magical power while entreating your patron to regain expended spell slots. You can regain all your warlock spell slots on a short or long rest.",type:"active",level:20,class:"Warlock",source:"default",tags:["magic","resource"]},{id:"mystic_arcanum",name:"Mystic Arcanum",description:"At 11th level, your patron bestows upon you the ability to cast a 6th-level spell. You gain additional spells at higher levels.",type:"passive",level:11,class:"Warlock",source:"default",tags:["magic"]},{id:"arcane_recovery",name:"Arcane Recovery",description:"You have learned to regain some of your magical energy by studying your spellbook. Once per day when you finish a short rest, you can recover expended spell slots whose combined level equals no more than half your wizard level.",type:"active",level:1,class:"Wizard",source:"default",tags:["magic","resource"]},{id:"arcane_tradition",name:"Arcane Tradition",description:"When you reach 2nd level, you choose an arcane tradition that shapes your practice of magic. Your choice grants you features at 2nd level and again at 6th, 10th, and 14th level.",type:"passive",level:2,class:"Wizard",source:"default",tags:["subclass"]},{id:"spell_mastery",name:"Spell Mastery",description:"At 18th level, you have achieved profound mastery over spells. Choose two 1st-level wizard spells that you know. You can cast these spells at their lowest level without expending a spell slot.",type:"passive",level:18,class:"Wizard",source:"default",tags:["magic"]},{id:"signature_spells",name:"Signature Spells",description:"When you reach 20th level, you gain mastery over two powerful spells. Choose two 3rd-level wizard spells that you know. You can cast these spells at their lowest level without expending a spell slot.",type:"passive",level:20,class:"Wizard",source:"default",tags:["magic"]}],ii=[{id:"human_versatile",name:"Versatile",description:"Humans gain proficiency in one skill of their choice.",race:"Human",source:"default",tags:["skill"]},{id:"human_extra_language",name:"Extra Language",description:"Humans can speak, read, and write one extra language of their choice.",race:"Human",source:"default",tags:["language"]},{id:"elf_darkvision",name:"Darkvision",description:"Accustomed to twilit forests and the night sky, elves have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Elf",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"elf_keen_senses",name:"Keen Senses",description:"Elves have proficiency in the Perception skill.",race:"Elf",source:"default",effects:[{type:"skill_proficiency",target:"perception",value:"proficient"}],tags:["skill","perception"]},{id:"elf_fey_ancestry",name:"Fey Ancestry",description:"Elves have advantage on saving throws against being charmed, and magic can't put them to sleep.",race:"Elf",source:"default",tags:["defense","magic"]},{id:"elf_trance",name:"Trance",description:"Elves don't need to sleep. Instead, they meditate deeply, remaining semiconscious, for 4 hours a day. After resting in this way, you gain the same benefit that a human does from 8 hours of sleep.",race:"Elf",source:"default",tags:["ability"]},{id:"dwarf_darkvision",name:"Darkvision",description:"Accustomed to life underground, dwarves have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Dwarf",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"dwarf_dwarven_resilience",name:"Dwarven Resilience",description:"Dwarves have advantage on saving throws against poison, and resistance against poison damage.",race:"Dwarf",source:"default",tags:["defense"]},{id:"dwarf_stonecunning",name:"Stonecunning",description:"Whenever you make an Intelligence (History) check related to the origin of stonework, you are considered proficient in the History skill and add double your proficiency bonus to the check.",race:"Dwarf",source:"default",tags:["skill","exploration"]},{id:"halfling_lucky",name:"Lucky",description:"When you roll a 1 on an attack roll, ability check, or saving throw, you can reroll the die and must use the new roll.",race:"Halfling",source:"default",tags:["luck"]},{id:"halfling_brave",name:"Brave",description:"Halflings have advantage on saving throws against being frightened.",race:"Halfling",source:"default",tags:["defense"]},{id:"halfling_halfling_nimbleness",name:"Halfling Nimbleness",description:"Halflings can move through the space of any creature that is larger than them.",race:"Halfling",source:"default",tags:["movement"]},{id:"dragonborn_draconic_ancestry",name:"Draconic Ancestry",description:"Dragonborn have draconic ancestry linked to a specific type of dragon. This determines their breath weapon and damage resistance.",race:"Dragonborn",source:"default",tags:["ancestry","combat"]},{id:"dragonborn_breath_weapon",name:"Breath Weapon",description:"Dragonborn can use their action to exhale destructive energy. Their draconic ancestry determines the size, shape, and damage type of the breath weapon.",race:"Dragonborn",source:"default",tags:["combat"]},{id:"dragonborn_damage_resistance",name:"Damage Resistance",description:"Dragonborn have resistance to the damage type associated with their draconic ancestry.",race:"Dragonborn",source:"default",tags:["defense"]},{id:"gnome_darkvision",name:"Darkvision",description:"Accustomed to life underground, gnomes have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Gnome",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"gnome_gnome_cunning",name:"Gnome Cunning",description:"Gnomes have advantage on all Intelligence, Wisdom, and Charisma saving throws against magic.",race:"Gnome",source:"default",tags:["defense","magic"]},{id:"half_elf_darkvision",name:"Darkvision",description:"Thanks to your elf blood, you have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Half-Elf",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"half_elf_fey_ancestry",name:"Fey Ancestry",description:"Half-elves have advantage on saving throws against being charmed, and magic can't put them to sleep.",race:"Half-Elf",source:"default",tags:["defense","magic"]},{id:"half_elf_skill_versatility",name:"Skill Versatility",description:"Half-elves gain proficiency in two skills of their choice.",race:"Half-Elf",source:"default",tags:["skill"]},{id:"half_orc_darkvision",name:"Darkvision",description:"Thanks to your orc blood, you have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Half-Orc",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"half_orc_relentless_endurance",name:"Relentless Endurance",description:"When you are reduced to 0 hit points but not killed outright, you can drop to 1 hit point instead. You can't use this feature again until you finish a long rest.",race:"Half-Orc",source:"default",tags:["survival"]},{id:"half_orc_savage_attacks",name:"Savage Attacks",description:"When you score a critical hit with a melee weapon attack, you can roll one of the weapon's damage dice one additional time and add it to the extra damage of the critical hit.",race:"Half-Orc",source:"default",tags:["combat","damage"]},{id:"tiefling_darkvision",name:"Darkvision",description:"Thanks to your infernal heritage, you have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Tiefling",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"tiefling_hellish_resistance",name:"Hellish Resistance",description:"Tieflings have resistance to fire damage.",race:"Tiefling",source:"default",tags:["defense"]},{id:"tiefling_infernal_legacy",name:"Infernal Legacy",description:"Tieflings know the thaumaturgy cantrip. When you reach 3rd level, you can cast the hellish rebuke spell as a 2nd-level spell once with this trait and regain the ability to do so when you finish a long rest. When you reach 5th level, you can cast the darkness spell once with this trait and regain the ability to do so when you finish a long rest. Charisma is your spellcasting ability for these spells.",race:"Tiefling",source:"default",tags:["magic","spell"]}],Ci=[{id:"athletics",name:"Athletics",ability:"STR",armorPenalty:!0,categories:["physical","exploration","combat"],source:"default",description:"Covers climbing, jumping, swimming, and other physical feats of strength. Use this skill when you need to scale walls, leap across chasms, swim in turbulent waters, or perform any other physical activity that raw strength can accomplish."},{id:"acrobatics",name:"Acrobatics",ability:"DEX",armorPenalty:!0,categories:["physical","exploration"],source:"default",description:"Covers balancing, tumbling, and maintaining footing in difficult situations. Use this skill to walk on tightropes, stay on your feet during earthquakes, perform gymnastic feats, and dodge falling objects or area effects."},{id:"sleight_of_hand",name:"Sleight of Hand",ability:"DEX",armorPenalty:!0,categories:["physical","criminal","subterfuge"],source:"default",description:"Covers manual dexterity and fine motor skills such as picking pockets, palming items, and performing magic tricks. Use this skill when you need to steal something unnoticed, hide an object on your person, or manipulate small objects with precision."},{id:"stealth",name:"Stealth",ability:"DEX",armorPenalty:!0,categories:["physical","subterfuge","exploration"],source:"default",description:"Covers hiding, moving silently, and avoiding detection. Use this skill when you want to sneak past guards, hide in shadows, stalk prey, or conceal yourself from enemies. Your environment matters—darkness and cover provide advantage."},{id:"arcana",name:"Arcana",ability:"INT",armorPenalty:!1,categories:["knowledge","magic"],source:"default",description:"Covers knowledge about magical theory, arcane traditions, magical creatures, and the planes. Use this skill to identify magical items, understand spells, recognize arcane symbols, and recall lore about wizards, dragons, and other magical phenomena."},{id:"history",name:"History",ability:"INT",armorPenalty:!1,categories:["knowledge"],source:"default",description:"Covers knowledge about historical events, legendary figures, ancient civilizations, and past conflicts. Use this skill to recall the origins of ruins, identify royal lineages, understand the significance of ancient documents, and recognize historical artifacts."},{id:"investigation",name:"Investigation",ability:"INT",armorPenalty:!1,categories:["knowledge","exploration"],source:"default",description:"Covers deductive reasoning, analyzing clues, and piecing together information. Use this skill when you need to deduce the composition of an object, follow tracks, interpret coded messages, or draw conclusions from scattered evidence."},{id:"nature",name:"Nature",ability:"INT",armorPenalty:!1,categories:["knowledge","environmental"],source:"default",description:"Covers knowledge about plants, animals, weather, and the natural world. Use this skill to identify plants and beasts, predict weather changes, understand terrain, and recall lore about the wilderness and its inhabitants."},{id:"religion",name:"Religion",ability:"INT",armorPenalty:!1,categories:["knowledge"],source:"default",description:"Covers knowledge about deities, religious traditions, divine magic, and the planes of existence. Use this skill to recognize religious symbols, understand divine spells, identify outsiders, and recall lore about gods, angels, and religious cults."},{id:"animal_handling",name:"Animal Handling",ability:"WIS",armorPenalty:!1,categories:["environmental","social"],source:"default",description:"Covers calming, training, and understanding animals. Use this skill when you need to control a mount, calm a frightened beast, read an animal's mood, or predict how an animal might react. This skill doesn't work on creatures with Intelligence higher than 2."},{id:"insight",name:"Insight",ability:"WIS",armorPenalty:!1,categories:["social","perception"],source:"default",description:"Covers reading people, detecting lies, and understanding motives. Use this skill to determine when someone is lying to you, sense hidden agendas, gauge someone's true feelings, or predict how someone might act in a social situation."},{id:"medicine",name:"Medicine",ability:"WIS",armorPenalty:!1,categories:["knowledge","practical"],source:"default",description:"Covers diagnosing illnesses, treating wounds, and stabilizing dying creatures. Use this skill to determine the cause of a strange illness, assess the severity of injuries, provide first aid, or stabilize a dying companion. This skill does not cover magical healing."},{id:"perception",name:"Perception",ability:"WIS",armorPenalty:!1,categories:["perception","exploration"],source:"default",description:"Covers awareness of your surroundings and noticing hidden things. Use this skill to spot hidden enemies, find secret doors, hear approaching creatures, detect ambushes, or notice unusual details in your environment. This is the most commonly used skill in the game."},{id:"survival",name:"Survival",ability:"WIS",armorPenalty:!1,categories:["environmental","exploration"],source:"default",description:"Covers following tracks, hunting, foraging, and navigating in the wilderness. Use this skill to follow creature tracks, find food and water, predict weather, navigate without a map, or avoid natural hazards. This skill is essential for wilderness adventures."},{id:"deception",name:"Deception",ability:"CHA",armorPenalty:!1,categories:["social","subterfuge"],source:"default",description:"Covers lying, misdirection, and hiding the truth. Use this skill when you need to convincingly tell a falsehood, maintain a cover identity, pass hidden messages, or trick someone into believing something that isn't true. Success depends on plausibility and your target's suspicions."},{id:"intimidation",name:"Intimidation",ability:"CHA",armorPenalty:!1,categories:["social","combat"],source:"default",description:"Covers frightening others and forcing compliance through threats. Use this skill when you want to scare someone into backing down, extract information through fear, force a prisoner to talk, or make an opponent hesitate. Physical presence and reputation can provide advantage."},{id:"performance",name:"Performance",ability:"CHA",armorPenalty:!1,categories:["social","entertainment"],source:"default",description:"Covers entertaining audiences through music, acting, storytelling, or other arts. Use this skill when you need to captivate an audience, earn money through performance, distract guards with entertainment, or pass as a traveling performer. Quality and audience receptiveness affect the DC."},{id:"persuasion",name:"Persuasion",ability:"CHA",armorPenalty:!1,categories:["social"],source:"default",description:"Covers influencing others through reason, charm, and good faith. Use this skill when you need to convince someone to see your point of view, negotiate favorable terms, get someone to do you a favor, or rally people to your cause. This skill works best when you're being honest."}],Bd=["physical","exploration","combat","criminal","subterfuge","knowledge","magic","environmental","social","perception","practical","entertainment"],gd={"appearance.bodyTypes":["slender","athletic","muscular","stocky"],"appearance.skinTones":["#F5E6D3","#E8C4A0","#D4A574","#C68642","#8D5524","#5C3317"],"appearance.hairColors":["#1C1C1C","#3B2414","#6A4E23","#A67B5B","#D4AF37","#E9C2A6","#B55239","#DC143C","#C0C0C0","#FFFFFF"],"appearance.hairStyles":["short","long","bald","braided","curly","wavy","straight","ponytail","mohawk","dreadlocks"],"appearance.eyeColors":["#3B2414","#6F4E37","#228B22","#4169E1","#708090","#000000"],"appearance.facialFeatures":["scar on cheek","tattoo on forehead","piercing","freckles","beard","mustache","clean-shaven","birthmark","sharp jawline","soft features"]};function ai(){const Q=AA.getInstance();for(const[A,B]of Object.entries(gd))Q.initializeDefaults(A,[...B])}function mo(){return AA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("appearance."))}function ei(){mo()||ai()}const Id=Object.values(wE),Qd=Object.entries(SI).map(([Q,A])=>({class:Q,cantrips:A.cantrips,spells_by_level:A.spells_by_level}));function oi(){const Q=AA.getInstance();Q.initializeDefaults("spells",Id);for(const A of Qd){const B=`spells.${A.class}`;Q.initializeDefaults(B,[A])}}function uo(){return AA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("spells"))}function $I(){uo()||oi()}const Ed=Object.values(Eg).map(Q=>({...Q,source:"default",spawnWeight:Q.spawnWeight??1,tags:Q.tags??[]}));function ti(){AA.getInstance().initializeDefaults("equipment",Ed)}function So(){return AA.getInstance().getRegisteredCategories().some(B=>B==="equipment")}function si(){So()||ti()}function Gi(){AA.getInstance().initializeDefaults("races",[...Ta])}function bo(){return AA.getInstance().getRegisteredCategories().some(B=>B==="races")}function ni(){bo()||Gi()}function hi(){AA.getInstance().initializeDefaults("races.data",[...Pa])}function po(){return AA.getInstance().getRegisteredCategories().some(B=>B==="races.data")}function Yo(){po()||hi()}function ci(){AA.getInstance().initializeDefaults("classes",[...Ka])}function Uo(){return AA.getInstance().getRegisteredCategories().some(B=>B==="classes")}function ri(){Uo()||ci()}function id(){ai(),oi(),ti(),Gi(),hi(),ci(),li(),di()}function Cd(){ei(),$I(),si(),ni(),Yo(),ri(),Di(),Wo()}function li(){const Q=AA.getInstance(),A={};for(const g of Ei)A[g.class]||(A[g.class]=[]),A[g.class].push(g);Q.initializeDefaults("classFeatures",[...Ei]);for(const[g,I]of Object.entries(A)){const E=`classFeatures.${g}`;Q.initializeDefaults(E,I)}const B={};for(const g of ii)B[g.race]||(B[g.race]=[]),B[g.race].push(g);Q.initializeDefaults("racialTraits",[...ii]);for(const[g,I]of Object.entries(B)){const E=`racialTraits.${g}`;Q.initializeDefaults(E,I)}}function ko(){return AA.getInstance().getRegisteredCategories().some(B=>B==="classFeatures"||B==="racialTraits")}function Di(){ko()||li()}function di(){const Q=AA.getInstance(),A={STR:[],DEX:[],CON:[],INT:[],WIS:[],CHA:[]};for(const B of Ci)A[B.ability].push(B);Q.initializeDefaults("skills",[...Ci]);for(const[B,g]of Object.entries(A)){const I=`skills.${B}`;Q.initializeDefaults(I,g)}}function Zo(){const Q=AA.getInstance();return Q.hasCustomData("skills")||Q.getDefaults("skills").length>0}function Wo(){Zo()||di()}class Ho{static select(A){ni();const B=AA.getInstance(),g=B.get("races"),I=B.getWeights("races"),E=B.getMode("races")||"default";return _A.select(g,I,A,E)}}const SC=class SC{static suggest(A,B){ri();const g=AA.getInstance(),I=g.get("classes"),E=this.calculateAllAffinities(A,I),i=this.calculateProbabilities(E),C=g.getWeights("classes"),a=this.applyCustomWeights(i,C,I),e=Object.entries(a).map(([o,t])=>[o,t]);return B.weightedChoice(e)}static calculateAllAffinities(A,B){const g={};for(const I of B)g[I]=this.calculateClassAffinity(A,I);return g}static calculateClassAffinity(A,B){let g=this.getCustomClassAudioPreferences(B);if(g||(g=za[B]),!g)return .5;let I=0;return I+=this.getTraitContribution(A,g.primary,g,1),g.secondary&&(I+=this.getTraitContribution(A,g.secondary,g,.5)),g.tertiary&&(I+=this.getTraitContribution(A,g.tertiary,g,.25)),I}static getCustomClassAudioPreferences(A){try{const g=AA.getInstance().get("classes.data");if(g&&Array.isArray(g)){const I=g.find(E=>E.name===A);if(I&&I.audio_preferences)return I.audio_preferences}}catch{}}static getTraitContribution(A,B,g,I){switch(B){case"bass":return A.bass_dominance*(g.bass||1)*I;case"treble":return A.treble_dominance*(g.treble||1)*I;case"mid":return A.mid_dominance*(g.mid||1)*I;case"amplitude":return A.average_amplitude*(g.amplitude||1)*I;case"chaos":{const E=A.bass_dominance,i=A.treble_dominance,C=A.mid_dominance;return(1-(Math.max(E,i,C)-Math.min(E,i,C)))*I}default:return 0}}static calculateProbabilities(A){const B=Object.keys(A),g=B.length;if(g===0)return{};const I=Object.values(A).reduce((t,s)=>t+s,0);if(I===0){const t=1/g,s={};for(const G of B)s[G]=t;return s}const E=this.BASELINE_PROBABILITY*g,i=1-E,C=E>=1?1/g:this.BASELINE_PROBABILITY,a=E>=1?0:i,e={};for(const t of B){const s=A[t]/I;e[t]=C+s*a}const o=Object.values(e).reduce((t,s)=>t+s,0);for(const t of B)e[t]/=o;return e}static applyCustomWeights(A,B,g){if(Object.keys(B).length===0)return A;const I=Object.values(B).reduce((a,e)=>a+Math.max(0,e),0);if(I===0)return A;const E={};for(const[a,e]of Object.entries(B))g.includes(a)&&(E[a]=Math.max(0,e)/I);const i=1-Object.values(E).reduce((a,e)=>a+e,0),C=Object.entries(A).filter(([a])=>!B[a]).reduce((a,[,e])=>a+e,0);for(const a of g)!B[a]&&A[a]&&(C>0?E[a]=A[a]/C*i:E[a]=i/g.length);return E}};SC.BASELINE_PROBABILITY=.04;let AQ=SC;class BQ{static getSpicedValue(A,B,g){let I;switch(A){case"bass":I=g.rms_energy??g.dynamic_range??B;break;case"mid":g.spectral_centroid!==void 0?I=Math.min(1,Math.max(0,(g.spectral_centroid-100)/9900)):I=g.dynamic_range??B;break;case"treble":g.zero_crossing_rate!==void 0?I=g.zero_crossing_rate:g.spectral_centroid!==void 0?I=Math.min(1,Math.max(0,(g.spectral_centroid-100)/9900)):I=B;break}return(B+I)/2}static createFrequencyMappings(A){const B=["STR","DEX","CON","INT","WIS","CHA"],g=new Map,I=A.shuffle(B),E=["bass","mid","treble"];for(let i=0;i<3;i++){const C=E[i],a=I[i*2],e=I[i*2+1],o=A.random()<.5;g.set(C,{abilities:[a,e],firstHasSpice:o})}return g}static calculateBaseScores(A,B){const{bass_dominance:g,mid_dominance:I,treble_dominance:E}=A,i=this.createFrequencyMappings(B),C={STR:8,DEX:8,CON:8,INT:8,WIS:8,CHA:8},a=3.5,e=3.5;for(const[o,t]of i){const[s,G]=t.abilities,n=t.firstHasSpice;let h;switch(o){case"bass":h=g;break;case"mid":h=I;break;case"treble":h=E;break}const c=n?this.getSpicedValue(o,h,A):h,d=n?h:this.getSpicedValue(o,h,A),l=B.random(),F=B.random();C[s]=Math.floor(8+l*e+c*a),C[G]=Math.floor(8+F*e+d*a)}return C}static applyRacialBonuses(A,B){const g=bI(B);if(!g)return console.warn(`Unknown race: "${B}", using no ability bonuses`),{...A};const I=g.ability_bonuses,E={...A};if(I)for(const[i,C]of Object.entries(I)){const a=i;E[a]=Math.min(20,(E[a]||0)+(C||0))}return E}static calculateModifiers(A){return{STR:Math.floor((A.STR-10)/2),DEX:Math.floor((A.DEX-10)/2),CON:Math.floor((A.CON-10)/2),INT:Math.floor((A.INT-10)/2),WIS:Math.floor((A.WIS-10)/2),CHA:Math.floor((A.CHA-10)/2)}}}class fo{static getSkillListDefinition(A){try{const g=AA.getInstance().get("skillLists");return Array.isArray(g)?g.find(I=>I.class===A):void 0}catch{return}}static assignSkills(A,B,g){const I=XA.getInstance(),E=I.getAllSkills(),i={};for(const s of E)i[s.id]="none";const C=RE(A);if(!C)return console.warn(`SkillAssigner: Unknown class "${A}", using default skill assignment`),i;const a=this.validateSkills(C.available_skills,I),e=g?this.filterSkillsByPrerequisites(a,I,g):a,o=this.getSkillListDefinition(A),t=this.selectSkills(e,C.skill_count,B,o?.selectionWeights);for(const s of t)i[s]="proficient";if(C.has_expertise&&C.expertise_count){const s=this.selectSkills(t,C.expertise_count,B);for(const G of s)i[G]="expertise"}return i}static validateSkills(A,B){const g=[];for(const I of A)B.isValidSkill(I)?g.push(I):console.warn(`SkillAssigner: Invalid skill ID "${I}" not found in SkillQuery. Skipping.`);return g}static filterSkillsByPrerequisites(A,B,g){const I=[];for(const E of A){const i=B.getSkill(E);i&&(i.prerequisites&&!EB.validateSkillPrerequisites(i.prerequisites,g).valid||I.push(E))}return I}static selectSkills(A,B,g,I){if(!I||I.mode==="default")return this.selectSkillsEqualWeight(A,B,g);const{weights:E,mode:i}=I,C=[];for(const o of A){const t=E[o];if(t!==0)if(i==="absolute"){if(t!==void 0){const s=Math.round(t*10);for(let G=0;G<s;G++)C.push(o)}}else{const G=Math.round((t??1)*10);for(let n=0;n<G;n++)C.push(o)}}if(C.length===0)return this.selectSkillsEqualWeight(A,B,g);for(let o=C.length-1;o>0;o--){const t=Math.floor(g.random()*(o+1));[C[o],C[t]]=[C[t],C[o]]}const a=[],e=new Set;for(const o of C)if(!e.has(o)&&(a.push(o),e.add(o),a.length>=B))break;return a}static selectSkillsEqualWeight(A,B,g){const I=[...A];for(let E=I.length-1;E>0;E--){const i=Math.floor(g.random()*(E+1));[I[E],I[i]]=[I[i],I[E]]}return I.slice(0,B)}}const ad=["Wizard","Sorcerer","Warlock","Bard","Cleric","Druid","Paladin"];class No{static generate(A,B,g){ei();const I=new QB(A),E=AA.getInstance(),i=E.get("appearance.bodyTypes"),C=E.getWeights("appearance.bodyTypes"),a=E.getMode("appearance.bodyTypes")||"default",e=E.get("appearance.skinTones"),o=E.getWeights("appearance.skinTones"),t=E.getMode("appearance.skinTones")||"default",s=E.get("appearance.hairStyles"),G=E.getWeights("appearance.hairStyles"),n=E.getMode("appearance.hairStyles")||"default",h=E.get("appearance.hairColors"),c=E.getWeights("appearance.hairColors"),d=E.getMode("appearance.hairColors")||"default",l=E.get("appearance.eyeColors"),F=E.getWeights("appearance.eyeColors"),m=E.getMode("appearance.eyeColors")||"default",y=E.get("appearance.facialFeatures"),p=E.getWeights("appearance.facialFeatures"),k=E.getMode("appearance.facialFeatures")||"default",H=_A.select(i,C,I,a),T=_A.select(e,o,I,t),q=_A.select(s,G,I,n),v=_A.select(h,c,I,d),EA=_A.select(l,F,I,m),aA=I.randomInt(1,4),GA=_A.selectMultiple(y,p,I,aA,k),rA=g.color_palette,P=rA?.primary_color,BA=rA?.secondary_color,wA=rA?.accent_color;let yA;return ad.includes(B)&&(yA=this.generateAuraColor(B,rA?.primary_color)),{body_type:H,skin_tone:T,hair_style:q,hair_color:v,eye_color:EA,facial_features:GA,primary_color:P,secondary_color:BA,accent_color:wA,aura_color:yA}}static generateAuraColor(A,B){return B?this.adjustColorBrightness(B,1.3):{Wizard:"#4169E1",Sorcerer:"#DC143C",Warlock:"#8B008B",Bard:"#FFD700",Cleric:"#F0E68C",Druid:"#228B22",Paladin:"#FFE4B5"}[A]||"#FFFFFF"}static adjustColorBrightness(A,B){const g=A.replace("#",""),I=parseInt(g.substring(0,2),16),E=parseInt(g.substring(2,4),16),i=parseInt(g.substring(4,6),16),C=Math.min(255,Math.floor(I*B)),a=Math.min(255,Math.floor(E*B)),e=Math.min(255,Math.floor(i*B)),o=t=>t.toString(16).padStart(2,"0");return`#${o(C)}${o(a)}${o(e)}`}}class Fi{static isSpellcaster(A){return["Bard","Cleric","Druid","Paladin","Ranger","Sorcerer","Warlock","Wizard"].includes(A)}static getSpellSlots(A,B){if(!this.isSpellcaster(A))return{};const g={};for(let E=0;E<=9;E++)g[E]={total:0,used:0};const I=SE(A,B);if(!I)return g;for(const[E,i]of Object.entries(I)){const C=parseInt(E,10);g[C]={total:i,used:0}}return g}static getCantrips(A){if(!this.isSpellcaster(A))return[];$I();const B=AA.getInstance(),g=uE(A),I=g?[...g.cantrips]:[],E=`spells.${A}`,i=B.get(E);for(const C of i){const a=C;if(a.cantrips&&a.cantrips.length>0)for(const e of a.cantrips)I.includes(e)||I.push(e)}return I}static getKnownSpells(A,B,g){if(!this.isSpellcaster(A))return[];$I();const I=AA.getInstance(),E=uE(A);if(!E||!E.spells_by_level)return[];[...E.cantrips];const i={};for(const[t,s]of Object.entries(E.spells_by_level))i[Number(t)]=[...s];const C=`spells.${A}`,a=I.get(C);for(const t of a){const s=t;if(s.cantrips&&s.cantrips.length>0)for(const G of s.cantrips);if(s.spells_by_level)for(const[G,n]of Object.entries(s.spells_by_level)){const h=Number(G);i[h]||(i[h]=[]);for(const c of n)i[h].includes(c)||i[h].push(c)}}const e={spells_by_level:i},o=[];for(let t=1;t<=B&&t<=9;t++){const s=e.spells_by_level[t];s&&s.length>0&&o.push(...s)}return g?this.filterSpellsByPrerequisites(o,g):o}static filterSpellsByPrerequisites(A,B){const g=[];for(const I of A){const E=wE[I];if(!E){g.push(I);continue}E.prerequisites&&!hB.validateSpellPrerequisites(E.prerequisites,B).valid||g.push(I)}return g}static initializeSpells(A,B,g){return{spell_slots:this.getSpellSlots(A,B),known_spells:this.getKnownSpells(A,B,g),cantrips:this.getCantrips(A)}}static getSpellCountAtLevel(A,B){return B[A]?.total||0}static useSpellSlot(A,B){if(B<1||B>9)throw new Error(`Invalid spell level: ${B}. Must be between 1 and 9.`);const g={...A},I=g[B];return I&&I.used<I.total&&(g[B]={...I,used:I.used+1}),g}static restoreSpellSlots(A,B){const g={...A};if(B!==void 0){const I=g[B];I&&(g[B]={...I,used:0})}else for(let I=1;I<=9;I++){const E=g[I];E&&(g[I]={...E,used:0})}return g}static filterCharacterSpells(A){if(!A.spells)return A;const B=this.filterSpellsByPrerequisites(A.spells.known_spells||[],A),g=this.filterSpellsByPrerequisites(A.spells.cantrips||[],A);return{...A,spells:{...A.spells,known_spells:B,cantrips:g}}}}const Mi={Barbarian:{weapons:["Greataxe","Handaxe"],armor:["No Armor"],items:["Explorer's Pack","Javelin"]},Bard:{weapons:["Rapier","Dagger","Dagger"],armor:["Leather Armor"],items:["Lute","Entertainer's Pack"]},Cleric:{weapons:["Mace","Light Crossbow"],armor:["Scale Mail","Shield"],items:["Holy Symbol","Priest's Pack","Healer's Kit"]},Druid:{weapons:["Quarterstaff","Dagger"],armor:["Leather Armor","Shield"],items:["Druidic Focus","Explorer's Pack"]},Fighter:{weapons:["Longsword"],armor:["Chain Mail","Shield"],items:["Martial Melee Weapon","Bedroll","Rope"]},Monk:{weapons:["Shortsword","Martial Arts"],armor:["No Armor"],items:["Insignia","Traveler's Pack","Dart"]},Paladin:{weapons:["Longsword"],armor:["Chain Mail","Shield"],items:["Holy Symbol","Priest's Pack"]},Ranger:{weapons:["Longsword","Shortsword","Longbow","Dagger"],armor:["Leather Armor"],items:["Explorer's Pack"]},Rogue:{weapons:["Rapier","Hand Crossbow","Dagger"],armor:["Leather Armor"],items:["Burglar's Pack","Thieves' Tools"]},Sorcerer:{weapons:["Light Crossbow","Dagger"],armor:["Leather Armor"],items:["Arcane Focus","Dungeoneer's Pack"]},Warlock:{weapons:["Light Crossbow","Dagger"],armor:["Leather Armor"],items:["Arcane Focus","Scholar's Pack"]},Wizard:{weapons:["Quarterstaff","Dagger"],armor:["No Armor"],items:["Spellbook","Component Pouch","Scholar's Pack","Ink & Quill"]}};function Jo(Q){if(Q in Mi)return Mi[Q];try{const A=AA.getInstance(),B=`classStartingEquipment.${Q}`,g=A.get(B);if(g&&Array.isArray(g)&&g.length>0){const I=g[0];return{weapons:I.weapons,armor:I.armor,items:I.items}}}catch{}}function wi(Q,A,B){Q.ability_scores[A]+=B;const g=Q.ability_scores[A];Q.ability_modifiers[A]=Math.floor((g-10)/2)}function yi(Q,A,B){const g=Q.skills[A];if(!g||g==="none"){Q.skills[A]=B;return}B==="expertise"&&(Q.skills[A]=B)}class HA{static equipItem(A,B,g){const I={applied:!1,count:0,errors:[]};if(A.equipment_effects||(A.equipment_effects=[]),this.findEquipmentEffect(A,B.name,g))return I.applied=!0,I;if(B.properties){const C=this.validateRequirements(A,B,B.properties);if(C.length>0)return I.errors.push(...C),I}const i={source:B.name,instanceId:g,effects:B.properties?[...B.properties]:[],features:[],skills:[],spells:[]};if(B.properties)for(const C of B.properties)try{this.applyProperty(A,C,B.name),I.count++}catch(a){const e=a instanceof Error?a.message:String(a);I.errors.push(`Failed to apply property from ${B.name}: ${e}`)}return B.grantsFeatures&&(this.applyEquipmentFeatures(A,B,g,i.features),I.count+=i.features.length),B.grantsSkills&&(this.applyEquipmentSkills(A,B,g,i.skills),I.count+=i.skills.length),B.grantsSpells&&(i.spells=B.grantsSpells.map(C=>({spellId:C.spellId,level:C.level,uses:C.uses,recharge:C.recharge})),this.addSpellsToCharacter(A,B.grantsSpells),I.count+=i.spells.length),A.equipment_effects.push(i),I.applied=I.errors.length===0,I}static unequipItem(A,B,g){const I={applied:!1,count:0,errors:[]};if(!A.equipment_effects)return I.errors.push("No equipment effects found on character"),I;const E=A.equipment_effects.findIndex(C=>C.source===B&&C.instanceId===g);if(E===-1)return I.errors.push(`Equipment "${B}" effects not found`),I;const i=A.equipment_effects[E];return i.effects.length>0&&(this.removeProperties(A,i.effects),I.count+=i.effects.length),i.features.length>0&&(this.removeEquipmentFeatures(A,B,g),I.count+=i.features.length),i.skills.length>0&&(this.removeEquipmentSkills(A,i.skills),I.count+=i.skills.length),i.spells&&i.spells.length>0&&(this.removeSpellsFromCharacter(A,i.spells),I.count+=i.spells.length),A.equipment_effects.splice(E,1),I.applied=I.count>0,I}static reapplyEquipmentEffects(A){const B={applied:!1,count:0,errors:[]};if(!A.equipment_effects||A.equipment_effects.length===0)return B;const g=[...A.equipment_effects];A.equipment_effects=[];for(const I of g){const E={source:I.source,instanceId:I.instanceId,effects:[...I.effects],features:[...I.features],skills:[...I.skills],spells:I.spells?[...I.spells]:[]};for(const i of I.effects)try{this.applyProperty(A,i,I.source),B.count++}catch(C){const a=C instanceof Error?C.message:String(C);B.errors.push(`Failed to reapply property from ${I.source}: ${a}`)}for(const i of I.features)this.addFeatureToCharacter(A,i),B.count++;for(const i of I.skills)this.addSkillToCharacter(A,i),B.count++;I.spells&&(this.addSpellsToCharacter(A,I.spells),B.count+=I.spells.length),A.equipment_effects.push(E)}return B.applied=B.count>0,B}static getActiveEffects(A){if(!A.equipment_effects)return[];const B=[];for(const g of A.equipment_effects)B.push(...g.effects);return B}static evaluateACFormula(A,B){const g=A.trim();if(/^\d+$/.test(g))return parseInt(g,10);const I=g.match(/^(\d+)\s*\+\s*min\(DEX,\s*(\d+)\)$/i);if(I){const i=parseInt(I[1],10),C=parseInt(I[2],10);return i+Math.min(B,C)}const E=g.match(/^(\d+)\s*\+\s*DEX$/i);if(E)return parseInt(E[1],10)+B;throw new Error(`Unknown AC formula: "${A}"`)}static applyProperty(A,B,g){if(!(B.condition&&!this.checkCondition(B.condition,A)))switch(B.type){case"stat_bonus":case"skill_proficiency":case"ability_unlock":case"passive_modifier":this.applyPropertyViaFeatureEffectApplier(A,B);break;case"special_property":this.trackSpecialProperty(A,B,g);break;case"damage_bonus":this.trackDamageBonus(A,B,g);break;case"stat_requirement":this.trackStatRequirement(A,B,g);break;default:throw new Error(`Unknown property type: ${B.type}`)}}static applyPropertyViaFeatureEffectApplier(A,B){switch(B.type){case"stat_bonus":this.applyStatBonus(A,B);break;case"skill_proficiency":this.applySkillProficiency(A,B);break;case"ability_unlock":this.applyAbilityUnlock(A,B);break;case"passive_modifier":this.applyPassiveModifier(A,B);break}}static applyStatBonus(A,B){const g=B.target,I=B.value;if(YB(g)){wi(A,g,I);return}}static applySkillProficiency(A,B){const g=B.target.toLowerCase(),I=B.value;yi(A,g,I)}static applyAbilityUnlock(A,B){}static applyPassiveModifier(A,B){const g=B.target,I=B.value;if(g==="speed"){A.speed+=I;return}if(g==="ac"||g==="armor_class"){if(typeof I=="string"){const E=A.ability_modifiers.DEX??0;A.armor_class=HA.evaluateACFormula(I,E)}else A.armor_class+=I;return}if(g==="max_hp"||g==="hp_max"){A.hp.max+=I,A.hp.current+=I;return}}static trackSpecialProperty(A,B,g){}static trackDamageBonus(A,B,g){}static removeProperties(A,B){for(let g=B.length-1;g>=0;g--){const I=B[g];switch(I.type){case"stat_bonus":this.removeStatBonus(A,I);break;case"skill_proficiency":this.removeSkillProficiency(A,I);break;case"passive_modifier":this.removePassiveModifier(A,I);break}}}static removeStatBonus(A,B){const g=B.target,I=B.value;YB(g)&&wi(A,g,-I)}static removeSkillProficiency(A,B){const g=B.target.toLowerCase();A.skills[g]="none"}static removePassiveModifier(A,B){const g=B.target,I=B.value;g==="speed"?A.speed-=I:g==="ac"||g==="armor_class"?typeof I=="string"?A.armor_class=10+(A.ability_modifiers.DEX??0):A.armor_class-=I:(g==="max_hp"||g==="hp_max")&&(A.hp.max-=I,A.hp.current=Math.min(A.hp.current,A.hp.max))}static applyEquipmentFeatures(A,B,g,I){if(B.grantsFeatures)for(const E of B.grantsFeatures)if(typeof E=="string"){const i=YA.getInstance(),C=i.getClassFeatureById(E),a=C?void 0:i.getRacialTraitById(E);if(C||a){const o={featureId:E,source:"equipment",equipmentName:B.name,instanceId:g,sourceType:B.source??"default"};I.push(o),this.addFeatureToCharacter(A,o)}}else{const i={featureId:E.id,source:"equipment",equipmentName:B.name,instanceId:g,sourceType:B.source??"default"};if(I.push(i),this.addFeatureToCharacter(A,i),E.effects)for(const C of E.effects)this.applyProperty(A,C,B.name)}}static applyEquipmentSkills(A,B,g,I){if(B.grantsSkills)for(const E of B.grantsSkills){const i={skillId:E.skillId,level:E.level,source:"equipment",equipmentName:B.name,instanceId:g,sourceType:B.source??"default"};I.push(i),this.addSkillToCharacter(A,i)}}static addSpellsToCharacter(A,B){A.spells||(A.spells={spell_slots:{},known_spells:[],cantrips:[]});for(const g of B)g.level===0?A.spells.cantrips.includes(g.spellId)||A.spells.cantrips.push(g.spellId):A.spells.known_spells.includes(g.spellId)||A.spells.known_spells.push(g.spellId)}static removeSpellsFromCharacter(A,B){if(A.spells)for(const g of B)if(g.level===0){const I=A.spells.cantrips.indexOf(g.spellId);I>-1&&A.spells.cantrips.splice(I,1)}else{const I=A.spells.known_spells.indexOf(g.spellId);I>-1&&A.spells.known_spells.splice(I,1)}}static addFeatureToCharacter(A,B){A.class_features.includes(B.featureId)||A.class_features.push(B.featureId)}static addSkillToCharacter(A,B){const g=B.skillId.toLowerCase();yi(A,g,B.level)}static removeEquipmentFeatures(A,B,g){if(!A.equipment_effects)return;const I=A.equipment_effects.filter(E=>E.source===B&&E.instanceId===g).flatMap(E=>E.features);for(const E of I){const i=A.class_features.indexOf(E.featureId);i>-1&&A.class_features.splice(i,1)}}static removeEquipmentSkills(A,B){for(const g of B){const I=g.skillId.toLowerCase();A.skills[I]="none"}}static checkCondition(A,B){switch(A.type){case"while_equipped":return!0;case"on_hit":case"on_damage_taken":return!1;case"wielder_race":return B.race===A.value;case"wielder_class":return B.class===A.value;case"at_time_of_day":return!0;case"vs_creature_type":return!1;case"custom":return!0;default:return!0}}static findEquipmentEffect(A,B,g){if(A.equipment_effects)return A.equipment_effects.find(I=>I.source===B&&I.instanceId===g)}static validateRequirements(A,B,g){const I=[];for(const E of g)if(E.type==="stat_requirement"){const i=E.target,C=E.value;if(YB(i)){const a=A.ability_scores[i];a<C&&I.push(`${B.name} requires ${i} ${C}, but character has ${i} ${a}`)}}return I}static trackStatRequirement(A,B,g){}}class Xg{static ensureInitialized(){si()}static getEquipmentDataStatic(A){return Xg.getEquipmentData(A)}static getEquipmentData(A){return AA.getInstance().get("equipment").find(I=>I.name===A)}static getStartingEquipment(A){this.ensureInitialized();const B=Jo(A);return B?{weapons:[...B.weapons],armor:[...B.armor],items:[...B.items]}:{weapons:[],armor:[],items:[]}}static initializeEquipment(A){this.ensureInitialized();const B=this.getStartingEquipment(A),g=[],I=[],E=[],i=[...B.weapons,...B.armor,...B.items];for(const a of i){const e=this.getEquipmentData(a);if(e){let o;e.type==="weapon"?o=g:e.type==="armor"?o=I:o=E;const t=o.find(s=>s.name===a);t?t.quantity+=1:o.push({name:a,quantity:1,equipped:!1})}else{console.warn(`EquipmentGenerator: Unknown item "${a}" in starting equipment.`);const o=E.find(t=>t.name===a);o?o.quantity+=1:E.push({name:a,quantity:1,equipped:!1})}}const C=this.getAmmunitionType(A,B.weapons);if(C){const a=this.getAmmunitionQuantity(A),e=E.find(o=>o.name===C);e?e.quantity+=a:E.push({name:C,quantity:a,equipped:!1})}return g.length>0&&(g[0].equipped=!0),I.length>0&&(I[0].equipped=!0),{weapons:g,armor:I,items:E,totalWeight:this.calculateTotalWeight(g,I,E),equippedWeight:this.calculateEquippedWeight(g,I,E)}}static addItem(A,B,g=1){this.ensureInitialized();const I=this.getEquipmentData(B);if(!I)return A;const E=this.cloneEquipment(A);let i;I.type==="weapon"?i=E.weapons:I.type==="armor"?i=E.armor:i=E.items;const C=i.find(a=>a.name===B);return C?g>0&&(C.quantity+=g):i.push({name:B,quantity:Math.max(0,g),equipped:!1}),E.totalWeight=this.calculateTotalWeight(E.weapons,E.armor,E.items),E.equippedWeight=this.calculateEquippedWeight(E.weapons,E.armor,E.items),E}static removeItem(A,B,g=1){if(this.ensureInitialized(),g<=0)return A;const I=this.cloneEquipment(A);let E;const i=this.getEquipmentData(B);if(!i)return A;i.type==="weapon"?E=I.weapons:i.type==="armor"?E=I.armor:E=I.items;const C=E.findIndex(a=>a.name===B);return C!==-1&&(E[C].quantity>g?E[C].quantity-=g:E.splice(C,1)),I.totalWeight=this.calculateTotalWeight(I.weapons,I.armor,I.items),I.equippedWeight=this.calculateEquippedWeight(I.weapons,I.armor,I.items),I}static equipItem(A,B,g){this.ensureInitialized();const I=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=I.weapons:E.type==="armor"?i=I.armor:i=I.items;const C=i.find(a=>a.name===B);if(C&&(C.equipped=!0,g)){const a=C.instanceId;HA.equipItem(g,E,a)}return I.equippedWeight=this.calculateEquippedWeight(I.weapons,I.armor,I.items),I}static unequipItem(A,B,g){this.ensureInitialized();const I=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=I.weapons:E.type==="armor"?i=I.armor:i=I.items;const C=i.find(a=>a.name===B);if(C&&(C.equipped=!1,g)){const a=C.instanceId;HA.unequipItem(g,B,a)}return I.equippedWeight=this.calculateEquippedWeight(I.weapons,I.armor,I.items),I}static getInventoryList(A){return[...A.weapons,...A.armor,...A.items]}static getEquipmentByType(A,B){return A[B]}static calculateTotalWeight(A,B,g){let I=0;for(const E of A){const i=this.getEquipmentData(E.name);i&&(I+=i.weight*E.quantity)}for(const E of B){const i=this.getEquipmentData(E.name);i&&(I+=i.weight*E.quantity)}for(const E of g){const i=this.getEquipmentData(E.name);i&&(I+=i.weight*E.quantity)}return Math.round(I*100)/100}static calculateEquippedWeight(A,B,g){let I=0;for(const E of A)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(I+=i.weight)}for(const E of B)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(I+=i.weight)}for(const E of g)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(I+=i.weight)}return Math.round(I*100)/100}static cloneEquipment(A){return{weapons:A.weapons.map(B=>({...B})),armor:A.armor.map(B=>({...B})),items:A.items.map(B=>({...B})),totalWeight:A.totalWeight,equippedWeight:A.equippedWeight}}static getAmmunitionType(A,B){const g=B.some(C=>C==="Longbow"),I=B.some(C=>C==="Shortbow"),E=B.some(C=>C==="Light Crossbow"),i=B.some(C=>C==="Hand Crossbow");return g||I?"Arrow":E||i?"Bolt":null}static getAmmunitionQuantity(A){return{Ranger:20,Fighter:20,Rogue:20}[A]||0}static addModification(A,B,g,I,E){this.ensureInitialized();const i=this.cloneEquipment(A),C=this.getEquipmentData(B);if(!C)return A;let a;C.type==="weapon"?a=i.weapons:C.type==="armor"?a=i.armor:a=i.items;const e=a.find(t=>t.name===B);if(!e)return A;e.modifications||(e.modifications=[]),!I&&!e.instanceId&&(e.instanceId=`${B}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`);const o=I||e.instanceId;return e.modifications.push(g),e.equipped&&E&&(HA.unequipItem(E,B,o),this.applyCombinedEffects(E,C,g,o)),i}static removeModification(A,B,g,I){this.ensureInitialized();const E=this.cloneEquipment(A),i=this.getEquipmentData(B);if(!i)return A;let C;i.type==="weapon"?C=E.weapons:i.type==="armor"?C=E.armor:C=E.items;const a=C.find(s=>s.name===B);if(!a||!a.modifications)return A;const e=a.equipped,o=a.instanceId,t=a.modifications.findIndex(s=>s.id===g);if(t!==-1&&a.modifications.splice(t,1),e&&I&&(HA.unequipItem(I,B,o),HA.equipItem(I,i,o),a.modifications))for(const s of a.modifications)this.applyCombinedEffects(I,i,s,o);return E}static getActiveEffects(A,B,g){this.ensureInitialized();const I=this.getEquipmentData(B);if(!I)return[];let E;I.type==="weapon"?E=A.weapons:I.type==="armor"?E=A.armor:E=A.items;const i=E.find(a=>a.name===B&&(!g||a.instanceId===g));if(!i)return[];const C=I.properties?[...I.properties]:[];if(i.modifications)for(const a of i.modifications)a.properties&&C.push(...a.properties);return C}static applyCombinedEffects(A,B,g,I){const E={...B,properties:[...B.properties||[],...g.properties],grantsFeatures:g.addsFeatures,grantsSkills:g.addsSkills,grantsSpells:g.addsSpells};HA.equipItem(A,E,I)}}class vg{static applyFeatureEffects(A,B){const g={applied:!1,count:0,errors:[]};if(!B.effects||B.effects.length===0)return g;for(const I of B.effects)try{this.applySingleEffect(A,I,B.id),g.applied=!0,g.count++}catch(E){const i=E instanceof Error?E.message:String(E);g.errors.push(`Failed to apply effect from ${B.id}: ${i}`)}return g}static applyMultipleEffects(A,B){const g={applied:!1,count:0,errors:[]};for(const I of B){const E=this.applyFeatureEffects(A,I);g.applied=g.applied||E.applied,g.count+=E.count,g.errors.push(...E.errors)}return g}static applySingleEffect(A,B,g){switch(B.type){case"stat_bonus":this.applyStatBonus(A,B);break;case"skill_proficiency":this.applySkillProficiency(A,B);break;case"ability_unlock":this.applyAbilityUnlock(A,B);break;case"passive_modifier":this.applyPassiveModifier(A,B);break;case"resource_grant":this.applyResourceGrant(A,B);break;case"spell_slot_bonus":this.applySpellSlotBonus(A,B);break;default:throw new Error(`Unknown effect type: ${B.type}`)}}static applyStatBonus(A,B){const g=B.target,I=B.value;if(YB(g)){wi(A,g,I);return}A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"stat_bonus",target:B.target,value:B.value,condition:B.condition})}static applySkillProficiency(A,B){const g=B.target.toLowerCase(),I=B.value;yi(A,g,I)}static applyAbilityUnlock(A,B){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"ability_unlock",target:B.target,value:B.value,condition:B.condition})}static applyPassiveModifier(A,B){const g=B.target,I=B.value;if(g==="speed"){A.speed+=I;return}if(g.endsWith("_max")){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"passive_modifier",target:B.target,value:B.value,condition:B.condition});return}A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"passive_modifier",target:B.target,value:B.value,condition:B.condition})}static applyResourceGrant(A,B){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"resource_grant",target:B.target,value:B.value,condition:B.condition})}static applySpellSlotBonus(A,B){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"spell_slot_bonus",target:B.target,value:B.value,condition:B.condition})}}class gQ{static registerExtensions(A){const B=AA.getInstance();if(A.spells&&A.spells.length>0&&B.register("spells",A.spells),A.equipment&&A.equipment.length>0&&B.register("equipment",A.equipment),A.races&&A.races.length>0&&B.register("races",A.races),A.classes&&A.classes.length>0&&B.register("classes",A.classes),A.appearance){const{appearance:g}=A;g.bodyTypes&&g.bodyTypes.length>0&&B.register("appearance.bodyTypes",g.bodyTypes),g.skinTones&&g.skinTones.length>0&&B.register("appearance.skinTones",g.skinTones),g.hairColors&&g.hairColors.length>0&&B.register("appearance.hairColors",g.hairColors),g.hairStyles&&g.hairStyles.length>0&&B.register("appearance.hairStyles",g.hairStyles),g.eyeColors&&g.eyeColors.length>0&&B.register("appearance.eyeColors",g.eyeColors),g.facialFeatures&&g.facialFeatures.length>0&&B.register("appearance.facialFeatures",g.facialFeatures)}}static generate(A,B,g,I={}){const E=new QB(A),i=I.level||1,C=I.gameMode||"standard";Di();const a=YA.getInstance();I.extensions&&gQ.registerExtensions(I.extensions);let e;const o=I.subrace;let t;if(o==="pure")e=void 0,t=I.forceRace;else if(o!==void 0)if(I.forceRace)e=o,t=I.forceRace;else{const QA=a.getRaceForSubrace(o);if(!QA)throw new Error(`Cannot determine race for subrace "${o}". Either specify forceRace or ensure the subrace is registered in racial traits. Example: { forceRace: 'Elf', subrace: 'High Elf' }`);t=QA,e=o}const s=t||Ho.select(E);if(e!==void 0&&o!=="pure"){const QA=a.getAvailableSubraces(s);if(!QA.includes(e))throw new Error(`Invalid subrace "${e}" for race "${s}". Available subraces: ${QA.length>0?QA.join(", "):"none"}`)}else if(e===void 0&&o===void 0){const DA=["pure",...a.getAvailableSubraces(s)],Qg=E.randomChoice(DA);e=Qg==="pure"?void 0:Qg}const G=I.forceClass||AQ.suggest(B,E),n=I.forceName||new Ro().generateName(A,g,B,G,I.deterministicName||!0),h=BQ.calculateBaseScores(B,E),c=BQ.applyRacialBonuses(h,s),d=BQ.calculateModifiers(c),l=RE(G);if(!l)throw new Error(`Unknown class: ${G}. Cannot generate character.`);const m=bI(s)?.speed??30,y=l.hit_die+d.CON,p=10+d.DEX,k=d.DEX,H=mE[i],T=fo.assignSkills(G,E),q={STR:l.saving_throws.includes("STR"),DEX:l.saving_throws.includes("DEX"),CON:l.saving_throws.includes("CON"),INT:l.saving_throws.includes("INT"),WIS:l.saving_throws.includes("WIS"),CHA:l.saving_throws.includes("CHA")},v=No.generate(A,G,B),EA=a.getClassFeatures(G,i),aA=e?a.getRacialTraitsForSubrace(s,e):a.getBaseRacialTraits(s),GA=Xg.initializeEquipment(G),rA={name:n,race:s,subrace:e,class:G,level:i,ability_scores:c,ability_modifiers:d,proficiency_bonus:H,hp:{current:y,max:y,temp:0},armor_class:p,initiative:k,speed:m,skills:T,saving_throws:q,racial_traits:[],class_features:[],appearance:v,spells:{spell_slots:{},known_spells:[],cantrips:[]},equipment:GA,xp:{current:0,next_level:Jg[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:C},P=Fi.initializeSpells(G,i,rA),BA=[];for(const QA of EA){const DA=a.validatePrerequisites(QA,rA);DA.valid||console.warn(`Feature "${QA.name}" (${QA.id}) failed prerequisite validation:`,DA.errors),BA.push(QA)}const wA=[];for(const QA of aA){const DA=a.validatePrerequisites(QA,rA);DA.valid||console.warn(`Trait "${QA.name}" (${QA.id}) failed prerequisite validation:`,DA.errors),wA.push(QA)}const yA={name:n,race:s,subrace:e,class:G,level:i,ability_scores:c,ability_modifiers:d,proficiency_bonus:H,hp:{current:y,max:y,temp:0},armor_class:p,initiative:k,speed:m,skills:T,saving_throws:q,racial_traits:wA.map(QA=>QA.id),class_features:BA.map(QA=>QA.id),appearance:v,spells:P,equipment:GA,xp:{current:0,next_level:Jg[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:C};if(vg.applyMultipleEffects(yA,wA),vg.applyMultipleEffects(yA,BA),GA){const QA=[...GA.weapons.filter(DA=>DA.equipped),...GA.armor.filter(DA=>DA.equipped),...GA.items.filter(DA=>DA.equipped)];for(const DA of QA){const Qg=Xg.getEquipmentDataStatic(DA.name);if(Qg){const pC=DA.instanceId;HA.equipItem(yA,Qg,pC).applied||(DA.equipped=!1)}}}return Fi.filterCharacterSpells(yA)}}function Ri(Q){return 2595*Math.log10(1+Q/700)}function qo(Q){return 700*(Math.pow(10,Q/2595)-1)}function Kg(Q,A){const B=Q.sampleRate,g=B/A,I=Q.length,E=Math.ceil(I/g),i=new Float32Array(I);for(let a=0;a<Q.numberOfChannels;a++){const e=Q.getChannelData(a);for(let o=0;o<I;o++)i[o]+=e[o]/Q.numberOfChannels}const C=new Float32Array(E);for(let a=0;a<E;a++){const e=a*g,o=Math.floor(e),t=Math.min(o+1,I-1),s=e-o;C[a]=i[o]*(1-s)+i[t]*s}return{data:C,originalSampleRate:B,targetSampleRate:A}}function xo(Q,A,B,g=0,I=B/2){const E=A/2+1,i=[],C=Ri(g),a=Ri(I),e=[];for(let t=0;t<Q+2;t++)e.push(C+t*(a-C)/(Q+1));const o=e.map(t=>{const s=qo(t);return Math.floor((A+1)*s/B)});for(let t=0;t<Q;t++){const s=new Float32Array(E),G=o[t],n=o[t+1],h=o[t+2];for(let c=G;c<n;c++)n!==G&&(s[c]=(c-G)/(n-G));for(let c=n;c<h;c++)h!==n&&(s[c]=(h-c)/(h-n));i.push(s)}return i}function Vo(Q,A,B){if(Q.length===0)return new Float32Array(0);const g=1/(2*Math.PI*A),I=1/B,E=g/(g+I),i=new Float32Array(Q.length);i[0]=Q[0];for(let C=1;C<Q.length;C++)i[C]=E*(i[C-1]+Q[C]-Q[C-1]);return i}function mi(Q,A,B){if(Q.length===0)return new Float32Array(0);const g=Math.round(A/1e3*B);if(g<=1)return new Float32Array(Q);const I=g/6,E=g,i=new Float32Array(E),C=Math.floor(E/2);let a=0;for(let o=0;o<E;o++){const t=o-C;i[o]=Math.exp(-(t*t)/(2*I*I)),a+=i[o]}for(let o=0;o<E;o++)i[o]/=a;const e=new Float32Array(Q.length);for(let o=0;o<Q.length;o++){let t=0;for(let s=0;s<E;s++){const G=o+s-C,n=G<0?-G:G>=Q.length?2*Q.length-G-2:G,h=Math.max(0,Math.min(Q.length-1,n));t+=Q[h]*i[s]}e[o]=t}return e}function Lo(Q){if(Q.length===0)return 0;let A=0;for(let E=0;E<Q.length;E++)A+=Q[E];const B=A/Q.length;let g=0;for(let E=0;E<Q.length;E++){const i=Q[E]-B;g+=i*i}const I=g/Q.length;return Math.sqrt(I)}function Xo(Q){const A=Q.length,B=Math.pow(2,Math.ceil(Math.log2(A))),g=new Float32Array(B),I=new Float32Array(B);for(let a=0;a<A;a++){const e=.5-.5*Math.cos(2*Math.PI*a/(A-1));g[a]=Q[a]*e}let E=0;for(let a=0;a<B-1;a++){a<E&&([g[a],g[E]]=[g[E],g[a]],[I[a],I[E]]=[I[E],I[a]]);let e=B/2;for(;E>=e;)E-=e,e/=2;E+=e}let i=2;for(;i<=B;){const a=-2*Math.PI/i,e=Math.cos(a),o=Math.sin(a);for(let t=0;t<B;t+=i){let s=1,G=0;for(let n=0;n<i/2;n++){const h=t+n,c=t+n+i/2,d=g[c]*s-I[c]*G,l=g[c]*G+I[c]*s;g[c]=g[h]-d,I[c]=I[h]-l,g[h]+=d,I[h]+=l;const F=s*e-G*o;G=s*o+G*e,s=F}}i*=2}const C=new Float32Array(B/2+1);for(let a=0;a<C.length;a++){const e=g[a],o=I[a];C[a]=Math.sqrt(e*e+o*o)}return C}function ui(Q,A,B,g){const I=[];let E=0;for(;E+A<=Q.length;){const i=Q.slice(E,E+A),C=Xo(i);I.push(C),E+=B}return{frames:I,numFrames:I.length,fftSize:A,hopSize:B,sampleRate:g}}const vo=[{name:"low",lowHz:20,highHz:500,description:"Low frequencies (bass, kick, sub)"},{name:"mid",lowHz:500,highHz:2e3,description:"Mid frequencies (vocals, snare body, lead instruments)"},{name:"high",lowHz:2e3,highHz:2e4,description:"High frequencies (hi-hats, cymbals, harmonics, air)"}];function Ko(Q,A){const B=Math.PI*(2*Q-1)/(2*A);return 1/(2*Math.sin(B))}function ed(Q,A,B,g){const I=2*Math.PI*Q/A,E=Math.cos(I),i=Math.sin(I),C=Ko(B,g),a=i/(2*C),e=1+a,o=(1-E)/2/e,t=(1-E)/e,s=(1-E)/2/e,G=-2*E/e,n=(1-a)/e;return{b0:o,b1:t,b2:s,a1:G,a2:n}}function od(Q,A,B,g){const I=2*Math.PI*Q/A,E=Math.cos(I),i=Math.sin(I),C=Ko(B,g),a=i/(2*C),e=1+a,o=(1+E)/2/e,t=-(1+E)/e,s=(1+E)/2/e,G=-2*E/e,n=(1-a)/e;return{b0:o,b1:t,b2:s,a1:G,a2:n}}function zo(Q,A){const{b0:B,b1:g,b2:I,a1:E,a2:i}=A,C=new Float32Array(Q.length);C[0]=B*Q[0],Q.length>1&&(C[1]=B*Q[1]+g*Q[0]-E*C[0]);for(let a=2;a<Q.length;a++)C[a]=B*Q[a]+g*Q[a-1]+I*Q[a-2]-E*C[a-1]-i*C[a-2];return C}function td(Q,A,B,g,I){if(Q.length===0)return new Float32Array(0);const E=8;if(A>=B)throw new Error(`Low frequency (${A} Hz) must be less than high frequency (${B} Hz)`);if(B>=g/2)throw new Error(`High frequency (${B} Hz) must be less than Nyquist frequency (${g/2} Hz)`);const i=E/2;let C=new Float32Array(Q);for(let a=1;a<=i;a++){const e=od(A,g,a,E);C=zo(C,e)}for(let a=1;a<=i;a++){const e=ed(B,g,a,E);C=zo(C,e)}return C}function sd(Q,A,B,g){const I=vo.find(E=>E.name===A);if(!I)throw new Error(`Unknown frequency band: ${A}. Valid bands are: low, mid, high`);return td(Q,I.lowHz,I.highHz,B)}const Gd={targetSampleRate:44100,fftWindowSizeMs:23,hopSizeMs:10,smoothWindowMs:10,peakThreshold:.3,bands:vo};class To{constructor(A={}){if(this.config={...Gd,...A},this.config.peakThreshold<0||this.config.peakThreshold>1)throw new Error(`peakThreshold must be between 0 and 1, got: ${this.config.peakThreshold}`);if(this.config.bands.length===0)throw new Error("At least one frequency band must be specified")}getConfig(){return{...this.config}}analyze(A){const B=A.duration,g=this.config.targetSampleRate,I=Kg(A,g),E=Math.pow(2,Math.ceil(Math.log2(this.config.fftWindowSizeMs/1e3*g))),i=Math.round(this.config.hopSizeMs/1e3*g),C=this.config.hopSizeMs/1e3,a=1/C,e=new Map,o=[];for(const n of this.config.bands){const h=this.analyzeBand(I.data,n,g,E,i,C,a);e.set(n.name,h),o.push(h.energyOverTime)}const t=o[0]?.length??0,s=this.combineEnergyProfiles(o,t),G=this.calculateDominantBands(e);return{bands:e,dominantBands:G,energyProfile:s,metadata:{numFrames:t,duration:B,hopSizeSeconds:C,effectiveSampleRate:g,bandsAnalyzed:this.config.bands.map(n=>n.name)}}}analyzeBand(A,B,g,I,E,i,C){const a=sd(A,B.name,g),e=ui(a,I,E,g),o=e.numFrames,t=new Float32Array(o);for(let m=0;m<o;m++){const y=e.frames[m];let p=0;for(let k=0;k<y.length;k++)p+=y[k]*y[k];t[m]=Math.sqrt(p/y.length)}const s=Math.max(...t);if(s>0)for(let m=0;m<t.length;m++)t[m]/=s;const G=s,n=this.calculateOnsetEnvelope(e.frames),h=mi(n,this.config.smoothWindowMs,C),c=Math.max(...h),d=new Float32Array(h.length);if(c>0)for(let m=0;m<h.length;m++)d[m]=h[m]/c;const l=this.findPeaks(d,this.config.peakThreshold),F=l.map(m=>m*i);return{name:B.name,frequencyRange:{lowHz:B.lowHz,highHz:B.highHz},envelope:d,peaks:l,peakTimes:F,energy:G,energyOverTime:t}}calculateOnsetEnvelope(A){const B=A.length,g=new Float32Array(B);g[0]=0;for(let I=1;I<B;I++){const E=A[I],i=A[I-1];let C=0;for(let a=0;a<E.length;a++){const e=E[a]-i[a];e>0&&(C+=e)}g[I]=C}return g}findPeaks(A,B){const g=[];for(let I=1;I<A.length-1;I++)A[I]>A[I-1]&&A[I]>A[I+1]&&A[I]>=B&&g.push(I);return g}combineEnergyProfiles(A,B){const g=new Float32Array(B);for(let I=0;I<B;I++){let E=0;for(const i of A)I<i.length&&i[I]>E&&(E=i[I]);g[I]=E}return g}calculateDominantBands(A){const B=[];for(const[g,I]of A)B.push({name:g,energy:I.energy});return B.sort((g,I)=>I.energy-g.energy),B.map(g=>g.name)}}const Si={low:{threshold:.5,minInterval:.1,adaptiveThresholding:!1},mid:{threshold:.3,minInterval:.08,adaptiveThresholding:!1},high:{threshold:.25,minInterval:.06,adaptiveThresholding:!1}},nd={baseThreshold:.3,adaptiveThresholding:!1,adaptiveWindowSize:50,minTransientInterval:.02};class jo{constructor(A={}){const{bands:B,bandConfig:g,...I}=A,E={low:{...Si.low,...g?.low},mid:{...Si.mid,...g?.mid},high:{...Si.high,...g?.high}};if(this.config={...nd,...I,bandConfig:E},B!==void 0&&(this.config.bands=B),this.config.baseThreshold<0||this.config.baseThreshold>1)throw new Error(`baseThreshold must be between 0 and 1, got: ${this.config.baseThreshold}`);if(this.config.adaptiveWindowSize<1)throw new Error(`adaptiveWindowSize must be at least 1, got: ${this.config.adaptiveWindowSize}`);if(this.config.minTransientInterval<0)throw new Error(`minTransientInterval must be non-negative, got: ${this.config.minTransientInterval}`);for(const i of["low","mid","high"]){const C=this.config.bandConfig[i];if(C.threshold<0||C.threshold>1)throw new Error(`${i} band threshold must be between 0 and 1, got: ${C.threshold}`);if(C.minInterval<0)throw new Error(`${i} band minInterval must be non-negative, got: ${C.minInterval}`)}}getConfig(){const{bandConfig:A,...B}=this.config;return{...B,bandConfig:{low:{...A.low},mid:{...A.mid},high:{...A.high}}}}getBandConfig(){return{low:{...this.config.bandConfig.low},mid:{...this.config.bandConfig.mid},high:{...this.config.bandConfig.high}}}detect(A){const B=new Map,g=[],I=new Set;for(const[C,a]of A.bands){const e=this.detectBandTransients(C,a,A.metadata.hopSizeSeconds);B.set(C,e),g.push(...e),e.forEach(o=>I.add(o.detectionMethod))}g.sort((C,a)=>C.timestamp-a.timestamp);const E=new Map;for(const[C,a]of B)E.set(C,a.length);const i=g.length>0?g.reduce((C,a)=>C+a.intensity,0)/g.length:0;return{transients:g,bandTransients:B,metadata:{totalTransients:g.length,transientsPerBand:E,duration:A.metadata.duration,averageIntensity:i,detectionMethodsUsed:Array.from(I)}}}detectBandTransients(A,B,g){const I=this.config.bandConfig[A],E=this.getDetectionMethod(A),i=E==="energy"?B.energyOverTime:B.envelope;if(!i||i.length===0)return[];const C=I.adaptiveThresholding?this.calculateAdaptiveThreshold(i,I.threshold):I.threshold,e=this.findPeaks(i,C).map(t=>({timestamp:t*g,intensity:i[t],band:A,detectionMethod:E}));return this.applyNonMaximumSuppression(e,I.minInterval)}applyNonMaximumSuppression(A,B){if(A.length===0)return[];const g=[...A].sort((E,i)=>i.intensity-E.intensity),I=[];for(const E of g){let i=!1;for(const C of I)if(Math.abs(E.timestamp-C.timestamp)<B){i=!0;break}i||I.push(E)}return I.sort((E,i)=>E.timestamp-i.timestamp),I}getDetectionMethod(A){switch(A){case"low":return"energy";case"mid":return"spectral_flux";case"high":return"hfc";default:return"spectral_flux"}}calculateAdaptiveThreshold(A,B){const g=B??this.config.baseThreshold;if(A.length===0)return g;let I=0,E=0;for(let s=0;s<A.length;s++)I+=A[s],A[s]>E&&(E=A[s]);const i=I/A.length;let C=0;for(let s=0;s<A.length;s++){const G=A[s]-i;C+=G*G}const a=Math.sqrt(C/A.length),o=1+(i>0?a/i:0)*.5,t=g*o;return Math.max(.1,Math.min(.9,t))}findPeaks(A,B){const g=[];for(let I=1;I<A.length-1;I++)A[I]>A[I-1]&&A[I]>A[I+1]&&A[I]>=B&&g.push(I);return g}}const zg={densityValidation:{maxRetries:0,baseSensitivityReduction:.1,maxCumulativeReduction:.5},minimumTransientIntensity:0,bands:[]};class bi{constructor(A={}){this.config={densityValidation:{maxRetries:A.densityValidation?.maxRetries??zg.densityValidation.maxRetries,baseSensitivityReduction:A.densityValidation?.baseSensitivityReduction??zg.densityValidation.baseSensitivityReduction,maxCumulativeReduction:A.densityValidation?.maxCumulativeReduction??zg.densityValidation.maxCumulativeReduction},minimumTransientIntensity:A.minimumTransientIntensity??zg.minimumTransientIntensity,bands:A.bands??zg.bands}}getConfig(){return{...this.config}}quantize(A,B,g){const I=this.splitTransientsByBand(A.transients),E=B.quarterNoteInterval/6,i=this.processBand(I.low,"low",E),C=this.processBand(I.mid,"mid",E),a=this.processBand(I.high,"high",E),e={low:this.quantizeBand(i.filteredTransients,B,"low",g),mid:this.quantizeBand(C.filteredTransients,B,"mid",g),high:this.quantizeBand(a.filteredTransients,B,"high",g)},o=i.filteredCount+C.filteredCount+a.filteredCount,t=this.aggregateDensityResults([i.densityResult,C.densityResult,a.densityResult],E);return{streams:e,metadata:{densityValidation:t,transientsFilteredByIntensity:o,transientsFilteredByBand:{low:i.filteredCount,mid:C.filteredCount,high:a.filteredCount}}}}splitTransientsByBand(A){return{low:A.filter(B=>B.band==="low"),mid:A.filter(B=>B.band==="mid"),high:A.filter(B=>B.band==="high")}}processBand(A,B,g){const I=this.config.densityValidation.maxRetries,E=this.config.densityValidation.baseSensitivityReduction,i=this.config.densityValidation.maxCumulativeReduction;let C=0,a=A;if(this.config.minimumTransientIntensity>0){const G=a.length;a=a.filter(n=>n.intensity>=this.config.minimumTransientIntensity),C=G-a.length}let e=this.config.minimumTransientIntensity,o=0,t=0;for(;t<=I;){const G=this.validateBandDensity(a,B,g,t,o);if(G.isValid)return{filteredTransients:a,filteredCount:C,densityResult:G};if(t>=I)return console.warn(`[${B}] Density validation: Max retries (${I}) reached. Proceeding with ${a.length} transients. Min interval: ${(G.minIntervalDetected*1e3).toFixed(1)}ms (required: ${(g*1e3).toFixed(1)}ms)`),{filteredTransients:a,filteredCount:C,densityResult:G};t++;const n=Math.min(E,i-o);o+=n,e=Math.min(this.config.minimumTransientIntensity+o,1);const h=a.length;a=a.filter(d=>d.intensity>=e);const c=h-a.length;C+=c,console.warn(`[${B}] Density validation retry ${t}: Threshold increased to ${(e*100).toFixed(1)}%, Filtered ${c} transients, ${a.length} remaining`)}const s=this.validateBandDensity(a,B,g,t,o);return{filteredTransients:a,filteredCount:C,densityResult:s}}validateBandDensity(A,B,g,I,E,i=this.config.minimumTransientIntensity){const C=A.length,a=Math.min(this.config.minimumTransientIntensity+E,1);if(A.length===0)return{band:B,isValid:!0,minIntervalDetected:1/0,requiredMinInterval:g,retryCount:I,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:C};const e=[...A].sort((s,G)=>s.timestamp-G.timestamp);let o=1/0;for(let s=1;s<e.length;s++){const G=e[s].timestamp-e[s-1].timestamp;G<o&&(o=G)}const t=o>=g;return{band:B,isValid:t,minIntervalDetected:o,requiredMinInterval:g,retryCount:I,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:C}}aggregateDensityResults(A,B){let g=0,I=0,E=1/0,i=!0;for(const C of A)C.retryCount>g&&(g=C.retryCount),C.sensitivityReduction>I&&(I=C.sensitivityReduction),C.minIntervalDetected<E&&(E=C.minIntervalDetected),C.isValid||(i=!1);return{isValid:i,bands:{low:A.find(C=>C.band==="low"),mid:A.find(C=>C.band==="mid"),high:A.find(C=>C.band==="high")},maxRetryCount:g,maxSensitivityReduction:I}}decideGrids(A,B,g){const I=[],E=B.quarterNoteInterval,i=this.getBandGridType(g),C=[...A].sort((a,e)=>a.timestamp-e.timestamp);for(let a=0;a<B.beats.length;a++){const e=B.beats[a],o=e.timestamp,t=a<B.beats.length-1?B.beats[a+1].timestamp:e.timestamp+E,s=C.filter(G=>G.timestamp>=o&&G.timestamp<t);s.length!==0&&(i?I.push({beatIndex:a,selectedGrid:i,transientCount:s.length,confidence:1}):I.push(this.detectGrid(s,e,a,E)))}return I}quantizeToGrids(A,B,g,I){const E=[],i=B.quarterNoteInterval,C=[...A].sort((e,o)=>e.timestamp-o.timestamp),a=new Map;for(const e of I)a.set(e.beatIndex,e);for(let e=0;e<B.beats.length;e++){const o=B.beats[e],t=a.get(e);if(!t)continue;const s=o.timestamp,G=e<B.beats.length-1?B.beats[e+1].timestamp:o.timestamp+i,n=C.filter(h=>h.timestamp>=s&&h.timestamp<G);for(const h of n){const c=this.quantizeTransient(h,o,e,t.selectedGrid,i);c&&E.push(c)}}return E}quantizeBand(A,B,g,I){const E=I?I(A,B,g):this.decideGrids(A,B,g),i=this.quantizeToGrids(A,B,g,E),C=this.deduplicateBeats(i);return{audioId:B.audioId,duration:B.duration,beats:C,gridDecisions:E,quarterNoteInterval:B.quarterNoteInterval}}deduplicateBeats(A){const B=new Map;for(const g of A){const I=`${g.beatIndex}:${g.gridPosition}:${g.gridType}`,E=B.get(I);(!E||g.intensity>E.intensity)&&B.set(I,g)}return Array.from(B.values()).sort((g,I)=>g.timestamp-I.timestamp)}getBandGridType(A){switch(A){case"low":return"straight_8th";case"mid":case"high":return null}}detectGrid(A,B,g,I){const E=this.calculateStraightGrid(B.timestamp,I),i=this.calculateTripletGrid(B.timestamp,I);let C=0,a=0,e=0;for(const n of A){const h=this.calculateOffsetFromGrid(n,E),c=this.calculateOffsetFromGrid(n,i);C+=h,a+=c,e++}const o=e>0?C/e:0,t=e>0?a/e:0,s=o<=t?"straight_16th":"triplet_8th",G=Math.abs(o-t);return{beatIndex:g,selectedGrid:s,straightAvgOffset:o,tripletAvgOffset:t,transientCount:e,confidence:G}}calculateStraightGrid(A,B){const g=[],I=B/4;for(let E=0;E<4;E++)g.push(A+E*I);return g}calculateTripletGrid(A,B){const g=[],I=B/3;for(let E=0;E<3;E++)g.push(A+E*I);return g}calculate8thGrid(A,B){const g=[],I=B/2;for(let E=0;E<2;E++)g.push(A+E*I);return g}calculateOffsetFromGrid(A,B){let g=1/0;for(const I of B){const E=Math.abs(A.timestamp-I);E<g&&(g=E)}return g*1e3}quantizeTransient(A,B,g,I,E){let i,C;switch(I){case"straight_8th":i=1,C=E/2;break;case"straight_16th":i=3,C=E/4;break;case"triplet_8th":i=2,C=E/3;break}const a=Math.round((A.timestamp-B.timestamp)/C);if(a<0||a>i)return null;const e=B.timestamp+a*C,o=Math.abs(A.timestamp-e)*1e3;return{timestamp:e,detectedTimestamp:A.timestamp,beatIndex:g,gridPosition:a,gridType:I,intensity:A.intensity,band:A.band,quantizationError:o}}}class Oo{constructor(A={}){this.id="high-bpm-grid-restriction",this.description="Restricts 16th notes and triplets to 8th notes at high BPMs for playability",this.restrict16thBpm=A.restrict16thBpm??160,this.restrictTripletBpm=A.restrictTripletBpm??200}applies(A,B){return B.band==="low"?!1:A>=this.restrict16thBpm}apply(A,B){const{bpm:g}=B,I=g>=this.restrictTripletBpm;return A.map(E=>{const{selectedGrid:i}=E;return i==="straight_8th"?E:i==="straight_16th"&&g>=this.restrict16thBpm?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:i==="triplet_8th"&&I?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:E})}}const pi={rules:[new Oo],enabled:!0};class Po{constructor(A=pi,B){this.config=A,this.rhythmQuantizer=B??new bi}getConfig(){return{...this.config}}decideGrids(A,B,g){const I=this.rhythmQuantizer.decideGrids(A,B,g),E={bpm:B.quarterNoteBpm,quarterNoteInterval:B.quarterNoteInterval,band:g,transients:A};return this.applyRules(I,E)}applyRules(A,B){if(this.config.enabled===!1)return A;let g=A;for(const I of this.config.rules)I.applies(B.bpm,B)&&(g=I.apply(g,B));return g}}const hd={phraseSizes:[1,2,4,8],minOccurrences:3,topSignificantCount:10,includePhrasesWithoutVariation:!1,minNotesPerPhrase:Q=>1+Q};class _o{constructor(A={}){this.config={...hd,...A}}analyze(A){const B={low:this.analyzeBand(A.low,"low"),mid:this.analyzeBand(A.mid,"mid"),high:this.analyzeBand(A.high,"high")},g=[...B.low.phrases,...B.mid.phrases,...B.high.phrases],I=new Map;I.set("low",B.low.phrases),I.set("mid",B.mid.phrases),I.set("high",B.high.phrases);const E=new Map;for(const e of this.config.phraseSizes){const o=g.filter(t=>t.sizeInBeats===e);o.length>0&&E.set(e,o)}const C=[...g].sort((e,o)=>o.significance-e.significance).slice(0,this.config.topSignificantCount),a=g.filter(e=>e.hasVariation&&e.availableForReuse);return{phrases:g,phrasesByBand:I,mostSignificantPhrases:C,phrasesBySize:E,patternLibrary:a,bandAnalysis:B}}getMinNotes(A){return typeof this.config.minNotesPerPhrase=="function"?this.config.minNotesPerPhrase(A):typeof this.config.minNotesPerPhrase=="number"?this.config.minNotesPerPhrase:1+A}analyzeBand(A,B){const g=Math.max(...A.beats.map(a=>a.beatIndex),0),I=new Map;for(const a of this.config.phraseSizes)for(let e=0;e<=g-a+1;e++){const o=this.extractPhraseCandidate(A,e,a,B);if(o){const t=I.get(o.hash);t?t.push(o):I.set(o.hash,[o])}}const E=[];for(const[a,e]of I){if(e.length<this.config.minOccurrences)continue;const o=e[0];if(o.pattern.length<this.getMinNotes(o.sizeInBeats))continue;const t=this.hasPatternVariation(o.pattern,o.sizeInBeats);if(!t&&!this.config.includePhrasesWithoutVariation)continue;const s=e.map(h=>({beatIndex:h.startBeatIndex,startTimestamp:h.startTimestamp,endTimestamp:h.endTimestamp})),G=this.calculateSignificance(o.sizeInBeats,e.length),n=t&&e.length>=this.config.minOccurrences;E.push({id:a,pattern:o.pattern,sizeInBeats:o.sizeInBeats,sourceBand:B,occurrences:s,significance:G,hasVariation:t,availableForReuse:n})}E.sort((a,e)=>e.significance-a.significance);const i=new Map;for(const a of this.config.phraseSizes){const e=E.filter(o=>o.sizeInBeats===a);e.length>0&&i.set(a,e)}const C=E.filter(a=>a.hasVariation);return{band:B,phrases:E,phrasesBySize:i,phrasesWithVariation:C}}extractPhraseCandidate(A,B,g,I){const E=B+g-1,i=A.beats.filter(t=>t.beatIndex>=B&&t.beatIndex<=E);if(i.length===0)return null;const C=i.map(t=>({...t,beatIndex:t.beatIndex-B})),a=this.hashPattern(C,g),e=Math.min(...i.map(t=>t.timestamp)),o=Math.max(...i.map(t=>t.timestamp));return{hash:a,pattern:C,sizeInBeats:g,startBeatIndex:B,startTimestamp:e,endTimestamp:o}}hashPattern(A,B){const I=[...A].sort((E,i)=>E.beatIndex!==i.beatIndex?E.beatIndex-i.beatIndex:E.gridPosition-i.gridPosition).map(E=>`${E.beatIndex}:${E.gridPosition}:${E.gridType}`);return`phrase_${B}_${I.join("|")}`}hasPatternVariation(A,B){if(A.length===0)return!1;if(A.some(C=>C.gridType==="triplet_8th")||A.some(C=>C.gridPosition===1||C.gridPosition===3))return!0;const g=A.map(C=>C.intensity),I=Math.max(...g),E=Math.min(...g);if(I-E>.1)return!0;if(A.length===B&&A.every(a=>a.gridPosition===0))return!1;const i=new Set(A.map(C=>C.gridPosition));return!(i.size===2&&i.has(0)&&i.has(2)&&this.countBeatsWithNoteCount(A,2)===B)}countBeatsWithNoteCount(A,B){const g=new Map;for(const E of A){const i=g.get(E.beatIndex)??0;g.set(E.beatIndex,i+1)}let I=0;for(const E of g.values())E===B&&I++;return I}calculateSignificance(A,B){const g=A,I=Math.log2(B+1);return g*I}}const cd={beatsPerSection:8,sparseThreshold:1,denseThreshold:1.5};class $o{constructor(A={}){this.config={...cd,...A}}analyze(A,B,g){const I=B/60,E={low:this.analyzeBand(A.streams.low,"low",I,g),mid:this.analyzeBand(A.streams.mid,"mid",I,g),high:this.analyzeBand(A.streams.high,"high",I,g)};[...A.streams.low.beats,...A.streams.mid.beats,...A.streams.high.beats];const i=this.calculateCombinedPerBeatDensity(A.streams.low,A.streams.mid,A.streams.high),C=this.calculateCombinedMetrics(i,I,g),a=this.calculateSectionMetrics(i,I,g);return{bandMetrics:E,combinedMetrics:C,sections:a,perBeatDensity:i}}analyzeBand(A,B,g,I){const E=A.beats,C=(E.length>0?Math.max(...E.map(l=>l.beatIndex)):0)+1,a=new Map;for(const l of E){const F=a.get(l.beatIndex);F?(F.count++,F.intensities.push(l.intensity)):a.set(l.beatIndex,{count:1,intensities:[l.intensity]})}const e=[];let o=0;for(let l=0;l<C;l++){const F=a.get(l),m=F?.count??0,y=F?F.intensities.reduce((p,k)=>p+k,0)/F.intensities.length:0;e.push({beatIndex:l,transientCount:m,bands:m>0?[B]:[],averageIntensity:y}),o+=m}const t=e.map(l=>l.transientCount);let s;I&&I>0?s=o/I:s=C>0?o/C*g:0;const G=t.length>0?Math.min(...t)*g:0,n=t.length>0?Math.max(...t)*g:0,h=this.calculateVariance(t,s/g)*g*g,c=this.categorizeDensity(s),d=this.determineNaturalDifficulty(c);return{band:B,totalBeats:C,totalTransients:o,notesPerSecond:s,minNotesPerSecond:G,maxNotesPerSecond:n,variance:h,densityCategory:c,naturalDifficulty:d,perBeatDensity:e}}calculateCombinedPerBeatDensity(A,B,g){const I=[...A.beats,...B.beats,...g.beats],i=(I.length>0?Math.max(...I.map(e=>e.beatIndex)):0)+1,C=new Map;for(const e of A.beats)this.addToBeatData(C,e,"low");for(const e of B.beats)this.addToBeatData(C,e,"mid");for(const e of g.beats)this.addToBeatData(C,e,"high");const a=[];for(let e=0;e<i;e++){const o=C.get(e);if(o){const t=o.intensities.length>0?o.intensities.reduce((s,G)=>s+G,0)/o.intensities.length:0;a.push({beatIndex:e,transientCount:o.count,bands:Array.from(o.bands),averageIntensity:t})}else a.push({beatIndex:e,transientCount:0,bands:[],averageIntensity:0})}return a}addToBeatData(A,B,g){const I=A.get(B.beatIndex);if(I)I.count++,I.bands.add(g),I.intensities.push(B.intensity);else{const E=new Set;E.add(g),A.set(B.beatIndex,{count:1,bands:E,intensities:[B.intensity]})}}calculateCombinedMetrics(A,B,g){const I=A.reduce((a,e)=>a+e.transientCount,0);let E;if(g&&g>0)E=I/g;else{const a=A.length;E=a>0?I/a*B:0}const i=this.categorizeDensity(E),C=this.determineNaturalDifficulty(i);return{totalTransients:I,notesPerSecond:E,densityCategory:i,naturalDifficulty:C}}calculateSectionMetrics(A,B,g){const I=[],E=this.config.beatsPerSection,i=A.length;for(let C=0;C<i;C+=E){const a=Math.min(C+E-1,i-1),e=A.slice(C,a+1),o=e.reduce((l,F)=>l+F.transientCount,0),t=e.length,s=t>0?o/t*B:0,G=e.map(l=>l.transientCount),n=G.length>0?Math.min(...G)*B:0,h=G.length>0?Math.max(...G)*B:0,c=this.categorizeDensity(s),d=this.determineNaturalDifficulty(c);I.push({startBeat:C,endBeat:a,beatCount:t,totalTransients:o,notesPerSecond:s,minNotesPerSecond:n,maxNotesPerSecond:h,densityCategory:c,naturalDifficulty:d})}return I}categorizeDensity(A){return A<this.config.sparseThreshold?"sparse":A>this.config.denseThreshold?"dense":"moderate"}determineNaturalDifficulty(A){switch(A){case"sparse":return"easy";case"moderate":return"medium";case"dense":return"hard"}}calculateVariance(A,B){return A.length===0?0:A.map(I=>Math.pow(I-B,2)).reduce((I,E)=>I+E,0)/A.length}getConfig(){return{...this.config}}}const At={beatsPerSection:8,ioiVarianceWeight:.3,syncopationWeight:.3,phraseSignificanceWeight:.25,densityWeight:.15,offbeatGridPositions:{straight_16th:[1,3],triplet_8th:[1,2],straight_8th:[1]},bandBiasWeights:{low:.8,mid:.95,high:1}},rd={low:.8,mid:.95,high:1},ld={ddr:{ioiVarianceWeight:.2,syncopationWeight:.15,phraseSignificanceWeight:.35,densityWeight:.3},guitar_hero:{ioiVarianceWeight:.3,syncopationWeight:.3,phraseSignificanceWeight:.25,densityWeight:.15},tap:{ioiVarianceWeight:.3,syncopationWeight:.2,phraseSignificanceWeight:.3,densityWeight:.2}};function Dd(Q){const A=ld[Q];return{...At,...A,bandBiasWeights:{...rd}}}class Bt{constructor(A={}){this.config={...At,...A}}score(A,B,g){const I=[],E={low:[],mid:[],high:[]},i=[...A.streams.low.beats,...A.streams.mid.beats,...A.streams.high.beats],C=i.length>0?Math.max(...i.map(G=>G.beatIndex)):0,a=C+1,e=["low","mid","high"];for(let G=0;G<a;G+=this.config.beatsPerSection){const n=Math.min(G+this.config.beatsPerSection-1,C),h={start:G,end:n};for(const c of e){const d=this.scoreSection(A.streams[c],c,h,B,g);I.push(d),E[c].push(d.score)}}const o={low:E.low.reduce((G,n)=>G+n,0),mid:E.mid.reduce((G,n)=>G+n,0),high:E.high.reduce((G,n)=>G+n,0)},t={low:E.low.length>0?o.low/E.low.length:0,mid:E.mid.length>0?o.mid/E.mid.length:0,high:E.high.length>0?o.high/E.high.length:0},s=this.determineSectionWinners(I);return{sectionScores:I,bandTotals:o,bandAverages:t,sectionWinners:s,config:{...this.config}}}scoreSection(A,B,g,I,E){const i=A.beats.filter(s=>s.beatIndex>=g.start&&s.beatIndex<=g.end),C=this.calculateIOIVariance(i),a=this.calculateSyncopationLevel(i),e=this.calculatePhraseSignificance(I,B,g),o=this.calculateDensityFactor(E,B,g);let t=C*this.config.ioiVarianceWeight+a*this.config.syncopationWeight+e*this.config.phraseSignificanceWeight+o*this.config.densityWeight;if(this.config.bandBiasWeights){const s=this.config.bandBiasWeights[B]??1;t*=s}return{beatRange:g,band:B,score:t,factors:{ioiVariance:C,syncopationLevel:a,phraseSignificance:e,densityFactor:o}}}calculateIOIVariance(A){if(A.length<2)return 0;const B=[...A].sort((a,e)=>a.timestamp-e.timestamp),g=[];for(let a=1;a<B.length;a++)g.push(B[a].timestamp-B[a-1].timestamp);if(g.length===0)return 0;const I=g.reduce((a,e)=>a+e,0)/g.length,E=g.reduce((a,e)=>a+Math.pow(e-I,2),0)/g.length,i=Math.sqrt(E),C=I>0?i/I:0;return Math.min(C,1)}calculateSyncopationLevel(A){if(A.length===0)return 0;let B=0,g=0;for(const I of A){const i=this.config.offbeatGridPositions[I.gridType].includes(I.gridPosition),C=I.intensity;i&&(B+=C),g+=C}return g===0?0:B/g}calculatePhraseSignificance(A,B,g){const I=A.phrasesByBand.get(B)??[];if(I.length===0)return 0;let E=0,i=0;for(const a of I){i=Math.max(i,a.significance);for(const e of a.occurrences){const o=e.beatIndex+a.sizeInBeats-1;if(e.beatIndex<=g.end&&o>=g.start){const t=Math.max(e.beatIndex,g.start),n=(Math.min(o,g.end)-t+1)/a.sizeInBeats;E+=a.significance*n;break}}}if(i===0)return 0;const C=E/i;return Math.min(C,1)}calculateDensityFactor(A,B,g){const i=A.bandMetrics[B].perBeatDensity.filter(G=>G.beatIndex>=g.start&&G.beatIndex<=g.end);if(i.length===0)return 0;const C=i.reduce((G,n)=>G+n.transientCount,0)/i.length,a=this.config.bpm!=null?this.config.bpm/60:1,e=C*a;return Math.exp(-Math.pow(e-1,2)/(2*Math.pow(.75,2)))}determineSectionWinners(A){const B=new Map;for(const I of A){const E=`${I.beatRange.start}-${I.beatRange.end}`,i=B.get(E);i?i.push(I):B.set(E,[I])}const g=[];for(const[,I]of B){if(I.length===0)continue;const E=[...I].sort((e,o)=>o.score-e.score),i=E[0],C=E[1],a=C?i.score-C.score:i.score;g.push({beatRange:i.beatRange,winner:i.band,score:i.score,margin:a})}return g.sort((I,E)=>I.beatRange.start-E.beatRange.start),g}getConfig(){return{...this.config}}updateConfig(A){this.config={...this.config,...A}}}const dd={transitionOverlapBeats:0,preserveGridDecisions:!0},Fd=1,Md=1.5;class gt{constructor(A={}){this.config={...dd,...A}}generate(A,B,g,I){const E=B.sectionWinners,i={low:0,mid:0,high:0},C={low:0,mid:0,high:0},e=E.filter(d=>{const l=["low","mid","high"];let F=!1;for(const m of l)if(A.streams[m].beats.filter(k=>k.beatIndex>=d.beatRange.start&&k.beatIndex<=d.beatRange.end).length>0){F=!0;break}return F}).map(d=>({beatRange:d.beatRange,sourceBand:d.winner,score:d.score,margin:d.margin}));for(const d of e)C[d.sourceBand]++;const o=[];for(const d of e){const l=A.streams[d.sourceBand],F=this.extractSectionBeats(l,d.beatRange,d.sourceBand);o.push(...F),i[d.sourceBand]+=F.length}o.sort((d,l)=>d.timestamp-l.timestamp);const t=this.deduplicateBeats(o),s=A.streams.low.quarterNoteInterval,G=60/s,n=this.determineNaturalDifficulty(t,g,G,I),h=e.length,c={totalBeats:t.length,sectionCount:h,beatsPerBand:i,sectionsPerBand:{low:h>0?C.low/h:0,mid:h>0?C.mid/h:0,high:h>0?C.high/h:0}};return{beats:t,sections:e,naturalDifficulty:n,quarterNoteInterval:s,metadata:c}}extractSectionBeats(A,B,g){return A.beats.filter(I=>I.beatIndex>=B.start&&I.beatIndex<=B.end).map(I=>({...I,sourceBand:g}))}deduplicateBeats(A){const B=new Map;for(const g of A){const I=Math.round(g.timestamp*1e3),E=B.get(I);(!E||g.intensity>E.intensity)&&B.set(I,g)}return Array.from(B.values()).sort((g,I)=>g.timestamp-I.timestamp)}determineNaturalDifficulty(A,B,g,I){if(A.length===0)return"easy";let E;if(I&&I>0)E=A.length/I;else{const C=Math.max(...A.map(a=>a.beatIndex))+1;E=A.length/C*(g/60)}return E<Fd?"easy":E>Md?"hard":"medium"}getConfig(){return{...this.config}}}const IQ={strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},wd={ddr:{strongBeatEmphasis:"natural",downbeatProximityRange:1,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},guitar_hero:{strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},tap:{strongBeatEmphasis:"natural",downbeatProximityRange:1.5,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5}};function yd(Q){return{...wd[Q]}}function It(Q){return Q%3===0?3:2}function Qt(Q,A){return Q%A===0}function Et(Q,A){return Q%A!==0}function it(Q,A){let B=Q[0];for(const g of Q)if(g.startBeat<=A)B=g;else break;return B}function Ct(Q,A,B){if(B==="neutral")return!1;const g=It(A);return B==="natural"?Qt(Q,g):Et(Q,g)}class at{constructor(A={}){this.config={...IQ,...A}}getConfig(){return{...this.config}}balance(A,B){const g={shiftedToDownbeat:0,emptyMeasuresFilled:0,proximityShifts:0,beatsAdded:0,beatsShifted:0,marginRemovals:0};let I=[...A.beats];return I=this.shiftLoneSubdivisionNotes(I,B,g),I=this.fillEmptyMeasures(I,B,g),I=this.enforceDownbeatProximity(I,B,g),I=this.removeMarginNotes(I,B.duration,g),I.sort((E,i)=>E.timestamp-i.timestamp),{composite:{...A,beats:I,metadata:{...A.metadata,totalBeats:I.length}},stats:g}}shiftLoneSubdivisionNotes(A,B,g){if(!B.downbeatConfig?.segments)return A;const I=new Map;for(const i of A){const C=B.beats[i.beatIndex];if(C){const a=C.measureNumber;I.has(a)||I.set(a,[]),I.get(a).push(i)}}const E=[];for(const i of A){const C=B.beats[i.beatIndex];if(!C){E.push(i);continue}const a=C.measureNumber;if((I.get(a)||[]).length===1&&i.gridPosition!==0){const o={...i,gridPosition:0,timestamp:B.beats[i.beatIndex].timestamp,balancerAction:"shifted_to_downbeat"};E.push(o),g.shiftedToDownbeat++,g.beatsShifted++}else E.push(i)}return E}fillEmptyMeasures(A,B,g){if(!this.config.fillEmptyMeasures||!B.downbeatConfig?.segments)return A;let I=1/0,E=-1/0;for(const e of B.beats)I=Math.min(I,e.measureNumber),E=Math.max(E,e.measureNumber);if(I===1/0)return A;const i=new Map;for(const e of A){const o=B.beats[e.beatIndex];if(o){const t=o.measureNumber;i.has(t)||i.set(t,[]),i.get(t).push(e)}}const C=new Map;for(const e of A)C.set(e.beatIndex,e.gridType);const a=[];for(let e=I;e<=E;e++)if((i.get(e)||[]).length===0){const t=B.beats.findIndex(s=>s.measureNumber===e&&s.isDownbeat);if(t>=0){let s="straight_8th";for(let h=1;h<=8;h++){const c=t-h,d=t+h;if(C.has(c)){s=C.get(c);break}if(C.has(d)){s=C.get(d);break}}const n={timestamp:B.beats[t].timestamp,beatIndex:t,gridPosition:0,gridType:s,intensity:this.config.addedBeatIntensity,band:"mid",sourceBand:"mid",balancerAction:"empty_measure_fill"};a.push(n),g.emptyMeasuresFilled++,g.beatsAdded++}}return[...A,...a]}enforceDownbeatProximity(A,B,g){const I=this.config.downbeatProximityRange;if(I<0)return A;const E=new Set;for(const C of A)C.gridPosition===0&&E.add(C.beatIndex);const i=[];for(const C of A){if(C.gridPosition===0){i.push(C);continue}let a=!1;const e=Math.ceil(I);for(let o=0;o<=e&&!(o>I);o++)if(o===0){if(E.has(C.beatIndex)){a=!0;break}}else if(E.has(C.beatIndex-o)||E.has(C.beatIndex+o)){a=!0;break}if(a)i.push(C);else{const o={...C,gridPosition:0,timestamp:B.beats[C.beatIndex]?.timestamp??C.timestamp,balancerAction:"proximity_shift"};i.push(o),E.add(C.beatIndex),g.proximityShifts++,g.beatsShifted++}}return i}removeMarginNotes(A,B,g){const I=this.config.marginSeconds;if(I<=0||B<=0)return A;const E=B-I;return A.filter(i=>i.timestamp<I||i.timestamp>E?(g.marginRemovals++,!1):!0)}}const Rd=["straight_16th","triplet_8th","straight_8th","quarter_triplet","straight_4th"],Yi={straight_16th:4,straight_8th:2,triplet_8th:3,straight_4th:1,quarter_triplet:1},iB={easy:{maxSubdivision:"eighth",allowedGridTypes:["straight_4th","quarter_triplet"],description:"Quarter notes and quarter note triplets only",targetDensityRange:{min:0,max:1}},medium:{maxSubdivision:"eighth",allowedGridTypes:["straight_8th","quarter_triplet"],description:"8th notes and quarter note triplets only, with density reduction for moderate difficulty",targetDensityRange:{min:1,max:1.5}},hard:{maxSubdivision:"sixteenth",allowedGridTypes:["straight_16th","triplet_8th","straight_8th","quarter_triplet"],description:"All subdivision types including 16th notes",targetDensityRange:{min:1.5,max:1/0}},natural:{maxSubdivision:"sixteenth",allowedGridTypes:["straight_16th","triplet_8th","straight_8th","quarter_triplet"],description:"Unedited composite stream - no subdivision restrictions",targetDensityRange:{min:0,max:1/0}},custom:{maxSubdivision:"sixteenth",allowedGridTypes:["straight_16th","triplet_8th","straight_8th","quarter_triplet"],description:"Custom density-based variant — parameters provided at generation time",targetDensityRange:{min:0,max:1/0}}},et=70,ot=70,tt=120;function FB(Q,A){if(Q==="natural")return[...iB.natural.allowedGridTypes];if(Q==="easy")return["straight_4th","quarter_triplet"];if(Q==="medium")return["straight_8th","quarter_triplet"];if(Q==="hard")return A>=ot?["straight_8th","quarter_triplet"]:[...iB.hard.allowedGridTypes];if(Q==="custom")return[...iB.custom.allowedGridTypes];const B=Q;throw new Error(`Unhandled difficulty: ${B}`)}const md={straight_4th:["straight_4th"],straight_8th:["straight_8th","quarter_triplet"],quarter_triplet:["quarter_triplet","straight_8th"],triplet_8th:["triplet_8th","straight_8th","quarter_triplet"],straight_16th:["straight_16th","triplet_8th","straight_8th","quarter_triplet"]};function st(Q,A){const B=md[Q.maxGridType]??[Q.maxGridType];if(!Q.bpmBasedQuantization)return[...B];const g=Q.restrictBpm??et,I=Q.quarterNoteBpm??tt;let E=[...B];return A>=g&&(E=E.filter(i=>i!=="straight_16th"&&i!=="triplet_8th")),A>I&&(E=E.filter(i=>i!=="straight_8th")),E}function Gt(Q,A){if(Q.length===0||A<=0)return 0;const B=60/A;return Math.max(...Q.map(I=>Yi[I]))/B}const ud={logConversions:!1,preservePhraseBoundaries:!0,simplificationIntensityThreshold:.3,heavySimplificationIntensityThreshold:.5,moderateSimplificationIntensityThreshold:.4,densityReductionMinIntensity:.25,interpolatedBeatIntensity:.5,preferPatternInsertion:!0,maxPatternInsertionSize:4,densityTargetStrategy:"midpoint",maxReductionPasses:3,seed:void 0,rhythmicBalanceConfig:void 0};function Sd(Q,A,B){return B!==void 0?FB(A,B).includes(Q):iB[A].allowedGridTypes.includes(Q)}function bd(Q,A){return A!==void 0?FB(Q,A):[...iB[Q].allowedGridTypes]}function QQ(Q,A,B,g){const I=g??(B!==void 0?FB(A,B):iB[A].allowedGridTypes);if(I.includes(Q))return Q;switch(Q){case"straight_16th":return I.includes("straight_4th")&&!I.includes("straight_8th")?"straight_4th":"straight_8th";case"triplet_8th":return"quarter_triplet";case"straight_8th":return"straight_4th";default:return Q}}function pd(Q){return Q}function nt(Q,A,B){const g=[],I=B!==void 0?FB(A,B):iB[A].allowedGridTypes;for(const E of Q)I.includes(E.gridType)||g.push({beat:E,gridType:E.gridType,suggestedConversion:QQ(E.gridType,A,B)});return{isValid:g.length===0,violations:g,totalBeats:Q.length,violationCount:g.length}}class EQ{constructor(A={}){this.currentUnifiedBeatMap=null,this.config={...ud,...A}}lockGridPerBeatIndex(A,B,g,I,E){const i=this.enforceSingleGridPerBeat(A),C=new Map;if(i.length===0)return{beats:[],gridLock:C};const a=Math.max(...i.map(t=>t.beatIndex)),e=new Map;for(const t of i){const s=e.get(t.beatIndex)??[];s.push(t),e.set(t.beatIndex,s)}for(const[t,s]of e)C.set(t,s[0].gridType);const o=E??FB(B,g);for(let t=0;t<=a;t++){if(C.has(t))continue;if(I?.has(t)){const n=I.get(t);C.set(t,n.selectedGrid);continue}let s=!1;for(const n of[1,-1,2,-2,3,-3]){const h=t+n;if(C.has(h)){C.set(t,C.get(h)),s=!0;break}}if(s)continue;const G=o[0]??"straight_8th";C.set(t,G)}return{beats:i,gridLock:C}}generate(A,B,g,I){this.currentUnifiedBeatMap=B;const E=A.naturalDifficulty,i=this.generateVariant(A,"easy",E,B,g,I),C=this.generateVariant(A,"medium",E,B,g,I),a=this.generateVariant(A,"hard",E,B,g,I);this.validateGridLockResult(i.beats,"easy"),this.validateGridLockResult(C.beats,"medium"),this.validateGridLockResult(a.beats,"hard");const e={difficulty:"natural",beats:this.enforceSingleGridPerBeat([...A.beats]),isUnedited:!0,editType:"none",editAmount:0};this.validateVariant(i,"easy"),this.validateVariant(C,"medium"),this.validateVariant(a,"hard");const o=B?.duration??120;if(i.densityValidation=this.validateDensityInRange(i,o),C.densityValidation=this.validateDensityInRange(C,o),a.densityValidation=this.validateDensityInRange(a,o),this.config.logConversions){const t=s=>{const G=s.densityValidation,n=G.targetRange.max===1/0?"∞":G.targetRange.max.toFixed(1),h=G.inRange?"✓":"✗";return`${s.difficulty}: ${G.density.toFixed(2)} nps (target [${G.targetRange.min}, ${n}]) ${h}`};console.log(`[DifficultyVariantGenerator] Density validation summary:
|
|
49
|
+
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const i of Q.seen.entries()){const C=i[1];if(A===i[0]){E(i);continue}if(Q.external){const e=Q.external.registry.get(i[0])?.id;if(A!==i[0]&&e){E(i);continue}}if(Q.metadataRegistry.get(i[0])?.id){E(i);continue}if(C.cycle){E(i);continue}if(C.count>1&&Q.reused==="ref"){E(i);continue}}}function Oe(Q,A){const B=Q.seen.get(A);if(!B)throw new Error("Unprocessed schema. This is a bug in Zod.");const g=i=>{const C=Q.seen.get(i);if(C.ref===null)return;const a=C.def??C.schema,e={...a},o=C.ref;if(C.ref=null,o){g(o);const s=Q.seen.get(o),G=s.schema;if(G.$ref&&(Q.target==="draft-07"||Q.target==="draft-04"||Q.target==="openapi-3.0")?(a.allOf=a.allOf??[],a.allOf.push(G)):Object.assign(a,G),Object.assign(a,e),i._zod.parent===o)for(const h in a)h==="$ref"||h==="allOf"||h in e||delete a[h];if(G.$ref&&s.def)for(const h in a)h==="$ref"||h==="allOf"||h in s.def&&JSON.stringify(a[h])===JSON.stringify(s.def[h])&&delete a[h]}const t=i._zod.parent;if(t&&t!==o){g(t);const s=Q.seen.get(t);if(s?.schema.$ref&&(a.$ref=s.schema.$ref,s.def))for(const G in a)G==="$ref"||G==="allOf"||G in s.def&&JSON.stringify(a[G])===JSON.stringify(s.def[G])&&delete a[G]}Q.override({zodSchema:i,jsonSchema:a,path:C.path??[]})};for(const i of[...Q.seen.entries()].reverse())g(i[0]);const I={};if(Q.target==="draft-2020-12"?I.$schema="https://json-schema.org/draft/2020-12/schema":Q.target==="draft-07"?I.$schema="http://json-schema.org/draft-07/schema#":Q.target==="draft-04"?I.$schema="http://json-schema.org/draft-04/schema#":Q.target,Q.external?.uri){const i=Q.external.registry.get(A)?.id;if(!i)throw new Error("Schema is missing an `id` property");I.$id=Q.external.uri(i)}Object.assign(I,B.def??B.schema);const E=Q.external?.defs??{};for(const i of Q.seen.entries()){const C=i[1];C.def&&C.defId&&(E[C.defId]=C.def)}Q.external||Object.keys(E).length>0&&(Q.target==="draft-2020-12"?I.$defs=E:I.definitions=E);try{const i=JSON.parse(JSON.stringify(I));return Object.defineProperty(i,"~standard",{value:{...A["~standard"],jsonSchema:{input:vI(A,"input",Q.processors),output:vI(A,"output",Q.processors)}},enumerable:!1,writable:!1}),i}catch{throw new Error("Error converting schema to JSON.")}}function xA(Q,A){const B=A??{seen:new Set};if(B.seen.has(Q))return!1;B.seen.add(Q);const g=Q._zod.def;if(g.type==="transform")return!0;if(g.type==="array")return xA(g.element,B);if(g.type==="set")return xA(g.valueType,B);if(g.type==="lazy")return xA(g.getter(),B);if(g.type==="promise"||g.type==="optional"||g.type==="nonoptional"||g.type==="nullable"||g.type==="readonly"||g.type==="default"||g.type==="prefault")return xA(g.innerType,B);if(g.type==="intersection")return xA(g.left,B)||xA(g.right,B);if(g.type==="record"||g.type==="map")return xA(g.keyType,B)||xA(g.valueType,B);if(g.type==="pipe")return xA(g.in,B)||xA(g.out,B);if(g.type==="object"){for(const I in g.shape)if(xA(g.shape[I],B))return!0;return!1}if(g.type==="union"){for(const I of g.options)if(xA(I,B))return!0;return!1}if(g.type==="tuple"){for(const I of g.items)if(xA(I,B))return!0;return!!(g.rest&&xA(g.rest,B))}return!1}const br=(Q,A={})=>B=>{const g=Te({...B,processors:A});return mA(Q,g),je(g,Q),Oe(g,Q)},vI=(Q,A,B={})=>g=>{const{libraryOptions:I,target:E}=g??{},i=Te({...I??{},target:E,io:A,processors:B});return mA(Q,i),je(i,Q),Oe(i,Q)},pr={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},Yr=(Q,A,B,g)=>{const I=B;I.type="string";const{minimum:E,maximum:i,format:C,patterns:a,contentEncoding:e}=Q._zod.bag;if(typeof E=="number"&&(I.minLength=E),typeof i=="number"&&(I.maxLength=i),C&&(I.format=pr[C]??C,I.format===""&&delete I.format,C==="time"&&delete I.format),e&&(I.contentEncoding=e),a&&a.size>0){const o=[...a];o.length===1?I.pattern=o[0].source:o.length>1&&(I.allOf=[...o.map(t=>({...A.target==="draft-07"||A.target==="draft-04"||A.target==="openapi-3.0"?{type:"string"}:{},pattern:t.source}))])}},Ur=(Q,A,B,g)=>{const I=B,{minimum:E,maximum:i,format:C,multipleOf:a,exclusiveMaximum:e,exclusiveMinimum:o}=Q._zod.bag;typeof C=="string"&&C.includes("int")?I.type="integer":I.type="number",typeof o=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(I.minimum=o,I.exclusiveMinimum=!0):I.exclusiveMinimum=o),typeof E=="number"&&(I.minimum=E,typeof o=="number"&&A.target!=="draft-04"&&(o>=E?delete I.minimum:delete I.exclusiveMinimum)),typeof e=="number"&&(A.target==="draft-04"||A.target==="openapi-3.0"?(I.maximum=e,I.exclusiveMaximum=!0):I.exclusiveMaximum=e),typeof i=="number"&&(I.maximum=i,typeof e=="number"&&A.target!=="draft-04"&&(e<=i?delete I.maximum:delete I.exclusiveMaximum)),typeof a=="number"&&(I.multipleOf=a)},kr=(Q,A,B,g)=>{B.type="boolean"},Zr=(Q,A,B,g)=>{B.not={}},Wr=(Q,A,B,g)=>{},Hr=(Q,A,B,g)=>{const I=Q._zod.def,E=se(I.entries);E.every(i=>typeof i=="number")&&(B.type="number"),E.every(i=>typeof i=="string")&&(B.type="string"),B.enum=E},fr=(Q,A,B,g)=>{if(A.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},Nr=(Q,A,B,g)=>{if(A.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},Jr=(Q,A,B,g)=>{const I=B,E=Q._zod.def,{minimum:i,maximum:C}=Q._zod.bag;typeof i=="number"&&(I.minItems=i),typeof C=="number"&&(I.maxItems=C),I.type="array",I.items=mA(E.element,A,{...g,path:[...g.path,"items"]})},qr=(Q,A,B,g)=>{const I=B,E=Q._zod.def;I.type="object",I.properties={};const i=E.shape;for(const e in i)I.properties[e]=mA(i[e],A,{...g,path:[...g.path,"properties",e]});const C=new Set(Object.keys(i)),a=new Set([...C].filter(e=>{const o=E.shape[e]._zod;return A.io==="input"?o.optin===void 0:o.optout===void 0}));a.size>0&&(I.required=Array.from(a)),E.catchall?._zod.def.type==="never"?I.additionalProperties=!1:E.catchall?E.catchall&&(I.additionalProperties=mA(E.catchall,A,{...g,path:[...g.path,"additionalProperties"]})):A.io==="output"&&(I.additionalProperties=!1)},xr=(Q,A,B,g)=>{const I=Q._zod.def,E=I.inclusive===!1,i=I.options.map((C,a)=>mA(C,A,{...g,path:[...g.path,E?"oneOf":"anyOf",a]}));E?B.oneOf=i:B.anyOf=i},Vr=(Q,A,B,g)=>{const I=Q._zod.def,E=mA(I.left,A,{...g,path:[...g.path,"allOf",0]}),i=mA(I.right,A,{...g,path:[...g.path,"allOf",1]}),C=e=>"allOf"in e&&Object.keys(e).length===1,a=[...C(E)?E.allOf:[E],...C(i)?i.allOf:[i]];B.allOf=a},Lr=(Q,A,B,g)=>{const I=B,E=Q._zod.def;I.type="object";const i=E.keyType,a=i._zod.bag?.patterns;if(E.mode==="loose"&&a&&a.size>0){const o=mA(E.valueType,A,{...g,path:[...g.path,"patternProperties","*"]});I.patternProperties={};for(const t of a)I.patternProperties[t.source]=o}else(A.target==="draft-07"||A.target==="draft-2020-12")&&(I.propertyNames=mA(E.keyType,A,{...g,path:[...g.path,"propertyNames"]})),I.additionalProperties=mA(E.valueType,A,{...g,path:[...g.path,"additionalProperties"]});const e=i._zod.values;if(e){const o=[...e].filter(t=>typeof t=="string"||typeof t=="number");o.length>0&&(I.required=o)}},Xr=(Q,A,B,g)=>{const I=Q._zod.def,E=mA(I.innerType,A,g),i=A.seen.get(Q);A.target==="openapi-3.0"?(i.ref=I.innerType,B.nullable=!0):B.anyOf=[E,{type:"null"}]},vr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType},Kr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType,B.default=JSON.parse(JSON.stringify(I.defaultValue))},zr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType,A.io==="input"&&(B._prefault=JSON.parse(JSON.stringify(I.defaultValue)))},Tr=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType;let i;try{i=I.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}B.default=i},jr=(Q,A,B,g)=>{const I=Q._zod.def,E=A.io==="input"?I.in._zod.def.type==="transform"?I.out:I.in:I.out;mA(E,A,g);const i=A.seen.get(Q);i.ref=E},Or=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType,B.readOnly=!0},Pe=(Q,A,B,g)=>{const I=Q._zod.def;mA(I.innerType,A,g);const E=A.seen.get(Q);E.ref=I.innerType},Pr=Z("ZodISODateTime",(Q,A)=>{Ac.init(Q,A),lA.init(Q,A)});function _r(Q){return Er(Pr,Q)}const $r=Z("ZodISODate",(Q,A)=>{Bc.init(Q,A),lA.init(Q,A)});function Al(Q){return ir($r,Q)}const Bl=Z("ZodISOTime",(Q,A)=>{gc.init(Q,A),lA.init(Q,A)});function gl(Q){return Cr(Bl,Q)}const Il=Z("ZodISODuration",(Q,A)=>{Ic.init(Q,A),lA.init(Q,A)});function Ql(Q){return ar(Il,Q)}const PA=Z("ZodError",(Q,A)=>{le.init(Q,A),Q.name="ZodError",Object.defineProperties(Q,{format:{value:B=>zn(Q,B)},flatten:{value:B=>Kn(Q,B)},addIssue:{value:B=>{Q.issues.push(B),Q.message=JSON.stringify(Q.issues,ZE,2)}},addIssues:{value:B=>{Q.issues.push(...B),Q.message=JSON.stringify(Q.issues,ZE,2)}},isEmpty:{get(){return Q.issues.length===0}}})},{Parent:Error}),El=JE(PA),il=qE(PA),Cl=JI(PA),al=qI(PA),el=On(PA),ol=Pn(PA),tl=_n(PA),sl=$n(PA),Gl=Ah(PA),nl=Bh(PA),hl=gh(PA),cl=Ih(PA),MA=Z("ZodType",(Q,A)=>(FA.init(Q,A),Object.assign(Q["~standard"],{jsonSchema:{input:vI(Q,"input"),output:vI(Q,"output")}}),Q.toJSONSchema=br(Q,{}),Q.def=A,Q.type=A.type,Object.defineProperty(Q,"_def",{value:A}),Q.check=(...B)=>Q.clone(kB(A,{checks:[...A.checks??[],...B.map(g=>typeof g=="function"?{_zod:{check:g,def:{check:"custom"},onattach:[]}}:g)]}),{parent:!0}),Q.with=Q.check,Q.clone=(B,g)=>ZB(Q,B,g),Q.brand=()=>Q,Q.register=((B,g)=>(B.add(Q,g),Q)),Q.parse=(B,g)=>El(Q,B,g,{callee:Q.parse}),Q.safeParse=(B,g)=>Cl(Q,B,g),Q.parseAsync=async(B,g)=>il(Q,B,g,{callee:Q.parseAsync}),Q.safeParseAsync=async(B,g)=>al(Q,B,g),Q.spa=Q.safeParseAsync,Q.encode=(B,g)=>el(Q,B,g),Q.decode=(B,g)=>ol(Q,B,g),Q.encodeAsync=async(B,g)=>tl(Q,B,g),Q.decodeAsync=async(B,g)=>sl(Q,B,g),Q.safeEncode=(B,g)=>Gl(Q,B,g),Q.safeDecode=(B,g)=>nl(Q,B,g),Q.safeEncodeAsync=async(B,g)=>hl(Q,B,g),Q.safeDecodeAsync=async(B,g)=>cl(Q,B,g),Q.refine=(B,g)=>Q.check(aD(B,g)),Q.superRefine=B=>Q.check(eD(B)),Q.overwrite=B=>Q.check(ng(B)),Q.optional=()=>Qo(Q),Q.exactOptional=()=>jl(Q),Q.nullable=()=>Eo(Q),Q.nullish=()=>Qo(Eo(Q)),Q.nonoptional=B=>BD(Q,B),Q.array=()=>UA(Q),Q.or=B=>KE([Q,B]),Q.and=B=>Xl(Q,B),Q.transform=B=>Co(Q,zl(B)),Q.default=B=>_l(Q,B),Q.prefault=B=>AD(Q,B),Q.catch=B=>ID(Q,B),Q.pipe=B=>Co(Q,B),Q.readonly=()=>iD(Q),Q.describe=B=>{const g=Q.clone();return Vg.add(g,{description:B}),g},Object.defineProperty(Q,"description",{get(){return Vg.get(Q)?.description},configurable:!0}),Q.meta=(...B)=>{if(B.length===0)return Vg.get(Q);const g=Q.clone();return Vg.add(g,B[0]),g},Q.isOptional=()=>Q.safeParse(void 0).success,Q.isNullable=()=>Q.safeParse(null).success,Q.apply=B=>B(Q),Q)),_e=Z("_ZodString",(Q,A)=>{xE.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(g,I,E)=>Yr(Q,g,I);const B=Q._zod.bag;Q.format=B.format??null,Q.minLength=B.minimum??null,Q.maxLength=B.maximum??null,Q.regex=(...g)=>Q.check(nr(...g)),Q.includes=(...g)=>Q.check(rr(...g)),Q.startsWith=(...g)=>Q.check(lr(...g)),Q.endsWith=(...g)=>Q.check(Dr(...g)),Q.min=(...g)=>Q.check(XI(...g)),Q.max=(...g)=>Q.check(Ke(...g)),Q.length=(...g)=>Q.check(ze(...g)),Q.nonempty=(...g)=>Q.check(XI(1,...g)),Q.lowercase=g=>Q.check(hr(g)),Q.uppercase=g=>Q.check(cr(g)),Q.trim=()=>Q.check(Fr()),Q.normalize=(...g)=>Q.check(dr(...g)),Q.toLowerCase=()=>Q.check(Mr()),Q.toUpperCase=()=>Q.check(wr()),Q.slugify=()=>Q.check(yr())}),rl=Z("ZodString",(Q,A)=>{xE.init(Q,A),_e.init(Q,A),Q.email=B=>Q.check(Nc(ll,B)),Q.url=B=>Q.check(Lc(Dl,B)),Q.jwt=B=>Q.check(Qr(Zl,B)),Q.emoji=B=>Q.check(Xc(dl,B)),Q.guid=B=>Q.check(Ve($e,B)),Q.uuid=B=>Q.check(Jc(KI,B)),Q.uuidv4=B=>Q.check(qc(KI,B)),Q.uuidv6=B=>Q.check(xc(KI,B)),Q.uuidv7=B=>Q.check(Vc(KI,B)),Q.nanoid=B=>Q.check(vc(Fl,B)),Q.guid=B=>Q.check(Ve($e,B)),Q.cuid=B=>Q.check(Kc(Ml,B)),Q.cuid2=B=>Q.check(zc(wl,B)),Q.ulid=B=>Q.check(Tc(yl,B)),Q.base64=B=>Q.check(Br(Yl,B)),Q.base64url=B=>Q.check(gr(Ul,B)),Q.xid=B=>Q.check(jc(Rl,B)),Q.ksuid=B=>Q.check(Oc(ml,B)),Q.ipv4=B=>Q.check(Pc(ul,B)),Q.ipv6=B=>Q.check(_c(Sl,B)),Q.cidrv4=B=>Q.check($c(bl,B)),Q.cidrv6=B=>Q.check(Ar(pl,B)),Q.e164=B=>Q.check(Ir(kl,B)),Q.datetime=B=>Q.check(_r(B)),Q.date=B=>Q.check(Al(B)),Q.time=B=>Q.check(gl(B)),Q.duration=B=>Q.check(Ql(B))});function z(Q){return fc(rl,Q)}const lA=Z("ZodStringFormat",(Q,A)=>{cA.init(Q,A),_e.init(Q,A)}),ll=Z("ZodEmail",(Q,A)=>{vh.init(Q,A),lA.init(Q,A)}),$e=Z("ZodGUID",(Q,A)=>{Lh.init(Q,A),lA.init(Q,A)}),KI=Z("ZodUUID",(Q,A)=>{Xh.init(Q,A),lA.init(Q,A)}),Dl=Z("ZodURL",(Q,A)=>{Kh.init(Q,A),lA.init(Q,A)}),dl=Z("ZodEmoji",(Q,A)=>{zh.init(Q,A),lA.init(Q,A)}),Fl=Z("ZodNanoID",(Q,A)=>{Th.init(Q,A),lA.init(Q,A)}),Ml=Z("ZodCUID",(Q,A)=>{jh.init(Q,A),lA.init(Q,A)}),wl=Z("ZodCUID2",(Q,A)=>{Oh.init(Q,A),lA.init(Q,A)}),yl=Z("ZodULID",(Q,A)=>{Ph.init(Q,A),lA.init(Q,A)}),Rl=Z("ZodXID",(Q,A)=>{_h.init(Q,A),lA.init(Q,A)}),ml=Z("ZodKSUID",(Q,A)=>{$h.init(Q,A),lA.init(Q,A)}),ul=Z("ZodIPv4",(Q,A)=>{Qc.init(Q,A),lA.init(Q,A)}),Sl=Z("ZodIPv6",(Q,A)=>{Ec.init(Q,A),lA.init(Q,A)}),bl=Z("ZodCIDRv4",(Q,A)=>{ic.init(Q,A),lA.init(Q,A)}),pl=Z("ZodCIDRv6",(Q,A)=>{Cc.init(Q,A),lA.init(Q,A)}),Yl=Z("ZodBase64",(Q,A)=>{ac.init(Q,A),lA.init(Q,A)}),Ul=Z("ZodBase64URL",(Q,A)=>{oc.init(Q,A),lA.init(Q,A)}),kl=Z("ZodE164",(Q,A)=>{tc.init(Q,A),lA.init(Q,A)}),Zl=Z("ZodJWT",(Q,A)=>{Gc.init(Q,A),lA.init(Q,A)}),Ao=Z("ZodNumber",(Q,A)=>{be.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(g,I,E)=>Ur(Q,g,I),Q.gt=(g,I)=>Q.check(Xe(g,I)),Q.gte=(g,I)=>Q.check(XE(g,I)),Q.min=(g,I)=>Q.check(XE(g,I)),Q.lt=(g,I)=>Q.check(Le(g,I)),Q.lte=(g,I)=>Q.check(LE(g,I)),Q.max=(g,I)=>Q.check(LE(g,I)),Q.int=g=>Q.check(Bo(g)),Q.safe=g=>Q.check(Bo(g)),Q.positive=g=>Q.check(Xe(0,g)),Q.nonnegative=g=>Q.check(XE(0,g)),Q.negative=g=>Q.check(Le(0,g)),Q.nonpositive=g=>Q.check(LE(0,g)),Q.multipleOf=(g,I)=>Q.check(ve(g,I)),Q.step=(g,I)=>Q.check(ve(g,I)),Q.finite=()=>Q;const B=Q._zod.bag;Q.minValue=Math.max(B.minimum??Number.NEGATIVE_INFINITY,B.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,Q.maxValue=Math.min(B.maximum??Number.POSITIVE_INFINITY,B.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,Q.isInt=(B.format??"").includes("int")||Number.isSafeInteger(B.multipleOf??.5),Q.isFinite=!0,Q.format=B.format??null});function X(Q){return er(Ao,Q)}const Wl=Z("ZodNumberFormat",(Q,A)=>{nc.init(Q,A),Ao.init(Q,A)});function Bo(Q){return or(Wl,Q)}const Hl=Z("ZodBoolean",(Q,A)=>{hc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>kr(Q,B,g)});function vE(Q){return tr(Hl,Q)}const fl=Z("ZodUnknown",(Q,A)=>{cc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Wr()});function go(){return sr(fl)}const Nl=Z("ZodNever",(Q,A)=>{rc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Zr(Q,B,g)});function Jl(Q){return Gr(Nl,Q)}const ql=Z("ZodArray",(Q,A)=>{lc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Jr(Q,B,g,I),Q.element=A.element,Q.min=(B,g)=>Q.check(XI(B,g)),Q.nonempty=B=>Q.check(XI(1,B)),Q.max=(B,g)=>Q.check(Ke(B,g)),Q.length=(B,g)=>Q.check(ze(B,g)),Q.unwrap=()=>Q.element});function UA(Q,A){return Rr(ql,Q,A)}const xl=Z("ZodObject",(Q,A)=>{dc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>qr(Q,B,g,I),tA(Q,"shape",()=>A.shape),Q.keyof=()=>TI(Object.keys(Q._zod.def.shape)),Q.catchall=B=>Q.clone({...Q._zod.def,catchall:B}),Q.passthrough=()=>Q.clone({...Q._zod.def,catchall:go()}),Q.loose=()=>Q.clone({...Q._zod.def,catchall:go()}),Q.strict=()=>Q.clone({...Q._zod.def,catchall:Jl()}),Q.strip=()=>Q.clone({...Q._zod.def,catchall:void 0}),Q.extend=B=>xn(Q,B),Q.safeExtend=B=>Vn(Q,B),Q.merge=B=>Ln(Q,B),Q.pick=B=>Jn(Q,B),Q.omit=B=>qn(Q,B),Q.partial=(...B)=>Xn(Io,Q,B[0]),Q.required=(...B)=>vn(io,Q,B[0])});function nA(Q,A){const B={type:"object",shape:Q??{},...$(A)};return new xl(B)}const Vl=Z("ZodUnion",(Q,A)=>{Fc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>xr(Q,B,g,I),Q.options=A.options});function KE(Q,A){return new Vl({type:"union",options:Q,...$(A)})}const Ll=Z("ZodIntersection",(Q,A)=>{Mc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Vr(Q,B,g,I)});function Xl(Q,A){return new Ll({type:"intersection",left:Q,right:A})}const vl=Z("ZodRecord",(Q,A)=>{wc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Lr(Q,B,g,I),Q.keyType=A.keyType,Q.valueType=A.valueType});function zI(Q,A,B){return new vl({type:"record",keyType:Q,valueType:A,...$(B)})}const zE=Z("ZodEnum",(Q,A)=>{yc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(g,I,E)=>Hr(Q,g,I),Q.enum=A.entries,Q.options=Object.values(A.entries);const B=new Set(Object.keys(A.entries));Q.extract=(g,I)=>{const E={};for(const i of g)if(B.has(i))E[i]=A.entries[i];else throw new Error(`Key ${i} not found in enum`);return new zE({...A,checks:[],...$(I),entries:E})},Q.exclude=(g,I)=>{const E={...A.entries};for(const i of g)if(B.has(i))delete E[i];else throw new Error(`Key ${i} not found in enum`);return new zE({...A,checks:[],...$(I),entries:E})}});function TI(Q,A){const B=Array.isArray(Q)?Object.fromEntries(Q.map(g=>[g,g])):Q;return new zE({type:"enum",entries:B,...$(A)})}const Kl=Z("ZodTransform",(Q,A)=>{Rc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Nr(Q,B),Q._zod.parse=(B,g)=>{if(g.direction==="backward")throw new oe(Q.constructor.name);B.addIssue=E=>{if(typeof E=="string")B.issues.push(xg(E,B.value,A));else{const i=E;i.fatal&&(i.continue=!1),i.code??(i.code="custom"),i.input??(i.input=B.value),i.inst??(i.inst=Q),B.issues.push(xg(i))}};const I=A.transform(B.value,B);return I instanceof Promise?I.then(E=>(B.value=E,B)):(B.value=I,B)}});function zl(Q){return new Kl({type:"transform",transform:Q})}const Io=Z("ZodOptional",(Q,A)=>{He.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Pe(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function Qo(Q){return new Io({type:"optional",innerType:Q})}const Tl=Z("ZodExactOptional",(Q,A)=>{mc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Pe(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function jl(Q){return new Tl({type:"optional",innerType:Q})}const Ol=Z("ZodNullable",(Q,A)=>{uc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Xr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function Eo(Q){return new Ol({type:"nullable",innerType:Q})}const Pl=Z("ZodDefault",(Q,A)=>{Sc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Kr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType,Q.removeDefault=Q.unwrap});function _l(Q,A){return new Pl({type:"default",innerType:Q,get defaultValue(){return typeof A=="function"?A():ce(A)}})}const $l=Z("ZodPrefault",(Q,A)=>{bc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>zr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function AD(Q,A){return new $l({type:"prefault",innerType:Q,get defaultValue(){return typeof A=="function"?A():ce(A)}})}const io=Z("ZodNonOptional",(Q,A)=>{pc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>vr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function BD(Q,A){return new io({type:"nonoptional",innerType:Q,...$(A)})}const gD=Z("ZodCatch",(Q,A)=>{Yc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Tr(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType,Q.removeCatch=Q.unwrap});function ID(Q,A){return new gD({type:"catch",innerType:Q,catchValue:typeof A=="function"?A:()=>A})}const QD=Z("ZodPipe",(Q,A)=>{Uc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>jr(Q,B,g,I),Q.in=A.in,Q.out=A.out});function Co(Q,A){return new QD({type:"pipe",in:Q,out:A})}const ED=Z("ZodReadonly",(Q,A)=>{kc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>Or(Q,B,g,I),Q.unwrap=()=>Q._zod.def.innerType});function iD(Q){return new ED({type:"readonly",innerType:Q})}const CD=Z("ZodCustom",(Q,A)=>{Zc.init(Q,A),MA.init(Q,A),Q._zod.processJSONSchema=(B,g,I)=>fr(Q,B)});function aD(Q,A={}){return mr(CD,Q,A)}function eD(Q){return ur(Q)}const oD=pB.map(Q=>Q),ao=nA({id:z(),uuid:z(),playlist_index:X().nonnegative(),chain_name:z(),token_address:z().optional(),token_id:z().optional(),tx_id:z().optional(),platform:z(),title:z(),artist:z(),description:z().optional(),album:z().optional(),image_url:z().url(),image_thumb_url:z().url().optional(),audio_url:z().url(),audio_url_lossless:z().url().optional(),duration:X().nonnegative(),genre:z(),tags:UA(z()),bpm:X().positive().optional(),key:z().optional(),attributes:zI(z(),KE([z(),X()])).optional()}).refine(Q=>Q.chain_name==="AR"?!!Q.tx_id:!!Q.token_address&&!!Q.token_id,{message:"AR chain tracks must have tx_id; other chains must have token_address and token_id",path:["chain_name"]}),tD=nA({name:z(),description:z().optional(),image:z().url(),creator:z(),genre:z().optional(),tags:UA(z()).optional(),tracks:UA(ao)}),sD=nA({bass_dominance:X().min(0).max(1),mid_dominance:X().min(0).max(1),treble_dominance:X().min(0).max(1),average_amplitude:X().min(0).max(1),spectral_centroid:X().optional(),spectral_rolloff:X().optional(),zero_crossing_rate:X().optional(),color_palette:nA({colors:UA(z()),primary_color:z(),secondary_color:z().optional(),accent_color:z().optional(),brightness:X().min(0).max(1),saturation:X().min(0).max(1),is_monochrome:vE()}).optional(),analysis_metadata:nA({duration_analyzed:X().positive(),full_buffer_analyzed:vE(),sample_positions:UA(X()),analyzed_at:z()})}),TE=nA({STR:X().min(1).max(20),DEX:X().min(1).max(20),CON:X().min(1).max(20),INT:X().min(1).max(20),WIS:X().min(1).max(20),CHA:X().min(1).max(20)}),GD=nA({name:z(),race:TI(["Human","Elf","Dwarf","Halfling","Dragonborn","Gnome","Half-Elf","Half-Orc","Tiefling"]),class:TI(oD),level:X().min(1).max(20),ability_scores:TE,ability_modifiers:TE,proficiency_bonus:X().min(2).max(6),hp:nA({current:X().nonnegative(),max:X().positive(),temp:X().nonnegative()}),armor_class:X().positive(),initiative:X(),speed:X().positive(),skills:zI(z(),TI(["none","proficient","expertise"])),saving_throws:zI(z(),vE()),racial_traits:UA(z()),class_features:UA(z()),spells:nA({spell_slots:zI(z(),nA({total:X().nonnegative(),used:X().nonnegative()})),known_spells:UA(z()),cantrips:UA(z())}).optional(),equipment:nA({weapons:UA(z()),armor:UA(z()),items:UA(z())}).optional(),appearance:nA({body_type:z(),skin_tone:z(),hair_style:z(),hair_color:z(),eye_color:z(),facial_features:UA(z()),primary_color:z().optional(),secondary_color:z().optional(),aura_color:z().optional()}).optional(),xp:nA({current:X().nonnegative(),next_level:X().positive()}),seed:z(),generated_at:z()});var eo=(Q=>(Q[Q.DEBUG=0]="DEBUG",Q[Q.INFO=1]="INFO",Q[Q.WARN=2]="WARN",Q[Q.ERROR=3]="ERROR",Q[Q.NONE=4]="NONE",Q))(eo||{});const nD={0:"DEBUG",1:"INFO",2:"WARN",3:"ERROR",4:"NONE"};let eB=1,jE=!0,OE=!0,jI=null,OI=!1,Lg=!1;class SA{constructor(A){this.context=A}static for(A){return new SA(A)}static enableDiagnosticMode(){OI=!0,eB=0}static disableDiagnosticMode(){OI=!1,eB=1}static isDiagnosticMode(){return OI}static enableVerbose(){Lg=!0,eB=0}static disableVerbose(){Lg=!1,eB=1}static isVerbose(){return Lg}static setVerbose(A){Lg=A,eB=A?0:1}static setLevel(A){eB=A}static getLevel(){return eB}static configure(A){A.level!==void 0&&(eB=A.level),A.includeTimestamp!==void 0&&(jE=A.includeTimestamp),A.includeContext!==void 0&&(OE=A.includeContext),A.customHandler!==void 0&&(jI=A.customHandler)}static reset(){eB=1,jE=!0,OE=!0,jI=null,OI=!1,Lg=!1}debug(A,B){this.log(0,A,B)}info(A,B){this.log(1,A,B)}warn(A,B){this.log(2,A,B)}error(A,B){this.log(3,A,B)}log(A,B,g){if(A<eB)return;const I={timestamp:new Date,level:A,context:this.context,message:B,data:g};if(jI){jI(I);return}const E=this.formatMessage(I);switch(A){case 0:g!==void 0?console.debug(E,g):console.debug(E);break;case 1:g!==void 0?console.info(E,g):console.info(E);break;case 2:g!==void 0?console.warn(E,g):console.warn(E);break;case 3:g!==void 0?console.error(E,g):console.error(E);break}}formatMessage(A){const B=[];return jE&&B.push(this.formatTimestamp(A.timestamp)),B.push(`[${nD[A.level]}]`),OE&&A.context&&B.push(`[${A.context}]`),B.push(A.message),B.join(" ")}formatTimestamp(A){const B=A.getHours().toString().padStart(2,"0"),g=A.getMinutes().toString().padStart(2,"0"),I=A.getSeconds().toString().padStart(2,"0"),E=A.getMilliseconds().toString().padStart(3,"0");return`${B}:${g}:${I}.${E}`}}function hD(Q){return SA.for(Q)}class IA{static extractAudioUrl(A){const B=["mp3_url","lossy_audio","audio_url","lossless_audio","animation_url","audio","multimedia_url","losslessAudio"];for(const g of B)if(A[g]&&typeof A[g]=="string")return A[g];return null}static extractAudioUrlLossless(A){const B=["audio_url","lossless_audio","wav_url","flac_url","losslessAudio"];for(const g of B)if(A[g]&&typeof A[g]=="string")return A[g];return null}static extractImageUrl(A){const B=["image_small","image","image_large","image_thumb","image_url","image_uri","image_preview"];for(const I of B)if(A[I]&&typeof A[I]=="string")return A[I];const g=[this.extractNestedUri(A,"artwork","uri"),this.extractNestedUri(A,"project","artwork","uri"),this.extractNestedUri(A,"primaryMedia","uri")];for(const I of g)if(I)return I;return null}static extractImageThumbUrl(A){return A.image_thumb_url&&typeof A.image_thumb_url=="string"?A.image_thumb_url:A.image_thumb&&typeof A.image_thumb=="string"?A.image_thumb:null}static extractTitle(A){return A.name&&typeof A.name=="string"?A.name:A.title&&typeof A.title=="string"?A.title:null}static extractArtist(A){const B=["artist","created_by","minter"];for(const g of B)if(A[g]&&typeof A[g]=="string")return A[g];return null}static parseMetadata(A){if(!A)return null;if(typeof A=="object"&&!Array.isArray(A))return A;if(typeof A=="string")try{const B=JSON.parse(A);if(typeof B=="object"&&!Array.isArray(B))return B}catch(B){return console.warn("Failed to parse metadata:",B),null}return null}static extractGenre(A){if(typeof A.genre=="string")return A.genre;if(Array.isArray(A.genre)&&A.genre.length>0){const B=A.genre[0];return typeof B=="string"?B:""}if(Array.isArray(A.attributes)){const B=A.attributes.find(g=>g.trait_type?.toLowerCase()==="genre"&&g.value!==void 0);if(B){if(typeof B.value=="string")return B.value;if(Array.isArray(B.value)&&B.value.length>0){const g=B.value[0];return typeof g=="string"?g:""}}}return""}static convertAttributes(A){if(!Array.isArray(A))return null;const B={};for(const g of A)g.trait_type&&g.value!==void 0&&(B[g.trait_type]=g.value);return Object.keys(B).length>0?B:null}static extractNestedUri(A,...B){let g=A;for(const I of B)if(g&&typeof g=="object"&&!Array.isArray(g))g=g[I];else return null;return typeof g=="string"?g:null}}function PE(Q){if("audio_url"in Q&&typeof Q.audio_url=="string")return Q.audio_url;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractAudioUrl(A)}return null}function cD(Q){if("audio_url_lossless"in Q&&typeof Q.audio_url_lossless=="string")return Q.audio_url_lossless;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractAudioUrlLossless(A)}return null}function _E(Q){if("image_url"in Q&&typeof Q.image_url=="string")return Q.image_url;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractImageUrl(A)}return null}function oo(Q){if("image_thumb_url"in Q&&typeof Q.image_thumb_url=="string")return Q.image_thumb_url;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A)return IA.extractImageThumbUrl(A)}return null}function to(Q){if("audio_url"in Q)return null;if("metadata"in Q){const A=IA.parseMetadata(Q.metadata);if(A&&typeof A.vrm=="string"&&A.vrm)return A.vrm}return null}function rD(Q){const A=[];for(const B of Q.tracks){const g=PE(B);g&&A.push(g)}return A}function lD(Q){const A=[];for(const B of Q.tracks){const g=_E(B);g&&A.push(g)}return A}function DD(Q){const A=[];for(const B of Q.tracks){if("title"in B&&typeof B.title=="string"){A.push(B.title);continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g){const I=IA.extractTitle(g);I&&A.push(I)}}}return A}function dD(Q){const A=[];for(const B of Q.tracks){if("artist"in B&&typeof B.artist=="string"){A.push(B.artist);continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g){const I=IA.extractArtist(g);I&&A.push(I)}}}return A}function FD(Q){const A=new Set;for(const B of Q.tracks){if("genre"in B&&typeof B.genre=="string"&&B.genre){A.add(B.genre);continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);g&&typeof g.genre=="string"&&g.genre&&A.add(g.genre)}}return Array.from(A).sort()}function MD(Q){const A=new Set;for(const B of Q.tracks){if("tags"in B&&Array.isArray(B.tags)){for(const g of B.tags)g&&A.add(g.toLowerCase());continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g&&Array.isArray(g.tags))for(const I of g.tags)I&&A.add(String(I).toLowerCase())}}return Array.from(A).sort()}function wD(Q){let A=0;for(const B of Q.tracks){if("duration"in B&&typeof B.duration=="number"){A+=B.duration;continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);g&&typeof g.duration=="number"&&(A+=g.duration)}}return A}function yD(Q){return Q.tracks.length}function RD(Q){const A=[];for(const B of Q.tracks){const g=PE(B),I=_E(B),E=oo(B);let i="",C="";if("title"in B)i=B.title||"",C=B.artist||"";else if("metadata"in B){const a=IA.parseMetadata(B.metadata);a&&(i=IA.extractTitle(a)||"",C=IA.extractArtist(a)||"")}if(g){const a={title:i,artist:C,audio_url:g,image_url:I||""},e=cD(B);e&&e!==g&&(a.audio_url_lossless=e),E&&(a.image_thumb_url=E),"audioIpfsHash"in B&&typeof B.audioIpfsHash=="string"&&(a.audioIpfsHash=B.audioIpfsHash),"artworkIpfsHash"in B&&typeof B.artworkIpfsHash=="string"&&(a.artworkIpfsHash=B.artworkIpfsHash),A.push(a)}}return A}function mD(Q){const A=[];for(const B of Q.tracks){if("audio_url"in B){A.push({...B});continue}if("metadata"in B){const g=IA.parseMetadata(B.metadata);if(g){const I=IA.extractAudioUrlLossless(g),E=IA.extractAudioUrl(g);A.push({id:B.chain_name==="AR"?`AR-${B.tx_id}`:`${B.chain_name}-${B.token_address}-${B.token_id}`,chain_name:B.chain_name,token_address:B.token_address,token_id:B.token_id,tx_id:B.tx_id,platform:B.platform,title:IA.extractTitle(g),artist:IA.extractArtist(g),audio_url:E,image_url:IA.extractImageUrl(g),image_thumb_url:IA.extractImageThumbUrl(g),duration:g.duration,genre:g.genre,tags:g.tags,bpm:g.bpm,key:g.key,album:g.album,description:g.description,attributes:IA.convertAttributes(g.attributes),...I&&I!==E?{audio_url_lossless:I}:{},...B.audioUrl?{audioUrl:B.audioUrl}:{},...B.artworkUrl?{artworkUrl:B.artworkUrl}:{},...B.audioIpfsHash?{audioIpfsHash:B.audioIpfsHash}:{},...B.artworkIpfsHash?{artworkIpfsHash:B.artworkIpfsHash}:{},...B["Mint-Function"]?{"Mint-Function":B["Mint-Function"]}:{},...B["Mint-Price"]?{"Mint-Price":B["Mint-Price"]}:{},...B["Mint-Snapshot-Time"]!=null?{"Mint-Snapshot-Time":B["Mint-Snapshot-Time"]}:{},...B["Mint-Token"]?{"Mint-Token":B["Mint-Token"]}:{}})}}}return A}function uD(Q){const A=[];for(const B of Q.tracks){const g=to(B);g&&A.push(g)}return A}function SD(Q){const A=[];for(const B of Q.tracks){const g=to(B);if(!g)continue;const I=PE(B),E=_E(B),i=oo(B);let C="",a="";if("title"in B)C=B.title||"",a=B.artist||"";else if("metadata"in B){const o=IA.parseMetadata(B.metadata);o&&(C=IA.extractTitle(o)||"",a=IA.extractArtist(o)||"")}const e={title:C,artist:a,audio_url:I||"",image_url:E||"",vrm:g};i&&(e.image_thumb_url=i),A.push(e)}return A}const $E=[{host:"arweave.net",protocol:"https",priority:3},{host:"ardrive.net",protocol:"https",priority:2},{host:"turbo-gateway.com",protocol:"https",priority:1}],Ai=["arweave.net","arweave.dev","www.arweave.net","ardrive.net","turbo-gateway.com","irys.xyz","ar-io.dev","ar-io.net","arweave.rocks","g8way.io"];function hg(Q){if(!Q||typeof Q!="string")return!1;if(Q.startsWith("ar://"))return!0;const A=Q.toLowerCase();try{const B=new URL(Q).hostname;return Ai.some(g=>B===g||B.endsWith("."+g))}catch{return Ai.some(B=>A.includes(B))}}function cg(Q){if(!Q||typeof Q!="string"||!hg(Q))return null;let A=null,B="";if(Q.startsWith("ar://")){const i=Q.slice(5),C=i.indexOf("/");return C!==-1?(A=i.slice(0,C),B=i.slice(C)):A=i,A.length===43&&/^[A-Za-z0-9_-]+$/.test(A)?{txId:A,originalUrl:Q,pathSuffix:B}:null}let g=Q;try{const i=new URL(Q);g=i.pathname+i.search}catch{}const I=/[A-Za-z0-9_-]{43}/g,E=g.match(I);if(E&&E.length>0){A=E[0];const i=Q.indexOf(A);if(i!==-1){const C=Q.slice(i+43),a=Math.min(C.indexOf("?")===-1?1/0:C.indexOf("?"),C.indexOf("#")===-1?1/0:C.indexOf("#"));a===1/0?B=C:B=C.slice(0,a)}return{txId:A,originalUrl:Q,pathSuffix:B}}return null}function oB(Q,A,B=""){return`${A.protocol||"https"}://${A.host}/${Q}${B}`}function bD(Q,A=$E,B=""){return A.sort((g,I)=>g.priority-I.priority).map(g=>oB(Q,g,B))}async function pD(){try{return await import("@ar.io/wayfinder-core")}catch{return null}}async function YD(){try{return await import("@ar.io/sdk")}catch{return null}}const UD=5e3,kD=864e5,Bi="arweave_active_gateway";class so{constructor(A){this.cache=new Map,this.logger=SA.for("ArweaveGateway"),this.hitCount=0,this.missCount=0,this.healthData=new Map,this.originalPriorities=new Map,this.MAX_HEALTH_RECORDS=50,this.inflightResolves=new Map,this.inflightControllers=new Map,this.wayfinder=null,this.activeGateway=null,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.gateways=(A?.gateways??$E).map(B=>({...B})),this.timeout=A?.timeout??UD,this.cacheTTL=A?.cacheTTL??kD,this.slowResponseThreshold=A?.slowResponseThreshold??8e3,this.maxSlowResponses=A?.maxSlowResponses??3,this.gateways.sort((B,g)=>B.priority-g.priority),this.gateways.forEach(B=>{this.originalPriorities.set(B.host,B.priority)}),this.activeGateway=this.loadPersistedGateway(),Promise.all([pD(),YD()]).then(([B,g])=>{if(B&&g)try{const{FastestPingRoutingStrategy:I,RandomRoutingStrategy:E,CompositeRoutingStrategy:i,NetworkGatewaysProvider:C}=B,a=g.ARIO,e=new C({ario:a.mainnet(),sortBy:"operatorStake",limit:10}),o=new C({ario:a.mainnet(),sortBy:"operatorStake",limit:20});this.wayfinder=B.createWayfinderClient({routingStrategy:new i({strategies:[new I({timeoutMs:3e3,gatewaysProvider:e}),new E({gatewaysProvider:o})]})}),this.logger.info("Wayfinder client initialized with FastestPing + Random fallback routing")}catch(I){this.logger.warn("Failed to configure Wayfinder routing strategy, using defaults",{error:I}),this.wayfinder=B.createWayfinderClient(),this.logger.info("Wayfinder client initialized with default routing")}else B&&(this.wayfinder=B.createWayfinderClient(),this.logger.info("Wayfinder client initialized with default routing (SDK unavailable)"))}).catch(()=>{this.logger.debug("Wayfinder client initialization failed, using static gateways")}),this.logger.info("Gateway manager initialized",{gateways:this.gateways.map(B=>B.host),timeout:this.timeout,cacheTTL:this.cacheTTL,activeGateway:this.activeGateway?.host??null})}withTimeout(A,B,g){return new Promise((I,E)=>{const i=setTimeout(()=>E(new Error(g)),B);A.then(C=>{clearTimeout(i),I(C)},C=>{clearTimeout(i),E(C)})})}resolveUrlSimple(A){if(!hg(A))return A;const B=cg(A);if(!B)return A;const g=this.activeGateway??this.gateways[0];return this.logger.debug("[gateway] resolveUrlSimple",{txId:B.txId,gateway:g.host,pathSuffix:B.pathSuffix||void 0}),oB(B.txId,g,B.pathSuffix)}setPreferredGateway(A){const B=this.gateways.find(g=>g.host===A);return B?(this.activeGateway=B,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.persistGateway(B),this.logger.info("Preferred gateway set",{host:A}),!0):(this.logger.warn("Cannot set preferred gateway — not in gateway list",{host:A,available:this.gateways.map(g=>g.host)}),!1)}clearPreferredGateway(){this.activeGateway=null,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.clearPersistedGateway(),this.cache.clear(),this.logger.info("Preferred gateway cleared, will re-discover on next resolve")}getDiagnostics(){const A=this.gateways.map(B=>{const g=this.healthData.get(B.host)??[],I=g.length,E=I>0?Math.round(g.reduce((C,a)=>C+a.responseTime,0)/I):0,i=I>0?g.filter(C=>C.success).length/I:1;return{host:B.host,avgMs:E,successRate:Math.round(i*100)/100,checks:I}});return{activeGateway:this.activeGateway?.host??null,activeGatewayAge:null,availableGateways:this.gateways.map(B=>B.host),lastFetchTiming:this.lastFetchTiming,consecutiveSlowResponses:this.consecutiveSlowResponses,healthSummary:A}}async resolveUrl(A,B){const g=B?.signal;if(g?.aborted)return this.logger.debug("resolveUrl called with already-aborted signal, returning original URL"),A;if(!hg(A))return A;const I=cg(A);if(!I)return this.logger.warn("Failed to parse Arweave URL, returning original",{url:A}),A;const{txId:E,pathSuffix:i}=I,C=this.getCachedGateway(E);if(C){this.hitCount++;const s=oB(E,C,i);return this.logger.debug("Cache hit for txId",{txId:E,gateway:C.host,pathSuffix:i}),s}const a=this.activeGateway?.host??"none";this.consecutiveSlowResponses>=this.maxSlowResponses&&(this.logger.warn("Proactive gateway rotation triggered",{slowCount:this.consecutiveSlowResponses,threshold:this.maxSlowResponses,previousGateway:a}),this.activeGateway=null,this.consecutiveSlowResponses=0,this.clearPersistedGateway(),this.cache.clear());const e=this.inflightResolves.get(E);if(e)return this.logger.debug("Reusing in-flight resolve for txId",{txId:E}),e;const o=new AbortController;g&&g.addEventListener("abort",()=>o.abort(),{once:!0});const t=this.resolveGatewayChain(A,E,i,o.signal,B).finally(()=>{this.inflightResolves.delete(E),this.inflightControllers.delete(E)});return this.inflightResolves.set(E,t),this.inflightControllers.set(E,o),t}async resolveGatewayChain(A,B,g,I,E){const i=Date.now(),C=E?.bypassArweaveNet??!1;let a=null;if(A.startsWith("https://")||A.startsWith("http://"))try{const s=new URL(A),G={host:s.host,protocol:s.protocol.replace(":",""),priority:0},n=Date.now(),h=await this.checkAndSetGateway(A,B,g,G,I),c=Date.now()-n;if(h)return this.logger.info("[gateway] Step 0 (original): success",{host:G.host,ms:c,totalMs:Date.now()-i}),h;this.logger.info("[gateway] Step 0 (original): failed",{host:G.host,ms:c}),a=G.host}catch{}if(this.activeGateway&&this.activeGateway.host!==a){const s=Date.now(),G=await this.checkAndSetGateway(A,B,g,this.activeGateway,I),n=Date.now()-s;if(G)return this.logger.info("[gateway] Step 1 (persisted): success",{host:this.activeGateway.host,ms:n,totalMs:Date.now()-i}),G;this.logger.info("[gateway] Step 1 (persisted): failed, clearing",{ms:n}),this.activeGateway=null,this.clearPersistedGateway()}if(!C&&a!=="arweave.net"){const s=this.gateways.find(G=>G.host==="arweave.net");if(s){const G=Date.now(),n=await this.checkAndSetGateway(A,B,g,s,I),h=Date.now()-G;if(n)return this.logger.info("[gateway] Step 2 (arweave.net): success",{ms:h,totalMs:Date.now()-i}),n;this.logger.info("[gateway] Step 2 (arweave.net): failed",{ms:h})}}const e=Date.now(),o=await this.tryFallbackGateways(A,B,g,I,a),t=Date.now()-e;if(o)return this.logger.info("[gateway] Step 3 (fallbacks): success",{ms:t,totalMs:Date.now()-i}),o;if(this.logger.info("[gateway] Step 3 (fallbacks): failed",{ms:t}),this.wayfinder&&!E?.bypassWayfinder){const s=Date.now();this.logger.info("[gateway] Step 4 (wayfinder): trying");const G=await this.tryWayfinder(A,B,g,I,a),n=Date.now()-s;if(G)return this.logger.info("[gateway] Step 4 (wayfinder): success",{ms:n,totalMs:Date.now()-i}),G;this.logger.info("[gateway] Step 4 (wayfinder): failed",{ms:n})}return this.logger.warn("All gateways (arweave.net + Wayfinder + fallbacks) failed, returning original URL",{txId:B,pathSuffix:g,originalUrl:A}),A}async reportGatewayFailure(A,B){const{signal:g,reason:I,excludeHost:E}=B??{};if(g?.aborted)return this.logger.debug("reportGatewayFailure called with already-aborted signal, returning original URL"),A;if(I==="user-cancel-fast")return this.logger.debug("User cancelled quickly, keeping current gateway"),A;const i=cg(A);if(!i)return A;const{txId:C,pathSuffix:a}=i;this.logger.warn("Gateway failure reported, finding new gateway",{failedHost:this.activeGateway?.host,txId:C,reason:I??"load-error"});const e=this.activeGateway?.host??E;this.activeGateway=null,this.cache.delete(C),this.clearPersistedGateway();const o=this.gateways.find(G=>G.host==="arweave.net"&&G.host!==e);if(o){const G=await this.checkAndSetGateway(A,C,a,o,g);if(G)return G}if(this.wayfinder){const G=await this.tryWayfinder(A,C,a,g);if(G)return G}const t=this.gateways;e&&(this.gateways=this.gateways.filter(G=>G.host!==e));const s=await this.tryFallbackGateways(A,C,a,g);return this.gateways=t,s||A}reportFetchSuccess(A){this.lastFetchTiming=A,A>=this.slowResponseThreshold?(this.consecutiveSlowResponses++,this.logger.warn("Slow fetch response recorded",{timingMs:A,threshold:this.slowResponseThreshold,consecutiveSlow:this.consecutiveSlowResponses,maxAllowed:this.maxSlowResponses,gateway:this.activeGateway?.host??"none"})):(this.consecutiveSlowResponses>0&&this.logger.info("Fetch timing recovered, resetting slow counter",{timingMs:A,previousSlowCount:this.consecutiveSlowResponses}),this.consecutiveSlowResponses=0)}async checkAndSetGateway(A,B,g,I,E){if(E?.aborted)return null;const i=await this.checkGateway(B,I,g,E);if(i===!0){this.setActiveGateway(I,B);const C=oB(B,I,g);return this.logger.info("Gateway resolved",{txId:B,gateway:I.host,pathSuffix:g,workingUrl:C}),C}if(i==="maybe"){const C=oB(B,I,g);return this.logger.info("Gateway maybe resolved (no-cors)",{txId:B,gateway:I.host,pathSuffix:g,workingUrl:C}),C}return null}async tryFallbackGateways(A,B,g,I,E){this.missCount++;const i=.7,C=3,a=this.gateways.filter(G=>G.host!=="arweave.net"&&G.host!==E),e=a.filter(G=>{const{rate:n,totalChecks:h}=this.getFailureRate(G.host);return!(h>=C&&n>i)}),o=e.length>0?e:a;if(I?.aborted||o.length===0)return null;const t=async G=>{if(I?.aborted||G.length===0)return null;const n=new AbortController,h=()=>n.abort();I?.addEventListener("abort",h,{once:!0});let c=!1;try{return await Promise.any(G.map(async l=>{const F=await this.checkGateway(B,l,g,n.signal);if(F){const m=oB(B,l,g);return c||(c=!0,F===!0?(this.setActiveGateway(l,B),this.logger.info("Gateway resolved via fallback",{txId:B,gateway:l.host,pathSuffix:g,workingUrl:m})):this.logger.info("Gateway maybe resolved via fallback (no-cors)",{txId:B,gateway:l.host,pathSuffix:g,workingUrl:m})),m}throw new Error(`Gateway ${l.host} failed check`)}))}catch{return null}finally{I?.removeEventListener("abort",h)}},s=await t(o);if(s)return s;if(e.length<a.length&&!I?.aborted){const G=a.filter(h=>!e.some(c=>c.host===h.host)).map(h=>h.host);this.logger.debug("Healthy gateways exhausted, retrying with previously unhealthy",{excludedHosts:G});const n=await t(a);if(n)return n}return null}async tryWayfinder(A,B,g,I,E){if(!this.wayfinder)return null;const i=3;for(let C=1;C<=i;C++){if(I?.aborted)return null;try{this.logger.debug(`Resolving via Wayfinder (attempt ${C}/${i})`,{txId:B});const a=await this.withTimeout(this.wayfinder.resolveUrl({originalUrl:A}),this.timeout+2e3,"Wayfinder resolution timed out");if(I?.aborted)return null;const e=a.hostname;if(E&&e===E){this.logger.debug(`Wayfinder resolved to already-failed host ${e}, retrying`,{attempt:C});continue}const o=a.protocol.replace(":",""),t={host:e,protocol:o,priority:0},s=await this.checkGateway(B,t,g,I);if(s){const G=oB(B,t,g);return s===!0?(this.setActiveGateway(t,B),this.logger.info("Gateway resolved via Wayfinder",{txId:B,gateway:e,attempt:C,pathSuffix:g,workingUrl:G})):this.logger.info("Gateway maybe resolved via Wayfinder (no-cors)",{txId:B,gateway:e,attempt:C,pathSuffix:g,workingUrl:G}),G}this.logger.debug(`Wayfinder attempt ${C} gateway did not pass check`,{host:e})}catch(a){this.logger.debug(`Wayfinder attempt ${C} failed`,{error:a})}}return null}setActiveGateway(A,B){this.activeGateway=A,this.lastFetchTiming=0,this.consecutiveSlowResponses=0,this.setCache(B,A),this.persistGateway(A)}loadPersistedGateway(){try{if(typeof localStorage>"u")return null;const A=localStorage.getItem(Bi);if(!A)return null;const B=JSON.parse(A);if(B&&typeof B.host=="string"&&typeof B.protocol=="string"){if(typeof B.timestamp=="number"&&Date.now()-B.timestamp>72e5)return this.logger.info("Ignoring persisted gateway — expired (older than 2 hours)",{host:B.host}),this.clearPersistedGateway(),null;this.logger.info("Restored active gateway from localStorage",{host:B.host});const{timestamp:I,...E}=B;return E}}catch{}return null}persistGateway(A){try{if(typeof localStorage>"u")return;const B={...A,timestamp:Date.now()};localStorage.setItem(Bi,JSON.stringify(B))}catch{}}clearPersistedGateway(){try{if(typeof localStorage>"u")return;localStorage.removeItem(Bi)}catch{}}async checkGateway(A,B,g="",I){const E=oB(A,B,g),i=Date.now(),C=new AbortController,a=setTimeout(()=>C.abort(),this.timeout),e=()=>C.abort();I?.addEventListener("abort",e,{once:!0});try{const o=await fetch(E,{method:"HEAD",mode:"cors",signal:C.signal});clearTimeout(a),I?.removeEventListener("abort",e);const t=Date.now()-i,s=o.ok||o.status>=200&&o.status<400;return this.recordGatewayResponse(B.host,t,s),s}catch(o){clearTimeout(a),I?.removeEventListener("abort",e);const t=Date.now()-i;if(this.recordGatewayResponse(B.host,t,!1),o instanceof Error&&o.name==="AbortError"){const s=I?.aborted;return this.logger.debug(s?"Gateway check aborted by external signal":"Gateway check timed out",{txId:A,gateway:B.host,timeout:this.timeout}),!1}if(o instanceof TypeError){this.logger.debug("HEAD failed (likely CORS), retrying with no-cors",{txId:A,gateway:B.host,error:o.message});try{await fetch(E,{method:"GET",mode:"no-cors",signal:C.signal});const s=Date.now()-i;return this.recordGatewayResponse(B.host,s,!0),"maybe"}catch{const s=Date.now()-i;return this.recordGatewayResponse(B.host,s,!1),!1}}return this.logger.debug("Gateway HEAD failed",{txId:A,gateway:B.host,error:o instanceof Error?o.message:String(o)}),!1}}getCachedGateway(A){const B=this.cache.get(A);return B?this.isCacheValid(B)?B.workingGateway:(this.cache.delete(A),null):null}setCache(A,B){const g={txId:A,workingGateway:B,timestamp:Date.now(),ttl:this.cacheTTL};this.cache.set(A,g),this.logger.debug("Cached working gateway",{txId:A,gateway:B.host})}clearCache(){const A=this.cache.size;this.cache.clear(),this.hitCount=0,this.missCount=0,this.logger.info("Cache cleared",{entriesRemoved:A})}invalidateCacheForUrl(A){if(!hg(A))return;const B=cg(A);B&&(this.cache.delete(B.txId),this.activeGateway=null,this.clearPersistedGateway())}async prefetchUrls(A,B){const g=B?.concurrency??5,I=B?.continueOnError??!0,E=[];let i=0,C=0,a=0;for(let e=0;e<A.length;e+=g){const o=A.slice(e,e+g),t=await Promise.allSettled(o.map(async s=>{if(!hg(s))return{url:s,txId:"",success:!1,error:"Not an Arweave URL"};const G=cg(s);if(!G)return{url:s,txId:"",success:!1,error:"Failed to parse Arweave URL"};const n=this.getCachedGateway(G.txId);if(n)return{url:s,txId:G.txId,success:!0,gateway:n};await this.resolveUrl(s);const h=this.getCachedGateway(G.txId);return h?{url:s,txId:G.txId,success:!0,gateway:h}:{url:s,txId:G.txId,success:!1,error:"All gateways failed"}}));for(const s of t)if(s.status==="fulfilled"){const G=s.value;E.push(G),G.error==="Not an Arweave URL"?a++:G.success?i++:C++}else C++,E.push({url:"unknown",txId:"",success:!1,error:s.reason?.message??"Unknown error"});if(!I&&C>0){this.logger.warn("Prefetch stopped due to failures",{failed:C,processed:E.length});break}}return this.logger.info("Prefetch complete",{total:A.length,succeeded:i,failed:C,skipped:a}),{total:A.length,succeeded:i,failed:C,skipped:a,entries:E}}getCacheStats(){const A=Array.from(this.cache.entries()),B=Date.now(),g=A.filter(([,I])=>B-I.timestamp<I.ttl).map(([I])=>I);return{size:g.length,txIds:g,hitCount:this.hitCount,missCount:this.missCount,ttl:this.cacheTTL}}getCacheEntries(){return Array.from(this.cache.values())}isCacheValid(A){return Date.now()-A.timestamp<A.ttl}getFailureRate(A){const B=this.healthData.get(A);return!B||B.length===0?{rate:0,totalChecks:0}:{rate:B.filter(I=>!I.success).length/B.length,totalChecks:B.length}}getAverageResponseTime(A){const B=this.healthData.get(A);return!B||B.length===0?0:B.reduce((g,I)=>g+I.responseTime,0)/B.length}recordGatewayResponse(A,B,g){this.healthData.has(A)||this.healthData.set(A,[]);const I=this.healthData.get(A);I.push({responseTime:B,success:g,timestamp:Date.now()}),I.length>this.MAX_HEALTH_RECORDS&&I.shift()}reportFetchTiming(A,B,g){this.recordGatewayResponse(A,B,g),this.logger.debug("Fetch timing reported",{host:A,timingMs:B,success:g})}getGatewayHealth(A){const B=this.gateways.find(s=>s.host===A);if(!B)return;const g=this.healthData.get(A)||[],I=this.originalPriorities.get(A)??B.priority;if(g.length===0)return{host:A,priority:B.priority,originalPriority:I,successCount:0,failureCount:0,totalChecks:0,successRate:0,averageResponseTime:0,lastSuccess:null,lastFailure:null,isHealthy:!0};const E=g.filter(s=>s.success).length,i=g.filter(s=>!s.success).length,C=E/g.length,a=Math.round(g.reduce((s,G)=>s+G.responseTime,0)/g.length),e=g.filter(s=>s.success).pop()?.timestamp??null,o=g.filter(s=>!s.success).pop()?.timestamp??null,t=C>=.5;return{host:A,priority:B.priority,originalPriority:I,successCount:E,failureCount:i,totalChecks:g.length,successRate:C,averageResponseTime:a,lastSuccess:e,lastFailure:o,isHealthy:t}}getAllGatewayHealth(){return this.gateways.map(A=>this.getGatewayHealth(A.host))}adjustGatewayPriorities(A){const B=A?.minChecks??3,g=A?.healthyThreshold??.5,E=this.getAllGatewayHealth().reduce((e,o)=>e+o.totalChecks,0);if(E<B)return this.logger.debug("Not enough health data to adjust priorities",{totalChecks:E,required:B}),[...this.gateways];const i=this.gateways.map((e,o)=>({gateway:e,originalIndex:o}));i.sort((e,o)=>{const t=this.getGatewayHealth(e.gateway.host),s=this.getGatewayHealth(o.gateway.host),G=t.successRate>=g||t.totalChecks===0,n=s.successRate>=g||s.totalChecks===0;if(G&&!n)return-1;if(!G&&n)return 1;if(t.totalChecks>0&&s.totalChecks>0){const h=t.averageResponseTime-s.averageResponseTime;if(Math.abs(h)>100)return h}if(t.totalChecks>0&&s.totalChecks>0){const h=s.successRate-t.successRate;if(Math.abs(h)>.1)return h}return e.originalIndex-o.originalIndex});const C=i.map(e=>e.gateway),a=Math.min(...Array.from(this.originalPriorities.values()));return C.forEach((e,o)=>{e.priority=a+o}),this.gateways=C,this.logger.info("Gateway priorities adjusted",{newOrder:this.gateways.map(e=>({host:e.host,priority:e.priority,health:this.getGatewayHealth(e.host)}))}),[...this.gateways]}async runHealthCheck(A){const B=Date.now(),g=A?.txId??"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk012345",I=A?.healthyThreshold??.5;A?.fastThreshold,this.logger.info("Starting gateway health check",{txId:g,gateways:this.gateways.map(n=>n.host)});const E=this.gateways.map(async n=>{const h=Date.now();let c=!1,d=this.timeout;try{const l=oB(g,n),F=new AbortController,m=setTimeout(()=>F.abort(),this.timeout),y=await fetch(l,{method:"HEAD",mode:"cors",signal:F.signal});clearTimeout(m),d=Date.now()-h,c=y.ok||y.status>=200&&y.status<400}catch{d=Date.now()-h,c=!1}return this.recordGatewayResponse(n.host,d,c),{host:n.host,success:c,responseTime:d}}),i=await Promise.all(E),C=this.getAllGatewayHealth(),a=[],e=[];let o=null,t=1/0;for(const n of i){const h=C.find(c=>c.host===n.host);n.success&&n.responseTime<t&&(t=n.responseTime,o=n.host),(h.successRate>=I||h.totalChecks===1)&&n.success?a.push(n.host):e.push(n.host)}const s=Date.now()-B;A?.adjustPriorities&&this.adjustGatewayPriorities({minChecks:A.minChecksForAdjustment??1,healthyThreshold:I});const G={timestamp:B,gateways:C,healthyGateways:a,unhealthyGateways:e,fastestGateway:o,totalTime:s};return this.logger.info("Health check complete",{healthyGateways:a,unhealthyGateways:e,fastestGateway:o,totalTime:s}),G}resetGatewayPriorities(){this.gateways.forEach(A=>{const B=this.originalPriorities.get(A.host);B!==void 0&&(A.priority=B)}),this.gateways.sort((A,B)=>{const g=this.originalPriorities.get(A.host)??A.priority,I=this.originalPriorities.get(B.host)??B.priority;return g-I}),this.logger.info("Gateway priorities reset to original values",{gateways:this.gateways.map(A=>({host:A.host,priority:A.priority}))})}clearHealthData(){this.healthData.clear(),this.logger.info("Health data cleared")}}const kA=new so,PI=["ipfs.io","cloudflare-ipfs.com","dweb.link","gateway.pinata.cloud","ipfs.infura.io","nftstorage.link","web3-music-pipeline.mypinata.cloud","soundxyz.mypinata.cloud","gold-broad-gibbon-29.mypinata.cloud","bonfire.mypinata.cloud","spinamp.mypinata.cloud","catalogworks.b-cdn.net","www.heds.cloud"],Go="ipfs.io",gi="/ipfs/";function no(Q){if(!Q||typeof Q!="string")return null;if(Q.startsWith("ipfs://ipfs/"))return Q.slice(12);if(Q.startsWith("ipfs://"))return Q.slice(7);try{const A=new URL(Q),{hostname:B,pathname:g}=A,I=B.match(/^([A-Za-z0-9]+)\.ipfs\.dweb\.link$/);if(I)return`${I[1]}${g}`;if(PI.some(i=>B===i||B.endsWith("."+i))&&g.startsWith(gi))return g.slice(gi.length)}catch{}return null}function ZD(Q){if(!Q||typeof Q!="string")return!1;if(Q.startsWith("ipfs://"))return!0;try{const A=new URL(Q),{hostname:B,pathname:g}=A;if(/^[A-Za-z0-9]+\.ipfs\.dweb\.link$/.test(B)||PI.some(E=>B===E||B.endsWith("."+E))&&g.startsWith(gi))return!0}catch{}return!1}function WD(Q){if(!(!Q||Q.startsWith("ipfs://")))try{const{hostname:A}=new URL(Q);return PI.some(g=>A===g||A.endsWith("."+g))?A:void 0}catch{return}}function HD(Q,A={}){if(!Q)return Q;const B=typeof A=="string"?{gatewayHost:A}:A,{gatewayHost:g=Go,preserveOriginalGateway:I=!1}=B,E=no(Q);if(E){if(I){const i=WD(Q);if(i)return`https://${i}/ipfs/${E}`}return`https://${g}/ipfs/${E}`}return Q}function _I(Q){throw new Error('Could not dynamically require "'+Q+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Ii={exports:{}};var ho;function fD(){return ho||(ho=1,(function(Q,A){(function(B){Q.exports=B()})(function(){return(function B(g,I,E){function i(e,o){if(!I[e]){if(!g[e]){var t=typeof _I=="function"&&_I;if(!o&&t)return t(e,!0);if(C)return C(e,!0);var s=new Error("Cannot find module '"+e+"'");throw s.code="MODULE_NOT_FOUND",s}var G=I[e]={exports:{}};g[e][0].call(G.exports,function(n){var h=g[e][1][n];return i(h||n)},G,G.exports,B,g,I,E)}return I[e].exports}for(var C=typeof _I=="function"&&_I,a=0;a<E.length;a++)i(E[a]);return i})({1:[function(B,g,I){(function(E){var i=E.MutationObserver||E.WebKitMutationObserver,C;if(i){var a=0,e=new i(n),o=E.document.createTextNode("");e.observe(o,{characterData:!0}),C=function(){o.data=a=++a%2}}else if(!E.setImmediate&&typeof E.MessageChannel<"u"){var t=new E.MessageChannel;t.port1.onmessage=n,C=function(){t.port2.postMessage(0)}}else"document"in E&&"onreadystatechange"in E.document.createElement("script")?C=function(){var c=E.document.createElement("script");c.onreadystatechange=function(){n(),c.onreadystatechange=null,c.parentNode.removeChild(c),c=null},E.document.documentElement.appendChild(c)}:C=function(){setTimeout(n,0)};var s,G=[];function n(){s=!0;for(var c,d,l=G.length;l;){for(d=G,G=[],c=-1;++c<l;)d[c]();l=G.length}s=!1}g.exports=h;function h(c){G.push(c)===1&&!s&&C()}}).call(this,typeof dI<"u"?dI:typeof self<"u"?self:typeof window<"u"?window:{})},{}],2:[function(B,g,I){var E=B(1);function i(){}var C={},a=["REJECTED"],e=["FULFILLED"],o=["PENDING"];g.exports=t;function t(y){if(typeof y!="function")throw new TypeError("resolver must be a function");this.state=o,this.queue=[],this.outcome=void 0,y!==i&&h(this,y)}t.prototype.catch=function(y){return this.then(null,y)},t.prototype.then=function(y,p){if(typeof y!="function"&&this.state===e||typeof p!="function"&&this.state===a)return this;var k=new this.constructor(i);if(this.state!==o){var H=this.state===e?y:p;G(k,H,this.outcome)}else this.queue.push(new s(k,y,p));return k};function s(y,p,k){this.promise=y,typeof p=="function"&&(this.onFulfilled=p,this.callFulfilled=this.otherCallFulfilled),typeof k=="function"&&(this.onRejected=k,this.callRejected=this.otherCallRejected)}s.prototype.callFulfilled=function(y){C.resolve(this.promise,y)},s.prototype.otherCallFulfilled=function(y){G(this.promise,this.onFulfilled,y)},s.prototype.callRejected=function(y){C.reject(this.promise,y)},s.prototype.otherCallRejected=function(y){G(this.promise,this.onRejected,y)};function G(y,p,k){E(function(){var H;try{H=p(k)}catch(T){return C.reject(y,T)}H===y?C.reject(y,new TypeError("Cannot resolve promise with itself")):C.resolve(y,H)})}C.resolve=function(y,p){var k=c(n,p);if(k.status==="error")return C.reject(y,k.value);var H=k.value;if(H)h(y,H);else{y.state=e,y.outcome=p;for(var T=-1,q=y.queue.length;++T<q;)y.queue[T].callFulfilled(p)}return y},C.reject=function(y,p){y.state=a,y.outcome=p;for(var k=-1,H=y.queue.length;++k<H;)y.queue[k].callRejected(p);return y};function n(y){var p=y&&y.then;if(y&&(typeof y=="object"||typeof y=="function")&&typeof p=="function")return function(){p.apply(y,arguments)}}function h(y,p){var k=!1;function H(EA){k||(k=!0,C.reject(y,EA))}function T(EA){k||(k=!0,C.resolve(y,EA))}function q(){p(T,H)}var v=c(q);v.status==="error"&&H(v.value)}function c(y,p){var k={};try{k.value=y(p),k.status="success"}catch(H){k.status="error",k.value=H}return k}t.resolve=d;function d(y){return y instanceof this?y:C.resolve(new this(i),y)}t.reject=l;function l(y){var p=new this(i);return C.reject(p,y)}t.all=F;function F(y){var p=this;if(Object.prototype.toString.call(y)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=y.length,H=!1;if(!k)return this.resolve([]);for(var T=new Array(k),q=0,v=-1,EA=new this(i);++v<k;)aA(y[v],v);return EA;function aA(GA,rA){p.resolve(GA).then(P,function(BA){H||(H=!0,C.reject(EA,BA))});function P(BA){T[rA]=BA,++q===k&&!H&&(H=!0,C.resolve(EA,T))}}}t.race=m;function m(y){var p=this;if(Object.prototype.toString.call(y)!=="[object Array]")return this.reject(new TypeError("must be an array"));var k=y.length,H=!1;if(!k)return this.resolve([]);for(var T=-1,q=new this(i);++T<k;)v(y[T]);return q;function v(EA){p.resolve(EA).then(function(aA){H||(H=!0,C.resolve(q,aA))},function(aA){H||(H=!0,C.reject(q,aA))})}}},{1:1}],3:[function(B,g,I){(function(E){typeof E.Promise!="function"&&(E.Promise=B(2))}).call(this,typeof dI<"u"?dI:typeof self<"u"?self:typeof window<"u"?window:{})},{2:2}],4:[function(B,g,I){var E=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(M){return typeof M}:function(M){return M&&typeof Symbol=="function"&&M.constructor===Symbol&&M!==Symbol.prototype?"symbol":typeof M};function i(M,u){if(!(M instanceof u))throw new TypeError("Cannot call a class as a function")}function C(){try{if(typeof indexedDB<"u")return indexedDB;if(typeof webkitIndexedDB<"u")return webkitIndexedDB;if(typeof mozIndexedDB<"u")return mozIndexedDB;if(typeof OIndexedDB<"u")return OIndexedDB;if(typeof msIndexedDB<"u")return msIndexedDB}catch{return}}var a=C();function e(){try{if(!a||!a.open)return!1;var M=typeof openDatabase<"u"&&/(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)&&!/BlackBerry/.test(navigator.platform),u=typeof fetch=="function"&&fetch.toString().indexOf("[native code")!==-1;return(!M||u)&&typeof indexedDB<"u"&&typeof IDBKeyRange<"u"}catch{return!1}}function o(M,u){M=M||[],u=u||{};try{return new Blob(M,u)}catch(b){if(b.name!=="TypeError")throw b;for(var R=typeof BlobBuilder<"u"?BlobBuilder:typeof MSBlobBuilder<"u"?MSBlobBuilder:typeof MozBlobBuilder<"u"?MozBlobBuilder:WebKitBlobBuilder,Y=new R,U=0;U<M.length;U+=1)Y.append(M[U]);return Y.getBlob(u.type)}}typeof Promise>"u"&&B(3);var t=Promise;function s(M,u){u&&M.then(function(R){u(null,R)},function(R){u(R)})}function G(M,u,R){typeof u=="function"&&M.then(u),typeof R=="function"&&M.catch(R)}function n(M){return typeof M!="string"&&(console.warn(M+" used as a key, but it is not a string."),M=String(M)),M}function h(){if(arguments.length&&typeof arguments[arguments.length-1]=="function")return arguments[arguments.length-1]}var c="local-forage-detect-blob-support",d=void 0,l={},F=Object.prototype.toString,m="readonly",y="readwrite";function p(M){for(var u=M.length,R=new ArrayBuffer(u),Y=new Uint8Array(R),U=0;U<u;U++)Y[U]=M.charCodeAt(U);return R}function k(M){return new t(function(u){var R=M.transaction(c,y),Y=o([""]);R.objectStore(c).put(Y,"key"),R.onabort=function(U){U.preventDefault(),U.stopPropagation(),u(!1)},R.oncomplete=function(){var U=navigator.userAgent.match(/Chrome\/(\d+)/),b=navigator.userAgent.match(/Edge\//);u(b||!U||parseInt(U[1],10)>=43)}}).catch(function(){return!1})}function H(M){return typeof d=="boolean"?t.resolve(d):k(M).then(function(u){return d=u,d})}function T(M){var u=l[M.name],R={};R.promise=new t(function(Y,U){R.resolve=Y,R.reject=U}),u.deferredOperations.push(R),u.dbReady?u.dbReady=u.dbReady.then(function(){return R.promise}):u.dbReady=R.promise}function q(M){var u=l[M.name],R=u.deferredOperations.pop();if(R)return R.resolve(),R.promise}function v(M,u){var R=l[M.name],Y=R.deferredOperations.pop();if(Y)return Y.reject(u),Y.promise}function EA(M,u){return new t(function(R,Y){if(l[M.name]=l[M.name]||DA(),M.db)if(u)T(M),M.db.close();else return R(M.db);var U=[M.name];u&&U.push(M.version);var b=a.open.apply(a,U);u&&(b.onupgradeneeded=function(W){var f=b.result;try{f.createObjectStore(M.storeName),W.oldVersion<=1&&f.createObjectStore(c)}catch(N){if(N.name==="ConstraintError")console.warn('The database "'+M.name+'" has been upgraded from version '+W.oldVersion+" to version "+W.newVersion+', but the storage "'+M.storeName+'" already exists.');else throw N}}),b.onerror=function(W){W.preventDefault(),Y(b.error)},b.onsuccess=function(){var W=b.result;W.onversionchange=function(f){f.target.close()},R(W),q(M)}})}function aA(M){return EA(M,!1)}function GA(M){return EA(M,!0)}function rA(M,u){if(!M.db)return!0;var R=!M.db.objectStoreNames.contains(M.storeName),Y=M.version<M.db.version,U=M.version>M.db.version;if(Y&&(M.version!==u&&console.warn('The database "'+M.name+`" can't be downgraded from version `+M.db.version+" to version "+M.version+"."),M.version=M.db.version),U||R){if(R){var b=M.db.version+1;b>M.version&&(M.version=b)}return!0}return!1}function P(M){return new t(function(u,R){var Y=new FileReader;Y.onerror=R,Y.onloadend=function(U){var b=btoa(U.target.result||"");u({__local_forage_encoded_blob:!0,data:b,type:M.type})},Y.readAsBinaryString(M)})}function BA(M){var u=p(atob(M.data));return o([u],{type:M.type})}function wA(M){return M&&M.__local_forage_encoded_blob}function yA(M){var u=this,R=u._initReady().then(function(){var Y=l[u._dbInfo.name];if(Y&&Y.dbReady)return Y.dbReady});return G(R,M,M),R}function jQ(M){T(M);for(var u=l[M.name],R=u.forages,Y=0;Y<R.length;Y++){var U=R[Y];U._dbInfo.db&&(U._dbInfo.db.close(),U._dbInfo.db=null)}return M.db=null,aA(M).then(function(b){return M.db=b,rA(M)?GA(M):b}).then(function(b){M.db=u.db=b;for(var W=0;W<R.length;W++)R[W]._dbInfo.db=b}).catch(function(b){throw v(M,b),b})}function QA(M,u,R,Y){Y===void 0&&(Y=1);try{var U=M.db.transaction(M.storeName,u);R(null,U)}catch(b){if(Y>0&&(!M.db||b.name==="InvalidStateError"||b.name==="NotFoundError"))return t.resolve().then(function(){if(!M.db||b.name==="NotFoundError"&&!M.db.objectStoreNames.contains(M.storeName)&&M.version<=M.db.version)return M.db&&(M.version=M.db.version+1),GA(M)}).then(function(){return jQ(M).then(function(){QA(M,u,R,Y-1)})}).catch(R);R(b)}}function DA(){return{forages:[],db:null,dbReady:null,deferredOperations:[]}}function Qg(M){var u=this,R={db:null};if(M)for(var Y in M)R[Y]=M[Y];var U=l[R.name];U||(U=DA(),l[R.name]=U),U.forages.push(u),u._initReady||(u._initReady=u.ready,u.ready=yA);var b=[];function W(){return t.resolve()}for(var f=0;f<U.forages.length;f++){var N=U.forages[f];N!==u&&b.push(N._initReady().catch(W))}var J=U.forages.slice(0);return t.all(b).then(function(){return R.db=U.db,aA(R)}).then(function(V){return R.db=V,rA(R,u._defaultConfig.version)?GA(R):V}).then(function(V){R.db=U.db=V,u._dbInfo=R;for(var O=0;O<J.length;O++){var iA=J[O];iA!==u&&(iA._dbInfo.db=R.db,iA._dbInfo.version=R.version)}})}function pC(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){QA(R._dbInfo,m,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=N.get(M);J.onsuccess=function(){var V=J.result;V===void 0&&(V=null),wA(V)&&(V=BA(V)),U(V)},J.onerror=function(){b(J.error)}}catch(V){b(V)}})}).catch(b)});return s(Y,u),Y}function Ls(M,u){var R=this,Y=new t(function(U,b){R.ready().then(function(){QA(R._dbInfo,m,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=N.openCursor(),V=1;J.onsuccess=function(){var O=J.result;if(O){var iA=O.value;wA(iA)&&(iA=BA(iA));var oA=M(iA,O.key,V++);oA!==void 0?U(oA):O.continue()}else U()},J.onerror=function(){b(J.error)}}catch(O){b(O)}})}).catch(b)});return s(Y,u),Y}function hR(M,u,R){var Y=this;M=n(M);var U=new t(function(b,W){var f;Y.ready().then(function(){return f=Y._dbInfo,F.call(u)==="[object Blob]"?H(f.db).then(function(N){return N?u:P(u)}):u}).then(function(N){QA(Y._dbInfo,y,function(J,V){if(J)return W(J);try{var O=V.objectStore(Y._dbInfo.storeName);N===null&&(N=void 0);var iA=O.put(N,M);V.oncomplete=function(){N===void 0&&(N=null),b(N)},V.onabort=V.onerror=function(){var oA=iA.error?iA.error:iA.transaction.error;W(oA)}}catch(oA){W(oA)}})}).catch(W)});return s(U,R),U}function cR(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){QA(R._dbInfo,y,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=N.delete(M);f.oncomplete=function(){U()},f.onerror=function(){b(J.error)},f.onabort=function(){var V=J.error?J.error:J.transaction.error;b(V)}}catch(V){b(V)}})}).catch(b)});return s(Y,u),Y}function rR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){QA(u._dbInfo,y,function(b,W){if(b)return U(b);try{var f=W.objectStore(u._dbInfo.storeName),N=f.clear();W.oncomplete=function(){Y()},W.onabort=W.onerror=function(){var J=N.error?N.error:N.transaction.error;U(J)}}catch(J){U(J)}})}).catch(U)});return s(R,M),R}function lR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){QA(u._dbInfo,m,function(b,W){if(b)return U(b);try{var f=W.objectStore(u._dbInfo.storeName),N=f.count();N.onsuccess=function(){Y(N.result)},N.onerror=function(){U(N.error)}}catch(J){U(J)}})}).catch(U)});return s(R,M),R}function DR(M,u){var R=this,Y=new t(function(U,b){if(M<0){U(null);return}R.ready().then(function(){QA(R._dbInfo,m,function(W,f){if(W)return b(W);try{var N=f.objectStore(R._dbInfo.storeName),J=!1,V=N.openKeyCursor();V.onsuccess=function(){var O=V.result;if(!O){U(null);return}M===0||J?U(O.key):(J=!0,O.advance(M))},V.onerror=function(){b(V.error)}}catch(O){b(O)}})}).catch(b)});return s(Y,u),Y}function dR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){QA(u._dbInfo,m,function(b,W){if(b)return U(b);try{var f=W.objectStore(u._dbInfo.storeName),N=f.openKeyCursor(),J=[];N.onsuccess=function(){var V=N.result;if(!V){Y(J);return}J.push(V.key),V.continue()},N.onerror=function(){U(N.error)}}catch(V){U(V)}})}).catch(U)});return s(R,M),R}function FR(M,u){u=h.apply(this,arguments);var R=this.config();M=typeof M!="function"&&M||{},M.name||(M.name=M.name||R.name,M.storeName=M.storeName||R.storeName);var Y=this,U;if(!M.name)U=t.reject("Invalid arguments");else{var b=M.name===R.name&&Y._dbInfo.db,W=b?t.resolve(Y._dbInfo.db):aA(M).then(function(f){var N=l[M.name],J=N.forages;N.db=f;for(var V=0;V<J.length;V++)J[V]._dbInfo.db=f;return f});M.storeName?U=W.then(function(f){if(f.objectStoreNames.contains(M.storeName)){var N=f.version+1;T(M);var J=l[M.name],V=J.forages;f.close();for(var O=0;O<V.length;O++){var iA=V[O];iA._dbInfo.db=null,iA._dbInfo.version=N}var oA=new t(function(sA,uA){var RA=a.open(M.name,N);RA.onerror=function(IB){var sI=RA.result;sI.close(),uA(IB)},RA.onupgradeneeded=function(){var IB=RA.result;IB.deleteObjectStore(M.storeName)},RA.onsuccess=function(){var IB=RA.result;IB.close(),sA(IB)}});return oA.then(function(sA){J.db=sA;for(var uA=0;uA<V.length;uA++){var RA=V[uA];RA._dbInfo.db=sA,q(RA._dbInfo)}}).catch(function(sA){throw(v(M,sA)||t.resolve()).catch(function(){}),sA})}}):U=W.then(function(f){T(M);var N=l[M.name],J=N.forages;f.close();for(var V=0;V<J.length;V++){var O=J[V];O._dbInfo.db=null}var iA=new t(function(oA,sA){var uA=a.deleteDatabase(M.name);uA.onerror=function(){var RA=uA.result;RA&&RA.close(),sA(uA.error)},uA.onblocked=function(){console.warn('dropInstance blocked for database "'+M.name+'" until all open connections are closed')},uA.onsuccess=function(){var RA=uA.result;RA&&RA.close(),oA(RA)}});return iA.then(function(oA){N.db=oA;for(var sA=0;sA<J.length;sA++){var uA=J[sA];q(uA._dbInfo)}}).catch(function(oA){throw(v(M,oA)||t.resolve()).catch(function(){}),oA})})}return s(U,u),U}var MR={_driver:"asyncStorage",_initStorage:Qg,_support:e(),iterate:Ls,getItem:pC,setItem:hR,removeItem:cR,clear:rR,length:lR,key:DR,keys:dR,dropInstance:FR};function wR(){return typeof openDatabase=="function"}var xB="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",yR="~~local_forage_type~",Xs=/^~~local_forage_type~([^~]+)~/,OQ="__lfsc__:",YC=OQ.length,UC="arbf",kC="blob",vs="si08",Ks="ui08",zs="uic8",Ts="si16",js="si32",Os="ur16",Ps="ui32",_s="fl32",$s="fl64",AG=YC+UC.length,BG=Object.prototype.toString;function gG(M){var u=M.length*.75,R=M.length,Y,U=0,b,W,f,N;M[M.length-1]==="="&&(u--,M[M.length-2]==="="&&u--);var J=new ArrayBuffer(u),V=new Uint8Array(J);for(Y=0;Y<R;Y+=4)b=xB.indexOf(M[Y]),W=xB.indexOf(M[Y+1]),f=xB.indexOf(M[Y+2]),N=xB.indexOf(M[Y+3]),V[U++]=b<<2|W>>4,V[U++]=(W&15)<<4|f>>2,V[U++]=(f&3)<<6|N&63;return J}function ZC(M){var u=new Uint8Array(M),R="",Y;for(Y=0;Y<u.length;Y+=3)R+=xB[u[Y]>>2],R+=xB[(u[Y]&3)<<4|u[Y+1]>>4],R+=xB[(u[Y+1]&15)<<2|u[Y+2]>>6],R+=xB[u[Y+2]&63];return u.length%3===2?R=R.substring(0,R.length-1)+"=":u.length%3===1&&(R=R.substring(0,R.length-2)+"=="),R}function RR(M,u){var R="";if(M&&(R=BG.call(M)),M&&(R==="[object ArrayBuffer]"||M.buffer&&BG.call(M.buffer)==="[object ArrayBuffer]")){var Y,U=OQ;M instanceof ArrayBuffer?(Y=M,U+=UC):(Y=M.buffer,R==="[object Int8Array]"?U+=vs:R==="[object Uint8Array]"?U+=Ks:R==="[object Uint8ClampedArray]"?U+=zs:R==="[object Int16Array]"?U+=Ts:R==="[object Uint16Array]"?U+=Os:R==="[object Int32Array]"?U+=js:R==="[object Uint32Array]"?U+=Ps:R==="[object Float32Array]"?U+=_s:R==="[object Float64Array]"?U+=$s:u(new Error("Failed to get type for BinaryArray"))),u(U+ZC(Y))}else if(R==="[object Blob]"){var b=new FileReader;b.onload=function(){var W=yR+M.type+"~"+ZC(this.result);u(OQ+kC+W)},b.readAsArrayBuffer(M)}else try{u(JSON.stringify(M))}catch(W){console.error("Couldn't convert value into a JSON string: ",M),u(null,W)}}function mR(M){if(M.substring(0,YC)!==OQ)return JSON.parse(M);var u=M.substring(AG),R=M.substring(YC,AG),Y;if(R===kC&&Xs.test(u)){var U=u.match(Xs);Y=U[1],u=u.substring(U[0].length)}var b=gG(u);switch(R){case UC:return b;case kC:return o([b],{type:Y});case vs:return new Int8Array(b);case Ks:return new Uint8Array(b);case zs:return new Uint8ClampedArray(b);case Ts:return new Int16Array(b);case Os:return new Uint16Array(b);case js:return new Int32Array(b);case Ps:return new Uint32Array(b);case _s:return new Float32Array(b);case $s:return new Float64Array(b);default:throw new Error("Unkown type: "+R)}}var WC={serialize:RR,deserialize:mR,stringToBuffer:gG,bufferToString:ZC};function IG(M,u,R,Y){M.executeSql("CREATE TABLE IF NOT EXISTS "+u.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],R,Y)}function uR(M){var u=this,R={db:null};if(M)for(var Y in M)R[Y]=typeof M[Y]!="string"?M[Y].toString():M[Y];var U=new t(function(b,W){try{R.db=openDatabase(R.name,String(R.version),R.description,R.size)}catch(f){return W(f)}R.db.transaction(function(f){IG(f,R,function(){u._dbInfo=R,b()},function(N,J){W(J)})},W)});return R.serializer=WC,U}function VB(M,u,R,Y,U,b){M.executeSql(R,Y,U,function(W,f){f.code===f.SYNTAX_ERR?W.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?",[u.storeName],function(N,J){J.rows.length?b(N,f):IG(N,u,function(){N.executeSql(R,Y,U,b)},b)},b):b(W,f)},b)}function SR(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"SELECT * FROM "+W.storeName+" WHERE key = ? LIMIT 1",[M],function(N,J){var V=J.rows.length?J.rows.item(0).value:null;V&&(V=W.serializer.deserialize(V)),U(V)},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function bR(M,u){var R=this,Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"SELECT * FROM "+W.storeName,[],function(N,J){for(var V=J.rows,O=V.length,iA=0;iA<O;iA++){var oA=V.item(iA),sA=oA.value;if(sA&&(sA=W.serializer.deserialize(sA)),sA=M(sA,oA.key,iA+1),sA!==void 0){U(sA);return}}U()},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function QG(M,u,R,Y){var U=this;M=n(M);var b=new t(function(W,f){U.ready().then(function(){u===void 0&&(u=null);var N=u,J=U._dbInfo;J.serializer.serialize(u,function(V,O){O?f(O):J.db.transaction(function(iA){VB(iA,J,"INSERT OR REPLACE INTO "+J.storeName+" (key, value) VALUES (?, ?)",[M,V],function(){W(N)},function(oA,sA){f(sA)})},function(iA){if(iA.code===iA.QUOTA_ERR){if(Y>0){W(QG.apply(U,[M,N,R,Y-1]));return}f(iA)}})})}).catch(f)});return s(b,R),b}function pR(M,u,R){return QG.apply(this,[M,u,R,1])}function YR(M,u){var R=this;M=n(M);var Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"DELETE FROM "+W.storeName+" WHERE key = ?",[M],function(){U()},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function UR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){var b=u._dbInfo;b.db.transaction(function(W){VB(W,b,"DELETE FROM "+b.storeName,[],function(){Y()},function(f,N){U(N)})})}).catch(U)});return s(R,M),R}function kR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){var b=u._dbInfo;b.db.transaction(function(W){VB(W,b,"SELECT COUNT(key) as c FROM "+b.storeName,[],function(f,N){var J=N.rows.item(0).c;Y(J)},function(f,N){U(N)})})}).catch(U)});return s(R,M),R}function ZR(M,u){var R=this,Y=new t(function(U,b){R.ready().then(function(){var W=R._dbInfo;W.db.transaction(function(f){VB(f,W,"SELECT key FROM "+W.storeName+" WHERE id = ? LIMIT 1",[M+1],function(N,J){var V=J.rows.length?J.rows.item(0).key:null;U(V)},function(N,J){b(J)})})}).catch(b)});return s(Y,u),Y}function WR(M){var u=this,R=new t(function(Y,U){u.ready().then(function(){var b=u._dbInfo;b.db.transaction(function(W){VB(W,b,"SELECT key FROM "+b.storeName,[],function(f,N){for(var J=[],V=0;V<N.rows.length;V++)J.push(N.rows.item(V).key);Y(J)},function(f,N){U(N)})})}).catch(U)});return s(R,M),R}function HR(M){return new t(function(u,R){M.transaction(function(Y){Y.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'",[],function(U,b){for(var W=[],f=0;f<b.rows.length;f++)W.push(b.rows.item(f).name);u({db:M,storeNames:W})},function(U,b){R(b)})},function(Y){R(Y)})})}function fR(M,u){u=h.apply(this,arguments);var R=this.config();M=typeof M!="function"&&M||{},M.name||(M.name=M.name||R.name,M.storeName=M.storeName||R.storeName);var Y=this,U;return M.name?U=new t(function(b){var W;M.name===R.name?W=Y._dbInfo.db:W=openDatabase(M.name,"","",0),M.storeName?b({db:W,storeNames:[M.storeName]}):b(HR(W))}).then(function(b){return new t(function(W,f){b.db.transaction(function(N){function J(oA){return new t(function(sA,uA){N.executeSql("DROP TABLE IF EXISTS "+oA,[],function(){sA()},function(RA,IB){uA(IB)})})}for(var V=[],O=0,iA=b.storeNames.length;O<iA;O++)V.push(J(b.storeNames[O]));t.all(V).then(function(){W()}).catch(function(oA){f(oA)})},function(N){f(N)})})}):U=t.reject("Invalid arguments"),s(U,u),U}var NR={_driver:"webSQLStorage",_initStorage:uR,_support:wR(),iterate:bR,getItem:SR,setItem:pR,removeItem:YR,clear:UR,length:kR,key:ZR,keys:WR,dropInstance:fR};function JR(){try{return typeof localStorage<"u"&&"setItem"in localStorage&&!!localStorage.setItem}catch{return!1}}function EG(M,u){var R=M.name+"/";return M.storeName!==u.storeName&&(R+=M.storeName+"/"),R}function qR(){var M="_localforage_support_test";try{return localStorage.setItem(M,!0),localStorage.removeItem(M),!1}catch{return!0}}function xR(){return!qR()||localStorage.length>0}function VR(M){var u=this,R={};if(M)for(var Y in M)R[Y]=M[Y];return R.keyPrefix=EG(M,u._defaultConfig),xR()?(u._dbInfo=R,R.serializer=WC,t.resolve()):t.reject()}function LR(M){var u=this,R=u.ready().then(function(){for(var Y=u._dbInfo.keyPrefix,U=localStorage.length-1;U>=0;U--){var b=localStorage.key(U);b.indexOf(Y)===0&&localStorage.removeItem(b)}});return s(R,M),R}function XR(M,u){var R=this;M=n(M);var Y=R.ready().then(function(){var U=R._dbInfo,b=localStorage.getItem(U.keyPrefix+M);return b&&(b=U.serializer.deserialize(b)),b});return s(Y,u),Y}function vR(M,u){var R=this,Y=R.ready().then(function(){for(var U=R._dbInfo,b=U.keyPrefix,W=b.length,f=localStorage.length,N=1,J=0;J<f;J++){var V=localStorage.key(J);if(V.indexOf(b)===0){var O=localStorage.getItem(V);if(O&&(O=U.serializer.deserialize(O)),O=M(O,V.substring(W),N++),O!==void 0)return O}}});return s(Y,u),Y}function KR(M,u){var R=this,Y=R.ready().then(function(){var U=R._dbInfo,b;try{b=localStorage.key(M)}catch{b=null}return b&&(b=b.substring(U.keyPrefix.length)),b});return s(Y,u),Y}function zR(M){var u=this,R=u.ready().then(function(){for(var Y=u._dbInfo,U=localStorage.length,b=[],W=0;W<U;W++){var f=localStorage.key(W);f.indexOf(Y.keyPrefix)===0&&b.push(f.substring(Y.keyPrefix.length))}return b});return s(R,M),R}function TR(M){var u=this,R=u.keys().then(function(Y){return Y.length});return s(R,M),R}function jR(M,u){var R=this;M=n(M);var Y=R.ready().then(function(){var U=R._dbInfo;localStorage.removeItem(U.keyPrefix+M)});return s(Y,u),Y}function OR(M,u,R){var Y=this;M=n(M);var U=Y.ready().then(function(){u===void 0&&(u=null);var b=u;return new t(function(W,f){var N=Y._dbInfo;N.serializer.serialize(u,function(J,V){if(V)f(V);else try{localStorage.setItem(N.keyPrefix+M,J),W(b)}catch(O){(O.name==="QuotaExceededError"||O.name==="NS_ERROR_DOM_QUOTA_REACHED")&&f(O),f(O)}})})});return s(U,R),U}function PR(M,u){if(u=h.apply(this,arguments),M=typeof M!="function"&&M||{},!M.name){var R=this.config();M.name=M.name||R.name,M.storeName=M.storeName||R.storeName}var Y=this,U;return M.name?U=new t(function(b){M.storeName?b(EG(M,Y._defaultConfig)):b(M.name+"/")}).then(function(b){for(var W=localStorage.length-1;W>=0;W--){var f=localStorage.key(W);f.indexOf(b)===0&&localStorage.removeItem(f)}}):U=t.reject("Invalid arguments"),s(U,u),U}var _R={_driver:"localStorageWrapper",_initStorage:VR,_support:JR(),iterate:vR,getItem:XR,setItem:OR,removeItem:jR,clear:LR,length:TR,key:KR,keys:zR,dropInstance:PR},$R=function(u,R){return u===R||typeof u=="number"&&typeof R=="number"&&isNaN(u)&&isNaN(R)},Am=function(u,R){for(var Y=u.length,U=0;U<Y;){if($R(u[U],R))return!0;U++}return!1},iG=Array.isArray||function(M){return Object.prototype.toString.call(M)==="[object Array]"},tI={},CG={},Ug={INDEXEDDB:MR,WEBSQL:NR,LOCALSTORAGE:_R},Bm=[Ug.INDEXEDDB._driver,Ug.WEBSQL._driver,Ug.LOCALSTORAGE._driver],PQ=["dropInstance"],HC=["clear","getItem","iterate","key","keys","length","removeItem","setItem"].concat(PQ),gm={description:"",driver:Bm.slice(),name:"localforage",size:4980736,storeName:"keyvaluepairs",version:1};function Im(M,u){M[u]=function(){var R=arguments;return M.ready().then(function(){return M[u].apply(M,R)})}}function fC(){for(var M=1;M<arguments.length;M++){var u=arguments[M];if(u)for(var R in u)u.hasOwnProperty(R)&&(iG(u[R])?arguments[0][R]=u[R].slice():arguments[0][R]=u[R])}return arguments[0]}var Qm=(function(){function M(u){i(this,M);for(var R in Ug)if(Ug.hasOwnProperty(R)){var Y=Ug[R],U=Y._driver;this[R]=U,tI[U]||this.defineDriver(Y)}this._defaultConfig=fC({},gm),this._config=fC({},this._defaultConfig,u),this._driverSet=null,this._initDriver=null,this._ready=!1,this._dbInfo=null,this._wrapLibraryMethodsWithReady(),this.setDriver(this._config.driver).catch(function(){})}return M.prototype.config=function(R){if((typeof R>"u"?"undefined":E(R))==="object"){if(this._ready)return new Error("Can't call config() after localforage has been used.");for(var Y in R){if(Y==="storeName"&&(R[Y]=R[Y].replace(/\W/g,"_")),Y==="version"&&typeof R[Y]!="number")return new Error("Database version must be a number.");this._config[Y]=R[Y]}return"driver"in R&&R.driver?this.setDriver(this._config.driver):!0}else return typeof R=="string"?this._config[R]:this._config},M.prototype.defineDriver=function(R,Y,U){var b=new t(function(W,f){try{var N=R._driver,J=new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver");if(!R._driver){f(J);return}for(var V=HC.concat("_initStorage"),O=0,iA=V.length;O<iA;O++){var oA=V[O],sA=!Am(PQ,oA);if((sA||R[oA])&&typeof R[oA]!="function"){f(J);return}}var uA=function(){for(var sI=function(Cm){return function(){var am=new Error("Method "+Cm+" is not implemented by the current driver"),aG=t.reject(am);return s(aG,arguments[arguments.length-1]),aG}},NC=0,im=PQ.length;NC<im;NC++){var JC=PQ[NC];R[JC]||(R[JC]=sI(JC))}};uA();var RA=function(sI){tI[N]&&console.info("Redefining LocalForage driver: "+N),tI[N]=R,CG[N]=sI,W()};"_support"in R?R._support&&typeof R._support=="function"?R._support().then(RA,f):RA(!!R._support):RA(!0)}catch(IB){f(IB)}});return G(b,Y,U),b},M.prototype.driver=function(){return this._driver||null},M.prototype.getDriver=function(R,Y,U){var b=tI[R]?t.resolve(tI[R]):t.reject(new Error("Driver not found."));return G(b,Y,U),b},M.prototype.getSerializer=function(R){var Y=t.resolve(WC);return G(Y,R),Y},M.prototype.ready=function(R){var Y=this,U=Y._driverSet.then(function(){return Y._ready===null&&(Y._ready=Y._initDriver()),Y._ready});return G(U,R,R),U},M.prototype.setDriver=function(R,Y,U){var b=this;iG(R)||(R=[R]);var W=this._getSupportedDrivers(R);function f(){b._config.driver=b.driver()}function N(O){return b._extend(O),f(),b._ready=b._initStorage(b._config),b._ready}function J(O){return function(){var iA=0;function oA(){for(;iA<O.length;){var sA=O[iA];return iA++,b._dbInfo=null,b._ready=null,b.getDriver(sA).then(N).catch(oA)}f();var uA=new Error("No available storage method found.");return b._driverSet=t.reject(uA),b._driverSet}return oA()}}var V=this._driverSet!==null?this._driverSet.catch(function(){return t.resolve()}):t.resolve();return this._driverSet=V.then(function(){var O=W[0];return b._dbInfo=null,b._ready=null,b.getDriver(O).then(function(iA){b._driver=iA._driver,f(),b._wrapLibraryMethodsWithReady(),b._initDriver=J(W)})}).catch(function(){f();var O=new Error("No available storage method found.");return b._driverSet=t.reject(O),b._driverSet}),G(this._driverSet,Y,U),this._driverSet},M.prototype.supports=function(R){return!!CG[R]},M.prototype._extend=function(R){fC(this,R)},M.prototype._getSupportedDrivers=function(R){for(var Y=[],U=0,b=R.length;U<b;U++){var W=R[U];this.supports(W)&&Y.push(W)}return Y},M.prototype._wrapLibraryMethodsWithReady=function(){for(var R=0,Y=HC.length;R<Y;R++)Im(this,HC[R])},M.prototype.createInstance=function(R){return new M(R)},M})(),Em=new Qm;g.exports=Em},{3:3}]},{},[4])(4)})})(Ii)),Ii.exports}var ND=fD();const JD=ca(ND);function rg(Q){return`model:${Q}`}function qD(Q){const A=Q.lastIndexOf("/");return A>=0?Q.substring(0,A+1):""}async function xD(Q,A=3,B=1e3){let g=null;for(let I=0;I<A;I++)try{const E=await fetch(Q);if(!E.ok)throw new Error(`HTTP ${E.status}: ${E.statusText}`);return E}catch(E){if(g=E,I===A-1)throw E;const i=B*Math.pow(2,I);console.warn(`[ModelCache] Fetch failed (attempt ${I+1}/${A}), retrying in ${i}ms...`,{url:Q,error:String(E)}),await new Promise(C=>setTimeout(C,i))}throw g}async function co(Q,A,B,g=3,I=1e3){let E=null;for(let i=0;i<g;i++){const C=A?await A(Q):Q;try{const a=await fetch(C);if(!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);const e=await a.text(),o=JSON.parse(e),t=qD(C),s={},G=[];if(o.weightsManifest&&Array.isArray(o.weightsManifest)){for(const h of o.weightsManifest)if(h.paths&&Array.isArray(h.paths))for(const c of h.paths)G.push(c)}const n=G.map(async h=>{const c=t+h,d=await xD(c,g,I);s[h]=await d.arrayBuffer()});return await Promise.all(n),{manifest:e,weights:s,savedAt:Date.now(),originalUrl:Q}}catch(a){if(E=a,i===g-1)throw a;B?.(Q);const e=I*Math.pow(2,i);console.warn(`[ModelCache] Model fetch failed (attempt ${i+1}/${g}), re-resolving and retrying in ${e}ms...`,{url:Q,resolvedUrl:C,error:String(a)}),await new Promise(o=>setTimeout(o,e))}}throw E}function Qi(Q,A){return JSON.parse(A.manifest),{load:async()=>ro(A)}}function ro(Q){const A=JSON.parse(Q.manifest),B=[],g=[];if(A.weightsManifest&&Array.isArray(A.weightsManifest))for(const I of A.weightsManifest){if(I.weights&&Array.isArray(I.weights))for(const E of I.weights)g.push(E);if(I.paths&&Array.isArray(I.paths))for(const E of I.paths){const i=Q.weights[E];if(!i)throw new Error(`[ModelCache] Weight shard "${E}" not found in cache`);B.push(i)}}return{modelTopology:A.modelTopology,format:A.format??"graph-model",generatedBy:A.generatedBy,convertedBy:A.convertedBy,weightSpecs:g.length>0?g:void 0,weightData:B.length>0?B.length===1?B[0]:B:void 0}}const lo=new Map;let Do=!1;function VD(){Do||(Do=!0,import("@tensorflow/tfjs").then(Q=>{Q.io.registerLoadRouter((A=>{if(typeof A=="string"&&A.startsWith("cached://")){const B=lo.get(A);if(B)return{load:async()=>{const g=await B.store.getItem(B.key);if(!g)throw new Error(`[ModelCache] Model not in cache: ${A}`);return ro(g)}}}return null}))}))}VD();class Fo{constructor(A={}){this.store=JD.createInstance({name:A.storeName??"playlist-data-engine-models",description:A.description??"Cached TF.js model artifacts for playlist-data-engine"})}async has(A){return await this.store.getItem(rg(A))!=null}async getCacheInfo(A){const B=await this.store.getItem(rg(A));if(!B)return{cached:!1};let g=B.manifest.length;for(const I of Object.values(B.weights))g+=I.byteLength;return{cached:!0,savedAt:B.savedAt,size:g}}async loadFromCache(A,B){const g=await this.store.getItem(rg(B));if(!g)throw new Error(`[ModelCache] Model not cached: ${B}`);return A.loadGraphModel(Qi(A,g))}async getOrFetchGraphModel(A,B,g={}){const I=rg(B);try{const i=await this.store.getItem(I);if(i)return console.info(`[ModelCache] Loading model from cache: ${B}`),await A.loadGraphModel(Qi(A,i))}catch(i){console.warn("[ModelCache] Cache load failed, clearing and re-fetching:",i),await this.store.removeItem(I)}console.info(`[ModelCache] Downloading model: ${B}`);const E=await co(B,g.resolveUrl,g.invalidateUrlCache,g.maxRetries??3,g.baseDelayMs??1e3);return await this.store.setItem(I,E),console.info(`[ModelCache] Model cached: ${B} (${Object.keys(E.weights).length} shards)`),A.loadGraphModel(Qi(A,E))}async getOrFetchEssentiaUrl(A,B={}){const g=rg(A),I=`cached://${A}`;if(await this.store.getItem(g))console.info(`[ModelCache] Loading Essentia model from cache: ${A}`);else{console.info(`[ModelCache] Downloading model for Essentia: ${A}`);const i=await co(A,B.resolveUrl,B.invalidateUrlCache,B.maxRetries??3,B.baseDelayMs??1e3);await this.store.setItem(g,i),console.info(`[ModelCache] Model cached: ${A} (${Object.keys(i.weights).length} shards)`)}return lo.set(I,{store:this.store,key:g}),I}async clear(A){A?(await this.store.removeItem(rg(A)),console.info(`[ModelCache] Cleared cache for: ${A}`)):(await this.store.clear(),console.info("[ModelCache] Cleared all cached models"))}async listCachedModels(){return(await this.store.keys()).filter(B=>B.startsWith("model:")).map(B=>B.replace("model:",""))}async totalCacheSize(){let A=0;return await this.store.iterate(B=>{if(B){A+=B.manifest.length;for(const g of Object.values(B.weights))A+=g.byteLength}}),A}}const lg=new Fo;function LD(Q){if(!Q||!Q.metadata)return null;if(typeof Q.metadata=="string")try{const A=JSON.parse(Q.metadata);return typeof A=="object"&&A!==null&&!Array.isArray(A)?A:null}catch{return null}return typeof Q.metadata=="object"&&!Array.isArray(Q.metadata)?Q.metadata:null}function Mo(Q){const A={stems:[],mixes:[],hasExtras:!1};if(!Q)return A;const B=zD(Q),g=TD(Q),I=typeof Q.vrm=="string"?Q.vrm:void 0,E=XD(Q.lyrics),i=wo(Q.visualizer),C=wo(Q.video),a=vD(Q.merch),e=KD(Q.credits),o=typeof Q.midi=="string"?Q.midi:void 0,t=typeof Q.step_mania=="string"?Q.step_mania:void 0,s=typeof Q.clone_hero=="string"?Q.clone_hero:void 0,G=typeof Q.external_url=="string"?Q.external_url:void 0;return{hasExtras:B.length>0||g.length>0||!!I||!!E||!!i||!!C||!!a||!!e||!!o||!!t||!!s||!!G,...B.length>0?{stems:B}:{},...g.length>0?{mixes:g}:{},...I?{vrm:I}:{},...E?{lyrics:E}:{},...i?{visualizer:i}:{},...C?{video:C}:{},...a?{merch:a}:{},...e?{credits:e}:{},...o?{midi:o}:{},...t?{step_mania:t}:{},...s?{clone_hero:s}:{},...G?{external_url:G}:{}}}function XD(Q){if(Q){if(typeof Q=="string")return{text:Q};if(typeof Q=="object"&&!Array.isArray(Q)){const A=Q;return{text:typeof A.text=="string"?A.text:void 0}}}}function wo(Q){if(!Q||typeof Q!="object"||Array.isArray(Q))return;const A=Q;if(typeof A.uri=="string")return{uri:A.uri,mime_type:typeof A.mime_type=="string"?A.mime_type:void 0}}function vD(Q){if(!Q||typeof Q!="object"||Array.isArray(Q))return;const A=Q;if(typeof A.uri=="string")return{uri:A.uri,mime_type:typeof A.mime_type=="string"?A.mime_type:void 0,type:typeof A.type=="string"?A.type:void 0}}function KD(Q){if(!Array.isArray(Q))return;const A=[];for(const B of Q)if(B&&typeof B=="object"){const g=B;typeof g.name=="string"&&typeof g.credit=="string"&&A.push({name:g.name,credit:g.credit})}return A.length>0?A:void 0}function zD(Q){const A=Q.stems;if(!Array.isArray(A))return[];const B=[];for(const g of A)if(g&&typeof g=="object"){const I=g;B.push({name:typeof I.name=="string"?I.name:"",uri:typeof I.uri=="string"?I.uri:void 0,mime_type:typeof I.mime_type=="string"?I.mime_type:void 0})}return B}function TD(Q){const A=Q.mixes;if(!Array.isArray(A))return[];const B=[];for(const g of A)if(g&&typeof g=="object"){const I=g,E=jD(I.name),i=OD(I.conditions);B.push({name:E||"",uri:typeof I.uri=="string"?I.uri:void 0,mime_type:typeof I.mime_type=="string"?I.mime_type:void 0,conditions:i})}return B}function jD(Q){if(typeof Q=="string")return Q;if(Q&&typeof Q=="object"&&!Array.isArray(Q)){const A=Q;if(typeof A.value=="string")return A.value}return""}function OD(Q){if(!Array.isArray(Q))return[];const A=[];for(const B of Q)if(B&&typeof B=="object"){const g=B;typeof g.type=="string"&&typeof g.value=="string"&&A.push({type:g.type,value:g.value})}return A}function PD(Q,A){const B=[],g=new Date;for(const I of Q.mixes||[]){if(I.conditions.length===0){B.push({mix:I,conditions:[],allMet:!0,unmetConditions:[]});continue}const E=[],i=[];for(const C of I.conditions){const a=_D(C,A,g);E.push(a),a.met||i.push(a)}B.push({mix:I,conditions:E,allMet:i.length===0,unmetConditions:i})}return B}function _D(Q,A,B=new Date){const{type:g,value:I}=Q,E=A?.environment,i=A?.appState;switch(g){case"weather":{const C=E?.weather?.weatherType||"",a=C.toLowerCase()===I.toLowerCase();return{type:g,value:I,met:a,reason:a?`Weather is ${C}`:`Weather is ${C} (need ${I})`}}case"day":{const a=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][B.getDay()],e=a.toLowerCase()===I.toLowerCase();return{type:g,value:I,met:e,reason:e?`Today is ${a}`:`Today is ${a} (need ${I})`}}case"start_time":{const C=B.getHours()*60+B.getMinutes(),a=yo(I),e=C>=a;return{type:g,value:I,met:e,reason:e?`Time is after ${I}`:`Time is before ${I}`}}case"end_time":{const C=B.getHours()*60+B.getMinutes(),a=yo(I),e=C<a;return{type:g,value:I,met:e,reason:e?`Time is before ${I}`:`Time is after ${I}`}}case"min_plays":{const C=parseInt(I,10),a=i?.playCount??0,e=a>=C;return{type:g,value:I,met:e,reason:e?`Played ${a} times (need ${C})`:`Played ${a} times (need ${C})`}}case"max_plays":{const C=parseInt(I,10),a=i?.playCount??0,e=a<=C;return{type:g,value:I,met:e,reason:e?`Played ${a} times (max ${C})`:`Played ${a} times (exceeds max ${C})`}}case"every_x_plays":{const C=parseInt(I,10),a=i?.playCount??0,e=C>0&&a>0&&a%C===0;return{type:g,value:I,met:e,reason:e?`Play #${a} (every ${C} plays)`:`Play #${a} (not a multiple of ${C})`}}case"altitude":{const C=E?.geolocation?.altitude;if(C==null)return{type:g,value:I,met:!1,reason:"Altitude unavailable"};const a=$D(I),e=Ad(C,a.operator,a.threshold);return{type:g,value:I,met:e,reason:e?`Altitude ${C}m ${a.operator} ${a.threshold}m`:`Altitude ${C}m (need ${a.operator} ${a.threshold}m)`}}case"favorite":{const C=i?.isFavorite??!1,a=I.toLowerCase()==="true",e=C===a;return{type:g,value:I,met:e,reason:e?C?"Track is favorited":"Track is not favorited":C?"Track is favorited (need unfavorited)":"Track is not favorited (need favorited)"}}case"birthday":{if(!i?.userBirthday)return{type:g,value:I,met:!1,reason:"Birthday not set"};const a=`${String(B.getMonth()+1).padStart(2,"0")}-${String(B.getDate()).padStart(2,"0")}`===i.userBirthday;return{type:g,value:I,met:a,reason:a?"It's your birthday!":`Not your birthday (need ${i.userBirthday})`}}case"weight":return{type:g,value:I,met:!0,reason:`Weight ${I} (used for random selection, always available)`};default:return{type:g,value:I,met:!0,reason:`Custom condition: ${g} = ${I}`}}}function yo(Q){const A=Q.split(":");if(A.length!==2)return 0;const B=parseInt(A[0],10),g=parseInt(A[1],10);return isNaN(B)||isNaN(g)?0:B*60+g}function $D(Q){const A=Q.match(/^(>=|<=|>|<|=)?\s*(\d+(?:\.\d+)?)\s*$/);return A?{operator:A[1]||">=",threshold:parseFloat(A[2])}:{operator:">=",threshold:parseFloat(Q)||0}}function Ad(Q,A,B){switch(A){case">":return Q>B;case">=":return Q>=B;case"<":return Q<B;case"<=":return Q<=B;case"=":case"==":return Q===B;default:return Q>=B}}class Ro{generateName(A,B,g,I,E=!1){const i=this.cleanTitle(B.title),C=E?A:`${A}-${Date.now()}-${Math.random()}`,a=new QB(C);switch(this.selectFormat(a)){case"class_title":return this.formatClassTitle(i,I,a);case"adjective_construct":return this.formatAdjectiveConstruct(i,B.genre,g,a);case"clan_construct":return this.formatClanConstruct(i,B.artist,a);case"descriptive_epithet":return this.formatDescriptiveEpithet(i,I,g,a);case"compound_adjective":return this.formatCompoundAdjective(i,B.genre,g,a);case"artist_inspired":return this.formatArtistInspired(i,B.artist,I,a);case"mononym_subtitle":return this.formatMononymSubtitle(i,g,B.genre,a);default:return i}}cleanTitle(A){let B=A;return B=B.replace(/\s*[([].*?(video|official|remix|mix|edit|feat|ft\.|version|remaster).*?[)\]]/gi,""),B=B.replace(/^\s*\d+[\s.-]+/,""),B=B.replace(/\.(mp3|wav|flac|m4a)$/i,""),B.trim()}selectFormat(A){const B=A.random();return B<.2?"class_title":B<.4?"adjective_construct":B<.5?"clan_construct":B<.7?"descriptive_epithet":B<.85?"compound_adjective":B<.95?"artist_inspired":"mononym_subtitle"}formatClassTitle(A,B,g){return`${A} the ${B}`}formatAdjectiveConstruct(A,B,g,I){const E=this.findGenreKey(B),i=aB.adjectives[E]||aB.adjectives.default,C=this.calculateBalancedAdjectiveWeights(g),a=I.weightedChoice(C),e=i[a];return`${I.randomChoice(e)} ${A}`}formatClanConstruct(A,B,g){return`${A} of ${B}`}formatDescriptiveEpithet(A,B,g,I){const E=I.randomChoice(aB.descriptors),i=aB.classAspects[B]||["Wanderer","Seeker","Sage","Hero"],C=I.randomChoice(i);return`${A}, the ${E} ${C}`}formatCompoundAdjective(A,B,g,I){const E=I.randomChoice(aB.prefixes),i=I.randomChoice(aB.suffixes);return`${E}-${i} ${A}`}formatArtistInspired(A,B,g,I){const E=B.split(" ")[0],i=I.randomChoice(aB.occupations),C=`${E}${i}`,a=I.randomChoice(aB.realms);return`${C} of the ${a}`}formatMononymSubtitle(A,B,g,I){const E=A.split(" "),i=E[0];let C;return E.length>1?C=E.slice(1).join(" "):C=I.randomChoice(aB.subtitlePrefixes),`${i} [${C}]`}calculateBalancedAdjectiveWeights(A){const g={bass:A.bass_dominance,treble:A.treble_dominance,mid:A.mid_dominance,quiet:A.average_amplitude<.4?.5:0,loud:A.average_amplitude>.6?.5:0};return[["bass",1+g.bass],["treble",1+g.treble],["mid",1+g.mid],["quiet",1+g.quiet],["loud",1+g.loud]]}findGenreKey(A){const B=A.toLowerCase(),g=Object.keys(aB.adjectives).filter(I=>I!=="default"&&B.includes(I));return g.length>0?g[0]:"default"}}class _A{static select(A,B,g,I="relative"){if(A.length===0)throw new Error("Cannot select from empty items array");const E=this.getFinalWeights(A,B,I),i=A.map(C=>{const a=this.getItemKey(C),e=a in E?E[a]:1;return[C,e]});return g.weightedChoice(i)}static selectMultiple(A,B,g,I,E="relative"){if(A.length===0)return[];if(I<=0)return[];if(I>=A.length)return g.shuffle(A);const i=[],C=[...A],a={...B};for(let e=0;e<I&&C.length>0;e++){const o=this.select(C,a,g,E);i.push(o);const t=C.indexOf(o);if(t!==-1){const s=this.getItemKey(o);C.splice(t,1),delete a[s]}}return i}static getProbabilities(A,B,g="relative"){if(A.length===0)return{};const I=this.getFinalWeights(A,B,g),E=Object.values(I).reduce((C,a)=>C+a,0);if(E===0){const C={};for(const a of A){const e=this.getItemKey(a);C[e]=1/A.length}return C}const i={};for(const C of A){const a=this.getItemKey(C),e=I[a]||0;i[a]=E>0?e/E:0}return i}static normalizeWeights(A,B,g="relative"){if(A.length===0)return{};const I=_A.getFinalWeights(A,B,g),E=Object.values(I).reduce((C,a)=>C+a,0);if(E===0){const C={};for(const a of A){const e=_A.getItemKey(a);C[e]=1/A.length}return C}const i={};for(const C of A){const a=_A.getItemKey(C);i[a]=I[a]/E}return i}static getItemKey(A){return typeof A=="string"?A:A&&typeof A=="object"&&"name"in A?String(A.name):String(A)}static getFinalWeights(A,B,g){const I={};if(g==="default")for(const E of A){const i=this.getItemKey(E);I[i]=1}else if(g==="absolute")for(const E of A){const i=this.getItemKey(E);I[i]=B[i]!==void 0?B[i]:1}else for(const E of A){const i=this.getItemKey(E);I[i]=B[i]!==void 0?B[i]:1}return I}}const Ei=[{id:"barbarian_rage",name:"Rage",description:"In battle, you fight with primal fury. On your turn, you can enter a rage as a bonus action. While raging, you gain the following benefits if you aren't wearing heavy armor: Advantage on Strength checks and Strength saving throws, +2 damage bonus with melee weapons using Strength, resistance to bludgeoning, piercing, and slashing damage.",type:"active",level:1,class:"Barbarian",effects:[{type:"stat_bonus",target:"melee_damage",value:2,condition:"while raging"}],source:"default",tags:["combat","damage"]},{id:"barbarian_unarmored_defense",name:"Unarmored Defense",description:"While you are not wearing any armor, your Armor Class equals 10 + your Dexterity modifier + your Constitution modifier.",type:"passive",level:1,class:"Barbarian",source:"default",tags:["defense"]},{id:"barbarian_reckless_attack",name:"Reckless Attack",description:"You can throw aside all concern for defense to attack with fierce desperation. When you make your first attack on your turn, you can decide to attack recklessly. Doing so gives you advantage on melee weapon attack rolls using Strength during this turn, but attack rolls against you have advantage until your next turn.",type:"active",level:2,class:"Barbarian",source:"default",tags:["combat"]},{id:"barbarian_danger_sense",name:"Danger Sense",description:"You gain an uncanny sense of when things nearby aren't as they should be, giving you edge when you attempt to dodge a danger or react to a hidden threat. You have advantage on Dexterity saving throws against effects that you can see, such as traps and spells.",type:"passive",level:2,class:"Barbarian",source:"default",tags:["defense","perception"]},{id:"barbarian_extra_attack",name:"Extra Attack",description:"You can attack twice, instead of once, whenever you take the Attack action on your turn.",type:"passive",level:5,class:"Barbarian",source:"default",tags:["combat"]},{id:"barbarian_fast_movement",name:"Fast Movement",description:"Your speed increases by 10 feet while you aren't wearing heavy armor.",type:"passive",level:5,class:"Barbarian",effects:[{type:"passive_modifier",target:"speed",value:10,condition:"unarmored"}],source:"default",tags:["movement"]},{id:"barbarian_feral_instinct",name:"Feral Instinct",description:"Your instincts are so honed that you have advantage on initiative rolls. Additionally, if you are surprised at the start of combat and aren't incapacitated, you can act normally on your first turn.",type:"passive",level:7,class:"Barbarian",source:"default",tags:["combat","perception"]},{id:"barbarian_brutal_critical",name:"Brutal Critical",description:"When you score a critical hit with a melee weapon attack, you can roll one of the weapon's damage dice one additional time and add it to the extra damage of the critical hit.",type:"passive",level:9,class:"Barbarian",source:"default",tags:["combat","damage"]},{id:"barbarian_relentless_endurance",name:"Relentless Endurance",description:"When you are reduced to 0 hit points but not killed outright, you can drop to 1 hit point instead. You can't use this feature again until you finish a long rest.",type:"active",level:11,class:"Barbarian",source:"default",tags:["survival"]},{id:"barbarian_persistent_rage",name:"Persistent Rage",description:"Your rage can't end early due to fatigue.",type:"passive",level:11,class:"Barbarian",source:"default",tags:["combat"]},{id:"barbarian_indomitable_might",name:"Indomitable Might",description:"Your Strength score increases by 4, and your maximum for that score becomes 24.",type:"passive",level:18,class:"Barbarian",effects:[{type:"stat_bonus",target:"STR",value:4},{type:"passive_modifier",target:"STR_max",value:24}],source:"default",tags:["ability"]},{id:"barbarian_primal_champion",name:"Primal Champion",description:"Your Strength and Constitution scores increase by 4, and your maximum for those scores becomes 24.",type:"passive",level:20,class:"Barbarian",effects:[{type:"stat_bonus",target:"STR",value:4},{type:"stat_bonus",target:"CON",value:4},{type:"passive_modifier",target:"STR_max",value:24},{type:"passive_modifier",target:"CON_max",value:24}],source:"default",tags:["ability"]},{id:"bardic_inspiration",name:"Bardic Inspiration",description:"You can inspire others through stirring words or music. To do so, you use a bonus action on your turn to choose one creature other than yourself within 60 feet of you who can hear you. That creature gains one Bardic Inspiration die, a d6.",type:"resource",level:1,class:"Bard",source:"default",tags:["support","resource"]},{id:"jack_of_all_trades",name:"Jack of All Trades",description:"You can add half your proficiency bonus, rounded down, to any ability check you make that doesn't already include your proficiency bonus.",type:"passive",level:2,class:"Bard",source:"default",tags:["skill"]},{id:"song_of_rest",name:"Song of Rest",description:"You can use soothing music or oration to help revitalize your wounded allies during a short rest. If you or any friendly creatures who can hear your performance regain hit points at the end of the short rest, each of those creatures regains an extra 1d6 hit points.",type:"passive",level:2,class:"Bard",source:"default",tags:["healing","support"]},{id:"bard_college",name:"Bard College",description:"At 3rd level, you delve into the advanced techniques of a bard college of your choice. Your choice grants you features at 3rd level and again at 6th and 14th level.",type:"passive",level:3,class:"Bard",source:"default",tags:["subclass"]},{id:"bardic_versatility",name:"Bardic Versatility",description:"Whenever you reach a level in this class that grants the Ability Score Improvement feature, you can do one of the following: Replace one of your skills with another skill from the bard list, gain proficiency in one skill of your choice, gain proficiency with one musical instrument of your choice, or gain proficiency with one tool of your choice.",type:"passive",level:4,class:"Bard",source:"default",tags:["skill","proficiency"]},{id:"font_of_inspiration",name:"Font of Inspiration",description:"When you roll initiative and have no uses of Bardic Inspiration left, you regain one use.",type:"passive",level:5,class:"Bard",source:"default",tags:["resource"]},{id:"countercharm",name:"Countercharm",description:"You gain the ability to use musical notes or words of power to disrupt mind-influencing effects. As an action, you can start a performance that lasts until the end of your next turn. During that time, you and any friendly creatures within 30 feet of you have advantage on saving throws against being frightened or charmed.",type:"active",level:6,class:"Bard",source:"default",tags:["support","defense"]},{id:"superior_inspiration",name:"Superior Inspiration",description:"When you roll initiative and have no uses of Bardic Inspiration left, you regain two uses.",type:"passive",level:10,class:"Bard",source:"default",tags:["resource"]},{id:"magical_secrets",name:"Magical Secrets",description:"You learn two spells of your choice from any class. A spell you choose must be of a level you can cast, as shown on the Bard table, or a cantrip. The chosen spells count as bard spells for you.",type:"passive",level:10,class:"Bard",source:"default",tags:["magic"]},{id:"unforgettable_face",name:"Unforgettable Face",description:"When you speak to a creature for the first time, you can choose one creature. That creature has disadvantage on attack rolls against you for 1 minute.",type:"active",level:14,class:"Bard",source:"default",tags:["social","defense"]},{id:"magical_secrets_2",name:"Magical Secrets",description:"You learn two spells of your choice from any class.",type:"passive",level:14,class:"Bard",source:"default",tags:["magic"]},{id:"bardic_inspiration_d8",name:"Bardic Inspiration (d8)",description:"Your Bardic Inspiration die changes to a d8.",type:"passive",level:15,class:"Bard",source:"default",tags:["resource"]},{id:"magical_secrets_3",name:"Magical Secrets",description:"You learn two spells of your choice from any class.",type:"passive",level:18,class:"Bard",source:"default",tags:["magic"]},{id:"bardic_inspiration_d10",name:"Bardic Inspiration (d10)",description:"Your Bardic Inspiration die changes to a d10.",type:"passive",level:20,class:"Bard",source:"default",tags:["resource"]},{id:"superior_inspiration_3",name:"Superior Inspiration",description:"When you roll initiative and have no uses of Bardic Inspiration left, you regain three uses.",type:"passive",level:20,class:"Bard",source:"default",tags:["resource"]},{id:"divine_domain",name:"Divine Domain",description:"Choose one domain related to your deity: Knowledge, Life, Light, Nature, Tempest, Trickery, or War. Each domain grants domain spells and other features at levels 1, 2, 6, 8, and 17.",type:"passive",level:1,class:"Cleric",source:"default",tags:["subclass","magic"]},{id:"divine_intervention",name:"Divine Intervention",description:"You can call on your deity to intervene on your behalf. Your deity intervenes by causing a effect related to their portfolio. You can use this feature once between long rests.",type:"active",level:10,class:"Cleric",source:"default",tags:["magic","divine"]},{id:"destroy_undead",name:"Destroy Undead",description:"When an undead fails its saving throw against your Turn Undead feature, the creature is instantly destroyed if its challenge rating is at or below a threshold shown on the Cleric table.",type:"passive",level:5,class:"Cleric",source:"default",tags:["combat","divine"]},{id:"divine_intervention_improved",name:"Divine Intervention (Improved)",description:"You can use Divine Intervention twice between long rests.",type:"active",level:20,class:"Cleric",source:"default",tags:["magic","divine"]},{id:"druidic",name:"Druidic",description:"You know Druidic, the secret language of druids. You can speak the language and use it to leave hidden messages. You and others who know this language automatically spot such a message. Others spot the message's presence with a successful DC 15 Wisdom (Perception) check but can't decipher it without magic.",type:"passive",level:1,class:"Druid",source:"default",tags:["language","secret"]},{id:"wild_shape",name:"Wild Shape",description:"You can use your action to magically assume the shape of a beast that you have seen before. You can transform into a beast with a challenge rating as shown on the Druid table.",type:"active",level:2,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"wild_shape_combat",name:"Wild Shape (Combat)",description:"You can transform into a beast with a challenge rating up to 1.",type:"passive",level:2,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"druid_circle",name:"Druid Circle",description:"At 2nd level, you choose to identify with a circle of druids. Your choice grants you features at 2nd level and again at 6th, 10th, and 14th level.",type:"passive",level:2,class:"Druid",source:"default",tags:["subclass"]},{id:"wild_shape_aquatic",name:"Wild Shape (Aquatic)",description:"You can transform into a beast with a swimming speed.",type:"passive",level:4,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"wild_shape_cr_2",name:"Wild Shape (CR 2)",description:"You can transform into a beast with a challenge rating up to 2.",type:"passive",level:8,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"wild_shape_cr_3",name:"Wild Shape (CR 3)",description:"You can transform into a beast with a challenge rating up to 3.",type:"passive",level:8,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"timeless_body",name:"Timeless Body",description:"You age slowly, appearing no older than you did at the start of your druidic studies.",type:"passive",level:18,class:"Druid",source:"default",tags:["ability"]},{id:"beast_spells",name:"Beast Spells",description:"You can cast many of your druid spells in any shape you assume using Wild Shape.",type:"passive",level:18,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"archdruid",name:"Archdruid",description:"You can use your Wild Shape an unlimited number of times.",type:"passive",level:20,class:"Druid",source:"default",tags:["magic","shapeshifting"]},{id:"fighting_style",name:"Fighting Style",description:"You adopt a style of fighting as your specialty. Choose one of the following: Archery, Defense, Dueling, Great Weapon Fighting, Protection, Two-Weapon Fighting, or Unarmed Fighting.",type:"passive",level:1,class:"Fighter",source:"default",tags:["combat","style"]},{id:"second_wind",name:"Second Wind",description:"You have a limited well of stamina you can draw on to protect yourself. As a bonus action, you can regain hit points equal to 1d10 + your fighter level.",type:"active",level:1,class:"Fighter",source:"default",tags:["healing","combat"]},{id:"action_surge",name:"Action Surge",description:"You can push yourself beyond your normal limits for a moment. On your turn, you can take one additional action.",type:"active",level:2,class:"Fighter",source:"default",tags:["combat"]},{id:"martial_archetype",name:"Martial Archetype",description:"At 3rd level, you choose an archetype that you strive to emulate in your combat styles. Your choice grants you features at 3rd level and again at 7th, 10th, 15th, and 18th level.",type:"passive",level:3,class:"Fighter",source:"default",tags:["subclass"]},{id:"fighter_extra_attack",name:"Extra Attack",description:"You can attack twice, instead of once, whenever you take the Attack action on your turn.",type:"passive",level:5,class:"Fighter",source:"default",tags:["combat"]},{id:"indomitable",name:"Indomitable",description:"You can reroll a saving throw that you fail. If you do so, you must use the new roll.",type:"active",level:9,class:"Fighter",source:"default",tags:["defense","combat"]},{id:"indomitable_2",name:"Indomitable (Twice)",description:"You can use Indomitable twice between long rests.",type:"active",level:13,class:"Fighter",source:"default",tags:["defense","combat"]},{id:"indomitable_3",name:"Indomitable (Thrice)",description:"You can use Indomitable three times between long rests.",type:"active",level:17,class:"Fighter",source:"default",tags:["defense","combat"]},{id:"action_surge_2",name:"Action Surge (Improved)",description:"You can use Action Surge twice between short rests.",type:"passive",level:17,class:"Fighter",source:"default",tags:["combat"]},{id:"unarmored_defense_monk",name:"Unarmored Defense",description:"Beginning at 1st level, while you are wearing no armor and not wielding a shield, your AC equals 10 + your Dexterity modifier + your Wisdom modifier.",type:"passive",level:1,class:"Monk",source:"default",tags:["defense"]},{id:"martial_arts",name:"Martial Arts",description:"You gain the following benefits while you are unarmed or wielding only monk weapons and you aren't wearing armor or wielding a shield: You can use Dexterity instead of Strength for attacks and damage rolls with your unarmed strikes and monk weapons, you can roll a d4 in place of the normal damage of your monk weapon or unarmed strike, and when you use the Attack action with an unarmed strike or a monk weapon, you can make one unarmed strike as a bonus action.",type:"passive",level:1,class:"Monk",source:"default",tags:["combat"]},{id:"ki",name:"Ki",description:"Starting at 2nd level, your training allows you to harness the mystic energy of ki. Your access to this energy is represented by a number of Ki points. You have a number of Ki points equal to your monk level.",type:"resource",level:2,class:"Monk",source:"default",tags:["resource","magic"]},{id:"flurry_of_blows",name:"Flurry of Blows",description:"Immediately after you take the Attack action on your turn, you can spend 1 Ki point to make two unarmed strikes as a bonus action.",type:"active",level:2,class:"Monk",source:"default",tags:["combat"]},{id:"patient_defense",name:"Patient Defense",description:"You can spend 1 Ki point to take the Dodge action as a bonus action on your turn.",type:"active",level:2,class:"Monk",source:"default",tags:["defense","combat"]},{id:"step_of_the_wind",name:"Step of the Wind",description:"You can spend 1 Ki point to take the Disengage or Dash action as a bonus action on your turn, and your jump distance is doubled for the turn.",type:"active",level:2,class:"Monk",source:"default",tags:["movement","combat"]},{id:"monastic_tradition",name:"Monastic Tradition",description:"When you reach 3rd level, you commit yourself to a monastic tradition. Your tradition grants you features at 3rd level and again at 6th, 11th, and 17th level.",type:"passive",level:3,class:"Monk",source:"default",tags:["subclass"]},{id:"slow_fall",name:"Slow Fall",description:"At 4th level, you can use your reaction when you fall to reduce any falling damage you take by an amount equal to five times your monk level.",type:"passive",level:4,class:"Monk",source:"default",tags:["defense","movement"]},{id:"extra_attack_monk",name:"Extra Attack",description:"You can attack twice, instead of once, whenever you take the Attack action on your turn.",type:"passive",level:5,class:"Monk",source:"default",tags:["combat"]},{id:"stunning_strike",name:"Stunning Strike",description:"Starting at 5th level, you can interfere with the flow of ki in an opponent's body. When you hit another creature with a melee weapon attack, you can spend 1 Ki point to attempt a stunning strike. The target must succeed on a Constitution saving throw or be stunned until the end of your next turn.",type:"active",level:5,class:"Monk",source:"default",tags:["combat"]},{id:"ki_empowered_strikes",name:"Ki-Empowered Strikes",description:"Starting at 6th level, your unarmed strikes count as magical for the purpose of overcoming resistance and immunity to nonmagical attacks and damage.",type:"passive",level:6,class:"Monk",source:"default",tags:["combat","magic"]},{id:"stillness_of_mind",name:"Stillness of Mind",description:"At 7th level, you can use your action to end one effect on yourself that is causing you to be charmed or frightened.",type:"active",level:7,class:"Monk",source:"default",tags:["defense"]},{id:"unarmored_movement",name:"Unarmored Movement",description:"Your speed increases by 10 feet while you are not wearing armor or wielding a shield. This bonus increases when you reach certain monk levels.",type:"passive",level:2,class:"Monk",effects:[{type:"passive_modifier",target:"speed",value:10,condition:"unarmored"}],source:"default",tags:["movement"]},{id:"pure_body",name:"Purity of Body",description:"At 10th level, your mastery of the ki flowing through you makes you immune to disease and poison.",type:"passive",level:10,class:"Monk",source:"default",tags:["defense","ability"]},{id:"tongue_of_the_sun_and_moon",name:"Tongue of the Sun and Moon",description:"At 13th level, you learn to touch the ki of other minds so that you understand all spoken languages. Moreover, any creature that can understand a language can understand what you say.",type:"passive",level:13,class:"Monk",source:"default",tags:["language","social"]},{id:"empty_body",name:"Empty Body",description:"At 18th level, you can spend 4 Ki points to start becoming invisible for 1 minute. During that time, you also have resistance to all damage but force damage.",type:"active",level:18,class:"Monk",source:"default",tags:["defense","magic"]},{id:"divine_sense",name:"Divine Sense",description:"As an action, you can detect good and evil. You can sense the presence of any celestial, fiend, or undead within 60 feet of you.",type:"active",level:1,class:"Paladin",source:"default",tags:["perception","divine"]},{id:"lay_on_hands",name:"Lay on Hands",description:"Your blessed touch can heal wounds. You have a pool of healing power that replenishes when you take a long rest. With that pool, you can restore a total number of hit points equal to your paladin level × 5.",type:"active",level:2,class:"Paladin",source:"default",tags:["healing","divine"]},{id:"fighting_style_paladin",name:"Fighting Style",description:"You adopt a style of fighting as your specialty. Choose one of the following: Defense, Dueling, Great Weapon Fighting, Protection, or Two-Weapon Fighting.",type:"passive",level:2,class:"Paladin",source:"default",tags:["combat","style"]},{id:"divine_smite",name:"Divine Smite",description:"When you hit a creature with a melee weapon attack, you can expend one spell slot to deal radiant damage to the target.",type:"active",level:2,class:"Paladin",source:"default",tags:["combat","divine"]},{id:"sacred_oath",name:"Sacred Oath",description:"When you reach 3rd level, you swear the oath that binds you as a paladin forever. Your choice grants you features at 3rd level and again at 7th, 15th, and 20th level.",type:"passive",level:3,class:"Paladin",source:"default",tags:["subclass","divine"]},{id:"aura_of_protection",name:"Aura of Protection",description:"Starting at 6th level, you and friendly creatures within 10 feet of you gain a bonus to all saving throws equal to your Charisma modifier (minimum of +1).",type:"passive",level:6,class:"Paladin",source:"default",tags:["defense","aura"]},{id:"aura_of_courage",name:"Aura of Courage",description:"Starting at 10th level, you and friendly creatures within 10 feet of you can't be frightened.",type:"passive",level:10,class:"Paladin",source:"default",tags:["defense","aura"]},{id:"improved_divine_smite",name:"Improved Divine Smite",description:"Starting at 11th level, you are so suffused with righteous might that all your melee weapon strikes carry divine power with them. Whenever you hit a creature with a melee weapon, the creature takes an extra 1d8 radiant damage.",type:"passive",level:11,class:"Paladin",source:"default",tags:["combat","divine"]},{id:"cleansing_touch",name:"Cleansing Touch",description:"At 14th level, you can use your action to end one spell or effect on yourself or one willing creature that you touch.",type:"active",level:14,class:"Paladin",source:"default",tags:["defense","divine"]},{id:"aura_improvements",name:"Aura Improvements",description:"At 18th level, the range of your auras increases to 30 feet.",type:"passive",level:18,class:"Paladin",source:"default",tags:["aura"]},{id:"favored_enemy",name:"Favored Enemy",description:"You have significant experience studying, tracking, hunting, and even talking to a certain type of enemy. Choose a type of favored enemy: aberrations, beasts, celestials, constructs, dragons, elementals, fey, fiends, giants, monstrosities, oozes, plants, or undead. You gain a bonus to damage rolls against creatures of the chosen type.",type:"passive",level:1,class:"Ranger",source:"default",tags:["combat"]},{id:"natural_explorer",name:"Natural Explorer",description:"You are a master of navigating the natural world. You choose a type of favored terrain: arctic, coast, desert, forest, grassland, mountain, swamp, or the Underdark. While traveling for an hour or more in your favored terrain, you gain the following benefits: Difficult terrain doesn't slow your group's travel, your group can't become lost except by magical means, and you remain alert to danger even when you are engaged in another activity.",type:"passive",level:1,class:"Ranger",source:"default",tags:["exploration"]},{id:"fighting_style_ranger",name:"Fighting Style",description:"You adopt a style of fighting as your specialty. Choose one of the following: Archery, Defense, Dueling, Great Weapon Fighting, Two-Weapon Fighting, or Mariner (if you have a swimming speed).",type:"passive",level:2,class:"Ranger",source:"default",tags:["combat","style"]},{id:"spellcasting_ranger",name:"Spellcasting",description:"By the time you reach 2nd level, you have learned to use the magical essence of nature to cast spells, much as a druid does.",type:"passive",level:2,class:"Ranger",source:"default",tags:["magic"]},{id:"ranger_archetype",name:"Ranger Archetype",description:"At 3rd level, you choose an archetype that you strive to emulate in your combat styles and techniques. Your choice grants you features at 3rd level and again at 5th, 7th, 11th, and 15th level.",type:"passive",level:3,class:"Ranger",source:"default",tags:["subclass"]},{id:"prime_awareness",name:"Prime-Aware Explorer",description:"At 6th level, your mastery of the wild allows you to navigate with ease. You can use the Hide action as a bonus action. You also gain an additional Favored Enemy and Favored Terrain.",type:"passive",level:6,class:"Ranger",source:"default",tags:["exploration","stealth"]},{id:"fleet_of_foot",name:"Fleet of Foot",description:"Your speed increases by 5 feet.",type:"passive",level:8,class:"Ranger",effects:[{type:"passive_modifier",target:"speed",value:5}],source:"default",tags:["movement"]},{id:"hide_in_plain_sight",name:"Hide in Plain Sight",description:"Starting at 10th level, you can remain perfectly still for long periods to blend in with your surroundings. You can spend 1 minute creating camouflage and gain advantage on Stealth checks.",type:"active",level:10,class:"Ranger",source:"default",tags:["stealth"]},{id:"vanish",name:"Vanish",description:"Starting at 14th level, you can use the Hide action as a bonus action on your turn. Also, you can't be tracked by nonmagical means.",type:"passive",level:14,class:"Ranger",source:"default",tags:["stealth"]},{id:"feral_senses",name:"Feral Senses",description:"At 18th level, you gain preternatural senses that help you fight creatures you can't see. When you attack a creature you can't see, your inability to see it doesn't impose disadvantage on your attack rolls. You are also aware of the location of any invisible creature within 30 feet of you.",type:"passive",level:18,class:"Ranger",source:"default",tags:["perception","combat"]},{id:"sneak_attack",name:"Sneak Attack",description:"You know how to strike subtly and exploit a foe's distraction. Once per turn, you can deal an extra 1d6 damage to one creature you hit with an attack if you have advantage on the attack roll.",type:"passive",level:1,class:"Rogue",source:"default",tags:["combat","damage"]},{id:"thieves_cant",name:"Thieves' Cant",description:"During your rogue training you learned thieves' cant, a secret mix of dialect, hand signs, and body language that allows you to hide messages in seemingly normal conversation.",type:"passive",level:1,class:"Rogue",source:"default",tags:["language","secret"]},{id:"cunning_action",name:"Cunning Action",description:"You can take a bonus action on each of your turns in combat. This action can be used only to take the Dash, Disengage, or Hide action.",type:"active",level:2,class:"Rogue",source:"default",tags:["combat","movement"]},{id:"roguish_archetype",name:"Roguish Archetype",description:"At 3rd level, you choose an archetype that you strive to emulate in your combat styles and techniques. Your choice grants you features at 3rd level and then again at 9th, 13th, and 17th level.",type:"passive",level:3,class:"Rogue",source:"default",tags:["subclass"]},{id:"ability_score_improvement_rogue",name:"Ability Score Improvement",description:"At 4th level, you can increase one ability score by 2 or two ability scores by 1.",type:"passive",level:4,class:"Rogue",source:"default",tags:["ability"]},{id:"uncanny_dodge",name:"Uncanny Dodge",description:"Starting at 5th level, when an attacker that you can see hits you with an attack, you can use your reaction to halve the attack's damage against you.",type:"active",level:5,class:"Rogue",source:"default",tags:["defense","combat"]},{id:"evasion",name:"Evasion",description:"Starting at 7th level, you can nimbly dodge out of the way of certain area effects. When you are subjected to an effect that allows you to make a Dexterity saving throw to take only half damage, you instead take no damage if you succeed and only half damage if you fail.",type:"passive",level:7,class:"Rogue",source:"default",tags:["defense"]},{id:"slippery_mind",name:"Slippery Mind",description:"At 11th level, you have acquired greater mental strength. You gain proficiency in Wisdom saving throws.",type:"passive",level:11,class:"Rogue",source:"default",tags:["defense"]},{id:"elusive",name:"Elusive",description:"Beginning at 18th level, you are so evasive that attackers rarely gain the upper hand against you. No attack roll has advantage against you while you aren't incapacitated.",type:"passive",level:18,class:"Rogue",source:"default",tags:["defense"]},{id:"stroke_of_luck",name:"Stroke of Luck",description:"At 20th level, you have an uncanny knack for succeeding when you need to. If your attack misses a target within range, you can turn the miss into a hit. Alternatively, if you fail an ability check, you can treat the d20 roll as a 20.",type:"active",level:20,class:"Rogue",source:"default",tags:["combat","luck"]},{id:"sorcerous_restoration",name:"Sorcerous Restoration",description:"You can regain 4 sorcery points on a short rest.",type:"passive",level:20,class:"Sorcerer",source:"default",tags:["resource"]},{id:"font_of_magic",name:"Font of Magic",description:"You can manipulate the weave of magic to your advantage. You have 2 sorcery points. You gain more as you level. You can use sorcery points to create additional spell slots or gain spell slots.",type:"resource",level:2,class:"Sorcerer",source:"default",tags:["resource","magic"]},{id:"metamagic",name:"Metamagic",description:"At 3rd level, you gain the ability to twist your spells to suit your needs. You gain two metamagic options of your choice: Careful Spell, Distant Spell, Empowered Spell, Extended Spell, Heightened Spell, Quickened Spell, Subtle Spell, Twinned Spell.",type:"active",level:3,class:"Sorcerer",source:"default",tags:["magic"]},{id:"sorcerous_origin",name:"Sorcerous Origin",description:"Choose a sorcerous origin, which describes the source of your magical power: Draconic Bloodline, Wild Magic, or another origin.",type:"passive",level:1,class:"Sorcerer",source:"default",tags:["subclass"]},{id:"metamagic_3",name:"Metamagic (3 options)",description:"At 10th level, you gain a third metamagic option.",type:"active",level:10,class:"Sorcerer",source:"default",tags:["magic"]},{id:"metamagic_4",name:"Metamagic (4 options)",description:"At 17th level, you gain a fourth metamagic option.",type:"active",level:17,class:"Sorcerer",source:"default",tags:["magic"]},{id:"otherworldly_patron",name:"Otherworldly Patron",description:"At 1st level, you have struck a bargain with an otherworldly being of power. Your choice grants you features at 1st level and again at 6th, 10th, and 14th level.",type:"passive",level:1,class:"Warlock",source:"default",tags:["subclass"]},{id:"pact_magic",name:"Pact Magic",description:"You have learned to delve into the secrets of magic to harness the power of your patron. You know two cantrips and a number of spells.",type:"passive",level:1,class:"Warlock",source:"default",tags:["magic"]},{id:"eldritch_master",name:"Eldritch Master",description:"At 20th level, you can draw on your inner reserve of magical power while entreating your patron to regain expended spell slots. You can regain all your warlock spell slots on a short or long rest.",type:"active",level:20,class:"Warlock",source:"default",tags:["magic","resource"]},{id:"mystic_arcanum",name:"Mystic Arcanum",description:"At 11th level, your patron bestows upon you the ability to cast a 6th-level spell. You gain additional spells at higher levels.",type:"passive",level:11,class:"Warlock",source:"default",tags:["magic"]},{id:"arcane_recovery",name:"Arcane Recovery",description:"You have learned to regain some of your magical energy by studying your spellbook. Once per day when you finish a short rest, you can recover expended spell slots whose combined level equals no more than half your wizard level.",type:"active",level:1,class:"Wizard",source:"default",tags:["magic","resource"]},{id:"arcane_tradition",name:"Arcane Tradition",description:"When you reach 2nd level, you choose an arcane tradition that shapes your practice of magic. Your choice grants you features at 2nd level and again at 6th, 10th, and 14th level.",type:"passive",level:2,class:"Wizard",source:"default",tags:["subclass"]},{id:"spell_mastery",name:"Spell Mastery",description:"At 18th level, you have achieved profound mastery over spells. Choose two 1st-level wizard spells that you know. You can cast these spells at their lowest level without expending a spell slot.",type:"passive",level:18,class:"Wizard",source:"default",tags:["magic"]},{id:"signature_spells",name:"Signature Spells",description:"When you reach 20th level, you gain mastery over two powerful spells. Choose two 3rd-level wizard spells that you know. You can cast these spells at their lowest level without expending a spell slot.",type:"passive",level:20,class:"Wizard",source:"default",tags:["magic"]}],ii=[{id:"human_versatile",name:"Versatile",description:"Humans gain proficiency in one skill of their choice.",race:"Human",source:"default",tags:["skill"]},{id:"human_extra_language",name:"Extra Language",description:"Humans can speak, read, and write one extra language of their choice.",race:"Human",source:"default",tags:["language"]},{id:"elf_darkvision",name:"Darkvision",description:"Accustomed to twilit forests and the night sky, elves have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Elf",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"elf_keen_senses",name:"Keen Senses",description:"Elves have proficiency in the Perception skill.",race:"Elf",source:"default",effects:[{type:"skill_proficiency",target:"perception",value:"proficient"}],tags:["skill","perception"]},{id:"elf_fey_ancestry",name:"Fey Ancestry",description:"Elves have advantage on saving throws against being charmed, and magic can't put them to sleep.",race:"Elf",source:"default",tags:["defense","magic"]},{id:"elf_trance",name:"Trance",description:"Elves don't need to sleep. Instead, they meditate deeply, remaining semiconscious, for 4 hours a day. After resting in this way, you gain the same benefit that a human does from 8 hours of sleep.",race:"Elf",source:"default",tags:["ability"]},{id:"dwarf_darkvision",name:"Darkvision",description:"Accustomed to life underground, dwarves have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Dwarf",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"dwarf_dwarven_resilience",name:"Dwarven Resilience",description:"Dwarves have advantage on saving throws against poison, and resistance against poison damage.",race:"Dwarf",source:"default",tags:["defense"]},{id:"dwarf_stonecunning",name:"Stonecunning",description:"Whenever you make an Intelligence (History) check related to the origin of stonework, you are considered proficient in the History skill and add double your proficiency bonus to the check.",race:"Dwarf",source:"default",tags:["skill","exploration"]},{id:"halfling_lucky",name:"Lucky",description:"When you roll a 1 on an attack roll, ability check, or saving throw, you can reroll the die and must use the new roll.",race:"Halfling",source:"default",tags:["luck"]},{id:"halfling_brave",name:"Brave",description:"Halflings have advantage on saving throws against being frightened.",race:"Halfling",source:"default",tags:["defense"]},{id:"halfling_halfling_nimbleness",name:"Halfling Nimbleness",description:"Halflings can move through the space of any creature that is larger than them.",race:"Halfling",source:"default",tags:["movement"]},{id:"dragonborn_draconic_ancestry",name:"Draconic Ancestry",description:"Dragonborn have draconic ancestry linked to a specific type of dragon. This determines their breath weapon and damage resistance.",race:"Dragonborn",source:"default",tags:["ancestry","combat"]},{id:"dragonborn_breath_weapon",name:"Breath Weapon",description:"Dragonborn can use their action to exhale destructive energy. Their draconic ancestry determines the size, shape, and damage type of the breath weapon.",race:"Dragonborn",source:"default",tags:["combat"]},{id:"dragonborn_damage_resistance",name:"Damage Resistance",description:"Dragonborn have resistance to the damage type associated with their draconic ancestry.",race:"Dragonborn",source:"default",tags:["defense"]},{id:"gnome_darkvision",name:"Darkvision",description:"Accustomed to life underground, gnomes have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Gnome",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"gnome_gnome_cunning",name:"Gnome Cunning",description:"Gnomes have advantage on all Intelligence, Wisdom, and Charisma saving throws against magic.",race:"Gnome",source:"default",tags:["defense","magic"]},{id:"half_elf_darkvision",name:"Darkvision",description:"Thanks to your elf blood, you have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Half-Elf",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"half_elf_fey_ancestry",name:"Fey Ancestry",description:"Half-elves have advantage on saving throws against being charmed, and magic can't put them to sleep.",race:"Half-Elf",source:"default",tags:["defense","magic"]},{id:"half_elf_skill_versatility",name:"Skill Versatility",description:"Half-elves gain proficiency in two skills of their choice.",race:"Half-Elf",source:"default",tags:["skill"]},{id:"half_orc_darkvision",name:"Darkvision",description:"Thanks to your orc blood, you have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Half-Orc",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"half_orc_relentless_endurance",name:"Relentless Endurance",description:"When you are reduced to 0 hit points but not killed outright, you can drop to 1 hit point instead. You can't use this feature again until you finish a long rest.",race:"Half-Orc",source:"default",tags:["survival"]},{id:"half_orc_savage_attacks",name:"Savage Attacks",description:"When you score a critical hit with a melee weapon attack, you can roll one of the weapon's damage dice one additional time and add it to the extra damage of the critical hit.",race:"Half-Orc",source:"default",tags:["combat","damage"]},{id:"tiefling_darkvision",name:"Darkvision",description:"Thanks to your infernal heritage, you have superior vision in dark and dim conditions. You can see in dim light within 60 feet of you as if it were bright light, and in darkness as if it were dim light. You can't discern color in darkness, only shades of gray.",race:"Tiefling",source:"default",effects:[{type:"ability_unlock",target:"darkvision",value:60}],tags:["vision"]},{id:"tiefling_hellish_resistance",name:"Hellish Resistance",description:"Tieflings have resistance to fire damage.",race:"Tiefling",source:"default",tags:["defense"]},{id:"tiefling_infernal_legacy",name:"Infernal Legacy",description:"Tieflings know the thaumaturgy cantrip. When you reach 3rd level, you can cast the hellish rebuke spell as a 2nd-level spell once with this trait and regain the ability to do so when you finish a long rest. When you reach 5th level, you can cast the darkness spell once with this trait and regain the ability to do so when you finish a long rest. Charisma is your spellcasting ability for these spells.",race:"Tiefling",source:"default",tags:["magic","spell"]}],Ci=[{id:"athletics",name:"Athletics",ability:"STR",armorPenalty:!0,categories:["physical","exploration","combat"],source:"default",description:"Covers climbing, jumping, swimming, and other physical feats of strength. Use this skill when you need to scale walls, leap across chasms, swim in turbulent waters, or perform any other physical activity that raw strength can accomplish."},{id:"acrobatics",name:"Acrobatics",ability:"DEX",armorPenalty:!0,categories:["physical","exploration"],source:"default",description:"Covers balancing, tumbling, and maintaining footing in difficult situations. Use this skill to walk on tightropes, stay on your feet during earthquakes, perform gymnastic feats, and dodge falling objects or area effects."},{id:"sleight_of_hand",name:"Sleight of Hand",ability:"DEX",armorPenalty:!0,categories:["physical","criminal","subterfuge"],source:"default",description:"Covers manual dexterity and fine motor skills such as picking pockets, palming items, and performing magic tricks. Use this skill when you need to steal something unnoticed, hide an object on your person, or manipulate small objects with precision."},{id:"stealth",name:"Stealth",ability:"DEX",armorPenalty:!0,categories:["physical","subterfuge","exploration"],source:"default",description:"Covers hiding, moving silently, and avoiding detection. Use this skill when you want to sneak past guards, hide in shadows, stalk prey, or conceal yourself from enemies. Your environment matters—darkness and cover provide advantage."},{id:"arcana",name:"Arcana",ability:"INT",armorPenalty:!1,categories:["knowledge","magic"],source:"default",description:"Covers knowledge about magical theory, arcane traditions, magical creatures, and the planes. Use this skill to identify magical items, understand spells, recognize arcane symbols, and recall lore about wizards, dragons, and other magical phenomena."},{id:"history",name:"History",ability:"INT",armorPenalty:!1,categories:["knowledge"],source:"default",description:"Covers knowledge about historical events, legendary figures, ancient civilizations, and past conflicts. Use this skill to recall the origins of ruins, identify royal lineages, understand the significance of ancient documents, and recognize historical artifacts."},{id:"investigation",name:"Investigation",ability:"INT",armorPenalty:!1,categories:["knowledge","exploration"],source:"default",description:"Covers deductive reasoning, analyzing clues, and piecing together information. Use this skill when you need to deduce the composition of an object, follow tracks, interpret coded messages, or draw conclusions from scattered evidence."},{id:"nature",name:"Nature",ability:"INT",armorPenalty:!1,categories:["knowledge","environmental"],source:"default",description:"Covers knowledge about plants, animals, weather, and the natural world. Use this skill to identify plants and beasts, predict weather changes, understand terrain, and recall lore about the wilderness and its inhabitants."},{id:"religion",name:"Religion",ability:"INT",armorPenalty:!1,categories:["knowledge"],source:"default",description:"Covers knowledge about deities, religious traditions, divine magic, and the planes of existence. Use this skill to recognize religious symbols, understand divine spells, identify outsiders, and recall lore about gods, angels, and religious cults."},{id:"animal_handling",name:"Animal Handling",ability:"WIS",armorPenalty:!1,categories:["environmental","social"],source:"default",description:"Covers calming, training, and understanding animals. Use this skill when you need to control a mount, calm a frightened beast, read an animal's mood, or predict how an animal might react. This skill doesn't work on creatures with Intelligence higher than 2."},{id:"insight",name:"Insight",ability:"WIS",armorPenalty:!1,categories:["social","perception"],source:"default",description:"Covers reading people, detecting lies, and understanding motives. Use this skill to determine when someone is lying to you, sense hidden agendas, gauge someone's true feelings, or predict how someone might act in a social situation."},{id:"medicine",name:"Medicine",ability:"WIS",armorPenalty:!1,categories:["knowledge","practical"],source:"default",description:"Covers diagnosing illnesses, treating wounds, and stabilizing dying creatures. Use this skill to determine the cause of a strange illness, assess the severity of injuries, provide first aid, or stabilize a dying companion. This skill does not cover magical healing."},{id:"perception",name:"Perception",ability:"WIS",armorPenalty:!1,categories:["perception","exploration"],source:"default",description:"Covers awareness of your surroundings and noticing hidden things. Use this skill to spot hidden enemies, find secret doors, hear approaching creatures, detect ambushes, or notice unusual details in your environment. This is the most commonly used skill in the game."},{id:"survival",name:"Survival",ability:"WIS",armorPenalty:!1,categories:["environmental","exploration"],source:"default",description:"Covers following tracks, hunting, foraging, and navigating in the wilderness. Use this skill to follow creature tracks, find food and water, predict weather, navigate without a map, or avoid natural hazards. This skill is essential for wilderness adventures."},{id:"deception",name:"Deception",ability:"CHA",armorPenalty:!1,categories:["social","subterfuge"],source:"default",description:"Covers lying, misdirection, and hiding the truth. Use this skill when you need to convincingly tell a falsehood, maintain a cover identity, pass hidden messages, or trick someone into believing something that isn't true. Success depends on plausibility and your target's suspicions."},{id:"intimidation",name:"Intimidation",ability:"CHA",armorPenalty:!1,categories:["social","combat"],source:"default",description:"Covers frightening others and forcing compliance through threats. Use this skill when you want to scare someone into backing down, extract information through fear, force a prisoner to talk, or make an opponent hesitate. Physical presence and reputation can provide advantage."},{id:"performance",name:"Performance",ability:"CHA",armorPenalty:!1,categories:["social","entertainment"],source:"default",description:"Covers entertaining audiences through music, acting, storytelling, or other arts. Use this skill when you need to captivate an audience, earn money through performance, distract guards with entertainment, or pass as a traveling performer. Quality and audience receptiveness affect the DC."},{id:"persuasion",name:"Persuasion",ability:"CHA",armorPenalty:!1,categories:["social"],source:"default",description:"Covers influencing others through reason, charm, and good faith. Use this skill when you need to convince someone to see your point of view, negotiate favorable terms, get someone to do you a favor, or rally people to your cause. This skill works best when you're being honest."}],Bd=["physical","exploration","combat","criminal","subterfuge","knowledge","magic","environmental","social","perception","practical","entertainment"],gd={"appearance.bodyTypes":["slender","athletic","muscular","stocky"],"appearance.skinTones":["#F5E6D3","#E8C4A0","#D4A574","#C68642","#8D5524","#5C3317"],"appearance.hairColors":["#1C1C1C","#3B2414","#6A4E23","#A67B5B","#D4AF37","#E9C2A6","#B55239","#DC143C","#C0C0C0","#FFFFFF"],"appearance.hairStyles":["short","long","bald","braided","curly","wavy","straight","ponytail","mohawk","dreadlocks"],"appearance.eyeColors":["#3B2414","#6F4E37","#228B22","#4169E1","#708090","#000000"],"appearance.facialFeatures":["scar on cheek","tattoo on forehead","piercing","freckles","beard","mustache","clean-shaven","birthmark","sharp jawline","soft features"]};function ai(){const Q=AA.getInstance();for(const[A,B]of Object.entries(gd))Q.initializeDefaults(A,[...B])}function mo(){return AA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("appearance."))}function ei(){mo()||ai()}const Id=Object.values(wE),Qd=Object.entries(SI).map(([Q,A])=>({class:Q,cantrips:A.cantrips,spells_by_level:A.spells_by_level}));function oi(){const Q=AA.getInstance();Q.initializeDefaults("spells",Id);for(const A of Qd){const B=`spells.${A.class}`;Q.initializeDefaults(B,[A])}}function uo(){return AA.getInstance().getRegisteredCategories().some(B=>String(B).startsWith("spells"))}function $I(){uo()||oi()}const Ed=Object.values(Eg).map(Q=>({...Q,source:"default",spawnWeight:Q.spawnWeight??1,tags:Q.tags??[]}));function ti(){AA.getInstance().initializeDefaults("equipment",Ed)}function So(){return AA.getInstance().getRegisteredCategories().some(B=>B==="equipment")}function si(){So()||ti()}function Gi(){AA.getInstance().initializeDefaults("races",[...Ta])}function bo(){return AA.getInstance().getRegisteredCategories().some(B=>B==="races")}function ni(){bo()||Gi()}function hi(){AA.getInstance().initializeDefaults("races.data",[...Pa])}function po(){return AA.getInstance().getRegisteredCategories().some(B=>B==="races.data")}function Yo(){po()||hi()}function ci(){AA.getInstance().initializeDefaults("classes",[...Ka])}function Uo(){return AA.getInstance().getRegisteredCategories().some(B=>B==="classes")}function ri(){Uo()||ci()}function id(){ai(),oi(),ti(),Gi(),hi(),ci(),li(),di()}function Cd(){ei(),$I(),si(),ni(),Yo(),ri(),Di(),Wo()}function li(){const Q=AA.getInstance(),A={};for(const g of Ei)A[g.class]||(A[g.class]=[]),A[g.class].push(g);Q.initializeDefaults("classFeatures",[...Ei]);for(const[g,I]of Object.entries(A)){const E=`classFeatures.${g}`;Q.initializeDefaults(E,I)}const B={};for(const g of ii)B[g.race]||(B[g.race]=[]),B[g.race].push(g);Q.initializeDefaults("racialTraits",[...ii]);for(const[g,I]of Object.entries(B)){const E=`racialTraits.${g}`;Q.initializeDefaults(E,I)}}function ko(){return AA.getInstance().getRegisteredCategories().some(B=>B==="classFeatures"||B==="racialTraits")}function Di(){ko()||li()}function di(){const Q=AA.getInstance(),A={STR:[],DEX:[],CON:[],INT:[],WIS:[],CHA:[]};for(const B of Ci)A[B.ability].push(B);Q.initializeDefaults("skills",[...Ci]);for(const[B,g]of Object.entries(A)){const I=`skills.${B}`;Q.initializeDefaults(I,g)}}function Zo(){const Q=AA.getInstance();return Q.hasCustomData("skills")||Q.getDefaults("skills").length>0}function Wo(){Zo()||di()}class Ho{static select(A){ni();const B=AA.getInstance(),g=B.get("races"),I=B.getWeights("races"),E=B.getMode("races")||"default";return _A.select(g,I,A,E)}}const SC=class SC{static suggest(A,B){ri();const g=AA.getInstance(),I=g.get("classes"),E=this.calculateAllAffinities(A,I),i=this.calculateProbabilities(E),C=g.getWeights("classes"),a=this.applyCustomWeights(i,C,I),e=Object.entries(a).map(([o,t])=>[o,t]);return B.weightedChoice(e)}static calculateAllAffinities(A,B){const g={};for(const I of B)g[I]=this.calculateClassAffinity(A,I);return g}static calculateClassAffinity(A,B){let g=this.getCustomClassAudioPreferences(B);if(g||(g=za[B]),!g)return .5;let I=0;return I+=this.getTraitContribution(A,g.primary,g,1),g.secondary&&(I+=this.getTraitContribution(A,g.secondary,g,.5)),g.tertiary&&(I+=this.getTraitContribution(A,g.tertiary,g,.25)),I}static getCustomClassAudioPreferences(A){try{const g=AA.getInstance().get("classes.data");if(g&&Array.isArray(g)){const I=g.find(E=>E.name===A);if(I&&I.audio_preferences)return I.audio_preferences}}catch{}}static getTraitContribution(A,B,g,I){switch(B){case"bass":return A.bass_dominance*(g.bass||1)*I;case"treble":return A.treble_dominance*(g.treble||1)*I;case"mid":return A.mid_dominance*(g.mid||1)*I;case"amplitude":return A.average_amplitude*(g.amplitude||1)*I;case"chaos":{const E=A.bass_dominance,i=A.treble_dominance,C=A.mid_dominance;return(1-(Math.max(E,i,C)-Math.min(E,i,C)))*I}default:return 0}}static calculateProbabilities(A){const B=Object.keys(A),g=B.length;if(g===0)return{};const I=Object.values(A).reduce((t,s)=>t+s,0);if(I===0){const t=1/g,s={};for(const G of B)s[G]=t;return s}const E=this.BASELINE_PROBABILITY*g,i=1-E,C=E>=1?1/g:this.BASELINE_PROBABILITY,a=E>=1?0:i,e={};for(const t of B){const s=A[t]/I;e[t]=C+s*a}const o=Object.values(e).reduce((t,s)=>t+s,0);for(const t of B)e[t]/=o;return e}static applyCustomWeights(A,B,g){if(Object.keys(B).length===0)return A;const I=Object.values(B).reduce((a,e)=>a+Math.max(0,e),0);if(I===0)return A;const E={};for(const[a,e]of Object.entries(B))g.includes(a)&&(E[a]=Math.max(0,e)/I);const i=1-Object.values(E).reduce((a,e)=>a+e,0),C=Object.entries(A).filter(([a])=>!B[a]).reduce((a,[,e])=>a+e,0);for(const a of g)!B[a]&&A[a]&&(C>0?E[a]=A[a]/C*i:E[a]=i/g.length);return E}};SC.BASELINE_PROBABILITY=.04;let AQ=SC;class BQ{static getSpicedValue(A,B,g){let I;switch(A){case"bass":I=g.rms_energy??g.dynamic_range??B;break;case"mid":g.spectral_centroid!==void 0?I=Math.min(1,Math.max(0,(g.spectral_centroid-100)/9900)):I=g.dynamic_range??B;break;case"treble":g.zero_crossing_rate!==void 0?I=g.zero_crossing_rate:g.spectral_centroid!==void 0?I=Math.min(1,Math.max(0,(g.spectral_centroid-100)/9900)):I=B;break}return(B+I)/2}static createFrequencyMappings(A){const B=["STR","DEX","CON","INT","WIS","CHA"],g=new Map,I=A.shuffle(B),E=["bass","mid","treble"];for(let i=0;i<3;i++){const C=E[i],a=I[i*2],e=I[i*2+1],o=A.random()<.5;g.set(C,{abilities:[a,e],firstHasSpice:o})}return g}static calculateBaseScores(A,B){const{bass_dominance:g,mid_dominance:I,treble_dominance:E}=A,i=this.createFrequencyMappings(B),C={STR:8,DEX:8,CON:8,INT:8,WIS:8,CHA:8},a=3.5,e=3.5;for(const[o,t]of i){const[s,G]=t.abilities,n=t.firstHasSpice;let h;switch(o){case"bass":h=g;break;case"mid":h=I;break;case"treble":h=E;break}const c=n?this.getSpicedValue(o,h,A):h,d=n?h:this.getSpicedValue(o,h,A),l=B.random(),F=B.random();C[s]=Math.floor(8+l*e+c*a),C[G]=Math.floor(8+F*e+d*a)}return C}static applyRacialBonuses(A,B){const g=bI(B);if(!g)return console.warn(`Unknown race: "${B}", using no ability bonuses`),{...A};const I=g.ability_bonuses,E={...A};if(I)for(const[i,C]of Object.entries(I)){const a=i;E[a]=Math.min(20,(E[a]||0)+(C||0))}return E}static calculateModifiers(A){return{STR:Math.floor((A.STR-10)/2),DEX:Math.floor((A.DEX-10)/2),CON:Math.floor((A.CON-10)/2),INT:Math.floor((A.INT-10)/2),WIS:Math.floor((A.WIS-10)/2),CHA:Math.floor((A.CHA-10)/2)}}}class fo{static getSkillListDefinition(A){try{const g=AA.getInstance().get("skillLists");return Array.isArray(g)?g.find(I=>I.class===A):void 0}catch{return}}static assignSkills(A,B,g){const I=XA.getInstance(),E=I.getAllSkills(),i={};for(const s of E)i[s.id]="none";const C=RE(A);if(!C)return console.warn(`SkillAssigner: Unknown class "${A}", using default skill assignment`),i;const a=this.validateSkills(C.available_skills,I),e=g?this.filterSkillsByPrerequisites(a,I,g):a,o=this.getSkillListDefinition(A),t=this.selectSkills(e,C.skill_count,B,o?.selectionWeights);for(const s of t)i[s]="proficient";if(C.has_expertise&&C.expertise_count){const s=this.selectSkills(t,C.expertise_count,B);for(const G of s)i[G]="expertise"}return i}static validateSkills(A,B){const g=[];for(const I of A)B.isValidSkill(I)?g.push(I):console.warn(`SkillAssigner: Invalid skill ID "${I}" not found in SkillQuery. Skipping.`);return g}static filterSkillsByPrerequisites(A,B,g){const I=[];for(const E of A){const i=B.getSkill(E);i&&(i.prerequisites&&!EB.validateSkillPrerequisites(i.prerequisites,g).valid||I.push(E))}return I}static selectSkills(A,B,g,I){if(!I||I.mode==="default")return this.selectSkillsEqualWeight(A,B,g);const{weights:E,mode:i}=I,C=[];for(const o of A){const t=E[o];if(t!==0)if(i==="absolute"){if(t!==void 0){const s=Math.round(t*10);for(let G=0;G<s;G++)C.push(o)}}else{const G=Math.round((t??1)*10);for(let n=0;n<G;n++)C.push(o)}}if(C.length===0)return this.selectSkillsEqualWeight(A,B,g);for(let o=C.length-1;o>0;o--){const t=Math.floor(g.random()*(o+1));[C[o],C[t]]=[C[t],C[o]]}const a=[],e=new Set;for(const o of C)if(!e.has(o)&&(a.push(o),e.add(o),a.length>=B))break;return a}static selectSkillsEqualWeight(A,B,g){const I=[...A];for(let E=I.length-1;E>0;E--){const i=Math.floor(g.random()*(E+1));[I[E],I[i]]=[I[i],I[E]]}return I.slice(0,B)}}const ad=["Wizard","Sorcerer","Warlock","Bard","Cleric","Druid","Paladin"];class No{static generate(A,B,g){ei();const I=new QB(A),E=AA.getInstance(),i=E.get("appearance.bodyTypes"),C=E.getWeights("appearance.bodyTypes"),a=E.getMode("appearance.bodyTypes")||"default",e=E.get("appearance.skinTones"),o=E.getWeights("appearance.skinTones"),t=E.getMode("appearance.skinTones")||"default",s=E.get("appearance.hairStyles"),G=E.getWeights("appearance.hairStyles"),n=E.getMode("appearance.hairStyles")||"default",h=E.get("appearance.hairColors"),c=E.getWeights("appearance.hairColors"),d=E.getMode("appearance.hairColors")||"default",l=E.get("appearance.eyeColors"),F=E.getWeights("appearance.eyeColors"),m=E.getMode("appearance.eyeColors")||"default",y=E.get("appearance.facialFeatures"),p=E.getWeights("appearance.facialFeatures"),k=E.getMode("appearance.facialFeatures")||"default",H=_A.select(i,C,I,a),T=_A.select(e,o,I,t),q=_A.select(s,G,I,n),v=_A.select(h,c,I,d),EA=_A.select(l,F,I,m),aA=I.randomInt(1,4),GA=_A.selectMultiple(y,p,I,aA,k),rA=g.color_palette,P=rA?.primary_color,BA=rA?.secondary_color,wA=rA?.accent_color;let yA;return ad.includes(B)&&(yA=this.generateAuraColor(B,rA?.primary_color)),{body_type:H,skin_tone:T,hair_style:q,hair_color:v,eye_color:EA,facial_features:GA,primary_color:P,secondary_color:BA,accent_color:wA,aura_color:yA}}static generateAuraColor(A,B){return B?this.adjustColorBrightness(B,1.3):{Wizard:"#4169E1",Sorcerer:"#DC143C",Warlock:"#8B008B",Bard:"#FFD700",Cleric:"#F0E68C",Druid:"#228B22",Paladin:"#FFE4B5"}[A]||"#FFFFFF"}static adjustColorBrightness(A,B){const g=A.replace("#",""),I=parseInt(g.substring(0,2),16),E=parseInt(g.substring(2,4),16),i=parseInt(g.substring(4,6),16),C=Math.min(255,Math.floor(I*B)),a=Math.min(255,Math.floor(E*B)),e=Math.min(255,Math.floor(i*B)),o=t=>t.toString(16).padStart(2,"0");return`#${o(C)}${o(a)}${o(e)}`}}class Fi{static isSpellcaster(A){return["Bard","Cleric","Druid","Paladin","Ranger","Sorcerer","Warlock","Wizard"].includes(A)}static getSpellSlots(A,B){if(!this.isSpellcaster(A))return{};const g={};for(let E=0;E<=9;E++)g[E]={total:0,used:0};const I=SE(A,B);if(!I)return g;for(const[E,i]of Object.entries(I)){const C=parseInt(E,10);g[C]={total:i,used:0}}return g}static getCantrips(A){if(!this.isSpellcaster(A))return[];$I();const B=AA.getInstance(),g=uE(A),I=g?[...g.cantrips]:[],E=`spells.${A}`,i=B.get(E);for(const C of i){const a=C;if(a.cantrips&&a.cantrips.length>0)for(const e of a.cantrips)I.includes(e)||I.push(e)}return I}static getKnownSpells(A,B,g){if(!this.isSpellcaster(A))return[];$I();const I=AA.getInstance(),E=uE(A);if(!E||!E.spells_by_level)return[];[...E.cantrips];const i={};for(const[t,s]of Object.entries(E.spells_by_level))i[Number(t)]=[...s];const C=`spells.${A}`,a=I.get(C);for(const t of a){const s=t;if(s.cantrips&&s.cantrips.length>0)for(const G of s.cantrips);if(s.spells_by_level)for(const[G,n]of Object.entries(s.spells_by_level)){const h=Number(G);i[h]||(i[h]=[]);for(const c of n)i[h].includes(c)||i[h].push(c)}}const e={spells_by_level:i},o=[];for(let t=1;t<=B&&t<=9;t++){const s=e.spells_by_level[t];s&&s.length>0&&o.push(...s)}return g?this.filterSpellsByPrerequisites(o,g):o}static filterSpellsByPrerequisites(A,B){const g=[];for(const I of A){const E=wE[I];if(!E){g.push(I);continue}E.prerequisites&&!hB.validateSpellPrerequisites(E.prerequisites,B).valid||g.push(I)}return g}static initializeSpells(A,B,g){return{spell_slots:this.getSpellSlots(A,B),known_spells:this.getKnownSpells(A,B,g),cantrips:this.getCantrips(A)}}static getSpellCountAtLevel(A,B){return B[A]?.total||0}static useSpellSlot(A,B){if(B<1||B>9)throw new Error(`Invalid spell level: ${B}. Must be between 1 and 9.`);const g={...A},I=g[B];return I&&I.used<I.total&&(g[B]={...I,used:I.used+1}),g}static restoreSpellSlots(A,B){const g={...A};if(B!==void 0){const I=g[B];I&&(g[B]={...I,used:0})}else for(let I=1;I<=9;I++){const E=g[I];E&&(g[I]={...E,used:0})}return g}static filterCharacterSpells(A){if(!A.spells)return A;const B=this.filterSpellsByPrerequisites(A.spells.known_spells||[],A),g=this.filterSpellsByPrerequisites(A.spells.cantrips||[],A);return{...A,spells:{...A.spells,known_spells:B,cantrips:g}}}}const Mi={Barbarian:{weapons:["Greataxe","Handaxe"],armor:["No Armor"],items:["Explorer's Pack","Javelin"]},Bard:{weapons:["Rapier","Dagger","Dagger"],armor:["Leather Armor"],items:["Lute","Entertainer's Pack"]},Cleric:{weapons:["Mace","Light Crossbow"],armor:["Scale Mail","Shield"],items:["Holy Symbol","Priest's Pack","Healer's Kit"]},Druid:{weapons:["Quarterstaff","Dagger"],armor:["Leather Armor","Shield"],items:["Druidic Focus","Explorer's Pack"]},Fighter:{weapons:["Longsword"],armor:["Chain Mail","Shield"],items:["Martial Melee Weapon","Bedroll","Rope"]},Monk:{weapons:["Shortsword","Martial Arts"],armor:["No Armor"],items:["Insignia","Traveler's Pack","Dart"]},Paladin:{weapons:["Longsword"],armor:["Chain Mail","Shield"],items:["Holy Symbol","Priest's Pack"]},Ranger:{weapons:["Longsword","Shortsword","Longbow","Dagger"],armor:["Leather Armor"],items:["Explorer's Pack"]},Rogue:{weapons:["Rapier","Hand Crossbow","Dagger"],armor:["Leather Armor"],items:["Burglar's Pack","Thieves' Tools"]},Sorcerer:{weapons:["Light Crossbow","Dagger"],armor:["Leather Armor"],items:["Arcane Focus","Dungeoneer's Pack"]},Warlock:{weapons:["Light Crossbow","Dagger"],armor:["Leather Armor"],items:["Arcane Focus","Scholar's Pack"]},Wizard:{weapons:["Quarterstaff","Dagger"],armor:["No Armor"],items:["Spellbook","Component Pouch","Scholar's Pack","Ink & Quill"]}};function Jo(Q){if(Q in Mi)return Mi[Q];try{const A=AA.getInstance(),B=`classStartingEquipment.${Q}`,g=A.get(B);if(g&&Array.isArray(g)&&g.length>0){const I=g[0];return{weapons:I.weapons,armor:I.armor,items:I.items}}}catch{}}function wi(Q,A,B){Q.ability_scores[A]+=B;const g=Q.ability_scores[A];Q.ability_modifiers[A]=Math.floor((g-10)/2)}function yi(Q,A,B){const g=Q.skills[A];if(!g||g==="none"){Q.skills[A]=B;return}B==="expertise"&&(Q.skills[A]=B)}class HA{static equipItem(A,B,g){const I={applied:!1,count:0,errors:[]};if(A.equipment_effects||(A.equipment_effects=[]),this.findEquipmentEffect(A,B.name,g))return I.applied=!0,I;if(B.properties){const C=this.validateRequirements(A,B,B.properties);if(C.length>0)return I.errors.push(...C),I}const i={source:B.name,instanceId:g,effects:B.properties?[...B.properties]:[],features:[],skills:[],spells:[]};if(B.properties)for(const C of B.properties)try{this.applyProperty(A,C,B.name),I.count++}catch(a){const e=a instanceof Error?a.message:String(a);I.errors.push(`Failed to apply property from ${B.name}: ${e}`)}return B.grantsFeatures&&(this.applyEquipmentFeatures(A,B,g,i.features),I.count+=i.features.length),B.grantsSkills&&(this.applyEquipmentSkills(A,B,g,i.skills),I.count+=i.skills.length),B.grantsSpells&&(i.spells=B.grantsSpells.map(C=>({spellId:C.spellId,level:C.level,uses:C.uses,recharge:C.recharge})),this.addSpellsToCharacter(A,B.grantsSpells),I.count+=i.spells.length),A.equipment_effects.push(i),I.applied=I.errors.length===0,I}static unequipItem(A,B,g){const I={applied:!1,count:0,errors:[]};if(!A.equipment_effects)return I.errors.push("No equipment effects found on character"),I;const E=A.equipment_effects.findIndex(C=>C.source===B&&C.instanceId===g);if(E===-1)return I.errors.push(`Equipment "${B}" effects not found`),I;const i=A.equipment_effects[E];return i.effects.length>0&&(this.removeProperties(A,i.effects),I.count+=i.effects.length),i.features.length>0&&(this.removeEquipmentFeatures(A,B,g),I.count+=i.features.length),i.skills.length>0&&(this.removeEquipmentSkills(A,i.skills),I.count+=i.skills.length),i.spells&&i.spells.length>0&&(this.removeSpellsFromCharacter(A,i.spells),I.count+=i.spells.length),A.equipment_effects.splice(E,1),I.applied=I.count>0,I}static reapplyEquipmentEffects(A){const B={applied:!1,count:0,errors:[]};if(!A.equipment_effects||A.equipment_effects.length===0)return B;const g=[...A.equipment_effects];A.equipment_effects=[];for(const I of g){const E={source:I.source,instanceId:I.instanceId,effects:[...I.effects],features:[...I.features],skills:[...I.skills],spells:I.spells?[...I.spells]:[]};for(const i of I.effects)try{this.applyProperty(A,i,I.source),B.count++}catch(C){const a=C instanceof Error?C.message:String(C);B.errors.push(`Failed to reapply property from ${I.source}: ${a}`)}for(const i of I.features)this.addFeatureToCharacter(A,i),B.count++;for(const i of I.skills)this.addSkillToCharacter(A,i),B.count++;I.spells&&(this.addSpellsToCharacter(A,I.spells),B.count+=I.spells.length),A.equipment_effects.push(E)}return B.applied=B.count>0,B}static getActiveEffects(A){if(!A.equipment_effects)return[];const B=[];for(const g of A.equipment_effects)B.push(...g.effects);return B}static evaluateACFormula(A,B){const g=A.trim();if(/^\d+$/.test(g))return parseInt(g,10);const I=g.match(/^(\d+)\s*\+\s*min\(DEX,\s*(\d+)\)$/i);if(I){const i=parseInt(I[1],10),C=parseInt(I[2],10);return i+Math.min(B,C)}const E=g.match(/^(\d+)\s*\+\s*DEX$/i);if(E)return parseInt(E[1],10)+B;throw new Error(`Unknown AC formula: "${A}"`)}static applyProperty(A,B,g){if(!(B.condition&&!this.checkCondition(B.condition,A)))switch(B.type){case"stat_bonus":case"skill_proficiency":case"ability_unlock":case"passive_modifier":this.applyPropertyViaFeatureEffectApplier(A,B);break;case"special_property":this.trackSpecialProperty(A,B,g);break;case"damage_bonus":this.trackDamageBonus(A,B,g);break;case"stat_requirement":this.trackStatRequirement(A,B,g);break;default:throw new Error(`Unknown property type: ${B.type}`)}}static applyPropertyViaFeatureEffectApplier(A,B){switch(B.type){case"stat_bonus":this.applyStatBonus(A,B);break;case"skill_proficiency":this.applySkillProficiency(A,B);break;case"ability_unlock":this.applyAbilityUnlock(A,B);break;case"passive_modifier":this.applyPassiveModifier(A,B);break}}static applyStatBonus(A,B){const g=B.target,I=B.value;if(YB(g)){wi(A,g,I);return}}static applySkillProficiency(A,B){const g=B.target.toLowerCase(),I=B.value;yi(A,g,I)}static applyAbilityUnlock(A,B){}static applyPassiveModifier(A,B){const g=B.target,I=B.value;if(g==="speed"){A.speed+=I;return}if(g==="ac"||g==="armor_class"){if(typeof I=="string"){const E=A.ability_modifiers.DEX??0;A.armor_class=HA.evaluateACFormula(I,E)}else A.armor_class+=I;return}if(g==="max_hp"||g==="hp_max"){A.hp.max+=I,A.hp.current+=I;return}}static trackSpecialProperty(A,B,g){}static trackDamageBonus(A,B,g){}static removeProperties(A,B){for(let g=B.length-1;g>=0;g--){const I=B[g];switch(I.type){case"stat_bonus":this.removeStatBonus(A,I);break;case"skill_proficiency":this.removeSkillProficiency(A,I);break;case"passive_modifier":this.removePassiveModifier(A,I);break}}}static removeStatBonus(A,B){const g=B.target,I=B.value;YB(g)&&wi(A,g,-I)}static removeSkillProficiency(A,B){const g=B.target.toLowerCase();A.skills[g]="none"}static removePassiveModifier(A,B){const g=B.target,I=B.value;g==="speed"?A.speed-=I:g==="ac"||g==="armor_class"?typeof I=="string"?A.armor_class=10+(A.ability_modifiers.DEX??0):A.armor_class-=I:(g==="max_hp"||g==="hp_max")&&(A.hp.max-=I,A.hp.current=Math.min(A.hp.current,A.hp.max))}static applyEquipmentFeatures(A,B,g,I){if(B.grantsFeatures)for(const E of B.grantsFeatures)if(typeof E=="string"){const i=YA.getInstance(),C=i.getClassFeatureById(E),a=C?void 0:i.getRacialTraitById(E);if(C||a){const o={featureId:E,source:"equipment",equipmentName:B.name,instanceId:g,sourceType:B.source??"default"};I.push(o),this.addFeatureToCharacter(A,o)}}else{const i={featureId:E.id,source:"equipment",equipmentName:B.name,instanceId:g,sourceType:B.source??"default"};if(I.push(i),this.addFeatureToCharacter(A,i),E.effects)for(const C of E.effects)this.applyProperty(A,C,B.name)}}static applyEquipmentSkills(A,B,g,I){if(B.grantsSkills)for(const E of B.grantsSkills){const i={skillId:E.skillId,level:E.level,source:"equipment",equipmentName:B.name,instanceId:g,sourceType:B.source??"default"};I.push(i),this.addSkillToCharacter(A,i)}}static addSpellsToCharacter(A,B){A.spells||(A.spells={spell_slots:{},known_spells:[],cantrips:[]});for(const g of B)g.level===0?A.spells.cantrips.includes(g.spellId)||A.spells.cantrips.push(g.spellId):A.spells.known_spells.includes(g.spellId)||A.spells.known_spells.push(g.spellId)}static removeSpellsFromCharacter(A,B){if(A.spells)for(const g of B)if(g.level===0){const I=A.spells.cantrips.indexOf(g.spellId);I>-1&&A.spells.cantrips.splice(I,1)}else{const I=A.spells.known_spells.indexOf(g.spellId);I>-1&&A.spells.known_spells.splice(I,1)}}static addFeatureToCharacter(A,B){A.class_features.includes(B.featureId)||A.class_features.push(B.featureId)}static addSkillToCharacter(A,B){const g=B.skillId.toLowerCase();yi(A,g,B.level)}static removeEquipmentFeatures(A,B,g){if(!A.equipment_effects)return;const I=A.equipment_effects.filter(E=>E.source===B&&E.instanceId===g).flatMap(E=>E.features);for(const E of I){const i=A.class_features.indexOf(E.featureId);i>-1&&A.class_features.splice(i,1)}}static removeEquipmentSkills(A,B){for(const g of B){const I=g.skillId.toLowerCase();A.skills[I]="none"}}static checkCondition(A,B){switch(A.type){case"while_equipped":return!0;case"on_hit":case"on_damage_taken":return!1;case"wielder_race":return B.race===A.value;case"wielder_class":return B.class===A.value;case"at_time_of_day":return!0;case"vs_creature_type":return!1;case"custom":return!0;default:return!0}}static findEquipmentEffect(A,B,g){if(A.equipment_effects)return A.equipment_effects.find(I=>I.source===B&&I.instanceId===g)}static validateRequirements(A,B,g){const I=[];for(const E of g)if(E.type==="stat_requirement"){const i=E.target,C=E.value;if(YB(i)){const a=A.ability_scores[i];a<C&&I.push(`${B.name} requires ${i} ${C}, but character has ${i} ${a}`)}}return I}static trackStatRequirement(A,B,g){}}class Xg{static ensureInitialized(){si()}static getEquipmentDataStatic(A){return Xg.getEquipmentData(A)}static getEquipmentData(A){return AA.getInstance().get("equipment").find(I=>I.name===A)}static getStartingEquipment(A){this.ensureInitialized();const B=Jo(A);return B?{weapons:[...B.weapons],armor:[...B.armor],items:[...B.items]}:{weapons:[],armor:[],items:[]}}static initializeEquipment(A){this.ensureInitialized();const B=this.getStartingEquipment(A),g=[],I=[],E=[],i=[...B.weapons,...B.armor,...B.items];for(const a of i){const e=this.getEquipmentData(a);if(e){let o;e.type==="weapon"?o=g:e.type==="armor"?o=I:o=E;const t=o.find(s=>s.name===a);t?t.quantity+=1:o.push({name:a,quantity:1,equipped:!1})}else{console.warn(`EquipmentGenerator: Unknown item "${a}" in starting equipment.`);const o=E.find(t=>t.name===a);o?o.quantity+=1:E.push({name:a,quantity:1,equipped:!1})}}const C=this.getAmmunitionType(A,B.weapons);if(C){const a=this.getAmmunitionQuantity(A),e=E.find(o=>o.name===C);e?e.quantity+=a:E.push({name:C,quantity:a,equipped:!1})}return g.length>0&&(g[0].equipped=!0),I.length>0&&(I[0].equipped=!0),{weapons:g,armor:I,items:E,totalWeight:this.calculateTotalWeight(g,I,E),equippedWeight:this.calculateEquippedWeight(g,I,E)}}static addItem(A,B,g=1){this.ensureInitialized();const I=this.getEquipmentData(B);if(!I)return A;const E=this.cloneEquipment(A);let i;I.type==="weapon"?i=E.weapons:I.type==="armor"?i=E.armor:i=E.items;const C=i.find(a=>a.name===B);return C?g>0&&(C.quantity+=g):i.push({name:B,quantity:Math.max(0,g),equipped:!1}),E.totalWeight=this.calculateTotalWeight(E.weapons,E.armor,E.items),E.equippedWeight=this.calculateEquippedWeight(E.weapons,E.armor,E.items),E}static removeItem(A,B,g=1){if(this.ensureInitialized(),g<=0)return A;const I=this.cloneEquipment(A);let E;const i=this.getEquipmentData(B);if(!i)return A;i.type==="weapon"?E=I.weapons:i.type==="armor"?E=I.armor:E=I.items;const C=E.findIndex(a=>a.name===B);return C!==-1&&(E[C].quantity>g?E[C].quantity-=g:E.splice(C,1)),I.totalWeight=this.calculateTotalWeight(I.weapons,I.armor,I.items),I.equippedWeight=this.calculateEquippedWeight(I.weapons,I.armor,I.items),I}static equipItem(A,B,g){this.ensureInitialized();const I=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=I.weapons:E.type==="armor"?i=I.armor:i=I.items;const C=i.find(a=>a.name===B);if(C&&(C.equipped=!0,g)){const a=C.instanceId;HA.equipItem(g,E,a)}return I.equippedWeight=this.calculateEquippedWeight(I.weapons,I.armor,I.items),I}static unequipItem(A,B,g){this.ensureInitialized();const I=this.cloneEquipment(A),E=this.getEquipmentData(B);if(!E)return A;let i;E.type==="weapon"?i=I.weapons:E.type==="armor"?i=I.armor:i=I.items;const C=i.find(a=>a.name===B);if(C&&(C.equipped=!1,g)){const a=C.instanceId;HA.unequipItem(g,B,a)}return I.equippedWeight=this.calculateEquippedWeight(I.weapons,I.armor,I.items),I}static getInventoryList(A){return[...A.weapons,...A.armor,...A.items]}static getEquipmentByType(A,B){return A[B]}static calculateTotalWeight(A,B,g){let I=0;for(const E of A){const i=this.getEquipmentData(E.name);i&&(I+=i.weight*E.quantity)}for(const E of B){const i=this.getEquipmentData(E.name);i&&(I+=i.weight*E.quantity)}for(const E of g){const i=this.getEquipmentData(E.name);i&&(I+=i.weight*E.quantity)}return Math.round(I*100)/100}static calculateEquippedWeight(A,B,g){let I=0;for(const E of A)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(I+=i.weight)}for(const E of B)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(I+=i.weight)}for(const E of g)if(E.equipped){const i=this.getEquipmentData(E.name);i&&(I+=i.weight)}return Math.round(I*100)/100}static cloneEquipment(A){return{weapons:A.weapons.map(B=>({...B})),armor:A.armor.map(B=>({...B})),items:A.items.map(B=>({...B})),totalWeight:A.totalWeight,equippedWeight:A.equippedWeight}}static getAmmunitionType(A,B){const g=B.some(C=>C==="Longbow"),I=B.some(C=>C==="Shortbow"),E=B.some(C=>C==="Light Crossbow"),i=B.some(C=>C==="Hand Crossbow");return g||I?"Arrow":E||i?"Bolt":null}static getAmmunitionQuantity(A){return{Ranger:20,Fighter:20,Rogue:20}[A]||0}static addModification(A,B,g,I,E){this.ensureInitialized();const i=this.cloneEquipment(A),C=this.getEquipmentData(B);if(!C)return A;let a;C.type==="weapon"?a=i.weapons:C.type==="armor"?a=i.armor:a=i.items;const e=a.find(t=>t.name===B);if(!e)return A;e.modifications||(e.modifications=[]),!I&&!e.instanceId&&(e.instanceId=`${B}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`);const o=I||e.instanceId;return e.modifications.push(g),e.equipped&&E&&(HA.unequipItem(E,B,o),this.applyCombinedEffects(E,C,g,o)),i}static removeModification(A,B,g,I){this.ensureInitialized();const E=this.cloneEquipment(A),i=this.getEquipmentData(B);if(!i)return A;let C;i.type==="weapon"?C=E.weapons:i.type==="armor"?C=E.armor:C=E.items;const a=C.find(s=>s.name===B);if(!a||!a.modifications)return A;const e=a.equipped,o=a.instanceId,t=a.modifications.findIndex(s=>s.id===g);if(t!==-1&&a.modifications.splice(t,1),e&&I&&(HA.unequipItem(I,B,o),HA.equipItem(I,i,o),a.modifications))for(const s of a.modifications)this.applyCombinedEffects(I,i,s,o);return E}static getActiveEffects(A,B,g){this.ensureInitialized();const I=this.getEquipmentData(B);if(!I)return[];let E;I.type==="weapon"?E=A.weapons:I.type==="armor"?E=A.armor:E=A.items;const i=E.find(a=>a.name===B&&(!g||a.instanceId===g));if(!i)return[];const C=I.properties?[...I.properties]:[];if(i.modifications)for(const a of i.modifications)a.properties&&C.push(...a.properties);return C}static applyCombinedEffects(A,B,g,I){const E={...B,properties:[...B.properties||[],...g.properties],grantsFeatures:g.addsFeatures,grantsSkills:g.addsSkills,grantsSpells:g.addsSpells};HA.equipItem(A,E,I)}}class vg{static applyFeatureEffects(A,B){const g={applied:!1,count:0,errors:[]};if(!B.effects||B.effects.length===0)return g;for(const I of B.effects)try{this.applySingleEffect(A,I,B.id),g.applied=!0,g.count++}catch(E){const i=E instanceof Error?E.message:String(E);g.errors.push(`Failed to apply effect from ${B.id}: ${i}`)}return g}static applyMultipleEffects(A,B){const g={applied:!1,count:0,errors:[]};for(const I of B){const E=this.applyFeatureEffects(A,I);g.applied=g.applied||E.applied,g.count+=E.count,g.errors.push(...E.errors)}return g}static applySingleEffect(A,B,g){switch(B.type){case"stat_bonus":this.applyStatBonus(A,B);break;case"skill_proficiency":this.applySkillProficiency(A,B);break;case"ability_unlock":this.applyAbilityUnlock(A,B);break;case"passive_modifier":this.applyPassiveModifier(A,B);break;case"resource_grant":this.applyResourceGrant(A,B);break;case"spell_slot_bonus":this.applySpellSlotBonus(A,B);break;default:throw new Error(`Unknown effect type: ${B.type}`)}}static applyStatBonus(A,B){const g=B.target,I=B.value;if(YB(g)){wi(A,g,I);return}A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"stat_bonus",target:B.target,value:B.value,condition:B.condition})}static applySkillProficiency(A,B){const g=B.target.toLowerCase(),I=B.value;yi(A,g,I)}static applyAbilityUnlock(A,B){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"ability_unlock",target:B.target,value:B.value,condition:B.condition})}static applyPassiveModifier(A,B){const g=B.target,I=B.value;if(g==="speed"){A.speed+=I;return}if(g.endsWith("_max")){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"passive_modifier",target:B.target,value:B.value,condition:B.condition});return}A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"passive_modifier",target:B.target,value:B.value,condition:B.condition})}static applyResourceGrant(A,B){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"resource_grant",target:B.target,value:B.value,condition:B.condition})}static applySpellSlotBonus(A,B){A.feature_effects||(A.feature_effects=[]),A.feature_effects.push({type:"spell_slot_bonus",target:B.target,value:B.value,condition:B.condition})}}class gQ{static registerExtensions(A){const B=AA.getInstance();if(A.spells&&A.spells.length>0&&B.register("spells",A.spells),A.equipment&&A.equipment.length>0&&B.register("equipment",A.equipment),A.races&&A.races.length>0&&B.register("races",A.races),A.classes&&A.classes.length>0&&B.register("classes",A.classes),A.appearance){const{appearance:g}=A;g.bodyTypes&&g.bodyTypes.length>0&&B.register("appearance.bodyTypes",g.bodyTypes),g.skinTones&&g.skinTones.length>0&&B.register("appearance.skinTones",g.skinTones),g.hairColors&&g.hairColors.length>0&&B.register("appearance.hairColors",g.hairColors),g.hairStyles&&g.hairStyles.length>0&&B.register("appearance.hairStyles",g.hairStyles),g.eyeColors&&g.eyeColors.length>0&&B.register("appearance.eyeColors",g.eyeColors),g.facialFeatures&&g.facialFeatures.length>0&&B.register("appearance.facialFeatures",g.facialFeatures)}}static generate(A,B,g,I={}){const E=new QB(A),i=I.level||1,C=I.gameMode||"standard";Di();const a=YA.getInstance();I.extensions&&gQ.registerExtensions(I.extensions);let e;const o=I.subrace;let t;if(o==="pure")e=void 0,t=I.forceRace;else if(o!==void 0)if(I.forceRace)e=o,t=I.forceRace;else{const QA=a.getRaceForSubrace(o);if(!QA)throw new Error(`Cannot determine race for subrace "${o}". Either specify forceRace or ensure the subrace is registered in racial traits. Example: { forceRace: 'Elf', subrace: 'High Elf' }`);t=QA,e=o}const s=t||Ho.select(E);if(e!==void 0&&o!=="pure"){const QA=a.getAvailableSubraces(s);if(!QA.includes(e))throw new Error(`Invalid subrace "${e}" for race "${s}". Available subraces: ${QA.length>0?QA.join(", "):"none"}`)}else if(e===void 0&&o===void 0){const DA=["pure",...a.getAvailableSubraces(s)],Qg=E.randomChoice(DA);e=Qg==="pure"?void 0:Qg}const G=I.forceClass||AQ.suggest(B,E),n=I.forceName||new Ro().generateName(A,g,B,G,I.deterministicName||!0),h=BQ.calculateBaseScores(B,E),c=BQ.applyRacialBonuses(h,s),d=BQ.calculateModifiers(c),l=RE(G);if(!l)throw new Error(`Unknown class: ${G}. Cannot generate character.`);const m=bI(s)?.speed??30,y=l.hit_die+d.CON,p=10+d.DEX,k=d.DEX,H=mE[i],T=fo.assignSkills(G,E),q={STR:l.saving_throws.includes("STR"),DEX:l.saving_throws.includes("DEX"),CON:l.saving_throws.includes("CON"),INT:l.saving_throws.includes("INT"),WIS:l.saving_throws.includes("WIS"),CHA:l.saving_throws.includes("CHA")},v=No.generate(A,G,B),EA=a.getClassFeatures(G,i),aA=e?a.getRacialTraitsForSubrace(s,e):a.getBaseRacialTraits(s),GA=Xg.initializeEquipment(G),rA={name:n,race:s,subrace:e,class:G,level:i,ability_scores:c,ability_modifiers:d,proficiency_bonus:H,hp:{current:y,max:y,temp:0},armor_class:p,initiative:k,speed:m,skills:T,saving_throws:q,racial_traits:[],class_features:[],appearance:v,spells:{spell_slots:{},known_spells:[],cantrips:[]},equipment:GA,xp:{current:0,next_level:Jg[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:C},P=Fi.initializeSpells(G,i,rA),BA=[];for(const QA of EA){const DA=a.validatePrerequisites(QA,rA);DA.valid||console.warn(`Feature "${QA.name}" (${QA.id}) failed prerequisite validation:`,DA.errors),BA.push(QA)}const wA=[];for(const QA of aA){const DA=a.validatePrerequisites(QA,rA);DA.valid||console.warn(`Trait "${QA.name}" (${QA.id}) failed prerequisite validation:`,DA.errors),wA.push(QA)}const yA={name:n,race:s,subrace:e,class:G,level:i,ability_scores:c,ability_modifiers:d,proficiency_bonus:H,hp:{current:y,max:y,temp:0},armor_class:p,initiative:k,speed:m,skills:T,saving_throws:q,racial_traits:wA.map(QA=>QA.id),class_features:BA.map(QA=>QA.id),appearance:v,spells:P,equipment:GA,xp:{current:0,next_level:Jg[i+1]||0},seed:A,generated_at:new Date().toISOString(),gameMode:C};if(vg.applyMultipleEffects(yA,wA),vg.applyMultipleEffects(yA,BA),GA){const QA=[...GA.weapons.filter(DA=>DA.equipped),...GA.armor.filter(DA=>DA.equipped),...GA.items.filter(DA=>DA.equipped)];for(const DA of QA){const Qg=Xg.getEquipmentDataStatic(DA.name);if(Qg){const pC=DA.instanceId;HA.equipItem(yA,Qg,pC).applied||(DA.equipped=!1)}}}return Fi.filterCharacterSpells(yA)}}function Ri(Q){return 2595*Math.log10(1+Q/700)}function qo(Q){return 700*(Math.pow(10,Q/2595)-1)}function Kg(Q,A){const B=Q.sampleRate,g=B/A,I=Q.length,E=Math.ceil(I/g),i=new Float32Array(I);for(let a=0;a<Q.numberOfChannels;a++){const e=Q.getChannelData(a);for(let o=0;o<I;o++)i[o]+=e[o]/Q.numberOfChannels}const C=new Float32Array(E);for(let a=0;a<E;a++){const e=a*g,o=Math.floor(e),t=Math.min(o+1,I-1),s=e-o;C[a]=i[o]*(1-s)+i[t]*s}return{data:C,originalSampleRate:B,targetSampleRate:A}}function xo(Q,A,B,g=0,I=B/2){const E=A/2+1,i=[],C=Ri(g),a=Ri(I),e=[];for(let t=0;t<Q+2;t++)e.push(C+t*(a-C)/(Q+1));const o=e.map(t=>{const s=qo(t);return Math.floor((A+1)*s/B)});for(let t=0;t<Q;t++){const s=new Float32Array(E),G=o[t],n=o[t+1],h=o[t+2];for(let c=G;c<n;c++)n!==G&&(s[c]=(c-G)/(n-G));for(let c=n;c<h;c++)h!==n&&(s[c]=(h-c)/(h-n));i.push(s)}return i}function Vo(Q,A,B){if(Q.length===0)return new Float32Array(0);const g=1/(2*Math.PI*A),I=1/B,E=g/(g+I),i=new Float32Array(Q.length);i[0]=Q[0];for(let C=1;C<Q.length;C++)i[C]=E*(i[C-1]+Q[C]-Q[C-1]);return i}function mi(Q,A,B){if(Q.length===0)return new Float32Array(0);const g=Math.round(A/1e3*B);if(g<=1)return new Float32Array(Q);const I=g/6,E=g,i=new Float32Array(E),C=Math.floor(E/2);let a=0;for(let o=0;o<E;o++){const t=o-C;i[o]=Math.exp(-(t*t)/(2*I*I)),a+=i[o]}for(let o=0;o<E;o++)i[o]/=a;const e=new Float32Array(Q.length);for(let o=0;o<Q.length;o++){let t=0;for(let s=0;s<E;s++){const G=o+s-C,n=G<0?-G:G>=Q.length?2*Q.length-G-2:G,h=Math.max(0,Math.min(Q.length-1,n));t+=Q[h]*i[s]}e[o]=t}return e}function Lo(Q){if(Q.length===0)return 0;let A=0;for(let E=0;E<Q.length;E++)A+=Q[E];const B=A/Q.length;let g=0;for(let E=0;E<Q.length;E++){const i=Q[E]-B;g+=i*i}const I=g/Q.length;return Math.sqrt(I)}function Xo(Q){const A=Q.length,B=Math.pow(2,Math.ceil(Math.log2(A))),g=new Float32Array(B),I=new Float32Array(B);for(let a=0;a<A;a++){const e=.5-.5*Math.cos(2*Math.PI*a/(A-1));g[a]=Q[a]*e}let E=0;for(let a=0;a<B-1;a++){a<E&&([g[a],g[E]]=[g[E],g[a]],[I[a],I[E]]=[I[E],I[a]]);let e=B/2;for(;E>=e;)E-=e,e/=2;E+=e}let i=2;for(;i<=B;){const a=-2*Math.PI/i,e=Math.cos(a),o=Math.sin(a);for(let t=0;t<B;t+=i){let s=1,G=0;for(let n=0;n<i/2;n++){const h=t+n,c=t+n+i/2,d=g[c]*s-I[c]*G,l=g[c]*G+I[c]*s;g[c]=g[h]-d,I[c]=I[h]-l,g[h]+=d,I[h]+=l;const F=s*e-G*o;G=s*o+G*e,s=F}}i*=2}const C=new Float32Array(B/2+1);for(let a=0;a<C.length;a++){const e=g[a],o=I[a];C[a]=Math.sqrt(e*e+o*o)}return C}function ui(Q,A,B,g){const I=[];let E=0;for(;E+A<=Q.length;){const i=Q.slice(E,E+A),C=Xo(i);I.push(C),E+=B}return{frames:I,numFrames:I.length,fftSize:A,hopSize:B,sampleRate:g}}const vo=[{name:"low",lowHz:20,highHz:500,description:"Low frequencies (bass, kick, sub)"},{name:"mid",lowHz:500,highHz:2e3,description:"Mid frequencies (vocals, snare body, lead instruments)"},{name:"high",lowHz:2e3,highHz:2e4,description:"High frequencies (hi-hats, cymbals, harmonics, air)"}];function Ko(Q,A){const B=Math.PI*(2*Q-1)/(2*A);return 1/(2*Math.sin(B))}function ed(Q,A,B,g){const I=2*Math.PI*Q/A,E=Math.cos(I),i=Math.sin(I),C=Ko(B,g),a=i/(2*C),e=1+a,o=(1-E)/2/e,t=(1-E)/e,s=(1-E)/2/e,G=-2*E/e,n=(1-a)/e;return{b0:o,b1:t,b2:s,a1:G,a2:n}}function od(Q,A,B,g){const I=2*Math.PI*Q/A,E=Math.cos(I),i=Math.sin(I),C=Ko(B,g),a=i/(2*C),e=1+a,o=(1+E)/2/e,t=-(1+E)/e,s=(1+E)/2/e,G=-2*E/e,n=(1-a)/e;return{b0:o,b1:t,b2:s,a1:G,a2:n}}function zo(Q,A){const{b0:B,b1:g,b2:I,a1:E,a2:i}=A,C=new Float32Array(Q.length);C[0]=B*Q[0],Q.length>1&&(C[1]=B*Q[1]+g*Q[0]-E*C[0]);for(let a=2;a<Q.length;a++)C[a]=B*Q[a]+g*Q[a-1]+I*Q[a-2]-E*C[a-1]-i*C[a-2];return C}function td(Q,A,B,g,I){if(Q.length===0)return new Float32Array(0);const E=8;if(A>=B)throw new Error(`Low frequency (${A} Hz) must be less than high frequency (${B} Hz)`);if(B>=g/2)throw new Error(`High frequency (${B} Hz) must be less than Nyquist frequency (${g/2} Hz)`);const i=E/2;let C=new Float32Array(Q);for(let a=1;a<=i;a++){const e=od(A,g,a,E);C=zo(C,e)}for(let a=1;a<=i;a++){const e=ed(B,g,a,E);C=zo(C,e)}return C}function sd(Q,A,B,g){const I=vo.find(E=>E.name===A);if(!I)throw new Error(`Unknown frequency band: ${A}. Valid bands are: low, mid, high`);return td(Q,I.lowHz,I.highHz,B)}const Gd={targetSampleRate:44100,fftWindowSizeMs:23,hopSizeMs:10,smoothWindowMs:10,peakThreshold:.3,bands:vo};class To{constructor(A={}){if(this.config={...Gd,...A},this.config.peakThreshold<0||this.config.peakThreshold>1)throw new Error(`peakThreshold must be between 0 and 1, got: ${this.config.peakThreshold}`);if(this.config.bands.length===0)throw new Error("At least one frequency band must be specified")}getConfig(){return{...this.config}}analyze(A){const B=A.duration,g=this.config.targetSampleRate,I=Kg(A,g),E=Math.pow(2,Math.ceil(Math.log2(this.config.fftWindowSizeMs/1e3*g))),i=Math.round(this.config.hopSizeMs/1e3*g),C=this.config.hopSizeMs/1e3,a=1/C,e=new Map,o=[];for(const n of this.config.bands){const h=this.analyzeBand(I.data,n,g,E,i,C,a);e.set(n.name,h),o.push(h.energyOverTime)}const t=o[0]?.length??0,s=this.combineEnergyProfiles(o,t),G=this.calculateDominantBands(e);return{bands:e,dominantBands:G,energyProfile:s,metadata:{numFrames:t,duration:B,hopSizeSeconds:C,effectiveSampleRate:g,bandsAnalyzed:this.config.bands.map(n=>n.name)}}}analyzeBand(A,B,g,I,E,i,C){const a=sd(A,B.name,g),e=ui(a,I,E,g),o=e.numFrames,t=new Float32Array(o);for(let m=0;m<o;m++){const y=e.frames[m];let p=0;for(let k=0;k<y.length;k++)p+=y[k]*y[k];t[m]=Math.sqrt(p/y.length)}const s=Math.max(...t);if(s>0)for(let m=0;m<t.length;m++)t[m]/=s;const G=s,n=this.calculateOnsetEnvelope(e.frames),h=mi(n,this.config.smoothWindowMs,C),c=Math.max(...h),d=new Float32Array(h.length);if(c>0)for(let m=0;m<h.length;m++)d[m]=h[m]/c;const l=this.findPeaks(d,this.config.peakThreshold),F=l.map(m=>m*i);return{name:B.name,frequencyRange:{lowHz:B.lowHz,highHz:B.highHz},envelope:d,peaks:l,peakTimes:F,energy:G,energyOverTime:t}}calculateOnsetEnvelope(A){const B=A.length,g=new Float32Array(B);g[0]=0;for(let I=1;I<B;I++){const E=A[I],i=A[I-1];let C=0;for(let a=0;a<E.length;a++){const e=E[a]-i[a];e>0&&(C+=e)}g[I]=C}return g}findPeaks(A,B){const g=[];for(let I=1;I<A.length-1;I++)A[I]>A[I-1]&&A[I]>A[I+1]&&A[I]>=B&&g.push(I);return g}combineEnergyProfiles(A,B){const g=new Float32Array(B);for(let I=0;I<B;I++){let E=0;for(const i of A)I<i.length&&i[I]>E&&(E=i[I]);g[I]=E}return g}calculateDominantBands(A){const B=[];for(const[g,I]of A)B.push({name:g,energy:I.energy});return B.sort((g,I)=>I.energy-g.energy),B.map(g=>g.name)}}const Si={low:{threshold:.5,minInterval:.1,adaptiveThresholding:!1},mid:{threshold:.3,minInterval:.08,adaptiveThresholding:!1},high:{threshold:.25,minInterval:.06,adaptiveThresholding:!1}},nd={baseThreshold:.3,adaptiveThresholding:!1,adaptiveWindowSize:50,minTransientInterval:.02};class jo{constructor(A={}){const{bands:B,bandConfig:g,...I}=A,E={low:{...Si.low,...g?.low},mid:{...Si.mid,...g?.mid},high:{...Si.high,...g?.high}};if(this.config={...nd,...I,bandConfig:E},B!==void 0&&(this.config.bands=B),this.config.baseThreshold<0||this.config.baseThreshold>1)throw new Error(`baseThreshold must be between 0 and 1, got: ${this.config.baseThreshold}`);if(this.config.adaptiveWindowSize<1)throw new Error(`adaptiveWindowSize must be at least 1, got: ${this.config.adaptiveWindowSize}`);if(this.config.minTransientInterval<0)throw new Error(`minTransientInterval must be non-negative, got: ${this.config.minTransientInterval}`);for(const i of["low","mid","high"]){const C=this.config.bandConfig[i];if(C.threshold<0||C.threshold>1)throw new Error(`${i} band threshold must be between 0 and 1, got: ${C.threshold}`);if(C.minInterval<0)throw new Error(`${i} band minInterval must be non-negative, got: ${C.minInterval}`)}}getConfig(){const{bandConfig:A,...B}=this.config;return{...B,bandConfig:{low:{...A.low},mid:{...A.mid},high:{...A.high}}}}getBandConfig(){return{low:{...this.config.bandConfig.low},mid:{...this.config.bandConfig.mid},high:{...this.config.bandConfig.high}}}detect(A){const B=new Map,g=[],I=new Set;for(const[C,a]of A.bands){const e=this.detectBandTransients(C,a,A.metadata.hopSizeSeconds);B.set(C,e),g.push(...e),e.forEach(o=>I.add(o.detectionMethod))}g.sort((C,a)=>C.timestamp-a.timestamp);const E=new Map;for(const[C,a]of B)E.set(C,a.length);const i=g.length>0?g.reduce((C,a)=>C+a.intensity,0)/g.length:0;return{transients:g,bandTransients:B,metadata:{totalTransients:g.length,transientsPerBand:E,duration:A.metadata.duration,averageIntensity:i,detectionMethodsUsed:Array.from(I)}}}detectBandTransients(A,B,g){const I=this.config.bandConfig[A],E=this.getDetectionMethod(A),i=E==="energy"?B.energyOverTime:B.envelope;if(!i||i.length===0)return[];const C=I.adaptiveThresholding?this.calculateAdaptiveThreshold(i,I.threshold):I.threshold,e=this.findPeaks(i,C).map(t=>({timestamp:t*g,intensity:i[t],band:A,detectionMethod:E}));return this.applyNonMaximumSuppression(e,I.minInterval)}applyNonMaximumSuppression(A,B){if(A.length===0)return[];const g=[...A].sort((E,i)=>i.intensity-E.intensity),I=[];for(const E of g){let i=!1;for(const C of I)if(Math.abs(E.timestamp-C.timestamp)<B){i=!0;break}i||I.push(E)}return I.sort((E,i)=>E.timestamp-i.timestamp),I}getDetectionMethod(A){switch(A){case"low":return"energy";case"mid":return"spectral_flux";case"high":return"hfc";default:return"spectral_flux"}}calculateAdaptiveThreshold(A,B){const g=B??this.config.baseThreshold;if(A.length===0)return g;let I=0,E=0;for(let s=0;s<A.length;s++)I+=A[s],A[s]>E&&(E=A[s]);const i=I/A.length;let C=0;for(let s=0;s<A.length;s++){const G=A[s]-i;C+=G*G}const a=Math.sqrt(C/A.length),o=1+(i>0?a/i:0)*.5,t=g*o;return Math.max(.1,Math.min(.9,t))}findPeaks(A,B){const g=[];for(let I=1;I<A.length-1;I++)A[I]>A[I-1]&&A[I]>A[I+1]&&A[I]>=B&&g.push(I);return g}}const zg={densityValidation:{maxRetries:0,baseSensitivityReduction:.1,maxCumulativeReduction:.5},minimumTransientIntensity:0,bands:[]};class bi{constructor(A={}){this.config={densityValidation:{maxRetries:A.densityValidation?.maxRetries??zg.densityValidation.maxRetries,baseSensitivityReduction:A.densityValidation?.baseSensitivityReduction??zg.densityValidation.baseSensitivityReduction,maxCumulativeReduction:A.densityValidation?.maxCumulativeReduction??zg.densityValidation.maxCumulativeReduction},minimumTransientIntensity:A.minimumTransientIntensity??zg.minimumTransientIntensity,bands:A.bands??zg.bands}}getConfig(){return{...this.config}}quantize(A,B,g){const I=this.splitTransientsByBand(A.transients),E=B.quarterNoteInterval/6,i=this.processBand(I.low,"low",E),C=this.processBand(I.mid,"mid",E),a=this.processBand(I.high,"high",E),e={low:this.quantizeBand(i.filteredTransients,B,"low",g),mid:this.quantizeBand(C.filteredTransients,B,"mid",g),high:this.quantizeBand(a.filteredTransients,B,"high",g)},o=i.filteredCount+C.filteredCount+a.filteredCount,t=this.aggregateDensityResults([i.densityResult,C.densityResult,a.densityResult],E);return{streams:e,metadata:{densityValidation:t,transientsFilteredByIntensity:o,transientsFilteredByBand:{low:i.filteredCount,mid:C.filteredCount,high:a.filteredCount}}}}splitTransientsByBand(A){return{low:A.filter(B=>B.band==="low"),mid:A.filter(B=>B.band==="mid"),high:A.filter(B=>B.band==="high")}}processBand(A,B,g){const I=this.config.densityValidation.maxRetries,E=this.config.densityValidation.baseSensitivityReduction,i=this.config.densityValidation.maxCumulativeReduction;let C=0,a=A;if(this.config.minimumTransientIntensity>0){const G=a.length;a=a.filter(n=>n.intensity>=this.config.minimumTransientIntensity),C=G-a.length}let e=this.config.minimumTransientIntensity,o=0,t=0;for(;t<=I;){const G=this.validateBandDensity(a,B,g,t,o);if(G.isValid)return{filteredTransients:a,filteredCount:C,densityResult:G};if(t>=I)return console.warn(`[${B}] Density validation: Max retries (${I}) reached. Proceeding with ${a.length} transients. Min interval: ${(G.minIntervalDetected*1e3).toFixed(1)}ms (required: ${(g*1e3).toFixed(1)}ms)`),{filteredTransients:a,filteredCount:C,densityResult:G};t++;const n=Math.min(E,i-o);o+=n,e=Math.min(this.config.minimumTransientIntensity+o,1);const h=a.length;a=a.filter(d=>d.intensity>=e);const c=h-a.length;C+=c,console.warn(`[${B}] Density validation retry ${t}: Threshold increased to ${(e*100).toFixed(1)}%, Filtered ${c} transients, ${a.length} remaining`)}const s=this.validateBandDensity(a,B,g,t,o);return{filteredTransients:a,filteredCount:C,densityResult:s}}validateBandDensity(A,B,g,I,E,i=this.config.minimumTransientIntensity){const C=A.length,a=Math.min(this.config.minimumTransientIntensity+E,1);if(A.length===0)return{band:B,isValid:!0,minIntervalDetected:1/0,requiredMinInterval:g,retryCount:I,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:C};const e=[...A].sort((s,G)=>s.timestamp-G.timestamp);let o=1/0;for(let s=1;s<e.length;s++){const G=e[s].timestamp-e[s-1].timestamp;G<o&&(o=G)}const t=o>=g;return{band:B,isValid:t,minIntervalDetected:o,requiredMinInterval:g,retryCount:I,sensitivityReduction:E,finalIntensityThreshold:a,transientsRemaining:C}}aggregateDensityResults(A,B){let g=0,I=0,E=1/0,i=!0;for(const C of A)C.retryCount>g&&(g=C.retryCount),C.sensitivityReduction>I&&(I=C.sensitivityReduction),C.minIntervalDetected<E&&(E=C.minIntervalDetected),C.isValid||(i=!1);return{isValid:i,bands:{low:A.find(C=>C.band==="low"),mid:A.find(C=>C.band==="mid"),high:A.find(C=>C.band==="high")},maxRetryCount:g,maxSensitivityReduction:I}}decideGrids(A,B,g){const I=[],E=B.quarterNoteInterval,i=this.getBandGridType(g),C=[...A].sort((a,e)=>a.timestamp-e.timestamp);for(let a=0;a<B.beats.length;a++){const e=B.beats[a],o=e.timestamp,t=a<B.beats.length-1?B.beats[a+1].timestamp:e.timestamp+E,s=C.filter(G=>G.timestamp>=o&&G.timestamp<t);s.length!==0&&(i?I.push({beatIndex:a,selectedGrid:i,transientCount:s.length,confidence:1}):I.push(this.detectGrid(s,e,a,E)))}return I}quantizeToGrids(A,B,g,I){const E=[],i=B.quarterNoteInterval,C=[...A].sort((e,o)=>e.timestamp-o.timestamp),a=new Map;for(const e of I)a.set(e.beatIndex,e);for(let e=0;e<B.beats.length;e++){const o=B.beats[e],t=a.get(e);if(!t)continue;const s=o.timestamp,G=e<B.beats.length-1?B.beats[e+1].timestamp:o.timestamp+i,n=C.filter(h=>h.timestamp>=s&&h.timestamp<G);for(const h of n){const c=this.quantizeTransient(h,o,e,t.selectedGrid,i);c&&E.push(c)}}return E}quantizeBand(A,B,g,I){const E=I?I(A,B,g):this.decideGrids(A,B,g),i=this.quantizeToGrids(A,B,g,E),C=this.deduplicateBeats(i);return{audioId:B.audioId,duration:B.duration,beats:C,gridDecisions:E,quarterNoteInterval:B.quarterNoteInterval}}deduplicateBeats(A){const B=new Map;for(const g of A){const I=`${g.beatIndex}:${g.gridPosition}:${g.gridType}`,E=B.get(I);(!E||g.intensity>E.intensity)&&B.set(I,g)}return Array.from(B.values()).sort((g,I)=>g.timestamp-I.timestamp)}getBandGridType(A){switch(A){case"low":return"straight_8th";case"mid":case"high":return null}}detectGrid(A,B,g,I){const E=this.calculateStraightGrid(B.timestamp,I),i=this.calculateTripletGrid(B.timestamp,I);let C=0,a=0,e=0;for(const n of A){const h=this.calculateOffsetFromGrid(n,E),c=this.calculateOffsetFromGrid(n,i);C+=h,a+=c,e++}const o=e>0?C/e:0,t=e>0?a/e:0,s=o<=t?"straight_16th":"triplet_8th",G=Math.abs(o-t);return{beatIndex:g,selectedGrid:s,straightAvgOffset:o,tripletAvgOffset:t,transientCount:e,confidence:G}}calculateStraightGrid(A,B){const g=[],I=B/4;for(let E=0;E<4;E++)g.push(A+E*I);return g}calculateTripletGrid(A,B){const g=[],I=B/3;for(let E=0;E<3;E++)g.push(A+E*I);return g}calculate8thGrid(A,B){const g=[],I=B/2;for(let E=0;E<2;E++)g.push(A+E*I);return g}calculateOffsetFromGrid(A,B){let g=1/0;for(const I of B){const E=Math.abs(A.timestamp-I);E<g&&(g=E)}return g*1e3}quantizeTransient(A,B,g,I,E){let i,C;switch(I){case"straight_8th":i=1,C=E/2;break;case"straight_16th":i=3,C=E/4;break;case"triplet_8th":i=2,C=E/3;break}const a=Math.round((A.timestamp-B.timestamp)/C);if(a<0||a>i)return null;const e=B.timestamp+a*C,o=Math.abs(A.timestamp-e)*1e3;return{timestamp:e,detectedTimestamp:A.timestamp,beatIndex:g,gridPosition:a,gridType:I,intensity:A.intensity,band:A.band,quantizationError:o}}}class Oo{constructor(A={}){this.id="high-bpm-grid-restriction",this.description="Restricts 16th notes and triplets to 8th notes at high BPMs for playability",this.restrict16thBpm=A.restrict16thBpm??160,this.restrictTripletBpm=A.restrictTripletBpm??200}applies(A,B){return B.band==="low"?!1:A>=this.restrict16thBpm}apply(A,B){const{bpm:g}=B,I=g>=this.restrictTripletBpm;return A.map(E=>{const{selectedGrid:i}=E;return i==="straight_8th"?E:i==="straight_16th"&&g>=this.restrict16thBpm?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:i==="triplet_8th"&&I?{...E,selectedGrid:"straight_8th",confidence:1,straightAvgOffset:void 0,tripletAvgOffset:void 0}:E})}}const pi={rules:[new Oo],enabled:!0};class Po{constructor(A=pi,B){this.config=A,this.rhythmQuantizer=B??new bi}getConfig(){return{...this.config}}decideGrids(A,B,g){const I=this.rhythmQuantizer.decideGrids(A,B,g),E={bpm:B.quarterNoteBpm,quarterNoteInterval:B.quarterNoteInterval,band:g,transients:A};return this.applyRules(I,E)}applyRules(A,B){if(this.config.enabled===!1)return A;let g=A;for(const I of this.config.rules)I.applies(B.bpm,B)&&(g=I.apply(g,B));return g}}const hd={phraseSizes:[1,2,4,8],minOccurrences:3,topSignificantCount:10,includePhrasesWithoutVariation:!1,minNotesPerPhrase:Q=>1+Q};class _o{constructor(A={}){this.config={...hd,...A}}analyze(A){const B={low:this.analyzeBand(A.low,"low"),mid:this.analyzeBand(A.mid,"mid"),high:this.analyzeBand(A.high,"high")},g=[...B.low.phrases,...B.mid.phrases,...B.high.phrases],I=new Map;I.set("low",B.low.phrases),I.set("mid",B.mid.phrases),I.set("high",B.high.phrases);const E=new Map;for(const e of this.config.phraseSizes){const o=g.filter(t=>t.sizeInBeats===e);o.length>0&&E.set(e,o)}const C=[...g].sort((e,o)=>o.significance-e.significance).slice(0,this.config.topSignificantCount),a=g.filter(e=>e.hasVariation&&e.availableForReuse);return{phrases:g,phrasesByBand:I,mostSignificantPhrases:C,phrasesBySize:E,patternLibrary:a,bandAnalysis:B}}getMinNotes(A){return typeof this.config.minNotesPerPhrase=="function"?this.config.minNotesPerPhrase(A):typeof this.config.minNotesPerPhrase=="number"?this.config.minNotesPerPhrase:1+A}analyzeBand(A,B){const g=Math.max(...A.beats.map(a=>a.beatIndex),0),I=new Map;for(const a of this.config.phraseSizes)for(let e=0;e<=g-a+1;e++){const o=this.extractPhraseCandidate(A,e,a,B);if(o){const t=I.get(o.hash);t?t.push(o):I.set(o.hash,[o])}}const E=[];for(const[a,e]of I){if(e.length<this.config.minOccurrences)continue;const o=e[0];if(o.pattern.length<this.getMinNotes(o.sizeInBeats))continue;const t=this.hasPatternVariation(o.pattern,o.sizeInBeats);if(!t&&!this.config.includePhrasesWithoutVariation)continue;const s=e.map(h=>({beatIndex:h.startBeatIndex,startTimestamp:h.startTimestamp,endTimestamp:h.endTimestamp})),G=this.calculateSignificance(o.sizeInBeats,e.length),n=t&&e.length>=this.config.minOccurrences;E.push({id:a,pattern:o.pattern,sizeInBeats:o.sizeInBeats,sourceBand:B,occurrences:s,significance:G,hasVariation:t,availableForReuse:n})}E.sort((a,e)=>e.significance-a.significance);const i=new Map;for(const a of this.config.phraseSizes){const e=E.filter(o=>o.sizeInBeats===a);e.length>0&&i.set(a,e)}const C=E.filter(a=>a.hasVariation);return{band:B,phrases:E,phrasesBySize:i,phrasesWithVariation:C}}extractPhraseCandidate(A,B,g,I){const E=B+g-1,i=A.beats.filter(t=>t.beatIndex>=B&&t.beatIndex<=E);if(i.length===0)return null;const C=i.map(t=>({...t,beatIndex:t.beatIndex-B})),a=this.hashPattern(C,g),e=Math.min(...i.map(t=>t.timestamp)),o=Math.max(...i.map(t=>t.timestamp));return{hash:a,pattern:C,sizeInBeats:g,startBeatIndex:B,startTimestamp:e,endTimestamp:o}}hashPattern(A,B){const I=[...A].sort((E,i)=>E.beatIndex!==i.beatIndex?E.beatIndex-i.beatIndex:E.gridPosition-i.gridPosition).map(E=>`${E.beatIndex}:${E.gridPosition}:${E.gridType}`);return`phrase_${B}_${I.join("|")}`}hasPatternVariation(A,B){if(A.length===0)return!1;if(A.some(C=>C.gridType==="triplet_8th")||A.some(C=>C.gridPosition===1||C.gridPosition===3))return!0;const g=A.map(C=>C.intensity),I=Math.max(...g),E=Math.min(...g);if(I-E>.1)return!0;if(A.length===B&&A.every(a=>a.gridPosition===0))return!1;const i=new Set(A.map(C=>C.gridPosition));return!(i.size===2&&i.has(0)&&i.has(2)&&this.countBeatsWithNoteCount(A,2)===B)}countBeatsWithNoteCount(A,B){const g=new Map;for(const E of A){const i=g.get(E.beatIndex)??0;g.set(E.beatIndex,i+1)}let I=0;for(const E of g.values())E===B&&I++;return I}calculateSignificance(A,B){const g=A,I=Math.log2(B+1);return g*I}}const cd={beatsPerSection:8,sparseThreshold:1,denseThreshold:1.5};class $o{constructor(A={}){this.config={...cd,...A}}analyze(A,B,g){const I=B/60,E={low:this.analyzeBand(A.streams.low,"low",I,g),mid:this.analyzeBand(A.streams.mid,"mid",I,g),high:this.analyzeBand(A.streams.high,"high",I,g)};[...A.streams.low.beats,...A.streams.mid.beats,...A.streams.high.beats];const i=this.calculateCombinedPerBeatDensity(A.streams.low,A.streams.mid,A.streams.high),C=this.calculateCombinedMetrics(i,I,g),a=this.calculateSectionMetrics(i,I,g);return{bandMetrics:E,combinedMetrics:C,sections:a,perBeatDensity:i}}analyzeBand(A,B,g,I){const E=A.beats,C=(E.length>0?Math.max(...E.map(l=>l.beatIndex)):0)+1,a=new Map;for(const l of E){const F=a.get(l.beatIndex);F?(F.count++,F.intensities.push(l.intensity)):a.set(l.beatIndex,{count:1,intensities:[l.intensity]})}const e=[];let o=0;for(let l=0;l<C;l++){const F=a.get(l),m=F?.count??0,y=F?F.intensities.reduce((p,k)=>p+k,0)/F.intensities.length:0;e.push({beatIndex:l,transientCount:m,bands:m>0?[B]:[],averageIntensity:y}),o+=m}const t=e.map(l=>l.transientCount);let s;I&&I>0?s=o/I:s=C>0?o/C*g:0;const G=t.length>0?Math.min(...t)*g:0,n=t.length>0?Math.max(...t)*g:0,h=this.calculateVariance(t,s/g)*g*g,c=this.categorizeDensity(s),d=this.determineNaturalDifficulty(c);return{band:B,totalBeats:C,totalTransients:o,notesPerSecond:s,minNotesPerSecond:G,maxNotesPerSecond:n,variance:h,densityCategory:c,naturalDifficulty:d,perBeatDensity:e}}calculateCombinedPerBeatDensity(A,B,g){const I=[...A.beats,...B.beats,...g.beats],i=(I.length>0?Math.max(...I.map(e=>e.beatIndex)):0)+1,C=new Map;for(const e of A.beats)this.addToBeatData(C,e,"low");for(const e of B.beats)this.addToBeatData(C,e,"mid");for(const e of g.beats)this.addToBeatData(C,e,"high");const a=[];for(let e=0;e<i;e++){const o=C.get(e);if(o){const t=o.intensities.length>0?o.intensities.reduce((s,G)=>s+G,0)/o.intensities.length:0;a.push({beatIndex:e,transientCount:o.count,bands:Array.from(o.bands),averageIntensity:t})}else a.push({beatIndex:e,transientCount:0,bands:[],averageIntensity:0})}return a}addToBeatData(A,B,g){const I=A.get(B.beatIndex);if(I)I.count++,I.bands.add(g),I.intensities.push(B.intensity);else{const E=new Set;E.add(g),A.set(B.beatIndex,{count:1,bands:E,intensities:[B.intensity]})}}calculateCombinedMetrics(A,B,g){const I=A.reduce((a,e)=>a+e.transientCount,0);let E;if(g&&g>0)E=I/g;else{const a=A.length;E=a>0?I/a*B:0}const i=this.categorizeDensity(E),C=this.determineNaturalDifficulty(i);return{totalTransients:I,notesPerSecond:E,densityCategory:i,naturalDifficulty:C}}calculateSectionMetrics(A,B,g){const I=[],E=this.config.beatsPerSection,i=A.length;for(let C=0;C<i;C+=E){const a=Math.min(C+E-1,i-1),e=A.slice(C,a+1),o=e.reduce((l,F)=>l+F.transientCount,0),t=e.length,s=t>0?o/t*B:0,G=e.map(l=>l.transientCount),n=G.length>0?Math.min(...G)*B:0,h=G.length>0?Math.max(...G)*B:0,c=this.categorizeDensity(s),d=this.determineNaturalDifficulty(c);I.push({startBeat:C,endBeat:a,beatCount:t,totalTransients:o,notesPerSecond:s,minNotesPerSecond:n,maxNotesPerSecond:h,densityCategory:c,naturalDifficulty:d})}return I}categorizeDensity(A){return A<this.config.sparseThreshold?"sparse":A>this.config.denseThreshold?"dense":"moderate"}determineNaturalDifficulty(A){switch(A){case"sparse":return"easy";case"moderate":return"medium";case"dense":return"hard"}}calculateVariance(A,B){return A.length===0?0:A.map(I=>Math.pow(I-B,2)).reduce((I,E)=>I+E,0)/A.length}getConfig(){return{...this.config}}}const At={beatsPerSection:8,ioiVarianceWeight:.3,syncopationWeight:.3,phraseSignificanceWeight:.25,densityWeight:.15,offbeatGridPositions:{straight_16th:[1,3],triplet_8th:[1,2],straight_8th:[1]},bandBiasWeights:{low:.8,mid:.95,high:1}},rd={low:.8,mid:.95,high:1},ld={ddr:{ioiVarianceWeight:.2,syncopationWeight:.15,phraseSignificanceWeight:.35,densityWeight:.3},guitar_hero:{ioiVarianceWeight:.3,syncopationWeight:.3,phraseSignificanceWeight:.25,densityWeight:.15},tap:{ioiVarianceWeight:.3,syncopationWeight:.2,phraseSignificanceWeight:.3,densityWeight:.2}};function Dd(Q){const A=ld[Q];return{...At,...A,bandBiasWeights:{...rd}}}class Bt{constructor(A={}){this.config={...At,...A}}score(A,B,g){const I=[],E={low:[],mid:[],high:[]},i=[...A.streams.low.beats,...A.streams.mid.beats,...A.streams.high.beats],C=i.length>0?Math.max(...i.map(G=>G.beatIndex)):0,a=C+1,e=["low","mid","high"];for(let G=0;G<a;G+=this.config.beatsPerSection){const n=Math.min(G+this.config.beatsPerSection-1,C),h={start:G,end:n};for(const c of e){const d=this.scoreSection(A.streams[c],c,h,B,g);I.push(d),E[c].push(d.score)}}const o={low:E.low.reduce((G,n)=>G+n,0),mid:E.mid.reduce((G,n)=>G+n,0),high:E.high.reduce((G,n)=>G+n,0)},t={low:E.low.length>0?o.low/E.low.length:0,mid:E.mid.length>0?o.mid/E.mid.length:0,high:E.high.length>0?o.high/E.high.length:0},s=this.determineSectionWinners(I);return{sectionScores:I,bandTotals:o,bandAverages:t,sectionWinners:s,config:{...this.config}}}scoreSection(A,B,g,I,E){const i=A.beats.filter(s=>s.beatIndex>=g.start&&s.beatIndex<=g.end),C=this.calculateIOIVariance(i),a=this.calculateSyncopationLevel(i),e=this.calculatePhraseSignificance(I,B,g),o=this.calculateDensityFactor(E,B,g);let t=C*this.config.ioiVarianceWeight+a*this.config.syncopationWeight+e*this.config.phraseSignificanceWeight+o*this.config.densityWeight;if(this.config.bandBiasWeights){const s=this.config.bandBiasWeights[B]??1;t*=s}return{beatRange:g,band:B,score:t,factors:{ioiVariance:C,syncopationLevel:a,phraseSignificance:e,densityFactor:o}}}calculateIOIVariance(A){if(A.length<2)return 0;const B=[...A].sort((a,e)=>a.timestamp-e.timestamp),g=[];for(let a=1;a<B.length;a++)g.push(B[a].timestamp-B[a-1].timestamp);if(g.length===0)return 0;const I=g.reduce((a,e)=>a+e,0)/g.length,E=g.reduce((a,e)=>a+Math.pow(e-I,2),0)/g.length,i=Math.sqrt(E),C=I>0?i/I:0;return Math.min(C,1)}calculateSyncopationLevel(A){if(A.length===0)return 0;let B=0,g=0;for(const I of A){const i=this.config.offbeatGridPositions[I.gridType].includes(I.gridPosition),C=I.intensity;i&&(B+=C),g+=C}return g===0?0:B/g}calculatePhraseSignificance(A,B,g){const I=A.phrasesByBand.get(B)??[];if(I.length===0)return 0;let E=0,i=0;for(const a of I){i=Math.max(i,a.significance);for(const e of a.occurrences){const o=e.beatIndex+a.sizeInBeats-1;if(e.beatIndex<=g.end&&o>=g.start){const t=Math.max(e.beatIndex,g.start),n=(Math.min(o,g.end)-t+1)/a.sizeInBeats;E+=a.significance*n;break}}}if(i===0)return 0;const C=E/i;return Math.min(C,1)}calculateDensityFactor(A,B,g){const i=A.bandMetrics[B].perBeatDensity.filter(G=>G.beatIndex>=g.start&&G.beatIndex<=g.end);if(i.length===0)return 0;const C=i.reduce((G,n)=>G+n.transientCount,0)/i.length,a=this.config.bpm!=null?this.config.bpm/60:1,e=C*a;return Math.exp(-Math.pow(e-1,2)/(2*Math.pow(.75,2)))}determineSectionWinners(A){const B=new Map;for(const I of A){const E=`${I.beatRange.start}-${I.beatRange.end}`,i=B.get(E);i?i.push(I):B.set(E,[I])}const g=[];for(const[,I]of B){if(I.length===0)continue;const E=[...I].sort((e,o)=>o.score-e.score),i=E[0],C=E[1],a=C?i.score-C.score:i.score;g.push({beatRange:i.beatRange,winner:i.band,score:i.score,margin:a})}return g.sort((I,E)=>I.beatRange.start-E.beatRange.start),g}getConfig(){return{...this.config}}updateConfig(A){this.config={...this.config,...A}}}const dd={transitionOverlapBeats:0,preserveGridDecisions:!0},Fd=1,Md=1.5;class gt{constructor(A={}){this.config={...dd,...A}}generate(A,B,g,I){const E=B.sectionWinners,i={low:0,mid:0,high:0},C={low:0,mid:0,high:0},e=E.filter(d=>{const l=["low","mid","high"];let F=!1;for(const m of l)if(A.streams[m].beats.filter(k=>k.beatIndex>=d.beatRange.start&&k.beatIndex<=d.beatRange.end).length>0){F=!0;break}return F}).map(d=>({beatRange:d.beatRange,sourceBand:d.winner,score:d.score,margin:d.margin}));for(const d of e)C[d.sourceBand]++;const o=[];for(const d of e){const l=A.streams[d.sourceBand],F=this.extractSectionBeats(l,d.beatRange,d.sourceBand);o.push(...F),i[d.sourceBand]+=F.length}o.sort((d,l)=>d.timestamp-l.timestamp);const t=this.deduplicateBeats(o),s=A.streams.low.quarterNoteInterval,G=60/s,n=this.determineNaturalDifficulty(t,g,G,I),h=e.length,c={totalBeats:t.length,sectionCount:h,beatsPerBand:i,sectionsPerBand:{low:h>0?C.low/h:0,mid:h>0?C.mid/h:0,high:h>0?C.high/h:0}};return{beats:t,sections:e,naturalDifficulty:n,quarterNoteInterval:s,metadata:c}}extractSectionBeats(A,B,g){return A.beats.filter(I=>I.beatIndex>=B.start&&I.beatIndex<=B.end).map(I=>({...I,sourceBand:g}))}deduplicateBeats(A){const B=new Map;for(const g of A){const I=Math.round(g.timestamp*1e3),E=B.get(I);(!E||g.intensity>E.intensity)&&B.set(I,g)}return Array.from(B.values()).sort((g,I)=>g.timestamp-I.timestamp)}determineNaturalDifficulty(A,B,g,I){if(A.length===0)return"easy";let E;if(I&&I>0)E=A.length/I;else{const C=Math.max(...A.map(a=>a.beatIndex))+1;E=A.length/C*(g/60)}return E<Fd?"easy":E>Md?"hard":"medium"}getConfig(){return{...this.config}}}const IQ={strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},wd={ddr:{strongBeatEmphasis:"natural",downbeatProximityRange:1,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},guitar_hero:{strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},tap:{strongBeatEmphasis:"natural",downbeatProximityRange:1.5,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5}};function yd(Q){return{...wd[Q]}}function It(Q){return Q%3===0?3:2}function Qt(Q,A){return Q%A===0}function Et(Q,A){return Q%A!==0}function it(Q,A){let B=Q[0];for(const g of Q)if(g.startBeat<=A)B=g;else break;return B}function Ct(Q,A,B){if(B==="neutral")return!1;const g=It(A);return B==="natural"?Qt(Q,g):Et(Q,g)}class at{constructor(A={}){this.config={...IQ,...A}}getConfig(){return{...this.config}}balance(A,B){const g={shiftedToDownbeat:0,emptyMeasuresFilled:0,proximityShifts:0,beatsAdded:0,beatsShifted:0,marginRemovals:0};let I=[...A.beats];return I=this.shiftLoneSubdivisionNotes(I,B,g),I=this.fillEmptyMeasures(I,B,g),I=this.enforceDownbeatProximity(I,B,g),I=this.removeMarginNotes(I,B.duration,g),I.sort((E,i)=>E.timestamp-i.timestamp),{composite:{...A,beats:I,metadata:{...A.metadata,totalBeats:I.length}},stats:g}}shiftLoneSubdivisionNotes(A,B,g){if(!B.downbeatConfig?.segments)return A;const I=new Map;for(const i of A){const C=B.beats[i.beatIndex];if(C){const a=C.measureNumber;I.has(a)||I.set(a,[]),I.get(a).push(i)}}const E=[];for(const i of A){const C=B.beats[i.beatIndex];if(!C){E.push(i);continue}const a=C.measureNumber;if((I.get(a)||[]).length===1&&i.gridPosition!==0){const o={...i,gridPosition:0,timestamp:B.beats[i.beatIndex].timestamp,balancerAction:"shifted_to_downbeat"};E.push(o),g.shiftedToDownbeat++,g.beatsShifted++}else E.push(i)}return E}fillEmptyMeasures(A,B,g){if(!this.config.fillEmptyMeasures||!B.downbeatConfig?.segments)return A;let I=1/0,E=-1/0;for(const e of B.beats)I=Math.min(I,e.measureNumber),E=Math.max(E,e.measureNumber);if(I===1/0)return A;const i=new Map;for(const e of A){const o=B.beats[e.beatIndex];if(o){const t=o.measureNumber;i.has(t)||i.set(t,[]),i.get(t).push(e)}}const C=new Map;for(const e of A)C.set(e.beatIndex,e.gridType);const a=[];for(let e=I;e<=E;e++)if((i.get(e)||[]).length===0){const t=B.beats.findIndex(s=>s.measureNumber===e&&s.isDownbeat);if(t>=0){let s="straight_8th";for(let h=1;h<=8;h++){const c=t-h,d=t+h;if(C.has(c)){s=C.get(c);break}if(C.has(d)){s=C.get(d);break}}const n={timestamp:B.beats[t].timestamp,beatIndex:t,gridPosition:0,gridType:s,intensity:this.config.addedBeatIntensity,band:"mid",sourceBand:"mid",balancerAction:"empty_measure_fill"};a.push(n),g.emptyMeasuresFilled++,g.beatsAdded++}}return[...A,...a]}enforceDownbeatProximity(A,B,g){const I=this.config.downbeatProximityRange;if(I<0)return A;const E=new Set;for(const C of A)C.gridPosition===0&&E.add(C.beatIndex);const i=[];for(const C of A){if(C.gridPosition===0){i.push(C);continue}let a=!1;const e=Math.ceil(I);for(let o=0;o<=e&&!(o>I);o++)if(o===0){if(E.has(C.beatIndex)){a=!0;break}}else if(E.has(C.beatIndex-o)||E.has(C.beatIndex+o)){a=!0;break}if(a)i.push(C);else{const o={...C,gridPosition:0,timestamp:B.beats[C.beatIndex]?.timestamp??C.timestamp,balancerAction:"proximity_shift"};i.push(o),E.add(C.beatIndex),g.proximityShifts++,g.beatsShifted++}}return i}removeMarginNotes(A,B,g){const I=this.config.marginSeconds;if(I<=0||B<=0)return A;const E=B-I;return A.filter(i=>i.timestamp<I||i.timestamp>E?(g.marginRemovals++,!1):!0)}}const Rd=["straight_16th","triplet_8th","straight_8th","quarter_triplet","straight_4th"],Yi={straight_16th:4,straight_8th:2,triplet_8th:3,straight_4th:1,quarter_triplet:1},iB={easy:{maxSubdivision:"eighth",allowedGridTypes:["straight_4th","quarter_triplet"],description:"Quarter notes and quarter note triplets only",targetDensityRange:{min:0,max:1}},medium:{maxSubdivision:"eighth",allowedGridTypes:["straight_8th","quarter_triplet"],description:"8th notes and quarter note triplets only, with density reduction for moderate difficulty",targetDensityRange:{min:1,max:1.5}},hard:{maxSubdivision:"sixteenth",allowedGridTypes:["straight_16th","triplet_8th","straight_8th","quarter_triplet"],description:"All subdivision types including 16th notes",targetDensityRange:{min:1.5,max:1/0}},natural:{maxSubdivision:"sixteenth",allowedGridTypes:["straight_16th","triplet_8th","straight_8th","quarter_triplet"],description:"Unedited composite stream - no subdivision restrictions",targetDensityRange:{min:0,max:1/0}},custom:{maxSubdivision:"sixteenth",allowedGridTypes:["straight_16th","triplet_8th","straight_8th","quarter_triplet"],description:"Custom density-based variant — parameters provided at generation time",targetDensityRange:{min:0,max:1/0}}},et=70,ot=70,tt=120;function FB(Q,A){if(Q==="natural")return[...iB.natural.allowedGridTypes];if(Q==="easy")return["straight_4th","quarter_triplet"];if(Q==="medium")return["straight_8th","quarter_triplet"];if(Q==="hard")return A>=ot?["straight_8th","quarter_triplet"]:[...iB.hard.allowedGridTypes];if(Q==="custom")return[...iB.custom.allowedGridTypes];const B=Q;throw new Error(`Unhandled difficulty: ${B}`)}const md={straight_4th:["straight_4th"],straight_8th:["straight_8th","quarter_triplet"],quarter_triplet:["quarter_triplet","straight_8th"],triplet_8th:["triplet_8th","straight_8th","quarter_triplet"],straight_16th:["straight_16th","triplet_8th","straight_8th","quarter_triplet"]};function st(Q,A){const B=md[Q.maxGridType]??[Q.maxGridType];if(!Q.bpmBasedQuantization)return[...B];const g=Q.restrictBpm??et,I=Q.quarterNoteBpm??tt;let E=[...B];return A>=g&&(E=E.filter(i=>i!=="straight_16th"&&i!=="triplet_8th")),A>I&&(E=E.filter(i=>i!=="straight_8th")),E}function Gt(Q,A){if(Q.length===0||A<=0)return 0;const B=60/A;return Math.max(...Q.map(I=>Yi[I]))/B}const ud={logConversions:!1,preservePhraseBoundaries:!0,simplificationIntensityThreshold:.3,heavySimplificationIntensityThreshold:.5,moderateSimplificationIntensityThreshold:.4,densityReductionMinIntensity:.25,interpolatedBeatIntensity:.5,preferPatternInsertion:!0,maxPatternInsertionSize:4,densityTargetStrategy:"midpoint",maxReductionPasses:3,seed:void 0,rhythmicBalanceConfig:void 0};function Sd(Q,A,B){return B!==void 0?FB(A,B).includes(Q):iB[A].allowedGridTypes.includes(Q)}function bd(Q,A){return A!==void 0?FB(Q,A):[...iB[Q].allowedGridTypes]}function QQ(Q,A,B,g){const I=g??(B!==void 0?FB(A,B):iB[A].allowedGridTypes);if(I.includes(Q))return Q;switch(Q){case"straight_16th":return I.includes("straight_4th")&&!I.includes("straight_8th")?"straight_4th":"straight_8th";case"triplet_8th":return"quarter_triplet";case"straight_8th":return"straight_4th";default:return Q}}function pd(Q){return Q}function nt(Q,A,B){const g=[],I=B!==void 0?FB(A,B):iB[A].allowedGridTypes;for(const E of Q)I.includes(E.gridType)||g.push({beat:E,gridType:E.gridType,suggestedConversion:QQ(E.gridType,A,B)});return{isValid:g.length===0,violations:g,totalBeats:Q.length,violationCount:g.length}}class EQ{constructor(A={}){this.currentUnifiedBeatMap=null,this.config={...ud,...A}}lockGridPerBeatIndex(A,B,g,I,E){const i=this.enforceSingleGridPerBeat(A),C=new Map;if(i.length===0)return{beats:[],gridLock:C};const a=Math.max(...i.map(t=>t.beatIndex)),e=new Map;for(const t of i){const s=e.get(t.beatIndex)??[];s.push(t),e.set(t.beatIndex,s)}for(const[t,s]of e)C.set(t,s[0].gridType);const o=E??FB(B,g);for(let t=0;t<=a;t++){if(C.has(t))continue;if(I?.has(t)){const n=I.get(t);C.set(t,n.selectedGrid);continue}let s=!1;for(const n of[1,-1,2,-2,3,-3]){const h=t+n;if(C.has(h)){C.set(t,C.get(h)),s=!0;break}}if(s)continue;const G=o[0]??"straight_8th";C.set(t,G)}return{beats:i,gridLock:C}}generate(A,B,g,I){this.currentUnifiedBeatMap=B;const E=A.naturalDifficulty,i=this.generateVariant(A,"easy",E,B,g,I),C=this.generateVariant(A,"medium",E,B,g,I),a=this.generateVariant(A,"hard",E,B,g,I);this.validateGridLockResult(i.beats,"easy"),this.validateGridLockResult(C.beats,"medium"),this.validateGridLockResult(a.beats,"hard");const e={difficulty:"natural",beats:this.enforceSingleGridPerBeat([...A.beats]),isUnedited:!0,editType:"none",editAmount:0};this.validateVariant(i,"easy"),this.validateVariant(C,"medium"),this.validateVariant(a,"hard");const o=B?.duration??120;if(i.densityValidation=this.validateDensityInRange(i,o),C.densityValidation=this.validateDensityInRange(C,o),a.densityValidation=this.validateDensityInRange(a,o),this.config.logConversions){const t=s=>{const G=s.densityValidation,n=G.targetRange.max===1/0?"∞":G.targetRange.max.toFixed(1),h=G.inRange?"✓":"✗";return`${s.difficulty}: ${G.density.toFixed(2)} nps (target [${G.targetRange.min}, ${n}]) ${h}`};console.log(`[DifficultyVariantGenerator] Density validation summary:
|
|
50
50
|
${t(i)}
|
|
51
51
|
${t(C)}
|
|
52
52
|
${t(a)}`)}return{easy:i,medium:C,hard:a,natural:e}}generateAtDensity(A,B,g,I,E){this.currentUnifiedBeatMap=g;const i=g?.quarterNoteBpm??120,C=g?.duration??120;this.calculateDensity(A.beats,C);const a=st(B,i),e=Gt(a,i);let o=B.targetDensity,t=!1;B.targetDensity>e&&(o=e,t=!0,console.warn(`[DifficultyVariantGenerator] Target density ${B.targetDensity.toFixed(2)} nps exceeds max achievable ${e.toFixed(2)} nps for grid types [${a.join(", ")}] at ${i} BPM. Clamping to ${o.toFixed(2)} nps.`));const{beats:s,gridLock:G}=this.lockGridPerBeatIndex(A.beats,"custom",i,E,a),n=this.calculateDensity(s,C),h=1e-10,c=Math.max(o,1e-10),d=s.some(l=>!a.includes(l.gridType));if(this.config.logConversions&&console.log(`[DifficultyVariantGenerator] generateAtDensity: current=${n.toFixed(2)} nps, target=${c.toFixed(2)} nps, maxGridType=${B.maxGridType}, allowedTypes=[${a.join(", ")}], clamped=${t}`),n>c*(1+h)){const l=this.simplifyBeats(s,"custom",A.quarterNoteInterval,!1,I,i,G,C,a,o);return{difficulty:"custom",beats:this.enforceSingleGridPerBeat(l.beats),isUnedited:!1,editType:"simplified",editAmount:l.metadata.totalBeatsBefore>0?(l.metadata.totalBeatsBefore-l.metadata.totalBeatsAfter)/l.metadata.totalBeatsBefore:0,conversionMetadata:l.metadata,densityClamped:t}}else if(n<o*(1-h)){const l=this.enhanceBeats(s,"custom",i,g,I,E,A.quarterNoteInterval,G,a,o),F=this.enforceSingleGridPerBeat(l.beats),m=l.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:"custom",beats:F,isUnedited:!1,editType:m,editAmount:l.metadata.totalBeatsBefore>0?(l.metadata.totalBeatsAfter-l.metadata.totalBeatsBefore)/l.metadata.totalBeatsBefore:0,patternsInserted:l.metadata.insertedPatternIds.length>0?l.metadata.insertedPatternIds:void 0,enhancementMetadata:l.metadata}}else{if(d){this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Density approximately equal (${n.toFixed(2)} ≈ ${o.toFixed(2)}), but grid restrictions needed`);const F=this.simplifyBeats(s,"custom",A.quarterNoteInterval,!1,I,i,G,C,a,o);return{difficulty:"custom",beats:this.enforceSingleGridPerBeat(F.beats),isUnedited:F.metadata.beatsRemoved===0&&!t,editType:F.metadata.beatsRemoved>0?"simplified":"none",editAmount:F.metadata.totalBeatsBefore>0?(F.metadata.totalBeatsBefore-F.metadata.totalBeatsAfter)/F.metadata.totalBeatsBefore:0,conversionMetadata:F.metadata,densityClamped:t}}return{difficulty:"custom",beats:this.enforceSingleGridPerBeat(s),isUnedited:!t,editType:"none",editAmount:0}}}generateAtDensities(A,B,g,I,E){const i=new Map;for(const{label:C,config:a}of B){const e={...A,beats:A.beats.map(t=>({...t}))},o=this.generateAtDensity(e,a,g,I,E);i.set(C,o)}return i}validateVariant(A,B){const g=nt(A.beats,B);if(g.isValid)this.config.logConversions&&console.log(`[DifficultyVariantGenerator] ${B} variant validated: ${g.totalBeats} beats, no subdivision violations`);else if(console.warn(`[DifficultyVariantGenerator] ${B} variant has ${g.violationCount} subdivision violations out of ${g.totalBeats} beats. This indicates a bug in the variant generation logic.`),this.config.logConversions){for(const I of g.violations.slice(0,5))console.warn(` - Beat at index ${I.beat.beatIndex}, position ${I.beat.gridPosition}, grid: ${I.gridType} (suggested: ${I.suggestedConversion})`);g.violations.length>5&&console.warn(` ... and ${g.violations.length-5} more violations`)}}validateGridLockResult(A,B){const g=this.validateSingleGridPerBeat(A);if(!g.isValid&&(console.warn(`[DifficultyVariantGenerator] ${B} variant has ${g.violations.length} grid lock violations (mixed grid types at same beat index). This indicates a bug in the grid lock implementation.`),this.config.logConversions)){for(const I of g.violations.slice(0,5))console.warn(` - Beat index ${I.beatIndex} has mixed grids: ${I.gridTypes.join(", ")}`);g.violations.length>5&&console.warn(` ... and ${g.violations.length-5} more violations`)}}validateDensityInRange(A,B){const g=this.calculateDensity(A.beats,B),I=iB[A.difficulty].targetDensityRange,E=g>=I.min&&(I.max===1/0||g<=I.max);if(E){if(this.config.logConversions){const i=I.max===1/0?"∞":I.max.toFixed(2);console.log(`[DifficultyVariantGenerator] ${A.difficulty} variant density ${g.toFixed(2)} nps is within target range [${I.min.toFixed(2)}, ${i}] ✓`)}}else{const i=I.max===1/0?"∞":I.max.toFixed(2);console.warn(`[DifficultyVariantGenerator] ${A.difficulty} variant density ${g.toFixed(2)} nps is OUTSIDE target range [${I.min.toFixed(2)}, ${i}]. This may occur for edge cases (short songs, extreme tempos).`)}return{inRange:E,density:g,targetRange:I,difficulty:A.difficulty}}generateVariant(A,B,g,I,E,i){const C=B===g,a=I?.quarterNoteBpm??120,e=I?.duration??120,o=FB(B,a),{beats:t,gridLock:s}=this.lockGridPerBeatIndex(A.beats,B,a,i);if(C){if(t.every(d=>o.includes(d.gridType))){const{targetCount:d}=this.calculateBeatCountTarget(t.length,e,B);if(t.length<d){const l=this.enhanceBeats(t,B,a,I,E,i,A.quarterNoteInterval,s),F=l.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:B,beats:l.beats,isUnedited:!1,editType:F,editAmount:l.metadata.totalBeatsBefore>0?(l.metadata.totalBeatsAfter-l.metadata.totalBeatsBefore)/l.metadata.totalBeatsBefore:0,enhancementMetadata:l.metadata}}return{difficulty:B,beats:[...t],isUnedited:!0,editType:"none",editAmount:0}}const c=this.simplifyBeats(t,B,A.quarterNoteInterval,!1,E,a,s,e);return{difficulty:B,beats:c.beats,isUnedited:!1,editType:"simplified",editAmount:c.metadata.totalBeatsBefore>0?(c.metadata.totalBeatsBefore-c.metadata.totalBeatsAfter)/c.metadata.totalBeatsBefore:0,conversionMetadata:c.metadata}}const G=this.needsSimplification(B,g),n=this.needsEnhancement(B,g);if(G){const h=this.isHeavySimplification(B,g),c=this.simplifyBeats(t,B,A.quarterNoteInterval,h,E,a,s,e),{targetCount:d}=this.calculateBeatCountTarget(c.beats.length,e,B);if(c.beats.length<d-1){const l=this.enhanceBeats(c.beats,B,a,I,E,i,A.quarterNoteInterval,s),F=l.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:B,beats:l.beats,isUnedited:!1,editType:F,editAmount:1,conversionMetadata:c.metadata,enhancementMetadata:l.metadata}}return{difficulty:B,beats:c.beats,isUnedited:!1,editType:"simplified",editAmount:c.metadata.totalBeatsBefore>0?(c.metadata.totalBeatsBefore-c.metadata.totalBeatsAfter)/c.metadata.totalBeatsBefore:0,conversionMetadata:c.metadata}}if(n){const h=this.enhanceBeats(t,B,a,I,E,i,A.quarterNoteInterval,s);let c=h.beats;if(c.some(F=>!o.includes(F.gridType))){const F=[];for(const m of c)if(o.includes(m.gridType))F.push(m);else{const y=this.convertBeatGridType(m,B,A.quarterNoteInterval,a);y&&F.push(y)}c=this.deduplicateConvertedBeats(F)}const l=h.metadata.patternsInserted>0?"pattern_inserted":"interpolated";return{difficulty:B,beats:c,isUnedited:!1,editType:l,editAmount:h.metadata.totalBeatsBefore>0?(h.metadata.totalBeatsAfter-h.metadata.totalBeatsBefore)/h.metadata.totalBeatsBefore:0,patternsInserted:h.metadata.insertedPatternIds.length>0?h.metadata.insertedPatternIds:void 0,enhancementMetadata:h.metadata}}return{difficulty:B,beats:[...t],isUnedited:!0,editType:"none",editAmount:0}}simplifyBeats(A,B,g,I=!1,E,i=120,C,a=120,e,o){const t={sixteenthToEighth:0,tripletToQuarterTriplet:0,eighthToQuarter:0,beatsRemoved:0,totalBeatsBefore:A.length,totalBeatsAfter:0},s=this.buildPhraseMembershipMap(E),G=C?A:this.enforceSingleGridPerBeat(A);t.totalBeatsBefore=G.length;const n=e??FB(B,i);if(G.every(H=>n.includes(H.gridType))&&!I){const H=o!==void 0?Math.round(o*a):this.calculateBeatCountTarget(G.length,a,B).targetCount,T=this.reduceDensityToTarget(G,B,t,s,i,H,a);return t.totalBeatsAfter=T.length,{beats:T,metadata:t}}let c=G;I&&(c=this.filterBeatsForHeavySimplification(G,t,s));const d=[];for(const H of c){if(n.includes(H.gridType)){d.push(H);continue}const T=C?.get(H.beatIndex),q=this.convertBeatGridType(H,B,g,i,T,n);if(q)if(d.push(q),H.gridType==="straight_16th"){if(t.sixteenthToEighth++,this.config.logConversions){const v=q.gridType==="straight_4th"?"quarter":"8th";console.log(`[DifficultyVariantGenerator] Converted 16th note at beat ${H.beatIndex} position ${H.gridPosition} to ${v} note`)}}else H.gridType==="triplet_8th"?(t.tripletToQuarterTriplet++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Converted 8th triplet at beat ${H.beatIndex} position ${H.gridPosition} to quarter triplet`)):H.gridType==="straight_8th"&&(t.eighthToQuarter++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Converted 8th note at beat ${H.beatIndex} position ${H.gridPosition} to quarter note`));else t.beatsRemoved++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Removed beat at beat ${H.beatIndex} position ${H.gridPosition} (grid: ${H.gridType})`)}const l=this.deduplicateConvertedBeats(d);t.beatsRemoved+=d.length-l.length;const F=d.length-l.length,m=this.calculateDensity(l,a),y=o!==void 0?Math.round(o*a):this.calculateBeatCountTarget(l.length,a,B).targetCount,p=o??this.calculateBeatCountTarget(l.length,a,B).targetDensity;if(l.length<=y)return this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Grid conversion achieved target density: ${m.toFixed(2)} notes/sec (target midpoint ${p.toFixed(2)} nps, ${y} beats) for ${B}`+(F>0?` (${F} beats collapsed)`:"")),t.totalBeatsAfter=l.length,{beats:l,metadata:t};const k=this.reduceDensityToTarget(l,B,t,s,i,y,a);return t.totalBeatsAfter=k.length,{beats:k,metadata:t}}filterBeatsForHeavySimplification(A,B,g=new Map){const I=this.config.heavySimplificationIntensityThreshold,E=[];for(const i of A){const C=this.isStrongBeat(i.beatIndex),a=i.gridPosition===0,e=i.gridPosition===1||i.gridPosition===3,o=this.shouldPreserveForPhrase(i,g,I);C||o||a&&i.intensity>=I*.7||e&&i.intensity>=I||i.gridPosition===2&&i.intensity>=I*.8?E.push(i):(B.beatsRemoved++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Heavy simplification: removed beat at beat ${i.beatIndex} position ${i.gridPosition} (intensity: ${i.intensity.toFixed(2)}, strongBeat: ${C})`))}return E}isStrongBeat(A){const B=this.config.rhythmicBalanceConfig?.strongBeatEmphasis??"natural";if(B==="neutral")return!1;const g=this.currentUnifiedBeatMap;if(!g){const a=A%4;return a===0||a===2}const I=g.beats[A];if(!I){const a=A%4;return a===0||a===2}const E=g.downbeatConfig?.segments;if(!E||E.length===0){const a=A%4;return a===0||a===2}const C=it(E,A).timeSignature.beatsPerMeasure;return Ct(I.beatInMeasure,C,B)}calculateDensity(A,B){return A.length===0||B<=0?0:A.length/B}calculateBeatCountTarget(A,B,g){const I=iB[g].targetDensityRange;if(g==="natural"||g==="custom"){const s=B>0?A/B:0;return{targetCount:A,maxCount:A,minCount:A,targetDensity:s}}const i={easy:.9,medium:1.25,hard:1.75}[g];let C;switch(this.config.densityTargetStrategy){case"lower":C=i*.75+I.min*.25;break;case"upper":{const s=I.max===1/0?i*1.5:I.max;C=i*.75+s*.25;break}default:C=i;break}const a=I.max===1/0?C:I.max;C=Math.max(I.min,Math.min(a,C));const e=Math.round(I.min*B),o=I.max===1/0?1/0:Math.round(I.max*B);return{targetCount:Math.round(C*B),maxCount:o,minCount:e,targetDensity:C}}calculateBeatsToAdd(A,B,g,I){const E=this.calculateBeatCountTarget(A,B,I),i=Math.max(0,E.targetCount-A),C=FB(I,g),a=this.getMaxBeatsPerIndexFromGridTypes(C);return{beatsToAdd:i,targetCount:E.targetCount,maxBeatsPerIndex:a}}getMaxBeatsPerIndexFromGridTypes(A){let B=1;for(const g of A){const I=Yi[g];I>B&&(B=I)}return B}getMaxBeatsForGridType(A){return Yi[A]??1}distributeBeatsAcrossIndices(A,B,g,I,E,i){const C=new Map;let a=A;for(let G=0;G<=I;G++){const n=B.get(G)??[];C.set(G,n.length)}if(a<=0)return C;const e=G=>{const n=g.get(G);return n?i&&!i.includes(n)?this.getMaxBeatsPerIndexFromGridTypes(i):this.getMaxBeatsForGridType(n):i?this.getMaxBeatsPerIndexFromGridTypes(i):4},o=[],t=[];for(let G=0;G<=I;G++){const n=C.get(G)??0,h=e(G);n===0?o.push(G):n<h&&t.push(G)}const s=this.groupConsecutiveEmptyIndices(o);s.sort((G,n)=>{const h=G.length-n.length;if(h!==0)return h;const c=bB(XB(E,`gap:${G[0]}`)),d=bB(XB(E,`gap:${n[0]}`));return c-d});for(const G of s){if(a<=0)break;const n=G.length<=2;for(const h of G){if(a<=0)break;const c=e(h);let d;n?d=Math.min(c,a,2):d=Math.min(c,a,1),d>0&&(C.set(h,d),a-=d)}}t.sort((G,n)=>{const h=C.get(G)??0,c=C.get(n)??0,d=e(G),l=e(n),F=d-h,y=l-c-F;if(y!==0)return y;const p=bB(XB(E,`partial:${G}`)),k=bB(XB(E,`partial:${n}`));return p-k});for(const G of t){if(a<=0)break;const n=C.get(G)??0,c=e(G)-n;if(c>0){const d=Math.min(c,a);C.set(G,n+d),a-=d}}if(a>0)for(const G of o){if(a<=0)break;const n=C.get(G)??0,c=e(G)-n;if(c>0){const d=Math.min(c,a);C.set(G,n+d),a-=d}}return C}groupConsecutiveEmptyIndices(A){if(A.length===0)return[];const B=[];let g=[A[0]];for(let I=1;I<A.length;I++){const E=A[I-1],i=A[I];i===E+1?g.push(i):(B.push(g),g=[i])}return B.push(g),B}reduceDensityToTarget(A,B,g,I=new Map,E=120,i,C=120){const a=iB[B].targetDensityRange,e=this.calculateDensity(A,C);if(i!==void 0&&A.length<=i)return this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Density ${e.toFixed(2)} notes/sec already at or below target midpoint (${i} beats) for ${B}`),A;if(e<=a.max&&i===void 0)return this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Density ${e.toFixed(2)} notes/sec already within target range [${a.min}, ${a.max}] for ${B}`),A;this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Reducing density from ${e.toFixed(2)} notes/sec to target max ${a.max} notes/sec for ${B}`);const o=this.buildDownbeatCountMap(A),t=A.map(m=>({beat:m,priority:this.calculateRemovalPriority(m,I,o)}));t.sort((m,y)=>m.priority-y.priority);const s=new Set;let G=A.length;const n=this.config.maxReductionPasses;let h=0;for(let m=1;m<=n;m++){h=m;let y=0;const p=m===n;let k,H,T=!1;m===1?(k=1-this.config.densityReductionMinIntensity,H=this.config.moderateSimplificationIntensityThreshold):m===2?(k=1-this.config.densityReductionMinIntensity-.15,H=this.config.moderateSimplificationIntensityThreshold-.1):(T=!0,k=0,H=0);for(const{beat:q,priority:v}of t)if(!s.has(q)){if(i!==void 0){if(G-1<=i)break}else if((G-1)/C<=a.max)break;if(T){if(this.isStrongBeat(q.beatIndex))continue}else if(v>=k||q.intensity>=H)continue;s.add(q),G--,y++,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Pass ${m}: Removed beat at index ${q.beatIndex} position ${q.gridPosition} (priority: ${v.toFixed(2)}, intensity: ${q.intensity.toFixed(2)})`)}if(this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Pass ${m}${p?" (final)":""}: Removed ${y} beats, density now: ${(G/C).toFixed(2)} notes/sec`),i!==void 0){if(G<=i)break}else if(G/C<=a.max)break}const c=G/C;if((i!==void 0?G>i:c>a.max)&&this.config.logConversions){const m=i!==void 0?`${i} beats (midpoint ${(i/C).toFixed(2)} nps)`:`${a.max} notes/sec`;console.warn(`[DifficultyVariantGenerator] Could not reach target density ${m} for ${B} after ${n} passes. Final density: ${c.toFixed(2)} notes/sec (${G} beats remaining)`)}const l=A.filter(m=>!s.has(m));g.reductionPasses=h,g.beatsRemoved+=s.size;const F=Math.ceil(a.min*C);if(l.length<F&&A.length>0){const m=t.filter(({beat:y})=>s.has(y)).sort((y,p)=>p.priority-y.priority);for(const{beat:y}of m){if(l.length>=F)break;l.push(y),g.beatsRemoved--}}return l}buildDownbeatCountMap(A){const B=new Map,g=this.currentUnifiedBeatMap;for(const I of A){if(I.gridPosition!==0)continue;let E;g?.beats[I.beatIndex]?E=g.beats[I.beatIndex].measureNumber:E=Math.floor(I.beatIndex/4),B.set(E,(B.get(E)??0)+1)}return B}calculateRemovalPriority(A,B,g=new Map){const I=this.config.rhythmicBalanceConfig?.strongBeatEmphasis??"natural";let E=.5;if(I!=="neutral"&&this.isStrongBeat(A.beatIndex)&&(E+=.3),A.gridPosition===0){E+=.2;const C=this.currentUnifiedBeatMap;let a;C?.beats[A.beatIndex]?a=C.beats[A.beatIndex].measureNumber:a=Math.floor(A.beatIndex/4),(g.get(a)??0)===1&&(E+=.2)}E+=A.intensity*.3;const i=B.get(A.beatIndex);if(i&&i.length>0){const C=Math.max(...i.map(a=>a.significance));E+=Math.min(.15,C*.05)}return(A.gridPosition===1||A.gridPosition===3)&&(E-=.1),Math.max(0,Math.min(1,E))}convertBeatGridType(A,B,g,I=120,E,i){const C=E??A.gridType,a=QQ(C,B,I,i);if(a===C)return{...A,gridType:a};let e,o,t;switch(C){case"straight_16th":{const s=g/4;if(t=A.timestamp-A.gridPosition*s,a==="straight_4th")e=0,o=t;else{A.gridPosition===1||A.gridPosition===3?e=A.gridPosition===1?0:2:e=A.gridPosition;const G=g/2;o=t+(e===0?0:G)}break}case"triplet_8th":{const s=g/3;t=A.timestamp-A.gridPosition*s,e=0,o=t;break}case"straight_8th":{const s=g/2;t=A.timestamp-A.gridPosition*s,e=0,o=t;break}default:return{...A,gridType:A.gridType}}return{...A,gridType:a,gridPosition:e,timestamp:o}}deduplicateConvertedBeats(A){const B=new Map;for(const g of A){const I=`${g.beatIndex}:${g.gridPosition}:${g.gridType}`,E=B.get(I);(!E||g.intensity>E.intensity)&&B.set(I,g)}return Array.from(B.values()).sort((g,I)=>g.timestamp-I.timestamp)}needsSimplification(A,B){const g=["easy","medium","hard"],I=g.indexOf(A),E=g.indexOf(B);return I<E}needsEnhancement(A,B){const g=["easy","medium","hard"],I=g.indexOf(A),E=g.indexOf(B);return I>E}isHeavySimplification(A,B){return B==="hard"&&A==="easy"}enhanceBeats(A,B,g,I,E,i,C=.5,a,e,o){const t=I?.duration??120,s={totalBeatsBefore:A.length,totalBeatsAfter:0,patternsInserted:0,interpolatedBeats:0,insertedPatternIds:[]},G=q=>{if(e){if(e.includes(q))return q;const v=["straight_16th","triplet_8th","straight_8th","quarter_triplet","straight_4th"],EA=v.indexOf(q);for(let aA=EA+1;aA<v.length;aA++)if(e.includes(v[aA]))return v[aA];return e[e.length-1]??q}return QQ(q,B,g)};if(A.length===0)return s.totalBeatsAfter=0,{beats:[],metadata:s};let n=a?A:this.enforceSingleGridPerBeat(A);if(e&&n.some(v=>!e.includes(v.gridType))){const v=[];for(const aA of n)if(e.includes(aA.gridType))v.push(aA);else{const GA=this.convertBeatGridType(aA,B,C,g,void 0,e);GA&&v.push(GA)}n=this.deduplicateConvertedBeats(v)}s.totalBeatsBefore=n.length;const h=this.groupBeatsByIndex(n),c=Math.max(...Array.from(h.keys()));let d;if(o!==void 0){const q=Math.round(o*t);d=Math.max(0,q-n.length);const v=Math.max(0,3*n.length);d=Math.min(d,v)}else d=this.calculateBeatsToAdd(n.length,t,g,B).beatsToAdd;const l=this.config.seed??`enhance:${c}:${n.length}`,F=this.distributeBeatsAcrossIndices(d,h,a??new Map,c,l,e),m=[],y=new Map,p=(q,v)=>`${q}:${v}`;for(const q of n){const v=p(q.beatIndex,q.gridPosition);y.has(v)||y.set(v,q.gridType)}for(let q=0;q<=c;q++){const v=h.get(q)??[],EA=F.get(q)??0;if(v.length>=EA){m.push(...v);continue}const aA=EA-v.length;if(v.length===0){const BA=a?.get(q),wA=BA?G(BA):void 0,yA=this.createBeatsForEmptyIndex(q,aA,I,i,C,h,y,wA),jQ=wA??this.getGridForBeatIndex(q,yA,i);for(const QA of yA){const DA=p(QA.beatIndex,QA.gridPosition);!y.has(DA)&&QA.gridType===jQ&&(y.set(DA,QA.gridType),m.push(QA),s.interpolatedBeats++)}continue}const GA=a?.get(q)??v[0].gridType,rA=G(GA);let P=0;if(this.config.preferPatternInsertion&&E){const BA=this.tryInsertPattern(v,q,aA,E,y,rA);P=BA.beatsAdded,BA.patternId&&(s.patternsInserted++,s.insertedPatternIds.push(BA.patternId))}if(P<aA){const BA=this.interpolateBeats(v,q,aA-P,C,y,rA,I);for(const wA of BA){const yA=p(wA.beatIndex,wA.gridPosition);y.has(yA)||(y.set(yA,wA.gridType),m.push(wA),s.interpolatedBeats++)}}m.push(...v)}const k=m.sort((q,v)=>q.beatIndex!==v.beatIndex?q.beatIndex-v.beatIndex:q.gridPosition-v.gridPosition);let H;a?(this.validateSingleGridPerBeat(k).isValid,H=k):H=this.enforceSingleGridPerBeat(k);const T=this.deduplicateEnhancedBeats(H);return s.totalBeatsAfter=T.length,this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Enhanced beats for ${B}: ${s.totalBeatsBefore} → ${s.totalBeatsAfter} beats (patterns: ${s.patternsInserted}, interpolated: ${s.interpolatedBeats})`),{beats:T,metadata:s}}groupBeatsByIndex(A){const B=new Map;for(const g of A){const I=B.get(g.beatIndex);I?I.push(g):B.set(g.beatIndex,[g])}return B}calculateTargetBeatsPerBeat(A,B,g){const I=new Map;for(let E=0;E<=g;E++){const i=A.get(E);if(i){const C=Math.min(Math.ceil(i.length*B),4);I.set(E,C)}else{const C=Math.min(Math.ceil(B*.7),4);C>=2&&I.set(E,C)}}return I}tryInsertPattern(A,B,g,I,E,i){const a=I.patternLibrary.filter(l=>l.sizeInBeats<=this.config.maxPatternInsertionSize&&l.availableForReuse);if(a.length===0)return{beatsAdded:0};const e=a.filter(l=>l.pattern.some(F=>F.gridType===i));if(e.length===0)return{beatsAdded:0};e.sort((l,F)=>F.significance-l.significance);const o=e[0],t=o.pattern.filter(l=>l.beatIndex===0),s=new Set(A.map(l=>l.gridPosition)),G=(l,F)=>`${l}:${F}`,n=t.filter(l=>!(l.gridType!==i||s.has(l.gridPosition)||E.has(G(B,l.gridPosition))));if(n.length===0)return{beatsAdded:0};const h=n.slice(0,g),c=o.sourceBand,d=h.map(l=>({...l,beatIndex:B,band:c,sourceBand:c,intensity:l.intensity*.8}));for(const l of d)E.set(G(l.beatIndex,l.gridPosition),l.gridType);return{beatsAdded:d.length,patternId:o.id}}createBeatsForEmptyIndex(A,B,g,I,E=.5,i,C,a){let e=a??"straight_16th",o="mid",t="mid";if(!a&&I){const m=I.get(A);m&&(e=m.selectedGrid)}if(!a&&!I?.has(A)&&i)for(const m of[1,-1,2,-2,3,-3]){const y=i.get(A+m);if(y&&y.length>0){e=y[0].gridType,o=y[0].band,t=y[0].sourceBand;break}}const s=new Set;if(C){const m=(y,p)=>`${y}:${p}`;for(let y=0;y<4;y++)C.has(m(A,y))&&s.add(y)}const n={straight_16th:4,straight_8th:2,triplet_8th:3,straight_4th:1,quarter_triplet:1}[e],h=[];for(let m=0;m<n;m++)s.has(m)||h.push(m);h.sort((m,y)=>{const p=k=>k===0?0:k===n-1?2:1;return p(m)-p(y)});const c=h.slice(0,B),d=g?.beats[A]?.timestamp??A*E,F={straight_16th:E/4,straight_8th:E/2,triplet_8th:E/3,straight_4th:E,quarter_triplet:E}[e];return c.map(m=>({timestamp:d+m*F,beatIndex:A,gridPosition:m,gridType:e,intensity:this.config.interpolatedBeatIntensity*.8,band:o,sourceBand:t,quantizationError:0}))}interpolateBeats(A,B,g,I=.5,E,i,C){if(g<=0||A.length===0)return[];const a=i??A[0].gridType,o=(m=>m==="straight_16th"?4:m==="straight_8th"?2:m==="straight_4th"||m==="quarter_triplet"?1:3)(a),t=(m,y)=>`${m}:${y}`,s=new Set(A.map(m=>m.gridPosition));if(E)for(let m=0;m<o;m++)E.has(t(B,m))&&s.add(m);const G=[];for(let m=0;m<o;m++)s.has(m)||G.push(m);G.sort((m,y)=>(m===0||m===3?2:1)-(y===0||y===3?2:1));const n=G.slice(0,g),h=A[0],c=C?.beats[B]?.timestamp??B*I,l={straight_16th:I/4,straight_8th:I/2,triplet_8th:I/3,straight_4th:I,quarter_triplet:I}[a];return n.map(m=>({timestamp:c+m*l,beatIndex:B,gridPosition:m,gridType:a,intensity:this.config.interpolatedBeatIntensity,band:h.band,sourceBand:h.sourceBand,quantizationError:0}))}getGridForBeatIndex(A,B,g,I){if(B.length>0)return B[0].gridType;if(g?.has(A))return g.get(A).selectedGrid;if(I)for(const E of[1,-1,2,-2,3,-3]){const i=I.get(A+E);if(i&&i.length>0)return i[0].gridType}return"straight_16th"}deduplicateEnhancedBeats(A){const B=new Map;for(const E of A){const i=B.get(E.beatIndex)??new Map;i.set(E.gridType,(i.get(E.gridType)??0)+1),B.set(E.beatIndex,i)}const g=new Map;for(const[E,i]of B){let C="straight_16th",a=0;for(const[e,o]of i)o>a&&(a=o,C=e);g.set(E,C)}const I=new Map;for(const E of A){const i=`${E.beatIndex}:${E.gridPosition}`,C=I.get(i),a=g.get(E.beatIndex);C?E.gridType===a&&C.gridType!==a&&I.set(i,E):I.set(i,E)}return Array.from(I.values())}enforceSingleGridPerBeat(A){const B=new Map;for(const I of A){const E=B.get(I.beatIndex)??[];E.push(I),B.set(I.beatIndex,E)}const g=[];for(const[,I]of B){if(I.length<=1){g.push(...I);continue}const E=new Set(I.map(e=>e.gridType));if(E.size<=1){g.push(...I);continue}let i="straight_16th",C=0;for(const e of E){const o=I.filter(t=>t.gridType===e).reduce((t,s)=>t+s.intensity,0);o>C&&(C=o,i=e)}const a=I.filter(e=>e.gridType===i);if(this.config.logConversions&&a.length<I.length){const e=I.filter(o=>o.gridType!==i);console.log(`[DifficultyVariantGenerator] Enforced single grid at beat ${I[0].beatIndex}: kept ${i} (${a.length} beats), removed ${e.map(o=>o.gridType).join(", ")} (${e.length} beats)`)}g.push(...a)}return g.sort((I,E)=>I.timestamp-E.timestamp)}validateSingleGridPerBeat(A){const B=new Map;for(const I of A){const E=B.get(I.beatIndex)??[];E.push(I),B.set(I.beatIndex,E)}const g=[];for(const[I,E]of B){if(E.length<=1)continue;const i=new Set(E.map(C=>C.gridType));i.size>1&&g.push({beatIndex:I,gridTypes:Array.from(i)})}if(g.length>0&&this.config.logConversions){console.warn(`[DifficultyVariantGenerator] Grid validation found ${g.length} violations. This indicates a bug in grid lock implementation.`);for(const I of g.slice(0,5))console.warn(` - Beat index ${I.beatIndex} has mixed grids: ${I.gridTypes.join(", ")}`)}return{isValid:g.length===0,violations:g}}getConfig(){return{...this.config}}buildPhraseMembershipMap(A){const B=new Map;if(!A||!this.config.preservePhraseBoundaries)return B;const g=A.phrases.filter(I=>I.hasVariation);for(const I of g)for(const E of I.occurrences)for(let i=0;i<I.sizeInBeats;i++){const C=E.beatIndex+i,a=B.get(C)??[];a.push(I),B.set(C,a)}return B}shouldPreserveForPhrase(A,B,g){if(!this.config.preservePhraseBoundaries)return!1;const I=B.get(A.beatIndex);if(!I||I.length===0)return!1;const E=I.reduce((o,t)=>t.significance>o.significance?t:o),C=A.intensity-g>=-.15,e=E.significance>=1.5;return C&&e?(this.config.logConversions&&console.log(`[DifficultyVariantGenerator] Preserving beat at index ${A.beatIndex} position ${A.gridPosition} (intensity: ${A.intensity.toFixed(2)}) due to phrase membership (phrase significance: ${E.significance.toFixed(2)})`),!0):!1}}const Ui={casual:{difficulty:"easy",outputMode:"composite",description:"Easy difficulty for relaxed gameplay"},standard:{difficulty:"medium",outputMode:"composite",description:"Balanced experience for most players"},challenge:{difficulty:"hard",outputMode:"composite",description:"Hard difficulty for skilled players"},bass:{difficulty:"medium",outputMode:"low",description:"Focus on bass/low-frequency rhythms"}};function Yd(Q){return Ui[Q]}function Ud(){return Object.keys(Ui)}const kd={difficulty:"medium",outputMode:"composite",measureStartOffset:0,minimumTransientIntensity:0,transientConfig:void 0,scoringConfig:void 0,phraseAnalyzerConfig:void 0,rhythmicBalanceConfig:IQ,seed:void 0,verbose:!1,enableCache:!0,cacheMaxAge:1800*1e3,skipDifficultyVariants:!1};class HB{constructor(A={}){this.cache=new Map,this.cacheHits=0,this.cacheMisses=0;const B={...IQ,...A.rhythmicBalanceConfig};this.options={...kd,...A,rhythmicBalanceConfig:B},this.multiBandAnalyzer=new To,this.transientDetector=new jo({bandConfig:this.options.transientConfig}),this.rhythmQuantizer=new bi({minimumTransientIntensity:this.options.minimumTransientIntensity,densityValidation:this.options.densityValidation}),this.phraseAnalyzer=new _o(this.options.phraseAnalyzerConfig),this.densityAnalyzer=new $o,this.streamScorer=new Bt(this.options.scoringConfig),this.compositeGenerator=new gt,this.variantGenerator=new EQ({seed:this.options.seed,rhythmicBalanceConfig:B}),this.rhythmicBalancer=new at(this.options.rhythmicBalanceConfig),this.tempoAwareQuantizer=new Po(this.options.tempoQuantizationConfig??pi,this.rhythmQuantizer)}generateCacheKey(A,B,g){return`${A}:${B}:${g}`}createConfigFingerprint(){const A={minimumTransientIntensity:this.options.minimumTransientIntensity,measureStartOffset:this.options.measureStartOffset,tempoQuantizationConfig:this.options.tempoQuantizationConfig};return JSON.stringify(A)}getFromCache(A){if(!this.options.enableCache)return null;const B=this.cache.get(A);return B?Date.now()-B.timestamp>this.options.cacheMaxAge?(this.cache.delete(A),this.cacheMisses++,null):(this.cacheHits++,this.options.verbose&&console.log(`[RhythmGenerator] Cache HIT for key: ${A}`),B.result):(this.cacheMisses++,null)}setCache(A,B){this.options.enableCache&&(this.cache.set(A,{result:B,timestamp:Date.now(),key:A}),this.options.verbose&&console.log(`[RhythmGenerator] Cache SET for key: ${A}`))}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0}pruneExpiredCache(){const A=Date.now();for(const[B,g]of this.cache.entries())A-g.timestamp>this.options.cacheMaxAge&&this.cache.delete(B)}getCacheStats(){let A=0;const B=[];let g=null;for(const[I,E]of this.cache.entries()){const i=I.split(":")[1];B.includes(i)||B.push(i);try{A+=JSON.stringify(E.result).length*2}catch{A+=1e3}(g===null||E.timestamp<g)&&(g=E.timestamp)}return{entryCount:this.cache.size,estimatedSize:A,cachedPhases:B,oldestEntry:g,hits:this.cacheHits,misses:this.cacheMisses}}isCached(A,B){const g=this.createConfigFingerprint(),I=this.generateCacheKey(A,B,g);return this.cache.has(I)}getOptions(){return{...this.options}}async generate(A,B,g,I){const E=(y,p,k)=>{this.options.verbose&&console.log(`[RhythmGenerator] [${y}] ${Math.round(p*100)}%: ${k}`),I?.(y,p,k)};g?.throwIfAborted();const i=this.generateCacheKey(B.audioId,"variants",this.createConfigFingerprint()),C=this.getFromCache(i);if(C)return E("Cache",1,"Retrieved complete result from cache"),C;E("Phase 1",0,"Starting multi-band analysis"),g?.throwIfAborted();const a=this.analyzeMultiBand(A);E("Phase 1",.2,`Analyzed ${a.bands.size} frequency bands`),g?.throwIfAborted();const e=this.detectTransients(a);E("Phase 1",.4,`Detected ${e.transients.length} transients`),g?.throwIfAborted();const o=this.quantizeTransients(e,B);E("Phase 1",.8,`Quantized to ${o.streams.low.beats.length+o.streams.mid.beats.length+o.streams.high.beats.length} beats across all bands`),E("Phase 1",1,"Phase 1 complete"),g?.throwIfAborted(),E("Phase 2",0,"Starting phrase and density analysis"),g?.throwIfAborted();const t=this.analyzePhrases(o.streams);E("Phase 2",.3,`Detected ${t.phrases.length} rhythmic phrases`),g?.throwIfAborted();const s=this.analyzeDensity(o,B.quarterNoteBpm,B.duration);E("Phase 2",.7,`Density category: ${s.combinedMetrics.densityCategory}`),E("Phase 2",1,"Phase 2 complete"),g?.throwIfAborted(),E("Phase 3",0,"Starting scoring and composite generation"),g?.throwIfAborted();const G=this.scoreStreams(o,t,s,B.quarterNoteBpm);E("Phase 3",.2,`Scored ${G.sectionWinners.length} sections`),g?.throwIfAborted();const n=this.generateComposite(o,G,s,B.duration);E("Phase 3",.4,`Generated composite with ${n.beats.length} beats, natural difficulty: ${n.naturalDifficulty}`),g?.throwIfAborted();const h=this.rhythmicBalancer.balance(n,B),c=h.composite,d=h.stats;E("Phase 3",.6,`Balanced composite: ${c.beats.length} beats (${d.beatsAdded} added, ${d.beatsShifted} shifted for rhythmic structure)`);const l=this.options.skipDifficultyVariants?null:this.generateDifficultyVariants(c,t,o,B);E("Phase 3",.8,this.options.skipDifficultyVariants?"Skipped preset difficulty variants (density-based mode)":"Generated easy/medium/hard difficulty variants"),E("Phase 3",1,"Phase 3 complete"),g?.throwIfAborted();const F={difficulty:this.options.difficulty,bandsAnalyzed:["low","mid","high"],transientsDetected:e.metadata.totalTransients,transientsFilteredByIntensity:o.metadata.transientsFilteredByIntensity,densityValidationRetries:o.metadata.densityValidation.maxRetryCount,phrasesDetected:t.phrases.length,averageDensity:s.combinedMetrics.notesPerSecond,naturalDifficulty:c.naturalDifficulty,generationConfig:this.options,duration:A.duration,totalBeats:B.beats.length,balanceStats:d},m={difficultyVariants:l,bandStreams:o.streams,composite:c,analysis:{transientAnalysis:e,quantizationResult:o,phraseAnalysis:t,densityAnalysis:s,scoringResult:G},metadata:F};return this.setCache(i,m),m}analyzeMultiBand(A){return this.multiBandAnalyzer.analyze(A)}detectTransients(A){return this.transientDetector.detect(A)}quantizeTransients(A,B){return this.rhythmQuantizer.quantize(A,B,(g,I,E)=>this.tempoAwareQuantizer.decideGrids(g,I,E))}analyzePhrases(A){return this.phraseAnalyzer.analyze(A)}analyzeDensity(A,B,g){return this.densityAnalyzer.analyze(A,B,g)}scoreStreams(A,B,g,I){return this.streamScorer.updateConfig({bpm:I}),this.streamScorer.score(A,B,g)}generateComposite(A,B,g,I){return this.compositeGenerator.generate(A,B,g,I)}generateDifficultyVariants(A,B,g,I){const E=this.collectGridDecisions(g);return this.variantGenerator.generate(A,I,B,E)}collectGridDecisions(A){const B=new Map,g=[...A.streams.low.gridDecisions,...A.streams.mid.gridDecisions,...A.streams.high.gridDecisions];for(const I of g){const E=B.get(I.beatIndex);(!E||I.confidence>E.confidence)&&B.set(I.beatIndex,I)}return B}static async quickGenerate(A,B){return new HB().generate(A,B)}static async generateForDifficulty(A,B,g){return(await new HB().generate(A,B)).difficultyVariants[g]}static toJSON(A){const B={difficultyVariants:A.difficultyVariants?{easy:this.serializeDifficultyVariant(A.difficultyVariants.easy),medium:this.serializeDifficultyVariant(A.difficultyVariants.medium),hard:this.serializeDifficultyVariant(A.difficultyVariants.hard),natural:this.serializeDifficultyVariant(A.difficultyVariants.natural)}:null,bandStreams:{low:this.serializeGeneratedRhythmMap(A.bandStreams.low),mid:this.serializeGeneratedRhythmMap(A.bandStreams.mid),high:this.serializeGeneratedRhythmMap(A.bandStreams.high)},composite:this.serializeCompositeStream(A.composite),analysis:{transientAnalysis:this.serializeTransientAnalysis(A.analysis.transientAnalysis),quantizationResult:this.serializeQuantizedBandStreams(A.analysis.quantizationResult),phraseAnalysis:this.serializePhraseAnalysisResult(A.analysis.phraseAnalysis),densityAnalysis:this.serializeDensityAnalysisResult(A.analysis.densityAnalysis),scoringResult:this.serializeStreamScoringResult(A.analysis.scoringResult)},metadata:A.metadata};return JSON.stringify(B,null,2)}static fromJSON(A){const B=JSON.parse(A);return{difficultyVariants:B.difficultyVariants?{easy:this.deserializeDifficultyVariant(B.difficultyVariants.easy),medium:this.deserializeDifficultyVariant(B.difficultyVariants.medium),hard:this.deserializeDifficultyVariant(B.difficultyVariants.hard),natural:this.deserializeDifficultyVariant(B.difficultyVariants.natural)}:null,bandStreams:{low:this.deserializeGeneratedRhythmMap(B.bandStreams.low),mid:this.deserializeGeneratedRhythmMap(B.bandStreams.mid),high:this.deserializeGeneratedRhythmMap(B.bandStreams.high)},composite:this.deserializeCompositeStream(B.composite),analysis:{transientAnalysis:this.deserializeTransientAnalysis(B.analysis.transientAnalysis),quantizationResult:this.deserializeQuantizedBandStreams(B.analysis.quantizationResult),phraseAnalysis:this.deserializePhraseAnalysisResult(B.analysis.phraseAnalysis),densityAnalysis:this.deserializeDensityAnalysisResult(B.analysis.densityAnalysis),scoringResult:this.deserializeStreamScoringResult(B.analysis.scoringResult)},metadata:B.metadata}}static async saveToFile(A,B){if(typeof process>"u"||!process.versions?.node)throw new Error("saveToFile is only available in Node.js environment");const{writeFile:g}=await Promise.resolve().then(()=>GB),I=HB.toJSON(A);await g(B,I,"utf-8")}static async loadFromFile(A){if(typeof process>"u"||!process.versions?.node)throw new Error("loadFromFile is only available in Node.js environment");const{readFile:B}=await Promise.resolve().then(()=>GB),g=await B(A,"utf-8");return HB.fromJSON(g)}static serializeDifficultyVariant(A){return{difficulty:A.difficulty,beats:A.beats.map(B=>this.serializeVariantBeat(B)),isUnedited:A.isUnedited,editType:A.editType,editAmount:A.editAmount,patternsInserted:A.patternsInserted,conversionMetadata:A.conversionMetadata,enhancementMetadata:A.enhancementMetadata}}static deserializeDifficultyVariant(A){return{difficulty:A.difficulty,beats:A.beats.map(B=>this.deserializeVariantBeat(B)),isUnedited:A.isUnedited,editType:A.editType,editAmount:A.editAmount,patternsInserted:A.patternsInserted,conversionMetadata:A.conversionMetadata,enhancementMetadata:A.enhancementMetadata}}static serializeVariantBeat(A){return{timestamp:A.timestamp,beatIndex:A.beatIndex,gridPosition:A.gridPosition,gridType:A.gridType,intensity:A.intensity,band:A.band,quantizationError:A.quantizationError,sourceBand:A.sourceBand}}static deserializeVariantBeat(A){return{timestamp:A.timestamp,beatIndex:A.beatIndex,gridPosition:A.gridPosition,gridType:A.gridType,intensity:A.intensity,band:A.band,quantizationError:A.quantizationError,sourceBand:A.sourceBand}}static serializeGeneratedRhythmMap(A){return{audioId:A.audioId,duration:A.duration,beats:A.beats.map(B=>this.serializeGeneratedBeat(B)),gridDecisions:A.gridDecisions,quarterNoteInterval:A.quarterNoteInterval}}static deserializeGeneratedRhythmMap(A){return{audioId:A.audioId,duration:A.duration,beats:A.beats.map(B=>this.deserializeGeneratedBeat(B)),gridDecisions:A.gridDecisions,quarterNoteInterval:A.quarterNoteInterval}}static serializeGeneratedBeat(A){return{timestamp:A.timestamp,beatIndex:A.beatIndex,gridPosition:A.gridPosition,gridType:A.gridType,intensity:A.intensity,band:A.band,quantizationError:A.quantizationError}}static deserializeGeneratedBeat(A){return{timestamp:A.timestamp,beatIndex:A.beatIndex,gridPosition:A.gridPosition,gridType:A.gridType,intensity:A.intensity,band:A.band,quantizationError:A.quantizationError}}static serializeCompositeStream(A){return{beats:A.beats.map(B=>this.serializeCompositeBeat(B)),sections:A.sections,naturalDifficulty:A.naturalDifficulty,quarterNoteInterval:A.quarterNoteInterval,metadata:A.metadata}}static deserializeCompositeStream(A){return{beats:A.beats.map(B=>this.deserializeCompositeBeat(B)),sections:A.sections,naturalDifficulty:A.naturalDifficulty,quarterNoteInterval:A.quarterNoteInterval,metadata:A.metadata}}static serializeCompositeBeat(A){return{timestamp:A.timestamp,beatIndex:A.beatIndex,gridPosition:A.gridPosition,gridType:A.gridType,intensity:A.intensity,band:A.band,quantizationError:A.quantizationError,sourceBand:A.sourceBand,balancerAction:A.balancerAction}}static deserializeCompositeBeat(A){return{timestamp:A.timestamp,beatIndex:A.beatIndex,gridPosition:A.gridPosition,gridType:A.gridType,intensity:A.intensity,band:A.band,quantizationError:A.quantizationError,sourceBand:A.sourceBand,balancerAction:A.balancerAction}}static serializeTransientAnalysis(A){return{transients:A.transients.map(B=>this.serializeTransientResult(B)),bandTransients:Array.from(A.bandTransients.entries()).map(([B,g])=>({band:B,transients:g.map(I=>this.serializeTransientResult(I))})),metadata:{totalTransients:A.metadata.totalTransients,transientsPerBand:Array.from(A.metadata.transientsPerBand.entries()).map(([B,g])=>({band:B,count:g})),duration:A.metadata.duration,averageIntensity:A.metadata.averageIntensity,detectionMethodsUsed:A.metadata.detectionMethodsUsed}}}static deserializeTransientAnalysis(A){const B=new Map;for(const I of A.bandTransients)B.set(I.band,I.transients.map(E=>this.deserializeTransientResult(E)));const g=new Map;for(const I of A.metadata.transientsPerBand)g.set(I.band,I.count);return{transients:A.transients.map(I=>this.deserializeTransientResult(I)),bandTransients:B,metadata:{totalTransients:A.metadata.totalTransients,transientsPerBand:g,duration:A.metadata.duration,averageIntensity:A.metadata.averageIntensity,detectionMethodsUsed:A.metadata.detectionMethodsUsed}}}static serializeTransientResult(A){return{timestamp:A.timestamp,intensity:A.intensity,band:A.band,detectionMethod:A.detectionMethod,nearestBeat:A.nearestBeat}}static deserializeTransientResult(A){return{timestamp:A.timestamp,intensity:A.intensity,band:A.band,detectionMethod:A.detectionMethod,nearestBeat:A.nearestBeat}}static serializeQuantizedBandStreams(A){return{streams:{low:this.serializeGeneratedRhythmMap(A.streams.low),mid:this.serializeGeneratedRhythmMap(A.streams.mid),high:this.serializeGeneratedRhythmMap(A.streams.high)},metadata:{densityValidation:this.serializeDensityValidationResult(A.metadata.densityValidation),transientsFilteredByIntensity:A.metadata.transientsFilteredByIntensity,transientsFilteredByBand:A.metadata.transientsFilteredByBand}}}static serializeDensityValidationResult(A){return{isValid:A.isValid,bands:{low:this.serializeBandDensityValidationResult(A.bands.low),mid:this.serializeBandDensityValidationResult(A.bands.mid),high:this.serializeBandDensityValidationResult(A.bands.high)},maxRetryCount:A.maxRetryCount,maxSensitivityReduction:A.maxSensitivityReduction}}static serializeBandDensityValidationResult(A){return{band:A.band,isValid:A.isValid,minIntervalDetected:A.minIntervalDetected,requiredMinInterval:A.requiredMinInterval,retryCount:A.retryCount,sensitivityReduction:A.sensitivityReduction,finalIntensityThreshold:A.finalIntensityThreshold,transientsRemaining:A.transientsRemaining}}static deserializeQuantizedBandStreams(A){return{streams:{low:this.deserializeGeneratedRhythmMap(A.streams.low),mid:this.deserializeGeneratedRhythmMap(A.streams.mid),high:this.deserializeGeneratedRhythmMap(A.streams.high)},metadata:{densityValidation:this.deserializeDensityValidationResult(A.metadata.densityValidation),transientsFilteredByIntensity:A.metadata.transientsFilteredByIntensity,transientsFilteredByBand:A.metadata.transientsFilteredByBand}}}static deserializeDensityValidationResult(A){return{isValid:A.isValid,bands:{low:this.deserializeBandDensityValidationResult(A.bands.low),mid:this.deserializeBandDensityValidationResult(A.bands.mid),high:this.deserializeBandDensityValidationResult(A.bands.high)},maxRetryCount:A.maxRetryCount,maxSensitivityReduction:A.maxSensitivityReduction}}static deserializeBandDensityValidationResult(A){return{band:A.band,isValid:A.isValid,minIntervalDetected:A.minIntervalDetected,requiredMinInterval:A.requiredMinInterval,retryCount:A.retryCount,sensitivityReduction:A.sensitivityReduction,finalIntensityThreshold:A.finalIntensityThreshold,transientsRemaining:A.transientsRemaining}}static serializePhraseAnalysisResult(A){return{phrases:A.phrases.map(B=>this.serializeRhythmicPhrase(B)),phrasesByBand:Array.from(A.phrasesByBand.entries()).map(([B,g])=>({band:B,phrases:g.map(I=>this.serializeRhythmicPhrase(I))})),mostSignificantPhrases:A.mostSignificantPhrases.map(B=>this.serializeRhythmicPhrase(B)),phrasesBySize:Array.from(A.phrasesBySize.entries()).map(([B,g])=>({size:B,phrases:g.map(I=>this.serializeRhythmicPhrase(I))})),patternLibrary:A.patternLibrary.map(B=>this.serializeRhythmicPhrase(B)),bandAnalysis:{low:this.serializeBandPhraseAnalysis(A.bandAnalysis.low),mid:this.serializeBandPhraseAnalysis(A.bandAnalysis.mid),high:this.serializeBandPhraseAnalysis(A.bandAnalysis.high)}}}static deserializePhraseAnalysisResult(A){const B=new Map;for(const I of A.phrasesByBand)B.set(I.band,I.phrases.map(E=>this.deserializeRhythmicPhrase(E)));const g=new Map;for(const I of A.phrasesBySize)g.set(I.size,I.phrases.map(E=>this.deserializeRhythmicPhrase(E)));return{phrases:A.phrases.map(I=>this.deserializeRhythmicPhrase(I)),phrasesByBand:B,mostSignificantPhrases:A.mostSignificantPhrases.map(I=>this.deserializeRhythmicPhrase(I)),phrasesBySize:g,patternLibrary:A.patternLibrary.map(I=>this.deserializeRhythmicPhrase(I)),bandAnalysis:{low:this.deserializeBandPhraseAnalysis(A.bandAnalysis.low),mid:this.deserializeBandPhraseAnalysis(A.bandAnalysis.mid),high:this.deserializeBandPhraseAnalysis(A.bandAnalysis.high)}}}static serializeRhythmicPhrase(A){return{id:A.id,pattern:A.pattern.map(B=>this.serializeGeneratedBeat(B)),sizeInBeats:A.sizeInBeats,sourceBand:A.sourceBand,occurrences:A.occurrences,significance:A.significance,hasVariation:A.hasVariation,availableForReuse:A.availableForReuse}}static deserializeRhythmicPhrase(A){return{id:A.id,pattern:A.pattern.map(B=>this.deserializeGeneratedBeat(B)),sizeInBeats:A.sizeInBeats,sourceBand:A.sourceBand,occurrences:A.occurrences,significance:A.significance,hasVariation:A.hasVariation,availableForReuse:A.availableForReuse}}static serializeBandPhraseAnalysis(A){return{band:A.band,phrases:A.phrases.map(B=>this.serializeRhythmicPhrase(B)),phrasesBySize:Array.from(A.phrasesBySize.entries()).map(([B,g])=>({size:B,phrases:g.map(I=>this.serializeRhythmicPhrase(I))})),phrasesWithVariation:A.phrasesWithVariation.map(B=>this.serializeRhythmicPhrase(B))}}static deserializeBandPhraseAnalysis(A){const B=new Map;for(const g of A.phrasesBySize)B.set(g.size,g.phrases.map(I=>this.deserializeRhythmicPhrase(I)));return{band:A.band,phrases:A.phrases.map(g=>this.deserializeRhythmicPhrase(g)),phrasesBySize:B,phrasesWithVariation:A.phrasesWithVariation.map(g=>this.deserializeRhythmicPhrase(g))}}static serializeDensityAnalysisResult(A){return{bandMetrics:{low:this.serializeBandDensityMetrics(A.bandMetrics.low),mid:this.serializeBandDensityMetrics(A.bandMetrics.mid),high:this.serializeBandDensityMetrics(A.bandMetrics.high)},combinedMetrics:A.combinedMetrics,sections:A.sections,perBeatDensity:A.perBeatDensity}}static deserializeDensityAnalysisResult(A){return{bandMetrics:{low:this.deserializeBandDensityMetrics(A.bandMetrics.low),mid:this.deserializeBandDensityMetrics(A.bandMetrics.mid),high:this.deserializeBandDensityMetrics(A.bandMetrics.high)},combinedMetrics:A.combinedMetrics,sections:A.sections,perBeatDensity:A.perBeatDensity}}static serializeBandDensityMetrics(A){return{band:A.band,totalBeats:A.totalBeats,totalTransients:A.totalTransients,notesPerSecond:A.notesPerSecond,minNotesPerSecond:A.minNotesPerSecond,maxNotesPerSecond:A.maxNotesPerSecond,variance:A.variance,densityCategory:A.densityCategory,naturalDifficulty:A.naturalDifficulty,perBeatDensity:A.perBeatDensity}}static deserializeBandDensityMetrics(A){return{band:A.band,totalBeats:A.totalBeats,totalTransients:A.totalTransients,notesPerSecond:A.notesPerSecond,minNotesPerSecond:A.minNotesPerSecond,maxNotesPerSecond:A.maxNotesPerSecond,variance:A.variance,densityCategory:A.densityCategory,naturalDifficulty:A.naturalDifficulty,perBeatDensity:A.perBeatDensity}}static serializeStreamScoringResult(A){return{sectionScores:A.sectionScores,bandTotals:A.bandTotals,bandAverages:A.bandAverages,sectionWinners:A.sectionWinners,config:A.config}}static deserializeStreamScoringResult(A){return{sectionScores:A.sectionScores,bandTotals:A.bandTotals,bandAverages:A.bandAverages,sectionWinners:A.sectionWinners,config:A.config}}}const Zd={minFrequency:80,maxFrequency:1e3,frameSize:2048,hopSize:512,voicingThreshold:.2,transitionPenalty:.5,selfTransitionProbability:.99,yinThreshold:.4,targetSampleRate:44100},ht=69,ct=440,Wd=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];class ki{constructor(A={}){if(this.states=[],this.transitionMatrix=[],this.config={...Zd,...A},this.config.minFrequency<=0)throw new Error(`minFrequency must be positive, got: ${this.config.minFrequency}`);if(this.config.maxFrequency<=this.config.minFrequency)throw new Error("maxFrequency must be greater than minFrequency");if(this.config.frameSize<=0||(this.config.frameSize&this.config.frameSize-1)!==0)throw new Error("frameSize must be a positive power of 2");if(this.config.hopSize<=0)throw new Error("hopSize must be positive");if(this.config.voicingThreshold<0||this.config.voicingThreshold>1)throw new Error("voicingThreshold must be between 0 and 1");this.initializeHMM()}getConfig(){return{...this.config}}initializeHMM(){const{minFrequency:A,maxFrequency:B}=this.config,g=this.frequencyToMidi(A),I=this.frequencyToMidi(B);this.states=[];for(let E=g;E<=I;E+=.5)this.states.push({frequency:this.midiToFrequency(E),midiNote:Math.round(E),index:this.states.length});this.states.push({frequency:0,midiNote:-1,index:this.states.length}),this.transitionMatrix=this.computeTransitionMatrix()}computeTransitionMatrix(){const A=this.states.length,B=[];for(let g=0;g<A;g++){B[g]=[];for(let I=0;I<A;I++)B[g][I]=this.transitionProbability(g,I)}return B}transitionProbability(A,B){const{selfTransitionProbability:g,transitionPenalty:I}=this.config,i=this.states.length-1;if(A===B)return Math.log(g);if(A===i||B===i)return Math.log((1-g)*.1);const C=this.states[A].midiNote,a=this.states[B].midiNote,e=Math.abs(a-C),o=(1-g)*Math.exp(-I*e);return Math.log(o)}frequencyToMidi(A){return ht+12*Math.log2(A/ct)}midiToFrequency(A){return ct*Math.pow(2,(A-ht)/12)}midiToNoteName(A){const B=Math.floor(A/12)-1,g=Math.round(A)%12;return`${Wd[g]}${B}`}detect(A){const g=Kg(A,this.config.targetSampleRate).data,I=this.config.targetSampleRate,{frameSize:E,hopSize:i}=this.config,C=Math.floor((g.length-E)/i)+1,a=i/I,e=[],o=[];for(let G=0;G<C;G++){const n=G*i,h=g.slice(n,n+E),{filtered:c,all:d}=this.analyzeFrame(h,I);e.push(c),o.push(d)}const t=this.viterbiDecode(e),s=[];for(let G=0;G<C;G++){const n=t[G],h=this.states[n],c=e[G],d=o[G],l={timestamp:G*a,frequency:h.frequency,probability:this.getFrameProbability(n,c),isVoiced:h.frequency>0,midiNote:h.frequency>0?h.midiNote:null,noteName:h.frequency>0?this.midiToNoteName(h.midiNote):null};d.length>1&&(l.alternativeHypotheses=d.slice(0,5).map(F=>({frequency:F.frequency,probability:F.probability}))),s.push(l)}return s}detectSignal(A,B){const{frameSize:g,hopSize:I}=this.config,E=Math.floor((A.length-g)/I)+1,i=I/B,C=[],a=[];for(let t=0;t<E;t++){const s=t*I,G=A.slice(s,s+g),{filtered:n,all:h}=this.analyzeFrame(G,B);C.push(n),a.push(h)}const e=this.viterbiDecode(C),o=[];for(let t=0;t<E;t++){const s=e[t],G=this.states[s],n=C[t],h=a[t],c={timestamp:t*i,frequency:G.frequency,probability:this.getFrameProbability(s,n),isVoiced:G.frequency>0,midiNote:G.frequency>0?G.midiNote:null,noteName:G.frequency>0?this.midiToNoteName(G.midiNote):null};h.length>1&&(c.alternativeHypotheses=h.slice(0,5).map(d=>({frequency:d.frequency,probability:d.probability}))),o.push(c)}return o}detectSignalRaw(A,B){const{frameSize:g,hopSize:I,voicingThreshold:E}=this.config,i=Math.floor((A.length-g)/I)+1,C=I/B,a=[];let e=0,o=0;const t={below01:0,b01_02:0,b02_03:0,b03_04:0,b04_05:0,above05:0};for(let s=0;s<i;s++){const G=s*I,n=A.slice(G,G+g),{filtered:h,all:c}=this.analyzeFrame(n,B),d=s*C;if(h.length>0){e++;const l=h[0].probability;if(l<.1?t.below01++:l<.2?t.b01_02++:l<.3?t.b02_03++:l<.4?t.b03_04++:l<.5?t.b04_05++:t.above05++,l>=E){const F=h[0],m=Math.round(this.frequencyToMidi(F.frequency)),y={timestamp:d,frequency:F.frequency,probability:F.probability,isVoiced:!0,midiNote:m,noteName:this.midiToNoteName(m)};c.length>1&&(y.alternativeHypotheses=c.slice(0,5).map(p=>({frequency:p.frequency,probability:p.probability}))),a.push(y)}else a.push({timestamp:d,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null})}else o++,a.push({timestamp:d,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null})}return console.log("[PitchDetector.detectSignalRaw] Candidate quality:",{numFrames:i,framesWithCandidates:e,framesWithNoCandidates:o,candidateRate:(e/i*100).toFixed(1)+"%",voicingThreshold:E,probBuckets:t}),a}detectAt(A,B,g){const{frameSize:I,hopSize:E}=this.config,i=Math.round(g*B),C=Math.max(0,i-Math.floor(I/2)),a=Math.min(A.length,C+I);if(a-C<I)return{timestamp:g,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null};const e=A.slice(C,a),{filtered:o,all:t}=this.analyzeFrame(e,B);if(o.length===0)return{timestamp:g,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null};const s=o[0],G=Math.round(this.frequencyToMidi(s.frequency)),n={timestamp:g,frequency:s.frequency,probability:s.probability,isVoiced:s.probability>=this.config.voicingThreshold,midiNote:G,noteName:this.midiToNoteName(G)};return t.length>1&&(n.alternativeHypotheses=t.slice(0,5).map(h=>({frequency:h.frequency,probability:h.probability}))),n}analyzeFrame(A,B){const{minFrequency:g,maxFrequency:I,yinThreshold:E}=this.config,i=Math.ceil(B/g),C=Math.max(2,Math.floor(B/I)),a=Math.min(i,Math.floor(A.length/2)),e=this.computeDifferenceFunction(A,a),o=this.computeCMNDF(e,C,a),t=[];for(let n=C+1;n<a-1;n++)if(o[n]<o[n-1]&&o[n]<o[n+1]&&o[n]<E){const h=this.parabolicInterpolation(o,n),c=B/h,d=1-o[n];c>=g&&c<=I&&t.push({lag:h,frequency:c,probability:d})}if(t.sort((n,h)=>h.probability-n.probability),t.length===0)return{filtered:[],all:[]};const s=[],G=t[0].probability;for(const n of t){let h=!1;for(const c of t){if(c.frequency<=n.frequency||c.probability<G*.9)continue;const d=c.frequency/n.frequency,l=Math.round(d),F=Math.abs(d-l);if(l>=2&&l<=5&&F<.1){h=!0;break}}h||s.push(n)}return s.length===0&&t.length>0&&s.push(t[0]),{filtered:s,all:t}}computeDifferenceFunction(A,B){const g=A.length,I=new Float32Array(B+1);I[0]=0;for(let E=1;E<=B;E++){let i=0;for(let C=0;C<g-E;C++){const a=A[C]-A[C+E];i+=a*a}I[E]=i}return I}computeCMNDF(A,B,g){const I=new Float32Array(A.length);I[0]=1;let E=0;for(let i=1;i<=g;i++)E+=A[i],I[i]=A[i]*i/E;return I}parabolicInterpolation(A,B){if(B<=0||B>=A.length-1)return B;const g=A[B-1],I=A[B],E=A[B+1],i=(E-g)/(2*(2*I-g-E));return Math.max(B-1,Math.min(B+1,B+i))}getFrameProbability(A,B){const I=this.states.length-1;if(A===I)return B.length===0?1:1-B[0].probability;const E=this.states[A].frequency;let i=0;for(const C of B)Math.abs(C.frequency-E)/E<.05&&(i=Math.max(i,C.probability));return i}viterbiDecode(A){const B=A.length,g=this.states.length;if(B===0)return[];const I=[];I[0]=[];for(let a=0;a<g;a++){const e=this.priorLogProbability(a,A[0]);I[0][a]={logProbability:e,previousState:-1}}for(let a=1;a<B;a++){I[a]=[];for(let e=0;e<g;e++){const o=this.observationLogProbability(e,A[a]);let t=0,s=-1/0;for(let G=0;G<g;G++){const n=this.transitionMatrix[G][e],h=I[a-1][G].logProbability+n;h>s&&(s=h,t=G)}I[a][e]={logProbability:s+o,previousState:t}}}const E=new Array(B);let i=0,C=I[B-1][0].logProbability;for(let a=1;a<g;a++)I[B-1][a].logProbability>C&&(C=I[B-1][a].logProbability,i=a);E[B-1]=i;for(let a=B-2;a>=0;a--)E[a]=I[a+1][E[a+1]].previousState;return E}priorLogProbability(A,B){const g=this.states.length,I=g-1,E=Math.log(.7/(g-1)),i=Math.log(.3);return A===I?i+this.observationLogProbability(A,B):E+this.observationLogProbability(A,B)}observationLogProbability(A,B){const I=this.states.length-1;if(A===I){if(B.length===0)return Math.log(.9);const C=B[0].probability;return Math.log(1-C*.8)}const E=this.states[A].frequency;let i=0;for(const C of B){const a=C.frequency/E,e=Math.abs(a-1);if(e<.05){const o=1-e/.05*.2,t=C.probability*o;t>i&&(i=t)}if(i===0){const o=Math.abs(a-.5),t=Math.abs(a-2);if(o<.05||t<.05){const s=C.probability*.4;s>i&&(i=s)}}}return Math.log(i===0?.01:i)}}const iQ="https://arweave.net/_HoMwkbF0JUamTiVGWNnCCC5yDjcPry-ENhzN6Xn3U0/model.json",rt={algorithm:"pitch_melodia",minFrequency:80,maxFrequency:2e4,frameSize:2048,hopSize:128,targetSampleRate:44100,crepeModelUrl:iQ},Hd=69,fd=440,Nd=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];class Tg{constructor(A){this.essentiaWASM=null,this.algorithms=null,this.crepeModel=null,this.initialized=!1,this.resolvedUrlCache=new Map,this.config={...rt,...A}}static async create(A={}){const B={...rt,...A};B.resolveUrl||(B.resolveUrl=kA.resolveUrl.bind(kA));const g=new Tg(B);return await g.initializeEssentia(),B.algorithm==="pitch_crepe"&&await g.loadCrepeModel(B.crepeModelUrl),g}getConfig(){return{...this.config}}async initializeEssentia(){if(this.initialized)return;const B=(await Promise.resolve().then(()=>xs)).EssentiaWASM;await B.ready,this.essentiaWASM=B,this.algorithms=new B.EssentiaJS(!1),this.initialized=!0}async loadCrepeModel(A){if(this.config.enableModelCache!==!1)this.crepeModel=await lg.getOrFetchGraphModel(JA,A,{resolveUrl:this.config.resolveUrl,invalidateUrlCache:g=>kA.invalidateCacheForUrl(g),maxRetries:3,baseDelayMs:1e3});else{const g=await this.resolveUrlWithCache(A);let I=null;for(let E=0;E<3;E++)try{this.crepeModel=await JA.loadGraphModel(g);break}catch(i){I=i;const C=String(i).toLowerCase();if(!(C.includes("fetch")||C.includes("network")||C.includes("timeout")||C.includes("failed to fetch")||C.includes("networkerror"))||E===2)throw i;const e=1e3*Math.pow(2,E);console.warn(`[EssentiaPitchDetector] CREPE model load failed (attempt ${E+1}/3), retrying in ${e}ms...`,{originalUrl:A,resolvedUrl:g,error:String(i)}),await new Promise(o=>setTimeout(o,e))}if(!this.crepeModel)throw new Error(`Failed to load CREPE model from ${A}: ${I?.message??String(I)}`)}const B=JA.zeros([1,1024]);JA.tidy(()=>{this.crepeModel.execute(B)}),B.dispose(),console.log("[EssentiaPitchDetector] CREPE model loaded")}async resolveUrlWithCache(A){if(this.resolvedUrlCache.has(A))return this.resolvedUrlCache.get(A);if(!this.config.resolveUrl)return A;try{const B=await this.config.resolveUrl(A);return this.resolvedUrlCache.set(A,B),B!==A&&console.info("[EssentiaPitchDetector] Resolved URL to alternate gateway",{originalUrl:A,resolvedUrl:B}),B}catch(B){return console.warn("[EssentiaPitchDetector] URL resolution failed, using original URL",{url:A,error:String(B)}),this.resolvedUrlCache.set(A,A),A}}detectSignal(A,B){if(!this.initialized)throw new Error("EssentiaPitchDetector not initialized. Use create() factory method.");if(A.length===0)return[];switch(this.config.algorithm){case"predominant_melodia":return this.runPredominantMelodia(A,B);case"pitch_melodia":return this.runPitchMelodia(A,B);case"pitch_yin_probabilistic":return this.runPitchYinProbabilistic(A,B);case"multipitch_melodia":return this.runMultiPitchMelodia(A,B);case"multipitch_klapuri":return this.runMultiPitchKlapuri(A,B);case"pitch_crepe":return this.runCrepe(A,B);default:throw new Error(`Unknown algorithm: ${this.config.algorithm}`)}}runPredominantMelodia(A,B){const g=this.essentiaWASM.arrayToVector(A),I=this.algorithms.PredominantPitchMelodia(g,10,3,this.config.frameSize,!1,.8,this.config.hopSize,1,40,this.config.maxFrequency,100,this.config.minFrequency,20,.9,.9,27.5625,55,B,100,!1,.2),E=Array.from(this.essentiaWASM.vectorToArray(I.pitch)),i=Array.from(this.essentiaWASM.vectorToArray(I.pitchConfidence)),C=this.config.hopSize/B;return this.mapSingleF0(E,i,C)}runPitchMelodia(A,B){const g=this.essentiaWASM.arrayToVector(A),I=this.algorithms.PitchMelodia(g,10,3,this.config.frameSize,!1,.8,this.config.hopSize,1,40,this.config.maxFrequency,100,this.config.minFrequency,20,.9,.9,27.5625,55,B,100),E=Array.from(this.essentiaWASM.vectorToArray(I.pitch)),i=Array.from(this.essentiaWASM.vectorToArray(I.pitchConfidence)),C=this.config.hopSize/B;return this.mapSingleF0(E,i,C)}runPitchYinProbabilistic(A,B){const g=this.essentiaWASM.arrayToVector(A),I=this.algorithms.PitchYinProbabilistic(g,this.config.frameSize,this.config.hopSize,.1,"negative",!1,B),E=Array.from(this.essentiaWASM.vectorToArray(I.pitch)),i=Array.from(this.essentiaWASM.vectorToArray(I.voicedProbabilities)),C=this.config.hopSize/B;return E.map((a,e)=>{const o=e*C;if(a>0&&i[e]>.5){const s=Math.round(this.frequencyToMidi(a));return{timestamp:o,frequency:a,probability:i[e],isVoiced:!0,midiNote:s,noteName:this.midiToNoteName(s)}}return{timestamp:o,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}})}runMultiPitchMelodia(A,B){const g=this.essentiaWASM.arrayToVector(A),I=this.algorithms.MultiPitchMelodia(g,10,3,this.config.frameSize,!1,.8,this.config.hopSize,1,40,this.config.maxFrequency,100,this.config.minFrequency,20,.9,.9,27.5625,55,B,100);return this.mapMultiPitch(I.pitch,B)}runMultiPitchKlapuri(A,B){const g=this.essentiaWASM.arrayToVector(A),I=this.algorithms.MultiPitchKlapuri(g,10,this.config.frameSize,.8,this.config.hopSize,1,40,this.config.maxFrequency,this.config.minFrequency,10,55,B);return this.mapMultiPitch(I.pitch,B)}runCrepe(A,B){if(!this.crepeModel)throw new Error('CREPE model not loaded. Ensure algorithm is "pitch_crepe" and model URL is valid.');const g=16e3,I=1024,E=256,i=this.resampleSignal(A,B,g),C=Math.floor((i.length-I)/E)+1,a=E/g,e=32.7,o=[];for(let t=0;t<C;t++){const s=t*E,G=i.slice(s,s+I),n=t*a;let h;try{const d=JA.tidy(()=>{const y=JA.tensor(G,[1,I]);return this.crepeModel.execute(y).dataSync().slice()});let l=0,F=0,m=0;for(let y=0;y<360;y++){const p=d[y];l+=y*10*p,F+=p,p>m&&(m=p)}if(F>0&&m>.3){const y=l/F,p=e*Math.pow(2,y/1200),k=Math.round(this.frequencyToMidi(p));h={timestamp:n,frequency:p,probability:m,isVoiced:!0,midiNote:k,noteName:this.midiToNoteName(k)}}else h={timestamp:n,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}}catch(c){console.error(`[EssentiaPitchDetector] CREPE inference error at frame ${t}:`,c),h={timestamp:n,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}}o.push(h)}return o}mapSingleF0(A,B,g){return A.map((I,E)=>{const i=E*g;if(I>0){const C=Math.round(this.frequencyToMidi(I));return{timestamp:i,frequency:I,probability:B[E]??0,isVoiced:!0,midiNote:C,noteName:this.midiToNoteName(C)}}return{timestamp:i,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null}})}mapMultiPitch(A,B){const g=A.size(),I=this.config.hopSize/B,E=[];for(let i=0;i<g;i++){const C=A.get(i),e=Array.from(this.essentiaWASM.vectorToArray(C)).filter(t=>t>0).sort((t,s)=>t-s),o=i*I;if(e.length>0){const t=e[0],s=Math.round(this.frequencyToMidi(t)),G=e.slice(1).map(n=>({frequency:n,probability:1}));E.push({timestamp:o,frequency:t,probability:1,isVoiced:!0,midiNote:s,noteName:this.midiToNoteName(s),...G.length>0?{alternativeHypotheses:G}:{}})}else E.push({timestamp:o,frequency:0,probability:0,isVoiced:!1,midiNote:null,noteName:null})}return E}resampleSignal(A,B,g){if(B===g)return A;const I=B/g,E=Math.round(A.length/I),i=new Float32Array(E);for(let C=0;C<E;C++){const a=C*I,e=Math.floor(a),o=Math.min(e+1,A.length-1),t=a-e;i[C]=A[e]*(1-t)+A[o]*t}return i}frequencyToMidi(A){return Hd+12*Math.log2(A/fd)}midiToNoteName(A){const B=Math.floor(A/12)-1,g=Math.round(A)%12;return`${Nd[g]}${B}`}}const lt={targetSampleRate:44100,pitchDetector:{},pitchAlgorithm:"pitch_melodia",crepeModelUrl:iQ};class Dt{constructor(A={}){this.essentiaDetector=null,this.config={...lt,...A,pitchDetector:{...lt.pitchDetector,...A.pitchDetector}},this.fullSpectrumDetector=new ki({...this.config.pitchDetector,minFrequency:this.config.pitchDetector.minFrequency??80,maxFrequency:this.config.pitchDetector.maxFrequency??1e3,targetSampleRate:this.config.targetSampleRate,yinThreshold:this.config.pitchDetector.yinThreshold??.4})}getConfig(){return{...this.config}}async linkWithComposite(A,B){const g=this.config.targetSampleRate,E=Kg(B,g).data;let i,C;this.config.pitchAlgorithm==="pyin_legacy"?(i=this.fullSpectrumDetector.detectSignalRaw(E,g),C=this.fullSpectrumDetector.getConfig().hopSize/g):(this.essentiaDetector||(this.essentiaDetector=await Tg.create({algorithm:this.config.pitchAlgorithm,minFrequency:this.config.pitchDetector.minFrequency??80,maxFrequency:this.config.pitchDetector.maxFrequency??2e4,crepeModelUrl:this.config.crepeModelUrl,resolveUrl:this.config.resolveUrl}),console.log(`[PitchBeatLinker] Essentia detector initialized: ${this.config.pitchAlgorithm}`)),i=this.essentiaDetector.detectSignal(E,g),C=this.essentiaDetector.getConfig().hopSize/g),console.debug("[PitchBeatLinker] Full-spectrum analysis:",{detector:this.config.pitchAlgorithm==="pyin_legacy"?"pYIN":`essentia/${this.config.pitchAlgorithm}`,totalFrames:i.length,voicedFrames:i.filter(e=>e.isVoiced).length,signalLength:E.length,signalSampleRate:g});const a=[];for(const e of A.beats){const o=e.detectedTimestamp??e.timestamp,t=Math.round(o/C);let s=null,G=1/0,n=0;for(let h=0;h<i.length;h++){const c=i[h];if(!c.isVoiced)continue;const d=Math.abs(h-t);(d<G||d===G&&c.probability>n)&&(G=d,n=c.probability,s=c)}a.push({beatIndex:e.beatIndex,timestamp:e.timestamp,band:e.sourceBand,pitch:s,direction:"none",intervalFromPrevious:0})}return a}deriveVariantPitches(A,B){const g=[],I=new Map;for(const E of B){const i=Math.round(E.timestamp*1e3);I.set(i,E)}for(const E of A.beats){const i=Math.round(E.timestamp*1e3);let C=I.get(i);if(!C)for(let a=-2;a<=2&&(C=I.get(i+a),!C);a++);C?g.push({beatIndex:E.beatIndex,timestamp:E.timestamp,band:E.sourceBand,pitch:C.pitch,direction:C.direction,intervalFromPrevious:C.intervalFromPrevious,intervalCategory:C.intervalCategory}):g.push({beatIndex:E.beatIndex,timestamp:E.timestamp,band:E.sourceBand,pitch:null,direction:"none",intervalFromPrevious:0})}return g}deriveAllVariantPitches(A,B){return{easy:this.deriveVariantPitches(A.easy,B),medium:this.deriveVariantPitches(A.medium,B),hard:this.deriveVariantPitches(A.hard,B)}}}const Jd={maxTimeGapForConsecutive:.5};function dt(Q){return Q===0?"unison":Q<=2?"small":Q<=4?"medium":Q<=7?"large":"very_large"}function qd(Q,A){return Math.abs(Q-A)}function xd(Q,A){return Q===null||A===null?"none":Q>A?"up":Q<A?"down":"stable"}function Vd(Q){if(Q.length===0)return"stable";let A=0,B=0,g=0;for(const C of Q)C.direction==="up"?A++:C.direction==="down"?B++:g++;if(A===0&&B===0)return"stable";const I=A-B,i=(A+B+g)*.2;return Math.abs(I)<=i?"mixed":A>B?"ascending":B>A?"descending":"stable"}function Ft(Q){const A=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],B=Math.floor(Q/12)-1,g=Q%12;return`${A[g]}${B}`}class Ld{constructor(A={}){this.config={...Jd,...A}}getConfig(){return{...this.config}}analyze(A){const B=this.analyzeBandPitches(A),{directionStats:g,intervalStats:I,metadata:E}=this.calculateStatistics(B),i=this.buildMelodyContour(B);return{pitchByBeat:B,melodyContour:i,directionStats:g,intervalStats:I,metadata:E}}analyzeBandPitches(A){if(A.length===0)return[];const B=[];for(let g=0;g<A.length;g++){const I=A[g],E=g>0?A[g-1]:null,i=E!==null&&I.timestamp-E.timestamp<=this.config.maxTimeGapForConsecutive;let C,a,e;if(!i||!E||!E.pitch||!I.pitch)C="none",a=0,e="unison";else{const o=I.pitch.midiNote,t=E.pitch.midiNote;o===null||t===null?(C="none",a=0,e="unison"):(C=xd(o,t),a=qd(o,t),e=dt(a))}B.push({...I,direction:C,intervalFromPrevious:a,intervalCategory:e})}return B}buildMelodyContour(A){const B=A.filter(G=>G.pitch?.isVoiced);if(B.length===0)return{segments:[],direction:"stable",range:{minNote:"N/A",maxNote:"N/A",semitones:0},shortTermDirection:"stable",mediumTermDirection:"stable",longTermDirection:"stable"};const g=B.map(G=>G.pitch?.midiNote).filter(G=>G!==null);if(g.length===0)return{segments:[],direction:"stable",range:{minNote:"N/A",maxNote:"N/A",semitones:0},shortTermDirection:"stable",mediumTermDirection:"stable",longTermDirection:"stable"};const I=Math.min(...g),E=Math.max(...g),i=Ft(I),C=Ft(E),a=this.buildSegments(B),e=Vd(a),o=this.calculateTimeWindowDirection(A,1,2),t=this.calculateTimeWindowDirection(A,4,8),s=this.calculateTimeWindowDirection(A,16,1/0);return{segments:a,direction:e,range:{minNote:i,maxNote:C,semitones:E-I},shortTermDirection:o,mediumTermDirection:t,longTermDirection:s}}calculateTimeWindowDirection(A,B,g){if(A.length===0||B<1)return"stable";const I=Math.min(g,Math.max(B,A.length)),E=A.slice(-I);if(E.length===0)return"stable";let i=0,C=0,a=0;for(const e of E)e.direction==="up"?i++:e.direction==="down"?C++:e.direction==="stable"&&a++;return this.determineOverallDirectionFromCounts(i,C,a)}determineOverallDirectionFromCounts(A,B,g){const I=A+B+g;if(I===0)return"stable";const E=I*.2,i=A-B;return Math.abs(i)<=E?"mixed":A>B?"ascending":B>A?"descending":"stable"}buildSegments(A){if(A.length===0)return[];const B=[];let g=null;for(const I of A){const E=I.direction;if(E==="none"){g&&(B.push({startTime:g.startTime,endTime:g.endTime,startPitch:g.startPitch,endPitch:g.endPitch,direction:g.direction,interval:Math.abs(g.endMidi-g.startMidi)}),g=null);continue}if(!g||g.direction!==E){g&&B.push({startTime:g.startTime,endTime:g.endTime,startPitch:g.startPitch,endPitch:g.endPitch,direction:g.direction,interval:Math.abs(g.endMidi-g.startMidi)});const i=I.pitch?.noteName??"N/A",C=I.pitch?.midiNote??60;g={startTime:I.timestamp,endTime:I.timestamp,startPitch:i,endPitch:i,direction:E,startMidi:C,endMidi:C}}else{const i=I.pitch?.midiNote??g.endMidi,C=I.pitch?.noteName??g.endPitch;g.endTime=I.timestamp,g.endPitch=C,g.endMidi=i}}return g&&B.push({startTime:g.startTime,endTime:g.endTime,startPitch:g.startPitch,endPitch:g.endPitch,direction:g.direction,interval:Math.abs(g.endMidi-g.startMidi)}),B}calculateStatistics(A){const B={up:0,down:0,stable:0,none:0},g={unison:0,small:0,medium:0,large:0,very_large:0};let I=0,E=0;for(const i of A)i.pitch?.isVoiced&&I++,B[i.direction]++,i.direction!=="none"&&E++,i.intervalCategory&&g[i.intervalCategory]++;return{directionStats:B,intervalStats:g,metadata:{totalBeats:A.length,voicedBeats:I,directionCalculatedBeats:E}}}}const Xd={algorithm:"pitch_melodia",minFrequency:80,maxFrequency:2e4,sampleRate:44100,hopSize:1024,crepeModelUrl:iQ,resolveUrl:kA.resolveUrl.bind(kA),includeContour:!0,onProgress:void 0},vd=69,Kd=440,zd=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];class Td{constructor(A={}){this.config={...Xd,...A}}getConfig(){return{...this.config}}async analyze(A){const{onProgress:B}=this.config;B?.("fetching",0);const{signal:g,sampleRate:I,duration:E}=await this.fetchAndDecodeAudio(A);B?.("fetching",1),B?.("detecting",0);const i=this.resolveDefaults(this.config),C=await this.detectPitch(g,I,i);B?.("detecting",1);const a=this.computeSummary(C);let e,o,t;if(this.config.includeContour!==!1){const s=this.computeContour(C);e=s.contour,o=s.directionStats,t=s.intervalStats}return{pitchResults:C,contour:e,voicingRatio:a.voicingRatio,averageFrequency:a.averageFrequency,medianFrequency:a.medianFrequency,minFrequency:a.minFrequency,maxFrequency:a.maxFrequency,pitchRangeSemitones:a.pitchRangeSemitones,lowestNote:a.lowestNote,highestNote:a.highestNote,noteDistribution:a.noteDistribution,totalFrames:a.totalFrames,voicedFrames:a.voicedFrames,directionStats:o,intervalStats:t,analysis_metadata:{algorithm_used:this.config.algorithm,analyzed_at:new Date().toISOString(),duration_analyzed:E}}}async fetchAndDecodeAudio(A){const B=this.config.resolveUrl?await this.config.resolveUrl(A):A,g=await fetch(B);if(!g.ok)throw new Error(`Failed to fetch audio: ${g.statusText}`);const I=await g.arrayBuffer(),E=globalThis.AudioContext||globalThis.window?.AudioContext;if(!E)throw new Error("AudioContext not available in this environment");const i=new E,C=await new Promise((e,o)=>{i.decodeAudioData(I,e,o)}),a=new Float32Array(C.length);for(let e=0;e<C.numberOfChannels;e++){const o=C.getChannelData(e);for(let t=0;t<C.length;t++)a[t]+=o[t]/C.numberOfChannels}return{signal:a,sampleRate:C.sampleRate,duration:C.duration}}resolveDefaults(A){const B={...A};return A.maxFrequency===void 0&&(A.algorithm==="pyin_legacy"?B.maxFrequency=1e3:B.maxFrequency=2e4),B}async detectPitch(A,B,g){const I=g.algorithm??"pitch_melodia";return I==="pyin_legacy"?new ki({minFrequency:g.minFrequency??80,maxFrequency:g.maxFrequency??1e3,targetSampleRate:g.sampleRate??44100,hopSize:g.hopSize??1024}).detectSignal(A,B):(await Tg.create({algorithm:I,minFrequency:g.minFrequency??80,maxFrequency:g.maxFrequency??2e4,targetSampleRate:g.sampleRate??44100,hopSize:g.hopSize??1024,crepeModelUrl:g.crepeModelUrl,resolveUrl:g.resolveUrl})).detectSignal(A,B)}computeSummary(A){const B=A.length,g=A.filter(F=>F.isVoiced&&F.frequency>0),I=g.length;if(I===0)return{voicingRatio:0,averageFrequency:0,medianFrequency:0,minFrequency:0,maxFrequency:0,pitchRangeSemitones:0,lowestNote:null,highestNote:null,noteDistribution:[],totalFrames:B,voicedFrames:0};const E=g.map(F=>F.frequency),i=[...E].sort((F,m)=>F-m),C=E.reduce((F,m)=>F+m,0)/E.length,a=Math.floor(i.length/2),e=i.length%2!==0?i[a]:(i[a-1]+i[a])/2,o=i[0],t=i[i.length-1],s=this.frequencyToMidi(o),G=this.frequencyToMidi(t),n=Math.abs(G-s),h=this.midiToNoteName(Math.round(s)),c=this.midiToNoteName(Math.round(G)),d=new Map;for(const F of g)F.noteName&&d.set(F.noteName,(d.get(F.noteName)??0)+1);const l=Array.from(d.entries()).map(([F,m])=>({note:F,count:m,percentage:m/I*100})).sort((F,m)=>m.count-F.count);return{voicingRatio:I/B,averageFrequency:C,medianFrequency:e,minFrequency:o,maxFrequency:t,pitchRangeSemitones:n,lowestNote:h,highestNote:c,noteDistribution:l,totalFrames:B,voicedFrames:I}}computeContour(A){const B=A.filter(d=>d.isVoiced&&d.midiNote!==null);if(B.length===0)return{contour:{direction:"stable",range:{minNote:"N/A",maxNote:"N/A",semitones:0},segments:[],shortTermDirection:"stable",mediumTermDirection:"stable",longTermDirection:"stable"},directionStats:{up:0,down:0,stable:0,none:A.length},intervalStats:{unison:0,small:0,medium:0,large:0,very_large:0}};const g=B.map(d=>d.midiNote).filter(d=>d!==null),I=Math.min(...g),E=Math.max(...g),i=this.midiToNoteName(I),C=this.midiToNoteName(E),a={up:0,down:0,stable:0,none:0},e={unison:0,small:0,medium:0,large:0,very_large:0},o=[];let t=null,s=null;for(const d of B){const l=d.midiNote;if(l===null){a.none++;continue}if(s===null){s=l;continue}let F;const m=Math.abs(l-s);l>s?(F="up",a.up++):l<s?(F="down",a.down++):(F="stable",a.stable++);const y=dt(m);e[y]++,!t||t.direction!==F?(t&&o.push({startTime:t.startTime,endTime:t.endTime,startNote:t.startNote,endNote:t.endNote,direction:t.direction,interval:Math.abs(t.endMidi-t.startMidi)}),t={startTime:d.timestamp,endTime:d.timestamp,startNote:this.midiToNoteName(s),endNote:this.midiToNoteName(l),direction:F,startMidi:s,endMidi:l}):(t.endTime=d.timestamp,t.endNote=this.midiToNoteName(l),t.endMidi=l),s=l}t&&o.push({startTime:t.startTime,endTime:t.endTime,startNote:t.startNote,endNote:t.endNote,direction:t.direction,interval:Math.abs(t.endMidi-t.startMidi)});const G=this.determineOverallDirection(o),n=this.calculateTimeWindowDirection(A,1,2),h=this.calculateTimeWindowDirection(A,4,8),c=this.calculateTimeWindowDirection(A,16,1/0);return{contour:{direction:G,range:{minNote:i,maxNote:C,semitones:E-I},segments:o,shortTermDirection:n,mediumTermDirection:h,longTermDirection:c},directionStats:a,intervalStats:e}}determineOverallDirection(A){if(A.length===0)return"stable";let B=0,g=0,I=0;for(const a of A)a.direction==="up"?B++:a.direction==="down"?g++:I++;if(B===0&&g===0)return"stable";const E=B-g,C=(B+g+I)*.2;return Math.abs(E)<=C?"mixed":B>g?"ascending":g>B?"descending":"stable"}calculateTimeWindowDirection(A,B,g){const I=A.filter(t=>t.isVoiced&&t.midiNote!==null);if(I.length===0||B<1)return"stable";const E=Math.min(g,Math.max(B,I.length)),i=I.slice(-E);if(i.length===0)return"stable";let C=0,a=0,e=0,o=null;for(const t of i){const s=t.midiNote;s!==null&&(o!==null&&(s>o?C++:s<o?a++:e++),o=s)}return this.determineOverallDirectionFromCounts(C,a,e)}determineOverallDirectionFromCounts(A,B,g){const I=A+B+g;if(I===0)return"stable";const E=I*.2,i=A-B;return Math.abs(i)<=E?"mixed":A>B?"ascending":B>A?"descending":"stable"}frequencyToMidi(A){return vd+12*Math.log2(A/Kd)}midiToNoteName(A){const B=Math.floor(A/12)-1,g=Math.round(A)%12;return`${zd[g]}${B}`}}const jd=[{id:"ddr_basic_single_up",name:"Single Up",controllerMode:"ddr",keys:["up"],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"ddr_basic_single_down",name:"Single Down",controllerMode:"ddr",keys:["down"],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"ddr_basic_single_left",name:"Single Left",controllerMode:"ddr",keys:["left"],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"ddr_basic_single_right",name:"Single Right",controllerMode:"ddr",keys:["right"],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"ddr_basic_alternating_up_down",name:"Alternating Up-Down",controllerMode:"ddr",keys:["up","down","up","down"],measures:1,tags:["basic","alternating","vertical"],category:"basic",difficulty:2},{id:"ddr_basic_alternating_left_right",name:"Alternating Left-Right",controllerMode:"ddr",keys:["left","right","left","right"],measures:1,tags:["basic","alternating","horizontal"],category:"basic",difficulty:2},{id:"ddr_basic_alternating_up_left",name:"Alternating Up-Left",controllerMode:"ddr",keys:["up","left","up","left"],measures:1,tags:["basic","alternating"],category:"basic",difficulty:2},{id:"ddr_basic_alternating_down_right",name:"Alternating Down-Right",controllerMode:"ddr",keys:["down","right","down","right"],measures:1,tags:["basic","alternating"],category:"basic",difficulty:2},{id:"ddr_basic_double_up",name:"Double Up",controllerMode:"ddr",keys:["up","up","down","down"],measures:1,tags:["basic","double","repeat"],category:"basic",difficulty:2},{id:"ddr_basic_double_left",name:"Double Left",controllerMode:"ddr",keys:["left","left","right","right"],measures:1,tags:["basic","double","repeat"],category:"basic",difficulty:2},{id:"ddr_basic_walk_forward",name:"Walk Forward",controllerMode:"ddr",keys:["left","right","left","right"],measures:1,tags:["basic","walk","horizontal"],category:"basic",difficulty:2},{id:"ddr_basic_walk_vertical",name:"Walk Vertical",controllerMode:"ddr",keys:["up","down","up","down"],measures:1,tags:["basic","walk","vertical"],category:"basic",difficulty:2}],Od=[{id:"ddr_roll_clockwise_full",name:"Clockwise Full Roll",controllerMode:"ddr",keys:["up","right","down","left"],measures:1,tags:["roll","clockwise","full"],category:"roll",difficulty:3},{id:"ddr_roll_clockwise_extended",name:"Clockwise Extended Roll",controllerMode:"ddr",keys:["up","right","down","left","up","right","down","left"],measures:2,tags:["roll","clockwise","extended"],category:"roll",difficulty:4},{id:"ddr_roll_counterclockwise_full",name:"Counter-Clockwise Full Roll",controllerMode:"ddr",keys:["up","left","down","right"],measures:1,tags:["roll","counterclockwise","full"],category:"roll",difficulty:3},{id:"ddr_roll_counterclockwise_extended",name:"Counter-Clockwise Extended Roll",controllerMode:"ddr",keys:["up","left","down","right","up","left","down","right"],measures:2,tags:["roll","counterclockwise","extended"],category:"roll",difficulty:4},{id:"ddr_roll_half_right",name:"Half Roll Right",controllerMode:"ddr",keys:["up","right","down"],measures:1,tags:["roll","half","right"],category:"roll",difficulty:3},{id:"ddr_roll_half_left",name:"Half Roll Left",controllerMode:"ddr",keys:["up","left","down"],measures:1,tags:["roll","half","left"],category:"roll",difficulty:3},{id:"ddr_roll_bottom_half_right",name:"Bottom Half Roll Right",controllerMode:"ddr",keys:["down","right","up"],measures:1,tags:["roll","half","bottom","right"],category:"roll",difficulty:3},{id:"ddr_roll_bottom_half_left",name:"Bottom Half Roll Left",controllerMode:"ddr",keys:["down","left","up"],measures:1,tags:["roll","half","bottom","left"],category:"roll",difficulty:3},{id:"ddr_roll_triangle_up",name:"Triangle Roll Up",controllerMode:"ddr",keys:["left","up","right"],measures:1,tags:["roll","triangle","top"],category:"roll",difficulty:3},{id:"ddr_roll_triangle_down",name:"Triangle Roll Down",controllerMode:"ddr",keys:["left","down","right"],measures:1,tags:["roll","triangle","bottom"],category:"roll",difficulty:3}],Pd=[{id:"ddr_stream_vertical_8",name:"Vertical Stream 8",controllerMode:"ddr",keys:["up","down","up","down","up","down","up","down"],measures:2,tags:["stream","vertical","fast"],category:"stream",difficulty:5},{id:"ddr_stream_vertical_16",name:"Vertical Stream 16",controllerMode:"ddr",keys:["up","down","up","down","up","down","up","down","up","down","up","down","up","down","up","down"],measures:4,tags:["stream","vertical","extended"],category:"stream",difficulty:7},{id:"ddr_stream_horizontal_8",name:"Horizontal Stream 8",controllerMode:"ddr",keys:["left","right","left","right","left","right","left","right"],measures:2,tags:["stream","horizontal","fast"],category:"stream",difficulty:5},{id:"ddr_stream_diagonal_1",name:"Diagonal Stream 1",controllerMode:"ddr",keys:["up","right","up","right","up","right","up","right"],measures:2,tags:["stream","diagonal"],category:"stream",difficulty:5},{id:"ddr_stream_diagonal_2",name:"Diagonal Stream 2",controllerMode:"ddr",keys:["up","left","up","left","up","left","up","left"],measures:2,tags:["stream","diagonal"],category:"stream",difficulty:5},{id:"ddr_stream_diagonal_3",name:"Diagonal Stream 3",controllerMode:"ddr",keys:["down","right","down","right","down","right","down","right"],measures:2,tags:["stream","diagonal"],category:"stream",difficulty:5},{id:"ddr_stream_diagonal_4",name:"Diagonal Stream 4",controllerMode:"ddr",keys:["down","left","down","left","down","left","down","left"],measures:2,tags:["stream","diagonal"],category:"stream",difficulty:5},{id:"ddr_stream_mixed_box",name:"Box Stream",controllerMode:"ddr",keys:["up","right","down","left","up","right","down","left"],measures:2,tags:["stream","box","circular"],category:"stream",difficulty:6},{id:"ddr_stream_mixed_zigzag",name:"Zigzag Stream",controllerMode:"ddr",keys:["up","left","down","right","up","left","down","right"],measures:2,tags:["stream","zigzag"],category:"stream",difficulty:6}],_d=[{id:"ddr_jump_opposite_vertical",name:"Opposite Jump Vertical",controllerMode:"ddr",keys:["up","down","up","down"],measures:1,tags:["jump","opposite","vertical"],category:"jump",difficulty:4},{id:"ddr_jump_opposite_horizontal",name:"Opposite Jump Horizontal",controllerMode:"ddr",keys:["left","right","left","right"],measures:1,tags:["jump","opposite","horizontal"],category:"jump",difficulty:4},{id:"ddr_jump_diagonal_1",name:"Diagonal Jump 1",controllerMode:"ddr",keys:["up","left","up","left"],measures:1,tags:["jump","diagonal"],category:"jump",difficulty:4},{id:"ddr_jump_diagonal_2",name:"Diagonal Jump 2",controllerMode:"ddr",keys:["up","right","up","right"],measures:1,tags:["jump","diagonal"],category:"jump",difficulty:4},{id:"ddr_jump_diagonal_3",name:"Diagonal Jump 3",controllerMode:"ddr",keys:["down","left","down","left"],measures:1,tags:["jump","diagonal"],category:"jump",difficulty:4},{id:"ddr_jump_diagonal_4",name:"Diagonal Jump 4",controllerMode:"ddr",keys:["down","right","down","right"],measures:1,tags:["jump","diagonal"],category:"jump",difficulty:4},{id:"ddr_jump_cross_pattern",name:"Cross Pattern",controllerMode:"ddr",keys:["up","left","down","right"],measures:1,tags:["jump","cross"],category:"jump",difficulty:5},{id:"ddr_jump_x_pattern",name:"X Pattern",controllerMode:"ddr",keys:["up","right","down","left"],measures:1,tags:["jump","x"],category:"jump",difficulty:5},{id:"ddr_jump_leap_sequence",name:"Leap Sequence",controllerMode:"ddr",keys:["up","down","left","right","up","down"],measures:2,tags:["jump","leap","sequence"],category:"jump",difficulty:6},{id:"ddr_jump_corner_to_corner",name:"Corner to Corner",controllerMode:"ddr",keys:["up","right","down","left","up","right"],measures:2,tags:["jump","corner"],category:"jump",difficulty:6}],$d=[{id:"ddr_transition_build_up",name:"Build Up",controllerMode:"ddr",keys:["left","left","up","up","right","right"],measures:2,tags:["transition","build-up","intensity"],category:"transition",difficulty:4},{id:"ddr_transition_wind_down",name:"Wind Down",controllerMode:"ddr",keys:["right","right","up","up","left","left"],measures:2,tags:["transition","wind-down"],category:"transition",difficulty:4},{id:"ddr_transition_fill_4",name:"Fill 4 Count",controllerMode:"ddr",keys:["up","right","down","left"],measures:1,tags:["transition","fill"],category:"transition",difficulty:3},{id:"ddr_transition_fill_8",name:"Fill 8 Count",controllerMode:"ddr",keys:["up","up","right","right","down","down","left","left"],measures:2,tags:["transition","fill","extended"],category:"transition",difficulty:4}],AF=[{id:"gh_basic_single_1",name:"Single Fret 1",controllerMode:"guitar_hero",keys:[1],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"gh_basic_single_2",name:"Single Fret 2",controllerMode:"guitar_hero",keys:[2],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"gh_basic_single_3",name:"Single Fret 3",controllerMode:"guitar_hero",keys:[3],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"gh_basic_single_4",name:"Single Fret 4",controllerMode:"guitar_hero",keys:[4],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"gh_basic_single_5",name:"Single Fret 5",controllerMode:"guitar_hero",keys:[5],measures:1,tags:["basic","single","beginner"],category:"basic",difficulty:1},{id:"gh_basic_ascending_full",name:"Ascending Full Run",controllerMode:"guitar_hero",keys:[1,2,3,4,5],measures:1,tags:["basic","ascending","full"],category:"basic",difficulty:3},{id:"gh_basic_ascending_quad",name:"Ascending Quad",controllerMode:"guitar_hero",keys:[1,2,3,4],measures:1,tags:["basic","ascending"],category:"basic",difficulty:2},{id:"gh_basic_ascending_tri_low",name:"Ascending Tri Low",controllerMode:"guitar_hero",keys:[1,2,3],measures:1,tags:["basic","ascending","tri"],category:"basic",difficulty:2},{id:"gh_basic_ascending_tri_mid",name:"Ascending Tri Mid",controllerMode:"guitar_hero",keys:[2,3,4],measures:1,tags:["basic","ascending","tri"],category:"basic",difficulty:2},{id:"gh_basic_ascending_tri_high",name:"Ascending Tri High",controllerMode:"guitar_hero",keys:[3,4,5],measures:1,tags:["basic","ascending","tri"],category:"basic",difficulty:2},{id:"gh_basic_descending_full",name:"Descending Full Run",controllerMode:"guitar_hero",keys:[5,4,3,2,1],measures:1,tags:["basic","descending","full"],category:"basic",difficulty:3},{id:"gh_basic_descending_quad",name:"Descending Quad",controllerMode:"guitar_hero",keys:[5,4,3,2],measures:1,tags:["basic","descending"],category:"basic",difficulty:2},{id:"gh_basic_descending_tri_high",name:"Descending Tri High",controllerMode:"guitar_hero",keys:[5,4,3],measures:1,tags:["basic","descending","tri"],category:"basic",difficulty:2},{id:"gh_basic_descending_tri_mid",name:"Descending Tri Mid",controllerMode:"guitar_hero",keys:[4,3,2],measures:1,tags:["basic","descending","tri"],category:"basic",difficulty:2},{id:"gh_basic_descending_tri_low",name:"Descending Tri Low",controllerMode:"guitar_hero",keys:[3,2,1],measures:1,tags:["basic","descending","tri"],category:"basic",difficulty:2},{id:"gh_basic_step_up",name:"Step Up",controllerMode:"guitar_hero",keys:[1,2,3,4],measures:1,tags:["basic","step","up"],category:"basic",difficulty:2},{id:"gh_basic_step_down",name:"Step Down",controllerMode:"guitar_hero",keys:[5,4,3,2],measures:1,tags:["basic","step","down"],category:"basic",difficulty:2}],BF=[{id:"gh_alternating_1_3",name:"Alternating 1-3",controllerMode:"guitar_hero",keys:[1,3,1,3],measures:1,tags:["alternating","skip"],category:"basic",difficulty:3},{id:"gh_alternating_2_4",name:"Alternating 2-4",controllerMode:"guitar_hero",keys:[2,4,2,4],measures:1,tags:["alternating","skip"],category:"basic",difficulty:3},{id:"gh_alternating_3_5",name:"Alternating 3-5",controllerMode:"guitar_hero",keys:[3,5,3,5],measures:1,tags:["alternating","skip"],category:"basic",difficulty:3},{id:"gh_alternating_1_2",name:"Alternating 1-2",controllerMode:"guitar_hero",keys:[1,2,1,2],measures:1,tags:["alternating","adjacent"],category:"basic",difficulty:2},{id:"gh_alternating_2_3",name:"Alternating 2-3",controllerMode:"guitar_hero",keys:[2,3,2,3],measures:1,tags:["alternating","adjacent"],category:"basic",difficulty:2},{id:"gh_alternating_3_4",name:"Alternating 3-4",controllerMode:"guitar_hero",keys:[3,4,3,4],measures:1,tags:["alternating","adjacent"],category:"basic",difficulty:2},{id:"gh_alternating_4_5",name:"Alternating 4-5",controllerMode:"guitar_hero",keys:[4,5,4,5],measures:1,tags:["alternating","adjacent"],category:"basic",difficulty:2},{id:"gh_alternating_tri_1_3_5",name:"Alternating 1-3-5",controllerMode:"guitar_hero",keys:[1,3,5,3],measures:1,tags:["alternating","tri","wide"],category:"basic",difficulty:4},{id:"gh_alternating_tri_1_2_3",name:"Alternating 1-2-3",controllerMode:"guitar_hero",keys:[1,2,3,2],measures:1,tags:["alternating","tri","tight"],category:"basic",difficulty:3},{id:"gh_alternating_tri_3_4_5",name:"Alternating 3-4-5",controllerMode:"guitar_hero",keys:[3,4,5,4],measures:1,tags:["alternating","tri","tight"],category:"basic",difficulty:3},{id:"gh_alternating_extended_1_3",name:"Extended Alternating 1-3",controllerMode:"guitar_hero",keys:[1,3,1,3,1,3,1,3],measures:2,tags:["alternating","extended"],category:"basic",difficulty:4},{id:"gh_alternating_extended_2_4",name:"Extended Alternating 2-4",controllerMode:"guitar_hero",keys:[2,4,2,4,2,4,2,4],measures:2,tags:["alternating","extended"],category:"basic",difficulty:4}],gF=[{id:"gh_chord_power_full",name:"Power Chord Full",controllerMode:"guitar_hero",keys:[1,3,5],measures:1,tags:["chord","power","full"],category:"chord",difficulty:4},{id:"gh_chord_power_low",name:"Power Chord Low",controllerMode:"guitar_hero",keys:[1,3],measures:1,tags:["chord","power","low"],category:"chord",difficulty:3},{id:"gh_chord_power_mid",name:"Power Chord Mid",controllerMode:"guitar_hero",keys:[2,4],measures:1,tags:["chord","power","mid"],category:"chord",difficulty:3},{id:"gh_chord_power_high",name:"Power Chord High",controllerMode:"guitar_hero",keys:[3,5],measures:1,tags:["chord","power","high"],category:"chord",difficulty:3},{id:"gh_chord_triad_low",name:"Triad Low",controllerMode:"guitar_hero",keys:[1,2,3],measures:1,tags:["chord","triad","low"],category:"chord",difficulty:4},{id:"gh_chord_triad_mid",name:"Triad Mid",controllerMode:"guitar_hero",keys:[2,3,4],measures:1,tags:["chord","triad","mid"],category:"chord",difficulty:4},{id:"gh_chord_triad_high",name:"Triad High",controllerMode:"guitar_hero",keys:[3,4,5],measures:1,tags:["chord","triad","high"],category:"chord",difficulty:4},{id:"gh_chord_progression_1",name:"Chord Progression 1",controllerMode:"guitar_hero",keys:[1,3,2,4,3,5],measures:2,tags:["chord","progression"],category:"chord",difficulty:5},{id:"gh_chord_progression_2",name:"Chord Progression 2",controllerMode:"guitar_hero",keys:[1,2,3,4,5,4,3,2],measures:2,tags:["chord","progression","wave"],category:"chord",difficulty:5}],IF=[{id:"gh_jump_wide_1_4",name:"Wide Jump 1-4",controllerMode:"guitar_hero",keys:[1,4,1,4],measures:1,tags:["jump","wide"],category:"jump",difficulty:4},{id:"gh_jump_wide_2_5",name:"Wide Jump 2-5",controllerMode:"guitar_hero",keys:[2,5,2,5],measures:1,tags:["jump","wide"],category:"jump",difficulty:4},{id:"gh_jump_wide_1_5",name:"Wide Jump 1-5",controllerMode:"guitar_hero",keys:[1,5,1,5],measures:1,tags:["jump","widest"],category:"jump",difficulty:5},{id:"gh_jump_shift_up",name:"Position Shift Up",controllerMode:"guitar_hero",keys:[1,2,4,5],measures:1,tags:["jump","shift","up"],category:"jump",difficulty:4},{id:"gh_jump_shift_down",name:"Position Shift Down",controllerMode:"guitar_hero",keys:[5,4,2,1],measures:1,tags:["jump","shift","down"],category:"jump",difficulty:4},{id:"gh_jump_leap_sequence",name:"Leap Sequence",controllerMode:"guitar_hero",keys:[1,3,5,3,1,3,5],measures:2,tags:["jump","leap","sequence"],category:"jump",difficulty:5},{id:"gh_jump_bounce",name:"Bounce Pattern",controllerMode:"guitar_hero",keys:[1,5,2,4,3],measures:1,tags:["jump","bounce"],category:"jump",difficulty:5},{id:"gh_jump_stretch_1_4_5",name:"Stretch 1-4-5",controllerMode:"guitar_hero",keys:[1,4,5,4],measures:1,tags:["jump","stretch"],category:"jump",difficulty:5},{id:"gh_jump_stretch_1_2_5",name:"Stretch 1-2-5",controllerMode:"guitar_hero",keys:[1,2,5,2],measures:1,tags:["jump","stretch"],category:"jump",difficulty:5}],QF=[{id:"gh_transition_build_up",name:"Build Up",controllerMode:"guitar_hero",keys:[1,1,2,2,3,3,4,4,5],measures:2,tags:["transition","build-up"],category:"transition",difficulty:4},{id:"gh_transition_wind_down",name:"Wind Down",controllerMode:"guitar_hero",keys:[5,5,4,4,3,3,2,2,1],measures:2,tags:["transition","wind-down"],category:"transition",difficulty:4},{id:"gh_transition_fill_ascending",name:"Fill Ascending",controllerMode:"guitar_hero",keys:[1,2,3,4,5],measures:1,tags:["transition","fill","ascending"],category:"transition",difficulty:3},{id:"gh_transition_fill_descending",name:"Fill Descending",controllerMode:"guitar_hero",keys:[5,4,3,2,1],measures:1,tags:["transition","fill","descending"],category:"transition",difficulty:3},{id:"gh_transition_fill_wave",name:"Fill Wave",controllerMode:"guitar_hero",keys:[1,3,5,3,1],measures:1,tags:["transition","fill","wave"],category:"transition",difficulty:4},{id:"gh_transition_end_resolve",name:"End Resolve",controllerMode:"guitar_hero",keys:[5,4,3,2,1,1],measures:2,tags:["transition","resolve","end"],category:"transition",difficulty:3}],EF=[...jd,...Od,...Pd,..._d,...$d],iF=[...AF,...BF,...gF,...IF,...QF];function Mt(Q,A){const B=new Map,g=["basic","roll","stream","jump","chord","transition"];for(const E of g){const i=A.filter(C=>C.category===E);i.length>0&&B.set(E,i)}const I=new Map;for(let E=1;E<=10;E++){const i=A.filter(C=>C.difficulty===E);i.length>0&&I.set(E,i)}return{controllerMode:Q,patterns:A,byCategory:B,byDifficulty:I}}const Zi=Mt("ddr",EF),Wi=Mt("guitar_hero",iF);function CF(Q){return Q==="ddr"?Zi:Wi}function aF(Q,A){return Q.byCategory.get(A)??[]}function eF(Q,A=1,B=10){const g=[];for(let I=A;I<=B;I++){const E=Q.byDifficulty.get(I);E&&g.push(...E)}return g}function oF(Q,A){return Q.patterns.filter(B=>A.every(g=>B.tags.includes(g)))}function tF(Q,A){return Q.patterns.filter(B=>B.keys.length===A)}function sF(Q,A){const B=A?Q.patterns.filter(A):Q.patterns;if(B.length===0)return;const g=Math.floor(Math.random()*B.length);return B[g]}function GF(Q,A){return Q.patterns.find(B=>B.id===A)}function nF(Q){const A={basic:0,roll:0,stream:0,jump:0,chord:0,transition:0},B={};for(let i=1;i<=10;i++)B[i]=0;let g=0,I=1/0,E=0;for(const i of Q.patterns)A[i.category]++,B[i.difficulty]++,g+=i.keys.length,I=Math.min(I,i.keys.length),E=Math.max(E,i.keys.length);return{totalPatterns:Q.patterns.length,byCategory:A,byDifficulty:B,averageKeyCount:Q.patterns.length>0?g/Q.patterns.length:0,minKeys:I===1/0?0:I,maxKeys:E}}const wt={up:{ascending:{unison:"up",small:"up",medium:"right",large:"right",very_large:"left"},descending:{unison:"up",small:"left",medium:"right",large:"down",very_large:"down"},stable:"up"},right:{ascending:{unison:"right",small:"up",medium:"up",large:"up",very_large:"left"},descending:{unison:"right",small:"down",medium:"down",large:"down",very_large:"left"},stable:"right"},down:{ascending:{unison:"down",small:"left",medium:"right",large:"up",very_large:"up"},descending:{unison:"down",small:"down",medium:"left",large:"left",very_large:"right"},stable:"down"},left:{ascending:{unison:"left",small:"up",medium:"up",large:"up",very_large:"right"},descending:{unison:"left",small:"down",medium:"down",large:"down",very_large:"right"},stable:"left"}},hF={up:{ascending:"up",descending:"left",stable:"up"},right:{ascending:"up",descending:"down",stable:"right"},down:{ascending:"right",descending:"down",stable:"down"},left:{ascending:"up",descending:"down",stable:"left"}},yt={1:{ascending:{unison:1,small:2,medium:2,large:3,very_large:3},descending:{unison:1,small:4,medium:4,large:3,very_large:3},stable:1},2:{ascending:{unison:2,small:3,medium:3,large:4,very_large:4},descending:{unison:2,small:1,medium:1,large:4,very_large:4},stable:2},3:{ascending:{unison:3,small:4,medium:4,large:5,very_large:5},descending:{unison:3,small:2,medium:2,large:1,very_large:1},stable:3},4:{ascending:{unison:4,small:5,medium:5,large:2,very_large:2},descending:{unison:4,small:3,medium:3,large:2,very_large:1},stable:4},5:{ascending:{unison:5,small:2,medium:2,large:3,very_large:3},descending:{unison:5,small:4,medium:4,large:3,very_large:2},stable:5}},cF={1:{ascending:2,descending:1,stable:1},2:{ascending:3,descending:1,stable:2},3:{ascending:4,descending:2,stable:3},4:{ascending:5,descending:3,stable:4},5:{ascending:5,descending:4,stable:5}};function Rt(Q){return Q.intervalCategory??"small"}function rF(Q,A,B){const g=A??"left";if(Q.direction==="stable"||Q.intervalCategory==="unison")return g;if(B==="easy"){const C=hF[g];return Q.direction==="up"?C.ascending:C.descending}const I=wt[g],E=Q.direction==="up"?"ascending":"descending",i=Rt(Q);return I[E][i]}function lF(Q,A,B){const g=A??3;if(Q.direction==="stable"||Q.intervalCategory==="unison")return g;if(B==="easy"){const C=cF[g];return Q.direction==="up"?C.ascending:C.descending}const I=yt[g],E=Q.direction==="up"?"ascending":"descending",i=Rt(Q);return I[E][i]}function DF(Q,A,B,g){const I=new Map;if(A)for(const a of A){const e=Math.round(a.timestamp*1e3);I.set(e,a)}const E=[],i=[];let C=null;for(const a of Q){const e=Math.round(a.timestamp*1e3);let o=null;for(let G=-2;G<=2&&(o=I.get(e+G)??null,!o);G++);let t=null,s=0;o&&o.direction!=="none"&&(t=B==="ddr"?rF(o,C,g):lF(o,C,g),s=o.pitch?.probability??.5),E.push(t),i.push(s),C=t}return{pitchKeys:E,probabilities:i}}function dF(Q){const A=[];let B=-1;for(let g=0;g<=Q.length;g++){const I=g<Q.length&&Q[g]===null;if(I&&B===-1)B=g;else if(!I&&B!==-1){const E=B>0?Q[B-1]:null,i=g<Q.length?Q[g]:null;A.push({startIndex:B,endIndex:g,length:g-B,previousKey:E,nextKey:i}),B=-1}}return A}function CQ(Q,A,B,g,I){if(Q.keys.length===0||B+Q.keys.length>A.length)return!1;const E=Q.keys[0],i=Q.keys[Q.keys.length-1];if(g!==null&&E===g)return!1;if(I!==null){if(typeof i=="string"&&typeof I=="string"&&!jg[i]?.includes(I)&&i!==I)return!1;if(typeof i=="number"&&typeof I=="number"){if(g!==null&&typeof g=="number"){if(!(g<I&&i>=g&&i<=I||g>I&&i<=g&&i>=I)&&i!==I)return!1}else if(Math.abs(i-I)>1)return!1}}return!0}function FF(Q,A,B,g,I){const E=[],i=A.filter(s=>s.difficulty<=B&&s.keys.length>0);i.sort((s,G)=>G.keys.length-s.keys.length);const C=i[0]?.controllerMode??"ddr";let a=0,e=Q.previousKey,o=null,t=null;for(;a<Q.length;){const s=Q.length-a;let G;const n=i.filter(h=>h.keys.length===s);if(G=Hi(n,Q,a,e,Q.nextKey,o,t,g,I),!G){const h=i.filter(c=>c.keys.length<=s);G=Hi(h,Q,a,e,null,o,t,g,I)}if(!G){const h=i.filter(c=>c.keys.length<=s);G=Hi(h,Q,a,e,null,null,null,null,I)}if(G)E.push({pattern:G,startIndex:Q.startIndex+a,filledLength:G.keys.length}),e=G.keys[G.keys.length-1],o=G.id,t=G.category,a+=G.keys.length;else{const h=a===Q.length-1?Q.nextKey:null,c=mt(e,h);E.push({pattern:{id:"__interpolated__",name:"Interpolated",controllerMode:C,keys:[c],measures:0,tags:["interpolated"],category:"transition",difficulty:1},startIndex:Q.startIndex+a,filledLength:1}),e=c,a++}}return E}function Hi(Q,A,B,g,I,E,i,C,a=Math.random){const e=Q.filter(G=>CQ(G,A,B,g,I)&&G.id!==E&&G.category!==i&&!C?.has(G.id));if(e.length>0)return aQ(e,a);const o=Q.filter(G=>CQ(G,A,B,g,I)&&G.id!==E&&!C?.has(G.id));if(o.length>0)return aQ(o,a);const t=Q.filter(G=>CQ(G,A,B,g,I)&&G.id!==E);if(t.length>0)return aQ(t,a);const s=Q.filter(G=>CQ(G,A,B,g,I));if(s.length>0)return aQ(s,a)}function aQ(Q,A=Math.random){const B=Q[0].keys.length,g=Q.filter(I=>I.keys.length===B);return g[Math.floor(A()*g.length)]}function MF(Q,A,B){const g=Q.length,I=[...Q],E=new Array(g).fill(void 0);for(let i=0;i<A.length;i++){const C=B[i];for(const a of C)for(let e=0;e<a.filledLength;e++){const o=a.startIndex+e;if(o>=g)break;I[o]=a.pattern.keys[e],E[o]=a.pattern.id}}for(let i=0;i<g;i++)if(I[i]===null){const C=i>0?I[i-1]:null,a=i<g-1?I[i+1]:null;I[i]=mt(C,a)}return{keys:I,patternIds:E}}function wF(Q,A){const B=[];if(A<=0||Q.length===0)return{positions:B};let g=1;const I=Q[0];for(let E=1;E<Q.length;E++)Q[E]===I?(g++,g>A&&B.push(E)):g=1;return{positions:B}}function yF(Q,A,B,g=Math.random){const I=A.filter(C=>C.difficulty<=B);if(I.length===0)return Q;const E=I.filter(C=>C.keys[0]!==Q),i=E.length>0?E:I;return i[Math.floor(g()*i.length)].keys[0]}const jg={up:["left","right"],down:["left","right"],left:["up","down"],right:["up","down"]};function mt(Q,A){if(Q===null)return A===null?typeof A=="string"?"left":3:typeof A=="string"?jg[A][0]:Math.max(1,A-1);if(A===null)return Q;if(typeof Q=="string"&&typeof A=="string"){const B=Q,g=A;if(B===g)return Q;if(jg[B].includes(g))return A;const E=jg[B],i=jg[g];for(const C of E)if(i.includes(C))return C;return E[0]}if(typeof Q=="number"&&typeof A=="number"){const B=Q,g=A;return B===g?Q:g>B?Math.min(5,B+1):Math.max(1,B-1)}return Q}class eQ{constructor(A){this.config=sE(A);const B=Qa(this.config);if(!B.valid)throw new Error(`Invalid button mapping config: ${B.errors.join(", ")}`)}seededRandom(A){return this.config.seed?bB(XB(this.config.seed,A)):Math.random()}getConfig(){return{...this.config}}mapVariant(A,B,g){const I=this.mapButtons(A,g,A.difficulty),E=this.buildMetadata(I,g),i=new Map,C=new Map,a=new Map;for(const e of I)i.set(e.beatIndex,String(e.key)),C.set(e.beatIndex,e.source),a.set(e.beatIndex,e.patternId);return{variant:A,rhythmMetadata:B,buttonMetadata:E,keyAssignments:i,mappingSources:C,mappingPatternIds:a}}map(A,B,g){const I=A.difficultyVariants[B];return this.mapVariant(I,A.metadata,g)}mapAll(A,B){return{easy:this.map(A,"easy",B),medium:this.map(A,"medium",B),hard:this.map(A,"hard",B)}}mapButtons(A,B,g){const I=A.beats;if(this.config.controllerMode==="tap")return I.map((l,F)=>({beatIndex:F,timestamp:l.timestamp,key:"tap",source:"pattern",patternId:void 0,probability:void 0}));const E=[],i=this.getMaxPatternDifficulty(g);let C=0;const{pitchKeys:a,probabilities:e}=DF(I,B,this.config.controllerMode,g),o=this.classifyPitchVsPattern(a,e,this.config.pitchInfluenceWeight),t=a.map((l,F)=>l!==null&&o[F]?l:null),s=this.config.controllerMode==="ddr"?Zi.patterns:Wi.patterns,G=dF(t),n=new Set,h=G.map((l,F)=>{const m=FF(l,s,i,n,()=>this.seededRandom(`run:${F}:pick:${C++}`));for(const y of m)y.pattern.id!=="__interpolated__"&&n.add(y.pattern.id);return m}),{keys:c,patternIds:d}=MF(t,G,h);for(let l=0;l<I.length;l++){const F=t[l]!==null;E.push({beatIndex:l,timestamp:I[l].timestamp,key:c[l],source:F?"pitch":"pattern",patternId:F?void 0:d[l],probability:e[l]})}return this.config.consecutiveSameKeyLimit>0&&this.applyConsecutiveLimit(E,s,i),E}classifyPitchVsPattern(A,B,g){const I=new Array(A.length).fill(!1),E=A.map((a,e)=>({index:e,probability:B[e],hasPitch:a!==null})).filter(a=>a.hasPitch);E.sort((a,e)=>a.probability-e.probability);const i=Math.floor(E.length*(1-g)),C=new Set(E.slice(0,i).map(a=>a.index));for(let a=0;a<A.length;a++)A[a]===null||C.has(a)?I[a]=!1:I[a]=!0;return I}getMaxPatternDifficulty(A){switch(A){case"easy":return 3;case"medium":return 6;case"hard":return 10;case"natural":return 10;case"custom":return 6}}applyConsecutiveLimit(A,B,g){const I=A.map(C=>C.key),E=this.config.consecutiveSameKeyLimit,{positions:i}=wF(I,E);for(let C=0;C<i.length;C++){const a=i[C],e=yF(A[a].key,B,g,()=>this.seededRandom(`var:${a}:${C}`));e!==A[a].key&&(A[a].key=e,A[a].source="pattern",A[a].patternId="consecutive_limit_fix")}}buildMetadata(A,B){const g=new Set,I=new Map;let E=0,i=0;const C=new Set;for(const n of A){const h=String(n.key);g.add(h),I.set(h,(I.get(h)??0)+1),n.source==="pitch"?E++:i++,n.patternId&&C.add(n.patternId)}let a,e,o;if(B&&B.length>0){a={up:0,down:0,stable:0,none:0},e={unison:0,small:0,medium:0,large:0,very_large:0},o={low:0,mid:0,high:0};for(const n of B)a[n.direction]++,n.intervalCategory&&e[n.intervalCategory]++,n.band&&o[n.band]++}const t=[];let s,G=0;for(let n=0;n<A.length;n++){const h=A[n].patternId;h&&h===s||(s&&t.push({patternId:s,startIndex:G,length:n-G}),s=h,G=n)}return s&&t.push({patternId:s,startIndex:G,length:A.length-G}),{controllerMode:this.config.controllerMode,keysUsed:Array.from(g),pitchInfluencedBeats:E,patternInfluencedBeats:i,patternsUsed:Array.from(C),buttonDistribution:I,directionStats:a,intervalStats:e,bandStats:o,patternPlacements:t}}static getDDRTransitions(){return wt}static getGuitarHeroTransitions(){return yt}getAvailableButtons(){return this.config.controllerMode==="ddr"?["up","down","left","right"]:[1,2,3,4,5]}isValidButton(A){return this.config.controllerMode==="ddr"?["up","down","left","right"].includes(A):[1,2,3,4,5].includes(A)}}class oQ{convertToChartedBeatMap(A,B,g,I,E,i){const C=[],a=[];for(let o=0;o<A.beats.length;o++){const t=A.beats[o],s=this.convertBeat(t,B,g.get(o),o,E?.get(o),i?.get(o));C.push(s),s.isDetected&&a.push(o)}const e=this.buildChartMetadata(A,I,C,g);return{audioId:B.audioId,duration:B.duration,beats:C,detectedBeatIndices:a,downbeatConfig:B.downbeatConfig,quarterNoteInterval:B.quarterNoteInterval,bpm:B.quarterNoteBpm,chartMetadata:e}}convertWithOptions(A,B){const g={version:"1.0.0",algorithm:"procedural-generation",minBpm:60,maxBpm:200,sensitivity:1,filter:.5,noiseFloorThreshold:.01,hopSizeMs:10,fftSize:2048,dpAlpha:.5,melBands:40,highPassCutoff:80,gaussianSmoothMs:20,tempoCenter:.5,tempoWidth:.5,useOctaveResolution:!1,useTripleMeter:!1,generatedAt:new Date().toISOString()},I={audioId:B.audioId,duration:B.duration,beats:[],detectedBeatIndices:[],quarterNoteInterval:B.quarterNoteInterval,quarterNoteBpm:60/B.quarterNoteInterval,downbeatConfig:B.downbeatConfig,originalMetadata:g};return this.convertToChartedBeatMap(A,I,B.keyAssignments,B.metadata)}convertBeat(A,B,g,I,E,i){const C=A.beatIndex,a=this.getParentBeat(B,C),e=this.calculateBeatInMeasure(a,A.gridPosition,A.gridType),o=this.isBeatDetected(A),t=this.mapGridToSubdivision(A.gridType),s=this.calculateConfidence(A,o);return{timestamp:A.timestamp,beatInMeasure:e,isDownbeat:(a?.isDownbeat??!1)&&A.gridPosition===0,measureNumber:a?.measureNumber??0,intensity:A.intensity,confidence:s,requiredKey:g,quarterNoteIndex:C,subdivisionPosition:A.gridPosition,isDetected:o,subdivisionType:t,sourceBand:A.sourceBand,quantizationError:A.quantizationError,mappingSource:E,patternId:i}}getParentBeat(A,B){return B<0||B>=A.beats.length?null:A.beats[B]}calculateBeatInMeasure(A,B,g){const I=A?.beatInMeasure??0;return ia(I,B,g)}isBeatDetected(A){return A.quantizationError===void 0?!0:A.quantizationError<10}mapGridToSubdivision(A){return Ea(A)}calculateConfidence(A,B){return B?Math.min(1,.8+A.intensity*.2):.8}buildChartMetadata(A,B,g,I){const E=B.pitchInfluencedBeats??0,i=this.getUniqueKeys(g);return this.getSubdivisionTypesUsed(g),{difficulty:A.difficulty,keysUsed:i,pitchInfluencedBeats:E,patternsUsed:B.patternsUsed??[],rhythmMetadata:B.rhythmMetadata??this.createDefaultRhythmMetadata(A),pitchMetadata:B.pitchMetadata??null,generatedAt:B.generatedAt??new Date().toISOString(),seed:B.seed}}getUniqueKeys(A){const B=new Set;for(const g of A)g.requiredKey!==void 0&&B.add(g.requiredKey);return Array.from(B).sort()}getSubdivisionTypesUsed(A){const B=new Set;for(const g of A)B.add(g.subdivisionType);return Array.from(B)}createDefaultRhythmMetadata(A){return{difficulty:A.difficulty,bandsAnalyzed:["low","mid","high"],transientsDetected:A.beats.length,averageDensity:A.beats.length/180,naturalDifficulty:A.difficulty}}static fromMappedResult(A,B,g,I,E,i,C){const a=E??new Map;if(a.size===0&&g.keysUsed.length>0)for(let G=0;G<A.beats.length;G++)a.set(G,g.keysUsed[G%g.keysUsed.length]);const e=new oQ,o={difficulty:I.difficulty,bandsAnalyzed:I.bandsAnalyzed,transientsDetected:I.transientsDetected,averageDensity:I.averageDensity,naturalDifficulty:I.naturalDifficulty},t=g.directionStats?{melodyRange:null,directionStats:g.directionStats,intervalStats:g.intervalStats??null}:null,s={difficulty:A.difficulty,keysUsed:g.keysUsed,pitchInfluencedBeats:g.pitchInfluencedBeats,patternsUsed:g.patternsUsed,rhythmMetadata:o,pitchMetadata:t,generatedAt:new Date().toISOString()};return e.convertToChartedBeatMap(A,B,a,s,i,C)}}const Og={difficulty:"medium",controllerMode:"ddr",rhythm:{},buttons:{},enableCache:!0,cacheMaxAge:1800*1e3};class tQ{constructor(A={}){this.cache=new Map,this.cacheHits=0,this.cacheMisses=0,this.options={...Og,...A,rhythm:{...Og.rhythm,...A.rhythm},buttons:{...Og.buttons,...A.buttons}},this.buttonConfig=sE({...this.options.buttons,difficulty:this.options.difficulty,controllerMode:this.options.controllerMode,seed:this.options.seed})}getOptions(){return{...this.options}}generateCacheKey(A,B,g){return`${A}:${B}:${g}`}createConfigFingerprint(A){const B=this.options.rhythm||{};return A==="rhythm"?JSON.stringify({measureStartOffset:B.measureStartOffset,minimumTransientIntensity:B.minimumTransientIntensity,seed:B.seed}):A==="pitch"?JSON.stringify({pitchAlgorithm:this.options.pitchAlgorithm,crepeModelUrl:this.options.crepeModelUrl,voicingThreshold:this.options.voicingThreshold}):"default"}getFromCache(A){if(!this.options.enableCache)return null;const B=this.cache.get(A);if(!B)return this.cacheMisses++,null;const g=Date.now()-B.timestamp,I=this.options.cacheMaxAge??Og.cacheMaxAge;return g>I?(this.cache.delete(A),this.cacheMisses++,null):(this.cacheHits++,B.result)}setCache(A,B){this.options.enableCache&&this.cache.set(A,{result:B,timestamp:Date.now(),key:A})}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0}pruneExpiredCache(){const A=Date.now(),B=this.options.cacheMaxAge??Og.cacheMaxAge;for(const[g,I]of this.cache.entries())A-I.timestamp>B&&this.cache.delete(g)}getCacheStats(){const A=[];for(const[B]of this.cache.entries()){const g=B.split(":")[1];A.includes(g)||A.push(g)}return{entryCount:this.cache.size,cachedPhases:A,hits:this.cacheHits,misses:this.cacheMisses}}isCached(A,B){const g=this.createConfigFingerprint(B),I=this.generateCacheKey(A,B,g);return this.cache.has(I)}getCacheHitRatio(){const A=this.cacheHits+this.cacheMisses;return A===0?0:this.cacheHits/A}async generate(A,B,g,I){const E=(s,G,n)=>{g?.({stage:s,progress:G,message:n})};I?.throwIfAborted();const i=B.audioId;E("rhythm",0,"Starting rhythm generation...");let C=null;if(this.options.cachedRhythm)C=this.options.cachedRhythm,E("rhythm",1,"Using pre-generated rhythm from store");else{const s=this.generateCacheKey(i,"rhythm",this.createConfigFingerprint("rhythm"));C=this.getFromCache(s),C?E("rhythm",1,"Rhythm loaded from cache"):(C=await this.generateRhythm(A,B,(G,n,h)=>{E("rhythm",n,`[${G}] ${h}`)},I),this.setCache(s,C),E("rhythm",1,"Rhythm generation complete"))}I?.throwIfAborted();let a=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const s=this.generateCacheKey(i,"pitch",this.createConfigFingerprint("pitch"));a=this.getFromCache(s),a?E("pitch",1,"Pitch analysis loaded from cache"):(E("pitch",0,"Starting pitch analysis..."),a=await this.analyzePitch(A,C,(G,n)=>{E("pitch",G,n)}),this.setCache(s,a),E("pitch",1,"Pitch analysis complete"))}else E("pitch",1,"Pitch analysis skipped");I?.throwIfAborted(),E("buttons",0,"Starting button mapping...");const e=this.mapButtons(C,a);E("buttons",1,"Button mapping complete"),I?.throwIfAborted(),E("conversion",0,"Converting to playable chart...");const o=this.convertToChart(e,B);E("conversion",1,"Chart conversion complete"),I?.throwIfAborted(),E("finalizing",0,"Finalizing level...");const t=this.buildLevel(o,e,C,a);return E("finalizing",1,"Level generation complete"),t}async generateAllDifficulties(A,B,g,I){const E=["easy","medium","hard","natural"],i={easy:null,medium:null,hard:null,natural:null};I?.throwIfAborted();const C=B.audioId;let a=null;if(this.options.cachedRhythm)a=this.options.cachedRhythm;else{const o=this.generateCacheKey(C,"rhythm",this.createConfigFingerprint("rhythm"));a=this.getFromCache(o),a||(a=await this.generateRhythm(A,B,void 0,I),this.setCache(o,a))}I?.throwIfAborted();let e=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const o=this.generateCacheKey(C,"pitch",this.createConfigFingerprint("pitch"));e=this.getFromCache(o),e||(e=await this.analyzePitch(A,a),this.setCache(o,e))}I?.throwIfAborted();for(let o=0;o<E.length;o++){const t=E[o];g?.({stage:"buttons",progress:o/E.length,message:`Generating ${t} chart...`}),I?.throwIfAborted();const s=new tQ({...this.options,difficulty:t,buttons:{...this.options.buttons,difficulty:t}}),G=s.mapButtons(a,e),n=s.convertToChart(G,B),h=s.buildLevel(n,G,a,e);i[t]=h}return{easy:i.easy,medium:i.medium,hard:i.hard,natural:i.natural}}async generateAtDensity(A,B,g,I,E){const i=(d,l,F)=>{I?.({stage:d,progress:l,message:F})};E?.throwIfAborted();const C=B.audioId;i("rhythm",0,"Starting rhythm generation...");let a=null;if(this.options.cachedRhythm)a=this.options.cachedRhythm,i("rhythm",1,"Using pre-generated rhythm from store");else{const d=this.generateCacheKey(C,"rhythm",this.createConfigFingerprint("rhythm"));a=this.getFromCache(d),a?i("rhythm",1,"Rhythm loaded from cache"):(a=await this.generateRhythm(A,B,(l,F,m)=>{i("rhythm",F,`[${l}] ${m}`)},E,!0),this.setCache(d,a),i("rhythm",1,"Rhythm generation complete"))}E?.throwIfAborted(),i("buttons",0,"Generating density-based variant...");const e=this.collectGridDecisions(a.analysis.quantizationResult),t=new EQ({seed:this.options.seed}).generateAtDensity(a.composite,g,B,a.analysis.phraseAnalysis,e);i("buttons",.3,"Density variant generated");let s=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const d=this.generateCacheKey(C,"pitch",this.createConfigFingerprint("pitch"));s=this.getFromCache(d),s?i("pitch",.5,"Pitch analysis loaded from cache"):(i("pitch",0,"Starting pitch analysis..."),s=await this.analyzePitch(A,a,(l,F)=>{i("pitch",l,F)}),this.setCache(d,s),i("pitch",1,"Pitch analysis complete"))}else i("pitch",1,"Pitch analysis skipped");E?.throwIfAborted(),i("buttons",.6,"Mapping buttons...");const n=new eQ(this.buttonConfig).mapVariant(t,a.metadata,s?.pitchByBeat);i("buttons",1,"Button mapping complete"),E?.throwIfAborted(),i("conversion",0,"Converting to playable chart...");const h=this.convertToChart(n,B);i("conversion",1,"Chart conversion complete"),E?.throwIfAborted(),i("finalizing",0,"Finalizing level...");const c=this.buildLevel(h,n,a,s,"custom");return i("finalizing",1,"Level generation complete"),c}async generateAtDensities(A,B,g,I,E){const i=new Map;E?.throwIfAborted();const C=B.audioId;I?.({stage:"rhythm",progress:0,message:"Starting rhythm generation..."});let a=null;if(this.options.cachedRhythm)a=this.options.cachedRhythm,I?.({stage:"rhythm",progress:1,message:"Using pre-generated rhythm from store"});else{const s=this.generateCacheKey(C,"rhythm",this.createConfigFingerprint("rhythm"));a=this.getFromCache(s),a?I?.({stage:"rhythm",progress:1,message:"Rhythm loaded from cache"}):(a=await this.generateRhythm(A,B,void 0,E,!0),this.setCache(s,a),I?.({stage:"rhythm",progress:1,message:"Rhythm generation complete"}))}E?.throwIfAborted();let e=null;if(this.buttonConfig.pitchInfluenceWeight>0&&this.buttonConfig.controllerMode!=="tap"){const s=this.generateCacheKey(C,"pitch",this.createConfigFingerprint("pitch"));e=this.getFromCache(s),e?I?.({stage:"pitch",progress:1,message:"Pitch analysis loaded from cache"}):(I?.({stage:"pitch",progress:0,message:"Starting pitch analysis..."}),e=await this.analyzePitch(A,a),this.setCache(s,e),I?.({stage:"pitch",progress:1,message:"Pitch analysis complete"}))}E?.throwIfAborted();const o=this.collectGridDecisions(a.analysis.quantizationResult),t=new EQ({seed:this.options.seed});for(let s=0;s<g.length;s++){const{label:G,config:n}=g[s];I?.({stage:"buttons",progress:s/g.length,message:`Generating ${G} density variant...`}),E?.throwIfAborted();const h=t.generateAtDensity(a.composite,n,B,a.analysis.phraseAnalysis,o),d=new eQ(this.buttonConfig).mapVariant(h,a.metadata,e?.pitchByBeat),l=this.convertToChart(d,B),F=this.buildLevel(l,d,a,e,"custom");i.set(G,F)}return I?.({stage:"finalizing",progress:1,message:"All density variants generated"}),i}collectGridDecisions(A){const B=new Map,g=[...A.streams.low.gridDecisions,...A.streams.mid.gridDecisions,...A.streams.high.gridDecisions];for(const I of g){const E=B.get(I.beatIndex);(!E||I.confidence>E.confidence)&&B.set(I.beatIndex,I)}return B}async generateRhythm(A,B,g,I,E){return await new HB({...this.options.rhythm,skipDifficultyVariants:E}).generate(A,B,I,g?(a,e,o)=>{g(a,e,o)}:void 0)}async analyzePitch(A,B,g){g?.(.1,"Linking pitch to beats...");const I={};this.options.pitchAlgorithm!==void 0&&(I.pitchAlgorithm=this.options.pitchAlgorithm),this.options.crepeModelUrl!==void 0&&(I.crepeModelUrl=this.options.crepeModelUrl),this.options.resolveUrl!==void 0&&(I.resolveUrl=this.options.resolveUrl),this.options.voicingThreshold!==void 0&&(I.pitchDetector={...I.pitchDetector,voicingThreshold:this.options.voicingThreshold});const E=new Dt(I),i=await E.linkWithComposite(B.composite,A);g?.(.4,"Analyzing melody contour...");const a=new Ld().analyze(i);g?.(.8,"Deriving variant pitches...");let e;if(!B.difficultyVariants)e=a.pitchByBeat;else{const o=this.options.difficulty==="custom"?"medium":this.options.difficulty;e=E.deriveVariantPitches(B.difficultyVariants[o],a.pitchByBeat)}return{...a,pitchByBeat:e}}mapButtons(A,B){const g=new eQ(this.buttonConfig),I=this.options.difficulty==="custom"?"medium":this.options.difficulty;return g.map(A,I,B?.pitchByBeat)}convertToChart(A,B){return oQ.fromMappedResult(A.variant,B,A.buttonMetadata,A.rhythmMetadata,A.keyAssignments,A.mappingSources,A.mappingPatternIds)}buildLevel(A,B,g,I,E){const i={difficulty:E??this.options.difficulty,controllerMode:this.options.controllerMode,rhythmMetadata:B.rhythmMetadata,buttonMetadata:B.buttonMetadata,pitchMetadata:I?{melodyRange:I.melodyContour.range.minNote!=="N/A"?{min:I.melodyContour.range.minNote,max:I.melodyContour.range.maxNote}:null,directionStats:I.directionStats,intervalStats:I.intervalStats}:null,chartMetadata:{totalBeats:A.beats.length,detectedBeats:A.detectedBeatIndices.length,generatedBeats:A.beats.length-A.detectedBeatIndices.length},generationConfig:this.options};return{chart:A,variant:B.variant,rhythm:g,pitchAnalysis:I,metadata:i}}}class RF{static toExportData(A,B={}){const{chart:g,metadata:I,pitchAnalysis:E}=A,i=this.buildDetectedBeats(g),C=this.buildMergedBeats(g),a=this.buildInterpolatedMetadata(g),e=this.buildSubdivisionData(g),o=this.buildChartExportData(g,I),t=this.buildGenerationMetadata(I,E);return{version:1,format:"full-beatmap",audioId:g.audioId,audioTitle:B.includeAudioTitle?B.audioTitle:void 0,exportedAt:Date.now(),duration:g.duration,quarterNoteBpm:g.bpm,quarterNoteConfidence:g.chartMetadata.rhythmMetadata.averageDensity,detectedBeats:i,mergedBeats:C,interpolatedMetadata:a,subdivision:e,chart:o,trackReference:B.trackReference,generationSource:"procedural",generationMetadata:t}}static buildDetectedBeats(A){const B=[],g=new Set(A.detectedBeatIndices);for(let I=0;I<A.beats.length;I++){const E=A.beats[I];g.has(I)&&B.push({timestamp:E.timestamp,beatInMeasure:E.beatInMeasure,isDownbeat:E.isDownbeat,measureNumber:E.measureNumber,intensity:E.intensity,confidence:E.confidence,requiredKey:E.requiredKey})}return B}static buildMergedBeats(A){const B=new Set(A.detectedBeatIndices);return A.beats.map((g,I)=>({timestamp:g.timestamp,beatInMeasure:g.beatInMeasure,isDownbeat:g.isDownbeat,measureNumber:g.measureNumber,intensity:g.intensity,confidence:g.confidence,requiredKey:g.requiredKey,source:B.has(I)?"detected":"interpolated",distanceToAnchor:g.quantizationError}))}static buildInterpolatedMetadata(A){const B=A.detectedBeatIndices.length,g=A.beats.length;return{quarterNoteInterval:A.quarterNoteInterval,quarterNoteBpm:A.bpm,quarterNoteConfidence:.9,detectedBeatCount:B,mergedBeatCount:g}}static buildSubdivisionData(A){const B=A.beats.map((C,a)=>this.chartedBeatToExportBeat(C,a,A.detectedBeatIndices)),g=new Set,I=[];B.forEach((C,a)=>{g.add(C.subdivisionType),I.push([a,C.subdivisionType])});const E={beatSubdivisions:I,defaultSubdivision:"sixteenth"},i={originalBeatCount:A.beats.length-A.detectedBeatIndices.length,subdividedBeatCount:A.beats.length,averageDensityMultiplier:1,explicitBeatCount:A.detectedBeatIndices.length};return{config:E,beats:B,metadata:i}}static chartedBeatToExportBeat(A,B,g){const I=g.includes(B);return{timestamp:A.timestamp,beatInMeasure:A.beatInMeasure,isDownbeat:A.isDownbeat,measureNumber:A.measureNumber,intensity:A.intensity,confidence:A.confidence,requiredKey:A.requiredKey,isDetected:I,originalBeatIndex:I?B:void 0,subdivisionType:A.subdivisionType,quarterNoteIndex:A.quarterNoteIndex,subdivisionPosition:A.subdivisionPosition,sourceBand:A.sourceBand,quantizationError:A.quantizationError}}static buildChartExportData(A,B){const g=A.beats.map(E=>E.requiredKey).filter(E=>E!==void 0),I=[...new Set(g)];return I.length===0?null:{style:B.controllerMode==="ddr"?"ddr":B.controllerMode==="guitar_hero"?"guitar":"tap",keyCount:I.length,usedKeys:I}}static buildGenerationMetadata(A,B){const g=A.rhythmMetadata;return{difficulty:A.difficulty,pitchInfluenceWeight:A.generationConfig.buttons?.pitchInfluenceWeight??1,patternsUsed:A.buttonMetadata.patternsUsed,controllerMode:A.controllerMode,seed:A.generationConfig.seed,generatedAt:new Date().toISOString(),directionStats:B?.directionStats??void 0,intervalStats:B?.intervalStats??void 0,rhythmMetadata:{difficulty:g.difficulty,bandsAnalyzed:g.bandsAnalyzed,transientsDetected:g.transientsDetected,averageDensity:g.averageDensity}}}static fromExportData(A){const B=this.validate(A);if(!B.success||!B.data)throw new Error(`Invalid export data: ${B.error??"Unknown error"}`);const g=B.data,I=this.reconstructChart(g),E=this.reconstructVariant(g,I),i=this.reconstructRhythm(g,I),C=this.reconstructPitchAnalysis(g),a=this.reconstructMetadata(g,I);return{chart:I,variant:E,rhythm:i,pitchAnalysis:C,metadata:a}}static reconstructChart(A){if(!A.subdivision)return this.reconstructChartFromMergedBeats(A);const B=A.subdivision.beats.map((i,C)=>({timestamp:i.timestamp,beatInMeasure:i.beatInMeasure,isDownbeat:i.isDownbeat,measureNumber:i.measureNumber,intensity:i.intensity,confidence:i.confidence,requiredKey:i.requiredKey,quarterNoteIndex:i.quarterNoteIndex??0,subdivisionPosition:i.subdivisionPosition??0,isDetected:i.isDetected,subdivisionType:i.subdivisionType,sourceBand:i.sourceBand??"mid",quantizationError:i.quantizationError})),g=A.subdivision.beats.map((i,C)=>i.isDetected?C:-1).filter(i=>i>=0),I=this.reconstructDownbeatConfig(B),E=this.reconstructChartMetadata(A);return{audioId:A.audioId,duration:A.duration,beats:B,detectedBeatIndices:g,downbeatConfig:I,quarterNoteInterval:A.interpolatedMetadata.quarterNoteInterval,bpm:A.quarterNoteBpm,chartMetadata:E}}static reconstructChartFromMergedBeats(A){const B=A.mergedBeats.map((i,C)=>({timestamp:i.timestamp,beatInMeasure:i.beatInMeasure,isDownbeat:i.isDownbeat,measureNumber:i.measureNumber,intensity:i.intensity,confidence:i.confidence,requiredKey:i.requiredKey,quarterNoteIndex:C,subdivisionPosition:0,isDetected:i.source==="detected",subdivisionType:"quarter",sourceBand:"mid",quantizationError:i.distanceToAnchor})),g=A.mergedBeats.map((i,C)=>i.source==="detected"?C:-1).filter(i=>i>=0),I=this.reconstructDownbeatConfig(B),E=this.reconstructChartMetadata(A);return{audioId:A.audioId,duration:A.duration,beats:B,detectedBeatIndices:g,downbeatConfig:I,quarterNoteInterval:A.interpolatedMetadata.quarterNoteInterval,bpm:A.quarterNoteBpm,chartMetadata:E}}static reconstructDownbeatConfig(A){const B=A.filter(E=>E.isDownbeat);if(B.length===0)return{segments:[{startBeat:0,downbeatBeatIndex:0,timeSignature:{beatsPerMeasure:4}}]};const g={beatsPerMeasure:4};return{segments:[{startBeat:0,downbeatBeatIndex:B[0]?.measureNumber??0,timeSignature:g}]}}static reconstructChartMetadata(A){const B=A.generationMetadata;return{difficulty:this.parseDifficultyLevel(B?.difficulty),keysUsed:A.chart?.usedKeys??[],pitchInfluencedBeats:B?.pitchInfluenceWeight&&B.pitchInfluenceWeight>0?A.subdivision?.beats.filter(g=>g.requiredKey).length??0:0,patternsUsed:B?.patternsUsed??[],rhythmMetadata:{difficulty:B?.rhythmMetadata?.difficulty??"medium",bandsAnalyzed:B?.rhythmMetadata?.bandsAnalyzed??["low","mid","high"],transientsDetected:B?.rhythmMetadata?.transientsDetected??A.detectedBeats.length,averageDensity:B?.rhythmMetadata?.averageDensity??.5,naturalDifficulty:this.parseDifficultyLevel(B?.difficulty)},pitchMetadata:B?.directionStats||B?.intervalStats?{melodyRange:null,directionStats:B.directionStats??null,intervalStats:B.intervalStats??null}:null,generatedAt:B?.generatedAt??new Date().toISOString(),seed:B?.seed}}static parseDifficultyLevel(A){return A==="easy"||A==="medium"||A==="hard"||A==="natural"||A==="custom"?A:"medium"}static parseDifficultyPreset(A){return A==="easy"||A==="medium"||A==="hard"||A==="natural"||A==="custom"?A:"medium"}static reconstructVariant(A,B){const g=A.generationMetadata,I=this.parseDifficultyLevel(g?.difficulty),E=B.beats.map(i=>({timestamp:i.timestamp,beatIndex:i.quarterNoteIndex,gridPosition:i.subdivisionPosition,gridType:this.subdivisionTypeToGridType(i.subdivisionType),intensity:i.intensity,band:i.sourceBand,quantizationError:i.quantizationError,sourceBand:i.sourceBand}));return{difficulty:I,beats:E,isUnedited:!0,editType:"none",editAmount:0,patternsInserted:g?.patternsUsed}}static subdivisionTypeToGridType(A){switch(A){case"sixteenth":case"eighth":case"quarter":return"straight_16th";case"triplet8":case"triplet4":return"triplet_8th";default:return"straight_16th"}}static reconstructRhythm(A,B){const g=A.generationMetadata,I=this.parseDifficultyLevel(g?.difficulty),E=t=>({audioId:A.audioId,duration:A.duration,beats:B.beats.filter(s=>s.sourceBand===t).map(s=>({timestamp:s.timestamp,beatIndex:s.quarterNoteIndex,gridPosition:s.subdivisionPosition,gridType:this.subdivisionTypeToGridType(s.subdivisionType),intensity:s.intensity,band:t,quantizationError:s.quantizationError})),gridDecisions:[],quarterNoteInterval:A.interpolatedMetadata.quarterNoteInterval}),i={low:E("low"),mid:E("mid"),high:E("high")},C=this.reconstructVariant(A,B),a=B.beats.map(t=>({timestamp:t.timestamp,beatIndex:t.quarterNoteIndex,gridPosition:t.subdivisionPosition,gridType:this.subdivisionTypeToGridType(t.subdivisionType),intensity:t.intensity,band:t.sourceBand,quantizationError:t.quantizationError,sourceBand:t.sourceBand})),e={low:0,mid:0,high:0};for(const t of a)e[t.sourceBand]++;const o={beats:a,sections:[],naturalDifficulty:I,quarterNoteInterval:A.interpolatedMetadata.quarterNoteInterval,metadata:{totalBeats:a.length,sectionCount:0,beatsPerBand:e,sectionsPerBand:{low:0,mid:0,high:0}}};return{difficultyVariants:{easy:{...C,difficulty:"easy"},medium:{...C,difficulty:"medium"},hard:{...C,difficulty:"hard"},natural:{...C,difficulty:"natural"}},bandStreams:i,composite:o,analysis:{transientAnalysis:{transients:A.detectedBeats.map(t=>({timestamp:t.timestamp,intensity:t.intensity,band:"mid",detectionMethod:"energy"})),bandTransients:new Map([["low",[]],["mid",A.detectedBeats.map(t=>({timestamp:t.timestamp,intensity:t.intensity,band:"mid",detectionMethod:"energy"}))],["high",[]]]),metadata:{totalTransients:A.detectedBeats.length,transientsPerBand:new Map([["low",0],["mid",A.detectedBeats.length],["high",0]]),duration:A.duration,averageIntensity:.5,detectionMethodsUsed:["energy"]}},quantizationResult:{streams:i,metadata:{densityValidation:{isValid:!0,bands:{low:{band:"low",isValid:!0,minIntervalDetected:1/0,requiredMinInterval:.1,retryCount:0,sensitivityReduction:0,finalIntensityThreshold:0,transientsRemaining:0},mid:{band:"mid",isValid:!0,minIntervalDetected:.1,requiredMinInterval:.1,retryCount:0,sensitivityReduction:0,finalIntensityThreshold:0,transientsRemaining:A.detectedBeats.length},high:{band:"high",isValid:!0,minIntervalDetected:1/0,requiredMinInterval:.1,retryCount:0,sensitivityReduction:0,finalIntensityThreshold:0,transientsRemaining:0}},maxRetryCount:0,maxSensitivityReduction:0},transientsFilteredByIntensity:0,transientsFilteredByBand:{low:0,mid:0,high:0}}},phraseAnalysis:{phrases:[],phrasesByBand:new Map([["low",[]],["mid",[]],["high",[]]]),mostSignificantPhrases:[],phrasesBySize:new Map,patternLibrary:[],bandAnalysis:{low:{band:"low",phrases:[],phrasesBySize:new Map,phrasesWithVariation:[]},mid:{band:"mid",phrases:[],phrasesBySize:new Map,phrasesWithVariation:[]},high:{band:"high",phrases:[],phrasesBySize:new Map,phrasesWithVariation:[]}}},densityAnalysis:{sections:[],perBeatDensity:[],bandMetrics:{low:{band:"low",totalBeats:0,totalTransients:0,notesPerSecond:1,minNotesPerSecond:0,maxNotesPerSecond:2,variance:0,densityCategory:"moderate",naturalDifficulty:"medium",perBeatDensity:[]},mid:{band:"mid",totalBeats:A.mergedBeats.length,totalTransients:A.detectedBeats.length,notesPerSecond:1,minNotesPerSecond:0,maxNotesPerSecond:2,variance:0,densityCategory:"moderate",naturalDifficulty:I,perBeatDensity:[]},high:{band:"high",totalBeats:0,totalTransients:0,notesPerSecond:1,minNotesPerSecond:0,maxNotesPerSecond:2,variance:0,densityCategory:"moderate",naturalDifficulty:"medium",perBeatDensity:[]}},combinedMetrics:{totalTransients:A.detectedBeats.length,notesPerSecond:1,densityCategory:"moderate",naturalDifficulty:I}},scoringResult:{sectionScores:[],bandTotals:{low:0,mid:0,high:0},bandAverages:{low:0,mid:0,high:0},sectionWinners:[],config:{beatsPerSection:8,ioiVarianceWeight:.25,syncopationWeight:.25,phraseSignificanceWeight:.25,densityWeight:.25,offbeatGridPositions:{straight_16th:[1,3],triplet_8th:[1,2],straight_8th:[1]}}}},metadata:this.buildFullRhythmMetadata(A,I)}}static buildFullRhythmMetadata(A,B){const g=A.generationMetadata;return{difficulty:this.parseDifficultyPreset(g?.difficulty),bandsAnalyzed:["low","mid","high"],transientsDetected:A.detectedBeats.length,transientsFilteredByIntensity:0,densityValidationRetries:0,phrasesDetected:0,averageDensity:g?.rhythmMetadata?.averageDensity??.5,naturalDifficulty:B,generationConfig:{difficulty:this.parseDifficultyPreset(g?.difficulty),outputMode:"composite",measureStartOffset:0,minimumTransientIntensity:.1,transientConfig:void 0,rhythmicBalanceConfig:{strongBeatEmphasis:"natural",downbeatProximityRange:2,fillEmptyMeasures:!0,addedBeatIntensity:.45,marginSeconds:.5},seed:g?.seed,verbose:!1,enableCache:!0,cacheMaxAge:1800*1e3,skipDifficultyVariants:!1},duration:A.duration,totalBeats:A.mergedBeats.length}}static buildMinimalMelodyContour(){return{segments:[],direction:"stable",range:{minNote:"N/A",maxNote:"N/A",semitones:0},shortTermDirection:"stable",mediumTermDirection:"stable",longTermDirection:"stable"}}static reconstructPitchAnalysis(A){const B=A.generationMetadata;return!B||!B.directionStats&&!B.intervalStats?null:{pitchByBeat:[],melodyContour:this.buildMinimalMelodyContour(),directionStats:B.directionStats??{up:0,down:0,stable:0,none:0},intervalStats:B.intervalStats??{unison:0,small:0,medium:0,large:0,very_large:0},metadata:{totalBeats:0,voicedBeats:0,directionCalculatedBeats:0}}}static reconstructMetadata(A,B){const g=A.generationMetadata,I=this.parseDifficultyPreset(g?.difficulty),E=g?.controllerMode??"ddr";return{difficulty:I,controllerMode:E,rhythmMetadata:this.buildFullRhythmMetadata(A,this.parseDifficultyLevel(g?.difficulty)),buttonMetadata:{controllerMode:E,keysUsed:A.chart?.usedKeys??[],pitchInfluencedBeats:g?.pitchInfluenceWeight&&g.pitchInfluenceWeight>0?B.beats.filter(i=>i.requiredKey).length:0,patternInfluencedBeats:B.beats.filter(i=>i.requiredKey).length-(g?.pitchInfluenceWeight&&g.pitchInfluenceWeight>0?B.beats.filter(i=>i.requiredKey).length:0),patternsUsed:g?.patternsUsed??[],buttonDistribution:new Map},pitchMetadata:g?.directionStats||g?.intervalStats?{melodyRange:null,directionStats:g.directionStats??null,intervalStats:g.intervalStats??null}:null,chartMetadata:{totalBeats:B.beats.length,detectedBeats:B.detectedBeatIndices.length,generatedBeats:B.beats.length-B.detectedBeatIndices.length},generationConfig:{difficulty:I,controllerMode:E,rhythm:{},buttons:{pitchInfluenceWeight:g?.pitchInfluenceWeight??1},seed:g?.seed}}}static toJSON(A,B={}){const g=this.toExportData(A,B);return JSON.stringify(g,null,2)}static fromJSON(A){let B;try{B=JSON.parse(A)}catch(I){throw new Error(`Invalid JSON: ${I instanceof Error?I.message:"Unknown error"}`)}const g=this.validate(B);if(!g.success||!g.data)throw new Error(`Invalid level data: ${g.error??"Unknown error"}`);return this.fromExportData(g.data)}static async saveToFile(A,B,g={}){const I=await Promise.resolve().then(()=>GB),E=this.toJSON(A,g);await I.writeFile(B,E,"utf-8")}static async loadFromFile(A){const g=await(await Promise.resolve().then(()=>GB)).readFile(A,"utf-8");return this.fromJSON(g)}static validate(A){const B=[];if(typeof A!="object"||A===null)return{success:!1,error:"Data must be a non-null object"};const g=A;if(g.version!==1)return{success:!1,error:`Unsupported version: ${g.version}. Expected 1.`};if(g.format!=="full-beatmap")return{success:!1,error:`Invalid format: ${g.format}. Expected 'full-beatmap'.`};const I=["audioId","duration","quarterNoteBpm","detectedBeats","mergedBeats"];for(const E of I)if(!(E in g))return{success:!1,error:`Missing required field: ${E}`};if(!Array.isArray(g.detectedBeats))return{success:!1,error:"detectedBeats must be an array"};if(!Array.isArray(g.mergedBeats))return{success:!1,error:"mergedBeats must be an array"};if(!g.subdivision||typeof g.subdivision!="object")B.push("No subdivision data - level may not be playable");else{const E=g.subdivision;if(!Array.isArray(E.beats))return{success:!1,error:"subdivision.beats must be an array"}}if(g.chart===null)B.push("No chart data - level has no key assignments");else if(g.chart!==void 0&&typeof g.chart!="object")return{success:!1,error:"chart must be an object or null"};return typeof g.interpolatedMetadata!="object"||g.interpolatedMetadata===null?{success:!1,error:"interpolatedMetadata must be an object"}:Ca(A)?{success:!0,data:A,warnings:B.length>0?B:void 0}:{success:!1,error:"Data does not match FullBeatMapExportData format",warnings:B.length>0?B:void 0}}static toPack(A,B={}){const g={};for(const[I,E]of Object.entries(A))if(E){const i={includeAudioTitle:B.includeAudioTitle,audioTitle:B.audioTitle};g[I]=this.toExportData(E,i)}return{version:1,format:"level-pack",exportedAt:Date.now(),trackReference:B.trackReference,difficulties:g}}static fromPack(A){const B={};for(const[g,I]of Object.entries(A.difficulties))if(I)try{B[g]=this.fromExportData(I)}catch{}return B}static packToJSON(A,B={}){const g=this.toPack(A,B);return JSON.stringify(g,null,2)}static packFromJSON(A){let B;try{B=JSON.parse(A)}catch(g){throw new Error(`Invalid JSON: ${g instanceof Error?g.message:"Unknown error"}`)}if(!aa(B))throw new Error("Data does not match LevelPackExport format");return this.fromPack(B)}static isProcedural(A){return A.generationSource==="procedural"}static getSummary(A){const B=[`Audio: ${A.audioId}`,`Duration: ${A.duration.toFixed(1)}s`,`BPM: ${A.quarterNoteBpm.toFixed(1)}`,`Beats: ${A.mergedBeats.length} (${A.detectedBeats.length} detected)`];return A.chart&&(B.push(`Keys: ${A.chart.keyCount} (${A.chart.style})`),B.push(`Keys used: ${A.chart.usedKeys.join(", ")}`)),A.generationMetadata&&(B.push(`Difficulty: ${A.generationMetadata.difficulty}`),B.push(`Controller: ${A.generationMetadata.controllerMode}`),B.push(`Pitch influence: ${(A.generationMetadata.pitchInfluenceWeight*100).toFixed(0)}%`)),B.join(`
|